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) 70f74e440cSMichał Mirosław 71f74e440cSMichał Mirosław #define KXCJK1013_REG_INT_CTRL1_BIT_IEL BIT(3) 72f74e440cSMichał Mirosław #define KXCJK1013_REG_INT_CTRL1_BIT_IEA BIT(4) 73f74e440cSMichał 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 80f74e440cSMichał Mirosław #define KXCJK1013_REG_INT_SRC1_BIT_WUFS BIT(1) 81f74e440cSMichał Mirosław #define KXCJK1013_REG_INT_SRC1_BIT_DRDY BIT(4) 82f74e440cSMichał 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 158*81fa8cb9SMichał Mirosław static const char *const kxcjk1013_samp_freq_avail = 159*81fa8cb9SMichał Mirosław "0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800 1600"; 160*81fa8cb9SMichał Mirosław 1611a4fbf6aSSrinivas Pandruvada /* Refer to section 4 of the specification */ 1621a4fbf6aSSrinivas Pandruvada static const struct { 1631a4fbf6aSSrinivas Pandruvada int odr_bits; 1641a4fbf6aSSrinivas Pandruvada int usec; 165c6861377SDaniel Baluta } odr_start_up_times[KX_MAX_CHIPS][12] = { 166c6861377SDaniel Baluta /* KXCJK-1013 */ 167c6861377SDaniel Baluta { 168c6861377SDaniel Baluta {0x08, 100000}, 169c6861377SDaniel Baluta {0x09, 100000}, 170c6861377SDaniel Baluta {0x0A, 100000}, 171c6861377SDaniel Baluta {0x0B, 100000}, 172c6861377SDaniel Baluta {0, 80000}, 173c6861377SDaniel Baluta {0x01, 41000}, 174c6861377SDaniel Baluta {0x02, 21000}, 175c6861377SDaniel Baluta {0x03, 11000}, 176c6861377SDaniel Baluta {0x04, 6400}, 177c6861377SDaniel Baluta {0x05, 3900}, 178c6861377SDaniel Baluta {0x06, 2700}, 179c6861377SDaniel Baluta {0x07, 2100}, 180c6861377SDaniel Baluta }, 181c6861377SDaniel Baluta /* KXCJ9-1008 */ 182c6861377SDaniel Baluta { 183c6861377SDaniel Baluta {0x08, 100000}, 184c6861377SDaniel Baluta {0x09, 100000}, 185c6861377SDaniel Baluta {0x0A, 100000}, 186c6861377SDaniel Baluta {0x0B, 100000}, 187c6861377SDaniel Baluta {0, 80000}, 188c6861377SDaniel Baluta {0x01, 41000}, 189c6861377SDaniel Baluta {0x02, 21000}, 190c6861377SDaniel Baluta {0x03, 11000}, 191c6861377SDaniel Baluta {0x04, 6400}, 192c6861377SDaniel Baluta {0x05, 3900}, 193c6861377SDaniel Baluta {0x06, 2700}, 194c6861377SDaniel Baluta {0x07, 2100}, 195c6861377SDaniel Baluta }, 196c6861377SDaniel Baluta /* KXCTJ2-1009 */ 197c6861377SDaniel Baluta { 198c6861377SDaniel Baluta {0x08, 1240000}, 199c6861377SDaniel Baluta {0x09, 621000}, 200c6861377SDaniel Baluta {0x0A, 309000}, 201c6861377SDaniel Baluta {0x0B, 151000}, 202c6861377SDaniel Baluta {0, 80000}, 203c6861377SDaniel Baluta {0x01, 41000}, 204c6861377SDaniel Baluta {0x02, 21000}, 205c6861377SDaniel Baluta {0x03, 11000}, 206c6861377SDaniel Baluta {0x04, 6000}, 207c6861377SDaniel Baluta {0x05, 4000}, 208c6861377SDaniel Baluta {0x06, 3000}, 209c6861377SDaniel Baluta {0x07, 2000}, 210c6861377SDaniel Baluta }, 211c6861377SDaniel Baluta }; 2121a4fbf6aSSrinivas Pandruvada 213a735e3d7SSrinivas Pandruvada static const struct { 214a735e3d7SSrinivas Pandruvada u16 scale; 215a735e3d7SSrinivas Pandruvada u8 gsel_0; 216a735e3d7SSrinivas Pandruvada u8 gsel_1; 217a735e3d7SSrinivas Pandruvada } KXCJK1013_scale_table[] = { {9582, 0, 0}, 218a735e3d7SSrinivas Pandruvada {19163, 1, 0}, 219a735e3d7SSrinivas Pandruvada {38326, 0, 1} }; 220a735e3d7SSrinivas Pandruvada 2211a4fbf6aSSrinivas Pandruvada static int kxcjk1013_set_mode(struct kxcjk1013_data *data, 2221a4fbf6aSSrinivas Pandruvada enum kxcjk1013_mode mode) 2231a4fbf6aSSrinivas Pandruvada { 2241a4fbf6aSSrinivas Pandruvada int ret; 2251a4fbf6aSSrinivas Pandruvada 2261a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); 2271a4fbf6aSSrinivas Pandruvada if (ret < 0) { 2281a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 2291a4fbf6aSSrinivas Pandruvada return ret; 2301a4fbf6aSSrinivas Pandruvada } 2311a4fbf6aSSrinivas Pandruvada 2321a4fbf6aSSrinivas Pandruvada if (mode == STANDBY) 2331a4fbf6aSSrinivas Pandruvada ret &= ~KXCJK1013_REG_CTRL1_BIT_PC1; 2341a4fbf6aSSrinivas Pandruvada else 2351a4fbf6aSSrinivas Pandruvada ret |= KXCJK1013_REG_CTRL1_BIT_PC1; 2361a4fbf6aSSrinivas Pandruvada 2371a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 2381a4fbf6aSSrinivas Pandruvada KXCJK1013_REG_CTRL1, ret); 2391a4fbf6aSSrinivas Pandruvada if (ret < 0) { 2401a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); 2411a4fbf6aSSrinivas Pandruvada return ret; 2421a4fbf6aSSrinivas Pandruvada } 2431a4fbf6aSSrinivas Pandruvada 2441a4fbf6aSSrinivas Pandruvada return 0; 2451a4fbf6aSSrinivas Pandruvada } 2461a4fbf6aSSrinivas Pandruvada 247124e1b1dSSrinivas Pandruvada static int kxcjk1013_get_mode(struct kxcjk1013_data *data, 248124e1b1dSSrinivas Pandruvada enum kxcjk1013_mode *mode) 249124e1b1dSSrinivas Pandruvada { 250124e1b1dSSrinivas Pandruvada int ret; 251124e1b1dSSrinivas Pandruvada 252124e1b1dSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); 253124e1b1dSSrinivas Pandruvada if (ret < 0) { 254124e1b1dSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 255124e1b1dSSrinivas Pandruvada return ret; 256124e1b1dSSrinivas Pandruvada } 257124e1b1dSSrinivas Pandruvada 258124e1b1dSSrinivas Pandruvada if (ret & KXCJK1013_REG_CTRL1_BIT_PC1) 259124e1b1dSSrinivas Pandruvada *mode = OPERATION; 260124e1b1dSSrinivas Pandruvada else 261124e1b1dSSrinivas Pandruvada *mode = STANDBY; 262124e1b1dSSrinivas Pandruvada 263124e1b1dSSrinivas Pandruvada return 0; 264124e1b1dSSrinivas Pandruvada } 265124e1b1dSSrinivas Pandruvada 266a735e3d7SSrinivas Pandruvada static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index) 267a735e3d7SSrinivas Pandruvada { 268a735e3d7SSrinivas Pandruvada int ret; 269a735e3d7SSrinivas Pandruvada 270a735e3d7SSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); 271a735e3d7SSrinivas Pandruvada if (ret < 0) { 272a735e3d7SSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 273a735e3d7SSrinivas Pandruvada return ret; 274a735e3d7SSrinivas Pandruvada } 275a735e3d7SSrinivas Pandruvada 276e90dea6aSDaniel Baluta ret &= ~(KXCJK1013_REG_CTRL1_BIT_GSEL0 | 277e90dea6aSDaniel Baluta KXCJK1013_REG_CTRL1_BIT_GSEL1); 278a735e3d7SSrinivas Pandruvada ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3); 279a735e3d7SSrinivas Pandruvada ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4); 280a735e3d7SSrinivas Pandruvada 281a735e3d7SSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 282a735e3d7SSrinivas Pandruvada KXCJK1013_REG_CTRL1, 283a735e3d7SSrinivas Pandruvada ret); 284a735e3d7SSrinivas Pandruvada if (ret < 0) { 285a735e3d7SSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); 286a735e3d7SSrinivas Pandruvada return ret; 287a735e3d7SSrinivas Pandruvada } 288a735e3d7SSrinivas Pandruvada 289a735e3d7SSrinivas Pandruvada data->range = range_index; 290a735e3d7SSrinivas Pandruvada 291a735e3d7SSrinivas Pandruvada return 0; 292a735e3d7SSrinivas Pandruvada } 293a735e3d7SSrinivas Pandruvada 2941a4fbf6aSSrinivas Pandruvada static int kxcjk1013_chip_init(struct kxcjk1013_data *data) 2951a4fbf6aSSrinivas Pandruvada { 2961a4fbf6aSSrinivas Pandruvada int ret; 2971a4fbf6aSSrinivas Pandruvada 2981a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_WHO_AM_I); 2991a4fbf6aSSrinivas Pandruvada if (ret < 0) { 3001a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading who_am_i\n"); 3011a4fbf6aSSrinivas Pandruvada return ret; 3021a4fbf6aSSrinivas Pandruvada } 3031a4fbf6aSSrinivas Pandruvada 3041a4fbf6aSSrinivas Pandruvada dev_dbg(&data->client->dev, "KXCJK1013 Chip Id %x\n", ret); 3051a4fbf6aSSrinivas Pandruvada 3061a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, STANDBY); 3071a4fbf6aSSrinivas Pandruvada if (ret < 0) 3081a4fbf6aSSrinivas Pandruvada return ret; 3091a4fbf6aSSrinivas Pandruvada 3101a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); 3111a4fbf6aSSrinivas Pandruvada if (ret < 0) { 3121a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 3131a4fbf6aSSrinivas Pandruvada return ret; 3141a4fbf6aSSrinivas Pandruvada } 3151a4fbf6aSSrinivas Pandruvada 3161a4fbf6aSSrinivas Pandruvada /* Set 12 bit mode */ 3171a4fbf6aSSrinivas Pandruvada ret |= KXCJK1013_REG_CTRL1_BIT_RES; 3181a4fbf6aSSrinivas Pandruvada 3191a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_CTRL1, 3201a4fbf6aSSrinivas Pandruvada ret); 3211a4fbf6aSSrinivas Pandruvada if (ret < 0) { 3221a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_ctrl\n"); 3231a4fbf6aSSrinivas Pandruvada return ret; 3241a4fbf6aSSrinivas Pandruvada } 3251a4fbf6aSSrinivas Pandruvada 326a735e3d7SSrinivas Pandruvada /* Setting range to 4G */ 327a735e3d7SSrinivas Pandruvada ret = kxcjk1013_set_range(data, KXCJK1013_RANGE_4G); 328a735e3d7SSrinivas Pandruvada if (ret < 0) 329a735e3d7SSrinivas Pandruvada return ret; 330a735e3d7SSrinivas Pandruvada 3311a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_DATA_CTRL); 3321a4fbf6aSSrinivas Pandruvada if (ret < 0) { 3331a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_data_ctrl\n"); 3341a4fbf6aSSrinivas Pandruvada return ret; 3351a4fbf6aSSrinivas Pandruvada } 3361a4fbf6aSSrinivas Pandruvada 3371a4fbf6aSSrinivas Pandruvada data->odr_bits = ret; 3381a4fbf6aSSrinivas Pandruvada 3391a4fbf6aSSrinivas Pandruvada /* Set up INT polarity */ 3401a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1); 3411a4fbf6aSSrinivas Pandruvada if (ret < 0) { 3421a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); 3431a4fbf6aSSrinivas Pandruvada return ret; 3441a4fbf6aSSrinivas Pandruvada } 3451a4fbf6aSSrinivas Pandruvada 3461a4fbf6aSSrinivas Pandruvada if (data->active_high_intr) 347f74e440cSMichał Mirosław ret |= KXCJK1013_REG_INT_CTRL1_BIT_IEA; 3481a4fbf6aSSrinivas Pandruvada else 349f74e440cSMichał Mirosław ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEA; 3501a4fbf6aSSrinivas Pandruvada 3511a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1, 3521a4fbf6aSSrinivas Pandruvada ret); 3531a4fbf6aSSrinivas Pandruvada if (ret < 0) { 3541a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); 3551a4fbf6aSSrinivas Pandruvada return ret; 3561a4fbf6aSSrinivas Pandruvada } 3571a4fbf6aSSrinivas Pandruvada 358124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, OPERATION); 359124e1b1dSSrinivas Pandruvada if (ret < 0) 360124e1b1dSSrinivas Pandruvada return ret; 361124e1b1dSSrinivas Pandruvada 362b4b491c0SSrinivas Pandruvada data->wake_thres = KXCJK1013_DEFAULT_WAKE_THRES; 363b4b491c0SSrinivas Pandruvada 364124e1b1dSSrinivas Pandruvada return 0; 365124e1b1dSSrinivas Pandruvada } 366124e1b1dSSrinivas Pandruvada 3676f0a13f2SRafael J. Wysocki #ifdef CONFIG_PM 368124e1b1dSSrinivas Pandruvada static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data) 369124e1b1dSSrinivas Pandruvada { 370124e1b1dSSrinivas Pandruvada int i; 371c6861377SDaniel Baluta int idx = data->chipset; 372124e1b1dSSrinivas Pandruvada 373c6861377SDaniel Baluta for (i = 0; i < ARRAY_SIZE(odr_start_up_times[idx]); ++i) { 374c6861377SDaniel Baluta if (odr_start_up_times[idx][i].odr_bits == data->odr_bits) 375c6861377SDaniel Baluta return odr_start_up_times[idx][i].usec; 376124e1b1dSSrinivas Pandruvada } 377124e1b1dSSrinivas Pandruvada 378124e1b1dSSrinivas Pandruvada return KXCJK1013_MAX_STARTUP_TIME_US; 379124e1b1dSSrinivas Pandruvada } 380c9bf2373SDaniel Baluta #endif 381124e1b1dSSrinivas Pandruvada 382124e1b1dSSrinivas Pandruvada static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) 383124e1b1dSSrinivas Pandruvada { 384c75b8dc8SIrina Tirdea #ifdef CONFIG_PM 385124e1b1dSSrinivas Pandruvada int ret; 386124e1b1dSSrinivas Pandruvada 387124e1b1dSSrinivas Pandruvada if (on) 388124e1b1dSSrinivas Pandruvada ret = pm_runtime_get_sync(&data->client->dev); 389124e1b1dSSrinivas Pandruvada else { 390124e1b1dSSrinivas Pandruvada pm_runtime_mark_last_busy(&data->client->dev); 391124e1b1dSSrinivas Pandruvada ret = pm_runtime_put_autosuspend(&data->client->dev); 392124e1b1dSSrinivas Pandruvada } 393124e1b1dSSrinivas Pandruvada if (ret < 0) { 394124e1b1dSSrinivas Pandruvada dev_err(&data->client->dev, 395124e1b1dSSrinivas Pandruvada "Failed: kxcjk1013_set_power_state for %d\n", on); 396fbd123e9SIrina Tirdea if (on) 397fbd123e9SIrina Tirdea pm_runtime_put_noidle(&data->client->dev); 398124e1b1dSSrinivas Pandruvada return ret; 399124e1b1dSSrinivas Pandruvada } 400c75b8dc8SIrina Tirdea #endif 401124e1b1dSSrinivas Pandruvada 4021a4fbf6aSSrinivas Pandruvada return 0; 4031a4fbf6aSSrinivas Pandruvada } 4041a4fbf6aSSrinivas Pandruvada 405b4b491c0SSrinivas Pandruvada static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data) 406b4b491c0SSrinivas Pandruvada { 407b4b491c0SSrinivas Pandruvada int ret; 408b4b491c0SSrinivas Pandruvada 409b4b491c0SSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 410b4b491c0SSrinivas Pandruvada KXCJK1013_REG_WAKE_TIMER, 411b4b491c0SSrinivas Pandruvada data->wake_dur); 412b4b491c0SSrinivas Pandruvada if (ret < 0) { 413b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, 414b4b491c0SSrinivas Pandruvada "Error writing reg_wake_timer\n"); 415b4b491c0SSrinivas Pandruvada return ret; 416b4b491c0SSrinivas Pandruvada } 417b4b491c0SSrinivas Pandruvada 418b4b491c0SSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 419b4b491c0SSrinivas Pandruvada KXCJK1013_REG_WAKE_THRES, 420b4b491c0SSrinivas Pandruvada data->wake_thres); 421b4b491c0SSrinivas Pandruvada if (ret < 0) { 422b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_wake_thres\n"); 423b4b491c0SSrinivas Pandruvada return ret; 424b4b491c0SSrinivas Pandruvada } 425b4b491c0SSrinivas Pandruvada 426b4b491c0SSrinivas Pandruvada return 0; 427b4b491c0SSrinivas Pandruvada } 428b4b491c0SSrinivas Pandruvada 429b4b491c0SSrinivas Pandruvada static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, 430b4b491c0SSrinivas Pandruvada bool status) 431b4b491c0SSrinivas Pandruvada { 432b4b491c0SSrinivas Pandruvada int ret; 433b4b491c0SSrinivas Pandruvada enum kxcjk1013_mode store_mode; 434b4b491c0SSrinivas Pandruvada 435b4b491c0SSrinivas Pandruvada ret = kxcjk1013_get_mode(data, &store_mode); 436b4b491c0SSrinivas Pandruvada if (ret < 0) 437b4b491c0SSrinivas Pandruvada return ret; 438b4b491c0SSrinivas Pandruvada 439b4b491c0SSrinivas Pandruvada /* This is requirement by spec to change state to STANDBY */ 440b4b491c0SSrinivas Pandruvada ret = kxcjk1013_set_mode(data, STANDBY); 441b4b491c0SSrinivas Pandruvada if (ret < 0) 442b4b491c0SSrinivas Pandruvada return ret; 443b4b491c0SSrinivas Pandruvada 444b4b491c0SSrinivas Pandruvada ret = kxcjk1013_chip_update_thresholds(data); 445b4b491c0SSrinivas Pandruvada if (ret < 0) 446b4b491c0SSrinivas Pandruvada return ret; 447b4b491c0SSrinivas Pandruvada 448b4b491c0SSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1); 449b4b491c0SSrinivas Pandruvada if (ret < 0) { 450b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); 451b4b491c0SSrinivas Pandruvada return ret; 452b4b491c0SSrinivas Pandruvada } 453b4b491c0SSrinivas Pandruvada 454b4b491c0SSrinivas Pandruvada if (status) 455f74e440cSMichał Mirosław ret |= KXCJK1013_REG_INT_CTRL1_BIT_IEN; 456b4b491c0SSrinivas Pandruvada else 457f74e440cSMichał Mirosław ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; 458b4b491c0SSrinivas Pandruvada 459b4b491c0SSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1, 460b4b491c0SSrinivas Pandruvada ret); 461b4b491c0SSrinivas Pandruvada if (ret < 0) { 462b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); 463b4b491c0SSrinivas Pandruvada return ret; 464b4b491c0SSrinivas Pandruvada } 465b4b491c0SSrinivas Pandruvada 466b4b491c0SSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); 467b4b491c0SSrinivas Pandruvada if (ret < 0) { 468b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 469b4b491c0SSrinivas Pandruvada return ret; 470b4b491c0SSrinivas Pandruvada } 471b4b491c0SSrinivas Pandruvada 472b4b491c0SSrinivas Pandruvada if (status) 473b4b491c0SSrinivas Pandruvada ret |= KXCJK1013_REG_CTRL1_BIT_WUFE; 474b4b491c0SSrinivas Pandruvada else 475b4b491c0SSrinivas Pandruvada ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE; 476b4b491c0SSrinivas Pandruvada 477b4b491c0SSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 478b4b491c0SSrinivas Pandruvada KXCJK1013_REG_CTRL1, ret); 479b4b491c0SSrinivas Pandruvada if (ret < 0) { 480b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); 481b4b491c0SSrinivas Pandruvada return ret; 482b4b491c0SSrinivas Pandruvada } 483b4b491c0SSrinivas Pandruvada 484b4b491c0SSrinivas Pandruvada if (store_mode == OPERATION) { 485b4b491c0SSrinivas Pandruvada ret = kxcjk1013_set_mode(data, OPERATION); 486b4b491c0SSrinivas Pandruvada if (ret < 0) 487b4b491c0SSrinivas Pandruvada return ret; 488b4b491c0SSrinivas Pandruvada } 489b4b491c0SSrinivas Pandruvada 490b4b491c0SSrinivas Pandruvada return 0; 491b4b491c0SSrinivas Pandruvada } 492b4b491c0SSrinivas Pandruvada 493b4b491c0SSrinivas Pandruvada static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, 4941a4fbf6aSSrinivas Pandruvada bool status) 4951a4fbf6aSSrinivas Pandruvada { 4961a4fbf6aSSrinivas Pandruvada int ret; 497124e1b1dSSrinivas Pandruvada enum kxcjk1013_mode store_mode; 498124e1b1dSSrinivas Pandruvada 499124e1b1dSSrinivas Pandruvada ret = kxcjk1013_get_mode(data, &store_mode); 500124e1b1dSSrinivas Pandruvada if (ret < 0) 501124e1b1dSSrinivas Pandruvada return ret; 5021a4fbf6aSSrinivas Pandruvada 5031a4fbf6aSSrinivas Pandruvada /* This is requirement by spec to change state to STANDBY */ 5041a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, STANDBY); 5051a4fbf6aSSrinivas Pandruvada if (ret < 0) 5061a4fbf6aSSrinivas Pandruvada return ret; 5071a4fbf6aSSrinivas Pandruvada 5081a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1); 5091a4fbf6aSSrinivas Pandruvada if (ret < 0) { 5101a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); 5111a4fbf6aSSrinivas Pandruvada return ret; 5121a4fbf6aSSrinivas Pandruvada } 5131a4fbf6aSSrinivas Pandruvada 5141a4fbf6aSSrinivas Pandruvada if (status) 515f74e440cSMichał Mirosław ret |= KXCJK1013_REG_INT_CTRL1_BIT_IEN; 5161a4fbf6aSSrinivas Pandruvada else 517f74e440cSMichał Mirosław ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; 5181a4fbf6aSSrinivas Pandruvada 5191a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1, 5201a4fbf6aSSrinivas Pandruvada ret); 5211a4fbf6aSSrinivas Pandruvada if (ret < 0) { 5221a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); 5231a4fbf6aSSrinivas Pandruvada return ret; 5241a4fbf6aSSrinivas Pandruvada } 5251a4fbf6aSSrinivas Pandruvada 5261a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); 5271a4fbf6aSSrinivas Pandruvada if (ret < 0) { 5281a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); 5291a4fbf6aSSrinivas Pandruvada return ret; 5301a4fbf6aSSrinivas Pandruvada } 5311a4fbf6aSSrinivas Pandruvada 5321a4fbf6aSSrinivas Pandruvada if (status) 5331a4fbf6aSSrinivas Pandruvada ret |= KXCJK1013_REG_CTRL1_BIT_DRDY; 5341a4fbf6aSSrinivas Pandruvada else 5351a4fbf6aSSrinivas Pandruvada ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY; 5361a4fbf6aSSrinivas Pandruvada 5371a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 5381a4fbf6aSSrinivas Pandruvada KXCJK1013_REG_CTRL1, ret); 5391a4fbf6aSSrinivas Pandruvada if (ret < 0) { 5401a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); 5411a4fbf6aSSrinivas Pandruvada return ret; 5421a4fbf6aSSrinivas Pandruvada } 5431a4fbf6aSSrinivas Pandruvada 544124e1b1dSSrinivas Pandruvada if (store_mode == OPERATION) { 545124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, OPERATION); 546124e1b1dSSrinivas Pandruvada if (ret < 0) 5471a4fbf6aSSrinivas Pandruvada return ret; 5481a4fbf6aSSrinivas Pandruvada } 5491a4fbf6aSSrinivas Pandruvada 550124e1b1dSSrinivas Pandruvada return 0; 551124e1b1dSSrinivas Pandruvada } 552124e1b1dSSrinivas Pandruvada 5537469ac69SMichał Mirosław static const struct kx_odr_map *kxcjk1013_find_odr_value( 5547469ac69SMichał Mirosław const struct kx_odr_map *map, size_t map_size, int val, int val2) 5551a4fbf6aSSrinivas Pandruvada { 5561a4fbf6aSSrinivas Pandruvada int i; 5571a4fbf6aSSrinivas Pandruvada 5587469ac69SMichał Mirosław for (i = 0; i < map_size; ++i) { 5597469ac69SMichał Mirosław if (map[i].val == val && map[i].val2 == val2) 5607469ac69SMichał Mirosław return &map[i]; 5611a4fbf6aSSrinivas Pandruvada } 5621a4fbf6aSSrinivas Pandruvada 5637469ac69SMichał Mirosław return ERR_PTR(-EINVAL); 5641a4fbf6aSSrinivas Pandruvada } 5651a4fbf6aSSrinivas Pandruvada 5667469ac69SMichał Mirosław static int kxcjk1013_convert_odr_value(const struct kx_odr_map *map, 5677469ac69SMichał Mirosław size_t map_size, int odr_bits, 5687469ac69SMichał Mirosław int *val, int *val2) 569b4b491c0SSrinivas Pandruvada { 570b4b491c0SSrinivas Pandruvada int i; 571b4b491c0SSrinivas Pandruvada 5727469ac69SMichał Mirosław for (i = 0; i < map_size; ++i) { 5737469ac69SMichał Mirosław if (map[i].odr_bits == odr_bits) { 5747469ac69SMichał Mirosław *val = map[i].val; 5757469ac69SMichał Mirosław *val2 = map[i].val2; 5767469ac69SMichał Mirosław return IIO_VAL_INT_PLUS_MICRO; 577b4b491c0SSrinivas Pandruvada } 578b4b491c0SSrinivas Pandruvada } 579b4b491c0SSrinivas Pandruvada 580b4b491c0SSrinivas Pandruvada return -EINVAL; 581b4b491c0SSrinivas Pandruvada } 582b4b491c0SSrinivas Pandruvada 5831a4fbf6aSSrinivas Pandruvada static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2) 5841a4fbf6aSSrinivas Pandruvada { 5851a4fbf6aSSrinivas Pandruvada int ret; 586124e1b1dSSrinivas Pandruvada enum kxcjk1013_mode store_mode; 5877469ac69SMichał Mirosław const struct kx_odr_map *odr_setting; 588124e1b1dSSrinivas Pandruvada 589124e1b1dSSrinivas Pandruvada ret = kxcjk1013_get_mode(data, &store_mode); 590124e1b1dSSrinivas Pandruvada if (ret < 0) 591124e1b1dSSrinivas Pandruvada return ret; 5921a4fbf6aSSrinivas Pandruvada 5937469ac69SMichał Mirosław odr_setting = kxcjk1013_find_odr_value(samp_freq_table, 5947469ac69SMichał Mirosław ARRAY_SIZE(samp_freq_table), 5957469ac69SMichał Mirosław val, val2); 5967469ac69SMichał Mirosław 5977469ac69SMichał Mirosław if (IS_ERR(odr_setting)) 5987469ac69SMichał Mirosław return PTR_ERR(odr_setting); 5991a4fbf6aSSrinivas Pandruvada 6001a4fbf6aSSrinivas Pandruvada /* To change ODR, the chip must be set to STANDBY as per spec */ 6011a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, STANDBY); 6021a4fbf6aSSrinivas Pandruvada if (ret < 0) 6031a4fbf6aSSrinivas Pandruvada return ret; 6041a4fbf6aSSrinivas Pandruvada 6051a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_DATA_CTRL, 6067469ac69SMichał Mirosław odr_setting->odr_bits); 6071a4fbf6aSSrinivas Pandruvada if (ret < 0) { 6081a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, "Error writing data_ctrl\n"); 6091a4fbf6aSSrinivas Pandruvada return ret; 6101a4fbf6aSSrinivas Pandruvada } 6111a4fbf6aSSrinivas Pandruvada 6127469ac69SMichał Mirosław data->odr_bits = odr_setting->odr_bits; 613b4b491c0SSrinivas Pandruvada 614b4b491c0SSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_CTRL2, 6157469ac69SMichał Mirosław odr_setting->wuf_bits); 616b4b491c0SSrinivas Pandruvada if (ret < 0) { 617b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_ctrl2\n"); 618b4b491c0SSrinivas Pandruvada return ret; 619b4b491c0SSrinivas Pandruvada } 620b4b491c0SSrinivas Pandruvada 621124e1b1dSSrinivas Pandruvada if (store_mode == OPERATION) { 6221a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, OPERATION); 6231a4fbf6aSSrinivas Pandruvada if (ret < 0) 6241a4fbf6aSSrinivas Pandruvada return ret; 6251a4fbf6aSSrinivas Pandruvada } 6261a4fbf6aSSrinivas Pandruvada 6271a4fbf6aSSrinivas Pandruvada return 0; 6281a4fbf6aSSrinivas Pandruvada } 6291a4fbf6aSSrinivas Pandruvada 6301a4fbf6aSSrinivas Pandruvada static int kxcjk1013_get_odr(struct kxcjk1013_data *data, int *val, int *val2) 6311a4fbf6aSSrinivas Pandruvada { 6327469ac69SMichał Mirosław return kxcjk1013_convert_odr_value(samp_freq_table, 6337469ac69SMichał Mirosław ARRAY_SIZE(samp_freq_table), 6347469ac69SMichał Mirosław data->odr_bits, val, val2); 6351a4fbf6aSSrinivas Pandruvada } 6361a4fbf6aSSrinivas Pandruvada 6371a4fbf6aSSrinivas Pandruvada static int kxcjk1013_get_acc_reg(struct kxcjk1013_data *data, int axis) 6381a4fbf6aSSrinivas Pandruvada { 6391a4fbf6aSSrinivas Pandruvada u8 reg = KXCJK1013_REG_XOUT_L + axis * 2; 6401a4fbf6aSSrinivas Pandruvada int ret; 6411a4fbf6aSSrinivas Pandruvada 6421a4fbf6aSSrinivas Pandruvada ret = i2c_smbus_read_word_data(data->client, reg); 6431a4fbf6aSSrinivas Pandruvada if (ret < 0) { 6441a4fbf6aSSrinivas Pandruvada dev_err(&data->client->dev, 6451a4fbf6aSSrinivas Pandruvada "failed to read accel_%c registers\n", 'x' + axis); 6461a4fbf6aSSrinivas Pandruvada return ret; 6471a4fbf6aSSrinivas Pandruvada } 6481a4fbf6aSSrinivas Pandruvada 6491a4fbf6aSSrinivas Pandruvada return ret; 6501a4fbf6aSSrinivas Pandruvada } 6511a4fbf6aSSrinivas Pandruvada 652a735e3d7SSrinivas Pandruvada static int kxcjk1013_set_scale(struct kxcjk1013_data *data, int val) 653a735e3d7SSrinivas Pandruvada { 654a735e3d7SSrinivas Pandruvada int ret, i; 655a735e3d7SSrinivas Pandruvada enum kxcjk1013_mode store_mode; 656a735e3d7SSrinivas Pandruvada 657a735e3d7SSrinivas Pandruvada for (i = 0; i < ARRAY_SIZE(KXCJK1013_scale_table); ++i) { 658a735e3d7SSrinivas Pandruvada if (KXCJK1013_scale_table[i].scale == val) { 659a735e3d7SSrinivas Pandruvada ret = kxcjk1013_get_mode(data, &store_mode); 660a735e3d7SSrinivas Pandruvada if (ret < 0) 661a735e3d7SSrinivas Pandruvada return ret; 662a735e3d7SSrinivas Pandruvada 663a735e3d7SSrinivas Pandruvada ret = kxcjk1013_set_mode(data, STANDBY); 664a735e3d7SSrinivas Pandruvada if (ret < 0) 665a735e3d7SSrinivas Pandruvada return ret; 666a735e3d7SSrinivas Pandruvada 667a735e3d7SSrinivas Pandruvada ret = kxcjk1013_set_range(data, i); 668a735e3d7SSrinivas Pandruvada if (ret < 0) 669a735e3d7SSrinivas Pandruvada return ret; 670a735e3d7SSrinivas Pandruvada 671a735e3d7SSrinivas Pandruvada if (store_mode == OPERATION) { 672a735e3d7SSrinivas Pandruvada ret = kxcjk1013_set_mode(data, OPERATION); 673a735e3d7SSrinivas Pandruvada if (ret) 674a735e3d7SSrinivas Pandruvada return ret; 675a735e3d7SSrinivas Pandruvada } 676a735e3d7SSrinivas Pandruvada 677a735e3d7SSrinivas Pandruvada return 0; 678a735e3d7SSrinivas Pandruvada } 679a735e3d7SSrinivas Pandruvada } 680a735e3d7SSrinivas Pandruvada 681a735e3d7SSrinivas Pandruvada return -EINVAL; 682a735e3d7SSrinivas Pandruvada } 683a735e3d7SSrinivas Pandruvada 6841a4fbf6aSSrinivas Pandruvada static int kxcjk1013_read_raw(struct iio_dev *indio_dev, 6851a4fbf6aSSrinivas Pandruvada struct iio_chan_spec const *chan, int *val, 6861a4fbf6aSSrinivas Pandruvada int *val2, long mask) 6871a4fbf6aSSrinivas Pandruvada { 6881a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 6891a4fbf6aSSrinivas Pandruvada int ret; 6901a4fbf6aSSrinivas Pandruvada 6911a4fbf6aSSrinivas Pandruvada switch (mask) { 6921a4fbf6aSSrinivas Pandruvada case IIO_CHAN_INFO_RAW: 6931a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 6941a4fbf6aSSrinivas Pandruvada if (iio_buffer_enabled(indio_dev)) 6951a4fbf6aSSrinivas Pandruvada ret = -EBUSY; 6961a4fbf6aSSrinivas Pandruvada else { 697124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_power_state(data, true); 69888f6da77SSrinivas Pandruvada if (ret < 0) { 69988f6da77SSrinivas Pandruvada mutex_unlock(&data->mutex); 7001a4fbf6aSSrinivas Pandruvada return ret; 70188f6da77SSrinivas Pandruvada } 7021a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_get_acc_reg(data, chan->scan_index); 703124e1b1dSSrinivas Pandruvada if (ret < 0) { 704124e1b1dSSrinivas Pandruvada kxcjk1013_set_power_state(data, false); 705124e1b1dSSrinivas Pandruvada mutex_unlock(&data->mutex); 706124e1b1dSSrinivas Pandruvada return ret; 707124e1b1dSSrinivas Pandruvada } 708124e1b1dSSrinivas Pandruvada *val = sign_extend32(ret >> 4, 11); 709124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_power_state(data, false); 7101a4fbf6aSSrinivas Pandruvada } 7111a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 7121a4fbf6aSSrinivas Pandruvada 7131a4fbf6aSSrinivas Pandruvada if (ret < 0) 7141a4fbf6aSSrinivas Pandruvada return ret; 7151a4fbf6aSSrinivas Pandruvada 7161a4fbf6aSSrinivas Pandruvada return IIO_VAL_INT; 7171a4fbf6aSSrinivas Pandruvada 7181a4fbf6aSSrinivas Pandruvada case IIO_CHAN_INFO_SCALE: 7191a4fbf6aSSrinivas Pandruvada *val = 0; 720a735e3d7SSrinivas Pandruvada *val2 = KXCJK1013_scale_table[data->range].scale; 7211a4fbf6aSSrinivas Pandruvada return IIO_VAL_INT_PLUS_MICRO; 7221a4fbf6aSSrinivas Pandruvada 7231a4fbf6aSSrinivas Pandruvada case IIO_CHAN_INFO_SAMP_FREQ: 7241a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 7251a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_get_odr(data, val, val2); 7261a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 7271a4fbf6aSSrinivas Pandruvada return ret; 7281a4fbf6aSSrinivas Pandruvada 7291a4fbf6aSSrinivas Pandruvada default: 7301a4fbf6aSSrinivas Pandruvada return -EINVAL; 7311a4fbf6aSSrinivas Pandruvada } 7321a4fbf6aSSrinivas Pandruvada } 7331a4fbf6aSSrinivas Pandruvada 7341a4fbf6aSSrinivas Pandruvada static int kxcjk1013_write_raw(struct iio_dev *indio_dev, 7351a4fbf6aSSrinivas Pandruvada struct iio_chan_spec const *chan, int val, 7361a4fbf6aSSrinivas Pandruvada int val2, long mask) 7371a4fbf6aSSrinivas Pandruvada { 7381a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 7391a4fbf6aSSrinivas Pandruvada int ret; 7401a4fbf6aSSrinivas Pandruvada 7411a4fbf6aSSrinivas Pandruvada switch (mask) { 7421a4fbf6aSSrinivas Pandruvada case IIO_CHAN_INFO_SAMP_FREQ: 7431a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 7441a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_set_odr(data, val, val2); 7451a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 7461a4fbf6aSSrinivas Pandruvada break; 747a735e3d7SSrinivas Pandruvada case IIO_CHAN_INFO_SCALE: 748a735e3d7SSrinivas Pandruvada if (val) 749a735e3d7SSrinivas Pandruvada return -EINVAL; 750a735e3d7SSrinivas Pandruvada 751a735e3d7SSrinivas Pandruvada mutex_lock(&data->mutex); 752a735e3d7SSrinivas Pandruvada ret = kxcjk1013_set_scale(data, val2); 753a735e3d7SSrinivas Pandruvada mutex_unlock(&data->mutex); 754a735e3d7SSrinivas Pandruvada break; 7551a4fbf6aSSrinivas Pandruvada default: 7561a4fbf6aSSrinivas Pandruvada ret = -EINVAL; 7571a4fbf6aSSrinivas Pandruvada } 7581a4fbf6aSSrinivas Pandruvada 7591a4fbf6aSSrinivas Pandruvada return ret; 7601a4fbf6aSSrinivas Pandruvada } 7611a4fbf6aSSrinivas Pandruvada 762b4b491c0SSrinivas Pandruvada static int kxcjk1013_read_event(struct iio_dev *indio_dev, 763b4b491c0SSrinivas Pandruvada const struct iio_chan_spec *chan, 764b4b491c0SSrinivas Pandruvada enum iio_event_type type, 765b4b491c0SSrinivas Pandruvada enum iio_event_direction dir, 766b4b491c0SSrinivas Pandruvada enum iio_event_info info, 767b4b491c0SSrinivas Pandruvada int *val, int *val2) 768b4b491c0SSrinivas Pandruvada { 769b4b491c0SSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 770b4b491c0SSrinivas Pandruvada 771b4b491c0SSrinivas Pandruvada *val2 = 0; 772b4b491c0SSrinivas Pandruvada switch (info) { 773b4b491c0SSrinivas Pandruvada case IIO_EV_INFO_VALUE: 774b4b491c0SSrinivas Pandruvada *val = data->wake_thres; 775b4b491c0SSrinivas Pandruvada break; 776b4b491c0SSrinivas Pandruvada case IIO_EV_INFO_PERIOD: 777b4b491c0SSrinivas Pandruvada *val = data->wake_dur; 778b4b491c0SSrinivas Pandruvada break; 779b4b491c0SSrinivas Pandruvada default: 780b4b491c0SSrinivas Pandruvada return -EINVAL; 781b4b491c0SSrinivas Pandruvada } 782b4b491c0SSrinivas Pandruvada 783b4b491c0SSrinivas Pandruvada return IIO_VAL_INT; 784b4b491c0SSrinivas Pandruvada } 785b4b491c0SSrinivas Pandruvada 786b4b491c0SSrinivas Pandruvada static int kxcjk1013_write_event(struct iio_dev *indio_dev, 787b4b491c0SSrinivas Pandruvada const struct iio_chan_spec *chan, 788b4b491c0SSrinivas Pandruvada enum iio_event_type type, 789b4b491c0SSrinivas Pandruvada enum iio_event_direction dir, 790b4b491c0SSrinivas Pandruvada enum iio_event_info info, 791b4b491c0SSrinivas Pandruvada int val, int val2) 792b4b491c0SSrinivas Pandruvada { 793b4b491c0SSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 794b4b491c0SSrinivas Pandruvada 795b4b491c0SSrinivas Pandruvada if (data->ev_enable_state) 796b4b491c0SSrinivas Pandruvada return -EBUSY; 797b4b491c0SSrinivas Pandruvada 798b4b491c0SSrinivas Pandruvada switch (info) { 799b4b491c0SSrinivas Pandruvada case IIO_EV_INFO_VALUE: 800b4b491c0SSrinivas Pandruvada data->wake_thres = val; 801b4b491c0SSrinivas Pandruvada break; 802b4b491c0SSrinivas Pandruvada case IIO_EV_INFO_PERIOD: 803b4b491c0SSrinivas Pandruvada data->wake_dur = val; 804b4b491c0SSrinivas Pandruvada break; 805b4b491c0SSrinivas Pandruvada default: 806b4b491c0SSrinivas Pandruvada return -EINVAL; 807b4b491c0SSrinivas Pandruvada } 808b4b491c0SSrinivas Pandruvada 809b4b491c0SSrinivas Pandruvada return 0; 810b4b491c0SSrinivas Pandruvada } 811b4b491c0SSrinivas Pandruvada 812b4b491c0SSrinivas Pandruvada static int kxcjk1013_read_event_config(struct iio_dev *indio_dev, 813b4b491c0SSrinivas Pandruvada const struct iio_chan_spec *chan, 814b4b491c0SSrinivas Pandruvada enum iio_event_type type, 815b4b491c0SSrinivas Pandruvada enum iio_event_direction dir) 816b4b491c0SSrinivas Pandruvada { 817b4b491c0SSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 818b4b491c0SSrinivas Pandruvada 819b4b491c0SSrinivas Pandruvada return data->ev_enable_state; 820b4b491c0SSrinivas Pandruvada } 821b4b491c0SSrinivas Pandruvada 822b4b491c0SSrinivas Pandruvada static int kxcjk1013_write_event_config(struct iio_dev *indio_dev, 823b4b491c0SSrinivas Pandruvada const struct iio_chan_spec *chan, 824b4b491c0SSrinivas Pandruvada enum iio_event_type type, 825b4b491c0SSrinivas Pandruvada enum iio_event_direction dir, 826b4b491c0SSrinivas Pandruvada int state) 827b4b491c0SSrinivas Pandruvada { 828b4b491c0SSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 829b4b491c0SSrinivas Pandruvada int ret; 830b4b491c0SSrinivas Pandruvada 831b4b491c0SSrinivas Pandruvada if (state && data->ev_enable_state) 832b4b491c0SSrinivas Pandruvada return 0; 833b4b491c0SSrinivas Pandruvada 834b4b491c0SSrinivas Pandruvada mutex_lock(&data->mutex); 835b4b491c0SSrinivas Pandruvada 836b4b491c0SSrinivas Pandruvada if (!state && data->motion_trigger_on) { 837b4b491c0SSrinivas Pandruvada data->ev_enable_state = 0; 838b4b491c0SSrinivas Pandruvada mutex_unlock(&data->mutex); 839b4b491c0SSrinivas Pandruvada return 0; 840b4b491c0SSrinivas Pandruvada } 841b4b491c0SSrinivas Pandruvada 842b4b491c0SSrinivas Pandruvada /* 843b4b491c0SSrinivas Pandruvada * We will expect the enable and disable to do operation in 844b4b491c0SSrinivas Pandruvada * in reverse order. This will happen here anyway as our 845b4b491c0SSrinivas Pandruvada * resume operation uses sync mode runtime pm calls, the 846b4b491c0SSrinivas Pandruvada * suspend operation will be delayed by autosuspend delay 847b4b491c0SSrinivas Pandruvada * So the disable operation will still happen in reverse of 848b4b491c0SSrinivas Pandruvada * enable operation. When runtime pm is disabled the mode 849b4b491c0SSrinivas Pandruvada * is always on so sequence doesn't matter 850b4b491c0SSrinivas Pandruvada */ 851b4b491c0SSrinivas Pandruvada ret = kxcjk1013_set_power_state(data, state); 852b4b491c0SSrinivas Pandruvada if (ret < 0) { 853b4b491c0SSrinivas Pandruvada mutex_unlock(&data->mutex); 854b4b491c0SSrinivas Pandruvada return ret; 855b4b491c0SSrinivas Pandruvada } 856b4b491c0SSrinivas Pandruvada 857b4b491c0SSrinivas Pandruvada ret = kxcjk1013_setup_any_motion_interrupt(data, state); 858b4b491c0SSrinivas Pandruvada if (ret < 0) { 859fbd123e9SIrina Tirdea kxcjk1013_set_power_state(data, false); 860fbd123e9SIrina Tirdea data->ev_enable_state = 0; 861b4b491c0SSrinivas Pandruvada mutex_unlock(&data->mutex); 862b4b491c0SSrinivas Pandruvada return ret; 863b4b491c0SSrinivas Pandruvada } 864b4b491c0SSrinivas Pandruvada 865b4b491c0SSrinivas Pandruvada data->ev_enable_state = state; 866b4b491c0SSrinivas Pandruvada mutex_unlock(&data->mutex); 867b4b491c0SSrinivas Pandruvada 868b4b491c0SSrinivas Pandruvada return 0; 869b4b491c0SSrinivas Pandruvada } 870b4b491c0SSrinivas Pandruvada 871a25691c1SVlad Dogaru static int kxcjk1013_buffer_preenable(struct iio_dev *indio_dev) 8721a4fbf6aSSrinivas Pandruvada { 8731a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 8741a4fbf6aSSrinivas Pandruvada 875a25691c1SVlad Dogaru return kxcjk1013_set_power_state(data, true); 876a25691c1SVlad Dogaru } 8771a4fbf6aSSrinivas Pandruvada 878a25691c1SVlad Dogaru static int kxcjk1013_buffer_postdisable(struct iio_dev *indio_dev) 879a25691c1SVlad Dogaru { 880a25691c1SVlad Dogaru struct kxcjk1013_data *data = iio_priv(indio_dev); 881a25691c1SVlad Dogaru 882a25691c1SVlad Dogaru return kxcjk1013_set_power_state(data, false); 8831a4fbf6aSSrinivas Pandruvada } 8841a4fbf6aSSrinivas Pandruvada 885*81fa8cb9SMichał Mirosław static ssize_t kxcjk1013_get_samp_freq_avail(struct device *dev, 886*81fa8cb9SMichał Mirosław struct device_attribute *attr, 887*81fa8cb9SMichał Mirosław char *buf) 888*81fa8cb9SMichał Mirosław { 889*81fa8cb9SMichał Mirosław return sprintf(buf, "%s\n", kxcjk1013_samp_freq_avail); 890*81fa8cb9SMichał Mirosław } 891*81fa8cb9SMichał Mirosław 892*81fa8cb9SMichał Mirosław static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(kxcjk1013_get_samp_freq_avail); 8931a4fbf6aSSrinivas Pandruvada 894a735e3d7SSrinivas Pandruvada static IIO_CONST_ATTR(in_accel_scale_available, "0.009582 0.019163 0.038326"); 895a735e3d7SSrinivas Pandruvada 8961a4fbf6aSSrinivas Pandruvada static struct attribute *kxcjk1013_attributes[] = { 897*81fa8cb9SMichał Mirosław &iio_dev_attr_sampling_frequency_available.dev_attr.attr, 898a735e3d7SSrinivas Pandruvada &iio_const_attr_in_accel_scale_available.dev_attr.attr, 8991a4fbf6aSSrinivas Pandruvada NULL, 9001a4fbf6aSSrinivas Pandruvada }; 9011a4fbf6aSSrinivas Pandruvada 9021a4fbf6aSSrinivas Pandruvada static const struct attribute_group kxcjk1013_attrs_group = { 9031a4fbf6aSSrinivas Pandruvada .attrs = kxcjk1013_attributes, 9041a4fbf6aSSrinivas Pandruvada }; 9051a4fbf6aSSrinivas Pandruvada 906b4b491c0SSrinivas Pandruvada static const struct iio_event_spec kxcjk1013_event = { 907b4b491c0SSrinivas Pandruvada .type = IIO_EV_TYPE_THRESH, 90825afffe1SDaniel Baluta .dir = IIO_EV_DIR_EITHER, 909b4b491c0SSrinivas Pandruvada .mask_separate = BIT(IIO_EV_INFO_VALUE) | 910b4b491c0SSrinivas Pandruvada BIT(IIO_EV_INFO_ENABLE) | 911b4b491c0SSrinivas Pandruvada BIT(IIO_EV_INFO_PERIOD) 912b4b491c0SSrinivas Pandruvada }; 913b4b491c0SSrinivas Pandruvada 9141a4fbf6aSSrinivas Pandruvada #define KXCJK1013_CHANNEL(_axis) { \ 9151a4fbf6aSSrinivas Pandruvada .type = IIO_ACCEL, \ 9161a4fbf6aSSrinivas Pandruvada .modified = 1, \ 9171a4fbf6aSSrinivas Pandruvada .channel2 = IIO_MOD_##_axis, \ 9181a4fbf6aSSrinivas Pandruvada .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 9191a4fbf6aSSrinivas Pandruvada .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 9201a4fbf6aSSrinivas Pandruvada BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 9211a4fbf6aSSrinivas Pandruvada .scan_index = AXIS_##_axis, \ 9221a4fbf6aSSrinivas Pandruvada .scan_type = { \ 9231a4fbf6aSSrinivas Pandruvada .sign = 's', \ 9241a4fbf6aSSrinivas Pandruvada .realbits = 12, \ 9251a4fbf6aSSrinivas Pandruvada .storagebits = 16, \ 9261a4fbf6aSSrinivas Pandruvada .shift = 4, \ 92765ae47b0SAdriana Reus .endianness = IIO_LE, \ 9281a4fbf6aSSrinivas Pandruvada }, \ 929b4b491c0SSrinivas Pandruvada .event_spec = &kxcjk1013_event, \ 930b4b491c0SSrinivas Pandruvada .num_event_specs = 1 \ 9311a4fbf6aSSrinivas Pandruvada } 9321a4fbf6aSSrinivas Pandruvada 9331a4fbf6aSSrinivas Pandruvada static const struct iio_chan_spec kxcjk1013_channels[] = { 9341a4fbf6aSSrinivas Pandruvada KXCJK1013_CHANNEL(X), 9351a4fbf6aSSrinivas Pandruvada KXCJK1013_CHANNEL(Y), 9361a4fbf6aSSrinivas Pandruvada KXCJK1013_CHANNEL(Z), 9371a4fbf6aSSrinivas Pandruvada IIO_CHAN_SOFT_TIMESTAMP(3), 9381a4fbf6aSSrinivas Pandruvada }; 9391a4fbf6aSSrinivas Pandruvada 940a25691c1SVlad Dogaru static const struct iio_buffer_setup_ops kxcjk1013_buffer_setup_ops = { 941a25691c1SVlad Dogaru .preenable = kxcjk1013_buffer_preenable, 942a25691c1SVlad Dogaru .postenable = iio_triggered_buffer_postenable, 943a25691c1SVlad Dogaru .postdisable = kxcjk1013_buffer_postdisable, 944a25691c1SVlad Dogaru .predisable = iio_triggered_buffer_predisable, 945a25691c1SVlad Dogaru }; 946a25691c1SVlad Dogaru 9471a4fbf6aSSrinivas Pandruvada static const struct iio_info kxcjk1013_info = { 9481a4fbf6aSSrinivas Pandruvada .attrs = &kxcjk1013_attrs_group, 9491a4fbf6aSSrinivas Pandruvada .read_raw = kxcjk1013_read_raw, 9501a4fbf6aSSrinivas Pandruvada .write_raw = kxcjk1013_write_raw, 951b4b491c0SSrinivas Pandruvada .read_event_value = kxcjk1013_read_event, 952b4b491c0SSrinivas Pandruvada .write_event_value = kxcjk1013_write_event, 953b4b491c0SSrinivas Pandruvada .write_event_config = kxcjk1013_write_event_config, 954b4b491c0SSrinivas Pandruvada .read_event_config = kxcjk1013_read_event_config, 9551a4fbf6aSSrinivas Pandruvada }; 9561a4fbf6aSSrinivas Pandruvada 95709cf1b32SAdriana Reus static const unsigned long kxcjk1013_scan_masks[] = {0x7, 0}; 95809cf1b32SAdriana Reus 9591a4fbf6aSSrinivas Pandruvada static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p) 9601a4fbf6aSSrinivas Pandruvada { 9611a4fbf6aSSrinivas Pandruvada struct iio_poll_func *pf = p; 9621a4fbf6aSSrinivas Pandruvada struct iio_dev *indio_dev = pf->indio_dev; 9631a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 96465ae47b0SAdriana Reus int ret; 9651a4fbf6aSSrinivas Pandruvada 9661a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 96765ae47b0SAdriana Reus ret = i2c_smbus_read_i2c_block_data_or_emulated(data->client, 96865ae47b0SAdriana Reus KXCJK1013_REG_XOUT_L, 96965ae47b0SAdriana Reus AXIS_MAX * 2, 97065ae47b0SAdriana Reus (u8 *)data->buffer); 9711a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 97265ae47b0SAdriana Reus if (ret < 0) 9731a4fbf6aSSrinivas Pandruvada goto err; 9741a4fbf6aSSrinivas Pandruvada 9751a4fbf6aSSrinivas Pandruvada iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, 976b4b491c0SSrinivas Pandruvada data->timestamp); 9771a4fbf6aSSrinivas Pandruvada err: 9781a4fbf6aSSrinivas Pandruvada iio_trigger_notify_done(indio_dev->trig); 9791a4fbf6aSSrinivas Pandruvada 9801a4fbf6aSSrinivas Pandruvada return IRQ_HANDLED; 9811a4fbf6aSSrinivas Pandruvada } 9821a4fbf6aSSrinivas Pandruvada 98359bfeabaSSrinivas Pandruvada static int kxcjk1013_trig_try_reen(struct iio_trigger *trig) 98459bfeabaSSrinivas Pandruvada { 98559bfeabaSSrinivas Pandruvada struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); 98659bfeabaSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 98759bfeabaSSrinivas Pandruvada int ret; 98859bfeabaSSrinivas Pandruvada 98959bfeabaSSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL); 99059bfeabaSSrinivas Pandruvada if (ret < 0) { 99159bfeabaSSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_rel\n"); 99259bfeabaSSrinivas Pandruvada return ret; 99359bfeabaSSrinivas Pandruvada } 99459bfeabaSSrinivas Pandruvada 99559bfeabaSSrinivas Pandruvada return 0; 99659bfeabaSSrinivas Pandruvada } 99759bfeabaSSrinivas Pandruvada 9981a4fbf6aSSrinivas Pandruvada static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig, 9991a4fbf6aSSrinivas Pandruvada bool state) 10001a4fbf6aSSrinivas Pandruvada { 10011a4fbf6aSSrinivas Pandruvada struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); 10021a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 1003124e1b1dSSrinivas Pandruvada int ret; 1004124e1b1dSSrinivas Pandruvada 10051a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 1006b4b491c0SSrinivas Pandruvada 1007b4b491c0SSrinivas Pandruvada if (!state && data->ev_enable_state && data->motion_trigger_on) { 1008b4b491c0SSrinivas Pandruvada data->motion_trigger_on = false; 1009b4b491c0SSrinivas Pandruvada mutex_unlock(&data->mutex); 1010b4b491c0SSrinivas Pandruvada return 0; 1011b4b491c0SSrinivas Pandruvada } 1012b4b491c0SSrinivas Pandruvada 1013124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_power_state(data, state); 1014124e1b1dSSrinivas Pandruvada if (ret < 0) { 101588f6da77SSrinivas Pandruvada mutex_unlock(&data->mutex); 1016124e1b1dSSrinivas Pandruvada return ret; 101788f6da77SSrinivas Pandruvada } 1018b4b491c0SSrinivas Pandruvada if (data->motion_trig == trig) 1019b4b491c0SSrinivas Pandruvada ret = kxcjk1013_setup_any_motion_interrupt(data, state); 1020b4b491c0SSrinivas Pandruvada else 1021b4b491c0SSrinivas Pandruvada ret = kxcjk1013_setup_new_data_interrupt(data, state); 1022b4b491c0SSrinivas Pandruvada if (ret < 0) { 1023fbd123e9SIrina Tirdea kxcjk1013_set_power_state(data, false); 1024b4b491c0SSrinivas Pandruvada mutex_unlock(&data->mutex); 1025b4b491c0SSrinivas Pandruvada return ret; 10261a4fbf6aSSrinivas Pandruvada } 1027b4b491c0SSrinivas Pandruvada if (data->motion_trig == trig) 1028b4b491c0SSrinivas Pandruvada data->motion_trigger_on = state; 1029b4b491c0SSrinivas Pandruvada else 1030b4b491c0SSrinivas Pandruvada data->dready_trigger_on = state; 1031b4b491c0SSrinivas Pandruvada 10321a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 10331a4fbf6aSSrinivas Pandruvada 10341a4fbf6aSSrinivas Pandruvada return 0; 10351a4fbf6aSSrinivas Pandruvada } 10361a4fbf6aSSrinivas Pandruvada 10371a4fbf6aSSrinivas Pandruvada static const struct iio_trigger_ops kxcjk1013_trigger_ops = { 10381a4fbf6aSSrinivas Pandruvada .set_trigger_state = kxcjk1013_data_rdy_trigger_set_state, 103959bfeabaSSrinivas Pandruvada .try_reenable = kxcjk1013_trig_try_reen, 10401a4fbf6aSSrinivas Pandruvada }; 10411a4fbf6aSSrinivas Pandruvada 1042d8408e98SMichał Mirosław static void kxcjk1013_report_motion_event(struct iio_dev *indio_dev) 1043b4b491c0SSrinivas Pandruvada { 1044b4b491c0SSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 1045b4b491c0SSrinivas Pandruvada 1046d8408e98SMichał Mirosław int ret = i2c_smbus_read_byte_data(data->client, 1047b4b491c0SSrinivas Pandruvada KXCJK1013_REG_INT_SRC2); 1048b4b491c0SSrinivas Pandruvada if (ret < 0) { 1049d8408e98SMichał Mirosław dev_err(&data->client->dev, "Error reading reg_int_src2\n"); 1050d8408e98SMichał Mirosław return; 1051b4b491c0SSrinivas Pandruvada } 1052b4b491c0SSrinivas Pandruvada 1053b4b491c0SSrinivas Pandruvada if (ret & KXCJK1013_REG_INT_SRC2_BIT_XN) 1054b4b491c0SSrinivas Pandruvada iio_push_event(indio_dev, 1055b4b491c0SSrinivas Pandruvada IIO_MOD_EVENT_CODE(IIO_ACCEL, 1056b4b491c0SSrinivas Pandruvada 0, 1057b4b491c0SSrinivas Pandruvada IIO_MOD_X, 1058b4b491c0SSrinivas Pandruvada IIO_EV_TYPE_THRESH, 1059b4b491c0SSrinivas Pandruvada IIO_EV_DIR_FALLING), 1060b4b491c0SSrinivas Pandruvada data->timestamp); 1061d8408e98SMichał Mirosław 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 if (ret & KXCJK1013_REG_INT_SRC2_BIT_YN) 1072b4b491c0SSrinivas Pandruvada iio_push_event(indio_dev, 1073b4b491c0SSrinivas Pandruvada IIO_MOD_EVENT_CODE(IIO_ACCEL, 1074b4b491c0SSrinivas Pandruvada 0, 1075b4b491c0SSrinivas Pandruvada IIO_MOD_Y, 1076b4b491c0SSrinivas Pandruvada IIO_EV_TYPE_THRESH, 1077b4b491c0SSrinivas Pandruvada IIO_EV_DIR_FALLING), 1078b4b491c0SSrinivas Pandruvada data->timestamp); 1079d8408e98SMichał Mirosław 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); 1097d8408e98SMichał Mirosław 1098b4b491c0SSrinivas Pandruvada if (ret & KXCJK1013_REG_INT_SRC2_BIT_ZP) 1099b4b491c0SSrinivas Pandruvada iio_push_event(indio_dev, 1100b4b491c0SSrinivas Pandruvada IIO_MOD_EVENT_CODE(IIO_ACCEL, 1101b4b491c0SSrinivas Pandruvada 0, 1102b4b491c0SSrinivas Pandruvada IIO_MOD_Z, 1103b4b491c0SSrinivas Pandruvada IIO_EV_TYPE_THRESH, 1104b4b491c0SSrinivas Pandruvada IIO_EV_DIR_RISING), 1105b4b491c0SSrinivas Pandruvada data->timestamp); 1106b4b491c0SSrinivas Pandruvada } 1107b4b491c0SSrinivas Pandruvada 1108d8408e98SMichał Mirosław static irqreturn_t kxcjk1013_event_handler(int irq, void *private) 1109d8408e98SMichał Mirosław { 1110d8408e98SMichał Mirosław struct iio_dev *indio_dev = private; 1111d8408e98SMichał Mirosław struct kxcjk1013_data *data = iio_priv(indio_dev); 1112d8408e98SMichał Mirosław int ret; 1113d8408e98SMichał Mirosław 1114d8408e98SMichał Mirosław ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_SRC1); 1115d8408e98SMichał Mirosław if (ret < 0) { 1116d8408e98SMichał Mirosław dev_err(&data->client->dev, "Error reading reg_int_src1\n"); 1117d8408e98SMichał Mirosław goto ack_intr; 1118d8408e98SMichał Mirosław } 1119d8408e98SMichał Mirosław 1120d8408e98SMichał Mirosław if (ret & KXCJK1013_REG_INT_SRC1_BIT_WUFS) { 1121d8408e98SMichał Mirosław kxcjk1013_report_motion_event(indio_dev); 1122d8408e98SMichał Mirosław } 1123d8408e98SMichał Mirosław 1124b4b491c0SSrinivas Pandruvada ack_intr: 1125b4b491c0SSrinivas Pandruvada if (data->dready_trigger_on) 1126b4b491c0SSrinivas Pandruvada return IRQ_HANDLED; 1127b4b491c0SSrinivas Pandruvada 1128b4b491c0SSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL); 1129b4b491c0SSrinivas Pandruvada if (ret < 0) 1130b4b491c0SSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_rel\n"); 1131b4b491c0SSrinivas Pandruvada 1132b4b491c0SSrinivas Pandruvada return IRQ_HANDLED; 1133b4b491c0SSrinivas Pandruvada } 1134b4b491c0SSrinivas Pandruvada 1135b4b491c0SSrinivas Pandruvada static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private) 1136b4b491c0SSrinivas Pandruvada { 1137b4b491c0SSrinivas Pandruvada struct iio_dev *indio_dev = private; 1138b4b491c0SSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 1139b4b491c0SSrinivas Pandruvada 1140bc2b7dabSGregor Boirie data->timestamp = iio_get_time_ns(indio_dev); 1141b4b491c0SSrinivas Pandruvada 1142b4b491c0SSrinivas Pandruvada if (data->dready_trigger_on) 1143b4b491c0SSrinivas Pandruvada iio_trigger_poll(data->dready_trig); 1144b4b491c0SSrinivas Pandruvada else if (data->motion_trigger_on) 1145b4b491c0SSrinivas Pandruvada iio_trigger_poll(data->motion_trig); 1146b4b491c0SSrinivas Pandruvada 1147b4b491c0SSrinivas Pandruvada if (data->ev_enable_state) 1148b4b491c0SSrinivas Pandruvada return IRQ_WAKE_THREAD; 1149b4b491c0SSrinivas Pandruvada else 1150b4b491c0SSrinivas Pandruvada return IRQ_HANDLED; 1151b4b491c0SSrinivas Pandruvada } 1152b4b491c0SSrinivas Pandruvada 1153c6861377SDaniel Baluta static const char *kxcjk1013_match_acpi_device(struct device *dev, 11543bfa74f8SBastien Nocera enum kx_chipset *chipset, 11553bfa74f8SBastien Nocera bool *is_smo8500_device) 11561a4fbf6aSSrinivas Pandruvada { 11571a4fbf6aSSrinivas Pandruvada const struct acpi_device_id *id; 1158b0868df4SRoberta Dobrescu 1159c6861377SDaniel Baluta id = acpi_match_device(dev->driver->acpi_match_table, dev); 1160c6861377SDaniel Baluta if (!id) 1161c6861377SDaniel Baluta return NULL; 1162e693e15eSAntonio Ospite 11633bfa74f8SBastien Nocera if (strcmp(id->id, "SMO8500") == 0) 11643bfa74f8SBastien Nocera *is_smo8500_device = true; 1165e693e15eSAntonio Ospite 1166c6861377SDaniel Baluta *chipset = (enum kx_chipset)id->driver_data; 1167c6861377SDaniel Baluta 1168c6861377SDaniel Baluta return dev_name(dev); 1169c6861377SDaniel Baluta } 1170c6861377SDaniel Baluta 11711a4fbf6aSSrinivas Pandruvada static int kxcjk1013_probe(struct i2c_client *client, 11721a4fbf6aSSrinivas Pandruvada const struct i2c_device_id *id) 11731a4fbf6aSSrinivas Pandruvada { 11741a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data; 11751a4fbf6aSSrinivas Pandruvada struct iio_dev *indio_dev; 11761a4fbf6aSSrinivas Pandruvada struct kxcjk_1013_platform_data *pdata; 1177c6861377SDaniel Baluta const char *name; 11781a4fbf6aSSrinivas Pandruvada int ret; 11791a4fbf6aSSrinivas Pandruvada 11801a4fbf6aSSrinivas Pandruvada indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 11811a4fbf6aSSrinivas Pandruvada if (!indio_dev) 11821a4fbf6aSSrinivas Pandruvada return -ENOMEM; 11831a4fbf6aSSrinivas Pandruvada 11841a4fbf6aSSrinivas Pandruvada data = iio_priv(indio_dev); 11851a4fbf6aSSrinivas Pandruvada i2c_set_clientdata(client, indio_dev); 11861a4fbf6aSSrinivas Pandruvada data->client = client; 11871a4fbf6aSSrinivas Pandruvada 11881a4fbf6aSSrinivas Pandruvada pdata = dev_get_platdata(&client->dev); 11891a4fbf6aSSrinivas Pandruvada if (pdata) 11901a4fbf6aSSrinivas Pandruvada data->active_high_intr = pdata->active_high_intr; 11911a4fbf6aSSrinivas Pandruvada else 11921a4fbf6aSSrinivas Pandruvada data->active_high_intr = true; /* default polarity */ 11931a4fbf6aSSrinivas Pandruvada 1194c6861377SDaniel Baluta if (id) { 1195c6861377SDaniel Baluta data->chipset = (enum kx_chipset)(id->driver_data); 1196c6861377SDaniel Baluta name = id->name; 1197c6861377SDaniel Baluta } else if (ACPI_HANDLE(&client->dev)) { 1198c6861377SDaniel Baluta name = kxcjk1013_match_acpi_device(&client->dev, 11993bfa74f8SBastien Nocera &data->chipset, 12003bfa74f8SBastien Nocera &data->is_smo8500_device); 1201c6861377SDaniel Baluta } else 1202c6861377SDaniel Baluta return -ENODEV; 1203c6861377SDaniel Baluta 12041a4fbf6aSSrinivas Pandruvada ret = kxcjk1013_chip_init(data); 12051a4fbf6aSSrinivas Pandruvada if (ret < 0) 12061a4fbf6aSSrinivas Pandruvada return ret; 12071a4fbf6aSSrinivas Pandruvada 12081a4fbf6aSSrinivas Pandruvada mutex_init(&data->mutex); 12091a4fbf6aSSrinivas Pandruvada 12101a4fbf6aSSrinivas Pandruvada indio_dev->dev.parent = &client->dev; 12111a4fbf6aSSrinivas Pandruvada indio_dev->channels = kxcjk1013_channels; 12121a4fbf6aSSrinivas Pandruvada indio_dev->num_channels = ARRAY_SIZE(kxcjk1013_channels); 121309cf1b32SAdriana Reus indio_dev->available_scan_masks = kxcjk1013_scan_masks; 1214c6861377SDaniel Baluta indio_dev->name = name; 12151a4fbf6aSSrinivas Pandruvada indio_dev->modes = INDIO_DIRECT_MODE; 12161a4fbf6aSSrinivas Pandruvada indio_dev->info = &kxcjk1013_info; 12171a4fbf6aSSrinivas Pandruvada 12180f079650SOctavian Purdila if (client->irq > 0 && !data->is_smo8500_device) { 1219b4b491c0SSrinivas Pandruvada ret = devm_request_threaded_irq(&client->dev, client->irq, 1220b4b491c0SSrinivas Pandruvada kxcjk1013_data_rdy_trig_poll, 1221b4b491c0SSrinivas Pandruvada kxcjk1013_event_handler, 12221a4fbf6aSSrinivas Pandruvada IRQF_TRIGGER_RISING, 12231a4fbf6aSSrinivas Pandruvada KXCJK1013_IRQ_NAME, 1224b4b491c0SSrinivas Pandruvada indio_dev); 12251a4fbf6aSSrinivas Pandruvada if (ret) 12269d02daf7SIrina Tirdea goto err_poweroff; 1227b4b491c0SSrinivas Pandruvada 1228b4b491c0SSrinivas Pandruvada data->dready_trig = devm_iio_trigger_alloc(&client->dev, 1229b4b491c0SSrinivas Pandruvada "%s-dev%d", 1230b4b491c0SSrinivas Pandruvada indio_dev->name, 1231b4b491c0SSrinivas Pandruvada indio_dev->id); 12329d02daf7SIrina Tirdea if (!data->dready_trig) { 12339d02daf7SIrina Tirdea ret = -ENOMEM; 12349d02daf7SIrina Tirdea goto err_poweroff; 12359d02daf7SIrina Tirdea } 1236b4b491c0SSrinivas Pandruvada 1237b4b491c0SSrinivas Pandruvada data->motion_trig = devm_iio_trigger_alloc(&client->dev, 1238b4b491c0SSrinivas Pandruvada "%s-any-motion-dev%d", 1239b4b491c0SSrinivas Pandruvada indio_dev->name, 1240b4b491c0SSrinivas Pandruvada indio_dev->id); 12419d02daf7SIrina Tirdea if (!data->motion_trig) { 12429d02daf7SIrina Tirdea ret = -ENOMEM; 12439d02daf7SIrina Tirdea goto err_poweroff; 12449d02daf7SIrina Tirdea } 1245b4b491c0SSrinivas Pandruvada 1246b4b491c0SSrinivas Pandruvada data->dready_trig->dev.parent = &client->dev; 1247b4b491c0SSrinivas Pandruvada data->dready_trig->ops = &kxcjk1013_trigger_ops; 1248b4b491c0SSrinivas Pandruvada iio_trigger_set_drvdata(data->dready_trig, indio_dev); 1249b4b491c0SSrinivas Pandruvada indio_dev->trig = data->dready_trig; 1250b4b491c0SSrinivas Pandruvada iio_trigger_get(indio_dev->trig); 1251b4b491c0SSrinivas Pandruvada ret = iio_trigger_register(data->dready_trig); 1252b4b491c0SSrinivas Pandruvada if (ret) 12539d02daf7SIrina Tirdea goto err_poweroff; 1254b4b491c0SSrinivas Pandruvada 1255b4b491c0SSrinivas Pandruvada data->motion_trig->dev.parent = &client->dev; 1256b4b491c0SSrinivas Pandruvada data->motion_trig->ops = &kxcjk1013_trigger_ops; 1257b4b491c0SSrinivas Pandruvada iio_trigger_set_drvdata(data->motion_trig, indio_dev); 1258b4b491c0SSrinivas Pandruvada ret = iio_trigger_register(data->motion_trig); 1259b4b491c0SSrinivas Pandruvada if (ret) { 1260b4b491c0SSrinivas Pandruvada data->motion_trig = NULL; 1261b4b491c0SSrinivas Pandruvada goto err_trigger_unregister; 1262b4b491c0SSrinivas Pandruvada } 1263a25691c1SVlad Dogaru } 12641a4fbf6aSSrinivas Pandruvada 12651a4fbf6aSSrinivas Pandruvada ret = iio_triggered_buffer_setup(indio_dev, 12661a4fbf6aSSrinivas Pandruvada &iio_pollfunc_store_time, 12671a4fbf6aSSrinivas Pandruvada kxcjk1013_trigger_handler, 1268a25691c1SVlad Dogaru &kxcjk1013_buffer_setup_ops); 12691a4fbf6aSSrinivas Pandruvada if (ret < 0) { 1270a25691c1SVlad Dogaru dev_err(&client->dev, "iio triggered buffer setup failed\n"); 12711a4fbf6aSSrinivas Pandruvada goto err_trigger_unregister; 12721a4fbf6aSSrinivas Pandruvada } 12731a4fbf6aSSrinivas Pandruvada 1274124e1b1dSSrinivas Pandruvada ret = pm_runtime_set_active(&client->dev); 1275124e1b1dSSrinivas Pandruvada if (ret) 12767d0ead5cSAdriana Reus goto err_buffer_cleanup; 1277124e1b1dSSrinivas Pandruvada 1278124e1b1dSSrinivas Pandruvada pm_runtime_enable(&client->dev); 1279124e1b1dSSrinivas Pandruvada pm_runtime_set_autosuspend_delay(&client->dev, 1280124e1b1dSSrinivas Pandruvada KXCJK1013_SLEEP_DELAY_MS); 1281124e1b1dSSrinivas Pandruvada pm_runtime_use_autosuspend(&client->dev); 1282124e1b1dSSrinivas Pandruvada 12837d0ead5cSAdriana Reus ret = iio_device_register(indio_dev); 12847d0ead5cSAdriana Reus if (ret < 0) { 12857d0ead5cSAdriana Reus dev_err(&client->dev, "unable to register iio device\n"); 12867d0ead5cSAdriana Reus goto err_buffer_cleanup; 12877d0ead5cSAdriana Reus } 12887d0ead5cSAdriana Reus 12891a4fbf6aSSrinivas Pandruvada return 0; 12901a4fbf6aSSrinivas Pandruvada 12911a4fbf6aSSrinivas Pandruvada err_buffer_cleanup: 1292b4b491c0SSrinivas Pandruvada if (data->dready_trig) 12931a4fbf6aSSrinivas Pandruvada iio_triggered_buffer_cleanup(indio_dev); 12941a4fbf6aSSrinivas Pandruvada err_trigger_unregister: 1295b4b491c0SSrinivas Pandruvada if (data->dready_trig) 1296b4b491c0SSrinivas Pandruvada iio_trigger_unregister(data->dready_trig); 1297b4b491c0SSrinivas Pandruvada if (data->motion_trig) 1298b4b491c0SSrinivas Pandruvada iio_trigger_unregister(data->motion_trig); 12999d02daf7SIrina Tirdea err_poweroff: 13009d02daf7SIrina Tirdea kxcjk1013_set_mode(data, STANDBY); 13011a4fbf6aSSrinivas Pandruvada 13021a4fbf6aSSrinivas Pandruvada return ret; 13031a4fbf6aSSrinivas Pandruvada } 13041a4fbf6aSSrinivas Pandruvada 13051a4fbf6aSSrinivas Pandruvada static int kxcjk1013_remove(struct i2c_client *client) 13061a4fbf6aSSrinivas Pandruvada { 13071a4fbf6aSSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(client); 13081a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 13091a4fbf6aSSrinivas Pandruvada 13107d0ead5cSAdriana Reus iio_device_unregister(indio_dev); 13117d0ead5cSAdriana Reus 1312124e1b1dSSrinivas Pandruvada pm_runtime_disable(&client->dev); 1313124e1b1dSSrinivas Pandruvada pm_runtime_set_suspended(&client->dev); 1314124e1b1dSSrinivas Pandruvada pm_runtime_put_noidle(&client->dev); 1315124e1b1dSSrinivas Pandruvada 1316b4b491c0SSrinivas Pandruvada if (data->dready_trig) { 13171a4fbf6aSSrinivas Pandruvada iio_triggered_buffer_cleanup(indio_dev); 1318b4b491c0SSrinivas Pandruvada iio_trigger_unregister(data->dready_trig); 1319b4b491c0SSrinivas Pandruvada iio_trigger_unregister(data->motion_trig); 13201a4fbf6aSSrinivas Pandruvada } 13211a4fbf6aSSrinivas Pandruvada 13221a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 13231a4fbf6aSSrinivas Pandruvada kxcjk1013_set_mode(data, STANDBY); 13241a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 13251a4fbf6aSSrinivas Pandruvada 13261a4fbf6aSSrinivas Pandruvada return 0; 13271a4fbf6aSSrinivas Pandruvada } 13281a4fbf6aSSrinivas Pandruvada 13291a4fbf6aSSrinivas Pandruvada #ifdef CONFIG_PM_SLEEP 13301a4fbf6aSSrinivas Pandruvada static int kxcjk1013_suspend(struct device *dev) 13311a4fbf6aSSrinivas Pandruvada { 13321a4fbf6aSSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 13331a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 1334124e1b1dSSrinivas Pandruvada int ret; 13351a4fbf6aSSrinivas Pandruvada 13361a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 1337124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, STANDBY); 13381a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 13391a4fbf6aSSrinivas Pandruvada 1340124e1b1dSSrinivas Pandruvada return ret; 13411a4fbf6aSSrinivas Pandruvada } 13421a4fbf6aSSrinivas Pandruvada 13431a4fbf6aSSrinivas Pandruvada static int kxcjk1013_resume(struct device *dev) 13441a4fbf6aSSrinivas Pandruvada { 13451a4fbf6aSSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 13461a4fbf6aSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 1347124e1b1dSSrinivas Pandruvada int ret = 0; 13481a4fbf6aSSrinivas Pandruvada 13491a4fbf6aSSrinivas Pandruvada mutex_lock(&data->mutex); 1350124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, OPERATION); 13511a4fbf6aSSrinivas Pandruvada mutex_unlock(&data->mutex); 13521a4fbf6aSSrinivas Pandruvada 1353124e1b1dSSrinivas Pandruvada return ret; 1354124e1b1dSSrinivas Pandruvada } 1355124e1b1dSSrinivas Pandruvada #endif 1356124e1b1dSSrinivas Pandruvada 13576f0a13f2SRafael J. Wysocki #ifdef CONFIG_PM 1358124e1b1dSSrinivas Pandruvada static int kxcjk1013_runtime_suspend(struct device *dev) 1359124e1b1dSSrinivas Pandruvada { 1360124e1b1dSSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 1361124e1b1dSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 1362fbd123e9SIrina Tirdea int ret; 1363124e1b1dSSrinivas Pandruvada 1364fbd123e9SIrina Tirdea ret = kxcjk1013_set_mode(data, STANDBY); 1365fbd123e9SIrina Tirdea if (ret < 0) { 1366fbd123e9SIrina Tirdea dev_err(&data->client->dev, "powering off device failed\n"); 1367fbd123e9SIrina Tirdea return -EAGAIN; 1368fbd123e9SIrina Tirdea } 1369fbd123e9SIrina Tirdea return 0; 1370124e1b1dSSrinivas Pandruvada } 1371124e1b1dSSrinivas Pandruvada 1372124e1b1dSSrinivas Pandruvada static int kxcjk1013_runtime_resume(struct device *dev) 1373124e1b1dSSrinivas Pandruvada { 1374124e1b1dSSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 1375124e1b1dSSrinivas Pandruvada struct kxcjk1013_data *data = iio_priv(indio_dev); 1376124e1b1dSSrinivas Pandruvada int ret; 1377124e1b1dSSrinivas Pandruvada int sleep_val; 1378124e1b1dSSrinivas Pandruvada 1379124e1b1dSSrinivas Pandruvada ret = kxcjk1013_set_mode(data, OPERATION); 1380124e1b1dSSrinivas Pandruvada if (ret < 0) 1381124e1b1dSSrinivas Pandruvada return ret; 1382124e1b1dSSrinivas Pandruvada 1383124e1b1dSSrinivas Pandruvada sleep_val = kxcjk1013_get_startup_times(data); 1384124e1b1dSSrinivas Pandruvada if (sleep_val < 20000) 1385124e1b1dSSrinivas Pandruvada usleep_range(sleep_val, 20000); 1386124e1b1dSSrinivas Pandruvada else 1387124e1b1dSSrinivas Pandruvada msleep_interruptible(sleep_val/1000); 1388124e1b1dSSrinivas Pandruvada 13891a4fbf6aSSrinivas Pandruvada return 0; 13901a4fbf6aSSrinivas Pandruvada } 13911a4fbf6aSSrinivas Pandruvada #endif 13921a4fbf6aSSrinivas Pandruvada 1393124e1b1dSSrinivas Pandruvada static const struct dev_pm_ops kxcjk1013_pm_ops = { 1394124e1b1dSSrinivas Pandruvada SET_SYSTEM_SLEEP_PM_OPS(kxcjk1013_suspend, kxcjk1013_resume) 1395124e1b1dSSrinivas Pandruvada SET_RUNTIME_PM_OPS(kxcjk1013_runtime_suspend, 1396124e1b1dSSrinivas Pandruvada kxcjk1013_runtime_resume, NULL) 1397124e1b1dSSrinivas Pandruvada }; 1398124e1b1dSSrinivas Pandruvada 13991a4fbf6aSSrinivas Pandruvada static const struct acpi_device_id kx_acpi_match[] = { 1400c6861377SDaniel Baluta {"KXCJ1013", KXCJK1013}, 1401c6861377SDaniel Baluta {"KXCJ1008", KXCJ91008}, 140261e2c70dSAntonio Ospite {"KXCJ9000", KXCJ91008}, 14034d19c487SChristophe Chapuis {"KIOX000A", KXCJ91008}, 1404c6861377SDaniel Baluta {"KXTJ1009", KXTJ21009}, 14053bfa74f8SBastien Nocera {"SMO8500", KXCJ91008}, 14061a4fbf6aSSrinivas Pandruvada { }, 14071a4fbf6aSSrinivas Pandruvada }; 14081a4fbf6aSSrinivas Pandruvada MODULE_DEVICE_TABLE(acpi, kx_acpi_match); 14091a4fbf6aSSrinivas Pandruvada 14101a4fbf6aSSrinivas Pandruvada static const struct i2c_device_id kxcjk1013_id[] = { 1411c6861377SDaniel Baluta {"kxcjk1013", KXCJK1013}, 1412c6861377SDaniel Baluta {"kxcj91008", KXCJ91008}, 1413c6861377SDaniel Baluta {"kxtj21009", KXTJ21009}, 14143bfa74f8SBastien Nocera {"SMO8500", KXCJ91008}, 14151a4fbf6aSSrinivas Pandruvada {} 14161a4fbf6aSSrinivas Pandruvada }; 14171a4fbf6aSSrinivas Pandruvada 14181a4fbf6aSSrinivas Pandruvada MODULE_DEVICE_TABLE(i2c, kxcjk1013_id); 14191a4fbf6aSSrinivas Pandruvada 14201a4fbf6aSSrinivas Pandruvada static struct i2c_driver kxcjk1013_driver = { 14211a4fbf6aSSrinivas Pandruvada .driver = { 14221a4fbf6aSSrinivas Pandruvada .name = KXCJK1013_DRV_NAME, 14231a4fbf6aSSrinivas Pandruvada .acpi_match_table = ACPI_PTR(kx_acpi_match), 1424124e1b1dSSrinivas Pandruvada .pm = &kxcjk1013_pm_ops, 14251a4fbf6aSSrinivas Pandruvada }, 14261a4fbf6aSSrinivas Pandruvada .probe = kxcjk1013_probe, 14271a4fbf6aSSrinivas Pandruvada .remove = kxcjk1013_remove, 14281a4fbf6aSSrinivas Pandruvada .id_table = kxcjk1013_id, 14291a4fbf6aSSrinivas Pandruvada }; 14301a4fbf6aSSrinivas Pandruvada module_i2c_driver(kxcjk1013_driver); 14311a4fbf6aSSrinivas Pandruvada 14321a4fbf6aSSrinivas Pandruvada MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 14331a4fbf6aSSrinivas Pandruvada MODULE_LICENSE("GPL v2"); 14341a4fbf6aSSrinivas Pandruvada MODULE_DESCRIPTION("KXCJK1013 accelerometer driver"); 1435