mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-02 13:12:12 -05:00
iio: pressure: bmp280: Add triggered buffer support
BMP2xx, BME280, BMP3xx, and BMP5xx use continuous buffers for their temperature, pressure and humidity readings. This facilitates the use of burst/bulk reads in order to acquire data faster. The approach is different from the one used in oneshot captures. BMP085 & BMP1xx devices use a completely different measurement process that is well defined and is used in their buffer_handler(). Suggested-by: Angel Iglesias <ang.iglesiasg@gmail.com> Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com> Link: https://lore.kernel.org/r/20240512230524.53990-6-vassilisamir@gmail.com Link: https://patch.msgid.link/20240628171726.124852-4-vassilisamir@gmail.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
committed by
Jonathan Cameron
parent
479e67ac64
commit
80cd23f43d
@@ -31,6 +31,8 @@ config BMP280
|
||||
select REGMAP
|
||||
select BMP280_I2C if (I2C)
|
||||
select BMP280_SPI if (SPI_MASTER)
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
Say yes here to build support for Bosch Sensortec BMP180, BMP280, BMP380
|
||||
and BMP580 pressure and temperature sensors. Also supports the BME280 with
|
||||
|
||||
@@ -41,7 +41,10 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
@@ -134,6 +137,12 @@ enum {
|
||||
BMP380_P11 = 20,
|
||||
};
|
||||
|
||||
enum bmp280_scan {
|
||||
BMP280_PRESS,
|
||||
BMP280_TEMP,
|
||||
BME280_HUMID,
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec bmp280_channels[] = {
|
||||
{
|
||||
.type = IIO_PRESSURE,
|
||||
@@ -142,6 +151,13 @@ static const struct iio_chan_spec bmp280_channels[] = {
|
||||
BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE) |
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
|
||||
.scan_index = 0,
|
||||
.scan_type = {
|
||||
.sign = 'u',
|
||||
.realbits = 32,
|
||||
.storagebits = 32,
|
||||
.endianness = IIO_CPU,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
@@ -150,7 +166,15 @@ static const struct iio_chan_spec bmp280_channels[] = {
|
||||
BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE) |
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
|
||||
.scan_index = 1,
|
||||
.scan_type = {
|
||||
.sign = 's',
|
||||
.realbits = 32,
|
||||
.storagebits = 32,
|
||||
.endianness = IIO_CPU,
|
||||
},
|
||||
},
|
||||
IIO_CHAN_SOFT_TIMESTAMP(2),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec bme280_channels[] = {
|
||||
@@ -161,6 +185,13 @@ static const struct iio_chan_spec bme280_channels[] = {
|
||||
BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE) |
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
|
||||
.scan_index = 0,
|
||||
.scan_type = {
|
||||
.sign = 'u',
|
||||
.realbits = 32,
|
||||
.storagebits = 32,
|
||||
.endianness = IIO_CPU,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
@@ -169,6 +200,13 @@ static const struct iio_chan_spec bme280_channels[] = {
|
||||
BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE) |
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
|
||||
.scan_index = 1,
|
||||
.scan_type = {
|
||||
.sign = 's',
|
||||
.realbits = 32,
|
||||
.storagebits = 32,
|
||||
.endianness = IIO_CPU,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = IIO_HUMIDITYRELATIVE,
|
||||
@@ -177,7 +215,15 @@ static const struct iio_chan_spec bme280_channels[] = {
|
||||
BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE) |
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
|
||||
.scan_index = 2,
|
||||
.scan_type = {
|
||||
.sign = 'u',
|
||||
.realbits = 32,
|
||||
.storagebits = 32,
|
||||
.endianness = IIO_CPU,
|
||||
},
|
||||
},
|
||||
IIO_CHAN_SOFT_TIMESTAMP(3),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec bmp380_channels[] = {
|
||||
@@ -190,6 +236,13 @@ static const struct iio_chan_spec bmp380_channels[] = {
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
|
||||
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
|
||||
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
|
||||
.scan_index = 0,
|
||||
.scan_type = {
|
||||
.sign = 'u',
|
||||
.realbits = 32,
|
||||
.storagebits = 32,
|
||||
.endianness = IIO_CPU,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
@@ -200,7 +253,53 @@ static const struct iio_chan_spec bmp380_channels[] = {
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
|
||||
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
|
||||
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
|
||||
.scan_index = 1,
|
||||
.scan_type = {
|
||||
.sign = 's',
|
||||
.realbits = 32,
|
||||
.storagebits = 32,
|
||||
.endianness = IIO_CPU,
|
||||
},
|
||||
},
|
||||
IIO_CHAN_SOFT_TIMESTAMP(2),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec bmp580_channels[] = {
|
||||
{
|
||||
.type = IIO_PRESSURE,
|
||||
/* PROCESSED maintained for ABI backwards compatibility */
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
|
||||
BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE) |
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
|
||||
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
|
||||
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
|
||||
.scan_index = 0,
|
||||
.scan_type = {
|
||||
.sign = 'u',
|
||||
.realbits = 24,
|
||||
.storagebits = 32,
|
||||
.endianness = IIO_LE,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
/* PROCESSED maintained for ABI backwards compatibility */
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
|
||||
BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE) |
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
|
||||
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
|
||||
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
|
||||
.scan_index = 1,
|
||||
.scan_type = {
|
||||
.sign = 's',
|
||||
.realbits = 24,
|
||||
.storagebits = 32,
|
||||
.endianness = IIO_LE,
|
||||
},
|
||||
},
|
||||
IIO_CHAN_SOFT_TIMESTAMP(2),
|
||||
};
|
||||
|
||||
static int bmp280_read_calib(struct bmp280_data *data)
|
||||
@@ -316,7 +415,7 @@ static int bme280_read_humid_adc(struct bmp280_data *data, u16 *adc_humidity)
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME280_REG_HUMIDITY_MSB,
|
||||
&data->be16, sizeof(data->be16));
|
||||
&data->be16, BME280_NUM_HUMIDITY_BYTES);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "failed to read humidity\n");
|
||||
return ret;
|
||||
@@ -362,7 +461,7 @@ static int bmp280_read_temp_adc(struct bmp280_data *data, u32 *adc_temp)
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB,
|
||||
data->buf, sizeof(data->buf));
|
||||
data->buf, BMP280_NUM_TEMP_BYTES);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "failed to read temperature\n");
|
||||
return ret;
|
||||
@@ -423,7 +522,7 @@ static int bmp280_read_press_adc(struct bmp280_data *data, u32 *adc_press)
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB,
|
||||
data->buf, sizeof(data->buf));
|
||||
data->buf, BMP280_NUM_PRESS_BYTES);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "failed to read pressure\n");
|
||||
return ret;
|
||||
@@ -874,6 +973,16 @@ static const struct iio_info bmp280_info = {
|
||||
.write_raw = &bmp280_write_raw,
|
||||
};
|
||||
|
||||
static const unsigned long bmp280_avail_scan_masks[] = {
|
||||
BIT(BMP280_TEMP) | BIT(BMP280_PRESS),
|
||||
0
|
||||
};
|
||||
|
||||
static const unsigned long bme280_avail_scan_masks[] = {
|
||||
BIT(BME280_HUMID) | BIT(BMP280_TEMP) | BIT(BMP280_PRESS),
|
||||
0
|
||||
};
|
||||
|
||||
static int bmp280_chip_config(struct bmp280_data *data)
|
||||
{
|
||||
u8 osrs = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp + 1) |
|
||||
@@ -901,6 +1010,53 @@ static int bmp280_chip_config(struct bmp280_data *data)
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&data->lock);
|
||||
|
||||
/* Burst read data registers */
|
||||
ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB,
|
||||
data->buf, BMP280_BURST_READ_BYTES);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "failed to burst read sensor data\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Temperature calculations */
|
||||
adc_temp = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[3]));
|
||||
if (adc_temp == BMP280_TEMP_SKIPPED) {
|
||||
dev_err(data->dev, "reading temperature skipped\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
data->sensor_data[1] = bmp280_compensate_temp(data, adc_temp);
|
||||
|
||||
/* Pressure calculations */
|
||||
adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[0]));
|
||||
if (adc_press == BMP280_PRESS_SKIPPED) {
|
||||
dev_err(data->dev, "reading pressure skipped\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
t_fine = bmp280_calc_t_fine(data, adc_temp);
|
||||
|
||||
data->sensor_data[0] = bmp280_compensate_press(data, adc_press, t_fine);
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
out:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const int bmp280_oversampling_avail[] = { 1, 2, 4, 8, 16 };
|
||||
static const u8 bmp280_chip_ids[] = { BMP280_CHIP_ID };
|
||||
static const int bmp280_temp_coeffs[] = { 10, 1 };
|
||||
@@ -914,6 +1070,7 @@ const struct bmp280_chip_info bmp280_chip_info = {
|
||||
.start_up_time = 2000,
|
||||
.channels = bmp280_channels,
|
||||
.num_channels = ARRAY_SIZE(bmp280_channels),
|
||||
.avail_scan_masks = bmp280_avail_scan_masks,
|
||||
|
||||
.oversampling_temp_avail = bmp280_oversampling_avail,
|
||||
.num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail),
|
||||
@@ -942,6 +1099,8 @@ const struct bmp280_chip_info bmp280_chip_info = {
|
||||
.read_temp = bmp280_read_temp,
|
||||
.read_press = bmp280_read_press,
|
||||
.read_calib = bmp280_read_calib,
|
||||
|
||||
.trigger_handler = bmp280_trigger_handler,
|
||||
};
|
||||
EXPORT_SYMBOL_NS(bmp280_chip_info, IIO_BMP280);
|
||||
|
||||
@@ -964,6 +1123,62 @@ static int bme280_chip_config(struct bmp280_data *data)
|
||||
return bmp280_chip_config(data);
|
||||
}
|
||||
|
||||
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;
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&data->lock);
|
||||
|
||||
/* Burst read data registers */
|
||||
ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB,
|
||||
data->buf, BME280_BURST_READ_BYTES);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "failed to burst read sensor data\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Temperature calculations */
|
||||
adc_temp = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[3]));
|
||||
if (adc_temp == BMP280_TEMP_SKIPPED) {
|
||||
dev_err(data->dev, "reading temperature skipped\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
data->sensor_data[1] = bmp280_compensate_temp(data, adc_temp);
|
||||
|
||||
/* Pressure calculations */
|
||||
adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[0]));
|
||||
if (adc_press == BMP280_PRESS_SKIPPED) {
|
||||
dev_err(data->dev, "reading pressure skipped\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
t_fine = bmp280_calc_t_fine(data, adc_temp);
|
||||
|
||||
data->sensor_data[0] = bmp280_compensate_press(data, adc_press, t_fine);
|
||||
|
||||
/* Humidity calculations */
|
||||
adc_humidity = get_unaligned_be16(&data->buf[6]);
|
||||
|
||||
if (adc_humidity == BMP280_HUMIDITY_SKIPPED) {
|
||||
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,
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
out:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const u8 bme280_chip_ids[] = { BME280_CHIP_ID };
|
||||
static const int bme280_humid_coeffs[] = { 1000, 1024 };
|
||||
|
||||
@@ -975,6 +1190,7 @@ const struct bmp280_chip_info bme280_chip_info = {
|
||||
.start_up_time = 2000,
|
||||
.channels = bme280_channels,
|
||||
.num_channels = ARRAY_SIZE(bme280_channels),
|
||||
.avail_scan_masks = bme280_avail_scan_masks,
|
||||
|
||||
.oversampling_temp_avail = bmp280_oversampling_avail,
|
||||
.num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail),
|
||||
@@ -1000,6 +1216,8 @@ const struct bmp280_chip_info bme280_chip_info = {
|
||||
.read_press = bmp280_read_press,
|
||||
.read_humid = bme280_read_humid,
|
||||
.read_calib = bme280_read_calib,
|
||||
|
||||
.trigger_handler = bme280_trigger_handler,
|
||||
};
|
||||
EXPORT_SYMBOL_NS(bme280_chip_info, IIO_BMP280);
|
||||
|
||||
@@ -1054,7 +1272,7 @@ static int bmp380_read_temp_adc(struct bmp280_data *data, u32 *adc_temp)
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BMP380_REG_TEMP_XLSB,
|
||||
data->buf, sizeof(data->buf));
|
||||
data->buf, BMP280_NUM_TEMP_BYTES);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "failed to read temperature\n");
|
||||
return ret;
|
||||
@@ -1123,7 +1341,7 @@ static int bmp380_read_press_adc(struct bmp280_data *data, u32 *adc_press)
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BMP380_REG_PRESS_XLSB,
|
||||
data->buf, sizeof(data->buf));
|
||||
data->buf, BMP280_NUM_PRESS_BYTES);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "failed to read pressure\n");
|
||||
return ret;
|
||||
@@ -1384,6 +1602,53 @@ static int bmp380_chip_config(struct bmp280_data *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&data->lock);
|
||||
|
||||
/* Burst read data registers */
|
||||
ret = regmap_bulk_read(data->regmap, BMP380_REG_PRESS_XLSB,
|
||||
data->buf, BMP280_BURST_READ_BYTES);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "failed to burst read sensor data\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Temperature calculations */
|
||||
adc_temp = get_unaligned_le24(&data->buf[3]);
|
||||
if (adc_temp == BMP380_TEMP_SKIPPED) {
|
||||
dev_err(data->dev, "reading temperature skipped\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
data->sensor_data[1] = bmp380_compensate_temp(data, adc_temp);
|
||||
|
||||
/* Pressure calculations */
|
||||
adc_press = get_unaligned_le24(&data->buf[0]);
|
||||
if (adc_press == BMP380_PRESS_SKIPPED) {
|
||||
dev_err(data->dev, "reading pressure skipped\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
t_fine = bmp380_calc_t_fine(data, adc_temp);
|
||||
|
||||
data->sensor_data[0] = bmp380_compensate_press(data, adc_press, t_fine);
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
out:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const int bmp380_oversampling_avail[] = { 1, 2, 4, 8, 16, 32 };
|
||||
static const int bmp380_iir_filter_coeffs_avail[] = { 1, 2, 4, 8, 16, 32, 64, 128};
|
||||
static const u8 bmp380_chip_ids[] = { BMP380_CHIP_ID, BMP390_CHIP_ID };
|
||||
@@ -1399,6 +1664,7 @@ const struct bmp280_chip_info bmp380_chip_info = {
|
||||
.start_up_time = 2000,
|
||||
.channels = bmp380_channels,
|
||||
.num_channels = ARRAY_SIZE(bmp380_channels),
|
||||
.avail_scan_masks = bmp280_avail_scan_masks,
|
||||
|
||||
.oversampling_temp_avail = bmp380_oversampling_avail,
|
||||
.num_oversampling_temp_avail = ARRAY_SIZE(bmp380_oversampling_avail),
|
||||
@@ -1426,6 +1692,8 @@ const struct bmp280_chip_info bmp380_chip_info = {
|
||||
.read_press = bmp380_read_press,
|
||||
.read_calib = bmp380_read_calib,
|
||||
.preinit = bmp380_preinit,
|
||||
|
||||
.trigger_handler = bmp380_trigger_handler,
|
||||
};
|
||||
EXPORT_SYMBOL_NS(bmp380_chip_info, IIO_BMP280);
|
||||
|
||||
@@ -1546,8 +1814,8 @@ static int bmp580_read_temp(struct bmp280_data *data, s32 *raw_temp)
|
||||
s32 value_temp;
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BMP580_REG_TEMP_XLSB, data->buf,
|
||||
sizeof(data->buf));
|
||||
ret = regmap_bulk_read(data->regmap, BMP580_REG_TEMP_XLSB,
|
||||
data->buf, BMP280_NUM_TEMP_BYTES);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "failed to read temperature\n");
|
||||
return ret;
|
||||
@@ -1568,8 +1836,8 @@ static int bmp580_read_press(struct bmp280_data *data, u32 *raw_press)
|
||||
u32 value_press;
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BMP580_REG_PRESS_XLSB, data->buf,
|
||||
sizeof(data->buf));
|
||||
ret = regmap_bulk_read(data->regmap, BMP580_REG_PRESS_XLSB,
|
||||
data->buf, BMP280_NUM_PRESS_BYTES);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "failed to read pressure\n");
|
||||
return ret;
|
||||
@@ -1916,6 +2184,38 @@ static int bmp580_chip_config(struct bmp280_data *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
guard(mutex)(&data->lock);
|
||||
|
||||
/* Burst read data registers */
|
||||
ret = regmap_bulk_read(data->regmap, BMP580_REG_TEMP_XLSB,
|
||||
data->buf, BMP280_BURST_READ_BYTES);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "failed to burst read sensor data\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Temperature calculations */
|
||||
memcpy(&data->sensor_data[1], &data->buf[0], 3);
|
||||
|
||||
/* Pressure calculations */
|
||||
memcpy(&data->sensor_data[0], &data->buf[3], 3);
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
out:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const int bmp580_oversampling_avail[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
|
||||
static const u8 bmp580_chip_ids[] = { BMP580_CHIP_ID, BMP580_CHIP_ID_ALT };
|
||||
/* Instead of { 1000, 16 } we do this, to avoid overflow issues */
|
||||
@@ -1928,8 +2228,9 @@ const struct bmp280_chip_info bmp580_chip_info = {
|
||||
.num_chip_id = ARRAY_SIZE(bmp580_chip_ids),
|
||||
.regmap_config = &bmp580_regmap_config,
|
||||
.start_up_time = 2000,
|
||||
.channels = bmp380_channels,
|
||||
.num_channels = ARRAY_SIZE(bmp380_channels),
|
||||
.channels = bmp580_channels,
|
||||
.num_channels = ARRAY_SIZE(bmp580_channels),
|
||||
.avail_scan_masks = bmp280_avail_scan_masks,
|
||||
|
||||
.oversampling_temp_avail = bmp580_oversampling_avail,
|
||||
.num_oversampling_temp_avail = ARRAY_SIZE(bmp580_oversampling_avail),
|
||||
@@ -1956,6 +2257,8 @@ const struct bmp280_chip_info bmp580_chip_info = {
|
||||
.read_temp = bmp580_read_temp,
|
||||
.read_press = bmp580_read_press,
|
||||
.preinit = bmp580_preinit,
|
||||
|
||||
.trigger_handler = bmp580_trigger_handler,
|
||||
};
|
||||
EXPORT_SYMBOL_NS(bmp580_chip_info, IIO_BMP280);
|
||||
|
||||
@@ -2134,7 +2437,7 @@ static int bmp180_read_press_adc(struct bmp280_data *data, u32 *adc_press)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB,
|
||||
data->buf, sizeof(data->buf));
|
||||
data->buf, BMP280_NUM_PRESS_BYTES);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "failed to read pressure\n");
|
||||
return ret;
|
||||
@@ -2205,6 +2508,36 @@ static int bmp180_chip_config(struct bmp280_data *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
guard(mutex)(&data->lock);
|
||||
|
||||
ret = bmp180_read_temp(data, &chan_value);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
data->sensor_data[1] = chan_value;
|
||||
|
||||
ret = bmp180_read_press(data, &chan_value);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
data->sensor_data[0] = chan_value;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
out:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const int bmp180_oversampling_temp_avail[] = { 1 };
|
||||
static const int bmp180_oversampling_press_avail[] = { 1, 2, 4, 8 };
|
||||
static const u8 bmp180_chip_ids[] = { BMP180_CHIP_ID };
|
||||
@@ -2219,6 +2552,7 @@ const struct bmp280_chip_info bmp180_chip_info = {
|
||||
.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 =
|
||||
@@ -2239,6 +2573,8 @@ const struct bmp280_chip_info bmp180_chip_info = {
|
||||
.read_temp = bmp180_read_temp,
|
||||
.read_press = bmp180_read_press,
|
||||
.read_calib = bmp180_read_calib,
|
||||
|
||||
.trigger_handler = bmp180_trigger_handler,
|
||||
};
|
||||
EXPORT_SYMBOL_NS(bmp180_chip_info, IIO_BMP280);
|
||||
|
||||
@@ -2284,6 +2620,30 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bmp280_buffer_preenable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct bmp280_data *data = iio_priv(indio_dev);
|
||||
|
||||
pm_runtime_get_sync(data->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bmp280_buffer_postdisable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct bmp280_data *data = iio_priv(indio_dev);
|
||||
|
||||
pm_runtime_mark_last_busy(data->dev);
|
||||
pm_runtime_put_autosuspend(data->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iio_buffer_setup_ops bmp280_buffer_setup_ops = {
|
||||
.preenable = bmp280_buffer_preenable,
|
||||
.postdisable = bmp280_buffer_postdisable,
|
||||
};
|
||||
|
||||
static void bmp280_pm_disable(void *data)
|
||||
{
|
||||
struct device *dev = data;
|
||||
@@ -2330,6 +2690,7 @@ int bmp280_common_probe(struct device *dev,
|
||||
/* Apply initial values from chip info structure */
|
||||
indio_dev->channels = chip_info->channels;
|
||||
indio_dev->num_channels = chip_info->num_channels;
|
||||
indio_dev->available_scan_masks = chip_info->avail_scan_masks;
|
||||
data->oversampling_press = chip_info->oversampling_press_default;
|
||||
data->oversampling_humid = chip_info->oversampling_humid_default;
|
||||
data->oversampling_temp = chip_info->oversampling_temp_default;
|
||||
@@ -2415,6 +2776,14 @@ int bmp280_common_probe(struct device *dev,
|
||||
"failed to read calibration coefficients\n");
|
||||
}
|
||||
|
||||
ret = devm_iio_triggered_buffer_setup(data->dev, indio_dev,
|
||||
iio_pollfunc_store_time,
|
||||
data->chip_info->trigger_handler,
|
||||
&bmp280_buffer_setup_ops);
|
||||
if (ret)
|
||||
return dev_err_probe(data->dev, ret,
|
||||
"iio triggered buffer setup failed\n");
|
||||
|
||||
/*
|
||||
* Attempt to grab an optional EOC IRQ - only the BMP085 has this
|
||||
* however as it happens, the BMP085 shares the chip ID of BMP180
|
||||
|
||||
@@ -40,14 +40,10 @@ static int bmp380_regmap_spi_read(void *context, const void *reg,
|
||||
size_t reg_size, void *val, size_t val_size)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(context);
|
||||
u8 rx_buf[4];
|
||||
u8 rx_buf[BME280_BURST_READ_BYTES + 1];
|
||||
ssize_t status;
|
||||
|
||||
/*
|
||||
* Maximum number of consecutive bytes read for a temperature or
|
||||
* pressure measurement is 3.
|
||||
*/
|
||||
if (val_size > 3)
|
||||
if (val_size > BME280_BURST_READ_BYTES)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
|
||||
@@ -304,6 +304,16 @@
|
||||
#define BMP280_PRESS_SKIPPED 0x80000
|
||||
#define BMP280_HUMIDITY_SKIPPED 0x8000
|
||||
|
||||
/* Number of bytes for each value */
|
||||
#define BMP280_NUM_PRESS_BYTES 3
|
||||
#define BMP280_NUM_TEMP_BYTES 3
|
||||
#define BME280_NUM_HUMIDITY_BYTES 2
|
||||
#define BMP280_BURST_READ_BYTES (BMP280_NUM_PRESS_BYTES + \
|
||||
BMP280_NUM_TEMP_BYTES)
|
||||
#define BME280_BURST_READ_BYTES (BMP280_NUM_PRESS_BYTES + \
|
||||
BMP280_NUM_TEMP_BYTES + \
|
||||
BME280_NUM_HUMIDITY_BYTES)
|
||||
|
||||
/* Core exported structs */
|
||||
|
||||
static const char *const bmp280_supply_names[] = {
|
||||
@@ -397,13 +407,19 @@ struct bmp280_data {
|
||||
*/
|
||||
int sampling_freq;
|
||||
|
||||
/*
|
||||
* Data to push to userspace triggered buffer. Up to 3 channels and
|
||||
* s64 timestamp, aligned.
|
||||
*/
|
||||
s32 sensor_data[6] __aligned(8);
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
*/
|
||||
union {
|
||||
/* Sensor data buffer */
|
||||
u8 buf[3];
|
||||
u8 buf[BME280_BURST_READ_BYTES];
|
||||
/* Calibration data buffers */
|
||||
__le16 bmp280_cal_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
|
||||
__be16 bmp180_cal_buf[BMP180_REG_CALIB_COUNT / 2];
|
||||
@@ -425,6 +441,7 @@ struct bmp280_chip_info {
|
||||
const struct iio_chan_spec *channels;
|
||||
int num_channels;
|
||||
unsigned int start_up_time;
|
||||
const unsigned long *avail_scan_masks;
|
||||
|
||||
const int *oversampling_temp_avail;
|
||||
int num_oversampling_temp_avail;
|
||||
@@ -459,6 +476,8 @@ struct bmp280_chip_info {
|
||||
int (*read_humid)(struct bmp280_data *data, u32 *adc_humidity);
|
||||
int (*read_calib)(struct bmp280_data *data);
|
||||
int (*preinit)(struct bmp280_data *data);
|
||||
|
||||
irqreturn_t (*trigger_handler)(int irq, void *p);
|
||||
};
|
||||
|
||||
/* Chip infos for each variant */
|
||||
|
||||
Reference in New Issue
Block a user