diff --git a/components/esp_hal_mspi/esp32p4/include/hal/psram_ctrlr_ll.h b/components/esp_hal_mspi/esp32p4/include/hal/psram_ctrlr_ll.h index af138f4a06a..d59c3faffef 100644 --- a/components/esp_hal_mspi/esp32p4/include/hal/psram_ctrlr_ll.h +++ b/components/esp_hal_mspi/esp32p4/include/hal/psram_ctrlr_ll.h @@ -26,6 +26,7 @@ #include "soc/clk_tree_defs.h" #include "soc/hp_system_struct.h" #include "rom/opi_flash.h" +#include "esp_rom_sys.h" #ifdef __cplusplus extern "C" { @@ -60,6 +61,14 @@ extern "C" { #define PSRAM_CTRLR_LL_INTR_EVENT_SUPPORTED 1 +/** + * ESP32-P4 MSPI revision < 3.0 lacks SPIMEM CS force-control (cs_keep_active / + * cs0_dis / cs1_dis) needed to assert CE# and wake PSRAM from half-sleep. + * The device driver must issue a dummy MSPI write instead. + * Revision >= 3.0 can use psram_ctrlr_ll_half_sleep_wakeup(). + */ +#define PSRAM_CTRLR_LL_MSPI_WAKEUP_WORKAROUND (HAL_CONFIG(CHIP_SUPPORT_MIN_REV) < 300) + /** * @brief Set PSRAM write cmd * @@ -946,6 +955,29 @@ static inline void psram_ctrlr_ll_enable_core_err_resp(void) HP_SYSTEM.core_err_resp_dis.val = 0x0; } +#if !PSRAM_CTRLR_LL_MSPI_WAKEUP_WORKAROUND +/** + * @brief Wake PSRAM from half-sleep via MSPI CS controls (P4 MSPI rev >= 3.0). + * + * MSPI2: mem_cs_oe_ctrl drives CS. MSPI3: cs_keep_active + cs0/cs1_dis for CE#. + * Restore MSPI2/MSPI3 cs settings when done. + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_half_sleep_wakeup(void) +{ + bool old_oe_ctrl = SPIMEM2.mem_misc.mem_cs_oe_ctrl; + SPIMEM2.mem_misc.mem_cs_oe_ctrl = 1; + SPIMEM3.misc.cs_keep_active = 1; + SPIMEM3.misc.cs0_dis = 1; + SPIMEM3.misc.cs1_dis = 0; + esp_rom_delay_us(3); + SPIMEM3.misc.cs1_dis = 1; + SPIMEM3.misc.cs0_dis = 0; + SPIMEM3.misc.cs_keep_active = 0; + SPIMEM2.mem_misc.mem_cs_oe_ctrl = old_oe_ctrl; +} +#endif + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_mspi/esp32s31/include/hal/psram_ctrlr_ll.h b/components/esp_hal_mspi/esp32s31/include/hal/psram_ctrlr_ll.h index c963e228bbd..f18fc2755cb 100644 --- a/components/esp_hal_mspi/esp32s31/include/hal/psram_ctrlr_ll.h +++ b/components/esp_hal_mspi/esp32s31/include/hal/psram_ctrlr_ll.h @@ -27,6 +27,7 @@ #include "soc/clk_tree_defs.h" #include "soc/hp_system_struct.h" #include "rom/opi_flash.h" +#include "esp_rom_sys.h" #ifdef __cplusplus extern "C" { @@ -958,6 +959,27 @@ static inline void psram_ctrlr_ll_enable_core_err_resp(void) HP_SYSTEM.core_err_resp_dis.val = 0x0; } +/** + * @brief Wake PSRAM from half-sleep via MSPI CS controls. + * + * MSPI2: mem_cs_oe_ctrl drives CS. MSPI3: cs_keep_active + cs0/cs1_dis for CE#. + * Restore MSPI2/MSPI3 cs settings when done. + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_half_sleep_wakeup(void) +{ + bool old_oe_ctrl = SPIMEM2.mem_misc.mem_cs_oe_ctrl; + SPIMEM2.mem_misc.mem_cs_oe_ctrl = 1; + SPIMEM3.misc.cs_keep_active = 1; + SPIMEM3.misc.cs0_dis = 1; + SPIMEM3.misc.cs1_dis = 0; + esp_rom_delay_us(3); + SPIMEM3.misc.cs1_dis = 1; + SPIMEM3.misc.cs0_dis = 0; + SPIMEM3.misc.cs_keep_active = 0; + SPIMEM2.mem_misc.mem_cs_oe_ctrl = old_oe_ctrl; +} + #ifdef __cplusplus } #endif diff --git a/components/esp_psram/device/esp_psram_impl_ap_hex.c b/components/esp_psram/device/esp_psram_impl_ap_hex.c index daed4151e26..ccc4cfbd921 100644 --- a/components/esp_psram/device/esp_psram_impl_ap_hex.c +++ b/components/esp_psram/device/esp_psram_impl_ap_hex.c @@ -568,7 +568,7 @@ PSRAM_HALFSLEEP_SLEEP_CODE_ATTR void esp_psram_impl_exit_halfsleep_mode(void) // Record the tick exiting halfsleep mode s_halfsleep_ctx.halfsleep_wakeup_tick = rtc_time_get(); - // Do a SPI dummy write transmission to invalid address to wake up from halfsleep mode +#if PSRAM_CTRLR_LL_MSPI_WAKEUP_WORKAROUND uint8_t null = 0; psram_ctrlr_ll_common_transaction(PSRAM_CTRLR_LL_MSPI_ID_3, AP_HEX_PSRAM_REG_WRITE, AP_HEX_PSRAM_WR_CMD_BITLEN, @@ -577,6 +577,10 @@ PSRAM_HALFSLEEP_SLEEP_CODE_ATTR void esp_psram_impl_exit_halfsleep_mode(void) &null, 0, NULL, 0, false); +#else + // Set CE# to active to wakeup PSRAM halfsleep + psram_ctrlr_ll_half_sleep_wakeup(); +#endif } PSRAM_HALFSLEEP_RESUME_CODE_ATTR void esp_psram_impl_resume_from_halfsleep_mode(uint32_t slowclk_period) diff --git a/components/esp_psram/device/esp_psram_impl_ap_oct.c b/components/esp_psram/device/esp_psram_impl_ap_oct.c index 8d70ece8676..485faf63096 100644 --- a/components/esp_psram/device/esp_psram_impl_ap_oct.c +++ b/components/esp_psram/device/esp_psram_impl_ap_oct.c @@ -565,15 +565,8 @@ void esp_psram_impl_exit_halfsleep_mode(void) // Record the tick exiting halfsleep mode s_halfsleep_ctx.halfsleep_wakeup_tick = rtc_time_get(); - // Do a SPI dummy write transmission to invalid address to wake up from halfsleep mode - uint8_t null = 0; - psram_ctrlr_ll_common_transaction(PSRAM_CTRLR_LL_MSPI_ID_3, - AP_OCT_PSRAM_REG_WRITE, AP_OCT_PSRAM_WR_CMD_BITLEN, - 0xFF, AP_OCT_PSRAM_ADDR_BITLEN, - 0, - &null, 0, - NULL, 0, - false); + // Set CE# to active to wakeup PSRAM halfsleep + psram_ctrlr_ll_half_sleep_wakeup(); } void esp_psram_impl_resume_from_halfsleep_mode(uint32_t slowclk_period)