1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <bitfield.h> 8 #include <clk-uclass.h> 9 #include <dm.h> 10 #include <errno.h> 11 #include <syscon.h> 12 #include <clk.h> 13 #include <asm/arch/clock.h> 14 #include <asm/arch/cru_rk1808.h> 15 #include <asm/arch/hardware.h> 16 #include <asm/io.h> 17 #include <dm/lists.h> 18 #include <dt-bindings/clock/rk1808-cru.h> 19 #include <div64.h> 20 21 DECLARE_GLOBAL_DATA_PTR; 22 23 #define RK1808_CPUCLK_RATE(_rate, _aclk_div, _pclk_div) \ 24 { \ 25 .rate = _rate##U, \ 26 .aclk_div = _aclk_div, \ 27 .pclk_div = _pclk_div, \ 28 } 29 30 #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1)) 31 32 static struct rockchip_pll_rate_table rk1808_pll_rates[] = { 33 /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ 34 RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), 35 RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0), 36 RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0), 37 RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), 38 RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0), 39 RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0), 40 RK3036_PLL_RATE(800000000, 6, 400, 2, 1, 1, 0), 41 RK3036_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0), 42 RK3036_PLL_RATE(594000000, 2, 99, 2, 1, 1, 0), 43 RK3036_PLL_RATE(500000000, 6, 250, 2, 1, 1, 0), 44 RK3036_PLL_RATE(200000000, 1, 200, 6, 4, 1, 0), 45 RK3036_PLL_RATE(100000000, 1, 150, 6, 6, 1, 0), 46 { /* sentinel */ }, 47 }; 48 49 #ifndef CONFIG_SPL_BUILD 50 #define RK1808_CLK_DUMP(_id, _name, _iscru) \ 51 { \ 52 .id = _id, \ 53 .name = _name, \ 54 .is_cru = _iscru, \ 55 } 56 57 static const struct rk1808_clk_info clks_dump[] = { 58 RK1808_CLK_DUMP(PLL_APLL, "apll", true), 59 RK1808_CLK_DUMP(PLL_DPLL, "dpll", true), 60 RK1808_CLK_DUMP(PLL_CPLL, "cpll", true), 61 RK1808_CLK_DUMP(PLL_GPLL, "gpll", true), 62 RK1808_CLK_DUMP(PLL_NPLL, "npll", true), 63 RK1808_CLK_DUMP(PLL_PPLL, "ppll", true), 64 RK1808_CLK_DUMP(HSCLK_BUS_PRE, "hsclk_bus", true), 65 RK1808_CLK_DUMP(MSCLK_BUS_PRE, "msclk_bus", true), 66 RK1808_CLK_DUMP(LSCLK_BUS_PRE, "lsclk_bus", true), 67 RK1808_CLK_DUMP(MSCLK_PERI, "msclk_peri", true), 68 RK1808_CLK_DUMP(LSCLK_PERI, "lsclk_peri", true), 69 }; 70 #endif 71 72 static struct rockchip_cpu_rate_table rk1808_cpu_rates[] = { 73 RK1808_CPUCLK_RATE(1200000000, 1, 5), 74 RK1808_CPUCLK_RATE(1008000000, 1, 5), 75 RK1808_CPUCLK_RATE(816000000, 1, 3), 76 RK1808_CPUCLK_RATE(600000000, 1, 3), 77 }; 78 79 static struct rockchip_pll_clock rk1808_pll_clks[] = { 80 [APLL] = PLL(pll_rk3036, PLL_APLL, RK1808_PLL_CON(0), 81 RK1808_MODE_CON, 0, 10, 0, rk1808_pll_rates), 82 [DPLL] = PLL(pll_rk3036, PLL_DPLL, RK1808_PLL_CON(8), 83 RK1808_MODE_CON, 2, 10, 0, NULL), 84 [CPLL] = PLL(pll_rk3036, PLL_CPLL, RK1808_PLL_CON(16), 85 RK1808_MODE_CON, 4, 10, 0, rk1808_pll_rates), 86 [GPLL] = PLL(pll_rk3036, PLL_GPLL, RK1808_PLL_CON(24), 87 RK1808_MODE_CON, 6, 10, 0, rk1808_pll_rates), 88 [NPLL] = PLL(pll_rk3036, PLL_NPLL, RK1808_PLL_CON(32), 89 RK1808_MODE_CON, 8, 10, 0, rk1808_pll_rates), 90 [PPLL] = PLL(pll_rk3036, PLL_PPLL, RK1808_PMU_PLL_CON(0), 91 RK1808_PMU_MODE_CON, 0, 10, 0, rk1808_pll_rates), 92 }; 93 94 #ifndef CONFIG_SPL_BUILD 95 static ulong rk1808_i2c_get_clk(struct rk1808_clk_priv *priv, ulong clk_id) 96 { 97 struct rk1808_cru *cru = priv->cru; 98 u32 div, con; 99 100 switch (clk_id) { 101 case SCLK_PMU_I2C0: 102 con = readl(&cru->pmu_clksel_con[7]); 103 div = (con & CLK_I2C0_DIV_CON_MASK) >> CLK_I2C0_DIV_CON_SHIFT; 104 break; 105 case SCLK_I2C1: 106 con = readl(&cru->clksel_con[59]); 107 div = (con & CLK_I2C1_DIV_CON_MASK) >> CLK_I2C1_DIV_CON_SHIFT; 108 break; 109 case SCLK_I2C2: 110 con = readl(&cru->clksel_con[59]); 111 div = (con & CLK_I2C2_DIV_CON_MASK) >> CLK_I2C2_DIV_CON_SHIFT; 112 break; 113 case SCLK_I2C3: 114 con = readl(&cru->clksel_con[60]); 115 div = (con & CLK_I2C3_DIV_CON_MASK) >> CLK_I2C3_DIV_CON_SHIFT; 116 break; 117 case SCLK_I2C4: 118 con = readl(&cru->clksel_con[71]); 119 div = (con & CLK_I2C4_DIV_CON_MASK) >> CLK_I2C4_DIV_CON_SHIFT; 120 break; 121 case SCLK_I2C5: 122 con = readl(&cru->clksel_con[71]); 123 div = (con & CLK_I2C5_DIV_CON_MASK) >> CLK_I2C5_DIV_CON_SHIFT; 124 break; 125 default: 126 printf("do not support this i2c bus\n"); 127 return -EINVAL; 128 } 129 130 return DIV_TO_RATE(priv->gpll_hz, div); 131 } 132 133 static ulong rk1808_i2c_set_clk(struct rk1808_clk_priv *priv, 134 ulong clk_id, uint hz) 135 { 136 struct rk1808_cru *cru = priv->cru; 137 int src_clk_div; 138 139 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 140 assert(src_clk_div - 1 < 127); 141 142 switch (clk_id) { 143 case SCLK_PMU_I2C0: 144 rk_clrsetreg(&cru->pmu_clksel_con[7], 145 CLK_I2C0_DIV_CON_MASK | CLK_I2C0_PLL_SEL_MASK, 146 (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT | 147 CLK_I2C0_PLL_SEL_PPLL << CLK_I2C0_PLL_SEL_SHIFT); 148 break; 149 case SCLK_I2C1: 150 rk_clrsetreg(&cru->clksel_con[59], 151 CLK_I2C1_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK, 152 (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT | 153 CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT); 154 break; 155 case SCLK_I2C2: 156 rk_clrsetreg(&cru->clksel_con[59], 157 CLK_I2C2_DIV_CON_MASK | CLK_I2C2_PLL_SEL_MASK, 158 (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT | 159 CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT); 160 break; 161 case SCLK_I2C3: 162 rk_clrsetreg(&cru->clksel_con[60], 163 CLK_I2C3_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK, 164 (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT | 165 CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT); 166 break; 167 case SCLK_I2C4: 168 rk_clrsetreg(&cru->clksel_con[71], 169 CLK_I2C4_DIV_CON_MASK | CLK_I2C4_PLL_SEL_MASK, 170 (src_clk_div - 1) << CLK_I2C4_DIV_CON_SHIFT | 171 CLK_I2C_PLL_SEL_GPLL << CLK_I2C4_PLL_SEL_SHIFT); 172 break; 173 case SCLK_I2C5: 174 rk_clrsetreg(&cru->clksel_con[71], 175 CLK_I2C5_DIV_CON_MASK | CLK_I2C5_PLL_SEL_MASK, 176 (src_clk_div - 1) << CLK_I2C5_DIV_CON_SHIFT | 177 CLK_I2C_PLL_SEL_GPLL << CLK_I2C5_PLL_SEL_SHIFT); 178 break; 179 default: 180 printf("do not support this i2c bus\n"); 181 return -EINVAL; 182 } 183 184 return rk1808_i2c_get_clk(priv, clk_id); 185 } 186 #endif 187 188 static ulong rk1808_mmc_get_clk(struct rk1808_clk_priv *priv, uint clk_id) 189 { 190 struct rk1808_cru *cru = priv->cru; 191 u32 div, con, con_id; 192 193 switch (clk_id) { 194 case HCLK_SDMMC: 195 case SCLK_SDMMC: 196 con_id = 20; 197 break; 198 case HCLK_SDIO: 199 case SCLK_SDIO: 200 con_id = 22; 201 break; 202 case HCLK_EMMC: 203 case SCLK_EMMC: 204 case SCLK_EMMC_SAMPLE: 205 con_id = 24; 206 break; 207 default: 208 return -EINVAL; 209 } 210 211 con = readl(&cru->clksel_con[con_id]); 212 div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT; 213 214 if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT 215 == EMMC_SEL_24M) 216 return DIV_TO_RATE(OSC_HZ, div) / 2; 217 else 218 return DIV_TO_RATE(priv->gpll_hz, div) / 2; 219 } 220 221 static ulong rk1808_mmc_set_clk(struct rk1808_clk_priv *priv, 222 ulong clk_id, ulong set_rate) 223 { 224 struct rk1808_cru *cru = priv->cru; 225 int src_clk_div; 226 u32 con_id; 227 228 switch (clk_id) { 229 case HCLK_SDMMC: 230 case SCLK_SDMMC: 231 con_id = 20; 232 break; 233 case HCLK_SDIO: 234 case SCLK_SDIO: 235 con_id = 22; 236 break; 237 case HCLK_EMMC: 238 case SCLK_EMMC: 239 con_id = 24; 240 break; 241 default: 242 return -EINVAL; 243 } 244 245 /* Select clk_sdmmc/emmc source from GPLL by default */ 246 /* mmc clock defaulg div 2 internal, need provide double in cru */ 247 src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, set_rate); 248 249 if (src_clk_div > 127) { 250 /* use 24MHz source for 400KHz clock */ 251 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate); 252 rk_clrsetreg(&cru->clksel_con[con_id], 253 EMMC_PLL_MASK | EMMC_DIV_MASK, 254 EMMC_SEL_24M << EMMC_PLL_SHIFT | 255 (src_clk_div - 1) << EMMC_DIV_SHIFT); 256 } else { 257 rk_clrsetreg(&cru->clksel_con[con_id], 258 EMMC_PLL_MASK | EMMC_DIV_MASK, 259 EMMC_SEL_GPLL << EMMC_PLL_SHIFT | 260 (src_clk_div - 1) << EMMC_DIV_SHIFT); 261 } 262 rk_clrsetreg(&cru->clksel_con[con_id + 1], EMMC_CLK_SEL_MASK, 263 EMMC_CLK_SEL_EMMC); 264 265 return rk1808_mmc_get_clk(priv, clk_id); 266 } 267 268 #ifndef CONFIG_SPL_BUILD 269 static ulong rk1808_pwm_get_clk(struct rk1808_clk_priv *priv, ulong clk_id) 270 { 271 struct rk1808_cru *cru = priv->cru; 272 u32 div, con; 273 274 switch (clk_id) { 275 case SCLK_PWM0: 276 con = readl(&cru->clksel_con[69]); 277 div = (con & CLK_PWM0_DIV_CON_MASK) >> CLK_PWM0_DIV_CON_SHIFT; 278 break; 279 case SCLK_PWM1: 280 con = readl(&cru->clksel_con[69]); 281 div = (con & CLK_PWM1_DIV_CON_MASK) >> CLK_PWM1_DIV_CON_SHIFT; 282 break; 283 case SCLK_PWM2: 284 con = readl(&cru->clksel_con[70]); 285 div = (con & CLK_PWM2_DIV_CON_MASK) >> CLK_PWM2_DIV_CON_SHIFT; 286 break; 287 default: 288 printf("do not support this pwm bus\n"); 289 return -EINVAL; 290 } 291 292 return DIV_TO_RATE(priv->gpll_hz, div); 293 } 294 295 static ulong rk1808_pwm_set_clk(struct rk1808_clk_priv *priv, 296 ulong clk_id, uint hz) 297 { 298 struct rk1808_cru *cru = priv->cru; 299 int src_clk_div; 300 301 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 302 assert(src_clk_div - 1 < 127); 303 304 switch (clk_id) { 305 case SCLK_PWM0: 306 rk_clrsetreg(&cru->clksel_con[69], 307 CLK_PWM0_DIV_CON_MASK | CLK_PWM0_PLL_SEL_MASK, 308 (src_clk_div - 1) << CLK_PWM0_DIV_CON_SHIFT | 309 CLK_PWM_PLL_SEL_GPLL << CLK_PWM0_PLL_SEL_SHIFT); 310 break; 311 case SCLK_PWM1: 312 rk_clrsetreg(&cru->clksel_con[69], 313 CLK_PWM1_DIV_CON_MASK | CLK_PWM1_PLL_SEL_MASK, 314 (src_clk_div - 1) << CLK_PWM1_DIV_CON_SHIFT | 315 CLK_PWM_PLL_SEL_GPLL << CLK_PWM1_PLL_SEL_SHIFT); 316 break; 317 case SCLK_PWM2: 318 rk_clrsetreg(&cru->clksel_con[70], 319 CLK_PWM2_DIV_CON_MASK | CLK_PWM2_PLL_SEL_MASK, 320 (src_clk_div - 1) << CLK_PWM2_DIV_CON_SHIFT | 321 CLK_PWM_PLL_SEL_GPLL << CLK_PWM2_PLL_SEL_SHIFT); 322 break; 323 default: 324 printf("do not support this pwm bus\n"); 325 return -EINVAL; 326 } 327 328 return rk1808_pwm_get_clk(priv, clk_id); 329 } 330 331 static ulong rk1808_saradc_get_clk(struct rk1808_clk_priv *priv) 332 { 333 struct rk1808_cru *cru = priv->cru; 334 u32 div, con; 335 336 con = readl(&cru->clksel_con[63]); 337 div = con & CLK_SARADC_DIV_CON_MASK; 338 339 return DIV_TO_RATE(OSC_HZ, div); 340 } 341 342 static ulong rk1808_saradc_set_clk(struct rk1808_clk_priv *priv, uint hz) 343 { 344 struct rk1808_cru *cru = priv->cru; 345 int src_clk_div; 346 347 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz); 348 assert(src_clk_div - 1 < 2047); 349 350 rk_clrsetreg(&cru->clksel_con[63], 351 CLK_SARADC_DIV_CON_MASK, 352 (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT); 353 354 return rk1808_saradc_get_clk(priv); 355 } 356 357 static ulong rk1808_tsadc_get_clk(struct rk1808_clk_priv *priv) 358 { 359 struct rk1808_cru *cru = priv->cru; 360 u32 div, con; 361 362 con = readl(&cru->clksel_con[62]); 363 div = con & CLK_SARADC_DIV_CON_MASK; 364 365 return DIV_TO_RATE(OSC_HZ, div); 366 } 367 368 static ulong rk1808_tsadc_set_clk(struct rk1808_clk_priv *priv, uint hz) 369 { 370 struct rk1808_cru *cru = priv->cru; 371 int src_clk_div; 372 373 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz); 374 assert(src_clk_div - 1 < 2047); 375 376 rk_clrsetreg(&cru->clksel_con[62], 377 CLK_SARADC_DIV_CON_MASK, 378 (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT); 379 380 return rk1808_tsadc_get_clk(priv); 381 } 382 383 static ulong rk1808_spi_get_clk(struct rk1808_clk_priv *priv, ulong clk_id) 384 { 385 struct rk1808_cru *cru = priv->cru; 386 u32 div, con; 387 388 switch (clk_id) { 389 case SCLK_SPI0: 390 con = readl(&cru->clksel_con[60]); 391 div = (con & CLK_SPI0_DIV_CON_MASK) >> CLK_SPI0_DIV_CON_SHIFT; 392 break; 393 case SCLK_SPI1: 394 con = readl(&cru->clksel_con[61]); 395 div = (con & CLK_SPI1_DIV_CON_MASK) >> CLK_SPI1_DIV_CON_SHIFT; 396 break; 397 case SCLK_SPI2: 398 con = readl(&cru->clksel_con[61]); 399 div = (con & CLK_SPI2_DIV_CON_MASK) >> CLK_SPI2_DIV_CON_SHIFT; 400 break; 401 default: 402 printf("do not support this pwm bus\n"); 403 return -EINVAL; 404 } 405 406 return DIV_TO_RATE(priv->gpll_hz, div); 407 } 408 409 static ulong rk1808_spi_set_clk(struct rk1808_clk_priv *priv, 410 ulong clk_id, uint hz) 411 { 412 struct rk1808_cru *cru = priv->cru; 413 int src_clk_div; 414 415 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 416 assert(src_clk_div - 1 < 127); 417 418 switch (clk_id) { 419 case SCLK_SPI0: 420 rk_clrsetreg(&cru->clksel_con[60], 421 CLK_SPI0_DIV_CON_MASK | CLK_SPI0_PLL_SEL_MASK, 422 (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT | 423 CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT); 424 break; 425 case SCLK_SPI1: 426 rk_clrsetreg(&cru->clksel_con[61], 427 CLK_SPI1_DIV_CON_MASK | CLK_SPI1_PLL_SEL_MASK, 428 (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT | 429 CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT); 430 break; 431 case SCLK_SPI2: 432 rk_clrsetreg(&cru->clksel_con[61], 433 CLK_SPI2_DIV_CON_MASK | CLK_SPI2_PLL_SEL_MASK, 434 (src_clk_div - 1) << CLK_SPI2_DIV_CON_SHIFT | 435 CLK_SPI_PLL_SEL_GPLL << CLK_SPI2_PLL_SEL_SHIFT); 436 break; 437 default: 438 printf("do not support this pwm bus\n"); 439 return -EINVAL; 440 } 441 442 return rk1808_spi_get_clk(priv, clk_id); 443 } 444 445 #define RK1808_VOP_PLL_LIMIT_FREQ 600 * 1000000 446 static ulong rk1808_vop_get_clk(struct rk1808_clk_priv *priv, ulong clk_id) 447 { 448 struct rk1808_cru *cru = priv->cru; 449 u32 div, con, parent; 450 451 switch (clk_id) { 452 case ACLK_VOPRAW: 453 case ACLK_VOPLITE: 454 con = readl(&cru->clksel_con[4]); 455 div = (con & ACLK_VOP_DIV_CON_MASK) >> ACLK_VOP_DIV_CON_SHIFT; 456 parent = priv->gpll_hz; 457 break; 458 case HCLK_VOPRAW: 459 case HCLK_VOPLITE: 460 parent = rk1808_vop_get_clk(priv, ACLK_VOPRAW); 461 con = readl(&cru->clksel_con[4]); 462 div = (con & HCLK_VOP_DIV_CON_MASK) >> HCLK_VOP_DIV_CON_SHIFT; 463 break; 464 case DCLK_VOPRAW: 465 con = readl(&cru->clksel_con[5]); 466 div = con & DCLK_VOPRAW_DIV_CON_MASK; 467 parent = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL], 468 priv->cru, NPLL); 469 break; 470 case DCLK_VOPLITE: 471 con = readl(&cru->clksel_con[7]); 472 div = con & DCLK_VOPLITE_DIV_CON_MASK; 473 parent = (con & DCLK_VOPLITE_PLL_SEL_MASK) >> 474 DCLK_VOPLITE_PLL_SEL_SHIFT; 475 if (parent == DCLK_VOPLITE_PLL_SEL_NPLL) 476 parent = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL], 477 priv->cru, NPLL); 478 else if (parent == DCLK_VOPLITE_PLL_SEL_CPLL) 479 parent = priv->cpll_hz; 480 else 481 parent = priv->gpll_hz; 482 break; 483 default: 484 return -ENOENT; 485 } 486 487 return DIV_TO_RATE(parent, div); 488 } 489 490 static ulong rk1808_vop_set_clk(struct rk1808_clk_priv *priv, 491 ulong clk_id, uint hz) 492 { 493 struct rk1808_cru *cru = priv->cru; 494 int src_clk_div, parent; 495 496 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 497 assert(src_clk_div - 1 < 31); 498 499 switch (clk_id) { 500 case ACLK_VOPRAW: 501 case ACLK_VOPLITE: 502 rk_clrsetreg(&cru->clksel_con[4], 503 ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK, 504 ACLK_VOP_PLL_SEL_GPLL << ACLK_VOP_PLL_SEL_SHIFT | 505 (src_clk_div - 1) << ACLK_VOP_DIV_CON_SHIFT); 506 break; 507 case HCLK_VOPRAW: 508 case HCLK_VOPLITE: 509 src_clk_div = 510 DIV_ROUND_UP(rk1808_vop_get_clk(priv, ACLK_VOPRAW), hz); 511 assert(src_clk_div - 1 < 15); 512 rk_clrsetreg(&cru->clksel_con[4], 513 HCLK_VOP_DIV_CON_MASK, 514 (src_clk_div - 1) << HCLK_VOP_DIV_CON_SHIFT); 515 break; 516 case DCLK_VOPRAW: 517 /* 518 * vopb dclk source from npll, and equals to 519 */ 520 src_clk_div = DIV_ROUND_UP(RK1808_VOP_PLL_LIMIT_FREQ, hz); 521 rk_clrsetreg(&cru->clksel_con[5], 522 DCLK_VOPRAW_SEL_MASK | 523 DCLK_VOPRAW_PLL_SEL_MASK | 524 DCLK_VOPRAW_DIV_CON_MASK, 525 (DCLK_VOPRAW_SEL_VOPRAW << 526 DCLK_VOPRAW_SEL_SHIFT) | 527 (DCLK_VOPRAW_PLL_SEL_NPLL << 528 DCLK_VOPRAW_PLL_SEL_SHIFT) | 529 ((src_clk_div - 1) << DCLK_VOPRAW_DIV_CON_SHIFT)); 530 rockchip_pll_set_rate(&rk1808_pll_clks[NPLL], 531 priv->cru, NPLL, src_clk_div * hz); 532 533 break; 534 case DCLK_VOPLITE: 535 /* 536 * vopl dclk source from cpll, and equals to 537 */ 538 if (!(priv->cpll_hz % hz)) { 539 parent = DCLK_VOPLITE_PLL_SEL_CPLL; 540 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz); 541 } else if (!(priv->gpll_hz % hz)) { 542 parent = DCLK_VOPLITE_PLL_SEL_GPLL; 543 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 544 } else { 545 parent = DCLK_VOPLITE_PLL_SEL_NPLL; 546 src_clk_div = DIV_ROUND_UP(RK1808_VOP_PLL_LIMIT_FREQ, 547 hz); 548 rockchip_pll_set_rate(&rk1808_pll_clks[NPLL], 549 priv->cru, NPLL, 550 src_clk_div * hz); 551 } 552 rk_clrsetreg(&cru->clksel_con[7], 553 DCLK_VOPLITE_SEL_MASK | DCLK_VOPLITE_PLL_SEL_MASK | 554 DCLK_VOPLITE_DIV_CON_MASK, 555 (DCLK_VOPLITE_SEL_VOPRAW << 556 DCLK_VOPLITE_SEL_SHIFT) | 557 (parent << DCLK_VOPLITE_PLL_SEL_SHIFT) | 558 ((src_clk_div - 1) << DCLK_VOPLITE_DIV_CON_SHIFT)); 559 break; 560 default: 561 printf("do not support this vop freq\n"); 562 return -EINVAL; 563 } 564 565 return rk1808_vop_get_clk(priv, clk_id); 566 } 567 568 static ulong rk1808_mac_set_clk(struct clk *clk, uint hz) 569 { 570 struct rk1808_clk_priv *priv = dev_get_priv(clk->dev); 571 struct rk1808_cru *cru = priv->cru; 572 u32 con = readl(&cru->clksel_con[26]); 573 ulong pll_rate; 574 u8 div; 575 576 if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_NPLL) 577 pll_rate = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL], 578 priv->cru, NPLL); 579 else if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_PPLL) 580 pll_rate = rockchip_pll_get_rate(&rk1808_pll_clks[PPLL], 581 priv->cru, PPLL); 582 else 583 pll_rate = rockchip_pll_get_rate(&rk1808_pll_clks[CPLL], 584 priv->cru, CPLL); 585 586 /*default set 50MHZ for gmac*/ 587 if (!hz) 588 hz = 50000000; 589 590 div = DIV_ROUND_UP(pll_rate, hz) - 1; 591 assert(div < 32); 592 rk_clrsetreg(&cru->clksel_con[26], CLK_GMAC_DIV_MASK, 593 div << CLK_GMAC_DIV_SHIFT); 594 595 return DIV_TO_RATE(pll_rate, div); 596 } 597 598 static int rk1808_mac_set_speed_clk(struct clk *clk, ulong clk_id, uint hz) 599 { 600 struct rk1808_clk_priv *priv = dev_get_priv(clk->dev); 601 struct rk1808_cru *cru = priv->cru; 602 u32 sel; 603 604 switch (clk_id) { 605 case SCLK_GMAC_RGMII_SPEED: 606 if (hz == 125000000) 607 sel = 0; 608 else if (hz == 2500000) 609 sel = 2; 610 else 611 sel = 3; 612 rk_clrsetreg(&cru->clksel_con[27], RGMII_CLK_SEL_MASK, 613 sel << RGMII_CLK_SEL_SHIFT); 614 break; 615 case SCLK_GMAC_RMII_SPEED: 616 if (hz == 2500000) 617 sel = 0; 618 else 619 sel = 1; 620 rk_clrsetreg(&cru->clksel_con[27], RMII_CLK_SEL_MASK, 621 sel << RMII_CLK_SEL_SHIFT); 622 break; 623 default: 624 return -ENOENT; 625 } 626 return 0; 627 } 628 629 static ulong rk1808_crypto_get_clk(struct rk1808_clk_priv *priv, ulong clk_id) 630 { 631 struct rk1808_cru *cru = priv->cru; 632 u32 div, con, parent; 633 634 switch (clk_id) { 635 case SCLK_CRYPTO: 636 con = readl(&cru->clksel_con[29]); 637 div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT; 638 parent = priv->gpll_hz; 639 break; 640 case SCLK_CRYPTO_APK: 641 con = readl(&cru->clksel_con[29]); 642 div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT; 643 parent = priv->gpll_hz; 644 break; 645 default: 646 return -ENOENT; 647 } 648 649 return DIV_TO_RATE(parent, div); 650 } 651 652 static ulong rk1808_crypto_set_clk(struct rk1808_clk_priv *priv, ulong clk_id, 653 ulong hz) 654 { 655 struct rk1808_cru *cru = priv->cru; 656 int src_clk_div; 657 658 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 659 assert(src_clk_div - 1 <= 31); 660 661 /* 662 * select gpll as crypto clock source and 663 * set up dependent divisors for crypto clocks. 664 */ 665 switch (clk_id) { 666 case SCLK_CRYPTO: 667 rk_clrsetreg(&cru->clksel_con[29], 668 CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK, 669 CRYPTO_PLL_SEL_GPLL << CRYPTO_PLL_SEL_SHIFT | 670 (src_clk_div - 1) << CRYPTO_DIV_SHIFT); 671 break; 672 case SCLK_CRYPTO_APK: 673 rk_clrsetreg(&cru->clksel_con[29], 674 CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK, 675 CRYPTO_PLL_SEL_GPLL << CRYPTO_APK_SEL_SHIFT | 676 (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT); 677 break; 678 default: 679 printf("do not support this peri freq\n"); 680 return -EINVAL; 681 } 682 683 return rk1808_crypto_get_clk(priv, clk_id); 684 } 685 #endif 686 687 static ulong rk1808_bus_get_clk(struct rk1808_clk_priv *priv, ulong clk_id) 688 { 689 struct rk1808_cru *cru = priv->cru; 690 u32 div, con, parent; 691 692 switch (clk_id) { 693 case HSCLK_BUS_PRE: 694 con = readl(&cru->clksel_con[27]); 695 div = (con & HSCLK_BUS_DIV_CON_MASK) >> HSCLK_BUS_DIV_CON_SHIFT; 696 parent = priv->gpll_hz; 697 break; 698 case MSCLK_BUS_PRE: 699 con = readl(&cru->clksel_con[28]); 700 div = (con & MSCLK_BUS_DIV_CON_MASK) >> MSCLK_BUS_DIV_CON_SHIFT; 701 parent = priv->gpll_hz; 702 break; 703 case LSCLK_BUS_PRE: 704 case PCLK_WDT: 705 con = readl(&cru->clksel_con[28]); 706 div = (con & LSCLK_BUS_DIV_CON_MASK) >> LSCLK_BUS_DIV_CON_SHIFT; 707 parent = priv->gpll_hz; 708 break; 709 default: 710 return -ENOENT; 711 } 712 713 return DIV_TO_RATE(parent, div); 714 } 715 716 static ulong rk1808_bus_set_clk(struct rk1808_clk_priv *priv, 717 ulong clk_id, ulong hz) 718 { 719 struct rk1808_cru *cru = priv->cru; 720 int src_clk_div; 721 722 /* 723 * select gpll as pd_bus bus clock source and 724 * set up dependent divisors for PCLK/HCLK and ACLK clocks. 725 */ 726 switch (clk_id) { 727 case HSCLK_BUS_PRE: 728 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 729 assert(src_clk_div - 1 < 31); 730 rk_clrsetreg(&cru->clksel_con[27], 731 CLK_BUS_PLL_SEL_MASK | HSCLK_BUS_DIV_CON_MASK, 732 CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT | 733 (src_clk_div - 1) << HSCLK_BUS_DIV_CON_SHIFT); 734 break; 735 case MSCLK_BUS_PRE: 736 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 737 assert(src_clk_div - 1 < 31); 738 rk_clrsetreg(&cru->clksel_con[28], 739 CLK_BUS_PLL_SEL_MASK | MSCLK_BUS_DIV_CON_MASK, 740 CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT | 741 (src_clk_div - 1) << MSCLK_BUS_DIV_CON_SHIFT); 742 break; 743 case LSCLK_BUS_PRE: 744 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 745 assert(src_clk_div - 1 < 31); 746 rk_clrsetreg(&cru->clksel_con[28], 747 CLK_BUS_PLL_SEL_MASK | LSCLK_BUS_DIV_CON_MASK, 748 CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT | 749 (src_clk_div - 1) << LSCLK_BUS_DIV_CON_SHIFT); 750 break; 751 default: 752 printf("do not support this bus freq\n"); 753 return -EINVAL; 754 } 755 756 return rk1808_bus_get_clk(priv, clk_id); 757 } 758 759 static ulong rk1808_peri_get_clk(struct rk1808_clk_priv *priv, ulong clk_id) 760 { 761 struct rk1808_cru *cru = priv->cru; 762 u32 div, con, parent; 763 764 switch (clk_id) { 765 case MSCLK_PERI: 766 con = readl(&cru->clksel_con[19]); 767 div = (con & MSCLK_PERI_DIV_CON_MASK) >> 768 MSCLK_PERI_DIV_CON_SHIFT; 769 parent = priv->gpll_hz; 770 break; 771 case LSCLK_PERI: 772 con = readl(&cru->clksel_con[19]); 773 div = (con & LSCLK_PERI_DIV_CON_MASK) >> 774 LSCLK_PERI_DIV_CON_SHIFT; 775 parent = priv->gpll_hz; 776 break; 777 default: 778 return -ENOENT; 779 } 780 781 return DIV_TO_RATE(parent, div); 782 } 783 784 static ulong rk1808_peri_set_clk(struct rk1808_clk_priv *priv, 785 ulong clk_id, ulong hz) 786 { 787 struct rk1808_cru *cru = priv->cru; 788 int src_clk_div; 789 790 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz); 791 assert(src_clk_div - 1 < 31); 792 793 /* 794 * select gpll as pd_peri bus clock source and 795 * set up dependent divisors for HCLK and ACLK clocks. 796 */ 797 switch (clk_id) { 798 case MSCLK_PERI: 799 rk_clrsetreg(&cru->clksel_con[19], 800 CLK_PERI_PLL_SEL_MASK | MSCLK_PERI_DIV_CON_MASK, 801 CLK_PERI_PLL_SEL_GPLL << CLK_PERI_PLL_SEL_SHIFT | 802 (src_clk_div - 1) << MSCLK_PERI_DIV_CON_SHIFT); 803 break; 804 case LSCLK_PERI: 805 rk_clrsetreg(&cru->clksel_con[19], 806 CLK_PERI_PLL_SEL_MASK | LSCLK_PERI_DIV_CON_MASK, 807 CLK_PERI_PLL_SEL_GPLL << CLK_PERI_PLL_SEL_SHIFT | 808 (src_clk_div - 1) << LSCLK_PERI_DIV_CON_SHIFT); 809 break; 810 default: 811 printf("do not support this peri freq\n"); 812 return -EINVAL; 813 } 814 815 return rk1808_peri_get_clk(priv, clk_id); 816 } 817 818 static ulong rk1808_pclk_pmu_set_clk(struct rk1808_clk_priv *priv, 819 ulong clk_id, ulong parent_hz, ulong hz) 820 { 821 struct rk1808_cru *cru = priv->cru; 822 int src_clk_div; 823 824 src_clk_div = DIV_ROUND_UP(parent_hz, hz); 825 assert(src_clk_div - 1 < 31); 826 827 rk_clrsetreg(&cru->pmu_clksel_con[0], 828 PCLK_PMU_DIV_CON_MASK, 829 (src_clk_div - 1) << PCLK_PMU_DIV_CON_SHIFT); 830 831 return parent_hz / src_clk_div; 832 } 833 834 static ulong rk1808_armclk_set_clk(struct rk1808_clk_priv *priv, ulong hz) 835 { 836 struct rk1808_cru *cru = priv->cru; 837 const struct rockchip_cpu_rate_table *rate; 838 ulong old_rate; 839 840 rate = rockchip_get_cpu_settings(rk1808_cpu_rates, hz); 841 if (!rate) { 842 printf("%s unsupported rate\n", __func__); 843 return -EINVAL; 844 } 845 846 /* 847 * select apll as cpu/core clock pll source and 848 * set up dependent divisors for PERI and ACLK clocks. 849 * core hz : apll = 1:1 850 */ 851 old_rate = rockchip_pll_get_rate(&rk1808_pll_clks[APLL], 852 priv->cru, APLL); 853 if (old_rate > hz) { 854 if (rockchip_pll_set_rate(&rk1808_pll_clks[APLL], 855 priv->cru, APLL, hz)) 856 return -EINVAL; 857 rk_clrsetreg(&cru->clksel_con[0], 858 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK | 859 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK, 860 rate->aclk_div << CORE_ACLK_DIV_SHIFT | 861 rate->pclk_div << CORE_DBG_DIV_SHIFT | 862 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 863 0 << CORE_DIV_CON_SHIFT); 864 } else if (old_rate < hz) { 865 rk_clrsetreg(&cru->clksel_con[0], 866 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK | 867 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK, 868 rate->aclk_div << CORE_ACLK_DIV_SHIFT | 869 rate->pclk_div << CORE_DBG_DIV_SHIFT | 870 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT | 871 0 << CORE_DIV_CON_SHIFT); 872 if (rockchip_pll_set_rate(&rk1808_pll_clks[APLL], 873 priv->cru, APLL, hz)) 874 return -EINVAL; 875 } 876 877 return rockchip_pll_get_rate(&rk1808_pll_clks[APLL], priv->cru, APLL); 878 } 879 880 static ulong rk1808_clk_get_rate(struct clk *clk) 881 { 882 struct rk1808_clk_priv *priv = dev_get_priv(clk->dev); 883 ulong rate = 0; 884 885 debug("%s %ld\n", __func__, clk->id); 886 switch (clk->id) { 887 case PLL_APLL: 888 case PLL_DPLL: 889 case PLL_CPLL: 890 case PLL_GPLL: 891 case PLL_NPLL: 892 case PLL_PPLL: 893 rate = rockchip_pll_get_rate(&rk1808_pll_clks[clk->id - 1], 894 priv->cru, clk->id - 1); 895 break; 896 case ARMCLK: 897 rate = rockchip_pll_get_rate(&rk1808_pll_clks[APLL], 898 priv->cru, APLL); 899 break; 900 case HCLK_SDMMC: 901 case HCLK_EMMC: 902 case HCLK_SDIO: 903 case SCLK_SDMMC: 904 case SCLK_EMMC: 905 case SCLK_EMMC_SAMPLE: 906 case SCLK_SDIO: 907 rate = rk1808_mmc_get_clk(priv, clk->id); 908 break; 909 #ifndef CONFIG_SPL_BUILD 910 case SCLK_PMU_I2C0: 911 case SCLK_I2C1: 912 case SCLK_I2C2: 913 case SCLK_I2C3: 914 case SCLK_I2C4: 915 case SCLK_I2C5: 916 rate = rk1808_i2c_get_clk(priv, clk->id); 917 break; 918 case SCLK_PWM0: 919 case SCLK_PWM1: 920 case SCLK_PWM2: 921 rate = rk1808_pwm_get_clk(priv, clk->id); 922 break; 923 case SCLK_SARADC: 924 rate = rk1808_saradc_get_clk(priv); 925 break; 926 case SCLK_TSADC: 927 rate = rk1808_tsadc_get_clk(priv); 928 break; 929 case SCLK_SPI0: 930 case SCLK_SPI1: 931 case SCLK_SPI2: 932 rate = rk1808_spi_get_clk(priv, clk->id); 933 break; 934 case ACLK_VOPRAW: 935 case DCLK_VOPRAW: 936 case ACLK_VOPLITE: 937 case DCLK_VOPLITE: 938 rate = rk1808_vop_get_clk(priv, clk->id); 939 break; 940 case SCLK_CRYPTO: 941 case SCLK_CRYPTO_APK: 942 rate = rk1808_crypto_get_clk(priv, clk->id); 943 break; 944 #endif 945 case HSCLK_BUS_PRE: 946 case MSCLK_BUS_PRE: 947 case LSCLK_BUS_PRE: 948 case PCLK_WDT: 949 rate = rk1808_bus_get_clk(priv, clk->id); 950 break; 951 case MSCLK_PERI: 952 case LSCLK_PERI: 953 rate = rk1808_peri_get_clk(priv, clk->id); 954 break; 955 default: 956 return -ENOENT; 957 } 958 959 return rate; 960 } 961 962 static ulong rk1808_clk_set_rate(struct clk *clk, ulong rate) 963 { 964 struct rk1808_clk_priv *priv = dev_get_priv(clk->dev); 965 ulong ret = 0; 966 967 debug("%s %ld %ld\n", __func__, clk->id, rate); 968 switch (clk->id) { 969 case PLL_APLL: 970 case PLL_DPLL: 971 ret = rockchip_pll_set_rate(&rk1808_pll_clks[clk->id - 1], 972 priv->cru, clk->id - 1, rate); 973 break; 974 case PLL_PPLL: 975 ret = rk1808_pclk_pmu_set_clk(priv, clk->id, rate, PCLK_PMU_HZ); 976 ret = rockchip_pll_set_rate(&rk1808_pll_clks[PPLL], 977 priv->cru, PPLL, rate); 978 break; 979 case PLL_CPLL: 980 ret = rockchip_pll_set_rate(&rk1808_pll_clks[CPLL], 981 priv->cru, CPLL, rate); 982 if (ret == 0) 983 priv->cpll_hz = rate; 984 break; 985 case PLL_GPLL: 986 ret = rockchip_pll_set_rate(&rk1808_pll_clks[GPLL], 987 priv->cru, GPLL, rate); 988 if (ret == 0) 989 priv->gpll_hz = rate; 990 break; 991 case PLL_NPLL: 992 ret = rockchip_pll_set_rate(&rk1808_pll_clks[NPLL], 993 priv->cru, NPLL, rate); 994 if (ret == 0) 995 priv->npll_hz = rate; 996 break; 997 case ARMCLK: 998 if (priv->armclk_hz) 999 rk1808_armclk_set_clk(priv, rate); 1000 priv->armclk_hz = rate; 1001 break; 1002 case HCLK_SDMMC: 1003 case HCLK_EMMC: 1004 case HCLK_SDIO: 1005 case SCLK_SDMMC: 1006 case SCLK_EMMC: 1007 case SCLK_SDIO: 1008 ret = rk1808_mmc_set_clk(priv, clk->id, rate); 1009 break; 1010 #ifndef CONFIG_SPL_BUILD 1011 case SCLK_PMU_I2C0: 1012 case SCLK_I2C1: 1013 case SCLK_I2C2: 1014 case SCLK_I2C3: 1015 case SCLK_I2C4: 1016 case SCLK_I2C5: 1017 ret = rk1808_i2c_set_clk(priv, clk->id, rate); 1018 break; 1019 case SCLK_PWM0: 1020 case SCLK_PWM1: 1021 case SCLK_PWM2: 1022 ret = rk1808_pwm_set_clk(priv, clk->id, rate); 1023 break; 1024 case SCLK_SARADC: 1025 ret = rk1808_saradc_set_clk(priv, rate); 1026 break; 1027 case SCLK_TSADC: 1028 ret = rk1808_tsadc_set_clk(priv, rate); 1029 break; 1030 case SCLK_SPI0: 1031 case SCLK_SPI1: 1032 case SCLK_SPI2: 1033 ret = rk1808_spi_set_clk(priv, clk->id, rate); 1034 break; 1035 case ACLK_VOPRAW: 1036 case DCLK_VOPRAW: 1037 case ACLK_VOPLITE: 1038 case DCLK_VOPLITE: 1039 ret = rk1808_vop_set_clk(priv, clk->id, rate); 1040 break; 1041 case SCLK_GMAC: 1042 case SCLK_GMAC_SRC: 1043 ret = rk1808_mac_set_clk(clk, rate); 1044 break; 1045 case SCLK_GMAC_RMII_SPEED: 1046 case SCLK_GMAC_RGMII_SPEED: 1047 ret = rk1808_mac_set_speed_clk(clk, clk->id, rate); 1048 break; 1049 case SCLK_CRYPTO: 1050 case SCLK_CRYPTO_APK: 1051 ret = rk1808_crypto_set_clk(priv, clk->id, rate); 1052 break; 1053 #endif 1054 case HSCLK_BUS_PRE: 1055 case MSCLK_BUS_PRE: 1056 case LSCLK_BUS_PRE: 1057 ret = rk1808_bus_set_clk(priv, clk->id, rate); 1058 break; 1059 case MSCLK_PERI: 1060 case LSCLK_PERI: 1061 ret = rk1808_peri_set_clk(priv, clk->id, rate); 1062 break; 1063 case SCLK_32K_IOE: 1064 return 0; 1065 default: 1066 return -ENOENT; 1067 } 1068 1069 return ret; 1070 } 1071 1072 #define ROCKCHIP_MMC_DELAY_SEL BIT(10) 1073 #define ROCKCHIP_MMC_DEGREE_MASK 0x3 1074 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2 1075 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 1076 1077 #define PSECS_PER_SEC 1000000000000LL 1078 /* 1079 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to 1080 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. 1081 */ 1082 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 1083 1084 int rk1808_mmc_get_phase(struct clk *clk) 1085 { 1086 struct rk1808_clk_priv *priv = dev_get_priv(clk->dev); 1087 struct rk1808_cru *cru = priv->cru; 1088 u32 raw_value, delay_num; 1089 u16 degrees = 0; 1090 ulong rate; 1091 1092 rate = rk1808_clk_get_rate(clk); 1093 1094 if (rate < 0) 1095 return rate; 1096 1097 if (clk->id == SCLK_EMMC_SAMPLE) 1098 raw_value = readl(&cru->emmc_con[1]); 1099 else if (clk->id == SCLK_SDMMC_SAMPLE) 1100 raw_value = readl(&cru->sdmmc_con[1]); 1101 else 1102 raw_value = readl(&cru->sdio_con[1]); 1103 1104 raw_value >>= 1; 1105 degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; 1106 1107 if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { 1108 /* degrees/delaynum * 10000 */ 1109 unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * 1110 36 * (rate / 1000000); 1111 1112 delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); 1113 delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; 1114 degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000); 1115 } 1116 1117 return degrees % 360; 1118 } 1119 1120 int rk1808_mmc_set_phase(struct clk *clk, u32 degrees) 1121 { 1122 struct rk1808_clk_priv *priv = dev_get_priv(clk->dev); 1123 struct rk1808_cru *cru = priv->cru; 1124 u8 nineties, remainder, delay_num; 1125 u32 raw_value, delay; 1126 ulong rate; 1127 1128 rate = rk1808_clk_get_rate(clk); 1129 1130 if (rate < 0) 1131 return rate; 1132 1133 nineties = degrees / 90; 1134 remainder = (degrees % 90); 1135 1136 /* 1137 * Convert to delay; do a little extra work to make sure we 1138 * don't overflow 32-bit / 64-bit numbers. 1139 */ 1140 delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ 1141 delay *= remainder; 1142 delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 * 1143 (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); 1144 1145 delay_num = (u8)min_t(u32, delay, 255); 1146 1147 raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; 1148 raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; 1149 raw_value |= nineties; 1150 1151 raw_value <<= 1; 1152 if (clk->id == SCLK_EMMC_SAMPLE) 1153 writel(raw_value | 0xffff0000, &cru->emmc_con[1]); 1154 else if (clk->id == SCLK_SDMMC_SAMPLE) 1155 writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]); 1156 else 1157 writel(raw_value | 0xffff0000, &cru->sdio_con[1]); 1158 1159 debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n", 1160 degrees, delay_num, raw_value, rk1808_mmc_get_phase(clk)); 1161 1162 return 0; 1163 } 1164 1165 static int rk1808_clk_get_phase(struct clk *clk) 1166 { 1167 int ret; 1168 1169 debug("%s %ld\n", __func__, clk->id); 1170 switch (clk->id) { 1171 case SCLK_EMMC_SAMPLE: 1172 case SCLK_SDMMC_SAMPLE: 1173 case SCLK_SDIO_SAMPLE: 1174 ret = rk1808_mmc_get_phase(clk); 1175 break; 1176 default: 1177 return -ENOENT; 1178 } 1179 1180 return ret; 1181 } 1182 1183 static int rk1808_clk_set_phase(struct clk *clk, int degrees) 1184 { 1185 int ret; 1186 1187 debug("%s %ld\n", __func__, clk->id); 1188 switch (clk->id) { 1189 case SCLK_EMMC_SAMPLE: 1190 case SCLK_SDMMC_SAMPLE: 1191 case SCLK_SDIO_SAMPLE: 1192 ret = rk1808_mmc_set_phase(clk, degrees); 1193 break; 1194 default: 1195 return -ENOENT; 1196 } 1197 1198 return ret; 1199 } 1200 1201 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) 1202 static int rk1808_gmac_set_parent(struct clk *clk, struct clk *parent) 1203 { 1204 struct rk1808_clk_priv *priv = dev_get_priv(clk->dev); 1205 struct rk1808_cru *cru = priv->cru; 1206 1207 if (parent->id == SCLK_GMAC_SRC) { 1208 debug("%s: switching GAMC to SCLK_GMAC_SRC\n", __func__); 1209 rk_clrsetreg(&cru->clksel_con[27], RMII_EXTCLK_SEL_MASK, 1210 RMII_EXTCLK_SEL_INT << RMII_EXTCLK_SEL_SHIFT); 1211 } else { 1212 debug("%s: switching GMAC to external clock\n", __func__); 1213 rk_clrsetreg(&cru->clksel_con[27], RMII_EXTCLK_SEL_MASK, 1214 RMII_EXTCLK_SEL_EXT << RMII_EXTCLK_SEL_SHIFT); 1215 } 1216 return 0; 1217 } 1218 1219 static int rk1808_clk_set_parent(struct clk *clk, struct clk *parent) 1220 { 1221 switch (clk->id) { 1222 case SCLK_GMAC: 1223 return rk1808_gmac_set_parent(clk, parent); 1224 case SCLK_32K_IOE: 1225 return 0; 1226 default: 1227 return -ENOENT; 1228 } 1229 } 1230 #endif 1231 1232 static struct clk_ops rk1808_clk_ops = { 1233 .get_rate = rk1808_clk_get_rate, 1234 .set_rate = rk1808_clk_set_rate, 1235 .get_phase = rk1808_clk_get_phase, 1236 .set_phase = rk1808_clk_set_phase, 1237 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) 1238 .set_parent = rk1808_clk_set_parent, 1239 #endif 1240 }; 1241 1242 static int rk1808_clk_probe(struct udevice *dev) 1243 { 1244 struct rk1808_clk_priv *priv = dev_get_priv(dev); 1245 int ret; 1246 1247 priv->sync_kernel = false; 1248 if (!priv->armclk_enter_hz) { 1249 priv->armclk_enter_hz = 1250 rockchip_pll_get_rate(&rk1808_pll_clks[APLL], 1251 priv->cru, APLL); 1252 priv->armclk_init_hz = priv->armclk_enter_hz; 1253 } 1254 if (rockchip_pll_get_rate(&rk1808_pll_clks[APLL], 1255 priv->cru, APLL) != APLL_HZ) { 1256 ret = rk1808_armclk_set_clk(priv, APLL_HZ); 1257 if (ret < 0) 1258 printf("%s failed to set armclk rate\n", __func__); 1259 priv->armclk_init_hz = APLL_HZ; 1260 } 1261 1262 priv->cpll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[CPLL], 1263 priv->cru, CPLL); 1264 priv->gpll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[GPLL], 1265 priv->cru, GPLL); 1266 priv->npll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL], 1267 priv->cru, NPLL); 1268 1269 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 1270 ret = clk_set_defaults(dev); 1271 if (ret) 1272 debug("%s clk_set_defaults failed %d\n", __func__, ret); 1273 else 1274 priv->sync_kernel = true; 1275 1276 return 0; 1277 } 1278 1279 static int rk1808_clk_ofdata_to_platdata(struct udevice *dev) 1280 { 1281 struct rk1808_clk_priv *priv = dev_get_priv(dev); 1282 1283 priv->cru = dev_read_addr_ptr(dev); 1284 1285 return 0; 1286 } 1287 1288 static int rk1808_clk_bind(struct udevice *dev) 1289 { 1290 int ret; 1291 struct udevice *sys_child, *sf_child; 1292 struct sysreset_reg *priv; 1293 struct softreset_reg *sf_priv; 1294 1295 /* The reset driver does not have a device node, so bind it here */ 1296 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 1297 &sys_child); 1298 if (ret) { 1299 debug("Warning: No sysreset driver: ret=%d\n", ret); 1300 } else { 1301 priv = malloc(sizeof(struct sysreset_reg)); 1302 priv->glb_srst_fst_value = offsetof(struct rk1808_cru, 1303 glb_srst_fst); 1304 priv->glb_srst_snd_value = offsetof(struct rk1808_cru, 1305 glb_srst_snd); 1306 sys_child->priv = priv; 1307 } 1308 1309 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 1310 dev_ofnode(dev), &sf_child); 1311 if (ret) { 1312 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 1313 } else { 1314 sf_priv = malloc(sizeof(struct softreset_reg)); 1315 sf_priv->sf_reset_offset = offsetof(struct rk1808_cru, 1316 softrst_con[0]); 1317 sf_priv->sf_reset_num = 16; 1318 sf_child->priv = sf_priv; 1319 } 1320 1321 return 0; 1322 } 1323 1324 static const struct udevice_id rk1808_clk_ids[] = { 1325 { .compatible = "rockchip,rk1808-cru" }, 1326 { } 1327 }; 1328 1329 U_BOOT_DRIVER(rockchip_rk1808_cru) = { 1330 .name = "rockchip_rk1808_cru", 1331 .id = UCLASS_CLK, 1332 .of_match = rk1808_clk_ids, 1333 .priv_auto_alloc_size = sizeof(struct rk1808_clk_priv), 1334 .ofdata_to_platdata = rk1808_clk_ofdata_to_platdata, 1335 .ops = &rk1808_clk_ops, 1336 .bind = rk1808_clk_bind, 1337 .probe = rk1808_clk_probe, 1338 }; 1339 1340 #ifndef CONFIG_SPL_BUILD 1341 /** 1342 * soc_clk_dump() - Print clock frequencies 1343 * Returns zero on success 1344 * 1345 * Implementation for the clk dump command. 1346 */ 1347 int soc_clk_dump(void) 1348 { 1349 struct udevice *cru_dev; 1350 struct rk1808_clk_priv *priv; 1351 const struct rk1808_clk_info *clk_dump; 1352 struct clk clk; 1353 unsigned long clk_count = ARRAY_SIZE(clks_dump); 1354 unsigned long rate; 1355 int i, ret; 1356 1357 ret = uclass_get_device_by_driver(UCLASS_CLK, 1358 DM_GET_DRIVER(rockchip_rk1808_cru), 1359 &cru_dev); 1360 if (ret) { 1361 printf("%s failed to get cru device\n", __func__); 1362 return ret; 1363 } 1364 1365 priv = dev_get_priv(cru_dev); 1366 printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n", 1367 priv->sync_kernel ? "sync kernel" : "uboot", 1368 priv->armclk_enter_hz / 1000, 1369 priv->armclk_init_hz / 1000, 1370 priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0, 1371 priv->set_armclk_rate ? " KHz" : "N/A"); 1372 1373 for (i = 0; i < clk_count; i++) { 1374 clk_dump = &clks_dump[i]; 1375 if (clk_dump->name) { 1376 clk.id = clk_dump->id; 1377 if (clk_dump->is_cru) 1378 ret = clk_request(cru_dev, &clk); 1379 if (ret < 0) 1380 return ret; 1381 1382 rate = clk_get_rate(&clk); 1383 clk_free(&clk); 1384 if (i == 0) { 1385 if (rate < 0) 1386 printf(" %s %s\n", clk_dump->name, 1387 "unknown"); 1388 else 1389 printf(" %s %lu KHz\n", clk_dump->name, 1390 rate / 1000); 1391 } else { 1392 if (rate < 0) 1393 printf(" %s %s\n", clk_dump->name, 1394 "unknown"); 1395 else 1396 printf(" %s %lu KHz\n", clk_dump->name, 1397 rate / 1000); 1398 } 1399 } 1400 } 1401 1402 return 0; 1403 } 1404 #endif 1405