soc/rtc: add function to get/set VDDSDIO configuration
Also consider case of VDDSDIO force powered on in rtc_sleep.
This commit is contained in:
parent
5a294c9acd
commit
fb9c106bcb
|
@ -198,14 +198,22 @@ static void rtc_wdt_disable()
|
|||
* Placed into IRAM as flash may need some time to be powered on.
|
||||
*/
|
||||
static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
|
||||
rtc_cpu_freq_t cpu_freq, uint32_t flash_enable_time_us) IRAM_ATTR __attribute__((noinline));
|
||||
rtc_cpu_freq_t cpu_freq, uint32_t flash_enable_time_us,
|
||||
rtc_vddsdio_config_t vddsdio_config) IRAM_ATTR __attribute__((noinline));
|
||||
|
||||
static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
|
||||
rtc_cpu_freq_t cpu_freq, uint32_t flash_enable_time_us)
|
||||
rtc_cpu_freq_t cpu_freq, uint32_t flash_enable_time_us,
|
||||
rtc_vddsdio_config_t vddsdio_config)
|
||||
{
|
||||
// Enter sleep
|
||||
esp_err_t err = esp_sleep_start(pd_flags);
|
||||
|
||||
// If VDDSDIO regulator was controlled by RTC registers before sleep,
|
||||
// restore the configuration.
|
||||
if (vddsdio_config.force) {
|
||||
rtc_vddsdio_set_config(vddsdio_config);
|
||||
}
|
||||
|
||||
// Restore CPU frequency
|
||||
rtc_clk_cpu_freq_set(cpu_freq);
|
||||
|
||||
|
@ -244,6 +252,7 @@ esp_err_t esp_light_sleep_start()
|
|||
s_config.sleep_duration -= flash_enable_time_us;
|
||||
}
|
||||
#endif //CONFIG_SPIRAM_SUPPORT
|
||||
rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config();
|
||||
|
||||
// Safety net: enable WDT in case exit from light sleep fails
|
||||
rtc_wdt_enable(1000);
|
||||
|
@ -252,7 +261,8 @@ esp_err_t esp_light_sleep_start()
|
|||
rtc_cpu_freq_t cpu_freq = rtc_clk_cpu_freq_get();
|
||||
|
||||
// Enter sleep, then wait for flash to be ready on wakeup
|
||||
esp_err_t err = esp_light_sleep_inner(pd_flags, cpu_freq, flash_enable_time_us);
|
||||
esp_err_t err = esp_light_sleep_inner(pd_flags, cpu_freq,
|
||||
flash_enable_time_us, vddsdio_config);
|
||||
|
||||
// At this point, if FRC1 is used for timekeeping, time will be lagging behind.
|
||||
// This will update the microsecond count based on RTC timer.
|
||||
|
|
|
@ -554,6 +554,36 @@ typedef struct {
|
|||
*/
|
||||
void rtc_init(rtc_config_t cfg);
|
||||
|
||||
/**
|
||||
* Structure describing vddsdio configuration
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t force : 1; //!< If 1, use configuration from RTC registers; if 0, use EFUSE/bootstrapping pins.
|
||||
uint32_t enable : 1; //!< Enable VDDSDIO regulator
|
||||
uint32_t tieh : 1; //!< Select VDDSDIO voltage: 1 — 1.8V, 0 — 3.3V
|
||||
uint32_t drefh : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
uint32_t drefm : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
uint32_t drefl : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
} rtc_vddsdio_config_t;
|
||||
|
||||
/**
|
||||
* Get current VDDSDIO configuration
|
||||
* If VDDSDIO configuration is overridden by RTC, get values from RTC
|
||||
* Otherwise, if VDDSDIO is configured by EFUSE, get values from EFUSE
|
||||
* Otherwise, use default values and the level of MTDI bootstrapping pin.
|
||||
* @return currently used VDDSDIO configuration
|
||||
*/
|
||||
rtc_vddsdio_config_t rtc_vddsdio_get_config();
|
||||
|
||||
/**
|
||||
* Set new VDDSDIO configuration using RTC registers.
|
||||
* If config.force == 1, this overrides configuration done using bootstrapping
|
||||
* pins and EFUSE.
|
||||
*
|
||||
* @param config new VDDSDIO configuration
|
||||
*/
|
||||
void rtc_vddsdio_set_config(rtc_vddsdio_config_t config);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/gpio_reg.h"
|
||||
|
||||
|
||||
void rtc_init(rtc_config_t cfg)
|
||||
|
@ -94,3 +96,51 @@ void rtc_init(rtc_config_t cfg)
|
|||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO);
|
||||
}
|
||||
}
|
||||
|
||||
rtc_vddsdio_config_t rtc_vddsdio_get_config()
|
||||
{
|
||||
rtc_vddsdio_config_t result;
|
||||
uint32_t sdio_conf_reg = REG_READ(RTC_CNTL_SDIO_CONF_REG);
|
||||
result.drefh = (sdio_conf_reg & RTC_CNTL_DREFH_SDIO_M) >> RTC_CNTL_DREFH_SDIO_S;
|
||||
result.drefm = (sdio_conf_reg & RTC_CNTL_DREFM_SDIO_M) >> RTC_CNTL_DREFM_SDIO_S;
|
||||
result.drefl = (sdio_conf_reg & RTC_CNTL_DREFL_SDIO_M) >> RTC_CNTL_DREFL_SDIO_S;
|
||||
if (sdio_conf_reg & RTC_CNTL_SDIO_FORCE) {
|
||||
// Get configuration from RTC
|
||||
result.force = 1;
|
||||
result.enable = (sdio_conf_reg & RTC_CNTL_XPD_SDIO_REG_M) >> RTC_CNTL_XPD_SDIO_REG_S;
|
||||
result.tieh = (sdio_conf_reg & RTC_CNTL_SDIO_TIEH_M) >> RTC_CNTL_SDIO_TIEH_S;
|
||||
return result;
|
||||
}
|
||||
uint32_t efuse_reg = REG_READ(EFUSE_BLK0_RDATA4_REG);
|
||||
if (efuse_reg & EFUSE_RD_SDIO_FORCE) {
|
||||
// Get configuration from EFUSE
|
||||
result.force = 0;
|
||||
result.enable = (efuse_reg & EFUSE_RD_XPD_SDIO_REG_M) >> EFUSE_RD_XPD_SDIO_REG_S;
|
||||
result.tieh = (efuse_reg & EFUSE_RD_SDIO_TIEH_M) >> EFUSE_RD_SDIO_TIEH_S;
|
||||
// in this case, DREFH/M/L are also set from EFUSE
|
||||
result.drefh = (efuse_reg & EFUSE_RD_SDIO_DREFH_M) >> EFUSE_RD_SDIO_DREFH_S;
|
||||
result.drefm = (efuse_reg & EFUSE_RD_SDIO_DREFM_M) >> EFUSE_RD_SDIO_DREFM_S;
|
||||
result.drefl = (efuse_reg & EFUSE_RD_SDIO_DREFL_M) >> EFUSE_RD_SDIO_DREFL_S;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Otherwise, VDD_SDIO is controlled by bootstrapping pin
|
||||
uint32_t strap_reg = REG_READ(GPIO_STRAP_REG);
|
||||
result.force = 0;
|
||||
result.tieh = (strap_reg & BIT(5)) ? 0 : 1;
|
||||
result.enable = result.tieh == 0; // only power on the regulator if VDD=1.8
|
||||
return result;
|
||||
}
|
||||
|
||||
void rtc_vddsdio_set_config(rtc_vddsdio_config_t config)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
val |= (config.force << RTC_CNTL_SDIO_FORCE_S);
|
||||
val |= (config.enable << RTC_CNTL_XPD_SDIO_REG_S);
|
||||
val |= (config.drefh << RTC_CNTL_DREFH_SDIO_S);
|
||||
val |= (config.drefm << RTC_CNTL_DREFM_SDIO_S);
|
||||
val |= (config.drefl << RTC_CNTL_DREFL_SDIO_S);
|
||||
val |= (config.tieh << RTC_CNTL_SDIO_TIEH_S);
|
||||
val |= RTC_CNTL_SDIO_PD_EN;
|
||||
REG_WRITE(RTC_CNTL_SDIO_CONF_REG, val);
|
||||
}
|
||||
|
|
|
@ -198,11 +198,9 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
|||
REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, 0);
|
||||
}
|
||||
|
||||
if (cfg.vddsdio_pd_en) {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN);
|
||||
}
|
||||
/* enable VDDSDIO control by state machine */
|
||||
REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE);
|
||||
REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en);
|
||||
|
||||
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SLP, cfg.rtc_dbias_slp);
|
||||
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, cfg.rtc_dbias_wak);
|
||||
|
|
Loading…
Reference in a new issue