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_MCLK_MUX(_name, _reg) \
105 AXG_AUD_MUX(_name##_sel, _reg, 0x7, 24, CLK_MUX_ROUND_CLOSEST, \
106 mst_mux_parent_names, CLK_SET_RATE_PARENT)
108 static AXG_MST_MCLK_MUX(mst_a_mclk
, AUDIO_MCLK_A_CTRL
);
109 static AXG_MST_MCLK_MUX(mst_b_mclk
, AUDIO_MCLK_B_CTRL
);
110 static AXG_MST_MCLK_MUX(mst_c_mclk
, AUDIO_MCLK_C_CTRL
);
111 static AXG_MST_MCLK_MUX(mst_d_mclk
, AUDIO_MCLK_D_CTRL
);
112 static AXG_MST_MCLK_MUX(mst_e_mclk
, AUDIO_MCLK_E_CTRL
);
113 static AXG_MST_MCLK_MUX(mst_f_mclk
, AUDIO_MCLK_F_CTRL
);
114 static AXG_MST_MCLK_MUX(spdifout_clk
, AUDIO_CLK_SPDIFOUT_CTRL
);
115 static AXG_MST_MCLK_MUX(spdifin_clk
, AUDIO_CLK_SPDIFIN_CTRL
);
116 static AXG_MST_MCLK_MUX(pdm_dclk
, AUDIO_CLK_PDMIN_CTRL0
);
117 static AXG_MST_MCLK_MUX(pdm_sysclk
, AUDIO_CLK_PDMIN_CTRL1
);
119 #define AXG_MST_MCLK_DIV(_name, _reg) \
120 AXG_AUD_DIV(_name##_div, _reg, 0, 16, CLK_DIVIDER_ROUND_CLOSEST, \
121 "axg_"#_name"_sel", CLK_SET_RATE_PARENT) \
123 static AXG_MST_MCLK_DIV(mst_a_mclk, AUDIO_MCLK_A_CTRL);
124 static AXG_MST_MCLK_DIV(mst_b_mclk
, AUDIO_MCLK_B_CTRL
);
125 static AXG_MST_MCLK_DIV(mst_c_mclk
, AUDIO_MCLK_C_CTRL
);
126 static AXG_MST_MCLK_DIV(mst_d_mclk
, AUDIO_MCLK_D_CTRL
);
127 static AXG_MST_MCLK_DIV(mst_e_mclk
, AUDIO_MCLK_E_CTRL
);
128 static AXG_MST_MCLK_DIV(mst_f_mclk
, AUDIO_MCLK_F_CTRL
);
129 static AXG_MST_MCLK_DIV(spdifout_clk
, AUDIO_CLK_SPDIFOUT_CTRL
);
130 static AXG_MST_MCLK_DIV(spdifin_clk
, AUDIO_CLK_SPDIFIN_CTRL
);
131 static AXG_MST_MCLK_DIV(pdm_dclk
, AUDIO_CLK_PDMIN_CTRL0
);
132 static AXG_MST_MCLK_DIV(pdm_sysclk
, AUDIO_CLK_PDMIN_CTRL1
);
134 #define AXG_MST_MCLK_GATE(_name, _reg) \
135 AXG_AUD_GATE(_name, _reg, 31, "axg_"#_name"_div", \
138 static AXG_MST_MCLK_GATE(mst_a_mclk
, AUDIO_MCLK_A_CTRL
);
139 static AXG_MST_MCLK_GATE(mst_b_mclk
, AUDIO_MCLK_B_CTRL
);
140 static AXG_MST_MCLK_GATE(mst_c_mclk
, AUDIO_MCLK_C_CTRL
);
141 static AXG_MST_MCLK_GATE(mst_d_mclk
, AUDIO_MCLK_D_CTRL
);
142 static AXG_MST_MCLK_GATE(mst_e_mclk
, AUDIO_MCLK_E_CTRL
);
143 static AXG_MST_MCLK_GATE(mst_f_mclk
, AUDIO_MCLK_F_CTRL
);
144 static AXG_MST_MCLK_GATE(spdifout_clk
, AUDIO_CLK_SPDIFOUT_CTRL
);
145 static AXG_MST_MCLK_GATE(spdifin_clk
, AUDIO_CLK_SPDIFIN_CTRL
);
146 static AXG_MST_MCLK_GATE(pdm_dclk
, AUDIO_CLK_PDMIN_CTRL0
);
147 static AXG_MST_MCLK_GATE(pdm_sysclk
, AUDIO_CLK_PDMIN_CTRL1
);
150 #define AXG_MST_SCLK_PRE_EN(_name, _reg) \
151 AXG_AUD_GATE(mst_##_name##_sclk_pre_en, _reg, 31, \
152 "axg_mst_"#_name"_mclk", 0)
154 static AXG_MST_SCLK_PRE_EN(a
, AUDIO_MST_A_SCLK_CTRL0
);
155 static AXG_MST_SCLK_PRE_EN(b
, AUDIO_MST_B_SCLK_CTRL0
);
156 static AXG_MST_SCLK_PRE_EN(c
, AUDIO_MST_C_SCLK_CTRL0
);
157 static AXG_MST_SCLK_PRE_EN(d
, AUDIO_MST_D_SCLK_CTRL0
);
158 static AXG_MST_SCLK_PRE_EN(e
, AUDIO_MST_E_SCLK_CTRL0
);
159 static AXG_MST_SCLK_PRE_EN(f
, AUDIO_MST_F_SCLK_CTRL0
);
161 #define AXG_AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width, \
162 _hi_shift, _hi_width, _pname, _iflags) \
163 struct clk_regmap axg_##_name = { \
164 .data = &(struct meson_sclk_div_data) { \
167 .shift = (_div_shift), \
168 .width = (_div_width), \
172 .shift = (_hi_shift), \
173 .width = (_hi_width), \
176 .hw.init = &(struct clk_init_data) { \
177 .name = "axg_"#_name, \
178 .ops = &meson_sclk_div_ops, \
179 .parent_names = (const char *[]) { _pname }, \
181 .flags = (_iflags), \
185 #define AXG_MST_SCLK_DIV(_name, _reg) \
186 AXG_AUD_SCLK_DIV(mst_##_name##_sclk_div, _reg, 20, 10, 0, 0, \
187 "axg_mst_"#_name"_sclk_pre_en", \
190 static AXG_MST_SCLK_DIV(a
, AUDIO_MST_A_SCLK_CTRL0
);
191 static AXG_MST_SCLK_DIV(b
, AUDIO_MST_B_SCLK_CTRL0
);
192 static AXG_MST_SCLK_DIV(c
, AUDIO_MST_C_SCLK_CTRL0
);
193 static AXG_MST_SCLK_DIV(d
, AUDIO_MST_D_SCLK_CTRL0
);
194 static AXG_MST_SCLK_DIV(e
, AUDIO_MST_E_SCLK_CTRL0
);
195 static AXG_MST_SCLK_DIV(f
, AUDIO_MST_F_SCLK_CTRL0
);
197 #define AXG_MST_SCLK_POST_EN(_name, _reg) \
198 AXG_AUD_GATE(mst_##_name##_sclk_post_en, _reg, 30, \
199 "axg_mst_"#_name"_sclk_div", CLK_SET_RATE_PARENT)
201 static AXG_MST_SCLK_POST_EN(a
, AUDIO_MST_A_SCLK_CTRL0
);
202 static AXG_MST_SCLK_POST_EN(b
, AUDIO_MST_B_SCLK_CTRL0
);
203 static AXG_MST_SCLK_POST_EN(c
, AUDIO_MST_C_SCLK_CTRL0
);
204 static AXG_MST_SCLK_POST_EN(d
, AUDIO_MST_D_SCLK_CTRL0
);
205 static AXG_MST_SCLK_POST_EN(e
, AUDIO_MST_E_SCLK_CTRL0
);
206 static AXG_MST_SCLK_POST_EN(f
, AUDIO_MST_F_SCLK_CTRL0
);
208 #define AXG_AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2, \
210 struct clk_regmap axg_##_name = { \
211 .data = &(struct meson_clk_triphase_data) { \
214 .shift = (_shift0), \
219 .shift = (_shift1), \
224 .shift = (_shift2), \
228 .hw.init = &(struct clk_init_data) { \
229 .name = "axg_"#_name, \
230 .ops = &meson_clk_triphase_ops, \
231 .parent_names = (const char *[]) { _pname }, \
233 .flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \
237 #define AXG_MST_SCLK(_name, _reg) \
238 AXG_AUD_TRIPHASE(mst_##_name##_sclk, _reg, 1, 0, 2, 4, \
239 "axg_mst_"#_name"_sclk_post_en", CLK_SET_RATE_PARENT)
241 static AXG_MST_SCLK(a
, AUDIO_MST_A_SCLK_CTRL1
);
242 static AXG_MST_SCLK(b
, AUDIO_MST_B_SCLK_CTRL1
);
243 static AXG_MST_SCLK(c
, AUDIO_MST_C_SCLK_CTRL1
);
244 static AXG_MST_SCLK(d
, AUDIO_MST_D_SCLK_CTRL1
);
245 static AXG_MST_SCLK(e
, AUDIO_MST_E_SCLK_CTRL1
);
246 static AXG_MST_SCLK(f
, AUDIO_MST_F_SCLK_CTRL1
);
248 #define AXG_MST_LRCLK_DIV(_name, _reg) \
249 AXG_AUD_SCLK_DIV(mst_##_name##_lrclk_div, _reg, 0, 10, 10, 10, \
250 "axg_mst_"#_name"_sclk_post_en", 0) \
252 static AXG_MST_LRCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0);
253 static AXG_MST_LRCLK_DIV(b
, AUDIO_MST_B_SCLK_CTRL0
);
254 static AXG_MST_LRCLK_DIV(c
, AUDIO_MST_C_SCLK_CTRL0
);
255 static AXG_MST_LRCLK_DIV(d
, AUDIO_MST_D_SCLK_CTRL0
);
256 static AXG_MST_LRCLK_DIV(e
, AUDIO_MST_E_SCLK_CTRL0
);
257 static AXG_MST_LRCLK_DIV(f
, AUDIO_MST_F_SCLK_CTRL0
);
259 #define AXG_MST_LRCLK(_name, _reg) \
260 AXG_AUD_TRIPHASE(mst_##_name##_lrclk, _reg, 1, 1, 3, 5, \
261 "axg_mst_"#_name"_lrclk_div", CLK_SET_RATE_PARENT)
263 static AXG_MST_LRCLK(a
, AUDIO_MST_A_SCLK_CTRL1
);
264 static AXG_MST_LRCLK(b
, AUDIO_MST_B_SCLK_CTRL1
);
265 static AXG_MST_LRCLK(c
, AUDIO_MST_C_SCLK_CTRL1
);
266 static AXG_MST_LRCLK(d
, AUDIO_MST_D_SCLK_CTRL1
);
267 static AXG_MST_LRCLK(e
, AUDIO_MST_E_SCLK_CTRL1
);
268 static AXG_MST_LRCLK(f
, AUDIO_MST_F_SCLK_CTRL1
);
270 static const char * const tdm_sclk_parent_names
[] = {
271 "axg_mst_a_sclk", "axg_mst_b_sclk", "axg_mst_c_sclk",
272 "axg_mst_d_sclk", "axg_mst_e_sclk", "axg_mst_f_sclk",
273 "axg_slv_sclk0", "axg_slv_sclk1", "axg_slv_sclk2",
274 "axg_slv_sclk3", "axg_slv_sclk4", "axg_slv_sclk5",
275 "axg_slv_sclk6", "axg_slv_sclk7", "axg_slv_sclk8",
279 #define AXG_TDM_SCLK_MUX(_name, _reg) \
280 AXG_AUD_MUX(tdm##_name##_sclk_sel, _reg, 0xf, 24, \
281 CLK_MUX_ROUND_CLOSEST, \
282 tdm_sclk_parent_names, 0)
284 static AXG_TDM_SCLK_MUX(in_a
, AUDIO_CLK_TDMIN_A_CTRL
);
285 static AXG_TDM_SCLK_MUX(in_b
, AUDIO_CLK_TDMIN_B_CTRL
);
286 static AXG_TDM_SCLK_MUX(in_c
, AUDIO_CLK_TDMIN_C_CTRL
);
287 static AXG_TDM_SCLK_MUX(in_lb
, AUDIO_CLK_TDMIN_LB_CTRL
);
288 static AXG_TDM_SCLK_MUX(out_a
, AUDIO_CLK_TDMOUT_A_CTRL
);
289 static AXG_TDM_SCLK_MUX(out_b
, AUDIO_CLK_TDMOUT_B_CTRL
);
290 static AXG_TDM_SCLK_MUX(out_c
, AUDIO_CLK_TDMOUT_C_CTRL
);
292 #define AXG_TDM_SCLK_PRE_EN(_name, _reg) \
293 AXG_AUD_GATE(tdm##_name##_sclk_pre_en, _reg, 31, \
294 "axg_tdm"#_name"_sclk_sel", CLK_SET_RATE_PARENT)
296 static AXG_TDM_SCLK_PRE_EN(in_a
, AUDIO_CLK_TDMIN_A_CTRL
);
297 static AXG_TDM_SCLK_PRE_EN(in_b
, AUDIO_CLK_TDMIN_B_CTRL
);
298 static AXG_TDM_SCLK_PRE_EN(in_c
, AUDIO_CLK_TDMIN_C_CTRL
);
299 static AXG_TDM_SCLK_PRE_EN(in_lb
, AUDIO_CLK_TDMIN_LB_CTRL
);
300 static AXG_TDM_SCLK_PRE_EN(out_a
, AUDIO_CLK_TDMOUT_A_CTRL
);
301 static AXG_TDM_SCLK_PRE_EN(out_b
, AUDIO_CLK_TDMOUT_B_CTRL
);
302 static AXG_TDM_SCLK_PRE_EN(out_c
, AUDIO_CLK_TDMOUT_C_CTRL
);
304 #define AXG_TDM_SCLK_POST_EN(_name, _reg) \
305 AXG_AUD_GATE(tdm##_name##_sclk_post_en, _reg, 30, \
306 "axg_tdm"#_name"_sclk_pre_en", CLK_SET_RATE_PARENT)
308 static AXG_TDM_SCLK_POST_EN(in_a
, AUDIO_CLK_TDMIN_A_CTRL
);
309 static AXG_TDM_SCLK_POST_EN(in_b
, AUDIO_CLK_TDMIN_B_CTRL
);
310 static AXG_TDM_SCLK_POST_EN(in_c
, AUDIO_CLK_TDMIN_C_CTRL
);
311 static AXG_TDM_SCLK_POST_EN(in_lb
, AUDIO_CLK_TDMIN_LB_CTRL
);
312 static AXG_TDM_SCLK_POST_EN(out_a
, AUDIO_CLK_TDMOUT_A_CTRL
);
313 static AXG_TDM_SCLK_POST_EN(out_b
, AUDIO_CLK_TDMOUT_B_CTRL
);
314 static AXG_TDM_SCLK_POST_EN(out_c
, AUDIO_CLK_TDMOUT_C_CTRL
);
316 #define AXG_TDM_SCLK(_name, _reg) \
317 struct clk_regmap axg_tdm##_name##_sclk = { \
318 .data = &(struct meson_clk_phase_data) { \
325 .hw.init = &(struct clk_init_data) { \
326 .name = "axg_tdm"#_name"_sclk", \
327 .ops = &meson_clk_phase_ops, \
328 .parent_names = (const char *[]) \
329 { "axg_tdm"#_name"_sclk_post_en" }, \
331 .flags = CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT, \
335 static AXG_TDM_SCLK(in_a
, AUDIO_CLK_TDMIN_A_CTRL
);
336 static AXG_TDM_SCLK(in_b
, AUDIO_CLK_TDMIN_B_CTRL
);
337 static AXG_TDM_SCLK(in_c
, AUDIO_CLK_TDMIN_C_CTRL
);
338 static AXG_TDM_SCLK(in_lb
, AUDIO_CLK_TDMIN_LB_CTRL
);
339 static AXG_TDM_SCLK(out_a
, AUDIO_CLK_TDMOUT_A_CTRL
);
340 static AXG_TDM_SCLK(out_b
, AUDIO_CLK_TDMOUT_B_CTRL
);
341 static AXG_TDM_SCLK(out_c
, AUDIO_CLK_TDMOUT_C_CTRL
);
343 static const char * const tdm_lrclk_parent_names
[] = {
344 "axg_mst_a_lrclk", "axg_mst_b_lrclk", "axg_mst_c_lrclk",
345 "axg_mst_d_lrclk", "axg_mst_e_lrclk", "axg_mst_f_lrclk",
346 "axg_slv_lrclk0", "axg_slv_lrclk1", "axg_slv_lrclk2",
347 "axg_slv_lrclk3", "axg_slv_lrclk4", "axg_slv_lrclk5",
348 "axg_slv_lrclk6", "axg_slv_lrclk7", "axg_slv_lrclk8",
352 #define AXG_TDM_LRLCK(_name, _reg) \
353 AXG_AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20, \
354 CLK_MUX_ROUND_CLOSEST, \
355 tdm_lrclk_parent_names, 0)
357 static AXG_TDM_LRLCK(in_a
, AUDIO_CLK_TDMIN_A_CTRL
);
358 static AXG_TDM_LRLCK(in_b
, AUDIO_CLK_TDMIN_B_CTRL
);
359 static AXG_TDM_LRLCK(in_c
, AUDIO_CLK_TDMIN_C_CTRL
);
360 static AXG_TDM_LRLCK(in_lb
, AUDIO_CLK_TDMIN_LB_CTRL
);
361 static AXG_TDM_LRLCK(out_a
, AUDIO_CLK_TDMOUT_A_CTRL
);
362 static AXG_TDM_LRLCK(out_b
, AUDIO_CLK_TDMOUT_B_CTRL
);
363 static AXG_TDM_LRLCK(out_c
, AUDIO_CLK_TDMOUT_C_CTRL
);
366 * Array of all clocks provided by this provider
367 * The input clocks of the controller will be populated at runtime
369 static struct clk_hw_onecell_data axg_audio_hw_onecell_data
= {
371 [AUD_CLKID_DDR_ARB
] = &axg_ddr_arb
.hw
,
372 [AUD_CLKID_PDM
] = &axg_pdm
.hw
,
373 [AUD_CLKID_TDMIN_A
] = &axg_tdmin_a
.hw
,
374 [AUD_CLKID_TDMIN_B
] = &axg_tdmin_b
.hw
,
375 [AUD_CLKID_TDMIN_C
] = &axg_tdmin_c
.hw
,
376 [AUD_CLKID_TDMIN_LB
] = &axg_tdmin_lb
.hw
,
377 [AUD_CLKID_TDMOUT_A
] = &axg_tdmout_a
.hw
,
378 [AUD_CLKID_TDMOUT_B
] = &axg_tdmout_b
.hw
,
379 [AUD_CLKID_TDMOUT_C
] = &axg_tdmout_c
.hw
,
380 [AUD_CLKID_FRDDR_A
] = &axg_frddr_a
.hw
,
381 [AUD_CLKID_FRDDR_B
] = &axg_frddr_b
.hw
,
382 [AUD_CLKID_FRDDR_C
] = &axg_frddr_c
.hw
,
383 [AUD_CLKID_TODDR_A
] = &axg_toddr_a
.hw
,
384 [AUD_CLKID_TODDR_B
] = &axg_toddr_b
.hw
,
385 [AUD_CLKID_TODDR_C
] = &axg_toddr_c
.hw
,
386 [AUD_CLKID_LOOPBACK
] = &axg_loopback
.hw
,
387 [AUD_CLKID_SPDIFIN
] = &axg_spdifin
.hw
,
388 [AUD_CLKID_SPDIFOUT
] = &axg_spdifout
.hw
,
389 [AUD_CLKID_RESAMPLE
] = &axg_resample
.hw
,
390 [AUD_CLKID_POWER_DETECT
] = &axg_power_detect
.hw
,
391 [AUD_CLKID_MST_A_MCLK_SEL
] = &axg_mst_a_mclk_sel
.hw
,
392 [AUD_CLKID_MST_B_MCLK_SEL
] = &axg_mst_b_mclk_sel
.hw
,
393 [AUD_CLKID_MST_C_MCLK_SEL
] = &axg_mst_c_mclk_sel
.hw
,
394 [AUD_CLKID_MST_D_MCLK_SEL
] = &axg_mst_d_mclk_sel
.hw
,
395 [AUD_CLKID_MST_E_MCLK_SEL
] = &axg_mst_e_mclk_sel
.hw
,
396 [AUD_CLKID_MST_F_MCLK_SEL
] = &axg_mst_f_mclk_sel
.hw
,
397 [AUD_CLKID_MST_A_MCLK_DIV
] = &axg_mst_a_mclk_div
.hw
,
398 [AUD_CLKID_MST_B_MCLK_DIV
] = &axg_mst_b_mclk_div
.hw
,
399 [AUD_CLKID_MST_C_MCLK_DIV
] = &axg_mst_c_mclk_div
.hw
,
400 [AUD_CLKID_MST_D_MCLK_DIV
] = &axg_mst_d_mclk_div
.hw
,
401 [AUD_CLKID_MST_E_MCLK_DIV
] = &axg_mst_e_mclk_div
.hw
,
402 [AUD_CLKID_MST_F_MCLK_DIV
] = &axg_mst_f_mclk_div
.hw
,
403 [AUD_CLKID_MST_A_MCLK
] = &axg_mst_a_mclk
.hw
,
404 [AUD_CLKID_MST_B_MCLK
] = &axg_mst_b_mclk
.hw
,
405 [AUD_CLKID_MST_C_MCLK
] = &axg_mst_c_mclk
.hw
,
406 [AUD_CLKID_MST_D_MCLK
] = &axg_mst_d_mclk
.hw
,
407 [AUD_CLKID_MST_E_MCLK
] = &axg_mst_e_mclk
.hw
,
408 [AUD_CLKID_MST_F_MCLK
] = &axg_mst_f_mclk
.hw
,
409 [AUD_CLKID_SPDIFOUT_CLK_SEL
] = &axg_spdifout_clk_sel
.hw
,
410 [AUD_CLKID_SPDIFOUT_CLK_DIV
] = &axg_spdifout_clk_div
.hw
,
411 [AUD_CLKID_SPDIFOUT_CLK
] = &axg_spdifout_clk
.hw
,
412 [AUD_CLKID_SPDIFIN_CLK_SEL
] = &axg_spdifin_clk_sel
.hw
,
413 [AUD_CLKID_SPDIFIN_CLK_DIV
] = &axg_spdifin_clk_div
.hw
,
414 [AUD_CLKID_SPDIFIN_CLK
] = &axg_spdifin_clk
.hw
,
415 [AUD_CLKID_PDM_DCLK_SEL
] = &axg_pdm_dclk_sel
.hw
,
416 [AUD_CLKID_PDM_DCLK_DIV
] = &axg_pdm_dclk_div
.hw
,
417 [AUD_CLKID_PDM_DCLK
] = &axg_pdm_dclk
.hw
,
418 [AUD_CLKID_PDM_SYSCLK_SEL
] = &axg_pdm_sysclk_sel
.hw
,
419 [AUD_CLKID_PDM_SYSCLK_DIV
] = &axg_pdm_sysclk_div
.hw
,
420 [AUD_CLKID_PDM_SYSCLK
] = &axg_pdm_sysclk
.hw
,
421 [AUD_CLKID_MST_A_SCLK_PRE_EN
] = &axg_mst_a_sclk_pre_en
.hw
,
422 [AUD_CLKID_MST_B_SCLK_PRE_EN
] = &axg_mst_b_sclk_pre_en
.hw
,
423 [AUD_CLKID_MST_C_SCLK_PRE_EN
] = &axg_mst_c_sclk_pre_en
.hw
,
424 [AUD_CLKID_MST_D_SCLK_PRE_EN
] = &axg_mst_d_sclk_pre_en
.hw
,
425 [AUD_CLKID_MST_E_SCLK_PRE_EN
] = &axg_mst_e_sclk_pre_en
.hw
,
426 [AUD_CLKID_MST_F_SCLK_PRE_EN
] = &axg_mst_f_sclk_pre_en
.hw
,
427 [AUD_CLKID_MST_A_SCLK_DIV
] = &axg_mst_a_sclk_div
.hw
,
428 [AUD_CLKID_MST_B_SCLK_DIV
] = &axg_mst_b_sclk_div
.hw
,
429 [AUD_CLKID_MST_C_SCLK_DIV
] = &axg_mst_c_sclk_div
.hw
,
430 [AUD_CLKID_MST_D_SCLK_DIV
] = &axg_mst_d_sclk_div
.hw
,
431 [AUD_CLKID_MST_E_SCLK_DIV
] = &axg_mst_e_sclk_div
.hw
,
432 [AUD_CLKID_MST_F_SCLK_DIV
] = &axg_mst_f_sclk_div
.hw
,
433 [AUD_CLKID_MST_A_SCLK_POST_EN
] = &axg_mst_a_sclk_post_en
.hw
,
434 [AUD_CLKID_MST_B_SCLK_POST_EN
] = &axg_mst_b_sclk_post_en
.hw
,
435 [AUD_CLKID_MST_C_SCLK_POST_EN
] = &axg_mst_c_sclk_post_en
.hw
,
436 [AUD_CLKID_MST_D_SCLK_POST_EN
] = &axg_mst_d_sclk_post_en
.hw
,
437 [AUD_CLKID_MST_E_SCLK_POST_EN
] = &axg_mst_e_sclk_post_en
.hw
,
438 [AUD_CLKID_MST_F_SCLK_POST_EN
] = &axg_mst_f_sclk_post_en
.hw
,
439 [AUD_CLKID_MST_A_SCLK
] = &axg_mst_a_sclk
.hw
,
440 [AUD_CLKID_MST_B_SCLK
] = &axg_mst_b_sclk
.hw
,
441 [AUD_CLKID_MST_C_SCLK
] = &axg_mst_c_sclk
.hw
,
442 [AUD_CLKID_MST_D_SCLK
] = &axg_mst_d_sclk
.hw
,
443 [AUD_CLKID_MST_E_SCLK
] = &axg_mst_e_sclk
.hw
,
444 [AUD_CLKID_MST_F_SCLK
] = &axg_mst_f_sclk
.hw
,
445 [AUD_CLKID_MST_A_LRCLK_DIV
] = &axg_mst_a_lrclk_div
.hw
,
446 [AUD_CLKID_MST_B_LRCLK_DIV
] = &axg_mst_b_lrclk_div
.hw
,
447 [AUD_CLKID_MST_C_LRCLK_DIV
] = &axg_mst_c_lrclk_div
.hw
,
448 [AUD_CLKID_MST_D_LRCLK_DIV
] = &axg_mst_d_lrclk_div
.hw
,
449 [AUD_CLKID_MST_E_LRCLK_DIV
] = &axg_mst_e_lrclk_div
.hw
,
450 [AUD_CLKID_MST_F_LRCLK_DIV
] = &axg_mst_f_lrclk_div
.hw
,
451 [AUD_CLKID_MST_A_LRCLK
] = &axg_mst_a_lrclk
.hw
,
452 [AUD_CLKID_MST_B_LRCLK
] = &axg_mst_b_lrclk
.hw
,
453 [AUD_CLKID_MST_C_LRCLK
] = &axg_mst_c_lrclk
.hw
,
454 [AUD_CLKID_MST_D_LRCLK
] = &axg_mst_d_lrclk
.hw
,
455 [AUD_CLKID_MST_E_LRCLK
] = &axg_mst_e_lrclk
.hw
,
456 [AUD_CLKID_MST_F_LRCLK
] = &axg_mst_f_lrclk
.hw
,
457 [AUD_CLKID_TDMIN_A_SCLK_SEL
] = &axg_tdmin_a_sclk_sel
.hw
,
458 [AUD_CLKID_TDMIN_B_SCLK_SEL
] = &axg_tdmin_b_sclk_sel
.hw
,
459 [AUD_CLKID_TDMIN_C_SCLK_SEL
] = &axg_tdmin_c_sclk_sel
.hw
,
460 [AUD_CLKID_TDMIN_LB_SCLK_SEL
] = &axg_tdmin_lb_sclk_sel
.hw
,
461 [AUD_CLKID_TDMOUT_A_SCLK_SEL
] = &axg_tdmout_a_sclk_sel
.hw
,
462 [AUD_CLKID_TDMOUT_B_SCLK_SEL
] = &axg_tdmout_b_sclk_sel
.hw
,
463 [AUD_CLKID_TDMOUT_C_SCLK_SEL
] = &axg_tdmout_c_sclk_sel
.hw
,
464 [AUD_CLKID_TDMIN_A_SCLK_PRE_EN
] = &axg_tdmin_a_sclk_pre_en
.hw
,
465 [AUD_CLKID_TDMIN_B_SCLK_PRE_EN
] = &axg_tdmin_b_sclk_pre_en
.hw
,
466 [AUD_CLKID_TDMIN_C_SCLK_PRE_EN
] = &axg_tdmin_c_sclk_pre_en
.hw
,
467 [AUD_CLKID_TDMIN_LB_SCLK_PRE_EN
] = &axg_tdmin_lb_sclk_pre_en
.hw
,
468 [AUD_CLKID_TDMOUT_A_SCLK_PRE_EN
] = &axg_tdmout_a_sclk_pre_en
.hw
,
469 [AUD_CLKID_TDMOUT_B_SCLK_PRE_EN
] = &axg_tdmout_b_sclk_pre_en
.hw
,
470 [AUD_CLKID_TDMOUT_C_SCLK_PRE_EN
] = &axg_tdmout_c_sclk_pre_en
.hw
,
471 [AUD_CLKID_TDMIN_A_SCLK_POST_EN
] = &axg_tdmin_a_sclk_post_en
.hw
,
472 [AUD_CLKID_TDMIN_B_SCLK_POST_EN
] = &axg_tdmin_b_sclk_post_en
.hw
,
473 [AUD_CLKID_TDMIN_C_SCLK_POST_EN
] = &axg_tdmin_c_sclk_post_en
.hw
,
474 [AUD_CLKID_TDMIN_LB_SCLK_POST_EN
] = &axg_tdmin_lb_sclk_post_en
.hw
,
475 [AUD_CLKID_TDMOUT_A_SCLK_POST_EN
] = &axg_tdmout_a_sclk_post_en
.hw
,
476 [AUD_CLKID_TDMOUT_B_SCLK_POST_EN
] = &axg_tdmout_b_sclk_post_en
.hw
,
477 [AUD_CLKID_TDMOUT_C_SCLK_POST_EN
] = &axg_tdmout_c_sclk_post_en
.hw
,
478 [AUD_CLKID_TDMIN_A_SCLK
] = &axg_tdmin_a_sclk
.hw
,
479 [AUD_CLKID_TDMIN_B_SCLK
] = &axg_tdmin_b_sclk
.hw
,
480 [AUD_CLKID_TDMIN_C_SCLK
] = &axg_tdmin_c_sclk
.hw
,
481 [AUD_CLKID_TDMIN_LB_SCLK
] = &axg_tdmin_lb_sclk
.hw
,
482 [AUD_CLKID_TDMOUT_A_SCLK
] = &axg_tdmout_a_sclk
.hw
,
483 [AUD_CLKID_TDMOUT_B_SCLK
] = &axg_tdmout_b_sclk
.hw
,
484 [AUD_CLKID_TDMOUT_C_SCLK
] = &axg_tdmout_c_sclk
.hw
,
485 [AUD_CLKID_TDMIN_A_LRCLK
] = &axg_tdmin_a_lrclk
.hw
,
486 [AUD_CLKID_TDMIN_B_LRCLK
] = &axg_tdmin_b_lrclk
.hw
,
487 [AUD_CLKID_TDMIN_C_LRCLK
] = &axg_tdmin_c_lrclk
.hw
,
488 [AUD_CLKID_TDMIN_LB_LRCLK
] = &axg_tdmin_lb_lrclk
.hw
,
489 [AUD_CLKID_TDMOUT_A_LRCLK
] = &axg_tdmout_a_lrclk
.hw
,
490 [AUD_CLKID_TDMOUT_B_LRCLK
] = &axg_tdmout_b_lrclk
.hw
,
491 [AUD_CLKID_TDMOUT_C_LRCLK
] = &axg_tdmout_c_lrclk
.hw
,
497 /* Convenience table to populate regmap in .probe() */
498 static struct clk_regmap
*const axg_audio_clk_regmaps
[] = {
537 &axg_spdifout_clk_sel
,
538 &axg_spdifout_clk_div
,
540 &axg_spdifin_clk_sel
,
541 &axg_spdifin_clk_div
,
549 &axg_mst_a_sclk_pre_en
,
550 &axg_mst_b_sclk_pre_en
,
551 &axg_mst_c_sclk_pre_en
,
552 &axg_mst_d_sclk_pre_en
,
553 &axg_mst_e_sclk_pre_en
,
554 &axg_mst_f_sclk_pre_en
,
561 &axg_mst_a_sclk_post_en
,
562 &axg_mst_b_sclk_post_en
,
563 &axg_mst_c_sclk_post_en
,
564 &axg_mst_d_sclk_post_en
,
565 &axg_mst_e_sclk_post_en
,
566 &axg_mst_f_sclk_post_en
,
573 &axg_mst_a_lrclk_div
,
574 &axg_mst_b_lrclk_div
,
575 &axg_mst_c_lrclk_div
,
576 &axg_mst_d_lrclk_div
,
577 &axg_mst_e_lrclk_div
,
578 &axg_mst_f_lrclk_div
,
585 &axg_tdmin_a_sclk_sel
,
586 &axg_tdmin_b_sclk_sel
,
587 &axg_tdmin_c_sclk_sel
,
588 &axg_tdmin_lb_sclk_sel
,
589 &axg_tdmout_a_sclk_sel
,
590 &axg_tdmout_b_sclk_sel
,
591 &axg_tdmout_c_sclk_sel
,
592 &axg_tdmin_a_sclk_pre_en
,
593 &axg_tdmin_b_sclk_pre_en
,
594 &axg_tdmin_c_sclk_pre_en
,
595 &axg_tdmin_lb_sclk_pre_en
,
596 &axg_tdmout_a_sclk_pre_en
,
597 &axg_tdmout_b_sclk_pre_en
,
598 &axg_tdmout_c_sclk_pre_en
,
599 &axg_tdmin_a_sclk_post_en
,
600 &axg_tdmin_b_sclk_post_en
,
601 &axg_tdmin_c_sclk_post_en
,
602 &axg_tdmin_lb_sclk_post_en
,
603 &axg_tdmout_a_sclk_post_en
,
604 &axg_tdmout_b_sclk_post_en
,
605 &axg_tdmout_c_sclk_post_en
,
622 static struct clk
*devm_clk_get_enable(struct device
*dev
, char *id
)
627 clk
= devm_clk_get(dev
, id
);
629 if (PTR_ERR(clk
) != -EPROBE_DEFER
)
630 dev_err(dev
, "failed to get %s", id
);
634 ret
= clk_prepare_enable(clk
);
636 dev_err(dev
, "failed to enable %s", id
);
640 ret
= devm_add_action_or_reset(dev
,
641 (void(*)(void *))clk_disable_unprepare
,
644 dev_err(dev
, "failed to add reset action on %s", id
);
651 static const struct clk_ops axg_clk_no_ops
= {};
653 static struct clk_hw
*axg_clk_hw_register_bypass(struct device
*dev
,
655 const char *parent_name
)
658 struct clk_init_data init
;
662 hw
= devm_kzalloc(dev
, sizeof(*hw
), GFP_KERNEL
);
664 return ERR_PTR(-ENOMEM
);
666 clk_name
= kasprintf(GFP_KERNEL
, "axg_%s", name
);
668 return ERR_PTR(-ENOMEM
);
670 init
.name
= clk_name
;
671 init
.ops
= &axg_clk_no_ops
;
673 init
.parent_names
= parent_name
? &parent_name
: NULL
;
674 init
.num_parents
= parent_name
? 1 : 0;
677 ret
= devm_clk_hw_register(dev
, hw
);
680 return ret
? ERR_PTR(ret
) : hw
;
683 static int axg_register_clk_hw_input(struct device
*dev
,
687 struct clk
*parent_clk
= devm_clk_get(dev
, name
);
688 struct clk_hw
*hw
= NULL
;
690 if (IS_ERR(parent_clk
)) {
691 int err
= PTR_ERR(parent_clk
);
693 /* It is ok if an input clock is missing */
694 if (err
== -ENOENT
) {
695 dev_dbg(dev
, "%s not provided", name
);
697 if (err
!= -EPROBE_DEFER
)
698 dev_err(dev
, "failed to get %s clock", name
);
702 hw
= axg_clk_hw_register_bypass(dev
, name
,
703 __clk_get_name(parent_clk
));
707 dev_err(dev
, "failed to register %s clock", name
);
711 axg_audio_hw_onecell_data
.hws
[clkid
] = hw
;
715 static int axg_register_clk_hw_inputs(struct device
*dev
,
716 const char *basename
,
723 for (i
= 0; i
< count
; i
++) {
724 name
= kasprintf(GFP_KERNEL
, "%s%d", basename
, i
);
728 ret
= axg_register_clk_hw_input(dev
, name
, clkid
+ i
);
737 static const struct regmap_config axg_audio_regmap_cfg
= {
741 .max_register
= AUDIO_CLK_PDMIN_CTRL1
,
744 static int axg_audio_clkc_probe(struct platform_device
*pdev
)
746 struct device
*dev
= &pdev
->dev
;
748 struct resource
*res
;
754 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
755 regs
= devm_ioremap_resource(dev
, res
);
757 return PTR_ERR(regs
);
759 map
= devm_regmap_init_mmio(dev
, regs
, &axg_audio_regmap_cfg
);
761 dev_err(dev
, "failed to init regmap: %ld\n", PTR_ERR(map
));
765 /* Get the mandatory peripheral clock */
766 clk
= devm_clk_get_enable(dev
, "pclk");
770 ret
= device_reset(dev
);
772 dev_err(dev
, "failed to reset device\n");
776 /* Register the peripheral input clock */
777 hw
= axg_clk_hw_register_bypass(dev
, "audio_pclk",
778 __clk_get_name(clk
));
782 axg_audio_hw_onecell_data
.hws
[AUD_CLKID_PCLK
] = hw
;
784 /* Register optional input master clocks */
785 ret
= axg_register_clk_hw_inputs(dev
, "mst_in",
791 /* Register optional input slave sclks */
792 ret
= axg_register_clk_hw_inputs(dev
, "slv_sclk",
794 AUD_CLKID_SLV_SCLK0
);
798 /* Register optional input slave lrclks */
799 ret
= axg_register_clk_hw_inputs(dev
, "slv_lrclk",
801 AUD_CLKID_SLV_LRCLK0
);
805 /* Populate regmap for the regmap backed clocks */
806 for (i
= 0; i
< ARRAY_SIZE(axg_audio_clk_regmaps
); i
++)
807 axg_audio_clk_regmaps
[i
]->map
= map
;
809 /* Take care to skip the registered input clocks */
810 for (i
= AUD_CLKID_DDR_ARB
; i
< axg_audio_hw_onecell_data
.num
; i
++) {
811 hw
= axg_audio_hw_onecell_data
.hws
[i
];
812 /* array might be sparse */
816 ret
= devm_clk_hw_register(dev
, hw
);
818 dev_err(dev
, "failed to register clock %s\n",
824 return devm_of_clk_add_hw_provider(dev
, of_clk_hw_onecell_get
,
825 &axg_audio_hw_onecell_data
);
828 static const struct of_device_id clkc_match_table
[] = {
829 { .compatible
= "amlogic,axg-audio-clkc" },
832 MODULE_DEVICE_TABLE(of
, clkc_match_table
);
834 static struct platform_driver axg_audio_driver
= {
835 .probe
= axg_audio_clkc_probe
,
837 .name
= "axg-audio-clkc",
838 .of_match_table
= clkc_match_table
,
841 module_platform_driver(axg_audio_driver
);
843 MODULE_DESCRIPTION("Amlogic A113x Audio Clock driver");
844 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
845 MODULE_LICENSE("GPL v2");