Skip to content

Commit 3ee348f

Browse files
committed
fix(esp_hw_support): add p4 rev3.0 MSPI workaround for deepsleep
1 parent bb2052f commit 3ee348f

File tree

15 files changed

+207
-16
lines changed

15 files changed

+207
-16
lines changed

components/bootloader_support/src/bootloader_common_loader.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,11 @@ rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void)
263263
#ifdef BOOTLOADER_BUILD
264264

265265
#if ESP_ROM_HAS_LP_ROM
266+
#if CONFIG_IDF_TARGET_ESP32P4
267+
#define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_LOW + CONFIG_P4_REV3_MSPI_WORKAROUND_SIZE)
268+
#else
266269
#define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_LOW)
270+
#endif
267271
#else
268272
/* Since the structure containing the retain_mem_t is aligned on 8 by the linker, make sure we align this
269273
* structure size here too */

components/esp_hw_support/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,5 @@ menu "Hardware Settings"
309309
bool "Place esp_intr_alloc functions in IRAM" if SPI_FLASH_AUTO_SUSPEND
310310
default y
311311

312+
orsource "./lowpower/port/esp32p4/Kconfig.p4_rev3_mspi_workaround"
312313
endmenu

components/esp_hw_support/lowpower/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP OR
1818
endif()
1919
endif()
2020

21+
if(CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND)
22+
list(APPEND srcs "port/esp32p4/p4_rev3_mspi_workaround.S")
23+
set_property(TARGET ${COMPONENT_LIB}
24+
APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u p4_rev3_mspi_workaround")
25+
endif()
26+
2127
if(CONFIG_SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD AND CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
2228
list(APPEND srcs "port/${target}/sleep_mmu.c")
2329
endif()
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
config P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
2+
bool
3+
depends on IDF_TARGET_ESP32P4
4+
default y if ESP32P4_REV_MIN_300
5+
6+
config P4_REV3_MSPI_WORKAROUND_SIZE
7+
hex
8+
depends on IDF_TARGET_ESP32P4
9+
default 0x100 if ESP32P4_REV_MIN_300
10+
default 0
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "soc/reg_base.h"
8+
9+
#define HP_SYSTEM_CORE_ERR_RESP_DIS_REG (DR_REG_HP_SYS_BASE + 0x1a4)
10+
11+
/* Clock related */
12+
#define DR_REG_LP_CLKRST_BASE (DR_REG_LPAON_BASE + 0x1000)
13+
#define LP_CLKRST_HPCPU_RESET_CTRL0_REG (DR_REG_LP_CLKRST_BASE + 0x14)
14+
#define LP_CLKRST_HPCORE0_STAT_VECTOR_SEL (1 << 15)
15+
16+
#define HP_SYS_CLKRST_HP_RST_EN0_REG (DR_REG_HP_SYS_CLKRST_BASE + 0xc0)
17+
#define HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI (1 << 22)
18+
#define HP_SYS_CLKRST_REG_RST_EN_MSPI_APB (1 << 24)
19+
20+
21+
/* SPIMEM related */
22+
#define DR_REG_FLASH_SPI0_BASE (DR_REG_HPPERIPH0_BASE + 0x8C000)
23+
#define SPI_MEM_C_CACHE_FCTRL_REG (DR_REG_FLASH_SPI0_BASE + 0x3c)
24+
#define SPI_MEM_C_CLOSE_AXI_INF_EN (1 << 31)
25+
#define SPI_MEM_C_AXI_REQ_EN (1 << 0)
26+
27+
#define SPI_MEM_C_MMU_ITEM_INDEX_REG (DR_REG_FLASH_SPI0_BASE + 0x380)
28+
#define SPI_MEM_C_MMU_ITEM_CONTENT_REG (DR_REG_FLASH_SPI0_BASE + 0x37c)
29+
30+
.macro REG_SET_BIT addr, value
31+
li a0, \addr
32+
li a1, \value
33+
lw a2, (a0)
34+
or a2, a2, a1
35+
sw a2, (a0)
36+
.endm
37+
38+
.macro REG_CLR_BIT addr, value
39+
li a0, \addr
40+
/* Since all our parameters will be constants, we can pre-calculate it at assemble time */
41+
li a1, ~\value
42+
lw a2, (a0)
43+
and a2, a2, a1
44+
sw a2, (a0)
45+
.endm
46+
47+
.macro REG_WRITE addr, value
48+
li a0, \addr
49+
li a1, \value
50+
sw a1, (a0)
51+
.endm
52+
53+
.macro REG_READ addr
54+
li a0, \addr
55+
lw a1, (a0)
56+
.endm
57+
58+
.macro DELAY_US us
59+
li t3, (40 * \us) /* CPU @40MHz after reset */
60+
csrr t0, cycle
61+
add t1, t0, t3
62+
1: csrr t2, cycle
63+
blt t2, t1, 1b
64+
.endm
65+
66+
/**
67+
* @brief Workaround for MSPI issues on ESP32-P4 revision 3
68+
*
69+
* This function implements a workaround for MSPI-related issues on ESP32-P4 revision 3.
70+
* It performs 2 flash dummy reads to stabilize the MSPI functionality before jumping to
71+
* ROM code after deepsleep wakeup.
72+
*/
73+
.global p4_rev3_mspi_workaround
74+
.section .p4_rev3_mspi_workaround.rtc_text,"ax"
75+
76+
p4_rev3_mspi_workaround:
77+
# Recover the reset vector to HP ROM
78+
REG_SET_BIT LP_CLKRST_HPCPU_RESET_CTRL0_REG, LP_CLKRST_HPCORE0_STAT_VECTOR_SEL
79+
80+
# Clear the bit to close AXI interface and then set the AXI request enable bit
81+
REG_CLR_BIT SPI_MEM_C_CACHE_FCTRL_REG, SPI_MEM_C_CLOSE_AXI_INF_EN
82+
REG_SET_BIT SPI_MEM_C_CACHE_FCTRL_REG, SPI_MEM_C_AXI_REQ_EN
83+
84+
# Set 1 mspi mmu entry for axi addr to flash addr
85+
REG_WRITE SPI_MEM_C_MMU_ITEM_INDEX_REG, 0
86+
REG_WRITE SPI_MEM_C_MMU_ITEM_CONTENT_REG, 0x1000
87+
88+
# Disable cpu get error response
89+
REG_WRITE HP_SYSTEM_CORE_ERR_RESP_DIS_REG, 0x7
90+
91+
# Perform dummy reads
92+
REG_READ 0x80000000
93+
# Perform dummy reads again
94+
REG_READ 0x80000080
95+
96+
# Delay 1us to wait MSPI read transmission done
97+
DELAY_US 1
98+
99+
# Enable cpu get error response
100+
REG_WRITE HP_SYSTEM_CORE_ERR_RESP_DIS_REG, 0
101+
102+
# Reset MSPI AXI and APB interfaces
103+
REG_SET_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI
104+
REG_SET_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_APB
105+
REG_CLR_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI
106+
REG_CLR_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_APB
107+
108+
# Jump to HP ROM first stage boot code
109+
li a5, 0x4fc00000
110+
jr a5

components/esp_hw_support/port/esp32p4/pmu_sleep.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "hal/pmu_hal.h"
3131
#include "hal/psram_ctrlr_ll.h"
3232
#include "hal/lp_sys_ll.h"
33+
#include "hal/lp_clkrst_ll.h"
3334
#include "hal/clk_gate_ll.h"
3435
#include "esp_private/esp_pmu.h"
3536
#include "pmu_param.h"
@@ -419,6 +420,10 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
419420
#endif
420421
rtc_clk_mpll_disable();
421422
}
423+
} else {
424+
#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
425+
lp_clkrst_ll_boot_from_lp_ram(true);
426+
#endif
422427
}
423428

