1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2023 Rockchip Electronics Co., Ltd 4 * Author: Finley Xiao <finley.xiao@rock-chips.com> 5 */ 6 7 #include <common.h> 8 #include <clk-uclass.h> 9 #include <dm.h> 10 #include <syscon.h> 11 #include <asm/arch/clock.h> 12 #include <asm/arch/cru_rk3506.h> 13 #include <asm/arch/grf_rk3506.h> 14 #include <asm/arch/hardware.h> 15 #include <asm/io.h> 16 #include <dm/lists.h> 17 #include <dt-bindings/clock/rockchip,rk3506-cru.h> 18 19 DECLARE_GLOBAL_DATA_PTR; 20 21 #define RK3506_CRU_BASE 0xFF9A0000 22 #define RK3506_SCRU_BASE 0xFF9A8000 23 24 #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1)) 25 26 /* 27 * [FRAC PLL]: GPLL, V0PLL, V1PLL 28 * - VCO Frequency: 950MHz to 3800MHZ 29 * - Output Frequency: 19MHz to 3800MHZ 30 * - refdiv: 1 to 63 (Int Mode), 1 to 2 (Frac Mode) 31 * - fbdiv: 16 to 3800 (Int Mode), 20 to 380 (Frac Mode) 32 * - post1div: 1 to 7 33 * - post2div: 1 to 7 34 */ 35 static struct rockchip_pll_rate_table rk3506_pll_rates[] = { 36 /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ 37 RK3036_PLL_RATE(1896000000, 1, 79, 1, 1, 1, 0), 38 RK3036_PLL_RATE(1800000000, 1, 75, 1, 1, 1, 0), 39 RK3036_PLL_RATE(1704000000, 1, 71, 1, 1, 1, 0), 40 RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0), 41 RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0), 42 RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0), 43 RK3036_PLL_RATE(1350000000, 4, 225, 1, 1, 1, 0), 44 RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0), 45 RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), 46 RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0), 47 RK3036_PLL_RATE(1179648000, 1, 49, 1, 1, 0, 2550137), 48 RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), 49 RK3036_PLL_RATE(1000000000, 3, 125, 1, 1, 1, 0), 50 RK3036_PLL_RATE(993484800, 1, 41, 1, 1, 0, 6630355), 51 RK3036_PLL_RATE(983040000, 1, 40, 1, 1, 0, 16106127), 52 RK3036_PLL_RATE(960000000, 1, 80, 2, 1, 1, 0), 53 RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0), 54 RK3036_PLL_RATE(903168000, 1, 75, 2, 1, 0, 4429185), 55 RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0), 56 RK3036_PLL_RATE(800000000, 3, 200, 2, 1, 1, 0), 57 RK3036_PLL_RATE(600000000, 1, 50, 2, 1, 1, 0), 58 RK3036_PLL_RATE(594000000, 2, 99, 2, 1, 1, 0), 59 RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0), 60 RK3036_PLL_RATE(312000000, 1, 78, 6, 1, 1, 0), 61 RK3036_PLL_RATE(216000000, 1, 72, 4, 2, 1, 0), 62 RK3036_PLL_RATE(96000000, 1, 48, 6, 2, 1, 0), 63 { /* sentinel */ }, 64 }; 65 66 static struct rockchip_pll_clock rk3506_pll_clks[] = { 67 [GPLL] = PLL(pll_rk3328, PLL_GPLL, RK3506_PLL_CON(0), 68 RK3506_MODE_CON, 0, 10, 0, rk3506_pll_rates), 69 [V0PLL] = PLL(pll_rk3328, PLL_V0PLL, RK3506_PLL_CON(8), 70 RK3506_MODE_CON, 2, 10, 0, rk3506_pll_rates), 71 [V1PLL] = PLL(pll_rk3328, PLL_V1PLL, RK3506_PLL_CON(16), 72 RK3506_MODE_CON, 4, 10, 0, rk3506_pll_rates), 73 }; 74 75 #define RK3506_CPUCLK_RATE(_rate, _aclk_m_core, _pclk_dbg) \ 76 { \ 77 .rate = _rate##U, \ 78 .aclk_div = _aclk_m_core, \ 79 .pclk_div = _pclk_dbg, \ 80 } 81 82 /* SIGN-OFF: aclk_core: 500M, pclk_core: 125M, */ 83 static struct rockchip_cpu_rate_table rk3506_cpu_rates[] = { 84 RK3506_CPUCLK_RATE(1179648000, 1, 6), 85 RK3506_CPUCLK_RATE(903168000, 1, 5), 86 RK3506_CPUCLK_RATE(800000000, 1, 4), 87 RK3506_CPUCLK_RATE(589824000, 1, 3), 88 RK3506_CPUCLK_RATE(400000000, 1, 2), 89 RK3506_CPUCLK_RATE(200000000, 1, 1), 90 { /* sentinel */ }, 91 }; 92 93 #ifndef CONFIG_SPL_BUILD 94 #define RK3506_CLK_DUMP(_id, _name) \ 95 { \ 96 .id = _id, \ 97 .name = _name, \ 98 } 99 100 static const struct rk3506_clk_info clks_dump[] = { 101 RK3506_CLK_DUMP(PLL_GPLL, "gpll"), 102 RK3506_CLK_DUMP(PLL_V0PLL, "v0pll"), 103 RK3506_CLK_DUMP(PLL_V1PLL, "v1pll"), 104 RK3506_CLK_DUMP(CLK_GPLL_DIV, "clk_gpll_div"), 105 RK3506_CLK_DUMP(CLK_GPLL_DIV_100M, "clk_gpll_div_100m"), 106 RK3506_CLK_DUMP(CLK_V0PLL_DIV, "clk_v0pll_div"), 107 RK3506_CLK_DUMP(CLK_V1PLL_DIV, "clk_v1pll_div"), 108 RK3506_CLK_DUMP(ACLK_BUS_ROOT, "aclk_bus_root"), 109 RK3506_CLK_DUMP(HCLK_BUS_ROOT, "hclk_bus_root"), 110 RK3506_CLK_DUMP(PCLK_BUS_ROOT, "pclk_bus_root"), 111 RK3506_CLK_DUMP(ACLK_HSPERI_ROOT, "aclk_hsperi_root"), 112 RK3506_CLK_DUMP(HCLK_LSPERI_ROOT, "hclk_ksperi_root"), 113 }; 114 115 /** 116 * soc_clk_dump() - Print clock frequencies 117 * Returns zero on success 118 * 119 * Implementation for the clk dump command. 120 */ 121 int soc_clk_dump(void) 122 { 123 const struct rk3506_clk_info *clk_dump; 124 struct rk3506_clk_priv *priv; 125 struct udevice *cru_dev; 126 struct clk clk; 127 ulong clk_count = ARRAY_SIZE(clks_dump); 128 ulong rate; 129 int i, ret; 130 u32 sel; 131 132 ret = uclass_get_device_by_driver(UCLASS_CLK, 133 DM_GET_DRIVER(rockchip_rk3506_cru), 134 &cru_dev); 135 if (ret) { 136 printf("%s failed to get cru device\n", __func__); 137 return ret; 138 } 139 140 priv = dev_get_priv(cru_dev); 141 sel = (readl(&priv->cru->clksel_con[15]) & 142 CLK_CORE_SRC_PVTMUX_SEL_MASK) >> 143 CLK_CORE_SRC_PVTMUX_SEL_SHIFT; 144 if (sel == CLK_CORE_PVTPLL_SRC) 145 printf("CLK: (arm clk use pvtpll, rate = 1200M)\n"); 146 else 147 printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n", 148 priv->sync_kernel ? "sync kernel" : "uboot", 149 priv->armclk_enter_hz / 1000, 150 priv->armclk_init_hz / 1000, 151 priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0, 152 priv->set_armclk_rate ? " KHz" : "N/A"); 153 for (i = 0; i < clk_count; i++) { 154 clk_dump = &clks_dump[i]; 155 if (clk_dump->name) { 156 clk.id = clk_dump->id; 157 ret = clk_request(cru_dev, &clk); 158 if (ret < 0) 159 return ret; 160 161 rate = clk_get_rate(&clk); 162 clk_free(&clk); 163 if (i == 0) { 164 if (rate < 0) 165 printf(" %s %s\n", clk_dump->name, 166 "unknown"); 167 else 168 printf(" %s %lu KHz\n", clk_dump->name, 169 rate / 1000); 170 } else { 171 if (rate < 0) 172 printf(" %s %s\n", clk_dump->name, 173 "unknown"); 174 else 175 printf(" %s %lu KHz\n", clk_dump->name, 176 rate / 1000); 177 } 178 } 179 } 180 181 return 0; 182 } 183 #endif 184 185 static int rk3506_armclk_get_rate(struct rk3506_clk_priv *priv) 186 { 187 struct rk3506_cru *cru = priv->cru; 188 u32 sel, con, div; 189 ulong prate; 190 191 con = readl(&cru->clksel_con[15]); 192 sel = (con & CLK_CORE_SRC_SEL_MASK) >> CLK_CORE_SRC_SEL_SHIFT; 193 div = (con & CLK_CORE_SRC_DIV_MASK) >> CLK_CORE_SRC_DIV_SHIFT; 194 195 if (sel == CLK_CORE_SEL_GPLL) 196 prate = priv->gpll_hz; 197 else if (sel == CLK_CORE_SEL_V0PLL) 198 prate = priv->v0pll_hz; 199 else if (sel == CLK_CORE_SEL_V1PLL) 200 prate = priv->v1pll_hz; 201 else 202 return -EINVAL; 203 204 return DIV_TO_RATE(prate, div); 205 } 206 207 static int rk3506_armclk_set_rate(struct rk3506_clk_priv *priv, ulong new_rate) 208 { 209 const struct rockchip_cpu_rate_table *rate; 210 struct rk3506_cru *cru = priv->cru; 211 ulong old_rate, prate; 212 u32 con, sel, div, old_div; 213 214 rate = rockchip_get_cpu_settings(rk3506_cpu_rates, new_rate); 215 if (!rate) { 216 printf("%s unsupported rate\n", __func__); 217 return -EINVAL; 218 } 219 220 /* 221 * set up dependent divisors for PCLK and ACLK clocks. 222 */ 223 old_rate = rk3506_armclk_get_rate(priv); 224 if (new_rate >= old_rate) { 225 rk_clrsetreg(&cru->clksel_con[15], ACLK_CORE_DIV_MASK, 226 rate->aclk_div << ACLK_CORE_DIV_SHIFT); 227 rk_clrsetreg(&cru->clksel_con[16], PCLK_CORE_DIV_MASK, 228 rate->pclk_div << PCLK_CORE_DIV_SHIFT); 229 } 230 231 if (new_rate == 589824000 || new_rate == 1179648000) { 232 sel = CLK_CORE_SEL_V0PLL; 233 div = DIV_ROUND_UP(priv->v0pll_hz, new_rate); 234 prate = priv->v0pll_hz; 235 } else if (new_rate == 903168000) { 236 sel = CLK_CORE_SEL_V1PLL; 237 div = DIV_ROUND_UP(priv->v1pll_hz, new_rate); 238 prate = priv->v1pll_hz; 239 } else { 240 sel = CLK_CORE_SEL_GPLL; 241 div = DIV_ROUND_UP(priv->gpll_hz, new_rate); 242 prate = priv->gpll_hz; 243 } 244 assert(div - 1 <= 31); 245 246 con = readl(&cru->clksel_con[15]); 247 old_div = (con & CLK_CORE_SRC_DIV_MASK) >> CLK_CORE_SRC_DIV_SHIFT; 248 if (DIV_TO_RATE(prate, old_div) > new_rate) { 249 rk_clrsetreg(&cru->clksel_con[15], CLK_CORE_SRC_DIV_MASK, 250 (div - 1) << CLK_CORE_SRC_DIV_SHIFT); 251 rk_clrsetreg(&cru->clksel_con[15], CLK_CORE_SRC_SEL_MASK, 252 sel << CLK_CORE_SRC_SEL_SHIFT); 253 } else { 254 rk_clrsetreg(&cru->clksel_con[15], CLK_CORE_SRC_SEL_MASK, 255 sel << CLK_CORE_SRC_SEL_SHIFT); 256 rk_clrsetreg(&cru->clksel_con[15], CLK_CORE_SRC_DIV_MASK, 257 (div - 1) << CLK_CORE_SRC_DIV_SHIFT); 258 } 259 260 if (new_rate < old_rate) { 261 rk_clrsetreg(&cru->clksel_con[15], ACLK_CORE_DIV_MASK, 262 rate->aclk_div << ACLK_CORE_DIV_SHIFT); 263 rk_clrsetreg(&cru->clksel_con[16], PCLK_CORE_DIV_MASK, 264 rate->pclk_div << PCLK_CORE_DIV_SHIFT); 265 } 266 267 return 0; 268 } 269 270 static ulong rk3506_pll_div_get_rate(struct rk3506_clk_priv *priv, ulong clk_id) 271 { 272 struct rk3506_cru *cru = priv->cru; 273 u32 con, div; 274 ulong prate; 275 276 switch (clk_id) { 277 case CLK_GPLL_DIV: 278 con = readl(&cru->clksel_con[0]); 279 div = (con & CLK_GPLL_DIV_MASK) >> CLK_GPLL_DIV_SHIFT; 280 prate = priv->gpll_hz; 281 break; 282 case CLK_GPLL_DIV_100M: 283 con = readl(&cru->clksel_con[0]); 284 div = (con & CLK_GPLL_DIV_100M_MASK) >> CLK_GPLL_DIV_100M_SHIFT; 285 prate = priv->gpll_div_hz; 286 break; 287 case CLK_V0PLL_DIV: 288 con = readl(&cru->clksel_con[1]); 289 div = (con & CLK_V0PLL_DIV_MASK) >> CLK_V0PLL_DIV_SHIFT; 290 prate = priv->v0pll_hz; 291 break; 292 case CLK_V1PLL_DIV: 293 con = readl(&cru->clksel_con[1]); 294 div = (con & CLK_V1PLL_DIV_MASK) >> CLK_V1PLL_DIV_SHIFT; 295 prate = priv->v1pll_hz; 296 break; 297 default: 298 return -ENOENT; 299 } 300 301 return DIV_TO_RATE(prate, div); 302 } 303 304 static ulong rk3506_pll_div_set_rate(struct rk3506_clk_priv *priv, ulong clk_id, 305 ulong rate) 306 { 307 struct rk3506_cru *cru = priv->cru; 308 u32 div; 309 310 switch (clk_id) { 311 case CLK_GPLL_DIV: 312 div = DIV_ROUND_UP(priv->gpll_hz, rate); 313 assert(div - 1 <= 15); 314 rk_clrsetreg(&cru->clksel_con[0], CLK_GPLL_DIV_MASK, 315 ((div - 1) << CLK_GPLL_DIV_SHIFT)); 316 break; 317 case CLK_GPLL_DIV_100M: 318 div = DIV_ROUND_UP(priv->gpll_div_hz, rate); 319 assert(div - 1 <= 15); 320 rk_clrsetreg(&cru->clksel_con[0], CLK_GPLL_DIV_100M_MASK, 321 ((div - 1) << CLK_GPLL_DIV_100M_SHIFT)); 322 break; 323 case CLK_V0PLL_DIV: 324 div = DIV_ROUND_UP(priv->v0pll_hz, rate); 325 assert(div - 1 <= 15); 326 rk_clrsetreg(&cru->clksel_con[1], CLK_V0PLL_DIV_MASK, 327 ((div - 1) << CLK_V0PLL_DIV_SHIFT)); 328 break; 329 case CLK_V1PLL_DIV: 330 div = DIV_ROUND_UP(priv->v1pll_hz, rate); 331 assert(div - 1 <= 15); 332 rk_clrsetreg(&cru->clksel_con[1], CLK_V1PLL_DIV_MASK, 333 ((div - 1) << CLK_V1PLL_DIV_SHIFT)); 334 break; 335 default: 336 return -ENOENT; 337 } 338 339 return rk3506_pll_div_get_rate(priv, clk_id); 340 } 341 342 static ulong rk3506_bus_get_rate(struct rk3506_clk_priv *priv, ulong clk_id) 343 { 344 struct rk3506_cru *cru = priv->cru; 345 u32 sel, con, div; 346 ulong prate; 347 348 switch (clk_id) { 349 case ACLK_BUS_ROOT: 350 con = readl(&cru->clksel_con[21]); 351 sel = (con & ACLK_BUS_SEL_MASK) >> ACLK_BUS_SEL_SHIFT; 352 div = (con & ACLK_BUS_DIV_MASK) >> ACLK_BUS_DIV_SHIFT; 353 break; 354 case HCLK_BUS_ROOT: 355 con = readl(&cru->clksel_con[21]); 356 sel = (con & HCLK_BUS_SEL_MASK) >> HCLK_BUS_SEL_SHIFT; 357 div = (con & HCLK_BUS_DIV_MASK) >> HCLK_BUS_DIV_SHIFT; 358 break; 359 case PCLK_BUS_ROOT: 360 con = readl(&cru->clksel_con[22]); 361 sel = (con & PCLK_BUS_SEL_MASK) >> PCLK_BUS_SEL_SHIFT; 362 div = (con & PCLK_BUS_DIV_MASK) >> PCLK_BUS_DIV_SHIFT; 363 break; 364 default: 365 return -ENOENT; 366 } 367 368 if (sel == ACLK_BUS_SEL_GPLL_DIV) 369 prate = priv->gpll_div_hz; 370 else if (sel == ACLK_BUS_SEL_V0PLL_DIV) 371 prate = priv->v0pll_div_hz; 372 else if (sel == ACLK_BUS_SEL_V1PLL_DIV) 373 prate = priv->v1pll_div_hz; 374 else 375 return -EINVAL; 376 377 return DIV_TO_RATE(prate, div); 378 } 379 380 static ulong rk3506_bus_set_rate(struct rk3506_clk_priv *priv, ulong clk_id, 381 ulong rate) 382 { 383 struct rk3506_cru *cru = priv->cru; 384 u32 sel, div; 385 386 if (priv->v0pll_div_hz % rate == 0) { 387 sel = ACLK_BUS_SEL_V0PLL_DIV; 388 div = DIV_ROUND_UP(priv->v0pll_div_hz, rate); 389 } else if (priv->v1pll_div_hz % rate == 0) { 390 sel= ACLK_BUS_SEL_V1PLL_DIV; 391 div = DIV_ROUND_UP(priv->v1pll_div_hz, rate); 392 } else { 393 sel= ACLK_BUS_SEL_GPLL_DIV; 394 div = DIV_ROUND_UP(priv->gpll_div_hz, rate); 395 } 396 assert(div - 1 <= 31); 397 398 switch (clk_id) { 399 case ACLK_BUS_ROOT: 400 rk_clrsetreg(&cru->clksel_con[21], 401 ACLK_BUS_DIV_MASK | ACLK_BUS_SEL_MASK, 402 (sel << ACLK_BUS_SEL_SHIFT) | 403 ((div - 1) << ACLK_BUS_DIV_SHIFT)); 404 break; 405 case HCLK_BUS_ROOT: 406 rk_clrsetreg(&cru->clksel_con[21], 407 HCLK_BUS_SEL_MASK | HCLK_BUS_DIV_MASK, 408 (sel << HCLK_BUS_SEL_SHIFT) | 409 ((div - 1) << HCLK_BUS_DIV_SHIFT)); 410 break; 411 case PCLK_BUS_ROOT: 412 rk_clrsetreg(&cru->clksel_con[22], 413 PCLK_BUS_SEL_MASK | PCLK_BUS_DIV_MASK, 414 (sel << PCLK_BUS_SEL_SHIFT) | 415 ((div - 1) << PCLK_BUS_DIV_SHIFT)); 416 break; 417 default: 418 return -ENOENT; 419 } 420 421 return rk3506_bus_get_rate(priv, clk_id); 422 } 423 424 static ulong rk3506_peri_get_rate(struct rk3506_clk_priv *priv, ulong clk_id) 425 { 426 struct rk3506_cru *cru = priv->cru; 427 u32 sel, con, div; 428 ulong prate; 429 430 switch (clk_id) { 431 case ACLK_HSPERI_ROOT: 432 con = readl(&cru->clksel_con[49]); 433 sel = (con & ACLK_HSPERI_SEL_MASK) >> ACLK_HSPERI_SEL_SHIFT; 434 div = (con & ACLK_HSPERI_DIV_MASK) >> ACLK_HSPERI_DIV_SHIFT; 435 break; 436 case HCLK_LSPERI_ROOT: 437 con = readl(&cru->clksel_con[29]); 438 sel = (con & HCLK_LSPERI_SEL_MASK) >> HCLK_LSPERI_SEL_SHIFT; 439 div = (con & HCLK_LSPERI_DIV_MASK) >> HCLK_LSPERI_DIV_SHIFT; 440 break; 441 default: 442 return -ENOENT; 443 } 444 445 if (sel == ACLK_HSPERI_SEL_GPLL_DIV) 446 prate = priv->gpll_div_hz; 447 else if (sel == ACLK_HSPERI_SEL_V0PLL_DIV) 448 prate = priv->v0pll_div_hz; 449 else if (sel == ACLK_HSPERI_SEL_V1PLL_DIV) 450 prate = priv->v1pll_div_hz; 451 else 452 return -EINVAL; 453 454 return DIV_TO_RATE(prate, div); 455 } 456 457 static ulong rk3506_peri_set_rate(struct rk3506_clk_priv *priv, ulong clk_id, 458 ulong rate) 459 { 460 struct rk3506_cru *cru = priv->cru; 461 u32 sel, div; 462 463 if (priv->v0pll_div_hz % rate == 0) { 464 sel = ACLK_BUS_SEL_V0PLL_DIV; 465 div = DIV_ROUND_UP(priv->v0pll_div_hz, rate); 466 } else if (priv->v1pll_div_hz % rate == 0) { 467 sel = ACLK_BUS_SEL_V1PLL_DIV; 468 div = DIV_ROUND_UP(priv->v1pll_div_hz, rate); 469 } else { 470 sel = ACLK_BUS_SEL_GPLL_DIV; 471 div = DIV_ROUND_UP(priv->gpll_div_hz, rate); 472 } 473 assert(div - 1 <= 31); 474 475 switch (clk_id) { 476 case ACLK_HSPERI_ROOT: 477 rk_clrsetreg(&cru->clksel_con[49], 478 ACLK_HSPERI_SEL_MASK | ACLK_HSPERI_DIV_MASK, 479 (sel << ACLK_HSPERI_SEL_SHIFT) | 480 ((div - 1) << ACLK_HSPERI_DIV_SHIFT)); 481 break; 482 case HCLK_LSPERI_ROOT: 483 rk_clrsetreg(&cru->clksel_con[29], 484 HCLK_LSPERI_SEL_MASK | HCLK_LSPERI_DIV_MASK, 485 (sel << HCLK_LSPERI_SEL_SHIFT) | 486 ((div - 1) << HCLK_LSPERI_DIV_SHIFT)); 487 break; 488 default: 489 return -ENOENT; 490 } 491 492 return rk3506_peri_get_rate(priv, clk_id); 493 } 494 495 static ulong rk3506_sdmmc_get_rate(struct rk3506_clk_priv *priv, ulong clk_id) 496 { 497 struct rk3506_cru *cru = priv->cru; 498 u32 sel, con, div; 499 ulong prate; 500 501 con = readl(&cru->clksel_con[49]); 502 sel = (con & CCLK_SDMMC_SEL_MASK) >> CCLK_SDMMC_SEL_SHIFT; 503 div = (con & CCLK_SDMMC_DIV_MASK) >> CCLK_SDMMC_DIV_SHIFT; 504 505 if (sel == CCLK_SDMMC_SEL_24M) 506 prate = OSC_HZ; 507 else if (sel == CCLK_SDMMC_SEL_GPLL) 508 prate = priv->gpll_hz; 509 else if (sel == CCLK_SDMMC_SEL_V0PLL) 510 prate = priv->v0pll_hz; 511 else if (sel == CCLK_SDMMC_SEL_V1PLL) 512 prate = priv->v1pll_hz; 513 else 514 return -EINVAL; 515 516 return DIV_TO_RATE(prate, div); 517 } 518 519 static ulong rk3506_sdmmc_set_rate(struct rk3506_clk_priv *priv, ulong clk_id, 520 ulong rate) 521 { 522 struct rk3506_cru *cru = priv->cru; 523 u32 sel, div; 524 525 if (OSC_HZ % rate == 0) { 526 sel = CCLK_SDMMC_SEL_24M; 527 div = DIV_ROUND_UP(OSC_HZ, rate); 528 } else if (priv->v0pll_hz % rate == 0) { 529 sel = CCLK_SDMMC_SEL_V0PLL; 530 div = DIV_ROUND_UP(priv->v0pll_hz, rate); 531 } else if (priv->v1pll_hz % rate == 0) { 532 sel= CCLK_SDMMC_SEL_V1PLL; 533 div = DIV_ROUND_UP(priv->v1pll_hz, rate); 534 } else { 535 sel= CCLK_SDMMC_SEL_GPLL; 536 div = DIV_ROUND_UP(priv->gpll_hz, rate); 537 } 538 assert(div - 1 <= 63); 539 540 rk_clrsetreg(&cru->clksel_con[49], 541 CCLK_SDMMC_SEL_MASK | CCLK_SDMMC_DIV_MASK, 542 (sel << CCLK_SDMMC_SEL_SHIFT) | 543 ((div - 1) << CCLK_SDMMC_DIV_SHIFT)); 544 545 return rk3506_sdmmc_get_rate(priv, clk_id); 546 } 547 548 static ulong rk3506_saradc_get_rate(struct rk3506_clk_priv *priv, ulong clk_id) 549 { 550 struct rk3506_cru *cru = priv->cru; 551 u32 div, con, sel; 552 ulong prate; 553 554 con = readl(&cru->clksel_con[54]); 555 div = (con & CLK_SARADC_DIV_MASK) >> CLK_SARADC_DIV_SHIFT; 556 sel = (con & CLK_SARADC_SEL_MASK) >> CLK_SARADC_SEL_SHIFT; 557 558 if (sel == CLK_SARADC_SEL_24M) 559 prate = OSC_HZ; 560 else if (sel == CLK_SARADC_SEL_400K) 561 prate = 400000; 562 else if (sel == CLK_SARADC_SEL_32K) 563 prate = 32000; 564 else 565 return -EINVAL; 566 567 return DIV_TO_RATE(prate, div); 568 } 569 570 static ulong rk3506_saradc_set_rate(struct rk3506_clk_priv *priv, ulong clk_id, 571 ulong rate) 572 { 573 struct rk3506_cru *cru = priv->cru; 574 u32 div, sel; 575 576 if (32000 % rate == 0) { 577 sel = CLK_SARADC_SEL_32K; 578 div = 1; 579 } else if (400000 % rate == 0) { 580 sel = CLK_SARADC_SEL_400K; 581 div = 1; 582 } else { 583 sel= CLK_SARADC_SEL_24M; 584 div = DIV_ROUND_UP(OSC_HZ, rate); 585 } 586 assert(div - 1 <= 15); 587 588 rk_clrsetreg(&cru->clksel_con[54], 589 CLK_SARADC_SEL_MASK | CLK_SARADC_DIV_MASK, 590 (sel << CLK_SARADC_SEL_SHIFT) | 591 ((div - 1) << CLK_SARADC_DIV_SHIFT)); 592 593 return rk3506_saradc_get_rate(priv, clk_id); 594 } 595 596 static ulong rk3506_tsadc_get_rate(struct rk3506_clk_priv *priv, ulong clk_id) 597 { 598 struct rk3506_cru *cru = priv->cru; 599 u32 div, con; 600 601 con = readl(&cru->clksel_con[61]); 602 switch (clk_id) { 603 case CLK_TSADC_TSEN: 604 div = (con & CLK_TSADC_TSEN_DIV_MASK) >> CLK_TSADC_TSEN_DIV_SHIFT; 605 break; 606 case CLK_TSADC: 607 div = (con & CLK_TSADC_DIV_MASK) >> CLK_TSADC_DIV_SHIFT; 608 break; 609 default: 610 return -ENOENT; 611 } 612 613 return DIV_TO_RATE(OSC_HZ, div); 614 } 615 616 static ulong rk3506_tsadc_set_rate(struct rk3506_clk_priv *priv, ulong clk_id, 617 ulong rate) 618 { 619 struct rk3506_cru *cru = priv->cru; 620 u32 div; 621 622 switch (clk_id) { 623 case CLK_TSADC_TSEN: 624 div = DIV_ROUND_UP(OSC_HZ, rate); 625 assert(div - 1 <= 7); 626 rk_clrsetreg(&cru->clksel_con[61], CLK_TSADC_TSEN_DIV_MASK, 627 (div - 1) << CLK_TSADC_TSEN_DIV_SHIFT); 628 break; 629 case CLK_TSADC: 630 div = DIV_ROUND_UP(OSC_HZ, rate); 631 assert(div - 1 <= 255); 632 rk_clrsetreg(&cru->clksel_con[61], CLK_TSADC_DIV_MASK, 633 (div - 1) << CLK_TSADC_DIV_SHIFT); 634 break; 635 default: 636 return -ENOENT; 637 } 638 639 640 return rk3506_tsadc_get_rate(priv, clk_id); 641 } 642 643 static ulong rk3506_i2c_get_rate(struct rk3506_clk_priv *priv, ulong clk_id) 644 { 645 struct rk3506_cru *cru = priv->cru; 646 u32 sel, con, div; 647 ulong prate; 648 649 switch (clk_id) { 650 case CLK_I2C0: 651 con = readl(&cru->clksel_con[32]); 652 sel = (con & CLK_I2C0_SEL_MASK) >> CLK_I2C0_SEL_SHIFT; 653 div = (con & CLK_I2C0_DIV_MASK) >> CLK_I2C0_DIV_SHIFT; 654 case CLK_I2C1: 655 con = readl(&cru->clksel_con[32]); 656 sel = (con & CLK_I2C1_SEL_MASK) >> CLK_I2C1_SEL_SHIFT; 657 div = (con & CLK_I2C1_DIV_MASK) >> CLK_I2C1_DIV_SHIFT; 658 case CLK_I2C2: 659 con = readl(&cru->clksel_con[33]); 660 sel = (con & CLK_I2C2_SEL_MASK) >> CLK_I2C2_SEL_SHIFT; 661 div = (con & CLK_I2C2_DIV_MASK) >> CLK_I2C2_DIV_SHIFT; 662 break; 663 default: 664 return -ENOENT; 665 } 666 667 if (sel == CLK_I2C_SEL_GPLL) 668 prate = priv->gpll_hz; 669 else if (sel == CLK_I2C_SEL_V0PLL) 670 prate = priv->v0pll_hz; 671 else if (sel == CLK_I2C_SEL_V1PLL) 672 prate = priv->v1pll_hz; 673 else 674 return -EINVAL; 675 676 return DIV_TO_RATE(prate, div); 677 } 678 679 static ulong rk3506_i2c_set_rate(struct rk3506_clk_priv *priv, ulong clk_id, 680 ulong rate) 681 { 682 struct rk3506_cru *cru = priv->cru; 683 u32 sel, div; 684 685 if (priv->v0pll_hz % rate == 0) { 686 sel = CLK_I2C_SEL_V0PLL; 687 div = DIV_ROUND_UP(priv->v0pll_hz, rate); 688 } else if (priv->v1pll_hz % rate == 0) { 689 sel = CLK_I2C_SEL_V1PLL; 690 div = DIV_ROUND_UP(priv->v1pll_hz, rate); 691 } else { 692 sel = CLK_I2C_SEL_GPLL; 693 div = DIV_ROUND_UP(priv->gpll_hz, rate); 694 } 695 assert(div - 1 <= 15); 696 697 switch (clk_id) { 698 case CLK_I2C0: 699 rk_clrsetreg(&cru->clksel_con[32], 700 CLK_I2C0_SEL_MASK | CLK_I2C0_DIV_MASK, 701 (sel << CLK_I2C0_SEL_SHIFT) | 702 ((div - 1) << CLK_I2C0_DIV_SHIFT)); 703 break; 704 case CLK_I2C1: 705 rk_clrsetreg(&cru->clksel_con[32], 706 CLK_I2C1_SEL_MASK | CLK_I2C1_DIV_MASK, 707 (sel << CLK_I2C1_SEL_SHIFT) | 708 ((div - 1) << CLK_I2C1_DIV_SHIFT)); 709 break; 710 case CLK_I2C2: 711 rk_clrsetreg(&cru->clksel_con[33], 712 CLK_I2C2_SEL_MASK | CLK_I2C2_DIV_MASK, 713 (sel << CLK_I2C2_SEL_SHIFT) | 714 ((div - 1) << CLK_I2C2_DIV_SHIFT)); 715 break; 716 default: 717 return -ENOENT; 718 } 719 720 721 return rk3506_i2c_get_rate(priv, clk_id); 722 } 723 724 static ulong rk3506_pwm_get_rate(struct rk3506_clk_priv *priv, ulong clk_id) 725 { 726 struct rk3506_cru *cru = priv->cru; 727 u32 sel, con, div; 728 ulong prate; 729 730 switch (clk_id) { 731 case CLK_PWM0: 732 con = readl(&cru->pmuclksel_con[0]); 733 div = (con & CLK_PWM0_DIV_MASK) >> CLK_PWM0_DIV_SHIFT; 734 prate = priv->gpll_div_100mhz; 735 break; 736 case CLK_PWM1: 737 con = readl(&cru->clksel_con[33]); 738 sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT; 739 div = (con & CLK_PWM1_DIV_MASK) >> CLK_PWM1_DIV_SHIFT; 740 if (sel == CLK_PWM1_SEL_GPLL_DIV) 741 prate = priv->gpll_div_hz; 742 else if (sel == CLK_PWM1_SEL_V0PLL_DIV) 743 prate = priv->v0pll_div_hz; 744 else if (sel == CLK_PWM1_SEL_V1PLL_DIV) 745 prate = priv->v1pll_div_hz; 746 else 747 return -EINVAL; 748 break; 749 default: 750 return -ENOENT; 751 } 752 753 return DIV_TO_RATE(prate, div); 754 } 755 756 static ulong rk3506_pwm_set_rate(struct rk3506_clk_priv *priv, ulong clk_id, 757 ulong rate) 758 { 759 struct rk3506_cru *cru = priv->cru; 760 u32 sel, div; 761 762 switch (clk_id) { 763 case CLK_PWM0: 764 div = DIV_ROUND_UP(priv->gpll_div_100mhz, rate); 765 assert(div - 1 <= 15); 766 rk_clrsetreg(&cru->pmuclksel_con[0], CLK_PWM0_DIV_MASK, 767 (div - 1) << CLK_PWM0_DIV_SHIFT); 768 break; 769 case CLK_PWM1: 770 if (priv->v0pll_hz % rate == 0) { 771 sel = CLK_PWM1_SEL_V0PLL_DIV; 772 div = DIV_ROUND_UP(priv->v0pll_div_hz, rate); 773 } else if (priv->v1pll_hz % rate == 0) { 774 sel = CLK_PWM1_SEL_V1PLL_DIV; 775 div = DIV_ROUND_UP(priv->v1pll_div_hz, rate); 776 } else { 777 sel = CLK_PWM1_SEL_GPLL_DIV; 778 div = DIV_ROUND_UP(priv->gpll_div_hz, rate); 779 } 780 assert(div - 1 <= 15); 781 rk_clrsetreg(&cru->clksel_con[33], 782 CLK_PWM1_SEL_MASK | CLK_PWM1_DIV_MASK, 783 (sel << CLK_PWM1_SEL_SHIFT) | 784 ((div - 1) << CLK_PWM1_DIV_SHIFT)); 785 break; 786 default: 787 return -ENOENT; 788 } 789 790 return rk3506_pwm_get_rate(priv, clk_id); 791 } 792 793 static ulong rk3506_spi_get_rate(struct rk3506_clk_priv *priv, ulong clk_id) 794 { 795 struct rk3506_cru *cru = priv->cru; 796 u32 sel, con, div; 797 ulong prate; 798 799 switch (clk_id) { 800 case CLK_SPI0: 801 con = readl(&cru->clksel_con[34]); 802 sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT; 803 div = (con & CLK_SPI0_DIV_MASK) >> CLK_SPI0_DIV_SHIFT; 804 break; 805 case CLK_SPI1: 806 con = readl(&cru->clksel_con[34]); 807 sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT; 808 div = (con & CLK_SPI1_DIV_MASK) >> CLK_SPI1_DIV_SHIFT; 809 break; 810 default: 811 return -ENOENT; 812 } 813 814 if (sel == CLK_SPI_SEL_24M) 815 prate = OSC_HZ; 816 else if (sel == CLK_SPI_SEL_GPLL_DIV) 817 prate = priv->gpll_div_hz; 818 else if (sel == CLK_SPI_SEL_V0PLL_DIV) 819 prate = priv->v0pll_div_hz; 820 else if (sel == CLK_SPI_SEL_V1PLL_DIV) 821 prate = priv->v1pll_div_hz; 822 else 823 return -EINVAL; 824 825 return DIV_TO_RATE(prate, div); 826 } 827 828 static ulong rk3506_spi_set_rate(struct rk3506_clk_priv *priv, ulong clk_id, 829 ulong rate) 830 { 831 struct rk3506_cru *cru = priv->cru; 832 u32 sel, div; 833 834 if (OSC_HZ % rate == 0) { 835 sel = CLK_SPI_SEL_24M; 836 div = DIV_ROUND_UP(OSC_HZ, rate); 837 } else if (priv->v0pll_div_hz % rate == 0) { 838 sel = CLK_SPI_SEL_V0PLL_DIV; 839 div = DIV_ROUND_UP(priv->v0pll_div_hz, rate); 840 } else if (priv->v1pll_div_hz % rate == 0) { 841 sel = CLK_SPI_SEL_V1PLL_DIV; 842 div = DIV_ROUND_UP(priv->v1pll_div_hz, rate); 843 } else { 844 sel = CLK_SPI_SEL_GPLL_DIV; 845 div = DIV_ROUND_UP(priv->gpll_div_hz, rate); 846 } 847 assert(div - 1 <= 15); 848 849 switch (clk_id) { 850 case CLK_SPI0: 851 rk_clrsetreg(&cru->clksel_con[34], 852 CLK_SPI0_SEL_MASK | CLK_SPI0_DIV_MASK, 853 (sel << CLK_SPI0_SEL_SHIFT) | 854 ((div - 1) << CLK_SPI0_DIV_SHIFT)); 855 break; 856 case CLK_SPI1: 857 rk_clrsetreg(&cru->clksel_con[34], 858 CLK_SPI1_SEL_MASK | CLK_SPI1_DIV_MASK, 859 (sel << CLK_SPI1_SEL_SHIFT) | 860 ((div - 1) << CLK_SPI1_DIV_SHIFT)); 861 break; 862 default: 863 return -ENOENT; 864 } 865 866 return rk3506_spi_get_rate(priv, clk_id); 867 } 868 869 static ulong rk3506_fspi_get_rate(struct rk3506_clk_priv *priv) 870 { 871 struct rk3506_cru *cru = priv->cru; 872 u32 div, sel, con, prate; 873 874 con = readl(&cru->clksel_con[50]); 875 div = (con & SCLK_FSPI_DIV_MASK) >> SCLK_FSPI_DIV_SHIFT; 876 sel = (con & SCLK_FSPI_SEL_MASK) >> SCLK_FSPI_SEL_SHIFT; 877 if (sel == SCLK_FSPI_SEL_24M) 878 prate = OSC_HZ; 879 else if (sel == SCLK_FSPI_SEL_GPLL) 880 prate = priv->gpll_hz; 881 else if (sel == SCLK_FSPI_SEL_V0PLL) 882 prate = priv->v0pll_hz; 883 else if (sel == SCLK_FSPI_SEL_V1PLL) 884 prate = priv->v1pll_hz; 885 else 886 return -EINVAL; 887 888 return DIV_TO_RATE(prate, div); 889 } 890 891 static ulong rk3506_fspi_set_rate(struct rk3506_clk_priv *priv, ulong rate) 892 { 893 struct rk3506_cru *cru = priv->cru; 894 int div, sel; 895 896 if (OSC_HZ % rate == 0) { 897 sel = SCLK_FSPI_SEL_24M; 898 div = DIV_ROUND_UP(OSC_HZ, rate); 899 } else if ((priv->v0pll_hz % rate) == 0) { 900 sel = SCLK_FSPI_SEL_V0PLL; 901 div = DIV_ROUND_UP(priv->v0pll_hz, rate); 902 } else if ((priv->v1pll_hz % rate) == 0) { 903 sel = SCLK_FSPI_SEL_V1PLL; 904 div = DIV_ROUND_UP(priv->v1pll_hz, rate); 905 } else { 906 sel = SCLK_FSPI_SEL_GPLL; 907 div = DIV_ROUND_UP(priv->gpll_hz, rate); 908 } 909 assert(div - 1 <= 31); 910 911 rk_clrsetreg(&cru->clksel_con[50], 912 SCLK_FSPI_SEL_MASK | SCLK_FSPI_DIV_MASK, 913 sel << SCLK_FSPI_SEL_SHIFT | 914 (div - 1) << SCLK_FSPI_DIV_SHIFT); 915 916 return rk3506_fspi_get_rate(priv); 917 } 918 919 static ulong rk3506_vop_dclk_get_rate(struct rk3506_clk_priv *priv) 920 { 921 struct rk3506_cru *cru = priv->cru; 922 u32 div, sel, con, prate; 923 924 con = readl(&cru->clksel_con[60]); 925 div = (con & DCLK_VOP_DIV_MASK) >> DCLK_VOP_DIV_SHIFT; 926 sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT; 927 928 if (sel == DCLK_VOP_SEL_24M) 929 prate = OSC_HZ; 930 else if (sel == DCLK_VOP_SEL_GPLL) 931 prate = priv->gpll_hz; 932 else if (sel == DCLK_VOP_SEL_V0PLL) 933 prate = priv->v0pll_hz; 934 else if (sel == DCLK_VOP_SEL_V1PLL) 935 prate = priv->v1pll_hz; 936 else 937 return -EINVAL; 938 939 return DIV_TO_RATE(prate, div); 940 } 941 942 static ulong rk3506_vop_dclk_set_rate(struct rk3506_clk_priv *priv, ulong rate) 943 { 944 struct rk3506_cru *cru = priv->cru; 945 int div, sel; 946 947 if (OSC_HZ % rate == 0) { 948 sel = DCLK_VOP_SEL_24M; 949 div = DIV_ROUND_UP(OSC_HZ, rate); 950 } else if ((priv->v0pll_hz % rate) == 0) { 951 sel = DCLK_VOP_SEL_V0PLL; 952 div = DIV_ROUND_UP(priv->v0pll_hz, rate); 953 } else if ((priv->v1pll_hz % rate) == 0) { 954 sel = DCLK_VOP_SEL_V1PLL; 955 div = DIV_ROUND_UP(priv->v1pll_hz, rate); 956 } else { 957 sel = DCLK_VOP_SEL_GPLL; 958 div = DIV_ROUND_UP(priv->gpll_hz, rate); 959 } 960 assert(div - 1 <= 255); 961 962 rk_clrsetreg(&cru->clksel_con[60], 963 DCLK_VOP_SEL_MASK | DCLK_VOP_DIV_MASK, 964 sel << DCLK_VOP_SEL_SHIFT | 965 (div - 1) << DCLK_VOP_DIV_SHIFT); 966 967 return rk3506_vop_dclk_get_rate(priv); 968 } 969 970 static ulong rk3506_mac_get_rate(struct rk3506_clk_priv *priv, ulong clk_id) 971 { 972 struct rk3506_cru *cru = priv->cru; 973 u32 div, con; 974 975 switch (clk_id) { 976 case CLK_MAC0: 977 case CLK_MAC1: 978 con = readl(&cru->clksel_con[50]); 979 div = (con & CLK_MAC_DIV_MASK) >> CLK_MAC_DIV_SHIFT; 980 break; 981 case CLK_MAC_OUT: 982 con = readl(&cru->pmuclksel_con[0]); 983 div = (con & CLK_MAC_OUT_DIV_MASK) >> CLK_MAC_OUT_DIV_SHIFT; 984 default: 985 return -ENOENT; 986 } 987 988 return DIV_TO_RATE(priv->gpll_hz, div); 989 } 990 991 static ulong rk3506_mac_set_rate(struct rk3506_clk_priv *priv, ulong clk_id, 992 ulong rate) 993 { 994 struct rk3506_cru *cru = priv->cru; 995 u32 div; 996 997 switch (clk_id) { 998 case CLK_MAC0: 999 case CLK_MAC1: 1000 div = DIV_ROUND_UP(priv->gpll_hz, rate); 1001 rk_clrsetreg(&cru->clksel_con[50], CLK_MAC_DIV_MASK, 1002 ((div - 1) << CLK_MAC_DIV_SHIFT)); 1003 break; 1004 case CLK_MAC_OUT: 1005 div = DIV_ROUND_UP(priv->gpll_hz, rate); 1006 rk_clrsetreg(&cru->pmuclksel_con[0], CLK_MAC_OUT_DIV_MASK, 1007 ((div - 1) << CLK_MAC_OUT_DIV_SHIFT)); 1008 default: 1009 return -ENOENT; 1010 } 1011 1012 return rk3506_mac_get_rate(priv, clk_id); 1013 } 1014 1015 static ulong rk3506_clk_get_rate(struct clk *clk) 1016 { 1017 struct rk3506_clk_priv *priv = dev_get_priv(clk->dev); 1018 ulong rate = 0; 1019 1020 if (!priv->gpll_hz || !priv->v0pll_hz || !priv->v1pll_hz) { 1021 printf("%s: gpll=%lu, v0pll=%lu, v1pll=%lu\n", 1022 __func__, priv->gpll_hz, priv->v0pll_hz, priv->v1pll_hz); 1023 return -ENOENT; 1024 } 1025 1026 switch (clk->id) { 1027 case PLL_GPLL: 1028 rate = priv->gpll_hz; 1029 break; 1030 case PLL_V0PLL: 1031 rate = priv->v0pll_hz; 1032 break; 1033 case PLL_V1PLL: 1034 rate = priv->v1pll_hz; 1035 break; 1036 case ARMCLK: 1037 rate = rk3506_armclk_get_rate(priv); 1038 break; 1039 case CLK_GPLL_DIV: 1040 case CLK_GPLL_DIV_100M: 1041 case CLK_V0PLL_DIV: 1042 case CLK_V1PLL_DIV: 1043 rate = rk3506_pll_div_get_rate(priv, clk->id); 1044 break; 1045 case ACLK_BUS_ROOT: 1046 case HCLK_BUS_ROOT: 1047 case PCLK_BUS_ROOT: 1048 rate = rk3506_bus_get_rate(priv, clk->id); 1049 break; 1050 case ACLK_HSPERI_ROOT: 1051 case HCLK_LSPERI_ROOT: 1052 rate = rk3506_peri_get_rate(priv, clk->id); 1053 break; 1054 case HCLK_SDMMC: 1055 case CCLK_SRC_SDMMC: 1056 rate = rk3506_sdmmc_get_rate(priv, clk->id); 1057 break; 1058 case CLK_SARADC: 1059 rate = rk3506_saradc_get_rate(priv, clk->id); 1060 break; 1061 case CLK_TSADC: 1062 case CLK_TSADC_TSEN: 1063 rate = rk3506_tsadc_get_rate(priv, clk->id); 1064 break; 1065 case CLK_I2C0: 1066 case CLK_I2C1: 1067 case CLK_I2C2: 1068 rate = rk3506_i2c_get_rate(priv, clk->id); 1069 break; 1070 case CLK_PWM0: 1071 case CLK_PWM1: 1072 rate = rk3506_pwm_get_rate(priv, clk->id); 1073 break; 1074 case CLK_SPI0: 1075 case CLK_SPI1: 1076 rate = rk3506_spi_get_rate(priv, clk->id); 1077 break; 1078 case SCLK_FSPI: 1079 rate = rk3506_fspi_get_rate(priv); 1080 break; 1081 case DCLK_VOP: 1082 rate = rk3506_vop_dclk_get_rate(priv); 1083 break; 1084 case CLK_MAC0: 1085 case CLK_MAC1: 1086 case CLK_MAC_OUT: 1087 rate = rk3506_mac_get_rate(priv, clk->id); 1088 break; 1089 default: 1090 return -ENOENT; 1091 } 1092 1093 return rate; 1094 }; 1095 1096 static ulong rk3506_clk_set_rate(struct clk *clk, ulong rate) 1097 { 1098 struct rk3506_clk_priv *priv = dev_get_priv(clk->dev); 1099 ulong ret = 0; 1100 1101 if (!priv->gpll_hz || !priv->v0pll_hz || !priv->v1pll_hz) { 1102 printf("%s: gpll=%lu, v0pll=%lu, v1pll=%lu\n", 1103 __func__, priv->gpll_hz, priv->v0pll_hz, priv->v1pll_hz); 1104 return -ENOENT; 1105 } 1106 1107 debug("%s: id=%ld, rate=%ld\n", __func__, clk->id, rate); 1108 1109 switch (clk->id) { 1110 case ARMCLK: 1111 if (priv->armclk_hz) 1112 rk3506_armclk_set_rate(priv, rate); 1113 priv->armclk_hz = rate; 1114 break; 1115 case CLK_GPLL_DIV: 1116 case CLK_GPLL_DIV_100M: 1117 case CLK_V0PLL_DIV: 1118 case CLK_V1PLL_DIV: 1119 ret = rk3506_pll_div_set_rate(priv, clk->id, rate); 1120 break; 1121 case ACLK_BUS_ROOT: 1122 case HCLK_BUS_ROOT: 1123 case PCLK_BUS_ROOT: 1124 ret = rk3506_bus_set_rate(priv, clk->id, rate); 1125 break; 1126 case ACLK_HSPERI_ROOT: 1127 case HCLK_LSPERI_ROOT: 1128 ret = rk3506_peri_set_rate(priv, clk->id, rate); 1129 break; 1130 case HCLK_SDMMC: 1131 case CCLK_SRC_SDMMC: 1132 ret = rk3506_sdmmc_set_rate(priv, clk->id, rate); 1133 break; 1134 case CLK_SARADC: 1135 ret = rk3506_saradc_set_rate(priv, clk->id, rate); 1136 break; 1137 case CLK_TSADC: 1138 case CLK_TSADC_TSEN: 1139 ret = rk3506_tsadc_set_rate(priv, clk->id, rate); 1140 break; 1141 case CLK_I2C0: 1142 case CLK_I2C1: 1143 case CLK_I2C2: 1144 ret = rk3506_i2c_set_rate(priv, clk->id, rate); 1145 break; 1146 case CLK_PWM0: 1147 case CLK_PWM1: 1148 ret = rk3506_pwm_set_rate(priv, clk->id, rate); 1149 break; 1150 case CLK_SPI0: 1151 case CLK_SPI1: 1152 ret = rk3506_spi_set_rate(priv, clk->id, rate); 1153 break; 1154 case HCLK_FSPI: 1155 case SCLK_FSPI: 1156 ret = rk3506_fspi_set_rate(priv, rate); 1157 break; 1158 case DCLK_VOP: 1159 ret = rk3506_vop_dclk_set_rate(priv, rate); 1160 break; 1161 case CLK_MAC0: 1162 case CLK_MAC1: 1163 case CLK_MAC_OUT: 1164 ret = rk3506_mac_set_rate(priv, clk->id, rate); 1165 break; 1166 default: 1167 return -ENOENT; 1168 } 1169 1170 return ret; 1171 }; 1172 1173 static struct clk_ops rk3506_clk_ops = { 1174 .get_rate = rk3506_clk_get_rate, 1175 .set_rate = rk3506_clk_set_rate, 1176 }; 1177 1178 static void rk3506_clk_init(struct rk3506_clk_priv *priv) 1179 { 1180 priv->sync_kernel = false; 1181 1182 if (!priv->gpll_hz) { 1183 priv->gpll_hz = rockchip_pll_get_rate(&rk3506_pll_clks[GPLL], 1184 priv->cru, GPLL); 1185 priv->gpll_hz = roundup(priv->gpll_hz, 1000); 1186 } 1187 if (!priv->v0pll_hz) { 1188 priv->v0pll_hz = rockchip_pll_get_rate(&rk3506_pll_clks[V0PLL], 1189 priv->cru, V0PLL); 1190 priv->v0pll_hz = roundup(priv->v0pll_hz, 1000); 1191 } 1192 if (!priv->v1pll_hz) { 1193 priv->v1pll_hz = rockchip_pll_get_rate(&rk3506_pll_clks[V1PLL], 1194 priv->cru, V1PLL); 1195 priv->v1pll_hz = roundup(priv->v1pll_hz, 1000); 1196 } 1197 if (!priv->gpll_div_hz) { 1198 priv->gpll_div_hz = rk3506_pll_div_get_rate(priv, CLK_GPLL_DIV); 1199 priv->gpll_div_hz = roundup(priv->gpll_div_hz, 1000); 1200 } 1201 if (!priv->gpll_div_100mhz) { 1202 priv->gpll_div_100mhz = rk3506_pll_div_get_rate(priv, CLK_GPLL_DIV_100M); 1203 priv->gpll_div_100mhz = roundup(priv->gpll_div_100mhz, 1000); 1204 } 1205 if (!priv->v0pll_div_hz) { 1206 priv->v0pll_div_hz = rk3506_pll_div_get_rate(priv, CLK_V0PLL_DIV); 1207 priv->v0pll_div_hz = roundup(priv->v0pll_div_hz, 1000); 1208 } 1209 if (!priv->v1pll_div_hz) { 1210 priv->v1pll_div_hz = rk3506_pll_div_get_rate(priv, CLK_V1PLL_DIV); 1211 priv->v1pll_div_hz = roundup(priv->v1pll_div_hz, 1000); 1212 } 1213 1214 if (!priv->armclk_enter_hz) { 1215 priv->armclk_enter_hz = rk3506_armclk_get_rate(priv); 1216 priv->armclk_init_hz = priv->armclk_enter_hz; 1217 } 1218 } 1219 1220 static int rk3506_clk_probe(struct udevice *dev) 1221 { 1222 struct rk3506_clk_priv *priv = dev_get_priv(dev); 1223 int ret; 1224 1225 #ifdef CONFIG_SPL_BUILD 1226 /* Init pka crypto rate, sel=v0pll, div=3 */ 1227 writel(0x3f801180, RK3506_SCRU_BASE + 0x0010); 1228 /* Change clk core src rate, sel=gpll, div=3 */ 1229 writel(0x007f0003, RK3506_CRU_BASE + 0x033c); 1230 #endif 1231 rk3506_clk_init(priv); 1232 1233 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 1234 ret = clk_set_defaults(dev); 1235 if (ret) 1236 debug("%s clk_set_defaults failed %d\n", __func__, ret); 1237 else 1238 priv->sync_kernel = true; 1239 1240 return 0; 1241 } 1242 1243 static int rk3506_clk_ofdata_to_platdata(struct udevice *dev) 1244 { 1245 struct rk3506_clk_priv *priv = dev_get_priv(dev); 1246 1247 priv->cru = dev_read_addr_ptr(dev); 1248 1249 return 0; 1250 } 1251 1252 static int rk3506_clk_bind(struct udevice *dev) 1253 { 1254 struct udevice *sys_child, *sf_child; 1255 struct softreset_reg *sf_priv; 1256 struct sysreset_reg *priv; 1257 int ret; 1258 1259 /* The reset driver does not have a device node, so bind it here */ 1260 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 1261 &sys_child); 1262 if (ret) { 1263 debug("Warning: No sysreset driver: ret=%d\n", ret); 1264 } else { 1265 priv = malloc(sizeof(struct sysreset_reg)); 1266 priv->glb_srst_fst_value = offsetof(struct rk3506_cru, 1267 glb_srst_fst); 1268 priv->glb_srst_snd_value = offsetof(struct rk3506_cru, 1269 glb_srst_snd); 1270 sys_child->priv = priv; 1271 } 1272 1273 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 1274 dev_ofnode(dev), &sf_child); 1275 if (ret) { 1276 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 1277 } else { 1278 sf_priv = malloc(sizeof(struct softreset_reg)); 1279 sf_priv->sf_reset_offset = offsetof(struct rk3506_cru, 1280 softrst_con[0]); 1281 sf_priv->sf_reset_num = 23; 1282 sf_child->priv = sf_priv; 1283 } 1284 1285 return 0; 1286 } 1287 1288 static const struct udevice_id rk3506_clk_ids[] = { 1289 { .compatible = "rockchip,rk3506-cru" }, 1290 { } 1291 }; 1292 1293 U_BOOT_DRIVER(rockchip_rk3506_cru) = { 1294 .name = "rockchip_rk3506_cru", 1295 .id = UCLASS_CLK, 1296 .of_match = rk3506_clk_ids, 1297 .priv_auto_alloc_size = sizeof(struct rk3506_clk_priv), 1298 .ofdata_to_platdata = rk3506_clk_ofdata_to_platdata, 1299 .ops = &rk3506_clk_ops, 1300 .bind = rk3506_clk_bind, 1301 .probe = rk3506_clk_probe, 1302 }; 1303