0347-clk-bcm2835-Skip-PLLC-clocks-when-deciding-on-a-new-.patch 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. From ca56b6fab9cfc0beca2a706193f1c158e124c1f9 Mon Sep 17 00:00:00 2001
  2. From: Eric Anholt <eric@anholt.net>
  3. Date: Tue, 26 Apr 2016 12:39:45 -0700
  4. Subject: [PATCH] clk: bcm2835: Skip PLLC clocks when deciding on a new clock
  5. parent
  6. If the firmware had set up a clock to source from PLLC, go along with
  7. it. But if we're looking for a new parent, we don't want to switch it
  8. to PLLC because the firmware will force PLLC (and thus the AXI bus
  9. clock) to different frequencies during over-temp/under-voltage,
  10. without notification to Linux.
  11. On my system, this moves the Linux-enabled HDMI state machine and DSI1
  12. escape clock over to plld_per from pllc_per. EMMC still ends up on
  13. pllc_per, because the firmware had set it up to use that.
  14. Signed-off-by: Eric Anholt <eric@anholt.net>
  15. Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks")
  16. ---
  17. drivers/clk/bcm/clk-bcm2835.c | 23 +++++++++++++++++++++++
  18. 1 file changed, 23 insertions(+)
  19. --- a/drivers/clk/bcm/clk-bcm2835.c
  20. +++ b/drivers/clk/bcm/clk-bcm2835.c
  21. @@ -1028,16 +1028,28 @@ static int bcm2835_clock_set_rate(struct
  22. return 0;
  23. }
  24. +static bool
  25. +bcm2835_clk_is_pllc(struct clk_hw *hw)
  26. +{
  27. + if (!hw)
  28. + return false;
  29. +
  30. + return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0;
  31. +}
  32. +
  33. static int bcm2835_clock_determine_rate(struct clk_hw *hw,
  34. struct clk_rate_request *req)
  35. {
  36. struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
  37. struct clk_hw *parent, *best_parent = NULL;
  38. + bool current_parent_is_pllc;
  39. unsigned long rate, best_rate = 0;
  40. unsigned long prate, best_prate = 0;
  41. size_t i;
  42. u32 div;
  43. + current_parent_is_pllc = bcm2835_clk_is_pllc(clk_hw_get_parent(hw));
  44. +
  45. /*
  46. * Select parent clock that results in the closest but lower rate
  47. */
  48. @@ -1045,6 +1057,17 @@ static int bcm2835_clock_determine_rate(
  49. parent = clk_hw_get_parent_by_index(hw, i);
  50. if (!parent)
  51. continue;
  52. +
  53. + /*
  54. + * Don't choose a PLLC-derived clock as our parent
  55. + * unless it had been manually set that way. PLLC's
  56. + * frequency gets adjusted by the firmware due to
  57. + * over-temp or under-voltage conditions, without
  58. + * prior notification to our clock consumer.
  59. + */
  60. + if (bcm2835_clk_is_pllc(parent) && !current_parent_is_pllc)
  61. + continue;
  62. +
  63. prate = clk_hw_get_rate(parent);
  64. div = bcm2835_clock_choose_div(hw, req->rate, prate, true);
  65. rate = bcm2835_clock_rate_from_divisor(clock, prate, div);