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 static ulong rk3308_armclk_set_clk(struct rk3308_clk_priv *priv, ulong hz) 87 { 88 struct rk3308_cru *cru = priv->cru; 89 const struct rockchip_cpu_rate_table *rate; 90 ulong old_rate; 91 92 rate = rockchip_get_cpu_settings(rk3308_cpu_rates, hz); 93 if (!rate) { 94 printf("%s unsupport rate\n", __func__); 95 return -EINVAL; 96 } 97 98 /* 99 * select apll as cpu/core clock pll source and 100 * set up dependent divisors for PERI and ACLK clocks. 101 * core hz : apll = 1:1 102 */ 103 old_rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 104 priv->cru, APLL); 105 if (old_rate > hz) { 106 if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL], 107 priv->cru, APLL, hz)) 108 return -EINVAL; 109 rk_clrsetreg(&cru->clksel_con[0], 110 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK | 111 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK, 112 rate->aclk_div << CORE_ACLK_DIV_SHIFT | 113 rate->pclk_div << CORE_DBG_DIV_SHIFT | 114 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 115 0 << CORE_DIV_CON_SHIFT); 116 } else if (old_rate < hz) { 117 rk_clrsetreg(&cru->clksel_con[0], 118 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK | 119 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK, 120 rate->aclk_div << CORE_ACLK_DIV_SHIFT | 121 rate->pclk_div << CORE_DBG_DIV_SHIFT | 122 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 123 0 << CORE_DIV_CON_SHIFT); 124 if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL], 125 priv->cru, APLL, hz)) 126 return -EINVAL; 127 } 128 129 return rockchip_pll_get_rate(&rk3308_pll_clks[APLL], priv->cru, APLL); 130 } 131 132 static void rk3308_clk_get_pll_rate(struct rk3308_clk_priv *priv) 133 { 134 if (!priv->dpll_hz) 135 priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL], 136 priv->cru, DPLL); 137 if (!priv->vpll0_hz) 138 priv->vpll0_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0], 139 priv->cru, VPLL0); 140 if (!priv->vpll1_hz) 141 priv->vpll1_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1], 142 priv->cru, VPLL1); 143 } 144 145 static ulong rk3308_i2c_get_clk(struct clk *clk) 146 { 147 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 148 struct rk3308_cru *cru = priv->cru; 149 u32 div, con, con_id; 150 151 switch (clk->id) { 152 case SCLK_I2C0: 153 con_id = 25; 154 break; 155 case SCLK_I2C1: 156 con_id = 26; 157 break; 158 case SCLK_I2C2: 159 con_id = 27; 160 break; 161 case SCLK_I2C3: 162 con_id = 28; 163 break; 164 default: 165 printf("do not support this i2c bus\n"); 166 return -EINVAL; 167 } 168 169 con = readl(&cru->clksel_con[con_id]); 170 div = con >> CLK_I2C_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 171 172 return DIV_TO_RATE(priv->dpll_hz, div); 173 } 174 175 static ulong rk3308_i2c_set_clk(struct clk *clk, uint hz) 176 { 177 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 178 struct rk3308_cru *cru = priv->cru; 179 u32 src_clk_div, con_id; 180 181 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); 182 assert(src_clk_div - 1 <= 127); 183 184 switch (clk->id) { 185 case SCLK_I2C0: 186 con_id = 25; 187 break; 188 case SCLK_I2C1: 189 con_id = 26; 190 break; 191 case SCLK_I2C2: 192 con_id = 27; 193 break; 194 case SCLK_I2C3: 195 con_id = 28; 196 break; 197 default: 198 printf("do not support this i2c bus\n"); 199 return -EINVAL; 200 } 201 rk_clrsetreg(&cru->clksel_con[con_id], 202 CLK_I2C_PLL_SEL_MASK | CLK_I2C_DIV_CON_MASK, 203 CLK_I2C_PLL_SEL_DPLL << CLK_I2C_PLL_SEL_SHIFT | 204 (src_clk_div - 1) << CLK_I2C_DIV_CON_SHIFT); 205 206 return rk3308_i2c_get_clk(clk); 207 } 208 209 static ulong rk3308_mac_set_clk(struct clk *clk, uint hz) 210 { 211 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 212 struct rk3308_cru *cru = priv->cru; 213 u32 con = readl(&cru->clksel_con[43]); 214 ulong pll_rate; 215 u8 div; 216 217 if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL0) 218 pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0], 219 priv->cru, VPLL0); 220 else if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL1) 221 pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1], 222 priv->cru, VPLL1); 223 else 224 pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL], 225 priv->cru, DPLL); 226 227 /*default set 50MHZ for gmac*/ 228 if (!hz) 229 hz = 50000000; 230 231 div = DIV_ROUND_UP(pll_rate, hz) - 1; 232 assert(div < 32); 233 rk_clrsetreg(&cru->clksel_con[43], MAC_DIV_MASK, 234 div << MAC_DIV_SHIFT); 235 236 return DIV_TO_RATE(pll_rate, div); 237 } 238 239 static int rk3308_mac_set_speed_clk(struct clk *clk, uint hz) 240 { 241 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 242 struct rk3308_cru *cru = priv->cru; 243 244 if (hz != 2500000 && hz != 25000000) { 245 debug("Unsupported mac speed:%d\n", hz); 246 return -EINVAL; 247 } 248 249 rk_clrsetreg(&cru->clksel_con[43], MAC_CLK_SPEED_SEL_MASK, 250 ((hz == 2500000) ? 0 : 1) << MAC_CLK_SPEED_SEL_SHIFT); 251 252 return 0; 253 } 254 255 static ulong rk3308_mmc_get_clk(struct clk *clk) 256 { 257 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 258 struct rk3308_cru *cru = priv->cru; 259 u32 div, con, con_id; 260 261 switch (clk->id) { 262 case HCLK_SDMMC: 263 case SCLK_SDMMC: 264 con_id = 39; 265 break; 266 case HCLK_EMMC: 267 case SCLK_EMMC: 268 case SCLK_EMMC_SAMPLE: 269 con_id = 41; 270 break; 271 default: 272 return -EINVAL; 273 } 274 275 con = readl(&cru->clksel_con[con_id]); 276 div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT; 277 278 if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT 279 == EMMC_SEL_24M) 280 return DIV_TO_RATE(OSC_HZ, div) / 2; 281 else 282 return DIV_TO_RATE(priv->vpll0_hz, div) / 2; 283 } 284 285 static ulong rk3308_mmc_set_clk(struct clk *clk, ulong set_rate) 286 { 287 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 288 struct rk3308_cru *cru = priv->cru; 289 int src_clk_div; 290 u32 con_id; 291 292 debug("%s %ld %ld\n", __func__, clk->id, set_rate); 293 294 switch (clk->id) { 295 case HCLK_SDMMC: 296 case SCLK_SDMMC: 297 con_id = 39; 298 break; 299 case HCLK_EMMC: 300 case SCLK_EMMC: 301 con_id = 41; 302 break; 303 default: 304 return -EINVAL; 305 } 306 /* Select clk_sdmmc/emmc source from VPLL0 by default */ 307 /* mmc clock defaulg div 2 internal, need provide double in cru */ 308 src_clk_div = DIV_ROUND_UP(priv->vpll0_hz / 2, set_rate); 309 310 if (src_clk_div > 127) { 311 /* use 24MHz source for 400KHz clock */ 312 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate); 313 rk_clrsetreg(&cru->clksel_con[con_id], 314 EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK, 315 EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT | 316 EMMC_SEL_24M << EMMC_PLL_SHIFT | 317 (src_clk_div - 1) << EMMC_DIV_SHIFT); 318 } else { 319 rk_clrsetreg(&cru->clksel_con[con_id], 320 EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK, 321 EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT | 322 EMMC_SEL_VPLL0 << EMMC_PLL_SHIFT | 323 (src_clk_div - 1) << EMMC_DIV_SHIFT); 324 } 325 326 return rk3308_mmc_get_clk(clk); 327 } 328 329 static ulong rk3308_saradc_get_clk(struct clk *clk) 330 { 331 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 332 struct rk3308_cru *cru = priv->cru; 333 u32 div, con; 334 335 con = readl(&cru->clksel_con[34]); 336 div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK; 337 338 return DIV_TO_RATE(OSC_HZ, div); 339 } 340 341 static ulong rk3308_saradc_set_clk(struct clk *clk, uint hz) 342 { 343 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 344 struct rk3308_cru *cru = priv->cru; 345 int src_clk_div; 346 347 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz); 348 assert(src_clk_div - 1 <= 2047); 349 350 rk_clrsetreg(&cru->clksel_con[34], 351 CLK_SARADC_DIV_CON_MASK, 352 (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT); 353 354 return rk3308_saradc_get_clk(clk); 355 } 356 357 static ulong rk3308_tsadc_get_clk(struct clk *clk) 358 { 359 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 360 struct rk3308_cru *cru = priv->cru; 361 u32 div, con; 362 363 con = readl(&cru->clksel_con[33]); 364 div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK; 365 366 return DIV_TO_RATE(OSC_HZ, div); 367 } 368 369 static ulong rk3308_tsadc_set_clk(struct clk *clk, uint hz) 370 { 371 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 372 struct rk3308_cru *cru = priv->cru; 373 int src_clk_div; 374 375 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz); 376 assert(src_clk_div - 1 <= 2047); 377 378 rk_clrsetreg(&cru->clksel_con[33], 379 CLK_SARADC_DIV_CON_MASK, 380 (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT); 381 382 return rk3308_tsadc_get_clk(clk); 383 } 384 385 static ulong rk3308_spi_get_clk(struct clk *clk) 386 { 387 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 388 struct rk3308_cru *cru = priv->cru; 389 u32 div, con, con_id; 390 391 switch (clk->id) { 392 case SCLK_SPI0: 393 con_id = 30; 394 break; 395 case SCLK_SPI1: 396 con_id = 31; 397 break; 398 case SCLK_SPI2: 399 con_id = 32; 400 break; 401 default: 402 printf("do not support this spi bus\n"); 403 return -EINVAL; 404 } 405 406 con = readl(&cru->clksel_con[con_id]); 407 div = con >> CLK_SPI_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK; 408 409 return DIV_TO_RATE(priv->dpll_hz, div); 410 } 411 412 static ulong rk3308_spi_set_clk(struct clk *clk, uint hz) 413 { 414 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 415 struct rk3308_cru *cru = priv->cru; 416 u32 src_clk_div, con_id; 417 418 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); 419 assert(src_clk_div - 1 <= 127); 420 421 switch (clk->id) { 422 case SCLK_SPI0: 423 con_id = 30; 424 break; 425 case SCLK_SPI1: 426 con_id = 31; 427 break; 428 case SCLK_SPI2: 429 con_id = 32; 430 break; 431 default: 432 printf("do not support this spi bus\n"); 433 return -EINVAL; 434 } 435 436 rk_clrsetreg(&cru->clksel_con[con_id], 437 CLK_SPI_PLL_SEL_MASK | CLK_SPI_DIV_CON_MASK, 438 CLK_SPI_PLL_SEL_DPLL << CLK_SPI_PLL_SEL_SHIFT | 439 (src_clk_div - 1) << CLK_SPI_DIV_CON_SHIFT); 440 441 return rk3308_spi_get_clk(clk); 442 } 443 444 static ulong rk3308_pwm_get_clk(struct clk *clk) 445 { 446 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 447 struct rk3308_cru *cru = priv->cru; 448 u32 div, con; 449 450 con = readl(&cru->clksel_con[29]); 451 div = con >> CLK_PWM_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK; 452 453 return DIV_TO_RATE(priv->dpll_hz, div); 454 } 455 456 static ulong rk3308_pwm_set_clk(struct clk *clk, uint hz) 457 { 458 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 459 struct rk3308_cru *cru = priv->cru; 460 int src_clk_div; 461 462 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); 463 assert(src_clk_div - 1 <= 127); 464 465 rk_clrsetreg(&cru->clksel_con[29], 466 CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK, 467 CLK_PWM_PLL_SEL_DPLL << CLK_PWM_PLL_SEL_SHIFT | 468 (src_clk_div - 1) << CLK_PWM_DIV_CON_SHIFT); 469 470 return rk3308_pwm_get_clk(clk); 471 } 472 473 static ulong rk3308_vop_get_clk(struct clk *clk) 474 { 475 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 476 struct rk3308_cru *cru = priv->cru; 477 u32 div, pll_sel, vol_sel, con, parent; 478 479 con = readl(&cru->clksel_con[8]); 480 vol_sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT; 481 pll_sel = (con & DCLK_VOP_PLL_SEL_MASK) >> DCLK_VOP_PLL_SEL_SHIFT; 482 div = con & DCLK_VOP_DIV_MASK; 483 484 if (vol_sel == DCLK_VOP_SEL_24M) { 485 parent = OSC_HZ; 486 } else if (vol_sel == DCLK_VOP_SEL_DIVOUT) { 487 switch (pll_sel) { 488 case DCLK_VOP_PLL_SEL_DPLL: 489 parent = priv->dpll_hz; 490 break; 491 case DCLK_VOP_PLL_SEL_VPLL0: 492 parent = priv->vpll0_hz; 493 break; 494 case DCLK_VOP_PLL_SEL_VPLL1: 495 parent = priv->vpll0_hz; 496 break; 497 default: 498 printf("do not support this vop pll sel\n"); 499 return -EINVAL; 500 } 501 } else { 502 printf("do not support this vop sel\n"); 503 return -EINVAL; 504 } 505 506 return DIV_TO_RATE(parent, div); 507 } 508 509 static ulong rk3308_vop_set_clk(struct clk *clk, ulong hz) 510 { 511 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 512 struct rk3308_cru *cru = priv->cru; 513 ulong pll_rate, now, best_rate = 0; 514 u32 i, div, best_div = 0, best_sel = 0; 515 516 for (i = 0; i <= DCLK_VOP_PLL_SEL_VPLL1; i++) { 517 switch (i) { 518 case DCLK_VOP_PLL_SEL_DPLL: 519 pll_rate = priv->dpll_hz; 520 break; 521 case DCLK_VOP_PLL_SEL_VPLL0: 522 pll_rate = priv->vpll0_hz; 523 break; 524 case DCLK_VOP_PLL_SEL_VPLL1: 525 pll_rate = priv->vpll1_hz; 526 break; 527 default: 528 printf("do not support this vop pll sel\n"); 529 return -EINVAL; 530 } 531 532 div = DIV_ROUND_UP(pll_rate, hz); 533 if (div > 255) 534 continue; 535 now = pll_rate / div; 536 if (abs(hz - now) < abs(hz - best_rate)) { 537 best_rate = now; 538 best_div = div; 539 best_sel = i; 540 } 541 debug("pll_rate=%lu, best_rate=%lu, best_div=%u, best_sel=%u\n", 542 pll_rate, best_rate, best_div, best_sel); 543 } 544 545 if (best_rate != hz && hz == OSC_HZ) { 546 rk_clrsetreg(&cru->clksel_con[8], 547 DCLK_VOP_SEL_MASK, 548 DCLK_VOP_SEL_24M << DCLK_VOP_SEL_SHIFT); 549 } else if (best_rate) { 550 rk_clrsetreg(&cru->clksel_con[8], 551 DCLK_VOP_SEL_MASK | DCLK_VOP_PLL_SEL_MASK | 552 DCLK_VOP_DIV_MASK, 553 DCLK_VOP_SEL_DIVOUT << DCLK_VOP_SEL_SHIFT | 554 best_sel << DCLK_VOP_PLL_SEL_SHIFT | 555 (best_div - 1) << DCLK_VOP_DIV_SHIFT); 556 } else { 557 printf("do not support this vop freq\n"); 558 return -EINVAL; 559 } 560 561 return rk3308_vop_get_clk(clk); 562 } 563 564 static ulong rk3308_bus_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) 565 { 566 struct rk3308_cru *cru = priv->cru; 567 u32 div, con, parent = priv->dpll_hz; 568 569 switch (clk_id) { 570 case ACLK_BUS: 571 con = readl(&cru->clksel_con[5]); 572 div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT; 573 break; 574 case HCLK_BUS: 575 con = readl(&cru->clksel_con[6]); 576 div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT; 577 break; 578 case PCLK_BUS: 579 case PCLK_WDT: 580 con = readl(&cru->clksel_con[6]); 581 div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT; 582 break; 583 default: 584 return -ENOENT; 585 } 586 587 return DIV_TO_RATE(parent, div); 588 } 589 590 static ulong rk3308_bus_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, 591 ulong hz) 592 { 593 struct rk3308_cru *cru = priv->cru; 594 int src_clk_div; 595 596 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); 597 assert(src_clk_div - 1 <= 31); 598 599 /* 600 * select dpll as pd_bus bus clock source and 601 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 602 */ 603 switch (clk_id) { 604 case ACLK_BUS: 605 rk_clrsetreg(&cru->clksel_con[5], 606 BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK, 607 BUS_PLL_SEL_DPLL << BUS_PLL_SEL_SHIFT | 608 (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT); 609 break; 610 case HCLK_BUS: 611 rk_clrsetreg(&cru->clksel_con[6], 612 BUS_HCLK_DIV_MASK, 613 (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT); 614 break; 615 case PCLK_BUS: 616 rk_clrsetreg(&cru->clksel_con[6], 617 BUS_PCLK_DIV_MASK, 618 (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT); 619 break; 620 default: 621 printf("do not support this bus freq\n"); 622 return -EINVAL; 623 } 624 625 return rk3308_bus_get_clk(priv, clk_id); 626 } 627 628 static ulong rk3308_peri_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) 629 { 630 struct rk3308_cru *cru = priv->cru; 631 u32 div, con, parent = priv->dpll_hz; 632 633 switch (clk_id) { 634 case ACLK_PERI: 635 con = readl(&cru->clksel_con[36]); 636 div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT; 637 break; 638 case HCLK_PERI: 639 con = readl(&cru->clksel_con[37]); 640 div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT; 641 break; 642 case PCLK_PERI: 643 con = readl(&cru->clksel_con[37]); 644 div = (con & PERI_PCLK_DIV_MASK) >> PERI_PCLK_DIV_SHIFT; 645 break; 646 default: 647 return -ENOENT; 648 } 649 650 return DIV_TO_RATE(parent, div); 651 } 652 653 static ulong rk3308_peri_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, 654 ulong hz) 655 { 656 struct rk3308_cru *cru = priv->cru; 657 int src_clk_div; 658 659 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); 660 assert(src_clk_div - 1 <= 31); 661 662 /* 663 * select dpll as pd_peri bus clock source and 664 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 665 */ 666 switch (clk_id) { 667 case ACLK_PERI: 668 rk_clrsetreg(&cru->clksel_con[36], 669 PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK, 670 PERI_PLL_DPLL << PERI_PLL_SEL_SHIFT | 671 (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT); 672 break; 673 case HCLK_PERI: 674 rk_clrsetreg(&cru->clksel_con[37], 675 PERI_HCLK_DIV_MASK, 676 (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT); 677 break; 678 case PCLK_PERI: 679 rk_clrsetreg(&cru->clksel_con[37], 680 PERI_PCLK_DIV_MASK, 681 (src_clk_div - 1) << PERI_PCLK_DIV_SHIFT); 682 break; 683 default: 684 printf("do not support this peri freq\n"); 685 return -EINVAL; 686 } 687 688 return rk3308_peri_get_clk(priv, clk_id); 689 } 690 691 static ulong rk3308_audio_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) 692 { 693 struct rk3308_cru *cru = priv->cru; 694 u32 div, con, parent = priv->vpll0_hz; 695 696 switch (clk_id) { 697 case HCLK_AUDIO: 698 con = readl(&cru->clksel_con[45]); 699 div = (con & AUDIO_HCLK_DIV_MASK) >> AUDIO_HCLK_DIV_SHIFT; 700 break; 701 case PCLK_AUDIO: 702 con = readl(&cru->clksel_con[45]); 703 div = (con & AUDIO_PCLK_DIV_MASK) >> AUDIO_PCLK_DIV_SHIFT; 704 break; 705 default: 706 return -ENOENT; 707 } 708 709 return DIV_TO_RATE(parent, div); 710 } 711 712 static ulong rk3308_audio_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, 713 ulong hz) 714 { 715 struct rk3308_cru *cru = priv->cru; 716 int src_clk_div; 717 718 src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz); 719 assert(src_clk_div - 1 <= 31); 720 721 /* 722 * select vpll0 as audio bus clock source and 723 * set up dependent divisors for HCLK and PCLK clocks. 724 */ 725 switch (clk_id) { 726 case HCLK_AUDIO: 727 rk_clrsetreg(&cru->clksel_con[45], 728 AUDIO_PLL_SEL_MASK | AUDIO_HCLK_DIV_MASK, 729 AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT | 730 (src_clk_div - 1) << AUDIO_HCLK_DIV_SHIFT); 731 break; 732 case PCLK_AUDIO: 733 rk_clrsetreg(&cru->clksel_con[45], 734 AUDIO_PLL_SEL_MASK | AUDIO_PCLK_DIV_MASK, 735 AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT | 736 (src_clk_div - 1) << AUDIO_PCLK_DIV_SHIFT); 737 break; 738 default: 739 printf("do not support this audio freq\n"); 740 return -EINVAL; 741 } 742 743 return rk3308_peri_get_clk(priv, clk_id); 744 } 745 746 static ulong rk3308_crypto_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) 747 { 748 struct rk3308_cru *cru = priv->cru; 749 u32 div, con, parent; 750 751 switch (clk_id) { 752 case SCLK_CRYPTO: 753 con = readl(&cru->clksel_con[7]); 754 div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT; 755 parent = priv->vpll0_hz; 756 break; 757 case SCLK_CRYPTO_APK: 758 con = readl(&cru->clksel_con[7]); 759 div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT; 760 parent = priv->vpll0_hz; 761 break; 762 default: 763 return -ENOENT; 764 } 765 766 return DIV_TO_RATE(parent, div); 767 } 768 769 static ulong rk3308_crypto_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, 770 ulong hz) 771 { 772 struct rk3308_cru *cru = priv->cru; 773 int src_clk_div; 774 775 src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz); 776 assert(src_clk_div - 1 <= 31); 777 778 /* 779 * select gpll as crypto clock source and 780 * set up dependent divisors for crypto clocks. 781 */ 782 switch (clk_id) { 783 case SCLK_CRYPTO: 784 rk_clrsetreg(&cru->clksel_con[7], 785 CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK, 786 CRYPTO_PLL_SEL_VPLL0 << CRYPTO_PLL_SEL_SHIFT | 787 (src_clk_div - 1) << CRYPTO_DIV_SHIFT); 788 break; 789 case SCLK_CRYPTO_APK: 790 rk_clrsetreg(&cru->clksel_con[7], 791 CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK, 792 CRYPTO_PLL_SEL_VPLL0 << CRYPTO_APK_SEL_SHIFT | 793 (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT); 794 break; 795 default: 796 printf("do not support this peri freq\n"); 797 return -EINVAL; 798 } 799 800 return rk3308_crypto_get_clk(priv, clk_id); 801 } 802 803 static ulong rk3308_clk_get_rate(struct clk *clk) 804 { 805 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 806 ulong rate = 0; 807 808 debug("%s id:%ld\n", __func__, clk->id); 809 810 switch (clk->id) { 811 case PLL_APLL: 812 case ARMCLK: 813 rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 814 priv->cru, APLL); 815 break; 816 case PLL_DPLL: 817 rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL], 818 priv->cru, DPLL); 819 break; 820 case PLL_VPLL0: 821 rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0], 822 priv->cru, VPLL0); 823 break; 824 case PLL_VPLL1: 825 rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1], 826 priv->cru, VPLL1); 827 break; 828 case HCLK_SDMMC: 829 case HCLK_EMMC: 830 case SCLK_SDMMC: 831 case SCLK_EMMC: 832 case SCLK_EMMC_SAMPLE: 833 rate = rk3308_mmc_get_clk(clk); 834 break; 835 case SCLK_I2C0: 836 case SCLK_I2C1: 837 case SCLK_I2C2: 838 case SCLK_I2C3: 839 rate = rk3308_i2c_get_clk(clk); 840 break; 841 case SCLK_SARADC: 842 rate = rk3308_saradc_get_clk(clk); 843 break; 844 case SCLK_TSADC: 845 rate = rk3308_tsadc_get_clk(clk); 846 break; 847 case SCLK_SPI0: 848 case SCLK_SPI1: 849 rate = rk3308_spi_get_clk(clk); 850 break; 851 case SCLK_PWM: 852 rate = rk3308_pwm_get_clk(clk); 853 break; 854 case DCLK_VOP: 855 rate = rk3308_vop_get_clk(clk); 856 break; 857 case ACLK_BUS: 858 case HCLK_BUS: 859 case PCLK_BUS: 860 case PCLK_WDT: 861 rate = rk3308_bus_get_clk(priv, clk->id); 862 break; 863 case ACLK_PERI: 864 case HCLK_PERI: 865 case PCLK_PERI: 866 rate = rk3308_peri_get_clk(priv, clk->id); 867 break; 868 case HCLK_AUDIO: 869 case PCLK_AUDIO: 870 rate = rk3308_audio_get_clk(priv, clk->id); 871 break; 872 case SCLK_CRYPTO: 873 case SCLK_CRYPTO_APK: 874 rate = rk3308_crypto_get_clk(priv, clk->id); 875 break; 876 default: 877 return -ENOENT; 878 } 879 880 return rate; 881 } 882 883 static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate) 884 { 885 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 886 ulong ret = 0; 887 888 debug("%s %ld %ld\n", __func__, clk->id, rate); 889 890 switch (clk->id) { 891 case PLL_DPLL: 892 ret = rockchip_pll_set_rate(&rk3308_pll_clks[DPLL], priv->cru, 893 DPLL, rate); 894 priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL], 895 priv->cru, DPLL); 896 break; 897 case ARMCLK: 898 if (priv->armclk_hz) 899 rk3308_armclk_set_clk(priv, rate); 900 priv->armclk_hz = rate; 901 break; 902 case HCLK_SDMMC: 903 case HCLK_EMMC: 904 case SCLK_SDMMC: 905 case SCLK_EMMC: 906 ret = rk3308_mmc_set_clk(clk, rate); 907 break; 908 case SCLK_I2C0: 909 case SCLK_I2C1: 910 case SCLK_I2C2: 911 case SCLK_I2C3: 912 ret = rk3308_i2c_set_clk(clk, rate); 913 break; 914 case SCLK_MAC: 915 ret = rk3308_mac_set_clk(clk, rate); 916 break; 917 case SCLK_MAC_RMII: 918 ret = rk3308_mac_set_speed_clk(clk, rate); 919 break; 920 case SCLK_SARADC: 921 ret = rk3308_saradc_set_clk(clk, rate); 922 break; 923 case SCLK_TSADC: 924 ret = rk3308_tsadc_set_clk(clk, rate); 925 break; 926 case SCLK_SPI0: 927 case SCLK_SPI1: 928 ret = rk3308_spi_set_clk(clk, rate); 929 break; 930 case SCLK_PWM: 931 ret = rk3308_pwm_set_clk(clk, rate); 932 break; 933 case DCLK_VOP: 934 ret = rk3308_vop_set_clk(clk, rate); 935 break; 936 case ACLK_BUS: 937 case HCLK_BUS: 938 case PCLK_BUS: 939 rate = rk3308_bus_set_clk(priv, clk->id, rate); 940 break; 941 case ACLK_PERI: 942 case HCLK_PERI: 943 case PCLK_PERI: 944 rate = rk3308_peri_set_clk(priv, clk->id, rate); 945 break; 946 case HCLK_AUDIO: 947 case PCLK_AUDIO: 948 rate = rk3308_audio_set_clk(priv, clk->id, rate); 949 break; 950 case SCLK_CRYPTO: 951 case SCLK_CRYPTO_APK: 952 ret = rk3308_crypto_set_clk(priv, clk->id, rate); 953 break; 954 default: 955 return -ENOENT; 956 } 957 958 return ret; 959 } 960 961 #define ROCKCHIP_MMC_DELAY_SEL BIT(11) 962 #define ROCKCHIP_MMC_DEGREE_OFFSET 1 963 #define ROCKCHIP_MMC_DEGREE_MASK (0x3 << ROCKCHIP_MMC_DEGREE_OFFSET) 964 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 3 965 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 966 967 #define PSECS_PER_SEC 1000000000000LL 968 /* 969 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 970 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 971 */ 972 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 973 974 int rockchip_mmc_get_phase(struct clk *clk) 975 { 976 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 977 struct rk3308_cru *cru = priv->cru; 978 u32 raw_value, delay_num; 979 u16 degrees = 0; 980 ulong rate; 981 982 rate = rk3308_clk_get_rate(clk); 983 984 if (rate < 0) 985 return rate; 986 987 if (clk->id == SCLK_EMMC_SAMPLE) 988 raw_value = readl(&cru->emmc_con[1]); 989 else 990 raw_value = readl(&cru->sdmmc_con[1]); 991 992 raw_value &= ROCKCHIP_MMC_DEGREE_MASK; 993 degrees = (raw_value >> ROCKCHIP_MMC_DEGREE_OFFSET) * 90; 994 995 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 996 /* degrees/delaynum * 10000 */ 997 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 998 36 * (rate / 1000000); 999 1000 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 1001 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 1002 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 1003 } 1004 1005 return degrees % 360; 1006 1007 } 1008 1009 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees) 1010 { 1011 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 1012 struct rk3308_cru *cru = priv->cru; 1013 u8 nineties, remainder, delay_num; 1014 u32 raw_value, delay; 1015 ulong rate; 1016 1017 rate = rk3308_clk_get_rate(clk); 1018 1019 if (rate < 0) 1020 return rate; 1021 1022 nineties = degrees / 90; 1023 remainder = (degrees % 90); 1024 1025 /* 1026 * Convert to delay; do a little extra work to make sure we 1027 * don't overflow 32-bit / 64-bit numbers. 1028 */ 1029 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 1030 delay *= remainder; 1031 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 1032 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 1033 1034 delay_num = (u8)min_t(u32, delay, 255); 1035 1036 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 1037 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 1038 raw_value |= nineties << ROCKCHIP_MMC_DEGREE_OFFSET; 1039 1040 if (clk->id == SCLK_EMMC_SAMPLE) 1041 writel(raw_value | 0xffff0000, &cru->emmc_con[1]); 1042 else 1043 writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]); 1044 1045 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 1046 degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk)); 1047 1048 return 0; 1049 1050 } 1051 1052 static int rk3308_clk_get_phase(struct clk *clk) 1053 { 1054 int ret; 1055 1056 switch (clk->id) { 1057 case SCLK_EMMC_SAMPLE: 1058 case SCLK_SDMMC_SAMPLE: 1059 ret = rockchip_mmc_get_phase(clk); 1060 break; 1061 default: 1062 return -ENOENT; 1063 } 1064 1065 return ret; 1066 } 1067 1068 static int rk3308_clk_set_phase(struct clk *clk, int degrees) 1069 { 1070 int ret; 1071 1072 switch (clk->id) { 1073 case SCLK_EMMC_SAMPLE: 1074 case SCLK_SDMMC_SAMPLE: 1075 ret = rockchip_mmc_set_phase(clk, degrees); 1076 break; 1077 default: 1078 return -ENOENT; 1079 } 1080 1081 return ret; 1082 } 1083 1084 static int __maybe_unused rk3308_mac_set_parent(struct clk *clk, struct clk *parent) 1085 { 1086 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 1087 1088 /* 1089 * If the requested parent is in the same clock-controller and 1090 * the id is SCLK_MAC_SRC, switch to the internal clock. 1091 */ 1092 if (parent->id == SCLK_MAC_SRC) { 1093 debug("%s: switching RMII to SCLK_MAC\n", __func__); 1094 rk_clrreg(&priv->cru->clksel_con[43], BIT(14)); 1095 } else { 1096 debug("%s: switching RMII to CLKIN\n", __func__); 1097 rk_setreg(&priv->cru->clksel_con[43], BIT(14)); 1098 } 1099 1100 return 0; 1101 } 1102 1103 static int __maybe_unused rk3308_clk_set_parent(struct clk *clk, struct clk *parent) 1104 { 1105 switch (clk->id) { 1106 case SCLK_MAC: 1107 return rk3308_mac_set_parent(clk, parent); 1108 default: 1109 break; 1110 } 1111 1112 debug("%s: unsupported clk %ld\n", __func__, clk->id); 1113 return -ENOENT; 1114 } 1115 1116 static struct clk_ops rk3308_clk_ops = { 1117 .get_rate = rk3308_clk_get_rate, 1118 .set_rate = rk3308_clk_set_rate, 1119 .get_phase = rk3308_clk_get_phase, 1120 .set_phase = rk3308_clk_set_phase, 1121 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) 1122 .set_parent = rk3308_clk_set_parent, 1123 #endif 1124 }; 1125 1126 static void rk3308_clk_init(struct udevice *dev) 1127 { 1128 struct rk3308_clk_priv *priv = dev_get_priv(dev); 1129 int ret; 1130 1131 if (rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 1132 priv->cru, APLL) != APLL_HZ) { 1133 ret = rk3308_armclk_set_clk(priv, APLL_HZ); 1134 if (ret < 0) 1135 printf("%s failed to set armclk rate\n", __func__); 1136 } 1137 1138 rk3308_clk_get_pll_rate(priv); 1139 1140 rk3308_bus_set_clk(priv, ACLK_BUS, BUS_ACLK_HZ); 1141 rk3308_bus_set_clk(priv, HCLK_BUS, BUS_HCLK_HZ); 1142 rk3308_bus_set_clk(priv, PCLK_BUS, BUS_PCLK_HZ); 1143 1144 rk3308_peri_set_clk(priv, ACLK_PERI, PERI_ACLK_HZ); 1145 rk3308_peri_set_clk(priv, HCLK_PERI, PERI_HCLK_HZ); 1146 rk3308_peri_set_clk(priv, PCLK_PERI, PERI_PCLK_HZ); 1147 1148 rk3308_audio_set_clk(priv, HCLK_AUDIO, AUDIO_HCLK_HZ); 1149 rk3308_audio_set_clk(priv, PCLK_AUDIO, AUDIO_PCLK_HZ); 1150 } 1151 1152 static int rk3308_clk_probe(struct udevice *dev) 1153 { 1154 struct rk3308_clk_priv *priv = dev_get_priv(dev); 1155 int ret; 1156 1157 priv->sync_kernel = false; 1158 if (!priv->armclk_enter_hz) 1159 priv->armclk_enter_hz = 1160 rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 1161 priv->cru, APLL); 1162 rk3308_clk_init(dev); 1163 if (!priv->armclk_init_hz) 1164 priv->armclk_init_hz = 1165 rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 1166 priv->cru, APLL); 1167 1168 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 1169 ret = clk_set_defaults(dev); 1170 if (ret) 1171 debug("%s clk_set_defaults failed %d\n", __func__, ret); 1172 else 1173 priv->sync_kernel = true; 1174 1175 return 0; 1176 } 1177 1178 static int rk3308_clk_ofdata_to_platdata(struct udevice *dev) 1179 { 1180 struct rk3308_clk_priv *priv = dev_get_priv(dev); 1181 1182 priv->cru = dev_read_addr_ptr(dev); 1183 1184 return 0; 1185 } 1186 1187 static int rk3308_clk_bind(struct udevice *dev) 1188 { 1189 int ret; 1190 struct udevice *sys_child, *sf_child; 1191 struct sysreset_reg *priv; 1192 struct softreset_reg *sf_priv; 1193 1194 /* The reset driver does not have a device node, so bind it here */ 1195 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 1196 &sys_child); 1197 if (ret) { 1198 debug("Warning: No sysreset driver: ret=%d\n", ret); 1199 } else { 1200 priv = malloc(sizeof(struct sysreset_reg)); 1201 priv->glb_srst_fst_value = offsetof(struct rk3308_cru, 1202 glb_srst_fst); 1203 priv->glb_srst_snd_value = offsetof(struct rk3308_cru, 1204 glb_srst_snd); 1205 sys_child->priv = priv; 1206 } 1207 1208 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 1209 dev_ofnode(dev), &sf_child); 1210 if (ret) { 1211 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 1212 } else { 1213 sf_priv = malloc(sizeof(struct softreset_reg)); 1214 sf_priv->sf_reset_offset = offsetof(struct rk3308_cru, 1215 softrst_con[0]); 1216 sf_priv->sf_reset_num = 12; 1217 sf_child->priv = sf_priv; 1218 } 1219 1220 return 0; 1221 } 1222 1223 static const struct udevice_id rk3308_clk_ids[] = { 1224 { .compatible = "rockchip,rk3308-cru" }, 1225 { } 1226 }; 1227 1228 U_BOOT_DRIVER(rockchip_rk3308_cru) = { 1229 .name = "rockchip_rk3308_cru", 1230 .id = UCLASS_CLK, 1231 .of_match = rk3308_clk_ids, 1232 .priv_auto_alloc_size = sizeof(struct rk3308_clk_priv), 1233 .ofdata_to_platdata = rk3308_clk_ofdata_to_platdata, 1234 .ops = &rk3308_clk_ops, 1235 .bind = rk3308_clk_bind, 1236 .probe = rk3308_clk_probe, 1237 }; 1238 1239 /** 1240 * soc_clk_dump() - Print clock frequencies 1241 * Returns zero on success 1242 * 1243 * Implementation for the clk dump command. 1244 */ 1245 int soc_clk_dump(void) 1246 { 1247 struct udevice *cru_dev; 1248 struct rk3308_clk_priv *priv; 1249 const struct rk3308_clk_info *clk_dump; 1250 struct clk clk; 1251 unsigned long clk_count = ARRAY_SIZE(clks_dump); 1252 unsigned long rate; 1253 int i, ret; 1254 1255 ret = uclass_get_device_by_driver(UCLASS_CLK, 1256 DM_GET_DRIVER(rockchip_rk3308_cru), 1257 &cru_dev); 1258 if (ret) { 1259 printf("%s failed to get cru device\n", __func__); 1260 return ret; 1261 } 1262 1263 priv = dev_get_priv(cru_dev); 1264 printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n", 1265 priv->sync_kernel ? "sync kernel" : "uboot", 1266 priv->armclk_enter_hz / 1000, 1267 priv->armclk_init_hz / 1000, 1268 priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0, 1269 priv->set_armclk_rate ? " KHz" : "N/A"); 1270 for (i = 0; i < clk_count; i++) { 1271 clk_dump = &clks_dump[i]; 1272 if (clk_dump->name) { 1273 clk.id = clk_dump->id; 1274 ret = clk_request(cru_dev, &clk); 1275 if (ret < 0) 1276 return ret; 1277 1278 rate = clk_get_rate(&clk); 1279 clk_free(&clk); 1280 if (i == 0) { 1281 if (rate < 0) 1282 printf(" %s %s\n", clk_dump->name, 1283 "unknown"); 1284 else 1285 printf(" %s %lu KHz\n", clk_dump->name, 1286 rate / 1000); 1287 } else { 1288 if (rate < 0) 1289 printf(" %s %s\n", clk_dump->name, 1290 "unknown"); 1291 else 1292 printf(" %s %lu KHz\n", clk_dump->name, 1293 rate / 1000); 1294 } 1295 } 1296 } 1297 1298 return 0; 1299 } 1300