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_ast2400.h>
12 #include <dt-bindings/clock/ast2400-clock.h>
13 #include <dt-bindings/reset/ast2400-reset.h>
14 
15 DECLARE_GLOBAL_DATA_PTR;
16 
17 /*
18  * Clock divider/multiplier configuration struct.
19  * For H-PLL and M-PLL the formula is
20  * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
21  * M - Numerator
22  * N - Denumerator
23  * P - Post Divider
24  * They have the same layout in their control register.
25  *
26  * D-PLL and D2-PLL have extra divider (OD + 1), which is not
27  * yet needed and ignored by clock configurations.
28  */
29 struct ast2400_div_config {
30 	unsigned int num;
31 	unsigned int denum;
32 	unsigned int post_div;
33 };
34 
35 #define CLKIN_25MHZ_EN BIT(23)
36 #define AST2400_CLK_SOURCE_SEL BIT(18)
ast2400_get_clkin(struct ast2400_scu * scu)37 extern u32 ast2400_get_clkin(struct ast2400_scu *scu)
38 {
39 	u32 clkin;
40 	u32 strap = readl(&scu->hwstrap);
41 
42 	if (strap & CLKIN_25MHZ_EN) {
43 		clkin = 25 * 1000 * 1000;
44 	} else {
45 		if (strap & AST2400_CLK_SOURCE_SEL)
46 			clkin = 48 * 1000 * 1000;
47 		else
48 			clkin = 24 * 1000 * 1000;
49 	}
50 
51 	return clkin;
52 }
53 
54 #define AST2400_MPLL_BYPASS_EN BIT(17)
55 #define AST2400_MPLL_OFF BIT(16)
56 
57 /*
58  * Get the rate of the M-PLL clock from input clock frequency and
59  * the value of the M-PLL Parameter Register.
60  */
ast2400_get_mpll_rate(struct ast2400_scu * scu)61 extern u32 ast2400_get_mpll_rate(struct ast2400_scu *scu)
62 {
63 	unsigned int mult, div;
64 	u32 clkin = ast2400_get_clkin(scu);
65 	u32 mpll_reg = readl(&scu->m_pll_param);
66 
67 	if (mpll_reg & AST2400_MPLL_OFF)
68 		return 0;
69 
70 	if (mpll_reg & AST2400_MPLL_BYPASS_EN)
71 		return clkin;
72 	else {
73 		u32 od = (mpll_reg >> 4) & 0x1;
74 		u32 n = (mpll_reg >> 5) & 0x3f;
75 		u32 d = mpll_reg & 0xf;
76 
77 		//mpll = 24MHz * (2-OD) * ((Numerator+2)/(Denumerator+1))
78 		mult = (2 - od) * (n + 2);
79 		div = (d + 1);
80 	}
81 
82 	return (clkin * mult / div);
83 }
84 
85 #define AST2400_HPLL_PROGRAMMED BIT(18)
86 #define AST2400_HPLL_BYPASS_EN BIT(17)
87 /*
88  * Get the rate of the H-PLL clock from input clock frequency and
89  * the value of the H-PLL Parameter Register.
90  */
ast2400_get_hpll_rate(struct ast2400_scu * scu)91 extern u32 ast2400_get_hpll_rate(struct ast2400_scu *scu)
92 {
93 	unsigned int mult, div;
94 	u32 clkin = ast2400_get_clkin(scu);
95 	u32 hpll_reg = readl(&scu->h_pll_param);
96 
97 	const u16 hpll_rates[][4] = {
98 	    {384, 360, 336, 408},
99 	    {400, 375, 350, 425},
100 	};
101 
102 	if (hpll_reg & AST2400_HPLL_PROGRAMMED) {
103 		if (hpll_reg & AST2400_HPLL_BYPASS_EN) {
104 			/* Pass through mode */
105 			mult = div = 1;
106 		} else {
107 			/* F = 24Mhz * (2-OD) * [(N + 2) / (D + 1)] */
108 			u32 n = (hpll_reg >> 5) & 0x3f;
109 			u32 od = (hpll_reg >> 4) & 0x1;
110 			u32 d = hpll_reg & 0xf;
111 
112 			mult = (2 - od) * (n + 2);
113 			div = d + 1;
114 		}
115 	} else {
116 		//fix
117 		u32 strap = readl(ASPEED_HW_STRAP1);
118 		u16 rate = (hpll_reg >> 8) & 3;
119 		if (strap & CLKIN_25MHZ_EN)
120 			clkin = hpll_rates[1][rate];
121 		else {
122 			if (strap & AST2400_CLK_SOURCE_SEL)
123 				clkin = hpll_rates[0][rate];
124 			else
125 				clkin = hpll_rates[0][rate];
126 		}
127 		clkin *= 1000000;
128 		mult = 1;
129 		div = 1;
130 	}
131 
132 	return (clkin * mult / div);
133 }
134 
135 #define AST2400_D2PLL_OFF BIT(17)
136 #define AST2400_D2PLL_BYPASS_EN BIT(18)
137 
138 /*
139  * Get the rate of the D2-PLL clock from input clock frequency and
140  * the value of the D2-PLL Parameter Register.
141  */
ast2400_get_d2pll_rate(struct ast2400_scu * scu)142 extern u32 ast2400_get_d2pll_rate(struct ast2400_scu *scu)
143 {
144 	unsigned int mult, div;
145 	u32 clkin = ast2400_get_clkin(scu);
146 	u32 d2pll_reg = readl(&scu->d2_pll_param);
147 
148 	/* F = clkin * [(M+1) / (N+1)] / (P + 1)/ (od + 1) */
149 	if (d2pll_reg & AST2400_D2PLL_OFF)
150 		return 0;
151 
152 	// Programming
153 	if (d2pll_reg & AST2400_D2PLL_BYPASS_EN)
154 		return clkin;
155 	else {
156 		u32 n = (d2pll_reg & 0xff);
157 		u32 d = (d2pll_reg >> 8) & 0x1f;
158 		u32 o = (d2pll_reg >> 13) & 0x3;
159 		o = (1 << (o - 1));
160 		u32 p = (d2pll_reg >> 15) & 0x3;
161 		if (p == 2)
162 			p = 2;
163 		else
164 			p = (0x1 << p);
165 		u32 p2 = (d2pll_reg >> 19) & 0x7;
166 		p2 += 1;
167 		//FOUT (Output frequency) = 24MHz * (Num * 2) / (Denum * OD * PD * PD2)
168 		mult = (n * 2);
169 		div = (d * o * p * p2);
170 	}
171 	return (clkin * mult / div);
172 }
173 
174 #define SCU_HWSTRAP_AXIAHB_DIV_SHIFT    9
175 #define SCU_HWSTRAP_AXIAHB_DIV_MASK     (0x7 << SCU_HWSTRAP_AXIAHB_DIV_SHIFT)
176 
ast2400_get_hclk(struct ast2400_scu * scu)177 static u32 ast2400_get_hclk(struct ast2400_scu *scu)
178 {
179 	u32 ahb_div;
180 	u32 strap = readl(&scu->hwstrap);
181 	u32 rate = ast2400_get_hpll_rate(scu);
182 
183 	ahb_div = ((strap >> 10) & 0x3) + 1;
184 
185 	return (rate / ahb_div);
186 }
187 
ast2400_get_pclk(struct ast2400_scu * scu)188 static u32 ast2400_get_pclk(struct ast2400_scu *scu)
189 {
190 	u32 rate = 0;
191 	rate = ast2400_get_hpll_rate(scu);
192 	u32 apb_div = (readl(&scu->clk_sel1) >> 23) & 0x7;
193 
194 	apb_div = (apb_div + 1) << 1;
195 
196 	return (rate / apb_div);
197 }
198 
ast2400_get_sdio_clk_rate(struct ast2400_scu * scu)199 static u32 ast2400_get_sdio_clk_rate(struct ast2400_scu *scu)
200 {
201 	u32 clkin = ast2400_get_hpll_rate(scu);
202 	u32 clk_sel = readl(&scu->clk_sel1);
203 	u32 div = (clk_sel >> 12) & 0x7;
204 
205 	div = (div + 1) << 1;
206 
207 	return (clkin / div);
208 }
209 
ast2400_get_uart_clk_rate(struct ast2400_scu * scu,int uart_idx)210 static u32 ast2400_get_uart_clk_rate(struct ast2400_scu *scu, int uart_idx)
211 {
212 	u32	uart_clkin = 24 * 1000 * 1000;
213 
214 	if (readl(&scu->misc_ctrl1) & SCU_MISC_UARTCLK_DIV13)
215 		uart_clkin /= 13;
216 
217 	return uart_clkin;
218 }
219 
ast2400_clk_get_rate(struct clk * clk)220 static ulong ast2400_clk_get_rate(struct clk *clk)
221 {
222 	struct ast2400_clk_priv *priv = dev_get_priv(clk->dev);
223 	ulong rate;
224 
225 	switch (clk->id) {
226 	case ASPEED_CLK_HPLL:
227 		rate = ast2400_get_hpll_rate(priv->scu);
228 		break;
229 	case ASPEED_CLK_MPLL:
230 		rate = ast2400_get_mpll_rate(priv->scu);
231 		break;
232 	case ASPEED_CLK_D2PLL:
233 		rate = ast2400_get_d2pll_rate(priv->scu);
234 		break;
235 	case ASPEED_CLK_AHB:
236 		rate = ast2400_get_hclk(priv->scu);
237 		break;
238 	case ASPEED_CLK_APB:
239 		rate = ast2400_get_pclk(priv->scu);
240 		break;
241 	case ASPEED_CLK_GATE_UART1CLK:
242 		rate = ast2400_get_uart_clk_rate(priv->scu, 1);
243 		break;
244 	case ASPEED_CLK_GATE_UART2CLK:
245 		rate = ast2400_get_uart_clk_rate(priv->scu, 2);
246 		break;
247 	case ASPEED_CLK_GATE_UART3CLK:
248 		rate = ast2400_get_uart_clk_rate(priv->scu, 3);
249 		break;
250 	case ASPEED_CLK_GATE_UART4CLK:
251 		rate = ast2400_get_uart_clk_rate(priv->scu, 4);
252 		break;
253 	case ASPEED_CLK_GATE_UART5CLK:
254 		rate = ast2400_get_uart_clk_rate(priv->scu, 5);
255 		break;
256 	case ASPEED_CLK_SDIO:
257 		rate = ast2400_get_sdio_clk_rate(priv->scu);
258 		break;
259 	default:
260 		pr_debug("can't get clk rate \n");
261 		return -ENOENT;
262 		break;
263 	}
264 
265 	return rate;
266 }
267 
268 struct ast2400_clock_config {
269 	ulong input_rate;
270 	ulong rate;
271 	struct ast2400_div_config cfg;
272 };
273 
274 static const struct ast2400_clock_config ast2400_clock_config_defaults[] = {
275 	{ 24000000, 250000000, { .num = 124, .denum = 1, .post_div = 5 } },
276 };
277 
ast2400_get_clock_config_default(ulong input_rate,ulong requested_rate,struct ast2400_div_config * cfg)278 static bool ast2400_get_clock_config_default(ulong input_rate,
279 					     ulong requested_rate,
280 					     struct ast2400_div_config *cfg)
281 {
282 	int i;
283 
284 	for (i = 0; i < ARRAY_SIZE(ast2400_clock_config_defaults); i++) {
285 		const struct ast2400_clock_config *default_cfg =
286 			&ast2400_clock_config_defaults[i];
287 		if (default_cfg->input_rate == input_rate &&
288 		    default_cfg->rate == requested_rate) {
289 			*cfg = default_cfg->cfg;
290 			return true;
291 		}
292 	}
293 
294 	return false;
295 }
296 
297 /*
298  * @input_rate - the rate of input clock in Hz
299  * @requested_rate - desired output rate in Hz
300  * @div - this is an IN/OUT parameter, at input all fields of the config
301  * need to be set to their maximum allowed values.
302  * The result (the best config we could find), would also be returned
303  * in this structure.
304  *
305  * @return The clock rate, when the resulting div_config is used.
306  */
ast2400_calc_clock_config(ulong input_rate,ulong requested_rate,struct ast2400_div_config * cfg)307 static ulong ast2400_calc_clock_config(ulong input_rate, ulong requested_rate,
308 				       struct ast2400_div_config *cfg)
309 {
310 	/*
311 	 * The assumption is that kHz precision is good enough and
312 	 * also enough to avoid overflow when multiplying.
313 	 */
314 	const ulong input_rate_khz = input_rate / 1000;
315 	const ulong rate_khz = requested_rate / 1000;
316 	const struct ast2400_div_config max_vals = *cfg;
317 	struct ast2400_div_config it = { 0, 0, 0 };
318 	ulong delta = rate_khz;
319 	ulong new_rate_khz = 0;
320 
321 	/*
322 	 * Look for a well known frequency first.
323 	 */
324 	if (ast2400_get_clock_config_default(input_rate, requested_rate, cfg))
325 		return requested_rate;
326 
327 	for (; it.denum <= max_vals.denum; ++it.denum) {
328 		for (it.post_div = 0; it.post_div <= max_vals.post_div;
329 		     ++it.post_div) {
330 			it.num = (rate_khz * (it.post_div + 1) / input_rate_khz)
331 			    * (it.denum + 1);
332 			if (it.num > max_vals.num)
333 				continue;
334 
335 			new_rate_khz = (input_rate_khz
336 					* ((it.num + 1) / (it.denum + 1)))
337 			    / (it.post_div + 1);
338 
339 			/* Keep the rate below requested one. */
340 			if (new_rate_khz > rate_khz)
341 				continue;
342 
343 			if (new_rate_khz - rate_khz < delta) {
344 				delta = new_rate_khz - rate_khz;
345 				*cfg = it;
346 				if (delta == 0)
347 					return new_rate_khz * 1000;
348 			}
349 		}
350 	}
351 
352 	return new_rate_khz * 1000;
353 }
354 
ast2400_configure_ddr(struct ast2400_scu * scu,ulong rate)355 static ulong ast2400_configure_ddr(struct ast2400_scu *scu, ulong rate)
356 {
357 	ulong clkin = ast2400_get_clkin(scu);
358 	u32 mpll_reg;
359 	struct ast2400_div_config div_cfg = {
360 		.num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT),
361 		.denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT),
362 		.post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT),
363 	};
364 
365 	ast2400_calc_clock_config(clkin, rate, &div_cfg);
366 
367 	mpll_reg = readl(&scu->m_pll_param);
368 	mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK
369 		      | SCU_MPLL_DENUM_MASK);
370 	mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
371 	    | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
372 	    | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
373 
374 	writel(mpll_reg, &scu->m_pll_param);
375 
376 	return ast2400_get_mpll_rate(scu);
377 }
378 
ast2400_clk_set_rate(struct clk * clk,ulong rate)379 static unsigned long ast2400_clk_set_rate(struct clk *clk, ulong rate)
380 {
381 	struct ast2400_clk_priv *priv = dev_get_priv(clk->dev);
382 
383 	ulong new_rate;
384 	switch (clk->id) {
385 		//mpll
386 		case ASPEED_CLK_MPLL:
387 			new_rate = ast2400_configure_ddr(priv->scu, rate);
388 			break;
389 		default:
390 			return -ENOENT;
391 	}
392 
393 	return new_rate;
394 }
395 
396 #define SCU_CLKSTOP_MAC1		(20)
397 #define SCU_CLKSTOP_MAC2		(21)
398 
ast2400_configure_mac(struct ast2400_scu * scu,int index)399 static ulong ast2400_configure_mac(struct ast2400_scu *scu, int index)
400 {
401 	u32 reset_bit;
402 	u32 clkstop_bit;
403 
404 	switch (index) {
405 	case 1:
406 		reset_bit = BIT(ASPEED_RESET_MAC1);
407 		clkstop_bit = BIT(SCU_CLKSTOP_MAC1);
408 		break;
409 	case 2:
410 		reset_bit = BIT(ASPEED_RESET_MAC2);
411 		clkstop_bit = BIT(SCU_CLKSTOP_MAC2);
412 		break;
413 	default:
414 		return -EINVAL;
415 	}
416 
417 	/*
418 	 * Disable MAC, start its clock and re-enable it.
419 	 * The procedure and the delays (100us & 10ms) are
420 	 * specified in the datasheet.
421 	 */
422 	setbits_le32(&scu->sysreset_ctrl1, reset_bit);
423 	udelay(100);
424 	clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
425 	mdelay(10);
426 	clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
427 
428 	return 0;
429 }
430 
431 #define SCU_CLKSTOP_SDIO 27
ast2400_enable_sdclk(struct ast2400_scu * scu)432 static ulong ast2400_enable_sdclk(struct ast2400_scu *scu)
433 {
434 	u32 reset_bit;
435 	u32 clkstop_bit;
436 
437 	reset_bit = BIT(ASEPPD_RESET_SDIO);
438 	clkstop_bit = BIT(SCU_CLKSTOP_SDIO);
439 
440 	setbits_le32(&scu->sysreset_ctrl1, reset_bit);
441 	udelay(100);
442 	//enable clk
443 	clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
444 	mdelay(10);
445 	clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
446 
447 	return 0;
448 }
449 
450 #define SCU_CLKSTOP_EXTSD 15
451 #define SCU_CLK_SD_MASK				(0x7 << 12)
452 #define SCU_CLK_SD_DIV(x)			(x << 12)
453 
ast2400_enable_extsdclk(struct ast2400_scu * scu)454 static ulong ast2400_enable_extsdclk(struct ast2400_scu *scu)
455 {
456 	u32 clk_sel = readl(&scu->clk_sel1);
457 	u32 enableclk_bit;
458 
459 	enableclk_bit = BIT(SCU_CLKSTOP_EXTSD);
460 
461 	// SDCLK = G4  H-PLL / 4, G5 = H-PLL /8
462 	clk_sel &= ~SCU_CLK_SD_MASK;
463 	clk_sel |= SCU_CLK_SD_DIV(1);
464 	writel(clk_sel, &scu->clk_sel1);
465 
466 	//enable clk
467 	setbits_le32(&scu->clk_sel1, enableclk_bit);
468 
469 	return 0;
470 }
471 
ast2400_clk_enable(struct clk * clk)472 static int ast2400_clk_enable(struct clk *clk)
473 {
474 	struct ast2400_clk_priv *priv = dev_get_priv(clk->dev);
475 
476 	switch (clk->id) {
477 		case ASPEED_CLK_GATE_MAC1CLK:
478 			ast2400_configure_mac(priv->scu, 1);
479 			break;
480 		case ASPEED_CLK_GATE_MAC2CLK:
481 			ast2400_configure_mac(priv->scu, 2);
482 			break;
483 		case ASPEED_CLK_GATE_SDCLK:
484 			ast2400_enable_sdclk(priv->scu);
485 			break;
486 		case ASPEED_CLK_GATE_SDEXTCLK:
487 			ast2400_enable_extsdclk(priv->scu);
488 			break;
489 		default:
490 			pr_debug("can't enable clk \n");
491 			return -ENOENT;
492 			break;
493 	}
494 
495 	return 0;
496 }
497 
498 struct clk_ops ast2400_clk_ops = {
499 	.get_rate = ast2400_clk_get_rate,
500 	.set_rate = ast2400_clk_set_rate,
501 	.enable = ast2400_clk_enable,
502 };
503 
ast2400_clk_probe(struct udevice * dev)504 static int ast2400_clk_probe(struct udevice *dev)
505 {
506 	struct ast2400_clk_priv *priv = dev_get_priv(dev);
507 
508 	priv->scu = devfdt_get_addr_ptr(dev);
509 	if (IS_ERR(priv->scu))
510 		return PTR_ERR(priv->scu);
511 
512 	return 0;
513 }
514 
ast2400_clk_bind(struct udevice * dev)515 static int ast2400_clk_bind(struct udevice *dev)
516 {
517 	int ret;
518 
519 	/* The reset driver does not have a device node, so bind it here */
520 	ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev);
521 	if (ret)
522 		debug("Warning: No reset driver: ret=%d\n", ret);
523 
524 	return 0;
525 }
526 
527 #if CONFIG_IS_ENABLED(CMD_CLK)
528 struct aspeed_clks {
529 	ulong id;
530 	const char *name;
531 };
532 
533 static struct aspeed_clks aspeed_clk_names[] = {
534 	{ ASPEED_CLK_UART, "uart" },
535 	{ ASPEED_CLK_HPLL, "hpll" },
536 	{ ASPEED_CLK_MPLL, "mpll" },
537 	{ ASPEED_CLK_D2PLL, "d2pll" },
538 	{ ASPEED_CLK_AHB, "hclk" },
539 	{ ASPEED_CLK_APB, "pclk" },
540 };
541 
soc_clk_dump(void)542 int soc_clk_dump(void)
543 {
544 	struct udevice *dev;
545 	struct clk clk;
546 	unsigned long rate;
547 	int i, ret;
548 
549 	ret = uclass_get_device_by_driver(UCLASS_CLK,
550 					  DM_GET_DRIVER(aspeed_scu), &dev);
551 	if (ret)
552 		return ret;
553 
554 	printf("Clk\t\tHz\n");
555 
556 	for (i = 0; i < ARRAY_SIZE(aspeed_clk_names); i++) {
557 		clk.id = aspeed_clk_names[i].id;
558 		ret = clk_request(dev, &clk);
559 		if (ret < 0) {
560 			debug("%s clk_request() failed: %d\n", __func__, ret);
561 			continue;
562 		}
563 
564 		ret = clk_get_rate(&clk);
565 		rate = ret;
566 
567 		clk_free(&clk);
568 
569 		if (ret == -ENOTSUPP) {
570 			printf("clk ID %lu not supported yet\n",
571 			       aspeed_clk_names[i].id);
572 			continue;
573 		}
574 		if (ret < 0) {
575 			printf("%s %lu: get_rate err: %d\n",
576 			       __func__, aspeed_clk_names[i].id, ret);
577 			continue;
578 		}
579 
580 		printf("%s(%3lu):\t%lu\n",
581 		       aspeed_clk_names[i].name, aspeed_clk_names[i].id, rate);
582 	}
583 
584 	return 0;
585 }
586 #endif
587 
588 static const struct udevice_id ast2400_clk_ids[] = {
589 	{ .compatible = "aspeed,ast2400-scu" },
590 	{ }
591 };
592 
593 U_BOOT_DRIVER(aspeed_scu) = {
594 	.name		= "aspeed_scu",
595 	.id		= UCLASS_CLK,
596 	.of_match	= ast2400_clk_ids,
597 	.priv_auto_alloc_size = sizeof(struct ast2400_clk_priv),
598 	.ops		= &ast2400_clk_ops,
599 	.bind		= ast2400_clk_bind,
600 	.probe		= ast2400_clk_probe,
601 };
602