1 /***************************************************************************//**
2 * \file cy_sysclk.c
3 * \version 3.70
4 *
5 * Provides an API implementation of the sysclk driver.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright (c) (2016-2022), Cypress Semiconductor Corporation (an Infineon company) or
10 * an affiliate of Cypress Semiconductor Corporation.
11 * SPDX-License-Identifier: Apache-2.0
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *******************************************************************************/
25
26 #include "cy_device.h"
27
28 #if defined (CY_IP_MXS40SRSS) && (CY_IP_MXS40SRSS_VERSION < 3)
29
30 #include "cy_sysclk.h"
31 #include "cy_syslib.h"
32 #include <stdlib.h>
33
34 #if defined (CY_DEVICE_SECURE)
35 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 17.2', 24, \
36 'Checked manually. All the recursive cycles are handled properly.')
37 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 18.6', 6, \
38 'Checked manually. Assignment of Local to global variable does not create any issue.')
39 #endif
40
41 cy_en_sysclk_status_t
Cy_SysClk_PeriphSetDivider(cy_en_divider_types_t dividerType,uint32_t dividerNum,uint32_t dividerValue)42 Cy_SysClk_PeriphSetDivider(cy_en_divider_types_t dividerType,
43 uint32_t dividerNum, uint32_t dividerValue)
44 {
45 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
46 if (dividerType == CY_SYSCLK_DIV_8_BIT)
47 {
48 if ((dividerNum < PERI_DIV_8_NR) &&
49 (dividerValue <= (PERI_DIV_8_CTL_INT8_DIV_Msk >> PERI_DIV_8_CTL_INT8_DIV_Pos)))
50 {
51 CY_REG32_CLR_SET(PERI_DIV_8_CTL[dividerNum], PERI_DIV_8_CTL_INT8_DIV, dividerValue);
52 retVal = CY_SYSCLK_SUCCESS;
53 }
54 }
55 else if (dividerType == CY_SYSCLK_DIV_16_BIT)
56 {
57 if ((dividerNum < PERI_DIV_16_NR) &&
58 (dividerValue <= (PERI_DIV_16_CTL_INT16_DIV_Msk >> PERI_DIV_16_CTL_INT16_DIV_Pos)))
59 {
60 CY_REG32_CLR_SET(PERI_DIV_16_CTL[dividerNum], PERI_DIV_16_CTL_INT16_DIV, dividerValue);
61 retVal = CY_SYSCLK_SUCCESS;
62 }
63 }
64 else
65 { /* return bad parameter */
66 }
67 return (retVal);
68 }
69
70
Cy_SysClk_PeriphGetDivider(cy_en_divider_types_t dividerType,uint32_t dividerNum)71 uint32_t Cy_SysClk_PeriphGetDivider(cy_en_divider_types_t dividerType, uint32_t dividerNum)
72 {
73 uint32_t retVal;
74
75 CY_ASSERT_L1(dividerType <= CY_SYSCLK_DIV_16_BIT);
76
77 if (dividerType == CY_SYSCLK_DIV_8_BIT)
78 {
79 CY_ASSERT_L1(dividerNum < PERI_DIV_8_NR);
80 retVal = _FLD2VAL(PERI_DIV_8_CTL_INT8_DIV, PERI_DIV_8_CTL[dividerNum]);
81 }
82 else
83 { /* 16-bit divider */
84 CY_ASSERT_L1(dividerNum < PERI_DIV_16_NR);
85 retVal = _FLD2VAL(PERI_DIV_16_CTL_INT16_DIV, PERI_DIV_16_CTL[dividerNum]);
86 }
87 return (retVal);
88 }
89
90
91 cy_en_sysclk_status_t
Cy_SysClk_PeriphSetFracDivider(cy_en_divider_types_t dividerType,uint32_t dividerNum,uint32_t dividerIntValue,uint32_t dividerFracValue)92 Cy_SysClk_PeriphSetFracDivider(cy_en_divider_types_t dividerType, uint32_t dividerNum,
93 uint32_t dividerIntValue, uint32_t dividerFracValue)
94 {
95 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
96 if (dividerType == CY_SYSCLK_DIV_16_5_BIT)
97 {
98 if ((dividerNum < PERI_DIV_16_5_NR) &&
99 (dividerIntValue <= (PERI_DIV_16_5_CTL_INT16_DIV_Msk >> PERI_DIV_16_5_CTL_INT16_DIV_Pos)) &&
100 (dividerFracValue <= (PERI_DIV_16_5_CTL_FRAC5_DIV_Msk >> PERI_DIV_16_5_CTL_FRAC5_DIV_Pos)))
101 {
102 CY_REG32_CLR_SET(PERI_DIV_16_5_CTL[dividerNum], PERI_DIV_16_5_CTL_INT16_DIV, dividerIntValue);
103 CY_REG32_CLR_SET(PERI_DIV_16_5_CTL[dividerNum], PERI_DIV_16_5_CTL_FRAC5_DIV, dividerFracValue);
104 retVal = CY_SYSCLK_SUCCESS;
105 }
106 }
107 else if (dividerType == CY_SYSCLK_DIV_24_5_BIT)
108 {
109 if ((dividerNum < PERI_DIV_24_5_NR) &&
110 (dividerIntValue <= (PERI_DIV_24_5_CTL_INT24_DIV_Msk >> PERI_DIV_24_5_CTL_INT24_DIV_Pos)) &&
111 (dividerFracValue <= (PERI_DIV_24_5_CTL_FRAC5_DIV_Msk >> PERI_DIV_24_5_CTL_FRAC5_DIV_Pos)))
112 {
113 CY_REG32_CLR_SET(PERI_DIV_24_5_CTL[dividerNum], PERI_DIV_24_5_CTL_INT24_DIV, dividerIntValue);
114 CY_REG32_CLR_SET(PERI_DIV_24_5_CTL[dividerNum], PERI_DIV_24_5_CTL_FRAC5_DIV, dividerFracValue);
115 retVal = CY_SYSCLK_SUCCESS;
116 }
117 }
118 else
119 { /* return bad parameter */
120 }
121 return (retVal);
122 }
123
124
Cy_SysClk_PeriphGetFracDivider(cy_en_divider_types_t dividerType,uint32_t dividerNum,uint32_t * dividerIntValue,uint32_t * dividerFracValue)125 void Cy_SysClk_PeriphGetFracDivider(cy_en_divider_types_t dividerType, uint32_t dividerNum,
126 uint32_t *dividerIntValue, uint32_t *dividerFracValue)
127 {
128 CY_ASSERT_L1(((dividerType == CY_SYSCLK_DIV_16_5_BIT) || (dividerType == CY_SYSCLK_DIV_24_5_BIT)) && \
129 (dividerIntValue != NULL) && (dividerFracValue != NULL));
130
131 if (dividerType == CY_SYSCLK_DIV_16_5_BIT)
132 {
133 CY_ASSERT_L1(dividerNum < PERI_DIV_16_5_NR);
134 *dividerIntValue = _FLD2VAL(PERI_DIV_16_5_CTL_INT16_DIV, PERI_DIV_16_5_CTL[dividerNum]);
135 *dividerFracValue = _FLD2VAL(PERI_DIV_16_5_CTL_FRAC5_DIV, PERI_DIV_16_5_CTL[dividerNum]);
136 }
137 else
138 { /* 24.5-bit divider */
139 CY_ASSERT_L1(dividerNum < PERI_DIV_24_5_NR);
140 *dividerIntValue = _FLD2VAL(PERI_DIV_24_5_CTL_INT24_DIV, PERI_DIV_24_5_CTL[dividerNum]);
141 *dividerFracValue = _FLD2VAL(PERI_DIV_24_5_CTL_FRAC5_DIV, PERI_DIV_24_5_CTL[dividerNum]);
142 }
143 }
144
145
146 cy_en_sysclk_status_t
Cy_SysClk_PeriphAssignDivider(en_clk_dst_t ipBlock,cy_en_divider_types_t dividerType,uint32_t dividerNum)147 Cy_SysClk_PeriphAssignDivider(en_clk_dst_t ipBlock,
148 cy_en_divider_types_t dividerType, uint32_t dividerNum)
149 {
150 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
151 if ((CY_PERI_CLOCK_NR > (uint32_t)ipBlock) && (CY_SYSCLK_DIV_24_5_BIT >= dividerType))
152 {
153 if (((dividerType == CY_SYSCLK_DIV_8_BIT) && (dividerNum < PERI_DIV_8_NR)) ||
154 ((dividerType == CY_SYSCLK_DIV_16_BIT) && (dividerNum < PERI_DIV_16_NR)) ||
155 ((dividerType == CY_SYSCLK_DIV_16_5_BIT) && (dividerNum < PERI_DIV_16_5_NR)) ||
156 ((dividerType == CY_SYSCLK_DIV_24_5_BIT) && (dividerNum < PERI_DIV_24_5_NR)))
157 {
158 PERI_CLOCK_CTL[ipBlock] = _VAL2FLD(CY_PERI_CLOCK_CTL_TYPE_SEL, dividerType) |
159 _VAL2FLD(CY_PERI_CLOCK_CTL_DIV_SEL, dividerNum);
160 retVal = CY_SYSCLK_SUCCESS;
161 }
162 }
163 return (retVal);
164 }
165
166
Cy_SysClk_PeriphGetAssignedDivider(en_clk_dst_t ipBlock)167 uint32_t Cy_SysClk_PeriphGetAssignedDivider(en_clk_dst_t ipBlock)
168 {
169 CY_ASSERT_L1(CY_PERI_CLOCK_NR > (uint32_t)ipBlock);
170 return (PERI_CLOCK_CTL[ipBlock] & (CY_PERI_CLOCK_CTL_DIV_SEL_Msk | CY_PERI_CLOCK_CTL_TYPE_SEL_Msk));
171 }
172
173
174 cy_en_sysclk_status_t
Cy_SysClk_PeriphEnableDivider(cy_en_divider_types_t dividerType,uint32_t dividerNum)175 Cy_SysClk_PeriphEnableDivider(cy_en_divider_types_t dividerType, uint32_t dividerNum)
176 {
177 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
178 if (dividerType <= CY_SYSCLK_DIV_24_5_BIT)
179 {
180 if (((dividerType == CY_SYSCLK_DIV_8_BIT) && (dividerNum < PERI_DIV_8_NR)) ||
181 ((dividerType == CY_SYSCLK_DIV_16_BIT) && (dividerNum < PERI_DIV_16_NR)) ||
182 ((dividerType == CY_SYSCLK_DIV_16_5_BIT) && (dividerNum < PERI_DIV_16_5_NR)) ||
183 ((dividerType == CY_SYSCLK_DIV_24_5_BIT) && (dividerNum < PERI_DIV_24_5_NR)))
184 {
185 /* specify the divider, make the reference = clk_peri, and enable the divider */
186 PERI_DIV_CMD = PERI_DIV_CMD_ENABLE_Msk |
187 CY_PERI_DIV_CMD_PA_TYPE_SEL_Msk |
188 CY_PERI_DIV_CMD_PA_DIV_SEL_Msk |
189 _VAL2FLD(CY_PERI_DIV_CMD_TYPE_SEL, dividerType) |
190 _VAL2FLD(CY_PERI_DIV_CMD_DIV_SEL, dividerNum);
191 (void)PERI_DIV_CMD; /* dummy read to handle buffered writes */
192 retVal = CY_SYSCLK_SUCCESS;
193 }
194 }
195 return (retVal);
196 }
197
198
199 cy_en_sysclk_status_t
Cy_SysClk_PeriphDisableDivider(cy_en_divider_types_t dividerType,uint32_t dividerNum)200 Cy_SysClk_PeriphDisableDivider(cy_en_divider_types_t dividerType, uint32_t dividerNum)
201 {
202 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
203 if (dividerType <= CY_SYSCLK_DIV_24_5_BIT)
204 {
205 if (((dividerType == CY_SYSCLK_DIV_8_BIT) && (dividerNum < PERI_DIV_8_NR)) ||
206 ((dividerType == CY_SYSCLK_DIV_16_BIT) && (dividerNum < PERI_DIV_16_NR)) ||
207 ((dividerType == CY_SYSCLK_DIV_16_5_BIT) && (dividerNum < PERI_DIV_16_5_NR)) ||
208 ((dividerType == CY_SYSCLK_DIV_24_5_BIT) && (dividerNum < PERI_DIV_24_5_NR)))
209 {
210 /* specify the divider and disable it */
211 PERI_DIV_CMD = PERI_DIV_CMD_DISABLE_Msk |
212 _VAL2FLD(CY_PERI_DIV_CMD_TYPE_SEL, dividerType) |
213 _VAL2FLD(CY_PERI_DIV_CMD_DIV_SEL, dividerNum);
214 retVal = CY_SYSCLK_SUCCESS;
215 }
216 }
217 return (retVal);
218 }
219
220
221 cy_en_sysclk_status_t
Cy_SysClk_PeriphEnablePhaseAlignDivider(cy_en_divider_types_t dividerType,uint32_t dividerNum,cy_en_divider_types_t dividerTypePA,uint32_t dividerNumPA)222 Cy_SysClk_PeriphEnablePhaseAlignDivider(cy_en_divider_types_t dividerType, uint32_t dividerNum,
223 cy_en_divider_types_t dividerTypePA, uint32_t dividerNumPA)
224 {
225 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
226 if (dividerTypePA <= CY_SYSCLK_DIV_24_5_BIT)
227 {
228 if (((dividerTypePA == CY_SYSCLK_DIV_8_BIT) && (dividerNumPA < PERI_DIV_8_NR)) ||
229 ((dividerTypePA == CY_SYSCLK_DIV_16_BIT) && (dividerNumPA < PERI_DIV_16_NR)) ||
230 ((dividerTypePA == CY_SYSCLK_DIV_16_5_BIT) && (dividerNumPA < PERI_DIV_16_5_NR)) ||
231 ((dividerTypePA == CY_SYSCLK_DIV_24_5_BIT) && ((dividerNumPA < PERI_DIV_24_5_NR) || (dividerNumPA == 63u))))
232 {
233 /* First, disable the divider that is to be phase-aligned.
234 The other two parameters are checked in that function;
235 if they're not valid, the divider is not disabled. */
236 retVal = Cy_SysClk_PeriphDisableDivider(dividerType, dividerNum);
237 if (retVal == CY_SYSCLK_SUCCESS)
238 {
239 /* Then, specify the reference divider, and the divider, and enable the divider */
240 PERI_DIV_CMD = PERI_DIV_CMD_ENABLE_Msk |
241 _VAL2FLD(CY_PERI_DIV_CMD_PA_TYPE_SEL, dividerTypePA) |
242 _VAL2FLD(CY_PERI_DIV_CMD_PA_DIV_SEL, dividerNumPA) |
243 _VAL2FLD(CY_PERI_DIV_CMD_TYPE_SEL, dividerType) |
244 _VAL2FLD(CY_PERI_DIV_CMD_DIV_SEL, dividerNum);
245 }
246 }
247 }
248 return (retVal);
249 }
250
251
Cy_SysClk_PeriphGetDividerEnabled(cy_en_divider_types_t dividerType,uint32_t dividerNum)252 bool Cy_SysClk_PeriphGetDividerEnabled(cy_en_divider_types_t dividerType, uint32_t dividerNum)
253 {
254 bool retVal = false;
255
256 CY_ASSERT_L1(((dividerType == CY_SYSCLK_DIV_8_BIT) && (dividerNum < PERI_DIV_8_NR)) || \
257 ((dividerType == CY_SYSCLK_DIV_16_BIT) && (dividerNum < PERI_DIV_16_NR)) || \
258 ((dividerType == CY_SYSCLK_DIV_16_5_BIT) && (dividerNum < PERI_DIV_16_5_NR)) || \
259 ((dividerType == CY_SYSCLK_DIV_24_5_BIT) && (dividerNum < PERI_DIV_24_5_NR)));
260
261 switch(dividerType)
262 {
263 case CY_SYSCLK_DIV_8_BIT:
264 retVal = _FLD2BOOL(PERI_DIV_8_CTL_EN, PERI_DIV_8_CTL[dividerNum]);
265 break;
266 case CY_SYSCLK_DIV_16_BIT:
267 retVal = _FLD2BOOL(PERI_DIV_16_CTL_EN, PERI_DIV_16_CTL[dividerNum]);
268 break;
269 case CY_SYSCLK_DIV_16_5_BIT:
270 retVal = _FLD2BOOL(PERI_DIV_16_5_CTL_EN, PERI_DIV_16_5_CTL[dividerNum]);
271 break;
272 case CY_SYSCLK_DIV_24_5_BIT:
273 retVal = _FLD2BOOL(PERI_DIV_24_5_CTL_EN, PERI_DIV_24_5_CTL[dividerNum]);
274 break;
275 default:
276 /* Unknown Divider */
277 break;
278 }
279 return (retVal);
280 }
281
282
283 /* ========================================================================== */
284 /* ========================= clk_slow SECTION ========================= */
285 /* ========================================================================== */
286
287
Cy_SysClk_ClkSlowGetFrequency(void)288 uint32_t Cy_SysClk_ClkSlowGetFrequency(void)
289 {
290 uint32_t locFreq = Cy_SysClk_ClkPeriGetFrequency(); /* Get Peri frequency */
291 uint32_t locDiv = 1UL + (uint32_t)Cy_SysClk_ClkSlowGetDivider(); /* peri prescaler (1-256) */
292
293 /* Divide the path input frequency down and return the result */
294 return (CY_SYSLIB_DIV_ROUND(locFreq, locDiv));
295 }
296
297
Cy_SysClk_ClkSlowSetDivider(uint8_t divider)298 void Cy_SysClk_ClkSlowSetDivider(uint8_t divider)
299 {
300 #if defined (CY_DEVICE_SECURE)
301 CY_PRA_FUNCTION_CALL_VOID_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_SLOW_SET_DIVIDER, divider);
302 #endif /* defined (CY_DEVICE_SECURE) */
303 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
304 CY_REG32_CLR_SET(CPUSS_CM0_CLOCK_CTL, CPUSS_CM0_CLOCK_CTL_SLOW_INT_DIV, divider);
305 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
306 }
307
308
Cy_SysClk_ClkSlowGetDivider(void)309 uint8_t Cy_SysClk_ClkSlowGetDivider(void)
310 {
311 return ((uint8_t)_FLD2VAL(CPUSS_CM0_CLOCK_CTL_SLOW_INT_DIV, CPUSS_CM0_CLOCK_CTL));
312 }
313
314
Cy_SysClk_ClkPumpSetSource(cy_en_clkpump_in_sources_t source)315 void Cy_SysClk_ClkPumpSetSource(cy_en_clkpump_in_sources_t source)
316 {
317 #if defined (CY_DEVICE_SECURE)
318 cy_en_pra_status_t retStatus;
319 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_PUMP_SET_SOURCE, source);
320
321 if (retStatus != CY_PRA_STATUS_SUCCESS)
322 {
323 CY_ASSERT_L1(false);
324 }
325 #endif /* defined (CY_DEVICE_SECURE) */
326 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
327 CY_ASSERT_L3(source <= CY_SYSCLK_PUMP_IN_CLKPATH15);
328 CY_REG32_CLR_SET(SRSS_CLK_SELECT, SRSS_CLK_SELECT_PUMP_SEL, source);
329 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
330 }
331
332
Cy_SysClk_ClkPumpGetSource(void)333 cy_en_clkpump_in_sources_t Cy_SysClk_ClkPumpGetSource(void)
334 {
335 return ((cy_en_clkpump_in_sources_t)((uint32_t)_FLD2VAL(SRSS_CLK_SELECT_PUMP_SEL, SRSS_CLK_SELECT)));
336 }
337
338
Cy_SysClk_ClkPumpSetDivider(cy_en_clkpump_divide_t divider)339 void Cy_SysClk_ClkPumpSetDivider(cy_en_clkpump_divide_t divider)
340 {
341 #if defined (CY_DEVICE_SECURE)
342 cy_en_pra_status_t retStatus;
343 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_PUMP_SET_DIVIDER, divider);
344
345 if (retStatus != CY_PRA_STATUS_SUCCESS)
346 {
347 CY_ASSERT_L1(false);
348 }
349 #endif /* defined (CY_DEVICE_SECURE) */
350 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
351 CY_ASSERT_L3(CY_SYSCLK_FLL_IS_DIVIDER_VALID(divider));
352 CY_REG32_CLR_SET(SRSS_CLK_SELECT, SRSS_CLK_SELECT_PUMP_DIV, divider);
353 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
354 }
355
356
Cy_SysClk_ClkPumpGetDivider(void)357 cy_en_clkpump_divide_t Cy_SysClk_ClkPumpGetDivider(void)
358 {
359 return ((cy_en_clkpump_divide_t)((uint32_t)_FLD2VAL(SRSS_CLK_SELECT_PUMP_DIV, SRSS_CLK_SELECT)));
360 }
361
362
Cy_SysClk_ClkPumpEnable(void)363 void Cy_SysClk_ClkPumpEnable(void)
364 {
365 #if defined (CY_DEVICE_SECURE)
366 cy_en_pra_status_t retStatus;
367 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_PUMP_ENABLE, 1UL);
368
369 if (retStatus != CY_PRA_STATUS_SUCCESS)
370 {
371 CY_ASSERT_L1(false);
372 }
373 #endif /* defined (CY_DEVICE_SECURE) */
374 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
375 SRSS_CLK_SELECT |= SRSS_CLK_SELECT_PUMP_ENABLE_Msk;
376 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
377 }
378
379
Cy_SysClk_ClkPumpIsEnabled(void)380 bool Cy_SysClk_ClkPumpIsEnabled(void)
381 {
382 return (_FLD2BOOL(SRSS_CLK_SELECT_PUMP_ENABLE, SRSS_CLK_SELECT));
383 }
384
385
Cy_SysClk_ClkPumpDisable(void)386 void Cy_SysClk_ClkPumpDisable(void)
387 {
388 #if defined (CY_DEVICE_SECURE)
389 cy_en_pra_status_t retStatus;
390 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_PUMP_DISABLE, 0UL);
391
392 if (retStatus != CY_PRA_STATUS_SUCCESS)
393 {
394 CY_ASSERT_L1(false);
395 }
396 #endif /* defined (CY_DEVICE_SECURE) */
397 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
398 SRSS_CLK_SELECT &= ~SRSS_CLK_SELECT_PUMP_ENABLE_Msk;
399 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
400 }
401
402
Cy_SysClk_ClkPumpGetFrequency(void)403 uint32_t Cy_SysClk_ClkPumpGetFrequency(void)
404 {
405 /* Divide the input frequency down and return the result */
406 return (Cy_SysClk_ClkPumpIsEnabled() ?
407 (Cy_SysClk_ClkPathGetFrequency((uint32_t)Cy_SysClk_ClkPumpGetSource()) /
408 (1UL << (uint32_t)Cy_SysClk_ClkPumpGetDivider())) : 0UL);
409 }
410
411
Cy_SysClk_ClkBakSetSource(cy_en_clkbak_in_sources_t source)412 void Cy_SysClk_ClkBakSetSource(cy_en_clkbak_in_sources_t source)
413 {
414 #if defined (CY_DEVICE_SECURE)
415 cy_en_pra_status_t retStatus;
416 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_BAK_SET_SOURCE, source);
417
418 if (retStatus != CY_PRA_STATUS_SUCCESS)
419 {
420 CY_ASSERT_L1(false);
421 }
422 #endif /* defined (CY_DEVICE_SECURE) */
423 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
424 CY_ASSERT_L3(source <= CY_SYSCLK_BAK_IN_CLKLF);
425 CY_REG32_CLR_SET(BACKUP_CTL, BACKUP_CTL_CLK_SEL, source);
426 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
427 }
428
429
Cy_SysClk_ClkBakGetSource(void)430 cy_en_clkbak_in_sources_t Cy_SysClk_ClkBakGetSource(void)
431 {
432 return ((cy_en_clkbak_in_sources_t)((uint32_t)_FLD2VAL(BACKUP_CTL_CLK_SEL, BACKUP_CTL)));
433 }
434
435
Cy_SysClk_ClkTimerSetSource(cy_en_clktimer_in_sources_t source)436 void Cy_SysClk_ClkTimerSetSource(cy_en_clktimer_in_sources_t source)
437 {
438 #if defined (CY_DEVICE_SECURE)
439 cy_en_pra_status_t retStatus;
440 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_TIMER_SET_SOURCE, source);
441
442 if (retStatus != CY_PRA_STATUS_SUCCESS)
443 {
444 CY_ASSERT_L1(false);
445 }
446 #endif /* defined (CY_DEVICE_SECURE) */
447 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
448 CY_ASSERT_L3(source <= CY_SYSCLK_CLKTIMER_IN_HF0_DIV8);
449 /* set both fields TIMER_SEL and TIMER_HF0_DIV with the same input value */
450 CY_REG32_CLR_SET(SRSS_CLK_TIMER_CTL, CY_SRSS_CLK_TIMER_CTL_TIMER, source);
451 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
452 }
453
454
Cy_SysClk_ClkTimerGetSource(void)455 cy_en_clktimer_in_sources_t Cy_SysClk_ClkTimerGetSource(void)
456 {
457 /* return both fields TIMER_SEL and TIMER_HF0_DIV as a single combined value */
458 return ((cy_en_clktimer_in_sources_t)((uint32_t)(SRSS_CLK_TIMER_CTL & CY_SRSS_CLK_TIMER_CTL_TIMER_Msk)));
459 }
460
461
Cy_SysClk_ClkTimerSetDivider(uint8_t divider)462 void Cy_SysClk_ClkTimerSetDivider(uint8_t divider)
463 {
464 #if defined (CY_DEVICE_SECURE)
465 cy_en_pra_status_t retStatus;
466 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_TIMER_SET_DIVIDER, divider);
467
468 if (retStatus != CY_PRA_STATUS_SUCCESS)
469 {
470 CY_ASSERT_L1(false);
471 }
472 #endif /* defined (CY_DEVICE_SECURE) */
473 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
474 CY_REG32_CLR_SET(SRSS_CLK_TIMER_CTL, SRSS_CLK_TIMER_CTL_TIMER_DIV, divider);
475 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
476 }
477
478
Cy_SysClk_ClkTimerGetDivider(void)479 uint8_t Cy_SysClk_ClkTimerGetDivider(void)
480 {
481 return ((uint8_t)_FLD2VAL(SRSS_CLK_TIMER_CTL_TIMER_DIV, SRSS_CLK_TIMER_CTL));
482 }
483
484
Cy_SysClk_ClkTimerEnable(void)485 void Cy_SysClk_ClkTimerEnable(void)
486 {
487 #if defined (CY_DEVICE_SECURE)
488 cy_en_pra_status_t retStatus;
489 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_TIMER_ENABLE, 1UL);
490
491 if (retStatus != CY_PRA_STATUS_SUCCESS)
492 {
493 CY_ASSERT_L1(false);
494 }
495 #endif /* defined (CY_DEVICE_SECURE) */
496 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
497 SRSS_CLK_TIMER_CTL |= SRSS_CLK_TIMER_CTL_ENABLE_Msk;
498 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
499 }
500
501
Cy_SysClk_ClkTimerIsEnabled(void)502 bool Cy_SysClk_ClkTimerIsEnabled(void)
503 {
504 return (_FLD2BOOL(SRSS_CLK_TIMER_CTL_ENABLE, SRSS_CLK_TIMER_CTL));
505 }
506
507
Cy_SysClk_ClkTimerDisable(void)508 void Cy_SysClk_ClkTimerDisable(void)
509 {
510 #if defined (CY_DEVICE_SECURE)
511 cy_en_pra_status_t retStatus;
512 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_TIMER_DISABLE, 0UL);
513
514 if (retStatus != CY_PRA_STATUS_SUCCESS)
515 {
516 CY_ASSERT_L1(false);
517 }
518 #endif /* defined (CY_DEVICE_SECURE) */
519 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
520 SRSS_CLK_TIMER_CTL &= ~SRSS_CLK_TIMER_CTL_ENABLE_Msk;
521 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
522 }
523
524
Cy_SysClk_ClkLfSetSource(cy_en_clklf_in_sources_t source)525 void Cy_SysClk_ClkLfSetSource(cy_en_clklf_in_sources_t source)
526 {
527 #if defined (CY_DEVICE_SECURE)
528 cy_en_pra_status_t retStatus;
529 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_LF_SET_SOURCE, source);
530
531 if (retStatus != CY_PRA_STATUS_SUCCESS)
532 {
533 CY_ASSERT_L1(false);
534 }
535 #endif /* defined (CY_DEVICE_SECURE) */
536 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
537 CY_ASSERT_L3(source <= CY_SYSCLK_CLKLF_IN_PILO);
538 CY_REG32_CLR_SET(SRSS_CLK_SELECT, SRSS_CLK_SELECT_LFCLK_SEL, source);
539 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
540 }
541
542
Cy_SysClk_ClkLfGetSource(void)543 cy_en_clklf_in_sources_t Cy_SysClk_ClkLfGetSource(void)
544 {
545 return ((cy_en_clklf_in_sources_t)(((uint32_t)_FLD2VAL(SRSS_CLK_SELECT_LFCLK_SEL, SRSS_CLK_SELECT))));
546 }
547
548
Cy_SysClk_ClkPeriGetFrequency(void)549 uint32_t Cy_SysClk_ClkPeriGetFrequency(void)
550 {
551 uint32_t locFreq = Cy_SysClk_ClkHfGetFrequency(0UL); /* Get root frequency */
552 uint32_t locDiv = 1UL + (uint32_t)Cy_SysClk_ClkPeriGetDivider(); /* peri prescaler (1-256) */
553
554 /* Divide the path input frequency down and return the result */
555 return (CY_SYSLIB_DIV_ROUND(locFreq, locDiv));
556 }
557
558
Cy_SysClk_ClkPeriSetDivider(uint8_t divider)559 void Cy_SysClk_ClkPeriSetDivider(uint8_t divider)
560 {
561 #if defined (CY_DEVICE_SECURE)
562 cy_en_pra_status_t retStatus;
563 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_PERI_SET_DIVIDER, divider);
564
565 if (retStatus != CY_PRA_STATUS_SUCCESS)
566 {
567 CY_ASSERT_L1(false);
568 }
569 #endif /* defined (CY_DEVICE_SECURE) */
570 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
571 CY_REG32_CLR_SET(CPUSS_CM0_CLOCK_CTL, CPUSS_CM0_CLOCK_CTL_PERI_INT_DIV, divider);
572 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
573 }
574
575
Cy_SysClk_ClkPeriGetDivider(void)576 uint8_t Cy_SysClk_ClkPeriGetDivider(void)
577 {
578 return ((uint8_t)_FLD2VAL(CPUSS_CM0_CLOCK_CTL_PERI_INT_DIV, CPUSS_CM0_CLOCK_CTL));
579 }
580
581
582 /* ========================================================================== */
583 /* ========================= clk_fast SECTION ========================= */
584 /* ========================================================================== */
585
586
Cy_SysClk_ClkFastGetFrequency(void)587 uint32_t Cy_SysClk_ClkFastGetFrequency(void)
588 {
589 uint32_t locFreq = Cy_SysClk_ClkHfGetFrequency(0UL); /* Get root frequency */
590 uint32_t locDiv = 1UL + (uint32_t)Cy_SysClk_ClkFastGetDivider(); /* fast prescaler (1-256) */
591
592 /* Divide the path input frequency down and return the result */
593 return (CY_SYSLIB_DIV_ROUND(locFreq, locDiv));
594 }
595
596
Cy_SysClk_ClkFastSetDivider(uint8_t divider)597 void Cy_SysClk_ClkFastSetDivider(uint8_t divider)
598 {
599 #if defined (CY_DEVICE_SECURE)
600 cy_en_pra_status_t retStatus;
601 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_FAST_SET_DIVIDER, divider);
602
603 if (retStatus != CY_PRA_STATUS_SUCCESS)
604 {
605 CY_ASSERT_L1(false);
606 }
607 #endif /* defined (CY_DEVICE_SECURE) */
608 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
609 CY_REG32_CLR_SET(CPUSS_CM4_CLOCK_CTL, CPUSS_CM4_CLOCK_CTL_FAST_INT_DIV, divider);
610 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
611 }
612
613
Cy_SysClk_ClkFastGetDivider(void)614 uint8_t Cy_SysClk_ClkFastGetDivider(void)
615 {
616 return ((uint8_t)_FLD2VAL(CPUSS_CM4_CLOCK_CTL_FAST_INT_DIV, CPUSS_CM4_CLOCK_CTL));
617 }
618
619
Cy_SysClk_ClkHfEnable(uint32_t clkHf)620 cy_en_sysclk_status_t Cy_SysClk_ClkHfEnable(uint32_t clkHf)
621 {
622 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
623 if (clkHf < CY_SRSS_NUM_HFROOT)
624 {
625 #if defined (CY_DEVICE_SECURE)
626 retVal = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_HF_ENABLE, clkHf);
627 #endif /* defined (CY_DEVICE_SECURE) */
628 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
629 SRSS_CLK_ROOT_SELECT[clkHf] |= SRSS_CLK_ROOT_SELECT_ENABLE_Msk;
630 retVal = CY_SYSCLK_SUCCESS;
631 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
632 }
633 return (retVal);
634 }
635
636
Cy_SysClk_ClkHfIsEnabled(uint32_t clkHf)637 bool Cy_SysClk_ClkHfIsEnabled(uint32_t clkHf)
638 {
639 bool retVal = false;
640 if (clkHf < CY_SRSS_NUM_HFROOT)
641 {
642 retVal = _FLD2BOOL(SRSS_CLK_ROOT_SELECT_ENABLE, SRSS_CLK_ROOT_SELECT[clkHf]);
643 }
644 return (retVal);
645 }
646
647
Cy_SysClk_ClkHfDisable(uint32_t clkHf)648 cy_en_sysclk_status_t Cy_SysClk_ClkHfDisable(uint32_t clkHf)
649 {
650 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
651 if ((0UL < clkHf) /* prevent CLK_HF0 disabling */
652 && (clkHf < CY_SRSS_NUM_HFROOT))
653 {
654 #if defined (CY_DEVICE_SECURE)
655 retVal = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_HF_DISABLE, clkHf);
656 #endif /* defined (CY_DEVICE_SECURE) */
657 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
658 SRSS_CLK_ROOT_SELECT[clkHf] &= ~SRSS_CLK_ROOT_SELECT_ENABLE_Msk;
659 retVal = CY_SYSCLK_SUCCESS;
660 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
661 }
662 return (retVal);
663 }
664
665
Cy_SysClk_ClkHfSetSource(uint32_t clkHf,cy_en_clkhf_in_sources_t source)666 cy_en_sysclk_status_t Cy_SysClk_ClkHfSetSource(uint32_t clkHf, cy_en_clkhf_in_sources_t source)
667 {
668 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
669 if ((clkHf < CY_SRSS_NUM_HFROOT) && (source <= CY_SYSCLK_CLKHF_IN_CLKPATH15))
670 {
671 #if defined (CY_DEVICE_SECURE)
672 cy_stc_pra_clkhfsetsource_t set_source;
673 set_source.clkHf = clkHf;
674 set_source.source = source;
675 retVal = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_HF_SET_SOURCE, &set_source);
676 #endif /* defined (CY_DEVICE_SECURE) */
677 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
678 CY_REG32_CLR_SET(SRSS_CLK_ROOT_SELECT[clkHf], SRSS_CLK_ROOT_SELECT_ROOT_MUX, source);
679 retVal = CY_SYSCLK_SUCCESS;
680 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
681 }
682 return (retVal);
683 }
684
685
Cy_SysClk_ClkHfGetSource(uint32_t clkHf)686 cy_en_clkhf_in_sources_t Cy_SysClk_ClkHfGetSource(uint32_t clkHf)
687 {
688 CY_ASSERT_L1(clkHf < CY_SRSS_NUM_HFROOT);
689 return ((cy_en_clkhf_in_sources_t)((uint32_t)(_FLD2VAL(SRSS_CLK_ROOT_SELECT_ROOT_MUX, SRSS_CLK_ROOT_SELECT[clkHf]))));
690 }
691
692
Cy_SysClk_ClkHfSetDivider(uint32_t clkHf,cy_en_clkhf_dividers_t divider)693 cy_en_sysclk_status_t Cy_SysClk_ClkHfSetDivider(uint32_t clkHf, cy_en_clkhf_dividers_t divider)
694 {
695 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
696 if ((clkHf < CY_SRSS_NUM_HFROOT) && (divider <= CY_SYSCLK_CLKHF_DIVIDE_BY_8))
697 {
698 #if defined (CY_DEVICE_SECURE)
699 cy_stc_pra_clkhfsetdivider_t set_divider;
700 set_divider.clkHf = clkHf;
701 set_divider.divider = divider;
702 retVal = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_HF_SET_DIVIDER, &set_divider);
703 #endif /* defined (CY_DEVICE_SECURE) */
704 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
705 CY_REG32_CLR_SET(SRSS_CLK_ROOT_SELECT[clkHf], SRSS_CLK_ROOT_SELECT_ROOT_DIV, divider);
706 retVal = CY_SYSCLK_SUCCESS;
707 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
708 }
709 return (retVal);
710 }
711
712
Cy_SysClk_ClkHfGetDivider(uint32_t clkHf)713 cy_en_clkhf_dividers_t Cy_SysClk_ClkHfGetDivider(uint32_t clkHf)
714 {
715 CY_ASSERT_L1(clkHf < CY_SRSS_NUM_HFROOT);
716 return ((cy_en_clkhf_dividers_t)(((uint32_t)_FLD2VAL(SRSS_CLK_ROOT_SELECT_ROOT_DIV, SRSS_CLK_ROOT_SELECT[clkHf]))));
717 }
718
719
720 /* ========================================================================== */
721 /* ============================ MF SECTION ============================ */
722 /* ========================================================================== */
723
724
Cy_SysClk_MfoEnable(bool deepSleepEnable)725 void Cy_SysClk_MfoEnable(bool deepSleepEnable)
726 {
727 if (CY_SRSS_MFO_PRESENT)
728 {
729 #if CY_CPU_CORTEX_M4 && defined(CY_DEVICE_SECURE)
730 CY_PRA_REG32_SET(CY_PRA_INDX_SRSS_CLK_MFO_CONFIG, (SRSS_CLK_MFO_CONFIG_ENABLE_Msk | (deepSleepEnable ? SRSS_CLK_MFO_CONFIG_DPSLP_ENABLE_Msk : 0UL)));
731 #else
732 SRSS_CLK_MFO_CONFIG = SRSS_CLK_MFO_CONFIG_ENABLE_Msk | (deepSleepEnable ? SRSS_CLK_MFO_CONFIG_DPSLP_ENABLE_Msk : 0UL);
733 #endif /* CY_CPU_CORTEX_M4 && defined(CY_DEVICE_SECURE) */
734 }
735 }
736
737
Cy_SysClk_MfoIsEnabled(void)738 bool Cy_SysClk_MfoIsEnabled(void)
739 {
740 return (CY_SRSS_MFO_PRESENT && (0UL != (SRSS_CLK_MFO_CONFIG & SRSS_CLK_MFO_CONFIG_ENABLE_Msk)));
741 }
742
743
Cy_SysClk_MfoDisable(void)744 void Cy_SysClk_MfoDisable(void)
745 {
746 if (CY_SRSS_MFO_PRESENT)
747 {
748 #if CY_CPU_CORTEX_M4 && defined(CY_DEVICE_SECURE)
749 CY_PRA_REG32_SET(CY_PRA_INDX_SRSS_CLK_MFO_CONFIG, 0UL);
750 #else
751 SRSS_CLK_MFO_CONFIG = 0UL;
752 #endif /* CY_CPU_CORTEX_M4 && defined(CY_DEVICE_SECURE) */
753 }
754 }
755
756
Cy_SysClk_ClkMfEnable(void)757 void Cy_SysClk_ClkMfEnable(void)
758 {
759 if (CY_SRSS_MFO_PRESENT)
760 {
761 #if CY_CPU_CORTEX_M4 && defined(CY_DEVICE_SECURE)
762 CY_PRA_REG32_CLR_SET(CY_PRA_INDX_SRSS_CLK_MF_SELECT, SRSS_CLK_MF_SELECT_ENABLE, 1U);
763 #else
764 SRSS_CLK_MF_SELECT |= SRSS_CLK_MF_SELECT_ENABLE_Msk;
765 #endif /* CY_CPU_CORTEX_M4 && defined(CY_DEVICE_SECURE) */
766 }
767 }
768
769
Cy_SysClk_ClkMfIsEnabled(void)770 bool Cy_SysClk_ClkMfIsEnabled(void)
771 {
772 return ((CY_SRSS_MFO_PRESENT) && (0UL != (SRSS_CLK_MF_SELECT & SRSS_CLK_MF_SELECT_ENABLE_Msk)));
773 }
774
775
Cy_SysClk_ClkMfDisable(void)776 void Cy_SysClk_ClkMfDisable(void)
777 {
778 if (CY_SRSS_MFO_PRESENT)
779 {
780 #if CY_CPU_CORTEX_M4 && defined(CY_DEVICE_SECURE)
781 CY_PRA_REG32_CLR_SET(CY_PRA_INDX_SRSS_CLK_MF_SELECT, SRSS_CLK_MF_SELECT_ENABLE, 0U);
782 #else
783 SRSS_CLK_MF_SELECT &= ~SRSS_CLK_MF_SELECT_ENABLE_Msk;
784 #endif /* CY_CPU_CORTEX_M4 && defined(CY_DEVICE_SECURE) */
785 }
786 }
787
788
Cy_SysClk_ClkMfSetDivider(uint32_t divider)789 void Cy_SysClk_ClkMfSetDivider(uint32_t divider)
790 {
791 if ((CY_SRSS_MFO_PRESENT) && CY_SYSCLK_IS_MF_DIVIDER_VALID(divider))
792 {
793 if (!Cy_SysClk_ClkMfIsEnabled())
794 {
795 #if CY_CPU_CORTEX_M4 && defined(CY_DEVICE_SECURE)
796 CY_PRA_REG32_CLR_SET(CY_PRA_INDX_SRSS_CLK_MF_SELECT, SRSS_CLK_MF_SELECT_MFCLK_DIV, divider - 1UL);
797 #else
798 CY_REG32_CLR_SET(SRSS_CLK_MF_SELECT, SRSS_CLK_MF_SELECT_MFCLK_DIV, divider - 1UL);
799 #endif /* CY_CPU_CORTEX_M4 && defined(CY_DEVICE_SECURE) */
800 }
801 }
802 }
803
804
Cy_SysClk_ClkMfGetDivider(void)805 uint32_t Cy_SysClk_ClkMfGetDivider(void)
806 {
807 return ((CY_SRSS_MFO_PRESENT) ? (1UL + _FLD2VAL(SRSS_CLK_MF_SELECT_MFCLK_DIV, SRSS_CLK_MF_SELECT)) : 1UL);
808 }
809
810
Cy_SysClk_ClkMfGetFrequency(void)811 uint32_t Cy_SysClk_ClkMfGetFrequency(void)
812 {
813 uint32_t locFreq = (Cy_SysClk_MfoIsEnabled()) ? CY_SYSCLK_MFO_FREQ : 0UL; /* Get root frequency */
814 uint32_t locDiv = Cy_SysClk_ClkMfGetDivider(); /* clkMf prescaler (1-256) */
815
816 /* Divide the path input frequency down and return the result */
817 return (CY_SYSLIB_DIV_ROUND(locFreq, locDiv));
818 }
819
820
Cy_SysClk_WcoEnable(uint32_t timeoutus)821 cy_en_sysclk_status_t Cy_SysClk_WcoEnable(uint32_t timeoutus)
822 {
823 cy_en_sysclk_status_t retVal;
824 #if defined (CY_DEVICE_SECURE)
825 retVal = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_WCO_ENABLE, timeoutus);
826 #endif /* defined (CY_DEVICE_SECURE) */
827 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
828 retVal = CY_SYSCLK_TIMEOUT;
829
830 /* first set the WCO enable bit */
831 BACKUP_CTL |= BACKUP_CTL_WCO_EN_Msk;
832
833 /* now do the timeout wait for STATUS, bit WCO_OK */
834 for (; (Cy_SysClk_WcoOkay() == false) && (0UL != timeoutus); timeoutus--)
835 {
836 Cy_SysLib_DelayUs(1U);
837 }
838
839 if (0UL != timeoutus)
840 {
841 retVal = CY_SYSCLK_SUCCESS;
842 }
843 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
844 return (retVal);
845 }
846
847
Cy_SysClk_WcoOkay(void)848 bool Cy_SysClk_WcoOkay(void)
849 {
850 return (_FLD2BOOL(BACKUP_STATUS_WCO_OK, BACKUP_STATUS));
851 }
852
853
Cy_SysClk_WcoDisable(void)854 void Cy_SysClk_WcoDisable(void)
855 {
856 #if defined (CY_DEVICE_SECURE)
857 cy_en_pra_status_t retStatus;
858 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_WCO_DISABLE, 0UL);
859
860 if (retStatus != CY_PRA_STATUS_SUCCESS)
861 {
862 CY_ASSERT_L1(false);
863 }
864 #endif /* defined (CY_DEVICE_SECURE) */
865 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
866 BACKUP_CTL &= (uint32_t)~BACKUP_CTL_WCO_EN_Msk;
867 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
868 }
869
870
Cy_SysClk_WcoBypass(cy_en_wco_bypass_modes_t bypass)871 void Cy_SysClk_WcoBypass(cy_en_wco_bypass_modes_t bypass)
872 {
873 #if defined (CY_DEVICE_SECURE)
874 cy_en_pra_status_t retStatus;
875 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_WCO_BYPASS, bypass);
876
877 if (retStatus != CY_PRA_STATUS_SUCCESS)
878 {
879 CY_ASSERT_L1(false);
880 }
881 #endif /* defined (CY_DEVICE_SECURE) */
882 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
883 CY_REG32_CLR_SET(BACKUP_CTL, BACKUP_CTL_WCO_BYPASS, bypass);
884 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
885 }
886
887
888 /* ========================================================================== */
889 /* =========================== PILO SECTION =========================== */
890 /* ========================================================================== */
891
892
Cy_SysClk_PiloEnable(void)893 void Cy_SysClk_PiloEnable(void)
894 {
895 #if defined (CY_DEVICE_SECURE)
896 cy_en_pra_status_t retStatus;
897 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_PILO_ENABLE, 1UL);
898
899 if (retStatus != CY_PRA_STATUS_SUCCESS)
900 {
901 CY_ASSERT_L1(false);
902 }
903 #endif /* defined (CY_DEVICE_SECURE) */
904 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
905 SRSS_CLK_PILO_CONFIG |= SRSS_CLK_PILO_CONFIG_PILO_EN_Msk; /* 1 = enable */
906 Cy_SysLib_Delay(1U/*msec*/);
907 /* release the reset and enable clock output */
908 SRSS_CLK_PILO_CONFIG |= SRSS_CLK_PILO_CONFIG_PILO_RESET_N_Msk |
909 SRSS_CLK_PILO_CONFIG_PILO_CLK_EN_Msk;
910 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
911 }
912
913
Cy_SysClk_PiloIsEnabled(void)914 bool Cy_SysClk_PiloIsEnabled(void)
915 {
916 return (_FLD2BOOL(SRSS_CLK_PILO_CONFIG_PILO_CLK_EN, SRSS_CLK_PILO_CONFIG));
917 }
918
919
Cy_SysClk_PiloDisable(void)920 void Cy_SysClk_PiloDisable(void)
921 {
922 #if defined (CY_DEVICE_SECURE)
923 cy_en_pra_status_t retStatus;
924 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_PILO_DISABLE, 0UL);
925
926 if (retStatus != CY_PRA_STATUS_SUCCESS)
927 {
928 CY_ASSERT_L1(false);
929 }
930 #endif /* defined (CY_DEVICE_SECURE) */
931 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
932 /* Clear PILO_EN, PILO_RESET_N, and PILO_CLK_EN bitfields. This disables the
933 PILO and holds the PILO in a reset state. */
934 SRSS_CLK_PILO_CONFIG &= (uint32_t)~(SRSS_CLK_PILO_CONFIG_PILO_EN_Msk |
935 SRSS_CLK_PILO_CONFIG_PILO_RESET_N_Msk |
936 SRSS_CLK_PILO_CONFIG_PILO_CLK_EN_Msk);
937 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
938 }
939
940
Cy_SysClk_PiloSetTrim(uint32_t trimVal)941 void Cy_SysClk_PiloSetTrim(uint32_t trimVal)
942 {
943 #if ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE)))
944 CY_PRA_FUNCTION_CALL_VOID_PARAM(CY_PRA_MSG_TYPE_SECURE_ONLY, CY_PRA_CLK_FUNC_SET_PILO_TRIM, trimVal);
945 #else
946 CY_REG32_CLR_SET(SRSS_CLK_PILO_CONFIG, SRSS_CLK_PILO_CONFIG_PILO_FFREQ, trimVal);
947 #endif /* ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE))) */
948 }
949
950
Cy_SysClk_PiloGetTrim(void)951 uint32_t Cy_SysClk_PiloGetTrim(void)
952 {
953 return (_FLD2VAL(SRSS_CLK_PILO_CONFIG_PILO_FFREQ, SRSS_CLK_PILO_CONFIG));
954 }
955
956
957 /* ========================================================================== */
958 /* ========================== ALTHF SECTION =========================== */
959 /* ========================================================================== */
960
961
Cy_SysClk_AltHfGetFrequency(void)962 uint32_t Cy_SysClk_AltHfGetFrequency(void)
963 {
964 #if defined(CY_IP_MXBLESS)
965 return (cy_BleEcoClockFreqHz);
966 #else /* CY_IP_MXBLESS */
967 return (0UL);
968 #endif /* CY_IP_MXBLESS */
969 }
970
971
972 /* ========================================================================== */
973 /* ========================== ALTLF SECTION =========================== */
974 /* ========================================================================== */
975
976
Cy_SysClk_AltLfGetFrequency(void)977 uint32_t Cy_SysClk_AltLfGetFrequency(void)
978 {
979 return (0UL);
980 }
981
982
Cy_SysClk_AltLfIsEnabled(void)983 bool Cy_SysClk_AltLfIsEnabled(void)
984 {
985 return (false);
986 }
987
988
989 /* ========================================================================== */
990 /* =========================== ILO SECTION ============================ */
991 /* ========================================================================== */
992
993
Cy_SysClk_IloEnable(void)994 void Cy_SysClk_IloEnable(void)
995 {
996 #if defined (CY_DEVICE_SECURE)
997 cy_en_pra_status_t retStatus;
998 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_ILO_ENABLE, 1UL);
999
1000 if (retStatus != CY_PRA_STATUS_SUCCESS)
1001 {
1002 CY_ASSERT_L1(false);
1003 }
1004 #endif /* defined (CY_DEVICE_SECURE) */
1005 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
1006 SRSS_CLK_ILO_CONFIG |= SRSS_CLK_ILO_CONFIG_ENABLE_Msk;
1007 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
1008 }
1009
1010
Cy_SysClk_IloIsEnabled(void)1011 bool Cy_SysClk_IloIsEnabled(void)
1012 {
1013 return (_FLD2BOOL(SRSS_CLK_ILO_CONFIG_ENABLE, SRSS_CLK_ILO_CONFIG));
1014 }
1015
1016
Cy_SysClk_IloDisable(void)1017 cy_en_sysclk_status_t Cy_SysClk_IloDisable(void)
1018 {
1019 cy_en_sysclk_status_t retVal;
1020 #if defined (CY_DEVICE_SECURE)
1021 retVal = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_ILO_DISABLE, 0UL);
1022
1023 #endif /* defined (CY_DEVICE_SECURE) */
1024 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
1025 retVal = CY_SYSCLK_INVALID_STATE;
1026 if (!_FLD2BOOL(SRSS_WDT_CTL_WDT_EN, SRSS_WDT_CTL)) /* if disabled */
1027 {
1028 SRSS_CLK_ILO_CONFIG &= ~SRSS_CLK_ILO_CONFIG_ENABLE_Msk;
1029 retVal = CY_SYSCLK_SUCCESS;
1030 }
1031 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
1032 return (retVal);
1033 }
1034
1035
Cy_SysClk_IloHibernateOn(bool on)1036 void Cy_SysClk_IloHibernateOn(bool on)
1037 {
1038 #if defined (CY_DEVICE_SECURE)
1039 cy_en_pra_status_t retStatus;
1040 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_ILO_HIBERNATE_ON, on);
1041
1042 if (retStatus != CY_PRA_STATUS_SUCCESS)
1043 {
1044 CY_ASSERT_L1(false);
1045 }
1046 #endif /* defined (CY_DEVICE_SECURE) */
1047 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
1048 CY_REG32_CLR_SET(SRSS_CLK_ILO_CONFIG, SRSS_CLK_ILO_CONFIG_ILO_BACKUP, ((on) ? 1UL : 0UL));
1049 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
1050 }
1051
1052
1053 /* ========================================================================== */
1054 /* ========================= EXTCLK SECTION =========================== */
1055 /* ========================================================================== */
1056
1057 #if ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE)))
1058 uint32_t cySysClkExtFreq = 0UL;
1059 #else
1060 static uint32_t cySysClkExtFreq = 0UL;
1061 #endif
1062
1063 #define CY_SYSCLK_EXTCLK_MAX_FREQ (100000000UL) /* 100 MHz */
1064 /** \endcond */
1065
Cy_SysClk_ExtClkSetFrequency(uint32_t freq)1066 void Cy_SysClk_ExtClkSetFrequency(uint32_t freq)
1067 {
1068 if (freq <= CY_SYSCLK_EXTCLK_MAX_FREQ)
1069 {
1070 #if defined (CY_DEVICE_SECURE)
1071 CY_PRA_FUNCTION_CALL_VOID_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_EXT_CLK_SET_FREQUENCY, freq);
1072 #endif
1073 cySysClkExtFreq = freq;
1074 }
1075
1076 }
1077
1078
Cy_SysClk_ExtClkGetFrequency(void)1079 uint32_t Cy_SysClk_ExtClkGetFrequency(void)
1080 {
1081 return (cySysClkExtFreq);
1082 }
1083
1084
1085 /* ========================================================================== */
1086 /* =========================== ECO SECTION ============================ */
1087 /* ========================================================================== */
1088 /** \cond INTERNAL */
1089 #define CY_SYSCLK_TRIM_ECO_Pos (SRSS_CLK_TRIM_ECO_CTL_WDTRIM_Pos)
1090 #define CY_SYSCLK_TRIM_ECO_Msk (SRSS_CLK_TRIM_ECO_CTL_WDTRIM_Msk | \
1091 SRSS_CLK_TRIM_ECO_CTL_ATRIM_Msk | \
1092 SRSS_CLK_TRIM_ECO_CTL_FTRIM_Msk | \
1093 SRSS_CLK_TRIM_ECO_CTL_RTRIM_Msk | \
1094 SRSS_CLK_TRIM_ECO_CTL_GTRIM_Msk)
1095
1096 /** \cond *********************************************************************
1097 * Function Name: cy_sqrt
1098 * Calculates square root.
1099 * The input is 32-bit wide.
1100 * The result is 16-bit wide.
1101 *******************************************************************************/
1102 #if !((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE)))
1103 static uint32_t cy_sqrt(uint32_t x);
cy_sqrt(uint32_t x)1104 static uint32_t cy_sqrt(uint32_t x)
1105 {
1106 uint32_t i;
1107 uint32_t res = 0UL;
1108 uint32_t add = 0x8000UL;
1109
1110 for(i = 0UL; i < 16UL; i++)
1111 {
1112 uint32_t tmp = res | add;
1113
1114 if (x >= (tmp * tmp))
1115 {
1116 res = tmp;
1117 }
1118
1119 add >>= 1U;
1120 }
1121
1122 return (res);
1123 }
1124 #endif /* !((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE))) */
1125
1126 static uint32_t ecoFrequency = 0UL; /* Internal storage for ECO frequency user setting */
1127
1128 #define CY_SYSCLK_ECO_FREQ_MIN (16000000UL) /* 16 MHz */
1129 #define CY_SYSCLK_ECO_FREQ_MAX (35000000UL) /* 35 MHz */
1130 #define CY_SYSCLK_ECO_CSM_MAX (100UL) /* 100 pF */
1131 #define CY_SYSCLK_ECO_ESR_MAX (1000UL) /* 1000 Ohm */
1132 #define CY_SYSCLK_ECO_DRV_MAX (2000UL) /* 2 mW */
1133
1134 #define CY_SYSCLK_ECO_IS_FREQ_VALID(freq) ((CY_SYSCLK_ECO_FREQ_MIN <= (freq)) && ((freq) <= CY_SYSCLK_ECO_FREQ_MAX))
1135 #define CY_SYSCLK_ECO_IS_CSM_VALID(csm) ((0UL < (csm)) && ((csm) <= CY_SYSCLK_ECO_CSM_MAX))
1136 #define CY_SYSCLK_ECO_IS_ESR_VALID(esr) ((0UL < (esr)) && ((esr) <= CY_SYSCLK_ECO_ESR_MAX))
1137 #define CY_SYSCLK_ECO_IS_DRV_VALID(drv) ((0UL < (drv)) && ((drv) <= CY_SYSCLK_ECO_DRV_MAX))
1138 /** \endcond */
1139
Cy_SysClk_EcoDisable(void)1140 void Cy_SysClk_EcoDisable(void)
1141 {
1142 #if defined (CY_DEVICE_SECURE)
1143 cy_en_pra_status_t retStatus;
1144 retStatus = CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_ECO_DISABLE, 0UL);
1145
1146 if (retStatus != CY_PRA_STATUS_SUCCESS)
1147 {
1148 CY_ASSERT_L1(false);
1149 }
1150 #endif /* defined (CY_DEVICE_SECURE) */
1151 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
1152 SRSS_CLK_ECO_CONFIG &= ~SRSS_CLK_ECO_CONFIG_ECO_EN_Msk;
1153 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
1154 }
1155
1156
Cy_SysClk_EcoGetStatus(void)1157 uint32_t Cy_SysClk_EcoGetStatus(void)
1158 {
1159 /* if ECO is not ready, just report the ECO_OK bit. Otherwise report 2 = ECO ready */
1160 return ((SRSS_CLK_ECO_STATUS_Msk == (SRSS_CLK_ECO_STATUS_Msk & SRSS_CLK_ECO_STATUS)) ?
1161 CY_SYSCLK_ECOSTAT_STABLE : (SRSS_CLK_ECO_STATUS_ECO_OK_Msk & SRSS_CLK_ECO_STATUS));
1162 }
1163
1164 #if (defined (CY_IP_MXS40SRSS)&& (CY_IP_MXS40SRSS_VERSION < 3))
Cy_SysClk_EcoSetFrequency(uint32_t freq)1165 void Cy_SysClk_EcoSetFrequency(uint32_t freq)
1166 {
1167 ecoFrequency = freq; /* Store the ECO frequency */
1168 }
1169 #endif /* (defined (CY_IP_MXS40SRSS)&& (CY_IP_MXS40SRSS_VERSION < 3)) */
1170
Cy_SysClk_EcoConfigure(uint32_t freq,uint32_t cSum,uint32_t esr,uint32_t driveLevel)1171 cy_en_sysclk_status_t Cy_SysClk_EcoConfigure(uint32_t freq, uint32_t cSum, uint32_t esr, uint32_t driveLevel)
1172 {
1173 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
1174
1175 #if defined (CY_DEVICE_SECURE)
1176 cy_stc_pra_clk_eco_configure_t ecoConfig;
1177 ecoConfig.praClkEcofreq = freq;
1178 ecoConfig.praCsum = cSum;
1179 ecoConfig.praEsr = esr;
1180 ecoConfig.praDriveLevel = driveLevel;
1181 retVal = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_ECO_CONFIGURE, &ecoConfig);
1182 if(CY_SYSCLK_SUCCESS == retVal)
1183 {
1184 ecoFrequency = freq; /* Store the ECO frequency */
1185 }
1186 #endif /* defined (CY_DEVICE_SECURE) */
1187 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
1188
1189
1190 if (0UL != (SRSS_CLK_ECO_CONFIG_ECO_EN_Msk & SRSS_CLK_ECO_CONFIG))
1191 {
1192 retVal = CY_SYSCLK_INVALID_STATE;
1193 }
1194 else if ((CY_SYSCLK_ECO_IS_FREQ_VALID(freq)) &&
1195 (CY_SYSCLK_ECO_IS_CSM_VALID(cSum)) &&
1196 (CY_SYSCLK_ECO_IS_ESR_VALID(esr)) &&
1197 (CY_SYSCLK_ECO_IS_DRV_VALID(driveLevel)))
1198 {
1199 /* Calculate intermediate values */
1200 uint32_t freqKhz = CY_SYSLIB_DIV_ROUND(freq, 1000UL);
1201
1202 uint32_t maxAmpl = CY_SYSLIB_DIV_ROUND((159155UL * /* 5 * 100000 / PI */
1203 cy_sqrt(CY_SYSLIB_DIV_ROUND(2000000UL * driveLevel, esr))), /* Scaled by 2 */
1204 (freqKhz * cSum)); /* The result is scaled by 10^3 */
1205
1206 /* 10^9 / (5 * 4 * 4 * PI^2) = 1266514,7955292221430484932901216.. -> 126651, scaled by 10 */
1207 uint32_t ampSect = (CY_SYSLIB_DIV_ROUND(cSum * cSum *
1208 CY_SYSLIB_DIV_ROUND(freqKhz * freqKhz, 126651UL), 100UL) * esr)/ 900000UL;
1209
1210 if ((maxAmpl >= 650UL) && (ampSect <= 3UL))
1211 {
1212 uint32_t gtrim = (ampSect > 1UL) ? ampSect :
1213 ((ampSect == 1UL) ? 0UL : 1UL);
1214
1215 /* Update all fields of trim control register with one write, without changing the ITRIM field */
1216 uint32_t reg = _VAL2FLD(SRSS_CLK_TRIM_ECO_CTL_WDTRIM, 7UL) |
1217 _VAL2FLD(SRSS_CLK_TRIM_ECO_CTL_ATRIM, 15UL) |
1218 _VAL2FLD(SRSS_CLK_TRIM_ECO_CTL_FTRIM, 3UL) |
1219 _VAL2FLD(SRSS_CLK_TRIM_ECO_CTL_RTRIM, 0UL) |
1220 _VAL2FLD(SRSS_CLK_TRIM_ECO_CTL_GTRIM, gtrim);
1221
1222 CY_REG32_CLR_SET(SRSS_CLK_TRIM_ECO_CTL, CY_SYSCLK_TRIM_ECO, reg);
1223
1224 SRSS_CLK_ECO_CONFIG |= SRSS_CLK_ECO_CONFIG_AGC_EN_Msk;
1225
1226 ecoFrequency = freq; /* Store the ECO frequency */
1227
1228 retVal = CY_SYSCLK_SUCCESS;
1229 }
1230 }
1231 else
1232 {
1233 /* Return CY_SYSCLK_BAD_PARAM */
1234 }
1235 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
1236 return (retVal);
1237 }
1238
1239
Cy_SysClk_EcoEnable(uint32_t timeoutus)1240 cy_en_sysclk_status_t Cy_SysClk_EcoEnable(uint32_t timeoutus)
1241 {
1242 cy_en_sysclk_status_t retVal;
1243 #if defined (CY_DEVICE_SECURE)
1244 retVal = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_ECO_ENABLE, timeoutus);
1245 #endif /* defined (CY_DEVICE_SECURE) */
1246 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
1247
1248 bool zeroTimeout = (0UL == timeoutus);
1249 retVal = CY_SYSCLK_INVALID_STATE;
1250
1251 /* Invalid state error if ECO is already enabled */
1252 if (0UL == (SRSS_CLK_ECO_CONFIG_ECO_EN_Msk & SRSS_CLK_ECO_CONFIG))
1253 {
1254 /* Set ECO enable */
1255 SRSS_CLK_ECO_CONFIG |= SRSS_CLK_ECO_CONFIG_ECO_EN_Msk;
1256
1257 /* Wait for CY_SYSCLK_ECOSTAT_STABLE */
1258 for (; (CY_SYSCLK_ECOSTAT_STABLE != Cy_SysClk_EcoGetStatus()) && (0UL != timeoutus); timeoutus--)
1259 {
1260 Cy_SysLib_DelayUs(1U);
1261 }
1262
1263 if (zeroTimeout || (0UL != timeoutus))
1264 {
1265 retVal = CY_SYSCLK_SUCCESS;
1266 }
1267 else
1268 {
1269 /* If ECO doesn't start, then disable it */
1270 SRSS_CLK_ECO_CONFIG &= ~SRSS_CLK_ECO_CONFIG_ECO_EN_Msk;
1271 retVal = CY_SYSCLK_TIMEOUT;
1272 }
1273 }
1274 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
1275 return (retVal);
1276 }
1277
1278
Cy_SysClk_EcoGetFrequency(void)1279 uint32_t Cy_SysClk_EcoGetFrequency(void)
1280 {
1281 return ((CY_SYSCLK_ECOSTAT_STABLE == Cy_SysClk_EcoGetStatus()) ? ecoFrequency : 0UL);
1282 }
1283
1284
1285 /* ========================================================================== */
1286 /* ==================== INPUT MULTIPLEXER SECTION ===================== */
1287 /* ========================================================================== */
1288
1289
Cy_SysClk_ClkPathSetSource(uint32_t clkPath,cy_en_clkpath_in_sources_t source)1290 cy_en_sysclk_status_t Cy_SysClk_ClkPathSetSource(uint32_t clkPath, cy_en_clkpath_in_sources_t source)
1291 {
1292 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
1293 if ((clkPath < CY_SRSS_NUM_CLKPATH) &&
1294 ((source <= CY_SYSCLK_CLKPATH_IN_DSIMUX) ||
1295 ((CY_SYSCLK_CLKPATH_IN_DSI <= source) && (source <= CY_SYSCLK_CLKPATH_IN_PILO))))
1296 {
1297 #if defined (CY_DEVICE_SECURE)
1298 cy_stc_pra_clkpathsetsource_t clkpath_set_source;
1299 clkpath_set_source.clk_path = clkPath;
1300 clkpath_set_source.source = source;
1301 retVal = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_PATH_SET_SOURCE, &clkpath_set_source);
1302 #endif /* defined (CY_DEVICE_SECURE) */
1303 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
1304
1305 if (source >= CY_SYSCLK_CLKPATH_IN_DSI)
1306 {
1307 SRSS_CLK_DSI_SELECT[clkPath] = _VAL2FLD(SRSS_CLK_DSI_SELECT_DSI_MUX, (uint32_t)source);
1308 SRSS_CLK_PATH_SELECT[clkPath] = _VAL2FLD(SRSS_CLK_PATH_SELECT_PATH_MUX, (uint32_t)CY_SYSCLK_CLKPATH_IN_DSIMUX);
1309 }
1310 else
1311 {
1312 SRSS_CLK_PATH_SELECT[clkPath] = _VAL2FLD(SRSS_CLK_PATH_SELECT_PATH_MUX, (uint32_t)source);
1313 }
1314 retVal = CY_SYSCLK_SUCCESS;
1315 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
1316 }
1317 return (retVal);
1318
1319 }
1320
1321
Cy_SysClk_ClkPathGetSource(uint32_t clkPath)1322 cy_en_clkpath_in_sources_t Cy_SysClk_ClkPathGetSource(uint32_t clkPath)
1323 {
1324 CY_ASSERT_L1(clkPath < CY_SRSS_NUM_CLKPATH);
1325 cy_en_clkpath_in_sources_t retVal =
1326 (cy_en_clkpath_in_sources_t )((uint32_t)_FLD2VAL(SRSS_CLK_PATH_SELECT_PATH_MUX, SRSS_CLK_PATH_SELECT[clkPath]));
1327 if (retVal == CY_SYSCLK_CLKPATH_IN_DSIMUX)
1328 {
1329 retVal = (cy_en_clkpath_in_sources_t)((uint32_t)(((uint32_t)CY_SYSCLK_CLKPATH_IN_DSI) |
1330 ((uint32_t)(_FLD2VAL(SRSS_CLK_DSI_SELECT_DSI_MUX, SRSS_CLK_DSI_SELECT[clkPath])))));
1331 }
1332 return (retVal);
1333 }
1334
1335
Cy_SysClk_ClkPathMuxGetFrequency(uint32_t clkPath)1336 uint32_t Cy_SysClk_ClkPathMuxGetFrequency(uint32_t clkPath)
1337 {
1338 CY_ASSERT_L1(clkPath < CY_SRSS_NUM_CLKPATH);
1339
1340 uint32_t freq = 0UL; /* The path mux output frequency in Hz, 0 = an unknown frequency */
1341
1342 /* Get the frequency of the source, i.e., the path mux input */
1343 switch(Cy_SysClk_ClkPathGetSource(clkPath))
1344 {
1345 case CY_SYSCLK_CLKPATH_IN_IMO: /* The IMO frequency is fixed at 8 MHz */
1346 freq = CY_SYSCLK_IMO_FREQ;
1347 break;
1348
1349 case CY_SYSCLK_CLKPATH_IN_EXT:
1350 freq = Cy_SysClk_ExtClkGetFrequency();
1351 break;
1352
1353 case CY_SYSCLK_CLKPATH_IN_ECO:
1354 freq = Cy_SysClk_EcoGetFrequency();
1355 break;
1356
1357 case CY_SYSCLK_CLKPATH_IN_ALTHF:
1358 freq = Cy_SysClk_AltHfGetFrequency();
1359 break;
1360
1361 case CY_SYSCLK_CLKPATH_IN_ILO:
1362 freq = (0UL != (SRSS_CLK_ILO_CONFIG & SRSS_CLK_ILO_CONFIG_ENABLE_Msk)) ? CY_SYSCLK_ILO_FREQ : 0UL;
1363 break;
1364
1365 case CY_SYSCLK_CLKPATH_IN_WCO:
1366 freq = (Cy_SysClk_WcoOkay()) ? CY_SYSCLK_WCO_FREQ : 0UL;
1367 break;
1368
1369 case CY_SYSCLK_CLKPATH_IN_PILO:
1370 freq = (0UL != (SRSS_CLK_PILO_CONFIG & SRSS_CLK_PILO_CONFIG_PILO_EN_Msk)) ? CY_SYSCLK_PILO_FREQ : 0UL;
1371 break;
1372
1373 case CY_SYSCLK_CLKPATH_IN_ALTLF:
1374 freq = Cy_SysClk_AltLfGetFrequency();
1375 break;
1376
1377 default:
1378 /* Don't know the frequency of dsi_out, leave freq = 0UL */
1379 break;
1380 }
1381
1382 return (freq);
1383 }
1384
1385
Cy_SysClk_ClkPathGetFrequency(uint32_t clkPath)1386 uint32_t Cy_SysClk_ClkPathGetFrequency(uint32_t clkPath)
1387 {
1388 CY_ASSERT_L1(clkPath < CY_SRSS_NUM_CLKPATH);
1389
1390 uint32_t freq = 0UL;
1391
1392 if (clkPath == (uint32_t)CY_SYSCLK_CLKHF_IN_CLKPATH0) /* FLL? (always path 0) */
1393 {
1394 freq = Cy_SysClk_FllGetFrequency();
1395 }
1396 else if (clkPath <= CY_SRSS_NUM_PLL) /* PLL? (always path 1...N)*/
1397 {
1398 freq = Cy_SysClk_PllGetFrequency(clkPath);
1399 }
1400 else
1401 {
1402 /* Do nothing with the path mux frequency */
1403 }
1404
1405 if(freq==0UL)
1406 {
1407 freq = Cy_SysClk_ClkPathMuxGetFrequency(clkPath);
1408 }
1409
1410 return (freq);
1411 }
1412
1413
1414 /* ========================================================================== */
1415 /* =========================== FLL SECTION ============================ */
1416 /* ========================================================================== */
1417
1418
1419 #define CY_SYSCLK_FLL_MIN_CCO_OUTPUT_FREQ (48000000UL)
1420 #define CY_SYSCLK_FLL_MIN_OUTPUT_FREQ (CY_SYSCLK_FLL_MIN_CCO_OUTPUT_FREQ / 2U)
1421 #define CY_SYSCLK_FLL_MAX_OUTPUT_FREQ (100000000UL)
1422
1423 #define CY_SYSCLK_FLL_IS_CCO_RANGE_VALID(range) (((range) == CY_SYSCLK_FLL_CCO_RANGE0) || \
1424 ((range) == CY_SYSCLK_FLL_CCO_RANGE1) || \
1425 ((range) == CY_SYSCLK_FLL_CCO_RANGE2) || \
1426 ((range) == CY_SYSCLK_FLL_CCO_RANGE3) || \
1427 ((range) == CY_SYSCLK_FLL_CCO_RANGE4))
1428 /** \cond INTERNAL */
1429 #define CY_SYSCLK_FLL_INT_COEF (327680000UL)
1430 #define CY_SYSCLK_FLL_GAIN_IDX (11U)
1431 #define CY_SYSCLK_FLL_GAIN_VAL (8UL * CY_SYSCLK_FLL_INT_COEF)
1432
1433 #define TRIM_STEPS_SCALE (100000000ULL) /* 10 ^ 8 */
1434 #define MARGIN_SCALE (100000ULL) /* 10 ^ 5 */
1435 /** \endcond */
1436
Cy_SysClk_FllIsEnabled(void)1437 bool Cy_SysClk_FllIsEnabled(void)
1438 {
1439 return (_FLD2BOOL(SRSS_CLK_FLL_CONFIG_FLL_ENABLE, SRSS_CLK_FLL_CONFIG));
1440 }
1441
1442
Cy_SysClk_FllLocked(void)1443 bool Cy_SysClk_FllLocked(void)
1444 {
1445 return (_FLD2BOOL(SRSS_CLK_FLL_STATUS_LOCKED, SRSS_CLK_FLL_STATUS));
1446 }
1447
1448
Cy_SysClk_FllDisable(void)1449 cy_en_sysclk_status_t Cy_SysClk_FllDisable(void)
1450 {
1451 cy_en_sysclk_status_t retStatus;
1452 #if defined (CY_DEVICE_SECURE)
1453 retStatus = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_FLL_DISABLE, 0UL);
1454
1455 #endif /* defined (CY_DEVICE_SECURE) */
1456 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
1457 CY_REG32_CLR_SET(SRSS_CLK_FLL_CONFIG3, SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, CY_SYSCLK_FLLPLL_OUTPUT_INPUT);
1458 SRSS_CLK_FLL_CONFIG &= ~SRSS_CLK_FLL_CONFIG_FLL_ENABLE_Msk;
1459 SRSS_CLK_FLL_CONFIG4 &= ~SRSS_CLK_FLL_CONFIG4_CCO_ENABLE_Msk;
1460 retStatus = (CY_SYSCLK_SUCCESS);
1461 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
1462 return retStatus;
1463 }
1464
1465
Cy_SysClk_FllConfigure(uint32_t inputFreq,uint32_t outputFreq,cy_en_fll_pll_output_mode_t outputMode)1466 cy_en_sysclk_status_t Cy_SysClk_FllConfigure(uint32_t inputFreq, uint32_t outputFreq, cy_en_fll_pll_output_mode_t outputMode)
1467 {
1468 cy_en_sysclk_status_t retVal = CY_SYSCLK_SUCCESS;
1469
1470 /* check for errors */
1471 if ((outputFreq < CY_SYSCLK_FLL_MIN_OUTPUT_FREQ) || (CY_SYSCLK_FLL_MAX_OUTPUT_FREQ < outputFreq) || /* invalid output frequency */
1472 (((outputFreq * 5UL) / inputFreq) < 11UL)) /* check output/input frequency ratio */
1473 {
1474 retVal = CY_SYSCLK_BAD_PARAM;
1475 }
1476 else /* no errors */
1477 {
1478 /* If output mode is bypass (input routed directly to output), then done.
1479 The output frequency equals the input frequency regardless of the
1480 frequency parameters. */
1481 if (outputMode != CY_SYSCLK_FLLPLL_OUTPUT_INPUT)
1482 {
1483 cy_stc_fll_manual_config_t config;
1484 uint32_t ccoFreq;
1485 bool wcoSource = (CY_SYSCLK_CLKPATH_IN_WCO == Cy_SysClk_ClkPathGetSource(0UL/*FLL*/)) ? true : false;
1486
1487 config.outputMode = outputMode;
1488 /* 1. Output division by 2 is always required */
1489 config.enableOutputDiv = true;
1490 /* 2. Compute the target CCO frequency from the target output frequency and output division */
1491 ccoFreq = outputFreq * 2UL;
1492 /* 3. Compute the CCO range value from the CCO frequency */
1493 config.ccoRange = ((ccoFreq >= 150339200UL) ? CY_SYSCLK_FLL_CCO_RANGE4 :
1494 ((ccoFreq >= 113009380UL) ? CY_SYSCLK_FLL_CCO_RANGE3 :
1495 ((ccoFreq >= 84948700UL) ? CY_SYSCLK_FLL_CCO_RANGE2 :
1496 ((ccoFreq >= 63855600UL) ? CY_SYSCLK_FLL_CCO_RANGE1 : CY_SYSCLK_FLL_CCO_RANGE0))));
1497
1498 /* 4. Compute the FLL reference divider value.
1499 refDiv is a constant if the WCO is the FLL source, otherwise the formula is
1500 refDiv = ROUNDUP((inputFreq / outputFreq) * 250) */
1501 config.refDiv = wcoSource ? 19U : (uint16_t)CY_SYSLIB_DIV_ROUNDUP((uint64_t)inputFreq * 250ULL, (uint64_t)outputFreq);
1502
1503 /* 5. Compute the FLL multiplier value.
1504 Formula is fllMult = ccoFreq / (inputFreq / refDiv) */
1505 config.fllMult = (uint32_t)CY_SYSLIB_DIV_ROUNDUP((uint64_t)ccoFreq * (uint64_t)config.refDiv, (uint64_t)inputFreq);
1506 /* 6. Compute the lock tolerance.
1507 Formula is lock tolerance = 1.5 * fllMult * (((1 + CCO accuracy) / (1 - source clock accuracy)) - 1)
1508 We assume CCO accuracy is 0.25%.
1509 We assume the source clock accuracy = 1%. This is the accuracy of the IMO.
1510 Therefore the formula is lock tolerance = 1.5 * fllMult * 0.012626 = 0.018939 * fllMult */
1511 config.lockTolerance = (uint16_t)CY_SYSLIB_DIV_ROUNDUP(config.fllMult * 18939UL, 1000000UL);
1512
1513 {
1514 /* constants indexed by ccoRange */
1515 const uint32_t trimSteps[] = {110340UL, 110200UL, 110000UL, 110000UL, 117062UL}; /* Scaled by 10^8 */
1516 const uint32_t margin[] = {436UL, 581UL, 772UL, 1030UL, 1320UL}; /* Scaled by 10^5 */
1517 /* 7. Compute the CCO igain and pgain */
1518 {
1519 /* intermediate parameters */
1520 uint32_t kcco = (trimSteps[config.ccoRange] * margin[config.ccoRange]);
1521 uint32_t ki_p = (uint32_t)CY_SYSLIB_DIV_ROUND(850ULL * CY_SYSCLK_FLL_INT_COEF * inputFreq, (uint64_t)kcco * (uint64_t)config.refDiv);
1522
1523 /* find the largest IGAIN value that is less than or equal to ki_p */
1524 uint32_t locigain = CY_SYSCLK_FLL_GAIN_VAL;
1525 uint32_t locpgain = CY_SYSCLK_FLL_GAIN_VAL;
1526
1527 /* find the largest IGAIN value that is less than or equal to ki_p */
1528 for(config.igain = CY_SYSCLK_FLL_GAIN_IDX; config.igain != 0UL; config.igain--)
1529 {
1530 if(locigain <= ki_p)
1531 {
1532 break;
1533 }
1534 locigain >>= 1U;
1535 }
1536 /* decrement igain if the WCO is the FLL source */
1537 if (wcoSource && (config.igain > 0U))
1538 {
1539 config.igain--;
1540 locigain >>= 1U;
1541 }
1542
1543 /* then find the largest PGAIN value that is less than or equal to ki_p - igain */
1544 for(config.pgain = CY_SYSCLK_FLL_GAIN_IDX; config.pgain != 0UL; config.pgain--)
1545 {
1546 if(locpgain <= (ki_p - locigain))
1547 {
1548 break;
1549 }
1550 locpgain >>= 1U;
1551 }
1552
1553 /* decrement pgain if the WCO is the FLL source */
1554 if (wcoSource && (config.pgain > 0U))
1555 {
1556 config.pgain--;
1557 }
1558 }
1559
1560 /* 8. Compute the CCO_FREQ bits in CLK_FLL_CONFIG4 register */
1561 {
1562 uint64_t cmp = CY_SYSLIB_DIV_ROUND(((TRIM_STEPS_SCALE / MARGIN_SCALE) * (uint64_t)ccoFreq), (uint64_t)margin[config.ccoRange]);
1563 uint64_t mlt = TRIM_STEPS_SCALE + (uint64_t)trimSteps[config.ccoRange];
1564 uint64_t res = mlt;
1565
1566 config.cco_Freq = 0U;
1567
1568 while(res < cmp)
1569 {
1570 res *= mlt;
1571 res /= TRIM_STEPS_SCALE;
1572 config.cco_Freq++;
1573 }
1574 }
1575 }
1576
1577 /* 9. Compute the settling count, using a 1 usec settling time. Use a constant if the WCO is the FLL source */
1578 {
1579 uint64_t fref = CY_SYSLIB_DIV_ROUND(6000ULL * (uint64_t)inputFreq, (uint64_t)config.refDiv);
1580 uint32_t divval = CY_SYSLIB_DIV_ROUNDUP(inputFreq, 1000000UL);
1581 uint32_t altval = (uint32_t)CY_SYSLIB_DIV_ROUNDUP((uint64_t)divval * fref, 6000000ULL) + 1UL;
1582
1583 config.settlingCount = wcoSource ? 200U : (uint16_t)
1584 ((outputFreq < fref) ? divval :
1585 ((divval > altval) ? divval : altval));
1586 }
1587 /* Configure FLL based on calculated values */
1588 retVal = Cy_SysClk_FllManualConfigure(&config);
1589 }
1590 else /* if not, bypass output mode */
1591 {
1592 CY_REG32_CLR_SET(SRSS_CLK_FLL_CONFIG3, SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, CY_SYSCLK_FLLPLL_OUTPUT_INPUT);
1593 }
1594 }
1595
1596 return (retVal);
1597 }
1598
1599
Cy_SysClk_FllManualConfigure(const cy_stc_fll_manual_config_t * config)1600 cy_en_sysclk_status_t Cy_SysClk_FllManualConfigure(const cy_stc_fll_manual_config_t *config)
1601 {
1602 cy_en_sysclk_status_t retVal;
1603 #if defined (CY_DEVICE_SECURE)
1604 retVal = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_FLL_MANCONFIG, config);
1605 #endif /* defined (CY_DEVICE_SECURE) */
1606 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
1607 retVal = CY_SYSCLK_INVALID_STATE;
1608
1609 /* Check for errors */
1610 CY_ASSERT_L1(config != NULL);
1611
1612 if (!Cy_SysClk_FllIsEnabled()) /* If disabled */
1613 {
1614 /* update CLK_FLL_CONFIG register with 2 parameters; FLL_ENABLE is already 0 */
1615 /* asserts just check for bitfield overflow */
1616 CY_ASSERT_L1(config->fllMult <= (SRSS_CLK_FLL_CONFIG_FLL_MULT_Msk >> SRSS_CLK_FLL_CONFIG_FLL_MULT_Pos));
1617
1618 SRSS_CLK_FLL_CONFIG = _VAL2FLD(SRSS_CLK_FLL_CONFIG_FLL_MULT, config->fllMult) |
1619 _BOOL2FLD(SRSS_CLK_FLL_CONFIG_FLL_OUTPUT_DIV, config->enableOutputDiv);
1620
1621 /* update CLK_FLL_CONFIG2 register with 2 parameters */
1622 /* asserts just check for bitfield overflow */
1623 CY_ASSERT_L1(config->refDiv <= (SRSS_CLK_FLL_CONFIG2_FLL_REF_DIV_Msk >> SRSS_CLK_FLL_CONFIG2_FLL_REF_DIV_Pos));
1624 CY_ASSERT_L1(config->lockTolerance <= (SRSS_CLK_FLL_CONFIG2_LOCK_TOL_Msk >> SRSS_CLK_FLL_CONFIG2_LOCK_TOL_Pos));
1625
1626 SRSS_CLK_FLL_CONFIG2 = _VAL2FLD(SRSS_CLK_FLL_CONFIG2_FLL_REF_DIV, config->refDiv) |
1627 _VAL2FLD(SRSS_CLK_FLL_CONFIG2_LOCK_TOL, config->lockTolerance);
1628
1629 /* update CLK_FLL_CONFIG3 register with 4 parameters */
1630 /* asserts just check for bitfield overflow */
1631 CY_ASSERT_L1(config->igain <= (SRSS_CLK_FLL_CONFIG3_FLL_LF_IGAIN_Msk >> SRSS_CLK_FLL_CONFIG3_FLL_LF_IGAIN_Pos));
1632 CY_ASSERT_L1(config->pgain <= (SRSS_CLK_FLL_CONFIG3_FLL_LF_PGAIN_Msk >> SRSS_CLK_FLL_CONFIG3_FLL_LF_PGAIN_Pos));
1633 CY_ASSERT_L1(config->settlingCount <= (SRSS_CLK_FLL_CONFIG3_SETTLING_COUNT_Msk >> SRSS_CLK_FLL_CONFIG3_SETTLING_COUNT_Pos));
1634
1635 SRSS_CLK_FLL_CONFIG3 = _VAL2FLD(SRSS_CLK_FLL_CONFIG3_FLL_LF_IGAIN, config->igain) |
1636 _VAL2FLD(SRSS_CLK_FLL_CONFIG3_FLL_LF_PGAIN, config->pgain) |
1637 _VAL2FLD(SRSS_CLK_FLL_CONFIG3_SETTLING_COUNT, config->settlingCount) |
1638 _VAL2FLD(SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, config->outputMode);
1639
1640 /* update CLK_FLL_CONFIG4 register with 1 parameter; preserve other bits */
1641 /* asserts just check for bitfield overflow */
1642 CY_ASSERT_L1(CY_SYSCLK_FLL_IS_CCO_RANGE_VALID(config->ccoRange));
1643 CY_ASSERT_L1(config->cco_Freq <= (SRSS_CLK_FLL_CONFIG4_CCO_FREQ_Msk >> SRSS_CLK_FLL_CONFIG4_CCO_FREQ_Pos));
1644
1645 CY_REG32_CLR_SET(SRSS_CLK_FLL_CONFIG4, SRSS_CLK_FLL_CONFIG4_CCO_RANGE, (uint32_t)(config->ccoRange));
1646 CY_REG32_CLR_SET(SRSS_CLK_FLL_CONFIG4, SRSS_CLK_FLL_CONFIG4_CCO_FREQ, (uint32_t)(config->cco_Freq));
1647
1648 retVal = CY_SYSCLK_SUCCESS;
1649 }
1650
1651 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
1652 return (retVal);
1653 }
1654
1655
Cy_SysClk_FllGetConfiguration(cy_stc_fll_manual_config_t * config)1656 void Cy_SysClk_FllGetConfiguration(cy_stc_fll_manual_config_t *config)
1657 {
1658 CY_ASSERT_L1(config != NULL);
1659 /* read 2 parameters from CLK_FLL_CONFIG register */
1660 uint32_t tempReg = SRSS_CLK_FLL_CONFIG;
1661 config->fllMult = _FLD2VAL(SRSS_CLK_FLL_CONFIG_FLL_MULT, tempReg);
1662 config->enableOutputDiv = _FLD2BOOL(SRSS_CLK_FLL_CONFIG_FLL_OUTPUT_DIV, tempReg);
1663 /* read 2 parameters from CLK_FLL_CONFIG2 register */
1664 tempReg = SRSS_CLK_FLL_CONFIG2;
1665 config->refDiv = (uint16_t)_FLD2VAL(SRSS_CLK_FLL_CONFIG2_FLL_REF_DIV, tempReg);
1666 config->lockTolerance = (uint16_t)_FLD2VAL(SRSS_CLK_FLL_CONFIG2_LOCK_TOL, tempReg);
1667 /* read 4 parameters from CLK_FLL_CONFIG3 register */
1668 tempReg = SRSS_CLK_FLL_CONFIG3;
1669 config->igain = (uint8_t)_FLD2VAL(SRSS_CLK_FLL_CONFIG3_FLL_LF_IGAIN, tempReg);
1670 config->pgain = (uint8_t)_FLD2VAL(SRSS_CLK_FLL_CONFIG3_FLL_LF_PGAIN, tempReg);
1671 config->settlingCount = (uint16_t)_FLD2VAL(SRSS_CLK_FLL_CONFIG3_SETTLING_COUNT, tempReg);
1672 config->outputMode = (cy_en_fll_pll_output_mode_t)((uint32_t)_FLD2VAL(SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, tempReg));
1673 /* read 2 parameters from CLK_FLL_CONFIG4 register */
1674 tempReg = SRSS_CLK_FLL_CONFIG4;
1675 config->ccoRange = (cy_en_fll_cco_ranges_t)((uint32_t)_FLD2VAL(SRSS_CLK_FLL_CONFIG4_CCO_RANGE, tempReg));
1676 config->cco_Freq = (uint16_t)_FLD2VAL(SRSS_CLK_FLL_CONFIG4_CCO_FREQ, tempReg);
1677 }
1678
1679
Cy_SysClk_FllEnable(uint32_t timeoutus)1680 cy_en_sysclk_status_t Cy_SysClk_FllEnable(uint32_t timeoutus)
1681 {
1682 cy_en_sysclk_status_t retStatus;
1683 #if defined (CY_DEVICE_SECURE)
1684 retStatus = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_FLL_ENABLE, timeoutus);
1685 #endif /* defined (CY_DEVICE_SECURE) */
1686 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
1687 bool zeroTimeout = (0UL == timeoutus);
1688
1689 /* first set the CCO enable bit */
1690 SRSS_CLK_FLL_CONFIG4 |= SRSS_CLK_FLL_CONFIG4_CCO_ENABLE_Msk;
1691
1692 /* Wait until CCO is ready */
1693 for (; (!_FLD2BOOL(SRSS_CLK_FLL_STATUS_CCO_READY, SRSS_CLK_FLL_STATUS)) && /* if cco_ready == 0 */
1694 (0UL != timeoutus);
1695 timeoutus--)
1696 {
1697 Cy_SysLib_DelayUs(1U);
1698 }
1699
1700 /* Set the FLL bypass mode to FLL_REF */
1701 CY_REG32_CLR_SET(SRSS_CLK_FLL_CONFIG3, SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, CY_SYSCLK_FLLPLL_OUTPUT_INPUT);
1702
1703 /* Set the FLL enable bit, if CCO is ready */
1704 if (zeroTimeout || (0UL != timeoutus))
1705 {
1706 SRSS_CLK_FLL_CONFIG |= SRSS_CLK_FLL_CONFIG_FLL_ENABLE_Msk;
1707 }
1708
1709 /* now do the timeout wait for FLL_STATUS, bit LOCKED */
1710 for (; (!Cy_SysClk_FllLocked()) && /* if locked == 0 */
1711 (0UL != timeoutus);
1712 timeoutus--)
1713 {
1714 Cy_SysLib_DelayUs(1U);
1715 }
1716
1717 if (zeroTimeout || (0UL != timeoutus))
1718 {
1719 /* Set the FLL bypass mode to FLL_OUT (ignoring lock indicator) */
1720 CY_REG32_CLR_SET(SRSS_CLK_FLL_CONFIG3, SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, CY_SYSCLK_FLLPLL_OUTPUT_OUTPUT);
1721 }
1722 else
1723 {
1724 /* If lock doesn't occur, FLL is stopped */
1725 (void)Cy_SysClk_FllDisable();
1726 }
1727
1728 retStatus = ((zeroTimeout || (0UL != timeoutus)) ? CY_SYSCLK_SUCCESS : CY_SYSCLK_TIMEOUT);
1729 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
1730 return retStatus;
1731 }
1732
1733
1734 /* ========================================================================== */
1735 /* =========================== PLL SECTION ============================ */
1736 /* ========================================================================== */
1737
1738 /* PLL OUTPUT_DIV bitfield allowable range */
1739 #define CY_SYSCLK_PLL_MIN_OUTPUT_DIV (2UL)
1740 #define CY_SYSCLK_PLL_MAX_OUTPUT_DIV (16UL)
1741
1742 /* PLL REFERENCE_DIV bitfield allowable range */
1743 #define CY_SYSCLK_PLL_MIN_REF_DIV (1UL)
1744 #define CY_SYSCLK_PLL_MAX_REF_DIV (18UL)
1745
1746 /* PLL FEEDBACK_DIV bitfield allowable ranges, LF and normal modes */
1747 #define CY_SYSCLK_PLL_MIN_FB_DIV_LF (19UL)
1748 #define CY_SYSCLK_PLL_MAX_FB_DIV_LF (56UL)
1749 #define CY_SYSCLK_PLL_MIN_FB_DIV_NORM (22UL)
1750 #define CY_SYSCLK_PLL_MAX_FB_DIV_NORM (112UL)
1751
1752 /* PLL FEEDBACK_DIV bitfield allowable range selection */
1753 #define CY_SYSCLK_PLL_MIN_FB_DIV ((config->lfMode) ? CY_SYSCLK_PLL_MIN_FB_DIV_LF : CY_SYSCLK_PLL_MIN_FB_DIV_NORM)
1754 #define CY_SYSCLK_PLL_MAX_FB_DIV ((config->lfMode) ? CY_SYSCLK_PLL_MAX_FB_DIV_LF : CY_SYSCLK_PLL_MAX_FB_DIV_NORM)
1755
1756 /* PLL Fvco range allowable ranges, LF and normal modes */
1757 #define CY_SYSCLK_PLL_MIN_FVCO_LF (170000000UL)
1758 #define CY_SYSCLK_PLL_MAX_FVCO_LF (200000000UL)
1759 #define CY_SYSCLK_PLL_MIN_FVCO_NORM (200000000UL)
1760 #define CY_SYSCLK_PLL_MAX_FVCO_NORM (400000000UL)
1761 /* PLL Fvco range selection */
1762 #define CY_SYSCLK_PLL_MIN_FVCO ((config->lfMode) ? CY_SYSCLK_PLL_MIN_FVCO_LF : CY_SYSCLK_PLL_MIN_FVCO_NORM)
1763 #define CY_SYSCLK_PLL_MAX_FVCO ((config->lfMode) ? CY_SYSCLK_PLL_MAX_FVCO_LF : CY_SYSCLK_PLL_MAX_FVCO_NORM)
1764
1765 /* PLL input and output frequency limits */
1766 #define CY_SYSCLK_PLL_MIN_IN_FREQ (4000000UL)
1767 #define CY_SYSCLK_PLL_MAX_IN_FREQ (64000000UL)
1768 #define CY_SYSCLK_PLL_MIN_OUT_FREQ (CY_SYSCLK_PLL_MIN_FVCO / CY_SYSCLK_PLL_MAX_OUTPUT_DIV)
1769 #define CY_SYSCLK_PLL_MAX_OUT_FREQ (150000000UL)
1770
1771
Cy_SysClk_PllIsEnabled(uint32_t clkPath)1772 bool Cy_SysClk_PllIsEnabled(uint32_t clkPath)
1773 {
1774 clkPath--; /* to correctly access PLL config and status registers structures */
1775 CY_ASSERT_L1(clkPath < CY_SRSS_NUM_PLL);
1776 return (_FLD2BOOL(SRSS_CLK_PLL_CONFIG_ENABLE, SRSS_CLK_PLL_CONFIG[clkPath]));
1777 }
1778
1779
Cy_SysClk_PllLocked(uint32_t clkPath)1780 bool Cy_SysClk_PllLocked(uint32_t clkPath)
1781 {
1782 clkPath--; /* to correctly access PLL config and status registers structures */
1783 CY_ASSERT_L1(clkPath < CY_SRSS_NUM_PLL);
1784 return (_FLD2BOOL(SRSS_CLK_PLL_STATUS_LOCKED, SRSS_CLK_PLL_STATUS[clkPath]));
1785 }
1786
1787
Cy_SysClk_PllLostLock(uint32_t clkPath)1788 bool Cy_SysClk_PllLostLock(uint32_t clkPath)
1789 {
1790 #if ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE)))
1791 (void) clkPath;
1792 return false;
1793
1794 #else
1795 clkPath--; /* to correctly access PLL config and status registers structures */
1796 CY_ASSERT_L1(clkPath < CY_SRSS_NUM_PLL);
1797 bool retVal = _FLD2BOOL(SRSS_CLK_PLL_STATUS_UNLOCK_OCCURRED, SRSS_CLK_PLL_STATUS[clkPath]);
1798 /* write a 1 to clear the unlock occurred bit */
1799 SRSS_CLK_PLL_STATUS[clkPath] = SRSS_CLK_PLL_STATUS_UNLOCK_OCCURRED_Msk;
1800 return (retVal);
1801 #endif /* ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE))) */
1802 }
1803
1804
Cy_SysClk_PllDisable(uint32_t clkPath)1805 cy_en_sysclk_status_t Cy_SysClk_PllDisable(uint32_t clkPath)
1806 {
1807 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
1808 clkPath--; /* to correctly access PLL config and status registers structures */
1809 if (clkPath < CY_SRSS_NUM_PLL)
1810 {
1811 #if defined (CY_DEVICE_SECURE)
1812 retVal = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_PLL_DISABLE, (clkPath + 1U));
1813 #endif /* defined (CY_DEVICE_SECURE) */
1814 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
1815 /* First bypass PLL */
1816 CY_REG32_CLR_SET(SRSS_CLK_PLL_CONFIG[clkPath], SRSS_CLK_PLL_CONFIG_BYPASS_SEL, CY_SYSCLK_FLLPLL_OUTPUT_INPUT);
1817 /* Wait at least 6 PLL clock cycles */
1818 Cy_SysLib_DelayUs(1U);
1819 /* And now disable the PLL itself */
1820 SRSS_CLK_PLL_CONFIG[clkPath] &= ~SRSS_CLK_PLL_CONFIG_ENABLE_Msk;
1821 retVal = CY_SYSCLK_SUCCESS;
1822 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
1823 }
1824 return (retVal);
1825 }
1826
1827
Cy_SysClk_PllConfigure(uint32_t clkPath,const cy_stc_pll_config_t * config)1828 cy_en_sysclk_status_t Cy_SysClk_PllConfigure(uint32_t clkPath, const cy_stc_pll_config_t *config)
1829 {
1830 cy_en_sysclk_status_t retVal = CY_SYSCLK_SUCCESS;
1831
1832 if (((config->inputFreq) < CY_SYSCLK_PLL_MIN_IN_FREQ) || (CY_SYSCLK_PLL_MAX_IN_FREQ < (config->inputFreq)) ||
1833 ((config->outputFreq) < CY_SYSCLK_PLL_MIN_OUT_FREQ) || (CY_SYSCLK_PLL_MAX_OUT_FREQ < (config->outputFreq)))
1834 {
1835 retVal = CY_SYSCLK_BAD_PARAM;
1836 }
1837 else
1838 {
1839 cy_stc_pll_manual_config_t manualConfig = {0U, 0U, 0U, false, CY_SYSCLK_FLLPLL_OUTPUT_AUTO};
1840
1841 /* If output mode is not bypass (input routed directly to output), then
1842 calculate new parameters. */
1843 if (config->outputMode != CY_SYSCLK_FLLPLL_OUTPUT_INPUT)
1844 {
1845 /* for each possible value of OUTPUT_DIV and REFERENCE_DIV (Q), try
1846 to find a value for FEEDBACK_DIV (P) that gives an output frequency
1847 as close as possible to the desired output frequency. */
1848 uint32_t p, q, out;
1849 uint32_t foutBest = 0UL; /* to ensure at least one pass through the for loops below */
1850
1851 /* REFERENCE_DIV (Q) selection */
1852 for (q = CY_SYSCLK_PLL_MIN_REF_DIV; q <= CY_SYSCLK_PLL_MAX_REF_DIV; q++)
1853 {
1854 /* FEEDBACK_DIV (P) selection */
1855 for (p = CY_SYSCLK_PLL_MIN_FB_DIV; p <= CY_SYSCLK_PLL_MAX_FB_DIV; p++)
1856 {
1857 /* Calculate the intermediate Fvco, and make sure that it's in range */
1858 uint32_t fvco = (uint32_t)(((uint64_t)(config->inputFreq) * (uint64_t)p) / (uint64_t)q);
1859 if ((CY_SYSCLK_PLL_MIN_FVCO <= fvco) && (fvco <= CY_SYSCLK_PLL_MAX_FVCO))
1860 {
1861 /* OUTPUT_DIV selection */
1862 for (out = CY_SYSCLK_PLL_MIN_OUTPUT_DIV; out <= CY_SYSCLK_PLL_MAX_OUTPUT_DIV; out++)
1863 {
1864 /* Calculate what output frequency will actually be produced.
1865 If it's closer to the target than what we have so far, then save it. */
1866 uint32_t fout = ((p * config->inputFreq) / q) / out;
1867 if ((uint32_t)abs((int32_t)fout - (int32_t)(config->outputFreq)) <
1868 (uint32_t)abs((int32_t)foutBest - (int32_t)(config->outputFreq)))
1869 {
1870 if (foutBest == (config->outputFreq))
1871 {
1872 break;
1873 }
1874
1875 foutBest = fout;
1876 manualConfig.feedbackDiv = (uint8_t)p;
1877 manualConfig.referenceDiv = (uint8_t)q;
1878 manualConfig.outputDiv = (uint8_t)out;
1879 }
1880 }
1881 }
1882 }
1883 }
1884 /* exit loops if foutBest equals outputFreq */
1885
1886 manualConfig.lfMode = config->lfMode;
1887 } /* if not, bypass output mode */
1888
1889 /* If output mode is bypass (input routed directly to output), then
1890 use old parameters. */
1891 else
1892 {
1893 (void)Cy_SysClk_PllGetConfiguration(clkPath, &manualConfig);
1894 }
1895 /* configure PLL based on calculated values */
1896
1897 manualConfig.outputMode = config->outputMode;
1898 retVal = Cy_SysClk_PllManualConfigure(clkPath, &manualConfig);
1899
1900 } /* if no error */
1901
1902 return (retVal);
1903 }
1904
1905
Cy_SysClk_PllManualConfigure(uint32_t clkPath,const cy_stc_pll_manual_config_t * config)1906 cy_en_sysclk_status_t Cy_SysClk_PllManualConfigure(uint32_t clkPath, const cy_stc_pll_manual_config_t *config)
1907 {
1908 cy_en_sysclk_status_t retVal = CY_SYSCLK_SUCCESS;
1909
1910 /* check for errors */
1911 if (clkPath > CY_SRSS_NUM_PLL) /* invalid clock path number */
1912 {
1913 retVal = CY_SYSCLK_BAD_PARAM;
1914 }
1915 else if (Cy_SysClk_PllIsEnabled(clkPath))
1916 {
1917 retVal = CY_SYSCLK_INVALID_STATE;
1918 }
1919 /* valid divider bitfield values */
1920 else if ((config->outputDiv < CY_SYSCLK_PLL_MIN_OUTPUT_DIV) || (CY_SYSCLK_PLL_MAX_OUTPUT_DIV < config->outputDiv) ||
1921 (config->referenceDiv < CY_SYSCLK_PLL_MIN_REF_DIV) || (CY_SYSCLK_PLL_MAX_REF_DIV < config->referenceDiv) ||
1922 (config->feedbackDiv < CY_SYSCLK_PLL_MIN_FB_DIV) || (CY_SYSCLK_PLL_MAX_FB_DIV < config->feedbackDiv))
1923 {
1924 retVal = CY_SYSCLK_BAD_PARAM;
1925 }
1926 else /* no errors */
1927 {
1928 #if defined (CY_DEVICE_SECURE)
1929 cy_stc_pra_clk_pll_manconfigure_t pll_config;
1930 pll_config.clkPath = clkPath;
1931 pll_config.praConfig = (cy_stc_pll_manual_config_t *)config;
1932 retVal = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_PLL_MANCONFIG, &pll_config);
1933 #endif /* defined (CY_DEVICE_SECURE) */
1934 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
1935 clkPath--; /* to correctly access PLL config registers structure */
1936 /* If output mode is bypass (input routed directly to output), then done.
1937 The output frequency equals the input frequency regardless of the frequency parameters. */
1938 if (config->outputMode != CY_SYSCLK_FLLPLL_OUTPUT_INPUT)
1939 {
1940 SRSS_CLK_PLL_CONFIG[clkPath] =
1941 _VAL2FLD(SRSS_CLK_PLL_CONFIG_FEEDBACK_DIV, config->feedbackDiv) |
1942 _VAL2FLD(SRSS_CLK_PLL_CONFIG_REFERENCE_DIV, config->referenceDiv) |
1943 _VAL2FLD(SRSS_CLK_PLL_CONFIG_OUTPUT_DIV, config->outputDiv) |
1944 _VAL2FLD(SRSS_CLK_PLL_CONFIG_PLL_LF_MODE, config->lfMode);
1945 }
1946
1947 CY_REG32_CLR_SET(SRSS_CLK_PLL_CONFIG[clkPath], SRSS_CLK_PLL_CONFIG_BYPASS_SEL, (uint32_t)config->outputMode);
1948 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
1949 }
1950
1951 return (retVal);
1952 }
1953
1954
Cy_SysClk_PllGetConfiguration(uint32_t clkPath,cy_stc_pll_manual_config_t * config)1955 cy_en_sysclk_status_t Cy_SysClk_PllGetConfiguration(uint32_t clkPath, cy_stc_pll_manual_config_t *config)
1956 {
1957 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
1958 clkPath--; /* to correctly access PLL config and status register structures */
1959 if (clkPath < CY_SRSS_NUM_PLL)
1960 {
1961 uint32_t tempReg = SRSS_CLK_PLL_CONFIG[clkPath];
1962 config->feedbackDiv = (uint8_t)_FLD2VAL(SRSS_CLK_PLL_CONFIG_FEEDBACK_DIV, tempReg);
1963 config->referenceDiv = (uint8_t)_FLD2VAL(SRSS_CLK_PLL_CONFIG_REFERENCE_DIV, tempReg);
1964 config->outputDiv = (uint8_t)_FLD2VAL(SRSS_CLK_PLL_CONFIG_OUTPUT_DIV, tempReg);
1965 config->lfMode = _FLD2BOOL(SRSS_CLK_PLL_CONFIG_PLL_LF_MODE, tempReg);
1966 config->outputMode = (cy_en_fll_pll_output_mode_t)((uint32_t)_FLD2VAL(SRSS_CLK_PLL_CONFIG_BYPASS_SEL, tempReg));
1967 retVal = CY_SYSCLK_SUCCESS;
1968 }
1969 return (retVal);
1970 }
1971
1972
Cy_SysClk_PllEnable(uint32_t clkPath,uint32_t timeoutus)1973 cy_en_sysclk_status_t Cy_SysClk_PllEnable(uint32_t clkPath, uint32_t timeoutus)
1974 {
1975 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
1976 bool zeroTimeout = (timeoutus == 0UL);
1977 clkPath--; /* to correctly access PLL config and status registers structures */
1978 if (clkPath < CY_SRSS_NUM_PLL)
1979 {
1980 #if defined (CY_DEVICE_SECURE)
1981 (void)timeoutus;
1982 (void)zeroTimeout;
1983 retVal = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_FUNC_POLICY, CY_PRA_CLK_FUNC_PLL_ENABLE, (clkPath + 1U));
1984 #endif /* defined (CY_DEVICE_SECURE) */
1985 #if ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE)))
1986 /* first set the PLL enable bit */
1987 SRSS_CLK_PLL_CONFIG[clkPath] |= SRSS_CLK_PLL_CONFIG_ENABLE_Msk;
1988
1989 /* now do the timeout wait for PLL_STATUS, bit LOCKED */
1990 for (; (0UL == (SRSS_CLK_PLL_STATUS_LOCKED_Msk & SRSS_CLK_PLL_STATUS[clkPath])) &&
1991 (0UL != timeoutus);
1992 timeoutus--)
1993 {
1994 Cy_SysLib_DelayUs(1U);
1995 }
1996
1997 if (zeroTimeout || (0UL != timeoutus))
1998 {
1999 /* Unbypass PLL, if it is not in AUTO mode */
2000 if ((uint32_t)CY_SYSCLK_FLLPLL_OUTPUT_INPUT == (uint32_t)_FLD2VAL(SRSS_CLK_PLL_CONFIG_BYPASS_SEL, SRSS_CLK_PLL_CONFIG[clkPath]))
2001 {
2002 CY_REG32_CLR_SET(SRSS_CLK_PLL_CONFIG[clkPath], SRSS_CLK_PLL_CONFIG_BYPASS_SEL, CY_SYSCLK_FLLPLL_OUTPUT_OUTPUT);
2003 }
2004
2005 retVal = CY_SYSCLK_SUCCESS;
2006 }
2007 else
2008 {
2009 /* If lock doesn't occur, then bypass PLL */
2010 CY_REG32_CLR_SET(SRSS_CLK_PLL_CONFIG[clkPath], SRSS_CLK_PLL_CONFIG_BYPASS_SEL, CY_SYSCLK_FLLPLL_OUTPUT_INPUT);
2011 /* Wait at least 6 PLL clock cycles */
2012 Cy_SysLib_DelayUs(1U);
2013 /* And now disable the PLL itself */
2014 SRSS_CLK_PLL_CONFIG[clkPath] &= ~SRSS_CLK_PLL_CONFIG_ENABLE_Msk;
2015 retVal = CY_SYSCLK_TIMEOUT;
2016 }
2017 #endif /* ((CY_CPU_CORTEX_M0P) || (!defined(CY_DEVICE_SECURE))) */
2018 }
2019 return (retVal);
2020 }
2021
2022
2023 /* ========================================================================== */
2024 /* ==================== Clock Measurement section ===================== */
2025 /* ========================================================================== */
2026 /* Slow control register default value */
2027 #define TST_DDFT_SLOW_CTL_DEFAULT_VAL (0x00001F1FUL)
2028
2029 /* Fast control register */
2030 #define TST_DDFT_FAST_CTL_REG (*(volatile uint32_t *) 0x40260104U)
2031
2032 /* Slow control register default value */
2033 #define TST_DDFT_FAST_CTL_DEFAULT_VAL (0x00003D3DUL)
2034
2035 /* Define for select signal outputs in slow clock */
2036 #define SRSS_CLK_OUTPUT_SLOW_MASK ((uint32_t) SRSS_CLK_OUTPUT_SLOW_SLOW_SEL0_Msk | \
2037 SRSS_CLK_OUTPUT_SLOW_SLOW_SEL1_Msk)
2038
2039 /* Define for select signal outputs in fast clock */
2040 #define SRSS_CLK_OUTPUT_FAST_MASK ((uint32_t) SRSS_CLK_OUTPUT_FAST_FAST_SEL0_Msk | \
2041 SRSS_CLK_OUTPUT_FAST_FAST_SEL1_Msk | \
2042 SRSS_CLK_OUTPUT_FAST_PATH_SEL0_Msk | \
2043 SRSS_CLK_OUTPUT_FAST_PATH_SEL1_Msk | \
2044 SRSS_CLK_OUTPUT_FAST_HFCLK_SEL0_Msk | \
2045 SRSS_CLK_OUTPUT_FAST_HFCLK_SEL1_Msk)
2046
2047 /* Cy_SysClk_StartClkMeasurementCounters() input parameter saved for use later in other functions */
2048 static uint32_t clk1Count1;
2049
2050 /* These variables act as locks to prevent collisions between clock measurement and entry into
2051 Deep Sleep mode. See Cy_SysClk_DeepSleep(). */
2052 static bool clkCounting = false;
2053 static bool preventCounting = false;
2054
2055
Cy_SysClk_ClkMeasurementCountersGetFreq(bool measuredClock,uint32_t refClkFreq)2056 uint32_t Cy_SysClk_ClkMeasurementCountersGetFreq(bool measuredClock, uint32_t refClkFreq)
2057 {
2058 uint32_t retVal = 0UL;
2059 bool isMeasurementValid = false;
2060
2061 /* Done counting; allow entry into Deep Sleep mode */
2062 clkCounting = false;
2063
2064 /* Acquire the IPC to prevent changing of the shared resources at the same time */
2065 while(0U == (IPC_STRUCT_ACQUIRE_SUCCESS_Msk & REG_IPC_STRUCT_ACQUIRE(CY_IPC_STRUCT_PTR(CY_IPC_CHAN_DDFT))))
2066 {
2067 /* Wait until the IPC structure is released by another process */
2068 }
2069
2070 /* Check whether the device was in the Deep Sleep mode or the flash partially blocked while the
2071 * operation was done
2072 */
2073 if(SRSS_TST_DDFT_SLOW_CTL_REG == TST_DDFT_SLOW_CTL_DEFAULT_VAL)
2074 {
2075 if(SRSS_TST_DDFT_FAST_CTL_REG == TST_DDFT_FAST_CTL_DEFAULT_VAL)
2076 {
2077 isMeasurementValid = true;
2078 }
2079 }
2080
2081 retVal = _FLD2VAL(SRSS_CLK_CAL_CNT2_CAL_COUNTER2, SRSS_CLK_CAL_CNT2);
2082 /* Release the IPC */
2083 REG_IPC_STRUCT_RELEASE(CY_IPC_STRUCT_PTR(CY_IPC_CHAN_DDFT)) = 0U;
2084
2085 if (isMeasurementValid && (0UL != retVal))
2086 {
2087 if (!measuredClock)
2088 { /* clock1 is the measured clock */
2089 retVal = (uint32_t)CY_SYSLIB_DIV_ROUND((uint64_t)clk1Count1 * (uint64_t)refClkFreq, (uint64_t)retVal);
2090 }
2091 else
2092 { /* clock2 is the measured clock */
2093 retVal = (uint32_t)CY_SYSLIB_DIV_ROUND((uint64_t)retVal * (uint64_t)refClkFreq, (uint64_t)clk1Count1);
2094 }
2095 }
2096 else
2097 {
2098 /* Return zero value to indicate invalid measurement */
2099 retVal = 0UL;
2100 }
2101
2102 return (retVal);
2103 }
2104
2105
Cy_SysClk_ClkMeasurementCountersDone(void)2106 bool Cy_SysClk_ClkMeasurementCountersDone(void)
2107 {
2108 return (_FLD2BOOL(SRSS_CLK_CAL_CNT1_CAL_COUNTER_DONE, SRSS_CLK_CAL_CNT1));
2109 }
2110
2111
Cy_SysClk_StartClkMeasurementCounters(cy_en_meas_clks_t clock1,uint32_t count1,cy_en_meas_clks_t clock2)2112 cy_en_sysclk_status_t Cy_SysClk_StartClkMeasurementCounters(cy_en_meas_clks_t clock1, uint32_t count1, cy_en_meas_clks_t clock2)
2113 {
2114 cy_en_sysclk_status_t retVal = CY_SYSCLK_BAD_PARAM;
2115
2116 #if ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE)))
2117
2118 cy_stc_pra_start_clk_measurement_t clkMeasurement;
2119 clkMeasurement.clock1 = clock1;
2120 clkMeasurement.count1 = count1;
2121 clkMeasurement.clock2 = clock2;
2122
2123 /* Don't start a measurement if about to enter Deep Sleep mode */
2124 if (!preventCounting)
2125 {
2126 retVal = (cy_en_sysclk_status_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_SECURE_ONLY, CY_PRA_CLK_FUNC_START_MEASUREMENT, &clkMeasurement);
2127 }
2128
2129 if (CY_SYSCLK_SUCCESS == retVal)
2130 {
2131 /* Disallow entry into Deep Sleep mode while counting */
2132 clkCounting = true;
2133
2134 /* Save this input parameter for use later, in other functions */
2135 clk1Count1 = count1;
2136 }
2137 #else
2138
2139 uint32_t clkOutputSlowVal = 0UL;
2140 uint32_t clkOutputFastVal = 0UL;
2141
2142 uint32_t clkOutputSlowMask = 0UL;
2143 uint32_t clkOutputFastMask = 0UL;
2144
2145 /* Prepare values for measurement control registers */
2146
2147 /* Connect the indicated clocks to the respective counters:
2148
2149 if clock1 is a slow clock,
2150 select it in SRSS_CLK_OUTPUT_SLOW.SLOW_SEL0, and SRSS_CLK_OUTPUT_FAST.FAST_SEL0 = SLOW_SEL0
2151 else if clock1 is a fast clock,
2152 select it in SRSS_CLK_OUTPUT_FAST.FAST_SEL0,
2153 else error, do nothing and return.
2154
2155 if clock2 is a slow clock,
2156 select it in SRSS_CLK_OUTPUT_SLOW.SLOW_SEL1, and SRSS_CLK_OUTPUT_FAST.FAST_SEL1 = SLOW_SEL1
2157 else if clock2 is a fast clock,
2158 select it in SRSS_CLK_OUTPUT_FAST.FAST_SEL1,
2159 else error, do nothing and return.
2160 */
2161 if ((clock1 < CY_SYSCLK_MEAS_CLK_LAST_CLK) && (clock2 < CY_SYSCLK_MEAS_CLK_LAST_CLK) &&
2162 (count1 <= (SRSS_CLK_CAL_CNT1_CAL_COUNTER1_Msk >> SRSS_CLK_CAL_CNT1_CAL_COUNTER1_Pos)))
2163 {
2164 /* Disallow entry into Deep Sleep mode while counting */
2165 clkCounting = true;
2166
2167 if (clock1 < CY_SYSCLK_MEAS_CLK_FAST_CLKS)
2168 { /* slow clock */
2169 clkOutputSlowVal |= _VAL2FLD(SRSS_CLK_OUTPUT_SLOW_SLOW_SEL0, (uint32_t)clock1);
2170 clkOutputFastVal |= _VAL2FLD(SRSS_CLK_OUTPUT_FAST_FAST_SEL0, 7UL/*slow_sel0 output*/);
2171
2172 clkOutputSlowMask |= SRSS_CLK_OUTPUT_SLOW_SLOW_SEL0_Msk;
2173 clkOutputFastMask |= SRSS_CLK_OUTPUT_FAST_FAST_SEL0_Msk;
2174 }
2175 else
2176 { /* fast clock */
2177 if (clock1 < CY_SYSCLK_MEAS_CLK_PATH_CLKS)
2178 { /* ECO, EXT, ALTHF */
2179 clkOutputFastVal |= _VAL2FLD(SRSS_CLK_OUTPUT_FAST_FAST_SEL0, (uint32_t)clock1);
2180 clkOutputFastMask |= SRSS_CLK_OUTPUT_FAST_FAST_SEL0_Msk;
2181 }
2182 else
2183 { /* PATH or CLKHF */
2184 clkOutputFastVal |= _VAL2FLD(SRSS_CLK_OUTPUT_FAST_FAST_SEL0, (((uint32_t)clock1 >> 8) & 0xFUL) /*use enum bits [11:8]*/);
2185 clkOutputFastMask |= SRSS_CLK_OUTPUT_FAST_FAST_SEL0_Msk;
2186
2187 if (clock1 < CY_SYSCLK_MEAS_CLK_CLKHFS)
2188 { /* PATH select */
2189 clkOutputFastVal |= _VAL2FLD(SRSS_CLK_OUTPUT_FAST_PATH_SEL0, ((uint32_t)clock1 & 0xFUL) /*use enum bits [3:0]*/);
2190 clkOutputFastMask |= SRSS_CLK_OUTPUT_FAST_PATH_SEL0_Msk;
2191 }
2192 else
2193 { /* CLKHF select */
2194 clkOutputFastVal |= _VAL2FLD(SRSS_CLK_OUTPUT_FAST_HFCLK_SEL0, ((uint32_t)clock1 & 0xFUL) /*use enum bits [3:0]*/);
2195 clkOutputFastMask |= SRSS_CLK_OUTPUT_FAST_HFCLK_SEL0_Msk;
2196 }
2197 }
2198 } /* clock1 fast clock */
2199
2200 if (clock2 < CY_SYSCLK_MEAS_CLK_FAST_CLKS)
2201 { /* slow clock */
2202 clkOutputSlowVal |= _VAL2FLD(SRSS_CLK_OUTPUT_SLOW_SLOW_SEL1, (uint32_t)clock2);
2203 clkOutputFastVal |= _VAL2FLD(SRSS_CLK_OUTPUT_FAST_FAST_SEL1, 7UL/*slow_sel1 output*/);
2204
2205 clkOutputSlowMask |= SRSS_CLK_OUTPUT_SLOW_SLOW_SEL1_Msk;
2206 clkOutputFastMask |= SRSS_CLK_OUTPUT_FAST_FAST_SEL1_Msk;
2207 }
2208 else
2209 { /* fast clock */
2210 if (clock2 < CY_SYSCLK_MEAS_CLK_PATH_CLKS)
2211 { /* ECO, EXT, ALTHF */
2212 clkOutputFastVal |= _VAL2FLD(SRSS_CLK_OUTPUT_FAST_FAST_SEL1, (uint32_t)clock2);
2213 clkOutputFastMask |= SRSS_CLK_OUTPUT_FAST_FAST_SEL1_Msk;
2214 }
2215 else
2216 { /* PATH or CLKHF */
2217 clkOutputFastVal |= _VAL2FLD(SRSS_CLK_OUTPUT_FAST_FAST_SEL1, (((uint32_t)clock2 >> 8) & 0xFUL) /*use enum bits [11:8]*/);
2218 clkOutputFastMask |= SRSS_CLK_OUTPUT_FAST_FAST_SEL1_Msk;
2219
2220 if (clock2 < CY_SYSCLK_MEAS_CLK_CLKHFS)
2221 { /* PATH select */
2222 clkOutputFastVal |= _VAL2FLD(SRSS_CLK_OUTPUT_FAST_PATH_SEL1, ((uint32_t)clock2 & 0xFUL) /*use enum bits [3:0]*/);
2223 clkOutputFastMask |= SRSS_CLK_OUTPUT_FAST_PATH_SEL1_Msk;
2224 }
2225 else
2226 { /* CLKHF select */
2227 clkOutputFastVal |= _VAL2FLD(SRSS_CLK_OUTPUT_FAST_HFCLK_SEL1, ((uint32_t)clock2 & 0xFUL) /*use enum bits [3:0]*/);
2228 clkOutputFastMask |= SRSS_CLK_OUTPUT_FAST_HFCLK_SEL1_Msk;
2229 }
2230 }
2231 } /* clock2 fast clock */
2232
2233 /* Acquire the IPC to prevent changing of the shared resources at the same time */
2234 while(0U == (IPC_STRUCT_ACQUIRE_SUCCESS_Msk & REG_IPC_STRUCT_ACQUIRE(CY_IPC_STRUCT_PTR(CY_IPC_CHAN_DDFT))))
2235 {
2236 /* Wait until the IPC structure is released by another process */
2237 }
2238
2239 if ((!preventCounting) /* don't start a measurement if about to enter Deep Sleep mode */ ||
2240 (_FLD2VAL(SRSS_CLK_CAL_CNT1_CAL_COUNTER_DONE, SRSS_CLK_CAL_CNT1) != 0UL/*1 = done*/))
2241 {
2242 /* Set default values for counters measurement control registers */
2243 SRSS_TST_DDFT_SLOW_CTL_REG = TST_DDFT_SLOW_CTL_DEFAULT_VAL;
2244 SRSS_TST_DDFT_FAST_CTL_REG = TST_DDFT_FAST_CTL_DEFAULT_VAL;
2245
2246 SRSS_CLK_OUTPUT_SLOW = ((SRSS_CLK_OUTPUT_SLOW & ((uint32_t) ~clkOutputSlowMask)) | clkOutputSlowVal);
2247 SRSS_CLK_OUTPUT_FAST = ((SRSS_CLK_OUTPUT_FAST & ((uint32_t) ~clkOutputFastMask)) | clkOutputFastVal);
2248
2249 /* Save this input parameter for use later, in other functions.
2250 No error checking is done on this parameter */
2251 clk1Count1 = count1;
2252
2253 /* Counting starts when counter1 is written with a nonzero value */
2254 SRSS_CLK_CAL_CNT1 = clk1Count1;
2255
2256 retVal = CY_SYSCLK_SUCCESS;
2257 }
2258
2259 /* Release the IPC */
2260 REG_IPC_STRUCT_RELEASE(CY_IPC_STRUCT_PTR(CY_IPC_CHAN_DDFT)) = 0U;
2261 }
2262
2263 #endif /* ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE))) */
2264
2265 return (retVal);
2266 }
2267
2268 /* ========================================================================== */
2269 /* ========================== TRIM SECTION ============================ */
2270 /* ========================================================================== */
2271
2272
2273 /** \cond INTERNAL */
2274 #define CY_SYSCLK_ILO_TARGET_FREQ (32768UL)
2275 /* Nominal trim step size is 1.5% of "the frequency". Using the target frequency */
2276 #define CY_SYSCLK_ILO_TRIM_STEP (CY_SYSLIB_DIV_ROUND(CY_SYSCLK_ILO_TARGET_FREQ * 15UL, 1000UL))
2277
2278 /* The step size to be used by Cy_SysClk_PiloTrim function */
2279 static uint32_t stepSize = CY_SYSCLK_PILO_TRIM_STEP;
2280 /** \endcond */
2281
Cy_SysClk_IloTrim(uint32_t iloFreq)2282 int32_t Cy_SysClk_IloTrim(uint32_t iloFreq)
2283 {
2284 int32_t changeInTrim;
2285 #if ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE)))
2286 (void) iloFreq;
2287 changeInTrim = (int32_t)CY_PRA_FUNCTION_CALL_RETURN_PARAM(CY_PRA_MSG_TYPE_SECURE_ONLY, CY_PRA_CLK_FUNC_ILO_TRIM, iloFreq);
2288 #else
2289 uint32_t diff;
2290 bool sign = false;
2291
2292 if(iloFreq > (CY_SYSCLK_ILO_TARGET_FREQ + CY_SYSCLK_ILO_TRIM_STEP))
2293 {
2294 diff = iloFreq - CY_SYSCLK_ILO_TARGET_FREQ;
2295 }
2296 else if (iloFreq < (CY_SYSCLK_ILO_TARGET_FREQ - CY_SYSCLK_ILO_TRIM_STEP))
2297 {
2298 diff = CY_SYSCLK_ILO_TARGET_FREQ - iloFreq;
2299 sign = true;
2300 }
2301 else
2302 {
2303 diff = 0UL;
2304 }
2305
2306 /* Do nothing if iloFreq is already within one trim step from the target */
2307 if(0UL != diff)
2308 {
2309 /* Get current trim value */
2310 uint32_t trim = _FLD2VAL(SRSS_CLK_TRIM_ILO_CTL_ILO_FTRIM, SRSS_CLK_TRIM_ILO_CTL);
2311
2312 diff = CY_SYSLIB_DIV_ROUND(diff, CY_SYSCLK_ILO_TRIM_STEP);
2313
2314 if(sign)
2315 {
2316 trim += diff;
2317 }
2318 else
2319 {
2320 trim -= diff;
2321 }
2322
2323 /* Update the trim value */
2324 CY_REG32_CLR_SET(SRSS_CLK_TRIM_ILO_CTL, SRSS_CLK_TRIM_ILO_CTL_ILO_FTRIM, trim);
2325 }
2326
2327 changeInTrim = (sign ? (int32_t)diff : (0L - (int32_t)diff));
2328 #endif /* ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE))) */
2329
2330 return changeInTrim;
2331 }
2332
2333
2334 /** \cond INTERNAL */
2335 #define CY_SYSCLK_PILO_TARGET_FREQ (32768UL)
2336 /* nominal trim step size */
2337 #define CY_SYSCLK_PILO_TRIM_STEP (5UL)
2338 /** \endcond */
2339
Cy_SysClk_PiloTrim(uint32_t piloFreq)2340 int32_t Cy_SysClk_PiloTrim(uint32_t piloFreq)
2341 {
2342 int32_t changeInTrim;
2343 uint32_t diff;
2344 bool sign = false;
2345
2346 if(piloFreq > (CY_SYSCLK_PILO_TARGET_FREQ + stepSize))
2347 {
2348 diff = piloFreq - CY_SYSCLK_PILO_TARGET_FREQ;
2349 }
2350 else if (piloFreq < (CY_SYSCLK_PILO_TARGET_FREQ - stepSize))
2351 {
2352 diff = CY_SYSCLK_PILO_TARGET_FREQ - piloFreq;
2353 sign = true;
2354 }
2355 else
2356 {
2357 diff = 0UL;
2358 }
2359
2360 /* Do nothing if piloFreq is already within one trim step from the target */
2361 if(0UL != diff)
2362 {
2363 /* Get current trim value */
2364 uint32_t trim = Cy_SysClk_PiloGetTrim();
2365
2366 diff = CY_SYSLIB_DIV_ROUND(diff, stepSize);
2367
2368 if(sign)
2369 {/* piloFreq too low. Increase the trim value */
2370 trim += diff;
2371 if (trim >= SRSS_CLK_PILO_CONFIG_PILO_FFREQ_Msk) /* limit overflow */
2372 {
2373 trim = SRSS_CLK_PILO_CONFIG_PILO_FFREQ_Msk;
2374 }
2375 }
2376 else
2377 {/* piloFreq too high. Decrease the trim value */
2378 trim -= diff;
2379 if ((int32_t)trim < 0) /* limit underflow */
2380 {
2381 trim = 0UL;
2382 }
2383 }
2384
2385 /* Update the trim value */
2386 Cy_SysClk_PiloSetTrim(trim);
2387 }
2388
2389 changeInTrim = ((int32_t)(sign ? (int32_t)diff : (0L - (int32_t)diff)));
2390 return changeInTrim;
2391 }
2392 /** \cond INTERNAL */
2393 #define LF_COUNT (64u)
2394 #define REF_COUNT (212u)
2395 #define FREQ_REF (31250u)
2396 #define TRIM_DELAY (2000u)
2397 #define STEP_SIZE_ITER (8u)
2398 /** \endcond */
2399
2400
2401
Cy_SysClk_PiloInitialTrim(void)2402 void Cy_SysClk_PiloInitialTrim(void)
2403 {
2404 #if ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE)))
2405 CY_PRA_FUNCTION_CALL_VOID_VOID(CY_PRA_MSG_TYPE_SECURE_ONLY, CY_PRA_CLK_FUNC_PILO_INITIAL_TRIM);
2406 #else
2407 uint32_t measuredCnt = 0xFFFFFFFFUL;
2408 uint32_t trimVal = 0UL;
2409 int32_t bitPos = 9;
2410
2411 do
2412 {
2413 SRSS_CLK_PILO_CONFIG &= ~(SRSS_CLK_PILO_CONFIG_PILO_FFREQ_Msk);
2414
2415 /* Set 1 at BitPos in FTRIM*/
2416 SRSS_CLK_PILO_CONFIG |= (trimVal | ((uint32_t) 1U << (uint32_t) bitPos));
2417
2418 /* Wait for 2 ms after setting FTRIM */
2419 Cy_SysLib_DelayUs(TRIM_DELAY);
2420 /* Start frequency measurement of PILO for
2421 * 64 PILO clock counts with BLE ECO ALTHF(configured to 16MHz) as reference clock */
2422 (void) Cy_SysClk_StartClkMeasurementCounters(CY_SYSCLK_MEAS_CLK_PILO, LF_COUNT, CY_SYSCLK_MEAS_CLK_ALTHF);
2423 while ( true != Cy_SysClk_ClkMeasurementCountersDone() )
2424 {
2425 /* Wait for the measurement to complete */
2426 }
2427 /* Read the number of reference clock cycles for 64 PILO clock cycles */
2428 measuredCnt = (uint32_t)_FLD2VAL(SRSS_CLK_CAL_CNT2_CAL_COUNTER2, SRSS_CLK_CAL_CNT2);
2429 /* If the measured clock cycles are greater than expected 31250 cycles, retain the bitPos as 1 in FTRIM */
2430 if (measuredCnt > FREQ_REF)
2431 {
2432 trimVal |= ((uint32_t) 1U << (uint32_t) bitPos);
2433 }
2434 /* Repeat until this is done for all 10 bits of FTRIM */
2435 bitPos--;
2436
2437 } while (bitPos >= 0);
2438 SRSS_CLK_PILO_CONFIG &= ~(SRSS_CLK_PILO_CONFIG_PILO_FFREQ_Msk);
2439 SRSS_CLK_PILO_CONFIG |= (trimVal);
2440 #endif
2441 }
2442
2443
Cy_SysClk_PiloUpdateTrimStep(void)2444 void Cy_SysClk_PiloUpdateTrimStep(void)
2445 {
2446 #if ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE)))
2447 (void)stepSize;
2448 CY_PRA_FUNCTION_CALL_VOID_VOID(CY_PRA_MSG_TYPE_SECURE_ONLY, CY_PRA_CLK_FUNC_UPDATE_PILO_TRIM_STEP);
2449 #else
2450 uint32_t iteration = 0u;
2451 uint32_t fTrim = 0u;
2452 uint32_t newFreq = 0u;
2453 uint32_t oldFreq = 0u;
2454 uint32_t initialFtrim = _FLD2VAL(SRSS_CLK_PILO_CONFIG_PILO_FFREQ, SRSS_CLK_PILO_CONFIG);
2455 uint32_t refClkFreq = Cy_SysClk_AltHfGetFrequency();
2456
2457 stepSize = 8U;
2458
2459 (void) Cy_SysClk_StartClkMeasurementCounters(CY_SYSCLK_MEAS_CLK_PILO, REF_COUNT, CY_SYSCLK_MEAS_CLK_ALTHF);
2460 while ( true != Cy_SysClk_ClkMeasurementCountersDone() )
2461 {
2462 /* Wait for the measurement to complete */
2463 }
2464
2465 oldFreq = Cy_SysClk_ClkMeasurementCountersGetFreq(false, refClkFreq);
2466 do
2467 {
2468 fTrim = _FLD2VAL(SRSS_CLK_PILO_CONFIG_PILO_FFREQ, SRSS_CLK_PILO_CONFIG);
2469 /* Update the fine trim value */
2470 CY_REG32_CLR_SET(SRSS_CLK_PILO_CONFIG, SRSS_CLK_PILO_CONFIG_PILO_FFREQ, fTrim + 1u);
2471 /* Wait for 2 ms after setting FTRIM */
2472 Cy_SysLib_DelayUs(TRIM_DELAY);
2473 (void) Cy_SysClk_StartClkMeasurementCounters(CY_SYSCLK_MEAS_CLK_PILO, REF_COUNT, CY_SYSCLK_MEAS_CLK_ALTHF);
2474 while ( true != Cy_SysClk_ClkMeasurementCountersDone() )
2475 {
2476 /* Wait for the measurement to complete */
2477 }
2478 newFreq = Cy_SysClk_ClkMeasurementCountersGetFreq(false, refClkFreq);
2479 stepSize += (newFreq - oldFreq);
2480 oldFreq = newFreq;
2481 iteration++;
2482
2483 } while (iteration < STEP_SIZE_ITER);
2484 stepSize = (stepSize/STEP_SIZE_ITER);
2485 /* Restore the fine trim value */
2486 CY_REG32_CLR_SET(SRSS_CLK_PILO_CONFIG, SRSS_CLK_PILO_CONFIG_PILO_FFREQ, initialFtrim);
2487 /* Wait for 2 ms after setting FTRIM */
2488 Cy_SysLib_DelayUs(TRIM_DELAY);
2489 #endif
2490 }
2491
2492
2493 /* ========================================================================== */
2494 /* ====================== POWER MANAGEMENT SECTION ==================== */
2495 /* ========================================================================== */
2496
2497
2498 /** \cond INTERNAL */
2499 /* Timeout count for use in function Cy_SysClk_DeepSleepCallback() is sufficiently large for ~1 second */
2500 #define TIMEOUT (1000000UL)
2501 /** \endcond */
2502
Cy_SysClk_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)2503 cy_en_syspm_status_t Cy_SysClk_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams, cy_en_syspm_callback_mode_t mode)
2504 {
2505
2506 /* Bitmapped paths with enabled FLL/PLL sourced by ECO */
2507 static uint16_t changedSourcePaths;
2508 static uint16_t pllAutoModes;
2509
2510 cy_en_syspm_status_t retVal = CY_SYSPM_FAIL;
2511
2512 (void)callbackParams; /* Suppress "not used" warning */
2513 (void)changedSourcePaths;
2514 (void)pllAutoModes;
2515
2516 switch (mode)
2517 {
2518 case CY_SYSPM_CHECK_READY:
2519 /* Don't allow entry into Deep Sleep mode if currently measuring a frequency */
2520 if (!clkCounting)
2521 {
2522 /* Indicating that we can go into Deep Sleep.
2523 * Prevent starting a new clock measurement until
2524 * after we've come back from Deep Sleep.
2525 */
2526 preventCounting = true;
2527 retVal = CY_SYSPM_SUCCESS;
2528 }
2529 break;
2530
2531 case CY_SYSPM_CHECK_FAIL:
2532 /* Cancellation of going into Deep Sleep, therefore allow a new clock measurement */
2533 preventCounting = false;
2534 retVal = CY_SYSPM_SUCCESS;
2535 break;
2536
2537 case CY_SYSPM_BEFORE_TRANSITION:
2538 {
2539 #if ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE)))
2540 retVal = (cy_en_syspm_status_t)CY_PRA_FUNCTION_CALL_RETURN_VOID(CY_PRA_MSG_TYPE_SECURE_ONLY, CY_PRA_CLK_FUNC_DS_BEFORE_TRANSITION);
2541 #else
2542 uint32_t fllpll; /* 0 = FLL, all other values = a PLL */
2543
2544 /* Initialize the storage of changed paths */
2545 changedSourcePaths = 0U;
2546 pllAutoModes = 0U;
2547
2548 /* For FLL and each PLL */
2549 for (fllpll = 0UL; fllpll <= CY_SRSS_NUM_PLL; fllpll++)
2550 {
2551 /* If FLL or PLL is enabled */
2552 if ((0UL == fllpll) ? Cy_SysClk_FllIsEnabled() : Cy_SysClk_PllIsEnabled(fllpll))
2553 {
2554 /* And the FLL/PLL has ECO as a source */
2555 if (Cy_SysClk_ClkPathGetSource(fllpll) == CY_SYSCLK_CLKPATH_IN_ECO)
2556 {
2557 /* Bypass the FLL/PLL */
2558 if (0UL == fllpll)
2559 {
2560 CY_REG32_CLR_SET(SRSS_CLK_FLL_CONFIG3, SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, CY_SYSCLK_FLLPLL_OUTPUT_INPUT);
2561 }
2562 else
2563 {
2564 if (((uint32_t)CY_SYSCLK_FLLPLL_OUTPUT_AUTO == _FLD2VAL(SRSS_CLK_PLL_CONFIG_BYPASS_SEL, SRSS_CLK_PLL_CONFIG[fllpll - 1UL])) ||
2565 ((uint32_t)CY_SYSCLK_FLLPLL_OUTPUT_AUTO1 == _FLD2VAL(SRSS_CLK_PLL_CONFIG_BYPASS_SEL, SRSS_CLK_PLL_CONFIG[fllpll - 1UL])))
2566 {
2567 pllAutoModes |= (uint16_t)(1UL << fllpll);
2568 }
2569
2570 CY_REG32_CLR_SET(SRSS_CLK_PLL_CONFIG[fllpll - 1UL], SRSS_CLK_PLL_CONFIG_BYPASS_SEL, CY_SYSCLK_FLLPLL_OUTPUT_INPUT);
2571 }
2572
2573 /* Change this path source to IMO */
2574 (void)Cy_SysClk_ClkPathSetSource(fllpll, CY_SYSCLK_CLKPATH_IN_IMO);
2575
2576 /* Store a record that this path source was changed from ECO */
2577 changedSourcePaths |= (uint16_t)(1UL << fllpll);
2578 }
2579 else if (0UL == fllpll)
2580 {
2581 CY_REG32_CLR_SET(SRSS_CLK_FLL_CONFIG3, SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, CY_SYSCLK_FLLPLL_OUTPUT_INPUT);
2582 }
2583 else
2584 {
2585 /* Do nothing */
2586 }
2587 }
2588 }
2589
2590 retVal = CY_SYSPM_SUCCESS;
2591 #endif /* ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE))) */
2592 }
2593 break;
2594
2595 case CY_SYSPM_AFTER_TRANSITION:
2596 {
2597 #if ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE)))
2598 retVal = (cy_en_syspm_status_t)CY_PRA_FUNCTION_CALL_RETURN_VOID(CY_PRA_MSG_TYPE_SECURE_ONLY, CY_PRA_CLK_FUNC_DS_AFTER_TRANSITION);
2599 #else
2600 /* After return from Deep Sleep, for each FLL/PLL, if needed, restore the source to ECO.
2601 * And block until the FLL/PLL has regained its frequency lock.
2602 */
2603 uint32_t timeout = TIMEOUT;
2604 retVal = CY_SYSPM_TIMEOUT;
2605
2606 if (0U != changedSourcePaths)
2607 {
2608 /* If any FLL/PLL was sourced by the ECO, timeout wait for the ECO to become fully stabilized again */
2609 while ((CY_SYSCLK_ECOSTAT_STABLE != Cy_SysClk_EcoGetStatus()) && (0UL != timeout))
2610 {
2611 timeout--;
2612 }
2613
2614 if (0UL != timeout)
2615 {
2616 uint32_t fllpll; /* 0 = FLL, all other values = PLL */
2617
2618 for (fllpll = 0UL; fllpll <= CY_SRSS_NUM_PLL; fllpll++)
2619 {
2620 /* If there is a correspondent record about a changed clock source */
2621 if (0U != (changedSourcePaths & (uint16_t)(1UL << fllpll)))
2622 {
2623 /* Change this path source back to ECO */
2624 (void)Cy_SysClk_ClkPathSetSource(fllpll, CY_SYSCLK_CLKPATH_IN_ECO);
2625
2626 /* Timeout wait for FLL/PLL to regain lock.
2627 * Split FLL and PLL lock polling loops into two separate threads to minimize one polling loop duration.
2628 */
2629 if (0UL == fllpll)
2630 {
2631 while ((!Cy_SysClk_FllLocked()) && (0UL != timeout))
2632 {
2633 timeout--;
2634 }
2635 }
2636 else
2637 {
2638 while ((!Cy_SysClk_PllLocked(fllpll)) && (0UL != timeout))
2639 {
2640 timeout--;
2641 }
2642 }
2643
2644 if (0UL != timeout)
2645 {
2646 /* Undo bypass the FLL/PLL */
2647 if (0UL == fllpll)
2648 {
2649 CY_REG32_CLR_SET(SRSS_CLK_FLL_CONFIG3, SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, CY_SYSCLK_FLLPLL_OUTPUT_OUTPUT);
2650 }
2651 else
2652 {
2653 if (0U != (pllAutoModes & (uint16_t)(1UL << fllpll)))
2654 {
2655 CY_REG32_CLR_SET(SRSS_CLK_PLL_CONFIG[fllpll - 1UL], SRSS_CLK_PLL_CONFIG_BYPASS_SEL, CY_SYSCLK_FLLPLL_OUTPUT_AUTO);
2656 }
2657 else
2658 {
2659 CY_REG32_CLR_SET(SRSS_CLK_PLL_CONFIG[fllpll - 1UL], SRSS_CLK_PLL_CONFIG_BYPASS_SEL, CY_SYSCLK_FLLPLL_OUTPUT_OUTPUT);
2660 }
2661 }
2662
2663 retVal = CY_SYSPM_SUCCESS;
2664 }
2665 }
2666 }
2667 }
2668 }
2669 else if (Cy_SysClk_FllIsEnabled())
2670 {
2671 /* Timeout wait for FLL to regain lock */
2672 while ((!Cy_SysClk_FllLocked()) && (0UL != timeout))
2673 {
2674 timeout--;
2675 }
2676
2677 if (0UL != timeout)
2678 {
2679 /* Undo bypass the FLL */
2680 CY_REG32_CLR_SET(SRSS_CLK_FLL_CONFIG3, SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, CY_SYSCLK_FLLPLL_OUTPUT_OUTPUT);
2681 retVal = CY_SYSPM_SUCCESS;
2682 }
2683 }
2684 else
2685 {
2686 retVal = CY_SYSPM_SUCCESS;
2687 }
2688
2689 preventCounting = false; /* Allow clock measurement */
2690 #endif /* ((CY_CPU_CORTEX_M4) && (defined(CY_DEVICE_SECURE))) */
2691 }
2692 break;
2693
2694 default: /* Unsupported mode, return CY_SYSPM_FAIL */
2695 break;
2696 }
2697
2698 return (retVal);
2699
2700 }
2701
2702
2703 /* ========================================================================== */
2704 /* ========================= clkHf[n] SECTION ========================= */
2705 /* ========================================================================== */
2706
2707
Cy_SysClk_ClkHfGetFrequency(uint32_t clkHf)2708 uint32_t Cy_SysClk_ClkHfGetFrequency(uint32_t clkHf)
2709 {
2710 /* variables holding intermediate clock frequencies, dividers and FLL/PLL settings */
2711 uint32_t pDiv = 1UL << (uint32_t)Cy_SysClk_ClkHfGetDivider(clkHf); /* root prescaler (1/2/4/8) */
2712 uint32_t path = (uint32_t) Cy_SysClk_ClkHfGetSource(clkHf); /* path input for root 0 (clkHf[0]) */
2713 uint32_t freq = Cy_SysClk_ClkPathGetFrequency(path);
2714
2715 /* Divide the path input frequency down and return the result */
2716 return (CY_SYSLIB_DIV_ROUND(freq, pDiv));
2717 }
2718
2719
2720 /* ========================================================================== */
2721 /* ===================== clk_peripherals SECTION ====================== */
2722 /* ========================================================================== */
2723
2724
Cy_SysClk_PeriphGetFrequency(cy_en_divider_types_t dividerType,uint32_t dividerNum)2725 uint32_t Cy_SysClk_PeriphGetFrequency(cy_en_divider_types_t dividerType, uint32_t dividerNum)
2726 {
2727 uint32_t integer = 0UL; /* Integer part of peripheral divider */
2728 uint32_t freq = Cy_SysClk_ClkPeriGetFrequency(); /* Get Peri frequency */
2729
2730 CY_ASSERT_L1(((dividerType == CY_SYSCLK_DIV_8_BIT) && (dividerNum < PERI_DIV_8_NR)) || \
2731 ((dividerType == CY_SYSCLK_DIV_16_BIT) && (dividerNum < PERI_DIV_16_NR)) || \
2732 ((dividerType == CY_SYSCLK_DIV_16_5_BIT) && (dividerNum < PERI_DIV_16_5_NR)) || \
2733 ((dividerType == CY_SYSCLK_DIV_24_5_BIT) && (dividerNum < PERI_DIV_24_5_NR)));
2734
2735 /* get the divider value for clk_peri to the selected peripheral clock */
2736 switch(dividerType)
2737 {
2738 case CY_SYSCLK_DIV_8_BIT:
2739 case CY_SYSCLK_DIV_16_BIT:
2740 integer = 1UL + Cy_SysClk_PeriphGetDivider(dividerType, dividerNum);
2741 freq = CY_SYSLIB_DIV_ROUND(freq, integer);
2742 break;
2743
2744 case CY_SYSCLK_DIV_16_5_BIT:
2745 case CY_SYSCLK_DIV_24_5_BIT:
2746 {
2747 uint32_t locFrac;
2748 uint32_t locDiv;
2749 uint64_t locFreq = freq * 32ULL;
2750 Cy_SysClk_PeriphGetFracDivider(dividerType, dividerNum, &integer, &locFrac);
2751 /* For fractional dividers, the divider is (int + 1) + frac/32 */
2752 locDiv = ((1UL + integer) * 32UL) + locFrac;
2753 freq = (uint32_t) CY_SYSLIB_DIV_ROUND(locFreq, (uint64_t)locDiv);
2754 }
2755 break;
2756
2757 default:
2758 /* Unknown divider */
2759 break;
2760 }
2761
2762 return (freq);
2763 }
2764
2765
Cy_SysClk_ClkTimerGetFrequency(void)2766 uint32_t Cy_SysClk_ClkTimerGetFrequency(void)
2767 {
2768 uint32_t freq = 0UL;
2769
2770 if (Cy_SysClk_ClkTimerIsEnabled())
2771 {
2772 freq = Cy_SysClk_ClkHfGetFrequency(0UL);
2773
2774 switch (Cy_SysClk_ClkTimerGetSource())
2775 {
2776 case CY_SYSCLK_CLKTIMER_IN_IMO:
2777 freq = CY_SYSCLK_IMO_FREQ;
2778 break;
2779
2780 case CY_SYSCLK_CLKTIMER_IN_HF0_NODIV:
2781 break;
2782
2783 case CY_SYSCLK_CLKTIMER_IN_HF0_DIV2:
2784 freq /= 2UL;
2785 break;
2786
2787 case CY_SYSCLK_CLKTIMER_IN_HF0_DIV4:
2788 freq /= 4UL;
2789 break;
2790
2791 case CY_SYSCLK_CLKTIMER_IN_HF0_DIV8:
2792 freq /= 8UL;
2793 break;
2794
2795 default:
2796 freq = 0UL;
2797 break;
2798 }
2799 }
2800
2801 /* Divide the input frequency down and return the result */
2802 return (CY_SYSLIB_DIV_ROUND(freq, 1UL + (uint32_t)Cy_SysClk_ClkTimerGetDivider()));
2803 }
2804
2805
Cy_SysClk_FllGetFrequency(void)2806 uint32_t Cy_SysClk_FllGetFrequency(void)
2807 {
2808 uint32_t fDiv ; /* FLL multiplier/feedback divider */
2809 uint32_t rDiv; /* FLL reference divider */
2810 uint32_t oDiv; /* FLL output divider */
2811 bool enabled; /* FLL enable status; n/a for direct */
2812 uint32_t freq = 0UL; /* FLL Frequency */
2813
2814 cy_stc_fll_manual_config_t fllCfg;
2815 Cy_SysClk_FllGetConfiguration(&fllCfg);
2816 enabled = (Cy_SysClk_FllIsEnabled()) && (CY_SYSCLK_FLLPLL_OUTPUT_INPUT != fllCfg.outputMode);
2817 fDiv = fllCfg.fllMult;
2818 rDiv = fllCfg.refDiv;
2819 oDiv = (fllCfg.enableOutputDiv) ? 2UL : 1UL;
2820
2821 if (enabled && /* If FLL is enabled and not bypassed */
2822 (0UL != rDiv)) /* to avoid division by zero */
2823 {
2824 freq = Cy_SysClk_ClkPathMuxGetFrequency(0UL); /* FLL mapped always to path 0 */
2825 freq = (uint32_t)CY_SYSLIB_DIV_ROUND(((uint64_t)freq * (uint64_t)fDiv),
2826 ((uint64_t)rDiv * (uint64_t)oDiv));
2827 }
2828
2829 return (freq);
2830 }
2831
Cy_SysClk_PllGetFrequency(uint32_t clkPath)2832 uint32_t Cy_SysClk_PllGetFrequency(uint32_t clkPath)
2833 {
2834 uint32_t fDiv = 0UL; /* PLL multiplier/feedback divider */
2835 uint32_t rDiv = 0UL; /* PLL reference divider */
2836 uint32_t oDiv = 0UL; /* PLL output divider */
2837 bool enabled = false; /* PLL enable status; n/a for direct */
2838 uint32_t freq=0UL; /* PLL Frequency */
2839
2840 if((CY_SRSS_NUM_PLL > 0UL) && (clkPath > 0UL))
2841 {
2842 CY_ASSERT_L1(clkPath < CY_SRSS_NUM_CLKPATH);
2843
2844 if (clkPath <= CY_SRSS_NUM_PLL)
2845 {
2846 cy_stc_pll_manual_config_t pllcfg;
2847 if (CY_SYSCLK_SUCCESS == Cy_SysClk_PllGetConfiguration(clkPath, &pllcfg))
2848 {
2849 enabled = (Cy_SysClk_PllIsEnabled(clkPath)) && (CY_SYSCLK_FLLPLL_OUTPUT_INPUT != pllcfg.outputMode);
2850 fDiv = pllcfg.feedbackDiv;
2851 rDiv = pllcfg.referenceDiv;
2852 oDiv = pllcfg.outputDiv;
2853 }
2854
2855 if (enabled && /* If PLL is enabled and not bypassed */
2856 (0UL != rDiv) && (0UL != oDiv)) /* to avoid division by zero */
2857 {
2858 freq = Cy_SysClk_ClkPathMuxGetFrequency(clkPath);
2859 freq = (uint32_t)CY_SYSLIB_DIV_ROUND(((uint64_t)freq * (uint64_t)fDiv),
2860 ((uint64_t)rDiv * (uint64_t)oDiv));
2861 }
2862 }
2863 }
2864
2865 return (freq);
2866 }
2867
2868 #if defined (CY_DEVICE_SECURE)
2869 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 17.2')
2870 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 18.6')
2871 #endif
2872
2873 #endif
2874
2875 /* [] END OF FILE */
2876