clk-pll.c (14089B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2014 Google, Inc. 4 */ 5 6#define pr_fmt(fmt) "%s: " fmt, __func__ 7 8#include <linux/clk-provider.h> 9#include <linux/io.h> 10#include <linux/kernel.h> 11#include <linux/printk.h> 12#include <linux/slab.h> 13 14#include "clk.h" 15 16#define PLL_STATUS 0x0 17#define PLL_STATUS_LOCK BIT(0) 18 19#define PLL_CTRL1 0x4 20#define PLL_CTRL1_REFDIV_SHIFT 0 21#define PLL_CTRL1_REFDIV_MASK 0x3f 22#define PLL_CTRL1_FBDIV_SHIFT 6 23#define PLL_CTRL1_FBDIV_MASK 0xfff 24#define PLL_INT_CTRL1_POSTDIV1_SHIFT 18 25#define PLL_INT_CTRL1_POSTDIV1_MASK 0x7 26#define PLL_INT_CTRL1_POSTDIV2_SHIFT 21 27#define PLL_INT_CTRL1_POSTDIV2_MASK 0x7 28#define PLL_INT_CTRL1_PD BIT(24) 29#define PLL_INT_CTRL1_DSMPD BIT(25) 30#define PLL_INT_CTRL1_FOUTPOSTDIVPD BIT(26) 31#define PLL_INT_CTRL1_FOUTVCOPD BIT(27) 32 33#define PLL_CTRL2 0x8 34#define PLL_FRAC_CTRL2_FRAC_SHIFT 0 35#define PLL_FRAC_CTRL2_FRAC_MASK 0xffffff 36#define PLL_FRAC_CTRL2_POSTDIV1_SHIFT 24 37#define PLL_FRAC_CTRL2_POSTDIV1_MASK 0x7 38#define PLL_FRAC_CTRL2_POSTDIV2_SHIFT 27 39#define PLL_FRAC_CTRL2_POSTDIV2_MASK 0x7 40#define PLL_INT_CTRL2_BYPASS BIT(28) 41 42#define PLL_CTRL3 0xc 43#define PLL_FRAC_CTRL3_PD BIT(0) 44#define PLL_FRAC_CTRL3_DACPD BIT(1) 45#define PLL_FRAC_CTRL3_DSMPD BIT(2) 46#define PLL_FRAC_CTRL3_FOUTPOSTDIVPD BIT(3) 47#define PLL_FRAC_CTRL3_FOUT4PHASEPD BIT(4) 48#define PLL_FRAC_CTRL3_FOUTVCOPD BIT(5) 49 50#define PLL_CTRL4 0x10 51#define PLL_FRAC_CTRL4_BYPASS BIT(28) 52 53#define MIN_PFD 9600000UL 54#define MIN_VCO_LA 400000000UL 55#define MAX_VCO_LA 1600000000UL 56#define MIN_VCO_FRAC_INT 600000000UL 57#define MAX_VCO_FRAC_INT 1600000000UL 58#define MIN_VCO_FRAC_FRAC 600000000UL 59#define MAX_VCO_FRAC_FRAC 2400000000UL 60#define MIN_OUTPUT_LA 8000000UL 61#define MAX_OUTPUT_LA 1600000000UL 62#define MIN_OUTPUT_FRAC 12000000UL 63#define MAX_OUTPUT_FRAC 1600000000UL 64 65/* Fractional PLL operating modes */ 66enum pll_mode { 67 PLL_MODE_FRAC, 68 PLL_MODE_INT, 69}; 70 71struct pistachio_clk_pll { 72 struct clk_hw hw; 73 void __iomem *base; 74 struct pistachio_pll_rate_table *rates; 75 unsigned int nr_rates; 76}; 77 78static inline u32 pll_readl(struct pistachio_clk_pll *pll, u32 reg) 79{ 80 return readl(pll->base + reg); 81} 82 83static inline void pll_writel(struct pistachio_clk_pll *pll, u32 val, u32 reg) 84{ 85 writel(val, pll->base + reg); 86} 87 88static inline void pll_lock(struct pistachio_clk_pll *pll) 89{ 90 while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK)) 91 cpu_relax(); 92} 93 94static inline u64 do_div_round_closest(u64 dividend, u64 divisor) 95{ 96 dividend += divisor / 2; 97 return div64_u64(dividend, divisor); 98} 99 100static inline struct pistachio_clk_pll *to_pistachio_pll(struct clk_hw *hw) 101{ 102 return container_of(hw, struct pistachio_clk_pll, hw); 103} 104 105static inline enum pll_mode pll_frac_get_mode(struct clk_hw *hw) 106{ 107 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 108 u32 val; 109 110 val = pll_readl(pll, PLL_CTRL3) & PLL_FRAC_CTRL3_DSMPD; 111 return val ? PLL_MODE_INT : PLL_MODE_FRAC; 112} 113 114static inline void pll_frac_set_mode(struct clk_hw *hw, enum pll_mode mode) 115{ 116 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 117 u32 val; 118 119 val = pll_readl(pll, PLL_CTRL3); 120 if (mode == PLL_MODE_INT) 121 val |= PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_DACPD; 122 else 123 val &= ~(PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_DACPD); 124 125 pll_writel(pll, val, PLL_CTRL3); 126} 127 128static struct pistachio_pll_rate_table * 129pll_get_params(struct pistachio_clk_pll *pll, unsigned long fref, 130 unsigned long fout) 131{ 132 unsigned int i; 133 134 for (i = 0; i < pll->nr_rates; i++) { 135 if (pll->rates[i].fref == fref && pll->rates[i].fout == fout) 136 return &pll->rates[i]; 137 } 138 139 return NULL; 140} 141 142static long pll_round_rate(struct clk_hw *hw, unsigned long rate, 143 unsigned long *parent_rate) 144{ 145 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 146 unsigned int i; 147 148 for (i = 0; i < pll->nr_rates; i++) { 149 if (i > 0 && pll->rates[i].fref == *parent_rate && 150 pll->rates[i].fout <= rate) 151 return pll->rates[i - 1].fout; 152 } 153 154 return pll->rates[0].fout; 155} 156 157static int pll_gf40lp_frac_enable(struct clk_hw *hw) 158{ 159 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 160 u32 val; 161 162 val = pll_readl(pll, PLL_CTRL3); 163 val &= ~(PLL_FRAC_CTRL3_PD | PLL_FRAC_CTRL3_FOUTPOSTDIVPD | 164 PLL_FRAC_CTRL3_FOUT4PHASEPD | PLL_FRAC_CTRL3_FOUTVCOPD); 165 pll_writel(pll, val, PLL_CTRL3); 166 167 val = pll_readl(pll, PLL_CTRL4); 168 val &= ~PLL_FRAC_CTRL4_BYPASS; 169 pll_writel(pll, val, PLL_CTRL4); 170 171 pll_lock(pll); 172 173 return 0; 174} 175 176static void pll_gf40lp_frac_disable(struct clk_hw *hw) 177{ 178 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 179 u32 val; 180 181 val = pll_readl(pll, PLL_CTRL3); 182 val |= PLL_FRAC_CTRL3_PD; 183 pll_writel(pll, val, PLL_CTRL3); 184} 185 186static int pll_gf40lp_frac_is_enabled(struct clk_hw *hw) 187{ 188 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 189 190 return !(pll_readl(pll, PLL_CTRL3) & PLL_FRAC_CTRL3_PD); 191} 192 193static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate, 194 unsigned long parent_rate) 195{ 196 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 197 struct pistachio_pll_rate_table *params; 198 int enabled = pll_gf40lp_frac_is_enabled(hw); 199 u64 val, vco, old_postdiv1, old_postdiv2; 200 const char *name = clk_hw_get_name(hw); 201 202 if (rate < MIN_OUTPUT_FRAC || rate > MAX_OUTPUT_FRAC) 203 return -EINVAL; 204 205 params = pll_get_params(pll, parent_rate, rate); 206 if (!params || !params->refdiv) 207 return -EINVAL; 208 209 /* calculate vco */ 210 vco = params->fref; 211 vco *= (params->fbdiv << 24) + params->frac; 212 vco = div64_u64(vco, params->refdiv << 24); 213 214 if (vco < MIN_VCO_FRAC_FRAC || vco > MAX_VCO_FRAC_FRAC) 215 pr_warn("%s: VCO %llu is out of range %lu..%lu\n", name, vco, 216 MIN_VCO_FRAC_FRAC, MAX_VCO_FRAC_FRAC); 217 218 val = div64_u64(params->fref, params->refdiv); 219 if (val < MIN_PFD) 220 pr_warn("%s: PFD %llu is too low (min %lu)\n", 221 name, val, MIN_PFD); 222 if (val > vco / 16) 223 pr_warn("%s: PFD %llu is too high (max %llu)\n", 224 name, val, vco / 16); 225 226 val = pll_readl(pll, PLL_CTRL1); 227 val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) | 228 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT)); 229 val |= (params->refdiv << PLL_CTRL1_REFDIV_SHIFT) | 230 (params->fbdiv << PLL_CTRL1_FBDIV_SHIFT); 231 pll_writel(pll, val, PLL_CTRL1); 232 233 val = pll_readl(pll, PLL_CTRL2); 234 235 old_postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) & 236 PLL_FRAC_CTRL2_POSTDIV1_MASK; 237 old_postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) & 238 PLL_FRAC_CTRL2_POSTDIV2_MASK; 239 if (enabled && 240 (params->postdiv1 != old_postdiv1 || 241 params->postdiv2 != old_postdiv2)) 242 pr_warn("%s: changing postdiv while PLL is enabled\n", name); 243 244 if (params->postdiv2 > params->postdiv1) 245 pr_warn("%s: postdiv2 should not exceed postdiv1\n", name); 246 247 val &= ~((PLL_FRAC_CTRL2_FRAC_MASK << PLL_FRAC_CTRL2_FRAC_SHIFT) | 248 (PLL_FRAC_CTRL2_POSTDIV1_MASK << 249 PLL_FRAC_CTRL2_POSTDIV1_SHIFT) | 250 (PLL_FRAC_CTRL2_POSTDIV2_MASK << 251 PLL_FRAC_CTRL2_POSTDIV2_SHIFT)); 252 val |= (params->frac << PLL_FRAC_CTRL2_FRAC_SHIFT) | 253 (params->postdiv1 << PLL_FRAC_CTRL2_POSTDIV1_SHIFT) | 254 (params->postdiv2 << PLL_FRAC_CTRL2_POSTDIV2_SHIFT); 255 pll_writel(pll, val, PLL_CTRL2); 256 257 /* set operating mode */ 258 if (params->frac) 259 pll_frac_set_mode(hw, PLL_MODE_FRAC); 260 else 261 pll_frac_set_mode(hw, PLL_MODE_INT); 262 263 if (enabled) 264 pll_lock(pll); 265 266 return 0; 267} 268 269static unsigned long pll_gf40lp_frac_recalc_rate(struct clk_hw *hw, 270 unsigned long parent_rate) 271{ 272 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 273 u64 val, prediv, fbdiv, frac, postdiv1, postdiv2, rate; 274 275 val = pll_readl(pll, PLL_CTRL1); 276 prediv = (val >> PLL_CTRL1_REFDIV_SHIFT) & PLL_CTRL1_REFDIV_MASK; 277 fbdiv = (val >> PLL_CTRL1_FBDIV_SHIFT) & PLL_CTRL1_FBDIV_MASK; 278 279 val = pll_readl(pll, PLL_CTRL2); 280 postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) & 281 PLL_FRAC_CTRL2_POSTDIV1_MASK; 282 postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) & 283 PLL_FRAC_CTRL2_POSTDIV2_MASK; 284 frac = (val >> PLL_FRAC_CTRL2_FRAC_SHIFT) & PLL_FRAC_CTRL2_FRAC_MASK; 285 286 /* get operating mode (int/frac) and calculate rate accordingly */ 287 rate = parent_rate; 288 if (pll_frac_get_mode(hw) == PLL_MODE_FRAC) 289 rate *= (fbdiv << 24) + frac; 290 else 291 rate *= (fbdiv << 24); 292 293 rate = do_div_round_closest(rate, (prediv * postdiv1 * postdiv2) << 24); 294 295 return rate; 296} 297 298static const struct clk_ops pll_gf40lp_frac_ops = { 299 .enable = pll_gf40lp_frac_enable, 300 .disable = pll_gf40lp_frac_disable, 301 .is_enabled = pll_gf40lp_frac_is_enabled, 302 .recalc_rate = pll_gf40lp_frac_recalc_rate, 303 .round_rate = pll_round_rate, 304 .set_rate = pll_gf40lp_frac_set_rate, 305}; 306 307static const struct clk_ops pll_gf40lp_frac_fixed_ops = { 308 .enable = pll_gf40lp_frac_enable, 309 .disable = pll_gf40lp_frac_disable, 310 .is_enabled = pll_gf40lp_frac_is_enabled, 311 .recalc_rate = pll_gf40lp_frac_recalc_rate, 312}; 313 314static int pll_gf40lp_laint_enable(struct clk_hw *hw) 315{ 316 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 317 u32 val; 318 319 val = pll_readl(pll, PLL_CTRL1); 320 val &= ~(PLL_INT_CTRL1_PD | 321 PLL_INT_CTRL1_FOUTPOSTDIVPD | PLL_INT_CTRL1_FOUTVCOPD); 322 pll_writel(pll, val, PLL_CTRL1); 323 324 val = pll_readl(pll, PLL_CTRL2); 325 val &= ~PLL_INT_CTRL2_BYPASS; 326 pll_writel(pll, val, PLL_CTRL2); 327 328 pll_lock(pll); 329 330 return 0; 331} 332 333static void pll_gf40lp_laint_disable(struct clk_hw *hw) 334{ 335 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 336 u32 val; 337 338 val = pll_readl(pll, PLL_CTRL1); 339 val |= PLL_INT_CTRL1_PD; 340 pll_writel(pll, val, PLL_CTRL1); 341} 342 343static int pll_gf40lp_laint_is_enabled(struct clk_hw *hw) 344{ 345 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 346 347 return !(pll_readl(pll, PLL_CTRL1) & PLL_INT_CTRL1_PD); 348} 349 350static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate, 351 unsigned long parent_rate) 352{ 353 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 354 struct pistachio_pll_rate_table *params; 355 int enabled = pll_gf40lp_laint_is_enabled(hw); 356 u32 val, vco, old_postdiv1, old_postdiv2; 357 const char *name = clk_hw_get_name(hw); 358 359 if (rate < MIN_OUTPUT_LA || rate > MAX_OUTPUT_LA) 360 return -EINVAL; 361 362 params = pll_get_params(pll, parent_rate, rate); 363 if (!params || !params->refdiv) 364 return -EINVAL; 365 366 vco = div_u64(params->fref * params->fbdiv, params->refdiv); 367 if (vco < MIN_VCO_LA || vco > MAX_VCO_LA) 368 pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco, 369 MIN_VCO_LA, MAX_VCO_LA); 370 371 val = div_u64(params->fref, params->refdiv); 372 if (val < MIN_PFD) 373 pr_warn("%s: PFD %u is too low (min %lu)\n", 374 name, val, MIN_PFD); 375 if (val > vco / 16) 376 pr_warn("%s: PFD %u is too high (max %u)\n", 377 name, val, vco / 16); 378 379 val = pll_readl(pll, PLL_CTRL1); 380 381 old_postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) & 382 PLL_INT_CTRL1_POSTDIV1_MASK; 383 old_postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) & 384 PLL_INT_CTRL1_POSTDIV2_MASK; 385 if (enabled && 386 (params->postdiv1 != old_postdiv1 || 387 params->postdiv2 != old_postdiv2)) 388 pr_warn("%s: changing postdiv while PLL is enabled\n", name); 389 390 if (params->postdiv2 > params->postdiv1) 391 pr_warn("%s: postdiv2 should not exceed postdiv1\n", name); 392 393 val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) | 394 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT) | 395 (PLL_INT_CTRL1_POSTDIV1_MASK << PLL_INT_CTRL1_POSTDIV1_SHIFT) | 396 (PLL_INT_CTRL1_POSTDIV2_MASK << PLL_INT_CTRL1_POSTDIV2_SHIFT)); 397 val |= (params->refdiv << PLL_CTRL1_REFDIV_SHIFT) | 398 (params->fbdiv << PLL_CTRL1_FBDIV_SHIFT) | 399 (params->postdiv1 << PLL_INT_CTRL1_POSTDIV1_SHIFT) | 400 (params->postdiv2 << PLL_INT_CTRL1_POSTDIV2_SHIFT); 401 pll_writel(pll, val, PLL_CTRL1); 402 403 if (enabled) 404 pll_lock(pll); 405 406 return 0; 407} 408 409static unsigned long pll_gf40lp_laint_recalc_rate(struct clk_hw *hw, 410 unsigned long parent_rate) 411{ 412 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 413 u32 val, prediv, fbdiv, postdiv1, postdiv2; 414 u64 rate = parent_rate; 415 416 val = pll_readl(pll, PLL_CTRL1); 417 prediv = (val >> PLL_CTRL1_REFDIV_SHIFT) & PLL_CTRL1_REFDIV_MASK; 418 fbdiv = (val >> PLL_CTRL1_FBDIV_SHIFT) & PLL_CTRL1_FBDIV_MASK; 419 postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) & 420 PLL_INT_CTRL1_POSTDIV1_MASK; 421 postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) & 422 PLL_INT_CTRL1_POSTDIV2_MASK; 423 424 rate *= fbdiv; 425 rate = do_div_round_closest(rate, prediv * postdiv1 * postdiv2); 426 427 return rate; 428} 429 430static const struct clk_ops pll_gf40lp_laint_ops = { 431 .enable = pll_gf40lp_laint_enable, 432 .disable = pll_gf40lp_laint_disable, 433 .is_enabled = pll_gf40lp_laint_is_enabled, 434 .recalc_rate = pll_gf40lp_laint_recalc_rate, 435 .round_rate = pll_round_rate, 436 .set_rate = pll_gf40lp_laint_set_rate, 437}; 438 439static const struct clk_ops pll_gf40lp_laint_fixed_ops = { 440 .enable = pll_gf40lp_laint_enable, 441 .disable = pll_gf40lp_laint_disable, 442 .is_enabled = pll_gf40lp_laint_is_enabled, 443 .recalc_rate = pll_gf40lp_laint_recalc_rate, 444}; 445 446static struct clk *pll_register(const char *name, const char *parent_name, 447 unsigned long flags, void __iomem *base, 448 enum pistachio_pll_type type, 449 struct pistachio_pll_rate_table *rates, 450 unsigned int nr_rates) 451{ 452 struct pistachio_clk_pll *pll; 453 struct clk_init_data init; 454 struct clk *clk; 455 456 pll = kzalloc(sizeof(*pll), GFP_KERNEL); 457 if (!pll) 458 return ERR_PTR(-ENOMEM); 459 460 init.name = name; 461 init.flags = flags | CLK_GET_RATE_NOCACHE; 462 init.parent_names = &parent_name; 463 init.num_parents = 1; 464 465 switch (type) { 466 case PLL_GF40LP_FRAC: 467 if (rates) 468 init.ops = &pll_gf40lp_frac_ops; 469 else 470 init.ops = &pll_gf40lp_frac_fixed_ops; 471 break; 472 case PLL_GF40LP_LAINT: 473 if (rates) 474 init.ops = &pll_gf40lp_laint_ops; 475 else 476 init.ops = &pll_gf40lp_laint_fixed_ops; 477 break; 478 default: 479 pr_err("Unrecognized PLL type %u\n", type); 480 kfree(pll); 481 return ERR_PTR(-EINVAL); 482 } 483 484 pll->hw.init = &init; 485 pll->base = base; 486 pll->rates = rates; 487 pll->nr_rates = nr_rates; 488 489 clk = clk_register(NULL, &pll->hw); 490 if (IS_ERR(clk)) 491 kfree(pll); 492 493 return clk; 494} 495 496void pistachio_clk_register_pll(struct pistachio_clk_provider *p, 497 struct pistachio_pll *pll, 498 unsigned int num) 499{ 500 struct clk *clk; 501 unsigned int i; 502 503 for (i = 0; i < num; i++) { 504 clk = pll_register(pll[i].name, pll[i].parent, 505 0, p->base + pll[i].reg_base, 506 pll[i].type, pll[i].rates, 507 pll[i].nr_rates); 508 p->clk_data.clks[pll[i].id] = clk; 509 } 510}