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