1 /*
2  * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <sys/param.h>
10 #include <esp_types.h>
11 #include "sdkconfig.h"
12 #include "esp_err.h"
13 #include "esp_attr.h"
14 #include "soc/soc.h"
15 #include "soc/rtc.h"
16 #include "soc/pmu_struct.h"
17 #include "hal/lp_aon_hal.h"
18 #include "esp_private/esp_pmu.h"
19 #include "pmu_param.h"
20 #include "hal/efuse_ll.h"
21 #include "hal/efuse_hal.h"
22 #include "esp_hw_log.h"
23 #include "soc/regi2c_bias.h"
24 #include "regi2c_ctrl.h"
25 
26 static __attribute__((unused)) const char *TAG = "pmu_sleep";
27 
28 #define HP(state)   (PMU_MODE_HP_ ## state)
29 #define LP(state)   (PMU_MODE_LP_ ## state)
30 
get_slp_lp_dbias(void)31 uint32_t get_slp_lp_dbias(void)
32 {
33     /* pmu_lp_dbias_sleep_0v7 is read from efuse to ensure that the HP_LDO_voltage is close to 0.68V,
34     ** and the LP_LDO_voltage is close to 0.73V
35     */
36     uint32_t pmu_lp_dbias_sleep_0v7 = PMU_LP_DBIAS_SLEEP_0V7_DEFAULT;
37     unsigned blk_version = efuse_hal_blk_version();
38     if (blk_version >= 3) {
39         pmu_lp_dbias_sleep_0v7 = efuse_ll_get_dslp_dbias();
40         if (pmu_lp_dbias_sleep_0v7 == 0) {
41             pmu_lp_dbias_sleep_0v7 = PMU_LP_DBIAS_SLEEP_0V7_DEFAULT;
42             ESP_HW_LOGD(TAG, "slp dbias not burnt in efuse or wrong value was burnt in blk version: %d\n", blk_version);
43         }
44     } else {
45         ESP_HW_LOGD(TAG, "blk_version is less than 3, slp dbias not burnt in efuse\n");
46     }
47 
48     return pmu_lp_dbias_sleep_0v7;
49 }
50 
pmu_sleep_enable_regdma_backup(void)51 void pmu_sleep_enable_regdma_backup(void)
52 {
53     assert(PMU_instance()->hal);
54     /* entry 0, 1, 2 is used by pmu HP_SLEEP and HP_ACTIVE, HP_SLEEP
55         * and HP_MODEM or HP_MODEM and HP_ACTIVE states switching,
56         * respectively. entry 3 is reserved, not used yet! */
57     pmu_hal_hp_set_sleep_active_backup_enable(PMU_instance()->hal);
58 }
59 
pmu_sleep_disable_regdma_backup(void)60 void pmu_sleep_disable_regdma_backup(void)
61 {
62     assert(PMU_instance()->hal);
63     pmu_hal_hp_set_sleep_active_backup_disable(PMU_instance()->hal);
64 }
65 
pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags,uint32_t slowclk_period,uint32_t fastclk_period)66 uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period)
67 {
68     pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
69 
70     /* LP core hardware wait time, microsecond */
71     const int lp_clk_switch_time_us         = rtc_time_slowclk_to_us(mc->lp.clk_switch_cycle, slowclk_period);
72     const int lp_clk_power_on_wait_time_us  = (pd_flags & PMU_SLEEP_PD_XTAL) ? mc->lp.xtal_wait_stable_time_us \
73                             : rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period);
74 
75     const int lp_hw_wait_time_us = mc->lp.min_slp_time_us + mc->lp.analog_wait_time_us + lp_clk_power_on_wait_time_us \
76                             + lp_clk_switch_time_us + mc->lp.power_supply_wait_time_us + mc->lp.power_up_wait_time_us;
77 
78     /* HP core hardware wait time, microsecond */
79     const int hp_digital_power_up_wait_time_us = mc->hp.power_supply_wait_time_us + mc->hp.power_up_wait_time_us;
80     if (pd_flags & PMU_SLEEP_PD_TOP) {
81         mc->hp.regdma_s2a_work_time_us = PMU_REGDMA_S2A_WORK_TIME_PD_TOP_US;
82     } else {
83         mc->hp.regdma_s2a_work_time_us = PMU_REGDMA_S2A_WORK_TIME_PU_TOP_US;
84     }
85     const int hp_regdma_wait_time_us = mc->hp.regdma_s2a_work_time_us;
86     const int hp_clock_wait_time_us = mc->hp.xtal_wait_stable_time_us + mc->hp.pll_wait_stable_time_us;
87 
88     const int hp_hw_wait_time_us = mc->hp.analog_wait_time_us + MAX(hp_digital_power_up_wait_time_us + hp_regdma_wait_time_us, hp_clock_wait_time_us);
89 
90     const int rf_on_protect_time_us = 0;
91     const int total_hw_wait_time_us = lp_hw_wait_time_us + hp_hw_wait_time_us;
92 
93     return total_hw_wait_time_us + rf_on_protect_time_us;
94 }
95 
96 #define rtc_time_us_to_fastclk(time_us, period)     rtc_time_us_to_slowclk((time_us), (period))
97 
pmu_sleep_param_config_default(pmu_sleep_param_config_t * param,pmu_sleep_power_config_t * power,const uint32_t pd_flags,const uint32_t adjustment,const uint32_t slowclk_period,const uint32_t fastclk_period)98 static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
99         pmu_sleep_param_config_t *param,
100         pmu_sleep_power_config_t *power, /* We'll use the runtime power parameter to determine some hardware parameters */
101         const uint32_t pd_flags,
102         const uint32_t adjustment,
103         const uint32_t slowclk_period,
104         const uint32_t fastclk_period
105     )
106 {
107     const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
108 
109     param->hp_sys.min_slp_slow_clk_cycle          = rtc_time_us_to_slowclk(mc->hp.min_slp_time_us, slowclk_period);
110     param->hp_sys.analog_wait_target_cycle        = rtc_time_us_to_fastclk(mc->hp.analog_wait_time_us, fastclk_period);
111     param->hp_sys.digital_power_supply_wait_cycle = rtc_time_us_to_fastclk(mc->hp.power_supply_wait_time_us, fastclk_period);
112     param->hp_sys.digital_power_up_wait_cycle     = rtc_time_us_to_fastclk(mc->hp.power_up_wait_time_us, fastclk_period);
113     param->hp_sys.pll_stable_wait_cycle           = rtc_time_us_to_fastclk(mc->hp.pll_wait_stable_time_us, fastclk_period);
114 
115     param->lp_sys.min_slp_slow_clk_cycle          = rtc_time_us_to_slowclk(mc->lp.min_slp_time_us, slowclk_period);
116     param->lp_sys.analog_wait_target_cycle        = rtc_time_us_to_slowclk(mc->lp.analog_wait_time_us, slowclk_period);
117     param->lp_sys.digital_power_supply_wait_cycle = rtc_time_us_to_fastclk(mc->lp.power_supply_wait_time_us, fastclk_period);
118     param->lp_sys.digital_power_up_wait_cycle     = rtc_time_us_to_fastclk(mc->lp.power_up_wait_time_us, fastclk_period);
119 
120     if (power->hp_sys.xtal.xpd_xtal) {
121         param->hp_lp.xtal_stable_wait_slow_clk_cycle = rtc_time_us_to_slowclk(mc->lp.xtal_wait_stable_time_us, slowclk_period);
122     } else {
123         param->hp_lp.xtal_stable_wait_cycle       = rtc_time_us_to_fastclk(mc->hp.xtal_wait_stable_time_us, fastclk_period);
124     }
125     return param;
126 }
127 
pmu_sleep_config_default(pmu_sleep_config_t * config,uint32_t pd_flags,uint32_t adjustment,uint32_t slowclk_period,uint32_t fastclk_period,bool dslp)128 const pmu_sleep_config_t* pmu_sleep_config_default(
129         pmu_sleep_config_t *config,
130         uint32_t pd_flags,
131         uint32_t adjustment,
132         uint32_t slowclk_period,
133         uint32_t fastclk_period,
134         bool dslp
135     )
136 {
137     pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags);
138 
139     uint32_t iram_pd_flags = 0;
140     iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G0) ? BIT(0) : 0;
141     iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G1) ? BIT(1) : 0;
142     iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G2) ? BIT(2) : 0;
143     iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G3) ? BIT(3) : 0;
144     config->power = power_default;
145 
146     pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags);
147     config->param = *pmu_sleep_param_config_default(&param_default, &power_default, pd_flags, adjustment, slowclk_period, fastclk_period);
148 
149     if (dslp) {
150         pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags);
151         analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_slp_lp_dbias();
152         config->analog = analog_default;
153     } else {
154         pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(pd_flags);
155         config->digital = digital_default;
156 
157         pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags);
158         analog_default.hp_sys.analog.dbias = PMU_HP_DBIAS_LIGHTSLEEP_0V6_DEFAULT;
159         analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_slp_lp_dbias();
160         if (!(pd_flags & PMU_SLEEP_PD_XTAL)){
161             analog_default.hp_sys.analog.xpd_trx = PMU_XPD_TRX_SLEEP_ON;
162             analog_default.hp_sys.analog.dbias = get_act_hp_dbias();
163             analog_default.hp_sys.analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
164             analog_default.hp_sys.analog.bias_sleep = PMU_BIASSLP_SLEEP_ON;
165 
166             analog_default.lp_sys[LP(SLEEP)].analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
167             analog_default.lp_sys[LP(SLEEP)].analog.bias_sleep = PMU_BIASSLP_SLEEP_ON;
168             analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_act_lp_dbias();
169         } else if (!(pd_flags & PMU_SLEEP_PD_RC_FAST)) {
170             analog_default.hp_sys.analog.dbias = get_act_hp_dbias();
171             analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_act_lp_dbias();
172         }
173         config->analog = analog_default;
174     }
175     return config;
176 }
177 
pmu_sleep_power_init(pmu_context_t * ctx,const pmu_sleep_power_config_t * power,bool dslp)178 static void pmu_sleep_power_init(pmu_context_t *ctx, const pmu_sleep_power_config_t *power, bool dslp)
179 {
180     pmu_ll_hp_set_dig_power(ctx->hal->dev, HP(SLEEP), power->hp_sys.dig_power.val);
181     pmu_ll_hp_set_clk_power(ctx->hal->dev, HP(SLEEP), power->hp_sys.clk_power.val);
182     pmu_ll_hp_set_xtal_xpd (ctx->hal->dev, HP(SLEEP), power->hp_sys.xtal.xpd_xtal);
183 
184     pmu_ll_lp_set_dig_power(ctx->hal->dev, LP(ACTIVE), power->lp_sys[LP(ACTIVE)].dig_power.val);
185     pmu_ll_lp_set_clk_power(ctx->hal->dev, LP(ACTIVE), power->lp_sys[LP(ACTIVE)].clk_power.val);
186 
187     pmu_ll_lp_set_dig_power(ctx->hal->dev, LP(SLEEP), power->lp_sys[LP(SLEEP)].dig_power.val);
188     pmu_ll_lp_set_clk_power(ctx->hal->dev, LP(SLEEP), power->lp_sys[LP(SLEEP)].clk_power.val);
189     pmu_ll_lp_set_xtal_xpd (ctx->hal->dev, LP(SLEEP), power->lp_sys[LP(SLEEP)].xtal.xpd_xtal);
190 }
191 
pmu_sleep_digital_init(pmu_context_t * ctx,const pmu_sleep_digital_config_t * dig)192 static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_config_t *dig)
193 {
194     pmu_ll_hp_set_dig_pad_slp_sel   (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
195 }
196 
pmu_sleep_analog_init(pmu_context_t * ctx,const pmu_sleep_analog_config_t * analog,bool dslp)197 static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_config_t *analog, bool dslp)
198 {
199     assert(ctx->hal);
200     pmu_ll_hp_set_current_power_off           (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.pd_cur);
201     pmu_ll_hp_set_bias_sleep_enable           (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.bias_sleep);
202     pmu_ll_hp_set_regulator_xpd               (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd);
203     pmu_ll_hp_set_regulator_dbias             (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias);
204     pmu_ll_hp_set_regulator_driver_bar        (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b);
205     pmu_ll_hp_set_trx_xpd                     (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd_trx);
206     pmu_ll_lp_set_current_power_off    (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur);
207     pmu_ll_lp_set_bias_sleep_enable    (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.bias_sleep);
208     pmu_ll_lp_set_regulator_slp_xpd    (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.slp_xpd);
209     pmu_ll_lp_set_regulator_xpd        (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.xpd);
210     pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.slp_dbias);
211     pmu_ll_lp_set_regulator_dbias      (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbias);
212     pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.drv_b);
213 }
214 
pmu_sleep_param_init(pmu_context_t * ctx,const pmu_sleep_param_config_t * param,bool dslp)215 static void pmu_sleep_param_init(pmu_context_t *ctx, const pmu_sleep_param_config_t *param, bool dslp)
216 {
217     assert(ctx->hal);
218     pmu_ll_hp_set_min_sleep_cycle(ctx->hal->dev, param->hp_sys.min_slp_slow_clk_cycle);
219     pmu_ll_lp_set_min_sleep_cycle(ctx->hal->dev, param->lp_sys.min_slp_slow_clk_cycle);
220 
221     pmu_ll_hp_set_analog_wait_target_cycle(ctx->hal->dev, param->hp_sys.analog_wait_target_cycle);
222     pmu_ll_lp_set_analog_wait_target_cycle(ctx->hal->dev, param->lp_sys.analog_wait_target_cycle);
223 
224     pmu_hal_hp_set_digital_power_up_wait_cycle(ctx->hal, param->hp_sys.digital_power_supply_wait_cycle, param->hp_sys.digital_power_up_wait_cycle);
225     pmu_hal_lp_set_digital_power_up_wait_cycle(ctx->hal, param->lp_sys.digital_power_supply_wait_cycle, param->lp_sys.digital_power_up_wait_cycle);
226 
227     pmu_ll_set_xtal_stable_wait_cycle(ctx->hal->dev, param->hp_lp.xtal_stable_wait_slow_clk_cycle);
228     pmu_ll_set_pll_stable_wait_cycle(ctx->hal->dev, param->hp_sys.pll_stable_wait_cycle);
229 }
230 
pmu_sleep_init(const pmu_sleep_config_t * config,bool dslp)231 void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp)
232 {
233     assert(PMU_instance());
234     pmu_sleep_power_init(PMU_instance(), &config->power, dslp);
235     if (!dslp) {
236         pmu_sleep_digital_init(PMU_instance(), &config->digital);
237     }
238     pmu_sleep_analog_init(PMU_instance(), &config->analog, dslp);
239     pmu_sleep_param_init(PMU_instance(), &config->param, dslp);
240 }
241 
pmu_sleep_start(uint32_t wakeup_opt,uint32_t reject_opt,uint32_t lslp_mem_inf_fpu,bool dslp)242 uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
243 {
244     assert(PMU_instance()->hal);
245 
246     lp_aon_hal_inform_wakeup_type(dslp);
247 
248     pmu_ll_hp_set_wakeup_enable(PMU_instance()->hal->dev, wakeup_opt);
249     pmu_ll_hp_set_reject_enable(PMU_instance()->hal->dev, reject_opt);
250 
251     pmu_ll_hp_clear_wakeup_intr_status(PMU_instance()->hal->dev);
252     pmu_ll_hp_clear_reject_intr_status(PMU_instance()->hal->dev);
253     pmu_ll_hp_clear_reject_cause(PMU_instance()->hal->dev);
254 
255     /* Start entry into sleep mode */
256     pmu_ll_hp_set_sleep_enable(PMU_instance()->hal->dev);
257 
258     while (!pmu_ll_hp_is_sleep_wakeup(PMU_instance()->hal->dev) &&
259         !pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev)) {
260         ;
261     }
262 
263     return ESP_OK;
264 }
265 
pmu_sleep_finish(void)266 bool pmu_sleep_finish(void)
267 {
268     // Restore registers lost during sleep
269     REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_0P8, 8);  // fix low temp issue, need to increase this internal voltage
270     return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev);
271 }
272 
pmu_sleep_get_wakup_retention_cost(void)273 uint32_t pmu_sleep_get_wakup_retention_cost(void)
274 {
275     const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
276     return mc->hp.regdma_s2a_work_time_us;
277 }
278