1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
3 * Copyright (c) 2018 BayLibre, SAS.
4 * Author: Jerome Brunet <jbrunet@baylibre.com>
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>
17 #include "clkc-audio.h"
18 #include "axg-audio.h"
20 #define AXG_MST_IN_COUNT 8
21 #define AXG_SLV_SCLK_COUNT 10
22 #define AXG_SLV_LRCLK_COUNT 10
24 #define AXG_AUD_GATE(_name, _reg, _bit, _pname, _iflags) \
25 struct clk_regmap axg_##_name = { \
26 .data = &(struct clk_regmap_gate_data){ \
30 .hw.init = &(struct clk_init_data) { \
31 .name = "axg_"#_name, \
32 .ops = &clk_regmap_gate_ops, \
33 .parent_names = (const char *[]){ _pname }, \
35 .flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \
39 #define AXG_AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pnames, _iflags) \
40 struct clk_regmap axg_##_name = { \
41 .data = &(struct clk_regmap_mux_data){ \
47 .hw.init = &(struct clk_init_data){ \
48 .name = "axg_"#_name, \
49 .ops = &clk_regmap_mux_ops, \
50 .parent_names = (_pnames), \
51 .num_parents = ARRAY_SIZE(_pnames), \
52 .flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \
56 #define AXG_AUD_DIV(_name, _reg, _shift, _width, _dflags, _pname, _iflags) \
57 struct clk_regmap axg_##_name = { \
58 .data = &(struct clk_regmap_div_data){ \
64 .hw.init = &(struct clk_init_data){ \
65 .name = "axg_"#_name, \
66 .ops = &clk_regmap_divider_ops, \
67 .parent_names = (const char *[]) { _pname }, \
73 #define AXG_PCLK_GATE(_name, _bit) \
74 AXG_AUD_GATE(_name, AUDIO_CLK_GATE_EN, _bit, "axg_audio_pclk", 0)
76 /* Audio peripheral clocks */
77 static AXG_PCLK_GATE(ddr_arb
, 0);
78 static AXG_PCLK_GATE(pdm
, 1);
79 static AXG_PCLK_GATE(tdmin_a
, 2);
80 static AXG_PCLK_GATE(tdmin_b
, 3);
81 static AXG_PCLK_GATE(tdmin_c
, 4);
82 static AXG_PCLK_GATE(tdmin_lb
, 5);
83 static AXG_PCLK_GATE(tdmout_a
, 6);
84 static AXG_PCLK_GATE(tdmout_b
, 7);
85 static AXG_PCLK_GATE(tdmout_c
, 8);
86 static AXG_PCLK_GATE(frddr_a
, 9);
87 static AXG_PCLK_GATE(frddr_b
, 10);
88 static AXG_PCLK_GATE(frddr_c
, 11);
89 static AXG_PCLK_GATE(toddr_a
, 12);
90 static AXG_PCLK_GATE(toddr_b
, 13);
91 static AXG_PCLK_GATE(toddr_c
, 14);
92 static AXG_PCLK_GATE(loopback
, 15);
93 static AXG_PCLK_GATE(spdifin
, 16);
94 static AXG_PCLK_GATE(spdifout
, 17);
95 static AXG_PCLK_GATE(resample
, 18);
96 static AXG_PCLK_GATE(power_detect
, 19);
98 /* Audio Master Clocks */
99 static const char * const mst_mux_parent_names
[] = {
100 "axg_mst_in0", "axg_mst_in1", "axg_mst_in2", "axg_mst_in3",
101 "axg_mst_in4", "axg_mst_in5", "axg_mst_in6", "axg_mst_in7",
104 #define AXG_MST_MUX(_name, _reg, _flag) \
105 AXG_AUD_MUX(_name##_sel, _reg, 0x7, 24, _flag, \
106 mst_mux_parent_names, CLK_SET_RATE_PARENT)
108 #define AXG_MST_MCLK_MUX(_name, _reg) \
109 AXG_MST_MUX(_name, _reg, CLK_MUX_ROUND_CLOSEST)
111 #define AXG_MST_SYS_MUX(_name, _reg) \
112 AXG_MST_MUX(_name, _reg, 0)
114 static AXG_MST_MCLK_MUX(mst_a_mclk
, AUDIO_MCLK_A_CTRL
);
115 static AXG_MST_MCLK_MUX(mst_b_mclk
, AUDIO_MCLK_B_CTRL
);
116 static AXG_MST_MCLK_MUX(mst_c_mclk
, AUDIO_MCLK_C_CTRL
);
117 static AXG_MST_MCLK_MUX(mst_d_mclk
, AUDIO_MCLK_D_CTRL
);
118 static AXG_MST_MCLK_MUX(mst_e_mclk
, AUDIO_MCLK_E_CTRL
);
119 static AXG_MST_MCLK_MUX(mst_f_mclk
, AUDIO_MCLK_F_CTRL
);
120 static AXG_MST_MCLK_MUX(spdifout_clk
, AUDIO_CLK_SPDIFOUT_CTRL
);
121 static AXG_MST_MCLK_MUX(pdm_dclk
, AUDIO_CLK_PDMIN_CTRL0
);
122 static AXG_MST_SYS_MUX(spdifin_clk
, AUDIO_CLK_SPDIFIN_CTRL
);
123 static AXG_MST_SYS_MUX(pdm_sysclk
, AUDIO_CLK_PDMIN_CTRL1
);
125 #define AXG_MST_DIV(_name, _reg, _flag) \
126 AXG_AUD_DIV(_name##_div, _reg, 0, 16, _flag, \
127 "axg_"#_name"_sel", CLK_SET_RATE_PARENT) \
129 #define AXG_MST_MCLK_DIV(_name, _reg) \
130 AXG_MST_DIV(_name, _reg, CLK_DIVIDER_ROUND_CLOSEST)
132 #define AXG_MST_SYS_DIV(_name, _reg) \
133 AXG_MST_DIV(_name, _reg, 0)
135 static AXG_MST_MCLK_DIV(mst_a_mclk
, AUDIO_MCLK_A_CTRL
);
136 static AXG_MST_MCLK_DIV(mst_b_mclk
, AUDIO_MCLK_B_CTRL
);
137 static AXG_MST_MCLK_DIV(mst_c_mclk
, AUDIO_MCLK_C_CTRL
);
138 static AXG_MST_MCLK_DIV(mst_d_mclk
, AUDIO_MCLK_D_CTRL
);
139 static AXG_MST_MCLK_DIV(mst_e_mclk
, AUDIO_MCLK_E_CTRL
);
140 static AXG_MST_MCLK_DIV(mst_f_mclk
, AUDIO_MCLK_F_CTRL
);
141 static AXG_MST_MCLK_DIV(spdifout_clk
, AUDIO_CLK_SPDIFOUT_CTRL
);
142 static AXG_MST_MCLK_DIV(pdm_dclk
, AUDIO_CLK_PDMIN_CTRL0
);
143 static AXG_MST_SYS_DIV(spdifin_clk
, AUDIO_CLK_SPDIFIN_CTRL
);
144 static AXG_MST_SYS_DIV(pdm_sysclk
, AUDIO_CLK_PDMIN_CTRL1
);
146 #define AXG_MST_MCLK_GATE(_name, _reg) \
147 AXG_AUD_GATE(_name, _reg, 31, "axg_"#_name"_div", \
150 static AXG_MST_MCLK_GATE(mst_a_mclk
, AUDIO_MCLK_A_CTRL
);
151 static AXG_MST_MCLK_GATE(mst_b_mclk
, AUDIO_MCLK_B_CTRL
);
152 static AXG_MST_MCLK_GATE(mst_c_mclk
, AUDIO_MCLK_C_CTRL
);
153 static AXG_MST_MCLK_GATE(mst_d_mclk
, AUDIO_MCLK_D_CTRL
);
154 static AXG_MST_MCLK_GATE(mst_e_mclk
, AUDIO_MCLK_E_CTRL
);
155 static AXG_MST_MCLK_GATE(mst_f_mclk
, AUDIO_MCLK_F_CTRL
);
156 static AXG_MST_MCLK_GATE(spdifout_clk
, AUDIO_CLK_SPDIFOUT_CTRL
);
157 static AXG_MST_MCLK_GATE(spdifin_clk
, AUDIO_CLK_SPDIFIN_CTRL
);
158 static AXG_MST_MCLK_GATE(pdm_dclk
, AUDIO_CLK_PDMIN_CTRL0
);
159 static AXG_MST_MCLK_GATE(pdm_sysclk
, AUDIO_CLK_PDMIN_CTRL1
);
162 #define AXG_MST_SCLK_PRE_EN(_name, _reg) \
163 AXG_AUD_GATE(mst_##_name##_sclk_pre_en, _reg, 31, \
164 "axg_mst_"#_name"_mclk", 0)
166 static AXG_MST_SCLK_PRE_EN(a
, AUDIO_MST_A_SCLK_CTRL0
);
167 static AXG_MST_SCLK_PRE_EN(b
, AUDIO_MST_B_SCLK_CTRL0
);
168 static AXG_MST_SCLK_PRE_EN(c
, AUDIO_MST_C_SCLK_CTRL0
);
169 static AXG_MST_SCLK_PRE_EN(d
, AUDIO_MST_D_SCLK_CTRL0
);
170 static AXG_MST_SCLK_PRE_EN(e
, AUDIO_MST_E_SCLK_CTRL0
);
171 static AXG_MST_SCLK_PRE_EN(f
, AUDIO_MST_F_SCLK_CTRL0
);
173 #define AXG_AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width, \
174 _hi_shift, _hi_width, _pname, _iflags) \
175 struct clk_regmap axg_##_name = { \
176 .data = &(struct meson_sclk_div_data) { \
179 .shift = (_div_shift), \
180 .width = (_div_width), \
184 .shift = (_hi_shift), \
185 .width = (_hi_width), \
188 .hw.init = &(struct clk_init_data) { \
189 .name = "axg_"#_name, \
190 .ops = &meson_sclk_div_ops, \
191 .parent_names = (const char *[]) { _pname }, \
193 .flags = (_iflags), \
197 #define AXG_MST_SCLK_DIV(_name, _reg) \
198 AXG_AUD_SCLK_DIV(mst_##_name##_sclk_div, _reg, 20, 10, 0, 0, \
199 "axg_mst_"#_name"_sclk_pre_en", \
202 static AXG_MST_SCLK_DIV(a
, AUDIO_MST_A_SCLK_CTRL0
);
203 static AXG_MST_SCLK_DIV(b
, AUDIO_MST_B_SCLK_CTRL0
);
204 static AXG_MST_SCLK_DIV(c
, AUDIO_MST_C_SCLK_CTRL0
);
205 static AXG_MST_SCLK_DIV(d
, AUDIO_MST_D_SCLK_CTRL0
);
206 static AXG_MST_SCLK_DIV(e
, AUDIO_MST_E_SCLK_CTRL0
);
207 static AXG_MST_SCLK_DIV(f
, AUDIO_MST_F_SCLK_CTRL0
);
209 #define AXG_MST_SCLK_POST_EN(_name, _reg) \
210 AXG_AUD_GATE(mst_##_name##_sclk_post_en, _reg, 30, \
211 "axg_mst_"#_name"_sclk_div", CLK_SET_RATE_PARENT)
213 static AXG_MST_SCLK_POST_EN(a
, AUDIO_MST_A_SCLK_CTRL0
);
214 static AXG_MST_SCLK_POST_EN(b
, AUDIO_MST_B_SCLK_CTRL0
);
215 static AXG_MST_SCLK_POST_EN(c
, AUDIO_MST_C_SCLK_CTRL0
);
216 static AXG_MST_SCLK_POST_EN(d
, AUDIO_MST_D_SCLK_CTRL0
);
217 static AXG_MST_SCLK_POST_EN(e
, AUDIO_MST_E_SCLK_CTRL0
);
218 static AXG_MST_SCLK_POST_EN(f
, AUDIO_MST_F_SCLK_CTRL0
);
220 #define AXG_AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2, \
222 struct clk_regmap axg_##_name = { \
223 .data = &(struct meson_clk_triphase_data) { \
226 .shift = (_shift0), \
231 .shift = (_shift1), \
236 .shift = (_shift2), \
240 .hw.init = &(struct clk_init_data) { \
241 .name = "axg_"#_name, \
242 .ops = &meson_clk_triphase_ops, \
243 .parent_names = (const char *[]) { _pname }, \
245 .flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \
249 #define AXG_MST_SCLK(_name, _reg) \
250 AXG_AUD_TRIPHASE(mst_##_name##_sclk, _reg, 1, 0, 2, 4, \
251 "axg_mst_"#_name"_sclk_post_en", CLK_SET_RATE_PARENT)
253 static AXG_MST_SCLK(a
, AUDIO_MST_A_SCLK_CTRL1
);
254 static AXG_MST_SCLK(b
, AUDIO_MST_B_SCLK_CTRL1
);
255 static AXG_MST_SCLK(c
, AUDIO_MST_C_SCLK_CTRL1
);
256 static AXG_MST_SCLK(d
, AUDIO_MST_D_SCLK_CTRL1
);
257 static AXG_MST_SCLK(e
, AUDIO_MST_E_SCLK_CTRL1
);
258 static AXG_MST_SCLK(f
, AUDIO_MST_F_SCLK_CTRL1
);
260 #define AXG_MST_LRCLK_DIV(_name, _reg) \
261 AXG_AUD_SCLK_DIV(mst_##_name##_lrclk_div, _reg, 0, 10, 10, 10, \
262 "axg_mst_"#_name"_sclk_post_en", 0) \
264 static AXG_MST_LRCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0);
265 static AXG_MST_LRCLK_DIV(b
, AUDIO_MST_B_SCLK_CTRL0
);
266 static AXG_MST_LRCLK_DIV(c
, AUDIO_MST_C_SCLK_CTRL0
);
267 static AXG_MST_LRCLK_DIV(d
, AUDIO_MST_D_SCLK_CTRL0
);
268 static AXG_MST_LRCLK_DIV(e
, AUDIO_MST_E_SCLK_CTRL0
);
269 static AXG_MST_LRCLK_DIV(f
, AUDIO_MST_F_SCLK_CTRL0
);
271 #define AXG_MST_LRCLK(_name, _reg) \
272 AXG_AUD_TRIPHASE(mst_##_name##_lrclk, _reg, 1, 1, 3, 5, \
273 "axg_mst_"#_name"_lrclk_div", CLK_SET_RATE_PARENT)
275 static AXG_MST_LRCLK(a
, AUDIO_MST_A_SCLK_CTRL1
);
276 static AXG_MST_LRCLK(b
, AUDIO_MST_B_SCLK_CTRL1
);
277 static AXG_MST_LRCLK(c
, AUDIO_MST_C_SCLK_CTRL1
);
278 static AXG_MST_LRCLK(d
, AUDIO_MST_D_SCLK_CTRL1
);
279 static AXG_MST_LRCLK(e
, AUDIO_MST_E_SCLK_CTRL1
);
280 static AXG_MST_LRCLK(f
, AUDIO_MST_F_SCLK_CTRL1
);
282 static const char * const tdm_sclk_parent_names
[] = {
283 "axg_mst_a_sclk", "axg_mst_b_sclk", "axg_mst_c_sclk",
284 "axg_mst_d_sclk", "axg_mst_e_sclk", "axg_mst_f_sclk",
285 "axg_slv_sclk0", "axg_slv_sclk1", "axg_slv_sclk2",
286 "axg_slv_sclk3", "axg_slv_sclk4", "axg_slv_sclk5",
287 "axg_slv_sclk6", "axg_slv_sclk7", "axg_slv_sclk8",
291 #define AXG_TDM_SCLK_MUX(_name, _reg) \
292 AXG_AUD_MUX(tdm##_name##_sclk_sel, _reg, 0xf, 24, \
293 CLK_MUX_ROUND_CLOSEST, \
294 tdm_sclk_parent_names, 0)
296 static AXG_TDM_SCLK_MUX(in_a
, AUDIO_CLK_TDMIN_A_CTRL
);
297 static AXG_TDM_SCLK_MUX(in_b
, AUDIO_CLK_TDMIN_B_CTRL
);
298 static AXG_TDM_SCLK_MUX(in_c
, AUDIO_CLK_TDMIN_C_CTRL
);
299 static AXG_TDM_SCLK_MUX(in_lb
, AUDIO_CLK_TDMIN_LB_CTRL
);
300 static AXG_TDM_SCLK_MUX(out_a
, AUDIO_CLK_TDMOUT_A_CTRL
);
301 static AXG_TDM_SCLK_MUX(out_b
, AUDIO_CLK_TDMOUT_B_CTRL
);
302 static AXG_TDM_SCLK_MUX(out_c
, AUDIO_CLK_TDMOUT_C_CTRL
);
304 #define AXG_TDM_SCLK_PRE_EN(_name, _reg) \
305 AXG_AUD_GATE(tdm##_name##_sclk_pre_en, _reg, 31, \
306 "axg_tdm"#_name"_sclk_sel", CLK_SET_RATE_PARENT)
308 static AXG_TDM_SCLK_PRE_EN(in_a
, AUDIO_CLK_TDMIN_A_CTRL
);
309 static AXG_TDM_SCLK_PRE_EN(in_b
, AUDIO_CLK_TDMIN_B_CTRL
);
310 static AXG_TDM_SCLK_PRE_EN(in_c
, AUDIO_CLK_TDMIN_C_CTRL
);
311 static AXG_TDM_SCLK_PRE_EN(in_lb
, AUDIO_CLK_TDMIN_LB_CTRL
);
312 static AXG_TDM_SCLK_PRE_EN(out_a
, AUDIO_CLK_TDMOUT_A_CTRL
);
313 static AXG_TDM_SCLK_PRE_EN(out_b
, AUDIO_CLK_TDMOUT_B_CTRL
);
314 static AXG_TDM_SCLK_PRE_EN(out_c
, AUDIO_CLK_TDMOUT_C_CTRL
);
316 #define AXG_TDM_SCLK_POST_EN(_name, _reg) \
317 AXG_AUD_GATE(tdm##_name##_sclk_post_en, _reg, 30, \
318 "axg_tdm"#_name"_sclk_pre_en", CLK_SET_RATE_PARENT)
320 static AXG_TDM_SCLK_POST_EN(in_a
, AUDIO_CLK_TDMIN_A_CTRL
);
321 static AXG_TDM_SCLK_POST_EN(in_b
, AUDIO_CLK_TDMIN_B_CTRL
);
322 static AXG_TDM_SCLK_POST_EN(in_c
, AUDIO_CLK_TDMIN_C_CTRL
);
323 static AXG_TDM_SCLK_POST_EN(in_lb
, AUDIO_CLK_TDMIN_LB_CTRL
);
324 static AXG_TDM_SCLK_POST_EN(out_a
, AUDIO_CLK_TDMOUT_A_CTRL
);
325 static AXG_TDM_SCLK_POST_EN(out_b
, AUDIO_CLK_TDMOUT_B_CTRL
);
326 static AXG_TDM_SCLK_POST_EN(out_c
, AUDIO_CLK_TDMOUT_C_CTRL
);
328 #define AXG_TDM_SCLK(_name, _reg) \
329 struct clk_regmap axg_tdm##_name##_sclk = { \
330 .data = &(struct meson_clk_phase_data) { \
337 .hw.init = &(struct clk_init_data) { \
338 .name = "axg_tdm"#_name"_sclk", \
339 .ops = &meson_clk_phase_ops, \
340 .parent_names = (const char *[]) \
341 { "axg_tdm"#_name"_sclk_post_en" }, \
343 .flags = CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT, \
347 static AXG_TDM_SCLK(in_a
, AUDIO_CLK_TDMIN_A_CTRL
);
348 static AXG_TDM_SCLK(in_b
, AUDIO_CLK_TDMIN_B_CTRL
);
349 static AXG_TDM_SCLK(in_c
, AUDIO_CLK_TDMIN_C_CTRL
);
350 static AXG_TDM_SCLK(in_lb
, AUDIO_CLK_TDMIN_LB_CTRL
);
351 static AXG_TDM_SCLK(out_a
, AUDIO_CLK_TDMOUT_A_CTRL
);
352 static AXG_TDM_SCLK(out_b
, AUDIO_CLK_TDMOUT_B_CTRL
);
353 static AXG_TDM_SCLK(out_c
, AUDIO_CLK_TDMOUT_C_CTRL
);
355 static const char * const tdm_lrclk_parent_names
[] = {
356 "axg_mst_a_lrclk", "axg_mst_b_lrclk", "axg_mst_c_lrclk",
357 "axg_mst_d_lrclk", "axg_mst_e_lrclk", "axg_mst_f_lrclk",
358 "axg_slv_lrclk0", "axg_slv_lrclk1", "axg_slv_lrclk2",
359 "axg_slv_lrclk3", "axg_slv_lrclk4", "axg_slv_lrclk5",
360 "axg_slv_lrclk6", "axg_slv_lrclk7", "axg_slv_lrclk8",
364 #define AXG_TDM_LRLCK(_name, _reg) \
365 AXG_AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20, \
366 CLK_MUX_ROUND_CLOSEST, \
367 tdm_lrclk_parent_names, 0)
369 static AXG_TDM_LRLCK(in_a
, AUDIO_CLK_TDMIN_A_CTRL
);
370 static AXG_TDM_LRLCK(in_b
, AUDIO_CLK_TDMIN_B_CTRL
);
371 static AXG_TDM_LRLCK(in_c
, AUDIO_CLK_TDMIN_C_CTRL
);
372 static AXG_TDM_LRLCK(in_lb
, AUDIO_CLK_TDMIN_LB_CTRL
);
373 static AXG_TDM_LRLCK(out_a
, AUDIO_CLK_TDMOUT_A_CTRL
);
374 static AXG_TDM_LRLCK(out_b
, AUDIO_CLK_TDMOUT_B_CTRL
);
375 static AXG_TDM_LRLCK(out_c
, AUDIO_CLK_TDMOUT_C_CTRL
);
378 * Array of all clocks provided by this provider
379 * The input clocks of the controller will be populated at runtime
381 static struct clk_hw_onecell_data axg_audio_hw_onecell_data
= {
383 [AUD_CLKID_DDR_ARB
] = &axg_ddr_arb
.hw
,
384 [AUD_CLKID_PDM
] = &axg_pdm
.hw
,
385 [AUD_CLKID_TDMIN_A
] = &axg_tdmin_a
.hw
,
386 [AUD_CLKID_TDMIN_B
] = &axg_tdmin_b
.hw
,
387 [AUD_CLKID_TDMIN_C
] = &axg_tdmin_c
.hw
,
388 [AUD_CLKID_TDMIN_LB
] = &axg_tdmin_lb
.hw
,
389 [AUD_CLKID_TDMOUT_A
] = &axg_tdmout_a
.hw
,
390 [AUD_CLKID_TDMOUT_B
] = &axg_tdmout_b
.hw
,
391 [AUD_CLKID_TDMOUT_C
] = &axg_tdmout_c
.hw
,
392 [AUD_CLKID_FRDDR_A
] = &axg_frddr_a
.hw
,
393 [AUD_CLKID_FRDDR_B
] = &axg_frddr_b
.hw
,
394 [AUD_CLKID_FRDDR_C
] = &axg_frddr_c
.hw
,
395 [AUD_CLKID_TODDR_A
] = &axg_toddr_a
.hw
,
396 [AUD_CLKID_TODDR_B
] = &axg_toddr_b
.hw
,
397 [AUD_CLKID_TODDR_C
] = &axg_toddr_c
.hw
,
398 [AUD_CLKID_LOOPBACK
] = &axg_loopback
.hw
,
399 [AUD_CLKID_SPDIFIN
] = &axg_spdifin
.hw
,
400 [AUD_CLKID_SPDIFOUT
] = &axg_spdifout
.hw
,
401 [AUD_CLKID_RESAMPLE
] = &axg_resample
.hw
,
402 [AUD_CLKID_POWER_DETECT
] = &axg_power_detect
.hw
,
403 [AUD_CLKID_MST_A_MCLK_SEL
] = &axg_mst_a_mclk_sel
.hw
,
404 [AUD_CLKID_MST_B_MCLK_SEL
] = &axg_mst_b_mclk_sel
.hw
,
405 [AUD_CLKID_MST_C_MCLK_SEL
] = &axg_mst_c_mclk_sel
.hw
,
406 [AUD_CLKID_MST_D_MCLK_SEL
] = &axg_mst_d_mclk_sel
.hw
,
407 [AUD_CLKID_MST_E_MCLK_SEL
] = &axg_mst_e_mclk_sel
.hw
,
408 [AUD_CLKID_MST_F_MCLK_SEL
] = &axg_mst_f_mclk_sel
.hw
,
409 [AUD_CLKID_MST_A_MCLK_DIV
] = &axg_mst_a_mclk_div
.hw
,
410 [AUD_CLKID_MST_B_MCLK_DIV
] = &axg_mst_b_mclk_div
.hw
,
411 [AUD_CLKID_MST_C_MCLK_DIV
] = &axg_mst_c_mclk_div
.hw
,
412 [AUD_CLKID_MST_D_MCLK_DIV
] = &axg_mst_d_mclk_div
.hw
,
413 [AUD_CLKID_MST_E_MCLK_DIV
] = &axg_mst_e_mclk_div
.hw
,
414 [AUD_CLKID_MST_F_MCLK_DIV
] = &axg_mst_f_mclk_div
.hw
,
415 [AUD_CLKID_MST_A_MCLK
] = &axg_mst_a_mclk
.hw
,
416 [AUD_CLKID_MST_B_MCLK
] = &axg_mst_b_mclk
.hw
,
417 [AUD_CLKID_MST_C_MCLK
] = &axg_mst_c_mclk
.hw
,
418 [AUD_CLKID_MST_D_MCLK
] = &axg_mst_d_mclk
.hw
,
419 [AUD_CLKID_MST_E_MCLK
] = &axg_mst_e_mclk
.hw
,
420 [AUD_CLKID_MST_F_MCLK
] = &axg_mst_f_mclk
.hw
,
421 [AUD_CLKID_SPDIFOUT_CLK_SEL
] = &axg_spdifout_clk_sel
.hw
,
422 [AUD_CLKID_SPDIFOUT_CLK_DIV
] = &axg_spdifout_clk_div
.hw
,
423 [AUD_CLKID_SPDIFOUT_CLK
] = &axg_spdifout_clk
.hw
,
424 [AUD_CLKID_SPDIFIN_CLK_SEL
] = &axg_spdifin_clk_sel
.hw
,
425 [AUD_CLKID_SPDIFIN_CLK_DIV
] = &axg_spdifin_clk_div
.hw
,
426 [AUD_CLKID_SPDIFIN_CLK
] = &axg_spdifin_clk
.hw
,
427 [AUD_CLKID_PDM_DCLK_SEL
] = &axg_pdm_dclk_sel
.hw
,
428 [AUD_CLKID_PDM_DCLK_DIV
] = &axg_pdm_dclk_div
.hw
,
429 [AUD_CLKID_PDM_DCLK
] = &axg_pdm_dclk
.hw
,
430 [AUD_CLKID_PDM_SYSCLK_SEL
] = &axg_pdm_sysclk_sel
.hw
,
431 [AUD_CLKID_PDM_SYSCLK_DIV
] = &axg_pdm_sysclk_div
.hw
,
432 [AUD_CLKID_PDM_SYSCLK
] = &axg_pdm_sysclk
.hw
,
433 [AUD_CLKID_MST_A_SCLK_PRE_EN
] = &axg_mst_a_sclk_pre_en
.hw
,
434 [AUD_CLKID_MST_B_SCLK_PRE_EN
] = &axg_mst_b_sclk_pre_en
.hw
,
435 [AUD_CLKID_MST_C_SCLK_PRE_EN
] = &axg_mst_c_sclk_pre_en
.hw
,
436 [AUD_CLKID_MST_D_SCLK_PRE_EN
] = &axg_mst_d_sclk_pre_en
.hw
,
437 [AUD_CLKID_MST_E_SCLK_PRE_EN
] = &axg_mst_e_sclk_pre_en
.hw
,
438 [AUD_CLKID_MST_F_SCLK_PRE_EN
] = &axg_mst_f_sclk_pre_en
.hw
,
439 [AUD_CLKID_MST_A_SCLK_DIV
] = &axg_mst_a_sclk_div
.hw
,
440 [AUD_CLKID_MST_B_SCLK_DIV
] = &axg_mst_b_sclk_div
.hw
,
441 [AUD_CLKID_MST_C_SCLK_DIV
] = &axg_mst_c_sclk_div
.hw
,
442 [AUD_CLKID_MST_D_SCLK_DIV
] = &axg_mst_d_sclk_div
.hw
,
443 [AUD_CLKID_MST_E_SCLK_DIV
] = &axg_mst_e_sclk_div
.hw
,
444 [AUD_CLKID_MST_F_SCLK_DIV
] = &axg_mst_f_sclk_div
.hw
,
445 [AUD_CLKID_MST_A_SCLK_POST_EN
] = &axg_mst_a_sclk_post_en
.hw
,
446 [AUD_CLKID_MST_B_SCLK_POST_EN
] = &axg_mst_b_sclk_post_en
.hw
,
447 [AUD_CLKID_MST_C_SCLK_POST_EN
] = &axg_mst_c_sclk_post_en
.hw
,
448 [AUD_CLKID_MST_D_SCLK_POST_EN
] = &axg_mst_d_sclk_post_en
.hw
,
449 [AUD_CLKID_MST_E_SCLK_POST_EN
] = &axg_mst_e_sclk_post_en
.hw
,
450 [AUD_CLKID_MST_F_SCLK_POST_EN
] = &axg_mst_f_sclk_post_en
.hw
,
451 [AUD_CLKID_MST_A_SCLK
] = &axg_mst_a_sclk
.hw
,
452 [AUD_CLKID_MST_B_SCLK
] = &axg_mst_b_sclk
.hw
,
453 [AUD_CLKID_MST_C_SCLK
] = &axg_mst_c_sclk
.hw
,
454 [AUD_CLKID_MST_D_SCLK
] = &axg_mst_d_sclk
.hw
,
455 [AUD_CLKID_MST_E_SCLK
] = &axg_mst_e_sclk
.hw
,
456 [AUD_CLKID_MST_F_SCLK
] = &axg_mst_f_sclk
.hw
,
457 [AUD_CLKID_MST_A_LRCLK_DIV
] = &axg_mst_a_lrclk_div
.hw
,
458 [AUD_CLKID_MST_B_LRCLK_DIV
] = &axg_mst_b_lrclk_div
.hw
,
459 [AUD_CLKID_MST_C_LRCLK_DIV
] = &axg_mst_c_lrclk_div
.hw
,
460 [AUD_CLKID_MST_D_LRCLK_DIV
] = &axg_mst_d_lrclk_div
.hw
,
461 [AUD_CLKID_MST_E_LRCLK_DIV
] = &axg_mst_e_lrclk_div
.hw
,
462 [AUD_CLKID_MST_F_LRCLK_DIV
] = &axg_mst_f_lrclk_div
.hw
,
463 [AUD_CLKID_MST_A_LRCLK
] = &axg_mst_a_lrclk
.hw
,
464 [AUD_CLKID_MST_B_LRCLK
] = &axg_mst_b_lrclk
.hw
,
465 [AUD_CLKID_MST_C_LRCLK
] = &axg_mst_c_lrclk
.hw
,
466 [AUD_CLKID_MST_D_LRCLK
] = &axg_mst_d_lrclk
.hw
,
467 [AUD_CLKID_MST_E_LRCLK
] = &axg_mst_e_lrclk
.hw
,
468 [AUD_CLKID_MST_F_LRCLK
] = &axg_mst_f_lrclk
.hw
,
469 [AUD_CLKID_TDMIN_A_SCLK_SEL
] = &axg_tdmin_a_sclk_sel
.hw
,
470 [AUD_CLKID_TDMIN_B_SCLK_SEL
] = &axg_tdmin_b_sclk_sel
.hw
,
471 [AUD_CLKID_TDMIN_C_SCLK_SEL
] = &axg_tdmin_c_sclk_sel
.hw
,
472 [AUD_CLKID_TDMIN_LB_SCLK_SEL
] = &axg_tdmin_lb_sclk_sel
.hw
,
473 [AUD_CLKID_TDMOUT_A_SCLK_SEL
] = &axg_tdmout_a_sclk_sel
.hw
,
474 [AUD_CLKID_TDMOUT_B_SCLK_SEL
] = &axg_tdmout_b_sclk_sel
.hw
,
475 [AUD_CLKID_TDMOUT_C_SCLK_SEL
] = &axg_tdmout_c_sclk_sel
.hw
,
476 [AUD_CLKID_TDMIN_A_SCLK_PRE_EN
] = &axg_tdmin_a_sclk_pre_en
.hw
,
477 [AUD_CLKID_TDMIN_B_SCLK_PRE_EN
] = &axg_tdmin_b_sclk_pre_en
.hw
,
478 [AUD_CLKID_TDMIN_C_SCLK_PRE_EN
] = &axg_tdmin_c_sclk_pre_en
.hw
,
479 [AUD_CLKID_TDMIN_LB_SCLK_PRE_EN
] = &axg_tdmin_lb_sclk_pre_en
.hw
,
480 [AUD_CLKID_TDMOUT_A_SCLK_PRE_EN
] = &axg_tdmout_a_sclk_pre_en
.hw
,
481 [AUD_CLKID_TDMOUT_B_SCLK_PRE_EN
] = &axg_tdmout_b_sclk_pre_en
.hw
,
482 [AUD_CLKID_TDMOUT_C_SCLK_PRE_EN
] = &axg_tdmout_c_sclk_pre_en
.hw
,
483 [AUD_CLKID_TDMIN_A_SCLK_POST_EN
] = &axg_tdmin_a_sclk_post_en
.hw
,
484 [AUD_CLKID_TDMIN_B_SCLK_POST_EN
] = &axg_tdmin_b_sclk_post_en
.hw
,
485 [AUD_CLKID_TDMIN_C_SCLK_POST_EN
] = &axg_tdmin_c_sclk_post_en
.hw
,
486 [AUD_CLKID_TDMIN_LB_SCLK_POST_EN
] = &axg_tdmin_lb_sclk_post_en
.hw
,
487 [AUD_CLKID_TDMOUT_A_SCLK_POST_EN
] = &axg_tdmout_a_sclk_post_en
.hw
,
488 [AUD_CLKID_TDMOUT_B_SCLK_POST_EN
] = &axg_tdmout_b_sclk_post_en
.hw
,
489 [AUD_CLKID_TDMOUT_C_SCLK_POST_EN
] = &axg_tdmout_c_sclk_post_en
.hw
,
490 [AUD_CLKID_TDMIN_A_SCLK
] = &axg_tdmin_a_sclk
.hw
,
491 [AUD_CLKID_TDMIN_B_SCLK
] = &axg_tdmin_b_sclk
.hw
,
492 [AUD_CLKID_TDMIN_C_SCLK
] = &axg_tdmin_c_sclk
.hw
,
493 [AUD_CLKID_TDMIN_LB_SCLK
] = &axg_tdmin_lb_sclk
.hw
,
494 [AUD_CLKID_TDMOUT_A_SCLK
] = &axg_tdmout_a_sclk
.hw
,
495 [AUD_CLKID_TDMOUT_B_SCLK
] = &axg_tdmout_b_sclk
.hw
,
496 [AUD_CLKID_TDMOUT_C_SCLK
] = &axg_tdmout_c_sclk
.hw
,
497 [AUD_CLKID_TDMIN_A_LRCLK
] = &axg_tdmin_a_lrclk
.hw
,
498 [AUD_CLKID_TDMIN_B_LRCLK
] = &axg_tdmin_b_lrclk
.hw
,
499 [AUD_CLKID_TDMIN_C_LRCLK
] = &axg_tdmin_c_lrclk
.hw
,
500 [AUD_CLKID_TDMIN_LB_LRCLK
] = &axg_tdmin_lb_lrclk
.hw
,
501 [AUD_CLKID_TDMOUT_A_LRCLK
] = &axg_tdmout_a_lrclk
.hw
,
502 [AUD_CLKID_TDMOUT_B_LRCLK
] = &axg_tdmout_b_lrclk
.hw
,
503 [AUD_CLKID_TDMOUT_C_LRCLK
] = &axg_tdmout_c_lrclk
.hw
,
509 /* Convenience table to populate regmap in .probe() */
510 static struct clk_regmap
*const axg_audio_clk_regmaps
[] = {
549 &axg_spdifout_clk_sel
,
550 &axg_spdifout_clk_div
,
552 &axg_spdifin_clk_sel
,
553 &axg_spdifin_clk_div
,
561 &axg_mst_a_sclk_pre_en
,
562 &axg_mst_b_sclk_pre_en
,
563 &axg_mst_c_sclk_pre_en
,
564 &axg_mst_d_sclk_pre_en
,
565 &axg_mst_e_sclk_pre_en
,
566 &axg_mst_f_sclk_pre_en
,
573 &axg_mst_a_sclk_post_en
,
574 &axg_mst_b_sclk_post_en
,
575 &axg_mst_c_sclk_post_en
,
576 &axg_mst_d_sclk_post_en
,
577 &axg_mst_e_sclk_post_en
,
578 &axg_mst_f_sclk_post_en
,
585 &axg_mst_a_lrclk_div
,
586 &axg_mst_b_lrclk_div
,
587 &axg_mst_c_lrclk_div
,
588 &axg_mst_d_lrclk_div
,
589 &axg_mst_e_lrclk_div
,
590 &axg_mst_f_lrclk_div
,
597 &axg_tdmin_a_sclk_sel
,
598 &axg_tdmin_b_sclk_sel
,
599 &axg_tdmin_c_sclk_sel
,
600 &axg_tdmin_lb_sclk_sel
,
601 &axg_tdmout_a_sclk_sel
,
602 &axg_tdmout_b_sclk_sel
,
603 &axg_tdmout_c_sclk_sel
,
604 &axg_tdmin_a_sclk_pre_en
,
605 &axg_tdmin_b_sclk_pre_en
,
606 &axg_tdmin_c_sclk_pre_en
,
607 &axg_tdmin_lb_sclk_pre_en
,
608 &axg_tdmout_a_sclk_pre_en
,
609 &axg_tdmout_b_sclk_pre_en
,
610 &axg_tdmout_c_sclk_pre_en
,
611 &axg_tdmin_a_sclk_post_en
,
612 &axg_tdmin_b_sclk_post_en
,
613 &axg_tdmin_c_sclk_post_en
,
614 &axg_tdmin_lb_sclk_post_en
,
615 &axg_tdmout_a_sclk_post_en
,
616 &axg_tdmout_b_sclk_post_en
,
617 &axg_tdmout_c_sclk_post_en
,
634 static int devm_clk_get_enable(struct device
*dev
, char *id
)
639 clk
= devm_clk_get(dev
, id
);
642 if (ret
!= -EPROBE_DEFER
)
643 dev_err(dev
, "failed to get %s", id
);
647 ret
= clk_prepare_enable(clk
);
649 dev_err(dev
, "failed to enable %s", id
);
653 ret
= devm_add_action_or_reset(dev
,
654 (void(*)(void *))clk_disable_unprepare
,
657 dev_err(dev
, "failed to add reset action on %s", id
);
664 static int axg_register_clk_hw_input(struct device
*dev
,
672 clk_name
= kasprintf(GFP_KERNEL
, "axg_%s", name
);
676 hw
= meson_clk_hw_register_input(dev
, name
, clk_name
, 0);
678 /* It is ok if an input clock is missing */
679 if (PTR_ERR(hw
) == -ENOENT
) {
680 dev_dbg(dev
, "%s not provided", name
);
683 if (err
!= -EPROBE_DEFER
)
684 dev_err(dev
, "failed to get %s clock", name
);
687 axg_audio_hw_onecell_data
.hws
[clkid
] = hw
;
694 static int axg_register_clk_hw_inputs(struct device
*dev
,
695 const char *basename
,
702 for (i
= 0; i
< count
; i
++) {
703 name
= kasprintf(GFP_KERNEL
, "%s%d", basename
, i
);
707 ret
= axg_register_clk_hw_input(dev
, name
, clkid
+ i
);
716 static const struct regmap_config axg_audio_regmap_cfg
= {
720 .max_register
= AUDIO_CLK_PDMIN_CTRL1
,
723 static int axg_audio_clkc_probe(struct platform_device
*pdev
)
725 struct device
*dev
= &pdev
->dev
;
727 struct resource
*res
;
732 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
733 regs
= devm_ioremap_resource(dev
, res
);
735 return PTR_ERR(regs
);
737 map
= devm_regmap_init_mmio(dev
, regs
, &axg_audio_regmap_cfg
);
739 dev_err(dev
, "failed to init regmap: %ld\n", PTR_ERR(map
));
743 /* Get the mandatory peripheral clock */
744 ret
= devm_clk_get_enable(dev
, "pclk");
748 ret
= device_reset(dev
);
750 dev_err(dev
, "failed to reset device\n");
754 /* Register the peripheral input clock */
755 hw
= meson_clk_hw_register_input(dev
, "pclk", "axg_audio_pclk", 0);
759 axg_audio_hw_onecell_data
.hws
[AUD_CLKID_PCLK
] = hw
;
761 /* Register optional input master clocks */
762 ret
= axg_register_clk_hw_inputs(dev
, "mst_in",
768 /* Register optional input slave sclks */
769 ret
= axg_register_clk_hw_inputs(dev
, "slv_sclk",
771 AUD_CLKID_SLV_SCLK0
);
775 /* Register optional input slave lrclks */
776 ret
= axg_register_clk_hw_inputs(dev
, "slv_lrclk",
778 AUD_CLKID_SLV_LRCLK0
);
782 /* Populate regmap for the regmap backed clocks */
783 for (i
= 0; i
< ARRAY_SIZE(axg_audio_clk_regmaps
); i
++)
784 axg_audio_clk_regmaps
[i
]->map
= map
;
786 /* Take care to skip the registered input clocks */
787 for (i
= AUD_CLKID_DDR_ARB
; i
< axg_audio_hw_onecell_data
.num
; i
++) {
788 hw
= axg_audio_hw_onecell_data
.hws
[i
];
789 /* array might be sparse */
793 ret
= devm_clk_hw_register(dev
, hw
);
795 dev_err(dev
, "failed to register clock %s\n",
801 return devm_of_clk_add_hw_provider(dev
, of_clk_hw_onecell_get
,
802 &axg_audio_hw_onecell_data
);
805 static const struct of_device_id clkc_match_table
[] = {
806 { .compatible
= "amlogic,axg-audio-clkc" },
809 MODULE_DEVICE_TABLE(of
, clkc_match_table
);
811 static struct platform_driver axg_audio_driver
= {
812 .probe
= axg_audio_clkc_probe
,
814 .name
= "axg-audio-clkc",
815 .of_match_table
= clkc_match_table
,
818 module_platform_driver(axg_audio_driver
);
820 MODULE_DESCRIPTION("Amlogic A113x Audio Clock driver");
821 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
822 MODULE_LICENSE("GPL v2");