diff mbox series

[v2,09/13] iio: imu: inv_mpu6050: fix data polling interface

Message ID 20200219143958.3548-10-jmaneyrol@invensense.com (mailing list archive)
State New, archived
Headers show
Series Rework sensors engines and power management | expand

Commit Message

Jean-Baptiste Maneyrol Feb. 19, 2020, 2:39 p.m. UTC
When reading data with the polling interface, we need to wait
at 1 sampling period to have a sample.
For gyroscope and magnetometer, we need to wait for 2 periods
before having a correct sample.

Signed-off-by: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
---
 drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 36 ++++++++++++++++++++--
 drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c | 21 -------------
 drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h |  3 ++
 3 files changed, 37 insertions(+), 23 deletions(-)

Comments

Jonathan Cameron Feb. 21, 2020, 11:34 a.m. UTC | #1
On Wed, 19 Feb 2020 15:39:54 +0100
Jean-Baptiste Maneyrol <jmaneyrol@invensense.com> wrote:

> When reading data with the polling interface, we need to wait
> at 1 sampling period to have a sample.
> For gyroscope and magnetometer, we need to wait for 2 periods
> before having a correct sample.
> 
> Signed-off-by: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>

I should have raised this before, but is this something we might want to
backport? I don't really want this whole cleanup series getting backported,
so is there a more minimal change for older kernels? (probably just sleep too
long in all cases!)

Applied,

Jonathan

