1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright 2026 Cix Technology Group Co., Ltd.
3
4 #include <linux/auxiliary_bus.h>
5 #include <linux/clk.h>
6 #include <linux/clk-provider.h>
7 #include <linux/device.h>
8 #include <linux/module.h>
9 #include <linux/of.h>
10 #include <linux/platform_device.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/regmap.h>
13 #include <linux/reset.h>
14
15 #include <dt-bindings/clock/cix,sky1-audss-cru.h>
16
17 #define INFO_HIFI0 0x00
18 #define INFO_CLK_GATE 0x10
19 #define INFO_CLK_DIV 0x14
20 #define INFO_CLK_MUX 0x18
21 #define INFO_MCLK 0x70
22
23 #define SKY1_AUDSS_CLK_PARENTS_CNT 4
24 #define SKY1_AUDSS_NUM_CLKS (CLK_MCLK4 + 1)
25
26 static u32 sky1_reg_save[][2] = {
27 { INFO_HIFI0, 0 },
28 { INFO_CLK_GATE, 0 },
29 { INFO_CLK_DIV, 0 },
30 { INFO_CLK_MUX, 0 },
31 { INFO_MCLK, 0 },
32 };
33
34 static const char * const sky1_audss_clk_names[SKY1_AUDSS_CLK_PARENTS_CNT] = {
35 "x8k", "x11k", "sys", "48m",
36 };
37
38 static const u32 sky1_clk_rate_default[SKY1_AUDSS_CLK_PARENTS_CNT] = {
39 294912000,
40 270950400,
41 800000000,
42 48000000,
43 };
44
45 static const char * const dsp_clk_parent[] = {
46 "audio_clk4"
47 };
48
49 static const char * const dsp_bclk_parent[] = {
50 "audio_clk4_div2"
51 };
52
53 static const char * const dsp_pbclk_parent[] = {
54 "audio_clk4_div4"
55 };
56
57 static const char * const sram_axi_parent[] = {
58 "audio_clk4_div2"
59 };
60
61 static const char * const hda_sys_parent[] = {
62 "audio_clk4_div2"
63 };
64
65 static const char * const hda_hda_parent[] = {
66 "audio_clk5"
67 };
68
69 static const char * const dmac_axi_parent[] = {
70 "audio_clk4_div2"
71 };
72
73 static const char * const wdg_apb_parent[] = {
74 "audio_clk5_div2"
75 };
76
77 static const char * const wdg_wdg_parent[] = {
78 "audio_clk5_div2"
79 };
80
81 static const char * const timer_apb_parent[] = {
82 "audio_clk4_div4"
83 };
84
85 static const char * const timer_timer_parent[] = {
86 "audio_clk5_div2"
87 };
88
89 static const char * const mailbox_apb_parent[] = {
90 "audio_clk4_div4"
91 };
92
93 static const char * const i2s_apb_parent[] = {
94 "audio_clk4_div4"
95 };
96
97 static const char * const i2s0_parents[] = {
98 "audio_clk0", "audio_clk2"
99 };
100
101 static const char * const i2s1_parents[] = {
102 "audio_clk0", "audio_clk2"
103 };
104
105 static const char * const i2s2_parents[] = {
106 "audio_clk0", "audio_clk2"
107 };
108
109 static const char * const i2s3_parents[] = {
110 "audio_clk0", "audio_clk2"
111 };
112
113 static const char * const i2s4_parents[] = {
114 "audio_clk0", "audio_clk2"
115 };
116
117 static const char * const i2s5_parents[] = {
118 "audio_clk0", "audio_clk2"
119 };
120
121 static const char * const i2s6_parents[] = {
122 "audio_clk0", "audio_clk2"
123 };
124
125 static const char * const i2s7_parents[] = {
126 "audio_clk0", "audio_clk2"
127 };
128
129 static const char * const i2s8_parents[] = {
130 "audio_clk0", "audio_clk2"
131 };
132
133 static const char * const i2s9_parents[] = {
134 "audio_clk0", "audio_clk2"
135 };
136
137 static const char * const mclk_parents[] = {
138 "audio_clk0", "audio_clk2"
139 };
140
141 static const u32 i2s3_mux_table[] = { 0, 2 };
142 static const u32 i2s4_mux_table[] = { 0, 2 };
143
144 /*
145 * audss composite clock definition
146 */
147 struct muxdiv_cfg {
148 int offset;
149 u8 shift;
150 u8 width;
151 u8 flags;
152 };
153
154 struct gate_cfg {
155 int offset;
156 u8 shift;
157 u8 flags;
158 };
159
160 struct composite_clk_cfg {
161 u32 id;
162 const char * const name;
163 const char * const *parent_names;
164 int num_parents;
165 const u32 *mux_table;
166 struct muxdiv_cfg *mux_cfg;
167 struct muxdiv_cfg *div_cfg;
168 struct gate_cfg *gate_cfg;
169 unsigned long flags;
170 };
171
172 #define CFG(_id,\
173 _name,\
174 _parent_names,\
175 _mux_table,\
176 _mux_offset, _mux_shift, _mux_width, _mux_flags,\
177 _div_offset, _div_shift, _div_width, _div_flags,\
178 _gate_offset, _gate_shift, _gate_flags,\
179 _flags)\
180 {\
181 .id = _id,\
182 .name = _name,\
183 .parent_names = _parent_names,\
184 .num_parents = ARRAY_SIZE(_parent_names),\
185 .mux_table = _mux_table,\
186 .mux_cfg = &(struct muxdiv_cfg) { _mux_offset, _mux_shift, _mux_width, _mux_flags },\
187 .div_cfg = &(struct muxdiv_cfg) { _div_offset, _div_shift, _div_width, _div_flags },\
188 .gate_cfg = &(struct gate_cfg) { _gate_offset, _gate_shift, _gate_flags },\
189 .flags = _flags,\
190 }
191
192 static const struct composite_clk_cfg sky1_audss_clks[] = {
193 /* dsp */
194 CFG(CLK_DSP_CLK,
195 "audss_dsp_clk",
196 dsp_clk_parent,
197 NULL,
198 -1, 0, 0, 0,
199 INFO_CLK_DIV, 0, 2, 0,
200 INFO_HIFI0, 0, 0,
201 0),
202 CFG(CLK_DSP_BCLK,
203 "audss_dsp_bclk",
204 dsp_bclk_parent,
205 NULL,
206 -1, 0, 0, 0,
207 INFO_CLK_DIV, 0, 2, 0,
208 -1, 0, 0,
209 0),
210 CFG(CLK_DSP_PBCLK,
211 "audss_dsp_pbclk",
212 dsp_pbclk_parent,
213 NULL,
214 -1, 0, 0, 0,
215 INFO_CLK_DIV, 0, 2, 0,
216 -1, 0, 0,
217 0),
218 /* sram */
219 CFG(CLK_SRAM_AXI,
220 "audss_sram_axi",
221 sram_axi_parent,
222 NULL,
223 -1, 0, 0, 0,
224 INFO_CLK_DIV, 0, 2, 0,
225 INFO_CLK_GATE, 16, 0,
226 0),
227 /* hda */
228 CFG(CLK_HDA_SYS,
229 "audss_hda_sys",
230 hda_sys_parent,
231 NULL,
232 -1, 0, 0, 0,
233 INFO_CLK_DIV, 0, 2, 0,
234 INFO_CLK_GATE, 14, 0,
235 0),
236 CFG(CLK_HDA_HDA,
237 "audss_hda_hda",
238 hda_hda_parent,
239 NULL,
240 -1, 0, 0, 0,
241 -1, 0, 0, 0,
242 INFO_CLK_GATE, 14, 0,
243 0),
244 /* dmac */
245 CFG(CLK_DMAC_AXI,
246 "audss_dmac_axi",
247 dmac_axi_parent,
248 NULL,
249 -1, 0, 0, 0,
250 INFO_CLK_DIV, 0, 2, 0,
251 INFO_CLK_GATE, 15, 0,
252 0),
253 /* wdg */
254 CFG(CLK_WDG_APB,
255 "audss_wdg_apb",
256 wdg_apb_parent,
257 NULL,
258 -1, 0, 0, 0,
259 -1, 0, 0, 0,
260 INFO_CLK_GATE, 10, 0,
261 0),
262 CFG(CLK_WDG_WDG,
263 "audss_wdg_wdg",
264 wdg_wdg_parent,
265 NULL,
266 -1, 0, 0, 0,
267 -1, 0, 0, 0,
268 INFO_CLK_GATE, 10, 0,
269 0),
270 /* timer */
271 CFG(CLK_TIMER_APB,
272 "audss_timer_apb",
273 timer_apb_parent,
274 NULL,
275 -1, 0, 0, 0,
276 INFO_CLK_DIV, 0, 2, 0,
277 INFO_CLK_GATE, 11, 0,
278 0),
279 CFG(CLK_TIMER_TIMER,
280 "audss_timer_timer",
281 timer_timer_parent,
282 NULL,
283 -1, 0, 0, 0,
284 -1, 0, 0, 0,
285 INFO_CLK_GATE, 11, 0,
286 0),
287 /* mailbox: mb0(ap->dsp), mb1(dsp->ap) */
288 CFG(CLK_MB_0_APB,
289 "audss_mb_0_apb",
290 mailbox_apb_parent,
291 NULL,
292 -1, 0, 0, 0,
293 -1, 0, 0, 0,
294 INFO_CLK_GATE, 12, 0,
295 0),
296 CFG(CLK_MB_1_APB,
297 "audss_mb_1_apb",
298 mailbox_apb_parent,
299 NULL,
300 -1, 0, 0, 0,
301 -1, 0, 0, 0,
302 INFO_CLK_GATE, 13, 0,
303 0),
304 /* i2s */
305 CFG(CLK_I2S0_APB,
306 "audss_i2s0_apb",
307 i2s_apb_parent,
308 NULL,
309 -1, 0, 0, 0,
310 INFO_CLK_DIV, 0, 2, 0,
311 INFO_CLK_GATE, 0, 0,
312 0),
313 CFG(CLK_I2S1_APB,
314 "audss_i2s1_apb",
315 i2s_apb_parent,
316 NULL,
317 -1, 0, 0, 0,
318 INFO_CLK_DIV, 0, 2, 0,
319 INFO_CLK_GATE, 1, 0,
320 0),
321 CFG(CLK_I2S2_APB,
322 "audss_i2s2_apb",
323 i2s_apb_parent,
324 NULL,
325 -1, 0, 0, 0,
326 INFO_CLK_DIV, 0, 2, 0,
327 INFO_CLK_GATE, 2, 0,
328 0),
329 CFG(CLK_I2S3_APB,
330 "audss_i2s3_apb",
331 i2s_apb_parent,
332 NULL,
333 -1, 0, 0, 0,
334 INFO_CLK_DIV, 0, 2, 0,
335 INFO_CLK_GATE, 3, 0,
336 0),
337 CFG(CLK_I2S4_APB,
338 "audss_i2s4_apb",
339 i2s_apb_parent,
340 NULL,
341 -1, 0, 0, 0,
342 INFO_CLK_DIV, 0, 2, 0,
343 INFO_CLK_GATE, 4, 0,
344 0),
345 CFG(CLK_I2S5_APB,
346 "audss_i2s5_apb",
347 i2s_apb_parent,
348 NULL,
349 -1, 0, 0, 0,
350 INFO_CLK_DIV, 0, 2, 0,
351 INFO_CLK_GATE, 5, 0,
352 0),
353 CFG(CLK_I2S6_APB,
354 "audss_i2s6_apb",
355 i2s_apb_parent,
356 NULL,
357 -1, 0, 0, 0,
358 INFO_CLK_DIV, 0, 2, 0,
359 INFO_CLK_GATE, 6, 0,
360 0),
361 CFG(CLK_I2S7_APB,
362 "audss_i2s7_apb",
363 i2s_apb_parent,
364 NULL,
365 -1, 0, 0, 0,
366 INFO_CLK_DIV, 0, 2, 0,
367 INFO_CLK_GATE, 7, 0,
368 0),
369 CFG(CLK_I2S8_APB,
370 "audss_i2s8_apb",
371 i2s_apb_parent,
372 NULL,
373 -1, 0, 0, 0,
374 INFO_CLK_DIV, 0, 2, 0,
375 INFO_CLK_GATE, 8, 0,
376 0),
377 CFG(CLK_I2S9_APB,
378 "audss_i2s9_apb",
379 i2s_apb_parent,
380 NULL,
381 -1, 0, 0, 0,
382 INFO_CLK_DIV, 0, 2, 0,
383 INFO_CLK_GATE, 9, 0,
384 0),
385 CFG(CLK_I2S0,
386 "audss_i2s0",
387 i2s0_parents,
388 NULL,
389 INFO_CLK_MUX, 0, 2, 0,
390 INFO_CLK_DIV, 2, 2, 0,
391 INFO_CLK_GATE, 0, 0,
392 0),
393 CFG(CLK_I2S1,
394 "audss_i2s1",
395 i2s1_parents,
396 NULL,
397 INFO_CLK_MUX, 2, 2, 0,
398 INFO_CLK_DIV, 4, 2, 0,
399 INFO_CLK_GATE, 1, 0,
400 0),
401 CFG(CLK_I2S2,
402 "audss_i2s2",
403 i2s2_parents,
404 NULL,
405 INFO_CLK_MUX, 4, 2, 0,
406 INFO_CLK_DIV, 6, 2, 0,
407 INFO_CLK_GATE, 2, 0,
408 0),
409 CFG(CLK_I2S3,
410 "audss_i2s3",
411 i2s3_parents,
412 i2s3_mux_table,
413 INFO_CLK_MUX, 6, 2, 0,
414 INFO_CLK_DIV, 8, 2, 0,
415 INFO_CLK_GATE, 3, 0,
416 0),
417 CFG(CLK_I2S4,
418 "audss_i2s4",
419 i2s4_parents,
420 i2s4_mux_table,
421 INFO_CLK_MUX, 8, 2, 0,
422 INFO_CLK_DIV, 10, 2, 0,
423 INFO_CLK_GATE, 4, 0,
424 0),
425 CFG(CLK_I2S5,
426 "audss_i2s5",
427 i2s5_parents,
428 NULL,
429 INFO_CLK_MUX, 10, 2, 0,
430 INFO_CLK_DIV, 12, 2, 0,
431 INFO_CLK_GATE, 5, 0,
432 0),
433 CFG(CLK_I2S6,
434 "audss_i2s6",
435 i2s6_parents,
436 NULL,
437 INFO_CLK_MUX, 12, 2, 0,
438 INFO_CLK_DIV, 14, 2, 0,
439 INFO_CLK_GATE, 6, 0,
440 0),
441 CFG(CLK_I2S7,
442 "audss_i2s7",
443 i2s7_parents,
444 NULL,
445 INFO_CLK_MUX, 14, 2, 0,
446 INFO_CLK_DIV, 16, 2, 0,
447 INFO_CLK_GATE, 7, 0,
448 0),
449 CFG(CLK_I2S8,
450 "audss_i2s8",
451 i2s8_parents,
452 NULL,
453 INFO_CLK_MUX, 16, 2, 0,
454 INFO_CLK_DIV, 18, 2, 0,
455 INFO_CLK_GATE, 8, 0,
456 0),
457 CFG(CLK_I2S9,
458 "audss_i2s9",
459 i2s9_parents,
460 NULL,
461 INFO_CLK_MUX, 18, 2, 0,
462 INFO_CLK_DIV, 20, 2, 0,
463 INFO_CLK_GATE, 9, 0,
464 0),
465 /* mclk */
466 CFG(CLK_MCLK0,
467 "audss_mclk0",
468 mclk_parents,
469 NULL,
470 INFO_MCLK, 5, 1, 0,
471 -1, 0, 0, 0,
472 INFO_MCLK, 0, 0,
473 0),
474 CFG(CLK_MCLK1,
475 "audss_mclk1",
476 mclk_parents,
477 NULL,
478 INFO_MCLK, 6, 1, 0,
479 -1, 0, 0, 0,
480 INFO_MCLK, 1, 0,
481 0),
482 CFG(CLK_MCLK2,
483 "audss_mclk2",
484 mclk_parents,
485 NULL,
486 INFO_MCLK, 7, 1, 0,
487 -1, 0, 0, 0,
488 INFO_MCLK, 2, 0,
489 0),
490 CFG(CLK_MCLK3,
491 "audss_mclk3",
492 mclk_parents,
493 NULL,
494 INFO_MCLK, 8, 1, 0,
495 -1, 0, 0, 0,
496 INFO_MCLK, 3, 0,
497 0),
498 CFG(CLK_MCLK4,
499 "audss_mclk4",
500 mclk_parents,
501 NULL,
502 INFO_MCLK, 9, 1, 0,
503 -1, 0, 0, 0,
504 INFO_MCLK, 4, 0,
505 0),
506 };
507
508 struct sky1_audss_clks_devtype_data {
509 u32 (*reg_save)[2];
510 size_t reg_save_size;
511 const char * const *clk_names;
512 size_t clk_num;
513 const u32 *clk_rate_default;
514 const struct composite_clk_cfg *clk_cfg;
515 size_t clk_cfg_size;
516 };
517
518 static const struct regmap_config sky1_audss_regmap_config = {
519 .reg_bits = 32,
520 .val_bits = 32,
521 .reg_stride = 4,
522 };
523
524 struct sky1_audss_clks_priv {
525 struct device *dev;
526 struct regmap *regmap_cru;
527 struct reset_control *rst_noc;
528 struct clk *clks[SKY1_AUDSS_CLK_PARENTS_CNT];
529 const struct sky1_audss_clks_devtype_data *devtype_data;
530 spinlock_t lock;
531 struct clk_hw_onecell_data *clk_data;
532 };
533
534 #if IS_ENABLED(CONFIG_RESET_SKY1_AUDSS)
535
sky1_audss_reset_controller_register(struct device * dev)536 static int sky1_audss_reset_controller_register(struct device *dev)
537 {
538 struct auxiliary_device *adev;
539
540 if (!of_property_present(dev->of_node, "#reset-cells"))
541 return 0;
542
543 adev = devm_auxiliary_device_create(dev, "reset", NULL);
544 if (!adev)
545 return -ENODEV;
546
547 return 0;
548 }
549
550 #else
551
sky1_audss_reset_controller_register(struct device * dev)552 static int sky1_audss_reset_controller_register(struct device *dev)
553 {
554 return 0;
555 }
556
557 #endif
558
559 /*
560 * clk_ops for audss clock mux/divider/gate
561 */
562 struct sky1_clk_divider {
563 struct clk_divider div;
564 struct regmap *regmap;
565 int offset;
566 };
567
568 struct sky1_clk_gate {
569 struct clk_gate gate;
570 struct regmap *regmap;
571 int offset;
572 };
573
574 struct sky1_clk_mux {
575 struct clk_mux mux;
576 struct regmap *regmap;
577 int offset;
578 };
579
to_sky1_clk_mux(struct clk_mux * mux)580 static inline struct sky1_clk_mux *to_sky1_clk_mux(struct clk_mux *mux)
581 {
582 return container_of(mux, struct sky1_clk_mux, mux);
583 }
584
sky1_audss_clk_mux_get_parent(struct clk_hw * hw)585 static u8 sky1_audss_clk_mux_get_parent(struct clk_hw *hw)
586 {
587 struct clk_mux *mux = to_clk_mux(hw);
588 struct sky1_clk_mux *sky1_mux = to_sky1_clk_mux(mux);
589 u32 val;
590
591 regmap_read(sky1_mux->regmap, sky1_mux->offset, &val);
592 val = val >> mux->shift;
593 val &= mux->mask;
594
595 return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
596 }
597
sky1_audss_clk_mux_set_parent(struct clk_hw * hw,u8 index)598 static int sky1_audss_clk_mux_set_parent(struct clk_hw *hw, u8 index)
599 {
600 struct clk_mux *mux = to_clk_mux(hw);
601 u32 val = clk_mux_index_to_val(mux->table, mux->flags, index);
602 struct sky1_clk_mux *sky1_mux = to_sky1_clk_mux(mux);
603 unsigned long flags = 0;
604 u32 reg;
605
606 if (mux->lock)
607 spin_lock_irqsave(mux->lock, flags);
608 else
609 __acquire(mux->lock);
610
611 if (mux->flags & CLK_MUX_HIWORD_MASK) {
612 reg = mux->mask << (mux->shift + 16);
613 } else {
614 regmap_read(sky1_mux->regmap, sky1_mux->offset, ®);
615 reg &= ~(mux->mask << mux->shift);
616 }
617 val = val << mux->shift;
618 reg |= val;
619 regmap_write(sky1_mux->regmap, sky1_mux->offset, reg);
620
621 if (mux->lock)
622 spin_unlock_irqrestore(mux->lock, flags);
623 else
624 __release(mux->lock);
625
626 return 0;
627 }
628
sky1_audss_clk_mux_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)629 static int sky1_audss_clk_mux_determine_rate(struct clk_hw *hw,
630 struct clk_rate_request *req)
631 {
632 struct clk_mux *mux = to_clk_mux(hw);
633
634 return clk_mux_determine_rate_flags(hw, req, mux->flags);
635 }
636
637 static const struct clk_ops sky1_audss_clk_mux_ops = {
638 .get_parent = sky1_audss_clk_mux_get_parent,
639 .set_parent = sky1_audss_clk_mux_set_parent,
640 .determine_rate = sky1_audss_clk_mux_determine_rate,
641 };
642
to_sky1_clk_divider(struct clk_divider * div)643 static inline struct sky1_clk_divider *to_sky1_clk_divider(struct clk_divider *div)
644 {
645 return container_of(div, struct sky1_clk_divider, div);
646 }
647
sky1_audss_clk_divider_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)648 static unsigned long sky1_audss_clk_divider_recalc_rate(struct clk_hw *hw,
649 unsigned long parent_rate)
650 {
651 struct clk_divider *divider = to_clk_divider(hw);
652 struct sky1_clk_divider *sky1_div = to_sky1_clk_divider(divider);
653 unsigned int val;
654
655 regmap_read(sky1_div->regmap, sky1_div->offset, &val);
656 val = val >> divider->shift;
657 val &= clk_div_mask(divider->width);
658
659 return divider_recalc_rate(hw, parent_rate, val, divider->table,
660 divider->flags, divider->width);
661 }
662
sky1_audss_clk_divider_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)663 static int sky1_audss_clk_divider_determine_rate(struct clk_hw *hw,
664 struct clk_rate_request *req)
665 {
666 struct clk_divider *divider = to_clk_divider(hw);
667 struct sky1_clk_divider *sky1_div = to_sky1_clk_divider(divider);
668
669 /* if read only, just return current value */
670 if (divider->flags & CLK_DIVIDER_READ_ONLY) {
671 u32 val;
672
673 regmap_read(sky1_div->regmap, sky1_div->offset, &val);
674 val = val >> divider->shift;
675 val &= clk_div_mask(divider->width);
676
677 return divider_ro_determine_rate(hw, req, divider->table,
678 divider->width,
679 divider->flags, val);
680 }
681
682 return divider_determine_rate(hw, req, divider->table, divider->width,
683 divider->flags);
684 }
685
sky1_audss_clk_divider_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)686 static int sky1_audss_clk_divider_set_rate(struct clk_hw *hw,
687 unsigned long rate,
688 unsigned long parent_rate)
689 {
690 struct clk_divider *divider = to_clk_divider(hw);
691 struct sky1_clk_divider *sky1_div = to_sky1_clk_divider(divider);
692 int value;
693 unsigned long flags = 0;
694 u32 val;
695
696 value = divider_get_val(rate, parent_rate, divider->table,
697 divider->width, divider->flags);
698 if (value < 0)
699 return value;
700
701 if (divider->lock)
702 spin_lock_irqsave(divider->lock, flags);
703 else
704 __acquire(divider->lock);
705
706 if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
707 val = clk_div_mask(divider->width) << (divider->shift + 16);
708 } else {
709 regmap_read(sky1_div->regmap, sky1_div->offset, &val);
710 val &= ~(clk_div_mask(divider->width) << divider->shift);
711 }
712 val |= (u32)value << divider->shift;
713 regmap_write(sky1_div->regmap, sky1_div->offset, val);
714
715 if (divider->lock)
716 spin_unlock_irqrestore(divider->lock, flags);
717 else
718 __release(divider->lock);
719
720 return 0;
721 }
722
723 static const struct clk_ops sky1_audss_clk_divider_ops = {
724 .recalc_rate = sky1_audss_clk_divider_recalc_rate,
725 .determine_rate = sky1_audss_clk_divider_determine_rate,
726 .set_rate = sky1_audss_clk_divider_set_rate,
727 };
728
to_sky1_clk_gate(struct clk_gate * gate)729 static inline struct sky1_clk_gate *to_sky1_clk_gate(struct clk_gate *gate)
730 {
731 return container_of(gate, struct sky1_clk_gate, gate);
732 }
733
sky1_audss_clk_gate_endisable(struct clk_hw * hw,int enable)734 static void sky1_audss_clk_gate_endisable(struct clk_hw *hw, int enable)
735 {
736 struct clk_gate *gate = to_clk_gate(hw);
737 struct sky1_clk_gate *sky1_gate = to_sky1_clk_gate(gate);
738 int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
739 unsigned long flags = 0;
740 u32 reg;
741
742 set ^= enable;
743
744 if (gate->lock)
745 spin_lock_irqsave(gate->lock, flags);
746 else
747 __acquire(gate->lock);
748
749 if (gate->flags & CLK_GATE_HIWORD_MASK) {
750 reg = BIT(gate->bit_idx + 16);
751 if (set)
752 reg |= BIT(gate->bit_idx);
753 } else {
754 regmap_read(sky1_gate->regmap, sky1_gate->offset, ®);
755
756 if (set)
757 reg |= BIT(gate->bit_idx);
758 else
759 reg &= ~BIT(gate->bit_idx);
760 }
761
762 regmap_write(sky1_gate->regmap, sky1_gate->offset, reg);
763
764 if (gate->lock)
765 spin_unlock_irqrestore(gate->lock, flags);
766 else
767 __release(gate->lock);
768 }
769
sky1_audss_clk_gate_enable(struct clk_hw * hw)770 static int sky1_audss_clk_gate_enable(struct clk_hw *hw)
771 {
772 sky1_audss_clk_gate_endisable(hw, 1);
773
774 return 0;
775 }
776
sky1_audss_clk_gate_disable(struct clk_hw * hw)777 static void sky1_audss_clk_gate_disable(struct clk_hw *hw)
778 {
779 sky1_audss_clk_gate_endisable(hw, 0);
780 }
781
sky1_audss_clk_gate_is_enabled(struct clk_hw * hw)782 static int sky1_audss_clk_gate_is_enabled(struct clk_hw *hw)
783 {
784 struct clk_gate *gate = to_clk_gate(hw);
785 struct sky1_clk_gate *sky1_gate = to_sky1_clk_gate(gate);
786 u32 reg;
787
788 regmap_read(sky1_gate->regmap, sky1_gate->offset, ®);
789
790 /* if a set bit disables this clk, flip it before masking */
791 if (gate->flags & CLK_GATE_SET_TO_DISABLE)
792 reg ^= BIT(gate->bit_idx);
793
794 reg &= BIT(gate->bit_idx);
795
796 return !!reg;
797 }
798
799 static const struct clk_ops sky1_audss_clk_gate_ops = {
800 .enable = sky1_audss_clk_gate_enable,
801 .disable = sky1_audss_clk_gate_disable,
802 .is_enabled = sky1_audss_clk_gate_is_enabled,
803 };
804
sky1_audss_clk_register(struct device * dev,const char * name,const char * const * parent_names,int num_parents,struct regmap * regmap,const u32 * mux_table,struct muxdiv_cfg * mux_cfg,struct muxdiv_cfg * div_cfg,struct gate_cfg * gate_cfg,unsigned long flags,spinlock_t * lock)805 static struct clk_hw *sky1_audss_clk_register(struct device *dev,
806 const char *name,
807 const char * const *parent_names,
808 int num_parents,
809 struct regmap *regmap,
810 const u32 *mux_table,
811 struct muxdiv_cfg *mux_cfg,
812 struct muxdiv_cfg *div_cfg,
813 struct gate_cfg *gate_cfg,
814 unsigned long flags,
815 spinlock_t *lock)
816 {
817 const struct clk_ops *sky1_gate_ops = NULL;
818 const struct clk_ops *sky1_mux_ops = NULL;
819 const struct clk_ops *sky1_div_ops = NULL;
820 struct sky1_clk_divider *sky1_div = NULL;
821 struct sky1_clk_gate *sky1_gate = NULL;
822 struct sky1_clk_mux *sky1_mux = NULL;
823 struct clk_hw *hw = ERR_PTR(-ENOMEM);
824 struct clk_parent_data *parent_data;
825 int i;
826
827 parent_data = devm_kcalloc(dev, num_parents, sizeof(*parent_data), GFP_KERNEL);
828 if (!parent_data)
829 return ERR_PTR(-ENOMEM);
830
831 for (i = 0; i < num_parents; i++)
832 parent_data[i].name = parent_names[i];
833
834 if (mux_cfg->offset >= 0) {
835 sky1_mux = devm_kzalloc(dev, sizeof(*sky1_mux), GFP_KERNEL);
836 if (!sky1_mux)
837 return ERR_PTR(-ENOMEM);
838
839 sky1_mux->mux.reg = NULL;
840 sky1_mux->mux.shift = mux_cfg->shift;
841 sky1_mux->mux.mask = BIT(mux_cfg->width) - 1;
842 sky1_mux->mux.flags = mux_cfg->flags;
843 sky1_mux->mux.table = mux_table;
844 sky1_mux->mux.lock = lock;
845 sky1_mux_ops = &sky1_audss_clk_mux_ops;
846 sky1_mux->regmap = regmap;
847 sky1_mux->offset = mux_cfg->offset;
848 }
849
850 if (div_cfg->offset >= 0) {
851 sky1_div = devm_kzalloc(dev, sizeof(*sky1_div), GFP_KERNEL);
852 if (!sky1_div)
853 return ERR_PTR(-ENOMEM);
854
855 sky1_div->div.reg = NULL;
856 sky1_div->div.shift = div_cfg->shift;
857 sky1_div->div.width = div_cfg->width;
858 sky1_div->div.flags = div_cfg->flags | CLK_DIVIDER_POWER_OF_TWO;
859 sky1_div->div.lock = lock;
860 sky1_div_ops = &sky1_audss_clk_divider_ops;
861 sky1_div->regmap = regmap;
862 sky1_div->offset = div_cfg->offset;
863 }
864
865 if (gate_cfg->offset >= 0) {
866 sky1_gate = devm_kzalloc(dev, sizeof(*sky1_gate), GFP_KERNEL);
867 if (!sky1_gate)
868 return ERR_PTR(-ENOMEM);
869
870 sky1_gate->gate.reg = NULL;
871 sky1_gate->gate.bit_idx = gate_cfg->shift;
872 sky1_gate->gate.flags = gate_cfg->flags;
873 sky1_gate->gate.lock = lock;
874 sky1_gate_ops = &sky1_audss_clk_gate_ops;
875 sky1_gate->regmap = regmap;
876 sky1_gate->offset = gate_cfg->offset;
877 }
878
879 hw = devm_clk_hw_register_composite_pdata(dev, name, parent_data, num_parents,
880 sky1_mux ? &sky1_mux->mux.hw : NULL, sky1_mux_ops,
881 sky1_div ? &sky1_div->div.hw : NULL, sky1_div_ops,
882 sky1_gate ? &sky1_gate->gate.hw : NULL, sky1_gate_ops,
883 flags);
884 if (IS_ERR(hw)) {
885 dev_err(dev, "register %s clock failed with err = %ld\n",
886 name, PTR_ERR(hw));
887 return hw;
888 }
889
890 return hw;
891 }
892
sky1_audss_clks_get(struct sky1_audss_clks_priv * priv)893 static int sky1_audss_clks_get(struct sky1_audss_clks_priv *priv)
894 {
895 const struct sky1_audss_clks_devtype_data *devtype_data = priv->devtype_data;
896 int i;
897
898 for (i = 0; i < devtype_data->clk_num; i++) {
899 priv->clks[i] = devm_clk_get(priv->dev, devtype_data->clk_names[i]);
900 if (IS_ERR(priv->clks[i]))
901 return dev_err_probe(priv->dev, PTR_ERR(priv->clks[i]),
902 "failed to get clock %s", devtype_data->clk_names[i]);
903 }
904
905 return 0;
906 }
907
sky1_audss_clks_enable(struct sky1_audss_clks_priv * priv)908 static int sky1_audss_clks_enable(struct sky1_audss_clks_priv *priv)
909 {
910 const struct sky1_audss_clks_devtype_data *devtype_data = priv->devtype_data;
911 int i, err;
912
913 for (i = 0; i < devtype_data->clk_num; i++) {
914 err = clk_prepare_enable(priv->clks[i]);
915 if (err) {
916 dev_err(priv->dev, "failed to enable clock %s\n",
917 devtype_data->clk_names[i]);
918 goto err_clks;
919 }
920 }
921
922 return 0;
923
924 err_clks:
925 while (--i >= 0)
926 clk_disable_unprepare(priv->clks[i]);
927
928 return err;
929 }
930
sky1_audss_clks_disable(struct sky1_audss_clks_priv * priv)931 static void sky1_audss_clks_disable(struct sky1_audss_clks_priv *priv)
932 {
933 const struct sky1_audss_clks_devtype_data *devtype_data = priv->devtype_data;
934 int i;
935
936 for (i = 0; i < devtype_data->clk_num; i++)
937 clk_disable_unprepare(priv->clks[i]);
938 }
939
sky1_audss_clks_set_rate(struct sky1_audss_clks_priv * priv)940 static int sky1_audss_clks_set_rate(struct sky1_audss_clks_priv *priv)
941 {
942 const struct sky1_audss_clks_devtype_data *devtype_data = priv->devtype_data;
943 int i, err;
944
945 for (i = 0; i < devtype_data->clk_num; i++) {
946 err = clk_set_rate(priv->clks[i], devtype_data->clk_rate_default[i]);
947 if (err) {
948 dev_err(priv->dev, "failed to set clock rate %s\n",
949 devtype_data->clk_names[i]);
950 return err;
951 }
952 }
953
954 return 0;
955 }
956
sky1_audss_clk_rpm_cleanup(void * data)957 static void sky1_audss_clk_rpm_cleanup(void *data)
958 {
959 pm_runtime_force_suspend(data);
960 }
961
962 /* register sky1 audio subsystem clocks */
sky1_audss_clk_probe(struct platform_device * pdev)963 static int sky1_audss_clk_probe(struct platform_device *pdev)
964 {
965 const struct sky1_audss_clks_devtype_data *devtype_data;
966 struct sky1_audss_clks_priv *priv;
967 struct device *dev = &pdev->dev;
968 struct clk_hw **clk_table;
969 void __iomem *base;
970 int i, ret;
971
972 devtype_data = device_get_match_data(dev);
973 if (!devtype_data)
974 return -ENODEV;
975
976 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
977 if (!priv)
978 return -ENOMEM;
979
980 spin_lock_init(&priv->lock);
981
982 priv->clk_data = devm_kzalloc(dev,
983 struct_size(priv->clk_data, hws, SKY1_AUDSS_NUM_CLKS),
984 GFP_KERNEL);
985 if (!priv->clk_data)
986 return -ENOMEM;
987
988 priv->clk_data->num = SKY1_AUDSS_NUM_CLKS;
989 clk_table = priv->clk_data->hws;
990
991 base = devm_platform_ioremap_resource(pdev, 0);
992 if (IS_ERR(base))
993 return PTR_ERR(base);
994
995 priv->regmap_cru = devm_regmap_init_mmio(dev, base, &sky1_audss_regmap_config);
996 if (IS_ERR(priv->regmap_cru))
997 return dev_err_probe(dev, PTR_ERR(priv->regmap_cru),
998 "failed to initialize regmap\n");
999
1000 priv->dev = dev;
1001 priv->devtype_data = devtype_data;
1002
1003 priv->rst_noc = devm_reset_control_get_exclusive(dev, NULL);
1004 if (IS_ERR(priv->rst_noc))
1005 return dev_err_probe(dev, PTR_ERR(priv->rst_noc),
1006 "failed to get audss noc reset");
1007
1008 platform_set_drvdata(pdev, priv);
1009
1010 reset_control_assert(priv->rst_noc);
1011
1012 ret = sky1_audss_clks_get(priv);
1013 if (ret)
1014 return ret;
1015
1016 ret = sky1_audss_clks_enable(priv);
1017 if (ret)
1018 return ret;
1019
1020 /* release noc reset after clock on */
1021 ret = reset_control_deassert(priv->rst_noc);
1022 if (ret) {
1023 sky1_audss_clks_disable(priv);
1024 return ret;
1025 }
1026
1027 pm_runtime_get_noresume(dev);
1028 pm_runtime_set_active(dev);
1029 pm_runtime_enable(dev);
1030
1031 /*
1032 * Register cleanup action before clocks/provider (released last under LIFO).
1033 */
1034 ret = devm_add_action_or_reset(dev, sky1_audss_clk_rpm_cleanup, dev);
1035 if (ret)
1036 return ret;
1037
1038 ret = sky1_audss_clks_set_rate(priv);
1039 if (ret)
1040 goto fail_pm;
1041
1042 /* audio_clk4 clock fixed divider */
1043 clk_table[CLK_AUD_CLK4_DIV2] =
1044 devm_clk_hw_register_fixed_factor(dev,
1045 "audio_clk4_div2",
1046 "audio_clk4",
1047 0,
1048 1, 2);
1049 if (IS_ERR(clk_table[CLK_AUD_CLK4_DIV2])) {
1050 ret = PTR_ERR(clk_table[CLK_AUD_CLK4_DIV2]);
1051 dev_err(dev, "failed to register clock %d, ret:%d\n", CLK_AUD_CLK4_DIV2, ret);
1052 goto fail_pm;
1053 }
1054
1055 clk_table[CLK_AUD_CLK4_DIV4] =
1056 devm_clk_hw_register_fixed_factor(dev,
1057 "audio_clk4_div4",
1058 "audio_clk4",
1059 0,
1060 1, 4);
1061 if (IS_ERR(clk_table[CLK_AUD_CLK4_DIV4])) {
1062 ret = PTR_ERR(clk_table[CLK_AUD_CLK4_DIV4]);
1063 dev_err(dev, "failed to register clock %d, ret:%d\n", CLK_AUD_CLK4_DIV4, ret);
1064 goto fail_pm;
1065 }
1066
1067 /* audio_clk5 clock fixed divider */
1068 clk_table[CLK_AUD_CLK5_DIV2] =
1069 devm_clk_hw_register_fixed_factor(dev,
1070 "audio_clk5_div2",
1071 "audio_clk5",
1072 0,
1073 1, 2);
1074 if (IS_ERR(clk_table[CLK_AUD_CLK5_DIV2])) {
1075 ret = PTR_ERR(clk_table[CLK_AUD_CLK5_DIV2]);
1076 dev_err(dev, "failed to register clock %d, ret:%d\n", CLK_AUD_CLK5_DIV2, ret);
1077 goto fail_pm;
1078 }
1079
1080 for (i = 0; i < devtype_data->clk_cfg_size; i++) {
1081 clk_table[devtype_data->clk_cfg[i].id] =
1082 sky1_audss_clk_register(dev,
1083 devtype_data->clk_cfg[i].name,
1084 devtype_data->clk_cfg[i].parent_names,
1085 devtype_data->clk_cfg[i].num_parents,
1086 priv->regmap_cru,
1087 devtype_data->clk_cfg[i].mux_table,
1088 devtype_data->clk_cfg[i].mux_cfg,
1089 devtype_data->clk_cfg[i].div_cfg,
1090 devtype_data->clk_cfg[i].gate_cfg,
1091 devtype_data->clk_cfg[i].flags,
1092 &priv->lock);
1093 if (IS_ERR(clk_table[devtype_data->clk_cfg[i].id])) {
1094 ret = PTR_ERR(clk_table[devtype_data->clk_cfg[i].id]);
1095 dev_err(dev, "failed to register clock %d, ret:%d\n",
1096 devtype_data->clk_cfg[i].id, ret);
1097 goto fail_pm;
1098 }
1099 }
1100
1101 ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, priv->clk_data);
1102 if (ret) {
1103 dev_err(dev, "failed to add clock provider: %d\n", ret);
1104 goto fail_pm;
1105 }
1106
1107 ret = sky1_audss_reset_controller_register(dev);
1108 if (ret) {
1109 dev_err(dev, "failed to register reset controller: %d\n", ret);
1110 goto fail_pm;
1111 }
1112
1113 pm_runtime_put_sync(dev);
1114
1115 return 0;
1116
1117 fail_pm:
1118 pm_runtime_put_sync(dev);
1119 return ret;
1120 }
1121
sky1_audss_clk_runtime_suspend(struct device * dev)1122 static int __maybe_unused sky1_audss_clk_runtime_suspend(struct device *dev)
1123 {
1124 struct sky1_audss_clks_priv *priv = dev_get_drvdata(dev);
1125 const struct sky1_audss_clks_devtype_data *devtype_data = priv->devtype_data;
1126 unsigned long flags;
1127 int i;
1128
1129 spin_lock_irqsave(&priv->lock, flags);
1130 for (i = 0; i < devtype_data->reg_save_size; i++)
1131 regmap_read(priv->regmap_cru,
1132 devtype_data->reg_save[i][0], &devtype_data->reg_save[i][1]);
1133 spin_unlock_irqrestore(&priv->lock, flags);
1134
1135 reset_control_assert(priv->rst_noc);
1136
1137 sky1_audss_clks_disable(priv);
1138
1139 return 0;
1140 }
1141
sky1_audss_clk_runtime_resume(struct device * dev)1142 static int __maybe_unused sky1_audss_clk_runtime_resume(struct device *dev)
1143 {
1144 struct sky1_audss_clks_priv *priv = dev_get_drvdata(dev);
1145 const struct sky1_audss_clks_devtype_data *devtype_data = priv->devtype_data;
1146 unsigned long flags;
1147 int i, ret;
1148
1149 ret = sky1_audss_clks_enable(priv);
1150 if (ret) {
1151 dev_err(dev, "failed to enable clocks\n");
1152 return ret;
1153 }
1154
1155 ret = reset_control_deassert(priv->rst_noc);
1156 if (ret) {
1157 sky1_audss_clks_disable(priv);
1158 return ret;
1159 }
1160
1161 spin_lock_irqsave(&priv->lock, flags);
1162 for (i = 0; i < devtype_data->reg_save_size; i++)
1163 regmap_write(priv->regmap_cru,
1164 devtype_data->reg_save[i][0], devtype_data->reg_save[i][1]);
1165 spin_unlock_irqrestore(&priv->lock, flags);
1166
1167 return 0;
1168 }
1169
1170 static const struct dev_pm_ops sky1_audss_clk_pm_ops = {
1171 SET_RUNTIME_PM_OPS(sky1_audss_clk_runtime_suspend,
1172 sky1_audss_clk_runtime_resume, NULL)
1173 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1174 pm_runtime_force_resume)
1175 };
1176
1177 static const struct sky1_audss_clks_devtype_data sky1_devtype_data = {
1178 .reg_save = sky1_reg_save,
1179 .reg_save_size = ARRAY_SIZE(sky1_reg_save),
1180 .clk_names = sky1_audss_clk_names,
1181 .clk_num = ARRAY_SIZE(sky1_audss_clk_names),
1182 .clk_rate_default = sky1_clk_rate_default,
1183 .clk_cfg = sky1_audss_clks,
1184 .clk_cfg_size = ARRAY_SIZE(sky1_audss_clks),
1185 };
1186
1187 static const struct of_device_id sky1_audss_clk_of_match[] = {
1188 { .compatible = "cix,sky1-audss-cru", .data = &sky1_devtype_data, },
1189 { /* sentinel */ },
1190 };
1191 MODULE_DEVICE_TABLE(of, sky1_audss_clk_of_match);
1192
1193 static struct platform_driver sky1_audss_clk_driver = {
1194 .probe = sky1_audss_clk_probe,
1195 .driver = {
1196 .name = "sky1-audss-clk",
1197 .suppress_bind_attrs = true,
1198 .of_match_table = sky1_audss_clk_of_match,
1199 .pm = pm_ptr(&sky1_audss_clk_pm_ops),
1200 },
1201 };
1202 module_platform_driver(sky1_audss_clk_driver);
1203
1204 MODULE_LICENSE("GPL");
1205 MODULE_AUTHOR("Joakim Zhang <joakim.zhang@cixtech.com>");
1206 MODULE_DESCRIPTION("Cixtech Sky1 Audio Subsystem Clock Controller Driver");
1207