drivers/spi: Add reentrance support to DW driver in a generic manner

Let's improve common SPI driver context by adding a lock and generic
function to get/release it.

It's statically initialized to save a bit of ROM.

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2017-05-05 13:28:17 +02:00 committed by Anas Nashif
commit 0bd83d21f2
2 changed files with 33 additions and 7 deletions

View file

@ -22,6 +22,8 @@ extern "C" {
struct spi_context { struct spi_context {
struct spi_config *config; struct spi_config *config;
struct k_sem lock;
const struct spi_buf **current_tx; const struct spi_buf **current_tx;
struct spi_buf **current_rx; struct spi_buf **current_rx;
@ -31,12 +33,25 @@ struct spi_context {
u32_t rx_len; u32_t rx_len;
}; };
#define SPI_CONTEXT_INIT_LOCK(_data, _ctx_name) \
._ctx_name.lock = K_SEM_INITIALIZER(_data._ctx_name.lock, 0, 1)
static inline bool spi_context_configured(struct spi_context *ctx, static inline bool spi_context_configured(struct spi_context *ctx,
struct spi_config *config) struct spi_config *config)
{ {
return !!(ctx->config == config); return !!(ctx->config == config);
} }
static inline void spi_context_lock(struct spi_context *ctx)
{
k_sem_take(&ctx->lock, K_FOREVER);
}
static inline void spi_context_release(struct spi_context *ctx)
{
k_sem_give(&ctx->lock);
}
static inline void spi_context_cs_configure(struct spi_context *ctx) static inline void spi_context_cs_configure(struct spi_context *ctx)
{ {
if (ctx->config->cs) { if (ctx->config->cs) {

View file

@ -259,6 +259,7 @@ static int spi_dw_transceive(struct device *dev,
struct spi_dw_data *spi = dev->driver_data; struct spi_dw_data *spi = dev->driver_data;
u32_t rx_thsld = DW_SPI_RXFTLR_DFLT; u32_t rx_thsld = DW_SPI_RXFTLR_DFLT;
u32_t imask = DW_SPI_IMR_UNMASK; u32_t imask = DW_SPI_IMR_UNMASK;
int ret = 0;
SYS_LOG_DBG("%p, %p, %p", dev, tx_bufs, rx_bufs); SYS_LOG_DBG("%p, %p, %p", dev, tx_bufs, rx_bufs);
@ -268,9 +269,12 @@ static int spi_dw_transceive(struct device *dev,
return -EBUSY; return -EBUSY;
} }
spi_context_lock(&spi->ctx);
/* Configure */ /* Configure */
if (spi_dw_configure(info, spi, config)) { ret = spi_dw_configure(info, spi, config);
return -EINVAL; if (ret) {
goto out;
} }
/* Set buffers info */ /* Set buffers info */
@ -305,11 +309,12 @@ static int spi_dw_transceive(struct device *dev,
k_sem_take(&spi->device_sync_sem, K_FOREVER); k_sem_take(&spi->device_sync_sem, K_FOREVER);
if (spi->error) { if (spi->error) {
spi->error = 0; ret = -EIO;
return -EIO;
} }
out:
spi_context_release(&spi->ctx);
return 0; return ret;
} }
void spi_dw_isr(struct device *dev) void spi_dw_isr(struct device *dev)
@ -365,6 +370,8 @@ int spi_dw_init(struct device *dev)
SYS_LOG_DBG("Designware SPI driver initialized on device: %p", dev); SYS_LOG_DBG("Designware SPI driver initialized on device: %p", dev);
spi_context_release(&spi->ctx);
return 0; return 0;
} }
@ -372,7 +379,9 @@ int spi_dw_init(struct device *dev)
#ifdef CONFIG_SPI_0 #ifdef CONFIG_SPI_0
void spi_config_0_irq(void); void spi_config_0_irq(void);
struct spi_dw_data spi_dw_data_port_0; struct spi_dw_data spi_dw_data_port_0 = {
SPI_CONTEXT_INIT_LOCK(spi_dw_data_port_0, ctx),
};
const struct spi_dw_config spi_dw_config_0 = { const struct spi_dw_config spi_dw_config_0 = {
.regs = SPI_DW_PORT_0_REGS, .regs = SPI_DW_PORT_0_REGS,
@ -415,7 +424,9 @@ void spi_config_0_irq(void)
#ifdef CONFIG_SPI_1 #ifdef CONFIG_SPI_1
void spi_config_1_irq(void); void spi_config_1_irq(void);
struct spi_dw_data spi_dw_data_port_1; struct spi_dw_data spi_dw_data_port_1 = {
SPI_CONTEXT_INIT_LOCK(spi_dw_data_port_1, ctx),
};
static const struct spi_dw_config spi_dw_config_1 = { static const struct spi_dw_config spi_dw_config_1 = {
.regs = SPI_DW_PORT_1_REGS, .regs = SPI_DW_PORT_1_REGS,