> ---
>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 36 ++++++++++++++++++++--
>  drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c | 21 -------------
>  drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h |  3 ++
>  3 files changed, 37 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> index a51efc4c941b..aeee39696d3a 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> @@ -563,9 +563,14 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
>  					 int *val)
>  {
>  	struct inv_mpu6050_state *st = iio_priv(indio_dev);
> +	unsigned int freq_hz, period_us, min_sleep_us, max_sleep_us;
>  	int result;
>  	int ret;
>  
> +	/* compute sample period */
> +	freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider);
> +	period_us = 1000000 / freq_hz;
> +
>  	result = inv_mpu6050_set_power_itg(st, true);
>  	if (result)
>  		return result;
> @@ -576,6 +581,10 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
>  				INV_MPU6050_SENSOR_GYRO);
>  		if (result)
>  			goto error_power_off;
> +		/* need to wait 2 periods to have first valid sample */
> +		min_sleep_us = 2 * period_us;
> +		max_sleep_us = 2 * (period_us + period_us / 2);
> +		usleep_range(min_sleep_us, max_sleep_us);
>  		ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro,
>  					      chan->channel2, val);
>  		result = inv_mpu6050_switch_engine(st, false,
> @@ -588,6 +597,10 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
>  				INV_MPU6050_SENSOR_ACCL);
>  		if (result)
>  			goto error_power_off;
> +		/* wait 1 period for first sample availability */
> +		min_sleep_us = period_us;
> +		max_sleep_us = period_us + period_us / 2;
> +		usleep_range(min_sleep_us, max_sleep_us);
>  		ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl,
>  					      chan->channel2, val);
>  		result = inv_mpu6050_switch_engine(st, false,
> @@ -600,8 +613,10 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
>  				INV_MPU6050_SENSOR_TEMP);
>  		if (result)
>  			goto error_power_off;
> -		/* wait for stablization */
> -		msleep(INV_MPU6050_TEMP_UP_TIME);
> +		/* wait 1 period for first sample availability */
> +		min_sleep_us = period_us;
> +		max_sleep_us = period_us + period_us / 2;
> +		usleep_range(min_sleep_us, max_sleep_us);
>  		ret = inv_mpu6050_sensor_show(st, st->reg->temperature,
>  					      IIO_MOD_X, val);
>  		result = inv_mpu6050_switch_engine(st, false,
> @@ -610,7 +625,24 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
>  			goto error_power_off;
>  		break;
>  	case IIO_MAGN:
> +		result = inv_mpu6050_switch_engine(st, true,
> +				INV_MPU6050_SENSOR_MAGN);
> +		if (result)
> +			goto error_power_off;
> +		/* frequency is limited for magnetometer */
> +		if (freq_hz > INV_MPU_MAGN_FREQ_HZ_MAX) {
> +			freq_hz = INV_MPU_MAGN_FREQ_HZ_MAX;
> +			period_us = 1000000 / freq_hz;
> +		}
> +		/* need to wait 2 periods to have first valid sample */
> +		min_sleep_us = 2 * period_us;
> +		max_sleep_us = 2 * (period_us + period_us / 2);
> +		usleep_range(min_sleep_us, max_sleep_us);
>  		ret = inv_mpu_magn_read(st, chan->channel2, val);
> +		result = inv_mpu6050_switch_engine(st, false,
> +				INV_MPU6050_SENSOR_MAGN);
> +		if (result)
> +			goto error_power_off;
>  		break;
>  	default:
>  		ret = -EINVAL;
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
> index 3f402fa56d95..f282e9cc34c5 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
> @@ -44,9 +44,6 @@
>  #define INV_MPU_MAGN_REG_ASAY		0x11
>  #define INV_MPU_MAGN_REG_ASAZ		0x12
>  
> -/* Magnetometer maximum frequency */
> -#define INV_MPU_MAGN_FREQ_HZ_MAX	50
> -
>  static bool inv_magn_supported(const struct inv_mpu6050_state *st)
>  {
>  	switch (st->chip_type) {
> @@ -321,7 +318,6 @@ int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val)
>  	unsigned int status;
>  	__be16 data;
>  	uint8_t addr;
> -	unsigned int freq_hz, period_ms;
>  	int ret;
>  
>  	/* quit if chip is not supported */
> @@ -344,23 +340,6 @@ int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val)
>  	}
>  	addr += INV_MPU6050_REG_EXT_SENS_DATA;
>  
> -	/* compute period depending on current sampling rate */
> -	freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider);
> -	if (freq_hz > INV_MPU_MAGN_FREQ_HZ_MAX)
> -		freq_hz = INV_MPU_MAGN_FREQ_HZ_MAX;
> -	period_ms = 1000 / freq_hz;
> -
> -	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);
> -
> -	ret = inv_mpu6050_switch_engine(st, false, INV_MPU6050_SENSOR_MAGN);
> -	if (ret)
> -		return ret;
> -
>  	/* check i2c status and read raw data */
>  	ret = regmap_read(st->map, INV_MPU6050_REG_I2C_MST_STATUS, &status);
>  	if (ret)
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h
> index f7ad50ca6c1b..185c000c697c 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h
> @@ -10,6 +10,9 @@
>  
>  #include "inv_mpu_iio.h"
>  
> +/* Magnetometer maximum frequency */
> +#define INV_MPU_MAGN_FREQ_HZ_MAX	50
> +
>  int inv_mpu_magn_probe(struct inv_mpu6050_state *st);
>  
>  /**
Jean-Baptiste Maneyrol Feb. 21, 2020, 2:03 p.m. UTC | #2
Hi Jonathan,

this is not something we want to backport. Mainly because it is heavly dependant on the rework of the power and sensor engines.

And polling interface without pm_runtime autosuspend is not really relevent.

Thanks,
JB


From: linux-iio-owner@vger.kernel.org <linux-iio-owner@vger.kernel.org> on behalf of Jonathan Cameron <jic23@kernel.org>

Sent: Friday, February 21, 2020 12:34

To: Jean-Baptiste Maneyrol <JManeyrol@invensense.com>

Cc: linux-iio@vger.kernel.org <linux-iio@vger.kernel.org>

Subject: Re: [PATCH v2 09/13] iio: imu: inv_mpu6050: fix data polling interface

 


 CAUTION: This email originated from outside of the organization. Please make sure the sender is who they say they are and do not click links or open attachments unless you recognize the sender and know the content is safe.



On Wed, 19 Feb 2020 15:39:54 +0100

Jean-Baptiste Maneyrol <jmaneyrol@invensense.com> wrote:



> When reading data with the polling interface, we need to wait

> at 1 sampling period to have a sample.

> For gyroscope and magnetometer, we need to wait for 2 periods

> before having a correct sample.

> 

> Signed-off-by: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>



I should have raised this before, but is this something we might want to

backport? I don't really want this whole cleanup series getting backported,

so is there a more minimal change for older kernels? (probably just sleep too

long in all cases!)



Applied,



Jonathan



> ---

>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 36 ++++++++++++++++++++--

>  drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c | 21 -------------

>  drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h |  3 ++

>  3 files changed, 37 insertions(+), 23 deletions(-)

> 

> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c

> index a51efc4c941b..aeee39696d3a 100644

> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c

> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c

> @@ -563,9 +563,14 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,

>                                         int *val)

>  {

>        struct inv_mpu6050_state *st = iio_priv(indio_dev);

> +     unsigned int freq_hz, period_us, min_sleep_us, max_sleep_us;

>        int result;

>        int ret;


> +     /* compute sample period */

