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 break; 312 case 2: 313 reset_bit = BIT(ASPEED_RESET_MAC2); 314 clkstop_bit = BIT(SCU_CLKSTOP_MAC2); 315 writel(reset_bit, &scu->sysreset_ctrl1); 316 udelay(100); 317 writel(clkstop_bit, &scu->clk_stop_clr_ctrl1); 318 mdelay(10); 319 writel(reset_bit, &scu->sysreset_clr_ctrl1); 320 break; 321 case 3: 322 reset_bit = BIT(ASPEED_RESET_MAC3 - 32); 323 clkstop_bit = BIT(SCU_CLKSTOP_MAC3); 324 writel(reset_bit, &scu->sysreset_ctrl2); 325 udelay(100); 326 writel(clkstop_bit, &scu->clk_stop_clr_ctrl2); 327 mdelay(10); 328 writel(reset_bit, &scu->sysreset_clr_ctrl2); 329 break; 330 case 4: 331 reset_bit = BIT(ASPEED_RESET_MAC4 - 32); 332 clkstop_bit = BIT(SCU_CLKSTOP_MAC4); 333 writel(reset_bit, &scu->sysreset_ctrl2); 334 udelay(100); 335 writel(clkstop_bit, &scu->clk_stop_clr_ctrl2); 336 mdelay(10); 337 writel(reset_bit, &scu->sysreset_clr_ctrl2); 338 break; 339 default: 340 return -EINVAL; 341 } 342 343 return 0; 344 } 345 346 static u32 ast2600_a0_axi_ahb_div_table[] = { 347 2, 2, 3, 5, 348 }; 349 350 static u32 ast2600_a1_axi_ahb_div_table[] = { 351 4, 6, 2, 4, 352 }; 353 354 static u32 ast2600_hpll_pclk_div_table[] = { 355 4, 8, 12, 16, 20, 24, 28, 32, 356 }; 357 static ulong ast2600_clk_get_rate(struct clk *clk) 358 { 359 struct ast2600_clk_priv *priv = dev_get_priv(clk->dev); 360 ulong rate; 361 362 switch (clk->id) { 363 //HPLL 364 case ASPEED_CLK_HPLL: 365 rate = ast2600_get_hpll_rate(priv->scu); 366 printf("hpll %ld \n", rate); 367 break; 368 //HCLK 369 case ASPEED_CLK_AHB: 370 { 371 u32 hw_rev = readl(&priv->scu->chip_id0); 372 u32 hwstrap1 = readl(&priv->scu->hwstrap1); 373 u32 axi_div = 1; 374 u32 ahb_div = 0; 375 if((hwstrap1 >> 16) & 0x1) 376 axi_div = 1; 377 else 378 axi_div = 2; 379 380 if (hw_rev & BIT(16)) 381 ahb_div = ast2600_a1_axi_ahb_div_table[(hwstrap1 >> 11) & 0x3]; 382 else 383 ahb_div = ast2600_a0_axi_ahb_div_table[(hwstrap1 >> 11) & 0x3]; 384 385 rate = ast2600_get_hpll_rate(priv->scu); 386 rate = rate / axi_div / ahb_div; 387 printf("hclk %ld \n", rate); 388 } 389 break; 390 case ASPEED_CLK_MPLL: 391 rate = ast2600_get_mpll_rate(priv->scu); 392 break; 393 //pclk 394 case ASPEED_CLK_APB: 395 { 396 u32 clk_sel1 = readl(&priv->scu->clk_sel1); 397 u32 apb_div = ast2600_hpll_pclk_div_table[((clk_sel1 >> 23) & 0x7)]; 398 rate = ast2600_get_hpll_rate(priv->scu); 399 rate = rate / apb_div; 400 } 401 break; 402 case PCLK_UART1: 403 rate = ast2600_get_uart_clk_rate(priv, 1); 404 break; 405 case PCLK_UART2: 406 rate = ast2600_get_uart_clk_rate(priv, 2); 407 break; 408 case PCLK_UART3: 409 rate = ast2600_get_uart_clk_rate(priv, 3); 410 break; 411 case PCLK_UART4: 412 rate = ast2600_get_uart_clk_rate(priv, 4); 413 break; 414 case ASPEED_CLK_GATE_UART5CLK: 415 rate = ast2600_get_uart_clk_rate(priv, 5); 416 break; 417 default: 418 return -ENOENT; 419 } 420 421 return rate; 422 } 423 424 static ulong ast2600_clk_set_rate(struct clk *clk, ulong rate) 425 { 426 struct ast2600_clk_priv *priv = dev_get_priv(clk->dev); 427 428 ulong new_rate; 429 switch (clk->id) { 430 case ASPEED_CLK_MPLL: 431 new_rate = ast2600_configure_ddr(priv, rate); 432 break; 433 default: 434 return -ENOENT; 435 } 436 437 return new_rate; 438 } 439 440 static int ast2600_clk_enable(struct clk *clk) 441 { 442 struct ast2600_clk_priv *priv = dev_get_priv(clk->dev); 443 444 switch (clk->id) { 445 /* 446 * For MAC clocks the clock rate is 447 * configured based on whether RGMII or RMII mode has been selected 448 * through hardware strapping. 449 */ 450 case ASPEED_CLK_GATE_MAC1CLK: 451 printf("ast2600_clk_enable mac 1 ~~~\n"); 452 ast2600_configure_mac(priv->scu, 1); 453 break; 454 case ASPEED_CLK_GATE_MAC2CLK: 455 printf("ast2600_clk_enable mac 2 ~~~\n"); 456 ast2600_configure_mac(priv->scu, 2); 457 break; 458 default: 459 return -ENOENT; 460 } 461 462 return 0; 463 } 464 465 struct clk_ops aspeed_clk_ops = { 466 .get_rate = ast2600_clk_get_rate, 467 .set_rate = ast2600_clk_set_rate, 468 .enable = ast2600_clk_enable, 469 }; 470 471 static int ast2600_clk_probe(struct udevice *dev) 472 { 473 struct ast2600_clk_priv *priv = dev_get_priv(dev); 474 475 priv->scu = devfdt_get_addr_ptr(dev); 476 if (IS_ERR(priv->scu)) 477 return PTR_ERR(priv->scu); 478 479 return 0; 480 } 481 482 static int ast2600_clk_bind(struct udevice *dev) 483 { 484 int ret; 485 486 /* The reset driver does not have a device node, so bind it here */ 487 ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev); 488 if (ret) 489 debug("Warning: No reset driver: ret=%d\n", ret); 490 491 return 0; 492 } 493 494 static const struct udevice_id ast2600_clk_ids[] = { 495 { .compatible = "aspeed,ast2600-scu", }, 496 { } 497 }; 498 499 U_BOOT_DRIVER(aspeed_scu) = { 500 .name = "aspeed_scu", 501 .id = UCLASS_CLK, 502 .of_match = ast2600_clk_ids, 503 .priv_auto_alloc_size = sizeof(struct ast2600_clk_priv), 504 .ops = &aspeed_clk_ops, 505 .bind = ast2600_clk_bind, 506 .probe = ast2600_clk_probe, 507 }; 508