[PATCH 3/8] fixup! ARM: mxs: Add lowlevel setup from U-Boot

Jan Luebbe jlu at pengutronix.de
Thu Dec 25 09:09:00 PST 2014


Some boards need to use a different memory setup. Instead of a weak
funktion like u-boot, we make the register data available to the board
code. Also add some early delay and block reset code.

Signed-off-by: Jan Luebbe <jlu at pengutronix.de>
---
 arch/arm/mach-mxs/include/mach/init.h |  3 ++
 arch/arm/mach-mxs/mem-init.c          | 91 ++++++++++++++++++++++++++++++++---
 2 files changed, 88 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-mxs/include/mach/init.h b/arch/arm/mach-mxs/include/mach/init.h
index d1ac2e4..1f9d8d4 100644
--- a/arch/arm/mach-mxs/include/mach/init.h
+++ b/arch/arm/mach-mxs/include/mach/init.h
@@ -18,6 +18,9 @@ void mx28_power_init(void);
 void mx28_power_init_battery_input(void);
 void mxs_power_wait_pswitch(void);
 
+extern uint32_t mx28_dram_vals[];
+extern uint32_t mx23_dram_vals[];
+
 void mx23_mem_init(void);
 void mx28_mem_init(void);
 void mxs_mem_setup_cpu_and_hbus(void);
diff --git a/arch/arm/mach-mxs/mem-init.c b/arch/arm/mach-mxs/mem-init.c
index f4328b7..9773f94 100644
--- a/arch/arm/mach-mxs/mem-init.c
+++ b/arch/arm/mach-mxs/mem-init.c
@@ -4,6 +4,8 @@
  * Copyright (C) 2011 Marek Vasut <marek.vasut at gmail.com>
  * on behalf of DENX Software Engineering GmbH
  *
+ * Copyright 2013 Stefan Roese <sr at denx.de>
+ *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
@@ -12,13 +14,80 @@
 #include <io.h>
 #include <mach/imx-regs.h>
 #include <linux/compiler.h>
-#include <stmp-device.h>
 
 #include <mach/init.h>
 #include <mach/regs-power-mx28.h>
-#include <mach/regs-clkctrl-mx28.h>
+#if defined CONFIG_ARCH_IMX23
+# include <mach/regs-clkctrl-mx23.h>
+#endif
+#if defined CONFIG_ARCH_IMX28
+# include <mach/regs-clkctrl-mx28.h>
+#endif
+
+/* 1 second delay should be plenty of time for block reset. */
+#define	RESET_MAX_TIMEOUT	1000000
+
+#define	MXS_BLOCK_SFTRST	(1 << 31)
+#define	MXS_BLOCK_CLKGATE	(1 << 30)
+
+int mxs_early_wait_mask_set(struct mxs_register_32 *reg, uint32_t mask, unsigned
+								int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == mask)
+			break;
+		mxs_early_delay(1);
+	}
+
+	return !timeout;
+}
+
+int mxs_early_wait_mask_clr(struct mxs_register_32 *reg, uint32_t mask, unsigned
+								int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == 0)
+			break;
+		mxs_early_delay(1);
+	}
+
+	return !timeout;
+}
+
+int mxs_early_reset_block(struct mxs_register_32 *reg)
+{
+	/* Clear SFTRST */
+	writel(MXS_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mxs_early_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
 
-static uint32_t mx28_dram_vals[] = {
+	/* Clear CLKGATE */
+	writel(MXS_BLOCK_CLKGATE, &reg->reg_clr);
+
+	/* Set SFTRST */
+	writel(MXS_BLOCK_SFTRST, &reg->reg_set);
+
+	/* Wait for CLKGATE being set */
+	if (mxs_early_wait_mask_set(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear SFTRST */
+	writel(MXS_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mxs_early_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MXS_BLOCK_CLKGATE, &reg->reg_clr);
+
+	if (mxs_early_wait_mask_clr(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	return 0;
+}
+
+uint32_t mx28_dram_vals[] = {
 /*
  * i.MX28 DDR2 at 200MHz
  */
@@ -75,7 +144,7 @@ static uint32_t mx28_dram_vals[] = {
 /*
  * i.MX23 DDR at 133MHz
  */
-static uint32_t mx23_dram_vals[] = {
+uint32_t mx23_dram_vals[] = {
 	0x01010001, 0x00010100, 0x01000101, 0x00000001,
 	0x00000101, 0x00000000, 0x00010000, 0x01000001,
 	0x00000000, 0x00000001, 0x07000200, 0x00070202,
@@ -202,9 +271,13 @@ static void mx23_mem_setup_vddmem(void)
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)IMX_POWER_BASE;
 
+	/* We must wait before and after disabling the current limiter! */
+	mxs_early_delay(10000);
+
 	clrbits_le32(&power_regs->hw_power_vddmemctrl,
 		POWER_VDDMEMCTRL_ENABLE_ILIMIT);
 
+	mxs_early_delay(10000);
 }
 
 void mx23_mem_init(void)
@@ -221,7 +294,7 @@ void mx23_mem_init(void)
 	 * suffers from memory instability. This thing is mx23 specific and is
 	 * no longer present on mx28.
 	 */
-	stmp_reset_block((struct mxs_register_32 *)IMX_EMI_BASE, 0);
+	mxs_early_reset_block((struct mxs_register_32 *)IMX_EMI_BASE);
 
 	mx23_mem_setup_vddmem();
 
@@ -238,7 +311,13 @@ void mx23_mem_init(void)
 	setbits_le32(IMX_SDRAMC_BASE + 0x20, 1 << 16);
 
 	clrbits_le32(IMX_SDRAMC_BASE + 0x40, 1 << 17);
-	mxs_early_delay(20000);
+
+	/* Wait for EMI_STAT bit DRAM_HALTED */
+	for (;;) {
+		if (!(readl(IMX_EMI_BASE + 0x10) & (1 << 1)))
+			break;
+		mxs_early_delay(1000);
+	}
 
 	/* Adjust EMI port priority. */
 	clrsetbits_le32(0x80020000, 0x1f << 16, 0x2);
-- 
2.1.4




More information about the barebox mailing list