1 /*
2  * Copyright 2021-2022 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /**
8 *   @file       Clock_Ip_ProgFreqSwitch.c
9 *   @version    0.9.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               0
41 #define CLOCK_IP_PROGFREQSWITCH_SW_MINOR_VERSION_C               9
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_NO];
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, uint32 Index);
134 #ifdef CLOCK_IP_CGM_X_PCFS_SDUR_DIVC_DIVE_DIVS
135 static void Clock_Ip_CgmXPcfsSdurDivcDiveDivs(Clock_Ip_PcfsConfigType const *Config, uint32 CfgIndex);
136 #endif
137 
138 /* Clock stop section code */
139 #define MCU_STOP_SEC_CODE
140 
141 #include "Mcu_MemMap.h"
142 /*==================================================================================================
143 *                                         LOCAL FUNCTIONS
144 ==================================================================================================*/
145 
146 
147 /* Clock start section code */
148 #define MCU_START_SEC_CODE
149 
150 #include "Mcu_MemMap.h"
151 
Clock_Ip_ProgressiveFrequencyClockSwitchEmpty(Clock_Ip_PcfsConfigType const * Config,uint32 Index)152 static void Clock_Ip_ProgressiveFrequencyClockSwitchEmpty(Clock_Ip_PcfsConfigType const* Config, uint32 Index)
153 {
154     (void)Config;
155     (void)Index;
156     /* No implementation */
157 }
158 
159 #ifdef CLOCK_IP_CGM_X_PCFS_SDUR_DIVC_DIVE_DIVS
Clock_Ip_CgmXPcfsSdurDivcDiveDivs(Clock_Ip_PcfsConfigType const * Config,uint32 CfgIndex)160 static void Clock_Ip_CgmXPcfsSdurDivcDiveDivs(Clock_Ip_PcfsConfigType const *Config, uint32 CfgIndex)
161 {
162     volatile Clock_Ip_CgmPcfsType* CgmPcfsBase  = Clock_Ip_apxCgmPcfs[Clock_Ip_au8ClockFeatures[Config->SelectorName][CLOCK_IP_MODULE_INSTANCE]];
163     uint32 HwIndex                       = Clock_Ip_au8ClockFeatures[Config->Name][CLOCK_IP_PCFS_INDEX];
164 
165     uint32 Finput = 0U;
166     uint32 Fsafe = 0U;
167     uint32 AmaxBrut;
168     uint32 Rate = 0U;
169     uint32 Index;
170     uint32 Var1;
171     uint32 Var2;
172     uint32 Var3;
173     uint32 K;
174 
175     uint32 Sdur;
176     uint32 DivcInit;
177     uint32 DivcRate;
178     uint32 DivStartValue;
179     uint32 DivEndValue;
180 
181 #if (defined(CLOCK_IP_DEV_ERROR_DETECT) && (CLOCK_IP_DEV_ERROR_DETECT == STD_ON))
182         CLOCK_IP_DEV_ASSERT(Config->SelectorName != RESERVED_CLK);
183 #endif
184 
185     if (HashPfs[CfgIndex] != ((((uint32)Config->ClockSourceFrequency) ^ ((uint32)Config->MaxAllowableIDDchange) ^ ((uint32)Config->Name)  ^ ((uint32)Config->SelectorName) ^ ((uint32)Config->StepDuration))))
186     {
187         HashPfs[CfgIndex] = ((((uint32)Config->ClockSourceFrequency) ^ ((uint32)Config->MaxAllowableIDDchange) ^ ((uint32)Config->Name)  ^ ((uint32)Config->SelectorName) ^ ((uint32)Config->StepDuration)));
188 
189         Finput = Config->ClockSourceFrequency / CLOCK_IP_DIVIDE_BY_1000000;
190     #if defined(CLOCK_IP_HAS_FIRC_CLK)
191         Fsafe = Clock_Ip_pxConfig->ConfiguredFrequencies[Clock_Ip_FreqIds[FIRC_CLK]].ConfiguredFrequencyValue / CLOCK_IP_DIVIDE_BY_1000000;
192 
193 
194     #endif
195 
196 #if (defined(CLOCK_IP_DEV_ERROR_DETECT) && (CLOCK_IP_DEV_ERROR_DETECT == STD_ON))
197         CLOCK_IP_DEV_ASSERT(Finput != 0U);
198         CLOCK_IP_DEV_ASSERT(Fsafe != 0U);
199         CLOCK_IP_DEV_ASSERT(Config->MaxAllowableIDDchange != 0U);
200         CLOCK_IP_DEV_ASSERT(Config->StepDuration != 0U);
201 #endif
202 
203         /* Calculate amax=fchg/Finput */
204         AmaxBrut = (Config->MaxAllowableIDDchange * Config->StepDuration * CLOCK_IP_DIVIDE_BY_100000 / (Finput * CLOCK_IP_DYNAMIC_IDD_CHANGE));
205         Rate = AmaxBrut;
206 
207         /* Round pcfs rate by rounding amax */
208         if (AmaxBrut < AMax[0U])
209         {
210             Rate = PcfsRate[0U];
211         }
212         else if (AmaxBrut > AMax[CLOCK_IP_A_MAX_SIZE-1U])
213         {
214             Rate = PcfsRate[CLOCK_IP_A_MAX_SIZE-1U];
215         }
216         else
217         {
218             for (Index = 1U; Index < (uint8)CLOCK_IP_A_MAX_SIZE; Index++)
219             {
220                 if (AMax[Index-1U] < AmaxBrut)
221                 {
222                     Rate = PcfsRate[Index];
223                 }
224             }
225         }
226 
227         /* Calculate K by using formula k = ceil(0.5 + sqrt(0.25 - (2000 * (1 -(Finput/fsafe)) / Rate))) */
228 
229         Var1 = 256U + ((CLOCK_IP_CONSTANT_2048000 * Finput) / (Fsafe * Rate)) - (CLOCK_IP_CONSTANT_2048000 / Rate);
230         Var2 = 1UL << 30U;   /* The second-to-top bit is set: use 1u << 14 for uint16 type; use 1uL<<30 for uint32 type  */
231         Var3 = 0U;
232 
233         /* Implement sqrt from K formula by using a square-root computing in embedded C */
234 
235         /* "one" starts at the highest power of four <= than the argument */
236         while (Var2 > Var1)
237         {
238             Var2 = Var2 >> 2;
239         }
240         /* Implement sqrt from K formula by using a square-root computing in embedded C */
241 
242         while (Var2 != 0U)
243         {
244             if (Var1 >= (Var3 + Var2))
245             {
246                 Var1 = Var1 - (Var3 + Var2);
247                 Var3 = Var3 + (Var2 << 1U);
248             }
249 
250             Var3 = Var3 >> 1U;
251             Var2 = Var2 >> 2U;
252         }
253 
254         K = (64U + 127U + (Var3 << 2U)) >> 7U;   /* Calculated K from k = ceil(0.5 + sqrt(0.25 - (2000 * (1 -(Fi/Fsafe)) / Rate))) */
255 
256         Sdur = Config->StepDuration * Fsafe;
257         DivcInit = Rate * K;
258         DivcRate = Rate;
259         DivStartValue = 999U + ((Rate * K * (K+1U)) >> 1U);
260         DivEndValue = (Finput * 1000U / Fsafe) - 1U;
261 
262         /* Configure pcfs registers */
263         CgmPcfsBase->PCFS_SDUR = MC_CGM_PCFS_SDUR_SDUR(Sdur);
264         CgmPcfsBase->PCFS[HwIndex].DIVC = MC_CGM_PCFS_DIVC_RATE(DivcRate) | MC_CGM_PCFS_DIVC_INIT(DivcInit);
265         CgmPcfsBase->PCFS[HwIndex].DIVE = MC_CGM_PCFS_DIVE_DIVE(DivEndValue);
266         CgmPcfsBase->PCFS[HwIndex].DIVS = MC_CGM_PCFS_DIVS_DIVS(DivStartValue);
267     }
268 }
269 #endif
270 
271 /* Clock stop section code */
272 #define MCU_STOP_SEC_CODE
273 
274 #include "Mcu_MemMap.h"
275 
276 /*==================================================================================================
277 *                                        GLOBAL FUNCTIONS
278 ==================================================================================================*/
279 
280 /*==================================================================================================
281 *                                        GLOBAL CONSTANTS
282 ==================================================================================================*/
283 
284 /* Clock start constant section data */
285 #define MCU_START_SEC_CONST_UNSPECIFIED
286 
287 #include "Mcu_MemMap.h"
288 
289 const Clock_Ip_PcfsCallbackType Clock_Ip_axPcfsCallbacks[CLOCK_IP_PCFS_CALLBACKS_COUNT] =
290 {
291     {
292         Clock_Ip_ProgressiveFrequencyClockSwitchEmpty,     /* Set */
293 
294     },
295 #ifdef CLOCK_IP_CGM_X_PCFS_SDUR_DIVC_DIVE_DIVS
296     {
297         Clock_Ip_CgmXPcfsSdurDivcDiveDivs,              /* Set */
298     },
299 #endif
300 };
301 
302 /* Clock stop constant section data */
303 #define MCU_STOP_SEC_CONST_UNSPECIFIED
304 
305 #include "Mcu_MemMap.h"
306 
307 
308 #ifdef __cplusplus
309 }
310 #endif
311 
312 /** @} */
313