diff options
author | Mike Turquette <mturquette@linaro.org> | 2014-09-26 19:10:57 -0400 |
---|---|---|
committer | Mike Turquette <mturquette@linaro.org> | 2014-09-26 19:10:57 -0400 |
commit | db0bcc33a8aabab462c996baeac619f21616d938 (patch) | |
tree | 935394b4fe27ab92ea260e7a095330524a5fe9f8 | |
parent | b6b2fe5b6e956c8217a7584472a3ac5c068b61d4 (diff) | |
parent | 229fd4a505553c3a475b90e9aa8e452f5d78eb3b (diff) |
Merge tag 'qcom-clocks-for-3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom into clk-next
qcom clock changes for 3.18
Some fixes for the IPQ driver and some code consolidation
and refactoring.
-rw-r--r-- | drivers/clk/qcom/clk-pll.c | 68 | ||||
-rw-r--r-- | drivers/clk/qcom/clk-pll.h | 20 | ||||
-rw-r--r-- | drivers/clk/qcom/clk-rcg.c | 115 | ||||
-rw-r--r-- | drivers/clk/qcom/clk-rcg.h | 6 | ||||
-rw-r--r-- | drivers/clk/qcom/clk-rcg2.c | 19 | ||||
-rw-r--r-- | drivers/clk/qcom/common.c | 16 | ||||
-rw-r--r-- | drivers/clk/qcom/common.h | 4 | ||||
-rw-r--r-- | drivers/clk/qcom/gcc-ipq806x.c | 31 | ||||
-rw-r--r-- | drivers/clk/qcom/mmcc-msm8960.c | 28 |
9 files changed, 219 insertions, 88 deletions
diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c index 9db03d3b1657..b823bc3b6250 100644 --- a/drivers/clk/qcom/clk-pll.c +++ b/drivers/clk/qcom/clk-pll.c | |||
@@ -97,7 +97,7 @@ static unsigned long | |||
97 | clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | 97 | clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) |
98 | { | 98 | { |
99 | struct clk_pll *pll = to_clk_pll(hw); | 99 | struct clk_pll *pll = to_clk_pll(hw); |
100 | u32 l, m, n; | 100 | u32 l, m, n, config; |
101 | unsigned long rate; | 101 | unsigned long rate; |
102 | u64 tmp; | 102 | u64 tmp; |
103 | 103 | ||
@@ -116,13 +116,79 @@ clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | |||
116 | do_div(tmp, n); | 116 | do_div(tmp, n); |
117 | rate += tmp; | 117 | rate += tmp; |
118 | } | 118 | } |
119 | if (pll->post_div_width) { | ||
120 | regmap_read(pll->clkr.regmap, pll->config_reg, &config); | ||
121 | config >>= pll->post_div_shift; | ||
122 | config &= BIT(pll->post_div_width) - 1; | ||
123 | rate /= config + 1; | ||
124 | } | ||
125 | |||
119 | return rate; | 126 | return rate; |
120 | } | 127 | } |
121 | 128 | ||
129 | static const | ||
130 | struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate) | ||
131 | { | ||
132 | if (!f) | ||
133 | return NULL; | ||
134 | |||
135 | for (; f->freq; f++) | ||
136 | if (rate <= f->freq) | ||
137 | return f; | ||
138 | |||
139 | return NULL; | ||
140 | } | ||
141 | |||
142 | static long | ||
143 | clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate, | ||
144 | unsigned long *p_rate, struct clk **p) | ||
145 | { | ||
146 | struct clk_pll *pll = to_clk_pll(hw); | ||
147 | const struct pll_freq_tbl *f; | ||
148 | |||
149 | f = find_freq(pll->freq_tbl, rate); | ||
150 | if (!f) | ||
151 | return clk_pll_recalc_rate(hw, *p_rate); | ||
152 | |||
153 | return f->freq; | ||
154 | } | ||
155 | |||
156 | static int | ||
157 | clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate) | ||
158 | { | ||
159 | struct clk_pll *pll = to_clk_pll(hw); | ||
160 | const struct pll_freq_tbl *f; | ||
161 | bool enabled; | ||
162 | u32 mode; | ||
163 | u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N; | ||
164 | |||
165 | f = find_freq(pll->freq_tbl, rate); | ||
166 | if (!f) | ||
167 | return -EINVAL; | ||
168 | |||
169 | regmap_read(pll->clkr.regmap, pll->mode_reg, &mode); | ||
170 | enabled = (mode & enable_mask) == enable_mask; | ||
171 | |||
172 | if (enabled) | ||
173 | clk_pll_disable(hw); | ||
174 | |||
175 | regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l); | ||
176 | regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m); | ||
177 | regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n); | ||
178 | regmap_write(pll->clkr.regmap, pll->config_reg, f->ibits); | ||
179 | |||
180 | if (enabled) | ||
181 | clk_pll_enable(hw); | ||
182 | |||
183 | return 0; | ||
184 | } | ||
185 | |||
122 | const struct clk_ops clk_pll_ops = { | 186 | const struct clk_ops clk_pll_ops = { |
123 | .enable = clk_pll_enable, | 187 | .enable = clk_pll_enable, |
124 | .disable = clk_pll_disable, | 188 | .disable = clk_pll_disable, |
125 | .recalc_rate = clk_pll_recalc_rate, | 189 | .recalc_rate = clk_pll_recalc_rate, |
190 | .determine_rate = clk_pll_determine_rate, | ||
191 | .set_rate = clk_pll_set_rate, | ||
126 | }; | 192 | }; |
127 | EXPORT_SYMBOL_GPL(clk_pll_ops); | 193 | EXPORT_SYMBOL_GPL(clk_pll_ops); |
128 | 194 | ||
diff --git a/drivers/clk/qcom/clk-pll.h b/drivers/clk/qcom/clk-pll.h index 3003e9962472..c9c0cda306d0 100644 --- a/drivers/clk/qcom/clk-pll.h +++ b/drivers/clk/qcom/clk-pll.h | |||
@@ -18,6 +18,21 @@ | |||
18 | #include "clk-regmap.h" | 18 | #include "clk-regmap.h" |
19 | 19 | ||
20 | /** | 20 | /** |
21 | * struct pll_freq_tbl - PLL frequency table | ||
22 | * @l: L value | ||
23 | * @m: M value | ||
24 | * @n: N value | ||
25 | * @ibits: internal values | ||
26 | */ | ||
27 | struct pll_freq_tbl { | ||
28 | unsigned long freq; | ||
29 | u16 l; | ||
30 | u16 m; | ||
31 | u16 n; | ||
32 | u32 ibits; | ||
33 | }; | ||
34 | |||
35 | /** | ||
21 | * struct clk_pll - phase locked loop (PLL) | 36 | * struct clk_pll - phase locked loop (PLL) |
22 | * @l_reg: L register | 37 | * @l_reg: L register |
23 | * @m_reg: M register | 38 | * @m_reg: M register |
@@ -26,6 +41,7 @@ | |||
26 | * @mode_reg: mode register | 41 | * @mode_reg: mode register |
27 | * @status_reg: status register | 42 | * @status_reg: status register |
28 | * @status_bit: ANDed with @status_reg to determine if PLL is enabled | 43 | * @status_bit: ANDed with @status_reg to determine if PLL is enabled |
44 | * @freq_tbl: PLL frequency table | ||
29 | * @hw: handle between common and hardware-specific interfaces | 45 | * @hw: handle between common and hardware-specific interfaces |
30 | */ | 46 | */ |
31 | struct clk_pll { | 47 | struct clk_pll { |
@@ -36,6 +52,10 @@ struct clk_pll { | |||
36 | u32 mode_reg; | 52 | u32 mode_reg; |
37 | u32 status_reg; | 53 | u32 status_reg; |
38 | u8 status_bit; | 54 | u8 status_bit; |
55 | u8 post_div_width; | ||
56 | u8 post_div_shift; | ||
57 | |||
58 | const struct pll_freq_tbl *freq_tbl; | ||
39 | 59 | ||
40 | struct clk_regmap clkr; | 60 | struct clk_regmap clkr; |
41 | }; | 61 | }; |
diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c index b638c5846dbf..b6e6959e89aa 100644 --- a/drivers/clk/qcom/clk-rcg.c +++ b/drivers/clk/qcom/clk-rcg.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/div64.h> | 21 | #include <asm/div64.h> |
22 | 22 | ||
23 | #include "clk-rcg.h" | 23 | #include "clk-rcg.h" |
24 | #include "common.h" | ||
24 | 25 | ||
25 | static u32 ns_to_src(struct src_sel *s, u32 ns) | 26 | static u32 ns_to_src(struct src_sel *s, u32 ns) |
26 | { | 27 | { |
@@ -67,16 +68,16 @@ static u8 clk_dyn_rcg_get_parent(struct clk_hw *hw) | |||
67 | { | 68 | { |
68 | struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); | 69 | struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); |
69 | int num_parents = __clk_get_num_parents(hw->clk); | 70 | int num_parents = __clk_get_num_parents(hw->clk); |
70 | u32 ns, ctl; | 71 | u32 ns, reg; |
71 | int bank; | 72 | int bank; |
72 | int i; | 73 | int i; |
73 | struct src_sel *s; | 74 | struct src_sel *s; |
74 | 75 | ||
75 | regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); | 76 | regmap_read(rcg->clkr.regmap, rcg->bank_reg, ®); |
76 | bank = reg_to_bank(rcg, ctl); | 77 | bank = reg_to_bank(rcg, reg); |
77 | s = &rcg->s[bank]; | 78 | s = &rcg->s[bank]; |
78 | 79 | ||
79 | regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); | 80 | regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns); |
80 | ns = ns_to_src(s, ns); | 81 | ns = ns_to_src(s, ns); |
81 | 82 | ||
82 | for (i = 0; i < num_parents; i++) | 83 | for (i = 0; i < num_parents; i++) |
@@ -192,90 +193,93 @@ static u32 mn_to_reg(struct mn *mn, u32 m, u32 n, u32 val) | |||
192 | 193 | ||
193 | static void configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f) | 194 | static void configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f) |
194 | { | 195 | { |
195 | u32 ns, md, ctl, *regp; | 196 | u32 ns, md, reg; |
196 | int bank, new_bank; | 197 | int bank, new_bank; |
197 | struct mn *mn; | 198 | struct mn *mn; |
198 | struct pre_div *p; | 199 | struct pre_div *p; |
199 | struct src_sel *s; | 200 | struct src_sel *s; |
200 | bool enabled; | 201 | bool enabled; |
201 | u32 md_reg; | 202 | u32 md_reg, ns_reg; |
202 | u32 bank_reg; | ||
203 | bool banked_mn = !!rcg->mn[1].width; | 203 | bool banked_mn = !!rcg->mn[1].width; |
204 | bool banked_p = !!rcg->p[1].pre_div_width; | ||
204 | struct clk_hw *hw = &rcg->clkr.hw; | 205 | struct clk_hw *hw = &rcg->clkr.hw; |
205 | 206 | ||
206 | enabled = __clk_is_enabled(hw->clk); | 207 | enabled = __clk_is_enabled(hw->clk); |
207 | 208 | ||
208 | regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); | 209 | regmap_read(rcg->clkr.regmap, rcg->bank_reg, ®); |
209 | regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); | 210 | bank = reg_to_bank(rcg, reg); |
210 | |||
211 | if (banked_mn) { | ||
212 | regp = &ctl; | ||
213 | bank_reg = rcg->clkr.enable_reg; | ||
214 | } else { | ||
215 | regp = &ns; | ||
216 | bank_reg = rcg->ns_reg; | ||
217 | } | ||
218 | |||
219 | bank = reg_to_bank(rcg, *regp); | ||
220 | new_bank = enabled ? !bank : bank; | 211 | new_bank = enabled ? !bank : bank; |
221 | 212 | ||
213 | ns_reg = rcg->ns_reg[new_bank]; | ||
214 | regmap_read(rcg->clkr.regmap, ns_reg, &ns); | ||
215 | |||
222 | if (banked_mn) { | 216 | if (banked_mn) { |
223 | mn = &rcg->mn[new_bank]; | 217 | mn = &rcg->mn[new_bank]; |
224 | md_reg = rcg->md_reg[new_bank]; | 218 | md_reg = rcg->md_reg[new_bank]; |
225 | 219 | ||
226 | ns |= BIT(mn->mnctr_reset_bit); | 220 | ns |= BIT(mn->mnctr_reset_bit); |
227 | regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); | 221 | regmap_write(rcg->clkr.regmap, ns_reg, ns); |
228 | 222 | ||
229 | regmap_read(rcg->clkr.regmap, md_reg, &md); | 223 | regmap_read(rcg->clkr.regmap, md_reg, &md); |
230 | md = mn_to_md(mn, f->m, f->n, md); | 224 | md = mn_to_md(mn, f->m, f->n, md); |
231 | regmap_write(rcg->clkr.regmap, md_reg, md); | 225 | regmap_write(rcg->clkr.regmap, md_reg, md); |
232 | 226 | ||
233 | ns = mn_to_ns(mn, f->m, f->n, ns); | 227 | ns = mn_to_ns(mn, f->m, f->n, ns); |
234 | regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); | 228 | regmap_write(rcg->clkr.regmap, ns_reg, ns); |
235 | 229 | ||
236 | ctl = mn_to_reg(mn, f->m, f->n, ctl); | 230 | /* Two NS registers means mode control is in NS register */ |
237 | regmap_write(rcg->clkr.regmap, rcg->clkr.enable_reg, ctl); | 231 | if (rcg->ns_reg[0] != rcg->ns_reg[1]) { |
232 | ns = mn_to_reg(mn, f->m, f->n, ns); | ||
233 | regmap_write(rcg->clkr.regmap, ns_reg, ns); | ||
234 | } else { | ||
235 | reg = mn_to_reg(mn, f->m, f->n, reg); | ||
236 | regmap_write(rcg->clkr.regmap, rcg->bank_reg, reg); | ||
237 | } | ||
238 | 238 | ||
239 | ns &= ~BIT(mn->mnctr_reset_bit); | 239 | ns &= ~BIT(mn->mnctr_reset_bit); |
240 | regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); | 240 | regmap_write(rcg->clkr.regmap, ns_reg, ns); |
241 | } else { | 241 | } |
242 | |||
243 | if (banked_p) { | ||
242 | p = &rcg->p[new_bank]; | 244 | p = &rcg->p[new_bank]; |
243 | ns = pre_div_to_ns(p, f->pre_div - 1, ns); | 245 | ns = pre_div_to_ns(p, f->pre_div - 1, ns); |
244 | } | 246 | } |
245 | 247 | ||
246 | s = &rcg->s[new_bank]; | 248 | s = &rcg->s[new_bank]; |
247 | ns = src_to_ns(s, s->parent_map[f->src], ns); | 249 | ns = src_to_ns(s, s->parent_map[f->src], ns); |
248 | regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); | 250 | regmap_write(rcg->clkr.regmap, ns_reg, ns); |
249 | 251 | ||
250 | if (enabled) { | 252 | if (enabled) { |
251 | *regp ^= BIT(rcg->mux_sel_bit); | 253 | regmap_read(rcg->clkr.regmap, rcg->bank_reg, ®); |
252 | regmap_write(rcg->clkr.regmap, bank_reg, *regp); | 254 | reg ^= BIT(rcg->mux_sel_bit); |
255 | regmap_write(rcg->clkr.regmap, rcg->bank_reg, reg); | ||
253 | } | 256 | } |
254 | } | 257 | } |
255 | 258 | ||
256 | static int clk_dyn_rcg_set_parent(struct clk_hw *hw, u8 index) | 259 | static int clk_dyn_rcg_set_parent(struct clk_hw *hw, u8 index) |
257 | { | 260 | { |
258 | struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); | 261 | struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); |
259 | u32 ns, ctl, md, reg; | 262 | u32 ns, md, reg; |
260 | int bank; | 263 | int bank; |
261 | struct freq_tbl f = { 0 }; | 264 | struct freq_tbl f = { 0 }; |
262 | bool banked_mn = !!rcg->mn[1].width; | 265 | bool banked_mn = !!rcg->mn[1].width; |
266 | bool banked_p = !!rcg->p[1].pre_div_width; | ||
263 | 267 | ||
264 | regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); | 268 | regmap_read(rcg->clkr.regmap, rcg->bank_reg, ®); |
265 | regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); | ||
266 | reg = banked_mn ? ctl : ns; | ||
267 | |||
268 | bank = reg_to_bank(rcg, reg); | 269 | bank = reg_to_bank(rcg, reg); |
269 | 270 | ||
271 | regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns); | ||
272 | |||
270 | if (banked_mn) { | 273 | if (banked_mn) { |
271 | regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md); | 274 | regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md); |
272 | f.m = md_to_m(&rcg->mn[bank], md); | 275 | f.m = md_to_m(&rcg->mn[bank], md); |
273 | f.n = ns_m_to_n(&rcg->mn[bank], ns, f.m); | 276 | f.n = ns_m_to_n(&rcg->mn[bank], ns, f.m); |
274 | } else { | ||
275 | f.pre_div = ns_to_pre_div(&rcg->p[bank], ns) + 1; | ||
276 | } | 277 | } |
277 | f.src = index; | ||
278 | 278 | ||
279 | if (banked_p) | ||
280 | f.pre_div = ns_to_pre_div(&rcg->p[bank], ns) + 1; | ||
281 | |||
282 | f.src = index; | ||
279 | configure_bank(rcg, &f); | 283 | configure_bank(rcg, &f); |
280 | 284 | ||
281 | return 0; | 285 | return 0; |
@@ -336,41 +340,30 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | |||
336 | u32 m, n, pre_div, ns, md, mode, reg; | 340 | u32 m, n, pre_div, ns, md, mode, reg; |
337 | int bank; | 341 | int bank; |
338 | struct mn *mn; | 342 | struct mn *mn; |
343 | bool banked_p = !!rcg->p[1].pre_div_width; | ||
339 | bool banked_mn = !!rcg->mn[1].width; | 344 | bool banked_mn = !!rcg->mn[1].width; |
340 | 345 | ||
341 | regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); | 346 | regmap_read(rcg->clkr.regmap, rcg->bank_reg, ®); |
342 | |||
343 | if (banked_mn) | ||
344 | regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, ®); | ||
345 | else | ||
346 | reg = ns; | ||
347 | |||
348 | bank = reg_to_bank(rcg, reg); | 347 | bank = reg_to_bank(rcg, reg); |
349 | 348 | ||
349 | regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns); | ||
350 | m = n = pre_div = mode = 0; | ||
351 | |||
350 | if (banked_mn) { | 352 | if (banked_mn) { |
351 | mn = &rcg->mn[bank]; | 353 | mn = &rcg->mn[bank]; |
352 | regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md); | 354 | regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md); |
353 | m = md_to_m(mn, md); | 355 | m = md_to_m(mn, md); |
354 | n = ns_m_to_n(mn, ns, m); | 356 | n = ns_m_to_n(mn, ns, m); |
357 | /* Two NS registers means mode control is in NS register */ | ||
358 | if (rcg->ns_reg[0] != rcg->ns_reg[1]) | ||
359 | reg = ns; | ||
355 | mode = reg_to_mnctr_mode(mn, reg); | 360 | mode = reg_to_mnctr_mode(mn, reg); |
356 | return calc_rate(parent_rate, m, n, mode, 0); | ||
357 | } else { | ||
358 | pre_div = ns_to_pre_div(&rcg->p[bank], ns); | ||
359 | return calc_rate(parent_rate, 0, 0, 0, pre_div); | ||
360 | } | 361 | } |
361 | } | ||
362 | 362 | ||
363 | static const | 363 | if (banked_p) |
364 | struct freq_tbl *find_freq(const struct freq_tbl *f, unsigned long rate) | 364 | pre_div = ns_to_pre_div(&rcg->p[bank], ns); |
365 | { | ||
366 | if (!f) | ||
367 | return NULL; | ||
368 | |||
369 | for (; f->freq; f++) | ||
370 | if (rate <= f->freq) | ||
371 | return f; | ||
372 | 365 | ||
373 | return NULL; | 366 | return calc_rate(parent_rate, m, n, mode, pre_div); |
374 | } | 367 | } |
375 | 368 | ||
376 | static long _freq_tbl_determine_rate(struct clk_hw *hw, | 369 | static long _freq_tbl_determine_rate(struct clk_hw *hw, |
@@ -379,7 +372,7 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw, | |||
379 | { | 372 | { |
380 | unsigned long clk_flags; | 373 | unsigned long clk_flags; |
381 | 374 | ||
382 | f = find_freq(f, rate); | 375 | f = qcom_find_freq(f, rate); |
383 | if (!f) | 376 | if (!f) |
384 | return -EINVAL; | 377 | return -EINVAL; |
385 | 378 | ||
@@ -477,7 +470,7 @@ static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate, | |||
477 | struct clk_rcg *rcg = to_clk_rcg(hw); | 470 | struct clk_rcg *rcg = to_clk_rcg(hw); |
478 | const struct freq_tbl *f; | 471 | const struct freq_tbl *f; |
479 | 472 | ||
480 | f = find_freq(rcg->freq_tbl, rate); | 473 | f = qcom_find_freq(rcg->freq_tbl, rate); |
481 | if (!f) | 474 | if (!f) |
482 | return -EINVAL; | 475 | return -EINVAL; |
483 | 476 | ||
@@ -497,7 +490,7 @@ static int __clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate) | |||
497 | struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); | 490 | struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); |
498 | const struct freq_tbl *f; | 491 | const struct freq_tbl *f; |
499 | 492 | ||
500 | f = find_freq(rcg->freq_tbl, rate); | 493 | f = qcom_find_freq(rcg->freq_tbl, rate); |
501 | if (!f) | 494 | if (!f) |
502 | return -EINVAL; | 495 | return -EINVAL; |
503 | 496 | ||
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index ba0523cefd2e..687e41f91d7c 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h | |||
@@ -103,8 +103,9 @@ extern const struct clk_ops clk_rcg_bypass_ops; | |||
103 | * struct clk_dyn_rcg - root clock generator with glitch free mux | 103 | * struct clk_dyn_rcg - root clock generator with glitch free mux |
104 | * | 104 | * |
105 | * @mux_sel_bit: bit to switch glitch free mux | 105 | * @mux_sel_bit: bit to switch glitch free mux |
106 | * @ns_reg: NS register | 106 | * @ns_reg: NS0 and NS1 register |
107 | * @md_reg: MD0 and MD1 register | 107 | * @md_reg: MD0 and MD1 register |
108 | * @bank_reg: register to XOR @mux_sel_bit into to switch glitch free mux | ||
108 | * @mn: mn counter (banked) | 109 | * @mn: mn counter (banked) |
109 | * @s: source selector (banked) | 110 | * @s: source selector (banked) |
110 | * @freq_tbl: frequency table | 111 | * @freq_tbl: frequency table |
@@ -113,8 +114,9 @@ extern const struct clk_ops clk_rcg_bypass_ops; | |||
113 | * | 114 | * |
114 | */ | 115 | */ |
115 | struct clk_dyn_rcg { | 116 | struct clk_dyn_rcg { |
116 | u32 ns_reg; | 117 | u32 ns_reg[2]; |
117 | u32 md_reg[2]; | 118 | u32 md_reg[2]; |
119 | u32 bank_reg; | ||
118 | 120 | ||
119 | u8 mux_sel_bit; | 121 | u8 mux_sel_bit; |
120 | 122 | ||
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index cd185d5cc67a..cfa9eb4fe9ca 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/div64.h> | 24 | #include <asm/div64.h> |
25 | 25 | ||
26 | #include "clk-rcg.h" | 26 | #include "clk-rcg.h" |
27 | #include "common.h" | ||
27 | 28 | ||
28 | #define CMD_REG 0x0 | 29 | #define CMD_REG 0x0 |
29 | #define CMD_UPDATE BIT(0) | 30 | #define CMD_UPDATE BIT(0) |
@@ -172,27 +173,13 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | |||
172 | return calc_rate(parent_rate, m, n, mode, hid_div); | 173 | return calc_rate(parent_rate, m, n, mode, hid_div); |
173 | } | 174 | } |
174 | 175 | ||
175 | static const | ||
176 | struct freq_tbl *find_freq(const struct freq_tbl *f, unsigned long rate) | ||
177 | { | ||
178 | if (!f) | ||
179 | return NULL; | ||
180 | |||
181 | for (; f->freq; f++) | ||
182 | if (rate <= f->freq) | ||
183 | return f; | ||
184 | |||
185 | /* Default to our fastest rate */ | ||
186 | return f - 1; | ||
187 | } | ||
188 | |||
189 | static long _freq_tbl_determine_rate(struct clk_hw *hw, | 176 | static long _freq_tbl_determine_rate(struct clk_hw *hw, |
190 | const struct freq_tbl *f, unsigned long rate, | 177 | const struct freq_tbl *f, unsigned long rate, |
191 | unsigned long *p_rate, struct clk **p) | 178 | unsigned long *p_rate, struct clk **p) |
192 | { | 179 | { |
193 | unsigned long clk_flags; | 180 | unsigned long clk_flags; |
194 | 181 | ||
195 | f = find_freq(f, rate); | 182 | f = qcom_find_freq(f, rate); |
196 | if (!f) | 183 | if (!f) |
197 | return -EINVAL; | 184 | return -EINVAL; |
198 | 185 | ||
@@ -268,7 +255,7 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate) | |||
268 | struct clk_rcg2 *rcg = to_clk_rcg2(hw); | 255 | struct clk_rcg2 *rcg = to_clk_rcg2(hw); |
269 | const struct freq_tbl *f; | 256 | const struct freq_tbl *f; |
270 | 257 | ||
271 | f = find_freq(rcg->freq_tbl, rate); | 258 | f = qcom_find_freq(rcg->freq_tbl, rate); |
272 | if (!f) | 259 | if (!f) |
273 | return -EINVAL; | 260 | return -EINVAL; |
274 | 261 | ||
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index eeb3eea01f4c..e20d947db3e5 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/reset-controller.h> | 18 | #include <linux/reset-controller.h> |
19 | 19 | ||
20 | #include "common.h" | 20 | #include "common.h" |
21 | #include "clk-rcg.h" | ||
21 | #include "clk-regmap.h" | 22 | #include "clk-regmap.h" |
22 | #include "reset.h" | 23 | #include "reset.h" |
23 | 24 | ||
@@ -27,6 +28,21 @@ struct qcom_cc { | |||
27 | struct clk *clks[]; | 28 | struct clk *clks[]; |
28 | }; | 29 | }; |
29 | 30 | ||
31 | const | ||
32 | struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate) | ||
33 | { | ||
34 | if (!f) | ||
35 | return NULL; | ||
36 | |||
37 | for (; f->freq; f++) | ||
38 | if (rate <= f->freq) | ||
39 | return f; | ||
40 | |||
41 | /* Default to our fastest rate */ | ||
42 | return f - 1; | ||
43 | } | ||
44 | EXPORT_SYMBOL_GPL(qcom_find_freq); | ||
45 | |||
30 | struct regmap * | 46 | struct regmap * |
31 | qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc) | 47 | qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc) |
32 | { | 48 | { |
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h index 2765e9d3da97..f519322acdf3 100644 --- a/drivers/clk/qcom/common.h +++ b/drivers/clk/qcom/common.h | |||
@@ -18,6 +18,7 @@ struct regmap_config; | |||
18 | struct clk_regmap; | 18 | struct clk_regmap; |
19 | struct qcom_reset_map; | 19 | struct qcom_reset_map; |
20 | struct regmap; | 20 | struct regmap; |
21 | struct freq_tbl; | ||
21 | 22 | ||
22 | struct qcom_cc_desc { | 23 | struct qcom_cc_desc { |
23 | const struct regmap_config *config; | 24 | const struct regmap_config *config; |
@@ -27,6 +28,9 @@ struct qcom_cc_desc { | |||
27 | size_t num_resets; | 28 | size_t num_resets; |
28 | }; | 29 | }; |
29 | 30 | ||
31 | extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, | ||
32 | unsigned long rate); | ||
33 | |||
30 | extern struct regmap *qcom_cc_map(struct platform_device *pdev, | 34 | extern struct regmap *qcom_cc_map(struct platform_device *pdev, |
31 | const struct qcom_cc_desc *desc); | 35 | const struct qcom_cc_desc *desc); |
32 | extern int qcom_cc_really_probe(struct platform_device *pdev, | 36 | extern int qcom_cc_really_probe(struct platform_device *pdev, |
diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c index 3b83b7dd78c7..5cd62a709ac7 100644 --- a/drivers/clk/qcom/gcc-ipq806x.c +++ b/drivers/clk/qcom/gcc-ipq806x.c | |||
@@ -32,6 +32,33 @@ | |||
32 | #include "clk-branch.h" | 32 | #include "clk-branch.h" |
33 | #include "reset.h" | 33 | #include "reset.h" |
34 | 34 | ||
35 | static struct clk_pll pll0 = { | ||
36 | .l_reg = 0x30c4, | ||
37 | .m_reg = 0x30c8, | ||
38 | .n_reg = 0x30cc, | ||
39 | .config_reg = 0x30d4, | ||
40 | .mode_reg = 0x30c0, | ||
41 | .status_reg = 0x30d8, | ||
42 | .status_bit = 16, | ||
43 | .clkr.hw.init = &(struct clk_init_data){ | ||
44 | .name = "pll0", | ||
45 | .parent_names = (const char *[]){ "pxo" }, | ||
46 | .num_parents = 1, | ||
47 | .ops = &clk_pll_ops, | ||
48 | }, | ||
49 | }; | ||
50 | |||
51 | static struct clk_regmap pll0_vote = { | ||
52 | .enable_reg = 0x34c0, | ||
53 | .enable_mask = BIT(0), | ||
54 | .hw.init = &(struct clk_init_data){ | ||
55 | .name = "pll0_vote", | ||
56 | .parent_names = (const char *[]){ "pll0" }, | ||
57 | .num_parents = 1, | ||
58 | .ops = &clk_pll_vote_ops, | ||
59 | }, | ||
60 | }; | ||
61 | |||
35 | static struct clk_pll pll3 = { | 62 | static struct clk_pll pll3 = { |
36 | .l_reg = 0x3164, | 63 | .l_reg = 0x3164, |
37 | .m_reg = 0x3168, | 64 | .m_reg = 0x3168, |
@@ -154,7 +181,7 @@ static const u8 gcc_pxo_pll8_pll0[] = { | |||
154 | static const char *gcc_pxo_pll8_pll0_map[] = { | 181 | static const char *gcc_pxo_pll8_pll0_map[] = { |
155 | "pxo", | 182 | "pxo", |
156 | "pll8_vote", | 183 | "pll8_vote", |
157 | "pll0", | 184 | "pll0_vote", |
158 | }; | 185 | }; |
159 | 186 | ||
160 | static struct freq_tbl clk_tbl_gsbi_uart[] = { | 187 | static struct freq_tbl clk_tbl_gsbi_uart[] = { |
@@ -2133,6 +2160,8 @@ static struct clk_branch usb_fs1_h_clk = { | |||
2133 | }; | 2160 | }; |
2134 | 2161 | ||
2135 | static struct clk_regmap *gcc_ipq806x_clks[] = { | 2162 | static struct clk_regmap *gcc_ipq806x_clks[] = { |
2163 | [PLL0] = &pll0.clkr, | ||
2164 | [PLL0_VOTE] = &pll0_vote, | ||
2136 | [PLL3] = &pll3.clkr, | 2165 | [PLL3] = &pll3.clkr, |
2137 | [PLL8] = &pll8.clkr, | 2166 | [PLL8] = &pll8.clkr, |
2138 | [PLL8_VOTE] = &pll8_vote, | 2167 | [PLL8_VOTE] = &pll8_vote, |
diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c index 68da36cd7ed0..e8b33bbc362f 100644 --- a/drivers/clk/qcom/mmcc-msm8960.c +++ b/drivers/clk/qcom/mmcc-msm8960.c | |||
@@ -773,9 +773,11 @@ static struct freq_tbl clk_tbl_gfx2d[] = { | |||
773 | }; | 773 | }; |
774 | 774 | ||
775 | static struct clk_dyn_rcg gfx2d0_src = { | 775 | static struct clk_dyn_rcg gfx2d0_src = { |
776 | .ns_reg = 0x0070, | 776 | .ns_reg[0] = 0x0070, |
777 | .ns_reg[1] = 0x0070, | ||
777 | .md_reg[0] = 0x0064, | 778 | .md_reg[0] = 0x0064, |
778 | .md_reg[1] = 0x0068, | 779 | .md_reg[1] = 0x0068, |
780 | .bank_reg = 0x0060, | ||
779 | .mn[0] = { | 781 | .mn[0] = { |
780 | .mnctr_en_bit = 8, | 782 | .mnctr_en_bit = 8, |
781 | .mnctr_reset_bit = 25, | 783 | .mnctr_reset_bit = 25, |
@@ -831,9 +833,11 @@ static struct clk_branch gfx2d0_clk = { | |||
831 | }; | 833 | }; |
832 | 834 | ||
833 | static struct clk_dyn_rcg gfx2d1_src = { | 835 | static struct clk_dyn_rcg gfx2d1_src = { |
834 | .ns_reg = 0x007c, | 836 | .ns_reg[0] = 0x007c, |
837 | .ns_reg[1] = 0x007c, | ||
835 | .md_reg[0] = 0x0078, | 838 | .md_reg[0] = 0x0078, |
836 | .md_reg[1] = 0x006c, | 839 | .md_reg[1] = 0x006c, |
840 | .bank_reg = 0x0074, | ||
837 | .mn[0] = { | 841 | .mn[0] = { |
838 | .mnctr_en_bit = 8, | 842 | .mnctr_en_bit = 8, |
839 | .mnctr_reset_bit = 25, | 843 | .mnctr_reset_bit = 25, |
@@ -930,9 +934,11 @@ static struct freq_tbl clk_tbl_gfx3d_8064[] = { | |||
930 | }; | 934 | }; |
931 | 935 | ||
932 | static struct clk_dyn_rcg gfx3d_src = { | 936 | static struct clk_dyn_rcg gfx3d_src = { |
933 | .ns_reg = 0x008c, | 937 | .ns_reg[0] = 0x008c, |
938 | .ns_reg[1] = 0x008c, | ||
934 | .md_reg[0] = 0x0084, | 939 | .md_reg[0] = 0x0084, |
935 | .md_reg[1] = 0x0088, | 940 | .md_reg[1] = 0x0088, |
941 | .bank_reg = 0x0080, | ||
936 | .mn[0] = { | 942 | .mn[0] = { |
937 | .mnctr_en_bit = 8, | 943 | .mnctr_en_bit = 8, |
938 | .mnctr_reset_bit = 25, | 944 | .mnctr_reset_bit = 25, |
@@ -1006,9 +1012,11 @@ static struct freq_tbl clk_tbl_vcap[] = { | |||
1006 | }; | 1012 | }; |
1007 | 1013 | ||
1008 | static struct clk_dyn_rcg vcap_src = { | 1014 | static struct clk_dyn_rcg vcap_src = { |
1009 | .ns_reg = 0x021c, | 1015 | .ns_reg[0] = 0x021c, |
1016 | .ns_reg[1] = 0x021c, | ||
1010 | .md_reg[0] = 0x01ec, | 1017 | .md_reg[0] = 0x01ec, |
1011 | .md_reg[1] = 0x0218, | 1018 | .md_reg[1] = 0x0218, |
1019 | .bank_reg = 0x0178, | ||
1012 | .mn[0] = { | 1020 | .mn[0] = { |
1013 | .mnctr_en_bit = 8, | 1021 | .mnctr_en_bit = 8, |
1014 | .mnctr_reset_bit = 23, | 1022 | .mnctr_reset_bit = 23, |
@@ -1211,9 +1219,11 @@ static struct freq_tbl clk_tbl_mdp[] = { | |||
1211 | }; | 1219 | }; |
1212 | 1220 | ||
1213 | static struct clk_dyn_rcg mdp_src = { | 1221 | static struct clk_dyn_rcg mdp_src = { |
1214 | .ns_reg = 0x00d0, | 1222 | .ns_reg[0] = 0x00d0, |
1223 | .ns_reg[1] = 0x00d0, | ||
1215 | .md_reg[0] = 0x00c4, | 1224 | .md_reg[0] = 0x00c4, |
1216 | .md_reg[1] = 0x00c8, | 1225 | .md_reg[1] = 0x00c8, |
1226 | .bank_reg = 0x00c0, | ||
1217 | .mn[0] = { | 1227 | .mn[0] = { |
1218 | .mnctr_en_bit = 8, | 1228 | .mnctr_en_bit = 8, |
1219 | .mnctr_reset_bit = 31, | 1229 | .mnctr_reset_bit = 31, |
@@ -1318,7 +1328,9 @@ static struct freq_tbl clk_tbl_rot[] = { | |||
1318 | }; | 1328 | }; |
1319 | 1329 | ||
1320 | static struct clk_dyn_rcg rot_src = { | 1330 | static struct clk_dyn_rcg rot_src = { |
1321 | .ns_reg = 0x00e8, | 1331 | .ns_reg[0] = 0x00e8, |
1332 | .ns_reg[1] = 0x00e8, | ||
1333 | .bank_reg = 0x00e8, | ||
1322 | .p[0] = { | 1334 | .p[0] = { |
1323 | .pre_div_shift = 22, | 1335 | .pre_div_shift = 22, |
1324 | .pre_div_width = 4, | 1336 | .pre_div_width = 4, |
@@ -1542,9 +1554,11 @@ static struct freq_tbl clk_tbl_vcodec[] = { | |||
1542 | }; | 1554 | }; |
1543 | 1555 | ||
1544 | static struct clk_dyn_rcg vcodec_src = { | 1556 | static struct clk_dyn_rcg vcodec_src = { |
1545 | .ns_reg = 0x0100, | 1557 | .ns_reg[0] = 0x0100, |
1558 | .ns_reg[1] = 0x0100, | ||
1546 | .md_reg[0] = 0x00fc, | 1559 | .md_reg[0] = 0x00fc, |
1547 | .md_reg[1] = 0x0128, | 1560 | .md_reg[1] = 0x0128, |
1561 | .bank_reg = 0x00f8, | ||
1548 | .mn[0] = { | 1562 | .mn[0] = { |
1549 | .mnctr_en_bit = 5, | 1563 | .mnctr_en_bit = 5, |
1550 | .mnctr_reset_bit = 31, | 1564 | .mnctr_reset_bit = 31, |