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