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