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