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 u32 hclk_div; 237 u32 pclk_div; 238 239 /* init pll */ 240 rkclk_set_pll(cru, APLL, apll_cfgs[APLL_816_MHZ]); 241 rkclk_set_pll(cru, GPLL, &gpll_init_cfg); 242 243 /* 244 * select apll as cpu/core clock pll source and 245 * set up dependent divisors for PERI and ACLK clocks. 246 * core hz : apll = 1:1 247 */ 248 aclk_div = APLL_HZ / CORE_ACLK_HZ - 1; 249 rk_clrsetreg(&cru->clksel_con[0], 250 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK | 251 CORE_ACLK_DIV_MASK, 252 aclk_div << CORE_ACLK_DIV_SHIFT | 253 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 254 0 << CORE_DIV_CON_SHIFT); 255 256 /* 257 * select gpll as pd_bus bus clock source and 258 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 259 */ 260 aclk_div = GPLL_HZ / BUS_ACLK_HZ - 1; 261 hclk_div = GPLL_HZ / BUS_HCLK_HZ - 1; 262 pclk_div = BUS_ACLK_HZ / BUS_PCLK_HZ - 1; 263 264 rk_clrsetreg(&cru->clksel_con[23], 265 BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK, 266 BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT | 267 aclk_div << BUS_ACLK_DIV_SHIFT); 268 269 rk_clrsetreg(&cru->clksel_con[24], 270 BUS_PCLK_DIV_MASK | BUS_HCLK_DIV_MASK, 271 pclk_div << BUS_PCLK_DIV_SHIFT | 272 hclk_div << BUS_HCLK_DIV_SHIFT); 273 274 /* 275 * select gpll as pd_peri bus clock source and 276 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 277 */ 278 aclk_div = GPLL_HZ / PERI_ACLK_HZ - 1; 279 hclk_div = GPLL_HZ / PERI_HCLK_HZ - 1; 280 281 rk_clrsetreg(&cru->clksel_con[14], 282 PERI_PLL_SEL_MASK | 283 PERI_HCLK_DIV_MASK | PERI_ACLK_DIV_MASK, 284 PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT | 285 hclk_div << PERI_HCLK_DIV_SHIFT | 286 aclk_div << PERI_ACLK_DIV_SHIFT); 287 } 288 289 static ulong px30_i2c_get_clk(struct px30_cru *cru, ulong clk_id) 290 { 291 u32 div, con; 292 293 switch (clk_id) { 294 case SCLK_I2C0: 295 con = readl(&cru->clksel_con[49]); 296 div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 297 break; 298 case SCLK_I2C1: 299 con = readl(&cru->clksel_con[49]); 300 div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 301 break; 302 case SCLK_I2C2: 303 con = readl(&cru->clksel_con[50]); 304 div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 305 break; 306 case SCLK_I2C3: 307 con = readl(&cru->clksel_con[50]); 308 div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 309 break; 310 default: 311 printf("do not support this i2c bus\n"); 312 return -EINVAL; 313 } 314 315 return DIV_TO_RATE(GPLL_HZ, div); 316 } 317 318 static ulong px30_i2c_set_clk(struct px30_cru *cru, ulong clk_id, uint hz) 319 { 320 int src_clk_div; 321 322 src_clk_div = GPLL_HZ / hz; 323 assert(src_clk_div - 1 < 127); 324 325 switch (clk_id) { 326 case SCLK_I2C0: 327 rk_clrsetreg(&cru->clksel_con[49], 328 CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT | 329 CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT, 330 (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT | 331 CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT); 332 break; 333 case SCLK_I2C1: 334 rk_clrsetreg(&cru->clksel_con[49], 335 CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT | 336 CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT, 337 (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT | 338 CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT); 339 break; 340 case SCLK_I2C2: 341 rk_clrsetreg(&cru->clksel_con[50], 342 CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT | 343 CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT, 344 (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT | 345 CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT); 346 break; 347 case SCLK_I2C3: 348 rk_clrsetreg(&cru->clksel_con[50], 349 CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT | 350 CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT, 351 (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT | 352 CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT); 353 break; 354 default: 355 printf("do not support this i2c bus\n"); 356 return -EINVAL; 357 } 358 359 return DIV_TO_RATE(GPLL_HZ, src_clk_div); 360 } 361 362 static ulong px30_mmc_get_clk(struct px30_cru *cru, uint clk_id) 363 { 364 u32 div, con, con_id; 365 366 switch (clk_id) { 367 case HCLK_SDMMC: 368 case SCLK_SDMMC: 369 con_id = 16; 370 break; 371 case HCLK_EMMC: 372 case SCLK_EMMC: 373 con_id = 20; 374 break; 375 default: 376 return -EINVAL; 377 } 378 379 con = readl(&cru->clksel_con[con_id]); 380 div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT; 381 382 if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT 383 == EMMC_SEL_24M) 384 return DIV_TO_RATE(OSC_HZ, div) / 2; 385 else 386 return DIV_TO_RATE(GPLL_HZ, div) / 2; 387 388 } 389 390 static ulong px30_mmc_set_clk(struct px30_cru *cru, 391 ulong clk_id, ulong set_rate) 392 { 393 int src_clk_div; 394 u32 con_id; 395 396 debug("%s %ld %ld\n", __func__, clk_id, set_rate); 397 switch (clk_id) { 398 case HCLK_SDMMC: 399 case SCLK_SDMMC: 400 con_id = 16; 401 break; 402 case HCLK_EMMC: 403 case SCLK_EMMC: 404 con_id = 20; 405 break; 406 default: 407 return -EINVAL; 408 } 409 /* Select clk_sdmmc/emmc source from GPLL by default */ 410 /* mmc clock defaulg div 2 internal, need provide double in cru */ 411 src_clk_div = DIV_ROUND_UP(GPLL_HZ / 2, set_rate); 412 413 if (src_clk_div > 127) { 414 /* use 24MHz source for 400KHz clock */ 415 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate); 416 rk_clrsetreg(&cru->clksel_con[con_id], 417 EMMC_PLL_MASK | EMMC_DIV_MASK, 418 EMMC_SEL_24M << EMMC_PLL_SHIFT | 419 (src_clk_div - 1) << EMMC_DIV_SHIFT); 420 } else { 421 rk_clrsetreg(&cru->clksel_con[con_id], 422 EMMC_PLL_MASK | EMMC_DIV_MASK, 423 EMMC_SEL_GPLL << EMMC_PLL_SHIFT | 424 (src_clk_div - 1) << EMMC_DIV_SHIFT); 425 } 426 rk_clrsetreg(&cru->clksel_con[con_id +1], EMMC_CLK_SEL_MASK, 427 EMMC_CLK_SEL_EMMC); 428 429 return px30_mmc_get_clk(cru, clk_id); 430 } 431 432 static ulong px30_pwm_get_clk(struct px30_cru *cru, ulong clk_id) 433 { 434 u32 div, con; 435 436 switch (clk_id) { 437 case SCLK_PWM0: 438 con = readl(&cru->clksel_con[52]); 439 div = con >> CLK_PWM0_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK; 440 break; 441 case SCLK_PWM1: 442 con = readl(&cru->clksel_con[52]); 443 div = con >> CLK_PWM1_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK; 444 break; 445 default: 446 printf("do not support this pwm bus\n"); 447 return -EINVAL; 448 } 449 450 return DIV_TO_RATE(GPLL_HZ, div); 451 } 452 453 static ulong px30_pwm_set_clk(struct px30_cru *cru, ulong clk_id, uint hz) 454 { 455 int src_clk_div; 456 457 src_clk_div = GPLL_HZ / hz; 458 assert(src_clk_div - 1 < 127); 459 460 switch (clk_id) { 461 case SCLK_PWM0: 462 rk_clrsetreg(&cru->clksel_con[52], 463 CLK_PWM_DIV_CON_MASK << CLK_PWM0_DIV_CON_SHIFT | 464 CLK_PWM_PLL_SEL_MASK << CLK_PWM0_PLL_SEL_SHIFT, 465 (src_clk_div - 1) << CLK_PWM0_DIV_CON_SHIFT | 466 CLK_PWM_PLL_SEL_GPLL << CLK_PWM0_PLL_SEL_SHIFT); 467 break; 468 case SCLK_PWM1: 469 rk_clrsetreg(&cru->clksel_con[52], 470 CLK_PWM_DIV_CON_MASK << CLK_PWM1_DIV_CON_SHIFT | 471 CLK_PWM_PLL_SEL_MASK << CLK_PWM1_PLL_SEL_SHIFT, 472 (src_clk_div - 1) << CLK_PWM1_DIV_CON_SHIFT | 473 CLK_PWM_PLL_SEL_GPLL << CLK_PWM1_PLL_SEL_SHIFT); 474 break; 475 default: 476 printf("do not support this pwm bus\n"); 477 return -EINVAL; 478 } 479 480 return DIV_TO_RATE(GPLL_HZ, src_clk_div); 481 } 482 483 static ulong px30_saradc_get_clk(struct px30_cru *cru) 484 { 485 u32 div, con; 486 487 con = readl(&cru->clksel_con[55]); 488 div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK; 489 490 return DIV_TO_RATE(OSC_HZ, div); 491 } 492 493 static ulong px30_saradc_set_clk(struct px30_cru *cru, uint hz) 494 { 495 int src_clk_div; 496 497 src_clk_div = OSC_HZ / hz; 498 assert(src_clk_div - 1 < 2047); 499 500 rk_clrsetreg(&cru->clksel_con[55], 501 CLK_SARADC_DIV_CON_MASK, 502 src_clk_div << CLK_SARADC_DIV_CON_SHIFT); 503 504 return DIV_TO_RATE(OSC_HZ, src_clk_div); 505 } 506 507 static ulong px30_spi_get_clk(struct px30_cru *cru, ulong clk_id) 508 { 509 u32 div, con; 510 511 switch (clk_id) { 512 case SCLK_PWM0: 513 con = readl(&cru->clksel_con[53]); 514 div = con >> CLK_SPI0_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK; 515 break; 516 case SCLK_PWM1: 517 con = readl(&cru->clksel_con[53]); 518 div = con >> CLK_SPI1_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK; 519 break; 520 default: 521 printf("do not support this pwm bus\n"); 522 return -EINVAL; 523 } 524 525 return DIV_TO_RATE(GPLL_HZ, div); 526 } 527 528 static ulong px30_spi_set_clk(struct px30_cru *cru, ulong clk_id, uint hz) 529 { 530 int src_clk_div; 531 532 src_clk_div = GPLL_HZ / hz; 533 assert(src_clk_div - 1 < 127); 534 535 switch (clk_id) { 536 case SCLK_SPI0: 537 rk_clrsetreg(&cru->clksel_con[53], 538 CLK_SPI_DIV_CON_MASK << CLK_SPI0_DIV_CON_SHIFT | 539 CLK_SPI_PLL_SEL_MASK << CLK_SPI0_PLL_SEL_SHIFT, 540 (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT | 541 CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT); 542 break; 543 case SCLK_SPI1: 544 rk_clrsetreg(&cru->clksel_con[53], 545 CLK_SPI_DIV_CON_MASK << CLK_SPI1_DIV_CON_SHIFT | 546 CLK_SPI_PLL_SEL_MASK << CLK_SPI1_PLL_SEL_SHIFT, 547 (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT | 548 CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT); 549 break; 550 default: 551 printf("do not support this pwm bus\n"); 552 return -EINVAL; 553 } 554 555 return DIV_TO_RATE(GPLL_HZ, src_clk_div); 556 } 557 558 static ulong px30_vop_get_clk(struct px30_cru *cru, ulong clk_id) 559 { 560 u32 div, con, parent; 561 562 switch (clk_id) { 563 case ACLK_VOPB: 564 con = readl(&cru->clksel_con[3]); 565 div = con & ACLK_VO_DIV_MASK; 566 parent = GPLL_HZ; 567 break; 568 case DCLK_VOPB: 569 con = readl(&cru->clksel_con[5]); 570 div = con & DCLK_VOPB_DIV_MASK; 571 parent = rkclk_pll_get_rate(cru, CPLL); 572 break; 573 default: 574 return -ENOENT; 575 } 576 577 return DIV_TO_RATE(parent, div); 578 } 579 580 static ulong px30_vop_set_clk(struct px30_cru *cru, ulong clk_id, uint hz) 581 { 582 int src_clk_div; 583 struct pll_div cpll_config = {0}; 584 585 src_clk_div = GPLL_HZ / hz; 586 assert(src_clk_div - 1 < 31); 587 588 switch (clk_id) { 589 case ACLK_VOPB: 590 rk_clrsetreg(&cru->clksel_con[3], 591 ACLK_VO_PLL_MASK | ACLK_VO_DIV_MASK, 592 ACLK_VO_SEL_GPLL << ACLK_VO_PLL_SHIFT | 593 (src_clk_div - 1) << ACLK_VO_DIV_SHIFT); 594 break; 595 case DCLK_VOPB: 596 /* 597 * vopb dclk source from cpll, and equals to 598 * cpll(means div == 1) 599 */ 600 if (pll_para_config(hz, &cpll_config)) 601 return -1; 602 rkclk_set_pll(cru, CPLL, &cpll_config); 603 604 rk_clrsetreg(&cru->clksel_con[5], 605 DCLK_VOPB_SEL_MASK | DCLK_VOPB_PLL_SEL_MASK | 606 DCLK_VOPB_DIV_MASK, 607 DCLK_VOPB_SEL_DIVOUT << DCLK_VOPB_SEL_SHIFT | 608 DCLK_VOPB_PLL_SEL_CPLL << DCLK_VOPB_PLL_SEL_SHIFT | 609 (1 - 1) << DCLK_VOPB_DIV_SHIFT); 610 break; 611 default: 612 printf("do not support this vop freq\n"); 613 return -EINVAL; 614 } 615 616 return hz; 617 } 618 619 static ulong px30_clk_get_rate(struct clk *clk) 620 { 621 struct px30_clk_priv *priv = dev_get_priv(clk->dev); 622 ulong rate = 0; 623 624 switch (clk->id) { 625 case 0 ... 15: 626 return 0; 627 case HCLK_SDMMC: 628 case HCLK_EMMC: 629 case SCLK_SDMMC: 630 case SCLK_EMMC: 631 rate = px30_mmc_get_clk(priv->cru, clk->id); 632 break; 633 case SCLK_I2C0: 634 case SCLK_I2C1: 635 case SCLK_I2C2: 636 case SCLK_I2C3: 637 rate = px30_i2c_get_clk(priv->cru, clk->id); 638 break; 639 case SCLK_PWM0: 640 rate = px30_pwm_get_clk(priv->cru, clk->id); 641 break; 642 case SCLK_SARADC: 643 rate = px30_saradc_get_clk(priv->cru); 644 break; 645 case SCLK_SPI0: 646 case SCLK_SPI1: 647 rate = px30_spi_get_clk(priv->cru, clk->id); 648 break; 649 case ACLK_VOPB: 650 case DCLK_VOPB: 651 rate = px30_vop_get_clk(priv->cru, clk->id); 652 break; 653 default: 654 return -ENOENT; 655 } 656 657 return rate; 658 } 659 660 static ulong px30_clk_set_rate(struct clk *clk, ulong rate) 661 { 662 struct px30_clk_priv *priv = dev_get_priv(clk->dev); 663 ulong ret = 0; 664 665 debug("%s %ld %ld\n", __func__, clk->id, rate); 666 switch (clk->id) { 667 case 0 ... 15: 668 return 0; 669 case HCLK_SDMMC: 670 case HCLK_EMMC: 671 case SCLK_SDMMC: 672 case SCLK_EMMC: 673 ret = px30_mmc_set_clk(priv->cru, clk->id, rate); 674 break; 675 case SCLK_I2C0: 676 case SCLK_I2C1: 677 case SCLK_I2C2: 678 case SCLK_I2C3: 679 ret = px30_i2c_set_clk(priv->cru, clk->id, rate); 680 break; 681 case SCLK_PWM0: 682 case SCLK_PWM1: 683 ret = px30_pwm_set_clk(priv->cru, clk->id, rate); 684 break; 685 case SCLK_SARADC: 686 ret = px30_saradc_set_clk(priv->cru, rate); 687 break; 688 case SCLK_SPI0: 689 case SCLK_SPI1: 690 ret = px30_spi_set_clk(priv->cru, clk->id, rate); 691 break; 692 case ACLK_VOPB: 693 case DCLK_VOPB: 694 ret = px30_vop_set_clk(priv->cru, clk->id, rate); 695 break; 696 default: 697 return -ENOENT; 698 } 699 700 return ret; 701 } 702 703 #define ROCKCHIP_MMC_DELAY_SEL BIT(10) 704 #define ROCKCHIP_MMC_DEGREE_MASK 0x3 705 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2 706 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 707 708 #define PSECS_PER_SEC 1000000000000LL 709 /* 710 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 711 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 712 */ 713 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 714 715 int rockchip_mmc_get_phase(struct clk *clk) 716 { 717 struct px30_clk_priv *priv = dev_get_priv(clk->dev); 718 struct px30_cru *cru = priv->cru; 719 u32 raw_value, delay_num; 720 u16 degrees = 0; 721 ulong rate; 722 723 rate = px30_clk_get_rate(clk); 724 725 if (rate < 0) 726 return rate; 727 728 if (clk->id == SCLK_EMMC_SAMPLE) 729 raw_value = readl(&cru->emmc_con[1]); 730 else 731 raw_value = readl(&cru->sdmmc_con[1]); 732 733 degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; 734 735 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 736 /* degrees/delaynum * 10000 */ 737 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 738 36 * (rate / 1000000); 739 740 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 741 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 742 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 743 } 744 745 return degrees % 360; 746 } 747 748 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees) 749 { 750 struct px30_clk_priv *priv = dev_get_priv(clk->dev); 751 struct px30_cru *cru = priv->cru; 752 u8 nineties, remainder, delay_num; 753 u32 raw_value, delay; 754 ulong rate; 755 756 rate = px30_clk_get_rate(clk); 757 758 if (rate < 0) 759 return rate; 760 761 nineties = degrees / 90; 762 remainder = (degrees % 90); 763 764 /* 765 * Convert to delay; do a little extra work to make sure we 766 * don't overflow 32-bit / 64-bit numbers. 767 */ 768 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 769 delay *= remainder; 770 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 771 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 772 773 delay_num = (u8)min_t(u32, delay, 255); 774 775 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 776 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 777 raw_value |= nineties; 778 779 if (clk->id == SCLK_EMMC_SAMPLE) 780 writel(raw_value | 0xffff0000, &cru->emmc_con[1]); 781 else 782 writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]); 783 784 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 785 degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk)); 786 787 return 0; 788 } 789 790 static int px30_clk_get_phase(struct clk *clk) 791 { 792 int ret; 793 794 switch (clk->id) { 795 case SCLK_EMMC_SAMPLE: 796 case SCLK_SDMMC_SAMPLE: 797 ret = rockchip_mmc_get_phase(clk); 798 break; 799 default: 800 return -ENOENT; 801 } 802 803 return ret; 804 } 805 806 static int px30_clk_set_phase(struct clk *clk, int degrees) 807 { 808 int ret; 809 810 switch (clk->id) { 811 case SCLK_EMMC_SAMPLE: 812 case SCLK_SDMMC_SAMPLE: 813 ret = rockchip_mmc_set_phase(clk, degrees); 814 break; 815 default: 816 return -ENOENT; 817 } 818 819 return ret; 820 } 821 822 static struct clk_ops px30_clk_ops = { 823 .get_rate = px30_clk_get_rate, 824 .set_rate = px30_clk_set_rate, 825 .get_phase = px30_clk_get_phase, 826 .set_phase = px30_clk_set_phase, 827 }; 828 829 static int px30_clk_probe(struct udevice *dev) 830 { 831 struct px30_clk_priv *priv = dev_get_priv(dev); 832 833 rkclk_init(priv->cru); 834 835 return 0; 836 } 837 838 static int px30_clk_ofdata_to_platdata(struct udevice *dev) 839 { 840 struct px30_clk_priv *priv = dev_get_priv(dev); 841 842 priv->cru = dev_read_addr_ptr(dev); 843 844 return 0; 845 } 846 847 static int px30_clk_bind(struct udevice *dev) 848 { 849 int ret; 850 struct udevice *sys_child, *sf_child; 851 struct sysreset_reg *priv; 852 struct softreset_reg *sf_priv; 853 854 /* The reset driver does not have a device node, so bind it here */ 855 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 856 &sys_child); 857 if (ret) { 858 debug("Warning: No sysreset driver: ret=%d\n", ret); 859 } else { 860 priv = malloc(sizeof(struct sysreset_reg)); 861 priv->glb_srst_fst_value = offsetof(struct px30_cru, 862 glb_srst_fst); 863 priv->glb_srst_snd_value = offsetof(struct px30_cru, 864 glb_srst_snd); 865 sys_child->priv = priv; 866 } 867 868 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 869 dev_ofnode(dev), &sf_child); 870 if (ret) { 871 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 872 } else { 873 sf_priv = malloc(sizeof(struct softreset_reg)); 874 sf_priv->sf_reset_offset = offsetof(struct px30_cru, 875 softrst_con[0]); 876 sf_priv->sf_reset_num = 12; 877 sf_child->priv = sf_priv; 878 } 879 880 return 0; 881 } 882 883 static const struct udevice_id px30_clk_ids[] = { 884 { .compatible = "rockchip,px30-cru" }, 885 { } 886 }; 887 888 U_BOOT_DRIVER(rockchip_px30_cru) = { 889 .name = "rockchip_px30_cru", 890 .id = UCLASS_CLK, 891 .of_match = px30_clk_ids, 892 .priv_auto_alloc_size = sizeof(struct px30_clk_priv), 893 .ofdata_to_platdata = px30_clk_ofdata_to_platdata, 894 .ops = &px30_clk_ops, 895 .bind = px30_clk_bind, 896 .probe = px30_clk_probe, 897 }; 898