]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/arm/mach-imx/clk-pllv3.c
MLK-9961-4 arm:imx6x: Change PLL1 clock management.
[karo-tx-linux.git] / arch / arm / mach-imx / clk-pllv3.c
1 /*
2  * Copyright 2012-2015 Freescale Semiconductor, Inc.
3  * Copyright 2012 Linaro Ltd.
4  *
5  * The code contained herein is licensed under the GNU General Public
6  * License. You may obtain a copy of the GNU General Public License
7  * Version 2 or later at the following locations:
8  *
9  * http://www.opensource.org/licenses/gpl-license.html
10  * http://www.gnu.org/copyleft/gpl.html
11  */
12
13 #include <linux/clk.h>
14 #include <linux/clk-provider.h>
15 #include <linux/delay.h>
16 #include <linux/imx_sema4.h>
17 #include <linux/io.h>
18 #include <linux/slab.h>
19 #include <linux/jiffies.h>
20 #include <linux/err.h>
21 #include "clk.h"
22 #include "common.h"
23
24 #define PLL_NUM_OFFSET          0x10
25 #define PLL_DENOM_OFFSET        0x20
26
27 #define BM_PLL_POWER            (0x1 << 12)
28 #define BM_PLL_LOCK             (0x1 << 31)
29
30 /**
31  * struct clk_pllv3 - IMX PLL clock version 3
32  * @clk_hw:      clock source
33  * @base:        base address of PLL registers
34  * @powerup_set: set POWER bit to power up the PLL
35  * @div_mask:    mask of divider bits
36  *
37  * IMX PLL clock version 3, found on i.MX6 series.  Divider for pllv3
38  * is actually a multiplier, and always sits at bit 0.
39  */
40 struct clk_pllv3 {
41         struct clk_hw   hw;
42         void __iomem    *base;
43         bool            powerup_set;
44         u32             div_mask;
45 };
46
47 #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw)
48
49 static int clk_pllv3_wait_lock(struct clk_pllv3 *pll)
50 {
51         unsigned long timeout = jiffies + msecs_to_jiffies(10);
52         u32 val = readl_relaxed(pll->base) & BM_PLL_POWER;
53
54         /* No need to wait for lock when pll is not powered up */
55         if ((pll->powerup_set && !val) || (!pll->powerup_set && val))
56                 return 0;
57
58         /* Wait for PLL to lock */
59         do {
60                 if (readl_relaxed(pll->base) & BM_PLL_LOCK)
61                         break;
62                 if (time_after(jiffies, timeout))
63                         break;
64         } while (1);
65
66         return readl_relaxed(pll->base) & BM_PLL_LOCK ? 0 : -ETIMEDOUT;
67 }
68
69 static int clk_pllv3_do_hardware(struct clk_hw *hw, bool enable)
70 {
71         struct clk_pllv3 *pll = to_clk_pllv3(hw);
72         u32 val;
73         int ret;
74
75         val = readl_relaxed(pll->base);
76         if (enable) {
77                 if (pll->powerup_set)
78                         val |= BM_PLL_POWER;
79                 else
80                         val &= ~BM_PLL_POWER;
81                 writel_relaxed(val, pll->base);
82
83                 ret = clk_pllv3_wait_lock(pll);
84                 if (ret)
85                         return ret;
86         } else {
87                 if (pll->powerup_set)
88                         val &= ~BM_PLL_POWER;
89                 else
90                         val |= BM_PLL_POWER;
91                 writel_relaxed(val, pll->base);
92         }
93
94         return 0;
95 }
96
97 static void clk_pllv3_do_shared_clks(struct clk_hw *hw, bool enable)
98 {
99         if (imx_src_is_m4_enabled()) {
100                 if (!amp_power_mutex || !shared_mem) {
101                         if (enable)
102                                 clk_pllv3_do_hardware(hw, enable);
103                         return;
104                 }
105
106                 imx_sema4_mutex_lock(amp_power_mutex);
107                 if (shared_mem->ca9_valid != SHARED_MEM_MAGIC_NUMBER ||
108                         shared_mem->cm4_valid != SHARED_MEM_MAGIC_NUMBER) {
109                         imx_sema4_mutex_unlock(amp_power_mutex);
110                         return;
111                 }
112
113                 if (!imx_update_shared_mem(hw, enable)) {
114                         imx_sema4_mutex_unlock(amp_power_mutex);
115                         return;
116                 }
117                 clk_pllv3_do_hardware(hw, enable);
118
119                 imx_sema4_mutex_unlock(amp_power_mutex);
120         } else {
121                 clk_pllv3_do_hardware(hw, enable);
122         }
123 }
124
125 static int clk_pllv3_prepare(struct clk_hw *hw)
126 {
127         clk_pllv3_do_shared_clks(hw, true);
128
129         return 0;
130 }
131
132 static void clk_pllv3_unprepare(struct clk_hw *hw)
133 {
134         clk_pllv3_do_shared_clks(hw, false);
135 }
136
137 static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw,
138                                            unsigned long parent_rate)
139 {
140         struct clk_pllv3 *pll = to_clk_pllv3(hw);
141         u32 div = readl_relaxed(pll->base)  & pll->div_mask;
142
143         return (div == 1) ? parent_rate * 22 : parent_rate * 20;
144 }
145
146 static long clk_pllv3_round_rate(struct clk_hw *hw, unsigned long rate,
147                                  unsigned long *prate)
148 {
149         unsigned long parent_rate = *prate;
150
151         return (rate >= parent_rate * 22) ? parent_rate * 22 :
152                                             parent_rate * 20;
153 }
154
155 static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate,
156                 unsigned long parent_rate)
157 {
158         struct clk_pllv3 *pll = to_clk_pllv3(hw);
159         u32 val, div;
160
161         if (rate == parent_rate * 22)
162                 div = 1;
163         else if (rate == parent_rate * 20)
164                 div = 0;
165         else
166                 return -EINVAL;
167
168         val = readl_relaxed(pll->base);
169         val &= ~pll->div_mask;
170         val |= div;
171         writel_relaxed(val, pll->base);
172
173         return clk_pllv3_wait_lock(pll);
174 }
175
176 static const struct clk_ops clk_pllv3_ops = {
177         .prepare        = clk_pllv3_prepare,
178         .unprepare      = clk_pllv3_unprepare,
179         .recalc_rate    = clk_pllv3_recalc_rate,
180         .round_rate     = clk_pllv3_round_rate,
181         .set_rate       = clk_pllv3_set_rate,
182 };
183
184 static unsigned long clk_pllv3_sys_recalc_rate(struct clk_hw *hw,
185                                                unsigned long parent_rate)
186 {
187         struct clk_pllv3 *pll = to_clk_pllv3(hw);
188         u32 div = readl_relaxed(pll->base) & pll->div_mask;
189
190         return parent_rate * div / 2;
191 }
192
193 static long clk_pllv3_sys_round_rate(struct clk_hw *hw, unsigned long rate,
194                                      unsigned long *prate)
195 {
196         unsigned long parent_rate = *prate;
197         unsigned long min_rate = parent_rate * 54 / 2;
198         unsigned long max_rate = parent_rate * 108 / 2;
199         u32 div;
200
201         if (rate > max_rate)
202                 rate = max_rate;
203         else if (rate < min_rate)
204                 rate = min_rate;
205         div = rate * 2 / parent_rate;
206
207         return parent_rate * div / 2;
208 }
209
210 static int clk_pllv3_sys_set_rate(struct clk_hw *hw, unsigned long rate,
211                 unsigned long parent_rate)
212 {
213         struct clk_pllv3 *pll = to_clk_pllv3(hw);
214         unsigned long min_rate = parent_rate * 54 / 2;
215         unsigned long max_rate = parent_rate * 108 / 2;
216         u32 val, div;
217
218         if (rate < min_rate || rate > max_rate)
219                 return -EINVAL;
220
221         div = rate * 2 / parent_rate;
222         val = readl_relaxed(pll->base);
223         val &= ~pll->div_mask;
224         val |= div;
225         writel_relaxed(val, pll->base);
226
227         return clk_pllv3_wait_lock(pll);
228 }
229
230 static const struct clk_ops clk_pllv3_sys_ops = {
231         .prepare        = clk_pllv3_prepare,
232         .unprepare      = clk_pllv3_unprepare,
233         .recalc_rate    = clk_pllv3_sys_recalc_rate,
234         .round_rate     = clk_pllv3_sys_round_rate,
235         .set_rate       = clk_pllv3_sys_set_rate,
236 };
237
238 static unsigned long clk_pllv3_av_recalc_rate(struct clk_hw *hw,
239                                               unsigned long parent_rate)
240 {
241         struct clk_pllv3 *pll = to_clk_pllv3(hw);
242         u32 mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET);
243         u32 mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET);
244         u32 div = readl_relaxed(pll->base) & pll->div_mask;
245
246         return (parent_rate * div) + ((parent_rate / mfd) * mfn);
247 }
248
249 static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate,
250                                     unsigned long *prate)
251 {
252         unsigned long parent_rate = *prate;
253         unsigned long min_rate = parent_rate * 27;
254         unsigned long max_rate = parent_rate * 54;
255         u32 div;
256         u32 mfn, mfd = 1000000;
257         s64 temp64;
258
259         if (rate > max_rate)
260                 rate = max_rate;
261         else if (rate < min_rate)
262                 rate = min_rate;
263
264         div = rate / parent_rate;
265         temp64 = (u64) (rate - div * parent_rate);
266         temp64 *= mfd;
267         do_div(temp64, parent_rate);
268         mfn = temp64;
269
270         return parent_rate * div + parent_rate / mfd * mfn;
271 }
272
273 static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
274                 unsigned long parent_rate)
275 {
276         struct clk_pllv3 *pll = to_clk_pllv3(hw);
277         unsigned long min_rate = parent_rate * 27;
278         unsigned long max_rate = parent_rate * 54;
279         u32 val, div;
280         u32 mfn, mfd = 1000000;
281         s64 temp64;
282
283         if (rate < min_rate || rate > max_rate)
284                 return -EINVAL;
285
286         div = rate / parent_rate;
287         temp64 = (u64) (rate - div * parent_rate);
288         temp64 *= mfd;
289         do_div(temp64, parent_rate);
290         mfn = temp64;
291
292         val = readl_relaxed(pll->base);
293         val &= ~pll->div_mask;
294         val |= div;
295         writel_relaxed(val, pll->base);
296         writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET);
297         writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET);
298
299         return clk_pllv3_wait_lock(pll);
300 }
301
302 static const struct clk_ops clk_pllv3_av_ops = {
303         .prepare        = clk_pllv3_prepare,
304         .unprepare      = clk_pllv3_unprepare,
305         .recalc_rate    = clk_pllv3_av_recalc_rate,
306         .round_rate     = clk_pllv3_av_round_rate,
307         .set_rate       = clk_pllv3_av_set_rate,
308 };
309
310 static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw,
311                                                 unsigned long parent_rate)
312 {
313         return 500000000;
314 }
315
316 static const struct clk_ops clk_pllv3_enet_ops = {
317         .prepare        = clk_pllv3_prepare,
318         .unprepare      = clk_pllv3_unprepare,
319         .recalc_rate    = clk_pllv3_enet_recalc_rate,
320 };
321
322 struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
323                           const char *parent_name, void __iomem *base,
324                           u32 div_mask)
325 {
326         struct clk_pllv3 *pll;
327         const struct clk_ops *ops;
328         struct clk *clk;
329         struct clk_init_data init;
330
331         pll = kzalloc(sizeof(*pll), GFP_KERNEL);
332         if (!pll)
333                 return ERR_PTR(-ENOMEM);
334
335         switch (type) {
336         case IMX_PLLV3_SYS:
337                 ops = &clk_pllv3_sys_ops;
338                 break;
339         case IMX_PLLV3_USB:
340                 ops = &clk_pllv3_ops;
341                 pll->powerup_set = true;
342                 break;
343         case IMX_PLLV3_AV:
344                 ops = &clk_pllv3_av_ops;
345                 break;
346         case IMX_PLLV3_ENET:
347                 ops = &clk_pllv3_enet_ops;
348                 break;
349         default:
350                 ops = &clk_pllv3_ops;
351         }
352         pll->base = base;
353         pll->div_mask = div_mask;
354
355         init.name = name;
356         init.ops = ops;
357         init.flags = CLK_SET_RATE_GATE | CLK_GET_RATE_NOCACHE;
358         init.parent_names = &parent_name;
359         init.num_parents = 1;
360
361         pll->hw.init = &init;
362
363         clk = clk_register(NULL, &pll->hw);
364         if (IS_ERR(clk))
365                 kfree(pll);
366
367         return clk;
368 }