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; 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 ret = rk3128_armclk_set_clk(priv, rate); 548 break; 549 case HCLK_EMMC: 550 case SCLK_EMMC: 551 case SCLK_EMMC_SAMPLE: 552 case HCLK_SDMMC: 553 case SCLK_SDMMC: 554 case SCLK_SDMMC_SAMPLE: 555 case HCLK_SDIO: 556 case SCLK_SDIO: 557 case SCLK_SDIO_SAMPLE: 558 ret = rockchip_mmc_set_clk(priv, clk->id, rate); 559 break; 560 case ACLK_PERI: 561 case PCLK_PERI: 562 case HCLK_PERI: 563 case PCLK_I2C0: 564 case PCLK_I2C1: 565 case PCLK_I2C2: 566 case PCLK_I2C3: 567 case PCLK_PWM: 568 ret = rk3128_peri_set_clk(priv, clk->id, rate); 569 break; 570 case ACLK_CPU: 571 case HCLK_CPU: 572 case PCLK_CPU: 573 ret = rk3128_bus_set_clk(priv, clk->id, rate); 574 break; 575 #ifndef CONFIG_SPL_BUILD 576 case SCLK_SARADC: 577 ret = rk3128_saradc_set_clk(priv, rate); 578 break; 579 case DCLK_VOP: 580 case ACLK_VIO0: 581 case ACLK_VIO1: 582 case ACLK_LCDC0: 583 ret = rk3128_vop_set_clk(priv, clk->id, rate); 584 break; 585 #endif 586 default: 587 return -ENOENT; 588 } 589 return ret; 590 } 591 592 #define ROCKCHIP_MMC_DELAY_SEL BIT(10) 593 #define ROCKCHIP_MMC_DEGREE_MASK 0x3 594 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2 595 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 596 597 #define PSECS_PER_SEC 1000000000000LL 598 /* 599 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 600 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 601 */ 602 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 603 604 int rk3128_mmc_get_phase(struct clk *clk) 605 { 606 struct rk3128_clk_priv *priv = dev_get_priv(clk->dev); 607 struct rk3128_cru *cru = priv->cru; 608 u32 raw_value, delay_num; 609 u16 degrees = 0; 610 ulong rate; 611 612 rate = rk3128_clk_get_rate(clk); 613 614 if (rate < 0) 615 return rate; 616 617 if (clk->id == SCLK_EMMC_SAMPLE) 618 raw_value = readl(&cru->cru_emmc_con[1]); 619 else if (clk->id == SCLK_SDMMC_SAMPLE) 620 raw_value = readl(&cru->cru_sdmmc_con[1]); 621 else 622 raw_value = readl(&cru->cru_sdio_con[1]); 623 624 raw_value >>= 1; 625 degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; 626 627 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 628 /* degrees/delaynum * 10000 */ 629 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 630 36 * (rate / 1000000); 631 632 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 633 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 634 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 635 } 636 637 return degrees % 360; 638 } 639 640 int rk3128_mmc_set_phase(struct clk *clk, u32 degrees) 641 { 642 struct rk3128_clk_priv *priv = dev_get_priv(clk->dev); 643 struct rk3128_cru *cru = priv->cru; 644 u8 nineties, remainder, delay_num; 645 u32 raw_value, delay; 646 ulong rate; 647 648 rate = rk3128_clk_get_rate(clk); 649 650 if (rate < 0) 651 return rate; 652 653 nineties = degrees / 90; 654 remainder = (degrees % 90); 655 656 /* 657 * Convert to delay; do a little extra work to make sure we 658 * don't overflow 32-bit / 64-bit numbers. 659 */ 660 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 661 delay *= remainder; 662 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 663 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 664 665 delay_num = (u8)min_t(u32, delay, 255); 666 667 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 668 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 669 raw_value |= nineties; 670 671 raw_value <<= 1; 672 if (clk->id == SCLK_EMMC_SAMPLE) 673 writel(raw_value | 0xffff0000, &cru->cru_emmc_con[1]); 674 else if (clk->id == SCLK_SDMMC_SAMPLE) 675 writel(raw_value | 0xffff0000, &cru->cru_sdmmc_con[1]); 676 else 677 writel(raw_value | 0xffff0000, &cru->cru_sdio_con[1]); 678 679 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 680 degrees, delay_num, raw_value, rk3128_mmc_get_phase(clk)); 681 682 return 0; 683 } 684 685 static int rk3128_clk_get_phase(struct clk *clk) 686 { 687 int ret; 688 689 debug("%s %ld\n", __func__, clk->id); 690 switch (clk->id) { 691 case SCLK_EMMC_SAMPLE: 692 case SCLK_SDMMC_SAMPLE: 693 case SCLK_SDIO_SAMPLE: 694 ret = rk3128_mmc_get_phase(clk); 695 break; 696 default: 697 return -ENOENT; 698 } 699 700 return ret; 701 } 702 703 static int rk3128_clk_set_phase(struct clk *clk, int degrees) 704 { 705 int ret; 706 707 debug("%s %ld\n", __func__, clk->id); 708 switch (clk->id) { 709 case SCLK_EMMC_SAMPLE: 710 case SCLK_SDMMC_SAMPLE: 711 case SCLK_SDIO_SAMPLE: 712 ret = rk3128_mmc_set_phase(clk, degrees); 713 break; 714 default: 715 return -ENOENT; 716 } 717 718 return ret; 719 } 720 721 static struct clk_ops rk3128_clk_ops = { 722 .get_rate = rk3128_clk_get_rate, 723 .set_rate = rk3128_clk_set_rate, 724 .get_phase = rk3128_clk_get_phase, 725 .set_phase = rk3128_clk_set_phase, 726 }; 727 728 static int rk3128_clk_ofdata_to_platdata(struct udevice *dev) 729 { 730 struct rk3128_clk_priv *priv = dev_get_priv(dev); 731 732 priv->cru = dev_read_addr_ptr(dev); 733 734 return 0; 735 } 736 737 static void rkclk_init(struct rk3128_clk_priv *priv) 738 { 739 if (rockchip_pll_get_rate(&rk3128_pll_clks[APLL], 740 priv->cru, APLL) != APLL_HZ) 741 rk3128_armclk_set_clk(priv, APLL_HZ); 742 743 priv->gpll_hz = rockchip_pll_get_rate(&rk3128_pll_clks[GPLL], 744 priv->cru, GPLL); 745 rk3128_bus_set_clk(priv, ACLK_CPU, ACLK_BUS_HZ / 2); 746 rk3128_peri_set_clk(priv, ACLK_PERI, ACLK_PERI_HZ / 2); 747 rockchip_pll_set_rate(&rk3128_pll_clks[GPLL], 748 priv->cru, GPLL, GPLL_HZ); 749 priv->gpll_hz = GPLL_HZ; 750 rk_clrsetreg(&priv->cru->cru_clksel_con[2], 751 NANDC_PLL_SEL_MASK | NANDC_CLK_DIV_MASK, 752 NANDC_PLL_SEL_GPLL << NANDC_PLL_SEL_SHIFT | 753 3 << NANDC_CLK_DIV_SHIFT); 754 rk3128_bus_set_clk(priv, ACLK_CPU, ACLK_BUS_HZ); 755 rk3128_bus_set_clk(priv, HCLK_CPU, ACLK_BUS_HZ / 2); 756 rk3128_bus_set_clk(priv, PCLK_CPU, ACLK_BUS_HZ / 2); 757 rk3128_peri_set_clk(priv, ACLK_PERI, ACLK_PERI_HZ); 758 rk3128_peri_set_clk(priv, HCLK_PERI, ACLK_PERI_HZ / 2); 759 rk3128_peri_set_clk(priv, PCLK_PERI, ACLK_PERI_HZ / 2); 760 761 rockchip_pll_set_rate(&rk3128_pll_clks[CPLL], 762 priv->cru, CPLL, CPLL_HZ); 763 } 764 765 static int rk3128_clk_probe(struct udevice *dev) 766 { 767 struct rk3128_clk_priv *priv = dev_get_priv(dev); 768 769 rkclk_init(priv); 770 771 return 0; 772 } 773 774 static int rk3128_clk_bind(struct udevice *dev) 775 { 776 int ret; 777 struct udevice *sys_child, *sf_child; 778 struct sysreset_reg *priv; 779 struct softreset_reg *sf_priv; 780 781 /* The reset driver does not have a device node, so bind it here */ 782 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 783 &sys_child); 784 if (ret) { 785 debug("Warning: No sysreset driver: ret=%d\n", ret); 786 } else { 787 priv = malloc(sizeof(struct sysreset_reg)); 788 priv->glb_srst_fst_value = offsetof(struct rk3128_cru, 789 cru_glb_srst_fst_value); 790 priv->glb_srst_snd_value = offsetof(struct rk3128_cru, 791 cru_glb_srst_snd_value); 792 sys_child->priv = priv; 793 } 794 795 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 796 dev_ofnode(dev), &sf_child); 797 if (ret) { 798 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 799 } else { 800 sf_priv = malloc(sizeof(struct softreset_reg)); 801 sf_priv->sf_reset_offset = offsetof(struct rk3128_cru, 802 cru_softrst_con[0]); 803 sf_priv->sf_reset_num = 9; 804 sf_child->priv = sf_priv; 805 } 806 807 return 0; 808 } 809 810 static const struct udevice_id rk3128_clk_ids[] = { 811 { .compatible = "rockchip,rk3128-cru" }, 812 { .compatible = "rockchip,rk3126-cru" }, 813 { } 814 }; 815 816 U_BOOT_DRIVER(rockchip_rk3128_cru) = { 817 .name = "clk_rk3128", 818 .id = UCLASS_CLK, 819 .of_match = rk3128_clk_ids, 820 .priv_auto_alloc_size = sizeof(struct rk3128_clk_priv), 821 .ofdata_to_platdata = rk3128_clk_ofdata_to_platdata, 822 .ops = &rk3128_clk_ops, 823 .bind = rk3128_clk_bind, 824 .probe = rk3128_clk_probe, 825 }; 826 827 #ifndef CONFIG_SPL_BUILD 828 /** 829 * soc_clk_dump() - Print clock frequencies 830 * Returns zero on success 831 * 832 * Implementation for the clk dump command. 833 */ 834 int soc_clk_dump(void) 835 { 836 struct udevice *cru_dev; 837 const struct rk3128_clk_info *clk_dump; 838 struct clk clk; 839 unsigned long clk_count = ARRAY_SIZE(clks_dump); 840 unsigned long rate; 841 int i, ret; 842 843 ret = uclass_get_device_by_driver(UCLASS_CLK, 844 DM_GET_DRIVER(rockchip_rk3128_cru), 845 &cru_dev); 846 if (ret) { 847 printf("%s failed to get cru device\n", __func__); 848 return ret; 849 } 850 851 printf("CLK:"); 852 for (i = 0; i < clk_count; i++) { 853 clk_dump = &clks_dump[i]; 854 if (clk_dump->name) { 855 clk.id = clk_dump->id; 856 if (clk_dump->is_cru) 857 ret = clk_request(cru_dev, &clk); 858 if (ret < 0) 859 return ret; 860 861 rate = clk_get_rate(&clk); 862 clk_free(&clk); 863 if (i == 0) { 864 if (rate < 0) 865 printf("%10s%20s\n", clk_dump->name, 866 "unknown"); 867 else 868 printf("%10s%20lu Hz\n", clk_dump->name, 869 rate); 870 } else { 871 if (rate < 0) 872 printf("%14s%20s\n", clk_dump->name, 873 "unknown"); 874 else 875 printf("%14s%20lu Hz\n", clk_dump->name, 876 rate); 877 } 878 } 879 } 880 881 return 0; 882 } 883 #endif 884 885