166af5425SGhennadi Procopciuc /*
247b3a825SGhennadi Procopciuc * Copyright 2024-2025 NXP
366af5425SGhennadi Procopciuc *
466af5425SGhennadi Procopciuc * SPDX-License-Identifier: BSD-3-Clause
566af5425SGhennadi Procopciuc */
666af5425SGhennadi Procopciuc #include <drivers/clk.h>
7e4462daeSGhennadi Procopciuc #include <platform_def.h>
866af5425SGhennadi Procopciuc #include <s32cc-clk-drv.h>
966af5425SGhennadi Procopciuc #include <s32cc-clk-ids.h>
10*c0cbf5adSKhristine Andreea Barbulescu #include <s32cc-clk-regs.h>
11*c0cbf5adSKhristine Andreea Barbulescu #include <s32cc-mc-rgm.h>
1266af5425SGhennadi Procopciuc #include <s32cc-clk-utils.h>
1366af5425SGhennadi Procopciuc
1466af5425SGhennadi Procopciuc #define S32CC_FXOSC_FREQ (40U * MHZ)
157ad4e231SGhennadi Procopciuc #define S32CC_ARM_PLL_VCO_FREQ (2U * GHZ)
16de950ef0SGhennadi Procopciuc #define S32CC_ARM_PLL_PHI0_FREQ (1U * GHZ)
1764e0c226SGhennadi Procopciuc #define S32CC_A53_FREQ (1U * GHZ)
18b8ad8800SGhennadi Procopciuc #define S32CC_XBAR_2X_FREQ (800U * MHZ)
198653352aSGhennadi Procopciuc #define S32CC_PERIPH_PLL_VCO_FREQ (2U * GHZ)
20e4462daeSGhennadi Procopciuc #define S32CC_PERIPH_PLL_PHI3_FREQ UART_CLOCK_HZ
2118c2b137SGhennadi Procopciuc #define S32CC_DDR_PLL_VCO_FREQ (1600U * MHZ)
2218c2b137SGhennadi Procopciuc #define S32CC_DDR_PLL_PHI0_FREQ (800U * MHZ)
2347b3a825SGhennadi Procopciuc #define S32CC_PERIPH_DFS_PHI3_FREQ (800U * MHZ)
249c640e09SGhennadi Procopciuc #define S32CC_USDHC_FREQ (200U * MHZ)
2566af5425SGhennadi Procopciuc
26*c0cbf5adSKhristine Andreea Barbulescu #define S32CC_DDR_RESET_TIMEOUT_US 1000000U
27*c0cbf5adSKhristine Andreea Barbulescu
setup_fxosc(void)285300040bSGhennadi Procopciuc static int setup_fxosc(void)
2966af5425SGhennadi Procopciuc {
3066af5425SGhennadi Procopciuc int ret;
3166af5425SGhennadi Procopciuc
32d3869455SGhennadi Procopciuc ret = clk_set_rate(S32CC_CLK_FXOSC, S32CC_FXOSC_FREQ, NULL);
33d3869455SGhennadi Procopciuc if (ret != 0) {
34d3869455SGhennadi Procopciuc return ret;
35d3869455SGhennadi Procopciuc }
36d3869455SGhennadi Procopciuc
37d3869455SGhennadi Procopciuc return ret;
38d3869455SGhennadi Procopciuc }
39d3869455SGhennadi Procopciuc
setup_arm_pll(void)405300040bSGhennadi Procopciuc static int setup_arm_pll(void)
41d3869455SGhennadi Procopciuc {
42d3869455SGhennadi Procopciuc int ret;
4366af5425SGhennadi Procopciuc
4483af4504SGhennadi Procopciuc ret = clk_set_parent(S32CC_CLK_ARM_PLL_MUX, S32CC_CLK_FXOSC);
4583af4504SGhennadi Procopciuc if (ret != 0) {
4683af4504SGhennadi Procopciuc return ret;
4783af4504SGhennadi Procopciuc }
4883af4504SGhennadi Procopciuc
497ad4e231SGhennadi Procopciuc ret = clk_set_rate(S32CC_CLK_ARM_PLL_VCO, S32CC_ARM_PLL_VCO_FREQ, NULL);
507ad4e231SGhennadi Procopciuc if (ret != 0) {
517ad4e231SGhennadi Procopciuc return ret;
527ad4e231SGhennadi Procopciuc }
537ad4e231SGhennadi Procopciuc
54de950ef0SGhennadi Procopciuc ret = clk_set_rate(S32CC_CLK_ARM_PLL_PHI0, S32CC_ARM_PLL_PHI0_FREQ, NULL);
55de950ef0SGhennadi Procopciuc if (ret != 0) {
56de950ef0SGhennadi Procopciuc return ret;
57de950ef0SGhennadi Procopciuc }
58de950ef0SGhennadi Procopciuc
59b5101c45SGhennadi Procopciuc return ret;
60b5101c45SGhennadi Procopciuc }
61b5101c45SGhennadi Procopciuc
setup_periph_pll(void)625300040bSGhennadi Procopciuc static int setup_periph_pll(void)
638653352aSGhennadi Procopciuc {
648653352aSGhennadi Procopciuc int ret;
658653352aSGhennadi Procopciuc
668653352aSGhennadi Procopciuc ret = clk_set_parent(S32CC_CLK_PERIPH_PLL_MUX, S32CC_CLK_FXOSC);
678653352aSGhennadi Procopciuc if (ret != 0) {
688653352aSGhennadi Procopciuc return ret;
698653352aSGhennadi Procopciuc }
708653352aSGhennadi Procopciuc
718653352aSGhennadi Procopciuc ret = clk_set_rate(S32CC_CLK_PERIPH_PLL_VCO, S32CC_PERIPH_PLL_VCO_FREQ, NULL);
728653352aSGhennadi Procopciuc if (ret != 0) {
738653352aSGhennadi Procopciuc return ret;
748653352aSGhennadi Procopciuc }
758653352aSGhennadi Procopciuc
768653352aSGhennadi Procopciuc ret = clk_set_rate(S32CC_CLK_PERIPH_PLL_PHI3, S32CC_PERIPH_PLL_PHI3_FREQ, NULL);
778653352aSGhennadi Procopciuc if (ret != 0) {
788653352aSGhennadi Procopciuc return ret;
798653352aSGhennadi Procopciuc }
808653352aSGhennadi Procopciuc
818653352aSGhennadi Procopciuc return ret;
828653352aSGhennadi Procopciuc }
838653352aSGhennadi Procopciuc
enable_a53_clk(void)84d3869455SGhennadi Procopciuc static int enable_a53_clk(void)
85d3869455SGhennadi Procopciuc {
86d3869455SGhennadi Procopciuc int ret;
87d3869455SGhennadi Procopciuc
88d3869455SGhennadi Procopciuc ret = clk_set_parent(S32CC_CLK_MC_CGM1_MUX0, S32CC_CLK_ARM_PLL_PHI0);
89d3869455SGhennadi Procopciuc if (ret != 0) {
90d3869455SGhennadi Procopciuc return ret;
91d3869455SGhennadi Procopciuc }
92d3869455SGhennadi Procopciuc
93d3869455SGhennadi Procopciuc ret = clk_set_rate(S32CC_CLK_A53_CORE, S32CC_A53_FREQ, NULL);
94d3869455SGhennadi Procopciuc if (ret != 0) {
95d3869455SGhennadi Procopciuc return ret;
96d3869455SGhennadi Procopciuc }
97d3869455SGhennadi Procopciuc
987004f678SGhennadi Procopciuc ret = clk_enable(S32CC_CLK_A53_CORE);
997004f678SGhennadi Procopciuc if (ret != 0) {
1007004f678SGhennadi Procopciuc return ret;
1017004f678SGhennadi Procopciuc }
1027004f678SGhennadi Procopciuc
10366af5425SGhennadi Procopciuc return ret;
10466af5425SGhennadi Procopciuc }
105d3869455SGhennadi Procopciuc
enable_xbar_clk(void)106b8ad8800SGhennadi Procopciuc static int enable_xbar_clk(void)
107b8ad8800SGhennadi Procopciuc {
108b8ad8800SGhennadi Procopciuc int ret;
109b8ad8800SGhennadi Procopciuc
110b8ad8800SGhennadi Procopciuc ret = clk_set_parent(S32CC_CLK_MC_CGM0_MUX0, S32CC_CLK_ARM_PLL_DFS1);
111b8ad8800SGhennadi Procopciuc if (ret != 0) {
112b8ad8800SGhennadi Procopciuc return ret;
113b8ad8800SGhennadi Procopciuc }
114b8ad8800SGhennadi Procopciuc
115b8ad8800SGhennadi Procopciuc ret = clk_set_rate(S32CC_CLK_XBAR_2X, S32CC_XBAR_2X_FREQ, NULL);
116b8ad8800SGhennadi Procopciuc if (ret != 0) {
117b8ad8800SGhennadi Procopciuc return ret;
118b8ad8800SGhennadi Procopciuc }
119b8ad8800SGhennadi Procopciuc
120b8ad8800SGhennadi Procopciuc ret = clk_enable(S32CC_CLK_ARM_PLL_DFS1);
121b8ad8800SGhennadi Procopciuc if (ret != 0) {
122b8ad8800SGhennadi Procopciuc return ret;
123b8ad8800SGhennadi Procopciuc }
124b8ad8800SGhennadi Procopciuc
125b8ad8800SGhennadi Procopciuc ret = clk_enable(S32CC_CLK_XBAR_2X);
126b8ad8800SGhennadi Procopciuc if (ret != 0) {
127b8ad8800SGhennadi Procopciuc return ret;
128b8ad8800SGhennadi Procopciuc }
129b8ad8800SGhennadi Procopciuc
130b8ad8800SGhennadi Procopciuc return ret;
131b8ad8800SGhennadi Procopciuc }
132b8ad8800SGhennadi Procopciuc
enable_uart_clk(void)133e4462daeSGhennadi Procopciuc static int enable_uart_clk(void)
134e4462daeSGhennadi Procopciuc {
135e4462daeSGhennadi Procopciuc int ret;
136e4462daeSGhennadi Procopciuc
137e4462daeSGhennadi Procopciuc ret = clk_set_parent(S32CC_CLK_MC_CGM0_MUX8, S32CC_CLK_PERIPH_PLL_PHI3);
138e4462daeSGhennadi Procopciuc if (ret != 0) {
139e4462daeSGhennadi Procopciuc return ret;
140e4462daeSGhennadi Procopciuc }
141e4462daeSGhennadi Procopciuc
142e4462daeSGhennadi Procopciuc ret = clk_enable(S32CC_CLK_LINFLEX_BAUD);
143e4462daeSGhennadi Procopciuc if (ret != 0) {
144e4462daeSGhennadi Procopciuc return ret;
145e4462daeSGhennadi Procopciuc }
146e4462daeSGhennadi Procopciuc
147e4462daeSGhennadi Procopciuc return ret;
148e4462daeSGhennadi Procopciuc }
149e4462daeSGhennadi Procopciuc
setup_ddr_pll(void)15018c2b137SGhennadi Procopciuc static int setup_ddr_pll(void)
15118c2b137SGhennadi Procopciuc {
15218c2b137SGhennadi Procopciuc int ret;
15318c2b137SGhennadi Procopciuc
15418c2b137SGhennadi Procopciuc ret = clk_set_parent(S32CC_CLK_DDR_PLL_MUX, S32CC_CLK_FXOSC);
15518c2b137SGhennadi Procopciuc if (ret != 0) {
15618c2b137SGhennadi Procopciuc return ret;
15718c2b137SGhennadi Procopciuc }
15818c2b137SGhennadi Procopciuc
15918c2b137SGhennadi Procopciuc ret = clk_set_rate(S32CC_CLK_DDR_PLL_VCO, S32CC_DDR_PLL_VCO_FREQ, NULL);
16018c2b137SGhennadi Procopciuc if (ret != 0) {
16118c2b137SGhennadi Procopciuc return ret;
16218c2b137SGhennadi Procopciuc }
16318c2b137SGhennadi Procopciuc
16418c2b137SGhennadi Procopciuc ret = clk_set_rate(S32CC_CLK_DDR_PLL_PHI0, S32CC_DDR_PLL_PHI0_FREQ, NULL);
16518c2b137SGhennadi Procopciuc if (ret != 0) {
16618c2b137SGhennadi Procopciuc return ret;
16718c2b137SGhennadi Procopciuc }
16818c2b137SGhennadi Procopciuc
16918c2b137SGhennadi Procopciuc return ret;
17018c2b137SGhennadi Procopciuc }
17118c2b137SGhennadi Procopciuc
enable_ddr_clk(void)1728a4f840bSGhennadi Procopciuc static int enable_ddr_clk(void)
1738a4f840bSGhennadi Procopciuc {
1748a4f840bSGhennadi Procopciuc int ret;
1758a4f840bSGhennadi Procopciuc
1768a4f840bSGhennadi Procopciuc ret = clk_set_parent(S32CC_CLK_MC_CGM5_MUX0, S32CC_CLK_DDR_PLL_PHI0);
1778a4f840bSGhennadi Procopciuc if (ret != 0) {
1788a4f840bSGhennadi Procopciuc return ret;
1798a4f840bSGhennadi Procopciuc }
1808a4f840bSGhennadi Procopciuc
1818a4f840bSGhennadi Procopciuc ret = clk_enable(S32CC_CLK_DDR);
1828a4f840bSGhennadi Procopciuc if (ret != 0) {
1838a4f840bSGhennadi Procopciuc return ret;
1848a4f840bSGhennadi Procopciuc }
1858a4f840bSGhennadi Procopciuc
1868a4f840bSGhennadi Procopciuc return ret;
1878a4f840bSGhennadi Procopciuc }
1888a4f840bSGhennadi Procopciuc
enable_usdhc_clk(void)18947b3a825SGhennadi Procopciuc static int enable_usdhc_clk(void)
19047b3a825SGhennadi Procopciuc {
19147b3a825SGhennadi Procopciuc int ret;
19247b3a825SGhennadi Procopciuc
19347b3a825SGhennadi Procopciuc ret = clk_set_parent(S32CC_CLK_MC_CGM0_MUX14,
19447b3a825SGhennadi Procopciuc S32CC_CLK_PERIPH_PLL_DFS3);
19547b3a825SGhennadi Procopciuc if (ret != 0) {
19647b3a825SGhennadi Procopciuc return ret;
19747b3a825SGhennadi Procopciuc }
19847b3a825SGhennadi Procopciuc
19947b3a825SGhennadi Procopciuc ret = clk_set_rate(S32CC_CLK_PERIPH_PLL_DFS3,
20047b3a825SGhennadi Procopciuc S32CC_PERIPH_DFS_PHI3_FREQ, NULL);
20147b3a825SGhennadi Procopciuc if (ret != 0) {
20247b3a825SGhennadi Procopciuc return ret;
20347b3a825SGhennadi Procopciuc }
20447b3a825SGhennadi Procopciuc
20547b3a825SGhennadi Procopciuc ret = clk_set_rate(S32CC_CLK_USDHC, S32CC_USDHC_FREQ, NULL);
20647b3a825SGhennadi Procopciuc if (ret != 0) {
20747b3a825SGhennadi Procopciuc return ret;
20847b3a825SGhennadi Procopciuc }
20947b3a825SGhennadi Procopciuc
21047b3a825SGhennadi Procopciuc ret = clk_enable(S32CC_CLK_USDHC);
21147b3a825SGhennadi Procopciuc if (ret != 0) {
21247b3a825SGhennadi Procopciuc return ret;
21347b3a825SGhennadi Procopciuc }
21447b3a825SGhennadi Procopciuc
21547b3a825SGhennadi Procopciuc return ret;
21647b3a825SGhennadi Procopciuc }
21747b3a825SGhennadi Procopciuc
plat_deassert_ddr_reset(void)218*c0cbf5adSKhristine Andreea Barbulescu int plat_deassert_ddr_reset(void)
219*c0cbf5adSKhristine Andreea Barbulescu {
220*c0cbf5adSKhristine Andreea Barbulescu int err;
221*c0cbf5adSKhristine Andreea Barbulescu
222*c0cbf5adSKhristine Andreea Barbulescu clk_disable(S32CC_CLK_DDR);
223*c0cbf5adSKhristine Andreea Barbulescu
224*c0cbf5adSKhristine Andreea Barbulescu err = clk_set_parent(S32CC_CLK_MC_CGM5_MUX0, S32CC_CLK_FIRC);
225*c0cbf5adSKhristine Andreea Barbulescu if (err != 0) {
226*c0cbf5adSKhristine Andreea Barbulescu return err;
227*c0cbf5adSKhristine Andreea Barbulescu }
228*c0cbf5adSKhristine Andreea Barbulescu
229*c0cbf5adSKhristine Andreea Barbulescu err = clk_enable(S32CC_CLK_DDR);
230*c0cbf5adSKhristine Andreea Barbulescu if (err != 0) {
231*c0cbf5adSKhristine Andreea Barbulescu return err;
232*c0cbf5adSKhristine Andreea Barbulescu }
233*c0cbf5adSKhristine Andreea Barbulescu
234*c0cbf5adSKhristine Andreea Barbulescu err = mc_rgm_ddr_reset(MC_RGM_BASE_ADDR, S32CC_DDR_RESET_TIMEOUT_US);
235*c0cbf5adSKhristine Andreea Barbulescu if (err != 0) {
236*c0cbf5adSKhristine Andreea Barbulescu return err;
237*c0cbf5adSKhristine Andreea Barbulescu }
238*c0cbf5adSKhristine Andreea Barbulescu
239*c0cbf5adSKhristine Andreea Barbulescu return enable_ddr_clk();
240*c0cbf5adSKhristine Andreea Barbulescu }
241*c0cbf5adSKhristine Andreea Barbulescu
s32cc_init_core_clocks(void)24261b5ef21SGhennadi Procopciuc int s32cc_init_core_clocks(void)
243d3869455SGhennadi Procopciuc {
244d3869455SGhennadi Procopciuc int ret;
245d3869455SGhennadi Procopciuc
24661b5ef21SGhennadi Procopciuc ret = s32cc_clk_register_drv(false);
247514c7380SGhennadi Procopciuc if (ret != 0) {
248514c7380SGhennadi Procopciuc return ret;
249514c7380SGhennadi Procopciuc }
250d3869455SGhennadi Procopciuc
2515300040bSGhennadi Procopciuc ret = setup_fxosc();
252d3869455SGhennadi Procopciuc if (ret != 0) {
253d3869455SGhennadi Procopciuc return ret;
254d3869455SGhennadi Procopciuc }
255d3869455SGhennadi Procopciuc
2565300040bSGhennadi Procopciuc ret = setup_arm_pll();
2578653352aSGhennadi Procopciuc if (ret != 0) {
2588653352aSGhennadi Procopciuc return ret;
2598653352aSGhennadi Procopciuc }
2608653352aSGhennadi Procopciuc
261d3869455SGhennadi Procopciuc ret = enable_a53_clk();
262d3869455SGhennadi Procopciuc if (ret != 0) {
263d3869455SGhennadi Procopciuc return ret;
264d3869455SGhennadi Procopciuc }
265d3869455SGhennadi Procopciuc
266b8ad8800SGhennadi Procopciuc ret = enable_xbar_clk();
267b8ad8800SGhennadi Procopciuc if (ret != 0) {
268b8ad8800SGhennadi Procopciuc return ret;
269b8ad8800SGhennadi Procopciuc }
270b8ad8800SGhennadi Procopciuc
27161b5ef21SGhennadi Procopciuc return ret;
27261b5ef21SGhennadi Procopciuc }
27361b5ef21SGhennadi Procopciuc
s32cc_init_early_clks(void)27461b5ef21SGhennadi Procopciuc int s32cc_init_early_clks(void)
27561b5ef21SGhennadi Procopciuc {
27661b5ef21SGhennadi Procopciuc int ret;
27761b5ef21SGhennadi Procopciuc
27861b5ef21SGhennadi Procopciuc ret = s32cc_clk_register_drv(true);
27961b5ef21SGhennadi Procopciuc if (ret != 0) {
28061b5ef21SGhennadi Procopciuc return ret;
28161b5ef21SGhennadi Procopciuc }
28261b5ef21SGhennadi Procopciuc
2835300040bSGhennadi Procopciuc ret = setup_periph_pll();
2845300040bSGhennadi Procopciuc if (ret != 0) {
2855300040bSGhennadi Procopciuc return ret;
2865300040bSGhennadi Procopciuc }
2875300040bSGhennadi Procopciuc
288e4462daeSGhennadi Procopciuc ret = enable_uart_clk();
289e4462daeSGhennadi Procopciuc if (ret != 0) {
290e4462daeSGhennadi Procopciuc return ret;
291e4462daeSGhennadi Procopciuc }
292e4462daeSGhennadi Procopciuc
29318c2b137SGhennadi Procopciuc ret = setup_ddr_pll();
29418c2b137SGhennadi Procopciuc if (ret != 0) {
29518c2b137SGhennadi Procopciuc return ret;
29618c2b137SGhennadi Procopciuc }
29718c2b137SGhennadi Procopciuc
2988a4f840bSGhennadi Procopciuc ret = enable_ddr_clk();
2998a4f840bSGhennadi Procopciuc if (ret != 0) {
3008a4f840bSGhennadi Procopciuc return ret;
3018a4f840bSGhennadi Procopciuc }
3028a4f840bSGhennadi Procopciuc
30347b3a825SGhennadi Procopciuc ret = enable_usdhc_clk();
30447b3a825SGhennadi Procopciuc if (ret != 0) {
30547b3a825SGhennadi Procopciuc return ret;
30647b3a825SGhennadi Procopciuc }
30747b3a825SGhennadi Procopciuc
308d3869455SGhennadi Procopciuc return ret;
309d3869455SGhennadi Procopciuc }
310