|
@@ -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 */
|
|
|
|