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 4b0dfa162f..b4ea66fa33 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 @@ -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 diff --git a/components/esp_psram/system_layer/esp_psram.c b/components/esp_psram/system_layer/esp_psram.c index 1cbe6a0acc..38aec72f7b 100644 --- a/components/esp_psram/system_layer/esp_psram.c +++ b/components/esp_psram/system_layer/esp_psram.c @@ -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); diff --git a/components/soc/esp32p4/register/hw_ver3/soc/hp_system_struct.h b/components/soc/esp32p4/register/hw_ver3/soc/hp_system_struct.h index e48b0e6b43..86a980f8e0 100644 --- a/components/soc/esp32p4/register/hw_ver3/soc/hp_system_struct.h +++ b/components/soc/esp32p4/register/hw_ver3/soc/hp_system_struct.h @@ -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