Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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");