xref: /openbmc/linux/drivers/iio/imu/kmx61.c (revision a3da4fa301ae60aac688ca320fb8b46a053d6d25)
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>
16b25862c5SDaniel Baluta #include <linux/acpi.h>
17b25862c5SDaniel Baluta #include <linux/gpio/consumer.h>
18aff8609aSDaniel Baluta #include <linux/interrupt.h>
193b9c40e6SDaniel Baluta #include <linux/pm.h>
20aff8609aSDaniel Baluta #include <linux/pm_runtime.h>
2120ffac27SDaniel Baluta #include <linux/iio/iio.h>
2220ffac27SDaniel Baluta #include <linux/iio/sysfs.h>
23fd3ae7a9SDaniel Baluta #include <linux/iio/events.h>
24c3a23eccSDaniel Baluta #include <linux/iio/trigger.h>
25c3a23eccSDaniel Baluta #include <linux/iio/buffer.h>
26c3a23eccSDaniel Baluta #include <linux/iio/triggered_buffer.h>
27c3a23eccSDaniel Baluta #include <linux/iio/trigger_consumer.h>
2820ffac27SDaniel Baluta 
2920ffac27SDaniel Baluta #define KMX61_DRV_NAME "kmx61"
30b25862c5SDaniel Baluta #define KMX61_GPIO_NAME "kmx61_int"
31c3a23eccSDaniel Baluta #define KMX61_IRQ_NAME "kmx61_event"
3220ffac27SDaniel Baluta 
3320ffac27SDaniel Baluta #define KMX61_REG_WHO_AM_I	0x00
34fd3ae7a9SDaniel Baluta #define KMX61_REG_INS1		0x01
35fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2		0x02
3620ffac27SDaniel Baluta 
3720ffac27SDaniel Baluta /*
3820ffac27SDaniel Baluta  * three 16-bit accelerometer output registers for X/Y/Z axis
3920ffac27SDaniel Baluta  * we use only XOUT_L as a base register, all other addresses
4020ffac27SDaniel Baluta  * can be obtained by applying an offset and are provided here
4120ffac27SDaniel Baluta  * only for clarity.
4220ffac27SDaniel Baluta  */
4320ffac27SDaniel Baluta #define KMX61_ACC_XOUT_L	0x0A
4420ffac27SDaniel Baluta #define KMX61_ACC_XOUT_H	0x0B
4520ffac27SDaniel Baluta #define KMX61_ACC_YOUT_L	0x0C
4620ffac27SDaniel Baluta #define KMX61_ACC_YOUT_H	0x0D
4720ffac27SDaniel Baluta #define KMX61_ACC_ZOUT_L	0x0E
4820ffac27SDaniel Baluta #define KMX61_ACC_ZOUT_H	0x0F
4920ffac27SDaniel Baluta 
5020ffac27SDaniel Baluta /*
5120ffac27SDaniel Baluta  * one 16-bit temperature output register
5220ffac27SDaniel Baluta  */
5320ffac27SDaniel Baluta #define KMX61_TEMP_L		0x10
5420ffac27SDaniel Baluta #define KMX61_TEMP_H		0x11
5520ffac27SDaniel Baluta 
5620ffac27SDaniel Baluta /*
5720ffac27SDaniel Baluta  * three 16-bit magnetometer output registers for X/Y/Z axis
5820ffac27SDaniel Baluta  */
5920ffac27SDaniel Baluta #define KMX61_MAG_XOUT_L	0x12
6020ffac27SDaniel Baluta #define KMX61_MAG_XOUT_H	0x13
6120ffac27SDaniel Baluta #define KMX61_MAG_YOUT_L	0x14
6220ffac27SDaniel Baluta #define KMX61_MAG_YOUT_H	0x15
6320ffac27SDaniel Baluta #define KMX61_MAG_ZOUT_L	0x16
6420ffac27SDaniel Baluta #define KMX61_MAG_ZOUT_H	0x17
6520ffac27SDaniel Baluta 
66c3a23eccSDaniel Baluta #define KMX61_REG_INL		0x28
6720ffac27SDaniel Baluta #define KMX61_REG_STBY		0x29
6820ffac27SDaniel Baluta #define KMX61_REG_CTRL1		0x2A
69fd3ae7a9SDaniel Baluta #define KMX61_REG_CTRL2		0x2B
7020ffac27SDaniel Baluta #define KMX61_REG_ODCNTL	0x2C
71c3a23eccSDaniel Baluta #define KMX61_REG_INC1		0x2D
7220ffac27SDaniel Baluta 
73fd3ae7a9SDaniel Baluta #define KMX61_REG_WUF_THRESH	0x3D
74fd3ae7a9SDaniel Baluta #define KMX61_REG_WUF_TIMER	0x3E
75fd3ae7a9SDaniel Baluta 
7620ffac27SDaniel Baluta #define KMX61_ACC_STBY_BIT	BIT(0)
7720ffac27SDaniel Baluta #define KMX61_MAG_STBY_BIT	BIT(1)
7820ffac27SDaniel Baluta #define KMX61_ACT_STBY_BIT	BIT(7)
7920ffac27SDaniel Baluta 
8020ffac27SDaniel Baluta #define KMX61_ALL_STBY		(KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT)
8120ffac27SDaniel Baluta 
82fd3ae7a9SDaniel Baluta #define KMX61_REG_INS1_BIT_WUFS		BIT(1)
83fd3ae7a9SDaniel Baluta 
84fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_ZP		BIT(0)
85fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_ZN		BIT(1)
86fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_YP		BIT(2)
87fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_YN		BIT(3)
88fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_XP		BIT(4)
89fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_XN		BIT(5)
90fd3ae7a9SDaniel Baluta 
9120ffac27SDaniel Baluta #define KMX61_REG_CTRL1_GSEL_MASK	0x03
9220ffac27SDaniel Baluta 
93c3a23eccSDaniel Baluta #define KMX61_REG_CTRL1_BIT_RES		BIT(4)
94c3a23eccSDaniel Baluta #define KMX61_REG_CTRL1_BIT_DRDYE	BIT(5)
95fd3ae7a9SDaniel Baluta #define KMX61_REG_CTRL1_BIT_WUFE	BIT(6)
96fd3ae7a9SDaniel Baluta #define KMX61_REG_CTRL1_BIT_BTSE	BIT(7)
97c3a23eccSDaniel Baluta 
98fd3ae7a9SDaniel Baluta #define KMX61_REG_INC1_BIT_WUFS		BIT(0)
99c3a23eccSDaniel Baluta #define KMX61_REG_INC1_BIT_DRDYM	BIT(1)
100c3a23eccSDaniel Baluta #define KMX61_REG_INC1_BIT_DRDYA	BIT(2)
101c3a23eccSDaniel Baluta #define KMX61_REG_INC1_BIT_IEN		BIT(5)
102c3a23eccSDaniel Baluta 
10320ffac27SDaniel Baluta #define KMX61_ACC_ODR_SHIFT	0
10420ffac27SDaniel Baluta #define KMX61_MAG_ODR_SHIFT	4
10520ffac27SDaniel Baluta #define KMX61_ACC_ODR_MASK	0x0F
10620ffac27SDaniel Baluta #define KMX61_MAG_ODR_MASK	0xF0
10720ffac27SDaniel Baluta 
108fd3ae7a9SDaniel Baluta #define KMX61_OWUF_MASK		0x7
109fd3ae7a9SDaniel Baluta 
110fd3ae7a9SDaniel Baluta #define KMX61_DEFAULT_WAKE_THRESH	1
111fd3ae7a9SDaniel Baluta #define KMX61_DEFAULT_WAKE_DURATION	1
112fd3ae7a9SDaniel Baluta 
113aff8609aSDaniel Baluta #define KMX61_SLEEP_DELAY_MS	2000
114aff8609aSDaniel Baluta 
11520ffac27SDaniel Baluta #define KMX61_CHIP_ID		0x12
11620ffac27SDaniel Baluta 
11720ffac27SDaniel Baluta /* KMX61 devices */
11820ffac27SDaniel Baluta #define KMX61_ACC	0x01
11920ffac27SDaniel Baluta #define KMX61_MAG	0x02
12020ffac27SDaniel Baluta 
12120ffac27SDaniel Baluta struct kmx61_data {
12220ffac27SDaniel Baluta 	struct i2c_client *client;
12320ffac27SDaniel Baluta 
12420ffac27SDaniel Baluta 	/* serialize access to non-atomic ops, e.g set_mode */
12520ffac27SDaniel Baluta 	struct mutex lock;
12620ffac27SDaniel Baluta 
12720ffac27SDaniel Baluta 	/* standby state */
12820ffac27SDaniel Baluta 	bool acc_stby;
12920ffac27SDaniel Baluta 	bool mag_stby;
13020ffac27SDaniel Baluta 
131aff8609aSDaniel Baluta 	/* power state */
132aff8609aSDaniel Baluta 	bool acc_ps;
133aff8609aSDaniel Baluta 	bool mag_ps;
134aff8609aSDaniel Baluta 
13520ffac27SDaniel Baluta 	/* config bits */
13620ffac27SDaniel Baluta 	u8 range;
13720ffac27SDaniel Baluta 	u8 odr_bits;
138fd3ae7a9SDaniel Baluta 	u8 wake_thresh;
139fd3ae7a9SDaniel Baluta 	u8 wake_duration;
14020ffac27SDaniel Baluta 
14120ffac27SDaniel Baluta 	/* accelerometer specific data */
14220ffac27SDaniel Baluta 	struct iio_dev *acc_indio_dev;
143c3a23eccSDaniel Baluta 	struct iio_trigger *acc_dready_trig;
144fd3ae7a9SDaniel Baluta 	struct iio_trigger *motion_trig;
145c3a23eccSDaniel Baluta 	bool acc_dready_trig_on;
146fd3ae7a9SDaniel Baluta 	bool motion_trig_on;
147fd3ae7a9SDaniel Baluta 	bool ev_enable_state;
14820ffac27SDaniel Baluta 
14920ffac27SDaniel Baluta 	/* magnetometer specific data */
15020ffac27SDaniel Baluta 	struct iio_dev *mag_indio_dev;
151c3a23eccSDaniel Baluta 	struct iio_trigger *mag_dready_trig;
152c3a23eccSDaniel Baluta 	bool mag_dready_trig_on;
15320ffac27SDaniel Baluta };
15420ffac27SDaniel Baluta 
15520ffac27SDaniel Baluta enum kmx61_range {
15620ffac27SDaniel Baluta 	KMX61_RANGE_2G,
15720ffac27SDaniel Baluta 	KMX61_RANGE_4G,
15820ffac27SDaniel Baluta 	KMX61_RANGE_8G,
15920ffac27SDaniel Baluta };
16020ffac27SDaniel Baluta 
16120ffac27SDaniel Baluta enum kmx61_axis {
16220ffac27SDaniel Baluta 	KMX61_AXIS_X,
16320ffac27SDaniel Baluta 	KMX61_AXIS_Y,
16420ffac27SDaniel Baluta 	KMX61_AXIS_Z,
16520ffac27SDaniel Baluta };
16620ffac27SDaniel Baluta 
16720ffac27SDaniel Baluta static const u16 kmx61_uscale_table[] = {9582, 19163, 38326};
16820ffac27SDaniel Baluta 
16920ffac27SDaniel Baluta static const struct {
17020ffac27SDaniel Baluta 	int val;
17120ffac27SDaniel Baluta 	int val2;
17220ffac27SDaniel Baluta 	u8 odr_bits;
17320ffac27SDaniel Baluta } kmx61_samp_freq_table[] = { {12, 500000, 0x00},
17420ffac27SDaniel Baluta 			{25, 0, 0x01},
17520ffac27SDaniel Baluta 			{50, 0, 0x02},
17620ffac27SDaniel Baluta 			{100, 0, 0x03},
17720ffac27SDaniel Baluta 			{200, 0, 0x04},
17820ffac27SDaniel Baluta 			{400, 0, 0x05},
17920ffac27SDaniel Baluta 			{800, 0, 0x06},
18020ffac27SDaniel Baluta 			{1600, 0, 0x07},
18120ffac27SDaniel Baluta 			{0, 781000, 0x08},
18220ffac27SDaniel Baluta 			{1, 563000, 0x09},
18320ffac27SDaniel Baluta 			{3, 125000, 0x0A},
18420ffac27SDaniel Baluta 			{6, 250000, 0x0B} };
18520ffac27SDaniel Baluta 
186fd3ae7a9SDaniel Baluta static const struct {
187fd3ae7a9SDaniel Baluta 	int val;
188fd3ae7a9SDaniel Baluta 	int val2;
189fd3ae7a9SDaniel Baluta 	int odr_bits;
190fd3ae7a9SDaniel Baluta } kmx61_wake_up_odr_table[] = { {0, 781000, 0x00},
191fd3ae7a9SDaniel Baluta 				 {1, 563000, 0x01},
192fd3ae7a9SDaniel Baluta 				 {3, 125000, 0x02},
193fd3ae7a9SDaniel Baluta 				 {6, 250000, 0x03},
194fd3ae7a9SDaniel Baluta 				 {12, 500000, 0x04},
195fd3ae7a9SDaniel Baluta 				 {25, 0, 0x05},
196fd3ae7a9SDaniel Baluta 				 {50, 0, 0x06},
197fd3ae7a9SDaniel Baluta 				 {100, 0, 0x06},
198fd3ae7a9SDaniel Baluta 				 {200, 0, 0x06},
199fd3ae7a9SDaniel Baluta 				 {400, 0, 0x06},
200fd3ae7a9SDaniel Baluta 				 {800, 0, 0x06},
201fd3ae7a9SDaniel Baluta 				 {1600, 0, 0x06} };
202fd3ae7a9SDaniel Baluta 
20320ffac27SDaniel Baluta static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326");
20420ffac27SDaniel Baluta static IIO_CONST_ATTR(magn_scale_available, "0.001465");
20520ffac27SDaniel Baluta static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
20620ffac27SDaniel Baluta 	"0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800");
20720ffac27SDaniel Baluta 
20820ffac27SDaniel Baluta static struct attribute *kmx61_acc_attributes[] = {
20920ffac27SDaniel Baluta 	&iio_const_attr_accel_scale_available.dev_attr.attr,
21020ffac27SDaniel Baluta 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
21120ffac27SDaniel Baluta 	NULL,
21220ffac27SDaniel Baluta };
21320ffac27SDaniel Baluta 
21420ffac27SDaniel Baluta static struct attribute *kmx61_mag_attributes[] = {
21520ffac27SDaniel Baluta 	&iio_const_attr_magn_scale_available.dev_attr.attr,
21620ffac27SDaniel Baluta 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
21720ffac27SDaniel Baluta 	NULL,
21820ffac27SDaniel Baluta };
21920ffac27SDaniel Baluta 
22020ffac27SDaniel Baluta static const struct attribute_group kmx61_acc_attribute_group = {
22120ffac27SDaniel Baluta 	.attrs = kmx61_acc_attributes,
22220ffac27SDaniel Baluta };
22320ffac27SDaniel Baluta 
22420ffac27SDaniel Baluta static const struct attribute_group kmx61_mag_attribute_group = {
22520ffac27SDaniel Baluta 	.attrs = kmx61_mag_attributes,
22620ffac27SDaniel Baluta };
22720ffac27SDaniel Baluta 
228fd3ae7a9SDaniel Baluta static const struct iio_event_spec kmx61_event = {
229fd3ae7a9SDaniel Baluta 	.type = IIO_EV_TYPE_THRESH,
230fd3ae7a9SDaniel Baluta 	.dir = IIO_EV_DIR_EITHER,
231fd3ae7a9SDaniel Baluta 	.mask_separate = BIT(IIO_EV_INFO_VALUE) |
232fd3ae7a9SDaniel Baluta 			 BIT(IIO_EV_INFO_ENABLE) |
233fd3ae7a9SDaniel Baluta 			 BIT(IIO_EV_INFO_PERIOD),
234fd3ae7a9SDaniel Baluta };
235fd3ae7a9SDaniel Baluta 
23620ffac27SDaniel Baluta #define KMX61_ACC_CHAN(_axis) { \
23720ffac27SDaniel Baluta 	.type = IIO_ACCEL, \
23820ffac27SDaniel Baluta 	.modified = 1, \
23920ffac27SDaniel Baluta 	.channel2 = IIO_MOD_ ## _axis, \
24020ffac27SDaniel Baluta 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
24120ffac27SDaniel Baluta 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
24220ffac27SDaniel Baluta 				BIT(IIO_CHAN_INFO_SAMP_FREQ), \
24320ffac27SDaniel Baluta 	.address = KMX61_ACC, \
24420ffac27SDaniel Baluta 	.scan_index = KMX61_AXIS_ ## _axis, \
24520ffac27SDaniel Baluta 	.scan_type = { \
24620ffac27SDaniel Baluta 		.sign = 's', \
24720ffac27SDaniel Baluta 		.realbits = 12, \
24820ffac27SDaniel Baluta 		.storagebits = 16, \
24920ffac27SDaniel Baluta 		.shift = 4, \
25020ffac27SDaniel Baluta 		.endianness = IIO_LE, \
25120ffac27SDaniel Baluta 	}, \
252fd3ae7a9SDaniel Baluta 	.event_spec = &kmx61_event, \
253fd3ae7a9SDaniel Baluta 	.num_event_specs = 1 \
25420ffac27SDaniel Baluta }
25520ffac27SDaniel Baluta 
25620ffac27SDaniel Baluta #define KMX61_MAG_CHAN(_axis) { \
25720ffac27SDaniel Baluta 	.type = IIO_MAGN, \
25820ffac27SDaniel Baluta 	.modified = 1, \
25920ffac27SDaniel Baluta 	.channel2 = IIO_MOD_ ## _axis, \
26020ffac27SDaniel Baluta 	.address = KMX61_MAG, \
26120ffac27SDaniel Baluta 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
26220ffac27SDaniel Baluta 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
26320ffac27SDaniel Baluta 				BIT(IIO_CHAN_INFO_SAMP_FREQ), \
26420ffac27SDaniel Baluta 	.scan_index = KMX61_AXIS_ ## _axis, \
26520ffac27SDaniel Baluta 	.scan_type = { \
26620ffac27SDaniel Baluta 		.sign = 's', \
26720ffac27SDaniel Baluta 		.realbits = 14, \
26820ffac27SDaniel Baluta 		.storagebits = 16, \
26920ffac27SDaniel Baluta 		.shift = 2, \
27020ffac27SDaniel Baluta 		.endianness = IIO_LE, \
27120ffac27SDaniel Baluta 	}, \
27220ffac27SDaniel Baluta }
27320ffac27SDaniel Baluta 
27420ffac27SDaniel Baluta static const struct iio_chan_spec kmx61_acc_channels[] = {
27520ffac27SDaniel Baluta 	KMX61_ACC_CHAN(X),
27620ffac27SDaniel Baluta 	KMX61_ACC_CHAN(Y),
27720ffac27SDaniel Baluta 	KMX61_ACC_CHAN(Z),
27820ffac27SDaniel Baluta };
27920ffac27SDaniel Baluta 
28020ffac27SDaniel Baluta static const struct iio_chan_spec kmx61_mag_channels[] = {
28120ffac27SDaniel Baluta 	KMX61_MAG_CHAN(X),
28220ffac27SDaniel Baluta 	KMX61_MAG_CHAN(Y),
28320ffac27SDaniel Baluta 	KMX61_MAG_CHAN(Z),
28420ffac27SDaniel Baluta };
28520ffac27SDaniel Baluta 
28620ffac27SDaniel Baluta static void kmx61_set_data(struct iio_dev *indio_dev, struct kmx61_data *data)
28720ffac27SDaniel Baluta {
28820ffac27SDaniel Baluta 	struct kmx61_data **priv = iio_priv(indio_dev);
28920ffac27SDaniel Baluta 
29020ffac27SDaniel Baluta 	*priv = data;
29120ffac27SDaniel Baluta }
29220ffac27SDaniel Baluta 
29320ffac27SDaniel Baluta static struct kmx61_data *kmx61_get_data(struct iio_dev *indio_dev)
29420ffac27SDaniel Baluta {
29520ffac27SDaniel Baluta 	return *(struct kmx61_data **)iio_priv(indio_dev);
29620ffac27SDaniel Baluta }
29720ffac27SDaniel Baluta 
29820ffac27SDaniel Baluta static int kmx61_convert_freq_to_bit(int val, int val2)
29920ffac27SDaniel Baluta {
30020ffac27SDaniel Baluta 	int i;
30120ffac27SDaniel Baluta 
30220ffac27SDaniel Baluta 	for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++)
30320ffac27SDaniel Baluta 		if (val == kmx61_samp_freq_table[i].val &&
30420ffac27SDaniel Baluta 		    val2 == kmx61_samp_freq_table[i].val2)
30520ffac27SDaniel Baluta 			return kmx61_samp_freq_table[i].odr_bits;
30620ffac27SDaniel Baluta 	return -EINVAL;
30720ffac27SDaniel Baluta }
30820ffac27SDaniel Baluta 
309fd3ae7a9SDaniel Baluta static int kmx61_convert_bit_to_freq(u8 odr_bits, int *val, int *val2)
310fd3ae7a9SDaniel Baluta {
311fd3ae7a9SDaniel Baluta 	int i;
312fd3ae7a9SDaniel Baluta 
313fd3ae7a9SDaniel Baluta 	for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++)
314fd3ae7a9SDaniel Baluta 		if (odr_bits == kmx61_samp_freq_table[i].odr_bits) {
315fd3ae7a9SDaniel Baluta 			*val = kmx61_samp_freq_table[i].val;
316fd3ae7a9SDaniel Baluta 			*val2 = kmx61_samp_freq_table[i].val2;
317fd3ae7a9SDaniel Baluta 			return 0;
318fd3ae7a9SDaniel Baluta 		}
319fd3ae7a9SDaniel Baluta 	return -EINVAL;
320fd3ae7a9SDaniel Baluta }
321fd3ae7a9SDaniel Baluta 
322fd3ae7a9SDaniel Baluta 
323fd3ae7a9SDaniel Baluta static int kmx61_convert_wake_up_odr_to_bit(int val, int val2)
324fd3ae7a9SDaniel Baluta {
325fd3ae7a9SDaniel Baluta 	int i;
326fd3ae7a9SDaniel Baluta 
327fd3ae7a9SDaniel Baluta 	for (i = 0; i < ARRAY_SIZE(kmx61_wake_up_odr_table); ++i)
328fd3ae7a9SDaniel Baluta 		if (kmx61_wake_up_odr_table[i].val == val &&
329fd3ae7a9SDaniel Baluta 			kmx61_wake_up_odr_table[i].val2 == val2)
330fd3ae7a9SDaniel Baluta 				return kmx61_wake_up_odr_table[i].odr_bits;
331fd3ae7a9SDaniel Baluta 	return -EINVAL;
332fd3ae7a9SDaniel Baluta }
333fd3ae7a9SDaniel Baluta 
33420ffac27SDaniel Baluta /**
33520ffac27SDaniel Baluta  * kmx61_set_mode() - set KMX61 device operating mode
33620ffac27SDaniel Baluta  * @data - kmx61 device private data pointer
33720ffac27SDaniel Baluta  * @mode - bitmask, indicating operating mode for @device
33820ffac27SDaniel Baluta  * @device - bitmask, indicating device for which @mode needs to be set
33920ffac27SDaniel Baluta  * @update - update stby bits stored in device's private  @data
34020ffac27SDaniel Baluta  *
34120ffac27SDaniel Baluta  * For each sensor (accelerometer/magnetometer) there are two operating modes
34220ffac27SDaniel Baluta  * STANDBY and OPERATION. Neither accel nor magn can be disabled independently
34320ffac27SDaniel Baluta  * if they are both enabled. Internal sensors state is saved in acc_stby and
34420ffac27SDaniel Baluta  * mag_stby members of driver's private @data.
34520ffac27SDaniel Baluta  */
34620ffac27SDaniel Baluta static int kmx61_set_mode(struct kmx61_data *data, u8 mode, u8 device,
34720ffac27SDaniel Baluta 			  bool update)
34820ffac27SDaniel Baluta {
34920ffac27SDaniel Baluta 	int ret;
35020ffac27SDaniel Baluta 	int acc_stby = -1, mag_stby = -1;
35120ffac27SDaniel Baluta 
35220ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY);
35320ffac27SDaniel Baluta 	if (ret < 0) {
35420ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_stby\n");
35520ffac27SDaniel Baluta 		return ret;
35620ffac27SDaniel Baluta 	}
35720ffac27SDaniel Baluta 	if (device & KMX61_ACC) {
35820ffac27SDaniel Baluta 		if (mode & KMX61_ACC_STBY_BIT) {
35920ffac27SDaniel Baluta 			ret |= KMX61_ACC_STBY_BIT;
36020ffac27SDaniel Baluta 			acc_stby = 1;
36120ffac27SDaniel Baluta 		} else {
36220ffac27SDaniel Baluta 			ret &= ~KMX61_ACC_STBY_BIT;
36320ffac27SDaniel Baluta 			acc_stby = 0;
36420ffac27SDaniel Baluta 		}
36520ffac27SDaniel Baluta 	}
36620ffac27SDaniel Baluta 
36720ffac27SDaniel Baluta 	if (device & KMX61_MAG) {
36820ffac27SDaniel Baluta 		if (mode & KMX61_MAG_STBY_BIT) {
36920ffac27SDaniel Baluta 			ret |= KMX61_MAG_STBY_BIT;
37020ffac27SDaniel Baluta 			mag_stby = 1;
37120ffac27SDaniel Baluta 		} else {
37220ffac27SDaniel Baluta 			ret &= ~KMX61_MAG_STBY_BIT;
37320ffac27SDaniel Baluta 			mag_stby = 0;
37420ffac27SDaniel Baluta 		}
37520ffac27SDaniel Baluta 	}
37620ffac27SDaniel Baluta 
37720ffac27SDaniel Baluta 	if (mode & KMX61_ACT_STBY_BIT)
37820ffac27SDaniel Baluta 		ret |= KMX61_ACT_STBY_BIT;
37920ffac27SDaniel Baluta 
38020ffac27SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_STBY, ret);
38120ffac27SDaniel Baluta 	if (ret < 0) {
38220ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_stby\n");
38320ffac27SDaniel Baluta 		return ret;
38420ffac27SDaniel Baluta 	}
38520ffac27SDaniel Baluta 
38620ffac27SDaniel Baluta 	if (acc_stby != -1 && update)
38720ffac27SDaniel Baluta 		data->acc_stby = acc_stby;
38820ffac27SDaniel Baluta 	if (mag_stby != -1 && update)
38920ffac27SDaniel Baluta 		data->mag_stby = mag_stby;
39020ffac27SDaniel Baluta 
39120ffac27SDaniel Baluta 	return 0;
39220ffac27SDaniel Baluta }
39320ffac27SDaniel Baluta 
39420ffac27SDaniel Baluta static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device)
39520ffac27SDaniel Baluta {
39620ffac27SDaniel Baluta 	int ret;
39720ffac27SDaniel Baluta 
39820ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY);
39920ffac27SDaniel Baluta 	if (ret < 0) {
40020ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_stby\n");
40120ffac27SDaniel Baluta 		return ret;
40220ffac27SDaniel Baluta 	}
40320ffac27SDaniel Baluta 	*mode = 0;
40420ffac27SDaniel Baluta 
40520ffac27SDaniel Baluta 	if (device & KMX61_ACC) {
40620ffac27SDaniel Baluta 		if (ret & KMX61_ACC_STBY_BIT)
40720ffac27SDaniel Baluta 			*mode |= KMX61_ACC_STBY_BIT;
40820ffac27SDaniel Baluta 		else
40920ffac27SDaniel Baluta 			*mode &= ~KMX61_ACC_STBY_BIT;
41020ffac27SDaniel Baluta 	}
41120ffac27SDaniel Baluta 
41220ffac27SDaniel Baluta 	if (device & KMX61_MAG) {
41320ffac27SDaniel Baluta 		if (ret & KMX61_MAG_STBY_BIT)
41420ffac27SDaniel Baluta 			*mode |= KMX61_MAG_STBY_BIT;
41520ffac27SDaniel Baluta 		else
41620ffac27SDaniel Baluta 			*mode &= ~KMX61_MAG_STBY_BIT;
41720ffac27SDaniel Baluta 	}
41820ffac27SDaniel Baluta 
41920ffac27SDaniel Baluta 	return 0;
42020ffac27SDaniel Baluta }
42120ffac27SDaniel Baluta 
422ebd16366Skbuild test robot static int kmx61_set_wake_up_odr(struct kmx61_data *data, int val, int val2)
423fd3ae7a9SDaniel Baluta {
424fd3ae7a9SDaniel Baluta 	int ret, odr_bits;
425fd3ae7a9SDaniel Baluta 
426fd3ae7a9SDaniel Baluta 	odr_bits = kmx61_convert_wake_up_odr_to_bit(val, val2);
427fd3ae7a9SDaniel Baluta 	if (odr_bits < 0)
428fd3ae7a9SDaniel Baluta 		return odr_bits;
429fd3ae7a9SDaniel Baluta 
430fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL2,
431fd3ae7a9SDaniel Baluta 					odr_bits);
432fd3ae7a9SDaniel Baluta 	if (ret < 0)
433fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl2\n");
434fd3ae7a9SDaniel Baluta 	return ret;
435fd3ae7a9SDaniel Baluta }
436fd3ae7a9SDaniel Baluta 
43720ffac27SDaniel Baluta static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device)
43820ffac27SDaniel Baluta {
43920ffac27SDaniel Baluta 	int ret;
44020ffac27SDaniel Baluta 	u8 mode;
44120ffac27SDaniel Baluta 	int lodr_bits, odr_bits;
44220ffac27SDaniel Baluta 
44320ffac27SDaniel Baluta 	ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG);
44420ffac27SDaniel Baluta 	if (ret < 0)
44520ffac27SDaniel Baluta 		return ret;
44620ffac27SDaniel Baluta 
44720ffac27SDaniel Baluta 	lodr_bits = kmx61_convert_freq_to_bit(val, val2);
44820ffac27SDaniel Baluta 	if (lodr_bits < 0)
44920ffac27SDaniel Baluta 		return lodr_bits;
45020ffac27SDaniel Baluta 
45120ffac27SDaniel Baluta 	/* To change ODR, accel and magn must be in STDBY */
45220ffac27SDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG,
45320ffac27SDaniel Baluta 			     true);
45420ffac27SDaniel Baluta 	if (ret < 0)
45520ffac27SDaniel Baluta 		return ret;
45620ffac27SDaniel Baluta 
45720ffac27SDaniel Baluta 	odr_bits = 0;
45820ffac27SDaniel Baluta 	if (device & KMX61_ACC)
45920ffac27SDaniel Baluta 		odr_bits |= lodr_bits << KMX61_ACC_ODR_SHIFT;
46020ffac27SDaniel Baluta 	if (device & KMX61_MAG)
46120ffac27SDaniel Baluta 		odr_bits |= lodr_bits << KMX61_MAG_ODR_SHIFT;
46220ffac27SDaniel Baluta 
46320ffac27SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_ODCNTL,
46420ffac27SDaniel Baluta 					odr_bits);
46520ffac27SDaniel Baluta 	if (ret < 0)
46620ffac27SDaniel Baluta 		return ret;
46720ffac27SDaniel Baluta 
4684e843977SDaniel Baluta 	data->odr_bits = odr_bits;
4694e843977SDaniel Baluta 
470fd3ae7a9SDaniel Baluta 	if (device & KMX61_ACC) {
471fd3ae7a9SDaniel Baluta 		ret = kmx61_set_wake_up_odr(data, val, val2);
472fd3ae7a9SDaniel Baluta 		if (ret)
473fd3ae7a9SDaniel Baluta 			return ret;
474fd3ae7a9SDaniel Baluta 	}
475fd3ae7a9SDaniel Baluta 
47620ffac27SDaniel Baluta 	return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true);
47720ffac27SDaniel Baluta }
47820ffac27SDaniel Baluta 
47920ffac27SDaniel Baluta static int kmx61_get_odr(struct kmx61_data *data, int *val, int *val2,
48020ffac27SDaniel Baluta 			 u8 device)
48120ffac27SDaniel Baluta {	int i;
48220ffac27SDaniel Baluta 	u8 lodr_bits;
48320ffac27SDaniel Baluta 
48420ffac27SDaniel Baluta 	if (device & KMX61_ACC)
48520ffac27SDaniel Baluta 		lodr_bits = (data->odr_bits >> KMX61_ACC_ODR_SHIFT) &
48620ffac27SDaniel Baluta 			     KMX61_ACC_ODR_MASK;
48720ffac27SDaniel Baluta 	else if (device & KMX61_MAG)
48820ffac27SDaniel Baluta 		lodr_bits = (data->odr_bits >> KMX61_MAG_ODR_SHIFT) &
48920ffac27SDaniel Baluta 			     KMX61_MAG_ODR_MASK;
49020ffac27SDaniel Baluta 	else
49120ffac27SDaniel Baluta 		return -EINVAL;
49220ffac27SDaniel Baluta 
49320ffac27SDaniel Baluta 	for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++)
49420ffac27SDaniel Baluta 		if (lodr_bits == kmx61_samp_freq_table[i].odr_bits) {
49520ffac27SDaniel Baluta 			*val = kmx61_samp_freq_table[i].val;
49620ffac27SDaniel Baluta 			*val2 = kmx61_samp_freq_table[i].val2;
49720ffac27SDaniel Baluta 			return 0;
49820ffac27SDaniel Baluta 		}
49920ffac27SDaniel Baluta 	return -EINVAL;
50020ffac27SDaniel Baluta }
50120ffac27SDaniel Baluta 
50220ffac27SDaniel Baluta static int kmx61_set_range(struct kmx61_data *data, u8 range)
50320ffac27SDaniel Baluta {
50420ffac27SDaniel Baluta 	int ret;
50520ffac27SDaniel Baluta 
50620ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1);
50720ffac27SDaniel Baluta 	if (ret < 0) {
50820ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
50920ffac27SDaniel Baluta 		return ret;
51020ffac27SDaniel Baluta 	}
51120ffac27SDaniel Baluta 
51220ffac27SDaniel Baluta 	ret &= ~KMX61_REG_CTRL1_GSEL_MASK;
51320ffac27SDaniel Baluta 	ret |= range & KMX61_REG_CTRL1_GSEL_MASK;
51420ffac27SDaniel Baluta 
51520ffac27SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret);
51620ffac27SDaniel Baluta 	if (ret < 0) {
51720ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
51820ffac27SDaniel Baluta 		return ret;
51920ffac27SDaniel Baluta 	}
52020ffac27SDaniel Baluta 
52120ffac27SDaniel Baluta 	data->range = range;
52220ffac27SDaniel Baluta 
52320ffac27SDaniel Baluta 	return 0;
52420ffac27SDaniel Baluta }
52520ffac27SDaniel Baluta 
52620ffac27SDaniel Baluta static int kmx61_set_scale(struct kmx61_data *data, u16 uscale)
52720ffac27SDaniel Baluta {
52820ffac27SDaniel Baluta 	int ret, i;
52920ffac27SDaniel Baluta 	u8  mode;
53020ffac27SDaniel Baluta 
53120ffac27SDaniel Baluta 	for (i = 0; i < ARRAY_SIZE(kmx61_uscale_table); i++) {
53220ffac27SDaniel Baluta 		if (kmx61_uscale_table[i] == uscale) {
53320ffac27SDaniel Baluta 			ret = kmx61_get_mode(data, &mode,
53420ffac27SDaniel Baluta 					     KMX61_ACC | KMX61_MAG);
53520ffac27SDaniel Baluta 			if (ret < 0)
53620ffac27SDaniel Baluta 				return ret;
53720ffac27SDaniel Baluta 
53820ffac27SDaniel Baluta 			ret = kmx61_set_mode(data, KMX61_ALL_STBY,
53920ffac27SDaniel Baluta 					     KMX61_ACC | KMX61_MAG, true);
54020ffac27SDaniel Baluta 			if (ret < 0)
54120ffac27SDaniel Baluta 				return ret;
54220ffac27SDaniel Baluta 
54320ffac27SDaniel Baluta 			ret = kmx61_set_range(data, i);
54420ffac27SDaniel Baluta 			if (ret < 0)
54520ffac27SDaniel Baluta 				return ret;
54620ffac27SDaniel Baluta 
54720ffac27SDaniel Baluta 			return  kmx61_set_mode(data, mode,
54820ffac27SDaniel Baluta 					       KMX61_ACC | KMX61_MAG, true);
54920ffac27SDaniel Baluta 		}
55020ffac27SDaniel Baluta 	}
55120ffac27SDaniel Baluta 	return -EINVAL;
55220ffac27SDaniel Baluta }
55320ffac27SDaniel Baluta 
55420ffac27SDaniel Baluta static int kmx61_chip_init(struct kmx61_data *data)
55520ffac27SDaniel Baluta {
556fd3ae7a9SDaniel Baluta 	int ret, val, val2;
55720ffac27SDaniel Baluta 
55820ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I);
55920ffac27SDaniel Baluta 	if (ret < 0) {
56020ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading who_am_i\n");
56120ffac27SDaniel Baluta 		return ret;
56220ffac27SDaniel Baluta 	}
56320ffac27SDaniel Baluta 
56420ffac27SDaniel Baluta 	if (ret != KMX61_CHIP_ID) {
56520ffac27SDaniel Baluta 		dev_err(&data->client->dev,
56620ffac27SDaniel Baluta 			"Wrong chip id, got %x expected %x\n",
56720ffac27SDaniel Baluta 			 ret, KMX61_CHIP_ID);
56820ffac27SDaniel Baluta 		return -EINVAL;
56920ffac27SDaniel Baluta 	}
57020ffac27SDaniel Baluta 
57120ffac27SDaniel Baluta 	/* set accel 12bit, 4g range */
57220ffac27SDaniel Baluta 	ret = kmx61_set_range(data, KMX61_RANGE_4G);
57320ffac27SDaniel Baluta 	if (ret < 0)
57420ffac27SDaniel Baluta 		return ret;
57520ffac27SDaniel Baluta 
57620ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_ODCNTL);
57720ffac27SDaniel Baluta 	if (ret < 0) {
57820ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_odcntl\n");
57920ffac27SDaniel Baluta 		return ret;
58020ffac27SDaniel Baluta 	}
58120ffac27SDaniel Baluta 	data->odr_bits = ret;
58220ffac27SDaniel Baluta 
583fd3ae7a9SDaniel Baluta 	/* set output data rate for wake up (motion detection) function */
584fd3ae7a9SDaniel Baluta 	ret = kmx61_convert_bit_to_freq(data->odr_bits, &val, &val2);
585fd3ae7a9SDaniel Baluta 	if (ret < 0)
586fd3ae7a9SDaniel Baluta 		return ret;
587fd3ae7a9SDaniel Baluta 
588fd3ae7a9SDaniel Baluta 	ret = kmx61_set_wake_up_odr(data, val, val2);
589fd3ae7a9SDaniel Baluta 	if (ret < 0)
590fd3ae7a9SDaniel Baluta 		return ret;
591fd3ae7a9SDaniel Baluta 
59220ffac27SDaniel Baluta 	/* set acc/magn to OPERATION mode */
59320ffac27SDaniel Baluta 	ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true);
59420ffac27SDaniel Baluta 	if (ret < 0)
59520ffac27SDaniel Baluta 		return ret;
59620ffac27SDaniel Baluta 
597fd3ae7a9SDaniel Baluta 	data->wake_thresh = KMX61_DEFAULT_WAKE_THRESH;
598fd3ae7a9SDaniel Baluta 	data->wake_duration = KMX61_DEFAULT_WAKE_DURATION;
599fd3ae7a9SDaniel Baluta 
60020ffac27SDaniel Baluta 	return 0;
60120ffac27SDaniel Baluta }
60220ffac27SDaniel Baluta 
603c3a23eccSDaniel Baluta static int kmx61_setup_new_data_interrupt(struct kmx61_data *data,
604c3a23eccSDaniel Baluta 					  bool status, u8 device)
605c3a23eccSDaniel Baluta {
606c3a23eccSDaniel Baluta 	u8 mode;
607c3a23eccSDaniel Baluta 	int ret;
608c3a23eccSDaniel Baluta 
609c3a23eccSDaniel Baluta 	ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG);
610c3a23eccSDaniel Baluta 	if (ret < 0)
611c3a23eccSDaniel Baluta 		return ret;
612c3a23eccSDaniel Baluta 
613c3a23eccSDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
614c3a23eccSDaniel Baluta 	if (ret < 0)
615c3a23eccSDaniel Baluta 		return ret;
616c3a23eccSDaniel Baluta 
617c3a23eccSDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INC1);
618c3a23eccSDaniel Baluta 	if (ret < 0) {
619c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
620c3a23eccSDaniel Baluta 		return ret;
621c3a23eccSDaniel Baluta 	}
622c3a23eccSDaniel Baluta 
623c3a23eccSDaniel Baluta 	if (status) {
624c3a23eccSDaniel Baluta 		ret |= KMX61_REG_INC1_BIT_IEN;
625c3a23eccSDaniel Baluta 		if (device & KMX61_ACC)
626c3a23eccSDaniel Baluta 			ret |= KMX61_REG_INC1_BIT_DRDYA;
627c3a23eccSDaniel Baluta 		if (device & KMX61_MAG)
628c3a23eccSDaniel Baluta 			ret |=  KMX61_REG_INC1_BIT_DRDYM;
629c3a23eccSDaniel Baluta 	} else {
630c3a23eccSDaniel Baluta 		ret &= ~KMX61_REG_INC1_BIT_IEN;
631c3a23eccSDaniel Baluta 		if (device & KMX61_ACC)
632c3a23eccSDaniel Baluta 			ret &= ~KMX61_REG_INC1_BIT_DRDYA;
633c3a23eccSDaniel Baluta 		if (device & KMX61_MAG)
634c3a23eccSDaniel Baluta 			ret &= ~KMX61_REG_INC1_BIT_DRDYM;
635c3a23eccSDaniel Baluta 	}
636c3a23eccSDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_INC1, ret);
637c3a23eccSDaniel Baluta 	if (ret < 0) {
638c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
639c3a23eccSDaniel Baluta 		return ret;
640c3a23eccSDaniel Baluta 	}
641c3a23eccSDaniel Baluta 
642c3a23eccSDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1);
643c3a23eccSDaniel Baluta 	if (ret < 0) {
644c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
645c3a23eccSDaniel Baluta 		return ret;
646c3a23eccSDaniel Baluta 	}
647c3a23eccSDaniel Baluta 
648c3a23eccSDaniel Baluta 	if (status)
649c3a23eccSDaniel Baluta 		ret |= KMX61_REG_CTRL1_BIT_DRDYE;
650c3a23eccSDaniel Baluta 	else
651c3a23eccSDaniel Baluta 		ret &= ~KMX61_REG_CTRL1_BIT_DRDYE;
652c3a23eccSDaniel Baluta 
653c3a23eccSDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret);
654c3a23eccSDaniel Baluta 	if (ret < 0) {
655c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
656c3a23eccSDaniel Baluta 		return ret;
657c3a23eccSDaniel Baluta 	}
658c3a23eccSDaniel Baluta 
659c3a23eccSDaniel Baluta 	ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true);
660c3a23eccSDaniel Baluta 	if (ret)
661c3a23eccSDaniel Baluta 		return ret;
662c3a23eccSDaniel Baluta 
663c3a23eccSDaniel Baluta 	return 0;
664c3a23eccSDaniel Baluta }
665c3a23eccSDaniel Baluta 
666fd3ae7a9SDaniel Baluta static int kmx61_chip_update_thresholds(struct kmx61_data *data)
667fd3ae7a9SDaniel Baluta {
668fd3ae7a9SDaniel Baluta 	int ret;
669fd3ae7a9SDaniel Baluta 
670fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client,
671fd3ae7a9SDaniel Baluta 					KMX61_REG_WUF_TIMER,
672fd3ae7a9SDaniel Baluta 					data->wake_duration);
673fd3ae7a9SDaniel Baluta 	if (ret < 0) {
674fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Errow writing reg_wuf_timer\n");
675fd3ae7a9SDaniel Baluta 		return ret;
676fd3ae7a9SDaniel Baluta 	}
677fd3ae7a9SDaniel Baluta 
678fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client,
679fd3ae7a9SDaniel Baluta 					KMX61_REG_WUF_THRESH,
680fd3ae7a9SDaniel Baluta 					data->wake_thresh);
681fd3ae7a9SDaniel Baluta 	if (ret < 0) {
682fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_wuf_thresh\n");
683fd3ae7a9SDaniel Baluta 		return ret;
684fd3ae7a9SDaniel Baluta 	}
685fd3ae7a9SDaniel Baluta 
686fd3ae7a9SDaniel Baluta 	return 0;
687fd3ae7a9SDaniel Baluta }
688fd3ae7a9SDaniel Baluta 
689fd3ae7a9SDaniel Baluta static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data,
690fd3ae7a9SDaniel Baluta 					    bool status, u8 device)
691fd3ae7a9SDaniel Baluta {
692fd3ae7a9SDaniel Baluta 	u8 mode;
693fd3ae7a9SDaniel Baluta 	int ret;
694fd3ae7a9SDaniel Baluta 
695fd3ae7a9SDaniel Baluta 	ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG);
696fd3ae7a9SDaniel Baluta 	if (ret < 0)
697fd3ae7a9SDaniel Baluta 		return ret;
698fd3ae7a9SDaniel Baluta 
699fd3ae7a9SDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
700fd3ae7a9SDaniel Baluta 	if (ret < 0)
701fd3ae7a9SDaniel Baluta 		return ret;
702fd3ae7a9SDaniel Baluta 
703fd3ae7a9SDaniel Baluta 	ret = kmx61_chip_update_thresholds(data);
704fd3ae7a9SDaniel Baluta 	if (ret < 0)
705fd3ae7a9SDaniel Baluta 		return ret;
706fd3ae7a9SDaniel Baluta 
707fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INC1);
708fd3ae7a9SDaniel Baluta 	if (ret < 0) {
709fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_inc1\n");
710fd3ae7a9SDaniel Baluta 		return ret;
711fd3ae7a9SDaniel Baluta 	}
712fd3ae7a9SDaniel Baluta 	if (status)
713fd3ae7a9SDaniel Baluta 		ret |= (KMX61_REG_INC1_BIT_IEN | KMX61_REG_INC1_BIT_WUFS);
714fd3ae7a9SDaniel Baluta 	else
715fd3ae7a9SDaniel Baluta 		ret &= ~(KMX61_REG_INC1_BIT_IEN | KMX61_REG_INC1_BIT_WUFS);
716fd3ae7a9SDaniel Baluta 
717fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_INC1, ret);
718fd3ae7a9SDaniel Baluta 	if (ret < 0) {
719fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_inc1\n");
720fd3ae7a9SDaniel Baluta 		return ret;
721fd3ae7a9SDaniel Baluta 	}
722fd3ae7a9SDaniel Baluta 
723fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1);
724fd3ae7a9SDaniel Baluta 	if (ret < 0) {
725fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
726fd3ae7a9SDaniel Baluta 		return ret;
727fd3ae7a9SDaniel Baluta 	}
728fd3ae7a9SDaniel Baluta 
729fd3ae7a9SDaniel Baluta 	if (status)
730fd3ae7a9SDaniel Baluta 		ret |= KMX61_REG_CTRL1_BIT_WUFE | KMX61_REG_CTRL1_BIT_BTSE;
731fd3ae7a9SDaniel Baluta 	else
732fd3ae7a9SDaniel Baluta 		ret &= ~(KMX61_REG_CTRL1_BIT_WUFE | KMX61_REG_CTRL1_BIT_BTSE);
733fd3ae7a9SDaniel Baluta 
734fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret);
735fd3ae7a9SDaniel Baluta 	if (ret < 0) {
736fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
737fd3ae7a9SDaniel Baluta 		return ret;
738fd3ae7a9SDaniel Baluta 	}
739fd3ae7a9SDaniel Baluta 	mode |= KMX61_ACT_STBY_BIT;
740fd3ae7a9SDaniel Baluta 	ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true);
741fd3ae7a9SDaniel Baluta 	if (ret)
742fd3ae7a9SDaniel Baluta 		return ret;
743fd3ae7a9SDaniel Baluta 
744fd3ae7a9SDaniel Baluta 	return 0;
745fd3ae7a9SDaniel Baluta }
746fd3ae7a9SDaniel Baluta 
747aff8609aSDaniel Baluta /**
748aff8609aSDaniel Baluta  * kmx61_set_power_state() - set power state for kmx61 @device
749aff8609aSDaniel Baluta  * @data - kmx61 device private pointer
750aff8609aSDaniel Baluta  * @on - power state to be set for @device
751aff8609aSDaniel Baluta  * @device - bitmask indicating device for which @on state needs to be set
752aff8609aSDaniel Baluta  *
753aff8609aSDaniel Baluta  * Notice that when ACC power state needs to be set to ON and MAG is in
754aff8609aSDaniel Baluta  * OPERATION then we know that kmx61_runtime_resume was already called
755aff8609aSDaniel Baluta  * so we must set ACC OPERATION mode here. The same happens when MAG power
756aff8609aSDaniel Baluta  * state needs to be set to ON and ACC is in OPERATION.
757aff8609aSDaniel Baluta  */
758aff8609aSDaniel Baluta static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device)
759aff8609aSDaniel Baluta {
760aff8609aSDaniel Baluta #ifdef CONFIG_PM_RUNTIME
761aff8609aSDaniel Baluta 	int ret;
762aff8609aSDaniel Baluta 
763aff8609aSDaniel Baluta 	if (device & KMX61_ACC) {
764aff8609aSDaniel Baluta 		if (on && !data->acc_ps && !data->mag_stby) {
765aff8609aSDaniel Baluta 			ret = kmx61_set_mode(data, 0, KMX61_ACC, true);
766aff8609aSDaniel Baluta 			if (ret < 0)
767aff8609aSDaniel Baluta 				return ret;
768aff8609aSDaniel Baluta 		}
769aff8609aSDaniel Baluta 		data->acc_ps = on;
770aff8609aSDaniel Baluta 	}
771aff8609aSDaniel Baluta 	if (device & KMX61_MAG) {
772aff8609aSDaniel Baluta 		if (on && !data->mag_ps && !data->acc_stby) {
773aff8609aSDaniel Baluta 			ret = kmx61_set_mode(data, 0, KMX61_MAG, true);
774aff8609aSDaniel Baluta 			if (ret < 0)
775aff8609aSDaniel Baluta 				return ret;
776aff8609aSDaniel Baluta 		}
777aff8609aSDaniel Baluta 		data->mag_ps = on;
778aff8609aSDaniel Baluta 	}
779aff8609aSDaniel Baluta 
780aff8609aSDaniel Baluta 	if (on) {
781aff8609aSDaniel Baluta 		ret = pm_runtime_get_sync(&data->client->dev);
782aff8609aSDaniel Baluta 	} else {
783aff8609aSDaniel Baluta 		pm_runtime_mark_last_busy(&data->client->dev);
784aff8609aSDaniel Baluta 		ret = pm_runtime_put_autosuspend(&data->client->dev);
785aff8609aSDaniel Baluta 	}
786aff8609aSDaniel Baluta 	if (ret < 0) {
787aff8609aSDaniel Baluta 		dev_err(&data->client->dev,
788aff8609aSDaniel Baluta 			"Failed: kmx61_set_power_state for %d, ret %d\n",
789aff8609aSDaniel Baluta 			on, ret);
790aff8609aSDaniel Baluta 		if (on)
791aff8609aSDaniel Baluta 			pm_runtime_put_noidle(&data->client->dev);
792aff8609aSDaniel Baluta 
793aff8609aSDaniel Baluta 		return ret;
794aff8609aSDaniel Baluta 	}
795aff8609aSDaniel Baluta #endif
796aff8609aSDaniel Baluta 	return 0;
797aff8609aSDaniel Baluta }
798aff8609aSDaniel Baluta 
79920ffac27SDaniel Baluta static int kmx61_read_measurement(struct kmx61_data *data, u8 base, u8 offset)
80020ffac27SDaniel Baluta {
80120ffac27SDaniel Baluta 	int ret;
80220ffac27SDaniel Baluta 	u8 reg = base + offset * 2;
80320ffac27SDaniel Baluta 
80420ffac27SDaniel Baluta 	ret = i2c_smbus_read_word_data(data->client, reg);
80520ffac27SDaniel Baluta 	if (ret < 0)
80620ffac27SDaniel Baluta 		dev_err(&data->client->dev, "failed to read reg at %x\n", reg);
80720ffac27SDaniel Baluta 
80820ffac27SDaniel Baluta 	return ret;
80920ffac27SDaniel Baluta }
81020ffac27SDaniel Baluta 
81120ffac27SDaniel Baluta static int kmx61_read_raw(struct iio_dev *indio_dev,
81220ffac27SDaniel Baluta 			  struct iio_chan_spec const *chan, int *val,
81320ffac27SDaniel Baluta 			  int *val2, long mask)
81420ffac27SDaniel Baluta {
81520ffac27SDaniel Baluta 	int ret;
81620ffac27SDaniel Baluta 	u8 base_reg;
81720ffac27SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
81820ffac27SDaniel Baluta 
81920ffac27SDaniel Baluta 	switch (mask) {
82020ffac27SDaniel Baluta 	case IIO_CHAN_INFO_RAW:
82120ffac27SDaniel Baluta 		switch (chan->type) {
82220ffac27SDaniel Baluta 		case IIO_ACCEL:
82320ffac27SDaniel Baluta 			base_reg = KMX61_ACC_XOUT_L;
82420ffac27SDaniel Baluta 			break;
82520ffac27SDaniel Baluta 		case IIO_MAGN:
82620ffac27SDaniel Baluta 			base_reg = KMX61_MAG_XOUT_L;
82720ffac27SDaniel Baluta 			break;
82820ffac27SDaniel Baluta 		default:
82920ffac27SDaniel Baluta 			return -EINVAL;
83020ffac27SDaniel Baluta 		}
83120ffac27SDaniel Baluta 		mutex_lock(&data->lock);
83220ffac27SDaniel Baluta 
833*a3da4fa3SDaniel Baluta 		ret = kmx61_set_power_state(data, true, chan->address);
834*a3da4fa3SDaniel Baluta 		if (ret) {
835*a3da4fa3SDaniel Baluta 			mutex_unlock(&data->lock);
836*a3da4fa3SDaniel Baluta 			return ret;
837*a3da4fa3SDaniel Baluta 		}
838*a3da4fa3SDaniel Baluta 
83920ffac27SDaniel Baluta 		ret = kmx61_read_measurement(data, base_reg, chan->scan_index);
84020ffac27SDaniel Baluta 		if (ret < 0) {
841aff8609aSDaniel Baluta 			kmx61_set_power_state(data, false, chan->address);
84220ffac27SDaniel Baluta 			mutex_unlock(&data->lock);
84320ffac27SDaniel Baluta 			return ret;
84420ffac27SDaniel Baluta 		}
84520ffac27SDaniel Baluta 		*val = sign_extend32(ret >> chan->scan_type.shift,
84620ffac27SDaniel Baluta 				     chan->scan_type.realbits - 1);
847*a3da4fa3SDaniel Baluta 		ret = kmx61_set_power_state(data, false, chan->address);
84820ffac27SDaniel Baluta 
84920ffac27SDaniel Baluta 		mutex_unlock(&data->lock);
850*a3da4fa3SDaniel Baluta 		if (ret)
851*a3da4fa3SDaniel Baluta 			return ret;
85220ffac27SDaniel Baluta 		return IIO_VAL_INT;
85320ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SCALE:
85420ffac27SDaniel Baluta 		switch (chan->type) {
85520ffac27SDaniel Baluta 		case IIO_ACCEL:
85620ffac27SDaniel Baluta 			*val = 0;
85720ffac27SDaniel Baluta 			*val2 = kmx61_uscale_table[data->range];
85820ffac27SDaniel Baluta 			return IIO_VAL_INT_PLUS_MICRO;
85920ffac27SDaniel Baluta 		case IIO_MAGN:
86020ffac27SDaniel Baluta 			/* 14 bits res, 1465 microGauss per magn count */
86120ffac27SDaniel Baluta 			*val = 0;
86220ffac27SDaniel Baluta 			*val2 = 1465;
86320ffac27SDaniel Baluta 			return IIO_VAL_INT_PLUS_MICRO;
86420ffac27SDaniel Baluta 		default:
86520ffac27SDaniel Baluta 			return -EINVAL;
86620ffac27SDaniel Baluta 		}
86720ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SAMP_FREQ:
86820ffac27SDaniel Baluta 		if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN)
86920ffac27SDaniel Baluta 			return -EINVAL;
87020ffac27SDaniel Baluta 
87120ffac27SDaniel Baluta 		mutex_lock(&data->lock);
87220ffac27SDaniel Baluta 		ret = kmx61_get_odr(data, val, val2, chan->address);
87320ffac27SDaniel Baluta 		mutex_unlock(&data->lock);
87420ffac27SDaniel Baluta 		if (ret)
87520ffac27SDaniel Baluta 			return -EINVAL;
87620ffac27SDaniel Baluta 		return IIO_VAL_INT_PLUS_MICRO;
87720ffac27SDaniel Baluta 	}
87820ffac27SDaniel Baluta 	return -EINVAL;
87920ffac27SDaniel Baluta }
88020ffac27SDaniel Baluta 
88120ffac27SDaniel Baluta static int kmx61_write_raw(struct iio_dev *indio_dev,
88220ffac27SDaniel Baluta 			   struct iio_chan_spec const *chan, int val,
88320ffac27SDaniel Baluta 			   int val2, long mask)
88420ffac27SDaniel Baluta {
88520ffac27SDaniel Baluta 	int ret;
88620ffac27SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
88720ffac27SDaniel Baluta 
88820ffac27SDaniel Baluta 	switch (mask) {
88920ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SAMP_FREQ:
89020ffac27SDaniel Baluta 		if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN)
89120ffac27SDaniel Baluta 			return -EINVAL;
89220ffac27SDaniel Baluta 
89320ffac27SDaniel Baluta 		mutex_lock(&data->lock);
89420ffac27SDaniel Baluta 		ret = kmx61_set_odr(data, val, val2, chan->address);
89520ffac27SDaniel Baluta 		mutex_unlock(&data->lock);
89620ffac27SDaniel Baluta 		return ret;
89720ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SCALE:
89820ffac27SDaniel Baluta 		switch (chan->type) {
89920ffac27SDaniel Baluta 		case IIO_ACCEL:
90020ffac27SDaniel Baluta 			if (val != 0)
90120ffac27SDaniel Baluta 				return -EINVAL;
90220ffac27SDaniel Baluta 			mutex_lock(&data->lock);
90320ffac27SDaniel Baluta 			ret = kmx61_set_scale(data, val2);
90420ffac27SDaniel Baluta 			mutex_unlock(&data->lock);
90520ffac27SDaniel Baluta 			return ret;
90620ffac27SDaniel Baluta 		default:
90720ffac27SDaniel Baluta 			return -EINVAL;
90820ffac27SDaniel Baluta 		}
90920ffac27SDaniel Baluta 	default:
91020ffac27SDaniel Baluta 		return -EINVAL;
91120ffac27SDaniel Baluta 	}
91220ffac27SDaniel Baluta }
91320ffac27SDaniel Baluta 
914fd3ae7a9SDaniel Baluta static int kmx61_read_event(struct iio_dev *indio_dev,
915fd3ae7a9SDaniel Baluta 			    const struct iio_chan_spec *chan,
916fd3ae7a9SDaniel Baluta 			    enum iio_event_type type,
917fd3ae7a9SDaniel Baluta 			    enum iio_event_direction dir,
918fd3ae7a9SDaniel Baluta 			    enum iio_event_info info,
919fd3ae7a9SDaniel Baluta 			    int *val, int *val2)
920fd3ae7a9SDaniel Baluta {
921fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
922fd3ae7a9SDaniel Baluta 
923fd3ae7a9SDaniel Baluta 	*val2 = 0;
924fd3ae7a9SDaniel Baluta 	switch (info) {
925fd3ae7a9SDaniel Baluta 	case IIO_EV_INFO_VALUE:
926fd3ae7a9SDaniel Baluta 		*val = data->wake_thresh;
927fd3ae7a9SDaniel Baluta 		break;
928fd3ae7a9SDaniel Baluta 	case IIO_EV_INFO_PERIOD:
929fd3ae7a9SDaniel Baluta 		*val = data->wake_duration;
930fd3ae7a9SDaniel Baluta 		break;
931fd3ae7a9SDaniel Baluta 	default:
932fd3ae7a9SDaniel Baluta 		return -EINVAL;
933fd3ae7a9SDaniel Baluta 	}
934fd3ae7a9SDaniel Baluta 
935fd3ae7a9SDaniel Baluta 	return IIO_VAL_INT;
936fd3ae7a9SDaniel Baluta }
937fd3ae7a9SDaniel Baluta 
938fd3ae7a9SDaniel Baluta static int kmx61_write_event(struct iio_dev *indio_dev,
939fd3ae7a9SDaniel Baluta 			    const struct iio_chan_spec *chan,
940fd3ae7a9SDaniel Baluta 			    enum iio_event_type type,
941fd3ae7a9SDaniel Baluta 			    enum iio_event_direction dir,
942fd3ae7a9SDaniel Baluta 			    enum iio_event_info info,
943fd3ae7a9SDaniel Baluta 			    int val, int val2)
944fd3ae7a9SDaniel Baluta {
945fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
946fd3ae7a9SDaniel Baluta 
947fd3ae7a9SDaniel Baluta 	if (data->ev_enable_state)
948fd3ae7a9SDaniel Baluta 		return -EBUSY;
949fd3ae7a9SDaniel Baluta 
950fd3ae7a9SDaniel Baluta 	switch (info) {
951fd3ae7a9SDaniel Baluta 	case IIO_EV_INFO_VALUE:
952fd3ae7a9SDaniel Baluta 		data->wake_thresh = val;
953fd3ae7a9SDaniel Baluta 		break;
954fd3ae7a9SDaniel Baluta 	case IIO_EV_INFO_PERIOD:
955fd3ae7a9SDaniel Baluta 		data->wake_duration = val;
956fd3ae7a9SDaniel Baluta 		break;
957fd3ae7a9SDaniel Baluta 	default:
958fd3ae7a9SDaniel Baluta 		return -EINVAL;
959fd3ae7a9SDaniel Baluta 	}
960fd3ae7a9SDaniel Baluta 
961fd3ae7a9SDaniel Baluta 	return IIO_VAL_INT;
962fd3ae7a9SDaniel Baluta }
963fd3ae7a9SDaniel Baluta 
964fd3ae7a9SDaniel Baluta static int kmx61_read_event_config(struct iio_dev *indio_dev,
965fd3ae7a9SDaniel Baluta 				   const struct iio_chan_spec *chan,
966fd3ae7a9SDaniel Baluta 				   enum iio_event_type type,
967fd3ae7a9SDaniel Baluta 				   enum iio_event_direction dir)
968fd3ae7a9SDaniel Baluta {
969fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
970fd3ae7a9SDaniel Baluta 
971fd3ae7a9SDaniel Baluta 	return data->ev_enable_state;
972fd3ae7a9SDaniel Baluta }
973fd3ae7a9SDaniel Baluta 
974fd3ae7a9SDaniel Baluta static int kmx61_write_event_config(struct iio_dev *indio_dev,
975fd3ae7a9SDaniel Baluta 				   const struct iio_chan_spec *chan,
976fd3ae7a9SDaniel Baluta 				   enum iio_event_type type,
977fd3ae7a9SDaniel Baluta 				   enum iio_event_direction dir,
978fd3ae7a9SDaniel Baluta 				   int state)
979fd3ae7a9SDaniel Baluta {
980fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
981fd3ae7a9SDaniel Baluta 	int ret;
982fd3ae7a9SDaniel Baluta 
983fd3ae7a9SDaniel Baluta 	if (state && data->ev_enable_state)
984fd3ae7a9SDaniel Baluta 		return 0;
985fd3ae7a9SDaniel Baluta 
986fd3ae7a9SDaniel Baluta 	mutex_lock(&data->lock);
987fd3ae7a9SDaniel Baluta 
988fd3ae7a9SDaniel Baluta 	if (!state && data->motion_trig_on) {
989fd3ae7a9SDaniel Baluta 		data->ev_enable_state = 0;
990fd3ae7a9SDaniel Baluta 		mutex_unlock(&data->lock);
991fd3ae7a9SDaniel Baluta 		return 0;
992fd3ae7a9SDaniel Baluta 	}
993fd3ae7a9SDaniel Baluta 
994fd3ae7a9SDaniel Baluta 	ret = kmx61_set_power_state(data, state, KMX61_ACC);
995fd3ae7a9SDaniel Baluta 	if (ret < 0) {
996fd3ae7a9SDaniel Baluta 		mutex_unlock(&data->lock);
997fd3ae7a9SDaniel Baluta 		return ret;
998fd3ae7a9SDaniel Baluta 	}
999fd3ae7a9SDaniel Baluta 
1000fd3ae7a9SDaniel Baluta 	ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC);
1001fd3ae7a9SDaniel Baluta 	if (ret < 0) {
1002fd3ae7a9SDaniel Baluta 		kmx61_set_power_state(data, false, KMX61_ACC);
1003fd3ae7a9SDaniel Baluta 		mutex_unlock(&data->lock);
1004fd3ae7a9SDaniel Baluta 		return ret;
1005fd3ae7a9SDaniel Baluta 	}
1006fd3ae7a9SDaniel Baluta 
1007fd3ae7a9SDaniel Baluta 	data->ev_enable_state = state;
1008fd3ae7a9SDaniel Baluta 	mutex_unlock(&data->lock);
1009fd3ae7a9SDaniel Baluta 
1010fd3ae7a9SDaniel Baluta 	return 0;
1011fd3ae7a9SDaniel Baluta }
1012fd3ae7a9SDaniel Baluta 
1013c3a23eccSDaniel Baluta static int kmx61_acc_validate_trigger(struct iio_dev *indio_dev,
1014c3a23eccSDaniel Baluta 				      struct iio_trigger *trig)
1015c3a23eccSDaniel Baluta {
1016c3a23eccSDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
1017c3a23eccSDaniel Baluta 
1018fd3ae7a9SDaniel Baluta 	if (data->acc_dready_trig != trig && data->motion_trig != trig)
1019c3a23eccSDaniel Baluta 		return -EINVAL;
1020c3a23eccSDaniel Baluta 
1021c3a23eccSDaniel Baluta 	return 0;
1022c3a23eccSDaniel Baluta }
1023c3a23eccSDaniel Baluta 
1024c3a23eccSDaniel Baluta static int kmx61_mag_validate_trigger(struct iio_dev *indio_dev,
1025c3a23eccSDaniel Baluta 				      struct iio_trigger *trig)
1026c3a23eccSDaniel Baluta {
1027c3a23eccSDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
1028c3a23eccSDaniel Baluta 
1029c3a23eccSDaniel Baluta 	if (data->mag_dready_trig != trig)
1030c3a23eccSDaniel Baluta 		return -EINVAL;
1031c3a23eccSDaniel Baluta 
1032c3a23eccSDaniel Baluta 	return 0;
1033c3a23eccSDaniel Baluta }
1034c3a23eccSDaniel Baluta 
103520ffac27SDaniel Baluta static const struct iio_info kmx61_acc_info = {
103620ffac27SDaniel Baluta 	.driver_module		= THIS_MODULE,
103720ffac27SDaniel Baluta 	.read_raw		= kmx61_read_raw,
103820ffac27SDaniel Baluta 	.write_raw		= kmx61_write_raw,
103920ffac27SDaniel Baluta 	.attrs			= &kmx61_acc_attribute_group,
1040fd3ae7a9SDaniel Baluta 	.read_event_value	= kmx61_read_event,
1041fd3ae7a9SDaniel Baluta 	.write_event_value	= kmx61_write_event,
1042fd3ae7a9SDaniel Baluta 	.read_event_config	= kmx61_read_event_config,
1043fd3ae7a9SDaniel Baluta 	.write_event_config	= kmx61_write_event_config,
1044c3a23eccSDaniel Baluta 	.validate_trigger	= kmx61_acc_validate_trigger,
104520ffac27SDaniel Baluta };
104620ffac27SDaniel Baluta 
104720ffac27SDaniel Baluta static const struct iio_info kmx61_mag_info = {
104820ffac27SDaniel Baluta 	.driver_module		= THIS_MODULE,
104920ffac27SDaniel Baluta 	.read_raw		= kmx61_read_raw,
105020ffac27SDaniel Baluta 	.write_raw		= kmx61_write_raw,
105120ffac27SDaniel Baluta 	.attrs			= &kmx61_mag_attribute_group,
1052c3a23eccSDaniel Baluta 	.validate_trigger	= kmx61_mag_validate_trigger,
105320ffac27SDaniel Baluta };
105420ffac27SDaniel Baluta 
1055c3a23eccSDaniel Baluta 
1056c3a23eccSDaniel Baluta static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig,
1057c3a23eccSDaniel Baluta 					    bool state)
1058c3a23eccSDaniel Baluta {
1059c3a23eccSDaniel Baluta 	int ret = 0;
1060c3a23eccSDaniel Baluta 	u8 device;
1061c3a23eccSDaniel Baluta 
1062c3a23eccSDaniel Baluta 	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
1063fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
1064c3a23eccSDaniel Baluta 
1065c3a23eccSDaniel Baluta 	mutex_lock(&data->lock);
1066c3a23eccSDaniel Baluta 
1067fd3ae7a9SDaniel Baluta 	if (!state && data->ev_enable_state && data->motion_trig_on) {
1068fd3ae7a9SDaniel Baluta 		data->motion_trig_on = false;
1069fd3ae7a9SDaniel Baluta 		mutex_unlock(&data->lock);
1070fd3ae7a9SDaniel Baluta 		return 0;
1071fd3ae7a9SDaniel Baluta 	}
1072fd3ae7a9SDaniel Baluta 
1073fd3ae7a9SDaniel Baluta 
1074fd3ae7a9SDaniel Baluta 	if (data->acc_dready_trig == trig || data->motion_trig)
1075c3a23eccSDaniel Baluta 		device = KMX61_ACC;
1076c3a23eccSDaniel Baluta 	else
1077c3a23eccSDaniel Baluta 		device = KMX61_MAG;
1078c3a23eccSDaniel Baluta 
1079c3a23eccSDaniel Baluta 	ret = kmx61_set_power_state(data, state, device);
1080c3a23eccSDaniel Baluta 	if (ret < 0) {
1081c3a23eccSDaniel Baluta 		mutex_unlock(&data->lock);
1082c3a23eccSDaniel Baluta 		return ret;
1083c3a23eccSDaniel Baluta 	}
1084c3a23eccSDaniel Baluta 
1085fd3ae7a9SDaniel Baluta 	if (data->acc_dready_trig == trig || data->mag_dready_trig == trig)
1086c3a23eccSDaniel Baluta 		ret = kmx61_setup_new_data_interrupt(data, state, device);
1087fd3ae7a9SDaniel Baluta 	else
1088fd3ae7a9SDaniel Baluta 		ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC);
1089c3a23eccSDaniel Baluta 	if (ret < 0) {
1090c3a23eccSDaniel Baluta 		kmx61_set_power_state(data, false, device);
1091c3a23eccSDaniel Baluta 		mutex_unlock(&data->lock);
1092c3a23eccSDaniel Baluta 		return ret;
1093c3a23eccSDaniel Baluta 	}
1094c3a23eccSDaniel Baluta 
1095c3a23eccSDaniel Baluta 	if (data->acc_dready_trig == trig)
1096c3a23eccSDaniel Baluta 		data->acc_dready_trig_on = state;
1097fd3ae7a9SDaniel Baluta 	else if (data->mag_dready_trig == trig)
1098c3a23eccSDaniel Baluta 		data->mag_dready_trig_on = state;
1099fd3ae7a9SDaniel Baluta 	else
1100fd3ae7a9SDaniel Baluta 		data->motion_trig_on = state;
1101c3a23eccSDaniel Baluta 
1102c3a23eccSDaniel Baluta 	mutex_unlock(&data->lock);
1103c3a23eccSDaniel Baluta 
1104c3a23eccSDaniel Baluta 	return 0;
1105c3a23eccSDaniel Baluta }
1106c3a23eccSDaniel Baluta 
1107c3a23eccSDaniel Baluta static int kmx61_trig_try_reenable(struct iio_trigger *trig)
1108c3a23eccSDaniel Baluta {
1109c3a23eccSDaniel Baluta 	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
1110c3a23eccSDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
1111c3a23eccSDaniel Baluta 	int ret;
1112c3a23eccSDaniel Baluta 
1113c3a23eccSDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL);
1114c3a23eccSDaniel Baluta 	if (ret < 0) {
1115c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_inl\n");
1116c3a23eccSDaniel Baluta 		return ret;
1117c3a23eccSDaniel Baluta 	}
1118c3a23eccSDaniel Baluta 
1119c3a23eccSDaniel Baluta 	return 0;
1120c3a23eccSDaniel Baluta }
1121c3a23eccSDaniel Baluta 
1122c3a23eccSDaniel Baluta static const struct iio_trigger_ops kmx61_trigger_ops = {
1123c3a23eccSDaniel Baluta 	.set_trigger_state = kmx61_data_rdy_trigger_set_state,
1124c3a23eccSDaniel Baluta 	.try_reenable = kmx61_trig_try_reenable,
1125c3a23eccSDaniel Baluta 	.owner = THIS_MODULE,
1126c3a23eccSDaniel Baluta };
1127c3a23eccSDaniel Baluta 
1128fd3ae7a9SDaniel Baluta static irqreturn_t kmx61_event_handler(int irq, void *private)
1129fd3ae7a9SDaniel Baluta {
1130fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = private;
1131fd3ae7a9SDaniel Baluta 	struct iio_dev *indio_dev = data->acc_indio_dev;
1132fd3ae7a9SDaniel Baluta 	int ret;
1133fd3ae7a9SDaniel Baluta 
1134fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS1);
1135fd3ae7a9SDaniel Baluta 	if (ret < 0) {
1136fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ins1\n");
1137fd3ae7a9SDaniel Baluta 		goto ack_intr;
1138fd3ae7a9SDaniel Baluta 	}
1139fd3ae7a9SDaniel Baluta 
1140fd3ae7a9SDaniel Baluta 	if (ret & KMX61_REG_INS1_BIT_WUFS) {
1141fd3ae7a9SDaniel Baluta 		ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS2);
1142fd3ae7a9SDaniel Baluta 		if (ret < 0) {
1143fd3ae7a9SDaniel Baluta 			dev_err(&data->client->dev, "Error reading reg_ins2\n");
1144fd3ae7a9SDaniel Baluta 			goto ack_intr;
1145fd3ae7a9SDaniel Baluta 		}
1146fd3ae7a9SDaniel Baluta 
1147fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_XN)
1148fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1149fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1150fd3ae7a9SDaniel Baluta 				       0,
1151fd3ae7a9SDaniel Baluta 				       IIO_MOD_X,
1152fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1153fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_FALLING),
1154fd3ae7a9SDaniel Baluta 				       0);
1155fd3ae7a9SDaniel Baluta 
1156fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_XP)
1157fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1158fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1159fd3ae7a9SDaniel Baluta 				       0,
1160fd3ae7a9SDaniel Baluta 				       IIO_MOD_X,
1161fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1162fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_RISING),
1163fd3ae7a9SDaniel Baluta 				       0);
1164fd3ae7a9SDaniel Baluta 
1165fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_YN)
1166fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1167fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1168fd3ae7a9SDaniel Baluta 				       0,
1169fd3ae7a9SDaniel Baluta 				       IIO_MOD_Y,
1170fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1171fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_FALLING),
1172fd3ae7a9SDaniel Baluta 				       0);
1173fd3ae7a9SDaniel Baluta 
1174fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_YP)
1175fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1176fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1177fd3ae7a9SDaniel Baluta 				       0,
1178fd3ae7a9SDaniel Baluta 				       IIO_MOD_Y,
1179fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1180fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_RISING),
1181fd3ae7a9SDaniel Baluta 				       0);
1182fd3ae7a9SDaniel Baluta 
1183fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_ZN)
1184fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1185fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1186fd3ae7a9SDaniel Baluta 				       0,
1187fd3ae7a9SDaniel Baluta 				       IIO_MOD_Z,
1188fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1189fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_FALLING),
1190fd3ae7a9SDaniel Baluta 				       0);
1191fd3ae7a9SDaniel Baluta 
1192fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_ZP)
1193fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1194fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1195fd3ae7a9SDaniel Baluta 				       0,
1196fd3ae7a9SDaniel Baluta 				       IIO_MOD_Z,
1197fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1198fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_RISING),
1199fd3ae7a9SDaniel Baluta 				       0);
1200fd3ae7a9SDaniel Baluta 	}
1201fd3ae7a9SDaniel Baluta 
1202fd3ae7a9SDaniel Baluta ack_intr:
1203fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1);
1204fd3ae7a9SDaniel Baluta 	if (ret < 0)
1205fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
1206fd3ae7a9SDaniel Baluta 
1207fd3ae7a9SDaniel Baluta 	ret |= KMX61_REG_CTRL1_BIT_RES;
1208fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret);
1209fd3ae7a9SDaniel Baluta 	if (ret < 0)
1210fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
1211fd3ae7a9SDaniel Baluta 
1212fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL);
1213fd3ae7a9SDaniel Baluta 	if (ret < 0)
1214fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_inl\n");
1215fd3ae7a9SDaniel Baluta 
1216fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS1);
1217fd3ae7a9SDaniel Baluta 
1218fd3ae7a9SDaniel Baluta 	return IRQ_HANDLED;
1219fd3ae7a9SDaniel Baluta }
1220fd3ae7a9SDaniel Baluta 
1221c3a23eccSDaniel Baluta static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private)
1222c3a23eccSDaniel Baluta {
1223c3a23eccSDaniel Baluta 	struct kmx61_data *data = private;
1224c3a23eccSDaniel Baluta 
1225c3a23eccSDaniel Baluta 	if (data->acc_dready_trig_on)
1226c3a23eccSDaniel Baluta 		iio_trigger_poll(data->acc_dready_trig);
1227c3a23eccSDaniel Baluta 	if (data->mag_dready_trig_on)
1228c3a23eccSDaniel Baluta 		iio_trigger_poll(data->mag_dready_trig);
1229c3a23eccSDaniel Baluta 
1230fd3ae7a9SDaniel Baluta 	if (data->motion_trig_on)
1231fd3ae7a9SDaniel Baluta 		iio_trigger_poll(data->motion_trig);
1232fd3ae7a9SDaniel Baluta 
1233fd3ae7a9SDaniel Baluta 	if (data->ev_enable_state)
1234fd3ae7a9SDaniel Baluta 		return IRQ_WAKE_THREAD;
1235c3a23eccSDaniel Baluta 	return IRQ_HANDLED;
1236c3a23eccSDaniel Baluta }
1237c3a23eccSDaniel Baluta 
1238c3a23eccSDaniel Baluta static irqreturn_t kmx61_trigger_handler(int irq, void *p)
1239c3a23eccSDaniel Baluta {
1240c3a23eccSDaniel Baluta 	struct iio_poll_func *pf = p;
1241c3a23eccSDaniel Baluta 	struct iio_dev *indio_dev = pf->indio_dev;
1242c3a23eccSDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
1243c3a23eccSDaniel Baluta 	int bit, ret, i = 0;
1244c3a23eccSDaniel Baluta 	s16 buffer[8];
1245c3a23eccSDaniel Baluta 
1246c3a23eccSDaniel Baluta 	mutex_lock(&data->lock);
1247c3a23eccSDaniel Baluta 	for_each_set_bit(bit, indio_dev->buffer->scan_mask,
1248c3a23eccSDaniel Baluta 			 indio_dev->masklength) {
1249c3a23eccSDaniel Baluta 		ret = kmx61_read_measurement(data, KMX61_ACC_XOUT_L, bit);
1250c3a23eccSDaniel Baluta 		if (ret < 0) {
1251c3a23eccSDaniel Baluta 			mutex_unlock(&data->lock);
1252c3a23eccSDaniel Baluta 			goto err;
1253c3a23eccSDaniel Baluta 		}
1254c3a23eccSDaniel Baluta 		buffer[i++] = ret;
1255c3a23eccSDaniel Baluta 	}
1256c3a23eccSDaniel Baluta 	mutex_unlock(&data->lock);
1257c3a23eccSDaniel Baluta 
1258c3a23eccSDaniel Baluta 	iio_push_to_buffers(indio_dev, buffer);
1259c3a23eccSDaniel Baluta err:
1260c3a23eccSDaniel Baluta 	iio_trigger_notify_done(indio_dev->trig);
1261c3a23eccSDaniel Baluta 
1262c3a23eccSDaniel Baluta 	return IRQ_HANDLED;
1263c3a23eccSDaniel Baluta }
1264c3a23eccSDaniel Baluta 
1265b25862c5SDaniel Baluta static const char *kmx61_match_acpi_device(struct device *dev)
1266b25862c5SDaniel Baluta {
1267b25862c5SDaniel Baluta 	const struct acpi_device_id *id;
1268b25862c5SDaniel Baluta 
1269b25862c5SDaniel Baluta 	id = acpi_match_device(dev->driver->acpi_match_table, dev);
1270b25862c5SDaniel Baluta 	if (!id)
1271b25862c5SDaniel Baluta 		return NULL;
1272b25862c5SDaniel Baluta 	return dev_name(dev);
1273b25862c5SDaniel Baluta }
1274b25862c5SDaniel Baluta 
1275b25862c5SDaniel Baluta static int kmx61_gpio_probe(struct i2c_client *client, struct kmx61_data *data)
1276b25862c5SDaniel Baluta {
1277b25862c5SDaniel Baluta 	struct device *dev;
1278b25862c5SDaniel Baluta 	struct gpio_desc *gpio;
1279b25862c5SDaniel Baluta 	int ret;
1280b25862c5SDaniel Baluta 
1281b25862c5SDaniel Baluta 	if (!client)
1282b25862c5SDaniel Baluta 		return -EINVAL;
1283b25862c5SDaniel Baluta 
1284b25862c5SDaniel Baluta 	dev = &client->dev;
1285b25862c5SDaniel Baluta 
1286b25862c5SDaniel Baluta 	/* data ready gpio interrupt pin */
1287b25862c5SDaniel Baluta 	gpio = devm_gpiod_get_index(dev, KMX61_GPIO_NAME, 0);
1288b25862c5SDaniel Baluta 	if (IS_ERR(gpio)) {
1289b25862c5SDaniel Baluta 		dev_err(dev, "acpi gpio get index failed\n");
1290b25862c5SDaniel Baluta 		return PTR_ERR(gpio);
1291b25862c5SDaniel Baluta 	}
1292b25862c5SDaniel Baluta 
1293b25862c5SDaniel Baluta 	ret = gpiod_direction_input(gpio);
1294b25862c5SDaniel Baluta 	if (ret)
1295b25862c5SDaniel Baluta 		return ret;
1296b25862c5SDaniel Baluta 
1297b25862c5SDaniel Baluta 	ret = gpiod_to_irq(gpio);
1298b25862c5SDaniel Baluta 
1299b25862c5SDaniel Baluta 	dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
1300b25862c5SDaniel Baluta 	return ret;
1301b25862c5SDaniel Baluta }
1302b25862c5SDaniel Baluta 
130320ffac27SDaniel Baluta static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data,
130420ffac27SDaniel Baluta 					    const struct iio_info *info,
130520ffac27SDaniel Baluta 					    const struct iio_chan_spec *chan,
130620ffac27SDaniel Baluta 					    int num_channels,
130720ffac27SDaniel Baluta 					    const char *name)
130820ffac27SDaniel Baluta {
130920ffac27SDaniel Baluta 	struct iio_dev *indio_dev;
131020ffac27SDaniel Baluta 
131120ffac27SDaniel Baluta 	indio_dev = devm_iio_device_alloc(&data->client->dev, sizeof(data));
131220ffac27SDaniel Baluta 	if (!indio_dev)
131320ffac27SDaniel Baluta 		return ERR_PTR(-ENOMEM);
131420ffac27SDaniel Baluta 
131520ffac27SDaniel Baluta 	kmx61_set_data(indio_dev, data);
131620ffac27SDaniel Baluta 
131720ffac27SDaniel Baluta 	indio_dev->dev.parent = &data->client->dev;
131820ffac27SDaniel Baluta 	indio_dev->channels = chan;
131920ffac27SDaniel Baluta 	indio_dev->num_channels = num_channels;
132020ffac27SDaniel Baluta 	indio_dev->name = name;
132120ffac27SDaniel Baluta 	indio_dev->modes = INDIO_DIRECT_MODE;
132220ffac27SDaniel Baluta 	indio_dev->info = info;
132320ffac27SDaniel Baluta 
132420ffac27SDaniel Baluta 	return indio_dev;
132520ffac27SDaniel Baluta }
132620ffac27SDaniel Baluta 
1327c3a23eccSDaniel Baluta static struct iio_trigger *kmx61_trigger_setup(struct kmx61_data *data,
1328c3a23eccSDaniel Baluta 					       struct iio_dev *indio_dev,
1329c3a23eccSDaniel Baluta 					       const char *tag)
1330c3a23eccSDaniel Baluta {
1331c3a23eccSDaniel Baluta 	struct iio_trigger *trig;
1332c3a23eccSDaniel Baluta 	int ret;
1333c3a23eccSDaniel Baluta 
1334c3a23eccSDaniel Baluta 	trig = devm_iio_trigger_alloc(&data->client->dev,
1335c3a23eccSDaniel Baluta 				      "%s-%s-dev%d",
1336c3a23eccSDaniel Baluta 				      indio_dev->name,
1337c3a23eccSDaniel Baluta 				      tag,
1338c3a23eccSDaniel Baluta 				      indio_dev->id);
1339c3a23eccSDaniel Baluta 	if (!trig)
1340c3a23eccSDaniel Baluta 		return ERR_PTR(-ENOMEM);
1341c3a23eccSDaniel Baluta 
1342c3a23eccSDaniel Baluta 	trig->dev.parent = &data->client->dev;
1343c3a23eccSDaniel Baluta 	trig->ops = &kmx61_trigger_ops;
1344c3a23eccSDaniel Baluta 	iio_trigger_set_drvdata(trig, indio_dev);
1345c3a23eccSDaniel Baluta 
1346c3a23eccSDaniel Baluta 	ret = iio_trigger_register(trig);
1347c3a23eccSDaniel Baluta 	if (ret)
1348c3a23eccSDaniel Baluta 		return ERR_PTR(ret);
1349c3a23eccSDaniel Baluta 
1350c3a23eccSDaniel Baluta 	return trig;
1351c3a23eccSDaniel Baluta }
1352c3a23eccSDaniel Baluta 
135320ffac27SDaniel Baluta static int kmx61_probe(struct i2c_client *client,
135420ffac27SDaniel Baluta 		       const struct i2c_device_id *id)
135520ffac27SDaniel Baluta {
135620ffac27SDaniel Baluta 	int ret;
135720ffac27SDaniel Baluta 	struct kmx61_data *data;
135820ffac27SDaniel Baluta 	const char *name = NULL;
135920ffac27SDaniel Baluta 
136020ffac27SDaniel Baluta 	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
136120ffac27SDaniel Baluta 	if (!data)
136220ffac27SDaniel Baluta 		return -ENOMEM;
136320ffac27SDaniel Baluta 
136420ffac27SDaniel Baluta 	i2c_set_clientdata(client, data);
136520ffac27SDaniel Baluta 	data->client = client;
136620ffac27SDaniel Baluta 
136720ffac27SDaniel Baluta 	mutex_init(&data->lock);
136820ffac27SDaniel Baluta 
1369b25862c5SDaniel Baluta 	if (id)
1370b25862c5SDaniel Baluta 		name = id->name;
1371b25862c5SDaniel Baluta 	else if (ACPI_HANDLE(&client->dev))
1372b25862c5SDaniel Baluta 		name = kmx61_match_acpi_device(&client->dev);
1373b25862c5SDaniel Baluta 	else
1374b25862c5SDaniel Baluta 		return -ENODEV;
1375b25862c5SDaniel Baluta 
137620ffac27SDaniel Baluta 	data->acc_indio_dev =
137720ffac27SDaniel Baluta 		kmx61_indiodev_setup(data, &kmx61_acc_info,
137820ffac27SDaniel Baluta 				     kmx61_acc_channels,
137920ffac27SDaniel Baluta 				     ARRAY_SIZE(kmx61_acc_channels),
138020ffac27SDaniel Baluta 				     name);
138120ffac27SDaniel Baluta 	if (IS_ERR(data->acc_indio_dev))
138220ffac27SDaniel Baluta 		return PTR_ERR(data->acc_indio_dev);
138320ffac27SDaniel Baluta 
138420ffac27SDaniel Baluta 	data->mag_indio_dev =
138520ffac27SDaniel Baluta 		kmx61_indiodev_setup(data, &kmx61_mag_info,
138620ffac27SDaniel Baluta 				     kmx61_mag_channels,
138720ffac27SDaniel Baluta 				     ARRAY_SIZE(kmx61_mag_channels),
138820ffac27SDaniel Baluta 				     name);
138920ffac27SDaniel Baluta 	if (IS_ERR(data->mag_indio_dev))
139020ffac27SDaniel Baluta 		return PTR_ERR(data->mag_indio_dev);
139120ffac27SDaniel Baluta 
139220ffac27SDaniel Baluta 	ret = kmx61_chip_init(data);
139320ffac27SDaniel Baluta 	if (ret < 0)
139420ffac27SDaniel Baluta 		return ret;
139520ffac27SDaniel Baluta 
1396b25862c5SDaniel Baluta 	if (client->irq < 0)
1397b25862c5SDaniel Baluta 		client->irq = kmx61_gpio_probe(client, data);
1398b25862c5SDaniel Baluta 
1399c3a23eccSDaniel Baluta 	if (client->irq >= 0) {
1400c3a23eccSDaniel Baluta 		ret = devm_request_threaded_irq(&client->dev, client->irq,
1401c3a23eccSDaniel Baluta 						kmx61_data_rdy_trig_poll,
1402fd3ae7a9SDaniel Baluta 						kmx61_event_handler,
1403c3a23eccSDaniel Baluta 						IRQF_TRIGGER_RISING,
1404c3a23eccSDaniel Baluta 						KMX61_IRQ_NAME,
1405c3a23eccSDaniel Baluta 						data);
1406c3a23eccSDaniel Baluta 		if (ret)
1407c3a23eccSDaniel Baluta 			goto err_chip_uninit;
1408c3a23eccSDaniel Baluta 
1409c3a23eccSDaniel Baluta 		data->acc_dready_trig =
1410c3a23eccSDaniel Baluta 			kmx61_trigger_setup(data, data->acc_indio_dev,
1411c3a23eccSDaniel Baluta 					    "dready");
1412c3a23eccSDaniel Baluta 		if (IS_ERR(data->acc_dready_trig))
1413c3a23eccSDaniel Baluta 			return PTR_ERR(data->acc_dready_trig);
1414c3a23eccSDaniel Baluta 
1415c3a23eccSDaniel Baluta 		data->mag_dready_trig =
1416c3a23eccSDaniel Baluta 			kmx61_trigger_setup(data, data->mag_indio_dev,
1417c3a23eccSDaniel Baluta 					    "dready");
1418c3a23eccSDaniel Baluta 		if (IS_ERR(data->mag_dready_trig)) {
1419c3a23eccSDaniel Baluta 			ret = PTR_ERR(data->mag_dready_trig);
1420c3a23eccSDaniel Baluta 			goto err_trigger_unregister;
1421c3a23eccSDaniel Baluta 		}
1422c3a23eccSDaniel Baluta 
1423fd3ae7a9SDaniel Baluta 		data->motion_trig =
1424fd3ae7a9SDaniel Baluta 			kmx61_trigger_setup(data, data->acc_indio_dev,
1425fd3ae7a9SDaniel Baluta 					    "any-motion");
1426fd3ae7a9SDaniel Baluta 		if (IS_ERR(data->motion_trig)) {
1427fd3ae7a9SDaniel Baluta 			ret = PTR_ERR(data->motion_trig);
1428fd3ae7a9SDaniel Baluta 			goto err_trigger_unregister;
1429fd3ae7a9SDaniel Baluta 		}
1430fd3ae7a9SDaniel Baluta 
1431c3a23eccSDaniel Baluta 		ret = iio_triggered_buffer_setup(data->acc_indio_dev,
1432c3a23eccSDaniel Baluta 						 &iio_pollfunc_store_time,
1433c3a23eccSDaniel Baluta 						 kmx61_trigger_handler,
1434c3a23eccSDaniel Baluta 						 NULL);
1435c3a23eccSDaniel Baluta 		if (ret < 0) {
1436c3a23eccSDaniel Baluta 			dev_err(&data->client->dev,
1437c3a23eccSDaniel Baluta 				"Failed to setup acc triggered buffer\n");
1438c3a23eccSDaniel Baluta 			goto err_trigger_unregister;
1439c3a23eccSDaniel Baluta 		}
1440c3a23eccSDaniel Baluta 
1441c3a23eccSDaniel Baluta 		ret = iio_triggered_buffer_setup(data->mag_indio_dev,
1442c3a23eccSDaniel Baluta 						 &iio_pollfunc_store_time,
1443c3a23eccSDaniel Baluta 						 kmx61_trigger_handler,
1444c3a23eccSDaniel Baluta 						 NULL);
1445c3a23eccSDaniel Baluta 		if (ret < 0) {
1446c3a23eccSDaniel Baluta 			dev_err(&data->client->dev,
1447c3a23eccSDaniel Baluta 				"Failed to setup mag triggered buffer\n");
1448c3a23eccSDaniel Baluta 			goto err_trigger_unregister;
1449c3a23eccSDaniel Baluta 		}
1450c3a23eccSDaniel Baluta 	}
1451c3a23eccSDaniel Baluta 
145220ffac27SDaniel Baluta 	ret = iio_device_register(data->acc_indio_dev);
145320ffac27SDaniel Baluta 	if (ret < 0) {
145420ffac27SDaniel Baluta 		dev_err(&client->dev, "Failed to register acc iio device\n");
1455c3a23eccSDaniel Baluta 		goto err_buffer_cleanup;
145620ffac27SDaniel Baluta 	}
145720ffac27SDaniel Baluta 
145820ffac27SDaniel Baluta 	ret = iio_device_register(data->mag_indio_dev);
145920ffac27SDaniel Baluta 	if (ret < 0) {
146020ffac27SDaniel Baluta 		dev_err(&client->dev, "Failed to register mag iio device\n");
1461aff8609aSDaniel Baluta 		goto err_iio_unregister_acc;
146220ffac27SDaniel Baluta 	}
146320ffac27SDaniel Baluta 
1464aff8609aSDaniel Baluta 	ret = pm_runtime_set_active(&client->dev);
1465aff8609aSDaniel Baluta 	if (ret < 0)
1466aff8609aSDaniel Baluta 		goto err_iio_unregister_mag;
1467aff8609aSDaniel Baluta 
1468aff8609aSDaniel Baluta 	pm_runtime_enable(&client->dev);
1469aff8609aSDaniel Baluta 	pm_runtime_set_autosuspend_delay(&client->dev, KMX61_SLEEP_DELAY_MS);
1470aff8609aSDaniel Baluta 	pm_runtime_use_autosuspend(&client->dev);
1471aff8609aSDaniel Baluta 
147220ffac27SDaniel Baluta 	return 0;
147320ffac27SDaniel Baluta 
1474aff8609aSDaniel Baluta err_iio_unregister_mag:
1475aff8609aSDaniel Baluta 	iio_device_unregister(data->mag_indio_dev);
1476aff8609aSDaniel Baluta err_iio_unregister_acc:
147720ffac27SDaniel Baluta 	iio_device_unregister(data->acc_indio_dev);
1478c3a23eccSDaniel Baluta err_buffer_cleanup:
1479c3a23eccSDaniel Baluta 	if (client->irq >= 0) {
1480c3a23eccSDaniel Baluta 		iio_triggered_buffer_cleanup(data->acc_indio_dev);
1481c3a23eccSDaniel Baluta 		iio_triggered_buffer_cleanup(data->mag_indio_dev);
1482c3a23eccSDaniel Baluta 	}
1483c3a23eccSDaniel Baluta err_trigger_unregister:
1484c3a23eccSDaniel Baluta 	if (data->acc_dready_trig)
1485c3a23eccSDaniel Baluta 		iio_trigger_unregister(data->acc_dready_trig);
1486c3a23eccSDaniel Baluta 	if (data->mag_dready_trig)
1487c3a23eccSDaniel Baluta 		iio_trigger_unregister(data->mag_dready_trig);
1488fd3ae7a9SDaniel Baluta 	if (data->motion_trig)
1489fd3ae7a9SDaniel Baluta 		iio_trigger_unregister(data->motion_trig);
149020ffac27SDaniel Baluta err_chip_uninit:
149120ffac27SDaniel Baluta 	kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
149220ffac27SDaniel Baluta 	return ret;
149320ffac27SDaniel Baluta }
149420ffac27SDaniel Baluta 
149520ffac27SDaniel Baluta static int kmx61_remove(struct i2c_client *client)
149620ffac27SDaniel Baluta {
149720ffac27SDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(client);
149820ffac27SDaniel Baluta 
1499aff8609aSDaniel Baluta 	pm_runtime_disable(&client->dev);
1500aff8609aSDaniel Baluta 	pm_runtime_set_suspended(&client->dev);
1501aff8609aSDaniel Baluta 	pm_runtime_put_noidle(&client->dev);
1502aff8609aSDaniel Baluta 
150320ffac27SDaniel Baluta 	iio_device_unregister(data->acc_indio_dev);
150420ffac27SDaniel Baluta 	iio_device_unregister(data->mag_indio_dev);
150520ffac27SDaniel Baluta 
1506c3a23eccSDaniel Baluta 	if (client->irq >= 0) {
1507c3a23eccSDaniel Baluta 		iio_triggered_buffer_cleanup(data->acc_indio_dev);
1508c3a23eccSDaniel Baluta 		iio_triggered_buffer_cleanup(data->mag_indio_dev);
1509c3a23eccSDaniel Baluta 		iio_trigger_unregister(data->acc_dready_trig);
1510c3a23eccSDaniel Baluta 		iio_trigger_unregister(data->mag_dready_trig);
1511fd3ae7a9SDaniel Baluta 		iio_trigger_unregister(data->motion_trig);
1512c3a23eccSDaniel Baluta 	}
1513c3a23eccSDaniel Baluta 
151420ffac27SDaniel Baluta 	mutex_lock(&data->lock);
151520ffac27SDaniel Baluta 	kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
151620ffac27SDaniel Baluta 	mutex_unlock(&data->lock);
151720ffac27SDaniel Baluta 
151820ffac27SDaniel Baluta 	return 0;
151920ffac27SDaniel Baluta }
152020ffac27SDaniel Baluta 
15213b9c40e6SDaniel Baluta #ifdef CONFIG_PM_SLEEP
15223b9c40e6SDaniel Baluta static int kmx61_suspend(struct device *dev)
15233b9c40e6SDaniel Baluta {
15243b9c40e6SDaniel Baluta 	int ret;
15253b9c40e6SDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev));
15263b9c40e6SDaniel Baluta 
15273b9c40e6SDaniel Baluta 	mutex_lock(&data->lock);
15283b9c40e6SDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG,
15293b9c40e6SDaniel Baluta 			     false);
15303b9c40e6SDaniel Baluta 	mutex_unlock(&data->lock);
15313b9c40e6SDaniel Baluta 
15323b9c40e6SDaniel Baluta 	return ret;
15333b9c40e6SDaniel Baluta }
15343b9c40e6SDaniel Baluta 
15353b9c40e6SDaniel Baluta static int kmx61_resume(struct device *dev)
15363b9c40e6SDaniel Baluta {
15373b9c40e6SDaniel Baluta 	u8 stby = 0;
15383b9c40e6SDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev));
15393b9c40e6SDaniel Baluta 
15403b9c40e6SDaniel Baluta 	if (data->acc_stby)
15413b9c40e6SDaniel Baluta 		stby |= KMX61_ACC_STBY_BIT;
15423b9c40e6SDaniel Baluta 	if (data->mag_stby)
15433b9c40e6SDaniel Baluta 		stby |= KMX61_MAG_STBY_BIT;
15443b9c40e6SDaniel Baluta 
15453b9c40e6SDaniel Baluta 	return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true);
15463b9c40e6SDaniel Baluta }
15473b9c40e6SDaniel Baluta #endif
1548aff8609aSDaniel Baluta 
1549aff8609aSDaniel Baluta #ifdef CONFIG_PM_RUNTIME
1550aff8609aSDaniel Baluta static int kmx61_runtime_suspend(struct device *dev)
1551aff8609aSDaniel Baluta {
1552aff8609aSDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev));
1553aff8609aSDaniel Baluta 	int ret;
1554aff8609aSDaniel Baluta 
1555aff8609aSDaniel Baluta 	mutex_lock(&data->lock);
1556aff8609aSDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
1557aff8609aSDaniel Baluta 	mutex_unlock(&data->lock);
1558aff8609aSDaniel Baluta 
1559aff8609aSDaniel Baluta 	return ret;
1560aff8609aSDaniel Baluta }
1561aff8609aSDaniel Baluta 
1562aff8609aSDaniel Baluta static int kmx61_runtime_resume(struct device *dev)
1563aff8609aSDaniel Baluta {
1564aff8609aSDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev));
1565aff8609aSDaniel Baluta 	u8 stby = 0;
1566aff8609aSDaniel Baluta 
1567aff8609aSDaniel Baluta 	if (!data->acc_ps)
1568aff8609aSDaniel Baluta 		stby |= KMX61_ACC_STBY_BIT;
1569aff8609aSDaniel Baluta 	if (!data->mag_ps)
1570aff8609aSDaniel Baluta 		stby |= KMX61_MAG_STBY_BIT;
1571aff8609aSDaniel Baluta 
1572aff8609aSDaniel Baluta 	return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true);
1573aff8609aSDaniel Baluta }
1574aff8609aSDaniel Baluta #endif
1575aff8609aSDaniel Baluta 
1576aff8609aSDaniel Baluta static const struct dev_pm_ops kmx61_pm_ops = {
15773b9c40e6SDaniel Baluta 	SET_SYSTEM_SLEEP_PM_OPS(kmx61_suspend, kmx61_resume)
1578aff8609aSDaniel Baluta 	SET_RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL)
1579aff8609aSDaniel Baluta };
1580aff8609aSDaniel Baluta 
1581b25862c5SDaniel Baluta static const struct acpi_device_id kmx61_acpi_match[] = {
1582b25862c5SDaniel Baluta 	{"KMX61021", 0},
1583b25862c5SDaniel Baluta 	{}
1584b25862c5SDaniel Baluta };
1585b25862c5SDaniel Baluta 
1586b25862c5SDaniel Baluta MODULE_DEVICE_TABLE(acpi, kmx61_acpi_match);
1587b25862c5SDaniel Baluta 
158820ffac27SDaniel Baluta static const struct i2c_device_id kmx61_id[] = {
158920ffac27SDaniel Baluta 	{"kmx611021", 0},
159020ffac27SDaniel Baluta 	{}
159120ffac27SDaniel Baluta };
159220ffac27SDaniel Baluta 
159320ffac27SDaniel Baluta MODULE_DEVICE_TABLE(i2c, kmx61_id);
159420ffac27SDaniel Baluta 
159520ffac27SDaniel Baluta static struct i2c_driver kmx61_driver = {
159620ffac27SDaniel Baluta 	.driver = {
159720ffac27SDaniel Baluta 		.name = KMX61_DRV_NAME,
1598b25862c5SDaniel Baluta 		.acpi_match_table = ACPI_PTR(kmx61_acpi_match),
1599aff8609aSDaniel Baluta 		.pm = &kmx61_pm_ops,
160020ffac27SDaniel Baluta 	},
160120ffac27SDaniel Baluta 	.probe		= kmx61_probe,
160220ffac27SDaniel Baluta 	.remove		= kmx61_remove,
160320ffac27SDaniel Baluta 	.id_table	= kmx61_id,
160420ffac27SDaniel Baluta };
160520ffac27SDaniel Baluta 
160620ffac27SDaniel Baluta module_i2c_driver(kmx61_driver);
160720ffac27SDaniel Baluta 
160820ffac27SDaniel Baluta MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
160920ffac27SDaniel Baluta MODULE_DESCRIPTION("KMX61 accelerometer/magnetometer driver");
161020ffac27SDaniel Baluta MODULE_LICENSE("GPL v2");
1611