122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada/* 222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * BMG160 Gyro Sensor driver 322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * Copyright (c) 2014, Intel Corporation. 422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * 522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * This program is free software; you can redistribute it and/or modify it 622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * under the terms and conditions of the GNU General Public License, 722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * version 2, as published by the Free Software Foundation. 822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * 922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * This program is distributed in the hope it will be useful, but WITHOUT 1022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * more details. 1322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada */ 1422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 1522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/module.h> 1622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/i2c.h> 1722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/interrupt.h> 1822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/delay.h> 1922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/slab.h> 2022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/acpi.h> 2122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/gpio/consumer.h> 2222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/pm.h> 2322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/pm_runtime.h> 2422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/iio/iio.h> 2522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/iio/sysfs.h> 2622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/iio/buffer.h> 2722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/iio/trigger.h> 2822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/iio/events.h> 2922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/iio/trigger_consumer.h> 3022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#include <linux/iio/triggered_buffer.h> 3122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 3222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_DRV_NAME "bmg160" 3322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_IRQ_NAME "bmg160_event" 3422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_GPIO_NAME "gpio_int" 3522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 3622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_REG_CHIP_ID 0x00 3722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_CHIP_ID_VAL 0x0F 3822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 3922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_REG_PMU_LPW 0x11 4022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_MODE_NORMAL 0x00 4122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_MODE_DEEP_SUSPEND 0x20 4222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_MODE_SUSPEND 0x80 4322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 4422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_REG_RANGE 0x0F 4522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 4622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_RANGE_2000DPS 0 4722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_RANGE_1000DPS 1 4822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_RANGE_500DPS 2 4922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_RANGE_250DPS 3 5022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_RANGE_125DPS 4 5122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 5222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_REG_PMU_BW 0x10 5322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_NO_FILTER 0 5422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_DEF_BW 100 5522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 5622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_REG_INT_MAP_0 0x17 5722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_INT_MAP_0_BIT_ANY BIT(1) 5822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 5922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_REG_INT_MAP_1 0x18 6022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_INT_MAP_1_BIT_NEW_DATA BIT(0) 6122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 6222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_REG_INT_RST_LATCH 0x21 6322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_INT_MODE_LATCH_RESET 0x80 6422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_INT_MODE_LATCH_INT 0x0F 6522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_INT_MODE_NON_LATCH_INT 0x00 6622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 6722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_REG_INT_EN_0 0x15 6822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_DATA_ENABLE_INT BIT(7) 6922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 705af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada#define BMG160_REG_INT_EN_1 0x16 715af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada#define BMG160_INT1_BIT_OD BIT(1) 725af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada 7322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_REG_XOUT_L 0x02 7422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_AXIS_TO_REG(axis) (BMG160_REG_XOUT_L + (axis * 2)) 7522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 7622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_REG_SLOPE_THRES 0x1B 7722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_SLOPE_THRES_MASK 0x0F 7822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 7922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_REG_MOTION_INTR 0x1C 8022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_INT_MOTION_X BIT(0) 8122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_INT_MOTION_Y BIT(1) 8222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_INT_MOTION_Z BIT(2) 8322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_ANY_DUR_MASK 0x30 8422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_ANY_DUR_SHIFT 4 8522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 8622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_REG_INT_STATUS_2 0x0B 8722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_ANY_MOTION_MASK 0x07 88cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada#define BMG160_ANY_MOTION_BIT_X BIT(0) 89cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada#define BMG160_ANY_MOTION_BIT_Y BIT(1) 90cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada#define BMG160_ANY_MOTION_BIT_Z BIT(2) 9122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 9222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_REG_TEMP 0x08 9322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_TEMP_CENTER_VAL 23 9422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 9522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_MAX_STARTUP_TIME_MS 80 9622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 9722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_AUTO_SUSPEND_DELAY_MS 2000 9822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 9922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastruct bmg160_data { 10022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct i2c_client *client; 10122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_trigger *dready_trig; 10222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_trigger *motion_trig; 10322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct mutex mutex; 10422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada s16 buffer[8]; 10522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada u8 bw_bits; 10622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada u32 dps_range; 10722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ev_enable_state; 10822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int slope_thres; 10922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bool dready_trigger_on; 11022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bool motion_trigger_on; 11122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int64_t timestamp; 11222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada}; 11322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 11422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadaenum bmg160_axis { 11522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada AXIS_X, 11622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada AXIS_Y, 11722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada AXIS_Z, 11822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada}; 11922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 12022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic const struct { 12122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int val; 12222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int bw_bits; 12322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} bmg160_samp_freq_table[] = { {100, 0x07}, 12422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada {200, 0x06}, 12522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada {400, 0x03}, 12622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada {1000, 0x02}, 12722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada {2000, 0x01} }; 12822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 12922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic const struct { 13022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int scale; 13122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int dps_range; 13222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} bmg160_scale_table[] = { { 1065, BMG160_RANGE_2000DPS}, 13322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada { 532, BMG160_RANGE_1000DPS}, 13422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada { 266, BMG160_RANGE_500DPS}, 13522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada { 133, BMG160_RANGE_250DPS}, 13622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada { 66, BMG160_RANGE_125DPS} }; 13722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 13822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_set_mode(struct bmg160_data *data, u8 mode) 13922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 14022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 14122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 14222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 14322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_PMU_LPW, mode); 14422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 14522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_pmu_lpw\n"); 14622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 14722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 14822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 14922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 15022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 15122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 15222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_convert_freq_to_bit(int val) 15322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 15422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int i; 15522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 15622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada for (i = 0; i < ARRAY_SIZE(bmg160_samp_freq_table); ++i) { 15722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (bmg160_samp_freq_table[i].val == val) 15822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return bmg160_samp_freq_table[i].bw_bits; 15922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 16022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 16122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 16222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 16322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 16422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_set_bw(struct bmg160_data *data, int val) 16522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 16622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 16722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int bw_bits; 16822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 16922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bw_bits = bmg160_convert_freq_to_bit(val); 17022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (bw_bits < 0) 17122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return bw_bits; 17222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 17322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, BMG160_REG_PMU_BW, 17422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bw_bits); 17522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 17622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_pmu_bw\n"); 17722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 17822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 17922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 18022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->bw_bits = bw_bits; 18122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 18222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 18322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 18422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 18522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_chip_init(struct bmg160_data *data) 18622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 18722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 18822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 18922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_CHIP_ID); 19022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 19122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_chip_id\n"); 19222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 19322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 19422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 19522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_dbg(&data->client->dev, "Chip Id %x\n", ret); 19622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret != BMG160_CHIP_ID_VAL) { 19722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "invalid chip %x\n", ret); 19822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -ENODEV; 19922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 20022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 20122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_mode(data, BMG160_MODE_NORMAL); 20222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) 20322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 20422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 20522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* Wait upto 500 ms to be ready after changing mode */ 20622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada usleep_range(500, 1000); 20722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 20822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* Set Bandwidth */ 20922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_bw(data, BMG160_DEF_BW); 21022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) 21122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 21222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 21322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* Set Default Range */ 21422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 21522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_RANGE, 21622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_RANGE_500DPS); 21722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 21822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_range\n"); 21922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 22022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 22122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->dps_range = BMG160_RANGE_500DPS; 22222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 22322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_SLOPE_THRES); 22422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 22522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_slope_thres\n"); 22622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 22722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 22822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->slope_thres = ret; 22922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 23022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* Set default interrupt mode */ 2315af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_INT_EN_1); 2325af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada if (ret < 0) { 2335af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_en_1\n"); 2345af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada return ret; 2355af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada } 2365af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada ret &= ~BMG160_INT1_BIT_OD; 2375af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 2385af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada BMG160_REG_INT_EN_1, ret); 2395af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada if (ret < 0) { 2405af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_int_en_1\n"); 2415af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada return ret; 2425af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada } 2435af6b30788d4f745e62e5cb53850f80222571d3aSrinivas Pandruvada 24422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 24522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_INT_RST_LATCH, 24622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MODE_LATCH_INT | 24722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MODE_LATCH_RESET); 24822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 24922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, 25022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada "Error writing reg_motion_intr\n"); 25122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 25222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 25322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 25422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 25522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 25622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 25722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_set_power_state(struct bmg160_data *data, bool on) 25822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 259ef1c6b23355b70356ca18c0d4c39b25dfbd7be02Irina Tirdea#ifdef CONFIG_PM_RUNTIME 26022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 26122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 26222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (on) 26322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = pm_runtime_get_sync(&data->client->dev); 26422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada else { 26522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada pm_runtime_mark_last_busy(&data->client->dev); 26622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = pm_runtime_put_autosuspend(&data->client->dev); 26722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 26822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 26922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 27022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, 27122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada "Failed: bmg160_set_power_state for %d\n", on); 27210bef28973071266e85fe7ea50e08ce8f46dc1caSrinivas Pandruvada if (on) 27310bef28973071266e85fe7ea50e08ce8f46dc1caSrinivas Pandruvada pm_runtime_put_noidle(&data->client->dev); 27410bef28973071266e85fe7ea50e08ce8f46dc1caSrinivas Pandruvada 27522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 27622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 277ef1c6b23355b70356ca18c0d4c39b25dfbd7be02Irina Tirdea#endif 27822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 27922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 28022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 28122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 28222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_setup_any_motion_interrupt(struct bmg160_data *data, 28322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bool status) 28422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 28522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 28622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 28722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* Enable/Disable INT_MAP0 mapping */ 28822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_INT_MAP_0); 28922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 29022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_map0\n"); 29122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 29222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 29322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (status) 29422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret |= BMG160_INT_MAP_0_BIT_ANY; 29522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada else 29622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret &= ~BMG160_INT_MAP_0_BIT_ANY; 29722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 29822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 29922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_INT_MAP_0, 30022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret); 30122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 30222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_int_map0\n"); 30322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 30422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 30522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 30622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* Enable/Disable slope interrupts */ 30722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (status) { 30822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* Update slope thres */ 30922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 31022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_SLOPE_THRES, 31122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->slope_thres); 31222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 31322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, 31422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada "Error writing reg_slope_thres\n"); 31522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 31622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 31722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 31822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 31922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_MOTION_INTR, 32022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MOTION_X | 32122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MOTION_Y | 32222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MOTION_Z); 32322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 32422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, 32522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada "Error writing reg_motion_intr\n"); 32622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 32722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 32822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 32922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* 33022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * New data interrupt is always non-latched, 33122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * which will have higher priority, so no need 33222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * to set latched mode, we will be flooded anyway with INTR 33322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada */ 33422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (!data->dready_trigger_on) { 33522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 33622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_INT_RST_LATCH, 33722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MODE_LATCH_INT | 33822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MODE_LATCH_RESET); 33922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 34022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, 34122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada "Error writing reg_rst_latch\n"); 34222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 34322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 34422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 34522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 34622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 34722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_INT_EN_0, 34822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_DATA_ENABLE_INT); 34922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 35022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } else 35122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 35222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_INT_EN_0, 35322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 0); 35422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 35522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 35622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_int_en0\n"); 35722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 35822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 35922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 36022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 36122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 36222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 36322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_setup_new_data_interrupt(struct bmg160_data *data, 36422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bool status) 36522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 36622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 36722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 36822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* Enable/Disable INT_MAP1 mapping */ 36922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_INT_MAP_1); 37022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 37122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_map1\n"); 37222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 37322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 37422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 37522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (status) 37622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret |= BMG160_INT_MAP_1_BIT_NEW_DATA; 37722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada else 37822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret &= ~BMG160_INT_MAP_1_BIT_NEW_DATA; 37922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 38022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 38122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_INT_MAP_1, 38222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret); 38322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 38422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_int_map1\n"); 38522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 38622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 38722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 38822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (status) { 38922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 39022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_INT_RST_LATCH, 39122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MODE_NON_LATCH_INT | 39222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MODE_LATCH_RESET); 39322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 39422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, 39522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada "Error writing reg_rst_latch\n"); 39622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 39722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 39822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 39922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 40022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_INT_EN_0, 40122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_DATA_ENABLE_INT); 40222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 40322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } else { 40422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* Restore interrupt mode */ 40522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 40622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_INT_RST_LATCH, 40722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MODE_LATCH_INT | 40822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MODE_LATCH_RESET); 40922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 41022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, 41122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada "Error writing reg_rst_latch\n"); 41222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 41322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 41422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 41522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 41622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_INT_EN_0, 41722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 0); 41822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 41922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 42022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 42122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_int_en0\n"); 42222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 42322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 42422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 42522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 42622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 42722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 42822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_get_bw(struct bmg160_data *data, int *val) 42922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 43022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int i; 43122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 43222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada for (i = 0; i < ARRAY_SIZE(bmg160_samp_freq_table); ++i) { 43322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (bmg160_samp_freq_table[i].bw_bits == data->bw_bits) { 43422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada *val = bmg160_samp_freq_table[i].val; 43522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return IIO_VAL_INT; 43622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 43722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 43822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 43922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 44022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 44122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 44222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_set_scale(struct bmg160_data *data, int val) 44322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 44422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret, i; 44522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 44622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada for (i = 0; i < ARRAY_SIZE(bmg160_scale_table); ++i) { 44722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (bmg160_scale_table[i].scale == val) { 44822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data( 44922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->client, 45022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_RANGE, 45122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bmg160_scale_table[i].dps_range); 45222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 45322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, 45422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada "Error writing reg_range\n"); 45522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 45622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 45722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->dps_range = bmg160_scale_table[i].dps_range; 45822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 45922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 46022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 46122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 46222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 46322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 46422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 46522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_get_temp(struct bmg160_data *data, int *val) 46622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 46722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 46822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 46922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_lock(&data->mutex); 47022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_power_state(data, true); 47122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 47222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 47322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 47422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 47522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 47622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_TEMP); 47722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 47822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_temp\n"); 47922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bmg160_set_power_state(data, false); 48022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 48122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 48222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 48322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 48422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada *val = sign_extend32(ret, 7); 48522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_power_state(data, false); 48622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 48722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) 48822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 48922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 49022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return IIO_VAL_INT; 49122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 49222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 49322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_get_axis(struct bmg160_data *data, int axis, int *val) 49422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 49522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 49622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 49722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_lock(&data->mutex); 49822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_power_state(data, true); 49922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 50022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 50122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 50222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 50322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 50422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_read_word_data(data->client, BMG160_AXIS_TO_REG(axis)); 50522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 50622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error reading axis %d\n", axis); 50722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bmg160_set_power_state(data, false); 50822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 50922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 51022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 51122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 51222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada *val = sign_extend32(ret, 15); 51322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_power_state(data, false); 51422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 51522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) 51622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 51722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 51822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return IIO_VAL_INT; 51922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 52022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 52122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_read_raw(struct iio_dev *indio_dev, 52222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_chan_spec const *chan, 52322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int *val, int *val2, long mask) 52422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 52522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 52622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 52722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 52822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada switch (mask) { 52922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada case IIO_CHAN_INFO_RAW: 53022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada switch (chan->type) { 53122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada case IIO_TEMP: 53222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return bmg160_get_temp(data, val); 53322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada case IIO_ANGL_VEL: 53422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (iio_buffer_enabled(indio_dev)) 53522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EBUSY; 53622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada else 53722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return bmg160_get_axis(data, chan->scan_index, 53822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada val); 53922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada default: 54022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 54122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 54222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada case IIO_CHAN_INFO_OFFSET: 54322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (chan->type == IIO_TEMP) { 54422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada *val = BMG160_TEMP_CENTER_VAL; 54522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return IIO_VAL_INT; 54622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } else 54722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 54822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada case IIO_CHAN_INFO_SCALE: 54922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada *val = 0; 55022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada switch (chan->type) { 55122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada case IIO_TEMP: 55222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada *val2 = 500000; 55322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return IIO_VAL_INT_PLUS_MICRO; 55422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada case IIO_ANGL_VEL: 55522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada { 55622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int i; 55722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 55822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada for (i = 0; i < ARRAY_SIZE(bmg160_scale_table); ++i) { 55922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (bmg160_scale_table[i].dps_range == 56022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->dps_range) { 56122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada *val2 = bmg160_scale_table[i].scale; 56222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return IIO_VAL_INT_PLUS_MICRO; 56322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 56422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 56522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 56622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 56722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada default: 56822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 56922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 57022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada case IIO_CHAN_INFO_SAMP_FREQ: 57122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada *val2 = 0; 57222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_lock(&data->mutex); 57322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_get_bw(data, val); 57422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 57522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 57622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada default: 57722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 57822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 57922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 58022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 58122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_write_raw(struct iio_dev *indio_dev, 58222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_chan_spec const *chan, 58322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int val, int val2, long mask) 58422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 58522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 58622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 58722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 58822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada switch (mask) { 58922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada case IIO_CHAN_INFO_SAMP_FREQ: 59022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_lock(&data->mutex); 59122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* 59222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * Section 4.2 of spec 59322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * In suspend mode, the only supported operations are reading 59422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * registers as well as writing to the (0x14) softreset 59522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * register. Since we will be in suspend mode by default, change 59622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * mode to power on for other writes. 59722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada */ 59822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_power_state(data, true); 59922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 60022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 60122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 60222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 60322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_bw(data, val); 60422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 60522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bmg160_set_power_state(data, false); 60622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 60722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 60822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 60922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_power_state(data, false); 61022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 61122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 61222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada case IIO_CHAN_INFO_SCALE: 61322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (val) 61422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 61522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 61622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_lock(&data->mutex); 61722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* Refer to comments above for the suspend mode ops */ 61822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_power_state(data, true); 61922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 62022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 62122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 62222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 62322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_scale(data, val2); 62422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 62522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bmg160_set_power_state(data, false); 62622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 62722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 62822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 62922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_power_state(data, false); 63022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 63122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 63222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada default: 63322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 63422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 63522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 63622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 63722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 63822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 63922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_read_event(struct iio_dev *indio_dev, 64022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada const struct iio_chan_spec *chan, 64122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada enum iio_event_type type, 64222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada enum iio_event_direction dir, 64322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada enum iio_event_info info, 64422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int *val, int *val2) 64522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 64622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 64722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 64822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada *val2 = 0; 64922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada switch (info) { 65022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada case IIO_EV_INFO_VALUE: 65122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada *val = data->slope_thres & BMG160_SLOPE_THRES_MASK; 65222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada break; 65322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada default: 65422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 65522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 65622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 65722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return IIO_VAL_INT; 65822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 65922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 66022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_write_event(struct iio_dev *indio_dev, 66122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada const struct iio_chan_spec *chan, 66222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada enum iio_event_type type, 66322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada enum iio_event_direction dir, 66422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada enum iio_event_info info, 66522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int val, int val2) 66622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 66722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 66822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 66922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada switch (info) { 67022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada case IIO_EV_INFO_VALUE: 67122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (data->ev_enable_state) 67222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EBUSY; 67322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->slope_thres &= ~BMG160_SLOPE_THRES_MASK; 67422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->slope_thres |= (val & BMG160_SLOPE_THRES_MASK); 67522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada break; 67622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada default: 67722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 67822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 67922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 68022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 68122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 68222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 68322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_read_event_config(struct iio_dev *indio_dev, 68422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada const struct iio_chan_spec *chan, 68522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada enum iio_event_type type, 68622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada enum iio_event_direction dir) 68722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 68822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 68922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 69022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 69122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return data->ev_enable_state; 69222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 69322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 69422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_write_event_config(struct iio_dev *indio_dev, 69522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada const struct iio_chan_spec *chan, 69622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada enum iio_event_type type, 69722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada enum iio_event_direction dir, 69822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int state) 69922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 70022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 70122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 70222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 70322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (state && data->ev_enable_state) 70422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 70522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 70622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_lock(&data->mutex); 70722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 70822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (!state && data->motion_trigger_on) { 70922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->ev_enable_state = 0; 71022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 71122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 71222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 71322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* 71422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * We will expect the enable and disable to do operation in 71522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * in reverse order. This will happen here anyway as our 71622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * resume operation uses sync mode runtime pm calls, the 71722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * suspend operation will be delayed by autosuspend delay 71822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * So the disable operation will still happen in reverse of 71922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * enable operation. When runtime pm is disabled the mode 72022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * is always on so sequence doesn't matter 72122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada */ 72222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_power_state(data, state); 72322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 72422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 72522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 72622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 72722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 72822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_setup_any_motion_interrupt(data, state); 72922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 73010bef28973071266e85fe7ea50e08ce8f46dc1caSrinivas Pandruvada bmg160_set_power_state(data, false); 73122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 73222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 73322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 73422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 73522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->ev_enable_state = state; 73622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 73722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 73822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 73922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 74022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 74122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_validate_trigger(struct iio_dev *indio_dev, 74222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_trigger *trig) 74322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 74422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 74522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 74622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (data->dready_trig != trig && data->motion_trig != trig) 74722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 74822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 74922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 75022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 75122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 75222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 400 1000 2000"); 75322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 75422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic IIO_CONST_ATTR(in_anglvel_scale_available, 75522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada "0.001065 0.000532 0.000266 0.000133 0.000066"); 75622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 75722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic struct attribute *bmg160_attributes[] = { 75822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada &iio_const_attr_sampling_frequency_available.dev_attr.attr, 75922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada &iio_const_attr_in_anglvel_scale_available.dev_attr.attr, 76022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada NULL, 76122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada}; 76222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 76322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic const struct attribute_group bmg160_attrs_group = { 76422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .attrs = bmg160_attributes, 76522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada}; 76622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 76722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic const struct iio_event_spec bmg160_event = { 76822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .type = IIO_EV_TYPE_ROC, 7696896ab3a8cfe383cc0c98790b62245a84c6335f7Srinivas Pandruvada .dir = IIO_EV_DIR_EITHER, 77022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | 77122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BIT(IIO_EV_INFO_ENABLE) 77222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada}; 77322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 77422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#define BMG160_CHANNEL(_axis) { \ 77522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .type = IIO_ANGL_VEL, \ 77622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .modified = 1, \ 77722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .channel2 = IIO_MOD_##_axis, \ 77822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 77922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 78022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 78122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .scan_index = AXIS_##_axis, \ 78222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .scan_type = { \ 78322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .sign = 's', \ 78422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .realbits = 16, \ 78522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .storagebits = 16, \ 78622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada }, \ 78722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .event_spec = &bmg160_event, \ 78822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .num_event_specs = 1 \ 78922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 79022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 79122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic const struct iio_chan_spec bmg160_channels[] = { 79222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada { 79322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .type = IIO_TEMP, 79422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 79522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BIT(IIO_CHAN_INFO_SCALE) | 79622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BIT(IIO_CHAN_INFO_OFFSET), 79722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .scan_index = -1, 79822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada }, 79922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_CHANNEL(X), 80022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_CHANNEL(Y), 80122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_CHANNEL(Z), 80222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada IIO_CHAN_SOFT_TIMESTAMP(3), 80322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada}; 80422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 80522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic const struct iio_info bmg160_info = { 80622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .attrs = &bmg160_attrs_group, 80722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .read_raw = bmg160_read_raw, 80822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .write_raw = bmg160_write_raw, 80922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .read_event_value = bmg160_read_event, 81022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .write_event_value = bmg160_write_event, 81122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .write_event_config = bmg160_write_event_config, 81222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .read_event_config = bmg160_read_event_config, 81322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .validate_trigger = bmg160_validate_trigger, 81422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .driver_module = THIS_MODULE, 81522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada}; 81622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 81722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic irqreturn_t bmg160_trigger_handler(int irq, void *p) 81822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 81922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_poll_func *pf = p; 82022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_dev *indio_dev = pf->indio_dev; 82122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 82222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int bit, ret, i = 0; 82322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 82422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_lock(&data->mutex); 82522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada for_each_set_bit(bit, indio_dev->buffer->scan_mask, 82622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada indio_dev->masklength) { 82722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_read_word_data(data->client, 82822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_AXIS_TO_REG(bit)); 82922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 83022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 83122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada goto err; 83222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 83322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->buffer[i++] = ret; 83422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 83522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 83622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 83722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, 83822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->timestamp); 83922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadaerr: 84022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_trigger_notify_done(indio_dev->trig); 84122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 84222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return IRQ_HANDLED; 84322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 84422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 84522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_trig_try_reen(struct iio_trigger *trig) 84622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 84722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); 84822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 84922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 85022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 85122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* new data interrupts don't need ack */ 85222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (data->dready_trigger_on) 85322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 85422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 85522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* Set latched mode interrupt and clear any latched interrupt */ 85622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 85722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_INT_RST_LATCH, 85822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MODE_LATCH_INT | 85922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MODE_LATCH_RESET); 86022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 86122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error writing reg_rst_latch\n"); 86222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 86322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 86422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 86522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 86622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 86722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 86822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_data_rdy_trigger_set_state(struct iio_trigger *trig, 86922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bool state) 87022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 87122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); 87222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 87322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 87422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 87522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_lock(&data->mutex); 87622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 87722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (!state && data->ev_enable_state && data->motion_trigger_on) { 87822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->motion_trigger_on = false; 87922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 88022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 88122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 88222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 88322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* 88422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * Refer to comment in bmg160_write_event_config for 88522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada * enable/disable operation order 88622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada */ 88722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_power_state(data, state); 88822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 88922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 89022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 89122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 89222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (data->motion_trig == trig) 89322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_setup_any_motion_interrupt(data, state); 89422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada else 89522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_setup_new_data_interrupt(data, state); 89622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 89710bef28973071266e85fe7ea50e08ce8f46dc1caSrinivas Pandruvada bmg160_set_power_state(data, false); 89822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 89922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 90022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 90122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (data->motion_trig == trig) 90222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->motion_trigger_on = state; 90322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada else 90422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->dready_trigger_on = state; 90522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 90622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 90722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 90822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 90922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 91022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 91122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic const struct iio_trigger_ops bmg160_trigger_ops = { 91222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .set_trigger_state = bmg160_data_rdy_trigger_set_state, 91322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .try_reenable = bmg160_trig_try_reen, 91422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .owner = THIS_MODULE, 91522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada}; 91622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 91722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic irqreturn_t bmg160_event_handler(int irq, void *private) 91822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 91922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_dev *indio_dev = private; 92022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 92122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 92222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int dir; 92322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 92422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_INT_STATUS_2); 92522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 92622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, "Error reading reg_int_status2\n"); 92722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada goto ack_intr_status; 92822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 92922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 93022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret & 0x08) 93122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dir = IIO_EV_DIR_RISING; 93222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada else 93322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dir = IIO_EV_DIR_FALLING; 93422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 935cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada if (ret & BMG160_ANY_MOTION_BIT_X) 93622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, 93722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 0, 938cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada IIO_MOD_X, 939cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada IIO_EV_TYPE_ROC, 940cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada dir), 941cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada data->timestamp); 942cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada if (ret & BMG160_ANY_MOTION_BIT_Y) 943cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, 944cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada 0, 945cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada IIO_MOD_Y, 946cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada IIO_EV_TYPE_ROC, 947cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada dir), 948cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada data->timestamp); 949cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada if (ret & BMG160_ANY_MOTION_BIT_Z) 950cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, 951cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada 0, 952cb80f6a36be9b3007f23c2d37eddc90a37dac87fSrinivas Pandruvada IIO_MOD_Z, 95322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada IIO_EV_TYPE_ROC, 95422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dir), 95522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->timestamp); 95622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 95722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadaack_intr_status: 95822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (!data->dready_trigger_on) { 95922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = i2c_smbus_write_byte_data(data->client, 96022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_REG_INT_RST_LATCH, 96122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MODE_LATCH_INT | 96222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_INT_MODE_LATCH_RESET); 96322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) 96422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&data->client->dev, 96522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada "Error writing reg_rst_latch\n"); 96622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 96722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 96822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return IRQ_HANDLED; 96922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 97022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 97122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic irqreturn_t bmg160_data_rdy_trig_poll(int irq, void *private) 97222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 97322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_dev *indio_dev = private; 97422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 97522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 97622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->timestamp = iio_get_time_ns(); 97722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 97822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (data->dready_trigger_on) 97922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_trigger_poll(data->dready_trig); 98022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada else if (data->motion_trigger_on) 98122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_trigger_poll(data->motion_trig); 98222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 98322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (data->ev_enable_state) 98422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return IRQ_WAKE_THREAD; 98522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada else 98622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return IRQ_HANDLED; 98722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 98822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 98922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 9903a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdeastatic int bmg160_gpio_probe(struct i2c_client *client, 9913a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea struct bmg160_data *data) 9923a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea 99322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 99422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct device *dev; 99522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct gpio_desc *gpio; 99622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 99722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 99822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (!client) 99922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -EINVAL; 100022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 100122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev = &client->dev; 100222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 100322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada /* data ready gpio interrupt pin */ 100422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada gpio = devm_gpiod_get_index(dev, BMG160_GPIO_NAME, 0); 100522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (IS_ERR(gpio)) { 100622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(dev, "acpi gpio get index failed\n"); 100722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return PTR_ERR(gpio); 100822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 100922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 101022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = gpiod_direction_input(gpio); 101122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret) 101222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 101322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 101422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = gpiod_to_irq(gpio); 101522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 101622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); 101722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 101822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 101922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 102022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 10213a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdeastatic const char *bmg160_match_acpi_device(struct device *dev) 10223a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea{ 10233a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea const struct acpi_device_id *id; 10243a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea 10253a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea id = acpi_match_device(dev->driver->acpi_match_table, dev); 10263a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea if (!id) 10273a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea return NULL; 10283a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea 10293a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea return dev_name(dev); 10303a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea} 10313a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea 103222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_probe(struct i2c_client *client, 103322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada const struct i2c_device_id *id) 103422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 103522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data; 103622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_dev *indio_dev; 103722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 10383a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea const char *name = NULL; 103922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 104022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 104122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (!indio_dev) 104222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -ENOMEM; 104322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 104422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data = iio_priv(indio_dev); 104522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada i2c_set_clientdata(client, indio_dev); 104622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->client = client; 104722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 104822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_chip_init(data); 104922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) 105022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 105122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 105222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_init(&data->mutex); 105322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 10543a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea if (id) 10553a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea name = id->name; 10563a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea 10573a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea if (ACPI_HANDLE(&client->dev)) 10583a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea name = bmg160_match_acpi_device(&client->dev); 10593a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea 106022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada indio_dev->dev.parent = &client->dev; 106122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada indio_dev->channels = bmg160_channels; 106222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada indio_dev->num_channels = ARRAY_SIZE(bmg160_channels); 10633a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea indio_dev->name = name; 106422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada indio_dev->modes = INDIO_DIRECT_MODE; 106522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada indio_dev->info = &bmg160_info; 106622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 106722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (client->irq <= 0) 10683a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea client->irq = bmg160_gpio_probe(client, data); 106922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 107022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (client->irq > 0) { 107122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = devm_request_threaded_irq(&client->dev, 107222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada client->irq, 107322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bmg160_data_rdy_trig_poll, 107422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bmg160_event_handler, 107522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada IRQF_TRIGGER_RISING, 107622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_IRQ_NAME, 107722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada indio_dev); 107822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret) 107922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 108022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 108122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->dready_trig = devm_iio_trigger_alloc(&client->dev, 108222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada "%s-dev%d", 108322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada indio_dev->name, 108422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada indio_dev->id); 108522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (!data->dready_trig) 108622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -ENOMEM; 108722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 108822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->motion_trig = devm_iio_trigger_alloc(&client->dev, 108922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada "%s-any-motion-dev%d", 109022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada indio_dev->name, 109122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada indio_dev->id); 109222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (!data->motion_trig) 109322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return -ENOMEM; 109422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 109522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->dready_trig->dev.parent = &client->dev; 109622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->dready_trig->ops = &bmg160_trigger_ops; 109722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_trigger_set_drvdata(data->dready_trig, indio_dev); 109822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = iio_trigger_register(data->dready_trig); 109922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret) 110022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 110122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 110222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->motion_trig->dev.parent = &client->dev; 110322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->motion_trig->ops = &bmg160_trigger_ops; 110422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_trigger_set_drvdata(data->motion_trig, indio_dev); 110522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = iio_trigger_register(data->motion_trig); 110622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret) { 110722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->motion_trig = NULL; 110822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada goto err_trigger_unregister; 110922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 111022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 111122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = iio_triggered_buffer_setup(indio_dev, 111222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada NULL, 111322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bmg160_trigger_handler, 111422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada NULL); 111522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 111622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&client->dev, 111722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada "iio triggered buffer setup failed\n"); 111822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada goto err_trigger_unregister; 111922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 112022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 112122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 112222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = iio_device_register(indio_dev); 112322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) { 112422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada dev_err(&client->dev, "unable to register iio device\n"); 112522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada goto err_buffer_cleanup; 112622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 112722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 112822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = pm_runtime_set_active(&client->dev); 112922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret) 113022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada goto err_iio_unregister; 113122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 113222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada pm_runtime_enable(&client->dev); 113322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada pm_runtime_set_autosuspend_delay(&client->dev, 113422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada BMG160_AUTO_SUSPEND_DELAY_MS); 113522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada pm_runtime_use_autosuspend(&client->dev); 113622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 113722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 113822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 113922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadaerr_iio_unregister: 114022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_device_unregister(indio_dev); 114122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadaerr_buffer_cleanup: 114222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (data->dready_trig) 114322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_triggered_buffer_cleanup(indio_dev); 114422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadaerr_trigger_unregister: 114522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (data->dready_trig) 114622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_trigger_unregister(data->dready_trig); 114722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (data->motion_trig) 114822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_trigger_unregister(data->motion_trig); 114922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 115022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 115122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 115222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 115322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_remove(struct i2c_client *client) 115422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 115522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(client); 115622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 115722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 115822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada pm_runtime_disable(&client->dev); 115922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada pm_runtime_set_suspended(&client->dev); 116022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada pm_runtime_put_noidle(&client->dev); 116122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 116222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_device_unregister(indio_dev); 116322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 116422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (data->dready_trig) { 116522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_triggered_buffer_cleanup(indio_dev); 116622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_trigger_unregister(data->dready_trig); 116722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada iio_trigger_unregister(data->motion_trig); 116822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada } 116922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 117022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_lock(&data->mutex); 117122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bmg160_set_mode(data, BMG160_MODE_DEEP_SUSPEND); 117222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 117322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 117422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 117522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 117622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 117722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#ifdef CONFIG_PM_SLEEP 117822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_suspend(struct device *dev) 117922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 118022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 118122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 118222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 118322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_lock(&data->mutex); 118422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bmg160_set_mode(data, BMG160_MODE_SUSPEND); 118522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 118622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 118722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 118822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 118922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 119022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_resume(struct device *dev) 119122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 119222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 119322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 119422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 119522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_lock(&data->mutex); 119622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (data->dready_trigger_on || data->motion_trigger_on || 119722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada data->ev_enable_state) 119822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bmg160_set_mode(data, BMG160_MODE_NORMAL); 119922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada mutex_unlock(&data->mutex); 120022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 120122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 120222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 120322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#endif 120422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 120522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#ifdef CONFIG_PM_RUNTIME 120622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_runtime_suspend(struct device *dev) 120722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 120822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 120922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 121010bef28973071266e85fe7ea50e08ce8f46dc1caSrinivas Pandruvada int ret; 121122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 121210bef28973071266e85fe7ea50e08ce8f46dc1caSrinivas Pandruvada ret = bmg160_set_mode(data, BMG160_MODE_SUSPEND); 121310bef28973071266e85fe7ea50e08ce8f46dc1caSrinivas Pandruvada if (ret < 0) { 121410bef28973071266e85fe7ea50e08ce8f46dc1caSrinivas Pandruvada dev_err(&data->client->dev, "set mode failed\n"); 121510bef28973071266e85fe7ea50e08ce8f46dc1caSrinivas Pandruvada return -EAGAIN; 121610bef28973071266e85fe7ea50e08ce8f46dc1caSrinivas Pandruvada } 121710bef28973071266e85fe7ea50e08ce8f46dc1caSrinivas Pandruvada 121810bef28973071266e85fe7ea50e08ce8f46dc1caSrinivas Pandruvada return 0; 121922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 122022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 122122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic int bmg160_runtime_resume(struct device *dev) 122222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada{ 122322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 122422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada struct bmg160_data *data = iio_priv(indio_dev); 122522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada int ret; 122622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 122722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada ret = bmg160_set_mode(data, BMG160_MODE_NORMAL); 122822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada if (ret < 0) 122922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return ret; 123022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 123122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada msleep_interruptible(BMG160_MAX_STARTUP_TIME_MS); 123222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 123322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada return 0; 123422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada} 123522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada#endif 123622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 123722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic const struct dev_pm_ops bmg160_pm_ops = { 123822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada SET_SYSTEM_SLEEP_PM_OPS(bmg160_suspend, bmg160_resume) 123922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada SET_RUNTIME_PM_OPS(bmg160_runtime_suspend, 124022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada bmg160_runtime_resume, NULL) 124122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada}; 124222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 124322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic const struct acpi_device_id bmg160_acpi_match[] = { 124422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada {"BMG0160", 0}, 12453a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea {"BMI055B", 0}, 12463a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea {}, 124722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada}; 12483a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea 124922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas PandruvadaMODULE_DEVICE_TABLE(acpi, bmg160_acpi_match); 125022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 125122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic const struct i2c_device_id bmg160_id[] = { 125222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada {"bmg160", 0}, 12533a0888edcffd9406f1cbbe240f4533e35db67e81Irina Tirdea {"bmi055_gyro", 0}, 125422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada {} 125522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada}; 125622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 125722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas PandruvadaMODULE_DEVICE_TABLE(i2c, bmg160_id); 125822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 125922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadastatic struct i2c_driver bmg160_driver = { 126022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .driver = { 126122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .name = BMG160_DRV_NAME, 126222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .acpi_match_table = ACPI_PTR(bmg160_acpi_match), 126322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .pm = &bmg160_pm_ops, 126422b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada }, 126522b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .probe = bmg160_probe, 126622b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .remove = bmg160_remove, 126722b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada .id_table = bmg160_id, 126822b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada}; 126922b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvadamodule_i2c_driver(bmg160_driver); 127022b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas Pandruvada 127122b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas PandruvadaMODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 127222b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas PandruvadaMODULE_LICENSE("GPL v2"); 127322b46c45fb9be8ec1fcb4d9b74810e6a20ff67ccSrinivas PandruvadaMODULE_DESCRIPTION("BMG160 Gyro driver"); 1274