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