1 /***************************************************************************//**
2 * \file cyhal_syspm.c
3 *
4 * \brief
5 * Provides a high level interface for interacting with the Infineon power
6 * management and system clock configuration. This interface abstracts out the
7 * chip specific details. If any chip specific functionality is necessary, or
8 * performance is critical the low level functions can be used directly.
9 *
10 ********************************************************************************
11 * \copyright
12 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
13 * an affiliate of Cypress Semiconductor Corporation
14 *
15 * SPDX-License-Identifier: Apache-2.0
16 *
17 * Licensed under the Apache License, Version 2.0 (the "License");
18 * you may not use this file except in compliance with the License.
19 * You may obtain a copy of the License at
20 *
21 * http://www.apache.org/licenses/LICENSE-2.0
22 *
23 * Unless required by applicable law or agreed to in writing, software
24 * distributed under the License is distributed on an "AS IS" BASIS,
25 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26 * See the License for the specific language governing permissions and
27 * limitations under the License.
28 *******************************************************************************/
29 #if defined(COMPONENT_CAT1)
30 /**
31 * \addtogroup group_hal_impl_syspm System Power Management
32 * \ingroup group_hal_impl
33 * \{
34 * \section section_hal_impl_syspm_set_system
35 *
36 * The callback mode \ref CYHAL_SYSPM_AFTER_DS_WFI_TRANSITION is only applicable
37 * for CAT1B devices.
38 *
39 * Setting the system state is unsupported on CAT1C devices. For CAT1C devices,
40 * \ref CYHAL_SYSPM_RSLT_ERR_NOT_SUPPORTED will be returned in the function \ref cyhal_syspm_set_system_state.
41 *
42 * \} group_hal_impl_pwm
43 */
44 #elif defined(COMPONENT_CAT2)
45 /**
46 * \addtogroup group_hal_impl_syspm System Power Management
47 * \ingroup group_hal_impl
48 * \{
49 * \section section_hal_impl_syspm_set_system
50 *
51 * Setting the system state is unsupported on CAT2 devices. For CAT2 devices,
52 * \ref CYHAL_SYSPM_RSLT_ERR_NOT_SUPPORTED will be returned in the function \ref cyhal_syspm_set_system_state.
53 *
54 * \} group_hal_impl_pwm
55 */
56 #endif
57
58 #include <limits.h>
59 #include <string.h>
60 #include "cyhal_system.h"
61 #include "cyhal_syspm.h"
62 #include "cy_syspm.h"
63 #include "cy_utils.h"
64 #include "cyhal_utils.h"
65 #if (defined(CY_RTOS_AWARE) || defined(COMPONENT_RTOS_AWARE)) && defined(CY_IP_MXS40SSRSS)
66 #include "cyabs_rtos_dsram.h"
67 #endif
68 #if defined(COMPONENT_CAT1B)
69 #include "system_cat1b.h"
70 #endif
71
72 #if (CYHAL_DRIVER_AVAILABLE_LPTIMER != 0)
73 #include "cyhal_lptimer.h"
74 #endif /* (CYHAL_DRIVER_AVAILABLE_LPTIMER != 0) */
75
76 #if (CYHAL_DRIVER_AVAILABLE_SYSPM)
77
78 #if defined(__cplusplus)
79 extern "C"
80 {
81 #endif
82
83 /* Check if the SysTick is enabled */
84 #define _cyhal_syspm_is_systick_enabled() (SysTick->CTRL & SysTick_CTRL_ENABLE_Msk)
85
86 /* Disable the SysTick */
87 #define _cyhal_syspm_disable_systick() (SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk)
88
89 /* Enable the SysTick */
90 #define _cyhal_syspm_enable_systick() (SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk)
91
92 /* Hz to KHz */
93 #define _CYHAL_HZ_TO_KHZ_CONVERSION_FACTOR 1000
94
95 /* The first entry in the callback chain is always reserved for the user set
96 * cyhal_syspm_register_callback callback. This may be set to a sentinel value
97 * indicating it is the end of the list. All subsequent slots are where
98 * peripheral drivers are tracked. This makes it very easy to determine whether
99 * the user registered a callback and to make sure we run that first. */
100 static cyhal_syspm_callback_data_t* _cyhal_syspm_callback_ptr = CYHAL_SYSPM_END_OF_LIST;
101 static cyhal_syspm_callback_data_t* _cyhal_syspm_peripheral_callback_ptr = CYHAL_SYSPM_END_OF_LIST;
102
103 static uint16_t _cyhal_deep_sleep_lock = 0;
104
105 static uint32_t _cyhal_syspm_supply_voltages[((size_t)CYHAL_VOLTAGE_SUPPLY_MAX) + 1] = { 0 };
106
107 static bool _cyhal_systick_disable = false;
108 static bool _cyhal_disable_systick_before_sleep_deepsleep = false;
109
110 #define SYSPM_CALLBACK_ORDER (10u)
111
112 static cy_stc_syspm_callback_params_t _cyhal_syspm_cb_params_default = {NULL, NULL};
113 static const cy_stc_syspm_callback_t _cyhal_syspm_cb_default =
114 {
115 .callback = NULL,
116 .type = CY_SYSPM_SLEEP,
117 .skipMode = 0,
118 .callbackParams = &_cyhal_syspm_cb_params_default,
119 .prevItm = NULL,
120 .nextItm = NULL,
121 .order = SYSPM_CALLBACK_ORDER,
122 };
123
124 static cy_stc_syspm_callback_t _cyhal_syspm_sleep;
125 static cy_stc_syspm_callback_t _cyhal_syspm_deepsleep;
126 static cy_stc_syspm_callback_t _cyhal_syspm_hibernate;
127 #if defined(COMPONENT_CAT1A)
128 static cy_stc_syspm_callback_t _cyhal_syspm_lp;
129 static cy_stc_syspm_callback_t _cyhal_syspm_normal;
130 #elif defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1D)
131 static cy_stc_syspm_callback_t _cyhal_syspm_lp;
132 static cy_stc_syspm_callback_t _cyhal_syspm_normal;
133 static cy_stc_syspm_callback_t _cyhal_syspm_deepsleep_ram;
134 static cy_stc_syspm_callback_t _cyhal_syspm_deepsleep_off;
135 #endif /* defined(COMPONENT_CAT1A) */
136
_cyhal_syspm_call_all_pm_callbacks(cyhal_syspm_callback_data_t * entry,bool * allow,cyhal_syspm_callback_state_t state,cyhal_syspm_callback_mode_t mode)137 static cyhal_syspm_callback_data_t* _cyhal_syspm_call_all_pm_callbacks(
138 cyhal_syspm_callback_data_t* entry, bool* allow, cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode)
139 {
140 while(entry != CYHAL_SYSPM_END_OF_LIST)
141 {
142 if (entry->callback != NULL &&
143 (entry->states & state) == state &&
144 (entry->ignore_modes & mode) != mode)
145 {
146 *allow = entry->callback(state, mode, entry->args) || mode != CYHAL_SYSPM_CHECK_READY;
147 if (!(*allow))
148 {
149 // Do not increment pointer so that backtracking stop at the correct location
150 break;
151 }
152 }
153 entry = entry->next;
154 }
155 return entry;
156 }
157
_cyhal_syspm_backtrack_all_pm_callbacks(cyhal_syspm_callback_data_t * start,cyhal_syspm_callback_data_t * end,cyhal_syspm_callback_state_t state)158 static void _cyhal_syspm_backtrack_all_pm_callbacks(cyhal_syspm_callback_data_t* start, cyhal_syspm_callback_data_t* end, cyhal_syspm_callback_state_t state)
159 {
160 while(start != end)
161 {
162 if (start->callback != NULL &&
163 (start->states & state) == state &&
164 (start->ignore_modes & CYHAL_SYSPM_CHECK_FAIL) != CYHAL_SYSPM_CHECK_FAIL)
165 {
166 start->callback(state, CYHAL_SYSPM_CHECK_FAIL, start->args);
167 }
168 start = start->next;
169 }
170 }
171
_cyhal_syspm_common_cb(cy_en_syspm_callback_mode_t mode,cyhal_syspm_callback_state_t state)172 static cy_en_syspm_status_t _cyhal_syspm_common_cb(cy_en_syspm_callback_mode_t mode, cyhal_syspm_callback_state_t state)
173 {
174 // The PDL function that wrap around this callback enters critical section, this function does not need to enter critical section.
175 cyhal_syspm_callback_mode_t hal_mode = _cyhal_utils_convert_pdltohal_pm_mode(mode);
176 bool allow = true;
177
178 cyhal_syspm_callback_data_t *first, *second;
179 if (hal_mode == CYHAL_SYSPM_CHECK_FAIL || hal_mode == CYHAL_SYSPM_AFTER_TRANSITION || hal_mode == CYHAL_SYSPM_AFTER_DS_WFI_TRANSITION)
180 {
181 first = _cyhal_syspm_peripheral_callback_ptr;
182 second = _cyhal_syspm_callback_ptr;
183 }
184 else
185 {
186 second = _cyhal_syspm_peripheral_callback_ptr;
187 first = _cyhal_syspm_callback_ptr;
188 }
189
190 cyhal_syspm_callback_data_t* first_current = _cyhal_syspm_call_all_pm_callbacks(first, &allow, state, hal_mode);
191 cyhal_syspm_callback_data_t* second_current = allow
192 ? _cyhal_syspm_call_all_pm_callbacks(second, &allow, state, hal_mode)
193 : second;
194
195 if (!allow && (CYHAL_SYSPM_CHECK_READY == hal_mode))
196 {
197 _cyhal_syspm_backtrack_all_pm_callbacks(second, second_current, state);
198 _cyhal_syspm_backtrack_all_pm_callbacks(first, first_current, state);
199 }
200
201 return allow ? CY_SYSPM_SUCCESS : CY_SYSPM_FAIL;
202 }
203
_cyhal_syspm_cb_sleep_deepsleep(cy_en_syspm_callback_mode_t mode,cyhal_syspm_callback_state_t state)204 static cy_en_syspm_status_t _cyhal_syspm_cb_sleep_deepsleep(cy_en_syspm_callback_mode_t mode, cyhal_syspm_callback_state_t state)
205 {
206 cy_en_syspm_status_t status = _cyhal_syspm_common_cb(mode, state);
207 // No need to test status here, as it only gets set when mode == CYHAL_SYSPM_CHECK_READY
208 if (mode == CY_SYSPM_BEFORE_TRANSITION)
209 {
210 _cyhal_systick_disable = _cyhal_syspm_is_systick_enabled() && _cyhal_disable_systick_before_sleep_deepsleep;
211 if (_cyhal_systick_disable)
212 {
213 _cyhal_syspm_disable_systick();
214 }
215 }
216 else if (mode == CY_SYSPM_AFTER_TRANSITION)
217 {
218 if (_cyhal_systick_disable)
219 {
220 _cyhal_syspm_enable_systick();
221 }
222 }
223 return status;
224 }
225
_cyhal_syspm_cb_sleep(cy_stc_syspm_callback_params_t * callback_params,cy_en_syspm_callback_mode_t mode)226 static cy_en_syspm_status_t _cyhal_syspm_cb_sleep(cy_stc_syspm_callback_params_t *callback_params, cy_en_syspm_callback_mode_t mode)
227 {
228 CY_UNUSED_PARAMETER(callback_params);
229 return _cyhal_syspm_cb_sleep_deepsleep(mode, CYHAL_SYSPM_CB_CPU_SLEEP);
230 }
_cyhal_syspm_cb_deepsleep(cy_stc_syspm_callback_params_t * callback_params,cy_en_syspm_callback_mode_t mode)231 static cy_en_syspm_status_t _cyhal_syspm_cb_deepsleep(cy_stc_syspm_callback_params_t *callback_params, cy_en_syspm_callback_mode_t mode)
232 {
233 if((mode == CY_SYSPM_CHECK_READY) && (_cyhal_deep_sleep_lock != 0))
234 {
235 return CY_SYSPM_FAIL;
236 }
237 CY_UNUSED_PARAMETER(callback_params);
238 return _cyhal_syspm_cb_sleep_deepsleep(mode, CYHAL_SYSPM_CB_CPU_DEEPSLEEP);
239 }
_cyhal_syspm_cb_hibernate(cy_stc_syspm_callback_params_t * callback_params,cy_en_syspm_callback_mode_t mode)240 static cy_en_syspm_status_t _cyhal_syspm_cb_hibernate(cy_stc_syspm_callback_params_t *callback_params, cy_en_syspm_callback_mode_t mode)
241 {
242 CY_UNUSED_PARAMETER(callback_params);
243 return _cyhal_syspm_common_cb(mode, CYHAL_SYSPM_CB_SYSTEM_HIBERNATE);
244 }
245 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1D)
_cyhal_syspm_cb_normal(cy_stc_syspm_callback_params_t * callback_params,cy_en_syspm_callback_mode_t mode)246 static cy_en_syspm_status_t _cyhal_syspm_cb_normal(cy_stc_syspm_callback_params_t *callback_params, cy_en_syspm_callback_mode_t mode)
247 {
248 CY_UNUSED_PARAMETER(callback_params);
249 cy_en_syspm_status_t status = _cyhal_syspm_common_cb(mode, CYHAL_SYSPM_CB_SYSTEM_NORMAL);
250
251 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1C)
252 if (mode == CY_SYSPM_AFTER_TRANSITION)
253 {
254 uint32_t hfclk_freq_mhz = Cy_SysClk_ClkHfGetFrequency(0) / 1000000;
255 Cy_SysLib_SetWaitStates(false, hfclk_freq_mhz);
256 }
257 #endif /* defined(COMPONENT_CAT1A) */
258 return status;
259 }
_cyhal_syspm_cb_lp(cy_stc_syspm_callback_params_t * callback_params,cy_en_syspm_callback_mode_t mode)260 static cy_en_syspm_status_t _cyhal_syspm_cb_lp(cy_stc_syspm_callback_params_t *callback_params, cy_en_syspm_callback_mode_t mode)
261 {
262 CY_UNUSED_PARAMETER(callback_params);
263 cy_en_syspm_status_t status = _cyhal_syspm_common_cb(mode, CYHAL_SYSPM_CB_SYSTEM_LOW);
264
265 if (mode == CY_SYSPM_BEFORE_TRANSITION)
266 {
267 uint32_t hfclk_freq_mhz = Cy_SysClk_ClkHfGetFrequency(0) / 1000000;
268 Cy_SysLib_SetWaitStates(true, hfclk_freq_mhz);
269 }
270 return status;
271 }
272 #endif
273 #if defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1D)
_cyhal_syspm_cb_deepsleep_ram(cy_stc_syspm_callback_params_t * callback_params,cy_en_syspm_callback_mode_t mode)274 static cy_en_syspm_status_t _cyhal_syspm_cb_deepsleep_ram(cy_stc_syspm_callback_params_t *callback_params, cy_en_syspm_callback_mode_t mode)
275 {
276 CY_UNUSED_PARAMETER(callback_params);
277 if ((mode == CY_SYSPM_CHECK_READY) && (_cyhal_deep_sleep_lock != 0))
278 {
279 return CY_SYSPM_FAIL;
280 }
281 return _cyhal_syspm_common_cb(mode, CYHAL_SYSPM_CB_CPU_DEEPSLEEP_RAM);
282 }
_cyhal_syspm_cb_deepsleep_off(cy_stc_syspm_callback_params_t * callback_params,cy_en_syspm_callback_mode_t mode)283 static cy_en_syspm_status_t _cyhal_syspm_cb_deepsleep_off(cy_stc_syspm_callback_params_t *callback_params, cy_en_syspm_callback_mode_t mode)
284 {
285 CY_UNUSED_PARAMETER(callback_params);
286 return _cyhal_syspm_common_cb(mode, CYHAL_SYSPM_CB_CPU_DEEPSLEEP/*_OFF*/);
287 }
288 #endif
289
_cyhal_syspm_is_registered(cyhal_syspm_callback_data_t * callback)290 static inline bool _cyhal_syspm_is_registered(cyhal_syspm_callback_data_t *callback)
291 {
292 // If callback->next is NULL it must not be registered since all registered
293 // next ptrs in the list must point to the next callback or be equal to
294 // CYHAL_SYSPM_END_OF_LIST
295 return (callback->next != NULL);
296 }
297
_cyhal_syspm_add_callback_to_list(cyhal_syspm_callback_data_t ** list,cyhal_syspm_callback_data_t * add)298 static void _cyhal_syspm_add_callback_to_list(cyhal_syspm_callback_data_t **list, cyhal_syspm_callback_data_t *add)
299 {
300 uint32_t intr_status = cyhal_system_critical_section_enter();
301 if(!_cyhal_syspm_is_registered(add))
302 {
303 add->next = *list;
304 *list = add;
305 }
306 cyhal_system_critical_section_exit(intr_status);
307 }
308
_cyhal_syspm_remove_callback_from_list(cyhal_syspm_callback_data_t ** list,cyhal_syspm_callback_data_t * rmv)309 static void _cyhal_syspm_remove_callback_from_list(cyhal_syspm_callback_data_t **list, cyhal_syspm_callback_data_t *rmv)
310 {
311 uint32_t intr_status = cyhal_system_critical_section_enter();
312 while(*list != CYHAL_SYSPM_END_OF_LIST)
313 {
314 if (*list == rmv)
315 {
316 *list = rmv->next;
317 rmv->next = NULL;
318 break;
319 }
320 list = &((*list)->next);
321 }
322 cyhal_system_critical_section_exit(intr_status);
323 }
324
_cyhal_syspm_register_peripheral_callback(cyhal_syspm_callback_data_t * callback_data)325 void _cyhal_syspm_register_peripheral_callback(cyhal_syspm_callback_data_t *callback_data)
326 {
327 CY_ASSERT(callback_data != NULL);
328 _cyhal_syspm_add_callback_to_list(&_cyhal_syspm_peripheral_callback_ptr, callback_data);
329 }
330
_cyhal_syspm_unregister_peripheral_callback(cyhal_syspm_callback_data_t * callback_data)331 void _cyhal_syspm_unregister_peripheral_callback(cyhal_syspm_callback_data_t *callback_data)
332 {
333 CY_ASSERT(callback_data != NULL);
334 _cyhal_syspm_remove_callback_from_list(&_cyhal_syspm_peripheral_callback_ptr, callback_data);
335 }
336
_cyhal_syspm_register_cb(cy_stc_syspm_callback_t * data,cy_en_syspm_callback_type_t type,Cy_SysPmCallback callback)337 static bool _cyhal_syspm_register_cb(cy_stc_syspm_callback_t *data, cy_en_syspm_callback_type_t type, Cy_SysPmCallback callback)
338 {
339 memcpy(data, &_cyhal_syspm_cb_default, sizeof(cy_stc_syspm_callback_t));
340 data->callback = callback;
341 data->type = type;
342 return Cy_SysPm_RegisterCallback(data);
343 }
344
345 #if defined(CY_IP_MXS40SSRSS) && (defined(CY_RTOS_AWARE) || defined(COMPONENT_RTOS_AWARE))
346 CY_RAMFUNC_BEGIN
_cyhal_syspm_enter_deepsleep_ram(void)347 cy_rslt_t _cyhal_syspm_enter_deepsleep_ram(void)
348 {
349 cy_rslt_t retVal;
350 uint32_t dsramIntState;
351
352 retVal = Cy_SysPm_SetupDeepSleepRAM(CY_SYSPM_PRE_DSRAM, &dsramIntState); /* Pre DSRAM checks */
353 if(retVal == CY_RSLT_SUCCESS)
354 {
355 System_Store_NVIC_Reg();
356 cyabs_rtos_enter_dsram(); /* Enter WFI with context saved */
357 System_Restore_NVIC_Reg();
358
359 Cy_SysPm_SetupDeepSleepRAM(CY_SYSPM_POST_DSRAM, &dsramIntState); /* Post DSRAM Checks */
360 }
361 return retVal;
362 }
363 CY_RAMFUNC_END
364 #endif
365
366
_cyhal_syspm_deepsleep_internal(void)367 static cy_rslt_t _cyhal_syspm_deepsleep_internal(void)
368 {
369 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
370 #if defined(CY_IP_MXS40SSRSS) && (defined(CY_RTOS_AWARE) || defined(COMPONENT_RTOS_AWARE))
371 if(Cy_SysPm_GetDeepSleepMode() == CY_SYSPM_MODE_DEEPSLEEP_RAM)
372 {
373 return _cyhal_syspm_enter_deepsleep_ram();
374 }
375 else
376 #endif
377 {
378 return Cy_SysPm_CpuEnterDeepSleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
379 }
380 #elif defined(COMPONENT_CAT2)
381 return Cy_SysPm_CpuEnterDeepSleep();
382 #endif
383
384 }
385
386 /******************************************************************************
387 ******************************** Public APIs *********************************
388 *****************************************************************************/
389
cyhal_syspm_init(void)390 cy_rslt_t cyhal_syspm_init(void)
391 {
392 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
393 /* Check the IO status. If current status is frozen, unfreeze the system. */
394 if (Cy_SysPm_GetIoFreezeStatus())
395 {
396 /* Unfreeze the system */
397 Cy_SysPm_IoUnfreeze();
398 }
399
400 #endif /* defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D) */
401
402 cy_rslt_t rslt = CY_RSLT_SUCCESS;
403 if (!_cyhal_syspm_register_cb(&_cyhal_syspm_sleep, CY_SYSPM_SLEEP, _cyhal_syspm_cb_sleep)
404 || !_cyhal_syspm_register_cb(&_cyhal_syspm_deepsleep, CY_SYSPM_DEEPSLEEP, _cyhal_syspm_cb_deepsleep)
405 || !_cyhal_syspm_register_cb(&_cyhal_syspm_hibernate, CY_SYSPM_HIBERNATE, _cyhal_syspm_cb_hibernate)
406 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1D)
407 || !_cyhal_syspm_register_cb(&_cyhal_syspm_normal, CY_SYSPM_LP, _cyhal_syspm_cb_normal)
408 || !_cyhal_syspm_register_cb(&_cyhal_syspm_lp, CY_SYSPM_ULP, _cyhal_syspm_cb_lp)
409 #endif /* defined(COMPONENT_CAT1A) */
410 #if defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1D)
411 #if defined(COMPONENT_CAT1B)
412 || !_cyhal_syspm_register_cb(&_cyhal_syspm_lp, CY_SYSPM_LPACTIVE_ENTER, _cyhal_syspm_cb_lp)
413 || !_cyhal_syspm_register_cb(&_cyhal_syspm_normal, CY_SYSPM_LPACTIVE_EXIT, _cyhal_syspm_cb_normal)
414 #endif /* defined(COMPONENT_CAT1B) */
415 || !_cyhal_syspm_register_cb(&_cyhal_syspm_deepsleep_ram, CY_SYSPM_DEEPSLEEP_RAM, _cyhal_syspm_cb_deepsleep_ram)
416 || !_cyhal_syspm_register_cb(&_cyhal_syspm_deepsleep_off, CY_SYSPM_DEEPSLEEP_OFF, _cyhal_syspm_cb_deepsleep_off)
417 #endif /* defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1D) */
418 )
419 {
420 rslt = CYHAL_SYSPM_RSLT_INIT_ERROR;
421 }
422 return rslt;
423 }
424
cyhal_syspm_hibernate(cyhal_syspm_hibernate_source_t wakeup_source)425 cy_rslt_t cyhal_syspm_hibernate(cyhal_syspm_hibernate_source_t wakeup_source)
426 {
427 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
428 /* Defines for mapping hal hibernate sources to pdl */
429 static const uint32_t source_map[] =
430 {
431 0u, // Default value, no wakeup
432 (uint32_t)CY_SYSPM_HIBERNATE_LPCOMP0_LOW, // CYHAL_SYSPM_HIBERNATE_LPCOMP0_LOW
433 (uint32_t)CY_SYSPM_HIBERNATE_LPCOMP0_HIGH, // CYHAL_SYSPM_HIBERNATE_LPCOMP0_HIGH
434 (uint32_t)CY_SYSPM_HIBERNATE_LPCOMP1_LOW, // CYHAL_SYSPM_HIBERNATE_LPCOMP1_LOW
435 (uint32_t)CY_SYSPM_HIBERNATE_LPCOMP1_HIGH, // CYHAL_SYSPM_HIBERNATE_LPCOMP1_HIGH
436 (uint32_t)CY_SYSPM_HIBERNATE_RTC_ALARM, // CYHAL_SYSPM_HIBERNATE_RTC_ALARM
437 (uint32_t)CY_SYSPM_HIBERNATE_WDT, // CYHAL_SYSPM_HIBERNATE_WDT
438 (uint32_t)CY_SYSPM_HIBERNATE_PIN0_LOW, // CYHAL_SYSPM_HIBERNATE_PINA_LOW
439 (uint32_t)CY_SYSPM_HIBERNATE_PIN0_HIGH, // CYHAL_SYSPM_HIBERNATE_PINA_HIGH
440 (uint32_t)CY_SYSPM_HIBERNATE_PIN1_LOW, // CYHAL_SYSPM_HIBERNATE_PINB_LOW
441 (uint32_t)CY_SYSPM_HIBERNATE_PIN1_HIGH, // CYHAL_SYSPM_HIBERNATE_PINB_HIGH
442 };
443
444 Cy_SysPm_SetHibernateWakeupSource(_cyhal_utils_convert_flags(source_map, sizeof(source_map) / sizeof(uint32_t), (uint32_t)wakeup_source));
445 return Cy_SysPm_SystemEnterHibernate();
446 #elif defined(COMPONENT_CAT2)
447 CY_UNUSED_PARAMETER(wakeup_source);
448 return CYHAL_SYSPM_RSLT_ERR_NOT_SUPPORTED;
449 #endif /* defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D) */
450 }
451
cyhal_syspm_set_system_state(cyhal_syspm_system_state_t state)452 cy_rslt_t cyhal_syspm_set_system_state(cyhal_syspm_system_state_t state)
453 {
454 #if defined(COMPONENT_CAT2) || defined(COMPONENT_CAT1C)
455 CY_UNUSED_PARAMETER(state);
456 return CYHAL_SYSPM_RSLT_ERR_NOT_SUPPORTED;
457 #else
458 cy_rslt_t rslt;
459
460 /* The wait states are changed in the common syspm handler after
461 * state change is allowed and all handlers are called to take into
462 * account any frequency change that might happen as a part of the
463 * power management handlers
464 */
465 switch (state)
466 {
467 case CYHAL_SYSPM_SYSTEM_NORMAL:
468 #if defined(CY_IP_MXS40SSRSS)
469 rslt = Cy_SysPm_SystemLpActiveExit();
470 #else
471 rslt = Cy_SysPm_SystemEnterLp();
472 #endif
473 break;
474 case CYHAL_SYSPM_SYSTEM_LOW:
475 #if defined(CY_IP_MXS40SSRSS)
476 rslt = Cy_SysPm_SystemLpActiveEnter();
477 #else
478 rslt = Cy_SysPm_SystemEnterUlp();
479 #endif
480 break;
481 default:
482 /* Should never get here */
483 CY_ASSERT(false);
484 rslt = CYHAL_SYSPM_RSLT_BAD_ARGUMENT;
485 break;
486 }
487 return rslt;
488 #endif /* defined(COMPONENT_CAT2) */
489 }
490
cyhal_syspm_register_callback(cyhal_syspm_callback_data_t * callback_data)491 void cyhal_syspm_register_callback(cyhal_syspm_callback_data_t *callback_data)
492 {
493 CY_ASSERT(callback_data != NULL);
494 _cyhal_syspm_add_callback_to_list(&_cyhal_syspm_callback_ptr, callback_data);
495 }
496
cyhal_syspm_unregister_callback(cyhal_syspm_callback_data_t * callback_data)497 void cyhal_syspm_unregister_callback(cyhal_syspm_callback_data_t *callback_data)
498 {
499 CY_ASSERT(callback_data != NULL);
500 _cyhal_syspm_remove_callback_from_list(&_cyhal_syspm_callback_ptr, callback_data);
501 }
502
cyhal_syspm_lock_deepsleep(void)503 void cyhal_syspm_lock_deepsleep(void)
504 {
505 CY_ASSERT(_cyhal_deep_sleep_lock != USHRT_MAX);
506 uint32_t intr_status = cyhal_system_critical_section_enter();
507 _cyhal_deep_sleep_lock++;
508 cyhal_system_critical_section_exit(intr_status);
509 }
510
cyhal_syspm_unlock_deepsleep(void)511 void cyhal_syspm_unlock_deepsleep(void)
512 {
513 CY_ASSERT(_cyhal_deep_sleep_lock != 0U);
514 uint32_t intr_status = cyhal_system_critical_section_enter();
515 _cyhal_deep_sleep_lock--;
516 cyhal_system_critical_section_exit(intr_status);
517 }
518
cyhal_syspm_deepsleep(void)519 cy_rslt_t cyhal_syspm_deepsleep(void)
520 {
521 if(_cyhal_deep_sleep_lock != 0)
522 {
523 return CYHAL_SYSPM_RSLT_DEEPSLEEP_LOCKED;
524 }
525 return _cyhal_syspm_deepsleep_internal();
526 }
527
528
cyhal_syspm_tickless_sleep_deepsleep(cyhal_lptimer_t * obj,uint32_t desired_ms,uint32_t * actual_ms,bool deep_sleep)529 cy_rslt_t cyhal_syspm_tickless_sleep_deepsleep(cyhal_lptimer_t *obj, uint32_t desired_ms, uint32_t *actual_ms, bool deep_sleep)
530 {
531 cy_rslt_t result = CY_RSLT_SUCCESS;
532
533 if( (deep_sleep == true) && (_cyhal_deep_sleep_lock != 0))
534 {
535 return CYHAL_SYSPM_RSLT_DEEPSLEEP_LOCKED;
536 }
537
538 #if (CYHAL_DRIVER_AVAILABLE_LPTIMER != 0)
539 CY_ASSERT(obj != NULL);
540 uint32_t initial_ticks;
541 uint32_t sleep_ticks;
542 cyhal_lptimer_info_t timer_info;
543
544 *actual_ms = 0;
545
546 if(desired_ms > 0)
547 {
548 cyhal_lptimer_get_info(obj, &timer_info);
549
550 //lp_ticks = ms * lp_rate_khz
551 sleep_ticks = (uint32_t)(((uint64_t)(desired_ms - 1) * timer_info.frequency_hz) / _CYHAL_HZ_TO_KHZ_CONVERSION_FACTOR);
552
553 result = cyhal_lptimer_set_delay(obj, sleep_ticks);
554 initial_ticks = cyhal_lptimer_read(obj);
555 if(result == CY_RSLT_SUCCESS)
556 {
557 /* Disabling and enabling the system timer is handled in _cyhal_syspm_common_cb in order
558 * to prevent loosing kernel ticks when sleep/deep-sleep is rejected causing the time spent
559 * in the callback handlers to check if the system can make the sleep/deep-sleep transition
560 * to be not accounted for.
561 */
562 _cyhal_disable_systick_before_sleep_deepsleep = true;
563 cyhal_lptimer_enable_event(obj, CYHAL_LPTIMER_COMPARE_MATCH, CYHAL_ISR_PRIORITY_DEFAULT, true);
564
565 result = deep_sleep ? _cyhal_syspm_deepsleep_internal() : cyhal_syspm_sleep();
566
567 if(result == CY_RSLT_SUCCESS)
568 {
569 uint32_t final_ticks = cyhal_lptimer_read(obj);
570 uint32_t ticks = (final_ticks < initial_ticks)
571 ? (timer_info.max_counter_value - initial_ticks) + final_ticks
572 : final_ticks - initial_ticks;
573 *actual_ms = (uint32_t)(((uint64_t)ticks * _CYHAL_HZ_TO_KHZ_CONVERSION_FACTOR) / timer_info.frequency_hz);
574 }
575
576 cyhal_lptimer_enable_event(obj, CYHAL_LPTIMER_COMPARE_MATCH, CYHAL_ISR_PRIORITY_DEFAULT, false);
577 _cyhal_disable_systick_before_sleep_deepsleep = false;
578 }
579 }
580
581 #else
582 /* no lptimer available on currently selected device */
583 result = CYHAL_SYSPM_RSLT_ERR_NOT_SUPPORTED;
584 CY_UNUSED_PARAMETER(obj);
585 CY_UNUSED_PARAMETER(desired_ms);
586 CY_UNUSED_PARAMETER(actual_ms);
587 CY_UNUSED_PARAMETER(deep_sleep);
588 #endif /* (CYHAL_DRIVER_AVAILABLE_LPTIMER != 0) */
589
590 return result;
591 }
592
593
cyhal_syspm_set_supply_voltage(cyhal_syspm_voltage_supply_t supply,uint32_t mvolts)594 void cyhal_syspm_set_supply_voltage(cyhal_syspm_voltage_supply_t supply, uint32_t mvolts)
595 {
596 CY_ASSERT((size_t)supply <= CYHAL_VOLTAGE_SUPPLY_MAX);
597 _cyhal_syspm_supply_voltages[(size_t)supply] = mvolts;
598 }
599
cyhal_syspm_get_supply_voltage(cyhal_syspm_voltage_supply_t supply)600 uint32_t cyhal_syspm_get_supply_voltage(cyhal_syspm_voltage_supply_t supply)
601 {
602 CY_ASSERT((size_t)supply <= CYHAL_VOLTAGE_SUPPLY_MAX);
603 return _cyhal_syspm_supply_voltages[(size_t)supply];
604 }
605
606 #if defined(__cplusplus)
607 }
608 #endif
609
610 #endif // CYHAL_DRIVER_AVAILABLE_SYSPM
611