Commit b1392de0 authored by Jean-Baptiste Maneyrol's avatar Jean-Baptiste Maneyrol Committed by Jonathan Cameron
Browse files

iio: imu: inv_mpu6050: add MPU925x magnetometer support



Add support of driving MPU9250 magnetometer connected on i2c
auxiliary bus using the MPU i2c master.

Signed-off-by: default avatarJean-Baptiste Maneyrol <jmaneyrol@invensense.com>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent 16ef4337
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@

obj-$(CONFIG_INV_MPU6050_IIO) += inv-mpu6050.o
inv-mpu6050-y := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o \
		 inv_mpu_aux.o
		 inv_mpu_aux.o inv_mpu_magn.o

obj-$(CONFIG_INV_MPU6050_I2C) += inv-mpu6050-i2c.o
inv-mpu6050-i2c-y := inv_mpu_i2c.o inv_mpu_acpi.o
+141 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include "inv_mpu_iio.h"
#include "inv_mpu_magn.h"

/*
 * this is the gyro scale translated from dynamic range plus/minus
@@ -332,6 +333,11 @@ static int inv_mpu6050_init_config(struct iio_dev *indio_dev)
	 */
	st->chip_period = NSEC_PER_MSEC;

	/* magn chip init, noop if not present in the chip */
	result = inv_mpu_magn_probe(st);
	if (result)
		goto error_power_off;

	return inv_mpu6050_set_power_itg(st, false);

error_power_off:
@@ -411,6 +417,9 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
		ret = inv_mpu6050_sensor_show(st, st->reg->temperature,
					      IIO_MOD_X, val);
		break;
	case IIO_MAGN:
		ret = inv_mpu_magn_read(st, chan->channel2, val);
		break;
	default:
		ret = -EINVAL;
		break;
@@ -469,6 +478,8 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
				*val2 = INV_MPU6050_TEMP_SCALE;

			return IIO_VAL_INT_PLUS_MICRO;
		case IIO_MAGN:
			return inv_mpu_magn_get_scale(st, chan, val, val2);
		default:
			return -EINVAL;
		}
@@ -710,6 +721,11 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr,
	if (result)
		goto fifo_rate_fail_power_off;

	/* update rate for magn, noop if not present in chip */
	result = inv_mpu_magn_set_rate(st, fifo_rate);
	if (result)
		goto fifo_rate_fail_power_off;

fifo_rate_fail_power_off:
	result |= inv_mpu6050_set_power_itg(st, false);
fifo_rate_fail_unlock:
@@ -795,8 +811,14 @@ inv_get_mount_matrix(const struct iio_dev *indio_dev,
		     const struct iio_chan_spec *chan)
{
	struct inv_mpu6050_state *data = iio_priv(indio_dev);
	const struct iio_mount_matrix *matrix;

	if (chan->type == IIO_MAGN)
		matrix = &data->magn_orient;
	else
		matrix = &data->orientation;

	return &data->orientation;
	return matrix;
}

static const struct iio_chan_spec_ext_info inv_ext_info[] = {
@@ -864,6 +886,98 @@ static const unsigned long inv_mpu_scan_masks[] = {
	0,
};

#define INV_MPU9X50_MAGN_CHAN(_chan2, _bits, _index)			\
	{								\
		.type = IIO_MAGN,					\
		.modified = 1,						\
		.channel2 = _chan2,					\
		.info_mask_separate = BIT(IIO_CHAN_INFO_SCALE) |	\
				      BIT(IIO_CHAN_INFO_RAW),		\
		.scan_index = _index,					\
		.scan_type = {						\
			.sign = 's',					\
			.realbits = _bits,				\
			.storagebits = 16,				\
			.shift = 0,					\
			.endianness = IIO_BE,				\
		},							\
		.ext_info = inv_ext_info,				\
	}

static const struct iio_chan_spec inv_mpu9250_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 16 bits */
	INV_MPU9X50_MAGN_CHAN(IIO_MOD_X, 16, INV_MPU9X50_SCAN_MAGN_X),
	INV_MPU9X50_MAGN_CHAN(IIO_MOD_Y, 16, INV_MPU9X50_SCAN_MAGN_Y),
	INV_MPU9X50_MAGN_CHAN(IIO_MOD_Z, 16, INV_MPU9X50_SCAN_MAGN_Z),
};

