Patchwork [U-Boot] ARM: OMAP5: Fix warm reset with USB cable connected

login
register
mail settings
Submitter Lokesh Vutla
Date April 18, 2013, 6:49 a.m.
Message ID <1366267780-15849-1-git-send-email-lokeshvutla@ti.com>
Download mbox | patch
Permalink /patch/237461/
State Accepted
Delegated to: Tom Rini
Headers show

Comments

Lokesh Vutla - April 18, 2013, 6:49 a.m.
Warm reset on OMAP5 freezes when USB cable is connected.
Fix requires PRM_RSTTIME.RSTTIME1 to be programmed
with the time for which reset should be held low for the
voltages and the oscillator to reach stable state.

There are 3 parameters to be considered for calculating
the time, which are mostly board and PMIC dependent.
-1- Time taken by the Oscillator to shut + restart
-2- PMIC OTP times
-3- Voltage rail ramp times, which inturn depends on the
PMIC slew rate and value of the voltage ramp needed.

In order to keep the code in u-boot simple, have a way
for boards to specify a pre computed time directly using
the 'CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC'
option. If boards fail to specify the time, use a default
as specified by 'CONFIG_DEFAULT_OMAP_RESET_TIME_MAX_USEC' instead.
Using the default value translates into some ~22ms and should work in
all cases.
However in order to avoid this large delay hiding other bugs,
its recommended that all boards look at their respective data
sheets and specify a pre computed and optimal value using
'CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC'

In order to help future board additions to compute this
config option value, add a README at doc/README.omap-reset-time
which explains how to compute the value. Also update the toplevel
README with the additional option and pointers to
doc/README.omap-reset-time.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
[rnayak@ti.com: Updated changelog and added the README]
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
 README                                         |    4 ++++
 arch/arm/cpu/armv7/omap-common/clocks-common.c |    1 +
 arch/arm/cpu/armv7/omap-common/reset.c         |    4 ++++
 arch/arm/cpu/armv7/omap5/hwinit.c              |   19 +++++++++++++++++++
 arch/arm/cpu/armv7/omap5/prcm-regs.c           |    2 ++
 arch/arm/include/asm/arch-omap4/sys_proto.h    |    1 +
 arch/arm/include/asm/arch-omap5/clocks.h       |   10 ++++++++++
 arch/arm/include/asm/arch-omap5/sys_proto.h    |   10 ++++++++++
 arch/arm/include/asm/omap_common.h             |    1 +
 doc/README.omap-reset-time                     |   20 ++++++++++++++++++++
 include/configs/omap5_uevm.h                   |    1 +
 11 files changed, 73 insertions(+)
 create mode 100644 doc/README.omap-reset-time
Tom Rini - April 29, 2013, 8:22 p.m.
On Wed, Apr 17, 2013 at 08:49:40PM -0000, Lokesh Vutla wrote:

> Warm reset on OMAP5 freezes when USB cable is connected.
> Fix requires PRM_RSTTIME.RSTTIME1 to be programmed
> with the time for which reset should be held low for the
> voltages and the oscillator to reach stable state.
> 
> There are 3 parameters to be considered for calculating
> the time, which are mostly board and PMIC dependent.
> -1- Time taken by the Oscillator to shut + restart
> -2- PMIC OTP times
> -3- Voltage rail ramp times, which inturn depends on the
> PMIC slew rate and value of the voltage ramp needed.
> 
> In order to keep the code in u-boot simple, have a way
> for boards to specify a pre computed time directly using
> the 'CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC'
> option. If boards fail to specify the time, use a default
> as specified by 'CONFIG_DEFAULT_OMAP_RESET_TIME_MAX_USEC' instead.
> Using the default value translates into some ~22ms and should work in
> all cases.
> However in order to avoid this large delay hiding other bugs,
> its recommended that all boards look at their respective data
> sheets and specify a pre computed and optimal value using
> 'CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC'
> 
> In order to help future board additions to compute this
> config option value, add a README at doc/README.omap-reset-time
> which explains how to compute the value. Also update the toplevel
> README with the additional option and pointers to
> doc/README.omap-reset-time.
> 
> Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
> [rnayak@ti.com: Updated changelog and added the README]
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>

Applied to u-boot-ti/master, thanks!

Patch

diff --git a/README b/README
index 0bc0af5..4531891 100644
--- a/README
+++ b/README
@@ -3323,6 +3323,10 @@  Configuration Settings:
 	offset _bss_start_ofs from CONFIG_SYS_TEXT_BASE, rather than
 	directly. You should not need to touch this setting.
 
+- CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC (OMAP only)
+	This is set by OMAP boards for the max time that reset should
+	be asserted. See doc/README.omap-reset-time for details on how
+	the value can be calulated on a given board.
 
 The following definitions that deal with the placement and management
 of environment data (variable area); in general, we support the
diff --git a/arch/arm/cpu/armv7/omap-common/clocks-common.c b/arch/arm/cpu/armv7/omap-common/clocks-common.c
index 2b955c7..99910cd 100644
--- a/arch/arm/cpu/armv7/omap-common/clocks-common.c
+++ b/arch/arm/cpu/armv7/omap-common/clocks-common.c
@@ -716,6 +716,7 @@  void prcm_init(void)
 		setup_non_essential_dplls();
 		enable_non_essential_clocks();
 #endif
+		setup_warmreset_time();
 		break;
 	default:
 		break;
diff --git a/arch/arm/cpu/armv7/omap-common/reset.c b/arch/arm/cpu/armv7/omap-common/reset.c
index 587bb47..57ea9d9 100644
--- a/arch/arm/cpu/armv7/omap-common/reset.c
+++ b/arch/arm/cpu/armv7/omap-common/reset.c
@@ -39,3 +39,7 @@  u32 __weak warm_reset(void)
 {
 	return (readl(PRM_RSTST) & PRM_RSTST_WARM_RESET_MASK);
 }
+
+void __weak setup_warmreset_time(void)
+{
+}
diff --git a/arch/arm/cpu/armv7/omap5/hwinit.c b/arch/arm/cpu/armv7/omap5/hwinit.c
index 2f4b247..d29df78 100644
--- a/arch/arm/cpu/armv7/omap5/hwinit.c
+++ b/arch/arm/cpu/armv7/omap5/hwinit.c
@@ -363,3 +363,22 @@  u32 warm_reset(void)
 {
 	return readl((*prcm)->prm_rstst) & PRM_RSTST_WARM_RESET_MASK;
 }
