summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2011-12-13 14:48:51 +0800
committerAnson Huang <b20788@freescale.com>2011-12-20 20:14:54 +0800
commit3568732ec72b2d792aeb3f780b0d1f32d86f36ec (patch)
tree6627be5c2a0b4baa04f79c4a9cf7932b8eaccf3f /cpu
parent14dab831e8e93a7ee03de2c7cca00d4b81e00cdc (diff)
ENGR00160621 [MX6]Workaround for reset issue
Add workaround for POR/wdog reset issue, we need to do a CORE LDO reset everytime POR/wdog reset, otherwise kernel will crash or hang when we booting more than 2 cores. Root cause is still under investigation, it is analog/power related issue, may take long time to identify the root cause, we need to add workaround to make function ready first. The flow of workaround is as below: 1. Check CORE LDO reset flag, currently stored in SNVS_LPGPR[0]; 2. If it is there, clear it, go on boot up system; If not, Set the flag, configure wdog to timeout in 0.5 seconds, then disable CORE LDO and wait for wdog timeout; This workaround will bring 0.5~1 seconds delay of booting. Signed-off-by: Anson Huang <b20788@freescale.com>
Diffstat (limited to 'cpu')
-rw-r--r--cpu/arm_cortexa8/mx6/generic.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/cpu/arm_cortexa8/mx6/generic.c b/cpu/arm_cortexa8/mx6/generic.c
index 47b9cd1512..216308bad4 100644
--- a/cpu/arm_cortexa8/mx6/generic.c
+++ b/cpu/arm_cortexa8/mx6/generic.c
@@ -82,6 +82,8 @@ enum pll_clocks {
#define NFC_CLK_MAX PLL2_FREQ_MAX
#endif
+#define SNVS_LPGPR_OFFSET 0x68
+
static u32 __decode_pll(enum pll_clocks pll, u32 infreq)
{
u32 div;
@@ -843,6 +845,29 @@ int cpu_eth_init(bd_t *bis)
int arch_cpu_init(void)
{
int val;
+ unsigned int reg;
+
+ /* Check the flag of SNVS_LPGPR[0], SRC register will not reset
+ when we do a wdog reset, so we keep flag in SNVS_LPGPR[0],
+ when we finish this workaround, we will clear it */
+ reg = readl(SNVS_BASE_ADDR + SNVS_LPGPR_OFFSET);
+ /* If flagg is not set */
+ if (!(reg & 0x1)) {
+ /* Set flag in SNVS_LPGPR[0] */
+ writel(readl(SNVS_BASE_ADDR + SNVS_LPGPR_OFFSET) | 0x1,
+ SNVS_BASE_ADDR + SNVS_LPGPR_OFFSET);
+ /* Set wdog to timeout in 0.5 second */
+ writew(0x34, WDOG1_BASE_ADDR);
+ /* Disable CORE LDO */
+ writel(0x0, ANATOP_BASE_ADDR + HW_ANADIG_REG_CORE);
+ /* Wait for wdog timeout */
+ while (1)
+ ;
+ } else {
+ /* Clear flag */
+ writel(readl(SNVS_BASE_ADDR + SNVS_LPGPR_OFFSET) & (~0x1),
+ SNVS_BASE_ADDR + SNVS_LPGPR_OFFSET);
+ }
icache_enable();
dcache_enable();