1 /*
2  * Copyright 2020-2023 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /**
8 *   @file       Clock_Ip_ProgFreqSwitch.c
9 *   @version    3.0.0
10 *
11 *   @brief   CLOCK driver implementations.
12 *   @details CLOCK driver implementations.
13 *
14 *   @addtogroup CLOCK_DRIVER Clock Ip Driver
15 *   @{
16 */
17 
18 
19 #ifdef __cplusplus
20 extern "C"{
21 #endif
22 
23 
24 /*==================================================================================================
25 *                                          INCLUDE FILES
26 * 1) system and project includes
27 * 2) needed interfaces from external units
28 * 3) internal and external interfaces from this unit
29 ==================================================================================================*/
30 
31 #include "Clock_Ip_Private.h"
32 
33 /*==================================================================================================
34                                SOURCE FILE VERSION INFORMATION
35 ==================================================================================================*/
36 #define CLOCK_IP_PROGFREQSWITCH_VENDOR_ID_C                      43
37 #define CLOCK_IP_PROGFREQSWITCH_AR_RELEASE_MAJOR_VERSION_C       4
38 #define CLOCK_IP_PROGFREQSWITCH_AR_RELEASE_MINOR_VERSION_C       7
39 #define CLOCK_IP_PROGFREQSWITCH_AR_RELEASE_REVISION_VERSION_C    0
40 #define CLOCK_IP_PROGFREQSWITCH_SW_MAJOR_VERSION_C               3
41 #define CLOCK_IP_PROGFREQSWITCH_SW_MINOR_VERSION_C               0
42 #define CLOCK_IP_PROGFREQSWITCH_SW_PATCH_VERSION_C               0
43 
44 /*==================================================================================================
45 *                                     FILE VERSION CHECKS
46 ==================================================================================================*/
47 /* Check if Clock_Ip_ProgFreqSwitch.c file and Clock_Ip_Private.h file are of the same vendor */
48 #if (CLOCK_IP_PROGFREQSWITCH_VENDOR_ID_C != CLOCK_IP_PRIVATE_VENDOR_ID)
49     #error "Clock_Ip_ProgFreqSwitch.c and Clock_Ip_Private.h have different vendor ids"
50 #endif
51 
52 /* Check if Clock_Ip_ProgFreqSwitch.c file and Clock_Ip_Private.h file are of the same Autosar version */
53 #if ((CLOCK_IP_PROGFREQSWITCH_AR_RELEASE_MAJOR_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_MAJOR_VERSION) || \
54      (CLOCK_IP_PROGFREQSWITCH_AR_RELEASE_MINOR_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_MINOR_VERSION) || \
55      (CLOCK_IP_PROGFREQSWITCH_AR_RELEASE_REVISION_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_REVISION_VERSION) \
56     )
57     #error "AutoSar Version Numbers of Clock_Ip_ProgFreqSwitch.c and Clock_Ip_Private.h are different"
58 #endif
59 
60 /* Check if Clock_Ip_ProgFreqSwitch.c file and Clock_Ip_Private.h file are of the same Software version */
61 #if ((CLOCK_IP_PROGFREQSWITCH_SW_MAJOR_VERSION_C != CLOCK_IP_PRIVATE_SW_MAJOR_VERSION) || \
62      (CLOCK_IP_PROGFREQSWITCH_SW_MINOR_VERSION_C != CLOCK_IP_PRIVATE_SW_MINOR_VERSION) || \
63      (CLOCK_IP_PROGFREQSWITCH_SW_PATCH_VERSION_C != CLOCK_IP_PRIVATE_SW_PATCH_VERSION) \
64     )
65     #error "Software Version Numbers of Clock_Ip_ProgFreqSwitch.c and Clock_Ip_Private.h are different"
66 #endif
67 
68 /*==================================================================================================
69 *                           LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
70 ==================================================================================================*/
71 
72 /*==================================================================================================
73 *                                          LOCAL MACROS
74 ==================================================================================================*/
75 #ifdef CLOCK_IP_CGM_X_PCFS_SDUR_DIVC_DIVE_DIVS
76 /* Pcfs settings that are dependent on device */
77 #define CLOCK_IP_A_MAX_SIZE 6U
78 
79 /* microA per MHz */
80 #define CLOCK_IP_DYNAMIC_IDD_CHANGE 2360U
81 
82 #define CLOCK_IP_DIVIDE_BY_1000000                              1000000U
83 #define CLOCK_IP_DIVIDE_BY_100000                               100000U
84 #define CLOCK_IP_CONSTANT_2048000                               (1024U * 2000U)
85 #endif
86 
87 /*==================================================================================================
88 *                                         LOCAL CONSTANTS
89 ==================================================================================================*/
90 
91 /* Clock start constant section data */
92 #define MCU_START_SEC_CONST_32
93 #include "Mcu_MemMap.h"
94 
95 #ifdef CLOCK_IP_CGM_X_PCFS_SDUR_DIVC_DIVE_DIVS
96 static const uint32 AMax[CLOCK_IP_A_MAX_SIZE] = {0U,5U,10U,15U,20U,100U};
97 static const uint32 PcfsRate[CLOCK_IP_A_MAX_SIZE] = {0U,12U,48U,112U,184U,1000U};
98 #endif
99 
100 /* Clock stop constant section data */
101 #define MCU_STOP_SEC_CONST_32
102 #include "Mcu_MemMap.h"
103 
104 /*==================================================================================================
105 *                                         LOCAL VARIABLES
106 ==================================================================================================*/
107 
108 /* Clock start initialized section data */
109 #define MCU_START_SEC_VAR_CLEARED_32
110 #include "Mcu_MemMap.h"
111 
112 #ifdef CLOCK_IP_CGM_X_PCFS_SDUR_DIVC_DIVE_DIVS
113 static uint32 HashPfs[CLOCK_IP_PCFS_COUNT];
114 #endif
115 
116 /* Clock stop initialized section data */
117 #define MCU_STOP_SEC_VAR_CLEARED_32
118 #include "Mcu_MemMap.h"
119 
120 /*==================================================================================================
121 *                                        GLOBAL VARIABLES
122 ==================================================================================================*/
123 
124 /*==================================================================================================
125 *                                    LOCAL FUNCTION PROTOTYPES
126 ==================================================================================================*/
127 /* Clock start section code */
128 #define MCU_START_SEC_CODE
129 
130 #include "Mcu_MemMap.h"
131 
132 
133 static void Clock_Ip_ProgressiveFrequencyClockSwitchEmpty(  Clock_Ip_PcfsConfigType const* Config,
134                                                             uint32 Index
135                                                           );
136 #ifdef CLOCK_IP_CGM_X_PCFS_SDUR_DIVC_DIVE_DIVS
137 static void Clock_Ip_CgmXPcfsSdurDivcDiveDivs(  Clock_Ip_PcfsConfigType const *Config,
138                                                 uint32 CfgIndex
139                                               );
140 #endif
141 
142 /* Clock stop section code */
143 #define MCU_STOP_SEC_CODE
144 
145 #include "Mcu_MemMap.h"
146 /*==================================================================================================
147 *                                         LOCAL FUNCTIONS
148 ==================================================================================================*/
149 
150 
151 /* Clock start section code */
152 #define MCU_START_SEC_CODE
153 
154 #include "Mcu_MemMap.h"
155 
Clock_Ip_ProgressiveFrequencyClockSwitchEmpty(Clock_Ip_PcfsConfigType const * Config,uint32 Index)156 static void Clock_Ip_ProgressiveFrequencyClockSwitchEmpty(  Clock_Ip_PcfsConfigType const* Config,
157                                                             uint32 Index
158                                                           )
159 {
160     (void)Config;
161     (void)Index;
162     /* No implementation */
163 }
164 
165 #ifdef CLOCK_IP_CGM_X_PCFS_SDUR_DIVC_DIVE_DIVS
Clock_Ip_CgmXPcfsSdurDivcDiveDivs(Clock_Ip_PcfsConfigType const * Config,uint32 CfgIndex)166 static void Clock_Ip_CgmXPcfsSdurDivcDiveDivs(  Clock_Ip_PcfsConfigType const *Config,
167                                                 uint32 CfgIndex
168                                               )
169 {
170     volatile Clock_Ip_CgmPcfsType* CgmPcfsBase;
171     uint32 HwIndex;
172 
173     uint32 Finput = 0U;
174     uint32 Fsafe = 0U;
175     uint32 AmaxBrut;
176     uint32 Rate = 0U;
177     uint32 Index;
178     uint32 Var1;
179     uint32 Var2;
180     uint32 Var3;
181     uint32 K;
182 
183     uint32 Sdur;
184     uint32 DivcInit;
185     uint32 DivcRate;
186     uint32 DivStartValue;
187     uint32 DivEndValue;
188 
189     if (NULL_PTR != Config)
190     {
191         CgmPcfsBase  = Clock_Ip_apxCgmPcfs[Clock_Ip_au8ClockFeatures[Config->SelectorName][CLOCK_IP_MODULE_INSTANCE]];
192         HwIndex      = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_PCFS_INDEX];
193 
194         #if (defined(CLOCK_IP_DEV_ERROR_DETECT) && (CLOCK_IP_DEV_ERROR_DETECT == STD_ON))
195         CLOCK_IP_DEV_ASSERT(Config->SelectorName != RESERVED_CLK);
196         #endif
197 
198         if (HashPfs[CfgIndex] != ((((uint32)Config->ClockSourceFrequency) ^ ((uint32)Config->MaxAllowableIDDchange) ^ ((uint32)Config->Name)  ^ ((uint32)Config->SelectorName) ^ ((uint32)Config->StepDuration))))
199         {
200             HashPfs[CfgIndex] = ((((uint32)Config->ClockSourceFrequency) ^ ((uint32)Config->MaxAllowableIDDchange) ^ ((uint32)Config->Name)  ^ ((uint32)Config->SelectorName) ^ ((uint32)Config->StepDuration)));
201 
202             Finput = Config->ClockSourceFrequency / CLOCK_IP_DIVIDE_BY_1000000;
203         #if defined(CLOCK_IP_HAS_FIRC_CLK)
204             Fsafe = (*Clock_Ip_pxConfig->ConfiguredFrequencies)[Clock_Ip_FreqIds[FIRC_CLK]].ConfiguredFrequencyValue / CLOCK_IP_DIVIDE_BY_1000000;
205 
206 
207         #endif
208 
209         #if (defined(CLOCK_IP_DEV_ERROR_DETECT) && (CLOCK_IP_DEV_ERROR_DETECT == STD_ON))
210             CLOCK_IP_DEV_ASSERT(Finput != 0U);
211             CLOCK_IP_DEV_ASSERT(Fsafe != 0U);
212             CLOCK_IP_DEV_ASSERT(Config->MaxAllowableIDDchange != 0U);
213             CLOCK_IP_DEV_ASSERT(Config->StepDuration != 0U);
214         #endif
215 
216             /* Calculate amax=fchg/Finput */
217             AmaxBrut = (Config->MaxAllowableIDDchange * Config->StepDuration * CLOCK_IP_DIVIDE_BY_100000 / (Finput * CLOCK_IP_DYNAMIC_IDD_CHANGE));
218             Rate = AmaxBrut;
219 
220             /* Round pcfs rate by rounding amax */
221             if (AmaxBrut < AMax[0U])
222             {
223                 Rate = PcfsRate[0U];
224             }
225             else if (AmaxBrut > AMax[CLOCK_IP_A_MAX_SIZE-1U])
226             {
227                 Rate = PcfsRate[CLOCK_IP_A_MAX_SIZE-1U];
228             }
229             else
230             {
231                 for (Index = 1U; Index < (uint8)CLOCK_IP_A_MAX_SIZE; Index++)
232                 {
233                     if (AMax[Index-1U] < AmaxBrut)
234                     {
235                         Rate = PcfsRate[Index];
236                     }
237                 }
238             }
239 
240             /* Calculate K by using formula k = ceil(0.5 + sqrt(0.25 - (2000 * (1 -(Finput/fsafe)) / Rate))) */
241 
242             Var1 = 256U + ((CLOCK_IP_CONSTANT_2048000 * Finput) / (Fsafe * Rate)) - (CLOCK_IP_CONSTANT_2048000 / Rate);
243             Var2 = 1UL << 30U;   /* The second-to-top bit is set: use 1u << 14 for uint16 type; use 1uL<<30 for uint32 type  */
244             Var3 = 0U;
245 
246             /* Implement sqrt from K formula by using a square-root computing in embedded C */
247 
248             /* "one" starts at the highest power of four <= than the argument */
249             while (Var2 > Var1)
250             {
251                 Var2 = Var2 >> 2;
252             }
253             /* Implement sqrt from K formula by using a square-root computing in embedded C */
254 
255             while (Var2 != 0U)
256             {
257                 if (Var1 >= (Var3 + Var2))
258                 {
259                     Var1 = Var1 - (Var3 + Var2);
260                     Var3 = Var3 + (Var2 << 1U);
261                 }
262 
263                 Var3 = Var3 >> 1U;
264                 Var2 = Var2 >> 2U;
265             }
266 
267             K = (64U + 127U + (Var3 << 2U)) >> 7U;   /* Calculated K from k = ceil(0.5 + sqrt(0.25 - (2000 * (1 -(Fi/Fsafe)) / Rate))) */
268 
269             Sdur = Config->StepDuration * Fsafe;
270             DivcInit = Rate * K;
271             DivcRate = Rate;
272             DivStartValue = 999U + ((Rate * K * (K+1U)) >> 1U);
273             DivEndValue = (Finput * 1000U / Fsafe) - 1U;
274 
275             /* Configure pcfs registers */
276             CgmPcfsBase->PCFS_SDUR = MC_CGM_PCFS_SDUR_SDUR(Sdur);
277             CgmPcfsBase->PCFS[HwIndex].DIVC = MC_CGM_PCFS_DIVC_RATE(DivcRate) | MC_CGM_PCFS_DIVC_INIT(DivcInit);
278             CgmPcfsBase->PCFS[HwIndex].DIVE = MC_CGM_PCFS_DIVE_DIVE(DivEndValue);
279             CgmPcfsBase->PCFS[HwIndex].DIVS = MC_CGM_PCFS_DIVS_DIVS(DivStartValue);
280         }
281     }
282     else
283     {
284         (void)CfgIndex;
285         (void)CgmPcfsBase;
286         (void)HwIndex;
287         (void)Finput;
288         (void)Fsafe;
289         (void)AmaxBrut;
290         (void)Rate;
291         (void)Index;
292         (void)Var1;
293         (void)Var2;
294         (void)Var3;
295         (void)K;
296         (void)Sdur;
297         (void)DivcInit;
298         (void)DivcRate;
299         (void)DivStartValue;
300         (void)DivEndValue;
301     }
302 }
303 #endif
304 
305 /* Clock stop section code */
306 #define MCU_STOP_SEC_CODE
307 
308 #include "Mcu_MemMap.h"
309 
310 /*==================================================================================================
311 *                                        GLOBAL FUNCTIONS
312 ==================================================================================================*/
313 
314 /*==================================================================================================
315 *                                        GLOBAL CONSTANTS
316 ==================================================================================================*/
317 
318 /* Clock start constant section data */
319 #define MCU_START_SEC_CONST_UNSPECIFIED
320 
321 #include "Mcu_MemMap.h"
322 
323 const Clock_Ip_PcfsCallbackType Clock_Ip_axPcfsCallbacks[CLOCK_IP_PCFS_CALLBACKS_COUNT] =
324 {
325     {
326         Clock_Ip_ProgressiveFrequencyClockSwitchEmpty,     /* Set */
327 
328     },
329 #ifdef CLOCK_IP_CGM_X_PCFS_SDUR_DIVC_DIVE_DIVS
330     {
331         Clock_Ip_CgmXPcfsSdurDivcDiveDivs,              /* Set */
332     },
333 #endif
334 };
335 
336 /* Clock stop constant section data */
337 #define MCU_STOP_SEC_CONST_UNSPECIFIED
338 
339 #include "Mcu_MemMap.h"
340 
341 
342 #ifdef __cplusplus
343 }
344 #endif
345 
346 /** @} */
347