clk: meson: axg-audio: don't register inputs in the onecell data
[platform/kernel/linux-starfive.git] / drivers / clk / meson / axg-audio.c
1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /*
3  * Copyright (c) 2018 BayLibre, SAS.
4  * Author: Jerome Brunet <jbrunet@baylibre.com>
5  */
6
7 #include <linux/clk.h>
8 #include <linux/clk-provider.h>
9 #include <linux/init.h>
10 #include <linux/of_device.h>
11 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <linux/regmap.h>
14 #include <linux/reset.h>
15 #include <linux/slab.h>
16
17 #include "axg-audio.h"
18 #include "clk-input.h"
19 #include "clk-regmap.h"
20 #include "clk-phase.h"
21 #include "sclk-div.h"
22
23 #define AUD_MST_IN_COUNT        8
24 #define AUD_SLV_SCLK_COUNT      10
25 #define AUD_SLV_LRCLK_COUNT     10
26
27 #define AUD_GATE(_name, _reg, _bit, _pname, _iflags)                    \
28 struct clk_regmap aud_##_name = {                                       \
29         .data = &(struct clk_regmap_gate_data){                         \
30                 .offset = (_reg),                                       \
31                 .bit_idx = (_bit),                                      \
32         },                                                              \
33         .hw.init = &(struct clk_init_data) {                            \
34                 .name = "aud_"#_name,                                   \
35                 .ops = &clk_regmap_gate_ops,                            \
36                 .parent_names = (const char *[]){ _pname },             \
37                 .num_parents = 1,                                       \
38                 .flags = CLK_DUTY_CYCLE_PARENT | (_iflags),             \
39         },                                                              \
40 }
41
42 #define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pnames, _iflags)  \
43 struct clk_regmap aud_##_name = {                                       \
44         .data = &(struct clk_regmap_mux_data){                          \
45                 .offset = (_reg),                                       \
46                 .mask = (_mask),                                        \
47                 .shift = (_shift),                                      \
48                 .flags = (_dflags),                                     \
49         },                                                              \
50         .hw.init = &(struct clk_init_data){                             \
51                 .name = "aud_"#_name,                                   \
52                 .ops = &clk_regmap_mux_ops,                             \
53                 .parent_names = (_pnames),                              \
54                 .num_parents = ARRAY_SIZE(_pnames),                     \
55                 .flags = CLK_DUTY_CYCLE_PARENT | (_iflags),             \
56         },                                                              \
57 }
58
59 #define AUD_DIV(_name, _reg, _shift, _width, _dflags, _pname, _iflags)  \
60 struct clk_regmap aud_##_name = {                                       \
61         .data = &(struct clk_regmap_div_data){                          \
62                 .offset = (_reg),                                       \
63                 .shift = (_shift),                                      \
64                 .width = (_width),                                      \
65                 .flags = (_dflags),                                     \
66         },                                                              \
67         .hw.init = &(struct clk_init_data){                             \
68                 .name = "aud_"#_name,                                   \
69                 .ops = &clk_regmap_divider_ops,                         \
70                 .parent_names = (const char *[]) { _pname },            \
71                 .num_parents = 1,                                       \
72                 .flags = (_iflags),                                     \
73         },                                                              \
74 }
75
76 #define AUD_PCLK_GATE(_name, _bit)                              \
77         AUD_GATE(_name, AUDIO_CLK_GATE_EN, _bit, "audio_pclk", 0)
78
79 /* Audio peripheral clocks */
80 static AUD_PCLK_GATE(ddr_arb,      0);
81 static AUD_PCLK_GATE(pdm,          1);
82 static AUD_PCLK_GATE(tdmin_a,      2);
83 static AUD_PCLK_GATE(tdmin_b,      3);
84 static AUD_PCLK_GATE(tdmin_c,      4);
85 static AUD_PCLK_GATE(tdmin_lb,     5);
86 static AUD_PCLK_GATE(tdmout_a,     6);
87 static AUD_PCLK_GATE(tdmout_b,     7);
88 static AUD_PCLK_GATE(tdmout_c,     8);
89 static AUD_PCLK_GATE(frddr_a,      9);
90 static AUD_PCLK_GATE(frddr_b,      10);
91 static AUD_PCLK_GATE(frddr_c,      11);
92 static AUD_PCLK_GATE(toddr_a,      12);
93 static AUD_PCLK_GATE(toddr_b,      13);
94 static AUD_PCLK_GATE(toddr_c,      14);
95 static AUD_PCLK_GATE(loopback,     15);
96 static AUD_PCLK_GATE(spdifin,      16);
97 static AUD_PCLK_GATE(spdifout,     17);
98 static AUD_PCLK_GATE(resample,     18);
99 static AUD_PCLK_GATE(power_detect, 19);
100
101 /* Audio Master Clocks */
102 static const char * const mst_mux_parent_names[] = {
103         "aud_mst_in0", "aud_mst_in1", "aud_mst_in2", "aud_mst_in3",
104         "aud_mst_in4", "aud_mst_in5", "aud_mst_in6", "aud_mst_in7",
105 };
106
107 #define AUD_MST_MUX(_name, _reg, _flag)                         \
108         AUD_MUX(_name##_sel, _reg, 0x7, 24, _flag,              \
109                 mst_mux_parent_names, CLK_SET_RATE_PARENT)
110
111 #define AUD_MST_MCLK_MUX(_name, _reg)                           \
112         AUD_MST_MUX(_name, _reg, CLK_MUX_ROUND_CLOSEST)
113
114 #define AUD_MST_SYS_MUX(_name, _reg)                            \
115         AUD_MST_MUX(_name, _reg, 0)
116
117 static AUD_MST_MCLK_MUX(mst_a_mclk,   AUDIO_MCLK_A_CTRL);
118 static AUD_MST_MCLK_MUX(mst_b_mclk,   AUDIO_MCLK_B_CTRL);
119 static AUD_MST_MCLK_MUX(mst_c_mclk,   AUDIO_MCLK_C_CTRL);
120 static AUD_MST_MCLK_MUX(mst_d_mclk,   AUDIO_MCLK_D_CTRL);
121 static AUD_MST_MCLK_MUX(mst_e_mclk,   AUDIO_MCLK_E_CTRL);
122 static AUD_MST_MCLK_MUX(mst_f_mclk,   AUDIO_MCLK_F_CTRL);
123 static AUD_MST_MCLK_MUX(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
124 static AUD_MST_MCLK_MUX(pdm_dclk,     AUDIO_CLK_PDMIN_CTRL0);
125 static AUD_MST_SYS_MUX(spdifin_clk,   AUDIO_CLK_SPDIFIN_CTRL);
126 static AUD_MST_SYS_MUX(pdm_sysclk,    AUDIO_CLK_PDMIN_CTRL1);
127
128 #define AUD_MST_DIV(_name, _reg, _flag)                         \
129         AUD_DIV(_name##_div, _reg, 0, 16, _flag,                \
130                     "aud_"#_name"_sel", CLK_SET_RATE_PARENT)    \
131
132 #define AUD_MST_MCLK_DIV(_name, _reg)                           \
133         AUD_MST_DIV(_name, _reg, CLK_DIVIDER_ROUND_CLOSEST)
134
135 #define AUD_MST_SYS_DIV(_name, _reg)                            \
136         AUD_MST_DIV(_name, _reg, 0)
137
138 static AUD_MST_MCLK_DIV(mst_a_mclk,   AUDIO_MCLK_A_CTRL);
139 static AUD_MST_MCLK_DIV(mst_b_mclk,   AUDIO_MCLK_B_CTRL);
140 static AUD_MST_MCLK_DIV(mst_c_mclk,   AUDIO_MCLK_C_CTRL);
141 static AUD_MST_MCLK_DIV(mst_d_mclk,   AUDIO_MCLK_D_CTRL);
142 static AUD_MST_MCLK_DIV(mst_e_mclk,   AUDIO_MCLK_E_CTRL);
143 static AUD_MST_MCLK_DIV(mst_f_mclk,   AUDIO_MCLK_F_CTRL);
144 static AUD_MST_MCLK_DIV(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
145 static AUD_MST_MCLK_DIV(pdm_dclk,     AUDIO_CLK_PDMIN_CTRL0);
146 static AUD_MST_SYS_DIV(spdifin_clk,   AUDIO_CLK_SPDIFIN_CTRL);
147 static AUD_MST_SYS_DIV(pdm_sysclk,    AUDIO_CLK_PDMIN_CTRL1);
148
149 #define AUD_MST_MCLK_GATE(_name, _reg)                          \
150         AUD_GATE(_name, _reg, 31,  "aud_"#_name"_div",  \
151                  CLK_SET_RATE_PARENT)
152
153 static AUD_MST_MCLK_GATE(mst_a_mclk,   AUDIO_MCLK_A_CTRL);
154 static AUD_MST_MCLK_GATE(mst_b_mclk,   AUDIO_MCLK_B_CTRL);
155 static AUD_MST_MCLK_GATE(mst_c_mclk,   AUDIO_MCLK_C_CTRL);
156 static AUD_MST_MCLK_GATE(mst_d_mclk,   AUDIO_MCLK_D_CTRL);
157 static AUD_MST_MCLK_GATE(mst_e_mclk,   AUDIO_MCLK_E_CTRL);
158 static AUD_MST_MCLK_GATE(mst_f_mclk,   AUDIO_MCLK_F_CTRL);
159 static AUD_MST_MCLK_GATE(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
160 static AUD_MST_MCLK_GATE(spdifin_clk,  AUDIO_CLK_SPDIFIN_CTRL);
161 static AUD_MST_MCLK_GATE(pdm_dclk,     AUDIO_CLK_PDMIN_CTRL0);
162 static AUD_MST_MCLK_GATE(pdm_sysclk,   AUDIO_CLK_PDMIN_CTRL1);
163
164 /* Sample Clocks */
165 #define AUD_MST_SCLK_PRE_EN(_name, _reg)                        \
166         AUD_GATE(mst_##_name##_sclk_pre_en, _reg, 31,           \
167                  "aud_mst_"#_name"_mclk", 0)
168
169 static AUD_MST_SCLK_PRE_EN(a, AUDIO_MST_A_SCLK_CTRL0);
170 static AUD_MST_SCLK_PRE_EN(b, AUDIO_MST_B_SCLK_CTRL0);
171 static AUD_MST_SCLK_PRE_EN(c, AUDIO_MST_C_SCLK_CTRL0);
172 static AUD_MST_SCLK_PRE_EN(d, AUDIO_MST_D_SCLK_CTRL0);
173 static AUD_MST_SCLK_PRE_EN(e, AUDIO_MST_E_SCLK_CTRL0);
174 static AUD_MST_SCLK_PRE_EN(f, AUDIO_MST_F_SCLK_CTRL0);
175
176 #define AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width,               \
177                          _hi_shift, _hi_width, _pname, _iflags)         \
178 struct clk_regmap aud_##_name = {                                       \
179         .data = &(struct meson_sclk_div_data) {                         \
180                 .div = {                                                \
181                         .reg_off = (_reg),                              \
182                         .shift   = (_div_shift),                        \
183                         .width   = (_div_width),                        \
184                 },                                                      \
185                 .hi = {                                                 \
186                         .reg_off = (_reg),                              \
187                         .shift   = (_hi_shift),                         \
188                         .width   = (_hi_width),                         \
189                 },                                                      \
190         },                                                              \
191         .hw.init = &(struct clk_init_data) {                            \
192                 .name = "aud_"#_name,                                   \
193                 .ops = &meson_sclk_div_ops,                             \
194                 .parent_names = (const char *[]) { _pname },            \
195                 .num_parents = 1,                                       \
196                 .flags = (_iflags),                                     \
197         },                                                              \
198 }
199
200 #define AUD_MST_SCLK_DIV(_name, _reg)                                   \
201         AUD_SCLK_DIV(mst_##_name##_sclk_div, _reg, 20, 10, 0, 0,        \
202                      "aud_mst_"#_name"_sclk_pre_en",                    \
203                      CLK_SET_RATE_PARENT)
204
205 static AUD_MST_SCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0);
206 static AUD_MST_SCLK_DIV(b, AUDIO_MST_B_SCLK_CTRL0);
207 static AUD_MST_SCLK_DIV(c, AUDIO_MST_C_SCLK_CTRL0);
208 static AUD_MST_SCLK_DIV(d, AUDIO_MST_D_SCLK_CTRL0);
209 static AUD_MST_SCLK_DIV(e, AUDIO_MST_E_SCLK_CTRL0);
210 static AUD_MST_SCLK_DIV(f, AUDIO_MST_F_SCLK_CTRL0);
211
212 #define AUD_MST_SCLK_POST_EN(_name, _reg)                               \
213         AUD_GATE(mst_##_name##_sclk_post_en, _reg, 30,          \
214                  "aud_mst_"#_name"_sclk_div", CLK_SET_RATE_PARENT)
215
216 static AUD_MST_SCLK_POST_EN(a, AUDIO_MST_A_SCLK_CTRL0);
217 static AUD_MST_SCLK_POST_EN(b, AUDIO_MST_B_SCLK_CTRL0);
218 static AUD_MST_SCLK_POST_EN(c, AUDIO_MST_C_SCLK_CTRL0);
219 static AUD_MST_SCLK_POST_EN(d, AUDIO_MST_D_SCLK_CTRL0);
220 static AUD_MST_SCLK_POST_EN(e, AUDIO_MST_E_SCLK_CTRL0);
221 static AUD_MST_SCLK_POST_EN(f, AUDIO_MST_F_SCLK_CTRL0);
222
223 #define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2, \
224                          _pname, _iflags)                               \
225 struct clk_regmap aud_##_name = {                                       \
226         .data = &(struct meson_clk_triphase_data) {                     \
227                 .ph0 = {                                                \
228                         .reg_off = (_reg),                              \
229                         .shift   = (_shift0),                           \
230                         .width   = (_width),                            \
231                 },                                                      \
232                 .ph1 = {                                                \
233                         .reg_off = (_reg),                              \
234                         .shift   = (_shift1),                           \
235                         .width   = (_width),                            \
236                 },                                                      \
237                 .ph2 = {                                                \
238                         .reg_off = (_reg),                              \
239                         .shift   = (_shift2),                           \
240                         .width   = (_width),                            \
241                 },                                                      \
242         },                                                              \
243         .hw.init = &(struct clk_init_data) {                            \
244                 .name = "aud_"#_name,                                   \
245                 .ops = &meson_clk_triphase_ops,                         \
246                 .parent_names = (const char *[]) { _pname },            \
247                 .num_parents = 1,                                       \
248                 .flags = CLK_DUTY_CYCLE_PARENT | (_iflags),             \
249         },                                                              \
250 }
251
252 #define AUD_MST_SCLK(_name, _reg)                                       \
253         AUD_TRIPHASE(mst_##_name##_sclk, _reg, 1, 0, 2, 4,              \
254                      "aud_mst_"#_name"_sclk_post_en", CLK_SET_RATE_PARENT)
255
256 static AUD_MST_SCLK(a, AUDIO_MST_A_SCLK_CTRL1);
257 static AUD_MST_SCLK(b, AUDIO_MST_B_SCLK_CTRL1);
258 static AUD_MST_SCLK(c, AUDIO_MST_C_SCLK_CTRL1);
259 static AUD_MST_SCLK(d, AUDIO_MST_D_SCLK_CTRL1);
260 static AUD_MST_SCLK(e, AUDIO_MST_E_SCLK_CTRL1);
261 static AUD_MST_SCLK(f, AUDIO_MST_F_SCLK_CTRL1);
262
263 #define AUD_MST_LRCLK_DIV(_name, _reg)                                  \
264         AUD_SCLK_DIV(mst_##_name##_lrclk_div, _reg, 0, 10, 10, 10,      \
265                      "aud_mst_"#_name"_sclk_post_en", 0)                \
266
267 static AUD_MST_LRCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0);
268 static AUD_MST_LRCLK_DIV(b, AUDIO_MST_B_SCLK_CTRL0);
269 static AUD_MST_LRCLK_DIV(c, AUDIO_MST_C_SCLK_CTRL0);
270 static AUD_MST_LRCLK_DIV(d, AUDIO_MST_D_SCLK_CTRL0);
271 static AUD_MST_LRCLK_DIV(e, AUDIO_MST_E_SCLK_CTRL0);
272 static AUD_MST_LRCLK_DIV(f, AUDIO_MST_F_SCLK_CTRL0);
273
274 #define AUD_MST_LRCLK(_name, _reg)                                      \
275         AUD_TRIPHASE(mst_##_name##_lrclk, _reg, 1, 1, 3, 5,             \
276                      "aud_mst_"#_name"_lrclk_div", CLK_SET_RATE_PARENT)
277
278 static AUD_MST_LRCLK(a, AUDIO_MST_A_SCLK_CTRL1);
279 static AUD_MST_LRCLK(b, AUDIO_MST_B_SCLK_CTRL1);
280 static AUD_MST_LRCLK(c, AUDIO_MST_C_SCLK_CTRL1);
281 static AUD_MST_LRCLK(d, AUDIO_MST_D_SCLK_CTRL1);
282 static AUD_MST_LRCLK(e, AUDIO_MST_E_SCLK_CTRL1);
283 static AUD_MST_LRCLK(f, AUDIO_MST_F_SCLK_CTRL1);
284
285 static const char * const tdm_sclk_parent_names[] = {
286         "aud_mst_a_sclk", "aud_mst_b_sclk", "aud_mst_c_sclk",
287         "aud_mst_d_sclk", "aud_mst_e_sclk", "aud_mst_f_sclk",
288         "aud_slv_sclk0", "aud_slv_sclk1", "aud_slv_sclk2",
289         "aud_slv_sclk3", "aud_slv_sclk4", "aud_slv_sclk5",
290         "aud_slv_sclk6", "aud_slv_sclk7", "aud_slv_sclk8",
291         "aud_slv_sclk9"
292 };
293
294 #define AUD_TDM_SCLK_MUX(_name, _reg)                           \
295         AUD_MUX(tdm##_name##_sclk_sel, _reg, 0xf, 24,           \
296                     CLK_MUX_ROUND_CLOSEST,                      \
297                     tdm_sclk_parent_names, 0)
298
299 static AUD_TDM_SCLK_MUX(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
300 static AUD_TDM_SCLK_MUX(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
301 static AUD_TDM_SCLK_MUX(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
302 static AUD_TDM_SCLK_MUX(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
303 static AUD_TDM_SCLK_MUX(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
304 static AUD_TDM_SCLK_MUX(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
305 static AUD_TDM_SCLK_MUX(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
306
307 #define AUD_TDM_SCLK_PRE_EN(_name, _reg)                                \
308         AUD_GATE(tdm##_name##_sclk_pre_en, _reg, 31,                    \
309                  "aud_tdm"#_name"_sclk_sel", CLK_SET_RATE_PARENT)
310
311 static AUD_TDM_SCLK_PRE_EN(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
312 static AUD_TDM_SCLK_PRE_EN(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
313 static AUD_TDM_SCLK_PRE_EN(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
314 static AUD_TDM_SCLK_PRE_EN(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
315 static AUD_TDM_SCLK_PRE_EN(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
316 static AUD_TDM_SCLK_PRE_EN(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
317 static AUD_TDM_SCLK_PRE_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
318
319 #define AUD_TDM_SCLK_POST_EN(_name, _reg)                               \
320         AUD_GATE(tdm##_name##_sclk_post_en, _reg, 30,                   \
321                  "aud_tdm"#_name"_sclk_pre_en", CLK_SET_RATE_PARENT)
322
323 static AUD_TDM_SCLK_POST_EN(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
324 static AUD_TDM_SCLK_POST_EN(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
325 static AUD_TDM_SCLK_POST_EN(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
326 static AUD_TDM_SCLK_POST_EN(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
327 static AUD_TDM_SCLK_POST_EN(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
328 static AUD_TDM_SCLK_POST_EN(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
329 static AUD_TDM_SCLK_POST_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
330
331 #define AUD_TDM_SCLK(_name, _reg)                                       \
332         struct clk_regmap aud_tdm##_name##_sclk = {                     \
333         .data = &(struct meson_clk_phase_data) {                        \
334                 .ph = {                                                 \
335                         .reg_off = (_reg),                              \
336                         .shift   = 29,                                  \
337                         .width   = 1,                                   \
338                 },                                                      \
339         },                                                              \
340         .hw.init = &(struct clk_init_data) {                            \
341                 .name = "aud_tdm"#_name"_sclk",                         \
342                 .ops = &meson_clk_phase_ops,                            \
343                 .parent_names = (const char *[])                        \
344                 { "aud_tdm"#_name"_sclk_post_en" },                     \
345                 .num_parents = 1,                                       \
346                 .flags = CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT,   \
347         },                                                              \
348 }
349
350 static AUD_TDM_SCLK(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
351 static AUD_TDM_SCLK(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
352 static AUD_TDM_SCLK(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
353 static AUD_TDM_SCLK(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
354 static AUD_TDM_SCLK(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
355 static AUD_TDM_SCLK(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
356 static AUD_TDM_SCLK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
357
358 static const char * const tdm_lrclk_parent_names[] = {
359         "aud_mst_a_lrclk", "aud_mst_b_lrclk", "aud_mst_c_lrclk",
360         "aud_mst_d_lrclk", "aud_mst_e_lrclk", "aud_mst_f_lrclk",
361         "aud_slv_lrclk0", "aud_slv_lrclk1", "aud_slv_lrclk2",
362         "aud_slv_lrclk3", "aud_slv_lrclk4", "aud_slv_lrclk5",
363         "aud_slv_lrclk6", "aud_slv_lrclk7", "aud_slv_lrclk8",
364         "aud_slv_lrclk9"
365 };
366
367 #define AUD_TDM_LRLCK(_name, _reg)                     \
368         AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20,     \
369                 CLK_MUX_ROUND_CLOSEST,                 \
370                 tdm_lrclk_parent_names, 0)
371
372 static AUD_TDM_LRLCK(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
373 static AUD_TDM_LRLCK(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
374 static AUD_TDM_LRLCK(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
375 static AUD_TDM_LRLCK(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
376 static AUD_TDM_LRLCK(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
377 static AUD_TDM_LRLCK(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
378 static AUD_TDM_LRLCK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
379
380 /*
381  * Array of all clocks provided by this provider
382  * The input clocks of the controller will be populated at runtime
383  */
384 static struct clk_hw_onecell_data axg_audio_hw_onecell_data = {
385         .hws = {
386                 [AUD_CLKID_DDR_ARB]             = &aud_ddr_arb.hw,
387                 [AUD_CLKID_PDM]                 = &aud_pdm.hw,
388                 [AUD_CLKID_TDMIN_A]             = &aud_tdmin_a.hw,
389                 [AUD_CLKID_TDMIN_B]             = &aud_tdmin_b.hw,
390                 [AUD_CLKID_TDMIN_C]             = &aud_tdmin_c.hw,
391                 [AUD_CLKID_TDMIN_LB]            = &aud_tdmin_lb.hw,
392                 [AUD_CLKID_TDMOUT_A]            = &aud_tdmout_a.hw,
393                 [AUD_CLKID_TDMOUT_B]            = &aud_tdmout_b.hw,
394                 [AUD_CLKID_TDMOUT_C]            = &aud_tdmout_c.hw,
395                 [AUD_CLKID_FRDDR_A]             = &aud_frddr_a.hw,
396                 [AUD_CLKID_FRDDR_B]             = &aud_frddr_b.hw,
397                 [AUD_CLKID_FRDDR_C]             = &aud_frddr_c.hw,
398                 [AUD_CLKID_TODDR_A]             = &aud_toddr_a.hw,
399                 [AUD_CLKID_TODDR_B]             = &aud_toddr_b.hw,
400                 [AUD_CLKID_TODDR_C]             = &aud_toddr_c.hw,
401                 [AUD_CLKID_LOOPBACK]            = &aud_loopback.hw,
402                 [AUD_CLKID_SPDIFIN]             = &aud_spdifin.hw,
403                 [AUD_CLKID_SPDIFOUT]            = &aud_spdifout.hw,
404                 [AUD_CLKID_RESAMPLE]            = &aud_resample.hw,
405                 [AUD_CLKID_POWER_DETECT]        = &aud_power_detect.hw,
406                 [AUD_CLKID_MST_A_MCLK_SEL]      = &aud_mst_a_mclk_sel.hw,
407                 [AUD_CLKID_MST_B_MCLK_SEL]      = &aud_mst_b_mclk_sel.hw,
408                 [AUD_CLKID_MST_C_MCLK_SEL]      = &aud_mst_c_mclk_sel.hw,
409                 [AUD_CLKID_MST_D_MCLK_SEL]      = &aud_mst_d_mclk_sel.hw,
410                 [AUD_CLKID_MST_E_MCLK_SEL]      = &aud_mst_e_mclk_sel.hw,
411                 [AUD_CLKID_MST_F_MCLK_SEL]      = &aud_mst_f_mclk_sel.hw,
412                 [AUD_CLKID_MST_A_MCLK_DIV]      = &aud_mst_a_mclk_div.hw,
413                 [AUD_CLKID_MST_B_MCLK_DIV]      = &aud_mst_b_mclk_div.hw,
414                 [AUD_CLKID_MST_C_MCLK_DIV]      = &aud_mst_c_mclk_div.hw,
415                 [AUD_CLKID_MST_D_MCLK_DIV]      = &aud_mst_d_mclk_div.hw,
416                 [AUD_CLKID_MST_E_MCLK_DIV]      = &aud_mst_e_mclk_div.hw,
417                 [AUD_CLKID_MST_F_MCLK_DIV]      = &aud_mst_f_mclk_div.hw,
418                 [AUD_CLKID_MST_A_MCLK]          = &aud_mst_a_mclk.hw,
419                 [AUD_CLKID_MST_B_MCLK]          = &aud_mst_b_mclk.hw,
420                 [AUD_CLKID_MST_C_MCLK]          = &aud_mst_c_mclk.hw,
421                 [AUD_CLKID_MST_D_MCLK]          = &aud_mst_d_mclk.hw,
422                 [AUD_CLKID_MST_E_MCLK]          = &aud_mst_e_mclk.hw,
423                 [AUD_CLKID_MST_F_MCLK]          = &aud_mst_f_mclk.hw,
424                 [AUD_CLKID_SPDIFOUT_CLK_SEL]    = &aud_spdifout_clk_sel.hw,
425                 [AUD_CLKID_SPDIFOUT_CLK_DIV]    = &aud_spdifout_clk_div.hw,
426                 [AUD_CLKID_SPDIFOUT_CLK]        = &aud_spdifout_clk.hw,
427                 [AUD_CLKID_SPDIFIN_CLK_SEL]     = &aud_spdifin_clk_sel.hw,
428                 [AUD_CLKID_SPDIFIN_CLK_DIV]     = &aud_spdifin_clk_div.hw,
429                 [AUD_CLKID_SPDIFIN_CLK]         = &aud_spdifin_clk.hw,
430                 [AUD_CLKID_PDM_DCLK_SEL]        = &aud_pdm_dclk_sel.hw,
431                 [AUD_CLKID_PDM_DCLK_DIV]        = &aud_pdm_dclk_div.hw,
432                 [AUD_CLKID_PDM_DCLK]            = &aud_pdm_dclk.hw,
433                 [AUD_CLKID_PDM_SYSCLK_SEL]      = &aud_pdm_sysclk_sel.hw,
434                 [AUD_CLKID_PDM_SYSCLK_DIV]      = &aud_pdm_sysclk_div.hw,
435                 [AUD_CLKID_PDM_SYSCLK]          = &aud_pdm_sysclk.hw,
436                 [AUD_CLKID_MST_A_SCLK_PRE_EN]   = &aud_mst_a_sclk_pre_en.hw,
437                 [AUD_CLKID_MST_B_SCLK_PRE_EN]   = &aud_mst_b_sclk_pre_en.hw,
438                 [AUD_CLKID_MST_C_SCLK_PRE_EN]   = &aud_mst_c_sclk_pre_en.hw,
439                 [AUD_CLKID_MST_D_SCLK_PRE_EN]   = &aud_mst_d_sclk_pre_en.hw,
440                 [AUD_CLKID_MST_E_SCLK_PRE_EN]   = &aud_mst_e_sclk_pre_en.hw,
441                 [AUD_CLKID_MST_F_SCLK_PRE_EN]   = &aud_mst_f_sclk_pre_en.hw,
442                 [AUD_CLKID_MST_A_SCLK_DIV]      = &aud_mst_a_sclk_div.hw,
443                 [AUD_CLKID_MST_B_SCLK_DIV]      = &aud_mst_b_sclk_div.hw,
444                 [AUD_CLKID_MST_C_SCLK_DIV]      = &aud_mst_c_sclk_div.hw,
445                 [AUD_CLKID_MST_D_SCLK_DIV]      = &aud_mst_d_sclk_div.hw,
446                 [AUD_CLKID_MST_E_SCLK_DIV]      = &aud_mst_e_sclk_div.hw,
447                 [AUD_CLKID_MST_F_SCLK_DIV]      = &aud_mst_f_sclk_div.hw,
448                 [AUD_CLKID_MST_A_SCLK_POST_EN]  = &aud_mst_a_sclk_post_en.hw,
449                 [AUD_CLKID_MST_B_SCLK_POST_EN]  = &aud_mst_b_sclk_post_en.hw,
450                 [AUD_CLKID_MST_C_SCLK_POST_EN]  = &aud_mst_c_sclk_post_en.hw,
451                 [AUD_CLKID_MST_D_SCLK_POST_EN]  = &aud_mst_d_sclk_post_en.hw,
452                 [AUD_CLKID_MST_E_SCLK_POST_EN]  = &aud_mst_e_sclk_post_en.hw,
453                 [AUD_CLKID_MST_F_SCLK_POST_EN]  = &aud_mst_f_sclk_post_en.hw,
454                 [AUD_CLKID_MST_A_SCLK]          = &aud_mst_a_sclk.hw,
455                 [AUD_CLKID_MST_B_SCLK]          = &aud_mst_b_sclk.hw,
456                 [AUD_CLKID_MST_C_SCLK]          = &aud_mst_c_sclk.hw,
457                 [AUD_CLKID_MST_D_SCLK]          = &aud_mst_d_sclk.hw,
458                 [AUD_CLKID_MST_E_SCLK]          = &aud_mst_e_sclk.hw,
459                 [AUD_CLKID_MST_F_SCLK]          = &aud_mst_f_sclk.hw,
460                 [AUD_CLKID_MST_A_LRCLK_DIV]     = &aud_mst_a_lrclk_div.hw,
461                 [AUD_CLKID_MST_B_LRCLK_DIV]     = &aud_mst_b_lrclk_div.hw,
462                 [AUD_CLKID_MST_C_LRCLK_DIV]     = &aud_mst_c_lrclk_div.hw,
463                 [AUD_CLKID_MST_D_LRCLK_DIV]     = &aud_mst_d_lrclk_div.hw,
464                 [AUD_CLKID_MST_E_LRCLK_DIV]     = &aud_mst_e_lrclk_div.hw,
465                 [AUD_CLKID_MST_F_LRCLK_DIV]     = &aud_mst_f_lrclk_div.hw,
466                 [AUD_CLKID_MST_A_LRCLK]         = &aud_mst_a_lrclk.hw,
467                 [AUD_CLKID_MST_B_LRCLK]         = &aud_mst_b_lrclk.hw,
468                 [AUD_CLKID_MST_C_LRCLK]         = &aud_mst_c_lrclk.hw,
469                 [AUD_CLKID_MST_D_LRCLK]         = &aud_mst_d_lrclk.hw,
470                 [AUD_CLKID_MST_E_LRCLK]         = &aud_mst_e_lrclk.hw,
471                 [AUD_CLKID_MST_F_LRCLK]         = &aud_mst_f_lrclk.hw,
472                 [AUD_CLKID_TDMIN_A_SCLK_SEL]    = &aud_tdmin_a_sclk_sel.hw,
473                 [AUD_CLKID_TDMIN_B_SCLK_SEL]    = &aud_tdmin_b_sclk_sel.hw,
474                 [AUD_CLKID_TDMIN_C_SCLK_SEL]    = &aud_tdmin_c_sclk_sel.hw,
475                 [AUD_CLKID_TDMIN_LB_SCLK_SEL]   = &aud_tdmin_lb_sclk_sel.hw,
476                 [AUD_CLKID_TDMOUT_A_SCLK_SEL]   = &aud_tdmout_a_sclk_sel.hw,
477                 [AUD_CLKID_TDMOUT_B_SCLK_SEL]   = &aud_tdmout_b_sclk_sel.hw,
478                 [AUD_CLKID_TDMOUT_C_SCLK_SEL]   = &aud_tdmout_c_sclk_sel.hw,
479                 [AUD_CLKID_TDMIN_A_SCLK_PRE_EN] = &aud_tdmin_a_sclk_pre_en.hw,
480                 [AUD_CLKID_TDMIN_B_SCLK_PRE_EN] = &aud_tdmin_b_sclk_pre_en.hw,
481                 [AUD_CLKID_TDMIN_C_SCLK_PRE_EN] = &aud_tdmin_c_sclk_pre_en.hw,
482                 [AUD_CLKID_TDMIN_LB_SCLK_PRE_EN] = &aud_tdmin_lb_sclk_pre_en.hw,
483                 [AUD_CLKID_TDMOUT_A_SCLK_PRE_EN] = &aud_tdmout_a_sclk_pre_en.hw,
484                 [AUD_CLKID_TDMOUT_B_SCLK_PRE_EN] = &aud_tdmout_b_sclk_pre_en.hw,
485                 [AUD_CLKID_TDMOUT_C_SCLK_PRE_EN] = &aud_tdmout_c_sclk_pre_en.hw,
486                 [AUD_CLKID_TDMIN_A_SCLK_POST_EN] = &aud_tdmin_a_sclk_post_en.hw,
487                 [AUD_CLKID_TDMIN_B_SCLK_POST_EN] = &aud_tdmin_b_sclk_post_en.hw,
488                 [AUD_CLKID_TDMIN_C_SCLK_POST_EN] = &aud_tdmin_c_sclk_post_en.hw,
489                 [AUD_CLKID_TDMIN_LB_SCLK_POST_EN] = &aud_tdmin_lb_sclk_post_en.hw,
490                 [AUD_CLKID_TDMOUT_A_SCLK_POST_EN] = &aud_tdmout_a_sclk_post_en.hw,
491                 [AUD_CLKID_TDMOUT_B_SCLK_POST_EN] = &aud_tdmout_b_sclk_post_en.hw,
492                 [AUD_CLKID_TDMOUT_C_SCLK_POST_EN] = &aud_tdmout_c_sclk_post_en.hw,
493                 [AUD_CLKID_TDMIN_A_SCLK]        = &aud_tdmin_a_sclk.hw,
494                 [AUD_CLKID_TDMIN_B_SCLK]        = &aud_tdmin_b_sclk.hw,
495                 [AUD_CLKID_TDMIN_C_SCLK]        = &aud_tdmin_c_sclk.hw,
496                 [AUD_CLKID_TDMIN_LB_SCLK]       = &aud_tdmin_lb_sclk.hw,
497                 [AUD_CLKID_TDMOUT_A_SCLK]       = &aud_tdmout_a_sclk.hw,
498                 [AUD_CLKID_TDMOUT_B_SCLK]       = &aud_tdmout_b_sclk.hw,
499                 [AUD_CLKID_TDMOUT_C_SCLK]       = &aud_tdmout_c_sclk.hw,
500                 [AUD_CLKID_TDMIN_A_LRCLK]       = &aud_tdmin_a_lrclk.hw,
501                 [AUD_CLKID_TDMIN_B_LRCLK]       = &aud_tdmin_b_lrclk.hw,
502                 [AUD_CLKID_TDMIN_C_LRCLK]       = &aud_tdmin_c_lrclk.hw,
503                 [AUD_CLKID_TDMIN_LB_LRCLK]      = &aud_tdmin_lb_lrclk.hw,
504                 [AUD_CLKID_TDMOUT_A_LRCLK]      = &aud_tdmout_a_lrclk.hw,
505                 [AUD_CLKID_TDMOUT_B_LRCLK]      = &aud_tdmout_b_lrclk.hw,
506                 [AUD_CLKID_TDMOUT_C_LRCLK]      = &aud_tdmout_c_lrclk.hw,
507                 [NR_CLKS] = NULL,
508         },
509         .num = NR_CLKS,
510 };
511
512 /* Convenience table to populate regmap in .probe() */
513 static struct clk_regmap *const aud_clk_regmaps[] = {
514         &aud_ddr_arb,
515         &aud_pdm,
516         &aud_tdmin_a,
517         &aud_tdmin_b,
518         &aud_tdmin_c,
519         &aud_tdmin_lb,
520         &aud_tdmout_a,
521         &aud_tdmout_b,
522         &aud_tdmout_c,
523         &aud_frddr_a,
524         &aud_frddr_b,
525         &aud_frddr_c,
526         &aud_toddr_a,
527         &aud_toddr_b,
528         &aud_toddr_c,
529         &aud_loopback,
530         &aud_spdifin,
531         &aud_spdifout,
532         &aud_resample,
533         &aud_power_detect,
534         &aud_mst_a_mclk_sel,
535         &aud_mst_b_mclk_sel,
536         &aud_mst_c_mclk_sel,
537         &aud_mst_d_mclk_sel,
538         &aud_mst_e_mclk_sel,
539         &aud_mst_f_mclk_sel,
540         &aud_mst_a_mclk_div,
541         &aud_mst_b_mclk_div,
542         &aud_mst_c_mclk_div,
543         &aud_mst_d_mclk_div,
544         &aud_mst_e_mclk_div,
545         &aud_mst_f_mclk_div,
546         &aud_mst_a_mclk,
547         &aud_mst_b_mclk,
548         &aud_mst_c_mclk,
549         &aud_mst_d_mclk,
550         &aud_mst_e_mclk,
551         &aud_mst_f_mclk,
552         &aud_spdifout_clk_sel,
553         &aud_spdifout_clk_div,
554         &aud_spdifout_clk,
555         &aud_spdifin_clk_sel,
556         &aud_spdifin_clk_div,
557         &aud_spdifin_clk,
558         &aud_pdm_dclk_sel,
559         &aud_pdm_dclk_div,
560         &aud_pdm_dclk,
561         &aud_pdm_sysclk_sel,
562         &aud_pdm_sysclk_div,
563         &aud_pdm_sysclk,
564         &aud_mst_a_sclk_pre_en,
565         &aud_mst_b_sclk_pre_en,
566         &aud_mst_c_sclk_pre_en,
567         &aud_mst_d_sclk_pre_en,
568         &aud_mst_e_sclk_pre_en,
569         &aud_mst_f_sclk_pre_en,
570         &aud_mst_a_sclk_div,
571         &aud_mst_b_sclk_div,
572         &aud_mst_c_sclk_div,
573         &aud_mst_d_sclk_div,
574         &aud_mst_e_sclk_div,
575         &aud_mst_f_sclk_div,
576         &aud_mst_a_sclk_post_en,
577         &aud_mst_b_sclk_post_en,
578         &aud_mst_c_sclk_post_en,
579         &aud_mst_d_sclk_post_en,
580         &aud_mst_e_sclk_post_en,
581         &aud_mst_f_sclk_post_en,
582         &aud_mst_a_sclk,
583         &aud_mst_b_sclk,
584         &aud_mst_c_sclk,
585         &aud_mst_d_sclk,
586         &aud_mst_e_sclk,
587         &aud_mst_f_sclk,
588         &aud_mst_a_lrclk_div,
589         &aud_mst_b_lrclk_div,
590         &aud_mst_c_lrclk_div,
591         &aud_mst_d_lrclk_div,
592         &aud_mst_e_lrclk_div,
593         &aud_mst_f_lrclk_div,
594         &aud_mst_a_lrclk,
595         &aud_mst_b_lrclk,
596         &aud_mst_c_lrclk,
597         &aud_mst_d_lrclk,
598         &aud_mst_e_lrclk,
599         &aud_mst_f_lrclk,
600         &aud_tdmin_a_sclk_sel,
601         &aud_tdmin_b_sclk_sel,
602         &aud_tdmin_c_sclk_sel,
603         &aud_tdmin_lb_sclk_sel,
604         &aud_tdmout_a_sclk_sel,
605         &aud_tdmout_b_sclk_sel,
606         &aud_tdmout_c_sclk_sel,
607         &aud_tdmin_a_sclk_pre_en,
608         &aud_tdmin_b_sclk_pre_en,
609         &aud_tdmin_c_sclk_pre_en,
610         &aud_tdmin_lb_sclk_pre_en,
611         &aud_tdmout_a_sclk_pre_en,
612         &aud_tdmout_b_sclk_pre_en,
613         &aud_tdmout_c_sclk_pre_en,
614         &aud_tdmin_a_sclk_post_en,
615         &aud_tdmin_b_sclk_post_en,
616         &aud_tdmin_c_sclk_post_en,
617         &aud_tdmin_lb_sclk_post_en,
618         &aud_tdmout_a_sclk_post_en,
619         &aud_tdmout_b_sclk_post_en,
620         &aud_tdmout_c_sclk_post_en,
621         &aud_tdmin_a_sclk,
622         &aud_tdmin_b_sclk,
623         &aud_tdmin_c_sclk,
624         &aud_tdmin_lb_sclk,
625         &aud_tdmout_a_sclk,
626         &aud_tdmout_b_sclk,
627         &aud_tdmout_c_sclk,
628         &aud_tdmin_a_lrclk,
629         &aud_tdmin_b_lrclk,
630         &aud_tdmin_c_lrclk,
631         &aud_tdmin_lb_lrclk,
632         &aud_tdmout_a_lrclk,
633         &aud_tdmout_b_lrclk,
634         &aud_tdmout_c_lrclk,
635 };
636
637 static int devm_clk_get_enable(struct device *dev, char *id)
638 {
639         struct clk *clk;
640         int ret;
641
642         clk = devm_clk_get(dev, id);
643         if (IS_ERR(clk)) {
644                 ret = PTR_ERR(clk);
645                 if (ret != -EPROBE_DEFER)
646                         dev_err(dev, "failed to get %s", id);
647                 return ret;
648         }
649
650         ret = clk_prepare_enable(clk);
651         if (ret) {
652                 dev_err(dev, "failed to enable %s", id);
653                 return ret;
654         }
655
656         ret = devm_add_action_or_reset(dev,
657                                        (void(*)(void *))clk_disable_unprepare,
658                                        clk);
659         if (ret) {
660                 dev_err(dev, "failed to add reset action on %s", id);
661                 return ret;
662         }
663
664         return 0;
665 }
666
667 static int axg_register_clk_hw_input(struct device *dev,
668                                      const char *name)
669 {
670         char *clk_name;
671         struct clk_hw *hw;
672         int err = 0;
673
674         clk_name = kasprintf(GFP_KERNEL, "aud_%s", name);
675         if (!clk_name)
676                 return -ENOMEM;
677
678         hw = meson_clk_hw_register_input(dev, name, clk_name, 0);
679         if (IS_ERR(hw)) {
680                 /* It is ok if an input clock is missing */
681                 if (PTR_ERR(hw) == -ENOENT) {
682                         dev_dbg(dev, "%s not provided", name);
683                 } else {
684                         err = PTR_ERR(hw);
685                         if (err != -EPROBE_DEFER)
686                                 dev_err(dev, "failed to get %s clock", name);
687                 }
688         }
689
690         kfree(clk_name);
691         return err;
692 }
693
694 static int axg_register_clk_hw_inputs(struct device *dev,
695                                       const char *basename,
696                                       unsigned int count)
697 {
698         char *name;
699         int i, ret;
700
701         for (i = 0; i < count; i++) {
702                 name = kasprintf(GFP_KERNEL, "%s%d", basename, i);
703                 if (!name)
704                         return -ENOMEM;
705
706                 ret = axg_register_clk_hw_input(dev, name);
707                 kfree(name);
708                 if (ret)
709                         return ret;
710         }
711
712         return 0;
713 }
714
715 static const struct regmap_config axg_audio_regmap_cfg = {
716         .reg_bits       = 32,
717         .val_bits       = 32,
718         .reg_stride     = 4,
719         .max_register   = AUDIO_CLK_PDMIN_CTRL1,
720 };
721
722 static int axg_audio_clkc_probe(struct platform_device *pdev)
723 {
724         struct device *dev = &pdev->dev;
725         struct regmap *map;
726         struct resource *res;
727         void __iomem *regs;
728         struct clk_hw *hw;
729         int ret, i;
730
731         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
732         regs = devm_ioremap_resource(dev, res);
733         if (IS_ERR(regs))
734                 return PTR_ERR(regs);
735
736         map = devm_regmap_init_mmio(dev, regs, &axg_audio_regmap_cfg);
737         if (IS_ERR(map)) {
738                 dev_err(dev, "failed to init regmap: %ld\n", PTR_ERR(map));
739                 return PTR_ERR(map);
740         }
741
742         /* Get the mandatory peripheral clock */
743         ret = devm_clk_get_enable(dev, "pclk");
744         if (ret)
745                 return ret;
746
747         ret = device_reset(dev);
748         if (ret) {
749                 dev_err(dev, "failed to reset device\n");
750                 return ret;
751         }
752
753         /* Register the peripheral input clock */
754         hw = meson_clk_hw_register_input(dev, "pclk", "audio_pclk", 0);
755         if (IS_ERR(hw))
756                 return PTR_ERR(hw);
757
758         /* Register optional input master clocks */
759         ret = axg_register_clk_hw_inputs(dev, "mst_in",
760                                          AUD_MST_IN_COUNT);
761         if (ret)
762                 return ret;
763
764         /* Register optional input slave sclks */
765         ret = axg_register_clk_hw_inputs(dev, "slv_sclk",
766                                          AUD_SLV_SCLK_COUNT);
767         if (ret)
768                 return ret;
769
770         /* Register optional input slave lrclks */
771         ret = axg_register_clk_hw_inputs(dev, "slv_lrclk",
772                                          AUD_SLV_LRCLK_COUNT);
773         if (ret)
774                 return ret;
775
776         /* Populate regmap for the regmap backed clocks */
777         for (i = 0; i < ARRAY_SIZE(aud_clk_regmaps); i++)
778                 aud_clk_regmaps[i]->map = map;
779
780         /* Take care to skip the registered input clocks */
781         for (i = AUD_CLKID_DDR_ARB; i < axg_audio_hw_onecell_data.num; i++) {
782                 hw = axg_audio_hw_onecell_data.hws[i];
783                 /* array might be sparse */
784                 if (!hw)
785                         continue;
786
787                 ret = devm_clk_hw_register(dev, hw);
788                 if (ret) {
789                         dev_err(dev, "failed to register clock %s\n",
790                                 hw->init->name);
791                         return ret;
792                 }
793         }
794
795         return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
796                                            &axg_audio_hw_onecell_data);
797 }
798
799 static const struct of_device_id clkc_match_table[] = {
800         { .compatible = "amlogic,axg-audio-clkc" },
801         {}
802 };
803 MODULE_DEVICE_TABLE(of, clkc_match_table);
804
805 static struct platform_driver axg_audio_driver = {
806         .probe          = axg_audio_clkc_probe,
807         .driver         = {
808                 .name   = "axg-audio-clkc",
809                 .of_match_table = clkc_match_table,
810         },
811 };
812 module_platform_driver(axg_audio_driver);
813
814 MODULE_DESCRIPTION("Amlogic A113x Audio Clock driver");
815 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
816 MODULE_LICENSE("GPL v2");