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 <errno.h> 11 #include <syscon.h> 12 #include <asm/arch/clock.h> 13 #include <asm/arch/cru_rk3308.h> 14 #include <asm/arch/hardware.h> 15 #include <asm/io.h> 16 #include <dm/lists.h> 17 #include <dt-bindings/clock/rk3308-cru.h> 18 19 DECLARE_GLOBAL_DATA_PTR; 20 21 enum { 22 VCO_MAX_HZ = 3200U * 1000000, 23 VCO_MIN_HZ = 800 * 1000000, 24 OUTPUT_MAX_HZ = 3200U * 1000000, 25 OUTPUT_MIN_HZ = 24 * 1000000, 26 }; 27 28 #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1)) 29 30 #define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\ 31 .refdiv = _refdiv,\ 32 .fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\ 33 .postdiv1 = _postdiv1, .postdiv2 = _postdiv2}; 34 35 static const struct pll_div apll_816_cfg = PLL_DIVISORS(816 * MHz, 1, 2, 1); 36 37 static u8 pll_mode_shift[PLL_COUNT] = { 38 APLL_MODE_SHIFT, DPLL_MODE_SHIFT, VPLL0_MODE_SHIFT, 39 VPLL1_MODE_SHIFT 40 }; 41 42 static u32 pll_mode_mask[PLL_COUNT] = { 43 APLL_MODE_MASK, DPLL_MODE_MASK, VPLL0_MODE_MASK, 44 VPLL1_MODE_MASK 45 }; 46 47 static ulong apll_hz, dpll_hz, vpll0_hz, vpll1_hz; 48 49 /* 50 * How to calculate the PLL: 51 * Formulas also embedded within the Fractional PLL Verilog model: 52 * If DSMPD = 1 (DSM is disabled, "integer mode") 53 * FOUTVCO = FREF / REFDIV * FBDIV 54 * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2 55 * Where: 56 * FOUTVCO = Fractional PLL non-divided output frequency 57 * FOUTPOSTDIV = Fractional PLL divided output frequency 58 * (output of second post divider) 59 * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input) 60 * REFDIV = Fractional PLL input reference clock divider 61 * FBDIV = Integer value programmed into feedback divide 62 * 63 */ 64 65 static void rkclk_set_pll(struct rk3308_cru *cru, enum rk3308_pll_id pll_id, 66 const struct pll_div *div) 67 { 68 struct rk3308_pll *pll; 69 unsigned int *mode; 70 /* All PLLs have same VCO and output frequency range restrictions. */ 71 uint vco_hz = OSC_HZ / 1000 * div->fbdiv / div->refdiv * 1000; 72 uint output_hz = vco_hz / div->postdiv1 / div->postdiv2; 73 74 pll = &cru->pll[pll_id]; 75 mode = &cru->mode; 76 77 debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n", 78 pll, div->fbdiv, div->refdiv, div->postdiv1, 79 div->postdiv2, vco_hz, output_hz); 80 assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ && 81 output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ); 82 83 /* 84 * When power on or changing PLL setting, 85 * we must force PLL into slow mode to ensure output stable clock. 86 */ 87 rk_clrsetreg(mode, pll_mode_mask[pll_id], 88 PLLMUX_FROM_XIN24M << pll_mode_shift[pll_id]); 89 90 /* use integer mode */ 91 rk_setreg(&pll->con1, 1 << PLL_DSMPD_SHIFT); 92 /* Power down */ 93 rk_setreg(&pll->con1, 1 << PLL_PD_SHIFT); 94 95 rk_clrsetreg(&pll->con0, 96 PLL_POSTDIV1_MASK | PLL_FBDIV_MASK, 97 (div->postdiv1 << PLL_POSTDIV1_SHIFT) | div->fbdiv); 98 rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK | PLL_REFDIV_MASK, 99 (div->postdiv2 << PLL_POSTDIV2_SHIFT | 100 div->refdiv << PLL_REFDIV_SHIFT)); 101 102 /* Power Up */ 103 rk_clrreg(&pll->con1, 1 << PLL_PD_SHIFT); 104 105 /* waiting for pll lock */ 106 while (!(readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT))) 107 udelay(1); 108 109 rk_clrsetreg(mode, pll_mode_mask[pll_id], 110 PLLMUX_FROM_PLL << pll_mode_shift[pll_id]); 111 } 112 113 static uint32_t rkclk_pll_get_rate(struct rk3308_cru *cru, 114 enum rk3308_pll_id pll_id) 115 { 116 u32 refdiv, fbdiv, postdiv1, postdiv2; 117 u32 con; 118 struct rk3308_pll *pll; 119 uint shift; 120 uint mask; 121 122 pll = &cru->pll[pll_id]; 123 con = readl(&cru->mode); 124 125 shift = pll_mode_shift[pll_id]; 126 mask = pll_mode_mask[pll_id]; 127 128 switch ((con & mask) >> shift) { 129 case PLLMUX_FROM_XIN24M: 130 return OSC_HZ; 131 case PLLMUX_FROM_PLL: 132 /* normal mode */ 133 con = readl(&pll->con0); 134 postdiv1 = (con & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT; 135 fbdiv = (con & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT; 136 con = readl(&pll->con1); 137 postdiv2 = (con & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT; 138 refdiv = (con & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT; 139 return (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000; 140 case PLLMUX_FROM_RTC32K: 141 default: 142 return 32768; 143 } 144 } 145 146 static void rkclk_init(struct rk3308_cru *cru) 147 { 148 u32 aclk_div, hclk_div, pclk_div; 149 150 /* init pll */ 151 rkclk_set_pll(cru, APLL, &apll_816_cfg); 152 153 /* 154 * select apll as cpu/core clock pll source and 155 * set up dependent divisors for PCLK and ACLK clocks. 156 * core hz : apll = 1:1 157 */ 158 apll_hz = rkclk_pll_get_rate(cru, APLL); 159 aclk_div = apll_hz / CORE_ACLK_HZ - 1; 160 pclk_div = apll_hz / CORE_DBG_HZ - 1; 161 rk_clrsetreg(&cru->clksel_con[0], 162 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK | 163 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK, 164 aclk_div << CORE_ACLK_DIV_SHIFT | 165 pclk_div << CORE_DBG_DIV_SHIFT | 166 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 167 0 << CORE_DIV_CON_SHIFT); 168 169 /* 170 * select dpll as pd_bus bus clock source and 171 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 172 */ 173 dpll_hz = rkclk_pll_get_rate(cru, DPLL); 174 aclk_div = dpll_hz / BUS_ACLK_HZ - 1; 175 hclk_div = dpll_hz / BUS_HCLK_HZ - 1; 176 pclk_div = dpll_hz / BUS_PCLK_HZ - 1; 177 rk_clrsetreg(&cru->clksel_con[5], 178 BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK, 179 BUS_PLL_SEL_DPLL << BUS_PLL_SEL_SHIFT | 180 aclk_div << BUS_ACLK_DIV_SHIFT); 181 rk_clrsetreg(&cru->clksel_con[6], 182 BUS_PCLK_DIV_MASK | BUS_HCLK_DIV_MASK, 183 pclk_div << BUS_PCLK_DIV_SHIFT | 184 hclk_div << BUS_HCLK_DIV_SHIFT); 185 186 /* 187 * select dpll as pd_peri bus clock source and 188 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 189 */ 190 aclk_div = dpll_hz / PERI_ACLK_HZ - 1; 191 hclk_div = dpll_hz / PERI_HCLK_HZ - 1; 192 pclk_div = dpll_hz / PERI_PCLK_HZ - 1; 193 rk_clrsetreg(&cru->clksel_con[36], 194 PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK, 195 BUS_PLL_SEL_DPLL << PERI_PLL_SEL_SHIFT | 196 aclk_div << PERI_ACLK_DIV_SHIFT); 197 rk_clrsetreg(&cru->clksel_con[37], 198 PERI_PCLK_DIV_MASK | PERI_HCLK_DIV_MASK, 199 pclk_div << PERI_PCLK_DIV_SHIFT | 200 hclk_div << PERI_HCLK_DIV_SHIFT); 201 202 vpll0_hz = rkclk_pll_get_rate(cru, VPLL0); 203 vpll1_hz = rkclk_pll_get_rate(cru, VPLL1); 204 } 205 206 static ulong rk3308_i2c_get_clk(struct rk3308_cru *cru, ulong clk_id) 207 { 208 u32 div, con, con_id; 209 210 switch (clk_id) { 211 case SCLK_I2C0: 212 con_id = 25; 213 break; 214 case SCLK_I2C1: 215 con_id = 26; 216 break; 217 case SCLK_I2C2: 218 con_id = 27; 219 break; 220 case SCLK_I2C3: 221 con_id = 28; 222 break; 223 default: 224 printf("do not support this i2c bus\n"); 225 return -EINVAL; 226 } 227 228 con = readl(&cru->clksel_con[con_id]); 229 div = con >> CLK_I2C_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 230 231 return DIV_TO_RATE(dpll_hz, div); 232 } 233 234 static ulong rk3308_i2c_set_clk(struct rk3308_cru *cru, ulong clk_id, uint hz) 235 { 236 u32 src_clk_div, con_id; 237 238 src_clk_div = dpll_hz / hz; 239 assert(src_clk_div - 1 < 127); 240 241 switch (clk_id) { 242 case SCLK_I2C0: 243 con_id = 25; 244 break; 245 case SCLK_I2C1: 246 con_id = 26; 247 break; 248 case SCLK_I2C2: 249 con_id = 27; 250 break; 251 case SCLK_I2C3: 252 con_id = 28; 253 break; 254 default: 255 printf("do not support this i2c bus\n"); 256 return -EINVAL; 257 } 258 rk_clrsetreg(&cru->clksel_con[con_id], 259 CLK_I2C_PLL_SEL_MASK | CLK_I2C_DIV_CON_MASK, 260 CLK_I2C_PLL_SEL_DPLL << CLK_I2C_PLL_SEL_SHIFT | 261 (src_clk_div - 1) << CLK_I2C_DIV_CON_SHIFT); 262 263 return rk3308_i2c_get_clk(cru, clk_id); 264 } 265 266 static ulong rk3308_mmc_get_clk(struct rk3308_cru *cru, uint clk_id) 267 { 268 u32 div, con, con_id; 269 270 switch (clk_id) { 271 case HCLK_SDMMC: 272 case SCLK_SDMMC: 273 con_id = 39; 274 break; 275 case HCLK_EMMC: 276 case SCLK_EMMC: 277 case SCLK_EMMC_SAMPLE: 278 con_id = 41; 279 break; 280 default: 281 return -EINVAL; 282 } 283 284 con = readl(&cru->clksel_con[con_id]); 285 div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT; 286 287 if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT 288 == EMMC_SEL_24M) 289 return DIV_TO_RATE(OSC_HZ, div) / 2; 290 else 291 return DIV_TO_RATE(vpll0_hz, div) / 2; 292 } 293 294 static ulong rk3308_mmc_set_clk(struct rk3308_cru *cru, 295 ulong clk_id, ulong set_rate) 296 { 297 int src_clk_div; 298 u32 con_id; 299 300 debug("%s %ld %ld\n", __func__, clk_id, set_rate); 301 302 switch (clk_id) { 303 case HCLK_SDMMC: 304 case SCLK_SDMMC: 305 con_id = 39; 306 break; 307 case HCLK_EMMC: 308 case SCLK_EMMC: 309 con_id = 41; 310 break; 311 default: 312 return -EINVAL; 313 } 314 /* Select clk_sdmmc/emmc source from VPLL0 by default */ 315 /* mmc clock defaulg div 2 internal, need provide double in cru */ 316 src_clk_div = DIV_ROUND_UP(vpll0_hz / 2, set_rate); 317 318 if (src_clk_div > 127) { 319 /* use 24MHz source for 400KHz clock */ 320 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate); 321 rk_clrsetreg(&cru->clksel_con[con_id], 322 EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK, 323 EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT | 324 EMMC_SEL_24M << EMMC_PLL_SHIFT | 325 (src_clk_div - 1) << EMMC_DIV_SHIFT); 326 } else { 327 rk_clrsetreg(&cru->clksel_con[con_id], 328 EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK, 329 EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT | 330 EMMC_SEL_VPLL0 << EMMC_PLL_SHIFT | 331 (src_clk_div - 1) << EMMC_DIV_SHIFT); 332 } 333 334 return rk3308_mmc_get_clk(cru, clk_id); 335 } 336 337 static ulong rk3308_saradc_get_clk(struct rk3308_cru *cru) 338 { 339 u32 div, con; 340 341 con = readl(&cru->clksel_con[34]); 342 div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK; 343 344 return DIV_TO_RATE(OSC_HZ, div); 345 } 346 347 static ulong rk3308_saradc_set_clk(struct rk3308_cru *cru, uint hz) 348 { 349 int src_clk_div; 350 351 src_clk_div = OSC_HZ / hz; 352 assert(src_clk_div - 1 < 2047); 353 354 rk_clrsetreg(&cru->clksel_con[34], 355 CLK_SARADC_DIV_CON_MASK, 356 (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT); 357 358 return rk3308_saradc_get_clk(cru); 359 } 360 361 static ulong rk3308_spi_get_clk(struct rk3308_cru *cru, ulong clk_id) 362 { 363 u32 div, con, con_id; 364 365 switch (clk_id) { 366 case SCLK_SPI0: 367 con_id = 30; 368 break; 369 case SCLK_SPI1: 370 con_id = 31; 371 break; 372 case SCLK_SPI2: 373 con_id = 32; 374 break; 375 default: 376 printf("do not support this spi bus\n"); 377 return -EINVAL; 378 } 379 380 con = readl(&cru->clksel_con[con_id]); 381 div = con >> CLK_SPI_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK; 382 383 return DIV_TO_RATE(dpll_hz, div); 384 } 385 386 static ulong rk3308_spi_set_clk(struct rk3308_cru *cru, ulong clk_id, uint hz) 387 { 388 u32 src_clk_div, con_id; 389 390 src_clk_div = dpll_hz / hz; 391 assert(src_clk_div - 1 < 127); 392 393 switch (clk_id) { 394 case SCLK_SPI0: 395 con_id = 30; 396 break; 397 case SCLK_SPI1: 398 con_id = 31; 399 break; 400 case SCLK_SPI2: 401 con_id = 32; 402 break; 403 default: 404 printf("do not support this spi bus\n"); 405 return -EINVAL; 406 } 407 408 rk_clrsetreg(&cru->clksel_con[con_id], 409 CLK_SPI_PLL_SEL_MASK | CLK_SPI_DIV_CON_MASK, 410 CLK_SPI_PLL_SEL_DPLL << CLK_SPI_PLL_SEL_SHIFT | 411 (src_clk_div - 1) << CLK_SPI_DIV_CON_SHIFT); 412 413 return rk3308_spi_get_clk(cru, clk_id); 414 } 415 416 static ulong rk3308_pwm_get_clk(struct rk3308_cru *cru) 417 { 418 u32 div, con; 419 420 con = readl(&cru->clksel_con[29]); 421 div = con >> CLK_PWM_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK; 422 423 return DIV_TO_RATE(dpll_hz, div); 424 } 425 426 static ulong rk3308_pwm_set_clk(struct rk3308_cru *cru, uint hz) 427 { 428 int src_clk_div; 429 430 src_clk_div = dpll_hz / hz; 431 assert(src_clk_div - 1 < 127); 432 433 rk_clrsetreg(&cru->clksel_con[29], 434 CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK, 435 CLK_PWM_PLL_SEL_DPLL << CLK_PWM_PLL_SEL_SHIFT | 436 (src_clk_div - 1) << CLK_PWM_DIV_CON_SHIFT); 437 438 return rk3308_pwm_get_clk(cru); 439 } 440 441 static ulong rk3308_vop_get_clk(struct rk3308_cru *cru) 442 { 443 u32 div, pll_sel, vol_sel, con, parent; 444 445 con = readl(&cru->clksel_con[8]); 446 vol_sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT; 447 pll_sel = (con & DCLK_VOP_PLL_SEL_MASK) >> DCLK_VOP_PLL_SEL_SHIFT; 448 div = con & DCLK_VOP_DIV_MASK; 449 450 if (vol_sel == DCLK_VOP_SEL_24M) { 451 parent = OSC_HZ; 452 } else if (vol_sel == DCLK_VOP_SEL_DIVOUT) { 453 switch (pll_sel) { 454 case DCLK_VOP_PLL_SEL_DPLL: 455 parent = rkclk_pll_get_rate(cru, DPLL); 456 break; 457 case DCLK_VOP_PLL_SEL_VPLL0: 458 parent = rkclk_pll_get_rate(cru, VPLL0); 459 break; 460 case DCLK_VOP_PLL_SEL_VPLL1: 461 parent = rkclk_pll_get_rate(cru, VPLL1); 462 break; 463 default: 464 printf("do not support this vop pll sel\n"); 465 return -EINVAL; 466 } 467 } else { 468 printf("do not support this vop sel\n"); 469 return -EINVAL; 470 } 471 472 return DIV_TO_RATE(parent, div); 473 } 474 475 static ulong rk3308_vop_set_clk(struct rk3308_cru *cru, ulong hz) 476 { 477 ulong pll_rate, now, best_rate = 0; 478 u32 i, div, best_div = 0, best_sel = 0; 479 480 for (i = 0; i <= DCLK_VOP_PLL_SEL_VPLL1; i++) { 481 switch (i) { 482 case DCLK_VOP_PLL_SEL_DPLL: 483 pll_rate = dpll_hz; 484 break; 485 case DCLK_VOP_PLL_SEL_VPLL0: 486 pll_rate = vpll0_hz; 487 break; 488 case DCLK_VOP_PLL_SEL_VPLL1: 489 pll_rate = vpll1_hz; 490 break; 491 default: 492 printf("do not support this vop pll sel\n"); 493 return -EINVAL; 494 } 495 496 div = DIV_ROUND_UP(pll_rate, hz); 497 if (div > 255) 498 continue; 499 now = pll_rate / div; 500 if (abs(hz - now) < abs(hz - best_rate)) { 501 best_rate = now; 502 best_div = div; 503 best_sel = i; 504 } 505 debug("pll_rate=%lu, best_rate=%lu, best_div=%u, best_sel=%u\n", 506 pll_rate, best_rate, best_div, best_sel); 507 } 508 509 if (best_rate != hz && hz == OSC_HZ) { 510 rk_clrsetreg(&cru->clksel_con[8], 511 DCLK_VOP_SEL_MASK, 512 DCLK_VOP_SEL_24M << DCLK_VOP_SEL_SHIFT); 513 } else if (best_rate) { 514 rk_clrsetreg(&cru->clksel_con[8], 515 DCLK_VOP_SEL_MASK | DCLK_VOP_PLL_SEL_MASK | 516 DCLK_VOP_DIV_MASK, 517 DCLK_VOP_SEL_DIVOUT << DCLK_VOP_SEL_SHIFT | 518 best_sel << DCLK_VOP_PLL_SEL_SHIFT | 519 (best_div - 1) << DCLK_VOP_DIV_SHIFT); 520 } else { 521 printf("do not support this vop freq\n"); 522 return -EINVAL; 523 } 524 525 return rk3308_vop_get_clk(cru); 526 } 527 528 static ulong rk3308_clk_get_rate(struct clk *clk) 529 { 530 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 531 ulong rate = 0; 532 533 debug("%s id:%ld\n", __func__, clk->id); 534 535 switch (clk->id) { 536 case 0 ... 15: 537 return 0; 538 case HCLK_SDMMC: 539 case HCLK_EMMC: 540 case SCLK_SDMMC: 541 case SCLK_EMMC: 542 case SCLK_EMMC_SAMPLE: 543 rate = rk3308_mmc_get_clk(priv->cru, clk->id); 544 break; 545 case SCLK_I2C0: 546 case SCLK_I2C1: 547 case SCLK_I2C2: 548 case SCLK_I2C3: 549 rate = rk3308_i2c_get_clk(priv->cru, clk->id); 550 break; 551 case SCLK_SARADC: 552 rate = rk3308_saradc_get_clk(priv->cru); 553 break; 554 case SCLK_SPI0: 555 case SCLK_SPI1: 556 rate = rk3308_spi_get_clk(priv->cru, clk->id); 557 break; 558 case SCLK_PWM: 559 rate = rk3308_pwm_get_clk(priv->cru); 560 break; 561 case DCLK_VOP: 562 rate = rk3308_vop_get_clk(priv->cru); 563 break; 564 default: 565 return -ENOENT; 566 } 567 568 return rate; 569 } 570 571 static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate) 572 { 573 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 574 ulong ret = 0; 575 576 debug("%s %ld %ld\n", __func__, clk->id, rate); 577 switch (clk->id) { 578 case 0 ... 15: 579 return 0; 580 case HCLK_SDMMC: 581 case HCLK_EMMC: 582 case SCLK_SDMMC: 583 case SCLK_EMMC: 584 ret = rk3308_mmc_set_clk(priv->cru, clk->id, rate); 585 break; 586 case SCLK_I2C0: 587 case SCLK_I2C1: 588 case SCLK_I2C2: 589 case SCLK_I2C3: 590 ret = rk3308_i2c_set_clk(priv->cru, clk->id, rate); 591 break; 592 case SCLK_SARADC: 593 ret = rk3308_saradc_set_clk(priv->cru, rate); 594 break; 595 case SCLK_SPI0: 596 case SCLK_SPI1: 597 ret = rk3308_spi_set_clk(priv->cru, clk->id, rate); 598 break; 599 case SCLK_PWM: 600 ret = rk3308_pwm_set_clk(priv->cru, rate); 601 break; 602 case DCLK_VOP: 603 ret = rk3308_vop_set_clk(priv->cru, rate); 604 break; 605 default: 606 return -ENOENT; 607 } 608 609 return ret; 610 } 611 612 #define ROCKCHIP_MMC_DELAY_SEL BIT(11) 613 #define ROCKCHIP_MMC_DEGREE_OFFSET 1 614 #define ROCKCHIP_MMC_DEGREE_MASK (0x3 << ROCKCHIP_MMC_DEGREE_OFFSET) 615 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 3 616 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 617 618 #define PSECS_PER_SEC 1000000000000LL 619 /* 620 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 621 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 622 */ 623 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 624 625 int rockchip_mmc_get_phase(struct clk *clk) 626 { 627 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 628 struct rk3308_cru *cru = priv->cru; 629 u32 raw_value, delay_num; 630 u16 degrees = 0; 631 ulong rate; 632 633 rate = rk3308_clk_get_rate(clk); 634 635 if (rate < 0) 636 return rate; 637 638 if (clk->id == SCLK_EMMC_SAMPLE) 639 raw_value = readl(&cru->emmc_con[1]); 640 else 641 raw_value = readl(&cru->sdmmc_con[1]); 642 643 raw_value &= ROCKCHIP_MMC_DEGREE_MASK; 644 degrees = (raw_value >> ROCKCHIP_MMC_DEGREE_OFFSET) * 90; 645 646 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 647 /* degrees/delaynum * 10000 */ 648 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 649 36 * (rate / 1000000); 650 651 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 652 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 653 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 654 } 655 656 return degrees % 360; 657 658 } 659 660 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees) 661 { 662 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 663 struct rk3308_cru *cru = priv->cru; 664 u8 nineties, remainder, delay_num; 665 u32 raw_value, delay; 666 ulong rate; 667 668 rate = rk3308_clk_get_rate(clk); 669 670 if (rate < 0) 671 return rate; 672 673 nineties = degrees / 90; 674 remainder = (degrees % 90); 675 676 /* 677 * Convert to delay; do a little extra work to make sure we 678 * don't overflow 32-bit / 64-bit numbers. 679 */ 680 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 681 delay *= remainder; 682 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 683 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 684 685 delay_num = (u8)min_t(u32, delay, 255); 686 687 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 688 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 689 raw_value |= nineties << ROCKCHIP_MMC_DEGREE_OFFSET; 690 691 if (clk->id == SCLK_EMMC_SAMPLE) 692 writel(raw_value | 0xffff0000, &cru->emmc_con[1]); 693 else 694 writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]); 695 696 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 697 degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk)); 698 699 return 0; 700 701 } 702 703 static int rk3308_clk_get_phase(struct clk *clk) 704 { 705 int ret; 706 707 switch (clk->id) { 708 case SCLK_EMMC_SAMPLE: 709 case SCLK_SDMMC_SAMPLE: 710 ret = rockchip_mmc_get_phase(clk); 711 break; 712 default: 713 return -ENOENT; 714 } 715 716 return ret; 717 } 718 719 static int rk3308_clk_set_phase(struct clk *clk, int degrees) 720 { 721 int ret; 722 723 switch (clk->id) { 724 case SCLK_EMMC_SAMPLE: 725 case SCLK_SDMMC_SAMPLE: 726 ret = rockchip_mmc_set_phase(clk, degrees); 727 break; 728 default: 729 return -ENOENT; 730 } 731 732 return ret; 733 } 734 735 static struct clk_ops rk3308_clk_ops = { 736 .get_rate = rk3308_clk_get_rate, 737 .set_rate = rk3308_clk_set_rate, 738 .get_phase = rk3308_clk_get_phase, 739 .set_phase = rk3308_clk_set_phase, 740 }; 741 742 static int rk3308_clk_probe(struct udevice *dev) 743 { 744 struct rk3308_clk_priv *priv = dev_get_priv(dev); 745 746 rkclk_init(priv->cru); 747 748 return 0; 749 } 750 751 static int rk3308_clk_ofdata_to_platdata(struct udevice *dev) 752 { 753 struct rk3308_clk_priv *priv = dev_get_priv(dev); 754 755 priv->cru = dev_read_addr_ptr(dev); 756 757 return 0; 758 } 759 760 static int rk3308_clk_bind(struct udevice *dev) 761 { 762 int ret; 763 struct udevice *sys_child, *sf_child; 764 struct sysreset_reg *priv; 765 struct softreset_reg *sf_priv; 766 767 /* The reset driver does not have a device node, so bind it here */ 768 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 769 &sys_child); 770 if (ret) { 771 debug("Warning: No sysreset driver: ret=%d\n", ret); 772 } else { 773 priv = malloc(sizeof(struct sysreset_reg)); 774 priv->glb_srst_fst_value = offsetof(struct rk3308_cru, 775 glb_srst_fst); 776 priv->glb_srst_snd_value = offsetof(struct rk3308_cru, 777 glb_srst_snd); 778 sys_child->priv = priv; 779 } 780 781 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 782 dev_ofnode(dev), &sf_child); 783 if (ret) { 784 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 785 } else { 786 sf_priv = malloc(sizeof(struct softreset_reg)); 787 sf_priv->sf_reset_offset = offsetof(struct rk3308_cru, 788 softrst_con[0]); 789 sf_priv->sf_reset_num = 12; 790 sf_child->priv = sf_priv; 791 } 792 793 return 0; 794 } 795 796 static const struct udevice_id rk3308_clk_ids[] = { 797 { .compatible = "rockchip,rk3308-cru" }, 798 { } 799 }; 800 801 U_BOOT_DRIVER(rockchip_rk3308_cru) = { 802 .name = "rockchip_rk3308_cru", 803 .id = UCLASS_CLK, 804 .of_match = rk3308_clk_ids, 805 .priv_auto_alloc_size = sizeof(struct rk3308_clk_priv), 806 .ofdata_to_platdata = rk3308_clk_ofdata_to_platdata, 807 .ops = &rk3308_clk_ops, 808 .bind = rk3308_clk_bind, 809 .probe = rk3308_clk_probe, 810 }; 811