@@ -19,15 +19,18 @@ LOG_MODULE_REGISTER(esp32_spi, CONFIG_SPI_LOG_LEVEL);
19
19
#include <zephyr/drivers/spi.h>
20
20
#include <zephyr/drivers/interrupt_controller/intc_esp32.h>
21
21
#ifdef SOC_GDMA_SUPPORTED
22
- #include <hal/gdma_hal .h>
23
- #include <hal/gdma_ll .h>
22
+ #include <zephyr/drivers/dma .h>
23
+ #include <zephyr/drivers/dma/dma_esp32 .h>
24
24
#endif
25
25
#include <zephyr/drivers/clock_control.h>
26
26
#include "spi_context.h"
27
27
#include "spi_esp32_spim.h"
28
28
29
29
#define SPI_DMA_MAX_BUFFER_SIZE 4092
30
30
31
+ #define SPI_DMA_RX 0
32
+ #define SPI_DMA_TX 1
33
+
31
34
static bool spi_esp32_transfer_ongoing (struct spi_esp32_data * data )
32
35
{
33
36
return spi_context_tx_on (& data -> ctx ) || spi_context_rx_on (& data -> ctx );
@@ -47,8 +50,67 @@ static inline void spi_esp32_complete(const struct device *dev,
47
50
#ifdef CONFIG_SPI_ESP32_INTERRUPT
48
51
spi_context_complete (& data -> ctx , dev , status );
49
52
#endif
53
+ }
54
+
55
+ #ifdef SOC_GDMA_SUPPORTED
56
+ static int spi_esp32_gdma_start (const struct device * dev , uint8_t dir , uint8_t * buf , size_t len )
57
+ {
58
+ const struct spi_esp32_config * cfg = dev -> config ;
59
+
60
+ struct dma_config dma_cfg = {};
61
+ struct dma_status dma_status = {};
62
+ struct dma_block_config dma_blk = {};
63
+ int err = 0 ;
64
+
65
+ uint8_t dma_channel = (dir == SPI_DMA_RX ) ? cfg -> dma_rx_ch : cfg -> dma_tx_ch ;
66
+
67
+ if (dma_channel == 0xFF ) {
68
+ LOG_ERR ("DMA channel is not configured in device tree" );
69
+ return - EINVAL ;
70
+ }
71
+
72
+ err = dma_get_status (cfg -> dma_dev , dma_channel , & dma_status );
73
+ if (err ) {
74
+ return - EINVAL ;
75
+ }
76
+
77
+ if (dma_status .busy ) {
78
+ LOG_ERR ("DMA channel %d is busy" , dma_channel );
79
+ return - EBUSY ;
80
+ }
81
+
82
+ unsigned int key = irq_lock ();
83
+
84
+ if (dir == SPI_DMA_RX ) {
85
+ dma_cfg .channel_direction = PERIPHERAL_TO_MEMORY ;
86
+ dma_blk .dest_address = (uint32_t )buf ;
87
+ } else {
88
+ dma_cfg .channel_direction = MEMORY_TO_PERIPHERAL ;
89
+ dma_blk .source_address = (uint32_t )buf ;
90
+ }
91
+ dma_cfg .dma_slot = cfg -> dma_host ;
92
+ dma_cfg .block_count = 1 ;
93
+ dma_cfg .head_block = & dma_blk ;
94
+ dma_blk .block_size = len ;
95
+
96
+ err = dma_config (cfg -> dma_dev , dma_channel , & dma_cfg );
97
+ if (err ) {
98
+ LOG_ERR ("Error configuring DMA (%d)" , err );
99
+ goto unlock ;
100
+ }
50
101
102
+ err = dma_start (cfg -> dma_dev , dma_channel );
103
+ if (err ) {
104
+ LOG_ERR ("Error starting DMA (%d)" , err );
105
+ goto unlock ;
106
+ }
107
+
108
+ unlock :
109
+ irq_unlock (key );
110
+
111
+ return err ;
51
112
}
113
+ #endif
52
114
53
115
static int IRAM_ATTR spi_esp32_transfer (const struct device * dev )
54
116
{
@@ -68,6 +130,8 @@ static int IRAM_ATTR spi_esp32_transfer(const struct device *dev)
68
130
uint8_t * tx_temp = NULL ;
69
131
size_t dma_len_tx = MIN (ctx -> tx_len * data -> dfs , SPI_DMA_MAX_BUFFER_SIZE );
70
132
size_t dma_len_rx = MIN (ctx -> rx_len * data -> dfs , SPI_DMA_MAX_BUFFER_SIZE );
133
+ bool prepare_data = true;
134
+ int err = 0 ;
71
135
72
136
if (cfg -> dma_enabled ) {
73
137
/* bit_len needs to be at least one byte long when using DMA */
@@ -91,8 +155,8 @@ static int IRAM_ATTR spi_esp32_transfer(const struct device *dev)
91
155
rx_temp = k_calloc (((dma_len_rx << 3 ) + 31 ) / 8 , sizeof (uint8_t ));
92
156
if (!rx_temp ) {
93
157
LOG_ERR ("Error allocating temp buffer Rx" );
94
- k_free ( tx_temp ) ;
95
- return - ENOMEM ;
158
+ err = - ENOMEM ;
159
+ goto free ;
96
160
}
97
161
}
98
162
}
@@ -119,7 +183,38 @@ static int IRAM_ATTR spi_esp32_transfer(const struct device *dev)
119
183
120
184
/* configure SPI */
121
185
spi_hal_setup_trans (hal , hal_dev , hal_trans );
122
- spi_hal_prepare_data (hal , hal_dev , hal_trans );
186
+
187
+ #if defined(SOC_GDMA_SUPPORTED )
188
+ if (cfg -> dma_enabled && hal_trans -> rcv_buffer && hal_trans -> send_buffer ) {
189
+ /* setup DMA channels via DMA driver */
190
+ spi_ll_dma_rx_fifo_reset (hal -> hw );
191
+ spi_ll_infifo_full_clr (hal -> hw );
192
+ spi_ll_dma_rx_enable (hal -> hw , 1 );
193
+
194
+ err = spi_esp32_gdma_start (dev , SPI_DMA_RX , hal_trans -> rcv_buffer ,
195
+ transfer_len_bytes );
196
+ if (err ) {
197
+ goto free ;
198
+ }
199
+
200
+ spi_ll_dma_tx_fifo_reset (hal -> hw );
201
+ spi_ll_outfifo_empty_clr (hal -> hw );
202
+ spi_ll_dma_tx_enable (hal -> hw , 1 );
203
+
204
+ err = spi_esp32_gdma_start (dev , SPI_DMA_TX , hal_trans -> send_buffer ,
205
+ transfer_len_bytes );
206
+ if (err ) {
207
+ goto free ;
208
+ }
209
+ }
210
+
211
+ prepare_data = !cfg -> dma_enabled ;
212
+ #endif
213
+
214
+ if (prepare_data ) {
215
+ /* only for plain transfers or DMA transfers w/o GDMA */
216
+ spi_hal_prepare_data (hal , hal_dev , hal_trans );
217
+ }
123
218
124
219
/* send data */
125
220
spi_hal_user_start (hal );
@@ -129,19 +224,22 @@ static int IRAM_ATTR spi_esp32_transfer(const struct device *dev)
129
224
/* nop */
130
225
}
131
226
132
- /* read data */
133
- spi_hal_fetch_result (hal );
227
+ if (!cfg -> dma_enabled ) {
228
+ /* read data */
229
+ spi_hal_fetch_result (hal );
230
+ }
134
231
135
232
if (rx_temp ) {
136
233
memcpy (& ctx -> rx_buf [0 ], rx_temp , transfer_len_bytes );
137
234
}
138
235
139
236
spi_context_update_rx (& data -> ctx , data -> dfs , transfer_len_frames );
140
237
238
+ free :
141
239
k_free (tx_temp );
142
240
k_free (rx_temp );
143
241
144
- return 0 ;
242
+ return err ;
145
243
}
146
244
147
245
#ifdef CONFIG_SPI_ESP32_INTERRUPT
@@ -163,31 +261,24 @@ static int spi_esp32_init_dma(const struct device *dev)
163
261
{
164
262
const struct spi_esp32_config * cfg = dev -> config ;
165
263
struct spi_esp32_data * data = dev -> data ;
166
- uint8_t channel_offset ;
167
264
265
+ #ifdef SOC_GDMA_SUPPORTED
266
+ if (cfg -> dma_dev ) {
267
+ if (!device_is_ready (cfg -> dma_dev )) {
268
+ LOG_ERR ("DMA device is not ready" );
269
+ return - ENODEV ;
270
+ }
271
+ }
272
+
273
+ /* DMA operation won't be handled by HAL */
274
+ data -> hal_config .dma_enabled = false;
275
+ #else
168
276
if (clock_control_on (cfg -> clock_dev , (clock_control_subsys_t )cfg -> dma_clk_src )) {
169
277
LOG_ERR ("Could not enable DMA clock" );
170
278
return - EIO ;
171
279
}
172
280
173
- #ifdef SOC_GDMA_SUPPORTED
174
- gdma_hal_init (& data -> hal_gdma , 0 );
175
- gdma_ll_enable_clock (data -> hal_gdma .dev , true);
176
- gdma_ll_tx_reset_channel (data -> hal_gdma .dev , cfg -> dma_host );
177
- gdma_ll_rx_reset_channel (data -> hal_gdma .dev , cfg -> dma_host );
178
- gdma_ll_tx_connect_to_periph (data -> hal_gdma .dev , cfg -> dma_host , GDMA_TRIG_PERIPH_SPI ,
179
- cfg -> dma_host );
180
- gdma_ll_rx_connect_to_periph (data -> hal_gdma .dev , cfg -> dma_host , GDMA_TRIG_PERIPH_SPI ,
181
- cfg -> dma_host );
182
- channel_offset = 0 ;
183
- #else
184
- channel_offset = 1 ;
185
- #endif /* SOC_GDMA_SUPPORTED */
186
- #ifdef CONFIG_SOC_SERIES_ESP32
187
- /*Connect SPI and DMA*/
188
- DPORT_SET_PERI_REG_BITS (DPORT_SPI_DMA_CHAN_SEL_REG , 3 , cfg -> dma_host + 1 ,
189
- ((cfg -> dma_host + 1 ) * 2 ));
190
- #endif /* CONFIG_SOC_SERIES_ESP32 */
281
+ int channel_offset = 1 ;
191
282
192
283
data -> hal_config .dma_in = (spi_dma_dev_t * )cfg -> spi ;
193
284
data -> hal_config .dma_out = (spi_dma_dev_t * )cfg -> spi ;
@@ -203,8 +294,16 @@ static int spi_esp32_init_dma(const struct device *dev)
203
294
k_free (data -> hal_config .dmadesc_rx );
204
295
return - ENOMEM ;
205
296
}
297
+ #endif /* SOC_GDMA_SUPPORTED */
298
+
299
+ #ifdef CONFIG_SOC_SERIES_ESP32
300
+ /* Connect SPI and DMA */
301
+ DPORT_SET_PERI_REG_BITS (DPORT_SPI_DMA_CHAN_SEL_REG , 3 , cfg -> dma_host + 1 ,
302
+ ((cfg -> dma_host + 1 ) * 2 ));
303
+ #endif /* CONFIG_SOC_SERIES_ESP32 */
206
304
207
305
spi_hal_init (& data -> hal , cfg -> dma_host + 1 , & data -> hal_config );
306
+
208
307
return 0 ;
209
308
}
210
309
@@ -511,6 +610,16 @@ static DEVICE_API(spi, spi_api) = {
511
610
#define GET_AS_CS (idx )
512
611
#endif
513
612
613
+ #if defined(SOC_GDMA_SUPPORTED )
614
+ #define SPI_DMA_CFG (idx ) \
615
+ .dma_dev = ESP32_DT_INST_DMA_CTLR(idx, tx), \
616
+ .dma_tx_ch = ESP32_DT_INST_DMA_CELL(idx, tx, channel), \
617
+ .dma_rx_ch = ESP32_DT_INST_DMA_CELL(idx, rx, channel)
618
+ #else
619
+ #define SPI_DMA_CFG (idx ) \
620
+ .dma_clk_src = DT_INST_PROP(idx, dma_clk)
621
+ #endif /* defined(SOC_GDMA_SUPPORTED) */
622
+
514
623
#define ESP32_SPI_INIT (idx ) \
515
624
\
516
625
PINCTRL_DT_INST_DEFINE(idx); \
@@ -545,8 +654,8 @@ static DEVICE_API(spi, spi_api) = {
545
654
(clock_control_subsys_t)DT_INST_CLOCKS_CELL(idx, offset), \
546
655
.use_iomux = DT_INST_PROP(idx, use_iomux), \
547
656
.dma_enabled = DT_INST_PROP(idx, dma_enabled), \
548
- .dma_clk_src = DT_INST_PROP(idx, dma_clk), \
549
657
.dma_host = DT_INST_PROP(idx, dma_host), \
658
+ SPI_DMA_CFG(idx), \
550
659
.cs_setup = DT_INST_PROP_OR(idx, cs_setup_time, 0), \
551
660
.cs_hold = DT_INST_PROP_OR(idx, cs_hold_time, 0), \
552
661
.line_idle_low = DT_INST_PROP(idx, line_idle_low), \
0 commit comments