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