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