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 <j...@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.va...@gmail.com> * on behalf of DENX Software Engineering GmbH * + * Copyright 2013 Stefan Roese <s...@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) & 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) & 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_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_clr); + + /* Set SFTRST */ + writel(MXS_BLOCK_SFTRST, ®->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_clr); + + if (mxs_early_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT)) + return 1; + + /* Clear CLKGATE */ + writel(MXS_BLOCK_CLKGATE, ®->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 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox