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_OKAY(DT_NODELABEL(uart1))
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_OKAY(DT_NODELABEL(uart2))
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_OKAY(DT_NODELABEL(uart3))
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_OKAY(DT_NODELABEL(uart4))
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_OKAY(DT_NODELABEL(uart5))
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_OKAY(DT_NODELABEL(uart6))
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_OKAY(DT_NODELABEL(gpio1))
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_OKAY(DT_NODELABEL(gpio2))
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_OKAY(DT_NODELABEL(gpio3))
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_OKAY(DT_NODELABEL(gpio4))
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_OKAY(DT_NODELABEL(gpio5))
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_OKAY(DT_NODELABEL(gpio6))
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_OKAY(DT_NODELABEL(gpio7))
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_OKAY(DT_NODELABEL(epit1))
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_OKAY(DT_NODELABEL(epit2))
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_OKAY(DT_NODELABEL(i2c1))
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_OKAY(DT_NODELABEL(i2c2))
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_OKAY(DT_NODELABEL(i2c3))
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_OKAY(DT_NODELABEL(i2c4))
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_OKAY(DT_NODELABEL(pwm1))
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_OKAY(DT_NODELABEL(pwm2))
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_OKAY(DT_NODELABEL(pwm3))
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_OKAY(DT_NODELABEL(pwm4))
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_OKAY(DT_NODELABEL(pwm5))
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_OKAY(DT_NODELABEL(pwm6))
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_OKAY(DT_NODELABEL(pwm7))
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_OKAY(DT_NODELABEL(pwm8))
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_OKAY(DT_NODELABEL(adc1))
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_OKAY(DT_NODELABEL(adc2))
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 	}
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 	}
179 	/* Enable code bus cache, enable write buffer */
180 	LMEM_PCCCR = (LMEM_PCCCR_ENWRBUF_MASK | LMEM_PCCCR_ENCACHE_MASK);
181 	barrier_isync_fence_full();
182 	barrier_dsync_fence_full();
183 }
184 
185 /* Initialize clock. */
SOC_ClockInit(void)186 static void SOC_ClockInit(void)
187 {
188 	/* OSC/PLL is already initialized by Cortex-A9 core */
189 
190 	/* Enable IP bridge and IO mux clock */
191 	CCM_ControlGate(CCM, ccmCcgrGateIomuxIptClkIo, ccmClockNeededAll);
192 	CCM_ControlGate(CCM, ccmCcgrGateIpmux1Clk, ccmClockNeededAll);
193 	CCM_ControlGate(CCM, ccmCcgrGateIpmux2Clk, ccmClockNeededAll);
194 	CCM_ControlGate(CCM, ccmCcgrGateIpmux3Clk, ccmClockNeededAll);
195 
196 #ifdef CONFIG_UART_IMX
197 	/* Set UART clock is derived from OSC clock (24M) */
198 	CCM_SetRootMux(CCM, ccmRootUartClkSel, ccmRootmuxUartClkOsc24m);
199 
200 	/* Configure UART divider */
201 	CCM_SetRootDivider(CCM, ccmRootUartClkPodf, 0);
202 
203 	/* Enable UART clock */
204 	CCM_ControlGate(CCM, ccmCcgrGateUartClk, ccmClockNeededAll);
205 	CCM_ControlGate(CCM, ccmCcgrGateUartSerialClk, ccmClockNeededAll);
206 #endif /* CONFIG_UART_IMX */
207 
208 #ifdef CONFIG_COUNTER_IMX_EPIT
209 	/* Select EPIT clock is derived from OSC (24M) */
210 	CCM_SetRootMux(CCM, ccmRootPerclkClkSel, ccmRootmuxPerclkClkOsc24m);
211 
212 	/* Configure EPIT divider */
213 	CCM_SetRootDivider(CCM, ccmRootPerclkPodf, 0);
214 
215 	/* Enable EPIT clocks */
216 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(epit1))
217 	CCM_ControlGate(CCM, ccmCcgrGateEpit1Clk, ccmClockNeededAll);
218 #endif
219 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(epit2))
220 	CCM_ControlGate(CCM, ccmCcgrGateEpit2Clk, ccmClockNeededAll);
221 #endif
222 #endif /* CONFIG_COUNTER_IMX_EPIT */
223 
224 #ifdef CONFIG_I2C_IMX
225 	/* Select I2C clock is derived from OSC (24M) */
226 	CCM_SetRootMux(CCM, ccmRootPerclkClkSel, ccmRootmuxPerclkClkOsc24m);
227 
228 	/* Set relevant divider = 1. */
229 	CCM_SetRootDivider(CCM, ccmRootPerclkPodf, 0);
230 
231 	/* Enable I2C clock */
232 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(i2c1))
233 	CCM_ControlGate(CCM, ccmCcgrGateI2c1Serialclk, ccmClockNeededAll);
234 #endif
235 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(i2c2))
236 	CCM_ControlGate(CCM, ccmCcgrGateI2c2Serialclk, ccmClockNeededAll);
237 #endif
238 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(i2c3))
239 	CCM_ControlGate(CCM, ccmCcgrGateI2c3Serialclk, ccmClockNeededAll);
240 #endif
241 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(i2c4))
242 	CCM_ControlGate(CCM, ccmCcgrGateI2c4Serialclk, ccmClockNeededAll);
243 #endif
244 #endif /* CONFIG_I2C_IMX */
245 
246 #ifdef CONFIG_PWM_IMX
247 	/* Select PWM clock is derived from OSC (24M) */
248 	CCM_SetRootMux(CCM, ccmRootPerclkClkSel, ccmRootmuxPerclkClkOsc24m);
249 
250 	/* Set relevant divider = 1. */
251 	CCM_SetRootDivider(CCM, ccmRootPerclkPodf, 0);
252 
253 	/* Enable PWM clock */
254 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pwm1))
255 	CCM_ControlGate(CCM, ccmCcgrGatePwm1Clk, ccmClockNeededAll);
256 #endif
257 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pwm2))
258 	CCM_ControlGate(CCM, ccmCcgrGatePwm2Clk, ccmClockNeededAll);
259 #endif
260 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pwm3))
261 	CCM_ControlGate(CCM, ccmCcgrGatePwm3Clk, ccmClockNeededAll);
262 #endif
263 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pwm4))
264 	CCM_ControlGate(CCM, ccmCcgrGatePwm4Clk, ccmClockNeededAll);
265 #endif
266 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pwm5))
267 	CCM_ControlGate(CCM, ccmCcgrGatePwm5Clk, ccmClockNeededAll);
268 #endif
269 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pwm6))
270 	CCM_ControlGate(CCM, ccmCcgrGatePwm6Clk, ccmClockNeededAll);
271 #endif
272 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pwm7))
273 	CCM_ControlGate(CCM, ccmCcgrGatePwm7Clk, ccmClockNeededAll);
274 #endif
275 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pwm8))
276 	CCM_ControlGate(CCM, ccmCcgrGatePwm8Clk, ccmClockNeededAll);
277 #endif
278 #endif /* CONFIG_PWM_IMX */
279 }
280 
281 /**
282  *
283  * @brief Perform basic hardware initialization
284  *
285  * Initialize the interrupt controller device drivers.
286  * Also initialize the counter device driver, if required.
287  *
288  * @return 0
289  */
soc_early_init_hook(void)290 void soc_early_init_hook(void)
291 {
292 	/* Configure RDC */
293 	SOC_RdcInit();
294 
295 	/* Disable WDOG3 powerdown */
296 	WDOG_DisablePowerdown(WDOG3);
297 
298 	/* Initialize Cache */
299 	SOC_CacheInit();
300 
301 	/* Initialize clock */
302 	SOC_ClockInit();
303 }
304