summaryrefslogtreecommitdiffstats
path: root/drivers/iio/pressure
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/pressure')
-rw-r--r--drivers/iio/pressure/Kconfig6
-rw-r--r--drivers/iio/pressure/bmp280-core.c765
-rw-r--r--drivers/iio/pressure/bmp280-i2c.c45
-rw-r--r--drivers/iio/pressure/bmp280-regmap.c60
-rw-r--r--drivers/iio/pressure/bmp280-spi.c47
-rw-r--r--drivers/iio/pressure/bmp280.h273
-rw-r--r--drivers/iio/pressure/zpa2326.c2
7 files changed, 952 insertions, 246 deletions
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index c9453389e4f7..02b97e89de50 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -17,14 +17,14 @@ config ABP060MG
will be called abp060mg.
config BMP280
- tristate "Bosch Sensortec BMP180/BMP280/BMP380 pressure sensor I2C driver"
+ tristate "Bosch Sensortec BMP180/BMP280/BMP380/BMP580 pressure sensor driver"
depends on (I2C || SPI_MASTER)
select REGMAP
select BMP280_I2C if (I2C)
select BMP280_SPI if (SPI_MASTER)
help
- Say yes here to build support for Bosch Sensortec BMP180, BMP280 and
- BMP380 pressure and temperature sensors. Also supports the BME280 with
+ Say yes here to build support for Bosch Sensortec BMP180, BMP280, BMP380
+ and BMP580 pressure and temperature sensors. Also supports the BME280 with
an additional humidity sensor channel.
To compile this driver as a module, choose M here: the core module
diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index c0aff78489b4..6089f3f9d8f4 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -13,6 +13,7 @@
* https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp280-ds001.pdf
* https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme280-ds002.pdf
* https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp388-ds001.pdf
+ * https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp581-ds004.pdf
*
* Notice:
* The link to the bmp180 datasheet points to an outdated version missing these changes:
@@ -27,6 +28,7 @@
#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/module.h>
+#include <linux/nvmem-provider.h>
#include <linux/regmap.h>
#include <linux/delay.h>
#include <linux/iio/iio.h>
@@ -49,65 +51,6 @@
*/
enum { AC1, AC2, AC3, AC4, AC5, AC6, B1, B2, MB, MC, MD };
-struct bmp180_calib {
- s16 AC1;
- s16 AC2;
- s16 AC3;
- u16 AC4;
- u16 AC5;
- u16 AC6;
- s16 B1;
- s16 B2;
- s16 MB;
- s16 MC;
- s16 MD;
-};
-
-/* See datasheet Section 4.2.2. */
-struct bmp280_calib {
- u16 T1;
- s16 T2;
- s16 T3;
- u16 P1;
- s16 P2;
- s16 P3;
- s16 P4;
- s16 P5;
- s16 P6;
- s16 P7;
- s16 P8;
- s16 P9;
- u8 H1;
- s16 H2;
- u8 H3;
- s16 H4;
- s16 H5;
- s8 H6;
-};
-
-/* See datasheet Section 3.11.1. */
-struct bmp380_calib {
- u16 T1;
- u16 T2;
- s8 T3;
- s16 P1;
- s16 P2;
- s8 P3;
- s8 P4;
- u16 P5;
- u16 P6;
- s8 P7;
- s8 P8;
- s16 P9;
- s8 P10;
- s8 P11;
-};
-
-static const char *const bmp280_supply_names[] = {
- "vddd", "vdda"
-};
-
-#define BMP280_NUM_SUPPLIES ARRAY_SIZE(bmp280_supply_names)
enum bmp380_odr {
BMP380_ODR_200HZ,
@@ -130,92 +73,39 @@ enum bmp380_odr {
BMP380_ODR_0_0015HZ,
};
-struct bmp280_data {
- struct device *dev;
- struct mutex lock;
- struct regmap *regmap;
- struct completion done;
- bool use_eoc;
- const struct bmp280_chip_info *chip_info;
- union {
- struct bmp180_calib bmp180;
- struct bmp280_calib bmp280;
- struct bmp380_calib bmp380;
- } calib;
- struct regulator_bulk_data supplies[BMP280_NUM_SUPPLIES];
- unsigned int start_up_time; /* in microseconds */
-
- /* log of base 2 of oversampling rate */
- u8 oversampling_press;
- u8 oversampling_temp;
- u8 oversampling_humid;
- u8 iir_filter_coeff;
-
- /*
- * BMP380 devices introduce sampling frequency configuration. See
- * datasheet sections 3.3.3. and 4.3.19 for more details.
- *
- * BMx280 devices allowed indirect configuration of sampling frequency
- * changing the t_standby duration between measurements, as detailed on
- * section 3.6.3 of the datasheet.
- */
- int sampling_freq;
-
- /*
- * Carryover value from temperature conversion, used in pressure
- * calculation.
- */
- s32 t_fine;
-
- /*
- * DMA (thus cache coherency maintenance) may require the
- * transfer buffers to live in their own cache lines.
- */
- union {
- /* Sensor data buffer */
- u8 buf[3];
- /* Calibration data buffers */
- __le16 bmp280_cal_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
- __be16 bmp180_cal_buf[BMP180_REG_CALIB_COUNT / 2];
- u8 bmp380_cal_buf[BMP380_CALIB_REG_COUNT];
- /* Miscellaneous, endianess-aware data buffers */
- __le16 le16;
- __be16 be16;
- } __aligned(IIO_DMA_MINALIGN);
-};
-
-struct bmp280_chip_info {
- unsigned int id_reg;
-
- const struct iio_chan_spec *channels;
- int num_channels;
- unsigned int start_up_time;
-
- const int *oversampling_temp_avail;
- int num_oversampling_temp_avail;
- int oversampling_temp_default;
-
- const int *oversampling_press_avail;
- int num_oversampling_press_avail;
- int oversampling_press_default;
-
- const int *oversampling_humid_avail;
- int num_oversampling_humid_avail;
- int oversampling_humid_default;
-
- const int *iir_filter_coeffs_avail;
- int num_iir_filter_coeffs_avail;
- int iir_filter_coeff_default;
-
- const int (*sampling_freq_avail)[2];
- int num_sampling_freq_avail;
- int sampling_freq_default;
-
- int (*chip_config)(struct bmp280_data *);
- int (*read_temp)(struct bmp280_data *, int *);
- int (*read_press)(struct bmp280_data *, int *, int *);
- int (*read_humid)(struct bmp280_data *, int *, int *);
- int (*read_calib)(struct bmp280_data *);
+enum bmp580_odr {
+ BMP580_ODR_240HZ,
+ BMP580_ODR_218HZ,
+ BMP580_ODR_199HZ,
+ BMP580_ODR_179HZ,
+ BMP580_ODR_160HZ,
+ BMP580_ODR_149HZ,
+ BMP580_ODR_140HZ,
+ BMP580_ODR_129HZ,
+ BMP580_ODR_120HZ,
+ BMP580_ODR_110HZ,
+ BMP580_ODR_100HZ,
+ BMP580_ODR_89HZ,
+ BMP580_ODR_80HZ,
+ BMP580_ODR_70HZ,
+ BMP580_ODR_60HZ,
+ BMP580_ODR_50HZ,
+ BMP580_ODR_45HZ,
+ BMP580_ODR_40HZ,
+ BMP580_ODR_35HZ,
+ BMP580_ODR_30HZ,
+ BMP580_ODR_25HZ,
+ BMP580_ODR_20HZ,
+ BMP580_ODR_15HZ,
+ BMP580_ODR_10HZ,
+ BMP580_ODR_5HZ,
+ BMP580_ODR_4HZ,
+ BMP580_ODR_3HZ,
+ BMP580_ODR_2HZ,
+ BMP580_ODR_1HZ,
+ BMP580_ODR_0_5HZ,
+ BMP580_ODR_0_25HZ,
+ BMP580_ODR_0_125HZ,
};
/*
@@ -473,7 +363,7 @@ static u32 bmp280_compensate_press(struct bmp280_data *data,
}
static int bmp280_read_temp(struct bmp280_data *data,
- int *val)
+ int *val, int *val2)
{
s32 adc_temp, comp_temp;
int ret;
@@ -513,7 +403,7 @@ static int bmp280_read_press(struct bmp280_data *data,
int ret;
/* Read and compensate temperature so we get a reading of t_fine. */
- ret = bmp280_read_temp(data, NULL);
+ ret = bmp280_read_temp(data, NULL, NULL);
if (ret < 0)
return ret;
@@ -545,7 +435,7 @@ static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
int ret;
/* Read and compensate temperature so we get a reading of t_fine. */
- ret = bmp280_read_temp(data, NULL);
+ ret = bmp280_read_temp(data, NULL, NULL);
if (ret < 0)
return ret;
@@ -589,7 +479,7 @@ static int bmp280_read_raw(struct iio_dev *indio_dev,
ret = data->chip_info->read_press(data, val, val2);
break;
case IIO_TEMP:
- ret = data->chip_info->read_temp(data, val);
+ ret = data->chip_info->read_temp(data, val, val2);
break;
default:
ret = -EINVAL;
@@ -905,8 +795,10 @@ static int bmp280_chip_config(struct bmp280_data *data)
static const int bmp280_oversampling_avail[] = { 1, 2, 4, 8, 16 };
-static const struct bmp280_chip_info bmp280_chip_info = {
+const struct bmp280_chip_info bmp280_chip_info = {
.id_reg = BMP280_REG_ID,
+ .chip_id = BMP280_CHIP_ID,
+ .regmap_config = &bmp280_regmap_config,
.start_up_time = 2000,
.channels = bmp280_channels,
.num_channels = 2,
@@ -934,6 +826,7 @@ static const struct bmp280_chip_info bmp280_chip_info = {
.read_press = bmp280_read_press,
.read_calib = bmp280_read_calib,
};
+EXPORT_SYMBOL_NS(bmp280_chip_info, IIO_BMP280);
static int bme280_chip_config(struct bmp280_data *data)
{
@@ -953,8 +846,10 @@ static int bme280_chip_config(struct bmp280_data *data)
return bmp280_chip_config(data);
}
-static const struct bmp280_chip_info bme280_chip_info = {
+const struct bmp280_chip_info bme280_chip_info = {
.id_reg = BMP280_REG_ID,
+ .chip_id = BME280_CHIP_ID,
+ .regmap_config = &bmp280_regmap_config,
.start_up_time = 2000,
.channels = bmp280_channels,
.num_channels = 3,
@@ -977,6 +872,7 @@ static const struct bmp280_chip_info bme280_chip_info = {
.read_humid = bmp280_read_humid,
.read_calib = bme280_read_calib,
};
+EXPORT_SYMBOL_NS(bme280_chip_info, IIO_BMP280);
/*
* Helper function to send a command to BMP3XX sensors.
@@ -1095,7 +991,7 @@ static u32 bmp380_compensate_press(struct bmp280_data *data, u32 adc_press)
return comp_press;
}
-static int bmp380_read_temp(struct bmp280_data *data, int *val)
+static int bmp380_read_temp(struct bmp280_data *data, int *val, int *val2)
{
s32 comp_temp;
u32 adc_temp;
@@ -1135,7 +1031,7 @@ static int bmp380_read_press(struct bmp280_data *data, int *val, int *val2)
int ret;
/* Read and compensate for temperature so we get a reading of t_fine */
- ret = bmp380_read_temp(data, NULL);
+ ret = bmp380_read_temp(data, NULL, NULL);
if (ret)
return ret;
@@ -1217,6 +1113,12 @@ static const int bmp380_odr_table[][2] = {
[BMP380_ODR_0_0015HZ] = {0, 1526},
};
+static int bmp380_preinit(struct bmp280_data *data)
+{
+ /* BMP3xx requires soft-reset as part of initialization */
+ return bmp380_cmd(data, BMP380_CMD_SOFT_RESET);
+}
+
static int bmp380_chip_config(struct bmp280_data *data)
{
bool change = false, aux;
@@ -1319,8 +1221,10 @@ static int bmp380_chip_config(struct bmp280_data *data)
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 struct bmp280_chip_info bmp380_chip_info = {
+const struct bmp280_chip_info bmp380_chip_info = {
.id_reg = BMP380_REG_ID,
+ .chip_id = BMP380_CHIP_ID,
+ .regmap_config = &bmp380_regmap_config,
.start_up_time = 2000,
.channels = bmp380_channels,
.num_channels = 2,
@@ -1345,7 +1249,508 @@ static const struct bmp280_chip_info bmp380_chip_info = {
.read_temp = bmp380_read_temp,
.read_press = bmp380_read_press,
.read_calib = bmp380_read_calib,
+ .preinit = bmp380_preinit,
+};
+EXPORT_SYMBOL_NS(bmp380_chip_info, IIO_BMP280);
+
+static int bmp580_soft_reset(struct bmp280_data *data)
+{
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_write(data->regmap, BMP580_REG_CMD, BMP580_CMD_SOFT_RESET);
+ if (ret) {
+ dev_err(data->dev, "failed to send reset command to device\n");
+ return ret;
+ }
+ usleep_range(2000, 2500);
+
+ /* Dummy read of chip_id */
+ ret = regmap_read(data->regmap, BMP580_REG_CHIP_ID, &reg);
+ if (ret) {
+ dev_err(data->dev, "failed to reestablish comms after reset\n");
+ return ret;
+ }
+
+ ret = regmap_read(data->regmap, BMP580_REG_INT_STATUS, &reg);
+ if (ret) {
+ dev_err(data->dev, "error reading interrupt status register\n");
+ return ret;
+ }
+ if (!(reg & BMP580_INT_STATUS_POR_MASK)) {
+ dev_err(data->dev, "error resetting sensor\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * bmp580_nvm_operation() - Helper function to commit NVM memory operations
+ * @data: sensor data struct
+ * @is_write: flag to signal write operation
+ */
+static int bmp580_nvm_operation(struct bmp280_data *data, bool is_write)
+{
+ unsigned long timeout, poll;
+ unsigned int reg;
+ int ret;
+
+ /* Check NVM ready flag */
+ ret = regmap_read(data->regmap, BMP580_REG_STATUS, &reg);
+ if (ret) {
+ dev_err(data->dev, "failed to check nvm status\n");
+ return ret;
+ }
+ if (!(reg & BMP580_STATUS_NVM_RDY_MASK)) {
+ dev_err(data->dev, "sensor's nvm is not ready\n");
+ return -EIO;
+ }
+
+ /* Start NVM operation sequence */
+ ret = regmap_write(data->regmap, BMP580_REG_CMD, BMP580_CMD_NVM_OP_SEQ_0);
+ if (ret) {
+ dev_err(data->dev, "failed to send nvm operation's first sequence\n");
+ return ret;
+ }
+ if (is_write) {
+ /* Send NVM write sequence */
+ ret = regmap_write(data->regmap, BMP580_REG_CMD,
+ BMP580_CMD_NVM_WRITE_SEQ_1);
+ if (ret) {
+ dev_err(data->dev, "failed to send nvm write sequence\n");
+ return ret;
+ }
+ /* Datasheet says on 4.8.1.2 it takes approximately 10ms */
+ poll = 2000;
+ timeout = 12000;
+ } else {
+ /* Send NVM read sequence */
+ ret = regmap_write(data->regmap, BMP580_REG_CMD,
+ BMP580_CMD_NVM_READ_SEQ_1);
+ if (ret) {
+ dev_err(data->dev, "failed to send nvm read sequence\n");
+ return ret;
+ }
+ /* Datasheet says on 4.8.1.1 it takes approximately 200us */
+ poll = 50;
+ timeout = 400;
+ }
+ if (ret) {
+ dev_err(data->dev, "failed to write command sequence\n");
+ return -EIO;
+ }
+
+ /* Wait until NVM is ready again */
+ ret = regmap_read_poll_timeout(data->regmap, BMP580_REG_STATUS, reg,
+ (reg & BMP580_STATUS_NVM_RDY_MASK),
+ poll, timeout);
+ if (ret) {
+ dev_err(data->dev, "error checking nvm operation status\n");
+ return ret;
+ }
+
+ /* Check NVM error flags */
+ if ((reg & BMP580_STATUS_NVM_ERR_MASK) || (reg & BMP580_STATUS_NVM_CMD_ERR_MASK)) {
+ dev_err(data->dev, "error processing nvm operation\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/*
+ * Contrary to previous sensors families, compensation algorithm is builtin.
+ * We are only required to read the register raw data and adapt the ranges
+ * for what is expected on IIO ABI.
+ */
+
+static int bmp580_read_temp(struct bmp280_data *data, int *val, int *val2)
+{
+ s32 raw_temp;
+ int ret;
+
+ ret = regmap_bulk_read(data->regmap, BMP580_REG_TEMP_XLSB, data->buf,
+ sizeof(data->buf));
+ if (ret) {
+ dev_err(data->dev, "failed to read temperature\n");
+ return ret;
+ }
+
+ raw_temp = get_unaligned_le24(data->buf);
+ if (raw_temp == BMP580_TEMP_SKIPPED) {
+ dev_err(data->dev, "reading temperature skipped\n");
+ return -EIO;
+ }
+
+ /*
+ * Temperature is returned in Celsius degrees in fractional
+ * form down 2^16. We reescale by x1000 to return milli Celsius
+ * to respect IIO ABI.
+ */
+ *val = raw_temp * 1000;
+ *val2 = 16;
+ return IIO_VAL_FRACTIONAL_LOG2;
+}
+
+static int bmp580_read_press(struct bmp280_data *data, int *val, int *val2)
+{
+ u32 raw_press;
+ int ret;
+
+ ret = regmap_bulk_read(data->regmap, BMP580_REG_PRESS_XLSB, data->buf,
+ sizeof(data->buf));
+ if (ret) {
+ dev_err(data->dev, "failed to read pressure\n");
+ return ret;
+ }
+
+ raw_press = get_unaligned_le24(data->buf);
+ if (raw_press == BMP580_PRESS_SKIPPED) {
+ dev_err(data->dev, "reading pressure skipped\n");
+ return -EIO;
+ }
+ /*
+ * Pressure is returned in Pascals in fractional form down 2^16.
+ * We reescale /1000 to convert to kilopascal to respect IIO ABI.
+ */
+ *val = raw_press;
+ *val2 = 64000; /* 2^6 * 1000 */
+ return IIO_VAL_FRACTIONAL;
+}
+
+static const int bmp580_odr_table[][2] = {
+ [BMP580_ODR_240HZ] = {240, 0},
+ [BMP580_ODR_218HZ] = {218, 0},
+ [BMP580_ODR_199HZ] = {199, 0},
+ [BMP580_ODR_179HZ] = {179, 0},
+ [BMP580_ODR_160HZ] = {160, 0},
+ [BMP580_ODR_149HZ] = {149, 0},
+ [BMP580_ODR_140HZ] = {140, 0},
+ [BMP580_ODR_129HZ] = {129, 0},
+ [BMP580_ODR_120HZ] = {120, 0},
+ [BMP580_ODR_110HZ] = {110, 0},
+ [BMP580_ODR_100HZ] = {100, 0},
+ [BMP580_ODR_89HZ] = {89, 0},
+ [BMP580_ODR_80HZ] = {80, 0},
+ [BMP580_ODR_70HZ] = {70, 0},
+ [BMP580_ODR_60HZ] = {60, 0},
+ [BMP580_ODR_50HZ] = {50, 0},
+ [BMP580_ODR_45HZ] = {45, 0},
+ [BMP580_ODR_40HZ] = {40, 0},
+ [BMP580_ODR_35HZ] = {35, 0},
+ [BMP580_ODR_30HZ] = {30, 0},
+ [BMP580_ODR_25HZ] = {25, 0},
+ [BMP580_ODR_20HZ] = {20, 0},
+ [BMP580_ODR_15HZ] = {15, 0},
+ [BMP580_ODR_10HZ] = {10, 0},
+ [BMP580_ODR_5HZ] = {5, 0},
+ [BMP580_ODR_4HZ] = {4, 0},
+ [BMP580_ODR_3HZ] = {3, 0},
+ [BMP580_ODR_2HZ] = {2, 0},
+ [BMP580_ODR_1HZ] = {1, 0},
+ [BMP580_ODR_0_5HZ] = {0, 500000},
+ [BMP580_ODR_0_25HZ] = {0, 250000},
+ [BMP580_ODR_0_125HZ] = {0, 125000},
+};
+
+static const int bmp580_nvmem_addrs[] = { 0x20, 0x21, 0x22 };
+
+static int bmp580_nvmem_read(void *priv, unsigned int offset, void *val,
+ size_t bytes)
+{
+ struct bmp280_data *data = priv;
+ u16 *dst = val;
+ int ret, addr;
+
+ pm_runtime_get_sync(data->dev);
+ mutex_lock(&data->lock);
+
+ /* Set sensor in standby mode */
+ ret = regmap_update_bits(data->regmap, BMP580_REG_ODR_CONFIG,
+ BMP580_MODE_MASK | BMP580_ODR_DEEPSLEEP_DIS,
+ BMP580_ODR_DEEPSLEEP_DIS |
+ FIELD_PREP(BMP580_MODE_MASK, BMP580_MODE_SLEEP));
+ if (ret) {
+ dev_err(data->dev, "failed to change sensor to standby mode\n");
+ goto exit;
+ }
+ /* Wait standby transition time */
+ usleep_range(2500, 3000);
+
+ while (bytes >= sizeof(*dst)) {
+ addr = bmp580_nvmem_addrs[offset / sizeof(*dst)];
+
+ ret = regmap_write(data->regmap, BMP580_REG_NVM_ADDR,
+ FIELD_PREP(BMP580_NVM_ROW_ADDR_MASK, addr));
+ if (ret) {
+ dev_err(data->dev, "error writing nvm address\n");
+ goto exit;
+ }
+
+ ret = bmp580_nvm_operation(data, false);
+ if (ret)
+ goto exit;
+
+ ret = regmap_bulk_read(data->regmap, BMP580_REG_NVM_DATA_LSB, &data->le16,
+ sizeof(data->le16));
+ if (ret) {
+ dev_err(data->dev, "error reading nvm data regs\n");
+ goto exit;
+ }
+
+ *dst++ = le16_to_cpu(data->le16);
+ bytes -= sizeof(*dst);
+ offset += sizeof(*dst);
+ }
+exit:
+ /* Restore chip config */
+ data->chip_info->chip_config(data);
+ mutex_unlock(&data->lock);
+ pm_runtime_mark_last_busy(data->dev);
+ pm_runtime_put_autosuspend(data->dev);
+ return ret;
+}
+
+static int bmp580_nvmem_write(void *priv, unsigned int offset, void *val,
+ size_t bytes)
+{
+ struct bmp280_data *data = priv;
+ u16 *buf = val;
+ int ret, addr;
+
+ pm_runtime_get_sync(data->dev);
+ mutex_lock(&data->lock);
+
+ /* Set sensor in standby mode */
+ ret = regmap_update_bits(data->regmap, BMP580_REG_ODR_CONFIG,
+ BMP580_MODE_MASK | BMP580_ODR_DEEPSLEEP_DIS,
+ BMP580_ODR_DEEPSLEEP_DIS |
+ FIELD_PREP(BMP580_MODE_MASK, BMP580_MODE_SLEEP));
+ if (ret) {
+ dev_err(data->dev, "failed to change sensor to standby mode\n");
+ goto exit;
+ }
+ /* Wait standby transition time */
+ usleep_range(2500, 3000);
+
+ while (bytes >= sizeof(*buf)) {
+ addr = bmp580_nvmem_addrs[offset / sizeof(*buf)];
+
+ ret = regmap_write(data->regmap, BMP580_REG_NVM_ADDR, BMP580_NVM_PROG_EN |
+ FIELD_PREP(BMP580_NVM_ROW_ADDR_MASK, addr));
+ if (ret) {
+ dev_err(data->dev, "error writing nvm address\n");
+ goto exit;
+ }
+ data->le16 = cpu_to_le16(*buf++);
+
+ ret = regmap_bulk_write(data->regmap, BMP580_REG_NVM_DATA_LSB, &data->le16,
+ sizeof(data->le16));
+ if (ret) {
+ dev_err(data->dev, "error writing LSB NVM data regs\n");
+ goto exit;
+ }
+
+ ret = bmp580_nvm_operation(data, true);
+ if (ret)
+ goto exit;
+
+ /* Disable programming mode bit */
+ ret = regmap_update_bits(data->regmap, BMP580_REG_NVM_ADDR,
+ BMP580_NVM_PROG_EN, 0);
+ if (ret) {
+ dev_err(data->dev, "error resetting nvm write\n");
+ goto exit;
+ }
+
+ bytes -= sizeof(*buf);
+ offset += sizeof(*buf);
+ }
+exit:
+ /* Restore chip config */
+ data->chip_info->chip_config(data);
+ mutex_unlock(&data->lock);
+ pm_runtime_mark_last_busy(data->dev);
+ pm_runtime_put_autosuspend(data->dev);
+ return ret;
+}
+
+static int bmp580_preinit(struct bmp280_data *data)
+{
+ struct nvmem_config config = {
+ .dev = data->dev,
+ .priv = data,
+ .name = "bmp580_nvmem",
+ .word_size = sizeof(u16),
+ .stride = sizeof(u16),
+ .size = 3 * sizeof(u16),
+ .reg_read = bmp580_nvmem_read,
+ .reg_write = bmp580_nvmem_write,
+ };
+ unsigned int reg;
+ int ret;
+
+ /* Issue soft-reset command */
+ ret = bmp580_soft_reset(data);
+ if (ret)
+ return ret;
+
+ /* Post powerup sequence */
+ ret = regmap_read(data->regmap, BMP580_REG_CHIP_ID, &reg);
+ if (ret)
+ return ret;
+
+ /* Print warn message if we don't know the chip id */
+ if (reg != BMP580_CHIP_ID && reg != BMP580_CHIP_ID_ALT)
+ dev_warn(data->dev, "preinit: unexpected chip_id\n");
+
+ ret = regmap_read(data->regmap, BMP580_REG_STATUS, &reg);
+ if (ret)
+ return ret;
+
+ /* Check nvm status */
+ if (!(reg & BMP580_STATUS_NVM_RDY_MASK) || (reg & BMP580_STATUS_NVM_ERR_MASK)) {
+ dev_err(data->dev, "preinit: nvm error on powerup sequence\n");
+ return -EIO;
+ }
+
+ /* Register nvmem device */
+ return PTR_ERR_OR_ZERO(devm_nvmem_register(config.dev, &config));
+}
+
+static int bmp580_chip_config(struct bmp280_data *data)
+{
+ bool change = false, aux;
+ unsigned int tmp;
+ u8 reg_val;
+ int ret;
+
+ /* Sets sensor in standby mode */
+ ret = regmap_update_bits(data->regmap, BMP580_REG_ODR_CONFIG,
+ BMP580_MODE_MASK | BMP580_ODR_DEEPSLEEP_DIS,
+ BMP580_ODR_DEEPSLEEP_DIS |
+ FIELD_PREP(BMP580_MODE_MASK, BMP580_MODE_SLEEP));
+ if (ret) {
+ dev_err(data->dev, "failed to change sensor to standby mode\n");
+ return ret;
+ }
+ /* From datasheet's table 4: electrical characteristics */
+ usleep_range(2500, 3000);
+
+ /* Set default DSP mode settings */
+ reg_val = FIELD_PREP(BMP580_DSP_COMP_MASK, BMP580_DSP_PRESS_TEMP_COMP_EN) |
+ BMP580_DSP_SHDW_IIR_TEMP_EN | BMP580_DSP_SHDW_IIR_PRESS_EN;
+
+ ret = regmap_update_bits(data->regmap, BMP580_REG_DSP_CONFIG,
+ BMP580_DSP_COMP_MASK |
+ BMP580_DSP_SHDW_IIR_TEMP_EN |
+ BMP580_DSP_SHDW_IIR_PRESS_EN, reg_val);
+
+ /* Configure oversampling */
+ reg_val = FIELD_PREP(BMP580_OSR_TEMP_MASK, data->oversampling_temp) |
+ FIELD_PREP(BMP580_OSR_PRESS_MASK, data->oversampling_press) |
+ BMP580_OSR_PRESS_EN;
+
+ ret = regmap_update_bits_check(data->regmap, BMP580_REG_OSR_CONFIG,
+ BMP580_OSR_TEMP_MASK | BMP580_OSR_PRESS_MASK |
+ BMP580_OSR_PRESS_EN,
+ reg_val, &aux);
+ if (ret) {
+ dev_err(data->dev, "failed to write oversampling register\n");
+ return ret;
+ }
+ change = change || aux;
+
+ /* Configure output data rate */
+ ret = regmap_update_bits_check(data->regmap, BMP580_REG_ODR_CONFIG, BMP580_ODR_MASK,
+ FIELD_PREP(BMP580_ODR_MASK, data->sampling_freq),
+ &aux);
+ if (ret) {
+ dev_err(data->dev, "failed to write ODR configuration register\n");
+ return ret;
+ }
+ change = change || aux;
+
+ /* Set filter 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);
+ 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) {
+ /*
+ * Check if ODR and OSR settings are valid or we are
+ * operating in a degraded mode.
+ */
+ ret = regmap_read(data->regmap, BMP580_REG_EFF_OSR, &tmp);
+ if (ret) {
+ dev_err(data->dev, "error reading effective OSR register\n");
+ return ret;
+ }
+ if (!(tmp & BMP580_EFF_OSR_VALID_ODR)) {
+ dev_warn(data->dev, "OSR and ODR incompatible settings detected\n");
+ /* Set current OSR settings from data on effective OSR */
+ data->oversampling_temp = FIELD_GET(BMP580_EFF_OSR_TEMP_MASK, tmp);
+ data->oversampling_press = FIELD_GET(BMP580_EFF_OSR_PRESS_MASK, tmp);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static const int bmp580_oversampling_avail[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+
+const struct bmp280_chip_info bmp580_chip_info = {
+ .id_reg = BMP580_REG_CHIP_ID,
+ .chip_id = BMP580_CHIP_ID,
+ .regmap_config = &bmp580_regmap_config,
+ .start_up_time = 2000,
+ .channels = bmp380_channels,
+ .num_channels = 2,
+
+ .oversampling_temp_avail = bmp580_oversampling_avail,
+ .num_oversampling_temp_avail = ARRAY_SIZE(bmp580_oversampling_avail),
+ .oversampling_temp_default = ilog2(1),
+
+ .oversampling_press_avail = bmp580_oversampling_avail,
+ .num_oversampling_press_avail = ARRAY_SIZE(bmp580_oversampling_avail),
+ .oversampling_press_default = ilog2(4),
+
+ .sampling_freq_avail = bmp580_odr_table,
+ .num_sampling_freq_avail = ARRAY_SIZE(bmp580_odr_table) * 2,
+ .sampling_freq_default = BMP580_ODR_50HZ,
+
+ .iir_filter_coeffs_avail = bmp380_iir_filter_coeffs_avail,
+ .num_iir_filter_coeffs_avail = ARRAY_SIZE(bmp380_iir_filter_coeffs_avail),
+ .iir_filter_coeff_default = 2,
+
+ .chip_config = bmp580_chip_config,
+ .read_temp = bmp580_read_temp,
+ .read_press = bmp580_read_press,
+ .preinit = bmp580_preinit,
};
+EXPORT_SYMBOL_NS(bmp580_chip_info, IIO_BMP280);
static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
{
@@ -1467,7 +1872,7 @@ static s32 bmp180_compensate_temp(struct bmp280_data *data, s32 adc_temp)
return (data->t_fine + 8) >> 4;
}
-static int bmp180_read_temp(struct bmp280_data *data, int *val)
+static int bmp180_read_temp(struct bmp280_data *data, int *val, int *val2)
{
s32 adc_temp, comp_temp;
int ret;
@@ -1555,7 +1960,7 @@ static int bmp180_read_press(struct bmp280_data *data,
int ret;
/* Read and compensate temperature so we get a reading of t_fine. */
- ret = bmp180_read_temp(data, NULL);
+ ret = bmp180_read_temp(data, NULL, NULL);
if (ret)
return ret;
@@ -1579,8 +1984,10 @@ static int bmp180_chip_config(struct bmp280_data *data)
static const int bmp180_oversampling_temp_avail[] = { 1 };
static const int bmp180_oversampling_press_avail[] = { 1, 2, 4, 8 };
-static const struct bmp280_chip_info bmp180_chip_info = {
+const struct bmp280_chip_info bmp180_chip_info = {
.id_reg = BMP280_REG_ID,
+ .chip_id = BMP180_CHIP_ID,
+ .regmap_config = &bmp180_regmap_config,
.start_up_time = 2000,
.channels = bmp280_channels,
.num_channels = 2,
@@ -1600,6 +2007,7 @@ static const struct bmp280_chip_info bmp180_chip_info = {
.read_press = bmp180_read_press,
.read_calib = bmp180_read_calib,
};
+EXPORT_SYMBOL_NS(bmp180_chip_info, IIO_BMP280);
static irqreturn_t bmp085_eoc_irq(int irq, void *d)
{
@@ -1661,11 +2069,10 @@ static void bmp280_regulators_disable(void *data)
int bmp280_common_probe(struct device *dev,
struct regmap *regmap,
- unsigned int chip,
+ const struct bmp280_chip_info *chip_info,
const char *name,
int irq)
{
- const struct bmp280_chip_info *chip_info;
struct iio_dev *indio_dev;
struct bmp280_data *data;
struct gpio_desc *gpiod;
@@ -1684,22 +2091,6 @@ int bmp280_common_probe(struct device *dev,
indio_dev->info = &bmp280_info;
indio_dev->modes = INDIO_DIRECT_MODE;
- switch (chip) {
- case BMP180_CHIP_ID:
- chip_info = &bmp180_chip_info;
- break;
- case BMP280_CHIP_ID:
- chip_info = &bmp280_chip_info;
- break;
- case BME280_CHIP_ID:
- chip_info = &bme280_chip_info;
- break;
- case BMP380_CHIP_ID:
- chip_info = &bmp380_chip_info;
- break;
- default:
- return -EINVAL;
- }
data->chip_info = chip_info;
/* Apply initial values from chip info structure */
@@ -1751,17 +2142,17 @@ int bmp280_common_probe(struct device *dev,
ret = regmap_read(regmap, data->chip_info->id_reg, &chip_id);
if (ret < 0)
return ret;
- if (chip_id != chip) {
+ if (chip_id != data->chip_info->chip_id) {
dev_err(dev, "bad chip id: expected %x got %x\n",
- chip, chip_id);
+ data->chip_info->chip_id, chip_id);
return -EINVAL;
}
- /* BMP3xx requires soft-reset as part of initialization */
- if (chip_id == BMP380_CHIP_ID) {
- ret = bmp380_cmd(data, BMP380_CMD_SOFT_RESET);
- if (ret < 0)
- return ret;
+ if (data->chip_info->preinit) {
+ ret = data->chip_info->preinit(data);
+ if (ret)
+ return dev_err_probe(data->dev, ret,
+ "error running preinit tasks\n");
}
ret = data->chip_info->chip_config(data);
@@ -1776,10 +2167,12 @@ int bmp280_common_probe(struct device *dev,
* time once. They will not change.
*/
- ret = data->chip_info->read_calib(data);
- if (ret < 0)
- return dev_err_probe(data->dev, ret,
- "failed to read calibration coefficients\n");
+ if (data->chip_info->read_calib) {
+ ret = data->chip_info->read_calib(data);
+ if (ret < 0)
+ return dev_err_probe(data->dev, ret,
+ "failed to read calibration coefficients\n");
+ }
/*
* Attempt to grab an optional EOC IRQ - only the BMP085 has this
diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c
index 14eab086d24a..567b945e6427 100644
--- a/drivers/iio/pressure/bmp280-i2c.c
+++ b/drivers/iio/pressure/bmp280-i2c.c
@@ -8,25 +8,14 @@
static int bmp280_i2c_probe(struct i2c_client *client)
{
struct regmap *regmap;
- const struct regmap_config *regmap_config;
+ const struct bmp280_chip_info *chip_info;
const struct i2c_device_id *id = i2c_client_get_device_id(client);
- switch (id->driver_data) {
- case BMP180_CHIP_ID:
- regmap_config = &bmp180_regmap_config;
- break;
- case BMP280_CHIP_ID:
- case BME280_CHIP_ID:
- regmap_config = &bmp280_regmap_config;
- break;
- case BMP380_CHIP_ID:
- regmap_config = &bmp380_regmap_config;
- break;
- default:
- return -EINVAL;
- }
+ chip_info = device_get_match_data(&client->dev);
+ if (!chip_info)
+ chip_info = (const struct bmp280_chip_info *) id->driver_data;
- regmap = devm_regmap_init_i2c(client, regmap_config);
+ regmap = devm_regmap_init_i2c(client, chip_info->regmap_config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "failed to allocate register map\n");
return PTR_ERR(regmap);
@@ -34,27 +23,29 @@ static int bmp280_i2c_probe(struct i2c_client *client)
return bmp280_common_probe(&client->dev,
regmap,
- id->driver_data,
+ chip_info,
id->name,
client->irq);
}
static const struct of_device_id bmp280_of_i2c_match[] = {
- { .compatible = "bosch,bmp085", .data = (void *)BMP180_CHIP_ID },
- { .compatible = "bosch,bmp180", .data = (void *)BMP180_CHIP_ID },
- { .compatible = "bosch,bmp280", .data = (void *)BMP280_CHIP_ID },
- { .compatible = "bosch,bme280", .data = (void *)BME280_CHIP_ID },
- { .compatible = "bosch,bmp380", .data = (void *)BMP380_CHIP_ID },
+ { .compatible = "bosch,bmp085", .data = &bmp180_chip_info },
+ { .compatible = "bosch,bmp180", .data = &bmp180_chip_info },
+ { .compatible = "bosch,bmp280", .data = &bmp280_chip_info },
+ { .compatible = "bosch,bme280", .data = &bme280_chip_info },
+ { .compatible = "bosch,bmp380", .data = &bmp380_chip_info },
+ { .compatible = "bosch,bmp580", .data = &bmp580_chip_info },
{ },
};
MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match);
static const struct i2c_device_id bmp280_i2c_id[] = {
- {"bmp085", BMP180_CHIP_ID },
- {"bmp180", BMP180_CHIP_ID },
- {"bmp280", BMP280_CHIP_ID },
- {"bme280", BME280_CHIP_ID },
- {"bmp380", BMP380_CHIP_ID },
+ {"bmp085", (kernel_ulong_t)&bmp180_chip_info },
+ {"bmp180", (kernel_ulong_t)&bmp180_chip_info },
+ {"bmp280", (kernel_ulong_t)&bmp280_chip_info },
+ {"bme280", (kernel_ulong_t)&bme280_chip_info },
+ {"bmp380", (kernel_ulong_t)&bmp380_chip_info },
+ {"bmp580", (kernel_ulong_t)&bmp580_chip_info },
{ },
};
MODULE_DEVICE_TABLE(i2c, bmp280_i2c_id);
diff --git a/drivers/iio/pressure/bmp280-regmap.c b/drivers/iio/pressure/bmp280-regmap.c
index c98c67970265..3ee56720428c 100644
--- a/drivers/iio/pressure/bmp280-regmap.c
+++ b/drivers/iio/pressure/bmp280-regmap.c
@@ -115,6 +115,54 @@ static bool bmp380_is_volatile_reg(struct device *dev, unsigned int reg)
}
}
+static bool bmp580_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case BMP580_REG_NVM_DATA_MSB:
+ case BMP580_REG_NVM_DATA_LSB:
+ case BMP580_REG_NVM_ADDR:
+ case BMP580_REG_ODR_CONFIG:
+ case BMP580_REG_OSR_CONFIG:
+ case BMP580_REG_INT_SOURCE:
+ case BMP580_REG_INT_CONFIG:
+ case BMP580_REG_OOR_THR_MSB:
+ case BMP580_REG_OOR_THR_LSB:
+ case BMP580_REG_OOR_CONFIG:
+ case BMP580_REG_OOR_RANGE:
+ case BMP580_REG_IF_CONFIG:
+ case BMP580_REG_FIFO_CONFIG:
+ case BMP580_REG_FIFO_SEL:
+ case BMP580_REG_DSP_CONFIG:
+ case BMP580_REG_DSP_IIR:
+ case BMP580_REG_CMD:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool bmp580_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case BMP580_REG_NVM_DATA_MSB:
+ case BMP580_REG_NVM_DATA_LSB:
+ case BMP580_REG_FIFO_COUNT:
+ case BMP580_REG_INT_STATUS:
+ case BMP580_REG_PRESS_XLSB:
+ case BMP580_REG_PRESS_LSB:
+ case BMP580_REG_PRESS_MSB:
+ case BMP580_REG_FIFO_DATA:
+ case BMP580_REG_TEMP_XLSB:
+ case BMP580_REG_TEMP_LSB:
+ case BMP580_REG_TEMP_MSB:
+ case BMP580_REG_EFF_OSR:
+ case BMP580_REG_STATUS:
+ return true;
+ default:
+ return false;
+ }
+}
+
const struct regmap_config bmp280_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -138,3 +186,15 @@ const struct regmap_config bmp380_regmap_config = {
.volatile_reg = bmp380_is_volatile_reg,
};
EXPORT_SYMBOL_NS(bmp380_regmap_config, IIO_BMP280);
+
+const struct regmap_config bmp580_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = BMP580_REG_CMD,
+ .cache_type = REGCACHE_RBTREE,
+
+ .writeable_reg = bmp580_is_writeable_reg,
+ .volatile_reg = bmp580_is_volatile_reg,
+};
+EXPORT_SYMBOL_NS(bmp580_regmap_config, IIO_BMP280);
diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c
index 011c68e07ebf..1dff9bb7c4e9 100644
--- a/drivers/iio/pressure/bmp280-spi.c
+++ b/drivers/iio/pressure/bmp280-spi.c
@@ -47,8 +47,8 @@ static struct regmap_bus bmp280_regmap_bus = {
static int bmp280_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
+ const struct bmp280_chip_info *chip_info;
struct regmap *regmap;
- const struct regmap_config *regmap_config;
int ret;
spi->bits_per_word = 8;
@@ -58,25 +58,14 @@ static int bmp280_spi_probe(struct spi_device *spi)
return ret;
}
- switch (id->driver_data) {
- case BMP180_CHIP_ID:
- regmap_config = &bmp180_regmap_config;
- break;
- case BMP280_CHIP_ID:
- case BME280_CHIP_ID:
- regmap_config = &bmp280_regmap_config;
- break;
- case BMP380_CHIP_ID:
- regmap_config = &bmp380_regmap_config;
- break;
- default:
- return -EINVAL;
- }
+ chip_info = device_get_match_data(&spi->dev);
+ if (!chip_info)
+ chip_info = (const struct bmp280_chip_info *) id->driver_data;
regmap = devm_regmap_init(&spi->dev,
&bmp280_regmap_bus,
&spi->dev,
- regmap_config);
+ chip_info->regmap_config);
if (IS_ERR(regmap)) {
dev_err(&spi->dev, "failed to allocate register map\n");
return PTR_ERR(regmap);
@@ -84,28 +73,30 @@ static int bmp280_spi_probe(struct spi_device *spi)
return bmp280_common_probe(&spi->dev,
regmap,
- id->driver_data,
+ chip_info,
id->name,
spi->irq);
}
static const struct of_device_id bmp280_of_spi_match[] = {
- { .compatible = "bosch,bmp085", },
- { .compatible = "bosch,bmp180", },
- { .compatible = "bosch,bmp181", },
- { .compatible = "bosch,bmp280", },
- { .compatible = "bosch,bme280", },
- { .compatible = "bosch,bmp380", },
+ { .compatible = "bosch,bmp085", .data = &bmp180_chip_info },
+ { .compatible = "bosch,bmp180", .data = &bmp180_chip_info },
+ { .compatible = "bosch,bmp181", .data = &bmp180_chip_info },
+ { .compatible = "bosch,bmp280", .data = &bmp280_chip_info },
+ { .compatible = "bosch,bme280", .data = &bmp280_chip_info },
+ { .compatible = "bosch,bmp380", .data = &bmp380_chip_info },
+ { .compatible = "bosch,bmp580", .data = &bmp580_chip_info },
{ },
};
MODULE_DEVICE_TABLE(of, bmp280_of_spi_match);
static const struct spi_device_id bmp280_spi_id[] = {
- { "bmp180", BMP180_CHIP_ID },
- { "bmp181", BMP180_CHIP_ID },
- { "bmp280", BMP280_CHIP_ID },
- { "bme280", BME280_CHIP_ID },
- { "bmp380", BMP380_CHIP_ID },
+ { "bmp180", (kernel_ulong_t)&bmp180_chip_info },
+ { "bmp181", (kernel_ulong_t)&bmp180_chip_info },
+ { "bmp280", (kernel_ulong_t)&bmp280_chip_info },
+ { "bme280", (kernel_ulong_t)&bmp280_chip_info },
+ { "bmp380", (kernel_ulong_t)&bmp380_chip_info },
+ { "bmp580", (kernel_ulong_t)&bmp580_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, bmp280_spi_id);
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index c791325c7416..5c0563ce7572 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -1,7 +1,114 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/bitops.h>
#include <linux/device.h>
+#include <linux/iio/iio.h>
#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+
+/* BMP580 specific registers */
+#define BMP580_REG_CMD 0x7E
+#define BMP580_REG_EFF_OSR 0x38
+#define BMP580_REG_ODR_CONFIG 0x37
+#define BMP580_REG_OSR_CONFIG 0x36
+#define BMP580_REG_IF_CONFIG 0x13
+#define BMP580_REG_REV_ID 0x02
+#define BMP580_REG_CHIP_ID 0x01
+/* OOR allows to configure a pressure alarm */
+#define BMP580_REG_OOR_CONFIG 0x35
+#define BMP580_REG_OOR_RANGE 0x34
+#define BMP580_REG_OOR_THR_MSB 0x33
+#define BMP580_REG_OOR_THR_LSB 0x32
+/* DSP registers (IIR filters) */
+#define BMP580_REG_DSP_IIR 0x31
+#define BMP580_REG_DSP_CONFIG 0x30
+/* NVM access registers */
+#define BMP580_REG_NVM_DATA_MSB 0x2D
+#define BMP580_REG_NVM_DATA_LSB 0x2C
+#define BMP580_REG_NVM_ADDR 0x2B
+/* Status registers */
+#define BMP580_REG_STATUS 0x28
+#define BMP580_REG_INT_STATUS 0x27
+#define BMP580_REG_CHIP_STATUS 0x11
+/* Data registers */
+#define BMP580_REG_FIFO_DATA 0x29
+#define BMP580_REG_PRESS_MSB 0x22
+#define BMP580_REG_PRESS_LSB 0x21
+#define BMP580_REG_PRESS_XLSB 0x20
+#define BMP580_REG_TEMP_MSB 0x1F
+#define BMP580_REG_TEMP_LSB 0x1E
+#define BMP580_REG_TEMP_XLSB 0x1D
+/* FIFO config registers */
+#define BMP580_REG_FIFO_SEL 0x18
+#define BMP580_REG_FIFO_COUNT 0x17
+#define BMP580_REG_FIFO_CONFIG 0x16
+/* Interruptions config registers */
+#define BMP580_REG_INT_SOURCE 0x15
+#define BMP580_REG_INT_CONFIG 0x14
+
+#define BMP580_CMD_NOOP 0x00
+#define BMP580_CMD_EXTMODE_SEQ_0 0x73
+#define BMP580_CMD_EXTMODE_SEQ_1 0xB4
+#define BMP580_CMD_EXTMODE_SEQ_2 0x69
+#define BMP580_CMD_NVM_OP_SEQ_0 0x5D
+#define BMP580_CMD_NVM_READ_SEQ_1 0xA5
+#define BMP580_CMD_NVM_WRITE_SEQ_1 0xA0
+#define BMP580_CMD_SOFT_RESET 0xB6
+
+#define BMP580_INT_STATUS_POR_MASK BIT(4)
+
+#define BMP580_STATUS_CORE_RDY_MASK BIT(0)
+#define BMP580_STATUS_NVM_RDY_MASK BIT(1)
+#define BMP580_STATUS_NVM_ERR_MASK BIT(2)
+#define BMP580_STATUS_NVM_CMD_ERR_MASK BIT(3)
+
+#define BMP580_OSR_PRESS_MASK GENMASK(5, 3)
+#define BMP580_OSR_TEMP_MASK GENMASK(2, 0)
+#define BMP580_OSR_PRESS_EN BIT(6)
+#define BMP580_EFF_OSR_PRESS_MASK GENMASK(5, 3)
+#define BMP580_EFF_OSR_TEMP_MASK GENMASK(2, 0)
+#define BMP580_EFF_OSR_VALID_ODR BIT(7)
+
+#define BMP580_ODR_MASK GENMASK(6, 2)
+#define BMP580_MODE_MASK GENMASK(1, 0)
+#define BMP580_MODE_SLEEP 0
+#define BMP580_MODE_NORMAL 1
+#define BMP580_MODE_FORCED 2
+#define BMP580_MODE_CONTINOUS 3
+#define BMP580_ODR_DEEPSLEEP_DIS BIT(7)
+
+#define BMP580_DSP_COMP_MASK GENMASK(1, 0)
+#define BMP580_DSP_COMP_DIS 0
+#define BMP580_DSP_TEMP_COMP_EN 1
+/*
+ * In section 7.27 of datasheet, modes 2 and 3 are technically the same.
+ * Pressure compensation means also enabling temperature compensation
+ */
+#define BMP580_DSP_PRESS_COMP_EN 2
+#define BMP580_DSP_PRESS_TEMP_COMP_EN 3
+#define BMP580_DSP_IIR_FORCED_FLUSH BIT(2)
+#define BMP580_DSP_SHDW_IIR_TEMP_EN BIT(3)
+#define BMP580_DSP_FIFO_IIR_TEMP_EN BIT(4)
+#define BMP580_DSP_SHDW_IIR_PRESS_EN BIT(5)
+#define BMP580_DSP_FIFO_IIR_PRESS_EN BIT(6)
+#define BMP580_DSP_OOR_IIR_PRESS_EN BIT(7)
+
+#define BMP580_DSP_IIR_PRESS_MASK GENMASK(5, 3)
+#define BMP580_DSP_IIR_TEMP_MASK GENMASK(2, 0)
+#define BMP580_FILTER_OFF 0
+#define BMP580_FILTER_1X 1
+#define BMP580_FILTER_3X 2
+#define BMP580_FILTER_7X 3
+#define BMP580_FILTER_15X 4
+#define BMP580_FILTER_31X 5
+#define BMP580_FILTER_63X 6
+#define BMP580_FILTER_127X 7
+
+#define BMP580_NVM_ROW_ADDR_MASK GENMASK(5, 0)
+#define BMP580_NVM_PROG_EN BIT(6)
+
+#define BMP580_TEMP_SKIPPED 0x7f7f7f
+#define BMP580_PRESS_SKIPPED 0x7f7f7f
/* BMP380 specific registers */
#define BMP380_REG_CMD 0x7E
@@ -181,6 +288,8 @@
#define BMP280_REG_ID 0xD0
#define BMP380_CHIP_ID 0x50
+#define BMP580_CHIP_ID 0x50
+#define BMP580_CHIP_ID_ALT 0x51
#define BMP180_CHIP_ID 0x55
#define BMP280_CHIP_ID 0x58
#define BME280_CHIP_ID 0x60
@@ -191,15 +300,177 @@
#define BMP280_PRESS_SKIPPED 0x80000
#define BMP280_HUMIDITY_SKIPPED 0x8000
+/* Core exported structs */
+
+static const char *const bmp280_supply_names[] = {
+ "vddd", "vdda"
+};
+
+#define BMP280_NUM_SUPPLIES ARRAY_SIZE(bmp280_supply_names)
+
+struct bmp180_calib {
+ s16 AC1;
+ s16 AC2;
+ s16 AC3;
+ u16 AC4;
+ u16 AC5;
+ u16 AC6;
+ s16 B1;
+ s16 B2;
+ s16 MB;
+ s16 MC;
+ s16 MD;
+};
+
+/* See datasheet Section 4.2.2. */
+struct bmp280_calib {
+ u16 T1;
+ s16 T2;
+ s16 T3;
+ u16 P1;
+ s16 P2;
+ s16 P3;
+ s16 P4;
+ s16 P5;
+ s16 P6;
+ s16 P7;
+ s16 P8;
+ s16 P9;
+ u8 H1;
+ s16 H2;
+ u8 H3;
+ s16 H4;
+ s16 H5;
+ s8 H6;
+};
+
+/* See datasheet Section 3.11.1. */
+struct bmp380_calib {
+ u16 T1;
+ u16 T2;
+ s8 T3;
+ s16 P1;
+ s16 P2;
+ s8 P3;
+ s8 P4;
+ u16 P5;
+ u16 P6;
+ s8 P7;
+ s8 P8;
+ s16 P9;
+ s8 P10;
+ s8 P11;
+};
+
+struct bmp280_data {
+ struct device *dev;
+ struct mutex lock;
+ struct regmap *regmap;
+ struct completion done;
+ bool use_eoc;
+ const struct bmp280_chip_info *chip_info;
+ union {
+ struct bmp180_calib bmp180;
+ struct bmp280_calib bmp280;
+ struct bmp380_calib bmp380;
+ } calib;
+ struct regulator_bulk_data supplies[BMP280_NUM_SUPPLIES];
+ unsigned int start_up_time; /* in microseconds */
+
+ /* log of base 2 of oversampling rate */
+ u8 oversampling_press;
+ u8 oversampling_temp;
+ u8 oversampling_humid;
+ u8 iir_filter_coeff;
+
+ /*
+ * BMP380 devices introduce sampling frequency configuration. See
+ * datasheet sections 3.3.3. and 4.3.19 for more details.
+ *
+ * BMx280 devices allowed indirect configuration of sampling frequency
+ * changing the t_standby duration between measurements, as detailed on
+ * section 3.6.3 of the datasheet.
+ */
+ int sampling_freq;
+
+ /*
+ * Carryover value from temperature conversion, used in pressure
+ * calculation.
+ */
+ s32 t_fine;
+
+ /*
+ * DMA (thus cache coherency maintenance) may require the
+ * transfer buffers to live in their own cache lines.
+ */
+ union {
+ /* Sensor data buffer */
+ u8 buf[3];
+ /* Calibration data buffers */
+ __le16 bmp280_cal_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
+ __be16 bmp180_cal_buf[BMP180_REG_CALIB_COUNT / 2];
+ u8 bmp380_cal_buf[BMP380_CALIB_REG_COUNT];
+ /* Miscellaneous, endianess-aware data buffers */
+ __le16 le16;
+ __be16 be16;
+ } __aligned(IIO_DMA_MINALIGN);
+};
+
+struct bmp280_chip_info {
+ unsigned int id_reg;
+ const unsigned int chip_id;
+
+ const struct regmap_config *regmap_config;
+
+ const struct iio_chan_spec *channels;
+ int num_channels;
+ unsigned int start_up_time;
+
+ const int *oversampling_temp_avail;
+ int num_oversampling_temp_avail;
+ int oversampling_temp_default;
+
+ const int *oversampling_press_avail;
+ int num_oversampling_press_avail;
+ int oversampling_press_default;
+
+ const int *oversampling_humid_avail;
+ int num_oversampling_humid_avail;
+ int oversampling_humid_default;
+
+ const int *iir_filter_coeffs_avail;
+ int num_iir_filter_coeffs_avail;
+ int iir_filter_coeff_default;
+
+ const int (*sampling_freq_avail)[2];
+ int num_sampling_freq_avail;
+ int sampling_freq_default;
+
+ int (*chip_config)(struct bmp280_data *);
+ int (*read_temp)(struct bmp280_data *, int *, int *);
+ int (*read_press)(struct bmp280_data *, int *, int *);
+ int (*read_humid)(struct bmp280_data *, int *, int *);
+ int (*read_calib)(struct bmp280_data *);
+ int (*preinit)(struct bmp280_data *);
+};
+
+/* Chip infos for each variant */
+extern const struct bmp280_chip_info bmp180_chip_info;
+extern const struct bmp280_chip_info bmp280_chip_info;
+extern const struct bmp280_chip_info bme280_chip_info;
+extern const struct bmp280_chip_info bmp380_chip_info;
+extern const struct bmp280_chip_info bmp580_chip_info;
+
/* Regmap configurations */
extern const struct regmap_config bmp180_regmap_config;
extern const struct regmap_config bmp280_regmap_config;
extern const struct regmap_config bmp380_regmap_config;
+extern const struct regmap_config bmp580_regmap_config;
/* Probe called from different transports */
int bmp280_common_probe(struct device *dev,
struct regmap *regmap,
- unsigned int chip,
+ const struct bmp280_chip_info *,
const char *name,
int irq);
diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c
index 67119a9b95fc..421e059d1f19 100644
--- a/drivers/iio/pressure/zpa2326.c
+++ b/drivers/iio/pressure/zpa2326.c
@@ -829,7 +829,7 @@ static irqreturn_t zpa2326_handle_threaded_irq(int irq, void *data)
}
/* New sample available: dispatch internal trigger consumers. */
- iio_trigger_poll_chained(priv->trigger);
+ iio_trigger_poll_nested(priv->trigger);
if (cont)
/*