All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jonathan Cameron <jic23@kernel.org>
To: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
Cc: linux-iio@vger.kernel.org
Subject: Re: [PATCH 2/2] iio: imu: inv_mpu6050: add support of MPU9150 magnetometer
Date: Sat, 16 Nov 2019 17:20:13 +0000	[thread overview]
Message-ID: <20191116172013.7d272d0b@archlinux> (raw)
In-Reply-To: <20191115140622.6429-3-jmaneyrol@invensense.com>

On Fri, 15 Nov 2019 15:06:22 +0100
Jean-Baptiste Maneyrol <jmaneyrol@invensense.com> wrote:

> Add support for driving MPU9150 magnetometer (AK8975) from mpu.
> 
> Signed-off-by: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
All the prerequisits are now (I think) in my togreg branch so
applied to that and pushed out as testing for the autobuilders
to do more build tests than I can be bothered with :)

Thanks,

Jonathan

> ---
>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c    | 57 ++++++++++---
>  drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c     |  2 +
>  drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c    | 80 +++++++++++++------
>  drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c |  1 +
>  4 files changed, 104 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> index 45e77b308238..23c0557891a0 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> @@ -914,6 +914,33 @@ static const unsigned long inv_mpu_scan_masks[] = {
>  		.ext_info = inv_ext_info,				\
>  	}
>  
> +static const struct iio_chan_spec inv_mpu9150_channels[] = {
> +	IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP),
> +	/*
> +	 * Note that temperature should only be via polled reading only,
> +	 * not the final scan elements output.
> +	 */
> +	{
> +		.type = IIO_TEMP,
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW)
> +				| BIT(IIO_CHAN_INFO_OFFSET)
> +				| BIT(IIO_CHAN_INFO_SCALE),
> +		.scan_index = -1,
> +	},
> +	INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X),
> +	INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y),
> +	INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z),
> +
> +	INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU6050_SCAN_ACCL_X),
> +	INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU6050_SCAN_ACCL_Y),
> +	INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z),
> +
> +	/* Magnetometer resolution is 13 bits */
> +	INV_MPU9X50_MAGN_CHAN(IIO_MOD_X, 13, INV_MPU9X50_SCAN_MAGN_X),
> +	INV_MPU9X50_MAGN_CHAN(IIO_MOD_Y, 13, INV_MPU9X50_SCAN_MAGN_Y),
> +	INV_MPU9X50_MAGN_CHAN(IIO_MOD_Z, 13, INV_MPU9X50_SCAN_MAGN_Z),
> +};
> +
>  static const struct iio_chan_spec inv_mpu9250_channels[] = {
>  	IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP),
>  	/*
> @@ -1323,21 +1350,16 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
>  		inv_mpu_bus_setup(indio_dev);
>  
>  	switch (chip_type) {
> +	case INV_MPU9150:
> +		indio_dev->channels = inv_mpu9150_channels;
> +		indio_dev->num_channels = ARRAY_SIZE(inv_mpu9150_channels);
> +		indio_dev->available_scan_masks = inv_mpu9x50_scan_masks;
> +		break;
>  	case INV_MPU9250:
>  	case INV_MPU9255:
> -		/*
> -		 * Use magnetometer inside the chip only if there is no i2c
> -		 * auxiliary device in use.
> -		 */
> -		if (!st->magn_disabled) {
> -			indio_dev->channels = inv_mpu9250_channels;
> -			indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels);
> -			indio_dev->available_scan_masks = inv_mpu9x50_scan_masks;
> -		} else {
> -			indio_dev->channels = inv_mpu_channels;
> -			indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
> -			indio_dev->available_scan_masks = inv_mpu_scan_masks;
> -		}
> +		indio_dev->channels = inv_mpu9250_channels;
> +		indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels);
> +		indio_dev->available_scan_masks = inv_mpu9x50_scan_masks;
>  		break;
>  	case INV_ICM20602:
>  		indio_dev->channels = inv_icm20602_channels;
> @@ -1350,6 +1372,15 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
>  		indio_dev->available_scan_masks = inv_mpu_scan_masks;
>  		break;
>  	}
> +	/*
> +	 * Use magnetometer inside the chip only if there is no i2c
> +	 * auxiliary device in use. Otherwise Going back to 6-axis only.
> +	 */
> +	if (st->magn_disabled) {
> +		indio_dev->channels = inv_mpu_channels;
> +		indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
> +		indio_dev->available_scan_masks = inv_mpu_scan_masks;
> +	}
>  
>  	indio_dev->info = &mpu_info;
>  	indio_dev->modes = INDIO_BUFFER_TRIGGERED;
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
> index 389cc8505e0e..f47a28b4be23 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
> @@ -77,6 +77,7 @@ static bool inv_mpu_i2c_aux_bus(struct device *dev)
>  	case INV_ICM20602:
>  		/* no i2c auxiliary bus on the chip */
>  		return false;
> +	case INV_MPU9150:
>  	case INV_MPU9250:
>  	case INV_MPU9255:
>  		if (st->magn_disabled)
> @@ -102,6 +103,7 @@ static int inv_mpu_magn_disable(struct iio_dev *indio_dev)
>  	struct device_node *mux_node;
>  
>  	switch (st->chip_type) {
> +	case INV_MPU9150:
>  	case INV_MPU9250:
>  	case INV_MPU9255:
>  		mux_node = of_get_child_by_name(dev->of_node, "i2c-gate");
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
> index 02735af152c8..4f192352521e 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
> @@ -12,7 +12,9 @@
>  #include "inv_mpu_magn.h"
>  
>  /*
> - * MPU9250 magnetometer is an AKM AK8963 chip on I2C aux bus
> + * MPU9xxx magnetometer are AKM chips on I2C aux bus
> + * MPU9150 is AK8975
> + * MPU9250 is AK8963
>   */
>  #define INV_MPU_MAGN_I2C_ADDR		0x0C
>  
> @@ -33,10 +35,10 @@
>  #define INV_MPU_MAGN_BITS_MODE_PWDN	0x00
>  #define INV_MPU_MAGN_BITS_MODE_SINGLE	0x01
>  #define INV_MPU_MAGN_BITS_MODE_FUSE	0x0F
> -#define INV_MPU_MAGN_BIT_OUTPUT_BIT	0x10
> +#define INV_MPU9250_MAGN_BIT_OUTPUT_BIT	0x10
>  
> -#define INV_MPU_MAGN_REG_CNTL2		0x0B
> -#define INV_MPU_MAGN_BIT_SRST		0x01
> +#define INV_MPU9250_MAGN_REG_CNTL2	0x0B
> +#define INV_MPU9250_MAGN_BIT_SRST	0x01
>  
>  #define INV_MPU_MAGN_REG_ASAX		0x10
>  #define INV_MPU_MAGN_REG_ASAY		0x11
> @@ -48,6 +50,7 @@
>  static bool inv_magn_supported(const struct inv_mpu6050_state *st)
>  {
>  	switch (st->chip_type) {
> +	case INV_MPU9150:
>  	case INV_MPU9250:
>  	case INV_MPU9255:
>  		return true;
> @@ -61,6 +64,7 @@ static int inv_magn_init(struct inv_mpu6050_state *st)
>  {
>  	uint8_t val;
>  	uint8_t asa[3];
> +	int32_t sensitivity;
>  	int ret;
>  
>  	/* check whoami */
> @@ -71,12 +75,19 @@ static int inv_magn_init(struct inv_mpu6050_state *st)
>  	if (val != INV_MPU_MAGN_BITS_WIA)
>  		return -ENODEV;
>  
> -	/* reset chip */
> -	ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR,
> -				INV_MPU_MAGN_REG_CNTL2,
> -				INV_MPU_MAGN_BIT_SRST);
> -	if (ret)
> -		return ret;
> +	/* software reset for MPU925x only */
> +	switch (st->chip_type) {
> +	case INV_MPU9250:
> +	case INV_MPU9255:
> +		ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR,
> +					INV_MPU9250_MAGN_REG_CNTL2,
> +					INV_MPU9250_MAGN_BIT_SRST);
> +		if (ret)
> +			return ret;
> +		break;
> +	default:
> +		break;
> +	}
>  
>  	/* read fuse ROM data */
>  	ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR,
> @@ -97,6 +108,25 @@ static int inv_magn_init(struct inv_mpu6050_state *st)
>  	if (ret)
>  		return ret;
>  
> +	/*
> +	 * Sensor sentivity
> +	 * 1 uT = 0.01 G and value is in micron (1e6)
> +	 * sensitvity = x uT * 0.01 * 1e6
> +	 */
> +	switch (st->chip_type) {
> +	case INV_MPU9150:
> +		/* sensor sensitivity is 0.3 uT */
> +		sensitivity = 3000;
> +		break;
> +	case INV_MPU9250:
> +	case INV_MPU9255:
> +		/* sensor sensitivity in 16 bits mode: 0.15 uT */
> +		sensitivity = 1500;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
>  	/*
>  	 * Sensitivity adjustement and scale to Gauss
>  	 *
> @@ -104,16 +134,11 @@ static int inv_magn_init(struct inv_mpu6050_state *st)
>  	 * Factor simplification:
>  	 * Hadj = H * ((ASA + 128) / 256)
>  	 *
> -	 * Sensor sentivity
> -	 * 0.15 uT in 16 bits mode
> -	 * 1 uT = 0.01 G and value is in micron (1e6)
> -	 * sensitvity = 0.15 uT * 0.01 * 1e6
> -	 *
> -	 * raw_to_gauss = Hadj * 1500
> +	 * raw_to_gauss = Hadj * sensitivity
>  	 */
> -	st->magn_raw_to_gauss[0] = (((int32_t)asa[0] + 128) * 1500) / 256;
> -	st->magn_raw_to_gauss[1] = (((int32_t)asa[1] + 128) * 1500) / 256;
> -	st->magn_raw_to_gauss[2] = (((int32_t)asa[2] + 128) * 1500) / 256;
> +	st->magn_raw_to_gauss[0] = (((int32_t)asa[0] + 128) * sensitivity) / 256;
> +	st->magn_raw_to_gauss[1] = (((int32_t)asa[1] + 128) * sensitivity) / 256;
> +	st->magn_raw_to_gauss[2] = (((int32_t)asa[2] + 128) * sensitivity) / 256;
>  
>  	return 0;
>  }
> @@ -129,6 +154,7 @@ static int inv_magn_init(struct inv_mpu6050_state *st)
>   */
>  int inv_mpu_magn_probe(struct inv_mpu6050_state *st)
>  {
> +	uint8_t val;
>  	int ret;
>  
>  	/* quit if chip is not supported */
> @@ -179,10 +205,17 @@ int inv_mpu_magn_probe(struct inv_mpu6050_state *st)
>  	if (ret)
>  		return ret;
>  
> -	/* add 16 bits mode */
> -	ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_DO(1),
> -			   INV_MPU_MAGN_BITS_MODE_SINGLE |
> -			   INV_MPU_MAGN_BIT_OUTPUT_BIT);
> +	/* add 16 bits mode for MPU925x */
> +	val = INV_MPU_MAGN_BITS_MODE_SINGLE;
> +	switch (st->chip_type) {
> +	case INV_MPU9250:
> +	case INV_MPU9255:
> +		val |= INV_MPU9250_MAGN_BIT_OUTPUT_BIT;
> +		break;
> +	default:
> +		break;
> +	}
> +	ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_DO(1), val);
>  	if (ret)
>  		return ret;
>  
> @@ -237,6 +270,7 @@ int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st)
>  
>  	/* fill magnetometer orientation */
>  	switch (st->chip_type) {
> +	case INV_MPU9150:
>  	case INV_MPU9250:
>  	case INV_MPU9255:
>  		/* x <- y */
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> index d7d951927a44..a9c75bc62f18 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> @@ -50,6 +50,7 @@ static void inv_scan_query(struct iio_dev *indio_dev)
>  	struct inv_mpu6050_state *st = iio_priv(indio_dev);
>  
>  	switch (st->chip_type) {
> +	case INV_MPU9150:
>  	case INV_MPU9250:
>  	case INV_MPU9255:
>  		return inv_scan_query_mpu9x50(indio_dev);


      reply	other threads:[~2019-11-16 17:20 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-15 14:06 [PATCH 0/2] Add MPU9150 magnetometer support Jean-Baptiste Maneyrol
2019-11-15 14:06 ` [PATCH 1/2] iio: imu: inv_mpu6050: delete not existing MPU9150 spi support Jean-Baptiste Maneyrol
2019-11-16 17:16   ` Jonathan Cameron
2019-11-15 14:06 ` [PATCH 2/2] iio: imu: inv_mpu6050: add support of MPU9150 magnetometer Jean-Baptiste Maneyrol
2019-11-16 17:20   ` Jonathan Cameron [this message]

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=20191116172013.7d272d0b@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.