+
+void setup_warmreset_time(void)
+{
+	u32 rst_time, rst_val;
+
+#ifndef CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC
+	rst_time = CONFIG_DEFAULT_OMAP_RESET_TIME_MAX_USEC;
+#else
+	rst_time = CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC;
+#endif
+	rst_time = usec_to_32k(rst_time) << RSTTIME1_SHIFT;
+
+	if (rst_time > RSTTIME1_MASK)
+		rst_time = RSTTIME1_MASK;
+
+	rst_val = readl((*prcm)->prm_rsttime) & ~RSTTIME1_MASK;
+	rst_val |= rst_time;
+	writel(rst_val, (*prcm)->prm_rsttime);
+}
diff --git a/arch/arm/cpu/armv7/omap5/prcm-regs.c b/arch/arm/cpu/armv7/omap5/prcm-regs.c
index b8a61fe..e9f6a32 100644
--- a/arch/arm/cpu/armv7/omap5/prcm-regs.c
+++ b/arch/arm/cpu/armv7/omap5/prcm-regs.c
@@ -729,6 +729,7 @@  struct prcm_regs const omap5_es2_prcm = {
 	.cm_wkupaon_io_srcomp_clkctrl = 0x4ae07998,
 	.prm_rstctrl = 0x4ae07c00,
 	.prm_rstst = 0x4ae07c04,
+	.prm_rsttime = 0x4ae07c08,
 	.prm_vc_val_bypass = 0x4ae07ca0,
 	.prm_vc_cfg_i2c_mode = 0x4ae07cb4,
 	.prm_vc_cfg_i2c_clk = 0x4ae07cb8,
@@ -952,6 +953,7 @@  struct prcm_regs const dra7xx_prcm = {
 	.cm_wkupaon_scrm_clkctrl		= 0x4ae07890,
 	.prm_rstctrl				= 0x4ae07d00,
 	.prm_rstst				= 0x4ae07d04,
+	.prm_rsttime				= 0x4ae07d08,
 	.prm_vc_val_bypass			= 0x4ae07da0,
 	.prm_vc_cfg_i2c_mode			= 0x4ae07db4,
 	.prm_vc_cfg_i2c_clk			= 0x4ae07db8,
diff --git a/arch/arm/include/asm/arch-omap4/sys_proto.h b/arch/arm/include/asm/arch-omap4/sys_proto.h
index d5f1868..ac9c1f8 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 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);
+void setup_warmreset_time(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/clocks.h b/arch/arm/include/asm/arch-omap5/clocks.h
index cfde374..68afa76 100644
--- a/arch/arm/include/asm/arch-omap5/clocks.h
+++ b/arch/arm/include/asm/arch-omap5/clocks.h
@@ -190,6 +190,10 @@ 
 #define OPTFCLKEN_SRCOMP_FCLK_SHIFT		8
 #define OPTFCLKEN_SRCOMP_FCLK_MASK		(1 << 8)
 
+/* PRM_RSTTIME */
+#define RSTTIME1_SHIFT				0
+#define RSTTIME1_MASK				(0x3ff << 0)
+
 /* Clock frequencies */
 #define OMAP_SYS_CLK_FREQ_38_4_MHZ	38400000
 #define OMAP_SYS_CLK_IND_38_4_MHZ	6
@@ -251,4 +255,10 @@ 
 #define DPLL_NO_LOCK	0
 #define DPLL_LOCK	1
 
+/*
+ * MAX value for PRM_RSTTIME[9:0]RSTTIME1 stored is 0x3ff.
+ * 0x3ff is in the no of FUNC_32K_CLK cycles. Converting cycles
+ * into microsec and passing the value.
+ */
+#define CONFIG_DEFAULT_OMAP_RESET_TIME_MAX_USEC	31219
 #endif /* _CLOCKS_OMAP5_H_ */
diff --git a/arch/arm/include/asm/arch-omap5/sys_proto.h b/arch/arm/include/asm/arch-omap5/sys_proto.h
index e66ab44..393c8bf 100644
--- a/arch/arm/include/asm/arch-omap5/sys_proto.h
+++ b/arch/arm/include/asm/arch-omap5/sys_proto.h
@@ -64,6 +64,7 @@  u32 warm_reset(void);
 void force_emif_self_refresh(void);
 void get_ioregs(const struct ctrl_ioregs **regs);
 void srcomp_enable(void);
+void setup_warmreset_time(void);
 
 /*
  * This is used to verify if the configuration header
@@ -122,4 +123,13 @@  static inline u32 omap_hw_init_context(void)
 #endif
 }
 
+static inline u32 div_round_up(u32 num, u32 den)
+{
+	return (num + den - 1)/den;
+}
+
+static inline u32 usec_to_32k(u32 usec)
+{
+	return div_round_up(32768 * usec, 1000000);
+}
 #endif
diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h
index 091ddb5..6d377d5 100644
--- a/arch/arm/include/asm/omap_common.h
+++ b/arch/arm/include/asm/omap_common.h
@@ -316,6 +316,7 @@  struct prcm_regs {
 	u32 cm_wkupaon_io_srcomp_clkctrl;
 	u32 prm_rstctrl;
 	u32 prm_rstst;
+	u32 prm_rsttime;
 	u32 prm_vc_val_bypass;
 	u32 prm_vc_cfg_i2c_mode;
 	u32 prm_vc_cfg_i2c_clk;
diff --git a/doc/README.omap-reset-time b/doc/README.omap-reset-time
new file mode 100644
index 0000000..0c974ba
--- /dev/null
+++ b/doc/README.omap-reset-time
@@ -0,0 +1,20 @@ 
+README on how reset time on OMAPs should be calculated
+
+CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC:
+Most OMAPs' provide a way to specify the time for
+which the reset should be held low while the voltages
+and Oscillator outputs stabilize.
+
+This time is mostly board and PMIC dependent. Hence the
+boards are expected to specify a pre-computed time
+using the above option, (the details on how to compute
+the value are given below) without which a default time
+as specified by CONFIG_DEFAULT_OMAP_RESET_TIME_MAX_USEC
+is used.
+
+The value for CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC
+can be computed using a summation of the below 3 parameters
+-1- Time taken by the Osciallator to stop and restart
+-2- PMIC OTP time
+-3- Voltage ramp time, which can be derived using the
+PMIC slew rate and value of voltage ramp needed.
diff --git a/include/configs/omap5_uevm.h b/include/configs/omap5_uevm.h
index 240fdfc..52eb7af 100644
--- a/include/configs/omap5_uevm.h
+++ b/include/configs/omap5_uevm.h
@@ -54,4 +54,5 @@ 
 
 #define CONFIG_SYS_PROMPT		"OMAP5430 EVM # "
 
+#define CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC	16296
 #endif /* __CONFIG_OMAP5_EVM_H */