[U-Boot] [PATCH 0/3] OMAP: Detect reset type and handle sdram init after warm rese

Certain modules are not affected by means of a warm reset and need not be configured again. Adding an API to detect a warm reset.
Emif is one such module that need not be configured after warm reset. All the registers are retained.So, skipping DDR init after warm reset. Freq_update is done to make sure timing registers are configured for appropriate frequency. This is tested on omap4430 sdp. Boot tested on omap5430uevm and omap5432sevm.
Patch 3 is taking care of Errata:i727
Lokesh Vutla (3): ARM: OMAP3+: Detect reset type OMAP4+: Handle sdram init after warm reset OMAP4+: Force DDR in self-refresh after warm reset
arch/arm/cpu/armv7/omap-common/emif-common.c | 31 ++++++++++++++++++++--- arch/arm/cpu/armv7/omap-common/hwinit-common.c | 4 +++ arch/arm/cpu/armv7/omap-common/reset.c | 5 ++++ arch/arm/include/asm/arch-am33xx/cpu.h | 2 + arch/arm/include/asm/arch-omap3/cpu.h | 2 + arch/arm/include/asm/arch-omap3/sys_proto.h | 1 + arch/arm/include/asm/arch-omap4/cpu.h | 2 + arch/arm/include/asm/arch-omap4/sys_proto.h | 2 + arch/arm/include/asm/arch-omap5/cpu.h | 2 + arch/arm/include/asm/arch-omap5/sys_proto.h | 2 + 10 files changed, 49 insertions(+), 4 deletions(-)

