Commit ce476cd1 authored by Alexandru Ardelean's avatar Alexandru Ardelean Committed by Jonathan Cameron

iio: imu: adis16400: rework locks using ADIS library's state lock

This change removes the use of indio_dev's mlock in favor using the state
lock from the ADIS library.

The set_freq() & get_freq() hooks are unlocked, so they require specific
locking. That is because in some cases the get_freq() hook is used in
combination with adis16400_set_filter().

In cases where only one read/write is done, the functions that hold the
state lock are used.
Signed-off-by: default avatarAlexandru Ardelean <alexandru.ardelean@analog.com>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent c5485a5d
...@@ -162,6 +162,7 @@ struct adis16400_chip_info { ...@@ -162,6 +162,7 @@ struct adis16400_chip_info {
unsigned int accel_scale_micro; unsigned int accel_scale_micro;
int temp_scale_nano; int temp_scale_nano;
int temp_offset; int temp_offset;
/* set_freq() & get_freq() need to avoid using ADIS lib's state lock */
int (*set_freq)(struct adis16400_state *st, unsigned int freq); int (*set_freq)(struct adis16400_state *st, unsigned int freq);
int (*get_freq)(struct adis16400_state *st); int (*get_freq)(struct adis16400_state *st);
}; };
...@@ -326,7 +327,7 @@ static int adis16334_get_freq(struct adis16400_state *st) ...@@ -326,7 +327,7 @@ static int adis16334_get_freq(struct adis16400_state *st)
int ret; int ret;
uint16_t t; uint16_t t;
ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); ret = __adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t);
if (ret) if (ret)
return ret; return ret;
...@@ -350,7 +351,7 @@ static int adis16334_set_freq(struct adis16400_state *st, unsigned int freq) ...@@ -350,7 +351,7 @@ static int adis16334_set_freq(struct adis16400_state *st, unsigned int freq)
t <<= ADIS16334_RATE_DIV_SHIFT; t <<= ADIS16334_RATE_DIV_SHIFT;
t |= ADIS16334_RATE_INT_CLK; t |= ADIS16334_RATE_INT_CLK;
return adis_write_reg_16(&st->adis, ADIS16400_SMPL_PRD, t); return __adis_write_reg_16(&st->adis, ADIS16400_SMPL_PRD, t);
} }
static int adis16400_get_freq(struct adis16400_state *st) static int adis16400_get_freq(struct adis16400_state *st)
...@@ -358,7 +359,7 @@ static int adis16400_get_freq(struct adis16400_state *st) ...@@ -358,7 +359,7 @@ static int adis16400_get_freq(struct adis16400_state *st)
int sps, ret; int sps, ret;
uint16_t t; uint16_t t;
ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); ret = __adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t);
if (ret) if (ret)
return ret; return ret;
...@@ -390,7 +391,7 @@ static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq) ...@@ -390,7 +391,7 @@ static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq)
else else
st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST; st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST;
return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val); return __adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val);
} }
static const unsigned int adis16400_3db_divisors[] = { static const unsigned int adis16400_3db_divisors[] = {
...@@ -404,7 +405,7 @@ static const unsigned int adis16400_3db_divisors[] = { ...@@ -404,7 +405,7 @@ static const unsigned int adis16400_3db_divisors[] = {
[7] = 200, /* Not a valid setting */ [7] = 200, /* Not a valid setting */
}; };
static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) static int __adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val)
{ {
struct adis16400_state *st = iio_priv(indio_dev); struct adis16400_state *st = iio_priv(indio_dev);
uint16_t val16; uint16_t val16;
...@@ -415,11 +416,11 @@ static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) ...@@ -415,11 +416,11 @@ static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val)
break; break;
} }
ret = adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16); ret = __adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16);
if (ret) if (ret)
return ret; return ret;
ret = adis_write_reg_16(&st->adis, ADIS16400_SENS_AVG, ret = __adis_write_reg_16(&st->adis, ADIS16400_SENS_AVG,
(val16 & ~0x07) | i); (val16 & ~0x07) | i);
return ret; return ret;
} }
...@@ -507,32 +508,31 @@ static int adis16400_write_raw(struct iio_dev *indio_dev, ...@@ -507,32 +508,31 @@ static int adis16400_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int val, int val2, long info) struct iio_chan_spec const *chan, int val, int val2, long info)
{ {
struct adis16400_state *st = iio_priv(indio_dev); struct adis16400_state *st = iio_priv(indio_dev);
struct mutex *slock = &st->adis.state_lock;
int ret, sps; int ret, sps;
switch (info) { switch (info) {
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
mutex_lock(&indio_dev->mlock);
ret = adis_write_reg_16(&st->adis, ret = adis_write_reg_16(&st->adis,
adis16400_addresses[chan->scan_index], val); adis16400_addresses[chan->scan_index], val);
mutex_unlock(&indio_dev->mlock);
return ret; return ret;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
/* /*
* Need to cache values so we can update if the frequency * Need to cache values so we can update if the frequency
* changes. * changes.
*/ */
mutex_lock(&indio_dev->mlock); mutex_lock(slock);
st->filt_int = val; st->filt_int = val;
/* Work out update to current value */ /* Work out update to current value */
sps = st->variant->get_freq(st); sps = st->variant->get_freq(st);
if (sps < 0) { if (sps < 0) {
mutex_unlock(&indio_dev->mlock); mutex_unlock(slock);
return sps; return sps;
} }
ret = adis16400_set_filter(indio_dev, sps, ret = __adis16400_set_filter(indio_dev, sps,
val * 1000 + val2 / 1000); val * 1000 + val2 / 1000);
mutex_unlock(&indio_dev->mlock); mutex_unlock(slock);
return ret; return ret;
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
sps = val * 1000 + val2 / 1000; sps = val * 1000 + val2 / 1000;
...@@ -540,9 +540,9 @@ static int adis16400_write_raw(struct iio_dev *indio_dev, ...@@ -540,9 +540,9 @@ static int adis16400_write_raw(struct iio_dev *indio_dev,
if (sps <= 0) if (sps <= 0)
return -EINVAL; return -EINVAL;
mutex_lock(&indio_dev->mlock); mutex_lock(slock);
ret = st->variant->set_freq(st, sps); ret = st->variant->set_freq(st, sps);
mutex_unlock(&indio_dev->mlock); mutex_unlock(slock);
return ret; return ret;
default: default:
return -EINVAL; return -EINVAL;
...@@ -553,6 +553,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, ...@@ -553,6 +553,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long info) struct iio_chan_spec const *chan, int *val, int *val2, long info)
{ {
struct adis16400_state *st = iio_priv(indio_dev); struct adis16400_state *st = iio_priv(indio_dev);
struct mutex *slock = &st->adis.state_lock;
int16_t val16; int16_t val16;
int ret; int ret;
...@@ -596,10 +597,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, ...@@ -596,10 +597,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
return -EINVAL; return -EINVAL;
} }
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
mutex_lock(&indio_dev->mlock);
ret = adis_read_reg_16(&st->adis, ret = adis_read_reg_16(&st->adis,
adis16400_addresses[chan->scan_index], &val16); adis16400_addresses[chan->scan_index], &val16);
mutex_unlock(&indio_dev->mlock);
if (ret) if (ret)
return ret; return ret;
val16 = sign_extend32(val16, 11); val16 = sign_extend32(val16, 11);
...@@ -610,27 +609,27 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, ...@@ -610,27 +609,27 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
*val = st->variant->temp_offset; *val = st->variant->temp_offset;
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
mutex_lock(&indio_dev->mlock); mutex_lock(slock);
/* Need both the number of taps and the sampling frequency */ /* Need both the number of taps and the sampling frequency */
ret = adis_read_reg_16(&st->adis, ret = __adis_read_reg_16(&st->adis,
ADIS16400_SENS_AVG, ADIS16400_SENS_AVG,
&val16); &val16);
if (ret) { if (ret) {
mutex_unlock(&indio_dev->mlock); mutex_unlock(slock);
return ret; return ret;
} }
ret = st->variant->get_freq(st); ret = st->variant->get_freq(st);
if (ret >= 0) { mutex_unlock(slock);
ret /= adis16400_3db_divisors[val16 & 0x07];
*val = ret / 1000;
*val2 = (ret % 1000) * 1000;
}
mutex_unlock(&indio_dev->mlock);
if (ret) if (ret)
return ret; return ret;
ret /= adis16400_3db_divisors[val16 & 0x07];
*val = ret / 1000;
*val2 = (ret % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO; return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
mutex_lock(slock);
ret = st->variant->get_freq(st); ret = st->variant->get_freq(st);
mutex_unlock(slock);
if (ret) if (ret)
return ret; return ret;
*val = ret / 1000; *val = ret / 1000;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment