xref: /openbmc/linux/drivers/iio/imu/kmx61.c (revision 36edc93958e06dfc15b61d1cfa7f33929bc26fe4)
1*36edc939SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
220ffac27SDaniel Baluta /*
320ffac27SDaniel Baluta  * KMX61 - Kionix 6-axis Accelerometer/Magnetometer
420ffac27SDaniel Baluta  *
520ffac27SDaniel Baluta  * Copyright (c) 2014, Intel Corporation.
620ffac27SDaniel Baluta  *
720ffac27SDaniel Baluta  * IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F).
820ffac27SDaniel Baluta  */
920ffac27SDaniel Baluta 
1020ffac27SDaniel Baluta #include <linux/module.h>
1120ffac27SDaniel Baluta #include <linux/i2c.h>
12b25862c5SDaniel Baluta #include <linux/acpi.h>
13aff8609aSDaniel Baluta #include <linux/interrupt.h>
143b9c40e6SDaniel Baluta #include <linux/pm.h>
15aff8609aSDaniel Baluta #include <linux/pm_runtime.h>
1620ffac27SDaniel Baluta #include <linux/iio/iio.h>
1720ffac27SDaniel Baluta #include <linux/iio/sysfs.h>
18fd3ae7a9SDaniel Baluta #include <linux/iio/events.h>
19c3a23eccSDaniel Baluta #include <linux/iio/trigger.h>
20c3a23eccSDaniel Baluta #include <linux/iio/buffer.h>
21c3a23eccSDaniel Baluta #include <linux/iio/triggered_buffer.h>
22c3a23eccSDaniel Baluta #include <linux/iio/trigger_consumer.h>
2320ffac27SDaniel Baluta 
2420ffac27SDaniel Baluta #define KMX61_DRV_NAME "kmx61"
25c3a23eccSDaniel Baluta #define KMX61_IRQ_NAME "kmx61_event"
2620ffac27SDaniel Baluta 
2720ffac27SDaniel Baluta #define KMX61_REG_WHO_AM_I	0x00
28fd3ae7a9SDaniel Baluta #define KMX61_REG_INS1		0x01
29fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2		0x02
3020ffac27SDaniel Baluta 
3120ffac27SDaniel Baluta /*
3220ffac27SDaniel Baluta  * three 16-bit accelerometer output registers for X/Y/Z axis
3320ffac27SDaniel Baluta  * we use only XOUT_L as a base register, all other addresses
3420ffac27SDaniel Baluta  * can be obtained by applying an offset and are provided here
3520ffac27SDaniel Baluta  * only for clarity.
3620ffac27SDaniel Baluta  */
3720ffac27SDaniel Baluta #define KMX61_ACC_XOUT_L	0x0A
3820ffac27SDaniel Baluta #define KMX61_ACC_XOUT_H	0x0B
3920ffac27SDaniel Baluta #define KMX61_ACC_YOUT_L	0x0C
4020ffac27SDaniel Baluta #define KMX61_ACC_YOUT_H	0x0D
4120ffac27SDaniel Baluta #define KMX61_ACC_ZOUT_L	0x0E
4220ffac27SDaniel Baluta #define KMX61_ACC_ZOUT_H	0x0F
4320ffac27SDaniel Baluta 
4420ffac27SDaniel Baluta /*
4520ffac27SDaniel Baluta  * one 16-bit temperature output register
4620ffac27SDaniel Baluta  */
4720ffac27SDaniel Baluta #define KMX61_TEMP_L		0x10
4820ffac27SDaniel Baluta #define KMX61_TEMP_H		0x11
4920ffac27SDaniel Baluta 
5020ffac27SDaniel Baluta /*
5120ffac27SDaniel Baluta  * three 16-bit magnetometer output registers for X/Y/Z axis
5220ffac27SDaniel Baluta  */
5320ffac27SDaniel Baluta #define KMX61_MAG_XOUT_L	0x12
5420ffac27SDaniel Baluta #define KMX61_MAG_XOUT_H	0x13
5520ffac27SDaniel Baluta #define KMX61_MAG_YOUT_L	0x14
5620ffac27SDaniel Baluta #define KMX61_MAG_YOUT_H	0x15
5720ffac27SDaniel Baluta #define KMX61_MAG_ZOUT_L	0x16
5820ffac27SDaniel Baluta #define KMX61_MAG_ZOUT_H	0x17
5920ffac27SDaniel Baluta 
60c3a23eccSDaniel Baluta #define KMX61_REG_INL		0x28
6120ffac27SDaniel Baluta #define KMX61_REG_STBY		0x29
6220ffac27SDaniel Baluta #define KMX61_REG_CTRL1		0x2A
63fd3ae7a9SDaniel Baluta #define KMX61_REG_CTRL2		0x2B
6420ffac27SDaniel Baluta #define KMX61_REG_ODCNTL	0x2C
65c3a23eccSDaniel Baluta #define KMX61_REG_INC1		0x2D
6620ffac27SDaniel Baluta 
67fd3ae7a9SDaniel Baluta #define KMX61_REG_WUF_THRESH	0x3D
68fd3ae7a9SDaniel Baluta #define KMX61_REG_WUF_TIMER	0x3E
69fd3ae7a9SDaniel Baluta 
7020ffac27SDaniel Baluta #define KMX61_ACC_STBY_BIT	BIT(0)
7120ffac27SDaniel Baluta #define KMX61_MAG_STBY_BIT	BIT(1)
7220ffac27SDaniel Baluta #define KMX61_ACT_STBY_BIT	BIT(7)
7320ffac27SDaniel Baluta 
7420ffac27SDaniel Baluta #define KMX61_ALL_STBY		(KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT)
7520ffac27SDaniel Baluta 
76fd3ae7a9SDaniel Baluta #define KMX61_REG_INS1_BIT_WUFS		BIT(1)
77fd3ae7a9SDaniel Baluta 
78fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_ZP		BIT(0)
79fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_ZN		BIT(1)
80fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_YP		BIT(2)
81fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_YN		BIT(3)
82fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_XP		BIT(4)
83fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_XN		BIT(5)
84fd3ae7a9SDaniel Baluta 
8520ffac27SDaniel Baluta #define KMX61_REG_CTRL1_GSEL_MASK	0x03
8620ffac27SDaniel Baluta 
87c3a23eccSDaniel Baluta #define KMX61_REG_CTRL1_BIT_RES		BIT(4)
88c3a23eccSDaniel Baluta #define KMX61_REG_CTRL1_BIT_DRDYE	BIT(5)
89fd3ae7a9SDaniel Baluta #define KMX61_REG_CTRL1_BIT_WUFE	BIT(6)
90fd3ae7a9SDaniel Baluta #define KMX61_REG_CTRL1_BIT_BTSE	BIT(7)
91c3a23eccSDaniel Baluta 
92fd3ae7a9SDaniel Baluta #define KMX61_REG_INC1_BIT_WUFS		BIT(0)
93c3a23eccSDaniel Baluta #define KMX61_REG_INC1_BIT_DRDYM	BIT(1)
94c3a23eccSDaniel Baluta #define KMX61_REG_INC1_BIT_DRDYA	BIT(2)
95c3a23eccSDaniel Baluta #define KMX61_REG_INC1_BIT_IEN		BIT(5)
96c3a23eccSDaniel Baluta 
9720ffac27SDaniel Baluta #define KMX61_ACC_ODR_SHIFT	0
9820ffac27SDaniel Baluta #define KMX61_MAG_ODR_SHIFT	4
9920ffac27SDaniel Baluta #define KMX61_ACC_ODR_MASK	0x0F
10020ffac27SDaniel Baluta #define KMX61_MAG_ODR_MASK	0xF0
10120ffac27SDaniel Baluta 
102fd3ae7a9SDaniel Baluta #define KMX61_OWUF_MASK		0x7
103fd3ae7a9SDaniel Baluta 
104fd3ae7a9SDaniel Baluta #define KMX61_DEFAULT_WAKE_THRESH	1
105fd3ae7a9SDaniel Baluta #define KMX61_DEFAULT_WAKE_DURATION	1
106fd3ae7a9SDaniel Baluta 
107aff8609aSDaniel Baluta #define KMX61_SLEEP_DELAY_MS	2000
108aff8609aSDaniel Baluta 
10920ffac27SDaniel Baluta #define KMX61_CHIP_ID		0x12
11020ffac27SDaniel Baluta 
11120ffac27SDaniel Baluta /* KMX61 devices */
11220ffac27SDaniel Baluta #define KMX61_ACC	0x01
11320ffac27SDaniel Baluta #define KMX61_MAG	0x02
11420ffac27SDaniel Baluta 
11520ffac27SDaniel Baluta struct kmx61_data {
11620ffac27SDaniel Baluta 	struct i2c_client *client;
11720ffac27SDaniel Baluta 
11820ffac27SDaniel Baluta 	/* serialize access to non-atomic ops, e.g set_mode */
11920ffac27SDaniel Baluta 	struct mutex lock;
12020ffac27SDaniel Baluta 
12120ffac27SDaniel Baluta 	/* standby state */
12220ffac27SDaniel Baluta 	bool acc_stby;
12320ffac27SDaniel Baluta 	bool mag_stby;
12420ffac27SDaniel Baluta 
125aff8609aSDaniel Baluta 	/* power state */
126aff8609aSDaniel Baluta 	bool acc_ps;
127aff8609aSDaniel Baluta 	bool mag_ps;
128aff8609aSDaniel Baluta 
12920ffac27SDaniel Baluta 	/* config bits */
13020ffac27SDaniel Baluta 	u8 range;
13120ffac27SDaniel Baluta 	u8 odr_bits;
132fd3ae7a9SDaniel Baluta 	u8 wake_thresh;
133fd3ae7a9SDaniel Baluta 	u8 wake_duration;
13420ffac27SDaniel Baluta 
13520ffac27SDaniel Baluta 	/* accelerometer specific data */
13620ffac27SDaniel Baluta 	struct iio_dev *acc_indio_dev;
137c3a23eccSDaniel Baluta 	struct iio_trigger *acc_dready_trig;
138fd3ae7a9SDaniel Baluta 	struct iio_trigger *motion_trig;
139c3a23eccSDaniel Baluta 	bool acc_dready_trig_on;
140fd3ae7a9SDaniel Baluta 	bool motion_trig_on;
141fd3ae7a9SDaniel Baluta 	bool ev_enable_state;
14220ffac27SDaniel Baluta 
14320ffac27SDaniel Baluta 	/* magnetometer specific data */
14420ffac27SDaniel Baluta 	struct iio_dev *mag_indio_dev;
145c3a23eccSDaniel Baluta 	struct iio_trigger *mag_dready_trig;
146c3a23eccSDaniel Baluta 	bool mag_dready_trig_on;
14720ffac27SDaniel Baluta };
14820ffac27SDaniel Baluta 
14920ffac27SDaniel Baluta enum kmx61_range {
15020ffac27SDaniel Baluta 	KMX61_RANGE_2G,
15120ffac27SDaniel Baluta 	KMX61_RANGE_4G,
15220ffac27SDaniel Baluta 	KMX61_RANGE_8G,
15320ffac27SDaniel Baluta };
15420ffac27SDaniel Baluta 
15520ffac27SDaniel Baluta enum kmx61_axis {
15620ffac27SDaniel Baluta 	KMX61_AXIS_X,
15720ffac27SDaniel Baluta 	KMX61_AXIS_Y,
15820ffac27SDaniel Baluta 	KMX61_AXIS_Z,
15920ffac27SDaniel Baluta };
16020ffac27SDaniel Baluta 
16120ffac27SDaniel Baluta static const u16 kmx61_uscale_table[] = {9582, 19163, 38326};
16220ffac27SDaniel Baluta 
16320ffac27SDaniel Baluta static const struct {
16420ffac27SDaniel Baluta 	int val;
16520ffac27SDaniel Baluta 	int val2;
166a36385a2SDaniel Baluta } kmx61_samp_freq_table[] = { {12, 500000},
167a36385a2SDaniel Baluta 			{25, 0},
168a36385a2SDaniel Baluta 			{50, 0},
169a36385a2SDaniel Baluta 			{100, 0},
170a36385a2SDaniel Baluta 			{200, 0},
171a36385a2SDaniel Baluta 			{400, 0},
172a36385a2SDaniel Baluta 			{800, 0},
173a36385a2SDaniel Baluta 			{1600, 0},
174a36385a2SDaniel Baluta 			{0, 781000},
175a36385a2SDaniel Baluta 			{1, 563000},
176a36385a2SDaniel Baluta 			{3, 125000},
177a36385a2SDaniel Baluta 			{6, 250000} };
17820ffac27SDaniel Baluta 
179fd3ae7a9SDaniel Baluta static const struct {
180fd3ae7a9SDaniel Baluta 	int val;
181fd3ae7a9SDaniel Baluta 	int val2;
182fd3ae7a9SDaniel Baluta 	int odr_bits;
183fd3ae7a9SDaniel Baluta } kmx61_wake_up_odr_table[] = { {0, 781000, 0x00},
184fd3ae7a9SDaniel Baluta 				 {1, 563000, 0x01},
185fd3ae7a9SDaniel Baluta 				 {3, 125000, 0x02},
186fd3ae7a9SDaniel Baluta 				 {6, 250000, 0x03},
187fd3ae7a9SDaniel Baluta 				 {12, 500000, 0x04},
188fd3ae7a9SDaniel Baluta 				 {25, 0, 0x05},
189fd3ae7a9SDaniel Baluta 				 {50, 0, 0x06},
190fd3ae7a9SDaniel Baluta 				 {100, 0, 0x06},
191fd3ae7a9SDaniel Baluta 				 {200, 0, 0x06},
192fd3ae7a9SDaniel Baluta 				 {400, 0, 0x06},
193fd3ae7a9SDaniel Baluta 				 {800, 0, 0x06},
194fd3ae7a9SDaniel Baluta 				 {1600, 0, 0x06} };
195fd3ae7a9SDaniel Baluta 
19620ffac27SDaniel Baluta static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326");
19720ffac27SDaniel Baluta static IIO_CONST_ATTR(magn_scale_available, "0.001465");
19820ffac27SDaniel Baluta static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
19920ffac27SDaniel Baluta 	"0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800");
20020ffac27SDaniel Baluta 
20120ffac27SDaniel Baluta static struct attribute *kmx61_acc_attributes[] = {
20220ffac27SDaniel Baluta 	&iio_const_attr_accel_scale_available.dev_attr.attr,
20320ffac27SDaniel Baluta 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
20420ffac27SDaniel Baluta 	NULL,
20520ffac27SDaniel Baluta };
20620ffac27SDaniel Baluta 
20720ffac27SDaniel Baluta static struct attribute *kmx61_mag_attributes[] = {
20820ffac27SDaniel Baluta 	&iio_const_attr_magn_scale_available.dev_attr.attr,
20920ffac27SDaniel Baluta 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
21020ffac27SDaniel Baluta 	NULL,
21120ffac27SDaniel Baluta };
21220ffac27SDaniel Baluta 
21320ffac27SDaniel Baluta static const struct attribute_group kmx61_acc_attribute_group = {
21420ffac27SDaniel Baluta 	.attrs = kmx61_acc_attributes,
21520ffac27SDaniel Baluta };
21620ffac27SDaniel Baluta 
21720ffac27SDaniel Baluta static const struct attribute_group kmx61_mag_attribute_group = {
21820ffac27SDaniel Baluta 	.attrs = kmx61_mag_attributes,
21920ffac27SDaniel Baluta };
22020ffac27SDaniel Baluta 
221fd3ae7a9SDaniel Baluta static const struct iio_event_spec kmx61_event = {
222fd3ae7a9SDaniel Baluta 	.type = IIO_EV_TYPE_THRESH,
223fd3ae7a9SDaniel Baluta 	.dir = IIO_EV_DIR_EITHER,
224fd3ae7a9SDaniel Baluta 	.mask_separate = BIT(IIO_EV_INFO_VALUE) |
225fd3ae7a9SDaniel Baluta 			 BIT(IIO_EV_INFO_ENABLE) |
226fd3ae7a9SDaniel Baluta 			 BIT(IIO_EV_INFO_PERIOD),
227fd3ae7a9SDaniel Baluta };
228fd3ae7a9SDaniel Baluta 
22920ffac27SDaniel Baluta #define KMX61_ACC_CHAN(_axis) { \
23020ffac27SDaniel Baluta 	.type = IIO_ACCEL, \
23120ffac27SDaniel Baluta 	.modified = 1, \
23220ffac27SDaniel Baluta 	.channel2 = IIO_MOD_ ## _axis, \
23320ffac27SDaniel Baluta 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
23420ffac27SDaniel Baluta 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
23520ffac27SDaniel Baluta 				BIT(IIO_CHAN_INFO_SAMP_FREQ), \
23620ffac27SDaniel Baluta 	.address = KMX61_ACC, \
23720ffac27SDaniel Baluta 	.scan_index = KMX61_AXIS_ ## _axis, \
23820ffac27SDaniel Baluta 	.scan_type = { \
23920ffac27SDaniel Baluta 		.sign = 's', \
24020ffac27SDaniel Baluta 		.realbits = 12, \
24120ffac27SDaniel Baluta 		.storagebits = 16, \
24220ffac27SDaniel Baluta 		.shift = 4, \
24320ffac27SDaniel Baluta 		.endianness = IIO_LE, \
24420ffac27SDaniel Baluta 	}, \
245fd3ae7a9SDaniel Baluta 	.event_spec = &kmx61_event, \
246fd3ae7a9SDaniel Baluta 	.num_event_specs = 1 \
24720ffac27SDaniel Baluta }
24820ffac27SDaniel Baluta 
24920ffac27SDaniel Baluta #define KMX61_MAG_CHAN(_axis) { \
25020ffac27SDaniel Baluta 	.type = IIO_MAGN, \
25120ffac27SDaniel Baluta 	.modified = 1, \
25220ffac27SDaniel Baluta 	.channel2 = IIO_MOD_ ## _axis, \
25320ffac27SDaniel Baluta 	.address = KMX61_MAG, \
25420ffac27SDaniel Baluta 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
25520ffac27SDaniel Baluta 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
25620ffac27SDaniel Baluta 				BIT(IIO_CHAN_INFO_SAMP_FREQ), \
25720ffac27SDaniel Baluta 	.scan_index = KMX61_AXIS_ ## _axis, \
25820ffac27SDaniel Baluta 	.scan_type = { \
25920ffac27SDaniel Baluta 		.sign = 's', \
26020ffac27SDaniel Baluta 		.realbits = 14, \
26120ffac27SDaniel Baluta 		.storagebits = 16, \
26220ffac27SDaniel Baluta 		.shift = 2, \
26320ffac27SDaniel Baluta 		.endianness = IIO_LE, \
26420ffac27SDaniel Baluta 	}, \
26520ffac27SDaniel Baluta }
26620ffac27SDaniel Baluta 
26720ffac27SDaniel Baluta static const struct iio_chan_spec kmx61_acc_channels[] = {
26820ffac27SDaniel Baluta 	KMX61_ACC_CHAN(X),
26920ffac27SDaniel Baluta 	KMX61_ACC_CHAN(Y),
27020ffac27SDaniel Baluta 	KMX61_ACC_CHAN(Z),
27120ffac27SDaniel Baluta };
27220ffac27SDaniel Baluta 
27320ffac27SDaniel Baluta static const struct iio_chan_spec kmx61_mag_channels[] = {
27420ffac27SDaniel Baluta 	KMX61_MAG_CHAN(X),
27520ffac27SDaniel Baluta 	KMX61_MAG_CHAN(Y),
27620ffac27SDaniel Baluta 	KMX61_MAG_CHAN(Z),
27720ffac27SDaniel Baluta };
27820ffac27SDaniel Baluta 
27920ffac27SDaniel Baluta static void kmx61_set_data(struct iio_dev *indio_dev, struct kmx61_data *data)
28020ffac27SDaniel Baluta {
28120ffac27SDaniel Baluta 	struct kmx61_data **priv = iio_priv(indio_dev);
28220ffac27SDaniel Baluta 
28320ffac27SDaniel Baluta 	*priv = data;
28420ffac27SDaniel Baluta }
28520ffac27SDaniel Baluta 
28620ffac27SDaniel Baluta static struct kmx61_data *kmx61_get_data(struct iio_dev *indio_dev)
28720ffac27SDaniel Baluta {
28820ffac27SDaniel Baluta 	return *(struct kmx61_data **)iio_priv(indio_dev);
28920ffac27SDaniel Baluta }
29020ffac27SDaniel Baluta 
29120ffac27SDaniel Baluta static int kmx61_convert_freq_to_bit(int val, int val2)
29220ffac27SDaniel Baluta {
29320ffac27SDaniel Baluta 	int i;
29420ffac27SDaniel Baluta 
29520ffac27SDaniel Baluta 	for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++)
29620ffac27SDaniel Baluta 		if (val == kmx61_samp_freq_table[i].val &&
29720ffac27SDaniel Baluta 		    val2 == kmx61_samp_freq_table[i].val2)
298a36385a2SDaniel Baluta 			return i;
29920ffac27SDaniel Baluta 	return -EINVAL;
30020ffac27SDaniel Baluta }
30120ffac27SDaniel Baluta 
302fd3ae7a9SDaniel Baluta static int kmx61_convert_wake_up_odr_to_bit(int val, int val2)
303fd3ae7a9SDaniel Baluta {
304fd3ae7a9SDaniel Baluta 	int i;
305fd3ae7a9SDaniel Baluta 
306fd3ae7a9SDaniel Baluta 	for (i = 0; i < ARRAY_SIZE(kmx61_wake_up_odr_table); ++i)
307fd3ae7a9SDaniel Baluta 		if (kmx61_wake_up_odr_table[i].val == val &&
308fd3ae7a9SDaniel Baluta 			kmx61_wake_up_odr_table[i].val2 == val2)
309fd3ae7a9SDaniel Baluta 				return kmx61_wake_up_odr_table[i].odr_bits;
310fd3ae7a9SDaniel Baluta 	return -EINVAL;
311fd3ae7a9SDaniel Baluta }
312fd3ae7a9SDaniel Baluta 
31320ffac27SDaniel Baluta /**
31420ffac27SDaniel Baluta  * kmx61_set_mode() - set KMX61 device operating mode
31520ffac27SDaniel Baluta  * @data - kmx61 device private data pointer
31620ffac27SDaniel Baluta  * @mode - bitmask, indicating operating mode for @device
31720ffac27SDaniel Baluta  * @device - bitmask, indicating device for which @mode needs to be set
31820ffac27SDaniel Baluta  * @update - update stby bits stored in device's private  @data
31920ffac27SDaniel Baluta  *
32020ffac27SDaniel Baluta  * For each sensor (accelerometer/magnetometer) there are two operating modes
32120ffac27SDaniel Baluta  * STANDBY and OPERATION. Neither accel nor magn can be disabled independently
32220ffac27SDaniel Baluta  * if they are both enabled. Internal sensors state is saved in acc_stby and
32320ffac27SDaniel Baluta  * mag_stby members of driver's private @data.
32420ffac27SDaniel Baluta  */
32520ffac27SDaniel Baluta static int kmx61_set_mode(struct kmx61_data *data, u8 mode, u8 device,
32620ffac27SDaniel Baluta 			  bool update)
32720ffac27SDaniel Baluta {
32820ffac27SDaniel Baluta 	int ret;
32920ffac27SDaniel Baluta 	int acc_stby = -1, mag_stby = -1;
33020ffac27SDaniel Baluta 
33120ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY);
33220ffac27SDaniel Baluta 	if (ret < 0) {
33320ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_stby\n");
33420ffac27SDaniel Baluta 		return ret;
33520ffac27SDaniel Baluta 	}
33620ffac27SDaniel Baluta 	if (device & KMX61_ACC) {
33720ffac27SDaniel Baluta 		if (mode & KMX61_ACC_STBY_BIT) {
33820ffac27SDaniel Baluta 			ret |= KMX61_ACC_STBY_BIT;
33920ffac27SDaniel Baluta 			acc_stby = 1;
34020ffac27SDaniel Baluta 		} else {
34120ffac27SDaniel Baluta 			ret &= ~KMX61_ACC_STBY_BIT;
34220ffac27SDaniel Baluta 			acc_stby = 0;
34320ffac27SDaniel Baluta 		}
34420ffac27SDaniel Baluta 	}
34520ffac27SDaniel Baluta 
34620ffac27SDaniel Baluta 	if (device & KMX61_MAG) {
34720ffac27SDaniel Baluta 		if (mode & KMX61_MAG_STBY_BIT) {
34820ffac27SDaniel Baluta 			ret |= KMX61_MAG_STBY_BIT;
34920ffac27SDaniel Baluta 			mag_stby = 1;
35020ffac27SDaniel Baluta 		} else {
35120ffac27SDaniel Baluta 			ret &= ~KMX61_MAG_STBY_BIT;
35220ffac27SDaniel Baluta 			mag_stby = 0;
35320ffac27SDaniel Baluta 		}
35420ffac27SDaniel Baluta 	}
35520ffac27SDaniel Baluta 
35620ffac27SDaniel Baluta 	if (mode & KMX61_ACT_STBY_BIT)
35720ffac27SDaniel Baluta 		ret |= KMX61_ACT_STBY_BIT;
35820ffac27SDaniel Baluta 
35920ffac27SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_STBY, ret);
36020ffac27SDaniel Baluta 	if (ret < 0) {
36120ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_stby\n");
36220ffac27SDaniel Baluta 		return ret;
36320ffac27SDaniel Baluta 	}
36420ffac27SDaniel Baluta 
36520ffac27SDaniel Baluta 	if (acc_stby != -1 && update)
36620ffac27SDaniel Baluta 		data->acc_stby = acc_stby;
36720ffac27SDaniel Baluta 	if (mag_stby != -1 && update)
36820ffac27SDaniel Baluta 		data->mag_stby = mag_stby;
36920ffac27SDaniel Baluta 
37020ffac27SDaniel Baluta 	return 0;
37120ffac27SDaniel Baluta }
37220ffac27SDaniel Baluta 
37320ffac27SDaniel Baluta static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device)
37420ffac27SDaniel Baluta {
37520ffac27SDaniel Baluta 	int ret;
37620ffac27SDaniel Baluta 
37720ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY);
37820ffac27SDaniel Baluta 	if (ret < 0) {
37920ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_stby\n");
38020ffac27SDaniel Baluta 		return ret;
38120ffac27SDaniel Baluta 	}
38220ffac27SDaniel Baluta 	*mode = 0;
38320ffac27SDaniel Baluta 
38420ffac27SDaniel Baluta 	if (device & KMX61_ACC) {
38520ffac27SDaniel Baluta 		if (ret & KMX61_ACC_STBY_BIT)
38620ffac27SDaniel Baluta 			*mode |= KMX61_ACC_STBY_BIT;
38720ffac27SDaniel Baluta 		else
38820ffac27SDaniel Baluta 			*mode &= ~KMX61_ACC_STBY_BIT;
38920ffac27SDaniel Baluta 	}
39020ffac27SDaniel Baluta 
39120ffac27SDaniel Baluta 	if (device & KMX61_MAG) {
39220ffac27SDaniel Baluta 		if (ret & KMX61_MAG_STBY_BIT)
39320ffac27SDaniel Baluta 			*mode |= KMX61_MAG_STBY_BIT;
39420ffac27SDaniel Baluta 		else
39520ffac27SDaniel Baluta 			*mode &= ~KMX61_MAG_STBY_BIT;
39620ffac27SDaniel Baluta 	}
39720ffac27SDaniel Baluta 
39820ffac27SDaniel Baluta 	return 0;
39920ffac27SDaniel Baluta }
40020ffac27SDaniel Baluta 
401ebd16366Skbuild test robot static int kmx61_set_wake_up_odr(struct kmx61_data *data, int val, int val2)
402fd3ae7a9SDaniel Baluta {
403fd3ae7a9SDaniel Baluta 	int ret, odr_bits;
404fd3ae7a9SDaniel Baluta 
405fd3ae7a9SDaniel Baluta 	odr_bits = kmx61_convert_wake_up_odr_to_bit(val, val2);
406fd3ae7a9SDaniel Baluta 	if (odr_bits < 0)
407fd3ae7a9SDaniel Baluta 		return odr_bits;
408fd3ae7a9SDaniel Baluta 
409fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL2,
410fd3ae7a9SDaniel Baluta 					odr_bits);
411fd3ae7a9SDaniel Baluta 	if (ret < 0)
412fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl2\n");
413fd3ae7a9SDaniel Baluta 	return ret;
414fd3ae7a9SDaniel Baluta }
415fd3ae7a9SDaniel Baluta 
41620ffac27SDaniel Baluta static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device)
41720ffac27SDaniel Baluta {
41820ffac27SDaniel Baluta 	int ret;
41920ffac27SDaniel Baluta 	u8 mode;
42020ffac27SDaniel Baluta 	int lodr_bits, odr_bits;
42120ffac27SDaniel Baluta 
42220ffac27SDaniel Baluta 	ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG);
42320ffac27SDaniel Baluta 	if (ret < 0)
42420ffac27SDaniel Baluta 		return ret;
42520ffac27SDaniel Baluta 
42620ffac27SDaniel Baluta 	lodr_bits = kmx61_convert_freq_to_bit(val, val2);
42720ffac27SDaniel Baluta 	if (lodr_bits < 0)
42820ffac27SDaniel Baluta 		return lodr_bits;
42920ffac27SDaniel Baluta 
43020ffac27SDaniel Baluta 	/* To change ODR, accel and magn must be in STDBY */
43120ffac27SDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG,
43220ffac27SDaniel Baluta 			     true);
43320ffac27SDaniel Baluta 	if (ret < 0)
43420ffac27SDaniel Baluta 		return ret;
43520ffac27SDaniel Baluta 
43620ffac27SDaniel Baluta 	odr_bits = 0;
43720ffac27SDaniel Baluta 	if (device & KMX61_ACC)
43820ffac27SDaniel Baluta 		odr_bits |= lodr_bits << KMX61_ACC_ODR_SHIFT;
43920ffac27SDaniel Baluta 	if (device & KMX61_MAG)
44020ffac27SDaniel Baluta 		odr_bits |= lodr_bits << KMX61_MAG_ODR_SHIFT;
44120ffac27SDaniel Baluta 
44220ffac27SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_ODCNTL,
44320ffac27SDaniel Baluta 					odr_bits);
44420ffac27SDaniel Baluta 	if (ret < 0)
44520ffac27SDaniel Baluta 		return ret;
44620ffac27SDaniel Baluta 
4474e843977SDaniel Baluta 	data->odr_bits = odr_bits;
4484e843977SDaniel Baluta 
449fd3ae7a9SDaniel Baluta 	if (device & KMX61_ACC) {
450fd3ae7a9SDaniel Baluta 		ret = kmx61_set_wake_up_odr(data, val, val2);
451fd3ae7a9SDaniel Baluta 		if (ret)
452fd3ae7a9SDaniel Baluta 			return ret;
453fd3ae7a9SDaniel Baluta 	}
454fd3ae7a9SDaniel Baluta 
45520ffac27SDaniel Baluta 	return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true);
45620ffac27SDaniel Baluta }
45720ffac27SDaniel Baluta 
45820ffac27SDaniel Baluta static int kmx61_get_odr(struct kmx61_data *data, int *val, int *val2,
45920ffac27SDaniel Baluta 			 u8 device)
460a36385a2SDaniel Baluta {
46120ffac27SDaniel Baluta 	u8 lodr_bits;
46220ffac27SDaniel Baluta 
46320ffac27SDaniel Baluta 	if (device & KMX61_ACC)
46420ffac27SDaniel Baluta 		lodr_bits = (data->odr_bits >> KMX61_ACC_ODR_SHIFT) &
46520ffac27SDaniel Baluta 			     KMX61_ACC_ODR_MASK;
46620ffac27SDaniel Baluta 	else if (device & KMX61_MAG)
46720ffac27SDaniel Baluta 		lodr_bits = (data->odr_bits >> KMX61_MAG_ODR_SHIFT) &
46820ffac27SDaniel Baluta 			     KMX61_MAG_ODR_MASK;
46920ffac27SDaniel Baluta 	else
47020ffac27SDaniel Baluta 		return -EINVAL;
47120ffac27SDaniel Baluta 
472a36385a2SDaniel Baluta 	if (lodr_bits >= ARRAY_SIZE(kmx61_samp_freq_table))
47320ffac27SDaniel Baluta 		return -EINVAL;
474a36385a2SDaniel Baluta 
475a36385a2SDaniel Baluta 	*val = kmx61_samp_freq_table[lodr_bits].val;
476a36385a2SDaniel Baluta 	*val2 = kmx61_samp_freq_table[lodr_bits].val2;
477a36385a2SDaniel Baluta 
478a36385a2SDaniel Baluta 	return 0;
47920ffac27SDaniel Baluta }
48020ffac27SDaniel Baluta 
48120ffac27SDaniel Baluta static int kmx61_set_range(struct kmx61_data *data, u8 range)
48220ffac27SDaniel Baluta {
48320ffac27SDaniel Baluta 	int ret;
48420ffac27SDaniel Baluta 
48520ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1);
48620ffac27SDaniel Baluta 	if (ret < 0) {
48720ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
48820ffac27SDaniel Baluta 		return ret;
48920ffac27SDaniel Baluta 	}
49020ffac27SDaniel Baluta 
49120ffac27SDaniel Baluta 	ret &= ~KMX61_REG_CTRL1_GSEL_MASK;
49220ffac27SDaniel Baluta 	ret |= range & KMX61_REG_CTRL1_GSEL_MASK;
49320ffac27SDaniel Baluta 
49420ffac27SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret);
49520ffac27SDaniel Baluta 	if (ret < 0) {
49620ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
49720ffac27SDaniel Baluta 		return ret;
49820ffac27SDaniel Baluta 	}
49920ffac27SDaniel Baluta 
50020ffac27SDaniel Baluta 	data->range = range;
50120ffac27SDaniel Baluta 
50220ffac27SDaniel Baluta 	return 0;
50320ffac27SDaniel Baluta }
50420ffac27SDaniel Baluta 
50520ffac27SDaniel Baluta static int kmx61_set_scale(struct kmx61_data *data, u16 uscale)
50620ffac27SDaniel Baluta {
50720ffac27SDaniel Baluta 	int ret, i;
50820ffac27SDaniel Baluta 	u8  mode;
50920ffac27SDaniel Baluta 
51020ffac27SDaniel Baluta 	for (i = 0; i < ARRAY_SIZE(kmx61_uscale_table); i++) {
51120ffac27SDaniel Baluta 		if (kmx61_uscale_table[i] == uscale) {
51220ffac27SDaniel Baluta 			ret = kmx61_get_mode(data, &mode,
51320ffac27SDaniel Baluta 					     KMX61_ACC | KMX61_MAG);
51420ffac27SDaniel Baluta 			if (ret < 0)
51520ffac27SDaniel Baluta 				return ret;
51620ffac27SDaniel Baluta 
51720ffac27SDaniel Baluta 			ret = kmx61_set_mode(data, KMX61_ALL_STBY,
51820ffac27SDaniel Baluta 					     KMX61_ACC | KMX61_MAG, true);
51920ffac27SDaniel Baluta 			if (ret < 0)
52020ffac27SDaniel Baluta 				return ret;
52120ffac27SDaniel Baluta 
52220ffac27SDaniel Baluta 			ret = kmx61_set_range(data, i);
52320ffac27SDaniel Baluta 			if (ret < 0)
52420ffac27SDaniel Baluta 				return ret;
52520ffac27SDaniel Baluta 
52620ffac27SDaniel Baluta 			return  kmx61_set_mode(data, mode,
52720ffac27SDaniel Baluta 					       KMX61_ACC | KMX61_MAG, true);
52820ffac27SDaniel Baluta 		}
52920ffac27SDaniel Baluta 	}
53020ffac27SDaniel Baluta 	return -EINVAL;
53120ffac27SDaniel Baluta }
53220ffac27SDaniel Baluta 
53320ffac27SDaniel Baluta static int kmx61_chip_init(struct kmx61_data *data)
53420ffac27SDaniel Baluta {
535fd3ae7a9SDaniel Baluta 	int ret, val, val2;
53620ffac27SDaniel Baluta 
53720ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I);
53820ffac27SDaniel Baluta 	if (ret < 0) {
53920ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading who_am_i\n");
54020ffac27SDaniel Baluta 		return ret;
54120ffac27SDaniel Baluta 	}
54220ffac27SDaniel Baluta 
54320ffac27SDaniel Baluta 	if (ret != KMX61_CHIP_ID) {
54420ffac27SDaniel Baluta 		dev_err(&data->client->dev,
54520ffac27SDaniel Baluta 			"Wrong chip id, got %x expected %x\n",
54620ffac27SDaniel Baluta 			 ret, KMX61_CHIP_ID);
54720ffac27SDaniel Baluta 		return -EINVAL;
54820ffac27SDaniel Baluta 	}
54920ffac27SDaniel Baluta 
55020ffac27SDaniel Baluta 	/* set accel 12bit, 4g range */
55120ffac27SDaniel Baluta 	ret = kmx61_set_range(data, KMX61_RANGE_4G);
55220ffac27SDaniel Baluta 	if (ret < 0)
55320ffac27SDaniel Baluta 		return ret;
55420ffac27SDaniel Baluta 
55520ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_ODCNTL);
55620ffac27SDaniel Baluta 	if (ret < 0) {
55720ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_odcntl\n");
55820ffac27SDaniel Baluta 		return ret;
55920ffac27SDaniel Baluta 	}
56020ffac27SDaniel Baluta 	data->odr_bits = ret;
56120ffac27SDaniel Baluta 
562a36385a2SDaniel Baluta 	/*
563a36385a2SDaniel Baluta 	 * set output data rate for wake up (motion detection) function
564a36385a2SDaniel Baluta 	 * to match data rate for accelerometer sampling
565a36385a2SDaniel Baluta 	 */
566a36385a2SDaniel Baluta 	ret = kmx61_get_odr(data, &val, &val2, KMX61_ACC);
567fd3ae7a9SDaniel Baluta 	if (ret < 0)
568fd3ae7a9SDaniel Baluta 		return ret;
569fd3ae7a9SDaniel Baluta 
570fd3ae7a9SDaniel Baluta 	ret = kmx61_set_wake_up_odr(data, val, val2);
571fd3ae7a9SDaniel Baluta 	if (ret < 0)
572fd3ae7a9SDaniel Baluta 		return ret;
573fd3ae7a9SDaniel Baluta 
57420ffac27SDaniel Baluta 	/* set acc/magn to OPERATION mode */
57520ffac27SDaniel Baluta 	ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true);
57620ffac27SDaniel Baluta 	if (ret < 0)
57720ffac27SDaniel Baluta 		return ret;
57820ffac27SDaniel Baluta 
579fd3ae7a9SDaniel Baluta 	data->wake_thresh = KMX61_DEFAULT_WAKE_THRESH;
580fd3ae7a9SDaniel Baluta 	data->wake_duration = KMX61_DEFAULT_WAKE_DURATION;
581fd3ae7a9SDaniel Baluta 
58220ffac27SDaniel Baluta 	return 0;
58320ffac27SDaniel Baluta }
58420ffac27SDaniel Baluta 
585c3a23eccSDaniel Baluta static int kmx61_setup_new_data_interrupt(struct kmx61_data *data,
586c3a23eccSDaniel Baluta 					  bool status, u8 device)
587c3a23eccSDaniel Baluta {
588c3a23eccSDaniel Baluta 	u8 mode;
589c3a23eccSDaniel Baluta 	int ret;
590c3a23eccSDaniel Baluta 
591c3a23eccSDaniel Baluta 	ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG);
592c3a23eccSDaniel Baluta 	if (ret < 0)
593c3a23eccSDaniel Baluta 		return ret;
594c3a23eccSDaniel Baluta 
595c3a23eccSDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
596c3a23eccSDaniel Baluta 	if (ret < 0)
597c3a23eccSDaniel Baluta 		return ret;
598c3a23eccSDaniel Baluta 
599c3a23eccSDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INC1);
600c3a23eccSDaniel Baluta 	if (ret < 0) {
601c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
602c3a23eccSDaniel Baluta 		return ret;
603c3a23eccSDaniel Baluta 	}
604c3a23eccSDaniel Baluta 
605c3a23eccSDaniel Baluta 	if (status) {
606c3a23eccSDaniel Baluta 		ret |= KMX61_REG_INC1_BIT_IEN;
607c3a23eccSDaniel Baluta 		if (device & KMX61_ACC)
608c3a23eccSDaniel Baluta 			ret |= KMX61_REG_INC1_BIT_DRDYA;
609c3a23eccSDaniel Baluta 		if (device & KMX61_MAG)
610c3a23eccSDaniel Baluta 			ret |=  KMX61_REG_INC1_BIT_DRDYM;
611c3a23eccSDaniel Baluta 	} else {
612c3a23eccSDaniel Baluta 		ret &= ~KMX61_REG_INC1_BIT_IEN;
613c3a23eccSDaniel Baluta 		if (device & KMX61_ACC)
614c3a23eccSDaniel Baluta 			ret &= ~KMX61_REG_INC1_BIT_DRDYA;
615c3a23eccSDaniel Baluta 		if (device & KMX61_MAG)
616c3a23eccSDaniel Baluta 			ret &= ~KMX61_REG_INC1_BIT_DRDYM;
617c3a23eccSDaniel Baluta 	}
618c3a23eccSDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_INC1, ret);
619c3a23eccSDaniel Baluta 	if (ret < 0) {
620c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
621c3a23eccSDaniel Baluta 		return ret;
622c3a23eccSDaniel Baluta 	}
623c3a23eccSDaniel Baluta 
624c3a23eccSDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1);
625c3a23eccSDaniel Baluta 	if (ret < 0) {
626c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
627c3a23eccSDaniel Baluta 		return ret;
628c3a23eccSDaniel Baluta 	}
629c3a23eccSDaniel Baluta 
630c3a23eccSDaniel Baluta 	if (status)
631c3a23eccSDaniel Baluta 		ret |= KMX61_REG_CTRL1_BIT_DRDYE;
632c3a23eccSDaniel Baluta 	else
633c3a23eccSDaniel Baluta 		ret &= ~KMX61_REG_CTRL1_BIT_DRDYE;
634c3a23eccSDaniel Baluta 
635c3a23eccSDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret);
636c3a23eccSDaniel Baluta 	if (ret < 0) {
637c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
638c3a23eccSDaniel Baluta 		return ret;
639c3a23eccSDaniel Baluta 	}
640c3a23eccSDaniel Baluta 
64128ff344eSDaniel Baluta 	return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true);
642c3a23eccSDaniel Baluta }
643c3a23eccSDaniel Baluta 
644fd3ae7a9SDaniel Baluta static int kmx61_chip_update_thresholds(struct kmx61_data *data)
645fd3ae7a9SDaniel Baluta {
646fd3ae7a9SDaniel Baluta 	int ret;
647fd3ae7a9SDaniel Baluta 
648fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client,
649fd3ae7a9SDaniel Baluta 					KMX61_REG_WUF_TIMER,
650fd3ae7a9SDaniel Baluta 					data->wake_duration);
651fd3ae7a9SDaniel Baluta 	if (ret < 0) {
652fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Errow writing reg_wuf_timer\n");
653fd3ae7a9SDaniel Baluta 		return ret;
654fd3ae7a9SDaniel Baluta 	}
655fd3ae7a9SDaniel Baluta 
656fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client,
657fd3ae7a9SDaniel Baluta 					KMX61_REG_WUF_THRESH,
658fd3ae7a9SDaniel Baluta 					data->wake_thresh);
65928ff344eSDaniel Baluta 	if (ret < 0)
660fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_wuf_thresh\n");
661fd3ae7a9SDaniel Baluta 
66228ff344eSDaniel Baluta 	return ret;
663fd3ae7a9SDaniel Baluta }
664fd3ae7a9SDaniel Baluta 
665fd3ae7a9SDaniel Baluta static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data,
6660475c685SDaniel Baluta 					    bool status)
667fd3ae7a9SDaniel Baluta {
668fd3ae7a9SDaniel Baluta 	u8 mode;
669fd3ae7a9SDaniel Baluta 	int ret;
670fd3ae7a9SDaniel Baluta 
671fd3ae7a9SDaniel Baluta 	ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG);
672fd3ae7a9SDaniel Baluta 	if (ret < 0)
673fd3ae7a9SDaniel Baluta 		return ret;
674fd3ae7a9SDaniel Baluta 
675fd3ae7a9SDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
676fd3ae7a9SDaniel Baluta 	if (ret < 0)
677fd3ae7a9SDaniel Baluta 		return ret;
678fd3ae7a9SDaniel Baluta 
679fd3ae7a9SDaniel Baluta 	ret = kmx61_chip_update_thresholds(data);
680fd3ae7a9SDaniel Baluta 	if (ret < 0)
681fd3ae7a9SDaniel Baluta 		return ret;
682fd3ae7a9SDaniel Baluta 
683fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INC1);
684fd3ae7a9SDaniel Baluta 	if (ret < 0) {
685fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_inc1\n");
686fd3ae7a9SDaniel Baluta 		return ret;
687fd3ae7a9SDaniel Baluta 	}
688fd3ae7a9SDaniel Baluta 	if (status)
689fd3ae7a9SDaniel Baluta 		ret |= (KMX61_REG_INC1_BIT_IEN | KMX61_REG_INC1_BIT_WUFS);
690fd3ae7a9SDaniel Baluta 	else
691fd3ae7a9SDaniel Baluta 		ret &= ~(KMX61_REG_INC1_BIT_IEN | KMX61_REG_INC1_BIT_WUFS);
692fd3ae7a9SDaniel Baluta 
693fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_INC1, ret);
694fd3ae7a9SDaniel Baluta 	if (ret < 0) {
695fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_inc1\n");
696fd3ae7a9SDaniel Baluta 		return ret;
697fd3ae7a9SDaniel Baluta 	}
698fd3ae7a9SDaniel Baluta 
699fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1);
700fd3ae7a9SDaniel Baluta 	if (ret < 0) {
701fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
702fd3ae7a9SDaniel Baluta 		return ret;
703fd3ae7a9SDaniel Baluta 	}
704fd3ae7a9SDaniel Baluta 
705fd3ae7a9SDaniel Baluta 	if (status)
706fd3ae7a9SDaniel Baluta 		ret |= KMX61_REG_CTRL1_BIT_WUFE | KMX61_REG_CTRL1_BIT_BTSE;
707fd3ae7a9SDaniel Baluta 	else
708fd3ae7a9SDaniel Baluta 		ret &= ~(KMX61_REG_CTRL1_BIT_WUFE | KMX61_REG_CTRL1_BIT_BTSE);
709fd3ae7a9SDaniel Baluta 
710fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret);
711fd3ae7a9SDaniel Baluta 	if (ret < 0) {
712fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
713fd3ae7a9SDaniel Baluta 		return ret;
714fd3ae7a9SDaniel Baluta 	}
715fd3ae7a9SDaniel Baluta 	mode |= KMX61_ACT_STBY_BIT;
71628ff344eSDaniel Baluta 	return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true);
717fd3ae7a9SDaniel Baluta }
718fd3ae7a9SDaniel Baluta 
719aff8609aSDaniel Baluta /**
720aff8609aSDaniel Baluta  * kmx61_set_power_state() - set power state for kmx61 @device
721aff8609aSDaniel Baluta  * @data - kmx61 device private pointer
722aff8609aSDaniel Baluta  * @on - power state to be set for @device
723aff8609aSDaniel Baluta  * @device - bitmask indicating device for which @on state needs to be set
724aff8609aSDaniel Baluta  *
725aff8609aSDaniel Baluta  * Notice that when ACC power state needs to be set to ON and MAG is in
726aff8609aSDaniel Baluta  * OPERATION then we know that kmx61_runtime_resume was already called
727aff8609aSDaniel Baluta  * so we must set ACC OPERATION mode here. The same happens when MAG power
728aff8609aSDaniel Baluta  * state needs to be set to ON and ACC is in OPERATION.
729aff8609aSDaniel Baluta  */
730aff8609aSDaniel Baluta static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device)
731aff8609aSDaniel Baluta {
732df1fad80SDaniel Baluta #ifdef CONFIG_PM
733aff8609aSDaniel Baluta 	int ret;
734aff8609aSDaniel Baluta 
735aff8609aSDaniel Baluta 	if (device & KMX61_ACC) {
736aff8609aSDaniel Baluta 		if (on && !data->acc_ps && !data->mag_stby) {
737aff8609aSDaniel Baluta 			ret = kmx61_set_mode(data, 0, KMX61_ACC, true);
738aff8609aSDaniel Baluta 			if (ret < 0)
739aff8609aSDaniel Baluta 				return ret;
740aff8609aSDaniel Baluta 		}
741aff8609aSDaniel Baluta 		data->acc_ps = on;
742aff8609aSDaniel Baluta 	}
743aff8609aSDaniel Baluta 	if (device & KMX61_MAG) {
744aff8609aSDaniel Baluta 		if (on && !data->mag_ps && !data->acc_stby) {
745aff8609aSDaniel Baluta 			ret = kmx61_set_mode(data, 0, KMX61_MAG, true);
746aff8609aSDaniel Baluta 			if (ret < 0)
747aff8609aSDaniel Baluta 				return ret;
748aff8609aSDaniel Baluta 		}
749aff8609aSDaniel Baluta 		data->mag_ps = on;
750aff8609aSDaniel Baluta 	}
751aff8609aSDaniel Baluta 
752aff8609aSDaniel Baluta 	if (on) {
753aff8609aSDaniel Baluta 		ret = pm_runtime_get_sync(&data->client->dev);
754aff8609aSDaniel Baluta 	} else {
755aff8609aSDaniel Baluta 		pm_runtime_mark_last_busy(&data->client->dev);
756aff8609aSDaniel Baluta 		ret = pm_runtime_put_autosuspend(&data->client->dev);
757aff8609aSDaniel Baluta 	}
758aff8609aSDaniel Baluta 	if (ret < 0) {
759aff8609aSDaniel Baluta 		dev_err(&data->client->dev,
760aff8609aSDaniel Baluta 			"Failed: kmx61_set_power_state for %d, ret %d\n",
761aff8609aSDaniel Baluta 			on, ret);
762aff8609aSDaniel Baluta 		if (on)
763aff8609aSDaniel Baluta 			pm_runtime_put_noidle(&data->client->dev);
764aff8609aSDaniel Baluta 
765aff8609aSDaniel Baluta 		return ret;
766aff8609aSDaniel Baluta 	}
767aff8609aSDaniel Baluta #endif
768aff8609aSDaniel Baluta 	return 0;
769aff8609aSDaniel Baluta }
770aff8609aSDaniel Baluta 
77120ffac27SDaniel Baluta static int kmx61_read_measurement(struct kmx61_data *data, u8 base, u8 offset)
77220ffac27SDaniel Baluta {
77320ffac27SDaniel Baluta 	int ret;
77420ffac27SDaniel Baluta 	u8 reg = base + offset * 2;
77520ffac27SDaniel Baluta 
77620ffac27SDaniel Baluta 	ret = i2c_smbus_read_word_data(data->client, reg);
77720ffac27SDaniel Baluta 	if (ret < 0)
77820ffac27SDaniel Baluta 		dev_err(&data->client->dev, "failed to read reg at %x\n", reg);
77920ffac27SDaniel Baluta 
78020ffac27SDaniel Baluta 	return ret;
78120ffac27SDaniel Baluta }
78220ffac27SDaniel Baluta 
78320ffac27SDaniel Baluta static int kmx61_read_raw(struct iio_dev *indio_dev,
78420ffac27SDaniel Baluta 			  struct iio_chan_spec const *chan, int *val,
78520ffac27SDaniel Baluta 			  int *val2, long mask)
78620ffac27SDaniel Baluta {
78720ffac27SDaniel Baluta 	int ret;
78820ffac27SDaniel Baluta 	u8 base_reg;
78920ffac27SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
79020ffac27SDaniel Baluta 
79120ffac27SDaniel Baluta 	switch (mask) {
79220ffac27SDaniel Baluta 	case IIO_CHAN_INFO_RAW:
79320ffac27SDaniel Baluta 		switch (chan->type) {
79420ffac27SDaniel Baluta 		case IIO_ACCEL:
79520ffac27SDaniel Baluta 			base_reg = KMX61_ACC_XOUT_L;
79620ffac27SDaniel Baluta 			break;
79720ffac27SDaniel Baluta 		case IIO_MAGN:
79820ffac27SDaniel Baluta 			base_reg = KMX61_MAG_XOUT_L;
79920ffac27SDaniel Baluta 			break;
80020ffac27SDaniel Baluta 		default:
80120ffac27SDaniel Baluta 			return -EINVAL;
80220ffac27SDaniel Baluta 		}
80320ffac27SDaniel Baluta 		mutex_lock(&data->lock);
80420ffac27SDaniel Baluta 
805a3da4fa3SDaniel Baluta 		ret = kmx61_set_power_state(data, true, chan->address);
806a3da4fa3SDaniel Baluta 		if (ret) {
807a3da4fa3SDaniel Baluta 			mutex_unlock(&data->lock);
808a3da4fa3SDaniel Baluta 			return ret;
809a3da4fa3SDaniel Baluta 		}
810a3da4fa3SDaniel Baluta 
81120ffac27SDaniel Baluta 		ret = kmx61_read_measurement(data, base_reg, chan->scan_index);
81220ffac27SDaniel Baluta 		if (ret < 0) {
813aff8609aSDaniel Baluta 			kmx61_set_power_state(data, false, chan->address);
81420ffac27SDaniel Baluta 			mutex_unlock(&data->lock);
81520ffac27SDaniel Baluta 			return ret;
81620ffac27SDaniel Baluta 		}
81720ffac27SDaniel Baluta 		*val = sign_extend32(ret >> chan->scan_type.shift,
81820ffac27SDaniel Baluta 				     chan->scan_type.realbits - 1);
819a3da4fa3SDaniel Baluta 		ret = kmx61_set_power_state(data, false, chan->address);
82020ffac27SDaniel Baluta 
82120ffac27SDaniel Baluta 		mutex_unlock(&data->lock);
822a3da4fa3SDaniel Baluta 		if (ret)
823a3da4fa3SDaniel Baluta 			return ret;
82420ffac27SDaniel Baluta 		return IIO_VAL_INT;
82520ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SCALE:
82620ffac27SDaniel Baluta 		switch (chan->type) {
82720ffac27SDaniel Baluta 		case IIO_ACCEL:
82820ffac27SDaniel Baluta 			*val = 0;
82920ffac27SDaniel Baluta 			*val2 = kmx61_uscale_table[data->range];
83020ffac27SDaniel Baluta 			return IIO_VAL_INT_PLUS_MICRO;
83120ffac27SDaniel Baluta 		case IIO_MAGN:
83220ffac27SDaniel Baluta 			/* 14 bits res, 1465 microGauss per magn count */
83320ffac27SDaniel Baluta 			*val = 0;
83420ffac27SDaniel Baluta 			*val2 = 1465;
83520ffac27SDaniel Baluta 			return IIO_VAL_INT_PLUS_MICRO;
83620ffac27SDaniel Baluta 		default:
83720ffac27SDaniel Baluta 			return -EINVAL;
83820ffac27SDaniel Baluta 		}
83920ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SAMP_FREQ:
84020ffac27SDaniel Baluta 		if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN)
84120ffac27SDaniel Baluta 			return -EINVAL;
84220ffac27SDaniel Baluta 
84320ffac27SDaniel Baluta 		mutex_lock(&data->lock);
84420ffac27SDaniel Baluta 		ret = kmx61_get_odr(data, val, val2, chan->address);
84520ffac27SDaniel Baluta 		mutex_unlock(&data->lock);
84620ffac27SDaniel Baluta 		if (ret)
84720ffac27SDaniel Baluta 			return -EINVAL;
84820ffac27SDaniel Baluta 		return IIO_VAL_INT_PLUS_MICRO;
84920ffac27SDaniel Baluta 	}
85020ffac27SDaniel Baluta 	return -EINVAL;
85120ffac27SDaniel Baluta }
85220ffac27SDaniel Baluta 
85320ffac27SDaniel Baluta static int kmx61_write_raw(struct iio_dev *indio_dev,
85420ffac27SDaniel Baluta 			   struct iio_chan_spec const *chan, int val,
85520ffac27SDaniel Baluta 			   int val2, long mask)
85620ffac27SDaniel Baluta {
85720ffac27SDaniel Baluta 	int ret;
85820ffac27SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
85920ffac27SDaniel Baluta 
86020ffac27SDaniel Baluta 	switch (mask) {
86120ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SAMP_FREQ:
86220ffac27SDaniel Baluta 		if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN)
86320ffac27SDaniel Baluta 			return -EINVAL;
86420ffac27SDaniel Baluta 
86520ffac27SDaniel Baluta 		mutex_lock(&data->lock);
86620ffac27SDaniel Baluta 		ret = kmx61_set_odr(data, val, val2, chan->address);
86720ffac27SDaniel Baluta 		mutex_unlock(&data->lock);
86820ffac27SDaniel Baluta 		return ret;
86920ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SCALE:
87020ffac27SDaniel Baluta 		switch (chan->type) {
87120ffac27SDaniel Baluta 		case IIO_ACCEL:
87220ffac27SDaniel Baluta 			if (val != 0)
87320ffac27SDaniel Baluta 				return -EINVAL;
87420ffac27SDaniel Baluta 			mutex_lock(&data->lock);
87520ffac27SDaniel Baluta 			ret = kmx61_set_scale(data, val2);
87620ffac27SDaniel Baluta 			mutex_unlock(&data->lock);
87720ffac27SDaniel Baluta 			return ret;
87820ffac27SDaniel Baluta 		default:
87920ffac27SDaniel Baluta 			return -EINVAL;
88020ffac27SDaniel Baluta 		}
88120ffac27SDaniel Baluta 	default:
88220ffac27SDaniel Baluta 		return -EINVAL;
88320ffac27SDaniel Baluta 	}
88420ffac27SDaniel Baluta }
88520ffac27SDaniel Baluta 
886fd3ae7a9SDaniel Baluta static int kmx61_read_event(struct iio_dev *indio_dev,
887fd3ae7a9SDaniel Baluta 			    const struct iio_chan_spec *chan,
888fd3ae7a9SDaniel Baluta 			    enum iio_event_type type,
889fd3ae7a9SDaniel Baluta 			    enum iio_event_direction dir,
890fd3ae7a9SDaniel Baluta 			    enum iio_event_info info,
891fd3ae7a9SDaniel Baluta 			    int *val, int *val2)
892fd3ae7a9SDaniel Baluta {
893fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
894fd3ae7a9SDaniel Baluta 
895fd3ae7a9SDaniel Baluta 	*val2 = 0;
896fd3ae7a9SDaniel Baluta 	switch (info) {
897fd3ae7a9SDaniel Baluta 	case IIO_EV_INFO_VALUE:
898fd3ae7a9SDaniel Baluta 		*val = data->wake_thresh;
89928ff344eSDaniel Baluta 		return IIO_VAL_INT;
900fd3ae7a9SDaniel Baluta 	case IIO_EV_INFO_PERIOD:
901fd3ae7a9SDaniel Baluta 		*val = data->wake_duration;
90228ff344eSDaniel Baluta 		return IIO_VAL_INT;
903fd3ae7a9SDaniel Baluta 	default:
904fd3ae7a9SDaniel Baluta 		return -EINVAL;
905fd3ae7a9SDaniel Baluta 	}
906fd3ae7a9SDaniel Baluta }
907fd3ae7a9SDaniel Baluta 
908fd3ae7a9SDaniel Baluta static int kmx61_write_event(struct iio_dev *indio_dev,
909fd3ae7a9SDaniel Baluta 			     const struct iio_chan_spec *chan,
910fd3ae7a9SDaniel Baluta 			     enum iio_event_type type,
911fd3ae7a9SDaniel Baluta 			     enum iio_event_direction dir,
912fd3ae7a9SDaniel Baluta 			     enum iio_event_info info,
913fd3ae7a9SDaniel Baluta 			     int val, int val2)
914fd3ae7a9SDaniel Baluta {
915fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
916fd3ae7a9SDaniel Baluta 
917fd3ae7a9SDaniel Baluta 	if (data->ev_enable_state)
918fd3ae7a9SDaniel Baluta 		return -EBUSY;
919fd3ae7a9SDaniel Baluta 
920fd3ae7a9SDaniel Baluta 	switch (info) {
921fd3ae7a9SDaniel Baluta 	case IIO_EV_INFO_VALUE:
922fd3ae7a9SDaniel Baluta 		data->wake_thresh = val;
92328ff344eSDaniel Baluta 		return IIO_VAL_INT;
924fd3ae7a9SDaniel Baluta 	case IIO_EV_INFO_PERIOD:
925fd3ae7a9SDaniel Baluta 		data->wake_duration = val;
92628ff344eSDaniel Baluta 		return IIO_VAL_INT;
927fd3ae7a9SDaniel Baluta 	default:
928fd3ae7a9SDaniel Baluta 		return -EINVAL;
929fd3ae7a9SDaniel Baluta 	}
930fd3ae7a9SDaniel Baluta }
931fd3ae7a9SDaniel Baluta 
932fd3ae7a9SDaniel Baluta static int kmx61_read_event_config(struct iio_dev *indio_dev,
933fd3ae7a9SDaniel Baluta 				   const struct iio_chan_spec *chan,
934fd3ae7a9SDaniel Baluta 				   enum iio_event_type type,
935fd3ae7a9SDaniel Baluta 				   enum iio_event_direction dir)
936fd3ae7a9SDaniel Baluta {
937fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
938fd3ae7a9SDaniel Baluta 
939fd3ae7a9SDaniel Baluta 	return data->ev_enable_state;
940fd3ae7a9SDaniel Baluta }
941fd3ae7a9SDaniel Baluta 
942fd3ae7a9SDaniel Baluta static int kmx61_write_event_config(struct iio_dev *indio_dev,
943fd3ae7a9SDaniel Baluta 				    const struct iio_chan_spec *chan,
944fd3ae7a9SDaniel Baluta 				    enum iio_event_type type,
945fd3ae7a9SDaniel Baluta 				    enum iio_event_direction dir,
946fd3ae7a9SDaniel Baluta 				    int state)
947fd3ae7a9SDaniel Baluta {
948fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
94928ff344eSDaniel Baluta 	int ret = 0;
950fd3ae7a9SDaniel Baluta 
951fd3ae7a9SDaniel Baluta 	if (state && data->ev_enable_state)
952fd3ae7a9SDaniel Baluta 		return 0;
953fd3ae7a9SDaniel Baluta 
954fd3ae7a9SDaniel Baluta 	mutex_lock(&data->lock);
955fd3ae7a9SDaniel Baluta 
956fd3ae7a9SDaniel Baluta 	if (!state && data->motion_trig_on) {
957d4a4ae04SDaniel Baluta 		data->ev_enable_state = false;
95828ff344eSDaniel Baluta 		goto err_unlock;
959fd3ae7a9SDaniel Baluta 	}
960fd3ae7a9SDaniel Baluta 
961fd3ae7a9SDaniel Baluta 	ret = kmx61_set_power_state(data, state, KMX61_ACC);
96228ff344eSDaniel Baluta 	if (ret < 0)
96328ff344eSDaniel Baluta 		goto err_unlock;
964fd3ae7a9SDaniel Baluta 
9650475c685SDaniel Baluta 	ret = kmx61_setup_any_motion_interrupt(data, state);
966fd3ae7a9SDaniel Baluta 	if (ret < 0) {
967fd3ae7a9SDaniel Baluta 		kmx61_set_power_state(data, false, KMX61_ACC);
96828ff344eSDaniel Baluta 		goto err_unlock;
969fd3ae7a9SDaniel Baluta 	}
970fd3ae7a9SDaniel Baluta 
971fd3ae7a9SDaniel Baluta 	data->ev_enable_state = state;
97228ff344eSDaniel Baluta 
97328ff344eSDaniel Baluta err_unlock:
974fd3ae7a9SDaniel Baluta 	mutex_unlock(&data->lock);
975fd3ae7a9SDaniel Baluta 
97628ff344eSDaniel Baluta 	return ret;
977fd3ae7a9SDaniel Baluta }
978fd3ae7a9SDaniel Baluta 
979c3a23eccSDaniel Baluta static int kmx61_acc_validate_trigger(struct iio_dev *indio_dev,
980c3a23eccSDaniel Baluta 				      struct iio_trigger *trig)
981c3a23eccSDaniel Baluta {
982c3a23eccSDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
983c3a23eccSDaniel Baluta 
984fd3ae7a9SDaniel Baluta 	if (data->acc_dready_trig != trig && data->motion_trig != trig)
985c3a23eccSDaniel Baluta 		return -EINVAL;
986c3a23eccSDaniel Baluta 
987c3a23eccSDaniel Baluta 	return 0;
988c3a23eccSDaniel Baluta }
989c3a23eccSDaniel Baluta 
990c3a23eccSDaniel Baluta static int kmx61_mag_validate_trigger(struct iio_dev *indio_dev,
991c3a23eccSDaniel Baluta 				      struct iio_trigger *trig)
992c3a23eccSDaniel Baluta {
993c3a23eccSDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
994c3a23eccSDaniel Baluta 
995c3a23eccSDaniel Baluta 	if (data->mag_dready_trig != trig)
996c3a23eccSDaniel Baluta 		return -EINVAL;
997c3a23eccSDaniel Baluta 
998c3a23eccSDaniel Baluta 	return 0;
999c3a23eccSDaniel Baluta }
1000c3a23eccSDaniel Baluta 
100120ffac27SDaniel Baluta static const struct iio_info kmx61_acc_info = {
100220ffac27SDaniel Baluta 	.read_raw		= kmx61_read_raw,
100320ffac27SDaniel Baluta 	.write_raw		= kmx61_write_raw,
100420ffac27SDaniel Baluta 	.attrs			= &kmx61_acc_attribute_group,
1005fd3ae7a9SDaniel Baluta 	.read_event_value	= kmx61_read_event,
1006fd3ae7a9SDaniel Baluta 	.write_event_value	= kmx61_write_event,
1007fd3ae7a9SDaniel Baluta 	.read_event_config	= kmx61_read_event_config,
1008fd3ae7a9SDaniel Baluta 	.write_event_config	= kmx61_write_event_config,
1009c3a23eccSDaniel Baluta 	.validate_trigger	= kmx61_acc_validate_trigger,
101020ffac27SDaniel Baluta };
101120ffac27SDaniel Baluta 
101220ffac27SDaniel Baluta static const struct iio_info kmx61_mag_info = {
101320ffac27SDaniel Baluta 	.read_raw		= kmx61_read_raw,
101420ffac27SDaniel Baluta 	.write_raw		= kmx61_write_raw,
101520ffac27SDaniel Baluta 	.attrs			= &kmx61_mag_attribute_group,
1016c3a23eccSDaniel Baluta 	.validate_trigger	= kmx61_mag_validate_trigger,
101720ffac27SDaniel Baluta };
101820ffac27SDaniel Baluta 
1019c3a23eccSDaniel Baluta 
1020c3a23eccSDaniel Baluta static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig,
1021c3a23eccSDaniel Baluta 					    bool state)
1022c3a23eccSDaniel Baluta {
1023c3a23eccSDaniel Baluta 	int ret = 0;
1024c3a23eccSDaniel Baluta 	u8 device;
1025c3a23eccSDaniel Baluta 
1026c3a23eccSDaniel Baluta 	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
1027fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
1028c3a23eccSDaniel Baluta 
1029c3a23eccSDaniel Baluta 	mutex_lock(&data->lock);
1030c3a23eccSDaniel Baluta 
1031fd3ae7a9SDaniel Baluta 	if (!state && data->ev_enable_state && data->motion_trig_on) {
1032fd3ae7a9SDaniel Baluta 		data->motion_trig_on = false;
103328ff344eSDaniel Baluta 		goto err_unlock;
1034fd3ae7a9SDaniel Baluta 	}
1035fd3ae7a9SDaniel Baluta 
1036dbdd0e2dSDaniel Baluta 	if (data->acc_dready_trig == trig || data->motion_trig == trig)
1037c3a23eccSDaniel Baluta 		device = KMX61_ACC;
1038c3a23eccSDaniel Baluta 	else
1039c3a23eccSDaniel Baluta 		device = KMX61_MAG;
1040c3a23eccSDaniel Baluta 
1041c3a23eccSDaniel Baluta 	ret = kmx61_set_power_state(data, state, device);
104228ff344eSDaniel Baluta 	if (ret < 0)
104328ff344eSDaniel Baluta 		goto err_unlock;
1044c3a23eccSDaniel Baluta 
1045fd3ae7a9SDaniel Baluta 	if (data->acc_dready_trig == trig || data->mag_dready_trig == trig)
1046c3a23eccSDaniel Baluta 		ret = kmx61_setup_new_data_interrupt(data, state, device);
1047fd3ae7a9SDaniel Baluta 	else
10480475c685SDaniel Baluta 		ret = kmx61_setup_any_motion_interrupt(data, state);
1049c3a23eccSDaniel Baluta 	if (ret < 0) {
1050c3a23eccSDaniel Baluta 		kmx61_set_power_state(data, false, device);
105128ff344eSDaniel Baluta 		goto err_unlock;
1052c3a23eccSDaniel Baluta 	}
1053c3a23eccSDaniel Baluta 
1054c3a23eccSDaniel Baluta 	if (data->acc_dready_trig == trig)
1055c3a23eccSDaniel Baluta 		data->acc_dready_trig_on = state;
1056fd3ae7a9SDaniel Baluta 	else if (data->mag_dready_trig == trig)
1057c3a23eccSDaniel Baluta 		data->mag_dready_trig_on = state;
1058fd3ae7a9SDaniel Baluta 	else
1059fd3ae7a9SDaniel Baluta 		data->motion_trig_on = state;
106028ff344eSDaniel Baluta err_unlock:
1061c3a23eccSDaniel Baluta 	mutex_unlock(&data->lock);
1062c3a23eccSDaniel Baluta 
106328ff344eSDaniel Baluta 	return ret;
1064c3a23eccSDaniel Baluta }
1065c3a23eccSDaniel Baluta 
1066c3a23eccSDaniel Baluta static int kmx61_trig_try_reenable(struct iio_trigger *trig)
1067c3a23eccSDaniel Baluta {
1068c3a23eccSDaniel Baluta 	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
1069c3a23eccSDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
1070c3a23eccSDaniel Baluta 	int ret;
1071c3a23eccSDaniel Baluta 
1072c3a23eccSDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL);
1073c3a23eccSDaniel Baluta 	if (ret < 0) {
1074c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_inl\n");
1075c3a23eccSDaniel Baluta 		return ret;
1076c3a23eccSDaniel Baluta 	}
1077c3a23eccSDaniel Baluta 
1078c3a23eccSDaniel Baluta 	return 0;
1079c3a23eccSDaniel Baluta }
1080c3a23eccSDaniel Baluta 
1081c3a23eccSDaniel Baluta static const struct iio_trigger_ops kmx61_trigger_ops = {
1082c3a23eccSDaniel Baluta 	.set_trigger_state = kmx61_data_rdy_trigger_set_state,
1083c3a23eccSDaniel Baluta 	.try_reenable = kmx61_trig_try_reenable,
1084c3a23eccSDaniel Baluta };
1085c3a23eccSDaniel Baluta 
1086fd3ae7a9SDaniel Baluta static irqreturn_t kmx61_event_handler(int irq, void *private)
1087fd3ae7a9SDaniel Baluta {
1088fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = private;
1089fd3ae7a9SDaniel Baluta 	struct iio_dev *indio_dev = data->acc_indio_dev;
1090fd3ae7a9SDaniel Baluta 	int ret;
1091fd3ae7a9SDaniel Baluta 
1092fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS1);
1093fd3ae7a9SDaniel Baluta 	if (ret < 0) {
1094fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ins1\n");
1095fd3ae7a9SDaniel Baluta 		goto ack_intr;
1096fd3ae7a9SDaniel Baluta 	}
1097fd3ae7a9SDaniel Baluta 
1098fd3ae7a9SDaniel Baluta 	if (ret & KMX61_REG_INS1_BIT_WUFS) {
1099fd3ae7a9SDaniel Baluta 		ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS2);
1100fd3ae7a9SDaniel Baluta 		if (ret < 0) {
1101fd3ae7a9SDaniel Baluta 			dev_err(&data->client->dev, "Error reading reg_ins2\n");
1102fd3ae7a9SDaniel Baluta 			goto ack_intr;
1103fd3ae7a9SDaniel Baluta 		}
1104fd3ae7a9SDaniel Baluta 
1105fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_XN)
1106fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1107fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1108fd3ae7a9SDaniel Baluta 				       0,
1109fd3ae7a9SDaniel Baluta 				       IIO_MOD_X,
1110fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1111fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_FALLING),
1112fd3ae7a9SDaniel Baluta 				       0);
1113fd3ae7a9SDaniel Baluta 
1114fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_XP)
1115fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1116fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1117fd3ae7a9SDaniel Baluta 				       0,
1118fd3ae7a9SDaniel Baluta 				       IIO_MOD_X,
1119fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1120fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_RISING),
1121fd3ae7a9SDaniel Baluta 				       0);
1122fd3ae7a9SDaniel Baluta 
1123fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_YN)
1124fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1125fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1126fd3ae7a9SDaniel Baluta 				       0,
1127fd3ae7a9SDaniel Baluta 				       IIO_MOD_Y,
1128fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1129fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_FALLING),
1130fd3ae7a9SDaniel Baluta 				       0);
1131fd3ae7a9SDaniel Baluta 
1132fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_YP)
1133fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1134fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1135fd3ae7a9SDaniel Baluta 				       0,
1136fd3ae7a9SDaniel Baluta 				       IIO_MOD_Y,
1137fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1138fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_RISING),
1139fd3ae7a9SDaniel Baluta 				       0);
1140fd3ae7a9SDaniel Baluta 
1141fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_ZN)
1142fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1143fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1144fd3ae7a9SDaniel Baluta 				       0,
1145fd3ae7a9SDaniel Baluta 				       IIO_MOD_Z,
1146fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1147fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_FALLING),
1148fd3ae7a9SDaniel Baluta 				       0);
1149fd3ae7a9SDaniel Baluta 
1150fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_ZP)
1151fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1152fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1153fd3ae7a9SDaniel Baluta 				       0,
1154fd3ae7a9SDaniel Baluta 				       IIO_MOD_Z,
1155fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1156fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_RISING),
1157fd3ae7a9SDaniel Baluta 				       0);
1158fd3ae7a9SDaniel Baluta 	}
1159fd3ae7a9SDaniel Baluta 
1160fd3ae7a9SDaniel Baluta ack_intr:
1161fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1);
1162fd3ae7a9SDaniel Baluta 	if (ret < 0)
1163fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
1164fd3ae7a9SDaniel Baluta 
1165fd3ae7a9SDaniel Baluta 	ret |= KMX61_REG_CTRL1_BIT_RES;
1166fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret);
1167fd3ae7a9SDaniel Baluta 	if (ret < 0)
116828ff344eSDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
1169fd3ae7a9SDaniel Baluta 
1170fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL);
1171fd3ae7a9SDaniel Baluta 	if (ret < 0)
1172fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_inl\n");
1173fd3ae7a9SDaniel Baluta 
1174fd3ae7a9SDaniel Baluta 	return IRQ_HANDLED;
1175fd3ae7a9SDaniel Baluta }
1176fd3ae7a9SDaniel Baluta 
1177c3a23eccSDaniel Baluta static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private)
1178c3a23eccSDaniel Baluta {
1179c3a23eccSDaniel Baluta 	struct kmx61_data *data = private;
1180c3a23eccSDaniel Baluta 
1181c3a23eccSDaniel Baluta 	if (data->acc_dready_trig_on)
1182c3a23eccSDaniel Baluta 		iio_trigger_poll(data->acc_dready_trig);
1183c3a23eccSDaniel Baluta 	if (data->mag_dready_trig_on)
1184c3a23eccSDaniel Baluta 		iio_trigger_poll(data->mag_dready_trig);
1185c3a23eccSDaniel Baluta 
1186fd3ae7a9SDaniel Baluta 	if (data->motion_trig_on)
1187fd3ae7a9SDaniel Baluta 		iio_trigger_poll(data->motion_trig);
1188fd3ae7a9SDaniel Baluta 
1189fd3ae7a9SDaniel Baluta 	if (data->ev_enable_state)
1190fd3ae7a9SDaniel Baluta 		return IRQ_WAKE_THREAD;
1191c3a23eccSDaniel Baluta 	return IRQ_HANDLED;
1192c3a23eccSDaniel Baluta }
1193c3a23eccSDaniel Baluta 
1194c3a23eccSDaniel Baluta static irqreturn_t kmx61_trigger_handler(int irq, void *p)
1195c3a23eccSDaniel Baluta {
1196c3a23eccSDaniel Baluta 	struct iio_poll_func *pf = p;
1197c3a23eccSDaniel Baluta 	struct iio_dev *indio_dev = pf->indio_dev;
1198c3a23eccSDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
1199c3a23eccSDaniel Baluta 	int bit, ret, i = 0;
12006a191c70SDaniel Baluta 	u8 base;
1201c3a23eccSDaniel Baluta 	s16 buffer[8];
1202c3a23eccSDaniel Baluta 
12036a191c70SDaniel Baluta 	if (indio_dev == data->acc_indio_dev)
12046a191c70SDaniel Baluta 		base = KMX61_ACC_XOUT_L;
12056a191c70SDaniel Baluta 	else
12066a191c70SDaniel Baluta 		base = KMX61_MAG_XOUT_L;
12076a191c70SDaniel Baluta 
1208c3a23eccSDaniel Baluta 	mutex_lock(&data->lock);
120970dddeeeSOctavian Purdila 	for_each_set_bit(bit, indio_dev->active_scan_mask,
1210c3a23eccSDaniel Baluta 			 indio_dev->masklength) {
12116a191c70SDaniel Baluta 		ret = kmx61_read_measurement(data, base, bit);
1212c3a23eccSDaniel Baluta 		if (ret < 0) {
1213c3a23eccSDaniel Baluta 			mutex_unlock(&data->lock);
1214c3a23eccSDaniel Baluta 			goto err;
1215c3a23eccSDaniel Baluta 		}
1216c3a23eccSDaniel Baluta 		buffer[i++] = ret;
1217c3a23eccSDaniel Baluta 	}
1218c3a23eccSDaniel Baluta 	mutex_unlock(&data->lock);
1219c3a23eccSDaniel Baluta 
1220c3a23eccSDaniel Baluta 	iio_push_to_buffers(indio_dev, buffer);
1221c3a23eccSDaniel Baluta err:
1222c3a23eccSDaniel Baluta 	iio_trigger_notify_done(indio_dev->trig);
1223c3a23eccSDaniel Baluta 
1224c3a23eccSDaniel Baluta 	return IRQ_HANDLED;
1225c3a23eccSDaniel Baluta }
1226c3a23eccSDaniel Baluta 
1227b25862c5SDaniel Baluta static const char *kmx61_match_acpi_device(struct device *dev)
1228b25862c5SDaniel Baluta {
1229b25862c5SDaniel Baluta 	const struct acpi_device_id *id;
1230b25862c5SDaniel Baluta 
1231b25862c5SDaniel Baluta 	id = acpi_match_device(dev->driver->acpi_match_table, dev);
1232b25862c5SDaniel Baluta 	if (!id)
1233b25862c5SDaniel Baluta 		return NULL;
1234b25862c5SDaniel Baluta 	return dev_name(dev);
1235b25862c5SDaniel Baluta }
1236b25862c5SDaniel Baluta 
123720ffac27SDaniel Baluta static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data,
123820ffac27SDaniel Baluta 					    const struct iio_info *info,
123920ffac27SDaniel Baluta 					    const struct iio_chan_spec *chan,
124020ffac27SDaniel Baluta 					    int num_channels,
124120ffac27SDaniel Baluta 					    const char *name)
124220ffac27SDaniel Baluta {
124320ffac27SDaniel Baluta 	struct iio_dev *indio_dev;
124420ffac27SDaniel Baluta 
124520ffac27SDaniel Baluta 	indio_dev = devm_iio_device_alloc(&data->client->dev, sizeof(data));
124620ffac27SDaniel Baluta 	if (!indio_dev)
124720ffac27SDaniel Baluta 		return ERR_PTR(-ENOMEM);
124820ffac27SDaniel Baluta 
124920ffac27SDaniel Baluta 	kmx61_set_data(indio_dev, data);
125020ffac27SDaniel Baluta 
125120ffac27SDaniel Baluta 	indio_dev->dev.parent = &data->client->dev;
125220ffac27SDaniel Baluta 	indio_dev->channels = chan;
125320ffac27SDaniel Baluta 	indio_dev->num_channels = num_channels;
125420ffac27SDaniel Baluta 	indio_dev->name = name;
125520ffac27SDaniel Baluta 	indio_dev->modes = INDIO_DIRECT_MODE;
125620ffac27SDaniel Baluta 	indio_dev->info = info;
125720ffac27SDaniel Baluta 
125820ffac27SDaniel Baluta 	return indio_dev;
125920ffac27SDaniel Baluta }
126020ffac27SDaniel Baluta 
1261c3a23eccSDaniel Baluta static struct iio_trigger *kmx61_trigger_setup(struct kmx61_data *data,
1262c3a23eccSDaniel Baluta 					       struct iio_dev *indio_dev,
1263c3a23eccSDaniel Baluta 					       const char *tag)
1264c3a23eccSDaniel Baluta {
1265c3a23eccSDaniel Baluta 	struct iio_trigger *trig;
1266c3a23eccSDaniel Baluta 	int ret;
1267c3a23eccSDaniel Baluta 
1268c3a23eccSDaniel Baluta 	trig = devm_iio_trigger_alloc(&data->client->dev,
1269c3a23eccSDaniel Baluta 				      "%s-%s-dev%d",
1270c3a23eccSDaniel Baluta 				      indio_dev->name,
1271c3a23eccSDaniel Baluta 				      tag,
1272c3a23eccSDaniel Baluta 				      indio_dev->id);
1273c3a23eccSDaniel Baluta 	if (!trig)
1274c3a23eccSDaniel Baluta 		return ERR_PTR(-ENOMEM);
1275c3a23eccSDaniel Baluta 
1276c3a23eccSDaniel Baluta 	trig->dev.parent = &data->client->dev;
1277c3a23eccSDaniel Baluta 	trig->ops = &kmx61_trigger_ops;
1278c3a23eccSDaniel Baluta 	iio_trigger_set_drvdata(trig, indio_dev);
1279c3a23eccSDaniel Baluta 
1280c3a23eccSDaniel Baluta 	ret = iio_trigger_register(trig);
1281c3a23eccSDaniel Baluta 	if (ret)
1282c3a23eccSDaniel Baluta 		return ERR_PTR(ret);
1283c3a23eccSDaniel Baluta 
1284c3a23eccSDaniel Baluta 	return trig;
1285c3a23eccSDaniel Baluta }
1286c3a23eccSDaniel Baluta 
128720ffac27SDaniel Baluta static int kmx61_probe(struct i2c_client *client,
128820ffac27SDaniel Baluta 		       const struct i2c_device_id *id)
128920ffac27SDaniel Baluta {
129020ffac27SDaniel Baluta 	int ret;
129120ffac27SDaniel Baluta 	struct kmx61_data *data;
129220ffac27SDaniel Baluta 	const char *name = NULL;
129320ffac27SDaniel Baluta 
129420ffac27SDaniel Baluta 	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
129520ffac27SDaniel Baluta 	if (!data)
129620ffac27SDaniel Baluta 		return -ENOMEM;
129720ffac27SDaniel Baluta 
129820ffac27SDaniel Baluta 	i2c_set_clientdata(client, data);
129920ffac27SDaniel Baluta 	data->client = client;
130020ffac27SDaniel Baluta 
130120ffac27SDaniel Baluta 	mutex_init(&data->lock);
130220ffac27SDaniel Baluta 
1303b25862c5SDaniel Baluta 	if (id)
1304b25862c5SDaniel Baluta 		name = id->name;
1305b25862c5SDaniel Baluta 	else if (ACPI_HANDLE(&client->dev))
1306b25862c5SDaniel Baluta 		name = kmx61_match_acpi_device(&client->dev);
1307b25862c5SDaniel Baluta 	else
1308b25862c5SDaniel Baluta 		return -ENODEV;
1309b25862c5SDaniel Baluta 
131020ffac27SDaniel Baluta 	data->acc_indio_dev =
131120ffac27SDaniel Baluta 		kmx61_indiodev_setup(data, &kmx61_acc_info,
131220ffac27SDaniel Baluta 				     kmx61_acc_channels,
131320ffac27SDaniel Baluta 				     ARRAY_SIZE(kmx61_acc_channels),
131420ffac27SDaniel Baluta 				     name);
131520ffac27SDaniel Baluta 	if (IS_ERR(data->acc_indio_dev))
131620ffac27SDaniel Baluta 		return PTR_ERR(data->acc_indio_dev);
131720ffac27SDaniel Baluta 
131820ffac27SDaniel Baluta 	data->mag_indio_dev =
131920ffac27SDaniel Baluta 		kmx61_indiodev_setup(data, &kmx61_mag_info,
132020ffac27SDaniel Baluta 				     kmx61_mag_channels,
132120ffac27SDaniel Baluta 				     ARRAY_SIZE(kmx61_mag_channels),
132220ffac27SDaniel Baluta 				     name);
132320ffac27SDaniel Baluta 	if (IS_ERR(data->mag_indio_dev))
132420ffac27SDaniel Baluta 		return PTR_ERR(data->mag_indio_dev);
132520ffac27SDaniel Baluta 
132620ffac27SDaniel Baluta 	ret = kmx61_chip_init(data);
132720ffac27SDaniel Baluta 	if (ret < 0)
132820ffac27SDaniel Baluta 		return ret;
132920ffac27SDaniel Baluta 
1330c176becdSOctavian Purdila 	if (client->irq > 0) {
1331c3a23eccSDaniel Baluta 		ret = devm_request_threaded_irq(&client->dev, client->irq,
1332c3a23eccSDaniel Baluta 						kmx61_data_rdy_trig_poll,
1333fd3ae7a9SDaniel Baluta 						kmx61_event_handler,
1334c3a23eccSDaniel Baluta 						IRQF_TRIGGER_RISING,
1335c3a23eccSDaniel Baluta 						KMX61_IRQ_NAME,
1336c3a23eccSDaniel Baluta 						data);
1337c3a23eccSDaniel Baluta 		if (ret)
1338c3a23eccSDaniel Baluta 			goto err_chip_uninit;
1339c3a23eccSDaniel Baluta 
1340c3a23eccSDaniel Baluta 		data->acc_dready_trig =
1341c3a23eccSDaniel Baluta 			kmx61_trigger_setup(data, data->acc_indio_dev,
1342c3a23eccSDaniel Baluta 					    "dready");
134328ff344eSDaniel Baluta 		if (IS_ERR(data->acc_dready_trig)) {
134428ff344eSDaniel Baluta 			ret = PTR_ERR(data->acc_dready_trig);
134528ff344eSDaniel Baluta 			goto err_chip_uninit;
134628ff344eSDaniel Baluta 		}
1347c3a23eccSDaniel Baluta 
1348c3a23eccSDaniel Baluta 		data->mag_dready_trig =
1349c3a23eccSDaniel Baluta 			kmx61_trigger_setup(data, data->mag_indio_dev,
1350c3a23eccSDaniel Baluta 					    "dready");
1351c3a23eccSDaniel Baluta 		if (IS_ERR(data->mag_dready_trig)) {
1352c3a23eccSDaniel Baluta 			ret = PTR_ERR(data->mag_dready_trig);
135328ff344eSDaniel Baluta 			goto err_trigger_unregister_acc_dready;
1354c3a23eccSDaniel Baluta 		}
1355c3a23eccSDaniel Baluta 
1356fd3ae7a9SDaniel Baluta 		data->motion_trig =
1357fd3ae7a9SDaniel Baluta 			kmx61_trigger_setup(data, data->acc_indio_dev,
1358fd3ae7a9SDaniel Baluta 					    "any-motion");
1359fd3ae7a9SDaniel Baluta 		if (IS_ERR(data->motion_trig)) {
1360fd3ae7a9SDaniel Baluta 			ret = PTR_ERR(data->motion_trig);
136128ff344eSDaniel Baluta 			goto err_trigger_unregister_mag_dready;
1362fd3ae7a9SDaniel Baluta 		}
1363fd3ae7a9SDaniel Baluta 
1364c3a23eccSDaniel Baluta 		ret = iio_triggered_buffer_setup(data->acc_indio_dev,
1365c3a23eccSDaniel Baluta 						 &iio_pollfunc_store_time,
1366c3a23eccSDaniel Baluta 						 kmx61_trigger_handler,
1367c3a23eccSDaniel Baluta 						 NULL);
1368c3a23eccSDaniel Baluta 		if (ret < 0) {
1369c3a23eccSDaniel Baluta 			dev_err(&data->client->dev,
1370c3a23eccSDaniel Baluta 				"Failed to setup acc triggered buffer\n");
137128ff344eSDaniel Baluta 			goto err_trigger_unregister_motion;
1372c3a23eccSDaniel Baluta 		}
1373c3a23eccSDaniel Baluta 
1374c3a23eccSDaniel Baluta 		ret = iio_triggered_buffer_setup(data->mag_indio_dev,
1375c3a23eccSDaniel Baluta 						 &iio_pollfunc_store_time,
1376c3a23eccSDaniel Baluta 						 kmx61_trigger_handler,
1377c3a23eccSDaniel Baluta 						 NULL);
1378c3a23eccSDaniel Baluta 		if (ret < 0) {
1379c3a23eccSDaniel Baluta 			dev_err(&data->client->dev,
1380c3a23eccSDaniel Baluta 				"Failed to setup mag triggered buffer\n");
138128ff344eSDaniel Baluta 			goto err_buffer_cleanup_acc;
1382c3a23eccSDaniel Baluta 		}
1383c3a23eccSDaniel Baluta 	}
1384c3a23eccSDaniel Baluta 
13857d0ead5cSAdriana Reus 	ret = pm_runtime_set_active(&client->dev);
13867d0ead5cSAdriana Reus 	if (ret < 0)
13877d0ead5cSAdriana Reus 		goto err_buffer_cleanup_mag;
13887d0ead5cSAdriana Reus 
13897d0ead5cSAdriana Reus 	pm_runtime_enable(&client->dev);
13907d0ead5cSAdriana Reus 	pm_runtime_set_autosuspend_delay(&client->dev, KMX61_SLEEP_DELAY_MS);
13917d0ead5cSAdriana Reus 	pm_runtime_use_autosuspend(&client->dev);
13927d0ead5cSAdriana Reus 
139320ffac27SDaniel Baluta 	ret = iio_device_register(data->acc_indio_dev);
139420ffac27SDaniel Baluta 	if (ret < 0) {
139520ffac27SDaniel Baluta 		dev_err(&client->dev, "Failed to register acc iio device\n");
139628ff344eSDaniel Baluta 		goto err_buffer_cleanup_mag;
139720ffac27SDaniel Baluta 	}
139820ffac27SDaniel Baluta 
139920ffac27SDaniel Baluta 	ret = iio_device_register(data->mag_indio_dev);
140020ffac27SDaniel Baluta 	if (ret < 0) {
140120ffac27SDaniel Baluta 		dev_err(&client->dev, "Failed to register mag iio device\n");
1402aff8609aSDaniel Baluta 		goto err_iio_unregister_acc;
140320ffac27SDaniel Baluta 	}
140420ffac27SDaniel Baluta 
140520ffac27SDaniel Baluta 	return 0;
140620ffac27SDaniel Baluta 
1407aff8609aSDaniel Baluta err_iio_unregister_acc:
140820ffac27SDaniel Baluta 	iio_device_unregister(data->acc_indio_dev);
140928ff344eSDaniel Baluta err_buffer_cleanup_mag:
1410c176becdSOctavian Purdila 	if (client->irq > 0)
1411c3a23eccSDaniel Baluta 		iio_triggered_buffer_cleanup(data->mag_indio_dev);
141228ff344eSDaniel Baluta err_buffer_cleanup_acc:
1413c176becdSOctavian Purdila 	if (client->irq > 0)
141428ff344eSDaniel Baluta 		iio_triggered_buffer_cleanup(data->acc_indio_dev);
141528ff344eSDaniel Baluta err_trigger_unregister_motion:
1416fd3ae7a9SDaniel Baluta 	iio_trigger_unregister(data->motion_trig);
141728ff344eSDaniel Baluta err_trigger_unregister_mag_dready:
141828ff344eSDaniel Baluta 	iio_trigger_unregister(data->mag_dready_trig);
141928ff344eSDaniel Baluta err_trigger_unregister_acc_dready:
142028ff344eSDaniel Baluta 	iio_trigger_unregister(data->acc_dready_trig);
142120ffac27SDaniel Baluta err_chip_uninit:
142220ffac27SDaniel Baluta 	kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
142320ffac27SDaniel Baluta 	return ret;
142420ffac27SDaniel Baluta }
142520ffac27SDaniel Baluta 
142620ffac27SDaniel Baluta static int kmx61_remove(struct i2c_client *client)
142720ffac27SDaniel Baluta {
142820ffac27SDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(client);
142920ffac27SDaniel Baluta 
14307d0ead5cSAdriana Reus 	iio_device_unregister(data->acc_indio_dev);
14317d0ead5cSAdriana Reus 	iio_device_unregister(data->mag_indio_dev);
14327d0ead5cSAdriana Reus 
1433aff8609aSDaniel Baluta 	pm_runtime_disable(&client->dev);
1434aff8609aSDaniel Baluta 	pm_runtime_set_suspended(&client->dev);
1435aff8609aSDaniel Baluta 	pm_runtime_put_noidle(&client->dev);
1436aff8609aSDaniel Baluta 
1437c176becdSOctavian Purdila 	if (client->irq > 0) {
1438c3a23eccSDaniel Baluta 		iio_triggered_buffer_cleanup(data->acc_indio_dev);
1439c3a23eccSDaniel Baluta 		iio_triggered_buffer_cleanup(data->mag_indio_dev);
1440c3a23eccSDaniel Baluta 		iio_trigger_unregister(data->acc_dready_trig);
1441c3a23eccSDaniel Baluta 		iio_trigger_unregister(data->mag_dready_trig);
1442fd3ae7a9SDaniel Baluta 		iio_trigger_unregister(data->motion_trig);
1443c3a23eccSDaniel Baluta 	}
1444c3a23eccSDaniel Baluta 
144520ffac27SDaniel Baluta 	mutex_lock(&data->lock);
144620ffac27SDaniel Baluta 	kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
144720ffac27SDaniel Baluta 	mutex_unlock(&data->lock);
144820ffac27SDaniel Baluta 
144920ffac27SDaniel Baluta 	return 0;
145020ffac27SDaniel Baluta }
145120ffac27SDaniel Baluta 
14523b9c40e6SDaniel Baluta #ifdef CONFIG_PM_SLEEP
14533b9c40e6SDaniel Baluta static int kmx61_suspend(struct device *dev)
14543b9c40e6SDaniel Baluta {
14553b9c40e6SDaniel Baluta 	int ret;
14563b9c40e6SDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev));
14573b9c40e6SDaniel Baluta 
14583b9c40e6SDaniel Baluta 	mutex_lock(&data->lock);
14593b9c40e6SDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG,
14603b9c40e6SDaniel Baluta 			     false);
14613b9c40e6SDaniel Baluta 	mutex_unlock(&data->lock);
14623b9c40e6SDaniel Baluta 
14633b9c40e6SDaniel Baluta 	return ret;
14643b9c40e6SDaniel Baluta }
14653b9c40e6SDaniel Baluta 
14663b9c40e6SDaniel Baluta static int kmx61_resume(struct device *dev)
14673b9c40e6SDaniel Baluta {
14683b9c40e6SDaniel Baluta 	u8 stby = 0;
14693b9c40e6SDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev));
14703b9c40e6SDaniel Baluta 
14713b9c40e6SDaniel Baluta 	if (data->acc_stby)
14723b9c40e6SDaniel Baluta 		stby |= KMX61_ACC_STBY_BIT;
14733b9c40e6SDaniel Baluta 	if (data->mag_stby)
14743b9c40e6SDaniel Baluta 		stby |= KMX61_MAG_STBY_BIT;
14753b9c40e6SDaniel Baluta 
14763b9c40e6SDaniel Baluta 	return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true);
14773b9c40e6SDaniel Baluta }
14783b9c40e6SDaniel Baluta #endif
1479aff8609aSDaniel Baluta 
1480df1fad80SDaniel Baluta #ifdef CONFIG_PM
1481aff8609aSDaniel Baluta static int kmx61_runtime_suspend(struct device *dev)
1482aff8609aSDaniel Baluta {
1483aff8609aSDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev));
1484aff8609aSDaniel Baluta 	int ret;
1485aff8609aSDaniel Baluta 
1486aff8609aSDaniel Baluta 	mutex_lock(&data->lock);
1487aff8609aSDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
1488aff8609aSDaniel Baluta 	mutex_unlock(&data->lock);
1489aff8609aSDaniel Baluta 
1490aff8609aSDaniel Baluta 	return ret;
1491aff8609aSDaniel Baluta }
1492aff8609aSDaniel Baluta 
1493aff8609aSDaniel Baluta static int kmx61_runtime_resume(struct device *dev)
1494aff8609aSDaniel Baluta {
1495aff8609aSDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev));
1496aff8609aSDaniel Baluta 	u8 stby = 0;
1497aff8609aSDaniel Baluta 
1498aff8609aSDaniel Baluta 	if (!data->acc_ps)
1499aff8609aSDaniel Baluta 		stby |= KMX61_ACC_STBY_BIT;
1500aff8609aSDaniel Baluta 	if (!data->mag_ps)
1501aff8609aSDaniel Baluta 		stby |= KMX61_MAG_STBY_BIT;
1502aff8609aSDaniel Baluta 
1503aff8609aSDaniel Baluta 	return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true);
1504aff8609aSDaniel Baluta }
1505aff8609aSDaniel Baluta #endif
1506aff8609aSDaniel Baluta 
1507aff8609aSDaniel Baluta static const struct dev_pm_ops kmx61_pm_ops = {
15083b9c40e6SDaniel Baluta 	SET_SYSTEM_SLEEP_PM_OPS(kmx61_suspend, kmx61_resume)
1509aff8609aSDaniel Baluta 	SET_RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL)
1510aff8609aSDaniel Baluta };
1511aff8609aSDaniel Baluta 
1512b25862c5SDaniel Baluta static const struct acpi_device_id kmx61_acpi_match[] = {
1513b25862c5SDaniel Baluta 	{"KMX61021", 0},
1514b25862c5SDaniel Baluta 	{}
1515b25862c5SDaniel Baluta };
1516b25862c5SDaniel Baluta 
1517b25862c5SDaniel Baluta MODULE_DEVICE_TABLE(acpi, kmx61_acpi_match);
1518b25862c5SDaniel Baluta 
151920ffac27SDaniel Baluta static const struct i2c_device_id kmx61_id[] = {
152020ffac27SDaniel Baluta 	{"kmx611021", 0},
152120ffac27SDaniel Baluta 	{}
152220ffac27SDaniel Baluta };
152320ffac27SDaniel Baluta 
152420ffac27SDaniel Baluta MODULE_DEVICE_TABLE(i2c, kmx61_id);
152520ffac27SDaniel Baluta 
152620ffac27SDaniel Baluta static struct i2c_driver kmx61_driver = {
152720ffac27SDaniel Baluta 	.driver = {
152820ffac27SDaniel Baluta 		.name = KMX61_DRV_NAME,
1529b25862c5SDaniel Baluta 		.acpi_match_table = ACPI_PTR(kmx61_acpi_match),
1530aff8609aSDaniel Baluta 		.pm = &kmx61_pm_ops,
153120ffac27SDaniel Baluta 	},
153220ffac27SDaniel Baluta 	.probe		= kmx61_probe,
153320ffac27SDaniel Baluta 	.remove		= kmx61_remove,
153420ffac27SDaniel Baluta 	.id_table	= kmx61_id,
153520ffac27SDaniel Baluta };
153620ffac27SDaniel Baluta 
153720ffac27SDaniel Baluta module_i2c_driver(kmx61_driver);
153820ffac27SDaniel Baluta 
153920ffac27SDaniel Baluta MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
154020ffac27SDaniel Baluta MODULE_DESCRIPTION("KMX61 accelerometer/magnetometer driver");
154120ffac27SDaniel Baluta MODULE_LICENSE("GPL v2");
1542