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

feat(spi_master): p4 add master driver supported

wanlei 2 роки тому
батько
коміт
00fcdce725
29 змінених файлів з 1729 додано та 541 видалено
  1. 20 13
      components/driver/include/esp_private/spi_common_internal.h
  2. 43 15
      components/driver/spi/gpspi/spi_common.c
  3. 82 30
      components/driver/spi/gpspi/spi_master.c
  4. 3 0
      components/driver/spi/gpspi/spi_slave.c
  5. 3 0
      components/driver/spi/include/driver/spi_master.h
  6. 1 0
      components/hal/esp32/include/hal/spi_ll.h
  7. 1 0
      components/hal/esp32c2/include/hal/spi_ll.h
  8. 1 0
      components/hal/esp32c3/include/hal/spi_ll.h
  9. 1 0
      components/hal/esp32c6/include/hal/spi_ll.h
  10. 1 0
      components/hal/esp32h2/include/hal/spi_ll.h
  11. 1 1
      components/hal/esp32p4/include/hal/cache_ll.h
  12. 0 16
      components/hal/esp32p4/include/hal/clk_gate_ll.h
  13. 1279 0
      components/hal/esp32p4/include/hal/spi_ll.h
  14. 1 0
      components/hal/esp32s2/include/hal/spi_ll.h
  15. 1 0
      components/hal/esp32s3/include/hal/spi_ll.h
  16. 11 5
      components/hal/include/hal/spi_hal.h
  17. 13 3
      components/hal/spi_hal.c
  18. 58 7
      components/hal/spi_hal_iram.c
  19. 12 2
      components/hal/spi_slave_hal.c
  20. 20 4
      components/hal/spi_slave_hal_iram.c
  21. 7 0
      components/idf_test/include/esp32p4/idf_performance_target.h
  22. 9 17
      components/soc/esp32p4/include/soc/Kconfig.soc_caps.in
  23. 8 4
      components/soc/esp32p4/include/soc/clk_tree_defs.h
  24. 1 0
      components/soc/esp32p4/include/soc/ext_mem_defs.h
  25. 13 13
      components/soc/esp32p4/include/soc/soc_caps.h
  26. 24 0
      components/soc/esp32p4/include/soc/spi_pins.h
  27. 29 408
      components/soc/esp32p4/include/soc/spi_struct.h
  28. 84 1
      components/soc/esp32p4/spi_periph.c
  29. 2 2
      examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/README.md

+ 20 - 13
components/driver/include/esp_private/spi_common_internal.h

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -12,6 +12,7 @@
 #include "driver/spi_common.h"
 #include "freertos/FreeRTOS.h"
 #include "hal/spi_types.h"
+#include "hal/dma_types.h"
 #include "esp_pm.h"
 #if SOC_GDMA_SUPPORTED
 #include "esp_private/gdma.h"
@@ -45,6 +46,13 @@ extern "C"
 #define BUS_LOCK_DEBUG_EXECUTE_CHECK(x)
 #endif
 
+#if SOC_GPSPI_SUPPORTED && (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI)
+#define DMA_DESC_MEM_ALIGN_SIZE 8
+typedef dma_descriptor_align8_t spi_dma_desc_t;
+#else
+#define DMA_DESC_MEM_ALIGN_SIZE 4
+typedef dma_descriptor_align4_t spi_dma_desc_t;
+#endif
 
 struct spi_bus_lock_t;
 struct spi_bus_lock_dev_t;
@@ -56,22 +64,21 @@ typedef struct spi_bus_lock_dev_t* spi_bus_lock_dev_handle_t;
 /// Background operation control function
 typedef void (*bg_ctrl_func_t)(void*);
 
-typedef struct lldesc_s lldesc_t;
-
 /// Attributes of an SPI bus
 typedef struct {
-    spi_bus_config_t bus_cfg;   ///< Config used to initialize the bus
-    uint32_t flags;             ///< Flags (attributes) of the bus
-    int max_transfer_sz;        ///< Maximum length of bytes available to send
-    bool dma_enabled;           ///< To enable DMA or not
-    int tx_dma_chan;            ///< TX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same
-    int rx_dma_chan;            ///< RX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same
-    int dma_desc_num;           ///< DMA descriptor number of dmadesc_tx or dmadesc_rx.
-    lldesc_t *dmadesc_tx;       ///< DMA descriptor array for TX
-    lldesc_t *dmadesc_rx;       ///< DMA descriptor array for RX
+    spi_bus_config_t bus_cfg;           ///< Config used to initialize the bus
+    uint32_t flags;                     ///< Flags (attributes) of the bus
+    int max_transfer_sz;                ///< Maximum length of bytes available to send
+    bool dma_enabled;                   ///< To enable DMA or not
+    uint16_t internal_mem_align_size;   ///< Buffer align byte requirement for internal memory
+    int tx_dma_chan;                    ///< TX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same
+    int rx_dma_chan;                    ///< RX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same
+    int dma_desc_num;                   ///< DMA descriptor number of dmadesc_tx or dmadesc_rx.
+    spi_dma_desc_t *dmadesc_tx;         ///< DMA descriptor array for TX
+    spi_dma_desc_t *dmadesc_rx;         ///< DMA descriptor array for RX
     spi_bus_lock_handle_t lock;
 #ifdef CONFIG_PM_ENABLE
-    esp_pm_lock_handle_t pm_lock;   ///< Power management lock
+    esp_pm_lock_handle_t pm_lock;       ///< Power management lock
 #endif
 } spi_bus_attr_t;
 

+ 43 - 15
components/driver/spi/gpspi/spi_common.c

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -13,7 +13,6 @@
 #include "esp_check.h"
 #include "esp_rom_gpio.h"
 #include "esp_heap_caps.h"
-#include "soc/lldesc.h"
 #include "soc/spi_periph.h"
 #include "driver/gpio.h"
 #include "driver/spi_master.h"
@@ -26,6 +25,14 @@
 #endif
 #if SOC_GDMA_SUPPORTED
 #include "esp_private/gdma.h"
+#include "hal/cache_hal.h"
+#include "hal/cache_ll.h"
+#endif
+
+#if SOC_PERIPH_CLK_CTRL_SHARED
+#define SPI_COMMON_RCC_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC()
+#else
+#define SPI_COMMON_RCC_CLOCK_ATOMIC()
 #endif
 
 static const char *SPI_TAG = "spi";
@@ -100,7 +107,15 @@ bool spicommon_periph_claim(spi_host_device_t host, const char* source)
     bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &false_var, true);
     if (ret) {
         spi_claiming_func[host] = source;
+#if CONFIG_IDF_TARGET_ESP32P4   //deprecate clk_gate_ll start from p4, others in TODO: IDF-8159
+        SPI_COMMON_RCC_CLOCK_ATOMIC() {
+            spi_ll_enable_bus_clock(host, true);
+            spi_ll_reset_register(host);
+            spi_ll_enable_clock(host, true);
+        }
+#else
         periph_module_enable(spi_periph_signal[host].module);
+#endif
     } else {
         ESP_EARLY_LOGE(SPI_TAG, "SPI%d already claimed by %s.", host+1, spi_claiming_func[host]);
     }
@@ -117,7 +132,15 @@ bool spicommon_periph_free(spi_host_device_t host)
 {
     bool true_var = true;
     bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &true_var, false);
-    if (ret) periph_module_disable(spi_periph_signal[host].module);
+    if (ret) {
+#if CONFIG_IDF_TARGET_ESP32P4
+        SPI_COMMON_RCC_CLOCK_ATOMIC() {
+            spi_ll_enable_bus_clock(host, false);
+        }
+#else
+        periph_module_disable(spi_periph_signal[host].module);
+#endif
+    }
     return ret;
 }
 
@@ -218,6 +241,12 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch
 }
 
 #else //SOC_GDMA_SUPPORTED
+
+#if (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AHB)
+static esp_err_t (*spi_gdma_chan_allocator)(const gdma_channel_alloc_config_t *, gdma_channel_handle_t *) = gdma_new_ahb_channel;
+#elif (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI)
+static esp_err_t (*spi_gdma_chan_allocator)(const gdma_channel_alloc_config_t *, gdma_channel_handle_t *) = gdma_new_axi_channel;
+#endif
 static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan)
 {
     assert(is_valid_host(host_id));
@@ -231,19 +260,13 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch
             .flags.reserve_sibling = 1,
             .direction = GDMA_CHANNEL_DIRECTION_TX,
         };
-        ret = gdma_new_channel(&tx_alloc_config, &ctx->tx_channel);
-        if (ret != ESP_OK) {
-            return ret;
-        }
+        ESP_RETURN_ON_ERROR(spi_gdma_chan_allocator(&tx_alloc_config, &ctx->tx_channel), SPI_TAG, "alloc gdma tx failed");
 
         gdma_channel_alloc_config_t rx_alloc_config = {
             .direction = GDMA_CHANNEL_DIRECTION_RX,
             .sibling_chan = ctx->tx_channel,
         };
-        ret = gdma_new_channel(&rx_alloc_config, &ctx->rx_channel);
-        if (ret != ESP_OK) {
-            return ret;
-        }
+        ESP_RETURN_ON_ERROR(spi_gdma_chan_allocator(&rx_alloc_config, &ctx->rx_channel), SPI_TAG, "alloc gdma rx failed");
 
         if (host_id == SPI2_HOST) {
             gdma_connect(ctx->rx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 2));
@@ -802,17 +825,22 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *
         bus_attr->tx_dma_chan = actual_tx_dma_chan;
         bus_attr->rx_dma_chan = actual_rx_dma_chan;
 
-        int dma_desc_ct = lldesc_get_required_num(bus_config->max_transfer_sz);
+        int dma_desc_ct = (bus_config->max_transfer_sz + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
         if (dma_desc_ct == 0) dma_desc_ct = 1; //default to 4k when max is not given
 
-        bus_attr->max_transfer_sz = dma_desc_ct * LLDESC_MAX_NUM_PER_DESC;
-        bus_attr->dmadesc_tx = heap_caps_malloc(sizeof(lldesc_t) * dma_desc_ct, MALLOC_CAP_DMA);
-        bus_attr->dmadesc_rx = heap_caps_malloc(sizeof(lldesc_t) * dma_desc_ct, MALLOC_CAP_DMA);
+        bus_attr->max_transfer_sz = dma_desc_ct * DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
+        bus_attr->dmadesc_tx = heap_caps_aligned_alloc(DMA_DESC_MEM_ALIGN_SIZE, sizeof(spi_dma_desc_t) * dma_desc_ct, MALLOC_CAP_DMA);
+        bus_attr->dmadesc_rx = heap_caps_aligned_alloc(DMA_DESC_MEM_ALIGN_SIZE, sizeof(spi_dma_desc_t) * dma_desc_ct, MALLOC_CAP_DMA);
         if (bus_attr->dmadesc_tx == NULL || bus_attr->dmadesc_rx == NULL) {
             err = ESP_ERR_NO_MEM;
             goto cleanup;
         }
         bus_attr->dma_desc_num = dma_desc_ct;
+#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
+        bus_attr->internal_mem_align_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
+#else
+        bus_attr->internal_mem_align_size = 4;
+#endif
     } else {
         bus_attr->dma_enabled = 0;
         bus_attr->max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE;

+ 82 - 30
components/driver/spi/gpspi/spi_master.c

@@ -112,6 +112,7 @@ We have two bits to control the interrupt:
 
 #include <string.h>
 #include <sys/param.h>
+#include "esp_private/periph_ctrl.h"
 #include "esp_private/spi_common_internal.h"
 #include "driver/spi_master.h"
 #include "esp_clk_tree.h"
@@ -126,6 +127,9 @@ We have two bits to control the interrupt:
 #include "hal/spi_hal.h"
 #include "hal/spi_ll.h"
 #include "esp_heap_caps.h"
+#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
+#include "esp_cache.h"
+#endif
 
 typedef struct spi_device_t spi_device_t;
 
@@ -172,6 +176,11 @@ static spi_host_t* bus_driver_ctx[SOC_SPI_PERIPH_NUM] = {};
 static const char *SPI_TAG = "spi_master";
 #define SPI_CHECK(a, str, ret_val)  ESP_RETURN_ON_FALSE_ISR(a, ret_val, SPI_TAG, str)
 
+#if SOC_PERIPH_CLK_CTRL_SHARED
+#define SPI_MASTER_RCC_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC()
+#else
+#define SPI_MASTER_RCC_CLOCK_ATOMIC()
+#endif
 
 static void spi_intr(void *arg);
 static void spi_bus_intr_enable(void *host);
@@ -547,6 +556,9 @@ static SPI_MASTER_ISR_ATTR void spi_setup_device(spi_device_t *dev)
     if (spi_bus_lock_touch(dev_lock)) {
         /* Configuration has not been applied yet. */
         spi_hal_setup_device(hal, hal_dev);
+        SPI_MASTER_RCC_CLOCK_ATOMIC() {
+            spi_ll_set_clk_source(hal->hw, hal_dev->timing_conf.clock_source);
+        }
     }
 }
 
@@ -680,13 +692,24 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
         const int cs = host->cur_cs;
         //Tell common code DMA workaround that our DMA channel is idle. If needed, the code will do a DMA reset.
 
-#if CONFIG_IDF_TARGET_ESP32
         if (bus_attr->dma_enabled) {
+#if CONFIG_IDF_TARGET_ESP32
             //This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same
             spicommon_dmaworkaround_idle(bus_attr->tx_dma_chan);
-        }
 #endif  //#if CONFIG_IDF_TARGET_ESP32
 
+#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE   //invalidate here to let user access rx data in post_cb if possible
+            if (host->cur_trans_buf.buffer_to_rcv) {
+                uint16_t alignment = bus_attr->internal_mem_align_size;
+                uint32_t buffer_byte_len = (host->cur_trans_buf.trans->rxlength + 7) / 8;
+                buffer_byte_len = (buffer_byte_len + alignment - 1) & (~(alignment - 1));
+                // invalidate priv_trans.buffer_to_rcv anyway, only user provide aligned buffer can rcv correct data in post_cb
+                esp_err_t ret = esp_cache_msync((void *)host->cur_trans_buf.buffer_to_rcv, buffer_byte_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
+                assert(ret == ESP_OK);
+            }
+#endif
+        }
+
         //cur_cs is changed to DEV_NUM_MAX here
         spi_post_trans(host);
 
@@ -824,9 +847,7 @@ static SPI_MASTER_ISR_ATTR void uninstall_priv_desc(spi_trans_priv_t* trans_buf)
         free((void *)trans_buf->buffer_to_send); //force free, ignore const
     }
     // copy data from temporary DMA-capable buffer back to IRAM buffer and free the temporary one.
-    if (trans_buf->buffer_to_rcv &&
-        (void *)trans_buf->buffer_to_rcv != &trans_desc->rx_data[0] &&
-        trans_buf->buffer_to_rcv != trans_desc->rx_buffer) { // NOLINT(clang-analyzer-unix.Malloc)
+    if (trans_buf->buffer_to_rcv && (void *)trans_buf->buffer_to_rcv != &trans_desc->rx_data[0] && trans_buf->buffer_to_rcv != trans_desc->rx_buffer) { // NOLINT(clang-analyzer-unix.Malloc)
         if (trans_desc->flags & SPI_TRANS_USE_RXDATA) {
             memcpy((uint8_t *) & trans_desc->rx_data[0], trans_buf->buffer_to_rcv, (trans_desc->rxlength + 7) / 8);
         } else {
@@ -836,9 +857,11 @@ static SPI_MASTER_ISR_ATTR void uninstall_priv_desc(spi_trans_priv_t* trans_buf)
     }
 }
 
-static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_transaction_t *trans_desc, spi_trans_priv_t* new_desc, bool isdma)
+static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_host_t *host, spi_trans_priv_t* priv_desc)
 {
-    *new_desc = (spi_trans_priv_t) { .trans = trans_desc, };
+    spi_transaction_t *trans_desc = priv_desc->trans;
+    const spi_bus_attr_t *bus_attr = host->bus_attr;
+    uint16_t alignment = bus_attr->internal_mem_align_size;
 
     // rx memory assign
     uint32_t* rcv_ptr;
@@ -848,13 +871,6 @@ static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_transaction_t *trans_de
         //if not use RXDATA neither rx_buffer, buffer_to_rcv assigned to NULL
         rcv_ptr = trans_desc->rx_buffer;
     }
-    if (rcv_ptr && isdma && (!esp_ptr_dma_capable(rcv_ptr) || ((int)rcv_ptr % 4 != 0))) {
-        //if rxbuf in the desc not DMA-capable, malloc a new one. The rx buffer need to be length of multiples of 32 bits to avoid heap corruption.
-        ESP_LOGD(SPI_TAG, "Allocate RX buffer for DMA" );
-        rcv_ptr = heap_caps_malloc(((trans_desc->rxlength + 31) / 32) * 4, MALLOC_CAP_DMA);
-        if (rcv_ptr == NULL) goto clean_up;
-    }
-    new_desc->buffer_to_rcv = rcv_ptr;
 
     // tx memory assign
     const uint32_t *send_ptr;
@@ -864,21 +880,53 @@ static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_transaction_t *trans_de
         //if not use TXDATA neither tx_buffer, tx data assigned to NULL
         send_ptr = trans_desc->tx_buffer ;
     }
