1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * Author: Andy Yan <andy.yan@rock-chips.com> 4 * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH 5 * SPDX-License-Identifier: GPL-2.0 6 */ 7 8 #include <common.h> 9 #include <clk-uclass.h> 10 #include <dm.h> 11 #include <dt-structs.h> 12 #include <errno.h> 13 #include <mapmem.h> 14 #include <syscon.h> 15 #include <asm/arch/clock.h> 16 #include <asm/arch/cru_rk3368.h> 17 #include <asm/arch/hardware.h> 18 #include <asm/io.h> 19 #include <dm/lists.h> 20 #include <dt-bindings/clock/rk3368-cru.h> 21 22 DECLARE_GLOBAL_DATA_PTR; 23 24 #if CONFIG_IS_ENABLED(OF_PLATDATA) 25 struct rk3368_clk_plat { 26 struct dtd_rockchip_rk3368_cru dtd; 27 }; 28 #endif 29 30 struct pll_div { 31 u32 nr; 32 u32 nf; 33 u32 no; 34 }; 35 36 #define OSC_HZ (24 * 1000 * 1000) 37 #define APLL_L_HZ (800 * 1000 * 1000) 38 #define APLL_B_HZ (816 * 1000 * 1000) 39 #define GPLL_HZ (576 * 1000 * 1000) 40 #define CPLL_HZ (400 * 1000 * 1000) 41 42 #define RATE_TO_DIV(input_rate, output_rate) \ 43 ((input_rate) / (output_rate) - 1); 44 45 #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1)) 46 47 #define PLL_DIVISORS(hz, _nr, _no) { \ 48 .nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no}; \ 49 _Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\ 50 (_nr * _no) == hz, #hz "Hz cannot be hit with PLL " \ 51 "divisors on line " __stringify(__LINE__)); 52 53 #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 54 static const struct pll_div apll_l_init_cfg = PLL_DIVISORS(APLL_L_HZ, 12, 2); 55 static const struct pll_div apll_b_init_cfg = PLL_DIVISORS(APLL_B_HZ, 1, 2); 56 #if !defined(CONFIG_TPL_BUILD) 57 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 2); 58 static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 6); 59 #endif 60 #endif 61 62 static ulong rk3368_clk_get_rate(struct clk *clk); 63 64 /* Get pll rate by id */ 65 static uint32_t rkclk_pll_get_rate(struct rk3368_cru *cru, 66 enum rk3368_pll_id pll_id) 67 { 68 uint32_t nr, no, nf; 69 uint32_t con; 70 struct rk3368_pll *pll = &cru->pll[pll_id]; 71 72 con = readl(&pll->con3); 73 74 switch ((con & PLL_MODE_MASK) >> PLL_MODE_SHIFT) { 75 case PLL_MODE_SLOW: 76 return OSC_HZ; 77 case PLL_MODE_NORMAL: 78 con = readl(&pll->con0); 79 no = ((con & PLL_OD_MASK) >> PLL_OD_SHIFT) + 1; 80 nr = ((con & PLL_NR_MASK) >> PLL_NR_SHIFT) + 1; 81 con = readl(&pll->con1); 82 nf = ((con & PLL_NF_MASK) >> PLL_NF_SHIFT) + 1; 83 84 return (24 * nf / (nr * no)) * 1000000; 85 case PLL_MODE_DEEP_SLOW: 86 default: 87 return 32768; 88 } 89 } 90 91 #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 92 static int rkclk_set_pll(struct rk3368_cru *cru, enum rk3368_pll_id pll_id, 93 const struct pll_div *div) 94 { 95 struct rk3368_pll *pll = &cru->pll[pll_id]; 96 /* All PLLs have same VCO and output frequency range restrictions*/ 97 uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000; 98 uint output_hz = vco_hz / div->no; 99 100 debug("PLL at %p: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n", 101 pll, div->nf, div->nr, div->no, vco_hz, output_hz); 102 103 /* enter slow mode and reset pll */ 104 rk_clrsetreg(&pll->con3, PLL_MODE_MASK | PLL_RESET_MASK, 105 PLL_RESET << PLL_RESET_SHIFT); 106 107 rk_clrsetreg(&pll->con0, PLL_NR_MASK | PLL_OD_MASK, 108 ((div->nr - 1) << PLL_NR_SHIFT) | 109 ((div->no - 1) << PLL_OD_SHIFT)); 110 writel((div->nf - 1) << PLL_NF_SHIFT, &pll->con1); 111 /* 112 * BWADJ should be set to NF / 2 to ensure the nominal bandwidth. 113 * Compare the RK3368 TRM, section "3.6.4 PLL Bandwidth Adjustment". 114 */ 115 clrsetbits_le32(&pll->con2, PLL_BWADJ_MASK, (div->nf >> 1) - 1); 116 117 udelay(10); 118 119 /* return from reset */ 120 rk_clrreg(&pll->con3, PLL_RESET_MASK); 121 122 /* waiting for pll lock */ 123 while (!(readl(&pll->con1) & PLL_LOCK_STA)) 124 udelay(1); 125 126 rk_clrsetreg(&pll->con3, PLL_MODE_MASK, 127 PLL_MODE_NORMAL << PLL_MODE_SHIFT); 128 129 return 0; 130 } 131 #endif 132 133 #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 134 static void rkclk_init(struct rk3368_cru *cru) 135 { 136 u32 apllb, aplll, dpll, cpll, gpll; 137 138 rkclk_set_pll(cru, APLLB, &apll_b_init_cfg); 139 rkclk_set_pll(cru, APLLL, &apll_l_init_cfg); 140 #if !defined(CONFIG_TPL_BUILD) 141 /* 142 * If we plan to return to the boot ROM, we can't increase the 143 * GPLL rate from the SPL stage. 144 */ 145 rkclk_set_pll(cru, GPLL, &gpll_init_cfg); 146 rkclk_set_pll(cru, CPLL, &cpll_init_cfg); 147 #endif 148 149 apllb = rkclk_pll_get_rate(cru, APLLB); 150 aplll = rkclk_pll_get_rate(cru, APLLL); 151 dpll = rkclk_pll_get_rate(cru, DPLL); 152 cpll = rkclk_pll_get_rate(cru, CPLL); 153 gpll = rkclk_pll_get_rate(cru, GPLL); 154 155 debug("%s apllb(%d) apll(%d) dpll(%d) cpll(%d) gpll(%d)\n", 156 __func__, apllb, aplll, dpll, cpll, gpll); 157 } 158 #endif 159 160 #if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT) 161 static ulong rk3368_mmc_get_clk(struct rk3368_cru *cru, uint clk_id) 162 { 163 u32 div, con, con_id, rate; 164 u32 pll_rate; 165 166 switch (clk_id) { 167 case HCLK_SDMMC: 168 con_id = 50; 169 break; 170 case HCLK_EMMC: 171 con_id = 51; 172 break; 173 case SCLK_SDIO0: 174 con_id = 48; 175 break; 176 default: 177 return -EINVAL; 178 } 179 180 con = readl(&cru->clksel_con[con_id]); 181 switch (con & MMC_PLL_SEL_MASK) { 182 case MMC_PLL_SEL_GPLL: 183 pll_rate = rkclk_pll_get_rate(cru, GPLL); 184 break; 185 case MMC_PLL_SEL_24M: 186 pll_rate = OSC_HZ; 187 break; 188 case MMC_PLL_SEL_CPLL: 189 pll_rate = rkclk_pll_get_rate(cru, CPLL); 190 break; 191 case MMC_PLL_SEL_USBPHY_480M: 192 default: 193 return -EINVAL; 194 } 195 div = (con & MMC_CLK_DIV_MASK) >> MMC_CLK_DIV_SHIFT; 196 rate = DIV_TO_RATE(pll_rate, div); 197 198 debug("%s: raw rate %d (post-divide by 2)\n", __func__, rate); 199 return rate >> 1; 200 } 201 202 static ulong rk3368_mmc_find_best_rate_and_parent(struct clk *clk, 203 ulong rate, 204 u32 *best_mux, 205 u32 *best_div) 206 { 207 int i; 208 ulong best_rate = 0; 209 const ulong MHz = 1000000; 210 const struct { 211 u32 mux; 212 ulong rate; 213 } parents[] = { 214 { .mux = MMC_PLL_SEL_CPLL, .rate = CPLL_HZ }, 215 { .mux = MMC_PLL_SEL_GPLL, .rate = GPLL_HZ }, 216 { .mux = MMC_PLL_SEL_24M, .rate = 24 * MHz } 217 }; 218 219 debug("%s: target rate %ld\n", __func__, rate); 220 for (i = 0; i < ARRAY_SIZE(parents); ++i) { 221 /* 222 * Find the largest rate no larger than the target-rate for 223 * the current parent. 224 */ 225 ulong parent_rate = parents[i].rate; 226 u32 div = DIV_ROUND_UP(parent_rate, rate); 227 u32 adj_div = div; 228 ulong new_rate = parent_rate / adj_div; 229 230 debug("%s: rate %ld, parent-mux %d, parent-rate %ld, div %d\n", 231 __func__, rate, parents[i].mux, parents[i].rate, div); 232 233 /* Skip, if not representable */ 234 if ((div - 1) > MMC_CLK_DIV_MASK) 235 continue; 236 237 /* Skip, if we already have a better (or equal) solution */ 238 if (new_rate <= best_rate) 239 continue; 240 241 /* This is our new best rate. */ 242 best_rate = new_rate; 243 *best_mux = parents[i].mux; 244 *best_div = div - 1; 245 } 246 247 debug("%s: best_mux = %x, best_div = %d, best_rate = %ld\n", 248 __func__, *best_mux, *best_div, best_rate); 249 250 return best_rate; 251 } 252 253 static ulong rk3368_mmc_set_clk(struct clk *clk, ulong rate) 254 { 255 struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 256 struct rk3368_cru *cru = priv->cru; 257 ulong clk_id = clk->id; 258 u32 con_id, mux = 0, div = 0; 259 260 /* Find the best parent and rate */ 261 rk3368_mmc_find_best_rate_and_parent(clk, rate << 1, &mux, &div); 262 263 switch (clk_id) { 264 case HCLK_SDMMC: 265 con_id = 50; 266 break; 267 case HCLK_EMMC: 268 con_id = 51; 269 break; 270 case SCLK_SDIO0: 271 con_id = 48; 272 break; 273 default: 274 return -EINVAL; 275 } 276 277 rk_clrsetreg(&cru->clksel_con[con_id], 278 MMC_PLL_SEL_MASK | MMC_CLK_DIV_MASK, 279 mux | div); 280 281 return rk3368_mmc_get_clk(cru, clk_id); 282 } 283 #endif 284 285 static ulong rk3368_clk_get_rate(struct clk *clk) 286 { 287 struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 288 ulong rate = 0; 289 290 debug("%s: id %ld\n", __func__, clk->id); 291 switch (clk->id) { 292 case PLL_CPLL: 293 rate = rkclk_pll_get_rate(priv->cru, CPLL); 294 break; 295 case PLL_GPLL: 296 rate = rkclk_pll_get_rate(priv->cru, GPLL); 297 break; 298 #if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT) 299 case HCLK_SDMMC: 300 case HCLK_EMMC: 301 rate = rk3368_mmc_get_clk(priv->cru, clk->id); 302 break; 303 #endif 304 default: 305 return -ENOENT; 306 } 307 308 return rate; 309 } 310 311 #if IS_ENABLED(CONFIG_TPL_BUILD) 312 static ulong rk3368_ddr_set_clk(struct rk3368_cru *cru, ulong set_rate) 313 { 314 const struct pll_div *dpll_cfg = NULL; 315 const ulong MHz = 1000000; 316 317 /* Fout = ((Fin /NR) * NF )/ NO */ 318 static const struct pll_div dpll_1200 = PLL_DIVISORS(1200 * MHz, 1, 1); 319 static const struct pll_div dpll_1332 = PLL_DIVISORS(1332 * MHz, 2, 1); 320 static const struct pll_div dpll_1600 = PLL_DIVISORS(1600 * MHz, 3, 2); 321 322 switch (set_rate) { 323 case 1200*MHz: 324 dpll_cfg = &dpll_1200; 325 break; 326 case 1332*MHz: 327 dpll_cfg = &dpll_1332; 328 break; 329 case 1600*MHz: 330 dpll_cfg = &dpll_1600; 331 break; 332 default: 333 error("Unsupported SDRAM frequency!,%ld\n", set_rate); 334 } 335 rkclk_set_pll(cru, DPLL, dpll_cfg); 336 337 return set_rate; 338 } 339 #endif 340 341 #if CONFIG_IS_ENABLED(GMAC_ROCKCHIP) 342 static ulong rk3368_gmac_set_clk(struct rk3368_cru *cru, 343 ulong clk_id, ulong set_rate) 344 { 345 /* 346 * This models the 'assigned-clock-parents = <&ext_gmac>' from 347 * the DTS and switches to the 'ext_gmac' clock parent. 348 */ 349 rk_setreg(&cru->clksel_con[43], GMAC_MUX_SEL_EXTCLK); 350 return set_rate; 351 } 352 #endif 353 354 static ulong rk3368_clk_set_rate(struct clk *clk, ulong rate) 355 { 356 __maybe_unused struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 357 ulong ret = 0; 358 359 debug("%s id:%ld rate:%ld\n", __func__, clk->id, rate); 360 switch (clk->id) { 361 #if IS_ENABLED(CONFIG_TPL_BUILD) 362 case CLK_DDR: 363 ret = rk3368_ddr_set_clk(priv->cru, rate); 364 break; 365 #endif 366 #if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT) 367 case HCLK_SDMMC: 368 case HCLK_EMMC: 369 ret = rk3368_mmc_set_clk(clk, rate); 370 break; 371 #endif 372 #if CONFIG_IS_ENABLED(GMAC_ROCKCHIP) 373 case SCLK_MAC: 374 /* select the external clock */ 375 ret = rk3368_gmac_set_clk(priv->cru, clk->id, rate); 376 break; 377 #endif 378 default: 379 return -ENOENT; 380 } 381 382 return ret; 383 } 384 385 static struct clk_ops rk3368_clk_ops = { 386 .get_rate = rk3368_clk_get_rate, 387 .set_rate = rk3368_clk_set_rate, 388 }; 389 390 static int rk3368_clk_probe(struct udevice *dev) 391 { 392 struct rk3368_clk_priv __maybe_unused *priv = dev_get_priv(dev); 393 #if CONFIG_IS_ENABLED(OF_PLATDATA) 394 struct rk3368_clk_plat *plat = dev_get_platdata(dev); 395 396 priv->cru = map_sysmem(plat->dtd.reg[1], plat->dtd.reg[3]); 397 #endif 398 #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 399 rkclk_init(priv->cru); 400 #endif 401 402 return 0; 403 } 404 405 static int rk3368_clk_ofdata_to_platdata(struct udevice *dev) 406 { 407 #if !CONFIG_IS_ENABLED(OF_PLATDATA) 408 struct rk3368_clk_priv *priv = dev_get_priv(dev); 409 410 priv->cru = (struct rk3368_cru *)devfdt_get_addr(dev); 411 #endif 412 413 return 0; 414 } 415 416 static int rk3368_clk_bind(struct udevice *dev) 417 { 418 int ret; 419 420 /* The reset driver does not have a device node, so bind it here */ 421 ret = device_bind_driver(gd->dm_root, "rk3368_sysreset", "reset", &dev); 422 if (ret) 423 error("bind RK3368 reset driver failed: ret=%d\n", ret); 424 425 return ret; 426 } 427 428 static const struct udevice_id rk3368_clk_ids[] = { 429 { .compatible = "rockchip,rk3368-cru" }, 430 { } 431 }; 432 433 U_BOOT_DRIVER(rockchip_rk3368_cru) = { 434 .name = "rockchip_rk3368_cru", 435 .id = UCLASS_CLK, 436 .of_match = rk3368_clk_ids, 437 .priv_auto_alloc_size = sizeof(struct rk3368_clk_priv), 438 #if CONFIG_IS_ENABLED(OF_PLATDATA) 439 .platdata_auto_alloc_size = sizeof(struct rk3368_clk_plat), 440 #endif 441 .ofdata_to_platdata = rk3368_clk_ofdata_to_platdata, 442 .ops = &rk3368_clk_ops, 443 .bind = rk3368_clk_bind, 444 .probe = rk3368_clk_probe, 445 }; 446