diff options
Diffstat (limited to 'drivers/iio/pressure/bmp280-core.c')
-rw-r--r-- | drivers/iio/pressure/bmp280-core.c | 177 |
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, ®); + 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; |