14
14
LOG_MODULE_REGISTER (esp32_spi , CONFIG_SPI_LOG_LEVEL );
15
15
16
16
#include <soc.h>
17
+ #include <soc/soc_memory_types.h>
17
18
#include <zephyr/drivers/spi.h>
18
19
#ifndef CONFIG_SOC_ESP32C3
19
20
#include <zephyr/drivers/interrupt_controller/intc_esp32.h>
@@ -55,19 +56,48 @@ static inline void spi_esp32_complete(const struct device *dev,
55
56
static int IRAM_ATTR spi_esp32_transfer (const struct device * dev )
56
57
{
57
58
struct spi_esp32_data * data = dev -> data ;
59
+ const struct spi_esp32_config * cfg = dev -> config ;
58
60
struct spi_context * ctx = & data -> ctx ;
59
61
spi_hal_context_t * hal = & data -> hal ;
60
62
spi_hal_dev_config_t * hal_dev = & data -> dev_config ;
61
63
spi_hal_trans_config_t * hal_trans = & data -> trans_config ;
62
64
size_t chunk_len = spi_context_max_continuous_chunk (& data -> ctx );
63
65
chunk_len = MIN (chunk_len , SOC_SPI_MAXIMUM_BUFFER_SIZE );
66
+ size_t bit_len = chunk_len << 3 ;
67
+ uint8_t * rx_temp = NULL ;
68
+ uint8_t * tx_temp = NULL ;
69
+
70
+ if (cfg -> dma_enabled ) {
71
+ /* bit_len needs to be at least one byte long when using DMA */
72
+ bit_len = !bit_len ? 8 : bit_len ;
73
+ if (ctx -> tx_buf && !esp_ptr_dma_capable ((uint32_t * )& ctx -> tx_buf [0 ])) {
74
+ tx_temp = k_malloc (ctx -> tx_len );
75
+ if (!tx_temp ) {
76
+ LOG_ERR ("Error allocating temp buffer Tx" );
77
+ return - ENOMEM ;
78
+ }
79
+ memcpy (tx_temp , & ctx -> tx_buf [0 ], ctx -> tx_len );
80
+ }
81
+ if (ctx -> rx_buf && (!esp_ptr_dma_capable ((uint32_t * )& ctx -> rx_buf [0 ]) ||
82
+ ((int )& ctx -> rx_buf [0 ] % 4 != 0 ))) {
83
+ /* The rx buffer need to be length of
84
+ * multiples of 32 bits to avoid heap
85
+ * corruption.
86
+ */
87
+ rx_temp = k_calloc (((ctx -> rx_len << 3 ) + 31 ) / 8 , sizeof (uint8_t ));
88
+ if (!rx_temp ) {
89
+ LOG_ERR ("Error allocating temp buffer Rx" );
90
+ return - ENOMEM ;
91
+ }
92
+ }
93
+ }
64
94
65
95
/* clean up and prepare SPI hal */
66
- memset ((uint32_t * ) hal -> hw -> data_buf , 0 , sizeof (hal -> hw -> data_buf ));
67
- hal_trans -> send_buffer = (uint8_t * ) ctx -> tx_buf ;
68
- hal_trans -> rcv_buffer = ctx -> rx_buf ;
69
- hal_trans -> tx_bitlen = chunk_len << 3 ;
70
- hal_trans -> rx_bitlen = chunk_len << 3 ;
96
+ memset ((uint32_t * )hal -> hw -> data_buf , 0 , sizeof (hal -> hw -> data_buf ));
97
+ hal_trans -> send_buffer = tx_temp ? tx_temp : (uint8_t * )ctx -> tx_buf ;
98
+ hal_trans -> rcv_buffer = rx_temp ? rx_temp : ctx -> rx_buf ;
99
+ hal_trans -> tx_bitlen = bit_len ;
100
+ hal_trans -> rx_bitlen = bit_len ;
71
101
72
102
/* configure SPI */
73
103
spi_hal_setup_trans (hal , hal_dev , hal_trans );
@@ -83,8 +113,21 @@ static int IRAM_ATTR spi_esp32_transfer(const struct device *dev)
83
113
84
114
/* read data */
85
115
spi_hal_fetch_result (hal );
116
+
117
+ if (rx_temp ) {
118
+ memcpy (& ctx -> rx_buf [0 ], rx_temp , chunk_len );
119
+ }
120
+
86
121
spi_context_update_rx (& data -> ctx , data -> dfs , chunk_len );
87
122
123
+ if (tx_temp ) {
124
+ k_free (tx_temp );
125
+ }
126
+
127
+ if (rx_temp ) {
128
+ k_free (rx_temp );
129
+ }
130
+
88
131
return 0 ;
89
132
}
90
133
@@ -103,6 +146,42 @@ static void IRAM_ATTR spi_esp32_isr(void *arg)
103
146
}
104
147
#endif
105
148
149
+ static int spi_esp32_init_dma (const struct device * dev )
150
+ {
151
+ const struct spi_esp32_config * cfg = dev -> config ;
152
+ struct spi_esp32_data * data = dev -> data ;
153
+
154
+ LOG_ERR ("DMA" );
155
+ if (clock_control_on (cfg -> clock_dev , (clock_control_subsys_t )cfg -> dma_clk_src )) {
156
+ LOG_ERR ("Could not enable DMA clock" );
157
+ return - EIO ;
158
+ }
159
+
160
+ #ifdef CONFIG_SOC_ESP32
161
+ /*Connect SPI and DMA*/
162
+ DPORT_SET_PERI_REG_BITS (DPORT_SPI_DMA_CHAN_SEL_REG , 3 , cfg -> dma_host + 1 ,
163
+ ((cfg -> dma_host + 1 ) * 2 ));
164
+ #endif /* CONFIG_SOC_ESP32 */
165
+
166
+ data -> hal_config .dma_in = (spi_dma_dev_t * )cfg -> spi ;
167
+ data -> hal_config .dma_out = (spi_dma_dev_t * )cfg -> spi ;
168
+ data -> hal_config .dma_enabled = true;
169
+ data -> hal_config .tx_dma_chan = cfg -> dma_host + 1 ;
170
+ data -> hal_config .rx_dma_chan = cfg -> dma_host + 1 ;
171
+ data -> hal_config .dmadesc_n = 1 ;
172
+ data -> hal_config .dmadesc_rx = & data -> dma_desc_rx ;
173
+ data -> hal_config .dmadesc_tx = & data -> dma_desc_tx ;
174
+
175
+ if (data -> hal_config .dmadesc_tx == NULL || data -> hal_config .dmadesc_rx == NULL ) {
176
+ k_free (data -> hal_config .dmadesc_tx );
177
+ k_free (data -> hal_config .dmadesc_rx );
178
+ return - ENOMEM ;
179
+ }
180
+
181
+ spi_hal_init (& data -> hal , cfg -> dma_host + 1 , & data -> hal_config );
182
+ return 0 ;
183
+ }
184
+
106
185
static int spi_esp32_init (const struct device * dev )
107
186
{
108
187
int err ;
@@ -113,6 +192,10 @@ static int spi_esp32_init(const struct device *dev)
113
192
return - EINVAL ;
114
193
}
115
194
195
+ if (cfg -> dma_enabled ) {
196
+ spi_esp32_init_dma (dev );
197
+ }
198
+
116
199
#ifdef CONFIG_SPI_ESP32_INTERRUPT
117
200
data -> irq_line = esp_intr_alloc (cfg -> irq_source ,
118
201
0 ,
@@ -382,6 +465,9 @@ static const struct spi_driver_api spi_api = {
382
465
.clock_subsys = \
383
466
(clock_control_subsys_t)DT_INST_CLOCKS_CELL(idx, offset), \
384
467
.use_iomux = DT_INST_PROP(idx, use_iomux), \
468
+ .dma_enabled = DT_INST_PROP(idx, dma_enabled), \
469
+ .dma_clk_src = DT_INST_PROP(idx, dma_clk), \
470
+ .dma_host = DT_INST_PROP(idx, dma_host), \
385
471
}; \
386
472
\
387
473
DEVICE_DT_INST_DEFINE(idx, &spi_esp32_init, \
0 commit comments