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