diff options
Diffstat (limited to 'target/linux/ipq806x/patches-3.18/135-clk-Avoid-sending-high-rates-to-downstream-clocks-during-set_rate.patch')
-rw-r--r-- | target/linux/ipq806x/patches-3.18/135-clk-Avoid-sending-high-rates-to-downstream-clocks-during-set_rate.patch | 129 |
1 files changed, 0 insertions, 129 deletions
diff --git a/target/linux/ipq806x/patches-3.18/135-clk-Avoid-sending-high-rates-to-downstream-clocks-during-set_rate.patch b/target/linux/ipq806x/patches-3.18/135-clk-Avoid-sending-high-rates-to-downstream-clocks-during-set_rate.patch deleted file mode 100644 index 02d96ad..0000000 --- a/target/linux/ipq806x/patches-3.18/135-clk-Avoid-sending-high-rates-to-downstream-clocks-during-set_rate.patch +++ /dev/null @@ -1,129 +0,0 @@ -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [v3, 03/13] clk: Avoid sending high rates to downstream clocks during - set_rate -From: Stephen Boyd <sboyd@codeaurora.org> -X-Patchwork-Id: 6063271 -Message-Id: <1426920332-9340-4-git-send-email-sboyd@codeaurora.org> -To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org> -Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, - linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, - Viresh Kumar <viresh.kumar@linaro.org> -Date: Fri, 20 Mar 2015 23:45:22 -0700 - -If a clock is on and we call clk_set_rate() on it we may get into -a situation where the clock temporarily increases in rate -dramatically while we walk the tree and call .set_rate() ops. For -example, consider a case where a PLL feeds into a divider. -Initially the divider is set to divide by 1 and the PLL is -running fairly slow (100MHz). The downstream consumer of the -divider output can only handle rates =< 400 MHz, but the divider -can only choose between divisors of 1 and 4. - - +-----+ +----------------+ - | PLL |-->| div 1 or div 4 |---> consumer device - +-----+ +----------------+ - -To achieve a rate of 400MHz on the output of the divider, we -would have to set the rate of the PLL to 1.6 GHz and then divide -it by 4. The current code would set the PLL to 1.6GHz first while -the divider is still set to 1, thus causing the downstream -consumer of the clock to receive a few clock cycles of 1.6GHz -clock (far beyond it's maximum acceptable rate). We should be -changing the divider first before increasing the PLL rate to -avoid this problem. - -Therefore, set the rate of any child clocks that are increasing -in rate from their current rate so that they can increase their -dividers if necessary. We assume that there isn't such a thing as -minimum rate requirements. - -Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> - ---- -drivers/clk/clk.c | 34 ++++++++++++++++++++++------------ - 1 file changed, 22 insertions(+), 12 deletions(-) - ---- a/drivers/clk/clk.c -+++ b/drivers/clk/clk.c -@@ -1476,21 +1476,23 @@ static struct clk *clk_propagate_rate_ch - * walk down a subtree and set the new rates notifying the rate - * change on the way - */ --static void clk_change_rate(struct clk *clk) -+static void clk_change_rate(struct clk *clk, unsigned long best_parent_rate) - { - struct clk *child; - struct hlist_node *tmp; - unsigned long old_rate; -- unsigned long best_parent_rate = 0; - bool skip_set_rate = false; - struct clk *old_parent; - -- old_rate = clk->rate; -+ hlist_for_each_entry(child, &clk->children, child_node) { -+ /* Skip children who will be reparented to another clock */ -+ if (child->new_parent && child->new_parent != clk) -+ continue; -+ if (child->new_rate > child->rate) -+ clk_change_rate(child, clk->new_rate); -+ } - -- if (clk->new_parent) -- best_parent_rate = clk->new_parent->rate; -- else if (clk->parent) -- best_parent_rate = clk->parent->rate; -+ old_rate = clk->rate; - - if (clk->new_parent && clk->new_parent != clk->parent) { - old_parent = __clk_set_parent_before(clk, clk->new_parent); -@@ -1510,7 +1512,7 @@ static void clk_change_rate(struct clk * - if (!skip_set_rate && clk->ops->set_rate) - clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate); - -- clk->rate = clk_recalc(clk, best_parent_rate); -+ clk->rate = clk->new_rate; - - if (clk->notifier_count && old_rate != clk->rate) - __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); -@@ -1523,12 +1525,13 @@ static void clk_change_rate(struct clk * - /* Skip children who will be reparented to another clock */ - if (child->new_parent && child->new_parent != clk) - continue; -- clk_change_rate(child); -+ if (child->new_rate != child->rate) -+ clk_change_rate(child, clk->new_rate); - } - - /* handle the new child who might not be in clk->children yet */ -- if (clk->new_child) -- clk_change_rate(clk->new_child); -+ if (clk->new_child && clk->new_child->new_rate != clk->new_child->rate) -+ clk_change_rate(clk->new_child, clk->new_rate); - } - - /** -@@ -1556,6 +1559,7 @@ int clk_set_rate(struct clk *clk, unsign - { - struct clk *top, *fail_clk; - int ret = 0; -+ unsigned long parent_rate; - - if (!clk) - return 0; -@@ -1589,8 +1593,13 @@ int clk_set_rate(struct clk *clk, unsign - goto out; - } - -+ if (top->parent) -+ parent_rate = top->parent->rate; -+ else -+ parent_rate = 0; -+ - /* change the rates */ -- clk_change_rate(top); -+ clk_change_rate(top, parent_rate); - - out: - clk_prepare_unlock(); |