424429

@@ -442,12 +447,16 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
442447
;
443448
}
444449

445-
#if CONFIG_SPIRAM && CONFIG_ESP_LDO_RESERVE_PSRAM
446-
// Enable PSRAM chip power supply after deepsleep request rejected
447450
if (dslp) {
451+
#if CONFIG_SPIRAM && CONFIG_ESP_LDO_RESERVE_PSRAM
452+
// Enable PSRAM chip power supply after deepsleep request rejected
448453
ldo_ll_enable(LDO_ID2UNIT(CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN), true);
449-
}
450454
#endif
455+
#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
456+
// Set reset vector back to HP ROM after deepsleep request rejected
457+
lp_clkrst_ll_boot_from_lp_ram(false);
458+
#endif
459+
}
451460

452461
return pmu_sleep_finish(dslp);
453462
}

components/esp_system/ld/esp32p4/memory.ld.in

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@
3232
#define SRAM_HIGH_END SRAM_HIGH_START + SRAM_HIGH_SIZE
3333
#endif
3434

35+
#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
36+
#define MSPI_WORKAROUND_SIZE CONFIG_P4_REV3_MSPI_WORKAROUND_SIZE
37+
#else
38+
#define MSPI_WORKAROUND_SIZE 0x0
39+
#endif
40+
3541
#define IDROM_SEG_SIZE (CONFIG_MMU_PAGE_SIZE << 10)
3642

