xref: /openbmc/u-boot/drivers/clk/aspeed/clk_ast2400.c (revision ab1375f7db7ad9b9e73fbc7c67c0e10f411a7b0d)
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)
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  */
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  */
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  */
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 
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 
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 
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 
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 
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 	printf("get id %ld rate %ld\n", clk->id, rate);
265 
266 	return rate;
267 }
268 
269 struct ast2400_clock_config {
270 	ulong input_rate;
271 	ulong rate;
272 	struct ast2400_div_config cfg;
273 };
274 
275 static const struct ast2400_clock_config ast2400_clock_config_defaults[] = {
276 	{ 24000000, 250000000, { .num = 124, .denum = 1, .post_div = 5 } },
277 };
278 
279 static bool ast2400_get_clock_config_default(ulong input_rate,
280 					     ulong requested_rate,
281 					     struct ast2400_div_config *cfg)
282 {
283 	int i;
284 
285 	for (i = 0; i < ARRAY_SIZE(ast2400_clock_config_defaults); i++) {
286 		const struct ast2400_clock_config *default_cfg =
287 			&ast2400_clock_config_defaults[i];
288 		if (default_cfg->input_rate == input_rate &&
289 		    default_cfg->rate == requested_rate) {
290 			*cfg = default_cfg->cfg;
291 			return true;
292 		}
293 	}
294 
295 	return false;
296 }
297 
298 /*
299  * @input_rate - the rate of input clock in Hz
300  * @requested_rate - desired output rate in Hz
301  * @div - this is an IN/OUT parameter, at input all fields of the config
302  * need to be set to their maximum allowed values.
303  * The result (the best config we could find), would also be returned
304  * in this structure.
305  *
306  * @return The clock rate, when the resulting div_config is used.
307  */
308 static ulong ast2400_calc_clock_config(ulong input_rate, ulong requested_rate,
309 				       struct ast2400_div_config *cfg)
310 {
311 	/*
312 	 * The assumption is that kHz precision is good enough and
313 	 * also enough to avoid overflow when multiplying.
314 	 */
315 	const ulong input_rate_khz = input_rate / 1000;
316 	const ulong rate_khz = requested_rate / 1000;
317 	const struct ast2400_div_config max_vals = *cfg;
318 	struct ast2400_div_config it = { 0, 0, 0 };
319 	ulong delta = rate_khz;
320 	ulong new_rate_khz = 0;
321 
322 	/*
323 	 * Look for a well known frequency first.
324 	 */
325 	if (ast2400_get_clock_config_default(input_rate, requested_rate, cfg))
326 		return requested_rate;
327 
328 	for (; it.denum <= max_vals.denum; ++it.denum) {
329 		for (it.post_div = 0; it.post_div <= max_vals.post_div;
330 		     ++it.post_div) {
331 			it.num = (rate_khz * (it.post_div + 1) / input_rate_khz)
332 			    * (it.denum + 1);
333 			if (it.num > max_vals.num)
334 				continue;
335 
336 			new_rate_khz = (input_rate_khz
337 					* ((it.num + 1) / (it.denum + 1)))
338 			    / (it.post_div + 1);
339 
340 			/* Keep the rate below requested one. */
341 			if (new_rate_khz > rate_khz)
342 				continue;
343 
344 			if (new_rate_khz - rate_khz < delta) {
345 				delta = new_rate_khz - rate_khz;
346 				*cfg = it;
347 				if (delta == 0)
348 					return new_rate_khz * 1000;
349 			}
350 		}
351 	}
352 
353 	return new_rate_khz * 1000;
354 }
355 
356 static ulong ast2400_configure_ddr(struct ast2400_scu *scu, ulong rate)
357 {
358 	ulong clkin = ast2400_get_clkin(scu);
359 	u32 mpll_reg;
360 	struct ast2400_div_config div_cfg = {
361 		.num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT),
362 		.denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT),
363 		.post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT),
364 	};
365 
366 	ast2400_calc_clock_config(clkin, rate, &div_cfg);
367 
368 	mpll_reg = readl(&scu->m_pll_param);
369 	mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK
370 		      | SCU_MPLL_DENUM_MASK);
371 	mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
372 	    | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
373 	    | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
374 
375 	writel(mpll_reg, &scu->m_pll_param);
376 
377 	return ast2400_get_mpll_rate(scu);
378 }
379 
380 static unsigned long ast2400_clk_set_rate(struct clk *clk, ulong rate)
381 {
382 	struct ast2400_clk_priv *priv = dev_get_priv(clk->dev);
383 
384 	ulong new_rate;
385 	switch (clk->id) {
386 		//mpll
387 		case ASPEED_CLK_MPLL:
388 			new_rate = ast2400_configure_ddr(priv->scu, rate);
389 			break;
390 		default:
391 			return -ENOENT;
392 	}
393 
394 	return new_rate;
395 }
396 
397 #define SCU_CLKSTOP_MAC1		(20)
398 #define SCU_CLKSTOP_MAC2		(21)
399 
400 static ulong ast2400_configure_mac(struct ast2400_scu *scu, int index)
401 {
402 	ulong hpll_rate = ast2400_get_hpll_rate(scu);
403 
404 	return 1;
405 }
406 
407 #define SCU_CLKSTOP_SDIO 27
408 static ulong ast2400_enable_sdclk(struct ast2400_scu *scu)
409 {
410 	u32 reset_bit;
411 	u32 clkstop_bit;
412 
413 	reset_bit = BIT(ASEPPD_RESET_SDIO);
414 	clkstop_bit = BIT(SCU_CLKSTOP_SDIO);
415 
416 	setbits_le32(&scu->sysreset_ctrl1, reset_bit);
417 	udelay(100);
418 	//enable clk
419 	clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
420 	mdelay(10);
421 	clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
422 
423 	return 0;
424 }
425 
426 #define SCU_CLKSTOP_EXTSD 15
427 #define SCU_CLK_SD_MASK				(0x7 << 12)
428 #define SCU_CLK_SD_DIV(x)			(x << 12)
429 
430 static ulong ast2400_enable_extsdclk(struct ast2400_scu *scu)
431 {
432 	u32 clk_sel = readl(&scu->clk_sel1);
433 	u32 enableclk_bit;
434 
435 	enableclk_bit = BIT(SCU_CLKSTOP_EXTSD);
436 
437 	// SDCLK = G4  H-PLL / 4, G5 = H-PLL /8
438 	clk_sel &= ~SCU_CLK_SD_MASK;
439 	clk_sel |= SCU_CLK_SD_DIV(1);
440 	writel(clk_sel, &scu->clk_sel1);
441 
442 	//enable clk
443 	setbits_le32(&scu->clk_sel1, enableclk_bit);
444 
445 	return 0;
446 }
447 
448 static int ast2400_clk_enable(struct clk *clk)
449 {
450 	struct ast2400_clk_priv *priv = dev_get_priv(clk->dev);
451 
452 	switch (clk->id) {
453 	/*
454 	 * For MAC clocks the clock rate is
455 	 * configured based on whether RGMII or RMII mode has been selected
456 	 * through hardware strapping.
457 	 */
458 	case ASPEED_CLK_GATE_MAC1CLK:
459 		ast2400_configure_mac(priv->scu, 1);
460 		break;
461 	case ASPEED_CLK_GATE_MAC2CLK:
462 		ast2400_configure_mac(priv->scu, 2);
463 		break;
464 	case ASPEED_CLK_GATE_SDCLK:
465 		ast2400_enable_sdclk(priv->scu);
466 		break;
467 	default:
468 		pr_debug("can't enable clk \n");
469 		return -ENOENT;
470 		break;
471 	}
472 
473 	return 0;
474 }
475 
476 struct clk_ops ast2400_clk_ops = {
477 	.get_rate = ast2400_clk_get_rate,
478 	.set_rate = ast2400_clk_set_rate,
479 	.enable = ast2400_clk_enable,
480 };
481 
482 static int ast2400_clk_probe(struct udevice *dev)
483 {
484 	struct ast2400_clk_priv *priv = dev_get_priv(dev);
485 
486 	priv->scu = devfdt_get_addr_ptr(dev);
487 	if (IS_ERR(priv->scu))
488 		return PTR_ERR(priv->scu);
489 
490 	return 0;
491 }
492 
493 static int ast2400_clk_bind(struct udevice *dev)
494 {
495 	int ret;
496 
497 	/* The reset driver does not have a device node, so bind it here */
498 	ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev);
499 	if (ret)
500 		debug("Warning: No reset driver: ret=%d\n", ret);
501 
502 	return 0;
503 }
504 
505 #if CONFIG_IS_ENABLED(CMD_CLK)
506 struct aspeed_clks {
507 	ulong id;
508 	const char *name;
509 };
510 
511 static struct aspeed_clks aspeed_clk_names[] = {
512 	{ ASPEED_CLK_UART, "uart" },
513 	{ ASPEED_CLK_HPLL, "hpll" },
514 	{ ASPEED_CLK_MPLL, "mpll" },
515 	{ ASPEED_CLK_D2PLL, "d2pll" },
516 	{ ASPEED_CLK_AHB, "hclk" },
517 	{ ASPEED_CLK_APB, "pclk" },
518 };
519 
520 int soc_clk_dump(void)
521 {
522 	struct udevice *dev;
523 	struct clk clk;
524 	unsigned long rate;
525 	int i, ret;
526 
527 	ret = uclass_get_device_by_driver(UCLASS_CLK,
528 					  DM_GET_DRIVER(aspeed_scu), &dev);
529 	if (ret)
530 		return ret;
531 
532 	printf("Clk\t\tHz\n");
533 
534 	for (i = 0; i < ARRAY_SIZE(aspeed_clk_names); i++) {
535 		clk.id = aspeed_clk_names[i].id;
536 		ret = clk_request(dev, &clk);
537 		if (ret < 0) {
538 			debug("%s clk_request() failed: %d\n", __func__, ret);
539 			continue;
540 		}
541 
542 		ret = clk_get_rate(&clk);
543 		rate = ret;
544 
545 		clk_free(&clk);
546 
547 		if (ret == -ENOTSUPP) {
548 			printf("clk ID %lu not supported yet\n",
549 			       aspeed_clk_names[i].id);
550 			continue;
551 		}
552 		if (ret < 0) {
553 			printf("%s %lu: get_rate err: %d\n",
554 			       __func__, aspeed_clk_names[i].id, ret);
555 			continue;
556 		}
557 
558 		printf("%s(%3lu):\t%lu\n",
559 		       aspeed_clk_names[i].name, aspeed_clk_names[i].id, rate);
560 	}
561 
562 	return 0;
563 }
564 #endif
565 
566 static const struct udevice_id ast2400_clk_ids[] = {
567 	{ .compatible = "aspeed,ast2400-scu" },
568 	{ }
569 };
570 
571 U_BOOT_DRIVER(aspeed_scu) = {
572 	.name		= "aspeed_scu",
573 	.id		= UCLASS_CLK,
574 	.of_match	= ast2400_clk_ids,
575 	.priv_auto_alloc_size = sizeof(struct ast2400_clk_priv),
576 	.ops		= &ast2400_clk_ops,
577 	.bind		= ast2400_clk_bind,
578 	.probe		= ast2400_clk_probe,
579 };
580