From 17c65dad272885c5cc03db56525dcd0bcc82b609 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 4 Jan 2021 20:34:31 +0100 Subject: [PATCH] soc: add esp32s3 sdmmc support * sync the latest struct header file from ESP32 * add soc_caps.h macros to distinguish between IO MUX and GPIO Matrix support in SDMMC on different chips. * store GPIO matrix signal numbers in sdmmc_slot_info_t --- components/esp32s3/ld/esp32s3.peripherals.ld | 1 + components/soc/esp32/include/soc/soc_caps.h | 8 +++ components/soc/esp32/sdmmc_periph.c | 53 +++++++++-------- .../soc/esp32s3/include/soc/sdmmc_pins.h | 22 +------ .../soc/esp32s3/include/soc/sdmmc_struct.h | 34 ++++++++--- components/soc/esp32s3/include/soc/soc_caps.h | 11 ++++ components/soc/esp32s3/sdmmc_periph.c | 53 +++++++++-------- components/soc/include/soc/sdmmc_periph.h | 58 ++++++++++++++----- 8 files changed, 150 insertions(+), 90 deletions(-) diff --git a/components/esp32s3/ld/esp32s3.peripherals.ld b/components/esp32s3/ld/esp32s3.peripherals.ld index 5e0188ee9a..4df638a025 100644 --- a/components/esp32s3/ld/esp32s3.peripherals.ld +++ b/components/esp32s3/ld/esp32s3.peripherals.ld @@ -28,6 +28,7 @@ PROVIDE ( GPSPI2 = 0x60024000 ); PROVIDE ( GPSPI3 = 0x60025000 ); PROVIDE ( SYSCON = 0x60026000 ); PROVIDE ( I2C1 = 0x60027000 ); +PROVIDE ( SDMMC = 0x60028000 ); PROVIDE ( TWAI = 0x6002B000 ); PROVIDE ( GPSPI4 = 0x60037000 ); PROVIDE ( GDMA = 0x6003F000 ); diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 4fd8632706..2031df36ee 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -282,3 +282,11 @@ # define CAN_BRP_DIV_SUPPORTED SOC_TWAI_BRP_DIV_SUPPORTED # define CAN_BRP_DIV_THRESH SOC_TWAI_BRP_DIV_THRESH #endif + +/*-------------------------- SDMMC CAPS -----------------------------------------*/ + +/* On ESP32, clock/cmd/data pins use IO MUX. + * Card detect, write protect, interrupt use GPIO Matrix on all chips. + */ +#define SOC_SDMMC_USE_IOMUX 1 +#define SOC_SDMMC_NUM_SLOTS 2 diff --git a/components/soc/esp32/sdmmc_periph.c b/components/soc/esp32/sdmmc_periph.c index db3af78203..9b98bffcbb 100644 --- a/components/soc/esp32/sdmmc_periph.c +++ b/components/soc/esp32/sdmmc_periph.c @@ -14,37 +14,44 @@ #include "soc/sdmmc_periph.h" -const sdmmc_slot_info_t sdmmc_slot_info[2] = { +const sdmmc_slot_info_t sdmmc_slot_info[SOC_SDMMC_NUM_SLOTS] = { { - .clk_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_CLK, - .cmd_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_CMD, - .d0_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D0, - .d1_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D1, - .d2_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D2, - .d3_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D3, - .d4_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D4, - .d5_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D5, - .d6_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D6, - .d7_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D7, + .width = 8, .card_detect = HOST_CARD_DETECT_N_1_IDX, .write_protect = HOST_CARD_WRITE_PRT_1_IDX, .card_int = HOST_CARD_INT_N_1_IDX, - .width = 8 }, { - .clk_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_CLK, - .cmd_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_CMD, - .d0_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_D0, - .d1_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_D1, - .d2_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_D2, - .d3_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_D3, - .d4_gpio = -1, //slot1 has no D4-7 - .d5_gpio = -1, - .d6_gpio = -1, - .d7_gpio = -1, + .width = 4, .card_detect = HOST_CARD_DETECT_N_2_IDX, .write_protect = HOST_CARD_WRITE_PRT_2_IDX, .card_int = HOST_CARD_INT_N_2_IDX, - .width = 4 + } +}; + +const sdmmc_slot_io_info_t sdmmc_slot_gpio_num[SOC_SDMMC_NUM_SLOTS] = { + { + .clk = SDMMC_SLOT0_IOMUX_PIN_NUM_CLK, + .cmd = SDMMC_SLOT0_IOMUX_PIN_NUM_CMD, + .d0 = SDMMC_SLOT0_IOMUX_PIN_NUM_D0, + .d1 = SDMMC_SLOT0_IOMUX_PIN_NUM_D1, + .d2 = SDMMC_SLOT0_IOMUX_PIN_NUM_D2, + .d3 = SDMMC_SLOT0_IOMUX_PIN_NUM_D3, + .d4 = SDMMC_SLOT0_IOMUX_PIN_NUM_D4, + .d5 = SDMMC_SLOT0_IOMUX_PIN_NUM_D5, + .d6 = SDMMC_SLOT0_IOMUX_PIN_NUM_D6, + .d7 = SDMMC_SLOT0_IOMUX_PIN_NUM_D7, + }, + { + .clk = SDMMC_SLOT1_IOMUX_PIN_NUM_CLK, + .cmd = SDMMC_SLOT1_IOMUX_PIN_NUM_CMD, + .d0 = SDMMC_SLOT1_IOMUX_PIN_NUM_D0, + .d1 = SDMMC_SLOT1_IOMUX_PIN_NUM_D1, + .d2 = SDMMC_SLOT1_IOMUX_PIN_NUM_D2, + .d3 = SDMMC_SLOT1_IOMUX_PIN_NUM_D3, + .d4 = -1, //slot1 has no D4-7 + .d5 = -1, + .d6 = -1, + .d7 = -1, } }; diff --git a/components/soc/esp32s3/include/soc/sdmmc_pins.h b/components/soc/esp32s3/include/soc/sdmmc_pins.h index b279793b6d..107bbf94ad 100644 --- a/components/soc/esp32s3/include/soc/sdmmc_pins.h +++ b/components/soc/esp32s3/include/soc/sdmmc_pins.h @@ -14,22 +14,6 @@ #pragma once -#define SDMMC_SLOT0_IOMUX_PIN_NUM_CLK 6 -#define SDMMC_SLOT0_IOMUX_PIN_NUM_CMD 11 -#define SDMMC_SLOT0_IOMUX_PIN_NUM_D0 7 -#define SDMMC_SLOT0_IOMUX_PIN_NUM_D1 8 -#define SDMMC_SLOT0_IOMUX_PIN_NUM_D2 9 -#define SDMMC_SLOT0_IOMUX_PIN_NUM_D3 10 -#define SDMMC_SLOT0_IOMUX_PIN_NUM_D4 16 -#define SDMMC_SLOT0_IOMUX_PIN_NUM_D5 17 -#define SDMMC_SLOT0_IOMUX_PIN_NUM_D6 5 -#define SDMMC_SLOT0_IOMUX_PIN_NUM_D7 18 -#define SDMMC_SLOT0_FUNC 0 - -#define SDMMC_SLOT1_IOMUX_PIN_NUM_CLK 14 -#define SDMMC_SLOT1_IOMUX_PIN_NUM_CMD 15 -#define SDMMC_SLOT1_IOMUX_PIN_NUM_D0 2 -#define SDMMC_SLOT1_IOMUX_PIN_NUM_D1 4 -#define SDMMC_SLOT1_IOMUX_PIN_NUM_D2 12 -#define SDMMC_SLOT1_IOMUX_PIN_NUM_D3 13 -#define SDMMC_SLOT1_FUNC 4 +/* SDMMC pins on ESP32-S3 are configurable through GPIO matrix. + * This file is kept for compatibility only. + */ diff --git a/components/soc/esp32s3/include/soc/sdmmc_struct.h b/components/soc/esp32s3/include/soc/sdmmc_struct.h index dc4e65df0c..6f5eef66ec 100644 --- a/components/soc/esp32s3/include/soc/sdmmc_struct.h +++ b/components/soc/esp32s3/include/soc/sdmmc_struct.h @@ -19,7 +19,7 @@ extern "C" { #endif -typedef struct { +typedef struct sdmmc_desc_s { uint32_t reserved1: 1; uint32_t disable_int_on_completion: 1; uint32_t last_descriptor: 1; @@ -32,10 +32,10 @@ typedef struct { uint32_t buffer1_size: 13; uint32_t buffer2_size: 13; uint32_t reserved3: 6; - void *buffer1_ptr; + void* buffer1_ptr; union { - void *buffer2_ptr; - void *next_desc_ptr; + void* buffer2_ptr; + void* next_desc_ptr; }; } sdmmc_desc_t; @@ -44,7 +44,7 @@ typedef struct { _Static_assert(sizeof(sdmmc_desc_t) == 16, "invalid size of sdmmc_desc_t structure"); -typedef struct { +typedef struct sdmmc_hw_cmd_s { uint32_t cmd_index: 6; ///< Command index uint32_t response_expect: 1; ///< set if response is expected uint32_t response_long: 1; ///< 0: short response expected, 1: long response expected @@ -73,7 +73,7 @@ typedef struct { _Static_assert(sizeof(sdmmc_hw_cmd_t) == 4, "invalid size of sdmmc_cmd_t structure"); -typedef volatile struct { +typedef volatile struct sdmmc_dev_s { union { struct { uint32_t controller_reset: 1; @@ -282,7 +282,12 @@ typedef volatile struct { uint32_t usrid; ///< user ID uint32_t verid; ///< IP block version uint32_t hcon; ///< compile-time IP configuration - uint32_t uhs; ///< TBD + union { + struct { + uint32_t voltage: 16; ///< voltage control for slots; no-op on ESP32. + uint32_t ddr: 16; ///< bit N enables DDR mode for card N + }; + } uhs; ///< UHS related settings union { struct { @@ -306,7 +311,7 @@ typedef volatile struct { } bmod; uint32_t pldmnd; ///< set any bit to resume IDMAC FSM from suspended state - sdmmc_desc_t *dbaddr; ///< descriptor list base + sdmmc_desc_t* dbaddr; ///< descriptor list base union { struct { @@ -347,7 +352,16 @@ typedef volatile struct { uint32_t bufaddrl; ///< unused uint32_t bufaddru; ///< unused uint32_t reserved_a8[22]; - uint32_t cardthrctl; + union { + struct { + uint32_t read_thr_en : 1; ///< initiate transfer only if FIFO has more space than the read threshold + uint32_t busy_clr_int_en : 1; ///< enable generation of busy clear interrupts + uint32_t write_thr_en : 1; ///< equivalent of read_thr_en for writes + uint32_t reserved1 : 13; + uint32_t card_threshold : 12; ///< threshold value for reads/writes, in bytes + }; + uint32_t val; + } cardthrctl; uint32_t back_end_power; uint32_t uhs_reg_ext; uint32_t emmc_ddr_reg; @@ -361,6 +375,8 @@ typedef volatile struct { uint32_t div_factor_p: 4; ///< controls clock period; it will be (div_factor_p + 1) / 160MHz uint32_t div_factor_h: 4; ///< controls length of high pulse; it will be (div_factor_h + 1) / 160MHz uint32_t div_factor_m: 4; ///< should be equal to div_factor_p + uint32_t reserved1 : 2; + uint32_t clk_sel : 1; ///< clock source select (0: XTAL, 1: 160 MHz from PLL) }; uint32_t val; } clock; diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 231057f879..307e960c18 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -21,6 +21,7 @@ #define SOC_HMAC_SUPPORTED 1 #define SOC_ASYNC_MEMCPY_SUPPORTED 1 #define SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 3 +#define SOC_SDMMC_HOST_SUPPORTED 1 /*-------------------------- ADC CAPS ----------------------------------------*/ @@ -214,3 +215,13 @@ #define SOC_SPI_MEM_SUPPORT_SW_SUSPEND (1) /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) + +/*-------------------------- SDMMC CAPS -----------------------------------------*/ + +/* Card detect, write protect, interrupt use GPIO Matrix on all chips. + * On ESP32-S3, clock/cmd/data pins use GPIO Matrix as well. + */ +#define SOC_SDMMC_USE_GPIO_MATRIX 1 +#define SOC_SDMMC_NUM_SLOTS 2 +/* Indicates that there is an option to use XTAL clock instead of PLL for SDMMC */ +#define SOC_SDMMC_SUPPORT_XTAL_CLOCK 1 diff --git a/components/soc/esp32s3/sdmmc_periph.c b/components/soc/esp32s3/sdmmc_periph.c index 4bf7c14db8..0d9d9621ff 100644 --- a/components/soc/esp32s3/sdmmc_periph.c +++ b/components/soc/esp32s3/sdmmc_periph.c @@ -14,37 +14,44 @@ #include "soc/sdmmc_periph.h" -const sdmmc_slot_info_t sdmmc_slot_info[2] = { +const sdmmc_slot_info_t sdmmc_slot_info[SOC_SDMMC_NUM_SLOTS] = { { - .clk_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_CLK, - .cmd_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_CMD, - .d0_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D0, - .d1_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D1, - .d2_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D2, - .d3_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D3, - .d4_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D4, - .d5_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D5, - .d6_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D6, - .d7_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D7, + .width = 8, .card_detect = SDHOST_CARD_DETECT_N_1_IDX, .write_protect = SDHOST_CARD_WRITE_PRT_1_IDX, .card_int = SDHOST_CARD_INT_N_1_IDX, - .width = 8 }, { - .clk_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_CLK, - .cmd_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_CMD, - .d0_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_D0, - .d1_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_D1, - .d2_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_D2, - .d3_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_D3, - .d4_gpio = -1, //slot1 has no D4-7 - .d5_gpio = -1, - .d6_gpio = -1, - .d7_gpio = -1, + .width = 8, .card_detect = SDHOST_CARD_DETECT_N_2_IDX, .write_protect = SDHOST_CARD_WRITE_PRT_2_IDX, .card_int = SDHOST_CARD_INT_N_2_IDX, - .width = 4 + } +}; + +const sdmmc_slot_io_info_t sdmmc_slot_gpio_sig[SOC_SDMMC_NUM_SLOTS] = { + { + .clk = SDHOST_CCLK_OUT_1_IDX, + .cmd = SDHOST_CCMD_OUT_1_IDX, + .d0 = SDHOST_CDATA_OUT_10_IDX, + .d1 = SDHOST_CDATA_OUT_11_IDX, + .d2 = SDHOST_CDATA_OUT_12_IDX, + .d3 = SDHOST_CDATA_OUT_13_IDX, + .d4 = SDHOST_CDATA_OUT_14_IDX, + .d5 = SDHOST_CDATA_OUT_15_IDX, + .d6 = SDHOST_CDATA_OUT_16_IDX, + .d7 = SDHOST_CDATA_OUT_17_IDX, + }, + { + .clk = SDHOST_CCLK_OUT_2_IDX, + .cmd = SDHOST_CCMD_OUT_2_IDX, + .d0 = SDHOST_CDATA_OUT_20_IDX, + .d1 = SDHOST_CDATA_OUT_21_IDX, + .d2 = SDHOST_CDATA_OUT_22_IDX, + .d3 = SDHOST_CDATA_OUT_23_IDX, + .d4 = SDHOST_CDATA_OUT_24_IDX, + .d5 = SDHOST_CDATA_OUT_25_IDX, + .d6 = SDHOST_CDATA_OUT_26_IDX, + .d7 = SDHOST_CDATA_OUT_27_IDX, } }; diff --git a/components/soc/include/soc/sdmmc_periph.h b/components/soc/include/soc/sdmmc_periph.h index 7a64f4c5fe..c1d38fa29b 100644 --- a/components/soc/include/soc/sdmmc_periph.h +++ b/components/soc/include/soc/sdmmc_periph.h @@ -15,6 +15,7 @@ #pragma once #include //include soc related (generated) definitions +#include "soc/soc_caps.h" #include "soc/soc_pins.h" #include "soc/sdmmc_reg.h" #include "soc/sdmmc_struct.h" @@ -24,25 +25,50 @@ extern "C" { #endif +/** + * Common SDMMC slot info, doesn't depend on SOC_SDMMC_USE_{IOMUX,GPIO_MATRIX} + */ typedef struct { - uint8_t clk_gpio; - uint8_t cmd_gpio; - uint8_t d0_gpio; - uint8_t d1_gpio; - uint8_t d2_gpio; - uint8_t d3_gpio; - uint8_t d4_gpio; - uint8_t d5_gpio; - uint8_t d6_gpio; - uint8_t d7_gpio; - uint8_t card_detect; - uint8_t write_protect; - uint8_t card_int; - uint8_t width; + uint8_t width; /*!< Maximum supported slot width (1, 4, 8) */ + uint8_t card_detect; /*!< Card detect signal in GPIO Matrix */ + uint8_t write_protect; /*!< Write protect signal in GPIO Matrix */ + uint8_t card_int; /*!< Card interrupt signal in GPIO Matrix */ } sdmmc_slot_info_t; -/** pin and signal information of each slot */ -extern const sdmmc_slot_info_t sdmmc_slot_info[]; +/** Width and GPIO matrix signal numbers for auxillary SD host signals, one structure per slot */ +extern const sdmmc_slot_info_t sdmmc_slot_info[SOC_SDMMC_NUM_SLOTS]; + +/** + * This structure lists pin numbers (if SOC_SDMMC_USE_IOMUX is set) + * or GPIO Matrix signal numbers (if SOC_SDMMC_USE_GPIO_MATRIX is set) + * for the SD bus signals. Field names match SD bus signal names. + */ +typedef struct { + uint8_t clk; + uint8_t cmd; + uint8_t d0; + uint8_t d1; + uint8_t d2; + uint8_t d3; + uint8_t d4; + uint8_t d5; + uint8_t d6; + uint8_t d7; +} sdmmc_slot_io_info_t; + +/* Note: it is in theory possible to have both IOMUX and GPIO Matrix supported + * in the same SoC. However this is not used on any SoC at this point, and would + * complicate the driver. Hence only one of these options is supported at a time. + */ +#if SOC_SDMMC_USE_IOMUX +/** GPIO pin numbers of SD bus signals, one structure per slot */ +extern const sdmmc_slot_io_info_t sdmmc_slot_gpio_num[SOC_SDMMC_NUM_SLOTS]; + +#elif SOC_SDMMC_USE_GPIO_MATRIX +/** GPIO matrix signal numbers of SD bus signals, one structure per slot */ +extern const sdmmc_slot_io_info_t sdmmc_slot_gpio_sig[SOC_SDMMC_NUM_SLOTS]; + +#endif // SOC_SDMMC_USE_{IOMUX,GPIO_MATRIX} #ifdef __cplusplus }