1 // 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 <asm/arch/scu_ast2400.h>
12 #include <dt-bindings/clock/ast2400-clock.h>
13 #include <dt-bindings/reset/ast2400-reset.h>
14
15 DECLARE_GLOBAL_DATA_PTR;
16
17 /*
18 * Clock divider/multiplier configuration struct.
19 * For H-PLL and M-PLL the formula is
20 * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
21 * M - Numerator
22 * N - Denumerator
23 * P - Post Divider
24 * They have the same layout in their control register.
25 *
26 * D-PLL and D2-PLL have extra divider (OD + 1), which is not
27 * yet needed and ignored by clock configurations.
28 */
29 struct ast2400_div_config {
30 unsigned int num;
31 unsigned int denum;
32 unsigned int post_div;
33 };
34
35 #define CLKIN_25MHZ_EN BIT(23)
36 #define AST2400_CLK_SOURCE_SEL BIT(18)
ast2400_get_clkin(struct ast2400_scu * scu)37 extern u32 ast2400_get_clkin(struct ast2400_scu *scu)
38 {
39 u32 clkin;
40 u32 strap = readl(&scu->hwstrap);
41
42 if (strap & CLKIN_25MHZ_EN) {
43 clkin = 25 * 1000 * 1000;
44 } else {
45 if (strap & AST2400_CLK_SOURCE_SEL)
46 clkin = 48 * 1000 * 1000;
47 else
48 clkin = 24 * 1000 * 1000;
49 }
50
51 return clkin;
52 }
53
54 #define AST2400_MPLL_BYPASS_EN BIT(17)
55 #define AST2400_MPLL_OFF BIT(16)
56
57 /*
58 * Get the rate of the M-PLL clock from input clock frequency and
59 * the value of the M-PLL Parameter Register.
60 */
ast2400_get_mpll_rate(struct ast2400_scu * scu)61 extern u32 ast2400_get_mpll_rate(struct ast2400_scu *scu)
62 {
63 unsigned int mult, div;
64 u32 clkin = ast2400_get_clkin(scu);
65 u32 mpll_reg = readl(&scu->m_pll_param);
66
67 if (mpll_reg & AST2400_MPLL_OFF)
68 return 0;
69
70 if (mpll_reg & AST2400_MPLL_BYPASS_EN)
71 return clkin;
72 else {
73 u32 od = (mpll_reg >> 4) & 0x1;
74 u32 n = (mpll_reg >> 5) & 0x3f;
75 u32 d = mpll_reg & 0xf;
76
77 //mpll = 24MHz * (2-OD) * ((Numerator+2)/(Denumerator+1))
78 mult = (2 - od) * (n + 2);
79 div = (d + 1);
80 }
81
82 return (clkin * mult / div);
83 }
84
85 #define AST2400_HPLL_PROGRAMMED BIT(18)
86 #define AST2400_HPLL_BYPASS_EN BIT(17)
87 /*
88 * Get the rate of the H-PLL clock from input clock frequency and
89 * the value of the H-PLL Parameter Register.
90 */
ast2400_get_hpll_rate(struct ast2400_scu * scu)91 extern u32 ast2400_get_hpll_rate(struct ast2400_scu *scu)
92 {
93 unsigned int mult, div;
94 u32 clkin = ast2400_get_clkin(scu);
95 u32 hpll_reg = readl(&scu->h_pll_param);
96
97 const u16 hpll_rates[][4] = {
98 {384, 360, 336, 408},
99 {400, 375, 350, 425},
100 };
101
102 if (hpll_reg & AST2400_HPLL_PROGRAMMED) {
103 if (hpll_reg & AST2400_HPLL_BYPASS_EN) {
104 /* Pass through mode */
105 mult = div = 1;
106 } else {
107 /* F = 24Mhz * (2-OD) * [(N + 2) / (D + 1)] */
108 u32 n = (hpll_reg >> 5) & 0x3f;
109 u32 od = (hpll_reg >> 4) & 0x1;
110 u32 d = hpll_reg & 0xf;
111
112 mult = (2 - od) * (n + 2);
113 div = d + 1;
114 }
115 } else {
116 //fix
117 u32 strap = readl(ASPEED_HW_STRAP1);
118 u16 rate = (hpll_reg >> 8) & 3;
119 if (strap & CLKIN_25MHZ_EN)
120 clkin = hpll_rates[1][rate];
121 else {
122 if (strap & AST2400_CLK_SOURCE_SEL)
123 clkin = hpll_rates[0][rate];
124 else
125 clkin = hpll_rates[0][rate];
126 }
127 clkin *= 1000000;
128 mult = 1;
129 div = 1;
130 }
131
132 return (clkin * mult / div);
133 }
134
135 #define AST2400_D2PLL_OFF BIT(17)
136 #define AST2400_D2PLL_BYPASS_EN BIT(18)
137
138 /*
139 * Get the rate of the D2-PLL clock from input clock frequency and
140 * the value of the D2-PLL Parameter Register.
141 */
ast2400_get_d2pll_rate(struct ast2400_scu * scu)142 extern u32 ast2400_get_d2pll_rate(struct ast2400_scu *scu)
143 {
144 unsigned int mult, div;
145 u32 clkin = ast2400_get_clkin(scu);
146 u32 d2pll_reg = readl(&scu->d2_pll_param);
147
148 /* F = clkin * [(M+1) / (N+1)] / (P + 1)/ (od + 1) */
149 if (d2pll_reg & AST2400_D2PLL_OFF)
150 return 0;
151
152 // Programming
153 if (d2pll_reg & AST2400_D2PLL_BYPASS_EN)
154 return clkin;
155 else {
156 u32 n = (d2pll_reg & 0xff);
157 u32 d = (d2pll_reg >> 8) & 0x1f;
158 u32 o = (d2pll_reg >> 13) & 0x3;
159 o = (1 << (o - 1));
160 u32 p = (d2pll_reg >> 15) & 0x3;
161 if (p == 2)
162 p = 2;
163 else
164 p = (0x1 << p);
165 u32 p2 = (d2pll_reg >> 19) & 0x7;
166 p2 += 1;
167 //FOUT (Output frequency) = 24MHz * (Num * 2) / (Denum * OD * PD * PD2)
168 mult = (n * 2);
169 div = (d * o * p * p2);
170 }
171 return (clkin * mult / div);
172 }
173
174 #define SCU_HWSTRAP_AXIAHB_DIV_SHIFT 9
175 #define SCU_HWSTRAP_AXIAHB_DIV_MASK (0x7 << SCU_HWSTRAP_AXIAHB_DIV_SHIFT)
176
ast2400_get_hclk(struct ast2400_scu * scu)177 static u32 ast2400_get_hclk(struct ast2400_scu *scu)
178 {
179 u32 ahb_div;
180 u32 strap = readl(&scu->hwstrap);
181 u32 rate = ast2400_get_hpll_rate(scu);
182
183 ahb_div = ((strap >> 10) & 0x3) + 1;
184
185 return (rate / ahb_div);
186 }
187
ast2400_get_pclk(struct ast2400_scu * scu)188 static u32 ast2400_get_pclk(struct ast2400_scu *scu)
189 {
190 u32 rate = 0;
191 rate = ast2400_get_hpll_rate(scu);
192 u32 apb_div = (readl(&scu->clk_sel1) >> 23) & 0x7;
193
194 apb_div = (apb_div + 1) << 1;
195
196 return (rate / apb_div);
197 }
198
ast2400_get_sdio_clk_rate(struct ast2400_scu * scu)199 static u32 ast2400_get_sdio_clk_rate(struct ast2400_scu *scu)
200 {
201 u32 clkin = ast2400_get_hpll_rate(scu);
202 u32 clk_sel = readl(&scu->clk_sel1);
203 u32 div = (clk_sel >> 12) & 0x7;
204
205 div = (div + 1) << 1;
206
207 return (clkin / div);
208 }
209
ast2400_get_uart_clk_rate(struct ast2400_scu * scu,int uart_idx)210 static u32 ast2400_get_uart_clk_rate(struct ast2400_scu *scu, int uart_idx)
211 {
212 u32 uart_clkin = 24 * 1000 * 1000;
213
214 if (readl(&scu->misc_ctrl1) & SCU_MISC_UARTCLK_DIV13)
215 uart_clkin /= 13;
216
217 return uart_clkin;
218 }
219
ast2400_clk_get_rate(struct clk * clk)220 static ulong ast2400_clk_get_rate(struct clk *clk)
221 {
222 struct ast2400_clk_priv *priv = dev_get_priv(clk->dev);
223 ulong rate;
224
225 switch (clk->id) {
226 case ASPEED_CLK_HPLL:
227 rate = ast2400_get_hpll_rate(priv->scu);
228 break;
229 case ASPEED_CLK_MPLL:
230 rate = ast2400_get_mpll_rate(priv->scu);
231 break;
232 case ASPEED_CLK_D2PLL:
233 rate = ast2400_get_d2pll_rate(priv->scu);
234 break;
235 case ASPEED_CLK_AHB:
236 rate = ast2400_get_hclk(priv->scu);
237 break;
238 case ASPEED_CLK_APB:
239 rate = ast2400_get_pclk(priv->scu);
240 break;
241 case ASPEED_CLK_GATE_UART1CLK:
242 rate = ast2400_get_uart_clk_rate(priv->scu, 1);
243 break;
244 case ASPEED_CLK_GATE_UART2CLK:
245 rate = ast2400_get_uart_clk_rate(priv->scu, 2);
246 break;
247 case ASPEED_CLK_GATE_UART3CLK:
248 rate = ast2400_get_uart_clk_rate(priv->scu, 3);
249 break;
250 case ASPEED_CLK_GATE_UART4CLK:
251 rate = ast2400_get_uart_clk_rate(priv->scu, 4);
252 break;
253 case ASPEED_CLK_GATE_UART5CLK:
254 rate = ast2400_get_uart_clk_rate(priv->scu, 5);
255 break;
256 case ASPEED_CLK_SDIO:
257 rate = ast2400_get_sdio_clk_rate(priv->scu);
258 break;
259 default:
260 pr_debug("can't get clk rate \n");
261 return -ENOENT;
262 break;
263 }
264
265 return rate;
266 }
267
268 struct ast2400_clock_config {
269 ulong input_rate;
270 ulong rate;
271 struct ast2400_div_config cfg;
272 };
273
274 static const struct ast2400_clock_config ast2400_clock_config_defaults[] = {
275 { 24000000, 250000000, { .num = 124, .denum = 1, .post_div = 5 } },
276 };
277
ast2400_get_clock_config_default(ulong input_rate,ulong requested_rate,struct ast2400_div_config * cfg)278 static bool ast2400_get_clock_config_default(ulong input_rate,
279 ulong requested_rate,
280 struct ast2400_div_config *cfg)
281 {
282 int i;
283
284 for (i = 0; i < ARRAY_SIZE(ast2400_clock_config_defaults); i++) {
285 const struct ast2400_clock_config *default_cfg =
286 &ast2400_clock_config_defaults[i];
287 if (default_cfg->input_rate == input_rate &&
288 default_cfg->rate == requested_rate) {
289 *cfg = default_cfg->cfg;
290 return true;
291 }
292 }
293
294 return false;
295 }
296
297 /*
298 * @input_rate - the rate of input clock in Hz
299 * @requested_rate - desired output rate in Hz
300 * @div - this is an IN/OUT parameter, at input all fields of the config
301 * need to be set to their maximum allowed values.
302 * The result (the best config we could find), would also be returned
303 * in this structure.
304 *
305 * @return The clock rate, when the resulting div_config is used.
306 */
ast2400_calc_clock_config(ulong input_rate,ulong requested_rate,struct ast2400_div_config * cfg)307 static ulong ast2400_calc_clock_config(ulong input_rate, ulong requested_rate,
308 struct ast2400_div_config *cfg)
309 {
310 /*
311 * The assumption is that kHz precision is good enough and
312 * also enough to avoid overflow when multiplying.
313 */
314 const ulong input_rate_khz = input_rate / 1000;
315 const ulong rate_khz = requested_rate / 1000;
316 const struct ast2400_div_config max_vals = *cfg;
317 struct ast2400_div_config it = { 0, 0, 0 };
318 ulong delta = rate_khz;
319 ulong new_rate_khz = 0;
320
321 /*
322 * Look for a well known frequency first.
323 */
324 if (ast2400_get_clock_config_default(input_rate, requested_rate, cfg))
325 return requested_rate;
326
327 for (; it.denum <= max_vals.denum; ++it.denum) {
328 for (it.post_div = 0; it.post_div <= max_vals.post_div;
329 ++it.post_div) {
330 it.num = (rate_khz * (it.post_div + 1) / input_rate_khz)
331 * (it.denum + 1);
332 if (it.num > max_vals.num)
333 continue;
334
335 new_rate_khz = (input_rate_khz
336 * ((it.num + 1) / (it.denum + 1)))
337 / (it.post_div + 1);
338
339 /* Keep the rate below requested one. */
340 if (new_rate_khz > rate_khz)
341 continue;
342
343 if (new_rate_khz - rate_khz < delta) {
344 delta = new_rate_khz - rate_khz;
345 *cfg = it;
346 if (delta == 0)
347 return new_rate_khz * 1000;
348 }
349 }
350 }
351
352 return new_rate_khz * 1000;
353 }
354
ast2400_configure_ddr(struct ast2400_scu * scu,ulong rate)355 static ulong ast2400_configure_ddr(struct ast2400_scu *scu, ulong rate)
356 {
357 ulong clkin = ast2400_get_clkin(scu);
358 u32 mpll_reg;
359 struct ast2400_div_config div_cfg = {
360 .num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT),
361 .denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT),
362 .post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT),
363 };
364
365 ast2400_calc_clock_config(clkin, rate, &div_cfg);
366
367 mpll_reg = readl(&scu->m_pll_param);
368 mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK
369 | SCU_MPLL_DENUM_MASK);
370 mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
371 | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
372 | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
373
374 writel(mpll_reg, &scu->m_pll_param);
375
376 return ast2400_get_mpll_rate(scu);
377 }
378
ast2400_clk_set_rate(struct clk * clk,ulong rate)379 static unsigned long ast2400_clk_set_rate(struct clk *clk, ulong rate)
380 {
381 struct ast2400_clk_priv *priv = dev_get_priv(clk->dev);
382
383 ulong new_rate;
384 switch (clk->id) {
385 //mpll
386 case ASPEED_CLK_MPLL:
387 new_rate = ast2400_configure_ddr(priv->scu, rate);
388 break;
389 default:
390 return -ENOENT;
391 }
392
393 return new_rate;
394 }
395
396 #define SCU_CLKSTOP_MAC1 (20)
397 #define SCU_CLKSTOP_MAC2 (21)
398
ast2400_configure_mac(struct ast2400_scu * scu,int index)399 static ulong ast2400_configure_mac(struct ast2400_scu *scu, int index)
400 {
401 u32 reset_bit;
402 u32 clkstop_bit;
403
404 switch (index) {
405 case 1:
406 reset_bit = BIT(ASPEED_RESET_MAC1);
407 clkstop_bit = BIT(SCU_CLKSTOP_MAC1);
408 break;
409 case 2:
410 reset_bit = BIT(ASPEED_RESET_MAC2);
411 clkstop_bit = BIT(SCU_CLKSTOP_MAC2);
412 break;
413 default:
414 return -EINVAL;
415 }
416
417 /*
418 * Disable MAC, start its clock and re-enable it.
419 * The procedure and the delays (100us & 10ms) are
420 * specified in the datasheet.
421 */
422 setbits_le32(&scu->sysreset_ctrl1, reset_bit);
423 udelay(100);
424 clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
425 mdelay(10);
426 clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
427
428 return 0;
429 }
430
431 #define SCU_CLKSTOP_SDIO 27
ast2400_enable_sdclk(struct ast2400_scu * scu)432 static ulong ast2400_enable_sdclk(struct ast2400_scu *scu)
433 {
434 u32 reset_bit;
435 u32 clkstop_bit;
436
437 reset_bit = BIT(ASEPPD_RESET_SDIO);
438 clkstop_bit = BIT(SCU_CLKSTOP_SDIO);
439
440 setbits_le32(&scu->sysreset_ctrl1, reset_bit);
441 udelay(100);
442 //enable clk
443 clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
444 mdelay(10);
445 clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
446
447 return 0;
448 }
449
450 #define SCU_CLKSTOP_EXTSD 15
451 #define SCU_CLK_SD_MASK (0x7 << 12)
452 #define SCU_CLK_SD_DIV(x) (x << 12)
453
ast2400_enable_extsdclk(struct ast2400_scu * scu)454 static ulong ast2400_enable_extsdclk(struct ast2400_scu *scu)
455 {
456 u32 clk_sel = readl(&scu->clk_sel1);
457 u32 enableclk_bit;
458
459 enableclk_bit = BIT(SCU_CLKSTOP_EXTSD);
460
461 // SDCLK = G4 H-PLL / 4, G5 = H-PLL /8
462 clk_sel &= ~SCU_CLK_SD_MASK;
463 clk_sel |= SCU_CLK_SD_DIV(1);
464 writel(clk_sel, &scu->clk_sel1);
465
466 //enable clk
467 setbits_le32(&scu->clk_sel1, enableclk_bit);
468
469 return 0;
470 }
471
ast2400_clk_enable(struct clk * clk)472 static int ast2400_clk_enable(struct clk *clk)
473 {
474 struct ast2400_clk_priv *priv = dev_get_priv(clk->dev);
475
476 switch (clk->id) {
477 case ASPEED_CLK_GATE_MAC1CLK:
478 ast2400_configure_mac(priv->scu, 1);
479 break;
480 case ASPEED_CLK_GATE_MAC2CLK:
481 ast2400_configure_mac(priv->scu, 2);
482 break;
483 case ASPEED_CLK_GATE_SDCLK:
484 ast2400_enable_sdclk(priv->scu);
485 break;
486 case ASPEED_CLK_GATE_SDEXTCLK:
487 ast2400_enable_extsdclk(priv->scu);
488 break;
489 default:
490 pr_debug("can't enable clk \n");
491 return -ENOENT;
492 break;
493 }
494
495 return 0;
496 }
497
498 struct clk_ops ast2400_clk_ops = {
499 .get_rate = ast2400_clk_get_rate,
500 .set_rate = ast2400_clk_set_rate,
501 .enable = ast2400_clk_enable,
502 };
503
ast2400_clk_probe(struct udevice * dev)504 static int ast2400_clk_probe(struct udevice *dev)
505 {
506 struct ast2400_clk_priv *priv = dev_get_priv(dev);
507
508 priv->scu = devfdt_get_addr_ptr(dev);
509 if (IS_ERR(priv->scu))
510 return PTR_ERR(priv->scu);
511
512 return 0;
513 }
514
ast2400_clk_bind(struct udevice * dev)515 static int ast2400_clk_bind(struct udevice *dev)
516 {
517 int ret;
518
519 /* The reset driver does not have a device node, so bind it here */
520 ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev);
521 if (ret)
522 debug("Warning: No reset driver: ret=%d\n", ret);
523
524 return 0;
525 }
526
527 #if CONFIG_IS_ENABLED(CMD_CLK)
528 struct aspeed_clks {
529 ulong id;
530 const char *name;
531 };
532
533 static struct aspeed_clks aspeed_clk_names[] = {
534 { ASPEED_CLK_UART, "uart" },
535 { ASPEED_CLK_HPLL, "hpll" },
536 { ASPEED_CLK_MPLL, "mpll" },
537 { ASPEED_CLK_D2PLL, "d2pll" },
538 { ASPEED_CLK_AHB, "hclk" },
539 { ASPEED_CLK_APB, "pclk" },
540 };
541
soc_clk_dump(void)542 int soc_clk_dump(void)
543 {
544 struct udevice *dev;
545 struct clk clk;
546 unsigned long rate;
547 int i, ret;
548
549 ret = uclass_get_device_by_driver(UCLASS_CLK,
550 DM_GET_DRIVER(aspeed_scu), &dev);
551 if (ret)
552 return ret;
553
554 printf("Clk\t\tHz\n");
555
556 for (i = 0; i < ARRAY_SIZE(aspeed_clk_names); i++) {
557 clk.id = aspeed_clk_names[i].id;
558 ret = clk_request(dev, &clk);
559 if (ret < 0) {
560 debug("%s clk_request() failed: %d\n", __func__, ret);
561 continue;
562 }
563
564 ret = clk_get_rate(&clk);
565 rate = ret;
566
567 clk_free(&clk);
568
569 if (ret == -ENOTSUPP) {
570 printf("clk ID %lu not supported yet\n",
571 aspeed_clk_names[i].id);
572 continue;
573 }
574 if (ret < 0) {
575 printf("%s %lu: get_rate err: %d\n",
576 __func__, aspeed_clk_names[i].id, ret);
577 continue;
578 }
579
580 printf("%s(%3lu):\t%lu\n",
581 aspeed_clk_names[i].name, aspeed_clk_names[i].id, rate);
582 }
583
584 return 0;
585 }
586 #endif
587
588 static const struct udevice_id ast2400_clk_ids[] = {
589 { .compatible = "aspeed,ast2400-scu" },
590 { }
591 };
592
593 U_BOOT_DRIVER(aspeed_scu) = {
594 .name = "aspeed_scu",
595 .id = UCLASS_CLK,
596 .of_match = ast2400_clk_ids,
597 .priv_auto_alloc_size = sizeof(struct ast2400_clk_priv),
598 .ops = &ast2400_clk_ops,
599 .bind = ast2400_clk_bind,
600 .probe = ast2400_clk_probe,
601 };
602