Commit a2587eb0 authored by Jean-Baptiste Maneyrol's avatar Jean-Baptiste Maneyrol Committed by Jonathan Cameron

iio: imu: inv_mpu6050: add support of MPU9150 magnetometer

Add support for driving MPU9150 magnetometer (AK8975) from mpu.
Signed-off-by: default avatarJean-Baptiste Maneyrol <jmaneyrol@invensense.com>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent b95ed406
...@@ -914,6 +914,33 @@ static const unsigned long inv_mpu_scan_masks[] = { ...@@ -914,6 +914,33 @@ static const unsigned long inv_mpu_scan_masks[] = {
.ext_info = inv_ext_info, \ .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[] = { static const struct iio_chan_spec inv_mpu9250_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP), 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, ...@@ -1323,21 +1350,16 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
inv_mpu_bus_setup(indio_dev); inv_mpu_bus_setup(indio_dev);
switch (chip_type) { 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_MPU9250:
case INV_MPU9255: case INV_MPU9255:
/* indio_dev->channels = inv_mpu9250_channels;
* Use magnetometer inside the chip only if there is no i2c indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels);
* auxiliary device in use. indio_dev->available_scan_masks = inv_mpu9x50_scan_masks;
*/
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;
}
break; break;
case INV_ICM20602: case INV_ICM20602:
indio_dev->channels = inv_icm20602_channels; indio_dev->channels = inv_icm20602_channels;
...@@ -1350,6 +1372,15 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, ...@@ -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; indio_dev->available_scan_masks = inv_mpu_scan_masks;
break; 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->info = &mpu_info;
indio_dev->modes = INDIO_BUFFER_TRIGGERED; indio_dev->modes = INDIO_BUFFER_TRIGGERED;
......
...@@ -77,6 +77,7 @@ static bool inv_mpu_i2c_aux_bus(struct device *dev) ...@@ -77,6 +77,7 @@ static bool inv_mpu_i2c_aux_bus(struct device *dev)
case INV_ICM20602: case INV_ICM20602:
/* no i2c auxiliary bus on the chip */ /* no i2c auxiliary bus on the chip */
return false; return false;
case INV_MPU9150:
case INV_MPU9250: case INV_MPU9250:
case INV_MPU9255: case INV_MPU9255:
if (st->magn_disabled) if (st->magn_disabled)
...@@ -102,6 +103,7 @@ static int inv_mpu_magn_disable(struct iio_dev *indio_dev) ...@@ -102,6 +103,7 @@ static int inv_mpu_magn_disable(struct iio_dev *indio_dev)
struct device_node *mux_node; struct device_node *mux_node;
switch (st->chip_type) { switch (st->chip_type) {
case INV_MPU9150:
case INV_MPU9250: case INV_MPU9250:
case INV_MPU9255: case INV_MPU9255:
mux_node = of_get_child_by_name(dev->of_node, "i2c-gate"); mux_node = of_get_child_by_name(dev->of_node, "i2c-gate");
......
...@@ -12,7 +12,9 @@ ...@@ -12,7 +12,9 @@
#include "inv_mpu_magn.h" #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 #define INV_MPU_MAGN_I2C_ADDR 0x0C
...@@ -33,10 +35,10 @@ ...@@ -33,10 +35,10 @@
#define INV_MPU_MAGN_BITS_MODE_PWDN 0x00 #define INV_MPU_MAGN_BITS_MODE_PWDN 0x00
#define INV_MPU_MAGN_BITS_MODE_SINGLE 0x01 #define INV_MPU_MAGN_BITS_MODE_SINGLE 0x01
#define INV_MPU_MAGN_BITS_MODE_FUSE 0x0F #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_MPU9250_MAGN_REG_CNTL2 0x0B
#define INV_MPU_MAGN_BIT_SRST 0x01 #define INV_MPU9250_MAGN_BIT_SRST 0x01
#define INV_MPU_MAGN_REG_ASAX 0x10 #define INV_MPU_MAGN_REG_ASAX 0x10
#define INV_MPU_MAGN_REG_ASAY 0x11 #define INV_MPU_MAGN_REG_ASAY 0x11
...@@ -48,6 +50,7 @@ ...@@ -48,6 +50,7 @@
static bool inv_magn_supported(const struct inv_mpu6050_state *st) static bool inv_magn_supported(const struct inv_mpu6050_state *st)
{ {
switch (st->chip_type) { switch (st->chip_type) {
case INV_MPU9150:
case INV_MPU9250: case INV_MPU9250:
case INV_MPU9255: case INV_MPU9255:
return true; return true;
...@@ -61,6 +64,7 @@ static int inv_magn_init(struct inv_mpu6050_state *st) ...@@ -61,6 +64,7 @@ static int inv_magn_init(struct inv_mpu6050_state *st)
{ {
uint8_t val; uint8_t val;
uint8_t asa[3]; uint8_t asa[3];
int32_t sensitivity;
int ret; int ret;
/* check whoami */ /* check whoami */
...@@ -71,12 +75,19 @@ static int inv_magn_init(struct inv_mpu6050_state *st) ...@@ -71,12 +75,19 @@ static int inv_magn_init(struct inv_mpu6050_state *st)
if (val != INV_MPU_MAGN_BITS_WIA) if (val != INV_MPU_MAGN_BITS_WIA)
return -ENODEV; return -ENODEV;
/* reset chip */ /* software reset for MPU925x only */
ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR, switch (st->chip_type) {
INV_MPU_MAGN_REG_CNTL2, case INV_MPU9250:
INV_MPU_MAGN_BIT_SRST); case INV_MPU9255:
if (ret) ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR,
return ret; INV_MPU9250_MAGN_REG_CNTL2,
INV_MPU9250_MAGN_BIT_SRST);
if (ret)
return ret;
break;
default:
break;
}
/* read fuse ROM data */ /* read fuse ROM data */
ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR, 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) ...@@ -97,6 +108,25 @@ static int inv_magn_init(struct inv_mpu6050_state *st)
if (ret) if (ret)
return 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 * Sensitivity adjustement and scale to Gauss
* *
...@@ -104,16 +134,11 @@ static int inv_magn_init(struct inv_mpu6050_state *st) ...@@ -104,16 +134,11 @@ static int inv_magn_init(struct inv_mpu6050_state *st)
* Factor simplification: * Factor simplification:
* Hadj = H * ((ASA + 128) / 256) * Hadj = H * ((ASA + 128) / 256)
* *
* Sensor sentivity * raw_to_gauss = Hadj * sensitivity
* 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
*/ */
st->magn_raw_to_gauss[0] = (((int32_t)asa[0] + 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) * 1500) / 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) * 1500) / 256; st->magn_raw_to_gauss[2] = (((int32_t)asa[2] + 128) * sensitivity) / 256;
return 0; return 0;
} }
...@@ -129,6 +154,7 @@ static int inv_magn_init(struct inv_mpu6050_state *st) ...@@ -129,6 +154,7 @@ static int inv_magn_init(struct inv_mpu6050_state *st)
*/ */
int inv_mpu_magn_probe(struct inv_mpu6050_state *st) int inv_mpu_magn_probe(struct inv_mpu6050_state *st)
{ {
uint8_t val;
int ret; int ret;
/* quit if chip is not supported */ /* quit if chip is not supported */
...@@ -179,10 +205,17 @@ int inv_mpu_magn_probe(struct inv_mpu6050_state *st) ...@@ -179,10 +205,17 @@ int inv_mpu_magn_probe(struct inv_mpu6050_state *st)
if (ret) if (ret)
return ret; return ret;
/* add 16 bits mode */ /* add 16 bits mode for MPU925x */
ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_DO(1), val = INV_MPU_MAGN_BITS_MODE_SINGLE;
INV_MPU_MAGN_BITS_MODE_SINGLE | switch (st->chip_type) {
INV_MPU_MAGN_BIT_OUTPUT_BIT); 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) if (ret)
return ret; return ret;
...@@ -237,6 +270,7 @@ int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st) ...@@ -237,6 +270,7 @@ int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st)
/* fill magnetometer orientation */ /* fill magnetometer orientation */
switch (st->chip_type) { switch (st->chip_type) {
case INV_MPU9150:
case INV_MPU9250: case INV_MPU9250:
case INV_MPU9255: case INV_MPU9255:
/* x <- y */ /* x <- y */
......
...@@ -50,6 +50,7 @@ static void inv_scan_query(struct iio_dev *indio_dev) ...@@ -50,6 +50,7 @@ static void inv_scan_query(struct iio_dev *indio_dev)
struct inv_mpu6050_state *st = iio_priv(indio_dev); struct inv_mpu6050_state *st = iio_priv(indio_dev);
switch (st->chip_type) { switch (st->chip_type) {
case INV_MPU9150:
case INV_MPU9250: case INV_MPU9250:
case INV_MPU9255: case INV_MPU9255:
return inv_scan_query_mpu9x50(indio_dev); return inv_scan_query_mpu9x50(indio_dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment