1 /*
2 * Copyright (c) 2018, NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/init.h>
8 #include <zephyr/sys/barrier.h>
9 #include <soc.h>
10 #include <zephyr/dt-bindings/rdc/imx_rdc.h>
11 #include "wdog_imx.h"
12
13 #include <cmsis_core.h>
14
15 /* Initialize Resource Domain Controller. */
SOC_RdcInit(void)16 static void SOC_RdcInit(void)
17 {
18 /* Move M4 core to the configured RDC domain */
19 RDC_SetDomainID(RDC, rdcMdaM4, M4_DOMAIN_ID, false);
20
21 /* Set access to WDOG3 for M4 core */
22 RDC_SetPdapAccess(RDC, rdcPdapWdog3,
23 RDC_DOMAIN_PERM(M4_DOMAIN_ID, RDC_DOMAIN_PERM_RW),
24 false, false);
25
26 #if DT_NODE_HAS_STATUS(DT_NODELABEL(uart1), okay)
27 /* Set access to UART_1 for M4 core */
28 RDC_SetPdapAccess(RDC, rdcPdapUart1, RDC_DT_VAL(uart1), false, false);
29 #endif
30 #if DT_NODE_HAS_STATUS(DT_NODELABEL(uart2), okay)
31 /* Set access to UART_2 for M4 core */
32 RDC_SetPdapAccess(RDC, rdcPdapUart2, RDC_DT_VAL(uart2), false, false);
33 #endif
34 #if DT_NODE_HAS_STATUS(DT_NODELABEL(uart3), okay)
35 /* Set access to UART_3 for M4 core */
36 RDC_SetPdapAccess(RDC, rdcPdapUart3, RDC_DT_VAL(uart3), false, false);
37 #endif
38 #if DT_NODE_HAS_STATUS(DT_NODELABEL(uart4), okay)
39 /* Set access to UART_4 for M4 core */
40 RDC_SetPdapAccess(RDC, rdcPdapUart4, RDC_DT_VAL(uart4), false, false);
41 #endif
42 #if DT_NODE_HAS_STATUS(DT_NODELABEL(uart5), okay)
43 /* Set access to UART_5 for M4 core */
44 RDC_SetPdapAccess(RDC, rdcPdapUart5, RDC_DT_VAL(uart5), false, false);
45 #endif
46 #if DT_NODE_HAS_STATUS(DT_NODELABEL(uart6), okay)
47 /* Set access to UART_6 for M4 core */
48 RDC_SetPdapAccess(RDC, rdcPdapUart6, RDC_DT_VAL(uart6), false, false);
49 #endif
50 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
51 /* Set access to GPIO_1 for M4 core */
52 RDC_SetPdapAccess(RDC, rdcPdapGpio1, RDC_DT_VAL(gpio1), false, false);
53 #endif
54 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio2), okay)
55 /* Set access to GPIO_2 for M4 core */
56 RDC_SetPdapAccess(RDC, rdcPdapGpio2, RDC_DT_VAL(gpio2), false, false);
57 #endif
58 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio3), okay)
59 /* Set access to GPIO_3 for M4 core */
60 RDC_SetPdapAccess(RDC, rdcPdapGpio3, RDC_DT_VAL(gpio3), false, false);
61 #endif
62 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio4), okay)
63 /* Set access to GPIO_4 for M4 core */
64 RDC_SetPdapAccess(RDC, rdcPdapGpio4, RDC_DT_VAL(gpio4), false, false);
65 #endif
66 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio5), okay)
67 /* Set access to GPIO_5 for M4 core */
68 RDC_SetPdapAccess(RDC, rdcPdapGpio5, RDC_DT_VAL(gpio5), false, false);
69 #endif
70 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio6), okay)
71 /* Set access to GPIO_6 for M4 core */
72 RDC_SetPdapAccess(RDC, rdcPdapGpio6, RDC_DT_VAL(gpio6), false, false);
73 #endif
74 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio7), okay)
75 /* Set access to GPIO_7 for M4 core */
76 RDC_SetPdapAccess(RDC, rdcPdapGpio7, RDC_DT_VAL(gpio7), false, false);
77 #endif
78
79 #ifdef CONFIG_IPM_IMX
80 /* Set access to MU B for M4 core */
81 RDC_SetPdapAccess(RDC, rdcPdapMuB, RDC_DT_VAL(mub), false, false);
82 #endif /* CONFIG_IPM_IMX */
83
84 #if DT_NODE_HAS_STATUS(DT_NODELABEL(epit1), okay)
85 /* Set access to EPIT_1 for M4 core */
86 RDC_SetPdapAccess(RDC, rdcPdapEpit1, RDC_DT_VAL(epit1), false, false);
87 #endif
88 #if DT_NODE_HAS_STATUS(DT_NODELABEL(epit2), okay)
89 /* Set access to EPIT_2 for M4 core */
90 RDC_SetPdapAccess(RDC, rdcPdapEpit2, RDC_DT_VAL(epit2), false, false);
91 #endif
92
93 #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay)
94 /* Set access to I2C-1 for M4 core */
95 RDC_SetPdapAccess(RDC, rdcPdapI2c1, RDC_DT_VAL(i2c1), false, false);
96 #endif
97 #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c2), okay)
98 /* Set access to I2C-2 for M4 core */
99 RDC_SetPdapAccess(RDC, rdcPdapI2c2, RDC_DT_VAL(i2c2), false, false);
100 #endif
101 #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c3), okay)
102 /* Set access to I2C-3 for M4 core */
103 RDC_SetPdapAccess(RDC, rdcPdapI2c3, RDC_DT_VAL(i2c3), false, false);
104 #endif
105 #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c4), okay)
106 /* Set access to I2C-4 for M4 core */
107 RDC_SetPdapAccess(RDC, rdcPdapI2c4, RDC_DT_VAL(i2c4), false, false);
108 #endif
109
110 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm1), okay)
111 /* Set access to PWM-1 for M4 core */
112 RDC_SetPdapAccess(RDC, rdcPdapPwm1, RDC_DT_VAL(pwm1), false, false);
113 #endif
114 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm2), okay)
115 /* Set access to PWM-2 for M4 core */
116 RDC_SetPdapAccess(RDC, rdcPdapPwm2, RDC_DT_VAL(pwm2), false, false);
117 #endif
118 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm3), okay)
119 /* Set access to PWM-3 for M4 core */
120 RDC_SetPdapAccess(RDC, rdcPdapPwm3, RDC_DT_VAL(pwm3), false, false);
121 #endif
122 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm4), okay)
123 /* Set access to PWM-4 for M4 core */
124 RDC_SetPdapAccess(RDC, rdcPdapPwm4, RDC_DT_VAL(pwm4), false, false);
125 #endif
126 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm5), okay)
127 /* Set access to PWM-5 for M4 core */
128 RDC_SetPdapAccess(RDC, rdcPdapPwm5, RDC_DT_VAL(pwm5), false, false);
129 #endif
130 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm6), okay)
131 /* Set access to PWM-6 for M4 core */
132 RDC_SetPdapAccess(RDC, rdcPdapPwm6, RDC_DT_VAL(pwm6), false, false);
133 #endif
134 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm7), okay)
135 /* Set access to PWM-7 for M4 core */
136 RDC_SetPdapAccess(RDC, rdcPdapPwm7, RDC_DT_VAL(pwm7), false, false);
137 #endif
138 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm8), okay)
139 /* Set access to PWM-8 for M4 core */
140 RDC_SetPdapAccess(RDC, rdcPdapPwm8, RDC_DT_VAL(pwm8), false, false);
141 #endif
142 #if DT_NODE_HAS_STATUS(DT_NODELABEL(adc1), okay)
143 /* Set access to ADC-1 for M4 core */
144 RDC_SetPdapAccess(RDC, rdcPdapAdc1, RDC_DT_VAL(adc1), false, false);
145 #endif
146 #if DT_NODE_HAS_STATUS(DT_NODELABEL(adc2), okay)
147 /* Set access to ADC-2 for M4 core */
148 RDC_SetPdapAccess(RDC, rdcPdapAdc2, RDC_DT_VAL(adc2), false, false);
149 #endif
150 }
151
152 /* Initialize cache. */
SOC_CacheInit(void)153 static void SOC_CacheInit(void)
154 {
155 /* Enable System Bus Cache */
156 /* set command to invalidate all ways and write GO bit
157 * to initiate command
158 */
159 LMEM_PSCCR = LMEM_PSCCR_INVW1_MASK | LMEM_PSCCR_INVW0_MASK;
160 LMEM_PSCCR |= LMEM_PSCCR_GO_MASK;
161 /* Wait until the command completes */
162 while (LMEM_PSCCR & LMEM_PSCCR_GO_MASK)
163 ;
164 /* Enable system bus cache, enable write buffer */
165 LMEM_PSCCR = (LMEM_PSCCR_ENWRBUF_MASK | LMEM_PSCCR_ENCACHE_MASK);
166 barrier_isync_fence_full();
167
168 /* Enable Code Bus Cache */
169 /* set command to invalidate all ways and write GO bit
170 * to initiate command
171 */
172 LMEM_PCCCR = LMEM_PCCCR_INVW1_MASK | LMEM_PCCCR_INVW0_MASK;
173 LMEM_PCCCR |= LMEM_PCCCR_GO_MASK;
174 /* Wait until the command completes */
175 while (LMEM_PCCCR & LMEM_PCCCR_GO_MASK)
176 ;
177 /* Enable code bus cache, enable write buffer */
178 LMEM_PCCCR = (LMEM_PCCCR_ENWRBUF_MASK | LMEM_PCCCR_ENCACHE_MASK);
179 barrier_isync_fence_full();
180 barrier_dsync_fence_full();
181 }
182
183 /* Initialize clock. */
SOC_ClockInit(void)184 static void SOC_ClockInit(void)
185 {
186 /* OSC/PLL is already initialized by Cortex-A9 core */
187
188 /* Enable IP bridge and IO mux clock */
189 CCM_ControlGate(CCM, ccmCcgrGateIomuxIptClkIo, ccmClockNeededAll);
190 CCM_ControlGate(CCM, ccmCcgrGateIpmux1Clk, ccmClockNeededAll);
191 CCM_ControlGate(CCM, ccmCcgrGateIpmux2Clk, ccmClockNeededAll);
192 CCM_ControlGate(CCM, ccmCcgrGateIpmux3Clk, ccmClockNeededAll);
193
194 #ifdef CONFIG_UART_IMX
195 /* Set UART clock is derived from OSC clock (24M) */
196 CCM_SetRootMux(CCM, ccmRootUartClkSel, ccmRootmuxUartClkOsc24m);
197
198 /* Configure UART divider */
199 CCM_SetRootDivider(CCM, ccmRootUartClkPodf, 0);
200
201 /* Enable UART clock */
202 CCM_ControlGate(CCM, ccmCcgrGateUartClk, ccmClockNeededAll);
203 CCM_ControlGate(CCM, ccmCcgrGateUartSerialClk, ccmClockNeededAll);
204 #endif /* CONFIG_UART_IMX */
205
206 #ifdef CONFIG_COUNTER_IMX_EPIT
207 /* Select EPIT clock is derived from OSC (24M) */
208 CCM_SetRootMux(CCM, ccmRootPerclkClkSel, ccmRootmuxPerclkClkOsc24m);
209
210 /* Configure EPIT divider */
211 CCM_SetRootDivider(CCM, ccmRootPerclkPodf, 0);
212
213 /* Enable EPIT clocks */
214 #if DT_NODE_HAS_STATUS(DT_NODELABEL(epit1), okay)
215 CCM_ControlGate(CCM, ccmCcgrGateEpit1Clk, ccmClockNeededAll);
216 #endif
217 #if DT_NODE_HAS_STATUS(DT_NODELABEL(epit2), okay)
218 CCM_ControlGate(CCM, ccmCcgrGateEpit2Clk, ccmClockNeededAll);
219 #endif
220 #endif /* CONFIG_COUNTER_IMX_EPIT */
221
222 #ifdef CONFIG_I2C_IMX
223 /* Select I2C clock is derived from OSC (24M) */
224 CCM_SetRootMux(CCM, ccmRootPerclkClkSel, ccmRootmuxPerclkClkOsc24m);
225
226 /* Set relevant divider = 1. */
227 CCM_SetRootDivider(CCM, ccmRootPerclkPodf, 0);
228
229 /* Enable I2C clock */
230 #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay)
231 CCM_ControlGate(CCM, ccmCcgrGateI2c1Serialclk, ccmClockNeededAll);
232 #endif
233 #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c2), okay)
234 CCM_ControlGate(CCM, ccmCcgrGateI2c2Serialclk, ccmClockNeededAll);
235 #endif
236 #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c3), okay)
237 CCM_ControlGate(CCM, ccmCcgrGateI2c3Serialclk, ccmClockNeededAll);
238 #endif
239 #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c4), okay)
240 CCM_ControlGate(CCM, ccmCcgrGateI2c4Serialclk, ccmClockNeededAll);
241 #endif
242 #endif /* CONFIG_I2C_IMX */
243
244 #ifdef CONFIG_PWM_IMX
245 /* Select PWM clock is derived from OSC (24M) */
246 CCM_SetRootMux(CCM, ccmRootPerclkClkSel, ccmRootmuxPerclkClkOsc24m);
247
248 /* Set relevant divider = 1. */
249 CCM_SetRootDivider(CCM, ccmRootPerclkPodf, 0);
250
251 /* Enable PWM clock */
252 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm1), okay)
253 CCM_ControlGate(CCM, ccmCcgrGatePwm1Clk, ccmClockNeededAll);
254 #endif
255 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm2), okay)
256 CCM_ControlGate(CCM, ccmCcgrGatePwm2Clk, ccmClockNeededAll);
257 #endif
258 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm3), okay)
259 CCM_ControlGate(CCM, ccmCcgrGatePwm3Clk, ccmClockNeededAll);
260 #endif
261 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm4), okay)
262 CCM_ControlGate(CCM, ccmCcgrGatePwm4Clk, ccmClockNeededAll);
263 #endif
264 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm5), okay)
265 CCM_ControlGate(CCM, ccmCcgrGatePwm5Clk, ccmClockNeededAll);
266 #endif
267 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm6), okay)
268 CCM_ControlGate(CCM, ccmCcgrGatePwm6Clk, ccmClockNeededAll);
269 #endif
270 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm7), okay)
271 CCM_ControlGate(CCM, ccmCcgrGatePwm7Clk, ccmClockNeededAll);
272 #endif
273 #if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm8), okay)
274 CCM_ControlGate(CCM, ccmCcgrGatePwm8Clk, ccmClockNeededAll);
275 #endif
276 #endif /* CONFIG_PWM_IMX */
277 }
278
279 /**
280 *
281 * @brief Perform basic hardware initialization
282 *
283 * Initialize the interrupt controller device drivers.
284 * Also initialize the counter device driver, if required.
285 *
286 * @return 0
287 */
mcimx6x_m4_init(void)288 static int mcimx6x_m4_init(void)
289 {
290 /* Configure RDC */
291 SOC_RdcInit();
292
293 /* Disable WDOG3 powerdown */
294 WDOG_DisablePowerdown(WDOG3);
295
296 /* Initialize Cache */
297 SOC_CacheInit();
298
299 /* Initialize clock */
300 SOC_ClockInit();
301
302 return 0;
303 }
304
305 SYS_INIT(mcimx6x_m4_init, PRE_KERNEL_1, 0);
306