diff options
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QX4/drivers/fsl_clock.c')
-rw-r--r-- | lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QX4/drivers/fsl_clock.c | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QX4/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QX4/drivers/fsl_clock.c new file mode 100644 index 000000000..e04fc7548 --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8QX4/drivers/fsl_clock.c | |||
@@ -0,0 +1,389 @@ | |||
1 | /* | ||
2 | * Copyright 2017-2019 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, (bool)1U, (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, (bool)0U, (bool)0U); | ||
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 | |||
162 | err = sc_pm_get_clock_rate(ipcHandle, SC_R_M4_0_PID0, SC_PM_CLK_PER, &freq); | ||
163 | if (err != SC_ERR_NONE) | ||
164 | { | ||
165 | freq = 0U; | ||
166 | } | ||
167 | |||
168 | return freq; | ||
169 | } | ||
170 | |||
171 | /*! | ||
172 | * brief Gets the clock frequency for a specific clock name. | ||
173 | * | ||
174 | * This function checks the current clock configurations and then calculates | ||
175 | * the clock frequency for a specific clock name defined in clock_name_t. | ||
176 | * | ||
177 | * param clockName Clock names defined in clock_name_t | ||
178 | * return Clock frequency value in hertz | ||
179 | */ | ||
180 | uint32_t CLOCK_GetFreq(clock_name_t name) | ||
181 | { | ||
182 | uint32_t freq; | ||
183 | |||
184 | switch (name) | ||
185 | { | ||
186 | case kCLOCK_CONECTIVITY_AhbClk: | ||
187 | freq = 167000000U; /* The CONNECTIVITY SS AHB clock is fixed to 167MHZ */ | ||
188 | break; | ||
189 | case kCLOCK_CoreSysClk: | ||
190 | freq = CLOCK_GetCoreSysClkFreq(); | ||
191 | break; | ||
192 | default: | ||
193 | freq = 0U; | ||
194 | break; | ||
195 | } | ||
196 | |||
197 | return freq; | ||
198 | } | ||
199 | |||
200 | /*! | ||
201 | * brief Set LPCG gate for specific LPCG. | ||
202 | * | ||
203 | * param regBase LPCG register base address. | ||
204 | * param swGate Software clock gating. 0: clock is gated; 1: clock is enabled | ||
205 | * param hwGate Hardware auto gating. 0: disable the HW clock gate control; 1: HW clock gating is enabled | ||
206 | * param bitsMask The available bits in LPCG register. Each bit indicate the corresponding bit is available or not. | ||
207 | */ | ||
208 | void CLOCK_SetLpcgGate(volatile uint32_t *regBase, bool swGate, bool hwGate, uint32_t bitsMask) | ||
209 | { | ||
210 | if (regBase != NULL) | ||
211 | { | ||
212 | if (swGate) | ||
213 | { | ||
214 | *regBase |= bitsMask & LPCG_CLK_SWEN_MASK; | ||
215 | } | ||
216 | else | ||
217 | { | ||
218 | *regBase &= ~(bitsMask & LPCG_CLK_SWEN_MASK); | ||
219 | } | ||
220 | |||
221 | if (hwGate) | ||
222 | { | ||
223 | *regBase |= bitsMask & LPCG_CLK_HWEN_MASK; | ||
224 | } | ||
225 | else | ||
226 | { | ||
227 | *regBase &= ~(bitsMask & LPCG_CLK_HWEN_MASK); | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | |||
232 | /*! | ||
233 | * brief Config the LPCG cell for specific IP. | ||
234 | * | ||
235 | * param name Which clock to enable, see \ref clock_ip_name_t. | ||
236 | * param swGate Software clock gating. 0: clock is gated; 1: clock is enabled | ||
237 | * param hwGate Hardware auto gating. 0: disable the HW clock gate control; 1: HW clock gating is enabled | ||
238 | */ | ||
239 | void CLOCK_ConfigLPCG(clock_ip_name_t name, bool swGate, bool hwGate) | ||
240 | { | ||
241 | volatile uint32_t *regBase; | ||
242 | |||
243 | regBase = LPCG_TUPLE_REG_BASE(name); | ||
244 | |||
245 | /* Return if LPCG Cell is not available. */ | ||
246 | if (regBase == NULL) | ||
247 | { | ||
248 | return; | ||
249 | } | ||
250 | |||
251 | /* Config the LPCG. LPCG Cells have different configurations per each clock target. */ | ||
252 | switch (name) | ||
253 | { | ||
254 | /* LPCG cell avalialbe bits field mask 0xBBAAAB, 0xBBAAAB (2 32-bits LPCG registers). */ | ||
255 | case kCLOCK_CONNECTIVITY_Enet0: | ||
256 | case kCLOCK_CONNECTIVITY_Enet1: | ||
257 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xBBAAABU); | ||
258 | CLOCK_SetLpcgGate(regBase + 0x1U, swGate, hwGate, 0xAU); | ||
259 | break; | ||
260 | |||
261 | /* LPCG cell avalialbe bits field mask 0xBAB0AAB.*/ | ||
262 | case kCLOCK_LSIO_Gpt0: | ||
263 | case kCLOCK_LSIO_Gpt1: | ||
264 | case kCLOCK_LSIO_Gpt2: | ||
265 | case kCLOCK_LSIO_Gpt3: | ||
266 | case kCLOCK_LSIO_Gpt4: | ||
267 | case kCLOCK_LSIO_Pwm0: | ||
268 | case kCLOCK_LSIO_Pwm1: | ||
269 | case kCLOCK_LSIO_Pwm2: | ||
270 | case kCLOCK_LSIO_Pwm3: | ||
271 | case kCLOCK_LSIO_Pwm4: | ||
272 | case kCLOCK_LSIO_Pwm5: | ||
273 | case kCLOCK_LSIO_Pwm6: | ||
274 | case kCLOCK_LSIO_Pwm7: | ||
275 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xBAB0AAB); | ||
276 | break; | ||
277 | |||
278 | /* LPCG cell avalialbe bits field mask 0xB0000.*/ | ||
279 | case kCLOCK_HSIO_Gpio: | ||
280 | case kCLOCK_LSIO_Gpio0: | ||
281 | case kCLOCK_LSIO_Gpio1: | ||
282 | case kCLOCK_LSIO_Gpio2: | ||
283 | case kCLOCK_LSIO_Gpio3: | ||
284 | case kCLOCK_LSIO_Gpio4: | ||
285 | case kCLOCK_LSIO_Gpio5: | ||
286 | case kCLOCK_LSIO_Gpio6: | ||
287 | case kCLOCK_LSIO_Gpio7: | ||
288 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xB0000U); | ||
289 | break; | ||
290 | /* LPCG cell avalialbe bits field mask 0xB000A. */ | ||
291 | case kCLOCK_AUDIO_Gpt0: | ||
292 | case kCLOCK_AUDIO_Gpt1: | ||
293 | case kCLOCK_AUDIO_Gpt2: | ||
294 | case kCLOCK_AUDIO_Gpt3: | ||
295 | case kCLOCK_AUDIO_Gpt4: | ||
296 | case kCLOCK_AUDIO_Gpt5: | ||
297 | case kCLOCK_LSIO_Mu5A: | ||
298 | case kCLOCK_LSIO_Mu6A: | ||
299 | case kCLOCK_LSIO_Mu7A: | ||
300 | case kCLOCK_LSIO_Mu8A: | ||
301 | case kCLOCK_LSIO_Mu9A: | ||
302 | case kCLOCK_LSIO_Mu10A: | ||
303 | case kCLOCK_LSIO_Mu11A: | ||
304 | case kCLOCK_LSIO_Mu12A: | ||
305 | case kCLOCK_LSIO_Mu13A: | ||
306 | case kCLOCK_LSIO_Mu5B: | ||
307 | case kCLOCK_LSIO_Mu6B: | ||
308 | case kCLOCK_LSIO_Mu7B: | ||
309 | case kCLOCK_LSIO_Mu8B: | ||
310 | case kCLOCK_LSIO_Mu9B: | ||
311 | case kCLOCK_LSIO_Mu10B: | ||
312 | case kCLOCK_LSIO_Mu11B: | ||
313 | case kCLOCK_LSIO_Mu12B: | ||
314 | case kCLOCK_LSIO_Mu13B: | ||
315 | case kCLOCK_AUDIO_Sai0: | ||
316 | case kCLOCK_AUDIO_Sai1: | ||
317 | case kCLOCK_AUDIO_Sai2: | ||
318 | case kCLOCK_AUDIO_Sai3: | ||
319 | case kCLOCK_AUDIO_Sai4: | ||
320 | case kCLOCK_AUDIO_Sai5: | ||
321 | case kCLOCK_AUDIO_Esai0: | ||
322 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xB000AU); | ||
323 | break; | ||
324 | |||
325 | /* LPCG cell avalialbe bits field mask 0xB000B. */ | ||
326 | case kCLOCK_DMA_Lpspi0: | ||
327 | case kCLOCK_DMA_Lpspi1: | ||
328 | case kCLOCK_DMA_Lpspi2: | ||
329 | case kCLOCK_DMA_Lpspi3: | ||
330 | case kCLOCK_DMA_Lpuart0: | ||
331 | case kCLOCK_DMA_Lpuart1: | ||
332 | case kCLOCK_DMA_Lpuart2: | ||
333 | case kCLOCK_DMA_Lpuart3: | ||
334 | case kCLOCK_DMA_Lpi2c0: | ||
335 | case kCLOCK_DMA_Lpi2c1: | ||
336 | case kCLOCK_DMA_Lpi2c2: | ||
337 | case kCLOCK_DMA_Lpi2c3: | ||
338 | case kCLOCK_DMA_Ftm0: | ||
339 | case kCLOCK_DMA_Ftm1: | ||
340 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xB000BU); | ||
341 | break; | ||
342 | |||
343 | /* LPCG cell avalialbe bits field mask 0xBB000B.*/ | ||
344 | case kCLOCK_DMA_Can0: | ||
345 | case kCLOCK_DMA_Can1: | ||
346 | case kCLOCK_DMA_Can2: | ||
347 | case kCLOCK_M4_0_Tpm: | ||
348 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xBB000B); | ||
349 | break; | ||
350 | |||
351 | /* LPCG cell avalialbe bits field mask 0xAB000A.*/ | ||
352 | case kCLOCK_CONNECTIVITY_Usdhc0: | ||
353 | case kCLOCK_CONNECTIVITY_Usdhc1: | ||
354 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xAB000A); | ||
355 | break; | ||
356 | |||
357 | /* LPCG cell avalialbe bits field mask 0xBAA000A.*/ | ||
358 | case kCLOCK_LSIO_Flexspi0: | ||
359 | case kCLOCK_LSIO_Flexspi1: | ||
360 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xBAA000A); | ||
361 | break; | ||
362 | |||
363 | /* LPCG cells avalialbe bits field mask 0xAA, 0xAB0000.*/ | ||
364 | case kCLOCK_Dpu0: | ||
365 | CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xAA); | ||
366 | CLOCK_SetLpcgGate(regBase + 0x5U, swGate, hwGate, 0xAB0000); | ||
367 | break; | ||
368 | |||
369 | /* LPCG cell avalialbe bits field mask 0xB000B.*/ | ||
370 | case kCLOCK_DiMiPiDsiLvds0Lpi2c0: | ||
371 | case kCLOCK_DiMiPiDsiLvds1Lpi2c0: | ||
372 | CLOCK_SetLpcgGate(regBase + 0x4U, swGate, hwGate, 0xB000B); | ||
373 | break; | ||
374 | |||
375 | /* LPCG cell does not config due to LPCG back to back write protection. */ | ||
376 | case kCLOCK_M4_0_Lpit: | ||
377 | case kCLOCK_M4_0_Lpuart: | ||
378 | case kCLOCK_M4_0_Lpi2c: | ||
379 | case kCLOCK_SCU_Lpit: | ||
380 | case kCLOCK_SCU_Lpuart: | ||
381 | case kCLOCK_SCU_Lpi2c: | ||
382 | break; | ||
383 | |||
384 | /* LPCG cell is not avaliable or is not supported by this function. */ | ||
385 | default: | ||
386 | assert(false); | ||
387 | break; | ||
388 | } | ||
389 | } | ||