summaryrefslogtreecommitdiff
path: root/drivers/iio/gyro/bmg160_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/gyro/bmg160_core.c')
-rw-r--r--drivers/iio/gyro/bmg160_core.c112
1 files changed, 55 insertions, 57 deletions
diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c
index 63ca31628a93..38394b5f3275 100644
--- a/drivers/iio/gyro/bmg160_core.c
+++ b/drivers/iio/gyro/bmg160_core.c
@@ -1,22 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* BMG160 Gyro Sensor driver
* Copyright (c) 2014, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
*/
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/acpi.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
@@ -27,10 +18,9 @@
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
#include "bmg160.h"
-#define BMG160_IRQ_NAME "bmg160_event"
-
#define BMG160_REG_CHIP_ID 0x00
#define BMG160_CHIP_ID_VAL 0x0F
@@ -102,8 +92,13 @@ struct bmg160_data {
struct regmap *regmap;
struct iio_trigger *dready_trig;
struct iio_trigger *motion_trig;
+ struct iio_mount_matrix orientation;
struct mutex mutex;
- s16 buffer[8];
+ /* Ensure naturally aligned timestamp */
+ struct {
+ s16 chans[3];
+ aligned_s64 timestamp;
+ } scan;
u32 dps_range;
int ev_enable_state;
int slope_thres;
@@ -287,8 +282,8 @@ static int bmg160_chip_init(struct bmg160_data *data)
data->slope_thres = val;
/* Set default interrupt mode */
- ret = regmap_update_bits(data->regmap, BMG160_REG_INT_EN_1,
- BMG160_INT1_BIT_OD, 0);
+ ret = regmap_clear_bits(data->regmap, BMG160_REG_INT_EN_1,
+ BMG160_INT1_BIT_OD);
if (ret < 0) {
dev_err(dev, "Error updating bits in reg_int_en_1\n");
return ret;
@@ -314,10 +309,8 @@ static int bmg160_set_power_state(struct bmg160_data *data, bool on)
if (on)
ret = pm_runtime_get_sync(dev);
- else {
- pm_runtime_mark_last_busy(dev);
+ else
ret = pm_runtime_put_autosuspend(dev);
- }
if (ret < 0) {
dev_err(dev, "Failed: bmg160_set_power_state for %d\n", on);
@@ -446,7 +439,7 @@ static int bmg160_setup_new_data_interrupt(struct bmg160_data *data,
static int bmg160_get_bw(struct bmg160_data *data, int *val)
{
- struct device *dev = regmap_get_device(data->regmap);
+ struct device *dev = regmap_get_device(data->regmap);
int i;
unsigned int bw_bits;
int ret;
@@ -582,11 +575,10 @@ static int bmg160_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
return bmg160_get_filter(data, val);
case IIO_CHAN_INFO_SCALE:
- *val = 0;
switch (chan->type) {
case IIO_TEMP:
- *val2 = 500000;
- return IIO_VAL_INT_PLUS_MICRO;
+ *val = 500;
+ return IIO_VAL_INT;
case IIO_ANGL_VEL:
{
int i;
@@ -594,6 +586,7 @@ static int bmg160_read_raw(struct iio_dev *indio_dev,
for (i = 0; i < ARRAY_SIZE(bmg160_scale_table); ++i) {
if (bmg160_scale_table[i].dps_range ==
data->dps_range) {
+ *val = 0;
*val2 = bmg160_scale_table[i].scale;
return IIO_VAL_INT_PLUS_MICRO;
}
@@ -751,7 +744,7 @@ static int 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)
+ bool state)
{
struct bmg160_data *data = iio_priv(indio_dev);
int ret;
@@ -767,7 +760,7 @@ static int bmg160_write_event_config(struct iio_dev *indio_dev,
return 0;
}
/*
- * We will expect the enable and disable to do operation in
+ * We will expect the enable and disable to do operation
* in reverse order. This will happen here anyway as our
* resume operation uses sync mode runtime pm calls, the
* suspend operation will be delayed by autosuspend delay
@@ -794,6 +787,20 @@ static int bmg160_write_event_config(struct iio_dev *indio_dev,
return 0;
}
+static const struct iio_mount_matrix *
+bmg160_get_mount_matrix(const struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan)
+{
+ struct bmg160_data *data = iio_priv(indio_dev);
+
+ return &data->orientation;
+}
+
+static const struct iio_chan_spec_ext_info bmg160_ext_info[] = {
+ IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bmg160_get_mount_matrix),
+ { }
+};
+
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 400 1000 2000");
static IIO_CONST_ATTR(in_anglvel_scale_available,
@@ -831,6 +838,7 @@ static const struct iio_event_spec bmg160_event = {
.storagebits = 16, \
.endianness = IIO_LE, \
}, \
+ .ext_info = bmg160_ext_info, \
.event_spec = &bmg160_event, \
.num_event_specs = 1 \
}
@@ -872,12 +880,12 @@ static irqreturn_t bmg160_trigger_handler(int irq, void *p)
mutex_lock(&data->mutex);
ret = regmap_bulk_read(data->regmap, BMG160_REG_XOUT_L,
- data->buffer, AXIS_MAX * 2);
+ data->scan.chans, AXIS_MAX * 2);
mutex_unlock(&data->mutex);
if (ret < 0)
goto err;
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
pf->timestamp);
err:
iio_trigger_notify_done(indio_dev->trig);
@@ -885,7 +893,7 @@ err:
return IRQ_HANDLED;
}
-static int bmg160_trig_try_reen(struct iio_trigger *trig)
+static void bmg160_trig_reen(struct iio_trigger *trig)
{
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
struct bmg160_data *data = iio_priv(indio_dev);
@@ -894,18 +902,14 @@ static int bmg160_trig_try_reen(struct iio_trigger *trig)
/* new data interrupts don't need ack */
if (data->dready_trigger_on)
- return 0;
+ return;
/* Set latched mode interrupt and clear any latched interrupt */
ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH,
BMG160_INT_MODE_LATCH_INT |
BMG160_INT_MODE_LATCH_RESET);
- if (ret < 0) {
+ if (ret < 0)
dev_err(dev, "Error writing reg_rst_latch\n");
- return ret;
- }
-
- return 0;
}
static int bmg160_data_rdy_trigger_set_state(struct iio_trigger *trig,
@@ -953,7 +957,7 @@ static int bmg160_data_rdy_trigger_set_state(struct iio_trigger *trig,
static const struct iio_trigger_ops bmg160_trigger_ops = {
.set_trigger_state = bmg160_data_rdy_trigger_set_state,
- .try_reenable = bmg160_trig_try_reen,
+ .reenable = bmg160_trig_reen,
};
static irqreturn_t bmg160_event_handler(int irq, void *private)
@@ -1043,25 +1047,13 @@ static int bmg160_buffer_postdisable(struct iio_dev *indio_dev)
static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = {
.preenable = bmg160_buffer_preenable,
- .postenable = iio_triggered_buffer_postenable,
- .predisable = iio_triggered_buffer_predisable,
.postdisable = bmg160_buffer_postdisable,
};
-static const char *bmg160_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- return dev_name(dev);
-}
-
int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
const char *name)
{
+ static const char * const regulators[] = { "vdd", "vddio" };
struct bmg160_data *data;
struct iio_dev *indio_dev;
int ret;
@@ -1075,16 +1067,21 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
data->irq = irq;
data->regmap = regmap;
+ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulators),
+ regulators);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+ ret = iio_read_mount_matrix(dev, &data->orientation);
+ if (ret)
+ return ret;
+
ret = bmg160_chip_init(data);
if (ret < 0)
return ret;
mutex_init(&data->mutex);
- if (ACPI_HANDLE(dev))
- name = bmg160_match_acpi_device(dev);
-
- indio_dev->dev.parent = dev;
indio_dev->channels = bmg160_channels;
indio_dev->num_channels = ARRAY_SIZE(bmg160_channels);
indio_dev->name = name;
@@ -1098,7 +1095,7 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
bmg160_data_rdy_trig_poll,
bmg160_event_handler,
IRQF_TRIGGER_RISING,
- BMG160_IRQ_NAME,
+ "bmg160_event",
indio_dev);
if (ret)
return ret;
@@ -1106,25 +1103,23 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
data->dready_trig = devm_iio_trigger_alloc(dev,
"%s-dev%d",
indio_dev->name,
- indio_dev->id);
+ iio_device_id(indio_dev));
if (!data->dready_trig)
return -ENOMEM;
data->motion_trig = devm_iio_trigger_alloc(dev,
"%s-any-motion-dev%d",
indio_dev->name,
- indio_dev->id);
+ iio_device_id(indio_dev));
if (!data->motion_trig)
return -ENOMEM;
- data->dready_trig->dev.parent = dev;
data->dready_trig->ops = &bmg160_trigger_ops;
iio_trigger_set_drvdata(data->dready_trig, indio_dev);
ret = iio_trigger_register(data->dready_trig);
if (ret)
return ret;
- data->motion_trig->dev.parent = dev;
data->motion_trig->ops = &bmg160_trigger_ops;
iio_trigger_set_drvdata(data->motion_trig, indio_dev);
ret = iio_trigger_register(data->motion_trig);
@@ -1156,11 +1151,14 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(dev, "unable to register iio device\n");
- goto err_buffer_cleanup;
+ goto err_pm_cleanup;
}
return 0;
+err_pm_cleanup:
+ pm_runtime_dont_use_autosuspend(dev);
+ pm_runtime_disable(dev);
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
err_trigger_unregister: