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 /**
131  * Get current rate or uart clock
132  *
133  * @scu SCU registers
134  * @uart_index UART index, 1-5
135  *
136  * @return current setting for uart clock rate
137  */
138 static u32 ast2500_get_uart_clk_rate(struct ast2500_scu *scu, int uart_index)
139 {
140 	/*
141 	 * ast2500 datasheet is very confusing when it comes to UART clocks,
142 	 * especially when CLKIN = 25 MHz. The settings are in
143 	 * different registers and it is unclear how they interact.
144 	 *
145 	 * This has only been tested with default settings and CLKIN = 24 MHz.
146 	 */
147 	u32 uart_clkin;
148 
149 	if (readl(&scu->misc_ctrl2) &
150 	    (1 << (uart_index - 1 + SCU_MISC2_UARTCLK_SHIFT)))
151 		uart_clkin = 192 * 1000 * 1000;
152 	else
153 		uart_clkin = 24 * 1000 * 1000;
154 
155 	if (readl(&scu->misc_ctrl1) & SCU_MISC_UARTCLK_DIV13)
156 		uart_clkin /= 13;
157 
158 	return uart_clkin;
159 }
160 
161 static u32 ast2500_get_sdio_clk_rate(struct ast2500_scu *scu)
162 {
163 	u32 clkin = ast2500_get_hpll_rate(scu);
164 	u32 clk_sel = readl(&scu->clk_sel1);
165 	u32 div = (clk_sel >> 12) & 0x7;
166 
167 	div = (div + 1) << 2;
168 
169 	return (clkin / div);
170 }
171 
172 static unsigned long ast2500_clk_get_rate(struct clk *clk)
173 {
174 	struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
175 	ulong rate;
176 
177 	switch (clk->id) {
178 	//HPLL
179 	case ASPEED_CLK_HPLL:
180 		rate = ast2500_get_hpll_rate(priv->scu);
181 		break;
182 	//HCLK
183 	case ASPEED_CLK_AHB:
184 		{
185 			ulong ahb_div = 1 + ((readl(&priv->scu->hwstrap)
186 					      & SCU_HWSTRAP_AXIAHB_DIV_MASK)
187 					     >> SCU_HWSTRAP_AXIAHB_DIV_SHIFT);
188 			ulong axi_div = 2;
189 
190 			rate = ast2500_get_hpll_rate(priv->scu);
191 			rate = rate / axi_div / ahb_div;
192 		}
193 		break;
194 	//mpll
195 	case ASPEED_CLK_MPLL:
196 		rate = ast2500_get_mpll_rate(priv->scu);
197 		break;
198 	//pclk
199 	case ASPEED_CLK_APB:
200 		{
201 			ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
202 						  & SCU_PCLK_DIV_MASK)
203 						 >> SCU_PCLK_DIV_SHIFT);
204 			rate = ast2500_get_hpll_rate(priv->scu);
205 			rate = rate / apb_div;
206 		}
207 		break;
208 	case ASPEED_CLK_GATE_UART1CLK:
209 		rate = ast2500_get_uart_clk_rate(priv->scu, 1);
210 		break;
211 	case ASPEED_CLK_GATE_UART2CLK:
212 		rate = ast2500_get_uart_clk_rate(priv->scu, 2);
213 		break;
214 	case ASPEED_CLK_GATE_UART3CLK:
215 		rate = ast2500_get_uart_clk_rate(priv->scu, 3);
216 		break;
217 	case ASPEED_CLK_GATE_UART4CLK:
218 		rate = ast2500_get_uart_clk_rate(priv->scu, 4);
219 		break;
220 	case ASPEED_CLK_GATE_UART5CLK:
221 		rate = ast2500_get_uart_clk_rate(priv->scu, 5);
222 		break;
223 	case ASPEED_CLK_SDIO:
224 		rate = ast2500_get_sdio_clk_rate(priv->scu);
225 		break;
226 	default:
227 		pr_debug("can't get clk rate \n");
228 		return -ENOENT;
229 	}
230 
231 	return rate;
232 }
233 
234 struct ast2500_clock_config {
235 	ulong input_rate;
236 	ulong rate;
237 	struct ast2500_div_config cfg;
238 };
239 
240 static const struct ast2500_clock_config ast2500_clock_config_defaults[] = {
241 	{ 24000000, 250000000, { .num = 124, .denum = 1, .post_div = 5 } },
242 };
243 
244 static bool ast2500_get_clock_config_default(ulong input_rate,
245 					     ulong requested_rate,
246 					     struct ast2500_div_config *cfg)
247 {
248 	int i;
249 
250 	for (i = 0; i < ARRAY_SIZE(ast2500_clock_config_defaults); i++) {
251 		const struct ast2500_clock_config *default_cfg =
252 			&ast2500_clock_config_defaults[i];
253 		if (default_cfg->input_rate == input_rate &&
254 		    default_cfg->rate == requested_rate) {
255 			*cfg = default_cfg->cfg;
256 			return true;
257 		}
258 	}
259 
260 	return false;
261 }
262 
263 /*
264  * @input_rate - the rate of input clock in Hz
265  * @requested_rate - desired output rate in Hz
266  * @div - this is an IN/OUT parameter, at input all fields of the config
267  * need to be set to their maximum allowed values.
268  * The result (the best config we could find), would also be returned
269  * in this structure.
270  *
271  * @return The clock rate, when the resulting div_config is used.
272  */
273 static ulong ast2500_calc_clock_config(ulong input_rate, ulong requested_rate,
274 				       struct ast2500_div_config *cfg)
275 {
276 	/*
277 	 * The assumption is that kHz precision is good enough and
278 	 * also enough to avoid overflow when multiplying.
279 	 */
280 	const ulong input_rate_khz = input_rate / 1000;
281 	const ulong rate_khz = requested_rate / 1000;
282 	const struct ast2500_div_config max_vals = *cfg;
283 	struct ast2500_div_config it = { 0, 0, 0 };
284 	ulong delta = rate_khz;
285 	ulong new_rate_khz = 0;
286 
287 	/*
288 	 * Look for a well known frequency first.
289 	 */
290 	if (ast2500_get_clock_config_default(input_rate, requested_rate, cfg))
291 		return requested_rate;
292 
293 	for (; it.denum <= max_vals.denum; ++it.denum) {
294 		for (it.post_div = 0; it.post_div <= max_vals.post_div;
295 		     ++it.post_div) {
296 			it.num = (rate_khz * (it.post_div + 1) / input_rate_khz)
297 			    * (it.denum + 1);
298 			if (it.num > max_vals.num)
299 				continue;
300 
301 			new_rate_khz = (input_rate_khz
302 					* ((it.num + 1) / (it.denum + 1)))
303 			    / (it.post_div + 1);
304 
305 			/* Keep the rate below requested one. */
306 			if (new_rate_khz > rate_khz)
307 				continue;
308 
309 			if (new_rate_khz - rate_khz < delta) {
310 				delta = new_rate_khz - rate_khz;
311 				*cfg = it;
312 				if (delta == 0)
313 					return new_rate_khz * 1000;
314 			}
315 		}
316 	}
317 
318 	return new_rate_khz * 1000;
319 }
320 
321 static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
322 {
323 	ulong clkin = ast2500_get_clkin(scu);
324 	u32 mpll_reg;
325 	struct ast2500_div_config div_cfg = {
326 		.num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT),
327 		.denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT),
328 		.post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT),
329 	};
330 
331 	ast2500_calc_clock_config(clkin, rate, &div_cfg);
332 
333 	mpll_reg = readl(&scu->m_pll_param);
334 	mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK
335 		      | SCU_MPLL_DENUM_MASK);
336 	mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
337 	    | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
338 	    | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
339 
340 	writel(mpll_reg, &scu->m_pll_param);
341 
342 	return ast2500_get_mpll_rate(scu);
343 }
344 
345 static ulong ast2500_configure_d2pll(struct ast2500_scu *scu, ulong rate)
346 {
347 	/*
348 	 * The values and the meaning of the next three
349 	 * parameters are undocumented. Taken from Aspeed SDK.
350 	 *
351 	 * TODO(clg@kaod.org): the SIP and SIC values depend on the
352 	 * Numerator value
353 	 */
354 	const u32 d2_pll_ext_param = 0x2c;
355 	const u32 d2_pll_sip = 0x11;
356 	const u32 d2_pll_sic = 0x18;
357 	struct ast2500_div_config div_cfg = {
358 		.num = SCU_D2PLL_NUM_MASK >> SCU_D2PLL_NUM_SHIFT,
359 		.denum = SCU_D2PLL_DENUM_MASK >> SCU_D2PLL_DENUM_SHIFT,
360 		.post_div = SCU_D2PLL_POST_MASK >> SCU_D2PLL_POST_SHIFT,
361 	};
362 	ulong clkin = ast2500_get_clkin(scu);
363 	ulong new_rate;
364 
365 	writel((d2_pll_ext_param << SCU_D2PLL_EXT1_PARAM_SHIFT)
366 	       | SCU_D2PLL_EXT1_OFF
367 	       | SCU_D2PLL_EXT1_RESET, &scu->d2_pll_ext_param[0]);
368 
369 	/*
370 	 * Select USB2.0 port1 PHY clock as a clock source for GCRT.
371 	 * This would disconnect it from D2-PLL.
372 	 */
373 	clrsetbits_le32(&scu->misc_ctrl1, SCU_MISC_D2PLL_OFF,
374 			SCU_MISC_GCRT_USB20CLK);
375 
376 	new_rate = ast2500_calc_clock_config(clkin, rate, &div_cfg);
377 	writel((d2_pll_sip << SCU_D2PLL_SIP_SHIFT)
378 	       | (d2_pll_sic << SCU_D2PLL_SIC_SHIFT)
379 	       | (div_cfg.num << SCU_D2PLL_NUM_SHIFT)
380 	       | (div_cfg.denum << SCU_D2PLL_DENUM_SHIFT)
381 	       | (div_cfg.post_div << SCU_D2PLL_POST_SHIFT),
382 	       &scu->d2_pll_param);
383 
384 	clrbits_le32(&scu->d2_pll_ext_param[0],
385 		     SCU_D2PLL_EXT1_OFF | SCU_D2PLL_EXT1_RESET);
386 
387 	clrsetbits_le32(&scu->misc_ctrl2,
388 			SCU_MISC2_RGMII_HPLL | SCU_MISC2_RMII_MPLL
389 			| SCU_MISC2_RGMII_CLKDIV_MASK |
390 			SCU_MISC2_RMII_CLKDIV_MASK,
391 			(4 << SCU_MISC2_RMII_CLKDIV_SHIFT));
392 
393 	return new_rate;
394 }
395 
396 static unsigned long ast2500_clk_set_rate(struct clk *clk, ulong rate)
397 {
398 	struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
399 
400 	ulong new_rate;
401 	switch (clk->id) {
402 	//mpll
403 	case ASPEED_CLK_MPLL:
404 		new_rate = ast2500_configure_ddr(priv->scu, rate);
405 //		printf("ast2500_clk_set_rate mpll %ld \n", new_rate);
406 		break;
407 	case ASPEED_CLK_D2PLL:
408 		new_rate = ast2500_configure_d2pll(priv->scu, rate);
409 //		printf("ast2500_clk_set_rate d2pll ==== %ld \n", new_rate);
410 		break;
411 	default:
412 		return -ENOENT;
413 	}
414 
415 	return new_rate;
416 }
417 
418 #define SCU_CLKSTOP_MAC1		(20)
419 #define SCU_CLKSTOP_MAC2		(21)
420 
421 static ulong ast2500_configure_mac(struct ast2500_scu *scu, int index)
422 {
423 	ulong hpll_rate = ast2500_get_hpll_rate(scu);
424 	ulong required_rate;
425 	u32 hwstrap;
426 	u32 divisor;
427 	u32 reset_bit;
428 	u32 clkstop_bit;
429 	u32 clk_delay_settings =
430 		(RMII_RXCLK_IDLY << SCU_MICDS_MAC1RMII_RDLY_SHIFT)
431 		| (RMII_RXCLK_IDLY << SCU_MICDS_MAC2RMII_RDLY_SHIFT)
432 		| (RGMII_TXCLK_ODLY << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT)
433 		| (RGMII_TXCLK_ODLY << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT);
434 
435 	/*
436 	 * According to data sheet, for 10/100 mode the MAC clock frequency
437 	 * should be at least 25MHz and for 1000 mode at least 100MHz
438 	 */
439 	hwstrap = readl(&scu->hwstrap);
440 	if (hwstrap & (SCU_HWSTRAP_MAC1_RGMII | SCU_HWSTRAP_MAC2_RGMII))
441 		required_rate = 100 * 1000 * 1000;
442 	else
443 		required_rate = 25 * 1000 * 1000;
444 
445 	divisor = hpll_rate / required_rate;
446 
447 	if (divisor < 4) {
448 		/* Clock can't run fast enough, but let's try anyway */
449 		debug("MAC clock too slow\n");
450 		divisor = 4;
451 	} else if (divisor > 16) {
452 		/* Can't slow down the clock enough, but let's try anyway */
453 		debug("MAC clock too fast\n");
454 		divisor = 16;
455 	}
456 
457 	switch (index) {
458 	case 1:
459 		reset_bit = BIT(ASPEED_RESET_MAC1);
460 		clkstop_bit = BIT(SCU_CLKSTOP_MAC1);
461 		break;
462 	case 2:
463 		reset_bit = BIT(ASPEED_RESET_MAC2);
464 		clkstop_bit = BIT(SCU_CLKSTOP_MAC2);
465 		break;
466 	default:
467 		return -EINVAL;
468 	}
469 
470 	clrsetbits_le32(&scu->clk_sel1, SCU_MACCLK_MASK,
471 			((divisor - 2) / 2) << SCU_MACCLK_SHIFT);
472 
473 	/*
474 	 * Disable MAC, start its clock and re-enable it.
475 	 * The procedure and the delays (100us & 10ms) are
476 	 * specified in the datasheet.
477 	 */
478 	setbits_le32(&scu->sysreset_ctrl1, reset_bit);
479 	udelay(100);
480 	clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
481 	mdelay(10);
482 	clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
483 
484 	writel((RGMII2_TXCK_DUTY << SCU_CLKDUTY_RGMII2TXCK_SHIFT)
485 	       | (RGMII1_TXCK_DUTY << SCU_CLKDUTY_RGMII1TXCK_SHIFT),
486 	       &scu->clk_duty_sel);
487 
488 	writel(clk_delay_settings | SCU_MICDS_RGMIIPLL, &scu->mac_clk_delay);
489 	writel(clk_delay_settings, &scu->mac_clk_delay_100M);
490 	writel(clk_delay_settings, &scu->mac_clk_delay_10M);
491 
492 	return required_rate;
493 }
494 
495 #define SCU_CLKSTOP_SDIO 27
496 static ulong ast2500_enable_sdclk(struct ast2500_scu *scu)
497 {
498 	u32 reset_bit;
499 	u32 clkstop_bit;
500 
501 	reset_bit = BIT(ASEPPD_RESET_SDIO);
502 	clkstop_bit = BIT(SCU_CLKSTOP_SDIO);
503 
504 	setbits_le32(&scu->sysreset_ctrl1, reset_bit);
505 	udelay(100);
506 	//enable clk
507 	clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
508 	mdelay(10);
509 	clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
510 
511 	return 0;
512 }
513 
514 #define SCU_CLKSTOP_EXTSD 15
515 #define SCU_CLK_SD_MASK				(0x7 << 12)
516 #define SCU_CLK_SD_DIV(x)			(x << 12)
517 
518 static ulong ast2500_enable_extsdclk(struct ast2500_scu *scu)
519 {
520 	u32 clk_sel = readl(&scu->clk_sel1);
521 	u32 enableclk_bit;
522 
523 	enableclk_bit = BIT(SCU_CLKSTOP_EXTSD);
524 
525 	// SDCLK = G4  H-PLL / 4, G5 = H-PLL /8
526 	clk_sel &= ~SCU_CLK_SD_MASK;
527 	clk_sel |= SCU_CLK_SD_DIV(1);
528 	writel(clk_sel, &scu->clk_sel1);
529 
530 	//enable clk
531 	setbits_le32(&scu->clk_sel1, enableclk_bit);
532 
533 	return 0;
534 }
535 
536 static int ast2500_clk_enable(struct clk *clk)
537 {
538 	struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
539 
540 	switch (clk->id) {
541 	/*
542 	 * For MAC clocks the clock rate is
543 	 * configured based on whether RGMII or RMII mode has been selected
544 	 * through hardware strapping.
545 	 */
546 	case ASPEED_CLK_GATE_MAC1CLK:
547 		ast2500_configure_mac(priv->scu, 1);
548 		break;
549 	case ASPEED_CLK_GATE_MAC2CLK:
550 		ast2500_configure_mac(priv->scu, 2);
551 		break;
552 	case ASPEED_CLK_D2PLL:
553 		ast2500_configure_d2pll(priv->scu, D2PLL_DEFAULT_RATE);
554 		break;
555 	case ASPEED_CLK_GATE_SDCLK:
556 		ast2500_enable_sdclk(priv->scu);
557 		break;
558 	case ASPEED_CLK_GATE_SDEXTCLK:
559 		ast2500_enable_extsdclk(priv->scu);
560 		break;
561 	default:
562 		pr_debug("can't enable clk \n");
563 		return -ENOENT;
564 		break;
565 	}
566 
567 	return 0;
568 }
569 
570 struct clk_ops ast2500_clk_ops = {
571 	.get_rate = ast2500_clk_get_rate,
572 	.set_rate = ast2500_clk_set_rate,
573 	.enable = ast2500_clk_enable,
574 };
575 
576 static int ast2500_clk_probe(struct udevice *dev)
577 {
578 	struct ast2500_clk_priv *priv = dev_get_priv(dev);
579 
580 	priv->scu = devfdt_get_addr_ptr(dev);
581 	if (IS_ERR(priv->scu))
582 		return PTR_ERR(priv->scu);
583 
584 	return 0;
585 }
586 
587 static int ast2500_clk_bind(struct udevice *dev)
588 {
589 	int ret;
590 
591 	/* The reset driver does not have a device node, so bind it here */
592 	ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev);
593 	if (ret)
594 		debug("Warning: No reset driver: ret=%d\n", ret);
595 
596 	return 0;
597 }
598 
599 static const struct udevice_id ast2500_clk_ids[] = {
600 	{ .compatible = "aspeed,ast2500-scu" },
601 	{ }
602 };
603 
604 U_BOOT_DRIVER(aspeed_scu) = {
605 	.name		= "aspeed_scu",
606 	.id		= UCLASS_CLK,
607 	.of_match	= ast2500_clk_ids,
608 	.priv_auto_alloc_size = sizeof(struct ast2500_clk_priv),
609 	.ops		= &ast2500_clk_ops,
610 	.bind		= ast2500_clk_bind,
611 	.probe		= ast2500_clk_probe,
612 };
613