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 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 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 */ 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 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 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 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 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 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 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 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 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 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