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