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 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 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 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 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 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 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 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 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 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 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 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 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