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