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:
parent
cd54dc66f2
commit
0bd83d21f2
2 changed files with 33 additions and 7 deletions
|
@ -22,6 +22,8 @@ extern "C" {
|
|||
struct spi_context {
|
||||
struct spi_config *config;
|
||||
|
||||
struct k_sem lock;
|
||||
|
||||
const struct spi_buf **current_tx;
|
||||
struct spi_buf **current_rx;
|
||||
|
||||
|
@ -31,12 +33,25 @@ struct spi_context {
|
|||
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,
|
||||
struct spi_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)
|
||||
{
|
||||
if (ctx->config->cs) {
|
||||
|
|
|
@ -259,6 +259,7 @@ static int spi_dw_transceive(struct device *dev,
|
|||
struct spi_dw_data *spi = dev->driver_data;
|
||||
u32_t rx_thsld = DW_SPI_RXFTLR_DFLT;
|
||||
u32_t imask = DW_SPI_IMR_UNMASK;
|
||||
int ret = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
spi_context_lock(&spi->ctx);
|
||||
|
||||
/* Configure */
|
||||
if (spi_dw_configure(info, spi, config)) {
|
||||
return -EINVAL;
|
||||
ret = spi_dw_configure(info, spi, config);
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set buffers info */
|
||||
|
@ -305,11 +309,12 @@ static int spi_dw_transceive(struct device *dev,
|
|||
k_sem_take(&spi->device_sync_sem, K_FOREVER);
|
||||
|
||||
if (spi->error) {
|
||||
spi->error = 0;
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
}
|
||||
out:
|
||||
spi_context_release(&spi->ctx);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
spi_context_release(&spi->ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -372,7 +379,9 @@ int spi_dw_init(struct device *dev)
|
|||
#ifdef CONFIG_SPI_0
|
||||
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 = {
|
||||
.regs = SPI_DW_PORT_0_REGS,
|
||||
|
@ -415,7 +424,9 @@ void spi_config_0_irq(void)
|
|||
#ifdef CONFIG_SPI_1
|
||||
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 = {
|
||||
.regs = SPI_DW_PORT_1_REGS,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue