1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0 5 */ 6 7 #include <common.h> 8 #include <bitfield.h> 9 #include <clk-uclass.h> 10 #include <dm.h> 11 #include <errno.h> 12 #include <syscon.h> 13 #include <asm/arch/clock.h> 14 #include <asm/arch/cru_px30.h> 15 #include <asm/arch/hardware.h> 16 #include <asm/io.h> 17 #include <dm/lists.h> 18 #include <dt-bindings/clock/px30-cru.h> 19 20 DECLARE_GLOBAL_DATA_PTR; 21 22 enum { 23 VCO_MAX_HZ = 3200U * 1000000, 24 VCO_MIN_HZ = 800 * 1000000, 25 OUTPUT_MAX_HZ = 3200U * 1000000, 26 OUTPUT_MIN_HZ = 24 * 1000000, 27 }; 28 29 #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1)) 30 31 #define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\ 32 .refdiv = _refdiv,\ 33 .fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\ 34 .postdiv1 = _postdiv1, .postdiv2 = _postdiv2}; 35 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 1, 1); 36 37 static const struct pll_div apll_816_cfg = PLL_DIVISORS(816 * MHz, 1, 2, 1); 38 static const struct pll_div apll_600_cfg = PLL_DIVISORS(600 * MHz, 1, 3, 1); 39 40 static const struct pll_div *apll_cfgs[] = { 41 [APLL_816_MHZ] = &apll_816_cfg, 42 [APLL_600_MHZ] = &apll_600_cfg, 43 }; 44 45 static u8 pll_mode_shift[PLL_COUNT] = { 46 APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT, 47 NPLL_MODE_SHIFT, GPLL_MODE_SHIFT 48 }; 49 static u32 pll_mode_mask[PLL_COUNT] = { 50 APLL_MODE_MASK, DPLL_MODE_MASK, CPLL_MODE_MASK, 51 NPLL_MODE_MASK, GPLL_MODE_MASK 52 }; 53 54 /* 55 * the div restructions of pll in integer mode, these are defined in 56 * * CRU_*PLL_CON0 or PMUCRU_*PLL_CON0 57 */ 58 #define PLL_DIV_MIN 16 59 #define PLL_DIV_MAX 3200 60 61 /* 62 * How to calculate the PLL(from TRM V0.3 Part 1 Page 63): 63 * Formulas also embedded within the Fractional PLL Verilog model: 64 * If DSMPD = 1 (DSM is disabled, "integer mode") 65 * FOUTVCO = FREF / REFDIV * FBDIV 66 * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2 67 * Where: 68 * FOUTVCO = Fractional PLL non-divided output frequency 69 * FOUTPOSTDIV = Fractional PLL divided output frequency 70 * (output of second post divider) 71 * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input) 72 * REFDIV = Fractional PLL input reference clock divider 73 * FBDIV = Integer value programmed into feedback divide 74 * 75 */ 76 static void rkclk_set_pll(struct px30_cru *cru, enum px30_pll_id pll_id, 77 const struct pll_div *div) 78 { 79 struct px30_pll *pll; 80 unsigned int *mode; 81 /* All PLLs have same VCO and output frequency range restrictions. */ 82 uint vco_hz = OSC_HZ / 1000 * div->fbdiv / div->refdiv * 1000; 83 uint output_hz = vco_hz / div->postdiv1 / div->postdiv2; 84 85 if (pll_id == GPLL) { 86 pll = &cru->gpll; 87 mode = &cru->pmu_mode; 88 } else { 89 pll = &cru->pll[pll_id]; 90 mode = &cru->mode; 91 }; 92 93 debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n", 94 pll, div->fbdiv, div->refdiv, div->postdiv1, 95 div->postdiv2, vco_hz, output_hz); 96 assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ && 97 output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ); 98 99 /* 100 * When power on or changing PLL setting, 101 * we must force PLL into slow mode to ensure output stable clock. 102 */ 103 rk_clrsetreg(mode, pll_mode_mask[pll_id], 104 PLLMUX_FROM_XIN24M << pll_mode_shift[pll_id]); 105 106 /* use integer mode */ 107 rk_setreg(&pll->con1, 1 << PLL_DSMPD_SHIFT); 108 /* Power down */ 109 rk_setreg(&pll->con1, 1 << PLL_PD_SHIFT); 110 111 rk_clrsetreg(&pll->con0, 112 PLL_POSTDIV1_MASK | PLL_FBDIV_MASK, 113 (div->postdiv1 << PLL_POSTDIV1_SHIFT) | div->fbdiv); 114 rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK | PLL_REFDIV_MASK, 115 (div->postdiv2 << PLL_POSTDIV2_SHIFT | 116 div->refdiv << PLL_REFDIV_SHIFT)); 117 118 /* Power Up */ 119 rk_clrreg(&pll->con1, 1 << PLL_PD_SHIFT); 120 121 /* waiting for pll lock */ 122 while (!(readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT))) 123 udelay(1); 124 125 rk_clrsetreg(mode, pll_mode_mask[pll_id], 126 PLLMUX_FROM_PLL << pll_mode_shift[pll_id]); 127 128 return; 129 } 130 131 static uint32_t rkclk_pll_get_rate(struct px30_cru *cru, 132 enum px30_pll_id pll_id) 133 { 134 u32 refdiv, fbdiv, postdiv1, postdiv2; 135 u32 con; 136 struct px30_pll *pll; 137 uint shift; 138 uint mask; 139 140 if (pll_id == GPLL) { 141 pll = &cru->gpll; 142 con = readl(&cru->pmu_mode); 143 } else { 144 pll = &cru->pll[pll_id]; 145 con = readl(&cru->mode); 146 } 147 148 shift = pll_mode_shift[pll_id]; 149 mask = pll_mode_mask[pll_id]; 150 151 switch ((con & mask) >> shift) { 152 case PLLMUX_FROM_XIN24M: 153 return OSC_HZ; 154 case PLLMUX_FROM_PLL: 155 /* normal mode */ 156 con = readl(&pll->con0); 157 postdiv1 = (con & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT; 158 fbdiv = (con & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT; 159 con = readl(&pll->con1); 160 postdiv2 = (con & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT; 161 refdiv = (con & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT; 162 return (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000; 163 case PLLMUX_FROM_RTC32K: 164 default: 165 return 32768; 166 } 167 } 168 169 static int pll_para_config(u32 freq_hz, struct pll_div *div) 170 { 171 u32 ref_khz = OSC_HZ / KHz, refdiv, fbdiv = 0; 172 u32 postdiv1, postdiv2 = 1; 173 u32 fref_khz; 174 u32 diff_khz, best_diff_khz; 175 const u32 max_refdiv = 63, max_fbdiv = 3200, min_fbdiv = 16; 176 const u32 max_postdiv1 = 7, max_postdiv2 = 7; 177 u32 vco_khz; 178 u32 freq_khz = freq_hz / KHz; 179 180 if (!freq_hz) { 181 printf("%s: the frequency can't be 0 Hz\n", __func__); 182 return -1; 183 } 184 185 postdiv1 = DIV_ROUND_UP(VCO_MIN_HZ / 1000, freq_khz); 186 if (postdiv1 > max_postdiv1) { 187 postdiv2 = DIV_ROUND_UP(postdiv1, max_postdiv1); 188 postdiv1 = DIV_ROUND_UP(postdiv1, postdiv2); 189 } 190 191 vco_khz = freq_khz * postdiv1 * postdiv2; 192 193 if (vco_khz < (VCO_MIN_HZ / KHz) || vco_khz > (VCO_MAX_HZ / KHz) || 194 postdiv2 > max_postdiv2) { 195 printf("%s: Cannot find out a supported VCO for Freq (%uHz)\n", 196 __func__, freq_hz); 197 return -1; 198 } 199 200 div->postdiv1 = postdiv1; 201 div->postdiv2 = postdiv2; 202 203 best_diff_khz = vco_khz; 204 for (refdiv = 1; refdiv < max_refdiv && best_diff_khz; refdiv++) { 205 fref_khz = ref_khz / refdiv; 206 207 fbdiv = vco_khz / fref_khz; 208 if ((fbdiv >= max_fbdiv) || (fbdiv <= min_fbdiv)) 209 continue; 210 diff_khz = vco_khz - fbdiv * fref_khz; 211 if (fbdiv + 1 < max_fbdiv && diff_khz > fref_khz / 2) { 212 fbdiv++; 213 diff_khz = fref_khz - diff_khz; 214 } 215 216 if (diff_khz >= best_diff_khz) 217 continue; 218 219 best_diff_khz = diff_khz; 220 div->refdiv = refdiv; 221 div->fbdiv = fbdiv; 222 } 223 224 if (best_diff_khz > 4 * (MHz / KHz)) { 225 printf("%s: Failed to match output frequency %u bestis %u Hz\n", 226 __func__, freq_hz, 227 best_diff_khz * KHz); 228 return -1; 229 } 230 return 0; 231 } 232 233 static void rkclk_init(struct px30_cru *cru) 234 { 235 u32 aclk_div; 236 237 /* init pll */ 238 rkclk_set_pll(cru, APLL, apll_cfgs[APLL_816_MHZ]); 239 rkclk_set_pll(cru, GPLL, &gpll_init_cfg); 240 241 /* 242 * select apll as cpu/core clock pll source and 243 * set up dependent divisors for PERI and ACLK clocks. 244 * core hz : apll = 1:1 245 */ 246 aclk_div = APLL_HZ / CORE_ACLK_HZ - 1; 247 rk_clrsetreg(&cru->clksel_con[0], 248 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK | 249 CORE_ACLK_DIV_MASK, 250 aclk_div << CORE_ACLK_DIV_SHIFT | 251 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 252 0 << CORE_DIV_CON_SHIFT); 253 } 254 255 static ulong px30_i2c_get_clk(struct px30_cru *cru, ulong clk_id) 256 { 257 u32 div, con; 258 259 switch (clk_id) { 260 case SCLK_I2C0: 261 con = readl(&cru->clksel_con[49]); 262 div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 263 break; 264 case SCLK_I2C1: 265 con = readl(&cru->clksel_con[49]); 266 div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 267 break; 268 case SCLK_I2C2: 269 con = readl(&cru->clksel_con[50]); 270 div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 271 break; 272 case SCLK_I2C3: 273 con = readl(&cru->clksel_con[50]); 274 div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 275 break; 276 default: 277 printf("do not support this i2c bus\n"); 278 return -EINVAL; 279 } 280 281 return DIV_TO_RATE(GPLL_HZ, div); 282 } 283 284 static ulong px30_i2c_set_clk(struct px30_cru *cru, ulong clk_id, uint hz) 285 { 286 int src_clk_div; 287 288 src_clk_div = GPLL_HZ / hz; 289 assert(src_clk_div - 1 < 127); 290 291 switch (clk_id) { 292 case SCLK_I2C0: 293 rk_clrsetreg(&cru->clksel_con[49], 294 CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT | 295 CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT, 296 (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT | 297 CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT); 298 break; 299 case SCLK_I2C1: 300 rk_clrsetreg(&cru->clksel_con[49], 301 CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT | 302 CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT, 303 (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT | 304 CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT); 305 break; 306 case SCLK_I2C2: 307 rk_clrsetreg(&cru->clksel_con[50], 308 CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT | 309 CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT, 310 (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT | 311 CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT); 312 break; 313 case SCLK_I2C3: 314 rk_clrsetreg(&cru->clksel_con[50], 315 CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT | 316 CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT, 317 (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT | 318 CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT); 319 break; 320 default: 321 printf("do not support this i2c bus\n"); 322 return -EINVAL; 323 } 324 325 return px30_i2c_get_clk(cru, clk_id); 326 } 327 328 static ulong px30_mmc_get_clk(struct px30_cru *cru, uint clk_id) 329 { 330 u32 div, con, con_id; 331 332 switch (clk_id) { 333 case HCLK_SDMMC: 334 case SCLK_SDMMC: 335 con_id = 16; 336 break; 337 case HCLK_EMMC: 338 case SCLK_EMMC: 339 case SCLK_EMMC_SAMPLE: 340 con_id = 20; 341 break; 342 default: 343 return -EINVAL; 344 } 345 346 con = readl(&cru->clksel_con[con_id]); 347 div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT; 348 349 if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT 350 == EMMC_SEL_24M) 351 return DIV_TO_RATE(OSC_HZ, div) / 2; 352 else 353 return DIV_TO_RATE(GPLL_HZ, div) / 2; 354 355 } 356 357 static ulong px30_mmc_set_clk(struct px30_cru *cru, 358 ulong clk_id, ulong set_rate) 359 { 360 int src_clk_div; 361 u32 con_id; 362 363 debug("%s %ld %ld\n", __func__, clk_id, set_rate); 364 switch (clk_id) { 365 case HCLK_SDMMC: 366 case SCLK_SDMMC: 367 con_id = 16; 368 break; 369 case HCLK_EMMC: 370 case SCLK_EMMC: 371 con_id = 20; 372 break; 373 default: 374 return -EINVAL; 375 } 376 /* Select clk_sdmmc/emmc source from GPLL by default */ 377 /* mmc clock defaulg div 2 internal, need provide double in cru */ 378 src_clk_div = DIV_ROUND_UP(GPLL_HZ / 2, set_rate); 379 380 if (src_clk_div > 127) { 381 /* use 24MHz source for 400KHz clock */ 382 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate); 383 rk_clrsetreg(&cru->clksel_con[con_id], 384 EMMC_PLL_MASK | EMMC_DIV_MASK, 385 EMMC_SEL_24M << EMMC_PLL_SHIFT | 386 (src_clk_div - 1) << EMMC_DIV_SHIFT); 387 } else { 388 rk_clrsetreg(&cru->clksel_con[con_id], 389 EMMC_PLL_MASK | EMMC_DIV_MASK, 390 EMMC_SEL_GPLL << EMMC_PLL_SHIFT | 391 (src_clk_div - 1) << EMMC_DIV_SHIFT); 392 } 393 rk_clrsetreg(&cru->clksel_con[con_id +1], EMMC_CLK_SEL_MASK, 394 EMMC_CLK_SEL_EMMC); 395 396 return px30_mmc_get_clk(cru, clk_id); 397 } 398 399 static ulong px30_pwm_get_clk(struct px30_cru *cru, ulong clk_id) 400 { 401 u32 div, con; 402 403 switch (clk_id) { 404 case SCLK_PWM0: 405 con = readl(&cru->clksel_con[52]); 406 div = con >> CLK_PWM0_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK; 407 break; 408 case SCLK_PWM1: 409 con = readl(&cru->clksel_con[52]); 410 div = con >> CLK_PWM1_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK; 411 break; 412 default: 413 printf("do not support this pwm bus\n"); 414 return -EINVAL; 415 } 416 417 return DIV_TO_RATE(GPLL_HZ, div); 418 } 419 420 static ulong px30_pwm_set_clk(struct px30_cru *cru, ulong clk_id, uint hz) 421 { 422 int src_clk_div; 423 424 src_clk_div = GPLL_HZ / hz; 425 assert(src_clk_div - 1 < 127); 426 427 switch (clk_id) { 428 case SCLK_PWM0: 429 rk_clrsetreg(&cru->clksel_con[52], 430 CLK_PWM_DIV_CON_MASK << CLK_PWM0_DIV_CON_SHIFT | 431 CLK_PWM_PLL_SEL_MASK << CLK_PWM0_PLL_SEL_SHIFT, 432 (src_clk_div - 1) << CLK_PWM0_DIV_CON_SHIFT | 433 CLK_PWM_PLL_SEL_GPLL << CLK_PWM0_PLL_SEL_SHIFT); 434 break; 435 case SCLK_PWM1: 436 rk_clrsetreg(&cru->clksel_con[52], 437 CLK_PWM_DIV_CON_MASK << CLK_PWM1_DIV_CON_SHIFT | 438 CLK_PWM_PLL_SEL_MASK << CLK_PWM1_PLL_SEL_SHIFT, 439 (src_clk_div - 1) << CLK_PWM1_DIV_CON_SHIFT | 440 CLK_PWM_PLL_SEL_GPLL << CLK_PWM1_PLL_SEL_SHIFT); 441 break; 442 default: 443 printf("do not support this pwm bus\n"); 444 return -EINVAL; 445 } 446 447 return px30_pwm_get_clk(cru, clk_id); 448 } 449 450 static ulong px30_saradc_get_clk(struct px30_cru *cru) 451 { 452 u32 div, con; 453 454 con = readl(&cru->clksel_con[55]); 455 div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK; 456 457 return DIV_TO_RATE(OSC_HZ, div); 458 } 459 460 static ulong px30_saradc_set_clk(struct px30_cru *cru, uint hz) 461 { 462 int src_clk_div; 463 464 src_clk_div = OSC_HZ / hz; 465 assert(src_clk_div - 1 < 2047); 466 467 rk_clrsetreg(&cru->clksel_con[55], 468 CLK_SARADC_DIV_CON_MASK, 469 (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT); 470 471 return px30_saradc_get_clk(cru); 472 } 473 474 static ulong px30_spi_get_clk(struct px30_cru *cru, ulong clk_id) 475 { 476 u32 div, con; 477 478 switch (clk_id) { 479 case SCLK_SPI0: 480 con = readl(&cru->clksel_con[53]); 481 div = con >> CLK_SPI0_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK; 482 break; 483 case SCLK_SPI1: 484 con = readl(&cru->clksel_con[53]); 485 div = con >> CLK_SPI1_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK; 486 break; 487 default: 488 printf("do not support this pwm bus\n"); 489 return -EINVAL; 490 } 491 492 return DIV_TO_RATE(GPLL_HZ, div); 493 } 494 495 static ulong px30_spi_set_clk(struct px30_cru *cru, ulong clk_id, uint hz) 496 { 497 int src_clk_div; 498 499 src_clk_div = GPLL_HZ / hz; 500 assert(src_clk_div - 1 < 127); 501 502 switch (clk_id) { 503 case SCLK_SPI0: 504 rk_clrsetreg(&cru->clksel_con[53], 505 CLK_SPI_DIV_CON_MASK << CLK_SPI0_DIV_CON_SHIFT | 506 CLK_SPI_PLL_SEL_MASK << CLK_SPI0_PLL_SEL_SHIFT, 507 (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT | 508 CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT); 509 break; 510 case SCLK_SPI1: 511 rk_clrsetreg(&cru->clksel_con[53], 512 CLK_SPI_DIV_CON_MASK << CLK_SPI1_DIV_CON_SHIFT | 513 CLK_SPI_PLL_SEL_MASK << CLK_SPI1_PLL_SEL_SHIFT, 514 (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT | 515 CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT); 516 break; 517 default: 518 printf("do not support this pwm bus\n"); 519 return -EINVAL; 520 } 521 522 return px30_spi_get_clk(cru, clk_id); 523 } 524 525 static ulong px30_vop_get_clk(struct px30_cru *cru, ulong clk_id) 526 { 527 u32 div, con, parent; 528 529 switch (clk_id) { 530 case ACLK_VOPB: 531 con = readl(&cru->clksel_con[3]); 532 div = con & ACLK_VO_DIV_MASK; 533 parent = GPLL_HZ; 534 break; 535 case DCLK_VOPB: 536 con = readl(&cru->clksel_con[5]); 537 div = con & DCLK_VOPB_DIV_MASK; 538 parent = rkclk_pll_get_rate(cru, CPLL); 539 break; 540 default: 541 return -ENOENT; 542 } 543 544 return DIV_TO_RATE(parent, div); 545 } 546 547 static ulong px30_vop_set_clk(struct px30_cru *cru, ulong clk_id, uint hz) 548 { 549 int src_clk_div; 550 struct pll_div cpll_config = {0}; 551 552 src_clk_div = GPLL_HZ / hz; 553 assert(src_clk_div - 1 < 31); 554 555 switch (clk_id) { 556 case ACLK_VOPB: 557 rk_clrsetreg(&cru->clksel_con[3], 558 ACLK_VO_PLL_MASK | ACLK_VO_DIV_MASK, 559 ACLK_VO_SEL_GPLL << ACLK_VO_PLL_SHIFT | 560 (src_clk_div - 1) << ACLK_VO_DIV_SHIFT); 561 break; 562 case DCLK_VOPB: 563 /* 564 * vopb dclk source from cpll, and equals to 565 * cpll(means div == 1) 566 */ 567 if (pll_para_config(hz, &cpll_config)) 568 return -1; 569 rkclk_set_pll(cru, CPLL, &cpll_config); 570 571 rk_clrsetreg(&cru->clksel_con[5], 572 DCLK_VOPB_SEL_MASK | DCLK_VOPB_PLL_SEL_MASK | 573 DCLK_VOPB_DIV_MASK, 574 DCLK_VOPB_SEL_DIVOUT << DCLK_VOPB_SEL_SHIFT | 575 DCLK_VOPB_PLL_SEL_CPLL << DCLK_VOPB_PLL_SEL_SHIFT | 576 (1 - 1) << DCLK_VOPB_DIV_SHIFT); 577 break; 578 default: 579 printf("do not support this vop freq\n"); 580 return -EINVAL; 581 } 582 583 return hz; 584 } 585 586 static ulong px30_bus_get_clk(struct px30_cru *cru, ulong clk_id) 587 { 588 u32 div, con, parent; 589 590 switch (clk_id) { 591 case ACLK_BUS_PRE: 592 con = readl(&cru->clksel_con[23]); 593 div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT; 594 parent = GPLL_HZ; 595 break; 596 case HCLK_BUS_PRE: 597 con = readl(&cru->clksel_con[24]); 598 div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT; 599 parent = GPLL_HZ; 600 break; 601 case PCLK_BUS_PRE: 602 parent = px30_bus_get_clk(cru, ACLK_BUS_PRE); 603 con = readl(&cru->clksel_con[24]); 604 div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT; 605 break; 606 default: 607 return -ENOENT; 608 } 609 610 return DIV_TO_RATE(parent, div); 611 } 612 613 static ulong px30_bus_set_clk(struct px30_cru *cru, ulong clk_id, ulong hz) 614 { 615 int src_clk_div; 616 617 /* 618 * select gpll as pd_bus bus clock source and 619 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 620 */ 621 switch (clk_id) { 622 case ACLK_BUS_PRE: 623 src_clk_div = GPLL_HZ / hz; 624 assert(src_clk_div - 1 < 31); 625 rk_clrsetreg(&cru->clksel_con[23], 626 BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK, 627 BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT | 628 (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT); 629 break; 630 case HCLK_BUS_PRE: 631 src_clk_div = GPLL_HZ / hz; 632 assert(src_clk_div - 1 < 31); 633 rk_clrsetreg(&cru->clksel_con[24], 634 BUS_PLL_SEL_MASK | BUS_HCLK_DIV_MASK, 635 BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT | 636 (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT); 637 break; 638 case PCLK_BUS_PRE: 639 src_clk_div = px30_bus_get_clk(cru, ACLK_BUS_PRE) / hz; 640 assert(src_clk_div - 1 < 3); 641 rk_clrsetreg(&cru->clksel_con[24], 642 BUS_PCLK_DIV_MASK, 643 (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT); 644 break; 645 default: 646 printf("do not support this bus freq\n"); 647 return -EINVAL; 648 } 649 650 return px30_bus_get_clk(cru, clk_id); 651 } 652 653 static ulong px30_peri_get_clk(struct px30_cru *cru, ulong clk_id) 654 { 655 u32 div, con, parent; 656 657 switch (clk_id) { 658 case ACLK_PERI_PRE: 659 con = readl(&cru->clksel_con[14]); 660 div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT; 661 parent = GPLL_HZ; 662 break; 663 case HCLK_PERI_PRE: 664 con = readl(&cru->clksel_con[14]); 665 div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT; 666 parent = GPLL_HZ; 667 break; 668 default: 669 return -ENOENT; 670 } 671 672 return DIV_TO_RATE(parent, div); 673 } 674 675 static ulong px30_peri_set_clk(struct px30_cru *cru, ulong clk_id, ulong hz) 676 { 677 int src_clk_div; 678 679 src_clk_div = GPLL_HZ / hz; 680 assert(src_clk_div - 1 < 31); 681 682 /* 683 * select gpll as pd_peri bus clock source and 684 * set up dependent divisors for HCLK and ACLK clocks. 685 */ 686 switch (clk_id) { 687 case ACLK_PERI_PRE: 688 rk_clrsetreg(&cru->clksel_con[14], 689 PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK, 690 PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT | 691 (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT); 692 break; 693 case HCLK_PERI_PRE: 694 rk_clrsetreg(&cru->clksel_con[14], 695 PERI_PLL_SEL_MASK | PERI_HCLK_DIV_MASK, 696 PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT | 697 (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT); 698 break; 699 default: 700 printf("do not support this peri freq\n"); 701 return -EINVAL; 702 } 703 704 return px30_peri_get_clk(cru, clk_id); 705 } 706 707 static ulong px30_clk_get_rate(struct clk *clk) 708 { 709 struct px30_clk_priv *priv = dev_get_priv(clk->dev); 710 ulong rate = 0; 711 712 switch (clk->id) { 713 case 0 ... 15: 714 return 0; 715 case HCLK_SDMMC: 716 case HCLK_EMMC: 717 case SCLK_SDMMC: 718 case SCLK_EMMC: 719 case SCLK_EMMC_SAMPLE: 720 rate = px30_mmc_get_clk(priv->cru, clk->id); 721 break; 722 case SCLK_I2C0: 723 case SCLK_I2C1: 724 case SCLK_I2C2: 725 case SCLK_I2C3: 726 rate = px30_i2c_get_clk(priv->cru, clk->id); 727 break; 728 case SCLK_PWM0: 729 case SCLK_PWM1: 730 rate = px30_pwm_get_clk(priv->cru, clk->id); 731 break; 732 case SCLK_SARADC: 733 rate = px30_saradc_get_clk(priv->cru); 734 break; 735 case SCLK_SPI0: 736 case SCLK_SPI1: 737 rate = px30_spi_get_clk(priv->cru, clk->id); 738 break; 739 case ACLK_VOPB: 740 case DCLK_VOPB: 741 rate = px30_vop_get_clk(priv->cru, clk->id); 742 break; 743 case ACLK_BUS_PRE: 744 case HCLK_BUS_PRE: 745 case PCLK_BUS_PRE: 746 rate = px30_bus_get_clk(priv->cru, clk->id); 747 break; 748 case ACLK_PERI_PRE: 749 case HCLK_PERI_PRE: 750 rate = px30_peri_get_clk(priv->cru, clk->id); 751 break; 752 default: 753 return -ENOENT; 754 } 755 756 return rate; 757 } 758 759 static ulong px30_clk_set_rate(struct clk *clk, ulong rate) 760 { 761 struct px30_clk_priv *priv = dev_get_priv(clk->dev); 762 ulong ret = 0; 763 764 debug("%s %ld %ld\n", __func__, clk->id, rate); 765 switch (clk->id) { 766 case 0 ... 15: 767 return 0; 768 case HCLK_SDMMC: 769 case HCLK_EMMC: 770 case SCLK_SDMMC: 771 case SCLK_EMMC: 772 ret = px30_mmc_set_clk(priv->cru, clk->id, rate); 773 break; 774 case SCLK_I2C0: 775 case SCLK_I2C1: 776 case SCLK_I2C2: 777 case SCLK_I2C3: 778 ret = px30_i2c_set_clk(priv->cru, clk->id, rate); 779 break; 780 case SCLK_PWM0: 781 case SCLK_PWM1: 782 ret = px30_pwm_set_clk(priv->cru, clk->id, rate); 783 break; 784 case SCLK_SARADC: 785 ret = px30_saradc_set_clk(priv->cru, rate); 786 break; 787 case SCLK_SPI0: 788 case SCLK_SPI1: 789 ret = px30_spi_set_clk(priv->cru, clk->id, rate); 790 break; 791 case ACLK_VOPB: 792 case DCLK_VOPB: 793 ret = px30_vop_set_clk(priv->cru, clk->id, rate); 794 break; 795 case ACLK_BUS_PRE: 796 case HCLK_BUS_PRE: 797 case PCLK_BUS_PRE: 798 ret = px30_bus_set_clk(priv->cru, clk->id, rate); 799 break; 800 case ACLK_PERI_PRE: 801 case HCLK_PERI_PRE: 802 ret = px30_peri_set_clk(priv->cru, clk->id, rate); 803 break; 804 default: 805 return -ENOENT; 806 } 807 808 return ret; 809 } 810 811 #define ROCKCHIP_MMC_DELAY_SEL BIT(10) 812 #define ROCKCHIP_MMC_DEGREE_MASK 0x3 813 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2 814 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 815 816 #define PSECS_PER_SEC 1000000000000LL 817 /* 818 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 819 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 820 */ 821 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 822 823 int rockchip_mmc_get_phase(struct clk *clk) 824 { 825 struct px30_clk_priv *priv = dev_get_priv(clk->dev); 826 struct px30_cru *cru = priv->cru; 827 u32 raw_value, delay_num; 828 u16 degrees = 0; 829 ulong rate; 830 831 rate = px30_clk_get_rate(clk); 832 833 if (rate < 0) 834 return rate; 835 836 if (clk->id == SCLK_EMMC_SAMPLE) 837 raw_value = readl(&cru->emmc_con[1]); 838 else 839 raw_value = readl(&cru->sdmmc_con[1]); 840 841 raw_value >>= 1; 842 degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; 843 844 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 845 /* degrees/delaynum * 10000 */ 846 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 847 36 * (rate / 1000000); 848 849 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 850 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 851 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 852 } 853 854 return degrees % 360; 855 } 856 857 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees) 858 { 859 struct px30_clk_priv *priv = dev_get_priv(clk->dev); 860 struct px30_cru *cru = priv->cru; 861 u8 nineties, remainder, delay_num; 862 u32 raw_value, delay; 863 ulong rate; 864 865 rate = px30_clk_get_rate(clk); 866 867 if (rate < 0) 868 return rate; 869 870 nineties = degrees / 90; 871 remainder = (degrees % 90); 872 873 /* 874 * Convert to delay; do a little extra work to make sure we 875 * don't overflow 32-bit / 64-bit numbers. 876 */ 877 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 878 delay *= remainder; 879 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 880 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 881 882 delay_num = (u8)min_t(u32, delay, 255); 883 884 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 885 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 886 raw_value |= nineties; 887 888 raw_value <<= 1; 889 if (clk->id == SCLK_EMMC_SAMPLE) 890 writel(raw_value | 0xffff0000, &cru->emmc_con[1]); 891 else 892 writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]); 893 894 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 895 degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk)); 896 897 return 0; 898 } 899 900 static int px30_clk_get_phase(struct clk *clk) 901 { 902 int ret; 903 904 switch (clk->id) { 905 case SCLK_EMMC_SAMPLE: 906 case SCLK_SDMMC_SAMPLE: 907 ret = rockchip_mmc_get_phase(clk); 908 break; 909 default: 910 return -ENOENT; 911 } 912 913 return ret; 914 } 915 916 static int px30_clk_set_phase(struct clk *clk, int degrees) 917 { 918 int ret; 919 920 switch (clk->id) { 921 case SCLK_EMMC_SAMPLE: 922 case SCLK_SDMMC_SAMPLE: 923 ret = rockchip_mmc_set_phase(clk, degrees); 924 break; 925 default: 926 return -ENOENT; 927 } 928 929 return ret; 930 } 931 932 static struct clk_ops px30_clk_ops = { 933 .get_rate = px30_clk_get_rate, 934 .set_rate = px30_clk_set_rate, 935 .get_phase = px30_clk_get_phase, 936 .set_phase = px30_clk_set_phase, 937 }; 938 939 static int px30_clk_probe(struct udevice *dev) 940 { 941 struct px30_clk_priv *priv = dev_get_priv(dev); 942 u32 reg = readl(&priv->cru->clksel_con[23]); 943 944 /* Only do the rkclk_init() one time for boot up */ 945 if (((reg & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT) != 946 (GPLL_HZ / BUS_ACLK_HZ - 1)) 947 rkclk_init(priv->cru); 948 949 return 0; 950 } 951 952 static int px30_clk_ofdata_to_platdata(struct udevice *dev) 953 { 954 struct px30_clk_priv *priv = dev_get_priv(dev); 955 956 priv->cru = dev_read_addr_ptr(dev); 957 958 return 0; 959 } 960 961 static int px30_clk_bind(struct udevice *dev) 962 { 963 int ret; 964 struct udevice *sys_child, *sf_child; 965 struct sysreset_reg *priv; 966 struct softreset_reg *sf_priv; 967 968 /* The reset driver does not have a device node, so bind it here */ 969 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 970 &sys_child); 971 if (ret) { 972 debug("Warning: No sysreset driver: ret=%d\n", ret); 973 } else { 974 priv = malloc(sizeof(struct sysreset_reg)); 975 priv->glb_srst_fst_value = offsetof(struct px30_cru, 976 glb_srst_fst); 977 priv->glb_srst_snd_value = offsetof(struct px30_cru, 978 glb_srst_snd); 979 sys_child->priv = priv; 980 } 981 982 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 983 dev_ofnode(dev), &sf_child); 984 if (ret) { 985 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 986 } else { 987 sf_priv = malloc(sizeof(struct softreset_reg)); 988 sf_priv->sf_reset_offset = offsetof(struct px30_cru, 989 softrst_con[0]); 990 sf_priv->sf_reset_num = 12; 991 sf_child->priv = sf_priv; 992 } 993 994 return 0; 995 } 996 997 static const struct udevice_id px30_clk_ids[] = { 998 { .compatible = "rockchip,px30-cru" }, 999 { } 1000 }; 1001 1002 U_BOOT_DRIVER(rockchip_px30_cru) = { 1003 .name = "rockchip_px30_cru", 1004 .id = UCLASS_CLK, 1005 .of_match = px30_clk_ids, 1006 .priv_auto_alloc_size = sizeof(struct px30_clk_priv), 1007 .ofdata_to_platdata = px30_clk_ofdata_to_platdata, 1008 .ops = &px30_clk_ops, 1009 .bind = px30_clk_bind, 1010 .probe = px30_clk_probe, 1011 }; 1012