Переглянути джерело

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
Ivan Grokhotkov 5 роки тому
батько
коміт
17c65dad27

+ 1 - 0
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 );

+ 8 - 0
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

+ 30 - 23
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,
     }
 };

+ 3 - 19
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.
+ */

+ 25 - 9
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;

+ 11 - 0
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

+ 30 - 23
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,
     }
 };

+ 42 - 16
components/soc/include/soc/sdmmc_periph.h

@@ -15,6 +15,7 @@
 #pragma once
 #include <stdint.h>
 //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
 }