> +     freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider);

> +     period_us = 1000000 / freq_hz;

> +

>        result = inv_mpu6050_set_power_itg(st, true);

>        if (result)

>                return result;

> @@ -576,6 +581,10 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,

>                                INV_MPU6050_SENSOR_GYRO);

>                if (result)

>                        goto error_power_off;

> +             /* need to wait 2 periods to have first valid sample */

> +             min_sleep_us = 2 * period_us;

> +             max_sleep_us = 2 * (period_us + period_us / 2);

> +             usleep_range(min_sleep_us, max_sleep_us);

>                ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro,

>                                              chan->channel2, val);

>                result = inv_mpu6050_switch_engine(st, false,

> @@ -588,6 +597,10 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,

>                                INV_MPU6050_SENSOR_ACCL);

>                if (result)

>                        goto error_power_off;

> +             /* wait 1 period for first sample availability */

> +             min_sleep_us = period_us;

> +             max_sleep_us = period_us + period_us / 2;

> +             usleep_range(min_sleep_us, max_sleep_us);

>                ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl,

>                                              chan->channel2, val);

>                result = inv_mpu6050_switch_engine(st, false,

> @@ -600,8 +613,10 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,

>                                INV_MPU6050_SENSOR_TEMP);

>                if (result)

>                        goto error_power_off;

> -             /* wait for stablization */

> -             msleep(INV_MPU6050_TEMP_UP_TIME);

> +             /* wait 1 period for first sample availability */

> +             min_sleep_us = period_us;

> +             max_sleep_us = period_us + period_us / 2;

> +             usleep_range(min_sleep_us, max_sleep_us);

>                ret = inv_mpu6050_sensor_show(st, st->reg->temperature,

>                                              IIO_MOD_X, val);

>                result = inv_mpu6050_switch_engine(st, false,

> @@ -610,7 +625,24 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,

>                        goto error_power_off;

>                break;

>        case IIO_MAGN:

> +             result = inv_mpu6050_switch_engine(st, true,

> +                             INV_MPU6050_SENSOR_MAGN);

> +             if (result)

> +                     goto error_power_off;

> +             /* frequency is limited for magnetometer */

> +             if (freq_hz > INV_MPU_MAGN_FREQ_HZ_MAX) {

> +                     freq_hz = INV_MPU_MAGN_FREQ_HZ_MAX;

> +                     period_us = 1000000 / freq_hz;

> +             }

> +             /* need to wait 2 periods to have first valid sample */

> +             min_sleep_us = 2 * period_us;

> +             max_sleep_us = 2 * (period_us + period_us / 2);

> +             usleep_range(min_sleep_us, max_sleep_us);

>                ret = inv_mpu_magn_read(st, chan->channel2, val);

> +             result = inv_mpu6050_switch_engine(st, false,

> +                             INV_MPU6050_SENSOR_MAGN);

> +             if (result)

> +                     goto error_power_off;

>                break;

>        default:

>                ret = -EINVAL;

> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c

> index 3f402fa56d95..f282e9cc34c5 100644

> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c

> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c

> @@ -44,9 +44,6 @@

>  #define INV_MPU_MAGN_REG_ASAY                0x11

>  #define INV_MPU_MAGN_REG_ASAZ                0x12


> -/* Magnetometer maximum frequency */

> -#define INV_MPU_MAGN_FREQ_HZ_MAX     50

> -

>  static bool inv_magn_supported(const struct inv_mpu6050_state *st)

>  {

>        switch (st->chip_type) {

> @@ -321,7 +318,6 @@ int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val)

>        unsigned int status;

>        __be16 data;

>        uint8_t addr;

> -     unsigned int freq_hz, period_ms;

>        int ret;


>        /* quit if chip is not supported */

> @@ -344,23 +340,6 @@ int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val)

>        }

