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 #define AST2600_CLK_IN 25000000 51 52 /* 53 * Get the rate of the M-PLL clock from input clock frequency and 54 * the value of the M-PLL Parameter Register. 55 */ 56 static u32 ast2600_get_mpll_rate(struct ast2600_scu *scu) 57 { 58 u32 clkin = AST2600_CLK_IN; 59 u32 mpll_reg = readl(&scu->m_pll_param); 60 unsigned int mult, div = 1; 61 62 if (mpll_reg & BIT(24)) { 63 /* Pass through mode */ 64 mult = div = 1; 65 } else { 66 /* F = 25Mhz * [(M + 2) / (n + 1)] / (p + 1) */ 67 u32 m = mpll_reg & 0x1fff; 68 u32 n = (mpll_reg >> 13) & 0x3f; 69 u32 p = (mpll_reg >> 19) & 0xf; 70 mult = (m + 1) / (n + 1); 71 div = (p + 1); 72 } 73 return ((clkin * mult)/div); 74 75 } 76 77 /* 78 * Get the rate of the H-PLL clock from input clock frequency and 79 * the value of the H-PLL Parameter Register. 80 */ 81 static ulong ast2600_get_hpll_rate(struct ast2600_scu *scu) 82 { 83 ulong clkin = AST2600_CLK_IN; 84 u32 hpll_reg = readl(&scu->h_pll_param); 85 86 const ulong num = (hpll_reg & 0x1fff); 87 const ulong denum = (hpll_reg >> 13) & 0x3f; 88 const ulong post_div = (hpll_reg >> 19) & 0xf; 89 90 return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1); 91 } 92 93 static ulong ast2600_get_apll_rate(struct ast2600_scu *scu) 94 { 95 u32 clk_in = AST2600_CLK_IN; 96 u32 apll_reg = readl(&scu->a_pll_param); 97 unsigned int mult, div = 1; 98 99 if (apll_reg & BIT(20)) { 100 /* Pass through mode */ 101 mult = div = 1; 102 } else { 103 /* F = 25Mhz * (2-OD) * [(M + 2) / (n + 1)] */ 104 u32 m = (apll_reg >> 5) & 0x3f; 105 u32 od = (apll_reg >> 4) & 0x1; 106 u32 n = apll_reg & 0xf; 107 108 mult = (2 - od) * ((m + 2) / (n + 1)); 109 } 110 return (clk_in * mult)/div; 111 } 112 113 static ulong ast2600_get_epll_rate(struct ast2600_scu *scu) 114 { 115 u32 clk_in = AST2600_CLK_IN; 116 u32 epll_reg = readl(&scu->e_pll_param); 117 unsigned int mult, div = 1; 118 119 if (epll_reg & BIT(24)) { 120 /* Pass through mode */ 121 mult = div = 1; 122 } else { 123 /* F = 25Mhz * [(M + 2) / (n + 1)] / (p + 1)*/ 124 u32 m = epll_reg & 0x1fff; 125 u32 n = (epll_reg >> 13) & 0x3f; 126 u32 p = (epll_reg >> 19) & 0x7; 127 128 mult = ((m + 1) / (n + 1)); 129 div = (p + 1); 130 } 131 return (clk_in * mult)/div; 132 } 133 134 static ulong ast2600_get_dpll_rate(struct ast2600_scu *scu) 135 { 136 u32 clk_in = AST2600_CLK_IN; 137 u32 dpll_reg = readl(&scu->d_pll_param); 138 unsigned int mult, div = 1; 139 140 if (dpll_reg & BIT(24)) { 141 /* Pass through mode */ 142 mult = div = 1; 143 } else { 144 /* F = 25Mhz * [(M + 2) / (n + 1)] / (p + 1)*/ 145 u32 m = dpll_reg & 0x1fff; 146 u32 n = (dpll_reg >> 13) & 0x3f; 147 u32 p = (dpll_reg >> 19) & 0x7; 148 mult = ((m + 1) / (n + 1)); 149 div = (p + 1); 150 } 151 return (clk_in * mult)/div; 152 } 153 154 static ulong ast2600_get_uart_clk_rate(struct ast2600_clk_priv *priv, int uart_index) 155 { 156 ulong uart_clkin; 157 158 printf("ast2600_get_uart_clk_rate source %ld \n\n", ast2600_get_apll_rate(priv->scu)); 159 return (24000000/13); 160 161 if (readl(&priv->scu->misc_ctrl2) & 162 (1 << (uart_index - 1 + SCU_MISC2_UARTCLK_SHIFT))) 163 uart_clkin = 192 * 1000 * 1000; 164 else 165 uart_clkin = 24 * 1000 * 1000; 166 167 if (readl(&priv->scu->misc_ctrl2) & SCU_MISC_UARTCLK_DIV13) 168 uart_clkin /= 13; 169 170 return uart_clkin; 171 } 172 173 struct aspeed_clock_config { 174 ulong input_rate; 175 ulong rate; 176 struct ast2600_div_config cfg; 177 }; 178 179 static const struct aspeed_clock_config aspeed_clock_config_defaults[] = { 180 { 24000000, 250000000, { .num = 124, .denum = 1, .post_div = 5 } }, 181 }; 182 183 static bool aspeed_get_clock_config_default(ulong input_rate, 184 ulong requested_rate, 185 struct ast2600_div_config *cfg) 186 { 187 int i; 188 189 for (i = 0; i < ARRAY_SIZE(aspeed_clock_config_defaults); i++) { 190 const struct aspeed_clock_config *default_cfg = 191 &aspeed_clock_config_defaults[i]; 192 if (default_cfg->input_rate == input_rate && 193 default_cfg->rate == requested_rate) { 194 *cfg = default_cfg->cfg; 195 return true; 196 } 197 } 198 199 return false; 200 } 201 202 /* 203 * @input_rate - the rate of input clock in Hz 204 * @requested_rate - desired output rate in Hz 205 * @div - this is an IN/OUT parameter, at input all fields of the config 206 * need to be set to their maximum allowed values. 207 * The result (the best config we could find), would also be returned 208 * in this structure. 209 * 210 * @return The clock rate, when the resulting div_config is used. 211 */ 212 static ulong aspeed_calc_clock_config(ulong input_rate, ulong requested_rate, 213 struct ast2600_div_config *cfg) 214 { 215 /* 216 * The assumption is that kHz precision is good enough and 217 * also enough to avoid overflow when multiplying. 218 */ 219 const ulong input_rate_khz = input_rate / 1000; 220 const ulong rate_khz = requested_rate / 1000; 221 const struct ast2600_div_config max_vals = *cfg; 222 struct ast2600_div_config it = { 0, 0, 0 }; 223 ulong delta = rate_khz; 224 ulong new_rate_khz = 0; 225 226 /* 227 * Look for a well known frequency first. 228 */ 229 if (aspeed_get_clock_config_default(input_rate, requested_rate, cfg)) 230 return requested_rate; 231 232 for (; it.denum <= max_vals.denum; ++it.denum) { 233 for (it.post_div = 0; it.post_div <= max_vals.post_div; 234 ++it.post_div) { 235 it.num = (rate_khz * (it.post_div + 1) / input_rate_khz) 236 * (it.denum + 1); 237 if (it.num > max_vals.num) 238 continue; 239 240 new_rate_khz = (input_rate_khz 241 * ((it.num + 1) / (it.denum + 1))) 242 / (it.post_div + 1); 243 244 /* Keep the rate below requested one. */ 245 if (new_rate_khz > rate_khz) 246 continue; 247 248 if (new_rate_khz - rate_khz < delta) { 249 delta = new_rate_khz - rate_khz; 250 *cfg = it; 251 if (delta == 0) 252 return new_rate_khz * 1000; 253 } 254 } 255 } 256 257 return new_rate_khz * 1000; 258 } 259 260 static u32 ast2600_configure_ddr(struct ast2600_clk_priv *priv, ulong rate) 261 { 262 u32 clkin = AST2600_CLK_IN; 263 u32 mpll_reg; 264 struct ast2600_div_config div_cfg = { 265 .num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT), 266 .denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT), 267 .post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT), 268 }; 269 270 aspeed_calc_clock_config(clkin, rate, &div_cfg); 271 272 mpll_reg = readl(&priv->scu->m_pll_param); 273 mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK 274 | SCU_MPLL_DENUM_MASK); 275 mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT) 276 | (div_cfg.num << SCU_MPLL_NUM_SHIFT) 277 | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT); 278 279 writel(mpll_reg, &priv->scu->m_pll_param); 280 281 return ast2600_get_mpll_rate(priv->scu); 282 } 283 284 static u32 ast2600_configure_mac(struct ast2600_scu *scu, int index) 285 { 286 u32 reset_bit; 287 u32 clkstop_bit; 288 289 290 switch (index) { 291 case 1: 292 reset_bit = BIT(ASPEED_RESET_MAC1); 293 clkstop_bit = SCU_CLKSTOP_MAC1; 294 break; 295 case 2: 296 reset_bit = BIT(ASPEED_RESET_MAC2); 297 clkstop_bit = SCU_CLKSTOP_MAC2; 298 break; 299 #if 0 300 case 3: 301 reset_bit = BIT(ASPEED_RESET_MAC3); 302 clkstop_bit = SCU_CLKSTOP_MAC1; 303 break; 304 case 4: 305 reset_bit = BIT(ASPEED_RESET_MAC4); 306 clkstop_bit = SCU_CLKSTOP_MAC2; 307 break; 308 #endif 309 default: 310 return -EINVAL; 311 } 312 313 /* 314 * Disable MAC, start its clock and re-enable it. 315 * The procedure and the delays (100us & 10ms) are 316 * specified in the datasheet. 317 */ 318 setbits_le32(&scu->sysreset_ctrl1, reset_bit); 319 udelay(100); 320 clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit); 321 mdelay(10); 322 clrbits_le32(&scu->sysreset_ctrl1, reset_bit); 323 324 return 0; 325 } 326 327 static u32 ast2600_a0_axi_ahb_div_table[] = { 328 2, 2, 3, 5, 329 }; 330 331 static u32 ast2600_a1_axi_ahb_div_table[] = { 332 4, 6, 2, 4, 333 }; 334 335 static u32 ast2600_hpll_pclk_div_table[] = { 336 4, 8, 12, 16, 20, 24, 28, 32, 337 }; 338 static ulong ast2600_clk_get_rate(struct clk *clk) 339 { 340 struct ast2600_clk_priv *priv = dev_get_priv(clk->dev); 341 ulong rate; 342 343 switch (clk->id) { 344 //HPLL 345 case ASPEED_CLK_HPLL: 346 rate = ast2600_get_hpll_rate(priv->scu); 347 printf("hpll %ld \n", rate); 348 break; 349 //HCLK 350 case ASPEED_CLK_AHB: 351 { 352 u32 hw_rev = readl(&priv->scu->chip_id0); 353 u32 hwstrap1 = readl(&priv->scu->hwstrap1); 354 u32 axi_div = 1; 355 u32 ahb_div = 0; 356 if((hwstrap1 >> 16) & 0x1) 357 axi_div = 1; 358 else 359 axi_div = 2; 360 361 if (hw_rev & BIT(16)) 362 ahb_div = ast2600_a1_axi_ahb_div_table[(hwstrap1 >> 11) & 0x3]; 363 else 364 ahb_div = ast2600_a0_axi_ahb_div_table[(hwstrap1 >> 11) & 0x3]; 365 366 rate = ast2600_get_hpll_rate(priv->scu); 367 rate = rate / axi_div / ahb_div; 368 printf("hclk %ld \n", rate); 369 } 370 break; 371 case ASPEED_CLK_MPLL: 372 rate = ast2600_get_mpll_rate(priv->scu); 373 break; 374 //pclk 375 case ASPEED_CLK_APB: 376 { 377 u32 clk_sel1 = readl(&priv->scu->clk_sel1); 378 u32 apb_div = ast2600_hpll_pclk_div_table[((clk_sel1 >> 23) & 0x7)]; 379 rate = ast2600_get_hpll_rate(priv->scu); 380 rate = rate / apb_div; 381 } 382 break; 383 case PCLK_UART1: 384 rate = ast2600_get_uart_clk_rate(priv, 1); 385 break; 386 case PCLK_UART2: 387 rate = ast2600_get_uart_clk_rate(priv, 2); 388 break; 389 case PCLK_UART3: 390 rate = ast2600_get_uart_clk_rate(priv, 3); 391 break; 392 case PCLK_UART4: 393 rate = ast2600_get_uart_clk_rate(priv, 4); 394 break; 395 case ASPEED_CLK_GATE_UART5CLK: 396 rate = ast2600_get_uart_clk_rate(priv, 5); 397 break; 398 default: 399 return -ENOENT; 400 } 401 402 return rate; 403 } 404 405 static ulong ast2600_clk_set_rate(struct clk *clk, ulong rate) 406 { 407 struct ast2600_clk_priv *priv = dev_get_priv(clk->dev); 408 409 ulong new_rate; 410 switch (clk->id) { 411 case ASPEED_CLK_MPLL: 412 new_rate = ast2600_configure_ddr(priv, rate); 413 break; 414 default: 415 return -ENOENT; 416 } 417 418 return new_rate; 419 } 420 421 static int ast2600_clk_enable(struct clk *clk) 422 { 423 struct ast2600_clk_priv *priv = dev_get_priv(clk->dev); 424 425 switch (clk->id) { 426 /* 427 * For MAC clocks the clock rate is 428 * configured based on whether RGMII or RMII mode has been selected 429 * through hardware strapping. 430 */ 431 case PCLK_MAC1: 432 printf("ast2600_clk_enable mac 1 ~~~\n"); 433 ast2600_configure_mac(priv, 1); 434 break; 435 case PCLK_MAC2: 436 printf("ast2600_clk_enable mac 2 ~~~\n"); 437 ast2600_configure_mac(priv, 2); 438 break; 439 default: 440 return -ENOENT; 441 } 442 443 return 0; 444 } 445 446 struct clk_ops aspeed_clk_ops = { 447 .get_rate = ast2600_clk_get_rate, 448 .set_rate = ast2600_clk_set_rate, 449 .enable = ast2600_clk_enable, 450 }; 451 452 static int ast2600_clk_probe(struct udevice *dev) 453 { 454 char buf[32]; 455 struct ast2600_clk_priv *priv = dev_get_priv(dev); 456 457 priv->scu = devfdt_get_addr_ptr(dev); 458 if (IS_ERR(priv->scu)) 459 return PTR_ERR(priv->scu); 460 461 printf("PLL : %4s MHz\n", strmhz(buf, AST2600_CLK_IN)); 462 printf("HPLL : %4s MHz\n", strmhz(buf, ast2600_get_hpll_rate(priv->scu))); 463 printf("MPLL : %4s Mhz\n", strmhz(buf, ast2600_get_mpll_rate(priv->scu))); 464 printf("APLL : %4s Mhz\n", strmhz(buf, ast2600_get_apll_rate(priv->scu))); 465 printf("EPLL : %4s Mhz\n", strmhz(buf, ast2600_get_epll_rate(priv->scu))); 466 printf("DPLL : %4s Mhz\n", strmhz(buf, ast2600_get_dpll_rate(priv->scu))); 467 468 469 return 0; 470 } 471 472 static int ast2600_clk_bind(struct udevice *dev) 473 { 474 int ret; 475 476 /* The reset driver does not have a device node, so bind it here */ 477 ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev); 478 if (ret) 479 debug("Warning: No reset driver: ret=%d\n", ret); 480 481 return 0; 482 } 483 484 static const struct udevice_id ast2600_clk_ids[] = { 485 { .compatible = "aspeed,ast2600-scu", }, 486 { } 487 }; 488 489 U_BOOT_DRIVER(aspeed_scu) = { 490 .name = "aspeed_scu", 491 .id = UCLASS_CLK, 492 .of_match = ast2600_clk_ids, 493 .priv_auto_alloc_size = sizeof(struct ast2600_clk_priv), 494 .ops = &aspeed_clk_ops, 495 .bind = ast2600_clk_bind, 496 .probe = ast2600_clk_probe, 497 }; 498