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->clksel_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_sclk_sfc_get_clk(struct rk3308_clk_priv *priv) 893 { 894 struct rk3308_cru *cru = priv->cru; 895 u32 div, con, sel, parent; 896 897 con = readl(&cru->clksel_con[42]); 898 div = (con & SCLK_SFC_DIV_MASK) >> SCLK_SFC_DIV_SHIFT; 899 sel = (con & SCLK_SFC_SEL_MASK) >> SCLK_SFC_SEL_SHIFT; 900 901 if (sel == SCLK_SFC_SEL_DPLL) 902 parent = priv->dpll_hz; 903 else if (sel == SCLK_SFC_SEL_VPLL0) 904 parent = priv->vpll0_hz; 905 else if (sel == SCLK_SFC_SEL_VPLL1) 906 parent = priv->vpll1_hz; 907 else 908 return -EINVAL; 909 910 return DIV_TO_RATE(parent, div); 911 } 912 913 static ulong rk3308_sclk_sfc_set_clk(struct rk3308_clk_priv *priv, uint hz) 914 { 915 struct rk3308_cru *cru = priv->cru; 916 int src_clk_div; 917 918 src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz); 919 assert(src_clk_div - 1 <= 127); 920 921 rk_clrsetreg(&cru->clksel_con[42], 922 SCLK_SFC_SEL_MASK | SCLK_SFC_DIV_MASK, 923 SCLK_SFC_SEL_VPLL0 << SCLK_SFC_SEL_SHIFT | 924 (src_clk_div - 1) << SCLK_SFC_DIV_SHIFT); 925 926 return rk3308_sclk_sfc_get_clk(priv); 927 } 928 929 static ulong rk3308_clk_get_rate(struct clk *clk) 930 { 931 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 932 ulong rate = 0; 933 934 debug("%s id:%ld\n", __func__, clk->id); 935 936 switch (clk->id) { 937 case PLL_APLL: 938 case ARMCLK: 939 rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 940 priv->cru, APLL); 941 break; 942 case PLL_DPLL: 943 rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL], 944 priv->cru, DPLL); 945 break; 946 case PLL_VPLL0: 947 rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0], 948 priv->cru, VPLL0); 949 break; 950 case PLL_VPLL1: 951 rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1], 952 priv->cru, VPLL1); 953 break; 954 case HCLK_SDMMC: 955 case HCLK_EMMC: 956 case SCLK_SDMMC: 957 case SCLK_EMMC: 958 case SCLK_EMMC_SAMPLE: 959 rate = rk3308_mmc_get_clk(clk); 960 break; 961 case SCLK_I2C0: 962 case SCLK_I2C1: 963 case SCLK_I2C2: 964 case SCLK_I2C3: 965 rate = rk3308_i2c_get_clk(clk); 966 break; 967 case SCLK_SARADC: 968 rate = rk3308_saradc_get_clk(clk); 969 break; 970 case SCLK_TSADC: 971 rate = rk3308_tsadc_get_clk(clk); 972 break; 973 case SCLK_SPI0: 974 case SCLK_SPI1: 975 rate = rk3308_spi_get_clk(clk); 976 break; 977 case SCLK_PWM0: 978 case SCLK_PWM1: 979 case SCLK_PWM2: 980 rate = rk3308_pwm_get_clk(clk); 981 break; 982 case DCLK_VOP: 983 rate = rk3308_vop_get_clk(clk); 984 break; 985 case ACLK_BUS: 986 case HCLK_BUS: 987 case PCLK_BUS: 988 case PCLK_WDT: 989 rate = rk3308_bus_get_clk(priv, clk->id); 990 break; 991 case ACLK_PERI: 992 case HCLK_PERI: 993 case PCLK_PERI: 994 rate = rk3308_peri_get_clk(priv, clk->id); 995 break; 996 case HCLK_AUDIO: 997 case PCLK_AUDIO: 998 rate = rk3308_audio_get_clk(priv, clk->id); 999 break; 1000 case SCLK_CRYPTO: 1001 case SCLK_CRYPTO_APK: 1002 rate = rk3308_crypto_get_clk(priv, clk->id); 1003 break; 1004 case SCLK_RTC32K: 1005 rate = rk3308_rtc32k_get_clk(priv, clk->id); 1006 break; 1007 case SCLK_SFC: 1008 rate = rk3308_sclk_sfc_get_clk(priv); 1009 break; 1010 default: 1011 return -ENOENT; 1012 } 1013 1014 return rate; 1015 } 1016 1017 static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate) 1018 { 1019 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 1020 ulong ret = 0; 1021 1022 debug("%s %ld %ld\n", __func__, clk->id, rate); 1023 1024 switch (clk->id) { 1025 case PLL_DPLL: 1026 ret = rockchip_pll_set_rate(&rk3308_pll_clks[DPLL], priv->cru, 1027 DPLL, rate); 1028 priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL], 1029 priv->cru, DPLL); 1030 break; 1031 case ARMCLK: 1032 /* 1033 * Why add `rate < rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 1034 * priv->cru, APLL)` ? 1035 * 1036 * rockchip_wtemp_dvfs.c may decrease the arm freq, don't 1037 * limit this decrease operation here. 1038 */ 1039 if (priv->armclk_hz || 1040 (rate < rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 1041 priv->cru, APLL))) 1042 rk3308_armclk_set_clk(priv, rate); 1043 priv->armclk_hz = rate; 1044 break; 1045 case HCLK_SDMMC: 1046 case HCLK_EMMC: 1047 case SCLK_SDMMC: 1048 case SCLK_EMMC: 1049 ret = rk3308_mmc_set_clk(clk, rate); 1050 break; 1051 case SCLK_I2C0: 1052 case SCLK_I2C1: 1053 case SCLK_I2C2: 1054 case SCLK_I2C3: 1055 ret = rk3308_i2c_set_clk(clk, rate); 1056 break; 1057 case SCLK_MAC: 1058 ret = rk3308_mac_set_clk(clk, rate); 1059 break; 1060 case SCLK_MAC_RMII: 1061 ret = rk3308_mac_set_speed_clk(clk, rate); 1062 break; 1063 case SCLK_SARADC: 1064 ret = rk3308_saradc_set_clk(clk, rate); 1065 break; 1066 case SCLK_TSADC: 1067 ret = rk3308_tsadc_set_clk(clk, rate); 1068 break; 1069 case SCLK_SPI0: 1070 case SCLK_SPI1: 1071 ret = rk3308_spi_set_clk(clk, rate); 1072 break; 1073 case SCLK_PWM0: 1074 case SCLK_PWM1: 1075 case SCLK_PWM2: 1076 ret = rk3308_pwm_set_clk(clk, rate); 1077 break; 1078 case DCLK_VOP: 1079 ret = rk3308_vop_set_clk(clk, rate); 1080 break; 1081 case ACLK_BUS: 1082 case HCLK_BUS: 1083 case PCLK_BUS: 1084 rate = rk3308_bus_set_clk(priv, clk->id, rate); 1085 break; 1086 case ACLK_PERI: 1087 case HCLK_PERI: 1088 case PCLK_PERI: 1089 rate = rk3308_peri_set_clk(priv, clk->id, rate); 1090 break; 1091 case HCLK_AUDIO: 1092 case PCLK_AUDIO: 1093 rate = rk3308_audio_set_clk(priv, clk->id, rate); 1094 break; 1095 case SCLK_CRYPTO: 1096 case SCLK_CRYPTO_APK: 1097 ret = rk3308_crypto_set_clk(priv, clk->id, rate); 1098 break; 1099 case SCLK_RTC32K: 1100 ret = rk3308_rtc32k_set_clk(priv, clk->id, rate); 1101 break; 1102 case SCLK_SFC: 1103 ret = rk3308_sclk_sfc_set_clk(priv, rate); 1104 break; 1105 default: 1106 return -ENOENT; 1107 } 1108 1109 return ret; 1110 } 1111 1112 #define ROCKCHIP_MMC_DELAY_SEL BIT(11) 1113 #define ROCKCHIP_MMC_DEGREE_OFFSET 1 1114 #define ROCKCHIP_MMC_DEGREE_MASK (0x3 << ROCKCHIP_MMC_DEGREE_OFFSET) 1115 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 3 1116 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 1117 1118 #define PSECS_PER_SEC 1000000000000LL 1119 /* 1120 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 1121 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 1122 */ 1123 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 1124 1125 int rockchip_mmc_get_phase(struct clk *clk) 1126 { 1127 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 1128 struct rk3308_cru *cru = priv->cru; 1129 u32 raw_value, delay_num; 1130 u16 degrees = 0; 1131 ulong rate; 1132 1133 rate = rk3308_clk_get_rate(clk); 1134 1135 if (rate < 0) 1136 return rate; 1137 1138 if (clk->id == SCLK_EMMC_SAMPLE) 1139 raw_value = readl(&cru->emmc_con[1]); 1140 else 1141 raw_value = readl(&cru->sdmmc_con[1]); 1142 1143 raw_value &= ROCKCHIP_MMC_DEGREE_MASK; 1144 degrees = (raw_value >> ROCKCHIP_MMC_DEGREE_OFFSET) * 90; 1145 1146 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 1147 /* degrees/delaynum * 10000 */ 1148 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 1149 36 * (rate / 1000000); 1150 1151 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 1152 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 1153 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 1154 } 1155 1156 return degrees % 360; 1157 1158 } 1159 1160 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees) 1161 { 1162 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 1163 struct rk3308_cru *cru = priv->cru; 1164 u8 nineties, remainder, delay_num; 1165 u32 raw_value, delay; 1166 ulong rate; 1167 1168 rate = rk3308_clk_get_rate(clk); 1169 1170 if (rate < 0) 1171 return rate; 1172 1173 nineties = degrees / 90; 1174 remainder = (degrees % 90); 1175 1176 /* 1177 * Convert to delay; do a little extra work to make sure we 1178 * don't overflow 32-bit / 64-bit numbers. 1179 */ 1180 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 1181 delay *= remainder; 1182 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 1183 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 1184 1185 delay_num = (u8)min_t(u32, delay, 255); 1186 1187 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 1188 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 1189 raw_value |= nineties << ROCKCHIP_MMC_DEGREE_OFFSET; 1190 1191 if (clk->id == SCLK_EMMC_SAMPLE) 1192 writel(raw_value | 0xffff0000, &cru->emmc_con[1]); 1193 else 1194 writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]); 1195 1196 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 1197 degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk)); 1198 1199 return 0; 1200 1201 } 1202 1203 static int rk3308_clk_get_phase(struct clk *clk) 1204 { 1205 int ret; 1206 1207 switch (clk->id) { 1208 case SCLK_EMMC_SAMPLE: 1209 case SCLK_SDMMC_SAMPLE: 1210 ret = rockchip_mmc_get_phase(clk); 1211 break; 1212 default: 1213 return -ENOENT; 1214 } 1215 1216 return ret; 1217 } 1218 1219 static int rk3308_clk_set_phase(struct clk *clk, int degrees) 1220 { 1221 int ret; 1222 1223 switch (clk->id) { 1224 case SCLK_EMMC_SAMPLE: 1225 case SCLK_SDMMC_SAMPLE: 1226 ret = rockchip_mmc_set_phase(clk, degrees); 1227 break; 1228 default: 1229 return -ENOENT; 1230 } 1231 1232 return ret; 1233 } 1234 1235 static int __maybe_unused rk3308_mac_set_parent(struct clk *clk, struct clk *parent) 1236 { 1237 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 1238 1239 /* 1240 * If the requested parent is in the same clock-controller and 1241 * the id is SCLK_MAC_SRC, switch to the internal clock. 1242 */ 1243 if (parent->id == SCLK_MAC_SRC) { 1244 debug("%s: switching RMII to SCLK_MAC\n", __func__); 1245 rk_clrreg(&priv->cru->clksel_con[43], BIT(14)); 1246 } else { 1247 debug("%s: switching RMII to CLKIN\n", __func__); 1248 rk_setreg(&priv->cru->clksel_con[43], BIT(14)); 1249 } 1250 1251 return 0; 1252 } 1253 1254 static int __maybe_unused rk3308_clk_set_parent(struct clk *clk, struct clk *parent) 1255 { 1256 switch (clk->id) { 1257 case SCLK_MAC: 1258 return rk3308_mac_set_parent(clk, parent); 1259 default: 1260 break; 1261 } 1262 1263 debug("%s: unsupported clk %ld\n", __func__, clk->id); 1264 return -ENOENT; 1265 } 1266 1267 static struct clk_ops rk3308_clk_ops = { 1268 .get_rate = rk3308_clk_get_rate, 1269 .set_rate = rk3308_clk_set_rate, 1270 .get_phase = rk3308_clk_get_phase, 1271 .set_phase = rk3308_clk_set_phase, 1272 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) 1273 .set_parent = rk3308_clk_set_parent, 1274 #endif 1275 }; 1276 1277 static void rk3308_clk_init(struct udevice *dev) 1278 { 1279 struct rk3308_clk_priv *priv = dev_get_priv(dev); 1280 int ret; 1281 1282 if (rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 1283 priv->cru, APLL) != APLL_HZ) { 1284 ret = rk3308_armclk_set_clk(priv, APLL_HZ); 1285 if (ret < 0) 1286 printf("%s failed to set armclk rate\n", __func__); 1287 } 1288 1289 rk3308_clk_get_pll_rate(priv); 1290 1291 rk3308_bus_set_clk(priv, ACLK_BUS, BUS_ACLK_HZ); 1292 rk3308_bus_set_clk(priv, HCLK_BUS, BUS_HCLK_HZ); 1293 rk3308_bus_set_clk(priv, PCLK_BUS, BUS_PCLK_HZ); 1294 1295 rk3308_peri_set_clk(priv, ACLK_PERI, PERI_ACLK_HZ); 1296 rk3308_peri_set_clk(priv, HCLK_PERI, PERI_HCLK_HZ); 1297 rk3308_peri_set_clk(priv, PCLK_PERI, PERI_PCLK_HZ); 1298 1299 rk3308_audio_set_clk(priv, HCLK_AUDIO, AUDIO_HCLK_HZ); 1300 rk3308_audio_set_clk(priv, PCLK_AUDIO, AUDIO_PCLK_HZ); 1301 } 1302 1303 static int rk3308_clk_probe(struct udevice *dev) 1304 { 1305 struct rk3308_clk_priv *priv = dev_get_priv(dev); 1306 int ret; 1307 1308 priv->sync_kernel = false; 1309 if (!priv->armclk_enter_hz) 1310 priv->armclk_enter_hz = 1311 rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 1312 priv->cru, APLL); 1313 rk3308_clk_init(dev); 1314 if (!priv->armclk_init_hz) 1315 priv->armclk_init_hz = 1316 rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 1317 priv->cru, APLL); 1318 1319 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 1320 ret = clk_set_defaults(dev); 1321 if (ret) 1322 debug("%s clk_set_defaults failed %d\n", __func__, ret); 1323 else 1324 priv->sync_kernel = true; 1325 1326 return 0; 1327 } 1328 1329 static int rk3308_clk_ofdata_to_platdata(struct udevice *dev) 1330 { 1331 struct rk3308_clk_priv *priv = dev_get_priv(dev); 1332 1333 priv->cru = dev_read_addr_ptr(dev); 1334 1335 return 0; 1336 } 1337 1338 static int rk3308_clk_bind(struct udevice *dev) 1339 { 1340 int ret; 1341 struct udevice *sys_child, *sf_child; 1342 struct sysreset_reg *priv; 1343 struct softreset_reg *sf_priv; 1344 1345 /* The reset driver does not have a device node, so bind it here */ 1346 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 1347 &sys_child); 1348 if (ret) { 1349 debug("Warning: No sysreset driver: ret=%d\n", ret); 1350 } else { 1351 priv = malloc(sizeof(struct sysreset_reg)); 1352 priv->glb_srst_fst_value = offsetof(struct rk3308_cru, 1353 glb_srst_fst); 1354 priv->glb_srst_snd_value = offsetof(struct rk3308_cru, 1355 glb_srst_snd); 1356 sys_child->priv = priv; 1357 } 1358 1359 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 1360 dev_ofnode(dev), &sf_child); 1361 if (ret) { 1362 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 1363 } else { 1364 sf_priv = malloc(sizeof(struct softreset_reg)); 1365 sf_priv->sf_reset_offset = offsetof(struct rk3308_cru, 1366 softrst_con[0]); 1367 sf_priv->sf_reset_num = 12; 1368 sf_child->priv = sf_priv; 1369 } 1370 1371 return 0; 1372 } 1373 1374 static const struct udevice_id rk3308_clk_ids[] = { 1375 { .compatible = "rockchip,rk3308-cru" }, 1376 { } 1377 }; 1378 1379 U_BOOT_DRIVER(rockchip_rk3308_cru) = { 1380 .name = "rockchip_rk3308_cru", 1381 .id = UCLASS_CLK, 1382 .of_match = rk3308_clk_ids, 1383 .priv_auto_alloc_size = sizeof(struct rk3308_clk_priv), 1384 .ofdata_to_platdata = rk3308_clk_ofdata_to_platdata, 1385 .ops = &rk3308_clk_ops, 1386 .bind = rk3308_clk_bind, 1387 .probe = rk3308_clk_probe, 1388 }; 1389 1390 /** 1391 * soc_clk_dump() - Print clock frequencies 1392 * Returns zero on success 1393 * 1394 * Implementation for the clk dump command. 1395 */ 1396 int soc_clk_dump(void) 1397 { 1398 struct udevice *cru_dev; 1399 struct rk3308_clk_priv *priv; 1400 const struct rk3308_clk_info *clk_dump; 1401 struct clk clk; 1402 unsigned long clk_count = ARRAY_SIZE(clks_dump); 1403 unsigned long rate; 1404 int i, ret; 1405 1406 ret = uclass_get_device_by_driver(UCLASS_CLK, 1407 DM_GET_DRIVER(rockchip_rk3308_cru), 1408 &cru_dev); 1409 if (ret) { 1410 printf("%s failed to get cru device\n", __func__); 1411 return ret; 1412 } 1413 1414 priv = dev_get_priv(cru_dev); 1415 printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n", 1416 priv->sync_kernel ? "sync kernel" : "uboot", 1417 priv->armclk_enter_hz / 1000, 1418 priv->armclk_init_hz / 1000, 1419 priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0, 1420 priv->set_armclk_rate ? " KHz" : "N/A"); 1421 for (i = 0; i < clk_count; i++) { 1422 clk_dump = &clks_dump[i]; 1423 if (clk_dump->name) { 1424 clk.id = clk_dump->id; 1425 ret = clk_request(cru_dev, &clk); 1426 if (ret < 0) 1427 return ret; 1428 1429 rate = clk_get_rate(&clk); 1430 clk_free(&clk); 1431 if (i == 0) { 1432 if (rate < 0) 1433 printf(" %s %s\n", clk_dump->name, 1434 "unknown"); 1435 else 1436 printf(" %s %lu KHz\n", clk_dump->name, 1437 rate / 1000); 1438 } else { 1439 if (rate < 0) 1440 printf(" %s %s\n", clk_dump->name, 1441 "unknown"); 1442 else 1443 printf(" %s %lu KHz\n", clk_dump->name, 1444 rate / 1000); 1445 } 1446 } 1447 } 1448 1449 return 0; 1450 } 1451