summaryrefslogtreecommitdiff
path: root/drivers/iio/magnetometer
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-25 02:55:23 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-25 02:55:23 +0300
commit25a0dc4be86fc0d8c7e81bb5f8be8427022bf15f (patch)
treec8d66d65eb0910a2dc8e00a96c1a4da1fc9e33d4 /drivers/iio/magnetometer
parent9d0be76f52faff97fd9581eba70870f27061ae93 (diff)
parent6c71ee3b6157fdbde5c839405b593876d3687eb9 (diff)
downloadlinux-25a0dc4be86fc0d8c7e81bb5f8be8427022bf15f.tar.xz
Merge tag 'staging-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging and IIO driver updates from Greg KH: "Here is the big Staging and IIO driver update for 4.8-rc1. We ended up adding more code than removing, again, but it's not all that bad. Lots of cleanups all over the staging tree, and new IIO drivers, full details in the shortlog. All of these have been in linux-next for a while with no reported issues" * tag 'staging-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (417 commits) drivers:iio:accel:mma8452: removed unwanted return statements drivers:iio:accel:mma8452: added cleanup provision in case of failure. iio: Add iio.git tree to MAINTAINERS iio:st_pressure: clean useless static channel initializers iio:st_pressure:lps22hb: temperature support iio:st_pressure:lps22hb: open drain support iio:st_pressure: temperature triggered buffering iio:st_pressure: document sampling gains iio:st_pressure: align storagebits on power of 2 iio:st_sensors: align on storagebits boundaries staging:iio:lis3l02dq drop separate driver iio: accel: st_accel: Add lis3l02dq support iio: adc: add missing of_node references to iio_dev iio: adc: ti-ads1015: add indio_dev->dev.of_node reference iio: potentiometer: Fix typo in Kconfig iio: potentiometer: mcp4531: Add device tree binding iio: potentiometer: mcp4531: Add device tree binding documentation iio: potentiometer: mcp4531: Add support for MCP454x, MCP456x, MCP464x and MCP466x iio:imu:mpu6050: icm20608 initial support iio: adc: max1363: Add device tree binding ...
Diffstat (limited to 'drivers/iio/magnetometer')
-rw-r--r--drivers/iio/magnetometer/Kconfig2
-rw-r--r--drivers/iio/magnetometer/ak8975.c154
-rw-r--r--drivers/iio/magnetometer/bmc150_magn_i2c.c3
-rw-r--r--drivers/iio/magnetometer/bmc150_magn_spi.c3
-rw-r--r--drivers/iio/magnetometer/hmc5843_core.c2
-rw-r--r--drivers/iio/magnetometer/mag3110.c2
-rw-r--r--drivers/iio/magnetometer/st_magn_core.c12
7 files changed, 140 insertions, 38 deletions
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index 84e6559ccc65..1f842abcb4a4 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -44,6 +44,7 @@ config BMC150_MAGN_I2C
This driver is only implementing magnetometer part, which has
its own address and register map.
+ This driver also supports I2C Bosch BMC156 and BMM150 chips.
To compile this driver as a module, choose M here: the module will be
called bmc150_magn_i2c.
@@ -60,6 +61,7 @@ config BMC150_MAGN_SPI
This driver is only implementing magnetometer part, which has
its own address and register map.
+ This driver also supports SPI Bosch BMC156 and BMM150 chips.
To compile this driver as a module, choose M here: the module will be
called bmc150_magn_spi.
diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
index 609a2c401b5d..af8606cc7812 100644
--- a/drivers/iio/magnetometer/ak8975.c
+++ b/drivers/iio/magnetometer/ak8975.c
@@ -33,6 +33,7 @@
#include <linux/of_gpio.h>
#include <linux/acpi.h>
#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -379,37 +380,40 @@ struct ak8975_data {
u8 cntl_cache;
struct iio_mount_matrix orientation;
struct regulator *vdd;
+ struct regulator *vid;
};
/* Enable attached power regulator if any. */
-static int ak8975_power_on(struct i2c_client *client)
+static int ak8975_power_on(const struct ak8975_data *data)
{
- const struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct ak8975_data *data = iio_priv(indio_dev);
int ret;
- data->vdd = devm_regulator_get(&client->dev, "vdd");
- if (IS_ERR_OR_NULL(data->vdd)) {
- ret = PTR_ERR(data->vdd);
- if (ret == -ENODEV)
- ret = 0;
- } else {
- ret = regulator_enable(data->vdd);
+ ret = regulator_enable(data->vdd);
+ if (ret) {
+ dev_warn(&data->client->dev,
+ "Failed to enable specified Vdd supply\n");
+ return ret;
}
-
- if (ret)
- dev_err(&client->dev, "failed to enable Vdd supply: %d\n", ret);
- return ret;
+ ret = regulator_enable(data->vid);
+ if (ret) {
+ dev_warn(&data->client->dev,
+ "Failed to enable specified Vid supply\n");
+ return ret;
+ }
+ /*
+ * According to the datasheet the power supply rise time i 200us
+ * and the minimum wait time before mode setting is 100us, in
+ * total 300 us. Add some margin and say minimum 500us here.
+ */
+ usleep_range(500, 1000);
+ return 0;
}
/* Disable attached power regulator if any. */
-static void ak8975_power_off(const struct i2c_client *client)
+static void ak8975_power_off(const struct ak8975_data *data)
{
- const struct iio_dev *indio_dev = i2c_get_clientdata(client);
- const struct ak8975_data *data = iio_priv(indio_dev);
-
- if (!IS_ERR_OR_NULL(data->vdd))
- regulator_disable(data->vdd);
+ regulator_disable(data->vid);
+ regulator_disable(data->vdd);
}
/*
@@ -430,8 +434,8 @@ static int ak8975_who_i_am(struct i2c_client *client,
* AK8975 | DEVICE_ID | NA
* AK8963 | DEVICE_ID | NA
*/
- ret = i2c_smbus_read_i2c_block_data(client, AK09912_REG_WIA1,
- 2, wia_val);
+ ret = i2c_smbus_read_i2c_block_data_or_emulated(
+ client, AK09912_REG_WIA1, 2, wia_val);
if (ret < 0) {
dev_err(&client->dev, "Error reading WIA\n");
return ret;
@@ -543,9 +547,9 @@ static int ak8975_setup(struct i2c_client *client)
}
/* Get asa data and store in the device data. */
- ret = i2c_smbus_read_i2c_block_data(client,
- data->def->ctrl_regs[ASA_BASE],
- 3, data->asa);
+ ret = i2c_smbus_read_i2c_block_data_or_emulated(
+ client, data->def->ctrl_regs[ASA_BASE],
+ 3, data->asa);
if (ret < 0) {
dev_err(&client->dev, "Not able to read asa data\n");
return ret;
@@ -686,22 +690,31 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
struct ak8975_data *data = iio_priv(indio_dev);
const struct i2c_client *client = data->client;
const struct ak_def *def = data->def;
+ u16 buff;
int ret;
+ pm_runtime_get_sync(&data->client->dev);
+
mutex_lock(&data->lock);
ret = ak8975_start_read_axis(data, client);
if (ret)
goto exit;
- ret = i2c_smbus_read_word_data(client, def->data_regs[index]);
+ ret = i2c_smbus_read_i2c_block_data_or_emulated(
+ client, def->data_regs[index],
+ sizeof(buff), (u8*)&buff);
if (ret < 0)
goto exit;
mutex_unlock(&data->lock);
- /* Clamp to valid range. */
- *val = clamp_t(s16, ret, -def->range, def->range);
+ pm_runtime_mark_last_busy(&data->client->dev);
+ pm_runtime_put_autosuspend(&data->client->dev);
+
+ /* Swap bytes and convert to valid range. */
+ buff = le16_to_cpu(buff);
+ *val = clamp_t(s16, buff, -def->range, def->range);
return IIO_VAL_INT;
exit:
@@ -825,7 +838,8 @@ static void ak8975_fill_buffer(struct iio_dev *indio_dev)
buff[1] = clamp_t(s16, le16_to_cpu(buff[1]), -def->range, def->range);
buff[2] = clamp_t(s16, le16_to_cpu(buff[2]), -def->range, def->range);
- iio_push_to_buffers_with_timestamp(indio_dev, buff, iio_get_time_ns());
+ iio_push_to_buffers_with_timestamp(indio_dev, buff,
+ iio_get_time_ns(indio_dev));
return;
unlock:
@@ -919,7 +933,15 @@ static int ak8975_probe(struct i2c_client *client,
data->def = &ak_def_array[chipset];
- err = ak8975_power_on(client);
+ /* Fetch the regulators */
+ data->vdd = devm_regulator_get(&client->dev, "vdd");
+ if (IS_ERR(data->vdd))
+ return PTR_ERR(data->vdd);
+ data->vid = devm_regulator_get(&client->dev, "vid");
+ if (IS_ERR(data->vid))
+ return PTR_ERR(data->vid);
+
+ err = ak8975_power_on(data);
if (err)
return err;
@@ -959,26 +981,93 @@ static int ak8975_probe(struct i2c_client *client,
goto cleanup_buffer;
}
+ /* Enable runtime PM */
+ pm_runtime_get_noresume(&client->dev);
+ pm_runtime_set_active(&client->dev);
+ pm_runtime_enable(&client->dev);
+ /*
+ * The device comes online in 500us, so add two orders of magnitude
+ * of delay before autosuspending: 50 ms.
+ */
+ pm_runtime_set_autosuspend_delay(&client->dev, 50);
+ pm_runtime_use_autosuspend(&client->dev);
+ pm_runtime_put(&client->dev);
+
return 0;
cleanup_buffer:
iio_triggered_buffer_cleanup(indio_dev);
power_off:
- ak8975_power_off(client);
+ ak8975_power_off(data);
return err;
}
static int ak8975_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct ak8975_data *data = iio_priv(indio_dev);
+ pm_runtime_get_sync(&client->dev);
+ pm_runtime_put_noidle(&client->dev);
+ pm_runtime_disable(&client->dev);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
- ak8975_power_off(client);
+ ak8975_set_mode(data, POWER_DOWN);
+ ak8975_power_off(data);
return 0;
}
+#ifdef CONFIG_PM
+static int ak8975_runtime_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct ak8975_data *data = iio_priv(indio_dev);
+ int ret;
+
+ /* Set the device in power down if it wasn't already */
+ ret = ak8975_set_mode(data, POWER_DOWN);
+ if (ret < 0) {
+ dev_err(&client->dev, "Error in setting power-down mode\n");
+ return ret;
+ }
+ /* Next cut the regulators */
+ ak8975_power_off(data);
+
+ return 0;
+}
+
+static int ak8975_runtime_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct ak8975_data *data = iio_priv(indio_dev);
+ int ret;
+
+ /* Take up the regulators */
+ ak8975_power_on(data);
+ /*
+ * We come up in powered down mode, the reading routines will
+ * put us in the mode to read values later.
+ */
+ ret = ak8975_set_mode(data, POWER_DOWN);
+ if (ret < 0) {
+ dev_err(&client->dev, "Error in setting power-down mode\n");
+ return ret;
+ }
+
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static const struct dev_pm_ops ak8975_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(ak8975_runtime_suspend,
+ ak8975_runtime_resume, NULL)
+};
+
static const struct i2c_device_id ak8975_id[] = {
{"ak8975", AK8975},
{"ak8963", AK8963},
@@ -1006,6 +1095,7 @@ MODULE_DEVICE_TABLE(of, ak8975_of_match);
static struct i2c_driver ak8975_driver = {
.driver = {
.name = "ak8975",
+ .pm = &ak8975_dev_pm_ops,
.of_match_table = of_match_ptr(ak8975_of_match),
.acpi_match_table = ACPI_PTR(ak_acpi_match),
},
diff --git a/drivers/iio/magnetometer/bmc150_magn_i2c.c b/drivers/iio/magnetometer/bmc150_magn_i2c.c
index eddc7f0d0096..ee05722587aa 100644
--- a/drivers/iio/magnetometer/bmc150_magn_i2c.c
+++ b/drivers/iio/magnetometer/bmc150_magn_i2c.c
@@ -2,6 +2,7 @@
* 3-axis magnetometer driver supporting following I2C Bosch-Sensortec chips:
* - BMC150
* - BMC156
+ * - BMM150
*
* Copyright (c) 2016, Intel Corporation.
*
@@ -49,6 +50,7 @@ static int bmc150_magn_i2c_remove(struct i2c_client *client)
static const struct acpi_device_id bmc150_magn_acpi_match[] = {
{"BMC150B", 0},
{"BMC156B", 0},
+ {"BMM150B", 0},
{},
};
MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
@@ -56,6 +58,7 @@ MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
static const struct i2c_device_id bmc150_magn_i2c_id[] = {
{"bmc150_magn", 0},
{"bmc156_magn", 0},
+ {"bmm150_magn", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, bmc150_magn_i2c_id);
diff --git a/drivers/iio/magnetometer/bmc150_magn_spi.c b/drivers/iio/magnetometer/bmc150_magn_spi.c
index c4c738a07695..7d4152d4d01e 100644
--- a/drivers/iio/magnetometer/bmc150_magn_spi.c
+++ b/drivers/iio/magnetometer/bmc150_magn_spi.c
@@ -2,6 +2,7 @@
* 3-axis magnetometer driver support following SPI Bosch-Sensortec chips:
* - BMC150
* - BMC156
+ * - BMM150
*
* Copyright (c) 2016, Intel Corporation.
*
@@ -41,6 +42,7 @@ static int bmc150_magn_spi_remove(struct spi_device *spi)
static const struct spi_device_id bmc150_magn_spi_id[] = {
{"bmc150_magn", 0},
{"bmc156_magn", 0},
+ {"bmm150_magn", 0},
{}
};
MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id);
@@ -48,6 +50,7 @@ MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id);
static const struct acpi_device_id bmc150_magn_acpi_match[] = {
{"BMC150B", 0},
{"BMC156B", 0},
+ {"BMM150B", 0},
{},
};
MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
diff --git a/drivers/iio/magnetometer/hmc5843_core.c b/drivers/iio/magnetometer/hmc5843_core.c
index 77882b466e0f..ba3e2a374ee5 100644
--- a/drivers/iio/magnetometer/hmc5843_core.c
+++ b/drivers/iio/magnetometer/hmc5843_core.c
@@ -451,7 +451,7 @@ static irqreturn_t hmc5843_trigger_handler(int irq, void *p)
goto done;
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
- iio_get_time_ns());
+ iio_get_time_ns(indio_dev));
done:
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c
index 261d517428e4..f2be4a049056 100644
--- a/drivers/iio/magnetometer/mag3110.c
+++ b/drivers/iio/magnetometer/mag3110.c
@@ -261,7 +261,7 @@ static irqreturn_t mag3110_trigger_handler(int irq, void *p)
}
iio_push_to_buffers_with_timestamp(indio_dev, buffer,
- iio_get_time_ns());
+ iio_get_time_ns(indio_dev));
done:
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
index 8250fc322c56..3e1f06b2224c 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -589,13 +589,15 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
indio_dev->info = &magn_info;
mutex_init(&mdata->tb.buf_lock);
- st_sensors_power_enable(indio_dev);
+ err = st_sensors_power_enable(indio_dev);
+ if (err)
+ return err;
err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_magn_sensors_settings),
st_magn_sensors_settings);
if (err < 0)
- return err;
+ goto st_magn_power_off;
mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS;
mdata->multiread_bit = mdata->sensor_settings->multi_read_bit;
@@ -608,11 +610,11 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
err = st_sensors_init_sensor(indio_dev, NULL);
if (err < 0)
- return err;
+ goto st_magn_power_off;
err = st_magn_allocate_ring(indio_dev);
if (err < 0)
- return err;
+ goto st_magn_power_off;
if (irq > 0) {
err = st_sensors_allocate_trigger(indio_dev,
@@ -635,6 +637,8 @@ st_magn_device_register_error:
st_sensors_deallocate_trigger(indio_dev);
st_magn_probe_trigger_error:
st_magn_deallocate_ring(indio_dev);
+st_magn_power_off:
+ st_sensors_power_disable(indio_dev);
return err;
}