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 #ifndef CONFIG_SPL_BUILD 747 static ulong rk3308_crypto_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) 748 { 749 struct rk3308_cru *cru = priv->cru; 750 u32 div, con, parent; 751 752 switch (clk_id) { 753 case SCLK_CRYPTO: 754 con = readl(&cru->clksel_con[7]); 755 div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT; 756 parent = priv->vpll0_hz; 757 break; 758 case SCLK_CRYPTO_APK: 759 con = readl(&cru->clksel_con[7]); 760 div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT; 761 parent = priv->vpll0_hz; 762 break; 763 default: 764 return -ENOENT; 765 } 766 767 return DIV_TO_RATE(parent, div); 768 } 769 770 static ulong rk3308_crypto_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, 771 ulong hz) 772 { 773 struct rk3308_cru *cru = priv->cru; 774 int src_clk_div; 775 776 src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz); 777 assert(src_clk_div - 1 <= 31); 778 779 /* 780 * select gpll as crypto clock source and 781 * set up dependent divisors for crypto clocks. 782 */ 783 switch (clk_id) { 784 case SCLK_CRYPTO: 785 rk_clrsetreg(&cru->clksel_con[7], 786 CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK, 787 CRYPTO_PLL_SEL_VPLL0 << CRYPTO_PLL_SEL_SHIFT | 788 (src_clk_div - 1) << CRYPTO_DIV_SHIFT); 789 break; 790 case SCLK_CRYPTO_APK: 791 rk_clrsetreg(&cru->clksel_con[7], 792 CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK, 793 CRYPTO_PLL_SEL_VPLL0 << CRYPTO_APK_SEL_SHIFT | 794 (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT); 795 break; 796 default: 797 printf("do not support this peri freq\n"); 798 return -EINVAL; 799 } 800 801 return rk3308_crypto_get_clk(priv, clk_id); 802 } 803 #endif 804 805 static ulong rk3308_clk_get_rate(struct clk *clk) 806 { 807 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 808 ulong rate = 0; 809 810 debug("%s id:%ld\n", __func__, clk->id); 811 812 switch (clk->id) { 813 case PLL_APLL: 814 case ARMCLK: 815 rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 816 priv->cru, APLL); 817 break; 818 case PLL_DPLL: 819 rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL], 820 priv->cru, DPLL); 821 break; 822 case PLL_VPLL0: 823 rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0], 824 priv->cru, VPLL0); 825 break; 826 case PLL_VPLL1: 827 rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1], 828 priv->cru, VPLL1); 829 break; 830 case HCLK_SDMMC: 831 case HCLK_EMMC: 832 case SCLK_SDMMC: 833 case SCLK_EMMC: 834 case SCLK_EMMC_SAMPLE: 835 rate = rk3308_mmc_get_clk(clk); 836 break; 837 case SCLK_I2C0: 838 case SCLK_I2C1: 839 case SCLK_I2C2: 840 case SCLK_I2C3: 841 rate = rk3308_i2c_get_clk(clk); 842 break; 843 case SCLK_SARADC: 844 rate = rk3308_saradc_get_clk(clk); 845 break; 846 case SCLK_TSADC: 847 rate = rk3308_tsadc_get_clk(clk); 848 break; 849 case SCLK_SPI0: 850 case SCLK_SPI1: 851 rate = rk3308_spi_get_clk(clk); 852 break; 853 case SCLK_PWM: 854 rate = rk3308_pwm_get_clk(clk); 855 break; 856 case DCLK_VOP: 857 rate = rk3308_vop_get_clk(clk); 858 break; 859 case ACLK_BUS: 860 case HCLK_BUS: 861 case PCLK_BUS: 862 case PCLK_WDT: 863 rate = rk3308_bus_get_clk(priv, clk->id); 864 break; 865 case ACLK_PERI: 866 case HCLK_PERI: 867 case PCLK_PERI: 868 rate = rk3308_peri_get_clk(priv, clk->id); 869 break; 870 case HCLK_AUDIO: 871 case PCLK_AUDIO: 872 rate = rk3308_audio_get_clk(priv, clk->id); 873 break; 874 #ifndef CONFIG_SPL_BUILD 875 case SCLK_CRYPTO: 876 case SCLK_CRYPTO_APK: 877 rate = rk3308_crypto_get_clk(priv, clk->id); 878 break; 879 #endif 880 default: 881 return -ENOENT; 882 } 883 884 return rate; 885 } 886 887 static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate) 888 { 889 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 890 ulong ret = 0; 891 892 debug("%s %ld %ld\n", __func__, clk->id, rate); 893 894 switch (clk->id) { 895 case PLL_DPLL: 896 ret = rockchip_pll_set_rate(&rk3308_pll_clks[DPLL], priv->cru, 897 DPLL, rate); 898 priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL], 899 priv->cru, DPLL); 900 break; 901 case ARMCLK: 902 if (priv->armclk_hz) 903 rk3308_armclk_set_clk(priv, rate); 904 priv->armclk_hz = rate; 905 break; 906 case HCLK_SDMMC: 907 case HCLK_EMMC: 908 case SCLK_SDMMC: 909 case SCLK_EMMC: 910 ret = rk3308_mmc_set_clk(clk, rate); 911 break; 912 case SCLK_I2C0: 913 case SCLK_I2C1: 914 case SCLK_I2C2: 915 case SCLK_I2C3: 916 ret = rk3308_i2c_set_clk(clk, rate); 917 break; 918 case SCLK_MAC: 919 ret = rk3308_mac_set_clk(clk, rate); 920 break; 921 case SCLK_MAC_RMII: 922 ret = rk3308_mac_set_speed_clk(clk, rate); 923 break; 924 case SCLK_SARADC: 925 ret = rk3308_saradc_set_clk(clk, rate); 926 break; 927 case SCLK_TSADC: 928 ret = rk3308_tsadc_set_clk(clk, rate); 929 break; 930 case SCLK_SPI0: 931 case SCLK_SPI1: 932 ret = rk3308_spi_set_clk(clk, rate); 933 break; 934 case SCLK_PWM: 935 ret = rk3308_pwm_set_clk(clk, rate); 936 break; 937 case DCLK_VOP: 938 ret = rk3308_vop_set_clk(clk, rate); 939 break; 940 case ACLK_BUS: 941 case HCLK_BUS: 942 case PCLK_BUS: 943 rate = rk3308_bus_set_clk(priv, clk->id, rate); 944 break; 945 case ACLK_PERI: 946 case HCLK_PERI: 947 case PCLK_PERI: 948 rate = rk3308_peri_set_clk(priv, clk->id, rate); 949 break; 950 case HCLK_AUDIO: 951 case PCLK_AUDIO: 952 rate = rk3308_audio_set_clk(priv, clk->id, rate); 953 break; 954 #ifndef CONFIG_SPL_BUILD 955 case SCLK_CRYPTO: 956 case SCLK_CRYPTO_APK: 957 ret = rk3308_crypto_set_clk(priv, clk->id, rate); 958 break; 959 #endif 960 default: 961 return -ENOENT; 962 } 963 964 return ret; 965 } 966 967 #define ROCKCHIP_MMC_DELAY_SEL BIT(11) 968 #define ROCKCHIP_MMC_DEGREE_OFFSET 1 969 #define ROCKCHIP_MMC_DEGREE_MASK (0x3 << ROCKCHIP_MMC_DEGREE_OFFSET) 970 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 3 971 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 972 973 #define PSECS_PER_SEC 1000000000000LL 974 /* 975 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 976 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 977 */ 978 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 979 980 int rockchip_mmc_get_phase(struct clk *clk) 981 { 982 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 983 struct rk3308_cru *cru = priv->cru; 984 u32 raw_value, delay_num; 985 u16 degrees = 0; 986 ulong rate; 987 988 rate = rk3308_clk_get_rate(clk); 989 990 if (rate < 0) 991 return rate; 992 993 if (clk->id == SCLK_EMMC_SAMPLE) 994 raw_value = readl(&cru->emmc_con[1]); 995 else 996 raw_value = readl(&cru->sdmmc_con[1]); 997 998 raw_value &= ROCKCHIP_MMC_DEGREE_MASK; 999 degrees = (raw_value >> ROCKCHIP_MMC_DEGREE_OFFSET) * 90; 1000 1001 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 1002 /* degrees/delaynum * 10000 */ 1003 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 1004 36 * (rate / 1000000); 1005 1006 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 1007 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 1008 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 1009 } 1010 1011 return degrees % 360; 1012 1013 } 1014 1015 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees) 1016 { 1017 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 1018 struct rk3308_cru *cru = priv->cru; 1019 u8 nineties, remainder, delay_num; 1020 u32 raw_value, delay; 1021 ulong rate; 1022 1023 rate = rk3308_clk_get_rate(clk); 1024 1025 if (rate < 0) 1026 return rate; 1027 1028 nineties = degrees / 90; 1029 remainder = (degrees % 90); 1030 1031 /* 1032 * Convert to delay; do a little extra work to make sure we 1033 * don't overflow 32-bit / 64-bit numbers. 1034 */ 1035 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 1036 delay *= remainder; 1037 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 1038 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 1039 1040 delay_num = (u8)min_t(u32, delay, 255); 1041 1042 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 1043 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 1044 raw_value |= nineties << ROCKCHIP_MMC_DEGREE_OFFSET; 1045 1046 if (clk->id == SCLK_EMMC_SAMPLE) 1047 writel(raw_value | 0xffff0000, &cru->emmc_con[1]); 1048 else 1049 writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]); 1050 1051 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 1052 degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk)); 1053 1054 return 0; 1055 1056 } 1057 1058 static int rk3308_clk_get_phase(struct clk *clk) 1059 { 1060 int ret; 1061 1062 switch (clk->id) { 1063 case SCLK_EMMC_SAMPLE: 1064 case SCLK_SDMMC_SAMPLE: 1065 ret = rockchip_mmc_get_phase(clk); 1066 break; 1067 default: 1068 return -ENOENT; 1069 } 1070 1071 return ret; 1072 } 1073 1074 static int rk3308_clk_set_phase(struct clk *clk, int degrees) 1075 { 1076 int ret; 1077 1078 switch (clk->id) { 1079 case SCLK_EMMC_SAMPLE: 1080 case SCLK_SDMMC_SAMPLE: 1081 ret = rockchip_mmc_set_phase(clk, degrees); 1082 break; 1083 default: 1084 return -ENOENT; 1085 } 1086 1087 return ret; 1088 } 1089 1090 static int __maybe_unused rk3308_mac_set_parent(struct clk *clk, struct clk *parent) 1091 { 1092 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); 1093 1094 /* 1095 * If the requested parent is in the same clock-controller and 1096 * the id is SCLK_MAC_SRC, switch to the internal clock. 1097 */ 1098 if (parent->id == SCLK_MAC_SRC) { 1099 debug("%s: switching RMII to SCLK_MAC\n", __func__); 1100 rk_clrreg(&priv->cru->clksel_con[43], BIT(14)); 1101 } else { 1102 debug("%s: switching RMII to CLKIN\n", __func__); 1103 rk_setreg(&priv->cru->clksel_con[43], BIT(14)); 1104 } 1105 1106 return 0; 1107 } 1108 1109 static int __maybe_unused rk3308_clk_set_parent(struct clk *clk, struct clk *parent) 1110 { 1111 switch (clk->id) { 1112 case SCLK_MAC: 1113 return rk3308_mac_set_parent(clk, parent); 1114 default: 1115 break; 1116 } 1117 1118 debug("%s: unsupported clk %ld\n", __func__, clk->id); 1119 return -ENOENT; 1120 } 1121 1122 static struct clk_ops rk3308_clk_ops = { 1123 .get_rate = rk3308_clk_get_rate, 1124 .set_rate = rk3308_clk_set_rate, 1125 .get_phase = rk3308_clk_get_phase, 1126 .set_phase = rk3308_clk_set_phase, 1127 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) 1128 .set_parent = rk3308_clk_set_parent, 1129 #endif 1130 }; 1131 1132 static void rk3308_clk_init(struct udevice *dev) 1133 { 1134 struct rk3308_clk_priv *priv = dev_get_priv(dev); 1135 int ret; 1136 1137 if (rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 1138 priv->cru, APLL) != APLL_HZ) { 1139 ret = rk3308_armclk_set_clk(priv, APLL_HZ); 1140 if (ret < 0) 1141 printf("%s failed to set armclk rate\n", __func__); 1142 } 1143 1144 rk3308_clk_get_pll_rate(priv); 1145 1146 rk3308_bus_set_clk(priv, ACLK_BUS, BUS_ACLK_HZ); 1147 rk3308_bus_set_clk(priv, HCLK_BUS, BUS_HCLK_HZ); 1148 rk3308_bus_set_clk(priv, PCLK_BUS, BUS_PCLK_HZ); 1149 1150 rk3308_peri_set_clk(priv, ACLK_PERI, PERI_ACLK_HZ); 1151 rk3308_peri_set_clk(priv, HCLK_PERI, PERI_HCLK_HZ); 1152 rk3308_peri_set_clk(priv, PCLK_PERI, PERI_PCLK_HZ); 1153 1154 rk3308_audio_set_clk(priv, HCLK_AUDIO, AUDIO_HCLK_HZ); 1155 rk3308_audio_set_clk(priv, PCLK_AUDIO, AUDIO_PCLK_HZ); 1156 } 1157 1158 static int rk3308_clk_probe(struct udevice *dev) 1159 { 1160 struct rk3308_clk_priv *priv = dev_get_priv(dev); 1161 int ret; 1162 1163 priv->sync_kernel = false; 1164 if (!priv->armclk_enter_hz) 1165 priv->armclk_enter_hz = 1166 rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 1167 priv->cru, APLL); 1168 rk3308_clk_init(dev); 1169 if (!priv->armclk_init_hz) 1170 priv->armclk_init_hz = 1171 rockchip_pll_get_rate(&rk3308_pll_clks[APLL], 1172 priv->cru, APLL); 1173 1174 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 1175 ret = clk_set_defaults(dev); 1176 if (ret) 1177 debug("%s clk_set_defaults failed %d\n", __func__, ret); 1178 else 1179 priv->sync_kernel = true; 1180 1181 return 0; 1182 } 1183 1184 static int rk3308_clk_ofdata_to_platdata(struct udevice *dev) 1185 { 1186 struct rk3308_clk_priv *priv = dev_get_priv(dev); 1187 1188 priv->cru = dev_read_addr_ptr(dev); 1189 1190 return 0; 1191 } 1192 1193 static int rk3308_clk_bind(struct udevice *dev) 1194 { 1195 int ret; 1196 struct udevice *sys_child, *sf_child; 1197 struct sysreset_reg *priv; 1198 struct softreset_reg *sf_priv; 1199 1200 /* The reset driver does not have a device node, so bind it here */ 1201 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 1202 &sys_child); 1203 if (ret) { 1204 debug("Warning: No sysreset driver: ret=%d\n", ret); 1205 } else { 1206 priv = malloc(sizeof(struct sysreset_reg)); 1207 priv->glb_srst_fst_value = offsetof(struct rk3308_cru, 1208 glb_srst_fst); 1209 priv->glb_srst_snd_value = offsetof(struct rk3308_cru, 1210 glb_srst_snd); 1211 sys_child->priv = priv; 1212 } 1213 1214 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 1215 dev_ofnode(dev), &sf_child); 1216 if (ret) { 1217 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 1218 } else { 1219 sf_priv = malloc(sizeof(struct softreset_reg)); 1220 sf_priv->sf_reset_offset = offsetof(struct rk3308_cru, 1221 softrst_con[0]); 1222 sf_priv->sf_reset_num = 12; 1223 sf_child->priv = sf_priv; 1224 } 1225 1226 return 0; 1227 } 1228 1229 static const struct udevice_id rk3308_clk_ids[] = { 1230 { .compatible = "rockchip,rk3308-cru" }, 1231 { } 1232 }; 1233 1234 U_BOOT_DRIVER(rockchip_rk3308_cru) = { 1235 .name = "rockchip_rk3308_cru", 1236 .id = UCLASS_CLK, 1237 .of_match = rk3308_clk_ids, 1238 .priv_auto_alloc_size = sizeof(struct rk3308_clk_priv), 1239 .ofdata_to_platdata = rk3308_clk_ofdata_to_platdata, 1240 .ops = &rk3308_clk_ops, 1241 .bind = rk3308_clk_bind, 1242 .probe = rk3308_clk_probe, 1243 }; 1244 1245 /** 1246 * soc_clk_dump() - Print clock frequencies 1247 * Returns zero on success 1248 * 1249 * Implementation for the clk dump command. 1250 */ 1251 int soc_clk_dump(void) 1252 { 1253 struct udevice *cru_dev; 1254 struct rk3308_clk_priv *priv; 1255 const struct rk3308_clk_info *clk_dump; 1256 struct clk clk; 1257 unsigned long clk_count = ARRAY_SIZE(clks_dump); 1258 unsigned long rate; 1259 int i, ret; 1260 1261 ret = uclass_get_device_by_driver(UCLASS_CLK, 1262 DM_GET_DRIVER(rockchip_rk3308_cru), 1263 &cru_dev); 1264 if (ret) { 1265 printf("%s failed to get cru device\n", __func__); 1266 return ret; 1267 } 1268 1269 priv = dev_get_priv(cru_dev); 1270 printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n", 1271 priv->sync_kernel ? "sync kernel" : "uboot", 1272 priv->armclk_enter_hz / 1000, 1273 priv->armclk_init_hz / 1000, 1274 priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0, 1275 priv->set_armclk_rate ? " KHz" : "N/A"); 1276 for (i = 0; i < clk_count; i++) { 1277 clk_dump = &clks_dump[i]; 1278 if (clk_dump->name) { 1279 clk.id = clk_dump->id; 1280 ret = clk_request(cru_dev, &clk); 1281 if (ret < 0) 1282 return ret; 1283 1284 rate = clk_get_rate(&clk); 1285 clk_free(&clk); 1286 if (i == 0) { 1287 if (rate < 0) 1288 printf(" %s %s\n", clk_dump->name, 1289 "unknown"); 1290 else 1291 printf(" %s %lu KHz\n", clk_dump->name, 1292 rate / 1000); 1293 } else { 1294 if (rate < 0) 1295 printf(" %s %s\n", clk_dump->name, 1296 "unknown"); 1297 else 1298 printf(" %s %lu KHz\n", clk_dump->name, 1299 rate / 1000); 1300 } 1301 } 1302 } 1303 1304 return 0; 1305 } 1306