d8617dd6d48638497f4652693177bbdfa930343d
[oweals/openwrt.git] /
1 From 2988239956fddb3fb808cfb50fa8d4e68b893f3d Mon Sep 17 00:00:00 2001
2 From: Boris Brezillon <boris.brezillon@free-electrons.com>
3 Date: Thu, 1 Dec 2016 22:00:19 +0100
4 Subject: [PATCH] clk: bcm: Support rate change propagation on bcm2835 clocks
5
6 Some peripheral clocks, like the VEC (Video EnCoder) clock need to be set
7 to a precise rate (in our case 108MHz). With the current implementation,
8 where peripheral clocks are not allowed to forward rate change requests
9 to their parents, it is impossible to match this requirement unless the
10 bootloader has configured things correctly, or a specific rate has been
11 assigned through the DT (with the assigned-clk-rates property).
12
13 Add a new field to struct bcm2835_clock_data to specify which parent
14 clocks accept rate change propagation, and support set rate propagation
15 in bcm2835_clock_determine_rate().
16
17 Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
18 Reviewed-by: Eric Anholt <eric@anholt.net>
19 Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
20 (cherry picked from commit 155e8b3b0ee320ae866b97dd31eba8a1f080a772)
21 ---
22  drivers/clk/bcm/clk-bcm2835.c | 67 ++++++++++++++++++++++++++++++++++++++++---
23  1 file changed, 63 insertions(+), 4 deletions(-)
24
25 --- a/drivers/clk/bcm/clk-bcm2835.c
26 +++ b/drivers/clk/bcm/clk-bcm2835.c
27 @@ -436,6 +436,9 @@ struct bcm2835_clock_data {
28         const char *const *parents;
29         int num_mux_parents;
30  
31 +       /* Bitmap encoding which parents accept rate change propagation. */
32 +       unsigned int set_rate_parent;
33 +
34         u32 ctl_reg;
35         u32 div_reg;
36  
37 @@ -1021,10 +1024,60 @@ bcm2835_clk_is_pllc(struct clk_hw *hw)
38         return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0;
39  }
40  
41 +static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
42 +                                                       int parent_idx,
43 +                                                       unsigned long rate,
44 +                                                       u32 *div,
45 +                                                       unsigned long *prate)
46 +{
47 +       struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
48 +       struct bcm2835_cprman *cprman = clock->cprman;
49 +       const struct bcm2835_clock_data *data = clock->data;
50 +       unsigned long best_rate;
51 +       u32 curdiv, mindiv, maxdiv;
52 +       struct clk_hw *parent;
53 +
54 +       parent = clk_hw_get_parent_by_index(hw, parent_idx);
55 +
56 +       if (!(BIT(parent_idx) & data->set_rate_parent)) {
57 +               *prate = clk_hw_get_rate(parent);
58 +               *div = bcm2835_clock_choose_div(hw, rate, *prate, true);
59 +
60 +               return bcm2835_clock_rate_from_divisor(clock, *prate,
61 +                                                      *div);
62 +       }
63 +
64 +       if (data->frac_bits)
65 +               dev_warn(cprman->dev,
66 +                       "frac bits are not used when propagating rate change");
67 +
68 +       /* clamp to min divider of 2 if we're dealing with a mash clock */
69 +       mindiv = data->is_mash_clock ? 2 : 1;
70 +       maxdiv = BIT(data->int_bits) - 1;
71 +
72 +       /* TODO: Be smart, and only test a subset of the available divisors. */
73 +       for (curdiv = mindiv; curdiv <= maxdiv; curdiv++) {
74 +               unsigned long tmp_rate;
75 +
76 +               tmp_rate = clk_hw_round_rate(parent, rate * curdiv);
77 +               tmp_rate /= curdiv;
78 +               if (curdiv == mindiv ||
79 +                   (tmp_rate > best_rate && tmp_rate <= rate))
80 +                       best_rate = tmp_rate;
81 +
82 +               if (best_rate == rate)
83 +                       break;
84 +       }
85 +
86 +       *div = curdiv << CM_DIV_FRAC_BITS;
87 +       *prate = curdiv * best_rate;
88 +
89 +       return best_rate;
90 +}
91 +
92  static int bcm2835_clock_determine_rate(struct clk_hw *hw,
93                                         struct clk_rate_request *req)
94  {
95 -       struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
96         struct clk_hw *parent, *best_parent = NULL;
97         bool current_parent_is_pllc;
98         unsigned long rate, best_rate = 0;
99 @@ -1052,9 +1105,8 @@ static int bcm2835_clock_determine_rate(
100                 if (bcm2835_clk_is_pllc(parent) && !current_parent_is_pllc)
101                         continue;
102  
103 -               prate = clk_hw_get_rate(parent);
104 -               div = bcm2835_clock_choose_div(hw, req->rate, prate, true);
105 -               rate = bcm2835_clock_rate_from_divisor(clock, prate, div);
106 +               rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
107 +                                                         &div, &prate);
108                 if (rate > best_rate && rate <= req->rate) {
109                         best_parent = parent;
110                         best_prate = prate;
111 @@ -1275,6 +1327,13 @@ static struct clk_hw *bcm2835_register_c
112         if ((cprman_read(cprman, data->ctl_reg) & CM_ENABLE) == 0)
113                 init.flags &= ~CLK_IS_CRITICAL;
114  
115 +       /*
116 +        * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate
117 +        * rate changes on at least of the parents.
118 +        */
119 +       if (data->set_rate_parent)
120 +               init.flags |= CLK_SET_RATE_PARENT;
121 +
122         if (data->is_vpu_clock) {
123                 init.ops = &bcm2835_vpu_clock_clk_ops;
124         } else {