1 /*
2 * Copyright 2020-2023 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 /**
7 * @file Clock_Ip_Pll.c
8 * @version 3.0.0
9 *
10 * @brief CLOCK driver implementations.
11 * @details CLOCK driver implementations.
12 *
13 * @addtogroup CLOCK_DRIVER Clock Ip Driver
14 * @{
15 */
16
17 #ifdef __cplusplus
18 extern "C"{
19 #endif
20
21
22 /*==================================================================================================
23 * INCLUDE FILES
24 * 1) system and project includes
25 * 2) needed interfaces from external units
26 * 3) internal and external interfaces from this unit
27 ==================================================================================================*/
28
29 #include "Clock_Ip_Private.h"
30
31 /*==================================================================================================
32 SOURCE FILE VERSION INFORMATION
33 ==================================================================================================*/
34 #define CLOCK_IP_PLL_VENDOR_ID_C 43
35 #define CLOCK_IP_PLL_AR_RELEASE_MAJOR_VERSION_C 4
36 #define CLOCK_IP_PLL_AR_RELEASE_MINOR_VERSION_C 7
37 #define CLOCK_IP_PLL_AR_RELEASE_REVISION_VERSION_C 0
38 #define CLOCK_IP_PLL_SW_MAJOR_VERSION_C 3
39 #define CLOCK_IP_PLL_SW_MINOR_VERSION_C 0
40 #define CLOCK_IP_PLL_SW_PATCH_VERSION_C 0
41
42 /*==================================================================================================
43 * FILE VERSION CHECKS
44 ==================================================================================================*/
45 /* Check if Clock_Ip_Pll.c file and Clock_Ip_Private.h file are of the same vendor */
46 #if (CLOCK_IP_PLL_VENDOR_ID_C != CLOCK_IP_PRIVATE_VENDOR_ID)
47 #error "Clock_Ip_Pll.c and Clock_Ip_Private.h have different vendor ids"
48 #endif
49
50 /* Check if Clock_Ip_Pll.c file and Clock_Ip_Private.h file are of the same Autosar version */
51 #if ((CLOCK_IP_PLL_AR_RELEASE_MAJOR_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_MAJOR_VERSION) || \
52 (CLOCK_IP_PLL_AR_RELEASE_MINOR_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_MINOR_VERSION) || \
53 (CLOCK_IP_PLL_AR_RELEASE_REVISION_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_REVISION_VERSION) \
54 )
55 #error "AutoSar Version Numbers of Clock_Ip_Pll.c and Clock_Ip_Private.h are different"
56 #endif
57
58 /* Check if Clock_Ip_Pll.c file and Clock_Ip_Private.h file are of the same Software version */
59 #if ((CLOCK_IP_PLL_SW_MAJOR_VERSION_C != CLOCK_IP_PRIVATE_SW_MAJOR_VERSION) || \
60 (CLOCK_IP_PLL_SW_MINOR_VERSION_C != CLOCK_IP_PRIVATE_SW_MINOR_VERSION) || \
61 (CLOCK_IP_PLL_SW_PATCH_VERSION_C != CLOCK_IP_PRIVATE_SW_PATCH_VERSION) \
62 )
63 #error "Software Version Numbers of Clock_Ip_Pll.c and Clock_Ip_Private.h are different"
64 #endif
65
66 /*==================================================================================================
67 * LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
68 ==================================================================================================*/
69
70 /*==================================================================================================
71 * LOCAL MACROS
72 ==================================================================================================*/
73
74 /*==================================================================================================
75 * LOCAL CONSTANTS
76 ==================================================================================================*/
77
78 /*==================================================================================================
79 * LOCAL VARIABLES
80 ==================================================================================================*/
81
82 /*==================================================================================================
83 * GLOBAL CONSTANTS
84 ==================================================================================================*/
85
86 /*==================================================================================================
87 * GLOBAL VARIABLES
88 ==================================================================================================*/
89
90 /*==================================================================================================
91 * GLOBAL FUNCTION PROTOTYPES
92 ==================================================================================================*/
93 /* Clock start section code */
94 #define MCU_START_SEC_CODE
95
96 #include "Mcu_MemMap.h"
97
98 /*==================================================================================================
99 * LOCAL FUNCTION PROTOTYPES
100 ==================================================================================================*/
101
102
103 static void Clock_Ip_CallbackPllEmpty(Clock_Ip_PllConfigType const* Config);
104 static Clock_Ip_PllStatusReturnType Clock_Ip_CallbackPllEmptyComplete(Clock_Ip_NameType PllName);
105 static void Clock_Ip_CallbackPllEmptyDisable(Clock_Ip_NameType PllName);
106
107 #ifdef CLOCK_IP_PLL_RDIV_MFI_MFN_ODIV2_SDMEN_SSCGBYP_SPREADCTL_STEPNO_STEPSIZE
108 static void Clock_Ip_ResetPllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize(Clock_Ip_PllConfigType const* Config);
109 static void Clock_Ip_SetPllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize(Clock_Ip_PllConfigType const* Config);
110 static Clock_Ip_PllStatusReturnType Clock_Ip_CompletePllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize(Clock_Ip_NameType PllName);
111 static void Clock_Ip_EnablePllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize(Clock_Ip_PllConfigType const* Config);
112 #endif
113
114 #ifdef CLOCK_IP_PLL_RDIV_MFI_MFN_ODIV2_SDMEN
115 static void Clock_Ip_ResetPllRdivMfiMfnOdiv2Sdmen(Clock_Ip_PllConfigType const* Config);
116 static void Clock_Ip_SetPllRdivMfiMfnOdiv2Sdmen(Clock_Ip_PllConfigType const* Config);
117 static Clock_Ip_PllStatusReturnType Clock_Ip_CompletePllRdivMfiMfnOdiv2Sdmen(Clock_Ip_NameType PllName);
118 static void Clock_Ip_EnablePllRdivMfiMfnOdiv2Sdmen(Clock_Ip_PllConfigType const* Config);
119 #endif
120
121
122 /* Clock stop section code */
123 #define MCU_STOP_SEC_CODE
124
125 #include "Mcu_MemMap.h"
126
127 /*==================================================================================================
128 * LOCAL FUNCTIONS
129 ==================================================================================================*/
130
131 #define MCU_START_SEC_CODE
132 /* Clock start section code */
133
134 #include "Mcu_MemMap.h"
135
136
Clock_Ip_CallbackPllEmpty(Clock_Ip_PllConfigType const * Config)137 static void Clock_Ip_CallbackPllEmpty(Clock_Ip_PllConfigType const* Config)
138 {
139 (void)Config;
140 /* No implementation */
141 }
Clock_Ip_CallbackPllEmptyComplete(Clock_Ip_NameType PllName)142 static Clock_Ip_PllStatusReturnType Clock_Ip_CallbackPllEmptyComplete(Clock_Ip_NameType PllName)
143 {
144 (void)PllName;
145 /* No implementation */
146 return STATUS_PLL_LOCKED;
147 }
Clock_Ip_CallbackPllEmptyDisable(Clock_Ip_NameType PllName)148 static void Clock_Ip_CallbackPllEmptyDisable(Clock_Ip_NameType PllName)
149 {
150 (void)PllName;
151 /* No implementation */
152 }
153
154
155 /* Pll with frequency modulation and VCO clock post divider for driving the PHI output clocks */
156 #ifdef CLOCK_IP_PLL_RDIV_MFI_MFN_ODIV2_SDMEN_SSCGBYP_SPREADCTL_STEPNO_STEPSIZE
157 /* Recommended unlock control accuracy when frequency modulation is bypassed */
158 #define CLOCK_IP_RECOMMENTED_ULKCTL_BYPASSED_FM 0U
159 /* Recommended unlock control accuracy when frequency modulation is not bypassed */
160 #define CLOCK_IP_RECOMMENTED_ULKCTL_NOT_BYPASSED_FM 1U
Clock_Ip_ResetPllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize(Clock_Ip_PllConfigType const * Config)161 static void Clock_Ip_ResetPllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize(Clock_Ip_PllConfigType const* Config)
162 {
163 uint32 Instance;
164 uint8 DividerIndex;
165
166 if (NULL_PTR != Config)
167 {
168 Instance = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_MODULE_INSTANCE];
169
170 /* Disable output dividers */
171 for (DividerIndex = 0U; DividerIndex < Clock_Ip_apxPll[Instance].DivsNo; DividerIndex++)
172 {
173 Clock_Ip_apxPll[Instance].PllInstance->PLLODIV[DividerIndex] &= ~PLL_PLLODIV_DE_MASK;
174 }
175 /* Power down PLL */
176 Clock_Ip_apxPll[Instance].PllInstance->PLLCR |= PLL_PLLCR_PLLPD_MASK;
177 }
178 else
179 {
180 (void)Instance;
181 (void)DividerIndex;
182 }
183 }
Clock_Ip_SetPllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize(Clock_Ip_PllConfigType const * Config)184 static void Clock_Ip_SetPllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize(Clock_Ip_PllConfigType const* Config)
185 {
186 uint32 Instance;
187 uint32 Value;
188
189 if (NULL_PTR != Config)
190 {
191 Instance = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_MODULE_INSTANCE];
192
193 if (Config->Enable != 0U)
194 {
195 /* Configure PLL: predivider and multiplier */
196 Value = Clock_Ip_apxPll[Instance].PllInstance->PLLDV;
197 Value &= ~(PLL_PLLDV_RDIV_MASK | PLL_PLLDV_MFI_MASK);
198 Value |= (uint32) (PLL_PLLDV_RDIV(Config->Predivider) |
199 PLL_PLLDV_MFI(Config->MulFactorDiv));
200 Clock_Ip_apxPll[Instance].PllInstance->PLLDV = Value;
201
202 /* Set numerator fractional loop divider and sigma delta modulation */
203 Value = Clock_Ip_apxPll[Instance].PllInstance->PLLFD;
204 Value &= ~(PLL_PLLFD_MFN_MASK | PLL_PLLFD_SDMEN_MASK);
205 Value |= PLL_PLLFD_MFN(Config->NumeratorFracLoopDiv);
206 Value |= PLL_PLLFD_SDMEN(Config->SigmaDelta);
207 Clock_Ip_apxPll[Instance].PllInstance->PLLFD = Value;
208
209 /* Configure modulation */
210 Value = (uint32) (PLL_PLLFM_SSCGBYP(Config->FrequencyModulationBypass) |
211 PLL_PLLFM_SPREADCTL(Config->ModulationType) |
212 PLL_PLLFM_STEPNO(Config->IncrementStep) |
213 PLL_PLLFM_STEPSIZE(Config->ModulationPeriod));
214 Clock_Ip_apxPll[Instance].PllInstance->PLLFM = Value;
215
216 /* Unlock Control Accuracy - accuracy necessary to achieve unlock. */
217 Clock_Ip_apxPll[Instance].PllInstance->PLLCAL2 = PLL_PLLCAL2_ULKCTL((Config->FrequencyModulationBypass != 0U) ? CLOCK_IP_RECOMMENTED_ULKCTL_BYPASSED_FM : CLOCK_IP_RECOMMENTED_ULKCTL_NOT_BYPASSED_FM);
218
219 /* Send command to enable PLL device. */
220 Clock_Ip_apxPll[Instance].PllInstance->PLLCR &= ~PLL_PLLCR_PLLPD_MASK;
221 }
222 }
223 else
224 {
225 (void)Instance;
226 (void)Value;
227 }
228 }
229
Clock_Ip_CompletePllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize(Clock_Ip_NameType PllName)230 static Clock_Ip_PllStatusReturnType Clock_Ip_CompletePllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize(Clock_Ip_NameType PllName)
231 {
232 Clock_Ip_PllStatusReturnType PllStatus = STATUS_PLL_LOCKED;
233
234 boolean TimeoutOccurred = FALSE;
235 uint32 StartTime;
236 uint32 ElapsedTime;
237 uint32 TimeoutTicks;
238 uint32 PllLockStatus;
239 uint32 Instance = Clock_Ip_au8ClockFeatures[PllName][CLOCK_IP_MODULE_INSTANCE];
240
241 if (0U == (Clock_Ip_apxPll[Instance].PllInstance->PLLCR & PLL_PLLCR_PLLPD_MASK))
242 {
243 Clock_Ip_StartTimeout(&StartTime, &ElapsedTime, &TimeoutTicks, CLOCK_IP_TIMEOUT_VALUE_US);
244 /* Wait until this pll is locked */
245 do
246 {
247 PllLockStatus = ((Clock_Ip_apxPll[Instance].PllInstance->PLLSR & PLL_PLLSR_LOCK_MASK) >> PLL_PLLSR_LOCK_SHIFT);
248 TimeoutOccurred = Clock_Ip_TimeoutExpired(&StartTime, &ElapsedTime, TimeoutTicks);
249 }
250 while ((0U == PllLockStatus) && (FALSE == TimeoutOccurred));
251
252 if (TRUE == TimeoutOccurred)
253 {
254 PllStatus = STATUS_PLL_UNLOCKED;
255 /* Report timeout error */
256 Clock_Ip_ReportClockErrors(CLOCK_IP_REPORT_TIMEOUT_ERROR, PllName);
257 }
258 }
259 else
260 {
261 PllStatus = STATUS_PLL_NOT_ENABLED;
262 }
263
264 return PllStatus;
265 }
Clock_Ip_EnablePllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize(Clock_Ip_PllConfigType const * Config)266 static void Clock_Ip_EnablePllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize(Clock_Ip_PllConfigType const* Config)
267 {
268 uint32 Instance;
269
270 if (NULL_PTR != Config)
271 {
272 Instance = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_MODULE_INSTANCE];
273
274 /* Configure PLL. */
275 if (1U == Config->Enable)
276 {
277 /* Send command to enable PLL device. */
278 Clock_Ip_apxPll[Instance].PllInstance->PLLCR &= ~PLL_PLLCR_PLLPD_MASK;
279 }
280 }
281 else
282 {
283 (void)Instance;
284 }
285 }
286 #endif
287
288 /*==================================================================================================
289 * GLOBAL FUNCTIONS
290 ==================================================================================================*/
291
292
293
294
295 /* Pll with frequency modulation and VCO clock post divider for driving the PHI output clocks */
296 #ifdef CLOCK_IP_PLL_RDIV_MFI_MFN_ODIV2_SDMEN
297
Clock_Ip_ResetPllRdivMfiMfnOdiv2Sdmen(Clock_Ip_PllConfigType const * Config)298 static void Clock_Ip_ResetPllRdivMfiMfnOdiv2Sdmen(Clock_Ip_PllConfigType const* Config)
299 {
300 uint32 Instance;
301 uint8 DividerIndex;
302
303 if (NULL_PTR != Config)
304 {
305 Instance = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_MODULE_INSTANCE];
306
307 /* Disable output dividers */
308 for (DividerIndex = 0U; DividerIndex < Clock_Ip_apxPll[Instance].DivsNo; DividerIndex++)
309 {
310 Clock_Ip_apxPll[Instance].PllInstance->PLLODIV[DividerIndex] &= ~PLL_PLLODIV_DE_MASK;
311 }
312 /* Power down PLL */
313 Clock_Ip_apxPll[Instance].PllInstance->PLLCR |= PLL_PLLCR_PLLPD_MASK;
314 }
315 else
316 {
317 (void)Instance;
318 (void)DividerIndex;
319 }
320
321 }
322
Clock_Ip_SetPllRdivMfiMfnOdiv2Sdmen(Clock_Ip_PllConfigType const * Config)323 static void Clock_Ip_SetPllRdivMfiMfnOdiv2Sdmen(Clock_Ip_PllConfigType const* Config)
324 {
325 uint32 Instance;
326 uint32 Value;
327
328 if (NULL_PTR != Config)
329 {
330 Instance = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_MODULE_INSTANCE];
331
332 if (Config->Enable != 0U)
333 {
334 /* Configure PLL: predivider and multiplier */
335 Value = Clock_Ip_apxPll[Instance].PllInstance->PLLDV;
336 Value &= ~(PLL_PLLDV_RDIV_MASK | PLL_PLLDV_MFI_MASK);
337 Value |= (uint32) (PLL_PLLDV_RDIV(Config->Predivider) |
338 PLL_PLLDV_MFI(Config->MulFactorDiv));
339 Clock_Ip_apxPll[Instance].PllInstance->PLLDV = Value;
340 Clock_Ip_apxPll[Instance].PllInstance->PLLCR &= ~PLL_PLLCR_PLLPD_MASK;
341 }
342 }
343 else
344 {
345 (void)Instance;
346 (void)Value;
347 }
348 }
349
Clock_Ip_CompletePllRdivMfiMfnOdiv2Sdmen(Clock_Ip_NameType PllName)350 static Clock_Ip_PllStatusReturnType Clock_Ip_CompletePllRdivMfiMfnOdiv2Sdmen(Clock_Ip_NameType PllName)
351 {
352 Clock_Ip_PllStatusReturnType PllStatus = STATUS_PLL_LOCKED;
353
354 boolean TimeoutOccurred = FALSE;
355 uint32 StartTime;
356 uint32 ElapsedTime;
357 uint32 TimeoutTicks;
358 uint32 PllLockStatus;
359 uint32 Instance = Clock_Ip_au8ClockFeatures[PllName][CLOCK_IP_MODULE_INSTANCE];
360
361 if (0U == (Clock_Ip_apxPll[Instance].PllInstance->PLLCR & PLL_PLLCR_PLLPD_MASK))
362 {
363 Clock_Ip_StartTimeout(&StartTime, &ElapsedTime, &TimeoutTicks, CLOCK_IP_TIMEOUT_VALUE_US);
364 /* Wait until this pll is locked */
365 do
366 {
367 PllLockStatus = ((Clock_Ip_apxPll[Instance].PllInstance->PLLSR & PLL_PLLSR_LOCK_MASK) >> PLL_PLLSR_LOCK_SHIFT);
368 TimeoutOccurred = Clock_Ip_TimeoutExpired(&StartTime, &ElapsedTime, TimeoutTicks);
369 }
370 while ((0U == PllLockStatus) && (FALSE == TimeoutOccurred));
371
372 if (TRUE == TimeoutOccurred)
373 {
374 PllStatus = STATUS_PLL_UNLOCKED;
375 /* Report timeout error */
376 Clock_Ip_ReportClockErrors(CLOCK_IP_REPORT_TIMEOUT_ERROR, PllName);
377 }
378 }
379 else
380 {
381 PllStatus = STATUS_PLL_NOT_ENABLED;
382 }
383 return PllStatus;
384 }
Clock_Ip_EnablePllRdivMfiMfnOdiv2Sdmen(Clock_Ip_PllConfigType const * Config)385 static void Clock_Ip_EnablePllRdivMfiMfnOdiv2Sdmen(Clock_Ip_PllConfigType const* Config)
386 {
387 uint32 Instance;
388
389 if (NULL_PTR != Config)
390 {
391 Instance = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_MODULE_INSTANCE];
392
393 /* Configure PLL. */
394 if (1U == Config->Enable)
395 {
396 /* Send command to enable PLL device. */
397 Clock_Ip_apxPll[Instance].PllInstance->PLLCR &= ~PLL_PLLCR_PLLPD_MASK;
398 }
399 }
400 else
401 {
402 (void)Instance;
403 }
404 }
405 #endif
406
407
408
409
410 /* Clock stop section code */
411 #define MCU_STOP_SEC_CODE
412
413 #include "Mcu_MemMap.h"
414
415 /*==================================================================================================
416 * GLOBAL CONSTANTS
417 ==================================================================================================*/
418 /* Clock start constant section data */
419 #define MCU_START_SEC_CONST_UNSPECIFIED
420
421 #include "Mcu_MemMap.h"
422 const Clock_Ip_PllCallbackType Clock_Ip_axPllCallbacks[CLOCK_IP_PLL_CALLBACKS_COUNT] =
423 {
424 {
425 Clock_Ip_CallbackPllEmpty, /* Reset */
426 Clock_Ip_CallbackPllEmpty, /* Set */
427 Clock_Ip_CallbackPllEmptyComplete, /* Complete */
428 Clock_Ip_CallbackPllEmpty, /* Enable */
429 Clock_Ip_CallbackPllEmptyDisable, /* Disable */
430 },
431 /* Pll with frequency modulation and VCO clock post divider for driving the PHI output clocks */
432 #ifdef CLOCK_IP_PLL_RDIV_MFI_MFN_ODIV2_SDMEN_SSCGBYP_SPREADCTL_STEPNO_STEPSIZE
433 {
434 Clock_Ip_ResetPllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize, /* Reset */
435 Clock_Ip_SetPllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize, /* Set */
436 Clock_Ip_CompletePllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize, /* Complete */
437 Clock_Ip_EnablePllRdivMfiMfnOdiv2SdmenSsscgbypSpreadctlStepnoStepsize, /* Enable */
438 Clock_Ip_CallbackPllEmptyDisable, /* Disable */
439 },
440 #endif /* CLOCK_IP_PLL_RDIV_MFI_MFN_ODIV2_SDMEN_SSCGBYP_SPREADCTL_STEPNO_STEPSIZE */
441 /* Pll with frequency modulation and VCO clock post divider for driving the PHI output clocks */
442 #ifdef CLOCK_IP_PLL_RDIV_MFI_MFN_ODIV2_SDMEN
443 {
444 Clock_Ip_ResetPllRdivMfiMfnOdiv2Sdmen, /* Reset */
445 Clock_Ip_SetPllRdivMfiMfnOdiv2Sdmen, /* Set */
446 Clock_Ip_CompletePllRdivMfiMfnOdiv2Sdmen, /* Complete */
447 Clock_Ip_EnablePllRdivMfiMfnOdiv2Sdmen, /* Enable */
448 Clock_Ip_CallbackPllEmptyDisable, /* Disable */
449 },
450 #endif /* CLOCK_IP_PLL_RDIV_MFI_MFN_ODIV2_SDMEN */
451 };
452
453
454 /* Clock stop constant section data */
455 #define MCU_STOP_SEC_CONST_UNSPECIFIED
456
457 #include "Mcu_MemMap.h"
458
459 #ifdef __cplusplus
460 }
461 #endif
462
463 /** @} */
464
465