summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c147
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c8
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h5
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c6
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c11
5 files changed, 103 insertions, 74 deletions
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 96dabbd2f004..9b4bbeea3d4f 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -187,7 +187,6 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
int result = 0;
if (power_on) {
- /* Already under indio-dev->mlock mutex */
if (!st->powerup_count)
result = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
if (!result)
@@ -298,50 +297,37 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
int result;
ret = IIO_VAL_INT;
- result = 0;
- mutex_lock(&indio_dev->mlock);
- if (!st->chip_config.enable) {
- result = inv_mpu6050_set_power_itg(st, true);
- if (result)
- goto error_read_raw;
- }
- /* when enable is on, power is already on */
+ mutex_lock(&st->lock);
+ result = iio_device_claim_direct_mode(indio_dev);
+ if (result)
+ goto error_read_raw_unlock;
+ result = inv_mpu6050_set_power_itg(st, true);
+ if (result)
+ goto error_read_raw_release;
switch (chan->type) {
case IIO_ANGL_VEL:
- if (!st->chip_config.gyro_fifo_enable ||
- !st->chip_config.enable) {
- result = inv_mpu6050_switch_engine(st, true,
- INV_MPU6050_BIT_PWR_GYRO_STBY);
- if (result)
- goto error_read_raw;
- }
+ result = inv_mpu6050_switch_engine(st, true,
+ INV_MPU6050_BIT_PWR_GYRO_STBY);
+ if (result)
+ goto error_read_raw_power_off;
ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro,
chan->channel2, val);
- if (!st->chip_config.gyro_fifo_enable ||
- !st->chip_config.enable) {
- result = inv_mpu6050_switch_engine(st, false,
- INV_MPU6050_BIT_PWR_GYRO_STBY);
- if (result)
- goto error_read_raw;
- }
+ result = inv_mpu6050_switch_engine(st, false,
+ INV_MPU6050_BIT_PWR_GYRO_STBY);
+ if (result)
+ goto error_read_raw_power_off;
break;
case IIO_ACCEL:
- if (!st->chip_config.accl_fifo_enable ||
- !st->chip_config.enable) {
- result = inv_mpu6050_switch_engine(st, true,
- INV_MPU6050_BIT_PWR_ACCL_STBY);
- if (result)
- goto error_read_raw;
- }
+ result = inv_mpu6050_switch_engine(st, true,
+ INV_MPU6050_BIT_PWR_ACCL_STBY);
+ if (result)
+ goto error_read_raw_power_off;
ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl,
chan->channel2, val);
- if (!st->chip_config.accl_fifo_enable ||
- !st->chip_config.enable) {
- result = inv_mpu6050_switch_engine(st, false,
- INV_MPU6050_BIT_PWR_ACCL_STBY);
- if (result)
- goto error_read_raw;
- }
+ result = inv_mpu6050_switch_engine(st, false,
+ INV_MPU6050_BIT_PWR_ACCL_STBY);
+ if (result)
+ goto error_read_raw_power_off;
break;
case IIO_TEMP:
/* wait for stablization */
@@ -353,10 +339,12 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
ret = -EINVAL;
break;
}
-error_read_raw:
- if (!st->chip_config.enable)
- result |= inv_mpu6050_set_power_itg(st, false);
- mutex_unlock(&indio_dev->mlock);
+error_read_raw_power_off:
+ result |= inv_mpu6050_set_power_itg(st, false);
+error_read_raw_release:
+ iio_device_release_direct_mode(indio_dev);
+error_read_raw_unlock:
+ mutex_unlock(&st->lock);
if (result)
return result;
@@ -365,13 +353,17 @@ error_read_raw:
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_ANGL_VEL:
+ mutex_lock(&st->lock);
*val = 0;
*val2 = gyro_scale_6050[st->chip_config.fsr];
+ mutex_unlock(&st->lock);
return IIO_VAL_INT_PLUS_NANO;
case IIO_ACCEL:
+ mutex_lock(&st->lock);
*val = 0;
*val2 = accel_scale[st->chip_config.accl_fs];
+ mutex_unlock(&st->lock);
return IIO_VAL_INT_PLUS_MICRO;
case IIO_TEMP:
@@ -394,12 +386,16 @@ error_read_raw:
case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) {
case IIO_ANGL_VEL:
+ mutex_lock(&st->lock);
ret = inv_mpu6050_sensor_show(st, st->reg->gyro_offset,
chan->channel2, val);
+ mutex_unlock(&st->lock);
return IIO_VAL_INT;
case IIO_ACCEL:
+ mutex_lock(&st->lock);
ret = inv_mpu6050_sensor_show(st, st->reg->accl_offset,
chan->channel2, val);
+ mutex_unlock(&st->lock);
return IIO_VAL_INT;
default:
@@ -475,18 +471,17 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
struct inv_mpu6050_state *st = iio_priv(indio_dev);
int result;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
/*
* we should only update scale when the chip is disabled, i.e.
* not running
*/
- if (st->chip_config.enable) {
- result = -EBUSY;
- goto error_write_raw;
- }
+ result = iio_device_claim_direct_mode(indio_dev);
+ if (result)
+ goto error_write_raw_unlock;
result = inv_mpu6050_set_power_itg(st, true);
if (result)
- goto error_write_raw;
+ goto error_write_raw_release;
switch (mask) {
case IIO_CHAN_INFO_SCALE:
@@ -522,9 +517,11 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
break;
}
-error_write_raw:
result |= inv_mpu6050_set_power_itg(st, false);
- mutex_unlock(&indio_dev->mlock);
+error_write_raw_release:
+ iio_device_release_direct_mode(indio_dev);
+error_write_raw_unlock:
+ mutex_unlock(&st->lock);
return result;
}
@@ -578,31 +575,35 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr,
if (fifo_rate < INV_MPU6050_MIN_FIFO_RATE ||
fifo_rate > INV_MPU6050_MAX_FIFO_RATE)
return -EINVAL;
- if (fifo_rate == st->chip_config.fifo_rate)
- return count;
- mutex_lock(&indio_dev->mlock);
- if (st->chip_config.enable) {
- result = -EBUSY;
- goto fifo_rate_fail;
+ mutex_lock(&st->lock);
+ if (fifo_rate == st->chip_config.fifo_rate) {
+ result = 0;
+ goto fifo_rate_fail_unlock;
}
+ result = iio_device_claim_direct_mode(indio_dev);
+ if (result)
+ goto fifo_rate_fail_unlock;
result = inv_mpu6050_set_power_itg(st, true);
if (result)
- goto fifo_rate_fail;
+ goto fifo_rate_fail_release;
d = INV_MPU6050_ONE_K_HZ / fifo_rate - 1;
result = regmap_write(st->map, st->reg->sample_rate_div, d);
if (result)
- goto fifo_rate_fail;
+ goto fifo_rate_fail_power_off;
st->chip_config.fifo_rate = fifo_rate;
result = inv_mpu6050_set_lpf(st, fifo_rate);
if (result)
- goto fifo_rate_fail;
+ goto fifo_rate_fail_power_off;
-fifo_rate_fail:
+fifo_rate_fail_power_off:
result |= inv_mpu6050_set_power_itg(st, false);
- mutex_unlock(&indio_dev->mlock);
+fifo_rate_fail_release:
+ iio_device_release_direct_mode(indio_dev);
+fifo_rate_fail_unlock:
+ mutex_unlock(&st->lock);
if (result)
return result;
@@ -617,8 +618,13 @@ inv_fifo_rate_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev));
+ unsigned fifo_rate;
+
+ mutex_lock(&st->lock);
+ fifo_rate = st->chip_config.fifo_rate;
+ mutex_unlock(&st->lock);
- return sprintf(buf, "%d\n", st->chip_config.fifo_rate);
+ return scnprintf(buf, PAGE_SIZE, "%u\n", fifo_rate);
}
/**
@@ -836,6 +842,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
return -ENODEV;
}
st = iio_priv(indio_dev);
+ mutex_init(&st->lock);
st->chip_type = chip_type;
st->powerup_count = 0;
st->irq = irq;
@@ -929,12 +936,26 @@ EXPORT_SYMBOL_GPL(inv_mpu_core_remove);
static int inv_mpu_resume(struct device *dev)
{
- return inv_mpu6050_set_power_itg(iio_priv(dev_get_drvdata(dev)), true);
+ struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));
+ int result;
+
+ mutex_lock(&st->lock);
+ result = inv_mpu6050_set_power_itg(st, true);
+ mutex_unlock(&st->lock);
+
+ return result;
}
static int inv_mpu_suspend(struct device *dev)
{
- return inv_mpu6050_set_power_itg(iio_priv(dev_get_drvdata(dev)), false);
+ struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));
+ int result;
+
+ mutex_lock(&st->lock);
+ result = inv_mpu6050_set_power_itg(st, false);
+ mutex_unlock(&st->lock);
+
+ return result;
}
#endif /* CONFIG_PM_SLEEP */
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index 64b5f5b92200..fcd7a92b6cf8 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -32,7 +32,7 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
int ret = 0;
/* Use the same mutex which was used everywhere to protect power-op */
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
if (!st->powerup_count) {
ret = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
if (ret)
@@ -48,7 +48,7 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
INV_MPU6050_BIT_BYPASS_EN);
}
write_error:
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -58,14 +58,14 @@ static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id)
struct iio_dev *indio_dev = i2c_mux_priv(muxc);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
/* It doesn't really mattter, if any of the calls fails */
regmap_write(st->map, st->reg->int_pin_cfg, INV_MPU6050_INT_PIN_CFG);
st->powerup_count--;
if (!st->powerup_count)
regmap_write(st->map, st->reg->pwr_mgmt_1,
INV_MPU6050_BIT_SLEEP);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return 0;
}
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index ef13de7a2c20..713fa7b06e08 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -14,6 +14,7 @@
#include <linux/i2c-mux.h>
#include <linux/kfifo.h>
#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/regmap.h>
@@ -80,7 +81,6 @@ enum inv_devices {
* @fsr: Full scale range.
* @lpf: Digital low pass filter frequency.
* @accl_fs: accel full scale range.
- * @enable: master enable state.
* @accl_fifo_enable: enable accel data output
* @gyro_fifo_enable: enable gyro data output
* @fifo_rate: FIFO update rate.
@@ -89,7 +89,6 @@ struct inv_mpu6050_chip_config {
unsigned int fsr:2;
unsigned int lpf:3;
unsigned int accl_fs:2;
- unsigned int enable:1;
unsigned int accl_fifo_enable:1;
unsigned int gyro_fifo_enable:1;
u16 fifo_rate;
@@ -112,6 +111,7 @@ struct inv_mpu6050_hw {
/*
* struct inv_mpu6050_state - Driver state variables.
* @TIMESTAMP_FIFO_SIZE: fifo size for timestamp.
+ * @lock: Chip access lock.
* @trig: IIO trigger.
* @chip_config: Cached attribute information.
* @reg: Map of important registers.
@@ -126,6 +126,7 @@ struct inv_mpu6050_hw {
*/
struct inv_mpu6050_state {
#define TIMESTAMP_FIFO_SIZE 16
+ struct mutex lock;
struct iio_trigger *trig;
struct inv_mpu6050_chip_config chip_config;
const struct inv_mpu6050_reg_map *reg;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
index 3a9f3eac91ab..ff81c6aa009d 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
@@ -128,7 +128,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
u16 fifo_count;
s64 timestamp;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
if (!(st->chip_config.accl_fifo_enable |
st->chip_config.gyro_fifo_enable))
goto end_session;
@@ -178,7 +178,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
}
end_session:
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
@@ -186,7 +186,7 @@ end_session:
flush_fifo:
/* Flush HW and SW FIFOs. */
inv_reset_fifo(indio_dev);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index e8818d4dd4b8..540070f0a230 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -90,7 +90,6 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
if (result)
return result;
}
- st->chip_config.enable = enable;
return 0;
}
@@ -103,7 +102,15 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
static int inv_mpu_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
- return inv_mpu6050_set_enable(iio_trigger_get_drvdata(trig), state);
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct inv_mpu6050_state *st = iio_priv(indio_dev);
+ int result;
+
+ mutex_lock(&st->lock);
+ result = inv_mpu6050_set_enable(indio_dev, state);
+ mutex_unlock(&st->lock);
+
+ return result;
}
static const struct iio_trigger_ops inv_mpu_trigger_ops = {