1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * Author: Andy Yan <andy.yan@rock-chips.com> 4 * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH 5 * SPDX-License-Identifier: GPL-2.0 6 */ 7 8 #include <common.h> 9 #include <clk-uclass.h> 10 #include <dm.h> 11 #include <dt-structs.h> 12 #include <errno.h> 13 #include <mapmem.h> 14 #include <syscon.h> 15 #include <bitfield.h> 16 #include <asm/arch/clock.h> 17 #include <asm/arch/cru_rk3368.h> 18 #include <asm/arch/hardware.h> 19 #include <asm/io.h> 20 #include <dm/lists.h> 21 #include <dt-bindings/clock/rk3368-cru.h> 22 23 DECLARE_GLOBAL_DATA_PTR; 24 25 #if CONFIG_IS_ENABLED(OF_PLATDATA) 26 struct rk3368_clk_plat { 27 struct dtd_rockchip_rk3368_cru dtd; 28 }; 29 #endif 30 31 struct pll_div { 32 u32 nr; 33 u32 nf; 34 u32 no; 35 }; 36 37 #define OSC_HZ (24 * 1000 * 1000) 38 #define APLL_L_HZ (800 * 1000 * 1000) 39 #define APLL_B_HZ (816 * 1000 * 1000) 40 #define GPLL_HZ (576 * 1000 * 1000) 41 #define CPLL_HZ (400 * 1000 * 1000) 42 43 #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1)) 44 45 #if !defined(CONFIG_SPL_BUILD) 46 #define RK3368_CLK_DUMP(_id, _name, _iscru) \ 47 { \ 48 .id = _id, \ 49 .name = _name, \ 50 .is_cru = _iscru, \ 51 } 52 53 static const struct rk3368_clk_info clks_dump[] = { 54 RK3368_CLK_DUMP(PLL_APLLB, "apllb", true), 55 RK3368_CLK_DUMP(PLL_APLLL, "aplll", true), 56 RK3368_CLK_DUMP(PLL_DPLL, "dpll", true), 57 RK3368_CLK_DUMP(PLL_CPLL, "cpll", true), 58 RK3368_CLK_DUMP(PLL_GPLL, "gpll", true), 59 RK3368_CLK_DUMP(PLL_NPLL, "npll", true), 60 RK3368_CLK_DUMP(ARMCLKB, "armclkb", true), 61 RK3368_CLK_DUMP(ARMCLKL, "armclkl", true), 62 RK3368_CLK_DUMP(ACLK_BUS, "aclk_bus", true), 63 RK3368_CLK_DUMP(HCLK_BUS, "hclk_bus", true), 64 RK3368_CLK_DUMP(PCLK_BUS, "pclk_Bus", true), 65 RK3368_CLK_DUMP(ACLK_PERI, "aclk_peri", true), 66 RK3368_CLK_DUMP(HCLK_PERI, "hclk_peri", true), 67 RK3368_CLK_DUMP(PCLK_PERI, "pclk_peri", true), 68 }; 69 #endif 70 71 #define RK3368_CPUCLK_RATE(_rate, _aclk_div, _pclk_div) \ 72 { \ 73 .rate = _rate##U, \ 74 .aclk_div = _aclk_div, \ 75 .pclk_div = _pclk_div, \ 76 } 77 78 static struct rockchip_cpu_rate_table rk3368_cpu_rates[] = { 79 #if !defined(CONFIG_SPL_BUILD) 80 RK3368_CPUCLK_RATE(1200000000, 1, 5), 81 RK3368_CPUCLK_RATE(1008000000, 1, 5), 82 #endif 83 RK3368_CPUCLK_RATE(816000000, 1, 3), 84 RK3368_CPUCLK_RATE(600000000, 1, 3), 85 }; 86 87 #define PLL_DIVISORS(hz, _nr, _no) { \ 88 .nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no}; \ 89 _Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\ 90 (_nr * _no) == hz, #hz "Hz cannot be hit with PLL " \ 91 "divisors on line " __stringify(__LINE__)); 92 93 #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 94 static const struct pll_div apll_l_init_cfg = PLL_DIVISORS(APLL_L_HZ, 12, 2); 95 static const struct pll_div apll_b_init_cfg = PLL_DIVISORS(APLL_B_HZ, 1, 2); 96 #if !defined(CONFIG_TPL_BUILD) 97 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 2); 98 static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 6); 99 #endif 100 #endif 101 102 static ulong rk3368_clk_get_rate(struct clk *clk); 103 104 #define VCO_MAX_KHZ 2200000 105 #define VCO_MIN_KHZ 440000 106 #define FREF_MAX_KHZ 2200000 107 #define FREF_MIN_KHZ 269 108 #define PLL_LIMIT_FREQ 400000000 109 110 static int pll_para_config(ulong freq_hz, struct pll_div *div, uint *ext_div) 111 { 112 uint ref_khz = OSC_HZ / 1000, nr, nf = 0; 113 uint fref_khz; 114 uint diff_khz, best_diff_khz; 115 const uint max_nr = 1 << 6, max_nf = 1 << 12, max_no = 1 << 4; 116 uint vco_khz; 117 uint no = 1; 118 uint freq_khz = freq_hz / 1000; 119 120 if (!freq_hz) { 121 printf("%s: the frequency can not be 0 Hz\n", __func__); 122 return -EINVAL; 123 } 124 125 no = DIV_ROUND_UP(VCO_MIN_KHZ, freq_khz); 126 if (ext_div) { 127 *ext_div = DIV_ROUND_UP(PLL_LIMIT_FREQ, freq_hz); 128 no = DIV_ROUND_UP(no, *ext_div); 129 } 130 131 /* only even divisors (and 1) are supported */ 132 if (no > 1) 133 no = DIV_ROUND_UP(no, 2) * 2; 134 135 vco_khz = freq_khz * no; 136 if (ext_div) 137 vco_khz *= *ext_div; 138 139 if (vco_khz < VCO_MIN_KHZ || vco_khz > VCO_MAX_KHZ || no > max_no) { 140 printf("%s: Cannot find out VCO for Frequency (%luHz).\n", 141 __func__, freq_hz); 142 return -1; 143 } 144 145 div->no = no; 146 147 best_diff_khz = vco_khz; 148 for (nr = 1; nr < max_nr && best_diff_khz; nr++) { 149 fref_khz = ref_khz / nr; 150 if (fref_khz < FREF_MIN_KHZ) 151 break; 152 if (fref_khz > FREF_MAX_KHZ) 153 continue; 154 155 nf = vco_khz / fref_khz; 156 if (nf >= max_nf) 157 continue; 158 diff_khz = vco_khz - nf * fref_khz; 159 if (nf + 1 < max_nf && diff_khz > fref_khz / 2) { 160 nf++; 161 diff_khz = fref_khz - diff_khz; 162 } 163 164 if (diff_khz >= best_diff_khz) 165 continue; 166 167 best_diff_khz = diff_khz; 168 div->nr = nr; 169 div->nf = nf; 170 } 171 172 if (best_diff_khz > 4 * 1000) { 173 printf("%s:Fail to match output freq %lu,best_is %u Hz\n", 174 __func__, freq_hz, best_diff_khz * 1000); 175 return -EINVAL; 176 } 177 178 return 0; 179 } 180 181 /* Get pll rate by id */ 182 static uint32_t rkclk_pll_get_rate(struct rk3368_cru *cru, 183 enum rk3368_pll_id pll_id) 184 { 185 uint32_t nr, no, nf; 186 uint32_t con; 187 struct rk3368_pll *pll = &cru->pll[pll_id]; 188 189 con = readl(&pll->con3); 190 191 switch ((con & PLL_MODE_MASK) >> PLL_MODE_SHIFT) { 192 case PLL_MODE_SLOW: 193 return OSC_HZ; 194 case PLL_MODE_NORMAL: 195 con = readl(&pll->con0); 196 no = ((con & PLL_OD_MASK) >> PLL_OD_SHIFT) + 1; 197 nr = ((con & PLL_NR_MASK) >> PLL_NR_SHIFT) + 1; 198 con = readl(&pll->con1); 199 nf = ((con & PLL_NF_MASK) >> PLL_NF_SHIFT) + 1; 200 201 return (24 * nf / (nr * no)) * 1000000; 202 case PLL_MODE_DEEP_SLOW: 203 default: 204 return 32768; 205 } 206 } 207 208 static int rkclk_set_pll(struct rk3368_cru *cru, enum rk3368_pll_id pll_id, 209 const struct pll_div *div) 210 { 211 struct rk3368_pll *pll = &cru->pll[pll_id]; 212 /* All PLLs have same VCO and output frequency range restrictions*/ 213 uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000; 214 uint output_hz = vco_hz / div->no; 215 216 debug("PLL at %p: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n", 217 pll, div->nf, div->nr, div->no, vco_hz, output_hz); 218 219 /* enter slow mode and reset pll */ 220 rk_clrsetreg(&pll->con3, PLL_MODE_MASK | PLL_RESET_MASK, 221 PLL_RESET << PLL_RESET_SHIFT); 222 223 rk_clrsetreg(&pll->con0, PLL_NR_MASK | PLL_OD_MASK, 224 ((div->nr - 1) << PLL_NR_SHIFT) | 225 ((div->no - 1) << PLL_OD_SHIFT)); 226 writel((div->nf - 1) << PLL_NF_SHIFT, &pll->con1); 227 /* 228 * BWADJ should be set to NF / 2 to ensure the nominal bandwidth. 229 * Compare the RK3368 TRM, section "3.6.4 PLL Bandwidth Adjustment". 230 */ 231 clrsetbits_le32(&pll->con2, PLL_BWADJ_MASK, (div->nf >> 1) - 1); 232 233 udelay(10); 234 235 /* return from reset */ 236 rk_clrreg(&pll->con3, PLL_RESET_MASK); 237 rk_clrreg(&pll->con3, 0xf << 0); 238 239 /* waiting for pll lock */ 240 while (!(readl(&pll->con1) & PLL_LOCK_STA)) 241 udelay(1); 242 243 rk_clrsetreg(&pll->con3, PLL_MODE_MASK, 244 PLL_MODE_NORMAL << PLL_MODE_SHIFT); 245 246 return 0; 247 } 248 249 #if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT) 250 static ulong rk3368_mmc_get_clk(struct rk3368_cru *cru, uint clk_id) 251 { 252 u32 div, con, con_id, rate; 253 u32 pll_rate; 254 255 switch (clk_id) { 256 case HCLK_SDMMC: 257 con_id = 50; 258 break; 259 case HCLK_EMMC: 260 con_id = 51; 261 break; 262 case SCLK_SDIO0: 263 con_id = 48; 264 break; 265 default: 266 return -EINVAL; 267 } 268 269 con = readl(&cru->clksel_con[con_id]); 270 switch (con & MMC_PLL_SEL_MASK) { 271 case MMC_PLL_SEL_GPLL: 272 pll_rate = rkclk_pll_get_rate(cru, GPLL); 273 break; 274 case MMC_PLL_SEL_24M: 275 pll_rate = OSC_HZ; 276 break; 277 case MMC_PLL_SEL_CPLL: 278 pll_rate = rkclk_pll_get_rate(cru, CPLL); 279 break; 280 case MMC_PLL_SEL_USBPHY_480M: 281 default: 282 return -EINVAL; 283 } 284 div = (con & MMC_CLK_DIV_MASK) >> MMC_CLK_DIV_SHIFT; 285 rate = DIV_TO_RATE(pll_rate, div); 286 287 debug("%s: raw rate %d (post-divide by 2)\n", __func__, rate); 288 return rate >> 1; 289 } 290 291 static ulong rk3368_mmc_find_best_rate_and_parent(struct clk *clk, 292 ulong rate, 293 u32 *best_mux, 294 u32 *best_div) 295 { 296 int i; 297 ulong best_rate = 0; 298 const ulong MHz = 1000000; 299 const struct { 300 u32 mux; 301 ulong rate; 302 } parents[] = { 303 { .mux = MMC_PLL_SEL_CPLL, .rate = CPLL_HZ }, 304 { .mux = MMC_PLL_SEL_GPLL, .rate = GPLL_HZ }, 305 { .mux = MMC_PLL_SEL_24M, .rate = 24 * MHz } 306 }; 307 308 debug("%s: target rate %ld\n", __func__, rate); 309 for (i = 0; i < ARRAY_SIZE(parents); ++i) { 310 /* 311 * Find the largest rate no larger than the target-rate for 312 * the current parent. 313 */ 314 ulong parent_rate = parents[i].rate; 315 u32 div = DIV_ROUND_UP(parent_rate, rate); 316 u32 adj_div = div; 317 ulong new_rate = parent_rate / adj_div; 318 319 debug("%s: rate %ld, parent-mux %d, parent-rate %ld, div %d\n", 320 __func__, rate, parents[i].mux, parents[i].rate, div); 321 322 /* Skip, if not representable */ 323 if ((div - 1) > MMC_CLK_DIV_MASK) 324 continue; 325 326 /* Skip, if we already have a better (or equal) solution */ 327 if (new_rate <= best_rate) 328 continue; 329 330 /* This is our new best rate. */ 331 best_rate = new_rate; 332 *best_mux = parents[i].mux; 333 *best_div = div - 1; 334 } 335 336 debug("%s: best_mux = %x, best_div = %d, best_rate = %ld\n", 337 __func__, *best_mux, *best_div, best_rate); 338 339 return best_rate; 340 } 341 342 static ulong rk3368_mmc_set_clk(struct clk *clk, ulong rate) 343 { 344 struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 345 struct rk3368_cru *cru = priv->cru; 346 ulong clk_id = clk->id; 347 u32 con_id, mux = 0, div = 0; 348 349 /* Find the best parent and rate */ 350 rk3368_mmc_find_best_rate_and_parent(clk, rate << 1, &mux, &div); 351 352 switch (clk_id) { 353 case HCLK_SDMMC: 354 con_id = 50; 355 break; 356 case HCLK_EMMC: 357 con_id = 51; 358 break; 359 case SCLK_SDIO0: 360 con_id = 48; 361 break; 362 default: 363 return -EINVAL; 364 } 365 366 rk_clrsetreg(&cru->clksel_con[con_id], 367 MMC_PLL_SEL_MASK | MMC_CLK_DIV_MASK, 368 mux | div); 369 370 return rk3368_mmc_get_clk(cru, clk_id); 371 } 372 #endif 373 374 #if IS_ENABLED(CONFIG_TPL_BUILD) 375 static ulong rk3368_ddr_set_clk(struct rk3368_cru *cru, ulong set_rate) 376 { 377 const struct pll_div *dpll_cfg = NULL; 378 const ulong MHz = 1000000; 379 380 /* Fout = ((Fin /NR) * NF )/ NO */ 381 static const struct pll_div dpll_1200 = PLL_DIVISORS(1200 * MHz, 1, 1); 382 static const struct pll_div dpll_1332 = PLL_DIVISORS(1332 * MHz, 2, 1); 383 static const struct pll_div dpll_1600 = PLL_DIVISORS(1600 * MHz, 3, 2); 384 385 switch (set_rate) { 386 case 1200*MHz: 387 dpll_cfg = &dpll_1200; 388 break; 389 case 1332*MHz: 390 dpll_cfg = &dpll_1332; 391 break; 392 case 1600*MHz: 393 dpll_cfg = &dpll_1600; 394 break; 395 default: 396 pr_err("Unsupported SDRAM frequency!,%ld\n", set_rate); 397 } 398 rkclk_set_pll(cru, DPLL, dpll_cfg); 399 400 return set_rate; 401 } 402 #endif 403 404 #if CONFIG_IS_ENABLED(GMAC_ROCKCHIP) 405 static ulong rk3368_gmac_set_clk(struct rk3368_cru *cru, ulong set_rate) 406 { 407 ulong ret; 408 409 /* 410 * The gmac clock can be derived either from an external clock 411 * or can be generated from internally by a divider from SCLK_MAC. 412 */ 413 if (readl(&cru->clksel_con[43]) & GMAC_MUX_SEL_EXTCLK) { 414 /* An external clock will always generate the right rate... */ 415 ret = set_rate; 416 } else { 417 u32 con = readl(&cru->clksel_con[43]); 418 ulong pll_rate; 419 u8 div; 420 421 if (((con >> GMAC_PLL_SHIFT) & GMAC_PLL_MASK) == 422 GMAC_PLL_SELECT_GENERAL) 423 pll_rate = GPLL_HZ; 424 else if (((con >> GMAC_PLL_SHIFT) & GMAC_PLL_MASK) == 425 GMAC_PLL_SELECT_CODEC) 426 pll_rate = CPLL_HZ; 427 else 428 /* CPLL is not set */ 429 return -EPERM; 430 431 div = DIV_ROUND_UP(pll_rate, set_rate) - 1; 432 if (div <= 0x1f) 433 rk_clrsetreg(&cru->clksel_con[43], GMAC_DIV_CON_MASK, 434 div << GMAC_DIV_CON_SHIFT); 435 else 436 debug("Unsupported div for gmac:%d\n", div); 437 438 return DIV_TO_RATE(pll_rate, div); 439 } 440 441 return ret; 442 } 443 #endif 444 445 /* 446 * RK3368 SPI clocks have a common divider-width (7 bits) and a single bit 447 * to select either CPLL or GPLL as the clock-parent. The location within 448 * the enclosing CLKSEL_CON (i.e. div_shift and sel_shift) are variable. 449 */ 450 451 struct spi_clkreg { 452 uint8_t reg; /* CLKSEL_CON[reg] register in CRU */ 453 uint8_t div_shift; 454 uint8_t sel_shift; 455 }; 456 457 /* 458 * The entries are numbered relative to their offset from SCLK_SPI0. 459 */ 460 static const struct spi_clkreg spi_clkregs[] = { 461 [0] = { .reg = 45, .div_shift = 0, .sel_shift = 7, }, 462 [1] = { .reg = 45, .div_shift = 8, .sel_shift = 15, }, 463 [2] = { .reg = 46, .div_shift = 8, .sel_shift = 15, }, 464 }; 465 466 static inline u32 extract_bits(u32 val, unsigned width, unsigned shift) 467 { 468 return (val >> shift) & ((1 << width) - 1); 469 } 470 471 static ulong rk3368_spi_get_clk(struct rk3368_cru *cru, ulong clk_id) 472 { 473 const struct spi_clkreg *spiclk = NULL; 474 u32 div, val; 475 476 switch (clk_id) { 477 case SCLK_SPI0 ... SCLK_SPI2: 478 spiclk = &spi_clkregs[clk_id - SCLK_SPI0]; 479 break; 480 481 default: 482 pr_err("%s: SPI clk-id %ld not supported\n", __func__, clk_id); 483 return -EINVAL; 484 } 485 486 val = readl(&cru->clksel_con[spiclk->reg]); 487 div = extract_bits(val, 7, spiclk->div_shift); 488 489 debug("%s: div 0x%x\n", __func__, div); 490 return DIV_TO_RATE(GPLL_HZ, div); 491 } 492 493 static ulong rk3368_spi_set_clk(struct rk3368_cru *cru, ulong clk_id, uint hz) 494 { 495 const struct spi_clkreg *spiclk = NULL; 496 int src_clk_div; 497 498 src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz); 499 assert(src_clk_div < 127); 500 501 switch (clk_id) { 502 case SCLK_SPI0 ... SCLK_SPI2: 503 spiclk = &spi_clkregs[clk_id - SCLK_SPI0]; 504 break; 505 506 default: 507 pr_err("%s: SPI clk-id %ld not supported\n", __func__, clk_id); 508 return -EINVAL; 509 } 510 511 rk_clrsetreg(&cru->clksel_con[spiclk->reg], 512 ((0x7f << spiclk->div_shift) | 513 (0x1 << spiclk->sel_shift)), 514 ((src_clk_div << spiclk->div_shift) | 515 (1 << spiclk->sel_shift))); 516 517 return rk3368_spi_get_clk(cru, clk_id); 518 } 519 520 static ulong rk3368_saradc_get_clk(struct rk3368_cru *cru) 521 { 522 u32 div, val; 523 524 val = readl(&cru->clksel_con[25]); 525 div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT, 526 CLK_SARADC_DIV_CON_WIDTH); 527 528 return DIV_TO_RATE(OSC_HZ, div); 529 } 530 531 static ulong rk3368_saradc_set_clk(struct rk3368_cru *cru, uint hz) 532 { 533 int src_clk_div; 534 535 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1; 536 assert(src_clk_div < 128); 537 538 rk_clrsetreg(&cru->clksel_con[25], 539 CLK_SARADC_DIV_CON_MASK, 540 src_clk_div << CLK_SARADC_DIV_CON_SHIFT); 541 542 return rk3368_saradc_get_clk(cru); 543 } 544 545 static ulong rk3368_bus_get_clk(struct rk3368_cru *cru, ulong clk_id) 546 { 547 u32 div, con, parent; 548 549 switch (clk_id) { 550 case ACLK_BUS: 551 con = readl(&cru->clksel_con[8]); 552 div = (con & ACLK_BUS_DIV_CON_MASK) >> ACLK_BUS_DIV_CON_SHIFT; 553 parent = rkclk_pll_get_rate(cru, GPLL); 554 break; 555 case HCLK_BUS: 556 con = readl(&cru->clksel_con[8]); 557 div = (con & HCLK_BUS_DIV_CON_MASK) >> HCLK_BUS_DIV_CON_SHIFT; 558 parent = rk3368_bus_get_clk(cru, ACLK_BUS); 559 break; 560 case PCLK_BUS: 561 case PCLK_PWM0: 562 case PCLK_PWM1: 563 case PCLK_I2C0: 564 case PCLK_I2C1: 565 con = readl(&cru->clksel_con[8]); 566 div = (con & PCLK_BUS_DIV_CON_MASK) >> PCLK_BUS_DIV_CON_SHIFT; 567 parent = rk3368_bus_get_clk(cru, ACLK_BUS); 568 break; 569 default: 570 return -ENOENT; 571 } 572 573 return DIV_TO_RATE(parent, div); 574 } 575 576 static ulong rk3368_bus_set_clk(struct rk3368_cru *cru, 577 ulong clk_id, ulong hz) 578 { 579 int src_clk_div; 580 581 /* 582 * select gpll as pd_bus bus clock source and 583 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 584 */ 585 switch (clk_id) { 586 case ACLK_BUS: 587 src_clk_div = DIV_ROUND_UP(rkclk_pll_get_rate(cru, GPLL), hz); 588 assert(src_clk_div - 1 < 31); 589 rk_clrsetreg(&cru->clksel_con[8], 590 CLK_BUS_PLL_SEL_MASK | ACLK_BUS_DIV_CON_MASK, 591 CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT | 592 (src_clk_div - 1) << ACLK_BUS_DIV_CON_SHIFT); 593 break; 594 case HCLK_BUS: 595 src_clk_div = DIV_ROUND_UP(rk3368_bus_get_clk(cru, 596 ACLK_BUS), 597 hz); 598 assert(src_clk_div - 1 < 3); 599 rk_clrsetreg(&cru->clksel_con[8], 600 HCLK_BUS_DIV_CON_MASK, 601 (src_clk_div - 1) << HCLK_BUS_DIV_CON_SHIFT); 602 break; 603 case PCLK_BUS: 604 src_clk_div = DIV_ROUND_UP(rk3368_bus_get_clk(cru, 605 ACLK_BUS), 606 hz); 607 assert(src_clk_div - 1 < 3); 608 rk_clrsetreg(&cru->clksel_con[8], 609 PCLK_BUS_DIV_CON_MASK, 610 (src_clk_div - 1) << PCLK_BUS_DIV_CON_SHIFT); 611 break; 612 default: 613 printf("do not support this bus freq\n"); 614 return -EINVAL; 615 } 616 return rk3368_bus_get_clk(cru, clk_id); 617 } 618 619 static ulong rk3368_peri_get_clk(struct rk3368_cru *cru, ulong clk_id) 620 { 621 u32 div, con, parent; 622 623 switch (clk_id) { 624 case ACLK_PERI: 625 con = readl(&cru->clksel_con[9]); 626 div = (con & ACLK_PERI_DIV_CON_MASK) >> ACLK_PERI_DIV_CON_SHIFT; 627 parent = rkclk_pll_get_rate(cru, GPLL); 628 break; 629 case HCLK_PERI: 630 con = readl(&cru->clksel_con[9]); 631 div = (con & HCLK_PERI_DIV_CON_MASK) >> HCLK_PERI_DIV_CON_SHIFT; 632 parent = rk3368_peri_get_clk(cru, ACLK_PERI); 633 break; 634 case PCLK_PERI: 635 case PCLK_I2C2: 636 case PCLK_I2C3: 637 case PCLK_I2C4: 638 case PCLK_I2C5: 639 con = readl(&cru->clksel_con[9]); 640 div = (con & PCLK_PERI_DIV_CON_MASK) >> PCLK_PERI_DIV_CON_SHIFT; 641 parent = rk3368_peri_get_clk(cru, ACLK_PERI); 642 break; 643 default: 644 return -ENOENT; 645 } 646 647 return DIV_TO_RATE(parent, div); 648 } 649 650 static ulong rk3368_peri_set_clk(struct rk3368_cru *cru, 651 ulong clk_id, ulong hz) 652 { 653 int src_clk_div; 654 655 /* 656 * select gpll as pd_bus bus clock source and 657 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 658 */ 659 switch (clk_id) { 660 case ACLK_PERI: 661 src_clk_div = DIV_ROUND_UP(rkclk_pll_get_rate(cru, GPLL), hz); 662 assert(src_clk_div - 1 < 31); 663 rk_clrsetreg(&cru->clksel_con[9], 664 CLK_PERI_PLL_SEL_MASK | ACLK_PERI_DIV_CON_MASK, 665 CLK_PERI_PLL_SEL_GPLL << CLK_PERI_PLL_SEL_SHIFT | 666 (src_clk_div - 1) << ACLK_PERI_DIV_CON_SHIFT); 667 break; 668 case HCLK_PERI: 669 src_clk_div = DIV_ROUND_UP(rk3368_peri_get_clk(cru, 670 ACLK_PERI), 671 hz); 672 assert(src_clk_div - 1 < 3); 673 rk_clrsetreg(&cru->clksel_con[9], 674 HCLK_PERI_DIV_CON_MASK, 675 (src_clk_div - 1) << HCLK_PERI_DIV_CON_SHIFT); 676 break; 677 case PCLK_PERI: 678 src_clk_div = DIV_ROUND_UP(rk3368_peri_get_clk(cru, 679 ACLK_PERI), 680 hz); 681 assert(src_clk_div - 1 < 3); 682 rk_clrsetreg(&cru->clksel_con[9], 683 PCLK_PERI_DIV_CON_MASK, 684 (src_clk_div - 1) << PCLK_PERI_DIV_CON_SHIFT); 685 break; 686 default: 687 printf("do not support this bus freq\n"); 688 return -EINVAL; 689 } 690 691 return rk3368_peri_get_clk(cru, clk_id); 692 } 693 694 #if !defined(CONFIG_SPL_BUILD) 695 static ulong rk3368_vop_get_clk(struct rk3368_cru *cru, int clk_id) 696 { 697 u32 div, con, parent, sel; 698 699 switch (clk_id) { 700 case DCLK_VOP: 701 con = readl(&cru->clksel_con[20]); 702 div = con & DCLK_VOP_DIV_MASK; 703 parent = rkclk_pll_get_rate(cru, NPLL); 704 break; 705 case ACLK_VOP: 706 con = readl(&cru->clksel_con[19]); 707 div = con & ACLK_VOP_DIV_MASK; 708 sel = (con & (ACLK_VOP_PLL_SEL_MASK << 709 ACLK_VOP_PLL_SEL_SHIFT)) >> 710 ACLK_VOP_PLL_SEL_SHIFT; 711 if (sel == ACLK_VOP_PLL_SEL_CPLL) 712 parent = rkclk_pll_get_rate(cru, CPLL); 713 else if (ACLK_VOP_PLL_SEL_GPLL) 714 parent = rkclk_pll_get_rate(cru, GPLL); 715 else 716 parent = 480000000; 717 break; 718 default: 719 return -EINVAL; 720 } 721 722 return DIV_TO_RATE(parent, div); 723 } 724 725 static ulong rk3368_vop_set_clk(struct rk3368_cru *cru, int clk_id, uint hz) 726 { 727 struct pll_div npll_config = {0}; 728 u32 lcdc_div; 729 int ret; 730 731 switch (clk_id) { 732 case DCLK_VOP: 733 ret = pll_para_config(hz, &npll_config, &lcdc_div); 734 if (ret) 735 return ret; 736 737 rkclk_set_pll(cru, NPLL, &npll_config); 738 739 /* vop dclk source clk: npll,dclk_div: 1 */ 740 rk_clrsetreg(&cru->clksel_con[20], 741 (DCLK_VOP_PLL_SEL_MASK << DCLK_VOP_PLL_SEL_SHIFT) | 742 (DCLK_VOP_DIV_MASK << DCLK_VOP_DIV_SHIFT), 743 (DCLK_VOP_PLL_SEL_NPLL << DCLK_VOP_PLL_SEL_SHIFT) | 744 (lcdc_div - 1) << DCLK_VOP_DIV_SHIFT); 745 break; 746 case ACLK_VOP: 747 if ((rkclk_pll_get_rate(cru, CPLL) % hz) == 0) { 748 lcdc_div = rkclk_pll_get_rate(cru, CPLL) / hz; 749 rk_clrsetreg(&cru->clksel_con[19], 750 (ACLK_VOP_PLL_SEL_MASK << 751 ACLK_VOP_PLL_SEL_SHIFT) | 752 (ACLK_VOP_DIV_MASK << 753 ACLK_VOP_DIV_SHIFT), 754 (ACLK_VOP_PLL_SEL_CPLL << 755 ACLK_VOP_PLL_SEL_SHIFT) | 756 (lcdc_div - 1) << 757 ACLK_VOP_DIV_SHIFT); 758 } else { 759 lcdc_div = rkclk_pll_get_rate(cru, GPLL) / hz; 760 rk_clrsetreg(&cru->clksel_con[19], 761 (ACLK_VOP_PLL_SEL_MASK << 762 ACLK_VOP_PLL_SEL_SHIFT) | 763 (ACLK_VOP_DIV_MASK << 764 ACLK_VOP_DIV_SHIFT), 765 (ACLK_VOP_PLL_SEL_GPLL << 766 ACLK_VOP_PLL_SEL_SHIFT) | 767 (lcdc_div - 1) << 768 ACLK_VOP_DIV_SHIFT); 769 } 770 break; 771 default: 772 return -EINVAL; 773 } 774 775 return 0; 776 } 777 778 static ulong rk3368_alive_get_clk(struct rk3368_clk_priv *priv) 779 { 780 struct rk3368_cru *cru = priv->cru; 781 u32 div, con, parent; 782 783 con = readl(&cru->clksel_con[10]); 784 div = (con & PCLK_ALIVE_DIV_CON_MASK) >> 785 PCLK_ALIVE_DIV_CON_SHIFT; 786 parent = GPLL_HZ; 787 return DIV_TO_RATE(parent, div); 788 } 789 790 static ulong rk3368_crypto_get_rate(struct rk3368_clk_priv *priv) 791 { 792 struct rk3368_cru *cru = priv->cru; 793 u32 div, val; 794 795 val = readl(&cru->clksel_con[10]); 796 div = (val & CLK_CRYPTO_DIV_CON_MASK) >> CLK_CRYPTO_DIV_CON_SHIFT; 797 798 return DIV_TO_RATE(rk3368_bus_get_clk(priv->cru, ACLK_BUS), div); 799 } 800 801 static ulong rk3368_crypto_set_rate(struct rk3368_clk_priv *priv, 802 uint hz) 803 { 804 struct rk3368_cru *cru = priv->cru; 805 int src_clk_div; 806 uint p_rate; 807 808 p_rate = rk3368_bus_get_clk(priv->cru, ACLK_BUS); 809 src_clk_div = DIV_ROUND_UP(p_rate, hz) - 1; 810 assert(src_clk_div < 3); 811 812 rk_clrsetreg(&cru->clksel_con[10], 813 CLK_CRYPTO_DIV_CON_MASK, 814 src_clk_div << CLK_CRYPTO_DIV_CON_SHIFT); 815 816 return rk3368_crypto_get_rate(priv); 817 } 818 #endif 819 820 static ulong rk3368_armclk_set_clk(struct rk3368_clk_priv *priv, 821 int clk_id, ulong hz) 822 { 823 struct rk3368_cru *cru = priv->cru; 824 const struct rockchip_cpu_rate_table *rate; 825 struct pll_div pll_config = {0}; 826 ulong old_rate; 827 u32 pll_div, pll_id, con_id; 828 int ret; 829 830 rate = rockchip_get_cpu_settings(rk3368_cpu_rates, hz); 831 if (!rate) { 832 printf("%s unsupported rate\n", __func__); 833 return -EINVAL; 834 } 835 836 /* 837 * select apll as cpu/core clock pll source and 838 * set up dependent divisors for PERI and ACLK clocks. 839 * core hz : apll = 1:1 840 */ 841 842 ret = pll_para_config(hz, &pll_config, &pll_div); 843 if (ret) 844 return ret; 845 846 if (clk_id == ARMCLKB) { 847 old_rate = rkclk_pll_get_rate(priv->cru, APLLB); 848 pll_id = APLLB; 849 con_id = 0; 850 } else { 851 old_rate = rkclk_pll_get_rate(priv->cru, APLLL); 852 pll_id = APLLL; 853 con_id = 2; 854 } 855 856 if (old_rate > hz) { 857 ret = rkclk_set_pll(priv->cru, pll_id, &pll_config); 858 rk_clrsetreg(&cru->clksel_con[con_id], 859 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK, 860 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 861 0 << CORE_DIV_CON_SHIFT); 862 rk_clrsetreg(&cru->clksel_con[con_id + 1], 863 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK, 864 rate->aclk_div << CORE_ACLK_DIV_SHIFT | 865 rate->pclk_div << CORE_DBG_DIV_SHIFT); 866 } else if (old_rate < hz) { 867 rk_clrsetreg(&cru->clksel_con[con_id], 868 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK, 869 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 870 0 << CORE_DIV_CON_SHIFT); 871 rk_clrsetreg(&cru->clksel_con[con_id + 1], 872 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK, 873 rate->aclk_div << CORE_ACLK_DIV_SHIFT | 874 rate->pclk_div << CORE_DBG_DIV_SHIFT); 875 ret = rkclk_set_pll(priv->cru, pll_id, &pll_config); 876 } 877 878 return rkclk_pll_get_rate(priv->cru, pll_id); 879 } 880 881 static ulong rk3368_clk_get_rate(struct clk *clk) 882 { 883 struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 884 ulong rate = 0; 885 886 debug("%s: id %ld\n", __func__, clk->id); 887 switch (clk->id) { 888 case PLL_APLLB: 889 case PLL_APLLL: 890 case PLL_DPLL: 891 case PLL_CPLL: 892 case PLL_GPLL: 893 case PLL_NPLL: 894 rate = rkclk_pll_get_rate(priv->cru, clk->id - 1); 895 break; 896 case ARMCLKB: 897 rate = rkclk_pll_get_rate(priv->cru, APLLB); 898 break; 899 case ARMCLKL: 900 rate = rkclk_pll_get_rate(priv->cru, APLLL); 901 break; 902 case SCLK_SPI0 ... SCLK_SPI2: 903 rate = rk3368_spi_get_clk(priv->cru, clk->id); 904 break; 905 case ACLK_BUS: 906 case HCLK_BUS: 907 case PCLK_BUS: 908 case PCLK_PWM0: 909 case PCLK_PWM1: 910 case PCLK_I2C0: 911 case PCLK_I2C1: 912 rate = rk3368_bus_get_clk(priv->cru, clk->id); 913 break; 914 case ACLK_PERI: 915 case HCLK_PERI: 916 case PCLK_PERI: 917 case PCLK_I2C2: 918 case PCLK_I2C3: 919 case PCLK_I2C4: 920 case PCLK_I2C5: 921 rate = rk3368_peri_get_clk(priv->cru, clk->id); 922 break; 923 #if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT) 924 case HCLK_SDMMC: 925 case HCLK_EMMC: 926 rate = rk3368_mmc_get_clk(priv->cru, clk->id); 927 break; 928 #endif 929 case SCLK_SARADC: 930 rate = rk3368_saradc_get_clk(priv->cru); 931 break; 932 #if !defined(CONFIG_SPL_BUILD) 933 case ACLK_VOP: 934 case DCLK_VOP: 935 rate = rk3368_vop_get_clk(priv->cru, clk->id); 936 break; 937 case PCLK_WDT: 938 rate = rk3368_alive_get_clk(priv); 939 break; 940 case SCLK_CRYPTO: 941 rate = rk3368_crypto_get_rate(priv); 942 break; 943 #endif 944 default: 945 return -ENOENT; 946 } 947 return rate; 948 } 949 950 static ulong rk3368_clk_set_rate(struct clk *clk, ulong rate) 951 { 952 __maybe_unused struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 953 struct pll_div pll_config = {0}; 954 u32 pll_div; 955 ulong ret = 0; 956 957 switch (clk->id) { 958 case PLL_APLLB: 959 case PLL_APLLL: 960 case PLL_CPLL: 961 case PLL_GPLL: 962 case PLL_NPLL: 963 ret = pll_para_config(rate, &pll_config, &pll_div); 964 if (ret) 965 return ret; 966 967 ret = rkclk_set_pll(priv->cru, clk->id - 1, &pll_config); 968 break; 969 case ARMCLKB: 970 if (priv->armbclk_hz) 971 ret = rk3368_armclk_set_clk(priv, clk->id, rate); 972 priv->armbclk_hz = rate; 973 break; 974 case ARMCLKL: 975 if (priv->armlclk_hz) 976 ret = rk3368_armclk_set_clk(priv, clk->id, rate); 977 priv->armlclk_hz = rate; 978 break; 979 case SCLK_SPI0 ... SCLK_SPI2: 980 ret = rk3368_spi_set_clk(priv->cru, clk->id, rate); 981 break; 982 #if IS_ENABLED(CONFIG_TPL_BUILD) 983 case SCLK_DDRCLK: 984 ret = rk3368_ddr_set_clk(priv->cru, rate); 985 break; 986 #endif 987 case ACLK_BUS: 988 case HCLK_BUS: 989 case PCLK_BUS: 990 rate = rk3368_bus_set_clk(priv->cru, clk->id, rate); 991 break; 992 case ACLK_PERI: 993 case HCLK_PERI: 994 case PCLK_PERI: 995 rate = rk3368_peri_set_clk(priv->cru, clk->id, rate); 996 break; 997 #if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT) 998 case HCLK_SDMMC: 999 case HCLK_EMMC: 1000 ret = rk3368_mmc_set_clk(clk, rate); 1001 break; 1002 #endif 1003 #if CONFIG_IS_ENABLED(GMAC_ROCKCHIP) 1004 case SCLK_MAC: 1005 /* select the external clock */ 1006 ret = rk3368_gmac_set_clk(priv->cru, rate); 1007 break; 1008 #endif 1009 case SCLK_SARADC: 1010 ret = rk3368_saradc_set_clk(priv->cru, rate); 1011 break; 1012 #if !defined(CONFIG_SPL_BUILD) 1013 case ACLK_VOP: 1014 case DCLK_VOP: 1015 ret = rk3368_vop_set_clk(priv->cru, clk->id, rate); 1016 break; 1017 case ACLK_CCI_PRE: 1018 ret = 0; 1019 break; 1020 case SCLK_CRYPTO: 1021 ret = rk3368_crypto_set_rate(priv, rate); 1022 break; 1023 #endif 1024 default: 1025 return -ENOENT; 1026 } 1027 1028 return ret; 1029 } 1030 1031 static int __maybe_unused rk3368_gmac_set_parent(struct clk *clk, struct clk *parent) 1032 { 1033 struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 1034 struct rk3368_cru *cru = priv->cru; 1035 const char *clock_output_name; 1036 int ret; 1037 1038 /* 1039 * If the requested parent is in the same clock-controller and 1040 * the id is SCLK_MAC ("sclk_mac"), switch to the internal 1041 * clock. 1042 */ 1043 if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC)) { 1044 debug("%s: switching GAMC to SCLK_MAC\n", __func__); 1045 rk_clrreg(&cru->clksel_con[43], GMAC_MUX_SEL_EXTCLK); 1046 return 0; 1047 } 1048 1049 /* 1050 * Otherwise, we need to check the clock-output-names of the 1051 * requested parent to see if the requested id is "ext_gmac". 1052 */ 1053 ret = dev_read_string_index(parent->dev, "clock-output-names", 1054 parent->id, &clock_output_name); 1055 if (ret < 0) 1056 return -ENODATA; 1057 1058 /* If this is "ext_gmac", switch to the external clock input */ 1059 if (!strcmp(clock_output_name, "ext_gmac")) { 1060 debug("%s: switching GMAC to external clock\n", __func__); 1061 rk_setreg(&cru->clksel_con[43], GMAC_MUX_SEL_EXTCLK); 1062 return 0; 1063 } 1064 1065 return -EINVAL; 1066 } 1067 1068 static int __maybe_unused rk3368_clk_set_parent(struct clk *clk, struct clk *parent) 1069 { 1070 switch (clk->id) { 1071 case SCLK_MAC: 1072 return rk3368_gmac_set_parent(clk, parent); 1073 } 1074 1075 debug("%s: unsupported clk %ld\n", __func__, clk->id); 1076 return -ENOENT; 1077 } 1078 1079 #define ROCKCHIP_MMC_DELAY_SEL BIT(10) 1080 #define ROCKCHIP_MMC_DEGREE_MASK 0x3 1081 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2 1082 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 1083 1084 #define PSECS_PER_SEC 1000000000000LL 1085 /* 1086 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 1087 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 1088 */ 1089 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 1090 1091 int rk3368_mmc_get_phase(struct clk *clk) 1092 { 1093 struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 1094 struct rk3368_cru *cru = priv->cru; 1095 u32 raw_value, delay_num; 1096 u16 degrees = 0; 1097 ulong rate; 1098 1099 rate = rk3368_clk_get_rate(clk); 1100 1101 if (rate < 0) 1102 return rate; 1103 1104 if (clk->id == SCLK_EMMC_SAMPLE) 1105 raw_value = readl(&cru->emmc_con[1]); 1106 else if (clk->id == SCLK_SDMMC_SAMPLE) 1107 raw_value = readl(&cru->sdmmc_con[1]); 1108 else 1109 raw_value = readl(&cru->sdio0_con[1]); 1110 1111 raw_value >>= 1; 1112 degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; 1113 1114 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 1115 /* degrees/delaynum * 10000 */ 1116 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 1117 36 * (rate / 1000000); 1118 1119 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 1120 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 1121 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 1122 } 1123 1124 return degrees % 360; 1125 } 1126 1127 int rk3368_mmc_set_phase(struct clk *clk, u32 degrees) 1128 { 1129 struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 1130 struct rk3368_cru *cru = priv->cru; 1131 u8 nineties, remainder, delay_num; 1132 u32 raw_value, delay; 1133 ulong rate; 1134 1135 rate = rk3368_clk_get_rate(clk); 1136 1137 if (rate < 0) 1138 return rate; 1139 1140 nineties = degrees / 90; 1141 remainder = (degrees % 90); 1142 1143 /* 1144 * Convert to delay; do a little extra work to make sure we 1145 * don't overflow 32-bit / 64-bit numbers. 1146 */ 1147 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 1148 delay *= remainder; 1149 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 1150 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 1151 1152 delay_num = (u8)min_t(u32, delay, 255); 1153 1154 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 1155 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 1156 raw_value |= nineties; 1157 1158 raw_value <<= 1; 1159 if (clk->id == SCLK_EMMC_SAMPLE) 1160 writel(raw_value | 0xffff0000, &cru->emmc_con[1]); 1161 else if (clk->id == SCLK_SDMMC_SAMPLE) 1162 writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]); 1163 else 1164 writel(raw_value | 0xffff0000, &cru->sdio0_con[1]); 1165 1166 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 1167 degrees, delay_num, raw_value, rk3368_mmc_get_phase(clk)); 1168 1169 return 0; 1170 } 1171 1172 static int rk3368_clk_get_phase(struct clk *clk) 1173 { 1174 int ret; 1175 1176 debug("%s %ld\n", __func__, clk->id); 1177 switch (clk->id) { 1178 case SCLK_EMMC_SAMPLE: 1179 case SCLK_SDMMC_SAMPLE: 1180 case SCLK_SDIO0_SAMPLE: 1181 ret = rk3368_mmc_get_phase(clk); 1182 break; 1183 default: 1184 return -ENOENT; 1185 } 1186 1187 return ret; 1188 } 1189 1190 static int rk3368_clk_set_phase(struct clk *clk, int degrees) 1191 { 1192 int ret; 1193 1194 debug("%s %ld\n", __func__, clk->id); 1195 switch (clk->id) { 1196 case SCLK_EMMC_SAMPLE: 1197 case SCLK_SDMMC_SAMPLE: 1198 case SCLK_SDIO0_SAMPLE: 1199 ret = rk3368_mmc_set_phase(clk, degrees); 1200 break; 1201 default: 1202 return -ENOENT; 1203 } 1204 1205 return ret; 1206 } 1207 1208 static struct clk_ops rk3368_clk_ops = { 1209 .get_rate = rk3368_clk_get_rate, 1210 .set_rate = rk3368_clk_set_rate, 1211 .get_phase = rk3368_clk_get_phase, 1212 .set_phase = rk3368_clk_set_phase, 1213 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) 1214 .set_parent = rk3368_clk_set_parent, 1215 #endif 1216 }; 1217 1218 #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 1219 static void rkclk_init(struct rk3368_cru *cru) 1220 { 1221 u32 apllb, aplll, dpll, cpll, gpll; 1222 1223 rkclk_set_pll(cru, APLLB, &apll_b_init_cfg); 1224 rkclk_set_pll(cru, APLLL, &apll_l_init_cfg); 1225 #if !defined(CONFIG_TPL_BUILD) 1226 /* 1227 * If we plan to return to the boot ROM, we can't increase the 1228 * GPLL rate from the SPL stage. 1229 */ 1230 rkclk_set_pll(cru, GPLL, &gpll_init_cfg); 1231 rkclk_set_pll(cru, CPLL, &cpll_init_cfg); 1232 #endif 1233 rk_clrsetreg(&cru->clksel_con[37], (1 << 8), 1 << 8); 1234 apllb = rkclk_pll_get_rate(cru, APLLB); 1235 aplll = rkclk_pll_get_rate(cru, APLLL); 1236 dpll = rkclk_pll_get_rate(cru, DPLL); 1237 cpll = rkclk_pll_get_rate(cru, CPLL); 1238 gpll = rkclk_pll_get_rate(cru, GPLL); 1239 1240 debug("%s apllb(%d) apll(%d) dpll(%d) cpll(%d) gpll(%d)\n", 1241 __func__, apllb, aplll, dpll, cpll, gpll); 1242 } 1243 #endif 1244 1245 static int rk3368_clk_probe(struct udevice *dev) 1246 { 1247 struct rk3368_clk_priv __maybe_unused *priv = dev_get_priv(dev); 1248 int ret; 1249 #if CONFIG_IS_ENABLED(OF_PLATDATA) 1250 struct rk3368_clk_plat *plat = dev_get_platdata(dev); 1251 1252 priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]); 1253 #endif 1254 priv->sync_kernel = false; 1255 if (!priv->armlclk_enter_hz) 1256 priv->armlclk_enter_hz = rkclk_pll_get_rate(priv->cru, APLLL); 1257 if (!priv->armbclk_enter_hz) 1258 priv->armbclk_enter_hz = rkclk_pll_get_rate(priv->cru, APLLB); 1259 #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 1260 rkclk_init(priv->cru); 1261 #endif 1262 if (!priv->armlclk_init_hz) 1263 priv->armlclk_init_hz = rkclk_pll_get_rate(priv->cru, APLLL); 1264 if (!priv->armbclk_init_hz) 1265 priv->armbclk_init_hz = rkclk_pll_get_rate(priv->cru, APLLB); 1266 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 1267 ret = clk_set_defaults(dev); 1268 if (ret) 1269 debug("%s clk_set_defaults failed %d\n", __func__, ret); 1270 else 1271 priv->sync_kernel = true; 1272 return 0; 1273 } 1274 1275 static int rk3368_clk_ofdata_to_platdata(struct udevice *dev) 1276 { 1277 #if !CONFIG_IS_ENABLED(OF_PLATDATA) 1278 struct rk3368_clk_priv *priv = dev_get_priv(dev); 1279 1280 priv->cru = dev_read_addr_ptr(dev); 1281 #endif 1282 1283 return 0; 1284 } 1285 1286 static int rk3368_clk_bind(struct udevice *dev) 1287 { 1288 int ret; 1289 struct udevice *sys_child, *sf_child; 1290 struct sysreset_reg *priv; 1291 struct softreset_reg *sf_priv; 1292 1293 /* The reset driver does not have a device node, so bind it here */ 1294 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 1295 &sys_child); 1296 if (ret) { 1297 debug("Warning: No sysreset driver: ret=%d\n", ret); 1298 } else { 1299 priv = malloc(sizeof(struct sysreset_reg)); 1300 priv->glb_srst_fst_value = offsetof(struct rk3368_cru, 1301 glb_srst_fst_val); 1302 priv->glb_srst_snd_value = offsetof(struct rk3368_cru, 1303 glb_srst_snd_val); 1304 sys_child->priv = priv; 1305 } 1306 1307 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 1308 dev_ofnode(dev), &sf_child); 1309 if (ret) { 1310 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 1311 } else { 1312 sf_priv = malloc(sizeof(struct softreset_reg)); 1313 sf_priv->sf_reset_offset = offsetof(struct rk3368_cru, 1314 softrst_con[0]); 1315 sf_priv->sf_reset_num = 15; 1316 sf_child->priv = sf_priv; 1317 } 1318 1319 return 0; 1320 } 1321 1322 static const struct udevice_id rk3368_clk_ids[] = { 1323 { .compatible = "rockchip,rk3368-cru" }, 1324 { } 1325 }; 1326 1327 U_BOOT_DRIVER(rockchip_rk3368_cru) = { 1328 .name = "rockchip_rk3368_cru", 1329 .id = UCLASS_CLK, 1330 .of_match = rk3368_clk_ids, 1331 .priv_auto_alloc_size = sizeof(struct rk3368_clk_priv), 1332 #if CONFIG_IS_ENABLED(OF_PLATDATA) 1333 .platdata_auto_alloc_size = sizeof(struct rk3368_clk_plat), 1334 #endif 1335 .ofdata_to_platdata = rk3368_clk_ofdata_to_platdata, 1336 .ops = &rk3368_clk_ops, 1337 .bind = rk3368_clk_bind, 1338 .probe = rk3368_clk_probe, 1339 }; 1340 1341 #if !defined(CONFIG_SPL_BUILD) 1342 /** 1343 * soc_clk_dump() - Print clock frequencies 1344 * Returns zero on success 1345 * 1346 * Implementation for the clk dump command. 1347 */ 1348 int soc_clk_dump(void) 1349 { 1350 struct udevice *cru_dev; 1351 struct rk3368_clk_priv *priv; 1352 const struct rk3368_clk_info *clk_dump; 1353 struct clk clk; 1354 unsigned long clk_count = ARRAY_SIZE(clks_dump); 1355 unsigned long rate; 1356 int i, ret; 1357 1358 ret = uclass_get_device_by_driver(UCLASS_CLK, 1359 DM_GET_DRIVER(rockchip_rk3368_cru), 1360 &cru_dev); 1361 if (ret) { 1362 printf("%s failed to get cru device\n", __func__); 1363 return ret; 1364 } 1365 1366 priv = dev_get_priv(cru_dev); 1367 printf("CLK: (%s. arml: enter %lu KHz, init %lu KHz, kernel %lu%s)\n", 1368 priv->sync_kernel ? "sync kernel" : "uboot", 1369 priv->armlclk_enter_hz / 1000, 1370 priv->armlclk_init_hz / 1000, 1371 priv->set_armclk_rate ? priv->armlclk_hz / 1000 : 0, 1372 priv->set_armclk_rate ? " KHz" : "N/A"); 1373 printf("CLK: (%s. armb: enter %lu KHz, init %lu KHz, kernel %lu%s)\n", 1374 priv->sync_kernel ? "sync kernel" : "uboot", 1375 priv->armbclk_enter_hz / 1000, 1376 priv->armbclk_init_hz / 1000, 1377 priv->set_armclk_rate ? priv->armlclk_hz / 1000 : 0, 1378 priv->set_armclk_rate ? " KHz" : "N/A"); 1379 for (i = 0; i < clk_count; i++) { 1380 clk_dump = &clks_dump[i]; 1381 if (clk_dump->name) { 1382 clk.id = clk_dump->id; 1383 if (clk_dump->is_cru) 1384 ret = clk_request(cru_dev, &clk); 1385 if (ret < 0) 1386 return ret; 1387 1388 rate = clk_get_rate(&clk); 1389 clk_free(&clk); 1390 if (i == 0) { 1391 if (rate < 0) 1392 printf(" %s %s\n", clk_dump->name, 1393 "unknown"); 1394 else 1395 printf(" %s %lu KHz\n", clk_dump->name, 1396 rate / 1000); 1397 } else { 1398 if (rate < 0) 1399 printf(" %s %s\n", clk_dump->name, 1400 "unknown"); 1401 else 1402 printf(" %s %lu KHz\n", clk_dump->name, 1403 rate / 1000); 1404 } 1405 } 1406 } 1407 1408 return 0; 1409 } 1410 #endif 1411