Blame view

arch/arm/mach-mxs/ocotp.c 2.25 KB
67f43086a   Shawn Guo   ARM: mxs: add oco...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   */
  
  #include <linux/delay.h>
  #include <linux/err.h>
  #include <linux/mutex.h>
ad377c630   Wolfram Sang   arm: mxs: include...
18
  #include <asm/processor.h>	/* for cpu_relax() */
67f43086a   Shawn Guo   ARM: mxs: add oco...
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  #include <mach/mxs.h>
  
  #define OCOTP_WORD_OFFSET		0x20
  #define OCOTP_WORD_COUNT		0x20
  
  #define BM_OCOTP_CTRL_BUSY		(1 << 8)
  #define BM_OCOTP_CTRL_ERROR		(1 << 9)
  #define BM_OCOTP_CTRL_RD_BANK_OPEN	(1 << 12)
  
  static DEFINE_MUTEX(ocotp_mutex);
  static u32 ocotp_words[OCOTP_WORD_COUNT];
  
  const u32 *mxs_get_ocotp(void)
  {
  	void __iomem *ocotp_base = MXS_IO_ADDRESS(MXS_OCOTP_BASE_ADDR);
  	int timeout = 0x400;
  	size_t i;
  	static int once = 0;
  
  	if (once)
  		return ocotp_words;
  
  	mutex_lock(&ocotp_mutex);
  
  	/*
  	 * clk_enable(hbus_clk) for ocotp can be skipped
  	 * as it must be on when system is running.
  	 */
  
  	/* try to clear ERROR bit */
  	__mxs_clrl(BM_OCOTP_CTRL_ERROR, ocotp_base);
  
  	/* check both BUSY and ERROR cleared */
  	while ((__raw_readl(ocotp_base) &
  		(BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) && --timeout)
  		cpu_relax();
  
  	if (unlikely(!timeout))
  		goto error_unlock;
  
  	/* open OCOTP banks for read */
  	__mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
  
  	/* approximately wait 32 hclk cycles */
  	udelay(1);
  
  	/* poll BUSY bit becoming cleared */
  	timeout = 0x400;
  	while ((__raw_readl(ocotp_base) & BM_OCOTP_CTRL_BUSY) && --timeout)
  		cpu_relax();
  
  	if (unlikely(!timeout))
  		goto error_unlock;
  
  	for (i = 0; i < OCOTP_WORD_COUNT; i++)
  		ocotp_words[i] = __raw_readl(ocotp_base + OCOTP_WORD_OFFSET +
  						i * 0x10);
  
  	/* close banks for power saving */
  	__mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
  
  	once = 1;
  
  	mutex_unlock(&ocotp_mutex);
  
  	return ocotp_words;
  
  error_unlock:
  	mutex_unlock(&ocotp_mutex);
  	pr_err("%s: timeout in reading OCOTP
  ", __func__);
  	return NULL;
  }