135-clk-Avoid-sending-high-rates-to-downstream-clocks-during-set_rate.patch 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. Content-Type: text/plain; charset="utf-8"
  2. MIME-Version: 1.0
  3. Content-Transfer-Encoding: 7bit
  4. Subject: [v3, 03/13] clk: Avoid sending high rates to downstream clocks during
  5. set_rate
  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
  14. If a clock is on and we call clk_set_rate() on it we may get into
  15. a situation where the clock temporarily increases in rate
  16. dramatically while we walk the tree and call .set_rate() ops. For
  17. example, consider a case where a PLL feeds into a divider.
  18. Initially the divider is set to divide by 1 and the PLL is
  19. running fairly slow (100MHz). The downstream consumer of the
  20. divider output can only handle rates =< 400 MHz, but the divider
  21. can only choose between divisors of 1 and 4.
  22. +-----+ +----------------+
  23. | PLL |-->| div 1 or div 4 |---> consumer device
  24. +-----+ +----------------+
  25. To achieve a rate of 400MHz on the output of the divider, we
  26. would have to set the rate of the PLL to 1.6 GHz and then divide
  27. it by 4. The current code would set the PLL to 1.6GHz first while
  28. the divider is still set to 1, thus causing the downstream
  29. consumer of the clock to receive a few clock cycles of 1.6GHz
  30. clock (far beyond it's maximum acceptable rate). We should be
  31. changing the divider first before increasing the PLL rate to
  32. avoid this problem.
  33. Therefore, set the rate of any child clocks that are increasing
  34. in rate from their current rate so that they can increase their
  35. dividers if necessary. We assume that there isn't such a thing as
  36. minimum rate requirements.
  37. Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
  38. ---
  39. drivers/clk/clk.c | 34 ++++++++++++++++++++++------------
  40. 1 file changed, 22 insertions(+), 12 deletions(-)
  41. --- a/drivers/clk/clk.c
  42. +++ b/drivers/clk/clk.c
  43. @@ -1476,21 +1476,23 @@ static struct clk *clk_propagate_rate_ch
  44. * walk down a subtree and set the new rates notifying the rate
  45. * change on the way
  46. */
  47. -static void clk_change_rate(struct clk *clk)
  48. +static void clk_change_rate(struct clk *clk, unsigned long best_parent_rate)
  49. {
  50. struct clk *child;
  51. struct hlist_node *tmp;
  52. unsigned long old_rate;
  53. - unsigned long best_parent_rate = 0;
  54. bool skip_set_rate = false;
  55. struct clk *old_parent;
  56. - old_rate = clk->rate;
  57. + hlist_for_each_entry(child, &clk->children, child_node) {
  58. + /* Skip children who will be reparented to another clock */
  59. + if (child->new_parent && child->new_parent != clk)
  60. + continue;
  61. + if (child->new_rate > child->rate)
  62. + clk_change_rate(child, clk->new_rate);
  63. + }
  64. - if (clk->new_parent)
  65. - best_parent_rate = clk->new_parent->rate;
  66. - else if (clk->parent)
  67. - best_parent_rate = clk->parent->rate;
  68. + old_rate = clk->rate;
  69. if (clk->new_parent && clk->new_parent != clk->parent) {
  70. old_parent = __clk_set_parent_before(clk, clk->new_parent);
  71. @@ -1510,7 +1512,7 @@ static void clk_change_rate(struct clk *
  72. if (!skip_set_rate && clk->ops->set_rate)
  73. clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate);
  74. - clk->rate = clk_recalc(clk, best_parent_rate);
  75. + clk->rate = clk->new_rate;
  76. if (clk->notifier_count && old_rate != clk->rate)
  77. __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
  78. @@ -1523,12 +1525,13 @@ static void clk_change_rate(struct clk *
  79. /* Skip children who will be reparented to another clock */
  80. if (child->new_parent && child->new_parent != clk)
  81. continue;
  82. - clk_change_rate(child);
  83. + if (child->new_rate != child->rate)
  84. + clk_change_rate(child, clk->new_rate);
  85. }
  86. /* handle the new child who might not be in clk->children yet */
  87. - if (clk->new_child)
  88. - clk_change_rate(clk->new_child);
  89. + if (clk->new_child && clk->new_child->new_rate != clk->new_child->rate)
  90. + clk_change_rate(clk->new_child, clk->new_rate);
  91. }
  92. /**
  93. @@ -1556,6 +1559,7 @@ int clk_set_rate(struct clk *clk, unsign
  94. {
  95. struct clk *top, *fail_clk;
  96. int ret = 0;
  97. + unsigned long parent_rate;
  98. if (!clk)
  99. return 0;
  100. @@ -1589,8 +1593,13 @@ int clk_set_rate(struct clk *clk, unsign
  101. goto out;
  102. }
  103. + if (top->parent)
  104. + parent_rate = top->parent->rate;
  105. + else
  106. + parent_rate = 0;
  107. +
  108. /* change the rates */
  109. - clk_change_rate(top);
  110. + clk_change_rate(top, parent_rate);
  111. out:
  112. clk_prepare_unlock();