-    if (send_ptr && isdma && !esp_ptr_dma_capable( send_ptr )) {
-        //if txbuf in the desc not DMA-capable, malloc a new one
-        ESP_LOGD(SPI_TAG, "Allocate TX buffer for DMA" );
-        uint32_t *temp = heap_caps_malloc((trans_desc->length + 7) / 8, MALLOC_CAP_DMA);
-        if (temp == NULL) goto clean_up;
-
-        memcpy( temp, send_ptr, (trans_desc->length + 7) / 8 );
-        send_ptr = temp;
+
+    uint32_t tx_byte_len = (trans_desc->length + 7) / 8;
+    uint32_t rx_byte_len = (trans_desc->rxlength + 7) / 8;
+#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
+    bool tx_un_align = ((((uint32_t)send_ptr) | tx_byte_len) & (alignment - 1));
+    bool rx_un_align = ((((uint32_t)rcv_ptr) | rx_byte_len) & (alignment - 1));
+#else
+    bool tx_un_align = false;   //tx don't need align on addr or length, for other chips
+    bool rx_un_align = (((uint32_t)rcv_ptr) & (alignment - 1));
+#endif
+
+    if (send_ptr && bus_attr->dma_enabled) {
+        if ((!esp_ptr_dma_capable(send_ptr) || tx_un_align )) {
+            ESP_RETURN_ON_FALSE(!(trans_desc->flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but TX buffer addr&len not align to %d, or not dma_capable", alignment);
+            //if txbuf in the desc not DMA-capable, or not bytes aligned to alignment, malloc a new one
+            ESP_EARLY_LOGD(SPI_TAG, "Allocate TX buffer for DMA" );
+            tx_byte_len = (tx_byte_len + alignment - 1) & (~(alignment - 1));   // up align alignment
+            uint32_t *temp = heap_caps_aligned_alloc(alignment, tx_byte_len, MALLOC_CAP_DMA);
+            if (temp == NULL) {
+                goto clean_up;
+            }
+
+            memcpy( temp, send_ptr, (trans_desc->length + 7) / 8 );
+            send_ptr = temp;
+        }
+#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
+        esp_err_t ret = esp_cache_msync((void *)send_ptr, tx_byte_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
+        assert(ret == ESP_OK);
+#endif
     }
-    new_desc->buffer_to_send = send_ptr;
 
+    if (rcv_ptr && bus_attr->dma_enabled && (!esp_ptr_dma_capable(rcv_ptr) || rx_un_align )) {
+        ESP_RETURN_ON_FALSE(!(trans_desc->flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but RX buffer addr&len not align to %d, or not dma_capable", alignment);
+        //if rxbuf in the desc not DMA-capable, or not aligned to alignment, malloc a new one
+        ESP_EARLY_LOGD(SPI_TAG, "Allocate RX buffer for DMA" );
+        rx_byte_len = (rx_byte_len + alignment - 1) & (~(alignment - 1));   // up align alignment
+        rcv_ptr = heap_caps_aligned_alloc(alignment, rx_byte_len, MALLOC_CAP_DMA);
+        if (rcv_ptr == NULL) {
+            goto clean_up;
+        }
+    }
+    priv_desc->buffer_to_send = send_ptr;
+    priv_desc->buffer_to_rcv = rcv_ptr;
     return ESP_OK;
 
 clean_up:
-    uninstall_priv_desc(new_desc);
+    uninstall_priv_desc(priv_desc);
     return ESP_ERR_NO_MEM;
 }
 
@@ -897,8 +945,8 @@ esp_err_t SPI_MASTER_ATTR spi_device_queue_trans(spi_device_handle_t handle, spi
         return ESP_ERR_INVALID_ARG;
     }
 
-    spi_trans_priv_t trans_buf;
-    ret = setup_priv_desc(trans_desc, &trans_buf, (host->bus_attr->dma_enabled));
+    spi_trans_priv_t trans_buf = { .trans = trans_desc, };
+    ret = setup_priv_desc(host, &trans_buf);
     if (ret != ESP_OK) return ret;
 
 #ifdef CONFIG_PM_ENABLE
@@ -935,6 +983,7 @@ esp_err_t SPI_MASTER_ATTR spi_device_get_trans_result(spi_device_handle_t handle
     BaseType_t r;
     spi_trans_priv_t trans_buf;
     SPI_CHECK(handle!=NULL, "invalid dev handle", ESP_ERR_INVALID_ARG);
+    bool use_dma = handle->host->bus_attr->dma_enabled;
 
     //if SPI_DEVICE_NO_RETURN_RESULT is set, ret_queue will always be empty
     SPI_CHECK(!(handle->cfg.flags & SPI_DEVICE_NO_RETURN_RESULT), "API not Supported!", ESP_ERR_NOT_SUPPORTED);
@@ -947,8 +996,10 @@ esp_err_t SPI_MASTER_ATTR spi_device_get_trans_result(spi_device_handle_t handle
         // Every in-flight transaction request occupies internal memory as DMA buffer if needed.
         return ESP_ERR_TIMEOUT;
     }
-    //release temporary buffers
-    uninstall_priv_desc(&trans_buf);
+    //release temporary buffers used by dma
+    if (use_dma) {
+        uninstall_priv_desc(&trans_buf);
+    }
     (*trans_desc) = trans_buf.trans;
 
     return ESP_OK;
@@ -1043,8 +1094,8 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_start(spi_device_handle_t handl
     SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot send polling transaction while the previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE );
 
     spi_host_t *host = handle->host;
-    spi_trans_priv_t priv_polling_trans;
-    ret = setup_priv_desc(trans_desc, &priv_polling_trans, (host->bus_attr->dma_enabled));
+    spi_trans_priv_t priv_polling_trans = { .trans = trans_desc, };
+    ret = setup_priv_desc(host, &priv_polling_trans);
     if (ret!=ESP_OK) return ret;
 
     /* If device_acquiring_lock is set to handle, it means that the user has already
@@ -1065,6 +1116,7 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_start(spi_device_handle_t handl
         ESP_LOGE(SPI_TAG, "polling can't get buslock");
         return ret;
     }
+    //After holding the buslock, common resource can be accessed !!
 
     //Polling, no interrupt is used.
     host->polling = true;

+ 3 - 0
components/driver/spi/gpspi/spi_slave.c

@@ -163,6 +163,9 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
     bool use_dma = (dma_chan != SPI_DMA_DISABLED);
     spihost[host]->dma_enabled = use_dma;
     if (use_dma) {
+#if CONFIG_IDF_TARGET_ESP32P4
+        abort();    //will supported in IDF-7503
+#endif
         ret = spicommon_dma_chan_alloc(host, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
         if (ret != ESP_OK) {
             goto cleanup;

+ 3 - 0
components/driver/spi/include/driver/spi_master.h

@@ -115,6 +115,7 @@ typedef struct {
 #define SPI_TRANS_MULTILINE_CMD       (1<<9)  ///< The data lines used at command phase is the same as data phase (otherwise, only one data line is used at command phase)
 #define SPI_TRANS_MODE_OCT            (1<<10) ///< Transmit/receive data in 8-bit mode
 #define SPI_TRANS_MULTILINE_ADDR      SPI_TRANS_MODE_DIOQIO_ADDR ///< The data lines used at address phase is the same as data phase (otherwise, only one data line is used at address phase)
+#define SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL   (1<<11) ///< By default driver will automatically re-alloc dma buffer if it doesn't meet hardware alignment or dma_capable requirements, this flag is for you to disable this feature, you will need to take care of the alignment otherwise driver will return you error ESP_ERR_INVALID_ARG
 
 /**
  * This structure describes one SPI transaction. The descriptor should not be modified until the transaction finishes.
@@ -208,6 +209,7 @@ esp_err_t spi_bus_remove_device(spi_device_handle_t handle);
  * @return
  *         - ESP_ERR_INVALID_ARG   if parameter is invalid. This can happen if SPI_TRANS_CS_KEEP_ACTIVE flag is specified while
  *                                 the bus was not acquired (`spi_device_acquire_bus()` should be called first)
+ *                                 or set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but tx or rx buffer not DMA-capable, or addr&len not align to cache line size
  *         - ESP_ERR_TIMEOUT       if there was no room in the queue before ticks_to_wait expired
  *         - ESP_ERR_NO_MEM        if allocating DMA-capable temporary buffer failed
  *         - ESP_ERR_INVALID_STATE if previous transactions are not finished
@@ -273,6 +275,7 @@ esp_err_t spi_device_transmit(spi_device_handle_t handle, spi_transaction_t *tra
  * @return
  *         - ESP_ERR_INVALID_ARG   if parameter is invalid. This can happen if SPI_TRANS_CS_KEEP_ACTIVE flag is specified while
  *                                 the bus was not acquired (`spi_device_acquire_bus()` should be called first)
+ *                                 or set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but tx or rx buffer not DMA-capable, or addr&len not align to cache line size
  *         - ESP_ERR_TIMEOUT       if the device cannot get control of the bus before ``ticks_to_wait`` expired
  *         - ESP_ERR_NO_MEM        if allocating DMA-capable temporary buffer failed
  *         - ESP_ERR_INVALID_STATE if previous transactions are not finished

+ 1 - 0
components/hal/esp32/include/hal/spi_ll.h

@@ -63,6 +63,7 @@ typedef spi_dev_t spi_dma_dev_t;
  * @param hw Beginning address of the peripheral registers.
  * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
  */
+__attribute__((always_inline))
 static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
 {
     //empty, keep this for compatibility

+ 1 - 0
components/hal/esp32c2/include/hal/spi_ll.h

@@ -97,6 +97,7 @@ typedef enum {
  * @param hw Beginning address of the peripheral registers.
  * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
  */
+__attribute__((always_inline))
 static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source){
     switch (clk_source)
     {

+ 1 - 0
components/hal/esp32c3/include/hal/spi_ll.h

@@ -99,6 +99,7 @@ typedef enum {
  * @param hw Beginning address of the peripheral registers.
  * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
  */
+__attribute__((always_inline))
 static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source){
     switch (clk_source)
     {

+ 1 - 0
components/hal/esp32c6/include/hal/spi_ll.h

@@ -98,6 +98,7 @@ typedef enum {
  * @param hw Beginning address of the peripheral registers.
  * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
  */
+__attribute__((always_inline))
 static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
 {
     switch (clk_source)

+ 1 - 0
components/hal/esp32h2/include/hal/spi_ll.h

@@ -100,6 +100,7 @@ typedef enum {
  * @param hw Beginning address of the peripheral registers.
  * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
  */
+__attribute__((always_inline))
 static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
 {
     switch (clk_source)

+ 1 - 1
components/hal/esp32p4/include/hal/cache_ll.h

@@ -23,7 +23,7 @@ extern "C" {
  * @brief Given a L2MEM cached address, get the corresponding non-cacheable address
  * @example 0x4FF0_0000 => 0x8FF0_0000
  */
-#define CACHE_LL_L2MEM_NON_CACHE_ADDR(addr) ((intptr_t)(addr) + 0x40000000)
+#define CACHE_LL_L2MEM_NON_CACHE_ADDR(addr) ((intptr_t)(addr) + SOC_NON_CACHEABLE_OFFSET)
 
 /**
  * Cache capabilities

+ 0 - 16
components/hal/esp32p4/include/hal/clk_gate_ll.h

@@ -54,12 +54,6 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph)
         return HP_SYS_CLKRST_REG_TWAI1_CLK_EN;
     case PERIPH_TWAI2_MODULE:
         return HP_SYS_CLKRST_REG_TWAI2_CLK_EN;
-    case PERIPH_GPSPI_MODULE:
-        return HP_SYS_CLKRST_REG_GPSPI2_HS_CLK_EN;
-    case PERIPH_GPSPI2_MODULE:
-        return HP_SYS_CLKRST_REG_GPSPI2_MST_CLK_EN;
-    case PERIPH_GPSPI3_MODULE:
-        return HP_SYS_CLKRST_REG_GPSPI3_MST_CLK_EN;
     case PERIPH_I3C_MODULE:
         return HP_SYS_CLKRST_REG_I3C_MST_CLK_EN;
     case PERIPH_CAM_MODULE:
@@ -145,10 +139,6 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en
         return HP_SYS_CLKRST_REG_RST_EN_CAN2;
     case PERIPH_LEDC_MODULE:
         return HP_SYS_CLKRST_REG_RST_EN_LEDC;
-    case PERIPH_GPSPI2_MODULE:
-        return HP_SYS_CLKRST_REG_RST_EN_SPI2;
-    case PERIPH_GPSPI3_MODULE:
-        return HP_SYS_CLKRST_REG_RST_EN_SPI3;
     case PERIPH_LCD_MODULE:
         return HP_SYS_CLKRST_REG_RST_EN_LCDCAM;
     case PERIPH_SARADC_MODULE:
@@ -224,10 +214,6 @@ static inline uint32_t periph_ll_get_clk_en_reg(periph_module_t periph)
     case PERIPH_TWAI1_MODULE:
     case PERIPH_TWAI2_MODULE:
         return HP_SYS_CLKRST_PERI_CLK_CTRL116_REG;
-    case PERIPH_GPSPI_MODULE:
-    case PERIPH_GPSPI2_MODULE:
-    case PERIPH_GPSPI3_MODULE:
-        return HP_SYS_CLKRST_PERI_CLK_CTRL117_REG;
     case PERIPH_I3C_MODULE:
     case PERIPH_CAM_MODULE:
         return HP_SYS_CLKRST_PERI_CLK_CTRL119_REG;
@@ -282,8 +268,6 @@ static inline uint32_t periph_ll_get_rst_en_reg(periph_module_t periph)
     case PERIPH_TWAI1_MODULE:
     case PERIPH_TWAI2_MODULE:
     case PERIPH_LEDC_MODULE:
-    case PERIPH_GPSPI2_MODULE:
-    case PERIPH_GPSPI3_MODULE:
     case PERIPH_CAM_MODULE:
     case PERIPH_SARADC_MODULE:
     case PERIPH_AES_MODULE:

+ 1279 - 0
components/hal/esp32p4/include/hal/spi_ll.h

@@ -0,0 +1,1279 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*******************************************************************************
+ * NOTICE
+ * The hal is not public api, don't use in application code.
+ * See readme.md in soc/include/hal/readme.md
+ ******************************************************************************/
+
+// The LL layer for SPI register operations
+
+#pragma once
+
+#include <stdlib.h> //for abs()
+#include <string.h>
+#include "esp_types.h"
+#include "soc/spi_periph.h"
+#include "soc/spi_struct.h"
+#include "soc/lldesc.h"
+#include "hal/assert.h"
+#include "hal/misc.h"
+#include "hal/spi_types.h"
+#include "soc/hp_sys_clkrst_struct.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Interrupt not used. Don't use in app.
+#define SPI_LL_UNUSED_INT_MASK  (SPI_TRANS_DONE_INT_ENA | SPI_SLV_WR_DMA_DONE_INT_ENA | SPI_SLV_RD_DMA_DONE_INT_ENA | SPI_SLV_WR_BUF_DONE_INT_ENA | SPI_SLV_RD_BUF_DONE_INT_ENA)
+/// These 2 masks together will set SPI transaction to one line mode
+#define SPI_LL_ONE_LINE_CTRL_MASK (SPI_FREAD_QUAD | SPI_FREAD_DUAL | SPI_FCMD_QUAD | SPI_FCMD_DUAL | SPI_FADDR_QUAD | SPI_FADDR_DUAL)
+#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL)
+/// Swap the bit order to its correct place to send
+#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
+#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):((ID)==1? &GPSPI2 : &GPSPI3))
+
+#define SPI_LL_DMA_MAX_BIT_LEN    (1 << 18)    //reg len: 18 bits
+#define SPI_LL_CPU_MAX_BIT_LEN    (16 * 32)    //Fifo len: 16 words
+
+/**
+ * The data structure holding calculated clock configuration. Since the
+ * calculation needs long time, it should be calculated during initialization and
+ * stored somewhere to be quickly used.
+ */
+typedef uint32_t spi_ll_clock_val_t;
+typedef spi_dev_t spi_dma_dev_t;
+
+// Type definition of all supported interrupts
+typedef enum {
+    SPI_LL_INTR_TRANS_DONE =    BIT(0),     ///< A transaction has done
+    SPI_LL_INTR_RDBUF =         BIT(6),     ///< Has received RDBUF command. Only available in slave HD.
+    SPI_LL_INTR_WRBUF =         BIT(7),     ///< Has received WRBUF command. Only available in slave HD.
+    SPI_LL_INTR_RDDMA =         BIT(8),     ///< Has received RDDMA command. Only available in slave HD.
+    SPI_LL_INTR_WRDMA =         BIT(9),     ///< Has received WRDMA command. Only available in slave HD.
+    SPI_LL_INTR_CMD7  =         BIT(10),    ///< Has received CMD7 command. Only available in slave HD.
+    SPI_LL_INTR_CMD8 =          BIT(11),    ///< Has received CMD8 command. Only available in slave HD.
+    SPI_LL_INTR_CMD9 =          BIT(12),    ///< Has received CMD9 command. Only available in slave HD.
+    SPI_LL_INTR_CMDA =          BIT(13),    ///< Has received CMDA command. Only available in slave HD.
+    SPI_LL_INTR_SEG_DONE =      BIT(14),
+} spi_ll_intr_t;
+
+// Flags for conditions under which the transaction length should be recorded
+typedef enum {
+    SPI_LL_TRANS_LEN_COND_WRBUF =   BIT(0), ///< WRBUF length will be recorded
+    SPI_LL_TRANS_LEN_COND_RDBUF =   BIT(1), ///< RDBUF length will be recorded
+    SPI_LL_TRANS_LEN_COND_WRDMA =   BIT(2), ///< WRDMA length will be recorded
+    SPI_LL_TRANS_LEN_COND_RDDMA =   BIT(3), ///< RDDMA length will be recorded
+} spi_ll_trans_len_cond_t;
+
+// SPI base command
+typedef enum {
+     /* Slave HD Only */
+    SPI_LL_BASE_CMD_HD_WRBUF    = 0x01,
+    SPI_LL_BASE_CMD_HD_RDBUF    = 0x02,
+    SPI_LL_BASE_CMD_HD_WRDMA    = 0x03,
+    SPI_LL_BASE_CMD_HD_RDDMA    = 0x04,
+    SPI_LL_BASE_CMD_HD_SEG_END  = 0x05,
+    SPI_LL_BASE_CMD_HD_EN_QPI   = 0x06,
+    SPI_LL_BASE_CMD_HD_WR_END   = 0x07,
+    SPI_LL_BASE_CMD_HD_INT0     = 0x08,
+    SPI_LL_BASE_CMD_HD_INT1     = 0x09,
+    SPI_LL_BASE_CMD_HD_INT2     = 0x0A,
+} spi_ll_base_command_t;
+/*------------------------------------------------------------------------------
+ * Control
+ *----------------------------------------------------------------------------*/
+
+/**
+ * Enable peripheral register clock
+ *
+ * @param host_id   Peripheral index number, see `spi_host_device_t`
+ * @param enable    Enable/Disable
+ */
+static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) {
+    switch (host_id)
+    {
+    case SPI2_HOST:
+        HP_SYS_CLKRST.soc_clk_ctrl1.reg_gpspi2_sys_clk_en = enable;
+        HP_SYS_CLKRST.soc_clk_ctrl2.reg_gpspi2_apb_clk_en = enable;
+        break;
+    case SPI3_HOST:
+        HP_SYS_CLKRST.soc_clk_ctrl1.reg_gpspi3_sys_clk_en = enable;
+        HP_SYS_CLKRST.soc_clk_ctrl2.reg_gpspi3_apb_clk_en = enable;
+        break;
+    default: HAL_ASSERT(false);
+    }
+}
+
+/// use a macro to wrap the function, force the caller to use it in a critical section
+/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
+#define spi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_enable_bus_clock(__VA_ARGS__)
+
+/**
+ * Reset whole peripheral register to init value defined by HW design
+ *
+ * @param host_id   Peripheral index number, see `spi_host_device_t`
+ */
+static inline void spi_ll_reset_register(spi_host_device_t host_id) {
+    switch (host_id)
+    {
+    case SPI2_HOST:
+        HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_spi2 = 1;
+        HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_spi2 = 0;
+        break;
+    case SPI3_HOST:
+        HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_spi3 = 1;
+        HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_spi3 = 0;
+        break;
+    default: HAL_ASSERT(false);
+    }
+}
+
+/// use a macro to wrap the function, force the caller to use it in a critical section
+/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
+#define spi_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_reset_register(__VA_ARGS__)
+
+/**
+ * Enable functional output clock within peripheral
+ *
+ * @param host_id   Peripheral index number, see `spi_host_device_t`
+ * @param enable    Enable/Disable
+ */
+static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable)
+{
+    switch (host_id)
+    {
+    case SPI2_HOST:
+        HP_SYS_CLKRST.peri_clk_ctrl116.reg_gpspi2_hs_clk_en = enable;
+        HP_SYS_CLKRST.peri_clk_ctrl116.reg_gpspi2_mst_clk_en = enable;
+        break;
+    case SPI3_HOST:
+        HP_SYS_CLKRST.peri_clk_ctrl116.reg_gpspi3_hs_clk_en = enable;
+        HP_SYS_CLKRST.peri_clk_ctrl117.reg_gpspi3_mst_clk_en = enable;
+        break;
+    default: HAL_ASSERT(false);
+    }
+}
+
+/// use a macro to wrap the function, force the caller to use it in a critical section
+/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
+#define spi_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_enable_clock(__VA_ARGS__)
+
+/**
+ * Select SPI peripheral clock source (master).
+ *
+ * @param hw Beginning address of the peripheral registers.
+ * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
+ */
+__attribute__((always_inline))
+static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
+{
+    uint32_t clk_id = 0;
+    switch (clk_source) {
+    case SPI_CLK_SRC_XTAL:
+        clk_id = 0;
+        break;
+    default:
+        HAL_ASSERT(false);
+    }
+
+    if (hw == &GPSPI2) {
+        HP_SYS_CLKRST.peri_clk_ctrl116.reg_gpspi2_clk_src_sel = clk_id;
+    } else if (hw == &GPSPI3) {
+        HP_SYS_CLKRST.peri_clk_ctrl116.reg_gpspi3_clk_src_sel = clk_id;
+    }
+}
+
+/// use a macro to wrap the function, force the caller to use it in a critical section
+/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
+#define spi_ll_set_clk_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_set_clk_source(__VA_ARGS__)
+
+/**
+ * Initialize SPI peripheral (master).
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_master_init(spi_dev_t *hw)
+{
+    //Reset timing
+    hw->user1.cs_setup_time = 0;
+    hw->user1.cs_hold_time = 0;
+
+    //use all 64 bytes of the buffer
+    hw->user.usr_miso_highpart = 0;
+    hw->user.usr_mosi_highpart = 0;
+
+    //Disable unneeded ints
+    hw->slave.val = 0;
+    hw->user.val = 0;
+
+    hw->dma_conf.val = 0;
+    hw->dma_conf.slv_tx_seg_trans_clr_en = 1;
+    hw->dma_conf.slv_rx_seg_trans_clr_en = 1;
+    hw->dma_conf.dma_slv_seg_trans_en = 0;
+}
+
+/**
+ * Initialize SPI peripheral (slave).
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_slave_init(spi_dev_t *hw)
+{
+    //Configure slave
+    hw->clock.val = 0;
+    hw->user.val = 0;
+    hw->ctrl.val = 0;
+    hw->user.doutdin = 1; //we only support full duplex
+    hw->user.sio = 0;
+    hw->slave.slave_mode = 1;
+    hw->slave.soft_reset = 1;
+    hw->slave.soft_reset = 0;
+    //use all 64 bytes of the buffer
+    hw->user.usr_miso_highpart = 0;
+    hw->user.usr_mosi_highpart = 0;
+
+    // Configure DMA In-Link to not be terminated when transaction bit counter exceeds
+    hw->dma_conf.rx_eof_en = 0;
+    hw->dma_conf.dma_slv_seg_trans_en = 0;
+
+    //Disable unneeded ints
+    hw->dma_int_ena.val &= ~SPI_LL_UNUSED_INT_MASK;
+}
+
+/**
+ * Initialize SPI peripheral (slave half duplex mode)
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_slave_hd_init(spi_dev_t *hw)
+{
+    hw->clock.val = 0;
+    hw->user.val = 0;
+    hw->ctrl.val = 0;
+    hw->user.doutdin = 0;
+    hw->user.sio = 0;
+
+    hw->slave.soft_reset = 1;
+    hw->slave.soft_reset = 0;
+    hw->slave.slave_mode = 1;
+}
+
+/**
+ * Check whether user-defined transaction is done.
+ *
+ * @param hw Beginning address of the peripheral registers.
+ *
+ * @return   True if transaction is done, otherwise false.
+ */
+static inline bool spi_ll_usr_is_done(spi_dev_t *hw)
+{
+    return hw->dma_int_raw.trans_done_int;
+}
+
+/**
+ * Apply the register configurations and wait until it's done
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_apply_config(spi_dev_t *hw)
+{
+    hw->cmd.update = 1;
+    while (hw->cmd.update);    //waiting config applied
+}
+
+/**
+ * Trigger start of user-defined transaction.
+ * The synchronization between two clock domains is required in ESP32-S3
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_user_start(spi_dev_t *hw)
+{
+    hw->cmd.usr = 1;
+}
+
+/**
+ * Get current running command bit-mask. (Preview)
+ *
+ * @param hw Beginning address of the peripheral registers.
+ *
+ * @return   Bitmask of running command, see ``SPI_CMD_REG``. 0 if no in-flight command.
+ */
+static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw)
+{
+    return hw->cmd.usr;
+}
+
+/**
+ * Reset the slave peripheral before next transaction.
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_slave_reset(spi_dev_t *hw)
+{
+    hw->slave.soft_reset = 1;
+    hw->slave.soft_reset = 0;
+}
+
+/**
+ * Reset SPI CPU TX FIFO
+ *
+ * On P4, this function is not seperated
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_cpu_tx_fifo_reset(spi_dev_t *hw)
+{
+    hw->dma_conf.buf_afifo_rst = 1;
+    hw->dma_conf.buf_afifo_rst = 0;
+}
+
+/**
+ * Reset SPI CPU RX FIFO
+ *
+ * On P4, this function is not seperated
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_cpu_rx_fifo_reset(spi_dev_t *hw)
+{
+    hw->dma_conf.rx_afifo_rst = 1;
+    hw->dma_conf.rx_afifo_rst = 0;
+}
+
+/**
+ * Reset SPI DMA TX FIFO
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_dma_tx_fifo_reset(spi_dev_t *hw)
+{
+    hw->dma_conf.dma_afifo_rst = 1;
+    hw->dma_conf.dma_afifo_rst = 0;
+}
+
+/**
+ * Reset SPI DMA RX FIFO
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_dma_rx_fifo_reset(spi_dev_t *hw)
+{
+    hw->dma_conf.rx_afifo_rst = 1;
+    hw->dma_conf.rx_afifo_rst = 0;
+}
+
+/**
+ * Clear in fifo full error
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_infifo_full_clr(spi_dev_t *hw)
+{
+    hw->dma_int_clr.dma_infifo_full_err_int = 1;
+}
+
+/**
+ * Clear out fifo empty error
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_outfifo_empty_clr(spi_dev_t *hw)
+{
+    hw->dma_int_clr.dma_outfifo_empty_err_int = 1;
+}
+
+/*------------------------------------------------------------------------------
+ * DMA
+ *----------------------------------------------------------------------------*/
+/**
+ * Enable/Disable RX DMA (Peripherals->DMA->RAM)
+ *
+ * @param hw     Beginning address of the peripheral registers.
+ * @param enable 1: enable; 2: disable
+ */
+static inline void spi_ll_dma_rx_enable(spi_dev_t *hw, bool enable)
+{
+    hw->dma_conf.dma_rx_ena = enable;
+}
+
+/**
+ * Enable/Disable TX DMA (RAM->DMA->Peripherals)
+ *
+ * @param hw     Beginning address of the peripheral registers.
+ * @param enable 1: enable; 2: disable
+ */
+static inline void spi_ll_dma_tx_enable(spi_dev_t *hw, bool enable)
+{
+    hw->dma_conf.dma_tx_ena = enable;
+}
+
+/**
+ * Configuration of RX DMA EOF interrupt generation way
+ *
+ * @param hw     Beginning address of the peripheral registers.
+ * @param enable 1: spi_dma_inlink_eof is set when the number of dma pushed data bytes is equal to the value of spi_slv/mst_dma_rd_bytelen[19:0] in spi dma transition.  0: spi_dma_inlink_eof is set by spi_trans_done in non-seg-trans or spi_dma_seg_trans_done in seg-trans.
+ */
+static inline void spi_ll_dma_set_rx_eof_generation(spi_dev_t *hw, bool enable)
+{
+    hw->dma_conf.rx_eof_en = enable;
+}
+
+/*------------------------------------------------------------------------------
+ * Buffer
+ *----------------------------------------------------------------------------*/
+/**
+ * Write to SPI hardware data buffer.
+ *
+ * @param hw             Beginning address of the peripheral registers.
+ * @param buffer_to_send Address of the data to be written to the hardware data buffer.
+ * @param bitlen         Length to write, in bits.
+ */
+static inline void spi_ll_write_buffer(spi_dev_t *hw, const uint8_t *buffer_to_send, size_t bitlen)
+{
+    for (int x = 0; x < bitlen; x += 32) {
+        //Use memcpy to get around alignment issues for txdata
+        uint32_t word;
+        memcpy(&word, &buffer_to_send[x / 8], 4);
+        hw->data_buf[(x / 32)].buf = word;
+    }
+}
+
+/**
+ * Write to SPI hardware data buffer by buffer ID (address)
+ *
+ * @param hw      Beginning address of the peripheral registers
+ * @param byte_id Start ID (address) of the hardware buffer to be written
+ * @param data    Address of the data to be written to the hardware data buffer.
+ * @param len     Length to write, in bytes.
+ */
+static inline void spi_ll_write_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t *data, int len)
+{
+    HAL_ASSERT(byte_id + len <= 64);
+    HAL_ASSERT(len > 0);
+    HAL_ASSERT(byte_id >= 0);
+
+    while (len > 0) {
+        uint32_t word;
+        int offset = byte_id % 4;
+        int copy_len = 4 - offset;
+        if (copy_len > len) {
+            copy_len = len;
+        }
+
+        //read-modify-write
+        if (copy_len != 4) {
+            word = hw->data_buf[byte_id / 4].buf;    //read
+        }
+        memcpy(((uint8_t *)&word) + offset, data, copy_len);  //modify
+        hw->data_buf[byte_id / 4].buf = word;                     //write
+
+        data += copy_len;
+        byte_id += copy_len;
+        len -= copy_len;
+    }
+}
+
+/**
+ * Read from SPI hardware data buffer.
+ *
+ * @param hw            Beginning address of the peripheral registers.
+ * @param buffer_to_rcv Address of a buffer to read data from hardware data buffer
+ * @param bitlen        Length to read, in bits.
+ */
+static inline void spi_ll_read_buffer(spi_dev_t *hw, uint8_t *buffer_to_rcv, size_t bitlen)
+{
+    for (int x = 0; x < bitlen; x += 32) {
+        //Do a memcpy to get around possible alignment issues in rx_buffer
+        uint32_t word = hw->data_buf[x / 32].buf;
+        int len = bitlen - x;
+        if (len > 32) {
+            len = 32;
+        }
+        memcpy(&buffer_to_rcv[x / 8], &word, (len + 7) / 8);
+    }
+}
+
+/**
+ * Read from SPI hardware data buffer by buffer ID (address)
+ *
+ * @param hw      Beginning address of the peripheral registers
+ * @param byte_id Start ID (address) of the hardware buffer to be read
+ * @param data    Address of a buffer to read data from hardware data buffer
+ * @param len     Length to read, in bytes.
+ */
+static inline void spi_ll_read_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t *out_data, int len)
+{
+    while (len > 0) {
+        uint32_t word = hw->data_buf[byte_id / 4].buf;
+        int offset = byte_id % 4;
+        int copy_len = 4 - offset;
+        if (copy_len > len) {
+            copy_len = len;
+        }
+
+        memcpy(out_data, ((uint8_t *)&word) + offset, copy_len);
+        byte_id += copy_len;
+        out_data += copy_len;
+        len -= copy_len;
+    }
+}
+
+/*------------------------------------------------------------------------------
+ * Configs: mode
+ *----------------------------------------------------------------------------*/
+/**
+ * Enable/disable the postive-cs feature.
+ *
+ * @param hw     Beginning address of the peripheral registers.
+ * @param cs     One of the CS (0-2) to enable/disable the feature.
+ * @param pos_cs True to enable the feature, otherwise disable (default).
+ */
+static inline void spi_ll_master_set_pos_cs(spi_dev_t *hw, int cs, uint32_t pos_cs)
+{
+    if (pos_cs) {
+        hw->misc.master_cs_pol |= (1 << cs);
+    } else {
+        hw->misc.master_cs_pol &= ~(1 << cs);
+    }
+}
+
+/**
+ * Enable/disable the LSBFIRST feature for TX data.
+ *
+ * @param hw       Beginning address of the peripheral registers.
+ * @param lsbfirst True if LSB of TX data to be sent first, otherwise MSB is sent first (default).
+ */
+static inline void spi_ll_set_tx_lsbfirst(spi_dev_t *hw, bool lsbfirst)
+{
+    hw->ctrl.wr_bit_order = lsbfirst;
+}
+
+/**
+ * Enable/disable the LSBFIRST feature for RX data.
+ *
+ * @param hw       Beginning address of the peripheral registers.
+ * @param lsbfirst True if first bit received as LSB, otherwise as MSB (default).
+ */
+static inline void spi_ll_set_rx_lsbfirst(spi_dev_t *hw, bool lsbfirst)
+{
+    hw->ctrl.rd_bit_order = lsbfirst;
+}
+
+/**
+ * Set SPI mode for the peripheral as master.
+ *
+ * @param hw   Beginning address of the peripheral registers.
+ * @param mode SPI mode to work at, 0-3.
+ */
+static inline void spi_ll_master_set_mode(spi_dev_t *hw, uint8_t mode)
+{
+    //Configure polarity
+    if (mode == 0) {
+        hw->misc.ck_idle_edge = 0;
+        hw->user.ck_out_edge = 0;
+    } else if (mode == 1) {
+        hw->misc.ck_idle_edge = 0;
+        hw->user.ck_out_edge = 1;
+    } else if (mode == 2) {
+        hw->misc.ck_idle_edge = 1;
+        hw->user.ck_out_edge = 1;
+    } else if (mode == 3) {
+        hw->misc.ck_idle_edge = 1;
+        hw->user.ck_out_edge = 0;
+    }
+}
+
+/**
+ * Set SPI mode for the peripheral as slave.
+ *
+ * @param hw   Beginning address of the peripheral registers.
+ * @param mode SPI mode to work at, 0-3.
+ */
+static inline void spi_ll_slave_set_mode(spi_dev_t *hw, const int mode, bool dma_used)
+{
+    if (mode == 0) {
+        hw->misc.ck_idle_edge = 0;
+        hw->user.rsck_i_edge = 0;
+        hw->user.tsck_i_edge = 0;
+        hw->slave.clk_mode_13 = 0;
+    } else if (mode == 1) {
+        hw->misc.ck_idle_edge = 0;
+        hw->user.rsck_i_edge = 1;
+        hw->user.tsck_i_edge = 1;
+        hw->slave.clk_mode_13 = 1;
+    } else if (mode == 2) {
+        hw->misc.ck_idle_edge = 1;
+        hw->user.rsck_i_edge = 1;
+        hw->user.tsck_i_edge = 1;
+        hw->slave.clk_mode_13 = 0;
+    } else if (mode == 3) {
+        hw->misc.ck_idle_edge = 1;
+        hw->user.rsck_i_edge = 0;
+        hw->user.tsck_i_edge = 0;
+        hw->slave.clk_mode_13 = 1;
+    }
+    hw->slave.rsck_data_out = 0;
+}
+
+/**
+ * Set SPI to work in full duplex or half duplex mode.
+ *
+ * @param hw          Beginning address of the peripheral registers.
+ * @param half_duplex True to work in half duplex mode, otherwise in full duplex mode.
+ */
+static inline void spi_ll_set_half_duplex(spi_dev_t *hw, bool half_duplex)
+{
+    hw->user.doutdin = !half_duplex;
+}
+
+/**
+ * Set SPI to work in SIO mode or not.
+ *
+ * SIO is a mode which MOSI and MISO share a line. The device MUST work in half-duplexmode.
+ *
+ * @param hw       Beginning address of the peripheral registers.
+ * @param sio_mode True to work in SIO mode, otherwise false.
+ */
+static inline void spi_ll_set_sio_mode(spi_dev_t *hw, int sio_mode)
+{
+    hw->user.sio = sio_mode;
+}
+
+/**
+ * Configure the SPI transaction line mode for the master to use.
+ *
+ * @param hw        Beginning address of the peripheral registers.
+ * @param line_mode SPI transaction line mode to use, see ``spi_line_mode_t``.
+ */
+static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t line_mode)
+{
+    hw->ctrl.val &= ~SPI_LL_ONE_LINE_CTRL_MASK;
+    hw->user.val &= ~SPI_LL_ONE_LINE_USER_MASK;
+    hw->ctrl.fcmd_dual = (line_mode.cmd_lines == 2);
+    hw->ctrl.fcmd_quad = (line_mode.cmd_lines == 4);
+    hw->ctrl.faddr_dual = (line_mode.addr_lines == 2);
+    hw->ctrl.faddr_quad = (line_mode.addr_lines == 4);
+    hw->ctrl.fread_dual = (line_mode.data_lines == 2);
+    hw->user.fwrite_dual = (line_mode.data_lines == 2);
+    hw->ctrl.fread_quad = (line_mode.data_lines == 4);
+    hw->user.fwrite_quad = (line_mode.data_lines == 4);
+}
+
+/**
+ * Set the SPI slave to work in segment transaction mode
+ *
+ * @param hw        Beginning address of the peripheral registers.
+ * @param seg_trans True to work in seg mode, otherwise false.
+ */
+static inline void spi_ll_slave_set_seg_mode(spi_dev_t *hw, bool seg_trans)
+{
+    hw->dma_conf.dma_slv_seg_trans_en = seg_trans;
+}
+
+/**
+ * Select one of the CS to use in current transaction.
+ *
+ * @param hw    Beginning address of the peripheral registers.
+ * @param cs_id The cs to use, 0-2, otherwise none of them is used.
+ */
+static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id)
+{
+    hw->misc.cs0_dis = (cs_id == 0) ? 0 : 1;
+    hw->misc.cs1_dis = (cs_id == 1) ? 0 : 1;
+    hw->misc.cs2_dis = (cs_id == 2) ? 0 : 1;
+    hw->misc.cs3_dis = (cs_id == 3) ? 0 : 1;
+    hw->misc.cs4_dis = (cs_id == 4) ? 0 : 1;
+    hw->misc.cs5_dis = (cs_id == 5) ? 0 : 1;
+}
+
+/**
+ * Keep Chip Select activated after the current transaction.
+ *
+ * @param hw Beginning address of the peripheral registers.
+ * @param keep_active if 0 don't keep CS activated, else keep CS activated
+ */
+static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active)
+{
+    hw->misc.cs_keep_active = (keep_active != 0) ? 1 : 0;
+}
+
+/*------------------------------------------------------------------------------
+ * Configs: parameters
+ *----------------------------------------------------------------------------*/
+/**
+ * Set the clock for master by stored value.
+ *
+ * @param hw  Beginning address of the peripheral registers.
+ * @param val Stored clock configuration calculated before (by ``spi_ll_cal_clock``).
+ */
+static inline void spi_ll_master_set_clock_by_reg(spi_dev_t *hw, const spi_ll_clock_val_t *val)
+{
+    hw->clock.val = *(uint32_t *)val;
+}
+
+/**
+ * Get the frequency of given dividers. Don't use in app.
+ *
+ * @param fapb APB clock of the system.
+ * @param pre  Pre devider.
+ * @param n    Main divider.
+ *
+ * @return     Frequency of given dividers.
+ */
+static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n)
+{
+    return (fapb / (pre * n));
+}
+
+/**
+ * Calculate the nearest frequency avaliable for master.
+ *
+ * @param fapb       APB clock of the system.
+ * @param hz         Frequncy desired.
+ * @param duty_cycle Duty cycle desired.
+ * @param out_reg    Output address to store the calculated clock configurations for the return frequency.
+ *
+ * @return           Actual (nearest) frequency.
+ */
+static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg)
+{
+    typeof(GPSPI2.clock) reg;
+    int eff_clk;
+
+    //In hw, n, h and l are 1-64, pre is 1-8K. Value written to register is one lower than used value.
+    if (hz > ((fapb / 4) * 3)) {
+        //Using Fapb directly will give us the best result here.
+        reg.clkcnt_l = 0;
+        reg.clkcnt_h = 0;
+        reg.clkcnt_n = 0;
+        reg.clkdiv_pre = 0;
+        reg.clk_equ_sysclk = 1;
+        eff_clk = fapb;
+    } else {
+        //For best duty cycle resolution, we want n to be as close to 32 as possible, but
+        //we also need a pre/n combo that gets us as close as possible to the intended freq.
+        //To do this, we bruteforce n and calculate the best pre to go along with that.
+        //If there's a choice between pre/n combos that give the same result, use the one
+        //with the higher n.
+        int pre, n, h, l;
+        int bestn = -1;
+        int bestpre = -1;
+        int besterr = 0;
+        int errval;
+        for (n = 2; n <= 64; n++) { //Start at 2: we need to be able to set h/l so we have at least one high and one low pulse.
+            //Effectively, this does pre=round((fapb/n)/hz).
+            pre = ((fapb / n) + (hz / 2)) / hz;
+            if (pre <= 0) {
+                pre = 1;
+            }
+            if (pre > 16) {
+                pre = 16;
+            }
+            errval = abs(spi_ll_freq_for_pre_n(fapb, pre, n) - hz);
+            if (bestn == -1 || errval <= besterr) {
+                besterr = errval;
+                bestn = n;
+                bestpre = pre;
+            }
+        }
+
+        n = bestn;
+        pre = bestpre;
+        l = n;
+        //This effectively does round((duty_cycle*n)/256)
+        h = (duty_cycle * n + 127) / 256;
+        if (h <= 0) {
+            h = 1;
+        }
+
+        reg.clk_equ_sysclk = 0;
+        reg.clkcnt_n = n - 1;
+        reg.clkdiv_pre = pre - 1;
+        reg.clkcnt_h = h - 1;
+        reg.clkcnt_l = l - 1;
+        eff_clk = spi_ll_freq_for_pre_n(fapb, pre, n);
+    }
+    if (out_reg != NULL) {
+        *(uint32_t *)out_reg = reg.val;
+    }
+    return eff_clk;
+}
+
+/**
+ * Calculate and set clock for SPI master according to desired parameters.
+ *
+ * This takes long, suggest to calculate the configuration during
+ * initialization by ``spi_ll_master_cal_clock`` and store the result, then
+ * configure the clock by stored value when used by
+ * ``spi_ll_msater_set_clock_by_reg``.
+ *
+ * @param hw         Beginning address of the peripheral registers.
+ * @param fapb       APB clock of the system.
+ * @param hz         Frequncy desired.
+ * @param duty_cycle Duty cycle desired.
+ *
+ * @return           Actual frequency that is used.
+ */
+static inline int spi_ll_master_set_clock(spi_dev_t *hw, int fapb, int hz, int duty_cycle)
+{
+    spi_ll_clock_val_t reg_val;
+    int freq = spi_ll_master_cal_clock(fapb, hz, duty_cycle, &reg_val);
+    spi_ll_master_set_clock_by_reg(hw, &reg_val);
+    return freq;
+}
+
+/**
+ * Set the mosi delay after the output edge to the signal. (Preview)
+ *
+ * The delay mode/num is a Espressif conception, may change in the new chips.
+ *
+ * @param hw         Beginning address of the peripheral registers.
+ * @param delay_mode Delay mode, see TRM.
+ * @param delay_num  APB clocks to delay.
+ */
+static inline void spi_ll_set_mosi_delay(spi_dev_t *hw, int delay_mode, int delay_num)
+{
+}
+
+/**
+ * Set the miso delay applied to the input signal before the internal peripheral. (Preview)
+ *
+ * The delay mode/num is a Espressif conception, may change in the new chips.
+ *
+ * @param hw         Beginning address of the peripheral registers.
+ * @param delay_mode Delay mode, see TRM.
+ * @param delay_num  APB clocks to delay.
+ */
+static inline void spi_ll_set_miso_delay(spi_dev_t *hw, int delay_mode, int delay_num)
+{
+}
+
+/**
+ * Set the delay of SPI clocks before the CS inactive edge after the last SPI clock.
+ *
+ * @param hw   Beginning address of the peripheral registers.
+ * @param hold Delay of SPI clocks after the last clock, 0 to disable the hold phase.
+ */
+static inline void spi_ll_master_set_cs_hold(spi_dev_t *hw, int hold)
+{
+    hw->user1.cs_hold_time = hold;
+    hw->user.cs_hold = hold ? 1 : 0;
+}
+
+/**
+ * Set the delay of SPI clocks before the first SPI clock after the CS active edge.
+ *
+ * Note ESP32 doesn't support to use this feature when command/address phases
+ * are used in full duplex mode.
+ *
+ * @param hw    Beginning address of the peripheral registers.
+ * @param setup Delay of SPI clocks after the CS active edge, 0 to disable the setup phase.
+ */
+static inline void spi_ll_master_set_cs_setup(spi_dev_t *hw, uint8_t setup)
+{
+    hw->user1.cs_setup_time = setup - 1;
+    hw->user.cs_setup = setup ? 1 : 0;
+}
+
+/*------------------------------------------------------------------------------
+ * Configs: data
+ *----------------------------------------------------------------------------*/
+/**
+ * Set the output length (master).
+ * This should be called before master setting MISO(input) length
+ *
+ * @param hw     Beginning address of the peripheral registers.
+ * @param bitlen output length, in bits.
+ */
+static inline void spi_ll_set_mosi_bitlen(spi_dev_t *hw, size_t bitlen)
+{
+    if (bitlen > 0) {
+        hw->ms_dlen.ms_data_bitlen = bitlen - 1;
+    }
+}
+
+/**
+ * Set the input length (master).
+ *
+ * @param hw     Beginning address of the peripheral registers.
+ * @param bitlen input length, in bits.
+ */
+static inline void spi_ll_set_miso_bitlen(spi_dev_t *hw, size_t bitlen)
+{
+    if (bitlen > 0) {
+        hw->ms_dlen.ms_data_bitlen = bitlen - 1;
+    }
+}
+
+/**
+ * Set the maximum input length (slave).
+ *
+ * @param hw     Beginning address of the peripheral registers.
+ * @param bitlen Input length, in bits.
+ */
+static inline void spi_ll_slave_set_rx_bitlen(spi_dev_t *hw, size_t bitlen)
+{
+    //This is not used in P4
+}
+
+/**
+ * Set the maximum output length (slave).
+ *
+ * @param hw     Beginning address of the peripheral registers.
+ * @param bitlen Output length, in bits.
+ */
+static inline void spi_ll_slave_set_tx_bitlen(spi_dev_t *hw, size_t bitlen)
+{
+    //This is not used in P4
+}
+
+/**
+ * Set the length of command phase.
+ *
+ * When in 4-bit mode, the SPI cycles of the phase will be shorter. E.g. 16-bit
+ * command phases takes 4 cycles in 4-bit mode.
+ *
+ * @param hw     Beginning address of the peripheral registers.
+ * @param bitlen Length of command phase, in bits. 0 to disable the command phase.
+ */
+static inline void spi_ll_set_command_bitlen(spi_dev_t *hw, int bitlen)
+{
+    hw->user2.usr_command_bitlen = bitlen - 1;
+    hw->user.usr_command = bitlen ? 1 : 0;
+}
+
+/**
+ * Set the length of address phase.
+ *
+ * When in 4-bit mode, the SPI cycles of the phase will be shorter. E.g. 16-bit
+ * address phases takes 4 cycles in 4-bit mode.
+ *
+ * @param hw     Beginning address of the peripheral registers.
+ * @param bitlen Length of address phase, in bits. 0 to disable the address phase.
+ */
+static inline void spi_ll_set_addr_bitlen(spi_dev_t *hw, int bitlen)
+{
+    hw->user1.usr_addr_bitlen = bitlen - 1;
+    hw->user.usr_addr = bitlen ? 1 : 0;
+}
+
+/**
+ * Set the address value in an intuitive way.
+ *
+ * The length and lsbfirst is required to shift and swap the address to the right place.
+ *
+ * @param hw       Beginning address of the peripheral registers.
+ * @param address  Address to set
+ * @param addrlen  Length of the address phase
+ * @param lsbfirst Whether the LSB first feature is enabled.
+ */
+static inline void spi_ll_set_address(spi_dev_t *hw, uint64_t addr, int addrlen, uint32_t lsbfirst)
+{
+    if (lsbfirst) {
+        /* The output address start from the LSB of the highest byte, i.e.
+        * addr[24] -> addr[31]
+        * ...
+        * addr[0] -> addr[7]
+        * So swap the byte order to let the LSB sent first.
+        */
+        addr = HAL_SWAP32(addr);
+        //otherwise only addr register is sent
+        hw->addr.val = addr;
+    } else {
+        // shift the address to MSB of addr register.
+        // output address will be sent from MSB to LSB of addr register
+        hw->addr.val = addr << (32 - addrlen);
+    }
+}
+
+/**
+ * Set the command value in an intuitive way.
+ *
+ * The length and lsbfirst is required to shift and swap the command to the right place.
+ *
+ * @param hw       Beginning command of the peripheral registers.
+ * @param command  Command to set
+ * @param addrlen  Length of the command phase
+ * @param lsbfirst Whether the LSB first feature is enabled.
+ */
+static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, bool lsbfirst)
+{
+    if (lsbfirst) {
+        // The output command start from bit0 to bit 15, kept as is.
+        HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, cmd);
+    } else {
+        /* Output command will be sent from bit 7 to 0 of command_value, and
+         * then bit 15 to 8 of the same register field. Shift and swap to send
+         * more straightly.
+         */
+        HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen));
+    }
+}
+
+/**
+ * Set dummy clocks to output before RX phase (master), or clocks to skip
+ * before the data phase and after the address phase (slave).
+ *
+ * Note this phase is also used to compensate RX timing in half duplex mode.
+ *
+ * @param hw      Beginning address of the peripheral registers.
+ * @param dummy_n Dummy cycles used. 0 to disable the dummy phase.
+ */
+static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n)
+{
+    hw->user.usr_dummy = dummy_n ? 1 : 0;
+    HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1);
+}
+
+/**
+ * Enable/disable the RX data phase.
+ *
+ * @param hw     Beginning address of the peripheral registers.
+ * @param enable True if RX phase exist, otherwise false.
+ */
+static inline void spi_ll_enable_miso(spi_dev_t *hw, int enable)
+{
+    hw->user.usr_miso = enable;
+}
+
+/**
+ * Enable/disable the TX data phase.
+ *
+ * @param hw     Beginning address of the peripheral registers.
+ * @param enable True if TX phase exist, otherwise false.
+ */
+static inline void spi_ll_enable_mosi(spi_dev_t *hw, int enable)
+{
+    hw->user.usr_mosi = enable;
+}
+
+/**
+ * Get the received bit length of the slave.
+ *
+ * @param hw Beginning address of the peripheral registers.
+ *
+ * @return   Received bits of the slave.
+ */
+static inline uint32_t spi_ll_slave_get_rcv_bitlen(spi_dev_t *hw)
+{
+    return hw->slave1.slv_data_bitlen;
+}
+
+/*------------------------------------------------------------------------------
+ * Interrupts
+ *----------------------------------------------------------------------------*/
+//helper macros to generate code for each interrupts
+#define FOR_EACH_ITEM(op, list) do { list(op) } while(0)
+#define INTR_LIST(item)    \
+    item(SPI_LL_INTR_TRANS_DONE,    dma_int_ena.trans_done_int,         dma_int_raw.trans_done_int,         dma_int_clr.trans_done_int,            dma_int_set.trans_done_int) \
+    item(SPI_LL_INTR_RDBUF,         dma_int_ena.slv_rd_buf_done_int,    dma_int_raw.slv_rd_buf_done_int,    dma_int_clr.slv_rd_buf_done_int,       dma_int_set.slv_rd_buf_done_int) \
+    item(SPI_LL_INTR_WRBUF,         dma_int_ena.slv_wr_buf_done_int,    dma_int_raw.slv_wr_buf_done_int,    dma_int_clr.slv_wr_buf_done_int,       dma_int_set.slv_wr_buf_done_int) \
+    item(SPI_LL_INTR_RDDMA,         dma_int_ena.slv_rd_dma_done_int,    dma_int_raw.slv_rd_dma_done_int,    dma_int_clr.slv_rd_dma_done_int,       dma_int_set.slv_rd_dma_done_int) \
+    item(SPI_LL_INTR_WRDMA,         dma_int_ena.slv_wr_dma_done_int,    dma_int_raw.slv_wr_dma_done_int,    dma_int_clr.slv_wr_dma_done_int,       dma_int_set.slv_wr_dma_done_int) \
+    item(SPI_LL_INTR_SEG_DONE,      dma_int_ena.dma_seg_trans_done_int, dma_int_raw.dma_seg_trans_done_int, dma_int_clr.dma_seg_trans_done_int,    dma_int_set.dma_seg_trans_done_int) \
+    item(SPI_LL_INTR_CMD7,          dma_int_ena.slv_cmd7_int,           dma_int_raw.slv_cmd7_int,           dma_int_clr.slv_cmd7_int,              dma_int_set.slv_cmd7_int) \
+    item(SPI_LL_INTR_CMD8,          dma_int_ena.slv_cmd8_int,           dma_int_raw.slv_cmd8_int,           dma_int_clr.slv_cmd8_int,              dma_int_set.slv_cmd8_int) \
+    item(SPI_LL_INTR_CMD9,          dma_int_ena.slv_cmd9_int,           dma_int_raw.slv_cmd9_int,           dma_int_clr.slv_cmd9_int,              dma_int_set.slv_cmd9_int) \
+    item(SPI_LL_INTR_CMDA,          dma_int_ena.slv_cmda_int,           dma_int_raw.slv_cmda_int,           dma_int_clr.slv_cmda_int,              dma_int_set.slv_cmda_int)
+
+
+static inline void spi_ll_enable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask)
+{
+#define ENA_INTR(intr_bit, en_reg, ...) if (intr_mask & (intr_bit)) hw->en_reg = 1;
+    FOR_EACH_ITEM(ENA_INTR, INTR_LIST);
+#undef ENA_INTR
+}
+
+static inline void spi_ll_disable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask)
+{
+#define DIS_INTR(intr_bit, en_reg, ...) if (intr_mask & (intr_bit)) hw->en_reg = 0;
+    FOR_EACH_ITEM(DIS_INTR, INTR_LIST);
+#undef DIS_INTR
+}
+
+static inline void spi_ll_set_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask)
+{
+#define SET_INTR(intr_bit, _, __, ___, set_reg) if (intr_mask & (intr_bit)) hw->set_reg = 1;
+    FOR_EACH_ITEM(SET_INTR, INTR_LIST);
+#undef SET_INTR
+}
+
+static inline void spi_ll_clear_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask)
+{
+#define CLR_INTR(intr_bit, _, __, clr_reg, ...) if (intr_mask & (intr_bit)) hw->clr_reg = 1;
+    FOR_EACH_ITEM(CLR_INTR, INTR_LIST);
+#undef CLR_INTR
+}
+
+static inline bool spi_ll_get_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask)
+{
+#define GET_INTR(intr_bit, _, sta_reg, ...) if (intr_mask & (intr_bit) && hw->sta_reg) return true;
+    FOR_EACH_ITEM(GET_INTR, INTR_LIST);
+    return false;
+#undef GET_INTR
+}
+
+#undef FOR_EACH_ITEM
+#undef INTR_LIST
+
+/**
+ * Disable the trans_done interrupt.
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_disable_int(spi_dev_t *hw)
+{
+    hw->dma_int_ena.trans_done_int = 0;
+}
+
+/**
+ * Clear the trans_done interrupt.
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_clear_int_stat(spi_dev_t *hw)
+{
+    hw->dma_int_clr.trans_done_int = 1;
+}
+
+/**
+ * Set the trans_done interrupt.
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_set_int_stat(spi_dev_t *hw)
+{
+    hw->dma_int_set.trans_done_int = 1;
+}
+
+/**
+ * Enable the trans_done interrupt.
+ *
+ * @param hw Beginning address of the peripheral registers.
+ */
+static inline void spi_ll_enable_int(spi_dev_t *hw)
+{
+    hw->dma_int_ena.trans_done_int = 1;
+}
+
+/*------------------------------------------------------------------------------
+ * Slave HD
+ *----------------------------------------------------------------------------*/
+static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t *hw, spi_ll_trans_len_cond_t cond_mask)
+{
+    hw->slave.slv_rdbuf_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_RDBUF) ? 1 : 0;
+    hw->slave.slv_wrbuf_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRBUF) ? 1 : 0;
+    hw->slave.slv_rddma_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_RDDMA) ? 1 : 0;
+    hw->slave.slv_wrdma_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRDMA) ? 1 : 0;
+}
+
+static inline int spi_ll_slave_get_rx_byte_len(spi_dev_t *hw)
+{
+    return hw->slave1.slv_data_bitlen / 8;
+}
+
+static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw)
+{
+    return hw->slave1.slv_last_addr;
+}
+
+#undef SPI_LL_RST_MASK
+#undef SPI_LL_UNUSED_INT_MASK
+
+/**
+ * Get the base spi command
+ *
+ * @param cmd_t           Command value
+ */
+static inline uint8_t spi_ll_get_slave_hd_base_command(spi_command_t cmd_t)
+{
+    uint8_t cmd_base = 0x00;
+    switch (cmd_t)
+    {
+    case SPI_CMD_HD_WRBUF:
+        cmd_base = SPI_LL_BASE_CMD_HD_WRBUF;
+        break;
+    case SPI_CMD_HD_RDBUF:
+        cmd_base = SPI_LL_BASE_CMD_HD_RDBUF;
+        break;
+    case SPI_CMD_HD_WRDMA:
+        cmd_base = SPI_LL_BASE_CMD_HD_WRDMA;
+        break;
+    case SPI_CMD_HD_RDDMA:
+        cmd_base = SPI_LL_BASE_CMD_HD_RDDMA;
+        break;
+    case SPI_CMD_HD_SEG_END:
+        cmd_base = SPI_LL_BASE_CMD_HD_SEG_END;
+        break;
+    case SPI_CMD_HD_EN_QPI:
+        cmd_base = SPI_LL_BASE_CMD_HD_EN_QPI;
+        break;
+    case SPI_CMD_HD_WR_END:
+        cmd_base = SPI_LL_BASE_CMD_HD_WR_END;
+        break;
+    case SPI_CMD_HD_INT0:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT0;
+        break;
+    case SPI_CMD_HD_INT1:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT1;
+        break;
+    case SPI_CMD_HD_INT2:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT2;
+        break;
+    default:
+        HAL_ASSERT(cmd_base);
+    }
+    return cmd_base;
+}
+
+/**
+ * Get the spi communication command
+ *
+ * @param cmd_t           Base command value
+ * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
+ */
+static inline uint16_t spi_ll_get_slave_hd_command(spi_command_t cmd_t, spi_line_mode_t line_mode)
+{
+    uint8_t cmd_base = spi_ll_get_slave_hd_base_command(cmd_t);
+    uint8_t cmd_mod = 0x00; //CMD:1-bit, ADDR:1-bit, DATA:1-bit
+
+    if (line_mode.data_lines == 2) {
+        if (line_mode.addr_lines == 2) {
+            cmd_mod = 0x50; //CMD:1-bit, ADDR:2-bit, DATA:2-bit
+        } else {
+            cmd_mod = 0x10; //CMD:1-bit, ADDR:1-bit, DATA:2-bit
+        }
+    } else if (line_mode.data_lines == 4) {
+        if (line_mode.addr_lines == 4) {
+            cmd_mod = 0xA0; //CMD:1-bit, ADDR:4-bit, DATA:4-bit
+        } else {
+            cmd_mod = 0x20; //CMD:1-bit, ADDR:1-bit, DATA:4-bit
+        }
+    }
+    if (cmd_base == SPI_LL_BASE_CMD_HD_SEG_END || cmd_base == SPI_LL_BASE_CMD_HD_EN_QPI) {
+        cmd_mod = 0x00;
+    }
+
+    return cmd_base | cmd_mod;
+}
+
+/**
+ * Get the dummy bits
+ *
+ * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
+ */
+static inline int spi_ll_get_slave_hd_dummy_bits(spi_line_mode_t line_mode)
+{
+    return 8;
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 1 - 0
components/hal/esp32s2/include/hal/spi_ll.h

@@ -107,6 +107,7 @@ typedef enum {
  * @param hw Beginning address of the peripheral registers.
  * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
  */
+__attribute__((always_inline))
 static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
 {
     //empty, keep this for compatibility

+ 1 - 0
components/hal/esp32s3/include/hal/spi_ll.h

@@ -99,6 +99,7 @@ typedef enum {
  * @param hw Beginning address of the peripheral registers.
  * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
  */
+__attribute__((always_inline))
 static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source){
     switch (clk_source)
     {

+ 11 - 5
components/hal/include/hal/spi_hal.h

@@ -29,9 +29,9 @@
 #include "esp_err.h"
 #include "soc/soc_caps.h"
 #include "hal/spi_types.h"
+#include "hal/dma_types.h"
 #if SOC_GPSPI_SUPPORTED
 #include "hal/spi_ll.h"
-#include "soc/lldesc.h"
 #endif
 
 #ifdef __cplusplus
@@ -40,6 +40,12 @@ extern "C" {
 
 #if SOC_GPSPI_SUPPORTED
 
+#if SOC_GPSPI_SUPPORTED && (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI)
+typedef dma_descriptor_align8_t spi_dma_desc_t;
+#else
+typedef dma_descriptor_align4_t spi_dma_desc_t;
+#endif
+
 /**
  * Input parameters to the ``spi_hal_cal_clock_conf`` to calculate the timing configuration
  */
@@ -76,11 +82,11 @@ typedef struct {
     spi_dma_dev_t *dma_in;              ///< Input  DMA(DMA -> RAM) peripheral register address
     spi_dma_dev_t *dma_out;             ///< Output DMA(RAM -> DMA) peripheral register address
     bool dma_enabled;                   ///< Whether the DMA is enabled, do not update after initialization
-    lldesc_t  *dmadesc_tx;              /**< Array of DMA descriptor used by the TX DMA.
+    spi_dma_desc_t *dmadesc_tx;        /**< Array of DMA descriptor used by the TX DMA.
                                          *   The amount should be larger than dmadesc_n. The driver should ensure that
                                          *   the data to be sent is shorter than the descriptors can hold.
                                          */
-    lldesc_t *dmadesc_rx;               /**< Array of DMA descriptor used by the RX DMA.
+    spi_dma_desc_t *dmadesc_rx;         /**< Array of DMA descriptor used by the RX DMA.
                                          *   The amount should be larger than dmadesc_n. The driver should ensure that
                                          *   the data to be sent is shorter than the descriptors can hold.
                                          */
@@ -112,11 +118,11 @@ typedef struct {
  */
 typedef struct {
     /* These two need to be malloced by the driver first */
-    lldesc_t  *dmadesc_tx;              /**< Array of DMA descriptor used by the TX DMA.
+    spi_dma_desc_t *dmadesc_tx;        /**< Array of DMA descriptor used by the TX DMA.
                                          *   The amount should be larger than dmadesc_n. The driver should ensure that
                                          *   the data to be sent is shorter than the descriptors can hold.
                                          */
-    lldesc_t *dmadesc_rx;               /**< Array of DMA descriptor used by the RX DMA.
+    spi_dma_desc_t *dmadesc_rx;         /**< Array of DMA descriptor used by the RX DMA.
                                          *   The amount should be larger than dmadesc_n. The driver should ensure that
                                          *   the data to be sent is shorter than the descriptors can hold.
                                          */

+ 13 - 3
components/hal/spi_hal.c

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -13,17 +13,27 @@
 #include "soc/clk_tree_defs.h"
 
 //This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
-#if SOC_AHB_GDMA_VERSION == 1
+#if SOC_GDMA_SUPPORTED
+#if (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AHB) && (SOC_AHB_GDMA_VERSION == 1)
 #include "soc/gdma_struct.h"
 #include "hal/gdma_ll.h"
-
 #define spi_dma_ll_rx_enable_burst_data(dev, chan, enable)         gdma_ll_rx_enable_data_burst(&GDMA, chan, enable);
 #define spi_dma_ll_tx_enable_burst_data(dev, chan, enable)         gdma_ll_tx_enable_data_burst(&GDMA, chan, enable);
 #define spi_dma_ll_rx_enable_burst_desc(dev, chan, enable)         gdma_ll_rx_enable_descriptor_burst(&GDMA, chan, enable);
 #define spi_dma_ll_tx_enable_burst_desc(dev, chan, enable)         gdma_ll_tx_enable_descriptor_burst(&GDMA, chan, enable);
 #define spi_dma_ll_enable_out_auto_wrback(dev, chan, enable)          gdma_ll_tx_enable_auto_write_back(&GDMA, chan, enable);
 #define spi_dma_ll_set_out_eof_generation(dev, chan, enable)          gdma_ll_tx_set_eof_mode(&GDMA, chan, enable);
+
+#elif (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI)   //TODO: IDF-6152, refactor spi hal layer
+#include "hal/axi_dma_ll.h"
+#define spi_dma_ll_rx_enable_burst_data(dev, chan, enable)         axi_dma_ll_rx_enable_data_burst(&AXI_DMA, chan, enable);
+#define spi_dma_ll_tx_enable_burst_data(dev, chan, enable)         axi_dma_ll_tx_enable_data_burst(&AXI_DMA, chan, enable);
+#define spi_dma_ll_rx_enable_burst_desc(dev, chan, enable)         axi_dma_ll_rx_enable_descriptor_burst(&AXI_DMA, chan, enable);
+#define spi_dma_ll_tx_enable_burst_desc(dev, chan, enable)         axi_dma_ll_tx_enable_descriptor_burst(&AXI_DMA, chan, enable);
+#define spi_dma_ll_enable_out_auto_wrback(dev, chan, enable)          axi_dma_ll_tx_enable_auto_write_back(&AXI_DMA, chan, enable);
+#define spi_dma_ll_set_out_eof_generation(dev, chan, enable)          axi_dma_ll_tx_set_eof_mode(&AXI_DMA, chan, enable);
 #endif
+#endif  //SOC_GDMA_SUPPORTED
 
 /* The tag may be unused if log level is set to NONE  */
 static const __attribute__((unused)) char SPI_HAL_TAG[] = "spi_hal";

+ 58 - 7
components/hal/spi_hal_iram.c

@@ -9,13 +9,14 @@
 
 #include "hal/spi_hal.h"
 #include "hal/assert.h"
+#include "soc/ext_mem_defs.h"
 #include "soc/soc_caps.h"
 
 //This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
-#if SOC_AHB_GDMA_VERSION == 1
+#if SOC_GDMA_SUPPORTED
+#if (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AHB) && (SOC_AHB_GDMA_VERSION == 1)
 #include "soc/gdma_struct.h"
 #include "hal/gdma_ll.h"
-
 #define spi_dma_ll_rx_reset(dev, chan)                             gdma_ll_rx_reset_channel(&GDMA, chan)
 #define spi_dma_ll_tx_reset(dev, chan)                             gdma_ll_tx_reset_channel(&GDMA, chan);
 #define spi_dma_ll_rx_start(dev, chan, addr) do {\
@@ -26,7 +27,21 @@
             gdma_ll_tx_set_desc_addr(&GDMA, chan, (uint32_t)addr);\
             gdma_ll_tx_start(&GDMA, chan);\
         } while (0)
+
+#elif (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI)   //TODO: IDF-6152, refactor spi hal layer
+#include "hal/axi_dma_ll.h"
+#define spi_dma_ll_rx_reset(dev, chan)                             axi_dma_ll_rx_reset_channel(&AXI_DMA, chan)
+#define spi_dma_ll_tx_reset(dev, chan)                             axi_dma_ll_tx_reset_channel(&AXI_DMA, chan);
+#define spi_dma_ll_rx_start(dev, chan, addr) do {\
+            axi_dma_ll_rx_set_desc_addr(&AXI_DMA, chan, (uint32_t)addr);\
+            axi_dma_ll_rx_start(&AXI_DMA, chan);\
+        } while (0)
+#define spi_dma_ll_tx_start(dev, chan, addr) do {\
+            axi_dma_ll_tx_set_desc_addr(&AXI_DMA, chan, (uint32_t)addr);\
+            axi_dma_ll_tx_start(&AXI_DMA, chan);\
+        } while (0)
 #endif
+#endif  //SOC_GDMA_SUPPORTED
 
 void spi_hal_setup_device(spi_hal_context_t *hal, const spi_hal_dev_config_t *dev)
 {
@@ -37,7 +52,6 @@ void spi_hal_setup_device(spi_hal_context_t *hal, const spi_hal_dev_config_t *de
 #endif
     spi_ll_master_set_pos_cs(hw, dev->cs_pin_id, dev->positive_cs);
     spi_ll_master_set_clock_by_reg(hw, &dev->timing_conf.clock_reg);
-    spi_ll_set_clk_source(hw, dev->timing_conf.clock_source);
     //Configure bit order
     spi_ll_set_rx_lsbfirst(hw, dev->rx_lsbfirst);
     spi_ll_set_tx_lsbfirst(hw, dev->tx_lsbfirst);
@@ -131,6 +145,43 @@ void spi_hal_setup_trans(spi_hal_context_t *hal, const spi_hal_dev_config_t *dev
     memcpy(&hal->trans_config, trans, sizeof(spi_hal_trans_config_t));
 }
 
+#if SOC_NON_CACHEABLE_OFFSET
+#define ADDR_DMA_2_CPU(addr)   ((typeof(addr))((uint32_t)(addr) + SOC_NON_CACHEABLE_OFFSET))
+#define ADDR_CPU_2_DMA(addr)   ((typeof(addr))((uint32_t)(addr) - SOC_NON_CACHEABLE_OFFSET))
+#else
+#define ADDR_DMA_2_CPU(addr)   (addr)
+#define ADDR_CPU_2_DMA(addr)   (addr)
+#endif
+//TODO: IDF-6152, refactor spi hal layer
+static void s_spi_hal_dma_desc_setup_link(spi_dma_desc_t *dmadesc, const void *data, int len, bool is_rx)
+{
+    dmadesc = ADDR_DMA_2_CPU(dmadesc);
+    int n = 0;
+    while (len) {
+        int dmachunklen = len;
+        if (dmachunklen > DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED) {
+            dmachunklen = DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
+        }
+        if (is_rx) {
+            //Receive needs DMA length rounded to next 32-bit boundary
+            dmadesc[n].dw0.size = (dmachunklen + 3) & (~3);
+            dmadesc[n].dw0.length = (dmachunklen + 3) & (~3);
+        } else {
+            dmadesc[n].dw0.size = dmachunklen;
+            dmadesc[n].dw0.length = dmachunklen;
+        }
+        dmadesc[n].buffer = (uint8_t *)data;
+        dmadesc[n].dw0.suc_eof = 0;
+        dmadesc[n].dw0.owner = 1;
+        dmadesc[n].next = ADDR_CPU_2_DMA(&dmadesc[n + 1]);
+        len -= dmachunklen;
+        data += dmachunklen;
+        n++;
+    }
+    dmadesc[n - 1].dw0.suc_eof = 1; //Mark last DMA desc as end of stream.
+    dmadesc[n - 1].next = NULL;
+}
+
 void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *dev, const spi_hal_trans_config_t *trans)
 {
     spi_dev_t *hw = hal->hw;
@@ -140,13 +191,13 @@ void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *de
         if (!hal->dma_enabled) {
             //No need to setup anything; we'll copy the result out of the work registers directly later.
         } else {
-            lldesc_setup_link(hal->dmadesc_rx, trans->rcv_buffer, ((trans->rx_bitlen + 7) / 8), true);
+            s_spi_hal_dma_desc_setup_link(hal->dmadesc_rx, trans->rcv_buffer, ((trans->rx_bitlen + 7) / 8), true);
 
             spi_dma_ll_rx_reset(hal->dma_in, hal->rx_dma_chan);
             spi_ll_dma_rx_fifo_reset(hal->hw);
             spi_ll_infifo_full_clr(hal->hw);
             spi_ll_dma_rx_enable(hal->hw, 1);
-            spi_dma_ll_rx_start(hal->dma_in, hal->rx_dma_chan, hal->dmadesc_rx);
+            spi_dma_ll_rx_start(hal->dma_in, hal->rx_dma_chan, (lldesc_t *)hal->dmadesc_rx);
         }
 
     }
@@ -165,13 +216,13 @@ void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *de
             //Need to copy data to registers manually
             spi_ll_write_buffer(hw, trans->send_buffer, trans->tx_bitlen);
         } else {
-            lldesc_setup_link(hal->dmadesc_tx, trans->send_buffer, (trans->tx_bitlen + 7) / 8, false);
+            s_spi_hal_dma_desc_setup_link(hal->dmadesc_tx, trans->send_buffer, (trans->tx_bitlen + 7) / 8, false);
 
             spi_dma_ll_tx_reset(hal->dma_out, hal->tx_dma_chan);
             spi_ll_dma_tx_fifo_reset(hal->hw);
             spi_ll_outfifo_empty_clr(hal->hw);
             spi_ll_dma_tx_enable(hal->hw, 1);
-            spi_dma_ll_tx_start(hal->dma_out, hal->tx_dma_chan, hal->dmadesc_tx);
+            spi_dma_ll_tx_start(hal->dma_out, hal->tx_dma_chan, (lldesc_t *)hal->dmadesc_tx);
         }
     }
 

+ 12 - 2
components/hal/spi_slave_hal.c

@@ -3,17 +3,27 @@
 #include "soc/soc_caps.h"
 
 //This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
-#if SOC_AHB_GDMA_VERSION == 1
+#if SOC_GDMA_SUPPORTED
+#if (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AHB) && (SOC_AHB_GDMA_VERSION == 1)
 #include "soc/gdma_struct.h"
 #include "hal/gdma_ll.h"
-
 #define spi_dma_ll_rx_enable_burst_data(dev, chan, enable)         gdma_ll_rx_enable_data_burst(&GDMA, chan, enable);
 #define spi_dma_ll_tx_enable_burst_data(dev, chan, enable)         gdma_ll_tx_enable_data_burst(&GDMA, chan, enable);
 #define spi_dma_ll_rx_enable_burst_desc(dev, chan, enable)         gdma_ll_rx_enable_descriptor_burst(&GDMA, chan, enable);
 #define spi_dma_ll_tx_enable_burst_desc(dev, chan, enable)         gdma_ll_tx_enable_descriptor_burst(&GDMA, chan, enable);
 #define spi_dma_ll_enable_out_auto_wrback(dev, chan, enable)          gdma_ll_tx_enable_auto_write_back(&GDMA, chan, enable);
 #define spi_dma_ll_set_out_eof_generation(dev, chan, enable)          gdma_ll_tx_set_eof_mode(&GDMA, chan, enable);
+
+#elif (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI)   //TODO: IDF-6152, refactor spi hal layer
+#include "hal/axi_dma_ll.h"
+#define spi_dma_ll_rx_enable_burst_data(dev, chan, enable)         axi_dma_ll_rx_enable_data_burst(&AXI_DMA, chan, enable);
+#define spi_dma_ll_tx_enable_burst_data(dev, chan, enable)         axi_dma_ll_tx_enable_data_burst(&AXI_DMA, chan, enable);
+#define spi_dma_ll_rx_enable_burst_desc(dev, chan, enable)         axi_dma_ll_rx_enable_descriptor_burst(&AXI_DMA, chan, enable);
+#define spi_dma_ll_tx_enable_burst_desc(dev, chan, enable)         axi_dma_ll_tx_enable_descriptor_burst(&AXI_DMA, chan, enable);
+#define spi_dma_ll_enable_out_auto_wrback(dev, chan, enable)          axi_dma_ll_tx_enable_auto_write_back(&AXI_DMA, chan, enable);
+#define spi_dma_ll_set_out_eof_generation(dev, chan, enable)          axi_dma_ll_tx_set_eof_mode(&AXI_DMA, chan, enable);
 #endif
+#endif  //SOC_GDMA_SUPPORTED
 
 static void s_spi_slave_hal_dma_init_config(const spi_slave_hal_context_t *hal)
 {

+ 20 - 4
components/hal/spi_slave_hal_iram.c

@@ -1,12 +1,13 @@
 #include "hal/spi_slave_hal.h"
 #include "hal/spi_ll.h"
+#include "soc/ext_mem_defs.h"
 #include "soc/soc_caps.h"
 
 //This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
-#if SOC_AHB_GDMA_VERSION == 1
+#if SOC_GDMA_SUPPORTED
+#if (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AHB) && (SOC_AHB_GDMA_VERSION == 1)
 #include "soc/gdma_struct.h"
 #include "hal/gdma_ll.h"
-
 #define spi_dma_ll_rx_reset(dev, chan)                             gdma_ll_rx_reset_channel(&GDMA, chan)
 #define spi_dma_ll_tx_reset(dev, chan)                             gdma_ll_tx_reset_channel(&GDMA, chan);
 #define spi_dma_ll_rx_start(dev, chan, addr) do {\
@@ -17,7 +18,21 @@
             gdma_ll_tx_set_desc_addr(&GDMA, chan, (uint32_t)addr);\
             gdma_ll_tx_start(&GDMA, chan);\
         } while (0)
+
+#elif (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI)   //TODO: IDF-6152, refactor spi hal layer
+#include "hal/axi_dma_ll.h"
+#define spi_dma_ll_rx_reset(dev, chan)                             axi_dma_ll_rx_reset_channel(&AXI_DMA, chan)
+#define spi_dma_ll_tx_reset(dev, chan)                             axi_dma_ll_tx_reset_channel(&AXI_DMA, chan);
+#define spi_dma_ll_rx_start(dev, chan, addr) do {\
+            axi_dma_ll_rx_set_desc_addr(&AXI_DMA, chan, (uint32_t)addr);\
+            axi_dma_ll_rx_start(&AXI_DMA, chan);\
+        } while (0)
+#define spi_dma_ll_tx_start(dev, chan, addr) do {\
+            axi_dma_ll_tx_set_desc_addr(&AXI_DMA, chan, (uint32_t)addr);\
+            axi_dma_ll_tx_start(&AXI_DMA, chan);\
+        } while (0)
 #endif
+#endif  //SOC_GDMA_SUPPORTED
 
 bool spi_slave_hal_usr_is_done(spi_slave_hal_context_t* hal)
 {
@@ -45,10 +60,11 @@ void spi_slave_hal_prepare_data(const spi_slave_hal_context_t *hal)
             spi_ll_infifo_full_clr(hal->hw);
 
             spi_ll_dma_rx_enable(hal->hw, 1);
-            spi_dma_ll_rx_start(hal->dma_in, hal->rx_dma_chan, &hal->dmadesc_rx[0]);
+            spi_dma_ll_rx_start(hal->dma_in, hal->rx_dma_chan, hal->dmadesc_rx);
         }
         if (hal->tx_buffer) {
             lldesc_setup_link(hal->dmadesc_tx, hal->tx_buffer, (hal->bitlen + 7) / 8, false);
+
             //reset dma outlink, this should be reset before spi related reset
             spi_dma_ll_tx_reset(hal->dma_out, hal->tx_dma_chan);
             spi_ll_dma_tx_fifo_reset(hal->dma_out);
@@ -56,7 +72,7 @@ void spi_slave_hal_prepare_data(const spi_slave_hal_context_t *hal)
             spi_ll_outfifo_empty_clr(hal->hw);
 
             spi_ll_dma_tx_enable(hal->hw, 1);
-            spi_dma_ll_tx_start(hal->dma_out, hal->tx_dma_chan, (&hal->dmadesc_tx[0]));
+            spi_dma_ll_tx_start(hal->dma_out, hal->tx_dma_chan, hal->dmadesc_tx);
         }
     } else {
         //No DMA. Turn off SPI and copy data to transmit buffers.

+ 7 - 0
components/idf_test/include/esp32p4/idf_performance_target.h

@@ -3,3 +3,10 @@
  *
  * SPDX-License-Identifier: Apache-2.0
  */
+
+//TODO: IDF-8313 update after chips back and PLL setup
+#define IDF_PERFORMANCE_MAX_SPI_CLK_FREQ                                        10*1000*1000
+#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING                            1000
+#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING                               1000
+#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA                     1000
+#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA                        1000

+ 9 - 17
components/soc/esp32p4/include/soc/Kconfig.soc_caps.in

@@ -71,6 +71,10 @@ config SOC_I2S_SUPPORTED
     bool
     default y
 
+config SOC_GPSPI_SUPPORTED
+    bool
+    default y
+
 config SOC_I2C_SUPPORTED
     bool
     default y
@@ -801,25 +805,21 @@ config SOC_SDM_CLK_SUPPORT_XTAL
 
 config SOC_SPI_PERIPH_NUM
     int
-    default 2
+    default 3
 
 config SOC_SPI_MAX_CS_NUM
     int
     default 6
 
-config SOC_MEMSPI_IS_INDEPENDENT
-    bool
-    default y
-
 config SOC_SPI_MAXIMUM_BUFFER_SIZE
     int
     default 64
 
-config SOC_SPI_SUPPORT_DDRCLK
+config SOC_SPI_SLAVE_SUPPORT_SEG_TRANS
     bool
     default y
 
-config SOC_SPI_SLAVE_SUPPORT_SEG_TRANS
+config SOC_SPI_SUPPORT_DDRCLK
     bool
     default y
 
@@ -827,23 +827,15 @@ config SOC_SPI_SUPPORT_CD_SIG
     bool
     default y
 
-config SOC_SPI_SUPPORT_CONTINUOUS_TRANS
+config SOC_SPI_SUPPORT_OCT
     bool
     default y
 
-config SOC_SPI_SUPPORT_SLAVE_HD_VER2
-    bool
-    default n
-
 config SOC_SPI_SUPPORT_CLK_XTAL
     bool
     default y
 
-config SOC_SPI_SUPPORT_CLK_PLL_F80M
-    bool
-    default y
-
-config SOC_SPI_SUPPORT_CLK_RC_FAST
+config SOC_MEMSPI_IS_INDEPENDENT
     bool
     default y
 

+ 8 - 4
components/soc/esp32p4/include/soc/clk_tree_defs.h

@@ -370,16 +370,20 @@ typedef enum {
 /**
  * @brief Array initializer for all supported clock sources of SPI
  */
-#define SOC_SPI_CLKS {SOC_MOD_CLK_PLL_F80M, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
+#define SOC_SPI_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_SPLL}
 
 /**
  * @brief Type of SPI clock source.
  */
 typedef enum {
-    SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F80M,     /*!< Select PLL_80M as SPI source clock */
-    SPI_CLK_SRC_PLL_F80M = SOC_MOD_CLK_PLL_F80M,    /*!< Select PLL_80M as SPI source clock */
     SPI_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL,            /*!< Select XTAL as SPI source clock */
-    SPI_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST,      /*!< Select RC_FAST as SPI source clock */
+#if SOC_CLK_TREE_SUPPORTED
+    SPI_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST,
+    SPI_CLK_SRC_SPLL_480 = SOC_MOD_CLK_SPLL,
+    SPI_CLK_SRC_DEFAULT = SPI_CLK_SRC_SPLL_480,     /*!< Select SPLL_480M as SPI source clock */
+#else
+    SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL,         /*!< Select XTAL as SPI source clock */
+#endif
 } soc_periph_spi_clk_src_t;
 
 /////////////////////////////////////////////////PSRAM////////////////////////////////////////////////////////////////////

+ 1 - 0
components/soc/esp32p4/include/soc/ext_mem_defs.h

@@ -57,6 +57,7 @@ extern "C" {
 #define SOC_MMU_FLASH_SENSITIVE             BIT(13)
 #define SOC_MMU_PSRAM_SENSITIVE             BIT(12)
 
+#define SOC_NON_CACHEABLE_OFFSET            0x40000000
 
 /**
  * MMU entry valid bit mask for mapping value.

+ 13 - 13
components/soc/esp32p4/include/soc/soc_caps.h

@@ -52,7 +52,7 @@
 #define SOC_I2S_SUPPORTED               1
 // #define SOC_RMT_SUPPORTED               1  //TODO: IDF-7476
 // #define SOC_SDM_SUPPORTED               1  //TODO: IDF-7551
-// #define SOC_GPSPI_SUPPORTED             1  //TODO: IDF-7502, TODO: IDF-7503
+#define SOC_GPSPI_SUPPORTED             1
 // #define SOC_LEDC_SUPPORTED              1  //TODO: IDF-6510
 #define SOC_I2C_SUPPORTED               1  //TODO: IDF-6507, TODO: IDF-7491
 #define SOC_SYSTIMER_SUPPORTED          1
@@ -377,29 +377,29 @@
 #define SOC_SDM_CLK_SUPPORT_PLL_F80M 1
 #define SOC_SDM_CLK_SUPPORT_XTAL     1
 
-// TODO: IDF-5334 (Copy from esp32c3, need check)
 /*-------------------------- SPI CAPS ----------------------------------------*/
-#define SOC_SPI_PERIPH_NUM          2
-#define SOC_SPI_PERIPH_CS_NUM(i)    6
-#define SOC_SPI_MAX_CS_NUM          6
-
-#define SOC_MEMSPI_IS_INDEPENDENT 1
+#define SOC_SPI_PERIPH_NUM              3
+#define SOC_SPI_PERIPH_CS_NUM(i)        (((i)==0)? 2: (((i)==1)? 6: 3))
+#define SOC_SPI_MAX_CS_NUM              6
 #define SOC_SPI_MAXIMUM_BUFFER_SIZE     64
 
-#define SOC_SPI_SUPPORT_DDRCLK              1
+// #define SOC_SPI_SUPPORT_SLAVE_HD_VER2       1    //TODO: IDF-7505
 #define SOC_SPI_SLAVE_SUPPORT_SEG_TRANS     1
+#define SOC_SPI_SUPPORT_DDRCLK              1
 #define SOC_SPI_SUPPORT_CD_SIG              1
-#define SOC_SPI_SUPPORT_CONTINUOUS_TRANS    1
-#define SOC_SPI_SUPPORT_SLAVE_HD_VER2       0
+#define SOC_SPI_SUPPORT_OCT                 1
 #define SOC_SPI_SUPPORT_CLK_XTAL            1
-#define SOC_SPI_SUPPORT_CLK_PLL_F80M        1
-#define SOC_SPI_SUPPORT_CLK_RC_FAST         1
+// #define SOC_SPI_SUPPORT_CLK_RC_FAST         1    //bellow clks are waiting for clock tree
+// #define SOC_SPI_SUPPORT_CLK_SPLL_F480M      1    //super pll
+// #define SOC_SPI_SUPPORT_CLK_SDIO            1    //sdio pll
+// #define SOC_SPI_SUPPORT_CLK_APLL            1    //audio pll
 
 // Peripheral supports DIO, DOUT, QIO, or QOUT
 // host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2,
 #define SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(host_id)  ({(void)host_id; 1;})
 
-#define SOC_SPI_MAX_PRE_DIVIDER 16
+#define SOC_MEMSPI_IS_INDEPENDENT   1
+#define SOC_SPI_MAX_PRE_DIVIDER     16
 
 /*-------------------------- SPI MEM CAPS ---------------------------------------*/
 #define SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE                (1)

+ 24 - 0
components/soc/esp32p4/include/soc/spi_pins.h

@@ -5,3 +5,27 @@
  */
 
 #pragma once
+
+// Normal IOMUX pins
+#define SPI2_FUNC_NUM               3
+#define SPI2_IOMUX_PIN_NUM_HD       6
+#define SPI2_IOMUX_PIN_NUM_CS       7
+#define SPI2_IOMUX_PIN_NUM_MOSI     8
+#define SPI2_IOMUX_PIN_NUM_CLK      9
+#define SPI2_IOMUX_PIN_NUM_MISO     10
+#define SPI2_IOMUX_PIN_NUM_WP       11
+
+// When using Octal SPI, we make use of SPI2_FUNC_NUM_OCT to route them as follows.
+#define SPI2_FUNC_NUM_OCT           2
+#define SPI2_IOMUX_PIN_NUM_HD_OCT   32
+#define SPI2_IOMUX_PIN_NUM_CS_OCT   28
+#define SPI2_IOMUX_PIN_NUM_MOSI_OCT 29
+#define SPI2_IOMUX_PIN_NUM_CLK_OCT  30
+#define SPI2_IOMUX_PIN_NUM_MISO_OCT 31
+#define SPI2_IOMUX_PIN_NUM_WP_OCT   33
+#define SPI2_IOMUX_PIN_NUM_IO4_OCT  34
+#define SPI2_IOMUX_PIN_NUM_IO5_OCT  35
+#define SPI2_IOMUX_PIN_NUM_IO6_OCT  36
+#define SPI2_IOMUX_PIN_NUM_IO7_OCT  37
+
+//SPI3 have no iomux pins

+ 29 - 408
components/soc/esp32p4/include/soc/spi_struct.h

@@ -839,198 +839,8 @@ typedef union {
     uint32_t val;
 } spi_dout_mode_reg_t;
 
-
-/** Group: Interrupt registers */
-/** Type of dma_int_ena register
- *  SPI interrupt enable register
- */
-typedef union {
-    struct {
-        /** dma_infifo_full_err_int_ena : R/W; bitpos: [0]; default: 0;
-         *  The enable bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt.
-         */
-        uint32_t dma_infifo_full_err_int_ena:1;
-        /** dma_outfifo_empty_err_int_ena : R/W; bitpos: [1]; default: 0;
-         *  The enable bit for SPI_DMA_OUTFIFO_EMPTY_ERR_INT interrupt.
-         */
-        uint32_t dma_outfifo_empty_err_int_ena:1;
-        /** slv_ex_qpi_int_ena : R/W; bitpos: [2]; default: 0;
-         *  The enable bit for SPI slave Ex_QPI interrupt.
-         */
-        uint32_t slv_ex_qpi_int_ena:1;
-        /** slv_en_qpi_int_ena : R/W; bitpos: [3]; default: 0;
-         *  The enable bit for SPI slave En_QPI interrupt.
-         */
-        uint32_t slv_en_qpi_int_ena:1;
-        /** slv_cmd7_int_ena : R/W; bitpos: [4]; default: 0;
-         *  The enable bit for SPI slave CMD7 interrupt.
-         */
-        uint32_t slv_cmd7_int_ena:1;
-        /** slv_cmd8_int_ena : R/W; bitpos: [5]; default: 0;
-         *  The enable bit for SPI slave CMD8 interrupt.
-         */
-        uint32_t slv_cmd8_int_ena:1;
-        /** slv_cmd9_int_ena : R/W; bitpos: [6]; default: 0;
-         *  The enable bit for SPI slave CMD9 interrupt.
-         */
-        uint32_t slv_cmd9_int_ena:1;
-        /** slv_cmda_int_ena : R/W; bitpos: [7]; default: 0;
-         *  The enable bit for SPI slave CMDA interrupt.
-         */
-        uint32_t slv_cmda_int_ena:1;
-        /** slv_rd_dma_done_int_ena : R/W; bitpos: [8]; default: 0;
-         *  The enable bit for SPI_SLV_RD_DMA_DONE_INT interrupt.
-         */
-        uint32_t slv_rd_dma_done_int_ena:1;
-        /** slv_wr_dma_done_int_ena : R/W; bitpos: [9]; default: 0;
-         *  The enable bit for SPI_SLV_WR_DMA_DONE_INT interrupt.
-         */
-        uint32_t slv_wr_dma_done_int_ena:1;
-        /** slv_rd_buf_done_int_ena : R/W; bitpos: [10]; default: 0;
-         *  The enable bit for SPI_SLV_RD_BUF_DONE_INT interrupt.
-         */
-        uint32_t slv_rd_buf_done_int_ena:1;
-        /** slv_wr_buf_done_int_ena : R/W; bitpos: [11]; default: 0;
-         *  The enable bit for SPI_SLV_WR_BUF_DONE_INT interrupt.
-         */
-        uint32_t slv_wr_buf_done_int_ena:1;
-        /** trans_done_int_ena : R/W; bitpos: [12]; default: 0;
-         *  The enable bit for SPI_TRANS_DONE_INT interrupt.
-         */
-        uint32_t trans_done_int_ena:1;
-        /** dma_seg_trans_done_int_ena : R/W; bitpos: [13]; default: 0;
-         *  The enable bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt.
-         */
-        uint32_t dma_seg_trans_done_int_ena:1;
-        /** seg_magic_err_int_ena : R/W; bitpos: [14]; default: 0;
-         *  The enable bit for SPI_SEG_MAGIC_ERR_INT interrupt.
-         */
-        uint32_t seg_magic_err_int_ena:1;  //this field is only for GPSPI2
-        /** slv_buf_addr_err_int_ena : R/W; bitpos: [15]; default: 0;
-         *  The enable bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt.
-         */
-        uint32_t slv_buf_addr_err_int_ena:1;
-        /** slv_cmd_err_int_ena : R/W; bitpos: [16]; default: 0;
-         *  The enable bit for SPI_SLV_CMD_ERR_INT interrupt.
-         */
-        uint32_t slv_cmd_err_int_ena:1;
-        /** mst_rx_afifo_wfull_err_int_ena : R/W; bitpos: [17]; default: 0;
-         *  The enable bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt.
-         */
-        uint32_t mst_rx_afifo_wfull_err_int_ena:1;
-        /** mst_tx_afifo_rempty_err_int_ena : R/W; bitpos: [18]; default: 0;
-         *  The enable bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt.
-         */
-        uint32_t mst_tx_afifo_rempty_err_int_ena:1;
-        /** app2_int_ena : R/W; bitpos: [19]; default: 0;
-         *  The enable bit for SPI_APP2_INT interrupt.
-         */
-        uint32_t app2_int_ena:1;
-        /** app1_int_ena : R/W; bitpos: [20]; default: 0;
-         *  The enable bit for SPI_APP1_INT interrupt.
-         */
-        uint32_t app1_int_ena:1;
-        uint32_t reserved_21:11;
-    };
-    uint32_t val;
-} spi_dma_int_ena_reg_t;
-
-/** Type of dma_int_clr register
- *  SPI interrupt clear register
- */
-typedef union {
-    struct {
-        /** dma_infifo_full_err_int_clr : WT; bitpos: [0]; default: 0;
-         *  The clear bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt.
-         */
-        uint32_t dma_infifo_full_err_int_clr:1;
-        /** dma_outfifo_empty_err_int_clr : WT; bitpos: [1]; default: 0;
-         *  The clear bit for SPI_DMA_OUTFIFO_EMPTY_ERR_INT interrupt.
-         */
-        uint32_t dma_outfifo_empty_err_int_clr:1;
-        /** slv_ex_qpi_int_clr : WT; bitpos: [2]; default: 0;
-         *  The clear bit for SPI slave Ex_QPI interrupt.
-         */
-        uint32_t slv_ex_qpi_int_clr:1;
-        /** slv_en_qpi_int_clr : WT; bitpos: [3]; default: 0;
-         *  The clear bit for SPI slave En_QPI interrupt.
-         */
-        uint32_t slv_en_qpi_int_clr:1;
-        /** slv_cmd7_int_clr : WT; bitpos: [4]; default: 0;
-         *  The clear bit for SPI slave CMD7 interrupt.
-         */
-        uint32_t slv_cmd7_int_clr:1;
-        /** slv_cmd8_int_clr : WT; bitpos: [5]; default: 0;
-         *  The clear bit for SPI slave CMD8 interrupt.
-         */
-        uint32_t slv_cmd8_int_clr:1;
-        /** slv_cmd9_int_clr : WT; bitpos: [6]; default: 0;
-         *  The clear bit for SPI slave CMD9 interrupt.
-         */
-        uint32_t slv_cmd9_int_clr:1;
-        /** slv_cmda_int_clr : WT; bitpos: [7]; default: 0;
-         *  The clear bit for SPI slave CMDA interrupt.
-         */
-        uint32_t slv_cmda_int_clr:1;
-        /** slv_rd_dma_done_int_clr : WT; bitpos: [8]; default: 0;
-         *  The clear bit for SPI_SLV_RD_DMA_DONE_INT interrupt.
-         */
-        uint32_t slv_rd_dma_done_int_clr:1;
-        /** slv_wr_dma_done_int_clr : WT; bitpos: [9]; default: 0;
-         *  The clear bit for SPI_SLV_WR_DMA_DONE_INT interrupt.
-         */
-        uint32_t slv_wr_dma_done_int_clr:1;
-        /** slv_rd_buf_done_int_clr : WT; bitpos: [10]; default: 0;
-         *  The clear bit for SPI_SLV_RD_BUF_DONE_INT interrupt.
-         */
-        uint32_t slv_rd_buf_done_int_clr:1;
-        /** slv_wr_buf_done_int_clr : WT; bitpos: [11]; default: 0;
-         *  The clear bit for SPI_SLV_WR_BUF_DONE_INT interrupt.
-         */
-        uint32_t slv_wr_buf_done_int_clr:1;
-        /** trans_done_int_clr : WT; bitpos: [12]; default: 0;
-         *  The clear bit for SPI_TRANS_DONE_INT interrupt.
-         */
-        uint32_t trans_done_int_clr:1;
-        /** dma_seg_trans_done_int_clr : WT; bitpos: [13]; default: 0;
-         *  The clear bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt.
-         */
-        uint32_t dma_seg_trans_done_int_clr:1;
-        /** seg_magic_err_int_clr : WT; bitpos: [14]; default: 0;
-         *  The clear bit for SPI_SEG_MAGIC_ERR_INT interrupt.
-         */
-        uint32_t seg_magic_err_int_clr:1;  //this field is only for GPSPI2
-        /** slv_buf_addr_err_int_clr : WT; bitpos: [15]; default: 0;
-         *  The clear bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt.
-         */
-        uint32_t slv_buf_addr_err_int_clr:1;
-        /** slv_cmd_err_int_clr : WT; bitpos: [16]; default: 0;
-         *  The clear bit for SPI_SLV_CMD_ERR_INT interrupt.
-         */
-        uint32_t slv_cmd_err_int_clr:1;
-        /** mst_rx_afifo_wfull_err_int_clr : WT; bitpos: [17]; default: 0;
-         *  The clear bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt.
-         */
-        uint32_t mst_rx_afifo_wfull_err_int_clr:1;
-        /** mst_tx_afifo_rempty_err_int_clr : WT; bitpos: [18]; default: 0;
-         *  The clear bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt.
-         */
-        uint32_t mst_tx_afifo_rempty_err_int_clr:1;
-        /** app2_int_clr : WT; bitpos: [19]; default: 0;
-         *  The clear bit for SPI_APP2_INT interrupt.
-         */
-        uint32_t app2_int_clr:1;
-        /** app1_int_clr : WT; bitpos: [20]; default: 0;
-         *  The clear bit for SPI_APP1_INT interrupt.
-         */
-        uint32_t app1_int_clr:1;
-        uint32_t reserved_21:11;
-    };
-    uint32_t val;
-} spi_dma_int_clr_reg_t;
-
-/** Type of dma_int_raw register
- *  SPI interrupt raw register
+/** Type of dma_int register
+ *  SPI interrupt raw/ena/clr/sta/set register
  */
 typedef union {
     struct {
@@ -1038,301 +848,112 @@ typedef union {
          *  1: The current data rate of DMA Rx is smaller than that of SPI, which will lose the
          *  receive data.  0: Others.
          */
-        uint32_t dma_infifo_full_err_int_raw:1;
+        uint32_t dma_infifo_full_err_int:1;
         /** dma_outfifo_empty_err_int_raw : R/WTC/SS; bitpos: [1]; default: 0;
          *  1: The current data rate of DMA TX is smaller than that of SPI. SPI will stop in
          *  master mode and send out all 0 in slave mode.  0: Others.
          */
-        uint32_t dma_outfifo_empty_err_int_raw:1;
+        uint32_t dma_outfifo_empty_err_int:1;
         /** slv_ex_qpi_int_raw : R/WTC/SS; bitpos: [2]; default: 0;
          *  The raw bit for SPI slave Ex_QPI interrupt. 1: SPI slave mode Ex_QPI transmission
          *  is ended. 0: Others.
          */
-        uint32_t slv_ex_qpi_int_raw:1;
+        uint32_t slv_ex_qpi_int:1;
         /** slv_en_qpi_int_raw : R/WTC/SS; bitpos: [3]; default: 0;
          *  The raw bit for SPI slave En_QPI interrupt. 1: SPI slave mode En_QPI transmission
          *  is ended. 0: Others.
          */
-        uint32_t slv_en_qpi_int_raw:1;
+        uint32_t slv_en_qpi_int:1;
         /** slv_cmd7_int_raw : R/WTC/SS; bitpos: [4]; default: 0;
          *  The raw bit for SPI slave CMD7 interrupt. 1: SPI slave mode CMD7 transmission is
          *  ended. 0: Others.
          */
-        uint32_t slv_cmd7_int_raw:1;
+        uint32_t slv_cmd7_int:1;
         /** slv_cmd8_int_raw : R/WTC/SS; bitpos: [5]; default: 0;
          *  The raw bit for SPI slave CMD8 interrupt. 1: SPI slave mode CMD8 transmission is
          *  ended. 0: Others.
          */
-        uint32_t slv_cmd8_int_raw:1;
+        uint32_t slv_cmd8_int:1;
         /** slv_cmd9_int_raw : R/WTC/SS; bitpos: [6]; default: 0;
          *  The raw bit for SPI slave CMD9 interrupt. 1: SPI slave mode CMD9 transmission is
          *  ended. 0: Others.
          */
-        uint32_t slv_cmd9_int_raw:1;
+        uint32_t slv_cmd9_int:1;
         /** slv_cmda_int_raw : R/WTC/SS; bitpos: [7]; default: 0;
          *  The raw bit for SPI slave CMDA interrupt. 1: SPI slave mode CMDA transmission is
          *  ended. 0: Others.
          */
-        uint32_t slv_cmda_int_raw:1;
+        uint32_t slv_cmda_int:1;
         /** slv_rd_dma_done_int_raw : R/WTC/SS; bitpos: [8]; default: 0;
          *  The raw bit for SPI_SLV_RD_DMA_DONE_INT interrupt. 1: SPI slave mode Rd_DMA
          *  transmission is ended. 0: Others.
          */
-        uint32_t slv_rd_dma_done_int_raw:1;
+        uint32_t slv_rd_dma_done_int:1;
         /** slv_wr_dma_done_int_raw : R/WTC/SS; bitpos: [9]; default: 0;
          *  The raw bit for SPI_SLV_WR_DMA_DONE_INT interrupt. 1: SPI slave mode Wr_DMA
          *  transmission is ended. 0: Others.
          */
-        uint32_t slv_wr_dma_done_int_raw:1;
+        uint32_t slv_wr_dma_done_int:1;
         /** slv_rd_buf_done_int_raw : R/WTC/SS; bitpos: [10]; default: 0;
          *  The raw bit for SPI_SLV_RD_BUF_DONE_INT interrupt. 1: SPI slave mode Rd_BUF
          *  transmission is ended. 0: Others.
          */
-        uint32_t slv_rd_buf_done_int_raw:1;
+        uint32_t slv_rd_buf_done_int:1;
         /** slv_wr_buf_done_int_raw : R/WTC/SS; bitpos: [11]; default: 0;
          *  The raw bit for SPI_SLV_WR_BUF_DONE_INT interrupt. 1: SPI slave mode Wr_BUF
          *  transmission is ended. 0: Others.
          */
-        uint32_t slv_wr_buf_done_int_raw:1;
+        uint32_t slv_wr_buf_done_int:1;
         /** trans_done_int_raw : R/WTC/SS; bitpos: [12]; default: 0;
          *  The raw bit for SPI_TRANS_DONE_INT interrupt. 1: SPI master mode transmission is
          *  ended. 0: others.
          */
-        uint32_t trans_done_int_raw:1;
+        uint32_t trans_done_int:1;
         /** dma_seg_trans_done_int_raw : R/WTC/SS; bitpos: [13]; default: 0;
          *  The raw bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt. 1:  spi master DMA
          *  full-duplex/half-duplex seg-conf-trans ends or slave half-duplex seg-trans ends.
          *  And data has been pushed to corresponding memory.  0:  seg-conf-trans or seg-trans
          *  is not ended or not occurred.
          */
-        uint32_t dma_seg_trans_done_int_raw:1;
+        uint32_t dma_seg_trans_done_int:1;
         /** seg_magic_err_int_raw : R/WTC/SS; bitpos: [14]; default: 0;
          *  The raw bit for SPI_SEG_MAGIC_ERR_INT interrupt. 1: The magic value in CONF buffer
          *  is error in the DMA seg-conf-trans. 0: others.
          */
-        uint32_t seg_magic_err_int_raw:1;  //this field is only for GPSPI2
+        uint32_t seg_magic_err_int_raw:1;  //this field is only forPI2
         /** slv_buf_addr_err_int_raw : R/WTC/SS; bitpos: [15]; default: 0;
          *  The raw bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt. 1: The accessing data address
          *  of the current SPI slave mode CPU controlled FD, Wr_BUF or Rd_BUF transmission is
          *  bigger than 63. 0: Others.
          */
-        uint32_t slv_buf_addr_err_int_raw:1;
+        uint32_t slv_buf_addr_err_int:1;
         /** slv_cmd_err_int_raw : R/WTC/SS; bitpos: [16]; default: 0;
          *  The raw bit for SPI_SLV_CMD_ERR_INT interrupt. 1: The slave command value in the
          *  current SPI slave HD mode transmission is not supported. 0: Others.
          */
-        uint32_t slv_cmd_err_int_raw:1;
+        uint32_t slv_cmd_err_int:1;
         /** mst_rx_afifo_wfull_err_int_raw : R/WTC/SS; bitpos: [17]; default: 0;
          *  The raw bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt. 1: There is a RX AFIFO
          *  write-full error when SPI inputs data in master mode. 0: Others.
          */
-        uint32_t mst_rx_afifo_wfull_err_int_raw:1;
+        uint32_t mst_rx_afifo_wfull_err_int:1;
         /** mst_tx_afifo_rempty_err_int_raw : R/WTC/SS; bitpos: [18]; default: 0;
          *  The raw bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt. 1: There is a TX BUF
          *  AFIFO read-empty error when SPI outputs data in master mode. 0: Others.
          */
-        uint32_t mst_tx_afifo_rempty_err_int_raw:1;
+        uint32_t mst_tx_afifo_rempty_err_int:1;
         /** app2_int_raw : R/WTC/SS; bitpos: [19]; default: 0;
          *  The raw bit for SPI_APP2_INT interrupt. The value is only controlled by software.
          */
-        uint32_t app2_int_raw:1;
+        uint32_t app2_int:1;
         /** app1_int_raw : R/WTC/SS; bitpos: [20]; default: 0;
          *  The raw bit for SPI_APP1_INT interrupt. The value is only controlled by software.
          */
-        uint32_t app1_int_raw:1;
+        uint32_t app1_int:1;
         uint32_t reserved_21:11;
     };
     uint32_t val;
-} spi_dma_int_raw_reg_t;
-
-/** Type of dma_int_st register
- *  SPI interrupt status register
- */
-typedef union {
-    struct {
-        /** dma_infifo_full_err_int_st : RO; bitpos: [0]; default: 0;
-         *  The status bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt.
-         */
-        uint32_t dma_infifo_full_err_int_st:1;
-        /** dma_outfifo_empty_err_int_st : RO; bitpos: [1]; default: 0;
-         *  The status bit for SPI_DMA_OUTFIFO_EMPTY_ERR_INT interrupt.
-         */
-        uint32_t dma_outfifo_empty_err_int_st:1;
-        /** slv_ex_qpi_int_st : RO; bitpos: [2]; default: 0;
-         *  The status bit for SPI slave Ex_QPI interrupt.
-         */
-        uint32_t slv_ex_qpi_int_st:1;
-        /** slv_en_qpi_int_st : RO; bitpos: [3]; default: 0;
-         *  The status bit for SPI slave En_QPI interrupt.
-         */
-        uint32_t slv_en_qpi_int_st:1;
-        /** slv_cmd7_int_st : RO; bitpos: [4]; default: 0;
-         *  The status bit for SPI slave CMD7 interrupt.
-         */
-        uint32_t slv_cmd7_int_st:1;
-        /** slv_cmd8_int_st : RO; bitpos: [5]; default: 0;
-         *  The status bit for SPI slave CMD8 interrupt.
-         */
-        uint32_t slv_cmd8_int_st:1;
-        /** slv_cmd9_int_st : RO; bitpos: [6]; default: 0;
-         *  The status bit for SPI slave CMD9 interrupt.
-         */
-        uint32_t slv_cmd9_int_st:1;
-        /** slv_cmda_int_st : RO; bitpos: [7]; default: 0;
-         *  The status bit for SPI slave CMDA interrupt.
-         */
-        uint32_t slv_cmda_int_st:1;
-        /** slv_rd_dma_done_int_st : RO; bitpos: [8]; default: 0;
-         *  The status bit for SPI_SLV_RD_DMA_DONE_INT interrupt.
-         */
-        uint32_t slv_rd_dma_done_int_st:1;
-        /** slv_wr_dma_done_int_st : RO; bitpos: [9]; default: 0;
-         *  The status bit for SPI_SLV_WR_DMA_DONE_INT interrupt.
-         */
-        uint32_t slv_wr_dma_done_int_st:1;
-        /** slv_rd_buf_done_int_st : RO; bitpos: [10]; default: 0;
-         *  The status bit for SPI_SLV_RD_BUF_DONE_INT interrupt.
-         */
-        uint32_t slv_rd_buf_done_int_st:1;
-        /** slv_wr_buf_done_int_st : RO; bitpos: [11]; default: 0;
-         *  The status bit for SPI_SLV_WR_BUF_DONE_INT interrupt.
-         */
-        uint32_t slv_wr_buf_done_int_st:1;
-        /** trans_done_int_st : RO; bitpos: [12]; default: 0;
-         *  The status bit for SPI_TRANS_DONE_INT interrupt.
-         */
-        uint32_t trans_done_int_st:1;
-        /** dma_seg_trans_done_int_st : RO; bitpos: [13]; default: 0;
-         *  The status bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt.
-         */
-        uint32_t dma_seg_trans_done_int_st:1;
-        /** seg_magic_err_int_st : RO; bitpos: [14]; default: 0;
-         *  The status bit for SPI_SEG_MAGIC_ERR_INT interrupt.
-         */
-        uint32_t seg_magic_err_int_st:1;  //this field is only for GPSPI2
-        /** slv_buf_addr_err_int_st : RO; bitpos: [15]; default: 0;
-         *  The status bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt.
-         */
-        uint32_t slv_buf_addr_err_int_st:1;
-        /** slv_cmd_err_int_st : RO; bitpos: [16]; default: 0;
-         *  The status bit for SPI_SLV_CMD_ERR_INT interrupt.
-         */
-        uint32_t slv_cmd_err_int_st:1;
-        /** mst_rx_afifo_wfull_err_int_st : RO; bitpos: [17]; default: 0;
-         *  The status bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt.
-         */
-        uint32_t mst_rx_afifo_wfull_err_int_st:1;
-        /** mst_tx_afifo_rempty_err_int_st : RO; bitpos: [18]; default: 0;
-         *  The status bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt.
-         */
-        uint32_t mst_tx_afifo_rempty_err_int_st:1;
-        /** app2_int_st : RO; bitpos: [19]; default: 0;
-         *  The status bit for SPI_APP2_INT interrupt.
-         */
-        uint32_t app2_int_st:1;
-        /** app1_int_st : RO; bitpos: [20]; default: 0;
-         *  The status bit for SPI_APP1_INT interrupt.
-         */
-        uint32_t app1_int_st:1;
-        uint32_t reserved_21:11;
-    };
-    uint32_t val;
-} spi_dma_int_st_reg_t;
-
-/** Type of dma_int_set register
- *  SPI interrupt software set register
- */
-typedef union {
-    struct {
-        /** dma_infifo_full_err_int_set : WT; bitpos: [0]; default: 0;
-         *  The software set bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt.
-         */
-        uint32_t dma_infifo_full_err_int_set:1;
-        /** dma_outfifo_empty_err_int_set : WT; bitpos: [1]; default: 0;
-         *  The software set bit for SPI_DMA_OUTFIFO_EMPTY_ERR_INT interrupt.
-         */
-        uint32_t dma_outfifo_empty_err_int_set:1;
-        /** slv_ex_qpi_int_set : WT; bitpos: [2]; default: 0;
-         *  The software set bit for SPI slave Ex_QPI interrupt.
-         */
-        uint32_t slv_ex_qpi_int_set:1;
-        /** slv_en_qpi_int_set : WT; bitpos: [3]; default: 0;
-         *  The software set bit for SPI slave En_QPI interrupt.
-         */
-        uint32_t slv_en_qpi_int_set:1;
-        /** slv_cmd7_int_set : WT; bitpos: [4]; default: 0;
-         *  The software set bit for SPI slave CMD7 interrupt.
-         */
-        uint32_t slv_cmd7_int_set:1;
-        /** slv_cmd8_int_set : WT; bitpos: [5]; default: 0;
-         *  The software set bit for SPI slave CMD8 interrupt.
-         */
-        uint32_t slv_cmd8_int_set:1;
-        /** slv_cmd9_int_set : WT; bitpos: [6]; default: 0;
-         *  The software set bit for SPI slave CMD9 interrupt.
-         */
-        uint32_t slv_cmd9_int_set:1;
-        /** slv_cmda_int_set : WT; bitpos: [7]; default: 0;
-         *  The software set bit for SPI slave CMDA interrupt.
-         */
-        uint32_t slv_cmda_int_set:1;
-        /** slv_rd_dma_done_int_set : WT; bitpos: [8]; default: 0;
-         *  The software set bit for SPI_SLV_RD_DMA_DONE_INT interrupt.
-         */
-        uint32_t slv_rd_dma_done_int_set:1;
-        /** slv_wr_dma_done_int_set : WT; bitpos: [9]; default: 0;
-         *  The software set bit for SPI_SLV_WR_DMA_DONE_INT interrupt.
-         */
-        uint32_t slv_wr_dma_done_int_set:1;
-        /** slv_rd_buf_done_int_set : WT; bitpos: [10]; default: 0;
-         *  The software set bit for SPI_SLV_RD_BUF_DONE_INT interrupt.
-         */
-        uint32_t slv_rd_buf_done_int_set:1;
-        /** slv_wr_buf_done_int_set : WT; bitpos: [11]; default: 0;
-         *  The software set bit for SPI_SLV_WR_BUF_DONE_INT interrupt.
-         */
-        uint32_t slv_wr_buf_done_int_set:1;
-        /** trans_done_int_set : WT; bitpos: [12]; default: 0;
-         *  The software set bit for SPI_TRANS_DONE_INT interrupt.
-         */
-        uint32_t trans_done_int_set:1;
-        /** dma_seg_trans_done_int_set : WT; bitpos: [13]; default: 0;
-         *  The software set bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt.
-         */
-        uint32_t dma_seg_trans_done_int_set:1;
-        /** seg_magic_err_int_set : WT; bitpos: [14]; default: 0;
-         *  The software set bit for SPI_SEG_MAGIC_ERR_INT interrupt.
-         */
-        uint32_t seg_magic_err_int_set:1;  //this field is only for GPSPI2
-        /** slv_buf_addr_err_int_set : WT; bitpos: [15]; default: 0;
-         *  The software set bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt.
-         */
-        uint32_t slv_buf_addr_err_int_set:1;
-        /** slv_cmd_err_int_set : WT; bitpos: [16]; default: 0;
-         *  The software set bit for SPI_SLV_CMD_ERR_INT interrupt.
-         */
-        uint32_t slv_cmd_err_int_set:1;
-        /** mst_rx_afifo_wfull_err_int_set : WT; bitpos: [17]; default: 0;
-         *  The software set bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt.
-         */
-        uint32_t mst_rx_afifo_wfull_err_int_set:1;
-        /** mst_tx_afifo_rempty_err_int_set : WT; bitpos: [18]; default: 0;
-         *  The software set bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt.
-         */
-        uint32_t mst_tx_afifo_rempty_err_int_set:1;
-        /** app2_int_set : WT; bitpos: [19]; default: 0;
-         *  The software set bit for SPI_APP2_INT interrupt.
-         */
-        uint32_t app2_int_set:1;
-        /** app1_int_set : WT; bitpos: [20]; default: 0;
-         *  The software set bit for SPI_APP1_INT interrupt.
-         */
-        uint32_t app1_int_set:1;
-        uint32_t reserved_21:11;
-    };
-    uint32_t val;
-} spi_dma_int_set_reg_t;
-
+} spi_dma_int_reg_t;
 
 /** Type of wn register
  *  SPI CPU-controlled buffer
@@ -1378,11 +999,11 @@ typedef struct {
     volatile spi_din_num_reg_t din_num;
     volatile spi_dout_mode_reg_t dout_mode;
     volatile spi_dma_conf_reg_t dma_conf;
-    volatile spi_dma_int_ena_reg_t dma_int_ena;
-    volatile spi_dma_int_clr_reg_t dma_int_clr;
-    volatile spi_dma_int_raw_reg_t dma_int_raw;
-    volatile spi_dma_int_st_reg_t dma_int_st;
-    volatile spi_dma_int_set_reg_t dma_int_set;
+    volatile spi_dma_int_reg_t dma_int_ena;
+    volatile spi_dma_int_reg_t dma_int_clr;
+    volatile spi_dma_int_reg_t dma_int_raw;
+    volatile spi_dma_int_reg_t dma_int_sta;
+    volatile spi_dma_int_reg_t dma_int_set;
     uint32_t reserved_048[20];
     volatile spi_wn_reg_t data_buf[16];
     uint32_t reserved_0d8[2];

+ 84 - 1
components/soc/esp32p4/spi_periph.c

@@ -11,5 +11,88 @@
  Bunch of constants for every SPI peripheral: GPIO signals, irqs, hw addr of registers etc
 */
 const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = {
-
+    {
+        // MSPI on P4 has dedicated iomux pins
+        .spiclk_out = -1,
+        .spiclk_in = -1,
+        .spid_out = -1,
+        .spiq_out = -1,
+        .spiwp_out = -1,
+        .spihd_out = -1,
+        .spid_in = -1,
+        .spiq_in = -1,
+        .spiwp_in = -1,
+        .spihd_in = -1,
+        .spics_out = {-1},
+        .spics_in = -1,
+        .spiclk_iomux_pin = -1,
+        .spid_iomux_pin = -1,
+        .spiq_iomux_pin = -1,
+        .spiwp_iomux_pin = -1,
+        .spihd_iomux_pin = -1,
+        .spics0_iomux_pin = -1,
+        .irq = -1,
+        .irq_dma = -1,
+        .module = -1,
+        .hw = NULL,
+        .func = -1,
+    }, {
+        .spiclk_out = SPI2_CK_PAD_OUT_IDX,
+        .spiclk_in = SPI2_CK_PAD_IN_IDX,
+        .spid_out = SPI2_D_PAD_OUT_IDX,
+        .spiq_out = SPI2_Q_PAD_OUT_IDX,
+        .spiwp_out = SPI2_WP_PAD_OUT_IDX,
+        .spihd_out = SPI2_HOLD_PAD_OUT_IDX,
+        .spid4_out = SPI2_IO4_PAD_OUT_IDX,
+        .spid5_out = SPI2_IO5_PAD_OUT_IDX,
+        .spid6_out = SPI2_IO6_PAD_OUT_IDX,
+        .spid7_out = SPI2_IO7_PAD_OUT_IDX,
+        .spid_in = SPI2_D_PAD_IN_IDX,
+        .spiq_in = SPI2_Q_PAD_IN_IDX,
+        .spiwp_in = SPI2_WP_PAD_IN_IDX,
+        .spihd_in = SPI2_HOLD_PAD_IN_IDX,
+        .spid4_in = SPI2_IO4_PAD_IN_IDX,
+        .spid5_in = SPI2_IO5_PAD_IN_IDX,
+        .spid6_in = SPI2_IO6_PAD_IN_IDX,
+        .spid7_in = SPI2_IO7_PAD_IN_IDX,
+        .spics_out = {SPI2_CS_PAD_OUT_IDX, SPI2_CS1_PAD_OUT_IDX, SPI2_CS2_PAD_OUT_IDX, SPI2_CS3_PAD_OUT_IDX, SPI2_CS4_PAD_OUT_IDX, SPI2_CS5_PAD_OUT_IDX},
+        .spics_in = SPI2_CS_PAD_IN_IDX,
+        .spiclk_iomux_pin = SPI2_IOMUX_PIN_NUM_CLK,
+        .spid_iomux_pin = SPI2_IOMUX_PIN_NUM_MOSI,
+        .spiq_iomux_pin = SPI2_IOMUX_PIN_NUM_MISO,
+        .spiwp_iomux_pin = SPI2_IOMUX_PIN_NUM_WP,
+        .spihd_iomux_pin = SPI2_IOMUX_PIN_NUM_HD,
+        .spics0_iomux_pin = SPI2_IOMUX_PIN_NUM_CS,
+        .irq = ETS_SPI2_INTR_SOURCE,
+        .irq_dma = -1,
+        .module = PERIPH_GPSPI2_MODULE,
+        .hw = &GPSPI2,
+        .func = SPI2_FUNC_NUM,
+    }, {
+        .spiclk_out = SPI3_CK_PAD_OUT_IDX,
+        .spiclk_in = SPI3_CK_PAD_IN_IDX,
+        .spid_out = SPI3_D_PAD_OUT_IDX,
+        .spiq_out = SPI3_QO_PAD_OUT_IDX,
+        //SPI3 doesn't have wp and hd signals
+        .spiwp_out = SPI3_WP_PAD_OUT_IDX,
+        .spihd_out = SPI3_HOLD_PAD_OUT_IDX,
+        .spid_in = SPI3_D_PAD_IN_IDX,
+        .spiq_in = SPI3_Q_PAD_IN_IDX,
+        .spiwp_in = SPI3_WP_PAD_IN_IDX,
+        .spihd_in = SPI3_HOLD_PAD_IN_IDX,
+        .spics_out = {SPI3_CS_PAD_OUT_IDX, SPI3_CS1_PAD_OUT_IDX, SPI3_CS2_PAD_OUT_IDX},
+        .spics_in = SPI3_CS_PAD_IN_IDX,
+        //SPI3 doesn't have iomux pins
+        .spiclk_iomux_pin = -1,
+        .spid_iomux_pin = -1,
+        .spiq_iomux_pin = -1,
+        .spiwp_iomux_pin = -1,
+        .spihd_iomux_pin = -1,
+        .spics0_iomux_pin = -1,
+        .irq = ETS_SPI3_INTR_SOURCE,
+        .irq_dma = -1,
+        .module = PERIPH_GPSPI3_MODULE,
+        .hw = &GPSPI3,
+        .func = -1,
+    }
 };

+ 2 - 2
examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/README.md

@@ -1,5 +1,5 @@
-| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S3 |
-| ----------------- | -------- | -------- | -------- | -------- |
+| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 |
+| ----------------- | -------- | -------- | -------- | -------- | -------- |
 
 # I2S TDM Example -- ES7210 4-Ch ADC Codec