Commit | Line | Data |
---|---|---|
e874a669 EL |
1 | /* |
2 | * Copyright 2013 Emilio López | |
3 | * | |
4 | * Emilio López <emilio@elopez.com.ar> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | */ | |
16 | ||
9dfefe8c | 17 | #include <linux/clk.h> |
e874a669 EL |
18 | #include <linux/clk-provider.h> |
19 | #include <linux/clkdev.h> | |
e874a669 EL |
20 | #include <linux/of.h> |
21 | #include <linux/of_address.h> | |
cfb0086d | 22 | #include <linux/reset-controller.h> |
9dfefe8c | 23 | #include <linux/slab.h> |
601da9d0 | 24 | #include <linux/spinlock.h> |
7954dfae | 25 | #include <linux/log2.h> |
e874a669 EL |
26 | |
27 | #include "clk-factors.h" | |
28 | ||
29 | static DEFINE_SPINLOCK(clk_lock); | |
30 | ||
7954dfae CYT |
31 | /** |
32 | * sun6i_a31_ahb1_clk_setup() - Setup function for a31 ahb1 composite clk | |
33 | */ | |
34 | ||
35 | #define SUN6I_AHB1_MAX_PARENTS 4 | |
36 | #define SUN6I_AHB1_MUX_PARENT_PLL6 3 | |
37 | #define SUN6I_AHB1_MUX_SHIFT 12 | |
38 | /* un-shifted mask is what mux_clk expects */ | |
39 | #define SUN6I_AHB1_MUX_MASK 0x3 | |
40 | #define SUN6I_AHB1_MUX_GET_PARENT(reg) ((reg >> SUN6I_AHB1_MUX_SHIFT) & \ | |
41 | SUN6I_AHB1_MUX_MASK) | |
42 | ||
43 | #define SUN6I_AHB1_DIV_SHIFT 4 | |
44 | #define SUN6I_AHB1_DIV_MASK (0x3 << SUN6I_AHB1_DIV_SHIFT) | |
45 | #define SUN6I_AHB1_DIV_GET(reg) ((reg & SUN6I_AHB1_DIV_MASK) >> \ | |
46 | SUN6I_AHB1_DIV_SHIFT) | |
47 | #define SUN6I_AHB1_DIV_SET(reg, div) ((reg & ~SUN6I_AHB1_DIV_MASK) | \ | |
48 | (div << SUN6I_AHB1_DIV_SHIFT)) | |
49 | #define SUN6I_AHB1_PLL6_DIV_SHIFT 6 | |
50 | #define SUN6I_AHB1_PLL6_DIV_MASK (0x3 << SUN6I_AHB1_PLL6_DIV_SHIFT) | |
51 | #define SUN6I_AHB1_PLL6_DIV_GET(reg) ((reg & SUN6I_AHB1_PLL6_DIV_MASK) >> \ | |
52 | SUN6I_AHB1_PLL6_DIV_SHIFT) | |
53 | #define SUN6I_AHB1_PLL6_DIV_SET(reg, div) ((reg & ~SUN6I_AHB1_PLL6_DIV_MASK) | \ | |
54 | (div << SUN6I_AHB1_PLL6_DIV_SHIFT)) | |
55 | ||
56 | struct sun6i_ahb1_clk { | |
57 | struct clk_hw hw; | |
58 | void __iomem *reg; | |
59 | }; | |
60 | ||
61 | #define to_sun6i_ahb1_clk(_hw) container_of(_hw, struct sun6i_ahb1_clk, hw) | |
62 | ||
63 | static unsigned long sun6i_ahb1_clk_recalc_rate(struct clk_hw *hw, | |
64 | unsigned long parent_rate) | |
65 | { | |
66 | struct sun6i_ahb1_clk *ahb1 = to_sun6i_ahb1_clk(hw); | |
67 | unsigned long rate; | |
68 | u32 reg; | |
69 | ||
70 | /* Fetch the register value */ | |
71 | reg = readl(ahb1->reg); | |
72 | ||
73 | /* apply pre-divider first if parent is pll6 */ | |
74 | if (SUN6I_AHB1_MUX_GET_PARENT(reg) == SUN6I_AHB1_MUX_PARENT_PLL6) | |
75 | parent_rate /= SUN6I_AHB1_PLL6_DIV_GET(reg) + 1; | |
76 | ||
77 | /* clk divider */ | |
78 | rate = parent_rate >> SUN6I_AHB1_DIV_GET(reg); | |
79 | ||
80 | return rate; | |
81 | } | |
82 | ||
83 | static long sun6i_ahb1_clk_round(unsigned long rate, u8 *divp, u8 *pre_divp, | |
84 | u8 parent, unsigned long parent_rate) | |
85 | { | |
86 | u8 div, calcp, calcm = 1; | |
87 | ||
88 | /* | |
89 | * clock can only divide, so we will never be able to achieve | |
90 | * frequencies higher than the parent frequency | |
91 | */ | |
92 | if (parent_rate && rate > parent_rate) | |
93 | rate = parent_rate; | |
94 | ||
95 | div = DIV_ROUND_UP(parent_rate, rate); | |
96 | ||
97 | /* calculate pre-divider if parent is pll6 */ | |
98 | if (parent == SUN6I_AHB1_MUX_PARENT_PLL6) { | |
99 | if (div < 4) | |
100 | calcp = 0; | |
101 | else if (div / 2 < 4) | |
102 | calcp = 1; | |
103 | else if (div / 4 < 4) | |
104 | calcp = 2; | |
105 | else | |
106 | calcp = 3; | |
107 | ||
108 | calcm = DIV_ROUND_UP(div, 1 << calcp); | |
109 | } else { | |
110 | calcp = __roundup_pow_of_two(div); | |
111 | calcp = calcp > 3 ? 3 : calcp; | |
112 | } | |
113 | ||
114 | /* we were asked to pass back divider values */ | |
115 | if (divp) { | |
116 | *divp = calcp; | |
117 | *pre_divp = calcm - 1; | |
118 | } | |
119 | ||
120 | return (parent_rate / calcm) >> calcp; | |
121 | } | |
122 | ||
0817b62c BB |
123 | static int sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, |
124 | struct clk_rate_request *req) | |
7954dfae | 125 | { |
1b14afa6 | 126 | struct clk_hw *parent, *best_parent = NULL; |
7954dfae CYT |
127 | int i, num_parents; |
128 | unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0; | |
129 | ||
130 | /* find the parent that can help provide the fastest rate <= rate */ | |
497295af | 131 | num_parents = clk_hw_get_num_parents(hw); |
7954dfae | 132 | for (i = 0; i < num_parents; i++) { |
1b14afa6 | 133 | parent = clk_hw_get_parent_by_index(hw, i); |
7954dfae CYT |
134 | if (!parent) |
135 | continue; | |
98d8a60e | 136 | if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) |
1b14afa6 | 137 | parent_rate = clk_hw_round_rate(parent, req->rate); |
7954dfae | 138 | else |
1b14afa6 | 139 | parent_rate = clk_hw_get_rate(parent); |
7954dfae | 140 | |
0817b62c | 141 | child_rate = sun6i_ahb1_clk_round(req->rate, NULL, NULL, i, |
7954dfae CYT |
142 | parent_rate); |
143 | ||
0817b62c | 144 | if (child_rate <= req->rate && child_rate > best_child_rate) { |
7954dfae CYT |
145 | best_parent = parent; |
146 | best = parent_rate; | |
147 | best_child_rate = child_rate; | |
148 | } | |
149 | } | |
150 | ||
57d866e6 BB |
151 | if (!best_parent) |
152 | return -EINVAL; | |
7954dfae | 153 | |
1b14afa6 | 154 | req->best_parent_hw = best_parent; |
0817b62c BB |
155 | req->best_parent_rate = best; |
156 | req->rate = best_child_rate; | |
7954dfae | 157 | |
0817b62c | 158 | return 0; |
7954dfae CYT |
159 | } |
160 | ||
161 | static int sun6i_ahb1_clk_set_rate(struct clk_hw *hw, unsigned long rate, | |
162 | unsigned long parent_rate) | |
163 | { | |
164 | struct sun6i_ahb1_clk *ahb1 = to_sun6i_ahb1_clk(hw); | |
165 | unsigned long flags; | |
166 | u8 div, pre_div, parent; | |
167 | u32 reg; | |
168 | ||
169 | spin_lock_irqsave(&clk_lock, flags); | |
170 | ||
171 | reg = readl(ahb1->reg); | |
172 | ||
173 | /* need to know which parent is used to apply pre-divider */ | |
174 | parent = SUN6I_AHB1_MUX_GET_PARENT(reg); | |
175 | sun6i_ahb1_clk_round(rate, &div, &pre_div, parent, parent_rate); | |
176 | ||
177 | reg = SUN6I_AHB1_DIV_SET(reg, div); | |
178 | reg = SUN6I_AHB1_PLL6_DIV_SET(reg, pre_div); | |
179 | writel(reg, ahb1->reg); | |
180 | ||
181 | spin_unlock_irqrestore(&clk_lock, flags); | |
182 | ||
183 | return 0; | |
184 | } | |
185 | ||
186 | static const struct clk_ops sun6i_ahb1_clk_ops = { | |
187 | .determine_rate = sun6i_ahb1_clk_determine_rate, | |
188 | .recalc_rate = sun6i_ahb1_clk_recalc_rate, | |
189 | .set_rate = sun6i_ahb1_clk_set_rate, | |
190 | }; | |
191 | ||
192 | static void __init sun6i_ahb1_clk_setup(struct device_node *node) | |
193 | { | |
194 | struct clk *clk; | |
195 | struct sun6i_ahb1_clk *ahb1; | |
196 | struct clk_mux *mux; | |
197 | const char *clk_name = node->name; | |
198 | const char *parents[SUN6I_AHB1_MAX_PARENTS]; | |
199 | void __iomem *reg; | |
8a53fb2b | 200 | int i; |
7954dfae CYT |
201 | |
202 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | |
5ac382c3 MR |
203 | if (IS_ERR(reg)) |
204 | return; | |
7954dfae CYT |
205 | |
206 | /* we have a mux, we will have >1 parents */ | |
8a53fb2b | 207 | i = of_clk_parent_fill(node, parents, SUN6I_AHB1_MAX_PARENTS); |
7954dfae CYT |
208 | of_property_read_string(node, "clock-output-names", &clk_name); |
209 | ||
210 | ahb1 = kzalloc(sizeof(struct sun6i_ahb1_clk), GFP_KERNEL); | |
211 | if (!ahb1) | |
212 | return; | |
213 | ||
214 | mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); | |
215 | if (!mux) { | |
216 | kfree(ahb1); | |
217 | return; | |
218 | } | |
219 | ||
220 | /* set up clock properties */ | |
221 | mux->reg = reg; | |
222 | mux->shift = SUN6I_AHB1_MUX_SHIFT; | |
223 | mux->mask = SUN6I_AHB1_MUX_MASK; | |
224 | mux->lock = &clk_lock; | |
225 | ahb1->reg = reg; | |
226 | ||
227 | clk = clk_register_composite(NULL, clk_name, parents, i, | |
228 | &mux->hw, &clk_mux_ops, | |
229 | &ahb1->hw, &sun6i_ahb1_clk_ops, | |
230 | NULL, NULL, 0); | |
231 | ||
232 | if (!IS_ERR(clk)) { | |
233 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | |
234 | clk_register_clkdev(clk, clk_name, NULL); | |
235 | } | |
236 | } | |
237 | CLK_OF_DECLARE(sun6i_a31_ahb1, "allwinner,sun6i-a31-ahb1-clk", sun6i_ahb1_clk_setup); | |
238 | ||
40a5dcba EL |
239 | /* Maximum number of parents our clocks have */ |
240 | #define SUNXI_MAX_PARENTS 5 | |
241 | ||
e874a669 | 242 | /** |
81ba6c5e | 243 | * sun4i_get_pll1_factors() - calculates n, k, m, p factors for PLL1 |
e874a669 EL |
244 | * PLL1 rate is calculated as follows |
245 | * rate = (parent_rate * n * (k + 1) >> p) / (m + 1); | |
246 | * parent_rate is always 24Mhz | |
247 | */ | |
248 | ||
81ba6c5e | 249 | static void sun4i_get_pll1_factors(u32 *freq, u32 parent_rate, |
e874a669 EL |
250 | u8 *n, u8 *k, u8 *m, u8 *p) |
251 | { | |
252 | u8 div; | |
253 | ||
254 | /* Normalize value to a 6M multiple */ | |
255 | div = *freq / 6000000; | |
256 | *freq = 6000000 * div; | |
257 | ||
258 | /* we were called to round the frequency, we can now return */ | |
259 | if (n == NULL) | |
260 | return; | |
261 | ||
262 | /* m is always zero for pll1 */ | |
263 | *m = 0; | |
264 | ||
265 | /* k is 1 only on these cases */ | |
266 | if (*freq >= 768000000 || *freq == 42000000 || *freq == 54000000) | |
267 | *k = 1; | |
268 | else | |
269 | *k = 0; | |
270 | ||
271 | /* p will be 3 for divs under 10 */ | |
272 | if (div < 10) | |
273 | *p = 3; | |
274 | ||
275 | /* p will be 2 for divs between 10 - 20 and odd divs under 32 */ | |
276 | else if (div < 20 || (div < 32 && (div & 1))) | |
277 | *p = 2; | |
278 | ||
279 | /* p will be 1 for even divs under 32, divs under 40 and odd pairs | |
280 | * of divs between 40-62 */ | |
281 | else if (div < 40 || (div < 64 && (div & 2))) | |
282 | *p = 1; | |
283 | ||
284 | /* any other entries have p = 0 */ | |
285 | else | |
286 | *p = 0; | |
287 | ||
288 | /* calculate a suitable n based on k and p */ | |
289 | div <<= *p; | |
290 | div /= (*k + 1); | |
291 | *n = div / 4; | |
292 | } | |
293 | ||
6a721db1 MR |
294 | /** |
295 | * sun6i_a31_get_pll1_factors() - calculates n, k and m factors for PLL1 | |
296 | * PLL1 rate is calculated as follows | |
297 | * rate = parent_rate * (n + 1) * (k + 1) / (m + 1); | |
298 | * parent_rate should always be 24MHz | |
299 | */ | |
300 | static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate, | |
301 | u8 *n, u8 *k, u8 *m, u8 *p) | |
302 | { | |
303 | /* | |
304 | * We can operate only on MHz, this will make our life easier | |
305 | * later. | |
306 | */ | |
307 | u32 freq_mhz = *freq / 1000000; | |
308 | u32 parent_freq_mhz = parent_rate / 1000000; | |
309 | ||
310 | /* | |
311 | * Round down the frequency to the closest multiple of either | |
312 | * 6 or 16 | |
313 | */ | |
314 | u32 round_freq_6 = round_down(freq_mhz, 6); | |
315 | u32 round_freq_16 = round_down(freq_mhz, 16); | |
316 | ||
317 | if (round_freq_6 > round_freq_16) | |
318 | freq_mhz = round_freq_6; | |
319 | else | |
320 | freq_mhz = round_freq_16; | |
e874a669 | 321 | |
6a721db1 MR |
322 | *freq = freq_mhz * 1000000; |
323 | ||
324 | /* | |
325 | * If the factors pointer are null, we were just called to | |
326 | * round down the frequency. | |
327 | * Exit. | |
328 | */ | |
329 | if (n == NULL) | |
330 | return; | |
331 | ||
332 | /* If the frequency is a multiple of 32 MHz, k is always 3 */ | |
333 | if (!(freq_mhz % 32)) | |
334 | *k = 3; | |
335 | /* If the frequency is a multiple of 9 MHz, k is always 2 */ | |
336 | else if (!(freq_mhz % 9)) | |
337 | *k = 2; | |
338 | /* If the frequency is a multiple of 8 MHz, k is always 1 */ | |
339 | else if (!(freq_mhz % 8)) | |
340 | *k = 1; | |
341 | /* Otherwise, we don't use the k factor */ | |
342 | else | |
343 | *k = 0; | |
344 | ||
345 | /* | |
346 | * If the frequency is a multiple of 2 but not a multiple of | |
347 | * 3, m is 3. This is the first time we use 6 here, yet we | |
348 | * will use it on several other places. | |
349 | * We use this number because it's the lowest frequency we can | |
350 | * generate (with n = 0, k = 0, m = 3), so every other frequency | |
351 | * somehow relates to this frequency. | |
352 | */ | |
353 | if ((freq_mhz % 6) == 2 || (freq_mhz % 6) == 4) | |
354 | *m = 2; | |
355 | /* | |
356 | * If the frequency is a multiple of 6MHz, but the factor is | |
357 | * odd, m will be 3 | |
358 | */ | |
359 | else if ((freq_mhz / 6) & 1) | |
360 | *m = 3; | |
361 | /* Otherwise, we end up with m = 1 */ | |
362 | else | |
363 | *m = 1; | |
364 | ||
365 | /* Calculate n thanks to the above factors we already got */ | |
366 | *n = freq_mhz * (*m + 1) / ((*k + 1) * parent_freq_mhz) - 1; | |
367 | ||
368 | /* | |
369 | * If n end up being outbound, and that we can still decrease | |
370 | * m, do it. | |
371 | */ | |
372 | if ((*n + 1) > 31 && (*m + 1) > 1) { | |
373 | *n = (*n + 1) / 2 - 1; | |
374 | *m = (*m + 1) / 2 - 1; | |
375 | } | |
376 | } | |
e874a669 | 377 | |
515c1a4b CYT |
378 | /** |
379 | * sun8i_a23_get_pll1_factors() - calculates n, k, m, p factors for PLL1 | |
380 | * PLL1 rate is calculated as follows | |
381 | * rate = (parent_rate * (n + 1) * (k + 1) >> p) / (m + 1); | |
382 | * parent_rate is always 24Mhz | |
383 | */ | |
384 | ||
385 | static void sun8i_a23_get_pll1_factors(u32 *freq, u32 parent_rate, | |
386 | u8 *n, u8 *k, u8 *m, u8 *p) | |
387 | { | |
388 | u8 div; | |
389 | ||
390 | /* Normalize value to a 6M multiple */ | |
391 | div = *freq / 6000000; | |
392 | *freq = 6000000 * div; | |
393 | ||
394 | /* we were called to round the frequency, we can now return */ | |
395 | if (n == NULL) | |
396 | return; | |
397 | ||
398 | /* m is always zero for pll1 */ | |
399 | *m = 0; | |
400 | ||
401 | /* k is 1 only on these cases */ | |
402 | if (*freq >= 768000000 || *freq == 42000000 || *freq == 54000000) | |
403 | *k = 1; | |
404 | else | |
405 | *k = 0; | |
406 | ||
407 | /* p will be 2 for divs under 20 and odd divs under 32 */ | |
408 | if (div < 20 || (div < 32 && (div & 1))) | |
409 | *p = 2; | |
410 | ||
411 | /* p will be 1 for even divs under 32, divs under 40 and odd pairs | |
412 | * of divs between 40-62 */ | |
413 | else if (div < 40 || (div < 64 && (div & 2))) | |
414 | *p = 1; | |
415 | ||
416 | /* any other entries have p = 0 */ | |
417 | else | |
418 | *p = 0; | |
419 | ||
420 | /* calculate a suitable n based on k and p */ | |
421 | div <<= *p; | |
422 | div /= (*k + 1); | |
423 | *n = div / 4 - 1; | |
424 | } | |
425 | ||
d584c133 EL |
426 | /** |
427 | * sun4i_get_pll5_factors() - calculates n, k factors for PLL5 | |
428 | * PLL5 rate is calculated as follows | |
429 | * rate = parent_rate * n * (k + 1) | |
430 | * parent_rate is always 24Mhz | |
431 | */ | |
432 | ||
433 | static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate, | |
434 | u8 *n, u8 *k, u8 *m, u8 *p) | |
435 | { | |
436 | u8 div; | |
437 | ||
438 | /* Normalize value to a parent_rate multiple (24M) */ | |
439 | div = *freq / parent_rate; | |
440 | *freq = parent_rate * div; | |
441 | ||
442 | /* we were called to round the frequency, we can now return */ | |
443 | if (n == NULL) | |
444 | return; | |
445 | ||
446 | if (div < 31) | |
447 | *k = 0; | |
448 | else if (div / 2 < 31) | |
449 | *k = 1; | |
450 | else if (div / 3 < 31) | |
451 | *k = 2; | |
452 | else | |
453 | *k = 3; | |
454 | ||
455 | *n = DIV_ROUND_UP(div, (*k+1)); | |
456 | } | |
457 | ||
92ef67c5 | 458 | /** |
95e94c1f CYT |
459 | * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6x2 |
460 | * PLL6x2 rate is calculated as follows | |
461 | * rate = parent_rate * (n + 1) * (k + 1) | |
92ef67c5 MR |
462 | * parent_rate is always 24Mhz |
463 | */ | |
464 | ||
465 | static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate, | |
466 | u8 *n, u8 *k, u8 *m, u8 *p) | |
467 | { | |
468 | u8 div; | |
469 | ||
95e94c1f | 470 | /* Normalize value to a parent_rate multiple (24M) */ |
92ef67c5 MR |
471 | div = *freq / parent_rate; |
472 | *freq = parent_rate * div; | |
473 | ||
474 | /* we were called to round the frequency, we can now return */ | |
475 | if (n == NULL) | |
476 | return; | |
477 | ||
478 | *k = div / 32; | |
479 | if (*k > 3) | |
480 | *k = 3; | |
d584c133 | 481 | |
95e94c1f | 482 | *n = DIV_ROUND_UP(div, (*k+1)) - 1; |
92ef67c5 | 483 | } |
d584c133 | 484 | |
9f243097 CYT |
485 | /** |
486 | * sun5i_a13_get_ahb_factors() - calculates m, p factors for AHB | |
487 | * AHB rate is calculated as follows | |
488 | * rate = parent_rate >> p | |
489 | */ | |
490 | ||
491 | static void sun5i_a13_get_ahb_factors(u32 *freq, u32 parent_rate, | |
492 | u8 *n, u8 *k, u8 *m, u8 *p) | |
493 | { | |
494 | u32 div; | |
495 | ||
496 | /* divide only */ | |
497 | if (parent_rate < *freq) | |
498 | *freq = parent_rate; | |
499 | ||
500 | /* | |
501 | * user manual says valid speed is 8k ~ 276M, but tests show it | |
502 | * can work at speeds up to 300M, just after reparenting to pll6 | |
503 | */ | |
504 | if (*freq < 8000) | |
505 | *freq = 8000; | |
506 | if (*freq > 300000000) | |
507 | *freq = 300000000; | |
508 | ||
509 | div = order_base_2(DIV_ROUND_UP(parent_rate, *freq)); | |
510 | ||
511 | /* p = 0 ~ 3 */ | |
512 | if (div > 3) | |
513 | div = 3; | |
514 | ||
515 | *freq = parent_rate >> div; | |
516 | ||
517 | /* we were called to round the frequency, we can now return */ | |
518 | if (p == NULL) | |
519 | return; | |
520 | ||
521 | *p = div; | |
522 | } | |
523 | ||
e874a669 | 524 | /** |
81ba6c5e | 525 | * sun4i_get_apb1_factors() - calculates m, p factors for APB1 |
e874a669 EL |
526 | * APB1 rate is calculated as follows |
527 | * rate = (parent_rate >> p) / (m + 1); | |
528 | */ | |
529 | ||
81ba6c5e | 530 | static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate, |
e874a669 EL |
531 | u8 *n, u8 *k, u8 *m, u8 *p) |
532 | { | |
533 | u8 calcm, calcp; | |
534 | ||
535 | if (parent_rate < *freq) | |
536 | *freq = parent_rate; | |
537 | ||
22260139 | 538 | parent_rate = DIV_ROUND_UP(parent_rate, *freq); |
e874a669 EL |
539 | |
540 | /* Invalid rate! */ | |
541 | if (parent_rate > 32) | |
542 | return; | |
543 | ||
544 | if (parent_rate <= 4) | |
545 | calcp = 0; | |
546 | else if (parent_rate <= 8) | |
547 | calcp = 1; | |
548 | else if (parent_rate <= 16) | |
549 | calcp = 2; | |
550 | else | |
551 | calcp = 3; | |
552 | ||
553 | calcm = (parent_rate >> calcp) - 1; | |
554 | ||
555 | *freq = (parent_rate >> calcp) / (calcm + 1); | |
556 | ||
557 | /* we were called to round the frequency, we can now return */ | |
558 | if (n == NULL) | |
559 | return; | |
560 | ||
561 | *m = calcm; | |
562 | *p = calcp; | |
563 | } | |
564 | ||
565 | ||
566 | ||
7551769a | 567 | |
6f863417 CYT |
568 | /** |
569 | * sun7i_a20_get_out_factors() - calculates m, p factors for CLK_OUT_A/B | |
570 | * CLK_OUT rate is calculated as follows | |
571 | * rate = (parent_rate >> p) / (m + 1); | |
572 | */ | |
573 | ||
574 | static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate, | |
575 | u8 *n, u8 *k, u8 *m, u8 *p) | |
576 | { | |
577 | u8 div, calcm, calcp; | |
578 | ||
579 | /* These clocks can only divide, so we will never be able to achieve | |
580 | * frequencies higher than the parent frequency */ | |
581 | if (*freq > parent_rate) | |
582 | *freq = parent_rate; | |
583 | ||
22260139 | 584 | div = DIV_ROUND_UP(parent_rate, *freq); |
6f863417 CYT |
585 | |
586 | if (div < 32) | |
587 | calcp = 0; | |
588 | else if (div / 2 < 32) | |
589 | calcp = 1; | |
590 | else if (div / 4 < 32) | |
591 | calcp = 2; | |
592 | else | |
593 | calcp = 3; | |
594 | ||
595 | calcm = DIV_ROUND_UP(div, 1 << calcp); | |
596 | ||
597 | *freq = (parent_rate >> calcp) / calcm; | |
598 | ||
599 | /* we were called to round the frequency, we can now return */ | |
600 | if (n == NULL) | |
601 | return; | |
602 | ||
603 | *m = calcm - 1; | |
604 | *p = calcp; | |
605 | } | |
606 | ||
e874a669 EL |
607 | /** |
608 | * sunxi_factors_clk_setup() - Setup function for factor clocks | |
609 | */ | |
610 | ||
81ba6c5e | 611 | static struct clk_factors_config sun4i_pll1_config = { |
e874a669 EL |
612 | .nshift = 8, |
613 | .nwidth = 5, | |
614 | .kshift = 4, | |
615 | .kwidth = 2, | |
616 | .mshift = 0, | |
617 | .mwidth = 2, | |
618 | .pshift = 16, | |
619 | .pwidth = 2, | |
620 | }; | |
621 | ||
6a721db1 MR |
622 | static struct clk_factors_config sun6i_a31_pll1_config = { |
623 | .nshift = 8, | |
624 | .nwidth = 5, | |
625 | .kshift = 4, | |
626 | .kwidth = 2, | |
627 | .mshift = 0, | |
628 | .mwidth = 2, | |
76820fcf | 629 | .n_start = 1, |
6a721db1 MR |
630 | }; |
631 | ||
515c1a4b CYT |
632 | static struct clk_factors_config sun8i_a23_pll1_config = { |
633 | .nshift = 8, | |
634 | .nwidth = 5, | |
635 | .kshift = 4, | |
636 | .kwidth = 2, | |
637 | .mshift = 0, | |
638 | .mwidth = 2, | |
639 | .pshift = 16, | |
640 | .pwidth = 2, | |
641 | .n_start = 1, | |
642 | }; | |
643 | ||
d584c133 EL |
644 | static struct clk_factors_config sun4i_pll5_config = { |
645 | .nshift = 8, | |
646 | .nwidth = 5, | |
647 | .kshift = 4, | |
648 | .kwidth = 2, | |
649 | }; | |
650 | ||
92ef67c5 MR |
651 | static struct clk_factors_config sun6i_a31_pll6_config = { |
652 | .nshift = 8, | |
653 | .nwidth = 5, | |
654 | .kshift = 4, | |
655 | .kwidth = 2, | |
95e94c1f | 656 | .n_start = 1, |
92ef67c5 MR |
657 | }; |
658 | ||
9f243097 CYT |
659 | static struct clk_factors_config sun5i_a13_ahb_config = { |
660 | .pshift = 4, | |
661 | .pwidth = 2, | |
662 | }; | |
663 | ||
81ba6c5e | 664 | static struct clk_factors_config sun4i_apb1_config = { |
e874a669 EL |
665 | .mshift = 0, |
666 | .mwidth = 5, | |
667 | .pshift = 16, | |
668 | .pwidth = 2, | |
669 | }; | |
670 | ||
6f863417 CYT |
671 | /* user manual says "n" but it's really "p" */ |
672 | static struct clk_factors_config sun7i_a20_out_config = { | |
673 | .mshift = 8, | |
674 | .mwidth = 5, | |
675 | .pshift = 20, | |
676 | .pwidth = 2, | |
677 | }; | |
678 | ||
52be7cc8 | 679 | static const struct factors_data sun4i_pll1_data __initconst = { |
d838ff33 | 680 | .enable = 31, |
81ba6c5e MR |
681 | .table = &sun4i_pll1_config, |
682 | .getter = sun4i_get_pll1_factors, | |
e874a669 EL |
683 | }; |
684 | ||
52be7cc8 | 685 | static const struct factors_data sun6i_a31_pll1_data __initconst = { |
d838ff33 | 686 | .enable = 31, |
6a721db1 MR |
687 | .table = &sun6i_a31_pll1_config, |
688 | .getter = sun6i_a31_get_pll1_factors, | |
689 | }; | |
690 | ||
515c1a4b CYT |
691 | static const struct factors_data sun8i_a23_pll1_data __initconst = { |
692 | .enable = 31, | |
693 | .table = &sun8i_a23_pll1_config, | |
694 | .getter = sun8i_a23_get_pll1_factors, | |
695 | }; | |
696 | ||
5a8ddf26 EL |
697 | static const struct factors_data sun7i_a20_pll4_data __initconst = { |
698 | .enable = 31, | |
699 | .table = &sun4i_pll5_config, | |
700 | .getter = sun4i_get_pll5_factors, | |
701 | }; | |
702 | ||
d584c133 EL |
703 | static const struct factors_data sun4i_pll5_data __initconst = { |
704 | .enable = 31, | |
705 | .table = &sun4i_pll5_config, | |
706 | .getter = sun4i_get_pll5_factors, | |
667f542d CYT |
707 | .name = "pll5", |
708 | }; | |
709 | ||
710 | static const struct factors_data sun4i_pll6_data __initconst = { | |
711 | .enable = 31, | |
712 | .table = &sun4i_pll5_config, | |
713 | .getter = sun4i_get_pll5_factors, | |
714 | .name = "pll6", | |
d584c133 EL |
715 | }; |
716 | ||
92ef67c5 MR |
717 | static const struct factors_data sun6i_a31_pll6_data __initconst = { |
718 | .enable = 31, | |
719 | .table = &sun6i_a31_pll6_config, | |
720 | .getter = sun6i_a31_get_pll6_factors, | |
95e94c1f | 721 | .name = "pll6x2", |
92ef67c5 MR |
722 | }; |
723 | ||
9f243097 CYT |
724 | static const struct factors_data sun5i_a13_ahb_data __initconst = { |
725 | .mux = 6, | |
726 | .muxmask = BIT(1) | BIT(0), | |
727 | .table = &sun5i_a13_ahb_config, | |
728 | .getter = sun5i_a13_get_ahb_factors, | |
729 | }; | |
730 | ||
52be7cc8 | 731 | static const struct factors_data sun4i_apb1_data __initconst = { |
93746e70 EL |
732 | .mux = 24, |
733 | .muxmask = BIT(1) | BIT(0), | |
81ba6c5e MR |
734 | .table = &sun4i_apb1_config, |
735 | .getter = sun4i_get_apb1_factors, | |
e874a669 EL |
736 | }; |
737 | ||
6f863417 CYT |
738 | static const struct factors_data sun7i_a20_out_data __initconst = { |
739 | .enable = 31, | |
740 | .mux = 24, | |
e94f8cb3 | 741 | .muxmask = BIT(1) | BIT(0), |
6f863417 CYT |
742 | .table = &sun7i_a20_out_config, |
743 | .getter = sun7i_a20_get_out_factors, | |
744 | }; | |
745 | ||
5f4e0be3 | 746 | static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, |
601da9d0 | 747 | const struct factors_data *data) |
e874a669 | 748 | { |
7c74c220 HG |
749 | void __iomem *reg; |
750 | ||
751 | reg = of_iomap(node, 0); | |
752 | if (!reg) { | |
753 | pr_err("Could not get registers for factors-clk: %s\n", | |
754 | node->name); | |
755 | return NULL; | |
756 | } | |
757 | ||
758 | return sunxi_factors_register(node, data, &clk_lock, reg); | |
e874a669 EL |
759 | } |
760 | ||
761 | ||
762 | ||
763 | /** | |
764 | * sunxi_mux_clk_setup() - Setup function for muxes | |
765 | */ | |
766 | ||
767 | #define SUNXI_MUX_GATE_WIDTH 2 | |
768 | ||
769 | struct mux_data { | |
770 | u8 shift; | |
771 | }; | |
772 | ||
52be7cc8 | 773 | static const struct mux_data sun4i_cpu_mux_data __initconst = { |
e874a669 EL |
774 | .shift = 16, |
775 | }; | |
776 | ||
52be7cc8 | 777 | static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = { |
6a721db1 MR |
778 | .shift = 12, |
779 | }; | |
780 | ||
e874a669 EL |
781 | static void __init sunxi_mux_clk_setup(struct device_node *node, |
782 | struct mux_data *data) | |
783 | { | |
784 | struct clk *clk; | |
785 | const char *clk_name = node->name; | |
edaf3fb5 | 786 | const char *parents[SUNXI_MAX_PARENTS]; |
89a9456d | 787 | void __iomem *reg; |
8a53fb2b | 788 | int i; |
e874a669 EL |
789 | |
790 | reg = of_iomap(node, 0); | |
791 | ||
8a53fb2b | 792 | i = of_clk_parent_fill(node, parents, SUNXI_MAX_PARENTS); |
f64111eb CYT |
793 | of_property_read_string(node, "clock-output-names", &clk_name); |
794 | ||
819c1de3 | 795 | clk = clk_register_mux(NULL, clk_name, parents, i, |
3ec72fab | 796 | CLK_SET_RATE_PARENT, reg, |
e874a669 EL |
797 | data->shift, SUNXI_MUX_GATE_WIDTH, |
798 | 0, &clk_lock); | |
799 | ||
800 | if (clk) { | |
801 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | |
802 | clk_register_clkdev(clk, clk_name, NULL); | |
803 | } | |
804 | } | |
805 | ||
806 | ||
807 | ||
808 | /** | |
809 | * sunxi_divider_clk_setup() - Setup function for simple divider clocks | |
810 | */ | |
811 | ||
e874a669 | 812 | struct div_data { |
70855bb5 MR |
813 | u8 shift; |
814 | u8 pow; | |
815 | u8 width; | |
ea5671bf | 816 | const struct clk_div_table *table; |
e874a669 EL |
817 | }; |
818 | ||
52be7cc8 | 819 | static const struct div_data sun4i_axi_data __initconst = { |
70855bb5 MR |
820 | .shift = 0, |
821 | .pow = 0, | |
822 | .width = 2, | |
e874a669 EL |
823 | }; |
824 | ||
515c1a4b CYT |
825 | static const struct clk_div_table sun8i_a23_axi_table[] __initconst = { |
826 | { .val = 0, .div = 1 }, | |
827 | { .val = 1, .div = 2 }, | |
828 | { .val = 2, .div = 3 }, | |
829 | { .val = 3, .div = 4 }, | |
830 | { .val = 4, .div = 4 }, | |
831 | { .val = 5, .div = 4 }, | |
832 | { .val = 6, .div = 4 }, | |
833 | { .val = 7, .div = 4 }, | |
834 | { } /* sentinel */ | |
835 | }; | |
836 | ||
837 | static const struct div_data sun8i_a23_axi_data __initconst = { | |
838 | .width = 3, | |
839 | .table = sun8i_a23_axi_table, | |
840 | }; | |
841 | ||
52be7cc8 | 842 | static const struct div_data sun4i_ahb_data __initconst = { |
70855bb5 MR |
843 | .shift = 4, |
844 | .pow = 1, | |
845 | .width = 2, | |
e874a669 EL |
846 | }; |
847 | ||
cfe4c93b CYT |
848 | static const struct clk_div_table sun4i_apb0_table[] __initconst = { |
849 | { .val = 0, .div = 2 }, | |
850 | { .val = 1, .div = 2 }, | |
851 | { .val = 2, .div = 4 }, | |
852 | { .val = 3, .div = 8 }, | |
853 | { } /* sentinel */ | |
854 | }; | |
855 | ||
52be7cc8 | 856 | static const struct div_data sun4i_apb0_data __initconst = { |
70855bb5 MR |
857 | .shift = 8, |
858 | .pow = 1, | |
859 | .width = 2, | |
cfe4c93b | 860 | .table = sun4i_apb0_table, |
e874a669 EL |
861 | }; |
862 | ||
863 | static void __init sunxi_divider_clk_setup(struct device_node *node, | |
864 | struct div_data *data) | |
865 | { | |
866 | struct clk *clk; | |
867 | const char *clk_name = node->name; | |
868 | const char *clk_parent; | |
89a9456d | 869 | void __iomem *reg; |
e874a669 EL |
870 | |
871 | reg = of_iomap(node, 0); | |
872 | ||
873 | clk_parent = of_clk_get_parent_name(node, 0); | |
874 | ||
f64111eb CYT |
875 | of_property_read_string(node, "clock-output-names", &clk_name); |
876 | ||
ea5671bf CYT |
877 | clk = clk_register_divider_table(NULL, clk_name, clk_parent, 0, |
878 | reg, data->shift, data->width, | |
879 | data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0, | |
880 | data->table, &clk_lock); | |
e874a669 EL |
881 | if (clk) { |
882 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | |
883 | clk_register_clkdev(clk, clk_name, NULL); | |
884 | } | |
885 | } | |
886 | ||
887 | ||
13569a70 EL |
888 | |
889 | /** | |
890 | * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks | |
891 | */ | |
892 | ||
893 | #define SUNXI_GATES_MAX_SIZE 64 | |
894 | ||
895 | struct gates_data { | |
896 | DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE); | |
897 | }; | |
898 | ||
d584c133 EL |
899 | /** |
900 | * sunxi_divs_clk_setup() helper data | |
901 | */ | |
902 | ||
934fe5f4 | 903 | #define SUNXI_DIVS_MAX_QTY 4 |
d584c133 EL |
904 | #define SUNXI_DIVISOR_WIDTH 2 |
905 | ||
906 | struct divs_data { | |
907 | const struct factors_data *factors; /* data for the factor clock */ | |
934fe5f4 CYT |
908 | int ndivs; /* number of outputs */ |
909 | /* | |
910 | * List of outputs. Refer to the diagram for sunxi_divs_clk_setup(): | |
911 | * self or base factor clock refers to the output from the pll | |
912 | * itself. The remaining refer to fixed or configurable divider | |
913 | * outputs. | |
914 | */ | |
d584c133 | 915 | struct { |
934fe5f4 | 916 | u8 self; /* is it the base factor clock? (only one) */ |
d584c133 EL |
917 | u8 fixed; /* is it a fixed divisor? if not... */ |
918 | struct clk_div_table *table; /* is it a table based divisor? */ | |
919 | u8 shift; /* otherwise it's a normal divisor with this shift */ | |
920 | u8 pow; /* is it power-of-two based? */ | |
921 | u8 gate; /* is it independently gateable? */ | |
922 | } div[SUNXI_DIVS_MAX_QTY]; | |
923 | }; | |
924 | ||
925 | static struct clk_div_table pll6_sata_tbl[] = { | |
926 | { .val = 0, .div = 6, }, | |
927 | { .val = 1, .div = 12, }, | |
928 | { .val = 2, .div = 18, }, | |
929 | { .val = 3, .div = 24, }, | |
930 | { } /* sentinel */ | |
931 | }; | |
932 | ||
933 | static const struct divs_data pll5_divs_data __initconst = { | |
934 | .factors = &sun4i_pll5_data, | |
13d52f61 | 935 | .ndivs = 2, |
d584c133 EL |
936 | .div = { |
937 | { .shift = 0, .pow = 0, }, /* M, DDR */ | |
938 | { .shift = 16, .pow = 1, }, /* P, other */ | |
934fe5f4 | 939 | /* No output for the base factor clock */ |
d584c133 EL |
940 | } |
941 | }; | |
942 | ||
943 | static const struct divs_data pll6_divs_data __initconst = { | |
667f542d | 944 | .factors = &sun4i_pll6_data, |
f1017969 | 945 | .ndivs = 4, |
d584c133 EL |
946 | .div = { |
947 | { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ | |
948 | { .fixed = 2 }, /* P, other */ | |
934fe5f4 | 949 | { .self = 1 }, /* base factor clock, 2x */ |
f1017969 | 950 | { .fixed = 4 }, /* pll6 / 4, used as ahb input */ |
d584c133 EL |
951 | } |
952 | }; | |
953 | ||
95e94c1f CYT |
954 | static const struct divs_data sun6i_a31_pll6_divs_data __initconst = { |
955 | .factors = &sun6i_a31_pll6_data, | |
934fe5f4 | 956 | .ndivs = 2, |
95e94c1f CYT |
957 | .div = { |
958 | { .fixed = 2 }, /* normal output */ | |
934fe5f4 | 959 | { .self = 1 }, /* base factor clock, 2x */ |
95e94c1f CYT |
960 | } |
961 | }; | |
962 | ||
d584c133 EL |
963 | /** |
964 | * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks | |
965 | * | |
966 | * These clocks look something like this | |
967 | * ________________________ | |
968 | * | ___divisor 1---|----> to consumer | |
969 | * parent >--| pll___/___divisor 2---|----> to consumer | |
970 | * | \_______________|____> to consumer | |
971 | * |________________________| | |
972 | */ | |
973 | ||
974 | static void __init sunxi_divs_clk_setup(struct device_node *node, | |
975 | struct divs_data *data) | |
976 | { | |
977 | struct clk_onecell_data *clk_data; | |
97e36b3c | 978 | const char *parent; |
d584c133 EL |
979 | const char *clk_name; |
980 | struct clk **clks, *pclk; | |
981 | struct clk_hw *gate_hw, *rate_hw; | |
982 | const struct clk_ops *rate_ops; | |
983 | struct clk_gate *gate = NULL; | |
984 | struct clk_fixed_factor *fix_factor; | |
985 | struct clk_divider *divider; | |
89a9456d | 986 | void __iomem *reg; |
13d52f61 | 987 | int ndivs = SUNXI_DIVS_MAX_QTY, i = 0; |
d584c133 EL |
988 | int flags, clkflags; |
989 | ||
934fe5f4 CYT |
990 | /* if number of children known, use it */ |
991 | if (data->ndivs) | |
992 | ndivs = data->ndivs; | |
993 | ||
d584c133 EL |
994 | /* Set up factor clock that we will be dividing */ |
995 | pclk = sunxi_factors_clk_setup(node, data->factors); | |
97e36b3c | 996 | parent = __clk_get_name(pclk); |
d584c133 EL |
997 | |
998 | reg = of_iomap(node, 0); | |
999 | ||
1000 | clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL); | |
1001 | if (!clk_data) | |
1002 | return; | |
1003 | ||
934fe5f4 | 1004 | clks = kcalloc(ndivs, sizeof(*clks), GFP_KERNEL); |
d584c133 EL |
1005 | if (!clks) |
1006 | goto free_clkdata; | |
1007 | ||
1008 | clk_data->clks = clks; | |
1009 | ||
1010 | /* It's not a good idea to have automatic reparenting changing | |
1011 | * our RAM clock! */ | |
1012 | clkflags = !strcmp("pll5", parent) ? 0 : CLK_SET_RATE_PARENT; | |
1013 | ||
13d52f61 | 1014 | for (i = 0; i < ndivs; i++) { |
d584c133 EL |
1015 | if (of_property_read_string_index(node, "clock-output-names", |
1016 | i, &clk_name) != 0) | |
1017 | break; | |
1018 | ||
934fe5f4 CYT |
1019 | /* If this is the base factor clock, only update clks */ |
1020 | if (data->div[i].self) { | |
1021 | clk_data->clks[i] = pclk; | |
1022 | continue; | |
1023 | } | |
1024 | ||
d584c133 EL |
1025 | gate_hw = NULL; |
1026 | rate_hw = NULL; | |
1027 | rate_ops = NULL; | |
1028 | ||
1029 | /* If this leaf clock can be gated, create a gate */ | |
1030 | if (data->div[i].gate) { | |
1031 | gate = kzalloc(sizeof(*gate), GFP_KERNEL); | |
1032 | if (!gate) | |
1033 | goto free_clks; | |
1034 | ||
1035 | gate->reg = reg; | |
1036 | gate->bit_idx = data->div[i].gate; | |
1037 | gate->lock = &clk_lock; | |
1038 | ||
1039 | gate_hw = &gate->hw; | |
1040 | } | |
1041 | ||
1042 | /* Leaves can be fixed or configurable divisors */ | |
1043 | if (data->div[i].fixed) { | |
1044 | fix_factor = kzalloc(sizeof(*fix_factor), GFP_KERNEL); | |
1045 | if (!fix_factor) | |
1046 | goto free_gate; | |
1047 | ||
1048 | fix_factor->mult = 1; | |
1049 | fix_factor->div = data->div[i].fixed; | |
1050 | ||
1051 | rate_hw = &fix_factor->hw; | |
1052 | rate_ops = &clk_fixed_factor_ops; | |
1053 | } else { | |
1054 | divider = kzalloc(sizeof(*divider), GFP_KERNEL); | |
1055 | if (!divider) | |
1056 | goto free_gate; | |
1057 | ||
1058 | flags = data->div[i].pow ? CLK_DIVIDER_POWER_OF_TWO : 0; | |
1059 | ||
1060 | divider->reg = reg; | |
1061 | divider->shift = data->div[i].shift; | |
1062 | divider->width = SUNXI_DIVISOR_WIDTH; | |
1063 | divider->flags = flags; | |
1064 | divider->lock = &clk_lock; | |
1065 | divider->table = data->div[i].table; | |
1066 | ||
1067 | rate_hw = ÷r->hw; | |
1068 | rate_ops = &clk_divider_ops; | |
1069 | } | |
1070 | ||
1071 | /* Wrap the (potential) gate and the divisor on a composite | |
1072 | * clock to unify them */ | |
1073 | clks[i] = clk_register_composite(NULL, clk_name, &parent, 1, | |
1074 | NULL, NULL, | |
1075 | rate_hw, rate_ops, | |
1076 | gate_hw, &clk_gate_ops, | |
1077 | clkflags); | |
1078 | ||
1079 | WARN_ON(IS_ERR(clk_data->clks[i])); | |
1080 | clk_register_clkdev(clks[i], clk_name, NULL); | |
1081 | } | |
1082 | ||
d584c133 EL |
1083 | /* Adjust to the real max */ |
1084 | clk_data->clk_num = i; | |
1085 | ||
1086 | of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); | |
1087 | ||
1088 | return; | |
1089 | ||
1090 | free_gate: | |
1091 | kfree(gate); | |
1092 | free_clks: | |
1093 | kfree(clks); | |
1094 | free_clkdata: | |
1095 | kfree(clk_data); | |
1096 | } | |
1097 | ||
1098 | ||
1099 | ||
e874a669 | 1100 | /* Matches for factors clocks */ |
52be7cc8 | 1101 | static const struct of_device_id clk_factors_match[] __initconst = { |
fd1b22f6 | 1102 | {.compatible = "allwinner,sun4i-a10-pll1-clk", .data = &sun4i_pll1_data,}, |
6a721db1 | 1103 | {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, |
515c1a4b | 1104 | {.compatible = "allwinner,sun8i-a23-pll1-clk", .data = &sun8i_a23_pll1_data,}, |
5a8ddf26 | 1105 | {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,}, |
9f243097 | 1106 | {.compatible = "allwinner,sun5i-a13-ahb-clk", .data = &sun5i_a13_ahb_data,}, |
fd1b22f6 | 1107 | {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,}, |
6f863417 | 1108 | {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, |
e874a669 EL |
1109 | {} |
1110 | }; | |
1111 | ||
1112 | /* Matches for divider clocks */ | |
52be7cc8 | 1113 | static const struct of_device_id clk_div_match[] __initconst = { |
fd1b22f6 | 1114 | {.compatible = "allwinner,sun4i-a10-axi-clk", .data = &sun4i_axi_data,}, |
515c1a4b | 1115 | {.compatible = "allwinner,sun8i-a23-axi-clk", .data = &sun8i_a23_axi_data,}, |
fd1b22f6 MR |
1116 | {.compatible = "allwinner,sun4i-a10-ahb-clk", .data = &sun4i_ahb_data,}, |
1117 | {.compatible = "allwinner,sun4i-a10-apb0-clk", .data = &sun4i_apb0_data,}, | |
e874a669 EL |
1118 | {} |
1119 | }; | |
1120 | ||
d584c133 EL |
1121 | /* Matches for divided outputs */ |
1122 | static const struct of_device_id clk_divs_match[] __initconst = { | |
fd1b22f6 MR |
1123 | {.compatible = "allwinner,sun4i-a10-pll5-clk", .data = &pll5_divs_data,}, |
1124 | {.compatible = "allwinner,sun4i-a10-pll6-clk", .data = &pll6_divs_data,}, | |
95e94c1f | 1125 | {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_divs_data,}, |
d584c133 EL |
1126 | {} |
1127 | }; | |
1128 | ||
e874a669 | 1129 | /* Matches for mux clocks */ |
52be7cc8 | 1130 | static const struct of_device_id clk_mux_match[] __initconst = { |
fd1b22f6 | 1131 | {.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,}, |
6a721db1 | 1132 | {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,}, |
e874a669 EL |
1133 | {} |
1134 | }; | |
1135 | ||
13569a70 | 1136 | |
e874a669 EL |
1137 | static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_match, |
1138 | void *function) | |
1139 | { | |
1140 | struct device_node *np; | |
1141 | const struct div_data *data; | |
1142 | const struct of_device_id *match; | |
1143 | void (*setup_function)(struct device_node *, const void *) = function; | |
1144 | ||
cb7d5f42 | 1145 | for_each_matching_node_and_match(np, clk_match, &match) { |
e874a669 EL |
1146 | data = match->data; |
1147 | setup_function(np, data); | |
1148 | } | |
1149 | } | |
1150 | ||
134a6690 | 1151 | static void __init sunxi_init_clocks(const char *clocks[], int nclocks) |
8e6a4c40 | 1152 | { |
134a6690 | 1153 | unsigned int i; |
8e6a4c40 | 1154 | |
b712a623 CYT |
1155 | /* Register divided output clocks */ |
1156 | of_sunxi_table_clock_setup(clk_divs_match, sunxi_divs_clk_setup); | |
1157 | ||
e874a669 EL |
1158 | /* Register factor clocks */ |
1159 | of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); | |
1160 | ||
1161 | /* Register divider clocks */ | |
1162 | of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup); | |
1163 | ||
1164 | /* Register mux clocks */ | |
1165 | of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup); | |
13569a70 | 1166 | |
134a6690 MR |
1167 | /* Protect the clocks that needs to stay on */ |
1168 | for (i = 0; i < nclocks; i++) { | |
1169 | struct clk *clk = clk_get(NULL, clocks[i]); | |
1170 | ||
1171 | if (!IS_ERR(clk)) | |
1172 | clk_prepare_enable(clk); | |
1173 | } | |
1174 | } | |
1175 | ||
1176 | static const char *sun4i_a10_critical_clocks[] __initdata = { | |
1177 | "pll5_ddr", | |
1178 | }; | |
1179 | ||
1180 | static void __init sun4i_a10_init_clocks(struct device_node *node) | |
1181 | { | |
1182 | sunxi_init_clocks(sun4i_a10_critical_clocks, | |
1183 | ARRAY_SIZE(sun4i_a10_critical_clocks)); | |
1184 | } | |
1185 | CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks); | |
1186 | ||
1187 | static const char *sun5i_critical_clocks[] __initdata = { | |
946fd40f | 1188 | "cpu", |
134a6690 MR |
1189 | "pll5_ddr", |
1190 | }; | |
1191 | ||
1192 | static void __init sun5i_init_clocks(struct device_node *node) | |
1193 | { | |
1194 | sunxi_init_clocks(sun5i_critical_clocks, | |
1195 | ARRAY_SIZE(sun5i_critical_clocks)); | |
1196 | } | |
1197 | CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sun5i_init_clocks); | |
1198 | CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sun5i_init_clocks); | |
bef6229f | 1199 | CLK_OF_DECLARE(sun5i_r8_clk_init, "allwinner,sun5i-r8", sun5i_init_clocks); |
134a6690 MR |
1200 | CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sun5i_init_clocks); |
1201 | ||
1202 | static const char *sun6i_critical_clocks[] __initdata = { | |
2df73f40 | 1203 | "cpu", |
134a6690 MR |
1204 | }; |
1205 | ||
1206 | static void __init sun6i_init_clocks(struct device_node *node) | |
1207 | { | |
1208 | sunxi_init_clocks(sun6i_critical_clocks, | |
1209 | ARRAY_SIZE(sun6i_critical_clocks)); | |
e874a669 | 1210 | } |
134a6690 | 1211 | CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks); |
b0f2faa5 | 1212 | CLK_OF_DECLARE(sun6i_a31s_clk_init, "allwinner,sun6i-a31s", sun6i_init_clocks); |
515c1a4b | 1213 | CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks); |
159870d2 | 1214 | CLK_OF_DECLARE(sun8i_a33_clk_init, "allwinner,sun8i-a33", sun6i_init_clocks); |
0b0f0802 CYT |
1215 | |
1216 | static void __init sun9i_init_clocks(struct device_node *node) | |
1217 | { | |
1218 | sunxi_init_clocks(NULL, 0); | |
1219 | } | |
1220 | CLK_OF_DECLARE(sun9i_a80_clk_init, "allwinner,sun9i-a80", sun9i_init_clocks); |