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 
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  */
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  */
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  */
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  */
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 
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 
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 
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 
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 
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 
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  */
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 
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 
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 
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 
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
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 
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 
544 static int ast2500_clk_enable(struct clk *clk)
545 {
546 	struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
547 
548 	switch (clk->id) {
549 	/*
550 	 * For MAC clocks the clock rate is
551 	 * configured based on whether RGMII or RMII mode has been selected
552 	 * through hardware strapping.
553 	 */
554 	case ASPEED_CLK_GATE_MAC1CLK:
555 		ast2500_configure_mac(priv->scu, 1);
556 		break;
557 	case ASPEED_CLK_GATE_MAC2CLK:
558 		ast2500_configure_mac(priv->scu, 2);
559 		break;
560 	case ASPEED_CLK_D2PLL:
561 		ast2500_configure_d2pll(priv->scu, D2PLL_DEFAULT_RATE);
562 		break;
563 	case ASPEED_CLK_GATE_SDCLK:
564 		ast2500_enable_sdclk(priv->scu);
565 		break;
566 	case ASPEED_CLK_GATE_SDEXTCLK:
567 		ast2500_enable_extsdclk(priv->scu);
568 		break;
569 	default:
570 		pr_debug("can't enable clk \n");
571 		return -ENOENT;
572 		break;
573 	}
574 
575 	return 0;
576 }
577 
578 struct clk_ops ast2500_clk_ops = {
579 	.get_rate = ast2500_clk_get_rate,
580 	.set_rate = ast2500_clk_set_rate,
581 	.enable = ast2500_clk_enable,
582 };
583 
584 static int ast2500_clk_probe(struct udevice *dev)
585 {
586 	struct ast2500_clk_priv *priv = dev_get_priv(dev);
587 
588 	priv->scu = devfdt_get_addr_ptr(dev);
589 	if (IS_ERR(priv->scu))
590 		return PTR_ERR(priv->scu);
591 
592 	return 0;
593 }
594 
595 static int ast2500_clk_bind(struct udevice *dev)
596 {
597 	int ret;
598 
599 	/* The reset driver does not have a device node, so bind it here */
600 	ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev);
601 	if (ret)
602 		debug("Warning: No reset driver: ret=%d\n", ret);
603 
604 	return 0;
605 }
606 
607 #if CONFIG_IS_ENABLED(CMD_CLK)
608 struct aspeed_clks {
609 	ulong id;
610 	const char *name;
611 };
612 
613 static struct aspeed_clks aspeed_clk_names[] = {
614 	{ ASPEED_CLK_HPLL, "hpll" },
615 	{ ASPEED_CLK_MPLL, "mpll" },
616 	{ ASPEED_CLK_DPLL, "dpll" },
617 	{ ASPEED_CLK_D2PLL, "d2pll" },
618 	{ ASPEED_CLK_AHB, "hclk" },
619 	{ ASPEED_CLK_APB, "pclk" },
620 };
621 
622 int soc_clk_dump(void)
623 {
624 	struct udevice *dev;
625 	struct clk clk;
626 	unsigned long rate;
627 	int i, ret;
628 
629 	ret = uclass_get_device_by_driver(UCLASS_CLK,
630 					  DM_GET_DRIVER(aspeed_scu), &dev);
631 	if (ret)
632 		return ret;
633 
634 	printf("Clk\t\tHz\n");
635 
636 	for (i = 0; i < ARRAY_SIZE(aspeed_clk_names); i++) {
637 		clk.id = aspeed_clk_names[i].id;
638 		ret = clk_request(dev, &clk);
639 		if (ret < 0) {
640 			debug("%s clk_request() failed: %d\n", __func__, ret);
641 			continue;
642 		}
643 
644 		ret = clk_get_rate(&clk);
645 		rate = ret;
646 
647 		clk_free(&clk);
648 
649 		if (ret == -ENOTSUPP) {
650 			printf("clk ID %lu not supported yet\n",
651 			       aspeed_clk_names[i].id);
652 			continue;
653 		}
654 		if (ret < 0) {
655 			printf("%s %lu: get_rate err: %d\n",
656 			       __func__, aspeed_clk_names[i].id, ret);
657 			continue;
658 		}
659 
660 		printf("%s(%3lu):\t%lu\n",
661 		       aspeed_clk_names[i].name, aspeed_clk_names[i].id, rate);
662 	}
663 
664 	return 0;
665 }
666 #endif
667 
668 static const struct udevice_id ast2500_clk_ids[] = {
669 	{ .compatible = "aspeed,ast2500-scu" },
670 	{ }
671 };
672 
673 U_BOOT_DRIVER(aspeed_scu) = {
674 	.name		= "aspeed_scu",
675 	.id		= UCLASS_CLK,
676 	.of_match	= ast2500_clk_ids,
677 	.priv_auto_alloc_size = sizeof(struct ast2500_clk_priv),
678 	.ops		= &ast2500_clk_ops,
679 	.bind		= ast2500_clk_bind,
680 	.probe		= ast2500_clk_probe,
681 };
682