1 // SPDX-License-Identifier: GPL-2.0
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>
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>
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
30 struct ccu_div_internal
{
45 struct ccu_internal mux
;
46 struct ccu_common common
;
51 struct ccu_common common
;
56 struct ccu_div_internal div
;
57 struct ccu_internal mux
;
58 struct ccu_common common
;
62 struct ccu_common common
;
65 #define TH_CCU_ARG(_shift, _width) \
71 #define TH_CCU_DIV_FLAGS(_shift, _width, _flags) \
78 #define CCU_GATE(_clkid, _struct, _name, _parent, _reg, _gate, _flags) \
79 struct ccu_gate _struct = { \
84 .hw.init = CLK_HW_INIT_PARENTS_DATA( \
92 static inline struct ccu_common
*hw_to_ccu_common(struct clk_hw
*hw
)
94 return container_of(hw
, struct ccu_common
, hw
);
97 static inline struct ccu_mux
*hw_to_ccu_mux(struct clk_hw
*hw
)
99 struct ccu_common
*common
= hw_to_ccu_common(hw
);
101 return container_of(common
, struct ccu_mux
, common
);
104 static inline struct ccu_pll
*hw_to_ccu_pll(struct clk_hw
*hw
)
106 struct ccu_common
*common
= hw_to_ccu_common(hw
);
108 return container_of(common
, struct ccu_pll
, common
);
111 static inline struct ccu_div
*hw_to_ccu_div(struct clk_hw
*hw
)
113 struct ccu_common
*common
= hw_to_ccu_common(hw
);
115 return container_of(common
, struct ccu_div
, common
);
118 static inline struct ccu_gate
*hw_to_ccu_gate(struct clk_hw
*hw
)
120 struct ccu_common
*common
= hw_to_ccu_common(hw
);
122 return container_of(common
, struct ccu_gate
, common
);
125 static u8
ccu_get_parent_helper(struct ccu_common
*common
,
126 struct ccu_internal
*mux
)
131 regmap_read(common
->map
, common
->cfg0
, &val
);
132 parent
= val
>> mux
->shift
;
133 parent
&= GENMASK(mux
->width
- 1, 0);
138 static int ccu_set_parent_helper(struct ccu_common
*common
,
139 struct ccu_internal
*mux
,
142 return regmap_update_bits(common
->map
, common
->cfg0
,
143 GENMASK(mux
->width
- 1, 0) << mux
->shift
,
144 index
<< mux
->shift
);
147 static void ccu_disable_helper(struct ccu_common
*common
, u32 gate
)
151 regmap_update_bits(common
->map
, common
->cfg0
,
155 static int ccu_enable_helper(struct ccu_common
*common
, u32 gate
)
163 ret
= regmap_update_bits(common
->map
, common
->cfg0
, gate
, gate
);
164 regmap_read(common
->map
, common
->cfg0
, &val
);
168 static int ccu_is_enabled_helper(struct ccu_common
*common
, u32 gate
)
175 regmap_read(common
->map
, common
->cfg0
, &val
);
179 static unsigned long ccu_div_recalc_rate(struct clk_hw
*hw
,
180 unsigned long parent_rate
)
182 struct ccu_div
*cd
= hw_to_ccu_div(hw
);
186 regmap_read(cd
->common
.map
, cd
->common
.cfg0
, &val
);
187 val
= val
>> cd
->div
.shift
;
188 val
&= GENMASK(cd
->div
.width
- 1, 0);
189 rate
= divider_recalc_rate(hw
, parent_rate
, val
, NULL
,
190 cd
->div
.flags
, cd
->div
.width
);
195 static u8
ccu_div_get_parent(struct clk_hw
*hw
)
197 struct ccu_div
*cd
= hw_to_ccu_div(hw
);
199 return ccu_get_parent_helper(&cd
->common
, &cd
->mux
);
202 static int ccu_div_set_parent(struct clk_hw
*hw
, u8 index
)
204 struct ccu_div
*cd
= hw_to_ccu_div(hw
);
206 return ccu_set_parent_helper(&cd
->common
, &cd
->mux
, index
);
209 static void ccu_div_disable(struct clk_hw
*hw
)
211 struct ccu_div
*cd
= hw_to_ccu_div(hw
);
213 ccu_disable_helper(&cd
->common
, cd
->enable
);
216 static int ccu_div_enable(struct clk_hw
*hw
)
218 struct ccu_div
*cd
= hw_to_ccu_div(hw
);
220 return ccu_enable_helper(&cd
->common
, cd
->enable
);
223 static int ccu_div_is_enabled(struct clk_hw
*hw
)
225 struct ccu_div
*cd
= hw_to_ccu_div(hw
);
227 return ccu_is_enabled_helper(&cd
->common
, cd
->enable
);
230 static const struct clk_ops ccu_div_ops
= {
231 .disable
= ccu_div_disable
,
232 .enable
= ccu_div_enable
,
233 .is_enabled
= ccu_div_is_enabled
,
234 .get_parent
= ccu_div_get_parent
,
235 .set_parent
= ccu_div_set_parent
,
236 .recalc_rate
= ccu_div_recalc_rate
,
237 .determine_rate
= clk_hw_determine_rate_no_reparent
,
240 static unsigned long th1520_pll_vco_recalc_rate(struct clk_hw
*hw
,
241 unsigned long parent_rate
)
243 struct ccu_pll
*pll
= hw_to_ccu_pll(hw
);
244 unsigned long div
, mul
, frac
;
245 unsigned int cfg0
, cfg1
;
246 u64 rate
= parent_rate
;
248 regmap_read(pll
->common
.map
, pll
->common
.cfg0
, &cfg0
);
249 regmap_read(pll
->common
.map
, pll
->common
.cfg1
, &cfg1
);
251 mul
= FIELD_GET(TH1520_PLL_FBDIV
, cfg0
);
252 div
= FIELD_GET(TH1520_PLL_REFDIV
, cfg0
);
253 if (!(cfg1
& TH1520_PLL_DSMPD
)) {
254 mul
<<= TH1520_PLL_FRAC_BITS
;
255 frac
= FIELD_GET(TH1520_PLL_FRAC
, cfg1
);
257 div
<<= TH1520_PLL_FRAC_BITS
;
259 rate
= parent_rate
* mul
;
264 static unsigned long th1520_pll_postdiv_recalc_rate(struct clk_hw
*hw
,
265 unsigned long parent_rate
)
267 struct ccu_pll
*pll
= hw_to_ccu_pll(hw
);
268 unsigned long div
, rate
= parent_rate
;
269 unsigned int cfg0
, cfg1
;
271 regmap_read(pll
->common
.map
, pll
->common
.cfg0
, &cfg0
);
272 regmap_read(pll
->common
.map
, pll
->common
.cfg1
, &cfg1
);
274 if (cfg1
& TH1520_PLL_BYPASS
)
277 div
= FIELD_GET(TH1520_PLL_POSTDIV1
, cfg0
) *
278 FIELD_GET(TH1520_PLL_POSTDIV2
, cfg0
);
285 static unsigned long ccu_pll_recalc_rate(struct clk_hw
*hw
,
286 unsigned long parent_rate
)
288 unsigned long rate
= parent_rate
;
290 rate
= th1520_pll_vco_recalc_rate(hw
, rate
);
291 rate
= th1520_pll_postdiv_recalc_rate(hw
, rate
);
296 static const struct clk_ops clk_pll_ops
= {
297 .recalc_rate
= ccu_pll_recalc_rate
,
300 static const struct clk_parent_data osc_24m_clk
[] = {
304 static struct ccu_pll cpu_pll0_clk
= {
306 .clkid
= CLK_CPU_PLL0
,
309 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("cpu-pll0",
316 static struct ccu_pll cpu_pll1_clk
= {
318 .clkid
= CLK_CPU_PLL1
,
321 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("cpu-pll1",
328 static struct ccu_pll gmac_pll_clk
= {
330 .clkid
= CLK_GMAC_PLL
,
333 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("gmac-pll",
340 static const struct clk_hw
*gmac_pll_clk_parent
[] = {
341 &gmac_pll_clk
.common
.hw
344 static const struct clk_parent_data gmac_pll_clk_pd
[] = {
345 { .hw
= &gmac_pll_clk
.common
.hw
}
348 static struct ccu_pll video_pll_clk
= {
350 .clkid
= CLK_VIDEO_PLL
,
353 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("video-pll",
360 static const struct clk_hw
*video_pll_clk_parent
[] = {
361 &video_pll_clk
.common
.hw
364 static const struct clk_parent_data video_pll_clk_pd
[] = {
365 { .hw
= &video_pll_clk
.common
.hw
}
368 static struct ccu_pll dpu0_pll_clk
= {
370 .clkid
= CLK_DPU0_PLL
,
373 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("dpu0-pll",
380 static const struct clk_hw
*dpu0_pll_clk_parent
[] = {
381 &dpu0_pll_clk
.common
.hw
384 static struct ccu_pll dpu1_pll_clk
= {
386 .clkid
= CLK_DPU1_PLL
,
389 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("dpu1-pll",
396 static const struct clk_hw
*dpu1_pll_clk_parent
[] = {
397 &dpu1_pll_clk
.common
.hw
400 static struct ccu_pll tee_pll_clk
= {
402 .clkid
= CLK_TEE_PLL
,
405 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("tee-pll",
412 static const struct clk_parent_data c910_i0_parents
[] = {
413 { .hw
= &cpu_pll0_clk
.common
.hw
},
417 static struct ccu_mux c910_i0_clk
= {
418 .mux
= TH_CCU_ARG(1, 1),
420 .clkid
= CLK_C910_I0
,
422 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("c910-i0",
429 static const struct clk_parent_data c910_parents
[] = {
430 { .hw
= &c910_i0_clk
.common
.hw
},
431 { .hw
= &cpu_pll1_clk
.common
.hw
}
434 static struct ccu_mux c910_clk
= {
435 .mux
= TH_CCU_ARG(0, 1),
439 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("c910",
446 static const struct clk_parent_data ahb2_cpusys_parents
[] = {
447 { .hw
= &gmac_pll_clk
.common
.hw
},
451 static struct ccu_div ahb2_cpusys_hclk
= {
452 .div
= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED
),
453 .mux
= TH_CCU_ARG(5, 1),
455 .clkid
= CLK_AHB2_CPUSYS_HCLK
,
457 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("ahb2-cpusys-hclk",
464 static const struct clk_parent_data ahb2_cpusys_hclk_pd
[] = {
465 { .hw
= &ahb2_cpusys_hclk
.common
.hw
}
468 static const struct clk_hw
*ahb2_cpusys_hclk_parent
[] = {
469 &ahb2_cpusys_hclk
.common
.hw
,
472 static struct ccu_div apb3_cpusys_pclk
= {
473 .div
= TH_CCU_ARG(0, 3),
475 .clkid
= CLK_APB3_CPUSYS_PCLK
,
477 .hw
.init
= CLK_HW_INIT_PARENTS_HW("apb3-cpusys-pclk",
478 ahb2_cpusys_hclk_parent
,
484 static const struct clk_parent_data apb3_cpusys_pclk_pd
[] = {
485 { .hw
= &apb3_cpusys_pclk
.common
.hw
}
488 static struct ccu_div axi4_cpusys2_aclk
= {
489 .div
= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED
),
491 .clkid
= CLK_AXI4_CPUSYS2_ACLK
,
493 .hw
.init
= CLK_HW_INIT_PARENTS_HW("axi4-cpusys2-aclk",
500 static const struct clk_parent_data axi4_cpusys2_aclk_pd
[] = {
501 { .hw
= &axi4_cpusys2_aclk
.common
.hw
}
504 static const struct clk_parent_data axi_parents
[] = {
505 { .hw
= &video_pll_clk
.common
.hw
},
509 static struct ccu_div axi_aclk
= {
510 .div
= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED
),
511 .mux
= TH_CCU_ARG(5, 1),
513 .clkid
= CLK_AXI_ACLK
,
515 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("axi-aclk",
522 static const struct clk_parent_data axi_aclk_pd
[] = {
523 { .hw
= &axi_aclk
.common
.hw
}
526 static const struct clk_parent_data perisys_ahb_hclk_parents
[] = {
527 { .hw
= &gmac_pll_clk
.common
.hw
},
531 static struct ccu_div perisys_ahb_hclk
= {
533 .div
= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED
),
534 .mux
= TH_CCU_ARG(5, 1),
536 .clkid
= CLK_PERI_AHB_HCLK
,
538 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("perisys-ahb-hclk",
539 perisys_ahb_hclk_parents
,
545 static const struct clk_parent_data perisys_ahb_hclk_pd
[] = {
546 { .hw
= &perisys_ahb_hclk
.common
.hw
}
549 static const struct clk_hw
*perisys_ahb_hclk_parent
[] = {
550 &perisys_ahb_hclk
.common
.hw
553 static struct ccu_div perisys_apb_pclk
= {
554 .div
= TH_CCU_ARG(0, 3),
556 .clkid
= CLK_PERI_APB_PCLK
,
558 .hw
.init
= CLK_HW_INIT_PARENTS_HW("perisys-apb-pclk",
559 perisys_ahb_hclk_parent
,
565 static const struct clk_parent_data perisys_apb_pclk_pd
[] = {
566 { .hw
= &perisys_apb_pclk
.common
.hw
}
569 static struct ccu_div peri2sys_apb_pclk
= {
570 .div
= TH_CCU_DIV_FLAGS(4, 3, CLK_DIVIDER_ONE_BASED
),
572 .clkid
= CLK_PERI2APB_PCLK
,
574 .hw
.init
= CLK_HW_INIT_PARENTS_HW("peri2sys-apb-pclk",
581 static const struct clk_parent_data peri2sys_apb_pclk_pd
[] = {
582 { .hw
= &peri2sys_apb_pclk
.common
.hw
}
585 static CLK_FIXED_FACTOR_FW_NAME(osc12m_clk
, "osc_12m", "osc_24m", 2, 1, 0);
587 static const char * const out_parents
[] = { "osc_24m", "osc_12m" };
589 static struct ccu_div out1_clk
= {
591 .div
= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED
),
592 .mux
= TH_CCU_ARG(4, 1),
596 .hw
.init
= CLK_HW_INIT_PARENTS("out1",
603 static struct ccu_div out2_clk
= {
605 .div
= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED
),
606 .mux
= TH_CCU_ARG(4, 1),
610 .hw
.init
= CLK_HW_INIT_PARENTS("out2",
617 static struct ccu_div out3_clk
= {
619 .div
= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED
),
620 .mux
= TH_CCU_ARG(4, 1),
624 .hw
.init
= CLK_HW_INIT_PARENTS("out3",
631 static struct ccu_div out4_clk
= {
633 .div
= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED
),
634 .mux
= TH_CCU_ARG(4, 1),
638 .hw
.init
= CLK_HW_INIT_PARENTS("out4",
645 static const struct clk_parent_data apb_parents
[] = {
646 { .hw
= &gmac_pll_clk
.common
.hw
},
650 static struct ccu_div apb_pclk
= {
652 .div
= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED
),
653 .mux
= TH_CCU_ARG(7, 1),
655 .clkid
= CLK_APB_PCLK
,
657 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("apb-pclk",
664 static const struct clk_hw
*npu_parents
[] = {
665 &gmac_pll_clk
.common
.hw
,
666 &video_pll_clk
.common
.hw
669 static struct ccu_div npu_clk
= {
671 .div
= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED
),
672 .mux
= TH_CCU_ARG(6, 1),
676 .hw
.init
= CLK_HW_INIT_PARENTS_HW("npu",
683 static struct ccu_div vi_clk
= {
684 .div
= TH_CCU_DIV_FLAGS(16, 4, CLK_DIVIDER_ONE_BASED
),
688 .hw
.init
= CLK_HW_INIT_PARENTS_HW("vi",
689 video_pll_clk_parent
,
695 static struct ccu_div vi_ahb_clk
= {
696 .div
= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED
),
700 .hw
.init
= CLK_HW_INIT_PARENTS_HW("vi-ahb",
701 video_pll_clk_parent
,
707 static struct ccu_div vo_axi_clk
= {
709 .div
= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED
),
713 .hw
.init
= CLK_HW_INIT_PARENTS_HW("vo-axi",
714 video_pll_clk_parent
,
720 static struct ccu_div vp_apb_clk
= {
721 .div
= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED
),
725 .hw
.init
= CLK_HW_INIT_PARENTS_HW("vp-apb",
732 static struct ccu_div vp_axi_clk
= {
734 .div
= TH_CCU_DIV_FLAGS(8, 4, CLK_DIVIDER_ONE_BASED
),
738 .hw
.init
= CLK_HW_INIT_PARENTS_HW("vp-axi",
739 video_pll_clk_parent
,
745 static struct ccu_div venc_clk
= {
747 .div
= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED
),
751 .hw
.init
= CLK_HW_INIT_PARENTS_HW("venc",
758 static struct ccu_div dpu0_clk
= {
759 .div
= TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED
),
763 .hw
.init
= CLK_HW_INIT_PARENTS_HW("dpu0",
770 static struct ccu_div dpu1_clk
= {
771 .div
= TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED
),
775 .hw
.init
= CLK_HW_INIT_PARENTS_HW("dpu1",
782 static CCU_GATE(CLK_BROM
, brom_clk
, "brom", ahb2_cpusys_hclk_pd
, 0x100, BIT(4), 0);
783 static CCU_GATE(CLK_BMU
, bmu_clk
, "bmu", axi4_cpusys2_aclk_pd
, 0x100, BIT(5), 0);
784 static CCU_GATE(CLK_AON2CPU_A2X
, aon2cpu_a2x_clk
, "aon2cpu-a2x", axi4_cpusys2_aclk_pd
,
786 static CCU_GATE(CLK_X2X_CPUSYS
, x2x_cpusys_clk
, "x2x-cpusys", axi4_cpusys2_aclk_pd
,
788 static CCU_GATE(CLK_CPU2AON_X2H
, cpu2aon_x2h_clk
, "cpu2aon-x2h", axi_aclk_pd
, 0x138, BIT(8), 0);
789 static CCU_GATE(CLK_CPU2PERI_X2H
, cpu2peri_x2h_clk
, "cpu2peri-x2h", axi4_cpusys2_aclk_pd
,
791 static CCU_GATE(CLK_PERISYS_APB1_HCLK
, perisys_apb1_hclk
, "perisys-apb1-hclk", perisys_ahb_hclk_pd
,
793 static CCU_GATE(CLK_PERISYS_APB2_HCLK
, perisys_apb2_hclk
, "perisys-apb2-hclk", perisys_ahb_hclk_pd
,
795 static CCU_GATE(CLK_PERISYS_APB3_HCLK
, perisys_apb3_hclk
, "perisys-apb3-hclk", perisys_ahb_hclk_pd
,
797 static CCU_GATE(CLK_PERISYS_APB4_HCLK
, perisys_apb4_hclk
, "perisys-apb4-hclk", perisys_ahb_hclk_pd
,
799 static CCU_GATE(CLK_NPU_AXI
, npu_axi_clk
, "npu-axi", axi_aclk_pd
, 0x1c8, BIT(5), 0);
800 static CCU_GATE(CLK_CPU2VP
, cpu2vp_clk
, "cpu2vp", axi_aclk_pd
, 0x1e0, BIT(13), 0);
801 static CCU_GATE(CLK_EMMC_SDIO
, emmc_sdio_clk
, "emmc-sdio", video_pll_clk_pd
, 0x204, BIT(30), 0);
802 static CCU_GATE(CLK_GMAC1
, gmac1_clk
, "gmac1", gmac_pll_clk_pd
, 0x204, BIT(26), 0);
803 static CCU_GATE(CLK_PADCTRL1
, padctrl1_clk
, "padctrl1", perisys_apb_pclk_pd
, 0x204, BIT(24), 0);
804 static CCU_GATE(CLK_DSMART
, dsmart_clk
, "dsmart", perisys_apb_pclk_pd
, 0x204, BIT(23), 0);
805 static CCU_GATE(CLK_PADCTRL0
, padctrl0_clk
, "padctrl0", perisys_apb_pclk_pd
, 0x204, BIT(22), 0);
806 static CCU_GATE(CLK_GMAC_AXI
, gmac_axi_clk
, "gmac-axi", axi4_cpusys2_aclk_pd
, 0x204, BIT(21), 0);
807 static CCU_GATE(CLK_GPIO3
, gpio3_clk
, "gpio3-clk", peri2sys_apb_pclk_pd
, 0x204, BIT(20), 0);
808 static CCU_GATE(CLK_GMAC0
, gmac0_clk
, "gmac0", gmac_pll_clk_pd
, 0x204, BIT(19), 0);
809 static CCU_GATE(CLK_PWM
, pwm_clk
, "pwm", perisys_apb_pclk_pd
, 0x204, BIT(18), 0);
810 static CCU_GATE(CLK_QSPI0
, qspi0_clk
, "qspi0", video_pll_clk_pd
, 0x204, BIT(17), 0);
811 static CCU_GATE(CLK_QSPI1
, qspi1_clk
, "qspi1", video_pll_clk_pd
, 0x204, BIT(16), 0);
812 static CCU_GATE(CLK_SPI
, spi_clk
, "spi", video_pll_clk_pd
, 0x204, BIT(15), 0);
813 static CCU_GATE(CLK_UART0_PCLK
, uart0_pclk
, "uart0-pclk", perisys_apb_pclk_pd
, 0x204, BIT(14), 0);
814 static CCU_GATE(CLK_UART1_PCLK
, uart1_pclk
, "uart1-pclk", perisys_apb_pclk_pd
, 0x204, BIT(13), 0);
815 static CCU_GATE(CLK_UART2_PCLK
, uart2_pclk
, "uart2-pclk", perisys_apb_pclk_pd
, 0x204, BIT(12), 0);
816 static CCU_GATE(CLK_UART3_PCLK
, uart3_pclk
, "uart3-pclk", perisys_apb_pclk_pd
, 0x204, BIT(11), 0);
817 static CCU_GATE(CLK_UART4_PCLK
, uart4_pclk
, "uart4-pclk", perisys_apb_pclk_pd
, 0x204, BIT(10), 0);
818 static CCU_GATE(CLK_UART5_PCLK
, uart5_pclk
, "uart5-pclk", perisys_apb_pclk_pd
, 0x204, BIT(9), 0);
819 static CCU_GATE(CLK_GPIO0
, gpio0_clk
, "gpio0-clk", perisys_apb_pclk_pd
, 0x204, BIT(8), 0);
820 static CCU_GATE(CLK_GPIO1
, gpio1_clk
, "gpio1-clk", perisys_apb_pclk_pd
, 0x204, BIT(7), 0);
821 static CCU_GATE(CLK_GPIO2
, gpio2_clk
, "gpio2-clk", peri2sys_apb_pclk_pd
, 0x204, BIT(6), 0);
822 static CCU_GATE(CLK_I2C0
, i2c0_clk
, "i2c0", perisys_apb_pclk_pd
, 0x204, BIT(5), 0);
823 static CCU_GATE(CLK_I2C1
, i2c1_clk
, "i2c1", perisys_apb_pclk_pd
, 0x204, BIT(4), 0);
824 static CCU_GATE(CLK_I2C2
, i2c2_clk
, "i2c2", perisys_apb_pclk_pd
, 0x204, BIT(3), 0);
825 static CCU_GATE(CLK_I2C3
, i2c3_clk
, "i2c3", perisys_apb_pclk_pd
, 0x204, BIT(2), 0);
826 static CCU_GATE(CLK_I2C4
, i2c4_clk
, "i2c4", perisys_apb_pclk_pd
, 0x204, BIT(1), 0);
827 static CCU_GATE(CLK_I2C5
, i2c5_clk
, "i2c5", perisys_apb_pclk_pd
, 0x204, BIT(0), 0);
828 static CCU_GATE(CLK_SPINLOCK
, spinlock_clk
, "spinlock", ahb2_cpusys_hclk_pd
, 0x208, BIT(10), 0);
829 static CCU_GATE(CLK_DMA
, dma_clk
, "dma", axi4_cpusys2_aclk_pd
, 0x208, BIT(8), 0);
830 static CCU_GATE(CLK_MBOX0
, mbox0_clk
, "mbox0", apb3_cpusys_pclk_pd
, 0x208, BIT(7), 0);
831 static CCU_GATE(CLK_MBOX1
, mbox1_clk
, "mbox1", apb3_cpusys_pclk_pd
, 0x208, BIT(6), 0);
832 static CCU_GATE(CLK_MBOX2
, mbox2_clk
, "mbox2", apb3_cpusys_pclk_pd
, 0x208, BIT(5), 0);
833 static CCU_GATE(CLK_MBOX3
, mbox3_clk
, "mbox3", apb3_cpusys_pclk_pd
, 0x208, BIT(4), 0);
834 static CCU_GATE(CLK_WDT0
, wdt0_clk
, "wdt0", apb3_cpusys_pclk_pd
, 0x208, BIT(3), 0);
835 static CCU_GATE(CLK_WDT1
, wdt1_clk
, "wdt1", apb3_cpusys_pclk_pd
, 0x208, BIT(2), 0);
836 static CCU_GATE(CLK_TIMER0
, timer0_clk
, "timer0", apb3_cpusys_pclk_pd
, 0x208, BIT(1), 0);
837 static CCU_GATE(CLK_TIMER1
, timer1_clk
, "timer1", apb3_cpusys_pclk_pd
, 0x208, BIT(0), 0);
838 static CCU_GATE(CLK_SRAM0
, sram0_clk
, "sram0", axi_aclk_pd
, 0x20c, BIT(4), 0);
839 static CCU_GATE(CLK_SRAM1
, sram1_clk
, "sram1", axi_aclk_pd
, 0x20c, BIT(3), 0);
840 static CCU_GATE(CLK_SRAM2
, sram2_clk
, "sram2", axi_aclk_pd
, 0x20c, BIT(2), 0);
841 static CCU_GATE(CLK_SRAM3
, sram3_clk
, "sram3", axi_aclk_pd
, 0x20c, BIT(1), 0);
843 static CLK_FIXED_FACTOR_HW(gmac_pll_clk_100m
, "gmac-pll-clk-100m",
844 &gmac_pll_clk
.common
.hw
, 10, 1, 0);
846 static const struct clk_parent_data uart_sclk_parents
[] = {
847 { .hw
= &gmac_pll_clk_100m
.hw
},
851 static struct ccu_mux uart_sclk
= {
852 .mux
= TH_CCU_ARG(0, 1),
854 .clkid
= CLK_UART_SCLK
,
856 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("uart-sclk",
863 static struct ccu_common
*th1520_pll_clks
[] = {
864 &cpu_pll0_clk
.common
,
865 &cpu_pll1_clk
.common
,
866 &gmac_pll_clk
.common
,
867 &video_pll_clk
.common
,
868 &dpu0_pll_clk
.common
,
869 &dpu1_pll_clk
.common
,
873 static struct ccu_common
*th1520_div_clks
[] = {
874 &ahb2_cpusys_hclk
.common
,
875 &apb3_cpusys_pclk
.common
,
876 &axi4_cpusys2_aclk
.common
,
877 &perisys_ahb_hclk
.common
,
878 &perisys_apb_pclk
.common
,
880 &peri2sys_apb_pclk
.common
,
898 static struct ccu_common
*th1520_mux_clks
[] = {
904 static struct ccu_common
*th1520_gate_clks
[] = {
905 &emmc_sdio_clk
.common
,
906 &aon2cpu_a2x_clk
.common
,
907 &x2x_cpusys_clk
.common
,
910 &cpu2aon_x2h_clk
.common
,
911 &cpu2peri_x2h_clk
.common
,
912 &perisys_apb1_hclk
.common
,
913 &perisys_apb2_hclk
.common
,
914 &perisys_apb3_hclk
.common
,
915 &perisys_apb4_hclk
.common
,
918 &padctrl1_clk
.common
,
920 &padctrl0_clk
.common
,
921 &gmac_axi_clk
.common
,
943 &spinlock_clk
.common
,
959 #define NR_CLKS (CLK_UART_SCLK + 1)
961 static const struct regmap_config th1520_clk_regmap_config
= {
968 static int th1520_clk_probe(struct platform_device
*pdev
)
970 struct device
*dev
= &pdev
->dev
;
971 struct clk_hw_onecell_data
*priv
;
978 priv
= devm_kzalloc(dev
, struct_size(priv
, hws
, NR_CLKS
), GFP_KERNEL
);
984 base
= devm_platform_ioremap_resource(pdev
, 0);
986 return PTR_ERR(base
);
988 map
= devm_regmap_init_mmio(dev
, base
, &th1520_clk_regmap_config
);
992 for (i
= 0; i
< ARRAY_SIZE(th1520_pll_clks
); i
++) {
993 struct ccu_pll
*cp
= hw_to_ccu_pll(&th1520_pll_clks
[i
]->hw
);
995 th1520_pll_clks
[i
]->map
= map
;
997 ret
= devm_clk_hw_register(dev
, &th1520_pll_clks
[i
]->hw
);
1001 priv
->hws
[cp
->common
.clkid
] = &cp
->common
.hw
;
1004 for (i
= 0; i
< ARRAY_SIZE(th1520_div_clks
); i
++) {
1005 struct ccu_div
*cd
= hw_to_ccu_div(&th1520_div_clks
[i
]->hw
);
1007 th1520_div_clks
[i
]->map
= map
;
1009 ret
= devm_clk_hw_register(dev
, &th1520_div_clks
[i
]->hw
);
1013 priv
->hws
[cd
->common
.clkid
] = &cd
->common
.hw
;
1016 for (i
= 0; i
< ARRAY_SIZE(th1520_mux_clks
); i
++) {
1017 struct ccu_mux
*cm
= hw_to_ccu_mux(&th1520_mux_clks
[i
]->hw
);
1018 const struct clk_init_data
*init
= cm
->common
.hw
.init
;
1020 th1520_mux_clks
[i
]->map
= map
;
1021 hw
= devm_clk_hw_register_mux_parent_data_table(dev
,
1026 base
+ cm
->common
.cfg0
,
1033 priv
->hws
[cm
->common
.clkid
] = hw
;
1036 for (i
= 0; i
< ARRAY_SIZE(th1520_gate_clks
); i
++) {
1037 struct ccu_gate
*cg
= hw_to_ccu_gate(&th1520_gate_clks
[i
]->hw
);
1039 th1520_gate_clks
[i
]->map
= map
;
1041 hw
= devm_clk_hw_register_gate_parent_data(dev
,
1042 cg
->common
.hw
.init
->name
,
1043 cg
->common
.hw
.init
->parent_data
,
1044 0, base
+ cg
->common
.cfg0
,
1045 ffs(cg
->enable
) - 1, 0, NULL
);
1049 priv
->hws
[cg
->common
.clkid
] = hw
;
1052 ret
= devm_clk_hw_register(dev
, &osc12m_clk
.hw
);
1055 priv
->hws
[CLK_OSC12M
] = &osc12m_clk
.hw
;
1057 ret
= devm_clk_hw_register(dev
, &gmac_pll_clk_100m
.hw
);
1060 priv
->hws
[CLK_PLL_GMAC_100M
] = &gmac_pll_clk_100m
.hw
;
1062 ret
= devm_of_clk_add_hw_provider(dev
, of_clk_hw_onecell_get
, priv
);
1069 static const struct of_device_id th1520_clk_match
[] = {
1071 .compatible
= "thead,th1520-clk-ap",
1075 MODULE_DEVICE_TABLE(of
, th1520_clk_match
);
1077 static struct platform_driver th1520_clk_driver
= {
1078 .probe
= th1520_clk_probe
,
1080 .name
= "th1520-clk",
1081 .of_match_table
= th1520_clk_match
,
1084 module_platform_driver(th1520_clk_driver
);
1086 MODULE_DESCRIPTION("T-HEAD TH1520 AP Clock driver");
1087 MODULE_AUTHOR("Yangtao Li <frank.li@vivo.com>");
1088 MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
1089 MODULE_LICENSE("GPL");