static const unsigned long inv_mpu9x50_scan_masks[] = {
	/* 3-axis accel */
	BIT(INV_MPU6050_SCAN_ACCL_X)
		| BIT(INV_MPU6050_SCAN_ACCL_Y)
		| BIT(INV_MPU6050_SCAN_ACCL_Z),
	/* 3-axis gyro */
	BIT(INV_MPU6050_SCAN_GYRO_X)
		| BIT(INV_MPU6050_SCAN_GYRO_Y)
		| BIT(INV_MPU6050_SCAN_GYRO_Z),
	/* 3-axis magn */
	BIT(INV_MPU9X50_SCAN_MAGN_X)
		| BIT(INV_MPU9X50_SCAN_MAGN_Y)
		| BIT(INV_MPU9X50_SCAN_MAGN_Z),
	/* 6-axis accel + gyro */
	BIT(INV_MPU6050_SCAN_ACCL_X)
		| BIT(INV_MPU6050_SCAN_ACCL_Y)
		| BIT(INV_MPU6050_SCAN_ACCL_Z)
		| BIT(INV_MPU6050_SCAN_GYRO_X)
		| BIT(INV_MPU6050_SCAN_GYRO_Y)
		| BIT(INV_MPU6050_SCAN_GYRO_Z),
	/* 6-axis accel + magn */
	BIT(INV_MPU6050_SCAN_ACCL_X)
		| BIT(INV_MPU6050_SCAN_ACCL_Y)
		| BIT(INV_MPU6050_SCAN_ACCL_Z)
		| BIT(INV_MPU9X50_SCAN_MAGN_X)
		| BIT(INV_MPU9X50_SCAN_MAGN_Y)
		| BIT(INV_MPU9X50_SCAN_MAGN_Z),
	/* 6-axis gyro + magn */
	BIT(INV_MPU6050_SCAN_GYRO_X)
		| BIT(INV_MPU6050_SCAN_GYRO_Y)
		| BIT(INV_MPU6050_SCAN_GYRO_Z)
		| BIT(INV_MPU9X50_SCAN_MAGN_X)
		| BIT(INV_MPU9X50_SCAN_MAGN_Y)
		| BIT(INV_MPU9X50_SCAN_MAGN_Z),
	/* 9-axis accel + gyro + magn */
	BIT(INV_MPU6050_SCAN_ACCL_X)
		| BIT(INV_MPU6050_SCAN_ACCL_Y)
		| BIT(INV_MPU6050_SCAN_ACCL_Z)
		| BIT(INV_MPU6050_SCAN_GYRO_X)
		| BIT(INV_MPU6050_SCAN_GYRO_Y)
		| BIT(INV_MPU6050_SCAN_GYRO_Z)
		| BIT(INV_MPU9X50_SCAN_MAGN_X)
		| BIT(INV_MPU9X50_SCAN_MAGN_Y)
		| BIT(INV_MPU9X50_SCAN_MAGN_Z),
	0,
};

