1 /*
2  * Copyright 2020-2023 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 /**
7 *   @file       Clock_Ip_Divider.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 /*==================================================================================================
33                                SOURCE FILE VERSION INFORMATION
34 ==================================================================================================*/
35 #define CLOCK_IP_DIVIDER_VENDOR_ID_C                      43
36 #define CLOCK_IP_DIVIDER_AR_RELEASE_MAJOR_VERSION_C       4
37 #define CLOCK_IP_DIVIDER_AR_RELEASE_MINOR_VERSION_C       7
38 #define CLOCK_IP_DIVIDER_AR_RELEASE_REVISION_VERSION_C    0
39 #define CLOCK_IP_DIVIDER_SW_MAJOR_VERSION_C               3
40 #define CLOCK_IP_DIVIDER_SW_MINOR_VERSION_C               0
41 #define CLOCK_IP_DIVIDER_SW_PATCH_VERSION_C               0
42 
43 /*==================================================================================================
44 *                                     FILE VERSION CHECKS
45 ==================================================================================================*/
46 /* Check if Clock_Ip_Divider.c file and Clock_Ip_Private.h file are of the same vendor */
47 #if (CLOCK_IP_DIVIDER_VENDOR_ID_C != CLOCK_IP_PRIVATE_VENDOR_ID)
48     #error "Clock_Ip_Divider.c and Clock_Ip_Private.h have different vendor ids"
49 #endif
50 
51 /* Check if Clock_Ip_Divider.c file and Clock_Ip_Private.h file are of the same Autosar version */
52 #if ((CLOCK_IP_DIVIDER_AR_RELEASE_MAJOR_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_MAJOR_VERSION) || \
53      (CLOCK_IP_DIVIDER_AR_RELEASE_MINOR_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_MINOR_VERSION) || \
54      (CLOCK_IP_DIVIDER_AR_RELEASE_REVISION_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_REVISION_VERSION) \
55     )
56     #error "AutoSar Version Numbers of Clock_Ip_Divider.c and Clock_Ip_Private.h are different"
57 #endif
58 
59 /* Check if Clock_Ip_Divider.c file and Clock_Ip_Private.h file are of the same Software version */
60 #if ((CLOCK_IP_DIVIDER_SW_MAJOR_VERSION_C != CLOCK_IP_PRIVATE_SW_MAJOR_VERSION) || \
61      (CLOCK_IP_DIVIDER_SW_MINOR_VERSION_C != CLOCK_IP_PRIVATE_SW_MINOR_VERSION) || \
62      (CLOCK_IP_DIVIDER_SW_PATCH_VERSION_C != CLOCK_IP_PRIVATE_SW_PATCH_VERSION) \
63     )
64     #error "Software Version Numbers of Clock_Ip_Divider.c and Clock_Ip_Private.h are different"
65 #endif
66 
67 /*==================================================================================================
68 *                           LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
69 ==================================================================================================*/
70 
71 /*==================================================================================================
72 *                                          LOCAL MACROS
73 ==================================================================================================*/
74 
75 /*==================================================================================================
76 *                                         LOCAL CONSTANTS
77 ==================================================================================================*/
78 
79 /*==================================================================================================
80 *                                         LOCAL VARIABLES
81 ==================================================================================================*/
82 
83 /*==================================================================================================
84 *                                        GLOBAL CONSTANTS
85 ==================================================================================================*/
86 
87 /*==================================================================================================
88 *                                        GLOBAL VARIABLES
89 ==================================================================================================*/
90 
91 /*==================================================================================================
92 *                                    GLOBAL FUNCTION PROTOTYPES
93 ==================================================================================================*/
94 /* Clock start section code */
95 #define MCU_START_SEC_CODE
96 
97 #include "Mcu_MemMap.h"
98 
99 /*==================================================================================================
100 *                                    LOCAL FUNCTION PROTOTYPES
101 ==================================================================================================*/
102 
103 static void Clock_Ip_Callback_DividerEmpty(Clock_Ip_DividerConfigType const* Config);
104 #ifdef CLOCK_IP_CGM_X_DE_DIV_STAT_WITHOUT_PHASE
105 static void Clock_Ip_SetCgmXDeDivStatWithoutPhase(Clock_Ip_DividerConfigType const* Config);
106 #endif
107 #ifdef CLOCK_IP_PLL_PLL0DIV_DE_DIV_OUTPUT
108 static void Clock_Ip_SetPllPll0divDeDivOutput(Clock_Ip_DividerConfigType const* Config);
109 #endif
110 
111 #ifdef CLOCK_IP_PLL_PLLDV_ODIV2_OUTPUT
112 static void Clock_Ip_SetPllPlldvOdiv2Output(Clock_Ip_DividerConfigType const* Config);
113 #endif
114 
115 
116 
117 /* Clock stop section code */
118 #define MCU_STOP_SEC_CODE
119 
120 #include "Mcu_MemMap.h"
121 /*==================================================================================================
122 *                                         LOCAL FUNCTIONS
123 ==================================================================================================*/
124 #define MCU_START_SEC_CODE
125 /* Clock start section code */
126 
127 #include "Mcu_MemMap.h"
128 
Clock_Ip_Callback_DividerEmpty(Clock_Ip_DividerConfigType const * Config)129 static void Clock_Ip_Callback_DividerEmpty(Clock_Ip_DividerConfigType const* Config)
130 {
131     (void)Config;
132     /* No implementation */
133 }
134 
135 #ifdef CLOCK_IP_CGM_X_DE_DIV_STAT_WITHOUT_PHASE
Clock_Ip_SetCgmXDeDivStatWithoutPhase(Clock_Ip_DividerConfigType const * Config)136 static void Clock_Ip_SetCgmXDeDivStatWithoutPhase(Clock_Ip_DividerConfigType const* Config)
137 {
138     uint32 Instance;
139     uint32 SelectorIndex;
140     uint32 DividerIndex;
141 
142     uint32 DividerMask;
143     uint32 DividerShift;
144 
145     uint32 RegValue;
146     boolean TimeoutOccurred = FALSE;
147     uint32 StartTime;
148     uint32 ElapsedTime;
149     uint32 TimeoutTicks;
150     uint32 DividerStatus;
151 
152     if (NULL_PTR != Config)
153     {
154         Instance      = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_MODULE_INSTANCE];
155         SelectorIndex = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_SELECTOR_INDEX];
156         DividerIndex  = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_DIVIDER_INDEX];
157         DividerMask   = Clock_Ip_axFeatureExtensions[Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_EXTENSION_INDEX]].DividerValueMask;
158         DividerShift  = Clock_Ip_axFeatureExtensions[Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_EXTENSION_INDEX]].DividerValueShift;
159 
160         /* Program divider value */
161         if (Config->Value != 0U)
162         {
163             RegValue = Clock_Ip_apxCgm[Instance][SelectorIndex]->Divider[DividerIndex];
164             RegValue &= ~DividerMask;
165             RegValue |= (((Config->Value-1U) << DividerShift) & DividerMask);
166             Clock_Ip_apxCgm[Instance][SelectorIndex]->Divider[DividerIndex] = RegValue;
167 
168         #ifdef CLOCK_IP_DIVIDER_HAVE_DIV_FMT
169             if((Instance == 0U)  && (SelectorIndex == 2U) && (DividerIndex == 2U))
170             {
171                 IP_MC_CGM_0->MUX_2_DC_2 &= ~MC_CGM_MUX_2_DC_2_DIV_FMT_MASK;
172             }
173             else if((Instance == 4U) && (SelectorIndex == 2U) && (DividerIndex == 2U))
174             {
175                 IP_MC_CGM_4->MUX_2_DC_2 &= ~MC_CGM_MUX_2_DC_2_DIV_FMT_MASK;
176             }
177             else
178             {
179                 /* Do nothing */
180             }
181         #endif
182         }
183 
184         Clock_Ip_StartTimeout(&StartTime, &ElapsedTime, &TimeoutTicks, CLOCK_IP_TIMEOUT_VALUE_US);
185         /* Wait for acknowledge to be cleared. */
186         do
187         {
188             DividerStatus = (Clock_Ip_apxCgm[Instance][SelectorIndex]->MUX_DIV_UPD_STAT & MC_CGM_MUX_DIV_UPD_STAT_DIV_STAT_MASK);
189             TimeoutOccurred = Clock_Ip_TimeoutExpired(&StartTime, &ElapsedTime, TimeoutTicks);
190         }
191         while ((MC_CGM_MUX_DIV_UPD_STAT_DIV_STAT_PENDING == DividerStatus) && (FALSE == TimeoutOccurred));
192 
193         if (FALSE == TimeoutOccurred)
194         {
195             /* Enable or Disable the Clock Divider */
196             if (Config->Value != 0U)
197             {
198                 /* Enable divider */
199                 Clock_Ip_apxCgm[Instance][SelectorIndex]->Divider[DividerIndex] |= MC_CGM_MUX_DC_DE_MASK;
200             }
201             else
202             {
203                 Clock_Ip_apxCgm[Instance][SelectorIndex]->Divider[DividerIndex] &= ~MC_CGM_MUX_DC_DE_MASK;
204             }
205         }
206         else
207         {
208             /* Report timeout error */
209             Clock_Ip_ReportClockErrors(CLOCK_IP_REPORT_TIMEOUT_ERROR, Config->Name);
210         }
211     }
212     else
213     {
214         (void)Instance;
215         (void)SelectorIndex;
216         (void)DividerIndex;
217         (void)DividerMask;
218         (void)DividerShift;
219         (void)RegValue;
220         (void)TimeoutOccurred;
221         (void)StartTime;
222         (void)ElapsedTime;
223         (void)TimeoutTicks;
224         (void)DividerStatus;
225     }
226 }
227 #endif
228 
229 #ifdef CLOCK_IP_PLL_PLL0DIV_DE_DIV_OUTPUT
Clock_Ip_SetPllPll0divDeDivOutput(Clock_Ip_DividerConfigType const * Config)230 static void Clock_Ip_SetPllPll0divDeDivOutput(Clock_Ip_DividerConfigType const* Config)
231 {
232     uint32 Instance;
233     uint32 DividerIndex;
234     uint32 RegValue;
235 
236     if (NULL_PTR != Config)
237     {
238         Instance      = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_MODULE_INSTANCE];
239         DividerIndex  = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_DIVIDER_INDEX];
240         /* Disable divider */
241         CLOCK_IP_DEV_ASSERT(!(Clock_Ip_apxPll[Instance].PllInstance->PLLODIV[DividerIndex] & PLL_PLLODIV_DE_MASK));
242         /* Check if divider is enabled */
243         if (Config->Value != 0U)
244         {
245             RegValue = Clock_Ip_apxPll[Instance].PllInstance->PLLODIV[DividerIndex];
246             RegValue |= PLL_PLLODIV_DE_MASK;
247             RegValue &= ~PLL_PLLODIV_DIV_MASK;
248             RegValue |= PLL_PLLODIV_DIV(Config->Value - 1U);
249             Clock_Ip_apxPll[Instance].PllInstance->PLLODIV[DividerIndex] = RegValue;
250         }
251     }
252     else
253     {
254         (void)Instance;
255         (void)DividerIndex;
256         (void)RegValue;
257     }
258 }
259 #endif
260 
261 #ifdef CLOCK_IP_PLL_PLLDV_ODIV2_OUTPUT
262 /* Set Pll Odiv2 configuration to register */
Clock_Ip_SetPllPlldvOdiv2Output(Clock_Ip_DividerConfigType const * Config)263 static void Clock_Ip_SetPllPlldvOdiv2Output(Clock_Ip_DividerConfigType const* Config)
264 {
265     uint32 Instance;
266     uint32 RegValue;
267     uint32 DividerValue;
268 
269     if (NULL_PTR != Config)
270     {
271         Instance      = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_MODULE_INSTANCE];
272         DividerValue = (Config->Value != 0U) ? Config->Value : 1U;
273 
274         RegValue = Clock_Ip_apxPll[Instance].PllInstance->PLLDV;
275         RegValue &= ~PLL_PLLDV_ODIV2_MASK;
276         RegValue |= PLL_PLLDV_ODIV2(DividerValue);
277         Clock_Ip_apxPll[Instance].PllInstance->PLLDV = RegValue;
278     }
279     else
280     {
281         (void)Instance;
282         (void)RegValue;
283         (void)DividerValue;
284     }
285 }
286 #endif
287 
288 
289 
290 /*==================================================================================================
291 *                                        GLOBAL FUNCTIONS
292 ==================================================================================================*/
293 
294 
295 /* Clock stop section code */
296 #define MCU_STOP_SEC_CODE
297 
298 #include "Mcu_MemMap.h"
299 
300 /*==================================================================================================
301 *                                        GLOBAL CONSTANTS
302 ==================================================================================================*/
303 
304 /* Clock start constant section data */
305 #define MCU_START_SEC_CONST_UNSPECIFIED
306 
307 #include "Mcu_MemMap.h"
308 
309 const Clock_Ip_DividerCallbackType Clock_Ip_axDividerCallbacks[CLOCK_IP_DIVIDER_CALLBACKS_COUNT] =
310 {
311     {
312         Clock_Ip_Callback_DividerEmpty,                  /* Set */
313     },
314 #ifdef CLOCK_IP_CGM_X_DE_DIV_STAT_WITHOUT_PHASE
315     {
316         Clock_Ip_SetCgmXDeDivStatWithoutPhase,           /* Set */
317     },
318 #endif
319 #ifdef CLOCK_IP_PLL_PLL0DIV_DE_DIV_OUTPUT
320     {
321         Clock_Ip_SetPllPll0divDeDivOutput,              /* Set */
322     },
323 #endif /* CLOCK_IP_PLL_PLL0DIV_DE_DIV_OUTPUT */
324 #ifdef CLOCK_IP_PLL_PLLDV_ODIV2_OUTPUT
325     {
326         Clock_Ip_SetPllPlldvOdiv2Output,              /* Set */
327     },
328 #endif /* CLOCK_IP_PLL_PLLDV_ODIV2_OUTPUT */
329 
330 };
331 
332 /* Clock stop constant section data */
333 #define MCU_STOP_SEC_CONST_UNSPECIFIED
334 
335 #include "Mcu_MemMap.h"
336 
337 
338 #ifdef __cplusplus
339 }
340 #endif
341 
342 /** @} */
343