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