1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 4 * Author: Andy Yan <andy.yan@rock-chips.com> 5 * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH 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 #if CONFIG_IS_ENABLED(OF_PLATDATA) 24 struct rk3368_clk_plat { 25 struct dtd_rockchip_rk3368_cru dtd; 26 }; 27 #endif 28 29 struct pll_div { 30 u32 nr; 31 u32 nf; 32 u32 no; 33 }; 34 35 #define OSC_HZ (24 * 1000 * 1000) 36 #define APLL_L_HZ (800 * 1000 * 1000) 37 #define APLL_B_HZ (816 * 1000 * 1000) 38 #define GPLL_HZ (576 * 1000 * 1000) 39 #define CPLL_HZ (400 * 1000 * 1000) 40 41 #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1)) 42 43 #define PLL_DIVISORS(hz, _nr, _no) { \ 44 .nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no}; \ 45 _Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\ 46 (_nr * _no) == hz, #hz "Hz cannot be hit with PLL " \ 47 "divisors on line " __stringify(__LINE__)); 48 49 #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 50 static const struct pll_div apll_l_init_cfg = PLL_DIVISORS(APLL_L_HZ, 12, 2); 51 static const struct pll_div apll_b_init_cfg = PLL_DIVISORS(APLL_B_HZ, 1, 2); 52 #if !defined(CONFIG_TPL_BUILD) 53 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 2); 54 static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 6); 55 #endif 56 #endif 57 58 static ulong rk3368_clk_get_rate(struct clk *clk); 59 60 /* Get pll rate by id */ 61 static uint32_t rkclk_pll_get_rate(struct rk3368_cru *cru, 62 enum rk3368_pll_id pll_id) 63 { 64 uint32_t nr, no, nf; 65 uint32_t con; 66 struct rk3368_pll *pll = &cru->pll[pll_id]; 67 68 con = readl(&pll->con3); 69 70 switch ((con & PLL_MODE_MASK) >> PLL_MODE_SHIFT) { 71 case PLL_MODE_SLOW: 72 return OSC_HZ; 73 case PLL_MODE_NORMAL: 74 con = readl(&pll->con0); 75 no = ((con & PLL_OD_MASK) >> PLL_OD_SHIFT) + 1; 76 nr = ((con & PLL_NR_MASK) >> PLL_NR_SHIFT) + 1; 77 con = readl(&pll->con1); 78 nf = ((con & PLL_NF_MASK) >> PLL_NF_SHIFT) + 1; 79 80 return (24 * nf / (nr * no)) * 1000000; 81 case PLL_MODE_DEEP_SLOW: 82 default: 83 return 32768; 84 } 85 } 86 87 #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 88 static int rkclk_set_pll(struct rk3368_cru *cru, enum rk3368_pll_id pll_id, 89 const struct pll_div *div) 90 { 91 struct rk3368_pll *pll = &cru->pll[pll_id]; 92 /* All PLLs have same VCO and output frequency range restrictions*/ 93 uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000; 94 uint output_hz = vco_hz / div->no; 95 96 debug("PLL at %p: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n", 97 pll, div->nf, div->nr, div->no, vco_hz, output_hz); 98 99 /* enter slow mode and reset pll */ 100 rk_clrsetreg(&pll->con3, PLL_MODE_MASK | PLL_RESET_MASK, 101 PLL_RESET << PLL_RESET_SHIFT); 102 103 rk_clrsetreg(&pll->con0, PLL_NR_MASK | PLL_OD_MASK, 104 ((div->nr - 1) << PLL_NR_SHIFT) | 105 ((div->no - 1) << PLL_OD_SHIFT)); 106 writel((div->nf - 1) << PLL_NF_SHIFT, &pll->con1); 107 /* 108 * BWADJ should be set to NF / 2 to ensure the nominal bandwidth. 109 * Compare the RK3368 TRM, section "3.6.4 PLL Bandwidth Adjustment". 110 */ 111 clrsetbits_le32(&pll->con2, PLL_BWADJ_MASK, (div->nf >> 1) - 1); 112 113 udelay(10); 114 115 /* return from reset */ 116 rk_clrreg(&pll->con3, PLL_RESET_MASK); 117 118 /* waiting for pll lock */ 119 while (!(readl(&pll->con1) & PLL_LOCK_STA)) 120 udelay(1); 121 122 rk_clrsetreg(&pll->con3, PLL_MODE_MASK, 123 PLL_MODE_NORMAL << PLL_MODE_SHIFT); 124 125 return 0; 126 } 127 #endif 128 129 #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 130 static void rkclk_init(struct rk3368_cru *cru) 131 { 132 u32 apllb, aplll, dpll, cpll, gpll; 133 134 rkclk_set_pll(cru, APLLB, &apll_b_init_cfg); 135 rkclk_set_pll(cru, APLLL, &apll_l_init_cfg); 136 #if !defined(CONFIG_TPL_BUILD) 137 /* 138 * If we plan to return to the boot ROM, we can't increase the 139 * GPLL rate from the SPL stage. 140 */ 141 rkclk_set_pll(cru, GPLL, &gpll_init_cfg); 142 rkclk_set_pll(cru, CPLL, &cpll_init_cfg); 143 #endif 144 145 apllb = rkclk_pll_get_rate(cru, APLLB); 146 aplll = rkclk_pll_get_rate(cru, APLLL); 147 dpll = rkclk_pll_get_rate(cru, DPLL); 148 cpll = rkclk_pll_get_rate(cru, CPLL); 149 gpll = rkclk_pll_get_rate(cru, GPLL); 150 151 debug("%s apllb(%d) apll(%d) dpll(%d) cpll(%d) gpll(%d)\n", 152 __func__, apllb, aplll, dpll, cpll, gpll); 153 } 154 #endif 155 156 #if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT) 157 static ulong rk3368_mmc_get_clk(struct rk3368_cru *cru, uint clk_id) 158 { 159 u32 div, con, con_id, rate; 160 u32 pll_rate; 161 162 switch (clk_id) { 163 case HCLK_SDMMC: 164 con_id = 50; 165 break; 166 case HCLK_EMMC: 167 con_id = 51; 168 break; 169 case SCLK_SDIO0: 170 con_id = 48; 171 break; 172 default: 173 return -EINVAL; 174 } 175 176 con = readl(&cru->clksel_con[con_id]); 177 switch (con & MMC_PLL_SEL_MASK) { 178 case MMC_PLL_SEL_GPLL: 179 pll_rate = rkclk_pll_get_rate(cru, GPLL); 180 break; 181 case MMC_PLL_SEL_24M: 182 pll_rate = OSC_HZ; 183 break; 184 case MMC_PLL_SEL_CPLL: 185 pll_rate = rkclk_pll_get_rate(cru, CPLL); 186 break; 187 case MMC_PLL_SEL_USBPHY_480M: 188 default: 189 return -EINVAL; 190 } 191 div = (con & MMC_CLK_DIV_MASK) >> MMC_CLK_DIV_SHIFT; 192 rate = DIV_TO_RATE(pll_rate, div); 193 194 debug("%s: raw rate %d (post-divide by 2)\n", __func__, rate); 195 return rate >> 1; 196 } 197 198 static ulong rk3368_mmc_find_best_rate_and_parent(struct clk *clk, 199 ulong rate, 200 u32 *best_mux, 201 u32 *best_div) 202 { 203 int i; 204 ulong best_rate = 0; 205 const ulong MHz = 1000000; 206 const struct { 207 u32 mux; 208 ulong rate; 209 } parents[] = { 210 { .mux = MMC_PLL_SEL_CPLL, .rate = CPLL_HZ }, 211 { .mux = MMC_PLL_SEL_GPLL, .rate = GPLL_HZ }, 212 { .mux = MMC_PLL_SEL_24M, .rate = 24 * MHz } 213 }; 214 215 debug("%s: target rate %ld\n", __func__, rate); 216 for (i = 0; i < ARRAY_SIZE(parents); ++i) { 217 /* 218 * Find the largest rate no larger than the target-rate for 219 * the current parent. 220 */ 221 ulong parent_rate = parents[i].rate; 222 u32 div = DIV_ROUND_UP(parent_rate, rate); 223 u32 adj_div = div; 224 ulong new_rate = parent_rate / adj_div; 225 226 debug("%s: rate %ld, parent-mux %d, parent-rate %ld, div %d\n", 227 __func__, rate, parents[i].mux, parents[i].rate, div); 228 229 /* Skip, if not representable */ 230 if ((div - 1) > MMC_CLK_DIV_MASK) 231 continue; 232 233 /* Skip, if we already have a better (or equal) solution */ 234 if (new_rate <= best_rate) 235 continue; 236 237 /* This is our new best rate. */ 238 best_rate = new_rate; 239 *best_mux = parents[i].mux; 240 *best_div = div - 1; 241 } 242 243 debug("%s: best_mux = %x, best_div = %d, best_rate = %ld\n", 244 __func__, *best_mux, *best_div, best_rate); 245 246 return best_rate; 247 } 248 249 static ulong rk3368_mmc_set_clk(struct clk *clk, ulong rate) 250 { 251 struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 252 struct rk3368_cru *cru = priv->cru; 253 ulong clk_id = clk->id; 254 u32 con_id, mux = 0, div = 0; 255 256 /* Find the best parent and rate */ 257 rk3368_mmc_find_best_rate_and_parent(clk, rate << 1, &mux, &div); 258 259 switch (clk_id) { 260 case HCLK_SDMMC: 261 con_id = 50; 262 break; 263 case HCLK_EMMC: 264 con_id = 51; 265 break; 266 case SCLK_SDIO0: 267 con_id = 48; 268 break; 269 default: 270 return -EINVAL; 271 } 272 273 rk_clrsetreg(&cru->clksel_con[con_id], 274 MMC_PLL_SEL_MASK | MMC_CLK_DIV_MASK, 275 mux | div); 276 277 return rk3368_mmc_get_clk(cru, clk_id); 278 } 279 #endif 280 281 #if IS_ENABLED(CONFIG_TPL_BUILD) 282 static ulong rk3368_ddr_set_clk(struct rk3368_cru *cru, ulong set_rate) 283 { 284 const struct pll_div *dpll_cfg = NULL; 285 const ulong MHz = 1000000; 286 287 /* Fout = ((Fin /NR) * NF )/ NO */ 288 static const struct pll_div dpll_1200 = PLL_DIVISORS(1200 * MHz, 1, 1); 289 static const struct pll_div dpll_1332 = PLL_DIVISORS(1332 * MHz, 2, 1); 290 static const struct pll_div dpll_1600 = PLL_DIVISORS(1600 * MHz, 3, 2); 291 292 switch (set_rate) { 293 case 1200*MHz: 294 dpll_cfg = &dpll_1200; 295 break; 296 case 1332*MHz: 297 dpll_cfg = &dpll_1332; 298 break; 299 case 1600*MHz: 300 dpll_cfg = &dpll_1600; 301 break; 302 default: 303 pr_err("Unsupported SDRAM frequency!,%ld\n", set_rate); 304 } 305 rkclk_set_pll(cru, DPLL, dpll_cfg); 306 307 return set_rate; 308 } 309 #endif 310 311 #if CONFIG_IS_ENABLED(GMAC_ROCKCHIP) 312 static ulong rk3368_gmac_set_clk(struct rk3368_cru *cru, ulong set_rate) 313 { 314 ulong ret; 315 316 /* 317 * The gmac clock can be derived either from an external clock 318 * or can be generated from internally by a divider from SCLK_MAC. 319 */ 320 if (readl(&cru->clksel_con[43]) & GMAC_MUX_SEL_EXTCLK) { 321 /* An external clock will always generate the right rate... */ 322 ret = set_rate; 323 } else { 324 u32 con = readl(&cru->clksel_con[43]); 325 ulong pll_rate; 326 u8 div; 327 328 if (((con >> GMAC_PLL_SHIFT) & GMAC_PLL_MASK) == 329 GMAC_PLL_SELECT_GENERAL) 330 pll_rate = GPLL_HZ; 331 else if (((con >> GMAC_PLL_SHIFT) & GMAC_PLL_MASK) == 332 GMAC_PLL_SELECT_CODEC) 333 pll_rate = CPLL_HZ; 334 else 335 /* CPLL is not set */ 336 return -EPERM; 337 338 div = DIV_ROUND_UP(pll_rate, set_rate) - 1; 339 if (div <= 0x1f) 340 rk_clrsetreg(&cru->clksel_con[43], GMAC_DIV_CON_MASK, 341 div << GMAC_DIV_CON_SHIFT); 342 else 343 debug("Unsupported div for gmac:%d\n", div); 344 345 return DIV_TO_RATE(pll_rate, div); 346 } 347 348 return ret; 349 } 350 #endif 351 352 /* 353 * RK3368 SPI clocks have a common divider-width (7 bits) and a single bit 354 * to select either CPLL or GPLL as the clock-parent. The location within 355 * the enclosing CLKSEL_CON (i.e. div_shift and sel_shift) are variable. 356 */ 357 358 struct spi_clkreg { 359 uint8_t reg; /* CLKSEL_CON[reg] register in CRU */ 360 uint8_t div_shift; 361 uint8_t sel_shift; 362 }; 363 364 /* 365 * The entries are numbered relative to their offset from SCLK_SPI0. 366 */ 367 static const struct spi_clkreg spi_clkregs[] = { 368 [0] = { .reg = 45, .div_shift = 0, .sel_shift = 7, }, 369 [1] = { .reg = 45, .div_shift = 8, .sel_shift = 15, }, 370 [2] = { .reg = 46, .div_shift = 8, .sel_shift = 15, }, 371 }; 372 373 static inline u32 extract_bits(u32 val, unsigned width, unsigned shift) 374 { 375 return (val >> shift) & ((1 << width) - 1); 376 } 377 378 static ulong rk3368_spi_get_clk(struct rk3368_cru *cru, ulong clk_id) 379 { 380 const struct spi_clkreg *spiclk = NULL; 381 u32 div, val; 382 383 switch (clk_id) { 384 case SCLK_SPI0 ... SCLK_SPI2: 385 spiclk = &spi_clkregs[clk_id - SCLK_SPI0]; 386 break; 387 388 default: 389 pr_err("%s: SPI clk-id %ld not supported\n", __func__, clk_id); 390 return -EINVAL; 391 } 392 393 val = readl(&cru->clksel_con[spiclk->reg]); 394 div = extract_bits(val, 7, spiclk->div_shift); 395 396 debug("%s: div 0x%x\n", __func__, div); 397 return DIV_TO_RATE(GPLL_HZ, div); 398 } 399 400 static ulong rk3368_spi_set_clk(struct rk3368_cru *cru, ulong clk_id, uint hz) 401 { 402 const struct spi_clkreg *spiclk = NULL; 403 int src_clk_div; 404 405 src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz); 406 assert(src_clk_div < 127); 407 408 switch (clk_id) { 409 case SCLK_SPI0 ... SCLK_SPI2: 410 spiclk = &spi_clkregs[clk_id - SCLK_SPI0]; 411 break; 412 413 default: 414 pr_err("%s: SPI clk-id %ld not supported\n", __func__, clk_id); 415 return -EINVAL; 416 } 417 418 rk_clrsetreg(&cru->clksel_con[spiclk->reg], 419 ((0x7f << spiclk->div_shift) | 420 (0x1 << spiclk->sel_shift)), 421 ((src_clk_div << spiclk->div_shift) | 422 (1 << spiclk->sel_shift))); 423 424 return rk3368_spi_get_clk(cru, clk_id); 425 } 426 427 static ulong rk3368_saradc_get_clk(struct rk3368_cru *cru) 428 { 429 u32 div, val; 430 431 val = readl(&cru->clksel_con[25]); 432 div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT, 433 CLK_SARADC_DIV_CON_WIDTH); 434 435 return DIV_TO_RATE(OSC_HZ, div); 436 } 437 438 static ulong rk3368_saradc_set_clk(struct rk3368_cru *cru, uint hz) 439 { 440 int src_clk_div; 441 442 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1; 443 assert(src_clk_div < 128); 444 445 rk_clrsetreg(&cru->clksel_con[25], 446 CLK_SARADC_DIV_CON_MASK, 447 src_clk_div << CLK_SARADC_DIV_CON_SHIFT); 448 449 return rk3368_saradc_get_clk(cru); 450 } 451 452 static ulong rk3368_clk_get_rate(struct clk *clk) 453 { 454 struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 455 ulong rate = 0; 456 457 debug("%s: id %ld\n", __func__, clk->id); 458 switch (clk->id) { 459 case PLL_CPLL: 460 rate = rkclk_pll_get_rate(priv->cru, CPLL); 461 break; 462 case PLL_GPLL: 463 rate = rkclk_pll_get_rate(priv->cru, GPLL); 464 break; 465 case SCLK_SPI0 ... SCLK_SPI2: 466 rate = rk3368_spi_get_clk(priv->cru, clk->id); 467 break; 468 #if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT) 469 case HCLK_SDMMC: 470 case HCLK_EMMC: 471 rate = rk3368_mmc_get_clk(priv->cru, clk->id); 472 break; 473 #endif 474 case SCLK_SARADC: 475 rate = rk3368_saradc_get_clk(priv->cru); 476 break; 477 default: 478 return -ENOENT; 479 } 480 481 return rate; 482 } 483 484 static ulong rk3368_clk_set_rate(struct clk *clk, ulong rate) 485 { 486 __maybe_unused struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 487 ulong ret = 0; 488 489 debug("%s id:%ld rate:%ld\n", __func__, clk->id, rate); 490 switch (clk->id) { 491 case SCLK_SPI0 ... SCLK_SPI2: 492 ret = rk3368_spi_set_clk(priv->cru, clk->id, rate); 493 break; 494 #if IS_ENABLED(CONFIG_TPL_BUILD) 495 case CLK_DDR: 496 ret = rk3368_ddr_set_clk(priv->cru, rate); 497 break; 498 #endif 499 #if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT) 500 case HCLK_SDMMC: 501 case HCLK_EMMC: 502 ret = rk3368_mmc_set_clk(clk, rate); 503 break; 504 #endif 505 #if CONFIG_IS_ENABLED(GMAC_ROCKCHIP) 506 case SCLK_MAC: 507 /* select the external clock */ 508 ret = rk3368_gmac_set_clk(priv->cru, rate); 509 break; 510 #endif 511 case SCLK_SARADC: 512 ret = rk3368_saradc_set_clk(priv->cru, rate); 513 break; 514 default: 515 return -ENOENT; 516 } 517 518 return ret; 519 } 520 521 static int __maybe_unused rk3368_gmac_set_parent(struct clk *clk, struct clk *parent) 522 { 523 struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 524 struct rk3368_cru *cru = priv->cru; 525 const char *clock_output_name; 526 int ret; 527 528 /* 529 * If the requested parent is in the same clock-controller and 530 * the id is SCLK_MAC ("sclk_mac"), switch to the internal 531 * clock. 532 */ 533 if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC)) { 534 debug("%s: switching GAMC to SCLK_MAC\n", __func__); 535 rk_clrreg(&cru->clksel_con[43], GMAC_MUX_SEL_EXTCLK); 536 return 0; 537 } 538 539 /* 540 * Otherwise, we need to check the clock-output-names of the 541 * requested parent to see if the requested id is "ext_gmac". 542 */ 543 ret = dev_read_string_index(parent->dev, "clock-output-names", 544 parent->id, &clock_output_name); 545 if (ret < 0) 546 return -ENODATA; 547 548 /* If this is "ext_gmac", switch to the external clock input */ 549 if (!strcmp(clock_output_name, "ext_gmac")) { 550 debug("%s: switching GMAC to external clock\n", __func__); 551 rk_setreg(&cru->clksel_con[43], GMAC_MUX_SEL_EXTCLK); 552 return 0; 553 } 554 555 return -EINVAL; 556 } 557 558 static int __maybe_unused rk3368_clk_set_parent(struct clk *clk, struct clk *parent) 559 { 560 switch (clk->id) { 561 case SCLK_MAC: 562 return rk3368_gmac_set_parent(clk, parent); 563 } 564 565 debug("%s: unsupported clk %ld\n", __func__, clk->id); 566 return -ENOENT; 567 } 568 569 static int rk3368_clk_enable(struct clk *clk) 570 { 571 switch (clk->id) { 572 case SCLK_MAC: 573 case SCLK_MAC_RX: 574 case SCLK_MAC_TX: 575 case SCLK_MACREF: 576 case SCLK_MACREF_OUT: 577 case ACLK_GMAC: 578 case PCLK_GMAC: 579 /* Required to successfully probe the Designware GMAC driver */ 580 return 0; 581 } 582 583 debug("%s: unsupported clk %ld\n", __func__, clk->id); 584 return -ENOENT; 585 } 586 587 static struct clk_ops rk3368_clk_ops = { 588 .get_rate = rk3368_clk_get_rate, 589 .set_rate = rk3368_clk_set_rate, 590 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) 591 .set_parent = rk3368_clk_set_parent, 592 #endif 593 .enable = rk3368_clk_enable, 594 }; 595 596 static int rk3368_clk_probe(struct udevice *dev) 597 { 598 struct rk3368_clk_priv __maybe_unused *priv = dev_get_priv(dev); 599 #if CONFIG_IS_ENABLED(OF_PLATDATA) 600 struct rk3368_clk_plat *plat = dev_get_platdata(dev); 601 602 priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]); 603 #endif 604 #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 605 rkclk_init(priv->cru); 606 #endif 607 608 return 0; 609 } 610 611 static int rk3368_clk_ofdata_to_platdata(struct udevice *dev) 612 { 613 #if !CONFIG_IS_ENABLED(OF_PLATDATA) 614 struct rk3368_clk_priv *priv = dev_get_priv(dev); 615 616 priv->cru = dev_read_addr_ptr(dev); 617 #endif 618 619 return 0; 620 } 621 622 static int rk3368_clk_bind(struct udevice *dev) 623 { 624 int ret; 625 struct udevice *sys_child; 626 struct sysreset_reg *priv; 627 628 /* The reset driver does not have a device node, so bind it here */ 629 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 630 &sys_child); 631 if (ret) { 632 debug("Warning: No sysreset driver: ret=%d\n", ret); 633 } else { 634 priv = malloc(sizeof(struct sysreset_reg)); 635 priv->glb_srst_fst_value = offsetof(struct rk3368_cru, 636 glb_srst_fst_val); 637 priv->glb_srst_snd_value = offsetof(struct rk3368_cru, 638 glb_srst_snd_val); 639 sys_child->priv = priv; 640 } 641 642 #if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP) 643 ret = offsetof(struct rk3368_cru, softrst_con[0]); 644 ret = rockchip_reset_bind(dev, ret, 15); 645 if (ret) 646 debug("Warning: software reset driver bind faile\n"); 647 #endif 648 649 return ret; 650 } 651 652 static const struct udevice_id rk3368_clk_ids[] = { 653 { .compatible = "rockchip,rk3368-cru" }, 654 { } 655 }; 656 657 U_BOOT_DRIVER(rockchip_rk3368_cru) = { 658 .name = "rockchip_rk3368_cru", 659 .id = UCLASS_CLK, 660 .of_match = rk3368_clk_ids, 661 .priv_auto_alloc_size = sizeof(struct rk3368_clk_priv), 662 #if CONFIG_IS_ENABLED(OF_PLATDATA) 663 .platdata_auto_alloc_size = sizeof(struct rk3368_clk_plat), 664 #endif 665 .ofdata_to_platdata = rk3368_clk_ofdata_to_platdata, 666 .ops = &rk3368_clk_ops, 667 .bind = rk3368_clk_bind, 668 .probe = rk3368_clk_probe, 669 }; 670