1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * (C) Copyright 2016 Google, Inc
4 *
5 * Copyright (C) ASPEED Technology Inc.
6 *
7 */
8
9 #include <common.h>
10 #include <clk-uclass.h>
11 #include <dm.h>
12 #include <asm/io.h>
13 #include <dm/lists.h>
14 #include <asm/arch/scu_ast2500.h>
15 #include <dt-bindings/clock/ast2500-clock.h>
16 #include <dt-bindings/reset/ast2500-reset.h>
17
18 /*
19 * MAC Clock Delay settings, taken from Aspeed SDK
20 */
21 #define RGMII_TXCLK_ODLY 8
22 #define RMII_RXCLK_IDLY 2
23
24 /*
25 * TGMII Clock Duty constants, taken from Aspeed SDK
26 */
27 #define RGMII2_TXCK_DUTY 0x66
28 #define RGMII1_TXCK_DUTY 0x64
29
30 #define D2PLL_DEFAULT_RATE (250 * 1000 * 1000)
31
32 DECLARE_GLOBAL_DATA_PTR;
33
34 /*
35 * Clock divider/multiplier configuration struct.
36 * For H-PLL and M-PLL the formula is
37 * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
38 * M - Numerator
39 * N - Denumerator
40 * P - Post Divider
41 * They have the same layout in their control register.
42 *
43 * D-PLL and D2-PLL have extra divider (OD + 1), which is not
44 * yet needed and ignored by clock configurations.
45 */
46 struct ast2500_div_config {
47 unsigned int num;
48 unsigned int denum;
49 unsigned int post_div;
50 };
51
ast2500_get_clkin(struct ast2500_scu * scu)52 extern u32 ast2500_get_clkin(struct ast2500_scu *scu)
53 {
54 return readl(&scu->hwstrap) & SCU_HWSTRAP_CLKIN_25MHZ
55 ? 25 * 1000 * 1000 : 24 * 1000 * 1000;
56 }
57
58 /*
59 * Get the rate of the M-PLL clock from input clock frequency and
60 * the value of the M-PLL Parameter Register.
61 */
ast2500_get_mpll_rate(struct ast2500_scu * scu)62 extern u32 ast2500_get_mpll_rate(struct ast2500_scu *scu)
63 {
64 u32 clkin = ast2500_get_clkin(scu);
65 u32 mpll_reg = readl(&scu->m_pll_param);
66
67 const ulong num = (mpll_reg & SCU_MPLL_NUM_MASK) >> SCU_MPLL_NUM_SHIFT;
68 const ulong denum = (mpll_reg & SCU_MPLL_DENUM_MASK)
69 >> SCU_MPLL_DENUM_SHIFT;
70 const ulong post_div = (mpll_reg & SCU_MPLL_POST_MASK)
71 >> SCU_MPLL_POST_SHIFT;
72
73 return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1);
74 }
75
76 /*
77 * Get the rate of the H-PLL clock from input clock frequency and
78 * the value of the H-PLL Parameter Register.
79 */
ast2500_get_hpll_rate(struct ast2500_scu * scu)80 extern u32 ast2500_get_hpll_rate(struct ast2500_scu *scu)
81 {
82 u32 clkin = ast2500_get_clkin(scu);
83 u32 hpll_reg = readl(&scu->h_pll_param);
84
85 /* F = clkin * [(M+1) / (N+1)] / (P + 1) */
86 const ulong num = (hpll_reg & SCU_HPLL_NUM_MASK) >> SCU_HPLL_NUM_SHIFT;
87 const ulong denum = (hpll_reg & SCU_HPLL_DENUM_MASK)
88 >> SCU_HPLL_DENUM_SHIFT;
89 const ulong post_div = (hpll_reg & SCU_HPLL_POST_MASK)
90 >> SCU_HPLL_POST_SHIFT;
91
92 return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1);
93 }
94
95 /*
96 * Get the rate of the D-PLL clock from input clock frequency and
97 * the value of the D-PLL Parameter Register.
98 */
ast2500_get_dpll_rate(struct ast2500_scu * scu)99 extern u32 ast2500_get_dpll_rate(struct ast2500_scu *scu)
100 {
101 u32 clkin = ast2500_get_clkin(scu);
102 u32 dpll_reg = readl(&scu->d_pll_param);
103
104 /* F = clkin * [(M+1) / (N+1)] / (P + 1)/ (od + 1) */
105 const ulong num = (dpll_reg & 0xff);
106 const ulong denum = (dpll_reg >> 8) & 0x1f;
107 const ulong post_div = (dpll_reg >> 13) & 0x3f;
108 const ulong od_div = (dpll_reg >> 19) & 0x7;
109 return (((clkin * ((num + 1) / (denum + 1))) / (post_div + 1))/ (od_div + 1));
110 }
111
112 /*
113 * Get the rate of the D2-PLL clock from input clock frequency and
114 * the value of the D2-PLL Parameter Register.
115 */
ast2500_get_d2pll_rate(struct ast2500_scu * scu)116 extern u32 ast2500_get_d2pll_rate(struct ast2500_scu *scu)
117 {
118 u32 clkin = ast2500_get_clkin(scu);
119 u32 d2pll_reg = readl(&scu->d2_pll_param);
120
121 /* F = clkin * [(M+1) / (N+1)] / (P + 1)/ (od + 1) */
122 const ulong num = (d2pll_reg & 0xff);
123 const ulong denum = (d2pll_reg >> 8) & 0x1f;
124 const ulong post_div = (d2pll_reg >> 13) & 0x3f;
125 const ulong od_div = (d2pll_reg >> 19) & 0x7 ;
126
127 return (((clkin * ((num + 1) / (denum + 1))) / (post_div + 1))/ (od_div + 1));
128 }
129
130 #define SCU_HWSTRAP_AXIAHB_DIV_SHIFT 9
131 #define SCU_HWSTRAP_AXIAHB_DIV_MASK (0x7 << SCU_HWSTRAP_AXIAHB_DIV_SHIFT)
132
ast2500_get_hclk(struct ast2500_scu * scu)133 static u32 ast2500_get_hclk(struct ast2500_scu *scu)
134 {
135 ulong ahb_div = 1 + ((readl(&scu->hwstrap)
136 & SCU_HWSTRAP_AXIAHB_DIV_MASK)
137 >> SCU_HWSTRAP_AXIAHB_DIV_SHIFT);
138
139 ulong axi_div = 2;
140 u32 rate = 0;
141
142 rate = ast2500_get_hpll_rate(scu);
143 return (rate / axi_div / ahb_div);
144 }
145
ast2500_get_pclk(struct ast2500_scu * scu)146 static u32 ast2500_get_pclk(struct ast2500_scu *scu)
147 {
148 u32 rate = 0;
149 ulong apb_div = 4 + 4 * ((readl(&scu->clk_sel1)
150 & SCU_PCLK_DIV_MASK)
151 >> SCU_PCLK_DIV_SHIFT);
152 rate = ast2500_get_hpll_rate(scu);
153
154 return (rate / apb_div);
155 }
156
ast2500_get_sdio_clk_rate(struct ast2500_scu * scu)157 static u32 ast2500_get_sdio_clk_rate(struct ast2500_scu *scu)
158 {
159 u32 clkin = ast2500_get_hpll_rate(scu);
160 u32 clk_sel = readl(&scu->clk_sel1);
161 u32 div = (clk_sel >> 12) & 0x7;
162
163 div = (div + 1) << 2;
164
165 return (clkin / div);
166 }
167
ast2500_get_uart_clk_rate(struct ast2500_scu * scu,int uart_idx)168 static u32 ast2500_get_uart_clk_rate(struct ast2500_scu *scu, int uart_idx)
169 {
170 /*
171 * ast2500 datasheet is very confusing when it comes to UART clocks,
172 * especially when CLKIN = 25 MHz. The settings are in
173 * different registers and it is unclear how they interact.
174 *
175 * This has only been tested with default settings and CLKIN = 24 MHz.
176 */
177 u32 uart_clkin;
178
179 if (readl(&scu->misc_ctrl2) &
180 (1 << (uart_idx - 1 + SCU_MISC2_UARTCLK_SHIFT)))
181 uart_clkin = 192 * 1000 * 1000;
182 else
183 uart_clkin = 24 * 1000 * 1000;
184
185 if (readl(&scu->misc_ctrl1) & SCU_MISC_UARTCLK_DIV13)
186 uart_clkin /= 13;
187
188 return uart_clkin;
189 }
190
ast2500_clk_get_rate(struct clk * clk)191 static ulong ast2500_clk_get_rate(struct clk *clk)
192 {
193 struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
194 ulong rate;
195
196 switch (clk->id) {
197 case ASPEED_CLK_HPLL:
198 rate = ast2500_get_hpll_rate(priv->scu);
199 break;
200 case ASPEED_CLK_MPLL:
201 rate = ast2500_get_mpll_rate(priv->scu);
202 break;
203 case ASPEED_CLK_DPLL:
204 rate = ast2500_get_dpll_rate(priv->scu);
205 break;
206 case ASPEED_CLK_D2PLL:
207 rate = ast2500_get_d2pll_rate(priv->scu);
208 break;
209 case ASPEED_CLK_AHB:
210 rate = ast2500_get_hclk(priv->scu);
211 break;
212 case ASPEED_CLK_APB:
213 rate = ast2500_get_pclk(priv->scu);
214 break;
215 case ASPEED_CLK_GATE_UART1CLK:
216 rate = ast2500_get_uart_clk_rate(priv->scu, 1);
217 break;
218 case ASPEED_CLK_GATE_UART2CLK:
219 rate = ast2500_get_uart_clk_rate(priv->scu, 2);
220 break;
221 case ASPEED_CLK_GATE_UART3CLK:
222 rate = ast2500_get_uart_clk_rate(priv->scu, 3);
223 break;
224 case ASPEED_CLK_GATE_UART4CLK:
225 rate = ast2500_get_uart_clk_rate(priv->scu, 4);
226 break;
227 case ASPEED_CLK_GATE_UART5CLK:
228 rate = ast2500_get_uart_clk_rate(priv->scu, 5);
229 break;
230 case ASPEED_CLK_SDIO:
231 rate = ast2500_get_sdio_clk_rate(priv->scu);
232 break;
233 default:
234 pr_debug("can't get clk rate \n");
235 return -ENOENT;
236 break;
237 }
238
239 return rate;
240 }
241
242 struct ast2500_clock_config {
243 ulong input_rate;
244 ulong rate;
245 struct ast2500_div_config cfg;
246 };
247
248 static const struct ast2500_clock_config ast2500_clock_config_defaults[] = {
249 { 24000000, 250000000, { .num = 124, .denum = 1, .post_div = 5 } },
250 };
251
ast2500_get_clock_config_default(ulong input_rate,ulong requested_rate,struct ast2500_div_config * cfg)252 static bool ast2500_get_clock_config_default(ulong input_rate,
253 ulong requested_rate,
254 struct ast2500_div_config *cfg)
255 {
256 int i;
257
258 for (i = 0; i < ARRAY_SIZE(ast2500_clock_config_defaults); i++) {
259 const struct ast2500_clock_config *default_cfg =
260 &ast2500_clock_config_defaults[i];
261 if (default_cfg->input_rate == input_rate &&
262 default_cfg->rate == requested_rate) {
263 *cfg = default_cfg->cfg;
264 return true;
265 }
266 }
267
268 return false;
269 }
270
271 /*
272 * @input_rate - the rate of input clock in Hz
273 * @requested_rate - desired output rate in Hz
274 * @div - this is an IN/OUT parameter, at input all fields of the config
275 * need to be set to their maximum allowed values.
276 * The result (the best config we could find), would also be returned
277 * in this structure.
278 *
279 * @return The clock rate, when the resulting div_config is used.
280 */
ast2500_calc_clock_config(ulong input_rate,ulong requested_rate,struct ast2500_div_config * cfg)281 static ulong ast2500_calc_clock_config(ulong input_rate, ulong requested_rate,
282 struct ast2500_div_config *cfg)
283 {
284 /*
285 * The assumption is that kHz precision is good enough and
286 * also enough to avoid overflow when multiplying.
287 */
288 const ulong input_rate_khz = input_rate / 1000;
289 const ulong rate_khz = requested_rate / 1000;
290 const struct ast2500_div_config max_vals = *cfg;
291 struct ast2500_div_config it = { 0, 0, 0 };
292 ulong delta = rate_khz;
293 ulong new_rate_khz = 0;
294
295 /*
296 * Look for a well known frequency first.
297 */
298 if (ast2500_get_clock_config_default(input_rate, requested_rate, cfg))
299 return requested_rate;
300
301 for (; it.denum <= max_vals.denum; ++it.denum) {
302 for (it.post_div = 0; it.post_div <= max_vals.post_div;
303 ++it.post_div) {
304 it.num = (rate_khz * (it.post_div + 1) / input_rate_khz)
305 * (it.denum + 1);
306 if (it.num > max_vals.num)
307 continue;
308
309 new_rate_khz = (input_rate_khz
310 * ((it.num + 1) / (it.denum + 1)))
311 / (it.post_div + 1);
312
313 /* Keep the rate below requested one. */
314 if (new_rate_khz > rate_khz)
315 continue;
316
317 if (new_rate_khz - rate_khz < delta) {
318 delta = new_rate_khz - rate_khz;
319 *cfg = it;
320 if (delta == 0)
321 return new_rate_khz * 1000;
322 }
323 }
324 }
325
326 return new_rate_khz * 1000;
327 }
328
ast2500_configure_ddr(struct ast2500_scu * scu,ulong rate)329 static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
330 {
331 ulong clkin = ast2500_get_clkin(scu);
332 u32 mpll_reg;
333 struct ast2500_div_config div_cfg = {
334 .num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT),
335 .denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT),
336 .post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT),
337 };
338
339 ast2500_calc_clock_config(clkin, rate, &div_cfg);
340
341 mpll_reg = readl(&scu->m_pll_param);
342 mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK
343 | SCU_MPLL_DENUM_MASK);
344 mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
345 | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
346 | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
347
348 writel(mpll_reg, &scu->m_pll_param);
349
350 return ast2500_get_mpll_rate(scu);
351 }
352
ast2500_configure_d2pll(struct ast2500_scu * scu,ulong rate)353 static ulong ast2500_configure_d2pll(struct ast2500_scu *scu, ulong rate)
354 {
355 /*
356 * The values and the meaning of the next three
357 * parameters are undocumented. Taken from Aspeed SDK.
358 *
359 * TODO(clg@kaod.org): the SIP and SIC values depend on the
360 * Numerator value
361 */
362 const u32 d2_pll_ext_param = 0x2c;
363 const u32 d2_pll_sip = 0x11;
364 const u32 d2_pll_sic = 0x18;
365 struct ast2500_div_config div_cfg = {
366 .num = SCU_D2PLL_NUM_MASK >> SCU_D2PLL_NUM_SHIFT,
367 .denum = SCU_D2PLL_DENUM_MASK >> SCU_D2PLL_DENUM_SHIFT,
368 .post_div = SCU_D2PLL_POST_MASK >> SCU_D2PLL_POST_SHIFT,
369 };
370 ulong clkin = ast2500_get_clkin(scu);
371 ulong new_rate;
372
373 writel((d2_pll_ext_param << SCU_D2PLL_EXT1_PARAM_SHIFT)
374 | SCU_D2PLL_EXT1_OFF
375 | SCU_D2PLL_EXT1_RESET, &scu->d2_pll_ext_param[0]);
376
377 /*
378 * Select USB2.0 port1 PHY clock as a clock source for GCRT.
379 * This would disconnect it from D2-PLL.
380 */
381 clrsetbits_le32(&scu->misc_ctrl1, SCU_MISC_D2PLL_OFF,
382 SCU_MISC_GCRT_USB20CLK);
383
384 new_rate = ast2500_calc_clock_config(clkin, rate, &div_cfg);
385 writel((d2_pll_sip << SCU_D2PLL_SIP_SHIFT)
386 | (d2_pll_sic << SCU_D2PLL_SIC_SHIFT)
387 | (div_cfg.num << SCU_D2PLL_NUM_SHIFT)
388 | (div_cfg.denum << SCU_D2PLL_DENUM_SHIFT)
389 | (div_cfg.post_div << SCU_D2PLL_POST_SHIFT),
390 &scu->d2_pll_param);
391
392 clrbits_le32(&scu->d2_pll_ext_param[0],
393 SCU_D2PLL_EXT1_OFF | SCU_D2PLL_EXT1_RESET);
394
395 clrsetbits_le32(&scu->misc_ctrl2,
396 SCU_MISC2_RGMII_HPLL | SCU_MISC2_RMII_MPLL
397 | SCU_MISC2_RGMII_CLKDIV_MASK |
398 SCU_MISC2_RMII_CLKDIV_MASK,
399 (4 << SCU_MISC2_RMII_CLKDIV_SHIFT));
400
401 return new_rate;
402 }
403
ast2500_clk_set_rate(struct clk * clk,ulong rate)404 static unsigned long ast2500_clk_set_rate(struct clk *clk, ulong rate)
405 {
406 struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
407
408 ulong new_rate;
409 switch (clk->id) {
410 //mpll
411 case ASPEED_CLK_MPLL:
412 new_rate = ast2500_configure_ddr(priv->scu, rate);
413 // printf("ast2500_clk_set_rate mpll %ld \n", new_rate);
414 break;
415 case ASPEED_CLK_D2PLL:
416 new_rate = ast2500_configure_d2pll(priv->scu, rate);
417 // printf("ast2500_clk_set_rate d2pll ==== %ld \n", new_rate);
418 break;
419 default:
420 return -ENOENT;
421 }
422
423 return new_rate;
424 }
425
426 #define SCU_CLKSTOP_MAC1 (20)
427 #define SCU_CLKSTOP_MAC2 (21)
428
ast2500_configure_mac(struct ast2500_scu * scu,int index)429 static ulong ast2500_configure_mac(struct ast2500_scu *scu, int index)
430 {
431 ulong hpll_rate = ast2500_get_hpll_rate(scu);
432 ulong required_rate;
433 u32 hwstrap;
434 u32 divisor;
435 u32 reset_bit;
436 u32 clkstop_bit;
437 u32 clk_delay_settings =
438 (RMII_RXCLK_IDLY << SCU_MICDS_MAC1RMII_RDLY_SHIFT)
439 | (RMII_RXCLK_IDLY << SCU_MICDS_MAC2RMII_RDLY_SHIFT)
440 | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT)
441 | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT);
442
443 /*
444 * According to data sheet, for 10/100 mode the MAC clock frequency
445 * should be at least 25MHz and for 1000 mode at least 100MHz
446 */
447 hwstrap = readl(&scu->hwstrap);
448 if (hwstrap & (SCU_HWSTRAP_MAC1_RGMII | SCU_HWSTRAP_MAC2_RGMII))
449 required_rate = 100 * 1000 * 1000;
450 else
451 required_rate = 25 * 1000 * 1000;
452
453 divisor = hpll_rate / required_rate;
454
455 if (divisor < 4) {
456 /* Clock can't run fast enough, but let's try anyway */
457 debug("MAC clock too slow\n");
458 divisor = 4;
459 } else if (divisor > 16) {
460 /* Can't slow down the clock enough, but let's try anyway */
461 debug("MAC clock too fast\n");
462 divisor = 16;
463 }
464
465 switch (index) {
466 case 1:
467 reset_bit = BIT(ASPEED_RESET_MAC1);
468 clkstop_bit = BIT(SCU_CLKSTOP_MAC1);
469 break;
470 case 2:
471 reset_bit = BIT(ASPEED_RESET_MAC2);
472 clkstop_bit = BIT(SCU_CLKSTOP_MAC2);
473 break;
474 default:
475 return -EINVAL;
476 }
477
478 clrsetbits_le32(&scu->clk_sel1, SCU_MACCLK_MASK,
479 ((divisor - 2) / 2) << SCU_MACCLK_SHIFT);
480
481 /*
482 * Disable MAC, start its clock and re-enable it.
483 * The procedure and the delays (100us & 10ms) are
484 * specified in the datasheet.
485 */
486 setbits_le32(&scu->sysreset_ctrl1, reset_bit);
487 udelay(100);
488 clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
489 mdelay(10);
490 clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
491
492 writel((RGMII2_TXCK_DUTY << SCU_CLKDUTY_RGMII2TXCK_SHIFT)
493 | (RGMII1_TXCK_DUTY << SCU_CLKDUTY_RGMII1TXCK_SHIFT),
494 &scu->clk_duty_sel);
495
496 writel(clk_delay_settings | SCU_MICDS_RGMIIPLL, &scu->mac_clk_delay);
497 writel(clk_delay_settings, &scu->mac_clk_delay_100M);
498 writel(clk_delay_settings, &scu->mac_clk_delay_10M);
499
500 return required_rate;
501 }
502
503 #define SCU_CLKSTOP_SDIO 27
ast2500_enable_sdclk(struct ast2500_scu * scu)504 static ulong ast2500_enable_sdclk(struct ast2500_scu *scu)
505 {
506 u32 reset_bit;
507 u32 clkstop_bit;
508
509 reset_bit = BIT(ASEPPD_RESET_SDIO);
510 clkstop_bit = BIT(SCU_CLKSTOP_SDIO);
511
512 setbits_le32(&scu->sysreset_ctrl1, reset_bit);
513 udelay(100);
514 //enable clk
515 clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
516 mdelay(10);
517 clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
518
519 return 0;
520 }
521
522 #define SCU_CLKSTOP_EXTSD 15
523 #define SCU_CLK_SD_MASK (0x7 << 12)
524 #define SCU_CLK_SD_DIV(x) (x << 12)
525
ast2500_enable_extsdclk(struct ast2500_scu * scu)526 static ulong ast2500_enable_extsdclk(struct ast2500_scu *scu)
527 {
528 u32 clk_sel = readl(&scu->clk_sel1);
529 u32 enableclk_bit;
530
531 enableclk_bit = BIT(SCU_CLKSTOP_EXTSD);
532
533 // SDCLK = G4 H-PLL / 4, G5 = H-PLL /8
534 clk_sel &= ~SCU_CLK_SD_MASK;
535 clk_sel |= SCU_CLK_SD_DIV(1);
536 writel(clk_sel, &scu->clk_sel1);
537
538 //enable clk
539 setbits_le32(&scu->clk_sel1, enableclk_bit);
540
541 return 0;
542 }
543
ast2500_enable_usbahclk(struct ast2500_scu * scu)544 static ulong ast2500_enable_usbahclk(struct ast2500_scu *scu)
545 {
546 u32 reset_bit;
547 u32 clkstop_bit;
548
549 reset_bit = BIT(ASPEED_RESET_EHCI_P1);
550 clkstop_bit = BIT(14);
551
552 setbits_le32(&scu->sysreset_ctrl1, reset_bit);
553 udelay(100);
554 setbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
555 mdelay(20);
556
557 clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
558
559 return 0;
560 }
561
ast2500_enable_usbbhclk(struct ast2500_scu * scu)562 static ulong ast2500_enable_usbbhclk(struct ast2500_scu *scu)
563 {
564 u32 reset_bit;
565 u32 clkstop_bit;
566
567 reset_bit = BIT(ASPEED_RESET_EHCI_P2);
568 clkstop_bit = BIT(7);
569
570 setbits_le32(&scu->sysreset_ctrl1, reset_bit);
571 udelay(100);
572 clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
573 mdelay(20);
574
575 clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
576
577 return 0;
578 }
579
ast2500_clk_enable(struct clk * clk)580 static int ast2500_clk_enable(struct clk *clk)
581 {
582 struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
583
584 switch (clk->id) {
585 /*
586 * For MAC clocks the clock rate is
587 * configured based on whether RGMII or RMII mode has been selected
588 * through hardware strapping.
589 */
590 case ASPEED_CLK_GATE_MAC1CLK:
591 ast2500_configure_mac(priv->scu, 1);
592 break;
593 case ASPEED_CLK_GATE_MAC2CLK:
594 ast2500_configure_mac(priv->scu, 2);
595 break;
596 case ASPEED_CLK_D2PLL:
597 ast2500_configure_d2pll(priv->scu, D2PLL_DEFAULT_RATE);
598 break;
599 case ASPEED_CLK_GATE_SDCLK:
600 ast2500_enable_sdclk(priv->scu);
601 break;
602 case ASPEED_CLK_GATE_SDEXTCLK:
603 ast2500_enable_extsdclk(priv->scu);
604 break;
605 case ASPEED_CLK_GATE_USBPORT1CLK:
606 ast2500_enable_usbahclk(priv->scu);
607 break;
608 case ASPEED_CLK_GATE_USBPORT2CLK:
609 ast2500_enable_usbbhclk(priv->scu);
610 break;
611 default:
612 pr_debug("can't enable clk \n");
613 return -ENOENT;
614 break;
615 }
616
617 return 0;
618 }
619
620 struct clk_ops ast2500_clk_ops = {
621 .get_rate = ast2500_clk_get_rate,
622 .set_rate = ast2500_clk_set_rate,
623 .enable = ast2500_clk_enable,
624 };
625
ast2500_clk_probe(struct udevice * dev)626 static int ast2500_clk_probe(struct udevice *dev)
627 {
628 struct ast2500_clk_priv *priv = dev_get_priv(dev);
629
630 priv->scu = devfdt_get_addr_ptr(dev);
631 if (IS_ERR(priv->scu))
632 return PTR_ERR(priv->scu);
633
634 return 0;
635 }
636
ast2500_clk_bind(struct udevice * dev)637 static int ast2500_clk_bind(struct udevice *dev)
638 {
639 int ret;
640
641 /* The reset driver does not have a device node, so bind it here */
642 ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev);
643 if (ret)
644 debug("Warning: No reset driver: ret=%d\n", ret);
645
646 return 0;
647 }
648
649 #if CONFIG_IS_ENABLED(CMD_CLK)
650 struct aspeed_clks {
651 ulong id;
652 const char *name;
653 };
654
655 static struct aspeed_clks aspeed_clk_names[] = {
656 { ASPEED_CLK_HPLL, "hpll" },
657 { ASPEED_CLK_MPLL, "mpll" },
658 { ASPEED_CLK_DPLL, "dpll" },
659 { ASPEED_CLK_D2PLL, "d2pll" },
660 { ASPEED_CLK_AHB, "hclk" },
661 { ASPEED_CLK_APB, "pclk" },
662 };
663
soc_clk_dump(void)664 int soc_clk_dump(void)
665 {
666 struct udevice *dev;
667 struct clk clk;
668 unsigned long rate;
669 int i, ret;
670
671 ret = uclass_get_device_by_driver(UCLASS_CLK,
672 DM_GET_DRIVER(aspeed_scu), &dev);
673 if (ret)
674 return ret;
675
676 printf("Clk\t\tHz\n");
677
678 for (i = 0; i < ARRAY_SIZE(aspeed_clk_names); i++) {
679 clk.id = aspeed_clk_names[i].id;
680 ret = clk_request(dev, &clk);
681 if (ret < 0) {
682 debug("%s clk_request() failed: %d\n", __func__, ret);
683 continue;
684 }
685
686 ret = clk_get_rate(&clk);
687 rate = ret;
688
689 clk_free(&clk);
690
691 if (ret == -ENOTSUPP) {
692 printf("clk ID %lu not supported yet\n",
693 aspeed_clk_names[i].id);
694 continue;
695 }
696 if (ret < 0) {
697 printf("%s %lu: get_rate err: %d\n",
698 __func__, aspeed_clk_names[i].id, ret);
699 continue;
700 }
701
702 printf("%s(%3lu):\t%lu\n",
703 aspeed_clk_names[i].name, aspeed_clk_names[i].id, rate);
704 }
705
706 return 0;
707 }
708 #endif
709
710 static const struct udevice_id ast2500_clk_ids[] = {
711 { .compatible = "aspeed,ast2500-scu" },
712 { }
713 };
714
715 U_BOOT_DRIVER(aspeed_scu) = {
716 .name = "aspeed_scu",
717 .id = UCLASS_CLK,
718 .of_match = ast2500_clk_ids,
719 .priv_auto_alloc_size = sizeof(struct ast2500_clk_priv),
720 .ops = &ast2500_clk_ops,
721 .bind = ast2500_clk_bind,
722 .probe = ast2500_clk_probe,
723 };
724