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_vop_get_clk(struct rk3328_clk_priv *priv, ulong clk_id) 403 { 404 struct rk3328_cru *cru = priv->cru; 405 u32 div, con, parent; 406 407 switch (clk_id) { 408 case ACLK_VOP_PRE: 409 case ACLK_VOP: 410 con = readl(&cru->clksel_con[39]); 411 div = (con & ACLK_VOP_DIV_CON_MASK) >> ACLK_VOP_DIV_CON_SHIFT; 412 parent = priv->cpll_hz; 413 break; 414 case ACLK_VIO_PRE: 415 case ACLK_VIO: 416 con = readl(&cru->clksel_con[37]); 417 div = (con & ACLK_VIO_DIV_CON_MASK) >> ACLK_VIO_DIV_CON_SHIFT; 418 parent = priv->cpll_hz; 419 break; 420 case HCLK_VIO_PRE: 421 case HCLK_VIO: 422 parent = rk3328_vop_get_clk(priv, ACLK_VIO_PRE); 423 con = readl(&cru->clksel_con[37]); 424 div = (con & HCLK_VIO_DIV_CON_MASK) >> HCLK_VIO_DIV_CON_SHIFT; 425 break; 426 default: 427 return -ENOENT; 428 } 429 430 return DIV_TO_RATE(parent, div); 431 } 432 433 static ulong rk3328_vop_set_clk(struct rk3328_clk_priv *priv, 434 ulong clk_id, uint hz) 435 { 436 struct rk3328_cru *cru = priv->cru; 437 int src_clk_div; 438 u32 con, parent; 439 440 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz); 441 assert(src_clk_div - 1 < 31); 442 443 switch (clk_id) { 444 case ACLK_VOP_PRE: 445 case ACLK_VOP: 446 rk_clrsetreg(&cru->clksel_con[39], 447 ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK, 448 ACLK_VOP_PLL_SEL_CPLL << ACLK_VOP_PLL_SEL_SHIFT | 449 (src_clk_div - 1) << ACLK_VOP_DIV_CON_SHIFT); 450 break; 451 case ACLK_VIO_PRE: 452 case ACLK_VIO: 453 rk_clrsetreg(&cru->clksel_con[37], 454 ACLK_VIO_PLL_SEL_MASK | ACLK_VIO_DIV_CON_MASK, 455 ACLK_VIO_PLL_SEL_CPLL << ACLK_VIO_PLL_SEL_SHIFT | 456 (src_clk_div - 1) << ACLK_VIO_DIV_CON_SHIFT); 457 break; 458 case HCLK_VIO_PRE: 459 case HCLK_VIO: 460 src_clk_div = DIV_ROUND_UP(rk3328_vop_get_clk(priv, 461 ACLK_VIO_PRE), 462 hz); 463 rk_clrsetreg(&cru->clksel_con[37], 464 HCLK_VIO_DIV_CON_MASK, 465 (src_clk_div - 1) << HCLK_VIO_DIV_CON_SHIFT); 466 break; 467 case DCLK_LCDC: 468 con = readl(&cru->clksel_con[40]); 469 con = (con & DCLK_LCDC_SEL_MASK) >> DCLK_LCDC_SEL_SHIFT; 470 if (con) { 471 parent = readl(&cru->clksel_con[40]); 472 parent = (parent & DCLK_LCDC_PLL_SEL_MASK) >> 473 DCLK_LCDC_PLL_SEL_SHIFT; 474 if (parent) 475 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz); 476 else 477 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 478 479 rk_clrsetreg(&cru->clksel_con[40], 480 DCLK_LCDC_DIV_CON_MASK, 481 (src_clk_div - 1) << 482 DCLK_LCDC_DIV_CON_SHIFT); 483 } 484 break; 485 default: 486 printf("do not support this vop freq\n"); 487 return -EINVAL; 488 } 489 490 return rk3328_vop_get_clk(priv, clk_id); 491 } 492 #endif 493 494 static ulong rk3328_bus_get_clk(struct rk3328_clk_priv *priv, ulong clk_id) 495 { 496 struct rk3328_cru *cru = priv->cru; 497 u32 div, con, parent; 498 499 switch (clk_id) { 500 case ACLK_BUS_PRE: 501 con = readl(&cru->clksel_con[0]); 502 div = (con & ACLK_BUS_DIV_CON_MASK) >> ACLK_BUS_DIV_CON_SHIFT; 503 parent = priv->cpll_hz; 504 break; 505 case HCLK_BUS_PRE: 506 con = readl(&cru->clksel_con[1]); 507 div = (con & HCLK_BUS_DIV_CON_MASK) >> HCLK_BUS_DIV_CON_SHIFT; 508 parent = rk3328_bus_get_clk(priv, ACLK_BUS_PRE); 509 break; 510 case PCLK_BUS_PRE: 511 con = readl(&cru->clksel_con[1]); 512 div = (con & PCLK_BUS_DIV_CON_MASK) >> PCLK_BUS_DIV_CON_SHIFT; 513 parent = rk3328_bus_get_clk(priv, ACLK_BUS_PRE); 514 break; 515 default: 516 return -ENOENT; 517 } 518 519 return DIV_TO_RATE(parent, div); 520 } 521 522 static ulong rk3328_bus_set_clk(struct rk3328_clk_priv *priv, 523 ulong clk_id, ulong hz) 524 { 525 struct rk3328_cru *cru = priv->cru; 526 int src_clk_div; 527 528 /* 529 * select gpll as pd_bus bus clock source and 530 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 531 */ 532 switch (clk_id) { 533 case ACLK_BUS_PRE: 534 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz); 535 assert(src_clk_div - 1 < 31); 536 rk_clrsetreg(&cru->clksel_con[0], 537 CLK_BUS_PLL_SEL_MASK | ACLK_BUS_DIV_CON_MASK, 538 CLK_BUS_PLL_SEL_CPLL << CLK_BUS_PLL_SEL_SHIFT | 539 (src_clk_div - 1) << ACLK_BUS_DIV_CON_SHIFT); 540 break; 541 case HCLK_BUS_PRE: 542 src_clk_div = DIV_ROUND_UP(rk3328_bus_get_clk(priv, 543 ACLK_BUS_PRE), 544 hz); 545 assert(src_clk_div - 1 < 3); 546 rk_clrsetreg(&cru->clksel_con[1], 547 HCLK_BUS_DIV_CON_MASK, 548 (src_clk_div - 1) << HCLK_BUS_DIV_CON_SHIFT); 549 break; 550 case PCLK_BUS_PRE: 551 src_clk_div = DIV_ROUND_UP(rk3328_bus_get_clk(priv, 552 ACLK_BUS_PRE), 553 hz); 554 assert(src_clk_div - 1 < 7); 555 rk_clrsetreg(&cru->clksel_con[1], 556 PCLK_BUS_DIV_CON_MASK, 557 (src_clk_div - 1) << PCLK_BUS_DIV_CON_SHIFT); 558 break; 559 default: 560 printf("do not support this bus freq\n"); 561 return -EINVAL; 562 } 563 return rk3328_bus_get_clk(priv, clk_id); 564 } 565 566 static ulong rk3328_peri_get_clk(struct rk3328_clk_priv *priv, ulong clk_id) 567 { 568 struct rk3328_cru *cru = priv->cru; 569 u32 div, con, parent; 570 571 switch (clk_id) { 572 case ACLK_PERI_PRE: 573 con = readl(&cru->clksel_con[28]); 574 div = (con & ACLK_PERI_DIV_CON_MASK) >> ACLK_PERI_DIV_CON_SHIFT; 575 parent = priv->cpll_hz; 576 break; 577 case HCLK_PERI: 578 con = readl(&cru->clksel_con[29]); 579 div = (con & HCLK_PERI_DIV_CON_MASK) >> HCLK_PERI_DIV_CON_SHIFT; 580 parent = rk3328_peri_get_clk(priv, ACLK_PERI_PRE); 581 break; 582 case PCLK_PERI: 583 con = readl(&cru->clksel_con[29]); 584 div = (con & PCLK_PERI_DIV_CON_MASK) >> PCLK_PERI_DIV_CON_SHIFT; 585 parent = rk3328_peri_get_clk(priv, ACLK_PERI_PRE); 586 break; 587 default: 588 return -ENOENT; 589 } 590 591 return DIV_TO_RATE(parent, div); 592 } 593 594 static ulong rk3328_peri_set_clk(struct rk3328_clk_priv *priv, 595 ulong clk_id, ulong hz) 596 { 597 struct rk3328_cru *cru = priv->cru; 598 int src_clk_div; 599 600 /* 601 * select gpll as pd_bus bus clock source and 602 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 603 */ 604 switch (clk_id) { 605 case ACLK_PERI_PRE: 606 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz); 607 assert(src_clk_div - 1 < 31); 608 rk_clrsetreg(&cru->clksel_con[28], 609 CLK_PERI_PLL_SEL_MASK | ACLK_PERI_DIV_CON_MASK, 610 CLK_PERI_PLL_SEL_CPLL << CLK_PERI_PLL_SEL_SHIFT | 611 (src_clk_div - 1) << ACLK_PERI_DIV_CON_SHIFT); 612 break; 613 case HCLK_PERI: 614 src_clk_div = DIV_ROUND_UP(rk3328_peri_get_clk(priv, 615 ACLK_PERI_PRE), 616 hz); 617 assert(src_clk_div - 1 < 3); 618 rk_clrsetreg(&cru->clksel_con[29], 619 HCLK_PERI_DIV_CON_MASK, 620 (src_clk_div - 1) << HCLK_PERI_DIV_CON_SHIFT); 621 break; 622 case PCLK_PERI: 623 src_clk_div = DIV_ROUND_UP(rk3328_peri_get_clk(priv, 624 ACLK_PERI_PRE), 625 hz); 626 assert(src_clk_div - 1 < 7); 627 rk_clrsetreg(&cru->clksel_con[29], 628 PCLK_PERI_DIV_CON_MASK, 629 (src_clk_div - 1) << PCLK_PERI_DIV_CON_SHIFT); 630 break; 631 default: 632 printf("do not support this bus freq\n"); 633 return -EINVAL; 634 } 635 636 return rk3328_peri_get_clk(priv, clk_id); 637 } 638 639 static ulong rk3328_clk_get_rate(struct clk *clk) 640 { 641 struct rk3328_clk_priv *priv = dev_get_priv(clk->dev); 642 ulong rate = 0; 643 644 #ifndef CONFIG_SPL_BUILD 645 if (!priv->gpll_hz) { 646 priv->gpll_hz = rockchip_pll_get_rate(&rk3328_pll_clks[GPLL], 647 priv->cru, GPLL); 648 debug("%s gpll=%lu\n", __func__, priv->gpll_hz); 649 } 650 if (!priv->cpll_hz) { 651 priv->cpll_hz = rockchip_pll_get_rate(&rk3328_pll_clks[CPLL], 652 priv->cru, CPLL); 653 debug("%s cpll=%lu\n", __func__, priv->cpll_hz); 654 } 655 #endif 656 657 switch (clk->id) { 658 case PLL_APLL: 659 case PLL_DPLL: 660 case PLL_CPLL: 661 case PLL_GPLL: 662 case PLL_NPLL: 663 rate = rockchip_pll_get_rate(&rk3328_pll_clks[clk->id - 1], 664 priv->cru, clk->id - 1); 665 break; 666 case ARMCLK: 667 rate = rockchip_pll_get_rate(&rk3328_pll_clks[NPLL], 668 priv->cru, NPLL); 669 break; 670 case ACLK_BUS_PRE: 671 case HCLK_BUS_PRE: 672 case PCLK_BUS_PRE: 673 rate = rk3328_bus_get_clk(priv, clk->id); 674 break; 675 case ACLK_PERI_PRE: 676 case HCLK_PERI: 677 case PCLK_PERI: 678 rate = rk3328_peri_get_clk(priv, clk->id); 679 break; 680 case HCLK_SDMMC: 681 case HCLK_EMMC: 682 case SCLK_SDMMC: 683 case SCLK_EMMC: 684 rate = rk3328_mmc_get_clk(priv, clk->id); 685 break; 686 #ifndef CONFIG_SPL_BUILD 687 case SCLK_I2C0: 688 case SCLK_I2C1: 689 case SCLK_I2C2: 690 case SCLK_I2C3: 691 rate = rk3328_i2c_get_clk(priv, clk->id); 692 break; 693 case SCLK_PWM: 694 rate = rk3328_pwm_get_clk(priv); 695 break; 696 case SCLK_SARADC: 697 rate = rk3328_saradc_get_clk(priv); 698 break; 699 case ACLK_VOP_PRE: 700 case ACLK_VIO_PRE: 701 case HCLK_VIO_PRE: 702 case ACLK_VOP: 703 case ACLK_VIO: 704 case HCLK_VIO: 705 rate = rk3328_vop_get_clk(priv, clk->id); 706 break; 707 #endif 708 default: 709 return -ENOENT; 710 } 711 712 return rate; 713 } 714 715 static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate) 716 { 717 struct rk3328_clk_priv *priv = dev_get_priv(clk->dev); 718 ulong ret = 0; 719 720 switch (clk->id) { 721 case PLL_APLL: 722 case PLL_DPLL: 723 case PLL_NPLL: 724 ret = rockchip_pll_set_rate(&rk3328_pll_clks[clk->id - 1], 725 priv->cru, clk->id - 1, rate); 726 break; 727 case PLL_CPLL: 728 ret = rockchip_pll_set_rate(&rk3328_pll_clks[CPLL], 729 priv->cru, CPLL, rate); 730 priv->cpll_hz = rate; 731 break; 732 case PLL_GPLL: 733 ret = rockchip_pll_set_rate(&rk3328_pll_clks[GPLL], 734 priv->cru, GPLL, rate); 735 priv->gpll_hz = rate; 736 break; 737 case ARMCLK: 738 ret = rk3328_armclk_set_clk(priv, rate); 739 break; 740 case ACLK_BUS_PRE: 741 case HCLK_BUS_PRE: 742 case PCLK_BUS_PRE: 743 rate = rk3328_bus_set_clk(priv, clk->id, rate); 744 break; 745 case ACLK_PERI_PRE: 746 case HCLK_PERI: 747 case PCLK_PERI: 748 rate = rk3328_peri_set_clk(priv, clk->id, rate); 749 break; 750 case HCLK_SDMMC: 751 case HCLK_EMMC: 752 case SCLK_SDMMC: 753 case SCLK_EMMC: 754 ret = rk3328_mmc_set_clk(priv, clk->id, rate); 755 break; 756 #ifndef CONFIG_SPL_BUILD 757 case SCLK_I2C0: 758 case SCLK_I2C1: 759 case SCLK_I2C2: 760 case SCLK_I2C3: 761 ret = rk3328_i2c_set_clk(priv, clk->id, rate); 762 break; 763 case SCLK_MAC2IO: 764 ret = rk3328_gmac2io_set_clk(priv, rate); 765 break; 766 case SCLK_PWM: 767 ret = rk3328_pwm_set_clk(priv, rate); 768 break; 769 case SCLK_SARADC: 770 ret = rk3328_saradc_set_clk(priv, rate); 771 break; 772 case DCLK_LCDC: 773 case ACLK_VOP_PRE: 774 case ACLK_VIO_PRE: 775 case HCLK_VIO_PRE: 776 case ACLK_VOP: 777 case ACLK_VIO: 778 case HCLK_VIO: 779 rate = rk3328_vop_set_clk(priv, clk->id, rate); 780 break; 781 #endif 782 case SCLK_PDM: 783 case SCLK_RTC32K: 784 case SCLK_UART0: 785 case SCLK_UART1: 786 case SCLK_UART2: 787 case SCLK_SDIO: 788 case SCLK_TSP: 789 case SCLK_WIFI: 790 case ACLK_RGA_PRE: 791 case SCLK_RGA: 792 case ACLK_RKVDEC_PRE: 793 case ACLK_RKVENC: 794 case ACLK_VPU_PRE: 795 case SCLK_VDEC_CABAC: 796 case SCLK_VDEC_CORE: 797 case SCLK_VENC_CORE: 798 case SCLK_VENC_DSP: 799 case SCLK_EFUSE: 800 case PCLK_DDR: 801 case ACLK_GMAC: 802 case PCLK_GMAC: 803 case SCLK_USB3OTG_SUSPEND: 804 return 0; 805 default: 806 return -ENOENT; 807 } 808 809 return ret; 810 } 811 812 #ifndef CONFIG_SPL_BUILD 813 static int rk3328_gmac2io_set_parent(struct clk *clk, struct clk *parent) 814 { 815 struct rk3328_grf_regs *grf; 816 const char *clock_output_name; 817 int ret; 818 819 grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 820 821 /* 822 * If the requested parent is in the same clock-controller and the id 823 * is SCLK_MAC2IO_SRC ("clk_mac2io_src"), switch to the internal clock. 824 */ 825 if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2IO_SRC)) { 826 debug("%s: switching RGMII to SCLK_MAC2IO_SRC\n", __func__); 827 rk_clrreg(&grf->mac_con[1], BIT(10)); 828 return 0; 829 } 830 831 /* 832 * Otherwise, we need to check the clock-output-names of the 833 * requested parent to see if the requested id is "gmac_clkin". 834 */ 835 ret = dev_read_string_index(parent->dev, "clock-output-names", 836 parent->id, &clock_output_name); 837 if (ret < 0) 838 return -ENODATA; 839 840 /* If this is "gmac_clkin", switch to the external clock input */ 841 if (!strcmp(clock_output_name, "gmac_clkin")) { 842 debug("%s: switching RGMII to CLKIN\n", __func__); 843 rk_setreg(&grf->mac_con[1], BIT(10)); 844 return 0; 845 } 846 847 return -EINVAL; 848 } 849 850 static int rk3328_gmac2io_ext_set_parent(struct clk *clk, struct clk *parent) 851 { 852 struct rk3328_grf_regs *grf; 853 const char *clock_output_name; 854 int ret; 855 856 grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 857 858 /* 859 * If the requested parent is in the same clock-controller and the id 860 * is SCLK_MAC2IO ("clk_mac2io"), switch to the internal clock. 861 */ 862 if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2IO)) { 863 debug("%s: switching RGMII to SCLK_MAC2IO\n", __func__); 864 rk_clrreg(&grf->soc_con[4], BIT(14)); 865 return 0; 866 } 867 868 /* 869 * Otherwise, we need to check the clock-output-names of the 870 * requested parent to see if the requested id is "gmac_clkin". 871 */ 872 ret = dev_read_string_index(parent->dev, "clock-output-names", 873 parent->id, &clock_output_name); 874 if (ret < 0) 875 return -ENODATA; 876 877 /* If this is "gmac_clkin", switch to the external clock input */ 878 if (!strcmp(clock_output_name, "gmac_clkin")) { 879 debug("%s: switching RGMII to CLKIN\n", __func__); 880 rk_setreg(&grf->soc_con[4], BIT(14)); 881 return 0; 882 } 883 884 return -EINVAL; 885 } 886 887 static int rk3328_lcdc_set_parent(struct clk *clk, struct clk *parent) 888 { 889 struct rk3328_clk_priv *priv = dev_get_priv(clk->dev); 890 891 if (parent->id == HDMIPHY) 892 rk_clrsetreg(&priv->cru->clksel_con[40], 893 DCLK_LCDC_SEL_MASK, 894 DCLK_LCDC_SEL_HDMIPHY << DCLK_LCDC_SEL_SHIFT); 895 else if (parent->id == PLL_CPLL) 896 rk_clrsetreg(&priv->cru->clksel_con[40], 897 DCLK_LCDC_SEL_MASK | DCLK_LCDC_PLL_SEL_MASK, 898 (DCLK_LCDC_SEL_PLL << DCLK_LCDC_SEL_SHIFT) | 899 (DCLK_LCDC_PLL_SEL_CPLL << 900 DCLK_LCDC_PLL_SEL_SHIFT)); 901 else 902 rk_clrsetreg(&priv->cru->clksel_con[40], 903 DCLK_LCDC_SEL_MASK | DCLK_LCDC_PLL_SEL_MASK, 904 (DCLK_LCDC_SEL_PLL << DCLK_LCDC_SEL_SHIFT) | 905 (DCLK_LCDC_PLL_SEL_GPLL << 906 DCLK_LCDC_PLL_SEL_SHIFT)); 907 908 return 0; 909 } 910 #endif 911 912 static int rk3328_clk_set_parent(struct clk *clk, struct clk *parent) 913 { 914 switch (clk->id) { 915 #ifndef CONFIG_SPL_BUILD 916 case SCLK_MAC2IO: 917 return rk3328_gmac2io_set_parent(clk, parent); 918 case SCLK_MAC2IO_EXT: 919 return rk3328_gmac2io_ext_set_parent(clk, parent); 920 case DCLK_LCDC: 921 return rk3328_lcdc_set_parent(clk, parent); 922 #endif 923 case SCLK_PDM: 924 case SCLK_RTC32K: 925 case SCLK_UART0: 926 case SCLK_UART1: 927 case SCLK_UART2: 928 return 0; 929 } 930 931 debug("%s: unsupported clk %ld\n", __func__, clk->id); 932 return -ENOENT; 933 } 934 935 static struct clk_ops rk3328_clk_ops = { 936 .get_rate = rk3328_clk_get_rate, 937 .set_rate = rk3328_clk_set_rate, 938 .set_parent = rk3328_clk_set_parent, 939 }; 940 941 static void rkclk_init(struct rk3328_clk_priv *priv) 942 { 943 if (rockchip_pll_get_rate(&rk3328_pll_clks[NPLL], 944 priv->cru, NPLL) != APLL_HZ) 945 rk3328_armclk_set_clk(priv, APLL_HZ); 946 947 priv->gpll_hz = rockchip_pll_get_rate(&rk3328_pll_clks[GPLL], 948 priv->cru, GPLL); 949 priv->cpll_hz = rockchip_pll_get_rate(&rk3328_pll_clks[CPLL], 950 priv->cru, CPLL); 951 952 /* before set pll set child div first */ 953 rk_clrsetreg(&priv->cru->clksel_con[24], (0x3f << 8) | (0x3f << 0), 954 (0x17 << 8) | (0x17 << 0)); 955 rk_clrsetreg(&priv->cru->clksel_con[27], (0x1f << 8) | (0x1f << 0), 956 (0x17 << 8) | (0x17 << 0)); 957 rk_clrsetreg(&priv->cru->clksel_con[31], 0xff << 0, 0xb << 0); 958 rk_clrsetreg(&priv->cru->clksel_con[43], 0xff << 0, 0xb << 0); 959 rk_clrsetreg(&priv->cru->clksel_con[52], 0x1f << 8, 0x5 << 8); 960 961 rockchip_pll_set_rate(&rk3328_pll_clks[GPLL], 962 priv->cru, GPLL, GPLL_HZ); 963 priv->gpll_hz = GPLL_HZ; 964 965 rockchip_pll_set_rate(&rk3328_pll_clks[CPLL], 966 priv->cru, CPLL, CPLL_HZ); 967 priv->cpll_hz = CPLL_HZ; 968 969 rk3328_bus_set_clk(priv, ACLK_BUS_PRE, ACLK_BUS_HZ); 970 rk3328_bus_set_clk(priv, HCLK_BUS_PRE, ACLK_BUS_HZ / 2); 971 rk3328_bus_set_clk(priv, PCLK_BUS_PRE, ACLK_BUS_HZ / 2); 972 rk3328_peri_set_clk(priv, ACLK_PERI_PRE, ACLK_PERI_HZ); 973 rk3328_peri_set_clk(priv, HCLK_PERI, ACLK_PERI_HZ / 2); 974 rk3328_peri_set_clk(priv, PCLK_PERI, ACLK_PERI_HZ / 2); 975 /*rk3328_mmc_set_clk(priv, SCLK_EMMC, rate);*/ 976 977 /* set usbphy and hdmiphy from phy */ 978 rk_clrsetreg(&priv->cru->misc, (0x1 << 13) | 979 (0x1 << 15), (0 << 15) | (0 << 13)); 980 } 981 982 static int rk3328_clk_probe(struct udevice *dev) 983 { 984 struct rk3328_clk_priv *priv = dev_get_priv(dev); 985 986 rkclk_init(priv); 987 988 return 0; 989 } 990 991 static int rk3328_clk_ofdata_to_platdata(struct udevice *dev) 992 { 993 struct rk3328_clk_priv *priv = dev_get_priv(dev); 994 995 priv->cru = dev_read_addr_ptr(dev); 996 997 return 0; 998 } 999 1000 static int rk3328_clk_bind(struct udevice *dev) 1001 { 1002 int ret; 1003 struct udevice *sys_child, *sf_child; 1004 struct sysreset_reg *priv; 1005 struct softreset_reg *sf_priv; 1006 1007 /* The reset driver does not have a device node, so bind it here */ 1008 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 1009 &sys_child); 1010 if (ret) { 1011 debug("Warning: No sysreset driver: ret=%d\n", ret); 1012 } else { 1013 priv = malloc(sizeof(struct sysreset_reg)); 1014 priv->glb_srst_fst_value = offsetof(struct rk3328_cru, 1015 glb_srst_fst_value); 1016 priv->glb_srst_snd_value = offsetof(struct rk3328_cru, 1017 glb_srst_snd_value); 1018 sys_child->priv = priv; 1019 } 1020 1021 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 1022 dev_ofnode(dev), &sf_child); 1023 if (ret) { 1024 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 1025 } else { 1026 sf_priv = malloc(sizeof(struct softreset_reg)); 1027 sf_priv->sf_reset_offset = offsetof(struct rk3328_cru, 1028 softrst_con[0]); 1029 sf_priv->sf_reset_num = 12; 1030 sf_child->priv = sf_priv; 1031 } 1032 1033 return 0; 1034 } 1035 1036 static const struct udevice_id rk3328_clk_ids[] = { 1037 { .compatible = "rockchip,rk3328-cru" }, 1038 { } 1039 }; 1040 1041 U_BOOT_DRIVER(rockchip_rk3328_cru) = { 1042 .name = "rockchip_rk3328_cru", 1043 .id = UCLASS_CLK, 1044 .of_match = rk3328_clk_ids, 1045 .priv_auto_alloc_size = sizeof(struct rk3328_clk_priv), 1046 .ofdata_to_platdata = rk3328_clk_ofdata_to_platdata, 1047 .ops = &rk3328_clk_ops, 1048 .bind = rk3328_clk_bind, 1049 .probe = rk3328_clk_probe, 1050 }; 1051 1052 #ifndef CONFIG_SPL_BUILD 1053 /** 1054 * soc_clk_dump() - Print clock frequencies 1055 * Returns zero on success 1056 * 1057 * Implementation for the clk dump command. 1058 */ 1059 int soc_clk_dump(void) 1060 { 1061 struct udevice *cru_dev; 1062 const struct rk3328_clk_info *clk_dump; 1063 struct clk clk; 1064 unsigned long clk_count = ARRAY_SIZE(clks_dump); 1065 unsigned long rate; 1066 int i, ret; 1067 1068 ret = uclass_get_device_by_driver(UCLASS_CLK, 1069 DM_GET_DRIVER(rockchip_rk3328_cru), 1070 &cru_dev); 1071 if (ret) { 1072 printf("%s failed to get cru device\n", __func__); 1073 return ret; 1074 } 1075 1076 printf("CLK:"); 1077 for (i = 0; i < clk_count; i++) { 1078 clk_dump = &clks_dump[i]; 1079 if (clk_dump->name) { 1080 clk.id = clk_dump->id; 1081 if (clk_dump->is_cru) 1082 ret = clk_request(cru_dev, &clk); 1083 if (ret < 0) 1084 return ret; 1085 1086 rate = clk_get_rate(&clk); 1087 clk_free(&clk); 1088 if (i == 0) { 1089 if (rate < 0) 1090 printf("%10s%20s\n", clk_dump->name, 1091 "unknown"); 1092 else 1093 printf("%10s%20lu Hz\n", clk_dump->name, 1094 rate); 1095 } else { 1096 if (rate < 0) 1097 printf("%14s%20s\n", clk_dump->name, 1098 "unknown"); 1099 else 1100 printf("%14s%20lu Hz\n", clk_dump->name, 1101 rate); 1102 } 1103 } 1104 } 1105 1106 return 0; 1107 } 1108 #endif 1109