11a4fbf6aSSrinivas Pandruvada /* 21a4fbf6aSSrinivas Pandruvada * KXCJK-1013 3-axis accelerometer driver 31a4fbf6aSSrinivas Pandruvada * Copyright (c) 2014, Intel Corporation. 41a4fbf6aSSrinivas Pandruvada * 51a4fbf6aSSrinivas Pandruvada * This program is free software; you can redistribute it and/or modify it 61a4fbf6aSSrinivas Pandruvada * under the terms and conditions of the GNU General Public License, 71a4fbf6aSSrinivas Pandruvada * version 2, as published by the Free Software Foundation. 81a4fbf6aSSrinivas Pandruvada * 91a4fbf6aSSrinivas Pandruvada * This program is distributed in the hope it will be useful, but WITHOUT 101a4fbf6aSSrinivas Pandruvada * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 111a4fbf6aSSrinivas Pandruvada * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 121a4fbf6aSSrinivas Pandruvada * more details. 131a4fbf6aSSrinivas Pandruvada */ 141a4fbf6aSSrinivas Pandruvada 151a4fbf6aSSrinivas Pandruvada #include <linux/module.h> 161a4fbf6aSSrinivas Pandruvada #include <linux/i2c.h> 171a4fbf6aSSrinivas Pandruvada #include <linux/interrupt.h> 181a4fbf6aSSrinivas Pandruvada #include <linux/delay.h> 191a4fbf6aSSrinivas Pandruvada #include <linux/bitops.h> 201a4fbf6aSSrinivas Pandruvada #include <linux/slab.h> 211a4fbf6aSSrinivas Pandruvada #include <linux/string.h> 221a4fbf6aSSrinivas Pandruvada #include <linux/acpi.h> 23124e1b1dSSrinivas Pandruvada #include <linux/pm.h> 24124e1b1dSSrinivas Pandruvada #include <linux/pm_runtime.h> 251a4fbf6aSSrinivas Pandruvada #include <linux/iio/iio.h> 261a4fbf6aSSrinivas Pandruvada #include <linux/iio/sysfs.h> 271a4fbf6aSSrinivas Pandruvada #include <linux/iio/buffer.h> 281a4fbf6aSSrinivas Pandruvada #include <linux/iio/trigger.h> 29b4b491c0SSrinivas Pandruvada #include <linux/iio/events.h> 301a4fbf6aSSrinivas Pandruvada #include <linux/iio/trigger_consumer.h> 311a4fbf6aSSrinivas Pandruvada #include <linux/iio/triggered_buffer.h> 321a4fbf6aSSrinivas Pandruvada #include <linux/iio/accel/kxcjk_1013.h> 331a4fbf6aSSrinivas Pandruvada 341a4fbf6aSSrinivas Pandruvada #define KXCJK1013_DRV_NAME "kxcjk1013" 351a4fbf6aSSrinivas Pandruvada #define KXCJK1013_IRQ_NAME "kxcjk1013_event" 361a4fbf6aSSrinivas Pandruvada 371a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_XOUT_L 0x06 381a4fbf6aSSrinivas Pandruvada /* 391a4fbf6aSSrinivas Pandruvada * From low byte X axis register, all the other addresses of Y and Z can be 401a4fbf6aSSrinivas Pandruvada * obtained by just applying axis offset. The following axis defines are just 411a4fbf6aSSrinivas Pandruvada * provide clarity, but not used. 421a4fbf6aSSrinivas Pandruvada */ 431a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_XOUT_H 0x07 441a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_YOUT_L 0x08 451a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_YOUT_H 0x09 461a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_ZOUT_L 0x0A 471a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_ZOUT_H 0x0B 481a4fbf6aSSrinivas Pandruvada 491a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_DCST_RESP 0x0C 501a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_WHO_AM_I 0x0F 511a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_INT_SRC1 0x16 521a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_INT_SRC2 0x17 531a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_STATUS_REG 0x18 541a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_INT_REL 0x1A 551a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_CTRL1 0x1B 561a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_CTRL2 0x1D 571a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_INT_CTRL1 0x1E 581a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_INT_CTRL2 0x1F 591a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_DATA_CTRL 0x21 601a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_WAKE_TIMER 0x29 611a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_SELF_TEST 0x3A 621a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_WAKE_THRES 0x6A 631a4fbf6aSSrinivas Pandruvada 641a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_CTRL1_BIT_PC1 BIT(7) 651a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_CTRL1_BIT_RES BIT(6) 661a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_CTRL1_BIT_DRDY BIT(5) 671a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_CTRL1_BIT_GSEL1 BIT(4) 681a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_CTRL1_BIT_GSEL0 BIT(3) 691a4fbf6aSSrinivas Pandruvada #define KXCJK1013_REG_CTRL1_BIT_WUFE BIT(1) 70*f74e440cSMichał Mirosław 71*f74e440cSMichał Mirosław #define KXCJK1013_REG_INT_CTRL1_BIT_IEL BIT(3) 72*f74e440cSMichał Mirosław #define KXCJK1013_REG_INT_CTRL1_BIT_IEA BIT(4) 73*f74e440cSMichał Mirosław #define KXCJK1013_REG_INT_CTRL1_BIT_IEN BIT(5) 741a4fbf6aSSrinivas Pandruvada 751a4fbf6aSSrinivas Pandruvada #define KXCJK1013_DATA_MASK_12_BIT 0x0FFF 761a4fbf6aSSrinivas Pandruvada #define KXCJK1013_MAX_STARTUP_TIME_US 100000 771a4fbf6aSSrinivas Pandruvada 78124e1b1dSSrinivas Pandruvada #define KXCJK1013_SLEEP_DELAY_MS 2000 79124e1b1dSSrinivas Pandruvada 80*f74e440cSMichał Mirosław #define KXCJK1013_REG_INT_SRC1_BIT_WUFS BIT(1) 81*f74e440cSMichał Mirosław #define KXCJK1013_REG_INT_SRC1_BIT_DRDY BIT(4) 82*f74e440cSMichał Mirosław 83b4b491c0SSrinivas Pandruvada #define KXCJK1013_REG_INT_SRC2_BIT_ZP BIT(0) 84b4b491c0SSrinivas Pandruvada #define KXCJK1013_REG_INT_SRC2_BIT_ZN BIT(1) 85b4b491c0SSrinivas Pandruvada #define KXCJK1013_REG_INT_SRC2_BIT_YP BIT(2) 86b4b491c0SSrinivas Pandruvada #define KXCJK1013_REG_INT_SRC2_BIT_YN BIT(3) 87b4b491c0SSrinivas Pandruvada #define KXCJK1013_REG_INT_SRC2_BIT_XP BIT(4) 88b4b491c0SSrinivas Pandruvada #define KXCJK1013_REG_INT_SRC2_BIT_XN BIT(5) 89b4b491c0SSrinivas Pandruvada 90b4b491c0SSrinivas Pandruvada #define KXCJK1013_DEFAULT_WAKE_THRES 1 91b4b491c0SSrinivas Pandruvada 92c6861377SDaniel Baluta enum kx_chipset { 93c6861377SDaniel Baluta KXCJK1013, 94c6861377SDaniel Baluta KXCJ91008, 95c6861377SDaniel Baluta KXTJ21009, 96c6861377SDaniel Baluta KX_MAX_CHIPS /* this must be last */ 97c6861377SDaniel Baluta }; 98c6861377SDaniel Baluta 991a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data { 1001a4fbf6aSSrinivas Pandruvada struct i2c_client *client; 101b4b491c0SSrinivas Pandruvada struct iio_trigger *dready_trig; 102b4b491c0SSrinivas Pandruvada struct iio_trigger *motion_trig; 1031a4fbf6aSSrinivas Pandruvada struct mutex mutex; 1041a4fbf6aSSrinivas Pandruvada s16 buffer[8]; 1051a4fbf6aSSrinivas Pandruvada u8 odr_bits; 106a735e3d7SSrinivas Pandruvada u8 range; 107b4b491c0SSrinivas Pandruvada int wake_thres; 108b4b491c0SSrinivas Pandruvada int wake_dur; 1091a4fbf6aSSrinivas Pandruvada bool active_high_intr; 110b4b491c0SSrinivas Pandruvada bool dready_trigger_on; 111b4b491c0SSrinivas Pandruvada int ev_enable_state; 112b4b491c0SSrinivas Pandruvada bool motion_trigger_on; 113b4b491c0SSrinivas Pandruvada int64_t timestamp; 114c6861377SDaniel Baluta enum kx_chipset chipset; 1153bfa74f8SBastien Nocera bool is_smo8500_device; 1161a4fbf6aSSrinivas Pandruvada }; 1171a4fbf6aSSrinivas Pandruvada 1181a4fbf6aSSrinivas Pandruvada enum kxcjk1013_axis { 1191a4fbf6aSSrinivas Pandruvada AXIS_X, 1201a4fbf6aSSrinivas Pandruvada AXIS_Y, 1211a4fbf6aSSrinivas Pandruvada AXIS_Z, 12209cf1b32SAdriana Reus AXIS_MAX, 1231a4fbf6aSSrinivas Pandruvada }; 1241a4fbf6aSSrinivas Pandruvada 1251a4fbf6aSSrinivas Pandruvada enum kxcjk1013_mode { 1261a4fbf6aSSrinivas Pandruvada STANDBY, 1271a4fbf6aSSrinivas Pandruvada OPERATION, 1281a4fbf6aSSrinivas Pandruvada }; 1291a4fbf6aSSrinivas Pandruvada 130a735e3d7SSrinivas Pandruvada enum kxcjk1013_range { 131a735e3d7SSrinivas Pandruvada KXCJK1013_RANGE_2G, 132a735e3d7SSrinivas Pandruvada KXCJK1013_RANGE_4G, 133a735e3d7SSrinivas Pandruvada KXCJK1013_RANGE_8G, 134a735e3d7SSrinivas Pandruvada }; 135a735e3d7SSrinivas Pandruvada 1367469ac69SMichał Mirosław struct kx_odr_map { 1371a4fbf6aSSrinivas Pandruvada int val; 1381a4fbf6aSSrinivas Pandruvada int val2; 1391a4fbf6aSSrinivas Pandruvada int odr_bits; 1407469ac69SMichał Mirosław int wuf_bits; 1417469ac69SMichał Mirosław }; 1427469ac69SMichał Mirosław 1437469ac69SMichał Mirosław static const struct kx_odr_map samp_freq_table[] = { 1447469ac69SMichał Mirosław { 0, 781000, 0x08, 0x00 }, 1457469ac69SMichał Mirosław { 1, 563000, 0x09, 0x01 }, 1467469ac69SMichał Mirosław { 3, 125000, 0x0A, 0x02 }, 1477469ac69SMichał Mirosław { 6, 250000, 0x0B, 0x03 }, 1487469ac69SMichał Mirosław { 12, 500000, 0x00, 0x04 }, 1497469ac69SMichał Mirosław { 25, 0, 0x01, 0x05 }, 1507469ac69SMichał Mirosław { 50, 0, 0x02, 0x06 }, 1517469ac69SMichał Mirosław { 100, 0, 0x03, 0x06 }, 1527469ac69SMichał Mirosław { 200, 0, 0x04, 0x06 }, 1537469ac69SMichał Mirosław { 400, 0, 0x05, 0x06 }, 1547469ac69SMichał Mirosław { 800, 0, 0x06, 0x06 }, 1557469ac69SMichał Mirosław { 1600, 0, 0x07, 0x06 }, 1567469ac69SMichał Mirosław }; 1571a4fbf6aSSrinivas Pandruvada 1581a4fbf6aSSrinivas Pandruvada /* Refer to section 4 of the specification */ 1591a4fbf6aSSrinivas Pandruvada static const struct { 1601a4fbf6aSSrinivas Pandruvada int odr_bits; 1611a4fbf6aSSrinivas Pandruvada int usec; 162c6861377SDaniel Baluta } odr_start_up_times[KX_MAX_CHIPS][12] = { 163c6861377SDaniel Baluta /* KXCJK-1013 */ 164c6861377SDaniel Baluta { 165c6861377SDaniel Baluta {0x08, 100000}, 166c6861377SDaniel Baluta {0x09, 100000}, 167c6861377SDaniel Baluta {0x0A, 100000}, 168c6861377SDaniel Baluta {0x0B, 100000}, 169c6861377SDaniel Baluta {0, 80000}, 170c6861377SDaniel Baluta {0x01, 41000}, 171c6861377SDaniel Baluta {0x02, 21000}, 172c6861377SDaniel Baluta {0x03, 11000}, 173c6861377SDaniel Baluta {0x04, 6400}, 174c6861377SDaniel Baluta {0x05, 3900}, 175c6861377SDaniel Baluta {0x06, 2700}, 176c6861377SDaniel Baluta {0x07, 2100}, 177c6861377SDaniel Baluta }, 178c6861377SDaniel Baluta /* KXCJ9-1008 */ 179c6861377SDaniel Baluta { 180c6861377SDaniel Baluta {0x08, 100000}, 181c6861377SDaniel Baluta {0x09, 100000}, 182c6861377SDaniel Baluta {0x0A, 100000}, 183c6861377SDaniel Baluta {0x0B, 100000}, 184c6861377SDaniel Baluta {0, 80000}, 185c6861377SDaniel Baluta {0x01, 41000}, 186c6861377SDaniel Baluta {0x02, 21000}, 187c6861377SDaniel Baluta {0x03, 11000}, 188c6861377SDaniel Baluta {0x04, 6400}, 189c6861377SDaniel Baluta {0x05, 3900}, 190c6861377SDaniel Baluta {0x06, 2700}, 191c6861377SDaniel Baluta {0x07, 2100}, 192c6861377SDaniel Baluta }, 193c6861377SDaniel Baluta /* KXCTJ2-1009 */ 194c6861377SDaniel Baluta { 195c6861377SDaniel Baluta {0x08, 1240000}, 196c6861377SDaniel Baluta {0x09, 621000}, 197c6861377SDaniel Baluta {0x0A, 309000}, 198c6861377SDaniel Baluta {0x0B, 151000}, 199c6861377SDaniel Baluta {0, 80000}, 200c6861377SDaniel Baluta {0x01, 41000}, 201c6861377SDaniel Baluta {0x02, 21000}, 202c6861377SDaniel Baluta {0x03, 11000}, 203c6861377SDaniel Baluta {0x04, 6000}, 204c6861377SDaniel Baluta {0x05, 4000}, 205c6861377SDaniel Baluta {0x06, 3000}, 206c6861377SDaniel Baluta {0x07, 2000}, 207c6861377SDaniel Baluta }, 208c6861377SDaniel Baluta }; 2091a4fbf6aSSrinivas Pandruvada 210a735e3d7SSrinivas Pandruvada static const struct { 211a735e3d7SSrinivas Pandruvada u16 scale; 212a735e3d7SSrinivas Pandruvada u8 gsel_0; 213a735e3d7SSrinivas Pandruvada u8 gsel_1; 214a735e3d7SSrinivas Pandruvada } KXCJK1013_scale_table[] = { {9582, 0, 0}, 215a735e3d7SSrinivas Pandruvada {19163, 1, 0}, 216a735e3d7SSrinivas Pandruvada {38326, 0, 1} }; 217a735e3d7SSrinivas Pandruvada 2181a4fbf6aSSrinivas Pandruvada static int kxcjk1013_set_mode(struct kxcjk1013_data *data, 2191a4fbf6aSSrinivas Pandruvada enum kxcjk1013_mode mode) 2201a4fbf6aSSrinivas Pandruvada { 2211a4fbf6aSSrinivas Pandruvada int ret; 2221a4fbf6aSSrinivas Pandruvada 2231a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); 2241a4fbf6aSSrinivas Pandruvada if (ret < 0) { 2251a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 2261a4fbf6aSSrinivas Pandruvada return ret; 2271a4fbf6aSSrinivas Pandruvada } 2281a4fbf6aSSrinivas Pandruvada 2291a4fbf6aSSrinivas Pandruvada if (mode == STANDBY) 2301a4fbf6aSSrinivas Pandruvada ret &= ~KXCJK1013_REG_CTRL1_BIT_PC1; 2311a4fbf6aSSrinivas Pandruvada else 2321a4fbf6aSSrinivas Pandruvada ret |= KXCJK1013_REG_CTRL1_BIT_PC1; 2331a4fbf6aSSrinivas Pandruvada 2341a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 2351a4fbf6aSSrinivas Pandruvada KXCJK1013_REG_CTRL1, ret); 2361a4fbf6aSSrinivas Pandruvada if (ret < 0) { 2371a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); 2381a4fbf6aSSrinivas Pandruvada return ret; 2391a4fbf6aSSrinivas Pandruvada } 2401a4fbf6aSSrinivas Pandruvada 2411a4fbf6aSSrinivas Pandruvada return 0; 2421a4fbf6aSSrinivas Pandruvada } 2431a4fbf6aSSrinivas Pandruvada 244124e1b1dSSrinivas Pandruvada static int kxcjk1013_get_mode(struct kxcjk1013_data *data, 245124e1b1dSSrinivas Pandruvada enum kxcjk1013_mode *mode) 246124e1b1dSSrinivas Pandruvada { 247124e1b1dSSrinivas Pandruvada int ret; 248124e1b1dSSrinivas Pandruvada 249124e1b1dSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); 250124e1b1dSSrinivas Pandruvada if (ret < 0) { 251124e1b1dSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 252124e1b1dSSrinivas Pandruvada return ret; 253124e1b1dSSrinivas Pandruvada } 254124e1b1dSSrinivas Pandruvada 255124e1b1dSSrinivas Pandruvada if (ret & KXCJK1013_REG_CTRL1_BIT_PC1) 256124e1b1dSSrinivas Pandruvada *mode = OPERATION; 257124e1b1dSSrinivas Pandruvada else 258124e1b1dSSrinivas Pandruvada *mode = STANDBY; 259124e1b1dSSrinivas Pandruvada 260124e1b1dSSrinivas Pandruvada return 0; 261124e1b1dSSrinivas Pandruvada } 262124e1b1dSSrinivas Pandruvada 263a735e3d7SSrinivas Pandruvada static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index) 264a735e3d7SSrinivas Pandruvada { 265a735e3d7SSrinivas Pandruvada int ret; 266a735e3d7SSrinivas Pandruvada 267a735e3d7SSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); 268a735e3d7SSrinivas Pandruvada if (ret < 0) { 269a735e3d7SSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 270a735e3d7SSrinivas Pandruvada return ret; 271a735e3d7SSrinivas Pandruvada } 272a735e3d7SSrinivas Pandruvada 273e90dea6aSDaniel Baluta ret &= ~(KXCJK1013_REG_CTRL1_BIT_GSEL0 | 274e90dea6aSDaniel Baluta KXCJK1013_REG_CTRL1_BIT_GSEL1); 275a735e3d7SSrinivas Pandruvada ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3); 276a735e3d7SSrinivas Pandruvada ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4); 277a735e3d7SSrinivas Pandruvada 278a735e3d7SSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 279a735e3d7SSrinivas Pandruvada KXCJK1013_REG_CTRL1, 280a735e3d7SSrinivas Pandruvada ret); 281a735e3d7SSrinivas Pandruvada if (ret < 0) { 282a735e3d7SSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); 283a735e3d7SSrinivas Pandruvada return ret; 284a735e3d7SSrinivas Pandruvada } 285a735e3d7SSrinivas Pandruvada 286a735e3d7SSrinivas Pandruvada data->range = range_index; 287a735e3d7SSrinivas Pandruvada 288a735e3d7SSrinivas Pandruvada return 0; 289a735e3d7SSrinivas Pandruvada } 290a735e3d7SSrinivas Pandruvada 2911a4fbf6aSSrinivas Pandruvada static int kxcjk1013_chip_init(struct kxcjk1013_data *data) 2921a4fbf6aSSrinivas Pandruvada { 2931a4fbf6aSSrinivas Pandruvada int ret; 2941a4fbf6aSSrinivas Pandruvada 2951a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_WHO_AM_I); 2961a4fbf6aSSrinivas Pandruvada if (ret < 0) { 2971a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading who_am_i\n"); 2981a4fbf6aSSrinivas Pandruvada return ret; 2991a4fbf6aSSrinivas Pandruvada } 3001a4fbf6aSSrinivas Pandruvada 3011a4fbf6aSSrinivas Pandruvada dev_dbg(&data->client->dev, "KXCJK1013 Chip Id %x\n", ret); 3021a4fbf6aSSrinivas Pandruvada 3031a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, STANDBY); 3041a4fbf6aSSrinivas Pandruvada if (ret < 0) 3051a4fbf6aSSrinivas Pandruvada return ret; 3061a4fbf6aSSrinivas Pandruvada 3071a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); 3081a4fbf6aSSrinivas Pandruvada if (ret < 0) { 3091a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 3101a4fbf6aSSrinivas Pandruvada return ret; 3111a4fbf6aSSrinivas Pandruvada } 3121a4fbf6aSSrinivas Pandruvada 3131a4fbf6aSSrinivas Pandruvada /* Set 12 bit mode */ 3141a4fbf6aSSrinivas Pandruvada ret |= KXCJK1013_REG_CTRL1_BIT_RES; 3151a4fbf6aSSrinivas Pandruvada 3161a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_CTRL1, 3171a4fbf6aSSrinivas Pandruvada ret); 3181a4fbf6aSSrinivas Pandruvada if (ret < 0) { 3191a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_ctrl\n"); 3201a4fbf6aSSrinivas Pandruvada return ret; 3211a4fbf6aSSrinivas Pandruvada } 3221a4fbf6aSSrinivas Pandruvada 323a735e3d7SSrinivas Pandruvada /* Setting range to 4G */ 324a735e3d7SSrinivas Pandruvada ret = kxcjk1013_set_range(data, KXCJK1013_RANGE_4G); 325a735e3d7SSrinivas Pandruvada if (ret < 0) 326a735e3d7SSrinivas Pandruvada return ret; 327a735e3d7SSrinivas Pandruvada 3281a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_DATA_CTRL); 3291a4fbf6aSSrinivas Pandruvada if (ret < 0) { 3301a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_data_ctrl\n"); 3311a4fbf6aSSrinivas Pandruvada return ret; 3321a4fbf6aSSrinivas Pandruvada } 3331a4fbf6aSSrinivas Pandruvada 3341a4fbf6aSSrinivas Pandruvada data->odr_bits = ret; 3351a4fbf6aSSrinivas Pandruvada 3361a4fbf6aSSrinivas Pandruvada /* Set up INT polarity */ 3371a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1); 3381a4fbf6aSSrinivas Pandruvada if (ret < 0) { 3391a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); 3401a4fbf6aSSrinivas Pandruvada return ret; 3411a4fbf6aSSrinivas Pandruvada } 3421a4fbf6aSSrinivas Pandruvada 3431a4fbf6aSSrinivas Pandruvada if (data->active_high_intr) 344*f74e440cSMichał Mirosław ret |= KXCJK1013_REG_INT_CTRL1_BIT_IEA; 3451a4fbf6aSSrinivas Pandruvada else 346*f74e440cSMichał Mirosław ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEA; 3471a4fbf6aSSrinivas Pandruvada 3481a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1, 3491a4fbf6aSSrinivas Pandruvada ret); 3501a4fbf6aSSrinivas Pandruvada if (ret < 0) { 3511a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); 3521a4fbf6aSSrinivas Pandruvada return ret; 3531a4fbf6aSSrinivas Pandruvada } 3541a4fbf6aSSrinivas Pandruvada 355124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, OPERATION); 356124e1b1dSSrinivas Pandruvada if (ret < 0) 357124e1b1dSSrinivas Pandruvada return ret; 358124e1b1dSSrinivas Pandruvada 359b4b491c0SSrinivas Pandruvada data->wake_thres = KXCJK1013_DEFAULT_WAKE_THRES; 360b4b491c0SSrinivas Pandruvada 361124e1b1dSSrinivas Pandruvada return 0; 362124e1b1dSSrinivas Pandruvada } 363124e1b1dSSrinivas Pandruvada 3646f0a13f2SRafael J. Wysocki #ifdef CONFIG_PM 365124e1b1dSSrinivas Pandruvada static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data) 366124e1b1dSSrinivas Pandruvada { 367124e1b1dSSrinivas Pandruvada int i; 368c6861377SDaniel Baluta int idx = data->chipset; 369124e1b1dSSrinivas Pandruvada 370c6861377SDaniel Baluta for (i = 0; i < ARRAY_SIZE(odr_start_up_times[idx]); ++i) { 371c6861377SDaniel Baluta if (odr_start_up_times[idx][i].odr_bits == data->odr_bits) 372c6861377SDaniel Baluta return odr_start_up_times[idx][i].usec; 373124e1b1dSSrinivas Pandruvada } 374124e1b1dSSrinivas Pandruvada 375124e1b1dSSrinivas Pandruvada return KXCJK1013_MAX_STARTUP_TIME_US; 376124e1b1dSSrinivas Pandruvada } 377c9bf2373SDaniel Baluta #endif 378124e1b1dSSrinivas Pandruvada 379124e1b1dSSrinivas Pandruvada static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) 380124e1b1dSSrinivas Pandruvada { 381c75b8dc8SIrina Tirdea #ifdef CONFIG_PM 382124e1b1dSSrinivas Pandruvada int ret; 383124e1b1dSSrinivas Pandruvada 384124e1b1dSSrinivas Pandruvada if (on) 385124e1b1dSSrinivas Pandruvada ret = pm_runtime_get_sync(&data->client->dev); 386124e1b1dSSrinivas Pandruvada else { 387124e1b1dSSrinivas Pandruvada pm_runtime_mark_last_busy(&data->client->dev); 388124e1b1dSSrinivas Pandruvada ret = pm_runtime_put_autosuspend(&data->client->dev); 389124e1b1dSSrinivas Pandruvada } 390124e1b1dSSrinivas Pandruvada if (ret < 0) { 391124e1b1dSSrinivas Pandruvada dev_err(&data->client->dev, 392124e1b1dSSrinivas Pandruvada "Failed: kxcjk1013_set_power_state for %d\n", on); 393fbd123e9SIrina Tirdea if (on) 394fbd123e9SIrina Tirdea pm_runtime_put_noidle(&data->client->dev); 395124e1b1dSSrinivas Pandruvada return ret; 396124e1b1dSSrinivas Pandruvada } 397c75b8dc8SIrina Tirdea #endif 398124e1b1dSSrinivas Pandruvada 3991a4fbf6aSSrinivas Pandruvada return 0; 4001a4fbf6aSSrinivas Pandruvada } 4011a4fbf6aSSrinivas Pandruvada 402b4b491c0SSrinivas Pandruvada static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data) 403b4b491c0SSrinivas Pandruvada { 404b4b491c0SSrinivas Pandruvada int ret; 405b4b491c0SSrinivas Pandruvada 406b4b491c0SSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 407b4b491c0SSrinivas Pandruvada KXCJK1013_REG_WAKE_TIMER, 408b4b491c0SSrinivas Pandruvada data->wake_dur); 409b4b491c0SSrinivas Pandruvada if (ret < 0) { 410b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, 411b4b491c0SSrinivas Pandruvada "Error writing reg_wake_timer\n"); 412b4b491c0SSrinivas Pandruvada return ret; 413b4b491c0SSrinivas Pandruvada } 414b4b491c0SSrinivas Pandruvada 415b4b491c0SSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 416b4b491c0SSrinivas Pandruvada KXCJK1013_REG_WAKE_THRES, 417b4b491c0SSrinivas Pandruvada data->wake_thres); 418b4b491c0SSrinivas Pandruvada if (ret < 0) { 419b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_wake_thres\n"); 420b4b491c0SSrinivas Pandruvada return ret; 421b4b491c0SSrinivas Pandruvada } 422b4b491c0SSrinivas Pandruvada 423b4b491c0SSrinivas Pandruvada return 0; 424b4b491c0SSrinivas Pandruvada } 425b4b491c0SSrinivas Pandruvada 426b4b491c0SSrinivas Pandruvada static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, 427b4b491c0SSrinivas Pandruvada bool status) 428b4b491c0SSrinivas Pandruvada { 429b4b491c0SSrinivas Pandruvada int ret; 430b4b491c0SSrinivas Pandruvada enum kxcjk1013_mode store_mode; 431b4b491c0SSrinivas Pandruvada 432b4b491c0SSrinivas Pandruvada ret = kxcjk1013_get_mode(data, &store_mode); 433b4b491c0SSrinivas Pandruvada if (ret < 0) 434b4b491c0SSrinivas Pandruvada return ret; 435b4b491c0SSrinivas Pandruvada 436b4b491c0SSrinivas Pandruvada /* This is requirement by spec to change state to STANDBY */ 437b4b491c0SSrinivas Pandruvada ret = kxcjk1013_set_mode(data, STANDBY); 438b4b491c0SSrinivas Pandruvada if (ret < 0) 439b4b491c0SSrinivas Pandruvada return ret; 440b4b491c0SSrinivas Pandruvada 441b4b491c0SSrinivas Pandruvada ret = kxcjk1013_chip_update_thresholds(data); 442b4b491c0SSrinivas Pandruvada if (ret < 0) 443b4b491c0SSrinivas Pandruvada return ret; 444b4b491c0SSrinivas Pandruvada 445b4b491c0SSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1); 446b4b491c0SSrinivas Pandruvada if (ret < 0) { 447b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); 448b4b491c0SSrinivas Pandruvada return ret; 449b4b491c0SSrinivas Pandruvada } 450b4b491c0SSrinivas Pandruvada 451b4b491c0SSrinivas Pandruvada if (status) 452*f74e440cSMichał Mirosław ret |= KXCJK1013_REG_INT_CTRL1_BIT_IEN; 453b4b491c0SSrinivas Pandruvada else 454*f74e440cSMichał Mirosław ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; 455b4b491c0SSrinivas Pandruvada 456b4b491c0SSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1, 457b4b491c0SSrinivas Pandruvada ret); 458b4b491c0SSrinivas Pandruvada if (ret < 0) { 459b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); 460b4b491c0SSrinivas Pandruvada return ret; 461b4b491c0SSrinivas Pandruvada } 462b4b491c0SSrinivas Pandruvada 463b4b491c0SSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); 464b4b491c0SSrinivas Pandruvada if (ret < 0) { 465b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 466b4b491c0SSrinivas Pandruvada return ret; 467b4b491c0SSrinivas Pandruvada } 468b4b491c0SSrinivas Pandruvada 469b4b491c0SSrinivas Pandruvada if (status) 470b4b491c0SSrinivas Pandruvada ret |= KXCJK1013_REG_CTRL1_BIT_WUFE; 471b4b491c0SSrinivas Pandruvada else 472b4b491c0SSrinivas Pandruvada ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE; 473b4b491c0SSrinivas Pandruvada 474b4b491c0SSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 475b4b491c0SSrinivas Pandruvada KXCJK1013_REG_CTRL1, ret); 476b4b491c0SSrinivas Pandruvada if (ret < 0) { 477b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); 478b4b491c0SSrinivas Pandruvada return ret; 479b4b491c0SSrinivas Pandruvada } 480b4b491c0SSrinivas Pandruvada 481b4b491c0SSrinivas Pandruvada if (store_mode == OPERATION) { 482b4b491c0SSrinivas Pandruvada ret = kxcjk1013_set_mode(data, OPERATION); 483b4b491c0SSrinivas Pandruvada if (ret < 0) 484b4b491c0SSrinivas Pandruvada return ret; 485b4b491c0SSrinivas Pandruvada } 486b4b491c0SSrinivas Pandruvada 487b4b491c0SSrinivas Pandruvada return 0; 488b4b491c0SSrinivas Pandruvada } 489b4b491c0SSrinivas Pandruvada 490b4b491c0SSrinivas Pandruvada static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, 4911a4fbf6aSSrinivas Pandruvada bool status) 4921a4fbf6aSSrinivas Pandruvada { 4931a4fbf6aSSrinivas Pandruvada int ret; 494124e1b1dSSrinivas Pandruvada enum kxcjk1013_mode store_mode; 495124e1b1dSSrinivas Pandruvada 496124e1b1dSSrinivas Pandruvada ret = kxcjk1013_get_mode(data, &store_mode); 497124e1b1dSSrinivas Pandruvada if (ret < 0) 498124e1b1dSSrinivas Pandruvada return ret; 4991a4fbf6aSSrinivas Pandruvada 5001a4fbf6aSSrinivas Pandruvada /* This is requirement by spec to change state to STANDBY */ 5011a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, STANDBY); 5021a4fbf6aSSrinivas Pandruvada if (ret < 0) 5031a4fbf6aSSrinivas Pandruvada return ret; 5041a4fbf6aSSrinivas Pandruvada 5051a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1); 5061a4fbf6aSSrinivas Pandruvada if (ret < 0) { 5071a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); 5081a4fbf6aSSrinivas Pandruvada return ret; 5091a4fbf6aSSrinivas Pandruvada } 5101a4fbf6aSSrinivas Pandruvada 5111a4fbf6aSSrinivas Pandruvada if (status) 512*f74e440cSMichał Mirosław ret |= KXCJK1013_REG_INT_CTRL1_BIT_IEN; 5131a4fbf6aSSrinivas Pandruvada else 514*f74e440cSMichał Mirosław ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; 5151a4fbf6aSSrinivas Pandruvada 5161a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1, 5171a4fbf6aSSrinivas Pandruvada ret); 5181a4fbf6aSSrinivas Pandruvada if (ret < 0) { 5191a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); 5201a4fbf6aSSrinivas Pandruvada return ret; 5211a4fbf6aSSrinivas Pandruvada } 5221a4fbf6aSSrinivas Pandruvada 5231a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); 5241a4fbf6aSSrinivas Pandruvada if (ret < 0) { 5251a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 5261a4fbf6aSSrinivas Pandruvada return ret; 5271a4fbf6aSSrinivas Pandruvada } 5281a4fbf6aSSrinivas Pandruvada 5291a4fbf6aSSrinivas Pandruvada if (status) 5301a4fbf6aSSrinivas Pandruvada ret |= KXCJK1013_REG_CTRL1_BIT_DRDY; 5311a4fbf6aSSrinivas Pandruvada else 5321a4fbf6aSSrinivas Pandruvada ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY; 5331a4fbf6aSSrinivas Pandruvada 5341a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 5351a4fbf6aSSrinivas Pandruvada KXCJK1013_REG_CTRL1, ret); 5361a4fbf6aSSrinivas Pandruvada if (ret < 0) { 5371a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); 5381a4fbf6aSSrinivas Pandruvada return ret; 5391a4fbf6aSSrinivas Pandruvada } 5401a4fbf6aSSrinivas Pandruvada 541124e1b1dSSrinivas Pandruvada if (store_mode == OPERATION) { 542124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, OPERATION); 543124e1b1dSSrinivas Pandruvada if (ret < 0) 5441a4fbf6aSSrinivas Pandruvada return ret; 5451a4fbf6aSSrinivas Pandruvada } 5461a4fbf6aSSrinivas Pandruvada 547124e1b1dSSrinivas Pandruvada return 0; 548124e1b1dSSrinivas Pandruvada } 549124e1b1dSSrinivas Pandruvada 5507469ac69SMichał Mirosław static const struct kx_odr_map *kxcjk1013_find_odr_value( 5517469ac69SMichał Mirosław const struct kx_odr_map *map, size_t map_size, int val, int val2) 5521a4fbf6aSSrinivas Pandruvada { 5531a4fbf6aSSrinivas Pandruvada int i; 5541a4fbf6aSSrinivas Pandruvada 5557469ac69SMichał Mirosław for (i = 0; i < map_size; ++i) { 5567469ac69SMichał Mirosław if (map[i].val == val && map[i].val2 == val2) 5577469ac69SMichał Mirosław return &map[i]; 5581a4fbf6aSSrinivas Pandruvada } 5591a4fbf6aSSrinivas Pandruvada 5607469ac69SMichał Mirosław return ERR_PTR(-EINVAL); 5611a4fbf6aSSrinivas Pandruvada } 5621a4fbf6aSSrinivas Pandruvada 5637469ac69SMichał Mirosław static int kxcjk1013_convert_odr_value(const struct kx_odr_map *map, 5647469ac69SMichał Mirosław size_t map_size, int odr_bits, 5657469ac69SMichał Mirosław int *val, int *val2) 566b4b491c0SSrinivas Pandruvada { 567b4b491c0SSrinivas Pandruvada int i; 568b4b491c0SSrinivas Pandruvada 5697469ac69SMichał Mirosław for (i = 0; i < map_size; ++i) { 5707469ac69SMichał Mirosław if (map[i].odr_bits == odr_bits) { 5717469ac69SMichał Mirosław *val = map[i].val; 5727469ac69SMichał Mirosław *val2 = map[i].val2; 5737469ac69SMichał Mirosław return IIO_VAL_INT_PLUS_MICRO; 574b4b491c0SSrinivas Pandruvada } 575b4b491c0SSrinivas Pandruvada } 576b4b491c0SSrinivas Pandruvada 577b4b491c0SSrinivas Pandruvada return -EINVAL; 578b4b491c0SSrinivas Pandruvada } 579b4b491c0SSrinivas Pandruvada 5801a4fbf6aSSrinivas Pandruvada static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2) 5811a4fbf6aSSrinivas Pandruvada { 5821a4fbf6aSSrinivas Pandruvada int ret; 583124e1b1dSSrinivas Pandruvada enum kxcjk1013_mode store_mode; 5847469ac69SMichał Mirosław const struct kx_odr_map *odr_setting; 585124e1b1dSSrinivas Pandruvada 586124e1b1dSSrinivas Pandruvada ret = kxcjk1013_get_mode(data, &store_mode); 587124e1b1dSSrinivas Pandruvada if (ret < 0) 588124e1b1dSSrinivas Pandruvada return ret; 5891a4fbf6aSSrinivas Pandruvada 5907469ac69SMichał Mirosław odr_setting = kxcjk1013_find_odr_value(samp_freq_table, 5917469ac69SMichał Mirosław ARRAY_SIZE(samp_freq_table), 5927469ac69SMichał Mirosław val, val2); 5937469ac69SMichał Mirosław 5947469ac69SMichał Mirosław if (IS_ERR(odr_setting)) 5957469ac69SMichał Mirosław return PTR_ERR(odr_setting); 5961a4fbf6aSSrinivas Pandruvada 5971a4fbf6aSSrinivas Pandruvada /* To change ODR, the chip must be set to STANDBY as per spec */ 5981a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, STANDBY); 5991a4fbf6aSSrinivas Pandruvada if (ret < 0) 6001a4fbf6aSSrinivas Pandruvada return ret; 6011a4fbf6aSSrinivas Pandruvada 6021a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_DATA_CTRL, 6037469ac69SMichał Mirosław odr_setting->odr_bits); 6041a4fbf6aSSrinivas Pandruvada if (ret < 0) { 6051a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error writing data_ctrl\n"); 6061a4fbf6aSSrinivas Pandruvada return ret; 6071a4fbf6aSSrinivas Pandruvada } 6081a4fbf6aSSrinivas Pandruvada 6097469ac69SMichał Mirosław data->odr_bits = odr_setting->odr_bits; 610b4b491c0SSrinivas Pandruvada 611b4b491c0SSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_CTRL2, 6127469ac69SMichał Mirosław odr_setting->wuf_bits); 613b4b491c0SSrinivas Pandruvada if (ret < 0) { 614b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_ctrl2\n"); 615b4b491c0SSrinivas Pandruvada return ret; 616b4b491c0SSrinivas Pandruvada } 617b4b491c0SSrinivas Pandruvada 618124e1b1dSSrinivas Pandruvada if (store_mode == OPERATION) { 6191a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, OPERATION); 6201a4fbf6aSSrinivas Pandruvada if (ret < 0) 6211a4fbf6aSSrinivas Pandruvada return ret; 6221a4fbf6aSSrinivas Pandruvada } 6231a4fbf6aSSrinivas Pandruvada 6241a4fbf6aSSrinivas Pandruvada return 0; 6251a4fbf6aSSrinivas Pandruvada } 6261a4fbf6aSSrinivas Pandruvada 6271a4fbf6aSSrinivas Pandruvada static int kxcjk1013_get_odr(struct kxcjk1013_data *data, int *val, int *val2) 6281a4fbf6aSSrinivas Pandruvada { 6297469ac69SMichał Mirosław return kxcjk1013_convert_odr_value(samp_freq_table, 6307469ac69SMichał Mirosław ARRAY_SIZE(samp_freq_table), 6317469ac69SMichał Mirosław data->odr_bits, val, val2); 6321a4fbf6aSSrinivas Pandruvada } 6331a4fbf6aSSrinivas Pandruvada 6341a4fbf6aSSrinivas Pandruvada static int kxcjk1013_get_acc_reg(struct kxcjk1013_data *data, int axis) 6351a4fbf6aSSrinivas Pandruvada { 6361a4fbf6aSSrinivas Pandruvada u8 reg = KXCJK1013_REG_XOUT_L + axis * 2; 6371a4fbf6aSSrinivas Pandruvada int ret; 6381a4fbf6aSSrinivas Pandruvada 6391a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_word_data(data->client, reg); 6401a4fbf6aSSrinivas Pandruvada if (ret < 0) { 6411a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, 6421a4fbf6aSSrinivas Pandruvada "failed to read accel_%c registers\n", 'x' + axis); 6431a4fbf6aSSrinivas Pandruvada return ret; 6441a4fbf6aSSrinivas Pandruvada } 6451a4fbf6aSSrinivas Pandruvada 6461a4fbf6aSSrinivas Pandruvada return ret; 6471a4fbf6aSSrinivas Pandruvada } 6481a4fbf6aSSrinivas Pandruvada 649a735e3d7SSrinivas Pandruvada static int kxcjk1013_set_scale(struct kxcjk1013_data *data, int val) 650a735e3d7SSrinivas Pandruvada { 651a735e3d7SSrinivas Pandruvada int ret, i; 652a735e3d7SSrinivas Pandruvada enum kxcjk1013_mode store_mode; 653a735e3d7SSrinivas Pandruvada 654a735e3d7SSrinivas Pandruvada for (i = 0; i < ARRAY_SIZE(KXCJK1013_scale_table); ++i) { 655a735e3d7SSrinivas Pandruvada if (KXCJK1013_scale_table[i].scale == val) { 656a735e3d7SSrinivas Pandruvada ret = kxcjk1013_get_mode(data, &store_mode); 657a735e3d7SSrinivas Pandruvada if (ret < 0) 658a735e3d7SSrinivas Pandruvada return ret; 659a735e3d7SSrinivas Pandruvada 660a735e3d7SSrinivas Pandruvada ret = kxcjk1013_set_mode(data, STANDBY); 661a735e3d7SSrinivas Pandruvada if (ret < 0) 662a735e3d7SSrinivas Pandruvada return ret; 663a735e3d7SSrinivas Pandruvada 664a735e3d7SSrinivas Pandruvada ret = kxcjk1013_set_range(data, i); 665a735e3d7SSrinivas Pandruvada if (ret < 0) 666a735e3d7SSrinivas Pandruvada return ret; 667a735e3d7SSrinivas Pandruvada 668a735e3d7SSrinivas Pandruvada if (store_mode == OPERATION) { 669a735e3d7SSrinivas Pandruvada ret = kxcjk1013_set_mode(data, OPERATION); 670a735e3d7SSrinivas Pandruvada if (ret) 671a735e3d7SSrinivas Pandruvada return ret; 672a735e3d7SSrinivas Pandruvada } 673a735e3d7SSrinivas Pandruvada 674a735e3d7SSrinivas Pandruvada return 0; 675a735e3d7SSrinivas Pandruvada } 676a735e3d7SSrinivas Pandruvada } 677a735e3d7SSrinivas Pandruvada 678a735e3d7SSrinivas Pandruvada return -EINVAL; 679a735e3d7SSrinivas Pandruvada } 680a735e3d7SSrinivas Pandruvada 6811a4fbf6aSSrinivas Pandruvada static int kxcjk1013_read_raw(struct iio_dev *indio_dev, 6821a4fbf6aSSrinivas Pandruvada struct iio_chan_spec const *chan, int *val, 6831a4fbf6aSSrinivas Pandruvada int *val2, long mask) 6841a4fbf6aSSrinivas Pandruvada { 6851a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 6861a4fbf6aSSrinivas Pandruvada int ret; 6871a4fbf6aSSrinivas Pandruvada 6881a4fbf6aSSrinivas Pandruvada switch (mask) { 6891a4fbf6aSSrinivas Pandruvada case IIO_CHAN_INFO_RAW: 6901a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 6911a4fbf6aSSrinivas Pandruvada if (iio_buffer_enabled(indio_dev)) 6921a4fbf6aSSrinivas Pandruvada ret = -EBUSY; 6931a4fbf6aSSrinivas Pandruvada else { 694124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_power_state(data, true); 69588f6da77SSrinivas Pandruvada if (ret < 0) { 69688f6da77SSrinivas Pandruvada mutex_unlock(&data->mutex); 6971a4fbf6aSSrinivas Pandruvada return ret; 69888f6da77SSrinivas Pandruvada } 6991a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_get_acc_reg(data, chan->scan_index); 700124e1b1dSSrinivas Pandruvada if (ret < 0) { 701124e1b1dSSrinivas Pandruvada kxcjk1013_set_power_state(data, false); 702124e1b1dSSrinivas Pandruvada mutex_unlock(&data->mutex); 703124e1b1dSSrinivas Pandruvada return ret; 704124e1b1dSSrinivas Pandruvada } 705124e1b1dSSrinivas Pandruvada *val = sign_extend32(ret >> 4, 11); 706124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_power_state(data, false); 7071a4fbf6aSSrinivas Pandruvada } 7081a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 7091a4fbf6aSSrinivas Pandruvada 7101a4fbf6aSSrinivas Pandruvada if (ret < 0) 7111a4fbf6aSSrinivas Pandruvada return ret; 7121a4fbf6aSSrinivas Pandruvada 7131a4fbf6aSSrinivas Pandruvada return IIO_VAL_INT; 7141a4fbf6aSSrinivas Pandruvada 7151a4fbf6aSSrinivas Pandruvada case IIO_CHAN_INFO_SCALE: 7161a4fbf6aSSrinivas Pandruvada *val = 0; 717a735e3d7SSrinivas Pandruvada *val2 = KXCJK1013_scale_table[data->range].scale; 7181a4fbf6aSSrinivas Pandruvada return IIO_VAL_INT_PLUS_MICRO; 7191a4fbf6aSSrinivas Pandruvada 7201a4fbf6aSSrinivas Pandruvada case IIO_CHAN_INFO_SAMP_FREQ: 7211a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 7221a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_get_odr(data, val, val2); 7231a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 7241a4fbf6aSSrinivas Pandruvada return ret; 7251a4fbf6aSSrinivas Pandruvada 7261a4fbf6aSSrinivas Pandruvada default: 7271a4fbf6aSSrinivas Pandruvada return -EINVAL; 7281a4fbf6aSSrinivas Pandruvada } 7291a4fbf6aSSrinivas Pandruvada } 7301a4fbf6aSSrinivas Pandruvada 7311a4fbf6aSSrinivas Pandruvada static int kxcjk1013_write_raw(struct iio_dev *indio_dev, 7321a4fbf6aSSrinivas Pandruvada struct iio_chan_spec const *chan, int val, 7331a4fbf6aSSrinivas Pandruvada int val2, long mask) 7341a4fbf6aSSrinivas Pandruvada { 7351a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 7361a4fbf6aSSrinivas Pandruvada int ret; 7371a4fbf6aSSrinivas Pandruvada 7381a4fbf6aSSrinivas Pandruvada switch (mask) { 7391a4fbf6aSSrinivas Pandruvada case IIO_CHAN_INFO_SAMP_FREQ: 7401a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 7411a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_set_odr(data, val, val2); 7421a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 7431a4fbf6aSSrinivas Pandruvada break; 744a735e3d7SSrinivas Pandruvada case IIO_CHAN_INFO_SCALE: 745a735e3d7SSrinivas Pandruvada if (val) 746a735e3d7SSrinivas Pandruvada return -EINVAL; 747a735e3d7SSrinivas Pandruvada 748a735e3d7SSrinivas Pandruvada mutex_lock(&data->mutex); 749a735e3d7SSrinivas Pandruvada ret = kxcjk1013_set_scale(data, val2); 750a735e3d7SSrinivas Pandruvada mutex_unlock(&data->mutex); 751a735e3d7SSrinivas Pandruvada break; 7521a4fbf6aSSrinivas Pandruvada default: 7531a4fbf6aSSrinivas Pandruvada ret = -EINVAL; 7541a4fbf6aSSrinivas Pandruvada } 7551a4fbf6aSSrinivas Pandruvada 7561a4fbf6aSSrinivas Pandruvada return ret; 7571a4fbf6aSSrinivas Pandruvada } 7581a4fbf6aSSrinivas Pandruvada 759b4b491c0SSrinivas Pandruvada static int kxcjk1013_read_event(struct iio_dev *indio_dev, 760b4b491c0SSrinivas Pandruvada const struct iio_chan_spec *chan, 761b4b491c0SSrinivas Pandruvada enum iio_event_type type, 762b4b491c0SSrinivas Pandruvada enum iio_event_direction dir, 763b4b491c0SSrinivas Pandruvada enum iio_event_info info, 764b4b491c0SSrinivas Pandruvada int *val, int *val2) 765b4b491c0SSrinivas Pandruvada { 766b4b491c0SSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 767b4b491c0SSrinivas Pandruvada 768b4b491c0SSrinivas Pandruvada *val2 = 0; 769b4b491c0SSrinivas Pandruvada switch (info) { 770b4b491c0SSrinivas Pandruvada case IIO_EV_INFO_VALUE: 771b4b491c0SSrinivas Pandruvada *val = data->wake_thres; 772b4b491c0SSrinivas Pandruvada break; 773b4b491c0SSrinivas Pandruvada case IIO_EV_INFO_PERIOD: 774b4b491c0SSrinivas Pandruvada *val = data->wake_dur; 775b4b491c0SSrinivas Pandruvada break; 776b4b491c0SSrinivas Pandruvada default: 777b4b491c0SSrinivas Pandruvada return -EINVAL; 778b4b491c0SSrinivas Pandruvada } 779b4b491c0SSrinivas Pandruvada 780b4b491c0SSrinivas Pandruvada return IIO_VAL_INT; 781b4b491c0SSrinivas Pandruvada } 782b4b491c0SSrinivas Pandruvada 783b4b491c0SSrinivas Pandruvada static int kxcjk1013_write_event(struct iio_dev *indio_dev, 784b4b491c0SSrinivas Pandruvada const struct iio_chan_spec *chan, 785b4b491c0SSrinivas Pandruvada enum iio_event_type type, 786b4b491c0SSrinivas Pandruvada enum iio_event_direction dir, 787b4b491c0SSrinivas Pandruvada enum iio_event_info info, 788b4b491c0SSrinivas Pandruvada int val, int val2) 789b4b491c0SSrinivas Pandruvada { 790b4b491c0SSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 791b4b491c0SSrinivas Pandruvada 792b4b491c0SSrinivas Pandruvada if (data->ev_enable_state) 793b4b491c0SSrinivas Pandruvada return -EBUSY; 794b4b491c0SSrinivas Pandruvada 795b4b491c0SSrinivas Pandruvada switch (info) { 796b4b491c0SSrinivas Pandruvada case IIO_EV_INFO_VALUE: 797b4b491c0SSrinivas Pandruvada data->wake_thres = val; 798b4b491c0SSrinivas Pandruvada break; 799b4b491c0SSrinivas Pandruvada case IIO_EV_INFO_PERIOD: 800b4b491c0SSrinivas Pandruvada data->wake_dur = val; 801b4b491c0SSrinivas Pandruvada break; 802b4b491c0SSrinivas Pandruvada default: 803b4b491c0SSrinivas Pandruvada return -EINVAL; 804b4b491c0SSrinivas Pandruvada } 805b4b491c0SSrinivas Pandruvada 806b4b491c0SSrinivas Pandruvada return 0; 807b4b491c0SSrinivas Pandruvada } 808b4b491c0SSrinivas Pandruvada 809b4b491c0SSrinivas Pandruvada static int kxcjk1013_read_event_config(struct iio_dev *indio_dev, 810b4b491c0SSrinivas Pandruvada const struct iio_chan_spec *chan, 811b4b491c0SSrinivas Pandruvada enum iio_event_type type, 812b4b491c0SSrinivas Pandruvada enum iio_event_direction dir) 813b4b491c0SSrinivas Pandruvada { 814b4b491c0SSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 815b4b491c0SSrinivas Pandruvada 816b4b491c0SSrinivas Pandruvada return data->ev_enable_state; 817b4b491c0SSrinivas Pandruvada } 818b4b491c0SSrinivas Pandruvada 819b4b491c0SSrinivas Pandruvada static int kxcjk1013_write_event_config(struct iio_dev *indio_dev, 820b4b491c0SSrinivas Pandruvada const struct iio_chan_spec *chan, 821b4b491c0SSrinivas Pandruvada enum iio_event_type type, 822b4b491c0SSrinivas Pandruvada enum iio_event_direction dir, 823b4b491c0SSrinivas Pandruvada int state) 824b4b491c0SSrinivas Pandruvada { 825b4b491c0SSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 826b4b491c0SSrinivas Pandruvada int ret; 827b4b491c0SSrinivas Pandruvada 828b4b491c0SSrinivas Pandruvada if (state && data->ev_enable_state) 829b4b491c0SSrinivas Pandruvada return 0; 830b4b491c0SSrinivas Pandruvada 831b4b491c0SSrinivas Pandruvada mutex_lock(&data->mutex); 832b4b491c0SSrinivas Pandruvada 833b4b491c0SSrinivas Pandruvada if (!state && data->motion_trigger_on) { 834b4b491c0SSrinivas Pandruvada data->ev_enable_state = 0; 835b4b491c0SSrinivas Pandruvada mutex_unlock(&data->mutex); 836b4b491c0SSrinivas Pandruvada return 0; 837b4b491c0SSrinivas Pandruvada } 838b4b491c0SSrinivas Pandruvada 839b4b491c0SSrinivas Pandruvada /* 840b4b491c0SSrinivas Pandruvada * We will expect the enable and disable to do operation in 841b4b491c0SSrinivas Pandruvada * in reverse order. This will happen here anyway as our 842b4b491c0SSrinivas Pandruvada * resume operation uses sync mode runtime pm calls, the 843b4b491c0SSrinivas Pandruvada * suspend operation will be delayed by autosuspend delay 844b4b491c0SSrinivas Pandruvada * So the disable operation will still happen in reverse of 845b4b491c0SSrinivas Pandruvada * enable operation. When runtime pm is disabled the mode 846b4b491c0SSrinivas Pandruvada * is always on so sequence doesn't matter 847b4b491c0SSrinivas Pandruvada */ 848b4b491c0SSrinivas Pandruvada ret = kxcjk1013_set_power_state(data, state); 849b4b491c0SSrinivas Pandruvada if (ret < 0) { 850b4b491c0SSrinivas Pandruvada mutex_unlock(&data->mutex); 851b4b491c0SSrinivas Pandruvada return ret; 852b4b491c0SSrinivas Pandruvada } 853b4b491c0SSrinivas Pandruvada 854b4b491c0SSrinivas Pandruvada ret = kxcjk1013_setup_any_motion_interrupt(data, state); 855b4b491c0SSrinivas Pandruvada if (ret < 0) { 856fbd123e9SIrina Tirdea kxcjk1013_set_power_state(data, false); 857fbd123e9SIrina Tirdea data->ev_enable_state = 0; 858b4b491c0SSrinivas Pandruvada mutex_unlock(&data->mutex); 859b4b491c0SSrinivas Pandruvada return ret; 860b4b491c0SSrinivas Pandruvada } 861b4b491c0SSrinivas Pandruvada 862b4b491c0SSrinivas Pandruvada data->ev_enable_state = state; 863b4b491c0SSrinivas Pandruvada mutex_unlock(&data->mutex); 864b4b491c0SSrinivas Pandruvada 865b4b491c0SSrinivas Pandruvada return 0; 866b4b491c0SSrinivas Pandruvada } 867b4b491c0SSrinivas Pandruvada 868a25691c1SVlad Dogaru static int kxcjk1013_buffer_preenable(struct iio_dev *indio_dev) 8691a4fbf6aSSrinivas Pandruvada { 8701a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 8711a4fbf6aSSrinivas Pandruvada 872a25691c1SVlad Dogaru return kxcjk1013_set_power_state(data, true); 873a25691c1SVlad Dogaru } 8741a4fbf6aSSrinivas Pandruvada 875a25691c1SVlad Dogaru static int kxcjk1013_buffer_postdisable(struct iio_dev *indio_dev) 876a25691c1SVlad Dogaru { 877a25691c1SVlad Dogaru struct kxcjk1013_data *data = iio_priv(indio_dev); 878a25691c1SVlad Dogaru 879a25691c1SVlad Dogaru return kxcjk1013_set_power_state(data, false); 8801a4fbf6aSSrinivas Pandruvada } 8811a4fbf6aSSrinivas Pandruvada 8821a4fbf6aSSrinivas Pandruvada static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( 8831a4fbf6aSSrinivas Pandruvada "0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800 1600"); 8841a4fbf6aSSrinivas Pandruvada 885a735e3d7SSrinivas Pandruvada static IIO_CONST_ATTR(in_accel_scale_available, "0.009582 0.019163 0.038326"); 886a735e3d7SSrinivas Pandruvada 8871a4fbf6aSSrinivas Pandruvada static struct attribute *kxcjk1013_attributes[] = { 8881a4fbf6aSSrinivas Pandruvada &iio_const_attr_sampling_frequency_available.dev_attr.attr, 889a735e3d7SSrinivas Pandruvada &iio_const_attr_in_accel_scale_available.dev_attr.attr, 8901a4fbf6aSSrinivas Pandruvada NULL, 8911a4fbf6aSSrinivas Pandruvada }; 8921a4fbf6aSSrinivas Pandruvada 8931a4fbf6aSSrinivas Pandruvada static const struct attribute_group kxcjk1013_attrs_group = { 8941a4fbf6aSSrinivas Pandruvada .attrs = kxcjk1013_attributes, 8951a4fbf6aSSrinivas Pandruvada }; 8961a4fbf6aSSrinivas Pandruvada 897b4b491c0SSrinivas Pandruvada static const struct iio_event_spec kxcjk1013_event = { 898b4b491c0SSrinivas Pandruvada .type = IIO_EV_TYPE_THRESH, 89925afffe1SDaniel Baluta .dir = IIO_EV_DIR_EITHER, 900b4b491c0SSrinivas Pandruvada .mask_separate = BIT(IIO_EV_INFO_VALUE) | 901b4b491c0SSrinivas Pandruvada BIT(IIO_EV_INFO_ENABLE) | 902b4b491c0SSrinivas Pandruvada BIT(IIO_EV_INFO_PERIOD) 903b4b491c0SSrinivas Pandruvada }; 904b4b491c0SSrinivas Pandruvada 9051a4fbf6aSSrinivas Pandruvada #define KXCJK1013_CHANNEL(_axis) { \ 9061a4fbf6aSSrinivas Pandruvada .type = IIO_ACCEL, \ 9071a4fbf6aSSrinivas Pandruvada .modified = 1, \ 9081a4fbf6aSSrinivas Pandruvada .channel2 = IIO_MOD_##_axis, \ 9091a4fbf6aSSrinivas Pandruvada .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 9101a4fbf6aSSrinivas Pandruvada .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 9111a4fbf6aSSrinivas Pandruvada BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 9121a4fbf6aSSrinivas Pandruvada .scan_index = AXIS_##_axis, \ 9131a4fbf6aSSrinivas Pandruvada .scan_type = { \ 9141a4fbf6aSSrinivas Pandruvada .sign = 's', \ 9151a4fbf6aSSrinivas Pandruvada .realbits = 12, \ 9161a4fbf6aSSrinivas Pandruvada .storagebits = 16, \ 9171a4fbf6aSSrinivas Pandruvada .shift = 4, \ 91865ae47b0SAdriana Reus .endianness = IIO_LE, \ 9191a4fbf6aSSrinivas Pandruvada }, \ 920b4b491c0SSrinivas Pandruvada .event_spec = &kxcjk1013_event, \ 921b4b491c0SSrinivas Pandruvada .num_event_specs = 1 \ 9221a4fbf6aSSrinivas Pandruvada } 9231a4fbf6aSSrinivas Pandruvada 9241a4fbf6aSSrinivas Pandruvada static const struct iio_chan_spec kxcjk1013_channels[] = { 9251a4fbf6aSSrinivas Pandruvada KXCJK1013_CHANNEL(X), 9261a4fbf6aSSrinivas Pandruvada KXCJK1013_CHANNEL(Y), 9271a4fbf6aSSrinivas Pandruvada KXCJK1013_CHANNEL(Z), 9281a4fbf6aSSrinivas Pandruvada IIO_CHAN_SOFT_TIMESTAMP(3), 9291a4fbf6aSSrinivas Pandruvada }; 9301a4fbf6aSSrinivas Pandruvada 931a25691c1SVlad Dogaru static const struct iio_buffer_setup_ops kxcjk1013_buffer_setup_ops = { 932a25691c1SVlad Dogaru .preenable = kxcjk1013_buffer_preenable, 933a25691c1SVlad Dogaru .postenable = iio_triggered_buffer_postenable, 934a25691c1SVlad Dogaru .postdisable = kxcjk1013_buffer_postdisable, 935a25691c1SVlad Dogaru .predisable = iio_triggered_buffer_predisable, 936a25691c1SVlad Dogaru }; 937a25691c1SVlad Dogaru 9381a4fbf6aSSrinivas Pandruvada static const struct iio_info kxcjk1013_info = { 9391a4fbf6aSSrinivas Pandruvada .attrs = &kxcjk1013_attrs_group, 9401a4fbf6aSSrinivas Pandruvada .read_raw = kxcjk1013_read_raw, 9411a4fbf6aSSrinivas Pandruvada .write_raw = kxcjk1013_write_raw, 942b4b491c0SSrinivas Pandruvada .read_event_value = kxcjk1013_read_event, 943b4b491c0SSrinivas Pandruvada .write_event_value = kxcjk1013_write_event, 944b4b491c0SSrinivas Pandruvada .write_event_config = kxcjk1013_write_event_config, 945b4b491c0SSrinivas Pandruvada .read_event_config = kxcjk1013_read_event_config, 9461a4fbf6aSSrinivas Pandruvada }; 9471a4fbf6aSSrinivas Pandruvada 94809cf1b32SAdriana Reus static const unsigned long kxcjk1013_scan_masks[] = {0x7, 0}; 94909cf1b32SAdriana Reus 9501a4fbf6aSSrinivas Pandruvada static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p) 9511a4fbf6aSSrinivas Pandruvada { 9521a4fbf6aSSrinivas Pandruvada struct iio_poll_func *pf = p; 9531a4fbf6aSSrinivas Pandruvada struct iio_dev *indio_dev = pf->indio_dev; 9541a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 95565ae47b0SAdriana Reus int ret; 9561a4fbf6aSSrinivas Pandruvada 9571a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 95865ae47b0SAdriana Reus ret = i2c_smbus_read_i2c_block_data_or_emulated(data->client, 95965ae47b0SAdriana Reus KXCJK1013_REG_XOUT_L, 96065ae47b0SAdriana Reus AXIS_MAX * 2, 96165ae47b0SAdriana Reus (u8 *)data->buffer); 9621a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 96365ae47b0SAdriana Reus if (ret < 0) 9641a4fbf6aSSrinivas Pandruvada goto err; 9651a4fbf6aSSrinivas Pandruvada 9661a4fbf6aSSrinivas Pandruvada iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, 967b4b491c0SSrinivas Pandruvada data->timestamp); 9681a4fbf6aSSrinivas Pandruvada err: 9691a4fbf6aSSrinivas Pandruvada iio_trigger_notify_done(indio_dev->trig); 9701a4fbf6aSSrinivas Pandruvada 9711a4fbf6aSSrinivas Pandruvada return IRQ_HANDLED; 9721a4fbf6aSSrinivas Pandruvada } 9731a4fbf6aSSrinivas Pandruvada 97459bfeabaSSrinivas Pandruvada static int kxcjk1013_trig_try_reen(struct iio_trigger *trig) 97559bfeabaSSrinivas Pandruvada { 97659bfeabaSSrinivas Pandruvada struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); 97759bfeabaSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 97859bfeabaSSrinivas Pandruvada int ret; 97959bfeabaSSrinivas Pandruvada 98059bfeabaSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL); 98159bfeabaSSrinivas Pandruvada if (ret < 0) { 98259bfeabaSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_rel\n"); 98359bfeabaSSrinivas Pandruvada return ret; 98459bfeabaSSrinivas Pandruvada } 98559bfeabaSSrinivas Pandruvada 98659bfeabaSSrinivas Pandruvada return 0; 98759bfeabaSSrinivas Pandruvada } 98859bfeabaSSrinivas Pandruvada 9891a4fbf6aSSrinivas Pandruvada static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig, 9901a4fbf6aSSrinivas Pandruvada bool state) 9911a4fbf6aSSrinivas Pandruvada { 9921a4fbf6aSSrinivas Pandruvada struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); 9931a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 994124e1b1dSSrinivas Pandruvada int ret; 995124e1b1dSSrinivas Pandruvada 9961a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 997b4b491c0SSrinivas Pandruvada 998b4b491c0SSrinivas Pandruvada if (!state && data->ev_enable_state && data->motion_trigger_on) { 999b4b491c0SSrinivas Pandruvada data->motion_trigger_on = false; 1000b4b491c0SSrinivas Pandruvada mutex_unlock(&data->mutex); 1001b4b491c0SSrinivas Pandruvada return 0; 1002b4b491c0SSrinivas Pandruvada } 1003b4b491c0SSrinivas Pandruvada 1004124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_power_state(data, state); 1005124e1b1dSSrinivas Pandruvada if (ret < 0) { 100688f6da77SSrinivas Pandruvada mutex_unlock(&data->mutex); 1007124e1b1dSSrinivas Pandruvada return ret; 100888f6da77SSrinivas Pandruvada } 1009b4b491c0SSrinivas Pandruvada if (data->motion_trig == trig) 1010b4b491c0SSrinivas Pandruvada ret = kxcjk1013_setup_any_motion_interrupt(data, state); 1011b4b491c0SSrinivas Pandruvada else 1012b4b491c0SSrinivas Pandruvada ret = kxcjk1013_setup_new_data_interrupt(data, state); 1013b4b491c0SSrinivas Pandruvada if (ret < 0) { 1014fbd123e9SIrina Tirdea kxcjk1013_set_power_state(data, false); 1015b4b491c0SSrinivas Pandruvada mutex_unlock(&data->mutex); 1016b4b491c0SSrinivas Pandruvada return ret; 10171a4fbf6aSSrinivas Pandruvada } 1018b4b491c0SSrinivas Pandruvada if (data->motion_trig == trig) 1019b4b491c0SSrinivas Pandruvada data->motion_trigger_on = state; 1020b4b491c0SSrinivas Pandruvada else 1021b4b491c0SSrinivas Pandruvada data->dready_trigger_on = state; 1022b4b491c0SSrinivas Pandruvada 10231a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 10241a4fbf6aSSrinivas Pandruvada 10251a4fbf6aSSrinivas Pandruvada return 0; 10261a4fbf6aSSrinivas Pandruvada } 10271a4fbf6aSSrinivas Pandruvada 10281a4fbf6aSSrinivas Pandruvada static const struct iio_trigger_ops kxcjk1013_trigger_ops = { 10291a4fbf6aSSrinivas Pandruvada .set_trigger_state = kxcjk1013_data_rdy_trigger_set_state, 103059bfeabaSSrinivas Pandruvada .try_reenable = kxcjk1013_trig_try_reen, 10311a4fbf6aSSrinivas Pandruvada }; 10321a4fbf6aSSrinivas Pandruvada 1033b4b491c0SSrinivas Pandruvada static irqreturn_t kxcjk1013_event_handler(int irq, void *private) 1034b4b491c0SSrinivas Pandruvada { 1035b4b491c0SSrinivas Pandruvada struct iio_dev *indio_dev = private; 1036b4b491c0SSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 1037b4b491c0SSrinivas Pandruvada int ret; 1038b4b491c0SSrinivas Pandruvada 1039b4b491c0SSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_SRC1); 1040b4b491c0SSrinivas Pandruvada if (ret < 0) { 1041b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_src1\n"); 1042b4b491c0SSrinivas Pandruvada goto ack_intr; 1043b4b491c0SSrinivas Pandruvada } 1044b4b491c0SSrinivas Pandruvada 1045*f74e440cSMichał Mirosław if (ret & KXCJK1013_REG_INT_SRC1_BIT_WUFS) { 1046b4b491c0SSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, 1047b4b491c0SSrinivas Pandruvada KXCJK1013_REG_INT_SRC2); 1048b4b491c0SSrinivas Pandruvada if (ret < 0) { 1049b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, 1050b4b491c0SSrinivas Pandruvada "Error reading reg_int_src2\n"); 1051b4b491c0SSrinivas Pandruvada goto ack_intr; 1052b4b491c0SSrinivas Pandruvada } 1053b4b491c0SSrinivas Pandruvada 1054b4b491c0SSrinivas Pandruvada if (ret & KXCJK1013_REG_INT_SRC2_BIT_XN) 1055b4b491c0SSrinivas Pandruvada iio_push_event(indio_dev, 1056b4b491c0SSrinivas Pandruvada IIO_MOD_EVENT_CODE(IIO_ACCEL, 1057b4b491c0SSrinivas Pandruvada 0, 1058b4b491c0SSrinivas Pandruvada IIO_MOD_X, 1059b4b491c0SSrinivas Pandruvada IIO_EV_TYPE_THRESH, 1060b4b491c0SSrinivas Pandruvada IIO_EV_DIR_FALLING), 1061b4b491c0SSrinivas Pandruvada data->timestamp); 1062b4b491c0SSrinivas Pandruvada if (ret & KXCJK1013_REG_INT_SRC2_BIT_XP) 1063b4b491c0SSrinivas Pandruvada iio_push_event(indio_dev, 1064b4b491c0SSrinivas Pandruvada IIO_MOD_EVENT_CODE(IIO_ACCEL, 1065b4b491c0SSrinivas Pandruvada 0, 1066b4b491c0SSrinivas Pandruvada IIO_MOD_X, 1067b4b491c0SSrinivas Pandruvada IIO_EV_TYPE_THRESH, 1068b4b491c0SSrinivas Pandruvada IIO_EV_DIR_RISING), 1069b4b491c0SSrinivas Pandruvada data->timestamp); 1070b4b491c0SSrinivas Pandruvada 1071b4b491c0SSrinivas Pandruvada 1072b4b491c0SSrinivas Pandruvada if (ret & KXCJK1013_REG_INT_SRC2_BIT_YN) 1073b4b491c0SSrinivas Pandruvada iio_push_event(indio_dev, 1074b4b491c0SSrinivas Pandruvada IIO_MOD_EVENT_CODE(IIO_ACCEL, 1075b4b491c0SSrinivas Pandruvada 0, 1076b4b491c0SSrinivas Pandruvada IIO_MOD_Y, 1077b4b491c0SSrinivas Pandruvada IIO_EV_TYPE_THRESH, 1078b4b491c0SSrinivas Pandruvada IIO_EV_DIR_FALLING), 1079b4b491c0SSrinivas Pandruvada data->timestamp); 1080b4b491c0SSrinivas Pandruvada if (ret & KXCJK1013_REG_INT_SRC2_BIT_YP) 1081b4b491c0SSrinivas Pandruvada iio_push_event(indio_dev, 1082b4b491c0SSrinivas Pandruvada IIO_MOD_EVENT_CODE(IIO_ACCEL, 1083b4b491c0SSrinivas Pandruvada 0, 1084b4b491c0SSrinivas Pandruvada IIO_MOD_Y, 1085b4b491c0SSrinivas Pandruvada IIO_EV_TYPE_THRESH, 1086b4b491c0SSrinivas Pandruvada IIO_EV_DIR_RISING), 1087b4b491c0SSrinivas Pandruvada data->timestamp); 1088b4b491c0SSrinivas Pandruvada 1089b4b491c0SSrinivas Pandruvada if (ret & KXCJK1013_REG_INT_SRC2_BIT_ZN) 1090b4b491c0SSrinivas Pandruvada iio_push_event(indio_dev, 1091b4b491c0SSrinivas Pandruvada IIO_MOD_EVENT_CODE(IIO_ACCEL, 1092b4b491c0SSrinivas Pandruvada 0, 1093b4b491c0SSrinivas Pandruvada IIO_MOD_Z, 1094b4b491c0SSrinivas Pandruvada IIO_EV_TYPE_THRESH, 1095b4b491c0SSrinivas Pandruvada IIO_EV_DIR_FALLING), 1096b4b491c0SSrinivas Pandruvada data->timestamp); 1097b4b491c0SSrinivas Pandruvada if (ret & KXCJK1013_REG_INT_SRC2_BIT_ZP) 1098b4b491c0SSrinivas Pandruvada iio_push_event(indio_dev, 1099b4b491c0SSrinivas Pandruvada IIO_MOD_EVENT_CODE(IIO_ACCEL, 1100b4b491c0SSrinivas Pandruvada 0, 1101b4b491c0SSrinivas Pandruvada IIO_MOD_Z, 1102b4b491c0SSrinivas Pandruvada IIO_EV_TYPE_THRESH, 1103b4b491c0SSrinivas Pandruvada IIO_EV_DIR_RISING), 1104b4b491c0SSrinivas Pandruvada data->timestamp); 1105b4b491c0SSrinivas Pandruvada } 1106b4b491c0SSrinivas Pandruvada 1107b4b491c0SSrinivas Pandruvada ack_intr: 1108b4b491c0SSrinivas Pandruvada if (data->dready_trigger_on) 1109b4b491c0SSrinivas Pandruvada return IRQ_HANDLED; 1110b4b491c0SSrinivas Pandruvada 1111b4b491c0SSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL); 1112b4b491c0SSrinivas Pandruvada if (ret < 0) 1113b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_rel\n"); 1114b4b491c0SSrinivas Pandruvada 1115b4b491c0SSrinivas Pandruvada return IRQ_HANDLED; 1116b4b491c0SSrinivas Pandruvada } 1117b4b491c0SSrinivas Pandruvada 1118b4b491c0SSrinivas Pandruvada static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private) 1119b4b491c0SSrinivas Pandruvada { 1120b4b491c0SSrinivas Pandruvada struct iio_dev *indio_dev = private; 1121b4b491c0SSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 1122b4b491c0SSrinivas Pandruvada 1123bc2b7dabSGregor Boirie data->timestamp = iio_get_time_ns(indio_dev); 1124b4b491c0SSrinivas Pandruvada 1125b4b491c0SSrinivas Pandruvada if (data->dready_trigger_on) 1126b4b491c0SSrinivas Pandruvada iio_trigger_poll(data->dready_trig); 1127b4b491c0SSrinivas Pandruvada else if (data->motion_trigger_on) 1128b4b491c0SSrinivas Pandruvada iio_trigger_poll(data->motion_trig); 1129b4b491c0SSrinivas Pandruvada 1130b4b491c0SSrinivas Pandruvada if (data->ev_enable_state) 1131b4b491c0SSrinivas Pandruvada return IRQ_WAKE_THREAD; 1132b4b491c0SSrinivas Pandruvada else 1133b4b491c0SSrinivas Pandruvada return IRQ_HANDLED; 1134b4b491c0SSrinivas Pandruvada } 1135b4b491c0SSrinivas Pandruvada 1136c6861377SDaniel Baluta static const char *kxcjk1013_match_acpi_device(struct device *dev, 11373bfa74f8SBastien Nocera enum kx_chipset *chipset, 11383bfa74f8SBastien Nocera bool *is_smo8500_device) 11391a4fbf6aSSrinivas Pandruvada { 11401a4fbf6aSSrinivas Pandruvada const struct acpi_device_id *id; 1141b0868df4SRoberta Dobrescu 1142c6861377SDaniel Baluta id = acpi_match_device(dev->driver->acpi_match_table, dev); 1143c6861377SDaniel Baluta if (!id) 1144c6861377SDaniel Baluta return NULL; 1145e693e15eSAntonio Ospite 11463bfa74f8SBastien Nocera if (strcmp(id->id, "SMO8500") == 0) 11473bfa74f8SBastien Nocera *is_smo8500_device = true; 1148e693e15eSAntonio Ospite 1149c6861377SDaniel Baluta *chipset = (enum kx_chipset)id->driver_data; 1150c6861377SDaniel Baluta 1151c6861377SDaniel Baluta return dev_name(dev); 1152c6861377SDaniel Baluta } 1153c6861377SDaniel Baluta 11541a4fbf6aSSrinivas Pandruvada static int kxcjk1013_probe(struct i2c_client *client, 11551a4fbf6aSSrinivas Pandruvada const struct i2c_device_id *id) 11561a4fbf6aSSrinivas Pandruvada { 11571a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data; 11581a4fbf6aSSrinivas Pandruvada struct iio_dev *indio_dev; 11591a4fbf6aSSrinivas Pandruvada struct kxcjk_1013_platform_data *pdata; 1160c6861377SDaniel Baluta const char *name; 11611a4fbf6aSSrinivas Pandruvada int ret; 11621a4fbf6aSSrinivas Pandruvada 11631a4fbf6aSSrinivas Pandruvada indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 11641a4fbf6aSSrinivas Pandruvada if (!indio_dev) 11651a4fbf6aSSrinivas Pandruvada return -ENOMEM; 11661a4fbf6aSSrinivas Pandruvada 11671a4fbf6aSSrinivas Pandruvada data = iio_priv(indio_dev); 11681a4fbf6aSSrinivas Pandruvada i2c_set_clientdata(client, indio_dev); 11691a4fbf6aSSrinivas Pandruvada data->client = client; 11701a4fbf6aSSrinivas Pandruvada 11711a4fbf6aSSrinivas Pandruvada pdata = dev_get_platdata(&client->dev); 11721a4fbf6aSSrinivas Pandruvada if (pdata) 11731a4fbf6aSSrinivas Pandruvada data->active_high_intr = pdata->active_high_intr; 11741a4fbf6aSSrinivas Pandruvada else 11751a4fbf6aSSrinivas Pandruvada data->active_high_intr = true; /* default polarity */ 11761a4fbf6aSSrinivas Pandruvada 1177c6861377SDaniel Baluta if (id) { 1178c6861377SDaniel Baluta data->chipset = (enum kx_chipset)(id->driver_data); 1179c6861377SDaniel Baluta name = id->name; 1180c6861377SDaniel Baluta } else if (ACPI_HANDLE(&client->dev)) { 1181c6861377SDaniel Baluta name = kxcjk1013_match_acpi_device(&client->dev, 11823bfa74f8SBastien Nocera &data->chipset, 11833bfa74f8SBastien Nocera &data->is_smo8500_device); 1184c6861377SDaniel Baluta } else 1185c6861377SDaniel Baluta return -ENODEV; 1186c6861377SDaniel Baluta 11871a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_chip_init(data); 11881a4fbf6aSSrinivas Pandruvada if (ret < 0) 11891a4fbf6aSSrinivas Pandruvada return ret; 11901a4fbf6aSSrinivas Pandruvada 11911a4fbf6aSSrinivas Pandruvada mutex_init(&data->mutex); 11921a4fbf6aSSrinivas Pandruvada 11931a4fbf6aSSrinivas Pandruvada indio_dev->dev.parent = &client->dev; 11941a4fbf6aSSrinivas Pandruvada indio_dev->channels = kxcjk1013_channels; 11951a4fbf6aSSrinivas Pandruvada indio_dev->num_channels = ARRAY_SIZE(kxcjk1013_channels); 119609cf1b32SAdriana Reus indio_dev->available_scan_masks = kxcjk1013_scan_masks; 1197c6861377SDaniel Baluta indio_dev->name = name; 11981a4fbf6aSSrinivas Pandruvada indio_dev->modes = INDIO_DIRECT_MODE; 11991a4fbf6aSSrinivas Pandruvada indio_dev->info = &kxcjk1013_info; 12001a4fbf6aSSrinivas Pandruvada 12010f079650SOctavian Purdila if (client->irq > 0 && !data->is_smo8500_device) { 1202b4b491c0SSrinivas Pandruvada ret = devm_request_threaded_irq(&client->dev, client->irq, 1203b4b491c0SSrinivas Pandruvada kxcjk1013_data_rdy_trig_poll, 1204b4b491c0SSrinivas Pandruvada kxcjk1013_event_handler, 12051a4fbf6aSSrinivas Pandruvada IRQF_TRIGGER_RISING, 12061a4fbf6aSSrinivas Pandruvada KXCJK1013_IRQ_NAME, 1207b4b491c0SSrinivas Pandruvada indio_dev); 12081a4fbf6aSSrinivas Pandruvada if (ret) 12099d02daf7SIrina Tirdea goto err_poweroff; 1210b4b491c0SSrinivas Pandruvada 1211b4b491c0SSrinivas Pandruvada data->dready_trig = devm_iio_trigger_alloc(&client->dev, 1212b4b491c0SSrinivas Pandruvada "%s-dev%d", 1213b4b491c0SSrinivas Pandruvada indio_dev->name, 1214b4b491c0SSrinivas Pandruvada indio_dev->id); 12159d02daf7SIrina Tirdea if (!data->dready_trig) { 12169d02daf7SIrina Tirdea ret = -ENOMEM; 12179d02daf7SIrina Tirdea goto err_poweroff; 12189d02daf7SIrina Tirdea } 1219b4b491c0SSrinivas Pandruvada 1220b4b491c0SSrinivas Pandruvada data->motion_trig = devm_iio_trigger_alloc(&client->dev, 1221b4b491c0SSrinivas Pandruvada "%s-any-motion-dev%d", 1222b4b491c0SSrinivas Pandruvada indio_dev->name, 1223b4b491c0SSrinivas Pandruvada indio_dev->id); 12249d02daf7SIrina Tirdea if (!data->motion_trig) { 12259d02daf7SIrina Tirdea ret = -ENOMEM; 12269d02daf7SIrina Tirdea goto err_poweroff; 12279d02daf7SIrina Tirdea } 1228b4b491c0SSrinivas Pandruvada 1229b4b491c0SSrinivas Pandruvada data->dready_trig->dev.parent = &client->dev; 1230b4b491c0SSrinivas Pandruvada data->dready_trig->ops = &kxcjk1013_trigger_ops; 1231b4b491c0SSrinivas Pandruvada iio_trigger_set_drvdata(data->dready_trig, indio_dev); 1232b4b491c0SSrinivas Pandruvada indio_dev->trig = data->dready_trig; 1233b4b491c0SSrinivas Pandruvada iio_trigger_get(indio_dev->trig); 1234b4b491c0SSrinivas Pandruvada ret = iio_trigger_register(data->dready_trig); 1235b4b491c0SSrinivas Pandruvada if (ret) 12369d02daf7SIrina Tirdea goto err_poweroff; 1237b4b491c0SSrinivas Pandruvada 1238b4b491c0SSrinivas Pandruvada data->motion_trig->dev.parent = &client->dev; 1239b4b491c0SSrinivas Pandruvada data->motion_trig->ops = &kxcjk1013_trigger_ops; 1240b4b491c0SSrinivas Pandruvada iio_trigger_set_drvdata(data->motion_trig, indio_dev); 1241b4b491c0SSrinivas Pandruvada ret = iio_trigger_register(data->motion_trig); 1242b4b491c0SSrinivas Pandruvada if (ret) { 1243b4b491c0SSrinivas Pandruvada data->motion_trig = NULL; 1244b4b491c0SSrinivas Pandruvada goto err_trigger_unregister; 1245b4b491c0SSrinivas Pandruvada } 1246a25691c1SVlad Dogaru } 12471a4fbf6aSSrinivas Pandruvada 12481a4fbf6aSSrinivas Pandruvada ret = iio_triggered_buffer_setup(indio_dev, 12491a4fbf6aSSrinivas Pandruvada &iio_pollfunc_store_time, 12501a4fbf6aSSrinivas Pandruvada kxcjk1013_trigger_handler, 1251a25691c1SVlad Dogaru &kxcjk1013_buffer_setup_ops); 12521a4fbf6aSSrinivas Pandruvada if (ret < 0) { 1253a25691c1SVlad Dogaru dev_err(&client->dev, "iio triggered buffer setup failed\n"); 12541a4fbf6aSSrinivas Pandruvada goto err_trigger_unregister; 12551a4fbf6aSSrinivas Pandruvada } 12561a4fbf6aSSrinivas Pandruvada 1257124e1b1dSSrinivas Pandruvada ret = pm_runtime_set_active(&client->dev); 1258124e1b1dSSrinivas Pandruvada if (ret) 12597d0ead5cSAdriana Reus goto err_buffer_cleanup; 1260124e1b1dSSrinivas Pandruvada 1261124e1b1dSSrinivas Pandruvada pm_runtime_enable(&client->dev); 1262124e1b1dSSrinivas Pandruvada pm_runtime_set_autosuspend_delay(&client->dev, 1263124e1b1dSSrinivas Pandruvada KXCJK1013_SLEEP_DELAY_MS); 1264124e1b1dSSrinivas Pandruvada pm_runtime_use_autosuspend(&client->dev); 1265124e1b1dSSrinivas Pandruvada 12667d0ead5cSAdriana Reus ret = iio_device_register(indio_dev); 12677d0ead5cSAdriana Reus if (ret < 0) { 12687d0ead5cSAdriana Reus dev_err(&client->dev, "unable to register iio device\n"); 12697d0ead5cSAdriana Reus goto err_buffer_cleanup; 12707d0ead5cSAdriana Reus } 12717d0ead5cSAdriana Reus 12721a4fbf6aSSrinivas Pandruvada return 0; 12731a4fbf6aSSrinivas Pandruvada 12741a4fbf6aSSrinivas Pandruvada err_buffer_cleanup: 1275b4b491c0SSrinivas Pandruvada if (data->dready_trig) 12761a4fbf6aSSrinivas Pandruvada iio_triggered_buffer_cleanup(indio_dev); 12771a4fbf6aSSrinivas Pandruvada err_trigger_unregister: 1278b4b491c0SSrinivas Pandruvada if (data->dready_trig) 1279b4b491c0SSrinivas Pandruvada iio_trigger_unregister(data->dready_trig); 1280b4b491c0SSrinivas Pandruvada if (data->motion_trig) 1281b4b491c0SSrinivas Pandruvada iio_trigger_unregister(data->motion_trig); 12829d02daf7SIrina Tirdea err_poweroff: 12839d02daf7SIrina Tirdea kxcjk1013_set_mode(data, STANDBY); 12841a4fbf6aSSrinivas Pandruvada 12851a4fbf6aSSrinivas Pandruvada return ret; 12861a4fbf6aSSrinivas Pandruvada } 12871a4fbf6aSSrinivas Pandruvada 12881a4fbf6aSSrinivas Pandruvada static int kxcjk1013_remove(struct i2c_client *client) 12891a4fbf6aSSrinivas Pandruvada { 12901a4fbf6aSSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(client); 12911a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 12921a4fbf6aSSrinivas Pandruvada 12937d0ead5cSAdriana Reus iio_device_unregister(indio_dev); 12947d0ead5cSAdriana Reus 1295124e1b1dSSrinivas Pandruvada pm_runtime_disable(&client->dev); 1296124e1b1dSSrinivas Pandruvada pm_runtime_set_suspended(&client->dev); 1297124e1b1dSSrinivas Pandruvada pm_runtime_put_noidle(&client->dev); 1298124e1b1dSSrinivas Pandruvada 1299b4b491c0SSrinivas Pandruvada if (data->dready_trig) { 13001a4fbf6aSSrinivas Pandruvada iio_triggered_buffer_cleanup(indio_dev); 1301b4b491c0SSrinivas Pandruvada iio_trigger_unregister(data->dready_trig); 1302b4b491c0SSrinivas Pandruvada iio_trigger_unregister(data->motion_trig); 13031a4fbf6aSSrinivas Pandruvada } 13041a4fbf6aSSrinivas Pandruvada 13051a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 13061a4fbf6aSSrinivas Pandruvada kxcjk1013_set_mode(data, STANDBY); 13071a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 13081a4fbf6aSSrinivas Pandruvada 13091a4fbf6aSSrinivas Pandruvada return 0; 13101a4fbf6aSSrinivas Pandruvada } 13111a4fbf6aSSrinivas Pandruvada 13121a4fbf6aSSrinivas Pandruvada #ifdef CONFIG_PM_SLEEP 13131a4fbf6aSSrinivas Pandruvada static int kxcjk1013_suspend(struct device *dev) 13141a4fbf6aSSrinivas Pandruvada { 13151a4fbf6aSSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 13161a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 1317124e1b1dSSrinivas Pandruvada int ret; 13181a4fbf6aSSrinivas Pandruvada 13191a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 1320124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, STANDBY); 13211a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 13221a4fbf6aSSrinivas Pandruvada 1323124e1b1dSSrinivas Pandruvada return ret; 13241a4fbf6aSSrinivas Pandruvada } 13251a4fbf6aSSrinivas Pandruvada 13261a4fbf6aSSrinivas Pandruvada static int kxcjk1013_resume(struct device *dev) 13271a4fbf6aSSrinivas Pandruvada { 13281a4fbf6aSSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 13291a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 1330124e1b1dSSrinivas Pandruvada int ret = 0; 13311a4fbf6aSSrinivas Pandruvada 13321a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 1333124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, OPERATION); 13341a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 13351a4fbf6aSSrinivas Pandruvada 1336124e1b1dSSrinivas Pandruvada return ret; 1337124e1b1dSSrinivas Pandruvada } 1338124e1b1dSSrinivas Pandruvada #endif 1339124e1b1dSSrinivas Pandruvada 13406f0a13f2SRafael J. Wysocki #ifdef CONFIG_PM 1341124e1b1dSSrinivas Pandruvada static int kxcjk1013_runtime_suspend(struct device *dev) 1342124e1b1dSSrinivas Pandruvada { 1343124e1b1dSSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 1344124e1b1dSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 1345fbd123e9SIrina Tirdea int ret; 1346124e1b1dSSrinivas Pandruvada 1347fbd123e9SIrina Tirdea ret = kxcjk1013_set_mode(data, STANDBY); 1348fbd123e9SIrina Tirdea if (ret < 0) { 1349fbd123e9SIrina Tirdea dev_err(&data->client->dev, "powering off device failed\n"); 1350fbd123e9SIrina Tirdea return -EAGAIN; 1351fbd123e9SIrina Tirdea } 1352fbd123e9SIrina Tirdea return 0; 1353124e1b1dSSrinivas Pandruvada } 1354124e1b1dSSrinivas Pandruvada 1355124e1b1dSSrinivas Pandruvada static int kxcjk1013_runtime_resume(struct device *dev) 1356124e1b1dSSrinivas Pandruvada { 1357124e1b1dSSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 1358124e1b1dSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 1359124e1b1dSSrinivas Pandruvada int ret; 1360124e1b1dSSrinivas Pandruvada int sleep_val; 1361124e1b1dSSrinivas Pandruvada 1362124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, OPERATION); 1363124e1b1dSSrinivas Pandruvada if (ret < 0) 1364124e1b1dSSrinivas Pandruvada return ret; 1365124e1b1dSSrinivas Pandruvada 1366124e1b1dSSrinivas Pandruvada sleep_val = kxcjk1013_get_startup_times(data); 1367124e1b1dSSrinivas Pandruvada if (sleep_val < 20000) 1368124e1b1dSSrinivas Pandruvada usleep_range(sleep_val, 20000); 1369124e1b1dSSrinivas Pandruvada else 1370124e1b1dSSrinivas Pandruvada msleep_interruptible(sleep_val/1000); 1371124e1b1dSSrinivas Pandruvada 13721a4fbf6aSSrinivas Pandruvada return 0; 13731a4fbf6aSSrinivas Pandruvada } 13741a4fbf6aSSrinivas Pandruvada #endif 13751a4fbf6aSSrinivas Pandruvada 1376124e1b1dSSrinivas Pandruvada static const struct dev_pm_ops kxcjk1013_pm_ops = { 1377124e1b1dSSrinivas Pandruvada SET_SYSTEM_SLEEP_PM_OPS(kxcjk1013_suspend, kxcjk1013_resume) 1378124e1b1dSSrinivas Pandruvada SET_RUNTIME_PM_OPS(kxcjk1013_runtime_suspend, 1379124e1b1dSSrinivas Pandruvada kxcjk1013_runtime_resume, NULL) 1380124e1b1dSSrinivas Pandruvada }; 1381124e1b1dSSrinivas Pandruvada 13821a4fbf6aSSrinivas Pandruvada static const struct acpi_device_id kx_acpi_match[] = { 1383c6861377SDaniel Baluta {"KXCJ1013", KXCJK1013}, 1384c6861377SDaniel Baluta {"KXCJ1008", KXCJ91008}, 138561e2c70dSAntonio Ospite {"KXCJ9000", KXCJ91008}, 13864d19c487SChristophe Chapuis {"KIOX000A", KXCJ91008}, 1387c6861377SDaniel Baluta {"KXTJ1009", KXTJ21009}, 13883bfa74f8SBastien Nocera {"SMO8500", KXCJ91008}, 13891a4fbf6aSSrinivas Pandruvada { }, 13901a4fbf6aSSrinivas Pandruvada }; 13911a4fbf6aSSrinivas Pandruvada MODULE_DEVICE_TABLE(acpi, kx_acpi_match); 13921a4fbf6aSSrinivas Pandruvada 13931a4fbf6aSSrinivas Pandruvada static const struct i2c_device_id kxcjk1013_id[] = { 1394c6861377SDaniel Baluta {"kxcjk1013", KXCJK1013}, 1395c6861377SDaniel Baluta {"kxcj91008", KXCJ91008}, 1396c6861377SDaniel Baluta {"kxtj21009", KXTJ21009}, 13973bfa74f8SBastien Nocera {"SMO8500", KXCJ91008}, 13981a4fbf6aSSrinivas Pandruvada {} 13991a4fbf6aSSrinivas Pandruvada }; 14001a4fbf6aSSrinivas Pandruvada 14011a4fbf6aSSrinivas Pandruvada MODULE_DEVICE_TABLE(i2c, kxcjk1013_id); 14021a4fbf6aSSrinivas Pandruvada 14031a4fbf6aSSrinivas Pandruvada static struct i2c_driver kxcjk1013_driver = { 14041a4fbf6aSSrinivas Pandruvada .driver = { 14051a4fbf6aSSrinivas Pandruvada .name = KXCJK1013_DRV_NAME, 14061a4fbf6aSSrinivas Pandruvada .acpi_match_table = ACPI_PTR(kx_acpi_match), 1407124e1b1dSSrinivas Pandruvada .pm = &kxcjk1013_pm_ops, 14081a4fbf6aSSrinivas Pandruvada }, 14091a4fbf6aSSrinivas Pandruvada .probe = kxcjk1013_probe, 14101a4fbf6aSSrinivas Pandruvada .remove = kxcjk1013_remove, 14111a4fbf6aSSrinivas Pandruvada .id_table = kxcjk1013_id, 14121a4fbf6aSSrinivas Pandruvada }; 14131a4fbf6aSSrinivas Pandruvada module_i2c_driver(kxcjk1013_driver); 14141a4fbf6aSSrinivas Pandruvada 14151a4fbf6aSSrinivas Pandruvada MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 14161a4fbf6aSSrinivas Pandruvada MODULE_LICENSE("GPL v2"); 14171a4fbf6aSSrinivas Pandruvada MODULE_DESCRIPTION("KXCJK1013 accelerometer driver"); 1418