@ -10,6 +10,7 @@
@@ -10,6 +10,7 @@
LOG_MODULE_REGISTER ( spi_cc23x0 , CONFIG_SPI_LOG_LEVEL ) ;
# include <zephyr/device.h>
# include <zephyr/drivers/dma.h>
# include <zephyr/drivers/pinctrl.h>
# include <zephyr/drivers/spi.h>
# include <zephyr/irq.h>
@ -18,6 +19,8 @@ LOG_MODULE_REGISTER(spi_cc23x0, CONFIG_SPI_LOG_LEVEL);
@@ -18,6 +19,8 @@ LOG_MODULE_REGISTER(spi_cc23x0, CONFIG_SPI_LOG_LEVEL);
# include <driverlib/clkctl.h>
# include <driverlib/spi.h>
# include <inc/hw_memmap.h>
# include "spi_context.h"
/*
@ -30,20 +33,34 @@ LOG_MODULE_REGISTER(spi_cc23x0, CONFIG_SPI_LOG_LEVEL);
@@ -30,20 +33,34 @@ LOG_MODULE_REGISTER(spi_cc23x0, CONFIG_SPI_LOG_LEVEL);
# define SPI_CC23_DATA_WIDTH 8
# define SPI_CC23_DFS (SPI_CC23_DATA_WIDTH >> 3)
# ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
# define SPI_CC23_REG_GET(base, offset) ((base) + (offset))
# define SPI_CC23_INT_MASK SPI_DMA_DONE_RX
# else
# define SPI_CC23_INT_MASK (SPI_TXEMPTY | SPI_IDLE | SPI_RX)
# endif
struct spi_cc23x0_config {
uint32_t base ;
const struct pinctrl_dev_config * pincfg ;
void ( * irq_config_func ) ( void ) ;
# ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
const struct device * dma_dev ;
uint8_t dma_channel_tx ;
uint8_t dma_trigsrc_tx ;
uint8_t dma_channel_rx ;
uint8_t dma_trigsrc_rx ;
# endif
} ;
struct spi_cc23x0_data {
struct spi_context ctx ;
size_t tx_len_left ;
# ifndef CONFIG_SPI_CC23X0_DMA_DRIVEN
uint32_t tx_count ;
uint32_t rx_count ;
bool xfer_done ;
# endif
} ;
static void spi_cc23x0_isr ( const struct device * dev )
@ -51,12 +68,20 @@ static void spi_cc23x0_isr(const struct device *dev)
@@ -51,12 +68,20 @@ static void spi_cc23x0_isr(const struct device *dev)
const struct spi_cc23x0_config * cfg = dev - > config ;
struct spi_cc23x0_data * data = dev - > data ;
struct spi_context * ctx = & data - > ctx ;
uint32_t txd = 0 , rxd ;
uint32_t status ;
# ifndef CONFIG_SPI_CC23X0_DMA_DRIVEN
uint32_t txd = 0 , rxd ;
# endif
status = SPIIntStatus ( cfg - > base , true ) ;
LOG_DBG ( " status = %08x " , status ) ;
# ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
if ( status & SPI_DMA_DONE_RX ) {
SPIClearInt ( cfg - > base , SPI_DMA_DONE_RX ) ;
spi_context_complete ( ctx , dev , 0 ) ;
}
# else
/*
* Disabling the interrupts in this ISR when SPI has completed
* the transfer triggers a subsequent spurious interrupt , with
@ -124,6 +149,7 @@ static void spi_cc23x0_isr(const struct device *dev)
@@ -124,6 +149,7 @@ static void spi_cc23x0_isr(const struct device *dev)
SPIDisableInt ( cfg - > base , SPI_CC23_INT_MASK ) ;
spi_context_complete ( ctx , dev , 0 ) ;
}
# endif
}
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,9 +247,11 @@ static void spi_cc23x0_initialize_data(struct spi_cc23x0_data *data)
{
data - > tx_len_left = MAX ( spi_context_total_tx_len ( & data - > ctx ) ,
spi_context_total_rx_len ( & data - > ctx ) ) ;
# ifndef CONFIG_SPI_CC23X0_DMA_DRIVEN
data - > tx_count = 0 ;
data - > rx_count = 0 ;
data - > xfer_done = false ;
# endif
}
static int spi_cc23x0_transceive ( const struct device * dev ,
@ -235,6 +263,43 @@ static int spi_cc23x0_transceive(const struct device *dev,
@@ -235,6 +263,43 @@ static int spi_cc23x0_transceive(const struct device *dev,
struct spi_cc23x0_data * data = dev - > data ;
struct spi_context * ctx = & data - > ctx ;
int ret ;
# ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
struct dma_block_config block_cfg_tx = {
. dest_address = SPI_CC23_REG_GET ( cfg - > base , SPI_O_TXDATA ) ,
. dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE ,
. block_size = 1 ,
} ;
struct dma_config dma_cfg_tx = {
. dma_slot = cfg - > dma_trigsrc_tx ,
. channel_direction = MEMORY_TO_PERIPHERAL ,
. block_count = 1 ,
. head_block = & block_cfg_tx ,
. source_data_size = SPI_CC23_DFS ,
. dest_data_size = SPI_CC23_DFS ,
. source_burst_length = SPI_CC23_DFS ,
. dma_callback = NULL ,
. user_data = NULL ,
} ;
struct dma_block_config block_cfg_rx = {
. source_address = SPI_CC23_REG_GET ( cfg - > base , SPI_O_RXDATA ) ,
. source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE ,
. block_size = 1 ,
} ;
struct dma_config dma_cfg_rx = {
. dma_slot = cfg - > dma_trigsrc_rx ,
. channel_direction = PERIPHERAL_TO_MEMORY ,
. block_count = 1 ,
. head_block = & block_cfg_rx ,
. source_data_size = SPI_CC23_DFS ,
. dest_data_size = SPI_CC23_DFS ,
. source_burst_length = SPI_CC23_DFS ,
. dma_callback = NULL ,
. user_data = NULL ,
} ;
# endif
spi_context_lock ( ctx , false , NULL , NULL , config ) ;
@ -245,12 +310,65 @@ static int spi_cc23x0_transceive(const struct device *dev,
@@ -245,12 +310,65 @@ static int spi_cc23x0_transceive(const struct device *dev,
spi_context_buffers_setup ( ctx , tx_bufs , rx_bufs , SPI_CC23_DFS ) ;
# ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
if ( spi_context_total_tx_len ( ctx ) ! = spi_context_total_rx_len ( ctx ) ) {
LOG_ERR ( " In DMA mode, RX and TX buffer lengths must be the same " ) ;
ret = - EINVAL ;
goto ctx_release ;
}
# endif
spi_cc23x0_initialize_data ( data ) ;
spi_context_cs_control ( ctx , true ) ;
SPIEnableInt ( cfg - > base , SPI_CC23_INT_MASK ) ;
# ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
block_cfg_tx . source_address = ( uint32_t ) ctx - > tx_buf ;
block_cfg_tx . source_addr_adj = DMA_ADDR_ADJ_INCREMENT ;
block_cfg_tx . block_size = SPI_CC23_DFS * data - > tx_len_left ;
block_cfg_rx . dest_address = ( uint32_t ) ctx - > rx_buf ;
block_cfg_rx . dest_addr_adj = DMA_ADDR_ADJ_INCREMENT ;
block_cfg_rx . block_size = SPI_CC23_DFS * data - > tx_len_left ;
ret = dma_config ( cfg - > dma_dev , cfg - > dma_channel_tx , & dma_cfg_tx ) ;
if ( ret ) {
LOG_ERR ( " Failed to configure DMA TX channel " ) ;
goto int_disable ;
}
ret = dma_config ( cfg - > dma_dev , cfg - > dma_channel_rx , & dma_cfg_rx ) ;
if ( ret ) {
LOG_ERR ( " Failed to configure DMA RX channel " ) ;
goto int_disable ;
}
/* Disable DMA triggers */
SPIDisableDMA ( cfg - > base , SPI_DMA_TX | SPI_DMA_RX ) ;
/* Start DMA channels */
dma_start ( cfg - > dma_dev , cfg - > dma_channel_rx ) ;
dma_start ( cfg - > dma_dev , cfg - > dma_channel_tx ) ;
/* Enable DMA triggers to start transfer */
SPIEnableDMA ( cfg - > base , SPI_DMA_TX | SPI_DMA_RX ) ;
ret = spi_context_wait_for_completion ( & data - > ctx ) ;
if ( ret ) {
LOG_ERR ( " SPI transfer failed (%d) " , ret ) ;
goto int_disable ;
}
spi_context_update_tx ( ctx , SPI_CC23_DFS , data - > tx_len_left ) ;
spi_context_update_rx ( ctx , SPI_CC23_DFS , data - > tx_len_left ) ;
LOG_DBG ( " SPI transfer completed " ) ;
int_disable :
SPIDisableInt ( cfg - > base , SPI_CC23_INT_MASK ) ;
# else
ret = spi_context_wait_for_completion ( ctx ) ;
if ( ret ) {
SPIDisableInt ( cfg - > base , SPI_CC23_INT_MASK ) ;
@ -258,6 +376,7 @@ static int spi_cc23x0_transceive(const struct device *dev,
@@ -258,6 +376,7 @@ static int spi_cc23x0_transceive(const struct device *dev,
} else {
LOG_DBG ( " SPI transfer completed " ) ;
}
# endif
spi_context_cs_control ( ctx , false ) ;
@ -304,6 +423,13 @@ static int spi_cc23x0_init(const struct device *dev)
@@ -304,6 +423,13 @@ static int spi_cc23x0_init(const struct device *dev)
return ret ;
}
# ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
if ( ! device_is_ready ( cfg - > dma_dev ) ) {
LOG_ERR ( " DMA not ready " ) ;
return - ENODEV ;
}
# endif
ret = spi_context_cs_configure_all ( & data - > ctx ) ;
if ( ret ) {
return ret ;
@ -314,6 +440,17 @@ static int spi_cc23x0_init(const struct device *dev)
@@ -314,6 +440,17 @@ static int spi_cc23x0_init(const struct device *dev)
return 0 ;
}
# ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN
# define SPI_CC23X0_DMA_INIT(n) \
. dma_dev = DEVICE_DT_GET ( TI_CC23X0_DT_INST_DMA_CTLR ( n , tx ) ) , \
. dma_channel_tx = TI_CC23X0_DT_INST_DMA_CHANNEL ( n , tx ) , \
. dma_trigsrc_tx = TI_CC23X0_DT_INST_DMA_TRIGSRC ( n , tx ) , \
. dma_channel_rx = TI_CC23X0_DT_INST_DMA_CHANNEL ( n , rx ) , \
. dma_trigsrc_rx = TI_CC23X0_DT_INST_DMA_TRIGSRC ( n , rx ) ,
# else
# define SPI_CC23X0_DMA_INIT(n)
# endif
# define SPI_CC23X0_INIT(n) \
PINCTRL_DT_INST_DEFINE ( n ) ; \
\
@ -329,7 +466,8 @@ static int spi_cc23x0_init(const struct device *dev)
@@ -329,7 +466,8 @@ static int spi_cc23x0_init(const struct device *dev)
static const struct spi_cc23x0_config spi_cc23x0_config_ # # n = { \
. base = DT_INST_REG_ADDR ( n ) , \
. pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET ( n ) , \
. irq_config_func = spi_irq_config_func_ # # n \
. irq_config_func = spi_irq_config_func_ # # n , \
SPI_CC23X0_DMA_INIT ( n ) \
} ; \
\
static struct spi_cc23x0_data spi_cc23x0_data_ # # n = { \