aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Turquette <mturquette@linaro.org>2014-09-26 19:10:57 -0400
committerMike Turquette <mturquette@linaro.org>2014-09-26 19:10:57 -0400
commitdb0bcc33a8aabab462c996baeac619f21616d938 (patch)
tree935394b4fe27ab92ea260e7a095330524a5fe9f8
parentb6b2fe5b6e956c8217a7584472a3ac5c068b61d4 (diff)
parent229fd4a505553c3a475b90e9aa8e452f5d78eb3b (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.c68
-rw-r--r--drivers/clk/qcom/clk-pll.h20
-rw-r--r--drivers/clk/qcom/clk-rcg.c115
-rw-r--r--drivers/clk/qcom/clk-rcg.h6
-rw-r--r--drivers/clk/qcom/clk-rcg2.c19
-rw-r--r--drivers/clk/qcom/common.c16
-rw-r--r--drivers/clk/qcom/common.h4
-rw-r--r--drivers/clk/qcom/gcc-ipq806x.c31
-rw-r--r--drivers/clk/qcom/mmcc-msm8960.c28
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
97clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) 97clk_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
129static const
130struct 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
142static long
143clk_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
156static int
157clk_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
122const struct clk_ops clk_pll_ops = { 186const 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};
127EXPORT_SYMBOL_GPL(clk_pll_ops); 193EXPORT_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 */
27struct 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 */
31struct clk_pll { 47struct 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
25static u32 ns_to_src(struct src_sel *s, u32 ns) 26static 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, &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
193static void configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f) 194static 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, &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, &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
256static int clk_dyn_rcg_set_parent(struct clk_hw *hw, u8 index) 259static 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, &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, &reg);
342
343 if (banked_mn)
344 regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &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
363static const 363 if (banked_p)
364struct 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
376static long _freq_tbl_determine_rate(struct clk_hw *hw, 369static 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 */
115struct clk_dyn_rcg { 116struct 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
175static const
176struct 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
189static long _freq_tbl_determine_rate(struct clk_hw *hw, 176static 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
31const
32struct 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}
44EXPORT_SYMBOL_GPL(qcom_find_freq);
45
30struct regmap * 46struct regmap *
31qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc) 47qcom_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;
18struct clk_regmap; 18struct clk_regmap;
19struct qcom_reset_map; 19struct qcom_reset_map;
20struct regmap; 20struct regmap;
21struct freq_tbl;
21 22
22struct qcom_cc_desc { 23struct 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
31extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
32 unsigned long rate);
33
30extern struct regmap *qcom_cc_map(struct platform_device *pdev, 34extern struct regmap *qcom_cc_map(struct platform_device *pdev,
31 const struct qcom_cc_desc *desc); 35 const struct qcom_cc_desc *desc);
32extern int qcom_cc_really_probe(struct platform_device *pdev, 36extern 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
35static 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
51static 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
35static struct clk_pll pll3 = { 62static 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[] = {
154static const char *gcc_pxo_pll8_pll0_map[] = { 181static 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
160static struct freq_tbl clk_tbl_gsbi_uart[] = { 187static struct freq_tbl clk_tbl_gsbi_uart[] = {
@@ -2133,6 +2160,8 @@ static struct clk_branch usb_fs1_h_clk = {
2133}; 2160};
2134 2161
2135static struct clk_regmap *gcc_ipq806x_clks[] = { 2162static 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
775static struct clk_dyn_rcg gfx2d0_src = { 775static 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
833static struct clk_dyn_rcg gfx2d1_src = { 835static 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
932static struct clk_dyn_rcg gfx3d_src = { 936static 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
1008static struct clk_dyn_rcg vcap_src = { 1014static 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
1213static struct clk_dyn_rcg mdp_src = { 1221static 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
1320static struct clk_dyn_rcg rot_src = { 1330static 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
1544static struct clk_dyn_rcg vcodec_src = { 1556static 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,