1 /*
2  * Copyright (c) 2020, Manivannan Sadhasivam <mani@kernel.org>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/device.h>
8 #include <fsl_clock.h>
9 #include <fsl_common.h>
10 #include <fsl_rdc.h>
11 #include <zephyr/init.h>
12 #include <zephyr/kernel.h>
13 #include <soc.h>
14 
15 #include <zephyr/dt-bindings/rdc/imx_rdc.h>
16 
17 /* OSC/PLL is already initialized by ROM and Cortex-A53 (u-boot) */
SOC_RdcInit(void)18 static void SOC_RdcInit(void)
19 {
20 	/* Move M4 core to specific RDC domain 1 */
21 	rdc_domain_assignment_t assignment = {0};
22 
23 	assignment.domainId = M4_DOMAIN_ID;
24 	RDC_SetMasterDomainAssignment(RDC, kRDC_Master_M4, &assignment);
25 
26 	/*
27 	 * The M4 core is running at domain 1, enable clock gate for
28 	 * Iomux to run at domain 1.
29 	 */
30 	CLOCK_EnableClock(kCLOCK_Iomux);
31 	CLOCK_EnableClock(kCLOCK_Ipmux1);
32 	CLOCK_EnableClock(kCLOCK_Ipmux2);
33 	CLOCK_EnableClock(kCLOCK_Ipmux3);
34 	CLOCK_EnableClock(kCLOCK_Ipmux4);
35 
36 	CLOCK_EnableClock(kCLOCK_Qspi);
37 
38 	/*
39 	 * The M4 core is running at domain 1, enable the PLL clock sources
40 	 * to domain 1.
41 	 */
42 	/* Enable SysPLL1 to Domain 1 */
43 	CLOCK_ControlGate(kCLOCK_SysPll1Gate, kCLOCK_ClockNeededAll);
44 	/* Enable SysPLL2 to Domain 1 */
45 	CLOCK_ControlGate(kCLOCK_SysPll2Gate, kCLOCK_ClockNeededAll);
46 	/* Enable SysPLL3 to Domain 1 */
47 	CLOCK_ControlGate(kCLOCK_SysPll3Gate, kCLOCK_ClockNeededAll);
48 	/* Enable AudioPLL1 to Domain 1 */
49 	CLOCK_ControlGate(kCLOCK_AudioPll1Gate, kCLOCK_ClockNeededAll);
50 	/* Enable AudioPLL2 to Domain 1 */
51 	CLOCK_ControlGate(kCLOCK_AudioPll2Gate, kCLOCK_ClockNeededAll);
52 	/* Enable VideoPLL1 to Domain 1 */
53 	CLOCK_ControlGate(kCLOCK_VideoPll1Gate, kCLOCK_ClockNeededAll);
54 }
55 
56 /* AUDIO PLL1 configuration */
57 static const ccm_analog_frac_pll_config_t g_audioPll1Config = {
58 	.refSel  = kANALOG_PllRefOsc24M, /* PLL reference OSC24M */
59 	.mainDiv = 655U,
60 	.dsm     = 23593U,
61 	.preDiv  = 5U,
62 	.postDiv = 2U, /* AUDIO PLL1 frequency  = 786432000HZ */
63 };
64 
65 /* AUDIO PLL2 configuration */
66 static const ccm_analog_frac_pll_config_t g_audioPll2Config = {
67 	.refSel  = kANALOG_PllRefOsc24M, /* PLL reference OSC24M */
68 	.mainDiv = 301U,
69 	.dsm     = 3670U,
70 	.preDiv  = 5U,
71 	.postDiv = 1U, /* AUDIO PLL2 frequency  = 722534399HZ */
72 };
73 
SOC_ClockInit(void)74 static void SOC_ClockInit(void)
75 {
76 	/*
77 	 * Switch AHB NOC root to 24M first in order to configure
78 	 * the SYSTEM PLL1
79 	 */
80 	CLOCK_SetRootMux(kCLOCK_RootAhb, kCLOCK_AhbRootmuxOsc24M);
81 
82 	/*
83 	 * Switch AXI M4 root to 24M first in order to configure
84 	 * the SYSTEM PLL2
85 	 */
86 	CLOCK_SetRootMux(kCLOCK_RootM4, kCLOCK_M4RootmuxOsc24M);
87 
88 	/* Init AUDIO PLL1 to run at 786432000HZ */
89 	CLOCK_InitAudioPll1(&g_audioPll1Config);
90 	/* Init AUDIO PLL2 to run at 722534399HZ */
91 	CLOCK_InitAudioPll2(&g_audioPll2Config);
92 
93 	CLOCK_SetRootDivider(kCLOCK_RootM4, 1U, 2U);
94 	/* Switch cortex-m4 to SYSTEM PLL1 */
95 	CLOCK_SetRootMux(kCLOCK_RootM4, kCLOCK_M4RootmuxSysPll1);
96 
97 	CLOCK_SetRootDivider(kCLOCK_RootAhb, 1U, 1U);
98 	/* Switch AHB to SYSTEM PLL1 DIV6 = 133MHZ */
99 	CLOCK_SetRootMux(kCLOCK_RootAhb, kCLOCK_AhbRootmuxSysPll1Div6);
100 
101 	/* Set root clock to 800MHZ/ 2= 400MHZ */
102 	CLOCK_SetRootDivider(kCLOCK_RootAudioAhb, 1U, 2U);
103 	/* switch AUDIO AHB to SYSTEM PLL1 */
104 	CLOCK_SetRootMux(kCLOCK_RootAudioAhb, kCLOCK_AudioAhbRootmuxSysPll1);
105 
106 #if defined(CONFIG_UART_MCUX_IUART)
107 #if DT_NODE_HAS_STATUS(DT_NODELABEL(uart1), okay)
108 	/* Set UART source to SysPLL1 Div10 80MHZ */
109 	CLOCK_SetRootMux(kCLOCK_RootUart1, kCLOCK_UartRootmuxSysPll1Div10);
110 	/* Set root clock to 80MHZ/ 1= 80MHZ */
111 	CLOCK_SetRootDivider(kCLOCK_RootUart1, 1U, 1U);
112 #endif
113 #if DT_NODE_HAS_STATUS(DT_NODELABEL(uart2), okay)
114 	/* Set UART source to SysPLL1 Div10 80MHZ */
115 	CLOCK_SetRootMux(kCLOCK_RootUart2, kCLOCK_UartRootmuxSysPll1Div10);
116 	/* Set root clock to 80MHZ/ 1= 80MHZ */
117 	CLOCK_SetRootDivider(kCLOCK_RootUart2, 1U, 1U);
118 #endif
119 #if DT_NODE_HAS_STATUS(DT_NODELABEL(uart3), okay)
120 	/* Set UART source to SysPLL1 Div10 80MHZ */
121 	CLOCK_SetRootMux(kCLOCK_RootUart3, kCLOCK_UartRootmuxSysPll1Div10);
122 	/* Set root clock to 80MHZ/ 1= 80MHZ */
123 	CLOCK_SetRootDivider(kCLOCK_RootUart3, 1U, 1U);
124 #endif
125 #if DT_NODE_HAS_STATUS(DT_NODELABEL(uart4), okay)
126 	/* Set UART source to SysPLL1 Div10 80MHZ */
127 	CLOCK_SetRootMux(kCLOCK_RootUart4, kCLOCK_UartRootmuxSysPll1Div10);
128 	/* Set root clock to 80MHZ/ 1= 80MHZ */
129 	CLOCK_SetRootDivider(kCLOCK_RootUart4, 1U, 1U);
130 #endif
131 #endif
132 
133 	/* Enable RDC clock */
134 	CLOCK_EnableClock(kCLOCK_Rdc);
135 
136 	/*
137 	 * The purpose to enable the following modules clock is to make
138 	 * sure the M4 core could work normally when A53 core
139 	 * enters the low power state
140 	 */
141 	CLOCK_EnableClock(kCLOCK_Sim_display);
142 	CLOCK_EnableClock(kCLOCK_Sim_m);
143 	CLOCK_EnableClock(kCLOCK_Sim_main);
144 	CLOCK_EnableClock(kCLOCK_Sim_s);
145 	CLOCK_EnableClock(kCLOCK_Sim_wakeup);
146 	CLOCK_EnableClock(kCLOCK_Debug);
147 	CLOCK_EnableClock(kCLOCK_Dram);
148 	CLOCK_EnableClock(kCLOCK_Sec_Debug);
149 }
150 
nxp_mimx8mm6_init(void)151 static int nxp_mimx8mm6_init(void)
152 {
153 
154 	/* SoC specific RDC settings */
155 	SOC_RdcInit();
156 
157 	/* SoC specific Clock settings */
158 	SOC_ClockInit();
159 
160 	return 0;
161 }
162 
163 SYS_INIT(nxp_mimx8mm6_init, PRE_KERNEL_1, 0);
164