136edc939SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 220ffac27SDaniel Baluta /* 320ffac27SDaniel Baluta * KMX61 - Kionix 6-axis Accelerometer/Magnetometer 420ffac27SDaniel Baluta * 520ffac27SDaniel Baluta * Copyright (c) 2014, Intel Corporation. 620ffac27SDaniel Baluta * 720ffac27SDaniel Baluta * IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F). 820ffac27SDaniel Baluta */ 920ffac27SDaniel Baluta 1020ffac27SDaniel Baluta #include <linux/module.h> 1120ffac27SDaniel Baluta #include <linux/i2c.h> 12b25862c5SDaniel Baluta #include <linux/acpi.h> 13aff8609aSDaniel Baluta #include <linux/interrupt.h> 143b9c40e6SDaniel Baluta #include <linux/pm.h> 15aff8609aSDaniel Baluta #include <linux/pm_runtime.h> 1620ffac27SDaniel Baluta #include <linux/iio/iio.h> 1720ffac27SDaniel Baluta #include <linux/iio/sysfs.h> 18fd3ae7a9SDaniel Baluta #include <linux/iio/events.h> 19c3a23eccSDaniel Baluta #include <linux/iio/trigger.h> 20c3a23eccSDaniel Baluta #include <linux/iio/buffer.h> 21c3a23eccSDaniel Baluta #include <linux/iio/triggered_buffer.h> 22c3a23eccSDaniel Baluta #include <linux/iio/trigger_consumer.h> 2320ffac27SDaniel Baluta 2420ffac27SDaniel Baluta #define KMX61_DRV_NAME "kmx61" 25c3a23eccSDaniel Baluta #define KMX61_IRQ_NAME "kmx61_event" 2620ffac27SDaniel Baluta 2720ffac27SDaniel Baluta #define KMX61_REG_WHO_AM_I 0x00 28fd3ae7a9SDaniel Baluta #define KMX61_REG_INS1 0x01 29fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2 0x02 3020ffac27SDaniel Baluta 3120ffac27SDaniel Baluta /* 3220ffac27SDaniel Baluta * three 16-bit accelerometer output registers for X/Y/Z axis 3320ffac27SDaniel Baluta * we use only XOUT_L as a base register, all other addresses 3420ffac27SDaniel Baluta * can be obtained by applying an offset and are provided here 3520ffac27SDaniel Baluta * only for clarity. 3620ffac27SDaniel Baluta */ 3720ffac27SDaniel Baluta #define KMX61_ACC_XOUT_L 0x0A 3820ffac27SDaniel Baluta #define KMX61_ACC_XOUT_H 0x0B 3920ffac27SDaniel Baluta #define KMX61_ACC_YOUT_L 0x0C 4020ffac27SDaniel Baluta #define KMX61_ACC_YOUT_H 0x0D 4120ffac27SDaniel Baluta #define KMX61_ACC_ZOUT_L 0x0E 4220ffac27SDaniel Baluta #define KMX61_ACC_ZOUT_H 0x0F 4320ffac27SDaniel Baluta 4420ffac27SDaniel Baluta /* 4520ffac27SDaniel Baluta * one 16-bit temperature output register 4620ffac27SDaniel Baluta */ 4720ffac27SDaniel Baluta #define KMX61_TEMP_L 0x10 4820ffac27SDaniel Baluta #define KMX61_TEMP_H 0x11 4920ffac27SDaniel Baluta 5020ffac27SDaniel Baluta /* 5120ffac27SDaniel Baluta * three 16-bit magnetometer output registers for X/Y/Z axis 5220ffac27SDaniel Baluta */ 5320ffac27SDaniel Baluta #define KMX61_MAG_XOUT_L 0x12 5420ffac27SDaniel Baluta #define KMX61_MAG_XOUT_H 0x13 5520ffac27SDaniel Baluta #define KMX61_MAG_YOUT_L 0x14 5620ffac27SDaniel Baluta #define KMX61_MAG_YOUT_H 0x15 5720ffac27SDaniel Baluta #define KMX61_MAG_ZOUT_L 0x16 5820ffac27SDaniel Baluta #define KMX61_MAG_ZOUT_H 0x17 5920ffac27SDaniel Baluta 60c3a23eccSDaniel Baluta #define KMX61_REG_INL 0x28 6120ffac27SDaniel Baluta #define KMX61_REG_STBY 0x29 6220ffac27SDaniel Baluta #define KMX61_REG_CTRL1 0x2A 63fd3ae7a9SDaniel Baluta #define KMX61_REG_CTRL2 0x2B 6420ffac27SDaniel Baluta #define KMX61_REG_ODCNTL 0x2C 65c3a23eccSDaniel Baluta #define KMX61_REG_INC1 0x2D 6620ffac27SDaniel Baluta 67fd3ae7a9SDaniel Baluta #define KMX61_REG_WUF_THRESH 0x3D 68fd3ae7a9SDaniel Baluta #define KMX61_REG_WUF_TIMER 0x3E 69fd3ae7a9SDaniel Baluta 7020ffac27SDaniel Baluta #define KMX61_ACC_STBY_BIT BIT(0) 7120ffac27SDaniel Baluta #define KMX61_MAG_STBY_BIT BIT(1) 7220ffac27SDaniel Baluta #define KMX61_ACT_STBY_BIT BIT(7) 7320ffac27SDaniel Baluta 7420ffac27SDaniel Baluta #define KMX61_ALL_STBY (KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT) 7520ffac27SDaniel Baluta 76fd3ae7a9SDaniel Baluta #define KMX61_REG_INS1_BIT_WUFS BIT(1) 77fd3ae7a9SDaniel Baluta 78fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_ZP BIT(0) 79fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_ZN BIT(1) 80fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_YP BIT(2) 81fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_YN BIT(3) 82fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_XP BIT(4) 83fd3ae7a9SDaniel Baluta #define KMX61_REG_INS2_BIT_XN BIT(5) 84fd3ae7a9SDaniel Baluta 8520ffac27SDaniel Baluta #define KMX61_REG_CTRL1_GSEL_MASK 0x03 8620ffac27SDaniel Baluta 87c3a23eccSDaniel Baluta #define KMX61_REG_CTRL1_BIT_RES BIT(4) 88c3a23eccSDaniel Baluta #define KMX61_REG_CTRL1_BIT_DRDYE BIT(5) 89fd3ae7a9SDaniel Baluta #define KMX61_REG_CTRL1_BIT_WUFE BIT(6) 90fd3ae7a9SDaniel Baluta #define KMX61_REG_CTRL1_BIT_BTSE BIT(7) 91c3a23eccSDaniel Baluta 92fd3ae7a9SDaniel Baluta #define KMX61_REG_INC1_BIT_WUFS BIT(0) 93c3a23eccSDaniel Baluta #define KMX61_REG_INC1_BIT_DRDYM BIT(1) 94c3a23eccSDaniel Baluta #define KMX61_REG_INC1_BIT_DRDYA BIT(2) 95c3a23eccSDaniel Baluta #define KMX61_REG_INC1_BIT_IEN BIT(5) 96c3a23eccSDaniel Baluta 9720ffac27SDaniel Baluta #define KMX61_ACC_ODR_SHIFT 0 9820ffac27SDaniel Baluta #define KMX61_MAG_ODR_SHIFT 4 9920ffac27SDaniel Baluta #define KMX61_ACC_ODR_MASK 0x0F 10020ffac27SDaniel Baluta #define KMX61_MAG_ODR_MASK 0xF0 10120ffac27SDaniel Baluta 102fd3ae7a9SDaniel Baluta #define KMX61_OWUF_MASK 0x7 103fd3ae7a9SDaniel Baluta 104fd3ae7a9SDaniel Baluta #define KMX61_DEFAULT_WAKE_THRESH 1 105fd3ae7a9SDaniel Baluta #define KMX61_DEFAULT_WAKE_DURATION 1 106fd3ae7a9SDaniel Baluta 107aff8609aSDaniel Baluta #define KMX61_SLEEP_DELAY_MS 2000 108aff8609aSDaniel Baluta 10920ffac27SDaniel Baluta #define KMX61_CHIP_ID 0x12 11020ffac27SDaniel Baluta 11120ffac27SDaniel Baluta /* KMX61 devices */ 11220ffac27SDaniel Baluta #define KMX61_ACC 0x01 11320ffac27SDaniel Baluta #define KMX61_MAG 0x02 11420ffac27SDaniel Baluta 11520ffac27SDaniel Baluta struct kmx61_data { 11620ffac27SDaniel Baluta struct i2c_client *client; 11720ffac27SDaniel Baluta 11820ffac27SDaniel Baluta /* serialize access to non-atomic ops, e.g set_mode */ 11920ffac27SDaniel Baluta struct mutex lock; 12020ffac27SDaniel Baluta 12120ffac27SDaniel Baluta /* standby state */ 12220ffac27SDaniel Baluta bool acc_stby; 12320ffac27SDaniel Baluta bool mag_stby; 12420ffac27SDaniel Baluta 125aff8609aSDaniel Baluta /* power state */ 126aff8609aSDaniel Baluta bool acc_ps; 127aff8609aSDaniel Baluta bool mag_ps; 128aff8609aSDaniel Baluta 12920ffac27SDaniel Baluta /* config bits */ 13020ffac27SDaniel Baluta u8 range; 13120ffac27SDaniel Baluta u8 odr_bits; 132fd3ae7a9SDaniel Baluta u8 wake_thresh; 133fd3ae7a9SDaniel Baluta u8 wake_duration; 13420ffac27SDaniel Baluta 13520ffac27SDaniel Baluta /* accelerometer specific data */ 13620ffac27SDaniel Baluta struct iio_dev *acc_indio_dev; 137c3a23eccSDaniel Baluta struct iio_trigger *acc_dready_trig; 138fd3ae7a9SDaniel Baluta struct iio_trigger *motion_trig; 139c3a23eccSDaniel Baluta bool acc_dready_trig_on; 140fd3ae7a9SDaniel Baluta bool motion_trig_on; 141fd3ae7a9SDaniel Baluta bool ev_enable_state; 14220ffac27SDaniel Baluta 14320ffac27SDaniel Baluta /* magnetometer specific data */ 14420ffac27SDaniel Baluta struct iio_dev *mag_indio_dev; 145c3a23eccSDaniel Baluta struct iio_trigger *mag_dready_trig; 146c3a23eccSDaniel Baluta bool mag_dready_trig_on; 14720ffac27SDaniel Baluta }; 14820ffac27SDaniel Baluta 14920ffac27SDaniel Baluta enum kmx61_range { 15020ffac27SDaniel Baluta KMX61_RANGE_2G, 15120ffac27SDaniel Baluta KMX61_RANGE_4G, 15220ffac27SDaniel Baluta KMX61_RANGE_8G, 15320ffac27SDaniel Baluta }; 15420ffac27SDaniel Baluta 15520ffac27SDaniel Baluta enum kmx61_axis { 15620ffac27SDaniel Baluta KMX61_AXIS_X, 15720ffac27SDaniel Baluta KMX61_AXIS_Y, 15820ffac27SDaniel Baluta KMX61_AXIS_Z, 15920ffac27SDaniel Baluta }; 16020ffac27SDaniel Baluta 16120ffac27SDaniel Baluta static const u16 kmx61_uscale_table[] = {9582, 19163, 38326}; 16220ffac27SDaniel Baluta 16320ffac27SDaniel Baluta static const struct { 16420ffac27SDaniel Baluta int val; 16520ffac27SDaniel Baluta int val2; 166a36385a2SDaniel Baluta } kmx61_samp_freq_table[] = { {12, 500000}, 167a36385a2SDaniel Baluta {25, 0}, 168a36385a2SDaniel Baluta {50, 0}, 169a36385a2SDaniel Baluta {100, 0}, 170a36385a2SDaniel Baluta {200, 0}, 171a36385a2SDaniel Baluta {400, 0}, 172a36385a2SDaniel Baluta {800, 0}, 173a36385a2SDaniel Baluta {1600, 0}, 174a36385a2SDaniel Baluta {0, 781000}, 175a36385a2SDaniel Baluta {1, 563000}, 176a36385a2SDaniel Baluta {3, 125000}, 177a36385a2SDaniel Baluta {6, 250000} }; 17820ffac27SDaniel Baluta 179fd3ae7a9SDaniel Baluta static const struct { 180fd3ae7a9SDaniel Baluta int val; 181fd3ae7a9SDaniel Baluta int val2; 182fd3ae7a9SDaniel Baluta int odr_bits; 183fd3ae7a9SDaniel Baluta } kmx61_wake_up_odr_table[] = { {0, 781000, 0x00}, 184fd3ae7a9SDaniel Baluta {1, 563000, 0x01}, 185fd3ae7a9SDaniel Baluta {3, 125000, 0x02}, 186fd3ae7a9SDaniel Baluta {6, 250000, 0x03}, 187fd3ae7a9SDaniel Baluta {12, 500000, 0x04}, 188fd3ae7a9SDaniel Baluta {25, 0, 0x05}, 189fd3ae7a9SDaniel Baluta {50, 0, 0x06}, 190fd3ae7a9SDaniel Baluta {100, 0, 0x06}, 191fd3ae7a9SDaniel Baluta {200, 0, 0x06}, 192fd3ae7a9SDaniel Baluta {400, 0, 0x06}, 193fd3ae7a9SDaniel Baluta {800, 0, 0x06}, 194fd3ae7a9SDaniel Baluta {1600, 0, 0x06} }; 195fd3ae7a9SDaniel Baluta 19620ffac27SDaniel Baluta static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326"); 19720ffac27SDaniel Baluta static IIO_CONST_ATTR(magn_scale_available, "0.001465"); 19820ffac27SDaniel Baluta static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( 19920ffac27SDaniel Baluta "0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800"); 20020ffac27SDaniel Baluta 20120ffac27SDaniel Baluta static struct attribute *kmx61_acc_attributes[] = { 20220ffac27SDaniel Baluta &iio_const_attr_accel_scale_available.dev_attr.attr, 20320ffac27SDaniel Baluta &iio_const_attr_sampling_frequency_available.dev_attr.attr, 20420ffac27SDaniel Baluta NULL, 20520ffac27SDaniel Baluta }; 20620ffac27SDaniel Baluta 20720ffac27SDaniel Baluta static struct attribute *kmx61_mag_attributes[] = { 20820ffac27SDaniel Baluta &iio_const_attr_magn_scale_available.dev_attr.attr, 20920ffac27SDaniel Baluta &iio_const_attr_sampling_frequency_available.dev_attr.attr, 21020ffac27SDaniel Baluta NULL, 21120ffac27SDaniel Baluta }; 21220ffac27SDaniel Baluta 21320ffac27SDaniel Baluta static const struct attribute_group kmx61_acc_attribute_group = { 21420ffac27SDaniel Baluta .attrs = kmx61_acc_attributes, 21520ffac27SDaniel Baluta }; 21620ffac27SDaniel Baluta 21720ffac27SDaniel Baluta static const struct attribute_group kmx61_mag_attribute_group = { 21820ffac27SDaniel Baluta .attrs = kmx61_mag_attributes, 21920ffac27SDaniel Baluta }; 22020ffac27SDaniel Baluta 221fd3ae7a9SDaniel Baluta static const struct iio_event_spec kmx61_event = { 222fd3ae7a9SDaniel Baluta .type = IIO_EV_TYPE_THRESH, 223fd3ae7a9SDaniel Baluta .dir = IIO_EV_DIR_EITHER, 224fd3ae7a9SDaniel Baluta .mask_separate = BIT(IIO_EV_INFO_VALUE) | 225fd3ae7a9SDaniel Baluta BIT(IIO_EV_INFO_ENABLE) | 226fd3ae7a9SDaniel Baluta BIT(IIO_EV_INFO_PERIOD), 227fd3ae7a9SDaniel Baluta }; 228fd3ae7a9SDaniel Baluta 22920ffac27SDaniel Baluta #define KMX61_ACC_CHAN(_axis) { \ 23020ffac27SDaniel Baluta .type = IIO_ACCEL, \ 23120ffac27SDaniel Baluta .modified = 1, \ 23220ffac27SDaniel Baluta .channel2 = IIO_MOD_ ## _axis, \ 23320ffac27SDaniel Baluta .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 23420ffac27SDaniel Baluta .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 23520ffac27SDaniel Baluta BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 23620ffac27SDaniel Baluta .address = KMX61_ACC, \ 23720ffac27SDaniel Baluta .scan_index = KMX61_AXIS_ ## _axis, \ 23820ffac27SDaniel Baluta .scan_type = { \ 23920ffac27SDaniel Baluta .sign = 's', \ 24020ffac27SDaniel Baluta .realbits = 12, \ 24120ffac27SDaniel Baluta .storagebits = 16, \ 24220ffac27SDaniel Baluta .shift = 4, \ 24320ffac27SDaniel Baluta .endianness = IIO_LE, \ 24420ffac27SDaniel Baluta }, \ 245fd3ae7a9SDaniel Baluta .event_spec = &kmx61_event, \ 246fd3ae7a9SDaniel Baluta .num_event_specs = 1 \ 24720ffac27SDaniel Baluta } 24820ffac27SDaniel Baluta 24920ffac27SDaniel Baluta #define KMX61_MAG_CHAN(_axis) { \ 25020ffac27SDaniel Baluta .type = IIO_MAGN, \ 25120ffac27SDaniel Baluta .modified = 1, \ 25220ffac27SDaniel Baluta .channel2 = IIO_MOD_ ## _axis, \ 25320ffac27SDaniel Baluta .address = KMX61_MAG, \ 25420ffac27SDaniel Baluta .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 25520ffac27SDaniel Baluta .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 25620ffac27SDaniel Baluta BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 25720ffac27SDaniel Baluta .scan_index = KMX61_AXIS_ ## _axis, \ 25820ffac27SDaniel Baluta .scan_type = { \ 25920ffac27SDaniel Baluta .sign = 's', \ 26020ffac27SDaniel Baluta .realbits = 14, \ 26120ffac27SDaniel Baluta .storagebits = 16, \ 26220ffac27SDaniel Baluta .shift = 2, \ 26320ffac27SDaniel Baluta .endianness = IIO_LE, \ 26420ffac27SDaniel Baluta }, \ 26520ffac27SDaniel Baluta } 26620ffac27SDaniel Baluta 26720ffac27SDaniel Baluta static const struct iio_chan_spec kmx61_acc_channels[] = { 26820ffac27SDaniel Baluta KMX61_ACC_CHAN(X), 26920ffac27SDaniel Baluta KMX61_ACC_CHAN(Y), 27020ffac27SDaniel Baluta KMX61_ACC_CHAN(Z), 27120ffac27SDaniel Baluta }; 27220ffac27SDaniel Baluta 27320ffac27SDaniel Baluta static const struct iio_chan_spec kmx61_mag_channels[] = { 27420ffac27SDaniel Baluta KMX61_MAG_CHAN(X), 27520ffac27SDaniel Baluta KMX61_MAG_CHAN(Y), 27620ffac27SDaniel Baluta KMX61_MAG_CHAN(Z), 27720ffac27SDaniel Baluta }; 27820ffac27SDaniel Baluta 27920ffac27SDaniel Baluta static void kmx61_set_data(struct iio_dev *indio_dev, struct kmx61_data *data) 28020ffac27SDaniel Baluta { 28120ffac27SDaniel Baluta struct kmx61_data **priv = iio_priv(indio_dev); 28220ffac27SDaniel Baluta 28320ffac27SDaniel Baluta *priv = data; 28420ffac27SDaniel Baluta } 28520ffac27SDaniel Baluta 28620ffac27SDaniel Baluta static struct kmx61_data *kmx61_get_data(struct iio_dev *indio_dev) 28720ffac27SDaniel Baluta { 28820ffac27SDaniel Baluta return *(struct kmx61_data **)iio_priv(indio_dev); 28920ffac27SDaniel Baluta } 29020ffac27SDaniel Baluta 29120ffac27SDaniel Baluta static int kmx61_convert_freq_to_bit(int val, int val2) 29220ffac27SDaniel Baluta { 29320ffac27SDaniel Baluta int i; 29420ffac27SDaniel Baluta 29520ffac27SDaniel Baluta for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) 29620ffac27SDaniel Baluta if (val == kmx61_samp_freq_table[i].val && 29720ffac27SDaniel Baluta val2 == kmx61_samp_freq_table[i].val2) 298a36385a2SDaniel Baluta return i; 29920ffac27SDaniel Baluta return -EINVAL; 30020ffac27SDaniel Baluta } 30120ffac27SDaniel Baluta 302fd3ae7a9SDaniel Baluta static int kmx61_convert_wake_up_odr_to_bit(int val, int val2) 303fd3ae7a9SDaniel Baluta { 304fd3ae7a9SDaniel Baluta int i; 305fd3ae7a9SDaniel Baluta 306fd3ae7a9SDaniel Baluta for (i = 0; i < ARRAY_SIZE(kmx61_wake_up_odr_table); ++i) 307fd3ae7a9SDaniel Baluta if (kmx61_wake_up_odr_table[i].val == val && 308fd3ae7a9SDaniel Baluta kmx61_wake_up_odr_table[i].val2 == val2) 309fd3ae7a9SDaniel Baluta return kmx61_wake_up_odr_table[i].odr_bits; 310fd3ae7a9SDaniel Baluta return -EINVAL; 311fd3ae7a9SDaniel Baluta } 312fd3ae7a9SDaniel Baluta 31320ffac27SDaniel Baluta /** 31420ffac27SDaniel Baluta * kmx61_set_mode() - set KMX61 device operating mode 315*0d674449SLee Jones * @data: kmx61 device private data pointer 316*0d674449SLee Jones * @mode: bitmask, indicating operating mode for @device 317*0d674449SLee Jones * @device: bitmask, indicating device for which @mode needs to be set 318*0d674449SLee Jones * @update: update stby bits stored in device's private @data 31920ffac27SDaniel Baluta * 32020ffac27SDaniel Baluta * For each sensor (accelerometer/magnetometer) there are two operating modes 32120ffac27SDaniel Baluta * STANDBY and OPERATION. Neither accel nor magn can be disabled independently 32220ffac27SDaniel Baluta * if they are both enabled. Internal sensors state is saved in acc_stby and 32320ffac27SDaniel Baluta * mag_stby members of driver's private @data. 32420ffac27SDaniel Baluta */ 32520ffac27SDaniel Baluta static int kmx61_set_mode(struct kmx61_data *data, u8 mode, u8 device, 32620ffac27SDaniel Baluta bool update) 32720ffac27SDaniel Baluta { 32820ffac27SDaniel Baluta int ret; 32920ffac27SDaniel Baluta int acc_stby = -1, mag_stby = -1; 33020ffac27SDaniel Baluta 33120ffac27SDaniel Baluta ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY); 33220ffac27SDaniel Baluta if (ret < 0) { 33320ffac27SDaniel Baluta dev_err(&data->client->dev, "Error reading reg_stby\n"); 33420ffac27SDaniel Baluta return ret; 33520ffac27SDaniel Baluta } 33620ffac27SDaniel Baluta if (device & KMX61_ACC) { 33720ffac27SDaniel Baluta if (mode & KMX61_ACC_STBY_BIT) { 33820ffac27SDaniel Baluta ret |= KMX61_ACC_STBY_BIT; 33920ffac27SDaniel Baluta acc_stby = 1; 34020ffac27SDaniel Baluta } else { 34120ffac27SDaniel Baluta ret &= ~KMX61_ACC_STBY_BIT; 34220ffac27SDaniel Baluta acc_stby = 0; 34320ffac27SDaniel Baluta } 34420ffac27SDaniel Baluta } 34520ffac27SDaniel Baluta 34620ffac27SDaniel Baluta if (device & KMX61_MAG) { 34720ffac27SDaniel Baluta if (mode & KMX61_MAG_STBY_BIT) { 34820ffac27SDaniel Baluta ret |= KMX61_MAG_STBY_BIT; 34920ffac27SDaniel Baluta mag_stby = 1; 35020ffac27SDaniel Baluta } else { 35120ffac27SDaniel Baluta ret &= ~KMX61_MAG_STBY_BIT; 35220ffac27SDaniel Baluta mag_stby = 0; 35320ffac27SDaniel Baluta } 35420ffac27SDaniel Baluta } 35520ffac27SDaniel Baluta 35620ffac27SDaniel Baluta if (mode & KMX61_ACT_STBY_BIT) 35720ffac27SDaniel Baluta ret |= KMX61_ACT_STBY_BIT; 35820ffac27SDaniel Baluta 35920ffac27SDaniel Baluta ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_STBY, ret); 36020ffac27SDaniel Baluta if (ret < 0) { 36120ffac27SDaniel Baluta dev_err(&data->client->dev, "Error writing reg_stby\n"); 36220ffac27SDaniel Baluta return ret; 36320ffac27SDaniel Baluta } 36420ffac27SDaniel Baluta 36520ffac27SDaniel Baluta if (acc_stby != -1 && update) 36620ffac27SDaniel Baluta data->acc_stby = acc_stby; 36720ffac27SDaniel Baluta if (mag_stby != -1 && update) 36820ffac27SDaniel Baluta data->mag_stby = mag_stby; 36920ffac27SDaniel Baluta 37020ffac27SDaniel Baluta return 0; 37120ffac27SDaniel Baluta } 37220ffac27SDaniel Baluta 37320ffac27SDaniel Baluta static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device) 37420ffac27SDaniel Baluta { 37520ffac27SDaniel Baluta int ret; 37620ffac27SDaniel Baluta 37720ffac27SDaniel Baluta ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY); 37820ffac27SDaniel Baluta if (ret < 0) { 37920ffac27SDaniel Baluta dev_err(&data->client->dev, "Error reading reg_stby\n"); 38020ffac27SDaniel Baluta return ret; 38120ffac27SDaniel Baluta } 38220ffac27SDaniel Baluta *mode = 0; 38320ffac27SDaniel Baluta 38420ffac27SDaniel Baluta if (device & KMX61_ACC) { 38520ffac27SDaniel Baluta if (ret & KMX61_ACC_STBY_BIT) 38620ffac27SDaniel Baluta *mode |= KMX61_ACC_STBY_BIT; 38720ffac27SDaniel Baluta else 38820ffac27SDaniel Baluta *mode &= ~KMX61_ACC_STBY_BIT; 38920ffac27SDaniel Baluta } 39020ffac27SDaniel Baluta 39120ffac27SDaniel Baluta if (device & KMX61_MAG) { 39220ffac27SDaniel Baluta if (ret & KMX61_MAG_STBY_BIT) 39320ffac27SDaniel Baluta *mode |= KMX61_MAG_STBY_BIT; 39420ffac27SDaniel Baluta else 39520ffac27SDaniel Baluta *mode &= ~KMX61_MAG_STBY_BIT; 39620ffac27SDaniel Baluta } 39720ffac27SDaniel Baluta 39820ffac27SDaniel Baluta return 0; 39920ffac27SDaniel Baluta } 40020ffac27SDaniel Baluta 401ebd16366Skbuild test robot static int kmx61_set_wake_up_odr(struct kmx61_data *data, int val, int val2) 402fd3ae7a9SDaniel Baluta { 403fd3ae7a9SDaniel Baluta int ret, odr_bits; 404fd3ae7a9SDaniel Baluta 405fd3ae7a9SDaniel Baluta odr_bits = kmx61_convert_wake_up_odr_to_bit(val, val2); 406fd3ae7a9SDaniel Baluta if (odr_bits < 0) 407fd3ae7a9SDaniel Baluta return odr_bits; 408fd3ae7a9SDaniel Baluta 409fd3ae7a9SDaniel Baluta ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL2, 410fd3ae7a9SDaniel Baluta odr_bits); 411fd3ae7a9SDaniel Baluta if (ret < 0) 412fd3ae7a9SDaniel Baluta dev_err(&data->client->dev, "Error writing reg_ctrl2\n"); 413fd3ae7a9SDaniel Baluta return ret; 414fd3ae7a9SDaniel Baluta } 415fd3ae7a9SDaniel Baluta 41620ffac27SDaniel Baluta static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) 41720ffac27SDaniel Baluta { 41820ffac27SDaniel Baluta int ret; 41920ffac27SDaniel Baluta u8 mode; 42020ffac27SDaniel Baluta int lodr_bits, odr_bits; 42120ffac27SDaniel Baluta 42220ffac27SDaniel Baluta ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); 42320ffac27SDaniel Baluta if (ret < 0) 42420ffac27SDaniel Baluta return ret; 42520ffac27SDaniel Baluta 42620ffac27SDaniel Baluta lodr_bits = kmx61_convert_freq_to_bit(val, val2); 42720ffac27SDaniel Baluta if (lodr_bits < 0) 42820ffac27SDaniel Baluta return lodr_bits; 42920ffac27SDaniel Baluta 43020ffac27SDaniel Baluta /* To change ODR, accel and magn must be in STDBY */ 43120ffac27SDaniel Baluta ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, 43220ffac27SDaniel Baluta true); 43320ffac27SDaniel Baluta if (ret < 0) 43420ffac27SDaniel Baluta return ret; 43520ffac27SDaniel Baluta 43620ffac27SDaniel Baluta odr_bits = 0; 43720ffac27SDaniel Baluta if (device & KMX61_ACC) 43820ffac27SDaniel Baluta odr_bits |= lodr_bits << KMX61_ACC_ODR_SHIFT; 43920ffac27SDaniel Baluta if (device & KMX61_MAG) 44020ffac27SDaniel Baluta odr_bits |= lodr_bits << KMX61_MAG_ODR_SHIFT; 44120ffac27SDaniel Baluta 44220ffac27SDaniel Baluta ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_ODCNTL, 44320ffac27SDaniel Baluta odr_bits); 44420ffac27SDaniel Baluta if (ret < 0) 44520ffac27SDaniel Baluta return ret; 44620ffac27SDaniel Baluta 4474e843977SDaniel Baluta data->odr_bits = odr_bits; 4484e843977SDaniel Baluta 449fd3ae7a9SDaniel Baluta if (device & KMX61_ACC) { 450fd3ae7a9SDaniel Baluta ret = kmx61_set_wake_up_odr(data, val, val2); 451fd3ae7a9SDaniel Baluta if (ret) 452fd3ae7a9SDaniel Baluta return ret; 453fd3ae7a9SDaniel Baluta } 454fd3ae7a9SDaniel Baluta 45520ffac27SDaniel Baluta return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); 45620ffac27SDaniel Baluta } 45720ffac27SDaniel Baluta 45820ffac27SDaniel Baluta static int kmx61_get_odr(struct kmx61_data *data, int *val, int *val2, 45920ffac27SDaniel Baluta u8 device) 460a36385a2SDaniel Baluta { 46120ffac27SDaniel Baluta u8 lodr_bits; 46220ffac27SDaniel Baluta 46320ffac27SDaniel Baluta if (device & KMX61_ACC) 46420ffac27SDaniel Baluta lodr_bits = (data->odr_bits >> KMX61_ACC_ODR_SHIFT) & 46520ffac27SDaniel Baluta KMX61_ACC_ODR_MASK; 46620ffac27SDaniel Baluta else if (device & KMX61_MAG) 46720ffac27SDaniel Baluta lodr_bits = (data->odr_bits >> KMX61_MAG_ODR_SHIFT) & 46820ffac27SDaniel Baluta KMX61_MAG_ODR_MASK; 46920ffac27SDaniel Baluta else 47020ffac27SDaniel Baluta return -EINVAL; 47120ffac27SDaniel Baluta 472a36385a2SDaniel Baluta if (lodr_bits >= ARRAY_SIZE(kmx61_samp_freq_table)) 47320ffac27SDaniel Baluta return -EINVAL; 474a36385a2SDaniel Baluta 475a36385a2SDaniel Baluta *val = kmx61_samp_freq_table[lodr_bits].val; 476a36385a2SDaniel Baluta *val2 = kmx61_samp_freq_table[lodr_bits].val2; 477a36385a2SDaniel Baluta 478a36385a2SDaniel Baluta return 0; 47920ffac27SDaniel Baluta } 48020ffac27SDaniel Baluta 48120ffac27SDaniel Baluta static int kmx61_set_range(struct kmx61_data *data, u8 range) 48220ffac27SDaniel Baluta { 48320ffac27SDaniel Baluta int ret; 48420ffac27SDaniel Baluta 48520ffac27SDaniel Baluta ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); 48620ffac27SDaniel Baluta if (ret < 0) { 48720ffac27SDaniel Baluta dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 48820ffac27SDaniel Baluta return ret; 48920ffac27SDaniel Baluta } 49020ffac27SDaniel Baluta 49120ffac27SDaniel Baluta ret &= ~KMX61_REG_CTRL1_GSEL_MASK; 49220ffac27SDaniel Baluta ret |= range & KMX61_REG_CTRL1_GSEL_MASK; 49320ffac27SDaniel Baluta 49420ffac27SDaniel Baluta ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); 49520ffac27SDaniel Baluta if (ret < 0) { 49620ffac27SDaniel Baluta dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); 49720ffac27SDaniel Baluta return ret; 49820ffac27SDaniel Baluta } 49920ffac27SDaniel Baluta 50020ffac27SDaniel Baluta data->range = range; 50120ffac27SDaniel Baluta 50220ffac27SDaniel Baluta return 0; 50320ffac27SDaniel Baluta } 50420ffac27SDaniel Baluta 50520ffac27SDaniel Baluta static int kmx61_set_scale(struct kmx61_data *data, u16 uscale) 50620ffac27SDaniel Baluta { 50720ffac27SDaniel Baluta int ret, i; 50820ffac27SDaniel Baluta u8 mode; 50920ffac27SDaniel Baluta 51020ffac27SDaniel Baluta for (i = 0; i < ARRAY_SIZE(kmx61_uscale_table); i++) { 51120ffac27SDaniel Baluta if (kmx61_uscale_table[i] == uscale) { 51220ffac27SDaniel Baluta ret = kmx61_get_mode(data, &mode, 51320ffac27SDaniel Baluta KMX61_ACC | KMX61_MAG); 51420ffac27SDaniel Baluta if (ret < 0) 51520ffac27SDaniel Baluta return ret; 51620ffac27SDaniel Baluta 51720ffac27SDaniel Baluta ret = kmx61_set_mode(data, KMX61_ALL_STBY, 51820ffac27SDaniel Baluta KMX61_ACC | KMX61_MAG, true); 51920ffac27SDaniel Baluta if (ret < 0) 52020ffac27SDaniel Baluta return ret; 52120ffac27SDaniel Baluta 52220ffac27SDaniel Baluta ret = kmx61_set_range(data, i); 52320ffac27SDaniel Baluta if (ret < 0) 52420ffac27SDaniel Baluta return ret; 52520ffac27SDaniel Baluta 52620ffac27SDaniel Baluta return kmx61_set_mode(data, mode, 52720ffac27SDaniel Baluta KMX61_ACC | KMX61_MAG, true); 52820ffac27SDaniel Baluta } 52920ffac27SDaniel Baluta } 53020ffac27SDaniel Baluta return -EINVAL; 53120ffac27SDaniel Baluta } 53220ffac27SDaniel Baluta 53320ffac27SDaniel Baluta static int kmx61_chip_init(struct kmx61_data *data) 53420ffac27SDaniel Baluta { 535fd3ae7a9SDaniel Baluta int ret, val, val2; 53620ffac27SDaniel Baluta 53720ffac27SDaniel Baluta ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I); 53820ffac27SDaniel Baluta if (ret < 0) { 53920ffac27SDaniel Baluta dev_err(&data->client->dev, "Error reading who_am_i\n"); 54020ffac27SDaniel Baluta return ret; 54120ffac27SDaniel Baluta } 54220ffac27SDaniel Baluta 54320ffac27SDaniel Baluta if (ret != KMX61_CHIP_ID) { 54420ffac27SDaniel Baluta dev_err(&data->client->dev, 54520ffac27SDaniel Baluta "Wrong chip id, got %x expected %x\n", 54620ffac27SDaniel Baluta ret, KMX61_CHIP_ID); 54720ffac27SDaniel Baluta return -EINVAL; 54820ffac27SDaniel Baluta } 54920ffac27SDaniel Baluta 55020ffac27SDaniel Baluta /* set accel 12bit, 4g range */ 55120ffac27SDaniel Baluta ret = kmx61_set_range(data, KMX61_RANGE_4G); 55220ffac27SDaniel Baluta if (ret < 0) 55320ffac27SDaniel Baluta return ret; 55420ffac27SDaniel Baluta 55520ffac27SDaniel Baluta ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_ODCNTL); 55620ffac27SDaniel Baluta if (ret < 0) { 55720ffac27SDaniel Baluta dev_err(&data->client->dev, "Error reading reg_odcntl\n"); 55820ffac27SDaniel Baluta return ret; 55920ffac27SDaniel Baluta } 56020ffac27SDaniel Baluta data->odr_bits = ret; 56120ffac27SDaniel Baluta 562a36385a2SDaniel Baluta /* 563a36385a2SDaniel Baluta * set output data rate for wake up (motion detection) function 564a36385a2SDaniel Baluta * to match data rate for accelerometer sampling 565a36385a2SDaniel Baluta */ 566a36385a2SDaniel Baluta ret = kmx61_get_odr(data, &val, &val2, KMX61_ACC); 567fd3ae7a9SDaniel Baluta if (ret < 0) 568fd3ae7a9SDaniel Baluta return ret; 569fd3ae7a9SDaniel Baluta 570fd3ae7a9SDaniel Baluta ret = kmx61_set_wake_up_odr(data, val, val2); 571fd3ae7a9SDaniel Baluta if (ret < 0) 572fd3ae7a9SDaniel Baluta return ret; 573fd3ae7a9SDaniel Baluta 57420ffac27SDaniel Baluta /* set acc/magn to OPERATION mode */ 57520ffac27SDaniel Baluta ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true); 57620ffac27SDaniel Baluta if (ret < 0) 57720ffac27SDaniel Baluta return ret; 57820ffac27SDaniel Baluta 579fd3ae7a9SDaniel Baluta data->wake_thresh = KMX61_DEFAULT_WAKE_THRESH; 580fd3ae7a9SDaniel Baluta data->wake_duration = KMX61_DEFAULT_WAKE_DURATION; 581fd3ae7a9SDaniel Baluta 58220ffac27SDaniel Baluta return 0; 58320ffac27SDaniel Baluta } 58420ffac27SDaniel Baluta 585c3a23eccSDaniel Baluta static int kmx61_setup_new_data_interrupt(struct kmx61_data *data, 586c3a23eccSDaniel Baluta bool status, u8 device) 587c3a23eccSDaniel Baluta { 588c3a23eccSDaniel Baluta u8 mode; 589c3a23eccSDaniel Baluta int ret; 590c3a23eccSDaniel Baluta 591c3a23eccSDaniel Baluta ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); 592c3a23eccSDaniel Baluta if (ret < 0) 593c3a23eccSDaniel Baluta return ret; 594c3a23eccSDaniel Baluta 595c3a23eccSDaniel Baluta ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); 596c3a23eccSDaniel Baluta if (ret < 0) 597c3a23eccSDaniel Baluta return ret; 598c3a23eccSDaniel Baluta 599c3a23eccSDaniel Baluta ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INC1); 600c3a23eccSDaniel Baluta if (ret < 0) { 601c3a23eccSDaniel Baluta dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 602c3a23eccSDaniel Baluta return ret; 603c3a23eccSDaniel Baluta } 604c3a23eccSDaniel Baluta 605c3a23eccSDaniel Baluta if (status) { 606c3a23eccSDaniel Baluta ret |= KMX61_REG_INC1_BIT_IEN; 607c3a23eccSDaniel Baluta if (device & KMX61_ACC) 608c3a23eccSDaniel Baluta ret |= KMX61_REG_INC1_BIT_DRDYA; 609c3a23eccSDaniel Baluta if (device & KMX61_MAG) 610c3a23eccSDaniel Baluta ret |= KMX61_REG_INC1_BIT_DRDYM; 611c3a23eccSDaniel Baluta } else { 612c3a23eccSDaniel Baluta ret &= ~KMX61_REG_INC1_BIT_IEN; 613c3a23eccSDaniel Baluta if (device & KMX61_ACC) 614c3a23eccSDaniel Baluta ret &= ~KMX61_REG_INC1_BIT_DRDYA; 615c3a23eccSDaniel Baluta if (device & KMX61_MAG) 616c3a23eccSDaniel Baluta ret &= ~KMX61_REG_INC1_BIT_DRDYM; 617c3a23eccSDaniel Baluta } 618c3a23eccSDaniel Baluta ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_INC1, ret); 619c3a23eccSDaniel Baluta if (ret < 0) { 620c3a23eccSDaniel Baluta dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); 621c3a23eccSDaniel Baluta return ret; 622c3a23eccSDaniel Baluta } 623c3a23eccSDaniel Baluta 624c3a23eccSDaniel Baluta ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); 625c3a23eccSDaniel Baluta if (ret < 0) { 626c3a23eccSDaniel Baluta dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 627c3a23eccSDaniel Baluta return ret; 628c3a23eccSDaniel Baluta } 629c3a23eccSDaniel Baluta 630c3a23eccSDaniel Baluta if (status) 631c3a23eccSDaniel Baluta ret |= KMX61_REG_CTRL1_BIT_DRDYE; 632c3a23eccSDaniel Baluta else 633c3a23eccSDaniel Baluta ret &= ~KMX61_REG_CTRL1_BIT_DRDYE; 634c3a23eccSDaniel Baluta 635c3a23eccSDaniel Baluta ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); 636c3a23eccSDaniel Baluta if (ret < 0) { 637c3a23eccSDaniel Baluta dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); 638c3a23eccSDaniel Baluta return ret; 639c3a23eccSDaniel Baluta } 640c3a23eccSDaniel Baluta 64128ff344eSDaniel Baluta return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); 642c3a23eccSDaniel Baluta } 643c3a23eccSDaniel Baluta 644fd3ae7a9SDaniel Baluta static int kmx61_chip_update_thresholds(struct kmx61_data *data) 645fd3ae7a9SDaniel Baluta { 646fd3ae7a9SDaniel Baluta int ret; 647fd3ae7a9SDaniel Baluta 648fd3ae7a9SDaniel Baluta ret = i2c_smbus_write_byte_data(data->client, 649fd3ae7a9SDaniel Baluta KMX61_REG_WUF_TIMER, 650fd3ae7a9SDaniel Baluta data->wake_duration); 651fd3ae7a9SDaniel Baluta if (ret < 0) { 652fd3ae7a9SDaniel Baluta dev_err(&data->client->dev, "Errow writing reg_wuf_timer\n"); 653fd3ae7a9SDaniel Baluta return ret; 654fd3ae7a9SDaniel Baluta } 655fd3ae7a9SDaniel Baluta 656fd3ae7a9SDaniel Baluta ret = i2c_smbus_write_byte_data(data->client, 657fd3ae7a9SDaniel Baluta KMX61_REG_WUF_THRESH, 658fd3ae7a9SDaniel Baluta data->wake_thresh); 65928ff344eSDaniel Baluta if (ret < 0) 660fd3ae7a9SDaniel Baluta dev_err(&data->client->dev, "Error writing reg_wuf_thresh\n"); 661fd3ae7a9SDaniel Baluta 66228ff344eSDaniel Baluta return ret; 663fd3ae7a9SDaniel Baluta } 664fd3ae7a9SDaniel Baluta 665fd3ae7a9SDaniel Baluta static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data, 6660475c685SDaniel Baluta bool status) 667fd3ae7a9SDaniel Baluta { 668fd3ae7a9SDaniel Baluta u8 mode; 669fd3ae7a9SDaniel Baluta int ret; 670fd3ae7a9SDaniel Baluta 671fd3ae7a9SDaniel Baluta ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); 672fd3ae7a9SDaniel Baluta if (ret < 0) 673fd3ae7a9SDaniel Baluta return ret; 674fd3ae7a9SDaniel Baluta 675fd3ae7a9SDaniel Baluta ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); 676fd3ae7a9SDaniel Baluta if (ret < 0) 677fd3ae7a9SDaniel Baluta return ret; 678fd3ae7a9SDaniel Baluta 679fd3ae7a9SDaniel Baluta ret = kmx61_chip_update_thresholds(data); 680fd3ae7a9SDaniel Baluta if (ret < 0) 681fd3ae7a9SDaniel Baluta return ret; 682fd3ae7a9SDaniel Baluta 683fd3ae7a9SDaniel Baluta ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INC1); 684fd3ae7a9SDaniel Baluta if (ret < 0) { 685fd3ae7a9SDaniel Baluta dev_err(&data->client->dev, "Error reading reg_inc1\n"); 686fd3ae7a9SDaniel Baluta return ret; 687fd3ae7a9SDaniel Baluta } 688fd3ae7a9SDaniel Baluta if (status) 689fd3ae7a9SDaniel Baluta ret |= (KMX61_REG_INC1_BIT_IEN | KMX61_REG_INC1_BIT_WUFS); 690fd3ae7a9SDaniel Baluta else 691fd3ae7a9SDaniel Baluta ret &= ~(KMX61_REG_INC1_BIT_IEN | KMX61_REG_INC1_BIT_WUFS); 692fd3ae7a9SDaniel Baluta 693fd3ae7a9SDaniel Baluta ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_INC1, ret); 694fd3ae7a9SDaniel Baluta if (ret < 0) { 695fd3ae7a9SDaniel Baluta dev_err(&data->client->dev, "Error writing reg_inc1\n"); 696fd3ae7a9SDaniel Baluta return ret; 697fd3ae7a9SDaniel Baluta } 698fd3ae7a9SDaniel Baluta 699fd3ae7a9SDaniel Baluta ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); 700fd3ae7a9SDaniel Baluta if (ret < 0) { 701fd3ae7a9SDaniel Baluta dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 702fd3ae7a9SDaniel Baluta return ret; 703fd3ae7a9SDaniel Baluta } 704fd3ae7a9SDaniel Baluta 705fd3ae7a9SDaniel Baluta if (status) 706fd3ae7a9SDaniel Baluta ret |= KMX61_REG_CTRL1_BIT_WUFE | KMX61_REG_CTRL1_BIT_BTSE; 707fd3ae7a9SDaniel Baluta else 708fd3ae7a9SDaniel Baluta ret &= ~(KMX61_REG_CTRL1_BIT_WUFE | KMX61_REG_CTRL1_BIT_BTSE); 709fd3ae7a9SDaniel Baluta 710fd3ae7a9SDaniel Baluta ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); 711fd3ae7a9SDaniel Baluta if (ret < 0) { 712fd3ae7a9SDaniel Baluta dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); 713fd3ae7a9SDaniel Baluta return ret; 714fd3ae7a9SDaniel Baluta } 715fd3ae7a9SDaniel Baluta mode |= KMX61_ACT_STBY_BIT; 71628ff344eSDaniel Baluta return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); 717fd3ae7a9SDaniel Baluta } 718fd3ae7a9SDaniel Baluta 719aff8609aSDaniel Baluta /** 720aff8609aSDaniel Baluta * kmx61_set_power_state() - set power state for kmx61 @device 721*0d674449SLee Jones * @data: kmx61 device private pointer 722*0d674449SLee Jones * @on: power state to be set for @device 723*0d674449SLee Jones * @device: bitmask indicating device for which @on state needs to be set 724aff8609aSDaniel Baluta * 725aff8609aSDaniel Baluta * Notice that when ACC power state needs to be set to ON and MAG is in 726aff8609aSDaniel Baluta * OPERATION then we know that kmx61_runtime_resume was already called 727aff8609aSDaniel Baluta * so we must set ACC OPERATION mode here. The same happens when MAG power 728aff8609aSDaniel Baluta * state needs to be set to ON and ACC is in OPERATION. 729aff8609aSDaniel Baluta */ 730aff8609aSDaniel Baluta static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device) 731aff8609aSDaniel Baluta { 732df1fad80SDaniel Baluta #ifdef CONFIG_PM 733aff8609aSDaniel Baluta int ret; 734aff8609aSDaniel Baluta 735aff8609aSDaniel Baluta if (device & KMX61_ACC) { 736aff8609aSDaniel Baluta if (on && !data->acc_ps && !data->mag_stby) { 737aff8609aSDaniel Baluta ret = kmx61_set_mode(data, 0, KMX61_ACC, true); 738aff8609aSDaniel Baluta if (ret < 0) 739aff8609aSDaniel Baluta return ret; 740aff8609aSDaniel Baluta } 741aff8609aSDaniel Baluta data->acc_ps = on; 742aff8609aSDaniel Baluta } 743aff8609aSDaniel Baluta if (device & KMX61_MAG) { 744aff8609aSDaniel Baluta if (on && !data->mag_ps && !data->acc_stby) { 745aff8609aSDaniel Baluta ret = kmx61_set_mode(data, 0, KMX61_MAG, true); 746aff8609aSDaniel Baluta if (ret < 0) 747aff8609aSDaniel Baluta return ret; 748aff8609aSDaniel Baluta } 749aff8609aSDaniel Baluta data->mag_ps = on; 750aff8609aSDaniel Baluta } 751aff8609aSDaniel Baluta 752aff8609aSDaniel Baluta if (on) { 753aff8609aSDaniel Baluta ret = pm_runtime_get_sync(&data->client->dev); 754aff8609aSDaniel Baluta } else { 755aff8609aSDaniel Baluta pm_runtime_mark_last_busy(&data->client->dev); 756aff8609aSDaniel Baluta ret = pm_runtime_put_autosuspend(&data->client->dev); 757aff8609aSDaniel Baluta } 758aff8609aSDaniel Baluta if (ret < 0) { 759aff8609aSDaniel Baluta dev_err(&data->client->dev, 760aff8609aSDaniel Baluta "Failed: kmx61_set_power_state for %d, ret %d\n", 761aff8609aSDaniel Baluta on, ret); 762aff8609aSDaniel Baluta if (on) 763aff8609aSDaniel Baluta pm_runtime_put_noidle(&data->client->dev); 764aff8609aSDaniel Baluta 765aff8609aSDaniel Baluta return ret; 766aff8609aSDaniel Baluta } 767aff8609aSDaniel Baluta #endif 768aff8609aSDaniel Baluta return 0; 769aff8609aSDaniel Baluta } 770aff8609aSDaniel Baluta 77120ffac27SDaniel Baluta static int kmx61_read_measurement(struct kmx61_data *data, u8 base, u8 offset) 77220ffac27SDaniel Baluta { 77320ffac27SDaniel Baluta int ret; 77420ffac27SDaniel Baluta u8 reg = base + offset * 2; 77520ffac27SDaniel Baluta 77620ffac27SDaniel Baluta ret = i2c_smbus_read_word_data(data->client, reg); 77720ffac27SDaniel Baluta if (ret < 0) 77820ffac27SDaniel Baluta dev_err(&data->client->dev, "failed to read reg at %x\n", reg); 77920ffac27SDaniel Baluta 78020ffac27SDaniel Baluta return ret; 78120ffac27SDaniel Baluta } 78220ffac27SDaniel Baluta 78320ffac27SDaniel Baluta static int kmx61_read_raw(struct iio_dev *indio_dev, 78420ffac27SDaniel Baluta struct iio_chan_spec const *chan, int *val, 78520ffac27SDaniel Baluta int *val2, long mask) 78620ffac27SDaniel Baluta { 78720ffac27SDaniel Baluta int ret; 78820ffac27SDaniel Baluta u8 base_reg; 78920ffac27SDaniel Baluta struct kmx61_data *data = kmx61_get_data(indio_dev); 79020ffac27SDaniel Baluta 79120ffac27SDaniel Baluta switch (mask) { 79220ffac27SDaniel Baluta case IIO_CHAN_INFO_RAW: 79320ffac27SDaniel Baluta switch (chan->type) { 79420ffac27SDaniel Baluta case IIO_ACCEL: 79520ffac27SDaniel Baluta base_reg = KMX61_ACC_XOUT_L; 79620ffac27SDaniel Baluta break; 79720ffac27SDaniel Baluta case IIO_MAGN: 79820ffac27SDaniel Baluta base_reg = KMX61_MAG_XOUT_L; 79920ffac27SDaniel Baluta break; 80020ffac27SDaniel Baluta default: 80120ffac27SDaniel Baluta return -EINVAL; 80220ffac27SDaniel Baluta } 80320ffac27SDaniel Baluta mutex_lock(&data->lock); 80420ffac27SDaniel Baluta 805a3da4fa3SDaniel Baluta ret = kmx61_set_power_state(data, true, chan->address); 806a3da4fa3SDaniel Baluta if (ret) { 807a3da4fa3SDaniel Baluta mutex_unlock(&data->lock); 808a3da4fa3SDaniel Baluta return ret; 809a3da4fa3SDaniel Baluta } 810a3da4fa3SDaniel Baluta 81120ffac27SDaniel Baluta ret = kmx61_read_measurement(data, base_reg, chan->scan_index); 81220ffac27SDaniel Baluta if (ret < 0) { 813aff8609aSDaniel Baluta kmx61_set_power_state(data, false, chan->address); 81420ffac27SDaniel Baluta mutex_unlock(&data->lock); 81520ffac27SDaniel Baluta return ret; 81620ffac27SDaniel Baluta } 81720ffac27SDaniel Baluta *val = sign_extend32(ret >> chan->scan_type.shift, 81820ffac27SDaniel Baluta chan->scan_type.realbits - 1); 819a3da4fa3SDaniel Baluta ret = kmx61_set_power_state(data, false, chan->address); 82020ffac27SDaniel Baluta 82120ffac27SDaniel Baluta mutex_unlock(&data->lock); 822a3da4fa3SDaniel Baluta if (ret) 823a3da4fa3SDaniel Baluta return ret; 82420ffac27SDaniel Baluta return IIO_VAL_INT; 82520ffac27SDaniel Baluta case IIO_CHAN_INFO_SCALE: 82620ffac27SDaniel Baluta switch (chan->type) { 82720ffac27SDaniel Baluta case IIO_ACCEL: 82820ffac27SDaniel Baluta *val = 0; 82920ffac27SDaniel Baluta *val2 = kmx61_uscale_table[data->range]; 83020ffac27SDaniel Baluta return IIO_VAL_INT_PLUS_MICRO; 83120ffac27SDaniel Baluta case IIO_MAGN: 83220ffac27SDaniel Baluta /* 14 bits res, 1465 microGauss per magn count */ 83320ffac27SDaniel Baluta *val = 0; 83420ffac27SDaniel Baluta *val2 = 1465; 83520ffac27SDaniel Baluta return IIO_VAL_INT_PLUS_MICRO; 83620ffac27SDaniel Baluta default: 83720ffac27SDaniel Baluta return -EINVAL; 83820ffac27SDaniel Baluta } 83920ffac27SDaniel Baluta case IIO_CHAN_INFO_SAMP_FREQ: 84020ffac27SDaniel Baluta if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) 84120ffac27SDaniel Baluta return -EINVAL; 84220ffac27SDaniel Baluta 84320ffac27SDaniel Baluta mutex_lock(&data->lock); 84420ffac27SDaniel Baluta ret = kmx61_get_odr(data, val, val2, chan->address); 84520ffac27SDaniel Baluta mutex_unlock(&data->lock); 84620ffac27SDaniel Baluta if (ret) 84720ffac27SDaniel Baluta return -EINVAL; 84820ffac27SDaniel Baluta return IIO_VAL_INT_PLUS_MICRO; 84920ffac27SDaniel Baluta } 85020ffac27SDaniel Baluta return -EINVAL; 85120ffac27SDaniel Baluta } 85220ffac27SDaniel Baluta 85320ffac27SDaniel Baluta static int kmx61_write_raw(struct iio_dev *indio_dev, 85420ffac27SDaniel Baluta struct iio_chan_spec const *chan, int val, 85520ffac27SDaniel Baluta int val2, long mask) 85620ffac27SDaniel Baluta { 85720ffac27SDaniel Baluta int ret; 85820ffac27SDaniel Baluta struct kmx61_data *data = kmx61_get_data(indio_dev); 85920ffac27SDaniel Baluta 86020ffac27SDaniel Baluta switch (mask) { 86120ffac27SDaniel Baluta case IIO_CHAN_INFO_SAMP_FREQ: 86220ffac27SDaniel Baluta if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) 86320ffac27SDaniel Baluta return -EINVAL; 86420ffac27SDaniel Baluta 86520ffac27SDaniel Baluta mutex_lock(&data->lock); 86620ffac27SDaniel Baluta ret = kmx61_set_odr(data, val, val2, chan->address); 86720ffac27SDaniel Baluta mutex_unlock(&data->lock); 86820ffac27SDaniel Baluta return ret; 86920ffac27SDaniel Baluta case IIO_CHAN_INFO_SCALE: 87020ffac27SDaniel Baluta switch (chan->type) { 87120ffac27SDaniel Baluta case IIO_ACCEL: 87220ffac27SDaniel Baluta if (val != 0) 87320ffac27SDaniel Baluta return -EINVAL; 87420ffac27SDaniel Baluta mutex_lock(&data->lock); 87520ffac27SDaniel Baluta ret = kmx61_set_scale(data, val2); 87620ffac27SDaniel Baluta mutex_unlock(&data->lock); 87720ffac27SDaniel Baluta return ret; 87820ffac27SDaniel Baluta default: 87920ffac27SDaniel Baluta return -EINVAL; 88020ffac27SDaniel Baluta } 88120ffac27SDaniel Baluta default: 88220ffac27SDaniel Baluta return -EINVAL; 88320ffac27SDaniel Baluta } 88420ffac27SDaniel Baluta } 88520ffac27SDaniel Baluta 886fd3ae7a9SDaniel Baluta static int kmx61_read_event(struct iio_dev *indio_dev, 887fd3ae7a9SDaniel Baluta const struct iio_chan_spec *chan, 888fd3ae7a9SDaniel Baluta enum iio_event_type type, 889fd3ae7a9SDaniel Baluta enum iio_event_direction dir, 890fd3ae7a9SDaniel Baluta enum iio_event_info info, 891fd3ae7a9SDaniel Baluta int *val, int *val2) 892fd3ae7a9SDaniel Baluta { 893fd3ae7a9SDaniel Baluta struct kmx61_data *data = kmx61_get_data(indio_dev); 894fd3ae7a9SDaniel Baluta 895fd3ae7a9SDaniel Baluta *val2 = 0; 896fd3ae7a9SDaniel Baluta switch (info) { 897fd3ae7a9SDaniel Baluta case IIO_EV_INFO_VALUE: 898fd3ae7a9SDaniel Baluta *val = data->wake_thresh; 89928ff344eSDaniel Baluta return IIO_VAL_INT; 900fd3ae7a9SDaniel Baluta case IIO_EV_INFO_PERIOD: 901fd3ae7a9SDaniel Baluta *val = data->wake_duration; 90228ff344eSDaniel Baluta return IIO_VAL_INT; 903fd3ae7a9SDaniel Baluta default: 904fd3ae7a9SDaniel Baluta return -EINVAL; 905fd3ae7a9SDaniel Baluta } 906fd3ae7a9SDaniel Baluta } 907fd3ae7a9SDaniel Baluta 908fd3ae7a9SDaniel Baluta static int kmx61_write_event(struct iio_dev *indio_dev, 909fd3ae7a9SDaniel Baluta const struct iio_chan_spec *chan, 910fd3ae7a9SDaniel Baluta enum iio_event_type type, 911fd3ae7a9SDaniel Baluta enum iio_event_direction dir, 912fd3ae7a9SDaniel Baluta enum iio_event_info info, 913fd3ae7a9SDaniel Baluta int val, int val2) 914fd3ae7a9SDaniel Baluta { 915fd3ae7a9SDaniel Baluta struct kmx61_data *data = kmx61_get_data(indio_dev); 916fd3ae7a9SDaniel Baluta 917fd3ae7a9SDaniel Baluta if (data->ev_enable_state) 918fd3ae7a9SDaniel Baluta return -EBUSY; 919fd3ae7a9SDaniel Baluta 920fd3ae7a9SDaniel Baluta switch (info) { 921fd3ae7a9SDaniel Baluta case IIO_EV_INFO_VALUE: 922fd3ae7a9SDaniel Baluta data->wake_thresh = val; 92328ff344eSDaniel Baluta return IIO_VAL_INT; 924fd3ae7a9SDaniel Baluta case IIO_EV_INFO_PERIOD: 925fd3ae7a9SDaniel Baluta data->wake_duration = val; 92628ff344eSDaniel Baluta return IIO_VAL_INT; 927fd3ae7a9SDaniel Baluta default: 928fd3ae7a9SDaniel Baluta return -EINVAL; 929fd3ae7a9SDaniel Baluta } 930fd3ae7a9SDaniel Baluta } 931fd3ae7a9SDaniel Baluta 932fd3ae7a9SDaniel Baluta static int kmx61_read_event_config(struct iio_dev *indio_dev, 933fd3ae7a9SDaniel Baluta const struct iio_chan_spec *chan, 934fd3ae7a9SDaniel Baluta enum iio_event_type type, 935fd3ae7a9SDaniel Baluta enum iio_event_direction dir) 936fd3ae7a9SDaniel Baluta { 937fd3ae7a9SDaniel Baluta struct kmx61_data *data = kmx61_get_data(indio_dev); 938fd3ae7a9SDaniel Baluta 939fd3ae7a9SDaniel Baluta return data->ev_enable_state; 940fd3ae7a9SDaniel Baluta } 941fd3ae7a9SDaniel Baluta 942fd3ae7a9SDaniel Baluta static int kmx61_write_event_config(struct iio_dev *indio_dev, 943fd3ae7a9SDaniel Baluta const struct iio_chan_spec *chan, 944fd3ae7a9SDaniel Baluta enum iio_event_type type, 945fd3ae7a9SDaniel Baluta enum iio_event_direction dir, 946fd3ae7a9SDaniel Baluta int state) 947fd3ae7a9SDaniel Baluta { 948fd3ae7a9SDaniel Baluta struct kmx61_data *data = kmx61_get_data(indio_dev); 94928ff344eSDaniel Baluta int ret = 0; 950fd3ae7a9SDaniel Baluta 951fd3ae7a9SDaniel Baluta if (state && data->ev_enable_state) 952fd3ae7a9SDaniel Baluta return 0; 953fd3ae7a9SDaniel Baluta 954fd3ae7a9SDaniel Baluta mutex_lock(&data->lock); 955fd3ae7a9SDaniel Baluta 956fd3ae7a9SDaniel Baluta if (!state && data->motion_trig_on) { 957d4a4ae04SDaniel Baluta data->ev_enable_state = false; 95828ff344eSDaniel Baluta goto err_unlock; 959fd3ae7a9SDaniel Baluta } 960fd3ae7a9SDaniel Baluta 961fd3ae7a9SDaniel Baluta ret = kmx61_set_power_state(data, state, KMX61_ACC); 96228ff344eSDaniel Baluta if (ret < 0) 96328ff344eSDaniel Baluta goto err_unlock; 964fd3ae7a9SDaniel Baluta 9650475c685SDaniel Baluta ret = kmx61_setup_any_motion_interrupt(data, state); 966fd3ae7a9SDaniel Baluta if (ret < 0) { 967fd3ae7a9SDaniel Baluta kmx61_set_power_state(data, false, KMX61_ACC); 96828ff344eSDaniel Baluta goto err_unlock; 969fd3ae7a9SDaniel Baluta } 970fd3ae7a9SDaniel Baluta 971fd3ae7a9SDaniel Baluta data->ev_enable_state = state; 97228ff344eSDaniel Baluta 97328ff344eSDaniel Baluta err_unlock: 974fd3ae7a9SDaniel Baluta mutex_unlock(&data->lock); 975fd3ae7a9SDaniel Baluta 97628ff344eSDaniel Baluta return ret; 977fd3ae7a9SDaniel Baluta } 978fd3ae7a9SDaniel Baluta 979c3a23eccSDaniel Baluta static int kmx61_acc_validate_trigger(struct iio_dev *indio_dev, 980c3a23eccSDaniel Baluta struct iio_trigger *trig) 981c3a23eccSDaniel Baluta { 982c3a23eccSDaniel Baluta struct kmx61_data *data = kmx61_get_data(indio_dev); 983c3a23eccSDaniel Baluta 984fd3ae7a9SDaniel Baluta if (data->acc_dready_trig != trig && data->motion_trig != trig) 985c3a23eccSDaniel Baluta return -EINVAL; 986c3a23eccSDaniel Baluta 987c3a23eccSDaniel Baluta return 0; 988c3a23eccSDaniel Baluta } 989c3a23eccSDaniel Baluta 990c3a23eccSDaniel Baluta static int kmx61_mag_validate_trigger(struct iio_dev *indio_dev, 991c3a23eccSDaniel Baluta struct iio_trigger *trig) 992c3a23eccSDaniel Baluta { 993c3a23eccSDaniel Baluta struct kmx61_data *data = kmx61_get_data(indio_dev); 994c3a23eccSDaniel Baluta 995c3a23eccSDaniel Baluta if (data->mag_dready_trig != trig) 996c3a23eccSDaniel Baluta return -EINVAL; 997c3a23eccSDaniel Baluta 998c3a23eccSDaniel Baluta return 0; 999c3a23eccSDaniel Baluta } 1000c3a23eccSDaniel Baluta 100120ffac27SDaniel Baluta static const struct iio_info kmx61_acc_info = { 100220ffac27SDaniel Baluta .read_raw = kmx61_read_raw, 100320ffac27SDaniel Baluta .write_raw = kmx61_write_raw, 100420ffac27SDaniel Baluta .attrs = &kmx61_acc_attribute_group, 1005fd3ae7a9SDaniel Baluta .read_event_value = kmx61_read_event, 1006fd3ae7a9SDaniel Baluta .write_event_value = kmx61_write_event, 1007fd3ae7a9SDaniel Baluta .read_event_config = kmx61_read_event_config, 1008fd3ae7a9SDaniel Baluta .write_event_config = kmx61_write_event_config, 1009c3a23eccSDaniel Baluta .validate_trigger = kmx61_acc_validate_trigger, 101020ffac27SDaniel Baluta }; 101120ffac27SDaniel Baluta 101220ffac27SDaniel Baluta static const struct iio_info kmx61_mag_info = { 101320ffac27SDaniel Baluta .read_raw = kmx61_read_raw, 101420ffac27SDaniel Baluta .write_raw = kmx61_write_raw, 101520ffac27SDaniel Baluta .attrs = &kmx61_mag_attribute_group, 1016c3a23eccSDaniel Baluta .validate_trigger = kmx61_mag_validate_trigger, 101720ffac27SDaniel Baluta }; 101820ffac27SDaniel Baluta 1019c3a23eccSDaniel Baluta 1020c3a23eccSDaniel Baluta static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, 1021c3a23eccSDaniel Baluta bool state) 1022c3a23eccSDaniel Baluta { 1023c3a23eccSDaniel Baluta int ret = 0; 1024c3a23eccSDaniel Baluta u8 device; 1025c3a23eccSDaniel Baluta 1026c3a23eccSDaniel Baluta struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); 1027fd3ae7a9SDaniel Baluta struct kmx61_data *data = kmx61_get_data(indio_dev); 1028c3a23eccSDaniel Baluta 1029c3a23eccSDaniel Baluta mutex_lock(&data->lock); 1030c3a23eccSDaniel Baluta 1031fd3ae7a9SDaniel Baluta if (!state && data->ev_enable_state && data->motion_trig_on) { 1032fd3ae7a9SDaniel Baluta data->motion_trig_on = false; 103328ff344eSDaniel Baluta goto err_unlock; 1034fd3ae7a9SDaniel Baluta } 1035fd3ae7a9SDaniel Baluta 1036dbdd0e2dSDaniel Baluta if (data->acc_dready_trig == trig || data->motion_trig == trig) 1037c3a23eccSDaniel Baluta device = KMX61_ACC; 1038c3a23eccSDaniel Baluta else 1039c3a23eccSDaniel Baluta device = KMX61_MAG; 1040c3a23eccSDaniel Baluta 1041c3a23eccSDaniel Baluta ret = kmx61_set_power_state(data, state, device); 104228ff344eSDaniel Baluta if (ret < 0) 104328ff344eSDaniel Baluta goto err_unlock; 1044c3a23eccSDaniel Baluta 1045fd3ae7a9SDaniel Baluta if (data->acc_dready_trig == trig || data->mag_dready_trig == trig) 1046c3a23eccSDaniel Baluta ret = kmx61_setup_new_data_interrupt(data, state, device); 1047fd3ae7a9SDaniel Baluta else 10480475c685SDaniel Baluta ret = kmx61_setup_any_motion_interrupt(data, state); 1049c3a23eccSDaniel Baluta if (ret < 0) { 1050c3a23eccSDaniel Baluta kmx61_set_power_state(data, false, device); 105128ff344eSDaniel Baluta goto err_unlock; 1052c3a23eccSDaniel Baluta } 1053c3a23eccSDaniel Baluta 1054c3a23eccSDaniel Baluta if (data->acc_dready_trig == trig) 1055c3a23eccSDaniel Baluta data->acc_dready_trig_on = state; 1056fd3ae7a9SDaniel Baluta else if (data->mag_dready_trig == trig) 1057c3a23eccSDaniel Baluta data->mag_dready_trig_on = state; 1058fd3ae7a9SDaniel Baluta else 1059fd3ae7a9SDaniel Baluta data->motion_trig_on = state; 106028ff344eSDaniel Baluta err_unlock: 1061c3a23eccSDaniel Baluta mutex_unlock(&data->lock); 1062c3a23eccSDaniel Baluta 106328ff344eSDaniel Baluta return ret; 1064c3a23eccSDaniel Baluta } 1065c3a23eccSDaniel Baluta 1066c3a23eccSDaniel Baluta static int kmx61_trig_try_reenable(struct iio_trigger *trig) 1067c3a23eccSDaniel Baluta { 1068c3a23eccSDaniel Baluta struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); 1069c3a23eccSDaniel Baluta struct kmx61_data *data = kmx61_get_data(indio_dev); 1070c3a23eccSDaniel Baluta int ret; 1071c3a23eccSDaniel Baluta 1072c3a23eccSDaniel Baluta ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL); 1073c3a23eccSDaniel Baluta if (ret < 0) { 1074c3a23eccSDaniel Baluta dev_err(&data->client->dev, "Error reading reg_inl\n"); 1075c3a23eccSDaniel Baluta return ret; 1076c3a23eccSDaniel Baluta } 1077c3a23eccSDaniel Baluta 1078c3a23eccSDaniel Baluta return 0; 1079c3a23eccSDaniel Baluta } 1080c3a23eccSDaniel Baluta 1081c3a23eccSDaniel Baluta static const struct iio_trigger_ops kmx61_trigger_ops = { 1082c3a23eccSDaniel Baluta .set_trigger_state = kmx61_data_rdy_trigger_set_state, 1083c3a23eccSDaniel Baluta .try_reenable = kmx61_trig_try_reenable, 1084c3a23eccSDaniel Baluta }; 1085c3a23eccSDaniel Baluta 1086fd3ae7a9SDaniel Baluta static irqreturn_t kmx61_event_handler(int irq, void *private) 1087fd3ae7a9SDaniel Baluta { 1088fd3ae7a9SDaniel Baluta struct kmx61_data *data = private; 1089fd3ae7a9SDaniel Baluta struct iio_dev *indio_dev = data->acc_indio_dev; 1090fd3ae7a9SDaniel Baluta int ret; 1091fd3ae7a9SDaniel Baluta 1092fd3ae7a9SDaniel Baluta ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS1); 1093fd3ae7a9SDaniel Baluta if (ret < 0) { 1094fd3ae7a9SDaniel Baluta dev_err(&data->client->dev, "Error reading reg_ins1\n"); 1095fd3ae7a9SDaniel Baluta goto ack_intr; 1096fd3ae7a9SDaniel Baluta } 1097fd3ae7a9SDaniel Baluta 1098fd3ae7a9SDaniel Baluta if (ret & KMX61_REG_INS1_BIT_WUFS) { 1099fd3ae7a9SDaniel Baluta ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS2); 1100fd3ae7a9SDaniel Baluta if (ret < 0) { 1101fd3ae7a9SDaniel Baluta dev_err(&data->client->dev, "Error reading reg_ins2\n"); 1102fd3ae7a9SDaniel Baluta goto ack_intr; 1103fd3ae7a9SDaniel Baluta } 1104fd3ae7a9SDaniel Baluta 1105fd3ae7a9SDaniel Baluta if (ret & KMX61_REG_INS2_BIT_XN) 1106fd3ae7a9SDaniel Baluta iio_push_event(indio_dev, 1107fd3ae7a9SDaniel Baluta IIO_MOD_EVENT_CODE(IIO_ACCEL, 1108fd3ae7a9SDaniel Baluta 0, 1109fd3ae7a9SDaniel Baluta IIO_MOD_X, 1110fd3ae7a9SDaniel Baluta IIO_EV_TYPE_THRESH, 1111fd3ae7a9SDaniel Baluta IIO_EV_DIR_FALLING), 1112fd3ae7a9SDaniel Baluta 0); 1113fd3ae7a9SDaniel Baluta 1114fd3ae7a9SDaniel Baluta if (ret & KMX61_REG_INS2_BIT_XP) 1115fd3ae7a9SDaniel Baluta iio_push_event(indio_dev, 1116fd3ae7a9SDaniel Baluta IIO_MOD_EVENT_CODE(IIO_ACCEL, 1117fd3ae7a9SDaniel Baluta 0, 1118fd3ae7a9SDaniel Baluta IIO_MOD_X, 1119fd3ae7a9SDaniel Baluta IIO_EV_TYPE_THRESH, 1120fd3ae7a9SDaniel Baluta IIO_EV_DIR_RISING), 1121fd3ae7a9SDaniel Baluta 0); 1122fd3ae7a9SDaniel Baluta 1123fd3ae7a9SDaniel Baluta if (ret & KMX61_REG_INS2_BIT_YN) 1124fd3ae7a9SDaniel Baluta iio_push_event(indio_dev, 1125fd3ae7a9SDaniel Baluta IIO_MOD_EVENT_CODE(IIO_ACCEL, 1126fd3ae7a9SDaniel Baluta 0, 1127fd3ae7a9SDaniel Baluta IIO_MOD_Y, 1128fd3ae7a9SDaniel Baluta IIO_EV_TYPE_THRESH, 1129fd3ae7a9SDaniel Baluta IIO_EV_DIR_FALLING), 1130fd3ae7a9SDaniel Baluta 0); 1131fd3ae7a9SDaniel Baluta 1132fd3ae7a9SDaniel Baluta if (ret & KMX61_REG_INS2_BIT_YP) 1133fd3ae7a9SDaniel Baluta iio_push_event(indio_dev, 1134fd3ae7a9SDaniel Baluta IIO_MOD_EVENT_CODE(IIO_ACCEL, 1135fd3ae7a9SDaniel Baluta 0, 1136fd3ae7a9SDaniel Baluta IIO_MOD_Y, 1137fd3ae7a9SDaniel Baluta IIO_EV_TYPE_THRESH, 1138fd3ae7a9SDaniel Baluta IIO_EV_DIR_RISING), 1139fd3ae7a9SDaniel Baluta 0); 1140fd3ae7a9SDaniel Baluta 1141fd3ae7a9SDaniel Baluta if (ret & KMX61_REG_INS2_BIT_ZN) 1142fd3ae7a9SDaniel Baluta iio_push_event(indio_dev, 1143fd3ae7a9SDaniel Baluta IIO_MOD_EVENT_CODE(IIO_ACCEL, 1144fd3ae7a9SDaniel Baluta 0, 1145fd3ae7a9SDaniel Baluta IIO_MOD_Z, 1146fd3ae7a9SDaniel Baluta IIO_EV_TYPE_THRESH, 1147fd3ae7a9SDaniel Baluta IIO_EV_DIR_FALLING), 1148fd3ae7a9SDaniel Baluta 0); 1149fd3ae7a9SDaniel Baluta 1150fd3ae7a9SDaniel Baluta if (ret & KMX61_REG_INS2_BIT_ZP) 1151fd3ae7a9SDaniel Baluta iio_push_event(indio_dev, 1152fd3ae7a9SDaniel Baluta IIO_MOD_EVENT_CODE(IIO_ACCEL, 1153fd3ae7a9SDaniel Baluta 0, 1154fd3ae7a9SDaniel Baluta IIO_MOD_Z, 1155fd3ae7a9SDaniel Baluta IIO_EV_TYPE_THRESH, 1156fd3ae7a9SDaniel Baluta IIO_EV_DIR_RISING), 1157fd3ae7a9SDaniel Baluta 0); 1158fd3ae7a9SDaniel Baluta } 1159fd3ae7a9SDaniel Baluta 1160fd3ae7a9SDaniel Baluta ack_intr: 1161fd3ae7a9SDaniel Baluta ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); 1162fd3ae7a9SDaniel Baluta if (ret < 0) 1163fd3ae7a9SDaniel Baluta dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 1164fd3ae7a9SDaniel Baluta 1165fd3ae7a9SDaniel Baluta ret |= KMX61_REG_CTRL1_BIT_RES; 1166fd3ae7a9SDaniel Baluta ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); 1167fd3ae7a9SDaniel Baluta if (ret < 0) 116828ff344eSDaniel Baluta dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); 1169fd3ae7a9SDaniel Baluta 1170fd3ae7a9SDaniel Baluta ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL); 1171fd3ae7a9SDaniel Baluta if (ret < 0) 1172fd3ae7a9SDaniel Baluta dev_err(&data->client->dev, "Error reading reg_inl\n"); 1173fd3ae7a9SDaniel Baluta 1174fd3ae7a9SDaniel Baluta return IRQ_HANDLED; 1175fd3ae7a9SDaniel Baluta } 1176fd3ae7a9SDaniel Baluta 1177c3a23eccSDaniel Baluta static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private) 1178c3a23eccSDaniel Baluta { 1179c3a23eccSDaniel Baluta struct kmx61_data *data = private; 1180c3a23eccSDaniel Baluta 1181c3a23eccSDaniel Baluta if (data->acc_dready_trig_on) 1182c3a23eccSDaniel Baluta iio_trigger_poll(data->acc_dready_trig); 1183c3a23eccSDaniel Baluta if (data->mag_dready_trig_on) 1184c3a23eccSDaniel Baluta iio_trigger_poll(data->mag_dready_trig); 1185c3a23eccSDaniel Baluta 1186fd3ae7a9SDaniel Baluta if (data->motion_trig_on) 1187fd3ae7a9SDaniel Baluta iio_trigger_poll(data->motion_trig); 1188fd3ae7a9SDaniel Baluta 1189fd3ae7a9SDaniel Baluta if (data->ev_enable_state) 1190fd3ae7a9SDaniel Baluta return IRQ_WAKE_THREAD; 1191c3a23eccSDaniel Baluta return IRQ_HANDLED; 1192c3a23eccSDaniel Baluta } 1193c3a23eccSDaniel Baluta 1194c3a23eccSDaniel Baluta static irqreturn_t kmx61_trigger_handler(int irq, void *p) 1195c3a23eccSDaniel Baluta { 1196c3a23eccSDaniel Baluta struct iio_poll_func *pf = p; 1197c3a23eccSDaniel Baluta struct iio_dev *indio_dev = pf->indio_dev; 1198c3a23eccSDaniel Baluta struct kmx61_data *data = kmx61_get_data(indio_dev); 1199c3a23eccSDaniel Baluta int bit, ret, i = 0; 12006a191c70SDaniel Baluta u8 base; 1201c3a23eccSDaniel Baluta s16 buffer[8]; 1202c3a23eccSDaniel Baluta 12036a191c70SDaniel Baluta if (indio_dev == data->acc_indio_dev) 12046a191c70SDaniel Baluta base = KMX61_ACC_XOUT_L; 12056a191c70SDaniel Baluta else 12066a191c70SDaniel Baluta base = KMX61_MAG_XOUT_L; 12076a191c70SDaniel Baluta 1208c3a23eccSDaniel Baluta mutex_lock(&data->lock); 120970dddeeeSOctavian Purdila for_each_set_bit(bit, indio_dev->active_scan_mask, 1210c3a23eccSDaniel Baluta indio_dev->masklength) { 12116a191c70SDaniel Baluta ret = kmx61_read_measurement(data, base, bit); 1212c3a23eccSDaniel Baluta if (ret < 0) { 1213c3a23eccSDaniel Baluta mutex_unlock(&data->lock); 1214c3a23eccSDaniel Baluta goto err; 1215c3a23eccSDaniel Baluta } 1216c3a23eccSDaniel Baluta buffer[i++] = ret; 1217c3a23eccSDaniel Baluta } 1218c3a23eccSDaniel Baluta mutex_unlock(&data->lock); 1219c3a23eccSDaniel Baluta 1220c3a23eccSDaniel Baluta iio_push_to_buffers(indio_dev, buffer); 1221c3a23eccSDaniel Baluta err: 1222c3a23eccSDaniel Baluta iio_trigger_notify_done(indio_dev->trig); 1223c3a23eccSDaniel Baluta 1224c3a23eccSDaniel Baluta return IRQ_HANDLED; 1225c3a23eccSDaniel Baluta } 1226c3a23eccSDaniel Baluta 1227b25862c5SDaniel Baluta static const char *kmx61_match_acpi_device(struct device *dev) 1228b25862c5SDaniel Baluta { 1229b25862c5SDaniel Baluta const struct acpi_device_id *id; 1230b25862c5SDaniel Baluta 1231b25862c5SDaniel Baluta id = acpi_match_device(dev->driver->acpi_match_table, dev); 1232b25862c5SDaniel Baluta if (!id) 1233b25862c5SDaniel Baluta return NULL; 1234b25862c5SDaniel Baluta return dev_name(dev); 1235b25862c5SDaniel Baluta } 1236b25862c5SDaniel Baluta 123720ffac27SDaniel Baluta static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data, 123820ffac27SDaniel Baluta const struct iio_info *info, 123920ffac27SDaniel Baluta const struct iio_chan_spec *chan, 124020ffac27SDaniel Baluta int num_channels, 124120ffac27SDaniel Baluta const char *name) 124220ffac27SDaniel Baluta { 124320ffac27SDaniel Baluta struct iio_dev *indio_dev; 124420ffac27SDaniel Baluta 124520ffac27SDaniel Baluta indio_dev = devm_iio_device_alloc(&data->client->dev, sizeof(data)); 124620ffac27SDaniel Baluta if (!indio_dev) 124720ffac27SDaniel Baluta return ERR_PTR(-ENOMEM); 124820ffac27SDaniel Baluta 124920ffac27SDaniel Baluta kmx61_set_data(indio_dev, data); 125020ffac27SDaniel Baluta 125120ffac27SDaniel Baluta indio_dev->channels = chan; 125220ffac27SDaniel Baluta indio_dev->num_channels = num_channels; 125320ffac27SDaniel Baluta indio_dev->name = name; 125420ffac27SDaniel Baluta indio_dev->modes = INDIO_DIRECT_MODE; 125520ffac27SDaniel Baluta indio_dev->info = info; 125620ffac27SDaniel Baluta 125720ffac27SDaniel Baluta return indio_dev; 125820ffac27SDaniel Baluta } 125920ffac27SDaniel Baluta 1260c3a23eccSDaniel Baluta static struct iio_trigger *kmx61_trigger_setup(struct kmx61_data *data, 1261c3a23eccSDaniel Baluta struct iio_dev *indio_dev, 1262c3a23eccSDaniel Baluta const char *tag) 1263c3a23eccSDaniel Baluta { 1264c3a23eccSDaniel Baluta struct iio_trigger *trig; 1265c3a23eccSDaniel Baluta int ret; 1266c3a23eccSDaniel Baluta 1267c3a23eccSDaniel Baluta trig = devm_iio_trigger_alloc(&data->client->dev, 1268c3a23eccSDaniel Baluta "%s-%s-dev%d", 1269c3a23eccSDaniel Baluta indio_dev->name, 1270c3a23eccSDaniel Baluta tag, 1271c3a23eccSDaniel Baluta indio_dev->id); 1272c3a23eccSDaniel Baluta if (!trig) 1273c3a23eccSDaniel Baluta return ERR_PTR(-ENOMEM); 1274c3a23eccSDaniel Baluta 1275c3a23eccSDaniel Baluta trig->dev.parent = &data->client->dev; 1276c3a23eccSDaniel Baluta trig->ops = &kmx61_trigger_ops; 1277c3a23eccSDaniel Baluta iio_trigger_set_drvdata(trig, indio_dev); 1278c3a23eccSDaniel Baluta 1279c3a23eccSDaniel Baluta ret = iio_trigger_register(trig); 1280c3a23eccSDaniel Baluta if (ret) 1281c3a23eccSDaniel Baluta return ERR_PTR(ret); 1282c3a23eccSDaniel Baluta 1283c3a23eccSDaniel Baluta return trig; 1284c3a23eccSDaniel Baluta } 1285c3a23eccSDaniel Baluta 128620ffac27SDaniel Baluta static int kmx61_probe(struct i2c_client *client, 128720ffac27SDaniel Baluta const struct i2c_device_id *id) 128820ffac27SDaniel Baluta { 128920ffac27SDaniel Baluta int ret; 129020ffac27SDaniel Baluta struct kmx61_data *data; 129120ffac27SDaniel Baluta const char *name = NULL; 129220ffac27SDaniel Baluta 129320ffac27SDaniel Baluta data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); 129420ffac27SDaniel Baluta if (!data) 129520ffac27SDaniel Baluta return -ENOMEM; 129620ffac27SDaniel Baluta 129720ffac27SDaniel Baluta i2c_set_clientdata(client, data); 129820ffac27SDaniel Baluta data->client = client; 129920ffac27SDaniel Baluta 130020ffac27SDaniel Baluta mutex_init(&data->lock); 130120ffac27SDaniel Baluta 1302b25862c5SDaniel Baluta if (id) 1303b25862c5SDaniel Baluta name = id->name; 1304b25862c5SDaniel Baluta else if (ACPI_HANDLE(&client->dev)) 1305b25862c5SDaniel Baluta name = kmx61_match_acpi_device(&client->dev); 1306b25862c5SDaniel Baluta else 1307b25862c5SDaniel Baluta return -ENODEV; 1308b25862c5SDaniel Baluta 130920ffac27SDaniel Baluta data->acc_indio_dev = 131020ffac27SDaniel Baluta kmx61_indiodev_setup(data, &kmx61_acc_info, 131120ffac27SDaniel Baluta kmx61_acc_channels, 131220ffac27SDaniel Baluta ARRAY_SIZE(kmx61_acc_channels), 131320ffac27SDaniel Baluta name); 131420ffac27SDaniel Baluta if (IS_ERR(data->acc_indio_dev)) 131520ffac27SDaniel Baluta return PTR_ERR(data->acc_indio_dev); 131620ffac27SDaniel Baluta 131720ffac27SDaniel Baluta data->mag_indio_dev = 131820ffac27SDaniel Baluta kmx61_indiodev_setup(data, &kmx61_mag_info, 131920ffac27SDaniel Baluta kmx61_mag_channels, 132020ffac27SDaniel Baluta ARRAY_SIZE(kmx61_mag_channels), 132120ffac27SDaniel Baluta name); 132220ffac27SDaniel Baluta if (IS_ERR(data->mag_indio_dev)) 132320ffac27SDaniel Baluta return PTR_ERR(data->mag_indio_dev); 132420ffac27SDaniel Baluta 132520ffac27SDaniel Baluta ret = kmx61_chip_init(data); 132620ffac27SDaniel Baluta if (ret < 0) 132720ffac27SDaniel Baluta return ret; 132820ffac27SDaniel Baluta 1329c176becdSOctavian Purdila if (client->irq > 0) { 1330c3a23eccSDaniel Baluta ret = devm_request_threaded_irq(&client->dev, client->irq, 1331c3a23eccSDaniel Baluta kmx61_data_rdy_trig_poll, 1332fd3ae7a9SDaniel Baluta kmx61_event_handler, 1333c3a23eccSDaniel Baluta IRQF_TRIGGER_RISING, 1334c3a23eccSDaniel Baluta KMX61_IRQ_NAME, 1335c3a23eccSDaniel Baluta data); 1336c3a23eccSDaniel Baluta if (ret) 1337c3a23eccSDaniel Baluta goto err_chip_uninit; 1338c3a23eccSDaniel Baluta 1339c3a23eccSDaniel Baluta data->acc_dready_trig = 1340c3a23eccSDaniel Baluta kmx61_trigger_setup(data, data->acc_indio_dev, 1341c3a23eccSDaniel Baluta "dready"); 134228ff344eSDaniel Baluta if (IS_ERR(data->acc_dready_trig)) { 134328ff344eSDaniel Baluta ret = PTR_ERR(data->acc_dready_trig); 134428ff344eSDaniel Baluta goto err_chip_uninit; 134528ff344eSDaniel Baluta } 1346c3a23eccSDaniel Baluta 1347c3a23eccSDaniel Baluta data->mag_dready_trig = 1348c3a23eccSDaniel Baluta kmx61_trigger_setup(data, data->mag_indio_dev, 1349c3a23eccSDaniel Baluta "dready"); 1350c3a23eccSDaniel Baluta if (IS_ERR(data->mag_dready_trig)) { 1351c3a23eccSDaniel Baluta ret = PTR_ERR(data->mag_dready_trig); 135228ff344eSDaniel Baluta goto err_trigger_unregister_acc_dready; 1353c3a23eccSDaniel Baluta } 1354c3a23eccSDaniel Baluta 1355fd3ae7a9SDaniel Baluta data->motion_trig = 1356fd3ae7a9SDaniel Baluta kmx61_trigger_setup(data, data->acc_indio_dev, 1357fd3ae7a9SDaniel Baluta "any-motion"); 1358fd3ae7a9SDaniel Baluta if (IS_ERR(data->motion_trig)) { 1359fd3ae7a9SDaniel Baluta ret = PTR_ERR(data->motion_trig); 136028ff344eSDaniel Baluta goto err_trigger_unregister_mag_dready; 1361fd3ae7a9SDaniel Baluta } 1362fd3ae7a9SDaniel Baluta 1363c3a23eccSDaniel Baluta ret = iio_triggered_buffer_setup(data->acc_indio_dev, 1364c3a23eccSDaniel Baluta &iio_pollfunc_store_time, 1365c3a23eccSDaniel Baluta kmx61_trigger_handler, 1366c3a23eccSDaniel Baluta NULL); 1367c3a23eccSDaniel Baluta if (ret < 0) { 1368c3a23eccSDaniel Baluta dev_err(&data->client->dev, 1369c3a23eccSDaniel Baluta "Failed to setup acc triggered buffer\n"); 137028ff344eSDaniel Baluta goto err_trigger_unregister_motion; 1371c3a23eccSDaniel Baluta } 1372c3a23eccSDaniel Baluta 1373c3a23eccSDaniel Baluta ret = iio_triggered_buffer_setup(data->mag_indio_dev, 1374c3a23eccSDaniel Baluta &iio_pollfunc_store_time, 1375c3a23eccSDaniel Baluta kmx61_trigger_handler, 1376c3a23eccSDaniel Baluta NULL); 1377c3a23eccSDaniel Baluta if (ret < 0) { 1378c3a23eccSDaniel Baluta dev_err(&data->client->dev, 1379c3a23eccSDaniel Baluta "Failed to setup mag triggered buffer\n"); 138028ff344eSDaniel Baluta goto err_buffer_cleanup_acc; 1381c3a23eccSDaniel Baluta } 1382c3a23eccSDaniel Baluta } 1383c3a23eccSDaniel Baluta 13847d0ead5cSAdriana Reus ret = pm_runtime_set_active(&client->dev); 13857d0ead5cSAdriana Reus if (ret < 0) 13867d0ead5cSAdriana Reus goto err_buffer_cleanup_mag; 13877d0ead5cSAdriana Reus 13887d0ead5cSAdriana Reus pm_runtime_enable(&client->dev); 13897d0ead5cSAdriana Reus pm_runtime_set_autosuspend_delay(&client->dev, KMX61_SLEEP_DELAY_MS); 13907d0ead5cSAdriana Reus pm_runtime_use_autosuspend(&client->dev); 13917d0ead5cSAdriana Reus 139220ffac27SDaniel Baluta ret = iio_device_register(data->acc_indio_dev); 139320ffac27SDaniel Baluta if (ret < 0) { 139420ffac27SDaniel Baluta dev_err(&client->dev, "Failed to register acc iio device\n"); 139528ff344eSDaniel Baluta goto err_buffer_cleanup_mag; 139620ffac27SDaniel Baluta } 139720ffac27SDaniel Baluta 139820ffac27SDaniel Baluta ret = iio_device_register(data->mag_indio_dev); 139920ffac27SDaniel Baluta if (ret < 0) { 140020ffac27SDaniel Baluta dev_err(&client->dev, "Failed to register mag iio device\n"); 1401aff8609aSDaniel Baluta goto err_iio_unregister_acc; 140220ffac27SDaniel Baluta } 140320ffac27SDaniel Baluta 140420ffac27SDaniel Baluta return 0; 140520ffac27SDaniel Baluta 1406aff8609aSDaniel Baluta err_iio_unregister_acc: 140720ffac27SDaniel Baluta iio_device_unregister(data->acc_indio_dev); 140828ff344eSDaniel Baluta err_buffer_cleanup_mag: 1409c176becdSOctavian Purdila if (client->irq > 0) 1410c3a23eccSDaniel Baluta iio_triggered_buffer_cleanup(data->mag_indio_dev); 141128ff344eSDaniel Baluta err_buffer_cleanup_acc: 1412c176becdSOctavian Purdila if (client->irq > 0) 141328ff344eSDaniel Baluta iio_triggered_buffer_cleanup(data->acc_indio_dev); 141428ff344eSDaniel Baluta err_trigger_unregister_motion: 1415fd3ae7a9SDaniel Baluta iio_trigger_unregister(data->motion_trig); 141628ff344eSDaniel Baluta err_trigger_unregister_mag_dready: 141728ff344eSDaniel Baluta iio_trigger_unregister(data->mag_dready_trig); 141828ff344eSDaniel Baluta err_trigger_unregister_acc_dready: 141928ff344eSDaniel Baluta iio_trigger_unregister(data->acc_dready_trig); 142020ffac27SDaniel Baluta err_chip_uninit: 142120ffac27SDaniel Baluta kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); 142220ffac27SDaniel Baluta return ret; 142320ffac27SDaniel Baluta } 142420ffac27SDaniel Baluta 142520ffac27SDaniel Baluta static int kmx61_remove(struct i2c_client *client) 142620ffac27SDaniel Baluta { 142720ffac27SDaniel Baluta struct kmx61_data *data = i2c_get_clientdata(client); 142820ffac27SDaniel Baluta 14297d0ead5cSAdriana Reus iio_device_unregister(data->acc_indio_dev); 14307d0ead5cSAdriana Reus iio_device_unregister(data->mag_indio_dev); 14317d0ead5cSAdriana Reus 1432aff8609aSDaniel Baluta pm_runtime_disable(&client->dev); 1433aff8609aSDaniel Baluta pm_runtime_set_suspended(&client->dev); 1434aff8609aSDaniel Baluta pm_runtime_put_noidle(&client->dev); 1435aff8609aSDaniel Baluta 1436c176becdSOctavian Purdila if (client->irq > 0) { 1437c3a23eccSDaniel Baluta iio_triggered_buffer_cleanup(data->acc_indio_dev); 1438c3a23eccSDaniel Baluta iio_triggered_buffer_cleanup(data->mag_indio_dev); 1439c3a23eccSDaniel Baluta iio_trigger_unregister(data->acc_dready_trig); 1440c3a23eccSDaniel Baluta iio_trigger_unregister(data->mag_dready_trig); 1441fd3ae7a9SDaniel Baluta iio_trigger_unregister(data->motion_trig); 1442c3a23eccSDaniel Baluta } 1443c3a23eccSDaniel Baluta 144420ffac27SDaniel Baluta mutex_lock(&data->lock); 144520ffac27SDaniel Baluta kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); 144620ffac27SDaniel Baluta mutex_unlock(&data->lock); 144720ffac27SDaniel Baluta 144820ffac27SDaniel Baluta return 0; 144920ffac27SDaniel Baluta } 145020ffac27SDaniel Baluta 14513b9c40e6SDaniel Baluta #ifdef CONFIG_PM_SLEEP 14523b9c40e6SDaniel Baluta static int kmx61_suspend(struct device *dev) 14533b9c40e6SDaniel Baluta { 14543b9c40e6SDaniel Baluta int ret; 14553b9c40e6SDaniel Baluta struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); 14563b9c40e6SDaniel Baluta 14573b9c40e6SDaniel Baluta mutex_lock(&data->lock); 14583b9c40e6SDaniel Baluta ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, 14593b9c40e6SDaniel Baluta false); 14603b9c40e6SDaniel Baluta mutex_unlock(&data->lock); 14613b9c40e6SDaniel Baluta 14623b9c40e6SDaniel Baluta return ret; 14633b9c40e6SDaniel Baluta } 14643b9c40e6SDaniel Baluta 14653b9c40e6SDaniel Baluta static int kmx61_resume(struct device *dev) 14663b9c40e6SDaniel Baluta { 14673b9c40e6SDaniel Baluta u8 stby = 0; 14683b9c40e6SDaniel Baluta struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); 14693b9c40e6SDaniel Baluta 14703b9c40e6SDaniel Baluta if (data->acc_stby) 14713b9c40e6SDaniel Baluta stby |= KMX61_ACC_STBY_BIT; 14723b9c40e6SDaniel Baluta if (data->mag_stby) 14733b9c40e6SDaniel Baluta stby |= KMX61_MAG_STBY_BIT; 14743b9c40e6SDaniel Baluta 14753b9c40e6SDaniel Baluta return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true); 14763b9c40e6SDaniel Baluta } 14773b9c40e6SDaniel Baluta #endif 1478aff8609aSDaniel Baluta 1479df1fad80SDaniel Baluta #ifdef CONFIG_PM 1480aff8609aSDaniel Baluta static int kmx61_runtime_suspend(struct device *dev) 1481aff8609aSDaniel Baluta { 1482aff8609aSDaniel Baluta struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); 1483aff8609aSDaniel Baluta int ret; 1484aff8609aSDaniel Baluta 1485aff8609aSDaniel Baluta mutex_lock(&data->lock); 1486aff8609aSDaniel Baluta ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); 1487aff8609aSDaniel Baluta mutex_unlock(&data->lock); 1488aff8609aSDaniel Baluta 1489aff8609aSDaniel Baluta return ret; 1490aff8609aSDaniel Baluta } 1491aff8609aSDaniel Baluta 1492aff8609aSDaniel Baluta static int kmx61_runtime_resume(struct device *dev) 1493aff8609aSDaniel Baluta { 1494aff8609aSDaniel Baluta struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); 1495aff8609aSDaniel Baluta u8 stby = 0; 1496aff8609aSDaniel Baluta 1497aff8609aSDaniel Baluta if (!data->acc_ps) 1498aff8609aSDaniel Baluta stby |= KMX61_ACC_STBY_BIT; 1499aff8609aSDaniel Baluta if (!data->mag_ps) 1500aff8609aSDaniel Baluta stby |= KMX61_MAG_STBY_BIT; 1501aff8609aSDaniel Baluta 1502aff8609aSDaniel Baluta return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true); 1503aff8609aSDaniel Baluta } 1504aff8609aSDaniel Baluta #endif 1505aff8609aSDaniel Baluta 1506aff8609aSDaniel Baluta static const struct dev_pm_ops kmx61_pm_ops = { 15073b9c40e6SDaniel Baluta SET_SYSTEM_SLEEP_PM_OPS(kmx61_suspend, kmx61_resume) 1508aff8609aSDaniel Baluta SET_RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL) 1509aff8609aSDaniel Baluta }; 1510aff8609aSDaniel Baluta 1511b25862c5SDaniel Baluta static const struct acpi_device_id kmx61_acpi_match[] = { 1512b25862c5SDaniel Baluta {"KMX61021", 0}, 1513b25862c5SDaniel Baluta {} 1514b25862c5SDaniel Baluta }; 1515b25862c5SDaniel Baluta 1516b25862c5SDaniel Baluta MODULE_DEVICE_TABLE(acpi, kmx61_acpi_match); 1517b25862c5SDaniel Baluta 151820ffac27SDaniel Baluta static const struct i2c_device_id kmx61_id[] = { 151920ffac27SDaniel Baluta {"kmx611021", 0}, 152020ffac27SDaniel Baluta {} 152120ffac27SDaniel Baluta }; 152220ffac27SDaniel Baluta 152320ffac27SDaniel Baluta MODULE_DEVICE_TABLE(i2c, kmx61_id); 152420ffac27SDaniel Baluta 152520ffac27SDaniel Baluta static struct i2c_driver kmx61_driver = { 152620ffac27SDaniel Baluta .driver = { 152720ffac27SDaniel Baluta .name = KMX61_DRV_NAME, 1528b25862c5SDaniel Baluta .acpi_match_table = ACPI_PTR(kmx61_acpi_match), 1529aff8609aSDaniel Baluta .pm = &kmx61_pm_ops, 153020ffac27SDaniel Baluta }, 153120ffac27SDaniel Baluta .probe = kmx61_probe, 153220ffac27SDaniel Baluta .remove = kmx61_remove, 153320ffac27SDaniel Baluta .id_table = kmx61_id, 153420ffac27SDaniel Baluta }; 153520ffac27SDaniel Baluta 153620ffac27SDaniel Baluta module_i2c_driver(kmx61_driver); 153720ffac27SDaniel Baluta 153820ffac27SDaniel Baluta MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); 153920ffac27SDaniel Baluta MODULE_DESCRIPTION("KMX61 accelerometer/magnetometer driver"); 154020ffac27SDaniel Baluta MODULE_LICENSE("GPL v2"); 1541