12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
213426454SMarkus Pargmann /*
313426454SMarkus Pargmann * BMG160 Gyro Sensor driver
413426454SMarkus Pargmann * Copyright (c) 2014, Intel Corporation.
513426454SMarkus Pargmann */
613426454SMarkus Pargmann
713426454SMarkus Pargmann #include <linux/module.h>
813426454SMarkus Pargmann #include <linux/interrupt.h>
913426454SMarkus Pargmann #include <linux/delay.h>
1013426454SMarkus Pargmann #include <linux/slab.h>
1113426454SMarkus Pargmann #include <linux/acpi.h>
1213426454SMarkus Pargmann #include <linux/pm.h>
1313426454SMarkus Pargmann #include <linux/pm_runtime.h>
1413426454SMarkus Pargmann #include <linux/iio/iio.h>
1513426454SMarkus Pargmann #include <linux/iio/sysfs.h>
1613426454SMarkus Pargmann #include <linux/iio/buffer.h>
1713426454SMarkus Pargmann #include <linux/iio/trigger.h>
1813426454SMarkus Pargmann #include <linux/iio/events.h>
1913426454SMarkus Pargmann #include <linux/iio/trigger_consumer.h>
2013426454SMarkus Pargmann #include <linux/iio/triggered_buffer.h>
2113426454SMarkus Pargmann #include <linux/regmap.h>
22ce69361aSStephan Gerhold #include <linux/regulator/consumer.h>
2313426454SMarkus Pargmann #include "bmg160.h"
2413426454SMarkus Pargmann
2513426454SMarkus Pargmann #define BMG160_IRQ_NAME "bmg160_event"
2613426454SMarkus Pargmann
2713426454SMarkus Pargmann #define BMG160_REG_CHIP_ID 0x00
2813426454SMarkus Pargmann #define BMG160_CHIP_ID_VAL 0x0F
2913426454SMarkus Pargmann
3013426454SMarkus Pargmann #define BMG160_REG_PMU_LPW 0x11
3113426454SMarkus Pargmann #define BMG160_MODE_NORMAL 0x00
3213426454SMarkus Pargmann #define BMG160_MODE_DEEP_SUSPEND 0x20
3313426454SMarkus Pargmann #define BMG160_MODE_SUSPEND 0x80
3413426454SMarkus Pargmann
3513426454SMarkus Pargmann #define BMG160_REG_RANGE 0x0F
3613426454SMarkus Pargmann
3713426454SMarkus Pargmann #define BMG160_RANGE_2000DPS 0
3813426454SMarkus Pargmann #define BMG160_RANGE_1000DPS 1
3913426454SMarkus Pargmann #define BMG160_RANGE_500DPS 2
4013426454SMarkus Pargmann #define BMG160_RANGE_250DPS 3
4113426454SMarkus Pargmann #define BMG160_RANGE_125DPS 4
4213426454SMarkus Pargmann
4313426454SMarkus Pargmann #define BMG160_REG_PMU_BW 0x10
4413426454SMarkus Pargmann #define BMG160_NO_FILTER 0
4513426454SMarkus Pargmann #define BMG160_DEF_BW 100
46bf61f5d2SSteffen Trumtrar #define BMG160_REG_PMU_BW_RES BIT(7)
4713426454SMarkus Pargmann
484bdc9029SQuentin Schulz #define BMG160_GYRO_REG_RESET 0x14
494bdc9029SQuentin Schulz #define BMG160_GYRO_RESET_VAL 0xb6
504bdc9029SQuentin Schulz
5113426454SMarkus Pargmann #define BMG160_REG_INT_MAP_0 0x17
5213426454SMarkus Pargmann #define BMG160_INT_MAP_0_BIT_ANY BIT(1)
5313426454SMarkus Pargmann
5413426454SMarkus Pargmann #define BMG160_REG_INT_MAP_1 0x18
5513426454SMarkus Pargmann #define BMG160_INT_MAP_1_BIT_NEW_DATA BIT(0)
5613426454SMarkus Pargmann
5713426454SMarkus Pargmann #define BMG160_REG_INT_RST_LATCH 0x21
5813426454SMarkus Pargmann #define BMG160_INT_MODE_LATCH_RESET 0x80
5913426454SMarkus Pargmann #define BMG160_INT_MODE_LATCH_INT 0x0F
6013426454SMarkus Pargmann #define BMG160_INT_MODE_NON_LATCH_INT 0x00
6113426454SMarkus Pargmann
6213426454SMarkus Pargmann #define BMG160_REG_INT_EN_0 0x15
6313426454SMarkus Pargmann #define BMG160_DATA_ENABLE_INT BIT(7)
6413426454SMarkus Pargmann
6513426454SMarkus Pargmann #define BMG160_REG_INT_EN_1 0x16
6613426454SMarkus Pargmann #define BMG160_INT1_BIT_OD BIT(1)
6713426454SMarkus Pargmann
6813426454SMarkus Pargmann #define BMG160_REG_XOUT_L 0x02
6913426454SMarkus Pargmann #define BMG160_AXIS_TO_REG(axis) (BMG160_REG_XOUT_L + (axis * 2))
7013426454SMarkus Pargmann
7113426454SMarkus Pargmann #define BMG160_REG_SLOPE_THRES 0x1B
7213426454SMarkus Pargmann #define BMG160_SLOPE_THRES_MASK 0x0F
7313426454SMarkus Pargmann
7413426454SMarkus Pargmann #define BMG160_REG_MOTION_INTR 0x1C
7513426454SMarkus Pargmann #define BMG160_INT_MOTION_X BIT(0)
7613426454SMarkus Pargmann #define BMG160_INT_MOTION_Y BIT(1)
7713426454SMarkus Pargmann #define BMG160_INT_MOTION_Z BIT(2)
7813426454SMarkus Pargmann #define BMG160_ANY_DUR_MASK 0x30
7913426454SMarkus Pargmann #define BMG160_ANY_DUR_SHIFT 4
8013426454SMarkus Pargmann
8113426454SMarkus Pargmann #define BMG160_REG_INT_STATUS_2 0x0B
8213426454SMarkus Pargmann #define BMG160_ANY_MOTION_MASK 0x07
8313426454SMarkus Pargmann #define BMG160_ANY_MOTION_BIT_X BIT(0)
8413426454SMarkus Pargmann #define BMG160_ANY_MOTION_BIT_Y BIT(1)
8513426454SMarkus Pargmann #define BMG160_ANY_MOTION_BIT_Z BIT(2)
8613426454SMarkus Pargmann
8713426454SMarkus Pargmann #define BMG160_REG_TEMP 0x08
8813426454SMarkus Pargmann #define BMG160_TEMP_CENTER_VAL 23
8913426454SMarkus Pargmann
9013426454SMarkus Pargmann #define BMG160_MAX_STARTUP_TIME_MS 80
9113426454SMarkus Pargmann
9213426454SMarkus Pargmann #define BMG160_AUTO_SUSPEND_DELAY_MS 2000
9313426454SMarkus Pargmann
9413426454SMarkus Pargmann struct bmg160_data {
9513426454SMarkus Pargmann struct regmap *regmap;
9613426454SMarkus Pargmann struct iio_trigger *dready_trig;
9713426454SMarkus Pargmann struct iio_trigger *motion_trig;
983a6049f6SH. Nikolaus Schaller struct iio_mount_matrix orientation;
9913426454SMarkus Pargmann struct mutex mutex;
10006778d88SJonathan Cameron /* Ensure naturally aligned timestamp */
10106778d88SJonathan Cameron struct {
10206778d88SJonathan Cameron s16 chans[3];
10306778d88SJonathan Cameron s64 timestamp __aligned(8);
10406778d88SJonathan Cameron } scan;
10513426454SMarkus Pargmann u32 dps_range;
10613426454SMarkus Pargmann int ev_enable_state;
10713426454SMarkus Pargmann int slope_thres;
10813426454SMarkus Pargmann bool dready_trigger_on;
10913426454SMarkus Pargmann bool motion_trigger_on;
11013426454SMarkus Pargmann int irq;
11113426454SMarkus Pargmann };
11213426454SMarkus Pargmann
11313426454SMarkus Pargmann enum bmg160_axis {
11413426454SMarkus Pargmann AXIS_X,
11513426454SMarkus Pargmann AXIS_Y,
11613426454SMarkus Pargmann AXIS_Z,
117ee8c5419SIrina Tirdea AXIS_MAX,
11813426454SMarkus Pargmann };
11913426454SMarkus Pargmann
12013426454SMarkus Pargmann static const struct {
121bf61f5d2SSteffen Trumtrar int odr;
122bf61f5d2SSteffen Trumtrar int filter;
12313426454SMarkus Pargmann int bw_bits;
124bf61f5d2SSteffen Trumtrar } bmg160_samp_freq_table[] = { {100, 32, 0x07},
125bf61f5d2SSteffen Trumtrar {200, 64, 0x06},
126bf61f5d2SSteffen Trumtrar {100, 12, 0x05},
127bf61f5d2SSteffen Trumtrar {200, 23, 0x04},
128bf61f5d2SSteffen Trumtrar {400, 47, 0x03},
129bf61f5d2SSteffen Trumtrar {1000, 116, 0x02},
130bf61f5d2SSteffen Trumtrar {2000, 230, 0x01} };
13113426454SMarkus Pargmann
13213426454SMarkus Pargmann static const struct {
13313426454SMarkus Pargmann int scale;
13413426454SMarkus Pargmann int dps_range;
13513426454SMarkus Pargmann } bmg160_scale_table[] = { { 1065, BMG160_RANGE_2000DPS},
13613426454SMarkus Pargmann { 532, BMG160_RANGE_1000DPS},
13713426454SMarkus Pargmann { 266, BMG160_RANGE_500DPS},
13813426454SMarkus Pargmann { 133, BMG160_RANGE_250DPS},
13913426454SMarkus Pargmann { 66, BMG160_RANGE_125DPS} };
14013426454SMarkus Pargmann
bmg160_set_mode(struct bmg160_data * data,u8 mode)14113426454SMarkus Pargmann static int bmg160_set_mode(struct bmg160_data *data, u8 mode)
14213426454SMarkus Pargmann {
143dc2c5715SAlison Schofield struct device *dev = regmap_get_device(data->regmap);
14413426454SMarkus Pargmann int ret;
14513426454SMarkus Pargmann
14613426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_PMU_LPW, mode);
14713426454SMarkus Pargmann if (ret < 0) {
148dc2c5715SAlison Schofield dev_err(dev, "Error writing reg_pmu_lpw\n");
14913426454SMarkus Pargmann return ret;
15013426454SMarkus Pargmann }
15113426454SMarkus Pargmann
15213426454SMarkus Pargmann return 0;
15313426454SMarkus Pargmann }
15413426454SMarkus Pargmann
bmg160_convert_freq_to_bit(int val)15513426454SMarkus Pargmann static int bmg160_convert_freq_to_bit(int val)
15613426454SMarkus Pargmann {
15713426454SMarkus Pargmann int i;
15813426454SMarkus Pargmann
15913426454SMarkus Pargmann for (i = 0; i < ARRAY_SIZE(bmg160_samp_freq_table); ++i) {
160bf61f5d2SSteffen Trumtrar if (bmg160_samp_freq_table[i].odr == val)
16113426454SMarkus Pargmann return bmg160_samp_freq_table[i].bw_bits;
16213426454SMarkus Pargmann }
16313426454SMarkus Pargmann
16413426454SMarkus Pargmann return -EINVAL;
16513426454SMarkus Pargmann }
16613426454SMarkus Pargmann
bmg160_set_bw(struct bmg160_data * data,int val)16713426454SMarkus Pargmann static int bmg160_set_bw(struct bmg160_data *data, int val)
16813426454SMarkus Pargmann {
169dc2c5715SAlison Schofield struct device *dev = regmap_get_device(data->regmap);
17013426454SMarkus Pargmann int ret;
17113426454SMarkus Pargmann int bw_bits;
17213426454SMarkus Pargmann
17313426454SMarkus Pargmann bw_bits = bmg160_convert_freq_to_bit(val);
17413426454SMarkus Pargmann if (bw_bits < 0)
17513426454SMarkus Pargmann return bw_bits;
17613426454SMarkus Pargmann
17713426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_PMU_BW, bw_bits);
17813426454SMarkus Pargmann if (ret < 0) {
179dc2c5715SAlison Schofield dev_err(dev, "Error writing reg_pmu_bw\n");
18013426454SMarkus Pargmann return ret;
18113426454SMarkus Pargmann }
18213426454SMarkus Pargmann
183bf61f5d2SSteffen Trumtrar return 0;
184bf61f5d2SSteffen Trumtrar }
185bf61f5d2SSteffen Trumtrar
bmg160_get_filter(struct bmg160_data * data,int * val)186bf61f5d2SSteffen Trumtrar static int bmg160_get_filter(struct bmg160_data *data, int *val)
187bf61f5d2SSteffen Trumtrar {
188bf61f5d2SSteffen Trumtrar struct device *dev = regmap_get_device(data->regmap);
189bf61f5d2SSteffen Trumtrar int ret;
190bf61f5d2SSteffen Trumtrar int i;
191bf61f5d2SSteffen Trumtrar unsigned int bw_bits;
192bf61f5d2SSteffen Trumtrar
193bf61f5d2SSteffen Trumtrar ret = regmap_read(data->regmap, BMG160_REG_PMU_BW, &bw_bits);
194bf61f5d2SSteffen Trumtrar if (ret < 0) {
195bf61f5d2SSteffen Trumtrar dev_err(dev, "Error reading reg_pmu_bw\n");
196bf61f5d2SSteffen Trumtrar return ret;
197bf61f5d2SSteffen Trumtrar }
198bf61f5d2SSteffen Trumtrar
199bf61f5d2SSteffen Trumtrar /* Ignore the readonly reserved bit. */
200bf61f5d2SSteffen Trumtrar bw_bits &= ~BMG160_REG_PMU_BW_RES;
201bf61f5d2SSteffen Trumtrar
202bf61f5d2SSteffen Trumtrar for (i = 0; i < ARRAY_SIZE(bmg160_samp_freq_table); ++i) {
203bf61f5d2SSteffen Trumtrar if (bmg160_samp_freq_table[i].bw_bits == bw_bits)
204bf61f5d2SSteffen Trumtrar break;
205bf61f5d2SSteffen Trumtrar }
206bf61f5d2SSteffen Trumtrar
207bf61f5d2SSteffen Trumtrar *val = bmg160_samp_freq_table[i].filter;
208bf61f5d2SSteffen Trumtrar
209bf61f5d2SSteffen Trumtrar return ret ? ret : IIO_VAL_INT;
210bf61f5d2SSteffen Trumtrar }
211bf61f5d2SSteffen Trumtrar
212bf61f5d2SSteffen Trumtrar
bmg160_set_filter(struct bmg160_data * data,int val)213bf61f5d2SSteffen Trumtrar static int bmg160_set_filter(struct bmg160_data *data, int val)
214bf61f5d2SSteffen Trumtrar {
215bf61f5d2SSteffen Trumtrar struct device *dev = regmap_get_device(data->regmap);
216bf61f5d2SSteffen Trumtrar int ret;
217bf61f5d2SSteffen Trumtrar int i;
218bf61f5d2SSteffen Trumtrar
219bf61f5d2SSteffen Trumtrar for (i = 0; i < ARRAY_SIZE(bmg160_samp_freq_table); ++i) {
220bf61f5d2SSteffen Trumtrar if (bmg160_samp_freq_table[i].filter == val)
221bf61f5d2SSteffen Trumtrar break;
222bf61f5d2SSteffen Trumtrar }
223bf61f5d2SSteffen Trumtrar
224bf61f5d2SSteffen Trumtrar ret = regmap_write(data->regmap, BMG160_REG_PMU_BW,
225bf61f5d2SSteffen Trumtrar bmg160_samp_freq_table[i].bw_bits);
226bf61f5d2SSteffen Trumtrar if (ret < 0) {
227bf61f5d2SSteffen Trumtrar dev_err(dev, "Error writing reg_pmu_bw\n");
228bf61f5d2SSteffen Trumtrar return ret;
229bf61f5d2SSteffen Trumtrar }
23013426454SMarkus Pargmann
23113426454SMarkus Pargmann return 0;
23213426454SMarkus Pargmann }
23313426454SMarkus Pargmann
bmg160_chip_init(struct bmg160_data * data)23413426454SMarkus Pargmann static int bmg160_chip_init(struct bmg160_data *data)
23513426454SMarkus Pargmann {
236dc2c5715SAlison Schofield struct device *dev = regmap_get_device(data->regmap);
23713426454SMarkus Pargmann int ret;
23813426454SMarkus Pargmann unsigned int val;
23913426454SMarkus Pargmann
2404bdc9029SQuentin Schulz /*
2414bdc9029SQuentin Schulz * Reset chip to get it in a known good state. A delay of 30ms after
2424bdc9029SQuentin Schulz * reset is required according to the datasheet.
2434bdc9029SQuentin Schulz */
2444bdc9029SQuentin Schulz regmap_write(data->regmap, BMG160_GYRO_REG_RESET,
2454bdc9029SQuentin Schulz BMG160_GYRO_RESET_VAL);
2464bdc9029SQuentin Schulz usleep_range(30000, 30700);
2474bdc9029SQuentin Schulz
24813426454SMarkus Pargmann ret = regmap_read(data->regmap, BMG160_REG_CHIP_ID, &val);
24913426454SMarkus Pargmann if (ret < 0) {
250dc2c5715SAlison Schofield dev_err(dev, "Error reading reg_chip_id\n");
25113426454SMarkus Pargmann return ret;
25213426454SMarkus Pargmann }
25313426454SMarkus Pargmann
254dc2c5715SAlison Schofield dev_dbg(dev, "Chip Id %x\n", val);
25513426454SMarkus Pargmann if (val != BMG160_CHIP_ID_VAL) {
256dc2c5715SAlison Schofield dev_err(dev, "invalid chip %x\n", val);
25713426454SMarkus Pargmann return -ENODEV;
25813426454SMarkus Pargmann }
25913426454SMarkus Pargmann
26013426454SMarkus Pargmann ret = bmg160_set_mode(data, BMG160_MODE_NORMAL);
26113426454SMarkus Pargmann if (ret < 0)
26213426454SMarkus Pargmann return ret;
26313426454SMarkus Pargmann
26413426454SMarkus Pargmann /* Wait upto 500 ms to be ready after changing mode */
26513426454SMarkus Pargmann usleep_range(500, 1000);
26613426454SMarkus Pargmann
26713426454SMarkus Pargmann /* Set Bandwidth */
26813426454SMarkus Pargmann ret = bmg160_set_bw(data, BMG160_DEF_BW);
26913426454SMarkus Pargmann if (ret < 0)
27013426454SMarkus Pargmann return ret;
27113426454SMarkus Pargmann
27213426454SMarkus Pargmann /* Set Default Range */
27313426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_RANGE, BMG160_RANGE_500DPS);
27413426454SMarkus Pargmann if (ret < 0) {
275dc2c5715SAlison Schofield dev_err(dev, "Error writing reg_range\n");
27613426454SMarkus Pargmann return ret;
27713426454SMarkus Pargmann }
27813426454SMarkus Pargmann data->dps_range = BMG160_RANGE_500DPS;
27913426454SMarkus Pargmann
28013426454SMarkus Pargmann ret = regmap_read(data->regmap, BMG160_REG_SLOPE_THRES, &val);
28113426454SMarkus Pargmann if (ret < 0) {
282dc2c5715SAlison Schofield dev_err(dev, "Error reading reg_slope_thres\n");
28313426454SMarkus Pargmann return ret;
28413426454SMarkus Pargmann }
28513426454SMarkus Pargmann data->slope_thres = val;
28613426454SMarkus Pargmann
28713426454SMarkus Pargmann /* Set default interrupt mode */
28813426454SMarkus Pargmann ret = regmap_update_bits(data->regmap, BMG160_REG_INT_EN_1,
28913426454SMarkus Pargmann BMG160_INT1_BIT_OD, 0);
29013426454SMarkus Pargmann if (ret < 0) {
291dc2c5715SAlison Schofield dev_err(dev, "Error updating bits in reg_int_en_1\n");
29213426454SMarkus Pargmann return ret;
29313426454SMarkus Pargmann }
29413426454SMarkus Pargmann
29513426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH,
29613426454SMarkus Pargmann BMG160_INT_MODE_LATCH_INT |
29713426454SMarkus Pargmann BMG160_INT_MODE_LATCH_RESET);
29813426454SMarkus Pargmann if (ret < 0) {
299dc2c5715SAlison Schofield dev_err(dev,
30013426454SMarkus Pargmann "Error writing reg_motion_intr\n");
30113426454SMarkus Pargmann return ret;
30213426454SMarkus Pargmann }
30313426454SMarkus Pargmann
30413426454SMarkus Pargmann return 0;
30513426454SMarkus Pargmann }
30613426454SMarkus Pargmann
bmg160_set_power_state(struct bmg160_data * data,bool on)30713426454SMarkus Pargmann static int bmg160_set_power_state(struct bmg160_data *data, bool on)
30813426454SMarkus Pargmann {
30913426454SMarkus Pargmann #ifdef CONFIG_PM
310dc2c5715SAlison Schofield struct device *dev = regmap_get_device(data->regmap);
31113426454SMarkus Pargmann int ret;
31213426454SMarkus Pargmann
31313426454SMarkus Pargmann if (on)
314dc2c5715SAlison Schofield ret = pm_runtime_get_sync(dev);
31513426454SMarkus Pargmann else {
316dc2c5715SAlison Schofield pm_runtime_mark_last_busy(dev);
317dc2c5715SAlison Schofield ret = pm_runtime_put_autosuspend(dev);
31813426454SMarkus Pargmann }
31913426454SMarkus Pargmann
32013426454SMarkus Pargmann if (ret < 0) {
321dc2c5715SAlison Schofield dev_err(dev, "Failed: bmg160_set_power_state for %d\n", on);
322dc2c5715SAlison Schofield
32313426454SMarkus Pargmann if (on)
324dc2c5715SAlison Schofield pm_runtime_put_noidle(dev);
32513426454SMarkus Pargmann
32613426454SMarkus Pargmann return ret;
32713426454SMarkus Pargmann }
32813426454SMarkus Pargmann #endif
32913426454SMarkus Pargmann
33013426454SMarkus Pargmann return 0;
33113426454SMarkus Pargmann }
33213426454SMarkus Pargmann
bmg160_setup_any_motion_interrupt(struct bmg160_data * data,bool status)33313426454SMarkus Pargmann static int bmg160_setup_any_motion_interrupt(struct bmg160_data *data,
33413426454SMarkus Pargmann bool status)
33513426454SMarkus Pargmann {
336dc2c5715SAlison Schofield struct device *dev = regmap_get_device(data->regmap);
33713426454SMarkus Pargmann int ret;
33813426454SMarkus Pargmann
33913426454SMarkus Pargmann /* Enable/Disable INT_MAP0 mapping */
34013426454SMarkus Pargmann ret = regmap_update_bits(data->regmap, BMG160_REG_INT_MAP_0,
34113426454SMarkus Pargmann BMG160_INT_MAP_0_BIT_ANY,
34213426454SMarkus Pargmann (status ? BMG160_INT_MAP_0_BIT_ANY : 0));
34313426454SMarkus Pargmann if (ret < 0) {
344dc2c5715SAlison Schofield dev_err(dev, "Error updating bits reg_int_map0\n");
34513426454SMarkus Pargmann return ret;
34613426454SMarkus Pargmann }
34713426454SMarkus Pargmann
34813426454SMarkus Pargmann /* Enable/Disable slope interrupts */
34913426454SMarkus Pargmann if (status) {
35013426454SMarkus Pargmann /* Update slope thres */
35113426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_SLOPE_THRES,
35213426454SMarkus Pargmann data->slope_thres);
35313426454SMarkus Pargmann if (ret < 0) {
354dc2c5715SAlison Schofield dev_err(dev, "Error writing reg_slope_thres\n");
35513426454SMarkus Pargmann return ret;
35613426454SMarkus Pargmann }
35713426454SMarkus Pargmann
35813426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_MOTION_INTR,
35913426454SMarkus Pargmann BMG160_INT_MOTION_X | BMG160_INT_MOTION_Y |
36013426454SMarkus Pargmann BMG160_INT_MOTION_Z);
36113426454SMarkus Pargmann if (ret < 0) {
362dc2c5715SAlison Schofield dev_err(dev, "Error writing reg_motion_intr\n");
36313426454SMarkus Pargmann return ret;
36413426454SMarkus Pargmann }
36513426454SMarkus Pargmann
36613426454SMarkus Pargmann /*
36713426454SMarkus Pargmann * New data interrupt is always non-latched,
36813426454SMarkus Pargmann * which will have higher priority, so no need
36913426454SMarkus Pargmann * to set latched mode, we will be flooded anyway with INTR
37013426454SMarkus Pargmann */
37113426454SMarkus Pargmann if (!data->dready_trigger_on) {
37213426454SMarkus Pargmann ret = regmap_write(data->regmap,
37313426454SMarkus Pargmann BMG160_REG_INT_RST_LATCH,
37413426454SMarkus Pargmann BMG160_INT_MODE_LATCH_INT |
37513426454SMarkus Pargmann BMG160_INT_MODE_LATCH_RESET);
37613426454SMarkus Pargmann if (ret < 0) {
377dc2c5715SAlison Schofield dev_err(dev, "Error writing reg_rst_latch\n");
37813426454SMarkus Pargmann return ret;
37913426454SMarkus Pargmann }
38013426454SMarkus Pargmann }
38113426454SMarkus Pargmann
38213426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0,
38313426454SMarkus Pargmann BMG160_DATA_ENABLE_INT);
38413426454SMarkus Pargmann
38513426454SMarkus Pargmann } else {
38613426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0, 0);
38713426454SMarkus Pargmann }
38813426454SMarkus Pargmann
38913426454SMarkus Pargmann if (ret < 0) {
390dc2c5715SAlison Schofield dev_err(dev, "Error writing reg_int_en0\n");
39113426454SMarkus Pargmann return ret;
39213426454SMarkus Pargmann }
39313426454SMarkus Pargmann
39413426454SMarkus Pargmann return 0;
39513426454SMarkus Pargmann }
39613426454SMarkus Pargmann
bmg160_setup_new_data_interrupt(struct bmg160_data * data,bool status)39713426454SMarkus Pargmann static int bmg160_setup_new_data_interrupt(struct bmg160_data *data,
39813426454SMarkus Pargmann bool status)
39913426454SMarkus Pargmann {
400dc2c5715SAlison Schofield struct device *dev = regmap_get_device(data->regmap);
40113426454SMarkus Pargmann int ret;
40213426454SMarkus Pargmann
40313426454SMarkus Pargmann /* Enable/Disable INT_MAP1 mapping */
40413426454SMarkus Pargmann ret = regmap_update_bits(data->regmap, BMG160_REG_INT_MAP_1,
40513426454SMarkus Pargmann BMG160_INT_MAP_1_BIT_NEW_DATA,
40613426454SMarkus Pargmann (status ? BMG160_INT_MAP_1_BIT_NEW_DATA : 0));
40713426454SMarkus Pargmann if (ret < 0) {
408dc2c5715SAlison Schofield dev_err(dev, "Error updating bits in reg_int_map1\n");
40913426454SMarkus Pargmann return ret;
41013426454SMarkus Pargmann }
41113426454SMarkus Pargmann
41213426454SMarkus Pargmann if (status) {
41313426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH,
41413426454SMarkus Pargmann BMG160_INT_MODE_NON_LATCH_INT |
41513426454SMarkus Pargmann BMG160_INT_MODE_LATCH_RESET);
41613426454SMarkus Pargmann if (ret < 0) {
417dc2c5715SAlison Schofield dev_err(dev, "Error writing reg_rst_latch\n");
41813426454SMarkus Pargmann return ret;
41913426454SMarkus Pargmann }
42013426454SMarkus Pargmann
42113426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0,
42213426454SMarkus Pargmann BMG160_DATA_ENABLE_INT);
42313426454SMarkus Pargmann
42413426454SMarkus Pargmann } else {
42513426454SMarkus Pargmann /* Restore interrupt mode */
42613426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH,
42713426454SMarkus Pargmann BMG160_INT_MODE_LATCH_INT |
42813426454SMarkus Pargmann BMG160_INT_MODE_LATCH_RESET);
42913426454SMarkus Pargmann if (ret < 0) {
430dc2c5715SAlison Schofield dev_err(dev, "Error writing reg_rst_latch\n");
43113426454SMarkus Pargmann return ret;
43213426454SMarkus Pargmann }
43313426454SMarkus Pargmann
43413426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0, 0);
43513426454SMarkus Pargmann }
43613426454SMarkus Pargmann
43713426454SMarkus Pargmann if (ret < 0) {
438dc2c5715SAlison Schofield dev_err(dev, "Error writing reg_int_en0\n");
43913426454SMarkus Pargmann return ret;
44013426454SMarkus Pargmann }
44113426454SMarkus Pargmann
44213426454SMarkus Pargmann return 0;
44313426454SMarkus Pargmann }
44413426454SMarkus Pargmann
bmg160_get_bw(struct bmg160_data * data,int * val)44513426454SMarkus Pargmann static int bmg160_get_bw(struct bmg160_data *data, int *val)
44613426454SMarkus Pargmann {
447bf61f5d2SSteffen Trumtrar struct device *dev = regmap_get_device(data->regmap);
44813426454SMarkus Pargmann int i;
449bf61f5d2SSteffen Trumtrar unsigned int bw_bits;
450bf61f5d2SSteffen Trumtrar int ret;
451bf61f5d2SSteffen Trumtrar
452bf61f5d2SSteffen Trumtrar ret = regmap_read(data->regmap, BMG160_REG_PMU_BW, &bw_bits);
453bf61f5d2SSteffen Trumtrar if (ret < 0) {
454bf61f5d2SSteffen Trumtrar dev_err(dev, "Error reading reg_pmu_bw\n");
455bf61f5d2SSteffen Trumtrar return ret;
456bf61f5d2SSteffen Trumtrar }
457bf61f5d2SSteffen Trumtrar
458bf61f5d2SSteffen Trumtrar /* Ignore the readonly reserved bit. */
459bf61f5d2SSteffen Trumtrar bw_bits &= ~BMG160_REG_PMU_BW_RES;
46013426454SMarkus Pargmann
46113426454SMarkus Pargmann for (i = 0; i < ARRAY_SIZE(bmg160_samp_freq_table); ++i) {
462bf61f5d2SSteffen Trumtrar if (bmg160_samp_freq_table[i].bw_bits == bw_bits) {
463bf61f5d2SSteffen Trumtrar *val = bmg160_samp_freq_table[i].odr;
46413426454SMarkus Pargmann return IIO_VAL_INT;
46513426454SMarkus Pargmann }
46613426454SMarkus Pargmann }
46713426454SMarkus Pargmann
46813426454SMarkus Pargmann return -EINVAL;
46913426454SMarkus Pargmann }
47013426454SMarkus Pargmann
bmg160_set_scale(struct bmg160_data * data,int val)47113426454SMarkus Pargmann static int bmg160_set_scale(struct bmg160_data *data, int val)
47213426454SMarkus Pargmann {
473dc2c5715SAlison Schofield struct device *dev = regmap_get_device(data->regmap);
47413426454SMarkus Pargmann int ret, i;
47513426454SMarkus Pargmann
47613426454SMarkus Pargmann for (i = 0; i < ARRAY_SIZE(bmg160_scale_table); ++i) {
47713426454SMarkus Pargmann if (bmg160_scale_table[i].scale == val) {
47813426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_RANGE,
47913426454SMarkus Pargmann bmg160_scale_table[i].dps_range);
48013426454SMarkus Pargmann if (ret < 0) {
481dc2c5715SAlison Schofield dev_err(dev, "Error writing reg_range\n");
48213426454SMarkus Pargmann return ret;
48313426454SMarkus Pargmann }
48413426454SMarkus Pargmann data->dps_range = bmg160_scale_table[i].dps_range;
48513426454SMarkus Pargmann return 0;
48613426454SMarkus Pargmann }
48713426454SMarkus Pargmann }
48813426454SMarkus Pargmann
48913426454SMarkus Pargmann return -EINVAL;
49013426454SMarkus Pargmann }
49113426454SMarkus Pargmann
bmg160_get_temp(struct bmg160_data * data,int * val)49213426454SMarkus Pargmann static int bmg160_get_temp(struct bmg160_data *data, int *val)
49313426454SMarkus Pargmann {
494dc2c5715SAlison Schofield struct device *dev = regmap_get_device(data->regmap);
49513426454SMarkus Pargmann int ret;
49613426454SMarkus Pargmann unsigned int raw_val;
49713426454SMarkus Pargmann
49813426454SMarkus Pargmann mutex_lock(&data->mutex);
49913426454SMarkus Pargmann ret = bmg160_set_power_state(data, true);
50013426454SMarkus Pargmann if (ret < 0) {
50113426454SMarkus Pargmann mutex_unlock(&data->mutex);
50213426454SMarkus Pargmann return ret;
50313426454SMarkus Pargmann }
50413426454SMarkus Pargmann
50513426454SMarkus Pargmann ret = regmap_read(data->regmap, BMG160_REG_TEMP, &raw_val);
50613426454SMarkus Pargmann if (ret < 0) {
507dc2c5715SAlison Schofield dev_err(dev, "Error reading reg_temp\n");
50813426454SMarkus Pargmann bmg160_set_power_state(data, false);
50913426454SMarkus Pargmann mutex_unlock(&data->mutex);
51013426454SMarkus Pargmann return ret;
51113426454SMarkus Pargmann }
51213426454SMarkus Pargmann
51313426454SMarkus Pargmann *val = sign_extend32(raw_val, 7);
51413426454SMarkus Pargmann ret = bmg160_set_power_state(data, false);
51513426454SMarkus Pargmann mutex_unlock(&data->mutex);
51613426454SMarkus Pargmann if (ret < 0)
51713426454SMarkus Pargmann return ret;
51813426454SMarkus Pargmann
51913426454SMarkus Pargmann return IIO_VAL_INT;
52013426454SMarkus Pargmann }
52113426454SMarkus Pargmann
bmg160_get_axis(struct bmg160_data * data,int axis,int * val)52213426454SMarkus Pargmann static int bmg160_get_axis(struct bmg160_data *data, int axis, int *val)
52313426454SMarkus Pargmann {
524dc2c5715SAlison Schofield struct device *dev = regmap_get_device(data->regmap);
52513426454SMarkus Pargmann int ret;
52695e7ff03SIrina Tirdea __le16 raw_val;
52713426454SMarkus Pargmann
52813426454SMarkus Pargmann mutex_lock(&data->mutex);
52913426454SMarkus Pargmann ret = bmg160_set_power_state(data, true);
53013426454SMarkus Pargmann if (ret < 0) {
53113426454SMarkus Pargmann mutex_unlock(&data->mutex);
53213426454SMarkus Pargmann return ret;
53313426454SMarkus Pargmann }
53413426454SMarkus Pargmann
53513426454SMarkus Pargmann ret = regmap_bulk_read(data->regmap, BMG160_AXIS_TO_REG(axis), &raw_val,
53695e7ff03SIrina Tirdea sizeof(raw_val));
53713426454SMarkus Pargmann if (ret < 0) {
538dc2c5715SAlison Schofield dev_err(dev, "Error reading axis %d\n", axis);
53913426454SMarkus Pargmann bmg160_set_power_state(data, false);
54013426454SMarkus Pargmann mutex_unlock(&data->mutex);
54113426454SMarkus Pargmann return ret;
54213426454SMarkus Pargmann }
54313426454SMarkus Pargmann
54495e7ff03SIrina Tirdea *val = sign_extend32(le16_to_cpu(raw_val), 15);
54513426454SMarkus Pargmann ret = bmg160_set_power_state(data, false);
54613426454SMarkus Pargmann mutex_unlock(&data->mutex);
54713426454SMarkus Pargmann if (ret < 0)
54813426454SMarkus Pargmann return ret;
54913426454SMarkus Pargmann
55013426454SMarkus Pargmann return IIO_VAL_INT;
55113426454SMarkus Pargmann }
55213426454SMarkus Pargmann
bmg160_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)55313426454SMarkus Pargmann static int bmg160_read_raw(struct iio_dev *indio_dev,
55413426454SMarkus Pargmann struct iio_chan_spec const *chan,
55513426454SMarkus Pargmann int *val, int *val2, long mask)
55613426454SMarkus Pargmann {
55713426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
55813426454SMarkus Pargmann int ret;
55913426454SMarkus Pargmann
56013426454SMarkus Pargmann switch (mask) {
56113426454SMarkus Pargmann case IIO_CHAN_INFO_RAW:
56213426454SMarkus Pargmann switch (chan->type) {
56313426454SMarkus Pargmann case IIO_TEMP:
56413426454SMarkus Pargmann return bmg160_get_temp(data, val);
56513426454SMarkus Pargmann case IIO_ANGL_VEL:
56613426454SMarkus Pargmann if (iio_buffer_enabled(indio_dev))
56713426454SMarkus Pargmann return -EBUSY;
56813426454SMarkus Pargmann else
56913426454SMarkus Pargmann return bmg160_get_axis(data, chan->scan_index,
57013426454SMarkus Pargmann val);
57113426454SMarkus Pargmann default:
57213426454SMarkus Pargmann return -EINVAL;
57313426454SMarkus Pargmann }
57413426454SMarkus Pargmann case IIO_CHAN_INFO_OFFSET:
57513426454SMarkus Pargmann if (chan->type == IIO_TEMP) {
57613426454SMarkus Pargmann *val = BMG160_TEMP_CENTER_VAL;
57713426454SMarkus Pargmann return IIO_VAL_INT;
57813426454SMarkus Pargmann } else
57913426454SMarkus Pargmann return -EINVAL;
580bf61f5d2SSteffen Trumtrar case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
581bf61f5d2SSteffen Trumtrar return bmg160_get_filter(data, val);
58213426454SMarkus Pargmann case IIO_CHAN_INFO_SCALE:
58313426454SMarkus Pargmann switch (chan->type) {
58413426454SMarkus Pargmann case IIO_TEMP:
58540a7198aSMike Looijmans *val = 500;
58640a7198aSMike Looijmans return IIO_VAL_INT;
58713426454SMarkus Pargmann case IIO_ANGL_VEL:
58813426454SMarkus Pargmann {
58913426454SMarkus Pargmann int i;
59013426454SMarkus Pargmann
59113426454SMarkus Pargmann for (i = 0; i < ARRAY_SIZE(bmg160_scale_table); ++i) {
59213426454SMarkus Pargmann if (bmg160_scale_table[i].dps_range ==
59313426454SMarkus Pargmann data->dps_range) {
59440a7198aSMike Looijmans *val = 0;
59513426454SMarkus Pargmann *val2 = bmg160_scale_table[i].scale;
59613426454SMarkus Pargmann return IIO_VAL_INT_PLUS_MICRO;
59713426454SMarkus Pargmann }
59813426454SMarkus Pargmann }
59913426454SMarkus Pargmann return -EINVAL;
60013426454SMarkus Pargmann }
60113426454SMarkus Pargmann default:
60213426454SMarkus Pargmann return -EINVAL;
60313426454SMarkus Pargmann }
60413426454SMarkus Pargmann case IIO_CHAN_INFO_SAMP_FREQ:
60513426454SMarkus Pargmann *val2 = 0;
60613426454SMarkus Pargmann mutex_lock(&data->mutex);
60713426454SMarkus Pargmann ret = bmg160_get_bw(data, val);
60813426454SMarkus Pargmann mutex_unlock(&data->mutex);
60913426454SMarkus Pargmann return ret;
61013426454SMarkus Pargmann default:
61113426454SMarkus Pargmann return -EINVAL;
61213426454SMarkus Pargmann }
61313426454SMarkus Pargmann }
61413426454SMarkus Pargmann
bmg160_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)61513426454SMarkus Pargmann static int bmg160_write_raw(struct iio_dev *indio_dev,
61613426454SMarkus Pargmann struct iio_chan_spec const *chan,
61713426454SMarkus Pargmann int val, int val2, long mask)
61813426454SMarkus Pargmann {
61913426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
62013426454SMarkus Pargmann int ret;
62113426454SMarkus Pargmann
62213426454SMarkus Pargmann switch (mask) {
62313426454SMarkus Pargmann case IIO_CHAN_INFO_SAMP_FREQ:
62413426454SMarkus Pargmann mutex_lock(&data->mutex);
62513426454SMarkus Pargmann /*
62613426454SMarkus Pargmann * Section 4.2 of spec
62713426454SMarkus Pargmann * In suspend mode, the only supported operations are reading
62813426454SMarkus Pargmann * registers as well as writing to the (0x14) softreset
62913426454SMarkus Pargmann * register. Since we will be in suspend mode by default, change
63013426454SMarkus Pargmann * mode to power on for other writes.
63113426454SMarkus Pargmann */
63213426454SMarkus Pargmann ret = bmg160_set_power_state(data, true);
63313426454SMarkus Pargmann if (ret < 0) {
63413426454SMarkus Pargmann mutex_unlock(&data->mutex);
63513426454SMarkus Pargmann return ret;
63613426454SMarkus Pargmann }
63713426454SMarkus Pargmann ret = bmg160_set_bw(data, val);
63813426454SMarkus Pargmann if (ret < 0) {
63913426454SMarkus Pargmann bmg160_set_power_state(data, false);
64013426454SMarkus Pargmann mutex_unlock(&data->mutex);
64113426454SMarkus Pargmann return ret;
64213426454SMarkus Pargmann }
64313426454SMarkus Pargmann ret = bmg160_set_power_state(data, false);
64413426454SMarkus Pargmann mutex_unlock(&data->mutex);
64513426454SMarkus Pargmann return ret;
646bf61f5d2SSteffen Trumtrar case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
647bf61f5d2SSteffen Trumtrar if (val2)
648bf61f5d2SSteffen Trumtrar return -EINVAL;
649bf61f5d2SSteffen Trumtrar
650bf61f5d2SSteffen Trumtrar mutex_lock(&data->mutex);
651bf61f5d2SSteffen Trumtrar ret = bmg160_set_power_state(data, true);
652bf61f5d2SSteffen Trumtrar if (ret < 0) {
653bf61f5d2SSteffen Trumtrar bmg160_set_power_state(data, false);
654bf61f5d2SSteffen Trumtrar mutex_unlock(&data->mutex);
655bf61f5d2SSteffen Trumtrar return ret;
656bf61f5d2SSteffen Trumtrar }
657bf61f5d2SSteffen Trumtrar ret = bmg160_set_filter(data, val);
658bf61f5d2SSteffen Trumtrar if (ret < 0) {
659bf61f5d2SSteffen Trumtrar bmg160_set_power_state(data, false);
660bf61f5d2SSteffen Trumtrar mutex_unlock(&data->mutex);
661bf61f5d2SSteffen Trumtrar return ret;
662bf61f5d2SSteffen Trumtrar }
663bf61f5d2SSteffen Trumtrar ret = bmg160_set_power_state(data, false);
664bf61f5d2SSteffen Trumtrar mutex_unlock(&data->mutex);
665bf61f5d2SSteffen Trumtrar return ret;
66613426454SMarkus Pargmann case IIO_CHAN_INFO_SCALE:
66713426454SMarkus Pargmann if (val)
66813426454SMarkus Pargmann return -EINVAL;
66913426454SMarkus Pargmann
67013426454SMarkus Pargmann mutex_lock(&data->mutex);
67113426454SMarkus Pargmann /* Refer to comments above for the suspend mode ops */
67213426454SMarkus Pargmann ret = bmg160_set_power_state(data, true);
67313426454SMarkus Pargmann if (ret < 0) {
67413426454SMarkus Pargmann mutex_unlock(&data->mutex);
67513426454SMarkus Pargmann return ret;
67613426454SMarkus Pargmann }
67713426454SMarkus Pargmann ret = bmg160_set_scale(data, val2);
67813426454SMarkus Pargmann if (ret < 0) {
67913426454SMarkus Pargmann bmg160_set_power_state(data, false);
68013426454SMarkus Pargmann mutex_unlock(&data->mutex);
68113426454SMarkus Pargmann return ret;
68213426454SMarkus Pargmann }
68313426454SMarkus Pargmann ret = bmg160_set_power_state(data, false);
68413426454SMarkus Pargmann mutex_unlock(&data->mutex);
68513426454SMarkus Pargmann return ret;
68613426454SMarkus Pargmann default:
68713426454SMarkus Pargmann return -EINVAL;
68813426454SMarkus Pargmann }
68913426454SMarkus Pargmann
69013426454SMarkus Pargmann return -EINVAL;
69113426454SMarkus Pargmann }
69213426454SMarkus Pargmann
bmg160_read_event(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int * val,int * val2)69313426454SMarkus Pargmann static int bmg160_read_event(struct iio_dev *indio_dev,
69413426454SMarkus Pargmann const struct iio_chan_spec *chan,
69513426454SMarkus Pargmann enum iio_event_type type,
69613426454SMarkus Pargmann enum iio_event_direction dir,
69713426454SMarkus Pargmann enum iio_event_info info,
69813426454SMarkus Pargmann int *val, int *val2)
69913426454SMarkus Pargmann {
70013426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
70113426454SMarkus Pargmann
70213426454SMarkus Pargmann *val2 = 0;
70313426454SMarkus Pargmann switch (info) {
70413426454SMarkus Pargmann case IIO_EV_INFO_VALUE:
70513426454SMarkus Pargmann *val = data->slope_thres & BMG160_SLOPE_THRES_MASK;
70613426454SMarkus Pargmann break;
70713426454SMarkus Pargmann default:
70813426454SMarkus Pargmann return -EINVAL;
70913426454SMarkus Pargmann }
71013426454SMarkus Pargmann
71113426454SMarkus Pargmann return IIO_VAL_INT;
71213426454SMarkus Pargmann }
71313426454SMarkus Pargmann
bmg160_write_event(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int val,int val2)71413426454SMarkus Pargmann static int bmg160_write_event(struct iio_dev *indio_dev,
71513426454SMarkus Pargmann const struct iio_chan_spec *chan,
71613426454SMarkus Pargmann enum iio_event_type type,
71713426454SMarkus Pargmann enum iio_event_direction dir,
71813426454SMarkus Pargmann enum iio_event_info info,
71913426454SMarkus Pargmann int val, int val2)
72013426454SMarkus Pargmann {
72113426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
72213426454SMarkus Pargmann
72313426454SMarkus Pargmann switch (info) {
72413426454SMarkus Pargmann case IIO_EV_INFO_VALUE:
72513426454SMarkus Pargmann if (data->ev_enable_state)
72613426454SMarkus Pargmann return -EBUSY;
72713426454SMarkus Pargmann data->slope_thres &= ~BMG160_SLOPE_THRES_MASK;
72813426454SMarkus Pargmann data->slope_thres |= (val & BMG160_SLOPE_THRES_MASK);
72913426454SMarkus Pargmann break;
73013426454SMarkus Pargmann default:
73113426454SMarkus Pargmann return -EINVAL;
73213426454SMarkus Pargmann }
73313426454SMarkus Pargmann
73413426454SMarkus Pargmann return 0;
73513426454SMarkus Pargmann }
73613426454SMarkus Pargmann
bmg160_read_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir)73713426454SMarkus Pargmann static int bmg160_read_event_config(struct iio_dev *indio_dev,
73813426454SMarkus Pargmann const struct iio_chan_spec *chan,
73913426454SMarkus Pargmann enum iio_event_type type,
74013426454SMarkus Pargmann enum iio_event_direction dir)
74113426454SMarkus Pargmann {
74213426454SMarkus Pargmann
74313426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
74413426454SMarkus Pargmann
74513426454SMarkus Pargmann return data->ev_enable_state;
74613426454SMarkus Pargmann }
74713426454SMarkus Pargmann
bmg160_write_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,int state)74813426454SMarkus Pargmann static int bmg160_write_event_config(struct iio_dev *indio_dev,
74913426454SMarkus Pargmann const struct iio_chan_spec *chan,
75013426454SMarkus Pargmann enum iio_event_type type,
75113426454SMarkus Pargmann enum iio_event_direction dir,
75213426454SMarkus Pargmann int state)
75313426454SMarkus Pargmann {
75413426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
75513426454SMarkus Pargmann int ret;
75613426454SMarkus Pargmann
75713426454SMarkus Pargmann if (state && data->ev_enable_state)
75813426454SMarkus Pargmann return 0;
75913426454SMarkus Pargmann
76013426454SMarkus Pargmann mutex_lock(&data->mutex);
76113426454SMarkus Pargmann
76213426454SMarkus Pargmann if (!state && data->motion_trigger_on) {
76313426454SMarkus Pargmann data->ev_enable_state = 0;
76413426454SMarkus Pargmann mutex_unlock(&data->mutex);
76513426454SMarkus Pargmann return 0;
76613426454SMarkus Pargmann }
76713426454SMarkus Pargmann /*
7687f467484SXiang wangx * We will expect the enable and disable to do operation
76913426454SMarkus Pargmann * in reverse order. This will happen here anyway as our
77013426454SMarkus Pargmann * resume operation uses sync mode runtime pm calls, the
77113426454SMarkus Pargmann * suspend operation will be delayed by autosuspend delay
77213426454SMarkus Pargmann * So the disable operation will still happen in reverse of
77313426454SMarkus Pargmann * enable operation. When runtime pm is disabled the mode
77413426454SMarkus Pargmann * is always on so sequence doesn't matter
77513426454SMarkus Pargmann */
77613426454SMarkus Pargmann ret = bmg160_set_power_state(data, state);
77713426454SMarkus Pargmann if (ret < 0) {
77813426454SMarkus Pargmann mutex_unlock(&data->mutex);
77913426454SMarkus Pargmann return ret;
78013426454SMarkus Pargmann }
78113426454SMarkus Pargmann
78213426454SMarkus Pargmann ret = bmg160_setup_any_motion_interrupt(data, state);
78313426454SMarkus Pargmann if (ret < 0) {
78413426454SMarkus Pargmann bmg160_set_power_state(data, false);
78513426454SMarkus Pargmann mutex_unlock(&data->mutex);
78613426454SMarkus Pargmann return ret;
78713426454SMarkus Pargmann }
78813426454SMarkus Pargmann
78913426454SMarkus Pargmann data->ev_enable_state = state;
79013426454SMarkus Pargmann mutex_unlock(&data->mutex);
79113426454SMarkus Pargmann
79213426454SMarkus Pargmann return 0;
79313426454SMarkus Pargmann }
79413426454SMarkus Pargmann
7953a6049f6SH. Nikolaus Schaller static const struct iio_mount_matrix *
bmg160_get_mount_matrix(const struct iio_dev * indio_dev,const struct iio_chan_spec * chan)7963a6049f6SH. Nikolaus Schaller bmg160_get_mount_matrix(const struct iio_dev *indio_dev,
7973a6049f6SH. Nikolaus Schaller const struct iio_chan_spec *chan)
7983a6049f6SH. Nikolaus Schaller {
7993a6049f6SH. Nikolaus Schaller struct bmg160_data *data = iio_priv(indio_dev);
8003a6049f6SH. Nikolaus Schaller
8013a6049f6SH. Nikolaus Schaller return &data->orientation;
8023a6049f6SH. Nikolaus Schaller }
8033a6049f6SH. Nikolaus Schaller
8043a6049f6SH. Nikolaus Schaller static const struct iio_chan_spec_ext_info bmg160_ext_info[] = {
8053a6049f6SH. Nikolaus Schaller IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bmg160_get_mount_matrix),
8063a6049f6SH. Nikolaus Schaller { }
8073a6049f6SH. Nikolaus Schaller };
8083a6049f6SH. Nikolaus Schaller
80913426454SMarkus Pargmann static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 400 1000 2000");
81013426454SMarkus Pargmann
81113426454SMarkus Pargmann static IIO_CONST_ATTR(in_anglvel_scale_available,
81213426454SMarkus Pargmann "0.001065 0.000532 0.000266 0.000133 0.000066");
81313426454SMarkus Pargmann
81413426454SMarkus Pargmann static struct attribute *bmg160_attributes[] = {
81513426454SMarkus Pargmann &iio_const_attr_sampling_frequency_available.dev_attr.attr,
81613426454SMarkus Pargmann &iio_const_attr_in_anglvel_scale_available.dev_attr.attr,
81713426454SMarkus Pargmann NULL,
81813426454SMarkus Pargmann };
81913426454SMarkus Pargmann
82013426454SMarkus Pargmann static const struct attribute_group bmg160_attrs_group = {
82113426454SMarkus Pargmann .attrs = bmg160_attributes,
82213426454SMarkus Pargmann };
82313426454SMarkus Pargmann
82413426454SMarkus Pargmann static const struct iio_event_spec bmg160_event = {
82513426454SMarkus Pargmann .type = IIO_EV_TYPE_ROC,
82613426454SMarkus Pargmann .dir = IIO_EV_DIR_EITHER,
82713426454SMarkus Pargmann .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
82813426454SMarkus Pargmann BIT(IIO_EV_INFO_ENABLE)
82913426454SMarkus Pargmann };
83013426454SMarkus Pargmann
83113426454SMarkus Pargmann #define BMG160_CHANNEL(_axis) { \
83213426454SMarkus Pargmann .type = IIO_ANGL_VEL, \
83313426454SMarkus Pargmann .modified = 1, \
83413426454SMarkus Pargmann .channel2 = IIO_MOD_##_axis, \
83513426454SMarkus Pargmann .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
83613426454SMarkus Pargmann .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
837bf61f5d2SSteffen Trumtrar BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
838bf61f5d2SSteffen Trumtrar BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
83913426454SMarkus Pargmann .scan_index = AXIS_##_axis, \
84013426454SMarkus Pargmann .scan_type = { \
84113426454SMarkus Pargmann .sign = 's', \
84213426454SMarkus Pargmann .realbits = 16, \
84313426454SMarkus Pargmann .storagebits = 16, \
8447e3d1eb1SIrina Tirdea .endianness = IIO_LE, \
84513426454SMarkus Pargmann }, \
8463a6049f6SH. Nikolaus Schaller .ext_info = bmg160_ext_info, \
84713426454SMarkus Pargmann .event_spec = &bmg160_event, \
84813426454SMarkus Pargmann .num_event_specs = 1 \
84913426454SMarkus Pargmann }
85013426454SMarkus Pargmann
85113426454SMarkus Pargmann static const struct iio_chan_spec bmg160_channels[] = {
85213426454SMarkus Pargmann {
85313426454SMarkus Pargmann .type = IIO_TEMP,
85413426454SMarkus Pargmann .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
85513426454SMarkus Pargmann BIT(IIO_CHAN_INFO_SCALE) |
85613426454SMarkus Pargmann BIT(IIO_CHAN_INFO_OFFSET),
85713426454SMarkus Pargmann .scan_index = -1,
85813426454SMarkus Pargmann },
85913426454SMarkus Pargmann BMG160_CHANNEL(X),
86013426454SMarkus Pargmann BMG160_CHANNEL(Y),
86113426454SMarkus Pargmann BMG160_CHANNEL(Z),
86213426454SMarkus Pargmann IIO_CHAN_SOFT_TIMESTAMP(3),
86313426454SMarkus Pargmann };
86413426454SMarkus Pargmann
86513426454SMarkus Pargmann static const struct iio_info bmg160_info = {
86613426454SMarkus Pargmann .attrs = &bmg160_attrs_group,
86713426454SMarkus Pargmann .read_raw = bmg160_read_raw,
86813426454SMarkus Pargmann .write_raw = bmg160_write_raw,
86913426454SMarkus Pargmann .read_event_value = bmg160_read_event,
87013426454SMarkus Pargmann .write_event_value = bmg160_write_event,
87113426454SMarkus Pargmann .write_event_config = bmg160_write_event_config,
87213426454SMarkus Pargmann .read_event_config = bmg160_read_event_config,
87313426454SMarkus Pargmann };
87413426454SMarkus Pargmann
875ee8c5419SIrina Tirdea static const unsigned long bmg160_accel_scan_masks[] = {
876ee8c5419SIrina Tirdea BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
877ee8c5419SIrina Tirdea 0};
878ee8c5419SIrina Tirdea
bmg160_trigger_handler(int irq,void * p)87913426454SMarkus Pargmann static irqreturn_t bmg160_trigger_handler(int irq, void *p)
88013426454SMarkus Pargmann {
88113426454SMarkus Pargmann struct iio_poll_func *pf = p;
88213426454SMarkus Pargmann struct iio_dev *indio_dev = pf->indio_dev;
88313426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
8847e3d1eb1SIrina Tirdea int ret;
88513426454SMarkus Pargmann
88613426454SMarkus Pargmann mutex_lock(&data->mutex);
8877e3d1eb1SIrina Tirdea ret = regmap_bulk_read(data->regmap, BMG160_REG_XOUT_L,
88806778d88SJonathan Cameron data->scan.chans, AXIS_MAX * 2);
88913426454SMarkus Pargmann mutex_unlock(&data->mutex);
8907e3d1eb1SIrina Tirdea if (ret < 0)
89113426454SMarkus Pargmann goto err;
89213426454SMarkus Pargmann
89306778d88SJonathan Cameron iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
89413426454SMarkus Pargmann pf->timestamp);
89513426454SMarkus Pargmann err:
89613426454SMarkus Pargmann iio_trigger_notify_done(indio_dev->trig);
89713426454SMarkus Pargmann
89813426454SMarkus Pargmann return IRQ_HANDLED;
89913426454SMarkus Pargmann }
90013426454SMarkus Pargmann
bmg160_trig_reen(struct iio_trigger * trig)901eca8523aSJonathan Cameron static void bmg160_trig_reen(struct iio_trigger *trig)
90213426454SMarkus Pargmann {
90313426454SMarkus Pargmann struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
90413426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
905dc2c5715SAlison Schofield struct device *dev = regmap_get_device(data->regmap);
90613426454SMarkus Pargmann int ret;
90713426454SMarkus Pargmann
90813426454SMarkus Pargmann /* new data interrupts don't need ack */
90913426454SMarkus Pargmann if (data->dready_trigger_on)
910eca8523aSJonathan Cameron return;
91113426454SMarkus Pargmann
91213426454SMarkus Pargmann /* Set latched mode interrupt and clear any latched interrupt */
91313426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH,
91413426454SMarkus Pargmann BMG160_INT_MODE_LATCH_INT |
91513426454SMarkus Pargmann BMG160_INT_MODE_LATCH_RESET);
916eca8523aSJonathan Cameron if (ret < 0)
917dc2c5715SAlison Schofield dev_err(dev, "Error writing reg_rst_latch\n");
91813426454SMarkus Pargmann }
91913426454SMarkus Pargmann
bmg160_data_rdy_trigger_set_state(struct iio_trigger * trig,bool state)92013426454SMarkus Pargmann static int bmg160_data_rdy_trigger_set_state(struct iio_trigger *trig,
92113426454SMarkus Pargmann bool state)
92213426454SMarkus Pargmann {
92313426454SMarkus Pargmann struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
92413426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
92513426454SMarkus Pargmann int ret;
92613426454SMarkus Pargmann
92713426454SMarkus Pargmann mutex_lock(&data->mutex);
92813426454SMarkus Pargmann
92913426454SMarkus Pargmann if (!state && data->ev_enable_state && data->motion_trigger_on) {
93013426454SMarkus Pargmann data->motion_trigger_on = false;
93113426454SMarkus Pargmann mutex_unlock(&data->mutex);
93213426454SMarkus Pargmann return 0;
93313426454SMarkus Pargmann }
93413426454SMarkus Pargmann
93513426454SMarkus Pargmann /*
93613426454SMarkus Pargmann * Refer to comment in bmg160_write_event_config for
93713426454SMarkus Pargmann * enable/disable operation order
93813426454SMarkus Pargmann */
93913426454SMarkus Pargmann ret = bmg160_set_power_state(data, state);
94013426454SMarkus Pargmann if (ret < 0) {
94113426454SMarkus Pargmann mutex_unlock(&data->mutex);
94213426454SMarkus Pargmann return ret;
94313426454SMarkus Pargmann }
94413426454SMarkus Pargmann if (data->motion_trig == trig)
94513426454SMarkus Pargmann ret = bmg160_setup_any_motion_interrupt(data, state);
94613426454SMarkus Pargmann else
94713426454SMarkus Pargmann ret = bmg160_setup_new_data_interrupt(data, state);
94813426454SMarkus Pargmann if (ret < 0) {
94913426454SMarkus Pargmann bmg160_set_power_state(data, false);
95013426454SMarkus Pargmann mutex_unlock(&data->mutex);
95113426454SMarkus Pargmann return ret;
95213426454SMarkus Pargmann }
95313426454SMarkus Pargmann if (data->motion_trig == trig)
95413426454SMarkus Pargmann data->motion_trigger_on = state;
95513426454SMarkus Pargmann else
95613426454SMarkus Pargmann data->dready_trigger_on = state;
95713426454SMarkus Pargmann
95813426454SMarkus Pargmann mutex_unlock(&data->mutex);
95913426454SMarkus Pargmann
96013426454SMarkus Pargmann return 0;
96113426454SMarkus Pargmann }
96213426454SMarkus Pargmann
96313426454SMarkus Pargmann static const struct iio_trigger_ops bmg160_trigger_ops = {
96413426454SMarkus Pargmann .set_trigger_state = bmg160_data_rdy_trigger_set_state,
965eca8523aSJonathan Cameron .reenable = bmg160_trig_reen,
96613426454SMarkus Pargmann };
96713426454SMarkus Pargmann
bmg160_event_handler(int irq,void * private)96813426454SMarkus Pargmann static irqreturn_t bmg160_event_handler(int irq, void *private)
96913426454SMarkus Pargmann {
97013426454SMarkus Pargmann struct iio_dev *indio_dev = private;
97113426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
972dc2c5715SAlison Schofield struct device *dev = regmap_get_device(data->regmap);
97313426454SMarkus Pargmann int ret;
97413426454SMarkus Pargmann int dir;
97513426454SMarkus Pargmann unsigned int val;
97613426454SMarkus Pargmann
97713426454SMarkus Pargmann ret = regmap_read(data->regmap, BMG160_REG_INT_STATUS_2, &val);
97813426454SMarkus Pargmann if (ret < 0) {
979dc2c5715SAlison Schofield dev_err(dev, "Error reading reg_int_status2\n");
98013426454SMarkus Pargmann goto ack_intr_status;
98113426454SMarkus Pargmann }
98213426454SMarkus Pargmann
98313426454SMarkus Pargmann if (val & 0x08)
98413426454SMarkus Pargmann dir = IIO_EV_DIR_RISING;
98513426454SMarkus Pargmann else
98613426454SMarkus Pargmann dir = IIO_EV_DIR_FALLING;
98713426454SMarkus Pargmann
98813426454SMarkus Pargmann if (val & BMG160_ANY_MOTION_BIT_X)
98913426454SMarkus Pargmann iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL,
99013426454SMarkus Pargmann 0,
99113426454SMarkus Pargmann IIO_MOD_X,
99213426454SMarkus Pargmann IIO_EV_TYPE_ROC,
99313426454SMarkus Pargmann dir),
994bc2b7dabSGregor Boirie iio_get_time_ns(indio_dev));
99513426454SMarkus Pargmann if (val & BMG160_ANY_MOTION_BIT_Y)
99613426454SMarkus Pargmann iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL,
99713426454SMarkus Pargmann 0,
99813426454SMarkus Pargmann IIO_MOD_Y,
99913426454SMarkus Pargmann IIO_EV_TYPE_ROC,
100013426454SMarkus Pargmann dir),
1001bc2b7dabSGregor Boirie iio_get_time_ns(indio_dev));
100213426454SMarkus Pargmann if (val & BMG160_ANY_MOTION_BIT_Z)
100313426454SMarkus Pargmann iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL,
100413426454SMarkus Pargmann 0,
100513426454SMarkus Pargmann IIO_MOD_Z,
100613426454SMarkus Pargmann IIO_EV_TYPE_ROC,
100713426454SMarkus Pargmann dir),
1008bc2b7dabSGregor Boirie iio_get_time_ns(indio_dev));
100913426454SMarkus Pargmann
101013426454SMarkus Pargmann ack_intr_status:
101113426454SMarkus Pargmann if (!data->dready_trigger_on) {
101213426454SMarkus Pargmann ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH,
101313426454SMarkus Pargmann BMG160_INT_MODE_LATCH_INT |
101413426454SMarkus Pargmann BMG160_INT_MODE_LATCH_RESET);
101513426454SMarkus Pargmann if (ret < 0)
1016dc2c5715SAlison Schofield dev_err(dev, "Error writing reg_rst_latch\n");
101713426454SMarkus Pargmann }
101813426454SMarkus Pargmann
101913426454SMarkus Pargmann return IRQ_HANDLED;
102013426454SMarkus Pargmann }
102113426454SMarkus Pargmann
bmg160_data_rdy_trig_poll(int irq,void * private)102213426454SMarkus Pargmann static irqreturn_t bmg160_data_rdy_trig_poll(int irq, void *private)
102313426454SMarkus Pargmann {
102413426454SMarkus Pargmann struct iio_dev *indio_dev = private;
102513426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
102613426454SMarkus Pargmann
102713426454SMarkus Pargmann if (data->dready_trigger_on)
102813426454SMarkus Pargmann iio_trigger_poll(data->dready_trig);
102913426454SMarkus Pargmann else if (data->motion_trigger_on)
103013426454SMarkus Pargmann iio_trigger_poll(data->motion_trig);
103113426454SMarkus Pargmann
103213426454SMarkus Pargmann if (data->ev_enable_state)
103313426454SMarkus Pargmann return IRQ_WAKE_THREAD;
103413426454SMarkus Pargmann else
103513426454SMarkus Pargmann return IRQ_HANDLED;
103613426454SMarkus Pargmann
103713426454SMarkus Pargmann }
103813426454SMarkus Pargmann
bmg160_buffer_preenable(struct iio_dev * indio_dev)103913426454SMarkus Pargmann static int bmg160_buffer_preenable(struct iio_dev *indio_dev)
104013426454SMarkus Pargmann {
104113426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
104213426454SMarkus Pargmann
104313426454SMarkus Pargmann return bmg160_set_power_state(data, true);
104413426454SMarkus Pargmann }
104513426454SMarkus Pargmann
bmg160_buffer_postdisable(struct iio_dev * indio_dev)104613426454SMarkus Pargmann static int bmg160_buffer_postdisable(struct iio_dev *indio_dev)
104713426454SMarkus Pargmann {
104813426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
104913426454SMarkus Pargmann
105013426454SMarkus Pargmann return bmg160_set_power_state(data, false);
105113426454SMarkus Pargmann }
105213426454SMarkus Pargmann
105313426454SMarkus Pargmann static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = {
105413426454SMarkus Pargmann .preenable = bmg160_buffer_preenable,
105513426454SMarkus Pargmann .postdisable = bmg160_buffer_postdisable,
105613426454SMarkus Pargmann };
105713426454SMarkus Pargmann
bmg160_match_acpi_device(struct device * dev)105813426454SMarkus Pargmann static const char *bmg160_match_acpi_device(struct device *dev)
105913426454SMarkus Pargmann {
106013426454SMarkus Pargmann const struct acpi_device_id *id;
106113426454SMarkus Pargmann
106213426454SMarkus Pargmann id = acpi_match_device(dev->driver->acpi_match_table, dev);
106313426454SMarkus Pargmann if (!id)
106413426454SMarkus Pargmann return NULL;
106513426454SMarkus Pargmann
106613426454SMarkus Pargmann return dev_name(dev);
106713426454SMarkus Pargmann }
106813426454SMarkus Pargmann
bmg160_core_probe(struct device * dev,struct regmap * regmap,int irq,const char * name)106913426454SMarkus Pargmann int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
107013426454SMarkus Pargmann const char *name)
107113426454SMarkus Pargmann {
1072*2c620883SMatti Vaittinen static const char * const regulators[] = { "vdd", "vddio" };
107313426454SMarkus Pargmann struct bmg160_data *data;
107413426454SMarkus Pargmann struct iio_dev *indio_dev;
107513426454SMarkus Pargmann int ret;
107613426454SMarkus Pargmann
107713426454SMarkus Pargmann indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
107813426454SMarkus Pargmann if (!indio_dev)
107913426454SMarkus Pargmann return -ENOMEM;
108013426454SMarkus Pargmann
108113426454SMarkus Pargmann data = iio_priv(indio_dev);
108213426454SMarkus Pargmann dev_set_drvdata(dev, indio_dev);
108313426454SMarkus Pargmann data->irq = irq;
108413426454SMarkus Pargmann data->regmap = regmap;
108513426454SMarkus Pargmann
1086*2c620883SMatti Vaittinen ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulators),
1087*2c620883SMatti Vaittinen regulators);
1088ce69361aSStephan Gerhold if (ret)
1089ce69361aSStephan Gerhold return dev_err_probe(dev, ret, "Failed to get regulators\n");
1090ce69361aSStephan Gerhold
1091b892770aSAndy Shevchenko ret = iio_read_mount_matrix(dev, &data->orientation);
10923a6049f6SH. Nikolaus Schaller if (ret)
10933a6049f6SH. Nikolaus Schaller return ret;
10943a6049f6SH. Nikolaus Schaller
109513426454SMarkus Pargmann ret = bmg160_chip_init(data);
109613426454SMarkus Pargmann if (ret < 0)
109713426454SMarkus Pargmann return ret;
109813426454SMarkus Pargmann
109913426454SMarkus Pargmann mutex_init(&data->mutex);
110013426454SMarkus Pargmann
110113426454SMarkus Pargmann if (ACPI_HANDLE(dev))
110213426454SMarkus Pargmann name = bmg160_match_acpi_device(dev);
110313426454SMarkus Pargmann
110413426454SMarkus Pargmann indio_dev->channels = bmg160_channels;
110513426454SMarkus Pargmann indio_dev->num_channels = ARRAY_SIZE(bmg160_channels);
110613426454SMarkus Pargmann indio_dev->name = name;
1107ee8c5419SIrina Tirdea indio_dev->available_scan_masks = bmg160_accel_scan_masks;
110813426454SMarkus Pargmann indio_dev->modes = INDIO_DIRECT_MODE;
110913426454SMarkus Pargmann indio_dev->info = &bmg160_info;
111013426454SMarkus Pargmann
111113426454SMarkus Pargmann if (data->irq > 0) {
111213426454SMarkus Pargmann ret = devm_request_threaded_irq(dev,
111313426454SMarkus Pargmann data->irq,
111413426454SMarkus Pargmann bmg160_data_rdy_trig_poll,
111513426454SMarkus Pargmann bmg160_event_handler,
111613426454SMarkus Pargmann IRQF_TRIGGER_RISING,
111713426454SMarkus Pargmann BMG160_IRQ_NAME,
111813426454SMarkus Pargmann indio_dev);
111913426454SMarkus Pargmann if (ret)
112013426454SMarkus Pargmann return ret;
112113426454SMarkus Pargmann
112213426454SMarkus Pargmann data->dready_trig = devm_iio_trigger_alloc(dev,
112313426454SMarkus Pargmann "%s-dev%d",
112413426454SMarkus Pargmann indio_dev->name,
112515ea2878SJonathan Cameron iio_device_id(indio_dev));
112613426454SMarkus Pargmann if (!data->dready_trig)
112713426454SMarkus Pargmann return -ENOMEM;
112813426454SMarkus Pargmann
112913426454SMarkus Pargmann data->motion_trig = devm_iio_trigger_alloc(dev,
113013426454SMarkus Pargmann "%s-any-motion-dev%d",
113113426454SMarkus Pargmann indio_dev->name,
113215ea2878SJonathan Cameron iio_device_id(indio_dev));
113313426454SMarkus Pargmann if (!data->motion_trig)
113413426454SMarkus Pargmann return -ENOMEM;
113513426454SMarkus Pargmann
113613426454SMarkus Pargmann data->dready_trig->ops = &bmg160_trigger_ops;
113713426454SMarkus Pargmann iio_trigger_set_drvdata(data->dready_trig, indio_dev);
113813426454SMarkus Pargmann ret = iio_trigger_register(data->dready_trig);
113913426454SMarkus Pargmann if (ret)
114013426454SMarkus Pargmann return ret;
114113426454SMarkus Pargmann
114213426454SMarkus Pargmann data->motion_trig->ops = &bmg160_trigger_ops;
114313426454SMarkus Pargmann iio_trigger_set_drvdata(data->motion_trig, indio_dev);
114413426454SMarkus Pargmann ret = iio_trigger_register(data->motion_trig);
114513426454SMarkus Pargmann if (ret) {
114613426454SMarkus Pargmann data->motion_trig = NULL;
114713426454SMarkus Pargmann goto err_trigger_unregister;
114813426454SMarkus Pargmann }
114913426454SMarkus Pargmann }
115013426454SMarkus Pargmann
115113426454SMarkus Pargmann ret = iio_triggered_buffer_setup(indio_dev,
115213426454SMarkus Pargmann iio_pollfunc_store_time,
115313426454SMarkus Pargmann bmg160_trigger_handler,
115413426454SMarkus Pargmann &bmg160_buffer_setup_ops);
115513426454SMarkus Pargmann if (ret < 0) {
115613426454SMarkus Pargmann dev_err(dev,
115713426454SMarkus Pargmann "iio triggered buffer setup failed\n");
115813426454SMarkus Pargmann goto err_trigger_unregister;
115913426454SMarkus Pargmann }
116013426454SMarkus Pargmann
116113426454SMarkus Pargmann ret = pm_runtime_set_active(dev);
116213426454SMarkus Pargmann if (ret)
11637d0ead5cSAdriana Reus goto err_buffer_cleanup;
116413426454SMarkus Pargmann
116513426454SMarkus Pargmann pm_runtime_enable(dev);
116613426454SMarkus Pargmann pm_runtime_set_autosuspend_delay(dev,
116713426454SMarkus Pargmann BMG160_AUTO_SUSPEND_DELAY_MS);
116813426454SMarkus Pargmann pm_runtime_use_autosuspend(dev);
116913426454SMarkus Pargmann
11707d0ead5cSAdriana Reus ret = iio_device_register(indio_dev);
11717d0ead5cSAdriana Reus if (ret < 0) {
11727d0ead5cSAdriana Reus dev_err(dev, "unable to register iio device\n");
1173632fe0bbSMiaoqian Lin goto err_pm_cleanup;
11747d0ead5cSAdriana Reus }
11757d0ead5cSAdriana Reus
117613426454SMarkus Pargmann return 0;
117713426454SMarkus Pargmann
1178632fe0bbSMiaoqian Lin err_pm_cleanup:
1179632fe0bbSMiaoqian Lin pm_runtime_dont_use_autosuspend(dev);
1180632fe0bbSMiaoqian Lin pm_runtime_disable(dev);
118113426454SMarkus Pargmann err_buffer_cleanup:
118213426454SMarkus Pargmann iio_triggered_buffer_cleanup(indio_dev);
118313426454SMarkus Pargmann err_trigger_unregister:
118413426454SMarkus Pargmann if (data->dready_trig)
118513426454SMarkus Pargmann iio_trigger_unregister(data->dready_trig);
118613426454SMarkus Pargmann if (data->motion_trig)
118713426454SMarkus Pargmann iio_trigger_unregister(data->motion_trig);
118813426454SMarkus Pargmann
118913426454SMarkus Pargmann return ret;
119013426454SMarkus Pargmann }
119113426454SMarkus Pargmann EXPORT_SYMBOL_GPL(bmg160_core_probe);
119213426454SMarkus Pargmann
bmg160_core_remove(struct device * dev)119313426454SMarkus Pargmann void bmg160_core_remove(struct device *dev)
119413426454SMarkus Pargmann {
119513426454SMarkus Pargmann struct iio_dev *indio_dev = dev_get_drvdata(dev);
119613426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
119713426454SMarkus Pargmann
11987d0ead5cSAdriana Reus iio_device_unregister(indio_dev);
11997d0ead5cSAdriana Reus
120013426454SMarkus Pargmann pm_runtime_disable(dev);
120113426454SMarkus Pargmann pm_runtime_set_suspended(dev);
120213426454SMarkus Pargmann pm_runtime_put_noidle(dev);
120313426454SMarkus Pargmann
120413426454SMarkus Pargmann iio_triggered_buffer_cleanup(indio_dev);
120513426454SMarkus Pargmann
120613426454SMarkus Pargmann if (data->dready_trig) {
120713426454SMarkus Pargmann iio_trigger_unregister(data->dready_trig);
120813426454SMarkus Pargmann iio_trigger_unregister(data->motion_trig);
120913426454SMarkus Pargmann }
121013426454SMarkus Pargmann
121113426454SMarkus Pargmann mutex_lock(&data->mutex);
121213426454SMarkus Pargmann bmg160_set_mode(data, BMG160_MODE_DEEP_SUSPEND);
121313426454SMarkus Pargmann mutex_unlock(&data->mutex);
121413426454SMarkus Pargmann }
121513426454SMarkus Pargmann EXPORT_SYMBOL_GPL(bmg160_core_remove);
121613426454SMarkus Pargmann
121713426454SMarkus Pargmann #ifdef CONFIG_PM_SLEEP
bmg160_suspend(struct device * dev)121813426454SMarkus Pargmann static int bmg160_suspend(struct device *dev)
121913426454SMarkus Pargmann {
122013426454SMarkus Pargmann struct iio_dev *indio_dev = dev_get_drvdata(dev);
122113426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
122213426454SMarkus Pargmann
122313426454SMarkus Pargmann mutex_lock(&data->mutex);
122413426454SMarkus Pargmann bmg160_set_mode(data, BMG160_MODE_SUSPEND);
122513426454SMarkus Pargmann mutex_unlock(&data->mutex);
122613426454SMarkus Pargmann
122713426454SMarkus Pargmann return 0;
122813426454SMarkus Pargmann }
122913426454SMarkus Pargmann
bmg160_resume(struct device * dev)123013426454SMarkus Pargmann static int bmg160_resume(struct device *dev)
123113426454SMarkus Pargmann {
123213426454SMarkus Pargmann struct iio_dev *indio_dev = dev_get_drvdata(dev);
123313426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
123413426454SMarkus Pargmann
123513426454SMarkus Pargmann mutex_lock(&data->mutex);
123613426454SMarkus Pargmann if (data->dready_trigger_on || data->motion_trigger_on ||
123713426454SMarkus Pargmann data->ev_enable_state)
123813426454SMarkus Pargmann bmg160_set_mode(data, BMG160_MODE_NORMAL);
123913426454SMarkus Pargmann mutex_unlock(&data->mutex);
124013426454SMarkus Pargmann
124113426454SMarkus Pargmann return 0;
124213426454SMarkus Pargmann }
124313426454SMarkus Pargmann #endif
124413426454SMarkus Pargmann
124513426454SMarkus Pargmann #ifdef CONFIG_PM
bmg160_runtime_suspend(struct device * dev)124613426454SMarkus Pargmann static int bmg160_runtime_suspend(struct device *dev)
124713426454SMarkus Pargmann {
124813426454SMarkus Pargmann struct iio_dev *indio_dev = dev_get_drvdata(dev);
124913426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
125013426454SMarkus Pargmann int ret;
125113426454SMarkus Pargmann
125213426454SMarkus Pargmann ret = bmg160_set_mode(data, BMG160_MODE_SUSPEND);
125313426454SMarkus Pargmann if (ret < 0) {
1254dc2c5715SAlison Schofield dev_err(dev, "set mode failed\n");
125513426454SMarkus Pargmann return -EAGAIN;
125613426454SMarkus Pargmann }
125713426454SMarkus Pargmann
125813426454SMarkus Pargmann return 0;
125913426454SMarkus Pargmann }
126013426454SMarkus Pargmann
bmg160_runtime_resume(struct device * dev)126113426454SMarkus Pargmann static int bmg160_runtime_resume(struct device *dev)
126213426454SMarkus Pargmann {
126313426454SMarkus Pargmann struct iio_dev *indio_dev = dev_get_drvdata(dev);
126413426454SMarkus Pargmann struct bmg160_data *data = iio_priv(indio_dev);
126513426454SMarkus Pargmann int ret;
126613426454SMarkus Pargmann
126713426454SMarkus Pargmann ret = bmg160_set_mode(data, BMG160_MODE_NORMAL);
126813426454SMarkus Pargmann if (ret < 0)
126913426454SMarkus Pargmann return ret;
127013426454SMarkus Pargmann
127113426454SMarkus Pargmann msleep_interruptible(BMG160_MAX_STARTUP_TIME_MS);
127213426454SMarkus Pargmann
127313426454SMarkus Pargmann return 0;
127413426454SMarkus Pargmann }
127513426454SMarkus Pargmann #endif
127613426454SMarkus Pargmann
127713426454SMarkus Pargmann const struct dev_pm_ops bmg160_pm_ops = {
127813426454SMarkus Pargmann SET_SYSTEM_SLEEP_PM_OPS(bmg160_suspend, bmg160_resume)
127913426454SMarkus Pargmann SET_RUNTIME_PM_OPS(bmg160_runtime_suspend,
128013426454SMarkus Pargmann bmg160_runtime_resume, NULL)
128113426454SMarkus Pargmann };
128213426454SMarkus Pargmann EXPORT_SYMBOL_GPL(bmg160_pm_ops);
128313426454SMarkus Pargmann
128413426454SMarkus Pargmann MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
128513426454SMarkus Pargmann MODULE_LICENSE("GPL v2");
128613426454SMarkus Pargmann MODULE_DESCRIPTION("BMG160 Gyro driver");
1287