diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-30 14:20:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-30 14:20:02 -0400 |
commit | 1056c9bd2702ea1bb79abf9bd1e78c578589d247 (patch) | |
tree | faada7d658151c059a845cdb9d9d521817d1e611 /drivers/clk/clk-vt8500.c | |
parent | 797cee982eef9195736afc5e7f3b8f613c41d19a (diff) | |
parent | d22527fed2f094c2e4f9a66f35b68a090c3d906a (diff) |
Merge tag 'clk-for-linus-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
Pull clk updates from Michael Turquette:
"The bulk of the changes are updates and fixes to existing clk provider
drivers, along with a pretty standard number of new drivers. The core
recieved a small number of updates as well.
Core changes of note:
- removed CLK_IS_ROOT flag
New clk provider drivers:
- Renesas r8a7796 clock pulse generator / module standby and
software reset
- Allwinner sun8i H3 clock controller unit
- AmLogic meson8b clock controller (rewritten)
- AmLogic gxbb clock controller
- support for some new ICs was added by simple changes to static
data tables for chips sharing the same family
Driver updates of note:
- the Allwinner sunxi clock driver infrastucture was rewritten to
comform to the state of the art at drivers/clk/sunxi-ng. The old
implementation is still supported for backwards compatibility with
the DT ABI"
* tag 'clk-for-linus-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (162 commits)
clk: Makefile: re-sort and clean up
Revert "clk: gxbb: expose CLKID_MMC_PCLK"
clk: samsung: Allow modular build of the Audio Subsystem CLKCON driver
clk: samsung: make clk-s5pv210-audss explicitly non-modular
clk: exynos5433: remove CLK_IGNORE_UNUSED flag from SPI clocks
clk: oxnas: Add hardware dependencies
clk: imx7d: do not set parent of ethernet time/ref clocks
ARM: dt: sun8i: switch the H3 to the new CCU driver
clk: sunxi-ng: h3: Fix Kconfig symbol typo
clk: sunxi-ng: h3: Fix audio clock divider offset
clk: sunxi-ng: Add H3 clocks
clk: sunxi-ng: Add N-K-M-P factor clock
clk: sunxi-ng: Add N-K-M Factor clock
clk: sunxi-ng: Add N-M-factor clock support
clk: sunxi-ng: Add N-K-factor clock support
clk: sunxi-ng: Add M-P factor clock support
clk: sunxi-ng: Add divider
clk: sunxi-ng: Add phase clock support
clk: sunxi-ng: Add mux clock support
clk: sunxi-ng: Add gate clock support
...
Diffstat (limited to 'drivers/clk/clk-vt8500.c')
-rw-r--r-- | drivers/clk/clk-vt8500.c | 99 |
1 files changed, 44 insertions, 55 deletions
diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c index b0f76a84f1e9..37368a399ff9 100644 --- a/drivers/clk/clk-vt8500.c +++ b/drivers/clk/clk-vt8500.c | |||
@@ -383,51 +383,49 @@ static int vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate, | |||
383 | return 0; | 383 | return 0; |
384 | } | 384 | } |
385 | 385 | ||
386 | static int wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate, | 386 | /* |
387 | u32 *multiplier, u32 *divisor1, u32 *divisor2) | 387 | * M * parent [O1] => / P [O2] => / D [O3] |
388 | * Where O1 is 900MHz...3GHz; | ||
389 | * O2 is 600MHz >= (M * parent) / P >= 300MHz; | ||
390 | * M is 36...120 [25MHz parent]; D is 1 or 2 or 4 or 8. | ||
391 | * Possible ranges (O3): | ||
392 | * D = 8: 37,5MHz...75MHz | ||
393 | * D = 4: 75MHz...150MHz | ||
394 | * D = 2: 150MHz...300MHz | ||
395 | * D = 1: 300MHz...600MHz | ||
396 | */ | ||
397 | static int wm8650_find_pll_bits(unsigned long rate, | ||
398 | unsigned long parent_rate, u32 *multiplier, u32 *divisor1, | ||
399 | u32 *divisor2) | ||
388 | { | 400 | { |
389 | u32 mul, div1; | 401 | unsigned long O1, min_err, rate_err; |
390 | int div2; | ||
391 | u32 best_mul, best_div1, best_div2; | ||
392 | unsigned long tclk, rate_err, best_err; | ||
393 | |||
394 | best_err = (unsigned long)-1; | ||
395 | 402 | ||
396 | /* Find the closest match (lower or equal to requested) */ | 403 | if (!parent_rate || (rate < 37500000) || (rate > 600000000)) |
397 | for (div1 = 5; div1 >= 3; div1--) | 404 | return -EINVAL; |
398 | for (div2 = 3; div2 >= 0; div2--) | ||
399 | for (mul = 3; mul <= 1023; mul++) { | ||
400 | tclk = parent_rate * mul / (div1 * (1 << div2)); | ||
401 | if (tclk > rate) | ||
402 | continue; | ||
403 | /* error will always be +ve */ | ||
404 | rate_err = rate - tclk; | ||
405 | if (rate_err == 0) { | ||
406 | *multiplier = mul; | ||
407 | *divisor1 = div1; | ||
408 | *divisor2 = div2; | ||
409 | return 0; | ||
410 | } | ||
411 | 405 | ||
412 | if (rate_err < best_err) { | 406 | *divisor2 = rate <= 75000000 ? 3 : rate <= 150000000 ? 2 : |
413 | best_err = rate_err; | 407 | rate <= 300000000 ? 1 : 0; |
414 | best_mul = mul; | 408 | /* |
415 | best_div1 = div1; | 409 | * Divisor P cannot be calculated. Test all divisors and find where M |
416 | best_div2 = div2; | 410 | * will be as close as possible to the requested rate. |
417 | } | 411 | */ |
418 | } | 412 | min_err = ULONG_MAX; |
413 | for (*divisor1 = 5; *divisor1 >= 3; (*divisor1)--) { | ||
414 | O1 = rate * *divisor1 * (1 << (*divisor2)); | ||
415 | rate_err = O1 % parent_rate; | ||
416 | if (rate_err < min_err) { | ||
417 | *multiplier = O1 / parent_rate; | ||
418 | if (rate_err == 0) | ||
419 | return 0; | ||
420 | |||
421 | min_err = rate_err; | ||
422 | } | ||
423 | } | ||
419 | 424 | ||
420 | if (best_err == (unsigned long)-1) { | 425 | if ((*multiplier < 3) || (*multiplier > 1023)) |
421 | pr_warn("%s: impossible rate %lu\n", __func__, rate); | ||
422 | return -EINVAL; | 426 | return -EINVAL; |
423 | } | ||
424 | 427 | ||
425 | /* if we got here, it wasn't an exact match */ | 428 | pr_warn("%s: rate error is %lu\n", __func__, min_err); |
426 | pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, | ||
427 | rate - best_err); | ||
428 | *multiplier = best_mul; | ||
429 | *divisor1 = best_div1; | ||
430 | *divisor2 = best_div2; | ||
431 | 429 | ||
432 | return 0; | 430 | return 0; |
433 | } | 431 | } |
@@ -464,7 +462,6 @@ static int wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate, | |||
464 | { | 462 | { |
465 | u32 mul; | 463 | u32 mul; |
466 | int div1, div2; | 464 | int div1, div2; |
467 | u32 best_mul, best_div1, best_div2; | ||
468 | unsigned long tclk, rate_err, best_err; | 465 | unsigned long tclk, rate_err, best_err; |
469 | 466 | ||
470 | best_err = (unsigned long)-1; | 467 | best_err = (unsigned long)-1; |
@@ -488,9 +485,9 @@ static int wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate, | |||
488 | 485 | ||
489 | if (rate_err < best_err) { | 486 | if (rate_err < best_err) { |
490 | best_err = rate_err; | 487 | best_err = rate_err; |
491 | best_mul = mul; | 488 | *multiplier = mul; |
492 | best_div1 = div1; | 489 | *divisor1 = div1; |
493 | best_div2 = div2; | 490 | *divisor2 = div2; |
494 | } | 491 | } |
495 | } | 492 | } |
496 | 493 | ||
@@ -503,10 +500,7 @@ static int wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate, | |||
503 | pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, | 500 | pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, |
504 | rate - best_err); | 501 | rate - best_err); |
505 | 502 | ||
506 | *filter = wm8750_get_filter(parent_rate, best_div1); | 503 | *filter = wm8750_get_filter(parent_rate, *divisor1); |
507 | *multiplier = best_mul; | ||
508 | *divisor1 = best_div1; | ||
509 | *divisor2 = best_div2; | ||
510 | 504 | ||
511 | return 0; | 505 | return 0; |
512 | } | 506 | } |
@@ -516,7 +510,6 @@ static int wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate, | |||
516 | { | 510 | { |
517 | u32 mul; | 511 | u32 mul; |
518 | int div1, div2; | 512 | int div1, div2; |
519 | u32 best_mul, best_div1, best_div2; | ||
520 | unsigned long tclk, rate_err, best_err; | 513 | unsigned long tclk, rate_err, best_err; |
521 | 514 | ||
522 | best_err = (unsigned long)-1; | 515 | best_err = (unsigned long)-1; |
@@ -540,9 +533,9 @@ static int wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate, | |||
540 | 533 | ||
541 | if (rate_err < best_err) { | 534 | if (rate_err < best_err) { |
542 | best_err = rate_err; | 535 | best_err = rate_err; |
543 | best_mul = mul; | 536 | *multiplier = mul; |
544 | best_div1 = div1; | 537 | *divisor1 = div1; |
545 | best_div2 = div2; | 538 | *divisor2 = div2; |
546 | } | 539 | } |
547 | } | 540 | } |
548 | 541 | ||
@@ -555,10 +548,6 @@ static int wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate, | |||
555 | pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, | 548 | pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, |
556 | rate - best_err); | 549 | rate - best_err); |
557 | 550 | ||
558 | *multiplier = best_mul; | ||
559 | *divisor1 = best_div1; | ||
560 | *divisor2 = best_div2; | ||
561 | |||
562 | return 0; | 551 | return 0; |
563 | } | 552 | } |
564 | 553 | ||