xref: /openbmc/linux/drivers/iio/imu/kmx61.c (revision b25862c577979659020f3575838d366f480ec3bf)
120ffac27SDaniel Baluta /*
220ffac27SDaniel Baluta  * KMX61 - Kionix 6-axis Accelerometer/Magnetometer
320ffac27SDaniel Baluta  *
420ffac27SDaniel Baluta  * Copyright (c) 2014, Intel Corporation.
520ffac27SDaniel Baluta  *
620ffac27SDaniel Baluta  * This file is subject to the terms and conditions of version 2 of
720ffac27SDaniel Baluta  * the GNU General Public License.  See the file COPYING in the main
820ffac27SDaniel Baluta  * directory of this archive for more details.
920ffac27SDaniel Baluta  *
1020ffac27SDaniel Baluta  * IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F).
1120ffac27SDaniel Baluta  *
1220ffac27SDaniel Baluta  */
1320ffac27SDaniel Baluta 
1420ffac27SDaniel Baluta #include <linux/module.h>
1520ffac27SDaniel Baluta #include <linux/i2c.h>
16*b25862c5SDaniel Baluta #include <linux/acpi.h>
17*b25862c5SDaniel Baluta #include <linux/gpio/consumer.h>
1820ffac27SDaniel Baluta #include <linux/iio/iio.h>
1920ffac27SDaniel Baluta #include <linux/iio/sysfs.h>
2020ffac27SDaniel Baluta 
2120ffac27SDaniel Baluta #define KMX61_DRV_NAME "kmx61"
22*b25862c5SDaniel Baluta #define KMX61_GPIO_NAME "kmx61_int"
2320ffac27SDaniel Baluta 
2420ffac27SDaniel Baluta #define KMX61_REG_WHO_AM_I	0x00
2520ffac27SDaniel Baluta 
2620ffac27SDaniel Baluta /*
2720ffac27SDaniel Baluta  * three 16-bit accelerometer output registers for X/Y/Z axis
2820ffac27SDaniel Baluta  * we use only XOUT_L as a base register, all other addresses
2920ffac27SDaniel Baluta  * can be obtained by applying an offset and are provided here
3020ffac27SDaniel Baluta  * only for clarity.
3120ffac27SDaniel Baluta  */
3220ffac27SDaniel Baluta #define KMX61_ACC_XOUT_L	0x0A
3320ffac27SDaniel Baluta #define KMX61_ACC_XOUT_H	0x0B
3420ffac27SDaniel Baluta #define KMX61_ACC_YOUT_L	0x0C
3520ffac27SDaniel Baluta #define KMX61_ACC_YOUT_H	0x0D
3620ffac27SDaniel Baluta #define KMX61_ACC_ZOUT_L	0x0E
3720ffac27SDaniel Baluta #define KMX61_ACC_ZOUT_H	0x0F
3820ffac27SDaniel Baluta 
3920ffac27SDaniel Baluta /*
4020ffac27SDaniel Baluta  * one 16-bit temperature output register
4120ffac27SDaniel Baluta  */
4220ffac27SDaniel Baluta #define KMX61_TEMP_L		0x10
4320ffac27SDaniel Baluta #define KMX61_TEMP_H		0x11
4420ffac27SDaniel Baluta 
4520ffac27SDaniel Baluta /*
4620ffac27SDaniel Baluta  * three 16-bit magnetometer output registers for X/Y/Z axis
4720ffac27SDaniel Baluta  */
4820ffac27SDaniel Baluta #define KMX61_MAG_XOUT_L	0x12
4920ffac27SDaniel Baluta #define KMX61_MAG_XOUT_H	0x13
5020ffac27SDaniel Baluta #define KMX61_MAG_YOUT_L	0x14
5120ffac27SDaniel Baluta #define KMX61_MAG_YOUT_H	0x15
5220ffac27SDaniel Baluta #define KMX61_MAG_ZOUT_L	0x16
5320ffac27SDaniel Baluta #define KMX61_MAG_ZOUT_H	0x17
5420ffac27SDaniel Baluta 
5520ffac27SDaniel Baluta #define KMX61_REG_STBY		0x29
5620ffac27SDaniel Baluta #define KMX61_REG_CTRL1		0x2A
5720ffac27SDaniel Baluta #define KMX61_REG_ODCNTL	0x2C
5820ffac27SDaniel Baluta 
5920ffac27SDaniel Baluta #define KMX61_ACC_STBY_BIT	BIT(0)
6020ffac27SDaniel Baluta #define KMX61_MAG_STBY_BIT	BIT(1)
6120ffac27SDaniel Baluta #define KMX61_ACT_STBY_BIT	BIT(7)
6220ffac27SDaniel Baluta 
6320ffac27SDaniel Baluta #define KMX61_ALL_STBY		(KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT)
6420ffac27SDaniel Baluta 
6520ffac27SDaniel Baluta #define KMX61_REG_CTRL1_GSEL_MASK	0x03
6620ffac27SDaniel Baluta 
6720ffac27SDaniel Baluta #define KMX61_ACC_ODR_SHIFT	0
6820ffac27SDaniel Baluta #define KMX61_MAG_ODR_SHIFT	4
6920ffac27SDaniel Baluta #define KMX61_ACC_ODR_MASK	0x0F
7020ffac27SDaniel Baluta #define KMX61_MAG_ODR_MASK	0xF0
7120ffac27SDaniel Baluta 
7220ffac27SDaniel Baluta #define KMX61_CHIP_ID		0x12
7320ffac27SDaniel Baluta 
7420ffac27SDaniel Baluta /* KMX61 devices */
7520ffac27SDaniel Baluta #define KMX61_ACC	0x01
7620ffac27SDaniel Baluta #define KMX61_MAG	0x02
7720ffac27SDaniel Baluta 
7820ffac27SDaniel Baluta struct kmx61_data {
7920ffac27SDaniel Baluta 	struct i2c_client *client;
8020ffac27SDaniel Baluta 
8120ffac27SDaniel Baluta 	/* serialize access to non-atomic ops, e.g set_mode */
8220ffac27SDaniel Baluta 	struct mutex lock;
8320ffac27SDaniel Baluta 
8420ffac27SDaniel Baluta 	/* standby state */
8520ffac27SDaniel Baluta 	bool acc_stby;
8620ffac27SDaniel Baluta 	bool mag_stby;
8720ffac27SDaniel Baluta 
8820ffac27SDaniel Baluta 	/* config bits */
8920ffac27SDaniel Baluta 	u8 range;
9020ffac27SDaniel Baluta 	u8 odr_bits;
9120ffac27SDaniel Baluta 
9220ffac27SDaniel Baluta 	/* accelerometer specific data */
9320ffac27SDaniel Baluta 	struct iio_dev *acc_indio_dev;
9420ffac27SDaniel Baluta 
9520ffac27SDaniel Baluta 	/* magnetometer specific data */
9620ffac27SDaniel Baluta 	struct iio_dev *mag_indio_dev;
9720ffac27SDaniel Baluta };
9820ffac27SDaniel Baluta 
9920ffac27SDaniel Baluta enum kmx61_range {
10020ffac27SDaniel Baluta 	KMX61_RANGE_2G,
10120ffac27SDaniel Baluta 	KMX61_RANGE_4G,
10220ffac27SDaniel Baluta 	KMX61_RANGE_8G,
10320ffac27SDaniel Baluta };
10420ffac27SDaniel Baluta 
10520ffac27SDaniel Baluta enum kmx61_axis {
10620ffac27SDaniel Baluta 	KMX61_AXIS_X,
10720ffac27SDaniel Baluta 	KMX61_AXIS_Y,
10820ffac27SDaniel Baluta 	KMX61_AXIS_Z,
10920ffac27SDaniel Baluta };
11020ffac27SDaniel Baluta 
11120ffac27SDaniel Baluta static const u16 kmx61_uscale_table[] = {9582, 19163, 38326};
11220ffac27SDaniel Baluta 
11320ffac27SDaniel Baluta static const struct {
11420ffac27SDaniel Baluta 	int val;
11520ffac27SDaniel Baluta 	int val2;
11620ffac27SDaniel Baluta 	u8 odr_bits;
11720ffac27SDaniel Baluta } kmx61_samp_freq_table[] = { {12, 500000, 0x00},
11820ffac27SDaniel Baluta 			{25, 0, 0x01},
11920ffac27SDaniel Baluta 			{50, 0, 0x02},
12020ffac27SDaniel Baluta 			{100, 0, 0x03},
12120ffac27SDaniel Baluta 			{200, 0, 0x04},
12220ffac27SDaniel Baluta 			{400, 0, 0x05},
12320ffac27SDaniel Baluta 			{800, 0, 0x06},
12420ffac27SDaniel Baluta 			{1600, 0, 0x07},
12520ffac27SDaniel Baluta 			{0, 781000, 0x08},
12620ffac27SDaniel Baluta 			{1, 563000, 0x09},
12720ffac27SDaniel Baluta 			{3, 125000, 0x0A},
12820ffac27SDaniel Baluta 			{6, 250000, 0x0B} };
12920ffac27SDaniel Baluta 
13020ffac27SDaniel Baluta static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326");
13120ffac27SDaniel Baluta static IIO_CONST_ATTR(magn_scale_available, "0.001465");
13220ffac27SDaniel Baluta static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
13320ffac27SDaniel Baluta 	"0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800");
13420ffac27SDaniel Baluta 
13520ffac27SDaniel Baluta static struct attribute *kmx61_acc_attributes[] = {
13620ffac27SDaniel Baluta 	&iio_const_attr_accel_scale_available.dev_attr.attr,
13720ffac27SDaniel Baluta 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
13820ffac27SDaniel Baluta 	NULL,
13920ffac27SDaniel Baluta };
14020ffac27SDaniel Baluta 
14120ffac27SDaniel Baluta static struct attribute *kmx61_mag_attributes[] = {
14220ffac27SDaniel Baluta 	&iio_const_attr_magn_scale_available.dev_attr.attr,
14320ffac27SDaniel Baluta 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
14420ffac27SDaniel Baluta 	NULL,
14520ffac27SDaniel Baluta };
14620ffac27SDaniel Baluta 
14720ffac27SDaniel Baluta static const struct attribute_group kmx61_acc_attribute_group = {
14820ffac27SDaniel Baluta 	.attrs = kmx61_acc_attributes,
14920ffac27SDaniel Baluta };
15020ffac27SDaniel Baluta 
15120ffac27SDaniel Baluta static const struct attribute_group kmx61_mag_attribute_group = {
15220ffac27SDaniel Baluta 	.attrs = kmx61_mag_attributes,
15320ffac27SDaniel Baluta };
15420ffac27SDaniel Baluta 
15520ffac27SDaniel Baluta #define KMX61_ACC_CHAN(_axis) { \
15620ffac27SDaniel Baluta 	.type = IIO_ACCEL, \
15720ffac27SDaniel Baluta 	.modified = 1, \
15820ffac27SDaniel Baluta 	.channel2 = IIO_MOD_ ## _axis, \
15920ffac27SDaniel Baluta 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
16020ffac27SDaniel Baluta 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
16120ffac27SDaniel Baluta 				BIT(IIO_CHAN_INFO_SAMP_FREQ), \
16220ffac27SDaniel Baluta 	.address = KMX61_ACC, \
16320ffac27SDaniel Baluta 	.scan_index = KMX61_AXIS_ ## _axis, \
16420ffac27SDaniel Baluta 	.scan_type = { \
16520ffac27SDaniel Baluta 		.sign = 's', \
16620ffac27SDaniel Baluta 		.realbits = 12, \
16720ffac27SDaniel Baluta 		.storagebits = 16, \
16820ffac27SDaniel Baluta 		.shift = 4, \
16920ffac27SDaniel Baluta 		.endianness = IIO_LE, \
17020ffac27SDaniel Baluta 	}, \
17120ffac27SDaniel Baluta }
17220ffac27SDaniel Baluta 
17320ffac27SDaniel Baluta #define KMX61_MAG_CHAN(_axis) { \
17420ffac27SDaniel Baluta 	.type = IIO_MAGN, \
17520ffac27SDaniel Baluta 	.modified = 1, \
17620ffac27SDaniel Baluta 	.channel2 = IIO_MOD_ ## _axis, \
17720ffac27SDaniel Baluta 	.address = KMX61_MAG, \
17820ffac27SDaniel Baluta 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
17920ffac27SDaniel Baluta 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
18020ffac27SDaniel Baluta 				BIT(IIO_CHAN_INFO_SAMP_FREQ), \
18120ffac27SDaniel Baluta 	.scan_index = KMX61_AXIS_ ## _axis, \
18220ffac27SDaniel Baluta 	.scan_type = { \
18320ffac27SDaniel Baluta 		.sign = 's', \
18420ffac27SDaniel Baluta 		.realbits = 14, \
18520ffac27SDaniel Baluta 		.storagebits = 16, \
18620ffac27SDaniel Baluta 		.shift = 2, \
18720ffac27SDaniel Baluta 		.endianness = IIO_LE, \
18820ffac27SDaniel Baluta 	}, \
18920ffac27SDaniel Baluta }
19020ffac27SDaniel Baluta 
19120ffac27SDaniel Baluta static const struct iio_chan_spec kmx61_acc_channels[] = {
19220ffac27SDaniel Baluta 	KMX61_ACC_CHAN(X),
19320ffac27SDaniel Baluta 	KMX61_ACC_CHAN(Y),
19420ffac27SDaniel Baluta 	KMX61_ACC_CHAN(Z),
19520ffac27SDaniel Baluta };
19620ffac27SDaniel Baluta 
19720ffac27SDaniel Baluta static const struct iio_chan_spec kmx61_mag_channels[] = {
19820ffac27SDaniel Baluta 	KMX61_MAG_CHAN(X),
19920ffac27SDaniel Baluta 	KMX61_MAG_CHAN(Y),
20020ffac27SDaniel Baluta 	KMX61_MAG_CHAN(Z),
20120ffac27SDaniel Baluta };
20220ffac27SDaniel Baluta 
20320ffac27SDaniel Baluta static void kmx61_set_data(struct iio_dev *indio_dev, struct kmx61_data *data)
20420ffac27SDaniel Baluta {
20520ffac27SDaniel Baluta 	struct kmx61_data **priv = iio_priv(indio_dev);
20620ffac27SDaniel Baluta 
20720ffac27SDaniel Baluta 	*priv = data;
20820ffac27SDaniel Baluta }
20920ffac27SDaniel Baluta 
21020ffac27SDaniel Baluta static struct kmx61_data *kmx61_get_data(struct iio_dev *indio_dev)
21120ffac27SDaniel Baluta {
21220ffac27SDaniel Baluta 	return *(struct kmx61_data **)iio_priv(indio_dev);
21320ffac27SDaniel Baluta }
21420ffac27SDaniel Baluta 
21520ffac27SDaniel Baluta static int kmx61_convert_freq_to_bit(int val, int val2)
21620ffac27SDaniel Baluta {
21720ffac27SDaniel Baluta 	int i;
21820ffac27SDaniel Baluta 
21920ffac27SDaniel Baluta 	for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++)
22020ffac27SDaniel Baluta 		if (val == kmx61_samp_freq_table[i].val &&
22120ffac27SDaniel Baluta 		    val2 == kmx61_samp_freq_table[i].val2)
22220ffac27SDaniel Baluta 			return kmx61_samp_freq_table[i].odr_bits;
22320ffac27SDaniel Baluta 	return -EINVAL;
22420ffac27SDaniel Baluta }
22520ffac27SDaniel Baluta 
22620ffac27SDaniel Baluta /**
22720ffac27SDaniel Baluta  * kmx61_set_mode() - set KMX61 device operating mode
22820ffac27SDaniel Baluta  * @data - kmx61 device private data pointer
22920ffac27SDaniel Baluta  * @mode - bitmask, indicating operating mode for @device
23020ffac27SDaniel Baluta  * @device - bitmask, indicating device for which @mode needs to be set
23120ffac27SDaniel Baluta  * @update - update stby bits stored in device's private  @data
23220ffac27SDaniel Baluta  *
23320ffac27SDaniel Baluta  * For each sensor (accelerometer/magnetometer) there are two operating modes
23420ffac27SDaniel Baluta  * STANDBY and OPERATION. Neither accel nor magn can be disabled independently
23520ffac27SDaniel Baluta  * if they are both enabled. Internal sensors state is saved in acc_stby and
23620ffac27SDaniel Baluta  * mag_stby members of driver's private @data.
23720ffac27SDaniel Baluta  */
23820ffac27SDaniel Baluta static int kmx61_set_mode(struct kmx61_data *data, u8 mode, u8 device,
23920ffac27SDaniel Baluta 			  bool update)
24020ffac27SDaniel Baluta {
24120ffac27SDaniel Baluta 	int ret;
24220ffac27SDaniel Baluta 	int acc_stby = -1, mag_stby = -1;
24320ffac27SDaniel Baluta 
24420ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY);
24520ffac27SDaniel Baluta 	if (ret < 0) {
24620ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_stby\n");
24720ffac27SDaniel Baluta 		return ret;
24820ffac27SDaniel Baluta 	}
24920ffac27SDaniel Baluta 	if (device & KMX61_ACC) {
25020ffac27SDaniel Baluta 		if (mode & KMX61_ACC_STBY_BIT) {
25120ffac27SDaniel Baluta 			ret |= KMX61_ACC_STBY_BIT;
25220ffac27SDaniel Baluta 			acc_stby = 1;
25320ffac27SDaniel Baluta 		} else {
25420ffac27SDaniel Baluta 			ret &= ~KMX61_ACC_STBY_BIT;
25520ffac27SDaniel Baluta 			acc_stby = 0;
25620ffac27SDaniel Baluta 		}
25720ffac27SDaniel Baluta 	}
25820ffac27SDaniel Baluta 
25920ffac27SDaniel Baluta 	if (device & KMX61_MAG) {
26020ffac27SDaniel Baluta 		if (mode & KMX61_MAG_STBY_BIT) {
26120ffac27SDaniel Baluta 			ret |= KMX61_MAG_STBY_BIT;
26220ffac27SDaniel Baluta 			mag_stby = 1;
26320ffac27SDaniel Baluta 		} else {
26420ffac27SDaniel Baluta 			ret &= ~KMX61_MAG_STBY_BIT;
26520ffac27SDaniel Baluta 			mag_stby = 0;
26620ffac27SDaniel Baluta 		}
26720ffac27SDaniel Baluta 	}
26820ffac27SDaniel Baluta 
26920ffac27SDaniel Baluta 	if (mode & KMX61_ACT_STBY_BIT)
27020ffac27SDaniel Baluta 		ret |= KMX61_ACT_STBY_BIT;
27120ffac27SDaniel Baluta 
27220ffac27SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_STBY, ret);
27320ffac27SDaniel Baluta 	if (ret < 0) {
27420ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_stby\n");
27520ffac27SDaniel Baluta 		return ret;
27620ffac27SDaniel Baluta 	}
27720ffac27SDaniel Baluta 
27820ffac27SDaniel Baluta 	if (acc_stby != -1 && update)
27920ffac27SDaniel Baluta 		data->acc_stby = acc_stby;
28020ffac27SDaniel Baluta 	if (mag_stby != -1 && update)
28120ffac27SDaniel Baluta 		data->mag_stby = mag_stby;
28220ffac27SDaniel Baluta 
28320ffac27SDaniel Baluta 	return 0;
28420ffac27SDaniel Baluta }
28520ffac27SDaniel Baluta 
28620ffac27SDaniel Baluta static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device)
28720ffac27SDaniel Baluta {
28820ffac27SDaniel Baluta 	int ret;
28920ffac27SDaniel Baluta 
29020ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY);
29120ffac27SDaniel Baluta 	if (ret < 0) {
29220ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_stby\n");
29320ffac27SDaniel Baluta 		return ret;
29420ffac27SDaniel Baluta 	}
29520ffac27SDaniel Baluta 	*mode = 0;
29620ffac27SDaniel Baluta 
29720ffac27SDaniel Baluta 	if (device & KMX61_ACC) {
29820ffac27SDaniel Baluta 		if (ret & KMX61_ACC_STBY_BIT)
29920ffac27SDaniel Baluta 			*mode |= KMX61_ACC_STBY_BIT;
30020ffac27SDaniel Baluta 		else
30120ffac27SDaniel Baluta 			*mode &= ~KMX61_ACC_STBY_BIT;
30220ffac27SDaniel Baluta 	}
30320ffac27SDaniel Baluta 
30420ffac27SDaniel Baluta 	if (device & KMX61_MAG) {
30520ffac27SDaniel Baluta 		if (ret & KMX61_MAG_STBY_BIT)
30620ffac27SDaniel Baluta 			*mode |= KMX61_MAG_STBY_BIT;
30720ffac27SDaniel Baluta 		else
30820ffac27SDaniel Baluta 			*mode &= ~KMX61_MAG_STBY_BIT;
30920ffac27SDaniel Baluta 	}
31020ffac27SDaniel Baluta 
31120ffac27SDaniel Baluta 	return 0;
31220ffac27SDaniel Baluta }
31320ffac27SDaniel Baluta 
31420ffac27SDaniel Baluta static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device)
31520ffac27SDaniel Baluta {
31620ffac27SDaniel Baluta 	int ret;
31720ffac27SDaniel Baluta 	u8 mode;
31820ffac27SDaniel Baluta 	int lodr_bits, odr_bits;
31920ffac27SDaniel Baluta 
32020ffac27SDaniel Baluta 	ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG);
32120ffac27SDaniel Baluta 	if (ret < 0)
32220ffac27SDaniel Baluta 		return ret;
32320ffac27SDaniel Baluta 
32420ffac27SDaniel Baluta 	lodr_bits = kmx61_convert_freq_to_bit(val, val2);
32520ffac27SDaniel Baluta 	if (lodr_bits < 0)
32620ffac27SDaniel Baluta 		return lodr_bits;
32720ffac27SDaniel Baluta 
32820ffac27SDaniel Baluta 	/* To change ODR, accel and magn must be in STDBY */
32920ffac27SDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG,
33020ffac27SDaniel Baluta 			     true);
33120ffac27SDaniel Baluta 	if (ret < 0)
33220ffac27SDaniel Baluta 		return ret;
33320ffac27SDaniel Baluta 
33420ffac27SDaniel Baluta 	odr_bits = 0;
33520ffac27SDaniel Baluta 	if (device & KMX61_ACC)
33620ffac27SDaniel Baluta 		odr_bits |= lodr_bits << KMX61_ACC_ODR_SHIFT;
33720ffac27SDaniel Baluta 	if (device & KMX61_MAG)
33820ffac27SDaniel Baluta 		odr_bits |= lodr_bits << KMX61_MAG_ODR_SHIFT;
33920ffac27SDaniel Baluta 
34020ffac27SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_ODCNTL,
34120ffac27SDaniel Baluta 					odr_bits);
34220ffac27SDaniel Baluta 	if (ret < 0)
34320ffac27SDaniel Baluta 		return ret;
34420ffac27SDaniel Baluta 
34520ffac27SDaniel Baluta 	return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true);
34620ffac27SDaniel Baluta }
34720ffac27SDaniel Baluta 
34820ffac27SDaniel Baluta static int kmx61_get_odr(struct kmx61_data *data, int *val, int *val2,
34920ffac27SDaniel Baluta 			 u8 device)
35020ffac27SDaniel Baluta {	int i;
35120ffac27SDaniel Baluta 	u8 lodr_bits;
35220ffac27SDaniel Baluta 
35320ffac27SDaniel Baluta 	if (device & KMX61_ACC)
35420ffac27SDaniel Baluta 		lodr_bits = (data->odr_bits >> KMX61_ACC_ODR_SHIFT) &
35520ffac27SDaniel Baluta 			     KMX61_ACC_ODR_MASK;
35620ffac27SDaniel Baluta 	else if (device & KMX61_MAG)
35720ffac27SDaniel Baluta 		lodr_bits = (data->odr_bits >> KMX61_MAG_ODR_SHIFT) &
35820ffac27SDaniel Baluta 			     KMX61_MAG_ODR_MASK;
35920ffac27SDaniel Baluta 	else
36020ffac27SDaniel Baluta 		return -EINVAL;
36120ffac27SDaniel Baluta 
36220ffac27SDaniel Baluta 	for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++)
36320ffac27SDaniel Baluta 		if (lodr_bits == kmx61_samp_freq_table[i].odr_bits) {
36420ffac27SDaniel Baluta 			*val = kmx61_samp_freq_table[i].val;
36520ffac27SDaniel Baluta 			*val2 = kmx61_samp_freq_table[i].val2;
36620ffac27SDaniel Baluta 			return 0;
36720ffac27SDaniel Baluta 		}
36820ffac27SDaniel Baluta 	return -EINVAL;
36920ffac27SDaniel Baluta }
37020ffac27SDaniel Baluta 
37120ffac27SDaniel Baluta static int kmx61_set_range(struct kmx61_data *data, u8 range)
37220ffac27SDaniel Baluta {
37320ffac27SDaniel Baluta 	int ret;
37420ffac27SDaniel Baluta 
37520ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1);
37620ffac27SDaniel Baluta 	if (ret < 0) {
37720ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
37820ffac27SDaniel Baluta 		return ret;
37920ffac27SDaniel Baluta 	}
38020ffac27SDaniel Baluta 
38120ffac27SDaniel Baluta 	ret &= ~KMX61_REG_CTRL1_GSEL_MASK;
38220ffac27SDaniel Baluta 	ret |= range & KMX61_REG_CTRL1_GSEL_MASK;
38320ffac27SDaniel Baluta 
38420ffac27SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret);
38520ffac27SDaniel Baluta 	if (ret < 0) {
38620ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
38720ffac27SDaniel Baluta 		return ret;
38820ffac27SDaniel Baluta 	}
38920ffac27SDaniel Baluta 
39020ffac27SDaniel Baluta 	data->range = range;
39120ffac27SDaniel Baluta 
39220ffac27SDaniel Baluta 	return 0;
39320ffac27SDaniel Baluta }
39420ffac27SDaniel Baluta 
39520ffac27SDaniel Baluta static int kmx61_set_scale(struct kmx61_data *data, u16 uscale)
39620ffac27SDaniel Baluta {
39720ffac27SDaniel Baluta 	int ret, i;
39820ffac27SDaniel Baluta 	u8  mode;
39920ffac27SDaniel Baluta 
40020ffac27SDaniel Baluta 	for (i = 0; i < ARRAY_SIZE(kmx61_uscale_table); i++) {
40120ffac27SDaniel Baluta 		if (kmx61_uscale_table[i] == uscale) {
40220ffac27SDaniel Baluta 			ret = kmx61_get_mode(data, &mode,
40320ffac27SDaniel Baluta 					     KMX61_ACC | KMX61_MAG);
40420ffac27SDaniel Baluta 			if (ret < 0)
40520ffac27SDaniel Baluta 				return ret;
40620ffac27SDaniel Baluta 
40720ffac27SDaniel Baluta 			ret = kmx61_set_mode(data, KMX61_ALL_STBY,
40820ffac27SDaniel Baluta 					     KMX61_ACC | KMX61_MAG, true);
40920ffac27SDaniel Baluta 			if (ret < 0)
41020ffac27SDaniel Baluta 				return ret;
41120ffac27SDaniel Baluta 
41220ffac27SDaniel Baluta 			ret = kmx61_set_range(data, i);
41320ffac27SDaniel Baluta 			if (ret < 0)
41420ffac27SDaniel Baluta 				return ret;
41520ffac27SDaniel Baluta 
41620ffac27SDaniel Baluta 			return  kmx61_set_mode(data, mode,
41720ffac27SDaniel Baluta 					       KMX61_ACC | KMX61_MAG, true);
41820ffac27SDaniel Baluta 		}
41920ffac27SDaniel Baluta 	}
42020ffac27SDaniel Baluta 	return -EINVAL;
42120ffac27SDaniel Baluta }
42220ffac27SDaniel Baluta 
42320ffac27SDaniel Baluta static int kmx61_chip_init(struct kmx61_data *data)
42420ffac27SDaniel Baluta {
42520ffac27SDaniel Baluta 	int ret;
42620ffac27SDaniel Baluta 
42720ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I);
42820ffac27SDaniel Baluta 	if (ret < 0) {
42920ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading who_am_i\n");
43020ffac27SDaniel Baluta 		return ret;
43120ffac27SDaniel Baluta 	}
43220ffac27SDaniel Baluta 
43320ffac27SDaniel Baluta 	if (ret != KMX61_CHIP_ID) {
43420ffac27SDaniel Baluta 		dev_err(&data->client->dev,
43520ffac27SDaniel Baluta 			"Wrong chip id, got %x expected %x\n",
43620ffac27SDaniel Baluta 			 ret, KMX61_CHIP_ID);
43720ffac27SDaniel Baluta 		return -EINVAL;
43820ffac27SDaniel Baluta 	}
43920ffac27SDaniel Baluta 
44020ffac27SDaniel Baluta 	/* set accel 12bit, 4g range */
44120ffac27SDaniel Baluta 	ret = kmx61_set_range(data, KMX61_RANGE_4G);
44220ffac27SDaniel Baluta 	if (ret < 0)
44320ffac27SDaniel Baluta 		return ret;
44420ffac27SDaniel Baluta 
44520ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_ODCNTL);
44620ffac27SDaniel Baluta 	if (ret < 0) {
44720ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_odcntl\n");
44820ffac27SDaniel Baluta 		return ret;
44920ffac27SDaniel Baluta 	}
45020ffac27SDaniel Baluta 	data->odr_bits = ret;
45120ffac27SDaniel Baluta 
45220ffac27SDaniel Baluta 	/* set acc/magn to OPERATION mode */
45320ffac27SDaniel Baluta 	ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true);
45420ffac27SDaniel Baluta 	if (ret < 0)
45520ffac27SDaniel Baluta 		return ret;
45620ffac27SDaniel Baluta 
45720ffac27SDaniel Baluta 	return 0;
45820ffac27SDaniel Baluta }
45920ffac27SDaniel Baluta 
46020ffac27SDaniel Baluta static int kmx61_read_measurement(struct kmx61_data *data, u8 base, u8 offset)
46120ffac27SDaniel Baluta {
46220ffac27SDaniel Baluta 	int ret;
46320ffac27SDaniel Baluta 	u8 reg = base + offset * 2;
46420ffac27SDaniel Baluta 
46520ffac27SDaniel Baluta 	ret = i2c_smbus_read_word_data(data->client, reg);
46620ffac27SDaniel Baluta 	if (ret < 0)
46720ffac27SDaniel Baluta 		dev_err(&data->client->dev, "failed to read reg at %x\n", reg);
46820ffac27SDaniel Baluta 
46920ffac27SDaniel Baluta 	return ret;
47020ffac27SDaniel Baluta }
47120ffac27SDaniel Baluta 
47220ffac27SDaniel Baluta static int kmx61_read_raw(struct iio_dev *indio_dev,
47320ffac27SDaniel Baluta 			  struct iio_chan_spec const *chan, int *val,
47420ffac27SDaniel Baluta 			  int *val2, long mask)
47520ffac27SDaniel Baluta {
47620ffac27SDaniel Baluta 	int ret;
47720ffac27SDaniel Baluta 	u8 base_reg;
47820ffac27SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
47920ffac27SDaniel Baluta 
48020ffac27SDaniel Baluta 	switch (mask) {
48120ffac27SDaniel Baluta 	case IIO_CHAN_INFO_RAW:
48220ffac27SDaniel Baluta 		switch (chan->type) {
48320ffac27SDaniel Baluta 		case IIO_ACCEL:
48420ffac27SDaniel Baluta 			base_reg = KMX61_ACC_XOUT_L;
48520ffac27SDaniel Baluta 			break;
48620ffac27SDaniel Baluta 		case IIO_MAGN:
48720ffac27SDaniel Baluta 			base_reg = KMX61_MAG_XOUT_L;
48820ffac27SDaniel Baluta 			break;
48920ffac27SDaniel Baluta 		default:
49020ffac27SDaniel Baluta 			return -EINVAL;
49120ffac27SDaniel Baluta 		}
49220ffac27SDaniel Baluta 		mutex_lock(&data->lock);
49320ffac27SDaniel Baluta 
49420ffac27SDaniel Baluta 		ret = kmx61_read_measurement(data, base_reg, chan->scan_index);
49520ffac27SDaniel Baluta 		if (ret < 0) {
49620ffac27SDaniel Baluta 			mutex_unlock(&data->lock);
49720ffac27SDaniel Baluta 			return ret;
49820ffac27SDaniel Baluta 		}
49920ffac27SDaniel Baluta 		*val = sign_extend32(ret >> chan->scan_type.shift,
50020ffac27SDaniel Baluta 				     chan->scan_type.realbits - 1);
50120ffac27SDaniel Baluta 
50220ffac27SDaniel Baluta 		mutex_unlock(&data->lock);
50320ffac27SDaniel Baluta 		return IIO_VAL_INT;
50420ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SCALE:
50520ffac27SDaniel Baluta 		switch (chan->type) {
50620ffac27SDaniel Baluta 		case IIO_ACCEL:
50720ffac27SDaniel Baluta 			*val = 0;
50820ffac27SDaniel Baluta 			*val2 = kmx61_uscale_table[data->range];
50920ffac27SDaniel Baluta 			return IIO_VAL_INT_PLUS_MICRO;
51020ffac27SDaniel Baluta 		case IIO_MAGN:
51120ffac27SDaniel Baluta 			/* 14 bits res, 1465 microGauss per magn count */
51220ffac27SDaniel Baluta 			*val = 0;
51320ffac27SDaniel Baluta 			*val2 = 1465;
51420ffac27SDaniel Baluta 			return IIO_VAL_INT_PLUS_MICRO;
51520ffac27SDaniel Baluta 		default:
51620ffac27SDaniel Baluta 			return -EINVAL;
51720ffac27SDaniel Baluta 		}
51820ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SAMP_FREQ:
51920ffac27SDaniel Baluta 		if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN)
52020ffac27SDaniel Baluta 			return -EINVAL;
52120ffac27SDaniel Baluta 
52220ffac27SDaniel Baluta 		mutex_lock(&data->lock);
52320ffac27SDaniel Baluta 		ret = kmx61_get_odr(data, val, val2, chan->address);
52420ffac27SDaniel Baluta 		mutex_unlock(&data->lock);
52520ffac27SDaniel Baluta 		if (ret)
52620ffac27SDaniel Baluta 			return -EINVAL;
52720ffac27SDaniel Baluta 		return IIO_VAL_INT_PLUS_MICRO;
52820ffac27SDaniel Baluta 	}
52920ffac27SDaniel Baluta 	return -EINVAL;
53020ffac27SDaniel Baluta }
53120ffac27SDaniel Baluta 
53220ffac27SDaniel Baluta static int kmx61_write_raw(struct iio_dev *indio_dev,
53320ffac27SDaniel Baluta 			   struct iio_chan_spec const *chan, int val,
53420ffac27SDaniel Baluta 			   int val2, long mask)
53520ffac27SDaniel Baluta {
53620ffac27SDaniel Baluta 	int ret;
53720ffac27SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
53820ffac27SDaniel Baluta 
53920ffac27SDaniel Baluta 	switch (mask) {
54020ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SAMP_FREQ:
54120ffac27SDaniel Baluta 		if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN)
54220ffac27SDaniel Baluta 			return -EINVAL;
54320ffac27SDaniel Baluta 
54420ffac27SDaniel Baluta 		mutex_lock(&data->lock);
54520ffac27SDaniel Baluta 		ret = kmx61_set_odr(data, val, val2, chan->address);
54620ffac27SDaniel Baluta 		mutex_unlock(&data->lock);
54720ffac27SDaniel Baluta 		return ret;
54820ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SCALE:
54920ffac27SDaniel Baluta 		switch (chan->type) {
55020ffac27SDaniel Baluta 		case IIO_ACCEL:
55120ffac27SDaniel Baluta 			if (val != 0)
55220ffac27SDaniel Baluta 				return -EINVAL;
55320ffac27SDaniel Baluta 			mutex_lock(&data->lock);
55420ffac27SDaniel Baluta 			ret = kmx61_set_scale(data, val2);
55520ffac27SDaniel Baluta 			mutex_unlock(&data->lock);
55620ffac27SDaniel Baluta 			return ret;
55720ffac27SDaniel Baluta 		default:
55820ffac27SDaniel Baluta 			return -EINVAL;
55920ffac27SDaniel Baluta 		}
56020ffac27SDaniel Baluta 	default:
56120ffac27SDaniel Baluta 		return -EINVAL;
56220ffac27SDaniel Baluta 	}
56320ffac27SDaniel Baluta }
56420ffac27SDaniel Baluta 
56520ffac27SDaniel Baluta static const struct iio_info kmx61_acc_info = {
56620ffac27SDaniel Baluta 	.driver_module		= THIS_MODULE,
56720ffac27SDaniel Baluta 	.read_raw		= kmx61_read_raw,
56820ffac27SDaniel Baluta 	.write_raw		= kmx61_write_raw,
56920ffac27SDaniel Baluta 	.attrs			= &kmx61_acc_attribute_group,
57020ffac27SDaniel Baluta };
57120ffac27SDaniel Baluta 
57220ffac27SDaniel Baluta static const struct iio_info kmx61_mag_info = {
57320ffac27SDaniel Baluta 	.driver_module		= THIS_MODULE,
57420ffac27SDaniel Baluta 	.read_raw		= kmx61_read_raw,
57520ffac27SDaniel Baluta 	.write_raw		= kmx61_write_raw,
57620ffac27SDaniel Baluta 	.attrs			= &kmx61_mag_attribute_group,
57720ffac27SDaniel Baluta };
57820ffac27SDaniel Baluta 
579*b25862c5SDaniel Baluta static const char *kmx61_match_acpi_device(struct device *dev)
580*b25862c5SDaniel Baluta {
581*b25862c5SDaniel Baluta 	const struct acpi_device_id *id;
582*b25862c5SDaniel Baluta 
583*b25862c5SDaniel Baluta 	id = acpi_match_device(dev->driver->acpi_match_table, dev);
584*b25862c5SDaniel Baluta 	if (!id)
585*b25862c5SDaniel Baluta 		return NULL;
586*b25862c5SDaniel Baluta 	return dev_name(dev);
587*b25862c5SDaniel Baluta }
588*b25862c5SDaniel Baluta 
589*b25862c5SDaniel Baluta static int kmx61_gpio_probe(struct i2c_client *client, struct kmx61_data *data)
590*b25862c5SDaniel Baluta {
591*b25862c5SDaniel Baluta 	struct device *dev;
592*b25862c5SDaniel Baluta 	struct gpio_desc *gpio;
593*b25862c5SDaniel Baluta 	int ret;
594*b25862c5SDaniel Baluta 
595*b25862c5SDaniel Baluta 	if (!client)
596*b25862c5SDaniel Baluta 		return -EINVAL;
597*b25862c5SDaniel Baluta 
598*b25862c5SDaniel Baluta 	dev = &client->dev;
599*b25862c5SDaniel Baluta 
600*b25862c5SDaniel Baluta 	/* data ready gpio interrupt pin */
601*b25862c5SDaniel Baluta 	gpio = devm_gpiod_get_index(dev, KMX61_GPIO_NAME, 0);
602*b25862c5SDaniel Baluta 	if (IS_ERR(gpio)) {
603*b25862c5SDaniel Baluta 		dev_err(dev, "acpi gpio get index failed\n");
604*b25862c5SDaniel Baluta 		return PTR_ERR(gpio);
605*b25862c5SDaniel Baluta 	}
606*b25862c5SDaniel Baluta 
607*b25862c5SDaniel Baluta 	ret = gpiod_direction_input(gpio);
608*b25862c5SDaniel Baluta 	if (ret)
609*b25862c5SDaniel Baluta 		return ret;
610*b25862c5SDaniel Baluta 
611*b25862c5SDaniel Baluta 	ret = gpiod_to_irq(gpio);
612*b25862c5SDaniel Baluta 
613*b25862c5SDaniel Baluta 	dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
614*b25862c5SDaniel Baluta 	return ret;
615*b25862c5SDaniel Baluta }
616*b25862c5SDaniel Baluta 
61720ffac27SDaniel Baluta static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data,
61820ffac27SDaniel Baluta 					    const struct iio_info *info,
61920ffac27SDaniel Baluta 					    const struct iio_chan_spec *chan,
62020ffac27SDaniel Baluta 					    int num_channels,
62120ffac27SDaniel Baluta 					    const char *name)
62220ffac27SDaniel Baluta {
62320ffac27SDaniel Baluta 	struct iio_dev *indio_dev;
62420ffac27SDaniel Baluta 
62520ffac27SDaniel Baluta 	indio_dev = devm_iio_device_alloc(&data->client->dev, sizeof(data));
62620ffac27SDaniel Baluta 	if (!indio_dev)
62720ffac27SDaniel Baluta 		return ERR_PTR(-ENOMEM);
62820ffac27SDaniel Baluta 
62920ffac27SDaniel Baluta 	kmx61_set_data(indio_dev, data);
63020ffac27SDaniel Baluta 
63120ffac27SDaniel Baluta 	indio_dev->dev.parent = &data->client->dev;
63220ffac27SDaniel Baluta 	indio_dev->channels = chan;
63320ffac27SDaniel Baluta 	indio_dev->num_channels = num_channels;
63420ffac27SDaniel Baluta 	indio_dev->name = name;
63520ffac27SDaniel Baluta 	indio_dev->modes = INDIO_DIRECT_MODE;
63620ffac27SDaniel Baluta 	indio_dev->info = info;
63720ffac27SDaniel Baluta 
63820ffac27SDaniel Baluta 	return indio_dev;
63920ffac27SDaniel Baluta }
64020ffac27SDaniel Baluta 
64120ffac27SDaniel Baluta static int kmx61_probe(struct i2c_client *client,
64220ffac27SDaniel Baluta 		       const struct i2c_device_id *id)
64320ffac27SDaniel Baluta {
64420ffac27SDaniel Baluta 	int ret;
64520ffac27SDaniel Baluta 	struct kmx61_data *data;
64620ffac27SDaniel Baluta 	const char *name = NULL;
64720ffac27SDaniel Baluta 
64820ffac27SDaniel Baluta 	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
64920ffac27SDaniel Baluta 	if (!data)
65020ffac27SDaniel Baluta 		return -ENOMEM;
65120ffac27SDaniel Baluta 
65220ffac27SDaniel Baluta 	i2c_set_clientdata(client, data);
65320ffac27SDaniel Baluta 	data->client = client;
65420ffac27SDaniel Baluta 
65520ffac27SDaniel Baluta 	mutex_init(&data->lock);
65620ffac27SDaniel Baluta 
657*b25862c5SDaniel Baluta 	if (id)
658*b25862c5SDaniel Baluta 		name = id->name;
659*b25862c5SDaniel Baluta 	else if (ACPI_HANDLE(&client->dev))
660*b25862c5SDaniel Baluta 		name = kmx61_match_acpi_device(&client->dev);
661*b25862c5SDaniel Baluta 	else
662*b25862c5SDaniel Baluta 		return -ENODEV;
663*b25862c5SDaniel Baluta 
66420ffac27SDaniel Baluta 	data->acc_indio_dev =
66520ffac27SDaniel Baluta 		kmx61_indiodev_setup(data, &kmx61_acc_info,
66620ffac27SDaniel Baluta 				     kmx61_acc_channels,
66720ffac27SDaniel Baluta 				     ARRAY_SIZE(kmx61_acc_channels),
66820ffac27SDaniel Baluta 				     name);
66920ffac27SDaniel Baluta 	if (IS_ERR(data->acc_indio_dev))
67020ffac27SDaniel Baluta 		return PTR_ERR(data->acc_indio_dev);
67120ffac27SDaniel Baluta 
67220ffac27SDaniel Baluta 	data->mag_indio_dev =
67320ffac27SDaniel Baluta 		kmx61_indiodev_setup(data, &kmx61_mag_info,
67420ffac27SDaniel Baluta 				     kmx61_mag_channels,
67520ffac27SDaniel Baluta 				     ARRAY_SIZE(kmx61_mag_channels),
67620ffac27SDaniel Baluta 				     name);
67720ffac27SDaniel Baluta 	if (IS_ERR(data->mag_indio_dev))
67820ffac27SDaniel Baluta 		return PTR_ERR(data->mag_indio_dev);
67920ffac27SDaniel Baluta 
68020ffac27SDaniel Baluta 	ret = kmx61_chip_init(data);
68120ffac27SDaniel Baluta 	if (ret < 0)
68220ffac27SDaniel Baluta 		return ret;
68320ffac27SDaniel Baluta 
684*b25862c5SDaniel Baluta 	if (client->irq < 0)
685*b25862c5SDaniel Baluta 		client->irq = kmx61_gpio_probe(client, data);
686*b25862c5SDaniel Baluta 
68720ffac27SDaniel Baluta 	ret = iio_device_register(data->acc_indio_dev);
68820ffac27SDaniel Baluta 	if (ret < 0) {
68920ffac27SDaniel Baluta 		dev_err(&client->dev, "Failed to register acc iio device\n");
69020ffac27SDaniel Baluta 		goto err_chip_uninit;
69120ffac27SDaniel Baluta 	}
69220ffac27SDaniel Baluta 
69320ffac27SDaniel Baluta 	ret = iio_device_register(data->mag_indio_dev);
69420ffac27SDaniel Baluta 	if (ret < 0) {
69520ffac27SDaniel Baluta 		dev_err(&client->dev, "Failed to register mag iio device\n");
69620ffac27SDaniel Baluta 		goto err_iio_unregister;
69720ffac27SDaniel Baluta 	}
69820ffac27SDaniel Baluta 
69920ffac27SDaniel Baluta 	return 0;
70020ffac27SDaniel Baluta 
70120ffac27SDaniel Baluta err_iio_unregister:
70220ffac27SDaniel Baluta 	iio_device_unregister(data->acc_indio_dev);
70320ffac27SDaniel Baluta err_chip_uninit:
70420ffac27SDaniel Baluta 	kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
70520ffac27SDaniel Baluta 	return ret;
70620ffac27SDaniel Baluta }
70720ffac27SDaniel Baluta 
70820ffac27SDaniel Baluta static int kmx61_remove(struct i2c_client *client)
70920ffac27SDaniel Baluta {
71020ffac27SDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(client);
71120ffac27SDaniel Baluta 
71220ffac27SDaniel Baluta 	iio_device_unregister(data->acc_indio_dev);
71320ffac27SDaniel Baluta 	iio_device_unregister(data->mag_indio_dev);
71420ffac27SDaniel Baluta 
71520ffac27SDaniel Baluta 	mutex_lock(&data->lock);
71620ffac27SDaniel Baluta 	kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
71720ffac27SDaniel Baluta 	mutex_unlock(&data->lock);
71820ffac27SDaniel Baluta 
71920ffac27SDaniel Baluta 	return 0;
72020ffac27SDaniel Baluta }
72120ffac27SDaniel Baluta 
722*b25862c5SDaniel Baluta static const struct acpi_device_id kmx61_acpi_match[] = {
723*b25862c5SDaniel Baluta 	{"KMX61021", 0},
724*b25862c5SDaniel Baluta 	{}
725*b25862c5SDaniel Baluta };
726*b25862c5SDaniel Baluta 
727*b25862c5SDaniel Baluta MODULE_DEVICE_TABLE(acpi, kmx61_acpi_match);
728*b25862c5SDaniel Baluta 
72920ffac27SDaniel Baluta static const struct i2c_device_id kmx61_id[] = {
73020ffac27SDaniel Baluta 	{"kmx611021", 0},
73120ffac27SDaniel Baluta 	{}
73220ffac27SDaniel Baluta };
73320ffac27SDaniel Baluta 
73420ffac27SDaniel Baluta MODULE_DEVICE_TABLE(i2c, kmx61_id);
73520ffac27SDaniel Baluta 
73620ffac27SDaniel Baluta static struct i2c_driver kmx61_driver = {
73720ffac27SDaniel Baluta 	.driver = {
73820ffac27SDaniel Baluta 		.name = KMX61_DRV_NAME,
739*b25862c5SDaniel Baluta 		.acpi_match_table = ACPI_PTR(kmx61_acpi_match),
74020ffac27SDaniel Baluta 	},
74120ffac27SDaniel Baluta 	.probe		= kmx61_probe,
74220ffac27SDaniel Baluta 	.remove		= kmx61_remove,
74320ffac27SDaniel Baluta 	.id_table	= kmx61_id,
74420ffac27SDaniel Baluta };
74520ffac27SDaniel Baluta 
74620ffac27SDaniel Baluta module_i2c_driver(kmx61_driver);
74720ffac27SDaniel Baluta 
74820ffac27SDaniel Baluta MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
74920ffac27SDaniel Baluta MODULE_DESCRIPTION("KMX61 accelerometer/magnetometer driver");
75020ffac27SDaniel Baluta MODULE_LICENSE("GPL v2");
751