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;
|
uint32_t txd, rxd;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
spi_context_lock(ctx, false, NULL);
|
spi_context_lock(ctx, false, NULL, config);
|
||||||
|
|
||||||
#if defined(CONFIG_SYS_POWER_MANAGEMENT) && \
|
#if defined(CONFIG_SYS_POWER_MANAGEMENT) && \
|
||||||
defined(CONFIG_SYS_POWER_SLEEP_STATES)
|
defined(CONFIG_SYS_POWER_SLEEP_STATES)
|
||||||
|
|
|
@ -26,6 +26,7 @@ enum spi_ctx_runtime_op_mode {
|
||||||
|
|
||||||
struct spi_context {
|
struct spi_context {
|
||||||
const struct spi_config *config;
|
const struct spi_config *config;
|
||||||
|
const struct spi_config *owner;
|
||||||
|
|
||||||
struct k_sem lock;
|
struct k_sem lock;
|
||||||
struct k_sem sync;
|
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,
|
static inline void spi_context_lock(struct spi_context *ctx,
|
||||||
bool asynchronous,
|
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);
|
k_sem_take(&ctx->lock, K_FOREVER);
|
||||||
|
ctx->owner = spi_cfg;
|
||||||
|
|
||||||
#ifdef CONFIG_SPI_ASYNC
|
#ifdef CONFIG_SPI_ASYNC
|
||||||
ctx->asynchronous = asynchronous;
|
ctx->asynchronous = asynchronous;
|
||||||
|
@ -89,10 +98,14 @@ static inline void spi_context_release(struct spi_context *ctx, int status)
|
||||||
|
|
||||||
#ifdef CONFIG_SPI_ASYNC
|
#ifdef CONFIG_SPI_ASYNC
|
||||||
if (!ctx->asynchronous || (status < 0)) {
|
if (!ctx->asynchronous || (status < 0)) {
|
||||||
|
ctx->owner = NULL;
|
||||||
k_sem_give(&ctx->lock);
|
k_sem_give(&ctx->lock);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
if (!(ctx->config->operation & SPI_LOCK_ON)) {
|
||||||
|
ctx->owner = NULL;
|
||||||
k_sem_give(&ctx->lock);
|
k_sem_give(&ctx->lock);
|
||||||
|
}
|
||||||
#endif /* CONFIG_SPI_ASYNC */
|
#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)) {
|
if (!(ctx->config->operation & SPI_LOCK_ON)) {
|
||||||
|
ctx->owner = NULL;
|
||||||
k_sem_give(&ctx->lock);
|
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);
|
_spi_context_cs_control(ctx, false, true);
|
||||||
|
|
||||||
if (!k_sem_count_get(&ctx->lock)) {
|
if (!k_sem_count_get(&ctx->lock)) {
|
||||||
|
ctx->owner = NULL;
|
||||||
k_sem_give(&ctx->lock);
|
k_sem_give(&ctx->lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -342,7 +342,7 @@ static int transceive(const struct device *dev,
|
||||||
uint32_t reg_data;
|
uint32_t reg_data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
spi_context_lock(&spi->ctx, asynchronous, signal);
|
spi_context_lock(&spi->ctx, asynchronous, signal, config);
|
||||||
|
|
||||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||||
if (device_busy_check(dev) != (-EBUSY)) {
|
if (device_busy_check(dev) != (-EBUSY)) {
|
||||||
|
|
|
@ -575,7 +575,7 @@ static int transceive(const struct device *dev,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
spi_context_lock(&data->ctx, asynchronous, signal);
|
spi_context_lock(&data->ctx, asynchronous, signal, config);
|
||||||
|
|
||||||
ret = spi_stm32_configure(dev, config);
|
ret = spi_stm32_configure(dev, config);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -671,7 +671,7 @@ static int transceive_dma(const struct device *dev,
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
spi_context_lock(&data->ctx, asynchronous, signal);
|
spi_context_lock(&data->ctx, asynchronous, signal, config);
|
||||||
|
|
||||||
k_sem_reset(&data->status_sem);
|
k_sem_reset(&data->status_sem);
|
||||||
|
|
||||||
|
|
|
@ -214,7 +214,7 @@ static int transceive(const struct device *dev,
|
||||||
struct spi_mcux_data *data = dev->data;
|
struct spi_mcux_data *data = dev->data;
|
||||||
int ret;
|
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);
|
ret = spi_mcux_configure(dev, spi_cfg);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
|
@ -622,7 +622,7 @@ static int transceive(const struct device *dev,
|
||||||
struct spi_mcux_data *data = dev->data;
|
struct spi_mcux_data *data = dev->data;
|
||||||
int ret;
|
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);
|
ret = spi_mcux_configure(dev, spi_cfg);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
|
@ -213,7 +213,7 @@ static int transceive(const struct device *dev,
|
||||||
struct spi_mcux_data *data = dev->data;
|
struct spi_mcux_data *data = dev->data;
|
||||||
int ret;
|
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);
|
ret = spi_mcux_configure(dev, spi_cfg);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
|
@ -180,7 +180,7 @@ static int transceive(const struct device *dev,
|
||||||
struct spi_nrfx_data *dev_data = get_dev_data(dev);
|
struct spi_nrfx_data *dev_data = get_dev_data(dev);
|
||||||
int error;
|
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);
|
error = configure(dev, spi_cfg);
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
|
|
|
@ -222,7 +222,7 @@ static int transceive(const struct device *dev,
|
||||||
struct spi_nrfx_data *dev_data = get_dev_data(dev);
|
struct spi_nrfx_data *dev_data = get_dev_data(dev);
|
||||||
int error;
|
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);
|
error = configure(dev, spi_cfg);
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
|
|
|
@ -151,7 +151,7 @@ static int transceive(const struct device *dev,
|
||||||
struct spi_nrfx_data *dev_data = get_dev_data(dev);
|
struct spi_nrfx_data *dev_data = get_dev_data(dev);
|
||||||
int error;
|
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);
|
error = configure(dev, spi_cfg);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
|
|
|
@ -100,7 +100,7 @@ int spi_oc_simple_transceive(const struct device *dev,
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Lock the SPI Context */
|
/* Lock the SPI Context */
|
||||||
spi_context_lock(ctx, false, NULL);
|
spi_context_lock(ctx, false, NULL, config);
|
||||||
|
|
||||||
spi_oc_simple_configure(info, spi, 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;
|
struct spi_mcux_data *data = dev->data;
|
||||||
int ret;
|
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);
|
ret = spi_mcux_configure(dev, spi_cfg);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
|
@ -366,7 +366,7 @@ static int spi_sam_transceive(const struct device *dev,
|
||||||
Spi *regs = cfg->regs;
|
Spi *regs = cfg->regs;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
spi_context_lock(&data->ctx, false, NULL);
|
spi_context_lock(&data->ctx, false, NULL, config);
|
||||||
|
|
||||||
err = spi_sam_configure(dev, config);
|
err = spi_sam_configure(dev, config);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
|
|
@ -396,7 +396,7 @@ static int spi_sam0_transceive(const struct device *dev,
|
||||||
SercomSpi *regs = cfg->regs;
|
SercomSpi *regs = cfg->regs;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
spi_context_lock(&data->ctx, false, NULL);
|
spi_context_lock(&data->ctx, false, NULL, config);
|
||||||
|
|
||||||
err = spi_sam0_configure(dev, config);
|
err = spi_sam0_configure(dev, config);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
@ -638,7 +638,7 @@ static int spi_sam0_transceive_async(const struct device *dev,
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
spi_context_lock(&data->ctx, true, async);
|
spi_context_lock(&data->ctx, true, async, config);
|
||||||
|
|
||||||
retval = spi_sam0_configure(dev, config);
|
retval = spi_sam0_configure(dev, config);
|
||||||
if (retval != 0) {
|
if (retval != 0) {
|
||||||
|
|
|
@ -168,7 +168,7 @@ int spi_sifive_transceive(const struct device *dev,
|
||||||
bool hw_cs_control = false;
|
bool hw_cs_control = false;
|
||||||
|
|
||||||
/* Lock the SPI Context */
|
/* 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 */
|
/* Configure the SPI bus */
|
||||||
SPI_DATA(dev)->ctx.config = config;
|
SPI_DATA(dev)->ctx.config = config;
|
||||||
|
|
|
@ -517,7 +517,7 @@ static int qmspi_transceive(const struct device *dev,
|
||||||
uint32_t descr, last_didx;
|
uint32_t descr, last_didx;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
spi_context_lock(&data->ctx, false, NULL);
|
spi_context_lock(&data->ctx, false, NULL, config);
|
||||||
|
|
||||||
err = qmspi_configure(dev, config);
|
err = qmspi_configure(dev, config);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
|
|
@ -321,7 +321,7 @@ static int xlnx_quadspi_transceive(const struct device *dev,
|
||||||
struct spi_context *ctx = &data->ctx;
|
struct spi_context *ctx = &data->ctx;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
spi_context_lock(ctx, async, signal);
|
spi_context_lock(ctx, async, signal, spi_cfg);
|
||||||
|
|
||||||
ret = xlnx_quadspi_configure(dev, spi_cfg);
|
ret = xlnx_quadspi_configure(dev, spi_cfg);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue