]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - arch/arm/mach-keystone/clock.c
ARM: keystone2: Use common definition for clk_get_rate
[karo-tx-uboot.git] / arch / arm / mach-keystone / clock.c
index 378ed101592aa4c91c7e53f802459f25fe61956d..fc3eadb3f27937a92b9e59d54bf0383227fc958e 100644 (file)
@@ -264,3 +264,142 @@ int get_max_dev_speed(void)
 
        return get_max_speed(devspeed, DEV_SUPPORTED_SPEEDS);
 }
+
+/**
+ * pll_freq_get - get pll frequency
+ * @pll:       pll identifier
+ */
+static unsigned long pll_freq_get(int pll)
+{
+       unsigned long mult = 1, prediv = 1, output_div = 2;
+       unsigned long ret;
+       u32 tmp, reg;
+
+       if (pll == MAIN_PLL) {
+               ret = external_clk[sys_clk];
+               if (pllctl_reg_read(pll, ctl) & PLLCTL_PLLEN_MASK) {
+                       /* PLL mode */
+                       tmp = __raw_readl(KS2_MAINPLLCTL0);
+                       prediv = (tmp & CFG_PLLCTL0_PLLD_MASK) + 1;
+                       mult = ((tmp & CFG_PLLCTL0_PLLM_HI_MASK) >>
+                               CFG_PLLCTL0_PLLM_SHIFT |
+                               (pllctl_reg_read(pll, mult) &
+                                PLLM_MULT_LO_MASK)) + 1;
+                       output_div = ((pllctl_reg_read(pll, secctl) &
+                                      SECCTL_OP_DIV_MASK) >>
+                                      SECCTL_OP_DIV_SHIFT) + 1;
+
+                       ret = ret / prediv / output_div * mult;
+               }
+       } else {
+               switch (pll) {
+               case PASS_PLL:
+                       ret = external_clk[pa_clk];
+                       reg = KS2_PASSPLLCTL0;
+                       break;
+               case TETRIS_PLL:
+                       ret = external_clk[tetris_clk];
+                       reg = KS2_ARMPLLCTL0;
+                       break;
+               case DDR3A_PLL:
+                       ret = external_clk[ddr3a_clk];
+                       reg = KS2_DDR3APLLCTL0;
+                       break;
+               case DDR3B_PLL:
+                       ret = external_clk[ddr3b_clk];
+                       reg = KS2_DDR3BPLLCTL0;
+                       break;
+               default:
+                       return 0;
+               }
+
+               tmp = __raw_readl(reg);
+
+               if (!(tmp & CFG_PLLCTL0_BYPASS_MASK)) {
+                       /* Bypass disabled */
+                       prediv = (tmp & CFG_PLLCTL0_PLLD_MASK) + 1;
+                       mult = ((tmp & CFG_PLLCTL0_PLLM_MASK) >>
+                               CFG_PLLCTL0_PLLM_SHIFT) + 1;
+                       output_div = ((tmp & CFG_PLLCTL0_CLKOD_MASK) >>
+                                     CFG_PLLCTL0_CLKOD_SHIFT) + 1;
+                       ret = ((ret / prediv) * mult) / output_div;
+               }
+       }
+
+       return ret;
+}
+
+unsigned long clk_get_rate(unsigned int clk)
+{
+       unsigned long freq = 0;
+
+       switch (clk) {
+       case core_pll_clk:
+               freq = pll_freq_get(CORE_PLL);
+               break;
+       case pass_pll_clk:
+               freq = pll_freq_get(PASS_PLL);
+               break;
+       case tetris_pll_clk:
+               if (!cpu_is_k2e())
+                       freq = pll_freq_get(TETRIS_PLL);
+               break;
+       case ddr3a_pll_clk:
+               freq = pll_freq_get(DDR3A_PLL);
+               break;
+       case ddr3b_pll_clk:
+               if (cpu_is_k2hk())
+                       freq = pll_freq_get(DDR3B_PLL);
+               break;
+       case sys_clk0_1_clk:
+       case sys_clk0_clk:
+               freq = pll_freq_get(CORE_PLL) / pll0div_read(1);
+               break;
+       case sys_clk1_clk:
+       return pll_freq_get(CORE_PLL) / pll0div_read(2);
+               break;
+       case sys_clk2_clk:
+               freq = pll_freq_get(CORE_PLL) / pll0div_read(3);
+               break;
+       case sys_clk3_clk:
+               freq = pll_freq_get(CORE_PLL) / pll0div_read(4);
+               break;
+       case sys_clk0_2_clk:
+               freq = clk_get_rate(sys_clk0_clk) / 2;
+               break;
+       case sys_clk0_3_clk:
+               freq = clk_get_rate(sys_clk0_clk) / 3;
+               break;
+       case sys_clk0_4_clk:
+               freq = clk_get_rate(sys_clk0_clk) / 4;
+               break;
+       case sys_clk0_6_clk:
+               freq = clk_get_rate(sys_clk0_clk) / 6;
+               break;
+       case sys_clk0_8_clk:
+               freq = clk_get_rate(sys_clk0_clk) / 8;
+               break;
+       case sys_clk0_12_clk:
+               freq = clk_get_rate(sys_clk0_clk) / 12;
+               break;
+       case sys_clk0_24_clk:
+               freq = clk_get_rate(sys_clk0_clk) / 24;
+               break;
+       case sys_clk1_3_clk:
+               freq = clk_get_rate(sys_clk1_clk) / 3;
+               break;
+       case sys_clk1_4_clk:
+               freq = clk_get_rate(sys_clk1_clk) / 4;
+               break;
+       case sys_clk1_6_clk:
+               freq = clk_get_rate(sys_clk1_clk) / 6;
+               break;
+       case sys_clk1_12_clk:
+               freq = clk_get_rate(sys_clk1_clk) / 12;
+               break;
+       default:
+               break;
+       }
+
+       return freq;
+}