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 
128 // This code will only run on CAT1A if ULP variant has not been set, or we are targeting S40E with HT mode.
129 #if (defined(COMPONENT_CAT1A) && !(defined(SRSS_ULP_VARIANT) && (SRSS_ULP_VARIANT == 0u)))
130 static cy_stc_syspm_callback_t _cyhal_syspm_lp;
131 static cy_stc_syspm_callback_t _cyhal_syspm_normal;
132 #elif defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1D)
133 static cy_stc_syspm_callback_t _cyhal_syspm_lp;
134 static cy_stc_syspm_callback_t _cyhal_syspm_normal;
135 static cy_stc_syspm_callback_t _cyhal_syspm_deepsleep_ram;
136 static cy_stc_syspm_callback_t _cyhal_syspm_deepsleep_off;
137 #endif /* defined(COMPONENT_CAT1A)  && !(defined(SRSS_ULP_VARIANT) && (SRSS_ULP_VARIANT == 0u)))*/
138 
_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)139 static cyhal_syspm_callback_data_t* _cyhal_syspm_call_all_pm_callbacks(
140     cyhal_syspm_callback_data_t* entry, bool* allow, cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode)
141 {
142     while(entry != CYHAL_SYSPM_END_OF_LIST)
143     {
144         if (entry->callback != NULL &&
145             (entry->states & state) == state &&
146             (entry->ignore_modes & mode) != mode)
147         {
148             *allow = entry->callback(state, mode, entry->args) || mode != CYHAL_SYSPM_CHECK_READY;
149             if (!(*allow))
150             {
151                 // Do not increment pointer so that backtracking stop at the correct location
152                 break;
153             }
154         }
155         entry = entry->next;
156     }
157     return entry;
158 }
159 
_cyhal_syspm_backtrack_all_pm_callbacks(cyhal_syspm_callback_data_t * start,cyhal_syspm_callback_data_t * end,cyhal_syspm_callback_state_t state)160 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)
161 {
162     while(start != end)
163     {
164         if (start->callback != NULL &&
165             (start->states & state) == state &&
166             (start->ignore_modes & CYHAL_SYSPM_CHECK_FAIL) != CYHAL_SYSPM_CHECK_FAIL)
167         {
168             start->callback(state, CYHAL_SYSPM_CHECK_FAIL, start->args);
169         }
170         start = start->next;
171     }
172 }
173 
_cyhal_syspm_common_cb(cy_en_syspm_callback_mode_t mode,cyhal_syspm_callback_state_t state)174 static cy_en_syspm_status_t _cyhal_syspm_common_cb(cy_en_syspm_callback_mode_t mode, cyhal_syspm_callback_state_t state)
175 {
176     // The PDL function that wrap around this callback enters critical section, this function does not need to enter critical section.
177     cyhal_syspm_callback_mode_t hal_mode = _cyhal_utils_convert_pdltohal_pm_mode(mode);
178     bool allow = true;
179 
180     cyhal_syspm_callback_data_t *first, *second;
181     if (hal_mode == CYHAL_SYSPM_CHECK_FAIL || hal_mode == CYHAL_SYSPM_AFTER_TRANSITION || hal_mode == CYHAL_SYSPM_AFTER_DS_WFI_TRANSITION)
182     {
183         first = _cyhal_syspm_peripheral_callback_ptr;
184         second = _cyhal_syspm_callback_ptr;
185     }
186     else
187     {
188         second = _cyhal_syspm_peripheral_callback_ptr;
189         first = _cyhal_syspm_callback_ptr;
190     }
191 
192     cyhal_syspm_callback_data_t* first_current = _cyhal_syspm_call_all_pm_callbacks(first, &allow, state, hal_mode);
193     cyhal_syspm_callback_data_t* second_current = allow
194         ? _cyhal_syspm_call_all_pm_callbacks(second, &allow, state, hal_mode)
195         : second;
196 
197     if (!allow && (CYHAL_SYSPM_CHECK_READY == hal_mode))
198     {
199         _cyhal_syspm_backtrack_all_pm_callbacks(second, second_current, state);
200         _cyhal_syspm_backtrack_all_pm_callbacks(first, first_current, state);
201     }
202 
203     return allow ? CY_SYSPM_SUCCESS : CY_SYSPM_FAIL;
204 }
205 
_cyhal_syspm_cb_sleep_deepsleep(cy_en_syspm_callback_mode_t mode,cyhal_syspm_callback_state_t state)206 static cy_en_syspm_status_t _cyhal_syspm_cb_sleep_deepsleep(cy_en_syspm_callback_mode_t mode, cyhal_syspm_callback_state_t state)
207 {
208     cy_en_syspm_status_t status = _cyhal_syspm_common_cb(mode, state);
209     // No need to test status here, as it only gets set when mode == CYHAL_SYSPM_CHECK_READY
210     if (mode == CY_SYSPM_BEFORE_TRANSITION)
211     {
212         _cyhal_systick_disable = _cyhal_syspm_is_systick_enabled() && _cyhal_disable_systick_before_sleep_deepsleep;
213         if (_cyhal_systick_disable)
214         {
215             _cyhal_syspm_disable_systick();
216         }
217     }
218     else if (mode == CY_SYSPM_AFTER_TRANSITION)
219     {
220         if (_cyhal_systick_disable)
221         {
222             _cyhal_syspm_enable_systick();
223         }
224     }
225     return status;
226 }
227 
_cyhal_syspm_cb_sleep(cy_stc_syspm_callback_params_t * callback_params,cy_en_syspm_callback_mode_t mode)228 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)
229 {
230     CY_UNUSED_PARAMETER(callback_params);
231     return _cyhal_syspm_cb_sleep_deepsleep(mode, CYHAL_SYSPM_CB_CPU_SLEEP);
232 }
_cyhal_syspm_cb_deepsleep(cy_stc_syspm_callback_params_t * callback_params,cy_en_syspm_callback_mode_t mode)233 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)
234 {
235     if((mode == CY_SYSPM_CHECK_READY) && (_cyhal_deep_sleep_lock != 0))
236     {
237         return CY_SYSPM_FAIL;
238     }
239     CY_UNUSED_PARAMETER(callback_params);
240     return _cyhal_syspm_cb_sleep_deepsleep(mode, CYHAL_SYSPM_CB_CPU_DEEPSLEEP);
241 }
_cyhal_syspm_cb_hibernate(cy_stc_syspm_callback_params_t * callback_params,cy_en_syspm_callback_mode_t mode)242 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)
243 {
244     CY_UNUSED_PARAMETER(callback_params);
245     return _cyhal_syspm_common_cb(mode, CYHAL_SYSPM_CB_SYSTEM_HIBERNATE);
246 }
247 #if (defined(COMPONENT_CAT1A) && !(defined(SRSS_ULP_VARIANT) && (SRSS_ULP_VARIANT == 0u))) || 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)248 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)
249 {
250     CY_UNUSED_PARAMETER(callback_params);
251     cy_en_syspm_status_t status = _cyhal_syspm_common_cb(mode, CYHAL_SYSPM_CB_SYSTEM_NORMAL);
252 
253 #if defined(COMPONENT_CAT1A)
254     if (mode == CY_SYSPM_AFTER_TRANSITION)
255     {
256         uint32_t hfclk_freq_mhz = Cy_SysClk_ClkHfGetFrequency(0) / 1000000;
257         Cy_SysLib_SetWaitStates(false, hfclk_freq_mhz);
258     }
259 #endif /* defined(COMPONENT_CAT1A) */
260     return status;
261 }
_cyhal_syspm_cb_lp(cy_stc_syspm_callback_params_t * callback_params,cy_en_syspm_callback_mode_t mode)262 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)
263 {
264     CY_UNUSED_PARAMETER(callback_params);
265     cy_en_syspm_status_t status = _cyhal_syspm_common_cb(mode, CYHAL_SYSPM_CB_SYSTEM_LOW);
266 
267     if (mode == CY_SYSPM_BEFORE_TRANSITION)
268     {
269         uint32_t hfclk_freq_mhz = Cy_SysClk_ClkHfGetFrequency(0) / 1000000;
270         Cy_SysLib_SetWaitStates(true, hfclk_freq_mhz);
271     }
272     return status;
273 }
274 #endif  /* defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1D) */
275 #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)276 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)
277 {
278     CY_UNUSED_PARAMETER(callback_params);
279     if ((mode == CY_SYSPM_CHECK_READY) && (_cyhal_deep_sleep_lock != 0))
280     {
281         return CY_SYSPM_FAIL;
282     }
283     return _cyhal_syspm_common_cb(mode, CYHAL_SYSPM_CB_CPU_DEEPSLEEP_RAM);
284 }
_cyhal_syspm_cb_deepsleep_off(cy_stc_syspm_callback_params_t * callback_params,cy_en_syspm_callback_mode_t mode)285 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)
286 {
287     CY_UNUSED_PARAMETER(callback_params);
288     return _cyhal_syspm_common_cb(mode, CYHAL_SYSPM_CB_CPU_DEEPSLEEP/*_OFF*/);
289 }
290 #endif
291 
_cyhal_syspm_is_registered(cyhal_syspm_callback_data_t * callback)292 static inline bool _cyhal_syspm_is_registered(cyhal_syspm_callback_data_t *callback)
293 {
294     // If callback->next is NULL it must not be registered since all registered
295     // next ptrs in the list must point to the next callback or be equal to
296     // CYHAL_SYSPM_END_OF_LIST
297     return (callback->next != NULL);
298 }
299 
_cyhal_syspm_add_callback_to_list(cyhal_syspm_callback_data_t ** list,cyhal_syspm_callback_data_t * add)300 static void _cyhal_syspm_add_callback_to_list(cyhal_syspm_callback_data_t **list, cyhal_syspm_callback_data_t *add)
301 {
302     uint32_t intr_status = cyhal_system_critical_section_enter();
303     if(!_cyhal_syspm_is_registered(add))
304     {
305         add->next = *list;
306         *list = add;
307     }
308     cyhal_system_critical_section_exit(intr_status);
309 }
310 
_cyhal_syspm_remove_callback_from_list(cyhal_syspm_callback_data_t ** list,cyhal_syspm_callback_data_t * rmv)311 static void _cyhal_syspm_remove_callback_from_list(cyhal_syspm_callback_data_t **list, cyhal_syspm_callback_data_t *rmv)
312 {
313     uint32_t intr_status = cyhal_system_critical_section_enter();
314     while(*list != CYHAL_SYSPM_END_OF_LIST)
315     {
316         if (*list == rmv)
317         {
318             *list = rmv->next;
319             rmv->next = NULL;
320             break;
321         }
322         list = &((*list)->next);
323     }
324     cyhal_system_critical_section_exit(intr_status);
325 }
326 
_cyhal_syspm_register_peripheral_callback(cyhal_syspm_callback_data_t * callback_data)327 void _cyhal_syspm_register_peripheral_callback(cyhal_syspm_callback_data_t *callback_data)
328 {
329     CY_ASSERT(callback_data != NULL);
330     _cyhal_syspm_add_callback_to_list(&_cyhal_syspm_peripheral_callback_ptr, callback_data);
331 }
332 
_cyhal_syspm_unregister_peripheral_callback(cyhal_syspm_callback_data_t * callback_data)333 void _cyhal_syspm_unregister_peripheral_callback(cyhal_syspm_callback_data_t *callback_data)
334 {
335     CY_ASSERT(callback_data != NULL);
336     _cyhal_syspm_remove_callback_from_list(&_cyhal_syspm_peripheral_callback_ptr, callback_data);
337 }
338 
_cyhal_syspm_register_cb(cy_stc_syspm_callback_t * data,cy_en_syspm_callback_type_t type,Cy_SysPmCallback callback)339 static bool _cyhal_syspm_register_cb(cy_stc_syspm_callback_t *data, cy_en_syspm_callback_type_t type, Cy_SysPmCallback callback)
340 {
341     memcpy(data, &_cyhal_syspm_cb_default, sizeof(cy_stc_syspm_callback_t));
342     data->callback = callback;
343     data->type = type;
344     return Cy_SysPm_RegisterCallback(data);
345 }
346 
347 
348 
_cyhal_syspm_deepsleep_internal(void)349 static cy_rslt_t _cyhal_syspm_deepsleep_internal(void)
350 {
351 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
352     return Cy_SysPm_CpuEnterDeepSleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
353 #elif defined(COMPONENT_CAT2)
354     return Cy_SysPm_CpuEnterDeepSleep();
355 #endif
356 
357 }
358 
359 /******************************************************************************
360  ******************************** Public APIs *********************************
361  *****************************************************************************/
362 
cyhal_syspm_init(void)363 cy_rslt_t cyhal_syspm_init(void)
364 {
365 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
366     /* Check the IO status. If current status is frozen, unfreeze the system. */
367     if (Cy_SysPm_GetIoFreezeStatus())
368     {
369         /* Unfreeze the system */
370         Cy_SysPm_IoUnfreeze();
371     }
372 
373 #endif /* defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D) */
374 
375     cy_rslt_t rslt = CY_RSLT_SUCCESS;
376     if (!_cyhal_syspm_register_cb(&_cyhal_syspm_sleep, CY_SYSPM_SLEEP, _cyhal_syspm_cb_sleep)
377         || !_cyhal_syspm_register_cb(&_cyhal_syspm_deepsleep, CY_SYSPM_DEEPSLEEP, _cyhal_syspm_cb_deepsleep)
378         || !_cyhal_syspm_register_cb(&_cyhal_syspm_hibernate, CY_SYSPM_HIBERNATE, _cyhal_syspm_cb_hibernate)
379     #if (defined(COMPONENT_CAT1A) && !(defined(SRSS_ULP_VARIANT) && (SRSS_ULP_VARIANT == 0u))) || defined(COMPONENT_CAT1D)
380         || !_cyhal_syspm_register_cb(&_cyhal_syspm_normal, CY_SYSPM_LP, _cyhal_syspm_cb_normal)
381         || !_cyhal_syspm_register_cb(&_cyhal_syspm_lp, CY_SYSPM_ULP, _cyhal_syspm_cb_lp)
382     #endif /* defined(COMPONENT_CAT1A) */
383     #if defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1D)
384         #if defined(COMPONENT_CAT1B)
385         || !_cyhal_syspm_register_cb(&_cyhal_syspm_lp, CY_SYSPM_LPACTIVE_ENTER, _cyhal_syspm_cb_lp)
386         || !_cyhal_syspm_register_cb(&_cyhal_syspm_normal, CY_SYSPM_LPACTIVE_EXIT, _cyhal_syspm_cb_normal)
387         #endif /* defined(COMPONENT_CAT1B) */
388         || !_cyhal_syspm_register_cb(&_cyhal_syspm_deepsleep_ram, CY_SYSPM_DEEPSLEEP_RAM, _cyhal_syspm_cb_deepsleep_ram)
389         || !_cyhal_syspm_register_cb(&_cyhal_syspm_deepsleep_off, CY_SYSPM_DEEPSLEEP_OFF, _cyhal_syspm_cb_deepsleep_off)
390     #endif /* defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1D) */
391     )
392         {
393             rslt = CYHAL_SYSPM_RSLT_INIT_ERROR;
394         }
395 
396     return rslt;
397 }
398 
cyhal_syspm_hibernate(cyhal_syspm_hibernate_source_t wakeup_source)399 cy_rslt_t cyhal_syspm_hibernate(cyhal_syspm_hibernate_source_t wakeup_source)
400 {
401     cy_rslt_t result = CYHAL_SYSPM_RSLT_ERR_NOT_SUPPORTED;
402 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
403     /* Defines for mapping hal hibernate sources to pdl */
404     static const uint32_t source_map[] =
405     {
406         0u,                                        // Default value, no wakeup
407         (uint32_t)CY_SYSPM_HIBERNATE_LPCOMP0_LOW,  // CYHAL_SYSPM_HIBERNATE_LPCOMP0_LOW
408         (uint32_t)CY_SYSPM_HIBERNATE_LPCOMP0_HIGH, // CYHAL_SYSPM_HIBERNATE_LPCOMP0_HIGH
409         (uint32_t)CY_SYSPM_HIBERNATE_LPCOMP1_LOW,  // CYHAL_SYSPM_HIBERNATE_LPCOMP1_LOW
410         (uint32_t)CY_SYSPM_HIBERNATE_LPCOMP1_HIGH, // CYHAL_SYSPM_HIBERNATE_LPCOMP1_HIGH
411         (uint32_t)CY_SYSPM_HIBERNATE_RTC_ALARM,    // CYHAL_SYSPM_HIBERNATE_RTC_ALARM
412         (uint32_t)CY_SYSPM_HIBERNATE_WDT,          // CYHAL_SYSPM_HIBERNATE_WDT
413         (uint32_t)CY_SYSPM_HIBERNATE_PIN0_LOW,     // CYHAL_SYSPM_HIBERNATE_PINA_LOW
414         (uint32_t)CY_SYSPM_HIBERNATE_PIN0_HIGH,    // CYHAL_SYSPM_HIBERNATE_PINA_HIGH
415         (uint32_t)CY_SYSPM_HIBERNATE_PIN1_LOW,     // CYHAL_SYSPM_HIBERNATE_PINB_LOW
416         (uint32_t)CY_SYSPM_HIBERNATE_PIN1_HIGH,    // CYHAL_SYSPM_HIBERNATE_PINB_HIGH
417     };
418 
419     Cy_SysPm_SetHibernateWakeupSource(_cyhal_utils_convert_flags(source_map, sizeof(source_map) / sizeof(uint32_t), (uint32_t)wakeup_source));
420     result = Cy_SysPm_SystemEnterHibernate();
421 #elif defined(COMPONENT_CAT2)
422     CY_UNUSED_PARAMETER(wakeup_source);
423     result = CYHAL_SYSPM_RSLT_ERR_NOT_SUPPORTED;
424 #endif /* defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D) */
425     return result;
426 }
427 
cyhal_syspm_set_system_state(cyhal_syspm_system_state_t state)428 cy_rslt_t cyhal_syspm_set_system_state(cyhal_syspm_system_state_t state)
429 {
430 #if defined(COMPONENT_CAT2) || defined(COMPONENT_CAT1C) || (defined(SRSS_ULP_VARIANT) && (SRSS_ULP_VARIANT == 0u))
431     CY_UNUSED_PARAMETER(state);
432     return CYHAL_SYSPM_RSLT_ERR_NOT_SUPPORTED;
433 #else
434     cy_rslt_t rslt;
435 
436     /* The wait states are changed in the common syspm handler after
437      * state change is allowed and all handlers are called to take into
438      * account any frequency change that might happen as a part of the
439      * power management handlers
440      */
441     switch (state)
442     {
443         case CYHAL_SYSPM_SYSTEM_NORMAL:
444 #if defined(CY_IP_MXS40SSRSS)
445             rslt = Cy_SysPm_SystemLpActiveExit();
446 #else
447             rslt = Cy_SysPm_SystemEnterLp();
448 #endif
449             break;
450         case CYHAL_SYSPM_SYSTEM_LOW:
451 #if defined(CY_IP_MXS40SSRSS)
452             rslt = Cy_SysPm_SystemLpActiveEnter();
453 #else
454             rslt = Cy_SysPm_SystemEnterUlp();
455 #endif
456             break;
457         default:
458             /* Should never get here */
459             CY_ASSERT(false);
460             rslt = CYHAL_SYSPM_RSLT_BAD_ARGUMENT;
461             break;
462     }
463     return rslt;
464 #endif /* defined(COMPONENT_CAT2) */
465 }
466 
cyhal_syspm_register_callback(cyhal_syspm_callback_data_t * callback_data)467 void cyhal_syspm_register_callback(cyhal_syspm_callback_data_t *callback_data)
468 {
469     CY_ASSERT(callback_data != NULL);
470     _cyhal_syspm_add_callback_to_list(&_cyhal_syspm_callback_ptr, callback_data);
471 }
472 
cyhal_syspm_unregister_callback(cyhal_syspm_callback_data_t * callback_data)473 void cyhal_syspm_unregister_callback(cyhal_syspm_callback_data_t *callback_data)
474 {
475     CY_ASSERT(callback_data != NULL);
476     _cyhal_syspm_remove_callback_from_list(&_cyhal_syspm_callback_ptr, callback_data);
477 }
478 
cyhal_syspm_lock_deepsleep(void)479 void cyhal_syspm_lock_deepsleep(void)
480 {
481     CY_ASSERT(_cyhal_deep_sleep_lock != USHRT_MAX);
482     uint32_t intr_status = cyhal_system_critical_section_enter();
483     _cyhal_deep_sleep_lock++;
484     cyhal_system_critical_section_exit(intr_status);
485 }
486 
cyhal_syspm_unlock_deepsleep(void)487 void cyhal_syspm_unlock_deepsleep(void)
488 {
489     CY_ASSERT(_cyhal_deep_sleep_lock != 0U);
490     uint32_t intr_status = cyhal_system_critical_section_enter();
491     _cyhal_deep_sleep_lock--;
492     cyhal_system_critical_section_exit(intr_status);
493 }
494 
cyhal_syspm_deepsleep(void)495 cy_rslt_t cyhal_syspm_deepsleep(void)
496 {
497     if(_cyhal_deep_sleep_lock != 0)
498     {
499         return CYHAL_SYSPM_RSLT_DEEPSLEEP_LOCKED;
500     }
501     return _cyhal_syspm_deepsleep_internal();
502 }
503 
504 
cyhal_syspm_tickless_sleep_deepsleep(cyhal_lptimer_t * obj,uint32_t desired_ms,uint32_t * actual_ms,bool deep_sleep)505 cy_rslt_t cyhal_syspm_tickless_sleep_deepsleep(cyhal_lptimer_t *obj, uint32_t desired_ms, uint32_t *actual_ms, bool deep_sleep)
506 {
507     cy_rslt_t result = CY_RSLT_SUCCESS;
508 
509     if( (deep_sleep == true) && (_cyhal_deep_sleep_lock != 0))
510     {
511         return CYHAL_SYSPM_RSLT_DEEPSLEEP_LOCKED;
512     }
513 
514     #if (CYHAL_DRIVER_AVAILABLE_LPTIMER != 0)
515     CY_ASSERT(obj != NULL);
516     uint32_t initial_ticks;
517     uint32_t sleep_ticks;
518     cyhal_lptimer_info_t timer_info;
519 
520     *actual_ms = 0;
521 
522     if(desired_ms > 1)
523     {
524         cyhal_lptimer_get_info(obj, &timer_info);
525 
526         //lp_ticks = ms * lp_rate_khz
527         sleep_ticks = (uint32_t)(((uint64_t)(desired_ms - 1) * timer_info.frequency_hz) / _CYHAL_HZ_TO_KHZ_CONVERSION_FACTOR);
528 
529         result = cyhal_lptimer_set_delay(obj, sleep_ticks);
530         initial_ticks = cyhal_lptimer_read(obj);
531         if(result == CY_RSLT_SUCCESS)
532         {
533             /* Disabling and enabling the system timer is handled in _cyhal_syspm_common_cb in order
534              * to prevent loosing kernel ticks when sleep/deep-sleep is rejected causing the time spent
535              * in the callback handlers to check if the system can make the sleep/deep-sleep transition
536              * to be not accounted for.
537              */
538             _cyhal_disable_systick_before_sleep_deepsleep = true;
539             cyhal_lptimer_enable_event(obj, CYHAL_LPTIMER_COMPARE_MATCH, CYHAL_ISR_PRIORITY_DEFAULT, true);
540 
541             result = deep_sleep ? _cyhal_syspm_deepsleep_internal() : cyhal_syspm_sleep();
542 
543             if(result == CY_RSLT_SUCCESS)
544             {
545                 uint32_t final_ticks = cyhal_lptimer_read(obj);
546                 uint32_t ticks = (final_ticks < initial_ticks)
547                                 ? (timer_info.max_counter_value - initial_ticks) + final_ticks
548                                 : final_ticks - initial_ticks;
549                 *actual_ms = (uint32_t)(((uint64_t)ticks * _CYHAL_HZ_TO_KHZ_CONVERSION_FACTOR) / timer_info.frequency_hz);
550             }
551 
552             cyhal_lptimer_enable_event(obj, CYHAL_LPTIMER_COMPARE_MATCH, CYHAL_ISR_PRIORITY_DEFAULT, false);
553             _cyhal_disable_systick_before_sleep_deepsleep = false;
554         }
555     }
556 
557     #else
558     /* no lptimer available on currently selected device */
559     result = CYHAL_SYSPM_RSLT_ERR_NOT_SUPPORTED;
560     CY_UNUSED_PARAMETER(obj);
561     CY_UNUSED_PARAMETER(desired_ms);
562     CY_UNUSED_PARAMETER(actual_ms);
563     CY_UNUSED_PARAMETER(deep_sleep);
564     #endif /* (CYHAL_DRIVER_AVAILABLE_LPTIMER != 0) */
565 
566     return result;
567 }
568 
cyhal_syspm_get_deepsleep_mode(void)569 cyhal_syspm_system_deep_sleep_mode_t cyhal_syspm_get_deepsleep_mode (void)
570 {
571     cyhal_syspm_system_deep_sleep_mode_t deep_sleep_mode = CYHAL_SYSPM_SYSTEM_DEEPSLEEP;
572 
573     #if defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1D)
574     cy_en_syspm_deep_sleep_mode_t mode = Cy_SysPm_GetDeepSleepMode();
575     switch (mode)
576     {
577         case CY_SYSPM_MODE_DEEPSLEEP:
578             deep_sleep_mode = CYHAL_SYSPM_SYSTEM_DEEPSLEEP;
579             break;
580         case CY_SYSPM_MODE_DEEPSLEEP_RAM:
581             deep_sleep_mode = CYHAL_SYSPM_SYSTEM_DEEPSLEEP_RAM;
582             break;
583         case CY_SYSPM_MODE_DEEPSLEEP_OFF:
584             deep_sleep_mode = CYHAL_SYSPM_SYSTEM_DEEPSLEEP_OFF;
585             break;
586         case CY_SYSPM_MODE_DEEPSLEEP_NONE:
587             deep_sleep_mode = CYHAL_SYSPM_SYSTEM_DEEPSLEEP_NONE;
588             break;
589         default:
590             deep_sleep_mode = CYHAL_SYSPM_SYSTEM_DEEPSLEEP_NONE;
591             break;
592     }
593     #endif /* defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1D) */
594 
595     return deep_sleep_mode;
596 }
597 
598 
cyhal_syspm_set_supply_voltage(cyhal_syspm_voltage_supply_t supply,uint32_t mvolts)599 void cyhal_syspm_set_supply_voltage(cyhal_syspm_voltage_supply_t supply, uint32_t mvolts)
600 {
601     CY_ASSERT((size_t)supply <= CYHAL_VOLTAGE_SUPPLY_MAX);
602     _cyhal_syspm_supply_voltages[(size_t)supply] = mvolts;
603 }
604 
cyhal_syspm_get_supply_voltage(cyhal_syspm_voltage_supply_t supply)605 uint32_t cyhal_syspm_get_supply_voltage(cyhal_syspm_voltage_supply_t supply)
606 {
607     CY_ASSERT((size_t)supply <= CYHAL_VOLTAGE_SUPPLY_MAX);
608     return _cyhal_syspm_supply_voltages[(size_t)supply];
609 }
610 
611 #if defined(__cplusplus)
612 }
613 #endif
614 
615 #endif // CYHAL_DRIVER_AVAILABLE_SYSPM
616