ARM: mxs: add ocotp read function
authorShawn Guo <shawn.guo@freescale.com>
Fri, 14 Jan 2011 15:11:23 +0000 (23:11 +0800)
committerSascha Hauer <s.hauer@pengutronix.de>
Fri, 21 Jan 2011 10:36:49 +0000 (11:36 +0100)
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
arch/arm/mach-mxs/Kconfig
arch/arm/mach-mxs/Makefile
arch/arm/mach-mxs/include/mach/common.h
arch/arm/mach-mxs/ocotp.c [new file with mode: 0644]

index 8bfc8df54617ccdd7091b995ddd1fd69ed1bf8f1..cd2fbdfc37e83ea3378ae13e24659bc3161f8b97 100644 (file)
@@ -2,6 +2,9 @@ if ARCH_MXS
 
 source "arch/arm/mach-mxs/devices/Kconfig"
 
+config MXS_OCOTP
+       bool
+
 config SOC_IMX23
        bool
        select CPU_ARM926T
@@ -26,6 +29,7 @@ config MACH_MX28EVK
        select SOC_IMX28
        select MXS_HAVE_AMBA_DUART
        select MXS_HAVE_PLATFORM_FEC
+       select MXS_OCOTP
        default y
        help
          Include support for MX28EVK platform. This includes specific
index 39d3f9c2a841f044c4e72f76a93fefe78ddf989d..df501a8340f23f70f9aabd193ba94277b09ec172 100644 (file)
@@ -1,6 +1,8 @@
 # Common support
 obj-y := clock.o devices.o gpio.o icoll.o iomux.o system.o timer.o
 
+obj-$(CONFIG_MXS_OCOTP) += ocotp.o
+
 obj-$(CONFIG_SOC_IMX23) += clock-mx23.o mm-mx23.o
 obj-$(CONFIG_SOC_IMX28) += clock-mx28.o mm-mx28.o
 
index 59133eb3cc9611ede9dfcb5cc7d1a314f0236172..635bb5d9a20ade988bfa61667b9513c985a47bb9 100644 (file)
@@ -13,6 +13,7 @@
 
 struct clk;
 
+extern const u32 *mxs_get_ocotp(void);
 extern int mxs_reset_block(void __iomem *);
 extern void mxs_timer_init(struct clk *, int);
 
diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c
new file mode 100644 (file)
index 0000000..65157a3
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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>
+
+#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\n", __func__);
+       return NULL;
+}