xref: /linux/drivers/clk/meson/t7-pll.c (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
1 // SPDX-License-Identifier: (GPL-2.0-only OR MIT)
2 /*
3  * Copyright (C) 2024-2025 Amlogic, Inc. All rights reserved.
4  * Author: Jian Hu <jian.hu@amlogic.com>
5  */
6 
7 #include <linux/clk-provider.h>
8 #include <linux/platform_device.h>
9 #include "clk-regmap.h"
10 #include "clk-pll.h"
11 #include "clk-mpll.h"
12 #include "meson-clkc-utils.h"
13 #include <dt-bindings/clock/amlogic,t7-pll-clkc.h>
14 
15 #define GP0PLL_CTRL0		0x00
16 #define GP0PLL_CTRL1		0x04
17 #define GP0PLL_CTRL2		0x08
18 #define GP0PLL_CTRL3		0x0c
19 #define GP0PLL_CTRL4		0x10
20 #define GP0PLL_CTRL5		0x14
21 #define GP0PLL_CTRL6		0x18
22 #define GP0PLL_STS		0x1c
23 
24 #define GP1PLL_CTRL0		0x00
25 #define GP1PLL_CTRL1		0x04
26 #define GP1PLL_CTRL2		0x08
27 #define GP1PLL_CTRL3		0x0c
28 #define GP1PLL_STS		0x1c
29 
30 #define HIFIPLL_CTRL0		0x00
31 #define HIFIPLL_CTRL1		0x04
32 #define HIFIPLL_CTRL2		0x08
33 #define HIFIPLL_CTRL3		0x0c
34 #define HIFIPLL_CTRL4		0x10
35 #define HIFIPLL_CTRL5		0x14
36 #define HIFIPLL_CTRL6		0x18
37 #define HIFIPLL_STS		0x1c
38 
39 #define PCIEPLL_CTRL0		0x00
40 #define PCIEPLL_CTRL1		0x04
41 #define PCIEPLL_CTRL2		0x08
42 #define PCIEPLL_CTRL3		0x0c
43 #define PCIEPLL_CTRL4		0x10
44 #define PCIEPLL_CTRL5		0x14
45 #define PCIEPLL_STS		0x18
46 
47 #define MPLL_CTRL0		0x00
48 #define MPLL_CTRL1		0x04
49 #define MPLL_CTRL2		0x08
50 #define MPLL_CTRL3		0x0c
51 #define MPLL_CTRL4		0x10
52 #define MPLL_CTRL5		0x14
53 #define MPLL_CTRL6		0x18
54 #define MPLL_CTRL7		0x1c
55 #define MPLL_CTRL8		0x20
56 #define MPLL_STS		0x24
57 
58 #define HDMIPLL_CTRL0		0x00
59 #define HDMIPLL_CTRL1		0x04
60 #define HDMIPLL_CTRL2		0x08
61 #define HDMIPLL_CTRL3		0x0c
62 #define HDMIPLL_CTRL4		0x10
63 #define HDMIPLL_CTRL5		0x14
64 #define HDMIPLL_CTRL6		0x18
65 #define HDMIPLL_STS		0x1c
66 
67 #define MCLK_PLL_CNTL0		0x00
68 #define MCLK_PLL_CNTL1		0x04
69 #define MCLK_PLL_CNTL2		0x08
70 #define MCLK_PLL_CNTL3		0x0c
71 #define MCLK_PLL_CNTL4		0x10
72 #define MCLK_PLL_STS		0x14
73 
74 static const struct pll_mult_range t7_media_pll_mult_range = {
75 	.min = 125,
76 	.max = 250,
77 };
78 
79 static const struct reg_sequence t7_gp0_init_regs[] = {
80 	{ .reg = GP0PLL_CTRL1,  .def = 0x00000000 },
81 	{ .reg = GP0PLL_CTRL2,  .def = 0x00000000 },
82 	{ .reg = GP0PLL_CTRL3,  .def = 0x48681c00 },
83 	{ .reg = GP0PLL_CTRL4,  .def = 0x88770290 },
84 	{ .reg = GP0PLL_CTRL5,  .def = 0x3927200a },
85 	{ .reg = GP0PLL_CTRL6,  .def = 0x56540000 },
86 };
87 
88 static struct clk_regmap t7_gp0_pll_dco = {
89 	.data = &(struct meson_clk_pll_data){
90 		.en = {
91 			.reg_off = GP0PLL_CTRL0,
92 			.shift   = 28,
93 			.width   = 1,
94 		},
95 		.m = {
96 			.reg_off = GP0PLL_CTRL0,
97 			.shift   = 0,
98 			.width   = 8,
99 		},
100 		.n = {
101 			.reg_off = GP0PLL_CTRL0,
102 			.shift   = 10,
103 			.width   = 5,
104 		},
105 		.l = {
106 			.reg_off = GP0PLL_STS,
107 			.shift   = 31,
108 			.width   = 1,
109 		},
110 		.rst = {
111 			.reg_off = GP0PLL_CTRL0,
112 			.shift   = 29,
113 			.width   = 1,
114 		},
115 		.range = &t7_media_pll_mult_range,
116 		.init_regs = t7_gp0_init_regs,
117 		.init_count = ARRAY_SIZE(t7_gp0_init_regs),
118 	},
119 	.hw.init = &(struct clk_init_data){
120 		.name = "gp0_pll_dco",
121 		.ops = &meson_clk_pll_ops,
122 		.parent_data = &(const struct clk_parent_data) {
123 			.fw_name = "in0",
124 		},
125 		.num_parents = 1,
126 	},
127 };
128 
129 static struct clk_regmap t7_gp0_pll = {
130 	.data = &(struct clk_regmap_div_data){
131 		.offset = GP0PLL_CTRL0,
132 		.shift = 16,
133 		.width = 3,
134 		.flags = CLK_DIVIDER_POWER_OF_TWO,
135 	},
136 	.hw.init = &(struct clk_init_data) {
137 		.name = "gp0_pll",
138 		.ops = &clk_regmap_divider_ops,
139 		.parent_hws = (const struct clk_hw *[]) {
140 			&t7_gp0_pll_dco.hw
141 		},
142 		.num_parents = 1,
143 		.flags = CLK_SET_RATE_PARENT,
144 	},
145 };
146 
147 /*
148  * Compared with GP0 PLL, GP1 PLL is a newly designed PLL with
149  * a DCO range of 1.6GHz to 3.2GHz.
150  */
151 static const struct pll_mult_range t7_gp1_pll_mult_range = {
152 	.min = 67,
153 	.max = 133,
154 };
155 
156 static const struct reg_sequence t7_gp1_init_regs[] = {
157 	{ .reg = GP1PLL_CTRL1,  .def = 0x1420500f },
158 	{ .reg = GP1PLL_CTRL2,  .def = 0x00023001 },
159 	{ .reg = GP1PLL_CTRL3,  .def = 0x00000000 },
160 };
161 
162 static struct clk_regmap t7_gp1_pll_dco = {
163 	.data = &(struct meson_clk_pll_data){
164 		.en = {
165 			.reg_off = GP1PLL_CTRL0,
166 			.shift   = 28,
167 			.width   = 1,
168 		},
169 		.m = {
170 			.reg_off = GP1PLL_CTRL0,
171 			.shift   = 0,
172 			.width   = 8,
173 		},
174 		.n = {
175 			.reg_off = GP1PLL_CTRL0,
176 			.shift   = 16,
177 			.width   = 5,
178 		},
179 		.l = {
180 			.reg_off = GP1PLL_STS,
181 			.shift   = 31,
182 			.width   = 1,
183 		},
184 		.rst = {
185 			.reg_off = GP1PLL_CTRL0,
186 			.shift   = 29,
187 			.width   = 1,
188 		},
189 		.range = &t7_gp1_pll_mult_range,
190 		.init_regs = t7_gp1_init_regs,
191 		.init_count = ARRAY_SIZE(t7_gp1_init_regs),
192 	},
193 	.hw.init = &(struct clk_init_data){
194 		.name = "gp1_pll_dco",
195 		.ops = &meson_clk_pll_ops,
196 		.parent_data = &(const struct clk_parent_data) {
197 			.fw_name = "in0",
198 		},
199 		.num_parents = 1,
200 	},
201 };
202 
203 static struct clk_regmap t7_gp1_pll = {
204 	.data = &(struct clk_regmap_div_data){
205 		.offset = GP1PLL_CTRL0,
206 		.shift = 12,
207 		.width = 3,
208 		.flags = CLK_DIVIDER_POWER_OF_TWO,
209 	},
210 	.hw.init = &(struct clk_init_data) {
211 		.name = "gp1_pll",
212 		.ops = &clk_regmap_divider_ops,
213 		.parent_hws = (const struct clk_hw *[]) {
214 			&t7_gp1_pll_dco.hw
215 		},
216 		.num_parents = 1,
217 		.flags = CLK_SET_RATE_PARENT,
218 	},
219 };
220 
221 static const struct reg_sequence t7_hifi_init_regs[] = {
222 	{ .reg = HIFIPLL_CTRL1, .def = 0x00000000 },
223 	{ .reg = HIFIPLL_CTRL2, .def = 0x00000000 },
224 	{ .reg = HIFIPLL_CTRL3, .def = 0x6a285c00 },
225 	{ .reg = HIFIPLL_CTRL4, .def = 0x65771290 },
226 	{ .reg = HIFIPLL_CTRL5, .def = 0x3927200a },
227 	{ .reg = HIFIPLL_CTRL6, .def = 0x56540000 }
228 };
229 
230 static struct clk_regmap t7_hifi_pll_dco = {
231 	.data = &(struct meson_clk_pll_data){
232 		.en = {
233 			.reg_off = HIFIPLL_CTRL0,
234 			.shift   = 28,
235 			.width   = 1,
236 		},
237 		.m = {
238 			.reg_off = HIFIPLL_CTRL0,
239 			.shift   = 0,
240 			.width   = 8,
241 		},
242 		.n = {
243 			.reg_off = HIFIPLL_CTRL0,
244 			.shift   = 10,
245 			.width   = 5,
246 		},
247 		.frac = {
248 			.reg_off = HIFIPLL_CTRL1,
249 			.shift   = 0,
250 			.width   = 17,
251 		},
252 		.l = {
253 			.reg_off = HIFIPLL_STS,
254 			.shift   = 31,
255 			.width   = 1,
256 		},
257 		.rst = {
258 			.reg_off = HIFIPLL_CTRL0,
259 			.shift   = 29,
260 			.width   = 1,
261 		},
262 		.range = &t7_media_pll_mult_range,
263 		.init_regs = t7_hifi_init_regs,
264 		.init_count = ARRAY_SIZE(t7_hifi_init_regs),
265 		.frac_max = 100000,
266 	},
267 	.hw.init = &(struct clk_init_data){
268 		.name = "hifi_pll_dco",
269 		.ops = &meson_clk_pll_ops,
270 		.parent_data = &(const struct clk_parent_data) {
271 			.fw_name = "in0",
272 		},
273 		.num_parents = 1,
274 	},
275 };
276 
277 static struct clk_regmap t7_hifi_pll = {
278 	.data = &(struct clk_regmap_div_data){
279 		.offset = HIFIPLL_CTRL0,
280 		.shift = 16,
281 		.width = 2,
282 		.flags = CLK_DIVIDER_POWER_OF_TWO,
283 	},
284 	.hw.init = &(struct clk_init_data) {
285 		.name = "hifi_pll",
286 		.ops = &clk_regmap_divider_ops,
287 		.parent_hws = (const struct clk_hw *[]) {
288 			&t7_hifi_pll_dco.hw
289 		},
290 		.num_parents = 1,
291 		.flags = CLK_SET_RATE_PARENT,
292 	},
293 };
294 
295 /*
296  * The T7 PCIE PLL is fined tuned to deliver a very precise
297  * 100MHz reference clock for the PCIe Analog PHY, and thus requires
298  * a strict register sequence to enable the PLL.
299  */
300 static const struct reg_sequence t7_pcie_pll_init_regs[] = {
301 	{ .reg = PCIEPLL_CTRL0,	.def = 0x200c04c8 },
302 	{ .reg = PCIEPLL_CTRL0,	.def = 0x300c04c8 },
303 	{ .reg = PCIEPLL_CTRL1,	.def = 0x30000000 },
304 	{ .reg = PCIEPLL_CTRL2,	.def = 0x00001100 },
305 	{ .reg = PCIEPLL_CTRL3,	.def = 0x10058e00 },
306 	{ .reg = PCIEPLL_CTRL4,	.def = 0x000100c0 },
307 	{ .reg = PCIEPLL_CTRL5,	.def = 0x68000048 },
308 	{ .reg = PCIEPLL_CTRL5,	.def = 0x68000068, .delay_us = 20 },
309 	{ .reg = PCIEPLL_CTRL4,	.def = 0x008100c0, .delay_us = 20 },
310 	{ .reg = PCIEPLL_CTRL0,	.def = 0x340c04c8 },
311 	{ .reg = PCIEPLL_CTRL0,	.def = 0x140c04c8, .delay_us = 20 },
312 	{ .reg = PCIEPLL_CTRL2,	.def = 0x00001000 }
313 };
314 
315 static struct clk_regmap t7_pcie_pll_dco = {
316 	.data = &(struct meson_clk_pll_data){
317 		.en = {
318 			.reg_off = PCIEPLL_CTRL0,
319 			.shift   = 28,
320 			.width   = 1,
321 		},
322 		.m = {
323 			.reg_off = PCIEPLL_CTRL0,
324 			.shift   = 0,
325 			.width   = 8,
326 		},
327 		.n = {
328 			.reg_off = PCIEPLL_CTRL0,
329 			.shift   = 10,
330 			.width   = 5,
331 		},
332 		.l = {
333 			.reg_off = PCIEPLL_CTRL0,
334 			.shift   = 31,
335 			.width   = 1,
336 		},
337 		.rst = {
338 			.reg_off = PCIEPLL_CTRL0,
339 			.shift   = 29,
340 			.width   = 1,
341 		},
342 		.init_regs = t7_pcie_pll_init_regs,
343 		.init_count = ARRAY_SIZE(t7_pcie_pll_init_regs),
344 	},
345 	.hw.init = &(struct clk_init_data){
346 		.name = "pcie_pll_dco",
347 		.ops = &meson_clk_pcie_pll_ops,
348 		.parent_data = &(const struct clk_parent_data) {
349 			.fw_name = "in0",
350 		},
351 		.num_parents = 1,
352 	},
353 };
354 
355 static struct clk_fixed_factor t7_pcie_pll_dco_div2 = {
356 	.mult = 1,
357 	.div = 2,
358 	.hw.init = &(struct clk_init_data){
359 		.name = "pcie_pll_dco_div2",
360 		.ops = &clk_fixed_factor_ops,
361 		.parent_hws = (const struct clk_hw *[]) {
362 			&t7_pcie_pll_dco.hw
363 		},
364 		.num_parents = 1,
365 		.flags = CLK_SET_RATE_PARENT,
366 	},
367 };
368 
369 static struct clk_regmap t7_pcie_pll_od = {
370 	.data = &(struct clk_regmap_div_data){
371 		.offset = PCIEPLL_CTRL0,
372 		.shift = 16,
373 		.width = 5,
374 		/* the divisor is 32 when [16:21] = 0 */
375 		.flags = CLK_DIVIDER_MAX_AT_ZERO,
376 	},
377 	.hw.init = &(struct clk_init_data){
378 		.name = "pcie_pll_od",
379 		.ops = &clk_regmap_divider_ops,
380 		.parent_hws = (const struct clk_hw *[]) {
381 			&t7_pcie_pll_dco_div2.hw
382 		},
383 		.num_parents = 1,
384 		.flags = CLK_SET_RATE_PARENT,
385 	},
386 };
387 
388 static struct clk_fixed_factor t7_pcie_pll = {
389 	.mult = 1,
390 	.div = 2,
391 	.hw.init = &(struct clk_init_data){
392 		.name = "pcie_pll",
393 		.ops = &clk_fixed_factor_ops,
394 		.parent_hws = (const struct clk_hw *[]) {
395 			&t7_pcie_pll_od.hw
396 		},
397 		.num_parents = 1,
398 		.flags = CLK_SET_RATE_PARENT,
399 	},
400 };
401 
402 static struct clk_fixed_factor t7_mpll_prediv = {
403 	.mult = 1,
404 	.div = 2,
405 	.hw.init = &(struct clk_init_data){
406 		.name = "mpll_prediv",
407 		.ops = &clk_fixed_factor_ops,
408 		.parent_data = &(const struct clk_parent_data) {
409 			.fw_name = "in0",
410 		},
411 		.num_parents = 1,
412 	},
413 };
414 
415 static const struct reg_sequence t7_mpll0_init_regs[] = {
416 	{ .reg = MPLL_CTRL2, .def = 0x40000033 }
417 };
418 
419 static struct clk_regmap t7_mpll0_div = {
420 	.data = &(struct meson_clk_mpll_data){
421 		.sdm = {
422 			.reg_off = MPLL_CTRL1,
423 			.shift   = 0,
424 			.width   = 14,
425 		},
426 		.sdm_en = {
427 			.reg_off = MPLL_CTRL1,
428 			.shift   = 30,
429 			.width	 = 1,
430 		},
431 		.n2 = {
432 			.reg_off = MPLL_CTRL1,
433 			.shift   = 20,
434 			.width   = 9,
435 		},
436 		.ssen = {
437 			.reg_off = MPLL_CTRL1,
438 			.shift   = 29,
439 			.width	 = 1,
440 		},
441 		.init_regs = t7_mpll0_init_regs,
442 		.init_count = ARRAY_SIZE(t7_mpll0_init_regs),
443 	},
444 	.hw.init = &(struct clk_init_data){
445 		.name = "mpll0_div",
446 		.ops = &meson_clk_mpll_ops,
447 		.parent_hws = (const struct clk_hw *[]) {
448 			&t7_mpll_prediv.hw
449 		},
450 		.num_parents = 1,
451 	},
452 };
453 
454 static struct clk_regmap t7_mpll0 = {
455 	.data = &(struct clk_regmap_gate_data){
456 		.offset = MPLL_CTRL1,
457 		.bit_idx = 31,
458 	},
459 	.hw.init = &(struct clk_init_data){
460 		.name = "mpll0",
461 		.ops = &clk_regmap_gate_ops,
462 		.parent_hws = (const struct clk_hw *[]) { &t7_mpll0_div.hw },
463 		.num_parents = 1,
464 		.flags = CLK_SET_RATE_PARENT,
465 	},
466 };
467 
468 static const struct reg_sequence t7_mpll1_init_regs[] = {
469 	{ .reg = MPLL_CTRL4,	.def = 0x40000033 }
470 };
471 
472 static struct clk_regmap t7_mpll1_div = {
473 	.data = &(struct meson_clk_mpll_data){
474 		.sdm = {
475 			.reg_off = MPLL_CTRL3,
476 			.shift   = 0,
477 			.width   = 14,
478 		},
479 		.sdm_en = {
480 			.reg_off = MPLL_CTRL3,
481 			.shift   = 30,
482 			.width	 = 1,
483 		},
484 		.n2 = {
485 			.reg_off = MPLL_CTRL3,
486 			.shift   = 20,
487 			.width   = 9,
488 		},
489 		.ssen = {
490 			.reg_off = MPLL_CTRL3,
491 			.shift   = 29,
492 			.width	 = 1,
493 		},
494 		.init_regs = t7_mpll1_init_regs,
495 		.init_count = ARRAY_SIZE(t7_mpll1_init_regs),
496 	},
497 	.hw.init = &(struct clk_init_data){
498 		.name = "mpll1_div",
499 		.ops = &meson_clk_mpll_ops,
500 		.parent_hws = (const struct clk_hw *[]) {
501 			&t7_mpll_prediv.hw
502 		},
503 		.num_parents = 1,
504 	},
505 };
506 
507 static struct clk_regmap t7_mpll1 = {
508 	.data = &(struct clk_regmap_gate_data){
509 		.offset = MPLL_CTRL3,
510 		.bit_idx = 31,
511 	},
512 	.hw.init = &(struct clk_init_data){
513 		.name = "mpll1",
514 		.ops = &clk_regmap_gate_ops,
515 		.parent_hws = (const struct clk_hw *[]) { &t7_mpll1_div.hw },
516 		.num_parents = 1,
517 		.flags = CLK_SET_RATE_PARENT,
518 	},
519 };
520 
521 static const struct reg_sequence t7_mpll2_init_regs[] = {
522 	{ .reg = MPLL_CTRL6, .def = 0x40000033 }
523 };
524 
525 static struct clk_regmap t7_mpll2_div = {
526 	.data = &(struct meson_clk_mpll_data){
527 		.sdm = {
528 			.reg_off = MPLL_CTRL5,
529 			.shift   = 0,
530 			.width   = 14,
531 		},
532 		.sdm_en = {
533 			.reg_off = MPLL_CTRL5,
534 			.shift   = 30,
535 			.width	 = 1,
536 		},
537 		.n2 = {
538 			.reg_off = MPLL_CTRL5,
539 			.shift   = 20,
540 			.width   = 9,
541 		},
542 		.ssen = {
543 			.reg_off = MPLL_CTRL5,
544 			.shift   = 29,
545 			.width	 = 1,
546 		},
547 		.init_regs = t7_mpll2_init_regs,
548 		.init_count = ARRAY_SIZE(t7_mpll2_init_regs),
549 	},
550 	.hw.init = &(struct clk_init_data){
551 		.name = "mpll2_div",
552 		.ops = &meson_clk_mpll_ops,
553 		.parent_hws = (const struct clk_hw *[]) {
554 			&t7_mpll_prediv.hw
555 		},
556 		.num_parents = 1,
557 	},
558 };
559 
560 static struct clk_regmap t7_mpll2 = {
561 	.data = &(struct clk_regmap_gate_data){
562 		.offset = MPLL_CTRL5,
563 		.bit_idx = 31,
564 	},
565 	.hw.init = &(struct clk_init_data){
566 		.name = "mpll2",
567 		.ops = &clk_regmap_gate_ops,
568 		.parent_hws = (const struct clk_hw *[]) { &t7_mpll2_div.hw },
569 		.num_parents = 1,
570 		.flags = CLK_SET_RATE_PARENT,
571 	},
572 };
573 
574 static const struct reg_sequence t7_mpll3_init_regs[] = {
575 	{ .reg = MPLL_CTRL8, .def = 0x40000033 }
576 };
577 
578 static struct clk_regmap t7_mpll3_div = {
579 	.data = &(struct meson_clk_mpll_data){
580 		.sdm = {
581 			.reg_off = MPLL_CTRL7,
582 			.shift   = 0,
583 			.width   = 14,
584 		},
585 		.sdm_en = {
586 			.reg_off = MPLL_CTRL7,
587 			.shift   = 30,
588 			.width	 = 1,
589 		},
590 		.n2 = {
591 			.reg_off = MPLL_CTRL7,
592 			.shift   = 20,
593 			.width   = 9,
594 		},
595 		.ssen = {
596 			.reg_off = MPLL_CTRL7,
597 			.shift   = 29,
598 			.width	 = 1,
599 		},
600 		.init_regs = t7_mpll3_init_regs,
601 		.init_count = ARRAY_SIZE(t7_mpll3_init_regs),
602 	},
603 	.hw.init = &(struct clk_init_data){
604 		.name = "mpll3_div",
605 		.ops = &meson_clk_mpll_ops,
606 		.parent_hws = (const struct clk_hw *[]) {
607 			&t7_mpll_prediv.hw
608 		},
609 		.num_parents = 1,
610 	},
611 };
612 
613 static struct clk_regmap t7_mpll3 = {
614 	.data = &(struct clk_regmap_gate_data){
615 		.offset = MPLL_CTRL7,
616 		.bit_idx = 31,
617 	},
618 	.hw.init = &(struct clk_init_data){
619 		.name = "mpll3",
620 		.ops = &clk_regmap_gate_ops,
621 		.parent_hws = (const struct clk_hw *[]) { &t7_mpll3_div.hw },
622 		.num_parents = 1,
623 		.flags = CLK_SET_RATE_PARENT,
624 	},
625 };
626 
627 static const struct reg_sequence t7_hdmi_init_regs[] = {
628 	{ .reg = HDMIPLL_CTRL1, .def = 0x00000000 },
629 	{ .reg = HDMIPLL_CTRL2, .def = 0x00000000 },
630 	{ .reg = HDMIPLL_CTRL3, .def = 0x6a28dc00 },
631 	{ .reg = HDMIPLL_CTRL4, .def = 0x65771290 },
632 	{ .reg = HDMIPLL_CTRL5, .def = 0x39272000 },
633 	{ .reg = HDMIPLL_CTRL6, .def = 0x56540000 }
634 };
635 
636 static struct clk_regmap t7_hdmi_pll_dco = {
637 	.data = &(struct meson_clk_pll_data){
638 		.en = {
639 			.reg_off = HDMIPLL_CTRL0,
640 			.shift   = 28,
641 			.width   = 1,
642 		},
643 		.m = {
644 			.reg_off = HDMIPLL_CTRL0,
645 			.shift   = 0,
646 			.width   = 9,
647 		},
648 		.n = {
649 			.reg_off = HDMIPLL_CTRL0,
650 			.shift   = 10,
651 			.width   = 5,
652 		},
653 		.l = {
654 			.reg_off = HDMIPLL_CTRL0,
655 			.shift   = 31,
656 			.width   = 1,
657 		},
658 		.rst = {
659 			.reg_off = HDMIPLL_CTRL0,
660 			.shift   = 29,
661 			.width   = 1,
662 		},
663 		.range = &t7_media_pll_mult_range,
664 		.init_regs = t7_hdmi_init_regs,
665 		.init_count = ARRAY_SIZE(t7_hdmi_init_regs),
666 	},
667 	.hw.init = &(struct clk_init_data){
668 		.name = "hdmi_pll_dco",
669 		.ops = &meson_clk_pll_ops,
670 		.parent_data = (const struct clk_parent_data []) {
671 			{ .fw_name = "in0", }
672 		},
673 		.num_parents = 1,
674 	},
675 };
676 
677 static struct clk_regmap t7_hdmi_pll_od = {
678 	.data = &(struct clk_regmap_div_data){
679 		.offset = HDMIPLL_CTRL0,
680 		.shift = 16,
681 		.width = 4,
682 		.flags = CLK_DIVIDER_POWER_OF_TWO,
683 	},
684 	.hw.init = &(struct clk_init_data){
685 		.name = "hdmi_pll_od",
686 		.ops = &clk_regmap_divider_ops,
687 		.parent_hws = (const struct clk_hw *[]) {
688 			&t7_hdmi_pll_dco.hw
689 		},
690 		.num_parents = 1,
691 		.flags = CLK_SET_RATE_PARENT,
692 	},
693 };
694 
695 static struct clk_regmap t7_hdmi_pll = {
696 	.data = &(struct clk_regmap_div_data){
697 		.offset = HDMIPLL_CTRL0,
698 		.shift = 20,
699 		.width = 2,
700 		.flags = CLK_DIVIDER_POWER_OF_TWO,
701 	},
702 	.hw.init = &(struct clk_init_data){
703 		.name = "hdmi_pll",
704 		.ops = &clk_regmap_divider_ops,
705 		.parent_hws = (const struct clk_hw *[]) {
706 			&t7_hdmi_pll_od.hw
707 		},
708 		.num_parents = 1,
709 		.flags = CLK_SET_RATE_PARENT,
710 	},
711 };
712 
713 static const struct pll_mult_range t7_mclk_pll_mult_range = {
714 	.min = 67,
715 	.max = 133,
716 };
717 
718 static const struct reg_sequence t7_mclk_init_regs[] = {
719 	{ .reg = MCLK_PLL_CNTL1, .def = 0x1470500f },
720 	{ .reg = MCLK_PLL_CNTL2, .def = 0x00023001 },
721 	{ .reg = MCLK_PLL_CNTL3, .def = 0x18180000 },
722 	{ .reg = MCLK_PLL_CNTL4, .def = 0x00180303 },
723 };
724 
725 static struct clk_regmap t7_mclk_pll_dco = {
726 	.data = &(struct meson_clk_pll_data){
727 		.en = {
728 			.reg_off = MCLK_PLL_CNTL0,
729 			.shift   = 28,
730 			.width   = 1,
731 		},
732 		.m = {
733 			.reg_off = MCLK_PLL_CNTL0,
734 			.shift   = 0,
735 			.width   = 8,
736 		},
737 		.n = {
738 			.reg_off = MCLK_PLL_CNTL0,
739 			.shift   = 16,
740 			.width   = 5,
741 		},
742 		.l = {
743 			.reg_off = MCLK_PLL_CNTL0,
744 			.shift   = 31,
745 			.width   = 1,
746 		},
747 		.rst = {
748 			.reg_off = MCLK_PLL_CNTL0,
749 			.shift   = 29,
750 			.width   = 1,
751 		},
752 		.l_detect = {
753 			.reg_off = MCLK_PLL_CNTL2,
754 			.shift   = 6,
755 			.width   = 1,
756 		},
757 		.range = &t7_mclk_pll_mult_range,
758 		.init_regs = t7_mclk_init_regs,
759 		.init_count = ARRAY_SIZE(t7_mclk_init_regs),
760 	},
761 	.hw.init = &(struct clk_init_data){
762 		.name = "mclk_pll_dco",
763 		.ops = &meson_clk_pll_ops,
764 		.parent_data = &(const struct clk_parent_data) {
765 			.fw_name = "in0",
766 		},
767 		.num_parents = 1,
768 	},
769 };
770 
771 /* max div is 16 */
772 static const struct clk_div_table t7_mclk_div[] = {
773 	{ .val = 0, .div = 1 },
774 	{ .val = 1, .div = 2 },
775 	{ .val = 2, .div = 4 },
776 	{ .val = 3, .div = 8 },
777 	{ .val = 4, .div = 16 },
778 	{ /* sentinel */ }
779 };
780 
781 static struct clk_regmap t7_mclk_pre_od = {
782 	.data = &(struct clk_regmap_div_data){
783 		.offset = MCLK_PLL_CNTL0,
784 		.shift = 12,
785 		.width = 3,
786 		.table = t7_mclk_div,
787 	},
788 	.hw.init = &(struct clk_init_data){
789 		.name = "mclk_pre_od",
790 		.ops = &clk_regmap_divider_ops,
791 		.parent_hws = (const struct clk_hw *[]) {
792 			&t7_mclk_pll_dco.hw
793 		},
794 		.num_parents = 1,
795 		.flags = CLK_SET_RATE_PARENT,
796 	},
797 };
798 
799 static struct clk_regmap t7_mclk_pll = {
800 	.data = &(struct clk_regmap_div_data){
801 		.offset = MCLK_PLL_CNTL4,
802 		.shift = 16,
803 		.width = 5,
804 		.flags = CLK_DIVIDER_ONE_BASED,
805 	},
806 	.hw.init = &(struct clk_init_data){
807 		.name = "mclk_pll",
808 		.ops = &clk_regmap_divider_ops,
809 		.parent_hws = (const struct clk_hw *[]) {
810 			&t7_mclk_pre_od.hw
811 		},
812 		.num_parents = 1,
813 		.flags = CLK_SET_RATE_PARENT,
814 	},
815 };
816 
817 static struct clk_regmap t7_mclk_0_sel = {
818 	.data = &(struct clk_regmap_mux_data){
819 		.offset = MCLK_PLL_CNTL4,
820 		.mask = 0x3,
821 		.shift = 4,
822 	},
823 	.hw.init = &(struct clk_init_data){
824 		.name = "mclk_0_sel",
825 		.ops = &clk_regmap_mux_ops,
826 		.parent_data = (const struct clk_parent_data []) {
827 			{ .hw = &t7_mclk_pll.hw },
828 			{ .fw_name = "in1", },
829 			{ .fw_name = "in2", },
830 		},
831 		.num_parents = 3,
832 	},
833 };
834 
835 static struct clk_fixed_factor t7_mclk_0_div2 = {
836 	.mult = 1,
837 	.div = 2,
838 	.hw.init = &(struct clk_init_data){
839 		.name = "mclk_0_div2",
840 		.ops = &clk_fixed_factor_ops,
841 		.parent_hws = (const struct clk_hw *[]) { &t7_mclk_0_sel.hw },
842 		.num_parents = 1,
843 		.flags = CLK_SET_RATE_PARENT,
844 	},
845 };
846 
847 static struct clk_regmap t7_mclk_0_pre = {
848 	.data = &(struct clk_regmap_gate_data){
849 		.offset = MCLK_PLL_CNTL4,
850 		.bit_idx = 2,
851 	},
852 	.hw.init = &(struct clk_init_data) {
853 		.name = "mclk_0_pre",
854 		.ops = &clk_regmap_gate_ops,
855 		.parent_hws = (const struct clk_hw *[]) {
856 			&t7_mclk_0_div2.hw
857 		},
858 		.num_parents = 1,
859 		.flags = CLK_SET_RATE_PARENT,
860 	},
861 };
862 
863 static struct clk_regmap t7_mclk_0 = {
864 	.data = &(struct clk_regmap_gate_data){
865 		.offset = MCLK_PLL_CNTL4,
866 		.bit_idx = 0,
867 	},
868 	.hw.init = &(struct clk_init_data) {
869 		.name = "mclk_0",
870 		.ops = &clk_regmap_gate_ops,
871 		.parent_hws = (const struct clk_hw *[]) {
872 			&t7_mclk_0_pre.hw
873 		},
874 		.num_parents = 1,
875 		.flags = CLK_SET_RATE_PARENT,
876 	},
877 };
878 
879 static struct clk_regmap t7_mclk_1_sel = {
880 	.data = &(struct clk_regmap_mux_data){
881 		.offset = MCLK_PLL_CNTL4,
882 		.mask = 0x3,
883 		.shift = 12,
884 	},
885 	.hw.init = &(struct clk_init_data){
886 		.name = "mclk_1_sel",
887 		.ops = &clk_regmap_mux_ops,
888 		.parent_data = (const struct clk_parent_data []) {
889 			{ .hw = &t7_mclk_pll.hw },
890 			{ .fw_name = "in1", },
891 			{ .fw_name = "in2", },
892 		},
893 		.num_parents = 3,
894 	},
895 };
896 
897 static struct clk_fixed_factor t7_mclk_1_div2 = {
898 	.mult = 1,
899 	.div = 2,
900 	.hw.init = &(struct clk_init_data){
901 		.name = "mclk_1_div2",
902 		.ops = &clk_fixed_factor_ops,
903 		.parent_hws = (const struct clk_hw *[]) { &t7_mclk_1_sel.hw },
904 		.num_parents = 1,
905 		.flags = CLK_SET_RATE_PARENT,
906 	},
907 };
908 
909 static struct clk_regmap t7_mclk_1_pre = {
910 	.data = &(struct clk_regmap_gate_data){
911 		.offset = MCLK_PLL_CNTL4,
912 		.bit_idx = 10,
913 	},
914 	.hw.init = &(struct clk_init_data) {
915 		.name = "mclk_1_pre",
916 		.ops = &clk_regmap_gate_ops,
917 		.parent_hws = (const struct clk_hw *[]) {
918 			&t7_mclk_1_div2.hw
919 		},
920 		.num_parents = 1,
921 		.flags = CLK_SET_RATE_PARENT,
922 	},
923 };
924 
925 static struct clk_regmap t7_mclk_1 = {
926 	.data = &(struct clk_regmap_gate_data){
927 		.offset = MCLK_PLL_CNTL4,
928 		.bit_idx = 8,
929 	},
930 	.hw.init = &(struct clk_init_data) {
931 		.name = "mclk_1",
932 		.ops = &clk_regmap_gate_ops,
933 		.parent_hws = (const struct clk_hw *[]) {
934 			&t7_mclk_1_pre.hw
935 		},
936 		.num_parents = 1,
937 		.flags = CLK_SET_RATE_PARENT,
938 	},
939 };
940 
941 static struct clk_hw *t7_gp0_hw_clks[] = {
942 	[CLKID_GP0_PLL_DCO]		= &t7_gp0_pll_dco.hw,
943 	[CLKID_GP0_PLL]			= &t7_gp0_pll.hw,
944 };
945 
946 static struct clk_hw *t7_gp1_hw_clks[] = {
947 	[CLKID_GP1_PLL_DCO]		= &t7_gp1_pll_dco.hw,
948 	[CLKID_GP1_PLL]			= &t7_gp1_pll.hw,
949 };
950 
951 static struct clk_hw *t7_hifi_hw_clks[] = {
952 	[CLKID_HIFI_PLL_DCO]		= &t7_hifi_pll_dco.hw,
953 	[CLKID_HIFI_PLL]		= &t7_hifi_pll.hw,
954 };
955 
956 static struct clk_hw *t7_pcie_hw_clks[] = {
957 	[CLKID_PCIE_PLL_DCO]		= &t7_pcie_pll_dco.hw,
958 	[CLKID_PCIE_PLL_DCO_DIV2]	= &t7_pcie_pll_dco_div2.hw,
959 	[CLKID_PCIE_PLL_OD]		= &t7_pcie_pll_od.hw,
960 	[CLKID_PCIE_PLL]		= &t7_pcie_pll.hw,
961 };
962 
963 static struct clk_hw *t7_mpll_hw_clks[] = {
964 	[CLKID_MPLL_PREDIV]		= &t7_mpll_prediv.hw,
965 	[CLKID_MPLL0_DIV]		= &t7_mpll0_div.hw,
966 	[CLKID_MPLL0]			= &t7_mpll0.hw,
967 	[CLKID_MPLL1_DIV]		= &t7_mpll1_div.hw,
968 	[CLKID_MPLL1]			= &t7_mpll1.hw,
969 	[CLKID_MPLL2_DIV]		= &t7_mpll2_div.hw,
970 	[CLKID_MPLL2]			= &t7_mpll2.hw,
971 	[CLKID_MPLL3_DIV]		= &t7_mpll3_div.hw,
972 	[CLKID_MPLL3]			= &t7_mpll3.hw,
973 };
974 
975 static struct clk_hw *t7_hdmi_hw_clks[] = {
976 	[CLKID_HDMI_PLL_DCO]		= &t7_hdmi_pll_dco.hw,
977 	[CLKID_HDMI_PLL_OD]		= &t7_hdmi_pll_od.hw,
978 	[CLKID_HDMI_PLL]		= &t7_hdmi_pll.hw,
979 };
980 
981 static struct clk_hw *t7_mclk_hw_clks[] = {
982 	[CLKID_MCLK_PLL_DCO]		= &t7_mclk_pll_dco.hw,
983 	[CLKID_MCLK_PRE]		= &t7_mclk_pre_od.hw,
984 	[CLKID_MCLK_PLL]		= &t7_mclk_pll.hw,
985 	[CLKID_MCLK_0_SEL]		= &t7_mclk_0_sel.hw,
986 	[CLKID_MCLK_0_DIV2]		= &t7_mclk_0_div2.hw,
987 	[CLKID_MCLK_0_PRE]		= &t7_mclk_0_pre.hw,
988 	[CLKID_MCLK_0]			= &t7_mclk_0.hw,
989 	[CLKID_MCLK_1_SEL]		= &t7_mclk_1_sel.hw,
990 	[CLKID_MCLK_1_DIV2]		= &t7_mclk_1_div2.hw,
991 	[CLKID_MCLK_1_PRE]		= &t7_mclk_1_pre.hw,
992 	[CLKID_MCLK_1]			= &t7_mclk_1.hw,
993 };
994 
995 static const struct meson_clkc_data t7_gp0_data = {
996 	.hw_clks = {
997 		.hws = t7_gp0_hw_clks,
998 		.num = ARRAY_SIZE(t7_gp0_hw_clks),
999 	},
1000 };
1001 
1002 static const struct meson_clkc_data t7_gp1_data = {
1003 	.hw_clks = {
1004 		.hws = t7_gp1_hw_clks,
1005 		.num = ARRAY_SIZE(t7_gp1_hw_clks),
1006 	},
1007 };
1008 
1009 static const struct meson_clkc_data t7_hifi_data = {
1010 	.hw_clks = {
1011 		.hws = t7_hifi_hw_clks,
1012 		.num = ARRAY_SIZE(t7_hifi_hw_clks),
1013 	},
1014 };
1015 
1016 static const struct meson_clkc_data t7_pcie_data = {
1017 	.hw_clks = {
1018 		.hws = t7_pcie_hw_clks,
1019 		.num = ARRAY_SIZE(t7_pcie_hw_clks),
1020 	},
1021 };
1022 
1023 static const struct reg_sequence t7_mpll_init_regs[] = {
1024 	{ .reg = MPLL_CTRL0, .def = 0x00000543 }
1025 };
1026 
1027 static const struct meson_clkc_data t7_mpll_data = {
1028 	.hw_clks = {
1029 		.hws = t7_mpll_hw_clks,
1030 		.num = ARRAY_SIZE(t7_mpll_hw_clks),
1031 	},
1032 	.init_regs = t7_mpll_init_regs,
1033 	.init_count = ARRAY_SIZE(t7_mpll_init_regs),
1034 };
1035 
1036 static const struct meson_clkc_data t7_hdmi_data = {
1037 	.hw_clks = {
1038 		.hws = t7_hdmi_hw_clks,
1039 		.num = ARRAY_SIZE(t7_hdmi_hw_clks),
1040 	},
1041 };
1042 
1043 static const struct meson_clkc_data t7_mclk_data = {
1044 	.hw_clks = {
1045 		.hws = t7_mclk_hw_clks,
1046 		.num = ARRAY_SIZE(t7_mclk_hw_clks),
1047 	},
1048 };
1049 
1050 static const struct of_device_id t7_pll_clkc_match_table[] = {
1051 	{ .compatible = "amlogic,t7-gp0-pll",	.data = &t7_gp0_data, },
1052 	{ .compatible = "amlogic,t7-gp1-pll",	.data = &t7_gp1_data, },
1053 	{ .compatible = "amlogic,t7-hifi-pll",	.data = &t7_hifi_data, },
1054 	{ .compatible = "amlogic,t7-pcie-pll",	.data = &t7_pcie_data, },
1055 	{ .compatible = "amlogic,t7-mpll",	.data = &t7_mpll_data, },
1056 	{ .compatible = "amlogic,t7-hdmi-pll",	.data = &t7_hdmi_data, },
1057 	{ .compatible = "amlogic,t7-mclk-pll",	.data = &t7_mclk_data, },
1058 	{}
1059 };
1060 MODULE_DEVICE_TABLE(of, t7_pll_clkc_match_table);
1061 
1062 static struct platform_driver t7_pll_clkc_driver = {
1063 	.probe = meson_clkc_mmio_probe,
1064 	.driver = {
1065 		.name = "t7-pll-clkc",
1066 		.of_match_table = t7_pll_clkc_match_table,
1067 	},
1068 };
1069 module_platform_driver(t7_pll_clkc_driver);
1070 
1071 MODULE_DESCRIPTION("Amlogic T7 PLL Clock Controller driver");
1072 MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>");
1073 MODULE_LICENSE("GPL");
1074 MODULE_IMPORT_NS("CLK_MESON");
1075