diff options
author | Daniel Baluta <daniel.baluta@intel.com> | 2014-12-03 08:31:53 -0500 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2014-12-12 08:54:33 -0500 |
commit | fd3ae7a9f21c2a51a1d220bc7a7c3b45ab5e6ad1 (patch) | |
tree | 6c520800e07a37e1fa0d83ea8708da7eef705953 /drivers/iio/imu/kmx61.c | |
parent | c3a23ecc0901f624b681bbfbc4829766c5aa3070 (diff) |
iio: imu: kmx61: Add support for any motion trigger
We use WUFE (Wake Up from Sleep Engine) and BTSE (Back to Sleep Engine)
to detect general motion input.
Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio/imu/kmx61.c')
-rw-r--r-- | drivers/iio/imu/kmx61.c | 433 |
1 files changed, 426 insertions, 7 deletions
diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index b8080fc54a76..bda9c40c020b 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/pm_runtime.h> | 20 | #include <linux/pm_runtime.h> |
21 | #include <linux/iio/iio.h> | 21 | #include <linux/iio/iio.h> |
22 | #include <linux/iio/sysfs.h> | 22 | #include <linux/iio/sysfs.h> |
23 | #include <linux/iio/events.h> | ||
23 | #include <linux/iio/trigger.h> | 24 | #include <linux/iio/trigger.h> |
24 | #include <linux/iio/buffer.h> | 25 | #include <linux/iio/buffer.h> |
25 | #include <linux/iio/triggered_buffer.h> | 26 | #include <linux/iio/triggered_buffer.h> |
@@ -30,6 +31,8 @@ | |||
30 | #define KMX61_IRQ_NAME "kmx61_event" | 31 | #define KMX61_IRQ_NAME "kmx61_event" |
31 | 32 | ||
32 | #define KMX61_REG_WHO_AM_I 0x00 | 33 | #define KMX61_REG_WHO_AM_I 0x00 |
34 | #define KMX61_REG_INS1 0x01 | ||
35 | #define KMX61_REG_INS2 0x02 | ||
33 | 36 | ||
34 | /* | 37 | /* |
35 | * three 16-bit accelerometer output registers for X/Y/Z axis | 38 | * three 16-bit accelerometer output registers for X/Y/Z axis |
@@ -63,20 +66,36 @@ | |||
63 | #define KMX61_REG_INL 0x28 | 66 | #define KMX61_REG_INL 0x28 |
64 | #define KMX61_REG_STBY 0x29 | 67 | #define KMX61_REG_STBY 0x29 |
65 | #define KMX61_REG_CTRL1 0x2A | 68 | #define KMX61_REG_CTRL1 0x2A |
69 | #define KMX61_REG_CTRL2 0x2B | ||
66 | #define KMX61_REG_ODCNTL 0x2C | 70 | #define KMX61_REG_ODCNTL 0x2C |
67 | #define KMX61_REG_INC1 0x2D | 71 | #define KMX61_REG_INC1 0x2D |
68 | 72 | ||
73 | #define KMX61_REG_WUF_THRESH 0x3D | ||
74 | #define KMX61_REG_WUF_TIMER 0x3E | ||
75 | |||
69 | #define KMX61_ACC_STBY_BIT BIT(0) | 76 | #define KMX61_ACC_STBY_BIT BIT(0) |
70 | #define KMX61_MAG_STBY_BIT BIT(1) | 77 | #define KMX61_MAG_STBY_BIT BIT(1) |
71 | #define KMX61_ACT_STBY_BIT BIT(7) | 78 | #define KMX61_ACT_STBY_BIT BIT(7) |
72 | 79 | ||
73 | #define KMX61_ALL_STBY (KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT) | 80 | #define KMX61_ALL_STBY (KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT) |
74 | 81 | ||
82 | #define KMX61_REG_INS1_BIT_WUFS BIT(1) | ||
83 | |||
84 | #define KMX61_REG_INS2_BIT_ZP BIT(0) | ||
85 | #define KMX61_REG_INS2_BIT_ZN BIT(1) | ||
86 | #define KMX61_REG_INS2_BIT_YP BIT(2) | ||
87 | #define KMX61_REG_INS2_BIT_YN BIT(3) | ||
88 | #define KMX61_REG_INS2_BIT_XP BIT(4) | ||
89 | #define KMX61_REG_INS2_BIT_XN BIT(5) | ||
90 | |||
75 | #define KMX61_REG_CTRL1_GSEL_MASK 0x03 | 91 | #define KMX61_REG_CTRL1_GSEL_MASK 0x03 |
76 | 92 | ||
77 | #define KMX61_REG_CTRL1_BIT_RES BIT(4) | 93 | #define KMX61_REG_CTRL1_BIT_RES BIT(4) |
78 | #define KMX61_REG_CTRL1_BIT_DRDYE BIT(5) | 94 | #define KMX61_REG_CTRL1_BIT_DRDYE BIT(5) |
95 | #define KMX61_REG_CTRL1_BIT_WUFE BIT(6) | ||
96 | #define KMX61_REG_CTRL1_BIT_BTSE BIT(7) | ||
79 | 97 | ||
98 | #define KMX61_REG_INC1_BIT_WUFS BIT(0) | ||
80 | #define KMX61_REG_INC1_BIT_DRDYM BIT(1) | 99 | #define KMX61_REG_INC1_BIT_DRDYM BIT(1) |
81 | #define KMX61_REG_INC1_BIT_DRDYA BIT(2) | 100 | #define KMX61_REG_INC1_BIT_DRDYA BIT(2) |
82 | #define KMX61_REG_INC1_BIT_IEN BIT(5) | 101 | #define KMX61_REG_INC1_BIT_IEN BIT(5) |
@@ -86,6 +105,11 @@ | |||
86 | #define KMX61_ACC_ODR_MASK 0x0F | 105 | #define KMX61_ACC_ODR_MASK 0x0F |
87 | #define KMX61_MAG_ODR_MASK 0xF0 | 106 | #define KMX61_MAG_ODR_MASK 0xF0 |
88 | 107 | ||
108 | #define KMX61_OWUF_MASK 0x7 | ||
109 | |||
110 | #define KMX61_DEFAULT_WAKE_THRESH 1 | ||
111 | #define KMX61_DEFAULT_WAKE_DURATION 1 | ||
112 | |||
89 | #define KMX61_SLEEP_DELAY_MS 2000 | 113 | #define KMX61_SLEEP_DELAY_MS 2000 |
90 | 114 | ||
91 | #define KMX61_CHIP_ID 0x12 | 115 | #define KMX61_CHIP_ID 0x12 |
@@ -111,11 +135,16 @@ struct kmx61_data { | |||
111 | /* config bits */ | 135 | /* config bits */ |
112 | u8 range; | 136 | u8 range; |
113 | u8 odr_bits; | 137 | u8 odr_bits; |
138 | u8 wake_thresh; | ||
139 | u8 wake_duration; | ||
114 | 140 | ||
115 | /* accelerometer specific data */ | 141 | /* accelerometer specific data */ |
116 | struct iio_dev *acc_indio_dev; | 142 | struct iio_dev *acc_indio_dev; |
117 | struct iio_trigger *acc_dready_trig; | 143 | struct iio_trigger *acc_dready_trig; |
144 | struct iio_trigger *motion_trig; | ||
118 | bool acc_dready_trig_on; | 145 | bool acc_dready_trig_on; |
146 | bool motion_trig_on; | ||
147 | bool ev_enable_state; | ||
119 | 148 | ||
120 | /* magnetometer specific data */ | 149 | /* magnetometer specific data */ |
121 | struct iio_dev *mag_indio_dev; | 150 | struct iio_dev *mag_indio_dev; |
@@ -154,6 +183,23 @@ static const struct { | |||
154 | {3, 125000, 0x0A}, | 183 | {3, 125000, 0x0A}, |
155 | {6, 250000, 0x0B} }; | 184 | {6, 250000, 0x0B} }; |
156 | 185 | ||
186 | static const struct { | ||
187 | int val; | ||
188 | int val2; | ||
189 | int odr_bits; | ||
190 | } kmx61_wake_up_odr_table[] = { {0, 781000, 0x00}, | ||
191 | {1, 563000, 0x01}, | ||
192 | {3, 125000, 0x02}, | ||
193 | {6, 250000, 0x03}, | ||
194 | {12, 500000, 0x04}, | ||
195 | {25, 0, 0x05}, | ||
196 | {50, 0, 0x06}, | ||
197 | {100, 0, 0x06}, | ||
198 | {200, 0, 0x06}, | ||
199 | {400, 0, 0x06}, | ||
200 | {800, 0, 0x06}, | ||
201 | {1600, 0, 0x06} }; | ||
202 | |||
157 | static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326"); | 203 | static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326"); |
158 | static IIO_CONST_ATTR(magn_scale_available, "0.001465"); | 204 | static IIO_CONST_ATTR(magn_scale_available, "0.001465"); |
159 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( | 205 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( |
@@ -179,6 +225,14 @@ static const struct attribute_group kmx61_mag_attribute_group = { | |||
179 | .attrs = kmx61_mag_attributes, | 225 | .attrs = kmx61_mag_attributes, |
180 | }; | 226 | }; |
181 | 227 | ||
228 | static const struct iio_event_spec kmx61_event = { | ||
229 | .type = IIO_EV_TYPE_THRESH, | ||
230 | .dir = IIO_EV_DIR_EITHER, | ||
231 | .mask_separate = BIT(IIO_EV_INFO_VALUE) | | ||
232 | BIT(IIO_EV_INFO_ENABLE) | | ||
233 | BIT(IIO_EV_INFO_PERIOD), | ||
234 | }; | ||
235 | |||
182 | #define KMX61_ACC_CHAN(_axis) { \ | 236 | #define KMX61_ACC_CHAN(_axis) { \ |
183 | .type = IIO_ACCEL, \ | 237 | .type = IIO_ACCEL, \ |
184 | .modified = 1, \ | 238 | .modified = 1, \ |
@@ -195,6 +249,8 @@ static const struct attribute_group kmx61_mag_attribute_group = { | |||
195 | .shift = 4, \ | 249 | .shift = 4, \ |
196 | .endianness = IIO_LE, \ | 250 | .endianness = IIO_LE, \ |
197 | }, \ | 251 | }, \ |
252 | .event_spec = &kmx61_event, \ | ||
253 | .num_event_specs = 1 \ | ||
198 | } | 254 | } |
199 | 255 | ||
200 | #define KMX61_MAG_CHAN(_axis) { \ | 256 | #define KMX61_MAG_CHAN(_axis) { \ |
@@ -250,6 +306,31 @@ static int kmx61_convert_freq_to_bit(int val, int val2) | |||
250 | return -EINVAL; | 306 | return -EINVAL; |
251 | } | 307 | } |
252 | 308 | ||
309 | static int kmx61_convert_bit_to_freq(u8 odr_bits, int *val, int *val2) | ||
310 | { | ||
311 | int i; | ||
312 | |||
313 | for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) | ||
314 | if (odr_bits == kmx61_samp_freq_table[i].odr_bits) { | ||
315 | *val = kmx61_samp_freq_table[i].val; | ||
316 | *val2 = kmx61_samp_freq_table[i].val2; | ||
317 | return 0; | ||
318 | } | ||
319 | return -EINVAL; | ||
320 | } | ||
321 | |||
322 | |||
323 | static int kmx61_convert_wake_up_odr_to_bit(int val, int val2) | ||
324 | { | ||
325 | int i; | ||
326 | |||
327 | for (i = 0; i < ARRAY_SIZE(kmx61_wake_up_odr_table); ++i) | ||
328 | if (kmx61_wake_up_odr_table[i].val == val && | ||
329 | kmx61_wake_up_odr_table[i].val2 == val2) | ||
330 | return kmx61_wake_up_odr_table[i].odr_bits; | ||
331 | return -EINVAL; | ||
332 | } | ||
333 | |||
253 | /** | 334 | /** |
254 | * kmx61_set_mode() - set KMX61 device operating mode | 335 | * kmx61_set_mode() - set KMX61 device operating mode |
255 | * @data - kmx61 device private data pointer | 336 | * @data - kmx61 device private data pointer |
@@ -338,6 +419,21 @@ static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device) | |||
338 | return 0; | 419 | return 0; |
339 | } | 420 | } |
340 | 421 | ||
422 | int kmx61_set_wake_up_odr(struct kmx61_data *data, int val, int val2) | ||
423 | { | ||
424 | int ret, odr_bits; | ||
425 | |||
426 | odr_bits = kmx61_convert_wake_up_odr_to_bit(val, val2); | ||
427 | if (odr_bits < 0) | ||
428 | return odr_bits; | ||
429 | |||
430 | ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL2, | ||
431 | odr_bits); | ||
432 | if (ret < 0) | ||
433 | dev_err(&data->client->dev, "Error writing reg_ctrl2\n"); | ||
434 | return ret; | ||
435 | } | ||
436 | |||
341 | static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) | 437 | static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) |
342 | { | 438 | { |
343 | int ret; | 439 | int ret; |
@@ -369,6 +465,12 @@ static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) | |||
369 | if (ret < 0) | 465 | if (ret < 0) |
370 | return ret; | 466 | return ret; |
371 | 467 | ||
468 | if (device & KMX61_ACC) { | ||
469 | ret = kmx61_set_wake_up_odr(data, val, val2); | ||
470 | if (ret) | ||
471 | return ret; | ||
472 | } | ||
473 | |||
372 | return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); | 474 | return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); |
373 | } | 475 | } |
374 | 476 | ||
@@ -449,7 +551,7 @@ static int kmx61_set_scale(struct kmx61_data *data, u16 uscale) | |||
449 | 551 | ||
450 | static int kmx61_chip_init(struct kmx61_data *data) | 552 | static int kmx61_chip_init(struct kmx61_data *data) |
451 | { | 553 | { |
452 | int ret; | 554 | int ret, val, val2; |
453 | 555 | ||
454 | ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I); | 556 | ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I); |
455 | if (ret < 0) { | 557 | if (ret < 0) { |
@@ -476,11 +578,23 @@ static int kmx61_chip_init(struct kmx61_data *data) | |||
476 | } | 578 | } |
477 | data->odr_bits = ret; | 579 | data->odr_bits = ret; |
478 | 580 | ||
581 | /* set output data rate for wake up (motion detection) function */ | ||
582 | ret = kmx61_convert_bit_to_freq(data->odr_bits, &val, &val2); | ||
583 | if (ret < 0) | ||
584 | return ret; | ||
585 | |||
586 | ret = kmx61_set_wake_up_odr(data, val, val2); | ||
587 | if (ret < 0) | ||
588 | return ret; | ||
589 | |||
479 | /* set acc/magn to OPERATION mode */ | 590 | /* set acc/magn to OPERATION mode */ |
480 | ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true); | 591 | ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true); |
481 | if (ret < 0) | 592 | if (ret < 0) |
482 | return ret; | 593 | return ret; |
483 | 594 | ||
595 | data->wake_thresh = KMX61_DEFAULT_WAKE_THRESH; | ||
596 | data->wake_duration = KMX61_DEFAULT_WAKE_DURATION; | ||
597 | |||
484 | return 0; | 598 | return 0; |
485 | } | 599 | } |
486 | 600 | ||
@@ -547,6 +661,87 @@ static int kmx61_setup_new_data_interrupt(struct kmx61_data *data, | |||
547 | return 0; | 661 | return 0; |
548 | } | 662 | } |
549 | 663 | ||
664 | static int kmx61_chip_update_thresholds(struct kmx61_data *data) | ||
665 | { | ||
666 | int ret; | ||
667 | |||
668 | ret = i2c_smbus_write_byte_data(data->client, | ||
669 | KMX61_REG_WUF_TIMER, | ||
670 | data->wake_duration); | ||
671 | if (ret < 0) { | ||
672 | dev_err(&data->client->dev, "Errow writing reg_wuf_timer\n"); | ||
673 | return ret; | ||
674 | } | ||
675 | |||
676 | ret = i2c_smbus_write_byte_data(data->client, | ||
677 | KMX61_REG_WUF_THRESH, | ||
678 | data->wake_thresh); | ||
679 | if (ret < 0) { | ||
680 | dev_err(&data->client->dev, "Error writing reg_wuf_thresh\n"); | ||
681 | return ret; | ||
682 | } | ||
683 | |||
684 | return 0; | ||
685 | } | ||
686 | |||
687 | static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data, | ||
688 | bool status, u8 device) | ||
689 | { | ||
690 | u8 mode; | ||
691 | int ret; | ||
692 | |||
693 | ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); | ||
694 | if (ret < 0) | ||
695 | return ret; | ||
696 | |||
697 | ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); | ||
698 | if (ret < 0) | ||
699 | return ret; | ||
700 | |||
701 | ret = kmx61_chip_update_thresholds(data); | ||
702 | if (ret < 0) | ||
703 | return ret; | ||
704 | |||
705 | ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INC1); | ||
706 | if (ret < 0) { | ||
707 | dev_err(&data->client->dev, "Error reading reg_inc1\n"); | ||
708 | return ret; | ||
709 | } | ||
710 | if (status) | ||
711 | ret |= (KMX61_REG_INC1_BIT_IEN | KMX61_REG_INC1_BIT_WUFS); | ||
712 | else | ||
713 | ret &= ~(KMX61_REG_INC1_BIT_IEN | KMX61_REG_INC1_BIT_WUFS); | ||
714 | |||
715 | ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_INC1, ret); | ||
716 | if (ret < 0) { | ||
717 | dev_err(&data->client->dev, "Error writing reg_inc1\n"); | ||
718 | return ret; | ||
719 | } | ||
720 | |||
721 | ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); | ||
722 | if (ret < 0) { | ||
723 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | ||
724 | return ret; | ||
725 | } | ||
726 | |||
727 | if (status) | ||
728 | ret |= KMX61_REG_CTRL1_BIT_WUFE | KMX61_REG_CTRL1_BIT_BTSE; | ||
729 | else | ||
730 | ret &= ~(KMX61_REG_CTRL1_BIT_WUFE | KMX61_REG_CTRL1_BIT_BTSE); | ||
731 | |||
732 | ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); | ||
733 | if (ret < 0) { | ||
734 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); | ||
735 | return ret; | ||
736 | } | ||
737 | mode |= KMX61_ACT_STBY_BIT; | ||
738 | ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); | ||
739 | if (ret) | ||
740 | return ret; | ||
741 | |||
742 | return 0; | ||
743 | } | ||
744 | |||
550 | /** | 745 | /** |
551 | * kmx61_set_power_state() - set power state for kmx61 @device | 746 | * kmx61_set_power_state() - set power state for kmx61 @device |
552 | * @data - kmx61 device private pointer | 747 | * @data - kmx61 device private pointer |
@@ -707,12 +902,111 @@ static int kmx61_write_raw(struct iio_dev *indio_dev, | |||
707 | } | 902 | } |
708 | } | 903 | } |
709 | 904 | ||
905 | static int kmx61_read_event(struct iio_dev *indio_dev, | ||
906 | const struct iio_chan_spec *chan, | ||
907 | enum iio_event_type type, | ||
908 | enum iio_event_direction dir, | ||
909 | enum iio_event_info info, | ||
910 | int *val, int *val2) | ||
911 | { | ||
912 | struct kmx61_data *data = kmx61_get_data(indio_dev); | ||
913 | |||
914 | *val2 = 0; | ||
915 | switch (info) { | ||
916 | case IIO_EV_INFO_VALUE: | ||
917 | *val = data->wake_thresh; | ||
918 | break; | ||
919 | case IIO_EV_INFO_PERIOD: | ||
920 | *val = data->wake_duration; | ||
921 | break; | ||
922 | default: | ||
923 | return -EINVAL; | ||
924 | } | ||
925 | |||
926 | return IIO_VAL_INT; | ||
927 | } | ||
928 | |||
929 | static int kmx61_write_event(struct iio_dev *indio_dev, | ||
930 | const struct iio_chan_spec *chan, | ||
931 | enum iio_event_type type, | ||
932 | enum iio_event_direction dir, | ||
933 | enum iio_event_info info, | ||
934 | int val, int val2) | ||
935 | { | ||
936 | struct kmx61_data *data = kmx61_get_data(indio_dev); | ||
937 | |||
938 | if (data->ev_enable_state) | ||
939 | return -EBUSY; | ||
940 | |||
941 | switch (info) { | ||
942 | case IIO_EV_INFO_VALUE: | ||
943 | data->wake_thresh = val; | ||
944 | break; | ||
945 | case IIO_EV_INFO_PERIOD: | ||
946 | data->wake_duration = val; | ||
947 | break; | ||
948 | default: | ||
949 | return -EINVAL; | ||
950 | } | ||
951 | |||
952 | return IIO_VAL_INT; | ||
953 | } | ||
954 | |||
955 | static int kmx61_read_event_config(struct iio_dev *indio_dev, | ||
956 | const struct iio_chan_spec *chan, | ||
957 | enum iio_event_type type, | ||
958 | enum iio_event_direction dir) | ||
959 | { | ||
960 | struct kmx61_data *data = kmx61_get_data(indio_dev); | ||
961 | |||
962 | return data->ev_enable_state; | ||
963 | } | ||
964 | |||
965 | static int kmx61_write_event_config(struct iio_dev *indio_dev, | ||
966 | const struct iio_chan_spec *chan, | ||
967 | enum iio_event_type type, | ||
968 | enum iio_event_direction dir, | ||
969 | int state) | ||
970 | { | ||
971 | struct kmx61_data *data = kmx61_get_data(indio_dev); | ||
972 | int ret; | ||
973 | |||
974 | if (state && data->ev_enable_state) | ||
975 | return 0; | ||
976 | |||
977 | mutex_lock(&data->lock); | ||
978 | |||
979 | if (!state && data->motion_trig_on) { | ||
980 | data->ev_enable_state = 0; | ||
981 | mutex_unlock(&data->lock); | ||
982 | return 0; | ||
983 | } | ||
984 | |||
985 | ret = kmx61_set_power_state(data, state, KMX61_ACC); | ||
986 | if (ret < 0) { | ||
987 | mutex_unlock(&data->lock); | ||
988 | return ret; | ||
989 | } | ||
990 | |||
991 | ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC); | ||
992 | if (ret < 0) { | ||
993 | kmx61_set_power_state(data, false, KMX61_ACC); | ||
994 | mutex_unlock(&data->lock); | ||
995 | return ret; | ||
996 | } | ||
997 | |||
998 | data->ev_enable_state = state; | ||
999 | mutex_unlock(&data->lock); | ||
1000 | |||
1001 | return 0; | ||
1002 | } | ||
1003 | |||
710 | static int kmx61_acc_validate_trigger(struct iio_dev *indio_dev, | 1004 | static int kmx61_acc_validate_trigger(struct iio_dev *indio_dev, |
711 | struct iio_trigger *trig) | 1005 | struct iio_trigger *trig) |
712 | { | 1006 | { |
713 | struct kmx61_data *data = kmx61_get_data(indio_dev); | 1007 | struct kmx61_data *data = kmx61_get_data(indio_dev); |
714 | 1008 | ||
715 | if (data->acc_dready_trig != trig) | 1009 | if (data->acc_dready_trig != trig && data->motion_trig != trig) |
716 | return -EINVAL; | 1010 | return -EINVAL; |
717 | 1011 | ||
718 | return 0; | 1012 | return 0; |
@@ -734,6 +1028,10 @@ static const struct iio_info kmx61_acc_info = { | |||
734 | .read_raw = kmx61_read_raw, | 1028 | .read_raw = kmx61_read_raw, |
735 | .write_raw = kmx61_write_raw, | 1029 | .write_raw = kmx61_write_raw, |
736 | .attrs = &kmx61_acc_attribute_group, | 1030 | .attrs = &kmx61_acc_attribute_group, |
1031 | .read_event_value = kmx61_read_event, | ||
1032 | .write_event_value = kmx61_write_event, | ||
1033 | .read_event_config = kmx61_read_event_config, | ||
1034 | .write_event_config = kmx61_write_event_config, | ||
737 | .validate_trigger = kmx61_acc_validate_trigger, | 1035 | .validate_trigger = kmx61_acc_validate_trigger, |
738 | }; | 1036 | }; |
739 | 1037 | ||
@@ -753,11 +1051,18 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, | |||
753 | u8 device; | 1051 | u8 device; |
754 | 1052 | ||
755 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | 1053 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); |
756 | struct kmx61_data *data = iio_priv(indio_dev); | 1054 | struct kmx61_data *data = kmx61_get_data(indio_dev); |
757 | 1055 | ||
758 | mutex_lock(&data->lock); | 1056 | mutex_lock(&data->lock); |
759 | 1057 | ||
760 | if (data->acc_dready_trig == trig) | 1058 | if (!state && data->ev_enable_state && data->motion_trig_on) { |
1059 | data->motion_trig_on = false; | ||
1060 | mutex_unlock(&data->lock); | ||
1061 | return 0; | ||
1062 | } | ||
1063 | |||
1064 | |||
1065 | if (data->acc_dready_trig == trig || data->motion_trig) | ||
761 | device = KMX61_ACC; | 1066 | device = KMX61_ACC; |
762 | else | 1067 | else |
763 | device = KMX61_MAG; | 1068 | device = KMX61_MAG; |
@@ -768,7 +1073,10 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, | |||
768 | return ret; | 1073 | return ret; |
769 | } | 1074 | } |
770 | 1075 | ||
771 | ret = kmx61_setup_new_data_interrupt(data, state, device); | 1076 | if (data->acc_dready_trig == trig || data->mag_dready_trig == trig) |
1077 | ret = kmx61_setup_new_data_interrupt(data, state, device); | ||
1078 | else | ||
1079 | ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC); | ||
772 | if (ret < 0) { | 1080 | if (ret < 0) { |
773 | kmx61_set_power_state(data, false, device); | 1081 | kmx61_set_power_state(data, false, device); |
774 | mutex_unlock(&data->lock); | 1082 | mutex_unlock(&data->lock); |
@@ -777,8 +1085,10 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, | |||
777 | 1085 | ||
778 | if (data->acc_dready_trig == trig) | 1086 | if (data->acc_dready_trig == trig) |
779 | data->acc_dready_trig_on = state; | 1087 | data->acc_dready_trig_on = state; |
780 | else | 1088 | else if (data->mag_dready_trig == trig) |
781 | data->mag_dready_trig_on = state; | 1089 | data->mag_dready_trig_on = state; |
1090 | else | ||
1091 | data->motion_trig_on = state; | ||
782 | 1092 | ||
783 | mutex_unlock(&data->lock); | 1093 | mutex_unlock(&data->lock); |
784 | 1094 | ||
@@ -806,6 +1116,99 @@ static const struct iio_trigger_ops kmx61_trigger_ops = { | |||
806 | .owner = THIS_MODULE, | 1116 | .owner = THIS_MODULE, |
807 | }; | 1117 | }; |
808 | 1118 | ||
1119 | static irqreturn_t kmx61_event_handler(int irq, void *private) | ||
1120 | { | ||
1121 | struct kmx61_data *data = private; | ||
1122 | struct iio_dev *indio_dev = data->acc_indio_dev; | ||
1123 | int ret; | ||
1124 | |||
1125 | ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS1); | ||
1126 | if (ret < 0) { | ||
1127 | dev_err(&data->client->dev, "Error reading reg_ins1\n"); | ||
1128 | goto ack_intr; | ||
1129 | } | ||
1130 | |||
1131 | if (ret & KMX61_REG_INS1_BIT_WUFS) { | ||
1132 | ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS2); | ||
1133 | if (ret < 0) { | ||
1134 | dev_err(&data->client->dev, "Error reading reg_ins2\n"); | ||
1135 | goto ack_intr; | ||
1136 | } | ||
1137 | |||
1138 | if (ret & KMX61_REG_INS2_BIT_XN) | ||
1139 | iio_push_event(indio_dev, | ||
1140 | IIO_MOD_EVENT_CODE(IIO_ACCEL, | ||
1141 | 0, | ||
1142 | IIO_MOD_X, | ||
1143 | IIO_EV_TYPE_THRESH, | ||
1144 | IIO_EV_DIR_FALLING), | ||
1145 | 0); | ||
1146 | |||
1147 | if (ret & KMX61_REG_INS2_BIT_XP) | ||
1148 | iio_push_event(indio_dev, | ||
1149 | IIO_MOD_EVENT_CODE(IIO_ACCEL, | ||
1150 | 0, | ||
1151 | IIO_MOD_X, | ||
1152 | IIO_EV_TYPE_THRESH, | ||
1153 | IIO_EV_DIR_RISING), | ||
1154 | 0); | ||
1155 | |||
1156 | if (ret & KMX61_REG_INS2_BIT_YN) | ||
1157 | iio_push_event(indio_dev, | ||
1158 | IIO_MOD_EVENT_CODE(IIO_ACCEL, | ||
1159 | 0, | ||
1160 | IIO_MOD_Y, | ||
1161 | IIO_EV_TYPE_THRESH, | ||
1162 | IIO_EV_DIR_FALLING), | ||
1163 | 0); | ||
1164 | |||
1165 | if (ret & KMX61_REG_INS2_BIT_YP) | ||
1166 | iio_push_event(indio_dev, | ||
1167 | IIO_MOD_EVENT_CODE(IIO_ACCEL, | ||
1168 | 0, | ||
1169 | IIO_MOD_Y, | ||
1170 | IIO_EV_TYPE_THRESH, | ||
1171 | IIO_EV_DIR_RISING), | ||
1172 | 0); | ||
1173 | |||
1174 | if (ret & KMX61_REG_INS2_BIT_ZN) | ||
1175 | iio_push_event(indio_dev, | ||
1176 | IIO_MOD_EVENT_CODE(IIO_ACCEL, | ||
1177 | 0, | ||
1178 | IIO_MOD_Z, | ||
1179 | IIO_EV_TYPE_THRESH, | ||
1180 | IIO_EV_DIR_FALLING), | ||
1181 | 0); | ||
1182 | |||
1183 | if (ret & KMX61_REG_INS2_BIT_ZP) | ||
1184 | iio_push_event(indio_dev, | ||
1185 | IIO_MOD_EVENT_CODE(IIO_ACCEL, | ||
1186 | 0, | ||
1187 | IIO_MOD_Z, | ||
1188 | IIO_EV_TYPE_THRESH, | ||
1189 | IIO_EV_DIR_RISING), | ||
1190 | 0); | ||
1191 | } | ||
1192 | |||
1193 | ack_intr: | ||
1194 | ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); | ||
1195 | if (ret < 0) | ||
1196 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | ||
1197 | |||
1198 | ret |= KMX61_REG_CTRL1_BIT_RES; | ||
1199 | ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); | ||
1200 | if (ret < 0) | ||
1201 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | ||
1202 | |||
1203 | ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL); | ||
1204 | if (ret < 0) | ||
1205 | dev_err(&data->client->dev, "Error reading reg_inl\n"); | ||
1206 | |||
1207 | ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS1); | ||
1208 | |||
1209 | return IRQ_HANDLED; | ||
1210 | } | ||
1211 | |||
809 | static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private) | 1212 | static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private) |
810 | { | 1213 | { |
811 | struct kmx61_data *data = private; | 1214 | struct kmx61_data *data = private; |
@@ -815,6 +1218,11 @@ static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private) | |||
815 | if (data->mag_dready_trig_on) | 1218 | if (data->mag_dready_trig_on) |
816 | iio_trigger_poll(data->mag_dready_trig); | 1219 | iio_trigger_poll(data->mag_dready_trig); |
817 | 1220 | ||
1221 | if (data->motion_trig_on) | ||
1222 | iio_trigger_poll(data->motion_trig); | ||
1223 | |||
1224 | if (data->ev_enable_state) | ||
1225 | return IRQ_WAKE_THREAD; | ||
818 | return IRQ_HANDLED; | 1226 | return IRQ_HANDLED; |
819 | } | 1227 | } |
820 | 1228 | ||
@@ -982,7 +1390,7 @@ static int kmx61_probe(struct i2c_client *client, | |||
982 | if (client->irq >= 0) { | 1390 | if (client->irq >= 0) { |
983 | ret = devm_request_threaded_irq(&client->dev, client->irq, | 1391 | ret = devm_request_threaded_irq(&client->dev, client->irq, |
984 | kmx61_data_rdy_trig_poll, | 1392 | kmx61_data_rdy_trig_poll, |
985 | NULL, | 1393 | kmx61_event_handler, |
986 | IRQF_TRIGGER_RISING, | 1394 | IRQF_TRIGGER_RISING, |
987 | KMX61_IRQ_NAME, | 1395 | KMX61_IRQ_NAME, |
988 | data); | 1396 | data); |
@@ -1003,6 +1411,14 @@ static int kmx61_probe(struct i2c_client *client, | |||
1003 | goto err_trigger_unregister; | 1411 | goto err_trigger_unregister; |
1004 | } | 1412 | } |
1005 | 1413 | ||
1414 | data->motion_trig = | ||
1415 | kmx61_trigger_setup(data, data->acc_indio_dev, | ||
1416 | "any-motion"); | ||
1417 | if (IS_ERR(data->motion_trig)) { | ||
1418 | ret = PTR_ERR(data->motion_trig); | ||
1419 | goto err_trigger_unregister; | ||
1420 | } | ||
1421 | |||
1006 | ret = iio_triggered_buffer_setup(data->acc_indio_dev, | 1422 | ret = iio_triggered_buffer_setup(data->acc_indio_dev, |
1007 | &iio_pollfunc_store_time, | 1423 | &iio_pollfunc_store_time, |
1008 | kmx61_trigger_handler, | 1424 | kmx61_trigger_handler, |
@@ -1060,6 +1476,8 @@ err_trigger_unregister: | |||
1060 | iio_trigger_unregister(data->acc_dready_trig); | 1476 | iio_trigger_unregister(data->acc_dready_trig); |
1061 | if (data->mag_dready_trig) | 1477 | if (data->mag_dready_trig) |
1062 | iio_trigger_unregister(data->mag_dready_trig); | 1478 | iio_trigger_unregister(data->mag_dready_trig); |
1479 | if (data->motion_trig) | ||
1480 | iio_trigger_unregister(data->motion_trig); | ||
1063 | err_chip_uninit: | 1481 | err_chip_uninit: |
1064 | kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); | 1482 | kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); |
1065 | return ret; | 1483 | return ret; |
@@ -1081,6 +1499,7 @@ static int kmx61_remove(struct i2c_client *client) | |||
1081 | iio_triggered_buffer_cleanup(data->mag_indio_dev); | 1499 | iio_triggered_buffer_cleanup(data->mag_indio_dev); |
1082 | iio_trigger_unregister(data->acc_dready_trig); | 1500 | iio_trigger_unregister(data->acc_dready_trig); |
1083 | iio_trigger_unregister(data->mag_dready_trig); | 1501 | iio_trigger_unregister(data->mag_dready_trig); |
1502 | iio_trigger_unregister(data->motion_trig); | ||
1084 | } | 1503 | } |
1085 | 1504 | ||
1086 | mutex_lock(&data->lock); | 1505 | mutex_lock(&data->lock); |