10
10
LOG_MODULE_REGISTER (spi_cc23x0 , CONFIG_SPI_LOG_LEVEL );
11
11
12
12
#include <zephyr/device.h>
13
+ #include <zephyr/drivers/dma.h>
13
14
#include <zephyr/drivers/pinctrl.h>
14
15
#include <zephyr/drivers/spi.h>
15
16
#include <zephyr/irq.h>
@@ -18,6 +19,8 @@ LOG_MODULE_REGISTER(spi_cc23x0, CONFIG_SPI_LOG_LEVEL);
18
19
#include <driverlib/clkctl.h>
19
20
#include <driverlib/spi.h>
20
21
22
+ #include <inc/hw_memmap.h>
23
+
21
24
#include "spi_context.h"
22
25
23
26
/*
@@ -30,33 +33,55 @@ LOG_MODULE_REGISTER(spi_cc23x0, CONFIG_SPI_LOG_LEVEL);
30
33
#define SPI_CC23_DATA_WIDTH 8
31
34
#define SPI_CC23_DFS (SPI_CC23_DATA_WIDTH >> 3)
32
35
36
+ #ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
37
+ #define SPI_CC23_REG_GET (base , offset ) ((base) + (offset))
38
+ #define SPI_CC23_INT_MASK SPI_DMA_DONE_RX
39
+ #else
33
40
#define SPI_CC23_INT_MASK (SPI_TXEMPTY | SPI_IDLE | SPI_RX)
41
+ #endif
34
42
35
43
struct spi_cc23x0_config {
36
44
uint32_t base ;
37
45
const struct pinctrl_dev_config * pincfg ;
38
46
void (* irq_config_func )(void );
47
+ #ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
48
+ const struct device * dma_dev ;
49
+ uint8_t dma_channel_tx ;
50
+ uint8_t dma_trigsrc_tx ;
51
+ uint8_t dma_channel_rx ;
52
+ uint8_t dma_trigsrc_rx ;
53
+ #endif
39
54
};
40
55
41
56
struct spi_cc23x0_data {
42
57
struct spi_context ctx ;
43
58
size_t tx_len_left ;
59
+ #ifndef CONFIG_SPI_CC23X0_DMA_DRIVEN
44
60
uint32_t tx_count ;
45
61
uint32_t rx_count ;
46
62
bool xfer_done ;
63
+ #endif
47
64
};
48
65
49
66
static void spi_cc23x0_isr (const struct device * dev )
50
67
{
51
68
const struct spi_cc23x0_config * cfg = dev -> config ;
52
69
struct spi_cc23x0_data * data = dev -> data ;
53
70
struct spi_context * ctx = & data -> ctx ;
54
- uint32_t txd = 0 , rxd ;
55
71
uint32_t status ;
72
+ #ifndef CONFIG_SPI_CC23X0_DMA_DRIVEN
73
+ uint32_t txd = 0 , rxd ;
74
+ #endif
56
75
57
76
status = SPIIntStatus (cfg -> base , true);
58
77
LOG_DBG ("status = %08x" , status );
59
78
79
+ #ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
80
+ if (status & SPI_DMA_DONE_RX ) {
81
+ SPIClearInt (cfg -> base , SPI_DMA_DONE_RX );
82
+ spi_context_complete (ctx , dev , 0 );
83
+ }
84
+ #else
60
85
/*
61
86
* Disabling the interrupts in this ISR when SPI has completed
62
87
* the transfer triggers a subsequent spurious interrupt, with
@@ -124,6 +149,7 @@ static void spi_cc23x0_isr(const struct device *dev)
124
149
SPIDisableInt (cfg -> base , SPI_CC23_INT_MASK );
125
150
spi_context_complete (ctx , dev , 0 );
126
151
}
152
+ #endif
127
153
}
128
154
129
155
static int spi_cc23x0_configure (const struct device * dev ,
@@ -221,9 +247,11 @@ static void spi_cc23x0_initialize_data(struct spi_cc23x0_data *data)
221
247
{
222
248
data -> tx_len_left = MAX (spi_context_total_tx_len (& data -> ctx ),
223
249
spi_context_total_rx_len (& data -> ctx ));
250
+ #ifndef CONFIG_SPI_CC23X0_DMA_DRIVEN
224
251
data -> tx_count = 0 ;
225
252
data -> rx_count = 0 ;
226
253
data -> xfer_done = false;
254
+ #endif
227
255
}
228
256
229
257
static int spi_cc23x0_transceive (const struct device * dev ,
@@ -235,6 +263,43 @@ static int spi_cc23x0_transceive(const struct device *dev,
235
263
struct spi_cc23x0_data * data = dev -> data ;
236
264
struct spi_context * ctx = & data -> ctx ;
237
265
int ret ;
266
+ #ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
267
+ struct dma_block_config block_cfg_tx = {
268
+ .dest_address = SPI_CC23_REG_GET (cfg -> base , SPI_O_TXDATA ),
269
+ .dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE ,
270
+ .block_size = 1 ,
271
+ };
272
+
273
+ struct dma_config dma_cfg_tx = {
274
+ .dma_slot = cfg -> dma_trigsrc_tx ,
275
+ .channel_direction = MEMORY_TO_PERIPHERAL ,
276
+ .block_count = 1 ,
277
+ .head_block = & block_cfg_tx ,
278
+ .source_data_size = SPI_CC23_DFS ,
279
+ .dest_data_size = SPI_CC23_DFS ,
280
+ .source_burst_length = SPI_CC23_DFS ,
281
+ .dma_callback = NULL ,
282
+ .user_data = NULL ,
283
+ };
284
+
285
+ struct dma_block_config block_cfg_rx = {
286
+ .source_address = SPI_CC23_REG_GET (cfg -> base , SPI_O_RXDATA ),
287
+ .source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE ,
288
+ .block_size = 1 ,
289
+ };
290
+
291
+ struct dma_config dma_cfg_rx = {
292
+ .dma_slot = cfg -> dma_trigsrc_rx ,
293
+ .channel_direction = PERIPHERAL_TO_MEMORY ,
294
+ .block_count = 1 ,
295
+ .head_block = & block_cfg_rx ,
296
+ .source_data_size = SPI_CC23_DFS ,
297
+ .dest_data_size = SPI_CC23_DFS ,
298
+ .source_burst_length = SPI_CC23_DFS ,
299
+ .dma_callback = NULL ,
300
+ .user_data = NULL ,
301
+ };
302
+ #endif
238
303
239
304
spi_context_lock (ctx , false, NULL , NULL , config );
240
305
@@ -245,19 +310,73 @@ static int spi_cc23x0_transceive(const struct device *dev,
245
310
246
311
spi_context_buffers_setup (ctx , tx_bufs , rx_bufs , SPI_CC23_DFS );
247
312
313
+ #ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
314
+ if (spi_context_total_tx_len (ctx ) != spi_context_total_rx_len (ctx )) {
315
+ LOG_ERR ("In DMA mode, RX and TX buffer lengths must be the same" );
316
+ ret = - EINVAL ;
317
+ goto ctx_release ;
318
+ }
319
+ #endif
320
+
248
321
spi_cc23x0_initialize_data (data );
249
322
250
323
spi_context_cs_control (ctx , true);
251
324
252
325
SPIEnableInt (cfg -> base , SPI_CC23_INT_MASK );
253
326
327
+ #ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
328
+ block_cfg_tx .source_address = (uint32_t )ctx -> tx_buf ;
329
+ block_cfg_tx .source_addr_adj = DMA_ADDR_ADJ_INCREMENT ;
330
+ block_cfg_tx .block_size = SPI_CC23_DFS * data -> tx_len_left ;
331
+
332
+ block_cfg_rx .dest_address = (uint32_t )ctx -> rx_buf ;
333
+ block_cfg_rx .dest_addr_adj = DMA_ADDR_ADJ_INCREMENT ;
334
+ block_cfg_rx .block_size = SPI_CC23_DFS * data -> tx_len_left ;
335
+
336
+ ret = dma_config (cfg -> dma_dev , cfg -> dma_channel_tx , & dma_cfg_tx );
337
+ if (ret ) {
338
+ LOG_ERR ("Failed to configure DMA TX channel" );
339
+ goto int_disable ;
340
+ }
341
+
342
+ ret = dma_config (cfg -> dma_dev , cfg -> dma_channel_rx , & dma_cfg_rx );
343
+ if (ret ) {
344
+ LOG_ERR ("Failed to configure DMA RX channel" );
345
+ goto int_disable ;
346
+ }
347
+
348
+ /* Disable DMA triggers */
349
+ SPIDisableDMA (cfg -> base , SPI_DMA_TX | SPI_DMA_RX );
350
+
351
+ /* Start DMA channels */
352
+ dma_start (cfg -> dma_dev , cfg -> dma_channel_rx );
353
+ dma_start (cfg -> dma_dev , cfg -> dma_channel_tx );
354
+
355
+ /* Enable DMA triggers to start transfer */
356
+ SPIEnableDMA (cfg -> base , SPI_DMA_TX | SPI_DMA_RX );
357
+
358
+ ret = spi_context_wait_for_completion (& data -> ctx );
359
+ if (ret ) {
360
+ LOG_ERR ("SPI transfer failed (%d)" , ret );
361
+ goto int_disable ;
362
+ }
363
+
364
+ spi_context_update_tx (ctx , SPI_CC23_DFS , data -> tx_len_left );
365
+ spi_context_update_rx (ctx , SPI_CC23_DFS , data -> tx_len_left );
366
+
367
+ LOG_DBG ("SPI transfer completed" );
368
+
369
+ int_disable :
370
+ SPIDisableInt (cfg -> base , SPI_CC23_INT_MASK );
371
+ #else
254
372
ret = spi_context_wait_for_completion (ctx );
255
373
if (ret ) {
256
374
SPIDisableInt (cfg -> base , SPI_CC23_INT_MASK );
257
375
LOG_ERR ("SPI transfer failed (%d)" , ret );
258
376
} else {
259
377
LOG_DBG ("SPI transfer completed" );
260
378
}
379
+ #endif
261
380
262
381
spi_context_cs_control (ctx , false);
263
382
@@ -304,6 +423,13 @@ static int spi_cc23x0_init(const struct device *dev)
304
423
return ret ;
305
424
}
306
425
426
+ #ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
427
+ if (!device_is_ready (cfg -> dma_dev )) {
428
+ LOG_ERR ("DMA not ready" );
429
+ return - ENODEV ;
430
+ }
431
+ #endif
432
+
307
433
ret = spi_context_cs_configure_all (& data -> ctx );
308
434
if (ret ) {
309
435
return ret ;
@@ -314,6 +440,17 @@ static int spi_cc23x0_init(const struct device *dev)
314
440
return 0 ;
315
441
}
316
442
443
+ #ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
444
+ #define SPI_CC23X0_DMA_INIT (n ) \
445
+ .dma_dev = DEVICE_DT_GET(TI_CC23X0_DT_INST_DMA_CTLR(n, tx)), \
446
+ .dma_channel_tx = TI_CC23X0_DT_INST_DMA_CHANNEL(n, tx), \
447
+ .dma_trigsrc_tx = TI_CC23X0_DT_INST_DMA_TRIGSRC(n, tx), \
448
+ .dma_channel_rx = TI_CC23X0_DT_INST_DMA_CHANNEL(n, rx), \
449
+ .dma_trigsrc_rx = TI_CC23X0_DT_INST_DMA_TRIGSRC(n, rx),
450
+ #else
451
+ #define SPI_CC23X0_DMA_INIT (n )
452
+ #endif
453
+
317
454
#define SPI_CC23X0_INIT (n ) \
318
455
PINCTRL_DT_INST_DEFINE(n); \
319
456
\
@@ -329,7 +466,8 @@ static int spi_cc23x0_init(const struct device *dev)
329
466
static const struct spi_cc23x0_config spi_cc23x0_config_##n = { \
330
467
.base = DT_INST_REG_ADDR(n), \
331
468
.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
332
- .irq_config_func = spi_irq_config_func_##n \
469
+ .irq_config_func = spi_irq_config_func_##n, \
470
+ SPI_CC23X0_DMA_INIT(n) \
333
471
}; \
334
472
\
335
473
static struct spi_cc23x0_data spi_cc23x0_data_##n = { \
0 commit comments