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, "gpll"), 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 rkclk_init(struct udevice *dev) 228 { 229 struct rk3308_clk_priv *priv = dev_get_priv(dev); 230 struct rk3308_cru *cru = priv->cru; 231 u32 aclk_div, pclk_div; 232 233 /* init pll */ 234 if (rkclk_set_pll(priv, APLL, APLL_HZ)) 235 printf("%s set apll unsuccessfully\n", __func__); 236 237 /* 238 * select apll as cpu/core clock pll source and 239 * set up dependent divisors for PCLK and ACLK clocks. 240 * core hz : apll = 1:1 241 */ 242 priv->apll_hz = rkclk_pll_get_rate(priv, APLL); 243 aclk_div = priv->apll_hz / CORE_ACLK_HZ - 1; 244 pclk_div = priv->apll_hz / CORE_DBG_HZ - 1; 245 rk_clrsetreg(&cru->clksel_con[0], 246 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK | 247 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK, 248 aclk_div << CORE_ACLK_DIV_SHIFT | 249 pclk_div << CORE_DBG_DIV_SHIFT | 250 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 251 0 << CORE_DIV_CON_SHIFT); 252 253 priv->dpll_hz = rkclk_pll_get_rate(priv, DPLL); 254 priv->vpll0_hz = rkclk_pll_get_rate(priv, VPLL0); 255 priv->vpll1_hz = rkclk_pll_get_rate(priv, VPLL1); 256 257 rk3308_bus_set_clk(priv, ACLK_BUS, BUS_ACLK_HZ); 258 rk3308_bus_set_clk(priv, HCLK_BUS, BUS_HCLK_HZ); 259 rk3308_bus_set_clk(priv, PCLK_BUS, BUS_PCLK_HZ); 260 261 rk3308_peri_set_clk(priv, ACLK_PERI, PERI_ACLK_HZ); 262 rk3308_peri_set_clk(priv, HCLK_PERI, PERI_HCLK_HZ); 263 rk3308_peri_set_clk(priv, PCLK_PERI, PERI_PCLK_HZ); 264 265 rk3308_audio_set_clk(priv, HCLK_AUDIO, AUDIO_HCLK_HZ); 266 rk3308_audio_set_clk(priv, PCLK_AUDIO, AUDIO_PCLK_HZ); 267 } 268 269 static ulong rk3308_i2c_get_clk(struct clk *clk) 270 { 271 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 272 struct rk3308_cru *cru = priv->cru; 273 u32 div, con, con_id; 274 275 switch (clk->id) { 276 case SCLK_I2C0: 277 con_id = 25; 278 break; 279 case SCLK_I2C1: 280 con_id = 26; 281 break; 282 case SCLK_I2C2: 283 con_id = 27; 284 break; 285 case SCLK_I2C3: 286 con_id = 28; 287 break; 288 default: 289 printf("do not support this i2c bus\n"); 290 return -EINVAL; 291 } 292 293 con = readl(&cru->clksel_con[con_id]); 294 div = con >> CLK_I2C_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 295 296 return DIV_TO_RATE(priv->dpll_hz, div); 297 } 298 299 static ulong rk3308_i2c_set_clk(struct clk *clk, uint hz) 300 { 301 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 302 struct rk3308_cru *cru = priv->cru; 303 u32 src_clk_div, con_id; 304 305 src_clk_div = priv->dpll_hz / hz; 306 assert(src_clk_div - 1 < 127); 307 308 switch (clk->id) { 309 case SCLK_I2C0: 310 con_id = 25; 311 break; 312 case SCLK_I2C1: 313 con_id = 26; 314 break; 315 case SCLK_I2C2: 316 con_id = 27; 317 break; 318 case SCLK_I2C3: 319 con_id = 28; 320 break; 321 default: 322 printf("do not support this i2c bus\n"); 323 return -EINVAL; 324 } 325 rk_clrsetreg(&cru->clksel_con[con_id], 326 CLK_I2C_PLL_SEL_MASK | CLK_I2C_DIV_CON_MASK, 327 CLK_I2C_PLL_SEL_DPLL << CLK_I2C_PLL_SEL_SHIFT | 328 (src_clk_div - 1) << CLK_I2C_DIV_CON_SHIFT); 329 330 return rk3308_i2c_get_clk(clk); 331 } 332 333 static ulong rk3308_mmc_get_clk(struct clk *clk) 334 { 335 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 336 struct rk3308_cru *cru = priv->cru; 337 u32 div, con, con_id; 338 339 switch (clk->id) { 340 case HCLK_SDMMC: 341 case SCLK_SDMMC: 342 con_id = 39; 343 break; 344 case HCLK_EMMC: 345 case SCLK_EMMC: 346 case SCLK_EMMC_SAMPLE: 347 con_id = 41; 348 break; 349 default: 350 return -EINVAL; 351 } 352 353 con = readl(&cru->clksel_con[con_id]); 354 div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT; 355 356 if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT 357 == EMMC_SEL_24M) 358 return DIV_TO_RATE(OSC_HZ, div) / 2; 359 else 360 return DIV_TO_RATE(priv->vpll0_hz, div) / 2; 361 } 362 363 static ulong rk3308_mmc_set_clk(struct clk *clk, ulong set_rate) 364 { 365 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 366 struct rk3308_cru *cru = priv->cru; 367 int src_clk_div; 368 u32 con_id; 369 370 debug("%s %ld %ld\n", __func__, clk->id, set_rate); 371 372 switch (clk->id) { 373 case HCLK_SDMMC: 374 case SCLK_SDMMC: 375 con_id = 39; 376 break; 377 case HCLK_EMMC: 378 case SCLK_EMMC: 379 con_id = 41; 380 break; 381 default: 382 return -EINVAL; 383 } 384 /* Select clk_sdmmc/emmc source from VPLL0 by default */ 385 /* mmc clock defaulg div 2 internal, need provide double in cru */ 386 src_clk_div = DIV_ROUND_UP(priv->vpll0_hz / 2, set_rate); 387 388 if (src_clk_div > 127) { 389 /* use 24MHz source for 400KHz clock */ 390 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate); 391 rk_clrsetreg(&cru->clksel_con[con_id], 392 EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK, 393 EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT | 394 EMMC_SEL_24M << EMMC_PLL_SHIFT | 395 (src_clk_div - 1) << EMMC_DIV_SHIFT); 396 } else { 397 rk_clrsetreg(&cru->clksel_con[con_id], 398 EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK, 399 EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT | 400 EMMC_SEL_VPLL0 << EMMC_PLL_SHIFT | 401 (src_clk_div - 1) << EMMC_DIV_SHIFT); 402 } 403 404 return rk3308_mmc_get_clk(clk); 405 } 406 407 static ulong rk3308_saradc_get_clk(struct clk *clk) 408 { 409 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 410 struct rk3308_cru *cru = priv->cru; 411 u32 div, con; 412 413 con = readl(&cru->clksel_con[34]); 414 div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK; 415 416 return DIV_TO_RATE(OSC_HZ, div); 417 } 418 419 static ulong rk3308_saradc_set_clk(struct clk *clk, uint hz) 420 { 421 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 422 struct rk3308_cru *cru = priv->cru; 423 int src_clk_div; 424 425 src_clk_div = OSC_HZ / hz; 426 assert(src_clk_div - 1 < 2047); 427 428 rk_clrsetreg(&cru->clksel_con[34], 429 CLK_SARADC_DIV_CON_MASK, 430 (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT); 431 432 return rk3308_saradc_get_clk(clk); 433 } 434 435 static ulong rk3308_spi_get_clk(struct clk *clk) 436 { 437 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 438 struct rk3308_cru *cru = priv->cru; 439 u32 div, con, con_id; 440 441 switch (clk->id) { 442 case SCLK_SPI0: 443 con_id = 30; 444 break; 445 case SCLK_SPI1: 446 con_id = 31; 447 break; 448 case SCLK_SPI2: 449 con_id = 32; 450 break; 451 default: 452 printf("do not support this spi bus\n"); 453 return -EINVAL; 454 } 455 456 con = readl(&cru->clksel_con[con_id]); 457 div = con >> CLK_SPI_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK; 458 459 return DIV_TO_RATE(priv->dpll_hz, div); 460 } 461 462 static ulong rk3308_spi_set_clk(struct clk *clk, uint hz) 463 { 464 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 465 struct rk3308_cru *cru = priv->cru; 466 u32 src_clk_div, con_id; 467 468 src_clk_div = priv->dpll_hz / hz; 469 assert(src_clk_div - 1 < 127); 470 471 switch (clk->id) { 472 case SCLK_SPI0: 473 con_id = 30; 474 break; 475 case SCLK_SPI1: 476 con_id = 31; 477 break; 478 case SCLK_SPI2: 479 con_id = 32; 480 break; 481 default: 482 printf("do not support this spi bus\n"); 483 return -EINVAL; 484 } 485 486 rk_clrsetreg(&cru->clksel_con[con_id], 487 CLK_SPI_PLL_SEL_MASK | CLK_SPI_DIV_CON_MASK, 488 CLK_SPI_PLL_SEL_DPLL << CLK_SPI_PLL_SEL_SHIFT | 489 (src_clk_div - 1) << CLK_SPI_DIV_CON_SHIFT); 490 491 return rk3308_spi_get_clk(clk); 492 } 493 494 static ulong rk3308_pwm_get_clk(struct clk *clk) 495 { 496 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 497 struct rk3308_cru *cru = priv->cru; 498 u32 div, con; 499 500 con = readl(&cru->clksel_con[29]); 501 div = con >> CLK_PWM_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK; 502 503 return DIV_TO_RATE(priv->dpll_hz, div); 504 } 505 506 static ulong rk3308_pwm_set_clk(struct clk *clk, uint hz) 507 { 508 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 509 struct rk3308_cru *cru = priv->cru; 510 int src_clk_div; 511 512 src_clk_div = priv->dpll_hz / hz; 513 assert(src_clk_div - 1 < 127); 514 515 rk_clrsetreg(&cru->clksel_con[29], 516 CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK, 517 CLK_PWM_PLL_SEL_DPLL << CLK_PWM_PLL_SEL_SHIFT | 518 (src_clk_div - 1) << CLK_PWM_DIV_CON_SHIFT); 519 520 return rk3308_pwm_get_clk(clk); 521 } 522 523 static ulong rk3308_vop_get_clk(struct clk *clk) 524 { 525 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 526 struct rk3308_cru *cru = priv->cru; 527 u32 div, pll_sel, vol_sel, con, parent; 528 529 con = readl(&cru->clksel_con[8]); 530 vol_sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT; 531 pll_sel = (con & DCLK_VOP_PLL_SEL_MASK) >> DCLK_VOP_PLL_SEL_SHIFT; 532 div = con & DCLK_VOP_DIV_MASK; 533 534 if (vol_sel == DCLK_VOP_SEL_24M) { 535 parent = OSC_HZ; 536 } else if (vol_sel == DCLK_VOP_SEL_DIVOUT) { 537 switch (pll_sel) { 538 case DCLK_VOP_PLL_SEL_DPLL: 539 parent = rkclk_pll_get_rate(priv, DPLL); 540 break; 541 case DCLK_VOP_PLL_SEL_VPLL0: 542 parent = rkclk_pll_get_rate(priv, VPLL0); 543 break; 544 case DCLK_VOP_PLL_SEL_VPLL1: 545 parent = rkclk_pll_get_rate(priv, VPLL1); 546 break; 547 default: 548 printf("do not support this vop pll sel\n"); 549 return -EINVAL; 550 } 551 } else { 552 printf("do not support this vop sel\n"); 553 return -EINVAL; 554 } 555 556 return DIV_TO_RATE(parent, div); 557 } 558 559 static ulong rk3308_vop_set_clk(struct clk *clk, ulong hz) 560 { 561 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 562 struct rk3308_cru *cru = priv->cru; 563 ulong pll_rate, now, best_rate = 0; 564 u32 i, div, best_div = 0, best_sel = 0; 565 566 for (i = 0; i <= DCLK_VOP_PLL_SEL_VPLL1; i++) { 567 switch (i) { 568 case DCLK_VOP_PLL_SEL_DPLL: 569 pll_rate = priv->dpll_hz; 570 break; 571 case DCLK_VOP_PLL_SEL_VPLL0: 572 pll_rate = priv->vpll0_hz; 573 break; 574 case DCLK_VOP_PLL_SEL_VPLL1: 575 pll_rate = priv->vpll1_hz; 576 break; 577 default: 578 printf("do not support this vop pll sel\n"); 579 return -EINVAL; 580 } 581 582 div = DIV_ROUND_UP(pll_rate, hz); 583 if (div > 255) 584 continue; 585 now = pll_rate / div; 586 if (abs(hz - now) < abs(hz - best_rate)) { 587 best_rate = now; 588 best_div = div; 589 best_sel = i; 590 } 591 debug("pll_rate=%lu, best_rate=%lu, best_div=%u, best_sel=%u\n", 592 pll_rate, best_rate, best_div, best_sel); 593 } 594 595 if (best_rate != hz && hz == OSC_HZ) { 596 rk_clrsetreg(&cru->clksel_con[8], 597 DCLK_VOP_SEL_MASK, 598 DCLK_VOP_SEL_24M << DCLK_VOP_SEL_SHIFT); 599 } else if (best_rate) { 600 rk_clrsetreg(&cru->clksel_con[8], 601 DCLK_VOP_SEL_MASK | DCLK_VOP_PLL_SEL_MASK | 602 DCLK_VOP_DIV_MASK, 603 DCLK_VOP_SEL_DIVOUT << DCLK_VOP_SEL_SHIFT | 604 best_sel << DCLK_VOP_PLL_SEL_SHIFT | 605 (best_div - 1) << DCLK_VOP_DIV_SHIFT); 606 } else { 607 printf("do not support this vop freq\n"); 608 return -EINVAL; 609 } 610 611 return rk3308_vop_get_clk(clk); 612 } 613 614 static ulong rk3308_bus_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) 615 { 616 struct rk3308_cru *cru = priv->cru; 617 u32 div, con, parent = priv->dpll_hz; 618 619 switch (clk_id) { 620 case ACLK_BUS: 621 con = readl(&cru->clksel_con[5]); 622 div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT; 623 break; 624 case HCLK_BUS: 625 con = readl(&cru->clksel_con[6]); 626 div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT; 627 break; 628 case PCLK_BUS: 629 con = readl(&cru->clksel_con[6]); 630 div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT; 631 break; 632 default: 633 return -ENOENT; 634 } 635 636 return DIV_TO_RATE(parent, div); 637 } 638 639 static ulong rk3308_bus_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, 640 ulong hz) 641 { 642 struct rk3308_cru *cru = priv->cru; 643 int src_clk_div; 644 645 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); 646 assert(src_clk_div - 1 < 31); 647 648 /* 649 * select dpll as pd_bus bus clock source and 650 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 651 */ 652 switch (clk_id) { 653 case ACLK_BUS: 654 rk_clrsetreg(&cru->clksel_con[5], 655 BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK, 656 BUS_PLL_SEL_DPLL << BUS_PLL_SEL_SHIFT | 657 (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT); 658 break; 659 case HCLK_BUS: 660 rk_clrsetreg(&cru->clksel_con[6], 661 BUS_HCLK_DIV_MASK, 662 (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT); 663 break; 664 case PCLK_BUS: 665 rk_clrsetreg(&cru->clksel_con[6], 666 BUS_PCLK_DIV_MASK, 667 (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT); 668 break; 669 default: 670 printf("do not support this bus freq\n"); 671 return -EINVAL; 672 } 673 674 return rk3308_bus_get_clk(priv, clk_id); 675 } 676 677 static ulong rk3308_peri_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) 678 { 679 struct rk3308_cru *cru = priv->cru; 680 u32 div, con, parent = priv->dpll_hz; 681 682 switch (clk_id) { 683 case ACLK_PERI: 684 con = readl(&cru->clksel_con[36]); 685 div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT; 686 break; 687 case HCLK_PERI: 688 con = readl(&cru->clksel_con[37]); 689 div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT; 690 break; 691 case PCLK_PERI: 692 con = readl(&cru->clksel_con[37]); 693 div = (con & PERI_PCLK_DIV_MASK) >> PERI_PCLK_DIV_SHIFT; 694 break; 695 default: 696 return -ENOENT; 697 } 698 699 return DIV_TO_RATE(parent, div); 700 } 701 702 static ulong rk3308_peri_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, 703 ulong hz) 704 { 705 struct rk3308_cru *cru = priv->cru; 706 int src_clk_div; 707 708 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); 709 assert(src_clk_div - 1 < 31); 710 711 /* 712 * select dpll as pd_peri bus clock source and 713 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 714 */ 715 switch (clk_id) { 716 case ACLK_PERI: 717 rk_clrsetreg(&cru->clksel_con[36], 718 PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK, 719 PERI_PLL_DPLL << PERI_PLL_SEL_SHIFT | 720 (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT); 721 break; 722 case HCLK_PERI: 723 rk_clrsetreg(&cru->clksel_con[37], 724 PERI_HCLK_DIV_MASK, 725 (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT); 726 break; 727 case PCLK_PERI: 728 rk_clrsetreg(&cru->clksel_con[37], 729 PERI_PCLK_DIV_MASK, 730 (src_clk_div - 1) << PERI_PCLK_DIV_SHIFT); 731 break; 732 default: 733 printf("do not support this peri freq\n"); 734 return -EINVAL; 735 } 736 737 return rk3308_peri_get_clk(priv, clk_id); 738 } 739 740 static ulong rk3308_audio_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) 741 { 742 struct rk3308_cru *cru = priv->cru; 743 u32 div, con, parent = priv->vpll0_hz; 744 745 switch (clk_id) { 746 case HCLK_AUDIO: 747 con = readl(&cru->clksel_con[45]); 748 div = (con & AUDIO_HCLK_DIV_MASK) >> AUDIO_HCLK_DIV_SHIFT; 749 break; 750 case PCLK_AUDIO: 751 con = readl(&cru->clksel_con[45]); 752 div = (con & AUDIO_PCLK_DIV_MASK) >> AUDIO_PCLK_DIV_SHIFT; 753 break; 754 default: 755 return -ENOENT; 756 } 757 758 return DIV_TO_RATE(parent, div); 759 } 760 761 static ulong rk3308_audio_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, 762 ulong hz) 763 { 764 struct rk3308_cru *cru = priv->cru; 765 int src_clk_div; 766 767 src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz); 768 assert(src_clk_div - 1 < 31); 769 770 /* 771 * select vpll0 as audio bus clock source and 772 * set up dependent divisors for HCLK and PCLK clocks. 773 */ 774 switch (clk_id) { 775 case HCLK_AUDIO: 776 rk_clrsetreg(&cru->clksel_con[45], 777 AUDIO_PLL_SEL_MASK | AUDIO_HCLK_DIV_MASK, 778 AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT | 779 (src_clk_div - 1) << AUDIO_HCLK_DIV_SHIFT); 780 break; 781 case PCLK_AUDIO: 782 rk_clrsetreg(&cru->clksel_con[45], 783 AUDIO_PLL_SEL_MASK | AUDIO_PCLK_DIV_MASK, 784 AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT | 785 (src_clk_div - 1) << AUDIO_PCLK_DIV_SHIFT); 786 break; 787 default: 788 printf("do not support this audio freq\n"); 789 return -EINVAL; 790 } 791 792 return rk3308_peri_get_clk(priv, clk_id); 793 } 794 795 static ulong rk3308_clk_get_rate(struct clk *clk) 796 { 797 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 798 ulong rate = 0; 799 800 debug("%s id:%ld\n", __func__, clk->id); 801 802 switch (clk->id) { 803 case PLL_APLL: 804 rate = rkclk_pll_get_rate(priv, APLL); 805 break; 806 case PLL_DPLL: 807 rate = rkclk_pll_get_rate(priv, DPLL); 808 break; 809 case PLL_VPLL0: 810 rate = rkclk_pll_get_rate(priv, VPLL0); 811 break; 812 case PLL_VPLL1: 813 rate = rkclk_pll_get_rate(priv, VPLL1); 814 break; 815 case HCLK_SDMMC: 816 case HCLK_EMMC: 817 case SCLK_SDMMC: 818 case SCLK_EMMC: 819 case SCLK_EMMC_SAMPLE: 820 rate = rk3308_mmc_get_clk(clk); 821 break; 822 case SCLK_I2C0: 823 case SCLK_I2C1: 824 case SCLK_I2C2: 825 case SCLK_I2C3: 826 rate = rk3308_i2c_get_clk(clk); 827 break; 828 case SCLK_SARADC: 829 rate = rk3308_saradc_get_clk(clk); 830 break; 831 case SCLK_SPI0: 832 case SCLK_SPI1: 833 rate = rk3308_spi_get_clk(clk); 834 break; 835 case SCLK_PWM: 836 rate = rk3308_pwm_get_clk(clk); 837 break; 838 case DCLK_VOP: 839 rate = rk3308_vop_get_clk(clk); 840 break; 841 case ACLK_BUS: 842 case HCLK_BUS: 843 case PCLK_BUS: 844 rate = rk3308_bus_get_clk(priv, clk->id); 845 break; 846 case ACLK_PERI: 847 case HCLK_PERI: 848 case PCLK_PERI: 849 rate = rk3308_peri_get_clk(priv, clk->id); 850 break; 851 case HCLK_AUDIO: 852 case PCLK_AUDIO: 853 rate = rk3308_audio_get_clk(priv, clk->id); 854 break; 855 default: 856 return -ENOENT; 857 } 858 859 return rate; 860 } 861 862 static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate) 863 { 864 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 865 ulong ret = 0; 866 867 debug("%s %ld %ld\n", __func__, clk->id, rate); 868 869 switch (clk->id) { 870 case PLL_DPLL: 871 ret = rkclk_set_pll(priv, DPLL, rate); 872 break; 873 case HCLK_SDMMC: 874 case HCLK_EMMC: 875 case SCLK_SDMMC: 876 case SCLK_EMMC: 877 ret = rk3308_mmc_set_clk(clk, rate); 878 break; 879 case SCLK_I2C0: 880 case SCLK_I2C1: 881 case SCLK_I2C2: 882 case SCLK_I2C3: 883 ret = rk3308_i2c_set_clk(clk, rate); 884 break; 885 case SCLK_SARADC: 886 ret = rk3308_saradc_set_clk(clk, rate); 887 break; 888 case SCLK_SPI0: 889 case SCLK_SPI1: 890 ret = rk3308_spi_set_clk(clk, rate); 891 break; 892 case SCLK_PWM: 893 ret = rk3308_pwm_set_clk(clk, rate); 894 break; 895 case DCLK_VOP: 896 ret = rk3308_vop_set_clk(clk, rate); 897 break; 898 case ACLK_BUS: 899 case HCLK_BUS: 900 case PCLK_BUS: 901 rate = rk3308_bus_set_clk(priv, clk->id, rate); 902 break; 903 case ACLK_PERI: 904 case HCLK_PERI: 905 case PCLK_PERI: 906 rate = rk3308_peri_set_clk(priv, clk->id, rate); 907 break; 908 case HCLK_AUDIO: 909 case PCLK_AUDIO: 910 rate = rk3308_audio_set_clk(priv, clk->id, rate); 911 break; 912 default: 913 return -ENOENT; 914 } 915 916 return ret; 917 } 918 919 #define ROCKCHIP_MMC_DELAY_SEL BIT(11) 920 #define ROCKCHIP_MMC_DEGREE_OFFSET 1 921 #define ROCKCHIP_MMC_DEGREE_MASK (0x3 << ROCKCHIP_MMC_DEGREE_OFFSET) 922 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 3 923 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 924 925 #define PSECS_PER_SEC 1000000000000LL 926 /* 927 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 928 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 929 */ 930 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 931 932 int rockchip_mmc_get_phase(struct clk *clk) 933 { 934 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 935 struct rk3308_cru *cru = priv->cru; 936 u32 raw_value, delay_num; 937 u16 degrees = 0; 938 ulong rate; 939 940 rate = rk3308_clk_get_rate(clk); 941 942 if (rate < 0) 943 return rate; 944 945 if (clk->id == SCLK_EMMC_SAMPLE) 946 raw_value = readl(&cru->emmc_con[1]); 947 else 948 raw_value = readl(&cru->sdmmc_con[1]); 949 950 raw_value &= ROCKCHIP_MMC_DEGREE_MASK; 951 degrees = (raw_value >> ROCKCHIP_MMC_DEGREE_OFFSET) * 90; 952 953 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 954 /* degrees/delaynum * 10000 */ 955 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 956 36 * (rate / 1000000); 957 958 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 959 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 960 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 961 } 962 963 return degrees % 360; 964 965 } 966 967 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees) 968 { 969 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 970 struct rk3308_cru *cru = priv->cru; 971 u8 nineties, remainder, delay_num; 972 u32 raw_value, delay; 973 ulong rate; 974 975 rate = rk3308_clk_get_rate(clk); 976 977 if (rate < 0) 978 return rate; 979 980 nineties = degrees / 90; 981 remainder = (degrees % 90); 982 983 /* 984 * Convert to delay; do a little extra work to make sure we 985 * don't overflow 32-bit / 64-bit numbers. 986 */ 987 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 988 delay *= remainder; 989 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 990 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 991 992 delay_num = (u8)min_t(u32, delay, 255); 993 994 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 995 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 996 raw_value |= nineties << ROCKCHIP_MMC_DEGREE_OFFSET; 997 998 if (clk->id == SCLK_EMMC_SAMPLE) 999 writel(raw_value | 0xffff0000, &cru->emmc_con[1]); 1000 else 1001 writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]); 1002 1003 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 1004 degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk)); 1005 1006 return 0; 1007 1008 } 1009 1010 static int rk3308_clk_get_phase(struct clk *clk) 1011 { 1012 int ret; 1013 1014 switch (clk->id) { 1015 case SCLK_EMMC_SAMPLE: 1016 case SCLK_SDMMC_SAMPLE: 1017 ret = rockchip_mmc_get_phase(clk); 1018 break; 1019 default: 1020 return -ENOENT; 1021 } 1022 1023 return ret; 1024 } 1025 1026 static int rk3308_clk_set_phase(struct clk *clk, int degrees) 1027 { 1028 int ret; 1029 1030 switch (clk->id) { 1031 case SCLK_EMMC_SAMPLE: 1032 case SCLK_SDMMC_SAMPLE: 1033 ret = rockchip_mmc_set_phase(clk, degrees); 1034 break; 1035 default: 1036 return -ENOENT; 1037 } 1038 1039 return ret; 1040 } 1041 1042 static struct clk_ops rk3308_clk_ops = { 1043 .get_rate = rk3308_clk_get_rate, 1044 .set_rate = rk3308_clk_set_rate, 1045 .get_phase = rk3308_clk_get_phase, 1046 .set_phase = rk3308_clk_set_phase, 1047 }; 1048 1049 static int rk3308_clk_probe(struct udevice *dev) 1050 { 1051 rkclk_init(dev); 1052 1053 return 0; 1054 } 1055 1056 static int rk3308_clk_ofdata_to_platdata(struct udevice *dev) 1057 { 1058 struct rk3308_clk_priv *priv = dev_get_priv(dev); 1059 1060 priv->cru = dev_read_addr_ptr(dev); 1061 1062 return 0; 1063 } 1064 1065 static int rk3308_clk_bind(struct udevice *dev) 1066 { 1067 int ret; 1068 struct udevice *sys_child, *sf_child; 1069 struct sysreset_reg *priv; 1070 struct softreset_reg *sf_priv; 1071 1072 /* The reset driver does not have a device node, so bind it here */ 1073 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 1074 &sys_child); 1075 if (ret) { 1076 debug("Warning: No sysreset driver: ret=%d\n", ret); 1077 } else { 1078 priv = malloc(sizeof(struct sysreset_reg)); 1079 priv->glb_srst_fst_value = offsetof(struct rk3308_cru, 1080 glb_srst_fst); 1081 priv->glb_srst_snd_value = offsetof(struct rk3308_cru, 1082 glb_srst_snd); 1083 sys_child->priv = priv; 1084 } 1085 1086 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 1087 dev_ofnode(dev), &sf_child); 1088 if (ret) { 1089 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 1090 } else { 1091 sf_priv = malloc(sizeof(struct softreset_reg)); 1092 sf_priv->sf_reset_offset = offsetof(struct rk3308_cru, 1093 softrst_con[0]); 1094 sf_priv->sf_reset_num = 12; 1095 sf_child->priv = sf_priv; 1096 } 1097 1098 return 0; 1099 } 1100 1101 static const struct udevice_id rk3308_clk_ids[] = { 1102 { .compatible = "rockchip,rk3308-cru" }, 1103 { } 1104 }; 1105 1106 U_BOOT_DRIVER(rockchip_rk3308_cru) = { 1107 .name = "rockchip_rk3308_cru", 1108 .id = UCLASS_CLK, 1109 .of_match = rk3308_clk_ids, 1110 .priv_auto_alloc_size = sizeof(struct rk3308_clk_priv), 1111 .ofdata_to_platdata = rk3308_clk_ofdata_to_platdata, 1112 .ops = &rk3308_clk_ops, 1113 .bind = rk3308_clk_bind, 1114 .probe = rk3308_clk_probe, 1115 }; 1116 1117 /** 1118 * soc_clk_dump() - Print clock frequencies 1119 * Returns zero on success 1120 * 1121 * Implementation for the clk dump command. 1122 */ 1123 int soc_clk_dump(void) 1124 { 1125 struct udevice *cru_dev; 1126 const struct rk3308_clk_info *clk_dump; 1127 struct clk clk; 1128 unsigned long clk_count = ARRAY_SIZE(clks_dump); 1129 unsigned long rate; 1130 int i, ret; 1131 1132 ret = uclass_get_device_by_driver(UCLASS_CLK, 1133 DM_GET_DRIVER(rockchip_rk3308_cru), 1134 &cru_dev); 1135 if (ret) { 1136 printf("%s failed to get cru device\n", __func__); 1137 return ret; 1138 } 1139 1140 printf("CLK:"); 1141 for (i = 0; i < clk_count; i++) { 1142 clk_dump = &clks_dump[i]; 1143 if (clk_dump->name) { 1144 clk.id = clk_dump->id; 1145 ret = clk_request(cru_dev, &clk); 1146 if (ret < 0) 1147 return ret; 1148 1149 rate = clk_get_rate(&clk); 1150 clk_free(&clk); 1151 if (i == 0) { 1152 if (rate < 0) 1153 printf("%10s%20s\n", clk_dump->name, 1154 "unknown"); 1155 else 1156 printf("%10s%20lu Hz\n", clk_dump->name, 1157 rate); 1158 } else { 1159 if (rate < 0) 1160 printf("%14s%20s\n", clk_dump->name, 1161 "unknown"); 1162 else 1163 printf("%14s%20lu Hz\n", clk_dump->name, 1164 rate); 1165 } 1166 } 1167 } 1168 1169 return 0; 1170 } 1171