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