Merge branch 'bugfix/pm-673_v5.5' into 'release/v5.5'

backport v5.5: fix analog i2c master race cause by phy retention link

See merge request espressif/esp-idf!46436
This commit is contained in:
Jiang Jiang Jian
2026-03-31 10:48:03 +08:00
5 changed files with 127 additions and 5 deletions
@@ -246,6 +246,13 @@ esp_err_t sleep_modem_state_phy_link_init(void **link_head);
* - ESP_ERR_INVALID_STATE if the phy module retention state is invalid
*/
esp_err_t sleep_modem_state_phy_link_deinit(void *link_head);
/**
* @brief Function to configure PHY link regdma description at runtime
* @param link_context PHY link regdma description conteoxt pointer
* @param flags A bitmap to indicate the PHY link regdma description configuration flag
*/
void sleep_modem_state_phy_link_config(void *link_context, uint32_t flags);
#endif
#ifdef __cplusplus
@@ -5,6 +5,7 @@
*/
#include "esp_log.h"
#include "esp_check.h"
#include "esp_attr.h"
#include "soc/soc_caps.h"
#include "soc/i2c_ana_mst_reg.h"
@@ -37,6 +38,13 @@
static __attribute__((unused)) const char *TAG = "sleep";
#if SOC_PM_PAU_REGDMA_LINK_IDX_WIFIMAC
typedef struct {
#define DESC_IDX_I2C_MST_ENA (0)
#define DESC_IDX_I2C_MST_DIS (1)
void *regdma_desc[DESC_IDX_I2C_MST_DIS + 1];
} sleep_modem_state_phy_link_context_t;
static esp_err_t sleep_modem_state_phy_wifi_init(void *arg)
{
#define WIFIMAC_ENTRY() (BIT(SOC_PM_PAU_REGDMA_LINK_IDX_WIFIMAC))
@@ -98,13 +106,41 @@ esp_err_t sleep_modem_state_phy_link_init(void **link_head)
if (err == ESP_OK) {
err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_MODEM_PHY);
if (err == ESP_OK) {
*link_head = sleep_retention_find_link_by_id(REGDMA_PHY_LINK(0x00));
const int id_array[] = { REGDMA_PHY_LINK(0x00), REGDMA_PHY_LINK(0x14) };
static DRAM_ATTR sleep_modem_state_phy_link_context_t phy_link_context;
for (int i = 0; (err == ESP_OK) && (i < ARRAY_SIZE(phy_link_context.regdma_desc)); i++) {
void *desc = sleep_retention_find_link_by_id(id_array[i]);
if (desc) {
phy_link_context.regdma_desc[i] = desc;
} else {
err = ESP_ERR_NOT_FOUND;
}
}
if (err == ESP_OK) {
*link_head = (void *)&phy_link_context;
}
}
}
#endif
return err;
}
void IRAM_ATTR sleep_modem_state_phy_link_config(void *link_context, uint32_t flags)
{
#if SOC_PM_PAU_REGDMA_LINK_IDX_WIFIMAC
sleep_modem_state_phy_link_context_t *phy_link_context = (sleep_modem_state_phy_link_context_t *)link_context;
if (flags & BIT(0)) {
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_ENA], true, true);
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_DIS], true, true);
} else {
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_ENA], true, false);
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_DIS], false, true);
}
#endif
}
esp_err_t sleep_modem_state_phy_link_deinit(void *link_head)
{
esp_err_t err = ESP_OK;
@@ -3,6 +3,8 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_attr.h"
#include "soc/soc_caps.h"
#include "soc/i2c_ana_mst_reg.h"
#include "soc/pmu_reg.h"
@@ -32,6 +34,14 @@
#define MODEM_FE_DATA_BASE (0x600a0400)
#define MODEM_FE_CTRL_BASE (0x600a0800)
typedef struct {
void *link_head;
#define DESC_IDX_I2C_MST_ENA (0)
#define DESC_IDX_I2C_MST_SEL (1)
#define DESC_IDX_I2C_MST_DIS (2)
void *regdma_desc[DESC_IDX_I2C_MST_DIS + 1];
} sleep_modem_state_phy_link_context_t;
esp_err_t sleep_modem_state_phy_link_init(void **link_head)
{
esp_err_t err = ESP_OK;
@@ -105,16 +115,46 @@ esp_err_t sleep_modem_state_phy_link_init(void **link_head)
}
if (err == ESP_OK) {
pau_regdma_set_modem_link_addr(link);
*link_head = link;
const int id_array[] = { REGDMA_PHY_LINK(0x00), REGDMA_PHY_LINK(0x01), REGDMA_PHY_LINK(0x1b) };
static DRAM_ATTR sleep_modem_state_phy_link_context_t phy_link_context;
for (int i = 0; (err == ESP_OK) && (i < ARRAY_SIZE(phy_link_context.regdma_desc)); i++) {
void *desc = regdma_find_link_by_id(link, 0, id_array[i]);
if (desc) {
phy_link_context.regdma_desc[i] = desc;
} else {
err = ESP_ERR_NOT_FOUND;
}
}
if (err == ESP_OK) {
phy_link_context.link_head = link;
*link_head = (void *)&phy_link_context;
}
}
#endif
return err;
}
void IRAM_ATTR sleep_modem_state_phy_link_config(void *link_context, uint32_t flags)
{
sleep_modem_state_phy_link_context_t *phy_link_context = (sleep_modem_state_phy_link_context_t *)link_context;
if (flags & BIT(0)) {
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_ENA], true, true);
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_SEL], true, true);
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_DIS], true, true);
} else {
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_ENA], true, false);
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_SEL], true, false);
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_DIS], false, true);
}
}
esp_err_t sleep_modem_state_phy_link_deinit(void *link_head)
{
#if SOC_PM_PAU_REGDMA_LINK_WIFIMAC
regdma_link_destroy(link_head, 0);
regdma_link_destroy(((sleep_modem_state_phy_link_context_t *)link_head)->link_head, 0);
#endif
return ESP_OK;
}
@@ -3,6 +3,8 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_attr.h"
#include "soc/soc_caps.h"
#include "soc/i2c_ana_mst_reg.h"
#include "soc/pmu_reg.h"
@@ -30,6 +32,13 @@
#define WDEVTXQ_BLOCK (0x600a4ca8)
#define WDEV_RXBLOCK (BIT(12))
typedef struct {
void *link_head;
#define DESC_IDX_I2C_MST_ENA (0)
#define DESC_IDX_I2C_MST_DIS (1)
void *regdma_desc[DESC_IDX_I2C_MST_DIS + 1];
} sleep_modem_state_phy_link_context_t;
esp_err_t sleep_modem_state_phy_link_init(void **link_head)
{
esp_err_t err = ESP_OK;
@@ -101,16 +110,44 @@ esp_err_t sleep_modem_state_phy_link_init(void **link_head)
}
if (err == ESP_OK) {
pau_regdma_set_modem_link_addr(link);
*link_head = link;
const int id_array[] = { REGDMA_PHY_LINK(0x00), REGDMA_PHY_LINK(0x1a) };
static DRAM_ATTR sleep_modem_state_phy_link_context_t phy_link_context;
for (int i = 0; (err == ESP_OK) && (i < ARRAY_SIZE(phy_link_context.regdma_desc)); i++) {
void *desc = regdma_find_link_by_id(link, 0, id_array[i]);
if (desc) {
phy_link_context.regdma_desc[i] = desc;
} else {
err = ESP_ERR_NOT_FOUND;
}
}
if (err == ESP_OK) {
phy_link_context.link_head = link;
*link_head = (void *)&phy_link_context;
}
}
#endif
return err;
}
void IRAM_ATTR sleep_modem_state_phy_link_config(void *link_context, uint32_t flags)
{
sleep_modem_state_phy_link_context_t *phy_link_context = (sleep_modem_state_phy_link_context_t *)link_context;
if (flags & BIT(0)) {
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_ENA], true, true);
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_DIS], true, true);
} else {
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_ENA], true, false);
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_DIS], false, true);
}
}
esp_err_t sleep_modem_state_phy_link_deinit(void *link_head)
{
#if SOC_PM_PAU_REGDMA_LINK_WIFIMAC
regdma_link_destroy(link_head, 0);
regdma_link_destroy(((sleep_modem_state_phy_link_context_t *)link_head)->link_head, 0);
#endif
return ESP_OK;
}
+2
View File
@@ -173,7 +173,9 @@ __attribute__((unused)) void sleep_modem_wifi_modem_state_deinit(void)
void IRAM_ATTR sleep_modem_wifi_do_phy_retention(bool restore)
{
sleep_modem_state_phy_link_config(s_sleep_modem.wifi.phy_link, 1);
sleep_retention_do_phy_retention(!restore);
sleep_modem_state_phy_link_config(s_sleep_modem.wifi.phy_link, 0);
if (!restore) {
s_sleep_modem.wifi.modem_state_phy_done = 1;
}