mirror of
https://github.com/espressif/esp-idf.git
synced 2026-05-28 16:46:31 +03:00
feat(ldo): support s31 psram sdmmc power domain
Move S31 PSRAM/SDMMC power setup onto the common LDO path so shared users can control the domain consistently.
This commit is contained in:
@@ -9,13 +9,45 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "hal/misc.h"
|
||||
#include "hal/pmu_types.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LDO_LL_RAIL_VOLTAGE_MV 3300
|
||||
#define LDO_LL_NUM_UNITS 1 // Number of LDO units
|
||||
#define LDO_LL_ADJUSTABLE_CHAN_MASK 0x01 // all the channels are adjustable by setting "mul" and "dref" registers
|
||||
|
||||
#define LDO_LL_RECOMMEND_MAX_VOLTAGE_MV 2700
|
||||
#define LDO_LL_RECOMMEND_MIN_VOLTAGE_MV 500
|
||||
#define LDO_LL_RAIL_VOLTAGE_MV 3300
|
||||
|
||||
/**
|
||||
* @brief In the analog design, the LDO output "channel" is index from 1, i.e., VO1, VO2, VO3, VO4.
|
||||
* But in software, we mapped them to "LDO unit", which is index from 0, i.e., 0, 1, 2, 3.
|
||||
*/
|
||||
#define LDO_ID2UNIT(ldo_id) ((ldo_id) - 1)
|
||||
|
||||
/**
|
||||
* @brief LDO unit owner
|
||||
*/
|
||||
typedef enum {
|
||||
LDO_LL_UNIT_OWNER_HW, // LDO unit is controlled by hardware
|
||||
LDO_LL_UNIT_OWNER_SW, // LDO unit is controlled by software
|
||||
} ldo_ll_unit_owner_t;
|
||||
|
||||
/**
|
||||
* @brief Check if a LDO channel is valid
|
||||
*
|
||||
* @param ldo_chan LDO channel ID, note, this is indexed from 1
|
||||
* @return True for valid, false for invalid
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool ldo_ll_is_valid_ldo_channel(int ldo_chan)
|
||||
{
|
||||
return (ldo_chan > 0) && (ldo_chan <= LDO_LL_NUM_UNITS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert voltage to dref and mul value
|
||||
@@ -62,6 +94,20 @@ static inline void ldo_ll_voltage_to_dref_mul(int ldo_unit, int voltage_mv, uint
|
||||
*use_rail_voltage = (voltage_mv == LDO_LL_RAIL_VOLTAGE_MV);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set owner of a LDO unit
|
||||
*
|
||||
* @note Even if the LDO unit is controlled by hardware, its voltage can still be changed by software by `ldo_ll_adjust_voltage`
|
||||
*
|
||||
* @param ldo_unit LDO unit
|
||||
* @param owner Owner of the LDO unit
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void ldo_ll_set_owner(int ldo_unit, ldo_ll_unit_owner_t owner)
|
||||
{
|
||||
//for compatibility
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adjust voltage of a LDO unit
|
||||
*
|
||||
@@ -81,17 +127,6 @@ static inline void ldo_ll_adjust_voltage(int ldo_unit, uint8_t dref, uint8_t mul
|
||||
PMU.ext_ldo_ctrl.ext_ldo_tie_high = use_rail_voltage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable power on the PSRAM domain
|
||||
*
|
||||
* @param enable True: enable; False: disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void ldo_ll_psram_power_enable(bool enable)
|
||||
{
|
||||
PMU.psram_cfg.psram_xpd = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable ripple suppression of a LDO unit
|
||||
*
|
||||
@@ -105,6 +140,20 @@ static inline void ldo_ll_enable_ripple_suppression(int ldo_unit, bool enable)
|
||||
PMU.ext_ldo_ctrl.ext_ldo_en_vdet = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable a LDO unit
|
||||
*
|
||||
* @param ldo_unit LDO unit
|
||||
* @param enable True: enable; False: disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void ldo_ll_enable(int ldo_unit, bool enable)
|
||||
{
|
||||
//for compatibility
|
||||
//PMU.hp_sys[PMU_MODE_HP_ACTIVE].regulator0.xpd is for chip internal LDO for chip power
|
||||
//this will not be controlled by this general purpose LDO file
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable current limit of a LDO unit to avoid inrush current
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -87,6 +87,7 @@ esp_err_t esp_ldo_acquire_channel(const esp_ldo_channel_config_t *config, esp_ld
|
||||
uint8_t dref = 0;
|
||||
uint8_t mul = 0;
|
||||
bool use_rail_voltage = false;
|
||||
ldo_ll_enable_current_limit(unit_id, true);
|
||||
// calculate the dref and mul
|
||||
ldo_ll_voltage_to_dref_mul(unit_id, config->voltage_mv, &dref, &mul, &use_rail_voltage);
|
||||
ldo_ll_adjust_voltage(unit_id, dref, mul, use_rail_voltage);
|
||||
@@ -95,6 +96,7 @@ esp_err_t esp_ldo_acquire_channel(const esp_ldo_channel_config_t *config, esp_ld
|
||||
// suppress voltage ripple
|
||||
ldo_ll_enable_ripple_suppression(unit_id, true);
|
||||
ldo_ll_enable(unit_id, true);
|
||||
ldo_ll_enable_current_limit(unit_id, false);
|
||||
}
|
||||
// update the channel attributes
|
||||
channel->ref_cnt++;
|
||||
@@ -146,7 +148,9 @@ esp_err_t esp_ldo_release_channel(esp_ldo_channel_handle_t chan)
|
||||
esp_err_t esp_ldo_channel_adjust_voltage(esp_ldo_channel_handle_t chan, int voltage_mv)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(chan->flags.adjustable, ESP_ERR_NOT_SUPPORTED, TAG, "LDO is not adjustable");
|
||||
if (chan->voltage_mv != voltage_mv) {
|
||||
ESP_RETURN_ON_FALSE(chan->flags.adjustable, ESP_ERR_NOT_SUPPORTED, TAG, "LDO is not adjustable");
|
||||
}
|
||||
// check if the target voltage is within the recommended range
|
||||
if (!((voltage_mv == LDO_LL_RAIL_VOLTAGE_MV) ||
|
||||
(voltage_mv >= LDO_LL_RECOMMEND_MIN_VOLTAGE_MV && voltage_mv <= LDO_LL_RECOMMEND_MAX_VOLTAGE_MV))) {
|
||||
|
||||
34
components/esp_hw_support/port/esp32s31/Kconfig.ldo
Normal file
34
components/esp_hw_support/port/esp32s31/Kconfig.ldo
Normal file
@@ -0,0 +1,34 @@
|
||||
menu "LDO Regulator Configurations"
|
||||
depends on SOC_GP_LDO_SUPPORTED
|
||||
|
||||
config ESP_LDO_RESERVE_PSRAM
|
||||
bool "Reserve one LDO regulator channel for PSRAM (READ HELP)"
|
||||
default y
|
||||
help
|
||||
The LDO channel can be used to power the PSRAM chip.
|
||||
If the PSRAM chip is not powered by ESP internal LDO, you can disable this option.
|
||||
Then you will free up one LDO channel for other general purpose.
|
||||
|
||||
config ESP_LDO_CHAN_PSRAM_DOMAIN
|
||||
int "LDO regulator channel that used to power PSRAM and MPLL (READ HELP)"
|
||||
depends on ESP_LDO_RESERVE_PSRAM
|
||||
default 1
|
||||
range 1 1
|
||||
help
|
||||
Select which LDO channel to connect to the PSRAM chip.
|
||||
|
||||
choice ESP_LDO_VOLTAGE_PSRAM_DOMAIN
|
||||
prompt "PSRAM power domain voltage"
|
||||
depends on ESP_LDO_RESERVE_PSRAM
|
||||
default ESP_LDO_VOLTAGE_PSRAM_1800_MV
|
||||
help
|
||||
Select the voltage used by the PSRAM power domain.
|
||||
|
||||
config ESP_LDO_VOLTAGE_PSRAM_1800_MV
|
||||
bool "1.8V"
|
||||
endchoice
|
||||
|
||||
config ESP_LDO_VOLTAGE_PSRAM_DOMAIN
|
||||
int
|
||||
default 1800 if ESP_LDO_VOLTAGE_PSRAM_1800_MV
|
||||
endmenu
|
||||
@@ -10,7 +10,9 @@ if(CONFIG_SOC_RNG_SUPPORTED)
|
||||
list(APPEND srcs "test_random.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_GP_LDO_SUPPORTED)
|
||||
if(CONFIG_SOC_GP_LDO_SUPPORTED AND NOT CONFIG_IDF_TARGET_ESP32S31)
|
||||
# on s31 ldo is general purpose (and also for psram), but runners all have psram
|
||||
# so we don't run ldo test on s31 to avoid breaking psram
|
||||
list(APPEND srcs "test_ldo.c")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ set(srcs "system_layer/esp_psram_mspi.c")
|
||||
|
||||
if(CONFIG_SPIRAM)
|
||||
list(APPEND srcs "system_layer/esp_psram.c")
|
||||
list(APPEND srcs "system_layer/esp_psram_ldo_supply.c")
|
||||
|
||||
if(${target} STREQUAL "esp32")
|
||||
list(APPEND srcs "esp32/esp_psram_extram_cache.c"
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/mspi_timing_tuning.h"
|
||||
#include "esp_private/esp_psram_impl.h"
|
||||
#include "esp_private/esp_psram_ldo.h"
|
||||
#include "hal/psram_ctrlr_ll.h"
|
||||
#include "hal/mspi_ll.h"
|
||||
#include "soc/rtc.h"
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/mspi_timing_tuning.h"
|
||||
#include "esp_private/esp_psram_impl.h"
|
||||
#include "esp_private/esp_psram_ldo.h"
|
||||
#include "hal/psram_ctrlr_ll.h"
|
||||
#include "hal/mspi_ll.h"
|
||||
#include "soc/rtc.h"
|
||||
@@ -415,12 +414,6 @@ esp_err_t esp_psram_impl_enable(void)
|
||||
{
|
||||
psram_ctrlr_ll_enable_power(true);
|
||||
|
||||
#if PSRAM_CTRLR_LL_DEDICATED_LDO
|
||||
esp_psram_power_cfg_t config = {
|
||||
.voltage_mv = CONFIG_SPIRAM_LDO_VOLTAGE_DOMAIN,
|
||||
};
|
||||
esp_psram_power_init(&config);
|
||||
#endif
|
||||
#if SOC_CLK_MPLL_SUPPORTED
|
||||
// We need to use the acquire and freq_set functions directly instead of general clk_tree API for IRAM safe function
|
||||
esp_clk_tree_mpll_acquire();
|
||||
|
||||
@@ -93,20 +93,3 @@ menu "PSRAM config"
|
||||
source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common" # insert non-chip-specific items here
|
||||
|
||||
endmenu
|
||||
|
||||
menu "PSRAM LDO Configurations"
|
||||
|
||||
choice SPIRAM_LDO_VOLTAGE_DOMAIN
|
||||
prompt "PSRAM power domain voltage"
|
||||
default SPIRAM_LDO_VOLTAGE_1800_MV
|
||||
help
|
||||
Select the voltage used by the PSRAM power domain.
|
||||
|
||||
config SPIRAM_LDO_VOLTAGE_1800_MV
|
||||
bool "1.8V"
|
||||
endchoice
|
||||
|
||||
config SPIRAM_LDO_VOLTAGE_DOMAIN
|
||||
int
|
||||
default 1800 if SPIRAM_LDO_VOLTAGE_1800_MV
|
||||
endmenu
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Configuration for PSRAM domain LDO supply initialization
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t voltage_mv; /*!< PSRAM supply voltage in mV */
|
||||
} esp_psram_power_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the PSRAM supply (LDO voltage and power switch)
|
||||
*
|
||||
* @param config Configuration for the PSRAM supply
|
||||
*/
|
||||
void esp_psram_power_init(const esp_psram_power_cfg_t *config);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -26,5 +26,3 @@ entries:
|
||||
esp_psram: esp_psram_init (noflash)
|
||||
esp_psram: s_psram_chip_init (noflash)
|
||||
esp_psram: s_xip_psram_placement (noflash)
|
||||
if IDF_TARGET_ESP32S31 = y:
|
||||
esp_psram_ldo_supply: esp_psram_power_init (noflash)
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#if !CONFIG_IDF_TARGET_ESP32 && !CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "hal/psram_ctrlr_ll.h"
|
||||
#endif
|
||||
#if PSRAM_CTRLR_LL_DEDICATED_LDO
|
||||
#include "hal/ldo_ll.h"
|
||||
#include "esp_private/esp_psram_ldo.h"
|
||||
|
||||
void esp_psram_power_init(const esp_psram_power_cfg_t *config)
|
||||
{
|
||||
uint8_t dref = 0;
|
||||
uint8_t mul = 0;
|
||||
bool use_rail_voltage = false;
|
||||
ldo_ll_enable_current_limit(0, true);
|
||||
ldo_ll_voltage_to_dref_mul(0, config->voltage_mv, &dref, &mul, &use_rail_voltage);
|
||||
ldo_ll_adjust_voltage(0, dref, mul, use_rail_voltage);
|
||||
ldo_ll_psram_power_enable(true);
|
||||
ldo_ll_enable_current_limit(0, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -18,6 +18,14 @@
|
||||
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
|
||||
#include "sd_pwr_ctrl_interface.h"
|
||||
|
||||
#if SOC_SDMMC_IO_UHS_POWER_EXTERNAL
|
||||
#define SD_VOLT_MV 1800
|
||||
#define SD_VOLT_ADJUST_MODE false
|
||||
#else
|
||||
#define SD_VOLT_MV 3300
|
||||
#define SD_VOLT_ADJUST_MODE true
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
esp_ldo_channel_handle_t ldo_chan;
|
||||
int voltage_mv;
|
||||
@@ -38,9 +46,9 @@ esp_err_t sd_pwr_ctrl_new_on_chip_ldo(const sd_pwr_ctrl_ldo_config_t *configs, s
|
||||
ESP_GOTO_ON_FALSE(ctx, ESP_ERR_NO_MEM, err, TAG, "no mem for on-chip ldo control driver context");
|
||||
|
||||
esp_ldo_channel_config_t chan_cfg = {
|
||||
.voltage_mv = 3300,
|
||||
.voltage_mv = SD_VOLT_MV,
|
||||
.chan_id = configs->ldo_chan_id,
|
||||
.flags.adjustable = true, // the SDMMC power control driver will adjust the voltage later according to different speed mode
|
||||
.flags.adjustable = SD_VOLT_ADJUST_MODE, // the SDMMC power control driver will adjust the voltage later according to different speed mode
|
||||
};
|
||||
esp_ldo_channel_handle_t ldo_chan = NULL;
|
||||
ESP_GOTO_ON_ERROR(esp_ldo_acquire_channel(&chan_cfg, &ldo_chan), err, TAG, "failed to enable the on-chip LDO unit");
|
||||
@@ -51,6 +59,8 @@ esp_err_t sd_pwr_ctrl_new_on_chip_ldo(const sd_pwr_ctrl_ldo_config_t *configs, s
|
||||
ctx->voltage_mv = 0;
|
||||
*ret_drv = driver;
|
||||
|
||||
ESP_LOGD(TAG, "on-chip LDO unit %d enabled", configs->ldo_chan_id);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
@@ -77,6 +87,7 @@ static esp_err_t s_ldo_set_voltage(void *arg, int voltage_mv)
|
||||
{
|
||||
//API checks done by caller
|
||||
sd_pwr_ctrl_ldo_ctx_t *ctx = arg;
|
||||
ESP_LOGD(TAG, "setting LDO unit output voltage to %dmV", voltage_mv);
|
||||
ESP_RETURN_ON_ERROR(esp_ldo_channel_adjust_voltage(ctx->ldo_chan, voltage_mv), TAG, "failed to set LDO unit output voltage");
|
||||
ctx->voltage_mv = voltage_mv;
|
||||
return ESP_OK;
|
||||
|
||||
Reference in New Issue
Block a user