1 /*
2  * Copyright 2020-2023 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 /**
7 *   @file       Clock_Ip.c
8 *   @version    2.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 #include "OsIf.h"
31 
32 /*==================================================================================================
33                                SOURCE FILE VERSION INFORMATION
34 ==================================================================================================*/
35 #define CLOCK_IP_VENDOR_ID_C                      43
36 #define CLOCK_IP_AR_RELEASE_MAJOR_VERSION_C       4
37 #define CLOCK_IP_AR_RELEASE_MINOR_VERSION_C       7
38 #define CLOCK_IP_AR_RELEASE_REVISION_VERSION_C    0
39 #define CLOCK_IP_SW_MAJOR_VERSION_C               2
40 #define CLOCK_IP_SW_MINOR_VERSION_C               0
41 #define CLOCK_IP_SW_PATCH_VERSION_C               0
42 
43 /*==================================================================================================
44 *                                     FILE VERSION CHECKS
45 ==================================================================================================*/
46 /* Check if Clock_Ip.c file and Clock_Ip_Private.h file are of the same vendor */
47 #if (CLOCK_IP_VENDOR_ID_C != CLOCK_IP_PRIVATE_VENDOR_ID)
48     #error "Clock_Ip.c and Clock_Ip_Private.h have different vendor ids"
49 #endif
50 
51 /* Check if Clock_Ip.c file and Clock_Ip_Private.h file are of the same Autosar version */
52 #if ((CLOCK_IP_AR_RELEASE_MAJOR_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_MAJOR_VERSION) || \
53      (CLOCK_IP_AR_RELEASE_MINOR_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_MINOR_VERSION) || \
54      (CLOCK_IP_AR_RELEASE_REVISION_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_REVISION_VERSION) \
55     )
56     #error "AutoSar Version Numbers of Clock_Ip.c and Clock_Ip_Private.h are different"
57 #endif
58 
59 /* Check if Clock_Ip.c file and Clock_Ip_Private.h file are of the same Software version */
60 #if ((CLOCK_IP_SW_MAJOR_VERSION_C != CLOCK_IP_PRIVATE_SW_MAJOR_VERSION) || \
61      (CLOCK_IP_SW_MINOR_VERSION_C != CLOCK_IP_PRIVATE_SW_MINOR_VERSION) || \
62      (CLOCK_IP_SW_PATCH_VERSION_C != CLOCK_IP_PRIVATE_SW_PATCH_VERSION) \
63     )
64     #error "Software Version Numbers of Clock_Ip.c and Clock_Ip_Private.h are different"
65 #endif
66 
67 #ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
68 /* Check if Clock_Ip.c file and OsIf.h file are of the same Autosar version */
69 #if ((CLOCK_IP_AR_RELEASE_MAJOR_VERSION_C    != OSIF_AR_RELEASE_MAJOR_VERSION) || \
70      (CLOCK_IP_AR_RELEASE_MINOR_VERSION_C    != OSIF_AR_RELEASE_MINOR_VERSION))
71     #error "AutoSar Version Numbers of Clock_Ip.c and OsIf.h are different"
72 #endif
73 #endif
74 
75 /*==================================================================================================
76 *                           LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
77 ==================================================================================================*/
78 
79 /*!
80  * @brief Clock ip driver context
81  */
82 typedef struct
83 {
84     boolean ClockTreeIsConsumingPll;                /**< Clock tree is using a PLL output. */
85     boolean WaitStatesAreSupported;                 /**< Wait states are supported. */
86     uint8 HwPllsNo;                                 /**< Number of plls . */
87     uint8 HwDfsNo;                                  /**< Number of fractional dividers . */
88 
89 } Clock_Ip_DriverContextType;
90 
91 /*==================================================================================================
92 *                                          LOCAL MACROS
93 ==================================================================================================*/
94 #define CLOCK_IP_WAIT_STATES_DELAY              0XEFFFFFFFU
95 
96 /*==================================================================================================
97 *                                         LOCAL CONSTANTS
98 ==================================================================================================*/
99 /* Clock start initialized section data */
100 #define MCU_START_SEC_VAR_CLEARED_UNSPECIFIED
101 #include "Mcu_MemMap.h"
102 
103 #if !((CLOCK_IP_CMU_INFO_SIZE > 0U) || defined(CLOCK_IP_CGU_INTERRUPT))
104 static const Clock_Ip_ClockConfigType *Clock_Ip_pxConfig;                                           /* Reference to the current clock configuration */
105 #endif
106 
107 /* Clock stop initialized section data */
108 #define MCU_STOP_SEC_VAR_CLEARED_UNSPECIFIED
109 #include "Mcu_MemMap.h"
110 /*==================================================================================================
111 *                                         LOCAL VARIABLES
112 ==================================================================================================*/
113 /* Clock start initialized section data */
114 #define MCU_START_SEC_VAR_CLEARED_BOOLEAN
115 #include "Mcu_MemMap.h"
116 
117 static boolean FunctionWasCalled;
118 
119 /* Clock stop initialized section data */
120 #define MCU_STOP_SEC_VAR_CLEARED_BOOLEAN
121 #include "Mcu_MemMap.h"
122 
123 /* Clock start initialized section data */
124 #define MCU_START_SEC_VAR_CLEARED_UNSPECIFIED
125 #include "Mcu_MemMap.h"
126 
127 static Clock_Ip_DriverContextType DriverContext;
128 
129 /* Clock stop initialized section data */
130 #define MCU_STOP_SEC_VAR_CLEARED_UNSPECIFIED
131 #include "Mcu_MemMap.h"
132 /*==================================================================================================
133 *                                        GLOBAL CONSTANTS
134 ==================================================================================================*/
135 
136 /*==================================================================================================
137 *                                        GLOBAL VARIABLES
138 ==================================================================================================*/
139 /* Clock start initialized section data */
140 #define MCU_START_SEC_VAR_CLEARED_UNSPECIFIED
141 #include "Mcu_MemMap.h"
142 
143 #if (CLOCK_IP_CMU_INFO_SIZE > 0U) || defined(CLOCK_IP_CGU_INTERRUPT)
144 const Clock_Ip_ClockConfigType *Clock_Ip_pxConfig;                                           /* Reference to the current clock configuration */
145 #endif
146 
147 /* Clock stop initialized section data */
148 #define MCU_STOP_SEC_VAR_CLEARED_UNSPECIFIED
149 #include "Mcu_MemMap.h"
150 
151 /* Clock start initialized section data */
152 #define MCU_START_SEC_VAR_INIT_BOOLEAN
153 #include "Mcu_MemMap.h"
154 
155     boolean Clock_Ip_bSentFromUpdateDriverContext = TRUE;
156 
157 /* Clock stop initialized section data */
158 #define MCU_STOP_SEC_VAR_INIT_BOOLEAN
159 #include "Mcu_MemMap.h"
160 
161 #if CLOCK_IP_CONFIGURED_FREQUENCIES_COUNT > 0U
162 
163 /* Clock start initialized section data */
164 #define MCU_START_SEC_VAR_CLEARED_8
165 #include "Mcu_MemMap.h"
166 
167 uint8 Clock_Ip_FreqIds[CLOCK_IP_FEATURE_NAMES_NO];
168 
169 /* Clock stop initialized section data */
170 #define MCU_STOP_SEC_VAR_CLEARED_8
171 #include "Mcu_MemMap.h"
172 
173 #endif /* CLOCK_IP_CONFIGURED_FREQUENCIES_COUNT > 0U */
174 /*==================================================================================================
175 *                                    LOCAL FUNCTION PROTOTYPES
176 ==================================================================================================*/
177 
178 #define MCU_START_SEC_CODE
179 #include "Mcu_MemMap.h"
180 
181 static void Clock_Ip_NotificatonsEmptyCallback(Clock_Ip_NotificationType Notification, Clock_Ip_NameType ClockName);
182 static void Clock_Ip_ResetClockConfiguration(Clock_Ip_ClockConfigType const * Config);
183 static void Clock_Ip_UpdateDriverContext(Clock_Ip_ClockConfigType const * Config);
184 static void Clock_Ip_CallEmptyCallbacks(void);
185 static void Clock_Ip_SetWaitStates(void);
186 
187 #if (defined(CLOCK_IP_DEV_ERROR_DETECT) && (CLOCK_IP_DEV_ERROR_DETECT == STD_ON))
188 static void Clock_Ip_CheckClockConfiguration(Clock_Ip_ClockConfigType const * Config);
189 static void Clock_Ip_CheckIrcoscClocks(Clock_Ip_ClockConfigType const * Config);
190 static void Clock_Ip_CheckXoscClocks(Clock_Ip_ClockConfigType const * Config);
191 static void Clock_Ip_CheckPllClocks(Clock_Ip_ClockConfigType const * Config);
192 static void Clock_Ip_CheckExtSigClocks(Clock_Ip_ClockConfigType const * Config);
193 static void Clock_Ip_CheckSelectorClocks(Clock_Ip_ClockConfigType const * Config);
194 static void Clock_Ip_CheckDividerClocks(Clock_Ip_ClockConfigType const * Config);
195 static void Clock_Ip_CheckDividerTriggerClocks(Clock_Ip_ClockConfigType const * Config);
196 static void Clock_Ip_CheckFracDividerClocks(Clock_Ip_ClockConfigType const * Config);
197 static void Clock_Ip_CheckGateClocks(Clock_Ip_ClockConfigType const * Config);
198 static void Clock_Ip_CheckPcfsClocks(Clock_Ip_ClockConfigType const * Config);
199 static void Clock_Ip_CheckCmuClocks(Clock_Ip_ClockConfigType const * Config);
200 #endif
201 
202 /* Clock Report Error Callback */
203 static Clock_Ip_NotificationsCallbackType Clock_Ip_pfkNotificationsCallback = Clock_Ip_NotificatonsEmptyCallback;
204 
205 #define MCU_STOP_SEC_CODE
206 #include "Mcu_MemMap.h"
207 
208 /*==================================================================================================
209 *                                         LOCAL VARIABLES
210 ==================================================================================================*/
211 
212 /*==================================================================================================
213 *                                         LOCAL FUNCTIONS
214 ==================================================================================================*/
215 
216 /* Clock start section code */
217 #define MCU_START_SEC_CODE
218 
219 #include "Mcu_MemMap.h"
220 
221 /*FUNCTION**********************************************************************
222  *
223  * Function Name : Clock_Ip_NotificatonsEmptyCallback.
224  * Description   : Notification clock call back.
225  *
226  *END**************************************************************************/
Clock_Ip_NotificatonsEmptyCallback(Clock_Ip_NotificationType Notification,Clock_Ip_NameType ClockName)227 static void Clock_Ip_NotificatonsEmptyCallback( Clock_Ip_NotificationType Notification,
228                                                 Clock_Ip_NameType ClockName
229                                                )
230 {
231     /* No implementation */
232     (void)Notification;
233     (void)ClockName;
234 }
235 
236 /*FUNCTION**********************************************************************
237  *
238  * Function Name : Clock_Ip_UpdateDriverContext.
239  * Description   : Updates context of the driver, internal memory, clock objects.
240  *
241  *END**************************************************************************/
Clock_Ip_UpdateDriverContext(Clock_Ip_ClockConfigType const * Config)242 static void Clock_Ip_UpdateDriverContext(Clock_Ip_ClockConfigType const * Config)
243 {
244     uint8 Index;
245     (void)Config;
246     Clock_Ip_bSentFromUpdateDriverContext = TRUE;
247     /* Initialize clock objects */
248     Clock_Ip_Command(Clock_Ip_pxConfig, CLOCK_IP_INITIALIZE_CLOCK_OBJECTS_COMMAND);
249 
250     for (Index = 0U; Index < Config->ExtClksCount; Index++)    /* Set external signal frequency. */
251     {
252         Clock_Ip_SetExternalSignalFrequency(Config->ExtClks[Index].Name, Config->ExtClks[Index].Value);
253     }
254 
255     /* Call empty callbacks */
256     Clock_Ip_CallEmptyCallbacks();
257 
258 #if CLOCK_IP_CONFIGURED_FREQUENCIES_COUNT > 0U
259 
260     for (Index = 1U; Index < Config->ConfigureFrequenciesCount; Index++)
261     {
262         Clock_Ip_FreqIds[Config->ConfiguredFrequencies[Index].Name] = Index;
263     }
264 
265 #endif /* CLOCK_IP_CONFIGURED_FREQUENCIES_COUNT > 0U */
266 }
267 
268 #if (defined(CLOCK_IP_DEV_ERROR_DETECT))
269     #if (CLOCK_IP_DEV_ERROR_DETECT == STD_ON)
270 /*FUNCTION**********************************************************************
271  *
272  * Function Name : Clock_Ip_CheckIrcoscClocks
273  * Description   : Checks clock names from ircoscs array
274  *
275  *END**************************************************************************/
Clock_Ip_CheckIrcoscClocks(Clock_Ip_ClockConfigType const * Config)276 static void Clock_Ip_CheckIrcoscClocks(Clock_Ip_ClockConfigType const * Config)
277 {
278 #if CLOCK_IP_IRCOSCS_COUNT > 1U
279     uint32 Index;
280 #endif
281     if (Config->IrcoscsCount != 0U)
282     {
283 #if CLOCK_IP_IRCOSCS_COUNT > 1U
284         if (Config->IrcoscsCount > 1U)
285         {
286             for (Index = 0U; Index < (Config->IrcoscsCount - 1U); Index++)
287             {
288                 CLOCK_IP_DEV_ASSERT(((uint32)Config->Ircoscs[Index].Name) < ((uint32)Config->Ircoscs[Index+1U].Name));
289                 CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Ircoscs[Index].Name] & CLOCK_IP_IRCOSC_OBJECT) != 0U);
290             }
291         }
292 #endif
293         CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Ircoscs[Config->IrcoscsCount - 1U].Name] & CLOCK_IP_IRCOSC_OBJECT) != 0U);
294     }
295 }
296 
297 /*FUNCTION**********************************************************************
298  *
299  * Function Name : Clock_Ip_CheckXoscClocks
300  * Description   : Checks clock names from xoscs array
301  *
302  *END**************************************************************************/
Clock_Ip_CheckXoscClocks(Clock_Ip_ClockConfigType const * Config)303 static void Clock_Ip_CheckXoscClocks(Clock_Ip_ClockConfigType const * Config)
304 {
305 #if CLOCK_IP_XOSCS_COUNT > 1U
306     uint32 Index;
307 #endif
308 
309     if (Config->XoscsCount != 0U)
310     {
311 #if CLOCK_IP_XOSCS_COUNT > 1U
312         if (Config->XoscsCount > 1U)
313         {
314             for (Index = 0U; Index < (Config->XoscsCount - 1U); Index++)
315             {
316                 CLOCK_IP_DEV_ASSERT(((uint32)Config->Xoscs[Index].Name) < ((uint32)Config->Xoscs[Index+1U].Name));
317                 CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Xoscs[Index].Name] & CLOCK_IP_XOSC_OBJECT) != 0U);
318             }
319         }
320 #endif
321         CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Xoscs[Config->XoscsCount - 1U].Name] & CLOCK_IP_XOSC_OBJECT) != 0U);
322     }
323 }
324 
325 /*FUNCTION**********************************************************************
326  *
327  * Function Name : Clock_Ip_CheckPllClocks
328  * Description   : Checks clock names from plls array
329  *
330  *END**************************************************************************/
Clock_Ip_CheckPllClocks(Clock_Ip_ClockConfigType const * Config)331 static void Clock_Ip_CheckPllClocks(Clock_Ip_ClockConfigType const * Config)
332 {
333 #if CLOCK_IP_PLLS_COUNT > 1U
334     uint32 Index;
335 #endif
336     if (Config->PllsCount != 0U)
337     {
338 #if CLOCK_IP_PLLS_COUNT > 1U
339         if (Config->PllsCount > 1U)
340         {
341             for (Index = 0U; Index < (Config->PllsCount - 1U); Index++)
342             {
343                 CLOCK_IP_DEV_ASSERT(((uint32)Config->Plls[Index].Name) < ((uint32)Config->Plls[Index+1U].Name));
344                 CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Plls[Index].Name] & CLOCK_IP_PLL_OBJECT) != 0U);
345             }
346         }
347 #endif
348         CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Plls[Config->PllsCount - 1U].Name] & CLOCK_IP_PLL_OBJECT) != 0U);
349     }
350 }
351 
352 /*FUNCTION**********************************************************************
353  *
354  * Function Name : Clock_Ip_CheckExtSigClocks
355  * Description   : Checks clock names from ext signal clocks array
356  *
357  *END**************************************************************************/
Clock_Ip_CheckExtSigClocks(Clock_Ip_ClockConfigType const * Config)358 static void Clock_Ip_CheckExtSigClocks(Clock_Ip_ClockConfigType const * Config)
359 {
360 #if CLOCK_IP_EXT_CLKS_NO > 1U
361     uint32 Index;
362 #endif
363     if (Config->ExtClksCount != 0U)
364     {
365 #if CLOCK_IP_EXT_CLKS_NO > 1U
366         if (Config->ExtClksCount > 1U)
367         {
368             for (Index = 0U; Index < (Config->ExtClksCount - 1U); Index++)
369             {
370                 CLOCK_IP_DEV_ASSERT(((uint32)Config->ExtClks[Index].Name) < ((uint32)Config->ExtClks[Index+1U].Name));
371                 CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->ExtClks[Index].Name] & CLOCK_IP_EXT_SIG_OBJECT) != 0U);
372             }
373         }
374 #endif
375         CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->ExtClks[Config->ExtClksCount - 1U].Name] & CLOCK_IP_EXT_SIG_OBJECT) != 0U);
376     }
377 }
378 
379 /*FUNCTION**********************************************************************
380  *
381  * Function Name : Clock_Ip_CheckSelectorClocks
382  * Description   : Checks clock names from selectors array
383  *
384  *END**************************************************************************/
Clock_Ip_CheckSelectorClocks(Clock_Ip_ClockConfigType const * Config)385 static void Clock_Ip_CheckSelectorClocks(Clock_Ip_ClockConfigType const * Config)
386 {
387     uint32 Index;
388 
389     if (Config->SelectorsCount != 0U)
390     {
391         if (Config->SelectorsCount > 1U)
392         {
393             for (Index = 0U; Index < (Config->SelectorsCount - 1U); Index++)
394             {
395                 CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Selectors[Index].Name] & CLOCK_IP_SELECTOR_OBJECT) != 0U);
396             }
397         }
398         CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Selectors[Config->SelectorsCount - 1U].Name] & CLOCK_IP_SELECTOR_OBJECT) != 0U);
399     }
400 }
401 
402 /*FUNCTION**********************************************************************
403  *
404  * Function Name : Clock_Ip_CheckDividerClocks
405  * Description   : Checks clock names from dividers array
406  *
407  *END**************************************************************************/
Clock_Ip_CheckDividerClocks(Clock_Ip_ClockConfigType const * Config)408 static void Clock_Ip_CheckDividerClocks(Clock_Ip_ClockConfigType const * Config)
409 {
410     uint32 Index;
411 
412     if (Config->DividersCount != 0U)
413     {
414         if (Config->DividersCount > 1U)
415         {
416             for (Index = 0U; Index < (Config->DividersCount - 1U); Index++)
417             {
418                 CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Dividers[Index].Name] & CLOCK_IP_DIVIDER_OBJECT) != 0U);
419             }
420         }
421         CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Dividers[Config->DividersCount - 1U].Name] & CLOCK_IP_DIVIDER_OBJECT) != 0U);
422     }
423 }
424 
425 /*FUNCTION**********************************************************************
426  *
427  * Function Name : Check_DividerTrigger_Clocks
428  * Description   : Checks clock names from divider triggers array
429  *
430  *END**************************************************************************/
Clock_Ip_CheckDividerTriggerClocks(Clock_Ip_ClockConfigType const * Config)431 static void Clock_Ip_CheckDividerTriggerClocks(Clock_Ip_ClockConfigType const * Config)
432 {
433 #if CLOCK_IP_DIVIDER_TRIGGERS_COUNT > 1U
434     uint32 Index;
435 #endif
436 
437     if (Config->DividerTriggersCount != 0U)
438     {
439 #if CLOCK_IP_DIVIDER_TRIGGERS_COUNT > 1U
440         if (Config->DividerTriggersCount > 1U)
441         {
442             for (Index = 0U; Index < (Config->DividerTriggersCount - 1U); Index++)
443             {
444                 CLOCK_IP_DEV_ASSERT(((uint32)Config->DividerTriggers[Index].Name) < ((uint32)Config->DividerTriggers[Index+1U].Name));
445                 CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->DividerTriggers[Index].Name] & CLOCK_IP_DIVIDER_TRIGGER_OBJECT) != 0U);
446             }
447         }
448 #endif
449         CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->DividerTriggers[Config->DividerTriggersCount - 1U].Name] & CLOCK_IP_DIVIDER_TRIGGER_OBJECT) != 0U);
450     }
451 }
452 
453 /*FUNCTION**********************************************************************
454  *
455  * Function Name : Check_FracDivider_Clocks
456  * Description   : Checks clock names from fractional divider array
457  *
458  *END**************************************************************************/
Clock_Ip_CheckFracDividerClocks(Clock_Ip_ClockConfigType const * Config)459 static void Clock_Ip_CheckFracDividerClocks(Clock_Ip_ClockConfigType const * Config)
460 {
461 #if CLOCK_IP_FRACTIONAL_DIVIDERS_COUNT > 1U
462     uint32 Index;
463 #endif
464 
465     if (Config->FracDivsCount != 0U)
466     {
467 #if CLOCK_IP_FRACTIONAL_DIVIDERS_COUNT > 1U
468         if (Config->FracDivsCount > 1U)
469         {
470             for (Index = 0U; Index < (Config->FracDivsCount - 1U); Index++)
471             {
472                 CLOCK_IP_DEV_ASSERT(((uint32)Config->FracDivs[Index].Name) < ((uint32)Config->FracDivs[Index+1U].Name));
473                 CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->FracDivs[Index].Name] & CLOCK_IP_FRAC_DIV_OBJECT) != 0U);
474             }
475         }
476 #endif
477         CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->FracDivs[Config->FracDivsCount - 1U].Name] & CLOCK_IP_FRAC_DIV_OBJECT) != 0U);
478     }
479 }
480 
481 /*FUNCTION**********************************************************************
482  *
483  * Function Name : Clock_Ip_CheckGateClocks
484  * Description   : Checks clock names from gates array
485  *
486  *END**************************************************************************/
Clock_Ip_CheckGateClocks(Clock_Ip_ClockConfigType const * Config)487 static void Clock_Ip_CheckGateClocks(Clock_Ip_ClockConfigType const * Config)
488 {
489     uint32 Index;
490 
491     if (Config->GatesCount != 0U)
492     {
493         if (Config->GatesCount > 1U)
494         {
495             for (Index = 0U; Index < (Config->GatesCount - 1U); Index++)
496             {
497                 CLOCK_IP_DEV_ASSERT(((uint32)Config->Gates[Index].Name) < ((uint32)Config->Gates[Index+1U].Name));
498                 CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Gates[Index].Name] & CLOCK_IP_GATE_OBJECT) != 0U);
499             }
500         }
501         CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Gates[Config->GatesCount - 1U].Name] & CLOCK_IP_GATE_OBJECT) != 0U);
502     }
503 }
504 
505 /*FUNCTION**********************************************************************
506  *
507  * Function Name : Clock_Ip_CheckPcfsClocks
508  * Description   : Checks clock names from pcfs array
509  *
510  *END**************************************************************************/
Clock_Ip_CheckPcfsClocks(Clock_Ip_ClockConfigType const * Config)511 static void Clock_Ip_CheckPcfsClocks(Clock_Ip_ClockConfigType const * Config)
512 {
513     uint32 Index;
514 
515     if (Config->PcfsCount != 0U)
516     {
517         if (Config->PcfsCount > 1U)
518         {
519             for (Index = 0U; Index < (Config->PcfsCount - 1U); Index++)
520             {
521                 CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Pcfs[Index].Name] & CLOCK_IP_PCFS_OBJECT) != 0U);
522             }
523         }
524         CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Pcfs[Config->PcfsCount - 1U].Name] & CLOCK_IP_PCFS_OBJECT) != 0U);
525     }
526 }
527 
528 /*FUNCTION**********************************************************************
529  *
530  * Function Name : Clock_Ip_CheckCmuClocks
531  * Description   : Checks clock names from cmu array
532  *
533  *END**************************************************************************/
Clock_Ip_CheckCmuClocks(Clock_Ip_ClockConfigType const * Config)534 static void Clock_Ip_CheckCmuClocks(Clock_Ip_ClockConfigType const * Config)
535 {
536     uint32 Index;
537 
538     if (Config->CmusCount != 0U)
539     {
540         if (Config->CmusCount > 1U)
541         {
542             for (Index = 0U; Index < (Config->CmusCount - 1U); Index++)
543             {
544                 CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Cmus[Index].Name] & CLOCK_IP_CMU_OBJECT) != 0U);
545             }
546         }
547         CLOCK_IP_DEV_ASSERT((Clock_Ip_au8ClockNameTypes[Config->Cmus[Config->CmusCount - 1U].Name] & CLOCK_IP_CMU_OBJECT) != 0U);
548     }
549 }
550     #endif
551 #endif
552 
553 #define CLOCK_IP_NO_CALLBACK 0U
554 
555 /* Call empty callbacks to improve CCOV*/
Clock_Ip_CallEmptyCallbacks(void)556 static void Clock_Ip_CallEmptyCallbacks(void)
557 {
558 
559     if (FALSE == FunctionWasCalled)
560     {
561         FunctionWasCalled = TRUE;
562 
563         Clock_Ip_axCmuCallbacks[CLOCK_IP_NO_CALLBACK].Set(NULL_PTR, 0U);
564         Clock_Ip_axCmuCallbacks[CLOCK_IP_NO_CALLBACK].Disable(RESERVED_CLK);
565 
566         Clock_Ip_axDividerCallbacks[CLOCK_IP_NO_CALLBACK].Set(NULL_PTR);
567 
568         Clock_Ip_axDividerTriggerCallbacks[CLOCK_IP_NO_CALLBACK].Configure(NULL_PTR);
569 
570         Clock_Ip_axExtOscCallbacks[CLOCK_IP_NO_CALLBACK].Reset(NULL_PTR);
571 
572         Clock_Ip_axFracDivCallbacks[CLOCK_IP_NO_CALLBACK].Set(NULL_PTR);
573         (void)Clock_Ip_axFracDivCallbacks[CLOCK_IP_NO_CALLBACK].Complete(RESERVED_CLK);
574 
575         Clock_Ip_axGateCallbacks[CLOCK_IP_NO_CALLBACK].Set(NULL_PTR);
576         Clock_Ip_axGateCallbacks[CLOCK_IP_NO_CALLBACK].Update(RESERVED_CLK,FALSE);
577 
578         Clock_Ip_axIntOscCallbacks[CLOCK_IP_NO_CALLBACK].Set(NULL_PTR);
579 
580         Clock_Ip_axPllCallbacks[CLOCK_IP_NO_CALLBACK].Set(NULL_PTR);
581         (void)Clock_Ip_axPllCallbacks[CLOCK_IP_NO_CALLBACK].Complete(RESERVED_CLK);
582 
583         Clock_Ip_axSelectorCallbacks[CLOCK_IP_NO_CALLBACK].Set(NULL_PTR);
584 
585         Clock_Ip_axPcfsCallbacks[CLOCK_IP_NO_CALLBACK].Set(NULL_PTR, 0U);
586     }
587 }
588 
Clock_Ip_ResetClockConfiguration(Clock_Ip_ClockConfigType const * Config)589 static void Clock_Ip_ResetClockConfiguration(Clock_Ip_ClockConfigType const * Config)
590 {
591     uint32 CallbackIndex;
592     uint32 Index;
593 
594     for (Index = Config->SelectorsCount ; Index > 0U; Index--)    /* Ramp down all selectors from configuration to SAFE_CLOCK */
595     {
596         CallbackIndex = Clock_Ip_au8SelectorCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Selectors[Index - 1U].Name][CLOCK_IP_CALLBACK]];
597         Clock_Ip_axSelectorCallbacks[CallbackIndex].Reset(&Config->Selectors[Index - 1U]);
598     }
599 
600     for (Index = Config->FracDivsCount; Index > 0U; Index--)    /* Put in reset state all fractional dividers from configuration */
601     {
602         CallbackIndex = Clock_Ip_au8FractionalDividerCallbackIndex[Clock_Ip_au8ClockFeatures[Config->FracDivs[Index - 1U].Name][CLOCK_IP_CALLBACK]];
603         Clock_Ip_axFracDivCallbacks[CallbackIndex].Reset(&Config->FracDivs[Index - 1U]);
604     }
605 
606     for (Index = Config->PllsCount; Index > 0U; Index--)       /* Power down all plls from configuration */
607     {
608         CallbackIndex = Clock_Ip_au8PllCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Plls[Index - 1U].Name][CLOCK_IP_CALLBACK]];
609         Clock_Ip_axPllCallbacks[CallbackIndex].Reset(&Config->Plls[Index - 1U]);
610     }
611 
612     for (Index = Config->XoscsCount; Index > 0U; Index--)     /* Power down all xoscs from configuration */
613     {
614         CallbackIndex = Clock_Ip_au8XoscCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Xoscs[Index - 1U].Name][CLOCK_IP_CALLBACK]];
615         Clock_Ip_axExtOscCallbacks[CallbackIndex].Reset(&Config->Xoscs[Index - 1U]);
616     }
617 }
618 
619 #if (defined(CLOCK_IP_DEV_ERROR_DETECT))
620     #if (CLOCK_IP_DEV_ERROR_DETECT == STD_ON)
Clock_Ip_CheckClockConfiguration(Clock_Ip_ClockConfigType const * Config)621 static void Clock_Ip_CheckClockConfiguration(Clock_Ip_ClockConfigType const * Config)
622 {
623     Clock_Ip_CheckIrcoscClocks(Config);
624     Clock_Ip_CheckXoscClocks(Config);
625     Clock_Ip_CheckPllClocks(Config);
626     Clock_Ip_CheckExtSigClocks(Config);
627     Clock_Ip_CheckSelectorClocks(Config);
628     Clock_Ip_CheckDividerClocks(Config);
629     Clock_Ip_CheckDividerTriggerClocks(Config);
630     Clock_Ip_CheckFracDividerClocks(Config);
631     Clock_Ip_CheckGateClocks(Config);
632     Clock_Ip_CheckPcfsClocks(Config);
633     Clock_Ip_CheckCmuClocks(Config);
634 }
635     #endif
636 #endif
637 /*==================================================================================================
638 *                                        GLOBAL FUNCTIONS
639 ==================================================================================================*/
640 
641 /*FUNCTION******************************************************************************
642  *
643  * Function Name : Clock_Ip_Init
644  *
645  * Description   : Set clock configuration according to pre-defined structure.
646  *                 This function sets system to target clock configuration; It sets the
647  *                 clock modules registers for clock mode change.
648  *
649  *                 If external clock is used in the target mode, please make sure it is
650  *                 enabled, for example, if the external oscillator is used, please setup correctly.
651  *
652  * @implements Clock_Ip_Init_Activity
653  * END**********************************************************************************/
Clock_Ip_Init(Clock_Ip_ClockConfigType const * Config)654 Clock_Ip_StatusType Clock_Ip_Init(Clock_Ip_ClockConfigType const * Config)
655 {
656     Clock_Ip_StatusType ClockStatus = CLOCK_IP_ERROR;
657 
658     Clock_Ip_PllStatusType PllStatus;
659 
660     (void)Clock_Ip_au8XoscCallbackIndex;
661     (void)Clock_Ip_axExtOscCallbacks;
662     (void)Clock_Ip_au8IrcoscCallbackIndex;
663     (void)Clock_Ip_axIntOscCallbacks;
664     (void)Clock_Ip_au8PcfsCallbackIndex;
665     (void)Clock_Ip_axPcfsCallbacks;
666     (void)Clock_Ip_au8DividerCallbackIndex;
667     (void)Clock_Ip_axDividerCallbacks;
668 
669     (void)CLOCK_IP_MODULE_INSTANCE;
670     (void)CLOCK_IP_CALLBACK;
671     (void)CLOCK_IP_EXTENSION_INDEX;
672     (void)CLOCK_IP_POWER_MODE_INDEX;
673     (void)CLOCK_IP_SELECTOR_INDEX;
674     (void)CLOCK_IP_DIVIDER_INDEX;
675     (void)CLOCK_IP_GATE_INDEX;
676     (void)CLOCK_IP_PCFS_INDEX;
677     (void)CLOCK_IP_CMU_INDEX;
678 
679 #if (defined(CLOCK_IP_ENABLE_USER_MODE_SUPPORT))
680   #if (STD_ON == CLOCK_IP_ENABLE_USER_MODE_SUPPORT)
681     /* Set user access allowed for Clock */
682     Clock_Ip_Command(Config, CLOCK_IP_SET_USER_ACCESS_ALLOWED_COMMAND);
683   #endif
684 #endif
685     CLOCK_IP_DEV_ASSERT(NULL_PTR != Config);
686 
687     Clock_Ip_InitClock(Config);
688 
689     if (DriverContext.ClockTreeIsConsumingPll)
690     {
691         PllStatus = Clock_Ip_GetPllStatus();
692         if (CLOCK_IP_PLL_LOCKED == PllStatus)
693         {
694             Clock_Ip_DistributePll();
695             ClockStatus = CLOCK_IP_SUCCESS;
696         }
697     }
698     else
699     {
700         ClockStatus = CLOCK_IP_SUCCESS;
701     }
702 
703     return ClockStatus;
704 }
705 
706 /*FUNCTION******************************************************************************
707  *
708  * Function Name : Clock_Ip_InitClock
709  *
710  * Description   : Set the PLL and other MCU specific clock options.
711  *                 This function initializes the PLL and other MCU specific clock options.
712  *                 The clock configuration parameters are provided via the configuration structure.
713  *
714  *                 This function shall start the PLL lock procedure (if PLL
715  *                 shall be initialized) and shall return without waiting until the PLL is locked.
716  *
717  * @implements Clock_Ip_InitClock_Activity
718  * END**********************************************************************************/
Clock_Ip_InitClock(Clock_Ip_ClockConfigType const * Config)719 void Clock_Ip_InitClock(Clock_Ip_ClockConfigType const * Config)
720 {
721     uint32 CallbackIndex;
722     uint32 Index;
723 
724 #if (defined(CLOCK_IP_DEV_ERROR_DETECT) && (CLOCK_IP_DEV_ERROR_DETECT == STD_ON))
725     /* Check clock elements from clock configuration */
726     Clock_Ip_CheckClockConfiguration(Config);
727 #endif
728 
729     CLOCK_IP_DEV_ASSERT(NULL_PTR != Config);
730 
731     /* Save the current clock configuration to be used by "Clock_Ip_DistributePllClock". */
732     Clock_Ip_pxConfig = Config;
733 
734     /* Platform specific initialization:
735      * DFS reset, FIRC_CLK configuration etc. */
736     Clock_Ip_Command(Config, CLOCK_IP_INITIALIZE_PLATFORM_COMMAND);
737 
738     /* Clear all the settings for CMU0/1/2... */
739     /* In case one clock configuration has the CMU disabled, then need to make the transition to
740     reset state of CMU modules. */
741     if (NULL_PTR != Clock_Ip_pxConfig)
742     {
743         for (Index = 0U; Index < Config->CmusCount; Index++)    /* Reset all clock monitor units from previous configuration. */
744         {
745             CallbackIndex = Clock_Ip_au8CmuCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Cmus[Index].Name][CLOCK_IP_CALLBACK]];
746             Clock_Ip_axCmuCallbacks[CallbackIndex].Reset(&Config->Cmus[Index]);
747         }
748     }
749 
750     /*********************************************************************
751      ***  Ramp down to safe configuration. Reset elements from clock tree:
752      ***  selectors, fractional dividers, plls and xoscs
753      ***********************************************************************/
754     Clock_Ip_ResetClockConfiguration(Config);
755 
756     /*******************************************************
757      *** Load the new configuration. Selectors that might
758      *** be clocked from PLLs shouldn't be configured.
759      *******************************************************/
760 
761     for (Index = 0U; Index < Config->IrcoscsCount; Index++)   /* Set internal oscillators from configuration */
762     {
763         CallbackIndex = Clock_Ip_au8IrcoscCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Ircoscs[Index].Name][CLOCK_IP_CALLBACK]];
764         Clock_Ip_axIntOscCallbacks[CallbackIndex].Set(&Config->Ircoscs[Index]);
765     }
766 
767     for (Index = 0U; Index < Config->XoscsCount; Index++)     /* Configure all xoscs from configuration */
768     {
769         CallbackIndex = Clock_Ip_au8XoscCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Xoscs[Index].Name][CLOCK_IP_CALLBACK]];
770         Clock_Ip_axExtOscCallbacks[CallbackIndex].Set(&Config->Xoscs[Index]);
771     }
772 
773     /* Initialize clock objects, internal driver data */
774     Clock_Ip_UpdateDriverContext(Config);
775 
776     /* Configure the PCFS  */
777     for (Index = 0U; Index < Config->PcfsCount; Index++)       /* Configure all progressive frequency switching clocks from configuration */
778     {
779         CallbackIndex = Clock_Ip_au8PcfsCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Pcfs[Index].Name][CLOCK_IP_CALLBACK]];
780         Clock_Ip_axPcfsCallbacks[CallbackIndex].Set(&Config->Pcfs[Index], Index);
781     }
782 
783     /* Configure the clock divider triggers that are under MCU control */
784     for (Index = 0U; Index < Config->DividerTriggersCount; Index++)    /* Set divider triggers from configuration. */
785     {
786         CallbackIndex = Clock_Ip_au8DividerTriggerCallbackIndex[Clock_Ip_au8ClockFeatures[Config->DividerTriggers[Index].Name][CLOCK_IP_CALLBACK]];
787         Clock_Ip_axDividerTriggerCallbacks[CallbackIndex].Configure(&Config->DividerTriggers[Index]);
788     }
789 
790     /* Configure the clock dividers that are under MCU control */
791     for (Index = 0U; Index < Config->DividersCount; Index++)    /* Set dividers from configuration. */
792     {
793         CallbackIndex = Clock_Ip_au8DividerCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Dividers[Index].Name][CLOCK_IP_CALLBACK]];
794         Clock_Ip_axDividerCallbacks[CallbackIndex].Set(&Config->Dividers[Index]);
795     }
796 
797     /* Trigger update for all divider trigger that are under MCU control */
798     for (Index = 0U; Index < Config->DividerTriggersCount; Index++)    /* Set divider triggers from configuration. */
799     {
800         CallbackIndex = Clock_Ip_au8DividerTriggerCallbackIndex[Clock_Ip_au8ClockFeatures[Config->DividerTriggers[Index].Name][CLOCK_IP_CALLBACK]];
801         Clock_Ip_axDividerTriggerCallbacks[CallbackIndex].TriggerUpdate(&Config->DividerTriggers[Index]);
802     }
803 
804     /* Configure PLL clock generators */
805     for (Index = 0U; Index < Config->PllsCount; Index++)       /* Configure all plls from configuration asynchronously. Do not enable. */
806     {
807         CallbackIndex = Clock_Ip_au8PllCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Plls[Index].Name][CLOCK_IP_CALLBACK]];
808         Clock_Ip_axPllCallbacks[CallbackIndex].Set(&Config->Plls[Index]);
809     }
810 
811     for (Index = 0U; Index < Config->CmusCount; Index++)     /* Set the Clock Monitoring Units that are under mcu control. Cmus are not enabled. */
812     {
813         CallbackIndex = Clock_Ip_au8CmuCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Cmus[Index].Name][CLOCK_IP_CALLBACK]];
814         Clock_Ip_axCmuCallbacks[CallbackIndex].Set(&Config->Cmus[Index], Index);
815     }
816 
817     for (Index = 0U; Index < Config->XoscsCount; Index++)     /* Wait for all xoscs from configuration to lock */
818     {
819         CallbackIndex = Clock_Ip_au8XoscCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Xoscs[Index].Name][CLOCK_IP_CALLBACK]];
820         Clock_Ip_axExtOscCallbacks[CallbackIndex].Complete(&Config->Xoscs[Index]);
821     }
822 
823     /* Configure PLL clock generators */
824     for (Index = 0U; Index < Config->PllsCount; Index++)       /* Enable plls according to configuration asynchronously. Do not wait. */
825     {
826         CallbackIndex = Clock_Ip_au8PllCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Plls[Index].Name][CLOCK_IP_CALLBACK]];
827         Clock_Ip_axPllCallbacks[CallbackIndex].Enable(&Config->Plls[Index]);
828     }
829 
830     /* Configure fractional dividers */
831     /* Note: The DFS configuration might actually need to be done after we
832      * know that the PLLs are all locked in "Clock_Ip_GetPllStatus". */
833     for (Index = 0U; Index < Config->FracDivsCount; Index++)    /* Configure all fractional dividers from configuration asynchronously. Do not wait. */
834     {
835         CallbackIndex = Clock_Ip_au8FractionalDividerCallbackIndex[Clock_Ip_au8ClockFeatures[Config->FracDivs[Index].Name][CLOCK_IP_CALLBACK]];
836         Clock_Ip_axFracDivCallbacks[CallbackIndex].Set(&Config->FracDivs[Index]);
837     }
838 
839     DriverContext.ClockTreeIsConsumingPll = FALSE;                                  /* Check if clock tree is using a PLL output */
840 #if (defined(CLOCK_IP_SUPPORTS_WAIT_STATES))
841 #if(CLOCK_IP_SUPPORTS_WAIT_STATES == STD_ON)
842     DriverContext.WaitStatesAreSupported = TRUE;                                    /* Wait states are supported */
843 #else
844     DriverContext.WaitStatesAreSupported = FALSE;                                   /* Wait states are not supported */
845 #endif /*CLOCK_IP_SUPPORTS_WAIT_STATES == STD_ON */
846 #else
847     DriverContext.WaitStatesAreSupported = FALSE;                                   /* Wait states are not supported */
848 #endif /* #if (defined(CLOCK_IP_SUPPORTS_WAIT_STATES)) */
849     DriverContext.HwPllsNo = CLOCK_IP_NUMBER_OF_HARDWARE_PLL;                       /* Number of plls */
850     DriverContext.HwDfsNo = CLOCK_IP_NUMBER_OF_HARDWARE_DFS;                        /* Number of fractional dividers */
851 
852 
853     /* Configure wait states */
854     Clock_Ip_SetWaitStates();
855 
856 
857     /* Switch the clock multiplexers under MCU control to the configured source clocks */
858     /* Note: if the configured source clock of a ClockMux is the output clock of a PLL/DFS,
859      * the configuration will be skipped and the respective ClockMux will be switched in
860      * the "Clock_Ip_DistributePllClock" function instead, when the source clock will have
861      * stabilized already. */
862     for (Index = 0U; Index < Config->SelectorsCount; Index++)    /* Set only if selected inputs are not clocked from PLLs */
863     {
864         if ((PLL_TYPE != Clock_Ip_aeSourceTypeClockName[Config->Selectors[Index].Value]))
865         {
866 
867             CallbackIndex = Clock_Ip_au8SelectorCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Selectors[Index].Name][CLOCK_IP_CALLBACK]];
868             Clock_Ip_axSelectorCallbacks[CallbackIndex].Set(&Config->Selectors[Index]);
869         }
870         else
871         {
872             /* At least one mux is consuming pll */
873             DriverContext.ClockTreeIsConsumingPll = TRUE;
874         }
875     }
876 
877     /* Check if the clock tree is using a PLL output */
878     if ( FALSE == DriverContext.ClockTreeIsConsumingPll )
879     {
880         for (Index = 0U; Index < Config->GatesCount; Index++)    /* Set clock gates that are under clock control. */
881         {
882             CallbackIndex = Clock_Ip_au8GateCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Gates[Index].Name][CLOCK_IP_CALLBACK]];
883             Clock_Ip_axGateCallbacks[CallbackIndex].Set(&Config->Gates[Index]);
884         }
885 
886         /* Enable the Clock Monitoring Units ( CMU0 .. n ) according to configuration. */
887         for (Index = 0U; Index < Config->CmusCount; Index++)
888         {
889             CallbackIndex = Clock_Ip_au8CmuCallbackIndex[Clock_Ip_au8ClockFeatures[Config->Cmus[Index].Name][CLOCK_IP_CALLBACK]];
890             Clock_Ip_axCmuCallbacks[CallbackIndex].Enable(&Config->Cmus[Index]);
891         }
892         /* Disable safe clock if it is supported by platform and it is configured/required. */
893         /* Note: Safe clock is the fast internal oscillator clock. It is clocking the clock tree until pll is distributed.
894          * At the end of configuration it can be disabled if it is supported on this platform and required/configured. */
895         Clock_Ip_Command(Config, CLOCK_IP_DISABLE_SAFE_CLOCK_COMMAND);
896     }
897     else
898     {
899         /* The clock tree is using at least one PLL/DFS output clock as source. */
900         /* The user must wait until the PLLs and DFSs are locked by polling Clock_Ip_GetPllStatus */
901         /* and then call "Clock_Ip_DistributePllClock" */
902     }
903 }
904 
905 /*FUNCTION******************************************************************************
906  *
907  * Function Name : Clock_Ip_GetPllStatus
908  * Description   : This function configures all clocks according to a clock configuration.
909  * If no configuration is received, no change will be processed in HW and clock driver
910  * will calculate frequencies only.
911  *
912  * @implements Clock_Ip_GetPllStatus_Activity
913  * END**********************************************************************************/
Clock_Ip_GetPllStatus(void)914 Clock_Ip_PllStatusType Clock_Ip_GetPllStatus(void)
915 {
916     Clock_Ip_PllStatusType RetValue = CLOCK_IP_PLL_STATUS_UNDEFINED;
917     Clock_Ip_PllStatusReturnType PllStatus;
918     Clock_Ip_DfsStatusType DfsStatus;
919 
920     uint32 Index;
921     uint32 CallbackIndex;
922 
923     for (Index = 0U; Index < DriverContext.HwPllsNo; Index++)
924     {
925         CallbackIndex = Clock_Ip_au8PllCallbackIndex[Clock_Ip_au8ClockFeatures[Clock_Ip_aeHwPllName[Index]][CLOCK_IP_CALLBACK]];
926         PllStatus = Clock_Ip_axPllCallbacks[CallbackIndex].Complete(Clock_Ip_aeHwPllName[Index]);
927         if (STATUS_PLL_UNLOCKED == PllStatus)
928         {
929             RetValue = CLOCK_IP_PLL_UNLOCKED;
930             break;
931         }
932         else
933         {
934             if (STATUS_PLL_LOCKED == PllStatus)
935             {
936                 RetValue = CLOCK_IP_PLL_LOCKED;
937             }
938         }
939     }
940 
941     if (CLOCK_IP_PLL_LOCKED == RetValue)
942     {
943         for (Index = 0U; Index < DriverContext.HwDfsNo; Index++)
944         {
945             CallbackIndex = Clock_Ip_au8FractionalDividerCallbackIndex[Clock_Ip_au8ClockFeatures[Clock_Ip_aeHwDfsName[Index]][CLOCK_IP_CALLBACK]];
946             DfsStatus = Clock_Ip_axFracDivCallbacks[CallbackIndex].Complete(Clock_Ip_aeHwDfsName[Index]);
947             if (STATUS_DFS_UNLOCKED == DfsStatus)
948             {
949                 RetValue = CLOCK_IP_PLL_UNLOCKED;
950                 break;
951             }
952         }
953     }
954 
955     return RetValue;
956 }
957 
958 /*FUNCTION******************************************************************************
959  *
960  * Function Name : Clock_Ip_DistributePll
961  * Description   : Function completes the PLL configuration and then activates the PLL clock to Mcu
962  * The function will not distribute the PLL clock if the driver state does not allow it, or the PLL is not stable.
963  *
964  * @implements Clock_Ip_DistributePll_Activity
965  * END**********************************************************************************/
Clock_Ip_DistributePll(void)966 void Clock_Ip_DistributePll(void)
967 {
968 
969     uint32 Index;
970     uint32 CallbackIndex;
971 
972     CLOCK_IP_DEV_ASSERT(NULL_PTR != Clock_Ip_pxConfig);
973     /* 'Clock_Ip_pxConfig' is set by Clock_Ip_InitClock().
974      *  It doesn't make sense to call PLL distribution without clock initialization. */
975     if (NULL_PTR != Clock_Ip_pxConfig)
976     {
977         for (Index = 0U; Index < Clock_Ip_pxConfig->SelectorsCount; Index++)    /* Set only if selected inputs are clocked from PLLs */
978         {
979             if (PLL_TYPE == Clock_Ip_aeSourceTypeClockName[Clock_Ip_pxConfig->Selectors[Index].Value])
980             {
981 
982                 CallbackIndex = Clock_Ip_au8SelectorCallbackIndex[Clock_Ip_au8ClockFeatures[Clock_Ip_pxConfig->Selectors[Index].Name][CLOCK_IP_CALLBACK]];
983                 Clock_Ip_axSelectorCallbacks[CallbackIndex].Set(&Clock_Ip_pxConfig->Selectors[Index]);
984             }
985         }
986 
987         /* In the case of PLL is enabled but PLL clock source is not used by any clock Mux.
988            So, no need to re-configure for CMUs, because they are configured by Clock_Ip_InitClock */
989         /* Check if the clock tree is using a PLL output */
990         if ( DriverContext.ClockTreeIsConsumingPll )
991         {
992             for (Index = 0U; Index < Clock_Ip_pxConfig->GatesCount; Index++)    /* Set clock gates that are under clock control. */
993             {
994                 CallbackIndex = Clock_Ip_au8GateCallbackIndex[Clock_Ip_au8ClockFeatures[Clock_Ip_pxConfig->Gates[Index].Name][CLOCK_IP_CALLBACK]];
995                 Clock_Ip_axGateCallbacks[CallbackIndex].Set(&Clock_Ip_pxConfig->Gates[Index]);
996             }
997 
998             /* Enable the Clock Monitoring Units ( CMU0 .. n ) according to configuration. */
999             for (Index = 0U; Index < Clock_Ip_pxConfig->CmusCount; Index++)
1000             {
1001                 CallbackIndex = Clock_Ip_au8CmuCallbackIndex[Clock_Ip_au8ClockFeatures[Clock_Ip_pxConfig->Cmus[Index].Name][CLOCK_IP_CALLBACK]];
1002                 Clock_Ip_axCmuCallbacks[CallbackIndex].Enable(&Clock_Ip_pxConfig->Cmus[Index]);
1003             }
1004 
1005             /* Disable safe clock if it is supported by platform and it is configured/required. */
1006             /* Note: Safe clock is the fast internal oscillator clock. It is clocking the clock tree until pll is distributed.
1007              * At the end of configuration it can be disabled if it is supported on this platform and required/configured. */
1008             Clock_Ip_Command(Clock_Ip_pxConfig, CLOCK_IP_DISABLE_SAFE_CLOCK_COMMAND);
1009         }
1010     }
1011 }
1012 
1013 /*FUNCTION******************************************************************************
1014  *
1015  * Function Name : Clock_Ip_DisableClockMonitor
1016  * Description   : Disables a clock monitor.
1017  *
1018  * @implements Clock_Ip_DisableClockMonitor_Activity
1019  * END**********************************************************************************/
Clock_Ip_DisableClockMonitor(Clock_Ip_NameType ClockName)1020 void Clock_Ip_DisableClockMonitor(Clock_Ip_NameType ClockName)
1021 {
1022 
1023     uint32 CallbackIndex;
1024 
1025     CallbackIndex = Clock_Ip_au8CmuCallbackIndex[Clock_Ip_au8ClockFeatures[ClockName][CLOCK_IP_CALLBACK]];
1026     Clock_Ip_axCmuCallbacks[CallbackIndex].Disable(ClockName);
1027 }
1028 
1029 /*FUNCTION******************************************************************************
1030  *
1031  * Function Name : Clock_Ip_InstallNotificationsCallback
1032  * Description   : This function installs a callback for clock notifications.
1033  *
1034  * @implements Clock_Ip_InstallNotificationsCallback_Activity
1035  * END**********************************************************************************/
Clock_Ip_InstallNotificationsCallback(Clock_Ip_NotificationsCallbackType Callback)1036 void Clock_Ip_InstallNotificationsCallback(Clock_Ip_NotificationsCallbackType Callback)
1037 {
1038     CLOCK_IP_DEV_ASSERT(NULL_PTR != Callback);
1039 
1040     Clock_Ip_pfkNotificationsCallback = Callback;
1041 }
1042 
1043 /*FUNCTION******************************************************************************
1044  *
1045  * Function Name : Clock_Ip_DisableModuleClock
1046  * Description   : Disables clock for a peripheral.
1047  *
1048  * @implements Clock_Ip_DisableModuleClock_Activity
1049  * END**********************************************************************************/
Clock_Ip_DisableModuleClock(Clock_Ip_NameType ClockName)1050 void Clock_Ip_DisableModuleClock(Clock_Ip_NameType ClockName)
1051 {
1052 
1053     uint32 CallbackIndex;
1054 
1055     CallbackIndex = Clock_Ip_au8GateCallbackIndex[Clock_Ip_au8ClockFeatures[ClockName][CLOCK_IP_CALLBACK]];
1056     Clock_Ip_axGateCallbacks[CallbackIndex].Update(ClockName,TRUE);
1057 }
1058 
1059 /*FUNCTION******************************************************************************
1060  *
1061  * Function Name : Clock_Ip_EnableModuleClock
1062  * Description   : Enable clock for a peripheral.
1063  *
1064  * @implements Clock_Ip_EnableModuleClock_Activity
1065  * END**********************************************************************************/
Clock_Ip_EnableModuleClock(Clock_Ip_NameType ClockName)1066 void Clock_Ip_EnableModuleClock(Clock_Ip_NameType ClockName)
1067 {
1068 
1069     uint32 CallbackIndex;
1070 
1071     CallbackIndex = Clock_Ip_au8GateCallbackIndex[Clock_Ip_au8ClockFeatures[ClockName][CLOCK_IP_CALLBACK]];
1072     Clock_Ip_axGateCallbacks[CallbackIndex].Update(ClockName,FALSE);
1073 }
1074 
1075 
1076 #ifdef CLOCK_IP_POWER_MODE_CHANGE_NOTIFICATION
1077 #if (CLOCK_IP_POWER_MODE_CHANGE_NOTIFICATION == STD_ON)
1078 /*FUNCTION******************************************************************************
1079  *
1080  * Function Name : Clock_Ip_PowerModeChangeNotification
1081  * Description   : Notifies clock driver when a power mode is changed.
1082  *
1083  * @implements Clock_Ip_PowerModeChangeNotification_Activity
1084  * END**********************************************************************************/
Clock_Ip_PowerModeChangeNotification(Clock_Ip_PowerModesType PowerMode,Clock_Ip_PowerNotificationType Notification)1085 void Clock_Ip_PowerModeChangeNotification(Clock_Ip_PowerModesType PowerMode,Clock_Ip_PowerNotificationType Notification)
1086 {
1087     Clock_Ip_bSentFromUpdateDriverContext  = FALSE;
1088     Clock_Ip_Command(Clock_Ip_pxConfig, CLOCK_IP_INITIALIZE_CLOCK_OBJECTS_COMMAND);
1089 
1090     Clock_Ip_ClockPowerModeChangeNotification(PowerMode, Notification);
1091 }
1092 #endif
1093 #endif
1094 
1095 
1096 #if (defined(CLOCK_IP_GET_FREQUENCY_API))
1097   #if (CLOCK_IP_GET_FREQUENCY_API == STD_ON)
1098 /*FUNCTION**********************************************************************
1099  *
1100  * Function Name : Clock_Ip_GetClockFrequency
1101  * Description   : This function returns the frequency of a given clock
1102  *
1103  * @implements Clock_Ip_GetClockFrequency_Activity
1104  * END**************************************************************************/
Clock_Ip_GetClockFrequency(Clock_Ip_NameType ClockName)1105 uint32 Clock_Ip_GetClockFrequency(Clock_Ip_NameType ClockName)
1106 {
1107 #if (defined(CLOCK_IP_DEV_ERROR_DETECT))
1108   #if (CLOCK_IP_DEV_ERROR_DETECT == STD_ON)
1109     CLOCK_IP_DEV_ASSERT((((uint32)ClockName) < ((uint32)CLOCK_IP_NAMES_NO)) && (THE_LAST_PRODUCER_CLK != ClockName));
1110   #endif
1111 #endif
1112     return Clock_Ip_GetFreq(ClockName);
1113 }
1114     #endif
1115 #endif
1116 
1117 
1118 
1119 /*FUNCTION**********************************************************************
1120  *
1121  * Function Name : Clock_Ip_SetWaitStates
1122  * Description   : Hardware wait states are not supported, checking function.
1123  *
1124  *END**************************************************************************/
Clock_Ip_SetWaitStates(void)1125 static void Clock_Ip_SetWaitStates(void)
1126 {
1127     uint32 Counter = CLOCK_IP_WAIT_STATES_DELAY;
1128 
1129     /* HW doesn't support wait states configuration */
1130     if (DriverContext.WaitStatesAreSupported)
1131     {
1132 #if (defined(CLOCK_IP_DEV_ERROR_DETECT))
1133   #if (CLOCK_IP_DEV_ERROR_DETECT == STD_ON)
1134         /* Error, software shouldn't reach this point,
1135            hardware doesn't support wait states */
1136         CLOCK_IP_DEV_ASSERT(FALSE);
1137   #endif
1138 #endif
1139         /* Wait states are not supported by HW,
1140            insert a delay . */
1141 
1142         do
1143         {
1144             Counter--;
1145         }
1146         while(Counter > 0u);
1147     }
1148 }
1149 
1150 
1151 /*FUNCTION**********************************************************************
1152  *
1153  * Function Name : Clock_Ip_ReportClockErrors
1154  * Description   : Report clock error
1155  *
1156  *END**************************************************************************/
Clock_Ip_ReportClockErrors(Clock_Ip_NotificationType Error,Clock_Ip_NameType ClockName)1157 void Clock_Ip_ReportClockErrors(Clock_Ip_NotificationType Error, Clock_Ip_NameType ClockName)
1158 {
1159     Clock_Ip_pfkNotificationsCallback(Error,ClockName);
1160 }
1161 
1162 /*FUNCTION**********************************************************************
1163  *
1164  * Function Name : Clock_Ip_StartTimeout
1165  * Description   : Checks for timeout condition
1166  *
1167  *END**************************************************************************/
Clock_Ip_StartTimeout(uint32 * StartTimeOut,uint32 * ElapsedTimeOut,uint32 * TimeoutTicksOut,uint32 TimeoutUs)1168 void Clock_Ip_StartTimeout(uint32 *StartTimeOut,
1169                        uint32 *ElapsedTimeOut,
1170                        uint32 *TimeoutTicksOut,
1171                        uint32 TimeoutUs)
1172 {
1173     *StartTimeOut    = OsIf_GetCounter(CLOCK_IP_TIMEOUT_TYPE);
1174     *ElapsedTimeOut  = 0U;
1175     *TimeoutTicksOut = OsIf_MicrosToTicks(TimeoutUs, CLOCK_IP_TIMEOUT_TYPE);
1176 }
1177 
1178 /*FUNCTION**********************************************************************
1179  *
1180  * Function Name : Clock_Ip_TimeoutExpired
1181  * Description   : Checks for timeout expiration condition
1182  *
1183  *END**************************************************************************/
Clock_Ip_TimeoutExpired(uint32 * StartTimeInOut,uint32 * ElapsedTimeInOut,uint32 TimeoutTicks)1184 boolean Clock_Ip_TimeoutExpired(uint32 *StartTimeInOut,
1185                             uint32 *ElapsedTimeInOut,
1186                             uint32 TimeoutTicks)
1187 {
1188     boolean RetVal = FALSE;
1189     *ElapsedTimeInOut += OsIf_GetElapsed(StartTimeInOut, CLOCK_IP_TIMEOUT_TYPE);
1190 
1191     if (*ElapsedTimeInOut >= TimeoutTicks)
1192     {
1193         RetVal = TRUE;
1194     }
1195     return RetVal;
1196 }
1197 
1198 /*FUNCTION**********************************************************************
1199  *
1200  * Function Name : Clock_Ip_WriteRegisterValues
1201  * Description   : Write register values
1202  *
1203  *END**************************************************************************/
1204 #if (defined(CLOCK_IP_REGISTER_VALUES_OPTIMIZATION) && (CLOCK_IP_REGISTER_VALUES_OPTIMIZATION == STD_ON))
Clock_Ip_WriteRegisterValues(const Clock_Ip_RegisterIndexType * Indexes)1205 void Clock_Ip_WriteRegisterValues(const Clock_Ip_RegisterIndexType *Indexes)
1206 {
1207     uint32 *RegAddr;
1208     uint32 RegData;
1209     uint32 Index;
1210 
1211     CLOCK_IP_DEV_ASSERT(NULL_PTR != Clock_Ip_pxConfig);
1212     /* 'Clock_Ip_pxConfig' is set by Clock_Ip_InitClock().
1213      *  It doesn't make sense to call this function without clock initialization. */
1214     if (NULL_PTR != Clock_Ip_pxConfig)
1215     {
1216         /* Register values array must be valid */
1217         CLOCK_IP_DEV_ASSERT(NULL_PTR != Clock_Ip_pxConfig->RegValues);
1218 
1219         /* Valus of indexes must be valid */
1220         CLOCK_IP_DEV_ASSERT(Indexes->StartIndex < Indexes->EndIndex);
1221 
1222         for (Index = Indexes->StartIndex; Index < Indexes->EndIndex; Index++)
1223         {
1224             RegAddr = (*Clock_Ip_pxConfig->RegValues)[Index].RegisterAddr;
1225             RegData = (*Clock_Ip_pxConfig->RegValues)[Index].RegisterData;
1226             *RegAddr = RegData;
1227         }
1228     }
1229 }
1230 #endif
1231 
1232 /* Clock stop section code */
1233 #define MCU_STOP_SEC_CODE
1234 
1235 #include "Mcu_MemMap.h"
1236 
1237 #ifdef __cplusplus
1238 }
1239 #endif
1240 
1241 /** @} */
1242