>        addr += INV_MPU6050_REG_EXT_SENS_DATA;


> -     /* compute period depending on current sampling rate */

> -     freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider);

> -     if (freq_hz > INV_MPU_MAGN_FREQ_HZ_MAX)

> -             freq_hz = INV_MPU_MAGN_FREQ_HZ_MAX;

> -     period_ms = 1000 / freq_hz;

> -

> -     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);

> -

> -     ret = inv_mpu6050_switch_engine(st, false, INV_MPU6050_SENSOR_MAGN);

> -     if (ret)

> -             return ret;

> -

>        /* check i2c status and read raw data */

>        ret = regmap_read(st->map, INV_MPU6050_REG_I2C_MST_STATUS, &status);

>        if (ret)

> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h

> index f7ad50ca6c1b..185c000c697c 100644

> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h

> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h

> @@ -10,6 +10,9 @@


>  #include "inv_mpu_iio.h"


> +/* Magnetometer maximum frequency */

> +#define INV_MPU_MAGN_FREQ_HZ_MAX     50

> +

>  int inv_mpu_magn_probe(struct inv_mpu6050_state *st);


>  /**
Jonathan Cameron Feb. 21, 2020, 3:29 p.m. UTC | #3
On Fri, 21 Feb 2020 14:03:39 +0000
Jean-Baptiste Maneyrol <JManeyrol@invensense.com> wrote:

> Hi Jonathan,
> 
> this is not something we want to backport. Mainly because it is heavly dependant on the rework of the power and sensor engines.
> 
> And polling interface without pm_runtime autosuspend is not really relevent.

Fair enough. I'll add a note to try and prevent it getting automatically
picked up as a fix.

Thanks,

Jonathan

> 
> Thanks,
> JB
> 
> 
> From: linux-iio-owner@vger.kernel.org <linux-iio-owner@vger.kernel.org> on behalf of Jonathan Cameron <jic23@kernel.org>
> 
> Sent: Friday, February 21, 2020 12:34
> 
> To: Jean-Baptiste Maneyrol <JManeyrol@invensense.com>
> 
> Cc: linux-iio@vger.kernel.org <linux-iio@vger.kernel.org>
> 
> Subject: Re: [PATCH v2 09/13] iio: imu: inv_mpu6050: fix data polling interface
> 
>  
> 
> 
>  CAUTION: This email originated from outside of the organization. Please make sure the sender is who they say they are and do not click links or open attachments unless you recognize the sender and know the content is safe.
> 
> 
> 
> On Wed, 19 Feb 2020 15:39:54 +0100
> 
> Jean-Baptiste Maneyrol <jmaneyrol@invensense.com> wrote:
> 
> 
> 
> > When reading data with the polling interface, we need to wait  
> 
> > at 1 sampling period to have a sample.  
> 
> > For gyroscope and magnetometer, we need to wait for 2 periods  
> 
> > before having a correct sample.  
> 
> >   
> 
> > Signed-off-by: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>  
> 
> 
> 
> I should have raised this before, but is this something we might want to
> 
> backport? I don't really want this whole cleanup series getting backported,
> 
> so is there a more minimal change for older kernels? (probably just sleep too
> 
> long in all cases!)
> 
> 
> 
> Applied,
> 
> 
> 
> Jonathan
> 
> 
> 
> > ---  
> 
> >  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 36 ++++++++++++++++++++--  
> 
> >  drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c | 21 -------------  
> 
> >  drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h |  3 ++  
> 
> >  3 files changed, 37 insertions(+), 23 deletions(-)  
> 
> >   
> 
> > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c  
> 
> > index a51efc4c941b..aeee39696d3a 100644  
> 
> > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c  
> 
> > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c  
> 
> > @@ -563,9 +563,14 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,  
> 
> >                                         int *val)  
> 
> >  {  
> 
> >        struct inv_mpu6050_state *st = iio_priv(indio_dev);  
> 
> > +     unsigned int freq_hz, period_us, min_sleep_us, max_sleep_us;  
> 
> >        int result;  
> 
> >        int ret;  
> 
> >    
> 
> > +     /* compute sample period */  
> 
> > +     freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider);  
> 
> > +     period_us = 1000000 / freq_hz;  
> 
> > +  
> 
> >        result = inv_mpu6050_set_power_itg(st, true);  
> 
> >        if (result)  
> 
> >                return result;  
> 
> > @@ -576,6 +581,10 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,  
> 
> >                                INV_MPU6050_SENSOR_GYRO);  
> 
> >                if (result)  
> 
> >                        goto error_power_off;  
> 
> > +             /* need to wait 2 periods to have first valid sample */  
> 
> > +             min_sleep_us = 2 * period_us;  
> 
> > +             max_sleep_us = 2 * (period_us + period_us / 2);  
> 
> > +             usleep_range(min_sleep_us, max_sleep_us);  
> 
> >                ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro,  
> 
> >                                              chan->channel2, val);  
> 
> >                result = inv_mpu6050_switch_engine(st, false,  
> 
> > @@ -588,6 +597,10 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,  
> 
> >                                INV_MPU6050_SENSOR_ACCL);  
> 
> >                if (result)  
> 
> >                        goto error_power_off;  
> 
> > +             /* wait 1 period for first sample availability */  
> 
> > +             min_sleep_us = period_us;  
> 
> > +             max_sleep_us = period_us + period_us / 2;  
> 
> > +             usleep_range(min_sleep_us, max_sleep_us);  
> 
> >                ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl,  
> 
> >                                              chan->channel2, val);  
> 
> >                result = inv_mpu6050_switch_engine(st, false,  
> 
> > @@ -600,8 +613,10 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,  
> 
> >                                INV_MPU6050_SENSOR_TEMP);  
> 
> >                if (result)  
> 
> >                        goto error_power_off;  
> 
> > -             /* wait for stablization */  
> 
> > -             msleep(INV_MPU6050_TEMP_UP_TIME);  
> 
> > +             /* wait 1 period for first sample availability */  
> 
> > +             min_sleep_us = period_us;  
> 
> > +             max_sleep_us = period_us + period_us / 2;  
> 
> > +             usleep_range(min_sleep_us, max_sleep_us);  
> 
> >                ret = inv_mpu6050_sensor_show(st, st->reg->temperature,  
> 
> >                                              IIO_MOD_X, val);  
> 
> >                result = inv_mpu6050_switch_engine(st, false,  
> 
> > @@ -610,7 +625,24 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,  
> 
> >                        goto error_power_off;  
> 
> >                break;  
> 
> >        case IIO_MAGN:  
> 
> > +             result = inv_mpu6050_switch_engine(st, true,  
> 
> > +                             INV_MPU6050_SENSOR_MAGN);  
> 
> > +             if (result)  
> 
> > +                     goto error_power_off;  
> 
> > +             /* frequency is limited for magnetometer */  
> 
> > +             if (freq_hz > INV_MPU_MAGN_FREQ_HZ_MAX) {  
> 
> > +                     freq_hz = INV_MPU_MAGN_FREQ_HZ_MAX;  
> 
> > +                     period_us = 1000000 / freq_hz;  
> 
> > +             }  
> 
> > +             /* need to wait 2 periods to have first valid sample */  
> 
> > +             min_sleep_us = 2 * period_us;  
> 
> > +             max_sleep_us = 2 * (period_us + period_us / 2);  
> 
> > +             usleep_range(min_sleep_us, max_sleep_us);  
> 
> >                ret = inv_mpu_magn_read(st, chan->channel2, val);  
> 
> > +             result = inv_mpu6050_switch_engine(st, false,  
> 
> > +                             INV_MPU6050_SENSOR_MAGN);  
> 
> > +             if (result)  
> 
> > +                     goto error_power_off;  
> 
> >                break;  
> 
> >        default:  
> 
> >                ret = -EINVAL;  
> 
> > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c  
> 
> > index 3f402fa56d95..f282e9cc34c5 100644  
> 
> > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c  
> 
> > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c  
> 
> > @@ -44,9 +44,6 @@  
> 
> >  #define INV_MPU_MAGN_REG_ASAY                0x11  
> 
> >  #define INV_MPU_MAGN_REG_ASAZ                0x12  
> 
> >    
> 
> > -/* Magnetometer maximum frequency */  
> 
> > -#define INV_MPU_MAGN_FREQ_HZ_MAX     50  
> 
> > -  
> 
> >  static bool inv_magn_supported(const struct inv_mpu6050_state *st)  
> 
> >  {  
> 
> >        switch (st->chip_type) {  
> 
> > @@ -321,7 +318,6 @@ int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val)  
> 
> >        unsigned int status;  
> 
> >        __be16 data;  
> 
> >        uint8_t addr;  
> 
> > -     unsigned int freq_hz, period_ms;  
> 
> >        int ret;  
> 
> >    
> 
> >        /* quit if chip is not supported */  
> 
> > @@ -344,23 +340,6 @@ int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val)  
> 
> >        }  
> 
> >        addr += INV_MPU6050_REG_EXT_SENS_DATA;  
> 
> >    
> 
> > -     /* compute period depending on current sampling rate */  
> 
> > -     freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider);  
> 
> > -     if (freq_hz > INV_MPU_MAGN_FREQ_HZ_MAX)  
> 
> > -             freq_hz = INV_MPU_MAGN_FREQ_HZ_MAX;  
> 
> > -     period_ms = 1000 / freq_hz;  
> 
> > -  
> 
> > -     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);  
> 
> > -  
> 
> > -     ret = inv_mpu6050_switch_engine(st, false, INV_MPU6050_SENSOR_MAGN);  
> 
> > -     if (ret)  
> 
> > -             return ret;  
> 
> > -  
> 
> >        /* check i2c status and read raw data */  
> 
> >        ret = regmap_read(st->map, INV_MPU6050_REG_I2C_MST_STATUS, &status);  
> 
> >        if (ret)  
> 
> > diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h  
> 
> > index f7ad50ca6c1b..185c000c697c 100644  
> 
> > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h  
> 
> > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h  
> 
> > @@ -10,6 +10,9 @@  
> 
> >    
> 
> >  #include "inv_mpu_iio.h"  
> 
> >    
> 
> > +/* Magnetometer maximum frequency */  
> 
> > +#define INV_MPU_MAGN_FREQ_HZ_MAX     50  
> 
> > +  
> 
> >  int inv_mpu_magn_probe(struct inv_mpu6050_state *st);  
> 
> >    
> 
> >  /**  
> 
> 
>
diff mbox series

Patch

diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index a51efc4c941b..aeee39696d3a 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -563,9 +563,14 @@  static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
 					 int *val)
 {
 	struct inv_mpu6050_state *st = iio_priv(indio_dev);
+	unsigned int freq_hz, period_us, min_sleep_us, max_sleep_us;
 	int result;
 	int ret;
 
+	/* compute sample period */
+	freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider);
+	period_us = 1000000 / freq_hz;
+
 	result = inv_mpu6050_set_power_itg(st, true);
 	if (result)
 		return result;
