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_rk3128.h> 15 #include <asm/arch/hardware.h> 16 #include <bitfield.h> 17 #include <dm/lists.h> 18 #include <dt-bindings/clock/rk3128-cru.h> 19 #include <linux/log2.h> 20 21 DECLARE_GLOBAL_DATA_PTR; 22 23 #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1)) 24 25 #ifndef CONFIG_SPL_BUILD 26 #define RK3128_CLK_DUMP(_id, _name, _iscru) \ 27 { \ 28 .id = _id, \ 29 .name = _name, \ 30 .is_cru = _iscru, \ 31 } 32 #endif 33 34 static struct rockchip_pll_rate_table rk3128_pll_rates[] = { 35 /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ 36 #ifndef CONFIG_SPL_BUILD 37 RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), 38 RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0), 39 RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), 40 #endif 41 RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0), 42 RK3036_PLL_RATE(800000000, 1, 200, 6, 1, 1, 0), 43 RK3036_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0), 44 RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0), 45 RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0), 46 RK3036_PLL_RATE(400000000, 1, 100, 6, 1, 1, 0), 47 { /* sentinel */ }, 48 }; 49 50 #define RK3128_CPUCLK_RATE(_rate, _aclk_div, _pclk_div) \ 51 { \ 52 .rate = _rate##U, \ 53 .aclk_div = _aclk_div, \ 54 .pclk_div = _pclk_div, \ 55 } 56 57 static struct rockchip_cpu_rate_table rk3128_cpu_rates[] = { 58 RK3128_CPUCLK_RATE(1200000000, 1, 5), 59 RK3128_CPUCLK_RATE(1008000000, 1, 5), 60 RK3128_CPUCLK_RATE(816000000, 1, 3), 61 RK3128_CPUCLK_RATE(600000000, 1, 3), 62 }; 63 64 #ifndef CONFIG_SPL_BUILD 65 static const struct rk3128_clk_info clks_dump[] = { 66 RK3128_CLK_DUMP(PLL_APLL, "apll", true), 67 RK3128_CLK_DUMP(PLL_DPLL, "dpll", true), 68 RK3128_CLK_DUMP(PLL_CPLL, "cpll", true), 69 RK3128_CLK_DUMP(PLL_GPLL, "gpll", true), 70 RK3128_CLK_DUMP(ARMCLK, "armclk", true), 71 RK3128_CLK_DUMP(ACLK_CPU, "aclk_cpu", true), 72 RK3128_CLK_DUMP(HCLK_CPU, "hclk_cpu", true), 73 RK3128_CLK_DUMP(PCLK_CPU, "pclk_cpu", true), 74 RK3128_CLK_DUMP(ACLK_PERI, "aclk_peri", true), 75 RK3128_CLK_DUMP(HCLK_PERI, "hclk_peri", true), 76 RK3128_CLK_DUMP(PCLK_PERI, "pclk_peri", true), 77 }; 78 #endif 79 80 static struct rockchip_pll_clock rk3128_pll_clks[] = { 81 [APLL] = PLL(pll_rk3036, PLL_APLL, RK2928_PLL_CON(0), 82 RK2928_MODE_CON, 0, 10, 0, rk3128_pll_rates), 83 [DPLL] = PLL(pll_rk3036, PLL_DPLL, RK2928_PLL_CON(4), 84 RK2928_MODE_CON, 4, 10, 0, NULL), 85 [CPLL] = PLL(pll_rk3036, PLL_CPLL, RK2928_PLL_CON(8), 86 RK2928_MODE_CON, 8, 10, 0, rk3128_pll_rates), 87 [GPLL] = PLL(pll_rk3036, PLL_GPLL, RK2928_PLL_CON(12), 88 RK2928_MODE_CON, 12, 10, 0, rk3128_pll_rates), 89 }; 90 91 static ulong rk3128_armclk_set_clk(struct rk3128_clk_priv *priv, ulong hz) 92 { 93 struct rk3128_cru *cru = priv->cru; 94 const struct rockchip_cpu_rate_table *rate; 95 ulong old_rate; 96 97 rate = rockchip_get_cpu_settings(rk3128_cpu_rates, hz); 98 if (!rate) { 99 printf("%s unsupported rate\n", __func__); 100 return -EINVAL; 101 } 102 103 /* 104 * select apll as cpu/core clock pll source and 105 * set up dependent divisors for PERI and ACLK clocks. 106 * core hz : apll = 1:1 107 */ 108 old_rate = rockchip_pll_get_rate(&rk3128_pll_clks[APLL], 109 priv->cru, APLL); 110 if (old_rate > hz) { 111 if (rockchip_pll_set_rate(&rk3128_pll_clks[APLL], 112 priv->cru, APLL, hz)) 113 return -EINVAL; 114 rk_clrsetreg(&cru->cru_clksel_con[0], 115 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK, 116 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 117 0 << CORE_DIV_CON_SHIFT); 118 rk_clrsetreg(&cru->cru_clksel_con[1], 119 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK, 120 rate->aclk_div << CORE_ACLK_DIV_SHIFT | 121 rate->pclk_div << CORE_DBG_DIV_SHIFT); 122 } else if (old_rate < hz) { 123 rk_clrsetreg(&cru->cru_clksel_con[1], 124 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK, 125 rate->aclk_div << CORE_ACLK_DIV_SHIFT | 126 rate->pclk_div << CORE_DBG_DIV_SHIFT); 127 rk_clrsetreg(&cru->cru_clksel_con[0], 128 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK, 129 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 130 0 << CORE_DIV_CON_SHIFT); 131 if (rockchip_pll_set_rate(&rk3128_pll_clks[APLL], 132 priv->cru, APLL, hz)) 133 return -EINVAL; 134 } 135 136 return rockchip_pll_get_rate(&rk3128_pll_clks[APLL], priv->cru, APLL); 137 } 138 139 static ulong rockchip_mmc_get_clk(struct rk3128_clk_priv *priv, 140 int periph) 141 { 142 struct rk3128_cru *cru = priv->cru; 143 uint src_rate; 144 uint div, mux; 145 u32 con; 146 147 switch (periph) { 148 case HCLK_EMMC: 149 case SCLK_EMMC: 150 case SCLK_EMMC_SAMPLE: 151 con = readl(&cru->cru_clksel_con[12]); 152 mux = (con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT; 153 div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT; 154 break; 155 case HCLK_SDMMC: 156 case SCLK_SDMMC: 157 case SCLK_SDMMC_SAMPLE: 158 con = readl(&cru->cru_clksel_con[11]); 159 mux = (con & MMC0_PLL_MASK) >> MMC0_PLL_SHIFT; 160 div = (con & MMC0_DIV_MASK) >> MMC0_DIV_SHIFT; 161 break; 162 case HCLK_SDIO: 163 case SCLK_SDIO: 164 case SCLK_SDIO_SAMPLE: 165 con = readl(&cru->cru_clksel_con[12]); 166 mux = (con & SDIO_PLL_MASK) >> SDIO_PLL_SHIFT; 167 div = (con & SDIO_DIV_MASK) >> SDIO_DIV_SHIFT; 168 break; 169 default: 170 return -EINVAL; 171 } 172 173 src_rate = mux == EMMC_SEL_24M ? OSC_HZ : priv->gpll_hz; 174 return DIV_TO_RATE(src_rate, div); 175 } 176 177 static ulong rockchip_mmc_set_clk(struct rk3128_clk_priv *priv, 178 int periph, uint freq) 179 { 180 struct rk3128_cru *cru = priv->cru; 181 int src_clk_div; 182 int mux; 183 184 /* mmc clock defaulg div 2 internal, need provide double in cru */ 185 src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, freq); 186 187 if (src_clk_div > 128) { 188 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, freq); 189 mux = EMMC_SEL_24M; 190 } else { 191 mux = EMMC_SEL_GPLL; 192 } 193 194 switch (periph) { 195 case HCLK_EMMC: 196 case SCLK_EMMC: 197 rk_clrsetreg(&cru->cru_clksel_con[12], 198 EMMC_PLL_MASK | EMMC_DIV_MASK, 199 mux << EMMC_PLL_SHIFT | 200 (src_clk_div - 1) << EMMC_DIV_SHIFT); 201 break; 202 case HCLK_SDMMC: 203 case SCLK_SDMMC: 204 rk_clrsetreg(&cru->cru_clksel_con[11], 205 MMC0_PLL_MASK | MMC0_DIV_MASK, 206 mux << MMC0_PLL_SHIFT | 207 (src_clk_div - 1) << MMC0_DIV_SHIFT); 208 break; 209 case HCLK_SDIO: 210 case SCLK_SDIO: 211 rk_clrsetreg(&cru->cru_clksel_con[12], 212 SDIO_PLL_MASK | SDIO_DIV_MASK, 213 mux << SDIO_PLL_SHIFT | 214 (src_clk_div - 1) << SDIO_DIV_SHIFT); 215 break; 216 default: 217 return -EINVAL; 218 } 219 220 return rockchip_mmc_get_clk(priv, periph); 221 } 222 223 static ulong rk3128_peri_get_clk(struct rk3128_clk_priv *priv, ulong clk_id) 224 { 225 struct rk3128_cru *cru = priv->cru; 226 u32 div, con, parent; 227 228 switch (clk_id) { 229 case ACLK_PERI: 230 con = readl(&cru->cru_clksel_con[10]); 231 div = (con & ACLK_PERI_DIV_MASK) >> ACLK_PERI_DIV_SHIFT; 232 parent = priv->gpll_hz; 233 break; 234 case PCLK_PERI: 235 case PCLK_I2C0: 236 case PCLK_I2C1: 237 case PCLK_I2C2: 238 case PCLK_I2C3: 239 case PCLK_PWM: 240 con = readl(&cru->cru_clksel_con[10]); 241 div = (con & PCLK_PERI_DIV_MASK) >> PCLK_PERI_DIV_SHIFT; 242 parent = rk3128_peri_get_clk(priv, ACLK_PERI); 243 break; 244 case HCLK_PERI: 245 con = readl(&cru->cru_clksel_con[10]); 246 div = (con & HCLK_PERI_DIV_MASK) >> HCLK_PERI_DIV_SHIFT; 247 parent = rk3128_peri_get_clk(priv, ACLK_PERI); 248 break; 249 default: 250 printf("do not support this peripheral bus\n"); 251 return -EINVAL; 252 } 253 254 return DIV_TO_RATE(parent, div); 255 } 256 257 static ulong rk3128_peri_set_clk(struct rk3128_clk_priv *priv, 258 ulong clk_id, uint hz) 259 { 260 struct rk3128_cru *cru = priv->cru; 261 int src_clk_div; 262 263 switch (clk_id) { 264 case ACLK_PERI: 265 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 266 assert(src_clk_div - 1 < 32); 267 rk_clrsetreg(&cru->cru_clksel_con[10], 268 PERI_PLL_SEL_MASK | ACLK_PERI_DIV_MASK, 269 PERI_PLL_SEL_GPLL << PERI_PLL_SEL_SHIFT | 270 (src_clk_div - 1) << ACLK_PERI_DIV_SHIFT); 271 break; 272 case PCLK_I2C0: 273 case PCLK_I2C1: 274 case PCLK_I2C2: 275 case PCLK_I2C3: 276 case PCLK_PWM: 277 case PCLK_PERI: 278 src_clk_div = DIV_ROUND_UP(rk3128_peri_get_clk(priv, 279 ACLK_PERI), 280 hz); 281 assert(src_clk_div - 1 < 3); 282 rk_clrsetreg(&cru->cru_clksel_con[10], 283 PCLK_PERI_DIV_MASK, 284 (src_clk_div - 1) << PCLK_PERI_DIV_SHIFT); 285 break; 286 case HCLK_PERI: 287 src_clk_div = DIV_ROUND_UP(rk3128_peri_get_clk(priv, 288 ACLK_PERI), 289 hz); 290 assert(src_clk_div - 1 < 7); 291 rk_clrsetreg(&cru->cru_clksel_con[10], 292 HCLK_PERI_DIV_MASK, 293 (src_clk_div - 1) << HCLK_PERI_DIV_SHIFT); 294 break; 295 default: 296 printf("do not support this peripheral bus\n"); 297 return -EINVAL; 298 } 299 300 return rk3128_peri_get_clk(priv, clk_id); 301 } 302 303 static ulong rk3128_bus_get_clk(struct rk3128_clk_priv *priv, ulong clk_id) 304 { 305 struct rk3128_cru *cru = priv->cru; 306 u32 div, con, parent; 307 308 switch (clk_id) { 309 case ACLK_CPU: 310 con = readl(&cru->cru_clksel_con[0]); 311 div = (con & ACLK_BUS_DIV_MASK) >> ACLK_BUS_DIV_SHIFT; 312 parent = priv->gpll_hz; 313 break; 314 case PCLK_CPU: 315 con = readl(&cru->cru_clksel_con[1]); 316 div = (con & PCLK_BUS_DIV_MASK) >> PCLK_BUS_DIV_SHIFT; 317 parent = rk3128_bus_get_clk(priv, ACLK_CPU); 318 break; 319 case HCLK_CPU: 320 con = readl(&cru->cru_clksel_con[1]); 321 div = (con & HCLK_BUS_DIV_MASK) >> HCLK_BUS_DIV_SHIFT; 322 parent = rk3128_bus_get_clk(priv, ACLK_CPU); 323 break; 324 default: 325 printf("do not support this peripheral bus\n"); 326 return -EINVAL; 327 } 328 329 return DIV_TO_RATE(parent, div); 330 } 331 332 static ulong rk3128_bus_set_clk(struct rk3128_clk_priv *priv, 333 ulong clk_id, uint hz) 334 { 335 struct rk3128_cru *cru = priv->cru; 336 int src_clk_div; 337 338 switch (clk_id) { 339 case ACLK_CPU: 340 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 341 assert(src_clk_div - 1 < 32); 342 rk_clrsetreg(&cru->cru_clksel_con[0], 343 BUS_PLL_SEL_MASK | ACLK_BUS_DIV_MASK, 344 BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT | 345 (src_clk_div - 1) << ACLK_BUS_DIV_SHIFT); 346 break; 347 case PCLK_CPU: 348 src_clk_div = DIV_ROUND_UP(rk3128_bus_get_clk(priv, 349 ACLK_CPU), 350 hz); 351 assert(src_clk_div - 1 < 3); 352 rk_clrsetreg(&cru->cru_clksel_con[1], 353 PCLK_BUS_DIV_MASK, 354 (src_clk_div - 1) << PCLK_BUS_DIV_SHIFT); 355 break; 356 case HCLK_CPU: 357 src_clk_div = DIV_ROUND_UP(rk3128_bus_get_clk(priv, 358 ACLK_CPU), 359 hz); 360 assert(src_clk_div - 1 < 7); 361 rk_clrsetreg(&cru->cru_clksel_con[1], 362 HCLK_BUS_DIV_MASK, 363 (src_clk_div - 1) << HCLK_BUS_DIV_SHIFT); 364 break; 365 default: 366 printf("do not support this peripheral bus\n"); 367 return -EINVAL; 368 } 369 370 return rk3128_bus_get_clk(priv, clk_id); 371 } 372 373 #ifndef CONFIG_SPL_BUILD 374 static ulong rk3128_saradc_get_clk(struct rk3128_clk_priv *priv) 375 { 376 struct rk3128_cru *cru = priv->cru; 377 u32 div, val; 378 379 val = readl(&cru->cru_clksel_con[24]); 380 div = bitfield_extract(val, SARADC_DIV_CON_SHIFT, 381 SARADC_DIV_CON_WIDTH); 382 383 return DIV_TO_RATE(OSC_HZ, div); 384 } 385 386 static ulong rk3128_saradc_set_clk(struct rk3128_clk_priv *priv, uint hz) 387 { 388 struct rk3128_cru *cru = priv->cru; 389 int src_clk_div; 390 391 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1; 392 assert(src_clk_div < 128); 393 394 rk_clrsetreg(&cru->cru_clksel_con[24], 395 SARADC_DIV_CON_MASK, 396 src_clk_div << SARADC_DIV_CON_SHIFT); 397 398 return rk3128_saradc_get_clk(priv); 399 } 400 401 #define RK3128_LCDC_PLL_LIMIT 600000000 402 403 static ulong rk3128_vop_set_clk(struct rk3128_clk_priv *priv, 404 ulong clk_id, uint hz) 405 { 406 struct rk3128_cru *cru = priv->cru; 407 int src_clk_div; 408 409 src_clk_div = GPLL_HZ / hz; 410 assert(src_clk_div - 1 < 31); 411 412 switch (clk_id) { 413 case ACLK_LCDC0: 414 case ACLK_VIO0: 415 rk_clrsetreg(&cru->cru_clksel_con[31], 416 VIO0_PLL_MASK | VIO0_DIV_MASK, 417 VIO0_SEL_GPLL << VIO0_PLL_SHIFT | 418 (src_clk_div - 1) << VIO0_DIV_SHIFT); 419 break; 420 case ACLK_VIO1: 421 rk_clrsetreg(&cru->cru_clksel_con[31], 422 VIO1_PLL_MASK | VIO1_DIV_MASK, 423 VIO1_SEL_GPLL << VIO1_PLL_SHIFT | 424 (src_clk_div - 1) << VIO1_DIV_SHIFT); 425 break; 426 case DCLK_VOP: 427 src_clk_div = DIV_ROUND_UP(RK3128_LCDC_PLL_LIMIT, hz); 428 rockchip_pll_set_rate(&rk3128_pll_clks[CPLL], 429 priv->cru, CPLL, src_clk_div * hz); 430 rk_clrsetreg(&cru->cru_clksel_con[27], 431 DCLK_VOP_SEL_MASK | DCLK_VOP_DIV_CON_MASK, 432 DCLK_VOP_PLL_SEL_CPLL << DCLK_VOP_SEL_SHIFT | 433 (src_clk_div - 1) << DCLK_VOP_DIV_CON_SHIFT); 434 break; 435 default: 436 printf("do not support this vop freq\n"); 437 return -EINVAL; 438 } 439 440 return hz; 441 } 442 443 static ulong rk3128_vop_get_rate(struct rk3128_clk_priv *priv, ulong clk_id) 444 { 445 struct rk3128_cru *cru = priv->cru; 446 u32 div, con, parent; 447 448 switch (clk_id) { 449 case ACLK_LCDC0: 450 case ACLK_VIO0: 451 con = readl(&cru->cru_clksel_con[31]); 452 div = con & 0x1f; 453 parent = GPLL_HZ; 454 break; 455 case ACLK_VIO1: 456 con = readl(&cru->cru_clksel_con[31]); 457 div = (con >> 8) & 0x1f; 458 parent = GPLL_HZ; 459 break; 460 case DCLK_VOP: 461 con = readl(&cru->cru_clksel_con[27]); 462 div = (con & DCLK_VOP_DIV_CON_MASK) >> DCLK_VOP_DIV_CON_SHIFT; 463 parent = rockchip_pll_get_rate(&rk3128_pll_clks[CPLL], 464 priv->cru, CPLL); 465 break; 466 default: 467 return -ENOENT; 468 } 469 return DIV_TO_RATE(parent, div); 470 } 471 #endif 472 473 static ulong rk3128_clk_get_rate(struct clk *clk) 474 { 475 struct rk3128_clk_priv *priv = dev_get_priv(clk->dev); 476 ulong rate = 0; 477 478 switch (clk->id) { 479 case PLL_APLL: 480 case PLL_DPLL: 481 case PLL_CPLL: 482 case PLL_GPLL: 483 rate = rockchip_pll_get_rate(&rk3128_pll_clks[clk->id - 1], 484 priv->cru, clk->id - 1); 485 break; 486 case ARMCLK: 487 rate = rockchip_pll_get_rate(&rk3128_pll_clks[APLL], 488 priv->cru, APLL); 489 break; 490 case HCLK_EMMC: 491 case SCLK_EMMC: 492 case HCLK_SDMMC: 493 case SCLK_SDMMC: 494 case HCLK_SDIO: 495 case SCLK_SDIO: 496 rate = rockchip_mmc_get_clk(priv, clk->id); 497 break; 498 case ACLK_PERI: 499 case HCLK_PERI: 500 case PCLK_PERI: 501 case PCLK_I2C0: 502 case PCLK_I2C1: 503 case PCLK_I2C2: 504 case PCLK_I2C3: 505 case PCLK_PWM: 506 rate = rk3128_peri_get_clk(priv, clk->id); 507 break; 508 case ACLK_CPU: 509 case HCLK_CPU: 510 case PCLK_CPU: 511 rate = rk3128_bus_get_clk(priv, clk->id); 512 break; 513 #ifndef CONFIG_SPL_BUILD 514 case SCLK_SARADC: 515 rate = rk3128_saradc_get_clk(priv); 516 break; 517 case DCLK_VOP: 518 case ACLK_VIO0: 519 case ACLK_VIO1: 520 case ACLK_LCDC0: 521 rate = rk3128_vop_get_rate(priv, clk->id); 522 break; 523 #endif 524 default: 525 return -ENOENT; 526 } 527 return rate; 528 } 529 530 static ulong rk3128_clk_set_rate(struct clk *clk, ulong rate) 531 { 532 struct rk3128_clk_priv *priv = dev_get_priv(clk->dev); 533 ulong ret = 0; 534 535 switch (clk->id) { 536 case PLL_APLL: 537 case PLL_DPLL: 538 case PLL_CPLL: 539 ret = rockchip_pll_set_rate(&rk3128_pll_clks[clk->id - 1], 540 priv->cru, clk->id - 1, rate); 541 case PLL_GPLL: 542 ret = rockchip_pll_set_rate(&rk3128_pll_clks[GPLL], 543 priv->cru, GPLL, rate); 544 priv->gpll_hz = rate; 545 break; 546 case ARMCLK: 547 if (priv->armclk_hz) 548 ret = rk3128_armclk_set_clk(priv, rate); 549 priv->armclk_hz = rate; 550 break; 551 case HCLK_EMMC: 552 case SCLK_EMMC: 553 case SCLK_EMMC_SAMPLE: 554 case HCLK_SDMMC: 555 case SCLK_SDMMC: 556 case SCLK_SDMMC_SAMPLE: 557 case HCLK_SDIO: 558 case SCLK_SDIO: 559 case SCLK_SDIO_SAMPLE: 560 ret = rockchip_mmc_set_clk(priv, clk->id, rate); 561 break; 562 case ACLK_PERI: 563 case PCLK_PERI: 564 case HCLK_PERI: 565 case PCLK_I2C0: 566 case PCLK_I2C1: 567 case PCLK_I2C2: 568 case PCLK_I2C3: 569 case PCLK_PWM: 570 ret = rk3128_peri_set_clk(priv, clk->id, rate); 571 break; 572 case ACLK_CPU: 573 case HCLK_CPU: 574 case PCLK_CPU: 575 ret = rk3128_bus_set_clk(priv, clk->id, rate); 576 break; 577 #ifndef CONFIG_SPL_BUILD 578 case SCLK_SARADC: 579 ret = rk3128_saradc_set_clk(priv, rate); 580 break; 581 case DCLK_VOP: 582 case ACLK_VIO0: 583 case ACLK_VIO1: 584 case ACLK_LCDC0: 585 ret = rk3128_vop_set_clk(priv, clk->id, rate); 586 break; 587 #endif 588 default: 589 return -ENOENT; 590 } 591 return ret; 592 } 593 594 #define ROCKCHIP_MMC_DELAY_SEL BIT(10) 595 #define ROCKCHIP_MMC_DEGREE_MASK 0x3 596 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2 597 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 598 599 #define PSECS_PER_SEC 1000000000000LL 600 /* 601 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 602 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 603 */ 604 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 605 606 int rk3128_mmc_get_phase(struct clk *clk) 607 { 608 struct rk3128_clk_priv *priv = dev_get_priv(clk->dev); 609 struct rk3128_cru *cru = priv->cru; 610 u32 raw_value, delay_num; 611 u16 degrees = 0; 612 ulong rate; 613 614 rate = rk3128_clk_get_rate(clk); 615 616 if (rate < 0) 617 return rate; 618 619 if (clk->id == SCLK_EMMC_SAMPLE) 620 raw_value = readl(&cru->cru_emmc_con[1]); 621 else if (clk->id == SCLK_SDMMC_SAMPLE) 622 raw_value = readl(&cru->cru_sdmmc_con[1]); 623 else 624 raw_value = readl(&cru->cru_sdio_con[1]); 625 626 raw_value >>= 1; 627 degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; 628 629 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 630 /* degrees/delaynum * 10000 */ 631 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 632 36 * (rate / 1000000); 633 634 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 635 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 636 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 637 } 638 639 return degrees % 360; 640 } 641 642 int rk3128_mmc_set_phase(struct clk *clk, u32 degrees) 643 { 644 struct rk3128_clk_priv *priv = dev_get_priv(clk->dev); 645 struct rk3128_cru *cru = priv->cru; 646 u8 nineties, remainder, delay_num; 647 u32 raw_value, delay; 648 ulong rate; 649 650 rate = rk3128_clk_get_rate(clk); 651 652 if (rate < 0) 653 return rate; 654 655 nineties = degrees / 90; 656 remainder = (degrees % 90); 657 658 /* 659 * Convert to delay; do a little extra work to make sure we 660 * don't overflow 32-bit / 64-bit numbers. 661 */ 662 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 663 delay *= remainder; 664 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 665 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 666 667 delay_num = (u8)min_t(u32, delay, 255); 668 669 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 670 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 671 raw_value |= nineties; 672 673 raw_value <<= 1; 674 if (clk->id == SCLK_EMMC_SAMPLE) 675 writel(raw_value | 0xffff0000, &cru->cru_emmc_con[1]); 676 else if (clk->id == SCLK_SDMMC_SAMPLE) 677 writel(raw_value | 0xffff0000, &cru->cru_sdmmc_con[1]); 678 else 679 writel(raw_value | 0xffff0000, &cru->cru_sdio_con[1]); 680 681 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 682 degrees, delay_num, raw_value, rk3128_mmc_get_phase(clk)); 683 684 return 0; 685 } 686 687 static int rk3128_clk_get_phase(struct clk *clk) 688 { 689 int ret; 690 691 debug("%s %ld\n", __func__, clk->id); 692 switch (clk->id) { 693 case SCLK_EMMC_SAMPLE: 694 case SCLK_SDMMC_SAMPLE: 695 case SCLK_SDIO_SAMPLE: 696 ret = rk3128_mmc_get_phase(clk); 697 break; 698 default: 699 return -ENOENT; 700 } 701 702 return ret; 703 } 704 705 static int rk3128_clk_set_phase(struct clk *clk, int degrees) 706 { 707 int ret; 708 709 debug("%s %ld\n", __func__, clk->id); 710 switch (clk->id) { 711 case SCLK_EMMC_SAMPLE: 712 case SCLK_SDMMC_SAMPLE: 713 case SCLK_SDIO_SAMPLE: 714 ret = rk3128_mmc_set_phase(clk, degrees); 715 break; 716 default: 717 return -ENOENT; 718 } 719 720 return ret; 721 } 722 723 static struct clk_ops rk3128_clk_ops = { 724 .get_rate = rk3128_clk_get_rate, 725 .set_rate = rk3128_clk_set_rate, 726 .get_phase = rk3128_clk_get_phase, 727 .set_phase = rk3128_clk_set_phase, 728 }; 729 730 static int rk3128_clk_ofdata_to_platdata(struct udevice *dev) 731 { 732 struct rk3128_clk_priv *priv = dev_get_priv(dev); 733 734 priv->cru = dev_read_addr_ptr(dev); 735 736 return 0; 737 } 738 739 static void rkclk_init(struct rk3128_clk_priv *priv) 740 { 741 if (rockchip_pll_get_rate(&rk3128_pll_clks[APLL], 742 priv->cru, APLL) != APLL_HZ) 743 rk3128_armclk_set_clk(priv, APLL_HZ); 744 745 priv->gpll_hz = rockchip_pll_get_rate(&rk3128_pll_clks[GPLL], 746 priv->cru, GPLL); 747 rk3128_bus_set_clk(priv, ACLK_CPU, ACLK_BUS_HZ / 2); 748 rk3128_peri_set_clk(priv, ACLK_PERI, ACLK_PERI_HZ / 2); 749 rockchip_pll_set_rate(&rk3128_pll_clks[GPLL], 750 priv->cru, GPLL, GPLL_HZ); 751 priv->gpll_hz = GPLL_HZ; 752 rk_clrsetreg(&priv->cru->cru_clksel_con[2], 753 NANDC_PLL_SEL_MASK | NANDC_CLK_DIV_MASK, 754 NANDC_PLL_SEL_GPLL << NANDC_PLL_SEL_SHIFT | 755 3 << NANDC_CLK_DIV_SHIFT); 756 rk_clrsetreg(&priv->cru->cru_clksel_con[11], 757 SFC_PLL_SEL_MASK | SFC_CLK_DIV_MASK, 758 SFC_PLL_SEL_GPLL << SFC_PLL_SEL_SHIFT | 759 9 << SFC_CLK_DIV_SHIFT); 760 761 rk3128_bus_set_clk(priv, ACLK_CPU, ACLK_BUS_HZ); 762 rk3128_bus_set_clk(priv, HCLK_CPU, ACLK_BUS_HZ / 2); 763 rk3128_bus_set_clk(priv, PCLK_CPU, ACLK_BUS_HZ / 2); 764 rk3128_peri_set_clk(priv, ACLK_PERI, ACLK_PERI_HZ); 765 rk3128_peri_set_clk(priv, HCLK_PERI, ACLK_PERI_HZ / 2); 766 rk3128_peri_set_clk(priv, PCLK_PERI, ACLK_PERI_HZ / 2); 767 768 rockchip_pll_set_rate(&rk3128_pll_clks[CPLL], 769 priv->cru, CPLL, CPLL_HZ); 770 } 771 772 static int rk3128_clk_probe(struct udevice *dev) 773 { 774 struct rk3128_clk_priv *priv = dev_get_priv(dev); 775 776 priv->sync_kernel = false; 777 if (!priv->armclk_enter_hz) 778 priv->armclk_enter_hz = 779 rockchip_pll_get_rate(&rk3128_pll_clks[APLL], 780 priv->cru, APLL); 781 rkclk_init(priv); 782 if (!priv->armclk_init_hz) 783 priv->armclk_init_hz = 784 rockchip_pll_get_rate(&rk3128_pll_clks[APLL], 785 priv->cru, APLL); 786 787 return 0; 788 } 789 790 static int rk3128_clk_bind(struct udevice *dev) 791 { 792 int ret; 793 struct udevice *sys_child, *sf_child; 794 struct sysreset_reg *priv; 795 struct softreset_reg *sf_priv; 796 797 /* The reset driver does not have a device node, so bind it here */ 798 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 799 &sys_child); 800 if (ret) { 801 debug("Warning: No sysreset driver: ret=%d\n", ret); 802 } else { 803 priv = malloc(sizeof(struct sysreset_reg)); 804 priv->glb_srst_fst_value = offsetof(struct rk3128_cru, 805 cru_glb_srst_fst_value); 806 priv->glb_srst_snd_value = offsetof(struct rk3128_cru, 807 cru_glb_srst_snd_value); 808 sys_child->priv = priv; 809 } 810 811 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 812 dev_ofnode(dev), &sf_child); 813 if (ret) { 814 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 815 } else { 816 sf_priv = malloc(sizeof(struct softreset_reg)); 817 sf_priv->sf_reset_offset = offsetof(struct rk3128_cru, 818 cru_softrst_con[0]); 819 sf_priv->sf_reset_num = 9; 820 sf_child->priv = sf_priv; 821 } 822 823 return 0; 824 } 825 826 static const struct udevice_id rk3128_clk_ids[] = { 827 { .compatible = "rockchip,rk3128-cru" }, 828 { .compatible = "rockchip,rk3126-cru" }, 829 { } 830 }; 831 832 U_BOOT_DRIVER(rockchip_rk3128_cru) = { 833 .name = "clk_rk3128", 834 .id = UCLASS_CLK, 835 .of_match = rk3128_clk_ids, 836 .priv_auto_alloc_size = sizeof(struct rk3128_clk_priv), 837 .ofdata_to_platdata = rk3128_clk_ofdata_to_platdata, 838 .ops = &rk3128_clk_ops, 839 .bind = rk3128_clk_bind, 840 .probe = rk3128_clk_probe, 841 }; 842 843 #ifndef CONFIG_SPL_BUILD 844 /** 845 * soc_clk_dump() - Print clock frequencies 846 * Returns zero on success 847 * 848 * Implementation for the clk dump command. 849 */ 850 int soc_clk_dump(void) 851 { 852 struct udevice *cru_dev; 853 struct rk3128_clk_priv *priv; 854 const struct rk3128_clk_info *clk_dump; 855 struct clk clk; 856 unsigned long clk_count = ARRAY_SIZE(clks_dump); 857 unsigned long rate; 858 int i, ret; 859 860 ret = uclass_get_device_by_driver(UCLASS_CLK, 861 DM_GET_DRIVER(rockchip_rk3128_cru), 862 &cru_dev); 863 if (ret) { 864 printf("%s failed to get cru device\n", __func__); 865 return ret; 866 } 867 868 priv = dev_get_priv(cru_dev); 869 printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n", 870 priv->sync_kernel ? "sync kernel" : "uboot", 871 priv->armclk_enter_hz / 1000, 872 priv->armclk_init_hz / 1000, 873 priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0, 874 priv->set_armclk_rate ? " KHz" : "N/A"); 875 for (i = 0; i < clk_count; i++) { 876 clk_dump = &clks_dump[i]; 877 if (clk_dump->name) { 878 clk.id = clk_dump->id; 879 if (clk_dump->is_cru) 880 ret = clk_request(cru_dev, &clk); 881 if (ret < 0) 882 return ret; 883 884 rate = clk_get_rate(&clk); 885 clk_free(&clk); 886 if (i == 0) { 887 if (rate < 0) 888 printf(" %s %s\n", clk_dump->name, 889 "unknown"); 890 else 891 printf(" %s %lu KHz\n", clk_dump->name, 892 rate / 1000); 893 } else { 894 if (rate < 0) 895 printf(" %s %s\n", clk_dump->name, 896 "unknown"); 897 else 898 printf(" %s %lu KHz\n", clk_dump->name, 899 rate / 1000); 900 } 901 } 902 } 903 904 return 0; 905 } 906 #endif 907 908