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:
Stefan Bigler 2020-10-19 08:52:29 +02:00 committed by Carles Cufí
commit 596cad8231
17 changed files with 35 additions and 20 deletions

View file

@ -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)

View file

@ -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);
}
}

View file

@ -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)) {

View file

@ -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);

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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);

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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;

View file

@ -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) {

View file

@ -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) {