sunxi: Fix dram initialization not working on some a33 devices
[oweals/u-boot.git] / arch / arm / cpu / armv7 / sunxi / clock_sun4i.c
index a0e49d179feff469f212f479925bc6ab881b3585..c3e04af36dab671aa0d6e16c63cacd40129c287d 100644 (file)
@@ -100,22 +100,23 @@ static struct {
        unsigned int freq;
 } pll1_para[] = {
        /* This array must be ordered by frequency. */
-       { PLL1_CFG(16, 0, 0, 0), 384000000 },
-       { PLL1_CFG(16, 1, 0, 0), 768000000 },
-       { PLL1_CFG(20, 1, 0, 0), 960000000 },
-       { PLL1_CFG(21, 1, 0, 0), 1008000000},
-       { PLL1_CFG(22, 1, 0, 0), 1056000000},
-       { PLL1_CFG(23, 1, 0, 0), 1104000000},
-       { PLL1_CFG(24, 1, 0, 0), 1152000000},
-       { PLL1_CFG(25, 1, 0, 0), 1200000000},
-       { PLL1_CFG(26, 1, 0, 0), 1248000000},
-       { PLL1_CFG(27, 1, 0, 0), 1296000000},
-       { PLL1_CFG(28, 1, 0, 0), 1344000000},
-       { PLL1_CFG(29, 1, 0, 0), 1392000000},
-       { PLL1_CFG(30, 1, 0, 0), 1440000000},
        { PLL1_CFG(31, 1, 0, 0), 1488000000},
-       /* Final catchall entry */
-       { PLL1_CFG(31, 1, 0, 0), ~0},
+       { PLL1_CFG(30, 1, 0, 0), 1440000000},
+       { PLL1_CFG(29, 1, 0, 0), 1392000000},
+       { PLL1_CFG(28, 1, 0, 0), 1344000000},
+       { PLL1_CFG(27, 1, 0, 0), 1296000000},
+       { PLL1_CFG(26, 1, 0, 0), 1248000000},
+       { PLL1_CFG(25, 1, 0, 0), 1200000000},
+       { PLL1_CFG(24, 1, 0, 0), 1152000000},
+       { PLL1_CFG(23, 1, 0, 0), 1104000000},
+       { PLL1_CFG(22, 1, 0, 0), 1056000000},
+       { PLL1_CFG(21, 1, 0, 0), 1008000000},
+       { PLL1_CFG(20, 1, 0, 0), 960000000 },
+       { PLL1_CFG(19, 1, 0, 0), 912000000 },
+       { PLL1_CFG(16, 1, 0, 0), 768000000 },
+       /* Final catchall entry 384MHz*/
+       { PLL1_CFG(16, 0, 0, 0), 0 },
+
 };
 
 void clock_set_pll1(unsigned int hz)
@@ -126,10 +127,12 @@ void clock_set_pll1(unsigned int hz)
                (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 
        /* Find target frequency */
-       while (pll1_para[i].freq < hz)
+       while (pll1_para[i].freq > hz)
                i++;
 
        hz = pll1_para[i].freq;
+       if (! hz)
+               hz = 384000000;
 
        /* Calculate system clock divisors */
        axi = DIV_ROUND_UP(hz, 432000000);      /* Max 450MHz */
@@ -180,6 +183,21 @@ void clock_set_pll1(unsigned int hz)
 }
 #endif
 
+void clock_set_pll3(unsigned int clk)
+{
+       struct sunxi_ccm_reg * const ccm =
+               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+       if (clk == 0) {
+               clrbits_le32(&ccm->pll3_cfg, CCM_PLL3_CTRL_EN);
+               return;
+       }
+
+       /* PLL3 rate = 3000000 * m */
+       writel(CCM_PLL3_CTRL_EN | CCM_PLL3_CTRL_INTEGER_MODE |
+              CCM_PLL3_CTRL_M(clk / 3000000), &ccm->pll3_cfg);
+}
+
 unsigned int clock_get_pll5p(void)
 {
        struct sunxi_ccm_reg *const ccm =
@@ -200,3 +218,15 @@ unsigned int clock_get_pll6(void)
        int k = ((rval & CCM_PLL6_CTRL_K_MASK) >> CCM_PLL6_CTRL_K_SHIFT) + 1;
        return 24000000 * n * k / 2;
 }
+
+void clock_set_de_mod_clock(u32 *clk_cfg, unsigned int hz)
+{
+       int pll = clock_get_pll5p();
+       int div = 1;
+
+       while ((pll / div) > hz)
+               div++;
+
+       writel(CCM_DE_CTRL_GATE | CCM_DE_CTRL_RST | CCM_DE_CTRL_PLL5P |
+              CCM_DE_CTRL_M(div), clk_cfg);
+}