3743
#define LP_ROM_DRAM_START 0x5010fa80 // Value taken from ROM elf, includes LP ROM stack
@@ -90,14 +96,17 @@ MEMORY
9096
/* (See irom_seg for meaning of 0x20 offset in the above.) */
9197
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
9298

99+
/* Used to store the deep sleep workaround code of P4 rev3.0. The reset vector will be set here before the chip enters sleep. */
100+
rev3_mspi_workaround_seg(RWX) : org = 0x50108000, len = MSPI_WORKAROUND_SIZE
101+
93102
/**
94103
* lp ram memory (RWX). Persists over deep sleep. // TODO: IDF-5667
95104
*/
96105
#if CONFIG_ULP_COPROC_ENABLED
97-
lp_ram_seg(RW) : org = 0x50108000 + RESERVE_RTC_MEM + CONFIG_ULP_COPROC_RESERVE_MEM,
106+
lp_ram_seg(RW) : org = 0x50108000 + MSPI_WORKAROUND_SIZE + RESERVE_RTC_MEM + CONFIG_ULP_COPROC_RESERVE_MEM,
98107
len = 0x8000 - CONFIG_ULP_COPROC_RESERVE_MEM - RESERVE_RTC_MEM - LP_ROM_DRAM_SIZE
99108
#else
100-
lp_ram_seg(RW) : org = 0x50108000 + RESERVE_RTC_MEM, len = 0x8000 - RESERVE_RTC_MEM
109+
lp_ram_seg(RW) : org = 0x50108000 + MSPI_WORKAROUND_SIZE + RESERVE_RTC_MEM, len = 0x8000 - RESERVE_RTC_MEM - MSPI_WORKAROUND_SIZE
101110
#endif // CONFIG_ULP_COPROC_ENABLED
102111

103112
/* We reduced the size of lp_ram_seg by RESERVE_RTC_MEM value.
@@ -108,7 +117,7 @@ MEMORY
108117
The aim of this is to keep data that will not be moved around and have a fixed address.
109118
This segment is placed at the beginning of LP RAM, as the end of LP RAM is occupied by LP ROM stack/data
110119
*/
111-
lp_reserved_seg(RW) : org = 0x50108000, len = RESERVE_RTC_MEM
120+
lp_reserved_seg(RW) : org = 0x50108000 + MSPI_WORKAROUND_SIZE, len = RESERVE_RTC_MEM
112121

113122
/* PSRAM seg */
114123
extern_ram_seg(RWX) : org = 0x48000000, len = IDROM_SEG_SIZE

components/esp_system/ld/esp32p4/sections.rev3.ld.in

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,15 @@ SECTIONS
115115
ALIGNED_SYMBOL(4, _rtc_force_slow_end)
116116
} > lp_ram_seg
117117

118+
#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
119+
.rtc.p4_rev3_mspi_workaround :
120+
{
121+
ALIGNED_SYMBOL(4, _rtc_p4_rev3_mspi_workaround_start)
122+
KEEP (*(.p4_rev3_mspi_workaround.rtc_text .p4_rev3_mspi_workaround.rtc_text.*))
123+
ALIGNED_SYMBOL(4, _rtc_p4_rev3_mspi_workaround_end)
124+
} > rev3_mspi_workaround_seg
125+
#endif
126+
118127
/**
119128
* This section holds RTC data that should have fixed addresses.
120129
* The data are not initialized at power-up and are retained during deep
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
// The LL layer for ESP32-P4 LP_CLKRST register operations
8+
9+
#pragma once
10+
11+
#include <stdbool.h>
12+
#include <stdlib.h>
13+
#include "soc/soc.h"
14+
#include "soc/lp_clkrst_struct.h"
15+
16+
#ifdef __cplusplus
17+
extern "C" {
18+
#endif
19+
20+
21+
/**
22+
* Select CPU reset vector
23+
* @param boot_from_lp_ram
24+
* true: boot from LP TCM RAM: 0x50108000
25+
* false: boot from HP TCM ROM: 0x4FC00000
26+
*/
27+
__attribute__((always_inline))
28+
static inline void lp_clkrst_ll_boot_from_lp_ram(bool boot_from_lp_ram)
29+
{
30+
LP_AON_CLKRST.hpcpu_reset_ctrl0.hpcore0_stat_vector_sel = !boot_from_lp_ram;
31+
}
32+
33+
#ifdef __cplusplus
34+
}
35+
#endif

components/hal/esp32p4/include/hal/lp_sys_ll.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "soc/soc.h"
1414
#include "soc/lp_system_struct.h"
1515
#include "hal/misc.h"
16+
#include "hal/config.h"
1617
#include "esp32p4/rom/rtc.h"
1718

1819

0 commit comments

Comments
 (0)