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