mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
Merge branch 'feat/ldo_esp32s31' into 'master'
feat(LDO): Support LDO for psram on esp32s31 See merge request espressif/esp-idf!47174
This commit is contained in:
@@ -59,6 +59,7 @@ extern "C" {
|
||||
PSRAM_CTRLR_LL_EVENT_TX_TRANS_UDF)
|
||||
|
||||
#define PSRAM_CTRLR_LL_INTR_EVENT_SUPPORTED 1
|
||||
#define PSRAM_CTRLR_LL_DEDICATED_LDO 1
|
||||
|
||||
/**
|
||||
* @brief Set PSRAM write cmd
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "hal/misc.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LDO_LL_RAIL_VOLTAGE_MV 3300
|
||||
|
||||
/**
|
||||
* @brief Convert voltage to dref and mul value
|
||||
*
|
||||
* @param ldo_unit LDO unit
|
||||
* @param voltage_mv Voltage in mV
|
||||
* @param dref Returned dref value
|
||||
* @param mul Returned mul value
|
||||
* @param use_rail_voltage Returned value to indicate if the rail voltage should be used
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void ldo_ll_voltage_to_dref_mul(int ldo_unit, int voltage_mv, uint8_t *dref, uint8_t *mul, bool *use_rail_voltage)
|
||||
{
|
||||
(void)ldo_unit;
|
||||
// to avoid using FPU, enlarge the constants by 1000 as fixed point
|
||||
int K_1000 = 1000;
|
||||
int Vos_1000 = 0;
|
||||
int C_1000 = 1000;
|
||||
|
||||
// TODO: [ESP32S31] IDF-15510 For efuse calibration.
|
||||
|
||||
// iterate all the possible dref and mul values to find the best match
|
||||
int min_voltage_diff = 400000000;
|
||||
uint8_t matched_dref = 0;
|
||||
uint8_t matched_mul = 0;
|
||||
for (uint8_t dref_val = 0; dref_val < 16; dref_val++) {
|
||||
int vref_20 = (dref_val < 9) ? (10 + dref_val) : (20 + (dref_val - 9) * 2);
|
||||
for (uint8_t mul_val = 0; mul_val < 8; mul_val++) {
|
||||
int vout_80000000 = (vref_20 * K_1000 + 20 * Vos_1000) * (4000 + mul_val * C_1000);
|
||||
int diff = voltage_mv * 80000 - vout_80000000;
|
||||
if (diff < 0) {
|
||||
diff = -diff;
|
||||
}
|
||||
if (diff < min_voltage_diff) {
|
||||
min_voltage_diff = diff;
|
||||
matched_dref = dref_val;
|
||||
matched_mul = mul_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
*dref = matched_dref;
|
||||
*mul = matched_mul;
|
||||
// if the expected voltage is 3.3V, use the rail voltage directly
|
||||
*use_rail_voltage = (voltage_mv == LDO_LL_RAIL_VOLTAGE_MV);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adjust voltage of a LDO unit
|
||||
*
|
||||
* @note When bypass is enabled, the input voltage is sourced directly to the output.
|
||||
* The dref and mul values will be ignored.
|
||||
*
|
||||
* @param ldo_unit LDO unit
|
||||
* @param dref A parameter which controls the internal reference voltage
|
||||
* @param mul Multiply factor
|
||||
* @param use_rail_voltage Use rail voltage directly (i.e. bypass the LDO)
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void ldo_ll_adjust_voltage(int ldo_unit, uint8_t dref, uint8_t mul, bool use_rail_voltage)
|
||||
{
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(PMU.ext_ldo_ctrl, ext_ldo_dref, dref);
|
||||
PMU.ext_ldo_ctrl.ext_ldo_mul = 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
|
||||
*
|
||||
* @param ldo_unit LDO unit
|
||||
* @param enable True: enable; False: disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void ldo_ll_enable_ripple_suppression(int ldo_unit, bool enable)
|
||||
{
|
||||
(void)ldo_unit;
|
||||
PMU.ext_ldo_ctrl.ext_ldo_en_vdet = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable current limit of a LDO unit to avoid inrush current
|
||||
*
|
||||
* @param ldo_unit LDO unit
|
||||
* @param enable True: enable; False: disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void ldo_ll_enable_current_limit(int ldo_unit, bool enable)
|
||||
{
|
||||
(void)ldo_unit;
|
||||
PMU.ext_ldo_ctrl.ext_cur_lim = enable;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+2
-2
@@ -143,7 +143,7 @@ uint32_t mspi_timing_psram_select_best_tuning_phase(const void *configs, uint32_
|
||||
}
|
||||
|
||||
if (success) {
|
||||
ESP_DRAM_LOGI(TAG, "tuning success, best phase id is %"PRIu32, best_phase_id);
|
||||
ESP_DRAM_LOGD(TAG, "tuning success, best phase id is %"PRIu32, best_phase_id);
|
||||
} else {
|
||||
ESP_DRAM_LOGW(TAG, "tuning fail, best phase id is fallen back to index %"PRIu32"", best_phase_id);
|
||||
}
|
||||
@@ -197,7 +197,7 @@ uint32_t mspi_timing_psram_select_best_tuning_delayline(const void *configs, uin
|
||||
ESP_DRAM_LOGW(TAG, "tuning fail, best delayline id is fallen back to index %"PRIu32"", bset_delayline_id);
|
||||
} else {
|
||||
bset_delayline_id = end - consecutive_length / 2;
|
||||
ESP_DRAM_LOGI(TAG, "tuning success, best delayline id is %"PRIu32, bset_delayline_id);
|
||||
ESP_DRAM_LOGD(TAG, "tuning success, best delayline id is %"PRIu32, bset_delayline_id);
|
||||
}
|
||||
|
||||
return bset_delayline_id;
|
||||
|
||||
@@ -15,10 +15,16 @@ if(${target} STREQUAL "esp32")
|
||||
list(APPEND priv_requires bootloader_support esp_driver_gpio)
|
||||
endif()
|
||||
|
||||
if(${target} STREQUAL "esp32s31")
|
||||
# only esp32s31 needs esp_hal_pmu for ldo.
|
||||
list(APPEND priv_requires esp_hal_pmu)
|
||||
endif()
|
||||
|
||||
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,6 +11,7 @@
|
||||
#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 "clk_ctrl_os.h"
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#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 "clk_ctrl_os.h"
|
||||
@@ -413,6 +414,12 @@ static void s_configure_psram_ecc(void)
|
||||
|
||||
esp_err_t esp_psram_impl_enable(void)
|
||||
{
|
||||
#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
|
||||
periph_rtc_mpll_acquire();
|
||||
uint32_t real_mpll_freq = 0;
|
||||
|
||||
@@ -94,3 +94,20 @@ 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
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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,3 +26,5 @@ 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)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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
|
||||
Reference in New Issue
Block a user