1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * mt8195-audsys-clk.h -- Mediatek 8195 audsys clock control |
4 | * |
5 | * Copyright (c) 2021 MediaTek Inc. |
6 | * Author: Trevor Wu <trevor.wu@mediatek.com> |
7 | */ |
8 | |
9 | #include <linux/clk.h> |
10 | #include <linux/clk-provider.h> |
11 | #include <linux/clkdev.h> |
12 | #include "mt8195-afe-common.h" |
13 | #include "mt8195-audsys-clk.h" |
14 | #include "mt8195-audsys-clkid.h" |
15 | #include "mt8195-reg.h" |
16 | |
17 | struct afe_gate { |
18 | int id; |
19 | const char *name; |
20 | const char *parent_name; |
21 | int reg; |
22 | u8 bit; |
23 | const struct clk_ops *ops; |
24 | unsigned long flags; |
25 | u8 cg_flags; |
26 | }; |
27 | |
28 | #define GATE_AFE_FLAGS(_id, _name, _parent, _reg, _bit, _flags, _cgflags) {\ |
29 | .id = _id, \ |
30 | .name = _name, \ |
31 | .parent_name = _parent, \ |
32 | .reg = _reg, \ |
33 | .bit = _bit, \ |
34 | .flags = _flags, \ |
35 | .cg_flags = _cgflags, \ |
36 | } |
37 | |
38 | #define GATE_AFE(_id, _name, _parent, _reg, _bit) \ |
39 | GATE_AFE_FLAGS(_id, _name, _parent, _reg, _bit, \ |
40 | CLK_SET_RATE_PARENT, CLK_GATE_SET_TO_DISABLE) |
41 | |
42 | #define GATE_AUD0(_id, _name, _parent, _bit) \ |
43 | GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON0, _bit) |
44 | |
45 | #define GATE_AUD1(_id, _name, _parent, _bit) \ |
46 | GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON1, _bit) |
47 | |
48 | #define GATE_AUD3(_id, _name, _parent, _bit) \ |
49 | GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON3, _bit) |
50 | |
51 | #define GATE_AUD4(_id, _name, _parent, _bit) \ |
52 | GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON4, _bit) |
53 | |
54 | #define GATE_AUD5(_id, _name, _parent, _bit) \ |
55 | GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON5, _bit) |
56 | |
57 | #define GATE_AUD6(_id, _name, _parent, _bit) \ |
58 | GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON6, _bit) |
59 | |
60 | static const struct afe_gate aud_clks[CLK_AUD_NR_CLK] = { |
61 | /* AUD0 */ |
62 | GATE_AUD0(CLK_AUD_AFE, "aud_afe" , "top_a1sys_hp" , 2), |
63 | GATE_AUD0(CLK_AUD_LRCK_CNT, "aud_lrck_cnt" , "top_a1sys_hp" , 4), |
64 | GATE_AUD0(CLK_AUD_SPDIFIN_TUNER_APLL, "aud_spdifin_tuner_apll" , "top_apll4" , 10), |
65 | GATE_AUD0(CLK_AUD_SPDIFIN_TUNER_DBG, "aud_spdifin_tuner_dbg" , "top_apll4" , 11), |
66 | GATE_AUD0(CLK_AUD_UL_TML, "aud_ul_tml" , "top_a1sys_hp" , 18), |
67 | GATE_AUD0(CLK_AUD_APLL1_TUNER, "aud_apll1_tuner" , "top_apll1" , 19), |
68 | GATE_AUD0(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner" , "top_apll2" , 20), |
69 | GATE_AUD0(CLK_AUD_TOP0_SPDF, "aud_top0_spdf" , "top_aud_iec_clk" , 21), |
70 | GATE_AUD0(CLK_AUD_APLL, "aud_apll" , "top_apll1" , 23), |
71 | GATE_AUD0(CLK_AUD_APLL2, "aud_apll2" , "top_apll2" , 24), |
72 | GATE_AUD0(CLK_AUD_DAC, "aud_dac" , "top_a1sys_hp" , 25), |
73 | GATE_AUD0(CLK_AUD_DAC_PREDIS, "aud_dac_predis" , "top_a1sys_hp" , 26), |
74 | GATE_AUD0(CLK_AUD_TML, "aud_tml" , "top_a1sys_hp" , 27), |
75 | GATE_AUD0(CLK_AUD_ADC, "aud_adc" , "top_a1sys_hp" , 28), |
76 | GATE_AUD0(CLK_AUD_DAC_HIRES, "aud_dac_hires" , "top_audio_h" , 31), |
77 | |
78 | /* AUD1 */ |
79 | GATE_AUD1(CLK_AUD_A1SYS_HP, "aud_a1sys_hp" , "top_a1sys_hp" , 2), |
80 | GATE_AUD1(CLK_AUD_AFE_DMIC1, "aud_afe_dmic1" , "top_a1sys_hp" , 10), |
81 | GATE_AUD1(CLK_AUD_AFE_DMIC2, "aud_afe_dmic2" , "top_a1sys_hp" , 11), |
82 | GATE_AUD1(CLK_AUD_AFE_DMIC3, "aud_afe_dmic3" , "top_a1sys_hp" , 12), |
83 | GATE_AUD1(CLK_AUD_AFE_DMIC4, "aud_afe_dmic4" , "top_a1sys_hp" , 13), |
84 | GATE_AUD1(CLK_AUD_AFE_26M_DMIC_TM, "aud_afe_26m_dmic_tm" , "top_a1sys_hp" , 14), |
85 | GATE_AUD1(CLK_AUD_UL_TML_HIRES, "aud_ul_tml_hires" , "top_audio_h" , 16), |
86 | GATE_AUD1(CLK_AUD_ADC_HIRES, "aud_adc_hires" , "top_audio_h" , 17), |
87 | GATE_AUD1(CLK_AUD_ADDA6_ADC, "aud_adda6_adc" , "top_a1sys_hp" , 18), |
88 | GATE_AUD1(CLK_AUD_ADDA6_ADC_HIRES, "aud_adda6_adc_hires" , "top_audio_h" , 19), |
89 | |
90 | /* AUD3 */ |
91 | GATE_AUD3(CLK_AUD_LINEIN_TUNER, "aud_linein_tuner" , "top_apll5" , 5), |
92 | GATE_AUD3(CLK_AUD_EARC_TUNER, "aud_earc_tuner" , "top_apll3" , 7), |
93 | |
94 | /* AUD4 */ |
95 | GATE_AUD4(CLK_AUD_I2SIN, "aud_i2sin" , "top_a1sys_hp" , 0), |
96 | GATE_AUD4(CLK_AUD_TDM_IN, "aud_tdm_in" , "top_a1sys_hp" , 1), |
97 | GATE_AUD4(CLK_AUD_I2S_OUT, "aud_i2s_out" , "top_a1sys_hp" , 6), |
98 | GATE_AUD4(CLK_AUD_TDM_OUT, "aud_tdm_out" , "top_a1sys_hp" , 7), |
99 | GATE_AUD4(CLK_AUD_HDMI_OUT, "aud_hdmi_out" , "top_a1sys_hp" , 8), |
100 | GATE_AUD4(CLK_AUD_ASRC11, "aud_asrc11" , "top_a1sys_hp" , 16), |
101 | GATE_AUD4(CLK_AUD_ASRC12, "aud_asrc12" , "top_a1sys_hp" , 17), |
102 | GATE_AUD4(CLK_AUD_MULTI_IN, "aud_multi_in" , "mphone_slave_b" , 19), |
103 | GATE_AUD4(CLK_AUD_INTDIR, "aud_intdir" , "top_intdir" , 20), |
104 | GATE_AUD4(CLK_AUD_A1SYS, "aud_a1sys" , "top_a1sys_hp" , 21), |
105 | GATE_AUD4(CLK_AUD_A2SYS, "aud_a2sys" , "top_a2sys_hf" , 22), |
106 | GATE_AUD4(CLK_AUD_PCMIF, "aud_pcmif" , "top_a1sys_hp" , 24), |
107 | GATE_AUD4(CLK_AUD_A3SYS, "aud_a3sys" , "top_a3sys_hf" , 30), |
108 | GATE_AUD4(CLK_AUD_A4SYS, "aud_a4sys" , "top_a4sys_hf" , 31), |
109 | |
110 | /* AUD5 */ |
111 | GATE_AUD5(CLK_AUD_MEMIF_UL1, "aud_memif_ul1" , "top_a1sys_hp" , 0), |
112 | GATE_AUD5(CLK_AUD_MEMIF_UL2, "aud_memif_ul2" , "top_a1sys_hp" , 1), |
113 | GATE_AUD5(CLK_AUD_MEMIF_UL3, "aud_memif_ul3" , "top_a1sys_hp" , 2), |
114 | GATE_AUD5(CLK_AUD_MEMIF_UL4, "aud_memif_ul4" , "top_a1sys_hp" , 3), |
115 | GATE_AUD5(CLK_AUD_MEMIF_UL5, "aud_memif_ul5" , "top_a1sys_hp" , 4), |
116 | GATE_AUD5(CLK_AUD_MEMIF_UL6, "aud_memif_ul6" , "top_a1sys_hp" , 5), |
117 | GATE_AUD5(CLK_AUD_MEMIF_UL8, "aud_memif_ul8" , "top_a1sys_hp" , 7), |
118 | GATE_AUD5(CLK_AUD_MEMIF_UL9, "aud_memif_ul9" , "top_a1sys_hp" , 8), |
119 | GATE_AUD5(CLK_AUD_MEMIF_UL10, "aud_memif_ul10" , "top_a1sys_hp" , 9), |
120 | GATE_AUD5(CLK_AUD_MEMIF_DL2, "aud_memif_dl2" , "top_a1sys_hp" , 18), |
121 | GATE_AUD5(CLK_AUD_MEMIF_DL3, "aud_memif_dl3" , "top_a1sys_hp" , 19), |
122 | GATE_AUD5(CLK_AUD_MEMIF_DL6, "aud_memif_dl6" , "top_a1sys_hp" , 22), |
123 | GATE_AUD5(CLK_AUD_MEMIF_DL7, "aud_memif_dl7" , "top_a1sys_hp" , 23), |
124 | GATE_AUD5(CLK_AUD_MEMIF_DL8, "aud_memif_dl8" , "top_a1sys_hp" , 24), |
125 | GATE_AUD5(CLK_AUD_MEMIF_DL10, "aud_memif_dl10" , "top_a1sys_hp" , 26), |
126 | GATE_AUD5(CLK_AUD_MEMIF_DL11, "aud_memif_dl11" , "top_a1sys_hp" , 27), |
127 | |
128 | /* AUD6 */ |
129 | GATE_AUD6(CLK_AUD_GASRC0, "aud_gasrc0" , "top_asm_h" , 0), |
130 | GATE_AUD6(CLK_AUD_GASRC1, "aud_gasrc1" , "top_asm_h" , 1), |
131 | GATE_AUD6(CLK_AUD_GASRC2, "aud_gasrc2" , "top_asm_h" , 2), |
132 | GATE_AUD6(CLK_AUD_GASRC3, "aud_gasrc3" , "top_asm_h" , 3), |
133 | GATE_AUD6(CLK_AUD_GASRC4, "aud_gasrc4" , "top_asm_h" , 4), |
134 | GATE_AUD6(CLK_AUD_GASRC5, "aud_gasrc5" , "top_asm_h" , 5), |
135 | GATE_AUD6(CLK_AUD_GASRC6, "aud_gasrc6" , "top_asm_h" , 6), |
136 | GATE_AUD6(CLK_AUD_GASRC7, "aud_gasrc7" , "top_asm_h" , 7), |
137 | GATE_AUD6(CLK_AUD_GASRC8, "aud_gasrc8" , "top_asm_h" , 8), |
138 | GATE_AUD6(CLK_AUD_GASRC9, "aud_gasrc9" , "top_asm_h" , 9), |
139 | GATE_AUD6(CLK_AUD_GASRC10, "aud_gasrc10" , "top_asm_h" , 10), |
140 | GATE_AUD6(CLK_AUD_GASRC11, "aud_gasrc11" , "top_asm_h" , 11), |
141 | GATE_AUD6(CLK_AUD_GASRC12, "aud_gasrc12" , "top_asm_h" , 12), |
142 | GATE_AUD6(CLK_AUD_GASRC13, "aud_gasrc13" , "top_asm_h" , 13), |
143 | GATE_AUD6(CLK_AUD_GASRC14, "aud_gasrc14" , "top_asm_h" , 14), |
144 | GATE_AUD6(CLK_AUD_GASRC15, "aud_gasrc15" , "top_asm_h" , 15), |
145 | GATE_AUD6(CLK_AUD_GASRC16, "aud_gasrc16" , "top_asm_h" , 16), |
146 | GATE_AUD6(CLK_AUD_GASRC17, "aud_gasrc17" , "top_asm_h" , 17), |
147 | GATE_AUD6(CLK_AUD_GASRC18, "aud_gasrc18" , "top_asm_h" , 18), |
148 | GATE_AUD6(CLK_AUD_GASRC19, "aud_gasrc19" , "top_asm_h" , 19), |
149 | }; |
150 | |
151 | static void mt8195_audsys_clk_unregister(void *data) |
152 | { |
153 | struct mtk_base_afe *afe = data; |
154 | struct mt8195_afe_private *afe_priv = afe->platform_priv; |
155 | struct clk *clk; |
156 | struct clk_lookup *cl; |
157 | int i; |
158 | |
159 | if (!afe_priv) |
160 | return; |
161 | |
162 | for (i = 0; i < CLK_AUD_NR_CLK; i++) { |
163 | cl = afe_priv->lookup[i]; |
164 | if (!cl) |
165 | continue; |
166 | |
167 | clk = cl->clk; |
168 | clk_unregister_gate(clk); |
169 | |
170 | clkdev_drop(cl); |
171 | } |
172 | } |
173 | |
174 | int mt8195_audsys_clk_register(struct mtk_base_afe *afe) |
175 | { |
176 | struct mt8195_afe_private *afe_priv = afe->platform_priv; |
177 | struct clk *clk; |
178 | struct clk_lookup *cl; |
179 | int i; |
180 | |
181 | afe_priv->lookup = devm_kcalloc(dev: afe->dev, n: CLK_AUD_NR_CLK, |
182 | size: sizeof(*afe_priv->lookup), |
183 | GFP_KERNEL); |
184 | |
185 | if (!afe_priv->lookup) |
186 | return -ENOMEM; |
187 | |
188 | for (i = 0; i < ARRAY_SIZE(aud_clks); i++) { |
189 | const struct afe_gate *gate = &aud_clks[i]; |
190 | |
191 | clk = clk_register_gate(dev: afe->dev, name: gate->name, parent_name: gate->parent_name, |
192 | flags: gate->flags, reg: afe->base_addr + gate->reg, |
193 | bit_idx: gate->bit, clk_gate_flags: gate->cg_flags, NULL); |
194 | |
195 | if (IS_ERR(ptr: clk)) { |
196 | dev_err(afe->dev, "Failed to register clk %s: %ld\n" , |
197 | gate->name, PTR_ERR(clk)); |
198 | continue; |
199 | } |
200 | |
201 | /* add clk_lookup for devm_clk_get(SND_SOC_DAPM_CLOCK_SUPPLY) */ |
202 | cl = kzalloc(size: sizeof(*cl), GFP_KERNEL); |
203 | if (!cl) |
204 | return -ENOMEM; |
205 | |
206 | cl->clk = clk; |
207 | cl->con_id = gate->name; |
208 | cl->dev_id = dev_name(dev: afe->dev); |
209 | clkdev_add(cl); |
210 | |
211 | afe_priv->lookup[i] = cl; |
212 | } |
213 | |
214 | return devm_add_action_or_reset(afe->dev, mt8195_audsys_clk_unregister, afe); |
215 | } |
216 | |