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 PX30_VOP_PLL_LIMIT 600000000 30 31 #define PX30_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \ 32 _postdiv2, _dsmpd, _frac) \ 33 { \ 34 .rate = _rate##U, \ 35 .fbdiv = _fbdiv, \ 36 .postdiv1 = _postdiv1, \ 37 .refdiv = _refdiv, \ 38 .postdiv2 = _postdiv2, \ 39 .dsmpd = _dsmpd, \ 40 .frac = _frac, \ 41 } 42 43 #define PX30_CPUCLK_RATE(_rate, _aclk_div, _pclk_div) \ 44 { \ 45 .rate = _rate##U, \ 46 .aclk_div = _aclk_div, \ 47 .pclk_div = _pclk_div, \ 48 } 49 50 #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1)) 51 52 #define PX30_CLK_DUMP(_id, _name, _iscru) \ 53 { \ 54 .id = _id, \ 55 .name = _name, \ 56 .is_cru = _iscru, \ 57 } 58 59 static struct pll_rate_table px30_pll_rates[] = { 60 /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ 61 PX30_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), 62 PX30_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0), 63 PX30_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0), 64 PX30_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), 65 PX30_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0), 66 PX30_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0), 67 PX30_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0), 68 }; 69 70 static const struct px30_clk_info clks_dump[] = { 71 PX30_CLK_DUMP(PLL_APLL, "apll", true), 72 PX30_CLK_DUMP(PLL_DPLL, "dpll", true), 73 PX30_CLK_DUMP(PLL_CPLL, "cpll", true), 74 PX30_CLK_DUMP(PLL_NPLL, "npll", true), 75 PX30_CLK_DUMP(PLL_GPLL, "gpll", false), 76 PX30_CLK_DUMP(ACLK_BUS_PRE, "aclk_bus", true), 77 PX30_CLK_DUMP(HCLK_BUS_PRE, "hclk_bus", true), 78 PX30_CLK_DUMP(PCLK_BUS_PRE, "pclk_bus", true), 79 PX30_CLK_DUMP(ACLK_PERI_PRE, "aclk_peri", true), 80 PX30_CLK_DUMP(HCLK_PERI_PRE, "hclk_peri", true), 81 PX30_CLK_DUMP(PCLK_PMU_PRE, "pclk_pmu", false), 82 }; 83 84 static struct cpu_rate_table px30_cpu_rates[] = { 85 PX30_CPUCLK_RATE(1200000000, 1, 5), 86 PX30_CPUCLK_RATE(1008000000, 1, 5), 87 PX30_CPUCLK_RATE(816000000, 1, 3), 88 PX30_CPUCLK_RATE(600000000, 1, 3), 89 }; 90 91 static u8 pll_mode_shift[PLL_COUNT] = { 92 APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT, 93 NPLL_MODE_SHIFT, GPLL_MODE_SHIFT 94 }; 95 static u32 pll_mode_mask[PLL_COUNT] = { 96 APLL_MODE_MASK, DPLL_MODE_MASK, CPLL_MODE_MASK, 97 NPLL_MODE_MASK, GPLL_MODE_MASK 98 }; 99 100 static struct pll_rate_table auto_table; 101 102 static ulong px30_clk_get_pll_rate(struct px30_clk_priv *priv, 103 enum px30_pll_id pll_id); 104 105 static struct pll_rate_table *pll_clk_set_by_auto(u32 drate) 106 { 107 struct pll_rate_table *rate = &auto_table; 108 u32 ref_khz = OSC_HZ / KHz, refdiv, fbdiv = 0; 109 u32 postdiv1, postdiv2 = 1; 110 u32 fref_khz; 111 u32 diff_khz, best_diff_khz; 112 const u32 max_refdiv = 63, max_fbdiv = 3200, min_fbdiv = 16; 113 const u32 max_postdiv1 = 7, max_postdiv2 = 7; 114 u32 vco_khz; 115 u32 rate_khz = drate / KHz; 116 117 if (!drate) { 118 printf("%s: the frequency can't be 0 Hz\n", __func__); 119 return NULL; 120 } 121 122 postdiv1 = DIV_ROUND_UP(VCO_MIN_HZ / 1000, rate_khz); 123 if (postdiv1 > max_postdiv1) { 124 postdiv2 = DIV_ROUND_UP(postdiv1, max_postdiv1); 125 postdiv1 = DIV_ROUND_UP(postdiv1, postdiv2); 126 } 127 128 vco_khz = rate_khz * postdiv1 * postdiv2; 129 130 if (vco_khz < (VCO_MIN_HZ / KHz) || vco_khz > (VCO_MAX_HZ / KHz) || 131 postdiv2 > max_postdiv2) { 132 printf("%s: Cannot find out a supported VCO for Freq (%uHz)\n", 133 __func__, rate_khz); 134 return NULL; 135 } 136 137 rate->postdiv1 = postdiv1; 138 rate->postdiv2 = postdiv2; 139 140 best_diff_khz = vco_khz; 141 for (refdiv = 1; refdiv < max_refdiv && best_diff_khz; refdiv++) { 142 fref_khz = ref_khz / refdiv; 143 144 fbdiv = vco_khz / fref_khz; 145 if ((fbdiv >= max_fbdiv) || (fbdiv <= min_fbdiv)) 146 continue; 147 diff_khz = vco_khz - fbdiv * fref_khz; 148 if (fbdiv + 1 < max_fbdiv && diff_khz > fref_khz / 2) { 149 fbdiv++; 150 diff_khz = fref_khz - diff_khz; 151 } 152 153 if (diff_khz >= best_diff_khz) 154 continue; 155 156 best_diff_khz = diff_khz; 157 rate->refdiv = refdiv; 158 rate->fbdiv = fbdiv; 159 } 160 161 if (best_diff_khz > 4 * (MHz / KHz)) { 162 printf("%s: Failed to match output frequency %u bestis %u Hz\n", 163 __func__, rate_khz, 164 best_diff_khz * KHz); 165 return NULL; 166 } 167 168 return rate; 169 } 170 171 static const struct pll_rate_table *get_pll_settings(unsigned long rate) 172 { 173 unsigned int rate_count = ARRAY_SIZE(px30_pll_rates); 174 int i; 175 176 for (i = 0; i < rate_count; i++) { 177 if (rate == px30_pll_rates[i].rate) 178 return &px30_pll_rates[i]; 179 } 180 181 return pll_clk_set_by_auto(rate); 182 } 183 184 static const struct cpu_rate_table *get_cpu_settings(unsigned long rate) 185 { 186 unsigned int rate_count = ARRAY_SIZE(px30_cpu_rates); 187 int i; 188 189 for (i = 0; i < rate_count; i++) { 190 if (rate == px30_cpu_rates[i].rate) 191 return &px30_cpu_rates[i]; 192 } 193 194 return NULL; 195 } 196 197 /* 198 * How to calculate the PLL(from TRM V0.3 Part 1 Page 63): 199 * Formulas also embedded within the Fractional PLL Verilog model: 200 * If DSMPD = 1 (DSM is disabled, "integer mode") 201 * FOUTVCO = FREF / REFDIV * FBDIV 202 * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2 203 * Where: 204 * FOUTVCO = Fractional PLL non-divided output frequency 205 * FOUTPOSTDIV = Fractional PLL divided output frequency 206 * (output of second post divider) 207 * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input) 208 * REFDIV = Fractional PLL input reference clock divider 209 * FBDIV = Integer value programmed into feedback divide 210 * 211 */ 212 static int rkclk_set_pll(struct px30_pll *pll, unsigned int *mode, 213 enum px30_pll_id pll_id, 214 unsigned long drate) 215 { 216 const struct pll_rate_table *rate; 217 uint vco_hz, output_hz; 218 219 rate = get_pll_settings(drate); 220 if (!rate) { 221 printf("%s unsupport rate\n", __func__); 222 return -EINVAL; 223 } 224 225 /* All PLLs have same VCO and output frequency range restrictions. */ 226 vco_hz = OSC_HZ / 1000 * rate->fbdiv / rate->refdiv * 1000; 227 output_hz = vco_hz / rate->postdiv1 / rate->postdiv2; 228 229 debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n", 230 pll, rate->fbdiv, rate->refdiv, rate->postdiv1, 231 rate->postdiv2, vco_hz, output_hz); 232 assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ && 233 output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ); 234 235 /* 236 * When power on or changing PLL setting, 237 * we must force PLL into slow mode to ensure output stable clock. 238 */ 239 rk_clrsetreg(mode, pll_mode_mask[pll_id], 240 PLLMUX_FROM_XIN24M << pll_mode_shift[pll_id]); 241 242 /* use integer mode */ 243 rk_setreg(&pll->con1, 1 << PLL_DSMPD_SHIFT); 244 /* Power down */ 245 rk_setreg(&pll->con1, 1 << PLL_PD_SHIFT); 246 247 rk_clrsetreg(&pll->con0, 248 PLL_POSTDIV1_MASK | PLL_FBDIV_MASK, 249 (rate->postdiv1 << PLL_POSTDIV1_SHIFT) | rate->fbdiv); 250 rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK | PLL_REFDIV_MASK, 251 (rate->postdiv2 << PLL_POSTDIV2_SHIFT | 252 rate->refdiv << PLL_REFDIV_SHIFT)); 253 254 /* Power Up */ 255 rk_clrreg(&pll->con1, 1 << PLL_PD_SHIFT); 256 257 /* waiting for pll lock */ 258 while (!(readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT))) 259 udelay(1); 260 261 rk_clrsetreg(mode, pll_mode_mask[pll_id], 262 PLLMUX_FROM_PLL << pll_mode_shift[pll_id]); 263 264 return 0; 265 } 266 267 static uint32_t rkclk_pll_get_rate(struct px30_pll *pll, unsigned int *mode, 268 enum px30_pll_id pll_id) 269 { 270 u32 refdiv, fbdiv, postdiv1, postdiv2; 271 u32 con, shift, mask; 272 273 con = readl(mode); 274 shift = pll_mode_shift[pll_id]; 275 mask = pll_mode_mask[pll_id]; 276 277 switch ((con & mask) >> shift) { 278 case PLLMUX_FROM_XIN24M: 279 return OSC_HZ; 280 case PLLMUX_FROM_PLL: 281 /* normal mode */ 282 con = readl(&pll->con0); 283 postdiv1 = (con & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT; 284 fbdiv = (con & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT; 285 con = readl(&pll->con1); 286 postdiv2 = (con & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT; 287 refdiv = (con & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT; 288 return (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000; 289 case PLLMUX_FROM_RTC32K: 290 default: 291 return 32768; 292 } 293 } 294 295 static ulong px30_i2c_get_clk(struct px30_clk_priv *priv, ulong clk_id) 296 { 297 struct px30_cru *cru = priv->cru; 298 u32 div, con; 299 300 switch (clk_id) { 301 case SCLK_I2C0: 302 con = readl(&cru->clksel_con[49]); 303 div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 304 break; 305 case SCLK_I2C1: 306 con = readl(&cru->clksel_con[49]); 307 div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 308 break; 309 case SCLK_I2C2: 310 con = readl(&cru->clksel_con[50]); 311 div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 312 break; 313 case SCLK_I2C3: 314 con = readl(&cru->clksel_con[50]); 315 div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 316 break; 317 default: 318 printf("do not support this i2c bus\n"); 319 return -EINVAL; 320 } 321 322 return DIV_TO_RATE(priv->gpll_hz, div); 323 } 324 325 static ulong px30_i2c_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz) 326 { 327 struct px30_cru *cru = priv->cru; 328 int src_clk_div; 329 330 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 331 assert(src_clk_div - 1 <= 127); 332 333 switch (clk_id) { 334 case SCLK_I2C0: 335 rk_clrsetreg(&cru->clksel_con[49], 336 CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT | 337 CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT, 338 (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT | 339 CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT); 340 break; 341 case SCLK_I2C1: 342 rk_clrsetreg(&cru->clksel_con[49], 343 CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT | 344 CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT, 345 (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT | 346 CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT); 347 break; 348 case SCLK_I2C2: 349 rk_clrsetreg(&cru->clksel_con[50], 350 CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT | 351 CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT, 352 (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT | 353 CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT); 354 break; 355 case SCLK_I2C3: 356 rk_clrsetreg(&cru->clksel_con[50], 357 CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT | 358 CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT, 359 (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT | 360 CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT); 361 break; 362 default: 363 printf("do not support this i2c bus\n"); 364 return -EINVAL; 365 } 366 367 return px30_i2c_get_clk(priv, clk_id); 368 } 369 370 static ulong px30_nandc_get_clk(struct px30_clk_priv *priv) 371 { 372 struct px30_cru *cru = priv->cru; 373 u32 div, con; 374 375 con = readl(&cru->clksel_con[15]); 376 div = (con & NANDC_DIV_MASK) >> NANDC_DIV_SHIFT; 377 378 return DIV_TO_RATE(priv->gpll_hz, div); 379 } 380 381 static ulong px30_nandc_set_clk(struct px30_clk_priv *priv, 382 ulong set_rate) 383 { 384 struct px30_cru *cru = priv->cru; 385 int src_clk_div; 386 387 /* Select nandc source from GPLL by default */ 388 /* nandc clock defaulg div 2 internal, need provide double in cru */ 389 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, set_rate); 390 assert(src_clk_div - 1 <= 31); 391 392 rk_clrsetreg(&cru->clksel_con[15], 393 NANDC_CLK_SEL_MASK | NANDC_PLL_MASK | 394 NANDC_DIV_MASK, 395 NANDC_CLK_SEL_NANDC << NANDC_CLK_SEL_SHIFT | 396 NANDC_SEL_GPLL << NANDC_PLL_SHIFT | 397 (src_clk_div - 1) << NANDC_DIV_SHIFT); 398 399 return px30_nandc_get_clk(priv); 400 } 401 402 static ulong px30_mmc_get_clk(struct px30_clk_priv *priv, uint clk_id) 403 { 404 struct px30_cru *cru = priv->cru; 405 u32 div, con, con_id; 406 407 switch (clk_id) { 408 case HCLK_SDMMC: 409 case SCLK_SDMMC: 410 con_id = 16; 411 break; 412 case HCLK_EMMC: 413 case SCLK_EMMC: 414 case SCLK_EMMC_SAMPLE: 415 con_id = 20; 416 break; 417 default: 418 return -EINVAL; 419 } 420 421 con = readl(&cru->clksel_con[con_id]); 422 div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT; 423 424 if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT 425 == EMMC_SEL_24M) 426 return DIV_TO_RATE(OSC_HZ, div) / 2; 427 else 428 return DIV_TO_RATE(priv->gpll_hz, div) / 2; 429 430 } 431 432 static ulong px30_mmc_set_clk(struct px30_clk_priv *priv, 433 ulong clk_id, ulong set_rate) 434 { 435 struct px30_cru *cru = priv->cru; 436 int src_clk_div; 437 u32 con_id; 438 439 switch (clk_id) { 440 case HCLK_SDMMC: 441 case SCLK_SDMMC: 442 con_id = 16; 443 break; 444 case HCLK_EMMC: 445 case SCLK_EMMC: 446 con_id = 20; 447 break; 448 default: 449 return -EINVAL; 450 } 451 452 /* Select clk_sdmmc/emmc source from GPLL by default */ 453 /* mmc clock defaulg div 2 internal, need provide double in cru */ 454 src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, set_rate); 455 456 if (src_clk_div > 127) { 457 /* use 24MHz source for 400KHz clock */ 458 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate); 459 rk_clrsetreg(&cru->clksel_con[con_id], 460 EMMC_PLL_MASK | EMMC_DIV_MASK, 461 EMMC_SEL_24M << EMMC_PLL_SHIFT | 462 (src_clk_div - 1) << EMMC_DIV_SHIFT); 463 } else { 464 rk_clrsetreg(&cru->clksel_con[con_id], 465 EMMC_PLL_MASK | EMMC_DIV_MASK, 466 EMMC_SEL_GPLL << EMMC_PLL_SHIFT | 467 (src_clk_div - 1) << EMMC_DIV_SHIFT); 468 } 469 rk_clrsetreg(&cru->clksel_con[con_id +1], EMMC_CLK_SEL_MASK, 470 EMMC_CLK_SEL_EMMC); 471 472 return px30_mmc_get_clk(priv, clk_id); 473 } 474 475 static ulong px30_pwm_get_clk(struct px30_clk_priv *priv, ulong clk_id) 476 { 477 struct px30_cru *cru = priv->cru; 478 u32 div, con; 479 480 switch (clk_id) { 481 case SCLK_PWM0: 482 con = readl(&cru->clksel_con[52]); 483 div = con >> CLK_PWM0_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK; 484 break; 485 case SCLK_PWM1: 486 con = readl(&cru->clksel_con[52]); 487 div = con >> CLK_PWM1_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK; 488 break; 489 default: 490 printf("do not support this pwm bus\n"); 491 return -EINVAL; 492 } 493 494 return DIV_TO_RATE(priv->gpll_hz, div); 495 } 496 497 static ulong px30_pwm_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz) 498 { 499 struct px30_cru *cru = priv->cru; 500 int src_clk_div; 501 502 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 503 assert(src_clk_div - 1 <= 127); 504 505 switch (clk_id) { 506 case SCLK_PWM0: 507 rk_clrsetreg(&cru->clksel_con[52], 508 CLK_PWM_DIV_CON_MASK << CLK_PWM0_DIV_CON_SHIFT | 509 CLK_PWM_PLL_SEL_MASK << CLK_PWM0_PLL_SEL_SHIFT, 510 (src_clk_div - 1) << CLK_PWM0_DIV_CON_SHIFT | 511 CLK_PWM_PLL_SEL_GPLL << CLK_PWM0_PLL_SEL_SHIFT); 512 break; 513 case SCLK_PWM1: 514 rk_clrsetreg(&cru->clksel_con[52], 515 CLK_PWM_DIV_CON_MASK << CLK_PWM1_DIV_CON_SHIFT | 516 CLK_PWM_PLL_SEL_MASK << CLK_PWM1_PLL_SEL_SHIFT, 517 (src_clk_div - 1) << CLK_PWM1_DIV_CON_SHIFT | 518 CLK_PWM_PLL_SEL_GPLL << CLK_PWM1_PLL_SEL_SHIFT); 519 break; 520 default: 521 printf("do not support this pwm bus\n"); 522 return -EINVAL; 523 } 524 525 return px30_pwm_get_clk(priv, clk_id); 526 } 527 528 static ulong px30_saradc_get_clk(struct px30_clk_priv *priv) 529 { 530 struct px30_cru *cru = priv->cru; 531 u32 div, con; 532 533 con = readl(&cru->clksel_con[55]); 534 div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK; 535 536 return DIV_TO_RATE(OSC_HZ, div); 537 } 538 539 static ulong px30_saradc_set_clk(struct px30_clk_priv *priv, uint hz) 540 { 541 struct px30_cru *cru = priv->cru; 542 int src_clk_div; 543 544 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz); 545 assert(src_clk_div - 1 <= 2047); 546 547 rk_clrsetreg(&cru->clksel_con[55], 548 CLK_SARADC_DIV_CON_MASK, 549 (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT); 550 551 return px30_saradc_get_clk(priv); 552 } 553 554 static ulong px30_spi_get_clk(struct px30_clk_priv *priv, ulong clk_id) 555 { 556 struct px30_cru *cru = priv->cru; 557 u32 div, con; 558 559 switch (clk_id) { 560 case SCLK_SPI0: 561 con = readl(&cru->clksel_con[53]); 562 div = con >> CLK_SPI0_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK; 563 break; 564 case SCLK_SPI1: 565 con = readl(&cru->clksel_con[53]); 566 div = con >> CLK_SPI1_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK; 567 break; 568 default: 569 printf("do not support this pwm bus\n"); 570 return -EINVAL; 571 } 572 573 return DIV_TO_RATE(priv->gpll_hz, div); 574 } 575 576 static ulong px30_spi_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz) 577 { 578 struct px30_cru *cru = priv->cru; 579 int src_clk_div; 580 581 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 582 assert(src_clk_div - 1 <= 127); 583 584 switch (clk_id) { 585 case SCLK_SPI0: 586 rk_clrsetreg(&cru->clksel_con[53], 587 CLK_SPI_DIV_CON_MASK << CLK_SPI0_DIV_CON_SHIFT | 588 CLK_SPI_PLL_SEL_MASK << CLK_SPI0_PLL_SEL_SHIFT, 589 (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT | 590 CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT); 591 break; 592 case SCLK_SPI1: 593 rk_clrsetreg(&cru->clksel_con[53], 594 CLK_SPI_DIV_CON_MASK << CLK_SPI1_DIV_CON_SHIFT | 595 CLK_SPI_PLL_SEL_MASK << CLK_SPI1_PLL_SEL_SHIFT, 596 (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT | 597 CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT); 598 break; 599 default: 600 printf("do not support this pwm bus\n"); 601 return -EINVAL; 602 } 603 604 return px30_spi_get_clk(priv, clk_id); 605 } 606 607 static ulong px30_vop_get_clk(struct px30_clk_priv *priv, ulong clk_id) 608 { 609 struct px30_cru *cru = priv->cru; 610 u32 div, con, parent; 611 612 switch (clk_id) { 613 case ACLK_VOPB: 614 case ACLK_VOPL: 615 con = readl(&cru->clksel_con[3]); 616 div = con & ACLK_VO_DIV_MASK; 617 parent = priv->gpll_hz; 618 break; 619 case DCLK_VOPB: 620 con = readl(&cru->clksel_con[5]); 621 div = con & DCLK_VOPB_DIV_MASK; 622 parent = rkclk_pll_get_rate(&cru->pll[CPLL], &cru->mode, CPLL); 623 break; 624 case DCLK_VOPL: 625 con = readl(&cru->clksel_con[8]); 626 div = con & DCLK_VOPL_DIV_MASK; 627 parent = rkclk_pll_get_rate(&cru->pll[NPLL], &cru->mode, NPLL); 628 break; 629 default: 630 return -ENOENT; 631 } 632 633 return DIV_TO_RATE(parent, div); 634 } 635 636 static ulong px30_vop_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz) 637 { 638 struct px30_cru *cru = priv->cru; 639 ulong npll_hz; 640 int src_clk_div; 641 642 switch (clk_id) { 643 case ACLK_VOPB: 644 case ACLK_VOPL: 645 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 646 assert(src_clk_div - 1 <= 31); 647 rk_clrsetreg(&cru->clksel_con[3], 648 ACLK_VO_PLL_MASK | ACLK_VO_DIV_MASK, 649 ACLK_VO_SEL_GPLL << ACLK_VO_PLL_SHIFT | 650 (src_clk_div - 1) << ACLK_VO_DIV_SHIFT); 651 break; 652 case DCLK_VOPB: 653 if (hz < PX30_VOP_PLL_LIMIT) 654 src_clk_div = DIV_ROUND_UP(PX30_VOP_PLL_LIMIT, hz); 655 else 656 src_clk_div = 1; 657 assert(src_clk_div - 1 <= 255); 658 rkclk_set_pll(&cru->pll[CPLL], &cru->mode, CPLL, hz * src_clk_div); 659 rk_clrsetreg(&cru->clksel_con[5], 660 DCLK_VOPB_SEL_MASK | DCLK_VOPB_PLL_SEL_MASK | 661 DCLK_VOPB_DIV_MASK, 662 DCLK_VOPB_SEL_DIVOUT << DCLK_VOPB_SEL_SHIFT | 663 DCLK_VOPB_PLL_SEL_CPLL << DCLK_VOPB_PLL_SEL_SHIFT | 664 (src_clk_div - 1) << DCLK_VOPB_DIV_SHIFT); 665 break; 666 case DCLK_VOPL: 667 npll_hz = px30_clk_get_pll_rate(priv, NPLL); 668 if (npll_hz >= PX30_VOP_PLL_LIMIT && npll_hz >= hz && npll_hz % hz == 0) { 669 src_clk_div = npll_hz / hz; 670 assert(src_clk_div - 1 <= 255); 671 } else { 672 if (hz < PX30_VOP_PLL_LIMIT) 673 src_clk_div = DIV_ROUND_UP(PX30_VOP_PLL_LIMIT, hz); 674 else 675 src_clk_div = 1; 676 assert(src_clk_div - 1 <= 255); 677 rkclk_set_pll(&cru->pll[NPLL], &cru->mode, NPLL, hz * src_clk_div); 678 } 679 rk_clrsetreg(&cru->clksel_con[8], 680 DCLK_VOPL_SEL_MASK | DCLK_VOPL_PLL_SEL_MASK | 681 DCLK_VOPL_DIV_MASK, 682 DCLK_VOPL_SEL_DIVOUT << DCLK_VOPL_SEL_SHIFT | 683 DCLK_VOPL_PLL_SEL_NPLL << DCLK_VOPL_PLL_SEL_SHIFT | 684 (src_clk_div - 1) << DCLK_VOPL_DIV_SHIFT); 685 break; 686 default: 687 printf("do not support this vop freq\n"); 688 return -EINVAL; 689 } 690 691 return px30_vop_get_clk(priv, clk_id); 692 } 693 694 static ulong px30_bus_get_clk(struct px30_clk_priv *priv, ulong clk_id) 695 { 696 struct px30_cru *cru = priv->cru; 697 u32 div, con, parent; 698 699 switch (clk_id) { 700 case ACLK_BUS_PRE: 701 con = readl(&cru->clksel_con[23]); 702 div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT; 703 parent = priv->gpll_hz; 704 break; 705 case HCLK_BUS_PRE: 706 con = readl(&cru->clksel_con[24]); 707 div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT; 708 parent = priv->gpll_hz; 709 break; 710 case PCLK_BUS_PRE: 711 parent = px30_bus_get_clk(priv, ACLK_BUS_PRE); 712 con = readl(&cru->clksel_con[24]); 713 div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT; 714 break; 715 default: 716 return -ENOENT; 717 } 718 719 return DIV_TO_RATE(parent, div); 720 } 721 722 static ulong px30_bus_set_clk(struct px30_clk_priv *priv, ulong clk_id, 723 ulong hz) 724 { 725 struct px30_cru *cru = priv->cru; 726 int src_clk_div; 727 728 /* 729 * select gpll as pd_bus bus clock source and 730 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 731 */ 732 switch (clk_id) { 733 case ACLK_BUS_PRE: 734 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 735 assert(src_clk_div - 1 <= 31); 736 rk_clrsetreg(&cru->clksel_con[23], 737 BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK, 738 BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT | 739 (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT); 740 break; 741 case HCLK_BUS_PRE: 742 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 743 assert(src_clk_div - 1 <= 31); 744 rk_clrsetreg(&cru->clksel_con[24], 745 BUS_PLL_SEL_MASK | BUS_HCLK_DIV_MASK, 746 BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT | 747 (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT); 748 break; 749 case PCLK_BUS_PRE: 750 src_clk_div = 751 DIV_ROUND_UP(px30_bus_get_clk(priv, ACLK_BUS_PRE), hz); 752 assert(src_clk_div - 1 <= 3); 753 rk_clrsetreg(&cru->clksel_con[24], 754 BUS_PCLK_DIV_MASK, 755 (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT); 756 break; 757 default: 758 printf("do not support this bus freq\n"); 759 return -EINVAL; 760 } 761 762 return px30_bus_get_clk(priv, clk_id); 763 } 764 765 static ulong px30_peri_get_clk(struct px30_clk_priv *priv, ulong clk_id) 766 { 767 struct px30_cru *cru = priv->cru; 768 u32 div, con, parent; 769 770 switch (clk_id) { 771 case ACLK_PERI_PRE: 772 con = readl(&cru->clksel_con[14]); 773 div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT; 774 parent = priv->gpll_hz; 775 break; 776 case HCLK_PERI_PRE: 777 con = readl(&cru->clksel_con[14]); 778 div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT; 779 parent = priv->gpll_hz; 780 break; 781 default: 782 return -ENOENT; 783 } 784 785 return DIV_TO_RATE(parent, div); 786 } 787 788 static ulong px30_peri_set_clk(struct px30_clk_priv *priv, ulong clk_id, 789 ulong hz) 790 { 791 struct px30_cru *cru = priv->cru; 792 int src_clk_div; 793 794 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 795 assert(src_clk_div - 1 <= 31); 796 797 /* 798 * select gpll as pd_peri bus clock source and 799 * set up dependent divisors for HCLK and ACLK clocks. 800 */ 801 switch (clk_id) { 802 case ACLK_PERI_PRE: 803 rk_clrsetreg(&cru->clksel_con[14], 804 PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK, 805 PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT | 806 (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT); 807 break; 808 case HCLK_PERI_PRE: 809 rk_clrsetreg(&cru->clksel_con[14], 810 PERI_PLL_SEL_MASK | PERI_HCLK_DIV_MASK, 811 PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT | 812 (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT); 813 break; 814 default: 815 printf("do not support this peri freq\n"); 816 return -EINVAL; 817 } 818 819 return px30_peri_get_clk(priv, clk_id); 820 } 821 822 static int px30_clk_get_gpll_rate(ulong *rate) 823 { 824 struct udevice *pmucru_dev; 825 struct px30_pmuclk_priv *priv; 826 int ret; 827 828 ret = uclass_get_device_by_driver(UCLASS_CLK, 829 DM_GET_DRIVER(rockchip_px30_pmucru), 830 &pmucru_dev); 831 if (ret) { 832 printf("%s: could not find pmucru device\n", __func__); 833 return ret; 834 } 835 priv = dev_get_priv(pmucru_dev); 836 *rate = priv->gpll_hz; 837 838 return 0; 839 } 840 841 static ulong px30_clk_get_pll_rate(struct px30_clk_priv *priv, 842 enum px30_pll_id pll_id) 843 { 844 struct px30_cru *cru = priv->cru; 845 846 return rkclk_pll_get_rate(&cru->pll[pll_id], &cru->mode, pll_id); 847 } 848 849 static ulong px30_clk_set_pll_rate(struct px30_clk_priv *priv, 850 enum px30_pll_id pll_id, ulong hz) 851 { 852 struct px30_cru *cru = priv->cru; 853 854 if (rkclk_set_pll(&cru->pll[pll_id], &cru->mode, pll_id, hz)) 855 return -EINVAL; 856 return rkclk_pll_get_rate(&cru->pll[pll_id], &cru->mode, pll_id); 857 } 858 859 static ulong px30_armclk_set_clk(struct px30_clk_priv *priv, ulong hz) 860 { 861 struct px30_cru *cru = priv->cru; 862 const struct cpu_rate_table *rate; 863 ulong old_rate; 864 865 rate = get_cpu_settings(hz); 866 if (!rate) { 867 printf("%s unsupport rate\n", __func__); 868 return -EINVAL; 869 } 870 871 /* 872 * select apll as cpu/core clock pll source and 873 * set up dependent divisors for PERI and ACLK clocks. 874 * core hz : apll = 1:1 875 */ 876 old_rate = px30_clk_get_pll_rate(priv, APLL); 877 if (old_rate > hz) { 878 if (rkclk_set_pll(&cru->pll[APLL], &cru->mode, APLL, hz)) 879 return -EINVAL; 880 rk_clrsetreg(&cru->clksel_con[0], 881 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK | 882 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK, 883 rate->aclk_div << CORE_ACLK_DIV_SHIFT | 884 rate->pclk_div << CORE_DBG_DIV_SHIFT | 885 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 886 0 << CORE_DIV_CON_SHIFT); 887 } else if (old_rate < hz) { 888 rk_clrsetreg(&cru->clksel_con[0], 889 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK | 890 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK, 891 rate->aclk_div << CORE_ACLK_DIV_SHIFT | 892 rate->pclk_div << CORE_DBG_DIV_SHIFT | 893 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 894 0 << CORE_DIV_CON_SHIFT); 895 if (rkclk_set_pll(&cru->pll[APLL], &cru->mode, APLL, hz)) 896 return -EINVAL; 897 } 898 899 return px30_clk_get_pll_rate(priv, APLL); 900 } 901 902 static ulong px30_clk_get_rate(struct clk *clk) 903 { 904 struct px30_clk_priv *priv = dev_get_priv(clk->dev); 905 ulong rate = 0; 906 907 if (!priv->gpll_hz && clk->id > ARMCLK) { 908 printf("%s gpll=%lu\n", __func__, priv->gpll_hz); 909 return -ENOENT; 910 } 911 912 debug("%s %ld\n", __func__, clk->id); 913 switch (clk->id) { 914 case PLL_APLL: 915 rate = px30_clk_get_pll_rate(priv, APLL); 916 break; 917 case PLL_DPLL: 918 rate = px30_clk_get_pll_rate(priv, DPLL); 919 break; 920 case PLL_CPLL: 921 rate = px30_clk_get_pll_rate(priv, CPLL); 922 break; 923 case PLL_NPLL: 924 rate = px30_clk_get_pll_rate(priv, NPLL); 925 break; 926 case ARMCLK: 927 rate = px30_clk_get_pll_rate(priv, APLL); 928 break; 929 case HCLK_SDMMC: 930 case HCLK_EMMC: 931 case SCLK_SDMMC: 932 case SCLK_EMMC: 933 case SCLK_EMMC_SAMPLE: 934 rate = px30_mmc_get_clk(priv, clk->id); 935 break; 936 case SCLK_I2C0: 937 case SCLK_I2C1: 938 case SCLK_I2C2: 939 case SCLK_I2C3: 940 rate = px30_i2c_get_clk(priv, clk->id); 941 break; 942 case SCLK_PWM0: 943 case SCLK_PWM1: 944 rate = px30_pwm_get_clk(priv, clk->id); 945 break; 946 case SCLK_SARADC: 947 rate = px30_saradc_get_clk(priv); 948 break; 949 case SCLK_SPI0: 950 case SCLK_SPI1: 951 rate = px30_spi_get_clk(priv, clk->id); 952 break; 953 case ACLK_VOPB: 954 case ACLK_VOPL: 955 case DCLK_VOPB: 956 case DCLK_VOPL: 957 rate = px30_vop_get_clk(priv, clk->id); 958 break; 959 case ACLK_BUS_PRE: 960 case HCLK_BUS_PRE: 961 case PCLK_BUS_PRE: 962 rate = px30_bus_get_clk(priv, clk->id); 963 break; 964 case ACLK_PERI_PRE: 965 case HCLK_PERI_PRE: 966 rate = px30_peri_get_clk(priv, clk->id); 967 break; 968 default: 969 return -ENOENT; 970 } 971 972 return rate; 973 } 974 975 static ulong px30_clk_set_rate(struct clk *clk, ulong rate) 976 { 977 struct px30_clk_priv *priv = dev_get_priv(clk->dev); 978 ulong ret = 0; 979 980 if (!priv->gpll_hz && clk->id > ARMCLK) { 981 printf("%s gpll=%lu\n", __func__, priv->gpll_hz); 982 return -ENOENT; 983 } 984 985 debug("%s %ld %ld\n", __func__, clk->id, rate); 986 switch (clk->id) { 987 case PLL_NPLL: 988 ret = px30_clk_set_pll_rate(priv, NPLL, rate); 989 break; 990 case ARMCLK: 991 if (priv->armclk_hz) 992 px30_armclk_set_clk(priv, rate); 993 priv->armclk_hz = rate; 994 break; 995 case HCLK_SDMMC: 996 case HCLK_EMMC: 997 case SCLK_SDMMC: 998 case SCLK_EMMC: 999 ret = px30_mmc_set_clk(priv, clk->id, rate); 1000 break; 1001 case SCLK_I2C0: 1002 case SCLK_I2C1: 1003 case SCLK_I2C2: 1004 case SCLK_I2C3: 1005 ret = px30_i2c_set_clk(priv, clk->id, rate); 1006 break; 1007 case SCLK_PWM0: 1008 case SCLK_PWM1: 1009 ret = px30_pwm_set_clk(priv, clk->id, rate); 1010 break; 1011 case SCLK_SARADC: 1012 ret = px30_saradc_set_clk(priv, rate); 1013 break; 1014 case SCLK_SPI0: 1015 case SCLK_SPI1: 1016 ret = px30_spi_set_clk(priv, clk->id, rate); 1017 break; 1018 case ACLK_VOPB: 1019 case ACLK_VOPL: 1020 case DCLK_VOPB: 1021 case DCLK_VOPL: 1022 ret = px30_vop_set_clk(priv, clk->id, rate); 1023 break; 1024 case ACLK_BUS_PRE: 1025 case HCLK_BUS_PRE: 1026 case PCLK_BUS_PRE: 1027 ret = px30_bus_set_clk(priv, clk->id, rate); 1028 break; 1029 case ACLK_PERI_PRE: 1030 case HCLK_PERI_PRE: 1031 ret = px30_peri_set_clk(priv, clk->id, rate); 1032 break; 1033 default: 1034 return -ENOENT; 1035 } 1036 1037 return ret; 1038 } 1039 1040 #define ROCKCHIP_MMC_DELAY_SEL BIT(10) 1041 #define ROCKCHIP_MMC_DEGREE_MASK 0x3 1042 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2 1043 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 1044 1045 #define PSECS_PER_SEC 1000000000000LL 1046 /* 1047 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 1048 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 1049 */ 1050 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 1051 1052 int rockchip_mmc_get_phase(struct clk *clk) 1053 { 1054 struct px30_clk_priv *priv = dev_get_priv(clk->dev); 1055 struct px30_cru *cru = priv->cru; 1056 u32 raw_value, delay_num; 1057 u16 degrees = 0; 1058 ulong rate; 1059 1060 rate = px30_clk_get_rate(clk); 1061 1062 if (rate < 0) 1063 return rate; 1064 1065 if (clk->id == SCLK_EMMC_SAMPLE) 1066 raw_value = readl(&cru->emmc_con[1]); 1067 else 1068 raw_value = readl(&cru->sdmmc_con[1]); 1069 1070 raw_value >>= 1; 1071 degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; 1072 1073 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 1074 /* degrees/delaynum * 10000 */ 1075 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 1076 36 * (rate / 1000000); 1077 1078 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 1079 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 1080 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 1081 } 1082 1083 return degrees % 360; 1084 } 1085 1086 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees) 1087 { 1088 struct px30_clk_priv *priv = dev_get_priv(clk->dev); 1089 struct px30_cru *cru = priv->cru; 1090 u8 nineties, remainder, delay_num; 1091 u32 raw_value, delay; 1092 ulong rate; 1093 1094 rate = px30_clk_get_rate(clk); 1095 1096 if (rate < 0) 1097 return rate; 1098 1099 nineties = degrees / 90; 1100 remainder = (degrees % 90); 1101 1102 /* 1103 * Convert to delay; do a little extra work to make sure we 1104 * don't overflow 32-bit / 64-bit numbers. 1105 */ 1106 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 1107 delay *= remainder; 1108 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 1109 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 1110 1111 delay_num = (u8)min_t(u32, delay, 255); 1112 1113 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 1114 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 1115 raw_value |= nineties; 1116 1117 raw_value <<= 1; 1118 if (clk->id == SCLK_EMMC_SAMPLE) 1119 writel(raw_value | 0xffff0000, &cru->emmc_con[1]); 1120 else 1121 writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]); 1122 1123 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 1124 degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk)); 1125 1126 return 0; 1127 } 1128 1129 static int px30_clk_get_phase(struct clk *clk) 1130 { 1131 int ret; 1132 1133 debug("%s %ld\n", __func__, clk->id); 1134 switch (clk->id) { 1135 case SCLK_EMMC_SAMPLE: 1136 case SCLK_SDMMC_SAMPLE: 1137 ret = rockchip_mmc_get_phase(clk); 1138 break; 1139 default: 1140 return -ENOENT; 1141 } 1142 1143 return ret; 1144 } 1145 1146 static int px30_clk_set_phase(struct clk *clk, int degrees) 1147 { 1148 int ret; 1149 1150 debug("%s %ld\n", __func__, clk->id); 1151 switch (clk->id) { 1152 case SCLK_EMMC_SAMPLE: 1153 case SCLK_SDMMC_SAMPLE: 1154 ret = rockchip_mmc_set_phase(clk, degrees); 1155 break; 1156 default: 1157 return -ENOENT; 1158 } 1159 1160 return ret; 1161 } 1162 1163 static struct clk_ops px30_clk_ops = { 1164 .get_rate = px30_clk_get_rate, 1165 .set_rate = px30_clk_set_rate, 1166 .get_phase = px30_clk_get_phase, 1167 .set_phase = px30_clk_set_phase, 1168 }; 1169 1170 static int px30_clk_probe(struct udevice *dev) 1171 { 1172 struct px30_clk_priv *priv = dev_get_priv(dev); 1173 int ret; 1174 1175 if (px30_clk_get_pll_rate(priv, APLL) != APLL_HZ) { 1176 ret = px30_armclk_set_clk(priv, APLL_HZ); 1177 if (ret < 0) 1178 printf("%s failed to set armclk rate\n", __func__); 1179 } 1180 1181 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 1182 ret = clk_set_defaults(dev); 1183 if (ret) 1184 debug("%s clk_set_defaults failed %d\n", __func__, ret); 1185 1186 if (!priv->gpll_hz) { 1187 ret = px30_clk_get_gpll_rate(&priv->gpll_hz); 1188 if (ret) { 1189 printf("%s failed to get gpll rate\n", __func__); 1190 return ret; 1191 } 1192 } 1193 1194 return 0; 1195 } 1196 1197 static int px30_clk_ofdata_to_platdata(struct udevice *dev) 1198 { 1199 struct px30_clk_priv *priv = dev_get_priv(dev); 1200 1201 priv->cru = dev_read_addr_ptr(dev); 1202 1203 return 0; 1204 } 1205 1206 static int px30_clk_bind(struct udevice *dev) 1207 { 1208 int ret; 1209 struct udevice *sys_child, *sf_child; 1210 struct sysreset_reg *priv; 1211 struct softreset_reg *sf_priv; 1212 1213 /* The reset driver does not have a device node, so bind it here */ 1214 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 1215 &sys_child); 1216 if (ret) { 1217 debug("Warning: No sysreset driver: ret=%d\n", ret); 1218 } else { 1219 priv = malloc(sizeof(struct sysreset_reg)); 1220 priv->glb_srst_fst_value = offsetof(struct px30_cru, 1221 glb_srst_fst); 1222 priv->glb_srst_snd_value = offsetof(struct px30_cru, 1223 glb_srst_snd); 1224 sys_child->priv = priv; 1225 } 1226 1227 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 1228 dev_ofnode(dev), &sf_child); 1229 if (ret) { 1230 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 1231 } else { 1232 sf_priv = malloc(sizeof(struct softreset_reg)); 1233 sf_priv->sf_reset_offset = offsetof(struct px30_cru, 1234 softrst_con[0]); 1235 sf_priv->sf_reset_num = 12; 1236 sf_child->priv = sf_priv; 1237 } 1238 1239 return 0; 1240 } 1241 1242 static const struct udevice_id px30_clk_ids[] = { 1243 { .compatible = "rockchip,px30-cru" }, 1244 { } 1245 }; 1246 1247 U_BOOT_DRIVER(rockchip_px30_cru) = { 1248 .name = "rockchip_px30_cru", 1249 .id = UCLASS_CLK, 1250 .of_match = px30_clk_ids, 1251 .priv_auto_alloc_size = sizeof(struct px30_clk_priv), 1252 .ofdata_to_platdata = px30_clk_ofdata_to_platdata, 1253 .ops = &px30_clk_ops, 1254 .bind = px30_clk_bind, 1255 .probe = px30_clk_probe, 1256 }; 1257 1258 static ulong px30_pclk_pmu_get_pmuclk(struct px30_pmuclk_priv *priv) 1259 { 1260 struct px30_pmucru *pmucru = priv->pmucru; 1261 u32 div, con; 1262 1263 con = readl(&pmucru->pmu_clksel_con[0]); 1264 div = (con & CLK_PMU_PCLK_DIV_MASK) >> CLK_PMU_PCLK_DIV_SHIFT; 1265 1266 return DIV_TO_RATE(priv->gpll_hz, div); 1267 } 1268 1269 static ulong px30_pclk_pmu_set_pmuclk(struct px30_pmuclk_priv *priv, ulong hz) 1270 { 1271 struct px30_pmucru *pmucru = priv->pmucru; 1272 int src_clk_div; 1273 1274 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 1275 assert(src_clk_div - 1 <= 31); 1276 1277 rk_clrsetreg(&pmucru->pmu_clksel_con[0], 1278 CLK_PMU_PCLK_DIV_MASK, 1279 (src_clk_div - 1) << CLK_PMU_PCLK_DIV_SHIFT); 1280 1281 return px30_pclk_pmu_get_pmuclk(priv); 1282 } 1283 1284 static ulong px30_gpll_get_pmuclk(struct px30_pmuclk_priv *priv) 1285 { 1286 struct px30_pmucru *pmucru = priv->pmucru; 1287 1288 return rkclk_pll_get_rate(&pmucru->pll, &pmucru->pmu_mode, GPLL); 1289 } 1290 1291 static ulong px30_gpll_set_pmuclk(struct px30_pmuclk_priv *priv, ulong hz) 1292 { 1293 struct udevice *cru_dev; 1294 struct px30_clk_priv *cru_priv; 1295 struct px30_pmucru *pmucru = priv->pmucru; 1296 u32 div; 1297 ulong emmc_rate, sdmmc_rate, nandc_rate; 1298 ulong aclk_bus_rate, hclk_bus_rate, pclk_bus_rate; 1299 ulong aclk_peri_rate, hclk_peri_rate, pclk_pmu_rate; 1300 int ret; 1301 1302 ret = uclass_get_device_by_name(UCLASS_CLK, 1303 "clock-controller@ff2b0000", 1304 &cru_dev); 1305 if (ret) { 1306 printf("%s failed to get cru device\n", __func__); 1307 return ret; 1308 } 1309 cru_priv = dev_get_priv(cru_dev); 1310 1311 if (priv->gpll_hz == hz) 1312 return priv->gpll_hz; 1313 1314 cru_priv->gpll_hz = priv->gpll_hz; 1315 div = DIV_ROUND_UP(hz, priv->gpll_hz); 1316 1317 /* save clock rate */ 1318 aclk_bus_rate = px30_bus_get_clk(cru_priv, ACLK_BUS_PRE); 1319 hclk_bus_rate = px30_bus_get_clk(cru_priv, HCLK_BUS_PRE); 1320 pclk_bus_rate = px30_bus_get_clk(cru_priv, PCLK_BUS_PRE); 1321 aclk_peri_rate = px30_peri_get_clk(cru_priv, ACLK_PERI_PRE); 1322 hclk_peri_rate = px30_peri_get_clk(cru_priv, HCLK_PERI_PRE); 1323 pclk_pmu_rate = px30_pclk_pmu_get_pmuclk(priv); 1324 debug("%s aclk_bus=%lu, hclk_bus=%lu, pclk_bus=%lu\n", __func__, 1325 aclk_bus_rate, hclk_bus_rate, pclk_bus_rate); 1326 debug("%s aclk_peri=%lu, hclk_peri=%lu, pclk_pmu=%lu\n", __func__, 1327 aclk_peri_rate, hclk_peri_rate, pclk_pmu_rate); 1328 emmc_rate = px30_mmc_get_clk(cru_priv, SCLK_EMMC); 1329 sdmmc_rate = px30_mmc_get_clk(cru_priv, SCLK_SDMMC); 1330 nandc_rate = px30_nandc_get_clk(cru_priv); 1331 debug("%s emmc=%lu, sdmmc=%lu, nandc=%lu\n", __func__, 1332 emmc_rate, sdmmc_rate, nandc_rate); 1333 1334 /* avoid rate too large, reduce rate first */ 1335 px30_bus_set_clk(cru_priv, ACLK_BUS_PRE, aclk_bus_rate / div); 1336 px30_bus_set_clk(cru_priv, HCLK_BUS_PRE, hclk_bus_rate / div); 1337 px30_bus_set_clk(cru_priv, PCLK_BUS_PRE, pclk_bus_rate / div); 1338 px30_peri_set_clk(cru_priv, ACLK_PERI_PRE, aclk_peri_rate / div); 1339 px30_peri_set_clk(cru_priv, HCLK_PERI_PRE, hclk_peri_rate / div); 1340 px30_pclk_pmu_set_pmuclk(priv, pclk_pmu_rate / div); 1341 1342 px30_mmc_set_clk(cru_priv, SCLK_EMMC, emmc_rate / div); 1343 px30_mmc_set_clk(cru_priv, SCLK_SDMMC, sdmmc_rate / div); 1344 px30_nandc_set_clk(cru_priv, nandc_rate / div); 1345 1346 /* change gpll rate */ 1347 rkclk_set_pll(&pmucru->pll, &pmucru->pmu_mode, GPLL, hz); 1348 priv->gpll_hz = px30_gpll_get_pmuclk(priv); 1349 cru_priv->gpll_hz = priv->gpll_hz; 1350 1351 /* restore clock rate */ 1352 px30_bus_set_clk(cru_priv, ACLK_BUS_PRE, aclk_bus_rate); 1353 px30_bus_set_clk(cru_priv, HCLK_BUS_PRE, hclk_bus_rate); 1354 px30_bus_set_clk(cru_priv, PCLK_BUS_PRE, pclk_bus_rate); 1355 px30_peri_set_clk(cru_priv, ACLK_PERI_PRE, aclk_peri_rate); 1356 px30_peri_set_clk(cru_priv, HCLK_PERI_PRE, hclk_peri_rate); 1357 px30_pclk_pmu_set_pmuclk(priv, pclk_pmu_rate); 1358 1359 px30_mmc_set_clk(cru_priv, SCLK_EMMC, emmc_rate); 1360 px30_mmc_set_clk(cru_priv, SCLK_SDMMC, sdmmc_rate); 1361 px30_nandc_set_clk(cru_priv, nandc_rate); 1362 1363 return priv->gpll_hz; 1364 } 1365 1366 static ulong px30_pmuclk_get_rate(struct clk *clk) 1367 { 1368 struct px30_pmuclk_priv *priv = dev_get_priv(clk->dev); 1369 ulong rate = 0; 1370 1371 debug("%s %ld\n", __func__, clk->id); 1372 switch (clk->id) { 1373 case PLL_GPLL: 1374 rate = px30_gpll_get_pmuclk(priv); 1375 break; 1376 case PCLK_PMU_PRE: 1377 rate = px30_pclk_pmu_get_pmuclk(priv); 1378 break; 1379 default: 1380 return -ENOENT; 1381 } 1382 1383 return rate; 1384 } 1385 1386 static ulong px30_pmuclk_set_rate(struct clk *clk, ulong rate) 1387 { 1388 struct px30_pmuclk_priv *priv = dev_get_priv(clk->dev); 1389 ulong ret = 0; 1390 1391 debug("%s %ld %ld\n", __func__, clk->id, rate); 1392 switch (clk->id) { 1393 case PLL_GPLL: 1394 ret = px30_gpll_set_pmuclk(priv, rate); 1395 break; 1396 case PCLK_PMU_PRE: 1397 ret = px30_pclk_pmu_set_pmuclk(priv, rate); 1398 break; 1399 default: 1400 return -ENOENT; 1401 } 1402 1403 return ret; 1404 } 1405 1406 static struct clk_ops px30_pmuclk_ops = { 1407 .get_rate = px30_pmuclk_get_rate, 1408 .set_rate = px30_pmuclk_set_rate, 1409 }; 1410 1411 static void px30_clk_init(struct px30_pmuclk_priv *priv) 1412 { 1413 struct udevice *cru_dev; 1414 struct px30_clk_priv *cru_priv; 1415 ulong npll_hz; 1416 int ret; 1417 1418 priv->gpll_hz = px30_gpll_get_pmuclk(priv); 1419 if (priv->gpll_hz != GPLL_HZ) { 1420 ret = px30_gpll_set_pmuclk(priv, GPLL_HZ); 1421 if (ret < 0) 1422 printf("%s failed to set gpll rate\n", __func__); 1423 } 1424 1425 ret = uclass_get_device_by_name(UCLASS_CLK, 1426 "clock-controller@ff2b0000", 1427 &cru_dev); 1428 if (ret) { 1429 printf("%s failed to get cru device\n", __func__); 1430 return; 1431 } 1432 cru_priv = dev_get_priv(cru_dev); 1433 cru_priv->gpll_hz = priv->gpll_hz; 1434 1435 npll_hz = px30_clk_get_pll_rate(cru_priv, NPLL); 1436 if (npll_hz != NPLL_HZ) { 1437 ret = px30_clk_set_pll_rate(cru_priv, NPLL, NPLL_HZ); 1438 if (ret < 0) 1439 printf("%s failed to set npll rate\n", __func__); 1440 } 1441 1442 px30_bus_set_clk(cru_priv, ACLK_BUS_PRE, ACLK_BUS_HZ); 1443 px30_bus_set_clk(cru_priv, HCLK_BUS_PRE, HCLK_BUS_HZ); 1444 px30_bus_set_clk(cru_priv, PCLK_BUS_PRE, PCLK_BUS_HZ); 1445 px30_peri_set_clk(cru_priv, ACLK_PERI_PRE, ACLK_PERI_HZ); 1446 px30_peri_set_clk(cru_priv, HCLK_PERI_PRE, HCLK_PERI_HZ); 1447 px30_pclk_pmu_set_pmuclk(priv, PCLK_PMU_HZ); 1448 } 1449 1450 static int px30_pmuclk_probe(struct udevice *dev) 1451 { 1452 struct px30_pmuclk_priv *priv = dev_get_priv(dev); 1453 int ret; 1454 1455 px30_clk_init(priv); 1456 1457 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 1458 ret = clk_set_defaults(dev); 1459 if (ret) 1460 debug("%s clk_set_defaults failed %d\n", __func__, ret); 1461 1462 return 0; 1463 } 1464 1465 static int px30_pmuclk_ofdata_to_platdata(struct udevice *dev) 1466 { 1467 struct px30_pmuclk_priv *priv = dev_get_priv(dev); 1468 1469 priv->pmucru = dev_read_addr_ptr(dev); 1470 1471 return 0; 1472 } 1473 1474 static const struct udevice_id px30_pmuclk_ids[] = { 1475 { .compatible = "rockchip,px30-pmucru" }, 1476 { } 1477 }; 1478 1479 U_BOOT_DRIVER(rockchip_px30_pmucru) = { 1480 .name = "rockchip_px30_pmucru", 1481 .id = UCLASS_CLK, 1482 .of_match = px30_pmuclk_ids, 1483 .priv_auto_alloc_size = sizeof(struct px30_pmuclk_priv), 1484 .ofdata_to_platdata = px30_pmuclk_ofdata_to_platdata, 1485 .ops = &px30_pmuclk_ops, 1486 .probe = px30_pmuclk_probe, 1487 }; 1488 1489 /** 1490 * soc_clk_dump() - Print clock frequencies 1491 * Returns zero on success 1492 * 1493 * Implementation for the clk dump command. 1494 */ 1495 int soc_clk_dump(void) 1496 { 1497 struct udevice *cru_dev, *pmucru_dev; 1498 const struct px30_clk_info *clk_dump; 1499 struct clk clk; 1500 unsigned long clk_count = ARRAY_SIZE(clks_dump); 1501 unsigned long rate; 1502 int i, ret; 1503 1504 ret = uclass_get_device_by_driver(UCLASS_CLK, 1505 DM_GET_DRIVER(rockchip_px30_cru), 1506 &cru_dev); 1507 if (ret) { 1508 printf("%s failed to get cru device\n", __func__); 1509 return ret; 1510 } 1511 1512 ret = uclass_get_device_by_driver(UCLASS_CLK, 1513 DM_GET_DRIVER(rockchip_px30_pmucru), 1514 &pmucru_dev); 1515 if (ret) { 1516 printf("%s failed to get pmucru device\n", __func__); 1517 return ret; 1518 } 1519 1520 printf("CLK:\n"); 1521 for (i = 0; i < clk_count; i++) { 1522 clk_dump = &clks_dump[i]; 1523 if (clk_dump->name) { 1524 clk.id = clk_dump->id; 1525 if (clk_dump->is_cru) 1526 ret = clk_request(cru_dev, &clk); 1527 else 1528 ret = clk_request(pmucru_dev, &clk); 1529 if (ret < 0) 1530 return ret; 1531 1532 rate = clk_get_rate(&clk); 1533 clk_free(&clk); 1534 if (i == 0) { 1535 if (rate < 0) 1536 printf("%s %s\n", clk_dump->name, 1537 "unknown"); 1538 else 1539 printf("%s %lu KHz\n", clk_dump->name, 1540 rate / 1000); 1541 } else { 1542 if (rate < 0) 1543 printf("%s %s\n", clk_dump->name, 1544 "unknown"); 1545 else 1546 printf("%s %lu KHz\n", clk_dump->name, 1547 rate / 1000); 1548 } 1549 } 1550 } 1551 1552 return 0; 1553 } 1554