Merge branch 'fix/fix_xip_power_reset_stuck_issue_p4_rev3' into 'master'

psram: fixed p4 rev3 xip stuck after board reset issue

See merge request espressif/esp-idf!42146
This commit is contained in:
Armando (Dou Yiwen)
2025-10-20 09:05:58 +00:00
3 changed files with 83 additions and 7 deletions

View File

@@ -24,6 +24,7 @@
#include "soc/spi1_mem_s_struct.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/clk_tree_defs.h"
#include "soc/hp_system_struct.h"
#include "rom/opi_flash.h"
#ifdef __cplusplus
@@ -355,20 +356,20 @@ static inline void _psram_ctrlr_ll_enable_module_clock(uint32_t mspi_id, bool en
* @param mspi_id mspi_id
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_reset_module_clock(uint32_t mspi_id)
static inline void _psram_ctrlr_ll_reset_module_clock(uint32_t mspi_id)
{
(void)mspi_id;
HP_SYS_CLKRST.hp_rst_en0.reg_rst_en_dual_mspi_axi = 1;
HP_SYS_CLKRST.hp_rst_en0.reg_rst_en_dual_mspi_axi = 0;
HP_SYS_CLKRST.hp_rst_en0.reg_rst_en_dual_mspi_apb = 1;
HP_SYS_CLKRST.hp_rst_en0.reg_rst_en_dual_mspi_apb = 0;
HP_SYS_CLKRST.hp_rst_en0.reg_rst_en_dual_mspi_axi = 0;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define psram_ctrlr_ll_reset_module_clock(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
psram_ctrlr_ll_reset_module_clock(__VA_ARGS__); \
_psram_ctrlr_ll_reset_module_clock(__VA_ARGS__); \
} while(0)
/**
@@ -828,6 +829,48 @@ static inline void psram_ctrlr_ll_wait_all_transaction_done(void)
}
}
/**
* @brief Backup PSRAM controller registers
*
* @param mspi_id mspi_id
* @param reg registers
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_backup_registers(uint32_t mspi_id, spi_mem_s_dev_t *reg)
{
memcpy(reg, &SPIMEM2, sizeof(spi_mem_s_dev_t));
}
/**
* @brief Restore PSRAM controller registers
*
* @param mspi_id mspi_id
* @param reg registers
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_restore_registers(uint32_t mspi_id, spi_mem_s_dev_t *reg)
{
memcpy(&SPIMEM2, reg, sizeof(spi_mem_s_dev_t));
}
/**
* @brief Disable core error response
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_disable_core_err_resp(void)
{
HP_SYSTEM.core_err_resp_dis.val = 0x7;
}
/**
* @brief Enable core error response
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_core_err_resp(void)
{
HP_SYSTEM.core_err_resp_dis.val = 0x0;
}
#ifdef __cplusplus
}
#endif

View File

@@ -154,6 +154,35 @@ static void IRAM_ATTR s_mapping(int v_start, int size)
}
#endif //CONFIG_IDF_TARGET_ESP32
#if CONFIG_ESP32P4_REV_MIN_FULL == 300
#include "hal/psram_ctrlr_ll.h"
static void IRAM_ATTR esp_psram_p4_rev3_workaround(void)
{
spi_mem_s_dev_t backup_reg = {};
psram_ctrlr_ll_backup_registers(PSRAM_CTRLR_LL_MSPI_ID_2, &backup_reg);
__attribute__((unused)) volatile uint32_t val = 0;
psram_ctrlr_ll_disable_core_err_resp();
/**
* this workaround is to have two dummy reads, therefore
* - map 1 page
* - read 2 times
* - delay 1us
*
* The mapping will be overwritten by the real mapping in `s_psram_mapping`
*/
mmu_ll_write_entry(1, 0, 0, MMU_TARGET_PSRAM0);
val = *(uint32_t *)(0x88000000);
val = *(uint32_t *)(0x88000080);
esp_rom_delay_us(1);
_psram_ctrlr_ll_reset_module_clock(PSRAM_CTRLR_LL_MSPI_ID_2);
psram_ctrlr_ll_enable_core_err_resp();
psram_ctrlr_ll_restore_registers(PSRAM_CTRLR_LL_MSPI_ID_2, &backup_reg);
}
#endif
static esp_err_t s_psram_chip_init(void)
{
if (s_psram_ctx.is_chip_initialised) {
@@ -375,6 +404,10 @@ esp_err_t esp_psram_init(void)
}
}
#if CONFIG_ESP32P4_REV_MIN_FULL == 300
esp_psram_p4_rev3_workaround();
#endif
uint32_t psram_available_size = 0;
ret = esp_psram_impl_get_available_size(&psram_available_size);
assert(ret == ESP_OK);

View File

@@ -2123,7 +2123,7 @@ typedef union {
} hp_hp2lp_intr_group3_st_reg_t;
typedef struct {
typedef struct hp_system_dev_t {
volatile hp_sys_ver_date_reg_t sys_ver_date;
volatile hp_clk_en_reg_t clk_en;
uint32_t reserved_008[2];
@@ -2244,12 +2244,12 @@ typedef struct {
volatile hp_hp2lp_wakeup_group1_en_reg_t hp2lp_wakeup_group1_en;
volatile hp_hp2lp_wakeup_group2_en_reg_t hp2lp_wakeup_group2_en;
volatile hp_hp2lp_wakeup_group3_en_reg_t hp2lp_wakeup_group3_en;
} hp_dev_t;
} hp_system_dev_t;
extern hp_dev_t HP_SYSTEM;
extern hp_system_dev_t HP_SYSTEM;
#ifndef __cplusplus
_Static_assert(sizeof(hp_dev_t) == 0x220, "Invalid size of hp_dev_t structure");
_Static_assert(sizeof(hp_system_dev_t) == 0x220, "Invalid size of hp_dev_t structure");
#endif
#ifdef __cplusplus