1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2016 Marek Vasut <marex@denx.de>
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <asm/io.h>
9*4882a593Smuzhiyun #include <asm/addrspace.h>
10*4882a593Smuzhiyun #include <asm/types.h>
11*4882a593Smuzhiyun #include <mach/ar71xx_regs.h>
12*4882a593Smuzhiyun #include <mach/ath79.h>
13*4882a593Smuzhiyun #include <wait_bit.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun /*
18*4882a593Smuzhiyun * The math for calculating PLL:
19*4882a593Smuzhiyun * NFRAC * 2^8
20*4882a593Smuzhiyun * NINT + -------------
21*4882a593Smuzhiyun * XTAL [MHz] 2^(18 - 1)
22*4882a593Smuzhiyun * PLL [MHz] = ------------ * ----------------------
23*4882a593Smuzhiyun * REFDIV 2^OUTDIV
24*4882a593Smuzhiyun *
25*4882a593Smuzhiyun * Unfortunatelly, there is no way to reliably compute the variables.
26*4882a593Smuzhiyun * The vendor U-Boot port contains macros for various combinations of
27*4882a593Smuzhiyun * CPU PLL / DDR PLL / AHB bus speed and there is no obvious pattern
28*4882a593Smuzhiyun * in those numbers.
29*4882a593Smuzhiyun */
30*4882a593Smuzhiyun struct ar934x_pll_config {
31*4882a593Smuzhiyun u8 range;
32*4882a593Smuzhiyun u8 refdiv;
33*4882a593Smuzhiyun u8 outdiv;
34*4882a593Smuzhiyun /* Index 0 is for XTAL=25MHz , Index 1 is for XTAL=40MHz */
35*4882a593Smuzhiyun u8 nint[2];
36*4882a593Smuzhiyun };
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun struct ar934x_clock_config {
39*4882a593Smuzhiyun u16 cpu_freq;
40*4882a593Smuzhiyun u16 ddr_freq;
41*4882a593Smuzhiyun u16 ahb_freq;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun struct ar934x_pll_config cpu_pll;
44*4882a593Smuzhiyun struct ar934x_pll_config ddr_pll;
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun static const struct ar934x_clock_config ar934x_clock_config[] = {
48*4882a593Smuzhiyun { 300, 300, 150, { 1, 1, 1, { 24, 15 } }, { 1, 1, 1, { 24, 15 } } },
49*4882a593Smuzhiyun { 400, 200, 200, { 1, 1, 1, { 32, 20 } }, { 1, 1, 2, { 32, 20 } } },
50*4882a593Smuzhiyun { 400, 400, 200, { 0, 1, 1, { 32, 20 } }, { 0, 1, 1, { 32, 20 } } },
51*4882a593Smuzhiyun { 500, 400, 200, { 1, 1, 0, { 20, 12 } }, { 0, 1, 1, { 32, 20 } } },
52*4882a593Smuzhiyun { 533, 400, 200, { 1, 1, 0, { 21, 13 } }, { 0, 1, 1, { 32, 20 } } },
53*4882a593Smuzhiyun { 533, 500, 250, { 1, 1, 0, { 21, 13 } }, { 0, 1, 0, { 20, 12 } } },
54*4882a593Smuzhiyun { 560, 480, 240, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 19, 12 } } },
55*4882a593Smuzhiyun { 566, 400, 200, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 16, 10 } } },
56*4882a593Smuzhiyun { 566, 450, 225, { 1, 1, 0, { 22, 14 } }, { 0, 1, 1, { 36, 22 } } },
57*4882a593Smuzhiyun { 566, 475, 237, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 19, 11 } } },
58*4882a593Smuzhiyun { 566, 500, 250, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 20, 12 } } },
59*4882a593Smuzhiyun { 566, 525, 262, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 21, 13 } } },
60*4882a593Smuzhiyun { 566, 550, 275, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 22, 13 } } },
61*4882a593Smuzhiyun { 600, 266, 133, { 0, 1, 0, { 24, 15 } }, { 1, 1, 1, { 21, 16 } } },
62*4882a593Smuzhiyun { 600, 266, 200, { 0, 1, 0, { 24, 15 } }, { 1, 1, 1, { 21, 16 } } },
63*4882a593Smuzhiyun { 600, 300, 150, { 0, 1, 0, { 24, 15 } }, { 0, 1, 1, { 24, 15 } } },
64*4882a593Smuzhiyun { 600, 332, 166, { 0, 1, 0, { 24, 15 } }, { 1, 1, 1, { 26, 16 } } },
65*4882a593Smuzhiyun { 600, 332, 200, { 0, 1, 0, { 24, 15 } }, { 1, 1, 1, { 26, 16 } } },
66*4882a593Smuzhiyun { 600, 400, 200, { 0, 1, 0, { 24, 15 } }, { 0, 1, 1, { 32, 20 } } },
67*4882a593Smuzhiyun { 600, 450, 200, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 18, 20 } } },
68*4882a593Smuzhiyun { 600, 500, 250, { 0, 1, 0, { 24, 15 } }, { 1, 1, 0, { 20, 12 } } },
69*4882a593Smuzhiyun { 600, 525, 262, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 21, 20 } } },
70*4882a593Smuzhiyun { 600, 550, 275, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 22, 20 } } },
71*4882a593Smuzhiyun { 600, 575, 287, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 23, 14 } } },
72*4882a593Smuzhiyun { 600, 600, 300, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 24, 20 } } },
73*4882a593Smuzhiyun { 600, 650, 325, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 26, 20 } } },
74*4882a593Smuzhiyun { 650, 600, 300, { 0, 1, 0, { 26, 15 } }, { 0, 1, 0, { 24, 20 } } },
75*4882a593Smuzhiyun { 700, 400, 200, { 3, 1, 0, { 28, 17 } }, { 0, 1, 1, { 32, 20 } } },
76*4882a593Smuzhiyun };
77*4882a593Smuzhiyun
ar934x_srif_pll_cfg(void __iomem * pll_reg_base,const u32 srif_val)78*4882a593Smuzhiyun static void ar934x_srif_pll_cfg(void __iomem *pll_reg_base, const u32 srif_val)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun u32 reg;
81*4882a593Smuzhiyun do {
82*4882a593Smuzhiyun writel(0x10810f00, pll_reg_base + 0x4);
83*4882a593Smuzhiyun writel(srif_val, pll_reg_base + 0x0);
84*4882a593Smuzhiyun writel(0xd0810f00, pll_reg_base + 0x4);
85*4882a593Smuzhiyun writel(0x03000000, pll_reg_base + 0x8);
86*4882a593Smuzhiyun writel(0xd0800f00, pll_reg_base + 0x4);
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun clrbits_be32(pll_reg_base + 0x8, BIT(30));
89*4882a593Smuzhiyun udelay(5);
90*4882a593Smuzhiyun setbits_be32(pll_reg_base + 0x8, BIT(30));
91*4882a593Smuzhiyun udelay(5);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun wait_for_bit_le32(pll_reg_base + 0xc, BIT(3), 1, 10, 0);
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun clrbits_be32(pll_reg_base + 0x8, BIT(30));
96*4882a593Smuzhiyun udelay(5);
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun /* Check if CPU SRIF PLL locked. */
99*4882a593Smuzhiyun reg = readl(pll_reg_base + 0x8);
100*4882a593Smuzhiyun reg = (reg & 0x7ffff8) >> 3;
101*4882a593Smuzhiyun } while (reg >= 0x40000);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
ar934x_pll_init(const u16 cpu_mhz,const u16 ddr_mhz,const u16 ahb_mhz)104*4882a593Smuzhiyun void ar934x_pll_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun void __iomem *srif_regs = map_physmem(AR934X_SRIF_BASE,
107*4882a593Smuzhiyun AR934X_SRIF_SIZE, MAP_NOCACHE);
108*4882a593Smuzhiyun void __iomem *pll_regs = map_physmem(AR71XX_PLL_BASE,
109*4882a593Smuzhiyun AR71XX_PLL_SIZE, MAP_NOCACHE);
110*4882a593Smuzhiyun const struct ar934x_pll_config *pll_cfg;
111*4882a593Smuzhiyun int i, pll_nint, pll_refdiv, xtal_40 = 0;
112*4882a593Smuzhiyun u32 reg, cpu_pll, cpu_srif, ddr_pll, ddr_srif;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun /* Configure SRIF PLL with initial values. */
115*4882a593Smuzhiyun writel(0x13210f00, srif_regs + AR934X_SRIF_CPU_DPLL2_REG);
116*4882a593Smuzhiyun writel(0x03000000, srif_regs + AR934X_SRIF_CPU_DPLL3_REG);
117*4882a593Smuzhiyun writel(0x13210f00, srif_regs + AR934X_SRIF_DDR_DPLL2_REG);
118*4882a593Smuzhiyun writel(0x03000000, srif_regs + AR934X_SRIF_DDR_DPLL3_REG);
119*4882a593Smuzhiyun writel(0x03000000, srif_regs + 0x188); /* Undocumented reg :-) */
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun /* Test for 40MHz XTAL */
122*4882a593Smuzhiyun reg = ath79_get_bootstrap();
123*4882a593Smuzhiyun if (reg & AR934X_BOOTSTRAP_REF_CLK_40) {
124*4882a593Smuzhiyun xtal_40 = 1;
125*4882a593Smuzhiyun cpu_srif = 0x41c00000;
126*4882a593Smuzhiyun ddr_srif = 0x41680000;
127*4882a593Smuzhiyun } else {
128*4882a593Smuzhiyun xtal_40 = 0;
129*4882a593Smuzhiyun cpu_srif = 0x29c00000;
130*4882a593Smuzhiyun ddr_srif = 0x29680000;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun /* Locate CPU/DDR PLL configuration */
134*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(ar934x_clock_config); i++) {
135*4882a593Smuzhiyun if (cpu_mhz != ar934x_clock_config[i].cpu_freq)
136*4882a593Smuzhiyun continue;
137*4882a593Smuzhiyun if (ddr_mhz != ar934x_clock_config[i].ddr_freq)
138*4882a593Smuzhiyun continue;
139*4882a593Smuzhiyun if (ahb_mhz != ar934x_clock_config[i].ahb_freq)
140*4882a593Smuzhiyun continue;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun /* Entry found */
143*4882a593Smuzhiyun pll_cfg = &ar934x_clock_config[i].cpu_pll;
144*4882a593Smuzhiyun pll_nint = pll_cfg->nint[xtal_40];
145*4882a593Smuzhiyun pll_refdiv = pll_cfg->refdiv;
146*4882a593Smuzhiyun cpu_pll =
147*4882a593Smuzhiyun (pll_nint << AR934X_PLL_CPU_CONFIG_NINT_SHIFT) |
148*4882a593Smuzhiyun (pll_refdiv << AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) |
149*4882a593Smuzhiyun (pll_cfg->range << AR934X_PLL_CPU_CONFIG_RANGE_SHIFT) |
150*4882a593Smuzhiyun (pll_cfg->outdiv << AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT);
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun pll_cfg = &ar934x_clock_config[i].ddr_pll;
153*4882a593Smuzhiyun pll_nint = pll_cfg->nint[xtal_40];
154*4882a593Smuzhiyun pll_refdiv = pll_cfg->refdiv;
155*4882a593Smuzhiyun ddr_pll =
156*4882a593Smuzhiyun (pll_nint << AR934X_PLL_DDR_CONFIG_NINT_SHIFT) |
157*4882a593Smuzhiyun (pll_refdiv << AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) |
158*4882a593Smuzhiyun (pll_cfg->range << AR934X_PLL_DDR_CONFIG_RANGE_SHIFT) |
159*4882a593Smuzhiyun (pll_cfg->outdiv << AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT);
160*4882a593Smuzhiyun break;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun /* PLL configuration not found, hang. */
164*4882a593Smuzhiyun if (i == ARRAY_SIZE(ar934x_clock_config))
165*4882a593Smuzhiyun hang();
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun /* Set PLL Bypass */
168*4882a593Smuzhiyun setbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG,
169*4882a593Smuzhiyun AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS);
170*4882a593Smuzhiyun setbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG,
171*4882a593Smuzhiyun AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS);
172*4882a593Smuzhiyun setbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG,
173*4882a593Smuzhiyun AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS);
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun /* Configure CPU PLL */
176*4882a593Smuzhiyun writel(cpu_pll | AR934X_PLL_CPU_CONFIG_PLLPWD,
177*4882a593Smuzhiyun pll_regs + AR934X_PLL_CPU_CONFIG_REG);
178*4882a593Smuzhiyun /* Configure DDR PLL */
179*4882a593Smuzhiyun writel(ddr_pll | AR934X_PLL_DDR_CONFIG_PLLPWD,
180*4882a593Smuzhiyun pll_regs + AR934X_PLL_DDR_CONFIG_REG);
181*4882a593Smuzhiyun /* Configure PLL routing */
182*4882a593Smuzhiyun writel(AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS |
183*4882a593Smuzhiyun AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS |
184*4882a593Smuzhiyun AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS |
185*4882a593Smuzhiyun (0 << AR934X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) |
186*4882a593Smuzhiyun (0 << AR934X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) |
187*4882a593Smuzhiyun (1 << AR934X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) |
188*4882a593Smuzhiyun AR934X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL |
189*4882a593Smuzhiyun AR934X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL |
190*4882a593Smuzhiyun AR934X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL,
191*4882a593Smuzhiyun pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun /* Configure SRIF PLLs, which is completely undocumented :-) */
194*4882a593Smuzhiyun ar934x_srif_pll_cfg(srif_regs + AR934X_SRIF_CPU_DPLL1_REG, cpu_srif);
195*4882a593Smuzhiyun ar934x_srif_pll_cfg(srif_regs + AR934X_SRIF_DDR_DPLL1_REG, ddr_srif);
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun /* Unset PLL Bypass */
198*4882a593Smuzhiyun clrbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG,
199*4882a593Smuzhiyun AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS);
200*4882a593Smuzhiyun clrbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG,
201*4882a593Smuzhiyun AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS);
202*4882a593Smuzhiyun clrbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG,
203*4882a593Smuzhiyun AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS);
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun /* Enable PLL dithering */
206*4882a593Smuzhiyun writel((1 << AR934X_PLL_DDR_DIT_FRAC_STEP_SHIFT) |
207*4882a593Smuzhiyun (0xf << AR934X_PLL_DDR_DIT_UPD_CNT_SHIFT),
208*4882a593Smuzhiyun pll_regs + AR934X_PLL_DDR_DIT_FRAC_REG);
209*4882a593Smuzhiyun writel(48 << AR934X_PLL_CPU_DIT_UPD_CNT_SHIFT,
210*4882a593Smuzhiyun pll_regs + AR934X_PLL_CPU_DIT_FRAC_REG);
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
ar934x_get_xtal(void)213*4882a593Smuzhiyun static u32 ar934x_get_xtal(void)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun u32 val;
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun val = ath79_get_bootstrap();
218*4882a593Smuzhiyun if (val & AR934X_BOOTSTRAP_REF_CLK_40)
219*4882a593Smuzhiyun return 40000000;
220*4882a593Smuzhiyun else
221*4882a593Smuzhiyun return 25000000;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun
get_serial_clock(void)224*4882a593Smuzhiyun int get_serial_clock(void)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun return ar934x_get_xtal();
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
ar934x_cpupll_to_hz(const u32 regval)229*4882a593Smuzhiyun static u32 ar934x_cpupll_to_hz(const u32 regval)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun const u32 outdiv = (regval >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
232*4882a593Smuzhiyun AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
233*4882a593Smuzhiyun const u32 refdiv = (regval >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
234*4882a593Smuzhiyun AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
235*4882a593Smuzhiyun const u32 nint = (regval >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
236*4882a593Smuzhiyun AR934X_PLL_CPU_CONFIG_NINT_MASK;
237*4882a593Smuzhiyun const u32 nfrac = (regval >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
238*4882a593Smuzhiyun AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
239*4882a593Smuzhiyun const u32 xtal = ar934x_get_xtal();
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun return (xtal * (nint + (nfrac >> 9))) / (refdiv * (1 << outdiv));
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
ar934x_ddrpll_to_hz(const u32 regval)244*4882a593Smuzhiyun static u32 ar934x_ddrpll_to_hz(const u32 regval)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun const u32 outdiv = (regval >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
247*4882a593Smuzhiyun AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
248*4882a593Smuzhiyun const u32 refdiv = (regval >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
249*4882a593Smuzhiyun AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
250*4882a593Smuzhiyun const u32 nint = (regval >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
251*4882a593Smuzhiyun AR934X_PLL_DDR_CONFIG_NINT_MASK;
252*4882a593Smuzhiyun const u32 nfrac = (regval >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
253*4882a593Smuzhiyun AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
254*4882a593Smuzhiyun const u32 xtal = ar934x_get_xtal();
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun return (xtal * (nint + (nfrac >> 9))) / (refdiv * (1 << outdiv));
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
ar934x_update_clock(void)259*4882a593Smuzhiyun static void ar934x_update_clock(void)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun void __iomem *regs;
262*4882a593Smuzhiyun u32 ctrl, cpu, cpupll, ddr, ddrpll;
263*4882a593Smuzhiyun u32 cpudiv, ddrdiv, busdiv;
264*4882a593Smuzhiyun u32 cpuclk, ddrclk, busclk;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
267*4882a593Smuzhiyun MAP_NOCACHE);
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun cpu = readl(regs + AR934X_PLL_CPU_CONFIG_REG);
270*4882a593Smuzhiyun ddr = readl(regs + AR934X_PLL_DDR_CONFIG_REG);
271*4882a593Smuzhiyun ctrl = readl(regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun cpupll = ar934x_cpupll_to_hz(cpu);
274*4882a593Smuzhiyun ddrpll = ar934x_ddrpll_to_hz(ddr);
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun if (ctrl & AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS)
277*4882a593Smuzhiyun cpuclk = ar934x_get_xtal();
278*4882a593Smuzhiyun else if (ctrl & AR934X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL)
279*4882a593Smuzhiyun cpuclk = cpupll;
280*4882a593Smuzhiyun else
281*4882a593Smuzhiyun cpuclk = ddrpll;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun if (ctrl & AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS)
284*4882a593Smuzhiyun ddrclk = ar934x_get_xtal();
285*4882a593Smuzhiyun else if (ctrl & AR934X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL)
286*4882a593Smuzhiyun ddrclk = ddrpll;
287*4882a593Smuzhiyun else
288*4882a593Smuzhiyun ddrclk = cpupll;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun if (ctrl & AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS)
291*4882a593Smuzhiyun busclk = ar934x_get_xtal();
292*4882a593Smuzhiyun else if (ctrl & AR934X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL)
293*4882a593Smuzhiyun busclk = ddrpll;
294*4882a593Smuzhiyun else
295*4882a593Smuzhiyun busclk = cpupll;
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun cpudiv = (ctrl >> AR934X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
298*4882a593Smuzhiyun AR934X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
299*4882a593Smuzhiyun ddrdiv = (ctrl >> AR934X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) &
300*4882a593Smuzhiyun AR934X_PLL_CLK_CTRL_DDR_POST_DIV_MASK;
301*4882a593Smuzhiyun busdiv = (ctrl >> AR934X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) &
302*4882a593Smuzhiyun AR934X_PLL_CLK_CTRL_AHB_POST_DIV_MASK;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun gd->cpu_clk = cpuclk / (cpudiv + 1);
305*4882a593Smuzhiyun gd->mem_clk = ddrclk / (ddrdiv + 1);
306*4882a593Smuzhiyun gd->bus_clk = busclk / (busdiv + 1);
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
get_bus_freq(ulong dummy)309*4882a593Smuzhiyun ulong get_bus_freq(ulong dummy)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun ar934x_update_clock();
312*4882a593Smuzhiyun return gd->bus_clk;
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun
get_ddr_freq(ulong dummy)315*4882a593Smuzhiyun ulong get_ddr_freq(ulong dummy)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun ar934x_update_clock();
318*4882a593Smuzhiyun return gd->mem_clk;
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun
do_ar934x_showclk(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])321*4882a593Smuzhiyun int do_ar934x_showclk(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun ar934x_update_clock();
324*4882a593Smuzhiyun printf("CPU: %8ld MHz\n", gd->cpu_clk / 1000000);
325*4882a593Smuzhiyun printf("Memory: %8ld MHz\n", gd->mem_clk / 1000000);
326*4882a593Smuzhiyun printf("AHB: %8ld MHz\n", gd->bus_clk / 1000000);
327*4882a593Smuzhiyun return 0;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun U_BOOT_CMD(
331*4882a593Smuzhiyun clocks, CONFIG_SYS_MAXARGS, 1, do_ar934x_showclk,
332*4882a593Smuzhiyun "display clocks",
333*4882a593Smuzhiyun ""
334*4882a593Smuzhiyun );
335