1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (C) 2016 Atmel Corporation, |
4 | * Songjun Wu <songjun.wu@atmel.com>, |
5 | * Nicolas Ferre <nicolas.ferre@atmel.com> |
6 | * Copyright (C) 2017 Free Electrons, |
7 | * Quentin Schulz <quentin.schulz@free-electrons.com> |
8 | * |
9 | * The Sama5d2 SoC has two audio PLLs (PMC and PAD) that shares the same parent |
10 | * (FRAC). FRAC can output between 620 and 700MHz and only multiply the rate of |
11 | * its own parent. PMC and PAD can then divide the FRAC rate to best match the |
12 | * asked rate. |
13 | * |
14 | * Traits of FRAC clock: |
15 | * enable - clk_enable writes nd, fracr parameters and enables PLL |
16 | * rate - rate is adjustable. |
17 | * clk->rate = parent->rate * ((nd + 1) + (fracr / 2^22)) |
18 | * parent - fixed parent. No clk_set_parent support |
19 | * |
20 | * Traits of PMC clock: |
21 | * enable - clk_enable writes qdpmc, and enables PMC output |
22 | * rate - rate is adjustable. |
23 | * clk->rate = parent->rate / (qdpmc + 1) |
24 | * parent - fixed parent. No clk_set_parent support |
25 | * |
26 | * Traits of PAD clock: |
27 | * enable - clk_enable writes divisors and enables PAD output |
28 | * rate - rate is adjustable. |
29 | * clk->rate = parent->rate / (qdaudio * div)) |
30 | * parent - fixed parent. No clk_set_parent support |
31 | */ |
32 | |
33 | #include <linux/clk.h> |
34 | #include <linux/clk-provider.h> |
35 | #include <linux/clk/at91_pmc.h> |
36 | #include <linux/of.h> |
37 | #include <linux/mfd/syscon.h> |
38 | #include <linux/regmap.h> |
39 | #include <linux/slab.h> |
40 | |
41 | #include "pmc.h" |
42 | |
43 | #define AUDIO_PLL_DIV_FRAC BIT(22) |
44 | #define AUDIO_PLL_ND_MAX (AT91_PMC_AUDIO_PLL_ND_MASK >> \ |
45 | AT91_PMC_AUDIO_PLL_ND_OFFSET) |
46 | |
47 | #define AUDIO_PLL_QDPAD(qd, div) ((AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV(qd) & \ |
48 | AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK) | \ |
49 | (AT91_PMC_AUDIO_PLL_QDPAD_DIV(div) & \ |
50 | AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK)) |
51 | |
52 | #define AUDIO_PLL_QDPMC_MAX (AT91_PMC_AUDIO_PLL_QDPMC_MASK >> \ |
53 | AT91_PMC_AUDIO_PLL_QDPMC_OFFSET) |
54 | |
55 | #define AUDIO_PLL_FOUT_MIN 620000000UL |
56 | #define AUDIO_PLL_FOUT_MAX 700000000UL |
57 | |
58 | struct clk_audio_frac { |
59 | struct clk_hw hw; |
60 | struct regmap *regmap; |
61 | u32 fracr; |
62 | u8 nd; |
63 | }; |
64 | |
65 | struct clk_audio_pad { |
66 | struct clk_hw hw; |
67 | struct regmap *regmap; |
68 | u8 qdaudio; |
69 | u8 div; |
70 | }; |
71 | |
72 | struct clk_audio_pmc { |
73 | struct clk_hw hw; |
74 | struct regmap *regmap; |
75 | u8 qdpmc; |
76 | }; |
77 | |
78 | #define to_clk_audio_frac(hw) container_of(hw, struct clk_audio_frac, hw) |
79 | #define to_clk_audio_pad(hw) container_of(hw, struct clk_audio_pad, hw) |
80 | #define to_clk_audio_pmc(hw) container_of(hw, struct clk_audio_pmc, hw) |
81 | |
82 | static int clk_audio_pll_frac_enable(struct clk_hw *hw) |
83 | { |
84 | struct clk_audio_frac *frac = to_clk_audio_frac(hw); |
85 | |
86 | regmap_update_bits(map: frac->regmap, AT91_PMC_AUDIO_PLL0, |
87 | AT91_PMC_AUDIO_PLL_RESETN, val: 0); |
88 | regmap_update_bits(map: frac->regmap, AT91_PMC_AUDIO_PLL0, |
89 | AT91_PMC_AUDIO_PLL_RESETN, |
90 | AT91_PMC_AUDIO_PLL_RESETN); |
91 | regmap_update_bits(map: frac->regmap, AT91_PMC_AUDIO_PLL1, |
92 | AT91_PMC_AUDIO_PLL_FRACR_MASK, val: frac->fracr); |
93 | |
94 | /* |
95 | * reset and enable have to be done in 2 separated writes |
96 | * for AT91_PMC_AUDIO_PLL0 |
97 | */ |
98 | regmap_update_bits(map: frac->regmap, AT91_PMC_AUDIO_PLL0, |
99 | AT91_PMC_AUDIO_PLL_PLLEN | |
100 | AT91_PMC_AUDIO_PLL_ND_MASK, |
101 | AT91_PMC_AUDIO_PLL_PLLEN | |
102 | AT91_PMC_AUDIO_PLL_ND(frac->nd)); |
103 | |
104 | return 0; |
105 | } |
106 | |
107 | static int clk_audio_pll_pad_enable(struct clk_hw *hw) |
108 | { |
109 | struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); |
110 | |
111 | regmap_update_bits(map: apad_ck->regmap, AT91_PMC_AUDIO_PLL1, |
112 | AT91_PMC_AUDIO_PLL_QDPAD_MASK, |
113 | AUDIO_PLL_QDPAD(apad_ck->qdaudio, apad_ck->div)); |
114 | regmap_update_bits(map: apad_ck->regmap, AT91_PMC_AUDIO_PLL0, |
115 | AT91_PMC_AUDIO_PLL_PADEN, AT91_PMC_AUDIO_PLL_PADEN); |
116 | |
117 | return 0; |
118 | } |
119 | |
120 | static int clk_audio_pll_pmc_enable(struct clk_hw *hw) |
121 | { |
122 | struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); |
123 | |
124 | regmap_update_bits(map: apmc_ck->regmap, AT91_PMC_AUDIO_PLL0, |
125 | AT91_PMC_AUDIO_PLL_PMCEN | |
126 | AT91_PMC_AUDIO_PLL_QDPMC_MASK, |
127 | AT91_PMC_AUDIO_PLL_PMCEN | |
128 | AT91_PMC_AUDIO_PLL_QDPMC(apmc_ck->qdpmc)); |
129 | return 0; |
130 | } |
131 | |
132 | static void clk_audio_pll_frac_disable(struct clk_hw *hw) |
133 | { |
134 | struct clk_audio_frac *frac = to_clk_audio_frac(hw); |
135 | |
136 | regmap_update_bits(map: frac->regmap, AT91_PMC_AUDIO_PLL0, |
137 | AT91_PMC_AUDIO_PLL_PLLEN, val: 0); |
138 | /* do it in 2 separated writes */ |
139 | regmap_update_bits(map: frac->regmap, AT91_PMC_AUDIO_PLL0, |
140 | AT91_PMC_AUDIO_PLL_RESETN, val: 0); |
141 | } |
142 | |
143 | static void clk_audio_pll_pad_disable(struct clk_hw *hw) |
144 | { |
145 | struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); |
146 | |
147 | regmap_update_bits(map: apad_ck->regmap, AT91_PMC_AUDIO_PLL0, |
148 | AT91_PMC_AUDIO_PLL_PADEN, val: 0); |
149 | } |
150 | |
151 | static void clk_audio_pll_pmc_disable(struct clk_hw *hw) |
152 | { |
153 | struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); |
154 | |
155 | regmap_update_bits(map: apmc_ck->regmap, AT91_PMC_AUDIO_PLL0, |
156 | AT91_PMC_AUDIO_PLL_PMCEN, val: 0); |
157 | } |
158 | |
159 | static unsigned long clk_audio_pll_fout(unsigned long parent_rate, |
160 | unsigned long nd, unsigned long fracr) |
161 | { |
162 | unsigned long long fr = (unsigned long long)parent_rate * fracr; |
163 | |
164 | pr_debug("A PLL: %s, fr = %llu\n" , __func__, fr); |
165 | |
166 | fr = DIV_ROUND_CLOSEST_ULL(fr, AUDIO_PLL_DIV_FRAC); |
167 | |
168 | pr_debug("A PLL: %s, fr = %llu\n" , __func__, fr); |
169 | |
170 | return parent_rate * (nd + 1) + fr; |
171 | } |
172 | |
173 | static unsigned long clk_audio_pll_frac_recalc_rate(struct clk_hw *hw, |
174 | unsigned long parent_rate) |
175 | { |
176 | struct clk_audio_frac *frac = to_clk_audio_frac(hw); |
177 | unsigned long fout; |
178 | |
179 | fout = clk_audio_pll_fout(parent_rate, nd: frac->nd, fracr: frac->fracr); |
180 | |
181 | pr_debug("A PLL: %s, fout = %lu (nd = %u, fracr = %lu)\n" , __func__, |
182 | fout, frac->nd, (unsigned long)frac->fracr); |
183 | |
184 | return fout; |
185 | } |
186 | |
187 | static unsigned long clk_audio_pll_pad_recalc_rate(struct clk_hw *hw, |
188 | unsigned long parent_rate) |
189 | { |
190 | struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); |
191 | unsigned long apad_rate = 0; |
192 | |
193 | if (apad_ck->qdaudio && apad_ck->div) |
194 | apad_rate = parent_rate / (apad_ck->qdaudio * apad_ck->div); |
195 | |
196 | pr_debug("A PLL/PAD: %s, apad_rate = %lu (div = %u, qdaudio = %u)\n" , |
197 | __func__, apad_rate, apad_ck->div, apad_ck->qdaudio); |
198 | |
199 | return apad_rate; |
200 | } |
201 | |
202 | static unsigned long clk_audio_pll_pmc_recalc_rate(struct clk_hw *hw, |
203 | unsigned long parent_rate) |
204 | { |
205 | struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); |
206 | unsigned long apmc_rate = 0; |
207 | |
208 | apmc_rate = parent_rate / (apmc_ck->qdpmc + 1); |
209 | |
210 | pr_debug("A PLL/PMC: %s, apmc_rate = %lu (qdpmc = %u)\n" , __func__, |
211 | apmc_rate, apmc_ck->qdpmc); |
212 | |
213 | return apmc_rate; |
214 | } |
215 | |
216 | static int clk_audio_pll_frac_compute_frac(unsigned long rate, |
217 | unsigned long parent_rate, |
218 | unsigned long *nd, |
219 | unsigned long *fracr) |
220 | { |
221 | unsigned long long tmp, rem; |
222 | |
223 | if (!rate) |
224 | return -EINVAL; |
225 | |
226 | tmp = rate; |
227 | rem = do_div(tmp, parent_rate); |
228 | if (!tmp || tmp >= AUDIO_PLL_ND_MAX) |
229 | return -EINVAL; |
230 | |
231 | *nd = tmp - 1; |
232 | |
233 | tmp = rem * AUDIO_PLL_DIV_FRAC; |
234 | tmp = DIV_ROUND_CLOSEST_ULL(tmp, parent_rate); |
235 | if (tmp > AT91_PMC_AUDIO_PLL_FRACR_MASK) |
236 | return -EINVAL; |
237 | |
238 | /* we can cast here as we verified the bounds just above */ |
239 | *fracr = (unsigned long)tmp; |
240 | |
241 | return 0; |
242 | } |
243 | |
244 | static int clk_audio_pll_frac_determine_rate(struct clk_hw *hw, |
245 | struct clk_rate_request *req) |
246 | { |
247 | unsigned long fracr, nd; |
248 | int ret; |
249 | |
250 | pr_debug("A PLL: %s, rate = %lu (parent_rate = %lu)\n" , __func__, |
251 | req->rate, req->best_parent_rate); |
252 | |
253 | req->rate = clamp(req->rate, AUDIO_PLL_FOUT_MIN, AUDIO_PLL_FOUT_MAX); |
254 | |
255 | req->min_rate = max(req->min_rate, AUDIO_PLL_FOUT_MIN); |
256 | req->max_rate = min(req->max_rate, AUDIO_PLL_FOUT_MAX); |
257 | |
258 | ret = clk_audio_pll_frac_compute_frac(rate: req->rate, parent_rate: req->best_parent_rate, |
259 | nd: &nd, fracr: &fracr); |
260 | if (ret) |
261 | return ret; |
262 | |
263 | req->rate = clk_audio_pll_fout(parent_rate: req->best_parent_rate, nd, fracr); |
264 | |
265 | req->best_parent_hw = clk_hw_get_parent(hw); |
266 | |
267 | pr_debug("A PLL: %s, best_rate = %lu (nd = %lu, fracr = %lu)\n" , |
268 | __func__, req->rate, nd, fracr); |
269 | |
270 | return 0; |
271 | } |
272 | |
273 | static long clk_audio_pll_pad_round_rate(struct clk_hw *hw, unsigned long rate, |
274 | unsigned long *parent_rate) |
275 | { |
276 | struct clk_hw *pclk = clk_hw_get_parent(hw); |
277 | long best_rate = -EINVAL; |
278 | unsigned long best_parent_rate; |
279 | unsigned long tmp_qd; |
280 | u32 div; |
281 | long tmp_rate; |
282 | int tmp_diff; |
283 | int best_diff = -1; |
284 | |
285 | pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n" , __func__, |
286 | rate, *parent_rate); |
287 | |
288 | /* |
289 | * Rate divisor is actually made of two different divisors, multiplied |
290 | * between themselves before dividing the rate. |
291 | * tmp_qd goes from 1 to 31 and div is either 2 or 3. |
292 | * In order to avoid testing twice the rate divisor (e.g. divisor 12 can |
293 | * be found with (tmp_qd, div) = (2, 6) or (3, 4)), we remove any loop |
294 | * for a rate divisor when div is 2 and tmp_qd is a multiple of 3. |
295 | * We cannot inverse it (condition div is 3 and tmp_qd is even) or we |
296 | * would miss some rate divisor that aren't reachable with div being 2 |
297 | * (e.g. rate divisor 90 is made with div = 3 and tmp_qd = 30, thus |
298 | * tmp_qd is even so we skip it because we think div 2 could make this |
299 | * rate divisor which isn't possible since tmp_qd has to be <= 31). |
300 | */ |
301 | for (tmp_qd = 1; tmp_qd < AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX; tmp_qd++) |
302 | for (div = 2; div <= 3; div++) { |
303 | if (div == 2 && tmp_qd % 3 == 0) |
304 | continue; |
305 | |
306 | best_parent_rate = clk_hw_round_rate(hw: pclk, |
307 | rate: rate * tmp_qd * div); |
308 | tmp_rate = best_parent_rate / (div * tmp_qd); |
309 | tmp_diff = abs(rate - tmp_rate); |
310 | |
311 | if (best_diff < 0 || best_diff > tmp_diff) { |
312 | *parent_rate = best_parent_rate; |
313 | best_rate = tmp_rate; |
314 | best_diff = tmp_diff; |
315 | } |
316 | } |
317 | |
318 | pr_debug("A PLL/PAD: %s, best_rate = %ld, best_parent_rate = %lu\n" , |
319 | __func__, best_rate, best_parent_rate); |
320 | |
321 | return best_rate; |
322 | } |
323 | |
324 | static long clk_audio_pll_pmc_round_rate(struct clk_hw *hw, unsigned long rate, |
325 | unsigned long *parent_rate) |
326 | { |
327 | struct clk_hw *pclk = clk_hw_get_parent(hw); |
328 | long best_rate = -EINVAL; |
329 | unsigned long best_parent_rate = 0; |
330 | u32 tmp_qd = 0, div; |
331 | long tmp_rate; |
332 | int tmp_diff; |
333 | int best_diff = -1; |
334 | |
335 | pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n" , __func__, |
336 | rate, *parent_rate); |
337 | |
338 | if (!rate) |
339 | return 0; |
340 | |
341 | best_parent_rate = clk_round_rate(clk: pclk->clk, rate: 1); |
342 | div = max(best_parent_rate / rate, 1UL); |
343 | for (; div <= AUDIO_PLL_QDPMC_MAX; div++) { |
344 | best_parent_rate = clk_round_rate(clk: pclk->clk, rate: rate * div); |
345 | tmp_rate = best_parent_rate / div; |
346 | tmp_diff = abs(rate - tmp_rate); |
347 | |
348 | if (best_diff < 0 || best_diff > tmp_diff) { |
349 | *parent_rate = best_parent_rate; |
350 | best_rate = tmp_rate; |
351 | best_diff = tmp_diff; |
352 | tmp_qd = div; |
353 | if (!best_diff) |
354 | break; /* got exact match */ |
355 | } |
356 | } |
357 | |
358 | pr_debug("A PLL/PMC: %s, best_rate = %ld, best_parent_rate = %lu (qd = %d)\n" , |
359 | __func__, best_rate, *parent_rate, tmp_qd - 1); |
360 | |
361 | return best_rate; |
362 | } |
363 | |
364 | static int clk_audio_pll_frac_set_rate(struct clk_hw *hw, unsigned long rate, |
365 | unsigned long parent_rate) |
366 | { |
367 | struct clk_audio_frac *frac = to_clk_audio_frac(hw); |
368 | unsigned long fracr, nd; |
369 | int ret; |
370 | |
371 | pr_debug("A PLL: %s, rate = %lu (parent_rate = %lu)\n" , __func__, rate, |
372 | parent_rate); |
373 | |
374 | if (rate < AUDIO_PLL_FOUT_MIN || rate > AUDIO_PLL_FOUT_MAX) |
375 | return -EINVAL; |
376 | |
377 | ret = clk_audio_pll_frac_compute_frac(rate, parent_rate, nd: &nd, fracr: &fracr); |
378 | if (ret) |
379 | return ret; |
380 | |
381 | frac->nd = nd; |
382 | frac->fracr = fracr; |
383 | |
384 | return 0; |
385 | } |
386 | |
387 | static int clk_audio_pll_pad_set_rate(struct clk_hw *hw, unsigned long rate, |
388 | unsigned long parent_rate) |
389 | { |
390 | struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); |
391 | u8 tmp_div; |
392 | |
393 | pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n" , __func__, |
394 | rate, parent_rate); |
395 | |
396 | if (!rate) |
397 | return -EINVAL; |
398 | |
399 | tmp_div = parent_rate / rate; |
400 | if (tmp_div % 3 == 0) { |
401 | apad_ck->qdaudio = tmp_div / 3; |
402 | apad_ck->div = 3; |
403 | } else { |
404 | apad_ck->qdaudio = tmp_div / 2; |
405 | apad_ck->div = 2; |
406 | } |
407 | |
408 | return 0; |
409 | } |
410 | |
411 | static int clk_audio_pll_pmc_set_rate(struct clk_hw *hw, unsigned long rate, |
412 | unsigned long parent_rate) |
413 | { |
414 | struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); |
415 | |
416 | if (!rate) |
417 | return -EINVAL; |
418 | |
419 | pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n" , __func__, |
420 | rate, parent_rate); |
421 | |
422 | apmc_ck->qdpmc = parent_rate / rate - 1; |
423 | |
424 | return 0; |
425 | } |
426 | |
427 | static const struct clk_ops audio_pll_frac_ops = { |
428 | .enable = clk_audio_pll_frac_enable, |
429 | .disable = clk_audio_pll_frac_disable, |
430 | .recalc_rate = clk_audio_pll_frac_recalc_rate, |
431 | .determine_rate = clk_audio_pll_frac_determine_rate, |
432 | .set_rate = clk_audio_pll_frac_set_rate, |
433 | }; |
434 | |
435 | static const struct clk_ops audio_pll_pad_ops = { |
436 | .enable = clk_audio_pll_pad_enable, |
437 | .disable = clk_audio_pll_pad_disable, |
438 | .recalc_rate = clk_audio_pll_pad_recalc_rate, |
439 | .round_rate = clk_audio_pll_pad_round_rate, |
440 | .set_rate = clk_audio_pll_pad_set_rate, |
441 | }; |
442 | |
443 | static const struct clk_ops audio_pll_pmc_ops = { |
444 | .enable = clk_audio_pll_pmc_enable, |
445 | .disable = clk_audio_pll_pmc_disable, |
446 | .recalc_rate = clk_audio_pll_pmc_recalc_rate, |
447 | .round_rate = clk_audio_pll_pmc_round_rate, |
448 | .set_rate = clk_audio_pll_pmc_set_rate, |
449 | }; |
450 | |
451 | struct clk_hw * __init |
452 | at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name, |
453 | const char *parent_name) |
454 | { |
455 | struct clk_audio_frac *frac_ck; |
456 | struct clk_init_data init = {}; |
457 | int ret; |
458 | |
459 | frac_ck = kzalloc(size: sizeof(*frac_ck), GFP_KERNEL); |
460 | if (!frac_ck) |
461 | return ERR_PTR(error: -ENOMEM); |
462 | |
463 | init.name = name; |
464 | init.ops = &audio_pll_frac_ops; |
465 | init.parent_names = &parent_name; |
466 | init.num_parents = 1; |
467 | init.flags = CLK_SET_RATE_GATE; |
468 | |
469 | frac_ck->hw.init = &init; |
470 | frac_ck->regmap = regmap; |
471 | |
472 | ret = clk_hw_register(NULL, hw: &frac_ck->hw); |
473 | if (ret) { |
474 | kfree(objp: frac_ck); |
475 | return ERR_PTR(error: ret); |
476 | } |
477 | |
478 | return &frac_ck->hw; |
479 | } |
480 | |
481 | struct clk_hw * __init |
482 | at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name, |
483 | const char *parent_name) |
484 | { |
485 | struct clk_audio_pad *apad_ck; |
486 | struct clk_init_data init; |
487 | int ret; |
488 | |
489 | apad_ck = kzalloc(size: sizeof(*apad_ck), GFP_KERNEL); |
490 | if (!apad_ck) |
491 | return ERR_PTR(error: -ENOMEM); |
492 | |
493 | init.name = name; |
494 | init.ops = &audio_pll_pad_ops; |
495 | init.parent_names = &parent_name; |
496 | init.num_parents = 1; |
497 | init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | |
498 | CLK_SET_RATE_PARENT; |
499 | |
500 | apad_ck->hw.init = &init; |
501 | apad_ck->regmap = regmap; |
502 | |
503 | ret = clk_hw_register(NULL, hw: &apad_ck->hw); |
504 | if (ret) { |
505 | kfree(objp: apad_ck); |
506 | return ERR_PTR(error: ret); |
507 | } |
508 | |
509 | return &apad_ck->hw; |
510 | } |
511 | |
512 | struct clk_hw * __init |
513 | at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name, |
514 | const char *parent_name) |
515 | { |
516 | struct clk_audio_pmc *apmc_ck; |
517 | struct clk_init_data init; |
518 | int ret; |
519 | |
520 | apmc_ck = kzalloc(size: sizeof(*apmc_ck), GFP_KERNEL); |
521 | if (!apmc_ck) |
522 | return ERR_PTR(error: -ENOMEM); |
523 | |
524 | init.name = name; |
525 | init.ops = &audio_pll_pmc_ops; |
526 | init.parent_names = &parent_name; |
527 | init.num_parents = 1; |
528 | init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | |
529 | CLK_SET_RATE_PARENT; |
530 | |
531 | apmc_ck->hw.init = &init; |
532 | apmc_ck->regmap = regmap; |
533 | |
534 | ret = clk_hw_register(NULL, hw: &apmc_ck->hw); |
535 | if (ret) { |
536 | kfree(objp: apmc_ck); |
537 | return ERR_PTR(error: ret); |
538 | } |
539 | |
540 | return &apmc_ck->hw; |
541 | } |
542 | |