]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/mach-keystone/clock-k2l.c
ARM: keystone2: Fix dev and arm speed detection
[karo-tx-uboot.git] / arch / arm / mach-keystone / clock-k2l.c
1 /*
2  * Keystone2: get clk rate for K2L
3  *
4  * (C) Copyright 2012-2014
5  *     Texas Instruments Incorporated, <www.ti.com>
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <common.h>
11 #include <asm/arch/clock.h>
12 #include <asm/arch/clock_defs.h>
13
14 const struct keystone_pll_regs keystone_pll_regs[] = {
15         [CORE_PLL] = {KS2_MAINPLLCTL0, KS2_MAINPLLCTL1},
16         [PASS_PLL] = {KS2_PASSPLLCTL0, KS2_PASSPLLCTL1},
17         [TETRIS_PLL] = {KS2_ARMPLLCTL0,  KS2_ARMPLLCTL1},
18         [DDR3_PLL] = {KS2_DDR3APLLCTL0, KS2_DDR3APLLCTL1},
19 };
20
21 /**
22  * pll_freq_get - get pll frequency
23  * Fout = Fref * NF(mult) / NR(prediv) / OD
24  * @pll:        pll identifier
25  */
26 static unsigned long pll_freq_get(int pll)
27 {
28         unsigned long mult = 1, prediv = 1, output_div = 2;
29         unsigned long ret;
30         u32 tmp, reg;
31
32         if (pll == CORE_PLL) {
33                 ret = external_clk[sys_clk];
34                 if (pllctl_reg_read(pll, ctl) & PLLCTL_PLLEN) {
35                         /* PLL mode */
36                         tmp = __raw_readl(KS2_MAINPLLCTL0);
37                         prediv = (tmp & PLL_DIV_MASK) + 1;
38                         mult = (((tmp & PLLM_MULT_HI_SMASK) >> 6) |
39                                 (pllctl_reg_read(pll, mult) &
40                                 PLLM_MULT_LO_MASK)) + 1;
41                         output_div = ((pllctl_reg_read(pll, secctl) >>
42                                         PLL_CLKOD_SHIFT) & PLL_CLKOD_MASK) + 1;
43
44                         ret = ret / prediv / output_div * mult;
45                 }
46         } else {
47                 switch (pll) {
48                 case PASS_PLL:
49                         ret = external_clk[pa_clk];
50                         reg = KS2_PASSPLLCTL0;
51                         break;
52                 case TETRIS_PLL:
53                         ret = external_clk[tetris_clk];
54                         reg = KS2_ARMPLLCTL0;
55                         break;
56                 case DDR3_PLL:
57                         ret = external_clk[ddr3_clk];
58                         reg = KS2_DDR3APLLCTL0;
59                         break;
60                 default:
61                         return 0;
62                 }
63
64                 tmp = __raw_readl(reg);
65                 if (!(tmp & PLLCTL_BYPASS)) {
66                         /* Bypass disabled */
67                         prediv = (tmp & PLL_DIV_MASK) + 1;
68                         mult = ((tmp >> PLL_MULT_SHIFT) & PLL_MULT_MASK) + 1;
69                         output_div = ((tmp >> PLL_CLKOD_SHIFT) &
70                                       PLL_CLKOD_MASK) + 1;
71                         ret = ((ret / prediv) * mult) / output_div;
72                 }
73         }
74
75         return ret;
76 }
77
78 unsigned long clk_get_rate(unsigned int clk)
79 {
80         switch (clk) {
81         case core_pll_clk:      return pll_freq_get(CORE_PLL);
82         case pass_pll_clk:      return pll_freq_get(PASS_PLL);
83         case tetris_pll_clk:    return pll_freq_get(TETRIS_PLL);
84         case ddr3_pll_clk:      return pll_freq_get(DDR3_PLL);
85         case sys_clk0_1_clk:
86         case sys_clk0_clk:      return pll_freq_get(CORE_PLL) / pll0div_read(1);
87         case sys_clk1_clk:      return pll_freq_get(CORE_PLL) / pll0div_read(2);
88         case sys_clk2_clk:      return pll_freq_get(CORE_PLL) / pll0div_read(3);
89         case sys_clk3_clk:      return pll_freq_get(CORE_PLL) / pll0div_read(4);
90         case sys_clk0_2_clk:    return clk_get_rate(sys_clk0_clk) / 2;
91         case sys_clk0_3_clk:    return clk_get_rate(sys_clk0_clk) / 3;
92         case sys_clk0_4_clk:    return clk_get_rate(sys_clk0_clk) / 4;
93         case sys_clk0_6_clk:    return clk_get_rate(sys_clk0_clk) / 6;
94         case sys_clk0_8_clk:    return clk_get_rate(sys_clk0_clk) / 8;
95         case sys_clk0_12_clk:   return clk_get_rate(sys_clk0_clk) / 12;
96         case sys_clk0_24_clk:   return clk_get_rate(sys_clk0_clk) / 24;
97         case sys_clk1_3_clk:    return clk_get_rate(sys_clk1_clk) / 3;
98         case sys_clk1_4_clk:    return clk_get_rate(sys_clk1_clk) / 4;
99         case sys_clk1_6_clk:    return clk_get_rate(sys_clk1_clk) / 6;
100         case sys_clk1_12_clk:   return clk_get_rate(sys_clk1_clk) / 12;
101         default:
102                 break;
103         }
104
105         return 0;
106 }