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