diff options
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/K32L3A60/drivers/fsl_clock.c')
-rw-r--r-- | lib/chibios-contrib/ext/mcux-sdk/devices/K32L3A60/drivers/fsl_clock.c | 855 |
1 files changed, 855 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/K32L3A60/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/K32L3A60/drivers/fsl_clock.c new file mode 100644 index 000000000..c1f95c029 --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/K32L3A60/drivers/fsl_clock.c | |||
@@ -0,0 +1,855 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015, Freescale Semiconductor, Inc. | ||
3 | * Copyright 2016 - 2017 , NXP | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * SPDX-License-Identifier: BSD-3-Clause | ||
7 | */ | ||
8 | |||
9 | #include "fsl_clock.h" | ||
10 | |||
11 | /******************************************************************************* | ||
12 | * Definitions | ||
13 | ******************************************************************************/ | ||
14 | /* Component ID definition, used by tools. */ | ||
15 | #ifndef FSL_COMPONENT_ID | ||
16 | #define FSL_COMPONENT_ID "platform.drivers.clock" | ||
17 | #endif | ||
18 | |||
19 | #define SCG_SIRC_LOW_RANGE_FREQ 2000000U /* Slow IRC low range clock frequency. */ | ||
20 | #define SCG_SIRC_HIGH_RANGE_FREQ 8000000U /* Slow IRC high range clock frequency. */ | ||
21 | |||
22 | #define SCG_FIRC_FREQ0 48000000U /* Fast IRC trimed clock frequency(48MHz). */ | ||
23 | #define SCG_FIRC_FREQ1 52000000U /* Fast IRC trimed clock frequency(52MHz). */ | ||
24 | #define SCG_FIRC_FREQ2 56000000U /* Fast IRC trimed clock frequency(56MHz). */ | ||
25 | #define SCG_FIRC_FREQ3 60000000U /* Fast IRC trimed clock frequency(60MHz). */ | ||
26 | |||
27 | #define SCG_LPFLL_FREQ0 48000000U /* LPFLL trimed clock frequency(48MHz). */ | ||
28 | #define SCG_LPFLL_FREQ1 72000000U /* LPFLL trimed clock frequency(72MHz). */ | ||
29 | #define SCG_LPFLL_FREQ2 96000000U /* LPFLL trimed clock frequency(96MHz). */ | ||
30 | #define SCG_LPFLL_FREQ3 120000000U /* LPFLL trimed clock frequency(120MHz). */ | ||
31 | |||
32 | #define SCG_CSR_SCS_VAL ((SCG->CSR & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT) | ||
33 | #define SCG_SOSCDIV_SOSCDIV1_VAL ((SCG->SOSCDIV & SCG_SOSCDIV_SOSCDIV1_MASK) >> SCG_SOSCDIV_SOSCDIV1_SHIFT) | ||
34 | #define SCG_SOSCDIV_SOSCDIV2_VAL ((SCG->SOSCDIV & SCG_SOSCDIV_SOSCDIV2_MASK) >> SCG_SOSCDIV_SOSCDIV2_SHIFT) | ||
35 | #define SCG_SOSCDIV_SOSCDIV3_VAL ((SCG->SOSCDIV & SCG_SOSCDIV_SOSCDIV3_MASK) >> SCG_SOSCDIV_SOSCDIV3_SHIFT) | ||
36 | #define SCG_SIRCDIV_SIRCDIV1_VAL ((SCG->SIRCDIV & SCG_SIRCDIV_SIRCDIV1_MASK) >> SCG_SIRCDIV_SIRCDIV1_SHIFT) | ||
37 | #define SCG_SIRCDIV_SIRCDIV2_VAL ((SCG->SIRCDIV & SCG_SIRCDIV_SIRCDIV2_MASK) >> SCG_SIRCDIV_SIRCDIV2_SHIFT) | ||
38 | #define SCG_SIRCDIV_SIRCDIV3_VAL ((SCG->SIRCDIV & SCG_SIRCDIV_SIRCDIV3_MASK) >> SCG_SIRCDIV_SIRCDIV3_SHIFT) | ||
39 | #define SCG_FIRCDIV_FIRCDIV1_VAL ((SCG->FIRCDIV & SCG_FIRCDIV_FIRCDIV1_MASK) >> SCG_FIRCDIV_FIRCDIV1_SHIFT) | ||
40 | #define SCG_FIRCDIV_FIRCDIV2_VAL ((SCG->FIRCDIV & SCG_FIRCDIV_FIRCDIV2_MASK) >> SCG_FIRCDIV_FIRCDIV2_SHIFT) | ||
41 | #define SCG_FIRCDIV_FIRCDIV3_VAL ((SCG->FIRCDIV & SCG_FIRCDIV_FIRCDIV3_MASK) >> SCG_FIRCDIV_FIRCDIV3_SHIFT) | ||
42 | |||
43 | #define SCG_LPFLLDIV_LPFLLDIV1_VAL ((SCG->LPFLLDIV & SCG_LPFLLDIV_LPFLLDIV1_MASK) >> SCG_LPFLLDIV_LPFLLDIV1_SHIFT) | ||
44 | #define SCG_LPFLLDIV_LPFLLDIV2_VAL ((SCG->LPFLLDIV & SCG_LPFLLDIV_LPFLLDIV2_MASK) >> SCG_LPFLLDIV_LPFLLDIV2_SHIFT) | ||
45 | #define SCG_LPFLLDIV_LPFLLDIV3_VAL ((SCG->LPFLLDIV & SCG_LPFLLDIV_LPFLLDIV3_MASK) >> SCG_LPFLLDIV_LPFLLDIV3_SHIFT) | ||
46 | |||
47 | #define SCG_SIRCCFG_RANGE_VAL ((SCG->SIRCCFG & SCG_SIRCCFG_RANGE_MASK) >> SCG_SIRCCFG_RANGE_SHIFT) | ||
48 | #define SCG_FIRCCFG_RANGE_VAL ((SCG->FIRCCFG & SCG_FIRCCFG_RANGE_MASK) >> SCG_FIRCCFG_RANGE_SHIFT) | ||
49 | |||
50 | #define SCG_LPFLLCFG_FSEL_VAL ((SCG->LPFLLCFG & SCG_LPFLLCFG_FSEL_MASK) >> SCG_LPFLLCFG_FSEL_SHIFT) | ||
51 | |||
52 | /* Get the value of each field in PCC register. */ | ||
53 | #define PCC_PCS_VAL(reg) (((reg)&PCC_CLKCFG_PCS_MASK) >> PCC_CLKCFG_PCS_SHIFT) | ||
54 | #define PCC_FRAC_VAL(reg) (((reg)&PCC_CLKCFG_FRAC_MASK) >> PCC_CLKCFG_FRAC_SHIFT) | ||
55 | #define PCC_PCD_VAL(reg) (((reg)&PCC_CLKCFG_PCD_MASK) >> PCC_CLKCFG_PCD_SHIFT) | ||
56 | |||
57 | /******************************************************************************* | ||
58 | * Variables | ||
59 | ******************************************************************************/ | ||
60 | |||
61 | /* External XTAL0 (OSC0) clock frequency. */ | ||
62 | volatile uint32_t g_xtal0Freq; | ||
63 | /* External XTAL32K clock frequency. */ | ||
64 | volatile uint32_t g_xtal32Freq; | ||
65 | |||
66 | /******************************************************************************* | ||
67 | * Prototypes | ||
68 | ******************************************************************************/ | ||
69 | |||
70 | /******************************************************************************* | ||
71 | * Code | ||
72 | ******************************************************************************/ | ||
73 | |||
74 | /*! | ||
75 | * brief Get the OSC 32K clock frequency (OSC32KCLK). | ||
76 | * | ||
77 | * return Clock frequency in Hz. | ||
78 | */ | ||
79 | uint32_t CLOCK_GetOsc32kClkFreq(void) | ||
80 | { | ||
81 | assert(g_xtal32Freq); | ||
82 | return g_xtal32Freq; | ||
83 | } | ||
84 | |||
85 | /*! | ||
86 | * brief Get the flash clock frequency. | ||
87 | * | ||
88 | * return Clock frequency in Hz. | ||
89 | */ | ||
90 | uint32_t CLOCK_GetFlashClkFreq(void) | ||
91 | { | ||
92 | return CLOCK_GetSysClkFreq(kSCG_SysClkSlow); | ||
93 | } | ||
94 | |||
95 | /*! | ||
96 | * brief Get the bus clock frequency. | ||
97 | * | ||
98 | * return Clock frequency in Hz. | ||
99 | */ | ||
100 | uint32_t CLOCK_GetBusClkFreq(void) | ||
101 | { | ||
102 | return CLOCK_GetSysClkFreq(kSCG_SysClkSlow); | ||
103 | } | ||
104 | |||
105 | /*! | ||
106 | * brief Get the platform clock frequency. | ||
107 | * | ||
108 | * return Clock frequency in Hz. | ||
109 | */ | ||
110 | uint32_t CLOCK_GetPlatClkFreq(void) | ||
111 | { | ||
112 | return CLOCK_GetSysClkFreq(kSCG_SysClkCore); | ||
113 | } | ||
114 | |||
115 | /*! | ||
116 | * brief Get the core clock or system clock frequency. | ||
117 | * | ||
118 | * return Clock frequency in Hz. | ||
119 | */ | ||
120 | uint32_t CLOCK_GetCoreSysClkFreq(void) | ||
121 | { | ||
122 | return CLOCK_GetSysClkFreq(kSCG_SysClkCore); | ||
123 | } | ||
124 | |||
125 | /*! | ||
126 | * brief Get the external clock frequency (EXTCLK). | ||
127 | * | ||
128 | * return Clock frequency in Hz. | ||
129 | */ | ||
130 | uint32_t CLOCK_GetExtClkFreq(void) | ||
131 | { | ||
132 | return CLOCK_GetSysClkFreq(kSCG_SysClkExt); | ||
133 | } | ||
134 | |||
135 | /*! | ||
136 | * brief Gets the clock frequency for a specific clock name. | ||
137 | * | ||
138 | * This function checks the current clock configurations and then calculates | ||
139 | * the clock frequency for a specific clock name defined in clock_name_t. | ||
140 | * | ||
141 | * param clockName Clock names defined in clock_name_t | ||
142 | * return Clock frequency value in hertz | ||
143 | */ | ||
144 | uint32_t CLOCK_GetFreq(clock_name_t clockName) | ||
145 | { | ||
146 | uint32_t freq; | ||
147 | |||
148 | switch (clockName) | ||
149 | { | ||
150 | /* System layer clock. */ | ||
151 | case kCLOCK_CoreSysClk: | ||
152 | case kCLOCK_PlatClk: | ||
153 | freq = CLOCK_GetSysClkFreq(kSCG_SysClkCore); | ||
154 | break; | ||
155 | case kCLOCK_BusClk: | ||
156 | freq = CLOCK_GetSysClkFreq(kSCG_SysClkBus); | ||
157 | break; | ||
158 | case kCLOCK_FlashClk: | ||
159 | freq = CLOCK_GetSysClkFreq(kSCG_SysClkSlow); | ||
160 | break; | ||
161 | case kCLOCK_ExtClk: | ||
162 | freq = CLOCK_GetSysClkFreq(kSCG_SysClkExt); | ||
163 | break; | ||
164 | case kCLOCK_ScgSircClk: | ||
165 | freq = CLOCK_GetSircFreq(); | ||
166 | break; | ||
167 | case kCLOCK_ScgFircClk: | ||
168 | freq = CLOCK_GetFircFreq(); | ||
169 | break; | ||
170 | case kCLOCK_ScgLpFllClk: | ||
171 | freq = CLOCK_GetLpFllFreq(); | ||
172 | break; | ||
173 | |||
174 | /* SIRC div clock. */ | ||
175 | case kCLOCK_ScgSircAsyncDiv1Clk: | ||
176 | freq = CLOCK_GetSircAsyncFreq(kSCG_AsyncDiv1Clk); | ||
177 | break; | ||
178 | case kCLOCK_ScgSircAsyncDiv2Clk: | ||
179 | freq = CLOCK_GetSircAsyncFreq(kSCG_AsyncDiv2Clk); | ||
180 | break; | ||
181 | case kCLOCK_ScgSircAsyncDiv3Clk: | ||
182 | freq = CLOCK_GetSircAsyncFreq(kSCG_AsyncDiv3Clk); | ||
183 | break; | ||
184 | |||
185 | /* FIRC div clock. */ | ||
186 | case kCLOCK_ScgFircAsyncDiv1Clk: | ||
187 | freq = CLOCK_GetFircAsyncFreq(kSCG_AsyncDiv1Clk); | ||
188 | break; | ||
189 | case kCLOCK_ScgFircAsyncDiv2Clk: | ||
190 | freq = CLOCK_GetFircAsyncFreq(kSCG_AsyncDiv2Clk); | ||
191 | break; | ||
192 | case kCLOCK_ScgFircAsyncDiv3Clk: | ||
193 | freq = CLOCK_GetFircAsyncFreq(kSCG_AsyncDiv3Clk); | ||
194 | break; | ||
195 | |||
196 | /* LPFLL div clock. */ | ||
197 | case kCLOCK_ScgSysLpFllAsyncDiv1Clk: | ||
198 | freq = CLOCK_GetLpFllAsyncFreq(kSCG_AsyncDiv1Clk); | ||
199 | break; | ||
200 | case kCLOCK_ScgSysLpFllAsyncDiv2Clk: | ||
201 | freq = CLOCK_GetLpFllAsyncFreq(kSCG_AsyncDiv2Clk); | ||
202 | break; | ||
203 | case kCLOCK_ScgSysLpFllAsyncDiv3Clk: | ||
204 | freq = CLOCK_GetLpFllAsyncFreq(kSCG_AsyncDiv3Clk); | ||
205 | break; | ||
206 | |||
207 | /* Other clocks. */ | ||
208 | case kCLOCK_LpoClk: | ||
209 | freq = CLOCK_GetLpoClkFreq(); | ||
210 | break; | ||
211 | case kCLOCK_Osc32kClk: | ||
212 | freq = CLOCK_GetOsc32kClkFreq(); | ||
213 | break; | ||
214 | default: | ||
215 | freq = 0U; | ||
216 | break; | ||
217 | } | ||
218 | return freq; | ||
219 | } | ||
220 | |||
221 | /*! | ||
222 | * brief Gets the functional clock frequency for a specific IP module. | ||
223 | * | ||
224 | * This function gets the IP module's functional clock frequency based on PCC | ||
225 | * registers. It is only used for the IP modules which could select clock source | ||
226 | * by PCC[PCS]. | ||
227 | * | ||
228 | * param name Which peripheral to get, see \ref clock_ip_name_t. | ||
229 | * return Clock frequency value in Hz | ||
230 | */ | ||
231 | uint32_t CLOCK_GetIpFreq(clock_ip_name_t name) | ||
232 | { | ||
233 | uint32_t reg = (*(volatile uint32_t *)(uint32_t)name); | ||
234 | |||
235 | scg_async_clk_t asycClk; | ||
236 | uint32_t freq; | ||
237 | |||
238 | assert(reg & PCC_CLKCFG_PR_MASK); | ||
239 | |||
240 | switch (name) | ||
241 | { | ||
242 | case kCLOCK_Lpit0: | ||
243 | case kCLOCK_Lpit1: | ||
244 | asycClk = kSCG_AsyncDiv3Clk; | ||
245 | break; | ||
246 | case kCLOCK_Sdhc0: | ||
247 | case kCLOCK_Usb0: | ||
248 | asycClk = kSCG_AsyncDiv1Clk; | ||
249 | break; | ||
250 | default: | ||
251 | asycClk = kSCG_AsyncDiv2Clk; | ||
252 | break; | ||
253 | } | ||
254 | |||
255 | switch (PCC_PCS_VAL(reg)) | ||
256 | { | ||
257 | case (uint8_t)kCLOCK_IpSrcSircAsync: | ||
258 | freq = CLOCK_GetSircAsyncFreq(asycClk); | ||
259 | break; | ||
260 | case (uint8_t)kCLOCK_IpSrcFircAsync: | ||
261 | freq = CLOCK_GetFircAsyncFreq(asycClk); | ||
262 | break; | ||
263 | case (uint8_t)kCLOCK_IpSrcLpFllAsync: | ||
264 | freq = CLOCK_GetLpFllAsyncFreq(asycClk); | ||
265 | break; | ||
266 | default: /* kCLOCK_IpSrcNoneOrExt. */ | ||
267 | freq = 0U; | ||
268 | break; | ||
269 | } | ||
270 | |||
271 | if (0U != (reg & (PCC_CLKCFG_PCD_MASK | PCC_CLKCFG_FRAC_MASK))) | ||
272 | { | ||
273 | return freq * (PCC_FRAC_VAL(reg) + 1U) / (PCC_PCD_VAL(reg) + 1U); | ||
274 | } | ||
275 | else | ||
276 | { | ||
277 | return freq; | ||
278 | } | ||
279 | } | ||
280 | |||
281 | /*! brief Enable USB FS clock. | ||
282 | * | ||
283 | * param src USB FS clock source. | ||
284 | * param freq The frequency specified by src. | ||
285 | * retval true The clock is set successfully. | ||
286 | * retval false The clock source is invalid to get proper USB FS clock. | ||
287 | */ | ||
288 | bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) | ||
289 | { | ||
290 | bool ret = true; | ||
291 | |||
292 | CLOCK_SetIpSrc(kCLOCK_Usb0, kCLOCK_IpSrcFircAsync); | ||
293 | |||
294 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) | ||
295 | /* Enable clock gate. */ | ||
296 | CLOCK_EnableClock(kCLOCK_Usb0); | ||
297 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ | ||
298 | |||
299 | USBVREG->CTRL |= USBVREG_CTRL_EN_MASK; | ||
300 | USB0->CONTROL &= (uint8_t)(~USB_CONTROL_DPPULLUPNONOTG_MASK); | ||
301 | |||
302 | if (kCLOCK_UsbSrcIrc48M == src) | ||
303 | { | ||
304 | USB0->CLK_RECOVER_IRC_EN = 0x03U; | ||
305 | USB0->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK; | ||
306 | USB0->CLK_RECOVER_INT_EN = 0x00U; | ||
307 | } | ||
308 | return ret; | ||
309 | } | ||
310 | |||
311 | /*! | ||
312 | * brief Gets the SCG system clock frequency. | ||
313 | * | ||
314 | * This function gets the SCG system clock frequency. These clocks are used for | ||
315 | * core, platform, external, and bus clock domains. | ||
316 | * | ||
317 | * param type Which type of clock to get, core clock or slow clock. | ||
318 | * return Clock frequency. | ||
319 | */ | ||
320 | uint32_t CLOCK_GetSysClkFreq(scg_sys_clk_t type) | ||
321 | { | ||
322 | uint32_t freq; | ||
323 | |||
324 | scg_sys_clk_config_t sysClkConfig; | ||
325 | |||
326 | CLOCK_GetCurSysClkConfig(&sysClkConfig); /* Get the main clock for SoC platform. */ | ||
327 | |||
328 | switch (sysClkConfig.src) | ||
329 | { | ||
330 | case (uint8_t)kSCG_SysClkSrcSirc: | ||
331 | freq = CLOCK_GetSircFreq(); | ||
332 | break; | ||
333 | case (uint8_t)kSCG_SysClkSrcFirc: | ||
334 | freq = CLOCK_GetFircFreq(); | ||
335 | break; | ||
336 | case (uint8_t)kSCG_SysClkSrcRosc: | ||
337 | freq = CLOCK_GetRtcOscFreq(); | ||
338 | break; | ||
339 | case (uint8_t)kSCG_SysClkSrcLpFll: | ||
340 | freq = CLOCK_GetLpFllFreq(); | ||
341 | break; | ||
342 | default: | ||
343 | freq = 0U; | ||
344 | break; | ||
345 | } | ||
346 | |||
347 | freq /= (sysClkConfig.divCore + 1U); /* divided by the DIVCORE firstly. */ | ||
348 | |||
349 | if (kSCG_SysClkSlow == type) | ||
350 | { | ||
351 | freq /= (sysClkConfig.divSlow + 1U); | ||
352 | } | ||
353 | else if (kSCG_SysClkBus == type) | ||
354 | { | ||
355 | freq /= (sysClkConfig.divBus + 1U); | ||
356 | } | ||
357 | else if (kSCG_SysClkExt == type) | ||
358 | { | ||
359 | freq /= (sysClkConfig.divExt + 1U); | ||
360 | } | ||
361 | else | ||
362 | { | ||
363 | /* Add comment to prevent the case of rule 15.7. */ | ||
364 | } | ||
365 | |||
366 | return freq; | ||
367 | } | ||
368 | |||
369 | /*! | ||
370 | * brief Initializes the SCG slow IRC clock. | ||
371 | * | ||
372 | * This function enables the SCG slow IRC clock according to the | ||
373 | * configuration. | ||
374 | * | ||
375 | * param config Pointer to the configuration structure. | ||
376 | * retval kStatus_Success SIRC is initialized. | ||
377 | * retval kStatus_SCG_Busy SIRC has been enabled and is used by system clock. | ||
378 | * retval kStatus_ReadOnly SIRC control register is locked. | ||
379 | * | ||
380 | * note This function can't detect whether the system OSC has been enabled and | ||
381 | * used by an IP. | ||
382 | */ | ||
383 | status_t CLOCK_InitSirc(const scg_sirc_config_t *config) | ||
384 | { | ||
385 | assert(config); | ||
386 | |||
387 | status_t status; | ||
388 | |||
389 | /* De-init the SIRC first. */ | ||
390 | status = CLOCK_DeinitSirc(); | ||
391 | |||
392 | if (kStatus_Success != status) | ||
393 | { | ||
394 | return status; | ||
395 | } | ||
396 | |||
397 | /* Now start to set up SIRC clock. */ | ||
398 | /* Step 1. Setup dividers. */ | ||
399 | SCG->SIRCDIV = | ||
400 | SCG_SIRCDIV_SIRCDIV1(config->div1) | SCG_SIRCDIV_SIRCDIV2(config->div2) | SCG_SIRCDIV_SIRCDIV3(config->div3); | ||
401 | |||
402 | /* Step 2. Set SIRC configuration. */ | ||
403 | SCG->SIRCCFG = SCG_SIRCCFG_RANGE(config->range); | ||
404 | |||
405 | /* Step 3. Enable clock. */ | ||
406 | SCG->SIRCCSR = SCG_SIRCCSR_SIRCEN_MASK | config->enableMode; | ||
407 | |||
408 | /* Step 4. Wait for SIRC clock to be valid. */ | ||
409 | while (0UL == (SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD_MASK)) | ||
410 | { | ||
411 | } | ||
412 | |||
413 | return kStatus_Success; | ||
414 | } | ||
415 | |||
416 | /*! | ||
417 | * brief De-initializes the SCG slow IRC. | ||
418 | * | ||
419 | * This function disables the SCG slow IRC. | ||
420 | * | ||
421 | * retval kStatus_Success SIRC is deinitialized. | ||
422 | * retval kStatus_SCG_Busy SIRC is used by system clock. | ||
423 | * retval kStatus_ReadOnly SIRC control register is locked. | ||
424 | * | ||
425 | * note This function can't detect whether the SIRC is used by an IP. | ||
426 | */ | ||
427 | status_t CLOCK_DeinitSirc(void) | ||
428 | { | ||
429 | uint32_t reg = SCG->SIRCCSR; | ||
430 | |||
431 | /* If clock is used by system, return error. */ | ||
432 | if ((reg & SCG_SIRCCSR_SIRCSEL_MASK) != 0UL) | ||
433 | { | ||
434 | return kStatus_SCG_Busy; | ||
435 | } | ||
436 | |||
437 | /* If configure register is locked, return error. */ | ||
438 | if ((reg & SCG_SIRCCSR_LK_MASK) != 0UL) | ||
439 | { | ||
440 | return kStatus_ReadOnly; | ||
441 | } | ||
442 | |||
443 | SCG->SIRCCSR = 0U; | ||
444 | |||
445 | return kStatus_Success; | ||
446 | } | ||
447 | |||
448 | /*! | ||
449 | * brief Gets the SCG SIRC clock frequency. | ||
450 | * | ||
451 | * return Clock frequency; If the clock is invalid, returns 0. | ||
452 | */ | ||
453 | uint32_t CLOCK_GetSircFreq(void) | ||
454 | { | ||
455 | static const uint32_t sircFreq[] = {SCG_SIRC_LOW_RANGE_FREQ, SCG_SIRC_HIGH_RANGE_FREQ}; | ||
456 | |||
457 | if ((SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD_MASK) != 0UL) /* SIRC is valid. */ | ||
458 | { | ||
459 | return sircFreq[SCG_SIRCCFG_RANGE_VAL]; | ||
460 | } | ||
461 | else | ||
462 | { | ||
463 | return 0U; | ||
464 | } | ||
465 | } | ||
466 | |||
467 | /*! | ||
468 | * brief Gets the SCG asynchronous clock frequency from the SIRC. | ||
469 | * | ||
470 | * param type The asynchronous clock type. | ||
471 | * return Clock frequency; If the clock is invalid, returns 0. | ||
472 | */ | ||
473 | uint32_t CLOCK_GetSircAsyncFreq(scg_async_clk_t type) | ||
474 | { | ||
475 | uint32_t sircFreq = CLOCK_GetSircFreq(); | ||
476 | uint32_t divider = 0U; | ||
477 | |||
478 | /* Get divider. */ | ||
479 | if (sircFreq != 0UL) | ||
480 | { | ||
481 | switch (type) | ||
482 | { | ||
483 | case kSCG_AsyncDiv3Clk: /* SIRCDIV3_CLK. */ | ||
484 | divider = SCG_SIRCDIV_SIRCDIV3_VAL; | ||
485 | break; | ||
486 | case kSCG_AsyncDiv2Clk: /* SIRCDIV2_CLK. */ | ||
487 | divider = SCG_SIRCDIV_SIRCDIV2_VAL; | ||
488 | break; | ||
489 | case kSCG_AsyncDiv1Clk: /* SIRCDIV2_CLK. */ | ||
490 | divider = SCG_SIRCDIV_SIRCDIV1_VAL; | ||
491 | break; | ||
492 | default: | ||
493 | divider = 0U; | ||
494 | break; | ||
495 | } | ||
496 | } | ||
497 | if (divider != 0U) | ||
498 | { | ||
499 | return sircFreq >> (divider - 1U); | ||
500 | } | ||
501 | else /* Output disabled. */ | ||
502 | { | ||
503 | return 0U; | ||
504 | } | ||
505 | } | ||
506 | |||
507 | /*! | ||
508 | * brief Initializes the SCG fast IRC clock. | ||
509 | * | ||
510 | * This function enables the SCG fast IRC clock according to the configuration. | ||
511 | * | ||
512 | * param config Pointer to the configuration structure. | ||
513 | * retval kStatus_Success FIRC is initialized. | ||
514 | * retval kStatus_SCG_Busy FIRC has been enabled and is used by the system clock. | ||
515 | * retval kStatus_ReadOnly FIRC control register is locked. | ||
516 | * | ||
517 | * note This function can't detect whether the FIRC has been enabled and | ||
518 | * used by an IP. | ||
519 | */ | ||
520 | status_t CLOCK_InitFirc(const scg_firc_config_t *config) | ||
521 | { | ||
522 | assert(config); | ||
523 | |||
524 | status_t status; | ||
525 | |||
526 | /* De-init the FIRC first. */ | ||
527 | status = CLOCK_DeinitFirc(); | ||
528 | |||
529 | if (kStatus_Success != status) | ||
530 | { | ||
531 | return status; | ||
532 | } | ||
533 | |||
534 | /* Now start to set up FIRC clock. */ | ||
535 | /* Step 1. Setup dividers. */ | ||
536 | SCG->FIRCDIV = | ||
537 | SCG_FIRCDIV_FIRCDIV1(config->div1) | SCG_FIRCDIV_FIRCDIV2(config->div2) | SCG_FIRCDIV_FIRCDIV3(config->div3); | ||
538 | |||
539 | /* Step 2. Set FIRC configuration. */ | ||
540 | SCG->FIRCCFG = SCG_FIRCCFG_RANGE(config->range); | ||
541 | |||
542 | /* Step 3. Set trimming configuration. */ | ||
543 | if ((config->trimConfig) != NULL) | ||
544 | { | ||
545 | SCG->FIRCTCFG = SCG_FIRCTCFG_TRIMSRC(config->trimConfig->trimSrc); | ||
546 | |||
547 | /* TODO: Write FIRCSTAT cause bus error: TKT266932. */ | ||
548 | if (kSCG_FircTrimNonUpdate == config->trimConfig->trimMode) | ||
549 | { | ||
550 | SCG->FIRCSTAT = SCG_FIRCSTAT_TRIMCOAR(config->trimConfig->trimCoar) | | ||
551 | SCG_FIRCSTAT_TRIMFINE(config->trimConfig->trimFine); | ||
552 | } | ||
553 | |||
554 | /* trim mode. */ | ||
555 | SCG->FIRCCSR = (uint32_t)(config->trimConfig->trimMode); | ||
556 | |||
557 | if ((SCG->FIRCCSR & SCG_FIRCCSR_FIRCERR_MASK) != 0U) | ||
558 | { | ||
559 | return kStatus_Fail; | ||
560 | } | ||
561 | } | ||
562 | |||
563 | /* Step 4. Enable clock. */ | ||
564 | SCG->FIRCCSR |= (SCG_FIRCCSR_FIRCEN_MASK | SCG_FIRCCSR_FIRCTREN_MASK | config->enableMode); | ||
565 | |||
566 | /* Step 5. Wait for FIRC clock to be valid. */ | ||
567 | while (0U == (SCG->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK)) | ||
568 | { | ||
569 | } | ||
570 | |||
571 | return kStatus_Success; | ||
572 | } | ||
573 | |||
574 | /*! | ||
575 | * brief De-initializes the SCG fast IRC. | ||
576 | * | ||
577 | * This function disables the SCG fast IRC. | ||
578 | * | ||
579 | * retval kStatus_Success FIRC is deinitialized. | ||
580 | * retval kStatus_SCG_Busy FIRC is used by the system clock. | ||
581 | * retval kStatus_ReadOnly FIRC control register is locked. | ||
582 | * | ||
583 | * note This function can't detect whether the FIRC is used by an IP. | ||
584 | */ | ||
585 | status_t CLOCK_DeinitFirc(void) | ||
586 | { | ||
587 | uint32_t reg = SCG->FIRCCSR; | ||
588 | |||
589 | /* If clock is used by system, return error. */ | ||
590 | if ((reg & SCG_FIRCCSR_FIRCSEL_MASK) != 0UL) | ||
591 | { | ||
592 | return kStatus_SCG_Busy; | ||
593 | } | ||
594 | |||
595 | /* If configure register is locked, return error. */ | ||
596 | if ((reg & SCG_FIRCCSR_LK_MASK) != 0UL) | ||
597 | { | ||
598 | return kStatus_ReadOnly; | ||
599 | } | ||
600 | |||
601 | SCG->FIRCCSR = SCG_FIRCCSR_FIRCERR_MASK; | ||
602 | |||
603 | return kStatus_Success; | ||
604 | } | ||
605 | |||
606 | /*! | ||
607 | * brief Gets the SCG FIRC clock frequency. | ||
608 | * | ||
609 | * return Clock frequency; If the clock is invalid, returns 0. | ||
610 | */ | ||
611 | uint32_t CLOCK_GetFircFreq(void) | ||
612 | { | ||
613 | static const uint32_t fircFreq[] = { | ||
614 | SCG_FIRC_FREQ0, | ||
615 | SCG_FIRC_FREQ1, | ||
616 | SCG_FIRC_FREQ2, | ||
617 | SCG_FIRC_FREQ3, | ||
618 | }; | ||
619 | |||
620 | if ((SCG->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK) != 0UL) /* FIRC is valid. */ | ||
621 | { | ||
622 | return fircFreq[SCG_FIRCCFG_RANGE_VAL]; | ||
623 | } | ||
624 | else | ||
625 | { | ||
626 | return 0U; | ||
627 | } | ||
628 | } | ||
629 | |||
630 | /*! | ||
631 | * brief Gets the SCG asynchronous clock frequency from the FIRC. | ||
632 | * | ||
633 | * param type The asynchronous clock type. | ||
634 | * return Clock frequency; If the clock is invalid, returns 0. | ||
635 | */ | ||
636 | uint32_t CLOCK_GetFircAsyncFreq(scg_async_clk_t type) | ||
637 | { | ||
638 | uint32_t fircFreq = CLOCK_GetFircFreq(); | ||
639 | uint32_t divider = 0U; | ||
640 | |||
641 | /* Get divider. */ | ||
642 | if (fircFreq != 0UL) | ||
643 | { | ||
644 | switch (type) | ||
645 | { | ||
646 | case kSCG_AsyncDiv3Clk: /* FIRCDIV3_CLK. */ | ||
647 | divider = SCG_FIRCDIV_FIRCDIV3_VAL; | ||
648 | break; | ||
649 | case kSCG_AsyncDiv2Clk: /* FIRCDIV2_CLK. */ | ||
650 | divider = SCG_FIRCDIV_FIRCDIV2_VAL; | ||
651 | break; | ||
652 | case kSCG_AsyncDiv1Clk: /* FIRCDIV1_CLK. */ | ||
653 | divider = SCG_FIRCDIV_FIRCDIV1_VAL; | ||
654 | break; | ||
655 | default: | ||
656 | divider = 0U; | ||
657 | break; | ||
658 | } | ||
659 | } | ||
660 | if (divider != 0UL) | ||
661 | { | ||
662 | return fircFreq >> (divider - 1U); | ||
663 | } | ||
664 | else /* Output disabled. */ | ||
665 | { | ||
666 | return 0U; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | /*! | ||
671 | * brief Gets the SCG RTC OSC clock frequency. | ||
672 | * | ||
673 | * return Clock frequency; If the clock is invalid, returns 0. | ||
674 | */ | ||
675 | uint32_t CLOCK_GetRtcOscFreq(void) | ||
676 | { | ||
677 | if ((SCG->ROSCCSR & SCG_ROSCCSR_ROSCVLD_MASK) != 0UL) /* RTC OSC clock is valid. */ | ||
678 | { | ||
679 | /* Please call CLOCK_SetXtal32Freq base on board setting before using RTC OSC clock. */ | ||
680 | assert(g_xtal32Freq); | ||
681 | return g_xtal32Freq; | ||
682 | } | ||
683 | else | ||
684 | { | ||
685 | return 0U; | ||
686 | } | ||
687 | } | ||
688 | |||
689 | /*! | ||
690 | * brief Initializes the SCG LPFLL clock. | ||
691 | * | ||
692 | * This function enables the SCG LPFLL clock according to the configuration. | ||
693 | * | ||
694 | * param config Pointer to the configuration structure. | ||
695 | * retval kStatus_Success LPFLL is initialized. | ||
696 | * retval kStatus_SCG_Busy LPFLL has been enabled and is used by the system clock. | ||
697 | * retval kStatus_ReadOnly LPFLL control register is locked. | ||
698 | * | ||
699 | * note This function can't detect whether the LPFLL has been enabled and | ||
700 | * used by an IP. | ||
701 | */ | ||
702 | status_t CLOCK_InitLpFll(const scg_lpfll_config_t *config) | ||
703 | { | ||
704 | assert(config); | ||
705 | |||
706 | status_t status; | ||
707 | |||
708 | /* De-init the LPFLL first. */ | ||
709 | status = CLOCK_DeinitLpFll(); | ||
710 | |||
711 | if (kStatus_Success != status) | ||
712 | { | ||
713 | return status; | ||
714 | } | ||
715 | |||
716 | /* Now start to set up LPFLL clock. */ | ||
717 | /* Step 1. Setup dividers. */ | ||
718 | SCG->LPFLLDIV = SCG_LPFLLDIV_LPFLLDIV1(config->div1) | SCG_LPFLLDIV_LPFLLDIV2(config->div2) | | ||
719 | SCG_LPFLLDIV_LPFLLDIV3(config->div3); | ||
720 | |||
721 | /* Step 2. Set LPFLL configuration. */ | ||
722 | SCG->LPFLLCFG = SCG_LPFLLCFG_FSEL(config->range); | ||
723 | |||
724 | /* Step 3. Set trimming configuration. */ | ||
725 | if ((config->trimConfig) != NULL) | ||
726 | { | ||
727 | SCG->LPFLLTCFG = SCG_LPFLLTCFG_TRIMDIV(config->trimConfig->trimDiv) | | ||
728 | SCG_LPFLLTCFG_TRIMSRC(config->trimConfig->trimSrc) | | ||
729 | SCG_LPFLLTCFG_LOCKW2LSB(config->trimConfig->lockMode); | ||
730 | |||
731 | if (kSCG_LpFllTrimNonUpdate == config->trimConfig->trimMode) | ||
732 | { | ||
733 | SCG->LPFLLSTAT = config->trimConfig->trimValue; | ||
734 | } | ||
735 | |||
736 | /* Trim mode. */ | ||
737 | SCG->LPFLLCSR = (uint32_t)(config->trimConfig->trimMode); | ||
738 | |||
739 | if ((SCG->LPFLLCSR & SCG_LPFLLCSR_LPFLLERR_MASK) != 0UL) | ||
740 | { | ||
741 | return kStatus_Fail; | ||
742 | } | ||
743 | } | ||
744 | |||
745 | /* Step 4. Enable clock. */ | ||
746 | SCG->LPFLLCSR |= ((uint32_t)SCG_LPFLLCSR_LPFLLEN_MASK | (uint32_t)config->enableMode); | ||
747 | |||
748 | /* Step 5. Wait for LPFLL clock to be valid. */ | ||
749 | while (0UL == (SCG->LPFLLCSR & SCG_LPFLLCSR_LPFLLVLD_MASK)) | ||
750 | { | ||
751 | } | ||
752 | |||
753 | /* Step 6. Wait for LPFLL trim lock. */ | ||
754 | if ((config->trimConfig != NULL) && (kSCG_LpFllTrimUpdate == config->trimConfig->trimMode)) | ||
755 | { | ||
756 | while (0UL == (SCG->LPFLLCSR & SCG_LPFLLCSR_LPFLLTRMLOCK_MASK)) | ||
757 | { | ||
758 | } | ||
759 | } | ||
760 | |||
761 | return kStatus_Success; | ||
762 | } | ||
763 | |||
764 | /*! | ||
765 | * brief De-initializes the SCG LPFLL. | ||
766 | * | ||
767 | * This function disables the SCG LPFLL. | ||
768 | * | ||
769 | * retval kStatus_Success LPFLL is deinitialized. | ||
770 | * retval kStatus_SCG_Busy LPFLL is used by the system clock. | ||
771 | * retval kStatus_ReadOnly LPFLL control register is locked. | ||
772 | * | ||
773 | * note This function can't detect whether the LPFLL is used by an IP. | ||
774 | */ | ||
775 | status_t CLOCK_DeinitLpFll(void) | ||
776 | { | ||
777 | uint32_t reg = SCG->LPFLLCSR; | ||
778 | |||
779 | /* If clock is used by system, return error. */ | ||
780 | if ((reg & SCG_LPFLLCSR_LPFLLSEL_MASK) != 0UL) | ||
781 | { | ||
782 | return kStatus_SCG_Busy; | ||
783 | } | ||
784 | |||
785 | /* If configure register is locked, return error. */ | ||
786 | if ((reg & SCG_LPFLLCSR_LK_MASK) != 0UL) | ||
787 | { | ||
788 | return kStatus_ReadOnly; | ||
789 | } | ||
790 | |||
791 | SCG->LPFLLCSR = SCG_LPFLLCSR_LPFLLERR_MASK; | ||
792 | |||
793 | return kStatus_Success; | ||
794 | } | ||
795 | |||
796 | /*! | ||
797 | * brief Gets the SCG LPFLL clock frequency. | ||
798 | * | ||
799 | * return Clock frequency in Hz; If the clock is invalid, returns 0. | ||
800 | */ | ||
801 | uint32_t CLOCK_GetLpFllFreq(void) | ||
802 | { | ||
803 | static const uint32_t lpfllFreq[] = { | ||
804 | SCG_LPFLL_FREQ0, | ||
805 | SCG_LPFLL_FREQ1, | ||
806 | SCG_LPFLL_FREQ2, | ||
807 | SCG_LPFLL_FREQ3, | ||
808 | }; | ||
809 | |||
810 | if ((SCG->LPFLLCSR & SCG_LPFLLCSR_LPFLLVLD_MASK) != 0UL) /* LPFLL is valid. */ | ||
811 | { | ||
812 | return lpfllFreq[SCG_LPFLLCFG_FSEL_VAL]; | ||
813 | } | ||
814 | else | ||
815 | { | ||
816 | return 0U; | ||
817 | } | ||
818 | } | ||
819 | |||
820 | /*! | ||
821 | * brief Gets the SCG asynchronous clock frequency from the LPFLL. | ||
822 | * | ||
823 | * param type The asynchronous clock type. | ||
824 | * return Clock frequency in Hz; If the clock is invalid, returns 0. | ||
825 | */ | ||
826 | uint32_t CLOCK_GetLpFllAsyncFreq(scg_async_clk_t type) | ||
827 | { | ||
828 | uint32_t lpfllFreq = CLOCK_GetLpFllFreq(); | ||
829 | uint32_t divider = 0U; | ||
830 | |||
831 | /* Get divider. */ | ||
832 | if (lpfllFreq != 0UL) | ||
833 | { | ||
834 | switch (type) | ||
835 | { | ||
836 | case kSCG_AsyncDiv2Clk: /* LPFLLDIV2_CLK. */ | ||
837 | divider = SCG_LPFLLDIV_LPFLLDIV2_VAL; | ||
838 | break; | ||
839 | case kSCG_AsyncDiv1Clk: /* LPFLLDIV1_CLK. */ | ||
840 | divider = SCG_LPFLLDIV_LPFLLDIV1_VAL; | ||
841 | break; | ||
842 | default: | ||
843 | divider = 0U; | ||
844 | break; | ||
845 | } | ||
846 | } | ||
847 | if (divider != 0U) | ||
848 | { | ||
849 | return lpfllFreq >> (divider - 1U); | ||
850 | } | ||
851 | else /* Output disabled. */ | ||
852 | { | ||
853 | return 0U; | ||
854 | } | ||
855 | } | ||