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 <esp_types.h>
10 #include "sdkconfig.h"
11 #include "esp_attr.h"
12 #include "soc/soc.h"
13 #include "soc/pmu_struct.h"
14 #include "hal/pmu_hal.h"
15 #include "pmu_param.h"
16 #include "esp_private/esp_pmu.h"
17 #include "soc/regi2c_pmu.h"
18 #include "soc/regi2c_bias.h"
19 #include "regi2c_ctrl.h"
20 
21 static __attribute__((unused)) const char *TAG = "pmu_init";
22 
23 typedef struct {
24     const pmu_hp_system_power_param_t     *power;
25     const pmu_hp_system_clock_param_t     *clock;
26     const pmu_hp_system_digital_param_t   *digital;
27     pmu_hp_system_analog_param_t          *analog;    //param determined at runtime
28     const pmu_hp_system_retention_param_t *retent;
29 } pmu_hp_system_param_t;
30 
31 typedef struct {
32     const pmu_lp_system_power_param_t  *power;
33     pmu_lp_system_analog_param_t       *analog;    //param determined at runtime
34 } pmu_lp_system_param_t;
35 
PMU_instance(void)36 pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
37 {
38     /* It should be explicitly defined in the internal RAM, because this
39      * instance will be used in pmu_sleep.c */
40     static DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = &PMU };
41     static DRAM_ATTR pmu_sleep_machine_constant_t pmu_mc = PMU_SLEEP_MC_DEFAULT();
42     static DRAM_ATTR pmu_context_t pmu_context = { .hal = &pmu_hal, .mc = (void *)&pmu_mc };
43     return &pmu_context;
44 }
45 
pmu_hp_system_init(pmu_context_t * ctx,pmu_hp_mode_t mode,const pmu_hp_system_param_t * param)46 void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, const pmu_hp_system_param_t *param)
47 {
48     const pmu_hp_system_power_param_t *power = param->power;
49     const pmu_hp_system_clock_param_t *clock = param->clock;
50     const pmu_hp_system_digital_param_t *dig = param->digital;
51     const pmu_hp_system_analog_param_t *anlg = param->analog;
52     const pmu_hp_system_retention_param_t *ret = param->retent;
53 
54     assert(ctx->hal);
55     /* Default configuration of hp-system power in active, modem and sleep modes */
56     pmu_ll_hp_set_dig_power(ctx->hal->dev, mode, power->dig_power.val);
57     pmu_ll_hp_set_clk_power(ctx->hal->dev, mode, power->clk_power.val);
58     pmu_ll_hp_set_xtal_xpd (ctx->hal->dev, mode, power->xtal.xpd_xtal);
59 
60     /* Default configuration of hp-system clock in active, modem and sleep modes */
61     pmu_ll_hp_set_icg_func          (ctx->hal->dev, mode, clock->icg_func);
62     pmu_ll_hp_set_icg_apb           (ctx->hal->dev, mode, clock->icg_apb);
63     pmu_ll_hp_set_icg_modem         (ctx->hal->dev, mode, clock->icg_modem.code);
64     pmu_ll_hp_set_sysclk_nodiv      (ctx->hal->dev, mode, clock->sysclk.dig_sysclk_nodiv);
65     pmu_ll_hp_set_icg_sysclk_enable (ctx->hal->dev, mode, clock->sysclk.icg_sysclk_en);
66     pmu_ll_hp_set_sysclk_slp_sel    (ctx->hal->dev, mode, clock->sysclk.sysclk_slp_sel);
67     pmu_ll_hp_set_icg_sysclk_slp_sel(ctx->hal->dev, mode, clock->sysclk.icg_slp_sel);
68     pmu_ll_hp_set_dig_sysclk        (ctx->hal->dev, mode, clock->sysclk.dig_sysclk_sel);
69 
70     /* Default configuration of hp-system digital sub-system in active, modem
71      * and sleep modes */
72     pmu_ll_hp_set_uart_wakeup_enable(ctx->hal->dev, mode, dig->syscntl.uart_wakeup_en);
73     pmu_ll_hp_set_hold_all_lp_pad   (ctx->hal->dev, mode, dig->syscntl.lp_pad_hold_all);
74     pmu_ll_hp_set_hold_all_hp_pad   (ctx->hal->dev, mode, dig->syscntl.hp_pad_hold_all);
75     pmu_ll_hp_set_dig_pad_slp_sel   (ctx->hal->dev, mode, dig->syscntl.dig_pad_slp_sel);
76     pmu_ll_hp_set_pause_watchdog    (ctx->hal->dev, mode, dig->syscntl.dig_pause_wdt);
77     pmu_ll_hp_set_cpu_stall         (ctx->hal->dev, mode, dig->syscntl.dig_cpu_stall);
78 
79     /* Default configuration of hp-system analog sub-system in active, modem and
80      * sleep modes */
81     pmu_ll_hp_set_bias_xpd                    (ctx->hal->dev, mode, anlg->bias.xpd_bias);
82     pmu_ll_hp_set_trx_xpd                     (ctx->hal->dev, mode, anlg->bias.xpd_trx);
83     pmu_ll_hp_set_current_power_off           (ctx->hal->dev, mode, anlg->bias.pd_cur);
84     pmu_ll_hp_set_bias_sleep_enable           (ctx->hal->dev, mode, anlg->bias.bias_sleep);
85     pmu_ll_hp_set_regulator_sleep_memory_xpd  (ctx->hal->dev, mode, anlg->regulator0.slp_mem_xpd);
86     pmu_ll_hp_set_regulator_sleep_logic_xpd   (ctx->hal->dev, mode, anlg->regulator0.slp_logic_xpd);
87     pmu_ll_hp_set_regulator_xpd               (ctx->hal->dev, mode, anlg->regulator0.xpd);
88     pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_mem_dbias);
89     pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, mode, anlg->regulator0.slp_logic_dbias);
90     pmu_ll_hp_set_regulator_dbias             (ctx->hal->dev, mode, anlg->regulator0.dbias);
91     pmu_ll_hp_set_regulator_driver_bar        (ctx->hal->dev, mode, anlg->regulator1.drv_b);
92 
93     /* Default configuration of hp-system retention sub-system in active, modem
94      * and sleep modes */
95     pmu_ll_hp_set_retention_param(ctx->hal->dev, mode, ret->retention.val);
96     pmu_ll_hp_set_backup_icg_func(ctx->hal->dev, mode, ret->backup_clk);
97 
98     /* Some PMU initial parameter configuration */
99     pmu_ll_imm_update_dig_icg_modem_code(ctx->hal->dev, true);
100     pmu_ll_imm_update_dig_icg_switch(ctx->hal->dev, true);
101 
102     pmu_ll_hp_set_sleep_protect_mode(ctx->hal->dev, PMU_SLEEP_PROTECT_HP_LP_SLEEP);
103 }
104 
pmu_lp_system_init(pmu_context_t * ctx,pmu_lp_mode_t mode,const pmu_lp_system_param_t * param)105 void pmu_lp_system_init(pmu_context_t *ctx, pmu_lp_mode_t mode, const pmu_lp_system_param_t *param)
106 {
107     const pmu_lp_system_power_param_t *power = param->power;
108     const pmu_lp_system_analog_param_t *anlg = param->analog;
109 
110     assert(ctx->hal);
111     /* Default configuration of lp-system power in active and sleep modes */
112     pmu_ll_lp_set_dig_power(ctx->hal->dev, mode, power->dig_power.val);
113     pmu_ll_lp_set_clk_power(ctx->hal->dev, mode, power->clk_power.val);
114     pmu_ll_lp_set_xtal_xpd (ctx->hal->dev, PMU_MODE_LP_SLEEP, power->xtal.xpd_xtal);
115 
116     /* Default configuration of lp-system analog sub-system in active and
117      * sleep modes */
118     pmu_ll_lp_set_bias_xpd             (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.xpd_bias);
119     pmu_ll_lp_set_current_power_off    (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.pd_cur);
120     pmu_ll_lp_set_bias_sleep_enable    (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.bias_sleep);
121     pmu_ll_lp_set_regulator_slp_xpd    (ctx->hal->dev, mode, anlg->regulator0.slp_xpd);
122     pmu_ll_lp_set_regulator_xpd        (ctx->hal->dev, mode, anlg->regulator0.xpd);
123     pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_dbias);
124     pmu_ll_lp_set_regulator_dbias      (ctx->hal->dev, mode, anlg->regulator0.dbias);
125     pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b);
126 }
127 
pmu_power_domain_force_default(pmu_context_t * ctx)128 static inline void pmu_power_domain_force_default(pmu_context_t *ctx)
129 {
130     assert(ctx);
131     // for bypass reserved power domain
132     const pmu_hp_power_domain_t pmu_hp_domains[] = {
133         PMU_HP_PD_TOP,
134         PMU_HP_PD_CPU,
135         PMU_HP_PD_WIFI
136     };
137 
138     for (uint8_t idx = 0; idx < (sizeof(pmu_hp_domains) / sizeof(pmu_hp_power_domain_t)); idx++) {
139         pmu_ll_hp_set_power_force_power_up  (ctx->hal->dev, pmu_hp_domains[idx], false);
140         pmu_ll_hp_set_power_force_no_reset  (ctx->hal->dev, pmu_hp_domains[idx], false);
141         pmu_ll_hp_set_power_force_no_isolate(ctx->hal->dev, pmu_hp_domains[idx], false);
142         pmu_ll_hp_set_power_force_power_down(ctx->hal->dev, pmu_hp_domains[idx], false);
143         pmu_ll_hp_set_power_force_isolate   (ctx->hal->dev, pmu_hp_domains[idx], false);
144         pmu_ll_hp_set_power_force_reset     (ctx->hal->dev, pmu_hp_domains[idx], false);
145     }
146 
147     /* Isolate all memory banks while sleeping, avoid memory leakage current */
148     pmu_ll_hp_set_memory_no_isolate     (ctx->hal->dev, 0);
149 
150     pmu_ll_lp_set_power_force_power_up  (ctx->hal->dev, false);
151     pmu_ll_lp_set_power_force_no_reset  (ctx->hal->dev, false);
152     pmu_ll_lp_set_power_force_no_isolate(ctx->hal->dev, false);
153     pmu_ll_lp_set_power_force_power_down(ctx->hal->dev, false);
154     pmu_ll_lp_set_power_force_isolate   (ctx->hal->dev, false);
155     pmu_ll_lp_set_power_force_reset     (ctx->hal->dev, false);
156 }
157 
pmu_hp_system_param_default(pmu_hp_mode_t mode,pmu_hp_system_param_t * param)158 static inline void pmu_hp_system_param_default(pmu_hp_mode_t mode, pmu_hp_system_param_t *param)
159 {
160     assert (param->analog);
161 
162     param->power = pmu_hp_system_power_param_default(mode);
163     param->clock = pmu_hp_system_clock_param_default(mode);
164     param->digital = pmu_hp_system_digital_param_default(mode);
165     *param->analog = *pmu_hp_system_analog_param_default(mode); //copy default value
166     param->retent = pmu_hp_system_retention_param_default(mode);
167 
168     if (mode == PMU_MODE_HP_ACTIVE || mode == PMU_MODE_HP_MODEM) {
169         param->analog->regulator0.dbias = get_act_hp_dbias();
170     }
171 }
172 
pmu_hp_system_init_default(pmu_context_t * ctx)173 static void pmu_hp_system_init_default(pmu_context_t *ctx)
174 {
175     assert(ctx);
176     for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) {
177         pmu_hp_system_analog_param_t analog = {};
178         pmu_hp_system_param_t param = {.analog = &analog};
179 
180         pmu_hp_system_param_default(mode, &param);
181         pmu_hp_system_init(ctx, mode, &param);
182     }
183 }
184 
pmu_lp_system_param_default(pmu_lp_mode_t mode,pmu_lp_system_param_t * param)185 static inline void pmu_lp_system_param_default(pmu_lp_mode_t mode, pmu_lp_system_param_t *param)
186 {
187     assert (param->analog);
188 
189     param->power = pmu_lp_system_power_param_default(mode);
190     *param->analog = *pmu_lp_system_analog_param_default(mode); //copy default value
191 
192     if (mode == PMU_MODE_LP_ACTIVE) {
193         param->analog->regulator0.dbias = get_act_lp_dbias();
194     }
195 }
196 
pmu_lp_system_init_default(pmu_context_t * ctx)197 static void pmu_lp_system_init_default(pmu_context_t *ctx)
198 {
199     assert(ctx);
200     for (pmu_lp_mode_t mode = PMU_MODE_LP_ACTIVE; mode < PMU_MODE_LP_MAX; mode++) {
201         pmu_lp_system_analog_param_t analog = {};
202         pmu_lp_system_param_t param = {.analog = &analog};
203 
204         pmu_lp_system_param_default(mode, &param);
205         pmu_lp_system_init(ctx, mode, &param);
206     }
207 }
208 
pmu_init()209 void pmu_init()
210 {
211     /* No peripheral reg i2c power up required on the target */
212 
213     REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG, 0);
214     REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG, 0);
215     REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG_SLP, 0);
216     REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG_SLP, 0);
217     REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_RTC_REG, 0);
218     REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_DIG_REG, 0);
219     REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_TRX, 0);
220 
221     REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_0P8, 8);  // fix low temp issue, need to increase this internal voltage
222 
223     WRITE_PERI_REG(PMU_POWER_PD_TOP_CNTL_REG, 0);
224     WRITE_PERI_REG(PMU_POWER_PD_HPAON_CNTL_REG, 0);
225     WRITE_PERI_REG(PMU_POWER_PD_HPCPU_CNTL_REG, 0);
226     WRITE_PERI_REG(PMU_POWER_PD_HPPERI_RESERVE_REG, 0);
227     WRITE_PERI_REG(PMU_POWER_PD_HPWIFI_CNTL_REG, 0);
228     WRITE_PERI_REG(PMU_POWER_PD_LPPERI_CNTL_REG, 0);
229 
230     pmu_hp_system_init_default(PMU_instance());
231     pmu_lp_system_init_default(PMU_instance());
232 
233     pmu_power_domain_force_default(PMU_instance());
234 }
235