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