static const struct iio_chan_spec inv_icm20602_channels[] = {
	IIO_CHAN_SOFT_TIMESTAMP(INV_ICM20602_SCAN_TIMESTAMP),
	{
@@ -1145,6 +1259,11 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
		return result;
	}

	/* fill magnetometer orientation */
	result = inv_mpu_magn_set_orient(st);
	if (result)
		return result;

	/* power is turned on inside check chip type*/
	result = inv_check_and_setup_chip(st);
	if (result)
@@ -1168,14 +1287,33 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
	if (inv_mpu_bus_setup)
		inv_mpu_bus_setup(indio_dev);

	if (chip_type == INV_ICM20602) {
	switch (chip_type) {
	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;
		}
		break;
	case INV_ICM20602:
		indio_dev->channels = inv_icm20602_channels;
		indio_dev->num_channels = ARRAY_SIZE(inv_icm20602_channels);
		indio_dev->available_scan_masks = inv_icm20602_scan_masks;
	} else {
		break;
	default:
		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;
	}

	indio_dev->info = &mpu_info;
+4 −0
Original line number Diff line number Diff line
@@ -130,6 +130,8 @@ struct inv_mpu6050_hw {
 *  @data_timestamp:	timestamp for next data sample.
 *  @vddio_supply	voltage regulator for the chip.
 *  @magn_disabled:     magnetometer disabled for backward compatibility reason.
 *  @magn_raw_to_gauss:	coefficient to convert mag raw value to Gauss.
 *  @magn_orient:       magnetometer sensor chip orientation if available.
 */
struct inv_mpu6050_state {
	struct mutex lock;
@@ -152,6 +154,8 @@ struct inv_mpu6050_state {
	s64 data_timestamp;
	struct regulator *vddio_supply;
	bool magn_disabled;
	s32 magn_raw_to_gauss[3];
	struct iio_mount_matrix magn_orient;
};

/*register and associated bit definition*/
+356 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2019 TDK-InvenSense, Inc.
 */

#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/string.h>

#include "inv_mpu_aux.h"
#include "inv_mpu_iio.h"
#include "inv_mpu_magn.h"

/*
 * MPU9250 magnetometer is an AKM AK8963 chip on I2C aux bus
 */
#define INV_MPU_MAGN_I2C_ADDR		0x0C

#define INV_MPU_MAGN_REG_WIA		0x00
#define INV_MPU_MAGN_BITS_WIA		0x48

#define INV_MPU_MAGN_REG_ST1		0x02
#define INV_MPU_MAGN_BIT_DRDY		0x01
#define INV_MPU_MAGN_BIT_DOR		0x02

#define INV_MPU_MAGN_REG_DATA		0x03

#define INV_MPU_MAGN_REG_ST2		0x09
#define INV_MPU_MAGN_BIT_HOFL		0x08
#define INV_MPU_MAGN_BIT_BITM		0x10

#define INV_MPU_MAGN_REG_CNTL1		0x0A
#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_MPU_MAGN_REG_CNTL2		0x0B
#define INV_MPU_MAGN_BIT_SRST		0x01

#define INV_MPU_MAGN_REG_ASAX		0x10
#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) {
	case INV_MPU9250:
	case INV_MPU9255:
		return true;
	default:
		return false;
	}
}

/* init magnetometer chip */
static int inv_magn_init(struct inv_mpu6050_state *st)
{
	uint8_t val;
	uint8_t asa[3];
	int ret;

	/* check whoami */
	ret = inv_mpu_aux_read(st, INV_MPU_MAGN_I2C_ADDR, INV_MPU_MAGN_REG_WIA,
			       &val, sizeof(val));
	if (ret)
		return ret;
	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;

	/* read fuse ROM data */
	ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR,
				INV_MPU_MAGN_REG_CNTL1,
				INV_MPU_MAGN_BITS_MODE_FUSE);
	if (ret)
		return ret;

	ret = inv_mpu_aux_read(st, INV_MPU_MAGN_I2C_ADDR, INV_MPU_MAGN_REG_ASAX,
			       asa, sizeof(asa));
	if (ret)
		return ret;

	/* switch back to power-down */
	ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR,
				INV_MPU_MAGN_REG_CNTL1,
				INV_MPU_MAGN_BITS_MODE_PWDN);
	if (ret)
		return ret;

	/*
	 * Sensitivity adjustement and scale to Gauss
	 *
	 * Hadj = H * (((ASA - 128) * 0.5 / 128) + 1)
	 * 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
	 */
	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;

	return 0;
}