@@ -576,6 +581,10 @@  static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
 				INV_MPU6050_SENSOR_GYRO);
 		if (result)
 			goto error_power_off;
+		/* need to wait 2 periods to have first valid sample */
+		min_sleep_us = 2 * period_us;
+		max_sleep_us = 2 * (period_us + period_us / 2);
+		usleep_range(min_sleep_us, max_sleep_us);
 		ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro,
 					      chan->channel2, val);
 		result = inv_mpu6050_switch_engine(st, false,
@@ -588,6 +597,10 @@  static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
 				INV_MPU6050_SENSOR_ACCL);
 		if (result)
 			goto error_power_off;
+		/* wait 1 period for first sample availability */
+		min_sleep_us = period_us;
+		max_sleep_us = period_us + period_us / 2;
+		usleep_range(min_sleep_us, max_sleep_us);
 		ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl,
 					      chan->channel2, val);
 		result = inv_mpu6050_switch_engine(st, false,
@@ -600,8 +613,10 @@  static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
 				INV_MPU6050_SENSOR_TEMP);
 		if (result)
 			goto error_power_off;
-		/* wait for stablization */
-		msleep(INV_MPU6050_TEMP_UP_TIME);
+		/* wait 1 period for first sample availability */
+		min_sleep_us = period_us;
+		max_sleep_us = period_us + period_us / 2;
+		usleep_range(min_sleep_us, max_sleep_us);
 		ret = inv_mpu6050_sensor_show(st, st->reg->temperature,
 					      IIO_MOD_X, val);
 		result = inv_mpu6050_switch_engine(st, false,
@@ -610,7 +625,24 @@  static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
 			goto error_power_off;
 		break;
 	case IIO_MAGN:
+		result = inv_mpu6050_switch_engine(st, true,
+				INV_MPU6050_SENSOR_MAGN);
+		if (result)
+			goto error_power_off;
+		/* frequency is limited for magnetometer */
+		if (freq_hz > INV_MPU_MAGN_FREQ_HZ_MAX) {
+			freq_hz = INV_MPU_MAGN_FREQ_HZ_MAX;
+			period_us = 1000000 / freq_hz;
+		}
+		/* need to wait 2 periods to have first valid sample */
+		min_sleep_us = 2 * period_us;
+		max_sleep_us = 2 * (period_us + period_us / 2);
+		usleep_range(min_sleep_us, max_sleep_us);
 		ret = inv_mpu_magn_read(st, chan->channel2, val);
+		result = inv_mpu6050_switch_engine(st, false,
+				INV_MPU6050_SENSOR_MAGN);
+		if (result)
+			goto error_power_off;
 		break;
 	default:
 		ret = -EINVAL;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
index 3f402fa56d95..f282e9cc34c5 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
@@ -44,9 +44,6 @@ 
 #define INV_MPU_MAGN_REG_ASAY		0x11
 #define INV_MPU_MAGN_REG_ASAZ		0x12
 
-/* Magnetometer maximum frequency */
-#define INV_MPU_MAGN_FREQ_HZ_MAX	50
-
 static bool inv_magn_supported(const struct inv_mpu6050_state *st)
 {
 	switch (st->chip_type) {
@@ -321,7 +318,6 @@  int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val)
 	unsigned int status;
 	__be16 data;
 	uint8_t addr;
-	unsigned int freq_hz, period_ms;
 	int ret;
 
 	/* quit if chip is not supported */
@@ -344,23 +340,6 @@  int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val)
 	}
 	addr += INV_MPU6050_REG_EXT_SENS_DATA;
 
-	/* compute period depending on current sampling rate */
-	freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider);
-	if (freq_hz > INV_MPU_MAGN_FREQ_HZ_MAX)
-		freq_hz = INV_MPU_MAGN_FREQ_HZ_MAX;
-	period_ms = 1000 / freq_hz;
-
-	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);
-
-	ret = inv_mpu6050_switch_engine(st, false, INV_MPU6050_SENSOR_MAGN);
-	if (ret)
-		return ret;
-
 	/* check i2c status and read raw data */
 	ret = regmap_read(st->map, INV_MPU6050_REG_I2C_MST_STATUS, &status);
 	if (ret)
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h
index f7ad50ca6c1b..185c000c697c 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h
@@ -10,6 +10,9 @@ 
 
 #include "inv_mpu_iio.h"
 
+/* Magnetometer maximum frequency */
+#define INV_MPU_MAGN_FREQ_HZ_MAX	50
+
 int inv_mpu_magn_probe(struct inv_mpu6050_state *st);
 
 /**