blob: e5ada5b6d49c90d3b8d4c69ecdaf13f09afa9885 [file] [log] [blame]
Ryan Chence5ecc12020-12-14 13:54:23 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) ASPEED Technology Inc.
4 */
5
6#include <common.h>
7#include <clk-uclass.h>
8#include <dm.h>
9#include <asm/io.h>
10#include <dm/lists.h>
11#include <linux/delay.h>
12#include <asm/arch/scu_ast2600.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060013#include <asm/global_data.h>
Ryan Chence5ecc12020-12-14 13:54:23 +080014#include <dt-bindings/clock/ast2600-clock.h>
15#include <dt-bindings/reset/ast2600-reset.h>
16
17DECLARE_GLOBAL_DATA_PTR;
18
19#define CLKIN_25M 25000000UL
20
21/* MAC Clock Delay settings */
Dylan Hungd9c87e32021-12-09 10:12:28 +080022#define MAC12_DEF_DELAY_1G 0x0028a410
23#define MAC12_DEF_DELAY_100M 0x00410410
24#define MAC12_DEF_DELAY_10M 0x00410410
25#define MAC34_DEF_DELAY_1G 0x00104208
26#define MAC34_DEF_DELAY_100M 0x00104208
Ryan Chence5ecc12020-12-14 13:54:23 +080027#define MAC34_DEF_DELAY_10M 0x00104208
28
29/*
30 * 3-bit encode of CPU freqeucy
31 * Some code is duplicated
32 */
33enum ast2600_cpu_freq {
34 CPU_FREQ_1200M_1,
35 CPU_FREQ_1600M_1,
36 CPU_FREQ_1200M_2,
37 CPU_FREQ_1600M_2,
38 CPU_FREQ_800M_1,
39 CPU_FREQ_800M_2,
40 CPU_FREQ_800M_3,
41 CPU_FREQ_800M_4,
42};
43
44struct ast2600_clk_priv {
45 struct ast2600_scu *scu;
46};
47
48/*
49 * Clock divider/multiplier configuration struct.
50 * For H-PLL and M-PLL the formula is
51 * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
52 * M - Numerator
53 * N - Denumerator
54 * P - Post Divider
55 * They have the same layout in their control register.
56 *
57 * D-PLL and D2-PLL have extra divider (OD + 1), which is not
58 * yet needed and ignored by clock configurations.
59 */
60union ast2600_pll_reg {
61 uint32_t w;
62 struct {
63 unsigned int m : 13;
64 unsigned int n : 6;
65 unsigned int p : 4;
66 unsigned int off : 1;
67 unsigned int bypass : 1;
68 unsigned int reset : 1;
69 unsigned int reserved : 6;
70 } b;
71};
72
73struct ast2600_pll_cfg {
74 union ast2600_pll_reg reg;
75 unsigned int ext_reg;
76};
77
78struct ast2600_pll_desc {
79 uint32_t in;
80 uint32_t out;
81 struct ast2600_pll_cfg cfg;
82};
83
84static const struct ast2600_pll_desc ast2600_pll_lookup[] = {
85 {
86 .in = CLKIN_25M,
87 .out = 400000000,
88 .cfg.reg.b.m = 95,
89 .cfg.reg.b.n = 2,
90 .cfg.reg.b.p = 1,
91 .cfg.ext_reg = 0x31,
92 },
93 {
94 .in = CLKIN_25M,
95 .out = 200000000,
96 .cfg.reg.b.m = 127,
97 .cfg.reg.b.n = 0,
98 .cfg.reg.b.p = 15,
99 .cfg.ext_reg = 0x3f,
100 },
101 {
102 .in = CLKIN_25M,
103 .out = 334000000,
104 .cfg.reg.b.m = 667,
105 .cfg.reg.b.n = 4,
106 .cfg.reg.b.p = 9,
107 .cfg.ext_reg = 0x14d,
108 },
109 {
110 .in = CLKIN_25M,
111 .out = 1000000000,
112 .cfg.reg.b.m = 119,
113 .cfg.reg.b.n = 2,
114 .cfg.reg.b.p = 0,
115 .cfg.ext_reg = 0x3d,
116 },
117 {
118 .in = CLKIN_25M,
119 .out = 50000000,
120 .cfg.reg.b.m = 95,
121 .cfg.reg.b.n = 2,
122 .cfg.reg.b.p = 15,
123 .cfg.ext_reg = 0x31,
124 },
125};
126
127/* divisor tables */
128static uint32_t axi_ahb_div0_table[] = {
129 3, 2, 3, 4,
130};
131
132static uint32_t axi_ahb_div1_table[] = {
133 3, 4, 6, 8,
134};
135
136static uint32_t axi_ahb_default_table[] = {
137 3, 4, 3, 4, 2, 2, 2, 2,
138};
139
140extern uint32_t ast2600_get_pll_rate(struct ast2600_scu *scu, int pll_idx)
141{
142 union ast2600_pll_reg pll_reg;
143 uint32_t hwstrap1;
144 uint32_t cpu_freq;
145 uint32_t mul = 1, div = 1;
146
147 switch (pll_idx) {
148 case ASPEED_CLK_APLL:
149 pll_reg.w = readl(&scu->apll);
150 break;
151 case ASPEED_CLK_DPLL:
152 pll_reg.w = readl(&scu->dpll);
153 break;
154 case ASPEED_CLK_EPLL:
155 pll_reg.w = readl(&scu->epll);
156 break;
157 case ASPEED_CLK_HPLL:
158 pll_reg.w = readl(&scu->hpll);
159 break;
160 case ASPEED_CLK_MPLL:
161 pll_reg.w = readl(&scu->mpll);
162 break;
163 }
164
165 if (!pll_reg.b.bypass) {
166 /* F = 25Mhz * [(M + 2) / (n + 1)] / (p + 1)
167 * HPLL Numerator (M) = fix 0x5F when SCU500[10]=1
168 * Fixed 0xBF when SCU500[10]=0 and SCU500[8]=1
169 * SCU200[12:0] (default 0x8F) when SCU510[10]=0 and SCU510[8]=0
170 * HPLL Denumerator (N) = SCU200[18:13] (default 0x2)
171 * HPLL Divider (P) = SCU200[22:19] (default 0x0)
172 * HPLL Bandwidth Adj (NB) = fix 0x2F when SCU500[10]=1
173 * Fixed 0x5F when SCU500[10]=0 and SCU500[8]=1
174 * SCU204[11:0] (default 0x31) when SCU500[10]=0 and SCU500[8]=0
175 */
176 if (pll_idx == ASPEED_CLK_HPLL) {
177 hwstrap1 = readl(&scu->hwstrap1);
178 cpu_freq = (hwstrap1 & SCU_HWSTRAP1_CPU_FREQ_MASK) >>
179 SCU_HWSTRAP1_CPU_FREQ_SHIFT;
180
181 switch (cpu_freq) {
182 case CPU_FREQ_800M_1:
183 case CPU_FREQ_800M_2:
184 case CPU_FREQ_800M_3:
185 case CPU_FREQ_800M_4:
186 pll_reg.b.m = 0x5f;
187 break;
188 case CPU_FREQ_1600M_1:
189 case CPU_FREQ_1600M_2:
190 pll_reg.b.m = 0xbf;
191 break;
192 default:
193 pll_reg.b.m = 0x8f;
194 break;
195 }
196 }
197
198 mul = (pll_reg.b.m + 1) / (pll_reg.b.n + 1);
199 div = (pll_reg.b.p + 1);
200 }
201
202 return ((CLKIN_25M * mul) / div);
203}
204
205static uint32_t ast2600_get_hclk_rate(struct ast2600_scu *scu)
206{
207 uint32_t rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
208 uint32_t axi_div, ahb_div;
209 uint32_t hwstrap1 = readl(&scu->hwstrap1);
210 uint32_t cpu_freq = (hwstrap1 & SCU_HWSTRAP1_CPU_FREQ_MASK) >>
211 SCU_HWSTRAP1_CPU_FREQ_SHIFT;
212 uint32_t axi_ahb_ratio = (hwstrap1 & SCU_HWSTRAP1_AXI_AHB_CLK_RATIO_MASK) >>
213 SCU_HWSTRAP1_AXI_AHB_CLK_RATIO_SHIFT;
214
215 if (hwstrap1 & SCU_HWSTRAP1_CPU_AXI_CLK_RATIO) {
216 axi_ahb_div1_table[0] = axi_ahb_default_table[cpu_freq] * 2;
217 axi_div = 1;
218 ahb_div = axi_ahb_div1_table[axi_ahb_ratio];
219 } else {
220 axi_ahb_div0_table[0] = axi_ahb_default_table[cpu_freq];
221 axi_div = 2;
222 ahb_div = axi_ahb_div0_table[axi_ahb_ratio];
223 }
224
225 return (rate / axi_div / ahb_div);
226}
227
228static uint32_t ast2600_get_bclk_rate(struct ast2600_scu *scu)
229{
230 uint32_t rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
231 uint32_t clksrc1 = readl(&scu->clksrc1);
232 uint32_t bclk_div = (clksrc1 & SCU_CLKSRC1_BCLK_DIV_MASK) >>
233 SCU_CLKSRC1_BCLK_DIV_SHIFT;
234
235 return (rate / ((bclk_div + 1) * 4));
236}
237
238static uint32_t ast2600_get_pclk1_rate(struct ast2600_scu *scu)
239{
240 uint32_t rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
241 uint32_t clksrc1 = readl(&scu->clksrc1);
242 uint32_t pclk_div = (clksrc1 & SCU_CLKSRC1_PCLK_DIV_MASK) >>
243 SCU_CLKSRC1_PCLK_DIV_SHIFT;
244
245 return (rate / ((pclk_div + 1) * 4));
246}
247
248static uint32_t ast2600_get_pclk2_rate(struct ast2600_scu *scu)
249{
250 uint32_t rate = ast2600_get_hclk_rate(scu);
251 uint32_t clksrc4 = readl(&scu->clksrc4);
252 uint32_t pclk_div = (clksrc4 & SCU_CLKSRC4_PCLK_DIV_MASK) >>
253 SCU_CLKSRC4_PCLK_DIV_SHIFT;
254
255 return (rate / ((pclk_div + 1) * 2));
256}
257
258static uint32_t ast2600_get_uxclk_in_rate(struct ast2600_scu *scu)
259{
260 uint32_t rate = 0;
261 uint32_t clksrc5 = readl(&scu->clksrc5);
262 uint32_t uxclk = (clksrc5 & SCU_CLKSRC5_UXCLK_MASK) >>
263 SCU_CLKSRC5_UXCLK_SHIFT;
264
265 switch (uxclk) {
266 case 0:
267 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL) / 4;
268 break;
269 case 1:
270 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL) / 2;
271 break;
272 case 2:
273 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL);
274 break;
275 case 3:
276 rate = ast2600_get_hclk_rate(scu);
277 break;
278 }
279
280 return rate;
281}
282
283static uint32_t ast2600_get_huxclk_in_rate(struct ast2600_scu *scu)
284{
285 uint32_t rate = 0;
286 uint32_t clksrc5 = readl(&scu->clksrc5);
287 uint32_t huxclk = (clksrc5 & SCU_CLKSRC5_HUXCLK_MASK) >>
288 SCU_CLKSRC5_HUXCLK_SHIFT;
289
290 switch (huxclk) {
291 case 0:
292 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL) / 4;
293 break;
294 case 1:
295 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL) / 2;
296 break;
297 case 2:
298 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL);
299 break;
300 case 3:
301 rate = ast2600_get_hclk_rate(scu);
302 break;
303 }
304
305 return rate;
306}
307
308static uint32_t ast2600_get_uart_uxclk_rate(struct ast2600_scu *scu)
309{
310 uint32_t rate = ast2600_get_uxclk_in_rate(scu);
311 uint32_t uart_clkgen = readl(&scu->uart_clkgen);
312 uint32_t n = (uart_clkgen & SCU_UART_CLKGEN_N_MASK) >>
313 SCU_UART_CLKGEN_N_SHIFT;
314 uint32_t r = (uart_clkgen & SCU_UART_CLKGEN_R_MASK) >>
315 SCU_UART_CLKGEN_R_SHIFT;
316
317 return ((rate * r) / (n * 2));
318}
319
320static uint32_t ast2600_get_uart_huxclk_rate(struct ast2600_scu *scu)
321{
322 uint32_t rate = ast2600_get_huxclk_in_rate(scu);
323 uint32_t huart_clkgen = readl(&scu->huart_clkgen);
324 uint32_t n = (huart_clkgen & SCU_HUART_CLKGEN_N_MASK) >>
325 SCU_HUART_CLKGEN_N_SHIFT;
326 uint32_t r = (huart_clkgen & SCU_HUART_CLKGEN_R_MASK) >>
327 SCU_HUART_CLKGEN_R_SHIFT;
328
329 return ((rate * r) / (n * 2));
330}
331
332static uint32_t ast2600_get_sdio_clk_rate(struct ast2600_scu *scu)
333{
334 uint32_t rate = 0;
335 uint32_t clksrc4 = readl(&scu->clksrc4);
336 uint32_t sdio_div = (clksrc4 & SCU_CLKSRC4_SDIO_DIV_MASK) >>
337 SCU_CLKSRC4_SDIO_DIV_SHIFT;
338
339 if (clksrc4 & SCU_CLKSRC4_SDIO)
340 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL);
341 else
342 rate = ast2600_get_hclk_rate(scu);
343
344 return (rate / ((sdio_div + 1) * 2));
345}
346
347static uint32_t ast2600_get_emmc_clk_rate(struct ast2600_scu *scu)
348{
349 uint32_t rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
350 uint32_t clksrc1 = readl(&scu->clksrc1);
351 uint32_t emmc_div = (clksrc1 & SCU_CLKSRC1_EMMC_DIV_MASK) >>
352 SCU_CLKSRC1_EMMC_DIV_SHIFT;
353
354 return (rate / ((emmc_div + 1) * 4));
355}
356
357static uint32_t ast2600_get_uart_clk_rate(struct ast2600_scu *scu, int uart_idx)
358{
359 uint32_t rate = 0;
360 uint32_t uart5_clk = 0;
361 uint32_t clksrc2 = readl(&scu->clksrc2);
362 uint32_t clksrc4 = readl(&scu->clksrc4);
363 uint32_t clksrc5 = readl(&scu->clksrc5);
364 uint32_t misc_ctrl1 = readl(&scu->misc_ctrl1);
365
366 switch (uart_idx) {
367 case 1:
368 case 2:
369 case 3:
370 case 4:
371 case 6:
372 if (clksrc4 & BIT(uart_idx - 1))
373 rate = ast2600_get_uart_huxclk_rate(scu);
374 else
375 rate = ast2600_get_uart_uxclk_rate(scu);
376 break;
377 case 5:
378 /*
379 * SCU0C[12] and SCU304[14] together decide
380 * the UART5 clock generation
381 */
382 if (misc_ctrl1 & SCU_MISC_CTRL1_UART5_DIV)
383 uart5_clk = 0x1 << 1;
384
385 if (clksrc2 & SCU_CLKSRC2_UART5)
386 uart5_clk |= 0x1;
387
388 switch (uart5_clk) {
389 case 0:
390 rate = 24000000;
391 break;
392 case 1:
393 rate = 192000000;
394 break;
395 case 2:
396 rate = 24000000 / 13;
397 break;
398 case 3:
399 rate = 192000000 / 13;
400 break;
401 }
402
403 break;
404 case 7:
405 case 8:
406 case 9:
407 case 10:
408 case 11:
409 case 12:
410 case 13:
411 if (clksrc5 & BIT(uart_idx - 1))
412 rate = ast2600_get_uart_huxclk_rate(scu);
413 else
414 rate = ast2600_get_uart_uxclk_rate(scu);
415 break;
416 }
417
418 return rate;
419}
420
421static ulong ast2600_clk_get_rate(struct clk *clk)
422{
423 struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
424 ulong rate = 0;
425
426 switch (clk->id) {
427 case ASPEED_CLK_HPLL:
428 case ASPEED_CLK_EPLL:
429 case ASPEED_CLK_DPLL:
430 case ASPEED_CLK_MPLL:
431 case ASPEED_CLK_APLL:
432 rate = ast2600_get_pll_rate(priv->scu, clk->id);
433 break;
434 case ASPEED_CLK_AHB:
435 rate = ast2600_get_hclk_rate(priv->scu);
436 break;
437 case ASPEED_CLK_APB1:
438 rate = ast2600_get_pclk1_rate(priv->scu);
439 break;
440 case ASPEED_CLK_APB2:
441 rate = ast2600_get_pclk2_rate(priv->scu);
442 break;
443 case ASPEED_CLK_GATE_UART1CLK:
444 rate = ast2600_get_uart_clk_rate(priv->scu, 1);
445 break;
446 case ASPEED_CLK_GATE_UART2CLK:
447 rate = ast2600_get_uart_clk_rate(priv->scu, 2);
448 break;
449 case ASPEED_CLK_GATE_UART3CLK:
450 rate = ast2600_get_uart_clk_rate(priv->scu, 3);
451 break;
452 case ASPEED_CLK_GATE_UART4CLK:
453 rate = ast2600_get_uart_clk_rate(priv->scu, 4);
454 break;
455 case ASPEED_CLK_GATE_UART5CLK:
456 rate = ast2600_get_uart_clk_rate(priv->scu, 5);
457 break;
458 case ASPEED_CLK_BCLK:
459 rate = ast2600_get_bclk_rate(priv->scu);
460 break;
461 case ASPEED_CLK_SDIO:
462 rate = ast2600_get_sdio_clk_rate(priv->scu);
463 break;
464 case ASPEED_CLK_EMMC:
465 rate = ast2600_get_emmc_clk_rate(priv->scu);
466 break;
467 case ASPEED_CLK_UARTX:
468 rate = ast2600_get_uart_uxclk_rate(priv->scu);
469 break;
470 case ASPEED_CLK_HUARTX:
471 rate = ast2600_get_uart_huxclk_rate(priv->scu);
472 break;
473 default:
Joel Stanley50ddb952022-06-23 18:35:30 +0930474 debug("%s: unknown clk %ld\n", __func__, clk->id);
Ryan Chence5ecc12020-12-14 13:54:23 +0800475 return -ENOENT;
476 }
477
478 return rate;
479}
480
481/**
482 * @brief lookup PLL divider config by input/output rate
483 * @param[in] *pll - PLL descriptor
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100484 * Return: true - if PLL divider config is found, false - else
Ryan Chence5ecc12020-12-14 13:54:23 +0800485 * The function caller shall fill "pll->in" and "pll->out",
486 * then this function will search the lookup table
487 * to find a valid PLL divider configuration.
488 */
489static bool ast2600_search_clock_config(struct ast2600_pll_desc *pll)
490{
491 uint32_t i;
492 const struct ast2600_pll_desc *def_desc;
493 bool is_found = false;
494
495 for (i = 0; i < ARRAY_SIZE(ast2600_pll_lookup); i++) {
496 def_desc = &ast2600_pll_lookup[i];
497
498 if (def_desc->in == pll->in && def_desc->out == pll->out) {
499 is_found = true;
500 pll->cfg.reg.w = def_desc->cfg.reg.w;
501 pll->cfg.ext_reg = def_desc->cfg.ext_reg;
502 break;
503 }
504 }
505 return is_found;
506}
507
508static uint32_t ast2600_configure_pll(struct ast2600_scu *scu,
509 struct ast2600_pll_cfg *p_cfg, int pll_idx)
510{
511 uint32_t addr, addr_ext;
512 uint32_t reg;
513
514 switch (pll_idx) {
515 case ASPEED_CLK_HPLL:
516 addr = (uint32_t)(&scu->hpll);
517 addr_ext = (uint32_t)(&scu->hpll_ext);
518 break;
519 case ASPEED_CLK_MPLL:
520 addr = (uint32_t)(&scu->mpll);
521 addr_ext = (uint32_t)(&scu->mpll_ext);
522 break;
523 case ASPEED_CLK_DPLL:
524 addr = (uint32_t)(&scu->dpll);
525 addr_ext = (uint32_t)(&scu->dpll_ext);
526 break;
527 case ASPEED_CLK_EPLL:
528 addr = (uint32_t)(&scu->epll);
529 addr_ext = (uint32_t)(&scu->epll_ext);
530 break;
531 case ASPEED_CLK_APLL:
532 addr = (uint32_t)(&scu->apll);
533 addr_ext = (uint32_t)(&scu->apll_ext);
534 break;
535 default:
536 debug("unknown PLL index\n");
537 return 1;
538 }
539
540 p_cfg->reg.b.bypass = 0;
Dylan Hung53281e92023-02-21 21:01:10 +0800541 p_cfg->reg.b.off = 0;
Ryan Chence5ecc12020-12-14 13:54:23 +0800542 p_cfg->reg.b.reset = 1;
543
544 reg = readl(addr);
545 reg &= ~GENMASK(25, 0);
546 reg |= p_cfg->reg.w;
547 writel(reg, addr);
548
549 /* write extend parameter */
550 writel(p_cfg->ext_reg, addr_ext);
551 udelay(100);
Ryan Chence5ecc12020-12-14 13:54:23 +0800552 p_cfg->reg.b.reset = 0;
553 reg &= ~GENMASK(25, 0);
554 reg |= p_cfg->reg.w;
555 writel(reg, addr);
556 while (!(readl(addr_ext) & BIT(31)))
557 ;
558
559 return 0;
560}
561
562static uint32_t ast2600_configure_ddr(struct ast2600_scu *scu, ulong rate)
563{
564 struct ast2600_pll_desc mpll;
565
566 mpll.in = CLKIN_25M;
567 mpll.out = rate;
568 if (ast2600_search_clock_config(&mpll) == false) {
569 printf("error!! unable to find valid DDR clock setting\n");
570 return 0;
571 }
572 ast2600_configure_pll(scu, &mpll.cfg, ASPEED_CLK_MPLL);
573
574 return ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL);
575}
576
577static ulong ast2600_clk_set_rate(struct clk *clk, ulong rate)
578{
579 struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
580 ulong new_rate;
581
582 switch (clk->id) {
583 case ASPEED_CLK_MPLL:
584 new_rate = ast2600_configure_ddr(priv->scu, rate);
585 break;
586 default:
587 return -ENOENT;
588 }
589
590 return new_rate;
591}
592
593static uint32_t ast2600_configure_mac12_clk(struct ast2600_scu *scu)
594{
595 /* scu340[25:0]: 1G default delay */
596 clrsetbits_le32(&scu->mac12_clk_delay, GENMASK(25, 0),
597 MAC12_DEF_DELAY_1G);
598
599 /* set 100M/10M default delay */
600 writel(MAC12_DEF_DELAY_100M, &scu->mac12_clk_delay_100M);
601 writel(MAC12_DEF_DELAY_10M, &scu->mac12_clk_delay_10M);
602
603 /* MAC AHB = HPLL / 6 */
604 clrsetbits_le32(&scu->clksrc1, SCU_CLKSRC1_MAC_DIV_MASK,
605 (0x2 << SCU_CLKSRC1_MAC_DIV_SHIFT));
606
607 return 0;
608}
609
610static uint32_t ast2600_configure_mac34_clk(struct ast2600_scu *scu)
611{
612 /*
613 * scu350[31] RGMII 125M source: 0 = from IO pin
614 * scu350[25:0] MAC 1G delay
615 */
616 clrsetbits_le32(&scu->mac34_clk_delay, (BIT(31) | GENMASK(25, 0)),
617 MAC34_DEF_DELAY_1G);
618 writel(MAC34_DEF_DELAY_100M, &scu->mac34_clk_delay_100M);
619 writel(MAC34_DEF_DELAY_10M, &scu->mac34_clk_delay_10M);
620
621 /*
622 * clock source seletion and divider
623 * scu310[26:24] : MAC AHB bus clock = HCLK / 2
624 * scu310[18:16] : RMII 50M = HCLK_200M / 4
625 */
626 clrsetbits_le32(&scu->clksrc4,
627 (SCU_CLKSRC4_MAC_DIV_MASK | SCU_CLKSRC4_RMII34_DIV_MASK),
628 ((0x0 << SCU_CLKSRC4_MAC_DIV_SHIFT)
629 | (0x3 << SCU_CLKSRC4_RMII34_DIV_SHIFT)));
630
631 /*
632 * set driving strength
633 * scu458[3:2] : MAC4 driving strength
634 * scu458[1:0] : MAC3 driving strength
635 */
636 clrsetbits_le32(&scu->pinmux16,
637 SCU_PINCTRL16_MAC4_DRIVING_MASK | SCU_PINCTRL16_MAC3_DRIVING_MASK,
638 (0x3 << SCU_PINCTRL16_MAC4_DRIVING_SHIFT)
639 | (0x3 << SCU_PINCTRL16_MAC3_DRIVING_SHIFT));
640
641 return 0;
642}
643
644/**
645 * ast2600 RGMII clock source tree
646 * 125M from external PAD -------->|\
647 * HPLL -->|\ | |---->RGMII 125M for MAC#1 & MAC#2
648 * | |---->| divider |---->|/ +
649 * EPLL -->|/ |
650 * |
651 * +---------<-----------|RGMIICK PAD output enable|<-------------+
652 * |
653 * +--------------------------->|\
654 * | |----> RGMII 125M for MAC#3 & MAC#4
655 * HCLK 200M ---->|divider|---->|/
656 * To simplify the control flow:
657 * 1. RGMII 1/2 always use EPLL as the internal clock source
658 * 2. RGMII 3/4 always use RGMIICK pad as the RGMII 125M source
659 * 125M from external PAD -------->|\
660 * | |---->RGMII 125M for MAC#1 & MAC#2
661 * EPLL---->| divider |--->|/ +
662 * |
663 * +<--------------------|RGMIICK PAD output enable|<-------------+
664 * |
665 * +--------------------------->RGMII 125M for MAC#3 & MAC#4
666 */
667#define RGMIICK_SRC_PAD 0
668#define RGMIICK_SRC_EPLL 1 /* recommended */
669#define RGMIICK_SRC_HPLL 2
670
671#define RGMIICK_DIV2 1
672#define RGMIICK_DIV3 2
673#define RGMIICK_DIV4 3
674#define RGMIICK_DIV5 4
675#define RGMIICK_DIV6 5
676#define RGMIICK_DIV7 6
677#define RGMIICK_DIV8 7 /* recommended */
678
679#define RMIICK_DIV4 0
680#define RMIICK_DIV8 1
681#define RMIICK_DIV12 2
682#define RMIICK_DIV16 3
683#define RMIICK_DIV20 4 /* recommended */
684#define RMIICK_DIV24 5
685#define RMIICK_DIV28 6
686#define RMIICK_DIV32 7
687
688struct ast2600_mac_clk_div {
689 uint32_t src; /* 0=external PAD, 1=internal PLL */
690 uint32_t fin; /* divider input speed */
691 uint32_t n; /* 0=div2, 1=div2, 2=div3, 3=div4,...,7=div8 */
692 uint32_t fout; /* fout = fin / n */
693};
694
695struct ast2600_mac_clk_div rgmii_clk_defconfig = {
696 .src = ASPEED_CLK_EPLL,
697 .fin = 1000000000,
698 .n = RGMIICK_DIV8,
699 .fout = 125000000,
700};
701
702struct ast2600_mac_clk_div rmii_clk_defconfig = {
703 .src = ASPEED_CLK_EPLL,
704 .fin = 1000000000,
705 .n = RMIICK_DIV20,
706 .fout = 50000000,
707};
708
709static void ast2600_init_mac_pll(struct ast2600_scu *p_scu,
710 struct ast2600_mac_clk_div *p_cfg)
711{
712 struct ast2600_pll_desc pll;
713
714 pll.in = CLKIN_25M;
715 pll.out = p_cfg->fin;
716 if (ast2600_search_clock_config(&pll) == false) {
717 pr_err("unable to find valid ETHNET MAC clock setting\n");
718 return;
719 }
720 ast2600_configure_pll(p_scu, &pll.cfg, p_cfg->src);
721}
722
723static void ast2600_init_rgmii_clk(struct ast2600_scu *p_scu,
724 struct ast2600_mac_clk_div *p_cfg)
725{
726 uint32_t reg_304 = readl(&p_scu->clksrc2);
727 uint32_t reg_340 = readl(&p_scu->mac12_clk_delay);
728 uint32_t reg_350 = readl(&p_scu->mac34_clk_delay);
729
730 reg_340 &= ~GENMASK(31, 29);
731 /* scu340[28]: RGMIICK PAD output enable (to MAC 3/4) */
732 reg_340 |= BIT(28);
733 if (p_cfg->src == ASPEED_CLK_EPLL || p_cfg->src == ASPEED_CLK_HPLL) {
734 /*
735 * re-init PLL if the current PLL output frequency doesn't match
736 * the divider setting
737 */
738 if (p_cfg->fin != ast2600_get_pll_rate(p_scu, p_cfg->src))
739 ast2600_init_mac_pll(p_scu, p_cfg);
740 /* scu340[31]: select RGMII 125M from internal source */
741 reg_340 |= BIT(31);
742 }
743
744 reg_304 &= ~GENMASK(23, 20);
745
746 /* set clock divider */
747 reg_304 |= (p_cfg->n & 0x7) << 20;
748
749 /* select internal clock source */
750 if (p_cfg->src == ASPEED_CLK_HPLL)
751 reg_304 |= BIT(23);
752
753 /* RGMII 3/4 clock source select */
754 reg_350 &= ~BIT(31);
755
756 writel(reg_304, &p_scu->clksrc2);
757 writel(reg_340, &p_scu->mac12_clk_delay);
758 writel(reg_350, &p_scu->mac34_clk_delay);
759}
760
761/**
762 * ast2600 RMII/NCSI clock source tree
763 * HPLL -->|\
764 * | |---->| divider |----> RMII 50M for MAC#1 & MAC#2
765 * EPLL -->|/
766 * HCLK(SCLICLK)---->| divider |----> RMII 50M for MAC#3 & MAC#4
767 */
768static void ast2600_init_rmii_clk(struct ast2600_scu *p_scu,
769 struct ast2600_mac_clk_div *p_cfg)
770{
771 uint32_t clksrc2 = readl(&p_scu->clksrc2);
772 uint32_t clksrc4 = readl(&p_scu->clksrc4);
773
774 if (p_cfg->src == ASPEED_CLK_EPLL || p_cfg->src == ASPEED_CLK_HPLL) {
775 /*
776 * re-init PLL if the current PLL output frequency doesn't match
777 * the divider setting
778 */
779 if (p_cfg->fin != ast2600_get_pll_rate(p_scu, p_cfg->src))
780 ast2600_init_mac_pll(p_scu, p_cfg);
781 }
782
783 clksrc2 &= ~(SCU_CLKSRC2_RMII12 | SCU_CLKSRC2_RMII12_DIV_MASK);
784
785 /* set RMII 1/2 clock divider */
786 clksrc2 |= (p_cfg->n & 0x7) << 16;
787
788 /* RMII clock source selection */
789 if (p_cfg->src == ASPEED_CLK_HPLL)
790 clksrc2 |= SCU_CLKSRC2_RMII12;
791
792 /* set RMII 3/4 clock divider */
793 clksrc4 &= ~SCU_CLKSRC4_RMII34_DIV_MASK;
794 clksrc4 |= (0x3 << SCU_CLKSRC4_RMII34_DIV_SHIFT);
795
796 writel(clksrc2, &p_scu->clksrc2);
797 writel(clksrc4, &p_scu->clksrc4);
798}
799
800static uint32_t ast2600_configure_mac(struct ast2600_scu *scu, int index)
801{
802 uint32_t reset_bit;
803 uint32_t clkgate_bit;
804
805 switch (index) {
806 case 1:
807 reset_bit = BIT(ASPEED_RESET_MAC1);
808 clkgate_bit = SCU_CLKGATE1_MAC1;
809 writel(reset_bit, &scu->modrst_ctrl1);
810 udelay(100);
811 writel(clkgate_bit, &scu->clkgate_clr1);
812 mdelay(10);
813 writel(reset_bit, &scu->modrst_clr1);
814 break;
815 case 2:
816 reset_bit = BIT(ASPEED_RESET_MAC2);
817 clkgate_bit = SCU_CLKGATE1_MAC2;
818 writel(reset_bit, &scu->modrst_ctrl1);
819 udelay(100);
820 writel(clkgate_bit, &scu->clkgate_clr1);
821 mdelay(10);
822 writel(reset_bit, &scu->modrst_clr1);
823 break;
824 case 3:
825 reset_bit = BIT(ASPEED_RESET_MAC3 - 32);
826 clkgate_bit = SCU_CLKGATE2_MAC3;
827 writel(reset_bit, &scu->modrst_ctrl2);
828 udelay(100);
829 writel(clkgate_bit, &scu->clkgate_clr2);
830 mdelay(10);
831 writel(reset_bit, &scu->modrst_clr2);
832 break;
833 case 4:
834 reset_bit = BIT(ASPEED_RESET_MAC4 - 32);
835 clkgate_bit = SCU_CLKGATE2_MAC4;
836 writel(reset_bit, &scu->modrst_ctrl2);
837 udelay(100);
838 writel(clkgate_bit, &scu->clkgate_clr2);
839 mdelay(10);
840 writel(reset_bit, &scu->modrst_clr2);
841 break;
842 default:
843 return -EINVAL;
844 }
845
846 return 0;
847}
848
849static void ast2600_configure_rsa_ecc_clk(struct ast2600_scu *scu)
850{
851 uint32_t clksrc1 = readl(&scu->clksrc1);
852
853 /* Configure RSA clock = HPLL/3 */
854 clksrc1 |= SCU_CLKSRC1_ECC_RSA;
855 clksrc1 &= ~SCU_CLKSRC1_ECC_RSA_DIV_MASK;
856 clksrc1 |= (2 << SCU_CLKSRC1_ECC_RSA_DIV_SHIFT);
857
858 writel(clksrc1, &scu->clksrc1);
859}
860
861static ulong ast2600_enable_sdclk(struct ast2600_scu *scu)
862{
863 uint32_t reset_bit;
864 uint32_t clkgate_bit;
865
866 reset_bit = BIT(ASPEED_RESET_SD - 32);
867 clkgate_bit = SCU_CLKGATE2_SDIO;
868
869 writel(reset_bit, &scu->modrst_ctrl2);
870 udelay(100);
871 writel(clkgate_bit, &scu->clkgate_clr2);
872 mdelay(10);
873 writel(reset_bit, &scu->modrst_clr2);
874
875 return 0;
876}
877
878static ulong ast2600_enable_extsdclk(struct ast2600_scu *scu)
879{
880 int i = 0;
881 uint32_t div = 0;
882 uint32_t rate = 0;
883 uint32_t clksrc4 = readl(&scu->clksrc4);
884
885 /*
886 * ast2600 SD controller max clk is 200Mhz
887 * use apll for clock source 800/4 = 200
888 * controller max is 200mhz
889 */
890 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_APLL);
891 for (i = 0; i < 8; i++) {
892 div = (i + 1) * 2;
893 if ((rate / div) <= 200000000)
894 break;
895 }
896 clksrc4 &= ~SCU_CLKSRC4_SDIO_DIV_MASK;
897 clksrc4 |= (i << SCU_CLKSRC4_SDIO_DIV_SHIFT);
898 clksrc4 |= SCU_CLKSRC4_SDIO;
899 writel(clksrc4, &scu->clksrc4);
900
901 setbits_le32(&scu->clksrc4, SCU_CLKSRC4_SDIO_EN);
902
903 return 0;
904}
905
906static ulong ast2600_enable_emmcclk(struct ast2600_scu *scu)
907{
908 uint32_t reset_bit;
909 uint32_t clkgate_bit;
910
911 reset_bit = BIT(ASPEED_RESET_EMMC);
912 clkgate_bit = SCU_CLKGATE1_EMMC;
913
914 writel(reset_bit, &scu->modrst_ctrl1);
915 udelay(100);
916 writel(clkgate_bit, &scu->clkgate_clr1);
917 mdelay(10);
918 writel(reset_bit, &scu->modrst_clr1);
919
920 return 0;
921}
922
923static ulong ast2600_enable_extemmcclk(struct ast2600_scu *scu)
924{
925 int i = 0;
926 uint32_t div = 0;
927 uint32_t rate = 0;
928 uint32_t clksrc1 = readl(&scu->clksrc1);
929
930 /*
931 * ast2600 eMMC controller max clk is 200Mhz
932 * HPll->1/2->|\
933 * |->SCU300[11]->SCU300[14:12][1/N] +
934 * MPLL------>|/ |
935 * +----------------------------------------------+
936 * |
937 * +---------> EMMC12C[15:8][1/N]-> eMMC clk
938 */
939 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL);
940 for (i = 0; i < 8; i++) {
941 div = (i + 1) * 2;
942 if ((rate / div) <= 200000000)
943 break;
944 }
945
946 clksrc1 &= ~SCU_CLKSRC1_EMMC_DIV_MASK;
947 clksrc1 |= (i << SCU_CLKSRC1_EMMC_DIV_SHIFT);
948 clksrc1 |= SCU_CLKSRC1_EMMC;
949 writel(clksrc1, &scu->clksrc1);
950
951 setbits_le32(&scu->clksrc1, SCU_CLKSRC1_EMMC_EN);
952
953 return 0;
954}
955
956static ulong ast2600_enable_fsiclk(struct ast2600_scu *scu)
957{
958 uint32_t reset_bit;
959 uint32_t clkgate_bit;
960
961 reset_bit = BIT(ASPEED_RESET_FSI % 32);
962 clkgate_bit = SCU_CLKGATE2_FSI;
963
964 /* The FSI clock is shared between masters. If it's already on
965 * don't touch it, as that will reset the existing master.
966 */
967 if (!(readl(&scu->clkgate_ctrl2) & clkgate_bit)) {
968 debug("%s: already running, not touching it\n", __func__);
969 return 0;
970 }
971
972 writel(reset_bit, &scu->modrst_ctrl2);
973 udelay(100);
974 writel(clkgate_bit, &scu->clkgate_clr2);
975 mdelay(10);
976 writel(reset_bit, &scu->modrst_clr2);
977
978 return 0;
979}
980
981static ulong ast2600_enable_usbahclk(struct ast2600_scu *scu)
982{
983 uint32_t reset_bit;
984 uint32_t clkgate_bit;
985
986 reset_bit = BIT(ASPEED_RESET_EHCI_P1);
987 clkgate_bit = SCU_CLKGATE1_USB_HUB;
988
989 writel(reset_bit, &scu->modrst_ctrl1);
990 udelay(100);
991 writel(clkgate_bit, &scu->clkgate_ctrl1);
992 mdelay(20);
993 writel(reset_bit, &scu->modrst_clr1);
994
995 return 0;
996}
997
998static ulong ast2600_enable_usbbhclk(struct ast2600_scu *scu)
999{
1000 uint32_t reset_bit;
1001 uint32_t clkgate_bit;
1002
1003 reset_bit = BIT(ASPEED_RESET_EHCI_P2);
1004 clkgate_bit = SCU_CLKGATE1_USB_HOST2;
1005
1006 writel(reset_bit, &scu->modrst_ctrl1);
1007 udelay(100);
1008 writel(clkgate_bit, &scu->clkgate_clr1);
1009 mdelay(20);
1010 writel(reset_bit, &scu->modrst_clr1);
1011
1012 return 0;
1013}
1014
Joel Stanleyd59cd6f2021-10-27 14:17:26 +08001015static ulong ast2600_enable_haceclk(struct ast2600_scu *scu)
1016{
1017 uint32_t reset_bit;
1018 uint32_t clkgate_bit;
1019
Chia-Wei Wangb0e3cf92021-10-27 14:17:29 +08001020 /* share the same reset control bit with ACRY */
Joel Stanleyd59cd6f2021-10-27 14:17:26 +08001021 reset_bit = BIT(ASPEED_RESET_HACE);
1022 clkgate_bit = SCU_CLKGATE1_HACE;
1023
1024 /*
1025 * we don't do reset assertion here as HACE
1026 * shares the same reset control with ACRY
1027 */
1028 writel(clkgate_bit, &scu->clkgate_clr1);
1029 mdelay(20);
1030 writel(reset_bit, &scu->modrst_clr1);
1031
1032 return 0;
1033}
1034
Chia-Wei Wangb0e3cf92021-10-27 14:17:29 +08001035static ulong ast2600_enable_rsaclk(struct ast2600_scu *scu)
1036{
1037 uint32_t reset_bit;
1038 uint32_t clkgate_bit;
1039
1040 /* same reset control bit with HACE */
1041 reset_bit = BIT(ASPEED_RESET_HACE);
1042 clkgate_bit = SCU_CLKGATE1_ACRY;
1043
1044 /*
1045 * we don't do reset assertion here as HACE
1046 * shares the same reset control with ACRY
1047 */
1048 writel(clkgate_bit, &scu->clkgate_clr1);
1049 mdelay(20);
1050 writel(reset_bit, &scu->modrst_clr1);
1051
1052 return 0;
1053}
1054
Ryan Chence5ecc12020-12-14 13:54:23 +08001055static int ast2600_clk_enable(struct clk *clk)
1056{
1057 struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
1058
1059 switch (clk->id) {
1060 case ASPEED_CLK_GATE_MAC1CLK:
1061 ast2600_configure_mac(priv->scu, 1);
1062 break;
1063 case ASPEED_CLK_GATE_MAC2CLK:
1064 ast2600_configure_mac(priv->scu, 2);
1065 break;
1066 case ASPEED_CLK_GATE_MAC3CLK:
1067 ast2600_configure_mac(priv->scu, 3);
1068 break;
1069 case ASPEED_CLK_GATE_MAC4CLK:
1070 ast2600_configure_mac(priv->scu, 4);
1071 break;
1072 case ASPEED_CLK_GATE_SDCLK:
1073 ast2600_enable_sdclk(priv->scu);
1074 break;
Joel Stanley68abf0f2022-06-23 18:35:31 +09301075 case ASPEED_CLK_SDIO:
Ryan Chence5ecc12020-12-14 13:54:23 +08001076 ast2600_enable_extsdclk(priv->scu);
1077 break;
1078 case ASPEED_CLK_GATE_EMMCCLK:
1079 ast2600_enable_emmcclk(priv->scu);
1080 break;
Joel Stanley68abf0f2022-06-23 18:35:31 +09301081 case ASPEED_CLK_EMMC:
Ryan Chence5ecc12020-12-14 13:54:23 +08001082 ast2600_enable_extemmcclk(priv->scu);
1083 break;
1084 case ASPEED_CLK_GATE_FSICLK:
1085 ast2600_enable_fsiclk(priv->scu);
1086 break;
1087 case ASPEED_CLK_GATE_USBPORT1CLK:
1088 ast2600_enable_usbahclk(priv->scu);
1089 break;
1090 case ASPEED_CLK_GATE_USBPORT2CLK:
1091 ast2600_enable_usbbhclk(priv->scu);
1092 break;
Joel Stanleyd59cd6f2021-10-27 14:17:26 +08001093 case ASPEED_CLK_GATE_YCLK:
1094 ast2600_enable_haceclk(priv->scu);
1095 break;
Chia-Wei Wangb0e3cf92021-10-27 14:17:29 +08001096 case ASPEED_CLK_GATE_RSACLK:
1097 ast2600_enable_rsaclk(priv->scu);
1098 break;
Ryan Chence5ecc12020-12-14 13:54:23 +08001099 default:
Joel Stanley50ddb952022-06-23 18:35:30 +09301100 debug("%s: unknown clk %ld\n", __func__, clk->id);
Ryan Chence5ecc12020-12-14 13:54:23 +08001101 return -ENOENT;
1102 }
1103
1104 return 0;
1105}
1106
1107struct clk_ops ast2600_clk_ops = {
1108 .get_rate = ast2600_clk_get_rate,
1109 .set_rate = ast2600_clk_set_rate,
1110 .enable = ast2600_clk_enable,
1111};
1112
1113static int ast2600_clk_probe(struct udevice *dev)
1114{
1115 struct ast2600_clk_priv *priv = dev_get_priv(dev);
1116
1117 priv->scu = devfdt_get_addr_ptr(dev);
1118 if (IS_ERR(priv->scu))
1119 return PTR_ERR(priv->scu);
1120
1121 ast2600_init_rgmii_clk(priv->scu, &rgmii_clk_defconfig);
1122 ast2600_init_rmii_clk(priv->scu, &rmii_clk_defconfig);
1123 ast2600_configure_mac12_clk(priv->scu);
1124 ast2600_configure_mac34_clk(priv->scu);
1125 ast2600_configure_rsa_ecc_clk(priv->scu);
1126
1127 return 0;
1128}
1129
1130static int ast2600_clk_bind(struct udevice *dev)
1131{
1132 int ret;
1133
1134 /* The reset driver does not have a device node, so bind it here */
1135 ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev);
1136 if (ret)
1137 debug("Warning: No reset driver: ret=%d\n", ret);
1138
1139 return 0;
1140}
1141
1142struct aspeed_clks {
1143 ulong id;
1144 const char *name;
1145};
1146
1147static struct aspeed_clks aspeed_clk_names[] = {
1148 { ASPEED_CLK_HPLL, "hpll" },
1149 { ASPEED_CLK_MPLL, "mpll" },
1150 { ASPEED_CLK_APLL, "apll" },
1151 { ASPEED_CLK_EPLL, "epll" },
1152 { ASPEED_CLK_DPLL, "dpll" },
1153 { ASPEED_CLK_AHB, "hclk" },
1154 { ASPEED_CLK_APB1, "pclk1" },
1155 { ASPEED_CLK_APB2, "pclk2" },
1156 { ASPEED_CLK_BCLK, "bclk" },
1157 { ASPEED_CLK_UARTX, "uxclk" },
1158 { ASPEED_CLK_HUARTX, "huxclk" },
1159};
1160
1161int soc_clk_dump(void)
1162{
1163 struct udevice *dev;
1164 struct clk clk;
1165 unsigned long rate;
1166 int i, ret;
1167
1168 ret = uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(aspeed_scu),
1169 &dev);
1170 if (ret)
1171 return ret;
1172
1173 printf("Clk\t\tHz\n");
1174
1175 for (i = 0; i < ARRAY_SIZE(aspeed_clk_names); i++) {
1176 clk.id = aspeed_clk_names[i].id;
1177 ret = clk_request(dev, &clk);
1178 if (ret < 0) {
1179 debug("%s clk_request() failed: %d\n", __func__, ret);
1180 continue;
1181 }
1182
1183 ret = clk_get_rate(&clk);
1184 rate = ret;
1185
1186 clk_free(&clk);
1187
Simon Glass29ff16a2021-03-25 10:26:08 +13001188 if (ret == -EINVAL) {
Ryan Chence5ecc12020-12-14 13:54:23 +08001189 printf("clk ID %lu not supported yet\n",
1190 aspeed_clk_names[i].id);
1191 continue;
1192 }
1193 if (ret < 0) {
1194 printf("%s %lu: get_rate err: %d\n", __func__,
1195 aspeed_clk_names[i].id, ret);
1196 continue;
1197 }
1198
1199 printf("%s(%3lu):\t%lu\n", aspeed_clk_names[i].name,
1200 aspeed_clk_names[i].id, rate);
1201 }
1202
1203 return 0;
1204}
1205
1206static const struct udevice_id ast2600_clk_ids[] = {
1207 { .compatible = "aspeed,ast2600-scu", },
1208 { },
1209};
1210
1211U_BOOT_DRIVER(aspeed_ast2600_scu) = {
1212 .name = "aspeed_ast2600_scu",
1213 .id = UCLASS_CLK,
1214 .of_match = ast2600_clk_ids,
1215 .priv_auto = sizeof(struct ast2600_clk_priv),
1216 .ops = &ast2600_clk_ops,
1217 .bind = ast2600_clk_bind,
1218 .probe = ast2600_clk_probe,
1219};