/**
 * inv_mpu_magn_probe() - probe and setup magnetometer chip
 * @st: driver internal state
 *
 * Returns 0 on success, a negative error code otherwise
 *
 * It is probing the chip and setting up all needed i2c transfers.
 * Noop if there is no magnetometer in the chip.
 */
int inv_mpu_magn_probe(struct inv_mpu6050_state *st)
{
	int ret;

	/* quit if chip is not supported */
	if (!inv_magn_supported(st))
		return 0;

	/* configure i2c master aux port */
	ret = inv_mpu_aux_init(st);
	if (ret)
		return ret;

	/* check and init mag chip */
	ret = inv_magn_init(st);
	if (ret)
		return ret;

	/*
	 * configure mpu i2c master accesses
	 * i2c SLV0: read sensor data, 7 bytes data(6)-ST2
	 * Byte swap data to store them in big-endian in impair address groups
	 */
	ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_ADDR(0),
			   INV_MPU6050_BIT_I2C_SLV_RNW | INV_MPU_MAGN_I2C_ADDR);
	if (ret)
		return ret;

	ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_REG(0),
			   INV_MPU_MAGN_REG_DATA);
	if (ret)
		return ret;

	ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_CTRL(0),
			   INV_MPU6050_BIT_SLV_EN |
			   INV_MPU6050_BIT_SLV_BYTE_SW |
			   INV_MPU6050_BIT_SLV_GRP |
			   INV_MPU9X50_BYTES_MAGN);
	if (ret)
		return ret;

	/* i2c SLV1: launch single measurement */
	ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_ADDR(1),
			   INV_MPU_MAGN_I2C_ADDR);
	if (ret)
		return ret;

	ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_REG(1),
			   INV_MPU_MAGN_REG_CNTL1);
	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);
	if (ret)
		return ret;

	return regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_CTRL(1),
			    INV_MPU6050_BIT_SLV_EN | 1);
}

/**
 * inv_mpu_magn_set_rate() - set magnetometer sampling rate
 * @st: driver internal state
 * @fifo_rate: mpu set fifo rate
 *
 * Returns 0 on success, a negative error code otherwise
 *
 * Limit sampling frequency to the maximum value supported by the
 * magnetometer chip. Resulting in duplicated data for higher frequencies.
 * Noop if there is no magnetometer in the chip.
 */
int inv_mpu_magn_set_rate(const struct inv_mpu6050_state *st, int fifo_rate)
{
	uint8_t d;

	/* quit if chip is not supported */
	if (!inv_magn_supported(st))
		return 0;

	/*
	 * update i2c master delay to limit mag sampling to max frequency
	 * compute fifo_rate divider d: rate = fifo_rate / (d + 1)
	 */
	if (fifo_rate > INV_MPU_MAGN_FREQ_HZ_MAX)
		d = fifo_rate / INV_MPU_MAGN_FREQ_HZ_MAX - 1;
	else
		d = 0;

	return regmap_write(st->map, INV_MPU6050_REG_I2C_SLV4_CTRL, d);
}

/**
 * inv_mpu_magn_set_orient() - fill magnetometer mounting matrix
 * @st: driver internal state
 *
 * Returns 0 on success, a negative error code otherwise
 *
 * Fill magnetometer mounting matrix using the provided chip matrix.
 */
