bcm53xx: add clk tree driver
[openwrt/svn-archive/archive.git] / target / linux / bcm53xx / patches-4.3 / 049-clk-iproc-Separate-status-and-control-variables.patch
1 From eeb32564795a3584dba6281f445ff2aa552be36b Mon Sep 17 00:00:00 2001
2 From: Jon Mason <jonmason@broadcom.com>
3 Date: Thu, 15 Oct 2015 15:48:30 -0400
4 Subject: [PATCH 49/50] clk: iproc: Separate status and control variables
5
6 Some PLLs have separate registers for Status and Control. The means the
7 pll_base needs to be split into 2 new variables, so that those PLLs can
8 specify device tree registers for those independently. Also, add a new
9 driver flag to identify this presence of the split, and let the driver
10 know that additional registers need to be used.
11
12 Signed-off-by: Jon Mason <jonmason@broadcom.com>
13 ---
14 drivers/clk/bcm/clk-iproc-pll.c | 96 ++++++++++++++++++++++++-----------------
15 drivers/clk/bcm/clk-iproc.h | 6 +++
16 2 files changed, 62 insertions(+), 40 deletions(-)
17
18 --- a/drivers/clk/bcm/clk-iproc-pll.c
19 +++ b/drivers/clk/bcm/clk-iproc-pll.c
20 @@ -74,7 +74,8 @@ struct iproc_clk {
21 };
22
23 struct iproc_pll {
24 - void __iomem *pll_base;
25 + void __iomem *status_base;
26 + void __iomem *control_base;
27 void __iomem *pwr_base;
28 void __iomem *asiu_base;
29
30 @@ -127,7 +128,7 @@ static int pll_wait_for_lock(struct ipro
31 const struct iproc_pll_ctrl *ctrl = pll->ctrl;
32
33 for (i = 0; i < LOCK_DELAY; i++) {
34 - u32 val = readl(pll->pll_base + ctrl->status.offset);
35 + u32 val = readl(pll->status_base + ctrl->status.offset);
36
37 if (val & (1 << ctrl->status.shift))
38 return 0;
39 @@ -145,7 +146,7 @@ static void iproc_pll_write(const struct
40 writel(val, base + offset);
41
42 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK &&
43 - base == pll->pll_base))
44 + (base == pll->status_base || base == pll->control_base)))
45 val = readl(base + offset);
46 }
47
48 @@ -161,9 +162,9 @@ static void __pll_disable(struct iproc_p
49 }
50
51 if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
52 - val = readl(pll->pll_base + ctrl->aon.offset);
53 + val = readl(pll->control_base + ctrl->aon.offset);
54 val |= (bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
55 - iproc_pll_write(pll, pll->pll_base, ctrl->aon.offset, val);
56 + iproc_pll_write(pll, pll->control_base, ctrl->aon.offset, val);
57 }
58
59 if (pll->pwr_base) {
60 @@ -184,9 +185,9 @@ static int __pll_enable(struct iproc_pll
61 u32 val;
62
63 if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
64 - val = readl(pll->pll_base + ctrl->aon.offset);
65 + val = readl(pll->control_base + ctrl->aon.offset);
66 val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
67 - iproc_pll_write(pll, pll->pll_base, ctrl->aon.offset, val);
68 + iproc_pll_write(pll, pll->control_base, ctrl->aon.offset, val);
69 }
70
71 if (pll->pwr_base) {
72 @@ -213,9 +214,9 @@ static void __pll_put_in_reset(struct ip
73 const struct iproc_pll_ctrl *ctrl = pll->ctrl;
74 const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
75
76 - val = readl(pll->pll_base + reset->offset);
77 + val = readl(pll->control_base + reset->offset);
78 val &= ~(1 << reset->reset_shift | 1 << reset->p_reset_shift);
79 - iproc_pll_write(pll, pll->pll_base, reset->offset, val);
80 + iproc_pll_write(pll, pll->control_base, reset->offset, val);
81 }
82
83 static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp,
84 @@ -226,17 +227,17 @@ static void __pll_bring_out_reset(struct
85 const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
86 const struct iproc_pll_dig_filter_ctrl *dig_filter = &ctrl->dig_filter;
87
88 - val = readl(pll->pll_base + dig_filter->offset);
89 + val = readl(pll->control_base + dig_filter->offset);
90 val &= ~(bit_mask(dig_filter->ki_width) << dig_filter->ki_shift |
91 bit_mask(dig_filter->kp_width) << dig_filter->kp_shift |
92 bit_mask(dig_filter->ka_width) << dig_filter->ka_shift);
93 val |= ki << dig_filter->ki_shift | kp << dig_filter->kp_shift |
94 ka << dig_filter->ka_shift;
95 - iproc_pll_write(pll, pll->pll_base, dig_filter->offset, val);
96 + iproc_pll_write(pll, pll->control_base, dig_filter->offset, val);
97
98 - val = readl(pll->pll_base + reset->offset);
99 + val = readl(pll->control_base + reset->offset);
100 val |= 1 << reset->reset_shift | 1 << reset->p_reset_shift;
101 - iproc_pll_write(pll, pll->pll_base, reset->offset, val);
102 + iproc_pll_write(pll, pll->control_base, reset->offset, val);
103 }
104
105 static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
106 @@ -291,9 +292,9 @@ static int pll_set_rate(struct iproc_clk
107 /* put PLL in reset */
108 __pll_put_in_reset(pll);
109
110 - iproc_pll_write(pll, pll->pll_base, ctrl->vco_ctrl.u_offset, 0);
111 + iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.u_offset, 0);
112
113 - val = readl(pll->pll_base + ctrl->vco_ctrl.l_offset);
114 + val = readl(pll->control_base + ctrl->vco_ctrl.l_offset);
115
116 if (rate >= VCO_LOW && rate < VCO_MID)
117 val |= (1 << PLL_VCO_LOW_SHIFT);
118 @@ -303,29 +304,29 @@ static int pll_set_rate(struct iproc_clk
119 else
120 val |= (1 << PLL_VCO_HIGH_SHIFT);
121
122 - iproc_pll_write(pll, pll->pll_base, ctrl->vco_ctrl.l_offset, val);
123 + iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.l_offset, val);
124
125 /* program integer part of NDIV */
126 - val = readl(pll->pll_base + ctrl->ndiv_int.offset);
127 + val = readl(pll->control_base + ctrl->ndiv_int.offset);
128 val &= ~(bit_mask(ctrl->ndiv_int.width) << ctrl->ndiv_int.shift);
129 val |= vco->ndiv_int << ctrl->ndiv_int.shift;
130 - iproc_pll_write(pll, pll->pll_base, ctrl->ndiv_int.offset, val);
131 + iproc_pll_write(pll, pll->control_base, ctrl->ndiv_int.offset, val);
132
133 /* program fractional part of NDIV */
134 if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
135 - val = readl(pll->pll_base + ctrl->ndiv_frac.offset);
136 + val = readl(pll->control_base + ctrl->ndiv_frac.offset);
137 val &= ~(bit_mask(ctrl->ndiv_frac.width) <<
138 ctrl->ndiv_frac.shift);
139 val |= vco->ndiv_frac << ctrl->ndiv_frac.shift;
140 - iproc_pll_write(pll, pll->pll_base, ctrl->ndiv_frac.offset,
141 + iproc_pll_write(pll, pll->control_base, ctrl->ndiv_frac.offset,
142 val);
143 }
144
145 /* program PDIV */
146 - val = readl(pll->pll_base + ctrl->pdiv.offset);
147 + val = readl(pll->control_base + ctrl->pdiv.offset);
148 val &= ~(bit_mask(ctrl->pdiv.width) << ctrl->pdiv.shift);
149 val |= vco->pdiv << ctrl->pdiv.shift;
150 - iproc_pll_write(pll, pll->pll_base, ctrl->pdiv.offset, val);
151 + iproc_pll_write(pll, pll->control_base, ctrl->pdiv.offset, val);
152
153 __pll_bring_out_reset(pll, kp, ka, ki);
154
155 @@ -372,7 +373,7 @@ static unsigned long iproc_pll_recalc_ra
156 return 0;
157
158 /* PLL needs to be locked */
159 - val = readl(pll->pll_base + ctrl->status.offset);
160 + val = readl(pll->status_base + ctrl->status.offset);
161 if ((val & (1 << ctrl->status.shift)) == 0) {
162 clk->rate = 0;
163 return 0;
164 @@ -383,19 +384,19 @@ static unsigned long iproc_pll_recalc_ra
165 *
166 * ((ndiv_int + ndiv_frac / 2^20) * (parent clock rate / pdiv)
167 */
168 - val = readl(pll->pll_base + ctrl->ndiv_int.offset);
169 + val = readl(pll->control_base + ctrl->ndiv_int.offset);
170 ndiv_int = (val >> ctrl->ndiv_int.shift) &
171 bit_mask(ctrl->ndiv_int.width);
172 ndiv = ndiv_int << 20;
173
174 if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
175 - val = readl(pll->pll_base + ctrl->ndiv_frac.offset);
176 + val = readl(pll->control_base + ctrl->ndiv_frac.offset);
177 ndiv_frac = (val >> ctrl->ndiv_frac.shift) &
178 bit_mask(ctrl->ndiv_frac.width);
179 ndiv += ndiv_frac;
180 }
181
182 - val = readl(pll->pll_base + ctrl->pdiv.offset);
183 + val = readl(pll->control_base + ctrl->pdiv.offset);
184 pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width);
185
186 clk->rate = (ndiv * parent_rate) >> 20;
187 @@ -460,14 +461,14 @@ static int iproc_clk_enable(struct clk_h
188 u32 val;
189
190 /* channel enable is active low */
191 - val = readl(pll->pll_base + ctrl->enable.offset);
192 + val = readl(pll->control_base + ctrl->enable.offset);
193 val &= ~(1 << ctrl->enable.enable_shift);
194 - iproc_pll_write(pll, pll->pll_base, ctrl->enable.offset, val);
195 + iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
196
197 /* also make sure channel is not held */
198 - val = readl(pll->pll_base + ctrl->enable.offset);
199 + val = readl(pll->control_base + ctrl->enable.offset);
200 val &= ~(1 << ctrl->enable.hold_shift);
201 - iproc_pll_write(pll, pll->pll_base, ctrl->enable.offset, val);
202 + iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
203
204 return 0;
205 }
206 @@ -482,9 +483,9 @@ static void iproc_clk_disable(struct clk
207 if (ctrl->flags & IPROC_CLK_AON)
208 return;
209
210 - val = readl(pll->pll_base + ctrl->enable.offset);
211 + val = readl(pll->control_base + ctrl->enable.offset);
212 val |= 1 << ctrl->enable.enable_shift;
213 - iproc_pll_write(pll, pll->pll_base, ctrl->enable.offset, val);
214 + iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
215 }
216
217 static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw,
218 @@ -499,7 +500,7 @@ static unsigned long iproc_clk_recalc_ra
219 if (parent_rate == 0)
220 return 0;
221
222 - val = readl(pll->pll_base + ctrl->mdiv.offset);
223 + val = readl(pll->control_base + ctrl->mdiv.offset);
224 mdiv = (val >> ctrl->mdiv.shift) & bit_mask(ctrl->mdiv.width);
225 if (mdiv == 0)
226 mdiv = 256;
227 @@ -546,14 +547,14 @@ static int iproc_clk_set_rate(struct clk
228 if (div > 256)
229 return -EINVAL;
230
231 - val = readl(pll->pll_base + ctrl->mdiv.offset);
232 + val = readl(pll->control_base + ctrl->mdiv.offset);
233 if (div == 256) {
234 val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
235 } else {
236 val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
237 val |= div << ctrl->mdiv.shift;
238 }
239 - iproc_pll_write(pll, pll->pll_base, ctrl->mdiv.offset, val);
240 + iproc_pll_write(pll, pll->control_base, ctrl->mdiv.offset, val);
241 clk->rate = parent_rate / div;
242
243 return 0;
244 @@ -578,9 +579,10 @@ static void iproc_pll_sw_cfg(struct ipro
245 if (ctrl->flags & IPROC_CLK_PLL_NEEDS_SW_CFG) {
246 u32 val;
247
248 - val = readl(pll->pll_base + ctrl->sw_ctrl.offset);
249 + val = readl(pll->control_base + ctrl->sw_ctrl.offset);
250 val |= BIT(ctrl->sw_ctrl.shift);
251 - iproc_pll_write(pll, pll->pll_base, ctrl->sw_ctrl.offset, val);
252 + iproc_pll_write(pll, pll->control_base, ctrl->sw_ctrl.offset,
253 + val);
254 }
255 }
256
257 @@ -615,8 +617,8 @@ void __init iproc_pll_clk_setup(struct d
258 if (WARN_ON(!pll->clks))
259 goto err_clks;
260
261 - pll->pll_base = of_iomap(node, 0);
262 - if (WARN_ON(!pll->pll_base))
263 + pll->control_base = of_iomap(node, 0);
264 + if (WARN_ON(!pll->control_base))
265 goto err_pll_iomap;
266
267 /* Some SoCs do not require the pwr_base, thus failing is not fatal */
268 @@ -629,6 +631,16 @@ void __init iproc_pll_clk_setup(struct d
269 goto err_asiu_iomap;
270 }
271
272 + if (pll_ctrl->flags & IPROC_CLK_PLL_SPLIT_STAT_CTRL) {
273 + /* Some SoCs have a split status/control. If this does not
274 + * exist, assume they are unified.
275 + */
276 + pll->status_base = of_iomap(node, 2);
277 + if (!pll->status_base)
278 + goto err_status_iomap;
279 + } else
280 + pll->status_base = pll->control_base;
281 +
282 /* initialize and register the PLL itself */
283 pll->ctrl = pll_ctrl;
284
285 @@ -699,6 +711,10 @@ err_clk_register:
286 clk_unregister(pll->clk_data.clks[i]);
287
288 err_pll_register:
289 + if (pll->status_base != pll->control_base)
290 + iounmap(pll->status_base);
291 +
292 +err_status_iomap:
293 if (pll->asiu_base)
294 iounmap(pll->asiu_base);
295
296 @@ -706,7 +722,7 @@ err_asiu_iomap:
297 if (pll->pwr_base)
298 iounmap(pll->pwr_base);
299
300 - iounmap(pll->pll_base);
301 + iounmap(pll->control_base);
302
303 err_pll_iomap:
304 kfree(pll->clks);
305 --- a/drivers/clk/bcm/clk-iproc.h
306 +++ b/drivers/clk/bcm/clk-iproc.h
307 @@ -55,6 +55,12 @@
308 #define IPROC_CLK_EMBED_PWRCTRL BIT(5)
309
310 /*
311 + * Some PLLs have separate registers for Status and Control. Identify this to
312 + * let the driver know if additional registers need to be used
313 + */
314 +#define IPROC_CLK_PLL_SPLIT_STAT_CTRL BIT(6)
315 +
316 +/*
317 * Parameters for VCO frequency configuration
318 *
319 * VCO frequency =