Certain modules are not affected by means of a warm reset and need not be configured again. Adding an API to detect the reset reason warm/cold.
This will be used to skip the module configurations that are retained across a warm reset.
Signed-off-by: Lokesh Vutla lokeshvutla@ti.com Signed-off-by: R Sricharan r.sricharan@ti.com --- arch/arm/cpu/armv7/omap-common/reset.c | 5 +++++ arch/arm/include/asm/arch-am33xx/cpu.h | 2 ++ arch/arm/include/asm/arch-omap3/cpu.h | 2 ++ arch/arm/include/asm/arch-omap3/sys_proto.h | 1 + arch/arm/include/asm/arch-omap4/cpu.h | 2 ++ arch/arm/include/asm/arch-omap4/sys_proto.h | 1 + arch/arm/include/asm/arch-omap5/cpu.h | 2 ++ arch/arm/include/asm/arch-omap5/sys_proto.h | 1 + 8 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/arch/arm/cpu/armv7/omap-common/reset.c b/arch/arm/cpu/armv7/omap-common/reset.c index 234e90a..587bb47 100644 --- a/arch/arm/cpu/armv7/omap-common/reset.c +++ b/arch/arm/cpu/armv7/omap-common/reset.c @@ -34,3 +34,8 @@ void __weak reset_cpu(unsigned long ignored) { writel(PRM_RSTCTRL_RESET, PRM_RSTCTRL); } + +u32 __weak warm_reset(void) +{ + return (readl(PRM_RSTST) & PRM_RSTST_WARM_RESET_MASK); +} diff --git a/arch/arm/include/asm/arch-am33xx/cpu.h b/arch/arm/include/asm/arch-am33xx/cpu.h index 5a6534e..a027e31 100644 --- a/arch/arm/include/asm/arch-am33xx/cpu.h +++ b/arch/arm/include/asm/arch-am33xx/cpu.h @@ -53,8 +53,10 @@ /* Reset control */ #ifdef CONFIG_AM33XX #define PRM_RSTCTRL 0x44E00F00 +#define PRM_RSTST 0x44E00F08 #endif #define PRM_RSTCTRL_RESET 0x01 +#define PRM_RSTST_WARM_RESET_MASK 0x232
#ifndef __KERNEL_STRICT_NAMES #ifndef __ASSEMBLY__ diff --git a/arch/arm/include/asm/arch-omap3/cpu.h b/arch/arm/include/asm/arch-omap3/cpu.h index 457f99d..5683e16 100644 --- a/arch/arm/include/asm/arch-omap3/cpu.h +++ b/arch/arm/include/asm/arch-omap3/cpu.h @@ -479,6 +479,8 @@ struct prm {
#define PRM_RSTCTRL 0x48307250 #define PRM_RSTCTRL_RESET 0x04 +#define PRM_RSTST 0x48307258 +#define PRM_RSTST_WARM_RESET_MASK 0x7D2 #define SYSCLKDIV_1 (0x1 << 6) #define SYSCLKDIV_2 (0x1 << 7)
diff --git a/arch/arm/include/asm/arch-omap3/sys_proto.h b/arch/arm/include/asm/arch-omap3/sys_proto.h index 2a89e56..9e52b12 100644 --- a/arch/arm/include/asm/arch-omap3/sys_proto.h +++ b/arch/arm/include/asm/arch-omap3/sys_proto.h @@ -74,4 +74,5 @@ void power_init_r(void); void dieid_num_r(void); void do_omap3_emu_romcode_call(u32 service_id, u32 parameters); void omap3_gp_romcode_call(u32 service_id, u32 parameter); +u32 warm_reset(void); #endif diff --git a/arch/arm/include/asm/arch-omap4/cpu.h b/arch/arm/include/asm/arch-omap4/cpu.h index feddb7d..a8c4c60 100644 --- a/arch/arm/include/asm/arch-omap4/cpu.h +++ b/arch/arm/include/asm/arch-omap4/cpu.h @@ -178,5 +178,7 @@ struct watchdog {
#define PRM_RSTCTRL PRM_DEVICE_BASE #define PRM_RSTCTRL_RESET 0x01 +#define PRM_RSTST (PRM_DEVICE_BASE + 0x4) +#define PRM_RSTST_WARM_RESET_MASK 0x07EA
#endif /* _CPU_H */ diff --git a/arch/arm/include/asm/arch-omap4/sys_proto.h b/arch/arm/include/asm/arch-omap4/sys_proto.h index c6e3ad2..4f0a29d 100644 --- a/arch/arm/include/asm/arch-omap4/sys_proto.h +++ b/arch/arm/include/asm/arch-omap4/sys_proto.h @@ -57,6 +57,7 @@ void init_omap_revision(void); void do_io_settings(void); void omap_vc_init(u16 speed_khz); int omap_vc_bypass_send_value(u8 sa, u8 reg_addr, u8 reg_data); +u32 warm_reset(void); /* * This is used to verify if the configuration header * was executed by Romcode prior to control of transfer diff --git a/arch/arm/include/asm/arch-omap5/cpu.h b/arch/arm/include/asm/arch-omap5/cpu.h index 8ef17c9..5e62013 100644 --- a/arch/arm/include/asm/arch-omap5/cpu.h +++ b/arch/arm/include/asm/arch-omap5/cpu.h @@ -182,5 +182,7 @@ struct watchdog {
#define PRM_RSTCTRL PRM_DEVICE_BASE #define PRM_RSTCTRL_RESET 0x01 +#define PRM_RSTST (PRM_DEVICE_BASE + 0x4) +#define PRM_RSTST_WARM_RESET_MASK 0x7FEA
#endif /* _CPU_H */ diff --git a/arch/arm/include/asm/arch-omap5/sys_proto.h b/arch/arm/include/asm/arch-omap5/sys_proto.h index 8396a22..b3bbdb7 100644 --- a/arch/arm/include/asm/arch-omap5/sys_proto.h +++ b/arch/arm/include/asm/arch-omap5/sys_proto.h @@ -57,6 +57,7 @@ void init_omap_revision(void); void do_io_settings(void); void omap_vc_init(u16 speed_khz); int omap_vc_bypass_send_value(u8 sa, u8 reg_addr, u8 reg_data); +u32 warm_reset(void);
/* * This is used to verify if the configuration header

EMIF and DDR device state are preserved in warmreset. Redoing the full initialisation would cause unexpected behaviour. Do only partial initialisation to account for frequency change.
Signed-off-by: Lokesh Vutla lokeshvutla@ti.com Signed-off-by: R Sricharan r.sricharan@ti.com Signed-off-by: Senthilvadivu Guruswamy svadivu@ti.com --- arch/arm/cpu/armv7/omap-common/emif-common.c | 10 ++++++---- 1 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c index 23cf619..edc63fa 100644 --- a/arch/arm/cpu/armv7/omap-common/emif-common.c +++ b/arch/arm/cpu/armv7/omap-common/emif-common.c @@ -990,7 +990,7 @@ struct lpddr2_device_details *emif_get_device_details(u32 emif_nr, u8 cs, return NULL;
/* Do the minimum init for mode register accesses */ - if (!running_from_sdram()) { + if (!(running_from_sdram() || warm_reset())) { phy = get_ddr_phy_ctrl_1(get_sys_clk_freq() / 2, RL_BOOT); writel(phy, &emif->emif_ddr_phy_ctrl_1); } @@ -1070,7 +1070,7 @@ static void do_sdram_init(u32 base) * Changing the timing registers in EMIF can happen(going from one * OPP to another) */ - if (!in_sdram) { + if (!(in_sdram || warm_reset())) { if (omap_revision() != OMAP5432_ES1_0) lpddr2_init(base, regs); else @@ -1242,7 +1242,7 @@ void sdram_init(void) in_sdram = running_from_sdram(); debug("in_sdram = %d\n", in_sdram);
- if (!in_sdram) { + if (!(in_sdram || warm_reset())) { if (omap_rev != OMAP5432_ES1_0) bypass_dpll(&prcm->cm_clkmode_dpll_core); else @@ -1252,8 +1252,10 @@ void sdram_init(void) do_sdram_init(EMIF1_BASE); do_sdram_init(EMIF2_BASE);
- if (!in_sdram) { + if (!in_sdram) dmm_init(DMM_BASE); + + if (!(in_sdram || warm_reset())) { emif_post_init_config(EMIF1_BASE); emif_post_init_config(EMIF2_BASE); }

Errata ID:i727
Description: The refresh rate is programmed in the EMIF_SDRAM_REF_CTRL[15:0] REG_REFRESH_RATE parameter taking into account frequency of the device. When a warm reset is applied on the system, the OMAP processor restarts with another OPP and so frequency is not the same. Due to this frequency change, the refresh rate will be too low and could result in an unexpected behavior on the memory side.
Workaround: The workaround is to force self-refresh when coming back from the warm reset with the following sequence: • Set EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x2 • Set EMIF_PWR_MGMT_CTRL[7:4] REG_SR_TIM to 0x0 • Do a dummy read (loads automatically new value of sr_tim) This will reduce the risk of memory content corruption, but memory content can't be guaranteed after a warm reset.
This errata is impacted on OMAP4430: 1.0, 2.0, 2.1, 2.2, 2.3 OMAP4460: 1.0, 1.1 OMAP4470: 1.0 OMAP5430: 1.0
Signed-off-by: Lokesh Vutla lokeshvutla@ti.com Signed-off-by: R Sricharan r.sricharan@ti.com Signed-off-by: Senthilvadivu Guruswamy svadivu@ti.com --- arch/arm/cpu/armv7/omap-common/emif-common.c | 21 +++++++++++++++++++++ arch/arm/cpu/armv7/omap-common/hwinit-common.c | 4 ++++ arch/arm/include/asm/arch-omap4/sys_proto.h | 1 + arch/arm/include/asm/arch-omap5/sys_proto.h | 1 + 4 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c index edc63fa..64427e6 100644 --- a/arch/arm/cpu/armv7/omap-common/emif-common.c +++ b/arch/arm/cpu/armv7/omap-common/emif-common.c @@ -32,6 +32,27 @@ #include <asm/omap_common.h> #include <asm/utils.h>
+void set_lpmode_selfrefresh(u32 base) +{ + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + u32 reg; + + reg = readl(&emif->emif_pwr_mgmt_ctrl); + reg &= ~EMIF_REG_LP_MODE_MASK; + reg |= LP_MODE_SELF_REFRESH << EMIF_REG_LP_MODE_SHIFT; + reg &= ~EMIF_REG_SR_TIM_MASK; + writel(reg, &emif->emif_pwr_mgmt_ctrl); + + /* dummy read for the new SR_TIM to be loaded */ + readl(&emif->emif_pwr_mgmt_ctrl); +} + +void force_emif_self_refresh() +{ + set_lpmode_selfrefresh(EMIF1_BASE); + set_lpmode_selfrefresh(EMIF2_BASE); +} + inline u32 emif_num(u32 base) { if (base == EMIF1_BASE) diff --git a/arch/arm/cpu/armv7/omap-common/hwinit-common.c b/arch/arm/cpu/armv7/omap-common/hwinit-common.c index 6600323..459ebb5 100644 --- a/arch/arm/cpu/armv7/omap-common/hwinit-common.c +++ b/arch/arm/cpu/armv7/omap-common/hwinit-common.c @@ -111,6 +111,10 @@ static void init_boot_params(void) void s_init(void) { init_omap_revision(); +#ifdef CONFIG_SPL_BUILD + if (warm_reset() && (omap_revision() <= OMAP5430_ES1_0)) + force_emif_self_refresh(); +#endif watchdog_init(); set_mux_conf_regs(); #ifdef CONFIG_SPL_BUILD diff --git a/arch/arm/include/asm/arch-omap4/sys_proto.h b/arch/arm/include/asm/arch-omap4/sys_proto.h index 4f0a29d..d633573 100644 --- a/arch/arm/include/asm/arch-omap4/sys_proto.h +++ b/arch/arm/include/asm/arch-omap4/sys_proto.h @@ -58,6 +58,7 @@ void do_io_settings(void); void omap_vc_init(u16 speed_khz); int omap_vc_bypass_send_value(u8 sa, u8 reg_addr, u8 reg_data); u32 warm_reset(void); +void force_emif_self_refresh(void); /* * This is used to verify if the configuration header * was executed by Romcode prior to control of transfer diff --git a/arch/arm/include/asm/arch-omap5/sys_proto.h b/arch/arm/include/asm/arch-omap5/sys_proto.h index b3bbdb7..74feb90 100644 --- a/arch/arm/include/asm/arch-omap5/sys_proto.h +++ b/arch/arm/include/asm/arch-omap5/sys_proto.h @@ -58,6 +58,7 @@ void do_io_settings(void); void omap_vc_init(u16 speed_khz); int omap_vc_bypass_send_value(u8 sa, u8 reg_addr, u8 reg_data); u32 warm_reset(void); +void force_emif_self_refresh(void);
/* * This is used to verify if the configuration header

On Wed, May 30, 2012 at 10:56:40AM +0530, Lokesh Vutla wrote: `
Certain modules are not affected by means of a warm reset and need not be configured again. Adding an API to detect a warm reset.
Emif is one such module that need not be configured after warm reset. All the registers are retained.So, skipping DDR init after warm reset. Freq_update is done to make sure timing registers are configured for appropriate frequency. This is tested on omap4430 sdp. Boot tested on omap5430uevm and omap5432sevm.
Patch 3 is taking care of Errata:i727
Lokesh Vutla (3): ARM: OMAP3+: Detect reset type OMAP4+: Handle sdram init after warm reset OMAP4+: Force DDR in self-refresh after warm reset
Queued up for u-boot-ti/master, thanks!
participants (2)
-
Lokesh Vutla
-
Tom Rini