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 <asm/arch/scu_aspeed.h> 12 #include <dm/lists.h> 13 #include <dt-bindings/clock/ast2500-scu.h> 14 15 /* register */ 16 #define ASPEED_STRAP 0x70 17 #define SCU_HWSTRAP_VGAMEM_SHIFT 2 18 #define SCU_HWSTRAP_VGAMEM_MASK (3 << SCU_HWSTRAP_VGAMEM_SHIFT) 19 #define SCU_HWSTRAP_MAC1_RGMII (1 << 6) 20 #define SCU_HWSTRAP_MAC2_RGMII (1 << 7) 21 #define SCU_HWSTRAP_DDR4 (1 << 24) 22 #define SCU_HWSTRAP_CLKIN_25MHZ (1 << 23) 23 24 #define ASPEED_CLK_SELECT 0x08 25 #define SCU_PCLK_DIV_SHIFT 23 26 #define SCU_PCLK_DIV_MASK (7 << SCU_PCLK_DIV_SHIFT) 27 28 #define ASPEED_MSIC2 0x4C 29 #define SCU_MISC2_RGMII_HPLL (1 << 23) 30 #define SCU_MISC2_RGMII_CLKDIV_SHIFT 20 31 #define SCU_MISC2_RGMII_CLKDIV_MASK (3 << SCU_MISC2_RGMII_CLKDIV_SHIFT) 32 #define SCU_MISC2_RMII_MPLL (1 << 19) 33 #define SCU_MISC2_RMII_CLKDIV_SHIFT 16 34 #define SCU_MISC2_RMII_CLKDIV_MASK (3 << SCU_MISC2_RMII_CLKDIV_SHIFT) 35 #define SCU_MISC2_UARTCLK_SHIFT 24 36 37 #define ASPEED_MPLL_PARAMETER 0x20 38 #define SCU_MPLL_DENUM_SHIFT 0 39 #define SCU_MPLL_DENUM_MASK 0x1f 40 #define SCU_MPLL_NUM_SHIFT 5 41 #define SCU_MPLL_NUM_MASK (0xff << SCU_MPLL_NUM_SHIFT) 42 #define SCU_MPLL_POST_SHIFT 13 43 #define SCU_MPLL_POST_MASK (0x3f << SCU_MPLL_POST_SHIFT) 44 45 #define ASPEED_HPLL_PARAMETER 0x24 46 #define SCU_HPLL_DENUM_SHIFT 0 47 #define SCU_HPLL_DENUM_MASK 0x1f 48 #define SCU_HPLL_NUM_SHIFT 5 49 #define SCU_HPLL_NUM_MASK (0xff << SCU_HPLL_NUM_SHIFT) 50 #define SCU_HPLL_POST_SHIFT 13 51 #define SCU_HPLL_POST_MASK (0x3f << SCU_HPLL_POST_SHIFT) 52 53 54 /* 55 * MAC Clock Delay settings, taken from Aspeed SDK 56 */ 57 #define RGMII_TXCLK_ODLY 8 58 #define RMII_RXCLK_IDLY 2 59 60 /* 61 * TGMII Clock Duty constants, taken from Aspeed SDK 62 */ 63 #define RGMII2_TXCK_DUTY 0x66 64 #define RGMII1_TXCK_DUTY 0x64 65 66 #define D2PLL_DEFAULT_RATE (250 * 1000 * 1000) 67 68 DECLARE_GLOBAL_DATA_PTR; 69 70 /* 71 * Clock divider/multiplier configuration struct. 72 * For H-PLL and M-PLL the formula is 73 * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1) 74 * M - Numerator 75 * N - Denumerator 76 * P - Post Divider 77 * They have the same layout in their control register. 78 * 79 * D-PLL and D2-PLL have extra divider (OD + 1), which is not 80 * yet needed and ignored by clock configurations. 81 */ 82 struct aspeed_div_config { 83 unsigned int num; 84 unsigned int denum; 85 unsigned int post_div; 86 }; 87 88 static u32 aspeed_get_clkin(struct aspeed_clk_priv *priv) 89 { 90 switch(priv->version) { 91 case AST2400: 92 case AST2500: 93 return readl(priv->regs + ASPEED_STRAP) & SCU_HWSTRAP_CLKIN_25MHZ 94 ? 25 * 1000 * 1000 : 24 * 1000 * 1000; 95 break; 96 case AST2600: 97 return 25000000; 98 break; 99 } 100 return 0; 101 } 102 103 /* 104 * Get the rate of the M-PLL clock from input clock frequency and 105 * the value of the M-PLL Parameter Register. 106 */ 107 static u32 aspeed_get_mpll_rate(struct aspeed_clk_priv *priv) 108 { 109 u32 clkin = aspeed_get_clkin(priv); 110 u32 mpll_reg = readl(priv->regs + ASPEED_MPLL_PARAMETER); 111 112 const ulong num = (mpll_reg & SCU_MPLL_NUM_MASK) >> SCU_MPLL_NUM_SHIFT; 113 const ulong denum = (mpll_reg & SCU_MPLL_DENUM_MASK) 114 >> SCU_MPLL_DENUM_SHIFT; 115 const ulong post_div = (mpll_reg & SCU_MPLL_POST_MASK) 116 >> SCU_MPLL_POST_SHIFT; 117 118 return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1); 119 } 120 121 /* 122 * Get the rate of the H-PLL clock from input clock frequency and 123 * the value of the H-PLL Parameter Register. 124 */ 125 static ulong aspeed_get_hpll_rate(struct aspeed_clk_priv *priv) 126 { 127 ulong clkin = aspeed_get_clkin(priv); 128 u32 hpll_reg = readl(priv->regs + ASPEED_HPLL_PARAMETER); 129 const ulong num = (hpll_reg & SCU_HPLL_NUM_MASK) >> SCU_HPLL_NUM_SHIFT; 130 const ulong denum = (hpll_reg & SCU_HPLL_DENUM_MASK) 131 >> SCU_HPLL_DENUM_SHIFT; 132 const ulong post_div = (hpll_reg & SCU_HPLL_POST_MASK) 133 >> SCU_HPLL_POST_SHIFT; 134 135 return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1); 136 } 137 138 139 /** 140 * Get current rate or uart clock 141 * 142 * @scu SCU registers 143 * @uart_index UART index, 1-5 144 * 145 * @return current setting for uart clock rate 146 */ 147 static ulong aspeed_get_uart_clk_rate(struct aspeed_clk_priv *priv, int uart_index) 148 { 149 /* 150 * ast2600 datasheet is very confusing when it comes to UART clocks, 151 * especially when CLKIN = 25 MHz. The settings are in 152 * different registers and it is unclear how they interact. 153 * 154 * This has only been tested with default settings and CLKIN = 24 MHz. 155 */ 156 ulong uart_clkin; 157 158 if (readl(priv->regs + ASPEED_MSIC2) & 159 (1 << (uart_index - 1 + SCU_MISC2_UARTCLK_SHIFT))) 160 uart_clkin = 192 * 1000 * 1000; 161 else 162 uart_clkin = 24 * 1000 * 1000; 163 164 if (readl(priv->regs + ASPEED_MSIC2) & SCU_MISC_UARTCLK_DIV13) 165 uart_clkin /= 13; 166 167 return uart_clkin; 168 } 169 170 static ulong aspeed_clk_get_rate(struct clk *clk) 171 { 172 struct aspeed_clk_priv *priv = dev_get_priv(clk->dev); 173 ulong rate; 174 175 switch (clk->id) { 176 case PLL_HPLL: 177 case ARMCLK: 178 /* 179 * This ignores dynamic/static slowdown of ARMCLK and may 180 * be inaccurate. 181 */ 182 rate = aspeed_get_hpll_rate(priv); 183 184 break; 185 case MCLK_DDR: 186 rate = aspeed_get_mpll_rate(priv); 187 break; 188 case BCLK_PCLK: 189 { 190 ulong apb_div = 4 + 4 * ((readl(priv->regs + ASPEED_CLK_SELECT) 191 & SCU_PCLK_DIV_MASK) 192 >> SCU_PCLK_DIV_SHIFT); 193 rate = aspeed_get_hpll_rate(priv); 194 rate = rate / apb_div; 195 } 196 break; 197 case PCLK_UART1: 198 rate = aspeed_get_uart_clk_rate(priv, 1); 199 break; 200 case PCLK_UART2: 201 rate = aspeed_get_uart_clk_rate(priv, 2); 202 break; 203 case PCLK_UART3: 204 rate = aspeed_get_uart_clk_rate(priv, 3); 205 break; 206 case PCLK_UART4: 207 rate = aspeed_get_uart_clk_rate(priv, 4); 208 break; 209 case PCLK_UART5: 210 rate = aspeed_get_uart_clk_rate(priv, 5); 211 break; 212 default: 213 return -ENOENT; 214 } 215 216 return rate; 217 } 218 219 struct aspeed_clock_config { 220 ulong input_rate; 221 ulong rate; 222 struct aspeed_div_config cfg; 223 }; 224 225 static const struct aspeed_clock_config aspeed_clock_config_defaults[] = { 226 { 24000000, 250000000, { .num = 124, .denum = 1, .post_div = 5 } }, 227 }; 228 229 static bool aspeed_get_clock_config_default(ulong input_rate, 230 ulong requested_rate, 231 struct aspeed_div_config *cfg) 232 { 233 int i; 234 235 for (i = 0; i < ARRAY_SIZE(aspeed_clock_config_defaults); i++) { 236 const struct aspeed_clock_config *default_cfg = 237 &aspeed_clock_config_defaults[i]; 238 if (default_cfg->input_rate == input_rate && 239 default_cfg->rate == requested_rate) { 240 *cfg = default_cfg->cfg; 241 return true; 242 } 243 } 244 245 return false; 246 } 247 248 /* 249 * @input_rate - the rate of input clock in Hz 250 * @requested_rate - desired output rate in Hz 251 * @div - this is an IN/OUT parameter, at input all fields of the config 252 * need to be set to their maximum allowed values. 253 * The result (the best config we could find), would also be returned 254 * in this structure. 255 * 256 * @return The clock rate, when the resulting div_config is used. 257 */ 258 static ulong aspeed_calc_clock_config(ulong input_rate, ulong requested_rate, 259 struct aspeed_div_config *cfg) 260 { 261 /* 262 * The assumption is that kHz precision is good enough and 263 * also enough to avoid overflow when multiplying. 264 */ 265 const ulong input_rate_khz = input_rate / 1000; 266 const ulong rate_khz = requested_rate / 1000; 267 const struct aspeed_div_config max_vals = *cfg; 268 struct aspeed_div_config it = { 0, 0, 0 }; 269 ulong delta = rate_khz; 270 ulong new_rate_khz = 0; 271 272 /* 273 * Look for a well known frequency first. 274 */ 275 if (aspeed_get_clock_config_default(input_rate, requested_rate, cfg)) 276 return requested_rate; 277 278 for (; it.denum <= max_vals.denum; ++it.denum) { 279 for (it.post_div = 0; it.post_div <= max_vals.post_div; 280 ++it.post_div) { 281 it.num = (rate_khz * (it.post_div + 1) / input_rate_khz) 282 * (it.denum + 1); 283 if (it.num > max_vals.num) 284 continue; 285 286 new_rate_khz = (input_rate_khz 287 * ((it.num + 1) / (it.denum + 1))) 288 / (it.post_div + 1); 289 290 /* Keep the rate below requested one. */ 291 if (new_rate_khz > rate_khz) 292 continue; 293 294 if (new_rate_khz - rate_khz < delta) { 295 delta = new_rate_khz - rate_khz; 296 *cfg = it; 297 if (delta == 0) 298 return new_rate_khz * 1000; 299 } 300 } 301 } 302 303 return new_rate_khz * 1000; 304 } 305 306 static u32 aspeed_configure_ddr(struct aspeed_clk_priv *priv, ulong rate) 307 { 308 u32 clkin = aspeed_get_clkin(priv); 309 u32 mpll_reg; 310 struct aspeed_div_config div_cfg = { 311 .num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT), 312 .denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT), 313 .post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT), 314 }; 315 316 aspeed_calc_clock_config(clkin, rate, &div_cfg); 317 318 mpll_reg = readl(priv->regs + ASPEED_MPLL_PARAMETER); 319 mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK 320 | SCU_MPLL_DENUM_MASK); 321 mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT) 322 | (div_cfg.num << SCU_MPLL_NUM_SHIFT) 323 | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT); 324 325 writel(mpll_reg, priv->regs + ASPEED_MPLL_PARAMETER); 326 327 return aspeed_get_mpll_rate(priv); 328 } 329 330 static u32 aspeed_configure_mac(struct aspeed_clk_priv *priv, int index) 331 { 332 u32 clkin = aspeed_get_clkin(priv); 333 u32 hpll_rate = aspeed_get_hpll_rate(priv); 334 ulong required_rate; 335 u32 hwstrap; 336 u32 divisor; 337 u32 reset_bit; 338 u32 clkstop_bit; 339 #if 0 340 /* 341 * According to data sheet, for 10/100 mode the MAC clock frequency 342 * should be at least 25MHz and for 1000 mode at least 100MHz 343 */ 344 hwstrap = readl(priv->regs + ASPEED_STRAP); 345 if (hwstrap & (SCU_HWSTRAP_MAC1_RGMII | SCU_HWSTRAP_MAC2_RGMII)) 346 required_rate = 100 * 1000 * 1000; 347 else 348 required_rate = 25 * 1000 * 1000; 349 350 divisor = hpll_rate / required_rate; 351 352 if (divisor < 4) { 353 /* Clock can't run fast enough, but let's try anyway */ 354 debug("MAC clock too slow\n"); 355 divisor = 4; 356 } else if (divisor > 16) { 357 /* Can't slow down the clock enough, but let's try anyway */ 358 debug("MAC clock too fast\n"); 359 divisor = 16; 360 } 361 362 switch (index) { 363 case 1: 364 reset_bit = SCU_SYSRESET_MAC1; 365 clkstop_bit = SCU_CLKSTOP_MAC1; 366 break; 367 case 2: 368 reset_bit = SCU_SYSRESET_MAC2; 369 clkstop_bit = SCU_CLKSTOP_MAC2; 370 break; 371 default: 372 return -EINVAL; 373 } 374 375 clrsetbits_le32(priv->regs + ASPEED_CLK_SELECT, SCU_MACCLK_MASK, 376 ((divisor - 2) / 2) << SCU_MACCLK_SHIFT); 377 378 /* 379 * Disable MAC, start its clock and re-enable it. 380 * The procedure and the delays (100us & 10ms) are 381 * specified in the datasheet. 382 */ 383 setbits_le32(&scu->sysreset_ctrl1, reset_bit); 384 udelay(100); 385 clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit); 386 mdelay(10); 387 clrbits_le32(&scu->sysreset_ctrl1, reset_bit); 388 389 writel((RGMII2_TXCK_DUTY << SCU_CLKDUTY_RGMII2TXCK_SHIFT) 390 | (RGMII1_TXCK_DUTY << SCU_CLKDUTY_RGMII1TXCK_SHIFT), 391 &scu->clk_duty_sel); 392 #endif 393 return required_rate; 394 } 395 396 static ulong aspeed_configure_d2pll(struct aspeed_clk_priv *priv, ulong rate) 397 { 398 /* 399 * The values and the meaning of the next three 400 * parameters are undocumented. Taken from Aspeed SDK. 401 * 402 * TODO(clg@kaod.org): the SIP and SIC values depend on the 403 * Numerator value 404 */ 405 406 const u32 d2_pll_ext_param = 0x2c; 407 const u32 d2_pll_sip = 0x11; 408 const u32 d2_pll_sic = 0x18; 409 u32 clk_delay_settings = 410 (RMII_RXCLK_IDLY << SCU_MICDS_MAC1RMII_RDLY_SHIFT) 411 | (RMII_RXCLK_IDLY << SCU_MICDS_MAC2RMII_RDLY_SHIFT) 412 | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT) 413 | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT); 414 struct aspeed_div_config div_cfg = { 415 .num = SCU_D2PLL_NUM_MASK >> SCU_D2PLL_NUM_SHIFT, 416 .denum = SCU_D2PLL_DENUM_MASK >> SCU_D2PLL_DENUM_SHIFT, 417 .post_div = SCU_D2PLL_POST_MASK >> SCU_D2PLL_POST_SHIFT, 418 }; 419 ulong clkin = aspeed_get_clkin(priv); 420 ulong new_rate; 421 #if 0 422 writel((d2_pll_ext_param << SCU_D2PLL_EXT1_PARAM_SHIFT) 423 | SCU_D2PLL_EXT1_OFF 424 | SCU_D2PLL_EXT1_RESET, &scu->d2_pll_ext_param[0]); 425 426 /* 427 * Select USB2.0 port1 PHY clock as a clock source for GCRT. 428 * This would disconnect it from D2-PLL. 429 */ 430 clrsetbits_le32(&scu->misc_ctrl1, SCU_MISC_D2PLL_OFF, 431 SCU_MISC_GCRT_USB20CLK); 432 433 new_rate = aspeed_calc_clock_config(clkin, rate, &div_cfg); 434 writel((d2_pll_sip << SCU_D2PLL_SIP_SHIFT) 435 | (d2_pll_sic << SCU_D2PLL_SIC_SHIFT) 436 | (div_cfg.num << SCU_D2PLL_NUM_SHIFT) 437 | (div_cfg.denum << SCU_D2PLL_DENUM_SHIFT) 438 | (div_cfg.post_div << SCU_D2PLL_POST_SHIFT), 439 &scu->d2_pll_param); 440 441 clrbits_le32(&scu->d2_pll_ext_param[0], 442 SCU_D2PLL_EXT1_OFF | SCU_D2PLL_EXT1_RESET); 443 444 clrsetbits_le32(&scu->misc_ctrl2, 445 SCU_MISC2_RGMII_HPLL | SCU_MISC2_RMII_MPLL 446 | SCU_MISC2_RGMII_CLKDIV_MASK | 447 SCU_MISC2_RMII_CLKDIV_MASK, 448 (4 << SCU_MISC2_RMII_CLKDIV_SHIFT)); 449 450 writel(clk_delay_settings | SCU_MICDS_RGMIIPLL, &scu->mac_clk_delay); 451 writel(clk_delay_settings, &scu->mac_clk_delay_100M); 452 writel(clk_delay_settings, &scu->mac_clk_delay_10M); 453 #endif 454 return new_rate; 455 } 456 457 static ulong aspeed_clk_set_rate(struct clk *clk, ulong rate) 458 { 459 struct aspeed_clk_priv *priv = dev_get_priv(clk->dev); 460 461 ulong new_rate; 462 switch (clk->id) { 463 case PLL_MPLL: 464 case MCLK_DDR: 465 new_rate = aspeed_configure_ddr(priv, rate); 466 break; 467 case PLL_D2PLL: 468 new_rate = aspeed_configure_d2pll(priv, rate); 469 break; 470 default: 471 return -ENOENT; 472 } 473 474 return new_rate; 475 } 476 477 static int aspeed_clk_enable(struct clk *clk) 478 { 479 struct aspeed_clk_priv *priv = dev_get_priv(clk->dev); 480 481 switch (clk->id) { 482 /* 483 * For MAC clocks the clock rate is 484 * configured based on whether RGMII or RMII mode has been selected 485 * through hardware strapping. 486 */ 487 case PCLK_MAC1: 488 aspeed_configure_mac(priv, 1); 489 break; 490 case PCLK_MAC2: 491 aspeed_configure_mac(priv, 2); 492 break; 493 case PLL_D2PLL: 494 aspeed_configure_d2pll(priv, D2PLL_DEFAULT_RATE); 495 break; 496 default: 497 return -ENOENT; 498 } 499 500 return 0; 501 } 502 503 struct clk_ops aspeed_clk_ops = { 504 .get_rate = aspeed_clk_get_rate, 505 .set_rate = aspeed_clk_set_rate, 506 .enable = aspeed_clk_enable, 507 }; 508 509 static int aspeed_clk_probe(struct udevice *dev) 510 { 511 struct aspeed_clk_priv *priv = dev_get_priv(dev); 512 513 priv->regs = devfdt_get_addr_ptr(dev); 514 515 if (IS_ERR(priv->regs)) 516 return PTR_ERR(priv->regs); 517 518 priv->version = dev_get_driver_data(dev); 519 520 return 0; 521 } 522 523 static int aspeed_clk_bind(struct udevice *dev) 524 { 525 int ret; 526 527 /* The reset driver does not have a device node, so bind it here */ 528 ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev); 529 if (ret) 530 debug("Warning: No reset driver: ret=%d\n", ret); 531 532 return 0; 533 } 534 535 static const struct udevice_id aspeed_clk_ids[] = { 536 { .compatible = "aspeed,ast2500-scu", .data = AST2500}, 537 { .compatible = "aspeed,ast2600-scu", .data = AST2600}, 538 { } 539 }; 540 541 U_BOOT_DRIVER(aspeed_scu) = { 542 .name = "aspeed_scu", 543 .id = UCLASS_CLK, 544 .of_match = aspeed_clk_ids, 545 .priv_auto_alloc_size = sizeof(struct aspeed_clk_priv), 546 .ops = &aspeed_clk_ops, 547 .bind = aspeed_clk_bind, 548 .probe = aspeed_clk_probe, 549 }; 550