Thread (55 messages) flat view 55 messages, 4 authors, 2011-01-01
STALE5745d

[PATCH 08/10] ARM: mxs: add ocotp read function

From: Uwe Kleine-König <hidden>
Date: 2010-12-30 09:02:24

Hello Shawn,

On Thu, Dec 30, 2010 at 04:41:40PM +0800, Shawn Guo wrote:
On Wed, Dec 29, 2010 at 12:22:08PM +0100, Uwe Kleine-K?nig wrote:
quoted
On Tue, Dec 28, 2010 at 10:55:53PM +0800, Shawn Guo wrote:
quoted
diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c
new file mode 100644
index 0000000..24457d7
--- /dev/null
+++ b/arch/arm/mach-mxs/ocotp.c
@@ -0,0 +1,52 @@
+/*
+ * 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 <mach/mxs.h>
+
+#define BM_OCOTP_CTRL_RD_BANK_OPEN	(1 << 12)
+#define BM_OCOTP_CTRL_BUSY		(1 << 8)
+
+int mxs_read_ocotp(int offset, int count, u32 *values)
+{
+	void __iomem *ocotp_base = MXS_IO_ADDRESS(MXS_OCOTP_BASE_ADDR);
+	int i, timeout = 0x400;
+
+	/* open OCOTP banks for read */
+	__mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
The reference manual specifies:
	1. Program the HCLK to a frequency up to the maximum allowable HCLK
	   frequency. [...]
	2. Check that HW_OCOTP_CTRL_BUSY and HW_OCOTP_CTRL_ERROR are clear.
	3. Set HW_OCOTP_CTRL_RD_BANK_OPEN. [...]

1. isn't done (which is probably OK, or should it aquire a clk?)
ocotp needs clk_h, which must be on when system is running.
maybe add a comment?  "clk_enable(clk_h) can be skipped as it must be on
anyhow because ..." or similar?  It's always good to document implicit
assumptions.
quoted
For 2. there is no check for HW_OCOTP_CTRL_ERROR which is not OK i
guess?!
How does the new code look to you?

static DEFINE_MUTEX(ocotp_mutex);

int mxs_read_ocotp(unsigned offset, size_t count, u32 *values)
{
	void __iomem *ocotp_base = MXS_IO_ADDRESS(MXS_OCOTP_BASE_ADDR);
	int i, timeout = 0x400;
i should be size_t, too
	mutex_lock(&ocotp_mutex);

	/* clear ERROR bit anyway */
anyway?  Better?: "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)
		/* nothing */;

	if (unlikely(!timeout))
		goto error;
This goto and some more leave the critical section without unlocking the
mutex.
	/* 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)
		/* nothing */;

	if (unlikely(!timeout))
		goto error;

	for (i = 0; i < count; i++, offset += 4)
		*values++ = __raw_readl(ocotp_base + offset);

	/* close banks for power saving */
	__mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);

	mutex_unlock(&ocotp_mutex);

	return 0;

error:
	pr_err("%s: timeout in reading OCOTP\n", __func__);
	return -ETIMEDOUT;
}
I think it's OK then.  One optimisation that comes to my mind is to make
BM_OCOTP_CTRL_RD_BANK_OPEN a clk (that can depend on clk_h).  This would
allow for multiple readers, but I think it's not worth the effort.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help