aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-mxs/Kconfig4
-rw-r--r--arch/arm/mach-mxs/Makefile2
-rw-r--r--arch/arm/mach-mxs/include/mach/common.h1
-rw-r--r--arch/arm/mach-mxs/ocotp.c90
4 files changed, 97 insertions, 0 deletions
diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index 8bfc8df54617..cd2fbdfc37e8 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -2,6 +2,9 @@ if ARCH_MXS
2 2
3source "arch/arm/mach-mxs/devices/Kconfig" 3source "arch/arm/mach-mxs/devices/Kconfig"
4 4
5config MXS_OCOTP
6 bool
7
5config SOC_IMX23 8config SOC_IMX23
6 bool 9 bool
7 select CPU_ARM926T 10 select CPU_ARM926T
@@ -26,6 +29,7 @@ config MACH_MX28EVK
26 select SOC_IMX28 29 select SOC_IMX28
27 select MXS_HAVE_AMBA_DUART 30 select MXS_HAVE_AMBA_DUART
28 select MXS_HAVE_PLATFORM_FEC 31 select MXS_HAVE_PLATFORM_FEC
32 select MXS_OCOTP
29 default y 33 default y
30 help 34 help
31 Include support for MX28EVK platform. This includes specific 35 Include support for MX28EVK platform. This includes specific
diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile
index 39d3f9c2a841..df501a8340f2 100644
--- a/arch/arm/mach-mxs/Makefile
+++ b/arch/arm/mach-mxs/Makefile
@@ -1,6 +1,8 @@
1# Common support 1# Common support
2obj-y := clock.o devices.o gpio.o icoll.o iomux.o system.o timer.o 2obj-y := clock.o devices.o gpio.o icoll.o iomux.o system.o timer.o
3 3
4obj-$(CONFIG_MXS_OCOTP) += ocotp.o
5
4obj-$(CONFIG_SOC_IMX23) += clock-mx23.o mm-mx23.o 6obj-$(CONFIG_SOC_IMX23) += clock-mx23.o mm-mx23.o
5obj-$(CONFIG_SOC_IMX28) += clock-mx28.o mm-mx28.o 7obj-$(CONFIG_SOC_IMX28) += clock-mx28.o mm-mx28.o
6 8
diff --git a/arch/arm/mach-mxs/include/mach/common.h b/arch/arm/mach-mxs/include/mach/common.h
index 59133eb3cc96..635bb5d9a20a 100644
--- a/arch/arm/mach-mxs/include/mach/common.h
+++ b/arch/arm/mach-mxs/include/mach/common.h
@@ -13,6 +13,7 @@
13 13
14struct clk; 14struct clk;
15 15
16extern const u32 *mxs_get_ocotp(void);
16extern int mxs_reset_block(void __iomem *); 17extern int mxs_reset_block(void __iomem *);
17extern void mxs_timer_init(struct clk *, int); 18extern void mxs_timer_init(struct clk *, int);
18 19
diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c
new file mode 100644
index 000000000000..65157a35dbba
--- /dev/null
+++ b/arch/arm/mach-mxs/ocotp.c
@@ -0,0 +1,90 @@
1/*
2 * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/delay.h>
16#include <linux/err.h>
17#include <linux/mutex.h>
18
19#include <mach/mxs.h>
20
21#define OCOTP_WORD_OFFSET 0x20
22#define OCOTP_WORD_COUNT 0x20
23
24#define BM_OCOTP_CTRL_BUSY (1 << 8)
25#define BM_OCOTP_CTRL_ERROR (1 << 9)
26#define BM_OCOTP_CTRL_RD_BANK_OPEN (1 << 12)
27
28static DEFINE_MUTEX(ocotp_mutex);
29static u32 ocotp_words[OCOTP_WORD_COUNT];
30
31const u32 *mxs_get_ocotp(void)
32{
33 void __iomem *ocotp_base = MXS_IO_ADDRESS(MXS_OCOTP_BASE_ADDR);
34 int timeout = 0x400;
35 size_t i;
36 static int once = 0;
37
38 if (once)
39 return ocotp_words;
40
41 mutex_lock(&ocotp_mutex);
42
43 /*
44 * clk_enable(hbus_clk) for ocotp can be skipped
45 * as it must be on when system is running.
46 */
47
48 /* try to clear ERROR bit */
49 __mxs_clrl(BM_OCOTP_CTRL_ERROR, ocotp_base);
50
51 /* check both BUSY and ERROR cleared */
52 while ((__raw_readl(ocotp_base) &
53 (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) && --timeout)
54 cpu_relax();
55
56 if (unlikely(!timeout))
57 goto error_unlock;
58
59 /* open OCOTP banks for read */
60 __mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
61
62 /* approximately wait 32 hclk cycles */
63 udelay(1);
64
65 /* poll BUSY bit becoming cleared */
66 timeout = 0x400;
67 while ((__raw_readl(ocotp_base) & BM_OCOTP_CTRL_BUSY) && --timeout)
68 cpu_relax();
69
70 if (unlikely(!timeout))
71 goto error_unlock;
72
73 for (i = 0; i < OCOTP_WORD_COUNT; i++)
74 ocotp_words[i] = __raw_readl(ocotp_base + OCOTP_WORD_OFFSET +
75 i * 0x10);
76
77 /* close banks for power saving */
78 __mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
79
80 once = 1;
81
82 mutex_unlock(&ocotp_mutex);
83
84 return ocotp_words;
85
86error_unlock:
87 mutex_unlock(&ocotp_mutex);
88 pr_err("%s: timeout in reading OCOTP\n", __func__);
89 return NULL;
90}