diff options
-rw-r--r-- | drivers/clk/qcom/clk-alpha-pll.c | 58 | ||||
-rw-r--r-- | drivers/clk/qcom/clk-alpha-pll.h | 1 |
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 | ||
315 | static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a) | 320 | static unsigned long |
321 | alpha_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 | ||
320 | static unsigned long | 326 | static unsigned long |
321 | alpha_pll_round_rate(unsigned long rate, unsigned long prate, u32 *l, u64 *a) | 327 | alpha_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 | ||
346 | static const struct pll_vco * | 354 | static 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 | ||
384 | static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate, | 395 | static 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 | ||