Merge branch 'feature/p4_rev3_sdmmc' into 'master'

sdmmc: supported sdmmc on p4 ECO5 real chip, and UHS-I SDR104 (200MHz)

Closes IDF-12222, IDF-13731, and IDF-14050

See merge request espressif/esp-idf!41563
This commit is contained in:
Armando (Dou Yiwen)
2025-09-17 09:09:24 +00:00
8 changed files with 56 additions and 1539 deletions

View File

@@ -217,8 +217,8 @@ static esp_err_t sd_host_slot_sdmmc_configure(sd_host_slot_handle_t slot, const
if (config->freq_hz == SDMMC_FREQ_SDR104 * 1000) {
unsigned chip_version = efuse_hal_chip_revision();
ESP_LOGD(TAG, "chip_version: %d", chip_version);
if (!ESP_CHIP_REV_ABOVE(chip_version, 200)) {
ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "UHS-I SDR104 is not supported on ESP32P4 chips prior than v2.0");
if (!ESP_CHIP_REV_ABOVE(chip_version, 300)) {
ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "UHS-I SDR104 is not supported on ESP32P4 chips prior than v3.0");
}
}
#endif

View File

@@ -38,6 +38,7 @@ esp_err_t sd_pwr_ctrl_new_on_chip_ldo(const sd_pwr_ctrl_ldo_config_t *configs, s
ESP_GOTO_ON_FALSE(ctx, ESP_ERR_NO_MEM, err, TAG, "no mem for on-chip ldo control driver context");
esp_ldo_channel_config_t chan_cfg = {
.voltage_mv = 3300,
.chan_id = configs->ldo_chan_id,
.flags.adjustable = true, // the SDMMC power control driver will adjust the voltage later according to different speed mode
};

File diff suppressed because it is too large Load Diff

View File

@@ -484,63 +484,6 @@ typedef union {
uint32_t val;
} sdhost_cmd_reg_t;
/** Group: Response data register */
/** Type of resp0 register
* Response data register
*/
typedef union {
struct {
/** response0_reg : RO; bitpos: [31:0]; default: 0;
* Bit[31:0] of response.
*/
uint32_t response0_reg:32;
};
uint32_t val;
} sdhost_resp0_reg_t;
/** Group: Long response data register */
/** Type of resp1 register
* Long response data register
*/
typedef union {
struct {
/** response1_reg : RO; bitpos: [31:0]; default: 0;
* Bit[63:32] of long response.
*/
uint32_t response1_reg:32;
};
uint32_t val;
} sdhost_resp1_reg_t;
/** Type of resp2 register
* Long response data register
*/
typedef union {
struct {
/** response2_reg : RO; bitpos: [31:0]; default: 0;
* Bit[95:64] of long response.
*/
uint32_t response2_reg:32;
};
uint32_t val;
} sdhost_resp2_reg_t;
/** Type of resp3 register
* Long response data register
*/
typedef union {
struct {
/** response3_reg : RO; bitpos: [31:0]; default: 0;
* Bit[127:96] of long response.
*/
uint32_t response3_reg:32;
};
uint32_t val;
} sdhost_resp3_reg_t;
/** Group: Masked interrupt status register */
/** Type of mintsts register
* Masked interrupt status register
@@ -606,22 +549,7 @@ typedef union {
* Bit 1 (RE): Response error;
* Bit 0 (CD): Card detect.
*/
uint32_t cd:1;
uint32_t re:1;
uint32_t cmd_done:1;
uint32_t dto:1;
uint32_t txdr:1;
uint32_t rxdr:1;
uint32_t rcrc:1;
uint32_t dcrc:1;
uint32_t rto:1;
uint32_t drto:1;
uint32_t hto:1;
uint32_t frun:1;
uint32_t hle:1;
uint32_t sbi_bci:1;
uint32_t acd:1;
uint32_t ebe:1;
uint32_t int_status_raw:16;
/** sdio_interrupt_raw : R/W; bitpos: [17:16]; default: 0;
* Interrupt from SDIO card, one bit for each card. Bit[17:16] correspond to card1 and
* card0, respectively. Setting a bit clears the corresponding interrupt bit and
@@ -922,8 +850,8 @@ typedef union {
uint32_t reserved_0:14;
/** ddr : R/W; bitpos: [17:16]; default: 0;
* DDR mode selection,1 bit for each card.
* 0: Non-DDR mode.
* 1: DDR mode.
* 0-Non-DDR mode.
* 1-DDR mode.
*/
uint32_t ddr:2;
uint32_t reserved_18:14;
@@ -1444,7 +1372,7 @@ typedef struct sdmmc_dev_t {
volatile sdhost_intmask_reg_t intmask;
volatile uint32_t cmdarg;
volatile sdhost_cmd_reg_t cmd;
volatile uint32_t resp[4]; ///< Response from card
volatile uint32_t resp[4];
volatile sdhost_mintsts_reg_t mintsts;
volatile sdhost_rintsts_reg_t rintsts;
volatile sdhost_status_reg_t status;

View File

@@ -74,7 +74,7 @@ Overview
.. only:: esp32p4
- :c:macro:`SDMMC_HOST_SLOT_1` is routed via GPIO Matrix. This means that any GPIO may be used for each of the SD card signals. It is for non UHS-I usage.
- :c:macro:`SDMMC_HOST_SLOT_0` is dedicated to UHS-I mode, which is not yet supported in the driver.
- :c:macro:`SDMMC_HOST_SLOT_0` is dedicated to UHS-I mode.
On {IDF_TARGET_NAME}, SDMMC host requires an external power supply for the IO voltage. Please refer to :ref:`pwr-ctrl` for details.
@@ -87,6 +87,7 @@ SDMMC Host driver supports the following speed modes:
- Default Speed (20 MHz): 1-line or 4-line with SD cards, and 1-line, 4-line, or 8-line with 3.3 V eMMC
- High Speed (40 MHz): 1-line or 4-line with SD cards, and 1-line, 4-line, or 8-line with 3.3 V eMMC
:SOC_SDMMC_UHS_I_SUPPORTED: - UHS-I 1.8 V, SDR104 (200 MHz): 4-line with SD cards
:SOC_SDMMC_UHS_I_SUPPORTED: - UHS-I 1.8 V, SDR50 (100 MHz): 4-line with SD cards
:SOC_SDMMC_UHS_I_SUPPORTED: - UHS-I 1.8 V, DDR50 (50 MHz): 4-line with SD cards
- High Speed DDR (40 MHz): 4-line with 3.3 V eMMC

View File

@@ -74,7 +74,7 @@ SDMMC 主机驱动
.. only:: esp32p4
- 卡槽 :c:macro:`SDMMC_HOST_SLOT_1` 通过 GPIO 交换矩阵路由,即任何 GPIO 都可以用于每个 SD 卡信号。这适用于非 UHS-I 用途。
- 卡槽 :c:macro:`SDMMC_HOST_SLOT_0` 专用于 UHS-I 模式,驱动程序中尚不支持该模式
- 卡槽 :c:macro:`SDMMC_HOST_SLOT_0` 专用于 UHS-I 模式。
在 {IDF_TARGET_NAME} 上SDMMC 主机需要外部电源为 IO 电压供电。详情请参阅 :ref:`pwr-ctrl`
@@ -87,6 +87,7 @@ SDMMC 主机驱动支持以下速率模式:
- 默认速率 (20 MHz):对于 SD 卡,支持 1 线或 4 线传输;对于 3.3 V eMMC支持 1 线、4 线或 8 线传输。
- 高速模式 (40 MHz):对于 SD 卡,支持 1 线或 4 线传输;对于 3.3 V eMMC支持 1 线、4 线或 8 线传输。
:SOC_SDMMC_UHS_I_SUPPORTED: - UHS-I 1.8 V, SDR104 模式 (200 MHz):支持 4 线 SD 卡传输。
:SOC_SDMMC_UHS_I_SUPPORTED: - UHS-I 1.8 V SDR50 模式 (100 MHz):支持 4 线 SD 卡传输。
:SOC_SDMMC_UHS_I_SUPPORTED: - UHS-I 1.8 V DDR50 模式 (50 MHz):支持 4 线 SD 卡传输。
- 高速 DDR 模式 (40 MHz):对于 3.3 V eMMC支持 4 线传输。

View File

@@ -47,6 +47,12 @@ menu "SD/MMC Example Configuration"
depends on SOC_SDMMC_UHS_I_SUPPORTED
endchoice
config EXAMPLE_PIN_CARD_POWER_RESET
int
depends on SOC_SDMMC_IO_POWER_EXTERNAL
prompt "Card Power Reset"
default 45
config EXAMPLE_PIN_CMD
int
prompt "CMD GPIO number" if SOC_SDMMC_USE_GPIO_MATRIX

View File

@@ -14,6 +14,7 @@
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "driver/sdmmc_host.h"
#include "driver/gpio.h"
#include "sd_test_io.h"
#if SOC_SDMMC_IO_POWER_EXTERNAL
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
@@ -98,6 +99,38 @@ static esp_err_t s_example_read_file(const char *path)
return ESP_OK;
}
#if CONFIG_EXAMPLE_PIN_CARD_POWER_RESET
static esp_err_t s_example_reset_card_power(void)
{
esp_err_t ret = ESP_FAIL;
gpio_config_t io_conf = {
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = (1ULL<<CONFIG_EXAMPLE_PIN_CARD_POWER_RESET),
};
ret = gpio_config(&io_conf);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to config GPIO");
return ret;
}
ret = gpio_set_level(CONFIG_EXAMPLE_PIN_CARD_POWER_RESET, 1);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to set GPIO level");
return ret;
}
vTaskDelay(100 / portTICK_PERIOD_MS);
ret = gpio_set_level(CONFIG_EXAMPLE_PIN_CARD_POWER_RESET, 0);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to set GPIO level");
return ret;
}
return ESP_OK;
}
#endif // CONFIG_EXAMPLE_PIN_CARD_POWER_RESET
void app_main(void)
{
esp_err_t ret;
@@ -161,6 +194,10 @@ void app_main(void)
host.pwr_ctrl_handle = pwr_ctrl_handle;
#endif
#if CONFIG_EXAMPLE_PIN_CARD_POWER_RESET
ESP_ERROR_CHECK(s_example_reset_card_power());
#endif
// This initializes the slot without card detect (CD) and write protect (WP) signals.
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();