summaryrefslogtreecommitdiff
path: root/drivers/iio/pressure/bmp280-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/pressure/bmp280-core.c')
-rw-r--r--drivers/iio/pressure/bmp280-core.c725
1 files changed, 608 insertions, 117 deletions
diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index a8b97b9b0461..5376605b69b4 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -16,6 +16,11 @@
* https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp390-ds002.pdf
* https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp581-ds004.pdf
*
+ * Sensor API:
+ * https://github.com/boschsensortec/BME280_SensorAPI
+ * https://github.com/boschsensortec/BMP3_SensorAPI
+ * https://github.com/boschsensortec/BMP5_SensorAPI
+ *
* Notice:
* The link to the bmp180 datasheet points to an outdated version missing these changes:
* - Changed document referral from ANP015 to BST-MPS-AN004-00 on page 26
@@ -37,12 +42,14 @@
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/pm_runtime.h>
+#include <linux/property.h>
#include <linux/random.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
@@ -340,10 +347,19 @@ static int bmp280_read_calib(struct bmp280_data *data)
return 0;
}
+/*
+ * These enums are used for indexing into the array of humidity parameters
+ * for BME280. Due to some weird indexing, unaligned BE/LE accesses co-exist in
+ * order to prepare the FIELD_{GET/PREP}() fields. Table 16 in Section 4.2.2 of
+ * the datasheet.
+ */
+enum { H2 = 0, H3 = 2, H4 = 3, H5 = 4, H6 = 6 };
+
static int bme280_read_calib(struct bmp280_data *data)
{
struct bmp280_calib *calib = &data->calib.bmp280;
struct device *dev = data->dev;
+ s16 h4_upper, h4_lower, tmp_1, tmp_2, tmp_3;
unsigned int tmp;
int ret;
@@ -352,14 +368,6 @@ static int bme280_read_calib(struct bmp280_data *data)
if (ret)
return ret;
- /*
- * Read humidity calibration values.
- * Due to some odd register addressing we cannot just
- * do a big bulk read. Instead, we have to read each Hx
- * value separately and sometimes do some bit shifting...
- * Humidity data is only available on BME280.
- */
-
ret = regmap_read(data->regmap, BME280_REG_COMP_H1, &tmp);
if (ret) {
dev_err(dev, "failed to read H1 comp value\n");
@@ -368,43 +376,23 @@ static int bme280_read_calib(struct bmp280_data *data)
calib->H1 = tmp;
ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H2,
- &data->le16, sizeof(data->le16));
+ data->bme280_humid_cal_buf,
+ sizeof(data->bme280_humid_cal_buf));
if (ret) {
- dev_err(dev, "failed to read H2 comp value\n");
+ dev_err(dev, "failed to read humidity calibration values\n");
return ret;
}
- calib->H2 = sign_extend32(le16_to_cpu(data->le16), 15);
- ret = regmap_read(data->regmap, BME280_REG_COMP_H3, &tmp);
- if (ret) {
- dev_err(dev, "failed to read H3 comp value\n");
- return ret;
- }
- calib->H3 = tmp;
-
- ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H4,
- &data->be16, sizeof(data->be16));
- if (ret) {
- dev_err(dev, "failed to read H4 comp value\n");
- return ret;
- }
- calib->H4 = sign_extend32(((be16_to_cpu(data->be16) >> 4) & 0xff0) |
- (be16_to_cpu(data->be16) & 0xf), 11);
-
- ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H5,
- &data->le16, sizeof(data->le16));
- if (ret) {
- dev_err(dev, "failed to read H5 comp value\n");
- return ret;
- }
- calib->H5 = sign_extend32(FIELD_GET(BME280_COMP_H5_MASK, le16_to_cpu(data->le16)), 11);
-
- ret = regmap_read(data->regmap, BME280_REG_COMP_H6, &tmp);
- if (ret) {
- dev_err(dev, "failed to read H6 comp value\n");
- return ret;
- }
- calib->H6 = sign_extend32(tmp, 7);
+ calib->H2 = get_unaligned_le16(&data->bme280_humid_cal_buf[H2]);
+ calib->H3 = data->bme280_humid_cal_buf[H3];
+ tmp_1 = get_unaligned_be16(&data->bme280_humid_cal_buf[H4]);
+ tmp_2 = FIELD_GET(BME280_COMP_H4_GET_MASK_UP, tmp_1);
+ h4_upper = FIELD_PREP(BME280_COMP_H4_PREP_MASK_UP, tmp_2);
+ h4_lower = FIELD_GET(BME280_COMP_H4_MASK_LOW, tmp_1);
+ calib->H4 = sign_extend32(h4_upper | h4_lower, 11);
+ tmp_3 = get_unaligned_le16(&data->bme280_humid_cal_buf[H5]);
+ calib->H5 = sign_extend32(FIELD_GET(BME280_COMP_H5_MASK, tmp_3), 11);
+ calib->H6 = data->bme280_humid_cal_buf[H6];
return 0;
}
@@ -635,6 +623,14 @@ static int bmp280_read_raw_impl(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
+ ret = data->chip_info->set_mode(data, BMP280_FORCED);
+ if (ret)
+ return ret;
+
+ ret = data->chip_info->wait_conv(data);
+ if (ret)
+ return ret;
+
switch (chan->type) {
case IIO_HUMIDITYRELATIVE:
ret = data->chip_info->read_humid(data, &chan_value);
@@ -664,6 +660,14 @@ static int bmp280_read_raw_impl(struct iio_dev *indio_dev,
return -EINVAL;
}
case IIO_CHAN_INFO_RAW:
+ ret = data->chip_info->set_mode(data, BMP280_FORCED);
+ if (ret)
+ return ret;
+
+ ret = data->chip_info->wait_conv(data);
+ if (ret)
+ return ret;
+
switch (chan->type) {
case IIO_HUMIDITYRELATIVE:
ret = data->chip_info->read_humid(data, &chan_value);
@@ -983,6 +987,92 @@ static const unsigned long bme280_avail_scan_masks[] = {
0
};
+static int bmp280_preinit(struct bmp280_data *data)
+{
+ struct device *dev = data->dev;
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_write(data->regmap, BMP280_REG_RESET, BMP280_RST_SOFT_CMD);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to reset device.\n");
+
+ /*
+ * According to the datasheet in Chapter 1: Specification, Table 2,
+ * after resetting, the device uses the complete power-on sequence so
+ * it needs to wait for the defined start-up time.
+ */
+ fsleep(data->start_up_time);
+
+ ret = regmap_read(data->regmap, BMP280_REG_STATUS, &reg);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to read status register.\n");
+
+ if (reg & BMP280_REG_STATUS_IM_UPDATE)
+ return dev_err_probe(dev, -EIO, "Failed to copy NVM contents.\n");
+
+ return 0;
+}
+
+static const u8 bmp280_operation_mode[] = {
+ [BMP280_SLEEP] = BMP280_MODE_SLEEP,
+ [BMP280_FORCED] = BMP280_MODE_FORCED,
+ [BMP280_NORMAL] = BMP280_MODE_NORMAL,
+};
+
+static int bmp280_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ int ret;
+
+ ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
+ BMP280_MODE_MASK, bmp280_operation_mode[mode]);
+ if (ret) {
+ dev_err(data->dev, "failed to write ctrl_meas register.\n");
+ return ret;
+ }
+
+ data->op_mode = mode;
+
+ return 0;
+}
+
+static int bmp280_wait_conv(struct bmp280_data *data)
+{
+ unsigned int reg, meas_time_us;
+ int ret;
+
+ /* Check if we are using a BME280 device */
+ if (data->oversampling_humid)
+ meas_time_us = BMP280_PRESS_HUMID_MEAS_OFFSET +
+ BIT(data->oversampling_humid) * BMP280_MEAS_DUR;
+
+ else
+ meas_time_us = 0;
+
+ /* Pressure measurement time */
+ meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
+ BIT(data->oversampling_press) * BMP280_MEAS_DUR;
+
+ /* Temperature measurement time */
+ meas_time_us += BIT(data->oversampling_temp) * BMP280_MEAS_DUR;
+
+ /* Waiting time according to the BM(P/E)2 Sensor API */
+ fsleep(meas_time_us);
+
+ ret = regmap_read(data->regmap, BMP280_REG_STATUS, &reg);
+ if (ret) {
+ dev_err(data->dev, "failed to read status register.\n");
+ return ret;
+ }
+
+ if (reg & BMP280_REG_STATUS_MEAS_BIT) {
+ dev_err(data->dev, "Measurement cycle didn't complete.\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
static int bmp280_chip_config(struct bmp280_data *data)
{
u8 osrs = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp + 1) |
@@ -993,7 +1083,7 @@ static int bmp280_chip_config(struct bmp280_data *data)
BMP280_OSRS_TEMP_MASK |
BMP280_OSRS_PRESS_MASK |
BMP280_MODE_MASK,
- osrs | BMP280_MODE_NORMAL);
+ osrs | BMP280_MODE_SLEEP);
if (ret) {
dev_err(data->dev, "failed to write ctrl_meas register\n");
return ret;
@@ -1015,7 +1105,9 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- s32 adc_temp, adc_press, t_fine;
+ u32 adc_temp, adc_press, comp_press;
+ s32 t_fine, comp_temp;
+ s32 *chans = (s32 *)data->sensor_data;
int ret;
guard(mutex)(&data->lock);
@@ -1035,7 +1127,7 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p)
goto out;
}
- data->sensor_data[1] = bmp280_compensate_temp(data, adc_temp);
+ comp_temp = bmp280_compensate_temp(data, adc_temp);
/* Pressure calculations */
adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[0]));
@@ -1045,10 +1137,12 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p)
}
t_fine = bmp280_calc_t_fine(data, adc_temp);
+ comp_press = bmp280_compensate_press(data, adc_press, t_fine);
- data->sensor_data[0] = bmp280_compensate_press(data, adc_press, t_fine);
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -1099,10 +1193,13 @@ const struct bmp280_chip_info bmp280_chip_info = {
.read_temp = bmp280_read_temp,
.read_press = bmp280_read_press,
.read_calib = bmp280_read_calib,
+ .set_mode = bmp280_set_mode,
+ .wait_conv = bmp280_wait_conv,
+ .preinit = bmp280_preinit,
.trigger_handler = bmp280_trigger_handler,
};
-EXPORT_SYMBOL_NS(bmp280_chip_info, IIO_BMP280);
+EXPORT_SYMBOL_NS(bmp280_chip_info, "IIO_BMP280");
static int bme280_chip_config(struct bmp280_data *data)
{
@@ -1128,7 +1225,9 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- s32 adc_temp, adc_press, adc_humidity, t_fine;
+ u32 adc_temp, adc_press, adc_humidity, comp_press, comp_humidity;
+ s32 t_fine, comp_temp;
+ s32 *chans = (s32 *)data->sensor_data;
int ret;
guard(mutex)(&data->lock);
@@ -1148,7 +1247,7 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
goto out;
}
- data->sensor_data[1] = bmp280_compensate_temp(data, adc_temp);
+ comp_temp = bmp280_compensate_temp(data, adc_temp);
/* Pressure calculations */
adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[0]));
@@ -1158,8 +1257,7 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
}
t_fine = bmp280_calc_t_fine(data, adc_temp);
-
- data->sensor_data[0] = bmp280_compensate_press(data, adc_press, t_fine);
+ comp_press = bmp280_compensate_press(data, adc_press, t_fine);
/* Humidity calculations */
adc_humidity = get_unaligned_be16(&data->buf[6]);
@@ -1168,9 +1266,14 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
dev_err(data->dev, "reading humidity skipped\n");
goto out;
}
- data->sensor_data[2] = bme280_compensate_humidity(data, adc_humidity, t_fine);
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ comp_humidity = bme280_compensate_humidity(data, adc_humidity, t_fine);
+
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
+ chans[2] = comp_humidity;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -1179,6 +1282,63 @@ out:
return IRQ_HANDLED;
}
+static int __bmp280_trigger_probe(struct iio_dev *indio_dev,
+ const struct iio_trigger_ops *trigger_ops,
+ int (*int_pin_config)(struct bmp280_data *data),
+ irq_handler_t irq_thread_handler)
+{
+ struct bmp280_data *data = iio_priv(indio_dev);
+ struct device *dev = data->dev;
+ u32 irq_type;
+ int ret, irq;
+
+ irq = fwnode_irq_get(dev_fwnode(dev), 0);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "No interrupt found.\n");
+
+ irq_type = irq_get_trigger_type(irq);
+ switch (irq_type) {
+ case IRQF_TRIGGER_RISING:
+ data->trig_active_high = true;
+ break;
+ case IRQF_TRIGGER_FALLING:
+ data->trig_active_high = false;
+ break;
+ default:
+ return dev_err_probe(dev, -EINVAL, "Invalid interrupt type specified.\n");
+ }
+
+ data->trig_open_drain =
+ fwnode_property_read_bool(dev_fwnode(dev), "int-open-drain");
+
+ ret = int_pin_config(data);
+ if (ret)
+ return ret;
+
+ data->trig = devm_iio_trigger_alloc(data->dev, "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!data->trig)
+ return -ENOMEM;
+
+ data->trig->ops = trigger_ops;
+ iio_trigger_set_drvdata(data->trig, data);
+
+ ret = devm_request_threaded_irq(data->dev, irq, NULL,
+ irq_thread_handler, IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "request IRQ failed.\n");
+
+ ret = devm_iio_trigger_register(data->dev, data->trig);
+ if (ret)
+ return dev_err_probe(dev, ret, "iio trigger register failed.\n");
+
+ indio_dev->trig = iio_trigger_get(data->trig);
+
+ return 0;
+}
+
static const u8 bme280_chip_ids[] = { BME280_CHIP_ID };
static const int bme280_humid_coeffs[] = { 1000, 1024 };
@@ -1216,10 +1376,13 @@ const struct bmp280_chip_info bme280_chip_info = {
.read_press = bmp280_read_press,
.read_humid = bme280_read_humid,
.read_calib = bme280_read_calib,
+ .set_mode = bmp280_set_mode,
+ .wait_conv = bmp280_wait_conv,
+ .preinit = bmp280_preinit,
.trigger_handler = bme280_trigger_handler,
};
-EXPORT_SYMBOL_NS(bme280_chip_info, IIO_BMP280);
+EXPORT_SYMBOL_NS(bme280_chip_info, "IIO_BMP280");
/*
* Helper function to send a command to BMP3XX sensors.
@@ -1502,6 +1665,64 @@ static int bmp380_preinit(struct bmp280_data *data)
return bmp380_cmd(data, BMP380_CMD_SOFT_RESET);
}
+static const u8 bmp380_operation_mode[] = {
+ [BMP280_SLEEP] = BMP380_MODE_SLEEP,
+ [BMP280_FORCED] = BMP380_MODE_FORCED,
+ [BMP280_NORMAL] = BMP380_MODE_NORMAL,
+};
+
+static int bmp380_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ int ret;
+
+ ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
+ BMP380_MODE_MASK,
+ FIELD_PREP(BMP380_MODE_MASK,
+ bmp380_operation_mode[mode]));
+ if (ret) {
+ dev_err(data->dev, "failed to write power control register.\n");
+ return ret;
+ }
+
+ data->op_mode = mode;
+
+ return 0;
+}
+
+static int bmp380_wait_conv(struct bmp280_data *data)
+{
+ unsigned int reg;
+ int ret, meas_time_us;
+
+ /* Offset measurement time */
+ meas_time_us = BMP380_MEAS_OFFSET;
+
+ /* Pressure measurement time */
+ meas_time_us += BMP380_PRESS_MEAS_OFFSET +
+ BIT(data->oversampling_press) * BMP380_MEAS_DUR;
+
+ /* Temperature measurement time */
+ meas_time_us += BMP380_TEMP_MEAS_OFFSET +
+ BIT(data->oversampling_temp) * BMP380_MEAS_DUR;
+
+ /* Measurement time defined in Datasheet Section 3.9.2 */
+ fsleep(meas_time_us);
+
+ ret = regmap_read(data->regmap, BMP380_REG_STATUS, &reg);
+ if (ret) {
+ dev_err(data->dev, "failed to read status register.\n");
+ return ret;
+ }
+
+ if (!((reg & BMP380_STATUS_DRDY_PRESS_MASK) &&
+ (reg & BMP380_STATUS_DRDY_TEMP_MASK))) {
+ dev_err(data->dev, "Measurement cycle didn't complete.\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
static int bmp380_chip_config(struct bmp280_data *data)
{
bool change = false, aux;
@@ -1545,14 +1766,12 @@ static int bmp380_chip_config(struct bmp280_data *data)
change = change || aux;
/* Set filter data */
- ret = regmap_update_bits_check(data->regmap, BMP380_REG_CONFIG, BMP380_FILTER_MASK,
- FIELD_PREP(BMP380_FILTER_MASK, data->iir_filter_coeff),
- &aux);
+ ret = regmap_update_bits(data->regmap, BMP380_REG_CONFIG, BMP380_FILTER_MASK,
+ FIELD_PREP(BMP380_FILTER_MASK, data->iir_filter_coeff));
if (ret) {
dev_err(data->dev, "failed to write config register\n");
return ret;
}
- change = change || aux;
if (change) {
/*
@@ -1564,17 +1783,19 @@ static int bmp380_chip_config(struct bmp280_data *data)
* Resets sensor measurement loop toggling between sleep and
* normal operating modes.
*/
- ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
- BMP380_MODE_MASK,
- FIELD_PREP(BMP380_MODE_MASK, BMP380_MODE_SLEEP));
+ ret = bmp380_set_mode(data, BMP280_SLEEP);
if (ret) {
dev_err(data->dev, "failed to set sleep mode\n");
return ret;
}
- usleep_range(2000, 2500);
- ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
- BMP380_MODE_MASK,
- FIELD_PREP(BMP380_MODE_MASK, BMP380_MODE_NORMAL));
+
+ /*
+ * According to the BMP3 Sensor API, the sensor needs 5ms
+ * in order to go to the sleep mode.
+ */
+ fsleep(5 * USEC_PER_MSEC);
+
+ ret = bmp380_set_mode(data, BMP280_NORMAL);
if (ret) {
dev_err(data->dev, "failed to set normal mode\n");
return ret;
@@ -1600,7 +1821,77 @@ static int bmp380_chip_config(struct bmp280_data *data)
}
}
- return 0;
+ /* Dummy read to empty data registers. */
+ ret = bmp380_read_press(data, &tmp);
+ if (ret)
+ return ret;
+
+ ret = bmp380_set_mode(data, BMP280_SLEEP);
+ if (ret)
+ dev_err(data->dev, "failed to set sleep mode.\n");
+
+ return ret;
+}
+
+static int bmp380_data_rdy_trigger_set_state(struct iio_trigger *trig,
+ bool state)
+{
+ struct bmp280_data *data = iio_trigger_get_drvdata(trig);
+ int ret;
+
+ guard(mutex)(&data->lock);
+
+ ret = regmap_update_bits(data->regmap, BMP380_REG_INT_CONTROL,
+ BMP380_INT_CTRL_DRDY_EN,
+ FIELD_PREP(BMP380_INT_CTRL_DRDY_EN, !!state));
+ if (ret)
+ dev_err(data->dev,
+ "Could not %s interrupt.\n", str_enable_disable(state));
+ return ret;
+}
+
+static const struct iio_trigger_ops bmp380_trigger_ops = {
+ .set_trigger_state = &bmp380_data_rdy_trigger_set_state,
+};
+
+static int bmp380_int_pin_config(struct bmp280_data *data)
+{
+ int pin_drive_cfg = FIELD_PREP(BMP380_INT_CTRL_OPEN_DRAIN,
+ data->trig_open_drain);
+ int pin_level_cfg = FIELD_PREP(BMP380_INT_CTRL_LEVEL,
+ data->trig_active_high);
+ int ret, int_pin_cfg = pin_drive_cfg | pin_level_cfg;
+
+ ret = regmap_update_bits(data->regmap, BMP380_REG_INT_CONTROL,
+ BMP380_INT_CTRL_SETTINGS_MASK, int_pin_cfg);
+ if (ret)
+ dev_err(data->dev, "Could not set interrupt settings.\n");
+
+ return ret;
+}
+
+static irqreturn_t bmp380_irq_thread_handler(int irq, void *p)
+{
+ struct iio_dev *indio_dev = p;
+ struct bmp280_data *data = iio_priv(indio_dev);
+ unsigned int int_ctrl;
+ int ret;
+
+ ret = regmap_read(data->regmap, BMP380_REG_INT_STATUS, &int_ctrl);
+ if (ret)
+ return IRQ_NONE;
+
+ if (FIELD_GET(BMP380_INT_STATUS_DRDY, int_ctrl))
+ iio_trigger_poll_nested(data->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int bmp380_trigger_probe(struct iio_dev *indio_dev)
+{
+ return __bmp280_trigger_probe(indio_dev, &bmp380_trigger_ops,
+ bmp380_int_pin_config,
+ bmp380_irq_thread_handler);
}
static irqreturn_t bmp380_trigger_handler(int irq, void *p)
@@ -1608,7 +1899,9 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- s32 adc_temp, adc_press, t_fine;
+ u32 adc_temp, adc_press, comp_press;
+ s32 t_fine, comp_temp;
+ s32 *chans = (s32 *)data->sensor_data;
int ret;
guard(mutex)(&data->lock);
@@ -1628,7 +1921,7 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p)
goto out;
}
- data->sensor_data[1] = bmp380_compensate_temp(data, adc_temp);
+ comp_temp = bmp380_compensate_temp(data, adc_temp);
/* Pressure calculations */
adc_press = get_unaligned_le24(&data->buf[0]);
@@ -1638,10 +1931,12 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p)
}
t_fine = bmp380_calc_t_fine(data, adc_temp);
+ comp_press = bmp380_compensate_press(data, adc_press, t_fine);
- data->sensor_data[0] = bmp380_compensate_press(data, adc_press, t_fine);
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -1692,11 +1987,14 @@ const struct bmp280_chip_info bmp380_chip_info = {
.read_temp = bmp380_read_temp,
.read_press = bmp380_read_press,
.read_calib = bmp380_read_calib,
+ .set_mode = bmp380_set_mode,
+ .wait_conv = bmp380_wait_conv,
.preinit = bmp380_preinit,
+ .trigger_probe = bmp380_trigger_probe,
.trigger_handler = bmp380_trigger_handler,
};
-EXPORT_SYMBOL_NS(bmp380_chip_info, IIO_BMP280);
+EXPORT_SYMBOL_NS(bmp380_chip_info, "IIO_BMP280");
static int bmp580_soft_reset(struct bmp280_data *data)
{
@@ -2079,6 +2377,70 @@ static int bmp580_preinit(struct bmp280_data *data)
return PTR_ERR_OR_ZERO(devm_nvmem_register(config.dev, &config));
}
+static const u8 bmp580_operation_mode[] = {
+ [BMP280_SLEEP] = BMP580_MODE_SLEEP,
+ [BMP280_FORCED] = BMP580_MODE_FORCED,
+ [BMP280_NORMAL] = BMP580_MODE_NORMAL,
+};
+
+static int bmp580_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ struct device *dev = data->dev;
+ int ret;
+
+ if (mode == BMP280_FORCED) {
+ ret = regmap_set_bits(data->regmap, BMP580_REG_DSP_CONFIG,
+ BMP580_DSP_IIR_FORCED_FLUSH);
+ if (ret) {
+ dev_err(dev, "Could not flush IIR filter constants.\n");
+ return ret;
+ }
+ }
+
+ ret = regmap_write_bits(data->regmap, BMP580_REG_ODR_CONFIG,
+ BMP580_MODE_MASK,
+ FIELD_PREP(BMP580_MODE_MASK,
+ bmp580_operation_mode[mode]));
+ if (ret) {
+ dev_err(dev, "failed to write power control register.\n");
+ return ret;
+ }
+
+ data->op_mode = mode;
+
+ return 0;
+}
+
+static int bmp580_wait_conv(struct bmp280_data *data)
+{
+ /*
+ * Taken from datasheet, Section 2 "Specification, Table 3 "Electrical
+ * characteristics.
+ */
+ static const int time_conv_press[] = {
+ 0, 1050, 1785, 3045, 5670, 10920, 21420, 42420,
+ 84420,
+ };
+ static const int time_conv_temp[] = {
+ 0, 1050, 1105, 1575, 2205, 3465, 6090, 11340,
+ 21840,
+ };
+ int meas_time_us;
+
+ meas_time_us = 4 * USEC_PER_MSEC +
+ time_conv_temp[data->oversampling_temp] +
+ time_conv_press[data->oversampling_press];
+
+ /*
+ * Measurement time mentioned in Chapter 2, Table 4 of the datasheet.
+ * The extra 4ms is the required mode change to start of measurement
+ * time.
+ */
+ fsleep(meas_time_us);
+
+ return 0;
+}
+
static int bmp580_chip_config(struct bmp280_data *data)
{
bool change = false, aux;
@@ -2141,26 +2503,13 @@ static int bmp580_chip_config(struct bmp280_data *data)
reg_val = FIELD_PREP(BMP580_DSP_IIR_PRESS_MASK, data->iir_filter_coeff) |
FIELD_PREP(BMP580_DSP_IIR_TEMP_MASK, data->iir_filter_coeff);
- ret = regmap_update_bits_check(data->regmap, BMP580_REG_DSP_IIR,
- BMP580_DSP_IIR_PRESS_MASK |
- BMP580_DSP_IIR_TEMP_MASK,
- reg_val, &aux);
+ ret = regmap_update_bits(data->regmap, BMP580_REG_DSP_IIR,
+ BMP580_DSP_IIR_PRESS_MASK | BMP580_DSP_IIR_TEMP_MASK,
+ reg_val);
if (ret) {
dev_err(data->dev, "failed to write config register\n");
return ret;
}
- change = change || aux;
-
- /* Restore sensor to normal operation mode */
- ret = regmap_write_bits(data->regmap, BMP580_REG_ODR_CONFIG,
- BMP580_MODE_MASK,
- FIELD_PREP(BMP580_MODE_MASK, BMP580_MODE_NORMAL));
- if (ret) {
- dev_err(data->dev, "failed to set normal mode\n");
- return ret;
- }
- /* From datasheet's table 4: electrical characteristics */
- usleep_range(3000, 3500);
if (change) {
/*
@@ -2185,12 +2534,80 @@ static int bmp580_chip_config(struct bmp280_data *data)
return 0;
}
+static int bmp580_data_rdy_trigger_set_state(struct iio_trigger *trig,
+ bool state)
+{
+ struct bmp280_data *data = iio_trigger_get_drvdata(trig);
+ int ret;
+
+ guard(mutex)(&data->lock);
+
+ ret = regmap_update_bits(data->regmap, BMP580_REG_INT_CONFIG,
+ BMP580_INT_CONFIG_INT_EN,
+ FIELD_PREP(BMP580_INT_CONFIG_INT_EN, !!state));
+ if (ret)
+ dev_err(data->dev,
+ "Could not %s interrupt.\n", str_enable_disable(state));
+ return ret;
+}
+
+static const struct iio_trigger_ops bmp580_trigger_ops = {
+ .set_trigger_state = &bmp580_data_rdy_trigger_set_state,
+};
+
+static int bmp580_int_pin_config(struct bmp280_data *data)
+{
+ int pin_drive_cfg = FIELD_PREP(BMP580_INT_CONFIG_OPEN_DRAIN,
+ data->trig_open_drain);
+ int pin_level_cfg = FIELD_PREP(BMP580_INT_CONFIG_LEVEL,
+ data->trig_active_high);
+ int ret, int_pin_cfg = pin_drive_cfg | pin_level_cfg;
+
+ ret = regmap_update_bits(data->regmap, BMP580_REG_INT_CONFIG,
+ BMP580_INT_CONFIG_MASK, int_pin_cfg);
+ if (ret) {
+ dev_err(data->dev, "Could not set interrupt settings.\n");
+ return ret;
+ }
+
+ ret = regmap_set_bits(data->regmap, BMP580_REG_INT_SOURCE,
+ BMP580_INT_SOURCE_DRDY);
+ if (ret)
+ dev_err(data->dev, "Could not set interrupt source.\n");
+
+ return ret;
+}
+
+static irqreturn_t bmp580_irq_thread_handler(int irq, void *p)
+{
+ struct iio_dev *indio_dev = p;
+ struct bmp280_data *data = iio_priv(indio_dev);
+ unsigned int int_ctrl;
+ int ret;
+
+ ret = regmap_read(data->regmap, BMP580_REG_INT_STATUS, &int_ctrl);
+ if (ret)
+ return IRQ_NONE;
+
+ if (FIELD_GET(BMP580_INT_STATUS_DRDY_MASK, int_ctrl))
+ iio_trigger_poll_nested(data->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int bmp580_trigger_probe(struct iio_dev *indio_dev)
+{
+ return __bmp280_trigger_probe(indio_dev, &bmp580_trigger_ops,
+ bmp580_int_pin_config,
+ bmp580_irq_thread_handler);
+}
+
static irqreturn_t bmp580_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- int ret;
+ int ret, offset;
guard(mutex)(&data->lock);
@@ -2202,13 +2619,17 @@ static irqreturn_t bmp580_trigger_handler(int irq, void *p)
goto out;
}
- /* Temperature calculations */
- memcpy(&data->sensor_data[1], &data->buf[0], 3);
+ offset = 0;
/* Pressure calculations */
- memcpy(&data->sensor_data[0], &data->buf[3], 3);
+ memcpy(&data->sensor_data[offset], &data->buf[3], 3);
+
+ offset += sizeof(s32);
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ /* Temperature calculations */
+ memcpy(&data->sensor_data[offset], &data->buf[0], 3);
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -2257,11 +2678,14 @@ const struct bmp280_chip_info bmp580_chip_info = {
.chip_config = bmp580_chip_config,
.read_temp = bmp580_read_temp,
.read_press = bmp580_read_press,
+ .set_mode = bmp580_set_mode,
+ .wait_conv = bmp580_wait_conv,
.preinit = bmp580_preinit,
+ .trigger_probe = bmp580_trigger_probe,
.trigger_handler = bmp580_trigger_handler,
};
-EXPORT_SYMBOL_NS(bmp580_chip_info, IIO_BMP280);
+EXPORT_SYMBOL_NS(bmp580_chip_info, "IIO_BMP280");
static int bmp180_wait_for_eoc(struct bmp280_data *data, u8 ctrl_meas)
{
@@ -2504,6 +2928,19 @@ static int bmp180_read_press(struct bmp280_data *data, u32 *comp_press)
return 0;
}
+/* Keep compatibility with newer generations of the sensor */
+static int bmp180_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ return 0;
+}
+
+/* Keep compatibility with newer generations of the sensor */
+static int bmp180_wait_conv(struct bmp280_data *data)
+{
+ return 0;
+}
+
+/* Keep compatibility with newer generations of the sensor */
static int bmp180_chip_config(struct bmp280_data *data)
{
return 0;
@@ -2514,23 +2951,24 @@ static irqreturn_t bmp180_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- int ret, chan_value;
+ int ret, comp_temp, comp_press;
+ s32 *chans = (s32 *)data->sensor_data;
guard(mutex)(&data->lock);
- ret = bmp180_read_temp(data, &chan_value);
+ ret = bmp180_read_temp(data, &comp_temp);
if (ret)
goto out;
- data->sensor_data[1] = chan_value;
- ret = bmp180_read_press(data, &chan_value);
+ ret = bmp180_read_press(data, &comp_press);
if (ret)
goto out;
- data->sensor_data[0] = chan_value;
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -2574,10 +3012,12 @@ const struct bmp280_chip_info bmp180_chip_info = {
.read_temp = bmp180_read_temp,
.read_press = bmp180_read_press,
.read_calib = bmp180_read_calib,
+ .set_mode = bmp180_set_mode,
+ .wait_conv = bmp180_wait_conv,
.trigger_handler = bmp180_trigger_handler,
};
-EXPORT_SYMBOL_NS(bmp180_chip_info, IIO_BMP280);
+EXPORT_SYMBOL_NS(bmp180_chip_info, "IIO_BMP280");
static irqreturn_t bmp085_eoc_irq(int irq, void *d)
{
@@ -2588,15 +3028,18 @@ static irqreturn_t bmp085_eoc_irq(int irq, void *d)
return IRQ_HANDLED;
}
-static int bmp085_fetch_eoc_irq(struct device *dev,
- const char *name,
- int irq,
- struct bmp280_data *data)
+static int bmp085_trigger_probe(struct iio_dev *indio_dev)
{
+ struct bmp280_data *data = iio_priv(indio_dev);
+ struct device *dev = data->dev;
unsigned long irq_trig;
- int ret;
+ int ret, irq;
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
+ irq = fwnode_irq_get(dev_fwnode(dev), 0);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "No interrupt found.\n");
+
+ irq_trig = irq_get_trigger_type(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;
@@ -2604,13 +3047,8 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
init_completion(&data->done);
- ret = devm_request_threaded_irq(dev,
- irq,
- bmp085_eoc_irq,
- NULL,
- irq_trig,
- name,
- data);
+ ret = devm_request_irq(dev, irq, bmp085_eoc_irq, irq_trig,
+ indio_dev->name, data);
if (ret) {
/* Bail out without IRQ but keep the driver in place */
dev_err(dev, "unable to request DRDY IRQ\n");
@@ -2618,14 +3056,54 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
}
data->use_eoc = true;
+
return 0;
}
+/* Identical to bmp180_chip_info + bmp085_trigger_probe */
+const struct bmp280_chip_info bmp085_chip_info = {
+ .id_reg = BMP280_REG_ID,
+ .chip_id = bmp180_chip_ids,
+ .num_chip_id = ARRAY_SIZE(bmp180_chip_ids),
+ .regmap_config = &bmp180_regmap_config,
+ .start_up_time = 2000,
+ .channels = bmp280_channels,
+ .num_channels = ARRAY_SIZE(bmp280_channels),
+ .avail_scan_masks = bmp280_avail_scan_masks,
+
+ .oversampling_temp_avail = bmp180_oversampling_temp_avail,
+ .num_oversampling_temp_avail =
+ ARRAY_SIZE(bmp180_oversampling_temp_avail),
+ .oversampling_temp_default = 0,
+
+ .oversampling_press_avail = bmp180_oversampling_press_avail,
+ .num_oversampling_press_avail =
+ ARRAY_SIZE(bmp180_oversampling_press_avail),
+ .oversampling_press_default = BMP180_MEAS_PRESS_8X,
+
+ .temp_coeffs = bmp180_temp_coeffs,
+ .temp_coeffs_type = IIO_VAL_FRACTIONAL,
+ .press_coeffs = bmp180_press_coeffs,
+ .press_coeffs_type = IIO_VAL_FRACTIONAL,
+
+ .chip_config = bmp180_chip_config,
+ .read_temp = bmp180_read_temp,
+ .read_press = bmp180_read_press,
+ .read_calib = bmp180_read_calib,
+ .set_mode = bmp180_set_mode,
+ .wait_conv = bmp180_wait_conv,
+
+ .trigger_probe = bmp085_trigger_probe,
+ .trigger_handler = bmp180_trigger_handler,
+};
+EXPORT_SYMBOL_NS(bmp085_chip_info, "IIO_BMP280");
+
static int bmp280_buffer_preenable(struct iio_dev *indio_dev)
{
struct bmp280_data *data = iio_priv(indio_dev);
pm_runtime_get_sync(data->dev);
+ data->chip_info->set_mode(data, BMP280_NORMAL);
return 0;
}
@@ -2790,12 +3268,17 @@ int bmp280_common_probe(struct device *dev,
* 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 (irq > 0) {
+ if (data->chip_info->trigger_probe)
+ ret = data->chip_info->trigger_probe(indio_dev);
if (ret)
return ret;
}
+ ret = data->chip_info->set_mode(data, BMP280_SLEEP);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to set sleep mode\n");
+
/* Enable runtime PM */
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
@@ -2814,13 +3297,16 @@ int bmp280_common_probe(struct device *dev,
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS(bmp280_common_probe, IIO_BMP280);
+EXPORT_SYMBOL_NS(bmp280_common_probe, "IIO_BMP280");
static int bmp280_runtime_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct bmp280_data *data = iio_priv(indio_dev);
+ data->chip_info->set_mode(data, BMP280_SLEEP);
+
+ fsleep(data->start_up_time);
return regulator_bulk_disable(BMP280_NUM_SUPPLIES, data->supplies);
}
@@ -2835,7 +3321,12 @@ static int bmp280_runtime_resume(struct device *dev)
return ret;
usleep_range(data->start_up_time, data->start_up_time + 100);
- return data->chip_info->chip_config(data);
+
+ ret = data->chip_info->chip_config(data);
+ if (ret)
+ return ret;
+
+ return data->chip_info->set_mode(data, data->op_mode);
}
EXPORT_RUNTIME_DEV_PM_OPS(bmp280_dev_pm_ops, bmp280_runtime_suspend,