int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st)
{
	const char *orient;
	char *str;
	int i;

	/* fill magnetometer orientation */
	switch (st->chip_type) {
	case INV_MPU9250:
	case INV_MPU9255:
		/* x <- y */
		st->magn_orient.rotation[0] = st->orientation.rotation[3];
		st->magn_orient.rotation[1] = st->orientation.rotation[4];
		st->magn_orient.rotation[2] = st->orientation.rotation[5];
		/* y <- x */
		st->magn_orient.rotation[3] = st->orientation.rotation[0];
		st->magn_orient.rotation[4] = st->orientation.rotation[1];
		st->magn_orient.rotation[5] = st->orientation.rotation[2];
		/* z <- -z */
		for (i = 0; i < 3; ++i) {
			orient = st->orientation.rotation[6 + i];
			/* use length + 2 for adding minus sign if needed */
			str = devm_kzalloc(regmap_get_device(st->map),
					   strlen(orient) + 2, GFP_KERNEL);
			if (str == NULL)
				return -ENOMEM;
			if (strcmp(orient, "0") == 0) {
				strcpy(str, orient);
			} else if (orient[0] == '-') {
				strcpy(str, &orient[1]);
			} else {
				str[0] = '-';
				strcpy(&str[1], orient);
			}
			st->magn_orient.rotation[6 + i] = str;
		}
		break;
	default:
		st->magn_orient = st->orientation;
		break;
	}

	return 0;
}

/**
 * inv_mpu_magn_read() - read magnetometer data
 * @st: driver internal state
 * @axis: IIO modifier axis value
 * @val: store corresponding axis value
 *
 * Returns 0 on success, a negative error code otherwise
 */
int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val)
{
	unsigned int user_ctrl, status;
	__be16 data[3];
	uint8_t addr;
	uint8_t d;
	unsigned int period_ms;
	int ret;

	/* quit if chip is not supported */
	if (!inv_magn_supported(st))
		return -ENODEV;

	/* Mag data: X - Y - Z */
	switch (axis) {
	case IIO_MOD_X:
		addr = 0;
		break;
	case IIO_MOD_Y:
		addr = 1;
		break;
	case IIO_MOD_Z:
		addr = 2;
		break;
	default:
		return -EINVAL;
	}

	/* set sample rate to max mag freq */
	d = INV_MPU6050_FIFO_RATE_TO_DIVIDER(INV_MPU_MAGN_FREQ_HZ_MAX);
	ret = regmap_write(st->map, st->reg->sample_rate_div, d);
	if (ret)
		return ret;

	/* 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);
	if (ret)
		return ret;

	/* need to wait 2 periods + half-period margin */
	period_ms = 1000 / INV_MPU_MAGN_FREQ_HZ_MAX;
	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);
	if (ret)
		return ret;

	/* restore sample rate */
	d = st->chip_config.divider;
	ret = regmap_write(st->map, st->reg->sample_rate_div, d);
	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)
		return ret;

	if (status & INV_MPU6050_BIT_I2C_SLV0_NACK ||
			status & INV_MPU6050_BIT_I2C_SLV1_NACK)
		return -EIO;

	ret = regmap_bulk_read(st->map, INV_MPU6050_REG_EXT_SENS_DATA,
			       data, sizeof(data));
	if (ret)
		return ret;

	*val = (int16_t)be16_to_cpu(data[addr]);

	return IIO_VAL_INT;
}
+36 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2019 TDK-InvenSense, Inc.
 */

#ifndef INV_MPU_MAGN_H_
#define INV_MPU_MAGN_H_

#include <linux/kernel.h>

#include "inv_mpu_iio.h"

int inv_mpu_magn_probe(struct inv_mpu6050_state *st);

/**
 * inv_mpu_magn_get_scale() - get magnetometer scale value
 * @st: driver internal state
 *
 * Returns IIO data format.
 */
static inline int inv_mpu_magn_get_scale(const struct inv_mpu6050_state *st,
					 const struct iio_chan_spec *chan,
					 int *val, int *val2)
{
	*val = 0;
	*val2 = st->magn_raw_to_gauss[chan->address];
	return IIO_VAL_INT_PLUS_MICRO;
}

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

#endif		/* INV_MPU_MAGN_H_ */