]> granicus.if.org Git - esp-idf/commitdiff
soc/rtc: add function to get/set VDDSDIO configuration
authorIvan Grokhotkov <ivan@espressif.com>
Wed, 1 Nov 2017 07:16:32 +0000 (15:16 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Fri, 3 Nov 2017 07:49:09 +0000 (15:49 +0800)
Also consider case of VDDSDIO force powered on in rtc_sleep.

components/esp32/sleep_modes.c
components/soc/esp32/include/soc/rtc.h
components/soc/esp32/rtc_init.c
components/soc/esp32/rtc_sleep.c

index 6927716c626f59b825a995d795f2aead68da18b3..2403638302bbf8a8491f9b825c91e80dafb8d078 100644 (file)
@@ -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.
index f13c113b4e487e63b16cdcf2e9d0ba6bc1f30352..e600e39e3c6ba7dae096aa04d4d94a54a76ed3ae 100644 (file)
@@ -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
 }
index ff7b6b73cca3e99e8cd803cd86617d1ef716aba0..44786fbcc56cddcc66971856404e8b128e308d6f 100644 (file)
@@ -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);
+}
index 0b20692fa0e1b1078a15c1ea99a964a6d46e0434..82a04d8caba8692280c85a7f71d9c34ad8a8a0de 100644 (file)
@@ -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);