1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0 5 */ 6 #include <common.h> 7 #include <bitfield.h> 8 #include <clk-uclass.h> 9 #include <dm.h> 10 #include <div64.h> 11 #include <errno.h> 12 #include <syscon.h> 13 #include <asm/arch/clock.h> 14 #include <asm/arch/cru_rk3308.h> 15 #include <asm/arch/hardware.h> 16 #include <asm/io.h> 17 #include <dm/lists.h> 18 #include <dt-bindings/clock/rk3308-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 RK3308_CLK_DUMP(_id, _name) \ 32 { \ 33 .id = _id, \ 34 .name = _name, \ 35 } 36 37 #define RK3308_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \ 38 _postdiv2, _dsmpd, _frac) \ 39 { \ 40 .rate = _rate##U, \ 41 .fbdiv = _fbdiv, \ 42 .postdiv1 = _postdiv1, \ 43 .refdiv = _refdiv, \ 44 .postdiv2 = _postdiv2, \ 45 .dsmpd = _dsmpd, \ 46 .frac = _frac, \ 47 } 48 49 static struct pll_rate_table rk3308_pll_rates[] = { 50 /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ 51 RK3308_PLL_RATE(1300000000, 6, 325, 1, 1, 1, 0), 52 RK3308_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), 53 RK3308_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0), 54 RK3308_PLL_RATE(748000000, 2, 187, 3, 1, 1, 0), 55 }; 56 57 static u8 pll_mode_shift[PLL_COUNT] = { 58 APLL_MODE_SHIFT, DPLL_MODE_SHIFT, VPLL0_MODE_SHIFT, 59 VPLL1_MODE_SHIFT 60 }; 61 62 static u32 pll_mode_mask[PLL_COUNT] = { 63 APLL_MODE_MASK, DPLL_MODE_MASK, VPLL0_MODE_MASK, 64 VPLL1_MODE_MASK 65 }; 66 67 static const struct rk3308_clk_info clks_dump[] = { 68 RK3308_CLK_DUMP(PLL_APLL, "apll"), 69 RK3308_CLK_DUMP(PLL_DPLL, "dpll"), 70 RK3308_CLK_DUMP(PLL_VPLL0, "vpll0"), 71 RK3308_CLK_DUMP(PLL_VPLL1, "vpll1"), 72 RK3308_CLK_DUMP(ACLK_BUS, "aclk_bus"), 73 RK3308_CLK_DUMP(HCLK_BUS, "hclk_bus"), 74 RK3308_CLK_DUMP(PCLK_BUS, "pclk_bus"), 75 RK3308_CLK_DUMP(ACLK_PERI, "aclk_peri"), 76 RK3308_CLK_DUMP(HCLK_PERI, "hclk_peri"), 77 RK3308_CLK_DUMP(PCLK_PERI, "pclk_peri"), 78 RK3308_CLK_DUMP(HCLK_AUDIO, "hclk_audio"), 79 RK3308_CLK_DUMP(PCLK_AUDIO, "pclk_audio"), 80 }; 81 82 static ulong rk3308_bus_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, 83 ulong hz); 84 static ulong rk3308_peri_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, 85 ulong hz); 86 static ulong rk3308_audio_set_clk(struct rk3308_clk_priv *priv, 87 ulong clk_id, ulong hz); 88 89 static const struct pll_rate_table *get_pll_settings(unsigned long rate) 90 { 91 unsigned int rate_count = ARRAY_SIZE(rk3308_pll_rates); 92 int i; 93 94 for (i = 0; i < rate_count; i++) { 95 if (rate == rk3308_pll_rates[i].rate) 96 return &rk3308_pll_rates[i]; 97 } 98 99 return NULL; 100 } 101 102 /* 103 * How to calculate the PLL: 104 * Formulas also embedded within the Fractional PLL Verilog model: 105 * If DSMPD = 1 (DSM is disabled, "integer mode") 106 * FOUTVCO = FREF / REFDIV * FBDIV 107 * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2 108 * Where: 109 * FOUTVCO = Fractional PLL non-divided output frequency 110 * FOUTPOSTDIV = Fractional PLL divided output frequency 111 * (output of second post divider) 112 * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input) 113 * REFDIV = Fractional PLL input reference clock divider 114 * FBDIV = Integer value programmed into feedback divide 115 * 116 */ 117 118 static int rkclk_set_pll(struct rk3308_clk_priv *priv, 119 enum rk3308_pll_id pll_id, 120 unsigned long drate) 121 { 122 struct rk3308_cru *cru = priv->cru; 123 struct rk3308_pll *pll; 124 unsigned int *mode; 125 const struct pll_rate_table *rate; 126 uint vco_hz, output_hz; 127 128 rate = get_pll_settings(drate); 129 if (!rate) { 130 printf("%s unsupport rate\n", __func__); 131 return -EINVAL; 132 } 133 134 /* All PLLs have same VCO and output frequency range restrictions. */ 135 vco_hz = OSC_HZ / 1000 * rate->fbdiv / rate->refdiv * 1000; 136 output_hz = vco_hz / rate->postdiv1 / rate->postdiv2; 137 138 pll = &cru->pll[pll_id]; 139 mode = &cru->mode; 140 141 debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n", 142 pll, rate->fbdiv, rate->refdiv, rate->postdiv1, 143 rate->postdiv2, vco_hz, output_hz); 144 assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ && 145 output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ); 146 147 /* 148 * When power on or changing PLL setting, 149 * we must force PLL into slow mode to ensure output stable clock. 150 */ 151 rk_clrsetreg(mode, pll_mode_mask[pll_id], 152 PLLMUX_FROM_XIN24M << pll_mode_shift[pll_id]); 153 154 /* use integer mode */ 155 rk_setreg(&pll->con1, 1 << PLL_DSMPD_SHIFT); 156 /* Power down */ 157 rk_setreg(&pll->con1, 1 << PLL_PD_SHIFT); 158 159 rk_clrsetreg(&pll->con0, 160 PLL_POSTDIV1_MASK | PLL_FBDIV_MASK, 161 (rate->postdiv1 << PLL_POSTDIV1_SHIFT) | rate->fbdiv); 162 rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK | PLL_REFDIV_MASK, 163 (rate->postdiv2 << PLL_POSTDIV2_SHIFT | 164 rate->refdiv << PLL_REFDIV_SHIFT)); 165 166 /* Power Up */ 167 rk_clrreg(&pll->con1, 1 << PLL_PD_SHIFT); 168 169 /* waiting for pll lock */ 170 while (!(readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT))) 171 udelay(1); 172 173 rk_clrsetreg(mode, pll_mode_mask[pll_id], 174 PLLMUX_FROM_PLL << pll_mode_shift[pll_id]); 175 176 return 0; 177 } 178 179 static uint32_t rkclk_pll_get_rate(struct rk3308_clk_priv *priv, 180 enum rk3308_pll_id pll_id) 181 { 182 struct rk3308_cru *cru = priv->cru; 183 struct rk3308_pll *pll; 184 u32 con, refdiv, fbdiv, postdiv1, postdiv2, dsmpd, frac; 185 u32 rate = 0; 186 u64 frac_rate64 = 0; 187 uint shift; 188 uint mask; 189 190 pll = &cru->pll[pll_id]; 191 con = readl(&cru->mode); 192 193 shift = pll_mode_shift[pll_id]; 194 mask = pll_mode_mask[pll_id]; 195 196 switch ((con & mask) >> shift) { 197 case PLLMUX_FROM_XIN24M: 198 return OSC_HZ; 199 case PLLMUX_FROM_PLL: 200 /* normal mode */ 201 con = readl(&pll->con0); 202 postdiv1 = (con & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT; 203 fbdiv = (con & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT; 204 con = readl(&pll->con1); 205 postdiv2 = (con & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT; 206 refdiv = (con & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT; 207 dsmpd = (con & PLL_DSMPD_MASK) >> PLL_DSMPD_SHIFT; 208 con = readl(&pll->con2); 209 frac = con & PLL_FRAC_DIV; 210 rate = (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000; 211 if (dsmpd == 0) { 212 /* fractional mode */ 213 frac_rate64 = 24000000 * (u64)frac; 214 do_div(frac_rate64, refdiv); 215 frac_rate64 >>= 24; 216 do_div(frac_rate64, postdiv1); 217 do_div(frac_rate64, postdiv2); 218 rate += (uint32_t)frac_rate64; 219 } 220 return rate; 221 case PLLMUX_FROM_RTC32K: 222 default: 223 return 32768; 224 } 225 } 226 227 static void rk3308_clk_get_pll_rate(struct rk3308_clk_priv *priv) 228 { 229 if (!priv->dpll_hz) 230 priv->dpll_hz = rkclk_pll_get_rate(priv, DPLL); 231 if (!priv->vpll0_hz) 232 priv->vpll0_hz = rkclk_pll_get_rate(priv, VPLL0); 233 if (!priv->vpll1_hz) 234 priv->vpll1_hz = rkclk_pll_get_rate(priv, VPLL1); 235 } 236 237 static void rkclk_init(struct udevice *dev) 238 { 239 struct rk3308_clk_priv *priv = dev_get_priv(dev); 240 struct rk3308_cru *cru = priv->cru; 241 u32 aclk_div, pclk_div; 242 243 /* init pll */ 244 if (rkclk_set_pll(priv, APLL, APLL_HZ)) 245 printf("%s set apll unsuccessfully\n", __func__); 246 247 /* 248 * select apll as cpu/core clock pll source and 249 * set up dependent divisors for PCLK and ACLK clocks. 250 * core hz : apll = 1:1 251 */ 252 priv->apll_hz = rkclk_pll_get_rate(priv, APLL); 253 aclk_div = priv->apll_hz / CORE_ACLK_HZ - 1; 254 pclk_div = priv->apll_hz / CORE_DBG_HZ - 1; 255 rk_clrsetreg(&cru->clksel_con[0], 256 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK | 257 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK, 258 aclk_div << CORE_ACLK_DIV_SHIFT | 259 pclk_div << CORE_DBG_DIV_SHIFT | 260 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 261 0 << CORE_DIV_CON_SHIFT); 262 263 #ifndef CONFIG_USING_KERNEL_DTB 264 rk3308_clk_get_pll_rate(priv); 265 266 rk3308_bus_set_clk(priv, ACLK_BUS, BUS_ACLK_HZ); 267 rk3308_bus_set_clk(priv, HCLK_BUS, BUS_HCLK_HZ); 268 rk3308_bus_set_clk(priv, PCLK_BUS, BUS_PCLK_HZ); 269 270 rk3308_peri_set_clk(priv, ACLK_PERI, PERI_ACLK_HZ); 271 rk3308_peri_set_clk(priv, HCLK_PERI, PERI_HCLK_HZ); 272 rk3308_peri_set_clk(priv, PCLK_PERI, PERI_PCLK_HZ); 273 274 rk3308_audio_set_clk(priv, HCLK_AUDIO, AUDIO_HCLK_HZ); 275 rk3308_audio_set_clk(priv, PCLK_AUDIO, AUDIO_PCLK_HZ); 276 #endif 277 } 278 279 static ulong rk3308_i2c_get_clk(struct clk *clk) 280 { 281 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 282 struct rk3308_cru *cru = priv->cru; 283 u32 div, con, con_id; 284 285 switch (clk->id) { 286 case SCLK_I2C0: 287 con_id = 25; 288 break; 289 case SCLK_I2C1: 290 con_id = 26; 291 break; 292 case SCLK_I2C2: 293 con_id = 27; 294 break; 295 case SCLK_I2C3: 296 con_id = 28; 297 break; 298 default: 299 printf("do not support this i2c bus\n"); 300 return -EINVAL; 301 } 302 303 con = readl(&cru->clksel_con[con_id]); 304 div = con >> CLK_I2C_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 305 306 return DIV_TO_RATE(priv->dpll_hz, div); 307 } 308 309 static ulong rk3308_i2c_set_clk(struct clk *clk, uint hz) 310 { 311 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 312 struct rk3308_cru *cru = priv->cru; 313 u32 src_clk_div, con_id; 314 315 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); 316 assert(src_clk_div - 1 < 127); 317 318 switch (clk->id) { 319 case SCLK_I2C0: 320 con_id = 25; 321 break; 322 case SCLK_I2C1: 323 con_id = 26; 324 break; 325 case SCLK_I2C2: 326 con_id = 27; 327 break; 328 case SCLK_I2C3: 329 con_id = 28; 330 break; 331 default: 332 printf("do not support this i2c bus\n"); 333 return -EINVAL; 334 } 335 rk_clrsetreg(&cru->clksel_con[con_id], 336 CLK_I2C_PLL_SEL_MASK | CLK_I2C_DIV_CON_MASK, 337 CLK_I2C_PLL_SEL_DPLL << CLK_I2C_PLL_SEL_SHIFT | 338 (src_clk_div - 1) << CLK_I2C_DIV_CON_SHIFT); 339 340 return rk3308_i2c_get_clk(clk); 341 } 342 343 static ulong rk3308_mmc_get_clk(struct clk *clk) 344 { 345 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 346 struct rk3308_cru *cru = priv->cru; 347 u32 div, con, con_id; 348 349 switch (clk->id) { 350 case HCLK_SDMMC: 351 case SCLK_SDMMC: 352 con_id = 39; 353 break; 354 case HCLK_EMMC: 355 case SCLK_EMMC: 356 case SCLK_EMMC_SAMPLE: 357 con_id = 41; 358 break; 359 default: 360 return -EINVAL; 361 } 362 363 con = readl(&cru->clksel_con[con_id]); 364 div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT; 365 366 if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT 367 == EMMC_SEL_24M) 368 return DIV_TO_RATE(OSC_HZ, div) / 2; 369 else 370 return DIV_TO_RATE(priv->vpll0_hz, div) / 2; 371 } 372 373 static ulong rk3308_mmc_set_clk(struct clk *clk, ulong set_rate) 374 { 375 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 376 struct rk3308_cru *cru = priv->cru; 377 int src_clk_div; 378 u32 con_id; 379 380 debug("%s %ld %ld\n", __func__, clk->id, set_rate); 381 382 switch (clk->id) { 383 case HCLK_SDMMC: 384 case SCLK_SDMMC: 385 con_id = 39; 386 break; 387 case HCLK_EMMC: 388 case SCLK_EMMC: 389 con_id = 41; 390 break; 391 default: 392 return -EINVAL; 393 } 394 /* Select clk_sdmmc/emmc source from VPLL0 by default */ 395 /* mmc clock defaulg div 2 internal, need provide double in cru */ 396 src_clk_div = DIV_ROUND_UP(priv->vpll0_hz / 2, set_rate); 397 398 if (src_clk_div > 127) { 399 /* use 24MHz source for 400KHz clock */ 400 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate); 401 rk_clrsetreg(&cru->clksel_con[con_id], 402 EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK, 403 EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT | 404 EMMC_SEL_24M << EMMC_PLL_SHIFT | 405 (src_clk_div - 1) << EMMC_DIV_SHIFT); 406 } else { 407 rk_clrsetreg(&cru->clksel_con[con_id], 408 EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK, 409 EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT | 410 EMMC_SEL_VPLL0 << EMMC_PLL_SHIFT | 411 (src_clk_div - 1) << EMMC_DIV_SHIFT); 412 } 413 414 return rk3308_mmc_get_clk(clk); 415 } 416 417 static ulong rk3308_saradc_get_clk(struct clk *clk) 418 { 419 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 420 struct rk3308_cru *cru = priv->cru; 421 u32 div, con; 422 423 con = readl(&cru->clksel_con[34]); 424 div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK; 425 426 return DIV_TO_RATE(OSC_HZ, div); 427 } 428 429 static ulong rk3308_saradc_set_clk(struct clk *clk, uint hz) 430 { 431 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 432 struct rk3308_cru *cru = priv->cru; 433 int src_clk_div; 434 435 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz); 436 assert(src_clk_div - 1 < 2047); 437 438 rk_clrsetreg(&cru->clksel_con[34], 439 CLK_SARADC_DIV_CON_MASK, 440 (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT); 441 442 return rk3308_saradc_get_clk(clk); 443 } 444 445 static ulong rk3308_spi_get_clk(struct clk *clk) 446 { 447 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 448 struct rk3308_cru *cru = priv->cru; 449 u32 div, con, con_id; 450 451 switch (clk->id) { 452 case SCLK_SPI0: 453 con_id = 30; 454 break; 455 case SCLK_SPI1: 456 con_id = 31; 457 break; 458 case SCLK_SPI2: 459 con_id = 32; 460 break; 461 default: 462 printf("do not support this spi bus\n"); 463 return -EINVAL; 464 } 465 466 con = readl(&cru->clksel_con[con_id]); 467 div = con >> CLK_SPI_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK; 468 469 return DIV_TO_RATE(priv->dpll_hz, div); 470 } 471 472 static ulong rk3308_spi_set_clk(struct clk *clk, uint hz) 473 { 474 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 475 struct rk3308_cru *cru = priv->cru; 476 u32 src_clk_div, con_id; 477 478 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); 479 assert(src_clk_div - 1 < 127); 480 481 switch (clk->id) { 482 case SCLK_SPI0: 483 con_id = 30; 484 break; 485 case SCLK_SPI1: 486 con_id = 31; 487 break; 488 case SCLK_SPI2: 489 con_id = 32; 490 break; 491 default: 492 printf("do not support this spi bus\n"); 493 return -EINVAL; 494 } 495 496 rk_clrsetreg(&cru->clksel_con[con_id], 497 CLK_SPI_PLL_SEL_MASK | CLK_SPI_DIV_CON_MASK, 498 CLK_SPI_PLL_SEL_DPLL << CLK_SPI_PLL_SEL_SHIFT | 499 (src_clk_div - 1) << CLK_SPI_DIV_CON_SHIFT); 500 501 return rk3308_spi_get_clk(clk); 502 } 503 504 static ulong rk3308_pwm_get_clk(struct clk *clk) 505 { 506 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 507 struct rk3308_cru *cru = priv->cru; 508 u32 div, con; 509 510 con = readl(&cru->clksel_con[29]); 511 div = con >> CLK_PWM_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK; 512 513 return DIV_TO_RATE(priv->dpll_hz, div); 514 } 515 516 static ulong rk3308_pwm_set_clk(struct clk *clk, uint hz) 517 { 518 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 519 struct rk3308_cru *cru = priv->cru; 520 int src_clk_div; 521 522 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); 523 assert(src_clk_div - 1 < 127); 524 525 rk_clrsetreg(&cru->clksel_con[29], 526 CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK, 527 CLK_PWM_PLL_SEL_DPLL << CLK_PWM_PLL_SEL_SHIFT | 528 (src_clk_div - 1) << CLK_PWM_DIV_CON_SHIFT); 529 530 return rk3308_pwm_get_clk(clk); 531 } 532 533 static ulong rk3308_vop_get_clk(struct clk *clk) 534 { 535 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 536 struct rk3308_cru *cru = priv->cru; 537 u32 div, pll_sel, vol_sel, con, parent; 538 539 con = readl(&cru->clksel_con[8]); 540 vol_sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT; 541 pll_sel = (con & DCLK_VOP_PLL_SEL_MASK) >> DCLK_VOP_PLL_SEL_SHIFT; 542 div = con & DCLK_VOP_DIV_MASK; 543 544 if (vol_sel == DCLK_VOP_SEL_24M) { 545 parent = OSC_HZ; 546 } else if (vol_sel == DCLK_VOP_SEL_DIVOUT) { 547 switch (pll_sel) { 548 case DCLK_VOP_PLL_SEL_DPLL: 549 parent = priv->dpll_hz; 550 break; 551 case DCLK_VOP_PLL_SEL_VPLL0: 552 parent = priv->vpll0_hz; 553 break; 554 case DCLK_VOP_PLL_SEL_VPLL1: 555 parent = priv->vpll0_hz; 556 break; 557 default: 558 printf("do not support this vop pll sel\n"); 559 return -EINVAL; 560 } 561 } else { 562 printf("do not support this vop sel\n"); 563 return -EINVAL; 564 } 565 566 return DIV_TO_RATE(parent, div); 567 } 568 569 static ulong rk3308_vop_set_clk(struct clk *clk, ulong hz) 570 { 571 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 572 struct rk3308_cru *cru = priv->cru; 573 ulong pll_rate, now, best_rate = 0; 574 u32 i, div, best_div = 0, best_sel = 0; 575 576 for (i = 0; i <= DCLK_VOP_PLL_SEL_VPLL1; i++) { 577 switch (i) { 578 case DCLK_VOP_PLL_SEL_DPLL: 579 pll_rate = priv->dpll_hz; 580 break; 581 case DCLK_VOP_PLL_SEL_VPLL0: 582 pll_rate = priv->vpll0_hz; 583 break; 584 case DCLK_VOP_PLL_SEL_VPLL1: 585 pll_rate = priv->vpll1_hz; 586 break; 587 default: 588 printf("do not support this vop pll sel\n"); 589 return -EINVAL; 590 } 591 592 div = DIV_ROUND_UP(pll_rate, hz); 593 if (div > 255) 594 continue; 595 now = pll_rate / div; 596 if (abs(hz - now) < abs(hz - best_rate)) { 597 best_rate = now; 598 best_div = div; 599 best_sel = i; 600 } 601 debug("pll_rate=%lu, best_rate=%lu, best_div=%u, best_sel=%u\n", 602 pll_rate, best_rate, best_div, best_sel); 603 } 604 605 if (best_rate != hz && hz == OSC_HZ) { 606 rk_clrsetreg(&cru->clksel_con[8], 607 DCLK_VOP_SEL_MASK, 608 DCLK_VOP_SEL_24M << DCLK_VOP_SEL_SHIFT); 609 } else if (best_rate) { 610 rk_clrsetreg(&cru->clksel_con[8], 611 DCLK_VOP_SEL_MASK | DCLK_VOP_PLL_SEL_MASK | 612 DCLK_VOP_DIV_MASK, 613 DCLK_VOP_SEL_DIVOUT << DCLK_VOP_SEL_SHIFT | 614 best_sel << DCLK_VOP_PLL_SEL_SHIFT | 615 (best_div - 1) << DCLK_VOP_DIV_SHIFT); 616 } else { 617 printf("do not support this vop freq\n"); 618 return -EINVAL; 619 } 620 621 return rk3308_vop_get_clk(clk); 622 } 623 624 static ulong rk3308_bus_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) 625 { 626 struct rk3308_cru *cru = priv->cru; 627 u32 div, con, parent = priv->dpll_hz; 628 629 switch (clk_id) { 630 case ACLK_BUS: 631 con = readl(&cru->clksel_con[5]); 632 div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT; 633 break; 634 case HCLK_BUS: 635 con = readl(&cru->clksel_con[6]); 636 div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT; 637 break; 638 case PCLK_BUS: 639 con = readl(&cru->clksel_con[6]); 640 div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT; 641 break; 642 default: 643 return -ENOENT; 644 } 645 646 return DIV_TO_RATE(parent, div); 647 } 648 649 static ulong rk3308_bus_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, 650 ulong hz) 651 { 652 struct rk3308_cru *cru = priv->cru; 653 int src_clk_div; 654 655 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); 656 assert(src_clk_div - 1 < 31); 657 658 /* 659 * select dpll as pd_bus bus clock source and 660 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 661 */ 662 switch (clk_id) { 663 case ACLK_BUS: 664 rk_clrsetreg(&cru->clksel_con[5], 665 BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK, 666 BUS_PLL_SEL_DPLL << BUS_PLL_SEL_SHIFT | 667 (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT); 668 break; 669 case HCLK_BUS: 670 rk_clrsetreg(&cru->clksel_con[6], 671 BUS_HCLK_DIV_MASK, 672 (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT); 673 break; 674 case PCLK_BUS: 675 rk_clrsetreg(&cru->clksel_con[6], 676 BUS_PCLK_DIV_MASK, 677 (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT); 678 break; 679 default: 680 printf("do not support this bus freq\n"); 681 return -EINVAL; 682 } 683 684 return rk3308_bus_get_clk(priv, clk_id); 685 } 686 687 static ulong rk3308_peri_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) 688 { 689 struct rk3308_cru *cru = priv->cru; 690 u32 div, con, parent = priv->dpll_hz; 691 692 switch (clk_id) { 693 case ACLK_PERI: 694 con = readl(&cru->clksel_con[36]); 695 div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT; 696 break; 697 case HCLK_PERI: 698 con = readl(&cru->clksel_con[37]); 699 div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT; 700 break; 701 case PCLK_PERI: 702 con = readl(&cru->clksel_con[37]); 703 div = (con & PERI_PCLK_DIV_MASK) >> PERI_PCLK_DIV_SHIFT; 704 break; 705 default: 706 return -ENOENT; 707 } 708 709 return DIV_TO_RATE(parent, div); 710 } 711 712 static ulong rk3308_peri_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, 713 ulong hz) 714 { 715 struct rk3308_cru *cru = priv->cru; 716 int src_clk_div; 717 718 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); 719 assert(src_clk_div - 1 < 31); 720 721 /* 722 * select dpll as pd_peri bus clock source and 723 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 724 */ 725 switch (clk_id) { 726 case ACLK_PERI: 727 rk_clrsetreg(&cru->clksel_con[36], 728 PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK, 729 PERI_PLL_DPLL << PERI_PLL_SEL_SHIFT | 730 (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT); 731 break; 732 case HCLK_PERI: 733 rk_clrsetreg(&cru->clksel_con[37], 734 PERI_HCLK_DIV_MASK, 735 (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT); 736 break; 737 case PCLK_PERI: 738 rk_clrsetreg(&cru->clksel_con[37], 739 PERI_PCLK_DIV_MASK, 740 (src_clk_div - 1) << PERI_PCLK_DIV_SHIFT); 741 break; 742 default: 743 printf("do not support this peri freq\n"); 744 return -EINVAL; 745 } 746 747 return rk3308_peri_get_clk(priv, clk_id); 748 } 749 750 static ulong rk3308_audio_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) 751 { 752 struct rk3308_cru *cru = priv->cru; 753 u32 div, con, parent = priv->vpll0_hz; 754 755 switch (clk_id) { 756 case HCLK_AUDIO: 757 con = readl(&cru->clksel_con[45]); 758 div = (con & AUDIO_HCLK_DIV_MASK) >> AUDIO_HCLK_DIV_SHIFT; 759 break; 760 case PCLK_AUDIO: 761 con = readl(&cru->clksel_con[45]); 762 div = (con & AUDIO_PCLK_DIV_MASK) >> AUDIO_PCLK_DIV_SHIFT; 763 break; 764 default: 765 return -ENOENT; 766 } 767 768 return DIV_TO_RATE(parent, div); 769 } 770 771 static ulong rk3308_audio_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, 772 ulong hz) 773 { 774 struct rk3308_cru *cru = priv->cru; 775 int src_clk_div; 776 777 src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz); 778 assert(src_clk_div - 1 < 31); 779 780 /* 781 * select vpll0 as audio bus clock source and 782 * set up dependent divisors for HCLK and PCLK clocks. 783 */ 784 switch (clk_id) { 785 case HCLK_AUDIO: 786 rk_clrsetreg(&cru->clksel_con[45], 787 AUDIO_PLL_SEL_MASK | AUDIO_HCLK_DIV_MASK, 788 AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT | 789 (src_clk_div - 1) << AUDIO_HCLK_DIV_SHIFT); 790 break; 791 case PCLK_AUDIO: 792 rk_clrsetreg(&cru->clksel_con[45], 793 AUDIO_PLL_SEL_MASK | AUDIO_PCLK_DIV_MASK, 794 AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT | 795 (src_clk_div - 1) << AUDIO_PCLK_DIV_SHIFT); 796 break; 797 default: 798 printf("do not support this audio freq\n"); 799 return -EINVAL; 800 } 801 802 return rk3308_peri_get_clk(priv, clk_id); 803 } 804 805 static ulong rk3308_clk_get_rate(struct clk *clk) 806 { 807 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 808 ulong rate = 0; 809 810 rk3308_clk_get_pll_rate(priv); 811 812 debug("%s id:%ld\n", __func__, clk->id); 813 814 switch (clk->id) { 815 case PLL_APLL: 816 rate = rkclk_pll_get_rate(priv, APLL); 817 break; 818 case PLL_DPLL: 819 rate = rkclk_pll_get_rate(priv, DPLL); 820 break; 821 case PLL_VPLL0: 822 rate = rkclk_pll_get_rate(priv, VPLL0); 823 break; 824 case PLL_VPLL1: 825 rate = rkclk_pll_get_rate(priv, VPLL1); 826 break; 827 case HCLK_SDMMC: 828 case HCLK_EMMC: 829 case SCLK_SDMMC: 830 case SCLK_EMMC: 831 case SCLK_EMMC_SAMPLE: 832 rate = rk3308_mmc_get_clk(clk); 833 break; 834 case SCLK_I2C0: 835 case SCLK_I2C1: 836 case SCLK_I2C2: 837 case SCLK_I2C3: 838 rate = rk3308_i2c_get_clk(clk); 839 break; 840 case SCLK_SARADC: 841 rate = rk3308_saradc_get_clk(clk); 842 break; 843 case SCLK_SPI0: 844 case SCLK_SPI1: 845 rate = rk3308_spi_get_clk(clk); 846 break; 847 case SCLK_PWM: 848 rate = rk3308_pwm_get_clk(clk); 849 break; 850 case DCLK_VOP: 851 rate = rk3308_vop_get_clk(clk); 852 break; 853 case ACLK_BUS: 854 case HCLK_BUS: 855 case PCLK_BUS: 856 rate = rk3308_bus_get_clk(priv, clk->id); 857 break; 858 case ACLK_PERI: 859 case HCLK_PERI: 860 case PCLK_PERI: 861 rate = rk3308_peri_get_clk(priv, clk->id); 862 break; 863 case HCLK_AUDIO: 864 case PCLK_AUDIO: 865 rate = rk3308_audio_get_clk(priv, clk->id); 866 break; 867 default: 868 return -ENOENT; 869 } 870 871 return rate; 872 } 873 874 static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate) 875 { 876 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 877 ulong ret = 0; 878 879 rk3308_clk_get_pll_rate(priv); 880 881 debug("%s %ld %ld\n", __func__, clk->id, rate); 882 883 switch (clk->id) { 884 case PLL_DPLL: 885 ret = rkclk_set_pll(priv, DPLL, rate); 886 priv->dpll_hz = rkclk_pll_get_rate(priv, DPLL); 887 break; 888 case HCLK_SDMMC: 889 case HCLK_EMMC: 890 case SCLK_SDMMC: 891 case SCLK_EMMC: 892 ret = rk3308_mmc_set_clk(clk, rate); 893 break; 894 case SCLK_I2C0: 895 case SCLK_I2C1: 896 case SCLK_I2C2: 897 case SCLK_I2C3: 898 ret = rk3308_i2c_set_clk(clk, rate); 899 break; 900 case SCLK_SARADC: 901 ret = rk3308_saradc_set_clk(clk, rate); 902 break; 903 case SCLK_SPI0: 904 case SCLK_SPI1: 905 ret = rk3308_spi_set_clk(clk, rate); 906 break; 907 case SCLK_PWM: 908 ret = rk3308_pwm_set_clk(clk, rate); 909 break; 910 case DCLK_VOP: 911 ret = rk3308_vop_set_clk(clk, rate); 912 break; 913 case ACLK_BUS: 914 case HCLK_BUS: 915 case PCLK_BUS: 916 rate = rk3308_bus_set_clk(priv, clk->id, rate); 917 break; 918 case ACLK_PERI: 919 case HCLK_PERI: 920 case PCLK_PERI: 921 rate = rk3308_peri_set_clk(priv, clk->id, rate); 922 break; 923 case HCLK_AUDIO: 924 case PCLK_AUDIO: 925 rate = rk3308_audio_set_clk(priv, clk->id, rate); 926 break; 927 default: 928 return -ENOENT; 929 } 930 931 return ret; 932 } 933 934 #define ROCKCHIP_MMC_DELAY_SEL BIT(11) 935 #define ROCKCHIP_MMC_DEGREE_OFFSET 1 936 #define ROCKCHIP_MMC_DEGREE_MASK (0x3 << ROCKCHIP_MMC_DEGREE_OFFSET) 937 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 3 938 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 939 940 #define PSECS_PER_SEC 1000000000000LL 941 /* 942 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 943 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 944 */ 945 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 946 947 int rockchip_mmc_get_phase(struct clk *clk) 948 { 949 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 950 struct rk3308_cru *cru = priv->cru; 951 u32 raw_value, delay_num; 952 u16 degrees = 0; 953 ulong rate; 954 955 rate = rk3308_clk_get_rate(clk); 956 957 if (rate < 0) 958 return rate; 959 960 if (clk->id == SCLK_EMMC_SAMPLE) 961 raw_value = readl(&cru->emmc_con[1]); 962 else 963 raw_value = readl(&cru->sdmmc_con[1]); 964 965 raw_value &= ROCKCHIP_MMC_DEGREE_MASK; 966 degrees = (raw_value >> ROCKCHIP_MMC_DEGREE_OFFSET) * 90; 967 968 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 969 /* degrees/delaynum * 10000 */ 970 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 971 36 * (rate / 1000000); 972 973 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 974 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 975 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 976 } 977 978 return degrees % 360; 979 980 } 981 982 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees) 983 { 984 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 985 struct rk3308_cru *cru = priv->cru; 986 u8 nineties, remainder, delay_num; 987 u32 raw_value, delay; 988 ulong rate; 989 990 rate = rk3308_clk_get_rate(clk); 991 992 if (rate < 0) 993 return rate; 994 995 nineties = degrees / 90; 996 remainder = (degrees % 90); 997 998 /* 999 * Convert to delay; do a little extra work to make sure we 1000 * don't overflow 32-bit / 64-bit numbers. 1001 */ 1002 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 1003 delay *= remainder; 1004 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 1005 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 1006 1007 delay_num = (u8)min_t(u32, delay, 255); 1008 1009 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 1010 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 1011 raw_value |= nineties << ROCKCHIP_MMC_DEGREE_OFFSET; 1012 1013 if (clk->id == SCLK_EMMC_SAMPLE) 1014 writel(raw_value | 0xffff0000, &cru->emmc_con[1]); 1015 else 1016 writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]); 1017 1018 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 1019 degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk)); 1020 1021 return 0; 1022 1023 } 1024 1025 static int rk3308_clk_get_phase(struct clk *clk) 1026 { 1027 int ret; 1028 1029 switch (clk->id) { 1030 case SCLK_EMMC_SAMPLE: 1031 case SCLK_SDMMC_SAMPLE: 1032 ret = rockchip_mmc_get_phase(clk); 1033 break; 1034 default: 1035 return -ENOENT; 1036 } 1037 1038 return ret; 1039 } 1040 1041 static int rk3308_clk_set_phase(struct clk *clk, int degrees) 1042 { 1043 int ret; 1044 1045 switch (clk->id) { 1046 case SCLK_EMMC_SAMPLE: 1047 case SCLK_SDMMC_SAMPLE: 1048 ret = rockchip_mmc_set_phase(clk, degrees); 1049 break; 1050 default: 1051 return -ENOENT; 1052 } 1053 1054 return ret; 1055 } 1056 1057 static struct clk_ops rk3308_clk_ops = { 1058 .get_rate = rk3308_clk_get_rate, 1059 .set_rate = rk3308_clk_set_rate, 1060 .get_phase = rk3308_clk_get_phase, 1061 .set_phase = rk3308_clk_set_phase, 1062 }; 1063 1064 static int rk3308_clk_probe(struct udevice *dev) 1065 { 1066 rkclk_init(dev); 1067 1068 return 0; 1069 } 1070 1071 static int rk3308_clk_ofdata_to_platdata(struct udevice *dev) 1072 { 1073 struct rk3308_clk_priv *priv = dev_get_priv(dev); 1074 1075 priv->cru = dev_read_addr_ptr(dev); 1076 1077 return 0; 1078 } 1079 1080 static int rk3308_clk_bind(struct udevice *dev) 1081 { 1082 int ret; 1083 struct udevice *sys_child, *sf_child; 1084 struct sysreset_reg *priv; 1085 struct softreset_reg *sf_priv; 1086 1087 /* The reset driver does not have a device node, so bind it here */ 1088 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 1089 &sys_child); 1090 if (ret) { 1091 debug("Warning: No sysreset driver: ret=%d\n", ret); 1092 } else { 1093 priv = malloc(sizeof(struct sysreset_reg)); 1094 priv->glb_srst_fst_value = offsetof(struct rk3308_cru, 1095 glb_srst_fst); 1096 priv->glb_srst_snd_value = offsetof(struct rk3308_cru, 1097 glb_srst_snd); 1098 sys_child->priv = priv; 1099 } 1100 1101 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 1102 dev_ofnode(dev), &sf_child); 1103 if (ret) { 1104 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 1105 } else { 1106 sf_priv = malloc(sizeof(struct softreset_reg)); 1107 sf_priv->sf_reset_offset = offsetof(struct rk3308_cru, 1108 softrst_con[0]); 1109 sf_priv->sf_reset_num = 12; 1110 sf_child->priv = sf_priv; 1111 } 1112 1113 return 0; 1114 } 1115 1116 static const struct udevice_id rk3308_clk_ids[] = { 1117 { .compatible = "rockchip,rk3308-cru" }, 1118 { } 1119 }; 1120 1121 U_BOOT_DRIVER(rockchip_rk3308_cru) = { 1122 .name = "rockchip_rk3308_cru", 1123 .id = UCLASS_CLK, 1124 .of_match = rk3308_clk_ids, 1125 .priv_auto_alloc_size = sizeof(struct rk3308_clk_priv), 1126 .ofdata_to_platdata = rk3308_clk_ofdata_to_platdata, 1127 .ops = &rk3308_clk_ops, 1128 .bind = rk3308_clk_bind, 1129 .probe = rk3308_clk_probe, 1130 }; 1131 1132 /** 1133 * soc_clk_dump() - Print clock frequencies 1134 * Returns zero on success 1135 * 1136 * Implementation for the clk dump command. 1137 */ 1138 int soc_clk_dump(void) 1139 { 1140 struct udevice *cru_dev; 1141 const struct rk3308_clk_info *clk_dump; 1142 struct clk clk; 1143 unsigned long clk_count = ARRAY_SIZE(clks_dump); 1144 unsigned long rate; 1145 int i, ret; 1146 1147 ret = uclass_get_device_by_driver(UCLASS_CLK, 1148 DM_GET_DRIVER(rockchip_rk3308_cru), 1149 &cru_dev); 1150 if (ret) { 1151 printf("%s failed to get cru device\n", __func__); 1152 return ret; 1153 } 1154 1155 printf("CLK:"); 1156 for (i = 0; i < clk_count; i++) { 1157 clk_dump = &clks_dump[i]; 1158 if (clk_dump->name) { 1159 clk.id = clk_dump->id; 1160 ret = clk_request(cru_dev, &clk); 1161 if (ret < 0) 1162 return ret; 1163 1164 rate = clk_get_rate(&clk); 1165 clk_free(&clk); 1166 if (i == 0) { 1167 if (rate < 0) 1168 printf("%10s%20s\n", clk_dump->name, 1169 "unknown"); 1170 else 1171 printf("%10s%20lu Hz\n", clk_dump->name, 1172 rate); 1173 } else { 1174 if (rate < 0) 1175 printf("%14s%20s\n", clk_dump->name, 1176 "unknown"); 1177 else 1178 printf("%14s%20lu Hz\n", clk_dump->name, 1179 rate); 1180 } 1181 } 1182 } 1183 1184 return 0; 1185 } 1186