aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.c58
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.h1
2 files changed, 34 insertions, 25 deletions
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 446a9a4eee18..3890f20be7d5 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -74,8 +74,13 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
74 * Even though 40 bits are present, use only 32 for ease of calculation. 74 * Even though 40 bits are present, use only 32 for ease of calculation.
75 */ 75 */
76#define ALPHA_REG_BITWIDTH 40 76#define ALPHA_REG_BITWIDTH 40
77#define ALPHA_BITWIDTH 32 77#define ALPHA_REG_16BIT_WIDTH 16
78#define ALPHA_16BIT_MASK 0xffff 78#define ALPHA_BITWIDTH 32U
79#define ALPHA_SHIFT(w) min(w, ALPHA_BITWIDTH)
80
81#define pll_alpha_width(p) \
82 ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \
83 ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH)
79 84
80#define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \ 85#define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \
81 struct clk_alpha_pll, clkr) 86 struct clk_alpha_pll, clkr)
@@ -312,13 +317,15 @@ static void clk_alpha_pll_disable(struct clk_hw *hw)
312 regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), mask, 0); 317 regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), mask, 0);
313} 318}
314 319
315static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a) 320static unsigned long
321alpha_pll_calc_rate(u64 prate, u32 l, u32 a, u32 alpha_width)
316{ 322{
317 return (prate * l) + ((prate * a) >> ALPHA_BITWIDTH); 323 return (prate * l) + ((prate * a) >> ALPHA_SHIFT(alpha_width));
318} 324}
319 325
320static unsigned long 326static unsigned long
321alpha_pll_round_rate(unsigned long rate, unsigned long prate, u32 *l, u64 *a) 327alpha_pll_round_rate(unsigned long rate, unsigned long prate, u32 *l, u64 *a,
328 u32 alpha_width)
322{ 329{
323 u64 remainder; 330 u64 remainder;
324 u64 quotient; 331 u64 quotient;
@@ -333,14 +340,15 @@ alpha_pll_round_rate(unsigned long rate, unsigned long prate, u32 *l, u64 *a)
333 } 340 }
334 341
335 /* Upper ALPHA_BITWIDTH bits of Alpha */ 342 /* Upper ALPHA_BITWIDTH bits of Alpha */
336 quotient = remainder << ALPHA_BITWIDTH; 343 quotient = remainder << ALPHA_SHIFT(alpha_width);
344
337 remainder = do_div(quotient, prate); 345 remainder = do_div(quotient, prate);
338 346
339 if (remainder) 347 if (remainder)
340 quotient++; 348 quotient++;
341 349
342 *a = quotient; 350 *a = quotient;
343 return alpha_pll_calc_rate(prate, *l, *a); 351 return alpha_pll_calc_rate(prate, *l, *a, alpha_width);
344} 352}
345 353
346static const struct pll_vco * 354static const struct pll_vco *
@@ -362,23 +370,26 @@ clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
362 u32 l, low, high, ctl; 370 u32 l, low, high, ctl;
363 u64 a = 0, prate = parent_rate; 371 u64 a = 0, prate = parent_rate;
364 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 372 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
373 u32 alpha_width = pll_alpha_width(pll);
365 374
366 regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); 375 regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);
367 376
368 regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); 377 regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);
369 if (ctl & PLL_ALPHA_EN) { 378 if (ctl & PLL_ALPHA_EN) {
370 regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low); 379 regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low);
371 if (pll->flags & SUPPORTS_16BIT_ALPHA) { 380 if (alpha_width > 32) {
372 a = low & ALPHA_16BIT_MASK;
373 } else {
374 regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), 381 regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll),
375 &high); 382 &high);
376 a = (u64)high << 32 | low; 383 a = (u64)high << 32 | low;
377 a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH; 384 } else {
385 a = low & GENMASK(alpha_width - 1, 0);
378 } 386 }
387
388 if (alpha_width > ALPHA_BITWIDTH)
389 a >>= alpha_width - ALPHA_BITWIDTH;
379 } 390 }
380 391
381 return alpha_pll_calc_rate(prate, l, a); 392 return alpha_pll_calc_rate(prate, l, a, alpha_width);
382} 393}
383 394
384static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate, 395static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -386,10 +397,10 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
386{ 397{
387 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 398 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
388 const struct pll_vco *vco; 399 const struct pll_vco *vco;
389 u32 l; 400 u32 l, alpha_width = pll_alpha_width(pll);
390 u64 a; 401 u64 a;
391 402
392 rate = alpha_pll_round_rate(rate, prate, &l, &a); 403 rate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);
393 vco = alpha_pll_find_vco(pll, rate); 404 vco = alpha_pll_find_vco(pll, rate);
394 if (!vco) { 405 if (!vco) {
395 pr_err("alpha pll not in a valid vco range\n"); 406 pr_err("alpha pll not in a valid vco range\n");
@@ -398,14 +409,13 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
398 409
399 regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); 410 regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
400 411
401 if (pll->flags & SUPPORTS_16BIT_ALPHA) { 412 if (alpha_width > ALPHA_BITWIDTH)
402 regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), 413 a <<= alpha_width - ALPHA_BITWIDTH;
403 a & ALPHA_16BIT_MASK); 414
404 } else { 415 if (alpha_width > 32)
405 a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH); 416 regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);
406 regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), 417
407 a >> 32); 418 regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
408 }
409 419
410 regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), 420 regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),
411 PLL_VCO_MASK << PLL_VCO_SHIFT, 421 PLL_VCO_MASK << PLL_VCO_SHIFT,
@@ -421,11 +431,11 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
421 unsigned long *prate) 431 unsigned long *prate)
422{ 432{
423 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 433 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
424 u32 l; 434 u32 l, alpha_width = pll_alpha_width(pll);
425 u64 a; 435 u64 a;
426 unsigned long min_freq, max_freq; 436 unsigned long min_freq, max_freq;
427 437
428 rate = alpha_pll_round_rate(rate, *prate, &l, &a); 438 rate = alpha_pll_round_rate(rate, *prate, &l, &a, alpha_width);
429 if (alpha_pll_find_vco(pll, rate)) 439 if (alpha_pll_find_vco(pll, rate))
430 return rate; 440 return rate;
431 441
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index ef7c75effbfe..18c0c3eff855 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -59,7 +59,6 @@ struct clk_alpha_pll {
59 const struct pll_vco *vco_table; 59 const struct pll_vco *vco_table;
60 size_t num_vco; 60 size_t num_vco;
61#define SUPPORTS_OFFLINE_REQ BIT(0) 61#define SUPPORTS_OFFLINE_REQ BIT(0)
62#define SUPPORTS_16BIT_ALPHA BIT(1)
63#define SUPPORTS_FSM_MODE BIT(2) 62#define SUPPORTS_FSM_MODE BIT(2)
64 u8 flags; 63 u8 flags;
65 64