diff options
author | Max Schwarz <max.schwarz@online.de> | 2014-11-20 04:26:50 -0500 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2014-11-23 11:27:46 -0500 |
commit | 249051f49907e7d147228a7d27a8ec37da1ea0fa (patch) | |
tree | a21bd2db97db21b85fe9614f6ea21f1e88b37331 /drivers/i2c | |
parent | 727f9c2dad9dd3e9aff4f64e92df577f1409a768 (diff) |
i2c: rk3x: handle dynamic clock rate changes correctly
The i2c input clock can change dynamically, e.g. on the RK3066 where
pclk_i2c0 and pclk_i2c1 are connected to the armclk, which changes
rate on cpu frequency scaling.
Until now, we incorrectly called clk_get_rate() while holding the
i2c->lock in rk3x_i2c_xfer() to adapt to clock rate changes.
Thanks to Huang Tao for reporting this issue.
Do it properly now using the clk notifier framework. The callback
logic was taken from i2c-cadence.c.
Also rename all misleading "i2c_rate" variables to "clk_rate", as they
describe the *input* clk rate.
Signed-off-by: Max Schwarz <max.schwarz@online.de>
Tested-by: Doug Anderson <dianders@chromium.org> on RK3288
Reviewed-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-rk3x.c | 153 |
1 files changed, 118 insertions, 35 deletions
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index e276ffbfbd1a..0ee5802f36d3 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c | |||
@@ -98,6 +98,7 @@ struct rk3x_i2c { | |||
98 | /* Hardware resources */ | 98 | /* Hardware resources */ |
99 | void __iomem *regs; | 99 | void __iomem *regs; |
100 | struct clk *clk; | 100 | struct clk *clk; |
101 | struct notifier_block clk_rate_nb; | ||
101 | 102 | ||
102 | /* Settings */ | 103 | /* Settings */ |
103 | unsigned int scl_frequency; | 104 | unsigned int scl_frequency; |
@@ -429,15 +430,27 @@ out: | |||
429 | return IRQ_HANDLED; | 430 | return IRQ_HANDLED; |
430 | } | 431 | } |
431 | 432 | ||
432 | static int rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long scl_rate, | 433 | /** |
433 | unsigned long *div_low, unsigned long *div_high) | 434 | * Calculate divider values for desired SCL frequency |
435 | * | ||
436 | * @clk_rate: I2C input clock rate | ||
437 | * @scl_rate: Desired SCL rate | ||
438 | * @div_low: Divider output for low | ||
439 | * @div_high: Divider output for high | ||
440 | * | ||
441 | * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case | ||
442 | * a best-effort divider value is returned in divs. If the target rate is | ||
443 | * too high, we silently use the highest possible rate. | ||
444 | */ | ||
445 | static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate, | ||
446 | unsigned long *div_low, unsigned long *div_high) | ||
434 | { | 447 | { |
435 | unsigned long min_low_ns, min_high_ns; | 448 | unsigned long min_low_ns, min_high_ns; |
436 | unsigned long max_data_hold_ns; | 449 | unsigned long max_data_hold_ns; |
437 | unsigned long data_hold_buffer_ns; | 450 | unsigned long data_hold_buffer_ns; |
438 | unsigned long max_low_ns, min_total_ns; | 451 | unsigned long max_low_ns, min_total_ns; |
439 | 452 | ||
440 | unsigned long i2c_rate_khz, scl_rate_khz; | 453 | unsigned long clk_rate_khz, scl_rate_khz; |
441 | 454 | ||
442 | unsigned long min_low_div, min_high_div; | 455 | unsigned long min_low_div, min_high_div; |
443 | unsigned long max_low_div; | 456 | unsigned long max_low_div; |
@@ -445,6 +458,8 @@ static int rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long scl_rate, | |||
445 | unsigned long min_div_for_hold, min_total_div; | 458 | unsigned long min_div_for_hold, min_total_div; |
446 | unsigned long extra_div, extra_low_div, ideal_low_div; | 459 | unsigned long extra_div, extra_low_div, ideal_low_div; |
447 | 460 | ||
461 | int ret = 0; | ||
462 | |||
448 | /* Only support standard-mode and fast-mode */ | 463 | /* Only support standard-mode and fast-mode */ |
449 | if (WARN_ON(scl_rate > 400000)) | 464 | if (WARN_ON(scl_rate > 400000)) |
450 | scl_rate = 400000; | 465 | scl_rate = 400000; |
@@ -480,25 +495,25 @@ static int rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long scl_rate, | |||
480 | min_total_ns = min_low_ns + min_high_ns; | 495 | min_total_ns = min_low_ns + min_high_ns; |
481 | 496 | ||
482 | /* Adjust to avoid overflow */ | 497 | /* Adjust to avoid overflow */ |
483 | i2c_rate_khz = DIV_ROUND_UP(i2c_rate, 1000); | 498 | clk_rate_khz = DIV_ROUND_UP(clk_rate, 1000); |
484 | scl_rate_khz = scl_rate / 1000; | 499 | scl_rate_khz = scl_rate / 1000; |
485 | 500 | ||
486 | /* | 501 | /* |
487 | * We need the total div to be >= this number | 502 | * We need the total div to be >= this number |
488 | * so we don't clock too fast. | 503 | * so we don't clock too fast. |
489 | */ | 504 | */ |
490 | min_total_div = DIV_ROUND_UP(i2c_rate_khz, scl_rate_khz * 8); | 505 | min_total_div = DIV_ROUND_UP(clk_rate_khz, scl_rate_khz * 8); |
491 | 506 | ||
492 | /* These are the min dividers needed for min hold times. */ | 507 | /* These are the min dividers needed for min hold times. */ |
493 | min_low_div = DIV_ROUND_UP(i2c_rate_khz * min_low_ns, 8 * 1000000); | 508 | min_low_div = DIV_ROUND_UP(clk_rate_khz * min_low_ns, 8 * 1000000); |
494 | min_high_div = DIV_ROUND_UP(i2c_rate_khz * min_high_ns, 8 * 1000000); | 509 | min_high_div = DIV_ROUND_UP(clk_rate_khz * min_high_ns, 8 * 1000000); |
495 | min_div_for_hold = (min_low_div + min_high_div); | 510 | min_div_for_hold = (min_low_div + min_high_div); |
496 | 511 | ||
497 | /* | 512 | /* |
498 | * This is the maximum divider so we don't go over the max. | 513 | * This is the maximum divider so we don't go over the max. |
499 | * We don't round up here (we round down) since this is a max. | 514 | * We don't round up here (we round down) since this is a max. |
500 | */ | 515 | */ |
501 | max_low_div = i2c_rate_khz * max_low_ns / (8 * 1000000); | 516 | max_low_div = clk_rate_khz * max_low_ns / (8 * 1000000); |
502 | 517 | ||
503 | if (min_low_div > max_low_div) { | 518 | if (min_low_div > max_low_div) { |
504 | WARN_ONCE(true, | 519 | WARN_ONCE(true, |
@@ -526,7 +541,7 @@ static int rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long scl_rate, | |||
526 | * biasing slightly towards having a higher div | 541 | * biasing slightly towards having a higher div |
527 | * for low (spend more time low). | 542 | * for low (spend more time low). |
528 | */ | 543 | */ |
529 | ideal_low_div = DIV_ROUND_UP(i2c_rate_khz * min_low_ns, | 544 | ideal_low_div = DIV_ROUND_UP(clk_rate_khz * min_low_ns, |
530 | scl_rate_khz * 8 * min_total_ns); | 545 | scl_rate_khz * 8 * min_total_ns); |
531 | 546 | ||
532 | /* Don't allow it to go over the max */ | 547 | /* Don't allow it to go over the max */ |
@@ -547,40 +562,99 @@ static int rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long scl_rate, | |||
547 | } | 562 | } |
548 | 563 | ||
549 | /* | 564 | /* |
550 | * Adjust to the fact that the hardware has an implicit "+1". | 565 | * Adjust to the fact that the hardware has an implicit "+1". |
551 | * NOTE: Above calculations always produce div_low > 0 and div_high > 0. | 566 | * NOTE: Above calculations always produce div_low > 0 and div_high > 0. |
552 | */ | 567 | */ |
553 | *div_low = *div_low - 1; | 568 | *div_low = *div_low - 1; |
554 | *div_high = *div_high - 1; | 569 | *div_high = *div_high - 1; |
555 | 570 | ||
556 | if (*div_low >= 0xffff || *div_high >= 0xffff) | 571 | /* Maximum divider supported by hw is 0xffff */ |
557 | return -EINVAL; | 572 | if (*div_low > 0xffff) { |
558 | else | 573 | *div_low = 0xffff; |
559 | return 0; | 574 | ret = -EINVAL; |
575 | } | ||
576 | |||
577 | if (*div_high > 0xffff) { | ||
578 | *div_high = 0xffff; | ||
579 | ret = -EINVAL; | ||
580 | } | ||
581 | |||
582 | return ret; | ||
560 | } | 583 | } |
561 | 584 | ||
562 | static int rk3x_i2c_set_scl_rate(struct rk3x_i2c *i2c, unsigned long scl_rate) | 585 | static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate) |
563 | { | 586 | { |
564 | unsigned long i2c_rate = clk_get_rate(i2c->clk); | ||
565 | unsigned long div_low, div_high; | 587 | unsigned long div_low, div_high; |
566 | u64 t_low_ns, t_high_ns; | 588 | u64 t_low_ns, t_high_ns; |
567 | int ret = 0; | 589 | int ret; |
568 | 590 | ||
569 | ret = rk3x_i2c_calc_divs(i2c_rate, scl_rate, &div_low, &div_high); | 591 | ret = rk3x_i2c_calc_divs(clk_rate, i2c->scl_frequency, &div_low, |
570 | if (ret < 0) | 592 | &div_high); |
571 | return ret; | ||
572 | 593 | ||
594 | WARN_ONCE(ret != 0, "Could not reach SCL freq %u", i2c->scl_frequency); | ||
595 | |||
596 | clk_enable(i2c->clk); | ||
573 | i2c_writel(i2c, (div_high << 16) | (div_low & 0xffff), REG_CLKDIV); | 597 | i2c_writel(i2c, (div_high << 16) | (div_low & 0xffff), REG_CLKDIV); |
598 | clk_disable(i2c->clk); | ||
574 | 599 | ||
575 | t_low_ns = div_u64(((u64)div_low + 1) * 8 * 1000000000, i2c_rate); | 600 | t_low_ns = div_u64(((u64)div_low + 1) * 8 * 1000000000, clk_rate); |
576 | t_high_ns = div_u64(((u64)div_high + 1) * 8 * 1000000000, i2c_rate); | 601 | t_high_ns = div_u64(((u64)div_high + 1) * 8 * 1000000000, clk_rate); |
577 | dev_dbg(i2c->dev, | 602 | dev_dbg(i2c->dev, |
578 | "CLK %lukhz, Req %luns, Act low %lluns high %lluns\n", | 603 | "CLK %lukhz, Req %uns, Act low %lluns high %lluns\n", |
579 | i2c_rate / 1000, | 604 | clk_rate / 1000, |
580 | 1000000000 / scl_rate, | 605 | 1000000000 / i2c->scl_frequency, |
581 | t_low_ns, t_high_ns); | 606 | t_low_ns, t_high_ns); |
607 | } | ||
582 | 608 | ||
583 | return ret; | 609 | /** |
610 | * rk3x_i2c_clk_notifier_cb - Clock rate change callback | ||
611 | * @nb: Pointer to notifier block | ||
612 | * @event: Notification reason | ||
613 | * @data: Pointer to notification data object | ||
614 | * | ||
615 | * The callback checks whether a valid bus frequency can be generated after the | ||
616 | * change. If so, the change is acknowledged, otherwise the change is aborted. | ||
617 | * New dividers are written to the HW in the pre- or post change notification | ||
618 | * depending on the scaling direction. | ||
619 | * | ||
620 | * Code adapted from i2c-cadence.c. | ||
621 | * | ||
622 | * Return: NOTIFY_STOP if the rate change should be aborted, NOTIFY_OK | ||
623 | * to acknowedge the change, NOTIFY_DONE if the notification is | ||
624 | * considered irrelevant. | ||
625 | */ | ||
626 | static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long | ||
627 | event, void *data) | ||
628 | { | ||
629 | struct clk_notifier_data *ndata = data; | ||
630 | struct rk3x_i2c *i2c = container_of(nb, struct rk3x_i2c, clk_rate_nb); | ||
631 | unsigned long div_low, div_high; | ||
632 | |||
633 | switch (event) { | ||
634 | case PRE_RATE_CHANGE: | ||
635 | if (rk3x_i2c_calc_divs(ndata->new_rate, i2c->scl_frequency, | ||
636 | &div_low, &div_high) != 0) { | ||
637 | return NOTIFY_STOP; | ||
638 | } | ||
639 | |||
640 | /* scale up */ | ||
641 | if (ndata->new_rate > ndata->old_rate) | ||
642 | rk3x_i2c_adapt_div(i2c, ndata->new_rate); | ||
643 | |||
644 | return NOTIFY_OK; | ||
645 | case POST_RATE_CHANGE: | ||
646 | /* scale down */ | ||
647 | if (ndata->new_rate < ndata->old_rate) | ||
648 | rk3x_i2c_adapt_div(i2c, ndata->new_rate); | ||
649 | return NOTIFY_OK; | ||
650 | case ABORT_RATE_CHANGE: | ||
651 | /* scale up */ | ||
652 | if (ndata->new_rate > ndata->old_rate) | ||
653 | rk3x_i2c_adapt_div(i2c, ndata->old_rate); | ||
654 | return NOTIFY_OK; | ||
655 | default: | ||
656 | return NOTIFY_DONE; | ||
657 | } | ||
584 | } | 658 | } |
585 | 659 | ||
586 | /** | 660 | /** |
@@ -677,11 +751,6 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap, | |||
677 | 751 | ||
678 | clk_enable(i2c->clk); | 752 | clk_enable(i2c->clk); |
679 | 753 | ||
680 | /* The clock rate might have changed, so setup the divider again */ | ||
681 | ret = rk3x_i2c_set_scl_rate(i2c, i2c->scl_frequency); | ||
682 | if (ret < 0) | ||
683 | goto exit; | ||
684 | |||
685 | i2c->is_last_msg = false; | 754 | i2c->is_last_msg = false; |
686 | 755 | ||
687 | /* | 756 | /* |
@@ -728,7 +797,6 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap, | |||
728 | } | 797 | } |
729 | } | 798 | } |
730 | 799 | ||
731 | exit: | ||
732 | clk_disable(i2c->clk); | 800 | clk_disable(i2c->clk); |
733 | spin_unlock_irqrestore(&i2c->lock, flags); | 801 | spin_unlock_irqrestore(&i2c->lock, flags); |
734 | 802 | ||
@@ -768,6 +836,7 @@ static int rk3x_i2c_probe(struct platform_device *pdev) | |||
768 | int bus_nr; | 836 | int bus_nr; |
769 | u32 value; | 837 | u32 value; |
770 | int irq; | 838 | int irq; |
839 | unsigned long clk_rate; | ||
771 | 840 | ||
772 | i2c = devm_kzalloc(&pdev->dev, sizeof(struct rk3x_i2c), GFP_KERNEL); | 841 | i2c = devm_kzalloc(&pdev->dev, sizeof(struct rk3x_i2c), GFP_KERNEL); |
773 | if (!i2c) | 842 | if (!i2c) |
@@ -868,16 +937,28 @@ static int rk3x_i2c_probe(struct platform_device *pdev) | |||
868 | return ret; | 937 | return ret; |
869 | } | 938 | } |
870 | 939 | ||
940 | i2c->clk_rate_nb.notifier_call = rk3x_i2c_clk_notifier_cb; | ||
941 | ret = clk_notifier_register(i2c->clk, &i2c->clk_rate_nb); | ||
942 | if (ret != 0) { | ||
943 | dev_err(&pdev->dev, "Unable to register clock notifier\n"); | ||
944 | goto err_clk; | ||
945 | } | ||
946 | |||
947 | clk_rate = clk_get_rate(i2c->clk); | ||
948 | rk3x_i2c_adapt_div(i2c, clk_rate); | ||
949 | |||
871 | ret = i2c_add_adapter(&i2c->adap); | 950 | ret = i2c_add_adapter(&i2c->adap); |
872 | if (ret < 0) { | 951 | if (ret < 0) { |
873 | dev_err(&pdev->dev, "Could not register adapter\n"); | 952 | dev_err(&pdev->dev, "Could not register adapter\n"); |
874 | goto err_clk; | 953 | goto err_clk_notifier; |
875 | } | 954 | } |
876 | 955 | ||
877 | dev_info(&pdev->dev, "Initialized RK3xxx I2C bus at %p\n", i2c->regs); | 956 | dev_info(&pdev->dev, "Initialized RK3xxx I2C bus at %p\n", i2c->regs); |
878 | 957 | ||
879 | return 0; | 958 | return 0; |
880 | 959 | ||
960 | err_clk_notifier: | ||
961 | clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb); | ||
881 | err_clk: | 962 | err_clk: |
882 | clk_unprepare(i2c->clk); | 963 | clk_unprepare(i2c->clk); |
883 | return ret; | 964 | return ret; |
@@ -888,6 +969,8 @@ static int rk3x_i2c_remove(struct platform_device *pdev) | |||
888 | struct rk3x_i2c *i2c = platform_get_drvdata(pdev); | 969 | struct rk3x_i2c *i2c = platform_get_drvdata(pdev); |
889 | 970 | ||
890 | i2c_del_adapter(&i2c->adap); | 971 | i2c_del_adapter(&i2c->adap); |
972 | |||
973 | clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb); | ||
891 | clk_unprepare(i2c->clk); | 974 | clk_unprepare(i2c->clk); |
892 | 975 | ||
893 | return 0; | 976 | return 0; |