fix(esp_hw_support): add p4 rev3.0 MSPI workaround for deepsleep

This commit is contained in:
wuzhenghui
2025-11-04 16:03:31 +08:00
parent e46e51fafb
commit 18475ffbe5
15 changed files with 217 additions and 263 deletions
+1
View File
@@ -292,4 +292,5 @@ menu "Hardware Settings"
Otherwise, internal voltage will be set to fix dbias.
This is a must for stable mass production. Disable for debugging only.
orsource "./lowpower/port/esp32p4/Kconfig.p4_rev3_mspi_workaround"
endmenu
@@ -16,6 +16,12 @@ if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP OR
endif()
endif()
if(CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND)
list(APPEND srcs "port/esp32p4/p4_rev3_mspi_workaround.S")
set_property(TARGET ${COMPONENT_LIB}
APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u p4_rev3_mspi_workaround")
endif()
if(CONFIG_SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD AND CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
list(APPEND srcs "port/${target}/sleep_mmu.c")
endif()
@@ -0,0 +1,10 @@
config P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
bool
depends on IDF_TARGET_ESP32P4
default y if ESP32P4_REV_MIN_300
config P4_REV3_MSPI_WORKAROUND_SIZE
hex
depends on IDF_TARGET_ESP32P4
default 0x100 if ESP32P4_REV_MIN_300
default 0
@@ -0,0 +1,110 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/reg_base.h"
#define HP_SYSTEM_CORE_ERR_RESP_DIS_REG (DR_REG_HP_SYS_BASE + 0x1a4)
/* Clock related */
#define DR_REG_LP_CLKRST_BASE (DR_REG_LPAON_BASE + 0x1000)
#define LP_CLKRST_HPCPU_RESET_CTRL0_REG (DR_REG_LP_CLKRST_BASE + 0x14)
#define LP_CLKRST_HPCORE0_STAT_VECTOR_SEL (1 << 15)
#define HP_SYS_CLKRST_HP_RST_EN0_REG (DR_REG_HP_SYS_CLKRST_BASE + 0xc0)
#define HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI (1 << 22)
#define HP_SYS_CLKRST_REG_RST_EN_MSPI_APB (1 << 24)
/* SPIMEM related */
#define DR_REG_FLASH_SPI0_BASE (DR_REG_HPPERIPH0_BASE + 0x8C000)
#define SPI_MEM_C_CACHE_FCTRL_REG (DR_REG_FLASH_SPI0_BASE + 0x3c)
#define SPI_MEM_C_CLOSE_AXI_INF_EN (1 << 31)
#define SPI_MEM_C_AXI_REQ_EN (1 << 0)
#define SPI_MEM_C_MMU_ITEM_INDEX_REG (DR_REG_FLASH_SPI0_BASE + 0x380)
#define SPI_MEM_C_MMU_ITEM_CONTENT_REG (DR_REG_FLASH_SPI0_BASE + 0x37c)
.macro REG_SET_BIT addr, value
li a0, \addr
li a1, \value
lw a2, (a0)
or a2, a2, a1
sw a2, (a0)
.endm
.macro REG_CLR_BIT addr, value
li a0, \addr
/* Since all our parameters will be constants, we can pre-calculate it at assemble time */
li a1, ~\value
lw a2, (a0)
and a2, a2, a1
sw a2, (a0)
.endm
.macro REG_WRITE addr, value
li a0, \addr
li a1, \value
sw a1, (a0)
.endm
.macro REG_READ addr
li a0, \addr
lw a1, (a0)
.endm
.macro DELAY_US us
li t3, (40 * \us) /* CPU @40MHz after reset */
csrr t0, cycle
add t1, t0, t3
1: csrr t2, cycle
blt t2, t1, 1b
.endm
/**
* @brief Workaround for MSPI issues on ESP32-P4 revision 3
*
* This function implements a workaround for MSPI-related issues on ESP32-P4 revision 3.
* It performs 2 flash dummy reads to stabilize the MSPI functionality before jumping to
* ROM code after deepsleep wakeup.
*/
.global p4_rev3_mspi_workaround
.section .p4_rev3_mspi_workaround.rtc_text,"ax"
p4_rev3_mspi_workaround:
# Recover the reset vector to HP ROM
REG_SET_BIT LP_CLKRST_HPCPU_RESET_CTRL0_REG, LP_CLKRST_HPCORE0_STAT_VECTOR_SEL
# Clear the bit to close AXI interface and then set the AXI request enable bit
REG_CLR_BIT SPI_MEM_C_CACHE_FCTRL_REG, SPI_MEM_C_CLOSE_AXI_INF_EN
REG_SET_BIT SPI_MEM_C_CACHE_FCTRL_REG, SPI_MEM_C_AXI_REQ_EN
# Set 1 mspi mmu entry for axi addr to flash addr
REG_WRITE SPI_MEM_C_MMU_ITEM_INDEX_REG, 0
REG_WRITE SPI_MEM_C_MMU_ITEM_CONTENT_REG, 0x1000
# Disable cpu get error response
REG_WRITE HP_SYSTEM_CORE_ERR_RESP_DIS_REG, 0x7
# Perform dummy reads
REG_READ 0x80000000
# Perform dummy reads again
REG_READ 0x80000080
# Delay 1us to wait MSPI read transmission done
DELAY_US 1
# Enable cpu get error response
REG_WRITE HP_SYSTEM_CORE_ERR_RESP_DIS_REG, 0
# Reset MSPI AXI and APB interfaces
REG_SET_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI
REG_SET_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_APB
REG_CLR_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI
REG_CLR_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_APB
# Jump to HP ROM first stage boot code
li a5, 0x4fc00000
jr a5
@@ -30,6 +30,7 @@
#include "hal/pmu_hal.h"
#include "hal/psram_ctrlr_ll.h"
#include "hal/lp_sys_ll.h"
#include "hal/lp_clkrst_ll.h"
#include "hal/clk_gate_ll.h"
#include "esp_private/esp_pmu.h"
#include "pmu_param.h"
@@ -407,6 +408,10 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
#endif
rtc_clk_mpll_disable();
}
} else {
#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
lp_clkrst_ll_boot_from_lp_ram(true);
#endif
}
@@ -430,12 +435,16 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
;
}
#if CONFIG_SPIRAM && CONFIG_ESP_LDO_RESERVE_PSRAM
// Enable PSRAM chip power supply after deepsleep request rejected
if (dslp) {
#if CONFIG_SPIRAM && CONFIG_ESP_LDO_RESERVE_PSRAM
// Enable PSRAM chip power supply after deepsleep request rejected
ldo_ll_enable(LDO_ID2UNIT(CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN), true);
}
#endif
#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
// Set reset vector back to HP ROM after deepsleep request rejected
lp_clkrst_ll_boot_from_lp_ram(false);
#endif
}
return pmu_sleep_finish(dslp);
}