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