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