diff options
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers')
9 files changed, 1738 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/driver_clock.cmake b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/driver_clock.cmake new file mode 100644 index 000000000..154d6a23a --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/driver_clock.cmake | |||
@@ -0,0 +1,16 @@ | |||
1 | if(NOT DRIVER_CLOCK_INCLUDED) | ||
2 | |||
3 | set(DRIVER_CLOCK_INCLUDED true CACHE BOOL "driver_clock component is included.") | ||
4 | |||
5 | target_sources(${MCUX_SDK_PROJECT_NAME} PRIVATE | ||
6 | ${CMAKE_CURRENT_LIST_DIR}/fsl_clock.c | ||
7 | ) | ||
8 | |||
9 | target_include_directories(${MCUX_SDK_PROJECT_NAME} PRIVATE | ||
10 | ${CMAKE_CURRENT_LIST_DIR}/. | ||
11 | ) | ||
12 | |||
13 | |||
14 | include(driver_common) | ||
15 | |||
16 | endif() \ No newline at end of file | ||
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/driver_memory.cmake b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/driver_memory.cmake new file mode 100644 index 000000000..f2142de90 --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/driver_memory.cmake | |||
@@ -0,0 +1,15 @@ | |||
1 | if(NOT DRIVER_MEMORY_INCLUDED) | ||
2 | |||
3 | set(DRIVER_MEMORY_INCLUDED true CACHE BOOL "driver_memory component is included.") | ||
4 | |||
5 | target_sources(${MCUX_SDK_PROJECT_NAME} PRIVATE | ||
6 | ) | ||
7 | |||
8 | target_include_directories(${MCUX_SDK_PROJECT_NAME} PRIVATE | ||
9 | ${CMAKE_CURRENT_LIST_DIR}/. | ||
10 | ) | ||
11 | |||
12 | |||
13 | include(driver_common) | ||
14 | |||
15 | endif() \ No newline at end of file | ||
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/driver_reset.cmake b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/driver_reset.cmake new file mode 100644 index 000000000..989530f6f --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/driver_reset.cmake | |||
@@ -0,0 +1,14 @@ | |||
1 | if(NOT DRIVER_RESET_INCLUDED) | ||
2 | |||
3 | set(DRIVER_RESET_INCLUDED true CACHE BOOL "driver_reset component is included.") | ||
4 | |||
5 | target_sources(${MCUX_SDK_PROJECT_NAME} PRIVATE | ||
6 | ) | ||
7 | |||
8 | target_include_directories(${MCUX_SDK_PROJECT_NAME} PRIVATE | ||
9 | ${CMAKE_CURRENT_LIST_DIR}/. | ||
10 | ) | ||
11 | |||
12 | |||
13 | |||
14 | endif() \ No newline at end of file | ||
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/driver_sc_event.cmake b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/driver_sc_event.cmake new file mode 100644 index 000000000..a1ce1f2af --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/driver_sc_event.cmake | |||
@@ -0,0 +1,18 @@ | |||
1 | if(NOT DRIVER_SC_EVENT_INCLUDED) | ||
2 | |||
3 | set(DRIVER_SC_EVENT_INCLUDED true CACHE BOOL "driver_sc_event component is included.") | ||
4 | |||
5 | target_sources(${MCUX_SDK_PROJECT_NAME} PRIVATE | ||
6 | ${CMAKE_CURRENT_LIST_DIR}/fsl_sc_event.c | ||
7 | ) | ||
8 | |||
9 | target_include_directories(${MCUX_SDK_PROJECT_NAME} PRIVATE | ||
10 | ${CMAKE_CURRENT_LIST_DIR}/. | ||
11 | ) | ||
12 | |||
13 | |||
14 | include(driver_common) | ||
15 | include(driver_scfw_api) | ||
16 | include(driver_mu) | ||
17 | |||
18 | endif() \ No newline at end of file | ||
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_clock.c new file mode 100644 index 000000000..bd9117091 --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_clock.c | |||
@@ -0,0 +1,377 @@ | |||
1 | /* | ||
2 | * Copyright 2017-2020 NXP | ||
3 | * | ||
4 | * SPDX-License-Identifier: BSD-3-Clause | ||
5 | */ | ||
6 | |||
7 | #include "fsl_clock.h" | ||
8 | |||
9 | /******************************************************************************* | ||
10 | * Definitions | ||
11 | ******************************************************************************/ | ||
12 | /* Component ID definition, used by tools. */ | ||
13 | #ifndef FSL_COMPONENT_ID | ||
14 | #define FSL_COMPONENT_ID "platform.drivers.clock" | ||
15 | #endif | ||
16 | /* LPCG register Bits Mask. LPCG register generally comes in four bit groups, a STOP, Reserved, [P|B]CG(SWEN), HWEN | ||
17 | * nibble. The HWEN bits are optional, but the allocations of the nibble always be on four bit boundaries. */ | ||
18 | #define LPCG_CLK_HWEN_MASK (0x11111111U) | ||
19 | #define LPCG_CLK_SWEN_MASK (0x22222222U) | ||
20 | #define LPCG_CLK_STOP_MASK (0x88888888U) | ||
21 | |||
22 | /******************************************************************************* | ||
23 | * Variables | ||
24 | ******************************************************************************/ | ||
25 | static sc_ipc_t ipcHandle; | ||
26 | |||
27 | /******************************************************************************* | ||
28 | * Prototypes | ||
29 | ******************************************************************************/ | ||
30 | |||
31 | /******************************************************************************* | ||
32 | * Code | ||
33 | ******************************************************************************/ | ||
34 | |||
35 | /*! | ||
36 | * brief Initialize Clock module. | ||
37 | * | ||
38 | * param ipc IPC handle for communication with SCU, see \ref sc_ipc_t. | ||
39 | */ | ||
40 | void CLOCK_Init(sc_ipc_t ipc) | ||
41 | { | ||
42 | ipcHandle = ipc; | ||
43 | } | ||
44 | |||
45 | /*! | ||
46 | * brief Deinitialize Clock module. | ||
47 | */ | ||
48 | void CLOCK_Deinit(void) | ||
49 | { | ||
50 | } | ||
51 | |||
52 | /*! | ||
53 | * brief Enable the clock for specific IP, with gate setting. | ||
54 | * | ||
55 | * param name Which clock to enable, see \ref clock_ip_name_t. | ||
56 | * param gate 0: clock always on, 1: HW auto clock gating. | ||
57 | * return true if success, false if failure. | ||
58 | */ | ||
59 | bool CLOCK_EnableClockExt(clock_ip_name_t name, uint32_t gate) | ||
60 | { | ||
61 | sc_err_t err; | ||
62 | |||
63 | err = sc_pm_clock_enable(ipcHandle, LPCG_TUPLE_RSRC(name), SC_PM_CLK_PER, true, (bool)gate); | ||
64 | |||
65 | /* Enable the Clock Gate control in LPCG */ | ||
66 | CLOCK_ConfigLPCG(name, true, (bool)gate); | ||
67 | |||
68 | if (err != SC_ERR_NONE) | ||
69 | { | ||
70 | return false; | ||
71 | } | ||
72 | else | ||
73 | { | ||
74 | return true; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | /*! | ||
79 | * brief Disable the clock for specific IP. | ||
80 | * | ||
81 | * param name Which clock to disable, see \ref clock_ip_name_t. | ||
82 | * return true for success, false for failure. | ||
83 | */ | ||
84 | bool CLOCK_DisableClock(clock_ip_name_t name) | ||
85 | { | ||
86 | sc_err_t err; | ||
87 | |||
88 | /* Disable the Clock Gate control in LPCG */ | ||
89 | CLOCK_ConfigLPCG(name, false, false); | ||
90 | |||
91 | err = sc_pm_clock_enable(ipcHandle, LPCG_TUPLE_RSRC(name), SC_PM_CLK_PER, false, false); | ||
92 | |||
93 | if (err != SC_ERR_NONE) | ||
94 | { | ||
95 | return false; | ||
96 | } | ||
97 | else | ||
98 | { | ||
99 | return true; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | /*! | ||
104 | * brief Set the clock frequency for specific IP module. | ||
105 | * | ||
106 | * This function sets the IP module clock frequency. | ||
107 | * | ||
108 | * param name Which peripheral to check, see \ref clock_ip_name_t. | ||
109 | * param freq Target clock frequency value in hertz. | ||
110 | * return the Real clock frequency value in hertz, or 0 if failed | ||
111 | */ | ||
112 | uint32_t CLOCK_SetIpFreq(clock_ip_name_t name, uint32_t freq) | ||
113 | { | ||
114 | uint32_t target = freq; | ||
115 | sc_err_t err; | ||
116 | |||
117 | err = sc_pm_set_clock_rate(ipcHandle, LPCG_TUPLE_RSRC(name), SC_PM_CLK_PER, &target); | ||
118 | if (err != SC_ERR_NONE) | ||
119 | { | ||
120 | return 0; | ||
121 | } | ||
122 | else | ||
123 | { | ||
124 | return target; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | /*! | ||
129 | * brief Get the clock frequency for a specific IP module. | ||
130 | * | ||
131 | * This function gets the IP module clock frequency. | ||
132 | * | ||
133 | * param name Which peripheral to get, see \ref clock_ip_name_t. | ||
134 | * return Clock frequency value in hertz, or 0 if failed | ||
135 | */ | ||
136 | uint32_t CLOCK_GetIpFreq(clock_ip_name_t name) | ||
137 | { | ||
138 | uint32_t freq; | ||
139 | sc_err_t err; | ||
140 | |||
141 | err = sc_pm_get_clock_rate(ipcHandle, LPCG_TUPLE_RSRC(name), SC_PM_CLK_PER, &freq); | ||
142 | if (err != SC_ERR_NONE) | ||
143 | { | ||
144 | return 0; | ||
145 | } | ||
146 | else | ||
147 | { | ||
148 | return freq; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | /*! | ||
153 | * brief Get the core clock or system clock frequency. | ||
154 | * | ||
155 | * return Clock frequency in Hz. | ||
156 | */ | ||
157 | uint32_t CLOCK_GetCoreSysClkFreq(void) | ||
158 | { | ||
159 | uint32_t freq; | ||
160 | sc_err_t err; | ||
161 | #if defined(MIMX8QM_CM4_CORE0) | ||
162 | err = sc_pm_get_clock_rate(ipcHandle, SC_R_M4_0_PID0, SC_PM_CLK_PER, &freq); | ||
163 | #elif defined(MIMX8QM_CM4_CORE1) | ||
164 | err = sc_pm_get_clock_rate(ipcHandle, SC_R_M4_1_PID0, SC_PM_CLK_PER, &freq); | ||
165 | #else | ||
166 | #error "Clock driver not support the core!" | ||
167 | #endif | ||
168 | if (err != SC_ERR_NONE) | ||
169 | { | ||
170 | freq = 0U; | ||
171 | } | ||
172 | |||
173 | return freq; | ||
174 | } | ||
175 | |||
176 | /*! | ||
177 | * brief Gets the clock frequency for a specific clock name. | ||
178 | * | ||
179 | * This function checks the current clock configurations and then calculates | ||
180 | * the clock frequency for a specific clock name defined in clock_name_t. | ||
181 | * | ||
182 | * param clockName Clock names defined in clock_name_t | ||
183 | * return Clock frequency value in hertz | ||
184 | */ | ||
185 | uint32_t CLOCK_GetFreq(clock_name_t name) | ||
186 | { | ||
187 | uint32_t freq; | ||
188 | |||
189 | switch (name) | ||
190 | { | ||
191 | case kCLOCK_CONECTIVITY_AhbClk: | ||
192 | freq = 167000000U; /* The CONNECTIVITY SS AHB clock is fixed to 166MHZ */ | ||
193 | break; | ||
194 | case kCLOCK_CoreSysClk: | ||
195 | freq = CLOCK_GetCoreSysClkFreq(); | ||
196 | break; | ||
197 | default: | ||
198 | freq = 0U; | ||
199 | break; | ||
200 | } | ||
201 | |||
202 | return freq; | ||
203 | } | ||
204 | |||
205 | /*! | ||
206 | * brief Set LPCG gate for specific LPCG. | ||
207 | * | ||
208 | * param regBase LPCG register base address. | ||
209 | * param swGate Software clock gating. 0: clock is gated; 1: clock is enabled | ||
210 | * param hwGate Hardware auto gating. 0: disable the HW clock gate control; 1: HW clock gating is enabled | ||
211 | * param bitsMask The available bits in LPCG register. Each bit indicate the corresponding bit is available or not. | ||
212 | */ | ||
213 | void CLOCK_SetLpcgGate(volatile uint32_t *regBase, bool swGate, bool hwGate, uint32_t bitsMask) | ||
214 | { | ||
215 | if (regBase != NULL) | ||
216 | { | ||
217 | if (swGate) | ||
218 | { | ||
219 | *regBase |= bitsMask & LPCG_CLK_SWEN_MASK; | ||
220 | } | ||
221 | else | ||
222 | { | ||
223 | *regBase &= ~(bitsMask & LPCG_CLK_SWEN_MASK); | ||
224 | } | ||
225 | |||
226 | if (hwGate) | ||
227 | { | ||
228 | *regBase |= bitsMask & LPCG_CLK_HWEN_MASK; | ||
229 | } | ||
230 | else | ||
231 | { | ||
232 | *regBase &= ~(bitsMask & LPCG_CLK_HWEN_MASK); | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | |||
237 | /*! | ||
238 | * brief Config the LPCG cell for specific IP. | ||
239 | * | ||
240 | * param name Which clock to enable, see \ref clock_ip_name_t. | ||
241 | * param swGate Software clock gating. 0: clock is gated; 1: clock is enabled | ||
242 | * param swGate Hardware auto gating. 0: disable the HW clock gate control; 1: HW clock gating is enabled | ||
243 | */ | ||
244 | void CLOCK_ConfigLPCG(clock_ip_name_t name, bool swGate, bool hwGate) | ||
245 | { | ||
246 | volatile uint32_t *regBase; | ||
247 | |||
248 | regBase = LPCG_TUPLE_REG_BASE(name); | ||
249 | |||
250 | /* Return if LPCG Cell is not available. */ | ||
251 | if (regBase == NULL) | ||
252 | { | ||
253 | return; | ||
254 | } | ||
255 | |||
256 | /* Config the LPCG. LPCG Cells have different configurations per each clock target. */ | ||
257 | switch (name) | ||
258 | { | ||
259 | /* LPCG cell avalialbe bits field mask 0xBBAAAB, 0xBBAAAB (2 32-bits LPCG registers). */ | ||
260 | case kCLOCK_CONNECTIVITY_Enet0: | ||
261 | case kCLOCK_CONNECTIVITY_Enet1: | ||
262 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xBBAAABU); | ||
263 | CLOCK_SetLpcgGate(®Base[1U], swGate, hwGate, 0xAU); | ||
264 | break; | ||
265 | |||
266 | /* LPCG cell avalialbe bits field mask 0xA000B.*/ | ||
267 | case kCLOCK_AUDIO_Esai0: | ||
268 | case kCLOCK_AUDIO_Esai1: | ||
269 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xA000BU); | ||
270 | break; | ||
271 | |||
272 | /* LPCG cell avalialbe bits field mask 0xAA000B.*/ | ||
273 | case kCLOCK_AUDIO_Gpt0: | ||
274 | case kCLOCK_AUDIO_Gpt1: | ||
275 | case kCLOCK_AUDIO_Gpt2: | ||
276 | case kCLOCK_AUDIO_Gpt3: | ||
277 | case kCLOCK_AUDIO_Gpt4: | ||
278 | case kCLOCK_AUDIO_Gpt5: | ||
279 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xAA000BU); | ||
280 | break; | ||
281 | |||
282 | /* LPCG cell avalialbe bits field mask 0xAAB0AAB.*/ | ||
283 | case kCLOCK_LSIO_Gpt0: | ||
284 | case kCLOCK_LSIO_Gpt1: | ||
285 | case kCLOCK_LSIO_Gpt2: | ||
286 | case kCLOCK_LSIO_Gpt3: | ||
287 | case kCLOCK_LSIO_Gpt4: | ||
288 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xAAB0AABU); | ||
289 | break; | ||
290 | |||
291 | /* LPCG cell avalialbe bits field mask 0xB0000.*/ | ||
292 | case kCLOCK_HSIO_Gpio: | ||
293 | case kCLOCK_LSIO_Gpio0: | ||
294 | case kCLOCK_LSIO_Gpio1: | ||
295 | case kCLOCK_LSIO_Gpio2: | ||
296 | case kCLOCK_LSIO_Gpio3: | ||
297 | case kCLOCK_LSIO_Gpio4: | ||
298 | case kCLOCK_LSIO_Gpio5: | ||
299 | case kCLOCK_LSIO_Gpio6: | ||
300 | case kCLOCK_LSIO_Gpio7: | ||
301 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xB0000U); | ||
302 | break; | ||
303 | /* LPCG cell avalialbe bits field mask 0xB000A. */ | ||
304 | case kCLOCK_DMA_Lpadc0: | ||
305 | case kCLOCK_DMA_Lpadc1: | ||
306 | case kCLOCK_LSIO_Mu5A: | ||
307 | case kCLOCK_LSIO_Mu6A: | ||
308 | case kCLOCK_LSIO_Mu7A: | ||
309 | case kCLOCK_LSIO_Mu8A: | ||
310 | case kCLOCK_LSIO_Mu9A: | ||
311 | case kCLOCK_LSIO_Mu10A: | ||
312 | case kCLOCK_LSIO_Mu11A: | ||
313 | case kCLOCK_LSIO_Mu12A: | ||
314 | case kCLOCK_LSIO_Mu13A: | ||
315 | case kCLOCK_LSIO_Mu5B: | ||
316 | case kCLOCK_LSIO_Mu6B: | ||
317 | case kCLOCK_LSIO_Mu7B: | ||
318 | case kCLOCK_LSIO_Mu8B: | ||
319 | case kCLOCK_LSIO_Mu9B: | ||
320 | case kCLOCK_LSIO_Mu10B: | ||
321 | case kCLOCK_LSIO_Mu11B: | ||
322 | case kCLOCK_LSIO_Mu12B: | ||
323 | case kCLOCK_LSIO_Mu13B: | ||
324 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xB000AU); | ||
325 | break; | ||
326 | |||
327 | /* LPCG cell avalialbe bits field mask 0xB000B. */ | ||
328 | case kCLOCK_DMA_Lpspi0: | ||
329 | case kCLOCK_DMA_Lpspi1: | ||
330 | case kCLOCK_DMA_Lpspi2: | ||
331 | case kCLOCK_DMA_Lpspi3: | ||
332 | case kCLOCK_DMA_Lpuart0: | ||
333 | case kCLOCK_DMA_Lpuart1: | ||
334 | case kCLOCK_DMA_Lpuart2: | ||
335 | case kCLOCK_DMA_Lpuart3: | ||
336 | case kCLOCK_DMA_Lpuart4: | ||
337 | case kCLOCK_DMA_Lpi2c0: | ||
338 | case kCLOCK_DMA_Lpi2c1: | ||
339 | case kCLOCK_DMA_Lpi2c2: | ||
340 | case kCLOCK_DMA_Lpi2c3: | ||
341 | case kCLOCK_DMA_Lpi2c4: | ||
342 | case kCLOCK_DMA_Ftm0: | ||
343 | case kCLOCK_DMA_Ftm1: | ||
344 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xB000BU); | ||
345 | break; | ||
346 | |||
347 | /* LPCG cell avalialbe bits field mask 0xA0B0A.*/ | ||
348 | case kCLOCK_AUDIO_Sai0: | ||
349 | case kCLOCK_AUDIO_Sai1: | ||
350 | case kCLOCK_AUDIO_Sai2: | ||
351 | case kCLOCK_AUDIO_Sai3: | ||
352 | case kCLOCK_AUDIO_Sai4: | ||
353 | case kCLOCK_AUDIO_Sai5: | ||
354 | case kCLOCK_AUDIO_Sai6: | ||
355 | case kCLOCK_AUDIO_Sai7: | ||
356 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xA0B0AU); | ||
357 | break; | ||
358 | |||
359 | /* LPCG cell avalialbe bits field mask 0xBB000B.*/ | ||
360 | case kCLOCK_DMA_Can0: | ||
361 | case kCLOCK_DMA_Can1: | ||
362 | case kCLOCK_DMA_Can2: | ||
363 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xBB000B); | ||
364 | break; | ||
365 | |||
366 | /* LPCG cell avalialbe bits field mask 0xBAA000A.*/ | ||
367 | case kCLOCK_LSIO_Flexspi0: | ||
368 | case kCLOCK_LSIO_Flexspi1: | ||
369 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xBAA000A); | ||
370 | break; | ||
371 | |||
372 | /* LPCG cell is not avaliable or is not supported by this function. */ | ||
373 | default: | ||
374 | /* Add comments to avoid the violation of MISRA C-2012 rule 16.4. */ | ||
375 | break; | ||
376 | } | ||
377 | } | ||
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_clock.h b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_clock.h new file mode 100644 index 000000000..a49264442 --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_clock.h | |||
@@ -0,0 +1,517 @@ | |||
1 | /* | ||
2 | * Copyright 2017-2020 NXP | ||
3 | * | ||
4 | * SPDX-License-Identifier: BSD-3-Clause | ||
5 | */ | ||
6 | |||
7 | #ifndef _FSL_CLOCK_H_ | ||
8 | #define _FSL_CLOCK_H_ | ||
9 | |||
10 | #include "fsl_device_registers.h" | ||
11 | #include <stdint.h> | ||
12 | #include <stdbool.h> | ||
13 | #include <assert.h> | ||
14 | |||
15 | #include "svc/pm/pm_api.h" | ||
16 | |||
17 | /*! @addtogroup clock */ | ||
18 | /*! @{ */ | ||
19 | |||
20 | /******************************************************************************* | ||
21 | * Definitions | ||
22 | ******************************************************************************/ | ||
23 | /*! @brief Configure whether driver controls clock | ||
24 | * | ||
25 | * When set to 0, peripheral drivers will enable clock in initialize function | ||
26 | * and disable clock in de-initialize function. When set to 1, peripheral | ||
27 | * driver will not control the clock, application could control the clock out of | ||
28 | * the driver. | ||
29 | * | ||
30 | * @note All drivers share this feature switcher. If it is set to 1, application | ||
31 | * should handle clock enable and disable for all drivers. | ||
32 | */ | ||
33 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) | ||
34 | #define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0 | ||
35 | #endif | ||
36 | |||
37 | /*! @name Driver version */ | ||
38 | /*@{*/ | ||
39 | /*! @brief CLOCK driver version 2.4.0. */ | ||
40 | #define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 4, 0)) | ||
41 | /*@}*/ | ||
42 | |||
43 | /* Definition for delay API in clock driver, users can redefine it to the real application. */ | ||
44 | #ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY | ||
45 | #define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (400000000UL) | ||
46 | #endif | ||
47 | |||
48 | /*! @brief Clock ip name array for MU. */ | ||
49 | #define MU_CLOCKS \ | ||
50 | { \ | ||
51 | kCLOCK_M4_0_Mu0B, kCLOCK_M4_0_Mu0B, kCLOCK_M4_0_Mu0B, kCLOCK_M4_0_Mu0B, kCLOCK_M4_0_Mu0A0, kCLOCK_M4_0_Mu0A1, \ | ||
52 | kCLOCK_M4_0_Mu0A2, kCLOCK_M4_0_Mu0A3, kCLOCK_M4_0_Mu1A, kCLOCK_M4_1_Mu0B, kCLOCK_M4_1_Mu0B, \ | ||
53 | kCLOCK_M4_1_Mu0B, kCLOCK_M4_1_Mu0B, kCLOCK_M4_1_Mu0A0, kCLOCK_M4_1_Mu0A1, kCLOCK_M4_1_Mu0A2, \ | ||
54 | kCLOCK_M4_1_Mu0A3, kCLOCK_M4_1_Mu1A, kCLOCK_LSIO_Mu0A, kCLOCK_LSIO_Mu1A, kCLOCK_LSIO_Mu2A, \ | ||
55 | kCLOCK_LSIO_Mu3A, kCLOCK_LSIO_Mu4A, kCLOCK_LSIO_Mu5A, kCLOCK_LSIO_Mu6A, kCLOCK_LSIO_Mu7A, \ | ||
56 | kCLOCK_LSIO_Mu8A, kCLOCK_LSIO_Mu9A, kCLOCK_LSIO_Mu10A, kCLOCK_LSIO_Mu11A, kCLOCK_LSIO_Mu12A, \ | ||
57 | kCLOCK_LSIO_Mu13A, kCLOCK_LSIO_Mu5B, kCLOCK_LSIO_Mu6B, kCLOCK_LSIO_Mu7B, kCLOCK_LSIO_Mu8B, \ | ||
58 | kCLOCK_LSIO_Mu9B, kCLOCK_LSIO_Mu10B, kCLOCK_LSIO_Mu11B, kCLOCK_LSIO_Mu12B, kCLOCK_LSIO_Mu13B, \ | ||
59 | } | ||
60 | |||
61 | /*! @brief Clock ip name array for GPIO. */ | ||
62 | #define GPIO_CLOCKS \ | ||
63 | { \ | ||
64 | kCLOCK_IpInvalid, kCLOCK_IpInvalid, kCLOCK_IpInvalid, kCLOCK_IpInvalid, kCLOCK_IpInvalid, kCLOCK_HSIO_Gpio, \ | ||
65 | kCLOCK_LSIO_Gpio0, kCLOCK_LSIO_Gpio1, kCLOCK_LSIO_Gpio2, kCLOCK_LSIO_Gpio3, kCLOCK_LSIO_Gpio4, \ | ||
66 | kCLOCK_LSIO_Gpio5, kCLOCK_LSIO_Gpio6, kCLOCK_LSIO_Gpio7, kCLOCK_IpInvalid, kCLOCK_IpInvalid, \ | ||
67 | kCLOCK_IpInvalid, \ | ||
68 | } | ||
69 | |||
70 | /*! @brief Clock ip name array for RGPIO. */ | ||
71 | #define RGPIO_CLOCKS \ | ||
72 | { \ | ||
73 | kCLOCK_M4_0_Rgpio, kCLOCK_M4_1_Rgpio, \ | ||
74 | } | ||
75 | |||
76 | /*! @brief Clock ip name array for FTM. */ | ||
77 | #define FTM_CLOCKS \ | ||
78 | { \ | ||
79 | kCLOCK_DMA_Ftm0, kCLOCK_DMA_Ftm1, \ | ||
80 | } | ||
81 | |||
82 | /*! @brief Clock ip name array for GPT. */ | ||
83 | #define GPT_CLOCKS \ | ||
84 | { \ | ||
85 | kCLOCK_AUDIO_Gpt0, kCLOCK_AUDIO_Gpt1, kCLOCK_AUDIO_Gpt2, kCLOCK_AUDIO_Gpt3, kCLOCK_AUDIO_Gpt4, \ | ||
86 | kCLOCK_AUDIO_Gpt5, kCLOCK_LSIO_Gpt0, kCLOCK_LSIO_Gpt1, kCLOCK_LSIO_Gpt2, kCLOCK_LSIO_Gpt3, \ | ||
87 | kCLOCK_LSIO_Gpt4, \ | ||
88 | } | ||
89 | /*! @brief Clock ip name array for FLEXCAN. */ | ||
90 | #define FLEXCAN_CLOCKS \ | ||
91 | { \ | ||
92 | kCLOCK_DMA_Can0, kCLOCK_DMA_Can1, kCLOCK_DMA_Can2, \ | ||
93 | } | ||
94 | /*! @brief Clock ip name array for FLEXSPI. */ | ||
95 | #define FLEXSPI_CLOCKS \ | ||
96 | { \ | ||
97 | kCLOCK_LSIO_Flexspi0, kCLOCK_LSIO_Flexspi1, \ | ||
98 | } | ||
99 | /*! @brief Clock ip name array for LPUART. */ | ||
100 | #define LPUART_CLOCKS \ | ||
101 | { \ | ||
102 | kCLOCK_M4_0_Lpuart, kCLOCK_M4_1_Lpuart, kCLOCK_DMA_Lpuart0, kCLOCK_DMA_Lpuart1, kCLOCK_DMA_Lpuart2, \ | ||
103 | kCLOCK_DMA_Lpuart3, kCLOCK_DMA_Lpuart4, kCLOCK_SCU_Lpuart, \ | ||
104 | } | ||
105 | |||
106 | /*! @brief Clock ip name array for LPADC. */ | ||
107 | #define LPADC_CLOCKS \ | ||
108 | { \ | ||
109 | kCLOCK_DMA_Lpadc0, kCLOCK_DMA_Lpadc1, \ | ||
110 | } | ||
111 | |||
112 | /*! @brief Clock ip name array for INTMUX. */ | ||
113 | #define INTMUX_CLOCKS \ | ||
114 | { \ | ||
115 | kCLOCK_M4_0_Intmux, kCLOCK_M4_1_Intmux, kCLOCK_IpInvalid, \ | ||
116 | } | ||
117 | |||
118 | /*! @brief Clock ip name array for SAI. */ | ||
119 | #define SAI_CLOCKS \ | ||
120 | { \ | ||
121 | kCLOCK_AUDIO_Sai0, kCLOCK_AUDIO_Sai1, kCLOCK_AUDIO_Sai2, kCLOCK_AUDIO_Sai3, kCLOCK_AUDIO_Sai4, \ | ||
122 | kCLOCK_AUDIO_Sai5, kCLOCK_AUDIO_Sai6, kCLOCK_AUDIO_Sai7, \ | ||
123 | } | ||
124 | |||
125 | /*! @brief Clock ip name array for SEMA42. */ | ||
126 | #define SEMA42_CLOCKS \ | ||
127 | { \ | ||
128 | kCLOCK_M4_0_Sema42, kCLOCK_M4_1_Sema42, kCLOCK_SCU_Sema42, \ | ||
129 | } | ||
130 | |||
131 | /*! @brief Clock ip name array for TPM. */ | ||
132 | #define TPM_CLOCKS \ | ||
133 | { \ | ||
134 | kCLOCK_M4_0_Tpm, kCLOCK_M4_1_Tpm, kCLOCK_SCU_Tpm, \ | ||
135 | } | ||
136 | |||
137 | /*! @brief Clock ip name array for LPIT. */ | ||
138 | #define LPIT_CLOCKS \ | ||
139 | { \ | ||
140 | kCLOCK_M4_0_Lpit, kCLOCK_M4_1_Lpit, kCLOCK_SCU_Lpit, \ | ||
141 | } | ||
142 | |||
143 | /*! @brief Clock ip name array for LPI2C. */ | ||
144 | #define LPI2C_CLOCKS \ | ||
145 | { \ | ||
146 | kCLOCK_M4_0_Lpi2c, kCLOCK_M4_1_Lpi2c, kCLOCK_HDMI_Lpi2c0, kCLOCK_LVDS_0_Lpi2c1, kCLOCK_LVDS_0_Lpi2c0, \ | ||
147 | kCLOCK_LVDS_1_Lpi2c1, kCLOCK_LVDS_1_Lpi2c0, kCLOCK_MIPI_0_Lpi2c0, kCLOCK_MIPI_0_Lpi2c1, \ | ||
148 | kCLOCK_MIPI_1_Lpi2c0, kCLOCK_MIPI_1_Lpi2c1, kCLOCK_DMA_Lpi2c0, kCLOCK_DMA_Lpi2c1, kCLOCK_DMA_Lpi2c2, \ | ||
149 | kCLOCK_DMA_Lpi2c3, kCLOCK_DMA_Lpi2c4, kCLOCK_CSI_0_Lpi2c0, kCLOCK_CSI_1_Lpi2c0, kCLOCK_HDMI_RX_Lpi2c0, \ | ||
150 | kCLOCK_SCU_Lpi2c, \ | ||
151 | } | ||
152 | |||
153 | /*! @brief Clock ip name array for LPSPI. */ | ||
154 | #define LPSPI_CLOCKS \ | ||
155 | { \ | ||
156 | kCLOCK_DMA_Lpspi0, kCLOCK_DMA_Lpspi1, kCLOCK_DMA_Lpspi2, kCLOCK_DMA_Lpspi3, \ | ||
157 | } | ||
158 | #if defined(MIMX8QM_CM4_CORE0) | ||
159 | #define IRQSTEER_CLOCKS \ | ||
160 | { \ | ||
161 | kCLOCK_M4_0_Irqsteer, \ | ||
162 | } | ||
163 | #elif defined(MIMX8QM_CM4_CORE1) | ||
164 | #define IRQSTEER_CLOCKS \ | ||
165 | { \ | ||
166 | kCLOCK_M4_1_Irqsteer, \ | ||
167 | } | ||
168 | #endif | ||
169 | |||
170 | /*! @brief Clock ip name array for EDMA. */ | ||
171 | #define EDMA_CLOCKS \ | ||
172 | { \ | ||
173 | kCLOCK_DMA_Dma0, \ | ||
174 | } | ||
175 | |||
176 | /*! @brief Clock ip name array for ESAI. */ | ||
177 | #define ESAI_CLOCKS \ | ||
178 | { \ | ||
179 | kCLOCK_AUDIO_Esai0, kCLOCK_AUDIO_Esai1 \ | ||
180 | } | ||
181 | |||
182 | /*! @brief Clock ip name array for ISI. */ | ||
183 | #define ISI_CLOCKS \ | ||
184 | { \ | ||
185 | kCLOCK_IMAGING_Isi0, kCLOCK_IMAGING_Isi1, kCLOCK_IMAGING_Isi2, kCLOCK_IMAGING_Isi3, kCLOCK_IMAGING_Isi4, \ | ||
186 | kCLOCK_IMAGING_Isi5, kCLOCK_IMAGING_Isi6, kCLOCK_IMAGING_Isi7, \ | ||
187 | } | ||
188 | |||
189 | /*! @brief Clock ip name array for MIPI CSI2 RX. */ | ||
190 | #define MIPI_CSI2RX_CLOCKS \ | ||
191 | { \ | ||
192 | kCLOCK_MipiCsi2Rx0, kCLOCK_MipiCsi2Rx1 \ | ||
193 | } | ||
194 | |||
195 | /*! @brief Clock ip name array for MIPI DSI host. */ | ||
196 | #define MIPI_DSI_HOST_CLOCKS \ | ||
197 | { \ | ||
198 | kCLOCK_MipiDsiHost0, kCLOCK_MipiDsiHost1 \ | ||
199 | } | ||
200 | |||
201 | /*! @brief Clock ip name array for ENET. */ | ||
202 | #define ENET_CLOCKS \ | ||
203 | { \ | ||
204 | kCLOCK_CONNECTIVITY_Enet0, kCLOCK_CONNECTIVITY_Enet1 \ | ||
205 | } | ||
206 | |||
207 | /*! @brief Clock ip name array for EMVSIM. */ | ||
208 | #define EMVSIM_CLOCKS \ | ||
209 | { \ | ||
210 | kCLOCK_DMA_EmvSim0, kCLOCK_DMA_EmvSim1, \ | ||
211 | } | ||
212 | |||
213 | /*! @brief Clock ip name array for DPU. */ | ||
214 | #define DPU_CLOCKS \ | ||
215 | { \ | ||
216 | kCLOCK_Dpu0, kCLOCK_Dpu1, \ | ||
217 | } | ||
218 | |||
219 | /*! @brief Clock ip name array for LVDS display bridge(LDB). */ | ||
220 | #define LDB_CLOCKS \ | ||
221 | { \ | ||
222 | kCLOCK_Ldb0, kCLOCK_Ldb1 \ | ||
223 | } | ||
224 | |||
225 | /*! | ||
226 | * @brief Clock source for peripherals that support various clock selections. | ||
227 | */ | ||
228 | typedef enum _clock_ip_src | ||
229 | { | ||
230 | kCLOCK_IpSrcNone = 0U, /*!< Clock is off. */ | ||
231 | kCLOCK_IpSrcDummy = 1U, /*!< Clock option 1. */ | ||
232 | } clock_ip_src_t; | ||
233 | |||
234 | /*! @brief Clock name used to get clock frequency. */ | ||
235 | typedef enum _clock_name | ||
236 | { | ||
237 | /* ----------------------------- System layer clock ---------------------- */ | ||
238 | kCLOCK_CoreSysClk, /*!< Core/system clock for M4 */ | ||
239 | |||
240 | /* --------------------------------- Other clock ------------------------- */ | ||
241 | kCLOCK_CONECTIVITY_AhbClk, /*!< AHB clock in Connectivity subsystem */ | ||
242 | } clock_name_t; | ||
243 | |||
244 | /*! | ||
245 | * @brief LPCG TUPLE macors to map corresponding ip clock name, SCFW API resource index and LPCG Register base address. | ||
246 | * The LPCG base should be 4KB aligned, if not it will be truncated. | ||
247 | */ | ||
248 | #define LPCG_TUPLE(rsrc, base) ((uint32_t)((((base) >> 12U) << 10U) | (rsrc))) | ||
249 | /*! @brief Get the LPCG REG base address. */ | ||
250 | #define LPCG_TUPLE_REG_BASE(tuple) ((volatile uint32_t *)((((uint32_t)(tuple) >> 10U) & 0xFFFFFU) << 12U)) | ||
251 | /*! @brief Get the resource index. */ | ||
252 | #define LPCG_TUPLE_RSRC(tuple) ((sc_rsrc_t)((uint32_t)(tuple)&0x3FFU)) | ||
253 | /*! @brief LPCG Cell not available. */ | ||
254 | #define NV (0U) | ||
255 | |||
256 | /*! | ||
257 | * @brief Peripheral clock name difinition used for clock gate, clock source | ||
258 | * and clock divider setting. It is defined as the corresponding register address. | ||
259 | */ | ||
260 | typedef enum _clock_ip_name | ||
261 | { | ||
262 | kCLOCK_M4_0_Irqsteer = LPCG_TUPLE(SC_R_IRQSTR_M4_0, NV), | ||
263 | kCLOCK_M4_1_Irqsteer = LPCG_TUPLE(SC_R_IRQSTR_M4_1, NV), | ||
264 | kCLOCK_DMA_Lpspi0 = LPCG_TUPLE(SC_R_SPI_0, DMA__LPCG_LPSPI0_BASE), | ||
265 | kCLOCK_DMA_Lpspi1 = LPCG_TUPLE(SC_R_SPI_1, DMA__LPCG_LPSPI1_BASE), | ||
266 | kCLOCK_DMA_Lpspi2 = LPCG_TUPLE(SC_R_SPI_2, DMA__LPCG_LPSPI2_BASE), | ||
267 | kCLOCK_DMA_Lpspi3 = LPCG_TUPLE(SC_R_SPI_3, DMA__LPCG_LPSPI3_BASE), | ||
268 | kCLOCK_DMA_Lpuart0 = LPCG_TUPLE(SC_R_UART_0, DMA__LPCG_LPUART0_BASE), | ||
269 | kCLOCK_DMA_Lpuart1 = LPCG_TUPLE(SC_R_UART_1, DMA__LPCG_LPUART1_BASE), | ||
270 | kCLOCK_DMA_Lpuart2 = LPCG_TUPLE(SC_R_UART_2, DMA__LPCG_LPUART2_BASE), | ||
271 | kCLOCK_DMA_Lpuart3 = LPCG_TUPLE(SC_R_UART_3, DMA__LPCG_LPUART3_BASE), | ||
272 | kCLOCK_DMA_Lpuart4 = LPCG_TUPLE(SC_R_UART_4, DMA__LPCG_LPUART4_BASE), | ||
273 | kCLOCK_DMA_EmvSim0 = LPCG_TUPLE(SC_R_EMVSIM_0, DMA__LPCG_EMV_SIM0_BASE), | ||
274 | kCLOCK_DMA_EmvSim1 = LPCG_TUPLE(SC_R_EMVSIM_1, DMA__LPCG_EMV_SIM1_BASE), | ||
275 | kCLOCK_DMA_Dma0 = LPCG_TUPLE(SC_R_DMA_0_CH0, NV), | ||
276 | kCLOCK_DMA_Lpi2c0 = LPCG_TUPLE(SC_R_I2C_0, DMA__LPCG_LPI2C0_BASE), | ||
277 | kCLOCK_DMA_Lpi2c1 = LPCG_TUPLE(SC_R_I2C_1, DMA__LPCG_LPI2C1_BASE), | ||
278 | kCLOCK_DMA_Lpi2c2 = LPCG_TUPLE(SC_R_I2C_2, DMA__LPCG_LPI2C2_BASE), | ||
279 | kCLOCK_DMA_Lpi2c3 = LPCG_TUPLE(SC_R_I2C_3, DMA__LPCG_LPI2C3_BASE), | ||
280 | kCLOCK_DMA_Lpi2c4 = LPCG_TUPLE(SC_R_I2C_4, DMA__LPCG_LPI2C4_BASE), | ||
281 | kCLOCK_DMA_Lpadc0 = LPCG_TUPLE(SC_R_ADC_0, DMA__LPCG_ADC0_BASE), | ||
282 | kCLOCK_DMA_Lpadc1 = LPCG_TUPLE(SC_R_ADC_1, DMA__LPCG_ADC1_BASE), | ||
283 | kCLOCK_DMA_Ftm0 = LPCG_TUPLE(SC_R_FTM_0, DMA__LPCG_FTM0_BASE), | ||
284 | kCLOCK_DMA_Ftm1 = LPCG_TUPLE(SC_R_FTM_1, DMA__LPCG_FTM1_BASE), | ||
285 | kCLOCK_DMA_Can0 = LPCG_TUPLE(SC_R_CAN_0, DMA__LPCG_CAN0_BASE), | ||
286 | kCLOCK_DMA_Can1 = LPCG_TUPLE(SC_R_CAN_1, DMA__LPCG_CAN1_BASE), | ||
287 | kCLOCK_DMA_Can2 = LPCG_TUPLE(SC_R_CAN_2, DMA__LPCG_CAN2_BASE), | ||
288 | kCLOCK_HSIO_Gpio = LPCG_TUPLE(SC_R_HSIO_GPIO, HSIO__LPCG_GPIO_BASE), | ||
289 | kCLOCK_LVDS_0_Lpi2c0 = LPCG_TUPLE(SC_R_LVDS_0_I2C_0, DI_LVDS_0__LPCG_CLK_BASE), | ||
290 | kCLOCK_LVDS_0_Lpi2c1 = LPCG_TUPLE(SC_R_LVDS_0_I2C_1, DI_LVDS_0__LPCG_CLK_BASE), | ||
291 | kCLOCK_LVDS_1_Lpi2c0 = LPCG_TUPLE(SC_R_LVDS_1_I2C_0, DI_LVDS_1__LPCG_CLK_BASE), | ||
292 | kCLOCK_LVDS_1_Lpi2c1 = LPCG_TUPLE(SC_R_LVDS_1_I2C_1, DI_LVDS_1__LPCG_CLK_BASE), | ||
293 | kCLOCK_LSIO_Gpio0 = LPCG_TUPLE(SC_R_GPIO_0, LSIO__LPCG_GPIO0_BASE), | ||
294 | kCLOCK_LSIO_Gpio1 = LPCG_TUPLE(SC_R_GPIO_1, LSIO__LPCG_GPIO1_BASE), | ||
295 | kCLOCK_LSIO_Gpio2 = LPCG_TUPLE(SC_R_GPIO_2, LSIO__LPCG_GPIO2_BASE), | ||
296 | kCLOCK_LSIO_Gpio3 = LPCG_TUPLE(SC_R_GPIO_3, LSIO__LPCG_GPIO3_BASE), | ||
297 | kCLOCK_LSIO_Gpio4 = LPCG_TUPLE(SC_R_GPIO_4, LSIO__LPCG_GPIO4_BASE), | ||
298 | kCLOCK_LSIO_Gpio5 = LPCG_TUPLE(SC_R_GPIO_5, LSIO__LPCG_GPIO5_BASE), | ||
299 | kCLOCK_LSIO_Gpio6 = LPCG_TUPLE(SC_R_GPIO_6, LSIO__LPCG_GPIO6_BASE), | ||
300 | kCLOCK_LSIO_Gpio7 = LPCG_TUPLE(SC_R_GPIO_7, LSIO__LPCG_GPIO7_BASE), | ||
301 | kCLOCK_AUDIO_Gpt0 = LPCG_TUPLE(SC_R_GPT_5, AUDIO__LPCG_GPT0_BASE), | ||
302 | kCLOCK_AUDIO_Gpt1 = LPCG_TUPLE(SC_R_GPT_6, AUDIO__LPCG_GPT1_BASE), | ||
303 | kCLOCK_AUDIO_Gpt2 = LPCG_TUPLE(SC_R_GPT_7, AUDIO__LPCG_GPT2_BASE), | ||
304 | kCLOCK_AUDIO_Gpt3 = LPCG_TUPLE(SC_R_GPT_8, AUDIO__LPCG_GPT3_BASE), | ||
305 | kCLOCK_AUDIO_Gpt4 = LPCG_TUPLE(SC_R_GPT_9, AUDIO__LPCG_GPT4_BASE), | ||
306 | kCLOCK_AUDIO_Gpt5 = LPCG_TUPLE(SC_R_GPT_10, AUDIO__LPCG_GPT5_BASE), | ||
307 | kCLOCK_LSIO_Gpt0 = LPCG_TUPLE(SC_R_GPT_0, LSIO__LPCG_GPT0_BASE), | ||
308 | kCLOCK_LSIO_Gpt1 = LPCG_TUPLE(SC_R_GPT_1, LSIO__LPCG_GPT1_BASE), | ||
309 | kCLOCK_LSIO_Gpt2 = LPCG_TUPLE(SC_R_GPT_2, LSIO__LPCG_GPT2_BASE), | ||
310 | kCLOCK_LSIO_Gpt3 = LPCG_TUPLE(SC_R_GPT_3, LSIO__LPCG_GPT3_BASE), | ||
311 | kCLOCK_LSIO_Gpt4 = LPCG_TUPLE(SC_R_GPT_4, LSIO__LPCG_GPT4_BASE), | ||
312 | kCLOCK_LSIO_Mu0A = LPCG_TUPLE(SC_R_MU_0A, NV), | ||
313 | kCLOCK_LSIO_Mu1A = LPCG_TUPLE(SC_R_MU_1A, NV), | ||
314 | kCLOCK_LSIO_Mu2A = LPCG_TUPLE(SC_R_MU_2A, NV), | ||
315 | kCLOCK_LSIO_Mu3A = LPCG_TUPLE(SC_R_MU_3A, NV), | ||
316 | kCLOCK_LSIO_Mu4A = LPCG_TUPLE(SC_R_MU_4A, NV), | ||
317 | kCLOCK_LSIO_Mu5A = LPCG_TUPLE(SC_R_MU_5A, LSIO__LPCG_MU5_MCU_BASE), | ||
318 | kCLOCK_LSIO_Mu6A = LPCG_TUPLE(SC_R_MU_6A, LSIO__LPCG_MU6_MCU_BASE), | ||
319 | kCLOCK_LSIO_Mu7A = LPCG_TUPLE(SC_R_MU_7A, LSIO__LPCG_MU7_MCU_BASE), | ||
320 | kCLOCK_LSIO_Mu8A = LPCG_TUPLE(SC_R_MU_8A, LSIO__LPCG_MU8_MCU_BASE), | ||
321 | kCLOCK_LSIO_Mu9A = LPCG_TUPLE(SC_R_MU_9A, LSIO__LPCG_MU9_MCU_BASE), | ||
322 | kCLOCK_LSIO_Mu10A = LPCG_TUPLE(SC_R_MU_10A, LSIO__LPCG_MU10_MCU_BASE), | ||
323 | kCLOCK_LSIO_Mu11A = LPCG_TUPLE(SC_R_MU_11A, LSIO__LPCG_MU11_MCU_BASE), | ||
324 | kCLOCK_LSIO_Mu12A = LPCG_TUPLE(SC_R_MU_12A, LSIO__LPCG_MU12_MCU_BASE), | ||
325 | kCLOCK_LSIO_Mu13A = LPCG_TUPLE(SC_R_MU_13A, LSIO__LPCG_MU13_MCU_BASE), | ||
326 | kCLOCK_LSIO_Mu5B = LPCG_TUPLE(SC_R_MU_5B, LSIO__LPCG_MU5_DSP_BASE), | ||
327 | kCLOCK_LSIO_Mu6B = LPCG_TUPLE(SC_R_MU_6B, LSIO__LPCG_MU6_DSP_BASE), | ||
328 | kCLOCK_LSIO_Mu7B = LPCG_TUPLE(SC_R_MU_7B, LSIO__LPCG_MU7_DSP_BASE), | ||
329 | kCLOCK_LSIO_Mu8B = LPCG_TUPLE(SC_R_MU_8B, LSIO__LPCG_MU8_DSP_BASE), | ||
330 | kCLOCK_LSIO_Mu9B = LPCG_TUPLE(SC_R_MU_9B, LSIO__LPCG_MU9_DSP_BASE), | ||
331 | kCLOCK_LSIO_Mu10B = LPCG_TUPLE(SC_R_MU_10B, LSIO__LPCG_MU10_DSP_BASE), | ||
332 | kCLOCK_LSIO_Mu11B = LPCG_TUPLE(SC_R_MU_11B, LSIO__LPCG_MU11_DSP_BASE), | ||
333 | kCLOCK_LSIO_Mu12B = LPCG_TUPLE(SC_R_MU_12B, LSIO__LPCG_MU12_DSP_BASE), | ||
334 | kCLOCK_LSIO_Mu13B = LPCG_TUPLE(SC_R_MU_13B, LSIO__LPCG_MU13_DSP_BASE), | ||
335 | kCLOCK_LSIO_Flexspi0 = LPCG_TUPLE(SC_R_FSPI_0, LSIO__LPCG_QSPI0_BASE), | ||
336 | kCLOCK_LSIO_Flexspi1 = LPCG_TUPLE(SC_R_FSPI_1, LSIO__LPCG_QSPI1_BASE), | ||
337 | kCLOCK_M4_0_Rgpio = LPCG_TUPLE(SC_R_M4_0_RGPIO, NV), | ||
338 | kCLOCK_M4_0_Sema42 = LPCG_TUPLE(SC_R_M4_0_SEMA42, NV), | ||
339 | kCLOCK_M4_0_Tpm = LPCG_TUPLE(SC_R_M4_0_TPM, CM4_0__LPCG_TPM_BASE), | ||
340 | kCLOCK_M4_0_Lpit = LPCG_TUPLE(SC_R_M4_0_PIT, CM4_0__LPCG_LPIT_BASE), | ||
341 | kCLOCK_M4_0_Lpuart = LPCG_TUPLE(SC_R_M4_0_UART, CM4_0__LPCG_LPUART_BASE), | ||
342 | kCLOCK_M4_0_Lpi2c = LPCG_TUPLE(SC_R_M4_0_I2C, CM4_0__LPCG_LPI2C_BASE), | ||
343 | kCLOCK_M4_0_Intmux = LPCG_TUPLE(SC_R_M4_0_INTMUX, NV), | ||
344 | kCLOCK_M4_0_Mu0B = LPCG_TUPLE(SC_R_M4_0_MU_0B, NV), | ||
345 | kCLOCK_M4_0_Mu0A0 = LPCG_TUPLE(SC_R_M4_0_MU_0A0, NV), | ||
346 | kCLOCK_M4_0_Mu0A1 = LPCG_TUPLE(SC_R_M4_0_MU_0A1, NV), | ||
347 | kCLOCK_M4_0_Mu0A2 = LPCG_TUPLE(SC_R_M4_0_MU_0A2, NV), | ||
348 | kCLOCK_M4_0_Mu0A3 = LPCG_TUPLE(SC_R_M4_0_MU_0A3, NV), | ||
349 | kCLOCK_M4_0_Mu1A = LPCG_TUPLE(SC_R_M4_0_MU_1A, NV), | ||
350 | kCLOCK_M4_1_Rgpio = LPCG_TUPLE(SC_R_M4_1_RGPIO, NV), | ||
351 | kCLOCK_M4_1_Sema42 = LPCG_TUPLE(SC_R_M4_1_SEMA42, NV), | ||
352 | kCLOCK_M4_1_Tpm = LPCG_TUPLE(SC_R_M4_1_TPM, CM4_1__LPCG_TPM_BASE), | ||
353 | kCLOCK_M4_1_Lpit = LPCG_TUPLE(SC_R_M4_1_PIT, CM4_1__LPCG_LPIT_BASE), | ||
354 | kCLOCK_M4_1_Lpuart = LPCG_TUPLE(SC_R_M4_1_UART, CM4_1__LPCG_LPUART_BASE), | ||
355 | kCLOCK_SCU_Lpuart = LPCG_TUPLE(SC_R_SC_UART, SCU__LPCG_LPUART_BASE), | ||
356 | kCLOCK_M4_1_Lpi2c = LPCG_TUPLE(SC_R_M4_1_I2C, CM4_1__LPCG_LPI2C_BASE), | ||
357 | kCLOCK_M4_1_Intmux = LPCG_TUPLE(SC_R_M4_1_INTMUX, NV), | ||
358 | kCLOCK_M4_1_Mu0B = LPCG_TUPLE(SC_R_M4_1_MU_0B, NV), | ||
359 | kCLOCK_M4_1_Mu0A0 = LPCG_TUPLE(SC_R_M4_1_MU_0A0, NV), | ||
360 | kCLOCK_M4_1_Mu0A1 = LPCG_TUPLE(SC_R_M4_1_MU_0A1, NV), | ||
361 | kCLOCK_M4_1_Mu0A2 = LPCG_TUPLE(SC_R_M4_1_MU_0A2, NV), | ||
362 | kCLOCK_M4_1_Mu0A3 = LPCG_TUPLE(SC_R_M4_1_MU_0A3, NV), | ||
363 | kCLOCK_M4_1_Mu1A = LPCG_TUPLE(SC_R_M4_1_MU_1A, NV), | ||
364 | kCLOCK_SCU_Lpi2c = LPCG_TUPLE(SC_R_SC_I2C, SCU__LPCG_LPI2C_BASE), | ||
365 | kCLOCK_SCU_Sema42 = LPCG_TUPLE(SC_R_SC_SEMA42, NV), | ||
366 | kCLOCK_SCU_Lpit = LPCG_TUPLE(SC_R_SC_PIT, SCU__LPCG_LPIT_BASE), | ||
367 | kCLOCK_SCU_Tpm = LPCG_TUPLE(SC_R_SC_TPM, SCU__LPCG_TPM_BASE), | ||
368 | kCLOCK_AUDIO_Sai0 = LPCG_TUPLE(SC_R_SAI_0, AUDIO__LPCG_SAI0_BASE), | ||
369 | kCLOCK_AUDIO_Sai1 = LPCG_TUPLE(SC_R_SAI_1, AUDIO__LPCG_SAI1_BASE), | ||
370 | kCLOCK_AUDIO_Sai2 = LPCG_TUPLE(SC_R_SAI_2, AUDIO__LPCG_SAI2_BASE), | ||
371 | kCLOCK_AUDIO_Sai3 = LPCG_TUPLE(SC_R_SAI_3, AUDIO__LPCG_SAI3_BASE), | ||
372 | kCLOCK_AUDIO_Sai4 = LPCG_TUPLE(SC_R_SAI_4, AUDIO__LPCG_SAI_HDMIRX0_BASE), | ||
373 | kCLOCK_AUDIO_Sai5 = LPCG_TUPLE(SC_R_SAI_5, AUDIO__LPCG_SAI_HDMITX0_BASE), | ||
374 | kCLOCK_AUDIO_Sai6 = LPCG_TUPLE(SC_R_SAI_6, AUDIO__LPCG_SAI6_BASE), | ||
375 | kCLOCK_AUDIO_Sai7 = LPCG_TUPLE(SC_R_SAI_7, AUDIO__LPCG_SAI7_BASE), | ||
376 | kCLOCK_AUDIO_Esai0 = LPCG_TUPLE(SC_R_ESAI_0, AUDIO__LPCG_ESAI0_BASE), | ||
377 | kCLOCK_AUDIO_Esai1 = LPCG_TUPLE(SC_R_ESAI_1, AUDIO__LPCG_ESAI1_BASE), | ||
378 | kCLOCK_IMAGING_Isi0 = LPCG_TUPLE(SC_R_ISI_CH0, NV), | ||
379 | kCLOCK_IMAGING_Isi1 = LPCG_TUPLE(SC_R_ISI_CH1, NV), | ||
380 | kCLOCK_IMAGING_Isi2 = LPCG_TUPLE(SC_R_ISI_CH2, NV), | ||
381 | kCLOCK_IMAGING_Isi3 = LPCG_TUPLE(SC_R_ISI_CH3, NV), | ||
382 | kCLOCK_IMAGING_Isi4 = LPCG_TUPLE(SC_R_ISI_CH4, NV), | ||
383 | kCLOCK_IMAGING_Isi5 = LPCG_TUPLE(SC_R_ISI_CH5, NV), | ||
384 | kCLOCK_IMAGING_Isi6 = LPCG_TUPLE(SC_R_ISI_CH6, NV), | ||
385 | kCLOCK_IMAGING_Isi7 = LPCG_TUPLE(SC_R_ISI_CH7, NV), | ||
386 | kCLOCK_MIPI_0_Lpi2c0 = LPCG_TUPLE(SC_R_MIPI_0_I2C_0, DI_MIPI_0__LPCG_CLK_BASE), | ||
387 | kCLOCK_MIPI_0_Lpi2c1 = LPCG_TUPLE(SC_R_MIPI_0_I2C_1, DI_MIPI_0__LPCG_CLK_BASE), | ||
388 | kCLOCK_MIPI_1_Lpi2c0 = LPCG_TUPLE(SC_R_MIPI_1_I2C_0, DI_MIPI_1__LPCG_CLK_BASE), | ||
389 | kCLOCK_MIPI_1_Lpi2c1 = LPCG_TUPLE(SC_R_MIPI_1_I2C_1, DI_MIPI_1__LPCG_CLK_BASE), | ||
390 | kCLOCK_CSI_0_Lpi2c0 = LPCG_TUPLE(SC_R_CSI_0_I2C_0, MIPI_CSI_0__LPCG_CLK_BASE), | ||
391 | kCLOCK_CSI_1_Lpi2c0 = LPCG_TUPLE(SC_R_CSI_1_I2C_0, MIPI_CSI_1__LPCG_CLK_BASE), | ||
392 | kCLOCK_Dpu0 = LPCG_TUPLE(SC_R_DC_0, DC_0__LPCG_DSP0_CLK_BASE), | ||
393 | kCLOCK_Dpu1 = LPCG_TUPLE(SC_R_DC_1, DC_1__LPCG_DSP0_CLK_BASE), | ||
394 | kCLOCK_HDMI_Lpi2c0 = LPCG_TUPLE(SC_R_HDMI_I2C_0, DI_HDMI__LPCG_CLK_BASE), | ||
395 | kCLOCK_HDMI_RX_Lpi2c0 = LPCG_TUPLE(SC_R_HDMI_RX_I2C_0, RX_HDMI__LPCG_GPIO_IPG_CLK_S_BASE), | ||
396 | kCLOCK_MipiCsi2Rx0 = LPCG_TUPLE(SC_R_CSI_0, MIPI_CSI_0__LPCG_CLK_BASE), | ||
397 | kCLOCK_MipiCsi2Rx1 = LPCG_TUPLE(SC_R_CSI_1, MIPI_CSI_1__LPCG_CLK_BASE), | ||
398 | kCLOCK_MipiDsiHost0 = LPCG_TUPLE(SC_R_MIPI_0, DI_MIPI_0__LPCG_CLK_BASE), | ||
399 | kCLOCK_MipiDsiHost1 = LPCG_TUPLE(SC_R_MIPI_1, DI_MIPI_1__LPCG_CLK_BASE), | ||
400 | kCLOCK_Ldb0 = LPCG_TUPLE(SC_R_LVDS_0, NV), | ||
401 | kCLOCK_Ldb1 = LPCG_TUPLE(SC_R_LVDS_1, NV), | ||
402 | kCLOCK_CONNECTIVITY_Enet0 = LPCG_TUPLE(SC_R_ENET_0, CONNECTIVITY__LPCG_ENET0_BASE), | ||
403 | kCLOCK_CONNECTIVITY_Enet1 = LPCG_TUPLE(SC_R_ENET_1, CONNECTIVITY__LPCG_ENET1_BASE), | ||
404 | kCLOCK_AUDIO_Pll0 = LPCG_TUPLE(SC_R_AUDIO_PLL_0, NV), | ||
405 | kCLOCK_AUDIO_Pll1 = LPCG_TUPLE(SC_R_AUDIO_PLL_1, NV), | ||
406 | kCLOCK_IpInvalid = LPCG_TUPLE(SC_R_LAST, NV) /* The selected IP does not support clock control. */ | ||
407 | } clock_ip_name_t; | ||
408 | |||
409 | #if defined(__cplusplus) | ||
410 | extern "C" { | ||
411 | #endif /* _cplusplus */ | ||
412 | |||
413 | /*! | ||
414 | * @brief Initialize Clock module. | ||
415 | * | ||
416 | * @param ipc IPC handle for communication with SCU, see sc_ipc_t. | ||
417 | */ | ||
418 | void CLOCK_Init(sc_ipc_t ipc); | ||
419 | |||
420 | /*! | ||
421 | * @brief Deinitialize Clock module. | ||
422 | */ | ||
423 | void CLOCK_Deinit(void); | ||
424 | |||
425 | /*! | ||
426 | * @brief Enable the clock for specific IP, with gate setting. | ||
427 | * | ||
428 | * @param name Which clock to enable, see \ref clock_ip_name_t. | ||
429 | * @param gate 0: clock always on, 1: HW auto clock gating. | ||
430 | * @return true if success, false if failure. | ||
431 | */ | ||
432 | bool CLOCK_EnableClockExt(clock_ip_name_t name, uint32_t gate); | ||
433 | |||
434 | /*! | ||
435 | * @brief Enable the clock for specific IP. | ||
436 | * | ||
437 | * @param name Which clock to enable, see \ref clock_ip_name_t. | ||
438 | * @return true for success, false for failure. | ||
439 | */ | ||
440 | static inline bool CLOCK_EnableClock(clock_ip_name_t name) | ||
441 | { | ||
442 | return CLOCK_EnableClockExt(name, 0); | ||
443 | } | ||
444 | |||
445 | /*! | ||
446 | * @brief Disable the clock for specific IP. | ||
447 | * | ||
448 | * @param name Which clock to disable, see \ref clock_ip_name_t. | ||
449 | * @return true for success, false for failure. | ||
450 | */ | ||
451 | bool CLOCK_DisableClock(clock_ip_name_t name); | ||
452 | |||
453 | /*! | ||
454 | * @brief Set the clock frequency for specific IP module. | ||
455 | * | ||
456 | * This function sets the IP module clock frequency. | ||
457 | * | ||
458 | * @param name Which peripheral to check, see \ref clock_ip_name_t. | ||
459 | * @param freq Target clock frequency value in hertz. | ||
460 | * @return the Real clock frequency value in hertz, or 0 if failed | ||
461 | */ | ||
462 | uint32_t CLOCK_SetIpFreq(clock_ip_name_t name, uint32_t freq); | ||
463 | |||
464 | /*! | ||
465 | * @brief Get the clock frequency for a specific IP module. | ||
466 | * | ||
467 | * This function gets the IP module clock frequency. | ||
468 | * | ||
469 | * @param name Which peripheral to get, see \ref clock_ip_name_t. | ||
470 | * @return Clock frequency value in hertz, or 0 if failed | ||
471 | */ | ||
472 | uint32_t CLOCK_GetIpFreq(clock_ip_name_t name); | ||
473 | |||
474 | /*! | ||
475 | * @brief Gets the clock frequency for a specific clock name. | ||
476 | * | ||
477 | * This function checks the current clock configurations and then calculates | ||
478 | * the clock frequency for a specific clock name defined in clock_name_t. | ||
479 | * | ||
480 | * @param name Clock names defined in clock_name_t | ||
481 | * @return Clock frequency value in hertz | ||
482 | */ | ||
483 | uint32_t CLOCK_GetFreq(clock_name_t name); | ||
484 | |||
485 | /*! | ||
486 | * @brief Get the core clock or system clock frequency. | ||
487 | * | ||
488 | * @return Clock frequency in Hz. | ||
489 | */ | ||
490 | uint32_t CLOCK_GetCoreSysClkFreq(void); | ||
491 | |||
492 | /*! | ||
493 | * @brief Config the LPCG cell for specific IP. | ||
494 | * | ||
495 | * @param name Which clock to enable, see \ref clock_ip_name_t. | ||
496 | * @param swGate Software clock gating. false: clock is gated; true: clock is enabled | ||
497 | * @param hwGate Hardware auto gating. false: disable the HW clock gate control; true: HW clock gating is enabled | ||
498 | */ | ||
499 | void CLOCK_ConfigLPCG(clock_ip_name_t name, bool swGate, bool hwGate); | ||
500 | |||
501 | /*! | ||
502 | * @brief Set LPCG gate for specific LPCG. | ||
503 | * | ||
504 | * @param regBase LPCG register base address. | ||
505 | * @param swGate Software clock gating. false: clock is gated; true: clock is enabled | ||
506 | * @param hwGate Hardware auto gating. false: disable the HW clock gate control; true: HW clock gating is enabled | ||
507 | * @param bitsMask The available bits in LPCG register. Each bit indicate the corresponding bit is available or not. | ||
508 | */ | ||
509 | void CLOCK_SetLpcgGate(volatile uint32_t *regBase, bool swGate, bool hwGate, uint32_t bitsMask); | ||
510 | |||
511 | #if defined(__cplusplus) | ||
512 | } | ||
513 | #endif /* __cplusplus */ | ||
514 | |||
515 | /*! @} */ | ||
516 | |||
517 | #endif /* _FSL_CLOCK_H_ */ | ||
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_memory.h b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_memory.h new file mode 100644 index 000000000..1f83092f1 --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_memory.h | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * Copyright 2017-2018 NXP | ||
3 | * | ||
4 | * SPDX-License-Identifier: BSD-3-Clause | ||
5 | */ | ||
6 | |||
7 | #ifndef _FSL_MEMORY_H_ | ||
8 | #define _FSL_MEMORY_H_ | ||
9 | |||
10 | #include "fsl_common.h" | ||
11 | |||
12 | /******************************************************************************* | ||
13 | * Definitions | ||
14 | ******************************************************************************/ | ||
15 | /* Component ID definition, used by tools. */ | ||
16 | #ifndef FSL_COMPONENT_ID | ||
17 | #define FSL_COMPONENT_ID "platform.drivers.memory" | ||
18 | #endif | ||
19 | /* The CM4 subsystem local TCM start address, refer to Reference Manual for detailed information */ | ||
20 | #define FSL_MEM_M4_TCM_BEGIN 0x1FFE0000U | ||
21 | /* The CM4 subsystem local TCM end address, refer to Reference Manual for detailed information */ | ||
22 | #define FSL_MEM_M4_TCM_END 0x2001FFFFU | ||
23 | |||
24 | /* The alias start address for CM4 subsystem */ | ||
25 | #define FSL_MEM_M4_ALIAS_BEGIN 0x21000000U | ||
26 | /* The alias end address for CM4 subsystem */ | ||
27 | #define FSL_MEM_M4_ALIAS_END 0x211FFFFFU | ||
28 | /* | ||
29 | This alias allows the ROM and OCRAM to be mapped to the CM4 system address space without the need | ||
30 | to enable and configure SMMU. | ||
31 | System-level address 0x0000_0000 to 0x001F_FFFF is mapped to the CM4 system address space 0x2100_0000 to 0x211F_FFFF | ||
32 | */ | ||
33 | #define FSL_MEM_M4_ALIAS_OFFSET 0x21000000U | ||
34 | |||
35 | #if defined(MIMX8QM_CM4_CORE0) | ||
36 | /* System level TCM memory address = CM4 subsystem local TCM address + FSL_FEATURE_TCM_OFFSET */ | ||
37 | #define FSL_MEM_M4_TCM_OFFSET 0x15000000U | ||
38 | #elif defined(MIMX8QM_CM4_CORE1) | ||
39 | /* System level TCM memory address = CM4 subsystem local TCM address + FSL_FEATURE_TCM_OFFSET */ | ||
40 | #define FSL_MEM_M4_TCM_OFFSET 0x19000000U | ||
41 | #else | ||
42 | #error "Device is not supported by this driver!" | ||
43 | #endif | ||
44 | |||
45 | typedef enum _mem_direction | ||
46 | { | ||
47 | kMEMORY_Local2DMA = 0, | ||
48 | kMEMORY_DMA2Local, | ||
49 | } mem_direction_t; | ||
50 | |||
51 | /******************************************************************************* | ||
52 | * API | ||
53 | ******************************************************************************/ | ||
54 | #if defined(__cplusplus) | ||
55 | extern "C" { | ||
56 | #endif | ||
57 | /*! | ||
58 | * @brief Convert the memory map address. | ||
59 | * | ||
60 | * This function convert the address between system mapped address and native mapped address. | ||
61 | * There maybe offset between subsystem native address and system address for some memory, | ||
62 | * this funciton convert the address to different memory map. | ||
63 | * @param addr address need to be converted. | ||
64 | * @param direction convert direction. | ||
65 | * @return the converted address | ||
66 | */ | ||
67 | static inline uint32_t MEMORY_ConvertMemoryMapAddress(uint32_t addr, mem_direction_t direction) | ||
68 | { | ||
69 | uint32_t dest; | ||
70 | |||
71 | switch (direction) | ||
72 | { | ||
73 | case kMEMORY_Local2DMA: | ||
74 | { | ||
75 | if ((addr >= FSL_MEM_M4_TCM_BEGIN) && (addr <= FSL_MEM_M4_TCM_END)) | ||
76 | { | ||
77 | dest = addr + FSL_MEM_M4_TCM_OFFSET; | ||
78 | } | ||
79 | else if ((addr >= FSL_MEM_M4_ALIAS_BEGIN) && (addr <= FSL_MEM_M4_ALIAS_END)) | ||
80 | { | ||
81 | dest = addr - FSL_MEM_M4_ALIAS_OFFSET; | ||
82 | } | ||
83 | else | ||
84 | { | ||
85 | dest = addr; | ||
86 | } | ||
87 | break; | ||
88 | } | ||
89 | case kMEMORY_DMA2Local: | ||
90 | { | ||
91 | if ((addr >= (FSL_MEM_M4_TCM_BEGIN + FSL_MEM_M4_TCM_OFFSET)) && | ||
92 | (addr <= (FSL_MEM_M4_TCM_END + FSL_MEM_M4_TCM_OFFSET))) | ||
93 | { | ||
94 | dest = addr - FSL_MEM_M4_TCM_OFFSET; | ||
95 | } | ||
96 | else if (addr <= (FSL_MEM_M4_ALIAS_END - FSL_MEM_M4_ALIAS_OFFSET)) | ||
97 | { | ||
98 | dest = addr + FSL_MEM_M4_ALIAS_OFFSET; | ||
99 | } | ||
100 | else | ||
101 | { | ||
102 | dest = addr; | ||
103 | } | ||
104 | break; | ||
105 | } | ||
106 | default: | ||
107 | dest = addr; | ||
108 | break; | ||
109 | } | ||
110 | |||
111 | return dest; | ||
112 | } | ||
113 | #if defined(__cplusplus) | ||
114 | } | ||
115 | #endif /* __cplusplus */ | ||
116 | #endif /* _FSL_MEMORY_H_ */ \ No newline at end of file | ||
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_sc_event.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_sc_event.c new file mode 100644 index 000000000..9c3bdf774 --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_sc_event.c | |||
@@ -0,0 +1,399 @@ | |||
1 | /* | ||
2 | * Copyright 2019 NXP | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * SPDX-License-Identifier: BSD-3-Clause | ||
6 | */ | ||
7 | |||
8 | #include "fsl_sc_event.h" | ||
9 | #include "fsl_mu.h" | ||
10 | #include "assert.h" | ||
11 | |||
12 | /******************************************************************************* | ||
13 | * Definitions | ||
14 | ******************************************************************************/ | ||
15 | |||
16 | /* Component ID definition, used by tools. */ | ||
17 | #ifndef FSL_COMPONENT_ID | ||
18 | #define FSL_COMPONENT_ID "platform.drivers.sc_event" | ||
19 | #endif | ||
20 | |||
21 | #if defined(MIMX8QM_CM4_CORE0) | ||
22 | #define IPC_MU CM4_0__MU1_A | ||
23 | #define SCEvent_MU_IRQHandler M4_0_MU1_A_IRQHandler | ||
24 | #define IPC_MU_IRQn M4_0_MU1_A_IRQn | ||
25 | #define IPC_MU_RSRC SC_R_M4_0_MU_1A | ||
26 | #elif defined(MIMX8QM_CM4_CORE1) | ||
27 | #define IPC_MU CM4_1__MU1_A | ||
28 | #define SCEvent_MU_IRQHandler M4_1_MU1_A_IRQHandler | ||
29 | #define IPC_MU_IRQn M4_1_MU1_A_IRQn | ||
30 | #define IPC_MU_RSRC SC_R_M4_1_MU_1A | ||
31 | #else | ||
32 | #error "Unsupported CPU." | ||
33 | #endif | ||
34 | |||
35 | /******************************************************************************* | ||
36 | * Prototypes | ||
37 | ******************************************************************************/ | ||
38 | /* Define a structure to hold SRTM_MESSAGE_BUF_SIZE buffer. */ | ||
39 | typedef struct | ||
40 | { | ||
41 | sc_event_list_t node; | ||
42 | uint8_t buf[sizeof(struct _sc_event_handler) - sizeof(sc_event_list_t)]; | ||
43 | } sc_event_handler_buf_t; | ||
44 | /******************************************************************************* | ||
45 | * Code | ||
46 | ******************************************************************************/ | ||
47 | static volatile bool s_irq; /* MU interrupt status. */ | ||
48 | |||
49 | static uint32_t s_irqEnabled[SC_IRQ_NUM_GROUP] = {0U}; | ||
50 | static sc_event_list_t s_registeredHandler; | ||
51 | static sc_ipc_t ipc; /* ipc handle */ | ||
52 | |||
53 | static sc_event_handler_buf_t s_handlerBuf[SC_EVENT_HANDLER_MEM_POOL_SIZE / sizeof(sc_event_handler_t)]; | ||
54 | static sc_event_list_t s_freeHandlerPool; | ||
55 | |||
56 | static void *s_sem = NULL; | ||
57 | static sc_event_sema4_post_t s_postFunc = NULL; | ||
58 | |||
59 | void SCEvent_MU_IRQHandler(void); | ||
60 | /*! | ||
61 | * @brief Initialize SC Event Handler list head. | ||
62 | * | ||
63 | * @param list SC Event Handler list head pointer. | ||
64 | */ | ||
65 | static inline void SCEvent_List_Init(sc_event_list_t *list) | ||
66 | { | ||
67 | assert(list); | ||
68 | |||
69 | list->prev = list; | ||
70 | list->next = list; | ||
71 | } | ||
72 | |||
73 | /*! | ||
74 | * @brief Check whether SC Event Handler list is empty. | ||
75 | * | ||
76 | * @param list SC Event Handler list head pointer. | ||
77 | * @return TRUE when list is empty, FALSE otherwise. | ||
78 | */ | ||
79 | static inline bool SCEvent_List_IsEmpty(sc_event_list_t *list) | ||
80 | { | ||
81 | assert(list); | ||
82 | |||
83 | return list->next == list; | ||
84 | } | ||
85 | |||
86 | /*! | ||
87 | * @brief Add list node at list tail. | ||
88 | * | ||
89 | * @param list SC Event Handler list head pointer. | ||
90 | * @param node SC Event Handler list node pointer to add. | ||
91 | */ | ||
92 | static inline void SCEvent_List_AddTail(sc_event_list_t *list, sc_event_list_t *node) | ||
93 | { | ||
94 | assert(list); | ||
95 | assert(node); | ||
96 | |||
97 | node->prev = list->prev; | ||
98 | node->next = list; | ||
99 | list->prev->next = node; | ||
100 | list->prev = node; | ||
101 | } | ||
102 | |||
103 | /*! | ||
104 | * @brief Remove list node from list. | ||
105 | * | ||
106 | * @param node SC Event Handler list node pointer to remove. | ||
107 | */ | ||
108 | static inline void SCEvent_List_Remove(sc_event_list_t *node) | ||
109 | { | ||
110 | assert(node); | ||
111 | |||
112 | node->prev->next = node->next; | ||
113 | node->next->prev = node->prev; | ||
114 | /* clear node */ | ||
115 | SCEvent_List_Init(node); | ||
116 | } | ||
117 | |||
118 | /*! | ||
119 | * @brief Allocate memory with specific size. | ||
120 | * | ||
121 | * @param size memory size to allocate. | ||
122 | * | ||
123 | * @return allocated memory address. | ||
124 | */ | ||
125 | static void *SCEvent_Pool_Alloc(uint32_t size) | ||
126 | { | ||
127 | uint32_t i; | ||
128 | void *buf; | ||
129 | uint32_t primask; | ||
130 | |||
131 | if (s_freeHandlerPool.next == NULL) | ||
132 | { | ||
133 | primask = DisableGlobalIRQ(); | ||
134 | if (s_freeHandlerPool.next == NULL) | ||
135 | { | ||
136 | /* Handler list not initialized, initialize now. */ | ||
137 | SCEvent_List_Init(&s_freeHandlerPool); | ||
138 | for (i = 0U; i < sizeof(s_handlerBuf) / sizeof(sc_event_handler_buf_t); i++) | ||
139 | { | ||
140 | SCEvent_List_AddTail(&s_freeHandlerPool, &s_handlerBuf[i].node); | ||
141 | } | ||
142 | } | ||
143 | EnableGlobalIRQ(primask); | ||
144 | } | ||
145 | |||
146 | if (size > sizeof(sc_event_handler_buf_t)) | ||
147 | { | ||
148 | return NULL; | ||
149 | } | ||
150 | else | ||
151 | { | ||
152 | primask = DisableGlobalIRQ(); | ||
153 | if (SCEvent_List_IsEmpty(&s_freeHandlerPool)) | ||
154 | { | ||
155 | return NULL; | ||
156 | } | ||
157 | else | ||
158 | { | ||
159 | buf = (void *)s_freeHandlerPool.next; | ||
160 | SCEvent_List_Remove(s_freeHandlerPool.next); | ||
161 | EnableGlobalIRQ(primask); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | return buf; | ||
166 | } | ||
167 | |||
168 | /*! | ||
169 | * @brief Free the allocated memory. | ||
170 | * | ||
171 | * @param buf the address of the allocated memory | ||
172 | */ | ||
173 | static void SCEvent_Pool_Free(void *buf) | ||
174 | { | ||
175 | sc_event_handler_t hBuf; | ||
176 | uint32_t primask; | ||
177 | |||
178 | /* buffer locates in handler pool */ | ||
179 | assert(((uint32_t)((sc_event_handler_buf_t*)buf) - (uint32_t)&s_handlerBuf[0]) % sizeof(sc_event_handler_buf_t) == 0U); | ||
180 | hBuf = (sc_event_handler_t)buf; | ||
181 | primask = DisableGlobalIRQ(); | ||
182 | SCEvent_List_AddTail(&s_freeHandlerPool, &hBuf->node); | ||
183 | EnableGlobalIRQ(primask); | ||
184 | } | ||
185 | |||
186 | void SCEvent_Init(uint8_t priority) | ||
187 | { | ||
188 | ipc = SystemGetScfwIpcHandle(); | ||
189 | NVIC_SetPriority(IPC_MU_IRQn, priority); | ||
190 | (void)EnableIRQ(IPC_MU_IRQn); | ||
191 | MU_EnableInterrupts(IPC_MU, MU_SR_GIPn_MASK); | ||
192 | |||
193 | SCEvent_List_Init(&s_registeredHandler); | ||
194 | } | ||
195 | |||
196 | void SCEvent_Deinit(void) | ||
197 | { | ||
198 | sc_event_list_t *list; | ||
199 | sc_event_handler_t handler; | ||
200 | |||
201 | /* Unregister all handler. */ | ||
202 | while (!SCEvent_List_IsEmpty(&s_registeredHandler)) | ||
203 | { | ||
204 | list = s_registeredHandler.next; | ||
205 | SCEvent_List_Remove(list); | ||
206 | handler = SC_EVENT_LIST_OBJ(sc_event_handler_t, node, list); | ||
207 | SCEvent_Pool_Free(handler); | ||
208 | } | ||
209 | |||
210 | MU_DisableInterrupts(IPC_MU, MU_SR_GIPn_MASK); | ||
211 | (void)DisableIRQ(IPC_MU_IRQn); | ||
212 | } | ||
213 | |||
214 | status_t SCEvent_Config(sc_event_t event, bool enable, uint32_t pt) | ||
215 | { | ||
216 | uint32_t status; | ||
217 | sc_err_t err; | ||
218 | uint32_t mask = SC_EVENT_GET_IRQ(event); | ||
219 | uint8_t group = (uint8_t)SC_EVENT_GET_IRQ_GROUP(event); | ||
220 | |||
221 | /* | ||
222 | * The SCFW IRQ pending flags will be set even the IRQ not enabled. If it's the first IRQ to be enabled in the | ||
223 | * group, clear the group's pending IRQ status in case some IRQ has already pending. | ||
224 | */ | ||
225 | if ((s_irqEnabled[group] == 0U) && enable) | ||
226 | { | ||
227 | err = sc_irq_status(ipc, IPC_MU_RSRC, group, &status); | ||
228 | if (err != SC_ERR_NONE) | ||
229 | { | ||
230 | return kStatus_Fail; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | if (mask == SC_EVENT_IRQ_DUMMY) | ||
235 | { | ||
236 | err = sc_irq_enable(ipc, IPC_MU_RSRC, group, (0x1UL << pt), enable); | ||
237 | if (err != SC_ERR_NONE) | ||
238 | { | ||
239 | return kStatus_Fail; | ||
240 | } | ||
241 | |||
242 | if (enable) | ||
243 | { | ||
244 | s_irqEnabled[group] |= 0x1UL << pt; | ||
245 | } | ||
246 | else | ||
247 | { | ||
248 | /* Clear the flag if IRQ disabled. */ | ||
249 | s_irqEnabled[group] &= (~(0x1UL << pt)) & SC_EVENT_IRQ_DUMMY; | ||
250 | } | ||
251 | } | ||
252 | else | ||
253 | { | ||
254 | err = sc_irq_enable(ipc, IPC_MU_RSRC, group, mask, enable); | ||
255 | if (err != SC_ERR_NONE) | ||
256 | { | ||
257 | return kStatus_Fail; | ||
258 | } | ||
259 | if (enable) | ||
260 | { | ||
261 | s_irqEnabled[group] |= mask; | ||
262 | } | ||
263 | else | ||
264 | { | ||
265 | s_irqEnabled[group] &= ~mask; | ||
266 | } | ||
267 | } | ||
268 | |||
269 | return kStatus_Success; | ||
270 | } | ||
271 | |||
272 | sc_event_handler_t SCEvent_RegisterEventHandler(sc_event_t event, sc_event_callback_t callback, void *userData) | ||
273 | { | ||
274 | assert(callback); | ||
275 | uint32_t primask; | ||
276 | sc_event_handler_t handler = (sc_event_handler_t)SCEvent_Pool_Alloc(sizeof(sc_event_handler_buf_t)); | ||
277 | |||
278 | if (handler == NULL) | ||
279 | { | ||
280 | return NULL; | ||
281 | } | ||
282 | else | ||
283 | { | ||
284 | (void)memset(handler, 0, sizeof(sc_event_handler_buf_t)); | ||
285 | /* clear node */ | ||
286 | SCEvent_List_Init(&handler->node); | ||
287 | |||
288 | handler->event = event; | ||
289 | handler->callback = callback; | ||
290 | handler->data = userData; | ||
291 | |||
292 | /* Add handler into registered handler list. */ | ||
293 | primask = DisableGlobalIRQ(); | ||
294 | SCEvent_List_AddTail(&s_registeredHandler, &handler->node); | ||
295 | EnableGlobalIRQ(primask); | ||
296 | return handler; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | void SCEvent_UnregisterEventHandler(sc_event_handler_t handler) | ||
301 | { | ||
302 | assert(handler); | ||
303 | uint32_t primask; | ||
304 | |||
305 | primask = DisableGlobalIRQ(); | ||
306 | SCEvent_List_Remove(&handler->node); | ||
307 | EnableGlobalIRQ(primask); | ||
308 | |||
309 | SCEvent_Pool_Free(handler); | ||
310 | } | ||
311 | |||
312 | void SCEvent_Process(void) | ||
313 | { | ||
314 | sc_err_t err; | ||
315 | uint32_t mask; /* Enabled IRQ mask. */ | ||
316 | uint8_t group; /* Event group. */ | ||
317 | uint32_t irqStatus[SC_IRQ_NUM_GROUP] = {0U}; | ||
318 | |||
319 | sc_event_list_t *list; | ||
320 | sc_event_handler_t handler; | ||
321 | |||
322 | if (s_irq) | ||
323 | { | ||
324 | for (list = s_registeredHandler.next; list != &s_registeredHandler; list = list->next) | ||
325 | { | ||
326 | handler = SC_EVENT_LIST_OBJ(sc_event_handler_t, node, list); | ||
327 | |||
328 | mask = SC_EVENT_GET_IRQ(handler->event); | ||
329 | group = (uint8_t)SC_EVENT_GET_IRQ_GROUP(handler->event); | ||
330 | /* Only read and clear status once for a group. */ | ||
331 | if (irqStatus[group] == 0U) | ||
332 | { | ||
333 | err = sc_irq_status(ipc, IPC_MU_RSRC, group, &irqStatus[group]); | ||
334 | if (err != SC_ERR_NONE) | ||
335 | { | ||
336 | continue; | ||
337 | } | ||
338 | |||
339 | } | ||
340 | /* If there's event pending and the event IRQ enabled, call the handler. */ | ||
341 | if ((irqStatus[group] & mask & s_irqEnabled[group]) != 0U) | ||
342 | { | ||
343 | handler->callback(irqStatus[group], handler->data); | ||
344 | } | ||
345 | } | ||
346 | |||
347 | /* Clean up the status. */ | ||
348 | (void)memset(irqStatus, 0, sizeof(irqStatus)); | ||
349 | |||
350 | s_irq = false; | ||
351 | } | ||
352 | } | ||
353 | |||
354 | status_t SCEvent_WaitEvent(sc_event_sema4_wait_t wait, sc_event_sema4_post_t post, void *sem, uint32_t timeout) | ||
355 | { | ||
356 | status_t ret = kStatus_Success; | ||
357 | uint32_t primask; | ||
358 | |||
359 | assert(post); | ||
360 | assert(wait); | ||
361 | |||
362 | primask = DisableGlobalIRQ(); | ||
363 | if (!s_irq) /* Return immediately if there's event pending. */ | ||
364 | { | ||
365 | s_sem = sem; | ||
366 | s_postFunc = post; | ||
367 | EnableGlobalIRQ(primask); | ||
368 | ret = wait(sem, timeout); | ||
369 | s_postFunc = NULL; | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | EnableGlobalIRQ(primask); | ||
374 | } | ||
375 | |||
376 | return ret; | ||
377 | } | ||
378 | |||
379 | /*! | ||
380 | * IRQ Handler for SCEvent Triggling MU IRQ | ||
381 | */ | ||
382 | void SCEvent_MU_IRQHandler(void) | ||
383 | { | ||
384 | /* Clear interrupt flag */ | ||
385 | MU_ClearStatusFlags(IPC_MU, MU_SR_GIPn_MASK); | ||
386 | |||
387 | if (s_postFunc != NULL) | ||
388 | { | ||
389 | s_postFunc(s_sem); | ||
390 | } | ||
391 | |||
392 | s_irq = true; | ||
393 | |||
394 | /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping | ||
395 | exception return operation might vector to incorrect interrupt */ | ||
396 | #if defined __CORTEX_M && (__CORTEX_M == 4U) | ||
397 | __DSB(); | ||
398 | #endif | ||
399 | } | ||
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_sc_event.h b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_sc_event.h new file mode 100644 index 000000000..7aa4e2f5b --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QM6/drivers/fsl_sc_event.h | |||
@@ -0,0 +1,266 @@ | |||
1 | /* | ||
2 | * Copyright 2019 NXP | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * SPDX-License-Identifier: BSD-3-Clause | ||
6 | */ | ||
7 | |||
8 | #ifndef _FSL_SC_EVENT_H_ | ||
9 | #define _FSL_SC_EVENT_H_ | ||
10 | |||
11 | #include "fsl_common.h" | ||
12 | #include "svc/irq/irq_api.h" | ||
13 | #include "svc/pad/pad_api.h" | ||
14 | |||
15 | /*! | ||
16 | * @addtogroup sc_event_driver | ||
17 | * @{ | ||
18 | */ | ||
19 | |||
20 | /******************************************************************************* | ||
21 | * Definitions | ||
22 | ******************************************************************************/ | ||
23 | |||
24 | /*! @name Driver version */ | ||
25 | /*@{*/ | ||
26 | /*! @brief Group interrupt driver version for SDK */ | ||
27 | #define FSL_SC_EVENT_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*!< Version 2.0.1. */ | ||
28 | /*@}*/ | ||
29 | |||
30 | /*! @brief The SC Event handler memory pool size in bytes. */ | ||
31 | #ifndef SC_EVENT_HANDLER_MEM_POOL_SIZE | ||
32 | #define SC_EVENT_HANDLER_MEM_POOL_SIZE (200U) | ||
33 | #endif | ||
34 | |||
35 | /*! | ||
36 | * @brief The SYSCTR SC Event maybe used as wakeup source in low power applications. | ||
37 | * Such as in LPM module(lpm.c), the SYSCTR is used as wakeup source in tickless idle. | ||
38 | */ | ||
39 | #ifndef SC_EVENT_USE_SYSCTR | ||
40 | #define SC_EVENT_USE_SYSCTR (0) | ||
41 | #endif | ||
42 | |||
43 | #define SC_EVENT_IRQ_DUMMY (0xFFFFFFFU) /* Dummy mask. */ | ||
44 | #define SC_EVENT_TYPE_TUPLE(group, irq) (((group) << 28) | (irq)) /* Marco to compose SC Event type. */ | ||
45 | #define SC_EVENT_GET_IRQ_GROUP(type) (((uint32_t)(type) >> 28) & 0xFU) /* Marco to get SC IRQ group. */ | ||
46 | #define SC_EVENT_GET_IRQ(type) ((uint32_t)(type) & 0xFFFFFFFU) /* Marco to get SC IRQ mask. */ | ||
47 | |||
48 | /*! | ||
49 | * @brief Get SC Event list object structure pointer. | ||
50 | */ | ||
51 | #define SC_EVENT_LIST_OBJ(type, field, list) (type)((uint32_t)(list) - (uint32_t)(&((type)0)->field)) | ||
52 | |||
53 | /*! @brief SC Event type. */ | ||
54 | typedef enum _sc_event | ||
55 | { | ||
56 | kSCEvent_TempHigh = SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_HIGH), /*!< Temp alarm interrupt */ | ||
57 | kSCEvent_TempCpu0High = | ||
58 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_CPU0_HIGH), /*!< CPU0 temp alarm interrupt */ | ||
59 | kSCEvent_TempCpu1High = | ||
60 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_CPU1_HIGH), /*!< CPU1 temp alarm interrupt */ | ||
61 | kSCEvent_TempGpu0High = | ||
62 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_GPU0_HIGH), /*!< GPU0 temp alarm interrupt */ | ||
63 | kSCEvent_TempGpu1High = | ||
64 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_GPU1_HIGH), /*!< GPU1 temp alarm interrupt */ | ||
65 | kSCEvent_TempDrc0High = | ||
66 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_DRC0_HIGH), /*!< DRC0 temp alarm interrupt */ | ||
67 | kSCEvent_TempDrc1High = | ||
68 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_DRC1_HIGH), /*!< DRC1 temp alarm interrupt */ | ||
69 | kSCEvent_TempVpuHigh = | ||
70 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_VPU_HIGH), /*!< VPU temp alarm interrupt */ | ||
71 | kSCEvent_TempPmic0High = | ||
72 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_PMIC0_HIGH), /*!< PMIC0 temp alarm interrupt */ | ||
73 | kSCEvent_TempPmic1High = | ||
74 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_PMIC1_HIGH), /*!< PMIC1 temp alarm interrupt */ | ||
75 | kSCEvent_TempLow = SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_LOW), /*!< Temp alarm interrupt */ | ||
76 | kSCEvent_TempCpu0Low = | ||
77 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_CPU0_LOW), /*!< CPU0 temp alarm interrupt */ | ||
78 | kSCEvent_TempCpu1Low = | ||
79 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_CPU1_LOW), /*!< CPU1 temp alarm interrupt */ | ||
80 | kSCEvent_TempGpu0Low = | ||
81 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_GPU0_LOW), /*!< GPU0 temp alarm interrupt */ | ||
82 | kSCEvent_TempGpu1Low = | ||
83 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_GPU1_LOW), /*!< GPU1 temp alarm interrupt */ | ||
84 | kSCEvent_TempDrc0Low = | ||
85 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_DRC0_LOW), /*!< DRC0 temp alarm interrupt */ | ||
86 | kSCEvent_TempDrc1Low = | ||
87 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_DRC1_LOW), /*!< DRC1 temp alarm interrupt */ | ||
88 | kSCEvent_TempVpuLow = SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_VPU_LOW), /*!< VPU temp alarm interrupt */ | ||
89 | kSCEvent_TempPmic0Low = | ||
90 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_PMIC0_LOW), /*!< PMIC0 temp alarm interrupt */ | ||
91 | kSCEvent_TempPmic1Low = | ||
92 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_PMIC1_LOW), /*!< PMIC1 temp alarm interrupt */ | ||
93 | kSCEvent_TempPmic2High = | ||
94 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_PMIC2_HIGH), /*!< PMIC2 temp alarm interrupt */ | ||
95 | kSCEvent_TempPmic2Low = | ||
96 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_TEMP, SC_IRQ_TEMP_PMIC2_LOW), /*!< PMIC2 temp alarm interrupt */ | ||
97 | |||
98 | kSCEvent_Wdog = SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_WDOG, SC_IRQ_WDOG), /*!< Watchdog interrupt */ | ||
99 | |||
100 | kSCEvent_Rtc = SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_RTC, SC_IRQ_RTC), /*!< RTC interrupt */ | ||
101 | |||
102 | kSCEvent_Button = SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON), /*!< Button interrupt */ | ||
103 | kSCEvent_Pad = SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_WAKE, SC_IRQ_PAD), /*!< Pad wakeup */ | ||
104 | kSCEvent_User1 = SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_WAKE, SC_IRQ_USR1), /*!< User defined 1 */ | ||
105 | kSCEvent_User2 = SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_WAKE, SC_IRQ_USR2), /*!< User defined 2 */ | ||
106 | kSCEvent_BcPad = | ||
107 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_WAKE, SC_IRQ_BC_PAD), /*!< Pad wakeup (broadcast to all partitions) */ | ||
108 | #if (defined(SC_EVENT_USE_SYSCTR) && SC_EVENT_USE_SYSCTR) | ||
109 | kSCEvent_SysCtr = SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_SYSCTR, SC_IRQ_SYSCTR), /*!< System counter interrupts */ | ||
110 | #endif | ||
111 | kSCEvent_Rebooted = | ||
112 | SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_REBOOTED, SC_EVENT_IRQ_DUMMY), /*!< Partition reboot complete */ | ||
113 | |||
114 | kSCEvent_Reboot = SC_EVENT_TYPE_TUPLE(SC_IRQ_GROUP_REBOOT, SC_EVENT_IRQ_DUMMY) /*!< Partition reboot starting */ | ||
115 | } sc_event_t; | ||
116 | |||
117 | /*! @brief SC Event callback function. | ||
118 | * | ||
119 | * The SC Event callback returns a status from the underlying layer. | ||
120 | * The status reflects the SC IRQ status got by sc_irq_status SCFW API. It's the bitmask of enabled IRQ in a group. | ||
121 | * Such as for kSCEvent_Reboot/kSCEvent_Rebooted event, if more than one partition reboot event is enabled, this status | ||
122 | * flag can be used to identify which partition the event comes from. Refer to SCFW API sc_irq_status for more details. | ||
123 | */ | ||
124 | typedef void (*sc_event_callback_t)(uint32_t status, void *userData); | ||
125 | |||
126 | /*! @brief SC Event Semaphore Wait function. | ||
127 | * | ||
128 | * The Semaphore Wait/Post function is used in RTOS envirnoment to pass Semaphore Wait/Post function into SC Event | ||
129 | * driver. Unused in baremetal envirnonment. The task can wait the event by calling SCEvent_WaitEvent function. | ||
130 | */ | ||
131 | typedef status_t (*sc_event_sema4_wait_t)(void *sem, uint32_t timeout); | ||
132 | |||
133 | /*! @brief SC Event Semaphore Post function. | ||
134 | * | ||
135 | * The Semaphore Wait/Post function is used in RTOS envirnoment to pass Semaphore Wait/Post function into SC Event | ||
136 | * driver. Unused in baremetal envirnonment. The post function is called to give semaphore if event triggered in IRQ. | ||
137 | */ | ||
138 | typedef void (*sc_event_sema4_post_t)(void *sem); | ||
139 | |||
140 | /** | ||
141 | * @brief SC Event list fields | ||
142 | */ | ||
143 | typedef struct _sc_event_list | ||
144 | { | ||
145 | struct _sc_event_list *prev; /*!< previous list node */ | ||
146 | struct _sc_event_list *next; /*!< next list node */ | ||
147 | } sc_event_list_t; | ||
148 | |||
149 | /*! @brief SC Event handler structure. */ | ||
150 | struct _sc_event_handler | ||
151 | { | ||
152 | sc_event_list_t node; | ||
153 | sc_event_t event; /*!< Event type. */ | ||
154 | sc_event_callback_t callback; /*!< Event callback. */ | ||
155 | void *data; /*!< User data. */ | ||
156 | }; | ||
157 | |||
158 | /*! | ||
159 | * @brief SC Event handler is a pointer to the SC Event handler instance | ||
160 | */ | ||
161 | typedef struct _sc_event_handler *sc_event_handler_t; | ||
162 | /******************************************************************************* | ||
163 | * API | ||
164 | ******************************************************************************/ | ||
165 | |||
166 | #ifdef __cplusplus | ||
167 | extern "C" { | ||
168 | #endif | ||
169 | |||
170 | /*! | ||
171 | * @brief Initialize SC Event module. | ||
172 | |||
173 | * This function enable the IPC MU interrupt, setup to listen the event comes from SCU/SCFW. | ||
174 | * | ||
175 | * @param priority The SC IRQ interrupt priority. Once any SC IRQ enabled, the SCU will broadcast MU interrupt through | ||
176 | * the IPC MU to M4 cores. | ||
177 | * | ||
178 | * @retval None. | ||
179 | */ | ||
180 | void SCEvent_Init(uint8_t priority); | ||
181 | |||
182 | /*! | ||
183 | * @brief Deinitialize SC Event. | ||
184 | * | ||
185 | * This function disable the IPC MU interrupt. | ||
186 | * | ||
187 | */ | ||
188 | void SCEvent_Deinit(void); | ||
189 | |||
190 | /*! | ||
191 | * @brief Register SC Event handler. | ||
192 | |||
193 | * This function register the handler for the specified event. When the event is enabled by SCEvent_Config and happens, | ||
194 | * the callback will be called from SCEvent_process. More than one callback can be added for an event. | ||
195 | * But the total registered events are limited to | ||
196 | * SC_EVENT_HANDLER_MEM_POOL_SIZE/(sizeof(struct _sc_event_handler)). | ||
197 | * | ||
198 | * @param event The event to be registered with. | ||
199 | * @param callback The callback function. This function will be called from SCEvent_process. | ||
200 | * @param userData User defined callback function parameter. | ||
201 | * | ||
202 | * @retval SC Event handler. | ||
203 | */ | ||
204 | sc_event_handler_t SCEvent_RegisterEventHandler(sc_event_t event, sc_event_callback_t callback, void *userData); | ||
205 | |||
206 | /*! | ||
207 | * @brief Unregister SC Event handler. | ||
208 | |||
209 | * This function unregister and delete the given event handler. | ||
210 | * | ||
211 | * @param handler The SC Event handler to unregister. | ||
212 | * | ||
213 | * @retval none. | ||
214 | */ | ||
215 | void SCEvent_UnregisterEventHandler(sc_event_handler_t handler); | ||
216 | |||
217 | /*! | ||
218 | * @brief Configure SC Event. | ||
219 | |||
220 | * This function enables/disables response for the event comes from SCU/SCFW. | ||
221 | * | ||
222 | * @param event The event to be configured. | ||
223 | * @param enable Enable the event or not. | ||
224 | * @param pt Which partition the event comes from. Only applicable for partition reboot event: kSCEvent_Rebooted, | ||
225 | kSCEvent_Reboot. | ||
226 | * | ||
227 | * @retval kStatus_Success - Configure SC Event Successfully. | ||
228 | * @retval kStatus_Fail - Failed to configure SC Event. | ||
229 | */ | ||
230 | status_t SCEvent_Config(sc_event_t event, bool enable, uint32_t pt); | ||
231 | |||
232 | /*! | ||
233 | * @brief SCEvent Process function. | ||
234 | * | ||
235 | * This function is used to check SC event status and handle all the registered event handlers. The SCFW API call is | ||
236 | * a blocking call and used to check SC IRQ status, so this function should be executed in task context to make sure | ||
237 | * other event(interrupt) handled in time. In RTOS enviroment, application creats a task and wait for some events came | ||
238 | * using SCEvent_WaitEvent to run this function to handle the events. In baremetal enviroment, application need | ||
239 | * preiodically call this function to make sure the pending events handled. | ||
240 | */ | ||
241 | void SCEvent_Process(void); | ||
242 | |||
243 | /*! | ||
244 | * @brief Set Semaphore and Semaphore wait/post funciton in RTOS environment. | ||
245 | * | ||
246 | * The Semaphore Wait/Post function is used in RTOS envirnoment to pass Semaphore Wait/Post function into SC Event | ||
247 | * driver. Unused in baremetal envirnonment. The SCEvent_process will wait the Semaphore registered by | ||
248 | * SCEvent_SetWaitPostFunc until the event comes, and give the Semaphore, then it will handle the event and call the | ||
249 | * event handler's callback. | ||
250 | * | ||
251 | * @param wait Semaphore wait function. | ||
252 | * @param post Semaphore post function. | ||
253 | * @param sem Semaphore. | ||
254 | * @param timeout timeout. | ||
255 | * | ||
256 | * @retval kStatus_Success if succeed, kStatus_Timeout if timeout. | ||
257 | */ | ||
258 | status_t SCEvent_WaitEvent(sc_event_sema4_wait_t wait, sc_event_sema4_post_t post, void *sem, uint32_t timeout); | ||
259 | |||
260 | #ifdef __cplusplus | ||
261 | } | ||
262 | #endif | ||
263 | |||
264 | /*@}*/ | ||
265 | |||
266 | #endif /* _SC_EVENT_H_ */ | ||