1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2014 Google, Inc. |
4 | */ |
5 | |
6 | #define pr_fmt(fmt) "%s: " fmt, __func__ |
7 | |
8 | #include <linux/clk-provider.h> |
9 | #include <linux/io.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/printk.h> |
12 | #include <linux/slab.h> |
13 | |
14 | #include "clk.h" |
15 | |
16 | #define PLL_STATUS 0x0 |
17 | #define PLL_STATUS_LOCK BIT(0) |
18 | |
19 | #define PLL_CTRL1 0x4 |
20 | #define PLL_CTRL1_REFDIV_SHIFT 0 |
21 | #define PLL_CTRL1_REFDIV_MASK 0x3f |
22 | #define PLL_CTRL1_FBDIV_SHIFT 6 |
23 | #define PLL_CTRL1_FBDIV_MASK 0xfff |
24 | #define PLL_INT_CTRL1_POSTDIV1_SHIFT 18 |
25 | #define PLL_INT_CTRL1_POSTDIV1_MASK 0x7 |
26 | #define PLL_INT_CTRL1_POSTDIV2_SHIFT 21 |
27 | #define PLL_INT_CTRL1_POSTDIV2_MASK 0x7 |
28 | #define PLL_INT_CTRL1_PD BIT(24) |
29 | #define PLL_INT_CTRL1_DSMPD BIT(25) |
30 | #define PLL_INT_CTRL1_FOUTPOSTDIVPD BIT(26) |
31 | #define PLL_INT_CTRL1_FOUTVCOPD BIT(27) |
32 | |
33 | #define PLL_CTRL2 0x8 |
34 | #define PLL_FRAC_CTRL2_FRAC_SHIFT 0 |
35 | #define PLL_FRAC_CTRL2_FRAC_MASK 0xffffff |
36 | #define PLL_FRAC_CTRL2_POSTDIV1_SHIFT 24 |
37 | #define PLL_FRAC_CTRL2_POSTDIV1_MASK 0x7 |
38 | #define PLL_FRAC_CTRL2_POSTDIV2_SHIFT 27 |
39 | #define PLL_FRAC_CTRL2_POSTDIV2_MASK 0x7 |
40 | #define PLL_INT_CTRL2_BYPASS BIT(28) |
41 | |
42 | #define PLL_CTRL3 0xc |
43 | #define PLL_FRAC_CTRL3_PD BIT(0) |
44 | #define PLL_FRAC_CTRL3_DACPD BIT(1) |
45 | #define PLL_FRAC_CTRL3_DSMPD BIT(2) |
46 | #define PLL_FRAC_CTRL3_FOUTPOSTDIVPD BIT(3) |
47 | #define PLL_FRAC_CTRL3_FOUT4PHASEPD BIT(4) |
48 | #define PLL_FRAC_CTRL3_FOUTVCOPD BIT(5) |
49 | |
50 | #define PLL_CTRL4 0x10 |
51 | #define PLL_FRAC_CTRL4_BYPASS BIT(28) |
52 | |
53 | #define MIN_PFD 9600000UL |
54 | #define MIN_VCO_LA 400000000UL |
55 | #define MAX_VCO_LA 1600000000UL |
56 | #define MIN_VCO_FRAC_INT 600000000UL |
57 | #define MAX_VCO_FRAC_INT 1600000000UL |
58 | #define MIN_VCO_FRAC_FRAC 600000000UL |
59 | #define MAX_VCO_FRAC_FRAC 2400000000UL |
60 | #define MIN_OUTPUT_LA 8000000UL |
61 | #define MAX_OUTPUT_LA 1600000000UL |
62 | #define MIN_OUTPUT_FRAC 12000000UL |
63 | #define MAX_OUTPUT_FRAC 1600000000UL |
64 | |
65 | /* Fractional PLL operating modes */ |
66 | enum pll_mode { |
67 | PLL_MODE_FRAC, |
68 | PLL_MODE_INT, |
69 | }; |
70 | |
71 | struct pistachio_clk_pll { |
72 | struct clk_hw hw; |
73 | void __iomem *base; |
74 | struct pistachio_pll_rate_table *rates; |
75 | unsigned int nr_rates; |
76 | }; |
77 | |
78 | static inline u32 pll_readl(struct pistachio_clk_pll *pll, u32 reg) |
79 | { |
80 | return readl(addr: pll->base + reg); |
81 | } |
82 | |
83 | static inline void pll_writel(struct pistachio_clk_pll *pll, u32 val, u32 reg) |
84 | { |
85 | writel(val, addr: pll->base + reg); |
86 | } |
87 | |
88 | static inline void pll_lock(struct pistachio_clk_pll *pll) |
89 | { |
90 | while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK)) |
91 | cpu_relax(); |
92 | } |
93 | |
94 | static inline u64 do_div_round_closest(u64 dividend, u64 divisor) |
95 | { |
96 | dividend += divisor / 2; |
97 | return div64_u64(dividend, divisor); |
98 | } |
99 | |
100 | static inline struct pistachio_clk_pll *to_pistachio_pll(struct clk_hw *hw) |
101 | { |
102 | return container_of(hw, struct pistachio_clk_pll, hw); |
103 | } |
104 | |
105 | static inline enum pll_mode pll_frac_get_mode(struct clk_hw *hw) |
106 | { |
107 | struct pistachio_clk_pll *pll = to_pistachio_pll(hw); |
108 | u32 val; |
109 | |
110 | val = pll_readl(pll, PLL_CTRL3) & PLL_FRAC_CTRL3_DSMPD; |
111 | return val ? PLL_MODE_INT : PLL_MODE_FRAC; |
112 | } |
113 | |
114 | static inline void pll_frac_set_mode(struct clk_hw *hw, enum pll_mode mode) |
115 | { |
116 | struct pistachio_clk_pll *pll = to_pistachio_pll(hw); |
117 | u32 val; |
118 | |
119 | val = pll_readl(pll, PLL_CTRL3); |
120 | if (mode == PLL_MODE_INT) |
121 | val |= PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_DACPD; |
122 | else |
123 | val &= ~(PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_DACPD); |
124 | |
125 | pll_writel(pll, val, PLL_CTRL3); |
126 | } |
127 | |
128 | static struct pistachio_pll_rate_table * |
129 | pll_get_params(struct pistachio_clk_pll *pll, unsigned long fref, |
130 | unsigned long fout) |
131 | { |
132 | unsigned int i; |
133 | |
134 | for (i = 0; i < pll->nr_rates; i++) { |
135 | if (pll->rates[i].fref == fref && pll->rates[i].fout == fout) |
136 | return &pll->rates[i]; |
137 | } |
138 | |
139 | return NULL; |
140 | } |
141 | |
142 | static long pll_round_rate(struct clk_hw *hw, unsigned long rate, |
143 | unsigned long *parent_rate) |
144 | { |
145 | struct pistachio_clk_pll *pll = to_pistachio_pll(hw); |
146 | unsigned int i; |
147 | |
148 | for (i = 0; i < pll->nr_rates; i++) { |
149 | if (i > 0 && pll->rates[i].fref == *parent_rate && |
150 | pll->rates[i].fout <= rate) |
151 | return pll->rates[i - 1].fout; |
152 | } |
153 | |
154 | return pll->rates[0].fout; |
155 | } |
156 | |
157 | static int pll_gf40lp_frac_enable(struct clk_hw *hw) |
158 | { |
159 | struct pistachio_clk_pll *pll = to_pistachio_pll(hw); |
160 | u32 val; |
161 | |
162 | val = pll_readl(pll, PLL_CTRL3); |
163 | val &= ~(PLL_FRAC_CTRL3_PD | PLL_FRAC_CTRL3_FOUTPOSTDIVPD | |
164 | PLL_FRAC_CTRL3_FOUT4PHASEPD | PLL_FRAC_CTRL3_FOUTVCOPD); |
165 | pll_writel(pll, val, PLL_CTRL3); |
166 | |
167 | val = pll_readl(pll, PLL_CTRL4); |
168 | val &= ~PLL_FRAC_CTRL4_BYPASS; |
169 | pll_writel(pll, val, PLL_CTRL4); |
170 | |
171 | pll_lock(pll); |
172 | |
173 | return 0; |
174 | } |
175 | |
176 | static void pll_gf40lp_frac_disable(struct clk_hw *hw) |
177 | { |
178 | struct pistachio_clk_pll *pll = to_pistachio_pll(hw); |
179 | u32 val; |
180 | |
181 | val = pll_readl(pll, PLL_CTRL3); |
182 | val |= PLL_FRAC_CTRL3_PD; |
183 | pll_writel(pll, val, PLL_CTRL3); |
184 | } |
185 | |
186 | static int pll_gf40lp_frac_is_enabled(struct clk_hw *hw) |
187 | { |
188 | struct pistachio_clk_pll *pll = to_pistachio_pll(hw); |
189 | |
190 | return !(pll_readl(pll, PLL_CTRL3) & PLL_FRAC_CTRL3_PD); |
191 | } |
192 | |
193 | static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate, |
194 | unsigned long parent_rate) |
195 | { |
196 | struct pistachio_clk_pll *pll = to_pistachio_pll(hw); |
197 | struct pistachio_pll_rate_table *params; |
198 | int enabled = pll_gf40lp_frac_is_enabled(hw); |
199 | u64 val, vco, old_postdiv1, old_postdiv2; |
200 | const char *name = clk_hw_get_name(hw); |
201 | |
202 | if (rate < MIN_OUTPUT_FRAC || rate > MAX_OUTPUT_FRAC) |
203 | return -EINVAL; |
204 | |
205 | params = pll_get_params(pll, fref: parent_rate, fout: rate); |
206 | if (!params || !params->refdiv) |
207 | return -EINVAL; |
208 | |
209 | /* calculate vco */ |
210 | vco = params->fref; |
211 | vco *= (params->fbdiv << 24) + params->frac; |
212 | vco = div64_u64(dividend: vco, divisor: params->refdiv << 24); |
213 | |
214 | if (vco < MIN_VCO_FRAC_FRAC || vco > MAX_VCO_FRAC_FRAC) |
215 | pr_warn("%s: VCO %llu is out of range %lu..%lu\n" , name, vco, |
216 | MIN_VCO_FRAC_FRAC, MAX_VCO_FRAC_FRAC); |
217 | |
218 | val = div64_u64(dividend: params->fref, divisor: params->refdiv); |
219 | if (val < MIN_PFD) |
220 | pr_warn("%s: PFD %llu is too low (min %lu)\n" , |
221 | name, val, MIN_PFD); |
222 | if (val > vco / 16) |
223 | pr_warn("%s: PFD %llu is too high (max %llu)\n" , |
224 | name, val, vco / 16); |
225 | |
226 | val = pll_readl(pll, PLL_CTRL1); |
227 | val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) | |
228 | (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT)); |
229 | val |= (params->refdiv << PLL_CTRL1_REFDIV_SHIFT) | |
230 | (params->fbdiv << PLL_CTRL1_FBDIV_SHIFT); |
231 | pll_writel(pll, val, PLL_CTRL1); |
232 | |
233 | val = pll_readl(pll, PLL_CTRL2); |
234 | |
235 | old_postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) & |
236 | PLL_FRAC_CTRL2_POSTDIV1_MASK; |
237 | old_postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) & |
238 | PLL_FRAC_CTRL2_POSTDIV2_MASK; |
239 | if (enabled && |
240 | (params->postdiv1 != old_postdiv1 || |
241 | params->postdiv2 != old_postdiv2)) |
242 | pr_warn("%s: changing postdiv while PLL is enabled\n" , name); |
243 | |
244 | if (params->postdiv2 > params->postdiv1) |
245 | pr_warn("%s: postdiv2 should not exceed postdiv1\n" , name); |
246 | |
247 | val &= ~((PLL_FRAC_CTRL2_FRAC_MASK << PLL_FRAC_CTRL2_FRAC_SHIFT) | |
248 | (PLL_FRAC_CTRL2_POSTDIV1_MASK << |
249 | PLL_FRAC_CTRL2_POSTDIV1_SHIFT) | |
250 | (PLL_FRAC_CTRL2_POSTDIV2_MASK << |
251 | PLL_FRAC_CTRL2_POSTDIV2_SHIFT)); |
252 | val |= (params->frac << PLL_FRAC_CTRL2_FRAC_SHIFT) | |
253 | (params->postdiv1 << PLL_FRAC_CTRL2_POSTDIV1_SHIFT) | |
254 | (params->postdiv2 << PLL_FRAC_CTRL2_POSTDIV2_SHIFT); |
255 | pll_writel(pll, val, PLL_CTRL2); |
256 | |
257 | /* set operating mode */ |
258 | if (params->frac) |
259 | pll_frac_set_mode(hw, mode: PLL_MODE_FRAC); |
260 | else |
261 | pll_frac_set_mode(hw, mode: PLL_MODE_INT); |
262 | |
263 | if (enabled) |
264 | pll_lock(pll); |
265 | |
266 | return 0; |
267 | } |
268 | |
269 | static unsigned long pll_gf40lp_frac_recalc_rate(struct clk_hw *hw, |
270 | unsigned long parent_rate) |
271 | { |
272 | struct pistachio_clk_pll *pll = to_pistachio_pll(hw); |
273 | u64 val, prediv, fbdiv, frac, postdiv1, postdiv2, rate; |
274 | |
275 | val = pll_readl(pll, PLL_CTRL1); |
276 | prediv = (val >> PLL_CTRL1_REFDIV_SHIFT) & PLL_CTRL1_REFDIV_MASK; |
277 | fbdiv = (val >> PLL_CTRL1_FBDIV_SHIFT) & PLL_CTRL1_FBDIV_MASK; |
278 | |
279 | val = pll_readl(pll, PLL_CTRL2); |
280 | postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) & |
281 | PLL_FRAC_CTRL2_POSTDIV1_MASK; |
282 | postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) & |
283 | PLL_FRAC_CTRL2_POSTDIV2_MASK; |
284 | frac = (val >> PLL_FRAC_CTRL2_FRAC_SHIFT) & PLL_FRAC_CTRL2_FRAC_MASK; |
285 | |
286 | /* get operating mode (int/frac) and calculate rate accordingly */ |
287 | rate = parent_rate; |
288 | if (pll_frac_get_mode(hw) == PLL_MODE_FRAC) |
289 | rate *= (fbdiv << 24) + frac; |
290 | else |
291 | rate *= (fbdiv << 24); |
292 | |
293 | rate = do_div_round_closest(dividend: rate, divisor: (prediv * postdiv1 * postdiv2) << 24); |
294 | |
295 | return rate; |
296 | } |
297 | |
298 | static const struct clk_ops pll_gf40lp_frac_ops = { |
299 | .enable = pll_gf40lp_frac_enable, |
300 | .disable = pll_gf40lp_frac_disable, |
301 | .is_enabled = pll_gf40lp_frac_is_enabled, |
302 | .recalc_rate = pll_gf40lp_frac_recalc_rate, |
303 | .round_rate = pll_round_rate, |
304 | .set_rate = pll_gf40lp_frac_set_rate, |
305 | }; |
306 | |
307 | static const struct clk_ops pll_gf40lp_frac_fixed_ops = { |
308 | .enable = pll_gf40lp_frac_enable, |
309 | .disable = pll_gf40lp_frac_disable, |
310 | .is_enabled = pll_gf40lp_frac_is_enabled, |
311 | .recalc_rate = pll_gf40lp_frac_recalc_rate, |
312 | }; |
313 | |
314 | static int pll_gf40lp_laint_enable(struct clk_hw *hw) |
315 | { |
316 | struct pistachio_clk_pll *pll = to_pistachio_pll(hw); |
317 | u32 val; |
318 | |
319 | val = pll_readl(pll, PLL_CTRL1); |
320 | val &= ~(PLL_INT_CTRL1_PD | |
321 | PLL_INT_CTRL1_FOUTPOSTDIVPD | PLL_INT_CTRL1_FOUTVCOPD); |
322 | pll_writel(pll, val, PLL_CTRL1); |
323 | |
324 | val = pll_readl(pll, PLL_CTRL2); |
325 | val &= ~PLL_INT_CTRL2_BYPASS; |
326 | pll_writel(pll, val, PLL_CTRL2); |
327 | |
328 | pll_lock(pll); |
329 | |
330 | return 0; |
331 | } |
332 | |
333 | static void pll_gf40lp_laint_disable(struct clk_hw *hw) |
334 | { |
335 | struct pistachio_clk_pll *pll = to_pistachio_pll(hw); |
336 | u32 val; |
337 | |
338 | val = pll_readl(pll, PLL_CTRL1); |
339 | val |= PLL_INT_CTRL1_PD; |
340 | pll_writel(pll, val, PLL_CTRL1); |
341 | } |
342 | |
343 | static int pll_gf40lp_laint_is_enabled(struct clk_hw *hw) |
344 | { |
345 | struct pistachio_clk_pll *pll = to_pistachio_pll(hw); |
346 | |
347 | return !(pll_readl(pll, PLL_CTRL1) & PLL_INT_CTRL1_PD); |
348 | } |
349 | |
350 | static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate, |
351 | unsigned long parent_rate) |
352 | { |
353 | struct pistachio_clk_pll *pll = to_pistachio_pll(hw); |
354 | struct pistachio_pll_rate_table *params; |
355 | int enabled = pll_gf40lp_laint_is_enabled(hw); |
356 | u32 val, vco, old_postdiv1, old_postdiv2; |
357 | const char *name = clk_hw_get_name(hw); |
358 | |
359 | if (rate < MIN_OUTPUT_LA || rate > MAX_OUTPUT_LA) |
360 | return -EINVAL; |
361 | |
362 | params = pll_get_params(pll, fref: parent_rate, fout: rate); |
363 | if (!params || !params->refdiv) |
364 | return -EINVAL; |
365 | |
366 | vco = div_u64(dividend: params->fref * params->fbdiv, divisor: params->refdiv); |
367 | if (vco < MIN_VCO_LA || vco > MAX_VCO_LA) |
368 | pr_warn("%s: VCO %u is out of range %lu..%lu\n" , name, vco, |
369 | MIN_VCO_LA, MAX_VCO_LA); |
370 | |
371 | val = div_u64(dividend: params->fref, divisor: params->refdiv); |
372 | if (val < MIN_PFD) |
373 | pr_warn("%s: PFD %u is too low (min %lu)\n" , |
374 | name, val, MIN_PFD); |
375 | if (val > vco / 16) |
376 | pr_warn("%s: PFD %u is too high (max %u)\n" , |
377 | name, val, vco / 16); |
378 | |
379 | val = pll_readl(pll, PLL_CTRL1); |
380 | |
381 | old_postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) & |
382 | PLL_INT_CTRL1_POSTDIV1_MASK; |
383 | old_postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) & |
384 | PLL_INT_CTRL1_POSTDIV2_MASK; |
385 | if (enabled && |
386 | (params->postdiv1 != old_postdiv1 || |
387 | params->postdiv2 != old_postdiv2)) |
388 | pr_warn("%s: changing postdiv while PLL is enabled\n" , name); |
389 | |
390 | if (params->postdiv2 > params->postdiv1) |
391 | pr_warn("%s: postdiv2 should not exceed postdiv1\n" , name); |
392 | |
393 | val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) | |
394 | (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT) | |
395 | (PLL_INT_CTRL1_POSTDIV1_MASK << PLL_INT_CTRL1_POSTDIV1_SHIFT) | |
396 | (PLL_INT_CTRL1_POSTDIV2_MASK << PLL_INT_CTRL1_POSTDIV2_SHIFT)); |
397 | val |= (params->refdiv << PLL_CTRL1_REFDIV_SHIFT) | |
398 | (params->fbdiv << PLL_CTRL1_FBDIV_SHIFT) | |
399 | (params->postdiv1 << PLL_INT_CTRL1_POSTDIV1_SHIFT) | |
400 | (params->postdiv2 << PLL_INT_CTRL1_POSTDIV2_SHIFT); |
401 | pll_writel(pll, val, PLL_CTRL1); |
402 | |
403 | if (enabled) |
404 | pll_lock(pll); |
405 | |
406 | return 0; |
407 | } |
408 | |
409 | static unsigned long pll_gf40lp_laint_recalc_rate(struct clk_hw *hw, |
410 | unsigned long parent_rate) |
411 | { |
412 | struct pistachio_clk_pll *pll = to_pistachio_pll(hw); |
413 | u32 val, prediv, fbdiv, postdiv1, postdiv2; |
414 | u64 rate = parent_rate; |
415 | |
416 | val = pll_readl(pll, PLL_CTRL1); |
417 | prediv = (val >> PLL_CTRL1_REFDIV_SHIFT) & PLL_CTRL1_REFDIV_MASK; |
418 | fbdiv = (val >> PLL_CTRL1_FBDIV_SHIFT) & PLL_CTRL1_FBDIV_MASK; |
419 | postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) & |
420 | PLL_INT_CTRL1_POSTDIV1_MASK; |
421 | postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) & |
422 | PLL_INT_CTRL1_POSTDIV2_MASK; |
423 | |
424 | rate *= fbdiv; |
425 | rate = do_div_round_closest(dividend: rate, divisor: prediv * postdiv1 * postdiv2); |
426 | |
427 | return rate; |
428 | } |
429 | |
430 | static const struct clk_ops pll_gf40lp_laint_ops = { |
431 | .enable = pll_gf40lp_laint_enable, |
432 | .disable = pll_gf40lp_laint_disable, |
433 | .is_enabled = pll_gf40lp_laint_is_enabled, |
434 | .recalc_rate = pll_gf40lp_laint_recalc_rate, |
435 | .round_rate = pll_round_rate, |
436 | .set_rate = pll_gf40lp_laint_set_rate, |
437 | }; |
438 | |
439 | static const struct clk_ops pll_gf40lp_laint_fixed_ops = { |
440 | .enable = pll_gf40lp_laint_enable, |
441 | .disable = pll_gf40lp_laint_disable, |
442 | .is_enabled = pll_gf40lp_laint_is_enabled, |
443 | .recalc_rate = pll_gf40lp_laint_recalc_rate, |
444 | }; |
445 | |
446 | static struct clk *pll_register(const char *name, const char *parent_name, |
447 | unsigned long flags, void __iomem *base, |
448 | enum pistachio_pll_type type, |
449 | struct pistachio_pll_rate_table *rates, |
450 | unsigned int nr_rates) |
451 | { |
452 | struct pistachio_clk_pll *pll; |
453 | struct clk_init_data init; |
454 | struct clk *clk; |
455 | |
456 | pll = kzalloc(size: sizeof(*pll), GFP_KERNEL); |
457 | if (!pll) |
458 | return ERR_PTR(error: -ENOMEM); |
459 | |
460 | init.name = name; |
461 | init.flags = flags | CLK_GET_RATE_NOCACHE; |
462 | init.parent_names = &parent_name; |
463 | init.num_parents = 1; |
464 | |
465 | switch (type) { |
466 | case PLL_GF40LP_FRAC: |
467 | if (rates) |
468 | init.ops = &pll_gf40lp_frac_ops; |
469 | else |
470 | init.ops = &pll_gf40lp_frac_fixed_ops; |
471 | break; |
472 | case PLL_GF40LP_LAINT: |
473 | if (rates) |
474 | init.ops = &pll_gf40lp_laint_ops; |
475 | else |
476 | init.ops = &pll_gf40lp_laint_fixed_ops; |
477 | break; |
478 | default: |
479 | pr_err("Unrecognized PLL type %u\n" , type); |
480 | kfree(objp: pll); |
481 | return ERR_PTR(error: -EINVAL); |
482 | } |
483 | |
484 | pll->hw.init = &init; |
485 | pll->base = base; |
486 | pll->rates = rates; |
487 | pll->nr_rates = nr_rates; |
488 | |
489 | clk = clk_register(NULL, hw: &pll->hw); |
490 | if (IS_ERR(ptr: clk)) |
491 | kfree(objp: pll); |
492 | |
493 | return clk; |
494 | } |
495 | |
496 | void pistachio_clk_register_pll(struct pistachio_clk_provider *p, |
497 | struct pistachio_pll *pll, |
498 | unsigned int num) |
499 | { |
500 | struct clk *clk; |
501 | unsigned int i; |
502 | |
503 | for (i = 0; i < num; i++) { |
504 | clk = pll_register(name: pll[i].name, parent_name: pll[i].parent, |
505 | flags: 0, base: p->base + pll[i].reg_base, |
506 | type: pll[i].type, rates: pll[i].rates, |
507 | nr_rates: pll[i].nr_rates); |
508 | p->clk_data.clks[pll[i].id] = clk; |
509 | } |
510 | } |
511 | |