1 /* 2 * (C) Copyright 2015 Google, Inc 3 * (C) Copyright 2016 Heiko Stuebner <heiko@sntech.de> 4 * 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 <asm/io.h> 16 #include <asm/arch/clock.h> 17 #include <asm/arch/cru_rk3188.h> 18 #include <asm/arch/grf_rk3188.h> 19 #include <asm/arch/hardware.h> 20 #include <bitfield.h> 21 #include <dt-bindings/clock/rk3188-cru.h> 22 #include <dm/device-internal.h> 23 #include <dm/lists.h> 24 #include <dm/uclass-internal.h> 25 #include <linux/log2.h> 26 27 DECLARE_GLOBAL_DATA_PTR; 28 29 enum rk3188_clk_type { 30 RK3188_CRU, 31 RK3188A_CRU, 32 }; 33 34 struct rk3188_clk_plat { 35 #if CONFIG_IS_ENABLED(OF_PLATDATA) 36 struct dtd_rockchip_rk3188_cru dtd; 37 #endif 38 }; 39 40 struct pll_div { 41 u32 nr; 42 u32 nf; 43 u32 no; 44 }; 45 46 enum { 47 VCO_MAX_HZ = 2200U * 1000000, 48 VCO_MIN_HZ = 440 * 1000000, 49 OUTPUT_MAX_HZ = 2200U * 1000000, 50 OUTPUT_MIN_HZ = 30 * 1000000, 51 FREF_MAX_HZ = 2200U * 1000000, 52 FREF_MIN_HZ = 30 * 1000, 53 }; 54 55 enum { 56 /* PLL CON0 */ 57 PLL_OD_MASK = 0x0f, 58 59 /* PLL CON1 */ 60 PLL_NF_MASK = 0x1fff, 61 62 /* PLL CON2 */ 63 PLL_BWADJ_MASK = 0x0fff, 64 65 /* PLL CON3 */ 66 PLL_RESET_SHIFT = 5, 67 68 /* GRF_SOC_STATUS0 */ 69 SOCSTS_DPLL_LOCK = 1 << 5, 70 SOCSTS_APLL_LOCK = 1 << 6, 71 SOCSTS_CPLL_LOCK = 1 << 7, 72 SOCSTS_GPLL_LOCK = 1 << 8, 73 }; 74 75 #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1)) 76 77 #define PLL_DIVISORS(hz, _nr, _no) {\ 78 .nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no};\ 79 _Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\ 80 (_nr * _no) == hz, #hz "Hz cannot be hit with PLL "\ 81 "divisors on line " __stringify(__LINE__)); 82 83 /* Keep divisors as low as possible to reduce jitter and power usage */ 84 #ifdef CONFIG_SPL_BUILD 85 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2); 86 static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2); 87 #endif 88 89 static int rkclk_set_pll(struct rk3188_cru *cru, enum rk_clk_id clk_id, 90 const struct pll_div *div, bool has_bwadj) 91 { 92 int pll_id = rk_pll_id(clk_id); 93 struct rk3188_pll *pll = &cru->pll[pll_id]; 94 /* All PLLs have same VCO and output frequency range restrictions. */ 95 uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000; 96 uint output_hz = vco_hz / div->no; 97 98 debug("PLL at %x: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n", 99 (uint)pll, div->nf, div->nr, div->no, vco_hz, output_hz); 100 assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ && 101 output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ && 102 (div->no == 1 || !(div->no % 2))); 103 104 /* enter reset */ 105 rk_setreg(&pll->con3, 1 << PLL_RESET_SHIFT); 106 107 rk_clrsetreg(&pll->con0, 108 CLKR_MASK << CLKR_SHIFT | PLL_OD_MASK, 109 ((div->nr - 1) << CLKR_SHIFT) | (div->no - 1)); 110 rk_clrsetreg(&pll->con1, CLKF_MASK, div->nf - 1); 111 112 if (has_bwadj) 113 rk_clrsetreg(&pll->con2, PLL_BWADJ_MASK, (div->nf >> 1) - 1); 114 115 udelay(10); 116 117 /* return from reset */ 118 rk_clrreg(&pll->con3, 1 << PLL_RESET_SHIFT); 119 120 return 0; 121 } 122 123 static int rkclk_configure_ddr(struct rk3188_cru *cru, struct rk3188_grf *grf, 124 unsigned int hz, bool has_bwadj) 125 { 126 static const struct pll_div dpll_cfg[] = { 127 {.nf = 25, .nr = 2, .no = 1}, 128 {.nf = 400, .nr = 9, .no = 2}, 129 {.nf = 500, .nr = 9, .no = 2}, 130 {.nf = 100, .nr = 3, .no = 1}, 131 }; 132 int cfg; 133 134 switch (hz) { 135 case 300000000: 136 cfg = 0; 137 break; 138 case 533000000: /* actually 533.3P MHz */ 139 cfg = 1; 140 break; 141 case 666000000: /* actually 666.6P MHz */ 142 cfg = 2; 143 break; 144 case 800000000: 145 cfg = 3; 146 break; 147 default: 148 debug("Unsupported SDRAM frequency"); 149 return -EINVAL; 150 } 151 152 /* pll enter slow-mode */ 153 rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK << DPLL_MODE_SHIFT, 154 DPLL_MODE_SLOW << DPLL_MODE_SHIFT); 155 156 rkclk_set_pll(cru, CLK_DDR, &dpll_cfg[cfg], has_bwadj); 157 158 /* wait for pll lock */ 159 while (!(readl(&grf->soc_status0) & SOCSTS_DPLL_LOCK)) 160 udelay(1); 161 162 /* PLL enter normal-mode */ 163 rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK << DPLL_MODE_SHIFT, 164 DPLL_MODE_NORMAL << DPLL_MODE_SHIFT); 165 166 return 0; 167 } 168 169 static int rkclk_configure_cpu(struct rk3188_cru *cru, struct rk3188_grf *grf, 170 unsigned int hz, bool has_bwadj) 171 { 172 static const struct pll_div apll_cfg[] = { 173 {.nf = 50, .nr = 1, .no = 2}, 174 {.nf = 67, .nr = 1, .no = 1}, 175 }; 176 int div_core_peri, div_aclk_core, cfg; 177 178 /* 179 * We support two possible frequencies, the safe 600MHz 180 * which will work with default pmic settings and will 181 * be set in SPL to get away from the 24MHz default and 182 * the maximum of 1.6Ghz, which boards can set if they 183 * were able to get pmic support for it. 184 */ 185 switch (hz) { 186 case APLL_SAFE_HZ: 187 cfg = 0; 188 div_core_peri = 1; 189 div_aclk_core = 3; 190 break; 191 case APLL_HZ: 192 cfg = 1; 193 div_core_peri = 2; 194 div_aclk_core = 3; 195 break; 196 default: 197 debug("Unsupported ARMCLK frequency"); 198 return -EINVAL; 199 } 200 201 /* pll enter slow-mode */ 202 rk_clrsetreg(&cru->cru_mode_con, APLL_MODE_MASK << APLL_MODE_SHIFT, 203 APLL_MODE_SLOW << APLL_MODE_SHIFT); 204 205 rkclk_set_pll(cru, CLK_ARM, &apll_cfg[cfg], has_bwadj); 206 207 /* waiting for pll lock */ 208 while (!(readl(&grf->soc_status0) & SOCSTS_APLL_LOCK)) 209 udelay(1); 210 211 /* Set divider for peripherals attached to the cpu core. */ 212 rk_clrsetreg(&cru->cru_clksel_con[0], 213 CORE_PERI_DIV_MASK << CORE_PERI_DIV_SHIFT, 214 div_core_peri << CORE_PERI_DIV_SHIFT); 215 216 /* set up dependent divisor for aclk_core */ 217 rk_clrsetreg(&cru->cru_clksel_con[1], 218 CORE_ACLK_DIV_MASK << CORE_ACLK_DIV_SHIFT, 219 div_aclk_core << CORE_ACLK_DIV_SHIFT); 220 221 /* PLL enter normal-mode */ 222 rk_clrsetreg(&cru->cru_mode_con, APLL_MODE_MASK << APLL_MODE_SHIFT, 223 APLL_MODE_NORMAL << APLL_MODE_SHIFT); 224 225 return hz; 226 } 227 228 /* Get pll rate by id */ 229 static uint32_t rkclk_pll_get_rate(struct rk3188_cru *cru, 230 enum rk_clk_id clk_id) 231 { 232 uint32_t nr, no, nf; 233 uint32_t con; 234 int pll_id = rk_pll_id(clk_id); 235 struct rk3188_pll *pll = &cru->pll[pll_id]; 236 static u8 clk_shift[CLK_COUNT] = { 237 0xff, APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT, 238 GPLL_MODE_SHIFT 239 }; 240 uint shift; 241 242 con = readl(&cru->cru_mode_con); 243 shift = clk_shift[clk_id]; 244 switch ((con >> shift) & APLL_MODE_MASK) { 245 case APLL_MODE_SLOW: 246 return OSC_HZ; 247 case APLL_MODE_NORMAL: 248 /* normal mode */ 249 con = readl(&pll->con0); 250 no = ((con >> CLKOD_SHIFT) & CLKOD_MASK) + 1; 251 nr = ((con >> CLKR_SHIFT) & CLKR_MASK) + 1; 252 con = readl(&pll->con1); 253 nf = ((con >> CLKF_SHIFT) & CLKF_MASK) + 1; 254 255 return (24 * nf / (nr * no)) * 1000000; 256 case APLL_MODE_DEEP: 257 default: 258 return 32768; 259 } 260 } 261 262 static ulong rockchip_mmc_get_clk(struct rk3188_cru *cru, uint gclk_rate, 263 int periph) 264 { 265 uint div; 266 u32 con; 267 268 switch (periph) { 269 case HCLK_EMMC: 270 case SCLK_EMMC: 271 con = readl(&cru->cru_clksel_con[12]); 272 div = (con >> EMMC_DIV_SHIFT) & EMMC_DIV_MASK; 273 break; 274 case HCLK_SDMMC: 275 case SCLK_SDMMC: 276 con = readl(&cru->cru_clksel_con[11]); 277 div = (con >> MMC0_DIV_SHIFT) & MMC0_DIV_MASK; 278 break; 279 case HCLK_SDIO: 280 case SCLK_SDIO: 281 con = readl(&cru->cru_clksel_con[12]); 282 div = (con >> SDIO_DIV_SHIFT) & SDIO_DIV_MASK; 283 break; 284 default: 285 return -EINVAL; 286 } 287 288 return DIV_TO_RATE(gclk_rate, div) / 2; 289 } 290 291 static ulong rockchip_mmc_set_clk(struct rk3188_cru *cru, uint gclk_rate, 292 int periph, uint freq) 293 { 294 int src_clk_div; 295 296 debug("%s: gclk_rate=%u\n", __func__, gclk_rate); 297 /* mmc clock defaulg div 2 internal, need provide double in cru */ 298 src_clk_div = DIV_ROUND_UP(gclk_rate / 2, freq) - 1; 299 assert(src_clk_div <= 0x3f); 300 301 switch (periph) { 302 case HCLK_EMMC: 303 case SCLK_EMMC: 304 rk_clrsetreg(&cru->cru_clksel_con[12], 305 EMMC_DIV_MASK << EMMC_DIV_SHIFT, 306 src_clk_div << EMMC_DIV_SHIFT); 307 break; 308 case HCLK_SDMMC: 309 case SCLK_SDMMC: 310 rk_clrsetreg(&cru->cru_clksel_con[11], 311 MMC0_DIV_MASK << MMC0_DIV_SHIFT, 312 src_clk_div << MMC0_DIV_SHIFT); 313 break; 314 case HCLK_SDIO: 315 case SCLK_SDIO: 316 rk_clrsetreg(&cru->cru_clksel_con[12], 317 SDIO_DIV_MASK << SDIO_DIV_SHIFT, 318 src_clk_div << SDIO_DIV_SHIFT); 319 break; 320 default: 321 return -EINVAL; 322 } 323 324 return rockchip_mmc_get_clk(cru, gclk_rate, periph); 325 } 326 327 static ulong rockchip_spi_get_clk(struct rk3188_cru *cru, uint gclk_rate, 328 int periph) 329 { 330 uint div; 331 u32 con; 332 333 switch (periph) { 334 case SCLK_SPI0: 335 con = readl(&cru->cru_clksel_con[25]); 336 div = (con >> SPI0_DIV_SHIFT) & SPI0_DIV_MASK; 337 break; 338 case SCLK_SPI1: 339 con = readl(&cru->cru_clksel_con[25]); 340 div = (con >> SPI1_DIV_SHIFT) & SPI1_DIV_MASK; 341 break; 342 default: 343 return -EINVAL; 344 } 345 346 return DIV_TO_RATE(gclk_rate, div); 347 } 348 349 static ulong rockchip_spi_set_clk(struct rk3188_cru *cru, uint gclk_rate, 350 int periph, uint freq) 351 { 352 int src_clk_div = DIV_ROUND_UP(gclk_rate, freq) - 1; 353 354 assert(src_clk_div < 128); 355 switch (periph) { 356 case SCLK_SPI0: 357 assert(src_clk_div <= SPI0_DIV_MASK); 358 rk_clrsetreg(&cru->cru_clksel_con[25], 359 SPI0_DIV_MASK << SPI0_DIV_SHIFT, 360 src_clk_div << SPI0_DIV_SHIFT); 361 break; 362 case SCLK_SPI1: 363 assert(src_clk_div <= SPI1_DIV_MASK); 364 rk_clrsetreg(&cru->cru_clksel_con[25], 365 SPI1_DIV_MASK << SPI1_DIV_SHIFT, 366 src_clk_div << SPI1_DIV_SHIFT); 367 break; 368 default: 369 return -EINVAL; 370 } 371 372 return rockchip_spi_get_clk(cru, gclk_rate, periph); 373 } 374 375 static ulong rk3188_saradc_get_clk(struct rk3188_cru *cru) 376 { 377 u32 div, val; 378 379 val = readl(&cru->cru_clksel_con[24]); 380 div = bitfield_extract(val, SARADC_DIV_SHIFT, SARADC_DIV_WIDTH); 381 382 return DIV_TO_RATE(OSC_HZ, div); 383 } 384 385 static ulong rk3188_saradc_set_clk(struct rk3188_cru *cru, uint hz) 386 { 387 int src_clk_div; 388 389 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1; 390 assert(src_clk_div < 128); 391 392 rk_clrsetreg(&cru->cru_clksel_con[24], 393 SARADC_DIV_MASK, 394 src_clk_div << SARADC_DIV_SHIFT); 395 396 return rk3188_saradc_get_clk(cru); 397 } 398 399 #ifdef CONFIG_SPL_BUILD 400 static void rkclk_init(struct rk3188_cru *cru, struct rk3188_grf *grf, 401 bool has_bwadj) 402 { 403 u32 aclk_div, hclk_div, pclk_div, h2p_div; 404 405 /* pll enter slow-mode */ 406 rk_clrsetreg(&cru->cru_mode_con, 407 GPLL_MODE_MASK << GPLL_MODE_SHIFT | 408 CPLL_MODE_MASK << CPLL_MODE_SHIFT, 409 GPLL_MODE_SLOW << GPLL_MODE_SHIFT | 410 CPLL_MODE_SLOW << CPLL_MODE_SHIFT); 411 412 /* init pll */ 413 rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg, has_bwadj); 414 rkclk_set_pll(cru, CLK_CODEC, &cpll_init_cfg, has_bwadj); 415 416 /* waiting for pll lock */ 417 while ((readl(&grf->soc_status0) & 418 (SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK)) != 419 (SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK)) 420 udelay(1); 421 422 /* 423 * cpu clock pll source selection and 424 * reparent aclk_cpu_pre from apll to gpll 425 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 426 */ 427 aclk_div = DIV_ROUND_UP(GPLL_HZ, CPU_ACLK_HZ) - 1; 428 assert((aclk_div + 1) * CPU_ACLK_HZ == GPLL_HZ && aclk_div <= 0x1f); 429 430 rk_clrsetreg(&cru->cru_clksel_con[0], 431 CPU_ACLK_PLL_MASK << CPU_ACLK_PLL_SHIFT | 432 A9_CPU_DIV_MASK << A9_CPU_DIV_SHIFT, 433 CPU_ACLK_PLL_SELECT_GPLL << CPU_ACLK_PLL_SHIFT | 434 aclk_div << A9_CPU_DIV_SHIFT); 435 436 hclk_div = ilog2(CPU_ACLK_HZ / CPU_HCLK_HZ); 437 assert((1 << hclk_div) * CPU_HCLK_HZ == CPU_ACLK_HZ && hclk_div < 0x3); 438 pclk_div = ilog2(CPU_ACLK_HZ / CPU_PCLK_HZ); 439 assert((1 << pclk_div) * CPU_PCLK_HZ == CPU_ACLK_HZ && pclk_div < 0x4); 440 h2p_div = ilog2(CPU_HCLK_HZ / CPU_H2P_HZ); 441 assert((1 << h2p_div) * CPU_H2P_HZ == CPU_HCLK_HZ && pclk_div < 0x3); 442 443 rk_clrsetreg(&cru->cru_clksel_con[1], 444 AHB2APB_DIV_MASK << AHB2APB_DIV_SHIFT | 445 CPU_PCLK_DIV_MASK << CPU_PCLK_DIV_SHIFT | 446 CPU_HCLK_DIV_MASK << CPU_HCLK_DIV_SHIFT, 447 h2p_div << AHB2APB_DIV_SHIFT | 448 pclk_div << CPU_PCLK_DIV_SHIFT | 449 hclk_div << CPU_HCLK_DIV_SHIFT); 450 451 /* 452 * peri clock pll source selection and 453 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 454 */ 455 aclk_div = GPLL_HZ / PERI_ACLK_HZ - 1; 456 assert((aclk_div + 1) * PERI_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f); 457 458 hclk_div = ilog2(PERI_ACLK_HZ / PERI_HCLK_HZ); 459 assert((1 << hclk_div) * PERI_HCLK_HZ == 460 PERI_ACLK_HZ && (hclk_div < 0x4)); 461 462 pclk_div = ilog2(PERI_ACLK_HZ / PERI_PCLK_HZ); 463 assert((1 << pclk_div) * PERI_PCLK_HZ == 464 PERI_ACLK_HZ && (pclk_div < 0x4)); 465 466 rk_clrsetreg(&cru->cru_clksel_con[10], 467 PERI_PCLK_DIV_MASK << PERI_PCLK_DIV_SHIFT | 468 PERI_HCLK_DIV_MASK << PERI_HCLK_DIV_SHIFT | 469 PERI_ACLK_DIV_MASK << PERI_ACLK_DIV_SHIFT, 470 PERI_SEL_GPLL << PERI_SEL_PLL_SHIFT | 471 pclk_div << PERI_PCLK_DIV_SHIFT | 472 hclk_div << PERI_HCLK_DIV_SHIFT | 473 aclk_div << PERI_ACLK_DIV_SHIFT); 474 475 /* PLL enter normal-mode */ 476 rk_clrsetreg(&cru->cru_mode_con, 477 GPLL_MODE_MASK << GPLL_MODE_SHIFT | 478 CPLL_MODE_MASK << CPLL_MODE_SHIFT, 479 GPLL_MODE_NORMAL << GPLL_MODE_SHIFT | 480 CPLL_MODE_NORMAL << CPLL_MODE_SHIFT); 481 482 rockchip_mmc_set_clk(cru, PERI_HCLK_HZ, HCLK_SDMMC, 16000000); 483 } 484 #endif 485 486 static ulong rk3188_clk_get_rate(struct clk *clk) 487 { 488 struct rk3188_clk_priv *priv = dev_get_priv(clk->dev); 489 ulong new_rate, gclk_rate; 490 491 gclk_rate = rkclk_pll_get_rate(priv->cru, CLK_GENERAL); 492 switch (clk->id) { 493 case 1 ... 4: 494 new_rate = rkclk_pll_get_rate(priv->cru, clk->id); 495 break; 496 case HCLK_EMMC: 497 case HCLK_SDMMC: 498 case HCLK_SDIO: 499 case SCLK_EMMC: 500 case SCLK_SDMMC: 501 case SCLK_SDIO: 502 new_rate = rockchip_mmc_get_clk(priv->cru, PERI_HCLK_HZ, 503 clk->id); 504 break; 505 case SCLK_SPI0: 506 case SCLK_SPI1: 507 new_rate = rockchip_spi_get_clk(priv->cru, PERI_PCLK_HZ, 508 clk->id); 509 break; 510 case PCLK_I2C0: 511 case PCLK_I2C1: 512 case PCLK_I2C2: 513 case PCLK_I2C3: 514 case PCLK_I2C4: 515 return gclk_rate; 516 case SCLK_SARADC: 517 new_rate = rk3188_saradc_get_clk(priv->cru); 518 default: 519 return -ENOENT; 520 } 521 522 return new_rate; 523 } 524 525 static ulong rk3188_clk_set_rate(struct clk *clk, ulong rate) 526 { 527 struct rk3188_clk_priv *priv = dev_get_priv(clk->dev); 528 struct rk3188_cru *cru = priv->cru; 529 ulong new_rate; 530 531 switch (clk->id) { 532 case PLL_APLL: 533 new_rate = rkclk_configure_cpu(priv->cru, priv->grf, rate, 534 priv->has_bwadj); 535 break; 536 case CLK_DDR: 537 new_rate = rkclk_configure_ddr(priv->cru, priv->grf, rate, 538 priv->has_bwadj); 539 break; 540 case HCLK_EMMC: 541 case HCLK_SDMMC: 542 case HCLK_SDIO: 543 case SCLK_EMMC: 544 case SCLK_SDMMC: 545 case SCLK_SDIO: 546 new_rate = rockchip_mmc_set_clk(cru, PERI_HCLK_HZ, 547 clk->id, rate); 548 break; 549 case SCLK_SPI0: 550 case SCLK_SPI1: 551 new_rate = rockchip_spi_set_clk(cru, PERI_PCLK_HZ, 552 clk->id, rate); 553 break; 554 case SCLK_SARADC: 555 new_rate = rk3188_saradc_set_clk(priv->cru, rate); 556 break; 557 default: 558 return -ENOENT; 559 } 560 561 return new_rate; 562 } 563 564 static struct clk_ops rk3188_clk_ops = { 565 .get_rate = rk3188_clk_get_rate, 566 .set_rate = rk3188_clk_set_rate, 567 }; 568 569 static int rk3188_clk_ofdata_to_platdata(struct udevice *dev) 570 { 571 #if !CONFIG_IS_ENABLED(OF_PLATDATA) 572 struct rk3188_clk_priv *priv = dev_get_priv(dev); 573 574 priv->cru = (struct rk3188_cru *)devfdt_get_addr(dev); 575 #endif 576 577 return 0; 578 } 579 580 static int rk3188_clk_probe(struct udevice *dev) 581 { 582 struct rk3188_clk_priv *priv = dev_get_priv(dev); 583 enum rk3188_clk_type type = dev_get_driver_data(dev); 584 585 priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 586 if (IS_ERR(priv->grf)) 587 return PTR_ERR(priv->grf); 588 priv->has_bwadj = (type == RK3188A_CRU) ? 1 : 0; 589 590 #ifdef CONFIG_SPL_BUILD 591 #if CONFIG_IS_ENABLED(OF_PLATDATA) 592 struct rk3188_clk_plat *plat = dev_get_platdata(dev); 593 594 priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]); 595 #endif 596 597 rkclk_init(priv->cru, priv->grf, priv->has_bwadj); 598 #endif 599 600 return 0; 601 } 602 603 static int rk3188_clk_bind(struct udevice *dev) 604 { 605 int ret; 606 struct udevice *sys_child, *sf_child; 607 struct sysreset_reg *priv; 608 struct softreset_reg *sf_priv; 609 610 /* The reset driver does not have a device node, so bind it here */ 611 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 612 &sys_child); 613 if (ret) { 614 debug("Warning: No sysreset driver: ret=%d\n", ret); 615 } else { 616 priv = malloc(sizeof(struct sysreset_reg)); 617 priv->glb_srst_fst_value = offsetof(struct rk3188_cru, 618 cru_glb_srst_fst_value); 619 priv->glb_srst_snd_value = offsetof(struct rk3188_cru, 620 cru_glb_srst_snd_value); 621 sys_child->priv = priv; 622 } 623 624 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 625 dev_ofnode(dev), &sf_child); 626 if (ret) { 627 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 628 } else { 629 sf_priv = malloc(sizeof(struct softreset_reg)); 630 sf_priv->sf_reset_offset = offsetof(struct rk3188_cru, 631 cru_softrst_con[0]); 632 sf_priv->sf_reset_num = 9; 633 sf_child->priv = sf_priv; 634 } 635 636 return 0; 637 } 638 639 static const struct udevice_id rk3188_clk_ids[] = { 640 { .compatible = "rockchip,rk3188-cru", .data = RK3188_CRU }, 641 { .compatible = "rockchip,rk3188a-cru", .data = RK3188A_CRU }, 642 { } 643 }; 644 645 U_BOOT_DRIVER(rockchip_rk3188_cru) = { 646 .name = "rockchip_rk3188_cru", 647 .id = UCLASS_CLK, 648 .of_match = rk3188_clk_ids, 649 .priv_auto_alloc_size = sizeof(struct rk3188_clk_priv), 650 .platdata_auto_alloc_size = sizeof(struct rk3188_clk_plat), 651 .ops = &rk3188_clk_ops, 652 .bind = rk3188_clk_bind, 653 .ofdata_to_platdata = rk3188_clk_ofdata_to_platdata, 654 .probe = rk3188_clk_probe, 655 }; 656