From: Jonathan Cameron <jic23@kernel.org>
To: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
Cc: linux-iio@vger.kernel.org
Subject: Re: [PATCH 08/13] iio: imu: inv_mpu6050: rewrite power and engine management
Date: Sat, 15 Feb 2020 18:09:30 +0000 [thread overview]
Message-ID: <20200215180930.5ebecddc@archlinux> (raw)
In-Reply-To: <20200212174048.1034-9-jmaneyrol@invensense.com>
On Wed, 12 Feb 2020 18:40:43 +0100
Jean-Baptiste Maneyrol <jmaneyrol@invensense.com> wrote:
> Rewrite clock management to use automatic clock switching
> present since MPU6500.
> Sensors engine management can now turn on or off a batch of
> sensors which simplifies usage a lot.
> Temperature sensor is now turned on/off depending on usage.
>
> Signed-off-by: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
At the fairly superficial level at which I'm reading this it all
looks fine. I suspect I'll not go into this in enough detail to
understand it properly. Will apply once the rest are ready to
go.
Thanks,
Jonathan
> ---
> drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 264 +++++++++++++-----
> drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 24 +-
> drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c | 12 +-
> drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h | 2 +-
> drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 91 +++---
> 5 files changed, 262 insertions(+), 131 deletions(-)
>
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> index 63cdde20df7e..a51efc4c941b 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> @@ -99,9 +99,31 @@ static const struct inv_mpu6050_reg_map reg_set_6050 = {
> };
>
> static const struct inv_mpu6050_chip_config chip_config_6050 = {
> + .clk = INV_CLK_INTERNAL,
> .fsr = INV_MPU6050_FSR_2000DPS,
> .lpf = INV_MPU6050_FILTER_20HZ,
> .divider = INV_MPU6050_FIFO_RATE_TO_DIVIDER(50),
> + .gyro_en = true,
> + .accl_en = true,
> + .temp_en = true,
> + .magn_en = false,
> + .gyro_fifo_enable = false,
> + .accl_fifo_enable = false,
> + .temp_fifo_enable = false,
> + .magn_fifo_enable = false,
> + .accl_fs = INV_MPU6050_FS_02G,
> + .user_ctrl = 0,
> +};
> +
> +static const struct inv_mpu6050_chip_config chip_config_6500 = {
> + .clk = INV_CLK_PLL,
> + .fsr = INV_MPU6050_FSR_2000DPS,
> + .lpf = INV_MPU6050_FILTER_20HZ,
> + .divider = INV_MPU6050_FIFO_RATE_TO_DIVIDER(50),
> + .gyro_en = true,
> + .accl_en = true,
> + .temp_en = true,
> + .magn_en = false,
> .gyro_fifo_enable = false,
> .accl_fifo_enable = false,
> .temp_fifo_enable = false,
> @@ -124,7 +146,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
> .whoami = INV_MPU6500_WHOAMI_VALUE,
> .name = "MPU6500",
> .reg = ®_set_6500,
> - .config = &chip_config_6050,
> + .config = &chip_config_6500,
> .fifo_size = 512,
> .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
> },
> @@ -132,7 +154,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
> .whoami = INV_MPU6515_WHOAMI_VALUE,
> .name = "MPU6515",
> .reg = ®_set_6500,
> - .config = &chip_config_6050,
> + .config = &chip_config_6500,
> .fifo_size = 512,
> .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
> },
> @@ -156,7 +178,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
> .whoami = INV_MPU9250_WHOAMI_VALUE,
> .name = "MPU9250",
> .reg = ®_set_6500,
> - .config = &chip_config_6050,
> + .config = &chip_config_6500,
> .fifo_size = 512,
> .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
> },
> @@ -164,7 +186,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
> .whoami = INV_MPU9255_WHOAMI_VALUE,
> .name = "MPU9255",
> .reg = ®_set_6500,
> - .config = &chip_config_6050,
> + .config = &chip_config_6500,
> .fifo_size = 512,
> .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
> },
> @@ -172,7 +194,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
> .whoami = INV_ICM20608_WHOAMI_VALUE,
> .name = "ICM20608",
> .reg = ®_set_6500,
> - .config = &chip_config_6050,
> + .config = &chip_config_6500,
> .fifo_size = 512,
> .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
> },
> @@ -180,7 +202,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
> .whoami = INV_ICM20609_WHOAMI_VALUE,
> .name = "ICM20609",
> .reg = ®_set_6500,
> - .config = &chip_config_6050,
> + .config = &chip_config_6500,
> .fifo_size = 4 * 1024,
> .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
> },
> @@ -188,7 +210,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
> .whoami = INV_ICM20689_WHOAMI_VALUE,
> .name = "ICM20689",
> .reg = ®_set_6500,
> - .config = &chip_config_6050,
> + .config = &chip_config_6500,
> .fifo_size = 4 * 1024,
> .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
> },
> @@ -196,15 +218,15 @@ static const struct inv_mpu6050_hw hw_info[] = {
> .whoami = INV_ICM20602_WHOAMI_VALUE,
> .name = "ICM20602",
> .reg = ®_set_icm20602,
> - .config = &chip_config_6050,
> + .config = &chip_config_6500,
> .fifo_size = 1008,
> .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
> },
> {
> .whoami = INV_ICM20690_WHOAMI_VALUE,
> .name = "ICM20690",
> - .reg = ®_set_icm20602,
> - .config = &chip_config_6050,
> + .reg = ®_set_6500,
> + .config = &chip_config_6500,
> .fifo_size = 1024,
> .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
> },
> @@ -212,61 +234,162 @@ static const struct inv_mpu6050_hw hw_info[] = {
> .whoami = INV_IAM20680_WHOAMI_VALUE,
> .name = "IAM20680",
> .reg = ®_set_6500,
> - .config = &chip_config_6050,
> + .config = &chip_config_6500,
> .fifo_size = 512,
> .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
> },
> };
>
> -int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
> +static int inv_mpu6050_pwr_mgmt_1_write(struct inv_mpu6050_state *st, bool sleep,
> + int clock, int temp_dis)
> {
> - unsigned int d, mgmt_1;
> - int result;
> - /*
> - * switch clock needs to be careful. Only when gyro is on, can
> - * clock source be switched to gyro. Otherwise, it must be set to
> - * internal clock
> - */
> - if (mask == INV_MPU6050_BIT_PWR_GYRO_STBY) {
> - result = regmap_read(st->map, st->reg->pwr_mgmt_1, &mgmt_1);
> - if (result)
> - return result;
> + u8 val;
> +
> + if (clock < 0)
> + clock = st->chip_config.clk;
> + if (temp_dis < 0)
> + temp_dis = !st->chip_config.temp_en;
> +
> + val = clock & INV_MPU6050_BIT_CLK_MASK;
> + if (temp_dis)
> + val |= INV_MPU6050_BIT_TEMP_DIS;
> + if (sleep)
> + val |= INV_MPU6050_BIT_SLEEP;
> +
> + dev_dbg(regmap_get_device(st->map), "pwr_mgmt_1: 0x%x\n", val);
> + return regmap_write(st->map, st->reg->pwr_mgmt_1, val);
> +}
> +
> +static int inv_mpu6050_clock_switch(struct inv_mpu6050_state *st,
> + unsigned int clock)
> +{
> + int ret;
> +
> + switch (st->chip_type) {
> + case INV_MPU6050:
> + case INV_MPU6000:
> + case INV_MPU9150:
> + /* old chips: switch clock manually */
> + ret = inv_mpu6050_pwr_mgmt_1_write(st, false, clock, -1);
> + if (ret)
> + return ret;
> + st->chip_config.clk = clock;
> + break;
> + default:
> + /* automatic clock switching, nothing to do */
> + break;
> + }
> +
> + return 0;
> +}
>
> - mgmt_1 &= ~INV_MPU6050_BIT_CLK_MASK;
> +int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en,
> + unsigned int mask)
> +{
> + unsigned int sleep;
> + u8 pwr_mgmt2, user_ctrl;
> + int ret;
> +
> + /* delete useless requests */
> + if (mask & INV_MPU6050_SENSOR_ACCL && en == st->chip_config.accl_en)
> + mask &= ~INV_MPU6050_SENSOR_ACCL;
> + if (mask & INV_MPU6050_SENSOR_GYRO && en == st->chip_config.gyro_en)
> + mask &= ~INV_MPU6050_SENSOR_GYRO;
> + if (mask & INV_MPU6050_SENSOR_TEMP && en == st->chip_config.temp_en)
> + mask &= ~INV_MPU6050_SENSOR_TEMP;
> + if (mask & INV_MPU6050_SENSOR_MAGN && en == st->chip_config.magn_en)
> + mask &= ~INV_MPU6050_SENSOR_MAGN;
> + if (mask == 0)
> + return 0;
> +
> + /* turn on/off temperature sensor */
> + if (mask & INV_MPU6050_SENSOR_TEMP) {
> + ret = inv_mpu6050_pwr_mgmt_1_write(st, false, -1, !en);
> + if (ret)
> + return ret;
> + st->chip_config.temp_en = en;
> }
>
> - if ((mask == INV_MPU6050_BIT_PWR_GYRO_STBY) && (!en)) {
> - /*
> - * turning off gyro requires switch to internal clock first.
> - * Then turn off gyro engine
> - */
> - mgmt_1 |= INV_CLK_INTERNAL;
> - result = regmap_write(st->map, st->reg->pwr_mgmt_1, mgmt_1);
> - if (result)
> - return result;
> + /* update user_crtl for driving magnetometer */
> + if (mask & INV_MPU6050_SENSOR_MAGN) {
> + user_ctrl = st->chip_config.user_ctrl;
> + if (en)
> + user_ctrl |= INV_MPU6050_BIT_I2C_MST_EN;
> + else
> + user_ctrl &= ~INV_MPU6050_BIT_I2C_MST_EN;
> + ret = regmap_write(st->map, st->reg->user_ctrl, user_ctrl);
> + if (ret)
> + return ret;
> + st->chip_config.user_ctrl = user_ctrl;
> + st->chip_config.magn_en = en;
> }
>
> - result = regmap_read(st->map, st->reg->pwr_mgmt_2, &d);
> - if (result)
> - return result;
> - if (en)
> - d &= ~mask;
> - else
> - d |= mask;
> - result = regmap_write(st->map, st->reg->pwr_mgmt_2, d);
> - if (result)
> - return result;
> + /* manage accel & gyro engines */
> + if (mask & (INV_MPU6050_SENSOR_ACCL | INV_MPU6050_SENSOR_GYRO)) {
> + /* compute power management 2 current value */
> + pwr_mgmt2 = 0;
> + if (!st->chip_config.accl_en)
> + pwr_mgmt2 |= INV_MPU6050_BIT_PWR_ACCL_STBY;
> + if (!st->chip_config.gyro_en)
> + pwr_mgmt2 |= INV_MPU6050_BIT_PWR_GYRO_STBY;
> +
> + /* update to new requested value */
> + if (mask & INV_MPU6050_SENSOR_ACCL) {
> + if (en)
> + pwr_mgmt2 &= ~INV_MPU6050_BIT_PWR_ACCL_STBY;
> + else
> + pwr_mgmt2 |= INV_MPU6050_BIT_PWR_ACCL_STBY;
> + }
> + if (mask & INV_MPU6050_SENSOR_GYRO) {
> + if (en)
> + pwr_mgmt2 &= ~INV_MPU6050_BIT_PWR_GYRO_STBY;
> + else
> + pwr_mgmt2 |= INV_MPU6050_BIT_PWR_GYRO_STBY;
> + }
>
> - if (en) {
> - /* Wait for output to stabilize */
> - msleep(INV_MPU6050_TEMP_UP_TIME);
> - if (mask == INV_MPU6050_BIT_PWR_GYRO_STBY) {
> - /* switch internal clock to PLL */
> - mgmt_1 |= INV_CLK_PLL;
> - result = regmap_write(st->map,
> - st->reg->pwr_mgmt_1, mgmt_1);
> - if (result)
> - return result;
> + /* switch clock to internal when turning gyro off */
> + if (mask & INV_MPU6050_SENSOR_GYRO && !en) {
> + ret = inv_mpu6050_clock_switch(st, INV_CLK_INTERNAL);
> + if (ret)
> + return ret;
> + }
> +
> + /* update sensors engine */
> + dev_dbg(regmap_get_device(st->map), "pwr_mgmt_2: 0x%x\n",
> + pwr_mgmt2);
> + ret = regmap_write(st->map, st->reg->pwr_mgmt_2, pwr_mgmt2);
> + if (ret)
> + return ret;
> + if (mask & INV_MPU6050_SENSOR_ACCL)
> + st->chip_config.accl_en = en;
> + if (mask & INV_MPU6050_SENSOR_GYRO)
> + st->chip_config.gyro_en = en;
> +
> + /* compute required time to have sensors stabilized */
> + sleep = 0;
> + if (en) {
> + if (mask & INV_MPU6050_SENSOR_ACCL) {
> + if (sleep < INV_MPU6050_ACCEL_UP_TIME)
> + sleep = INV_MPU6050_ACCEL_UP_TIME;
> + }
> + if (mask & INV_MPU6050_SENSOR_GYRO) {
> + if (sleep < INV_MPU6050_GYRO_UP_TIME)
> + sleep = INV_MPU6050_GYRO_UP_TIME;
> + }
> + } else {
> + if (mask & INV_MPU6050_SENSOR_GYRO) {
> + if (sleep < INV_MPU6050_GYRO_DOWN_TIME)
> + sleep = INV_MPU6050_GYRO_DOWN_TIME;
> + }
> + }
> + if (sleep)
> + msleep(sleep);
> +
> + /* switch clock to PLL when turning gyro on */
> + if (mask & INV_MPU6050_SENSOR_GYRO && en) {
> + ret = inv_mpu6050_clock_switch(st, INV_CLK_PLL);
> + if (ret)
> + return ret;
> }
> }
>
> @@ -279,7 +402,7 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
>
> if (power_on) {
> if (!st->powerup_count) {
> - result = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
> + result = inv_mpu6050_pwr_mgmt_1_write(st, false, -1, -1);
> if (result)
> return result;
> usleep_range(INV_MPU6050_REG_UP_TIME_MIN,
> @@ -288,8 +411,7 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
> st->powerup_count++;
> } else {
> if (st->powerup_count == 1) {
> - result = regmap_write(st->map, st->reg->pwr_mgmt_1,
> - INV_MPU6050_BIT_SLEEP);
> + result = inv_mpu6050_pwr_mgmt_1_write(st, true, -1, -1);
> if (result)
> return result;
> }
> @@ -451,33 +573,41 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
> switch (chan->type) {
> case IIO_ANGL_VEL:
> result = inv_mpu6050_switch_engine(st, true,
> - INV_MPU6050_BIT_PWR_GYRO_STBY);
> + INV_MPU6050_SENSOR_GYRO);
> if (result)
> goto error_power_off;
> ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro,
> chan->channel2, val);
> result = inv_mpu6050_switch_engine(st, false,
> - INV_MPU6050_BIT_PWR_GYRO_STBY);
> + INV_MPU6050_SENSOR_GYRO);
> if (result)
> goto error_power_off;
> break;
> case IIO_ACCEL:
> result = inv_mpu6050_switch_engine(st, true,
> - INV_MPU6050_BIT_PWR_ACCL_STBY);
> + INV_MPU6050_SENSOR_ACCL);
> if (result)
> goto error_power_off;
> ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl,
> chan->channel2, val);
> result = inv_mpu6050_switch_engine(st, false,
> - INV_MPU6050_BIT_PWR_ACCL_STBY);
> + INV_MPU6050_SENSOR_ACCL);
> if (result)
> goto error_power_off;
> break;
> case IIO_TEMP:
> + result = inv_mpu6050_switch_engine(st, true,
> + INV_MPU6050_SENSOR_TEMP);
> + if (result)
> + goto error_power_off;
> /* wait for stablization */
> - msleep(INV_MPU6050_SENSOR_UP_TIME);
> + msleep(INV_MPU6050_TEMP_UP_TIME);
> ret = inv_mpu6050_sensor_show(st, st->reg->temperature,
> IIO_MOD_X, val);
> + result = inv_mpu6050_switch_engine(st, false,
> + INV_MPU6050_SENSOR_TEMP);
> + if (result)
> + goto error_power_off;
> break;
> case IIO_MAGN:
> ret = inv_mpu_magn_read(st, chan->channel2, val);
> @@ -1108,7 +1238,7 @@ static const struct iio_info mpu_info = {
> static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
> {
> int result;
> - unsigned int regval;
> + unsigned int regval, mask;
> int i;
>
> st->hw = &hw_info[st->chip_type];
> @@ -1174,13 +1304,9 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
> result = inv_mpu6050_set_power_itg(st, true);
> if (result)
> return result;
> -
> - result = inv_mpu6050_switch_engine(st, false,
> - INV_MPU6050_BIT_PWR_ACCL_STBY);
> - if (result)
> - goto error_power_off;
> - result = inv_mpu6050_switch_engine(st, false,
> - INV_MPU6050_BIT_PWR_GYRO_STBY);
> + mask = INV_MPU6050_SENSOR_ACCL | INV_MPU6050_SENSOR_GYRO |
> + INV_MPU6050_SENSOR_TEMP | INV_MPU6050_SENSOR_MAGN;
> + result = inv_mpu6050_switch_engine(st, false, mask);
> if (result)
> goto error_power_off;
>
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> index 17f1f6a15f95..a578789c9210 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> @@ -83,11 +83,22 @@ enum inv_devices {
> INV_NUM_PARTS
> };
>
> +/* chip sensors mask: accelerometer, gyroscope, temperature, magnetometer */
> +#define INV_MPU6050_SENSOR_ACCL BIT(0)
> +#define INV_MPU6050_SENSOR_GYRO BIT(1)
> +#define INV_MPU6050_SENSOR_TEMP BIT(2)
> +#define INV_MPU6050_SENSOR_MAGN BIT(3)
> +
> /**
> * struct inv_mpu6050_chip_config - Cached chip configuration data.
> + * @clk: selected chip clock
> * @fsr: Full scale range.
> * @lpf: Digital low pass filter frequency.
> * @accl_fs: accel full scale range.
> + * @accl_en: accel engine enabled
> + * @gyro_en: gyro engine enabled
> + * @temp_en: temperature sensor enabled
> + * @magn_en: magn engine (i2c master) enabled
> * @accl_fifo_enable: enable accel data output
> * @gyro_fifo_enable: enable gyro data output
> * @temp_fifo_enable: enable temp data output
> @@ -95,9 +106,14 @@ enum inv_devices {
> * @divider: chip sample rate divider (sample rate divider - 1)
> */
> struct inv_mpu6050_chip_config {
> + unsigned int clk:3;
> unsigned int fsr:2;
> unsigned int lpf:3;
> unsigned int accl_fs:2;
> + unsigned int accl_en:1;
> + unsigned int gyro_en:1;
> + unsigned int temp_en:1;
> + unsigned int magn_en:1;
> unsigned int accl_fifo_enable:1;
> unsigned int gyro_fifo_enable:1;
> unsigned int temp_fifo_enable:1;
> @@ -262,6 +278,7 @@ struct inv_mpu6050_state {
> #define INV_MPU6050_REG_PWR_MGMT_1 0x6B
> #define INV_MPU6050_BIT_H_RESET 0x80
> #define INV_MPU6050_BIT_SLEEP 0x40
> +#define INV_MPU6050_BIT_TEMP_DIS 0x08
> #define INV_MPU6050_BIT_CLK_MASK 0x7
>
> #define INV_MPU6050_REG_PWR_MGMT_2 0x6C
> @@ -292,7 +309,9 @@ struct inv_mpu6050_state {
> /* delay time in milliseconds */
> #define INV_MPU6050_POWER_UP_TIME 100
> #define INV_MPU6050_TEMP_UP_TIME 100
> -#define INV_MPU6050_SENSOR_UP_TIME 30
> +#define INV_MPU6050_ACCEL_UP_TIME 20
> +#define INV_MPU6050_GYRO_UP_TIME 35
> +#define INV_MPU6050_GYRO_DOWN_TIME 150
>
> /* delay time in microseconds */
> #define INV_MPU6050_REG_UP_TIME_MIN 5000
> @@ -417,7 +436,8 @@ enum inv_mpu6050_clock_sel_e {
> irqreturn_t inv_mpu6050_read_fifo(int irq, void *p);
> int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type);
> int inv_reset_fifo(struct iio_dev *indio_dev);
> -int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask);
> +int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en,
> + unsigned int mask);
> int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val);
> int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on);
> int inv_mpu_acpi_create_mux_client(struct i2c_client *client);
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
> index 607104a2631e..3f402fa56d95 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
> @@ -316,9 +316,9 @@ int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st)
> *
> * Returns 0 on success, a negative error code otherwise
> */
> -int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val)
> +int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val)
> {
> - unsigned int user_ctrl, status;
> + unsigned int status;
> __be16 data;
> uint8_t addr;
> unsigned int freq_hz, period_ms;
> @@ -350,16 +350,14 @@ int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val)
> freq_hz = INV_MPU_MAGN_FREQ_HZ_MAX;
> period_ms = 1000 / freq_hz;
>
> - /* start i2c master, wait for xfer, stop */
> - user_ctrl = st->chip_config.user_ctrl | INV_MPU6050_BIT_I2C_MST_EN;
> - ret = regmap_write(st->map, st->reg->user_ctrl, user_ctrl);
> + ret = inv_mpu6050_switch_engine(st, true, INV_MPU6050_SENSOR_MAGN);
> if (ret)
> return ret;
>
> /* need to wait 2 periods + half-period margin */
> msleep(period_ms * 2 + period_ms / 2);
> - user_ctrl = st->chip_config.user_ctrl;
> - ret = regmap_write(st->map, st->reg->user_ctrl, user_ctrl);
> +
> + ret = inv_mpu6050_switch_engine(st, false, INV_MPU6050_SENSOR_MAGN);
> if (ret)
> return ret;
>
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h
> index b41bd0578478..f7ad50ca6c1b 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h
> @@ -31,6 +31,6 @@ int inv_mpu_magn_set_rate(const struct inv_mpu6050_state *st, int fifo_rate);
>
> int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st);
>
> -int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val);
> +int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val);
>
> #endif /* INV_MPU_MAGN_H_ */
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> index 5199fe790c30..cfd7243159f6 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> @@ -5,9 +5,10 @@
>
> #include "inv_mpu_iio.h"
>
> -static void inv_scan_query_mpu6050(struct iio_dev *indio_dev)
> +static unsigned int inv_scan_query_mpu6050(struct iio_dev *indio_dev)
> {
> struct inv_mpu6050_state *st = iio_priv(indio_dev);
> + unsigned int mask;
>
> st->chip_config.gyro_fifo_enable =
> test_bit(INV_MPU6050_SCAN_GYRO_X,
> @@ -27,17 +28,28 @@ static void inv_scan_query_mpu6050(struct iio_dev *indio_dev)
>
> st->chip_config.temp_fifo_enable =
> test_bit(INV_MPU6050_SCAN_TEMP, indio_dev->active_scan_mask);
> +
> + mask = 0;
> + if (st->chip_config.gyro_fifo_enable)
> + mask |= INV_MPU6050_SENSOR_GYRO;
> + if (st->chip_config.accl_fifo_enable)
> + mask |= INV_MPU6050_SENSOR_ACCL;
> + if (st->chip_config.temp_fifo_enable)
> + mask |= INV_MPU6050_SENSOR_TEMP;
> +
> + return mask;
> }
>
> -static void inv_scan_query_mpu9x50(struct iio_dev *indio_dev)
> +static unsigned int inv_scan_query_mpu9x50(struct iio_dev *indio_dev)
> {
> struct inv_mpu6050_state *st = iio_priv(indio_dev);
> + unsigned int mask;
>
> - inv_scan_query_mpu6050(indio_dev);
> + mask = inv_scan_query_mpu6050(indio_dev);
>
> /* no magnetometer if i2c auxiliary bus is used */
> if (st->magn_disabled)
> - return;
> + return mask;
>
> st->chip_config.magn_fifo_enable =
> test_bit(INV_MPU9X50_SCAN_MAGN_X,
> @@ -46,9 +58,13 @@ static void inv_scan_query_mpu9x50(struct iio_dev *indio_dev)
> indio_dev->active_scan_mask) ||
> test_bit(INV_MPU9X50_SCAN_MAGN_Z,
> indio_dev->active_scan_mask);
> + if (st->chip_config.magn_fifo_enable)
> + mask |= INV_MPU6050_SENSOR_MAGN;
> +
> + return mask;
> }
>
> -static void inv_scan_query(struct iio_dev *indio_dev)
> +static unsigned int inv_scan_query(struct iio_dev *indio_dev)
> {
> struct inv_mpu6050_state *st = iio_priv(indio_dev);
>
> @@ -92,62 +108,40 @@ static unsigned int inv_compute_skip_samples(const struct inv_mpu6050_state *st)
> static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
> {
> struct inv_mpu6050_state *st = iio_priv(indio_dev);
> - uint8_t d;
> + unsigned int scan;
> int result;
>
> + scan = inv_scan_query(indio_dev);
> +
> if (enable) {
> result = inv_mpu6050_set_power_itg(st, true);
> if (result)
> return result;
> - inv_scan_query(indio_dev);
> - if (st->chip_config.gyro_fifo_enable) {
> - result = inv_mpu6050_switch_engine(st, true,
> - INV_MPU6050_BIT_PWR_GYRO_STBY);
> - if (result)
> - goto error_power_off;
> - }
> - if (st->chip_config.accl_fifo_enable) {
> - result = inv_mpu6050_switch_engine(st, true,
> - INV_MPU6050_BIT_PWR_ACCL_STBY);
> - if (result)
> - goto error_gyro_off;
> - }
> - if (st->chip_config.magn_fifo_enable) {
> - d = st->chip_config.user_ctrl |
> - INV_MPU6050_BIT_I2C_MST_EN;
> - result = regmap_write(st->map, st->reg->user_ctrl, d);
> - if (result)
> - goto error_accl_off;
> - st->chip_config.user_ctrl = d;
> - }
> + result = inv_mpu6050_switch_engine(st, true, scan);
> + if (result)
> + goto error_power_off;
> st->skip_samples = inv_compute_skip_samples(st);
> result = inv_reset_fifo(indio_dev);
> if (result)
> - goto error_magn_off;
> + goto error_sensors_off;
> } else {
> result = regmap_write(st->map, st->reg->fifo_en, 0);
> if (result)
> - goto error_magn_off;
> + goto error_fifo_off;
>
> result = regmap_write(st->map, st->reg->int_enable, 0);
> if (result)
> - goto error_magn_off;
> -
> - d = st->chip_config.user_ctrl & ~INV_MPU6050_BIT_I2C_MST_EN;
> - result = regmap_write(st->map, st->reg->user_ctrl, d);
> - if (result)
> - goto error_magn_off;
> - st->chip_config.user_ctrl = d;
> + goto error_fifo_off;
>
> - result = inv_mpu6050_switch_engine(st, false,
> - INV_MPU6050_BIT_PWR_ACCL_STBY);
> + /* restore user_ctrl for disabling FIFO reading */
> + result = regmap_write(st->map, st->reg->user_ctrl,
> + st->chip_config.user_ctrl);
> if (result)
> - goto error_accl_off;
> + goto error_sensors_off;
>
> - result = inv_mpu6050_switch_engine(st, false,
> - INV_MPU6050_BIT_PWR_GYRO_STBY);
> + result = inv_mpu6050_switch_engine(st, false, scan);
> if (result)
> - goto error_gyro_off;
> + goto error_power_off;
>
> result = inv_mpu6050_set_power_itg(st, false);
> if (result)
> @@ -156,18 +150,11 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
>
> return 0;
>
> -error_magn_off:
> +error_fifo_off:
> /* always restore user_ctrl to disable fifo properly */
> - st->chip_config.user_ctrl &= ~INV_MPU6050_BIT_I2C_MST_EN;
> regmap_write(st->map, st->reg->user_ctrl, st->chip_config.user_ctrl);
> -error_accl_off:
> - if (st->chip_config.accl_fifo_enable)
> - inv_mpu6050_switch_engine(st, false,
> - INV_MPU6050_BIT_PWR_ACCL_STBY);
> -error_gyro_off:
> - if (st->chip_config.gyro_fifo_enable)
> - inv_mpu6050_switch_engine(st, false,
> - INV_MPU6050_BIT_PWR_GYRO_STBY);
> +error_sensors_off:
> + inv_mpu6050_switch_engine(st, false, scan);
> error_power_off:
> inv_mpu6050_set_power_itg(st, false);
> return result;
next prev parent reply other threads:[~2020-02-15 18:09 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-12 17:40 [PATCH 00/13] Rework sensors engines and power management Jean-Baptiste Maneyrol
2020-02-12 17:40 ` [PATCH 01/13] iio: imu: inv_mpu6050: enable i2c aux mux bypass only once Jean-Baptiste Maneyrol
2020-02-15 17:30 ` Jonathan Cameron
2020-02-18 16:03 ` Jean-Baptiste Maneyrol
2020-02-12 17:40 ` [PATCH 02/13] iio: imu: inv_mpu6050: delete useless check Jean-Baptiste Maneyrol
2020-02-12 17:40 ` [PATCH 03/13] iio: imu: inv_mpu6050: set power on/off only once during all init Jean-Baptiste Maneyrol
2020-02-12 17:40 ` [PATCH 04/13] iio: imu: inv_mpu6050: simplify polling magnetometer Jean-Baptiste Maneyrol
2020-02-12 17:40 ` [PATCH 05/13] iio: imu: inv_mpu6050: early init of chip_config for use at setup Jean-Baptiste Maneyrol
2020-02-12 17:40 ` [PATCH 06/13] iio: imu: inv_mpu6050: add all signal path resets at init Jean-Baptiste Maneyrol
2020-02-12 17:40 ` [PATCH 07/13] iio: imu: inv_mpu6050: fix sleep time when turning regulators on Jean-Baptiste Maneyrol
2020-02-12 17:40 ` [PATCH 08/13] iio: imu: inv_mpu6050: rewrite power and engine management Jean-Baptiste Maneyrol
2020-02-15 18:09 ` Jonathan Cameron [this message]
2020-02-12 17:40 ` [PATCH 09/13] iio: imu: inv_mpu6050: fix data polling interface Jean-Baptiste Maneyrol
2020-02-12 17:40 ` [PATCH 10/13] iio: imu: inv_mpu6050: factorize fifo enable/disable Jean-Baptiste Maneyrol
2020-02-12 17:40 ` [PATCH 11/13] iio: imu: inv_mpu6050: dynamic sampling rate change Jean-Baptiste Maneyrol
2020-02-12 17:40 ` [PATCH 12/13] iio: imu: inv_mpu6050: use runtime pm with autosuspend Jean-Baptiste Maneyrol
2020-02-15 18:22 ` Jonathan Cameron
2020-02-18 16:44 ` Jean-Baptiste Maneyrol
2020-02-12 17:40 ` [PATCH 13/13] iio: imu: inv_mpu6050: temperature only work with accel/gyro Jean-Baptiste Maneyrol
2020-02-15 18:23 ` Jonathan Cameron
2020-02-18 16:46 ` Jean-Baptiste Maneyrol
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200215180930.5ebecddc@archlinux \
--to=jic23@kernel.org \
--cc=jmaneyrol@invensense.com \
--cc=linux-iio@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.