spi: fix locking for SPI_LOCK_ON using synchronous API
Keep locking for SPI_LOCK_ON from the first call of transceive until spi_release release the lock. Use owner parameter to in the spi_context to store the owner of the lock. The locking is in line with the SPI_HOLD_ON_CS Signed-off-by: Stefan Bigler <stefan@bigler.io>
This commit is contained in:
parent
638b5f389f
commit
596cad8231
17 changed files with 35 additions and 20 deletions
|
@ -146,7 +146,7 @@ static int spi_cc13xx_cc26xx_transceive(const struct device *dev,
|
|||
uint32_t txd, rxd;
|
||||
int err;
|
||||
|
||||
spi_context_lock(ctx, false, NULL);
|
||||
spi_context_lock(ctx, false, NULL, config);
|
||||
|
||||
#if defined(CONFIG_SYS_POWER_MANAGEMENT) && \
|
||||
defined(CONFIG_SYS_POWER_SLEEP_STATES)
|
||||
|
|
|
@ -26,6 +26,7 @@ enum spi_ctx_runtime_op_mode {
|
|||
|
||||
struct spi_context {
|
||||
const struct spi_config *config;
|
||||
const struct spi_config *owner;
|
||||
|
||||
struct k_sem lock;
|
||||
struct k_sem sync;
|
||||
|
@ -69,9 +70,17 @@ static inline bool spi_context_is_slave(struct spi_context *ctx)
|
|||
|
||||
static inline void spi_context_lock(struct spi_context *ctx,
|
||||
bool asynchronous,
|
||||
struct k_poll_signal *signal)
|
||||
struct k_poll_signal *signal,
|
||||
const struct spi_config *spi_cfg)
|
||||
{
|
||||
if ((spi_cfg->operation & SPI_LOCK_ON) &&
|
||||
(k_sem_count_get(&ctx->lock) == 0) &&
|
||||
(ctx->owner == spi_cfg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
k_sem_take(&ctx->lock, K_FOREVER);
|
||||
ctx->owner = spi_cfg;
|
||||
|
||||
#ifdef CONFIG_SPI_ASYNC
|
||||
ctx->asynchronous = asynchronous;
|
||||
|
@ -89,10 +98,14 @@ static inline void spi_context_release(struct spi_context *ctx, int status)
|
|||
|
||||
#ifdef CONFIG_SPI_ASYNC
|
||||
if (!ctx->asynchronous || (status < 0)) {
|
||||
ctx->owner = NULL;
|
||||
k_sem_give(&ctx->lock);
|
||||
}
|
||||
#else
|
||||
k_sem_give(&ctx->lock);
|
||||
if (!(ctx->config->operation & SPI_LOCK_ON)) {
|
||||
ctx->owner = NULL;
|
||||
k_sem_give(&ctx->lock);
|
||||
}
|
||||
#endif /* CONFIG_SPI_ASYNC */
|
||||
}
|
||||
|
||||
|
@ -138,6 +151,7 @@ static inline void spi_context_complete(struct spi_context *ctx, int status)
|
|||
}
|
||||
|
||||
if (!(ctx->config->operation & SPI_LOCK_ON)) {
|
||||
ctx->owner = NULL;
|
||||
k_sem_give(&ctx->lock);
|
||||
}
|
||||
}
|
||||
|
@ -205,6 +219,7 @@ static inline void spi_context_unlock_unconditionally(struct spi_context *ctx)
|
|||
_spi_context_cs_control(ctx, false, true);
|
||||
|
||||
if (!k_sem_count_get(&ctx->lock)) {
|
||||
ctx->owner = NULL;
|
||||
k_sem_give(&ctx->lock);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -342,7 +342,7 @@ static int transceive(const struct device *dev,
|
|||
uint32_t reg_data;
|
||||
int ret;
|
||||
|
||||
spi_context_lock(&spi->ctx, asynchronous, signal);
|
||||
spi_context_lock(&spi->ctx, asynchronous, signal, config);
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
if (device_busy_check(dev) != (-EBUSY)) {
|
||||
|
|
|
@ -575,7 +575,7 @@ static int transceive(const struct device *dev,
|
|||
}
|
||||
#endif
|
||||
|
||||
spi_context_lock(&data->ctx, asynchronous, signal);
|
||||
spi_context_lock(&data->ctx, asynchronous, signal, config);
|
||||
|
||||
ret = spi_stm32_configure(dev, config);
|
||||
if (ret) {
|
||||
|
@ -671,7 +671,7 @@ static int transceive_dma(const struct device *dev,
|
|||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
spi_context_lock(&data->ctx, asynchronous, signal);
|
||||
spi_context_lock(&data->ctx, asynchronous, signal, config);
|
||||
|
||||
k_sem_reset(&data->status_sem);
|
||||
|
||||
|
|
|
@ -214,7 +214,7 @@ static int transceive(const struct device *dev,
|
|||
struct spi_mcux_data *data = dev->data;
|
||||
int ret;
|
||||
|
||||
spi_context_lock(&data->ctx, asynchronous, signal);
|
||||
spi_context_lock(&data->ctx, asynchronous, signal, spi_cfg);
|
||||
|
||||
ret = spi_mcux_configure(dev, spi_cfg);
|
||||
if (ret) {
|
||||
|
|
|
@ -622,7 +622,7 @@ static int transceive(const struct device *dev,
|
|||
struct spi_mcux_data *data = dev->data;
|
||||
int ret;
|
||||
|
||||
spi_context_lock(&data->ctx, asynchronous, signal);
|
||||
spi_context_lock(&data->ctx, asynchronous, signal, spi_cfg);
|
||||
|
||||
ret = spi_mcux_configure(dev, spi_cfg);
|
||||
if (ret) {
|
||||
|
|
|
@ -213,7 +213,7 @@ static int transceive(const struct device *dev,
|
|||
struct spi_mcux_data *data = dev->data;
|
||||
int ret;
|
||||
|
||||
spi_context_lock(&data->ctx, asynchronous, signal);
|
||||
spi_context_lock(&data->ctx, asynchronous, signal, spi_cfg);
|
||||
|
||||
ret = spi_mcux_configure(dev, spi_cfg);
|
||||
if (ret) {
|
||||
|
|
|
@ -180,7 +180,7 @@ static int transceive(const struct device *dev,
|
|||
struct spi_nrfx_data *dev_data = get_dev_data(dev);
|
||||
int error;
|
||||
|
||||
spi_context_lock(&dev_data->ctx, asynchronous, signal);
|
||||
spi_context_lock(&dev_data->ctx, asynchronous, signal, spi_cfg);
|
||||
|
||||
error = configure(dev, spi_cfg);
|
||||
if (error == 0) {
|
||||
|
|
|
@ -222,7 +222,7 @@ static int transceive(const struct device *dev,
|
|||
struct spi_nrfx_data *dev_data = get_dev_data(dev);
|
||||
int error;
|
||||
|
||||
spi_context_lock(&dev_data->ctx, asynchronous, signal);
|
||||
spi_context_lock(&dev_data->ctx, asynchronous, signal, spi_cfg);
|
||||
|
||||
error = configure(dev, spi_cfg);
|
||||
if (error == 0) {
|
||||
|
|
|
@ -151,7 +151,7 @@ static int transceive(const struct device *dev,
|
|||
struct spi_nrfx_data *dev_data = get_dev_data(dev);
|
||||
int error;
|
||||
|
||||
spi_context_lock(&dev_data->ctx, asynchronous, signal);
|
||||
spi_context_lock(&dev_data->ctx, asynchronous, signal, spi_cfg);
|
||||
|
||||
error = configure(dev, spi_cfg);
|
||||
if (error != 0) {
|
||||
|
|
|
@ -100,7 +100,7 @@ int spi_oc_simple_transceive(const struct device *dev,
|
|||
int rc;
|
||||
|
||||
/* Lock the SPI Context */
|
||||
spi_context_lock(ctx, false, NULL);
|
||||
spi_context_lock(ctx, false, NULL, config);
|
||||
|
||||
spi_oc_simple_configure(info, spi, config);
|
||||
|
||||
|
|
|
@ -210,7 +210,7 @@ static int transceive(const struct device *dev,
|
|||
struct spi_mcux_data *data = dev->data;
|
||||
int ret;
|
||||
|
||||
spi_context_lock(&data->ctx, asynchronous, signal);
|
||||
spi_context_lock(&data->ctx, asynchronous, signal, spi_cfg);
|
||||
|
||||
ret = spi_mcux_configure(dev, spi_cfg);
|
||||
if (ret) {
|
||||
|
|
|
@ -366,7 +366,7 @@ static int spi_sam_transceive(const struct device *dev,
|
|||
Spi *regs = cfg->regs;
|
||||
int err;
|
||||
|
||||
spi_context_lock(&data->ctx, false, NULL);
|
||||
spi_context_lock(&data->ctx, false, NULL, config);
|
||||
|
||||
err = spi_sam_configure(dev, config);
|
||||
if (err != 0) {
|
||||
|
|
|
@ -396,7 +396,7 @@ static int spi_sam0_transceive(const struct device *dev,
|
|||
SercomSpi *regs = cfg->regs;
|
||||
int err;
|
||||
|
||||
spi_context_lock(&data->ctx, false, NULL);
|
||||
spi_context_lock(&data->ctx, false, NULL, config);
|
||||
|
||||
err = spi_sam0_configure(dev, config);
|
||||
if (err != 0) {
|
||||
|
@ -638,7 +638,7 @@ static int spi_sam0_transceive_async(const struct device *dev,
|
|||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
spi_context_lock(&data->ctx, true, async);
|
||||
spi_context_lock(&data->ctx, true, async, config);
|
||||
|
||||
retval = spi_sam0_configure(dev, config);
|
||||
if (retval != 0) {
|
||||
|
|
|
@ -168,7 +168,7 @@ int spi_sifive_transceive(const struct device *dev,
|
|||
bool hw_cs_control = false;
|
||||
|
||||
/* Lock the SPI Context */
|
||||
spi_context_lock(&SPI_DATA(dev)->ctx, false, NULL);
|
||||
spi_context_lock(&SPI_DATA(dev)->ctx, false, NULL, config);
|
||||
|
||||
/* Configure the SPI bus */
|
||||
SPI_DATA(dev)->ctx.config = config;
|
||||
|
|
|
@ -517,7 +517,7 @@ static int qmspi_transceive(const struct device *dev,
|
|||
uint32_t descr, last_didx;
|
||||
int err;
|
||||
|
||||
spi_context_lock(&data->ctx, false, NULL);
|
||||
spi_context_lock(&data->ctx, false, NULL, config);
|
||||
|
||||
err = qmspi_configure(dev, config);
|
||||
if (err != 0) {
|
||||
|
|
|
@ -321,7 +321,7 @@ static int xlnx_quadspi_transceive(const struct device *dev,
|
|||
struct spi_context *ctx = &data->ctx;
|
||||
int ret;
|
||||
|
||||
spi_context_lock(ctx, async, signal);
|
||||
spi_context_lock(ctx, async, signal, spi_cfg);
|
||||
|
||||
ret = xlnx_quadspi_configure(dev, spi_cfg);
|
||||
if (ret) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue