xref: /linux/drivers/clk/mediatek/clk-mt8196-vlpckgen.c (revision 8a7c601e14576a22c2bbf7f67455ccf3f3d2737f)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2025 MediaTek Inc.
4  *                    Guangjie Song <guangjie.song@mediatek.com>
5  * Copyright (c) 2025 Collabora Ltd.
6  *                    Laura Nao <laura.nao@collabora.com>
7  */
8 #include <dt-bindings/clock/mediatek,mt8196-clock.h>
9 
10 #include <linux/clk.h>
11 #include <linux/module.h>
12 #include <linux/of.h>
13 #include <linux/of_address.h>
14 #include <linux/of_device.h>
15 #include <linux/platform_device.h>
16 #include <linux/regmap.h>
17 
18 #include "clk-mtk.h"
19 #include "clk-mux.h"
20 #include "clk-pll.h"
21 
22 /* MUX SEL REG */
23 #define VLP_CLK_CFG_UPDATE		0x0004
24 #define VLP_CLK_CFG_UPDATE1		0x0008
25 #define VLP_CLK_CFG_0			0x0010
26 #define VLP_CLK_CFG_0_SET		0x0014
27 #define VLP_CLK_CFG_0_CLR		0x0018
28 #define VLP_CLK_CFG_1			0x0020
29 #define VLP_CLK_CFG_1_SET		0x0024
30 #define VLP_CLK_CFG_1_CLR		0x0028
31 #define VLP_CLK_CFG_2			0x0030
32 #define VLP_CLK_CFG_2_SET		0x0034
33 #define VLP_CLK_CFG_2_CLR		0x0038
34 #define VLP_CLK_CFG_3			0x0040
35 #define VLP_CLK_CFG_3_SET		0x0044
36 #define VLP_CLK_CFG_3_CLR		0x0048
37 #define VLP_CLK_CFG_4			0x0050
38 #define VLP_CLK_CFG_4_SET		0x0054
39 #define VLP_CLK_CFG_4_CLR		0x0058
40 #define VLP_CLK_CFG_5			0x0060
41 #define VLP_CLK_CFG_5_SET		0x0064
42 #define VLP_CLK_CFG_5_CLR		0x0068
43 #define VLP_CLK_CFG_6			0x0070
44 #define VLP_CLK_CFG_6_SET		0x0074
45 #define VLP_CLK_CFG_6_CLR		0x0078
46 #define VLP_CLK_CFG_7			0x0080
47 #define VLP_CLK_CFG_7_SET		0x0084
48 #define VLP_CLK_CFG_7_CLR		0x0088
49 #define VLP_CLK_CFG_8			0x0090
50 #define VLP_CLK_CFG_8_SET		0x0094
51 #define VLP_CLK_CFG_8_CLR		0x0098
52 #define VLP_CLK_CFG_9			0x00a0
53 #define VLP_CLK_CFG_9_SET		0x00a4
54 #define VLP_CLK_CFG_9_CLR		0x00a8
55 #define VLP_CLK_CFG_10			0x00b0
56 #define VLP_CLK_CFG_10_SET		0x00b4
57 #define VLP_CLK_CFG_10_CLR		0x00b8
58 #define VLP_OCIC_FENC_STATUS_MON_0	0x039c
59 #define VLP_OCIC_FENC_STATUS_MON_1	0x03a0
60 
61 /* MUX SHIFT */
62 #define TOP_MUX_SCP_SHIFT			0
63 #define TOP_MUX_SCP_SPI_SHIFT			1
64 #define TOP_MUX_SCP_IIC_SHIFT			2
65 #define TOP_MUX_SCP_IIC_HS_SHIFT		3
66 #define TOP_MUX_PWRAP_ULPOSC_SHIFT		4
67 #define TOP_MUX_SPMI_M_TIA_32K_SHIFT		5
68 #define TOP_MUX_APXGPT_26M_B_SHIFT		6
69 #define TOP_MUX_DPSW_SHIFT			7
70 #define TOP_MUX_DPSW_CENTRAL_SHIFT		8
71 #define TOP_MUX_SPMI_M_MST_SHIFT		9
72 #define TOP_MUX_DVFSRC_SHIFT			10
73 #define TOP_MUX_PWM_VLP_SHIFT			11
74 #define TOP_MUX_AXI_VLP_SHIFT			12
75 #define TOP_MUX_SYSTIMER_26M_SHIFT		13
76 #define TOP_MUX_SSPM_SHIFT			14
77 #define TOP_MUX_SRCK_SHIFT			15
78 #define TOP_MUX_CAMTG0_SHIFT			16
79 #define TOP_MUX_CAMTG1_SHIFT			17
80 #define TOP_MUX_CAMTG2_SHIFT			18
81 #define TOP_MUX_CAMTG3_SHIFT			19
82 #define TOP_MUX_CAMTG4_SHIFT			20
83 #define TOP_MUX_CAMTG5_SHIFT			21
84 #define TOP_MUX_CAMTG6_SHIFT			22
85 #define TOP_MUX_CAMTG7_SHIFT			23
86 #define TOP_MUX_SSPM_26M_SHIFT			25
87 #define TOP_MUX_ULPOSC_SSPM_SHIFT		26
88 #define TOP_MUX_VLP_PBUS_26M_SHIFT		27
89 #define TOP_MUX_DEBUG_ERR_FLAG_VLP_26M_SHIFT	28
90 #define TOP_MUX_DPMSRDMA_SHIFT			29
91 #define TOP_MUX_VLP_PBUS_156M_SHIFT		30
92 #define TOP_MUX_SPM_SHIFT			0
93 #define TOP_MUX_MMINFRA_VLP_SHIFT		1
94 #define TOP_MUX_USB_TOP_SHIFT			2
95 #define TOP_MUX_SSUSB_XHCI_SHIFT		3
96 #define TOP_MUX_NOC_VLP_SHIFT			4
97 #define TOP_MUX_AUDIO_H_SHIFT			5
98 #define TOP_MUX_AUD_ENGEN1_SHIFT		6
99 #define TOP_MUX_AUD_ENGEN2_SHIFT		7
100 #define TOP_MUX_AUD_INTBUS_SHIFT		8
101 #define TOP_MUX_SPU_VLP_26M_SHIFT		9
102 #define TOP_MUX_SPU0_VLP_SHIFT			10
103 #define TOP_MUX_SPU1_VLP_SHIFT			11
104 
105 /* CKSTA REG */
106 #define VLP_CKSTA_REG0			0x0250
107 #define VLP_CKSTA_REG1			0x0254
108 
109 /* HW Voter REG */
110 #define HWV_CG_9_SET	0x0048
111 #define HWV_CG_9_CLR	0x004c
112 #define HWV_CG_9_DONE	0x2c24
113 #define HWV_CG_10_SET	0x0050
114 #define HWV_CG_10_CLR	0x0054
115 #define HWV_CG_10_DONE	0x2c28
116 
117 /* PLL REG */
118 #define VLP_AP_PLL_CON3		0x264
119 #define VLP_APLL1_TUNER_CON0	0x2a4
120 #define VLP_APLL2_TUNER_CON0	0x2a8
121 #define VLP_APLL1_CON0		0x274
122 #define VLP_APLL1_CON1		0x278
123 #define VLP_APLL1_CON2		0x27c
124 #define VLP_APLL1_CON3		0x280
125 #define VLP_APLL2_CON0		0x28c
126 #define VLP_APLL2_CON1		0x290
127 #define VLP_APLL2_CON2		0x294
128 #define VLP_APLL2_CON3		0x298
129 
130 /* vlp apll1 tuner default value*/
131 #define VLP_APLL1_TUNER_CON0_VALUE 0x6f28bd4d
132 /* vlp apll2 tuner default value + 1*/
133 #define VLP_APLL2_TUNER_CON0_VALUE 0x78fd5265
134 
135 #define VLP_PLLEN_ALL		0x080
136 #define VLP_PLLEN_ALL_SET	0x084
137 #define VLP_PLLEN_ALL_CLR	0x088
138 
139 #define MT8196_PLL_FMAX		(3800UL * MHZ)
140 #define MT8196_PLL_FMIN		(1500UL * MHZ)
141 #define MT8196_INTEGER_BITS	8
142 
143 #define PLL_FENC(_id, _name, _reg, _fenc_sta_ofs, _fenc_sta_bit,\
144 			_flags, _pd_reg, _pd_shift,			\
145 			_pcw_reg, _pcw_shift, _pcwbits,		\
146 			_pll_en_bit) {					\
147 		.id = _id,					\
148 		.name = _name,					\
149 		.reg = _reg,					\
150 		.fenc_sta_ofs = _fenc_sta_ofs,			\
151 		.fenc_sta_bit = _fenc_sta_bit,			\
152 		.flags = _flags,				\
153 		.fmax = MT8196_PLL_FMAX,			\
154 		.fmin = MT8196_PLL_FMIN,			\
155 		.pd_reg = _pd_reg,				\
156 		.pd_shift = _pd_shift,				\
157 		.pcw_reg = _pcw_reg,				\
158 		.pcw_shift = _pcw_shift,			\
159 		.pcwbits = _pcwbits,				\
160 		.pcwibits = MT8196_INTEGER_BITS,		\
161 		.en_reg = VLP_PLLEN_ALL,			\
162 		.en_set_reg = VLP_PLLEN_ALL_SET,		\
163 		.en_clr_reg = VLP_PLLEN_ALL_CLR,		\
164 		.pll_en_bit = _pll_en_bit,			\
165 		.ops = &mtk_pll_fenc_clr_set_ops,		\
166 }
167 
168 static DEFINE_SPINLOCK(mt8196_clk_vlp_lock);
169 
170 static const struct mtk_fixed_factor vlp_divs[] = {
171 	FACTOR(CLK_VLP_CLK26M, "vlp_clk26m", "clk26m", 1, 1),
172 	FACTOR(CLK_VLP_APLL1_D4, "apll1_d4", "vlp_apll1", 1, 4),
173 	FACTOR(CLK_VLP_APLL1_D8, "apll1_d8", "vlp_apll1", 1, 8),
174 	FACTOR(CLK_VLP_APLL2_D4, "apll2_d4", "vlp_apll2", 1, 4),
175 	FACTOR(CLK_VLP_APLL2_D8, "apll2_d8", "vlp_apll2", 1, 8),
176 };
177 
178 static const char * const vlp_scp_parents[] = {
179 	"clk26m",
180 	"osc_d20",
181 	"mainpll_d6",
182 	"mainpll_d4",
183 	"mainpll_d3",
184 	"vlp_apll1"
185 };
186 
187 static const char * const vlp_scp_spi_parents[] = {
188 	"clk26m",
189 	"osc_d20",
190 	"mainpll_d7_d2",
191 	"mainpll_d5_d2"
192 };
193 
194 static const char * const vlp_scp_iic_parents[] = {
195 	"clk26m",
196 	"osc_d20",
197 	"mainpll_d5_d4",
198 	"mainpll_d7_d2"
199 };
200 
201 static const char * const vlp_scp_iic_hs_parents[] = {
202 	"clk26m",
203 	"osc_d20",
204 	"mainpll_d5_d4",
205 	"mainpll_d7_d2",
206 	"mainpll_d7"
207 };
208 
209 static const char * const vlp_pwrap_ulposc_parents[] = {
210 	"clk26m",
211 	"osc_d20",
212 	"osc_d14",
213 	"osc_d10"
214 };
215 
216 static const char * const vlp_spmi_32k_parents[] = {
217 	"clk26m",
218 	"clk32k",
219 	"osc_d20",
220 	"osc_d14",
221 	"osc_d10"
222 };
223 
224 static const char * const vlp_apxgpt_26m_b_parents[] = {
225 	"clk26m",
226 	"osc_d20"
227 };
228 
229 static const char * const vlp_dpsw_parents[] = {
230 	"clk26m",
231 	"osc_d10",
232 	"osc_d7",
233 	"mainpll_d7_d4"
234 };
235 
236 static const char * const vlp_dpsw_central_parents[] = {
237 	"clk26m",
238 	"osc_d10",
239 	"osc_d7",
240 	"mainpll_d7_d4"
241 };
242 
243 static const char * const vlp_spmi_m_parents[] = {
244 	"clk26m",
245 	"osc_d20",
246 	"osc_d14",
247 	"osc_d10"
248 };
249 
250 static const char * const vlp_dvfsrc_parents[] = {
251 	"clk26m",
252 	"osc_d20"
253 };
254 
255 static const char * const vlp_pwm_vlp_parents[] = {
256 	"clk26m",
257 	"clk32k",
258 	"osc_d20",
259 	"osc_d8",
260 	"mainpll_d4_d8"
261 };
262 
263 static const char * const vlp_axi_vlp_parents[] = {
264 	"clk26m",
265 	"osc_d20",
266 	"mainpll_d7_d4",
267 	"osc_d4",
268 	"mainpll_d7_d2"
269 };
270 
271 static const char * const vlp_systimer_26m_parents[] = {
272 	"clk26m",
273 	"osc_d20"
274 };
275 
276 static const char * const vlp_sspm_parents[] = {
277 	"clk26m",
278 	"osc_d20",
279 	"mainpll_d5_d2",
280 	"osc_d2",
281 	"mainpll_d6"
282 };
283 
284 static const char * const vlp_srck_parents[] = {
285 	"clk26m",
286 	"osc_d20"
287 };
288 
289 static const char * const vlp_camtg0_1_parents[] = {
290 	"clk26m",
291 	"univpll_192m_d32",
292 	"univpll_192m_d16",
293 	"clk13m",
294 	"osc_d40",
295 	"osc_d32",
296 	"univpll_192m_d10",
297 	"univpll_192m_d8",
298 	"univpll_d6_d16",
299 	"ulposc3",
300 	"osc_d20",
301 	"ck2_tvdpll1_d16",
302 	"univpll_d6_d8"
303 };
304 
305 static const char * const vlp_camtg2_7_parents[] = {
306 	"clk26m",
307 	"univpll_192m_d32",
308 	"univpll_192m_d16",
309 	"clk13m",
310 	"osc_d40",
311 	"osc_d32",
312 	"univpll_192m_d10",
313 	"univpll_192m_d8",
314 	"univpll_d6_d16",
315 	"osc_d20",
316 	"ck2_tvdpll1_d16",
317 	"univpll_d6_d8"
318 };
319 
320 static const char * const vlp_sspm_26m_parents[] = {
321 	"clk26m",
322 	"osc_d20"
323 };
324 
325 static const char * const vlp_ulposc_sspm_parents[] = {
326 	"clk26m",
327 	"osc_d2",
328 	"mainpll_d4_d2"
329 };
330 
331 static const char * const vlp_vlp_pbus_26m_parents[] = {
332 	"clk26m",
333 	"osc_d20"
334 };
335 
336 static const char * const vlp_debug_err_flag_parents[] = {
337 	"clk26m",
338 	"osc_d20"
339 };
340 
341 static const char * const vlp_dpmsrdma_parents[] = {
342 	"clk26m",
343 	"mainpll_d7_d2"
344 };
345 
346 static const char * const vlp_vlp_pbus_156m_parents[] = {
347 	"clk26m",
348 	"osc_d2",
349 	"mainpll_d7_d2",
350 	"mainpll_d7"
351 };
352 
353 static const char * const vlp_spm_parents[] = {
354 	"clk26m",
355 	"mainpll_d7_d4"
356 };
357 
358 static const char * const vlp_mminfra_parents[] = {
359 	"clk26m",
360 	"osc_d4",
361 	"mainpll_d3"
362 };
363 
364 static const char * const vlp_usb_parents[] = {
365 	"clk26m",
366 	"mainpll_d9"
367 };
368 
369 static const char * const vlp_noc_vlp_parents[] = {
370 	"clk26m",
371 	"osc_d20",
372 	"mainpll_d9"
373 };
374 
375 static const char * const vlp_audio_h_parents[] = {
376 	"vlp_clk26m",
377 	"vlp_apll1",
378 	"vlp_apll2"
379 };
380 
381 static const char * const vlp_aud_engen1_parents[] = {
382 	"vlp_clk26m",
383 	"apll1_d8",
384 	"apll1_d4"
385 };
386 
387 static const char * const vlp_aud_engen2_parents[] = {
388 	"vlp_clk26m",
389 	"apll2_d8",
390 	"apll2_d4"
391 };
392 
393 static const char * const vlp_aud_intbus_parents[] = {
394 	"vlp_clk26m",
395 	"mainpll_d7_d4",
396 	"mainpll_d4_d4"
397 };
398 
399 static const u8 vlp_aud_parent_index[] = { 1, 2, 3 };
400 
401 static const char * const vlp_spvlp_26m_parents[] = {
402 	"clk26m",
403 	"osc_d20"
404 };
405 
406 static const char * const vlp_spu0_vlp_parents[] = {
407 	"clk26m",
408 	"osc_d20",
409 	"mainpll_d4_d4",
410 	"mainpll_d4_d2",
411 	"mainpll_d7",
412 	"mainpll_d6",
413 	"mainpll_d5"
414 };
415 
416 static const char * const vlp_spu1_vlp_parents[] = {
417 	"clk26m",
418 	"osc_d20",
419 	"mainpll_d4_d4",
420 	"mainpll_d4_d2",
421 	"mainpll_d7",
422 	"mainpll_d6",
423 	"mainpll_d5"
424 };
425 
426 static const struct mtk_mux vlp_muxes[] = {
427 	/* VLP_CLK_CFG_0 */
428 	MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_SCP, "vlp_scp", vlp_scp_parents,
429 		VLP_CLK_CFG_0, VLP_CLK_CFG_0_SET, VLP_CLK_CFG_0_CLR,
430 		0, 3, 7, VLP_CLK_CFG_UPDATE, TOP_MUX_SCP_SHIFT,
431 		VLP_OCIC_FENC_STATUS_MON_0, 31),
432 	MUX_CLR_SET_UPD(CLK_VLP_SCP_SPI, "vlp_scp_spi",
433 		vlp_scp_spi_parents, VLP_CLK_CFG_0, VLP_CLK_CFG_0_SET,
434 		VLP_CLK_CFG_0_CLR, 8, 2,
435 		VLP_CLK_CFG_UPDATE, TOP_MUX_SCP_SPI_SHIFT),
436 	MUX_CLR_SET_UPD(CLK_VLP_SCP_IIC, "vlp_scp_iic",
437 		vlp_scp_iic_parents, VLP_CLK_CFG_0, VLP_CLK_CFG_0_SET,
438 		VLP_CLK_CFG_0_CLR, 16, 2,
439 		VLP_CLK_CFG_UPDATE, TOP_MUX_SCP_IIC_SHIFT),
440 	MUX_CLR_SET_UPD(CLK_VLP_SCP_IIC_HS, "vlp_scp_iic_hs",
441 		vlp_scp_iic_hs_parents, VLP_CLK_CFG_0, VLP_CLK_CFG_0_SET,
442 		VLP_CLK_CFG_0_CLR, 24, 3,
443 		VLP_CLK_CFG_UPDATE, TOP_MUX_SCP_IIC_HS_SHIFT),
444 	/* VLP_CLK_CFG_1 */
445 	MUX_CLR_SET_UPD(CLK_VLP_PWRAP_ULPOSC, "vlp_pwrap_ulposc",
446 		vlp_pwrap_ulposc_parents, VLP_CLK_CFG_1, VLP_CLK_CFG_1_SET,
447 		VLP_CLK_CFG_1_CLR, 0, 2,
448 		VLP_CLK_CFG_UPDATE, TOP_MUX_PWRAP_ULPOSC_SHIFT),
449 	MUX_CLR_SET_UPD(CLK_VLP_SPMI_M_TIA_32K, "vlp_spmi_32k",
450 		vlp_spmi_32k_parents, VLP_CLK_CFG_1, VLP_CLK_CFG_1_SET,
451 		VLP_CLK_CFG_1_CLR, 8, 3,
452 		VLP_CLK_CFG_UPDATE, TOP_MUX_SPMI_M_TIA_32K_SHIFT),
453 	MUX_CLR_SET_UPD(CLK_VLP_APXGPT_26M_B, "vlp_apxgpt_26m_b",
454 		vlp_apxgpt_26m_b_parents, VLP_CLK_CFG_1, VLP_CLK_CFG_1_SET,
455 		VLP_CLK_CFG_1_CLR, 16, 1,
456 		VLP_CLK_CFG_UPDATE, TOP_MUX_APXGPT_26M_B_SHIFT),
457 	MUX_CLR_SET_UPD(CLK_VLP_DPSW, "vlp_dpsw",
458 		vlp_dpsw_parents, VLP_CLK_CFG_1, VLP_CLK_CFG_1_SET,
459 		VLP_CLK_CFG_1_CLR, 24, 2,
460 		VLP_CLK_CFG_UPDATE, TOP_MUX_DPSW_SHIFT),
461 	/* VLP_CLK_CFG_2 */
462 	MUX_CLR_SET_UPD(CLK_VLP_DPSW_CENTRAL, "vlp_dpsw_central",
463 		vlp_dpsw_central_parents, VLP_CLK_CFG_2, VLP_CLK_CFG_2_SET,
464 		VLP_CLK_CFG_2_CLR, 0, 2,
465 		VLP_CLK_CFG_UPDATE, TOP_MUX_DPSW_CENTRAL_SHIFT),
466 	MUX_CLR_SET_UPD(CLK_VLP_SPMI_M_MST, "vlp_spmi_m",
467 		vlp_spmi_m_parents, VLP_CLK_CFG_2, VLP_CLK_CFG_2_SET,
468 		VLP_CLK_CFG_2_CLR, 8, 2,
469 		VLP_CLK_CFG_UPDATE, TOP_MUX_SPMI_M_MST_SHIFT),
470 	MUX_CLR_SET_UPD(CLK_VLP_DVFSRC, "vlp_dvfsrc",
471 		vlp_dvfsrc_parents, VLP_CLK_CFG_2, VLP_CLK_CFG_2_SET,
472 		VLP_CLK_CFG_2_CLR, 16, 1,
473 		VLP_CLK_CFG_UPDATE, TOP_MUX_DVFSRC_SHIFT),
474 	MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_PWM_VLP, "vlp_pwm_vlp", vlp_pwm_vlp_parents,
475 		VLP_CLK_CFG_2, VLP_CLK_CFG_2_SET, VLP_CLK_CFG_2_CLR,
476 		24, 3, 31, VLP_CLK_CFG_UPDATE, TOP_MUX_PWM_VLP_SHIFT,
477 		VLP_OCIC_FENC_STATUS_MON_0, 20),
478 	/* VLP_CLK_CFG_3 */
479 	MUX_CLR_SET_UPD(CLK_VLP_AXI_VLP, "vlp_axi_vlp",
480 		vlp_axi_vlp_parents, VLP_CLK_CFG_3, VLP_CLK_CFG_3_SET,
481 		VLP_CLK_CFG_3_CLR, 0, 3,
482 		VLP_CLK_CFG_UPDATE, TOP_MUX_AXI_VLP_SHIFT),
483 	MUX_CLR_SET_UPD(CLK_VLP_SYSTIMER_26M, "vlp_systimer_26m",
484 		vlp_systimer_26m_parents, VLP_CLK_CFG_3, VLP_CLK_CFG_3_SET,
485 		VLP_CLK_CFG_3_CLR, 8, 1,
486 		VLP_CLK_CFG_UPDATE, TOP_MUX_SYSTIMER_26M_SHIFT),
487 	MUX_CLR_SET_UPD(CLK_VLP_SSPM, "vlp_sspm",
488 		vlp_sspm_parents, VLP_CLK_CFG_3, VLP_CLK_CFG_3_SET,
489 		VLP_CLK_CFG_3_CLR, 16, 3,
490 		VLP_CLK_CFG_UPDATE, TOP_MUX_SSPM_SHIFT),
491 	MUX_CLR_SET_UPD(CLK_VLP_SRCK, "vlp_srck",
492 		vlp_srck_parents, VLP_CLK_CFG_3, VLP_CLK_CFG_3_SET,
493 		VLP_CLK_CFG_3_CLR, 24, 1,
494 		VLP_CLK_CFG_UPDATE, TOP_MUX_SRCK_SHIFT),
495 	/* VLP_CLK_CFG_4 */
496 	MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG0, "vlp_camtg0", vlp_camtg0_1_parents,
497 		VLP_CLK_CFG_4, VLP_CLK_CFG_4_SET, VLP_CLK_CFG_4_CLR,
498 		HWV_CG_9_DONE, HWV_CG_9_SET, HWV_CG_9_CLR,
499 		0, 4, 7, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG0_SHIFT,
500 		VLP_OCIC_FENC_STATUS_MON_0, 15),
501 	MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG1, "vlp_camtg1", vlp_camtg0_1_parents,
502 		VLP_CLK_CFG_4, VLP_CLK_CFG_4_SET, VLP_CLK_CFG_4_CLR,
503 		HWV_CG_9_DONE, HWV_CG_9_SET, HWV_CG_9_CLR,
504 		8, 4, 15, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG1_SHIFT,
505 		VLP_OCIC_FENC_STATUS_MON_0, 14),
506 	MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG2, "vlp_camtg2", vlp_camtg2_7_parents,
507 		VLP_CLK_CFG_4, VLP_CLK_CFG_4_SET, VLP_CLK_CFG_4_CLR,
508 		HWV_CG_9_DONE, HWV_CG_9_SET, HWV_CG_9_CLR,
509 		16, 4, 23, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG2_SHIFT,
510 		VLP_OCIC_FENC_STATUS_MON_0, 13),
511 	MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG3, "vlp_camtg3", vlp_camtg2_7_parents,
512 		VLP_CLK_CFG_4, VLP_CLK_CFG_4_SET, VLP_CLK_CFG_4_CLR,
513 		HWV_CG_9_DONE, HWV_CG_9_SET, HWV_CG_9_CLR,
514 		24, 4, 31, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG3_SHIFT,
515 		VLP_OCIC_FENC_STATUS_MON_0, 12),
516 	/* VLP_CLK_CFG_5 */
517 	MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG4, "vlp_camtg4", vlp_camtg2_7_parents,
518 		VLP_CLK_CFG_5, VLP_CLK_CFG_5_SET, VLP_CLK_CFG_5_CLR,
519 		HWV_CG_10_DONE, HWV_CG_10_SET, HWV_CG_10_CLR,
520 		0, 4, 7, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG4_SHIFT,
521 		VLP_OCIC_FENC_STATUS_MON_0, 11),
522 	MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG5, "vlp_camtg5", vlp_camtg2_7_parents,
523 		VLP_CLK_CFG_5, VLP_CLK_CFG_5_SET, VLP_CLK_CFG_5_CLR,
524 		HWV_CG_10_DONE, HWV_CG_10_SET, HWV_CG_10_CLR,
525 		8, 4, 15, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG5_SHIFT,
526 		VLP_OCIC_FENC_STATUS_MON_0, 10),
527 	MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG6, "vlp_camtg6", vlp_camtg2_7_parents,
528 		VLP_CLK_CFG_5, VLP_CLK_CFG_5_SET, VLP_CLK_CFG_5_CLR,
529 		HWV_CG_10_DONE, HWV_CG_10_SET, HWV_CG_10_CLR,
530 		16, 4, 23, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG6_SHIFT,
531 		VLP_OCIC_FENC_STATUS_MON_0, 9),
532 	MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG7, "vlp_camtg7", vlp_camtg2_7_parents,
533 		VLP_CLK_CFG_5, VLP_CLK_CFG_5_SET, VLP_CLK_CFG_5_CLR,
534 		HWV_CG_10_DONE, HWV_CG_10_SET, HWV_CG_10_CLR,
535 		24, 4, 31, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG7_SHIFT,
536 		VLP_OCIC_FENC_STATUS_MON_0, 8),
537 	/* VLP_CLK_CFG_6 */
538 	MUX_CLR_SET_UPD(CLK_VLP_SSPM_26M, "vlp_sspm_26m",
539 		vlp_sspm_26m_parents, VLP_CLK_CFG_6, VLP_CLK_CFG_6_SET,
540 		VLP_CLK_CFG_6_CLR, 8, 1,
541 		VLP_CLK_CFG_UPDATE, TOP_MUX_SSPM_26M_SHIFT),
542 	MUX_CLR_SET_UPD(CLK_VLP_ULPOSC_SSPM, "vlp_ulposc_sspm",
543 		vlp_ulposc_sspm_parents, VLP_CLK_CFG_6, VLP_CLK_CFG_6_SET,
544 		VLP_CLK_CFG_6_CLR, 16, 2,
545 		VLP_CLK_CFG_UPDATE, TOP_MUX_ULPOSC_SSPM_SHIFT),
546 	MUX_CLR_SET_UPD(CLK_VLP_VLP_PBUS_26M, "vlp_vlp_pbus_26m",
547 		vlp_vlp_pbus_26m_parents, VLP_CLK_CFG_6, VLP_CLK_CFG_6_SET,
548 		VLP_CLK_CFG_6_CLR, 24, 1,
549 		VLP_CLK_CFG_UPDATE, TOP_MUX_VLP_PBUS_26M_SHIFT),
550 	/* VLP_CLK_CFG_7 */
551 	MUX_CLR_SET_UPD(CLK_VLP_DEBUG_ERR_FLAG, "vlp_debug_err_flag",
552 		vlp_debug_err_flag_parents, VLP_CLK_CFG_7, VLP_CLK_CFG_7_SET,
553 		VLP_CLK_CFG_7_CLR, 0, 1,
554 		VLP_CLK_CFG_UPDATE, TOP_MUX_DEBUG_ERR_FLAG_VLP_26M_SHIFT),
555 	MUX_CLR_SET_UPD(CLK_VLP_DPMSRDMA, "vlp_dpmsrdma",
556 		vlp_dpmsrdma_parents, VLP_CLK_CFG_7, VLP_CLK_CFG_7_SET,
557 		VLP_CLK_CFG_7_CLR, 8, 1,
558 		VLP_CLK_CFG_UPDATE, TOP_MUX_DPMSRDMA_SHIFT),
559 	MUX_CLR_SET_UPD(CLK_VLP_VLP_PBUS_156M, "vlp_vlp_pbus_156m",
560 		vlp_vlp_pbus_156m_parents, VLP_CLK_CFG_7, VLP_CLK_CFG_7_SET,
561 		VLP_CLK_CFG_7_CLR, 16, 2,
562 		VLP_CLK_CFG_UPDATE, TOP_MUX_VLP_PBUS_156M_SHIFT),
563 	MUX_CLR_SET_UPD(CLK_VLP_SPM, "vlp_spm",
564 		vlp_spm_parents, VLP_CLK_CFG_7, VLP_CLK_CFG_7_SET,
565 		VLP_CLK_CFG_7_CLR, 24, 1,
566 		VLP_CLK_CFG_UPDATE1, TOP_MUX_SPM_SHIFT),
567 	/* VLP_CLK_CFG_8 */
568 	MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_MMINFRA, "vlp_mminfra", vlp_mminfra_parents,
569 		VLP_CLK_CFG_8, VLP_CLK_CFG_8_SET, VLP_CLK_CFG_8_CLR,
570 		0, 2, 7, VLP_CLK_CFG_UPDATE1, TOP_MUX_MMINFRA_VLP_SHIFT,
571 		VLP_OCIC_FENC_STATUS_MON_1, 31),
572 	MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_USB_TOP, "vlp_usb", vlp_usb_parents,
573 		VLP_CLK_CFG_8, VLP_CLK_CFG_8_SET, VLP_CLK_CFG_8_CLR,
574 		8, 1, 15, VLP_CLK_CFG_UPDATE1, TOP_MUX_USB_TOP_SHIFT,
575 		VLP_OCIC_FENC_STATUS_MON_1, 30),
576 	MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_USB_XHCI, "vlp_usb_xhci", vlp_usb_parents,
577 		VLP_CLK_CFG_8, VLP_CLK_CFG_8_SET, VLP_CLK_CFG_8_CLR,
578 		16, 1, 23, VLP_CLK_CFG_UPDATE1, TOP_MUX_SSUSB_XHCI_SHIFT,
579 		VLP_OCIC_FENC_STATUS_MON_1, 29),
580 	MUX_CLR_SET_UPD(CLK_VLP_NOC_VLP, "vlp_noc_vlp",
581 		vlp_noc_vlp_parents, VLP_CLK_CFG_8, VLP_CLK_CFG_8_SET,
582 		VLP_CLK_CFG_8_CLR, 24, 2,
583 		VLP_CLK_CFG_UPDATE1, TOP_MUX_NOC_VLP_SHIFT),
584 	/* VLP_CLK_CFG_9 */
585 	MUX_GATE_FENC_CLR_SET_UPD_INDEXED(CLK_VLP_AUDIO_H, "vlp_audio_h",
586 		vlp_audio_h_parents, vlp_aud_parent_index,
587 		VLP_CLK_CFG_9, VLP_CLK_CFG_9_SET, VLP_CLK_CFG_9_CLR,
588 		0, 2, 7, VLP_CLK_CFG_UPDATE1, TOP_MUX_AUDIO_H_SHIFT,
589 		VLP_OCIC_FENC_STATUS_MON_1, 27),
590 	MUX_GATE_FENC_CLR_SET_UPD_INDEXED(CLK_VLP_AUD_ENGEN1, "vlp_aud_engen1",
591 		vlp_aud_engen1_parents, vlp_aud_parent_index,
592 		VLP_CLK_CFG_9, VLP_CLK_CFG_9_SET, VLP_CLK_CFG_9_CLR,
593 		8, 2, 15, VLP_CLK_CFG_UPDATE1, TOP_MUX_AUD_ENGEN1_SHIFT,
594 		VLP_OCIC_FENC_STATUS_MON_1, 26),
595 	MUX_GATE_FENC_CLR_SET_UPD_INDEXED(CLK_VLP_AUD_ENGEN2, "vlp_aud_engen2",
596 		vlp_aud_engen2_parents, vlp_aud_parent_index,
597 		VLP_CLK_CFG_9, VLP_CLK_CFG_9_SET, VLP_CLK_CFG_9_CLR,
598 		16, 2, 23, VLP_CLK_CFG_UPDATE1, TOP_MUX_AUD_ENGEN2_SHIFT,
599 		VLP_OCIC_FENC_STATUS_MON_1, 25),
600 	MUX_GATE_FENC_CLR_SET_UPD_INDEXED(CLK_VLP_AUD_INTBUS, "vlp_aud_intbus",
601 		vlp_aud_intbus_parents, vlp_aud_parent_index,
602 		VLP_CLK_CFG_9, VLP_CLK_CFG_9_SET, VLP_CLK_CFG_9_CLR,
603 		24, 2, 31, VLP_CLK_CFG_UPDATE1, TOP_MUX_AUD_INTBUS_SHIFT,
604 		VLP_OCIC_FENC_STATUS_MON_1, 24),
605 	/* VLP_CLK_CFG_10 */
606 	MUX_CLR_SET_UPD(CLK_VLP_SPVLP_26M, "vlp_spvlp_26m",
607 		vlp_spvlp_26m_parents, VLP_CLK_CFG_10, VLP_CLK_CFG_10_SET,
608 		VLP_CLK_CFG_10_CLR, 0, 1,
609 		VLP_CLK_CFG_UPDATE1, TOP_MUX_SPU_VLP_26M_SHIFT),
610 	MUX_CLR_SET_UPD(CLK_VLP_SPU0_VLP, "vlp_spu0_vlp",
611 		vlp_spu0_vlp_parents, VLP_CLK_CFG_10, VLP_CLK_CFG_10_SET,
612 		VLP_CLK_CFG_10_CLR, 8, 3,
613 		VLP_CLK_CFG_UPDATE1, TOP_MUX_SPU0_VLP_SHIFT),
614 	MUX_CLR_SET_UPD(CLK_VLP_SPU1_VLP, "vlp_spu1_vlp",
615 		vlp_spu1_vlp_parents, VLP_CLK_CFG_10, VLP_CLK_CFG_10_SET,
616 		VLP_CLK_CFG_10_CLR, 16, 3,
617 		VLP_CLK_CFG_UPDATE1, TOP_MUX_SPU1_VLP_SHIFT),
618 };
619 
620 static const struct mtk_pll_data vlp_plls[] = {
621 	PLL_FENC(CLK_VLP_APLL1, "vlp_apll1", VLP_APLL1_CON0, 0x0358, 1, 0,
622 		 VLP_APLL1_CON1, 24, VLP_APLL1_CON2, 0, 32, 0),
623 	PLL_FENC(CLK_VLP_APLL2, "vlp_apll2", VLP_APLL2_CON0, 0x0358, 0, 0,
624 		 VLP_APLL2_CON1, 24, VLP_APLL2_CON2, 0, 32, 1),
625 };
626 
627 static const struct regmap_config vlpckgen_regmap_config = {
628 	.reg_bits = 32,
629 	.val_bits = 32,
630 	.reg_stride = 4,
631 	.max_register = 0x1000,
632 	.fast_io = true,
633 };
634 
635 static int clk_mt8196_vlp_probe(struct platform_device *pdev)
636 {
637 	static void __iomem *base;
638 	struct clk_hw_onecell_data *clk_data;
639 	int r;
640 	struct device_node *node = pdev->dev.of_node;
641 	struct device *dev = &pdev->dev;
642 	struct regmap *regmap;
643 
644 	clk_data = mtk_alloc_clk_data(ARRAY_SIZE(vlp_muxes) +
645 				      ARRAY_SIZE(vlp_plls) +
646 				      ARRAY_SIZE(vlp_divs));
647 	if (!clk_data)
648 		return -ENOMEM;
649 
650 	base = devm_platform_ioremap_resource(pdev, 0);
651 	if (IS_ERR(base))
652 		return PTR_ERR(base);
653 
654 	regmap = devm_regmap_init_mmio(dev, base, &vlpckgen_regmap_config);
655 	if (IS_ERR(regmap))
656 		return PTR_ERR(regmap);
657 
658 	r = mtk_clk_register_factors(vlp_divs, ARRAY_SIZE(vlp_divs), clk_data);
659 	if (r)
660 		goto free_clk_data;
661 
662 	r = mtk_clk_register_muxes(&pdev->dev, vlp_muxes, ARRAY_SIZE(vlp_muxes),
663 				   node, &mt8196_clk_vlp_lock, clk_data);
664 	if (r)
665 		goto unregister_factors;
666 
667 	r = mtk_clk_register_plls(node, vlp_plls, ARRAY_SIZE(vlp_plls),
668 				  clk_data);
669 	if (r)
670 		goto unregister_muxes;
671 
672 	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
673 	if (r)
674 		goto unregister_plls;
675 
676 	platform_set_drvdata(pdev, clk_data);
677 
678 	/* Initialize APLL tuner registers */
679 	regmap_write(regmap, VLP_APLL1_TUNER_CON0, VLP_APLL1_TUNER_CON0_VALUE);
680 	regmap_write(regmap, VLP_APLL2_TUNER_CON0, VLP_APLL2_TUNER_CON0_VALUE);
681 
682 	return r;
683 
684 unregister_plls:
685 	mtk_clk_unregister_plls(vlp_plls, ARRAY_SIZE(vlp_plls), clk_data);
686 unregister_muxes:
687 	mtk_clk_unregister_muxes(vlp_muxes, ARRAY_SIZE(vlp_muxes), clk_data);
688 unregister_factors:
689 	mtk_clk_unregister_factors(vlp_divs, ARRAY_SIZE(vlp_divs), clk_data);
690 free_clk_data:
691 	mtk_free_clk_data(clk_data);
692 
693 	return r;
694 }
695 
696 static void clk_mt8196_vlp_remove(struct platform_device *pdev)
697 {
698 	struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
699 	struct device_node *node = pdev->dev.of_node;
700 
701 	of_clk_del_provider(node);
702 	mtk_clk_unregister_plls(vlp_plls, ARRAY_SIZE(vlp_plls), clk_data);
703 	mtk_clk_unregister_muxes(vlp_muxes, ARRAY_SIZE(vlp_muxes), clk_data);
704 	mtk_clk_unregister_factors(vlp_divs, ARRAY_SIZE(vlp_divs), clk_data);
705 	mtk_free_clk_data(clk_data);
706 }
707 
708 static const struct of_device_id of_match_clk_mt8196_vlp_ck[] = {
709 	{ .compatible = "mediatek,mt8196-vlpckgen" },
710 	{ /* sentinel */ }
711 };
712 MODULE_DEVICE_TABLE(of, of_match_clk_mt8196_vlp_ck);
713 
714 static struct platform_driver clk_mt8196_vlp_drv = {
715 	.probe = clk_mt8196_vlp_probe,
716 	.remove = clk_mt8196_vlp_remove,
717 	.driver = {
718 		.name = "clk-mt8196-vlpck",
719 		.of_match_table = of_match_clk_mt8196_vlp_ck,
720 	},
721 };
722 
723 MODULE_DESCRIPTION("MediaTek MT8196 VLP clock generator driver");
724 module_platform_driver(clk_mt8196_vlp_drv);
725 MODULE_LICENSE("GPL");
726