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 case PCLK_WDT: 241 con = readl(&cru->cru_clksel_con[10]); 242 div = (con & PCLK_PERI_DIV_MASK) >> PCLK_PERI_DIV_SHIFT; 243 parent = rk3128_peri_get_clk(priv, ACLK_PERI); 244 break; 245 case HCLK_PERI: 246 con = readl(&cru->cru_clksel_con[10]); 247 div = (con & HCLK_PERI_DIV_MASK) >> HCLK_PERI_DIV_SHIFT; 248 parent = rk3128_peri_get_clk(priv, ACLK_PERI); 249 break; 250 default: 251 printf("do not support this peripheral bus\n"); 252 return -EINVAL; 253 } 254 255 return DIV_TO_RATE(parent, div); 256 } 257 258 static ulong rk3128_peri_set_clk(struct rk3128_clk_priv *priv, 259 ulong clk_id, uint hz) 260 { 261 struct rk3128_cru *cru = priv->cru; 262 int src_clk_div; 263 264 switch (clk_id) { 265 case ACLK_PERI: 266 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 267 assert(src_clk_div - 1 < 32); 268 rk_clrsetreg(&cru->cru_clksel_con[10], 269 PERI_PLL_SEL_MASK | ACLK_PERI_DIV_MASK, 270 PERI_PLL_SEL_GPLL << PERI_PLL_SEL_SHIFT | 271 (src_clk_div - 1) << ACLK_PERI_DIV_SHIFT); 272 break; 273 case PCLK_I2C0: 274 case PCLK_I2C1: 275 case PCLK_I2C2: 276 case PCLK_I2C3: 277 case PCLK_PWM: 278 case PCLK_PERI: 279 src_clk_div = DIV_ROUND_UP(rk3128_peri_get_clk(priv, 280 ACLK_PERI), 281 hz); 282 assert(src_clk_div - 1 < 3); 283 rk_clrsetreg(&cru->cru_clksel_con[10], 284 PCLK_PERI_DIV_MASK, 285 (src_clk_div - 1) << PCLK_PERI_DIV_SHIFT); 286 break; 287 case HCLK_PERI: 288 src_clk_div = DIV_ROUND_UP(rk3128_peri_get_clk(priv, 289 ACLK_PERI), 290 hz); 291 assert(src_clk_div - 1 < 7); 292 rk_clrsetreg(&cru->cru_clksel_con[10], 293 HCLK_PERI_DIV_MASK, 294 (src_clk_div - 1) << HCLK_PERI_DIV_SHIFT); 295 break; 296 default: 297 printf("do not support this peripheral bus\n"); 298 return -EINVAL; 299 } 300 301 return rk3128_peri_get_clk(priv, clk_id); 302 } 303 304 static ulong rk3128_bus_get_clk(struct rk3128_clk_priv *priv, ulong clk_id) 305 { 306 struct rk3128_cru *cru = priv->cru; 307 u32 div, con, parent; 308 309 switch (clk_id) { 310 case ACLK_CPU: 311 con = readl(&cru->cru_clksel_con[0]); 312 div = (con & ACLK_BUS_DIV_MASK) >> ACLK_BUS_DIV_SHIFT; 313 parent = priv->gpll_hz; 314 break; 315 case PCLK_CPU: 316 con = readl(&cru->cru_clksel_con[1]); 317 div = (con & PCLK_BUS_DIV_MASK) >> PCLK_BUS_DIV_SHIFT; 318 parent = rk3128_bus_get_clk(priv, ACLK_CPU); 319 break; 320 case HCLK_CPU: 321 con = readl(&cru->cru_clksel_con[1]); 322 div = (con & HCLK_BUS_DIV_MASK) >> HCLK_BUS_DIV_SHIFT; 323 parent = rk3128_bus_get_clk(priv, ACLK_CPU); 324 break; 325 default: 326 printf("do not support this peripheral bus\n"); 327 return -EINVAL; 328 } 329 330 return DIV_TO_RATE(parent, div); 331 } 332 333 static ulong rk3128_bus_set_clk(struct rk3128_clk_priv *priv, 334 ulong clk_id, uint hz) 335 { 336 struct rk3128_cru *cru = priv->cru; 337 int src_clk_div; 338 339 switch (clk_id) { 340 case ACLK_CPU: 341 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 342 assert(src_clk_div - 1 < 32); 343 rk_clrsetreg(&cru->cru_clksel_con[0], 344 BUS_PLL_SEL_MASK | ACLK_BUS_DIV_MASK, 345 BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT | 346 (src_clk_div - 1) << ACLK_BUS_DIV_SHIFT); 347 break; 348 case PCLK_CPU: 349 src_clk_div = DIV_ROUND_UP(rk3128_bus_get_clk(priv, 350 ACLK_CPU), 351 hz); 352 assert(src_clk_div - 1 < 3); 353 rk_clrsetreg(&cru->cru_clksel_con[1], 354 PCLK_BUS_DIV_MASK, 355 (src_clk_div - 1) << PCLK_BUS_DIV_SHIFT); 356 break; 357 case HCLK_CPU: 358 src_clk_div = DIV_ROUND_UP(rk3128_bus_get_clk(priv, 359 ACLK_CPU), 360 hz); 361 assert(src_clk_div - 1 < 7); 362 rk_clrsetreg(&cru->cru_clksel_con[1], 363 HCLK_BUS_DIV_MASK, 364 (src_clk_div - 1) << HCLK_BUS_DIV_SHIFT); 365 break; 366 default: 367 printf("do not support this peripheral bus\n"); 368 return -EINVAL; 369 } 370 371 return rk3128_bus_get_clk(priv, clk_id); 372 } 373 374 static ulong rk3128_spi_get_clk(struct rk3128_clk_priv *priv) 375 { 376 struct rk3128_cru *cru = priv->cru; 377 u32 div, con, parent; 378 379 con = readl(&cru->cru_clksel_con[25]); 380 div = (con & SPI_DIV_MASK) >> SPI_DIV_SHIFT; 381 parent = priv->gpll_hz; 382 383 return DIV_TO_RATE(parent, div); 384 } 385 386 static ulong rk3128_spi_set_clk(struct rk3128_clk_priv *priv, ulong hz) 387 { 388 struct rk3128_cru *cru = priv->cru; 389 int div; 390 391 div = DIV_ROUND_UP(priv->gpll_hz, hz); 392 assert(div - 1 < 128); 393 rk_clrsetreg(&cru->cru_clksel_con[25], 394 SPI_PLL_SEL_MASK | SPI_DIV_MASK, 395 SPI_PLL_SEL_GPLL << SPI_PLL_SEL_SHIFT | 396 (div - 1) << SPI_DIV_SHIFT); 397 return rk3128_spi_get_clk(priv); 398 } 399 400 #ifndef CONFIG_SPL_BUILD 401 static ulong rk3128_saradc_get_clk(struct rk3128_clk_priv *priv) 402 { 403 struct rk3128_cru *cru = priv->cru; 404 u32 div, val; 405 406 val = readl(&cru->cru_clksel_con[24]); 407 div = bitfield_extract(val, SARADC_DIV_CON_SHIFT, 408 SARADC_DIV_CON_WIDTH); 409 410 return DIV_TO_RATE(OSC_HZ, div); 411 } 412 413 static ulong rk3128_saradc_set_clk(struct rk3128_clk_priv *priv, uint hz) 414 { 415 struct rk3128_cru *cru = priv->cru; 416 int src_clk_div; 417 418 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1; 419 assert(src_clk_div < 128); 420 421 rk_clrsetreg(&cru->cru_clksel_con[24], 422 SARADC_DIV_CON_MASK, 423 src_clk_div << SARADC_DIV_CON_SHIFT); 424 425 return rk3128_saradc_get_clk(priv); 426 } 427 428 #define RK3128_LCDC_PLL_LIMIT 600000000 429 430 static ulong rk3128_vop_set_clk(struct rk3128_clk_priv *priv, 431 ulong clk_id, uint hz) 432 { 433 struct rk3128_cru *cru = priv->cru; 434 int src_clk_div; 435 436 src_clk_div = GPLL_HZ / hz; 437 assert(src_clk_div - 1 < 31); 438 439 switch (clk_id) { 440 case ACLK_LCDC0: 441 case ACLK_VIO0: 442 rk_clrsetreg(&cru->cru_clksel_con[31], 443 VIO0_PLL_MASK | VIO0_DIV_MASK, 444 VIO0_SEL_GPLL << VIO0_PLL_SHIFT | 445 (src_clk_div - 1) << VIO0_DIV_SHIFT); 446 break; 447 case ACLK_VIO1: 448 rk_clrsetreg(&cru->cru_clksel_con[31], 449 VIO1_PLL_MASK | VIO1_DIV_MASK, 450 VIO1_SEL_GPLL << VIO1_PLL_SHIFT | 451 (src_clk_div - 1) << VIO1_DIV_SHIFT); 452 break; 453 case DCLK_VOP: 454 src_clk_div = DIV_ROUND_UP(RK3128_LCDC_PLL_LIMIT, hz); 455 rockchip_pll_set_rate(&rk3128_pll_clks[CPLL], 456 priv->cru, CPLL, src_clk_div * hz); 457 rk_clrsetreg(&cru->cru_clksel_con[27], 458 DCLK_VOP_SEL_MASK | DCLK_VOP_DIV_CON_MASK, 459 DCLK_VOP_PLL_SEL_CPLL << DCLK_VOP_SEL_SHIFT | 460 (src_clk_div - 1) << DCLK_VOP_DIV_CON_SHIFT); 461 break; 462 default: 463 printf("do not support this vop freq\n"); 464 return -EINVAL; 465 } 466 467 return hz; 468 } 469 470 static ulong rk3128_vop_get_rate(struct rk3128_clk_priv *priv, ulong clk_id) 471 { 472 struct rk3128_cru *cru = priv->cru; 473 u32 div, con, parent; 474 475 switch (clk_id) { 476 case ACLK_LCDC0: 477 case ACLK_VIO0: 478 con = readl(&cru->cru_clksel_con[31]); 479 div = con & 0x1f; 480 parent = GPLL_HZ; 481 break; 482 case ACLK_VIO1: 483 con = readl(&cru->cru_clksel_con[31]); 484 div = (con >> 8) & 0x1f; 485 parent = GPLL_HZ; 486 break; 487 case DCLK_VOP: 488 con = readl(&cru->cru_clksel_con[27]); 489 div = (con & DCLK_VOP_DIV_CON_MASK) >> DCLK_VOP_DIV_CON_SHIFT; 490 parent = rockchip_pll_get_rate(&rk3128_pll_clks[CPLL], 491 priv->cru, CPLL); 492 break; 493 default: 494 return -ENOENT; 495 } 496 return DIV_TO_RATE(parent, div); 497 } 498 499 static ulong rk3128_crypto_get_rate(struct rk3128_clk_priv *priv) 500 { 501 struct rk3128_cru *cru = priv->cru; 502 u32 div, val; 503 504 val = readl(&cru->cru_clksel_con[24]); 505 div = (val & CLK_CRYPTO_DIV_CON_MASK) >> CLK_CRYPTO_DIV_CON_SHIFT; 506 507 return DIV_TO_RATE(rk3128_bus_get_clk(priv, ACLK_CPU), div); 508 } 509 510 static ulong rk3128_crypto_set_rate(struct rk3128_clk_priv *priv, 511 uint hz) 512 { 513 struct rk3128_cru *cru = priv->cru; 514 int src_clk_div; 515 uint p_rate; 516 517 p_rate = rk3128_bus_get_clk(priv, ACLK_CPU); 518 src_clk_div = DIV_ROUND_UP(p_rate, hz) - 1; 519 assert(src_clk_div < 3); 520 521 rk_clrsetreg(&cru->cru_clksel_con[24], 522 CLK_CRYPTO_DIV_CON_MASK, 523 src_clk_div << CLK_CRYPTO_DIV_CON_SHIFT); 524 525 return rk3128_crypto_get_rate(priv); 526 } 527 #endif 528 529 static ulong rk3128_clk_get_rate(struct clk *clk) 530 { 531 struct rk3128_clk_priv *priv = dev_get_priv(clk->dev); 532 ulong rate = 0; 533 534 switch (clk->id) { 535 case PLL_APLL: 536 case PLL_DPLL: 537 case PLL_CPLL: 538 case PLL_GPLL: 539 rate = rockchip_pll_get_rate(&rk3128_pll_clks[clk->id - 1], 540 priv->cru, clk->id - 1); 541 break; 542 case ARMCLK: 543 rate = rockchip_pll_get_rate(&rk3128_pll_clks[APLL], 544 priv->cru, APLL); 545 break; 546 case HCLK_EMMC: 547 case SCLK_EMMC: 548 case HCLK_SDMMC: 549 case SCLK_SDMMC: 550 case HCLK_SDIO: 551 case SCLK_SDIO: 552 rate = rockchip_mmc_get_clk(priv, clk->id); 553 break; 554 case ACLK_PERI: 555 case HCLK_PERI: 556 case PCLK_PERI: 557 case PCLK_I2C0: 558 case PCLK_I2C1: 559 case PCLK_I2C2: 560 case PCLK_I2C3: 561 case PCLK_PWM: 562 case PCLK_WDT: 563 rate = rk3128_peri_get_clk(priv, clk->id); 564 break; 565 case ACLK_CPU: 566 case HCLK_CPU: 567 case PCLK_CPU: 568 rate = rk3128_bus_get_clk(priv, clk->id); 569 break; 570 case SCLK_SPI0: 571 rate = rk3128_spi_get_clk(priv); 572 break; 573 #ifndef CONFIG_SPL_BUILD 574 case SCLK_SARADC: 575 rate = rk3128_saradc_get_clk(priv); 576 break; 577 case DCLK_VOP: 578 case ACLK_VIO0: 579 case ACLK_VIO1: 580 case ACLK_LCDC0: 581 rate = rk3128_vop_get_rate(priv, clk->id); 582 break; 583 case SCLK_CRYPTO: 584 rate = rk3128_crypto_get_rate(priv); 585 break; 586 #endif 587 default: 588 return -ENOENT; 589 } 590 return rate; 591 } 592 593 static ulong rk3128_clk_set_rate(struct clk *clk, ulong rate) 594 { 595 struct rk3128_clk_priv *priv = dev_get_priv(clk->dev); 596 ulong ret = 0; 597 598 switch (clk->id) { 599 case PLL_APLL: 600 case PLL_DPLL: 601 case PLL_CPLL: 602 ret = rockchip_pll_set_rate(&rk3128_pll_clks[clk->id - 1], 603 priv->cru, clk->id - 1, rate); 604 case PLL_GPLL: 605 ret = rockchip_pll_set_rate(&rk3128_pll_clks[GPLL], 606 priv->cru, GPLL, rate); 607 priv->gpll_hz = rate; 608 break; 609 case ARMCLK: 610 if (priv->armclk_hz) 611 ret = rk3128_armclk_set_clk(priv, rate); 612 priv->armclk_hz = rate; 613 break; 614 case HCLK_EMMC: 615 case SCLK_EMMC: 616 case SCLK_EMMC_SAMPLE: 617 case HCLK_SDMMC: 618 case SCLK_SDMMC: 619 case SCLK_SDMMC_SAMPLE: 620 case HCLK_SDIO: 621 case SCLK_SDIO: 622 case SCLK_SDIO_SAMPLE: 623 ret = rockchip_mmc_set_clk(priv, clk->id, rate); 624 break; 625 case ACLK_PERI: 626 case PCLK_PERI: 627 case HCLK_PERI: 628 case PCLK_I2C0: 629 case PCLK_I2C1: 630 case PCLK_I2C2: 631 case PCLK_I2C3: 632 case PCLK_PWM: 633 ret = rk3128_peri_set_clk(priv, clk->id, rate); 634 break; 635 case ACLK_CPU: 636 case HCLK_CPU: 637 case PCLK_CPU: 638 ret = rk3128_bus_set_clk(priv, clk->id, rate); 639 break; 640 case SCLK_SPI0: 641 rate = rk3128_spi_set_clk(priv, rate); 642 break; 643 #ifndef CONFIG_SPL_BUILD 644 case SCLK_SARADC: 645 ret = rk3128_saradc_set_clk(priv, rate); 646 break; 647 case DCLK_VOP: 648 case ACLK_VIO0: 649 case ACLK_VIO1: 650 case ACLK_LCDC0: 651 ret = rk3128_vop_set_clk(priv, clk->id, rate); 652 break; 653 case SCLK_CRYPTO: 654 ret = rk3128_crypto_set_rate(priv, rate); 655 break; 656 #endif 657 default: 658 return -ENOENT; 659 } 660 return ret; 661 } 662 663 #define ROCKCHIP_MMC_DELAY_SEL BIT(10) 664 #define ROCKCHIP_MMC_DEGREE_MASK 0x3 665 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2 666 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 667 668 #define PSECS_PER_SEC 1000000000000LL 669 /* 670 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 671 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 672 */ 673 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 674 675 int rk3128_mmc_get_phase(struct clk *clk) 676 { 677 struct rk3128_clk_priv *priv = dev_get_priv(clk->dev); 678 struct rk3128_cru *cru = priv->cru; 679 u32 raw_value, delay_num; 680 u16 degrees = 0; 681 ulong rate; 682 683 rate = rk3128_clk_get_rate(clk); 684 685 if (rate < 0) 686 return rate; 687 688 if (clk->id == SCLK_EMMC_SAMPLE) 689 raw_value = readl(&cru->cru_emmc_con[1]); 690 else if (clk->id == SCLK_SDMMC_SAMPLE) 691 raw_value = readl(&cru->cru_sdmmc_con[1]); 692 else 693 raw_value = readl(&cru->cru_sdio_con[1]); 694 695 raw_value >>= 1; 696 degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; 697 698 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 699 /* degrees/delaynum * 10000 */ 700 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 701 36 * (rate / 1000000); 702 703 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 704 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 705 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 706 } 707 708 return degrees % 360; 709 } 710 711 int rk3128_mmc_set_phase(struct clk *clk, u32 degrees) 712 { 713 struct rk3128_clk_priv *priv = dev_get_priv(clk->dev); 714 struct rk3128_cru *cru = priv->cru; 715 u8 nineties, remainder, delay_num; 716 u32 raw_value, delay; 717 ulong rate; 718 719 rate = rk3128_clk_get_rate(clk); 720 721 if (rate < 0) 722 return rate; 723 724 nineties = degrees / 90; 725 remainder = (degrees % 90); 726 727 /* 728 * Convert to delay; do a little extra work to make sure we 729 * don't overflow 32-bit / 64-bit numbers. 730 */ 731 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 732 delay *= remainder; 733 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 734 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 735 736 delay_num = (u8)min_t(u32, delay, 255); 737 738 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 739 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 740 raw_value |= nineties; 741 742 raw_value <<= 1; 743 if (clk->id == SCLK_EMMC_SAMPLE) 744 writel(raw_value | 0xffff0000, &cru->cru_emmc_con[1]); 745 else if (clk->id == SCLK_SDMMC_SAMPLE) 746 writel(raw_value | 0xffff0000, &cru->cru_sdmmc_con[1]); 747 else 748 writel(raw_value | 0xffff0000, &cru->cru_sdio_con[1]); 749 750 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 751 degrees, delay_num, raw_value, rk3128_mmc_get_phase(clk)); 752 753 return 0; 754 } 755 756 static int rk3128_clk_get_phase(struct clk *clk) 757 { 758 int ret; 759 760 debug("%s %ld\n", __func__, clk->id); 761 switch (clk->id) { 762 case SCLK_EMMC_SAMPLE: 763 case SCLK_SDMMC_SAMPLE: 764 case SCLK_SDIO_SAMPLE: 765 ret = rk3128_mmc_get_phase(clk); 766 break; 767 default: 768 return -ENOENT; 769 } 770 771 return ret; 772 } 773 774 static int rk3128_clk_set_phase(struct clk *clk, int degrees) 775 { 776 int ret; 777 778 debug("%s %ld\n", __func__, clk->id); 779 switch (clk->id) { 780 case SCLK_EMMC_SAMPLE: 781 case SCLK_SDMMC_SAMPLE: 782 case SCLK_SDIO_SAMPLE: 783 ret = rk3128_mmc_set_phase(clk, degrees); 784 break; 785 default: 786 return -ENOENT; 787 } 788 789 return ret; 790 } 791 792 static struct clk_ops rk3128_clk_ops = { 793 .get_rate = rk3128_clk_get_rate, 794 .set_rate = rk3128_clk_set_rate, 795 .get_phase = rk3128_clk_get_phase, 796 .set_phase = rk3128_clk_set_phase, 797 }; 798 799 static int rk3128_clk_ofdata_to_platdata(struct udevice *dev) 800 { 801 struct rk3128_clk_priv *priv = dev_get_priv(dev); 802 803 priv->cru = dev_read_addr_ptr(dev); 804 805 return 0; 806 } 807 808 static void rkclk_init(struct rk3128_clk_priv *priv) 809 { 810 if (rockchip_pll_get_rate(&rk3128_pll_clks[APLL], 811 priv->cru, APLL) != APLL_HZ) 812 rk3128_armclk_set_clk(priv, APLL_HZ); 813 814 priv->gpll_hz = rockchip_pll_get_rate(&rk3128_pll_clks[GPLL], 815 priv->cru, GPLL); 816 rk3128_bus_set_clk(priv, ACLK_CPU, ACLK_BUS_HZ / 2); 817 rk3128_peri_set_clk(priv, ACLK_PERI, ACLK_PERI_HZ / 2); 818 rockchip_pll_set_rate(&rk3128_pll_clks[GPLL], 819 priv->cru, GPLL, GPLL_HZ); 820 priv->gpll_hz = GPLL_HZ; 821 rk_clrsetreg(&priv->cru->cru_clksel_con[2], 822 NANDC_PLL_SEL_MASK | NANDC_CLK_DIV_MASK, 823 NANDC_PLL_SEL_GPLL << NANDC_PLL_SEL_SHIFT | 824 3 << NANDC_CLK_DIV_SHIFT); 825 rk_clrsetreg(&priv->cru->cru_clksel_con[11], 826 SFC_PLL_SEL_MASK | SFC_CLK_DIV_MASK, 827 SFC_PLL_SEL_GPLL << SFC_PLL_SEL_SHIFT | 828 9 << SFC_CLK_DIV_SHIFT); 829 830 rk3128_bus_set_clk(priv, ACLK_CPU, ACLK_BUS_HZ); 831 rk3128_bus_set_clk(priv, HCLK_CPU, ACLK_BUS_HZ / 2); 832 rk3128_bus_set_clk(priv, PCLK_CPU, ACLK_BUS_HZ / 2); 833 rk3128_peri_set_clk(priv, ACLK_PERI, ACLK_PERI_HZ); 834 rk3128_peri_set_clk(priv, HCLK_PERI, ACLK_PERI_HZ / 2); 835 rk3128_peri_set_clk(priv, PCLK_PERI, ACLK_PERI_HZ / 2); 836 837 rockchip_pll_set_rate(&rk3128_pll_clks[CPLL], 838 priv->cru, CPLL, CPLL_HZ); 839 } 840 841 static int rk3128_clk_probe(struct udevice *dev) 842 { 843 struct rk3128_clk_priv *priv = dev_get_priv(dev); 844 845 priv->sync_kernel = false; 846 if (!priv->armclk_enter_hz) 847 priv->armclk_enter_hz = 848 rockchip_pll_get_rate(&rk3128_pll_clks[APLL], 849 priv->cru, APLL); 850 rkclk_init(priv); 851 if (!priv->armclk_init_hz) 852 priv->armclk_init_hz = 853 rockchip_pll_get_rate(&rk3128_pll_clks[APLL], 854 priv->cru, APLL); 855 856 return 0; 857 } 858 859 static int rk3128_clk_bind(struct udevice *dev) 860 { 861 int ret; 862 struct udevice *sys_child, *sf_child; 863 struct sysreset_reg *priv; 864 struct softreset_reg *sf_priv; 865 866 /* The reset driver does not have a device node, so bind it here */ 867 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 868 &sys_child); 869 if (ret) { 870 debug("Warning: No sysreset driver: ret=%d\n", ret); 871 } else { 872 priv = malloc(sizeof(struct sysreset_reg)); 873 priv->glb_srst_fst_value = offsetof(struct rk3128_cru, 874 cru_glb_srst_fst_value); 875 priv->glb_srst_snd_value = offsetof(struct rk3128_cru, 876 cru_glb_srst_snd_value); 877 sys_child->priv = priv; 878 } 879 880 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 881 dev_ofnode(dev), &sf_child); 882 if (ret) { 883 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 884 } else { 885 sf_priv = malloc(sizeof(struct softreset_reg)); 886 sf_priv->sf_reset_offset = offsetof(struct rk3128_cru, 887 cru_softrst_con[0]); 888 sf_priv->sf_reset_num = 9; 889 sf_child->priv = sf_priv; 890 } 891 892 return 0; 893 } 894 895 static const struct udevice_id rk3128_clk_ids[] = { 896 { .compatible = "rockchip,rk3128-cru" }, 897 { .compatible = "rockchip,rk3126-cru" }, 898 { } 899 }; 900 901 U_BOOT_DRIVER(rockchip_rk3128_cru) = { 902 .name = "clk_rk3128", 903 .id = UCLASS_CLK, 904 .of_match = rk3128_clk_ids, 905 .priv_auto_alloc_size = sizeof(struct rk3128_clk_priv), 906 .ofdata_to_platdata = rk3128_clk_ofdata_to_platdata, 907 .ops = &rk3128_clk_ops, 908 .bind = rk3128_clk_bind, 909 .probe = rk3128_clk_probe, 910 }; 911 912 #ifndef CONFIG_SPL_BUILD 913 /** 914 * soc_clk_dump() - Print clock frequencies 915 * Returns zero on success 916 * 917 * Implementation for the clk dump command. 918 */ 919 int soc_clk_dump(void) 920 { 921 struct udevice *cru_dev; 922 struct rk3128_clk_priv *priv; 923 const struct rk3128_clk_info *clk_dump; 924 struct clk clk; 925 unsigned long clk_count = ARRAY_SIZE(clks_dump); 926 unsigned long rate; 927 int i, ret; 928 929 ret = uclass_get_device_by_driver(UCLASS_CLK, 930 DM_GET_DRIVER(rockchip_rk3128_cru), 931 &cru_dev); 932 if (ret) { 933 printf("%s failed to get cru device\n", __func__); 934 return ret; 935 } 936 937 priv = dev_get_priv(cru_dev); 938 printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n", 939 priv->sync_kernel ? "sync kernel" : "uboot", 940 priv->armclk_enter_hz / 1000, 941 priv->armclk_init_hz / 1000, 942 priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0, 943 priv->set_armclk_rate ? " KHz" : "N/A"); 944 for (i = 0; i < clk_count; i++) { 945 clk_dump = &clks_dump[i]; 946 if (clk_dump->name) { 947 clk.id = clk_dump->id; 948 if (clk_dump->is_cru) 949 ret = clk_request(cru_dev, &clk); 950 if (ret < 0) 951 return ret; 952 953 rate = clk_get_rate(&clk); 954 clk_free(&clk); 955 if (i == 0) { 956 if (rate < 0) 957 printf(" %s %s\n", clk_dump->name, 958 "unknown"); 959 else 960 printf(" %s %lu KHz\n", clk_dump->name, 961 rate / 1000); 962 } else { 963 if (rate < 0) 964 printf(" %s %s\n", clk_dump->name, 965 "unknown"); 966 else 967 printf(" %s %lu KHz\n", clk_dump->name, 968 rate / 1000); 969 } 970 } 971 } 972 973 return 0; 974 } 975 #endif 976 977