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