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