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