1 Content-Type: text/plain; charset="utf-8"
 
   3 Content-Transfer-Encoding: 7bit
 
   4 Subject: [v3, 03/13] clk: Avoid sending high rates to downstream clocks during
 
   6 From: Stephen Boyd <sboyd@codeaurora.org>
 
   7 X-Patchwork-Id: 6063271
 
   8 Message-Id: <1426920332-9340-4-git-send-email-sboyd@codeaurora.org>
 
   9 To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
 
  10 Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
 
  11         linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
 
  12         Viresh Kumar <viresh.kumar@linaro.org>
 
  13 Date: Fri, 20 Mar 2015 23:45:22 -0700
 
  15 If a clock is on and we call clk_set_rate() on it we may get into
 
  16 a situation where the clock temporarily increases in rate
 
  17 dramatically while we walk the tree and call .set_rate() ops. For
 
  18 example, consider a case where a PLL feeds into a divider.
 
  19 Initially the divider is set to divide by 1 and the PLL is
 
  20 running fairly slow (100MHz). The downstream consumer of the
 
  21 divider output can only handle rates =< 400 MHz, but the divider
 
  22 can only choose between divisors of 1 and 4.
 
  24  +-----+   +----------------+
 
  25  | PLL |-->| div 1 or div 4 |---> consumer device
 
  26  +-----+   +----------------+
 
  28 To achieve a rate of 400MHz on the output of the divider, we
 
  29 would have to set the rate of the PLL to 1.6 GHz and then divide
 
  30 it by 4. The current code would set the PLL to 1.6GHz first while
 
  31 the divider is still set to 1, thus causing the downstream
 
  32 consumer of the clock to receive a few clock cycles of 1.6GHz
 
  33 clock (far beyond it's maximum acceptable rate). We should be
 
  34 changing the divider first before increasing the PLL rate to
 
  37 Therefore, set the rate of any child clocks that are increasing
 
  38 in rate from their current rate so that they can increase their
 
  39 dividers if necessary. We assume that there isn't such a thing as
 
  40 minimum rate requirements.
 
  42 Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
 
  45 drivers/clk/clk.c | 34 ++++++++++++++++++++++------------
 
  46  1 file changed, 22 insertions(+), 12 deletions(-)
 
  48 --- a/drivers/clk/clk.c
 
  49 +++ b/drivers/clk/clk.c
 
  50 @@ -1476,21 +1476,23 @@ static struct clk *clk_propagate_rate_ch
 
  51   * walk down a subtree and set the new rates notifying the rate
 
  54 -static void clk_change_rate(struct clk *clk)
 
  55 +static void clk_change_rate(struct clk *clk, unsigned long best_parent_rate)
 
  58         struct hlist_node *tmp;
 
  59         unsigned long old_rate;
 
  60 -       unsigned long best_parent_rate = 0;
 
  61         bool skip_set_rate = false;
 
  62         struct clk *old_parent;
 
  64 -       old_rate = clk->rate;
 
  65 +       hlist_for_each_entry(child, &clk->children, child_node) {
 
  66 +               /* Skip children who will be reparented to another clock */
 
  67 +               if (child->new_parent && child->new_parent != clk)
 
  69 +               if (child->new_rate > child->rate)
 
  70 +                       clk_change_rate(child, clk->new_rate);
 
  73 -       if (clk->new_parent)
 
  74 -               best_parent_rate = clk->new_parent->rate;
 
  75 -       else if (clk->parent)
 
  76 -               best_parent_rate = clk->parent->rate;
 
  77 +       old_rate = clk->rate;
 
  79         if (clk->new_parent && clk->new_parent != clk->parent) {
 
  80                 old_parent = __clk_set_parent_before(clk, clk->new_parent);
 
  81 @@ -1510,7 +1512,7 @@ static void clk_change_rate(struct clk *
 
  82         if (!skip_set_rate && clk->ops->set_rate)
 
  83                 clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate);
 
  85 -       clk->rate = clk_recalc(clk, best_parent_rate);
 
  86 +       clk->rate = clk->new_rate;
 
  88         if (clk->notifier_count && old_rate != clk->rate)
 
  89                 __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
 
  90 @@ -1523,12 +1525,13 @@ static void clk_change_rate(struct clk *
 
  91                 /* Skip children who will be reparented to another clock */
 
  92                 if (child->new_parent && child->new_parent != clk)
 
  94 -               clk_change_rate(child);
 
  95 +               if (child->new_rate != child->rate)
 
  96 +                       clk_change_rate(child, clk->new_rate);
 
  99         /* handle the new child who might not be in clk->children yet */
 
 100 -       if (clk->new_child)
 
 101 -               clk_change_rate(clk->new_child);
 
 102 +       if (clk->new_child && clk->new_child->new_rate != clk->new_child->rate)
 
 103 +               clk_change_rate(clk->new_child, clk->new_rate);
 
 107 @@ -1556,6 +1559,7 @@ int clk_set_rate(struct clk *clk, unsign
 
 109         struct clk *top, *fail_clk;
 
 111 +       unsigned long parent_rate;
 
 115 @@ -1589,8 +1593,13 @@ int clk_set_rate(struct clk *clk, unsign
 
 120 +               parent_rate = top->parent->rate;
 
 124         /* change the rates */
 
 125 -       clk_change_rate(top);
 
 126 +       clk_change_rate(top, parent_rate);
 
 129         clk_prepare_unlock();