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)