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