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