Skip to content

Commit

Permalink
iio: ad_sigma_delta: Properly handle SPI bus locking vs CS assertion
Browse files Browse the repository at this point in the history
For devices from the SigmaDelta family we need to keep CS low when doing a
conversion, since the device will use the MISO line as a interrupt to
indicate that the conversion is complete.

This is why the driver locks the SPI bus and when the SPI bus is locked
keeps as long as a conversion is going on. The current implementation gets
one small detail wrong though. CS is only de-asserted after the SPI bus is
unlocked. This means it is possible for a different SPI device on the same
bus to send a message which would be wrongfully be addressed to the
SigmaDelta device as well. Make sure that the last SPI transfer that is
done while holding the SPI bus lock de-asserts the CS signal.

Signed-off-by: Lars-Peter Clausen <[email protected]>
Signed-off-by: Alexandru Ardelean <[email protected]>
Signed-off-by: Jonathan Cameron <[email protected]>
  • Loading branch information
larsclausen authored and jic23 committed Apr 4, 2019
1 parent 6ec417d commit df1d80a
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 5 deletions.
16 changes: 11 additions & 5 deletions drivers/iio/adc/ad_sigma_delta.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
struct spi_transfer t = {
.tx_buf = data,
.len = size + 1,
.cs_change = sigma_delta->bus_locked,
.cs_change = sigma_delta->keep_cs_asserted,
};
struct spi_message m;
int ret;
Expand Down Expand Up @@ -217,6 +217,7 @@ static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,

spi_bus_lock(sigma_delta->spi->master);
sigma_delta->bus_locked = true;
sigma_delta->keep_cs_asserted = true;
reinit_completion(&sigma_delta->completion);

ret = ad_sigma_delta_set_mode(sigma_delta, mode);
Expand All @@ -234,9 +235,10 @@ static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
ret = 0;
}
out:
sigma_delta->keep_cs_asserted = false;
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
sigma_delta->bus_locked = false;
spi_bus_unlock(sigma_delta->spi->master);
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);

return ret;
}
Expand Down Expand Up @@ -289,6 +291,7 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,

spi_bus_lock(sigma_delta->spi->master);
sigma_delta->bus_locked = true;
sigma_delta->keep_cs_asserted = true;
reinit_completion(&sigma_delta->completion);

ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_SINGLE);
Expand All @@ -298,9 +301,6 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
ret = wait_for_completion_interruptible_timeout(
&sigma_delta->completion, HZ);

sigma_delta->bus_locked = false;
spi_bus_unlock(sigma_delta->spi->master);

if (ret == 0)
ret = -EIO;
if (ret < 0)
Expand All @@ -321,7 +321,10 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
sigma_delta->irq_dis = true;
}

sigma_delta->keep_cs_asserted = false;
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
sigma_delta->bus_locked = false;
spi_bus_unlock(sigma_delta->spi->master);
mutex_unlock(&indio_dev->mlock);

if (ret)
Expand Down Expand Up @@ -358,6 +361,8 @@ static int ad_sd_buffer_postenable(struct iio_dev *indio_dev)

spi_bus_lock(sigma_delta->spi->master);
sigma_delta->bus_locked = true;
sigma_delta->keep_cs_asserted = true;

ret = ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_CONTINUOUS);
if (ret)
goto err_unlock;
Expand Down Expand Up @@ -386,6 +391,7 @@ static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev)
sigma_delta->irq_dis = true;
}

sigma_delta->keep_cs_asserted = false;
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);

sigma_delta->bus_locked = false;
Expand Down
1 change: 1 addition & 0 deletions include/linux/iio/adc/ad_sigma_delta.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ struct ad_sigma_delta {
bool irq_dis;

bool bus_locked;
bool keep_cs_asserted;

uint8_t comm;

Expand Down

0 comments on commit df1d80a

Please sign in to comment.