MIPS: Alchemy: Fix cpu clock calculation
[GitHub/exynos8895/android_kernel_samsung_universal8895.git] / arch / mips / alchemy / common / clock.c
index 203e4403c366869ed1acbd99cbf4e82c92b83942..4b5ec49139c227f062cffa71fa6155c0c124f97b 100644 (file)
@@ -127,12 +127,20 @@ static unsigned long alchemy_clk_cpu_recalc(struct clk_hw *hw,
                t = 396000000;
        else {
                t = alchemy_rdsys(AU1000_SYS_CPUPLL) & 0x7f;
+               if (alchemy_get_cputype() < ALCHEMY_CPU_AU1300)
+                       t &= 0x3f;
                t *= parent_rate;
        }
 
        return t;
 }
 
+void __init alchemy_set_lpj(void)
+{
+       preset_lpj = alchemy_clk_cpu_recalc(NULL, ALCHEMY_ROOTCLK_RATE);
+       preset_lpj /= 2 * HZ;
+}
+
 static struct clk_ops alchemy_clkops_cpu = {
        .recalc_rate    = alchemy_clk_cpu_recalc,
 };
@@ -315,17 +323,26 @@ static struct clk __init *alchemy_clk_setup_mem(const char *pn, int ct)
 
 /* lrclk: external synchronous static bus clock ***********************/
 
-static struct clk __init *alchemy_clk_setup_lrclk(const char *pn)
+static struct clk __init *alchemy_clk_setup_lrclk(const char *pn, int t)
 {
-       /* MEM_STCFG0[15:13] = divisor.
+       /* Au1000, Au1500: MEM_STCFG0[11]: If bit is set, lrclk=pclk/5,
+        * otherwise lrclk=pclk/4.
+        * All other variants: MEM_STCFG0[15:13] = divisor.
         * L/RCLK = periph_clk / (divisor + 1)
         * On Au1000, Au1500, Au1100 it's called LCLK,
         * on later models it's called RCLK, but it's the same thing.
         */
        struct clk *c;
-       unsigned long v = alchemy_rdsmem(AU1000_MEM_STCFG0) >> 13;
+       unsigned long v = alchemy_rdsmem(AU1000_MEM_STCFG0);
 
-       v = (v & 7) + 1;
+       switch (t) {
+       case ALCHEMY_CPU_AU1000:
+       case ALCHEMY_CPU_AU1500:
+               v = 4 + ((v >> 11) & 1);
+               break;
+       default:        /* all other models */
+               v = ((v >> 13) & 7) + 1;
+       }
        c = clk_register_fixed_factor(NULL, ALCHEMY_LR_CLK,
                                      pn, 0, 1, v);
        if (!IS_ERR(c))
@@ -374,7 +391,7 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate,
 
 static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
                                        unsigned long *best_parent_rate,
-                                       struct clk **best_parent_clk,
+                                       struct clk_hw **best_parent_clk,
                                        int scale, int maxdiv)
 {
        struct clk *pc, *bpc, *free;
@@ -453,7 +470,7 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
        }
 
        *best_parent_rate = bpr;
-       *best_parent_clk = bpc;
+       *best_parent_clk = __clk_get_hw(bpc);
        return br;
 }
 
@@ -547,7 +564,7 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
 
 static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
                                        unsigned long *best_parent_rate,
-                                       struct clk **best_parent_clk)
+                                       struct clk_hw **best_parent_clk)
 {
        return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
                                     best_parent_clk, 2, 512);
@@ -679,7 +696,7 @@ static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
 
 static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
                                        unsigned long *best_parent_rate,
-                                       struct clk **best_parent_clk)
+                                       struct clk_hw **best_parent_clk)
 {
        struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
        int scale, maxdiv;
@@ -898,7 +915,7 @@ static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
 
 static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
                                        unsigned long *best_parent_rate,
-                                       struct clk **best_parent_clk)
+                                       struct clk_hw **best_parent_clk)
 {
        struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
        int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */
@@ -1060,7 +1077,7 @@ static int __init alchemy_clk_init(void)
        ERRCK(c)
 
        /* L/RCLK: external static bus clock for synchronous mode */
-       c = alchemy_clk_setup_lrclk(ALCHEMY_PERIPH_CLK);
+       c = alchemy_clk_setup_lrclk(ALCHEMY_PERIPH_CLK, ctype);
        ERRCK(c)
 
        /* Frequency dividers 0-5 */