]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - arch/arm/cpu/arm926ejs/mxs/mxs.c
TX6 Release 2013-04-22
[karo-tx-uboot.git] / arch / arm / cpu / arm926ejs / mxs / mxs.c
index 6ce8019b835ef832a2dfdab056f8bc7215b73aec..d314144f50055a498fd3466da46ee3bfccddc6e0 100644 (file)
@@ -81,12 +81,20 @@ void enable_caches(void)
 #endif
 }
 
+#define        MX28_HW_DIGCTL_MICROSECONDS     (void *)0x8001c0c0
+
 int mxs_wait_mask_set(struct mxs_register_32 *reg, uint32_t mask, unsigned
                                                                int timeout)
 {
-       while (--timeout) {
-               if ((readl(&reg->reg) & mask) == mask)
-                       break;
+       uint32_t start = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+       /* Wait for at least one microsecond for the bit mask to be set */
+       while (readl(MX28_HW_DIGCTL_MICROSECONDS) - start <= 1 || --timeout) {
+               if ((readl(&reg->reg) & mask) == mask) {
+                       while (readl(MX28_HW_DIGCTL_MICROSECONDS) - start <= 1)
+                               ;
+                       return 0;
+               }
                udelay(1);
        }
 
@@ -96,9 +104,15 @@ int mxs_wait_mask_set(struct mxs_register_32 *reg, uint32_t mask, unsigned
 int mxs_wait_mask_clr(struct mxs_register_32 *reg, uint32_t mask, unsigned
                                                                int timeout)
 {
-       while (--timeout) {
-               if ((readl(&reg->reg) & mask) == 0)
-                       break;
+       uint32_t start = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+       /* Wait for at least one microsecond for the bit mask to be cleared */
+       while (readl(MX28_HW_DIGCTL_MICROSECONDS) - start <= 1 || --timeout) {
+               if ((readl(&reg->reg) & mask) == 0) {
+                       while (readl(MX28_HW_DIGCTL_MICROSECONDS) - start <= 1)
+                               ;
+                       return 0;
+               }
                udelay(1);
        }
 
@@ -110,8 +124,11 @@ int mxs_reset_block(struct mxs_register_32 *reg)
        /* Clear SFTRST */
        writel(MXS_BLOCK_SFTRST, &reg->reg_clr);
 
-       if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+       if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT)) {
+               printf("TIMEOUT waiting for SFTRST[%p] to clear: %08x\n",
+                       reg, readl(&reg->reg));
                return 1;
+       }
 
        /* Clear CLKGATE */
        writel(MXS_BLOCK_CLKGATE, &reg->reg_clr);
@@ -120,20 +137,29 @@ int mxs_reset_block(struct mxs_register_32 *reg)
        writel(MXS_BLOCK_SFTRST, &reg->reg_set);
 
        /* Wait for CLKGATE being set */
-       if (mxs_wait_mask_set(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+       if (mxs_wait_mask_set(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT)) {
+               printf("TIMEOUT waiting for CLKGATE[%p] to set: %08x\n",
+                       reg, readl(&reg->reg));
                return 1;
+       }
 
        /* Clear SFTRST */
        writel(MXS_BLOCK_SFTRST, &reg->reg_clr);
 
-       if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+       if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT)) {
+               printf("TIMEOUT waiting for SFTRST[%p] to clear: %08x\n",
+                       reg, readl(&reg->reg));
                return 1;
+       }
 
        /* Clear CLKGATE */
        writel(MXS_BLOCK_CLKGATE, &reg->reg_clr);
 
-       if (mxs_wait_mask_clr(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+       if (mxs_wait_mask_clr(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT)) {
+               printf("TIMEOUT waiting for CLKGATE[%p] to clear: %08x\n",
+                       reg, readl(&reg->reg));
                return 1;
+       }
 
        return 0;
 }
@@ -155,6 +181,7 @@ int arch_misc_init(void)
 }
 #endif
 
+#ifdef CONFIG_ARCH_CPU_INIT
 int arch_cpu_init(void)
 {
        struct mxs_clkctrl_regs *clkctrl_regs =
@@ -188,6 +215,7 @@ int arch_cpu_init(void)
 
        return 0;
 }
+#endif
 
 #if defined(CONFIG_DISPLAY_CPUINFO)
 static const char *get_cpu_type(void)
@@ -265,13 +293,16 @@ int cpu_eth_init(bd_t *bis)
 
        udelay(10);
 
+       /*
+        * Enable pad output; must be done BEFORE enabling PLL
+        * according to i.MX28 Ref. Manual Rev. 1, 2010 p. 883
+        */
+       setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
+
        /* Gate on ENET PLL */
        writel(CLKCTRL_PLL2CTRL0_CLKGATE,
                &clkctrl_regs->hw_clkctrl_pll2ctrl0_clr);
 
-       /* Enable pad output */
-       setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
-
        return 0;
 }
 #endif