diff options
Diffstat (limited to 'drivers/iio/pressure')
-rw-r--r-- | drivers/iio/pressure/Kconfig | 31 | ||||
-rw-r--r-- | drivers/iio/pressure/Makefile | 3 | ||||
-rw-r--r-- | drivers/iio/pressure/bmp280-core.c (renamed from drivers/iio/pressure/bmp280.c) | 673 | ||||
-rw-r--r-- | drivers/iio/pressure/bmp280-i2c.c | 91 | ||||
-rw-r--r-- | drivers/iio/pressure/bmp280-regmap.c | 84 | ||||
-rw-r--r-- | drivers/iio/pressure/bmp280-spi.c | 125 | ||||
-rw-r--r-- | drivers/iio/pressure/bmp280.h | 112 | ||||
-rw-r--r-- | drivers/iio/pressure/hp206c.c | 1 | ||||
-rw-r--r-- | drivers/iio/pressure/mpl3115.c | 2 | ||||
-rw-r--r-- | drivers/iio/pressure/ms5611_core.c | 3 | ||||
-rw-r--r-- | drivers/iio/pressure/ms5637.c | 13 | ||||
-rw-r--r-- | drivers/iio/pressure/st_pressure.h | 1 | ||||
-rw-r--r-- | drivers/iio/pressure/st_pressure_core.c | 252 | ||||
-rw-r--r-- | drivers/iio/pressure/st_pressure_i2c.c | 4 | ||||
-rw-r--r-- | drivers/iio/pressure/st_pressure_spi.c | 1 |
15 files changed, 1115 insertions, 281 deletions
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index cda9f128f3a4..d130cdc78f43 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -6,16 +6,33 @@ menu "Pressure sensors" config BMP280 - tristate "Bosch Sensortec BMP180 and BMP280 pressure sensor driver" - depends on I2C + tristate "Bosch Sensortec BMP180/BMP280 pressure sensor I2C driver" + depends on (I2C || SPI_MASTER) depends on !(BMP085_I2C=y || BMP085_I2C=m) - select REGMAP_I2C + depends on !(BMP085_SPI=y || BMP085_SPI=m) + select REGMAP + select BMP280_I2C if (I2C) + select BMP280_SPI if (SPI_MASTER) help Say yes here to build support for Bosch Sensortec BMP180 and BMP280 - pressure and temperature sensors. + pressure and temperature sensors. Also supports the BE280 with + an additional humidity sensor channel. - To compile this driver as a module, choose M here: the module - will be called bmp280. + To compile this driver as a module, choose M here: the core module + will be called bmp280 and you will also get bmp280-i2c for I2C + and/or bmp280-spi for SPI support. + +config BMP280_I2C + tristate + depends on BMP280 + depends on I2C + select REGMAP_I2C + +config BMP280_SPI + tristate + depends on BMP280 + depends on SPI_MASTER + select REGMAP config HID_SENSOR_PRESS depends on HID_SENSOR_HUB @@ -130,7 +147,7 @@ config IIO_ST_PRESS select IIO_TRIGGERED_BUFFER if (IIO_BUFFER) help Say yes here to build support for STMicroelectronics pressure - sensors: LPS001WP, LPS25H, LPS331AP. + sensors: LPS001WP, LPS25H, LPS331AP, LPS22HB. This driver can also be built as a module. If so, these modules will be created: diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index 17d6e7afa1ff..7f395bed5e88 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -4,6 +4,9 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_BMP280) += bmp280.o +bmp280-objs := bmp280-core.o bmp280-regmap.o +obj-$(CONFIG_BMP280_I2C) += bmp280-i2c.o +obj-$(CONFIG_BMP280_SPI) += bmp280-spi.o obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o obj-$(CONFIG_HP03) += hp03.o obj-$(CONFIG_MPL115) += mpl115.o diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280-core.c index 724452d61846..6943688e66df 100644 --- a/drivers/iio/pressure/bmp280.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -1,5 +1,9 @@ /* + * Copyright (c) 2010 Christoph Mair <christoph.mair@gmail.com> + * Copyright (c) 2012 Bosch Sensortec GmbH + * Copyright (c) 2012 Unixphere AB * Copyright (c) 2014 Intel Corporation + * Copyright (c) 2016 Linus Walleij <linus.walleij@linaro.org> * * Driver for Bosch Sensortec BMP180 and BMP280 digital pressure sensor. * @@ -10,99 +14,63 @@ * Datasheet: * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP180-DS000-121.pdf * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP280-DS001-12.pdf + * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME280_DS001-11.pdf */ #define pr_fmt(fmt) "bmp280: " fmt +#include <linux/device.h> #include <linux/module.h> -#include <linux/i2c.h> -#include <linux/acpi.h> #include <linux/regmap.h> #include <linux/delay.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> +#include <linux/gpio/consumer.h> +#include <linux/regulator/consumer.h> +#include <linux/interrupt.h> +#include <linux/irq.h> /* For irq_get_irq_data() */ +#include <linux/completion.h> +#include <linux/pm_runtime.h> +#include <linux/random.h> -/* BMP280 specific registers */ -#define BMP280_REG_TEMP_XLSB 0xFC -#define BMP280_REG_TEMP_LSB 0xFB -#define BMP280_REG_TEMP_MSB 0xFA -#define BMP280_REG_PRESS_XLSB 0xF9 -#define BMP280_REG_PRESS_LSB 0xF8 -#define BMP280_REG_PRESS_MSB 0xF7 - -#define BMP280_REG_CONFIG 0xF5 -#define BMP280_REG_STATUS 0xF3 - -#define BMP280_REG_COMP_TEMP_START 0x88 -#define BMP280_COMP_TEMP_REG_COUNT 6 - -#define BMP280_REG_COMP_PRESS_START 0x8E -#define BMP280_COMP_PRESS_REG_COUNT 18 - -#define BMP280_FILTER_MASK (BIT(4) | BIT(3) | BIT(2)) -#define BMP280_FILTER_OFF 0 -#define BMP280_FILTER_2X BIT(2) -#define BMP280_FILTER_4X BIT(3) -#define BMP280_FILTER_8X (BIT(3) | BIT(2)) -#define BMP280_FILTER_16X BIT(4) - -#define BMP280_OSRS_TEMP_MASK (BIT(7) | BIT(6) | BIT(5)) -#define BMP280_OSRS_TEMP_SKIP 0 -#define BMP280_OSRS_TEMP_X(osrs_t) ((osrs_t) << 5) -#define BMP280_OSRS_TEMP_1X BMP280_OSRS_TEMP_X(1) -#define BMP280_OSRS_TEMP_2X BMP280_OSRS_TEMP_X(2) -#define BMP280_OSRS_TEMP_4X BMP280_OSRS_TEMP_X(3) -#define BMP280_OSRS_TEMP_8X BMP280_OSRS_TEMP_X(4) -#define BMP280_OSRS_TEMP_16X BMP280_OSRS_TEMP_X(5) - -#define BMP280_OSRS_PRESS_MASK (BIT(4) | BIT(3) | BIT(2)) -#define BMP280_OSRS_PRESS_SKIP 0 -#define BMP280_OSRS_PRESS_X(osrs_p) ((osrs_p) << 2) -#define BMP280_OSRS_PRESS_1X BMP280_OSRS_PRESS_X(1) -#define BMP280_OSRS_PRESS_2X BMP280_OSRS_PRESS_X(2) -#define BMP280_OSRS_PRESS_4X BMP280_OSRS_PRESS_X(3) -#define BMP280_OSRS_PRESS_8X BMP280_OSRS_PRESS_X(4) -#define BMP280_OSRS_PRESS_16X BMP280_OSRS_PRESS_X(5) - -#define BMP280_MODE_MASK (BIT(1) | BIT(0)) -#define BMP280_MODE_SLEEP 0 -#define BMP280_MODE_FORCED BIT(0) -#define BMP280_MODE_NORMAL (BIT(1) | BIT(0)) - -/* BMP180 specific registers */ -#define BMP180_REG_OUT_XLSB 0xF8 -#define BMP180_REG_OUT_LSB 0xF7 -#define BMP180_REG_OUT_MSB 0xF6 - -#define BMP180_REG_CALIB_START 0xAA -#define BMP180_REG_CALIB_COUNT 22 - -#define BMP180_MEAS_SCO BIT(5) -#define BMP180_MEAS_TEMP (0x0E | BMP180_MEAS_SCO) -#define BMP180_MEAS_PRESS_X(oss) ((oss) << 6 | 0x14 | BMP180_MEAS_SCO) -#define BMP180_MEAS_PRESS_1X BMP180_MEAS_PRESS_X(0) -#define BMP180_MEAS_PRESS_2X BMP180_MEAS_PRESS_X(1) -#define BMP180_MEAS_PRESS_4X BMP180_MEAS_PRESS_X(2) -#define BMP180_MEAS_PRESS_8X BMP180_MEAS_PRESS_X(3) - -/* BMP180 and BMP280 common registers */ -#define BMP280_REG_CTRL_MEAS 0xF4 -#define BMP280_REG_RESET 0xE0 -#define BMP280_REG_ID 0xD0 - -#define BMP180_CHIP_ID 0x55 -#define BMP280_CHIP_ID 0x58 -#define BMP280_SOFT_RESET_VAL 0xB6 +#include "bmp280.h" + +/* + * These enums are used for indexing into the array of calibration + * coefficients for BMP180. + */ +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; +}; struct bmp280_data { - struct i2c_client *client; + struct device *dev; struct mutex lock; struct regmap *regmap; + struct completion done; + bool use_eoc; const struct bmp280_chip_info *chip_info; + struct bmp180_calib calib; + struct regulator *vddd; + struct regulator *vdda; + unsigned int start_up_time; /* in milliseconds */ /* log of base 2 of oversampling rate */ u8 oversampling_press; u8 oversampling_temp; + u8 oversampling_humid; /* * Carryover value from temperature conversion, used in pressure @@ -112,17 +80,19 @@ struct bmp280_data { }; struct bmp280_chip_info { - const struct regmap_config *regmap_config; - const int *oversampling_temp_avail; int num_oversampling_temp_avail; const int *oversampling_press_avail; int num_oversampling_press_avail; + const int *oversampling_humid_avail; + int num_oversampling_humid_avail; + 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 *); }; /* @@ -143,45 +113,75 @@ static const struct iio_chan_spec bmp280_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), }, + { + .type = IIO_HUMIDITYRELATIVE, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + }, }; -static bool bmp280_is_writeable_reg(struct device *dev, unsigned int reg) -{ - switch (reg) { - case BMP280_REG_CONFIG: - case BMP280_REG_CTRL_MEAS: - case BMP280_REG_RESET: - return true; - default: - return false; - }; -} +/* + * Returns humidity in percent, resolution is 0.01 percent. Output value of + * "47445" represents 47445/1024 = 46.333 %RH. + * + * Taken from BME280 datasheet, Section 4.2.3, "Compensation formula". + */ -static bool bmp280_is_volatile_reg(struct device *dev, unsigned int reg) +static u32 bmp280_compensate_humidity(struct bmp280_data *data, + s32 adc_humidity) { - switch (reg) { - case BMP280_REG_TEMP_XLSB: - case BMP280_REG_TEMP_LSB: - case BMP280_REG_TEMP_MSB: - case BMP280_REG_PRESS_XLSB: - case BMP280_REG_PRESS_LSB: - case BMP280_REG_PRESS_MSB: - case BMP280_REG_STATUS: - return true; - default: - return false; + struct device *dev = data->dev; + unsigned int H1, H3, tmp; + int H2, H4, H5, H6, ret, var; + + ret = regmap_read(data->regmap, BMP280_REG_COMP_H1, &H1); + if (ret < 0) { + dev_err(dev, "failed to read H1 comp value\n"); + return ret; } -} -static const struct regmap_config bmp280_regmap_config = { - .reg_bits = 8, - .val_bits = 8, + ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H2, &tmp, 2); + if (ret < 0) { + dev_err(dev, "failed to read H2 comp value\n"); + return ret; + } + H2 = sign_extend32(le16_to_cpu(tmp), 15); + + ret = regmap_read(data->regmap, BMP280_REG_COMP_H3, &H3); + if (ret < 0) { + dev_err(dev, "failed to read H3 comp value\n"); + return ret; + } + + ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H4, &tmp, 2); + if (ret < 0) { + dev_err(dev, "failed to read H4 comp value\n"); + return ret; + } + H4 = sign_extend32(((be16_to_cpu(tmp) >> 4) & 0xff0) | + (be16_to_cpu(tmp) & 0xf), 11); + + ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H5, &tmp, 2); + if (ret < 0) { + dev_err(dev, "failed to read H5 comp value\n"); + return ret; + } + H5 = sign_extend32(((le16_to_cpu(tmp) >> 4) & 0xfff), 11); + + ret = regmap_read(data->regmap, BMP280_REG_COMP_H6, &tmp); + if (ret < 0) { + dev_err(dev, "failed to read H6 comp value\n"); + return ret; + } + H6 = sign_extend32(tmp, 7); - .max_register = BMP280_REG_TEMP_XLSB, - .cache_type = REGCACHE_RBTREE, + var = ((s32)data->t_fine) - 76800; + var = ((((adc_humidity << 14) - (H4 << 20) - (H5 * var)) + 16384) >> 15) + * (((((((var * H6) >> 10) * (((var * H3) >> 11) + 32768)) >> 10) + + 2097152) * H2 + 8192) >> 14); + var -= ((((var >> 15) * (var >> 15)) >> 7) * H1) >> 4; - .writeable_reg = bmp280_is_writeable_reg, - .volatile_reg = bmp280_is_volatile_reg, + return var >> 12; }; /* @@ -201,7 +201,7 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data, ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START, buf, BMP280_COMP_TEMP_REG_COUNT); if (ret < 0) { - dev_err(&data->client->dev, + dev_err(data->dev, "failed to read temperature calibration parameters\n"); return ret; } @@ -241,7 +241,7 @@ static u32 bmp280_compensate_press(struct bmp280_data *data, ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_PRESS_START, buf, BMP280_COMP_PRESS_REG_COUNT); if (ret < 0) { - dev_err(&data->client->dev, + dev_err(data->dev, "failed to read pressure calibration parameters\n"); return ret; } @@ -276,7 +276,7 @@ static int bmp280_read_temp(struct bmp280_data *data, ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB, (u8 *) &tmp, 3); if (ret < 0) { - dev_err(&data->client->dev, "failed to read temperature\n"); + dev_err(data->dev, "failed to read temperature\n"); return ret; } @@ -311,7 +311,7 @@ static int bmp280_read_press(struct bmp280_data *data, ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB, (u8 *) &tmp, 3); if (ret < 0) { - dev_err(&data->client->dev, "failed to read pressure\n"); + dev_err(data->dev, "failed to read pressure\n"); return ret; } @@ -324,6 +324,34 @@ static int bmp280_read_press(struct bmp280_data *data, return IIO_VAL_FRACTIONAL; } +static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2) +{ + int ret; + __be16 tmp = 0; + s32 adc_humidity; + u32 comp_humidity; + + /* Read and compensate temperature so we get a reading of t_fine. */ + ret = bmp280_read_temp(data, NULL); + if (ret < 0) + return ret; + + ret = regmap_bulk_read(data->regmap, BMP280_REG_HUMIDITY_MSB, + (u8 *) &tmp, 2); + if (ret < 0) { + dev_err(data->dev, "failed to read humidity\n"); + return ret; + } + + adc_humidity = be16_to_cpu(tmp); + comp_humidity = bmp280_compensate_humidity(data, adc_humidity); + + *val = comp_humidity; + *val2 = 1024; + + return IIO_VAL_FRACTIONAL; +} + static int bmp280_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -331,11 +359,15 @@ static int bmp280_read_raw(struct iio_dev *indio_dev, int ret; struct bmp280_data *data = iio_priv(indio_dev); + pm_runtime_get_sync(data->dev); mutex_lock(&data->lock); switch (mask) { case IIO_CHAN_INFO_PROCESSED: switch (chan->type) { + case IIO_HUMIDITYRELATIVE: + ret = data->chip_info->read_humid(data, val, val2); + break; case IIO_PRESSURE: ret = data->chip_info->read_press(data, val, val2); break; @@ -349,6 +381,10 @@ static int bmp280_read_raw(struct iio_dev *indio_dev, break; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: switch (chan->type) { + case IIO_HUMIDITYRELATIVE: + *val = 1 << data->oversampling_humid; + ret = IIO_VAL_INT; + break; case IIO_PRESSURE: *val = 1 << data->oversampling_press; ret = IIO_VAL_INT; @@ -368,10 +404,29 @@ static int bmp280_read_raw(struct iio_dev *indio_dev, } mutex_unlock(&data->lock); + pm_runtime_mark_last_busy(data->dev); + pm_runtime_put_autosuspend(data->dev); return ret; } +static int bmp280_write_oversampling_ratio_humid(struct bmp280_data *data, + int val) +{ + int i; + const int *avail = data->chip_info->oversampling_humid_avail; + const int n = data->chip_info->num_oversampling_humid_avail; + + for (i = 0; i < n; i++) { + if (avail[i] == val) { + data->oversampling_humid = ilog2(val); + + return data->chip_info->chip_config(data); + } + } + return -EINVAL; +} + static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data, int val) { @@ -415,8 +470,12 @@ static int bmp280_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + pm_runtime_get_sync(data->dev); mutex_lock(&data->lock); switch (chan->type) { + case IIO_HUMIDITYRELATIVE: + ret = bmp280_write_oversampling_ratio_humid(data, val); + break; case IIO_PRESSURE: ret = bmp280_write_oversampling_ratio_press(data, val); break; @@ -428,6 +487,8 @@ static int bmp280_write_raw(struct iio_dev *indio_dev, break; } mutex_unlock(&data->lock); + pm_runtime_mark_last_busy(data->dev); + pm_runtime_put_autosuspend(data->dev); break; default: return -EINVAL; @@ -502,7 +563,7 @@ static int bmp280_chip_config(struct bmp280_data *data) BMP280_MODE_MASK, osrs | BMP280_MODE_NORMAL); if (ret < 0) { - dev_err(&data->client->dev, + dev_err(data->dev, "failed to write ctrl_meas register\n"); return ret; } @@ -511,7 +572,7 @@ static int bmp280_chip_config(struct bmp280_data *data) BMP280_FILTER_MASK, BMP280_FILTER_4X); if (ret < 0) { - dev_err(&data->client->dev, + dev_err(data->dev, "failed to write config register\n"); return ret; } @@ -522,8 +583,6 @@ 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 = { - .regmap_config = &bmp280_regmap_config, - .oversampling_temp_avail = bmp280_oversampling_avail, .num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail), @@ -535,39 +594,32 @@ static const struct bmp280_chip_info bmp280_chip_info = { .read_press = bmp280_read_press, }; -static bool bmp180_is_writeable_reg(struct device *dev, unsigned int reg) +static int bme280_chip_config(struct bmp280_data *data) { - switch (reg) { - case BMP280_REG_CTRL_MEAS: - case BMP280_REG_RESET: - return true; - default: - return false; - }; -} + int ret = bmp280_chip_config(data); + u8 osrs = BMP280_OSRS_HUMIDITIY_X(data->oversampling_humid + 1); -static bool bmp180_is_volatile_reg(struct device *dev, unsigned int reg) -{ - switch (reg) { - case BMP180_REG_OUT_XLSB: - case BMP180_REG_OUT_LSB: - case BMP180_REG_OUT_MSB: - case BMP280_REG_CTRL_MEAS: - return true; - default: - return false; - } + if (ret < 0) + return ret; + + return regmap_update_bits(data->regmap, BMP280_REG_CTRL_HUMIDITY, + BMP280_OSRS_HUMIDITY_MASK, osrs); } -static const struct regmap_config bmp180_regmap_config = { - .reg_bits = 8, - .val_bits = 8, +static const struct bmp280_chip_info bme280_chip_info = { + .oversampling_temp_avail = bmp280_oversampling_avail, + .num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail), + + .oversampling_press_avail = bmp280_oversampling_avail, + .num_oversampling_press_avail = ARRAY_SIZE(bmp280_oversampling_avail), - .max_register = BMP180_REG_OUT_XLSB, - .cache_type = REGCACHE_RBTREE, + .oversampling_humid_avail = bmp280_oversampling_avail, + .num_oversampling_humid_avail = ARRAY_SIZE(bmp280_oversampling_avail), - .writeable_reg = bmp180_is_writeable_reg, - .volatile_reg = bmp180_is_volatile_reg, + .chip_config = bme280_chip_config, + .read_temp = bmp280_read_temp, + .read_press = bmp280_read_press, + .read_humid = bmp280_read_humid, }; static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas) @@ -577,16 +629,32 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas) unsigned int delay_us; unsigned int ctrl; + if (data->use_eoc) + init_completion(&data->done); + ret = regmap_write(data->regmap, BMP280_REG_CTRL_MEAS, ctrl_meas); if (ret) return ret; - if (ctrl_meas == BMP180_MEAS_TEMP) - delay_us = 4500; - else - delay_us = conversion_time_max[data->oversampling_press]; - - usleep_range(delay_us, delay_us + 1000); + if (data->use_eoc) { + /* + * If we have a completion interrupt, use it, wait up to + * 100ms. The longest conversion time listed is 76.5 ms for + * advanced resolution mode. + */ + ret = wait_for_completion_timeout(&data->done, + 1 + msecs_to_jiffies(100)); + if (!ret) + dev_err(data->dev, "timeout waiting for completion\n"); + } else { + if (ctrl_meas == BMP180_MEAS_TEMP) + delay_us = 4500; + else + delay_us = + conversion_time_max[data->oversampling_press]; + + usleep_range(delay_us, delay_us + 1000); + } ret = regmap_read(data->regmap, BMP280_REG_CTRL_MEAS, &ctrl); if (ret) @@ -617,26 +685,6 @@ static int bmp180_read_adc_temp(struct bmp280_data *data, int *val) return 0; } -/* - * These enums are used for indexing into the array of calibration - * coefficients for BMP180. - */ -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; -}; - static int bmp180_read_calib(struct bmp280_data *data, struct bmp180_calib *calib) { @@ -656,6 +704,9 @@ static int bmp180_read_calib(struct bmp280_data *data, return -EIO; } + /* Toss the calibration data into the entropy pool */ + add_device_randomness(buf, sizeof(buf)); + calib->AC1 = be16_to_cpu(buf[AC1]); calib->AC2 = be16_to_cpu(buf[AC2]); calib->AC3 = be16_to_cpu(buf[AC3]); @@ -679,19 +730,11 @@ static int bmp180_read_calib(struct bmp280_data *data, */ static s32 bmp180_compensate_temp(struct bmp280_data *data, s32 adc_temp) { - int ret; s32 x1, x2; - struct bmp180_calib calib; + struct bmp180_calib *calib = &data->calib; - ret = bmp180_read_calib(data, &calib); - if (ret < 0) { - dev_err(&data->client->dev, - "failed to read calibration coefficients\n"); - return ret; - } - - x1 = ((adc_temp - calib.AC6) * calib.AC5) >> 15; - x2 = (calib.MC << 11) / (x1 + calib.MD); + x1 = ((adc_temp - calib->AC6) * calib->AC5) >> 15; + x2 = (calib->MC << 11) / (x1 + calib->MD); data->t_fine = x1 + x2; return (data->t_fine + 8) >> 4; @@ -746,29 +789,21 @@ static int bmp180_read_adc_press(struct bmp280_data *data, int *val) */ static u32 bmp180_compensate_press(struct bmp280_data *data, s32 adc_press) { - int ret; s32 x1, x2, x3, p; s32 b3, b6; u32 b4, b7; s32 oss = data->oversampling_press; - struct bmp180_calib calib; - - ret = bmp180_read_calib(data, &calib); - if (ret < 0) { - dev_err(&data->client->dev, - "failed to read calibration coefficients\n"); - return ret; - } + struct bmp180_calib *calib = &data->calib; b6 = data->t_fine - 4000; - x1 = (calib.B2 * (b6 * b6 >> 12)) >> 11; - x2 = calib.AC2 * b6 >> 11; + x1 = (calib->B2 * (b6 * b6 >> 12)) >> 11; + x2 = calib->AC2 * b6 >> 11; x3 = x1 + x2; - b3 = ((((s32)calib.AC1 * 4 + x3) << oss) + 2) / 4; - x1 = calib.AC3 * b6 >> 13; - x2 = (calib.B1 * ((b6 * b6) >> 12)) >> 16; + b3 = ((((s32)calib->AC1 * 4 + x3) << oss) + 2) / 4; + x1 = calib->AC3 * b6 >> 13; + x2 = (calib->B1 * ((b6 * b6) >> 12)) >> 16; x3 = (x1 + x2 + 2) >> 2; - b4 = calib.AC4 * (u32)(x3 + 32768) >> 15; + b4 = calib->AC4 * (u32)(x3 + 32768) >> 15; b7 = ((u32)adc_press - b3) * (50000 >> oss); if (b7 < 0x80000000) p = (b7 * 2) / b4; @@ -815,8 +850,6 @@ 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 = { - .regmap_config = &bmp180_regmap_config, - .oversampling_temp_avail = bmp180_oversampling_temp_avail, .num_oversampling_temp_avail = ARRAY_SIZE(bmp180_oversampling_temp_avail), @@ -830,92 +863,254 @@ static const struct bmp280_chip_info bmp180_chip_info = { .read_press = bmp180_read_press, }; -static int bmp280_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static irqreturn_t bmp085_eoc_irq(int irq, void *d) +{ + struct bmp280_data *data = d; + + complete(&data->done); + + return IRQ_HANDLED; +} + +static int bmp085_fetch_eoc_irq(struct device *dev, + const char *name, + int irq, + struct bmp280_data *data) +{ + unsigned long irq_trig; + int ret; + + irq_trig = irqd_get_trigger_type(irq_get_irq_data(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; + } + ret = devm_request_threaded_irq(dev, + irq, + bmp085_eoc_irq, + NULL, + irq_trig, + name, + data); + if (ret) { + /* Bail out without IRQ but keep the driver in place */ + dev_err(dev, "unable to request DRDY IRQ\n"); + return 0; + } + + data->use_eoc = true; + return 0; +} + +int bmp280_common_probe(struct device *dev, + struct regmap *regmap, + unsigned int chip, + const char *name, + int irq) { int ret; struct iio_dev *indio_dev; struct bmp280_data *data; unsigned int chip_id; + struct gpio_desc *gpiod; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); mutex_init(&data->lock); - data->client = client; + data->dev = dev; - indio_dev->dev.parent = &client->dev; - indio_dev->name = id->name; + indio_dev->dev.parent = dev; + indio_dev->name = name; indio_dev->channels = bmp280_channels; - indio_dev->num_channels = ARRAY_SIZE(bmp280_channels); indio_dev->info = &bmp280_info; indio_dev->modes = INDIO_DIRECT_MODE; - switch (id->driver_data) { + switch (chip) { case BMP180_CHIP_ID: + indio_dev->num_channels = 2; data->chip_info = &bmp180_chip_info; data->oversampling_press = ilog2(8); data->oversampling_temp = ilog2(1); + data->start_up_time = 10; break; case BMP280_CHIP_ID: + indio_dev->num_channels = 2; data->chip_info = &bmp280_chip_info; data->oversampling_press = ilog2(16); data->oversampling_temp = ilog2(2); + data->start_up_time = 2; + break; + case BME280_CHIP_ID: + indio_dev->num_channels = 3; + data->chip_info = &bme280_chip_info; + data->oversampling_press = ilog2(16); + data->oversampling_humid = ilog2(16); + data->oversampling_temp = ilog2(2); + data->start_up_time = 2; break; default: return -EINVAL; } - data->regmap = devm_regmap_init_i2c(client, - data->chip_info->regmap_config); - if (IS_ERR(data->regmap)) { - dev_err(&client->dev, "failed to allocate register map\n"); - return PTR_ERR(data->regmap); + /* Bring up regulators */ + data->vddd = devm_regulator_get(dev, "vddd"); + if (IS_ERR(data->vddd)) { + dev_err(dev, "failed to get VDDD regulator\n"); + return PTR_ERR(data->vddd); + } + ret = regulator_enable(data->vddd); + if (ret) { + dev_err(dev, "failed to enable VDDD regulator\n"); + return ret; + } + data->vdda = devm_regulator_get(dev, "vdda"); + if (IS_ERR(data->vdda)) { + dev_err(dev, "failed to get VDDA regulator\n"); + ret = PTR_ERR(data->vddd); + goto out_disable_vddd; + } + ret = regulator_enable(data->vdda); + if (ret) { + dev_err(dev, "failed to enable VDDA regulator\n"); + goto out_disable_vddd; + } + /* Wait to make sure we started up properly */ + mdelay(data->start_up_time); + + /* Bring chip out of reset if there is an assigned GPIO line */ + gpiod = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + /* Deassert the signal */ + if (!IS_ERR(gpiod)) { + dev_info(dev, "release reset\n"); + gpiod_set_value(gpiod, 0); } - ret = regmap_read(data->regmap, BMP280_REG_ID, &chip_id); + data->regmap = regmap; + ret = regmap_read(regmap, BMP280_REG_ID, &chip_id); if (ret < 0) - return ret; - if (chip_id != id->driver_data) { - dev_err(&client->dev, "bad chip id. expected %lx got %x\n", - id->driver_data, chip_id); - return -EINVAL; + goto out_disable_vdda; + if (chip_id != chip) { + dev_err(dev, "bad chip id: expected %x got %x\n", + chip, chip_id); + ret = -EINVAL; + goto out_disable_vdda; } ret = data->chip_info->chip_config(data); if (ret < 0) - return ret; + goto out_disable_vdda; + + dev_set_drvdata(dev, indio_dev); + + /* + * The BMP085 and BMP180 has calibration in an E2PROM, read it out + * at probe time. It will not change. + */ + if (chip_id == BMP180_CHIP_ID) { + ret = bmp180_read_calib(data, &data->calib); + if (ret < 0) { + dev_err(data->dev, + "failed to read calibration coefficients\n"); + goto out_disable_vdda; + } + } + + /* + * Attempt to grab an optional EOC IRQ - only the BMP085 has this + * however as it happens, the BMP085 shares the chip ID of BMP180 + * so we look for an IRQ if we have that. + */ + if (irq > 0 || (chip_id == BMP180_CHIP_ID)) { + ret = bmp085_fetch_eoc_irq(dev, name, irq, data); + if (ret) + goto out_disable_vdda; + } + + /* Enable runtime PM */ + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + /* + * Set autosuspend to two orders of magnitude larger than the + * start-up time. + */ + pm_runtime_set_autosuspend_delay(dev, data->start_up_time *100); + pm_runtime_use_autosuspend(dev); + pm_runtime_put(dev); + + ret = iio_device_register(indio_dev); + if (ret) + goto out_runtime_pm_disable; + - return devm_iio_device_register(&client->dev, indio_dev); + return 0; + +out_runtime_pm_disable: + pm_runtime_get_sync(data->dev); + pm_runtime_put_noidle(data->dev); + pm_runtime_disable(data->dev); +out_disable_vdda: + regulator_disable(data->vdda); +out_disable_vddd: + regulator_disable(data->vddd); + return ret; } +EXPORT_SYMBOL(bmp280_common_probe); -static const struct acpi_device_id bmp280_acpi_match[] = { - {"BMP0280", BMP280_CHIP_ID }, - {"BMP0180", BMP180_CHIP_ID }, - {"BMP0085", BMP180_CHIP_ID }, - { }, -}; -MODULE_DEVICE_TABLE(acpi, bmp280_acpi_match); +int bmp280_common_remove(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct bmp280_data *data = iio_priv(indio_dev); -static const struct i2c_device_id bmp280_id[] = { - {"bmp280", BMP280_CHIP_ID }, - {"bmp180", BMP180_CHIP_ID }, - {"bmp085", BMP180_CHIP_ID }, - { }, -}; -MODULE_DEVICE_TABLE(i2c, bmp280_id); + iio_device_unregister(indio_dev); + pm_runtime_get_sync(data->dev); + pm_runtime_put_noidle(data->dev); + pm_runtime_disable(data->dev); + regulator_disable(data->vdda); + regulator_disable(data->vddd); + return 0; +} +EXPORT_SYMBOL(bmp280_common_remove); -static struct i2c_driver bmp280_driver = { - .driver = { - .name = "bmp280", - .acpi_match_table = ACPI_PTR(bmp280_acpi_match), - }, - .probe = bmp280_probe, - .id_table = bmp280_id, +#ifdef CONFIG_PM +static int bmp280_runtime_suspend(struct device *dev) +{ + struct bmp280_data *data = dev_get_drvdata(dev); + int ret; + + ret = regulator_disable(data->vdda); + if (ret) + return ret; + return regulator_disable(data->vddd); +} + +static int bmp280_runtime_resume(struct device *dev) +{ + struct bmp280_data *data = dev_get_drvdata(dev); + int ret; + + ret = regulator_enable(data->vddd); + if (ret) + return ret; + ret = regulator_enable(data->vdda); + if (ret) + return ret; + msleep(data->start_up_time); + return data->chip_info->chip_config(data); +} +#endif /* CONFIG_PM */ + +const struct dev_pm_ops bmp280_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(bmp280_runtime_suspend, + bmp280_runtime_resume, NULL) }; -module_i2c_driver(bmp280_driver); +EXPORT_SYMBOL(bmp280_dev_pm_ops); MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>"); MODULE_DESCRIPTION("Driver for Bosch Sensortec BMP180/BMP280 pressure and temperature sensor"); diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c new file mode 100644 index 000000000000..03742b15b72a --- /dev/null +++ b/drivers/iio/pressure/bmp280-i2c.c @@ -0,0 +1,91 @@ +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/acpi.h> +#include <linux/of.h> +#include <linux/regmap.h> + +#include "bmp280.h" + +static int bmp280_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + const struct regmap_config *regmap_config; + + 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; + default: + return -EINVAL; + } + + regmap = devm_regmap_init_i2c(client, regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "failed to allocate register map\n"); + return PTR_ERR(regmap); + } + + return bmp280_common_probe(&client->dev, + regmap, + id->driver_data, + id->name, + client->irq); +} + +static int bmp280_i2c_remove(struct i2c_client *client) +{ + return bmp280_common_remove(&client->dev); +} + +static const struct acpi_device_id bmp280_acpi_i2c_match[] = { + {"BMP0280", BMP280_CHIP_ID }, + {"BMP0180", BMP180_CHIP_ID }, + {"BMP0085", BMP180_CHIP_ID }, + {"BME0280", BME280_CHIP_ID }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, bmp280_acpi_i2c_match); + +#ifdef CONFIG_OF +static const struct of_device_id bmp280_of_i2c_match[] = { + { .compatible = "bosch,bme280", .data = (void *)BME280_CHIP_ID }, + { .compatible = "bosch,bmp280", .data = (void *)BMP280_CHIP_ID }, + { .compatible = "bosch,bmp180", .data = (void *)BMP180_CHIP_ID }, + { .compatible = "bosch,bmp085", .data = (void *)BMP180_CHIP_ID }, + { }, +}; +MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match); +#else +#define bmp280_of_i2c_match NULL +#endif + +static const struct i2c_device_id bmp280_i2c_id[] = { + {"bmp280", BMP280_CHIP_ID }, + {"bmp180", BMP180_CHIP_ID }, + {"bmp085", BMP180_CHIP_ID }, + {"bme280", BME280_CHIP_ID }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, bmp280_i2c_id); + +static struct i2c_driver bmp280_i2c_driver = { + .driver = { + .name = "bmp280", + .acpi_match_table = ACPI_PTR(bmp280_acpi_i2c_match), + .of_match_table = of_match_ptr(bmp280_of_i2c_match), + .pm = &bmp280_dev_pm_ops, + }, + .probe = bmp280_i2c_probe, + .remove = bmp280_i2c_remove, + .id_table = bmp280_i2c_id, +}; +module_i2c_driver(bmp280_i2c_driver); + +MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>"); +MODULE_DESCRIPTION("Driver for Bosch Sensortec BMP180/BMP280 pressure and temperature sensor"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/pressure/bmp280-regmap.c b/drivers/iio/pressure/bmp280-regmap.c new file mode 100644 index 000000000000..6807113ec09f --- /dev/null +++ b/drivers/iio/pressure/bmp280-regmap.c @@ -0,0 +1,84 @@ +#include <linux/device.h> +#include <linux/module.h> +#include <linux/regmap.h> + +#include "bmp280.h" + +static bool bmp180_is_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case BMP280_REG_CTRL_MEAS: + case BMP280_REG_RESET: + return true; + default: + return false; + }; +} + +static bool bmp180_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case BMP180_REG_OUT_XLSB: + case BMP180_REG_OUT_LSB: + case BMP180_REG_OUT_MSB: + case BMP280_REG_CTRL_MEAS: + return true; + default: + return false; + } +} + +const struct regmap_config bmp180_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = BMP180_REG_OUT_XLSB, + .cache_type = REGCACHE_RBTREE, + + .writeable_reg = bmp180_is_writeable_reg, + .volatile_reg = bmp180_is_volatile_reg, +}; +EXPORT_SYMBOL(bmp180_regmap_config); + +static bool bmp280_is_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case BMP280_REG_CONFIG: + case BMP280_REG_CTRL_HUMIDITY: + case BMP280_REG_CTRL_MEAS: + case BMP280_REG_RESET: + return true; + default: + return false; + }; +} + +static bool bmp280_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case BMP280_REG_HUMIDITY_LSB: + case BMP280_REG_HUMIDITY_MSB: + case BMP280_REG_TEMP_XLSB: + case BMP280_REG_TEMP_LSB: + case BMP280_REG_TEMP_MSB: + case BMP280_REG_PRESS_XLSB: + case BMP280_REG_PRESS_LSB: + case BMP280_REG_PRESS_MSB: + case BMP280_REG_STATUS: + return true; + default: + return false; + } +} + +const struct regmap_config bmp280_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = BMP280_REG_HUMIDITY_LSB, + .cache_type = REGCACHE_RBTREE, + + .writeable_reg = bmp280_is_writeable_reg, + .volatile_reg = bmp280_is_volatile_reg, +}; +EXPORT_SYMBOL(bmp280_regmap_config); diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c new file mode 100644 index 000000000000..17bc95586f9e --- /dev/null +++ b/drivers/iio/pressure/bmp280-spi.c @@ -0,0 +1,125 @@ +/* + * SPI interface for the BMP280 driver + * + * Inspired by the older BMP085 driver drivers/misc/bmp085-spi.c + */ +#include <linux/module.h> +#include <linux/spi/spi.h> +#include <linux/err.h> +#include <linux/regmap.h> + +#include "bmp280.h" + +static int bmp280_regmap_spi_write(void *context, const void *data, + size_t count) +{ + struct device *dev = context; + struct spi_device *spi = to_spi_device(dev); + u8 buf[2]; + + memcpy(buf, data, 2); + /* + * The SPI register address (= full register address without bit 7) and + * the write command (bit7 = RW = '0') + */ + buf[0] &= ~0x80; + + return spi_write_then_read(spi, buf, 2, NULL, 0); +} + +static int bmp280_regmap_spi_read(void *context, const void *reg, + size_t reg_size, void *val, size_t val_size) +{ + struct device *dev = context; + struct spi_device *spi = to_spi_device(dev); + + return spi_write_then_read(spi, reg, reg_size, val, val_size); +} + +static struct regmap_bus bmp280_regmap_bus = { + .write = bmp280_regmap_spi_write, + .read = bmp280_regmap_spi_read, + .reg_format_endian_default = REGMAP_ENDIAN_BIG, + .val_format_endian_default = REGMAP_ENDIAN_BIG, +}; + +static int bmp280_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + struct regmap *regmap; + const struct regmap_config *regmap_config; + int ret; + + spi->bits_per_word = 8; + ret = spi_setup(spi); + if (ret < 0) { + dev_err(&spi->dev, "spi_setup failed!\n"); + 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; + default: + return -EINVAL; + } + + regmap = devm_regmap_init(&spi->dev, + &bmp280_regmap_bus, + &spi->dev, + regmap_config); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "failed to allocate register map\n"); + return PTR_ERR(regmap); + } + + return bmp280_common_probe(&spi->dev, + regmap, + id->driver_data, + id->name, + spi->irq); +} + +static int bmp280_spi_remove(struct spi_device *spi) +{ + return bmp280_common_remove(&spi->dev); +} + +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", }, + { }, +}; +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 }, + { } +}; +MODULE_DEVICE_TABLE(spi, bmp280_spi_id); + +static struct spi_driver bmp280_spi_driver = { + .driver = { + .name = "bmp280", + .of_match_table = bmp280_of_spi_match, + .pm = &bmp280_dev_pm_ops, + }, + .id_table = bmp280_spi_id, + .probe = bmp280_spi_probe, + .remove = bmp280_spi_remove, +}; +module_spi_driver(bmp280_spi_driver); + +MODULE_DESCRIPTION("BMP280 SPI bus driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h new file mode 100644 index 000000000000..2c770e13be0e --- /dev/null +++ b/drivers/iio/pressure/bmp280.h @@ -0,0 +1,112 @@ +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/regmap.h> + +/* BMP280 specific registers */ +#define BMP280_REG_HUMIDITY_LSB 0xFE +#define BMP280_REG_HUMIDITY_MSB 0xFD +#define BMP280_REG_TEMP_XLSB 0xFC +#define BMP280_REG_TEMP_LSB 0xFB +#define BMP280_REG_TEMP_MSB 0xFA +#define BMP280_REG_PRESS_XLSB 0xF9 +#define BMP280_REG_PRESS_LSB 0xF8 +#define BMP280_REG_PRESS_MSB 0xF7 + +#define BMP280_REG_CONFIG 0xF5 +#define BMP280_REG_CTRL_MEAS 0xF4 +#define BMP280_REG_STATUS 0xF3 +#define BMP280_REG_CTRL_HUMIDITY 0xF2 + +/* Due to non linear mapping, and data sizes we can't do a bulk read */ +#define BMP280_REG_COMP_H1 0xA1 +#define BMP280_REG_COMP_H2 0xE1 +#define BMP280_REG_COMP_H3 0xE3 +#define BMP280_REG_COMP_H4 0xE4 +#define BMP280_REG_COMP_H5 0xE5 +#define BMP280_REG_COMP_H6 0xE7 + +#define BMP280_REG_COMP_TEMP_START 0x88 +#define BMP280_COMP_TEMP_REG_COUNT 6 + +#define BMP280_REG_COMP_PRESS_START 0x8E +#define BMP280_COMP_PRESS_REG_COUNT 18 + +#define BMP280_FILTER_MASK (BIT(4) | BIT(3) | BIT(2)) +#define BMP280_FILTER_OFF 0 +#define BMP280_FILTER_2X BIT(2) +#define BMP280_FILTER_4X BIT(3) +#define BMP280_FILTER_8X (BIT(3) | BIT(2)) +#define BMP280_FILTER_16X BIT(4) + +#define BMP280_OSRS_HUMIDITY_MASK (BIT(2) | BIT(1) | BIT(0)) +#define BMP280_OSRS_HUMIDITIY_X(osrs_h) ((osrs_h) << 0) +#define BMP280_OSRS_HUMIDITY_SKIP 0 +#define BMP280_OSRS_HUMIDITY_1X BMP280_OSRS_HUMIDITIY_X(1) +#define BMP280_OSRS_HUMIDITY_2X BMP280_OSRS_HUMIDITIY_X(2) +#define BMP280_OSRS_HUMIDITY_4X BMP280_OSRS_HUMIDITIY_X(3) +#define BMP280_OSRS_HUMIDITY_8X BMP280_OSRS_HUMIDITIY_X(4) +#define BMP280_OSRS_HUMIDITY_16X BMP280_OSRS_HUMIDITIY_X(5) + +#define BMP280_OSRS_TEMP_MASK (BIT(7) | BIT(6) | BIT(5)) +#define BMP280_OSRS_TEMP_SKIP 0 +#define BMP280_OSRS_TEMP_X(osrs_t) ((osrs_t) << 5) +#define BMP280_OSRS_TEMP_1X BMP280_OSRS_TEMP_X(1) +#define BMP280_OSRS_TEMP_2X BMP280_OSRS_TEMP_X(2) +#define BMP280_OSRS_TEMP_4X BMP280_OSRS_TEMP_X(3) +#define BMP280_OSRS_TEMP_8X BMP280_OSRS_TEMP_X(4) +#define BMP280_OSRS_TEMP_16X BMP280_OSRS_TEMP_X(5) + +#define BMP280_OSRS_PRESS_MASK (BIT(4) | BIT(3) | BIT(2)) +#define BMP280_OSRS_PRESS_SKIP 0 +#define BMP280_OSRS_PRESS_X(osrs_p) ((osrs_p) << 2) +#define BMP280_OSRS_PRESS_1X BMP280_OSRS_PRESS_X(1) +#define BMP280_OSRS_PRESS_2X BMP280_OSRS_PRESS_X(2) +#define BMP280_OSRS_PRESS_4X BMP280_OSRS_PRESS_X(3) +#define BMP280_OSRS_PRESS_8X BMP280_OSRS_PRESS_X(4) +#define BMP280_OSRS_PRESS_16X BMP280_OSRS_PRESS_X(5) + +#define BMP280_MODE_MASK (BIT(1) | BIT(0)) +#define BMP280_MODE_SLEEP 0 +#define BMP280_MODE_FORCED BIT(0) +#define BMP280_MODE_NORMAL (BIT(1) | BIT(0)) + +/* BMP180 specific registers */ +#define BMP180_REG_OUT_XLSB 0xF8 +#define BMP180_REG_OUT_LSB 0xF7 +#define BMP180_REG_OUT_MSB 0xF6 + +#define BMP180_REG_CALIB_START 0xAA +#define BMP180_REG_CALIB_COUNT 22 + +#define BMP180_MEAS_SCO BIT(5) +#define BMP180_MEAS_TEMP (0x0E | BMP180_MEAS_SCO) +#define BMP180_MEAS_PRESS_X(oss) ((oss) << 6 | 0x14 | BMP180_MEAS_SCO) +#define BMP180_MEAS_PRESS_1X BMP180_MEAS_PRESS_X(0) +#define BMP180_MEAS_PRESS_2X BMP180_MEAS_PRESS_X(1) +#define BMP180_MEAS_PRESS_4X BMP180_MEAS_PRESS_X(2) +#define BMP180_MEAS_PRESS_8X BMP180_MEAS_PRESS_X(3) + +/* BMP180 and BMP280 common registers */ +#define BMP280_REG_CTRL_MEAS 0xF4 +#define BMP280_REG_RESET 0xE0 +#define BMP280_REG_ID 0xD0 + +#define BMP180_CHIP_ID 0x55 +#define BMP280_CHIP_ID 0x58 +#define BME280_CHIP_ID 0x60 +#define BMP280_SOFT_RESET_VAL 0xB6 + +/* Regmap configurations */ +extern const struct regmap_config bmp180_regmap_config; +extern const struct regmap_config bmp280_regmap_config; + +/* Probe called from different transports */ +int bmp280_common_probe(struct device *dev, + struct regmap *regmap, + unsigned int chip, + const char *name, + int irq); +int bmp280_common_remove(struct device *dev); + +/* PM ops */ +extern const struct dev_pm_ops bmp280_dev_pm_ops; diff --git a/drivers/iio/pressure/hp206c.c b/drivers/iio/pressure/hp206c.c index 90f2b6e4a920..12f769e86355 100644 --- a/drivers/iio/pressure/hp206c.c +++ b/drivers/iio/pressure/hp206c.c @@ -401,6 +401,7 @@ static const struct i2c_device_id hp206c_id[] = { {"hp206c"}, {} }; +MODULE_DEVICE_TABLE(i2c, hp206c_id); #ifdef CONFIG_ACPI static const struct acpi_device_id hp206c_acpi_match[] = { diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c index 01b2e0b18878..6392d7b62841 100644 --- a/drivers/iio/pressure/mpl3115.c +++ b/drivers/iio/pressure/mpl3115.c @@ -171,7 +171,7 @@ static irqreturn_t mpl3115_trigger_handler(int irq, void *p) mutex_unlock(&data->lock); iio_push_to_buffers_with_timestamp(indio_dev, buffer, - iio_get_time_ns()); + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index 76578b07bb6e..feb41f82c64a 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -224,7 +224,8 @@ static irqreturn_t ms5611_trigger_handler(int irq, void *p) if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); + iio_push_to_buffers_with_timestamp(indio_dev, buf, + iio_get_time_ns(indio_dev)); err: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/pressure/ms5637.c b/drivers/iio/pressure/ms5637.c index e68052c118e6..953ffbc0ef96 100644 --- a/drivers/iio/pressure/ms5637.c +++ b/drivers/iio/pressure/ms5637.c @@ -1,6 +1,6 @@ /* - * ms5637.c - Support for Measurement-Specialties ms5637 and ms8607 - * pressure & temperature sensor + * ms5637.c - Support for Measurement-Specialties MS5637, MS5805 + * MS5837 and MS8607 pressure & temperature sensor * * Copyright (c) 2015 Measurement-Specialties * @@ -11,6 +11,10 @@ * Datasheet: * http://www.meas-spec.com/downloads/MS5637-02BA03.pdf * Datasheet: + * http://www.meas-spec.com/downloads/MS5805-02BA01.pdf + * Datasheet: + * http://www.meas-spec.com/downloads/MS5837-30BA.pdf + * Datasheet: * http://www.meas-spec.com/downloads/MS8607-02BA01.pdf */ @@ -170,9 +174,12 @@ static int ms5637_probe(struct i2c_client *client, static const struct i2c_device_id ms5637_id[] = { {"ms5637", 0}, - {"ms8607-temppressure", 1}, + {"ms5805", 0}, + {"ms5837", 0}, + {"ms8607-temppressure", 0}, {} }; +MODULE_DEVICE_TABLE(i2c, ms5637_id); static struct i2c_driver ms5637_driver = { .probe = ms5637_probe, diff --git a/drivers/iio/pressure/st_pressure.h b/drivers/iio/pressure/st_pressure.h index f5f41490060b..903a21e46874 100644 --- a/drivers/iio/pressure/st_pressure.h +++ b/drivers/iio/pressure/st_pressure.h @@ -17,6 +17,7 @@ #define LPS001WP_PRESS_DEV_NAME "lps001wp" #define LPS25H_PRESS_DEV_NAME "lps25h" #define LPS331AP_PRESS_DEV_NAME "lps331ap" +#define LPS22HB_PRESS_DEV_NAME "lps22hb" /** * struct st_sensors_platform_data - default press platform data diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index 92a118c3c4ac..55df9a75eb3a 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -28,6 +28,72 @@ #include <linux/iio/common/st_sensors.h> #include "st_pressure.h" +/* + * About determining pressure scaling factors + * ------------------------------------------ + * + * Datasheets specify typical pressure sensitivity so that pressure is computed + * according to the following equation : + * pressure[mBar] = raw / sensitivity + * where : + * raw the 24 bits long raw sampled pressure + * sensitivity a scaling factor specified by the datasheet in LSB/mBar + * + * IIO ABI expects pressure to be expressed as kPascal, hence pressure should be + * computed according to : + * pressure[kPascal] = pressure[mBar] / 10 + * = raw / (sensitivity * 10) (1) + * + * Finally, st_press_read_raw() returns pressure scaling factor as an + * IIO_VAL_INT_PLUS_NANO with a zero integral part and "gain" as decimal part. + * Therefore, from (1), "gain" becomes : + * gain = 10^9 / (sensitivity * 10) + * = 10^8 / sensitivity + * + * About determining temperature scaling factors and offsets + * --------------------------------------------------------- + * + * Datasheets specify typical temperature sensitivity and offset so that + * temperature is computed according to the following equation : + * temp[Celsius] = offset[Celsius] + (raw / sensitivity) + * where : + * raw the 16 bits long raw sampled temperature + * offset a constant specified by the datasheet in degree Celsius + * (sometimes zero) + * sensitivity a scaling factor specified by the datasheet in LSB/Celsius + * + * IIO ABI expects temperature to be expressed as milli degree Celsius such as + * user space should compute temperature according to : + * temp[mCelsius] = temp[Celsius] * 10^3 + * = (offset[Celsius] + (raw / sensitivity)) * 10^3 + * = ((offset[Celsius] * sensitivity) + raw) * + * (10^3 / sensitivity) (2) + * + * IIO ABI expects user space to apply offset and scaling factors to raw samples + * according to : + * temp[mCelsius] = (OFFSET + raw) * SCALE + * where : + * OFFSET an arbitrary constant exposed by device + * SCALE an arbitrary scaling factor exposed by device + * + * Matching OFFSET and SCALE with members of (2) gives : + * OFFSET = offset[Celsius] * sensitivity (3) + * SCALE = 10^3 / sensitivity (4) + * + * st_press_read_raw() returns temperature scaling factor as an + * IIO_VAL_FRACTIONAL with a 10^3 numerator and "gain2" as denominator. + * Therefore, from (3), "gain2" becomes : + * gain2 = sensitivity + * + * When declared within channel, i.e. for a non zero specified offset, + * st_press_read_raw() will return the latter as an IIO_VAL_FRACTIONAL such as : + * numerator = OFFSET * 10^3 + * denominator = 10^3 + * giving from (4): + * numerator = offset[Celsius] * 10^3 * sensitivity + * = offset[mCelsius] * gain2 + */ + #define MCELSIUS_PER_CELSIUS 1000 /* Default pressure sensitivity */ @@ -39,8 +105,6 @@ #define ST_PRESS_LSB_PER_CELSIUS 480UL #define ST_PRESS_MILLI_CELSIUS_OFFSET 42500UL -#define ST_PRESS_NUMBER_DATA_CHANNELS 1 - /* FULLSCALE */ #define ST_PRESS_FS_AVL_1100MB 1100 #define ST_PRESS_FS_AVL_1260MB 1260 @@ -48,7 +112,11 @@ #define ST_PRESS_1_OUT_XL_ADDR 0x28 #define ST_TEMP_1_OUT_L_ADDR 0x2b -/* CUSTOM VALUES FOR LPS331AP SENSOR */ +/* + * CUSTOM VALUES FOR LPS331AP SENSOR + * See LPS331AP datasheet: + * http://www2.st.com/resource/en/datasheet/lps331ap.pdf + */ #define ST_PRESS_LPS331AP_WAI_EXP 0xbb #define ST_PRESS_LPS331AP_ODR_ADDR 0x20 #define ST_PRESS_LPS331AP_ODR_MASK 0x70 @@ -71,7 +139,9 @@ #define ST_PRESS_LPS331AP_OD_IRQ_MASK 0x40 #define ST_PRESS_LPS331AP_MULTIREAD_BIT true -/* CUSTOM VALUES FOR LPS001WP SENSOR */ +/* + * CUSTOM VALUES FOR THE OBSOLETE LPS001WP SENSOR + */ /* LPS001WP pressure resolution */ #define ST_PRESS_LPS001WP_LSB_PER_MBAR 16UL @@ -94,7 +164,11 @@ #define ST_PRESS_LPS001WP_OUT_L_ADDR 0x28 #define ST_TEMP_LPS001WP_OUT_L_ADDR 0x2a -/* CUSTOM VALUES FOR LPS25H SENSOR */ +/* + * CUSTOM VALUES FOR LPS25H SENSOR + * See LPS25H datasheet: + * http://www2.st.com/resource/en/datasheet/lps25h.pdf + */ #define ST_PRESS_LPS25H_WAI_EXP 0xbd #define ST_PRESS_LPS25H_ODR_ADDR 0x20 #define ST_PRESS_LPS25H_ODR_MASK 0x70 @@ -117,27 +191,54 @@ #define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28 #define ST_TEMP_LPS25H_OUT_L_ADDR 0x2b +/* + * CUSTOM VALUES FOR LPS22HB SENSOR + * See LPS22HB datasheet: + * http://www2.st.com/resource/en/datasheet/lps22hb.pdf + */ + +/* LPS22HB temperature sensitivity */ +#define ST_PRESS_LPS22HB_LSB_PER_CELSIUS 100UL + +#define ST_PRESS_LPS22HB_WAI_EXP 0xb1 +#define ST_PRESS_LPS22HB_ODR_ADDR 0x10 +#define ST_PRESS_LPS22HB_ODR_MASK 0x70 +#define ST_PRESS_LPS22HB_ODR_AVL_1HZ_VAL 0x01 +#define ST_PRESS_LPS22HB_ODR_AVL_10HZ_VAL 0x02 +#define ST_PRESS_LPS22HB_ODR_AVL_25HZ_VAL 0x03 +#define ST_PRESS_LPS22HB_ODR_AVL_50HZ_VAL 0x04 +#define ST_PRESS_LPS22HB_ODR_AVL_75HZ_VAL 0x05 +#define ST_PRESS_LPS22HB_PW_ADDR 0x10 +#define ST_PRESS_LPS22HB_PW_MASK 0x70 +#define ST_PRESS_LPS22HB_BDU_ADDR 0x10 +#define ST_PRESS_LPS22HB_BDU_MASK 0x02 +#define ST_PRESS_LPS22HB_DRDY_IRQ_ADDR 0x12 +#define ST_PRESS_LPS22HB_DRDY_IRQ_INT1_MASK 0x04 +#define ST_PRESS_LPS22HB_DRDY_IRQ_INT2_MASK 0x08 +#define ST_PRESS_LPS22HB_IHL_IRQ_ADDR 0x12 +#define ST_PRESS_LPS22HB_IHL_IRQ_MASK 0x80 +#define ST_PRESS_LPS22HB_OD_IRQ_ADDR 0x12 +#define ST_PRESS_LPS22HB_OD_IRQ_MASK 0x40 +#define ST_PRESS_LPS22HB_MULTIREAD_BIT true + static const struct iio_chan_spec st_press_1_channels[] = { { .type = IIO_PRESSURE, - .channel2 = IIO_NO_MOD, .address = ST_PRESS_1_OUT_XL_ADDR, - .scan_index = ST_SENSORS_SCAN_X, + .scan_index = 0, .scan_type = { .sign = 'u', .realbits = 24, - .storagebits = 24, + .storagebits = 32, .endianness = IIO_LE, }, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), - .modified = 0, }, { .type = IIO_TEMP, - .channel2 = IIO_NO_MOD, .address = ST_TEMP_1_OUT_L_ADDR, - .scan_index = -1, + .scan_index = 1, .scan_type = { .sign = 'u', .realbits = 16, @@ -148,17 +249,15 @@ static const struct iio_chan_spec st_press_1_channels[] = { BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET), - .modified = 0, }, - IIO_CHAN_SOFT_TIMESTAMP(1) + IIO_CHAN_SOFT_TIMESTAMP(2) }; static const struct iio_chan_spec st_press_lps001wp_channels[] = { { .type = IIO_PRESSURE, - .channel2 = IIO_NO_MOD, .address = ST_PRESS_LPS001WP_OUT_L_ADDR, - .scan_index = ST_SENSORS_SCAN_X, + .scan_index = 0, .scan_type = { .sign = 'u', .realbits = 16, @@ -168,13 +267,11 @@ static const struct iio_chan_spec st_press_lps001wp_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), - .modified = 0, }, { .type = IIO_TEMP, - .channel2 = IIO_NO_MOD, .address = ST_TEMP_LPS001WP_OUT_L_ADDR, - .scan_index = -1, + .scan_index = 1, .scan_type = { .sign = 'u', .realbits = 16, @@ -184,9 +281,42 @@ static const struct iio_chan_spec st_press_lps001wp_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), - .modified = 0, }, - IIO_CHAN_SOFT_TIMESTAMP(1) + IIO_CHAN_SOFT_TIMESTAMP(2) +}; + +static const struct iio_chan_spec st_press_lps22hb_channels[] = { + { + .type = IIO_PRESSURE, + .address = ST_PRESS_1_OUT_XL_ADDR, + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = 24, + .storagebits = 32, + .endianness = IIO_LE, + }, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + }, + { + .type = IIO_TEMP, + .address = ST_TEMP_1_OUT_L_ADDR, + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + }, + IIO_CHAN_SOFT_TIMESTAMP(2) }; static const struct st_sensor_settings st_press_sensors_settings[] = { @@ -346,6 +476,59 @@ static const struct st_sensor_settings st_press_sensors_settings[] = { .multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT, .bootime = 2, }, + { + .wai = ST_PRESS_LPS22HB_WAI_EXP, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LPS22HB_PRESS_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_press_lps22hb_channels, + .num_ch = ARRAY_SIZE(st_press_lps22hb_channels), + .odr = { + .addr = ST_PRESS_LPS22HB_ODR_ADDR, + .mask = ST_PRESS_LPS22HB_ODR_MASK, + .odr_avl = { + { 1, ST_PRESS_LPS22HB_ODR_AVL_1HZ_VAL, }, + { 10, ST_PRESS_LPS22HB_ODR_AVL_10HZ_VAL, }, + { 25, ST_PRESS_LPS22HB_ODR_AVL_25HZ_VAL, }, + { 50, ST_PRESS_LPS22HB_ODR_AVL_50HZ_VAL, }, + { 75, ST_PRESS_LPS22HB_ODR_AVL_75HZ_VAL, }, + }, + }, + .pw = { + .addr = ST_PRESS_LPS22HB_PW_ADDR, + .mask = ST_PRESS_LPS22HB_PW_MASK, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .fs = { + .fs_avl = { + /* + * Pressure and temperature sensitivity values + * as defined in table 3 of LPS22HB datasheet. + */ + [0] = { + .num = ST_PRESS_FS_AVL_1260MB, + .gain = ST_PRESS_KPASCAL_NANO_SCALE, + .gain2 = ST_PRESS_LPS22HB_LSB_PER_CELSIUS, + }, + }, + }, + .bdu = { + .addr = ST_PRESS_LPS22HB_BDU_ADDR, + .mask = ST_PRESS_LPS22HB_BDU_MASK, + }, + .drdy_irq = { + .addr = ST_PRESS_LPS22HB_DRDY_IRQ_ADDR, + .mask_int1 = ST_PRESS_LPS22HB_DRDY_IRQ_INT1_MASK, + .mask_int2 = ST_PRESS_LPS22HB_DRDY_IRQ_INT2_MASK, + .addr_ihl = ST_PRESS_LPS22HB_IHL_IRQ_ADDR, + .mask_ihl = ST_PRESS_LPS22HB_IHL_IRQ_MASK, + .addr_od = ST_PRESS_LPS22HB_OD_IRQ_ADDR, + .mask_od = ST_PRESS_LPS22HB_OD_IRQ_MASK, + .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, + }, + .multi_read_bit = ST_PRESS_LPS22HB_MULTIREAD_BIT, + }, }; static int st_press_write_raw(struct iio_dev *indio_dev, @@ -462,23 +645,30 @@ int st_press_common_probe(struct iio_dev *indio_dev) indio_dev->info = &press_info; mutex_init(&press_data->tb.buf_lock); - st_sensors_power_enable(indio_dev); + err = st_sensors_power_enable(indio_dev); + if (err) + return err; err = st_sensors_check_device_support(indio_dev, ARRAY_SIZE(st_press_sensors_settings), st_press_sensors_settings); if (err < 0) - return err; - - press_data->num_data_channels = ST_PRESS_NUMBER_DATA_CHANNELS; + goto st_press_power_off; + + /* + * Skip timestamping channel while declaring available channels to + * common st_sensor layer. Look at st_sensors_get_buffer_element() to + * see how timestamps are explicitly pushed as last samples block + * element. + */ + press_data->num_data_channels = press_data->sensor_settings->num_ch - 1; press_data->multiread_bit = press_data->sensor_settings->multi_read_bit; indio_dev->channels = press_data->sensor_settings->ch; indio_dev->num_channels = press_data->sensor_settings->num_ch; - if (press_data->sensor_settings->fs.addr != 0) - press_data->current_fullscale = - (struct st_sensor_fullscale_avl *) - &press_data->sensor_settings->fs.fs_avl[0]; + press_data->current_fullscale = + (struct st_sensor_fullscale_avl *) + &press_data->sensor_settings->fs.fs_avl[0]; press_data->odr = press_data->sensor_settings->odr.odr_avl[0].hz; @@ -490,11 +680,11 @@ int st_press_common_probe(struct iio_dev *indio_dev) err = st_sensors_init_sensor(indio_dev, press_data->dev->platform_data); if (err < 0) - return err; + goto st_press_power_off; err = st_press_allocate_ring(indio_dev); if (err < 0) - return err; + goto st_press_power_off; if (irq > 0) { err = st_sensors_allocate_trigger(indio_dev, @@ -517,6 +707,8 @@ st_press_device_register_error: st_sensors_deallocate_trigger(indio_dev); st_press_probe_trigger_error: st_press_deallocate_ring(indio_dev); +st_press_power_off: + st_sensors_power_disable(indio_dev); return err; } diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index 8fcf9766eaec..ed18701c68c9 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -32,6 +32,10 @@ static const struct of_device_id st_press_of_match[] = { .compatible = "st,lps331ap-press", .data = LPS331AP_PRESS_DEV_NAME, }, + { + .compatible = "st,lps22hb-press", + .data = LPS22HB_PRESS_DEV_NAME, + }, {}, }; MODULE_DEVICE_TABLE(of, st_press_of_match); diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c index 40c0692ff1de..550508025af1 100644 --- a/drivers/iio/pressure/st_pressure_spi.c +++ b/drivers/iio/pressure/st_pressure_spi.c @@ -50,6 +50,7 @@ static const struct spi_device_id st_press_id_table[] = { { LPS001WP_PRESS_DEV_NAME }, { LPS25H_PRESS_DEV_NAME }, { LPS331AP_PRESS_DEV_NAME }, + { LPS22HB_PRESS_DEV_NAME }, {}, }; MODULE_DEVICE_TABLE(spi, st_press_id_table); |