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 break; 985 default: 986 return -ENOENT; 987 } 988 989 return DIV_TO_RATE(priv->gpll_hz, div); 990 } 991 992 static ulong rk3506_mac_set_rate(struct rk3506_clk_priv *priv, ulong clk_id, 993 ulong rate) 994 { 995 struct rk3506_cru *cru = priv->cru; 996 u32 div; 997 998 switch (clk_id) { 999 case CLK_MAC0: 1000 case CLK_MAC1: 1001 div = DIV_ROUND_UP(priv->gpll_hz, rate); 1002 rk_clrsetreg(&cru->clksel_con[50], CLK_MAC_DIV_MASK, 1003 ((div - 1) << CLK_MAC_DIV_SHIFT)); 1004 break; 1005 case CLK_MAC_OUT: 1006 div = DIV_ROUND_UP(priv->gpll_hz, rate); 1007 rk_clrsetreg(&cru->pmuclksel_con[0], CLK_MAC_OUT_DIV_MASK, 1008 ((div - 1) << CLK_MAC_OUT_DIV_SHIFT)); 1009 break; 1010 default: 1011 return -ENOENT; 1012 } 1013 1014 return rk3506_mac_get_rate(priv, clk_id); 1015 } 1016 1017 static ulong rk3506_clk_get_rate(struct clk *clk) 1018 { 1019 struct rk3506_clk_priv *priv = dev_get_priv(clk->dev); 1020 ulong rate = 0; 1021 1022 if (!priv->gpll_hz || !priv->v0pll_hz || !priv->v1pll_hz) { 1023 printf("%s: gpll=%lu, v0pll=%lu, v1pll=%lu\n", 1024 __func__, priv->gpll_hz, priv->v0pll_hz, priv->v1pll_hz); 1025 return -ENOENT; 1026 } 1027 1028 switch (clk->id) { 1029 case PLL_GPLL: 1030 rate = priv->gpll_hz; 1031 break; 1032 case PLL_V0PLL: 1033 rate = priv->v0pll_hz; 1034 break; 1035 case PLL_V1PLL: 1036 rate = priv->v1pll_hz; 1037 break; 1038 case ARMCLK: 1039 rate = rk3506_armclk_get_rate(priv); 1040 break; 1041 case CLK_GPLL_DIV: 1042 case CLK_GPLL_DIV_100M: 1043 case CLK_V0PLL_DIV: 1044 case CLK_V1PLL_DIV: 1045 rate = rk3506_pll_div_get_rate(priv, clk->id); 1046 break; 1047 case ACLK_BUS_ROOT: 1048 case HCLK_BUS_ROOT: 1049 case PCLK_BUS_ROOT: 1050 rate = rk3506_bus_get_rate(priv, clk->id); 1051 break; 1052 case ACLK_HSPERI_ROOT: 1053 case HCLK_LSPERI_ROOT: 1054 rate = rk3506_peri_get_rate(priv, clk->id); 1055 break; 1056 case HCLK_SDMMC: 1057 case CCLK_SRC_SDMMC: 1058 rate = rk3506_sdmmc_get_rate(priv, clk->id); 1059 break; 1060 case CLK_SARADC: 1061 rate = rk3506_saradc_get_rate(priv, clk->id); 1062 break; 1063 case CLK_TSADC: 1064 case CLK_TSADC_TSEN: 1065 rate = rk3506_tsadc_get_rate(priv, clk->id); 1066 break; 1067 case CLK_I2C0: 1068 case CLK_I2C1: 1069 case CLK_I2C2: 1070 rate = rk3506_i2c_get_rate(priv, clk->id); 1071 break; 1072 case CLK_PWM0: 1073 case CLK_PWM1: 1074 rate = rk3506_pwm_get_rate(priv, clk->id); 1075 break; 1076 case CLK_SPI0: 1077 case CLK_SPI1: 1078 rate = rk3506_spi_get_rate(priv, clk->id); 1079 break; 1080 case SCLK_FSPI: 1081 rate = rk3506_fspi_get_rate(priv); 1082 break; 1083 case DCLK_VOP: 1084 rate = rk3506_vop_dclk_get_rate(priv); 1085 break; 1086 case CLK_MAC0: 1087 case CLK_MAC1: 1088 case CLK_MAC_OUT: 1089 rate = rk3506_mac_get_rate(priv, clk->id); 1090 break; 1091 default: 1092 return -ENOENT; 1093 } 1094 1095 return rate; 1096 }; 1097 1098 static ulong rk3506_clk_set_rate(struct clk *clk, ulong rate) 1099 { 1100 struct rk3506_clk_priv *priv = dev_get_priv(clk->dev); 1101 ulong ret = 0; 1102 1103 if (!priv->gpll_hz || !priv->v0pll_hz || !priv->v1pll_hz) { 1104 printf("%s: gpll=%lu, v0pll=%lu, v1pll=%lu\n", 1105 __func__, priv->gpll_hz, priv->v0pll_hz, priv->v1pll_hz); 1106 return -ENOENT; 1107 } 1108 1109 debug("%s: id=%ld, rate=%ld\n", __func__, clk->id, rate); 1110 1111 switch (clk->id) { 1112 case ARMCLK: 1113 if (priv->armclk_hz) 1114 rk3506_armclk_set_rate(priv, rate); 1115 priv->armclk_hz = rate; 1116 break; 1117 case CLK_GPLL_DIV: 1118 case CLK_GPLL_DIV_100M: 1119 case CLK_V0PLL_DIV: 1120 case CLK_V1PLL_DIV: 1121 ret = rk3506_pll_div_set_rate(priv, clk->id, rate); 1122 break; 1123 case ACLK_BUS_ROOT: 1124 case HCLK_BUS_ROOT: 1125 case PCLK_BUS_ROOT: 1126 ret = rk3506_bus_set_rate(priv, clk->id, rate); 1127 break; 1128 case ACLK_HSPERI_ROOT: 1129 case HCLK_LSPERI_ROOT: 1130 ret = rk3506_peri_set_rate(priv, clk->id, rate); 1131 break; 1132 case HCLK_SDMMC: 1133 case CCLK_SRC_SDMMC: 1134 ret = rk3506_sdmmc_set_rate(priv, clk->id, rate); 1135 break; 1136 case CLK_SARADC: 1137 ret = rk3506_saradc_set_rate(priv, clk->id, rate); 1138 break; 1139 case CLK_TSADC: 1140 case CLK_TSADC_TSEN: 1141 ret = rk3506_tsadc_set_rate(priv, clk->id, rate); 1142 break; 1143 case CLK_I2C0: 1144 case CLK_I2C1: 1145 case CLK_I2C2: 1146 ret = rk3506_i2c_set_rate(priv, clk->id, rate); 1147 break; 1148 case CLK_PWM0: 1149 case CLK_PWM1: 1150 ret = rk3506_pwm_set_rate(priv, clk->id, rate); 1151 break; 1152 case CLK_SPI0: 1153 case CLK_SPI1: 1154 ret = rk3506_spi_set_rate(priv, clk->id, rate); 1155 break; 1156 case HCLK_FSPI: 1157 case SCLK_FSPI: 1158 ret = rk3506_fspi_set_rate(priv, rate); 1159 break; 1160 case DCLK_VOP: 1161 ret = rk3506_vop_dclk_set_rate(priv, rate); 1162 break; 1163 case CLK_MAC0: 1164 case CLK_MAC1: 1165 case CLK_MAC_OUT: 1166 ret = rk3506_mac_set_rate(priv, clk->id, rate); 1167 break; 1168 default: 1169 return -ENOENT; 1170 } 1171 1172 return ret; 1173 }; 1174 1175 static struct clk_ops rk3506_clk_ops = { 1176 .get_rate = rk3506_clk_get_rate, 1177 .set_rate = rk3506_clk_set_rate, 1178 }; 1179 1180 static void rk3506_clk_init(struct rk3506_clk_priv *priv) 1181 { 1182 priv->sync_kernel = false; 1183 1184 if (!priv->gpll_hz) { 1185 priv->gpll_hz = rockchip_pll_get_rate(&rk3506_pll_clks[GPLL], 1186 priv->cru, GPLL); 1187 priv->gpll_hz = roundup(priv->gpll_hz, 1000); 1188 } 1189 if (!priv->v0pll_hz) { 1190 priv->v0pll_hz = rockchip_pll_get_rate(&rk3506_pll_clks[V0PLL], 1191 priv->cru, V0PLL); 1192 priv->v0pll_hz = roundup(priv->v0pll_hz, 1000); 1193 } 1194 if (!priv->v1pll_hz) { 1195 priv->v1pll_hz = rockchip_pll_get_rate(&rk3506_pll_clks[V1PLL], 1196 priv->cru, V1PLL); 1197 priv->v1pll_hz = roundup(priv->v1pll_hz, 1000); 1198 } 1199 if (!priv->gpll_div_hz) { 1200 priv->gpll_div_hz = rk3506_pll_div_get_rate(priv, CLK_GPLL_DIV); 1201 priv->gpll_div_hz = roundup(priv->gpll_div_hz, 1000); 1202 } 1203 if (!priv->gpll_div_100mhz) { 1204 priv->gpll_div_100mhz = rk3506_pll_div_get_rate(priv, CLK_GPLL_DIV_100M); 1205 priv->gpll_div_100mhz = roundup(priv->gpll_div_100mhz, 1000); 1206 } 1207 if (!priv->v0pll_div_hz) { 1208 priv->v0pll_div_hz = rk3506_pll_div_get_rate(priv, CLK_V0PLL_DIV); 1209 priv->v0pll_div_hz = roundup(priv->v0pll_div_hz, 1000); 1210 } 1211 if (!priv->v1pll_div_hz) { 1212 priv->v1pll_div_hz = rk3506_pll_div_get_rate(priv, CLK_V1PLL_DIV); 1213 priv->v1pll_div_hz = roundup(priv->v1pll_div_hz, 1000); 1214 } 1215 1216 if (!priv->armclk_enter_hz) { 1217 priv->armclk_enter_hz = rk3506_armclk_get_rate(priv); 1218 priv->armclk_init_hz = priv->armclk_enter_hz; 1219 } 1220 } 1221 1222 static int rk3506_clk_probe(struct udevice *dev) 1223 { 1224 struct rk3506_clk_priv *priv = dev_get_priv(dev); 1225 int ret; 1226 1227 #ifdef CONFIG_SPL_BUILD 1228 /* Init pka crypto rate, sel=v0pll, div=3 */ 1229 writel(0x3f801180, RK3506_SCRU_BASE + 0x0010); 1230 /* Change clk core src rate, sel=gpll, div=3 */ 1231 writel(0x007f0003, RK3506_CRU_BASE + 0x033c); 1232 #endif 1233 rk3506_clk_init(priv); 1234 1235 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 1236 ret = clk_set_defaults(dev); 1237 if (ret) 1238 debug("%s clk_set_defaults failed %d\n", __func__, ret); 1239 else 1240 priv->sync_kernel = true; 1241 1242 return 0; 1243 } 1244 1245 static int rk3506_clk_ofdata_to_platdata(struct udevice *dev) 1246 { 1247 struct rk3506_clk_priv *priv = dev_get_priv(dev); 1248 1249 priv->cru = dev_read_addr_ptr(dev); 1250 1251 return 0; 1252 } 1253 1254 static int rk3506_clk_bind(struct udevice *dev) 1255 { 1256 struct udevice *sys_child, *sf_child; 1257 struct softreset_reg *sf_priv; 1258 struct sysreset_reg *priv; 1259 int ret; 1260 1261 /* The reset driver does not have a device node, so bind it here */ 1262 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 1263 &sys_child); 1264 if (ret) { 1265 debug("Warning: No sysreset driver: ret=%d\n", ret); 1266 } else { 1267 priv = malloc(sizeof(struct sysreset_reg)); 1268 priv->glb_srst_fst_value = offsetof(struct rk3506_cru, 1269 glb_srst_fst); 1270 priv->glb_srst_snd_value = offsetof(struct rk3506_cru, 1271 glb_srst_snd); 1272 sys_child->priv = priv; 1273 } 1274 1275 ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset", 1276 dev_ofnode(dev), &sf_child); 1277 if (ret) { 1278 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 1279 } else { 1280 sf_priv = malloc(sizeof(struct softreset_reg)); 1281 sf_priv->sf_reset_offset = offsetof(struct rk3506_cru, 1282 softrst_con[0]); 1283 sf_priv->sf_reset_num = 23; 1284 sf_child->priv = sf_priv; 1285 } 1286 1287 return 0; 1288 } 1289 1290 static const struct udevice_id rk3506_clk_ids[] = { 1291 { .compatible = "rockchip,rk3506-cru" }, 1292 { } 1293 }; 1294 1295 U_BOOT_DRIVER(rockchip_rk3506_cru) = { 1296 .name = "rockchip_rk3506_cru", 1297 .id = UCLASS_CLK, 1298 .of_match = rk3506_clk_ids, 1299 .priv_auto_alloc_size = sizeof(struct rk3506_clk_priv), 1300 .ofdata_to_platdata = rk3506_clk_ofdata_to_platdata, 1301 .ops = &rk3506_clk_ops, 1302 .bind = rk3506_clk_bind, 1303 .probe = rk3506_clk_probe, 1304 }; 1305