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.c177
1 files changed, 101 insertions, 76 deletions
diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index a8b97b9b0461..682329f81886 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -340,10 +340,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 +361,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 +369,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;
}
@@ -983,6 +964,33 @@ 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 int bmp280_chip_config(struct bmp280_data *data)
{
u8 osrs = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp + 1) |
@@ -1015,7 +1023,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 +1045,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 +1055,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,6 +1111,7 @@ const struct bmp280_chip_info bmp280_chip_info = {
.read_temp = bmp280_read_temp,
.read_press = bmp280_read_press,
.read_calib = bmp280_read_calib,
+ .preinit = bmp280_preinit,
.trigger_handler = bmp280_trigger_handler,
};
@@ -1128,7 +1141,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 +1163,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 +1173,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 +1182,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:
@@ -1216,6 +1235,7 @@ const struct bmp280_chip_info bme280_chip_info = {
.read_press = bmp280_read_press,
.read_humid = bme280_read_humid,
.read_calib = bme280_read_calib,
+ .preinit = bmp280_preinit,
.trigger_handler = bme280_trigger_handler,
};
@@ -1545,14 +1565,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) {
/*
@@ -1608,7 +1626,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 +1648,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 +1658,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:
@@ -2141,15 +2163,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,
@@ -2190,7 +2210,7 @@ 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 +2222,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);
+
+ /* Temperature calculations */
+ memcpy(&data->sensor_data[offset], &data->buf[0], 3);
- 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:
@@ -2514,23 +2538,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:
@@ -2596,7 +2621,7 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
unsigned long irq_trig;
int ret;
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
+ 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;