File Index
Files and directories
Sign in
FILE

clk-mt8196-vlpckgen.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/mediatek/clk-mt8196-vlpckgen.c C
  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
168static DEFINE_SPINLOCK(mt8196_clk_vlp_lock);
169
170static 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
178static 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
187static const char * const vlp_scp_spi_parents[] = {
188	"clk26m",
189	"osc_d20",
190	"mainpll_d7_d2",
191	"mainpll_d5_d2"
192};
193
194static const char * const vlp_scp_iic_parents[] = {
195	"clk26m",
196	"osc_d20",
197	"mainpll_d5_d4",
198	"mainpll_d7_d2"
199};
200
201static 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
209static const char * const vlp_pwrap_ulposc_parents[] = {
210	"clk26m",
211	"osc_d20",
212	"osc_d14",
213	"osc_d10"
214};
215
216static const char * const vlp_spmi_32k_parents[] = {
217	"clk26m",
218	"clk32k",
219	"osc_d20",
220	"osc_d14",
221	"osc_d10"
222};
223
224static const char * const vlp_apxgpt_26m_b_parents[] = {
225	"clk26m",
226	"osc_d20"
227};
228
229static const char * const vlp_dpsw_parents[] = {
230	"clk26m",
231	"osc_d10",
232	"osc_d7",
233	"mainpll_d7_d4"
234};
235
236static const char * const vlp_dpsw_central_parents[] = {
237	"clk26m",
238	"osc_d10",
239	"osc_d7",
240	"mainpll_d7_d4"
241};
242
243static const char * const vlp_spmi_m_parents[] = {
244	"clk26m",
245	"osc_d20",
246	"osc_d14",
247	"osc_d10"
248};
249
250static const char * const vlp_dvfsrc_parents[] = {
251	"clk26m",
252	"osc_d20"
253};
254
255static const char * const vlp_pwm_vlp_parents[] = {
256	"clk26m",
257	"clk32k",
258	"osc_d20",
259	"osc_d8",
260	"mainpll_d4_d8"
261};
262
263static 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
271static const char * const vlp_systimer_26m_parents[] = {
272	"clk26m",
273	"osc_d20"
274};
275
276static const char * const vlp_sspm_parents[] = {
277	"clk26m",
278	"osc_d20",
279	"mainpll_d5_d2",
280	"osc_d2",
281	"mainpll_d6"
282};
283
284static const char * const vlp_srck_parents[] = {
285	"clk26m",
286	"osc_d20"
287};
288
289static 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
305static 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
320static const char * const vlp_sspm_26m_parents[] = {
321	"clk26m",
322	"osc_d20"
323};
324
325static const char * const vlp_ulposc_sspm_parents[] = {
326	"clk26m",
327	"osc_d2",
328	"mainpll_d4_d2"
329};
330
331static const char * const vlp_vlp_pbus_26m_parents[] = {
332	"clk26m",
333	"osc_d20"
334};
335
336static const char * const vlp_debug_err_flag_parents[] = {
337	"clk26m",
338	"osc_d20"
339};
340
341static const char * const vlp_dpmsrdma_parents[] = {
342	"clk26m",
343	"mainpll_d7_d2"
344};
345
346static const char * const vlp_vlp_pbus_156m_parents[] = {
347	"clk26m",
348	"osc_d2",
349	"mainpll_d7_d2",
350	"mainpll_d7"
351};
352
353static const char * const vlp_spm_parents[] = {
354	"clk26m",
355	"mainpll_d7_d4"
356};
357
358static const char * const vlp_mminfra_parents[] = {
359	"clk26m",
360	"osc_d4",
361	"mainpll_d3"
362};
363
364static const char * const vlp_usb_parents[] = {
365	"clk26m",
366	"mainpll_d9"
367};
368
369static const char * const vlp_noc_vlp_parents[] = {
370	"clk26m",
371	"osc_d20",
372	"mainpll_d9"
373};
374
375static const char * const vlp_audio_h_parents[] = {
376	"vlp_clk26m",
377	"vlp_apll1",
378	"vlp_apll2"
379};
380
381static const char * const vlp_aud_engen1_parents[] = {
382	"vlp_clk26m",
383	"apll1_d8",
384	"apll1_d4"
385};
386
387static const char * const vlp_aud_engen2_parents[] = {
388	"vlp_clk26m",
389	"apll2_d8",
390	"apll2_d4"
391};
392
393static const char * const vlp_aud_intbus_parents[] = {
394	"vlp_clk26m",
395	"mainpll_d7_d4",
396	"mainpll_d4_d4"
397};
398
399static const u8 vlp_aud_parent_index[] = { 1, 2, 3 };
400
401static const char * const vlp_spvlp_26m_parents[] = {
402	"clk26m",
403	"osc_d20"
404};
405
406static 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
416static 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
426static 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
620static 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
627static 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
635static 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
684unregister_plls:
685	mtk_clk_unregister_plls(vlp_plls, ARRAY_SIZE(vlp_plls), clk_data);
686unregister_muxes:
687	mtk_clk_unregister_muxes(vlp_muxes, ARRAY_SIZE(vlp_muxes), clk_data);
688unregister_factors:
689	mtk_clk_unregister_factors(vlp_divs, ARRAY_SIZE(vlp_divs), clk_data);
690free_clk_data:
691	mtk_free_clk_data(clk_data);
692
693	return r;
694}
695
696static 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
708static const struct of_device_id of_match_clk_mt8196_vlp_ck[] = {
709	{ .compatible = "mediatek,mt8196-vlpckgen" },
710	{ /* sentinel */ }
711};
712MODULE_DEVICE_TABLE(of, of_match_clk_mt8196_vlp_ck);
713
714static 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
723MODULE_DESCRIPTION("MediaTek MT8196 VLP clock generator driver");
724module_platform_driver(clk_mt8196_vlp_drv);
725MODULE_LICENSE("GPL");
~/ Read-only file preview.