Commit | Line | Data |
---|---|---|
b066303f PB |
1 | /* |
2 | * Ingenic SoC CGU driver | |
3 | * | |
4 | * Copyright (c) 2013-2015 Imagination Technologies | |
5 | * Author: Paul Burton <paul.burton@imgtec.com> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License as | |
9 | * published by the Free Software Foundation; either version 2 of | |
10 | * the License, or (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | */ | |
17 | ||
18 | #include <linux/bitops.h> | |
e2a65709 | 19 | #include <linux/clk.h> |
b066303f PB |
20 | #include <linux/clk-provider.h> |
21 | #include <linux/clkdev.h> | |
22 | #include <linux/delay.h> | |
23 | #include <linux/math64.h> | |
24 | #include <linux/of.h> | |
25 | #include <linux/of_address.h> | |
26 | #include <linux/slab.h> | |
27 | #include <linux/spinlock.h> | |
28 | #include "cgu.h" | |
29 | ||
30 | #define MHZ (1000 * 1000) | |
31 | ||
32 | /** | |
33 | * ingenic_cgu_gate_get() - get the value of clock gate register bit | |
34 | * @cgu: reference to the CGU whose registers should be read | |
35 | * @info: info struct describing the gate bit | |
36 | * | |
37 | * Retrieves the state of the clock gate bit described by info. The | |
38 | * caller must hold cgu->lock. | |
39 | * | |
40 | * Return: true if the gate bit is set, else false. | |
41 | */ | |
42 | static inline bool | |
43 | ingenic_cgu_gate_get(struct ingenic_cgu *cgu, | |
44 | const struct ingenic_cgu_gate_info *info) | |
45 | { | |
46 | return readl(cgu->base + info->reg) & BIT(info->bit); | |
47 | } | |
48 | ||
49 | /** | |
50 | * ingenic_cgu_gate_set() - set the value of clock gate register bit | |
51 | * @cgu: reference to the CGU whose registers should be modified | |
52 | * @info: info struct describing the gate bit | |
53 | * @val: non-zero to gate a clock, otherwise zero | |
54 | * | |
55 | * Sets the given gate bit in order to gate or ungate a clock. | |
56 | * | |
57 | * The caller must hold cgu->lock. | |
58 | */ | |
59 | static inline void | |
60 | ingenic_cgu_gate_set(struct ingenic_cgu *cgu, | |
61 | const struct ingenic_cgu_gate_info *info, bool val) | |
62 | { | |
63 | u32 clkgr = readl(cgu->base + info->reg); | |
64 | ||
65 | if (val) | |
66 | clkgr |= BIT(info->bit); | |
67 | else | |
68 | clkgr &= ~BIT(info->bit); | |
69 | ||
70 | writel(clkgr, cgu->base + info->reg); | |
71 | } | |
72 | ||
73 | /* | |
74 | * PLL operations | |
75 | */ | |
76 | ||
77 | static unsigned long | |
78 | ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | |
79 | { | |
80 | struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); | |
81 | struct ingenic_cgu *cgu = ingenic_clk->cgu; | |
82 | const struct ingenic_cgu_clk_info *clk_info; | |
83 | const struct ingenic_cgu_pll_info *pll_info; | |
84 | unsigned m, n, od_enc, od; | |
85 | bool bypass, enable; | |
86 | unsigned long flags; | |
87 | u32 ctl; | |
88 | ||
89 | clk_info = &cgu->clock_info[ingenic_clk->idx]; | |
90 | BUG_ON(clk_info->type != CGU_CLK_PLL); | |
91 | pll_info = &clk_info->pll; | |
92 | ||
93 | spin_lock_irqsave(&cgu->lock, flags); | |
94 | ctl = readl(cgu->base + pll_info->reg); | |
95 | spin_unlock_irqrestore(&cgu->lock, flags); | |
96 | ||
97 | m = (ctl >> pll_info->m_shift) & GENMASK(pll_info->m_bits - 1, 0); | |
98 | m += pll_info->m_offset; | |
99 | n = (ctl >> pll_info->n_shift) & GENMASK(pll_info->n_bits - 1, 0); | |
100 | n += pll_info->n_offset; | |
101 | od_enc = ctl >> pll_info->od_shift; | |
102 | od_enc &= GENMASK(pll_info->od_bits - 1, 0); | |
103 | bypass = !!(ctl & BIT(pll_info->bypass_bit)); | |
104 | enable = !!(ctl & BIT(pll_info->enable_bit)); | |
105 | ||
106 | if (bypass) | |
107 | return parent_rate; | |
108 | ||
109 | if (!enable) | |
110 | return 0; | |
111 | ||
112 | for (od = 0; od < pll_info->od_max; od++) { | |
113 | if (pll_info->od_encoding[od] == od_enc) | |
114 | break; | |
115 | } | |
116 | BUG_ON(od == pll_info->od_max); | |
117 | od++; | |
118 | ||
119 | return div_u64((u64)parent_rate * m, n * od); | |
120 | } | |
121 | ||
122 | static unsigned long | |
123 | ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info, | |
124 | unsigned long rate, unsigned long parent_rate, | |
125 | unsigned *pm, unsigned *pn, unsigned *pod) | |
126 | { | |
127 | const struct ingenic_cgu_pll_info *pll_info; | |
128 | unsigned m, n, od; | |
129 | ||
130 | pll_info = &clk_info->pll; | |
131 | od = 1; | |
132 | ||
133 | /* | |
134 | * The frequency after the input divider must be between 10 and 50 MHz. | |
135 | * The highest divider yields the best resolution. | |
136 | */ | |
137 | n = parent_rate / (10 * MHZ); | |
138 | n = min_t(unsigned, n, 1 << clk_info->pll.n_bits); | |
139 | n = max_t(unsigned, n, pll_info->n_offset); | |
140 | ||
141 | m = (rate / MHZ) * od * n / (parent_rate / MHZ); | |
142 | m = min_t(unsigned, m, 1 << clk_info->pll.m_bits); | |
143 | m = max_t(unsigned, m, pll_info->m_offset); | |
144 | ||
145 | if (pm) | |
146 | *pm = m; | |
147 | if (pn) | |
148 | *pn = n; | |
149 | if (pod) | |
150 | *pod = od; | |
151 | ||
152 | return div_u64((u64)parent_rate * m, n * od); | |
153 | } | |
154 | ||
155 | static long | |
156 | ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate, | |
157 | unsigned long *prate) | |
158 | { | |
159 | struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); | |
160 | struct ingenic_cgu *cgu = ingenic_clk->cgu; | |
161 | const struct ingenic_cgu_clk_info *clk_info; | |
162 | ||
163 | clk_info = &cgu->clock_info[ingenic_clk->idx]; | |
164 | BUG_ON(clk_info->type != CGU_CLK_PLL); | |
165 | ||
166 | return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL); | |
167 | } | |
168 | ||
169 | static int | |
170 | ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate, | |
171 | unsigned long parent_rate) | |
172 | { | |
173 | const unsigned timeout = 100; | |
174 | struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); | |
175 | struct ingenic_cgu *cgu = ingenic_clk->cgu; | |
176 | const struct ingenic_cgu_clk_info *clk_info; | |
177 | const struct ingenic_cgu_pll_info *pll_info; | |
178 | unsigned long rate, flags; | |
179 | unsigned m, n, od, i; | |
180 | u32 ctl; | |
181 | ||
182 | clk_info = &cgu->clock_info[ingenic_clk->idx]; | |
183 | BUG_ON(clk_info->type != CGU_CLK_PLL); | |
184 | pll_info = &clk_info->pll; | |
185 | ||
186 | rate = ingenic_pll_calc(clk_info, req_rate, parent_rate, | |
187 | &m, &n, &od); | |
188 | if (rate != req_rate) | |
189 | pr_info("ingenic-cgu: request '%s' rate %luHz, actual %luHz\n", | |
190 | clk_info->name, req_rate, rate); | |
191 | ||
192 | spin_lock_irqsave(&cgu->lock, flags); | |
193 | ctl = readl(cgu->base + pll_info->reg); | |
194 | ||
195 | ctl &= ~(GENMASK(pll_info->m_bits - 1, 0) << pll_info->m_shift); | |
196 | ctl |= (m - pll_info->m_offset) << pll_info->m_shift; | |
197 | ||
198 | ctl &= ~(GENMASK(pll_info->n_bits - 1, 0) << pll_info->n_shift); | |
199 | ctl |= (n - pll_info->n_offset) << pll_info->n_shift; | |
200 | ||
201 | ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift); | |
202 | ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift; | |
203 | ||
204 | ctl &= ~BIT(pll_info->bypass_bit); | |
205 | ctl |= BIT(pll_info->enable_bit); | |
206 | ||
207 | writel(ctl, cgu->base + pll_info->reg); | |
208 | ||
209 | /* wait for the PLL to stabilise */ | |
210 | for (i = 0; i < timeout; i++) { | |
211 | ctl = readl(cgu->base + pll_info->reg); | |
212 | if (ctl & BIT(pll_info->stable_bit)) | |
213 | break; | |
214 | mdelay(1); | |
215 | } | |
216 | ||
217 | spin_unlock_irqrestore(&cgu->lock, flags); | |
218 | ||
219 | if (i == timeout) | |
220 | return -EBUSY; | |
221 | ||
222 | return 0; | |
223 | } | |
224 | ||
225 | static const struct clk_ops ingenic_pll_ops = { | |
226 | .recalc_rate = ingenic_pll_recalc_rate, | |
227 | .round_rate = ingenic_pll_round_rate, | |
228 | .set_rate = ingenic_pll_set_rate, | |
229 | }; | |
230 | ||
231 | /* | |
232 | * Operations for all non-PLL clocks | |
233 | */ | |
234 | ||
235 | static u8 ingenic_clk_get_parent(struct clk_hw *hw) | |
236 | { | |
237 | struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); | |
238 | struct ingenic_cgu *cgu = ingenic_clk->cgu; | |
239 | const struct ingenic_cgu_clk_info *clk_info; | |
240 | u32 reg; | |
241 | u8 i, hw_idx, idx = 0; | |
242 | ||
243 | clk_info = &cgu->clock_info[ingenic_clk->idx]; | |
244 | ||
245 | if (clk_info->type & CGU_CLK_MUX) { | |
246 | reg = readl(cgu->base + clk_info->mux.reg); | |
247 | hw_idx = (reg >> clk_info->mux.shift) & | |
248 | GENMASK(clk_info->mux.bits - 1, 0); | |
249 | ||
250 | /* | |
251 | * Convert the hardware index to the parent index by skipping | |
252 | * over any -1's in the parents array. | |
253 | */ | |
254 | for (i = 0; i < hw_idx; i++) { | |
255 | if (clk_info->parents[i] != -1) | |
256 | idx++; | |
257 | } | |
258 | } | |
259 | ||
260 | return idx; | |
261 | } | |
262 | ||
263 | static int ingenic_clk_set_parent(struct clk_hw *hw, u8 idx) | |
264 | { | |
265 | struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); | |
266 | struct ingenic_cgu *cgu = ingenic_clk->cgu; | |
267 | const struct ingenic_cgu_clk_info *clk_info; | |
268 | unsigned long flags; | |
269 | u8 curr_idx, hw_idx, num_poss; | |
270 | u32 reg, mask; | |
271 | ||
272 | clk_info = &cgu->clock_info[ingenic_clk->idx]; | |
273 | ||
274 | if (clk_info->type & CGU_CLK_MUX) { | |
275 | /* | |
276 | * Convert the parent index to the hardware index by adding | |
277 | * 1 for any -1 in the parents array preceding the given | |
278 | * index. That is, we want the index of idx'th entry in | |
279 | * clk_info->parents which does not equal -1. | |
280 | */ | |
281 | hw_idx = curr_idx = 0; | |
282 | num_poss = 1 << clk_info->mux.bits; | |
283 | for (; hw_idx < num_poss; hw_idx++) { | |
284 | if (clk_info->parents[hw_idx] == -1) | |
285 | continue; | |
286 | if (curr_idx == idx) | |
287 | break; | |
288 | curr_idx++; | |
289 | } | |
290 | ||
291 | /* idx should always be a valid parent */ | |
292 | BUG_ON(curr_idx != idx); | |
293 | ||
294 | mask = GENMASK(clk_info->mux.bits - 1, 0); | |
295 | mask <<= clk_info->mux.shift; | |
296 | ||
297 | spin_lock_irqsave(&cgu->lock, flags); | |
298 | ||
299 | /* write the register */ | |
300 | reg = readl(cgu->base + clk_info->mux.reg); | |
301 | reg &= ~mask; | |
302 | reg |= hw_idx << clk_info->mux.shift; | |
303 | writel(reg, cgu->base + clk_info->mux.reg); | |
304 | ||
305 | spin_unlock_irqrestore(&cgu->lock, flags); | |
306 | return 0; | |
307 | } | |
308 | ||
309 | return idx ? -EINVAL : 0; | |
310 | } | |
311 | ||
312 | static unsigned long | |
313 | ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | |
314 | { | |
315 | struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); | |
316 | struct ingenic_cgu *cgu = ingenic_clk->cgu; | |
317 | const struct ingenic_cgu_clk_info *clk_info; | |
318 | unsigned long rate = parent_rate; | |
319 | u32 div_reg, div; | |
320 | ||
321 | clk_info = &cgu->clock_info[ingenic_clk->idx]; | |
322 | ||
323 | if (clk_info->type & CGU_CLK_DIV) { | |
324 | div_reg = readl(cgu->base + clk_info->div.reg); | |
325 | div = (div_reg >> clk_info->div.shift) & | |
326 | GENMASK(clk_info->div.bits - 1, 0); | |
327 | div += 1; | |
4afe2d1a | 328 | div *= clk_info->div.div; |
b066303f PB |
329 | |
330 | rate /= div; | |
331 | } | |
332 | ||
333 | return rate; | |
334 | } | |
335 | ||
336 | static unsigned | |
337 | ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info, | |
338 | unsigned long parent_rate, unsigned long req_rate) | |
339 | { | |
340 | unsigned div; | |
341 | ||
342 | /* calculate the divide */ | |
343 | div = DIV_ROUND_UP(parent_rate, req_rate); | |
344 | ||
345 | /* and impose hardware constraints */ | |
346 | div = min_t(unsigned, div, 1 << clk_info->div.bits); | |
347 | div = max_t(unsigned, div, 1); | |
348 | ||
4afe2d1a HH |
349 | /* |
350 | * If the divider value itself must be divided before being written to | |
351 | * the divider register, we must ensure we don't have any bits set that | |
352 | * would be lost as a result of doing so. | |
353 | */ | |
354 | div /= clk_info->div.div; | |
355 | div *= clk_info->div.div; | |
356 | ||
b066303f PB |
357 | return div; |
358 | } | |
359 | ||
360 | static long | |
361 | ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate, | |
362 | unsigned long *parent_rate) | |
363 | { | |
364 | struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); | |
365 | struct ingenic_cgu *cgu = ingenic_clk->cgu; | |
366 | const struct ingenic_cgu_clk_info *clk_info; | |
367 | long rate = *parent_rate; | |
368 | ||
369 | clk_info = &cgu->clock_info[ingenic_clk->idx]; | |
370 | ||
371 | if (clk_info->type & CGU_CLK_DIV) | |
372 | rate /= ingenic_clk_calc_div(clk_info, *parent_rate, req_rate); | |
373 | else if (clk_info->type & CGU_CLK_FIXDIV) | |
374 | rate /= clk_info->fixdiv.div; | |
375 | ||
376 | return rate; | |
377 | } | |
378 | ||
379 | static int | |
380 | ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate, | |
381 | unsigned long parent_rate) | |
382 | { | |
383 | struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); | |
384 | struct ingenic_cgu *cgu = ingenic_clk->cgu; | |
385 | const struct ingenic_cgu_clk_info *clk_info; | |
386 | const unsigned timeout = 100; | |
387 | unsigned long rate, flags; | |
388 | unsigned div, i; | |
389 | u32 reg, mask; | |
390 | int ret = 0; | |
391 | ||
392 | clk_info = &cgu->clock_info[ingenic_clk->idx]; | |
393 | ||
394 | if (clk_info->type & CGU_CLK_DIV) { | |
395 | div = ingenic_clk_calc_div(clk_info, parent_rate, req_rate); | |
396 | rate = parent_rate / div; | |
397 | ||
398 | if (rate != req_rate) | |
399 | return -EINVAL; | |
400 | ||
401 | spin_lock_irqsave(&cgu->lock, flags); | |
402 | reg = readl(cgu->base + clk_info->div.reg); | |
403 | ||
404 | /* update the divide */ | |
405 | mask = GENMASK(clk_info->div.bits - 1, 0); | |
406 | reg &= ~(mask << clk_info->div.shift); | |
4afe2d1a | 407 | reg |= ((div / clk_info->div.div) - 1) << clk_info->div.shift; |
b066303f PB |
408 | |
409 | /* clear the stop bit */ | |
410 | if (clk_info->div.stop_bit != -1) | |
411 | reg &= ~BIT(clk_info->div.stop_bit); | |
412 | ||
413 | /* set the change enable bit */ | |
414 | if (clk_info->div.ce_bit != -1) | |
415 | reg |= BIT(clk_info->div.ce_bit); | |
416 | ||
417 | /* update the hardware */ | |
418 | writel(reg, cgu->base + clk_info->div.reg); | |
419 | ||
420 | /* wait for the change to take effect */ | |
421 | if (clk_info->div.busy_bit != -1) { | |
422 | for (i = 0; i < timeout; i++) { | |
423 | reg = readl(cgu->base + clk_info->div.reg); | |
424 | if (!(reg & BIT(clk_info->div.busy_bit))) | |
425 | break; | |
426 | mdelay(1); | |
427 | } | |
428 | if (i == timeout) | |
429 | ret = -EBUSY; | |
430 | } | |
431 | ||
432 | spin_unlock_irqrestore(&cgu->lock, flags); | |
433 | return ret; | |
434 | } | |
435 | ||
436 | return -EINVAL; | |
437 | } | |
438 | ||
439 | static int ingenic_clk_enable(struct clk_hw *hw) | |
440 | { | |
441 | struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); | |
442 | struct ingenic_cgu *cgu = ingenic_clk->cgu; | |
443 | const struct ingenic_cgu_clk_info *clk_info; | |
444 | unsigned long flags; | |
445 | ||
446 | clk_info = &cgu->clock_info[ingenic_clk->idx]; | |
447 | ||
448 | if (clk_info->type & CGU_CLK_GATE) { | |
449 | /* ungate the clock */ | |
450 | spin_lock_irqsave(&cgu->lock, flags); | |
451 | ingenic_cgu_gate_set(cgu, &clk_info->gate, false); | |
452 | spin_unlock_irqrestore(&cgu->lock, flags); | |
453 | } | |
454 | ||
455 | return 0; | |
456 | } | |
457 | ||
458 | static void ingenic_clk_disable(struct clk_hw *hw) | |
459 | { | |
460 | struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); | |
461 | struct ingenic_cgu *cgu = ingenic_clk->cgu; | |
462 | const struct ingenic_cgu_clk_info *clk_info; | |
463 | unsigned long flags; | |
464 | ||
465 | clk_info = &cgu->clock_info[ingenic_clk->idx]; | |
466 | ||
467 | if (clk_info->type & CGU_CLK_GATE) { | |
468 | /* gate the clock */ | |
469 | spin_lock_irqsave(&cgu->lock, flags); | |
470 | ingenic_cgu_gate_set(cgu, &clk_info->gate, true); | |
471 | spin_unlock_irqrestore(&cgu->lock, flags); | |
472 | } | |
473 | } | |
474 | ||
475 | static int ingenic_clk_is_enabled(struct clk_hw *hw) | |
476 | { | |
477 | struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); | |
478 | struct ingenic_cgu *cgu = ingenic_clk->cgu; | |
479 | const struct ingenic_cgu_clk_info *clk_info; | |
480 | unsigned long flags; | |
481 | int enabled = 1; | |
482 | ||
483 | clk_info = &cgu->clock_info[ingenic_clk->idx]; | |
484 | ||
485 | if (clk_info->type & CGU_CLK_GATE) { | |
486 | spin_lock_irqsave(&cgu->lock, flags); | |
487 | enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate); | |
488 | spin_unlock_irqrestore(&cgu->lock, flags); | |
489 | } | |
490 | ||
491 | return enabled; | |
492 | } | |
493 | ||
494 | static const struct clk_ops ingenic_clk_ops = { | |
495 | .get_parent = ingenic_clk_get_parent, | |
496 | .set_parent = ingenic_clk_set_parent, | |
497 | ||
498 | .recalc_rate = ingenic_clk_recalc_rate, | |
499 | .round_rate = ingenic_clk_round_rate, | |
500 | .set_rate = ingenic_clk_set_rate, | |
501 | ||
502 | .enable = ingenic_clk_enable, | |
503 | .disable = ingenic_clk_disable, | |
504 | .is_enabled = ingenic_clk_is_enabled, | |
505 | }; | |
506 | ||
507 | /* | |
508 | * Setup functions. | |
509 | */ | |
510 | ||
511 | static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx) | |
512 | { | |
513 | const struct ingenic_cgu_clk_info *clk_info = &cgu->clock_info[idx]; | |
514 | struct clk_init_data clk_init; | |
515 | struct ingenic_clk *ingenic_clk = NULL; | |
516 | struct clk *clk, *parent; | |
517 | const char *parent_names[4]; | |
518 | unsigned caps, i, num_possible; | |
519 | int err = -EINVAL; | |
520 | ||
521 | BUILD_BUG_ON(ARRAY_SIZE(clk_info->parents) > ARRAY_SIZE(parent_names)); | |
522 | ||
523 | if (clk_info->type == CGU_CLK_EXT) { | |
524 | clk = of_clk_get_by_name(cgu->np, clk_info->name); | |
525 | if (IS_ERR(clk)) { | |
526 | pr_err("%s: no external clock '%s' provided\n", | |
527 | __func__, clk_info->name); | |
528 | err = -ENODEV; | |
529 | goto out; | |
530 | } | |
531 | err = clk_register_clkdev(clk, clk_info->name, NULL); | |
532 | if (err) { | |
533 | clk_put(clk); | |
534 | goto out; | |
535 | } | |
536 | cgu->clocks.clks[idx] = clk; | |
537 | return 0; | |
538 | } | |
539 | ||
540 | if (!clk_info->type) { | |
541 | pr_err("%s: no clock type specified for '%s'\n", __func__, | |
542 | clk_info->name); | |
543 | goto out; | |
544 | } | |
545 | ||
546 | ingenic_clk = kzalloc(sizeof(*ingenic_clk), GFP_KERNEL); | |
547 | if (!ingenic_clk) { | |
548 | err = -ENOMEM; | |
549 | goto out; | |
550 | } | |
551 | ||
552 | ingenic_clk->hw.init = &clk_init; | |
553 | ingenic_clk->cgu = cgu; | |
554 | ingenic_clk->idx = idx; | |
555 | ||
556 | clk_init.name = clk_info->name; | |
557 | clk_init.flags = 0; | |
558 | clk_init.parent_names = parent_names; | |
559 | ||
560 | caps = clk_info->type; | |
561 | ||
562 | if (caps & (CGU_CLK_MUX | CGU_CLK_CUSTOM)) { | |
563 | clk_init.num_parents = 0; | |
564 | ||
565 | if (caps & CGU_CLK_MUX) | |
566 | num_possible = 1 << clk_info->mux.bits; | |
567 | else | |
568 | num_possible = ARRAY_SIZE(clk_info->parents); | |
569 | ||
570 | for (i = 0; i < num_possible; i++) { | |
571 | if (clk_info->parents[i] == -1) | |
572 | continue; | |
573 | ||
574 | parent = cgu->clocks.clks[clk_info->parents[i]]; | |
575 | parent_names[clk_init.num_parents] = | |
576 | __clk_get_name(parent); | |
577 | clk_init.num_parents++; | |
578 | } | |
579 | ||
580 | BUG_ON(!clk_init.num_parents); | |
581 | BUG_ON(clk_init.num_parents > ARRAY_SIZE(parent_names)); | |
582 | } else { | |
583 | BUG_ON(clk_info->parents[0] == -1); | |
584 | clk_init.num_parents = 1; | |
585 | parent = cgu->clocks.clks[clk_info->parents[0]]; | |
586 | parent_names[0] = __clk_get_name(parent); | |
587 | } | |
588 | ||
589 | if (caps & CGU_CLK_CUSTOM) { | |
590 | clk_init.ops = clk_info->custom.clk_ops; | |
591 | ||
592 | caps &= ~CGU_CLK_CUSTOM; | |
593 | ||
594 | if (caps) { | |
595 | pr_err("%s: custom clock may not be combined with type 0x%x\n", | |
596 | __func__, caps); | |
597 | goto out; | |
598 | } | |
599 | } else if (caps & CGU_CLK_PLL) { | |
600 | clk_init.ops = &ingenic_pll_ops; | |
601 | ||
602 | caps &= ~CGU_CLK_PLL; | |
603 | ||
604 | if (caps) { | |
605 | pr_err("%s: PLL may not be combined with type 0x%x\n", | |
606 | __func__, caps); | |
607 | goto out; | |
608 | } | |
609 | } else { | |
610 | clk_init.ops = &ingenic_clk_ops; | |
611 | } | |
612 | ||
613 | /* nothing to do for gates or fixed dividers */ | |
614 | caps &= ~(CGU_CLK_GATE | CGU_CLK_FIXDIV); | |
615 | ||
616 | if (caps & CGU_CLK_MUX) { | |
617 | if (!(caps & CGU_CLK_MUX_GLITCHFREE)) | |
618 | clk_init.flags |= CLK_SET_PARENT_GATE; | |
619 | ||
620 | caps &= ~(CGU_CLK_MUX | CGU_CLK_MUX_GLITCHFREE); | |
621 | } | |
622 | ||
623 | if (caps & CGU_CLK_DIV) { | |
624 | caps &= ~CGU_CLK_DIV; | |
625 | } else { | |
626 | /* pass rate changes to the parent clock */ | |
627 | clk_init.flags |= CLK_SET_RATE_PARENT; | |
628 | } | |
629 | ||
630 | if (caps) { | |
631 | pr_err("%s: unknown clock type 0x%x\n", __func__, caps); | |
632 | goto out; | |
633 | } | |
634 | ||
635 | clk = clk_register(NULL, &ingenic_clk->hw); | |
636 | if (IS_ERR(clk)) { | |
637 | pr_err("%s: failed to register clock '%s'\n", __func__, | |
638 | clk_info->name); | |
639 | err = PTR_ERR(clk); | |
640 | goto out; | |
641 | } | |
642 | ||
643 | err = clk_register_clkdev(clk, clk_info->name, NULL); | |
644 | if (err) | |
645 | goto out; | |
646 | ||
647 | cgu->clocks.clks[idx] = clk; | |
648 | out: | |
649 | if (err) | |
650 | kfree(ingenic_clk); | |
651 | return err; | |
652 | } | |
653 | ||
654 | struct ingenic_cgu * | |
655 | ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info, | |
656 | unsigned num_clocks, struct device_node *np) | |
657 | { | |
658 | struct ingenic_cgu *cgu; | |
659 | ||
660 | cgu = kzalloc(sizeof(*cgu), GFP_KERNEL); | |
661 | if (!cgu) | |
662 | goto err_out; | |
663 | ||
664 | cgu->base = of_iomap(np, 0); | |
665 | if (!cgu->base) { | |
666 | pr_err("%s: failed to map CGU registers\n", __func__); | |
667 | goto err_out_free; | |
668 | } | |
669 | ||
670 | cgu->np = np; | |
671 | cgu->clock_info = clock_info; | |
672 | cgu->clocks.clk_num = num_clocks; | |
673 | ||
674 | spin_lock_init(&cgu->lock); | |
675 | ||
676 | return cgu; | |
677 | ||
678 | err_out_free: | |
679 | kfree(cgu); | |
680 | err_out: | |
681 | return NULL; | |
682 | } | |
683 | ||
684 | int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu) | |
685 | { | |
686 | unsigned i; | |
687 | int err; | |
688 | ||
689 | cgu->clocks.clks = kcalloc(cgu->clocks.clk_num, sizeof(struct clk *), | |
690 | GFP_KERNEL); | |
691 | if (!cgu->clocks.clks) { | |
692 | err = -ENOMEM; | |
693 | goto err_out; | |
694 | } | |
695 | ||
696 | for (i = 0; i < cgu->clocks.clk_num; i++) { | |
697 | err = ingenic_register_clock(cgu, i); | |
698 | if (err) | |
699 | goto err_out_unregister; | |
700 | } | |
701 | ||
702 | err = of_clk_add_provider(cgu->np, of_clk_src_onecell_get, | |
703 | &cgu->clocks); | |
704 | if (err) | |
705 | goto err_out_unregister; | |
706 | ||
707 | return 0; | |
708 | ||
709 | err_out_unregister: | |
710 | for (i = 0; i < cgu->clocks.clk_num; i++) { | |
711 | if (!cgu->clocks.clks[i]) | |
712 | continue; | |
713 | if (cgu->clock_info[i].type & CGU_CLK_EXT) | |
714 | clk_put(cgu->clocks.clks[i]); | |
715 | else | |
716 | clk_unregister(cgu->clocks.clks[i]); | |
717 | } | |
718 | kfree(cgu->clocks.clks); | |
719 | err_out: | |
720 | return err; | |
721 | } |