Commit aae95394 authored by Linus Walleij's avatar Linus Walleij Committed by Jonathan Cameron

iio: pressure: bmp280: add support for BMP085 EOC interrupt

The first version of this sensor, BMP085, supports sending an
End-of-Conversion (EOC) interrupt. Add code to support this using
a completion, in a similar vein as drivers/misc/bmp085.c does.

Make sure to check that we are given a rising edge, because the
EOC line goes from low-to-high when the conversion is ready.
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent b26b4e91
...@@ -27,6 +27,9 @@ ...@@ -27,6 +27,9 @@
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/interrupt.h>
#include <linux/irq.h> /* For irq_get_irq_data() */
#include <linux/completion.h>
#include "bmp280.h" #include "bmp280.h"
...@@ -34,6 +37,8 @@ struct bmp280_data { ...@@ -34,6 +37,8 @@ struct bmp280_data {
struct device *dev; struct device *dev;
struct mutex lock; struct mutex lock;
struct regmap *regmap; struct regmap *regmap;
struct completion done;
bool use_eoc;
const struct bmp280_chip_info *chip_info; const struct bmp280_chip_info *chip_info;
struct regulator *vddd; struct regulator *vddd;
struct regulator *vdda; struct regulator *vdda;
...@@ -595,16 +600,32 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas) ...@@ -595,16 +600,32 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
unsigned int delay_us; unsigned int delay_us;
unsigned int ctrl; unsigned int ctrl;
if (data->use_eoc)
init_completion(&data->done);
ret = regmap_write(data->regmap, BMP280_REG_CTRL_MEAS, ctrl_meas); ret = regmap_write(data->regmap, BMP280_REG_CTRL_MEAS, ctrl_meas);
if (ret) if (ret)
return ret; return ret;
if (ctrl_meas == BMP180_MEAS_TEMP) if (data->use_eoc) {
delay_us = 4500; /*
else * If we have a completion interrupt, use it, wait up to
delay_us = conversion_time_max[data->oversampling_press]; * 100ms. The longest conversion time listed is 76.5 ms for
* advanced resolution mode.
usleep_range(delay_us, delay_us + 1000); */
ret = wait_for_completion_timeout(&data->done,
1 + msecs_to_jiffies(100));
if (!ret)
dev_err(data->dev, "timeout waiting for completion\n");
} else {
if (ctrl_meas == BMP180_MEAS_TEMP)
delay_us = 4500;
else
delay_us =
conversion_time_max[data->oversampling_press];
usleep_range(delay_us, delay_us + 1000);
}
ret = regmap_read(data->regmap, BMP280_REG_CTRL_MEAS, &ctrl); ret = regmap_read(data->regmap, BMP280_REG_CTRL_MEAS, &ctrl);
if (ret) if (ret)
...@@ -846,10 +867,51 @@ static const struct bmp280_chip_info bmp180_chip_info = { ...@@ -846,10 +867,51 @@ static const struct bmp280_chip_info bmp180_chip_info = {
.read_press = bmp180_read_press, .read_press = bmp180_read_press,
}; };
static irqreturn_t bmp085_eoc_irq(int irq, void *d)
{
struct bmp280_data *data = d;
complete(&data->done);
return IRQ_HANDLED;
}
static int bmp085_fetch_eoc_irq(struct device *dev,
const char *name,
int irq,
struct bmp280_data *data)
{
unsigned long irq_trig;
int ret;
irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
if (irq_trig != IRQF_TRIGGER_RISING) {
dev_err(dev, "non-rising trigger given for EOC interrupt, "
"trying to enforce it\n");
irq_trig = IRQF_TRIGGER_RISING;
}
ret = devm_request_threaded_irq(dev,
irq,
bmp085_eoc_irq,
NULL,
irq_trig,
name,
data);
if (ret) {
/* Bail out without IRQ but keep the driver in place */
dev_err(dev, "unable to request DRDY IRQ\n");
return 0;
}
data->use_eoc = true;
return 0;
}
int bmp280_common_probe(struct device *dev, int bmp280_common_probe(struct device *dev,
struct regmap *regmap, struct regmap *regmap,
unsigned int chip, unsigned int chip,
const char *name) const char *name,
int irq)
{ {
int ret; int ret;
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
...@@ -948,6 +1010,17 @@ int bmp280_common_probe(struct device *dev, ...@@ -948,6 +1010,17 @@ int bmp280_common_probe(struct device *dev,
dev_set_drvdata(dev, indio_dev); dev_set_drvdata(dev, indio_dev);
/*
* Attempt to grab an optional EOC IRQ - only the BMP085 has this
* however as it happens, the BMP085 shares the chip ID of BMP180
* so we look for an IRQ if we have that.
*/
if (irq > 0 || (chip_id == BMP180_CHIP_ID)) {
ret = bmp085_fetch_eoc_irq(dev, name, irq, data);
if (ret)
goto out_disable_vdda;
}
ret = iio_device_register(indio_dev); ret = iio_device_register(indio_dev);
if (ret) if (ret)
goto out_disable_vdda; goto out_disable_vdda;
......
...@@ -33,7 +33,8 @@ static int bmp280_i2c_probe(struct i2c_client *client, ...@@ -33,7 +33,8 @@ static int bmp280_i2c_probe(struct i2c_client *client,
return bmp280_common_probe(&client->dev, return bmp280_common_probe(&client->dev,
regmap, regmap,
id->driver_data, id->driver_data,
id->name); id->name,
client->irq);
} }
static int bmp280_i2c_remove(struct i2c_client *client) static int bmp280_i2c_remove(struct i2c_client *client)
......
...@@ -81,7 +81,8 @@ static int bmp280_spi_probe(struct spi_device *spi) ...@@ -81,7 +81,8 @@ static int bmp280_spi_probe(struct spi_device *spi)
return bmp280_common_probe(&spi->dev, return bmp280_common_probe(&spi->dev,
regmap, regmap,
id->driver_data, id->driver_data,
id->name); id->name,
spi->irq);
} }
static int bmp280_spi_remove(struct spi_device *spi) static int bmp280_spi_remove(struct spi_device *spi)
......
...@@ -104,5 +104,6 @@ extern const struct regmap_config bmp280_regmap_config; ...@@ -104,5 +104,6 @@ extern const struct regmap_config bmp280_regmap_config;
int bmp280_common_probe(struct device *dev, int bmp280_common_probe(struct device *dev,
struct regmap *regmap, struct regmap *regmap,
unsigned int chip, unsigned int chip,
const char *name); const char *name,
int irq);
int bmp280_common_remove(struct device *dev); int bmp280_common_remove(struct device *dev);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment