xref: /openbmc/u-boot/drivers/clk/aspeed/clk_ast2600.c (revision 0735660ae420e38f707be144b2299b761341b638)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) ASPEED Technology Inc.
4  */
5 
6 #include <common.h>
7 #include <clk-uclass.h>
8 #include <dm.h>
9 #include <asm/io.h>
10 #include <dm/lists.h>
11 #include <asm/arch/scu_ast2600.h>
12 #include <dt-bindings/clock/ast2600-clock.h>
13 #include <dt-bindings/reset/ast2600-reset.h>
14 
15 /*
16  * MAC Clock Delay settings, taken from Aspeed SDK
17  */
18 #define RGMII_TXCLK_ODLY	8
19 #define RMII_RXCLK_IDLY		2
20 
21 #define MAC_DEF_DELAY_1G	0x00410410
22 #define MAC_DEF_DELAY_100M	0x00410410
23 #define MAC_DEF_DELAY_10M	0x00410410
24 
25 #define MAC34_DEF_DELAY_1G	0x00104208
26 #define MAC34_DEF_DELAY_100M	0x00104208
27 #define MAC34_DEF_DELAY_10M	0x00104208
28 
29 /*
30  * TGMII Clock Duty constants, taken from Aspeed SDK
31  */
32 #define RGMII2_TXCK_DUTY	0x66
33 #define RGMII1_TXCK_DUTY	0x64
34 
35 #define D2PLL_DEFAULT_RATE	(250 * 1000 * 1000)
36 
37 DECLARE_GLOBAL_DATA_PTR;
38 
39 /*
40  * Clock divider/multiplier configuration struct.
41  * For H-PLL and M-PLL the formula is
42  * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
43  * M - Numerator
44  * N - Denumerator
45  * P - Post Divider
46  * They have the same layout in their control register.
47  *
48  * D-PLL and D2-PLL have extra divider (OD + 1), which is not
49  * yet needed and ignored by clock configurations.
50  */
51 union ast2600_pll_reg {
52 	unsigned int w;
53 	struct {
54 		unsigned int m : 13;	/* 12:0  */
55 		unsigned int n : 6;	/* 18:13  */
56 		unsigned int p : 4;	/* 22:19  */
57 		unsigned int reserved : 9; /* 31:20  */
58 	} b;
59 };
60 
61 struct ast2600_pll_cfg {
62 	union ast2600_pll_reg reg;
63 	unsigned int ext_reg;
64 };
65 
66 struct ast2600_pll_desc {
67 	u32 in;
68 	u32 out;
69 	struct ast2600_pll_cfg cfg;
70 };
71 
72 static const struct ast2600_pll_desc ast2600_pll_lookup[] = {
73     {.in = AST2600_CLK_IN, .out = 400000000,
74     .cfg.reg.b.m = 95, .cfg.reg.b.n = 2, .cfg.reg.b.p = 1,
75     .cfg.ext_reg = 0x31,
76     },
77     {.in = AST2600_CLK_IN, .out = 200000000,
78     .cfg.reg.b.m = 127, .cfg.reg.b.n = 0, .cfg.reg.b.p = 15,
79     .cfg.ext_reg = 0x3f
80     },
81     {.in = AST2600_CLK_IN, .out = 334000000,
82     .cfg.reg.b.m = 667, .cfg.reg.b.n = 4, .cfg.reg.b.p = 9,
83     .cfg.ext_reg = 0x14d
84     },
85 
86     {.in = AST2600_CLK_IN, .out = 1000000000,
87     .cfg.reg.b.m = 119, .cfg.reg.b.n = 2, .cfg.reg.b.p = 0,
88     .cfg.ext_reg = 0x3d
89     },
90 
91     {.in = AST2600_CLK_IN, .out = 50000000,
92     .cfg.reg.b.m = 95, .cfg.reg.b.n = 2, .cfg.reg.b.p = 15,
93     .cfg.ext_reg = 0x31
94     },
95 };
96 
97 extern u32 ast2600_get_pll_rate(struct ast2600_scu *scu, int pll_idx)
98 {
99 	u32 clkin = AST2600_CLK_IN;
100 	u32 pll_reg = 0;
101 	unsigned int mult, div = 1;
102 
103 	switch(pll_idx) {
104 		case ASPEED_CLK_HPLL:
105 			pll_reg = readl(&scu->h_pll_param);
106 			break;
107 		case ASPEED_CLK_MPLL:
108 			pll_reg = readl(&scu->m_pll_param);
109 			break;
110 		case ASPEED_CLK_DPLL:
111 			pll_reg = readl(&scu->d_pll_param);
112 			break;
113 		case ASPEED_CLK_EPLL:
114 			pll_reg = readl(&scu->e_pll_param);
115 			break;
116 
117 	}
118 	if (pll_reg & BIT(24)) {
119 		/* Pass through mode */
120 		mult = div = 1;
121 	} else {
122 		/* F = 25Mhz * [(M + 2) / (n + 1)] / (p + 1) */
123 		union ast2600_pll_reg reg;
124 		reg.w = pll_reg;
125 		mult = (reg.b.m + 1) / (reg.b.n + 1);
126 		div = (reg.b.p + 1);
127 	}
128 	return ((clkin * mult)/div);
129 
130 }
131 
132 extern u32 ast2600_get_apll_rate(struct ast2600_scu *scu)
133 {
134 	u32 clkin = AST2600_CLK_IN;
135 	u32 apll_reg = readl(&scu->a_pll_param);
136 	unsigned int mult, div = 1;
137 
138 	if (apll_reg & BIT(20)) {
139 		/* Pass through mode */
140 		mult = div = 1;
141 	} else {
142 		/* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */
143 		u32 m = (apll_reg >> 5) & 0x3f;
144 		u32 od = (apll_reg >> 4) & 0x1;
145 		u32 n = apll_reg & 0xf;
146 
147 		mult = (2 - od) * (m + 2);
148 		div = n + 1;
149 	}
150 	return ((clkin * mult)/div);
151 }
152 
153 static u32 ast2600_a0_axi_ahb_div_table[] = {
154 	2, 2, 3, 5,
155 };
156 
157 static u32 ast2600_a1_axi_ahb_div_table[] = {
158 	4, 6, 2, 4,
159 };
160 
161 static u32 ast2600_get_hclk(struct ast2600_scu *scu)
162 {
163 	u32 hw_rev = readl(&scu->chip_id0);
164 	u32 hwstrap1 = readl(&scu->hwstrap1);
165 	u32 axi_div = 1;
166 	u32 ahb_div = 0;
167 	u32 rate = 0;
168 
169 	if(hwstrap1 & BIT(16))
170 		axi_div = 1;
171 	else
172 		axi_div = 2;
173 
174 	if (hw_rev & BIT(16))
175 		ahb_div = ast2600_a1_axi_ahb_div_table[(hwstrap1 >> 11) & 0x3];
176 	else
177 		ahb_div = ast2600_a0_axi_ahb_div_table[(hwstrap1 >> 11) & 0x3];
178 
179 	rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
180 
181 	return (rate / axi_div / ahb_div);
182 }
183 
184 static u32 ast2600_hpll_pclk_div_table[] = {
185 	4, 8, 12, 16, 20, 24, 28, 32,
186 };
187 
188 static u32 ast2600_get_pclk(struct ast2600_scu *scu)
189 {
190 	u32 clk_sel1 = readl(&scu->clk_sel1);
191 	u32 apb_div = ast2600_hpll_pclk_div_table[((clk_sel1 >> 23) & 0x7)];
192 	u32 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
193 
194 	return (rate / apb_div);
195 }
196 
197 static u32 ast2600_get_uxclk_rate(struct ast2600_scu *scu)
198 {
199 	u32 clk_in = 0;
200 	u32 uxclk_sel = readl(&scu->clk_sel4);
201 
202 	uxclk_sel &= 0x3;
203 	switch(uxclk_sel) {
204 		case 0:
205 			clk_in = ast2600_get_apll_rate(scu) / 4;
206 			break;
207 		case 1:
208 			clk_in = ast2600_get_apll_rate(scu) / 2;
209 			break;
210 		case 2:
211 			clk_in = ast2600_get_apll_rate(scu);
212 			break;
213 		case 3:
214 			clk_in = ast2600_get_hclk(scu);
215 			break;
216 	}
217 
218 	return clk_in;
219 }
220 
221 static u32 ast2600_get_huxclk_rate(struct ast2600_scu *scu)
222 {
223 	u32 clk_in = 0;
224 	u32 huclk_sel = readl(&scu->clk_sel4);
225 
226 	huclk_sel = ((huclk_sel >> 3) & 0x3);
227 	switch(huclk_sel) {
228 		case 0:
229 			clk_in = ast2600_get_apll_rate(scu) / 4;
230 			break;
231 		case 1:
232 			clk_in = ast2600_get_apll_rate(scu) / 2;
233 			break;
234 		case 2:
235 			clk_in = ast2600_get_apll_rate(scu);
236 			break;
237 		case 3:
238 			clk_in = ast2600_get_hclk(scu);
239 			break;
240 	}
241 
242 	return clk_in;
243 }
244 
245 static u32 ast2600_get_uart_from_uxclk_rate(struct ast2600_scu *scu)
246 {
247 	u32 clk_in = ast2600_get_uxclk_rate(scu);
248 	u32 div_reg = readl(&scu->uart_24m_ref_uxclk);
249 	unsigned int mult, div;
250 
251 	u32 n = (div_reg >> 8) & 0x3ff;
252 	u32 r = div_reg & 0xff;
253 
254 	mult = r;
255 	div = (n * 4);
256 	return (clk_in * mult)/div;
257 }
258 
259 static u32 ast2600_get_uart_from_huxclk_rate(struct ast2600_scu *scu)
260 {
261 	u32 clk_in = ast2600_get_huxclk_rate(scu);
262 	u32 div_reg = readl(&scu->uart_24m_ref_huxclk);
263 
264 	unsigned int mult, div;
265 
266 	u32 n = (div_reg >> 8) & 0x3ff;
267 	u32 r = div_reg & 0xff;
268 
269 	mult = r;
270 	div = (n * 4);
271 	return (clk_in * mult)/div;
272 }
273 
274 static u32 ast2600_get_sdio_clk_rate(struct ast2600_scu *scu)
275 {
276 	u32 clkin = 0;
277 	u32 clk_sel = readl(&scu->clk_sel4);
278 	u32 div = (clk_sel >> 28) & 0x7;
279 
280 	if(clk_sel & BIT(8)) {
281 		clkin = ast2600_get_apll_rate(scu);
282 	} else {
283 		clkin = 200 * 1000 * 1000;
284 	}
285 	div = (div + 1) << 1;
286 
287 	return (clkin / div);
288 }
289 
290 static u32 ast2600_get_emmc_clk_rate(struct ast2600_scu *scu)
291 {
292 	u32 clkin = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
293 	u32 clk_sel = readl(&scu->clk_sel1);
294 	u32 div = (clk_sel >> 12) & 0x7;
295 
296 	div = (div + 1) << 2;
297 
298 	return (clkin / div);
299 }
300 
301 static u32 ast2600_get_uart_clk_rate(struct ast2600_scu *scu, int uart_idx)
302 {
303 	u32 uart_sel = readl(&scu->clk_sel4);
304 	u32 uart_sel5 = readl(&scu->clk_sel5);
305 	ulong uart_clk = 0;
306 
307 	switch(uart_idx) {
308 		case 1:
309 		case 2:
310 		case 3:
311 		case 4:
312 		case 6:
313 			if(uart_sel & BIT(uart_idx - 1))
314 				uart_clk = ast2600_get_uart_from_uxclk_rate(scu)/13 ;
315 			else
316 				uart_clk = ast2600_get_uart_from_huxclk_rate(scu)/13 ;
317 			break;
318 		case 5: //24mhz is come form usb phy 48Mhz
319 			{
320 			u8 uart5_clk_sel = 0;
321 			//high bit
322 			if (readl(&scu->misc_ctrl1) & BIT(12))
323 				uart5_clk_sel = 0x2;
324 			else
325 				uart5_clk_sel = 0x0;
326 
327 			if (readl(&scu->clk_sel2) & BIT(14))
328 				uart5_clk_sel |= 0x1;
329 
330 			switch(uart5_clk_sel) {
331 				case 0:
332 					uart_clk = 24000000;
333 					break;
334 				case 1:
335 					uart_clk = 0;
336 					break;
337 				case 2:
338 					uart_clk = 24000000/13;
339 					break;
340 				case 3:
341 					uart_clk = 192000000/13;
342 					break;
343 			}
344 			}
345 			break;
346 		case 7:
347 		case 8:
348 		case 9:
349 		case 10:
350 		case 11:
351 		case 12:
352 		case 13:
353 			if(uart_sel5 & BIT(uart_idx - 1))
354 				uart_clk = ast2600_get_uart_from_uxclk_rate(scu)/13 ;
355 			else
356 				uart_clk = ast2600_get_uart_from_huxclk_rate(scu)/13 ;
357 			break;
358 	}
359 
360 	return uart_clk;
361 }
362 
363 static ulong ast2600_clk_get_rate(struct clk *clk)
364 {
365 	struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
366 	ulong rate = 0;
367 
368 	switch (clk->id) {
369 	case ASPEED_CLK_HPLL:
370 	case ASPEED_CLK_EPLL:
371 	case ASPEED_CLK_DPLL:
372 	case ASPEED_CLK_MPLL:
373 		rate = ast2600_get_pll_rate(priv->scu, clk->id);
374 		break;
375 	case ASPEED_CLK_AHB:
376 		rate = ast2600_get_hclk(priv->scu);
377 		break;
378 	case ASPEED_CLK_APB:
379 		rate = ast2600_get_pclk(priv->scu);
380 		break;
381 	case ASPEED_CLK_APLL:
382 		rate = ast2600_get_apll_rate(priv->scu);
383 		break;
384 	case ASPEED_CLK_GATE_UART1CLK:
385 		rate = ast2600_get_uart_clk_rate(priv->scu, 1);
386 		break;
387 	case ASPEED_CLK_GATE_UART2CLK:
388 		rate = ast2600_get_uart_clk_rate(priv->scu, 2);
389 		break;
390 	case ASPEED_CLK_GATE_UART3CLK:
391 		rate = ast2600_get_uart_clk_rate(priv->scu, 3);
392 		break;
393 	case ASPEED_CLK_GATE_UART4CLK:
394 		rate = ast2600_get_uart_clk_rate(priv->scu, 4);
395 		break;
396 	case ASPEED_CLK_GATE_UART5CLK:
397 		rate = ast2600_get_uart_clk_rate(priv->scu, 5);
398 		break;
399 	case ASPEED_CLK_SDIO:
400 		rate = ast2600_get_sdio_clk_rate(priv->scu);
401 		break;
402 	case ASPEED_CLK_EMMC:
403 		rate = ast2600_get_emmc_clk_rate(priv->scu);
404 		break;
405 	default:
406 		pr_debug("can't get clk rate \n");
407 		return -ENOENT;
408 		break;
409 	}
410 
411 	return rate;
412 }
413 
414 /**
415  * @brief	lookup PLL divider config by input/output rate
416  * @param[in]	*pll - PLL descriptor
417  * @return	true - if PLL divider config is found, false - else
418  *
419  * The function caller shall fill "pll->in" and "pll->out", then this function
420  * will search the lookup table to find a valid PLL divider configuration.
421  */
422 static bool ast2600_search_clock_config(struct ast2600_pll_desc *pll)
423 {
424 	u32 i;
425 	bool is_found = false;
426 
427 	for (i = 0; i < ARRAY_SIZE(ast2600_pll_lookup); i++) {
428 		const struct ast2600_pll_desc *def_cfg = &ast2600_pll_lookup[i];
429 		if ((def_cfg->in == pll->in) && (def_cfg->out == pll->out)) {
430 			is_found = true;
431 			pll->cfg.reg.w = def_cfg->cfg.reg.w;
432 			pll->cfg.ext_reg = def_cfg->cfg.ext_reg;
433 			break;
434 		}
435 	}
436 	return is_found;
437 }
438 
439 static u32 ast2600_configure_ddr(struct ast2600_scu *scu, ulong rate)
440 {
441 	u32 mpll_reg;
442 	struct ast2600_pll_desc mpll;
443 
444 	mpll.in = AST2600_CLK_IN;
445 	mpll.out = rate;
446 	if (false == ast2600_search_clock_config(&mpll)) {
447 		printf("error!! unable to find valid DDR clock setting\n");
448 		return 0;
449 	}
450 
451 	mpll_reg = readl(&scu->m_pll_param);
452 	mpll_reg &= ~GENMASK(22, 0);
453 	mpll_reg |= mpll.cfg.reg.w;
454 	writel(mpll_reg, &scu->m_pll_param);
455 
456 	/* write extend parameter */
457 	writel(mpll.cfg.ext_reg, &scu->m_pll_ext_param);
458 
459 	return ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL);
460 }
461 
462 static ulong ast2600_clk_set_rate(struct clk *clk, ulong rate)
463 {
464 	struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
465 
466 	ulong new_rate;
467 	switch (clk->id) {
468 	case ASPEED_CLK_MPLL:
469 		new_rate = ast2600_configure_ddr(priv->scu, rate);
470 		break;
471 	default:
472 		return -ENOENT;
473 	}
474 
475 	return new_rate;
476 }
477 
478 #define SCU_CLKSTOP_MAC1		(20)
479 #define SCU_CLKSTOP_MAC2		(21)
480 #define SCU_CLKSTOP_MAC3		(20)
481 #define SCU_CLKSTOP_MAC4		(21)
482 
483 static u32 ast2600_configure_mac12_clk(struct ast2600_scu *scu)
484 {
485 	u32 epll_reg;
486 	u32 clksel;
487 	u32 clkdelay;
488 
489 	struct ast2600_pll_desc epll;
490 
491 	epll.in = AST2600_CLK_IN;
492 	epll.out = 1000000000;
493 	if (false == ast2600_search_clock_config(&epll)) {
494 		printf(
495 		    "error!! unable to find valid ETHNET MAC clock setting\n");
496 		debug("%s: epll cfg = 0x%08x 0x%08x\n", __func__,
497 		      epll.cfg.reg.w, epll.cfg.ext_reg);
498 		debug("%s: epll cfg = %02x %02x %02x\n", __func__,
499 		      epll.cfg.reg.b.m, epll.cfg.reg.b.n, epll.cfg.reg.b.p);
500 		return 0;
501 	}
502 
503 	epll_reg = readl(&scu->e_pll_param);
504 	epll_reg &= ~GENMASK(22, 0);
505 	epll_reg |= epll.cfg.reg.w;
506 	writel(epll_reg, &scu->e_pll_param);
507 
508 	/* write extend parameter */
509 	writel(epll.cfg.ext_reg, &scu->e_pll_ext_param);
510 
511 	/* select MAC#1 and MAC#2 clock source = EPLL / 8 */
512 	clksel = readl(&scu->clk_sel2);
513 	clksel &= ~BIT(23);
514 	clksel |= 0x7 << 20;
515 	writel(clksel, &scu->clk_sel2);
516 
517 	/*
518 	BIT(31): select RGMII 125M from internal source
519 	BIT(28): RGMII 125M output enable
520 	BIT(25:0): 1G default delay
521 	*/
522 	clkdelay = MAC_DEF_DELAY_1G | BIT(31) | BIT(28);
523 	writel(clkdelay, &scu->mac12_clk_delay);
524 
525 	/* set 100M/10M default delay */
526 	writel(MAC_DEF_DELAY_100M, &scu->mac12_clk_delay_100M);
527 	writel(MAC_DEF_DELAY_10M, &scu->mac12_clk_delay_10M);
528 
529 	/* MAC AHB = HPLL / 6 */
530 	clksel = readl(&scu->clk_sel1);
531 	clksel &= ~GENMASK(18, 16);
532 	clksel |= 0x2 << 16;
533 	writel(clksel, &scu->clk_sel1);
534 
535 	return 0;
536 }
537 
538 static u32 ast2600_configure_mac34_clk(struct ast2600_scu *scu)
539 {
540 	u32 reg;
541 
542 	ast2600_configure_mac12_clk(scu);
543 
544 	/*
545 	BIT[31]   RGMII 125M source: 0 = from IO pin
546 	BIT[25:0] MAC 1G delay
547 	*/
548 	reg = readl(&scu->mac34_clk_delay);
549 	reg &= ~(BIT(31) | GENMASK(25, 0));
550 	reg |= MAC34_DEF_DELAY_1G;
551 	writel(reg, &scu->mac34_clk_delay);
552 	writel(MAC34_DEF_DELAY_100M, &scu->mac34_clk_delay_100M);
553 	writel(MAC34_DEF_DELAY_10M, &scu->mac34_clk_delay_10M);
554 
555 	/* clock source seletion and divider */
556 	reg = readl(&scu->clk_sel4);
557 	reg &= ~GENMASK(26, 24);	/* MAC AHB = HCLK / 2 */
558 	reg &= ~GENMASK(18, 16);
559 	reg |= 0x3 << 16;		/* RMII 50M = SLICLK_200M / 4 */
560 	writel(reg, &scu->clk_sel4);
561 
562 	/* set driving strength */
563 	reg = readl(&scu->pinmux_ctrl16);
564 	reg &= GENMASK(3, 0);
565 	reg |= (0x2 << 0) | (0x2 << 2);
566 	writel(reg, &scu->pinmux_ctrl16);
567 
568 	return 0;
569 }
570 #if 0
571 /**
572  * WIP: ast2600 RGMII clock source tree
573  *
574  *    125M from external PAD -------->|\
575  *    HPLL -->|\                      | |---->RGMII 125M for MAC#1 & MAC#2
576  *            | |---->| divider |---->|/                             +
577  *    EPLL -->|/                                                     |
578  *                                                                   |
579  *    +---------<-----------|PAD output enable|<---------------------+
580  *    |
581  *    +--->|PAD input enable|----->|\
582  *                                 | |----> RGMII 125M for MAC#3 & MAC#4
583  *    SLICLK 200M -->|divider|---->|/
584 */
585 struct ast2600_rgmii_clk_config {
586 	u32 mac_1_2_src;	/* 0=external PAD, 1=internal PLL */
587 	u32 int_clk_src;	/* 0=EPLL, 1=HPLL */
588 	u32 int_clk_div;
589 
590 	u32 mac_3_4_src;	/* 0=external PAD, 1=SLICLK */
591 	u32 sli_clk_div;	/* reserved */
592 };
593 
594 static void ast2600_init_rgmii_clk(struct ast2600_scu *scu, int index)
595 {
596 	debug("%s not ready\n", __func__);
597 }
598 
599 static void ast2600_init_rmii_clk(struct ast2600_scu *scu, int index)
600 {
601 	debug("%s not ready\n", __func__);
602 }
603 #endif
604 static u32 ast2600_configure_mac(struct ast2600_scu *scu, int index)
605 {
606 	u32 reset_bit;
607 	u32 clkstop_bit;
608 
609 	if (index < 3)
610 		ast2600_configure_mac12_clk(scu);
611 	else
612 		ast2600_configure_mac34_clk(scu);
613 
614 	switch (index) {
615 	case 1:
616 		reset_bit = BIT(ASPEED_RESET_MAC1);
617 		clkstop_bit = BIT(SCU_CLKSTOP_MAC1);
618 		writel(reset_bit, &scu->sysreset_ctrl1);
619 		udelay(100);
620 		writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
621 		mdelay(10);
622 		writel(reset_bit, &scu->sysreset_clr_ctrl1);
623 
624 		break;
625 	case 2:
626 		reset_bit = BIT(ASPEED_RESET_MAC2);
627 		clkstop_bit = BIT(SCU_CLKSTOP_MAC2);
628 		writel(reset_bit, &scu->sysreset_ctrl1);
629 		udelay(100);
630 		writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
631 		mdelay(10);
632 		writel(reset_bit, &scu->sysreset_clr_ctrl1);
633 		break;
634 	case 3:
635 		reset_bit = BIT(ASPEED_RESET_MAC3 - 32);
636 		clkstop_bit = BIT(SCU_CLKSTOP_MAC3);
637 		writel(reset_bit, &scu->sysreset_ctrl2);
638 		udelay(100);
639 		writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
640 		mdelay(10);
641 		writel(reset_bit, &scu->sysreset_clr_ctrl2);
642 		break;
643 	case 4:
644 		reset_bit = BIT(ASPEED_RESET_MAC4 - 32);
645 		clkstop_bit = BIT(SCU_CLKSTOP_MAC4);
646 		writel(reset_bit, &scu->sysreset_ctrl2);
647 		udelay(100);
648 		writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
649 		mdelay(10);
650 		writel(reset_bit, &scu->sysreset_clr_ctrl2);
651 		break;
652 	default:
653 		return -EINVAL;
654 	}
655 
656 	return 0;
657 }
658 
659 #define SCU_CLKSTOP_SDIO 4
660 static ulong ast2600_enable_sdclk(struct ast2600_scu *scu)
661 {
662 	u32 reset_bit;
663 	u32 clkstop_bit;
664 
665 	reset_bit = BIT(ASPEED_RESET_SD - 32);
666 	clkstop_bit = BIT(SCU_CLKSTOP_SDIO);
667 
668 	writel(reset_bit, &scu->sysreset_clr_ctrl2);
669 	udelay(100);
670 	//enable clk
671 	writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
672 	mdelay(10);
673 	writel(reset_bit, &scu->sysreset_ctrl2);
674 
675 	return 0;
676 }
677 
678 #define SCU_CLKSTOP_EXTSD 31
679 #define SCU_CLK_SD_MASK				(0x7 << 28)
680 #define SCU_CLK_SD_DIV(x)			(x << 28)
681 
682 static ulong ast2600_enable_extsdclk(struct ast2600_scu *scu)
683 {
684 	u32 clk_sel = readl(&scu->clk_sel4);
685 	u32 enableclk_bit;
686 
687 	enableclk_bit = BIT(SCU_CLKSTOP_EXTSD);
688 
689 	clk_sel &= ~SCU_CLK_SD_MASK;
690 	clk_sel |= SCU_CLK_SD_DIV(0);
691 	writel(clk_sel, &scu->clk_sel4);
692 
693 	//enable clk
694 	setbits_le32(&scu->clk_sel4, enableclk_bit);
695 
696 	return 0;
697 }
698 
699 #define SCU_CLKSTOP_EMMC 27
700 static ulong ast2600_enable_emmcclk(struct ast2600_scu *scu)
701 {
702 	u32 reset_bit;
703 	u32 clkstop_bit;
704 
705 	reset_bit = BIT(ASPEED_RESET_EMMC);
706 	clkstop_bit = BIT(SCU_CLKSTOP_EMMC);
707 
708 	writel(reset_bit, &scu->sysreset_clr_ctrl1);
709 	udelay(100);
710 	//enable clk
711 	writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
712 	mdelay(10);
713 	writel(reset_bit, &scu->sysreset_ctrl2);
714 
715 	return 0;
716 }
717 
718 #define SCU_CLKSTOP_EXTEMMC 15
719 #define SCU_CLK_EMMC_MASK			(0x7 << 12)
720 #define SCU_CLK_EMMC_DIV(x)			(x << 12)
721 
722 static ulong ast2600_enable_extemmcclk(struct ast2600_scu *scu)
723 {
724 	u32 clk_sel = readl(&scu->clk_sel1);
725 	u32 enableclk_bit;
726 
727 	enableclk_bit = BIT(SCU_CLKSTOP_EXTSD);
728 
729 	clk_sel &= ~SCU_CLK_SD_MASK;
730 	clk_sel |= SCU_CLK_SD_DIV(1);
731 	writel(clk_sel, &scu->clk_sel1);
732 
733 	//enable clk
734 	setbits_le32(&scu->clk_sel1, enableclk_bit);
735 
736 	return 0;
737 }
738 
739 static int ast2600_clk_enable(struct clk *clk)
740 {
741 	struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
742 
743 	switch (clk->id) {
744 		case ASPEED_CLK_GATE_MAC1CLK:
745 			ast2600_configure_mac(priv->scu, 1);
746 			break;
747 		case ASPEED_CLK_GATE_MAC2CLK:
748 			ast2600_configure_mac(priv->scu, 2);
749 			break;
750 		case ASPEED_CLK_GATE_MAC3CLK:
751 			ast2600_configure_mac(priv->scu, 3);
752 			break;
753 		case ASPEED_CLK_GATE_MAC4CLK:
754 			ast2600_configure_mac(priv->scu, 4);
755 			break;
756 		case ASPEED_CLK_GATE_SDCLK:
757 			ast2600_enable_sdclk(priv->scu);
758 			break;
759 		case ASPEED_CLK_GATE_SDEXTCLK:
760 			ast2600_enable_extsdclk(priv->scu);
761 			break;
762 		case ASPEED_CLK_GATE_EMMCCLK:
763 			ast2600_enable_emmcclk(priv->scu);
764 			break;
765 		case ASPEED_CLK_GATE_EMMCEXTCLK:
766 			ast2600_enable_extemmcclk(priv->scu);
767 			break;
768 		default:
769 			pr_debug("can't enable clk \n");
770 			return -ENOENT;
771 			break;
772 	}
773 
774 	return 0;
775 }
776 
777 struct clk_ops ast2600_clk_ops = {
778 	.get_rate = ast2600_clk_get_rate,
779 	.set_rate = ast2600_clk_set_rate,
780 	.enable = ast2600_clk_enable,
781 };
782 
783 static int ast2600_clk_probe(struct udevice *dev)
784 {
785 	struct ast2600_clk_priv *priv = dev_get_priv(dev);
786 
787 	priv->scu = devfdt_get_addr_ptr(dev);
788 	if (IS_ERR(priv->scu))
789 		return PTR_ERR(priv->scu);
790 
791 	return 0;
792 }
793 
794 static int ast2600_clk_bind(struct udevice *dev)
795 {
796 	int ret;
797 
798 	/* The reset driver does not have a device node, so bind it here */
799 	ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev);
800 	if (ret)
801 		debug("Warning: No reset driver: ret=%d\n", ret);
802 
803 	return 0;
804 }
805 
806 #if CONFIG_IS_ENABLED(CMD_CLK)
807 struct aspeed_clks {
808 	ulong id;
809 	const char *name;
810 };
811 
812 static struct aspeed_clks aspeed_clk_names[] = {
813 	{ ASPEED_CLK_HPLL, "hpll" },
814 	{ ASPEED_CLK_MPLL, "mpll" },
815 	{ ASPEED_CLK_APLL, "apll" },
816 	{ ASPEED_CLK_EPLL, "epll" },
817 	{ ASPEED_CLK_DPLL, "dpll" },
818 	{ ASPEED_CLK_AHB, "hclk" },
819 	{ ASPEED_CLK_APB, "pclk" },
820 };
821 
822 int soc_clk_dump(void)
823 {
824 	struct udevice *dev;
825 	struct clk clk;
826 	unsigned long rate;
827 	int i, ret;
828 
829 	ret = uclass_get_device_by_driver(UCLASS_CLK,
830 					  DM_GET_DRIVER(aspeed_scu), &dev);
831 	if (ret)
832 		return ret;
833 
834 	printf("Clk\t\tHz\n");
835 
836 	for (i = 0; i < ARRAY_SIZE(aspeed_clk_names); i++) {
837 		clk.id = aspeed_clk_names[i].id;
838 		ret = clk_request(dev, &clk);
839 		if (ret < 0) {
840 			debug("%s clk_request() failed: %d\n", __func__, ret);
841 			continue;
842 		}
843 
844 		ret = clk_get_rate(&clk);
845 		rate = ret;
846 
847 		clk_free(&clk);
848 
849 		if (ret == -ENOTSUPP) {
850 			printf("clk ID %lu not supported yet\n",
851 			       aspeed_clk_names[i].id);
852 			continue;
853 		}
854 		if (ret < 0) {
855 			printf("%s %lu: get_rate err: %d\n",
856 			       __func__, aspeed_clk_names[i].id, ret);
857 			continue;
858 		}
859 
860 		printf("%s(%3lu):\t%lu\n",
861 		       aspeed_clk_names[i].name, aspeed_clk_names[i].id, rate);
862 	}
863 
864 	return 0;
865 }
866 #endif
867 
868 static const struct udevice_id ast2600_clk_ids[] = {
869 	{ .compatible = "aspeed,ast2600-scu", },
870 	{ }
871 };
872 
873 U_BOOT_DRIVER(aspeed_scu) = {
874 	.name		= "aspeed_scu",
875 	.id		= UCLASS_CLK,
876 	.of_match	= ast2600_clk_ids,
877 	.priv_auto_alloc_size = sizeof(struct ast2600_clk_priv),
878 	.ops		= &ast2600_clk_ops,
879 	.bind		= ast2600_clk_bind,
880 	.probe		= ast2600_clk_probe,
881 };
882