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