diff options
author | Scott Wood <oss@buserror.net> | 2016-10-17 14:42:23 -0400 |
---|---|---|
committer | Stephen Boyd <sboyd@codeaurora.org> | 2016-11-01 20:26:15 -0400 |
commit | 7c1c5413a7bdf1c9adc8d979521f1b8286366aef (patch) | |
tree | 91e4786a854b7b2b1372d7e427436f2006e008b0 | |
parent | c7129375312732f006ba9054c12ae4d4097d5519 (diff) |
clk: qoriq: Don't allow CPU clocks higher than starting value
The boot-time frequency of a CPU is considered its rated maximum, as we
have no other source of such information. However, this was previously
only used for chips with 80% restrictions on secondary PLLs. This
usually wasn't a problem because most chips/configs boot with a divider
of /1, with other dividers being used only for dynamic frequency
reduction. However, at least one config (LS1021A at less than 1 GHz)
uses a different divider for top speed. This was causing cpufreq to set
a frequency beyond the chip's rated speed.
This is fixed by applying a 100%-of-initial-speed limit to all CPU PLLs,
similar to the existing 80% limit that only applied to some.
Signed-off-by: Scott Wood <oss@buserror.net>
Cc: stable@vger.kernel.org
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-rw-r--r-- | drivers/clk/clk-qoriq.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c index 20b105584f82..80ae2a51452d 100644 --- a/drivers/clk/clk-qoriq.c +++ b/drivers/clk/clk-qoriq.c | |||
@@ -700,6 +700,7 @@ static struct clk * __init create_mux_common(struct clockgen *cg, | |||
700 | struct mux_hwclock *hwc, | 700 | struct mux_hwclock *hwc, |
701 | const struct clk_ops *ops, | 701 | const struct clk_ops *ops, |
702 | unsigned long min_rate, | 702 | unsigned long min_rate, |
703 | unsigned long max_rate, | ||
703 | unsigned long pct80_rate, | 704 | unsigned long pct80_rate, |
704 | const char *fmt, int idx) | 705 | const char *fmt, int idx) |
705 | { | 706 | { |
@@ -728,6 +729,8 @@ static struct clk * __init create_mux_common(struct clockgen *cg, | |||
728 | continue; | 729 | continue; |
729 | if (rate < min_rate) | 730 | if (rate < min_rate) |
730 | continue; | 731 | continue; |
732 | if (rate > max_rate) | ||
733 | continue; | ||
731 | 734 | ||
732 | parent_names[j] = div->name; | 735 | parent_names[j] = div->name; |
733 | hwc->parent_to_clksel[j] = i; | 736 | hwc->parent_to_clksel[j] = i; |
@@ -759,7 +762,7 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx) | |||
759 | struct mux_hwclock *hwc; | 762 | struct mux_hwclock *hwc; |
760 | const struct clockgen_pll_div *div; | 763 | const struct clockgen_pll_div *div; |
761 | unsigned long plat_rate, min_rate; | 764 | unsigned long plat_rate, min_rate; |
762 | u64 pct80_rate; | 765 | u64 max_rate, pct80_rate; |
763 | u32 clksel; | 766 | u32 clksel; |
764 | 767 | ||
765 | hwc = kzalloc(sizeof(*hwc), GFP_KERNEL); | 768 | hwc = kzalloc(sizeof(*hwc), GFP_KERNEL); |
@@ -787,8 +790,8 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx) | |||
787 | return NULL; | 790 | return NULL; |
788 | } | 791 | } |
789 | 792 | ||
790 | pct80_rate = clk_get_rate(div->clk); | 793 | max_rate = clk_get_rate(div->clk); |
791 | pct80_rate *= 8; | 794 | pct80_rate = max_rate * 8; |
792 | do_div(pct80_rate, 10); | 795 | do_div(pct80_rate, 10); |
793 | 796 | ||
794 | plat_rate = clk_get_rate(cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk); | 797 | plat_rate = clk_get_rate(cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk); |
@@ -798,7 +801,7 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx) | |||
798 | else | 801 | else |
799 | min_rate = plat_rate / 2; | 802 | min_rate = plat_rate / 2; |
800 | 803 | ||
801 | return create_mux_common(cg, hwc, &cmux_ops, min_rate, | 804 | return create_mux_common(cg, hwc, &cmux_ops, min_rate, max_rate, |
802 | pct80_rate, "cg-cmux%d", idx); | 805 | pct80_rate, "cg-cmux%d", idx); |
803 | } | 806 | } |
804 | 807 | ||
@@ -813,7 +816,7 @@ static struct clk * __init create_one_hwaccel(struct clockgen *cg, int idx) | |||
813 | hwc->reg = cg->regs + 0x20 * idx + 0x10; | 816 | hwc->reg = cg->regs + 0x20 * idx + 0x10; |
814 | hwc->info = cg->info.hwaccel[idx]; | 817 | hwc->info = cg->info.hwaccel[idx]; |
815 | 818 | ||
816 | return create_mux_common(cg, hwc, &hwaccel_ops, 0, 0, | 819 | return create_mux_common(cg, hwc, &hwaccel_ops, 0, ULONG_MAX, 0, |
817 | "cg-hwaccel%d", idx); | 820 | "cg-hwaccel%d", idx); |
818 | } | 821 | } |
819 | 822 | ||