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