xref: /linux/drivers/clk/cix/clk-sky1-audss.c (revision 502d45774af09f1c681c754c4b7cdfb5d7f72fd9)
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, &reg);
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, &reg);
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, &reg);
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