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