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 <clk-uclass.h> 9 #include <dm.h> 10 #include <errno.h> 11 #include <syscon.h> 12 #include <asm/io.h> 13 #include <asm/arch/clock.h> 14 #include <asm/arch/cru_rk322x.h> 15 #include <asm/arch/hardware.h> 16 #include <dm/lists.h> 17 #include <dt-bindings/clock/rk3228-cru.h> 18 #include <linux/log2.h> 19 20 DECLARE_GLOBAL_DATA_PTR; 21 22 #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1)) 23 24 #ifndef CONFIG_SPL_BUILD 25 #define RK322x_CLK_DUMP(_id, _name, _iscru) \ 26 { \ 27 .id = _id, \ 28 .name = _name, \ 29 .is_cru = _iscru, \ 30 } 31 #endif 32 33 static struct rockchip_pll_rate_table rk322x_pll_rates[] = { 34 /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ 35 RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), 36 #ifndef CONFIG_SPL_BUILD 37 RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0), 38 RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), 39 #endif 40 RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0), 41 RK3036_PLL_RATE(800000000, 1, 100, 3, 1, 1, 0), 42 RK3036_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0), 43 #ifndef CONFIG_SPL_BUILD 44 RK3036_PLL_RATE(594000000, 2, 99, 2, 1, 1, 0), 45 RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0), 46 RK3036_PLL_RATE(400000000, 1, 50, 3, 1, 1, 0), 47 #endif 48 { /* sentinel */ }, 49 }; 50 51 #define RK322x_CPUCLK_RATE(_rate, _aclk_div, _pclk_div) \ 52 { \ 53 .rate = _rate##U, \ 54 .aclk_div = _aclk_div, \ 55 .pclk_div = _pclk_div, \ 56 } 57 58 static struct rockchip_cpu_rate_table rk322x_cpu_rates[] = { 59 RK322x_CPUCLK_RATE(1200000000, 1, 5), 60 RK322x_CPUCLK_RATE(1008000000, 1, 5), 61 RK322x_CPUCLK_RATE(816000000, 1, 3), 62 RK322x_CPUCLK_RATE(600000000, 1, 3), 63 }; 64 65 #ifndef CONFIG_SPL_BUILD 66 static const struct rk322x_clk_info clks_dump[] = { 67 RK322x_CLK_DUMP(PLL_APLL, "apll", true), 68 RK322x_CLK_DUMP(PLL_DPLL, "dpll", true), 69 RK322x_CLK_DUMP(PLL_CPLL, "cpll", true), 70 RK322x_CLK_DUMP(PLL_GPLL, "gpll", true), 71 RK322x_CLK_DUMP(ARMCLK, "armclk", true), 72 RK322x_CLK_DUMP(ACLK_CPU, "aclk_bus", true), 73 RK322x_CLK_DUMP(HCLK_CPU, "hclk_bus", true), 74 RK322x_CLK_DUMP(PCLK_CPU, "pclk_bus", true), 75 RK322x_CLK_DUMP(ACLK_PERI, "aclk_peri", true), 76 RK322x_CLK_DUMP(HCLK_PERI, "hclk_peri", true), 77 RK322x_CLK_DUMP(PCLK_PERI, "pclk_peri", true), 78 }; 79 #endif 80 81 static struct rockchip_pll_clock rk322x_pll_clks[] = { 82 [APLL] = PLL(pll_rk3036, PLL_APLL, RK2928_PLL_CON(0), 83 RK2928_MODE_CON, 0, 10, 0, rk322x_pll_rates), 84 [DPLL] = PLL(pll_rk3036, PLL_DPLL, RK2928_PLL_CON(3), 85 RK2928_MODE_CON, 4, 10, 0, rk322x_pll_rates), 86 [CPLL] = PLL(pll_rk3036, PLL_CPLL, RK2928_PLL_CON(6), 87 RK2928_MODE_CON, 8, 10, 0, rk322x_pll_rates), 88 [GPLL] = PLL(pll_rk3036, PLL_GPLL, RK2928_PLL_CON(9), 89 RK2928_MODE_CON, 12, 10, 0, rk322x_pll_rates), 90 }; 91 92 static ulong rk322x_armclk_set_clk(struct rk322x_clk_priv *priv, ulong hz) 93 { 94 struct rk322x_cru *cru = priv->cru; 95 const struct rockchip_cpu_rate_table *rate; 96 ulong old_rate; 97 98 rate = rockchip_get_cpu_settings(rk322x_cpu_rates, hz); 99 if (!rate) { 100 printf("%s unsupported rate\n", __func__); 101 return -EINVAL; 102 } 103 104 /* 105 * select apll as cpu/core clock pll source and 106 * set up dependent divisors for PERI and ACLK clocks. 107 * core hz : apll = 1:1 108 */ 109 old_rate = rockchip_pll_get_rate(&rk322x_pll_clks[APLL], 110 priv->cru, APLL); 111 if (old_rate > hz) { 112 if (rockchip_pll_set_rate(&rk322x_pll_clks[APLL], 113 priv->cru, APLL, hz)) 114 return -EINVAL; 115 rk_clrsetreg(&cru->cru_clksel_con[0], 116 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK, 117 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 118 0 << CORE_DIV_CON_SHIFT); 119 rk_clrsetreg(&cru->cru_clksel_con[1], 120 CORE_ACLK_DIV_MASK | CORE_PERI_DIV_MASK, 121 rate->aclk_div << CORE_ACLK_DIV_SHIFT | 122 rate->pclk_div << CORE_PERI_DIV_SHIFT); 123 } else if (old_rate < hz) { 124 rk_clrsetreg(&cru->cru_clksel_con[1], 125 CORE_ACLK_DIV_MASK | CORE_PERI_DIV_MASK, 126 rate->aclk_div << CORE_ACLK_DIV_SHIFT | 127 rate->pclk_div << CORE_PERI_DIV_SHIFT); 128 rk_clrsetreg(&cru->cru_clksel_con[0], 129 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK, 130 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 131 0 << CORE_DIV_CON_SHIFT); 132 if (rockchip_pll_set_rate(&rk322x_pll_clks[APLL], 133 priv->cru, APLL, hz)) 134 return -EINVAL; 135 } 136 137 return rockchip_pll_get_rate(&rk322x_pll_clks[APLL], priv->cru, APLL); 138 } 139 140 static ulong rk322x_mmc_get_clk(struct rk322x_clk_priv *priv, 141 int periph) 142 { 143 struct rk322x_cru *cru = priv->cru; 144 uint src_rate; 145 uint div, mux; 146 u32 con; 147 148 switch (periph) { 149 case HCLK_EMMC: 150 case SCLK_EMMC: 151 case SCLK_EMMC_SAMPLE: 152 con = readl(&cru->cru_clksel_con[11]); 153 mux = (con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT; 154 con = readl(&cru->cru_clksel_con[12]); 155 div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT; 156 break; 157 case HCLK_SDMMC: 158 case SCLK_SDMMC: 159 case SCLK_SDMMC_SAMPLE: 160 con = readl(&cru->cru_clksel_con[11]); 161 mux = (con & MMC0_PLL_MASK) >> MMC0_PLL_SHIFT; 162 div = (con & MMC0_DIV_MASK) >> MMC0_DIV_SHIFT; 163 break; 164 case SCLK_SDIO: 165 case SCLK_SDIO_SAMPLE: 166 con = readl(&cru->cru_clksel_con[11]); 167 mux = (con & SDIO_PLL_MASK) >> SDIO_PLL_SHIFT; 168 con = readl(&cru->cru_clksel_con[12]); 169 div = (con & SDIO_DIV_MASK) >> SDIO_DIV_SHIFT; 170 break; 171 default: 172 return -EINVAL; 173 } 174 175 src_rate = mux == EMMC_SEL_24M ? OSC_HZ : priv->gpll_hz; 176 return DIV_TO_RATE(src_rate, div) / 2; 177 } 178 179 #ifndef CONFIG_SPL_BUILD 180 static ulong rk322x_mac_set_clk(struct rk322x_clk_priv *priv, uint freq) 181 { 182 struct rk322x_cru *cru = priv->cru; 183 ulong ret; 184 185 /* 186 * The gmac clock can be derived either from an external clock 187 * or can be generated from internally by a divider from SCLK_MAC. 188 */ 189 if (readl(&cru->cru_clksel_con[5]) & BIT(5)) { 190 /* An external clock will always generate the right rate... */ 191 ret = freq; 192 } else { 193 u32 con = readl(&cru->cru_clksel_con[5]); 194 ulong pll_rate; 195 u8 div; 196 197 if ((con >> MAC_PLL_SEL_SHIFT) & MAC_PLL_SEL_MASK) 198 pll_rate = priv->gpll_hz; 199 else 200 /* CPLL is not set */ 201 return -EPERM; 202 203 div = DIV_ROUND_UP(pll_rate, freq) - 1; 204 if (div <= 0x1f) 205 rk_clrsetreg(&cru->cru_clksel_con[5], CLK_MAC_DIV_MASK, 206 div << CLK_MAC_DIV_SHIFT); 207 else 208 debug("Unsupported div for gmac:%d\n", div); 209 210 return DIV_TO_RATE(pll_rate, div); 211 } 212 213 return ret; 214 } 215 #endif 216 217 static ulong rk322x_mmc_set_clk(struct rk322x_clk_priv *priv, 218 int periph, uint freq) 219 { 220 struct rk322x_cru *cru = priv->cru; 221 int src_clk_div; 222 int mux; 223 224 /* mmc clock defaulg div 2 internal, need provide double in cru */ 225 src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, freq); 226 227 if (src_clk_div > 128) { 228 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, freq); 229 assert(src_clk_div - 1 < 128); 230 mux = EMMC_SEL_24M; 231 } else { 232 mux = EMMC_SEL_GPLL; 233 } 234 235 switch (periph) { 236 case HCLK_EMMC: 237 case SCLK_EMMC: 238 case SCLK_EMMC_SAMPLE: 239 rk_clrsetreg(&cru->cru_clksel_con[11], 240 EMMC_PLL_MASK, 241 mux << EMMC_PLL_SHIFT); 242 rk_clrsetreg(&cru->cru_clksel_con[12], 243 EMMC_DIV_MASK, 244 (src_clk_div - 1) << EMMC_DIV_SHIFT); 245 break; 246 case HCLK_SDMMC: 247 case SCLK_SDMMC: 248 case SCLK_SDMMC_SAMPLE: 249 rk_clrsetreg(&cru->cru_clksel_con[11], 250 MMC0_PLL_MASK | MMC0_DIV_MASK, 251 mux << MMC0_PLL_SHIFT | 252 (src_clk_div - 1) << MMC0_DIV_SHIFT); 253 break; 254 case SCLK_SDIO: 255 case SCLK_SDIO_SAMPLE: 256 rk_clrsetreg(&cru->cru_clksel_con[11], 257 SDIO_PLL_MASK, 258 mux << SDIO_PLL_SHIFT); 259 rk_clrsetreg(&cru->cru_clksel_con[12], 260 SDIO_DIV_MASK, 261 (src_clk_div - 1) << SDIO_DIV_SHIFT); 262 break; 263 default: 264 return -EINVAL; 265 } 266 267 return rk322x_mmc_get_clk(priv, periph); 268 } 269 270 static ulong rk322x_bus_get_clk(struct rk322x_clk_priv *priv, ulong clk_id) 271 { 272 struct rk322x_cru *cru = priv->cru; 273 u32 div, con, parent; 274 275 switch (clk_id) { 276 case ACLK_CPU: 277 con = readl(&cru->cru_clksel_con[0]); 278 div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT; 279 parent = priv->gpll_hz; 280 break; 281 case HCLK_CPU: 282 con = readl(&cru->cru_clksel_con[1]); 283 div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT; 284 parent = rk322x_bus_get_clk(priv, ACLK_CPU); 285 break; 286 case PCLK_CPU: 287 case PCLK_I2C0: 288 case PCLK_I2C1: 289 case PCLK_I2C2: 290 case PCLK_I2C3: 291 case PCLK_PWM: 292 con = readl(&cru->cru_clksel_con[1]); 293 div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT; 294 parent = rk322x_bus_get_clk(priv, ACLK_CPU); 295 break; 296 default: 297 return -ENOENT; 298 } 299 300 return DIV_TO_RATE(parent, div); 301 } 302 303 static ulong rk322x_bus_set_clk(struct rk322x_clk_priv *priv, 304 ulong clk_id, ulong hz) 305 { 306 struct rk322x_cru *cru = priv->cru; 307 int src_clk_div; 308 309 /* 310 * select gpll as pd_bus bus clock source and 311 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 312 */ 313 switch (clk_id) { 314 case ACLK_CPU: 315 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 316 assert(src_clk_div - 1 < 32); 317 rk_clrsetreg(&cru->cru_clksel_con[0], 318 BUS_ACLK_PLL_SEL_MASK | BUS_ACLK_DIV_MASK, 319 BUS_ACLK_PLL_SEL_GPLL << BUS_ACLK_PLL_SEL_SHIFT | 320 (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT); 321 break; 322 case HCLK_CPU: 323 src_clk_div = DIV_ROUND_UP(rk322x_bus_get_clk(priv, 324 ACLK_CPU), 325 hz); 326 assert(src_clk_div - 1 < 4); 327 rk_clrsetreg(&cru->cru_clksel_con[1], 328 BUS_HCLK_DIV_MASK, 329 (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT); 330 break; 331 case PCLK_CPU: 332 src_clk_div = DIV_ROUND_UP(rk322x_bus_get_clk(priv, 333 ACLK_CPU), 334 hz); 335 assert(src_clk_div - 1 < 8); 336 rk_clrsetreg(&cru->cru_clksel_con[1], 337 BUS_PCLK_DIV_MASK, 338 (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT); 339 break; 340 default: 341 printf("do not support this bus freq\n"); 342 return -EINVAL; 343 } 344 345 return rk322x_bus_get_clk(priv, clk_id); 346 } 347 348 static ulong rk322x_peri_get_clk(struct rk322x_clk_priv *priv, ulong clk_id) 349 { 350 struct rk322x_cru *cru = priv->cru; 351 u32 div, con, parent; 352 353 switch (clk_id) { 354 case ACLK_PERI: 355 con = readl(&cru->cru_clksel_con[10]); 356 div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT; 357 parent = priv->gpll_hz; 358 break; 359 case HCLK_PERI: 360 con = readl(&cru->cru_clksel_con[10]); 361 div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT; 362 parent = rk322x_peri_get_clk(priv, ACLK_PERI); 363 break; 364 case PCLK_PERI: 365 con = readl(&cru->cru_clksel_con[10]); 366 div = (con & PERI_PCLK_DIV_MASK) >> PERI_PCLK_DIV_SHIFT; 367 parent = rk322x_peri_get_clk(priv, ACLK_PERI); 368 break; 369 default: 370 return -ENOENT; 371 } 372 373 return DIV_TO_RATE(parent, div); 374 } 375 376 static ulong rk322x_peri_set_clk(struct rk322x_clk_priv *priv, 377 ulong clk_id, ulong hz) 378 { 379 struct rk322x_cru *cru = priv->cru; 380 int src_clk_div; 381 382 /* 383 * select gpll as pd_bus bus clock source and 384 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 385 */ 386 switch (clk_id) { 387 case ACLK_PERI: 388 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 389 assert(src_clk_div - 1 < 32); 390 rk_clrsetreg(&cru->cru_clksel_con[10], 391 PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK, 392 PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT | 393 (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT); 394 break; 395 case HCLK_PERI: 396 src_clk_div = DIV_ROUND_UP(rk322x_peri_get_clk(priv, 397 ACLK_PERI), 398 hz); 399 assert(src_clk_div - 1 < 4); 400 rk_clrsetreg(&cru->cru_clksel_con[10], 401 PERI_HCLK_DIV_MASK, 402 (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT); 403 break; 404 case PCLK_PERI: 405 src_clk_div = DIV_ROUND_UP(rk322x_peri_get_clk(priv, 406 ACLK_PERI), 407 hz); 408 assert(src_clk_div - 1 < 8); 409 rk_clrsetreg(&cru->cru_clksel_con[10], 410 PERI_PCLK_DIV_MASK, 411 (src_clk_div - 1) << PERI_PCLK_DIV_SHIFT); 412 break; 413 default: 414 printf("do not support this bus freq\n"); 415 return -EINVAL; 416 } 417 418 return rk322x_peri_get_clk(priv, clk_id); 419 } 420 421 #ifndef CONFIG_SPL_BUILD 422 static ulong rk322x_vop_get_clk(struct rk322x_clk_priv *priv, ulong clk_id) 423 { 424 struct rk322x_cru *cru = priv->cru; 425 u32 div, con, sel, parent; 426 427 switch (clk_id) { 428 case ACLK_VOP: 429 con = readl(&cru->cru_clksel_con[33]); 430 div = (con & ACLK_VOP_DIV_CON_MASK) >> ACLK_VOP_DIV_CON_SHIFT; 431 parent = priv->gpll_hz; 432 break; 433 case DCLK_VOP: 434 con = readl(&cru->cru_clksel_con[27]); 435 con = (con & DCLK_LCDC_SEL_MASK) >> DCLK_LCDC_SEL_SHIFT; 436 if (con) { 437 sel = readl(&cru->cru_clksel_con[27]); 438 sel = (sel & DCLK_LCDC_PLL_SEL_MASK) >> 439 DCLK_LCDC_PLL_SEL_SHIFT; 440 if (sel) 441 parent = priv->cpll_hz; 442 else 443 parent = priv->gpll_hz; 444 445 con = readl(&cru->cru_clksel_con[27]); 446 div = (con & DCLK_LCDC_DIV_CON_MASK) >> 447 DCLK_LCDC_DIV_CON_SHIFT; 448 } else { 449 parent = priv->cpll_hz; 450 div = 1; 451 } 452 break; 453 default: 454 return -ENOENT; 455 } 456 457 return DIV_TO_RATE(parent, div); 458 } 459 460 static ulong rk322x_vop_set_clk(struct rk322x_clk_priv *priv, 461 ulong clk_id, uint hz) 462 { 463 struct rk322x_cru *cru = priv->cru; 464 int src_clk_div; 465 u32 con, parent; 466 467 switch (clk_id) { 468 case ACLK_VOP: 469 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 470 assert(src_clk_div - 1 < 32); 471 rk_clrsetreg(&cru->cru_clksel_con[33], 472 ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK, 473 ACLK_VOP_PLL_SEL_GPLL << ACLK_VOP_PLL_SEL_SHIFT | 474 (src_clk_div - 1) << ACLK_VOP_DIV_CON_SHIFT); 475 break; 476 case DCLK_VOP: 477 con = readl(&cru->cru_clksel_con[27]); 478 con = (con & DCLK_LCDC_SEL_MASK) >> DCLK_LCDC_SEL_SHIFT; 479 if (con) { 480 parent = readl(&cru->cru_clksel_con[27]); 481 parent = (parent & DCLK_LCDC_PLL_SEL_MASK) >> 482 DCLK_LCDC_PLL_SEL_SHIFT; 483 if (parent) 484 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz); 485 else 486 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 487 488 assert(src_clk_div - 1 < 256); 489 rk_clrsetreg(&cru->cru_clksel_con[27], 490 DCLK_LCDC_DIV_CON_MASK, 491 (src_clk_div - 1) << 492 DCLK_LCDC_DIV_CON_SHIFT); 493 } 494 break; 495 default: 496 printf("do not support this vop freq\n"); 497 return -EINVAL; 498 } 499 500 return rk322x_vop_get_clk(priv, clk_id); 501 } 502 503 static ulong rk322x_crypto_get_clk(struct rk322x_clk_priv *priv, ulong clk_id) 504 { 505 struct rk322x_cru *cru = priv->cru; 506 u32 div, con, parent; 507 508 switch (clk_id) { 509 case SCLK_CRYPTO: 510 con = readl(&cru->cru_clksel_con[24]); 511 div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT; 512 parent = priv->gpll_hz; 513 break; 514 default: 515 return -ENOENT; 516 } 517 518 return DIV_TO_RATE(parent, div); 519 } 520 521 static ulong rk322x_crypto_set_clk(struct rk322x_clk_priv *priv, ulong clk_id, 522 ulong hz) 523 { 524 struct rk322x_cru *cru = priv->cru; 525 int src_clk_div; 526 527 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 528 assert(src_clk_div - 1 <= 31); 529 530 /* 531 * select gpll as crypto clock source and 532 * set up dependent divisors for crypto clocks. 533 */ 534 switch (clk_id) { 535 case SCLK_CRYPTO: 536 rk_clrsetreg(&cru->cru_clksel_con[24], 537 CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK, 538 CRYPTO_PLL_SEL_GPLL << CRYPTO_PLL_SEL_SHIFT | 539 (src_clk_div - 1) << CRYPTO_DIV_SHIFT); 540 break; 541 default: 542 printf("do not support this peri freq\n"); 543 return -EINVAL; 544 } 545 546 return rk322x_crypto_get_clk(priv, clk_id); 547 } 548 #endif 549 550 static ulong rk322x_clk_get_rate(struct clk *clk) 551 { 552 struct rk322x_clk_priv *priv = dev_get_priv(clk->dev); 553 ulong rate; 554 555 switch (clk->id) { 556 case PLL_APLL: 557 case PLL_DPLL: 558 case PLL_CPLL: 559 case PLL_GPLL: 560 rate = rockchip_pll_get_rate(&rk322x_pll_clks[clk->id - 1], 561 priv->cru, clk->id - 1); 562 break; 563 case ARMCLK: 564 rate = rockchip_pll_get_rate(&rk322x_pll_clks[APLL], 565 priv->cru, APLL); 566 break; 567 case HCLK_EMMC: 568 case SCLK_EMMC: 569 case SCLK_EMMC_SAMPLE: 570 case HCLK_SDMMC: 571 case SCLK_SDMMC: 572 case SCLK_SDMMC_SAMPLE: 573 case SCLK_SDIO: 574 case SCLK_SDIO_SAMPLE: 575 rate = rk322x_mmc_get_clk(priv, clk->id); 576 break; 577 case ACLK_CPU: 578 case HCLK_CPU: 579 case PCLK_CPU: 580 case PCLK_I2C0: 581 case PCLK_I2C1: 582 case PCLK_I2C2: 583 case PCLK_I2C3: 584 case PCLK_PWM: 585 rate = rk322x_bus_get_clk(priv, clk->id); 586 break; 587 case ACLK_PERI: 588 case HCLK_PERI: 589 case PCLK_PERI: 590 rate = rk322x_peri_get_clk(priv, clk->id); 591 break; 592 #ifndef CONFIG_SPL_BUILD 593 case DCLK_VOP: 594 case ACLK_VOP: 595 rate = rk322x_vop_get_clk(priv, clk->id); 596 break; 597 case SCLK_CRYPTO: 598 rate = rk322x_crypto_get_clk(priv, clk->id); 599 break; 600 #endif 601 default: 602 return -ENOENT; 603 } 604 605 return rate; 606 } 607 608 static ulong rk322x_clk_set_rate(struct clk *clk, ulong rate) 609 { 610 struct rk322x_clk_priv *priv = dev_get_priv(clk->dev); 611 ulong ret = 0; 612 613 switch (clk->id) { 614 case PLL_APLL: 615 case PLL_DPLL: 616 ret = rockchip_pll_set_rate(&rk322x_pll_clks[clk->id - 1], 617 priv->cru, clk->id - 1, rate); 618 break; 619 case PLL_CPLL: 620 ret = rockchip_pll_set_rate(&rk322x_pll_clks[CPLL], 621 priv->cru, CPLL, rate); 622 priv->cpll_hz = rate; 623 break; 624 case PLL_GPLL: 625 ret = rockchip_pll_set_rate(&rk322x_pll_clks[GPLL], 626 priv->cru, GPLL, rate); 627 priv->gpll_hz = rate; 628 break; 629 case ARMCLK: 630 if (priv->armclk_hz) 631 ret = rk322x_armclk_set_clk(priv, rate); 632 priv->armclk_hz = rate; 633 break; 634 case HCLK_EMMC: 635 case SCLK_EMMC: 636 case SCLK_EMMC_SAMPLE: 637 case HCLK_SDMMC: 638 case SCLK_SDMMC: 639 case SCLK_SDMMC_SAMPLE: 640 case SCLK_SDIO: 641 case SCLK_SDIO_SAMPLE: 642 ret = rk322x_mmc_set_clk(priv, clk->id, rate); 643 break; 644 case SCLK_DDRC: 645 ret = rockchip_pll_set_rate(&rk322x_pll_clks[DPLL], 646 priv->cru, DPLL, rate); 647 break; 648 case ACLK_CPU: 649 case HCLK_CPU: 650 case PCLK_CPU: 651 ret = rk322x_bus_set_clk(priv, clk->id, rate); 652 break; 653 case ACLK_PERI: 654 case HCLK_PERI: 655 case PCLK_PERI: 656 ret = rk322x_peri_set_clk(priv, clk->id, rate); 657 break; 658 #ifndef CONFIG_SPL_BUILD 659 case SCLK_MAC: 660 ret = rk322x_mac_set_clk(priv, rate); 661 break; 662 case DCLK_VOP: 663 case ACLK_VOP: 664 ret = rk322x_vop_set_clk(priv, clk->id, rate); 665 break; 666 case SCLK_CRYPTO: 667 ret = rk322x_crypto_set_clk(priv, clk->id, rate); 668 break; 669 #endif 670 default: 671 return -ENOENT; 672 } 673 674 return ret; 675 } 676 677 #ifndef CONFIG_SPL_BUILD 678 static int rk322x_gmac_set_parent(struct clk *clk, struct clk *parent) 679 { 680 struct rk322x_clk_priv *priv = dev_get_priv(clk->dev); 681 struct rk322x_cru *cru = priv->cru; 682 683 /* 684 * If the requested parent is in the same clock-controller and the id 685 * is SCLK_MAC_SRC ("sclk_gmac_src"), switch to the internal clock. 686 */ 687 if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC_SRC)) { 688 debug("%s: switching RGMII to SCLK_MAC_SRC\n", __func__); 689 rk_clrsetreg(&cru->cru_clksel_con[5], BIT(5), 0); 690 return 0; 691 } 692 693 /* 694 * If the requested parent is in the same clock-controller and the id 695 * is SCLK_MAC_EXTCLK (sclk_mac_extclk), switch to the external clock. 696 */ 697 if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC_EXTCLK)) { 698 debug("%s: switching RGMII to SCLK_MAC_EXTCLK\n", __func__); 699 rk_clrsetreg(&cru->cru_clksel_con[5], BIT(5), BIT(5)); 700 return 0; 701 } 702 703 return -EINVAL; 704 } 705 706 static int rk322x_gmac_extclk_set_parent(struct clk *clk, struct clk *parent) 707 { 708 struct rk322x_clk_priv *priv = dev_get_priv(clk->dev); 709 const char *clock_output_name; 710 struct rk322x_cru *cru = priv->cru; 711 int ret; 712 713 ret = dev_read_string_index(parent->dev, "clock-output-names", 714 parent->id, &clock_output_name); 715 if (ret < 0) 716 return -ENODATA; 717 718 if (!strcmp(clock_output_name, "ext_gmac")) { 719 debug("%s: switching gmac extclk to ext_gmac\n", __func__); 720 rk_clrsetreg(&cru->cru_clksel_con[29], BIT(10), 0); 721 return 0; 722 } else if (!strcmp(clock_output_name, "phy_50m_out")) { 723 debug("%s: switching gmac extclk to phy_50m_out\n", __func__); 724 rk_clrsetreg(&cru->cru_clksel_con[29], BIT(10), BIT(10)); 725 return 0; 726 } 727 728 return -EINVAL; 729 } 730 731 static int rk322x_lcdc_set_parent(struct clk *clk, struct clk *parent) 732 { 733 struct rk322x_clk_priv *priv = dev_get_priv(clk->dev); 734 735 if (parent->id == HDMIPHY) 736 rk_clrsetreg(&priv->cru->cru_clksel_con[27], 737 DCLK_LCDC_SEL_MASK, 738 DCLK_LCDC_SEL_HDMIPHY << DCLK_LCDC_SEL_SHIFT); 739 else if (parent->id == PLL_CPLL) 740 rk_clrsetreg(&priv->cru->cru_clksel_con[27], 741 DCLK_LCDC_SEL_MASK | DCLK_LCDC_PLL_SEL_MASK, 742 (DCLK_LCDC_SEL_PLL << DCLK_LCDC_SEL_SHIFT) | 743 (DCLK_LCDC_PLL_SEL_CPLL << 744 DCLK_LCDC_PLL_SEL_SHIFT)); 745 else 746 rk_clrsetreg(&priv->cru->cru_clksel_con[27], 747 DCLK_LCDC_SEL_MASK | DCLK_LCDC_PLL_SEL_MASK, 748 (DCLK_LCDC_SEL_PLL << DCLK_LCDC_SEL_SHIFT) | 749 (DCLK_LCDC_PLL_SEL_GPLL << 750 DCLK_LCDC_PLL_SEL_SHIFT)); 751 752 return 0; 753 } 754 #endif 755 756 static int rk322x_clk_set_parent(struct clk *clk, struct clk *parent) 757 { 758 switch (clk->id) { 759 #ifndef CONFIG_SPL_BUILD 760 case SCLK_MAC: 761 return rk322x_gmac_set_parent(clk, parent); 762 case SCLK_MAC_EXTCLK: 763 return rk322x_gmac_extclk_set_parent(clk, parent); 764 case DCLK_VOP: 765 return rk322x_lcdc_set_parent(clk, parent); 766 #endif 767 } 768 769 debug("%s: unsupported clk %ld\n", __func__, clk->id); 770 return -ENOENT; 771 } 772 773 #define ROCKCHIP_MMC_DELAY_SEL BIT(10) 774 #define ROCKCHIP_MMC_DEGREE_MASK 0x3 775 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2 776 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 777 778 #define PSECS_PER_SEC 1000000000000LL 779 /* 780 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 781 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 782 */ 783 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 784 785 int rk322x_mmc_get_phase(struct clk *clk) 786 { 787 struct rk322x_clk_priv *priv = dev_get_priv(clk->dev); 788 struct rk322x_cru *cru = priv->cru; 789 u32 raw_value, delay_num; 790 u16 degrees = 0; 791 ulong rate; 792 793 rate = rk322x_clk_get_rate(clk); 794 795 if (rate < 0) 796 return rate; 797 798 if (clk->id == SCLK_EMMC_SAMPLE) 799 raw_value = readl(&cru->cru_emmc_con[1]); 800 else if (clk->id == SCLK_SDMMC_SAMPLE) 801 raw_value = readl(&cru->cru_sdmmc_con[1]); 802 else 803 raw_value = readl(&cru->cru_sdio_con[1]); 804 805 raw_value >>= 1; 806 degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; 807 808 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 809 /* degrees/delaynum * 10000 */ 810 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 811 36 * (rate / 1000000); 812 813 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 814 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 815 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 816 } 817 818 return degrees % 360; 819 } 820 821 int rk322x_mmc_set_phase(struct clk *clk, u32 degrees) 822 { 823 struct rk322x_clk_priv *priv = dev_get_priv(clk->dev); 824 struct rk322x_cru *cru = priv->cru; 825 u8 nineties, remainder, delay_num; 826 u32 raw_value, delay; 827 ulong rate; 828 829 rate = rk322x_clk_get_rate(clk); 830 831 if (rate < 0) 832 return rate; 833 834 nineties = degrees / 90; 835 remainder = (degrees % 90); 836 837 /* 838 * Convert to delay; do a little extra work to make sure we 839 * don't overflow 32-bit / 64-bit numbers. 840 */ 841 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 842 delay *= remainder; 843 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 844 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 845 846 delay_num = (u8)min_t(u32, delay, 255); 847 848 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 849 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 850 raw_value |= nineties; 851 852 raw_value <<= 1; 853 if (clk->id == SCLK_EMMC_SAMPLE) 854 writel(raw_value | 0xffff0000, &cru->cru_emmc_con[1]); 855 else if (clk->id == SCLK_SDMMC_SAMPLE) 856 writel(raw_value | 0xffff0000, &cru->cru_sdmmc_con[1]); 857 else 858 writel(raw_value | 0xffff0000, &cru->cru_sdio_con[1]); 859 860 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 861 degrees, delay_num, raw_value, rk322x_mmc_get_phase(clk)); 862 863 return 0; 864 } 865 866 static int rk322x_clk_get_phase(struct clk *clk) 867 { 868 int ret; 869 870 debug("%s %ld\n", __func__, clk->id); 871 switch (clk->id) { 872 case SCLK_EMMC_SAMPLE: 873 case SCLK_SDMMC_SAMPLE: 874 case SCLK_SDIO_SAMPLE: 875 ret = rk322x_mmc_get_phase(clk); 876 break; 877 default: 878 return -ENOENT; 879 } 880 881 return ret; 882 } 883 884 static int rk322x_clk_set_phase(struct clk *clk, int degrees) 885 { 886 int ret; 887 888 debug("%s %ld\n", __func__, clk->id); 889 switch (clk->id) { 890 case SCLK_EMMC_SAMPLE: 891 case SCLK_SDMMC_SAMPLE: 892 case SCLK_SDIO_SAMPLE: 893 ret = rk322x_mmc_set_phase(clk, degrees); 894 break; 895 default: 896 return -ENOENT; 897 } 898 899 return ret; 900 } 901 902 static struct clk_ops rk322x_clk_ops = { 903 .get_rate = rk322x_clk_get_rate, 904 .set_rate = rk322x_clk_set_rate, 905 .set_parent = rk322x_clk_set_parent, 906 .get_phase = rk322x_clk_get_phase, 907 .set_phase = rk322x_clk_set_phase, 908 }; 909 910 static int rk322x_clk_ofdata_to_platdata(struct udevice *dev) 911 { 912 struct rk322x_clk_priv *priv = dev_get_priv(dev); 913 914 priv->cru = dev_read_addr_ptr(dev); 915 916 return 0; 917 } 918 919 #ifndef CONFIG_TPL_BUILD 920 static void rkclk_init(struct rk322x_clk_priv *priv) 921 { 922 struct rk322x_cru *cru = priv->cru; 923 924 if (rockchip_pll_get_rate(&rk322x_pll_clks[APLL], 925 priv->cru, APLL) != APLL_HZ) 926 rk322x_armclk_set_clk(priv, APLL_HZ); 927 928 priv->gpll_hz = rockchip_pll_get_rate(&rk322x_pll_clks[GPLL], 929 priv->cru, GPLL); 930 priv->cpll_hz = rockchip_pll_get_rate(&rk322x_pll_clks[CPLL], 931 priv->cru, CPLL); 932 933 /* before set pll set child div first */ 934 rk322x_bus_set_clk(priv, ACLK_CPU, ACLK_BUS_HZ / 4); 935 rk322x_peri_set_clk(priv, ACLK_PERI, ACLK_PERI_HZ / 4); 936 rk322x_mmc_set_clk(priv, SCLK_EMMC, 50000000); 937 rk322x_mmc_set_clk(priv, SCLK_SDMMC, 50000000); 938 rk322x_mmc_set_clk(priv, SCLK_SDIO, 50000000); 939 rk_clrsetreg(&cru->cru_clksel_con[2], (0x1 << 14) | 940 (0x1f << 8), (1 << 14) | (0xb << 8)); 941 rk_clrsetreg(&cru->cru_clksel_con[23], (0x1f << 0) | (0x1f << 8), 942 (0x1f << 0) | (5 << 8)); 943 rk_clrsetreg(&cru->cru_clksel_con[33], 944 ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK, 945 ACLK_VOP_PLL_SEL_GPLL << ACLK_VOP_PLL_SEL_SHIFT | 946 3 << ACLK_VOP_DIV_CON_SHIFT); 947 rk_clrsetreg(&cru->cru_clksel_con[22], 0x1f << 0, 5 << 0); 948 rk_clrsetreg(&cru->cru_clksel_con[24], 0x1f << 0, 0xb << 0); 949 rk_clrsetreg(&cru->cru_clksel_con[28], (0x1f << 8) | (0x1f << 0), 950 (5 << 8) | (5 << 0)); 951 rk_clrsetreg(&cru->cru_clksel_con[31], (0x1f << 8) | (0x1f << 0), 952 (5 << 8) | (5 << 0)); 953 rk_clrsetreg(&cru->cru_clksel_con[32], 0x1f << 0, 5 << 0); 954 rk_clrsetreg(&cru->cru_clksel_con[33], (0x1f << 8) | (0x1f << 0), 955 (5 << 8) | (5 << 0)); 956 rk_clrsetreg(&cru->cru_clksel_con[34], (0x1f << 8) | (0x1f << 0), 957 (5 << 8) | (3 << 0)); 958 959 rockchip_pll_set_rate(&rk322x_pll_clks[GPLL], 960 priv->cru, GPLL, GPLL_HZ); 961 priv->gpll_hz = GPLL_HZ; 962 963 rockchip_pll_set_rate(&rk322x_pll_clks[CPLL], 964 priv->cru, CPLL, CPLL_HZ); 965 priv->cpll_hz = CPLL_HZ; 966 967 rk322x_bus_set_clk(priv, ACLK_CPU, ACLK_BUS_HZ); 968 rk322x_bus_set_clk(priv, HCLK_CPU, ACLK_BUS_HZ / 2); 969 rk322x_bus_set_clk(priv, PCLK_CPU, ACLK_BUS_HZ / 2); 970 rk322x_peri_set_clk(priv, ACLK_PERI, ACLK_PERI_HZ); 971 rk322x_peri_set_clk(priv, HCLK_PERI, ACLK_PERI_HZ / 2); 972 rk322x_peri_set_clk(priv, PCLK_PERI, ACLK_PERI_HZ / 2); 973 /*rk322x_mmc_set_clk(priv, SCLK_EMMC, rate);*/ 974 975 /* set usbphy and hdmiphy from phy */ 976 rk_clrsetreg(&cru->cru_misc_con, (0x1 << 13) | 977 (0x1 << 15), (0 << 15) | (0 << 13)); 978 } 979 #endif 980 981 static int rk322x_clk_probe(struct udevice *dev) 982 { 983 #ifndef CONFIG_TPL_BUILD 984 struct rk322x_clk_priv *priv = dev_get_priv(dev); 985 int ret = 0; 986 987 priv->sync_kernel = false; 988 if (!priv->armclk_enter_hz) 989 priv->armclk_enter_hz = 990 rockchip_pll_get_rate(&rk322x_pll_clks[APLL], 991 priv->cru, APLL); 992 rkclk_init(priv); 993 if (!priv->armclk_init_hz) 994 priv->armclk_init_hz = 995 rockchip_pll_get_rate(&rk322x_pll_clks[APLL], 996 priv->cru, APLL); 997 ret = clk_set_defaults(dev); 998 if (ret) 999 debug("%s clk_set_defaults failed %d\n", __func__, ret); 1000 else 1001 priv->sync_kernel = true; 1002 #endif 1003 return 0; 1004 } 1005 1006 static int rk322x_clk_bind(struct udevice *dev) 1007 { 1008 int ret; 1009 struct udevice *sys_child, *sf_child; 1010 struct sysreset_reg *priv; 1011 struct softreset_reg *sf_priv; 1012 1013 /* The reset driver does not have a device node, so bind it here */ 1014 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 1015 &sys_child); 1016 if (ret) { 1017 debug("Warning: No sysreset driver: ret=%d\n", ret); 1018 } else { 1019 priv = malloc(sizeof(struct sysreset_reg)); 1020 priv->glb_srst_fst_value = offsetof(struct rk322x_cru, 1021 cru_glb_srst_fst_value); 1022 priv->glb_srst_snd_value = offsetof(struct rk322x_cru, 1023 cru_glb_srst_snd_value); 1024 sys_child->priv = priv; 1025 } 1026 1027 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 1028 dev_ofnode(dev), &sf_child); 1029 if (ret) { 1030 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 1031 } else { 1032 sf_priv = malloc(sizeof(struct softreset_reg)); 1033 sf_priv->sf_reset_offset = offsetof(struct rk322x_cru, 1034 cru_softrst_con[0]); 1035 sf_priv->sf_reset_num = 9; 1036 sf_child->priv = sf_priv; 1037 } 1038 1039 return 0; 1040 } 1041 1042 static const struct udevice_id rk322x_clk_ids[] = { 1043 { .compatible = "rockchip,rk3228-cru" }, 1044 { } 1045 }; 1046 1047 U_BOOT_DRIVER(rockchip_rk322x_cru) = { 1048 .name = "clk_rk322x", 1049 .id = UCLASS_CLK, 1050 .of_match = rk322x_clk_ids, 1051 .priv_auto_alloc_size = sizeof(struct rk322x_clk_priv), 1052 .ofdata_to_platdata = rk322x_clk_ofdata_to_platdata, 1053 .ops = &rk322x_clk_ops, 1054 .bind = rk322x_clk_bind, 1055 .probe = rk322x_clk_probe, 1056 }; 1057 1058 #ifndef CONFIG_SPL_BUILD 1059 /** 1060 * soc_clk_dump() - Print clock frequencies 1061 * Returns zero on success 1062 * 1063 * Implementation for the clk dump command. 1064 */ 1065 int soc_clk_dump(void) 1066 { 1067 struct udevice *cru_dev; 1068 struct rk322x_clk_priv *priv; 1069 const struct rk322x_clk_info *clk_dump; 1070 struct clk clk; 1071 unsigned long clk_count = ARRAY_SIZE(clks_dump); 1072 unsigned long rate; 1073 int i, ret; 1074 1075 ret = uclass_get_device_by_driver(UCLASS_CLK, 1076 DM_GET_DRIVER(rockchip_rk322x_cru), 1077 &cru_dev); 1078 if (ret) { 1079 printf("%s failed to get cru device\n", __func__); 1080 return ret; 1081 } 1082 1083 priv = dev_get_priv(cru_dev); 1084 printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n", 1085 priv->sync_kernel ? "sync kernel" : "uboot", 1086 priv->armclk_enter_hz / 1000, 1087 priv->armclk_init_hz / 1000, 1088 priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0, 1089 priv->set_armclk_rate ? " KHz" : "N/A"); 1090 for (i = 0; i < clk_count; i++) { 1091 clk_dump = &clks_dump[i]; 1092 if (clk_dump->name) { 1093 clk.id = clk_dump->id; 1094 if (clk_dump->is_cru) 1095 ret = clk_request(cru_dev, &clk); 1096 if (ret < 0) 1097 return ret; 1098 1099 rate = clk_get_rate(&clk); 1100 clk_free(&clk); 1101 if (i == 0) { 1102 if (rate < 0) 1103 printf(" %s %s\n", clk_dump->name, 1104 "unknown"); 1105 else 1106 printf(" %s %lu KHz\n", clk_dump->name, 1107 rate / 1000); 1108 } else { 1109 if (rate < 0) 1110 printf(" %s %s\n", clk_dump->name, 1111 "unknown"); 1112 else 1113 printf(" %s %lu KHz\n", clk_dump->name, 1114 rate / 1000); 1115 } 1116 } 1117 } 1118 1119 return 0; 1120 } 1121 #endif 1122 1123