1 /*
2  * Copyright 2021-2022 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 /**
7 *   @file       Clock_Ip_Divider.c
8 *   @version    0.9.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               0
40 #define CLOCK_IP_DIVIDER_SW_MINOR_VERSION_C               9
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_CGM_X_DE_DIV_STAT_WITHOUT_PHASE_WITH_TRIGGER
108 static void Clock_Ip_SetCgmXDeDivStatWithoutPhaseWithTrigger(Clock_Ip_DividerConfigType const* Config);
109 #endif
110 #ifdef CLOCK_IP_PLLDIG_PLL0DIV_DE_DIV_OUTPUT
111 static void Clock_Ip_SetPlldigPll0divDeDivOutput(Clock_Ip_DividerConfigType const* Config);
112 #endif
113 
114 
115 /* Clock stop section code */
116 #define MCU_STOP_SEC_CODE
117 
118 #include "Mcu_MemMap.h"
119 /*==================================================================================================
120 *                                         LOCAL FUNCTIONS
121 ==================================================================================================*/
122 #define MCU_START_SEC_CODE
123 /* Clock start section code */
124 
125 #include "Mcu_MemMap.h"
126 
Clock_Ip_Callback_DividerEmpty(Clock_Ip_DividerConfigType const * Config)127 static void Clock_Ip_Callback_DividerEmpty(Clock_Ip_DividerConfigType const* Config)
128 {
129     (void)Config;
130     /* No implementation */
131 }
132 
133 #ifdef CLOCK_IP_CGM_X_DE_DIV_STAT_WITHOUT_PHASE
Clock_Ip_SetCgmXDeDivStatWithoutPhase(Clock_Ip_DividerConfigType const * Config)134 static void Clock_Ip_SetCgmXDeDivStatWithoutPhase(Clock_Ip_DividerConfigType const* Config)
135 {
136     uint32 Instance      = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_MODULE_INSTANCE];
137     uint32 SelectorIndex = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_SELECTOR_INDEX];
138     uint32 DividerIndex  = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_DIVIDER_INDEX];
139 
140     uint32 DividerMask  = Clock_Ip_axFeatureExtensions[Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_EXTENSION_INDEX]].DividerValueMask;
141     uint32 DividerShift = Clock_Ip_axFeatureExtensions[Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_EXTENSION_INDEX]].DividerValueShift;
142 
143     uint32 RegValue;
144     boolean TimeoutOccurred = FALSE;
145     uint32 StartTime;
146     uint32 ElapsedTime;
147     uint32 TimeoutTicks;
148     uint32 DividerStatus;
149 
150     /* Program divider value */
151     if (Config->Value != 0U)
152     {
153         RegValue = Clock_Ip_apxCgm[Instance][SelectorIndex]->Divider[DividerIndex];
154         RegValue &= ~DividerMask;
155         RegValue |= (((Config->Value-1U) << DividerShift) & DividerMask);
156         Clock_Ip_apxCgm[Instance][SelectorIndex]->Divider[DividerIndex] = RegValue;
157 
158 #ifdef CLOCK_IP_DIVIDER_HAVE_DIV_FMT
159         if((Instance == 0U)  && (SelectorIndex == 2U) && (DividerIndex == 2U))
160         {
161             IP_MC_CGM_0->MUX_2_DC_2 &= ~MC_CGM_MUX_2_DC_2_DIV_FMT_MASK;
162         }
163         else if((Instance == 4U) && (SelectorIndex == 2U) && (DividerIndex == 2U))
164         {
165             IP_MC_CGM_4->MUX_2_DC_2 &= ~MC_CGM_MUX_2_DC_2_DIV_FMT_MASK;
166         }
167         else
168         {
169             /* Do nothing */
170         }
171 #endif
172     }
173 
174     Clock_Ip_StartTimeout(&StartTime, &ElapsedTime, &TimeoutTicks, CLOCK_IP_TIMEOUT_VALUE_US);
175     /* Wait for acknowledge to be cleared. */
176     do
177     {
178         DividerStatus = (Clock_Ip_apxCgm[Instance][SelectorIndex]->MUX_DIV_UPD_STAT & MC_CGM_MUX_DIV_UPD_STAT_DIV_STAT_MASK);
179         TimeoutOccurred = Clock_Ip_TimeoutExpired(&StartTime, &ElapsedTime, TimeoutTicks);
180     }
181     while ((MC_CGM_MUX_DIV_UPD_STAT_DIV_STAT_PENDING == DividerStatus) && (FALSE == TimeoutOccurred));
182 
183     if (FALSE == TimeoutOccurred)
184     {
185         /* Enable or Disable the Clock Divider */
186         if (Config->Value != 0U)
187         {
188             /* Enable divider */
189             Clock_Ip_apxCgm[Instance][SelectorIndex]->Divider[DividerIndex] |= MC_CGM_MUX_DC_DE_MASK;
190         }
191         else
192         {
193             Clock_Ip_apxCgm[Instance][SelectorIndex]->Divider[DividerIndex] &= ~MC_CGM_MUX_DC_DE_MASK;
194         }
195     }
196     else
197     {
198         /* Report timeout error */
199         Clock_Ip_ReportClockErrors(CLOCK_IP_REPORT_TIMEOUT_ERROR, Config->Name);
200     }
201 }
202 #endif
203 
204 #ifdef CLOCK_IP_CGM_X_DE_DIV_STAT_WITHOUT_PHASE_WITH_TRIGGER
Clock_Ip_SetCgmXDeDivStatWithoutPhaseWithTrigger(Clock_Ip_DividerConfigType const * Config)205 static void Clock_Ip_SetCgmXDeDivStatWithoutPhaseWithTrigger(Clock_Ip_DividerConfigType const* Config)
206 {
207     uint32 Instance      = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_MODULE_INSTANCE];
208     uint32 SelectorIndex = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_SELECTOR_INDEX];
209     uint32 DividerIndex  = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_DIVIDER_INDEX];
210 
211     uint32 DividerMask  = Clock_Ip_axFeatureExtensions[Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_EXTENSION_INDEX]].DividerValueMask;
212     uint32 DividerShift = Clock_Ip_axFeatureExtensions[Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_EXTENSION_INDEX]].DividerValueShift;
213 
214     uint32 RegValue;
215     boolean TimeoutOccurred = FALSE;
216     uint32 StartTime;
217     uint32 ElapsedTime;
218     uint32 TimeoutTicks;
219     uint32 DividerStatus;
220 
221     /* Program divider value */
222     if (Config->Value != 0U)
223     {
224         RegValue = Clock_Ip_apxCgm[Instance][SelectorIndex]->Divider[DividerIndex];
225         RegValue &= ~DividerMask;
226         RegValue |= ((Config->Value-1U) << DividerShift) & DividerMask;
227         Clock_Ip_apxCgm[Instance][SelectorIndex]->Divider[DividerIndex] = RegValue;
228     }
229 
230     /* Immediate update is triggered. */
231     if ((Clock_Ip_apxCgm[Instance][SelectorIndex]->MUX_DIV_TRIG_CTRL & MC_CGM_MUX_DIV_TRIG_CTRL_TCTL_MASK) != MC_CGM_MUX_DIV_TRIG_CTRL_COMMON_TRIGGER_DIVIDER_UPDATE)
232     {
233         Clock_Ip_StartTimeout(&StartTime, &ElapsedTime, &TimeoutTicks, CLOCK_IP_TIMEOUT_VALUE_US);
234         /* Wait for acknowledge to be cleared. */
235         do
236         {
237             DividerStatus = (Clock_Ip_apxCgm[Instance][SelectorIndex]->MUX_DIV_UPD_STAT & MC_CGM_MUX_DIV_UPD_STAT_DIV_STAT_MASK);
238             TimeoutOccurred = Clock_Ip_TimeoutExpired(&StartTime, &ElapsedTime, TimeoutTicks);
239         }
240         while ((MC_CGM_MUX_DIV_UPD_STAT_DIV_STAT_PENDING == DividerStatus) && (FALSE == TimeoutOccurred));
241     }
242 
243     if (FALSE == TimeoutOccurred)
244     {
245         /* Enable or Disable the Clock Divider */
246         if (Config->Value != 0U)
247         {
248             /* Enable divider */
249             Clock_Ip_apxCgm[Instance][SelectorIndex]->Divider[DividerIndex] |= MC_CGM_MUX_DC_DE_MASK;
250         }
251         else
252         {
253             Clock_Ip_apxCgm[Instance][SelectorIndex]->Divider[DividerIndex] &= ~MC_CGM_MUX_DC_DE_MASK;
254         }
255     }
256     else
257     {
258         /* Report timeout error */
259         Clock_Ip_ReportClockErrors(CLOCK_IP_REPORT_TIMEOUT_ERROR, Config->Name);
260     }
261 }
262 #endif
263 
264 #ifdef CLOCK_IP_PLLDIG_PLL0DIV_DE_DIV_OUTPUT
Clock_Ip_SetPlldigPll0divDeDivOutput(Clock_Ip_DividerConfigType const * Config)265 static void Clock_Ip_SetPlldigPll0divDeDivOutput(Clock_Ip_DividerConfigType const* Config)
266 {
267 
268     uint32 Instance      = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_MODULE_INSTANCE];
269     uint32 DividerIndex  = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_DIVIDER_INDEX];
270     uint32 RegValue;
271 
272     /* Check that divider is already disabled */
273     CLOCK_IP_DEV_ASSERT(!(Clock_Ip_apxPll[Instance].PllInstance->PLLODIV[DividerIndex] & PLLDIG_PLLODIV_DE_MASK));
274 
275     /* Check if divider is enabled */
276     if (Config->Value != 0U)
277     {
278         RegValue = Clock_Ip_apxPll[Instance].PllInstance->PLLODIV[DividerIndex];
279         RegValue |= PLLDIG_PLLODIV_DE_MASK;
280         RegValue &= ~PLLDIG_PLLODIV_DIV_MASK;
281         RegValue |= PLLDIG_PLLODIV_DIV(Config->Value - 1U);
282         Clock_Ip_apxPll[Instance].PllInstance->PLLODIV[DividerIndex] = RegValue;
283     }
284 }
285 #endif
286 
287 
288 
289 /*==================================================================================================
290 *                                        GLOBAL FUNCTIONS
291 ==================================================================================================*/
292 
293 /* Clock stop section code */
294 #define MCU_STOP_SEC_CODE
295 
296 #include "Mcu_MemMap.h"
297 
298 /*==================================================================================================
299 *                                        GLOBAL CONSTANTS
300 ==================================================================================================*/
301 
302 /* Clock start constant section data */
303 #define MCU_START_SEC_CONST_UNSPECIFIED
304 
305 #include "Mcu_MemMap.h"
306 
307 const Clock_Ip_DividerCallbackType Clock_Ip_axDividerCallbacks[CLOCK_IP_DIVIDER_CALLBACKS_COUNT] =
308 {
309     {
310         Clock_Ip_Callback_DividerEmpty,                  /* Set */
311     },
312 #ifdef CLOCK_IP_CGM_X_DE_DIV_STAT_WITHOUT_PHASE
313     {
314         Clock_Ip_SetCgmXDeDivStatWithoutPhase,           /* Set */
315     },
316 #endif
317 #ifdef CLOCK_IP_CGM_X_DE_DIV_STAT_WITHOUT_PHASE_WITH_TRIGGER
318     {
319         Clock_Ip_SetCgmXDeDivStatWithoutPhaseWithTrigger,               /* Set */
320     },
321 #endif
322 #ifdef CLOCK_IP_PLLDIG_PLL0DIV_DE_DIV_OUTPUT
323     {
324         Clock_Ip_SetPlldigPll0divDeDivOutput,            /* Set */
325     },
326 #endif
327 };
328 
329 /* Clock stop constant section data */
330 #define MCU_STOP_SEC_CONST_UNSPECIFIED
331 
332 #include "Mcu_MemMap.h"
333 
334 
335 #ifdef __cplusplus
336 }
337 #endif
338 
339 /** @} */
340