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_ast2600.h> 12 #include <dt-bindings/clock/ast2600-clock.h> 13 #include <dt-bindings/reset/ast2600-reset.h> 14 15 /* 16 * MAC Clock Delay settings, taken from Aspeed SDK 17 */ 18 #define RGMII_TXCLK_ODLY 8 19 #define RMII_RXCLK_IDLY 2 20 21 #define MAC_DEF_DELAY_1G 0x00410410 22 #define MAC_DEF_DELAY_100M 0x00410410 23 #define MAC_DEF_DELAY_10M 0x00410410 24 25 #define MAC34_DEF_DELAY_1G 0x00104208 26 #define MAC34_DEF_DELAY_100M 0x00104208 27 #define MAC34_DEF_DELAY_10M 0x00104208 28 29 /* 30 * TGMII Clock Duty constants, taken from Aspeed SDK 31 */ 32 #define RGMII2_TXCK_DUTY 0x66 33 #define RGMII1_TXCK_DUTY 0x64 34 35 #define D2PLL_DEFAULT_RATE (250 * 1000 * 1000) 36 37 DECLARE_GLOBAL_DATA_PTR; 38 39 /* 40 * Clock divider/multiplier configuration struct. 41 * For H-PLL and M-PLL the formula is 42 * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1) 43 * M - Numerator 44 * N - Denumerator 45 * P - Post Divider 46 * They have the same layout in their control register. 47 * 48 * D-PLL and D2-PLL have extra divider (OD + 1), which is not 49 * yet needed and ignored by clock configurations. 50 */ 51 union ast2600_pll_reg { 52 unsigned int w; 53 struct { 54 unsigned int m : 13; /* 12:0 */ 55 unsigned int n : 6; /* 18:13 */ 56 unsigned int p : 4; /* 22:19 */ 57 unsigned int reserved : 9; /* 31:20 */ 58 } b; 59 }; 60 61 struct ast2600_pll_cfg { 62 union ast2600_pll_reg reg; 63 unsigned int ext_reg; 64 }; 65 66 struct ast2600_pll_desc { 67 u32 in; 68 u32 out; 69 struct ast2600_pll_cfg cfg; 70 }; 71 72 static const struct ast2600_pll_desc ast2600_pll_lookup[] = { 73 {.in = AST2600_CLK_IN, .out = 400000000, 74 .cfg.reg.b.m = 95, .cfg.reg.b.n = 2, .cfg.reg.b.p = 1, 75 .cfg.ext_reg = 0x31, 76 }, 77 {.in = AST2600_CLK_IN, .out = 200000000, 78 .cfg.reg.b.m = 127, .cfg.reg.b.n = 0, .cfg.reg.b.p = 15, 79 .cfg.ext_reg = 0x3f 80 }, 81 {.in = AST2600_CLK_IN, .out = 334000000, 82 .cfg.reg.b.m = 667, .cfg.reg.b.n = 4, .cfg.reg.b.p = 9, 83 .cfg.ext_reg = 0x14d 84 }, 85 86 {.in = AST2600_CLK_IN, .out = 1000000000, 87 .cfg.reg.b.m = 119, .cfg.reg.b.n = 2, .cfg.reg.b.p = 0, 88 .cfg.ext_reg = 0x3d 89 }, 90 91 {.in = AST2600_CLK_IN, .out = 50000000, 92 .cfg.reg.b.m = 95, .cfg.reg.b.n = 2, .cfg.reg.b.p = 15, 93 .cfg.ext_reg = 0x31 94 }, 95 }; 96 97 extern u32 ast2600_get_pll_rate(struct ast2600_scu *scu, int pll_idx) 98 { 99 u32 clkin = AST2600_CLK_IN; 100 u32 pll_reg = 0; 101 unsigned int mult, div = 1; 102 103 switch(pll_idx) { 104 case ASPEED_CLK_HPLL: 105 pll_reg = readl(&scu->h_pll_param); 106 break; 107 case ASPEED_CLK_MPLL: 108 pll_reg = readl(&scu->m_pll_param); 109 break; 110 case ASPEED_CLK_DPLL: 111 pll_reg = readl(&scu->d_pll_param); 112 break; 113 case ASPEED_CLK_EPLL: 114 pll_reg = readl(&scu->e_pll_param); 115 break; 116 117 } 118 if (pll_reg & BIT(24)) { 119 /* Pass through mode */ 120 mult = div = 1; 121 } else { 122 /* F = 25Mhz * [(M + 2) / (n + 1)] / (p + 1) */ 123 union ast2600_pll_reg reg; 124 reg.w = pll_reg; 125 mult = (reg.b.m + 1) / (reg.b.n + 1); 126 div = (reg.b.p + 1); 127 } 128 return ((clkin * mult)/div); 129 130 } 131 132 extern u32 ast2600_get_apll_rate(struct ast2600_scu *scu) 133 { 134 u32 clkin = AST2600_CLK_IN; 135 u32 apll_reg = readl(&scu->a_pll_param); 136 unsigned int mult, div = 1; 137 138 if (apll_reg & BIT(20)) { 139 /* Pass through mode */ 140 mult = div = 1; 141 } else { 142 /* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */ 143 u32 m = (apll_reg >> 5) & 0x3f; 144 u32 od = (apll_reg >> 4) & 0x1; 145 u32 n = apll_reg & 0xf; 146 147 mult = (2 - od) * (m + 2); 148 div = n + 1; 149 } 150 return ((clkin * mult)/div); 151 } 152 153 static u32 ast2600_a0_axi_ahb_div_table[] = { 154 2, 2, 3, 5, 155 }; 156 157 static u32 ast2600_a1_axi_ahb_div_table[] = { 158 4, 6, 2, 4, 159 }; 160 161 static u32 ast2600_get_hclk(struct ast2600_scu *scu) 162 { 163 u32 hw_rev = readl(&scu->chip_id0); 164 u32 hwstrap1 = readl(&scu->hwstrap1); 165 u32 axi_div = 1; 166 u32 ahb_div = 0; 167 u32 rate = 0; 168 169 if(hwstrap1 & BIT(16)) 170 axi_div = 1; 171 else 172 axi_div = 2; 173 174 if (hw_rev & BIT(16)) 175 ahb_div = ast2600_a1_axi_ahb_div_table[(hwstrap1 >> 11) & 0x3]; 176 else 177 ahb_div = ast2600_a0_axi_ahb_div_table[(hwstrap1 >> 11) & 0x3]; 178 179 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL); 180 181 return (rate / axi_div / ahb_div); 182 } 183 184 static u32 ast2600_hpll_pclk1_div_table[] = { 185 4, 8, 12, 16, 20, 24, 28, 32, 186 }; 187 188 static u32 ast2600_hpll_pclk2_div_table[] = { 189 2, 4, 6, 8, 10, 12, 14, 16, 190 }; 191 192 static u32 ast2600_get_pclk1(struct ast2600_scu *scu) 193 { 194 u32 clk_sel1 = readl(&scu->clk_sel1); 195 u32 apb_div = ast2600_hpll_pclk1_div_table[((clk_sel1 >> 23) & 0x7)]; 196 u32 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL); 197 198 return (rate / apb_div); 199 } 200 201 static u32 ast2600_get_pclk2(struct ast2600_scu *scu) 202 { 203 u32 clk_sel4 = readl(&scu->clk_sel4); 204 u32 apb_div = ast2600_hpll_pclk2_div_table[((clk_sel4 >> 9) & 0x7)]; 205 u32 rate = ast2600_get_hclk(scu); 206 207 return (rate / apb_div); 208 } 209 210 static u32 ast2600_get_uxclk_rate(struct ast2600_scu *scu) 211 { 212 u32 clk_in = 0; 213 u32 uxclk_sel = readl(&scu->clk_sel4); 214 215 uxclk_sel &= 0x3; 216 switch(uxclk_sel) { 217 case 0: 218 clk_in = ast2600_get_apll_rate(scu) / 4; 219 break; 220 case 1: 221 clk_in = ast2600_get_apll_rate(scu) / 2; 222 break; 223 case 2: 224 clk_in = ast2600_get_apll_rate(scu); 225 break; 226 case 3: 227 clk_in = ast2600_get_hclk(scu); 228 break; 229 } 230 231 return clk_in; 232 } 233 234 static u32 ast2600_get_huxclk_rate(struct ast2600_scu *scu) 235 { 236 u32 clk_in = 0; 237 u32 huclk_sel = readl(&scu->clk_sel4); 238 239 huclk_sel = ((huclk_sel >> 3) & 0x3); 240 switch(huclk_sel) { 241 case 0: 242 clk_in = ast2600_get_apll_rate(scu) / 4; 243 break; 244 case 1: 245 clk_in = ast2600_get_apll_rate(scu) / 2; 246 break; 247 case 2: 248 clk_in = ast2600_get_apll_rate(scu); 249 break; 250 case 3: 251 clk_in = ast2600_get_hclk(scu); 252 break; 253 } 254 255 return clk_in; 256 } 257 258 static u32 ast2600_get_uart_from_uxclk_rate(struct ast2600_scu *scu) 259 { 260 u32 clk_in = ast2600_get_uxclk_rate(scu); 261 u32 div_reg = readl(&scu->uart_24m_ref_uxclk); 262 unsigned int mult, div; 263 264 u32 n = (div_reg >> 8) & 0x3ff; 265 u32 r = div_reg & 0xff; 266 267 mult = r; 268 div = (n * 4); 269 return (clk_in * mult)/div; 270 } 271 272 static u32 ast2600_get_uart_from_huxclk_rate(struct ast2600_scu *scu) 273 { 274 u32 clk_in = ast2600_get_huxclk_rate(scu); 275 u32 div_reg = readl(&scu->uart_24m_ref_huxclk); 276 277 unsigned int mult, div; 278 279 u32 n = (div_reg >> 8) & 0x3ff; 280 u32 r = div_reg & 0xff; 281 282 mult = r; 283 div = (n * 4); 284 return (clk_in * mult)/div; 285 } 286 287 static u32 ast2600_get_sdio_clk_rate(struct ast2600_scu *scu) 288 { 289 u32 clkin = 0; 290 u32 clk_sel = readl(&scu->clk_sel4); 291 u32 div = (clk_sel >> 28) & 0x7; 292 293 if(clk_sel & BIT(8)) { 294 clkin = ast2600_get_apll_rate(scu); 295 } else { 296 clkin = 200 * 1000 * 1000; 297 } 298 div = (div + 1) << 1; 299 300 return (clkin / div); 301 } 302 303 static u32 ast2600_get_emmc_clk_rate(struct ast2600_scu *scu) 304 { 305 u32 clkin = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL); 306 u32 clk_sel = readl(&scu->clk_sel1); 307 u32 div = (clk_sel >> 12) & 0x7; 308 309 div = (div + 1) << 2; 310 311 return (clkin / div); 312 } 313 314 static u32 ast2600_get_uart_clk_rate(struct ast2600_scu *scu, int uart_idx) 315 { 316 u32 uart_sel = readl(&scu->clk_sel4); 317 u32 uart_sel5 = readl(&scu->clk_sel5); 318 ulong uart_clk = 0; 319 320 switch(uart_idx) { 321 case 1: 322 case 2: 323 case 3: 324 case 4: 325 case 6: 326 if(uart_sel & BIT(uart_idx - 1)) 327 uart_clk = ast2600_get_uart_from_uxclk_rate(scu)/13 ; 328 else 329 uart_clk = ast2600_get_uart_from_huxclk_rate(scu)/13 ; 330 break; 331 case 5: //24mhz is come form usb phy 48Mhz 332 { 333 u8 uart5_clk_sel = 0; 334 //high bit 335 if (readl(&scu->misc_ctrl1) & BIT(12)) 336 uart5_clk_sel = 0x2; 337 else 338 uart5_clk_sel = 0x0; 339 340 if (readl(&scu->clk_sel2) & BIT(14)) 341 uart5_clk_sel |= 0x1; 342 343 switch(uart5_clk_sel) { 344 case 0: 345 uart_clk = 24000000; 346 break; 347 case 1: 348 uart_clk = 0; 349 break; 350 case 2: 351 uart_clk = 24000000/13; 352 break; 353 case 3: 354 uart_clk = 192000000/13; 355 break; 356 } 357 } 358 break; 359 case 7: 360 case 8: 361 case 9: 362 case 10: 363 case 11: 364 case 12: 365 case 13: 366 if(uart_sel5 & BIT(uart_idx - 1)) 367 uart_clk = ast2600_get_uart_from_uxclk_rate(scu)/13 ; 368 else 369 uart_clk = ast2600_get_uart_from_huxclk_rate(scu)/13 ; 370 break; 371 } 372 373 return uart_clk; 374 } 375 376 static ulong ast2600_clk_get_rate(struct clk *clk) 377 { 378 struct ast2600_clk_priv *priv = dev_get_priv(clk->dev); 379 ulong rate = 0; 380 381 switch (clk->id) { 382 case ASPEED_CLK_HPLL: 383 case ASPEED_CLK_EPLL: 384 case ASPEED_CLK_DPLL: 385 case ASPEED_CLK_MPLL: 386 rate = ast2600_get_pll_rate(priv->scu, clk->id); 387 break; 388 case ASPEED_CLK_AHB: 389 rate = ast2600_get_hclk(priv->scu); 390 break; 391 case ASPEED_CLK_APB1: 392 rate = ast2600_get_pclk1(priv->scu); 393 break; 394 case ASPEED_CLK_APB2: 395 rate = ast2600_get_pclk2(priv->scu); 396 break; 397 case ASPEED_CLK_APLL: 398 rate = ast2600_get_apll_rate(priv->scu); 399 break; 400 case ASPEED_CLK_GATE_UART1CLK: 401 rate = ast2600_get_uart_clk_rate(priv->scu, 1); 402 break; 403 case ASPEED_CLK_GATE_UART2CLK: 404 rate = ast2600_get_uart_clk_rate(priv->scu, 2); 405 break; 406 case ASPEED_CLK_GATE_UART3CLK: 407 rate = ast2600_get_uart_clk_rate(priv->scu, 3); 408 break; 409 case ASPEED_CLK_GATE_UART4CLK: 410 rate = ast2600_get_uart_clk_rate(priv->scu, 4); 411 break; 412 case ASPEED_CLK_GATE_UART5CLK: 413 rate = ast2600_get_uart_clk_rate(priv->scu, 5); 414 break; 415 case ASPEED_CLK_SDIO: 416 rate = ast2600_get_sdio_clk_rate(priv->scu); 417 break; 418 case ASPEED_CLK_EMMC: 419 rate = ast2600_get_emmc_clk_rate(priv->scu); 420 break; 421 default: 422 pr_debug("can't get clk rate \n"); 423 return -ENOENT; 424 break; 425 } 426 427 return rate; 428 } 429 430 /** 431 * @brief lookup PLL divider config by input/output rate 432 * @param[in] *pll - PLL descriptor 433 * @return true - if PLL divider config is found, false - else 434 * 435 * The function caller shall fill "pll->in" and "pll->out", then this function 436 * will search the lookup table to find a valid PLL divider configuration. 437 */ 438 static bool ast2600_search_clock_config(struct ast2600_pll_desc *pll) 439 { 440 u32 i; 441 bool is_found = false; 442 443 for (i = 0; i < ARRAY_SIZE(ast2600_pll_lookup); i++) { 444 const struct ast2600_pll_desc *def_cfg = &ast2600_pll_lookup[i]; 445 if ((def_cfg->in == pll->in) && (def_cfg->out == pll->out)) { 446 is_found = true; 447 pll->cfg.reg.w = def_cfg->cfg.reg.w; 448 pll->cfg.ext_reg = def_cfg->cfg.ext_reg; 449 break; 450 } 451 } 452 return is_found; 453 } 454 455 static u32 ast2600_configure_ddr(struct ast2600_scu *scu, ulong rate) 456 { 457 u32 mpll_reg; 458 struct ast2600_pll_desc mpll; 459 460 mpll.in = AST2600_CLK_IN; 461 mpll.out = rate; 462 if (false == ast2600_search_clock_config(&mpll)) { 463 printf("error!! unable to find valid DDR clock setting\n"); 464 return 0; 465 } 466 467 mpll_reg = readl(&scu->m_pll_param); 468 mpll_reg &= ~GENMASK(22, 0); 469 mpll_reg |= mpll.cfg.reg.w; 470 writel(mpll_reg, &scu->m_pll_param); 471 472 /* write extend parameter */ 473 writel(mpll.cfg.ext_reg, &scu->m_pll_ext_param); 474 475 return ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL); 476 } 477 478 static ulong ast2600_clk_set_rate(struct clk *clk, ulong rate) 479 { 480 struct ast2600_clk_priv *priv = dev_get_priv(clk->dev); 481 482 ulong new_rate; 483 switch (clk->id) { 484 case ASPEED_CLK_MPLL: 485 new_rate = ast2600_configure_ddr(priv->scu, rate); 486 break; 487 default: 488 return -ENOENT; 489 } 490 491 return new_rate; 492 } 493 494 #define SCU_CLKSTOP_MAC1 (20) 495 #define SCU_CLKSTOP_MAC2 (21) 496 #define SCU_CLKSTOP_MAC3 (20) 497 #define SCU_CLKSTOP_MAC4 (21) 498 499 static u32 ast2600_configure_mac12_clk(struct ast2600_scu *scu) 500 { 501 u32 epll_reg; 502 u32 clksel; 503 u32 clkdelay; 504 505 struct ast2600_pll_desc epll; 506 507 epll.in = AST2600_CLK_IN; 508 epll.out = 1000000000; 509 if (false == ast2600_search_clock_config(&epll)) { 510 printf( 511 "error!! unable to find valid ETHNET MAC clock setting\n"); 512 debug("%s: epll cfg = 0x%08x 0x%08x\n", __func__, 513 epll.cfg.reg.w, epll.cfg.ext_reg); 514 debug("%s: epll cfg = %02x %02x %02x\n", __func__, 515 epll.cfg.reg.b.m, epll.cfg.reg.b.n, epll.cfg.reg.b.p); 516 return 0; 517 } 518 519 epll_reg = readl(&scu->e_pll_param); 520 epll_reg &= ~GENMASK(22, 0); 521 epll_reg |= epll.cfg.reg.w; 522 writel(epll_reg, &scu->e_pll_param); 523 524 /* write extend parameter */ 525 writel(epll.cfg.ext_reg, &scu->e_pll_ext_param); 526 527 /* select MAC#1 and MAC#2 clock source = EPLL / 8 */ 528 clksel = readl(&scu->clk_sel2); 529 clksel &= ~BIT(23); 530 clksel |= 0x7 << 20; 531 writel(clksel, &scu->clk_sel2); 532 533 /* 534 BIT(31): select RGMII 125M from internal source 535 BIT(28): RGMII 125M output enable 536 BIT(25:0): 1G default delay 537 */ 538 clkdelay = MAC_DEF_DELAY_1G | BIT(31) | BIT(28); 539 writel(clkdelay, &scu->mac12_clk_delay); 540 541 /* set 100M/10M default delay */ 542 writel(MAC_DEF_DELAY_100M, &scu->mac12_clk_delay_100M); 543 writel(MAC_DEF_DELAY_10M, &scu->mac12_clk_delay_10M); 544 545 /* MAC AHB = HPLL / 6 */ 546 clksel = readl(&scu->clk_sel1); 547 clksel &= ~GENMASK(18, 16); 548 clksel |= 0x2 << 16; 549 writel(clksel, &scu->clk_sel1); 550 551 return 0; 552 } 553 554 static u32 ast2600_configure_mac34_clk(struct ast2600_scu *scu) 555 { 556 u32 reg; 557 558 ast2600_configure_mac12_clk(scu); 559 560 /* 561 BIT[31] RGMII 125M source: 0 = from IO pin 562 BIT[25:0] MAC 1G delay 563 */ 564 reg = readl(&scu->mac34_clk_delay); 565 reg &= ~(BIT(31) | GENMASK(25, 0)); 566 reg |= MAC34_DEF_DELAY_1G; 567 writel(reg, &scu->mac34_clk_delay); 568 writel(MAC34_DEF_DELAY_100M, &scu->mac34_clk_delay_100M); 569 writel(MAC34_DEF_DELAY_10M, &scu->mac34_clk_delay_10M); 570 571 /* clock source seletion and divider */ 572 reg = readl(&scu->clk_sel4); 573 reg &= ~GENMASK(26, 24); /* MAC AHB = HCLK / 2 */ 574 reg &= ~GENMASK(18, 16); 575 reg |= 0x3 << 16; /* RMII 50M = SLICLK_200M / 4 */ 576 writel(reg, &scu->clk_sel4); 577 578 /* set driving strength */ 579 reg = readl(&scu->pinmux_ctrl16); 580 reg &= GENMASK(3, 0); 581 reg |= (0x2 << 0) | (0x2 << 2); 582 writel(reg, &scu->pinmux_ctrl16); 583 584 return 0; 585 } 586 #if 0 587 /** 588 * WIP: ast2600 RGMII clock source tree 589 * 590 * 125M from external PAD -------->|\ 591 * HPLL -->|\ | |---->RGMII 125M for MAC#1 & MAC#2 592 * | |---->| divider |---->|/ + 593 * EPLL -->|/ | 594 * | 595 * +---------<-----------|PAD output enable|<---------------------+ 596 * | 597 * +--->|PAD input enable|----->|\ 598 * | |----> RGMII 125M for MAC#3 & MAC#4 599 * SLICLK 200M -->|divider|---->|/ 600 */ 601 struct ast2600_rgmii_clk_config { 602 u32 mac_1_2_src; /* 0=external PAD, 1=internal PLL */ 603 u32 int_clk_src; /* 0=EPLL, 1=HPLL */ 604 u32 int_clk_div; 605 606 u32 mac_3_4_src; /* 0=external PAD, 1=SLICLK */ 607 u32 sli_clk_div; /* reserved */ 608 }; 609 610 static void ast2600_init_rgmii_clk(struct ast2600_scu *scu, int index) 611 { 612 debug("%s not ready\n", __func__); 613 } 614 615 static void ast2600_init_rmii_clk(struct ast2600_scu *scu, int index) 616 { 617 debug("%s not ready\n", __func__); 618 } 619 #endif 620 static u32 ast2600_configure_mac(struct ast2600_scu *scu, int index) 621 { 622 u32 reset_bit; 623 u32 clkstop_bit; 624 625 if (index < 3) 626 ast2600_configure_mac12_clk(scu); 627 else 628 ast2600_configure_mac34_clk(scu); 629 630 switch (index) { 631 case 1: 632 reset_bit = BIT(ASPEED_RESET_MAC1); 633 clkstop_bit = BIT(SCU_CLKSTOP_MAC1); 634 writel(reset_bit, &scu->sysreset_ctrl1); 635 udelay(100); 636 writel(clkstop_bit, &scu->clk_stop_clr_ctrl1); 637 mdelay(10); 638 writel(reset_bit, &scu->sysreset_clr_ctrl1); 639 640 break; 641 case 2: 642 reset_bit = BIT(ASPEED_RESET_MAC2); 643 clkstop_bit = BIT(SCU_CLKSTOP_MAC2); 644 writel(reset_bit, &scu->sysreset_ctrl1); 645 udelay(100); 646 writel(clkstop_bit, &scu->clk_stop_clr_ctrl1); 647 mdelay(10); 648 writel(reset_bit, &scu->sysreset_clr_ctrl1); 649 break; 650 case 3: 651 reset_bit = BIT(ASPEED_RESET_MAC3 - 32); 652 clkstop_bit = BIT(SCU_CLKSTOP_MAC3); 653 writel(reset_bit, &scu->sysreset_ctrl2); 654 udelay(100); 655 writel(clkstop_bit, &scu->clk_stop_clr_ctrl2); 656 mdelay(10); 657 writel(reset_bit, &scu->sysreset_clr_ctrl2); 658 break; 659 case 4: 660 reset_bit = BIT(ASPEED_RESET_MAC4 - 32); 661 clkstop_bit = BIT(SCU_CLKSTOP_MAC4); 662 writel(reset_bit, &scu->sysreset_ctrl2); 663 udelay(100); 664 writel(clkstop_bit, &scu->clk_stop_clr_ctrl2); 665 mdelay(10); 666 writel(reset_bit, &scu->sysreset_clr_ctrl2); 667 break; 668 default: 669 return -EINVAL; 670 } 671 672 return 0; 673 } 674 675 #define SCU_CLKSTOP_SDIO 4 676 static ulong ast2600_enable_sdclk(struct ast2600_scu *scu) 677 { 678 u32 reset_bit; 679 u32 clkstop_bit; 680 681 reset_bit = BIT(ASPEED_RESET_SD - 32); 682 clkstop_bit = BIT(SCU_CLKSTOP_SDIO); 683 684 writel(reset_bit, &scu->sysreset_clr_ctrl2); 685 udelay(100); 686 //enable clk 687 writel(clkstop_bit, &scu->clk_stop_clr_ctrl2); 688 mdelay(10); 689 writel(reset_bit, &scu->sysreset_ctrl2); 690 691 return 0; 692 } 693 694 #define SCU_CLKSTOP_EXTSD 31 695 #define SCU_CLK_SD_MASK (0x7 << 28) 696 #define SCU_CLK_SD_DIV(x) (x << 28) 697 698 static ulong ast2600_enable_extsdclk(struct ast2600_scu *scu) 699 { 700 u32 clk_sel = readl(&scu->clk_sel4); 701 u32 enableclk_bit; 702 703 enableclk_bit = BIT(SCU_CLKSTOP_EXTSD); 704 705 clk_sel &= ~SCU_CLK_SD_MASK; 706 clk_sel |= SCU_CLK_SD_DIV(0); 707 writel(clk_sel, &scu->clk_sel4); 708 709 //enable clk 710 setbits_le32(&scu->clk_sel4, enableclk_bit); 711 712 return 0; 713 } 714 715 #define SCU_CLKSTOP_EMMC 27 716 static ulong ast2600_enable_emmcclk(struct ast2600_scu *scu) 717 { 718 u32 reset_bit; 719 u32 clkstop_bit; 720 721 reset_bit = BIT(ASPEED_RESET_EMMC); 722 clkstop_bit = BIT(SCU_CLKSTOP_EMMC); 723 724 writel(reset_bit, &scu->sysreset_clr_ctrl1); 725 udelay(100); 726 //enable clk 727 writel(clkstop_bit, &scu->clk_stop_clr_ctrl1); 728 mdelay(10); 729 writel(reset_bit, &scu->sysreset_ctrl2); 730 731 return 0; 732 } 733 734 #define SCU_CLKSTOP_EXTEMMC 15 735 #define SCU_CLK_EMMC_MASK (0x7 << 12) 736 #define SCU_CLK_EMMC_DIV(x) (x << 12) 737 738 static ulong ast2600_enable_extemmcclk(struct ast2600_scu *scu) 739 { 740 u32 clk_sel = readl(&scu->clk_sel1); 741 u32 enableclk_bit; 742 743 enableclk_bit = BIT(SCU_CLKSTOP_EXTSD); 744 745 clk_sel &= ~SCU_CLK_SD_MASK; 746 clk_sel |= SCU_CLK_SD_DIV(1); 747 writel(clk_sel, &scu->clk_sel1); 748 749 //enable clk 750 setbits_le32(&scu->clk_sel1, enableclk_bit); 751 752 return 0; 753 } 754 755 static int ast2600_clk_enable(struct clk *clk) 756 { 757 struct ast2600_clk_priv *priv = dev_get_priv(clk->dev); 758 759 switch (clk->id) { 760 case ASPEED_CLK_GATE_MAC1CLK: 761 ast2600_configure_mac(priv->scu, 1); 762 break; 763 case ASPEED_CLK_GATE_MAC2CLK: 764 ast2600_configure_mac(priv->scu, 2); 765 break; 766 case ASPEED_CLK_GATE_MAC3CLK: 767 ast2600_configure_mac(priv->scu, 3); 768 break; 769 case ASPEED_CLK_GATE_MAC4CLK: 770 ast2600_configure_mac(priv->scu, 4); 771 break; 772 case ASPEED_CLK_GATE_SDCLK: 773 ast2600_enable_sdclk(priv->scu); 774 break; 775 case ASPEED_CLK_GATE_SDEXTCLK: 776 ast2600_enable_extsdclk(priv->scu); 777 break; 778 case ASPEED_CLK_GATE_EMMCCLK: 779 ast2600_enable_emmcclk(priv->scu); 780 break; 781 case ASPEED_CLK_GATE_EMMCEXTCLK: 782 ast2600_enable_extemmcclk(priv->scu); 783 break; 784 default: 785 pr_debug("can't enable clk \n"); 786 return -ENOENT; 787 break; 788 } 789 790 return 0; 791 } 792 793 struct clk_ops ast2600_clk_ops = { 794 .get_rate = ast2600_clk_get_rate, 795 .set_rate = ast2600_clk_set_rate, 796 .enable = ast2600_clk_enable, 797 }; 798 799 static int ast2600_clk_probe(struct udevice *dev) 800 { 801 struct ast2600_clk_priv *priv = dev_get_priv(dev); 802 803 priv->scu = devfdt_get_addr_ptr(dev); 804 if (IS_ERR(priv->scu)) 805 return PTR_ERR(priv->scu); 806 807 return 0; 808 } 809 810 static int ast2600_clk_bind(struct udevice *dev) 811 { 812 int ret; 813 814 /* The reset driver does not have a device node, so bind it here */ 815 ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev); 816 if (ret) 817 debug("Warning: No reset driver: ret=%d\n", ret); 818 819 return 0; 820 } 821 822 #if CONFIG_IS_ENABLED(CMD_CLK) 823 struct aspeed_clks { 824 ulong id; 825 const char *name; 826 }; 827 828 static struct aspeed_clks aspeed_clk_names[] = { 829 { ASPEED_CLK_HPLL, "hpll" }, 830 { ASPEED_CLK_MPLL, "mpll" }, 831 { ASPEED_CLK_APLL, "apll" }, 832 { ASPEED_CLK_EPLL, "epll" }, 833 { ASPEED_CLK_DPLL, "dpll" }, 834 { ASPEED_CLK_AHB, "hclk" }, 835 { ASPEED_CLK_APB1, "pclk1" }, 836 { ASPEED_CLK_APB2, "pclk2" }, 837 }; 838 839 int soc_clk_dump(void) 840 { 841 struct udevice *dev; 842 struct clk clk; 843 unsigned long rate; 844 int i, ret; 845 846 ret = uclass_get_device_by_driver(UCLASS_CLK, 847 DM_GET_DRIVER(aspeed_scu), &dev); 848 if (ret) 849 return ret; 850 851 printf("Clk\t\tHz\n"); 852 853 for (i = 0; i < ARRAY_SIZE(aspeed_clk_names); i++) { 854 clk.id = aspeed_clk_names[i].id; 855 ret = clk_request(dev, &clk); 856 if (ret < 0) { 857 debug("%s clk_request() failed: %d\n", __func__, ret); 858 continue; 859 } 860 861 ret = clk_get_rate(&clk); 862 rate = ret; 863 864 clk_free(&clk); 865 866 if (ret == -ENOTSUPP) { 867 printf("clk ID %lu not supported yet\n", 868 aspeed_clk_names[i].id); 869 continue; 870 } 871 if (ret < 0) { 872 printf("%s %lu: get_rate err: %d\n", 873 __func__, aspeed_clk_names[i].id, ret); 874 continue; 875 } 876 877 printf("%s(%3lu):\t%lu\n", 878 aspeed_clk_names[i].name, aspeed_clk_names[i].id, rate); 879 } 880 881 return 0; 882 } 883 #endif 884 885 static const struct udevice_id ast2600_clk_ids[] = { 886 { .compatible = "aspeed,ast2600-scu", }, 887 { } 888 }; 889 890 U_BOOT_DRIVER(aspeed_scu) = { 891 .name = "aspeed_scu", 892 .id = UCLASS_CLK, 893 .of_match = ast2600_clk_ids, 894 .priv_auto_alloc_size = sizeof(struct ast2600_clk_priv), 895 .ops = &ast2600_clk_ops, 896 .bind = ast2600_clk_bind, 897 .probe = ast2600_clk_probe, 898 }; 899