brcm2708: update linux 4.4 patches to latest version
[openwrt/staging/dedeckeh.git] / target / linux / brcm2708 / patches-4.4 / 0253-clk-bcm2835-Support-for-clock-parent-selection.patch
1 From 8578eeecb147439b7286e14cd0ce8a5078851f56 Mon Sep 17 00:00:00 2001
2 From: Remi Pommarel <repk@triplefau.lt>
3 Date: Sun, 6 Dec 2015 17:22:47 +0100
4 Subject: [PATCH 253/381] clk: bcm2835: Support for clock parent selection
5
6 Some bcm2835 clocks used by hardware (like "PWM" or "H264") can have multiple
7 parent clocks. These clocks divide the rate of a parent which can be selected by
8 setting the proper bits in the clock control register.
9
10 Previously all these parents where handled by a mux clock. But a mux clock
11 cannot be used because updating clock control register to select parent needs a
12 password to be xor'd with the parent index.
13
14 This patch get rid of mux clock and make these clocks handle their own parent,
15 allowing them to select the one to use.
16
17 Signed-off-by: Remi Pommarel <repk@triplefau.lt>
18 Reviewed-by: Eric Anholt <eric@anholt.net>
19 Signed-off-by: Michael Turquette <mturquette@baylibre.com>
20 (cherry picked from commit 6d18b8adbe679b5947aa822b676efff230acc5f6)
21 ---
22 drivers/clk/bcm/clk-bcm2835.c | 122 ++++++++++++++++++++++++++----------------
23 1 file changed, 77 insertions(+), 45 deletions(-)
24
25 --- a/drivers/clk/bcm/clk-bcm2835.c
26 +++ b/drivers/clk/bcm/clk-bcm2835.c
27 @@ -1205,16 +1205,6 @@ static long bcm2835_clock_rate_from_divi
28 return temp;
29 }
30
31 -static long bcm2835_clock_round_rate(struct clk_hw *hw,
32 - unsigned long rate,
33 - unsigned long *parent_rate)
34 -{
35 - struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
36 - u32 div = bcm2835_clock_choose_div(hw, rate, *parent_rate, false);
37 -
38 - return bcm2835_clock_rate_from_divisor(clock, *parent_rate, div);
39 -}
40 -
41 static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw,
42 unsigned long parent_rate)
43 {
44 @@ -1286,13 +1276,75 @@ static int bcm2835_clock_set_rate(struct
45 return 0;
46 }
47
48 +static int bcm2835_clock_determine_rate(struct clk_hw *hw,
49 + struct clk_rate_request *req)
50 +{
51 + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
52 + struct clk_hw *parent, *best_parent = NULL;
53 + unsigned long rate, best_rate = 0;
54 + unsigned long prate, best_prate = 0;
55 + size_t i;
56 + u32 div;
57 +
58 + /*
59 + * Select parent clock that results in the closest but lower rate
60 + */
61 + for (i = 0; i < clk_hw_get_num_parents(hw); ++i) {
62 + parent = clk_hw_get_parent_by_index(hw, i);
63 + if (!parent)
64 + continue;
65 + prate = clk_hw_get_rate(parent);
66 + div = bcm2835_clock_choose_div(hw, req->rate, prate, true);
67 + rate = bcm2835_clock_rate_from_divisor(clock, prate, div);
68 + if (rate > best_rate && rate <= req->rate) {
69 + best_parent = parent;
70 + best_prate = prate;
71 + best_rate = rate;
72 + }
73 + }
74 +
75 + if (!best_parent)
76 + return -EINVAL;
77 +
78 + req->best_parent_hw = best_parent;
79 + req->best_parent_rate = best_prate;
80 +
81 + req->rate = best_rate;
82 +
83 + return 0;
84 +}
85 +
86 +static int bcm2835_clock_set_parent(struct clk_hw *hw, u8 index)
87 +{
88 + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
89 + struct bcm2835_cprman *cprman = clock->cprman;
90 + const struct bcm2835_clock_data *data = clock->data;
91 + u8 src = (index << CM_SRC_SHIFT) & CM_SRC_MASK;
92 +
93 + cprman_write(cprman, data->ctl_reg, src);
94 + return 0;
95 +}
96 +
97 +static u8 bcm2835_clock_get_parent(struct clk_hw *hw)
98 +{
99 + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
100 + struct bcm2835_cprman *cprman = clock->cprman;
101 + const struct bcm2835_clock_data *data = clock->data;
102 + u32 src = cprman_read(cprman, data->ctl_reg);
103 +
104 + return (src & CM_SRC_MASK) >> CM_SRC_SHIFT;
105 +}
106 +
107 +
108 static const struct clk_ops bcm2835_clock_clk_ops = {
109 .is_prepared = bcm2835_clock_is_on,
110 .prepare = bcm2835_clock_on,
111 .unprepare = bcm2835_clock_off,
112 .recalc_rate = bcm2835_clock_get_rate,
113 .set_rate = bcm2835_clock_set_rate,
114 - .round_rate = bcm2835_clock_round_rate,
115 + .determine_rate = bcm2835_clock_determine_rate,
116 + .set_parent = bcm2835_clock_set_parent,
117 + .get_parent = bcm2835_clock_get_parent,
118 };
119
120 static int bcm2835_vpu_clock_is_on(struct clk_hw *hw)
121 @@ -1308,7 +1360,9 @@ static const struct clk_ops bcm2835_vpu_
122 .is_prepared = bcm2835_vpu_clock_is_on,
123 .recalc_rate = bcm2835_clock_get_rate,
124 .set_rate = bcm2835_clock_set_rate,
125 - .round_rate = bcm2835_clock_round_rate,
126 + .determine_rate = bcm2835_clock_determine_rate,
127 + .set_parent = bcm2835_clock_set_parent,
128 + .get_parent = bcm2835_clock_get_parent,
129 };
130
131 static struct clk *bcm2835_register_pll(struct bcm2835_cprman *cprman,
132 @@ -1402,45 +1456,23 @@ static struct clk *bcm2835_register_cloc
133 {
134 struct bcm2835_clock *clock;
135 struct clk_init_data init;
136 - const char *parent;
137 + const char *parents[1 << CM_SRC_BITS];
138 + size_t i;
139
140 /*
141 - * Most of the clock generators have a mux field, so we
142 - * instantiate a generic mux as our parent to handle it.
143 + * Replace our "xosc" references with the oscillator's
144 + * actual name.
145 */
146 - if (data->num_mux_parents) {
147 - const char *parents[1 << CM_SRC_BITS];
148 - int i;
149 -
150 - parent = devm_kasprintf(cprman->dev, GFP_KERNEL,
151 - "mux_%s", data->name);
152 - if (!parent)
153 - return NULL;
154 -
155 - /*
156 - * Replace our "xosc" references with the oscillator's
157 - * actual name.
158 - */
159 - for (i = 0; i < data->num_mux_parents; i++) {
160 - if (strcmp(data->parents[i], "xosc") == 0)
161 - parents[i] = cprman->osc_name;
162 - else
163 - parents[i] = data->parents[i];
164 - }
165 -
166 - clk_register_mux(cprman->dev, parent,
167 - parents, data->num_mux_parents,
168 - CLK_SET_RATE_PARENT,
169 - cprman->regs + data->ctl_reg,
170 - CM_SRC_SHIFT, CM_SRC_BITS,
171 - 0, &cprman->regs_lock);
172 - } else {
173 - parent = data->parents[0];
174 + for (i = 0; i < data->num_mux_parents; i++) {
175 + if (strcmp(data->parents[i], "xosc") == 0)
176 + parents[i] = cprman->osc_name;
177 + else
178 + parents[i] = data->parents[i];
179 }
180
181 memset(&init, 0, sizeof(init));
182 - init.parent_names = &parent;
183 - init.num_parents = 1;
184 + init.parent_names = parents;
185 + init.num_parents = data->num_mux_parents;
186 init.name = data->name;
187 init.flags = CLK_IGNORE_UNUSED;
188