1 /***************************************************************************//**
2  * @file
3  * @brief Power Manager Internal API definition.
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 
31 #include "sl_power_manager.h"
32 #include "sl_slist.h"
33 #include "sl_code_classification.h"
34 
35 #if defined(SL_COMPONENT_CATALOG_PRESENT)
36 #include "sl_component_catalog.h"
37 #endif
38 
39 #if defined(SL_CATALOG_EMLIB_CORE_DEBUG_CONFIG_PRESENT)
40 #include "emlib_core_debug_config.h"
41 #endif
42 
43 #if !defined(SL_EMLIB_CORE_ENABLE_INTERRUPT_DISABLED_TIMING)
44 #define SL_EMLIB_CORE_ENABLE_INTERRUPT_DISABLED_TIMING   0
45 #endif
46 
47 #if (SL_EMLIB_CORE_ENABLE_INTERRUPT_DISABLED_TIMING == 1)
48 #include "sl_cycle_counter.h"
49 #endif
50 
51 #ifdef __cplusplus
52 extern "C" {
53 #endif
54 
55 /*******************************************************************************
56  *******************************   DEFINES   ***********************************
57  ******************************************************************************/
58 
59 #define SLI_POWER_MANAGER_EM_TABLE_SIZE  2
60 
61 #define SLI_POWER_MANAGER_EM4_ENTRY_WAIT_LOOPS 200
62 /*******************************************************************************
63  *****************************   DATA TYPES   *********************************
64  ******************************************************************************/
65 
66 // Debug entry
67 typedef struct {
68   sl_slist_node_t node;
69   const char *module_name;
70 } sli_power_debug_requirement_entry_t;
71 
72 /*******************************************************************************
73  *****************************   PROTOTYPES   **********************************
74  ******************************************************************************/
75 
76 void sli_power_manager_init_hardware(void);
77 
78 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_POWER_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
79 void sli_power_manager_apply_em(sl_power_manager_em_t em);
80 
81 void sli_power_manager_debug_init(void);
82 
83 #if !defined(SL_CATALOG_POWER_MANAGER_NO_DEEPSLEEP_PRESENT)
84 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_POWER_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
85 void sli_power_manager_save_states(void);
86 
87 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_POWER_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
88 void sli_power_manager_handle_pre_deepsleep_operations(void);
89 
90 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_POWER_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
91 void sli_power_manager_restore_high_freq_accuracy_clk(void);
92 
93 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_POWER_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
94 bool sli_power_manager_is_high_freq_accuracy_clk_ready(bool wait);
95 
96 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_POWER_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
97 void sli_power_manager_restore_states(void);
98 
99 /*******************************************************************************
100  * Converts microseconds time in sleeptimer ticks.
101  ******************************************************************************/
102 uint32_t sli_power_manager_convert_delay_us_to_tick(uint32_t time_us);
103 
104 /*******************************************************************************
105  * Returns the default minimum offtime for xtal high frequency oscillator.
106  ******************************************************************************/
107 uint32_t sli_power_manager_get_default_high_frequency_minimum_offtime(void);
108 
109 /*******************************************************************************
110  * Restores the Low Frequency clocks according to which LF oscillators are used.
111  ******************************************************************************/
112 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_POWER_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
113 void sli_power_manager_low_frequency_restore(void);
114 
115 /***************************************************************************//**
116  * Informs the power manager if the high accuracy/high frequency clock
117  * is used, prior to scheduling an early clock restore.
118  *
119  * @return true if HFXO is used, else false.
120  ******************************************************************************/
121 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_POWER_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
122 bool sli_power_manager_is_high_freq_accuracy_clk_used(void);
123 #endif
124 
125 /*******************************************************************************
126  * Gets the delay associated the wake-up process from EM23.
127  *
128  * @return Delay for the complete wake-up process with full restore.
129  ******************************************************************************/
130 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_POWER_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
131 uint32_t sli_power_manager_get_wakeup_process_time_overhead(void);
132 
133 #if !defined(SL_CATALOG_POWER_MANAGER_NO_DEEPSLEEP_PRESENT)
134 /*******************************************************************************
135  * Gets the status of power manager variable is_sleeping_waiting_for_clock_restore.
136  *
137  * @return true if Power Manager is sleeping waiting for clock restore, else false.
138  *
139  * @note FOR INTERNAL USE ONLY.
140  ******************************************************************************/
141 bool sli_power_manager_get_clock_restore_status(void);
142 #endif
143 
144 #if defined(SL_CATALOG_POWER_MANAGER_NO_DEEPSLEEP_PRESENT)
145 /*******************************************************************************
146  * HAL hook function for pre EM1HCLKDIV sleep.
147  *
148  * @note FOR INTERNAL USE ONLY.
149  ******************************************************************************/
150 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_POWER_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
151 void sli_power_manager_em1hclkdiv_presleep_operations(void);
152 
153 /*******************************************************************************
154  * HAL hook function for post EM1HCLKDIV sleep.
155  *
156  * @note FOR INTERNAL USE ONLY.
157  ******************************************************************************/
158 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_POWER_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
159 void sli_power_manager_em1hclkdiv_postsleep_operations(void);
160 #endif
161 
162 #ifdef __cplusplus
163 }
164 #endif
165