brcm2708: update linux 4.4 patches to latest version
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-4.4 / 0581-clk-bcm-Support-rate-change-propagation-on-bcm2835-c.patch
1 From e75f021850a698fec611538e8ff293c22a4604f5 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 diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
26 index 3fbd2e8..5f0e2f3 100644
27 --- a/drivers/clk/bcm/clk-bcm2835.c
28 +++ b/drivers/clk/bcm/clk-bcm2835.c
29 @@ -457,6 +457,9 @@ struct bcm2835_clock_data {
30 const char *const *parents;
31 int num_mux_parents;
32
33 + /* Bitmap encoding which parents accept rate change propagation. */
34 + unsigned int set_rate_parent;
35 +
36 u32 ctl_reg;
37 u32 div_reg;
38
39 @@ -1055,10 +1058,60 @@ bcm2835_clk_is_pllc(struct clk_hw *hw)
40 return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0;
41 }
42
43 +static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
44 + int parent_idx,
45 + unsigned long rate,
46 + u32 *div,
47 + unsigned long *prate)
48 +{
49 + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
50 + struct bcm2835_cprman *cprman = clock->cprman;
51 + const struct bcm2835_clock_data *data = clock->data;
52 + unsigned long best_rate;
53 + u32 curdiv, mindiv, maxdiv;
54 + struct clk_hw *parent;
55 +
56 + parent = clk_hw_get_parent_by_index(hw, parent_idx);
57 +
58 + if (!(BIT(parent_idx) & data->set_rate_parent)) {
59 + *prate = clk_hw_get_rate(parent);
60 + *div = bcm2835_clock_choose_div(hw, rate, *prate, true);
61 +
62 + return bcm2835_clock_rate_from_divisor(clock, *prate,
63 + *div);
64 + }
65 +
66 + if (data->frac_bits)
67 + dev_warn(cprman->dev,
68 + "frac bits are not used when propagating rate change");
69 +
70 + /* clamp to min divider of 2 if we're dealing with a mash clock */
71 + mindiv = data->is_mash_clock ? 2 : 1;
72 + maxdiv = BIT(data->int_bits) - 1;
73 +
74 + /* TODO: Be smart, and only test a subset of the available divisors. */
75 + for (curdiv = mindiv; curdiv <= maxdiv; curdiv++) {
76 + unsigned long tmp_rate;
77 +
78 + tmp_rate = clk_hw_round_rate(parent, rate * curdiv);
79 + tmp_rate /= curdiv;
80 + if (curdiv == mindiv ||
81 + (tmp_rate > best_rate && tmp_rate <= rate))
82 + best_rate = tmp_rate;
83 +
84 + if (best_rate == rate)
85 + break;
86 + }
87 +
88 + *div = curdiv << CM_DIV_FRAC_BITS;
89 + *prate = curdiv * best_rate;
90 +
91 + return best_rate;
92 +}
93 +
94 static int bcm2835_clock_determine_rate(struct clk_hw *hw,
95 struct clk_rate_request *req)
96 {
97 - struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
98 struct clk_hw *parent, *best_parent = NULL;
99 bool current_parent_is_pllc;
100 unsigned long rate, best_rate = 0;
101 @@ -1086,9 +1139,8 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
102 if (bcm2835_clk_is_pllc(parent) && !current_parent_is_pllc)
103 continue;
104
105 - prate = clk_hw_get_rate(parent);
106 - div = bcm2835_clock_choose_div(hw, req->rate, prate, true);
107 - rate = bcm2835_clock_rate_from_divisor(clock, prate, div);
108 + rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
109 + &div, &prate);
110 if (rate > best_rate && rate <= req->rate) {
111 best_parent = parent;
112 best_prate = prate;
113 @@ -1308,6 +1360,13 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
114 if ((cprman_read(cprman, data->ctl_reg) & CM_ENABLE) == 0)
115 init.flags &= ~CLK_IS_CRITICAL;
116
117 + /*
118 + * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate
119 + * rate changes on at least of the parents.
120 + */
121 + if (data->set_rate_parent)
122 + init.flags |= CLK_SET_RATE_PARENT;
123 +
124 if (data->is_vpu_clock) {
125 init.ops = &bcm2835_vpu_clock_clk_ops;
126 } else {
127 --
128 2.1.4
129