1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0 5 */ 6 7 #include <common.h> 8 #include <bitfield.h> 9 #include <clk-uclass.h> 10 #include <dm.h> 11 #include <errno.h> 12 #include <syscon.h> 13 #include <asm/arch/clock.h> 14 #include <asm/arch/cru_rk3328.h> 15 #include <asm/arch/hardware.h> 16 #include <asm/arch/grf_rk3328.h> 17 #include <asm/io.h> 18 #include <dm/lists.h> 19 #include <dt-bindings/clock/rk3328-cru.h> 20 21 DECLARE_GLOBAL_DATA_PTR; 22 23 #define RATE_TO_DIV(input_rate, output_rate) \ 24 ((input_rate) / (output_rate) - 1); 25 #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1)) 26 27 #ifndef CONFIG_SPL_BUILD 28 #define RK3328_CLK_DUMP(_id, _name, _iscru) \ 29 { \ 30 .id = _id, \ 31 .name = _name, \ 32 .is_cru = _iscru, \ 33 } 34 #endif 35 36 static struct rockchip_pll_rate_table rk3328_pll_rates[] = { 37 /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ 38 RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), 39 #ifndef CONFIG_SPL_BUILD 40 RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0), 41 RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), 42 #endif 43 RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0), 44 RK3036_PLL_RATE(800000000, 1, 200, 6, 1, 1, 0), 45 RK3036_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0), 46 #ifndef CONFIG_SPL_BUILD 47 RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0), 48 RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0), 49 #endif 50 { /* sentinel */ }, 51 }; 52 53 static struct rockchip_pll_rate_table rk3328_pll_frac_rates[] = { 54 /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ 55 #ifndef CONFIG_SPL_BUILD 56 RK3036_PLL_RATE(1016064000, 3, 127, 1, 1, 0, 134217), 57 /* vco = 1016064000 */ 58 RK3036_PLL_RATE(983040000, 24, 983, 1, 1, 0, 671088), 59 /* vco = 983040000 */ 60 #endif 61 RK3036_PLL_RATE(491520000, 24, 983, 2, 1, 0, 671088), 62 /* vco = 983040000 */ 63 #ifndef CONFIG_SPL_BUILD 64 RK3036_PLL_RATE(61440000, 6, 215, 7, 2, 0, 671088), 65 /* vco = 860156000 */ 66 RK3036_PLL_RATE(56448000, 12, 451, 4, 4, 0, 9797894), 67 /* vco = 903168000 */ 68 RK3036_PLL_RATE(40960000, 12, 409, 4, 5, 0, 10066329), 69 /* vco = 819200000 */ 70 #endif 71 { /* sentinel */ }, 72 }; 73 74 #define RK3328_CPUCLK_RATE(_rate, _aclk_div, _pclk_div) \ 75 { \ 76 .rate = _rate##U, \ 77 .aclk_div = _aclk_div, \ 78 .pclk_div = _pclk_div, \ 79 } 80 81 static struct rockchip_cpu_rate_table rk3328_cpu_rates[] = { 82 RK3328_CPUCLK_RATE(1200000000, 1, 5), 83 RK3328_CPUCLK_RATE(1008000000, 1, 5), 84 RK3328_CPUCLK_RATE(816000000, 1, 3), 85 RK3328_CPUCLK_RATE(600000000, 1, 3), 86 }; 87 88 #ifndef CONFIG_SPL_BUILD 89 static const struct rk3328_clk_info clks_dump[] = { 90 RK3328_CLK_DUMP(PLL_APLL, "apll", true), 91 RK3328_CLK_DUMP(PLL_DPLL, "dpll", true), 92 RK3328_CLK_DUMP(PLL_CPLL, "cpll", true), 93 RK3328_CLK_DUMP(PLL_GPLL, "gpll", true), 94 RK3328_CLK_DUMP(PLL_NPLL, "npll", true), 95 RK3328_CLK_DUMP(ARMCLK, "armclk", true), 96 RK3328_CLK_DUMP(ACLK_BUS_PRE, "aclk_bus", true), 97 RK3328_CLK_DUMP(HCLK_BUS_PRE, "hclk_bus", true), 98 RK3328_CLK_DUMP(PCLK_BUS_PRE, "pclk_bus", true), 99 RK3328_CLK_DUMP(ACLK_PERI_PRE, "aclk_peri", true), 100 RK3328_CLK_DUMP(HCLK_PERI, "hclk_peri", true), 101 RK3328_CLK_DUMP(PCLK_PERI, "pclk_peri", true), 102 }; 103 #endif 104 105 static struct rockchip_pll_clock rk3328_pll_clks[] = { 106 [APLL] = PLL(pll_rk3328, PLL_APLL, RK3328_PLL_CON(0), 107 RK3328_MODE_CON, 0, 10, 0, rk3328_pll_frac_rates), 108 [DPLL] = PLL(pll_rk3328, PLL_DPLL, RK3328_PLL_CON(8), 109 RK3328_MODE_CON, 4, 10, 0, NULL), 110 [CPLL] = PLL(pll_rk3328, PLL_CPLL, RK3328_PLL_CON(16), 111 RK3328_MODE_CON, 8, 10, 0, rk3328_pll_rates), 112 [GPLL] = PLL(pll_rk3328, PLL_GPLL, RK3328_PLL_CON(24), 113 RK3328_MODE_CON, 12, 10, 0, rk3328_pll_frac_rates), 114 [NPLL] = PLL(pll_rk3328, PLL_NPLL, RK3328_PLL_CON(40), 115 RK3328_MODE_CON, 1, 10, 0, rk3328_pll_rates), 116 }; 117 118 static ulong rk3328_armclk_set_clk(struct rk3328_clk_priv *priv, ulong hz) 119 { 120 struct rk3328_cru *cru = priv->cru; 121 const struct rockchip_cpu_rate_table *rate; 122 ulong old_rate; 123 124 rate = rockchip_get_cpu_settings(rk3328_cpu_rates, hz); 125 if (!rate) { 126 printf("%s unsupported rate\n", __func__); 127 return -EINVAL; 128 } 129 130 /* 131 * select apll as cpu/core clock pll source and 132 * set up dependent divisors for PERI and ACLK clocks. 133 * core hz : apll = 1:1 134 */ 135 old_rate = rockchip_pll_get_rate(&rk3328_pll_clks[NPLL], 136 priv->cru, NPLL); 137 if (old_rate > hz) { 138 if (rockchip_pll_set_rate(&rk3328_pll_clks[NPLL], 139 priv->cru, NPLL, hz)) 140 return -EINVAL; 141 rk_clrsetreg(&cru->clksel_con[0], 142 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK, 143 CORE_CLK_PLL_SEL_NPLL << CORE_CLK_PLL_SEL_SHIFT | 144 0 << CORE_DIV_CON_SHIFT); 145 rk_clrsetreg(&cru->clksel_con[1], 146 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK, 147 rate->aclk_div << CORE_ACLK_DIV_SHIFT | 148 rate->pclk_div << CORE_DBG_DIV_SHIFT); 149 } else if (old_rate < hz) { 150 rk_clrsetreg(&cru->clksel_con[1], 151 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK, 152 rate->aclk_div << CORE_ACLK_DIV_SHIFT | 153 rate->pclk_div << CORE_DBG_DIV_SHIFT); 154 rk_clrsetreg(&cru->clksel_con[0], 155 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK, 156 CORE_CLK_PLL_SEL_NPLL << CORE_CLK_PLL_SEL_SHIFT | 157 0 << CORE_DIV_CON_SHIFT); 158 if (rockchip_pll_set_rate(&rk3328_pll_clks[NPLL], 159 priv->cru, NPLL, hz)) 160 return -EINVAL; 161 } 162 163 return rockchip_pll_get_rate(&rk3328_pll_clks[NPLL], priv->cru, NPLL); 164 } 165 166 #ifndef CONFIG_SPL_BUILD 167 static ulong rk3328_i2c_get_clk(struct rk3328_clk_priv *priv, ulong clk_id) 168 { 169 struct rk3328_cru *cru = priv->cru; 170 u32 div, con; 171 172 switch (clk_id) { 173 case SCLK_I2C0: 174 con = readl(&cru->clksel_con[34]); 175 div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 176 break; 177 case SCLK_I2C1: 178 con = readl(&cru->clksel_con[34]); 179 div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 180 break; 181 case SCLK_I2C2: 182 con = readl(&cru->clksel_con[35]); 183 div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 184 break; 185 case SCLK_I2C3: 186 con = readl(&cru->clksel_con[35]); 187 div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; 188 break; 189 default: 190 printf("do not support this i2c bus\n"); 191 return -EINVAL; 192 } 193 194 return DIV_TO_RATE(priv->gpll_hz, div); 195 } 196 197 static ulong rk3328_i2c_set_clk(struct rk3328_clk_priv *priv, 198 ulong clk_id, uint hz) 199 { 200 struct rk3328_cru *cru = priv->cru; 201 int src_clk_div; 202 203 src_clk_div = priv->gpll_hz / hz; 204 assert(src_clk_div - 1 < 127); 205 206 switch (clk_id) { 207 case SCLK_I2C0: 208 rk_clrsetreg(&cru->clksel_con[34], 209 CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT | 210 CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT, 211 (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT | 212 CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT); 213 break; 214 case SCLK_I2C1: 215 rk_clrsetreg(&cru->clksel_con[34], 216 CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT | 217 CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT, 218 (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT | 219 CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT); 220 break; 221 case SCLK_I2C2: 222 rk_clrsetreg(&cru->clksel_con[35], 223 CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT | 224 CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT, 225 (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT | 226 CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT); 227 break; 228 case SCLK_I2C3: 229 rk_clrsetreg(&cru->clksel_con[35], 230 CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT | 231 CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT, 232 (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT | 233 CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT); 234 break; 235 default: 236 printf("do not support this i2c bus\n"); 237 return -EINVAL; 238 } 239 240 return DIV_TO_RATE(priv->gpll_hz, src_clk_div); 241 } 242 243 static ulong rk3328_gmac2io_set_clk(struct rk3328_clk_priv *priv, ulong rate) 244 { 245 struct rk3328_cru *cru = priv->cru; 246 struct rk3328_grf_regs *grf; 247 ulong ret; 248 249 grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 250 251 /* 252 * The RGMII CLK can be derived either from an external "clkin" 253 * or can be generated from internally by a divider from SCLK_MAC. 254 */ 255 if (readl(&grf->mac_con[1]) & BIT(10) && 256 readl(&grf->soc_con[4]) & BIT(14)) { 257 /* An external clock will always generate the right rate... */ 258 ret = rate; 259 } else { 260 u32 con = readl(&cru->clksel_con[27]); 261 ulong pll_rate; 262 u8 div; 263 264 if ((con >> GMAC2IO_PLL_SEL_SHIFT) & GMAC2IO_PLL_SEL_GPLL) 265 pll_rate = priv->gpll_hz; 266 else 267 pll_rate = priv->cpll_hz; 268 269 div = DIV_ROUND_UP(pll_rate, rate) - 1; 270 if (div <= 0x1f) 271 rk_clrsetreg(&cru->clksel_con[27], GMAC2IO_CLK_DIV_MASK, 272 div << GMAC2IO_CLK_DIV_SHIFT); 273 else 274 debug("Unsupported div for gmac:%d\n", div); 275 276 return DIV_TO_RATE(pll_rate, div); 277 } 278 279 return ret; 280 } 281 #endif 282 283 static ulong rk3328_mmc_get_clk(struct rk3328_clk_priv *priv, uint clk_id) 284 { 285 struct rk3328_cru *cru = priv->cru; 286 u32 div, con, con_id; 287 288 switch (clk_id) { 289 case HCLK_SDMMC: 290 case SCLK_SDMMC: 291 con_id = 30; 292 break; 293 case HCLK_EMMC: 294 case SCLK_EMMC: 295 case SCLK_EMMC_SAMPLE: 296 con_id = 32; 297 break; 298 default: 299 return -EINVAL; 300 } 301 con = readl(&cru->clksel_con[con_id]); 302 div = (con & CLK_EMMC_DIV_CON_MASK) >> CLK_EMMC_DIV_CON_SHIFT; 303 304 if ((con & CLK_EMMC_PLL_MASK) >> CLK_EMMC_PLL_SHIFT 305 == CLK_EMMC_PLL_SEL_24M) 306 return DIV_TO_RATE(OSC_HZ, div) / 2; 307 else 308 return DIV_TO_RATE(priv->gpll_hz, div) / 2; 309 } 310 311 static ulong rk3328_mmc_set_clk(struct rk3328_clk_priv *priv, 312 ulong clk_id, ulong set_rate) 313 { 314 struct rk3328_cru *cru = priv->cru; 315 int src_clk_div; 316 u32 con_id; 317 318 switch (clk_id) { 319 case HCLK_SDMMC: 320 case SCLK_SDMMC: 321 con_id = 30; 322 break; 323 case HCLK_EMMC: 324 case SCLK_EMMC: 325 con_id = 32; 326 break; 327 default: 328 return -EINVAL; 329 } 330 /* Select clk_sdmmc/emmc source from GPLL by default */ 331 /* mmc clock defaulg div 2 internal, need provide double in cru */ 332 src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, set_rate); 333 334 if (src_clk_div > 127) { 335 /* use 24MHz source for 400KHz clock */ 336 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate); 337 rk_clrsetreg(&cru->clksel_con[con_id], 338 CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK, 339 CLK_EMMC_PLL_SEL_24M << CLK_EMMC_PLL_SHIFT | 340 (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT); 341 } else { 342 rk_clrsetreg(&cru->clksel_con[con_id], 343 CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK, 344 CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT | 345 (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT); 346 } 347 348 return rk3328_mmc_get_clk(priv, clk_id); 349 } 350 351 #ifndef CONFIG_SPL_BUILD 352 static ulong rk3328_pwm_get_clk(struct rk3328_clk_priv *priv) 353 { 354 struct rk3328_cru *cru = priv->cru; 355 u32 div, con; 356 357 con = readl(&cru->clksel_con[24]); 358 div = (con & CLK_PWM_DIV_CON_MASK) >> CLK_PWM_DIV_CON_SHIFT; 359 360 return DIV_TO_RATE(priv->gpll_hz, div); 361 } 362 363 static ulong rk3328_pwm_set_clk(struct rk3328_clk_priv *priv, uint hz) 364 { 365 struct rk3328_cru *cru = priv->cru; 366 u32 div = priv->gpll_hz / hz; 367 368 rk_clrsetreg(&cru->clksel_con[24], 369 CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK, 370 CLK_PWM_PLL_SEL_GPLL << CLK_PWM_PLL_SEL_SHIFT | 371 (div - 1) << CLK_PWM_DIV_CON_SHIFT); 372 373 return DIV_TO_RATE(priv->gpll_hz, div); 374 } 375 376 static ulong rk3328_saradc_get_clk(struct rk3328_clk_priv *priv) 377 { 378 struct rk3328_cru *cru = priv->cru; 379 u32 div, val; 380 381 val = readl(&cru->clksel_con[23]); 382 div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT, 383 CLK_SARADC_DIV_CON_WIDTH); 384 385 return DIV_TO_RATE(OSC_HZ, div); 386 } 387 388 static ulong rk3328_saradc_set_clk(struct rk3328_clk_priv *priv, uint hz) 389 { 390 struct rk3328_cru *cru = priv->cru; 391 int src_clk_div; 392 393 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1; 394 assert(src_clk_div < 128); 395 396 rk_clrsetreg(&cru->clksel_con[23], 397 CLK_SARADC_DIV_CON_MASK, 398 src_clk_div << CLK_SARADC_DIV_CON_SHIFT); 399 400 return rk3328_saradc_get_clk(priv); 401 } 402 403 static ulong rk3328_tsadc_get_clk(struct rk3328_clk_priv *priv) 404 { 405 struct rk3328_cru *cru = priv->cru; 406 u32 div, val; 407 408 val = readl(&cru->clksel_con[22]); 409 div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT, 410 CLK_SARADC_DIV_CON_WIDTH); 411 412 return DIV_TO_RATE(OSC_HZ, div); 413 } 414 415 static ulong rk3328_tsadc_set_clk(struct rk3328_clk_priv *priv, uint hz) 416 { 417 struct rk3328_cru *cru = priv->cru; 418 int src_clk_div; 419 420 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1; 421 assert(src_clk_div < 128); 422 423 rk_clrsetreg(&cru->clksel_con[22], 424 CLK_SARADC_DIV_CON_MASK, 425 src_clk_div << CLK_SARADC_DIV_CON_SHIFT); 426 427 return rk3328_tsadc_get_clk(priv); 428 } 429 430 static ulong rk3328_vop_get_clk(struct rk3328_clk_priv *priv, ulong clk_id) 431 { 432 struct rk3328_cru *cru = priv->cru; 433 u32 div, con, parent; 434 435 switch (clk_id) { 436 case ACLK_VOP_PRE: 437 case ACLK_VOP: 438 con = readl(&cru->clksel_con[39]); 439 div = (con & ACLK_VOP_DIV_CON_MASK) >> ACLK_VOP_DIV_CON_SHIFT; 440 parent = priv->cpll_hz; 441 break; 442 case ACLK_VIO_PRE: 443 case ACLK_VIO: 444 con = readl(&cru->clksel_con[37]); 445 div = (con & ACLK_VIO_DIV_CON_MASK) >> ACLK_VIO_DIV_CON_SHIFT; 446 parent = priv->cpll_hz; 447 break; 448 case HCLK_VIO_PRE: 449 case HCLK_VIO: 450 parent = rk3328_vop_get_clk(priv, ACLK_VIO_PRE); 451 con = readl(&cru->clksel_con[37]); 452 div = (con & HCLK_VIO_DIV_CON_MASK) >> HCLK_VIO_DIV_CON_SHIFT; 453 break; 454 default: 455 return -ENOENT; 456 } 457 458 return DIV_TO_RATE(parent, div); 459 } 460 461 static ulong rk3328_vop_set_clk(struct rk3328_clk_priv *priv, 462 ulong clk_id, uint hz) 463 { 464 struct rk3328_cru *cru = priv->cru; 465 int src_clk_div; 466 u32 con, parent; 467 468 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz); 469 assert(src_clk_div - 1 < 31); 470 471 switch (clk_id) { 472 case ACLK_VOP_PRE: 473 case ACLK_VOP: 474 rk_clrsetreg(&cru->clksel_con[39], 475 ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK, 476 ACLK_VOP_PLL_SEL_CPLL << ACLK_VOP_PLL_SEL_SHIFT | 477 (src_clk_div - 1) << ACLK_VOP_DIV_CON_SHIFT); 478 break; 479 case ACLK_VIO_PRE: 480 case ACLK_VIO: 481 rk_clrsetreg(&cru->clksel_con[37], 482 ACLK_VIO_PLL_SEL_MASK | ACLK_VIO_DIV_CON_MASK, 483 ACLK_VIO_PLL_SEL_CPLL << ACLK_VIO_PLL_SEL_SHIFT | 484 (src_clk_div - 1) << ACLK_VIO_DIV_CON_SHIFT); 485 break; 486 case HCLK_VIO_PRE: 487 case HCLK_VIO: 488 src_clk_div = DIV_ROUND_UP(rk3328_vop_get_clk(priv, 489 ACLK_VIO_PRE), 490 hz); 491 rk_clrsetreg(&cru->clksel_con[37], 492 HCLK_VIO_DIV_CON_MASK, 493 (src_clk_div - 1) << HCLK_VIO_DIV_CON_SHIFT); 494 break; 495 case DCLK_LCDC: 496 con = readl(&cru->clksel_con[40]); 497 con = (con & DCLK_LCDC_SEL_MASK) >> DCLK_LCDC_SEL_SHIFT; 498 if (con) { 499 parent = readl(&cru->clksel_con[40]); 500 parent = (parent & DCLK_LCDC_PLL_SEL_MASK) >> 501 DCLK_LCDC_PLL_SEL_SHIFT; 502 if (parent) 503 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz); 504 else 505 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 506 507 rk_clrsetreg(&cru->clksel_con[40], 508 DCLK_LCDC_DIV_CON_MASK, 509 (src_clk_div - 1) << 510 DCLK_LCDC_DIV_CON_SHIFT); 511 } 512 break; 513 default: 514 printf("do not support this vop freq\n"); 515 return -EINVAL; 516 } 517 518 return rk3328_vop_get_clk(priv, clk_id); 519 } 520 #endif 521 522 static ulong rk3328_bus_get_clk(struct rk3328_clk_priv *priv, ulong clk_id) 523 { 524 struct rk3328_cru *cru = priv->cru; 525 u32 div, con, parent; 526 527 switch (clk_id) { 528 case ACLK_BUS_PRE: 529 con = readl(&cru->clksel_con[0]); 530 div = (con & ACLK_BUS_DIV_CON_MASK) >> ACLK_BUS_DIV_CON_SHIFT; 531 parent = priv->cpll_hz; 532 break; 533 case HCLK_BUS_PRE: 534 con = readl(&cru->clksel_con[1]); 535 div = (con & HCLK_BUS_DIV_CON_MASK) >> HCLK_BUS_DIV_CON_SHIFT; 536 parent = rk3328_bus_get_clk(priv, ACLK_BUS_PRE); 537 break; 538 case PCLK_BUS_PRE: 539 con = readl(&cru->clksel_con[1]); 540 div = (con & PCLK_BUS_DIV_CON_MASK) >> PCLK_BUS_DIV_CON_SHIFT; 541 parent = rk3328_bus_get_clk(priv, ACLK_BUS_PRE); 542 break; 543 default: 544 return -ENOENT; 545 } 546 547 return DIV_TO_RATE(parent, div); 548 } 549 550 static ulong rk3328_bus_set_clk(struct rk3328_clk_priv *priv, 551 ulong clk_id, ulong hz) 552 { 553 struct rk3328_cru *cru = priv->cru; 554 int src_clk_div; 555 556 /* 557 * select gpll as pd_bus bus clock source and 558 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 559 */ 560 switch (clk_id) { 561 case ACLK_BUS_PRE: 562 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz); 563 assert(src_clk_div - 1 < 31); 564 rk_clrsetreg(&cru->clksel_con[0], 565 CLK_BUS_PLL_SEL_MASK | ACLK_BUS_DIV_CON_MASK, 566 CLK_BUS_PLL_SEL_CPLL << CLK_BUS_PLL_SEL_SHIFT | 567 (src_clk_div - 1) << ACLK_BUS_DIV_CON_SHIFT); 568 break; 569 case HCLK_BUS_PRE: 570 src_clk_div = DIV_ROUND_UP(rk3328_bus_get_clk(priv, 571 ACLK_BUS_PRE), 572 hz); 573 assert(src_clk_div - 1 < 3); 574 rk_clrsetreg(&cru->clksel_con[1], 575 HCLK_BUS_DIV_CON_MASK, 576 (src_clk_div - 1) << HCLK_BUS_DIV_CON_SHIFT); 577 break; 578 case PCLK_BUS_PRE: 579 src_clk_div = DIV_ROUND_UP(rk3328_bus_get_clk(priv, 580 ACLK_BUS_PRE), 581 hz); 582 assert(src_clk_div - 1 < 7); 583 rk_clrsetreg(&cru->clksel_con[1], 584 PCLK_BUS_DIV_CON_MASK, 585 (src_clk_div - 1) << PCLK_BUS_DIV_CON_SHIFT); 586 break; 587 default: 588 printf("do not support this bus freq\n"); 589 return -EINVAL; 590 } 591 return rk3328_bus_get_clk(priv, clk_id); 592 } 593 594 static ulong rk3328_peri_get_clk(struct rk3328_clk_priv *priv, ulong clk_id) 595 { 596 struct rk3328_cru *cru = priv->cru; 597 u32 div, con, parent; 598 599 switch (clk_id) { 600 case ACLK_PERI_PRE: 601 con = readl(&cru->clksel_con[28]); 602 div = (con & ACLK_PERI_DIV_CON_MASK) >> ACLK_PERI_DIV_CON_SHIFT; 603 parent = priv->cpll_hz; 604 break; 605 case HCLK_PERI: 606 con = readl(&cru->clksel_con[29]); 607 div = (con & HCLK_PERI_DIV_CON_MASK) >> HCLK_PERI_DIV_CON_SHIFT; 608 parent = rk3328_peri_get_clk(priv, ACLK_PERI_PRE); 609 break; 610 case PCLK_PERI: 611 con = readl(&cru->clksel_con[29]); 612 div = (con & PCLK_PERI_DIV_CON_MASK) >> PCLK_PERI_DIV_CON_SHIFT; 613 parent = rk3328_peri_get_clk(priv, ACLK_PERI_PRE); 614 break; 615 default: 616 return -ENOENT; 617 } 618 619 return DIV_TO_RATE(parent, div); 620 } 621 622 static ulong rk3328_peri_set_clk(struct rk3328_clk_priv *priv, 623 ulong clk_id, ulong hz) 624 { 625 struct rk3328_cru *cru = priv->cru; 626 int src_clk_div; 627 628 /* 629 * select gpll as pd_bus bus clock source and 630 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 631 */ 632 switch (clk_id) { 633 case ACLK_PERI_PRE: 634 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz); 635 assert(src_clk_div - 1 < 31); 636 rk_clrsetreg(&cru->clksel_con[28], 637 CLK_PERI_PLL_SEL_MASK | ACLK_PERI_DIV_CON_MASK, 638 CLK_PERI_PLL_SEL_CPLL << CLK_PERI_PLL_SEL_SHIFT | 639 (src_clk_div - 1) << ACLK_PERI_DIV_CON_SHIFT); 640 break; 641 case HCLK_PERI: 642 src_clk_div = DIV_ROUND_UP(rk3328_peri_get_clk(priv, 643 ACLK_PERI_PRE), 644 hz); 645 assert(src_clk_div - 1 < 3); 646 rk_clrsetreg(&cru->clksel_con[29], 647 HCLK_PERI_DIV_CON_MASK, 648 (src_clk_div - 1) << HCLK_PERI_DIV_CON_SHIFT); 649 break; 650 case PCLK_PERI: 651 src_clk_div = DIV_ROUND_UP(rk3328_peri_get_clk(priv, 652 ACLK_PERI_PRE), 653 hz); 654 assert(src_clk_div - 1 < 7); 655 rk_clrsetreg(&cru->clksel_con[29], 656 PCLK_PERI_DIV_CON_MASK, 657 (src_clk_div - 1) << PCLK_PERI_DIV_CON_SHIFT); 658 break; 659 default: 660 printf("do not support this bus freq\n"); 661 return -EINVAL; 662 } 663 664 return rk3328_peri_get_clk(priv, clk_id); 665 } 666 667 #ifndef CONFIG_SPL_BUILD 668 static ulong rk3328_crypto_get_clk(struct rk3328_clk_priv *priv, ulong clk_id) 669 { 670 struct rk3328_cru *cru = priv->cru; 671 u32 div, con, parent; 672 673 switch (clk_id) { 674 case SCLK_CRYPTO: 675 con = readl(&cru->clksel_con[20]); 676 div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT; 677 parent = priv->gpll_hz; 678 break; 679 default: 680 return -ENOENT; 681 } 682 683 return DIV_TO_RATE(parent, div); 684 } 685 686 static ulong rk3328_crypto_set_clk(struct rk3328_clk_priv *priv, ulong clk_id, 687 ulong hz) 688 { 689 struct rk3328_cru *cru = priv->cru; 690 int src_clk_div; 691 692 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 693 assert(src_clk_div - 1 <= 127); 694 695 /* 696 * select gpll as crypto clock source and 697 * set up dependent divisors for crypto clocks. 698 */ 699 switch (clk_id) { 700 case SCLK_CRYPTO: 701 rk_clrsetreg(&cru->clksel_con[20], 702 CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK, 703 CRYPTO_PLL_SEL_GPLL << CRYPTO_PLL_SEL_SHIFT | 704 (src_clk_div - 1) << CRYPTO_DIV_SHIFT); 705 break; 706 default: 707 printf("do not support this peri freq\n"); 708 return -EINVAL; 709 } 710 711 return rk3328_crypto_get_clk(priv, clk_id); 712 } 713 #endif 714 715 static ulong rk3328_clk_get_rate(struct clk *clk) 716 { 717 struct rk3328_clk_priv *priv = dev_get_priv(clk->dev); 718 ulong rate = 0; 719 720 #ifndef CONFIG_SPL_BUILD 721 if (!priv->gpll_hz) { 722 priv->gpll_hz = rockchip_pll_get_rate(&rk3328_pll_clks[GPLL], 723 priv->cru, GPLL); 724 debug("%s gpll=%lu\n", __func__, priv->gpll_hz); 725 } 726 if (!priv->cpll_hz) { 727 priv->cpll_hz = rockchip_pll_get_rate(&rk3328_pll_clks[CPLL], 728 priv->cru, CPLL); 729 debug("%s cpll=%lu\n", __func__, priv->cpll_hz); 730 } 731 #endif 732 733 switch (clk->id) { 734 case PLL_APLL: 735 case PLL_DPLL: 736 case PLL_CPLL: 737 case PLL_GPLL: 738 case PLL_NPLL: 739 rate = rockchip_pll_get_rate(&rk3328_pll_clks[clk->id - 1], 740 priv->cru, clk->id - 1); 741 break; 742 case ARMCLK: 743 rate = rockchip_pll_get_rate(&rk3328_pll_clks[NPLL], 744 priv->cru, NPLL); 745 break; 746 case ACLK_BUS_PRE: 747 case HCLK_BUS_PRE: 748 case PCLK_BUS_PRE: 749 rate = rk3328_bus_get_clk(priv, clk->id); 750 break; 751 case ACLK_PERI_PRE: 752 case HCLK_PERI: 753 case PCLK_PERI: 754 rate = rk3328_peri_get_clk(priv, clk->id); 755 break; 756 case HCLK_SDMMC: 757 case HCLK_EMMC: 758 case SCLK_SDMMC: 759 case SCLK_EMMC: 760 case SCLK_EMMC_SAMPLE: 761 rate = rk3328_mmc_get_clk(priv, clk->id); 762 break; 763 #ifndef CONFIG_SPL_BUILD 764 case SCLK_I2C0: 765 case SCLK_I2C1: 766 case SCLK_I2C2: 767 case SCLK_I2C3: 768 rate = rk3328_i2c_get_clk(priv, clk->id); 769 break; 770 case SCLK_PWM: 771 rate = rk3328_pwm_get_clk(priv); 772 break; 773 case SCLK_SARADC: 774 rate = rk3328_saradc_get_clk(priv); 775 break; 776 case SCLK_TSADC: 777 rate = rk3328_tsadc_get_clk(priv); 778 break; 779 case ACLK_VOP_PRE: 780 case ACLK_VIO_PRE: 781 case HCLK_VIO_PRE: 782 case ACLK_VOP: 783 case ACLK_VIO: 784 case HCLK_VIO: 785 rate = rk3328_vop_get_clk(priv, clk->id); 786 break; 787 case SCLK_CRYPTO: 788 rate = rk3328_crypto_get_clk(priv, clk->id); 789 break; 790 #endif 791 default: 792 return -ENOENT; 793 } 794 795 return rate; 796 } 797 798 static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate) 799 { 800 struct rk3328_clk_priv *priv = dev_get_priv(clk->dev); 801 ulong ret = 0; 802 803 switch (clk->id) { 804 case PLL_APLL: 805 case PLL_DPLL: 806 case PLL_NPLL: 807 ret = rockchip_pll_set_rate(&rk3328_pll_clks[clk->id - 1], 808 priv->cru, clk->id - 1, rate); 809 break; 810 case PLL_CPLL: 811 ret = rockchip_pll_set_rate(&rk3328_pll_clks[CPLL], 812 priv->cru, CPLL, rate); 813 priv->cpll_hz = rate; 814 break; 815 case PLL_GPLL: 816 ret = rockchip_pll_set_rate(&rk3328_pll_clks[GPLL], 817 priv->cru, GPLL, rate); 818 priv->gpll_hz = rate; 819 break; 820 case ARMCLK: 821 if (priv->armclk_hz) 822 ret = rk3328_armclk_set_clk(priv, rate); 823 priv->armclk_hz = rate; 824 break; 825 case ACLK_BUS_PRE: 826 case HCLK_BUS_PRE: 827 case PCLK_BUS_PRE: 828 rate = rk3328_bus_set_clk(priv, clk->id, rate); 829 break; 830 case ACLK_PERI_PRE: 831 case HCLK_PERI: 832 case PCLK_PERI: 833 rate = rk3328_peri_set_clk(priv, clk->id, rate); 834 break; 835 case HCLK_SDMMC: 836 case HCLK_EMMC: 837 case SCLK_SDMMC: 838 case SCLK_EMMC: 839 ret = rk3328_mmc_set_clk(priv, clk->id, rate); 840 break; 841 #ifndef CONFIG_SPL_BUILD 842 case SCLK_I2C0: 843 case SCLK_I2C1: 844 case SCLK_I2C2: 845 case SCLK_I2C3: 846 ret = rk3328_i2c_set_clk(priv, clk->id, rate); 847 break; 848 case SCLK_MAC2IO: 849 ret = rk3328_gmac2io_set_clk(priv, rate); 850 break; 851 case SCLK_PWM: 852 ret = rk3328_pwm_set_clk(priv, rate); 853 break; 854 case SCLK_SARADC: 855 ret = rk3328_saradc_set_clk(priv, rate); 856 break; 857 case SCLK_TSADC: 858 ret = rk3328_tsadc_set_clk(priv, rate); 859 break; 860 case DCLK_LCDC: 861 case ACLK_VOP_PRE: 862 case ACLK_VIO_PRE: 863 case HCLK_VIO_PRE: 864 case ACLK_VOP: 865 case ACLK_VIO: 866 case HCLK_VIO: 867 rate = rk3328_vop_set_clk(priv, clk->id, rate); 868 break; 869 case SCLK_CRYPTO: 870 rate = rk3328_crypto_set_clk(priv, clk->id, rate); 871 break; 872 #endif 873 case SCLK_PDM: 874 case SCLK_RTC32K: 875 case SCLK_UART0: 876 case SCLK_UART1: 877 case SCLK_UART2: 878 case SCLK_SDIO: 879 case SCLK_TSP: 880 case SCLK_WIFI: 881 case ACLK_RGA_PRE: 882 case SCLK_RGA: 883 case ACLK_RKVDEC_PRE: 884 case ACLK_RKVENC: 885 case ACLK_VPU_PRE: 886 case SCLK_VDEC_CABAC: 887 case SCLK_VDEC_CORE: 888 case SCLK_VENC_CORE: 889 case SCLK_VENC_DSP: 890 case SCLK_EFUSE: 891 case PCLK_DDR: 892 case ACLK_GMAC: 893 case PCLK_GMAC: 894 case SCLK_USB3OTG_SUSPEND: 895 return 0; 896 default: 897 return -ENOENT; 898 } 899 900 return ret; 901 } 902 903 #ifndef CONFIG_SPL_BUILD 904 static int rk3328_gmac2io_set_parent(struct clk *clk, struct clk *parent) 905 { 906 struct rk3328_grf_regs *grf; 907 const char *clock_output_name; 908 int ret; 909 910 grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 911 912 /* 913 * If the requested parent is in the same clock-controller and the id 914 * is SCLK_MAC2IO_SRC ("clk_mac2io_src"), switch to the internal clock. 915 */ 916 if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2IO_SRC)) { 917 debug("%s: switching RGMII to SCLK_MAC2IO_SRC\n", __func__); 918 rk_clrreg(&grf->mac_con[1], BIT(10)); 919 return 0; 920 } 921 922 /* 923 * Otherwise, we need to check the clock-output-names of the 924 * requested parent to see if the requested id is "gmac_clkin". 925 */ 926 ret = dev_read_string_index(parent->dev, "clock-output-names", 927 parent->id, &clock_output_name); 928 if (ret < 0) 929 return -ENODATA; 930 931 /* If this is "gmac_clkin", switch to the external clock input */ 932 if (!strcmp(clock_output_name, "gmac_clkin")) { 933 debug("%s: switching RGMII to CLKIN\n", __func__); 934 rk_setreg(&grf->mac_con[1], BIT(10)); 935 return 0; 936 } 937 938 return -EINVAL; 939 } 940 941 static int rk3328_gmac2io_ext_set_parent(struct clk *clk, struct clk *parent) 942 { 943 struct rk3328_grf_regs *grf; 944 const char *clock_output_name; 945 int ret; 946 947 grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 948 949 /* 950 * If the requested parent is in the same clock-controller and the id 951 * is SCLK_MAC2IO ("clk_mac2io"), switch to the internal clock. 952 */ 953 if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2IO)) { 954 debug("%s: switching RGMII to SCLK_MAC2IO\n", __func__); 955 rk_clrreg(&grf->soc_con[4], BIT(14)); 956 return 0; 957 } 958 959 /* 960 * Otherwise, we need to check the clock-output-names of the 961 * requested parent to see if the requested id is "gmac_clkin". 962 */ 963 ret = dev_read_string_index(parent->dev, "clock-output-names", 964 parent->id, &clock_output_name); 965 if (ret < 0) 966 return -ENODATA; 967 968 /* If this is "gmac_clkin", switch to the external clock input */ 969 if (!strcmp(clock_output_name, "gmac_clkin")) { 970 debug("%s: switching RGMII to CLKIN\n", __func__); 971 rk_setreg(&grf->soc_con[4], BIT(14)); 972 return 0; 973 } 974 975 return -EINVAL; 976 } 977 978 static int rk3328_lcdc_set_parent(struct clk *clk, struct clk *parent) 979 { 980 struct rk3328_clk_priv *priv = dev_get_priv(clk->dev); 981 982 if (parent->id == HDMIPHY) 983 rk_clrsetreg(&priv->cru->clksel_con[40], 984 DCLK_LCDC_SEL_MASK, 985 DCLK_LCDC_SEL_HDMIPHY << DCLK_LCDC_SEL_SHIFT); 986 else if (parent->id == PLL_CPLL) 987 rk_clrsetreg(&priv->cru->clksel_con[40], 988 DCLK_LCDC_SEL_MASK | DCLK_LCDC_PLL_SEL_MASK, 989 (DCLK_LCDC_SEL_PLL << DCLK_LCDC_SEL_SHIFT) | 990 (DCLK_LCDC_PLL_SEL_CPLL << 991 DCLK_LCDC_PLL_SEL_SHIFT)); 992 else 993 rk_clrsetreg(&priv->cru->clksel_con[40], 994 DCLK_LCDC_SEL_MASK | DCLK_LCDC_PLL_SEL_MASK, 995 (DCLK_LCDC_SEL_PLL << DCLK_LCDC_SEL_SHIFT) | 996 (DCLK_LCDC_PLL_SEL_GPLL << 997 DCLK_LCDC_PLL_SEL_SHIFT)); 998 999 return 0; 1000 } 1001 #endif 1002 1003 static int rk3328_clk_set_parent(struct clk *clk, struct clk *parent) 1004 { 1005 switch (clk->id) { 1006 #ifndef CONFIG_SPL_BUILD 1007 case SCLK_MAC2IO: 1008 return rk3328_gmac2io_set_parent(clk, parent); 1009 case SCLK_MAC2IO_EXT: 1010 return rk3328_gmac2io_ext_set_parent(clk, parent); 1011 case DCLK_LCDC: 1012 return rk3328_lcdc_set_parent(clk, parent); 1013 #endif 1014 case SCLK_PDM: 1015 case SCLK_RTC32K: 1016 case SCLK_UART0: 1017 case SCLK_UART1: 1018 case SCLK_UART2: 1019 return 0; 1020 } 1021 1022 debug("%s: unsupported clk %ld\n", __func__, clk->id); 1023 return -ENOENT; 1024 } 1025 1026 #define ROCKCHIP_MMC_DELAY_SEL BIT(10) 1027 #define ROCKCHIP_MMC_DEGREE_MASK 0x3 1028 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2 1029 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 1030 1031 #define PSECS_PER_SEC 1000000000000LL 1032 /* 1033 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 1034 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 1035 */ 1036 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 1037 1038 int rk3328_mmc_get_phase(struct clk *clk) 1039 { 1040 struct rk3328_clk_priv *priv = dev_get_priv(clk->dev); 1041 struct rk3328_cru *cru = priv->cru; 1042 u32 raw_value, delay_num; 1043 u16 degrees = 0; 1044 ulong rate; 1045 1046 rate = rk3328_clk_get_rate(clk); 1047 1048 if (rate < 0) 1049 return rate; 1050 1051 if (clk->id == SCLK_EMMC_SAMPLE) 1052 raw_value = readl(&cru->emmc_con[1]); 1053 else if (clk->id == SCLK_SDMMC_SAMPLE) 1054 raw_value = readl(&cru->sdmmc_con[1]); 1055 else 1056 raw_value = readl(&cru->sdio_con[1]); 1057 1058 raw_value >>= 1; 1059 degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; 1060 1061 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 1062 /* degrees/delaynum * 10000 */ 1063 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 1064 36 * (rate / 1000000); 1065 1066 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 1067 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 1068 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 1069 } 1070 1071 return degrees % 360; 1072 } 1073 1074 int rk3328_mmc_set_phase(struct clk *clk, u32 degrees) 1075 { 1076 struct rk3328_clk_priv *priv = dev_get_priv(clk->dev); 1077 struct rk3328_cru *cru = priv->cru; 1078 u8 nineties, remainder, delay_num; 1079 u32 raw_value, delay; 1080 ulong rate; 1081 1082 rate = rk3328_clk_get_rate(clk); 1083 1084 if (rate < 0) 1085 return rate; 1086 1087 nineties = degrees / 90; 1088 remainder = (degrees % 90); 1089 1090 /* 1091 * Convert to delay; do a little extra work to make sure we 1092 * don't overflow 32-bit / 64-bit numbers. 1093 */ 1094 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 1095 delay *= remainder; 1096 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 1097 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 1098 1099 delay_num = (u8)min_t(u32, delay, 255); 1100 1101 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 1102 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 1103 raw_value |= nineties; 1104 1105 raw_value <<= 1; 1106 if (clk->id == SCLK_EMMC_SAMPLE) 1107 writel(raw_value | 0xffff0000, &cru->emmc_con[1]); 1108 else if (clk->id == SCLK_SDMMC_SAMPLE) 1109 writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]); 1110 else 1111 writel(raw_value | 0xffff0000, &cru->sdio_con[1]); 1112 1113 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 1114 degrees, delay_num, raw_value, rk3328_mmc_get_phase(clk)); 1115 1116 return 0; 1117 } 1118 1119 static int rk3328_clk_get_phase(struct clk *clk) 1120 { 1121 int ret; 1122 1123 debug("%s %ld\n", __func__, clk->id); 1124 switch (clk->id) { 1125 case SCLK_EMMC_SAMPLE: 1126 case SCLK_SDMMC_SAMPLE: 1127 case SCLK_SDIO_SAMPLE: 1128 ret = rk3328_mmc_get_phase(clk); 1129 break; 1130 default: 1131 return -ENOENT; 1132 } 1133 1134 return ret; 1135 } 1136 1137 static int rk3328_clk_set_phase(struct clk *clk, int degrees) 1138 { 1139 int ret; 1140 1141 debug("%s %ld\n", __func__, clk->id); 1142 switch (clk->id) { 1143 case SCLK_EMMC_SAMPLE: 1144 case SCLK_SDMMC_SAMPLE: 1145 case SCLK_SDIO_SAMPLE: 1146 ret = rk3328_mmc_set_phase(clk, degrees); 1147 break; 1148 default: 1149 return -ENOENT; 1150 } 1151 1152 return ret; 1153 } 1154 1155 static struct clk_ops rk3328_clk_ops = { 1156 .get_rate = rk3328_clk_get_rate, 1157 .set_rate = rk3328_clk_set_rate, 1158 .set_parent = rk3328_clk_set_parent, 1159 .get_phase = rk3328_clk_get_phase, 1160 .set_phase = rk3328_clk_set_phase, 1161 }; 1162 1163 static void rkclk_init(struct rk3328_clk_priv *priv) 1164 { 1165 if (rockchip_pll_get_rate(&rk3328_pll_clks[NPLL], 1166 priv->cru, NPLL) != APLL_HZ) 1167 rk3328_armclk_set_clk(priv, APLL_HZ); 1168 1169 priv->gpll_hz = rockchip_pll_get_rate(&rk3328_pll_clks[GPLL], 1170 priv->cru, GPLL); 1171 priv->cpll_hz = rockchip_pll_get_rate(&rk3328_pll_clks[CPLL], 1172 priv->cru, CPLL); 1173 1174 /* before set pll set child div first */ 1175 rk_clrsetreg(&priv->cru->clksel_con[24], (0x3f << 8) | (0x3f << 0), 1176 (0x17 << 8) | (0x17 << 0)); 1177 rk_clrsetreg(&priv->cru->clksel_con[27], (0x1f << 8) | (0x1f << 0), 1178 (0x17 << 8) | (0x17 << 0)); 1179 rk_clrsetreg(&priv->cru->clksel_con[31], 0xff << 0, 0xb << 0); 1180 rk_clrsetreg(&priv->cru->clksel_con[43], 0xff << 0, 0xb << 0); 1181 rk_clrsetreg(&priv->cru->clksel_con[52], 0x1f << 8, 0x5 << 8); 1182 1183 rockchip_pll_set_rate(&rk3328_pll_clks[GPLL], 1184 priv->cru, GPLL, GPLL_HZ); 1185 priv->gpll_hz = GPLL_HZ; 1186 1187 rockchip_pll_set_rate(&rk3328_pll_clks[CPLL], 1188 priv->cru, CPLL, CPLL_HZ); 1189 priv->cpll_hz = CPLL_HZ; 1190 1191 rk3328_bus_set_clk(priv, ACLK_BUS_PRE, ACLK_BUS_HZ); 1192 rk3328_bus_set_clk(priv, HCLK_BUS_PRE, ACLK_BUS_HZ / 2); 1193 rk3328_bus_set_clk(priv, PCLK_BUS_PRE, ACLK_BUS_HZ / 2); 1194 rk3328_peri_set_clk(priv, ACLK_PERI_PRE, ACLK_PERI_HZ); 1195 rk3328_peri_set_clk(priv, HCLK_PERI, ACLK_PERI_HZ / 2); 1196 rk3328_peri_set_clk(priv, PCLK_PERI, ACLK_PERI_HZ / 2); 1197 /*rk3328_mmc_set_clk(priv, SCLK_EMMC, rate);*/ 1198 1199 /* set usbphy and hdmiphy from phy */ 1200 rk_clrsetreg(&priv->cru->misc, (0x1 << 13) | 1201 (0x1 << 15), (0 << 15) | (0 << 13)); 1202 } 1203 1204 static int rk3328_clk_probe(struct udevice *dev) 1205 { 1206 struct rk3328_clk_priv *priv = dev_get_priv(dev); 1207 int ret = 0; 1208 1209 priv->sync_kernel = false; 1210 if (!priv->armclk_enter_hz) 1211 priv->armclk_enter_hz = 1212 rockchip_pll_get_rate(&rk3328_pll_clks[NPLL], 1213 priv->cru, NPLL); 1214 rkclk_init(priv); 1215 if (!priv->armclk_init_hz) 1216 priv->armclk_init_hz = 1217 rockchip_pll_get_rate(&rk3328_pll_clks[NPLL], 1218 priv->cru, NPLL); 1219 1220 ret = clk_set_defaults(dev); 1221 if (ret) 1222 debug("%s clk_set_defaults failed %d\n", __func__, ret); 1223 else 1224 priv->sync_kernel = true; 1225 1226 return 0; 1227 } 1228 1229 static int rk3328_clk_ofdata_to_platdata(struct udevice *dev) 1230 { 1231 struct rk3328_clk_priv *priv = dev_get_priv(dev); 1232 1233 priv->cru = dev_read_addr_ptr(dev); 1234 1235 return 0; 1236 } 1237 1238 static int rk3328_clk_bind(struct udevice *dev) 1239 { 1240 int ret; 1241 struct udevice *sys_child, *sf_child; 1242 struct sysreset_reg *priv; 1243 struct softreset_reg *sf_priv; 1244 1245 /* The reset driver does not have a device node, so bind it here */ 1246 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 1247 &sys_child); 1248 if (ret) { 1249 debug("Warning: No sysreset driver: ret=%d\n", ret); 1250 } else { 1251 priv = malloc(sizeof(struct sysreset_reg)); 1252 priv->glb_srst_fst_value = offsetof(struct rk3328_cru, 1253 glb_srst_fst_value); 1254 priv->glb_srst_snd_value = offsetof(struct rk3328_cru, 1255 glb_srst_snd_value); 1256 sys_child->priv = priv; 1257 } 1258 1259 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 1260 dev_ofnode(dev), &sf_child); 1261 if (ret) { 1262 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 1263 } else { 1264 sf_priv = malloc(sizeof(struct softreset_reg)); 1265 sf_priv->sf_reset_offset = offsetof(struct rk3328_cru, 1266 softrst_con[0]); 1267 sf_priv->sf_reset_num = 12; 1268 sf_child->priv = sf_priv; 1269 } 1270 1271 return 0; 1272 } 1273 1274 static const struct udevice_id rk3328_clk_ids[] = { 1275 { .compatible = "rockchip,rk3328-cru" }, 1276 { } 1277 }; 1278 1279 U_BOOT_DRIVER(rockchip_rk3328_cru) = { 1280 .name = "rockchip_rk3328_cru", 1281 .id = UCLASS_CLK, 1282 .of_match = rk3328_clk_ids, 1283 .priv_auto_alloc_size = sizeof(struct rk3328_clk_priv), 1284 .ofdata_to_platdata = rk3328_clk_ofdata_to_platdata, 1285 .ops = &rk3328_clk_ops, 1286 .bind = rk3328_clk_bind, 1287 .probe = rk3328_clk_probe, 1288 }; 1289 1290 #ifndef CONFIG_SPL_BUILD 1291 /** 1292 * soc_clk_dump() - Print clock frequencies 1293 * Returns zero on success 1294 * 1295 * Implementation for the clk dump command. 1296 */ 1297 int soc_clk_dump(void) 1298 { 1299 struct udevice *cru_dev; 1300 struct rk3328_clk_priv *priv; 1301 const struct rk3328_clk_info *clk_dump; 1302 struct clk clk; 1303 unsigned long clk_count = ARRAY_SIZE(clks_dump); 1304 unsigned long rate; 1305 int i, ret; 1306 1307 ret = uclass_get_device_by_driver(UCLASS_CLK, 1308 DM_GET_DRIVER(rockchip_rk3328_cru), 1309 &cru_dev); 1310 if (ret) { 1311 printf("%s failed to get cru device\n", __func__); 1312 return ret; 1313 } 1314 1315 priv = dev_get_priv(cru_dev); 1316 printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n", 1317 priv->sync_kernel ? "sync kernel" : "uboot", 1318 priv->armclk_enter_hz / 1000, 1319 priv->armclk_init_hz / 1000, 1320 priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0, 1321 priv->set_armclk_rate ? " KHz" : "N/A"); 1322 for (i = 0; i < clk_count; i++) { 1323 clk_dump = &clks_dump[i]; 1324 if (clk_dump->name) { 1325 clk.id = clk_dump->id; 1326 if (clk_dump->is_cru) 1327 ret = clk_request(cru_dev, &clk); 1328 if (ret < 0) 1329 return ret; 1330 1331 rate = clk_get_rate(&clk); 1332 clk_free(&clk); 1333 if (i == 0) { 1334 if (rate < 0) 1335 printf(" %s %s\n", clk_dump->name, 1336 "unknown"); 1337 else 1338 printf(" %s %lu KHz\n", clk_dump->name, 1339 rate / 1000); 1340 } else { 1341 if (rate < 0) 1342 printf(" %s %s\n", clk_dump->name, 1343 "unknown"); 1344 else 1345 printf(" %s %lu KHz\n", clk_dump->name, 1346 rate / 1000); 1347 } 1348 } 1349 } 1350 1351 return 0; 1352 } 1353 #endif 1354