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 con_id = 32; 296 break; 297 default: 298 return -EINVAL; 299 } 300 con = readl(&cru->clksel_con[con_id]); 301 div = (con & CLK_EMMC_DIV_CON_MASK) >> CLK_EMMC_DIV_CON_SHIFT; 302 303 if ((con & CLK_EMMC_PLL_MASK) >> CLK_EMMC_PLL_SHIFT 304 == CLK_EMMC_PLL_SEL_24M) 305 return DIV_TO_RATE(OSC_HZ, div) / 2; 306 else 307 return DIV_TO_RATE(priv->gpll_hz, div) / 2; 308 } 309 310 static ulong rk3328_mmc_set_clk(struct rk3328_clk_priv *priv, 311 ulong clk_id, ulong set_rate) 312 { 313 struct rk3328_cru *cru = priv->cru; 314 int src_clk_div; 315 u32 con_id; 316 317 switch (clk_id) { 318 case HCLK_SDMMC: 319 case SCLK_SDMMC: 320 con_id = 30; 321 break; 322 case HCLK_EMMC: 323 case SCLK_EMMC: 324 con_id = 32; 325 break; 326 default: 327 return -EINVAL; 328 } 329 /* Select clk_sdmmc/emmc source from GPLL by default */ 330 /* mmc clock defaulg div 2 internal, need provide double in cru */ 331 src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, set_rate); 332 333 if (src_clk_div > 127) { 334 /* use 24MHz source for 400KHz clock */ 335 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate); 336 rk_clrsetreg(&cru->clksel_con[con_id], 337 CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK, 338 CLK_EMMC_PLL_SEL_24M << CLK_EMMC_PLL_SHIFT | 339 (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT); 340 } else { 341 rk_clrsetreg(&cru->clksel_con[con_id], 342 CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK, 343 CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT | 344 (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT); 345 } 346 347 return rk3328_mmc_get_clk(priv, clk_id); 348 } 349 350 #ifndef CONFIG_SPL_BUILD 351 static ulong rk3328_pwm_get_clk(struct rk3328_clk_priv *priv) 352 { 353 struct rk3328_cru *cru = priv->cru; 354 u32 div, con; 355 356 con = readl(&cru->clksel_con[24]); 357 div = (con & CLK_PWM_DIV_CON_MASK) >> CLK_PWM_DIV_CON_SHIFT; 358 359 return DIV_TO_RATE(priv->gpll_hz, div); 360 } 361 362 static ulong rk3328_pwm_set_clk(struct rk3328_clk_priv *priv, uint hz) 363 { 364 struct rk3328_cru *cru = priv->cru; 365 u32 div = priv->gpll_hz / hz; 366 367 rk_clrsetreg(&cru->clksel_con[24], 368 CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK, 369 CLK_PWM_PLL_SEL_GPLL << CLK_PWM_PLL_SEL_SHIFT | 370 (div - 1) << CLK_PWM_DIV_CON_SHIFT); 371 372 return DIV_TO_RATE(priv->gpll_hz, div); 373 } 374 375 static ulong rk3328_saradc_get_clk(struct rk3328_clk_priv *priv) 376 { 377 struct rk3328_cru *cru = priv->cru; 378 u32 div, val; 379 380 val = readl(&cru->clksel_con[23]); 381 div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT, 382 CLK_SARADC_DIV_CON_WIDTH); 383 384 return DIV_TO_RATE(OSC_HZ, div); 385 } 386 387 static ulong rk3328_saradc_set_clk(struct rk3328_clk_priv *priv, uint hz) 388 { 389 struct rk3328_cru *cru = priv->cru; 390 int src_clk_div; 391 392 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1; 393 assert(src_clk_div < 128); 394 395 rk_clrsetreg(&cru->clksel_con[23], 396 CLK_SARADC_DIV_CON_MASK, 397 src_clk_div << CLK_SARADC_DIV_CON_SHIFT); 398 399 return rk3328_saradc_get_clk(priv); 400 } 401 402 static ulong rk3328_tsadc_get_clk(struct rk3328_clk_priv *priv) 403 { 404 struct rk3328_cru *cru = priv->cru; 405 u32 div, val; 406 407 val = readl(&cru->clksel_con[22]); 408 div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT, 409 CLK_SARADC_DIV_CON_WIDTH); 410 411 return DIV_TO_RATE(OSC_HZ, div); 412 } 413 414 static ulong rk3328_tsadc_set_clk(struct rk3328_clk_priv *priv, uint hz) 415 { 416 struct rk3328_cru *cru = priv->cru; 417 int src_clk_div; 418 419 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1; 420 assert(src_clk_div < 128); 421 422 rk_clrsetreg(&cru->clksel_con[22], 423 CLK_SARADC_DIV_CON_MASK, 424 src_clk_div << CLK_SARADC_DIV_CON_SHIFT); 425 426 return rk3328_tsadc_get_clk(priv); 427 } 428 429 static ulong rk3328_vop_get_clk(struct rk3328_clk_priv *priv, ulong clk_id) 430 { 431 struct rk3328_cru *cru = priv->cru; 432 u32 div, con, parent; 433 434 switch (clk_id) { 435 case ACLK_VOP_PRE: 436 case ACLK_VOP: 437 con = readl(&cru->clksel_con[39]); 438 div = (con & ACLK_VOP_DIV_CON_MASK) >> ACLK_VOP_DIV_CON_SHIFT; 439 parent = priv->cpll_hz; 440 break; 441 case ACLK_VIO_PRE: 442 case ACLK_VIO: 443 con = readl(&cru->clksel_con[37]); 444 div = (con & ACLK_VIO_DIV_CON_MASK) >> ACLK_VIO_DIV_CON_SHIFT; 445 parent = priv->cpll_hz; 446 break; 447 case HCLK_VIO_PRE: 448 case HCLK_VIO: 449 parent = rk3328_vop_get_clk(priv, ACLK_VIO_PRE); 450 con = readl(&cru->clksel_con[37]); 451 div = (con & HCLK_VIO_DIV_CON_MASK) >> HCLK_VIO_DIV_CON_SHIFT; 452 break; 453 default: 454 return -ENOENT; 455 } 456 457 return DIV_TO_RATE(parent, div); 458 } 459 460 static ulong rk3328_vop_set_clk(struct rk3328_clk_priv *priv, 461 ulong clk_id, uint hz) 462 { 463 struct rk3328_cru *cru = priv->cru; 464 int src_clk_div; 465 u32 con, parent; 466 467 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz); 468 assert(src_clk_div - 1 < 31); 469 470 switch (clk_id) { 471 case ACLK_VOP_PRE: 472 case ACLK_VOP: 473 rk_clrsetreg(&cru->clksel_con[39], 474 ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK, 475 ACLK_VOP_PLL_SEL_CPLL << ACLK_VOP_PLL_SEL_SHIFT | 476 (src_clk_div - 1) << ACLK_VOP_DIV_CON_SHIFT); 477 break; 478 case ACLK_VIO_PRE: 479 case ACLK_VIO: 480 rk_clrsetreg(&cru->clksel_con[37], 481 ACLK_VIO_PLL_SEL_MASK | ACLK_VIO_DIV_CON_MASK, 482 ACLK_VIO_PLL_SEL_CPLL << ACLK_VIO_PLL_SEL_SHIFT | 483 (src_clk_div - 1) << ACLK_VIO_DIV_CON_SHIFT); 484 break; 485 case HCLK_VIO_PRE: 486 case HCLK_VIO: 487 src_clk_div = DIV_ROUND_UP(rk3328_vop_get_clk(priv, 488 ACLK_VIO_PRE), 489 hz); 490 rk_clrsetreg(&cru->clksel_con[37], 491 HCLK_VIO_DIV_CON_MASK, 492 (src_clk_div - 1) << HCLK_VIO_DIV_CON_SHIFT); 493 break; 494 case DCLK_LCDC: 495 con = readl(&cru->clksel_con[40]); 496 con = (con & DCLK_LCDC_SEL_MASK) >> DCLK_LCDC_SEL_SHIFT; 497 if (con) { 498 parent = readl(&cru->clksel_con[40]); 499 parent = (parent & DCLK_LCDC_PLL_SEL_MASK) >> 500 DCLK_LCDC_PLL_SEL_SHIFT; 501 if (parent) 502 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz); 503 else 504 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 505 506 rk_clrsetreg(&cru->clksel_con[40], 507 DCLK_LCDC_DIV_CON_MASK, 508 (src_clk_div - 1) << 509 DCLK_LCDC_DIV_CON_SHIFT); 510 } 511 break; 512 default: 513 printf("do not support this vop freq\n"); 514 return -EINVAL; 515 } 516 517 return rk3328_vop_get_clk(priv, clk_id); 518 } 519 #endif 520 521 static ulong rk3328_bus_get_clk(struct rk3328_clk_priv *priv, ulong clk_id) 522 { 523 struct rk3328_cru *cru = priv->cru; 524 u32 div, con, parent; 525 526 switch (clk_id) { 527 case ACLK_BUS_PRE: 528 con = readl(&cru->clksel_con[0]); 529 div = (con & ACLK_BUS_DIV_CON_MASK) >> ACLK_BUS_DIV_CON_SHIFT; 530 parent = priv->cpll_hz; 531 break; 532 case HCLK_BUS_PRE: 533 con = readl(&cru->clksel_con[1]); 534 div = (con & HCLK_BUS_DIV_CON_MASK) >> HCLK_BUS_DIV_CON_SHIFT; 535 parent = rk3328_bus_get_clk(priv, ACLK_BUS_PRE); 536 break; 537 case PCLK_BUS_PRE: 538 con = readl(&cru->clksel_con[1]); 539 div = (con & PCLK_BUS_DIV_CON_MASK) >> PCLK_BUS_DIV_CON_SHIFT; 540 parent = rk3328_bus_get_clk(priv, ACLK_BUS_PRE); 541 break; 542 default: 543 return -ENOENT; 544 } 545 546 return DIV_TO_RATE(parent, div); 547 } 548 549 static ulong rk3328_bus_set_clk(struct rk3328_clk_priv *priv, 550 ulong clk_id, ulong hz) 551 { 552 struct rk3328_cru *cru = priv->cru; 553 int src_clk_div; 554 555 /* 556 * select gpll as pd_bus bus clock source and 557 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 558 */ 559 switch (clk_id) { 560 case ACLK_BUS_PRE: 561 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz); 562 assert(src_clk_div - 1 < 31); 563 rk_clrsetreg(&cru->clksel_con[0], 564 CLK_BUS_PLL_SEL_MASK | ACLK_BUS_DIV_CON_MASK, 565 CLK_BUS_PLL_SEL_CPLL << CLK_BUS_PLL_SEL_SHIFT | 566 (src_clk_div - 1) << ACLK_BUS_DIV_CON_SHIFT); 567 break; 568 case HCLK_BUS_PRE: 569 src_clk_div = DIV_ROUND_UP(rk3328_bus_get_clk(priv, 570 ACLK_BUS_PRE), 571 hz); 572 assert(src_clk_div - 1 < 3); 573 rk_clrsetreg(&cru->clksel_con[1], 574 HCLK_BUS_DIV_CON_MASK, 575 (src_clk_div - 1) << HCLK_BUS_DIV_CON_SHIFT); 576 break; 577 case PCLK_BUS_PRE: 578 src_clk_div = DIV_ROUND_UP(rk3328_bus_get_clk(priv, 579 ACLK_BUS_PRE), 580 hz); 581 assert(src_clk_div - 1 < 7); 582 rk_clrsetreg(&cru->clksel_con[1], 583 PCLK_BUS_DIV_CON_MASK, 584 (src_clk_div - 1) << PCLK_BUS_DIV_CON_SHIFT); 585 break; 586 default: 587 printf("do not support this bus freq\n"); 588 return -EINVAL; 589 } 590 return rk3328_bus_get_clk(priv, clk_id); 591 } 592 593 static ulong rk3328_peri_get_clk(struct rk3328_clk_priv *priv, ulong clk_id) 594 { 595 struct rk3328_cru *cru = priv->cru; 596 u32 div, con, parent; 597 598 switch (clk_id) { 599 case ACLK_PERI_PRE: 600 con = readl(&cru->clksel_con[28]); 601 div = (con & ACLK_PERI_DIV_CON_MASK) >> ACLK_PERI_DIV_CON_SHIFT; 602 parent = priv->cpll_hz; 603 break; 604 case HCLK_PERI: 605 con = readl(&cru->clksel_con[29]); 606 div = (con & HCLK_PERI_DIV_CON_MASK) >> HCLK_PERI_DIV_CON_SHIFT; 607 parent = rk3328_peri_get_clk(priv, ACLK_PERI_PRE); 608 break; 609 case PCLK_PERI: 610 con = readl(&cru->clksel_con[29]); 611 div = (con & PCLK_PERI_DIV_CON_MASK) >> PCLK_PERI_DIV_CON_SHIFT; 612 parent = rk3328_peri_get_clk(priv, ACLK_PERI_PRE); 613 break; 614 default: 615 return -ENOENT; 616 } 617 618 return DIV_TO_RATE(parent, div); 619 } 620 621 static ulong rk3328_peri_set_clk(struct rk3328_clk_priv *priv, 622 ulong clk_id, ulong hz) 623 { 624 struct rk3328_cru *cru = priv->cru; 625 int src_clk_div; 626 627 /* 628 * select gpll as pd_bus bus clock source and 629 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 630 */ 631 switch (clk_id) { 632 case ACLK_PERI_PRE: 633 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz); 634 assert(src_clk_div - 1 < 31); 635 rk_clrsetreg(&cru->clksel_con[28], 636 CLK_PERI_PLL_SEL_MASK | ACLK_PERI_DIV_CON_MASK, 637 CLK_PERI_PLL_SEL_CPLL << CLK_PERI_PLL_SEL_SHIFT | 638 (src_clk_div - 1) << ACLK_PERI_DIV_CON_SHIFT); 639 break; 640 case HCLK_PERI: 641 src_clk_div = DIV_ROUND_UP(rk3328_peri_get_clk(priv, 642 ACLK_PERI_PRE), 643 hz); 644 assert(src_clk_div - 1 < 3); 645 rk_clrsetreg(&cru->clksel_con[29], 646 HCLK_PERI_DIV_CON_MASK, 647 (src_clk_div - 1) << HCLK_PERI_DIV_CON_SHIFT); 648 break; 649 case PCLK_PERI: 650 src_clk_div = DIV_ROUND_UP(rk3328_peri_get_clk(priv, 651 ACLK_PERI_PRE), 652 hz); 653 assert(src_clk_div - 1 < 7); 654 rk_clrsetreg(&cru->clksel_con[29], 655 PCLK_PERI_DIV_CON_MASK, 656 (src_clk_div - 1) << PCLK_PERI_DIV_CON_SHIFT); 657 break; 658 default: 659 printf("do not support this bus freq\n"); 660 return -EINVAL; 661 } 662 663 return rk3328_peri_get_clk(priv, clk_id); 664 } 665 666 #ifndef CONFIG_SPL_BUILD 667 static ulong rk3328_crypto_get_clk(struct rk3328_clk_priv *priv, ulong clk_id) 668 { 669 struct rk3328_cru *cru = priv->cru; 670 u32 div, con, parent; 671 672 switch (clk_id) { 673 case SCLK_CRYPTO: 674 con = readl(&cru->clksel_con[20]); 675 div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT; 676 parent = priv->gpll_hz; 677 break; 678 default: 679 return -ENOENT; 680 } 681 682 return DIV_TO_RATE(parent, div); 683 } 684 685 static ulong rk3328_crypto_set_clk(struct rk3328_clk_priv *priv, ulong clk_id, 686 ulong hz) 687 { 688 struct rk3328_cru *cru = priv->cru; 689 int src_clk_div; 690 691 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 692 assert(src_clk_div - 1 <= 127); 693 694 /* 695 * select gpll as crypto clock source and 696 * set up dependent divisors for crypto clocks. 697 */ 698 switch (clk_id) { 699 case SCLK_CRYPTO: 700 rk_clrsetreg(&cru->clksel_con[20], 701 CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK, 702 CRYPTO_PLL_SEL_GPLL << CRYPTO_PLL_SEL_SHIFT | 703 (src_clk_div - 1) << CRYPTO_DIV_SHIFT); 704 break; 705 default: 706 printf("do not support this peri freq\n"); 707 return -EINVAL; 708 } 709 710 return rk3328_crypto_get_clk(priv, clk_id); 711 } 712 #endif 713 714 static ulong rk3328_clk_get_rate(struct clk *clk) 715 { 716 struct rk3328_clk_priv *priv = dev_get_priv(clk->dev); 717 ulong rate = 0; 718 719 #ifndef CONFIG_SPL_BUILD 720 if (!priv->gpll_hz) { 721 priv->gpll_hz = rockchip_pll_get_rate(&rk3328_pll_clks[GPLL], 722 priv->cru, GPLL); 723 debug("%s gpll=%lu\n", __func__, priv->gpll_hz); 724 } 725 if (!priv->cpll_hz) { 726 priv->cpll_hz = rockchip_pll_get_rate(&rk3328_pll_clks[CPLL], 727 priv->cru, CPLL); 728 debug("%s cpll=%lu\n", __func__, priv->cpll_hz); 729 } 730 #endif 731 732 switch (clk->id) { 733 case PLL_APLL: 734 case PLL_DPLL: 735 case PLL_CPLL: 736 case PLL_GPLL: 737 case PLL_NPLL: 738 rate = rockchip_pll_get_rate(&rk3328_pll_clks[clk->id - 1], 739 priv->cru, clk->id - 1); 740 break; 741 case ARMCLK: 742 rate = rockchip_pll_get_rate(&rk3328_pll_clks[NPLL], 743 priv->cru, NPLL); 744 break; 745 case ACLK_BUS_PRE: 746 case HCLK_BUS_PRE: 747 case PCLK_BUS_PRE: 748 rate = rk3328_bus_get_clk(priv, clk->id); 749 break; 750 case ACLK_PERI_PRE: 751 case HCLK_PERI: 752 case PCLK_PERI: 753 rate = rk3328_peri_get_clk(priv, clk->id); 754 break; 755 case HCLK_SDMMC: 756 case HCLK_EMMC: 757 case SCLK_SDMMC: 758 case SCLK_EMMC: 759 rate = rk3328_mmc_get_clk(priv, clk->id); 760 break; 761 #ifndef CONFIG_SPL_BUILD 762 case SCLK_I2C0: 763 case SCLK_I2C1: 764 case SCLK_I2C2: 765 case SCLK_I2C3: 766 rate = rk3328_i2c_get_clk(priv, clk->id); 767 break; 768 case SCLK_PWM: 769 rate = rk3328_pwm_get_clk(priv); 770 break; 771 case SCLK_SARADC: 772 rate = rk3328_saradc_get_clk(priv); 773 break; 774 case SCLK_TSADC: 775 rate = rk3328_tsadc_get_clk(priv); 776 break; 777 case ACLK_VOP_PRE: 778 case ACLK_VIO_PRE: 779 case HCLK_VIO_PRE: 780 case ACLK_VOP: 781 case ACLK_VIO: 782 case HCLK_VIO: 783 rate = rk3328_vop_get_clk(priv, clk->id); 784 break; 785 case SCLK_CRYPTO: 786 rate = rk3328_crypto_get_clk(priv, clk->id); 787 break; 788 #endif 789 default: 790 return -ENOENT; 791 } 792 793 return rate; 794 } 795 796 static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate) 797 { 798 struct rk3328_clk_priv *priv = dev_get_priv(clk->dev); 799 ulong ret = 0; 800 801 switch (clk->id) { 802 case PLL_APLL: 803 case PLL_DPLL: 804 case PLL_NPLL: 805 ret = rockchip_pll_set_rate(&rk3328_pll_clks[clk->id - 1], 806 priv->cru, clk->id - 1, rate); 807 break; 808 case PLL_CPLL: 809 ret = rockchip_pll_set_rate(&rk3328_pll_clks[CPLL], 810 priv->cru, CPLL, rate); 811 priv->cpll_hz = rate; 812 break; 813 case PLL_GPLL: 814 ret = rockchip_pll_set_rate(&rk3328_pll_clks[GPLL], 815 priv->cru, GPLL, rate); 816 priv->gpll_hz = rate; 817 break; 818 case ARMCLK: 819 ret = rk3328_armclk_set_clk(priv, rate); 820 break; 821 case ACLK_BUS_PRE: 822 case HCLK_BUS_PRE: 823 case PCLK_BUS_PRE: 824 rate = rk3328_bus_set_clk(priv, clk->id, rate); 825 break; 826 case ACLK_PERI_PRE: 827 case HCLK_PERI: 828 case PCLK_PERI: 829 rate = rk3328_peri_set_clk(priv, clk->id, rate); 830 break; 831 case HCLK_SDMMC: 832 case HCLK_EMMC: 833 case SCLK_SDMMC: 834 case SCLK_EMMC: 835 ret = rk3328_mmc_set_clk(priv, clk->id, rate); 836 break; 837 #ifndef CONFIG_SPL_BUILD 838 case SCLK_I2C0: 839 case SCLK_I2C1: 840 case SCLK_I2C2: 841 case SCLK_I2C3: 842 ret = rk3328_i2c_set_clk(priv, clk->id, rate); 843 break; 844 case SCLK_MAC2IO: 845 ret = rk3328_gmac2io_set_clk(priv, rate); 846 break; 847 case SCLK_PWM: 848 ret = rk3328_pwm_set_clk(priv, rate); 849 break; 850 case SCLK_SARADC: 851 ret = rk3328_saradc_set_clk(priv, rate); 852 break; 853 case SCLK_TSADC: 854 ret = rk3328_tsadc_set_clk(priv, rate); 855 break; 856 case DCLK_LCDC: 857 case ACLK_VOP_PRE: 858 case ACLK_VIO_PRE: 859 case HCLK_VIO_PRE: 860 case ACLK_VOP: 861 case ACLK_VIO: 862 case HCLK_VIO: 863 rate = rk3328_vop_set_clk(priv, clk->id, rate); 864 break; 865 case SCLK_CRYPTO: 866 rate = rk3328_crypto_set_clk(priv, clk->id, rate); 867 break; 868 #endif 869 case SCLK_PDM: 870 case SCLK_RTC32K: 871 case SCLK_UART0: 872 case SCLK_UART1: 873 case SCLK_UART2: 874 case SCLK_SDIO: 875 case SCLK_TSP: 876 case SCLK_WIFI: 877 case ACLK_RGA_PRE: 878 case SCLK_RGA: 879 case ACLK_RKVDEC_PRE: 880 case ACLK_RKVENC: 881 case ACLK_VPU_PRE: 882 case SCLK_VDEC_CABAC: 883 case SCLK_VDEC_CORE: 884 case SCLK_VENC_CORE: 885 case SCLK_VENC_DSP: 886 case SCLK_EFUSE: 887 case PCLK_DDR: 888 case ACLK_GMAC: 889 case PCLK_GMAC: 890 case SCLK_USB3OTG_SUSPEND: 891 return 0; 892 default: 893 return -ENOENT; 894 } 895 896 return ret; 897 } 898 899 #ifndef CONFIG_SPL_BUILD 900 static int rk3328_gmac2io_set_parent(struct clk *clk, struct clk *parent) 901 { 902 struct rk3328_grf_regs *grf; 903 const char *clock_output_name; 904 int ret; 905 906 grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 907 908 /* 909 * If the requested parent is in the same clock-controller and the id 910 * is SCLK_MAC2IO_SRC ("clk_mac2io_src"), switch to the internal clock. 911 */ 912 if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2IO_SRC)) { 913 debug("%s: switching RGMII to SCLK_MAC2IO_SRC\n", __func__); 914 rk_clrreg(&grf->mac_con[1], BIT(10)); 915 return 0; 916 } 917 918 /* 919 * Otherwise, we need to check the clock-output-names of the 920 * requested parent to see if the requested id is "gmac_clkin". 921 */ 922 ret = dev_read_string_index(parent->dev, "clock-output-names", 923 parent->id, &clock_output_name); 924 if (ret < 0) 925 return -ENODATA; 926 927 /* If this is "gmac_clkin", switch to the external clock input */ 928 if (!strcmp(clock_output_name, "gmac_clkin")) { 929 debug("%s: switching RGMII to CLKIN\n", __func__); 930 rk_setreg(&grf->mac_con[1], BIT(10)); 931 return 0; 932 } 933 934 return -EINVAL; 935 } 936 937 static int rk3328_gmac2io_ext_set_parent(struct clk *clk, struct clk *parent) 938 { 939 struct rk3328_grf_regs *grf; 940 const char *clock_output_name; 941 int ret; 942 943 grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 944 945 /* 946 * If the requested parent is in the same clock-controller and the id 947 * is SCLK_MAC2IO ("clk_mac2io"), switch to the internal clock. 948 */ 949 if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2IO)) { 950 debug("%s: switching RGMII to SCLK_MAC2IO\n", __func__); 951 rk_clrreg(&grf->soc_con[4], BIT(14)); 952 return 0; 953 } 954 955 /* 956 * Otherwise, we need to check the clock-output-names of the 957 * requested parent to see if the requested id is "gmac_clkin". 958 */ 959 ret = dev_read_string_index(parent->dev, "clock-output-names", 960 parent->id, &clock_output_name); 961 if (ret < 0) 962 return -ENODATA; 963 964 /* If this is "gmac_clkin", switch to the external clock input */ 965 if (!strcmp(clock_output_name, "gmac_clkin")) { 966 debug("%s: switching RGMII to CLKIN\n", __func__); 967 rk_setreg(&grf->soc_con[4], BIT(14)); 968 return 0; 969 } 970 971 return -EINVAL; 972 } 973 974 static int rk3328_lcdc_set_parent(struct clk *clk, struct clk *parent) 975 { 976 struct rk3328_clk_priv *priv = dev_get_priv(clk->dev); 977 978 if (parent->id == HDMIPHY) 979 rk_clrsetreg(&priv->cru->clksel_con[40], 980 DCLK_LCDC_SEL_MASK, 981 DCLK_LCDC_SEL_HDMIPHY << DCLK_LCDC_SEL_SHIFT); 982 else if (parent->id == PLL_CPLL) 983 rk_clrsetreg(&priv->cru->clksel_con[40], 984 DCLK_LCDC_SEL_MASK | DCLK_LCDC_PLL_SEL_MASK, 985 (DCLK_LCDC_SEL_PLL << DCLK_LCDC_SEL_SHIFT) | 986 (DCLK_LCDC_PLL_SEL_CPLL << 987 DCLK_LCDC_PLL_SEL_SHIFT)); 988 else 989 rk_clrsetreg(&priv->cru->clksel_con[40], 990 DCLK_LCDC_SEL_MASK | DCLK_LCDC_PLL_SEL_MASK, 991 (DCLK_LCDC_SEL_PLL << DCLK_LCDC_SEL_SHIFT) | 992 (DCLK_LCDC_PLL_SEL_GPLL << 993 DCLK_LCDC_PLL_SEL_SHIFT)); 994 995 return 0; 996 } 997 #endif 998 999 static int rk3328_clk_set_parent(struct clk *clk, struct clk *parent) 1000 { 1001 switch (clk->id) { 1002 #ifndef CONFIG_SPL_BUILD 1003 case SCLK_MAC2IO: 1004 return rk3328_gmac2io_set_parent(clk, parent); 1005 case SCLK_MAC2IO_EXT: 1006 return rk3328_gmac2io_ext_set_parent(clk, parent); 1007 case DCLK_LCDC: 1008 return rk3328_lcdc_set_parent(clk, parent); 1009 #endif 1010 case SCLK_PDM: 1011 case SCLK_RTC32K: 1012 case SCLK_UART0: 1013 case SCLK_UART1: 1014 case SCLK_UART2: 1015 return 0; 1016 } 1017 1018 debug("%s: unsupported clk %ld\n", __func__, clk->id); 1019 return -ENOENT; 1020 } 1021 1022 #define ROCKCHIP_MMC_DELAY_SEL BIT(10) 1023 #define ROCKCHIP_MMC_DEGREE_MASK 0x3 1024 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2 1025 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 1026 1027 #define PSECS_PER_SEC 1000000000000LL 1028 /* 1029 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 1030 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 1031 */ 1032 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 1033 1034 int rk3328_mmc_get_phase(struct clk *clk) 1035 { 1036 struct rk3328_clk_priv *priv = dev_get_priv(clk->dev); 1037 struct rk3328_cru *cru = priv->cru; 1038 u32 raw_value, delay_num; 1039 u16 degrees = 0; 1040 ulong rate; 1041 1042 rate = rk3328_clk_get_rate(clk); 1043 1044 if (rate < 0) 1045 return rate; 1046 1047 if (clk->id == SCLK_EMMC_SAMPLE) 1048 raw_value = readl(&cru->emmc_con[1]); 1049 else if (clk->id == SCLK_SDMMC_SAMPLE) 1050 raw_value = readl(&cru->sdmmc_con[1]); 1051 else 1052 raw_value = readl(&cru->sdio_con[1]); 1053 1054 raw_value >>= 1; 1055 degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; 1056 1057 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 1058 /* degrees/delaynum * 10000 */ 1059 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 1060 36 * (rate / 1000000); 1061 1062 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 1063 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 1064 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 1065 } 1066 1067 return degrees % 360; 1068 } 1069 1070 int rk3328_mmc_set_phase(struct clk *clk, u32 degrees) 1071 { 1072 struct rk3328_clk_priv *priv = dev_get_priv(clk->dev); 1073 struct rk3328_cru *cru = priv->cru; 1074 u8 nineties, remainder, delay_num; 1075 u32 raw_value, delay; 1076 ulong rate; 1077 1078 rate = rk3328_clk_get_rate(clk); 1079 1080 if (rate < 0) 1081 return rate; 1082 1083 nineties = degrees / 90; 1084 remainder = (degrees % 90); 1085 1086 /* 1087 * Convert to delay; do a little extra work to make sure we 1088 * don't overflow 32-bit / 64-bit numbers. 1089 */ 1090 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 1091 delay *= remainder; 1092 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 1093 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 1094 1095 delay_num = (u8)min_t(u32, delay, 255); 1096 1097 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 1098 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 1099 raw_value |= nineties; 1100 1101 raw_value <<= 1; 1102 if (clk->id == SCLK_EMMC_SAMPLE) 1103 writel(raw_value | 0xffff0000, &cru->emmc_con[1]); 1104 else if (clk->id == SCLK_SDMMC_SAMPLE) 1105 writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]); 1106 else 1107 writel(raw_value | 0xffff0000, &cru->sdio_con[1]); 1108 1109 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 1110 degrees, delay_num, raw_value, rk3328_mmc_get_phase(clk)); 1111 1112 return 0; 1113 } 1114 1115 static int rk3328_clk_get_phase(struct clk *clk) 1116 { 1117 int ret; 1118 1119 debug("%s %ld\n", __func__, clk->id); 1120 switch (clk->id) { 1121 case SCLK_EMMC_SAMPLE: 1122 case SCLK_SDMMC_SAMPLE: 1123 case SCLK_SDIO_SAMPLE: 1124 ret = rk3328_mmc_get_phase(clk); 1125 break; 1126 default: 1127 return -ENOENT; 1128 } 1129 1130 return ret; 1131 } 1132 1133 static int rk3328_clk_set_phase(struct clk *clk, int degrees) 1134 { 1135 int ret; 1136 1137 debug("%s %ld\n", __func__, clk->id); 1138 switch (clk->id) { 1139 case SCLK_EMMC_SAMPLE: 1140 case SCLK_SDMMC_SAMPLE: 1141 case SCLK_SDIO_SAMPLE: 1142 ret = rk3328_mmc_set_phase(clk, degrees); 1143 break; 1144 default: 1145 return -ENOENT; 1146 } 1147 1148 return ret; 1149 } 1150 1151 static struct clk_ops rk3328_clk_ops = { 1152 .get_rate = rk3328_clk_get_rate, 1153 .set_rate = rk3328_clk_set_rate, 1154 .set_parent = rk3328_clk_set_parent, 1155 .get_phase = rk3328_clk_get_phase, 1156 .set_phase = rk3328_clk_set_phase, 1157 }; 1158 1159 static void rkclk_init(struct rk3328_clk_priv *priv) 1160 { 1161 if (rockchip_pll_get_rate(&rk3328_pll_clks[NPLL], 1162 priv->cru, NPLL) != APLL_HZ) 1163 rk3328_armclk_set_clk(priv, APLL_HZ); 1164 1165 priv->gpll_hz = rockchip_pll_get_rate(&rk3328_pll_clks[GPLL], 1166 priv->cru, GPLL); 1167 priv->cpll_hz = rockchip_pll_get_rate(&rk3328_pll_clks[CPLL], 1168 priv->cru, CPLL); 1169 1170 /* before set pll set child div first */ 1171 rk_clrsetreg(&priv->cru->clksel_con[24], (0x3f << 8) | (0x3f << 0), 1172 (0x17 << 8) | (0x17 << 0)); 1173 rk_clrsetreg(&priv->cru->clksel_con[27], (0x1f << 8) | (0x1f << 0), 1174 (0x17 << 8) | (0x17 << 0)); 1175 rk_clrsetreg(&priv->cru->clksel_con[31], 0xff << 0, 0xb << 0); 1176 rk_clrsetreg(&priv->cru->clksel_con[43], 0xff << 0, 0xb << 0); 1177 rk_clrsetreg(&priv->cru->clksel_con[52], 0x1f << 8, 0x5 << 8); 1178 1179 rockchip_pll_set_rate(&rk3328_pll_clks[GPLL], 1180 priv->cru, GPLL, GPLL_HZ); 1181 priv->gpll_hz = GPLL_HZ; 1182 1183 rockchip_pll_set_rate(&rk3328_pll_clks[CPLL], 1184 priv->cru, CPLL, CPLL_HZ); 1185 priv->cpll_hz = CPLL_HZ; 1186 1187 rk3328_bus_set_clk(priv, ACLK_BUS_PRE, ACLK_BUS_HZ); 1188 rk3328_bus_set_clk(priv, HCLK_BUS_PRE, ACLK_BUS_HZ / 2); 1189 rk3328_bus_set_clk(priv, PCLK_BUS_PRE, ACLK_BUS_HZ / 2); 1190 rk3328_peri_set_clk(priv, ACLK_PERI_PRE, ACLK_PERI_HZ); 1191 rk3328_peri_set_clk(priv, HCLK_PERI, ACLK_PERI_HZ / 2); 1192 rk3328_peri_set_clk(priv, PCLK_PERI, ACLK_PERI_HZ / 2); 1193 /*rk3328_mmc_set_clk(priv, SCLK_EMMC, rate);*/ 1194 1195 /* set usbphy and hdmiphy from phy */ 1196 rk_clrsetreg(&priv->cru->misc, (0x1 << 13) | 1197 (0x1 << 15), (0 << 15) | (0 << 13)); 1198 } 1199 1200 static int rk3328_clk_probe(struct udevice *dev) 1201 { 1202 struct rk3328_clk_priv *priv = dev_get_priv(dev); 1203 int ret = 0; 1204 1205 rkclk_init(priv); 1206 1207 ret = clk_set_defaults(dev); 1208 if (ret) 1209 debug("%s clk_set_defaults failed %d\n", __func__, ret); 1210 1211 return 0; 1212 } 1213 1214 static int rk3328_clk_ofdata_to_platdata(struct udevice *dev) 1215 { 1216 struct rk3328_clk_priv *priv = dev_get_priv(dev); 1217 1218 priv->cru = dev_read_addr_ptr(dev); 1219 1220 return 0; 1221 } 1222 1223 static int rk3328_clk_bind(struct udevice *dev) 1224 { 1225 int ret; 1226 struct udevice *sys_child, *sf_child; 1227 struct sysreset_reg *priv; 1228 struct softreset_reg *sf_priv; 1229 1230 /* The reset driver does not have a device node, so bind it here */ 1231 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 1232 &sys_child); 1233 if (ret) { 1234 debug("Warning: No sysreset driver: ret=%d\n", ret); 1235 } else { 1236 priv = malloc(sizeof(struct sysreset_reg)); 1237 priv->glb_srst_fst_value = offsetof(struct rk3328_cru, 1238 glb_srst_fst_value); 1239 priv->glb_srst_snd_value = offsetof(struct rk3328_cru, 1240 glb_srst_snd_value); 1241 sys_child->priv = priv; 1242 } 1243 1244 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 1245 dev_ofnode(dev), &sf_child); 1246 if (ret) { 1247 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 1248 } else { 1249 sf_priv = malloc(sizeof(struct softreset_reg)); 1250 sf_priv->sf_reset_offset = offsetof(struct rk3328_cru, 1251 softrst_con[0]); 1252 sf_priv->sf_reset_num = 12; 1253 sf_child->priv = sf_priv; 1254 } 1255 1256 return 0; 1257 } 1258 1259 static const struct udevice_id rk3328_clk_ids[] = { 1260 { .compatible = "rockchip,rk3328-cru" }, 1261 { } 1262 }; 1263 1264 U_BOOT_DRIVER(rockchip_rk3328_cru) = { 1265 .name = "rockchip_rk3328_cru", 1266 .id = UCLASS_CLK, 1267 .of_match = rk3328_clk_ids, 1268 .priv_auto_alloc_size = sizeof(struct rk3328_clk_priv), 1269 .ofdata_to_platdata = rk3328_clk_ofdata_to_platdata, 1270 .ops = &rk3328_clk_ops, 1271 .bind = rk3328_clk_bind, 1272 .probe = rk3328_clk_probe, 1273 }; 1274 1275 #ifndef CONFIG_SPL_BUILD 1276 /** 1277 * soc_clk_dump() - Print clock frequencies 1278 * Returns zero on success 1279 * 1280 * Implementation for the clk dump command. 1281 */ 1282 int soc_clk_dump(void) 1283 { 1284 struct udevice *cru_dev; 1285 const struct rk3328_clk_info *clk_dump; 1286 struct clk clk; 1287 unsigned long clk_count = ARRAY_SIZE(clks_dump); 1288 unsigned long rate; 1289 int i, ret; 1290 1291 ret = uclass_get_device_by_driver(UCLASS_CLK, 1292 DM_GET_DRIVER(rockchip_rk3328_cru), 1293 &cru_dev); 1294 if (ret) { 1295 printf("%s failed to get cru device\n", __func__); 1296 return ret; 1297 } 1298 1299 printf("CLK:"); 1300 for (i = 0; i < clk_count; i++) { 1301 clk_dump = &clks_dump[i]; 1302 if (clk_dump->name) { 1303 clk.id = clk_dump->id; 1304 if (clk_dump->is_cru) 1305 ret = clk_request(cru_dev, &clk); 1306 if (ret < 0) 1307 return ret; 1308 1309 rate = clk_get_rate(&clk); 1310 clk_free(&clk); 1311 if (i == 0) { 1312 if (rate < 0) 1313 printf("%10s%20s\n", clk_dump->name, 1314 "unknown"); 1315 else 1316 printf("%10s%20lu Hz\n", clk_dump->name, 1317 rate); 1318 } else { 1319 if (rate < 0) 1320 printf("%14s%20s\n", clk_dump->name, 1321 "unknown"); 1322 else 1323 printf("%14s%20lu Hz\n", clk_dump->name, 1324 rate); 1325 } 1326 } 1327 } 1328 1329 return 0; 1330 } 1331 #endif 1332