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: Alexandru Ardelean <alexandru.ardelean@analog.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
committed by
Jonathan Cameron
parent
c5485a5d6a
commit
ce476cd18a
@@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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[] = {
|
|||||||
[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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
*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);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
ret /= adis16400_3db_divisors[val16 & 0x07];
|
ret /= adis16400_3db_divisors[val16 & 0x07];
|
||||||
*val = ret / 1000;
|
*val = ret / 1000;
|
||||||
*val2 = (ret % 1000) * 1000;
|
*val2 = (ret % 1000) * 1000;
|
||||||
}
|
|
||||||
mutex_unlock(&indio_dev->mlock);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user