xref: /linux/drivers/clk/thead/clk-th1520-ap.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
4  * Copyright (C) 2023 Vivo Communication Technology Co. Ltd.
5  *  Authors: Yangtao Li <frank.li@vivo.com>
6  */
7 
8 #include <dt-bindings/clock/thead,th1520-clk-ap.h>
9 #include <linux/bitfield.h>
10 #include <linux/clk-provider.h>
11 #include <linux/device.h>
12 #include <linux/module.h>
13 #include <linux/platform_device.h>
14 #include <linux/regmap.h>
15 
16 #define TH1520_PLL_POSTDIV2	GENMASK(26, 24)
17 #define TH1520_PLL_POSTDIV1	GENMASK(22, 20)
18 #define TH1520_PLL_FBDIV	GENMASK(19, 8)
19 #define TH1520_PLL_REFDIV	GENMASK(5, 0)
20 #define TH1520_PLL_BYPASS	BIT(30)
21 #define TH1520_PLL_DSMPD	BIT(24)
22 #define TH1520_PLL_FRAC		GENMASK(23, 0)
23 #define TH1520_PLL_FRAC_BITS    24
24 
25 struct ccu_internal {
26 	u8	shift;
27 	u8	width;
28 };
29 
30 struct ccu_div_internal {
31 	u8	shift;
32 	u8	width;
33 	u32	flags;
34 };
35 
36 struct ccu_common {
37 	int		clkid;
38 	struct regmap	*map;
39 	u16		cfg0;
40 	u16		cfg1;
41 	struct clk_hw	hw;
42 };
43 
44 struct ccu_mux {
45 	int			clkid;
46 	u32			reg;
47 	struct clk_mux		mux;
48 };
49 
50 struct ccu_gate {
51 	u32			enable;
52 	struct ccu_common	common;
53 };
54 
55 struct ccu_div {
56 	u32			enable;
57 	struct ccu_div_internal	div;
58 	struct ccu_internal	mux;
59 	struct ccu_common	common;
60 };
61 
62 struct ccu_pll {
63 	struct ccu_common	common;
64 };
65 
66 #define TH_CCU_ARG(_shift, _width)					\
67 	{								\
68 		.shift	= _shift,					\
69 		.width	= _width,					\
70 	}
71 
72 #define TH_CCU_DIV_FLAGS(_shift, _width, _flags)			\
73 	{								\
74 		.shift	= _shift,					\
75 		.width	= _width,					\
76 		.flags	= _flags,					\
77 	}
78 
79 #define TH_CCU_MUX(_name, _parents, _shift, _width)			\
80 	{								\
81 		.mask		= GENMASK(_width - 1, 0),		\
82 		.shift		= _shift,				\
83 		.hw.init	= CLK_HW_INIT_PARENTS_DATA(		\
84 					_name,				\
85 					_parents,			\
86 					&clk_mux_ops,			\
87 					0),				\
88 	}
89 
90 #define CCU_GATE(_clkid, _struct, _name, _parent, _reg, _gate, _flags)	\
91 	struct ccu_gate _struct = {					\
92 		.enable	= _gate,					\
93 		.common	= {						\
94 			.clkid		= _clkid,			\
95 			.cfg0		= _reg,				\
96 			.hw.init	= CLK_HW_INIT_PARENTS_DATA(	\
97 						_name,			\
98 						_parent,		\
99 						&clk_gate_ops,		\
100 						_flags),		\
101 		}							\
102 	}
103 
hw_to_ccu_common(struct clk_hw * hw)104 static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw)
105 {
106 	return container_of(hw, struct ccu_common, hw);
107 }
108 
hw_to_ccu_pll(struct clk_hw * hw)109 static inline struct ccu_pll *hw_to_ccu_pll(struct clk_hw *hw)
110 {
111 	struct ccu_common *common = hw_to_ccu_common(hw);
112 
113 	return container_of(common, struct ccu_pll, common);
114 }
115 
hw_to_ccu_div(struct clk_hw * hw)116 static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
117 {
118 	struct ccu_common *common = hw_to_ccu_common(hw);
119 
120 	return container_of(common, struct ccu_div, common);
121 }
122 
hw_to_ccu_gate(struct clk_hw * hw)123 static inline struct ccu_gate *hw_to_ccu_gate(struct clk_hw *hw)
124 {
125 	struct ccu_common *common = hw_to_ccu_common(hw);
126 
127 	return container_of(common, struct ccu_gate, common);
128 }
129 
ccu_get_parent_helper(struct ccu_common * common,struct ccu_internal * mux)130 static u8 ccu_get_parent_helper(struct ccu_common *common,
131 				struct ccu_internal *mux)
132 {
133 	unsigned int val;
134 	u8 parent;
135 
136 	regmap_read(common->map, common->cfg0, &val);
137 	parent = val >> mux->shift;
138 	parent &= GENMASK(mux->width - 1, 0);
139 
140 	return parent;
141 }
142 
ccu_set_parent_helper(struct ccu_common * common,struct ccu_internal * mux,u8 index)143 static int ccu_set_parent_helper(struct ccu_common *common,
144 				 struct ccu_internal *mux,
145 				 u8 index)
146 {
147 	return regmap_update_bits(common->map, common->cfg0,
148 			GENMASK(mux->width - 1, 0) << mux->shift,
149 			index << mux->shift);
150 }
151 
ccu_disable_helper(struct ccu_common * common,u32 gate)152 static void ccu_disable_helper(struct ccu_common *common, u32 gate)
153 {
154 	if (!gate)
155 		return;
156 	regmap_update_bits(common->map, common->cfg0,
157 			   gate, ~gate);
158 }
159 
ccu_enable_helper(struct ccu_common * common,u32 gate)160 static int ccu_enable_helper(struct ccu_common *common, u32 gate)
161 {
162 	unsigned int val;
163 	int ret;
164 
165 	if (!gate)
166 		return 0;
167 
168 	ret = regmap_update_bits(common->map, common->cfg0, gate, gate);
169 	regmap_read(common->map, common->cfg0, &val);
170 	return ret;
171 }
172 
ccu_is_enabled_helper(struct ccu_common * common,u32 gate)173 static int ccu_is_enabled_helper(struct ccu_common *common, u32 gate)
174 {
175 	unsigned int val;
176 
177 	if (!gate)
178 		return true;
179 
180 	regmap_read(common->map, common->cfg0, &val);
181 	return val & gate;
182 }
183 
ccu_div_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)184 static unsigned long ccu_div_recalc_rate(struct clk_hw *hw,
185 					 unsigned long parent_rate)
186 {
187 	struct ccu_div *cd = hw_to_ccu_div(hw);
188 	unsigned long rate;
189 	unsigned int val;
190 
191 	regmap_read(cd->common.map, cd->common.cfg0, &val);
192 	val = val >> cd->div.shift;
193 	val &= GENMASK(cd->div.width - 1, 0);
194 	rate = divider_recalc_rate(hw, parent_rate, val, NULL,
195 				   cd->div.flags, cd->div.width);
196 
197 	return rate;
198 }
199 
ccu_div_get_parent(struct clk_hw * hw)200 static u8 ccu_div_get_parent(struct clk_hw *hw)
201 {
202 	struct ccu_div *cd = hw_to_ccu_div(hw);
203 
204 	return ccu_get_parent_helper(&cd->common, &cd->mux);
205 }
206 
ccu_div_set_parent(struct clk_hw * hw,u8 index)207 static int ccu_div_set_parent(struct clk_hw *hw, u8 index)
208 {
209 	struct ccu_div *cd = hw_to_ccu_div(hw);
210 
211 	return ccu_set_parent_helper(&cd->common, &cd->mux, index);
212 }
213 
ccu_div_disable(struct clk_hw * hw)214 static void ccu_div_disable(struct clk_hw *hw)
215 {
216 	struct ccu_div *cd = hw_to_ccu_div(hw);
217 
218 	ccu_disable_helper(&cd->common, cd->enable);
219 }
220 
ccu_div_enable(struct clk_hw * hw)221 static int ccu_div_enable(struct clk_hw *hw)
222 {
223 	struct ccu_div *cd = hw_to_ccu_div(hw);
224 
225 	return ccu_enable_helper(&cd->common, cd->enable);
226 }
227 
ccu_div_is_enabled(struct clk_hw * hw)228 static int ccu_div_is_enabled(struct clk_hw *hw)
229 {
230 	struct ccu_div *cd = hw_to_ccu_div(hw);
231 
232 	return ccu_is_enabled_helper(&cd->common, cd->enable);
233 }
234 
235 static const struct clk_ops ccu_div_ops = {
236 	.disable	= ccu_div_disable,
237 	.enable		= ccu_div_enable,
238 	.is_enabled	= ccu_div_is_enabled,
239 	.get_parent	= ccu_div_get_parent,
240 	.set_parent	= ccu_div_set_parent,
241 	.recalc_rate	= ccu_div_recalc_rate,
242 	.determine_rate	= clk_hw_determine_rate_no_reparent,
243 };
244 
th1520_pll_vco_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)245 static unsigned long th1520_pll_vco_recalc_rate(struct clk_hw *hw,
246 						unsigned long parent_rate)
247 {
248 	struct ccu_pll *pll = hw_to_ccu_pll(hw);
249 	unsigned long div, mul, frac;
250 	unsigned int cfg0, cfg1;
251 	u64 rate = parent_rate;
252 
253 	regmap_read(pll->common.map, pll->common.cfg0, &cfg0);
254 	regmap_read(pll->common.map, pll->common.cfg1, &cfg1);
255 
256 	mul = FIELD_GET(TH1520_PLL_FBDIV, cfg0);
257 	div = FIELD_GET(TH1520_PLL_REFDIV, cfg0);
258 	if (!(cfg1 & TH1520_PLL_DSMPD)) {
259 		mul <<= TH1520_PLL_FRAC_BITS;
260 		frac = FIELD_GET(TH1520_PLL_FRAC, cfg1);
261 		mul += frac;
262 		div <<= TH1520_PLL_FRAC_BITS;
263 	}
264 	rate = parent_rate * mul;
265 	rate = rate / div;
266 	return rate;
267 }
268 
th1520_pll_postdiv_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)269 static unsigned long th1520_pll_postdiv_recalc_rate(struct clk_hw *hw,
270 						    unsigned long parent_rate)
271 {
272 	struct ccu_pll *pll = hw_to_ccu_pll(hw);
273 	unsigned long div, rate = parent_rate;
274 	unsigned int cfg0, cfg1;
275 
276 	regmap_read(pll->common.map, pll->common.cfg0, &cfg0);
277 	regmap_read(pll->common.map, pll->common.cfg1, &cfg1);
278 
279 	if (cfg1 & TH1520_PLL_BYPASS)
280 		return rate;
281 
282 	div = FIELD_GET(TH1520_PLL_POSTDIV1, cfg0) *
283 	      FIELD_GET(TH1520_PLL_POSTDIV2, cfg0);
284 
285 	rate = rate / div;
286 
287 	return rate;
288 }
289 
ccu_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)290 static unsigned long ccu_pll_recalc_rate(struct clk_hw *hw,
291 					 unsigned long parent_rate)
292 {
293 	unsigned long rate = parent_rate;
294 
295 	rate = th1520_pll_vco_recalc_rate(hw, rate);
296 	rate = th1520_pll_postdiv_recalc_rate(hw, rate);
297 
298 	return rate;
299 }
300 
301 static const struct clk_ops clk_pll_ops = {
302 	.recalc_rate	= ccu_pll_recalc_rate,
303 };
304 
305 static const struct clk_parent_data osc_24m_clk[] = {
306 	{ .index = 0 }
307 };
308 
309 static struct ccu_pll cpu_pll0_clk = {
310 	.common		= {
311 		.clkid		= CLK_CPU_PLL0,
312 		.cfg0		= 0x000,
313 		.cfg1		= 0x004,
314 		.hw.init	= CLK_HW_INIT_PARENTS_DATA("cpu-pll0",
315 					      osc_24m_clk,
316 					      &clk_pll_ops,
317 					      0),
318 	},
319 };
320 
321 static struct ccu_pll cpu_pll1_clk = {
322 	.common		= {
323 		.clkid		= CLK_CPU_PLL1,
324 		.cfg0		= 0x010,
325 		.cfg1		= 0x014,
326 		.hw.init	= CLK_HW_INIT_PARENTS_DATA("cpu-pll1",
327 					      osc_24m_clk,
328 					      &clk_pll_ops,
329 					      0),
330 	},
331 };
332 
333 static struct ccu_pll gmac_pll_clk = {
334 	.common		= {
335 		.clkid		= CLK_GMAC_PLL,
336 		.cfg0		= 0x020,
337 		.cfg1		= 0x024,
338 		.hw.init	= CLK_HW_INIT_PARENTS_DATA("gmac-pll",
339 					      osc_24m_clk,
340 					      &clk_pll_ops,
341 					      0),
342 	},
343 };
344 
345 static const struct clk_hw *gmac_pll_clk_parent[] = {
346 	&gmac_pll_clk.common.hw
347 };
348 
349 static const struct clk_parent_data gmac_pll_clk_pd[] = {
350 	{ .hw = &gmac_pll_clk.common.hw }
351 };
352 
353 static struct ccu_pll video_pll_clk = {
354 	.common		= {
355 		.clkid		= CLK_VIDEO_PLL,
356 		.cfg0		= 0x030,
357 		.cfg1		= 0x034,
358 		.hw.init	= CLK_HW_INIT_PARENTS_DATA("video-pll",
359 					      osc_24m_clk,
360 					      &clk_pll_ops,
361 					      0),
362 	},
363 };
364 
365 static const struct clk_hw *video_pll_clk_parent[] = {
366 	&video_pll_clk.common.hw
367 };
368 
369 static const struct clk_parent_data video_pll_clk_pd[] = {
370 	{ .hw = &video_pll_clk.common.hw }
371 };
372 
373 static struct ccu_pll dpu0_pll_clk = {
374 	.common		= {
375 		.clkid		= CLK_DPU0_PLL,
376 		.cfg0		= 0x040,
377 		.cfg1		= 0x044,
378 		.hw.init	= CLK_HW_INIT_PARENTS_DATA("dpu0-pll",
379 					      osc_24m_clk,
380 					      &clk_pll_ops,
381 					      0),
382 	},
383 };
384 
385 static const struct clk_hw *dpu0_pll_clk_parent[] = {
386 	&dpu0_pll_clk.common.hw
387 };
388 
389 static struct ccu_pll dpu1_pll_clk = {
390 	.common		= {
391 		.clkid		= CLK_DPU1_PLL,
392 		.cfg0		= 0x050,
393 		.cfg1		= 0x054,
394 		.hw.init	= CLK_HW_INIT_PARENTS_DATA("dpu1-pll",
395 					      osc_24m_clk,
396 					      &clk_pll_ops,
397 					      0),
398 	},
399 };
400 
401 static const struct clk_hw *dpu1_pll_clk_parent[] = {
402 	&dpu1_pll_clk.common.hw
403 };
404 
405 static struct ccu_pll tee_pll_clk = {
406 	.common		= {
407 		.clkid		= CLK_TEE_PLL,
408 		.cfg0		= 0x060,
409 		.cfg1		= 0x064,
410 		.hw.init	= CLK_HW_INIT_PARENTS_DATA("tee-pll",
411 					      osc_24m_clk,
412 					      &clk_pll_ops,
413 					      0),
414 	},
415 };
416 
417 static const struct clk_parent_data c910_i0_parents[] = {
418 	{ .hw = &cpu_pll0_clk.common.hw },
419 	{ .index = 0 }
420 };
421 
422 static struct ccu_mux c910_i0_clk = {
423 	.clkid	= CLK_C910_I0,
424 	.reg	= 0x100,
425 	.mux	= TH_CCU_MUX("c910-i0", c910_i0_parents, 1, 1),
426 };
427 
428 static const struct clk_parent_data c910_parents[] = {
429 	{ .hw = &c910_i0_clk.mux.hw },
430 	{ .hw = &cpu_pll1_clk.common.hw }
431 };
432 
433 static struct ccu_mux c910_clk = {
434 	.clkid	= CLK_C910,
435 	.reg	= 0x100,
436 	.mux	= TH_CCU_MUX("c910", c910_parents, 0, 1),
437 };
438 
439 static const struct clk_parent_data ahb2_cpusys_parents[] = {
440 	{ .hw = &gmac_pll_clk.common.hw },
441 	{ .index = 0 }
442 };
443 
444 static struct ccu_div ahb2_cpusys_hclk = {
445 	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
446 	.mux		= TH_CCU_ARG(5, 1),
447 	.common		= {
448 		.clkid          = CLK_AHB2_CPUSYS_HCLK,
449 		.cfg0		= 0x120,
450 		.hw.init	= CLK_HW_INIT_PARENTS_DATA("ahb2-cpusys-hclk",
451 						      ahb2_cpusys_parents,
452 						      &ccu_div_ops,
453 						      0),
454 	},
455 };
456 
457 static const struct clk_parent_data ahb2_cpusys_hclk_pd[] = {
458 	{ .hw = &ahb2_cpusys_hclk.common.hw }
459 };
460 
461 static const struct clk_hw *ahb2_cpusys_hclk_parent[] = {
462 	&ahb2_cpusys_hclk.common.hw,
463 };
464 
465 static struct ccu_div apb3_cpusys_pclk = {
466 	.div		= TH_CCU_ARG(0, 3),
467 	.common		= {
468 		.clkid          = CLK_APB3_CPUSYS_PCLK,
469 		.cfg0		= 0x130,
470 		.hw.init	= CLK_HW_INIT_PARENTS_HW("apb3-cpusys-pclk",
471 							   ahb2_cpusys_hclk_parent,
472 							   &ccu_div_ops,
473 							   0),
474 	},
475 };
476 
477 static const struct clk_parent_data apb3_cpusys_pclk_pd[] = {
478 	{ .hw = &apb3_cpusys_pclk.common.hw }
479 };
480 
481 static struct ccu_div axi4_cpusys2_aclk = {
482 	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
483 	.common		= {
484 		.clkid          = CLK_AXI4_CPUSYS2_ACLK,
485 		.cfg0		= 0x134,
486 		.hw.init	= CLK_HW_INIT_PARENTS_HW("axi4-cpusys2-aclk",
487 					      gmac_pll_clk_parent,
488 					      &ccu_div_ops,
489 					      0),
490 	},
491 };
492 
493 static const struct clk_parent_data axi4_cpusys2_aclk_pd[] = {
494 	{ .hw = &axi4_cpusys2_aclk.common.hw }
495 };
496 
497 static const struct clk_parent_data axi_parents[] = {
498 	{ .hw = &video_pll_clk.common.hw },
499 	{ .index = 0 }
500 };
501 
502 static struct ccu_div axi_aclk = {
503 	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
504 	.mux		= TH_CCU_ARG(5, 1),
505 	.common		= {
506 		.clkid          = CLK_AXI_ACLK,
507 		.cfg0		= 0x138,
508 		.hw.init	= CLK_HW_INIT_PARENTS_DATA("axi-aclk",
509 						      axi_parents,
510 						      &ccu_div_ops,
511 						      0),
512 	},
513 };
514 
515 static const struct clk_parent_data axi_aclk_pd[] = {
516 	{ .hw = &axi_aclk.common.hw }
517 };
518 
519 static const struct clk_parent_data perisys_ahb_hclk_parents[] = {
520 	{ .hw = &gmac_pll_clk.common.hw },
521 	{ .index = 0 },
522 };
523 
524 static struct ccu_div perisys_ahb_hclk = {
525 	.enable		= BIT(6),
526 	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
527 	.mux		= TH_CCU_ARG(5, 1),
528 	.common		= {
529 		.clkid          = CLK_PERI_AHB_HCLK,
530 		.cfg0		= 0x140,
531 		.hw.init	= CLK_HW_INIT_PARENTS_DATA("perisys-ahb-hclk",
532 						      perisys_ahb_hclk_parents,
533 						      &ccu_div_ops,
534 						      0),
535 	},
536 };
537 
538 static const struct clk_parent_data perisys_ahb_hclk_pd[] = {
539 	{ .hw = &perisys_ahb_hclk.common.hw }
540 };
541 
542 static const struct clk_hw *perisys_ahb_hclk_parent[] = {
543 	&perisys_ahb_hclk.common.hw
544 };
545 
546 static struct ccu_div perisys_apb_pclk = {
547 	.div		= TH_CCU_ARG(0, 3),
548 	.common		= {
549 		.clkid          = CLK_PERI_APB_PCLK,
550 		.cfg0		= 0x150,
551 		.hw.init	= CLK_HW_INIT_PARENTS_HW("perisys-apb-pclk",
552 					      perisys_ahb_hclk_parent,
553 					      &ccu_div_ops,
554 					      0),
555 	},
556 };
557 
558 static const struct clk_parent_data perisys_apb_pclk_pd[] = {
559 	{ .hw = &perisys_apb_pclk.common.hw }
560 };
561 
562 static struct ccu_div peri2sys_apb_pclk = {
563 	.div		= TH_CCU_DIV_FLAGS(4, 3, CLK_DIVIDER_ONE_BASED),
564 	.common		= {
565 		.clkid          = CLK_PERI2APB_PCLK,
566 		.cfg0		= 0x150,
567 		.hw.init	= CLK_HW_INIT_PARENTS_HW("peri2sys-apb-pclk",
568 					      gmac_pll_clk_parent,
569 					      &ccu_div_ops,
570 					      0),
571 	},
572 };
573 
574 static const struct clk_parent_data peri2sys_apb_pclk_pd[] = {
575 	{ .hw = &peri2sys_apb_pclk.common.hw }
576 };
577 
578 static struct clk_fixed_factor osc12m_clk = {
579 	.div		= 2,
580 	.mult		= 1,
581 	.hw.init	= CLK_HW_INIT_PARENTS_DATA("osc_12m",
582 						   osc_24m_clk,
583 						   &clk_fixed_factor_ops,
584 						   0),
585 };
586 
587 static const char * const out_parents[] = { "osc_24m", "osc_12m" };
588 
589 static struct ccu_div out1_clk = {
590 	.enable		= BIT(5),
591 	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
592 	.mux		= TH_CCU_ARG(4, 1),
593 	.common		= {
594 		.clkid          = CLK_OUT1,
595 		.cfg0		= 0x1b4,
596 		.hw.init	= CLK_HW_INIT_PARENTS("out1",
597 						      out_parents,
598 						      &ccu_div_ops,
599 						      0),
600 	},
601 };
602 
603 static struct ccu_div out2_clk = {
604 	.enable		= BIT(5),
605 	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
606 	.mux		= TH_CCU_ARG(4, 1),
607 	.common		= {
608 		.clkid          = CLK_OUT2,
609 		.cfg0		= 0x1b8,
610 		.hw.init	= CLK_HW_INIT_PARENTS("out2",
611 						      out_parents,
612 						      &ccu_div_ops,
613 						      0),
614 	},
615 };
616 
617 static struct ccu_div out3_clk = {
618 	.enable		= BIT(5),
619 	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
620 	.mux		= TH_CCU_ARG(4, 1),
621 	.common		= {
622 		.clkid          = CLK_OUT3,
623 		.cfg0		= 0x1bc,
624 		.hw.init	= CLK_HW_INIT_PARENTS("out3",
625 						      out_parents,
626 						      &ccu_div_ops,
627 						      0),
628 	},
629 };
630 
631 static struct ccu_div out4_clk = {
632 	.enable		= BIT(5),
633 	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
634 	.mux		= TH_CCU_ARG(4, 1),
635 	.common		= {
636 		.clkid          = CLK_OUT4,
637 		.cfg0		= 0x1c0,
638 		.hw.init	= CLK_HW_INIT_PARENTS("out4",
639 						      out_parents,
640 						      &ccu_div_ops,
641 						      0),
642 	},
643 };
644 
645 static const struct clk_parent_data apb_parents[] = {
646 	{ .hw = &gmac_pll_clk.common.hw },
647 	{ .index = 0 },
648 };
649 
650 static struct ccu_div apb_pclk = {
651 	.enable		= BIT(5),
652 	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
653 	.mux		= TH_CCU_ARG(7, 1),
654 	.common		= {
655 		.clkid          = CLK_APB_PCLK,
656 		.cfg0		= 0x1c4,
657 		.hw.init	= CLK_HW_INIT_PARENTS_DATA("apb-pclk",
658 						      apb_parents,
659 						      &ccu_div_ops,
660 						      CLK_IGNORE_UNUSED),
661 	},
662 };
663 
664 static const struct clk_hw *npu_parents[] = {
665 	&gmac_pll_clk.common.hw,
666 	&video_pll_clk.common.hw
667 };
668 
669 static struct ccu_div npu_clk = {
670 	.enable		= BIT(4),
671 	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
672 	.mux		= TH_CCU_ARG(6, 1),
673 	.common		= {
674 		.clkid          = CLK_NPU,
675 		.cfg0		= 0x1c8,
676 		.hw.init	= CLK_HW_INIT_PARENTS_HW("npu",
677 						      npu_parents,
678 						      &ccu_div_ops,
679 						      0),
680 	},
681 };
682 
683 static struct ccu_div vi_clk = {
684 	.div		= TH_CCU_DIV_FLAGS(16, 4, CLK_DIVIDER_ONE_BASED),
685 	.common		= {
686 		.clkid          = CLK_VI,
687 		.cfg0		= 0x1d0,
688 		.hw.init	= CLK_HW_INIT_PARENTS_HW("vi",
689 					      video_pll_clk_parent,
690 					      &ccu_div_ops,
691 					      0),
692 	},
693 };
694 
695 static struct ccu_div vi_ahb_clk = {
696 	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
697 	.common		= {
698 		.clkid          = CLK_VI_AHB,
699 		.cfg0		= 0x1d0,
700 		.hw.init	= CLK_HW_INIT_PARENTS_HW("vi-ahb",
701 					      video_pll_clk_parent,
702 					      &ccu_div_ops,
703 					      0),
704 	},
705 };
706 
707 static struct ccu_div vo_axi_clk = {
708 	.enable		= BIT(5),
709 	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
710 	.common		= {
711 		.clkid          = CLK_VO_AXI,
712 		.cfg0		= 0x1dc,
713 		.hw.init	= CLK_HW_INIT_PARENTS_HW("vo-axi",
714 					      video_pll_clk_parent,
715 					      &ccu_div_ops,
716 					      0),
717 	},
718 };
719 
720 static struct ccu_div vp_apb_clk = {
721 	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
722 	.common		= {
723 		.clkid          = CLK_VP_APB,
724 		.cfg0		= 0x1e0,
725 		.hw.init	= CLK_HW_INIT_PARENTS_HW("vp-apb",
726 					      gmac_pll_clk_parent,
727 					      &ccu_div_ops,
728 					      0),
729 	},
730 };
731 
732 static struct ccu_div vp_axi_clk = {
733 	.enable		= BIT(15),
734 	.div		= TH_CCU_DIV_FLAGS(8, 4, CLK_DIVIDER_ONE_BASED),
735 	.common		= {
736 		.clkid          = CLK_VP_AXI,
737 		.cfg0		= 0x1e0,
738 		.hw.init	= CLK_HW_INIT_PARENTS_HW("vp-axi",
739 					      video_pll_clk_parent,
740 					      &ccu_div_ops,
741 					      CLK_IGNORE_UNUSED),
742 	},
743 };
744 
745 static struct ccu_div venc_clk = {
746 	.enable		= BIT(5),
747 	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
748 	.common		= {
749 		.clkid          = CLK_VENC,
750 		.cfg0		= 0x1e4,
751 		.hw.init	= CLK_HW_INIT_PARENTS_HW("venc",
752 					      gmac_pll_clk_parent,
753 					      &ccu_div_ops,
754 					      0),
755 	},
756 };
757 
758 static struct ccu_div dpu0_clk = {
759 	.div		= TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED),
760 	.common		= {
761 		.clkid          = CLK_DPU0,
762 		.cfg0		= 0x1e8,
763 		.hw.init	= CLK_HW_INIT_PARENTS_HW("dpu0",
764 					      dpu0_pll_clk_parent,
765 					      &ccu_div_ops,
766 					      0),
767 	},
768 };
769 
770 static struct ccu_div dpu1_clk = {
771 	.div		= TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED),
772 	.common		= {
773 		.clkid          = CLK_DPU1,
774 		.cfg0		= 0x1ec,
775 		.hw.init	= CLK_HW_INIT_PARENTS_HW("dpu1",
776 					      dpu1_pll_clk_parent,
777 					      &ccu_div_ops,
778 					      0),
779 	},
780 };
781 
782 static CLK_FIXED_FACTOR_HW(emmc_sdio_ref_clk, "emmc-sdio-ref",
783 			   &video_pll_clk.common.hw, 4, 1, 0);
784 
785 static const struct clk_parent_data emmc_sdio_ref_clk_pd[] = {
786 	{ .hw = &emmc_sdio_ref_clk.hw },
787 };
788 
789 static CCU_GATE(CLK_BROM, brom_clk, "brom", ahb2_cpusys_hclk_pd, 0x100, BIT(4), 0);
790 static CCU_GATE(CLK_BMU, bmu_clk, "bmu", axi4_cpusys2_aclk_pd, 0x100, BIT(5), 0);
791 static CCU_GATE(CLK_AON2CPU_A2X, aon2cpu_a2x_clk, "aon2cpu-a2x", axi4_cpusys2_aclk_pd,
792 		0x134, BIT(8), 0);
793 static CCU_GATE(CLK_X2X_CPUSYS, x2x_cpusys_clk, "x2x-cpusys", axi4_cpusys2_aclk_pd,
794 		0x134, BIT(7), 0);
795 static CCU_GATE(CLK_CPU2AON_X2H, cpu2aon_x2h_clk, "cpu2aon-x2h", axi_aclk_pd,
796 		0x138, BIT(8), CLK_IGNORE_UNUSED);
797 static CCU_GATE(CLK_CPU2PERI_X2H, cpu2peri_x2h_clk, "cpu2peri-x2h", axi4_cpusys2_aclk_pd,
798 		0x140, BIT(9), CLK_IGNORE_UNUSED);
799 static CCU_GATE(CLK_PERISYS_APB1_HCLK, perisys_apb1_hclk, "perisys-apb1-hclk", perisys_ahb_hclk_pd,
800 		0x150, BIT(9), CLK_IGNORE_UNUSED);
801 static CCU_GATE(CLK_PERISYS_APB2_HCLK, perisys_apb2_hclk, "perisys-apb2-hclk", perisys_ahb_hclk_pd,
802 		0x150, BIT(10), CLK_IGNORE_UNUSED);
803 static CCU_GATE(CLK_PERISYS_APB3_HCLK, perisys_apb3_hclk, "perisys-apb3-hclk", perisys_ahb_hclk_pd,
804 		0x150, BIT(11), CLK_IGNORE_UNUSED);
805 static CCU_GATE(CLK_PERISYS_APB4_HCLK, perisys_apb4_hclk, "perisys-apb4-hclk", perisys_ahb_hclk_pd,
806 		0x150, BIT(12), 0);
807 static CCU_GATE(CLK_NPU_AXI, npu_axi_clk, "npu-axi", axi_aclk_pd, 0x1c8, BIT(5), 0);
808 static CCU_GATE(CLK_CPU2VP, cpu2vp_clk, "cpu2vp", axi_aclk_pd, 0x1e0, BIT(13), 0);
809 static CCU_GATE(CLK_EMMC_SDIO, emmc_sdio_clk, "emmc-sdio", emmc_sdio_ref_clk_pd, 0x204, BIT(30), 0);
810 static CCU_GATE(CLK_GMAC1, gmac1_clk, "gmac1", gmac_pll_clk_pd, 0x204, BIT(26), 0);
811 static CCU_GATE(CLK_PADCTRL1, padctrl1_clk, "padctrl1", perisys_apb_pclk_pd, 0x204, BIT(24), 0);
812 static CCU_GATE(CLK_DSMART, dsmart_clk, "dsmart", perisys_apb_pclk_pd, 0x204, BIT(23), 0);
813 static CCU_GATE(CLK_PADCTRL0, padctrl0_clk, "padctrl0", perisys_apb_pclk_pd, 0x204, BIT(22), 0);
814 static CCU_GATE(CLK_GMAC_AXI, gmac_axi_clk, "gmac-axi", axi4_cpusys2_aclk_pd, 0x204, BIT(21), 0);
815 static CCU_GATE(CLK_GPIO3, gpio3_clk, "gpio3-clk", peri2sys_apb_pclk_pd, 0x204, BIT(20), 0);
816 static CCU_GATE(CLK_GMAC0, gmac0_clk, "gmac0", gmac_pll_clk_pd, 0x204, BIT(19), 0);
817 static CCU_GATE(CLK_PWM, pwm_clk, "pwm", perisys_apb_pclk_pd, 0x204, BIT(18), 0);
818 static CCU_GATE(CLK_QSPI0, qspi0_clk, "qspi0", video_pll_clk_pd, 0x204, BIT(17), 0);
819 static CCU_GATE(CLK_QSPI1, qspi1_clk, "qspi1", video_pll_clk_pd, 0x204, BIT(16), 0);
820 static CCU_GATE(CLK_SPI, spi_clk, "spi", video_pll_clk_pd, 0x204, BIT(15), 0);
821 static CCU_GATE(CLK_UART0_PCLK, uart0_pclk, "uart0-pclk", perisys_apb_pclk_pd, 0x204, BIT(14), 0);
822 static CCU_GATE(CLK_UART1_PCLK, uart1_pclk, "uart1-pclk", perisys_apb_pclk_pd, 0x204, BIT(13), 0);
823 static CCU_GATE(CLK_UART2_PCLK, uart2_pclk, "uart2-pclk", perisys_apb_pclk_pd, 0x204, BIT(12), 0);
824 static CCU_GATE(CLK_UART3_PCLK, uart3_pclk, "uart3-pclk", perisys_apb_pclk_pd, 0x204, BIT(11), 0);
825 static CCU_GATE(CLK_UART4_PCLK, uart4_pclk, "uart4-pclk", perisys_apb_pclk_pd, 0x204, BIT(10), 0);
826 static CCU_GATE(CLK_UART5_PCLK, uart5_pclk, "uart5-pclk", perisys_apb_pclk_pd, 0x204, BIT(9), 0);
827 static CCU_GATE(CLK_GPIO0, gpio0_clk, "gpio0-clk", perisys_apb_pclk_pd, 0x204, BIT(8), 0);
828 static CCU_GATE(CLK_GPIO1, gpio1_clk, "gpio1-clk", perisys_apb_pclk_pd, 0x204, BIT(7), 0);
829 static CCU_GATE(CLK_GPIO2, gpio2_clk, "gpio2-clk", peri2sys_apb_pclk_pd, 0x204, BIT(6), 0);
830 static CCU_GATE(CLK_I2C0, i2c0_clk, "i2c0", perisys_apb_pclk_pd, 0x204, BIT(5), 0);
831 static CCU_GATE(CLK_I2C1, i2c1_clk, "i2c1", perisys_apb_pclk_pd, 0x204, BIT(4), 0);
832 static CCU_GATE(CLK_I2C2, i2c2_clk, "i2c2", perisys_apb_pclk_pd, 0x204, BIT(3), 0);
833 static CCU_GATE(CLK_I2C3, i2c3_clk, "i2c3", perisys_apb_pclk_pd, 0x204, BIT(2), 0);
834 static CCU_GATE(CLK_I2C4, i2c4_clk, "i2c4", perisys_apb_pclk_pd, 0x204, BIT(1), 0);
835 static CCU_GATE(CLK_I2C5, i2c5_clk, "i2c5", perisys_apb_pclk_pd, 0x204, BIT(0), 0);
836 static CCU_GATE(CLK_SPINLOCK, spinlock_clk, "spinlock", ahb2_cpusys_hclk_pd, 0x208, BIT(10), 0);
837 static CCU_GATE(CLK_DMA, dma_clk, "dma", axi4_cpusys2_aclk_pd, 0x208, BIT(8), 0);
838 static CCU_GATE(CLK_MBOX0, mbox0_clk, "mbox0", apb3_cpusys_pclk_pd, 0x208, BIT(7), 0);
839 static CCU_GATE(CLK_MBOX1, mbox1_clk, "mbox1", apb3_cpusys_pclk_pd, 0x208, BIT(6), 0);
840 static CCU_GATE(CLK_MBOX2, mbox2_clk, "mbox2", apb3_cpusys_pclk_pd, 0x208, BIT(5), 0);
841 static CCU_GATE(CLK_MBOX3, mbox3_clk, "mbox3", apb3_cpusys_pclk_pd, 0x208, BIT(4), 0);
842 static CCU_GATE(CLK_WDT0, wdt0_clk, "wdt0", apb3_cpusys_pclk_pd, 0x208, BIT(3), 0);
843 static CCU_GATE(CLK_WDT1, wdt1_clk, "wdt1", apb3_cpusys_pclk_pd, 0x208, BIT(2), 0);
844 static CCU_GATE(CLK_TIMER0, timer0_clk, "timer0", apb3_cpusys_pclk_pd, 0x208, BIT(1), 0);
845 static CCU_GATE(CLK_TIMER1, timer1_clk, "timer1", apb3_cpusys_pclk_pd, 0x208, BIT(0), 0);
846 static CCU_GATE(CLK_SRAM0, sram0_clk, "sram0", axi_aclk_pd, 0x20c, BIT(4), 0);
847 static CCU_GATE(CLK_SRAM1, sram1_clk, "sram1", axi_aclk_pd, 0x20c, BIT(3), 0);
848 static CCU_GATE(CLK_SRAM2, sram2_clk, "sram2", axi_aclk_pd, 0x20c, BIT(2), 0);
849 static CCU_GATE(CLK_SRAM3, sram3_clk, "sram3", axi_aclk_pd, 0x20c, BIT(1), 0);
850 
851 static CCU_GATE(CLK_AXI4_VO_ACLK, axi4_vo_aclk, "axi4-vo-aclk",
852 		video_pll_clk_pd, 0x0, BIT(0), 0);
853 static CCU_GATE(CLK_GPU_CORE, gpu_core_clk, "gpu-core-clk", video_pll_clk_pd,
854 		0x0, BIT(3), 0);
855 static CCU_GATE(CLK_GPU_CFG_ACLK, gpu_cfg_aclk, "gpu-cfg-aclk",
856 		video_pll_clk_pd, 0x0, BIT(4), 0);
857 static CCU_GATE(CLK_DPU_PIXELCLK0, dpu0_pixelclk, "dpu0-pixelclk",
858 		video_pll_clk_pd, 0x0, BIT(5), 0);
859 static CCU_GATE(CLK_DPU_PIXELCLK1, dpu1_pixelclk, "dpu1-pixelclk",
860 		video_pll_clk_pd, 0x0, BIT(6), 0);
861 static CCU_GATE(CLK_DPU_HCLK, dpu_hclk, "dpu-hclk", video_pll_clk_pd, 0x0,
862 		BIT(7), 0);
863 static CCU_GATE(CLK_DPU_ACLK, dpu_aclk, "dpu-aclk", video_pll_clk_pd, 0x0,
864 		BIT(8), 0);
865 static CCU_GATE(CLK_DPU_CCLK, dpu_cclk, "dpu-cclk", video_pll_clk_pd, 0x0,
866 		BIT(9), 0);
867 static CCU_GATE(CLK_HDMI_SFR, hdmi_sfr_clk, "hdmi-sfr-clk", video_pll_clk_pd,
868 		0x0, BIT(10), 0);
869 static CCU_GATE(CLK_HDMI_PCLK, hdmi_pclk, "hdmi-pclk", video_pll_clk_pd, 0x0,
870 		BIT(11), 0);
871 static CCU_GATE(CLK_HDMI_CEC, hdmi_cec_clk, "hdmi-cec-clk", video_pll_clk_pd,
872 		0x0, BIT(12), 0);
873 static CCU_GATE(CLK_MIPI_DSI0_PCLK, mipi_dsi0_pclk, "mipi-dsi0-pclk",
874 		video_pll_clk_pd, 0x0, BIT(13), 0);
875 static CCU_GATE(CLK_MIPI_DSI1_PCLK, mipi_dsi1_pclk, "mipi-dsi1-pclk",
876 		video_pll_clk_pd, 0x0, BIT(14), 0);
877 static CCU_GATE(CLK_MIPI_DSI0_CFG, mipi_dsi0_cfg_clk, "mipi-dsi0-cfg-clk",
878 		video_pll_clk_pd, 0x0, BIT(15), 0);
879 static CCU_GATE(CLK_MIPI_DSI1_CFG, mipi_dsi1_cfg_clk, "mipi-dsi1-cfg-clk",
880 		video_pll_clk_pd, 0x0, BIT(16), 0);
881 static CCU_GATE(CLK_MIPI_DSI0_REFCLK, mipi_dsi0_refclk, "mipi-dsi0-refclk",
882 		video_pll_clk_pd, 0x0, BIT(17), 0);
883 static CCU_GATE(CLK_MIPI_DSI1_REFCLK, mipi_dsi1_refclk, "mipi-dsi1-refclk",
884 		video_pll_clk_pd, 0x0, BIT(18), 0);
885 static CCU_GATE(CLK_HDMI_I2S, hdmi_i2s_clk, "hdmi-i2s-clk", video_pll_clk_pd,
886 		0x0, BIT(19), 0);
887 static CCU_GATE(CLK_X2H_DPU1_ACLK, x2h_dpu1_aclk, "x2h-dpu1-aclk",
888 		video_pll_clk_pd, 0x0, BIT(20), 0);
889 static CCU_GATE(CLK_X2H_DPU_ACLK, x2h_dpu_aclk, "x2h-dpu-aclk",
890 		video_pll_clk_pd, 0x0, BIT(21), 0);
891 static CCU_GATE(CLK_AXI4_VO_PCLK, axi4_vo_pclk, "axi4-vo-pclk",
892 		video_pll_clk_pd, 0x0, BIT(22), 0);
893 static CCU_GATE(CLK_IOPMP_VOSYS_DPU_PCLK, iopmp_vosys_dpu_pclk,
894 		"iopmp-vosys-dpu-pclk", video_pll_clk_pd, 0x0, BIT(23), 0);
895 static CCU_GATE(CLK_IOPMP_VOSYS_DPU1_PCLK, iopmp_vosys_dpu1_pclk,
896 		"iopmp-vosys-dpu1-pclk", video_pll_clk_pd, 0x0, BIT(24), 0);
897 static CCU_GATE(CLK_IOPMP_VOSYS_GPU_PCLK, iopmp_vosys_gpu_pclk,
898 		"iopmp-vosys-gpu-pclk", video_pll_clk_pd, 0x0, BIT(25), 0);
899 static CCU_GATE(CLK_IOPMP_DPU1_ACLK, iopmp_dpu1_aclk, "iopmp-dpu1-aclk",
900 		video_pll_clk_pd, 0x0, BIT(27), 0);
901 static CCU_GATE(CLK_IOPMP_DPU_ACLK, iopmp_dpu_aclk, "iopmp-dpu-aclk",
902 		video_pll_clk_pd, 0x0, BIT(28), 0);
903 static CCU_GATE(CLK_IOPMP_GPU_ACLK, iopmp_gpu_aclk, "iopmp-gpu-aclk",
904 		video_pll_clk_pd, 0x0, BIT(29), 0);
905 static CCU_GATE(CLK_MIPIDSI0_PIXCLK, mipi_dsi0_pixclk, "mipi-dsi0-pixclk",
906 		video_pll_clk_pd, 0x0, BIT(30), 0);
907 static CCU_GATE(CLK_MIPIDSI1_PIXCLK, mipi_dsi1_pixclk, "mipi-dsi1-pixclk",
908 		video_pll_clk_pd, 0x0, BIT(31), 0);
909 static CCU_GATE(CLK_HDMI_PIXCLK, hdmi_pixclk, "hdmi-pixclk", video_pll_clk_pd,
910 		0x4, BIT(0), 0);
911 
912 static CLK_FIXED_FACTOR_HW(gmac_pll_clk_100m, "gmac-pll-clk-100m",
913 			   &gmac_pll_clk.common.hw, 10, 1, 0);
914 
915 static const struct clk_parent_data uart_sclk_parents[] = {
916 	{ .hw = &gmac_pll_clk_100m.hw },
917 	{ .index = 0 },
918 };
919 
920 static struct ccu_mux uart_sclk = {
921 	.clkid	= CLK_UART_SCLK,
922 	.reg	= 0x210,
923 	.mux	= TH_CCU_MUX("uart-sclk", uart_sclk_parents, 0, 1),
924 };
925 
926 static struct ccu_common *th1520_pll_clks[] = {
927 	&cpu_pll0_clk.common,
928 	&cpu_pll1_clk.common,
929 	&gmac_pll_clk.common,
930 	&video_pll_clk.common,
931 	&dpu0_pll_clk.common,
932 	&dpu1_pll_clk.common,
933 	&tee_pll_clk.common,
934 };
935 
936 static struct ccu_common *th1520_div_clks[] = {
937 	&ahb2_cpusys_hclk.common,
938 	&apb3_cpusys_pclk.common,
939 	&axi4_cpusys2_aclk.common,
940 	&perisys_ahb_hclk.common,
941 	&perisys_apb_pclk.common,
942 	&axi_aclk.common,
943 	&peri2sys_apb_pclk.common,
944 	&out1_clk.common,
945 	&out2_clk.common,
946 	&out3_clk.common,
947 	&out4_clk.common,
948 	&apb_pclk.common,
949 	&npu_clk.common,
950 	&vi_clk.common,
951 	&vi_ahb_clk.common,
952 	&vo_axi_clk.common,
953 	&vp_apb_clk.common,
954 	&vp_axi_clk.common,
955 	&venc_clk.common,
956 	&dpu0_clk.common,
957 	&dpu1_clk.common,
958 };
959 
960 static struct ccu_mux *th1520_mux_clks[] = {
961 	&c910_i0_clk,
962 	&c910_clk,
963 	&uart_sclk,
964 };
965 
966 static struct ccu_common *th1520_gate_clks[] = {
967 	&emmc_sdio_clk.common,
968 	&aon2cpu_a2x_clk.common,
969 	&x2x_cpusys_clk.common,
970 	&brom_clk.common,
971 	&bmu_clk.common,
972 	&cpu2aon_x2h_clk.common,
973 	&cpu2peri_x2h_clk.common,
974 	&cpu2vp_clk.common,
975 	&perisys_apb1_hclk.common,
976 	&perisys_apb2_hclk.common,
977 	&perisys_apb3_hclk.common,
978 	&perisys_apb4_hclk.common,
979 	&npu_axi_clk.common,
980 	&gmac1_clk.common,
981 	&padctrl1_clk.common,
982 	&dsmart_clk.common,
983 	&padctrl0_clk.common,
984 	&gmac_axi_clk.common,
985 	&gpio3_clk.common,
986 	&gmac0_clk.common,
987 	&pwm_clk.common,
988 	&qspi0_clk.common,
989 	&qspi1_clk.common,
990 	&spi_clk.common,
991 	&uart0_pclk.common,
992 	&uart1_pclk.common,
993 	&uart2_pclk.common,
994 	&uart3_pclk.common,
995 	&uart4_pclk.common,
996 	&uart5_pclk.common,
997 	&gpio0_clk.common,
998 	&gpio1_clk.common,
999 	&gpio2_clk.common,
1000 	&i2c0_clk.common,
1001 	&i2c1_clk.common,
1002 	&i2c2_clk.common,
1003 	&i2c3_clk.common,
1004 	&i2c4_clk.common,
1005 	&i2c5_clk.common,
1006 	&spinlock_clk.common,
1007 	&dma_clk.common,
1008 	&mbox0_clk.common,
1009 	&mbox1_clk.common,
1010 	&mbox2_clk.common,
1011 	&mbox3_clk.common,
1012 	&wdt0_clk.common,
1013 	&wdt1_clk.common,
1014 	&timer0_clk.common,
1015 	&timer1_clk.common,
1016 	&sram0_clk.common,
1017 	&sram1_clk.common,
1018 	&sram2_clk.common,
1019 	&sram3_clk.common,
1020 };
1021 
1022 static struct ccu_common *th1520_vo_gate_clks[] = {
1023 	&axi4_vo_aclk.common,
1024 	&gpu_core_clk.common,
1025 	&gpu_cfg_aclk.common,
1026 	&dpu0_pixelclk.common,
1027 	&dpu1_pixelclk.common,
1028 	&dpu_hclk.common,
1029 	&dpu_aclk.common,
1030 	&dpu_cclk.common,
1031 	&hdmi_sfr_clk.common,
1032 	&hdmi_pclk.common,
1033 	&hdmi_cec_clk.common,
1034 	&mipi_dsi0_pclk.common,
1035 	&mipi_dsi1_pclk.common,
1036 	&mipi_dsi0_cfg_clk.common,
1037 	&mipi_dsi1_cfg_clk.common,
1038 	&mipi_dsi0_refclk.common,
1039 	&mipi_dsi1_refclk.common,
1040 	&hdmi_i2s_clk.common,
1041 	&x2h_dpu1_aclk.common,
1042 	&x2h_dpu_aclk.common,
1043 	&axi4_vo_pclk.common,
1044 	&iopmp_vosys_dpu_pclk.common,
1045 	&iopmp_vosys_dpu1_pclk.common,
1046 	&iopmp_vosys_gpu_pclk.common,
1047 	&iopmp_dpu1_aclk.common,
1048 	&iopmp_dpu_aclk.common,
1049 	&iopmp_gpu_aclk.common,
1050 	&mipi_dsi0_pixclk.common,
1051 	&mipi_dsi1_pixclk.common,
1052 	&hdmi_pixclk.common
1053 };
1054 
1055 static const struct regmap_config th1520_clk_regmap_config = {
1056 	.reg_bits = 32,
1057 	.val_bits = 32,
1058 	.reg_stride = 4,
1059 	.fast_io = true,
1060 };
1061 
1062 struct th1520_plat_data {
1063 	struct ccu_common **th1520_pll_clks;
1064 	struct ccu_common **th1520_div_clks;
1065 	struct ccu_mux	  **th1520_mux_clks;
1066 	struct ccu_common **th1520_gate_clks;
1067 
1068 	int nr_clks;
1069 	int nr_pll_clks;
1070 	int nr_div_clks;
1071 	int nr_mux_clks;
1072 	int nr_gate_clks;
1073 };
1074 
1075 static const struct th1520_plat_data th1520_ap_platdata = {
1076 	.th1520_pll_clks = th1520_pll_clks,
1077 	.th1520_div_clks = th1520_div_clks,
1078 	.th1520_mux_clks = th1520_mux_clks,
1079 	.th1520_gate_clks = th1520_gate_clks,
1080 
1081 	.nr_clks = CLK_UART_SCLK + 1,
1082 
1083 	.nr_pll_clks = ARRAY_SIZE(th1520_pll_clks),
1084 	.nr_div_clks = ARRAY_SIZE(th1520_div_clks),
1085 	.nr_mux_clks = ARRAY_SIZE(th1520_mux_clks),
1086 	.nr_gate_clks = ARRAY_SIZE(th1520_gate_clks),
1087 };
1088 
1089 static const struct th1520_plat_data th1520_vo_platdata = {
1090 	.th1520_gate_clks = th1520_vo_gate_clks,
1091 
1092 	.nr_clks = CLK_HDMI_PIXCLK + 1,
1093 
1094 	.nr_gate_clks = ARRAY_SIZE(th1520_vo_gate_clks),
1095 };
1096 
th1520_clk_probe(struct platform_device * pdev)1097 static int th1520_clk_probe(struct platform_device *pdev)
1098 {
1099 	const struct th1520_plat_data *plat_data;
1100 	struct device *dev = &pdev->dev;
1101 	struct clk_hw_onecell_data *priv;
1102 
1103 	struct regmap *map;
1104 	void __iomem *base;
1105 	struct clk_hw *hw;
1106 	int ret, i;
1107 
1108 	plat_data = device_get_match_data(&pdev->dev);
1109 	if (!plat_data)
1110 		return dev_err_probe(&pdev->dev, -ENODEV,
1111 				     "No device match data found\n");
1112 
1113 	priv = devm_kzalloc(dev, struct_size(priv, hws, plat_data->nr_clks), GFP_KERNEL);
1114 	if (!priv)
1115 		return -ENOMEM;
1116 
1117 	priv->num = plat_data->nr_clks;
1118 
1119 	base = devm_platform_ioremap_resource(pdev, 0);
1120 	if (IS_ERR(base))
1121 		return PTR_ERR(base);
1122 
1123 	map = devm_regmap_init_mmio(dev, base, &th1520_clk_regmap_config);
1124 	if (IS_ERR(map))
1125 		return PTR_ERR(map);
1126 
1127 	for (i = 0; i < plat_data->nr_pll_clks; i++) {
1128 		struct ccu_pll *cp = hw_to_ccu_pll(&plat_data->th1520_pll_clks[i]->hw);
1129 
1130 		plat_data->th1520_pll_clks[i]->map = map;
1131 
1132 		ret = devm_clk_hw_register(dev, &plat_data->th1520_pll_clks[i]->hw);
1133 		if (ret)
1134 			return ret;
1135 
1136 		priv->hws[cp->common.clkid] = &cp->common.hw;
1137 	}
1138 
1139 	for (i = 0; i < plat_data->nr_div_clks; i++) {
1140 		struct ccu_div *cd = hw_to_ccu_div(&plat_data->th1520_div_clks[i]->hw);
1141 
1142 		plat_data->th1520_div_clks[i]->map = map;
1143 
1144 		ret = devm_clk_hw_register(dev, &plat_data->th1520_div_clks[i]->hw);
1145 		if (ret)
1146 			return ret;
1147 
1148 		priv->hws[cd->common.clkid] = &cd->common.hw;
1149 	}
1150 
1151 	for (i = 0; i < plat_data->nr_mux_clks; i++) {
1152 		struct ccu_mux *cm = plat_data->th1520_mux_clks[i];
1153 
1154 		cm->mux.reg = base + cm->reg;
1155 
1156 		ret = devm_clk_hw_register(dev, &cm->mux.hw);
1157 		if (ret)
1158 			return ret;
1159 
1160 		priv->hws[cm->clkid] = &cm->mux.hw;
1161 	}
1162 
1163 	for (i = 0; i < plat_data->nr_gate_clks; i++) {
1164 		struct ccu_gate *cg = hw_to_ccu_gate(&plat_data->th1520_gate_clks[i]->hw);
1165 
1166 		plat_data->th1520_gate_clks[i]->map = map;
1167 
1168 		hw = devm_clk_hw_register_gate_parent_data(dev,
1169 							   cg->common.hw.init->name,
1170 							   cg->common.hw.init->parent_data,
1171 							   cg->common.hw.init->flags,
1172 							   base + cg->common.cfg0,
1173 							   ffs(cg->enable) - 1, 0, NULL);
1174 		if (IS_ERR(hw))
1175 			return PTR_ERR(hw);
1176 
1177 		priv->hws[cg->common.clkid] = hw;
1178 	}
1179 
1180 	if (plat_data == &th1520_ap_platdata) {
1181 		ret = devm_clk_hw_register(dev, &osc12m_clk.hw);
1182 		if (ret)
1183 			return ret;
1184 		priv->hws[CLK_OSC12M] = &osc12m_clk.hw;
1185 
1186 		ret = devm_clk_hw_register(dev, &gmac_pll_clk_100m.hw);
1187 		if (ret)
1188 			return ret;
1189 		priv->hws[CLK_PLL_GMAC_100M] = &gmac_pll_clk_100m.hw;
1190 
1191 		ret = devm_clk_hw_register(dev, &emmc_sdio_ref_clk.hw);
1192 		if (ret)
1193 			return ret;
1194 	}
1195 
1196 	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, priv);
1197 	if (ret)
1198 		return ret;
1199 
1200 	return 0;
1201 }
1202 
1203 static const struct of_device_id th1520_clk_match[] = {
1204 	{
1205 		.compatible = "thead,th1520-clk-ap",
1206 		.data = &th1520_ap_platdata,
1207 	},
1208 	{
1209 		.compatible = "thead,th1520-clk-vo",
1210 		.data = &th1520_vo_platdata,
1211 	},
1212 	{ /* sentinel */ },
1213 };
1214 MODULE_DEVICE_TABLE(of, th1520_clk_match);
1215 
1216 static struct platform_driver th1520_clk_driver = {
1217 	.probe		= th1520_clk_probe,
1218 	.driver		= {
1219 		.name	= "th1520-clk",
1220 		.of_match_table = th1520_clk_match,
1221 	},
1222 };
1223 module_platform_driver(th1520_clk_driver);
1224 
1225 MODULE_DESCRIPTION("T-HEAD TH1520 AP Clock driver");
1226 MODULE_AUTHOR("Yangtao Li <frank.li@vivo.com>");
1227 MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
1228 MODULE_LICENSE("GPL");
1229