xref: /openbmc/linux/drivers/iio/imu/kmx61.c (revision 7d0ead5c3f00a0652fa4436f0d2dd05e9f2de140)
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"
30c3a23eccSDaniel Baluta #define KMX61_IRQ_NAME "kmx61_event"
3120ffac27SDaniel Baluta 
3220ffac27SDaniel Baluta #define KMX61_REG_WHO_AM_I	0x00
33fd3ae7a9SDaniel Baluta #define KMX61_REG_INS1		0x01
34fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2		0x02
3520ffac27SDaniel Baluta 
3620ffac27SDaniel Baluta /*
3720ffac27SDaniel Baluta  * three 16-bit accelerometer output registers for X/Y/Z axis
3820ffac27SDaniel Baluta  * we use only XOUT_L as a base register, all other addresses
3920ffac27SDaniel Baluta  * can be obtained by applying an offset and are provided here
4020ffac27SDaniel Baluta  * only for clarity.
4120ffac27SDaniel Baluta  */
4220ffac27SDaniel Baluta #define KMX61_ACC_XOUT_L	0x0A
4320ffac27SDaniel Baluta #define KMX61_ACC_XOUT_H	0x0B
4420ffac27SDaniel Baluta #define KMX61_ACC_YOUT_L	0x0C
4520ffac27SDaniel Baluta #define KMX61_ACC_YOUT_H	0x0D
4620ffac27SDaniel Baluta #define KMX61_ACC_ZOUT_L	0x0E
4720ffac27SDaniel Baluta #define KMX61_ACC_ZOUT_H	0x0F
4820ffac27SDaniel Baluta 
4920ffac27SDaniel Baluta /*
5020ffac27SDaniel Baluta  * one 16-bit temperature output register
5120ffac27SDaniel Baluta  */
5220ffac27SDaniel Baluta #define KMX61_TEMP_L		0x10
5320ffac27SDaniel Baluta #define KMX61_TEMP_H		0x11
5420ffac27SDaniel Baluta 
5520ffac27SDaniel Baluta /*
5620ffac27SDaniel Baluta  * three 16-bit magnetometer output registers for X/Y/Z axis
5720ffac27SDaniel Baluta  */
5820ffac27SDaniel Baluta #define KMX61_MAG_XOUT_L	0x12
5920ffac27SDaniel Baluta #define KMX61_MAG_XOUT_H	0x13
6020ffac27SDaniel Baluta #define KMX61_MAG_YOUT_L	0x14
6120ffac27SDaniel Baluta #define KMX61_MAG_YOUT_H	0x15
6220ffac27SDaniel Baluta #define KMX61_MAG_ZOUT_L	0x16
6320ffac27SDaniel Baluta #define KMX61_MAG_ZOUT_H	0x17
6420ffac27SDaniel Baluta 
65c3a23eccSDaniel Baluta #define KMX61_REG_INL		0x28
6620ffac27SDaniel Baluta #define KMX61_REG_STBY		0x29
6720ffac27SDaniel Baluta #define KMX61_REG_CTRL1		0x2A
68fd3ae7a9SDaniel Baluta #define KMX61_REG_CTRL2		0x2B
6920ffac27SDaniel Baluta #define KMX61_REG_ODCNTL	0x2C
70c3a23eccSDaniel Baluta #define KMX61_REG_INC1		0x2D
7120ffac27SDaniel Baluta 
72fd3ae7a9SDaniel Baluta #define KMX61_REG_WUF_THRESH	0x3D
73fd3ae7a9SDaniel Baluta #define KMX61_REG_WUF_TIMER	0x3E
74fd3ae7a9SDaniel Baluta 
7520ffac27SDaniel Baluta #define KMX61_ACC_STBY_BIT	BIT(0)
7620ffac27SDaniel Baluta #define KMX61_MAG_STBY_BIT	BIT(1)
7720ffac27SDaniel Baluta #define KMX61_ACT_STBY_BIT	BIT(7)
7820ffac27SDaniel Baluta 
7920ffac27SDaniel Baluta #define KMX61_ALL_STBY		(KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT)
8020ffac27SDaniel Baluta 
81fd3ae7a9SDaniel Baluta #define KMX61_REG_INS1_BIT_WUFS		BIT(1)
82fd3ae7a9SDaniel Baluta 
83fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_ZP		BIT(0)
84fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_ZN		BIT(1)
85fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_YP		BIT(2)
86fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_YN		BIT(3)
87fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_XP		BIT(4)
88fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_XN		BIT(5)
89fd3ae7a9SDaniel Baluta 
9020ffac27SDaniel Baluta #define KMX61_REG_CTRL1_GSEL_MASK	0x03
9120ffac27SDaniel Baluta 
92c3a23eccSDaniel Baluta #define KMX61_REG_CTRL1_BIT_RES		BIT(4)
93c3a23eccSDaniel Baluta #define KMX61_REG_CTRL1_BIT_DRDYE	BIT(5)
94fd3ae7a9SDaniel Baluta #define KMX61_REG_CTRL1_BIT_WUFE	BIT(6)
95fd3ae7a9SDaniel Baluta #define KMX61_REG_CTRL1_BIT_BTSE	BIT(7)
96c3a23eccSDaniel Baluta 
97fd3ae7a9SDaniel Baluta #define KMX61_REG_INC1_BIT_WUFS		BIT(0)
98c3a23eccSDaniel Baluta #define KMX61_REG_INC1_BIT_DRDYM	BIT(1)
99c3a23eccSDaniel Baluta #define KMX61_REG_INC1_BIT_DRDYA	BIT(2)
100c3a23eccSDaniel Baluta #define KMX61_REG_INC1_BIT_IEN		BIT(5)
101c3a23eccSDaniel Baluta 
10220ffac27SDaniel Baluta #define KMX61_ACC_ODR_SHIFT	0
10320ffac27SDaniel Baluta #define KMX61_MAG_ODR_SHIFT	4
10420ffac27SDaniel Baluta #define KMX61_ACC_ODR_MASK	0x0F
10520ffac27SDaniel Baluta #define KMX61_MAG_ODR_MASK	0xF0
10620ffac27SDaniel Baluta 
107fd3ae7a9SDaniel Baluta #define KMX61_OWUF_MASK		0x7
108fd3ae7a9SDaniel Baluta 
109fd3ae7a9SDaniel Baluta #define KMX61_DEFAULT_WAKE_THRESH	1
110fd3ae7a9SDaniel Baluta #define KMX61_DEFAULT_WAKE_DURATION	1
111fd3ae7a9SDaniel Baluta 
112aff8609aSDaniel Baluta #define KMX61_SLEEP_DELAY_MS	2000
113aff8609aSDaniel Baluta 
11420ffac27SDaniel Baluta #define KMX61_CHIP_ID		0x12
11520ffac27SDaniel Baluta 
11620ffac27SDaniel Baluta /* KMX61 devices */
11720ffac27SDaniel Baluta #define KMX61_ACC	0x01
11820ffac27SDaniel Baluta #define KMX61_MAG	0x02
11920ffac27SDaniel Baluta 
12020ffac27SDaniel Baluta struct kmx61_data {
12120ffac27SDaniel Baluta 	struct i2c_client *client;
12220ffac27SDaniel Baluta 
12320ffac27SDaniel Baluta 	/* serialize access to non-atomic ops, e.g set_mode */
12420ffac27SDaniel Baluta 	struct mutex lock;
12520ffac27SDaniel Baluta 
12620ffac27SDaniel Baluta 	/* standby state */
12720ffac27SDaniel Baluta 	bool acc_stby;
12820ffac27SDaniel Baluta 	bool mag_stby;
12920ffac27SDaniel Baluta 
130aff8609aSDaniel Baluta 	/* power state */
131aff8609aSDaniel Baluta 	bool acc_ps;
132aff8609aSDaniel Baluta 	bool mag_ps;
133aff8609aSDaniel Baluta 
13420ffac27SDaniel Baluta 	/* config bits */
13520ffac27SDaniel Baluta 	u8 range;
13620ffac27SDaniel Baluta 	u8 odr_bits;
137fd3ae7a9SDaniel Baluta 	u8 wake_thresh;
138fd3ae7a9SDaniel Baluta 	u8 wake_duration;
13920ffac27SDaniel Baluta 
14020ffac27SDaniel Baluta 	/* accelerometer specific data */
14120ffac27SDaniel Baluta 	struct iio_dev *acc_indio_dev;
142c3a23eccSDaniel Baluta 	struct iio_trigger *acc_dready_trig;
143fd3ae7a9SDaniel Baluta 	struct iio_trigger *motion_trig;
144c3a23eccSDaniel Baluta 	bool acc_dready_trig_on;
145fd3ae7a9SDaniel Baluta 	bool motion_trig_on;
146fd3ae7a9SDaniel Baluta 	bool ev_enable_state;
14720ffac27SDaniel Baluta 
14820ffac27SDaniel Baluta 	/* magnetometer specific data */
14920ffac27SDaniel Baluta 	struct iio_dev *mag_indio_dev;
150c3a23eccSDaniel Baluta 	struct iio_trigger *mag_dready_trig;
151c3a23eccSDaniel Baluta 	bool mag_dready_trig_on;
15220ffac27SDaniel Baluta };
15320ffac27SDaniel Baluta 
15420ffac27SDaniel Baluta enum kmx61_range {
15520ffac27SDaniel Baluta 	KMX61_RANGE_2G,
15620ffac27SDaniel Baluta 	KMX61_RANGE_4G,
15720ffac27SDaniel Baluta 	KMX61_RANGE_8G,
15820ffac27SDaniel Baluta };
15920ffac27SDaniel Baluta 
16020ffac27SDaniel Baluta enum kmx61_axis {
16120ffac27SDaniel Baluta 	KMX61_AXIS_X,
16220ffac27SDaniel Baluta 	KMX61_AXIS_Y,
16320ffac27SDaniel Baluta 	KMX61_AXIS_Z,
16420ffac27SDaniel Baluta };
16520ffac27SDaniel Baluta 
16620ffac27SDaniel Baluta static const u16 kmx61_uscale_table[] = {9582, 19163, 38326};
16720ffac27SDaniel Baluta 
16820ffac27SDaniel Baluta static const struct {
16920ffac27SDaniel Baluta 	int val;
17020ffac27SDaniel Baluta 	int val2;
171a36385a2SDaniel Baluta } kmx61_samp_freq_table[] = { {12, 500000},
172a36385a2SDaniel Baluta 			{25, 0},
173a36385a2SDaniel Baluta 			{50, 0},
174a36385a2SDaniel Baluta 			{100, 0},
175a36385a2SDaniel Baluta 			{200, 0},
176a36385a2SDaniel Baluta 			{400, 0},
177a36385a2SDaniel Baluta 			{800, 0},
178a36385a2SDaniel Baluta 			{1600, 0},
179a36385a2SDaniel Baluta 			{0, 781000},
180a36385a2SDaniel Baluta 			{1, 563000},
181a36385a2SDaniel Baluta 			{3, 125000},
182a36385a2SDaniel Baluta 			{6, 250000} };
18320ffac27SDaniel Baluta 
184fd3ae7a9SDaniel Baluta static const struct {
185fd3ae7a9SDaniel Baluta 	int val;
186fd3ae7a9SDaniel Baluta 	int val2;
187fd3ae7a9SDaniel Baluta 	int odr_bits;
188fd3ae7a9SDaniel Baluta } kmx61_wake_up_odr_table[] = { {0, 781000, 0x00},
189fd3ae7a9SDaniel Baluta 				 {1, 563000, 0x01},
190fd3ae7a9SDaniel Baluta 				 {3, 125000, 0x02},
191fd3ae7a9SDaniel Baluta 				 {6, 250000, 0x03},
192fd3ae7a9SDaniel Baluta 				 {12, 500000, 0x04},
193fd3ae7a9SDaniel Baluta 				 {25, 0, 0x05},
194fd3ae7a9SDaniel Baluta 				 {50, 0, 0x06},
195fd3ae7a9SDaniel Baluta 				 {100, 0, 0x06},
196fd3ae7a9SDaniel Baluta 				 {200, 0, 0x06},
197fd3ae7a9SDaniel Baluta 				 {400, 0, 0x06},
198fd3ae7a9SDaniel Baluta 				 {800, 0, 0x06},
199fd3ae7a9SDaniel Baluta 				 {1600, 0, 0x06} };
200fd3ae7a9SDaniel Baluta 
20120ffac27SDaniel Baluta static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326");
20220ffac27SDaniel Baluta static IIO_CONST_ATTR(magn_scale_available, "0.001465");
20320ffac27SDaniel Baluta static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
20420ffac27SDaniel Baluta 	"0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800");
20520ffac27SDaniel Baluta 
20620ffac27SDaniel Baluta static struct attribute *kmx61_acc_attributes[] = {
20720ffac27SDaniel Baluta 	&iio_const_attr_accel_scale_available.dev_attr.attr,
20820ffac27SDaniel Baluta 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
20920ffac27SDaniel Baluta 	NULL,
21020ffac27SDaniel Baluta };
21120ffac27SDaniel Baluta 
21220ffac27SDaniel Baluta static struct attribute *kmx61_mag_attributes[] = {
21320ffac27SDaniel Baluta 	&iio_const_attr_magn_scale_available.dev_attr.attr,
21420ffac27SDaniel Baluta 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
21520ffac27SDaniel Baluta 	NULL,
21620ffac27SDaniel Baluta };
21720ffac27SDaniel Baluta 
21820ffac27SDaniel Baluta static const struct attribute_group kmx61_acc_attribute_group = {
21920ffac27SDaniel Baluta 	.attrs = kmx61_acc_attributes,
22020ffac27SDaniel Baluta };
22120ffac27SDaniel Baluta 
22220ffac27SDaniel Baluta static const struct attribute_group kmx61_mag_attribute_group = {
22320ffac27SDaniel Baluta 	.attrs = kmx61_mag_attributes,
22420ffac27SDaniel Baluta };
22520ffac27SDaniel Baluta 
226fd3ae7a9SDaniel Baluta static const struct iio_event_spec kmx61_event = {
227fd3ae7a9SDaniel Baluta 	.type = IIO_EV_TYPE_THRESH,
228fd3ae7a9SDaniel Baluta 	.dir = IIO_EV_DIR_EITHER,
229fd3ae7a9SDaniel Baluta 	.mask_separate = BIT(IIO_EV_INFO_VALUE) |
230fd3ae7a9SDaniel Baluta 			 BIT(IIO_EV_INFO_ENABLE) |
231fd3ae7a9SDaniel Baluta 			 BIT(IIO_EV_INFO_PERIOD),
232fd3ae7a9SDaniel Baluta };
233fd3ae7a9SDaniel Baluta 
23420ffac27SDaniel Baluta #define KMX61_ACC_CHAN(_axis) { \
23520ffac27SDaniel Baluta 	.type = IIO_ACCEL, \
23620ffac27SDaniel Baluta 	.modified = 1, \
23720ffac27SDaniel Baluta 	.channel2 = IIO_MOD_ ## _axis, \
23820ffac27SDaniel Baluta 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
23920ffac27SDaniel Baluta 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
24020ffac27SDaniel Baluta 				BIT(IIO_CHAN_INFO_SAMP_FREQ), \
24120ffac27SDaniel Baluta 	.address = KMX61_ACC, \
24220ffac27SDaniel Baluta 	.scan_index = KMX61_AXIS_ ## _axis, \
24320ffac27SDaniel Baluta 	.scan_type = { \
24420ffac27SDaniel Baluta 		.sign = 's', \
24520ffac27SDaniel Baluta 		.realbits = 12, \
24620ffac27SDaniel Baluta 		.storagebits = 16, \
24720ffac27SDaniel Baluta 		.shift = 4, \
24820ffac27SDaniel Baluta 		.endianness = IIO_LE, \
24920ffac27SDaniel Baluta 	}, \
250fd3ae7a9SDaniel Baluta 	.event_spec = &kmx61_event, \
251fd3ae7a9SDaniel Baluta 	.num_event_specs = 1 \
25220ffac27SDaniel Baluta }
25320ffac27SDaniel Baluta 
25420ffac27SDaniel Baluta #define KMX61_MAG_CHAN(_axis) { \
25520ffac27SDaniel Baluta 	.type = IIO_MAGN, \
25620ffac27SDaniel Baluta 	.modified = 1, \
25720ffac27SDaniel Baluta 	.channel2 = IIO_MOD_ ## _axis, \
25820ffac27SDaniel Baluta 	.address = KMX61_MAG, \
25920ffac27SDaniel Baluta 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
26020ffac27SDaniel Baluta 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
26120ffac27SDaniel Baluta 				BIT(IIO_CHAN_INFO_SAMP_FREQ), \
26220ffac27SDaniel Baluta 	.scan_index = KMX61_AXIS_ ## _axis, \
26320ffac27SDaniel Baluta 	.scan_type = { \
26420ffac27SDaniel Baluta 		.sign = 's', \
26520ffac27SDaniel Baluta 		.realbits = 14, \
26620ffac27SDaniel Baluta 		.storagebits = 16, \
26720ffac27SDaniel Baluta 		.shift = 2, \
26820ffac27SDaniel Baluta 		.endianness = IIO_LE, \
26920ffac27SDaniel Baluta 	}, \
27020ffac27SDaniel Baluta }
27120ffac27SDaniel Baluta 
27220ffac27SDaniel Baluta static const struct iio_chan_spec kmx61_acc_channels[] = {
27320ffac27SDaniel Baluta 	KMX61_ACC_CHAN(X),
27420ffac27SDaniel Baluta 	KMX61_ACC_CHAN(Y),
27520ffac27SDaniel Baluta 	KMX61_ACC_CHAN(Z),
27620ffac27SDaniel Baluta };
27720ffac27SDaniel Baluta 
27820ffac27SDaniel Baluta static const struct iio_chan_spec kmx61_mag_channels[] = {
27920ffac27SDaniel Baluta 	KMX61_MAG_CHAN(X),
28020ffac27SDaniel Baluta 	KMX61_MAG_CHAN(Y),
28120ffac27SDaniel Baluta 	KMX61_MAG_CHAN(Z),
28220ffac27SDaniel Baluta };
28320ffac27SDaniel Baluta 
28420ffac27SDaniel Baluta static void kmx61_set_data(struct iio_dev *indio_dev, struct kmx61_data *data)
28520ffac27SDaniel Baluta {
28620ffac27SDaniel Baluta 	struct kmx61_data **priv = iio_priv(indio_dev);
28720ffac27SDaniel Baluta 
28820ffac27SDaniel Baluta 	*priv = data;
28920ffac27SDaniel Baluta }
29020ffac27SDaniel Baluta 
29120ffac27SDaniel Baluta static struct kmx61_data *kmx61_get_data(struct iio_dev *indio_dev)
29220ffac27SDaniel Baluta {
29320ffac27SDaniel Baluta 	return *(struct kmx61_data **)iio_priv(indio_dev);
29420ffac27SDaniel Baluta }
29520ffac27SDaniel Baluta 
29620ffac27SDaniel Baluta static int kmx61_convert_freq_to_bit(int val, int val2)
29720ffac27SDaniel Baluta {
29820ffac27SDaniel Baluta 	int i;
29920ffac27SDaniel Baluta 
30020ffac27SDaniel Baluta 	for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++)
30120ffac27SDaniel Baluta 		if (val == kmx61_samp_freq_table[i].val &&
30220ffac27SDaniel Baluta 		    val2 == kmx61_samp_freq_table[i].val2)
303a36385a2SDaniel Baluta 			return i;
30420ffac27SDaniel Baluta 	return -EINVAL;
30520ffac27SDaniel Baluta }
30620ffac27SDaniel Baluta 
307fd3ae7a9SDaniel Baluta static int kmx61_convert_wake_up_odr_to_bit(int val, int val2)
308fd3ae7a9SDaniel Baluta {
309fd3ae7a9SDaniel Baluta 	int i;
310fd3ae7a9SDaniel Baluta 
311fd3ae7a9SDaniel Baluta 	for (i = 0; i < ARRAY_SIZE(kmx61_wake_up_odr_table); ++i)
312fd3ae7a9SDaniel Baluta 		if (kmx61_wake_up_odr_table[i].val == val &&
313fd3ae7a9SDaniel Baluta 			kmx61_wake_up_odr_table[i].val2 == val2)
314fd3ae7a9SDaniel Baluta 				return kmx61_wake_up_odr_table[i].odr_bits;
315fd3ae7a9SDaniel Baluta 	return -EINVAL;
316fd3ae7a9SDaniel Baluta }
317fd3ae7a9SDaniel Baluta 
31820ffac27SDaniel Baluta /**
31920ffac27SDaniel Baluta  * kmx61_set_mode() - set KMX61 device operating mode
32020ffac27SDaniel Baluta  * @data - kmx61 device private data pointer
32120ffac27SDaniel Baluta  * @mode - bitmask, indicating operating mode for @device
32220ffac27SDaniel Baluta  * @device - bitmask, indicating device for which @mode needs to be set
32320ffac27SDaniel Baluta  * @update - update stby bits stored in device's private  @data
32420ffac27SDaniel Baluta  *
32520ffac27SDaniel Baluta  * For each sensor (accelerometer/magnetometer) there are two operating modes
32620ffac27SDaniel Baluta  * STANDBY and OPERATION. Neither accel nor magn can be disabled independently
32720ffac27SDaniel Baluta  * if they are both enabled. Internal sensors state is saved in acc_stby and
32820ffac27SDaniel Baluta  * mag_stby members of driver's private @data.
32920ffac27SDaniel Baluta  */
33020ffac27SDaniel Baluta static int kmx61_set_mode(struct kmx61_data *data, u8 mode, u8 device,
33120ffac27SDaniel Baluta 			  bool update)
33220ffac27SDaniel Baluta {
33320ffac27SDaniel Baluta 	int ret;
33420ffac27SDaniel Baluta 	int acc_stby = -1, mag_stby = -1;
33520ffac27SDaniel Baluta 
33620ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY);
33720ffac27SDaniel Baluta 	if (ret < 0) {
33820ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_stby\n");
33920ffac27SDaniel Baluta 		return ret;
34020ffac27SDaniel Baluta 	}
34120ffac27SDaniel Baluta 	if (device & KMX61_ACC) {
34220ffac27SDaniel Baluta 		if (mode & KMX61_ACC_STBY_BIT) {
34320ffac27SDaniel Baluta 			ret |= KMX61_ACC_STBY_BIT;
34420ffac27SDaniel Baluta 			acc_stby = 1;
34520ffac27SDaniel Baluta 		} else {
34620ffac27SDaniel Baluta 			ret &= ~KMX61_ACC_STBY_BIT;
34720ffac27SDaniel Baluta 			acc_stby = 0;
34820ffac27SDaniel Baluta 		}
34920ffac27SDaniel Baluta 	}
35020ffac27SDaniel Baluta 
35120ffac27SDaniel Baluta 	if (device & KMX61_MAG) {
35220ffac27SDaniel Baluta 		if (mode & KMX61_MAG_STBY_BIT) {
35320ffac27SDaniel Baluta 			ret |= KMX61_MAG_STBY_BIT;
35420ffac27SDaniel Baluta 			mag_stby = 1;
35520ffac27SDaniel Baluta 		} else {
35620ffac27SDaniel Baluta 			ret &= ~KMX61_MAG_STBY_BIT;
35720ffac27SDaniel Baluta 			mag_stby = 0;
35820ffac27SDaniel Baluta 		}
35920ffac27SDaniel Baluta 	}
36020ffac27SDaniel Baluta 
36120ffac27SDaniel Baluta 	if (mode & KMX61_ACT_STBY_BIT)
36220ffac27SDaniel Baluta 		ret |= KMX61_ACT_STBY_BIT;
36320ffac27SDaniel Baluta 
36420ffac27SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_STBY, ret);
36520ffac27SDaniel Baluta 	if (ret < 0) {
36620ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_stby\n");
36720ffac27SDaniel Baluta 		return ret;
36820ffac27SDaniel Baluta 	}
36920ffac27SDaniel Baluta 
37020ffac27SDaniel Baluta 	if (acc_stby != -1 && update)
37120ffac27SDaniel Baluta 		data->acc_stby = acc_stby;
37220ffac27SDaniel Baluta 	if (mag_stby != -1 && update)
37320ffac27SDaniel Baluta 		data->mag_stby = mag_stby;
37420ffac27SDaniel Baluta 
37520ffac27SDaniel Baluta 	return 0;
37620ffac27SDaniel Baluta }
37720ffac27SDaniel Baluta 
37820ffac27SDaniel Baluta static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device)
37920ffac27SDaniel Baluta {
38020ffac27SDaniel Baluta 	int ret;
38120ffac27SDaniel Baluta 
38220ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY);
38320ffac27SDaniel Baluta 	if (ret < 0) {
38420ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_stby\n");
38520ffac27SDaniel Baluta 		return ret;
38620ffac27SDaniel Baluta 	}
38720ffac27SDaniel Baluta 	*mode = 0;
38820ffac27SDaniel Baluta 
38920ffac27SDaniel Baluta 	if (device & KMX61_ACC) {
39020ffac27SDaniel Baluta 		if (ret & KMX61_ACC_STBY_BIT)
39120ffac27SDaniel Baluta 			*mode |= KMX61_ACC_STBY_BIT;
39220ffac27SDaniel Baluta 		else
39320ffac27SDaniel Baluta 			*mode &= ~KMX61_ACC_STBY_BIT;
39420ffac27SDaniel Baluta 	}
39520ffac27SDaniel Baluta 
39620ffac27SDaniel Baluta 	if (device & KMX61_MAG) {
39720ffac27SDaniel Baluta 		if (ret & KMX61_MAG_STBY_BIT)
39820ffac27SDaniel Baluta 			*mode |= KMX61_MAG_STBY_BIT;
39920ffac27SDaniel Baluta 		else
40020ffac27SDaniel Baluta 			*mode &= ~KMX61_MAG_STBY_BIT;
40120ffac27SDaniel Baluta 	}
40220ffac27SDaniel Baluta 
40320ffac27SDaniel Baluta 	return 0;
40420ffac27SDaniel Baluta }
40520ffac27SDaniel Baluta 
406ebd16366Skbuild test robot static int kmx61_set_wake_up_odr(struct kmx61_data *data, int val, int val2)
407fd3ae7a9SDaniel Baluta {
408fd3ae7a9SDaniel Baluta 	int ret, odr_bits;
409fd3ae7a9SDaniel Baluta 
410fd3ae7a9SDaniel Baluta 	odr_bits = kmx61_convert_wake_up_odr_to_bit(val, val2);
411fd3ae7a9SDaniel Baluta 	if (odr_bits < 0)
412fd3ae7a9SDaniel Baluta 		return odr_bits;
413fd3ae7a9SDaniel Baluta 
414fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL2,
415fd3ae7a9SDaniel Baluta 					odr_bits);
416fd3ae7a9SDaniel Baluta 	if (ret < 0)
417fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl2\n");
418fd3ae7a9SDaniel Baluta 	return ret;
419fd3ae7a9SDaniel Baluta }
420fd3ae7a9SDaniel Baluta 
42120ffac27SDaniel Baluta static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device)
42220ffac27SDaniel Baluta {
42320ffac27SDaniel Baluta 	int ret;
42420ffac27SDaniel Baluta 	u8 mode;
42520ffac27SDaniel Baluta 	int lodr_bits, odr_bits;
42620ffac27SDaniel Baluta 
42720ffac27SDaniel Baluta 	ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG);
42820ffac27SDaniel Baluta 	if (ret < 0)
42920ffac27SDaniel Baluta 		return ret;
43020ffac27SDaniel Baluta 
43120ffac27SDaniel Baluta 	lodr_bits = kmx61_convert_freq_to_bit(val, val2);
43220ffac27SDaniel Baluta 	if (lodr_bits < 0)
43320ffac27SDaniel Baluta 		return lodr_bits;
43420ffac27SDaniel Baluta 
43520ffac27SDaniel Baluta 	/* To change ODR, accel and magn must be in STDBY */
43620ffac27SDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG,
43720ffac27SDaniel Baluta 			     true);
43820ffac27SDaniel Baluta 	if (ret < 0)
43920ffac27SDaniel Baluta 		return ret;
44020ffac27SDaniel Baluta 
44120ffac27SDaniel Baluta 	odr_bits = 0;
44220ffac27SDaniel Baluta 	if (device & KMX61_ACC)
44320ffac27SDaniel Baluta 		odr_bits |= lodr_bits << KMX61_ACC_ODR_SHIFT;
44420ffac27SDaniel Baluta 	if (device & KMX61_MAG)
44520ffac27SDaniel Baluta 		odr_bits |= lodr_bits << KMX61_MAG_ODR_SHIFT;
44620ffac27SDaniel Baluta 
44720ffac27SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_ODCNTL,
44820ffac27SDaniel Baluta 					odr_bits);
44920ffac27SDaniel Baluta 	if (ret < 0)
45020ffac27SDaniel Baluta 		return ret;
45120ffac27SDaniel Baluta 
4524e843977SDaniel Baluta 	data->odr_bits = odr_bits;
4534e843977SDaniel Baluta 
454fd3ae7a9SDaniel Baluta 	if (device & KMX61_ACC) {
455fd3ae7a9SDaniel Baluta 		ret = kmx61_set_wake_up_odr(data, val, val2);
456fd3ae7a9SDaniel Baluta 		if (ret)
457fd3ae7a9SDaniel Baluta 			return ret;
458fd3ae7a9SDaniel Baluta 	}
459fd3ae7a9SDaniel Baluta 
46020ffac27SDaniel Baluta 	return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true);
46120ffac27SDaniel Baluta }
46220ffac27SDaniel Baluta 
46320ffac27SDaniel Baluta static int kmx61_get_odr(struct kmx61_data *data, int *val, int *val2,
46420ffac27SDaniel Baluta 			 u8 device)
465a36385a2SDaniel Baluta {
46620ffac27SDaniel Baluta 	u8 lodr_bits;
46720ffac27SDaniel Baluta 
46820ffac27SDaniel Baluta 	if (device & KMX61_ACC)
46920ffac27SDaniel Baluta 		lodr_bits = (data->odr_bits >> KMX61_ACC_ODR_SHIFT) &
47020ffac27SDaniel Baluta 			     KMX61_ACC_ODR_MASK;
47120ffac27SDaniel Baluta 	else if (device & KMX61_MAG)
47220ffac27SDaniel Baluta 		lodr_bits = (data->odr_bits >> KMX61_MAG_ODR_SHIFT) &
47320ffac27SDaniel Baluta 			     KMX61_MAG_ODR_MASK;
47420ffac27SDaniel Baluta 	else
47520ffac27SDaniel Baluta 		return -EINVAL;
47620ffac27SDaniel Baluta 
477a36385a2SDaniel Baluta 	if (lodr_bits >= ARRAY_SIZE(kmx61_samp_freq_table))
47820ffac27SDaniel Baluta 		return -EINVAL;
479a36385a2SDaniel Baluta 
480a36385a2SDaniel Baluta 	*val = kmx61_samp_freq_table[lodr_bits].val;
481a36385a2SDaniel Baluta 	*val2 = kmx61_samp_freq_table[lodr_bits].val2;
482a36385a2SDaniel Baluta 
483a36385a2SDaniel Baluta 	return 0;
48420ffac27SDaniel Baluta }
48520ffac27SDaniel Baluta 
48620ffac27SDaniel Baluta static int kmx61_set_range(struct kmx61_data *data, u8 range)
48720ffac27SDaniel Baluta {
48820ffac27SDaniel Baluta 	int ret;
48920ffac27SDaniel Baluta 
49020ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1);
49120ffac27SDaniel Baluta 	if (ret < 0) {
49220ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
49320ffac27SDaniel Baluta 		return ret;
49420ffac27SDaniel Baluta 	}
49520ffac27SDaniel Baluta 
49620ffac27SDaniel Baluta 	ret &= ~KMX61_REG_CTRL1_GSEL_MASK;
49720ffac27SDaniel Baluta 	ret |= range & KMX61_REG_CTRL1_GSEL_MASK;
49820ffac27SDaniel Baluta 
49920ffac27SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret);
50020ffac27SDaniel Baluta 	if (ret < 0) {
50120ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
50220ffac27SDaniel Baluta 		return ret;
50320ffac27SDaniel Baluta 	}
50420ffac27SDaniel Baluta 
50520ffac27SDaniel Baluta 	data->range = range;
50620ffac27SDaniel Baluta 
50720ffac27SDaniel Baluta 	return 0;
50820ffac27SDaniel Baluta }
50920ffac27SDaniel Baluta 
51020ffac27SDaniel Baluta static int kmx61_set_scale(struct kmx61_data *data, u16 uscale)
51120ffac27SDaniel Baluta {
51220ffac27SDaniel Baluta 	int ret, i;
51320ffac27SDaniel Baluta 	u8  mode;
51420ffac27SDaniel Baluta 
51520ffac27SDaniel Baluta 	for (i = 0; i < ARRAY_SIZE(kmx61_uscale_table); i++) {
51620ffac27SDaniel Baluta 		if (kmx61_uscale_table[i] == uscale) {
51720ffac27SDaniel Baluta 			ret = kmx61_get_mode(data, &mode,
51820ffac27SDaniel Baluta 					     KMX61_ACC | KMX61_MAG);
51920ffac27SDaniel Baluta 			if (ret < 0)
52020ffac27SDaniel Baluta 				return ret;
52120ffac27SDaniel Baluta 
52220ffac27SDaniel Baluta 			ret = kmx61_set_mode(data, KMX61_ALL_STBY,
52320ffac27SDaniel Baluta 					     KMX61_ACC | KMX61_MAG, true);
52420ffac27SDaniel Baluta 			if (ret < 0)
52520ffac27SDaniel Baluta 				return ret;
52620ffac27SDaniel Baluta 
52720ffac27SDaniel Baluta 			ret = kmx61_set_range(data, i);
52820ffac27SDaniel Baluta 			if (ret < 0)
52920ffac27SDaniel Baluta 				return ret;
53020ffac27SDaniel Baluta 
53120ffac27SDaniel Baluta 			return  kmx61_set_mode(data, mode,
53220ffac27SDaniel Baluta 					       KMX61_ACC | KMX61_MAG, true);
53320ffac27SDaniel Baluta 		}
53420ffac27SDaniel Baluta 	}
53520ffac27SDaniel Baluta 	return -EINVAL;
53620ffac27SDaniel Baluta }
53720ffac27SDaniel Baluta 
53820ffac27SDaniel Baluta static int kmx61_chip_init(struct kmx61_data *data)
53920ffac27SDaniel Baluta {
540fd3ae7a9SDaniel Baluta 	int ret, val, val2;
54120ffac27SDaniel Baluta 
54220ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I);
54320ffac27SDaniel Baluta 	if (ret < 0) {
54420ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading who_am_i\n");
54520ffac27SDaniel Baluta 		return ret;
54620ffac27SDaniel Baluta 	}
54720ffac27SDaniel Baluta 
54820ffac27SDaniel Baluta 	if (ret != KMX61_CHIP_ID) {
54920ffac27SDaniel Baluta 		dev_err(&data->client->dev,
55020ffac27SDaniel Baluta 			"Wrong chip id, got %x expected %x\n",
55120ffac27SDaniel Baluta 			 ret, KMX61_CHIP_ID);
55220ffac27SDaniel Baluta 		return -EINVAL;
55320ffac27SDaniel Baluta 	}
55420ffac27SDaniel Baluta 
55520ffac27SDaniel Baluta 	/* set accel 12bit, 4g range */
55620ffac27SDaniel Baluta 	ret = kmx61_set_range(data, KMX61_RANGE_4G);
55720ffac27SDaniel Baluta 	if (ret < 0)
55820ffac27SDaniel Baluta 		return ret;
55920ffac27SDaniel Baluta 
56020ffac27SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_ODCNTL);
56120ffac27SDaniel Baluta 	if (ret < 0) {
56220ffac27SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_odcntl\n");
56320ffac27SDaniel Baluta 		return ret;
56420ffac27SDaniel Baluta 	}
56520ffac27SDaniel Baluta 	data->odr_bits = ret;
56620ffac27SDaniel Baluta 
567a36385a2SDaniel Baluta 	/*
568a36385a2SDaniel Baluta 	 * set output data rate for wake up (motion detection) function
569a36385a2SDaniel Baluta 	 * to match data rate for accelerometer sampling
570a36385a2SDaniel Baluta 	 */
571a36385a2SDaniel Baluta 	ret = kmx61_get_odr(data, &val, &val2, KMX61_ACC);
572fd3ae7a9SDaniel Baluta 	if (ret < 0)
573fd3ae7a9SDaniel Baluta 		return ret;
574fd3ae7a9SDaniel Baluta 
575fd3ae7a9SDaniel Baluta 	ret = kmx61_set_wake_up_odr(data, val, val2);
576fd3ae7a9SDaniel Baluta 	if (ret < 0)
577fd3ae7a9SDaniel Baluta 		return ret;
578fd3ae7a9SDaniel Baluta 
57920ffac27SDaniel Baluta 	/* set acc/magn to OPERATION mode */
58020ffac27SDaniel Baluta 	ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true);
58120ffac27SDaniel Baluta 	if (ret < 0)
58220ffac27SDaniel Baluta 		return ret;
58320ffac27SDaniel Baluta 
584fd3ae7a9SDaniel Baluta 	data->wake_thresh = KMX61_DEFAULT_WAKE_THRESH;
585fd3ae7a9SDaniel Baluta 	data->wake_duration = KMX61_DEFAULT_WAKE_DURATION;
586fd3ae7a9SDaniel Baluta 
58720ffac27SDaniel Baluta 	return 0;
58820ffac27SDaniel Baluta }
58920ffac27SDaniel Baluta 
590c3a23eccSDaniel Baluta static int kmx61_setup_new_data_interrupt(struct kmx61_data *data,
591c3a23eccSDaniel Baluta 					  bool status, u8 device)
592c3a23eccSDaniel Baluta {
593c3a23eccSDaniel Baluta 	u8 mode;
594c3a23eccSDaniel Baluta 	int ret;
595c3a23eccSDaniel Baluta 
596c3a23eccSDaniel Baluta 	ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG);
597c3a23eccSDaniel Baluta 	if (ret < 0)
598c3a23eccSDaniel Baluta 		return ret;
599c3a23eccSDaniel Baluta 
600c3a23eccSDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
601c3a23eccSDaniel Baluta 	if (ret < 0)
602c3a23eccSDaniel Baluta 		return ret;
603c3a23eccSDaniel Baluta 
604c3a23eccSDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INC1);
605c3a23eccSDaniel Baluta 	if (ret < 0) {
606c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
607c3a23eccSDaniel Baluta 		return ret;
608c3a23eccSDaniel Baluta 	}
609c3a23eccSDaniel Baluta 
610c3a23eccSDaniel Baluta 	if (status) {
611c3a23eccSDaniel Baluta 		ret |= KMX61_REG_INC1_BIT_IEN;
612c3a23eccSDaniel Baluta 		if (device & KMX61_ACC)
613c3a23eccSDaniel Baluta 			ret |= KMX61_REG_INC1_BIT_DRDYA;
614c3a23eccSDaniel Baluta 		if (device & KMX61_MAG)
615c3a23eccSDaniel Baluta 			ret |=  KMX61_REG_INC1_BIT_DRDYM;
616c3a23eccSDaniel Baluta 	} else {
617c3a23eccSDaniel Baluta 		ret &= ~KMX61_REG_INC1_BIT_IEN;
618c3a23eccSDaniel Baluta 		if (device & KMX61_ACC)
619c3a23eccSDaniel Baluta 			ret &= ~KMX61_REG_INC1_BIT_DRDYA;
620c3a23eccSDaniel Baluta 		if (device & KMX61_MAG)
621c3a23eccSDaniel Baluta 			ret &= ~KMX61_REG_INC1_BIT_DRDYM;
622c3a23eccSDaniel Baluta 	}
623c3a23eccSDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_INC1, ret);
624c3a23eccSDaniel Baluta 	if (ret < 0) {
625c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
626c3a23eccSDaniel Baluta 		return ret;
627c3a23eccSDaniel Baluta 	}
628c3a23eccSDaniel Baluta 
629c3a23eccSDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1);
630c3a23eccSDaniel Baluta 	if (ret < 0) {
631c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
632c3a23eccSDaniel Baluta 		return ret;
633c3a23eccSDaniel Baluta 	}
634c3a23eccSDaniel Baluta 
635c3a23eccSDaniel Baluta 	if (status)
636c3a23eccSDaniel Baluta 		ret |= KMX61_REG_CTRL1_BIT_DRDYE;
637c3a23eccSDaniel Baluta 	else
638c3a23eccSDaniel Baluta 		ret &= ~KMX61_REG_CTRL1_BIT_DRDYE;
639c3a23eccSDaniel Baluta 
640c3a23eccSDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret);
641c3a23eccSDaniel Baluta 	if (ret < 0) {
642c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
643c3a23eccSDaniel Baluta 		return ret;
644c3a23eccSDaniel Baluta 	}
645c3a23eccSDaniel Baluta 
64628ff344eSDaniel Baluta 	return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true);
647c3a23eccSDaniel Baluta }
648c3a23eccSDaniel Baluta 
649fd3ae7a9SDaniel Baluta static int kmx61_chip_update_thresholds(struct kmx61_data *data)
650fd3ae7a9SDaniel Baluta {
651fd3ae7a9SDaniel Baluta 	int ret;
652fd3ae7a9SDaniel Baluta 
653fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client,
654fd3ae7a9SDaniel Baluta 					KMX61_REG_WUF_TIMER,
655fd3ae7a9SDaniel Baluta 					data->wake_duration);
656fd3ae7a9SDaniel Baluta 	if (ret < 0) {
657fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Errow writing reg_wuf_timer\n");
658fd3ae7a9SDaniel Baluta 		return ret;
659fd3ae7a9SDaniel Baluta 	}
660fd3ae7a9SDaniel Baluta 
661fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client,
662fd3ae7a9SDaniel Baluta 					KMX61_REG_WUF_THRESH,
663fd3ae7a9SDaniel Baluta 					data->wake_thresh);
66428ff344eSDaniel Baluta 	if (ret < 0)
665fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_wuf_thresh\n");
666fd3ae7a9SDaniel Baluta 
66728ff344eSDaniel Baluta 	return ret;
668fd3ae7a9SDaniel Baluta }
669fd3ae7a9SDaniel Baluta 
670fd3ae7a9SDaniel Baluta static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data,
6710475c685SDaniel Baluta 					    bool status)
672fd3ae7a9SDaniel Baluta {
673fd3ae7a9SDaniel Baluta 	u8 mode;
674fd3ae7a9SDaniel Baluta 	int ret;
675fd3ae7a9SDaniel Baluta 
676fd3ae7a9SDaniel Baluta 	ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG);
677fd3ae7a9SDaniel Baluta 	if (ret < 0)
678fd3ae7a9SDaniel Baluta 		return ret;
679fd3ae7a9SDaniel Baluta 
680fd3ae7a9SDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
681fd3ae7a9SDaniel Baluta 	if (ret < 0)
682fd3ae7a9SDaniel Baluta 		return ret;
683fd3ae7a9SDaniel Baluta 
684fd3ae7a9SDaniel Baluta 	ret = kmx61_chip_update_thresholds(data);
685fd3ae7a9SDaniel Baluta 	if (ret < 0)
686fd3ae7a9SDaniel Baluta 		return ret;
687fd3ae7a9SDaniel Baluta 
688fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INC1);
689fd3ae7a9SDaniel Baluta 	if (ret < 0) {
690fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_inc1\n");
691fd3ae7a9SDaniel Baluta 		return ret;
692fd3ae7a9SDaniel Baluta 	}
693fd3ae7a9SDaniel Baluta 	if (status)
694fd3ae7a9SDaniel Baluta 		ret |= (KMX61_REG_INC1_BIT_IEN | KMX61_REG_INC1_BIT_WUFS);
695fd3ae7a9SDaniel Baluta 	else
696fd3ae7a9SDaniel Baluta 		ret &= ~(KMX61_REG_INC1_BIT_IEN | KMX61_REG_INC1_BIT_WUFS);
697fd3ae7a9SDaniel Baluta 
698fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_INC1, ret);
699fd3ae7a9SDaniel Baluta 	if (ret < 0) {
700fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_inc1\n");
701fd3ae7a9SDaniel Baluta 		return ret;
702fd3ae7a9SDaniel Baluta 	}
703fd3ae7a9SDaniel Baluta 
704fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1);
705fd3ae7a9SDaniel Baluta 	if (ret < 0) {
706fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
707fd3ae7a9SDaniel Baluta 		return ret;
708fd3ae7a9SDaniel Baluta 	}
709fd3ae7a9SDaniel Baluta 
710fd3ae7a9SDaniel Baluta 	if (status)
711fd3ae7a9SDaniel Baluta 		ret |= KMX61_REG_CTRL1_BIT_WUFE | KMX61_REG_CTRL1_BIT_BTSE;
712fd3ae7a9SDaniel Baluta 	else
713fd3ae7a9SDaniel Baluta 		ret &= ~(KMX61_REG_CTRL1_BIT_WUFE | KMX61_REG_CTRL1_BIT_BTSE);
714fd3ae7a9SDaniel Baluta 
715fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret);
716fd3ae7a9SDaniel Baluta 	if (ret < 0) {
717fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
718fd3ae7a9SDaniel Baluta 		return ret;
719fd3ae7a9SDaniel Baluta 	}
720fd3ae7a9SDaniel Baluta 	mode |= KMX61_ACT_STBY_BIT;
72128ff344eSDaniel Baluta 	return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true);
722fd3ae7a9SDaniel Baluta }
723fd3ae7a9SDaniel Baluta 
724aff8609aSDaniel Baluta /**
725aff8609aSDaniel Baluta  * kmx61_set_power_state() - set power state for kmx61 @device
726aff8609aSDaniel Baluta  * @data - kmx61 device private pointer
727aff8609aSDaniel Baluta  * @on - power state to be set for @device
728aff8609aSDaniel Baluta  * @device - bitmask indicating device for which @on state needs to be set
729aff8609aSDaniel Baluta  *
730aff8609aSDaniel Baluta  * Notice that when ACC power state needs to be set to ON and MAG is in
731aff8609aSDaniel Baluta  * OPERATION then we know that kmx61_runtime_resume was already called
732aff8609aSDaniel Baluta  * so we must set ACC OPERATION mode here. The same happens when MAG power
733aff8609aSDaniel Baluta  * state needs to be set to ON and ACC is in OPERATION.
734aff8609aSDaniel Baluta  */
735aff8609aSDaniel Baluta static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device)
736aff8609aSDaniel Baluta {
737df1fad80SDaniel Baluta #ifdef CONFIG_PM
738aff8609aSDaniel Baluta 	int ret;
739aff8609aSDaniel Baluta 
740aff8609aSDaniel Baluta 	if (device & KMX61_ACC) {
741aff8609aSDaniel Baluta 		if (on && !data->acc_ps && !data->mag_stby) {
742aff8609aSDaniel Baluta 			ret = kmx61_set_mode(data, 0, KMX61_ACC, true);
743aff8609aSDaniel Baluta 			if (ret < 0)
744aff8609aSDaniel Baluta 				return ret;
745aff8609aSDaniel Baluta 		}
746aff8609aSDaniel Baluta 		data->acc_ps = on;
747aff8609aSDaniel Baluta 	}
748aff8609aSDaniel Baluta 	if (device & KMX61_MAG) {
749aff8609aSDaniel Baluta 		if (on && !data->mag_ps && !data->acc_stby) {
750aff8609aSDaniel Baluta 			ret = kmx61_set_mode(data, 0, KMX61_MAG, true);
751aff8609aSDaniel Baluta 			if (ret < 0)
752aff8609aSDaniel Baluta 				return ret;
753aff8609aSDaniel Baluta 		}
754aff8609aSDaniel Baluta 		data->mag_ps = on;
755aff8609aSDaniel Baluta 	}
756aff8609aSDaniel Baluta 
757aff8609aSDaniel Baluta 	if (on) {
758aff8609aSDaniel Baluta 		ret = pm_runtime_get_sync(&data->client->dev);
759aff8609aSDaniel Baluta 	} else {
760aff8609aSDaniel Baluta 		pm_runtime_mark_last_busy(&data->client->dev);
761aff8609aSDaniel Baluta 		ret = pm_runtime_put_autosuspend(&data->client->dev);
762aff8609aSDaniel Baluta 	}
763aff8609aSDaniel Baluta 	if (ret < 0) {
764aff8609aSDaniel Baluta 		dev_err(&data->client->dev,
765aff8609aSDaniel Baluta 			"Failed: kmx61_set_power_state for %d, ret %d\n",
766aff8609aSDaniel Baluta 			on, ret);
767aff8609aSDaniel Baluta 		if (on)
768aff8609aSDaniel Baluta 			pm_runtime_put_noidle(&data->client->dev);
769aff8609aSDaniel Baluta 
770aff8609aSDaniel Baluta 		return ret;
771aff8609aSDaniel Baluta 	}
772aff8609aSDaniel Baluta #endif
773aff8609aSDaniel Baluta 	return 0;
774aff8609aSDaniel Baluta }
775aff8609aSDaniel Baluta 
77620ffac27SDaniel Baluta static int kmx61_read_measurement(struct kmx61_data *data, u8 base, u8 offset)
77720ffac27SDaniel Baluta {
77820ffac27SDaniel Baluta 	int ret;
77920ffac27SDaniel Baluta 	u8 reg = base + offset * 2;
78020ffac27SDaniel Baluta 
78120ffac27SDaniel Baluta 	ret = i2c_smbus_read_word_data(data->client, reg);
78220ffac27SDaniel Baluta 	if (ret < 0)
78320ffac27SDaniel Baluta 		dev_err(&data->client->dev, "failed to read reg at %x\n", reg);
78420ffac27SDaniel Baluta 
78520ffac27SDaniel Baluta 	return ret;
78620ffac27SDaniel Baluta }
78720ffac27SDaniel Baluta 
78820ffac27SDaniel Baluta static int kmx61_read_raw(struct iio_dev *indio_dev,
78920ffac27SDaniel Baluta 			  struct iio_chan_spec const *chan, int *val,
79020ffac27SDaniel Baluta 			  int *val2, long mask)
79120ffac27SDaniel Baluta {
79220ffac27SDaniel Baluta 	int ret;
79320ffac27SDaniel Baluta 	u8 base_reg;
79420ffac27SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
79520ffac27SDaniel Baluta 
79620ffac27SDaniel Baluta 	switch (mask) {
79720ffac27SDaniel Baluta 	case IIO_CHAN_INFO_RAW:
79820ffac27SDaniel Baluta 		switch (chan->type) {
79920ffac27SDaniel Baluta 		case IIO_ACCEL:
80020ffac27SDaniel Baluta 			base_reg = KMX61_ACC_XOUT_L;
80120ffac27SDaniel Baluta 			break;
80220ffac27SDaniel Baluta 		case IIO_MAGN:
80320ffac27SDaniel Baluta 			base_reg = KMX61_MAG_XOUT_L;
80420ffac27SDaniel Baluta 			break;
80520ffac27SDaniel Baluta 		default:
80620ffac27SDaniel Baluta 			return -EINVAL;
80720ffac27SDaniel Baluta 		}
80820ffac27SDaniel Baluta 		mutex_lock(&data->lock);
80920ffac27SDaniel Baluta 
810a3da4fa3SDaniel Baluta 		ret = kmx61_set_power_state(data, true, chan->address);
811a3da4fa3SDaniel Baluta 		if (ret) {
812a3da4fa3SDaniel Baluta 			mutex_unlock(&data->lock);
813a3da4fa3SDaniel Baluta 			return ret;
814a3da4fa3SDaniel Baluta 		}
815a3da4fa3SDaniel Baluta 
81620ffac27SDaniel Baluta 		ret = kmx61_read_measurement(data, base_reg, chan->scan_index);
81720ffac27SDaniel Baluta 		if (ret < 0) {
818aff8609aSDaniel Baluta 			kmx61_set_power_state(data, false, chan->address);
81920ffac27SDaniel Baluta 			mutex_unlock(&data->lock);
82020ffac27SDaniel Baluta 			return ret;
82120ffac27SDaniel Baluta 		}
82220ffac27SDaniel Baluta 		*val = sign_extend32(ret >> chan->scan_type.shift,
82320ffac27SDaniel Baluta 				     chan->scan_type.realbits - 1);
824a3da4fa3SDaniel Baluta 		ret = kmx61_set_power_state(data, false, chan->address);
82520ffac27SDaniel Baluta 
82620ffac27SDaniel Baluta 		mutex_unlock(&data->lock);
827a3da4fa3SDaniel Baluta 		if (ret)
828a3da4fa3SDaniel Baluta 			return ret;
82920ffac27SDaniel Baluta 		return IIO_VAL_INT;
83020ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SCALE:
83120ffac27SDaniel Baluta 		switch (chan->type) {
83220ffac27SDaniel Baluta 		case IIO_ACCEL:
83320ffac27SDaniel Baluta 			*val = 0;
83420ffac27SDaniel Baluta 			*val2 = kmx61_uscale_table[data->range];
83520ffac27SDaniel Baluta 			return IIO_VAL_INT_PLUS_MICRO;
83620ffac27SDaniel Baluta 		case IIO_MAGN:
83720ffac27SDaniel Baluta 			/* 14 bits res, 1465 microGauss per magn count */
83820ffac27SDaniel Baluta 			*val = 0;
83920ffac27SDaniel Baluta 			*val2 = 1465;
84020ffac27SDaniel Baluta 			return IIO_VAL_INT_PLUS_MICRO;
84120ffac27SDaniel Baluta 		default:
84220ffac27SDaniel Baluta 			return -EINVAL;
84320ffac27SDaniel Baluta 		}
84420ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SAMP_FREQ:
84520ffac27SDaniel Baluta 		if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN)
84620ffac27SDaniel Baluta 			return -EINVAL;
84720ffac27SDaniel Baluta 
84820ffac27SDaniel Baluta 		mutex_lock(&data->lock);
84920ffac27SDaniel Baluta 		ret = kmx61_get_odr(data, val, val2, chan->address);
85020ffac27SDaniel Baluta 		mutex_unlock(&data->lock);
85120ffac27SDaniel Baluta 		if (ret)
85220ffac27SDaniel Baluta 			return -EINVAL;
85320ffac27SDaniel Baluta 		return IIO_VAL_INT_PLUS_MICRO;
85420ffac27SDaniel Baluta 	}
85520ffac27SDaniel Baluta 	return -EINVAL;
85620ffac27SDaniel Baluta }
85720ffac27SDaniel Baluta 
85820ffac27SDaniel Baluta static int kmx61_write_raw(struct iio_dev *indio_dev,
85920ffac27SDaniel Baluta 			   struct iio_chan_spec const *chan, int val,
86020ffac27SDaniel Baluta 			   int val2, long mask)
86120ffac27SDaniel Baluta {
86220ffac27SDaniel Baluta 	int ret;
86320ffac27SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
86420ffac27SDaniel Baluta 
86520ffac27SDaniel Baluta 	switch (mask) {
86620ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SAMP_FREQ:
86720ffac27SDaniel Baluta 		if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN)
86820ffac27SDaniel Baluta 			return -EINVAL;
86920ffac27SDaniel Baluta 
87020ffac27SDaniel Baluta 		mutex_lock(&data->lock);
87120ffac27SDaniel Baluta 		ret = kmx61_set_odr(data, val, val2, chan->address);
87220ffac27SDaniel Baluta 		mutex_unlock(&data->lock);
87320ffac27SDaniel Baluta 		return ret;
87420ffac27SDaniel Baluta 	case IIO_CHAN_INFO_SCALE:
87520ffac27SDaniel Baluta 		switch (chan->type) {
87620ffac27SDaniel Baluta 		case IIO_ACCEL:
87720ffac27SDaniel Baluta 			if (val != 0)
87820ffac27SDaniel Baluta 				return -EINVAL;
87920ffac27SDaniel Baluta 			mutex_lock(&data->lock);
88020ffac27SDaniel Baluta 			ret = kmx61_set_scale(data, val2);
88120ffac27SDaniel Baluta 			mutex_unlock(&data->lock);
88220ffac27SDaniel Baluta 			return ret;
88320ffac27SDaniel Baluta 		default:
88420ffac27SDaniel Baluta 			return -EINVAL;
88520ffac27SDaniel Baluta 		}
88620ffac27SDaniel Baluta 	default:
88720ffac27SDaniel Baluta 		return -EINVAL;
88820ffac27SDaniel Baluta 	}
88920ffac27SDaniel Baluta }
89020ffac27SDaniel Baluta 
891fd3ae7a9SDaniel Baluta static int kmx61_read_event(struct iio_dev *indio_dev,
892fd3ae7a9SDaniel Baluta 			    const struct iio_chan_spec *chan,
893fd3ae7a9SDaniel Baluta 			    enum iio_event_type type,
894fd3ae7a9SDaniel Baluta 			    enum iio_event_direction dir,
895fd3ae7a9SDaniel Baluta 			    enum iio_event_info info,
896fd3ae7a9SDaniel Baluta 			    int *val, int *val2)
897fd3ae7a9SDaniel Baluta {
898fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
899fd3ae7a9SDaniel Baluta 
900fd3ae7a9SDaniel Baluta 	*val2 = 0;
901fd3ae7a9SDaniel Baluta 	switch (info) {
902fd3ae7a9SDaniel Baluta 	case IIO_EV_INFO_VALUE:
903fd3ae7a9SDaniel Baluta 		*val = data->wake_thresh;
90428ff344eSDaniel Baluta 		return IIO_VAL_INT;
905fd3ae7a9SDaniel Baluta 	case IIO_EV_INFO_PERIOD:
906fd3ae7a9SDaniel Baluta 		*val = data->wake_duration;
90728ff344eSDaniel Baluta 		return IIO_VAL_INT;
908fd3ae7a9SDaniel Baluta 	default:
909fd3ae7a9SDaniel Baluta 		return -EINVAL;
910fd3ae7a9SDaniel Baluta 	}
911fd3ae7a9SDaniel Baluta }
912fd3ae7a9SDaniel Baluta 
913fd3ae7a9SDaniel Baluta static int kmx61_write_event(struct iio_dev *indio_dev,
914fd3ae7a9SDaniel Baluta 			     const struct iio_chan_spec *chan,
915fd3ae7a9SDaniel Baluta 			     enum iio_event_type type,
916fd3ae7a9SDaniel Baluta 			     enum iio_event_direction dir,
917fd3ae7a9SDaniel Baluta 			     enum iio_event_info info,
918fd3ae7a9SDaniel Baluta 			     int val, int val2)
919fd3ae7a9SDaniel Baluta {
920fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
921fd3ae7a9SDaniel Baluta 
922fd3ae7a9SDaniel Baluta 	if (data->ev_enable_state)
923fd3ae7a9SDaniel Baluta 		return -EBUSY;
924fd3ae7a9SDaniel Baluta 
925fd3ae7a9SDaniel Baluta 	switch (info) {
926fd3ae7a9SDaniel Baluta 	case IIO_EV_INFO_VALUE:
927fd3ae7a9SDaniel Baluta 		data->wake_thresh = val;
92828ff344eSDaniel Baluta 		return IIO_VAL_INT;
929fd3ae7a9SDaniel Baluta 	case IIO_EV_INFO_PERIOD:
930fd3ae7a9SDaniel Baluta 		data->wake_duration = val;
93128ff344eSDaniel Baluta 		return IIO_VAL_INT;
932fd3ae7a9SDaniel Baluta 	default:
933fd3ae7a9SDaniel Baluta 		return -EINVAL;
934fd3ae7a9SDaniel Baluta 	}
935fd3ae7a9SDaniel Baluta }
936fd3ae7a9SDaniel Baluta 
937fd3ae7a9SDaniel Baluta static int kmx61_read_event_config(struct iio_dev *indio_dev,
938fd3ae7a9SDaniel Baluta 				   const struct iio_chan_spec *chan,
939fd3ae7a9SDaniel Baluta 				   enum iio_event_type type,
940fd3ae7a9SDaniel Baluta 				   enum iio_event_direction dir)
941fd3ae7a9SDaniel Baluta {
942fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
943fd3ae7a9SDaniel Baluta 
944fd3ae7a9SDaniel Baluta 	return data->ev_enable_state;
945fd3ae7a9SDaniel Baluta }
946fd3ae7a9SDaniel Baluta 
947fd3ae7a9SDaniel Baluta static int kmx61_write_event_config(struct iio_dev *indio_dev,
948fd3ae7a9SDaniel Baluta 				    const struct iio_chan_spec *chan,
949fd3ae7a9SDaniel Baluta 				    enum iio_event_type type,
950fd3ae7a9SDaniel Baluta 				    enum iio_event_direction dir,
951fd3ae7a9SDaniel Baluta 				    int state)
952fd3ae7a9SDaniel Baluta {
953fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
95428ff344eSDaniel Baluta 	int ret = 0;
955fd3ae7a9SDaniel Baluta 
956fd3ae7a9SDaniel Baluta 	if (state && data->ev_enable_state)
957fd3ae7a9SDaniel Baluta 		return 0;
958fd3ae7a9SDaniel Baluta 
959fd3ae7a9SDaniel Baluta 	mutex_lock(&data->lock);
960fd3ae7a9SDaniel Baluta 
961fd3ae7a9SDaniel Baluta 	if (!state && data->motion_trig_on) {
962d4a4ae04SDaniel Baluta 		data->ev_enable_state = false;
96328ff344eSDaniel Baluta 		goto err_unlock;
964fd3ae7a9SDaniel Baluta 	}
965fd3ae7a9SDaniel Baluta 
966fd3ae7a9SDaniel Baluta 	ret = kmx61_set_power_state(data, state, KMX61_ACC);
96728ff344eSDaniel Baluta 	if (ret < 0)
96828ff344eSDaniel Baluta 		goto err_unlock;
969fd3ae7a9SDaniel Baluta 
9700475c685SDaniel Baluta 	ret = kmx61_setup_any_motion_interrupt(data, state);
971fd3ae7a9SDaniel Baluta 	if (ret < 0) {
972fd3ae7a9SDaniel Baluta 		kmx61_set_power_state(data, false, KMX61_ACC);
97328ff344eSDaniel Baluta 		goto err_unlock;
974fd3ae7a9SDaniel Baluta 	}
975fd3ae7a9SDaniel Baluta 
976fd3ae7a9SDaniel Baluta 	data->ev_enable_state = state;
97728ff344eSDaniel Baluta 
97828ff344eSDaniel Baluta err_unlock:
979fd3ae7a9SDaniel Baluta 	mutex_unlock(&data->lock);
980fd3ae7a9SDaniel Baluta 
98128ff344eSDaniel Baluta 	return ret;
982fd3ae7a9SDaniel Baluta }
983fd3ae7a9SDaniel Baluta 
984c3a23eccSDaniel Baluta static int kmx61_acc_validate_trigger(struct iio_dev *indio_dev,
985c3a23eccSDaniel Baluta 				      struct iio_trigger *trig)
986c3a23eccSDaniel Baluta {
987c3a23eccSDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
988c3a23eccSDaniel Baluta 
989fd3ae7a9SDaniel Baluta 	if (data->acc_dready_trig != trig && data->motion_trig != trig)
990c3a23eccSDaniel Baluta 		return -EINVAL;
991c3a23eccSDaniel Baluta 
992c3a23eccSDaniel Baluta 	return 0;
993c3a23eccSDaniel Baluta }
994c3a23eccSDaniel Baluta 
995c3a23eccSDaniel Baluta static int kmx61_mag_validate_trigger(struct iio_dev *indio_dev,
996c3a23eccSDaniel Baluta 				      struct iio_trigger *trig)
997c3a23eccSDaniel Baluta {
998c3a23eccSDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
999c3a23eccSDaniel Baluta 
1000c3a23eccSDaniel Baluta 	if (data->mag_dready_trig != trig)
1001c3a23eccSDaniel Baluta 		return -EINVAL;
1002c3a23eccSDaniel Baluta 
1003c3a23eccSDaniel Baluta 	return 0;
1004c3a23eccSDaniel Baluta }
1005c3a23eccSDaniel Baluta 
100620ffac27SDaniel Baluta static const struct iio_info kmx61_acc_info = {
100720ffac27SDaniel Baluta 	.driver_module		= THIS_MODULE,
100820ffac27SDaniel Baluta 	.read_raw		= kmx61_read_raw,
100920ffac27SDaniel Baluta 	.write_raw		= kmx61_write_raw,
101020ffac27SDaniel Baluta 	.attrs			= &kmx61_acc_attribute_group,
1011fd3ae7a9SDaniel Baluta 	.read_event_value	= kmx61_read_event,
1012fd3ae7a9SDaniel Baluta 	.write_event_value	= kmx61_write_event,
1013fd3ae7a9SDaniel Baluta 	.read_event_config	= kmx61_read_event_config,
1014fd3ae7a9SDaniel Baluta 	.write_event_config	= kmx61_write_event_config,
1015c3a23eccSDaniel Baluta 	.validate_trigger	= kmx61_acc_validate_trigger,
101620ffac27SDaniel Baluta };
101720ffac27SDaniel Baluta 
101820ffac27SDaniel Baluta static const struct iio_info kmx61_mag_info = {
101920ffac27SDaniel Baluta 	.driver_module		= THIS_MODULE,
102020ffac27SDaniel Baluta 	.read_raw		= kmx61_read_raw,
102120ffac27SDaniel Baluta 	.write_raw		= kmx61_write_raw,
102220ffac27SDaniel Baluta 	.attrs			= &kmx61_mag_attribute_group,
1023c3a23eccSDaniel Baluta 	.validate_trigger	= kmx61_mag_validate_trigger,
102420ffac27SDaniel Baluta };
102520ffac27SDaniel Baluta 
1026c3a23eccSDaniel Baluta 
1027c3a23eccSDaniel Baluta static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig,
1028c3a23eccSDaniel Baluta 					    bool state)
1029c3a23eccSDaniel Baluta {
1030c3a23eccSDaniel Baluta 	int ret = 0;
1031c3a23eccSDaniel Baluta 	u8 device;
1032c3a23eccSDaniel Baluta 
1033c3a23eccSDaniel Baluta 	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
1034fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
1035c3a23eccSDaniel Baluta 
1036c3a23eccSDaniel Baluta 	mutex_lock(&data->lock);
1037c3a23eccSDaniel Baluta 
1038fd3ae7a9SDaniel Baluta 	if (!state && data->ev_enable_state && data->motion_trig_on) {
1039fd3ae7a9SDaniel Baluta 		data->motion_trig_on = false;
104028ff344eSDaniel Baluta 		goto err_unlock;
1041fd3ae7a9SDaniel Baluta 	}
1042fd3ae7a9SDaniel Baluta 
1043dbdd0e2dSDaniel Baluta 	if (data->acc_dready_trig == trig || data->motion_trig == trig)
1044c3a23eccSDaniel Baluta 		device = KMX61_ACC;
1045c3a23eccSDaniel Baluta 	else
1046c3a23eccSDaniel Baluta 		device = KMX61_MAG;
1047c3a23eccSDaniel Baluta 
1048c3a23eccSDaniel Baluta 	ret = kmx61_set_power_state(data, state, device);
104928ff344eSDaniel Baluta 	if (ret < 0)
105028ff344eSDaniel Baluta 		goto err_unlock;
1051c3a23eccSDaniel Baluta 
1052fd3ae7a9SDaniel Baluta 	if (data->acc_dready_trig == trig || data->mag_dready_trig == trig)
1053c3a23eccSDaniel Baluta 		ret = kmx61_setup_new_data_interrupt(data, state, device);
1054fd3ae7a9SDaniel Baluta 	else
10550475c685SDaniel Baluta 		ret = kmx61_setup_any_motion_interrupt(data, state);
1056c3a23eccSDaniel Baluta 	if (ret < 0) {
1057c3a23eccSDaniel Baluta 		kmx61_set_power_state(data, false, device);
105828ff344eSDaniel Baluta 		goto err_unlock;
1059c3a23eccSDaniel Baluta 	}
1060c3a23eccSDaniel Baluta 
1061c3a23eccSDaniel Baluta 	if (data->acc_dready_trig == trig)
1062c3a23eccSDaniel Baluta 		data->acc_dready_trig_on = state;
1063fd3ae7a9SDaniel Baluta 	else if (data->mag_dready_trig == trig)
1064c3a23eccSDaniel Baluta 		data->mag_dready_trig_on = state;
1065fd3ae7a9SDaniel Baluta 	else
1066fd3ae7a9SDaniel Baluta 		data->motion_trig_on = state;
106728ff344eSDaniel Baluta err_unlock:
1068c3a23eccSDaniel Baluta 	mutex_unlock(&data->lock);
1069c3a23eccSDaniel Baluta 
107028ff344eSDaniel Baluta 	return ret;
1071c3a23eccSDaniel Baluta }
1072c3a23eccSDaniel Baluta 
1073c3a23eccSDaniel Baluta static int kmx61_trig_try_reenable(struct iio_trigger *trig)
1074c3a23eccSDaniel Baluta {
1075c3a23eccSDaniel Baluta 	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
1076c3a23eccSDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
1077c3a23eccSDaniel Baluta 	int ret;
1078c3a23eccSDaniel Baluta 
1079c3a23eccSDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL);
1080c3a23eccSDaniel Baluta 	if (ret < 0) {
1081c3a23eccSDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_inl\n");
1082c3a23eccSDaniel Baluta 		return ret;
1083c3a23eccSDaniel Baluta 	}
1084c3a23eccSDaniel Baluta 
1085c3a23eccSDaniel Baluta 	return 0;
1086c3a23eccSDaniel Baluta }
1087c3a23eccSDaniel Baluta 
1088c3a23eccSDaniel Baluta static const struct iio_trigger_ops kmx61_trigger_ops = {
1089c3a23eccSDaniel Baluta 	.set_trigger_state = kmx61_data_rdy_trigger_set_state,
1090c3a23eccSDaniel Baluta 	.try_reenable = kmx61_trig_try_reenable,
1091c3a23eccSDaniel Baluta 	.owner = THIS_MODULE,
1092c3a23eccSDaniel Baluta };
1093c3a23eccSDaniel Baluta 
1094fd3ae7a9SDaniel Baluta static irqreturn_t kmx61_event_handler(int irq, void *private)
1095fd3ae7a9SDaniel Baluta {
1096fd3ae7a9SDaniel Baluta 	struct kmx61_data *data = private;
1097fd3ae7a9SDaniel Baluta 	struct iio_dev *indio_dev = data->acc_indio_dev;
1098fd3ae7a9SDaniel Baluta 	int ret;
1099fd3ae7a9SDaniel Baluta 
1100fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS1);
1101fd3ae7a9SDaniel Baluta 	if (ret < 0) {
1102fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ins1\n");
1103fd3ae7a9SDaniel Baluta 		goto ack_intr;
1104fd3ae7a9SDaniel Baluta 	}
1105fd3ae7a9SDaniel Baluta 
1106fd3ae7a9SDaniel Baluta 	if (ret & KMX61_REG_INS1_BIT_WUFS) {
1107fd3ae7a9SDaniel Baluta 		ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS2);
1108fd3ae7a9SDaniel Baluta 		if (ret < 0) {
1109fd3ae7a9SDaniel Baluta 			dev_err(&data->client->dev, "Error reading reg_ins2\n");
1110fd3ae7a9SDaniel Baluta 			goto ack_intr;
1111fd3ae7a9SDaniel Baluta 		}
1112fd3ae7a9SDaniel Baluta 
1113fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_XN)
1114fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1115fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1116fd3ae7a9SDaniel Baluta 				       0,
1117fd3ae7a9SDaniel Baluta 				       IIO_MOD_X,
1118fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1119fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_FALLING),
1120fd3ae7a9SDaniel Baluta 				       0);
1121fd3ae7a9SDaniel Baluta 
1122fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_XP)
1123fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1124fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1125fd3ae7a9SDaniel Baluta 				       0,
1126fd3ae7a9SDaniel Baluta 				       IIO_MOD_X,
1127fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1128fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_RISING),
1129fd3ae7a9SDaniel Baluta 				       0);
1130fd3ae7a9SDaniel Baluta 
1131fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_YN)
1132fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1133fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1134fd3ae7a9SDaniel Baluta 				       0,
1135fd3ae7a9SDaniel Baluta 				       IIO_MOD_Y,
1136fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1137fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_FALLING),
1138fd3ae7a9SDaniel Baluta 				       0);
1139fd3ae7a9SDaniel Baluta 
1140fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_YP)
1141fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1142fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1143fd3ae7a9SDaniel Baluta 				       0,
1144fd3ae7a9SDaniel Baluta 				       IIO_MOD_Y,
1145fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1146fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_RISING),
1147fd3ae7a9SDaniel Baluta 				       0);
1148fd3ae7a9SDaniel Baluta 
1149fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_ZN)
1150fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1151fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1152fd3ae7a9SDaniel Baluta 				       0,
1153fd3ae7a9SDaniel Baluta 				       IIO_MOD_Z,
1154fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1155fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_FALLING),
1156fd3ae7a9SDaniel Baluta 				       0);
1157fd3ae7a9SDaniel Baluta 
1158fd3ae7a9SDaniel Baluta 		if (ret & KMX61_REG_INS2_BIT_ZP)
1159fd3ae7a9SDaniel Baluta 			iio_push_event(indio_dev,
1160fd3ae7a9SDaniel Baluta 				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
1161fd3ae7a9SDaniel Baluta 				       0,
1162fd3ae7a9SDaniel Baluta 				       IIO_MOD_Z,
1163fd3ae7a9SDaniel Baluta 				       IIO_EV_TYPE_THRESH,
1164fd3ae7a9SDaniel Baluta 				       IIO_EV_DIR_RISING),
1165fd3ae7a9SDaniel Baluta 				       0);
1166fd3ae7a9SDaniel Baluta 	}
1167fd3ae7a9SDaniel Baluta 
1168fd3ae7a9SDaniel Baluta ack_intr:
1169fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1);
1170fd3ae7a9SDaniel Baluta 	if (ret < 0)
1171fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
1172fd3ae7a9SDaniel Baluta 
1173fd3ae7a9SDaniel Baluta 	ret |= KMX61_REG_CTRL1_BIT_RES;
1174fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret);
1175fd3ae7a9SDaniel Baluta 	if (ret < 0)
117628ff344eSDaniel Baluta 		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
1177fd3ae7a9SDaniel Baluta 
1178fd3ae7a9SDaniel Baluta 	ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL);
1179fd3ae7a9SDaniel Baluta 	if (ret < 0)
1180fd3ae7a9SDaniel Baluta 		dev_err(&data->client->dev, "Error reading reg_inl\n");
1181fd3ae7a9SDaniel Baluta 
1182fd3ae7a9SDaniel Baluta 	return IRQ_HANDLED;
1183fd3ae7a9SDaniel Baluta }
1184fd3ae7a9SDaniel Baluta 
1185c3a23eccSDaniel Baluta static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private)
1186c3a23eccSDaniel Baluta {
1187c3a23eccSDaniel Baluta 	struct kmx61_data *data = private;
1188c3a23eccSDaniel Baluta 
1189c3a23eccSDaniel Baluta 	if (data->acc_dready_trig_on)
1190c3a23eccSDaniel Baluta 		iio_trigger_poll(data->acc_dready_trig);
1191c3a23eccSDaniel Baluta 	if (data->mag_dready_trig_on)
1192c3a23eccSDaniel Baluta 		iio_trigger_poll(data->mag_dready_trig);
1193c3a23eccSDaniel Baluta 
1194fd3ae7a9SDaniel Baluta 	if (data->motion_trig_on)
1195fd3ae7a9SDaniel Baluta 		iio_trigger_poll(data->motion_trig);
1196fd3ae7a9SDaniel Baluta 
1197fd3ae7a9SDaniel Baluta 	if (data->ev_enable_state)
1198fd3ae7a9SDaniel Baluta 		return IRQ_WAKE_THREAD;
1199c3a23eccSDaniel Baluta 	return IRQ_HANDLED;
1200c3a23eccSDaniel Baluta }
1201c3a23eccSDaniel Baluta 
1202c3a23eccSDaniel Baluta static irqreturn_t kmx61_trigger_handler(int irq, void *p)
1203c3a23eccSDaniel Baluta {
1204c3a23eccSDaniel Baluta 	struct iio_poll_func *pf = p;
1205c3a23eccSDaniel Baluta 	struct iio_dev *indio_dev = pf->indio_dev;
1206c3a23eccSDaniel Baluta 	struct kmx61_data *data = kmx61_get_data(indio_dev);
1207c3a23eccSDaniel Baluta 	int bit, ret, i = 0;
12086a191c70SDaniel Baluta 	u8 base;
1209c3a23eccSDaniel Baluta 	s16 buffer[8];
1210c3a23eccSDaniel Baluta 
12116a191c70SDaniel Baluta 	if (indio_dev == data->acc_indio_dev)
12126a191c70SDaniel Baluta 		base = KMX61_ACC_XOUT_L;
12136a191c70SDaniel Baluta 	else
12146a191c70SDaniel Baluta 		base = KMX61_MAG_XOUT_L;
12156a191c70SDaniel Baluta 
1216c3a23eccSDaniel Baluta 	mutex_lock(&data->lock);
121770dddeeeSOctavian Purdila 	for_each_set_bit(bit, indio_dev->active_scan_mask,
1218c3a23eccSDaniel Baluta 			 indio_dev->masklength) {
12196a191c70SDaniel Baluta 		ret = kmx61_read_measurement(data, base, bit);
1220c3a23eccSDaniel Baluta 		if (ret < 0) {
1221c3a23eccSDaniel Baluta 			mutex_unlock(&data->lock);
1222c3a23eccSDaniel Baluta 			goto err;
1223c3a23eccSDaniel Baluta 		}
1224c3a23eccSDaniel Baluta 		buffer[i++] = ret;
1225c3a23eccSDaniel Baluta 	}
1226c3a23eccSDaniel Baluta 	mutex_unlock(&data->lock);
1227c3a23eccSDaniel Baluta 
1228c3a23eccSDaniel Baluta 	iio_push_to_buffers(indio_dev, buffer);
1229c3a23eccSDaniel Baluta err:
1230c3a23eccSDaniel Baluta 	iio_trigger_notify_done(indio_dev->trig);
1231c3a23eccSDaniel Baluta 
1232c3a23eccSDaniel Baluta 	return IRQ_HANDLED;
1233c3a23eccSDaniel Baluta }
1234c3a23eccSDaniel Baluta 
1235b25862c5SDaniel Baluta static const char *kmx61_match_acpi_device(struct device *dev)
1236b25862c5SDaniel Baluta {
1237b25862c5SDaniel Baluta 	const struct acpi_device_id *id;
1238b25862c5SDaniel Baluta 
1239b25862c5SDaniel Baluta 	id = acpi_match_device(dev->driver->acpi_match_table, dev);
1240b25862c5SDaniel Baluta 	if (!id)
1241b25862c5SDaniel Baluta 		return NULL;
1242b25862c5SDaniel Baluta 	return dev_name(dev);
1243b25862c5SDaniel Baluta }
1244b25862c5SDaniel Baluta 
124520ffac27SDaniel Baluta static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data,
124620ffac27SDaniel Baluta 					    const struct iio_info *info,
124720ffac27SDaniel Baluta 					    const struct iio_chan_spec *chan,
124820ffac27SDaniel Baluta 					    int num_channels,
124920ffac27SDaniel Baluta 					    const char *name)
125020ffac27SDaniel Baluta {
125120ffac27SDaniel Baluta 	struct iio_dev *indio_dev;
125220ffac27SDaniel Baluta 
125320ffac27SDaniel Baluta 	indio_dev = devm_iio_device_alloc(&data->client->dev, sizeof(data));
125420ffac27SDaniel Baluta 	if (!indio_dev)
125520ffac27SDaniel Baluta 		return ERR_PTR(-ENOMEM);
125620ffac27SDaniel Baluta 
125720ffac27SDaniel Baluta 	kmx61_set_data(indio_dev, data);
125820ffac27SDaniel Baluta 
125920ffac27SDaniel Baluta 	indio_dev->dev.parent = &data->client->dev;
126020ffac27SDaniel Baluta 	indio_dev->channels = chan;
126120ffac27SDaniel Baluta 	indio_dev->num_channels = num_channels;
126220ffac27SDaniel Baluta 	indio_dev->name = name;
126320ffac27SDaniel Baluta 	indio_dev->modes = INDIO_DIRECT_MODE;
126420ffac27SDaniel Baluta 	indio_dev->info = info;
126520ffac27SDaniel Baluta 
126620ffac27SDaniel Baluta 	return indio_dev;
126720ffac27SDaniel Baluta }
126820ffac27SDaniel Baluta 
1269c3a23eccSDaniel Baluta static struct iio_trigger *kmx61_trigger_setup(struct kmx61_data *data,
1270c3a23eccSDaniel Baluta 					       struct iio_dev *indio_dev,
1271c3a23eccSDaniel Baluta 					       const char *tag)
1272c3a23eccSDaniel Baluta {
1273c3a23eccSDaniel Baluta 	struct iio_trigger *trig;
1274c3a23eccSDaniel Baluta 	int ret;
1275c3a23eccSDaniel Baluta 
1276c3a23eccSDaniel Baluta 	trig = devm_iio_trigger_alloc(&data->client->dev,
1277c3a23eccSDaniel Baluta 				      "%s-%s-dev%d",
1278c3a23eccSDaniel Baluta 				      indio_dev->name,
1279c3a23eccSDaniel Baluta 				      tag,
1280c3a23eccSDaniel Baluta 				      indio_dev->id);
1281c3a23eccSDaniel Baluta 	if (!trig)
1282c3a23eccSDaniel Baluta 		return ERR_PTR(-ENOMEM);
1283c3a23eccSDaniel Baluta 
1284c3a23eccSDaniel Baluta 	trig->dev.parent = &data->client->dev;
1285c3a23eccSDaniel Baluta 	trig->ops = &kmx61_trigger_ops;
1286c3a23eccSDaniel Baluta 	iio_trigger_set_drvdata(trig, indio_dev);
1287c3a23eccSDaniel Baluta 
1288c3a23eccSDaniel Baluta 	ret = iio_trigger_register(trig);
1289c3a23eccSDaniel Baluta 	if (ret)
1290c3a23eccSDaniel Baluta 		return ERR_PTR(ret);
1291c3a23eccSDaniel Baluta 
1292c3a23eccSDaniel Baluta 	return trig;
1293c3a23eccSDaniel Baluta }
1294c3a23eccSDaniel Baluta 
129520ffac27SDaniel Baluta static int kmx61_probe(struct i2c_client *client,
129620ffac27SDaniel Baluta 		       const struct i2c_device_id *id)
129720ffac27SDaniel Baluta {
129820ffac27SDaniel Baluta 	int ret;
129920ffac27SDaniel Baluta 	struct kmx61_data *data;
130020ffac27SDaniel Baluta 	const char *name = NULL;
130120ffac27SDaniel Baluta 
130220ffac27SDaniel Baluta 	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
130320ffac27SDaniel Baluta 	if (!data)
130420ffac27SDaniel Baluta 		return -ENOMEM;
130520ffac27SDaniel Baluta 
130620ffac27SDaniel Baluta 	i2c_set_clientdata(client, data);
130720ffac27SDaniel Baluta 	data->client = client;
130820ffac27SDaniel Baluta 
130920ffac27SDaniel Baluta 	mutex_init(&data->lock);
131020ffac27SDaniel Baluta 
1311b25862c5SDaniel Baluta 	if (id)
1312b25862c5SDaniel Baluta 		name = id->name;
1313b25862c5SDaniel Baluta 	else if (ACPI_HANDLE(&client->dev))
1314b25862c5SDaniel Baluta 		name = kmx61_match_acpi_device(&client->dev);
1315b25862c5SDaniel Baluta 	else
1316b25862c5SDaniel Baluta 		return -ENODEV;
1317b25862c5SDaniel Baluta 
131820ffac27SDaniel Baluta 	data->acc_indio_dev =
131920ffac27SDaniel Baluta 		kmx61_indiodev_setup(data, &kmx61_acc_info,
132020ffac27SDaniel Baluta 				     kmx61_acc_channels,
132120ffac27SDaniel Baluta 				     ARRAY_SIZE(kmx61_acc_channels),
132220ffac27SDaniel Baluta 				     name);
132320ffac27SDaniel Baluta 	if (IS_ERR(data->acc_indio_dev))
132420ffac27SDaniel Baluta 		return PTR_ERR(data->acc_indio_dev);
132520ffac27SDaniel Baluta 
132620ffac27SDaniel Baluta 	data->mag_indio_dev =
132720ffac27SDaniel Baluta 		kmx61_indiodev_setup(data, &kmx61_mag_info,
132820ffac27SDaniel Baluta 				     kmx61_mag_channels,
132920ffac27SDaniel Baluta 				     ARRAY_SIZE(kmx61_mag_channels),
133020ffac27SDaniel Baluta 				     name);
133120ffac27SDaniel Baluta 	if (IS_ERR(data->mag_indio_dev))
133220ffac27SDaniel Baluta 		return PTR_ERR(data->mag_indio_dev);
133320ffac27SDaniel Baluta 
133420ffac27SDaniel Baluta 	ret = kmx61_chip_init(data);
133520ffac27SDaniel Baluta 	if (ret < 0)
133620ffac27SDaniel Baluta 		return ret;
133720ffac27SDaniel Baluta 
1338c176becdSOctavian Purdila 	if (client->irq > 0) {
1339c3a23eccSDaniel Baluta 		ret = devm_request_threaded_irq(&client->dev, client->irq,
1340c3a23eccSDaniel Baluta 						kmx61_data_rdy_trig_poll,
1341fd3ae7a9SDaniel Baluta 						kmx61_event_handler,
1342c3a23eccSDaniel Baluta 						IRQF_TRIGGER_RISING,
1343c3a23eccSDaniel Baluta 						KMX61_IRQ_NAME,
1344c3a23eccSDaniel Baluta 						data);
1345c3a23eccSDaniel Baluta 		if (ret)
1346c3a23eccSDaniel Baluta 			goto err_chip_uninit;
1347c3a23eccSDaniel Baluta 
1348c3a23eccSDaniel Baluta 		data->acc_dready_trig =
1349c3a23eccSDaniel Baluta 			kmx61_trigger_setup(data, data->acc_indio_dev,
1350c3a23eccSDaniel Baluta 					    "dready");
135128ff344eSDaniel Baluta 		if (IS_ERR(data->acc_dready_trig)) {
135228ff344eSDaniel Baluta 			ret = PTR_ERR(data->acc_dready_trig);
135328ff344eSDaniel Baluta 			goto err_chip_uninit;
135428ff344eSDaniel Baluta 		}
1355c3a23eccSDaniel Baluta 
1356c3a23eccSDaniel Baluta 		data->mag_dready_trig =
1357c3a23eccSDaniel Baluta 			kmx61_trigger_setup(data, data->mag_indio_dev,
1358c3a23eccSDaniel Baluta 					    "dready");
1359c3a23eccSDaniel Baluta 		if (IS_ERR(data->mag_dready_trig)) {
1360c3a23eccSDaniel Baluta 			ret = PTR_ERR(data->mag_dready_trig);
136128ff344eSDaniel Baluta 			goto err_trigger_unregister_acc_dready;
1362c3a23eccSDaniel Baluta 		}
1363c3a23eccSDaniel Baluta 
1364fd3ae7a9SDaniel Baluta 		data->motion_trig =
1365fd3ae7a9SDaniel Baluta 			kmx61_trigger_setup(data, data->acc_indio_dev,
1366fd3ae7a9SDaniel Baluta 					    "any-motion");
1367fd3ae7a9SDaniel Baluta 		if (IS_ERR(data->motion_trig)) {
1368fd3ae7a9SDaniel Baluta 			ret = PTR_ERR(data->motion_trig);
136928ff344eSDaniel Baluta 			goto err_trigger_unregister_mag_dready;
1370fd3ae7a9SDaniel Baluta 		}
1371fd3ae7a9SDaniel Baluta 
1372c3a23eccSDaniel Baluta 		ret = iio_triggered_buffer_setup(data->acc_indio_dev,
1373c3a23eccSDaniel Baluta 						 &iio_pollfunc_store_time,
1374c3a23eccSDaniel Baluta 						 kmx61_trigger_handler,
1375c3a23eccSDaniel Baluta 						 NULL);
1376c3a23eccSDaniel Baluta 		if (ret < 0) {
1377c3a23eccSDaniel Baluta 			dev_err(&data->client->dev,
1378c3a23eccSDaniel Baluta 				"Failed to setup acc triggered buffer\n");
137928ff344eSDaniel Baluta 			goto err_trigger_unregister_motion;
1380c3a23eccSDaniel Baluta 		}
1381c3a23eccSDaniel Baluta 
1382c3a23eccSDaniel Baluta 		ret = iio_triggered_buffer_setup(data->mag_indio_dev,
1383c3a23eccSDaniel Baluta 						 &iio_pollfunc_store_time,
1384c3a23eccSDaniel Baluta 						 kmx61_trigger_handler,
1385c3a23eccSDaniel Baluta 						 NULL);
1386c3a23eccSDaniel Baluta 		if (ret < 0) {
1387c3a23eccSDaniel Baluta 			dev_err(&data->client->dev,
1388c3a23eccSDaniel Baluta 				"Failed to setup mag triggered buffer\n");
138928ff344eSDaniel Baluta 			goto err_buffer_cleanup_acc;
1390c3a23eccSDaniel Baluta 		}
1391c3a23eccSDaniel Baluta 	}
1392c3a23eccSDaniel Baluta 
1393*7d0ead5cSAdriana Reus 	ret = pm_runtime_set_active(&client->dev);
1394*7d0ead5cSAdriana Reus 	if (ret < 0)
1395*7d0ead5cSAdriana Reus 		goto err_buffer_cleanup_mag;
1396*7d0ead5cSAdriana Reus 
1397*7d0ead5cSAdriana Reus 	pm_runtime_enable(&client->dev);
1398*7d0ead5cSAdriana Reus 	pm_runtime_set_autosuspend_delay(&client->dev, KMX61_SLEEP_DELAY_MS);
1399*7d0ead5cSAdriana Reus 	pm_runtime_use_autosuspend(&client->dev);
1400*7d0ead5cSAdriana Reus 
140120ffac27SDaniel Baluta 	ret = iio_device_register(data->acc_indio_dev);
140220ffac27SDaniel Baluta 	if (ret < 0) {
140320ffac27SDaniel Baluta 		dev_err(&client->dev, "Failed to register acc iio device\n");
140428ff344eSDaniel Baluta 		goto err_buffer_cleanup_mag;
140520ffac27SDaniel Baluta 	}
140620ffac27SDaniel Baluta 
140720ffac27SDaniel Baluta 	ret = iio_device_register(data->mag_indio_dev);
140820ffac27SDaniel Baluta 	if (ret < 0) {
140920ffac27SDaniel Baluta 		dev_err(&client->dev, "Failed to register mag iio device\n");
1410aff8609aSDaniel Baluta 		goto err_iio_unregister_acc;
141120ffac27SDaniel Baluta 	}
141220ffac27SDaniel Baluta 
141320ffac27SDaniel Baluta 	return 0;
141420ffac27SDaniel Baluta 
1415aff8609aSDaniel Baluta err_iio_unregister_acc:
141620ffac27SDaniel Baluta 	iio_device_unregister(data->acc_indio_dev);
141728ff344eSDaniel Baluta err_buffer_cleanup_mag:
1418c176becdSOctavian Purdila 	if (client->irq > 0)
1419c3a23eccSDaniel Baluta 		iio_triggered_buffer_cleanup(data->mag_indio_dev);
142028ff344eSDaniel Baluta err_buffer_cleanup_acc:
1421c176becdSOctavian Purdila 	if (client->irq > 0)
142228ff344eSDaniel Baluta 		iio_triggered_buffer_cleanup(data->acc_indio_dev);
142328ff344eSDaniel Baluta err_trigger_unregister_motion:
1424fd3ae7a9SDaniel Baluta 	iio_trigger_unregister(data->motion_trig);
142528ff344eSDaniel Baluta err_trigger_unregister_mag_dready:
142628ff344eSDaniel Baluta 	iio_trigger_unregister(data->mag_dready_trig);
142728ff344eSDaniel Baluta err_trigger_unregister_acc_dready:
142828ff344eSDaniel Baluta 	iio_trigger_unregister(data->acc_dready_trig);
142920ffac27SDaniel Baluta err_chip_uninit:
143020ffac27SDaniel Baluta 	kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
143120ffac27SDaniel Baluta 	return ret;
143220ffac27SDaniel Baluta }
143320ffac27SDaniel Baluta 
143420ffac27SDaniel Baluta static int kmx61_remove(struct i2c_client *client)
143520ffac27SDaniel Baluta {
143620ffac27SDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(client);
143720ffac27SDaniel Baluta 
1438*7d0ead5cSAdriana Reus 	iio_device_unregister(data->acc_indio_dev);
1439*7d0ead5cSAdriana Reus 	iio_device_unregister(data->mag_indio_dev);
1440*7d0ead5cSAdriana Reus 
1441aff8609aSDaniel Baluta 	pm_runtime_disable(&client->dev);
1442aff8609aSDaniel Baluta 	pm_runtime_set_suspended(&client->dev);
1443aff8609aSDaniel Baluta 	pm_runtime_put_noidle(&client->dev);
1444aff8609aSDaniel Baluta 
1445c176becdSOctavian Purdila 	if (client->irq > 0) {
1446c3a23eccSDaniel Baluta 		iio_triggered_buffer_cleanup(data->acc_indio_dev);
1447c3a23eccSDaniel Baluta 		iio_triggered_buffer_cleanup(data->mag_indio_dev);
1448c3a23eccSDaniel Baluta 		iio_trigger_unregister(data->acc_dready_trig);
1449c3a23eccSDaniel Baluta 		iio_trigger_unregister(data->mag_dready_trig);
1450fd3ae7a9SDaniel Baluta 		iio_trigger_unregister(data->motion_trig);
1451c3a23eccSDaniel Baluta 	}
1452c3a23eccSDaniel Baluta 
145320ffac27SDaniel Baluta 	mutex_lock(&data->lock);
145420ffac27SDaniel Baluta 	kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
145520ffac27SDaniel Baluta 	mutex_unlock(&data->lock);
145620ffac27SDaniel Baluta 
145720ffac27SDaniel Baluta 	return 0;
145820ffac27SDaniel Baluta }
145920ffac27SDaniel Baluta 
14603b9c40e6SDaniel Baluta #ifdef CONFIG_PM_SLEEP
14613b9c40e6SDaniel Baluta static int kmx61_suspend(struct device *dev)
14623b9c40e6SDaniel Baluta {
14633b9c40e6SDaniel Baluta 	int ret;
14643b9c40e6SDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev));
14653b9c40e6SDaniel Baluta 
14663b9c40e6SDaniel Baluta 	mutex_lock(&data->lock);
14673b9c40e6SDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG,
14683b9c40e6SDaniel Baluta 			     false);
14693b9c40e6SDaniel Baluta 	mutex_unlock(&data->lock);
14703b9c40e6SDaniel Baluta 
14713b9c40e6SDaniel Baluta 	return ret;
14723b9c40e6SDaniel Baluta }
14733b9c40e6SDaniel Baluta 
14743b9c40e6SDaniel Baluta static int kmx61_resume(struct device *dev)
14753b9c40e6SDaniel Baluta {
14763b9c40e6SDaniel Baluta 	u8 stby = 0;
14773b9c40e6SDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev));
14783b9c40e6SDaniel Baluta 
14793b9c40e6SDaniel Baluta 	if (data->acc_stby)
14803b9c40e6SDaniel Baluta 		stby |= KMX61_ACC_STBY_BIT;
14813b9c40e6SDaniel Baluta 	if (data->mag_stby)
14823b9c40e6SDaniel Baluta 		stby |= KMX61_MAG_STBY_BIT;
14833b9c40e6SDaniel Baluta 
14843b9c40e6SDaniel Baluta 	return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true);
14853b9c40e6SDaniel Baluta }
14863b9c40e6SDaniel Baluta #endif
1487aff8609aSDaniel Baluta 
1488df1fad80SDaniel Baluta #ifdef CONFIG_PM
1489aff8609aSDaniel Baluta static int kmx61_runtime_suspend(struct device *dev)
1490aff8609aSDaniel Baluta {
1491aff8609aSDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev));
1492aff8609aSDaniel Baluta 	int ret;
1493aff8609aSDaniel Baluta 
1494aff8609aSDaniel Baluta 	mutex_lock(&data->lock);
1495aff8609aSDaniel Baluta 	ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true);
1496aff8609aSDaniel Baluta 	mutex_unlock(&data->lock);
1497aff8609aSDaniel Baluta 
1498aff8609aSDaniel Baluta 	return ret;
1499aff8609aSDaniel Baluta }
1500aff8609aSDaniel Baluta 
1501aff8609aSDaniel Baluta static int kmx61_runtime_resume(struct device *dev)
1502aff8609aSDaniel Baluta {
1503aff8609aSDaniel Baluta 	struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev));
1504aff8609aSDaniel Baluta 	u8 stby = 0;
1505aff8609aSDaniel Baluta 
1506aff8609aSDaniel Baluta 	if (!data->acc_ps)
1507aff8609aSDaniel Baluta 		stby |= KMX61_ACC_STBY_BIT;
1508aff8609aSDaniel Baluta 	if (!data->mag_ps)
1509aff8609aSDaniel Baluta 		stby |= KMX61_MAG_STBY_BIT;
1510aff8609aSDaniel Baluta 
1511aff8609aSDaniel Baluta 	return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true);
1512aff8609aSDaniel Baluta }
1513aff8609aSDaniel Baluta #endif
1514aff8609aSDaniel Baluta 
1515aff8609aSDaniel Baluta static const struct dev_pm_ops kmx61_pm_ops = {
15163b9c40e6SDaniel Baluta 	SET_SYSTEM_SLEEP_PM_OPS(kmx61_suspend, kmx61_resume)
1517aff8609aSDaniel Baluta 	SET_RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL)
1518aff8609aSDaniel Baluta };
1519aff8609aSDaniel Baluta 
1520b25862c5SDaniel Baluta static const struct acpi_device_id kmx61_acpi_match[] = {
1521b25862c5SDaniel Baluta 	{"KMX61021", 0},
1522b25862c5SDaniel Baluta 	{}
1523b25862c5SDaniel Baluta };
1524b25862c5SDaniel Baluta 
1525b25862c5SDaniel Baluta MODULE_DEVICE_TABLE(acpi, kmx61_acpi_match);
1526b25862c5SDaniel Baluta 
152720ffac27SDaniel Baluta static const struct i2c_device_id kmx61_id[] = {
152820ffac27SDaniel Baluta 	{"kmx611021", 0},
152920ffac27SDaniel Baluta 	{}
153020ffac27SDaniel Baluta };
153120ffac27SDaniel Baluta 
153220ffac27SDaniel Baluta MODULE_DEVICE_TABLE(i2c, kmx61_id);
153320ffac27SDaniel Baluta 
153420ffac27SDaniel Baluta static struct i2c_driver kmx61_driver = {
153520ffac27SDaniel Baluta 	.driver = {
153620ffac27SDaniel Baluta 		.name = KMX61_DRV_NAME,
1537b25862c5SDaniel Baluta 		.acpi_match_table = ACPI_PTR(kmx61_acpi_match),
1538aff8609aSDaniel Baluta 		.pm = &kmx61_pm_ops,
153920ffac27SDaniel Baluta 	},
154020ffac27SDaniel Baluta 	.probe		= kmx61_probe,
154120ffac27SDaniel Baluta 	.remove		= kmx61_remove,
154220ffac27SDaniel Baluta 	.id_table	= kmx61_id,
154320ffac27SDaniel Baluta };
154420ffac27SDaniel Baluta 
154520ffac27SDaniel Baluta module_i2c_driver(kmx61_driver);
154620ffac27SDaniel Baluta 
154720ffac27SDaniel Baluta MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
154820ffac27SDaniel Baluta MODULE_DESCRIPTION("KMX61 accelerometer/magnetometer driver");
154920ffac27SDaniel Baluta MODULE_LICENSE("GPL v2");
1550