* Re: [PATCH 2/3] iio: pressure: bmp280: add per chip initialize function pointer
2016-04-12 5:21 ` [PATCH 2/3] iio: pressure: bmp280: add per chip initialize function pointer Matt Ranostay
@ 2016-04-12 5:17 ` Peter Meerwald-Stadler
0 siblings, 0 replies; 10+ messages in thread
From: Peter Meerwald-Stadler @ 2016-04-12 5:17 UTC (permalink / raw)
To: Matt Ranostay; +Cc: linux-iio, jic23
> Some variants have functions that need to be enabled outside of an core
> chip initialization.
comment below
> Signed-off-by: Matt Ranostay <matt.ranostay@intel.com>
> ---
> drivers/iio/pressure/bmp280.c | 15 +++++++++++++--
> 1 file changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c
> index 2e7cff38f5ff..e80cbf3b21fc 100644
> --- a/drivers/iio/pressure/bmp280.c
> +++ b/drivers/iio/pressure/bmp280.c
> @@ -88,6 +88,9 @@ enum { bmp280, bme280 };
> struct bmp280_chip_info {
> int id;
> int num_channels;
> +
> + /* per chip initialization function */
> + int (*init)(struct bmp280_data *);
> };
>
> static struct bmp280_chip_info bmp280_chip_info_table[] = {
> @@ -336,10 +339,18 @@ static const struct iio_info bmp280_info = {
> .read_raw = &bmp280_read_raw,
> };
>
> -static int bmp280_chip_init(struct bmp280_data *data)
> +static int bmp280_common_init(struct bmp280_data *data)
> {
> int ret;
>
> + if (data->chip->init) {
> + ret = data->chip->init(data);
> + if (ret < 0) {
> + dev_err(&data->client->dev, "failed to run chip init");
should have \n I think
> + return ret;
> + }
> + }
> +
> ret = regmap_update_bits(data->regmap, BMP280_REG_CTRL_MEAS,
> BMP280_OSRS_TEMP_MASK |
> BMP280_OSRS_PRESS_MASK |
> @@ -429,7 +440,7 @@ static int bmp280_probe(struct i2c_client *client,
> return -EINVAL;
> }
>
> - ret = bmp280_chip_init(data);
> + ret = bmp280_common_init(data);
> if (ret < 0)
> return ret;
>
>
--
Peter Meerwald-Stadler
+43-664-2444418 (mobile)
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 0/3] iio: pressure: bmp280: add BME280 part support
@ 2016-04-12 5:21 Matt Ranostay
2016-04-12 5:21 ` [PATCH 1/3] iio: pressure: bmp280: add initial support for multiple chips Matt Ranostay
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Matt Ranostay @ 2016-04-12 5:21 UTC (permalink / raw)
To: linux-iio; +Cc: jic23, Matt Ranostay
Add functionality to allow multiple parts to be selected via ACPI or DT
properties; also allows per chip info and initialiation.
Add BME280 device and relative humidity reading functionality.
Matt Ranostay (3):
iio: pressure: bmp280: add initial support for multiple chips
iio: pressure: bmp280: add per chip initialize function pointer
iio: pressure: bmp280: add humidity support
drivers/iio/pressure/bmp280.c | 209 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 199 insertions(+), 10 deletions(-)
--
1.9.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/3] iio: pressure: bmp280: add initial support for multiple chips
2016-04-12 5:21 [PATCH 0/3] iio: pressure: bmp280: add BME280 part support Matt Ranostay
@ 2016-04-12 5:21 ` Matt Ranostay
2016-04-12 5:23 ` Peter Meerwald-Stadler
2016-04-12 5:21 ` [PATCH 2/3] iio: pressure: bmp280: add per chip initialize function pointer Matt Ranostay
2016-04-12 5:21 ` [PATCH 3/3] iio: pressure: bmp280: add humidity support Matt Ranostay
2 siblings, 1 reply; 10+ messages in thread
From: Matt Ranostay @ 2016-04-12 5:21 UTC (permalink / raw)
To: linux-iio; +Cc: jic23, Matt Ranostay
Bosch has several chipsets that use BMP280 as core features, this enables
chip information for each variant.
Signed-off-by: Matt Ranostay <matt.ranostay@intel.com>
---
drivers/iio/pressure/bmp280.c | 59 +++++++++++++++++++++++++++++++++++++++----
1 file changed, 54 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c
index a2602d8dd6d5..2e7cff38f5ff 100644
--- a/drivers/iio/pressure/bmp280.c
+++ b/drivers/iio/pressure/bmp280.c
@@ -66,12 +66,15 @@
#define BMP280_MODE_NORMAL (BIT(1) | BIT(0))
#define BMP280_CHIP_ID 0x58
+#define BME280_CHIP_ID 0x60
+
#define BMP280_SOFT_RESET_VAL 0xB6
struct bmp280_data {
struct i2c_client *client;
struct mutex lock;
struct regmap *regmap;
+ struct bmp280_chip_info *chip;
/*
* Carryover value from temperature conversion, used in pressure
@@ -80,6 +83,24 @@ struct bmp280_data {
s32 t_fine;
};
+enum { bmp280, bme280 };
+
+struct bmp280_chip_info {
+ int id;
+ int num_channels;
+};
+
+static struct bmp280_chip_info bmp280_chip_info_table[] = {
+ [bmp280] = {
+ .id = BMP280_CHIP_ID,
+ .num_channels = 2,
+ },
+ [bme280] = {
+ .id = BME280_CHIP_ID,
+ .num_channels = 2,
+ },
+};
+
/*
* These enums are used for indexing into the array of compensation
* parameters.
@@ -344,6 +365,20 @@ static int bmp280_chip_init(struct bmp280_data *data)
return ret;
}
+static int bmp280_match_acpi_device(struct device *dev,
+ struct bmp280_chip_info **chipset)
+{
+ const struct acpi_device_id *id;
+
+ id = acpi_match_device(dev->driver->acpi_match_table, dev);
+ if (!id)
+ return -ENODEV;
+
+ *chipset = &bmp280_chip_info_table[id->driver_data];
+
+ return 0;
+}
+
static int bmp280_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -357,13 +392,25 @@ static int bmp280_probe(struct i2c_client *client,
return -ENOMEM;
data = iio_priv(indio_dev);
+
+ if (id) {
+ data->chip = &bmp280_chip_info_table[id->driver_data];
+ } else if (ACPI_HANDLE(&client->dev)) {
+ ret = bmp280_match_acpi_device(&client->dev, &data->chip);
+ if (ret < 0)
+ return ret;
+ } else {
+ /* Don't break sysfs registration of BMP280 devices */
+ data->chip = &bmp280_chip_info_table[bmp280];
+ }
+
mutex_init(&data->lock);
data->client = client;
indio_dev->dev.parent = &client->dev;
indio_dev->name = id->name;
indio_dev->channels = bmp280_channels;
- indio_dev->num_channels = ARRAY_SIZE(bmp280_channels);
+ indio_dev->num_channels = data->chip->num_channels;
indio_dev->info = &bmp280_info;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -376,9 +423,9 @@ static int bmp280_probe(struct i2c_client *client,
ret = regmap_read(data->regmap, BMP280_REG_ID, &chip_id);
if (ret < 0)
return ret;
- if (chip_id != BMP280_CHIP_ID) {
+ if (chip_id != data->chip->id) {
dev_err(&client->dev, "bad chip id. expected %x got %x\n",
- BMP280_CHIP_ID, chip_id);
+ data->chip->id, chip_id);
return -EINVAL;
}
@@ -390,13 +437,15 @@ static int bmp280_probe(struct i2c_client *client,
}
static const struct acpi_device_id bmp280_acpi_match[] = {
- {"BMP0280", 0},
+ {"BMP0280", bmp280},
+ {"BME0280", bme280},
{ },
};
MODULE_DEVICE_TABLE(acpi, bmp280_acpi_match);
static const struct i2c_device_id bmp280_id[] = {
- {"bmp280", 0},
+ {"bmp280", bmp280},
+ {"bme280", bme280},
{ },
};
MODULE_DEVICE_TABLE(i2c, bmp280_id);
--
1.9.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/3] iio: pressure: bmp280: add per chip initialize function pointer
2016-04-12 5:21 [PATCH 0/3] iio: pressure: bmp280: add BME280 part support Matt Ranostay
2016-04-12 5:21 ` [PATCH 1/3] iio: pressure: bmp280: add initial support for multiple chips Matt Ranostay
@ 2016-04-12 5:21 ` Matt Ranostay
2016-04-12 5:17 ` Peter Meerwald-Stadler
2016-04-12 5:21 ` [PATCH 3/3] iio: pressure: bmp280: add humidity support Matt Ranostay
2 siblings, 1 reply; 10+ messages in thread
From: Matt Ranostay @ 2016-04-12 5:21 UTC (permalink / raw)
To: linux-iio; +Cc: jic23, Matt Ranostay
Some variants have functions that need to be enabled outside of an core
chip initialization.
Signed-off-by: Matt Ranostay <matt.ranostay@intel.com>
---
drivers/iio/pressure/bmp280.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c
index 2e7cff38f5ff..e80cbf3b21fc 100644
--- a/drivers/iio/pressure/bmp280.c
+++ b/drivers/iio/pressure/bmp280.c
@@ -88,6 +88,9 @@ enum { bmp280, bme280 };
struct bmp280_chip_info {
int id;
int num_channels;
+
+ /* per chip initialization function */
+ int (*init)(struct bmp280_data *);
};
static struct bmp280_chip_info bmp280_chip_info_table[] = {
@@ -336,10 +339,18 @@ static const struct iio_info bmp280_info = {
.read_raw = &bmp280_read_raw,
};
-static int bmp280_chip_init(struct bmp280_data *data)
+static int bmp280_common_init(struct bmp280_data *data)
{
int ret;
+ if (data->chip->init) {
+ ret = data->chip->init(data);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "failed to run chip init");
+ return ret;
+ }
+ }
+
ret = regmap_update_bits(data->regmap, BMP280_REG_CTRL_MEAS,
BMP280_OSRS_TEMP_MASK |
BMP280_OSRS_PRESS_MASK |
@@ -429,7 +440,7 @@ static int bmp280_probe(struct i2c_client *client,
return -EINVAL;
}
- ret = bmp280_chip_init(data);
+ ret = bmp280_common_init(data);
if (ret < 0)
return ret;
--
1.9.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/3] iio: pressure: bmp280: add humidity support
2016-04-12 5:21 [PATCH 0/3] iio: pressure: bmp280: add BME280 part support Matt Ranostay
2016-04-12 5:21 ` [PATCH 1/3] iio: pressure: bmp280: add initial support for multiple chips Matt Ranostay
2016-04-12 5:21 ` [PATCH 2/3] iio: pressure: bmp280: add per chip initialize function pointer Matt Ranostay
@ 2016-04-12 5:21 ` Matt Ranostay
2016-04-12 5:21 ` Peter Meerwald-Stadler
2 siblings, 1 reply; 10+ messages in thread
From: Matt Ranostay @ 2016-04-12 5:21 UTC (permalink / raw)
To: linux-iio; +Cc: jic23, Matt Ranostay
Enable humidity support for the BME280 part
Signed-off-by: Matt Ranostay <matt.ranostay@intel.com>
---
drivers/iio/pressure/bmp280.c | 137 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 133 insertions(+), 4 deletions(-)
diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c
index e80cbf3b21fc..9e3a9f00cd84 100644
--- a/drivers/iio/pressure/bmp280.c
+++ b/drivers/iio/pressure/bmp280.c
@@ -18,6 +18,8 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#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
@@ -26,11 +28,20 @@
#define BMP280_REG_PRESS_MSB 0xF7
#define BMP280_REG_CONFIG 0xF5
+#define BMP280_REG_CTRL_HUMIDITY 0xF2
#define BMP280_REG_CTRL_MEAS 0xF4
#define BMP280_REG_STATUS 0xF3
#define BMP280_REG_RESET 0xE0
#define BMP280_REG_ID 0xD0
+/* 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
@@ -44,6 +55,14 @@
#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_HUMIDITY_SKIP 0
+#define BMP280_OSRS_HUMIDITY_1X BIT(0)
+#define BMP280_OSRS_HUMIDITY_2X BIT(1)
+#define BMP280_OSRS_HUMIDITY_4X (BIT(1) | BIT(0))
+#define BMP280_OSRS_HUMIDITY_8X BIT(2)
+#define BMP280_OSRS_HUMIDITY_16X (BIT(2) | BIT(0))
+
#define BMP280_OSRS_TEMP_MASK (BIT(7) | BIT(6) | BIT(5))
#define BMP280_OSRS_TEMP_SKIP 0
#define BMP280_OSRS_TEMP_1X BIT(5)
@@ -93,6 +112,13 @@ struct bmp280_chip_info {
int (*init)(struct bmp280_data *);
};
+static int bme280_chip_init(struct bmp280_data *data)
+{
+ return regmap_update_bits(data->regmap, BMP280_REG_CTRL_HUMIDITY,
+ BMP280_OSRS_HUMIDITY_MASK,
+ BMP280_OSRS_HUMIDITY_16X);
+}
+
static struct bmp280_chip_info bmp280_chip_info_table[] = {
[bmp280] = {
.id = BMP280_CHIP_ID,
@@ -100,7 +126,8 @@ static struct bmp280_chip_info bmp280_chip_info_table[] = {
},
[bme280] = {
.id = BME280_CHIP_ID,
- .num_channels = 2,
+ .num_channels = 3,
+ .init = bme280_chip_init,
},
};
@@ -120,12 +147,17 @@ static const struct iio_chan_spec bmp280_channels[] = {
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
},
+ {
+ .type = IIO_HUMIDITYRELATIVE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ },
};
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;
@@ -137,6 +169,8 @@ static bool bmp280_is_writeable_reg(struct device *dev, unsigned int reg)
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:
@@ -154,7 +188,7 @@ static const struct regmap_config bmp280_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
- .max_register = BMP280_REG_TEMP_XLSB,
+ .max_register = BMP280_REG_HUMIDITY_LSB,
.cache_type = REGCACHE_RBTREE,
.writeable_reg = bmp280_is_writeable_reg,
@@ -162,11 +196,74 @@ static const struct regmap_config bmp280_regmap_config = {
};
/*
+ * 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 u32 bmp280_compensate_humidity(struct bmp280_data *data,
+ s32 adc_humidity)
+{
+ struct device *dev = &data->client->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;
+ }
+
+ 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(le16_to_cpu(tmp) >> 4 | (le16_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) & 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);
+
+ 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;
+
+ return var >> 12;
+};
+
+/*
* Returns temperature in DegC, resolution is 0.01 DegC. Output value of
* "5123" equals 51.23 DegC. t_fine carries fine temperature as global
* value.
*
- * Taken from datasheet, Section 3.11.3, "Compensation formula".
+ * Taken from BMP280 datasheet, Section 3.11.3, "Compensation formula".
*/
static s32 bmp280_compensate_temp(struct bmp280_data *data,
s32 adc_temp)
@@ -206,7 +303,7 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data,
* integer bits and 8 fractional bits). Output value of "24674867"
* represents 24674867/256 = 96386.2 Pa = 963.862 hPa
*
- * Taken from datasheet, Section 3.11.3, "Compensation formula".
+ * Taken from BMP280 datasheet, Section 3.11.3, "Compensation formula".
*/
static u32 bmp280_compensate_press(struct bmp280_data *data,
s32 adc_press)
@@ -301,6 +398,35 @@ static int bmp280_read_press(struct bmp280_data *data,
return IIO_VAL_FRACTIONAL;
}
+static int bmp280_read_humidity(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_PRESS_MSB,
+ (u8 *) &tmp, 2);
+ if (ret < 0) {
+ dev_err(&data->client->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)
@@ -313,6 +439,9 @@ static int bmp280_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
switch (chan->type) {
+ case IIO_HUMIDITYRELATIVE:
+ ret = bmp280_read_humidity(data, val, val2);
+ break;
case IIO_PRESSURE:
ret = bmp280_read_press(data, val, val2);
break;
--
1.9.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 3/3] iio: pressure: bmp280: add humidity support
2016-04-12 5:21 ` [PATCH 3/3] iio: pressure: bmp280: add humidity support Matt Ranostay
@ 2016-04-12 5:21 ` Peter Meerwald-Stadler
2016-04-12 5:42 ` Matt Ranostay
0 siblings, 1 reply; 10+ messages in thread
From: Peter Meerwald-Stadler @ 2016-04-12 5:21 UTC (permalink / raw)
To: Matt Ranostay; +Cc: linux-iio, jic23
> Enable humidity support for the BME280 part
this also changes unrelated comments referring to datasheets
does this chip really use both, LE (in _compensate_humidity) and BE in
(read_humidity)?
> Signed-off-by: Matt Ranostay <matt.ranostay@intel.com>
> ---
> drivers/iio/pressure/bmp280.c | 137 ++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 133 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c
> index e80cbf3b21fc..9e3a9f00cd84 100644
> --- a/drivers/iio/pressure/bmp280.c
> +++ b/drivers/iio/pressure/bmp280.c
> @@ -18,6 +18,8 @@
> #include <linux/iio/iio.h>
> #include <linux/iio/sysfs.h>
>
> +#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
> @@ -26,11 +28,20 @@
> #define BMP280_REG_PRESS_MSB 0xF7
>
> #define BMP280_REG_CONFIG 0xF5
> +#define BMP280_REG_CTRL_HUMIDITY 0xF2
> #define BMP280_REG_CTRL_MEAS 0xF4
> #define BMP280_REG_STATUS 0xF3
> #define BMP280_REG_RESET 0xE0
> #define BMP280_REG_ID 0xD0
>
> +/* 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
>
> @@ -44,6 +55,14 @@
> #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_HUMIDITY_SKIP 0
> +#define BMP280_OSRS_HUMIDITY_1X BIT(0)
> +#define BMP280_OSRS_HUMIDITY_2X BIT(1)
> +#define BMP280_OSRS_HUMIDITY_4X (BIT(1) | BIT(0))
> +#define BMP280_OSRS_HUMIDITY_8X BIT(2)
> +#define BMP280_OSRS_HUMIDITY_16X (BIT(2) | BIT(0))
> +
> #define BMP280_OSRS_TEMP_MASK (BIT(7) | BIT(6) | BIT(5))
> #define BMP280_OSRS_TEMP_SKIP 0
> #define BMP280_OSRS_TEMP_1X BIT(5)
> @@ -93,6 +112,13 @@ struct bmp280_chip_info {
> int (*init)(struct bmp280_data *);
> };
>
> +static int bme280_chip_init(struct bmp280_data *data)
> +{
> + return regmap_update_bits(data->regmap, BMP280_REG_CTRL_HUMIDITY,
> + BMP280_OSRS_HUMIDITY_MASK,
> + BMP280_OSRS_HUMIDITY_16X);
> +}
> +
> static struct bmp280_chip_info bmp280_chip_info_table[] = {
> [bmp280] = {
> .id = BMP280_CHIP_ID,
> @@ -100,7 +126,8 @@ static struct bmp280_chip_info bmp280_chip_info_table[] = {
> },
> [bme280] = {
> .id = BME280_CHIP_ID,
> - .num_channels = 2,
> + .num_channels = 3,
> + .init = bme280_chip_init,
> },
> };
>
> @@ -120,12 +147,17 @@ static const struct iio_chan_spec bmp280_channels[] = {
> .type = IIO_TEMP,
> .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
> },
> + {
> + .type = IIO_HUMIDITYRELATIVE,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
> + },
> };
>
> 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;
> @@ -137,6 +169,8 @@ static bool bmp280_is_writeable_reg(struct device *dev, unsigned int reg)
> 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:
> @@ -154,7 +188,7 @@ static const struct regmap_config bmp280_regmap_config = {
> .reg_bits = 8,
> .val_bits = 8,
>
> - .max_register = BMP280_REG_TEMP_XLSB,
> + .max_register = BMP280_REG_HUMIDITY_LSB,
> .cache_type = REGCACHE_RBTREE,
>
> .writeable_reg = bmp280_is_writeable_reg,
> @@ -162,11 +196,74 @@ static const struct regmap_config bmp280_regmap_config = {
> };
>
> /*
> + * 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 u32 bmp280_compensate_humidity(struct bmp280_data *data,
> + s32 adc_humidity)
> +{
> + struct device *dev = &data->client->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;
> + }
> +
> + 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(le16_to_cpu(tmp) >> 4 | (le16_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) & 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);
> +
> + 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;
> +
> + return var >> 12;
> +};
> +
> +/*
> * Returns temperature in DegC, resolution is 0.01 DegC. Output value of
> * "5123" equals 51.23 DegC. t_fine carries fine temperature as global
> * value.
> *
> - * Taken from datasheet, Section 3.11.3, "Compensation formula".
> + * Taken from BMP280 datasheet, Section 3.11.3, "Compensation formula".
> */
> static s32 bmp280_compensate_temp(struct bmp280_data *data,
> s32 adc_temp)
> @@ -206,7 +303,7 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data,
> * integer bits and 8 fractional bits). Output value of "24674867"
> * represents 24674867/256 = 96386.2 Pa = 963.862 hPa
> *
> - * Taken from datasheet, Section 3.11.3, "Compensation formula".
> + * Taken from BMP280 datasheet, Section 3.11.3, "Compensation formula".
> */
> static u32 bmp280_compensate_press(struct bmp280_data *data,
> s32 adc_press)
> @@ -301,6 +398,35 @@ static int bmp280_read_press(struct bmp280_data *data,
> return IIO_VAL_FRACTIONAL;
> }
>
> +static int bmp280_read_humidity(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_PRESS_MSB,
> + (u8 *) &tmp, 2);
> + if (ret < 0) {
> + dev_err(&data->client->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)
> @@ -313,6 +439,9 @@ static int bmp280_read_raw(struct iio_dev *indio_dev,
> switch (mask) {
> case IIO_CHAN_INFO_PROCESSED:
> switch (chan->type) {
> + case IIO_HUMIDITYRELATIVE:
> + ret = bmp280_read_humidity(data, val, val2);
> + break;
> case IIO_PRESSURE:
> ret = bmp280_read_press(data, val, val2);
> break;
>
--
Peter Meerwald-Stadler
+43-664-2444418 (mobile)
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/3] iio: pressure: bmp280: add initial support for multiple chips
2016-04-12 5:21 ` [PATCH 1/3] iio: pressure: bmp280: add initial support for multiple chips Matt Ranostay
@ 2016-04-12 5:23 ` Peter Meerwald-Stadler
2016-04-12 5:27 ` Matt Ranostay
0 siblings, 1 reply; 10+ messages in thread
From: Peter Meerwald-Stadler @ 2016-04-12 5:23 UTC (permalink / raw)
To: Matt Ranostay; +Cc: linux-iio, jic23
> Bosch has several chipsets that use BMP280 as core features, this enables
> chip information for each variant.
these patches clash with work to add BMP180 to the same driver, Akinobu
Mita was first :)
> Signed-off-by: Matt Ranostay <matt.ranostay@intel.com>
> ---
> drivers/iio/pressure/bmp280.c | 59 +++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 54 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c
> index a2602d8dd6d5..2e7cff38f5ff 100644
> --- a/drivers/iio/pressure/bmp280.c
> +++ b/drivers/iio/pressure/bmp280.c
> @@ -66,12 +66,15 @@
> #define BMP280_MODE_NORMAL (BIT(1) | BIT(0))
>
> #define BMP280_CHIP_ID 0x58
> +#define BME280_CHIP_ID 0x60
> +
> #define BMP280_SOFT_RESET_VAL 0xB6
>
> struct bmp280_data {
> struct i2c_client *client;
> struct mutex lock;
> struct regmap *regmap;
> + struct bmp280_chip_info *chip;
>
> /*
> * Carryover value from temperature conversion, used in pressure
> @@ -80,6 +83,24 @@ struct bmp280_data {
> s32 t_fine;
> };
>
> +enum { bmp280, bme280 };
> +
> +struct bmp280_chip_info {
> + int id;
> + int num_channels;
> +};
> +
> +static struct bmp280_chip_info bmp280_chip_info_table[] = {
> + [bmp280] = {
> + .id = BMP280_CHIP_ID,
> + .num_channels = 2,
> + },
> + [bme280] = {
> + .id = BME280_CHIP_ID,
> + .num_channels = 2,
> + },
> +};
> +
> /*
> * These enums are used for indexing into the array of compensation
> * parameters.
> @@ -344,6 +365,20 @@ static int bmp280_chip_init(struct bmp280_data *data)
> return ret;
> }
>
> +static int bmp280_match_acpi_device(struct device *dev,
> + struct bmp280_chip_info **chipset)
> +{
> + const struct acpi_device_id *id;
> +
> + id = acpi_match_device(dev->driver->acpi_match_table, dev);
> + if (!id)
> + return -ENODEV;
> +
> + *chipset = &bmp280_chip_info_table[id->driver_data];
> +
> + return 0;
> +}
> +
> static int bmp280_probe(struct i2c_client *client,
> const struct i2c_device_id *id)
> {
> @@ -357,13 +392,25 @@ static int bmp280_probe(struct i2c_client *client,
> return -ENOMEM;
>
> data = iio_priv(indio_dev);
> +
> + if (id) {
> + data->chip = &bmp280_chip_info_table[id->driver_data];
> + } else if (ACPI_HANDLE(&client->dev)) {
> + ret = bmp280_match_acpi_device(&client->dev, &data->chip);
> + if (ret < 0)
> + return ret;
> + } else {
> + /* Don't break sysfs registration of BMP280 devices */
> + data->chip = &bmp280_chip_info_table[bmp280];
> + }
> +
> mutex_init(&data->lock);
> data->client = client;
>
> indio_dev->dev.parent = &client->dev;
> indio_dev->name = id->name;
> indio_dev->channels = bmp280_channels;
> - indio_dev->num_channels = ARRAY_SIZE(bmp280_channels);
> + indio_dev->num_channels = data->chip->num_channels;
> indio_dev->info = &bmp280_info;
> indio_dev->modes = INDIO_DIRECT_MODE;
>
> @@ -376,9 +423,9 @@ static int bmp280_probe(struct i2c_client *client,
> ret = regmap_read(data->regmap, BMP280_REG_ID, &chip_id);
> if (ret < 0)
> return ret;
> - if (chip_id != BMP280_CHIP_ID) {
> + if (chip_id != data->chip->id) {
> dev_err(&client->dev, "bad chip id. expected %x got %x\n",
> - BMP280_CHIP_ID, chip_id);
> + data->chip->id, chip_id);
> return -EINVAL;
> }
>
> @@ -390,13 +437,15 @@ static int bmp280_probe(struct i2c_client *client,
> }
>
> static const struct acpi_device_id bmp280_acpi_match[] = {
> - {"BMP0280", 0},
> + {"BMP0280", bmp280},
> + {"BME0280", bme280},
> { },
> };
> MODULE_DEVICE_TABLE(acpi, bmp280_acpi_match);
>
> static const struct i2c_device_id bmp280_id[] = {
> - {"bmp280", 0},
> + {"bmp280", bmp280},
> + {"bme280", bme280},
> { },
> };
> MODULE_DEVICE_TABLE(i2c, bmp280_id);
>
--
Peter Meerwald-Stadler
+43-664-2444418 (mobile)
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/3] iio: pressure: bmp280: add initial support for multiple chips
2016-04-12 5:23 ` Peter Meerwald-Stadler
@ 2016-04-12 5:27 ` Matt Ranostay
2016-04-17 11:51 ` Jonathan Cameron
0 siblings, 1 reply; 10+ messages in thread
From: Matt Ranostay @ 2016-04-12 5:27 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Matt Ranostay, linux-iio, Jonathan Cameron
Ah noticed that just now... ironically I was thinking about submitting
this last night :)
On Mon, Apr 11, 2016 at 10:23 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
>
>> Bosch has several chipsets that use BMP280 as core features, this enables
>> chip information for each variant.
>
> these patches clash with work to add BMP180 to the same driver, Akinobu
> Mita was first :)
>
>> Signed-off-by: Matt Ranostay <matt.ranostay@intel.com>
>> ---
>> drivers/iio/pressure/bmp280.c | 59 +++++++++++++++++++++++++++++++++++++++----
>> 1 file changed, 54 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c
>> index a2602d8dd6d5..2e7cff38f5ff 100644
>> --- a/drivers/iio/pressure/bmp280.c
>> +++ b/drivers/iio/pressure/bmp280.c
>> @@ -66,12 +66,15 @@
>> #define BMP280_MODE_NORMAL (BIT(1) | BIT(0))
>>
>> #define BMP280_CHIP_ID 0x58
>> +#define BME280_CHIP_ID 0x60
>> +
>> #define BMP280_SOFT_RESET_VAL 0xB6
>>
>> struct bmp280_data {
>> struct i2c_client *client;
>> struct mutex lock;
>> struct regmap *regmap;
>> + struct bmp280_chip_info *chip;
>>
>> /*
>> * Carryover value from temperature conversion, used in pressure
>> @@ -80,6 +83,24 @@ struct bmp280_data {
>> s32 t_fine;
>> };
>>
>> +enum { bmp280, bme280 };
>> +
>> +struct bmp280_chip_info {
>> + int id;
>> + int num_channels;
>> +};
>> +
>> +static struct bmp280_chip_info bmp280_chip_info_table[] = {
>> + [bmp280] = {
>> + .id = BMP280_CHIP_ID,
>> + .num_channels = 2,
>> + },
>> + [bme280] = {
>> + .id = BME280_CHIP_ID,
>> + .num_channels = 2,
>> + },
>> +};
>> +
>> /*
>> * These enums are used for indexing into the array of compensation
>> * parameters.
>> @@ -344,6 +365,20 @@ static int bmp280_chip_init(struct bmp280_data *data)
>> return ret;
>> }
>>
>> +static int bmp280_match_acpi_device(struct device *dev,
>> + struct bmp280_chip_info **chipset)
>> +{
>> + const struct acpi_device_id *id;
>> +
>> + id = acpi_match_device(dev->driver->acpi_match_table, dev);
>> + if (!id)
>> + return -ENODEV;
>> +
>> + *chipset = &bmp280_chip_info_table[id->driver_data];
>> +
>> + return 0;
>> +}
>> +
>> static int bmp280_probe(struct i2c_client *client,
>> const struct i2c_device_id *id)
>> {
>> @@ -357,13 +392,25 @@ static int bmp280_probe(struct i2c_client *client,
>> return -ENOMEM;
>>
>> data = iio_priv(indio_dev);
>> +
>> + if (id) {
>> + data->chip = &bmp280_chip_info_table[id->driver_data];
>> + } else if (ACPI_HANDLE(&client->dev)) {
>> + ret = bmp280_match_acpi_device(&client->dev, &data->chip);
>> + if (ret < 0)
>> + return ret;
>> + } else {
>> + /* Don't break sysfs registration of BMP280 devices */
>> + data->chip = &bmp280_chip_info_table[bmp280];
>> + }
>> +
>> mutex_init(&data->lock);
>> data->client = client;
>>
>> indio_dev->dev.parent = &client->dev;
>> indio_dev->name = id->name;
>> indio_dev->channels = bmp280_channels;
>> - indio_dev->num_channels = ARRAY_SIZE(bmp280_channels);
>> + indio_dev->num_channels = data->chip->num_channels;
>> indio_dev->info = &bmp280_info;
>> indio_dev->modes = INDIO_DIRECT_MODE;
>>
>> @@ -376,9 +423,9 @@ static int bmp280_probe(struct i2c_client *client,
>> ret = regmap_read(data->regmap, BMP280_REG_ID, &chip_id);
>> if (ret < 0)
>> return ret;
>> - if (chip_id != BMP280_CHIP_ID) {
>> + if (chip_id != data->chip->id) {
>> dev_err(&client->dev, "bad chip id. expected %x got %x\n",
>> - BMP280_CHIP_ID, chip_id);
>> + data->chip->id, chip_id);
>> return -EINVAL;
>> }
>>
>> @@ -390,13 +437,15 @@ static int bmp280_probe(struct i2c_client *client,
>> }
>>
>> static const struct acpi_device_id bmp280_acpi_match[] = {
>> - {"BMP0280", 0},
>> + {"BMP0280", bmp280},
>> + {"BME0280", bme280},
>> { },
>> };
>> MODULE_DEVICE_TABLE(acpi, bmp280_acpi_match);
>>
>> static const struct i2c_device_id bmp280_id[] = {
>> - {"bmp280", 0},
>> + {"bmp280", bmp280},
>> + {"bme280", bme280},
>> { },
>> };
>> MODULE_DEVICE_TABLE(i2c, bmp280_id);
>>
>
> --
>
> Peter Meerwald-Stadler
> +43-664-2444418 (mobile)
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 3/3] iio: pressure: bmp280: add humidity support
2016-04-12 5:21 ` Peter Meerwald-Stadler
@ 2016-04-12 5:42 ` Matt Ranostay
0 siblings, 0 replies; 10+ messages in thread
From: Matt Ranostay @ 2016-04-12 5:42 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Matt Ranostay, linux-iio, Jonathan Cameron
On Mon, Apr 11, 2016 at 10:21 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
>
>> Enable humidity support for the BME280 part
>
> this also changes unrelated comments referring to datasheets
>
> does this chip really use both, LE (in _compensate_humidity) and BE in
> (read_humidity)?
>
Yeah didn't notice that till now.. and went back to BME280 datasheet
and that appears to be the case.
If you look at bmp280_compensate_temp and bmp280_compensate_press it
does the same exact thing...
>> Signed-off-by: Matt Ranostay <matt.ranostay@intel.com>
>> ---
>> drivers/iio/pressure/bmp280.c | 137 ++++++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 133 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c
>> index e80cbf3b21fc..9e3a9f00cd84 100644
>> --- a/drivers/iio/pressure/bmp280.c
>> +++ b/drivers/iio/pressure/bmp280.c
>> @@ -18,6 +18,8 @@
>> #include <linux/iio/iio.h>
>> #include <linux/iio/sysfs.h>
>>
>> +#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
>> @@ -26,11 +28,20 @@
>> #define BMP280_REG_PRESS_MSB 0xF7
>>
>> #define BMP280_REG_CONFIG 0xF5
>> +#define BMP280_REG_CTRL_HUMIDITY 0xF2
>> #define BMP280_REG_CTRL_MEAS 0xF4
>> #define BMP280_REG_STATUS 0xF3
>> #define BMP280_REG_RESET 0xE0
>> #define BMP280_REG_ID 0xD0
>>
>> +/* 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
>>
>> @@ -44,6 +55,14 @@
>> #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_HUMIDITY_SKIP 0
>> +#define BMP280_OSRS_HUMIDITY_1X BIT(0)
>> +#define BMP280_OSRS_HUMIDITY_2X BIT(1)
>> +#define BMP280_OSRS_HUMIDITY_4X (BIT(1) | BIT(0))
>> +#define BMP280_OSRS_HUMIDITY_8X BIT(2)
>> +#define BMP280_OSRS_HUMIDITY_16X (BIT(2) | BIT(0))
>> +
>> #define BMP280_OSRS_TEMP_MASK (BIT(7) | BIT(6) | BIT(5))
>> #define BMP280_OSRS_TEMP_SKIP 0
>> #define BMP280_OSRS_TEMP_1X BIT(5)
>> @@ -93,6 +112,13 @@ struct bmp280_chip_info {
>> int (*init)(struct bmp280_data *);
>> };
>>
>> +static int bme280_chip_init(struct bmp280_data *data)
>> +{
>> + return regmap_update_bits(data->regmap, BMP280_REG_CTRL_HUMIDITY,
>> + BMP280_OSRS_HUMIDITY_MASK,
>> + BMP280_OSRS_HUMIDITY_16X);
>> +}
>> +
>> static struct bmp280_chip_info bmp280_chip_info_table[] = {
>> [bmp280] = {
>> .id = BMP280_CHIP_ID,
>> @@ -100,7 +126,8 @@ static struct bmp280_chip_info bmp280_chip_info_table[] = {
>> },
>> [bme280] = {
>> .id = BME280_CHIP_ID,
>> - .num_channels = 2,
>> + .num_channels = 3,
>> + .init = bme280_chip_init,
>> },
>> };
>>
>> @@ -120,12 +147,17 @@ static const struct iio_chan_spec bmp280_channels[] = {
>> .type = IIO_TEMP,
>> .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
>> },
>> + {
>> + .type = IIO_HUMIDITYRELATIVE,
>> + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
>> + },
>> };
>>
>> 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;
>> @@ -137,6 +169,8 @@ static bool bmp280_is_writeable_reg(struct device *dev, unsigned int reg)
>> 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:
>> @@ -154,7 +188,7 @@ static const struct regmap_config bmp280_regmap_config = {
>> .reg_bits = 8,
>> .val_bits = 8,
>>
>> - .max_register = BMP280_REG_TEMP_XLSB,
>> + .max_register = BMP280_REG_HUMIDITY_LSB,
>> .cache_type = REGCACHE_RBTREE,
>>
>> .writeable_reg = bmp280_is_writeable_reg,
>> @@ -162,11 +196,74 @@ static const struct regmap_config bmp280_regmap_config = {
>> };
>>
>> /*
>> + * 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 u32 bmp280_compensate_humidity(struct bmp280_data *data,
>> + s32 adc_humidity)
>> +{
>> + struct device *dev = &data->client->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;
>> + }
>> +
>> + 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(le16_to_cpu(tmp) >> 4 | (le16_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) & 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);
>> +
>> + 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;
>> +
>> + return var >> 12;
>> +};
>> +
>> +/*
>> * Returns temperature in DegC, resolution is 0.01 DegC. Output value of
>> * "5123" equals 51.23 DegC. t_fine carries fine temperature as global
>> * value.
>> *
>> - * Taken from datasheet, Section 3.11.3, "Compensation formula".
>> + * Taken from BMP280 datasheet, Section 3.11.3, "Compensation formula".
>> */
>> static s32 bmp280_compensate_temp(struct bmp280_data *data,
>> s32 adc_temp)
>> @@ -206,7 +303,7 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data,
>> * integer bits and 8 fractional bits). Output value of "24674867"
>> * represents 24674867/256 = 96386.2 Pa = 963.862 hPa
>> *
>> - * Taken from datasheet, Section 3.11.3, "Compensation formula".
>> + * Taken from BMP280 datasheet, Section 3.11.3, "Compensation formula".
>> */
>> static u32 bmp280_compensate_press(struct bmp280_data *data,
>> s32 adc_press)
>> @@ -301,6 +398,35 @@ static int bmp280_read_press(struct bmp280_data *data,
>> return IIO_VAL_FRACTIONAL;
>> }
>>
>> +static int bmp280_read_humidity(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_PRESS_MSB,
>> + (u8 *) &tmp, 2);
>> + if (ret < 0) {
>> + dev_err(&data->client->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)
>> @@ -313,6 +439,9 @@ static int bmp280_read_raw(struct iio_dev *indio_dev,
>> switch (mask) {
>> case IIO_CHAN_INFO_PROCESSED:
>> switch (chan->type) {
>> + case IIO_HUMIDITYRELATIVE:
>> + ret = bmp280_read_humidity(data, val, val2);
>> + break;
>> case IIO_PRESSURE:
>> ret = bmp280_read_press(data, val, val2);
>> break;
>>
>
> --
>
> Peter Meerwald-Stadler
> +43-664-2444418 (mobile)
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/3] iio: pressure: bmp280: add initial support for multiple chips
2016-04-12 5:27 ` Matt Ranostay
@ 2016-04-17 11:51 ` Jonathan Cameron
0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Cameron @ 2016-04-17 11:51 UTC (permalink / raw)
To: Matt Ranostay, Peter Meerwald-Stadler; +Cc: Matt Ranostay, linux-iio
On 12/04/16 06:27, Matt Ranostay wrote:
> Ah noticed that just now... ironically I was thinking about submitting
> this last night :)
>
Life's like that sometimes. Anyhow, please rebase on Akinobu's
series once he's sent a V2.
Bad luck!
Jonathan
p.s. The silly thing here is that I review backwards from latest emails
so you might well have gotten merged if Peter hadn't pointed this out!
> On Mon, Apr 11, 2016 at 10:23 PM, Peter Meerwald-Stadler
> <pmeerw@pmeerw.net> wrote:
>>
>>> Bosch has several chipsets that use BMP280 as core features, this enables
>>> chip information for each variant.
>>
>> these patches clash with work to add BMP180 to the same driver, Akinobu
>> Mita was first :)
>>
>>> Signed-off-by: Matt Ranostay <matt.ranostay@intel.com>
>>> ---
>>> drivers/iio/pressure/bmp280.c | 59 +++++++++++++++++++++++++++++++++++++++----
>>> 1 file changed, 54 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c
>>> index a2602d8dd6d5..2e7cff38f5ff 100644
>>> --- a/drivers/iio/pressure/bmp280.c
>>> +++ b/drivers/iio/pressure/bmp280.c
>>> @@ -66,12 +66,15 @@
>>> #define BMP280_MODE_NORMAL (BIT(1) | BIT(0))
>>>
>>> #define BMP280_CHIP_ID 0x58
>>> +#define BME280_CHIP_ID 0x60
>>> +
>>> #define BMP280_SOFT_RESET_VAL 0xB6
>>>
>>> struct bmp280_data {
>>> struct i2c_client *client;
>>> struct mutex lock;
>>> struct regmap *regmap;
>>> + struct bmp280_chip_info *chip;
>>>
>>> /*
>>> * Carryover value from temperature conversion, used in pressure
>>> @@ -80,6 +83,24 @@ struct bmp280_data {
>>> s32 t_fine;
>>> };
>>>
>>> +enum { bmp280, bme280 };
>>> +
>>> +struct bmp280_chip_info {
>>> + int id;
>>> + int num_channels;
>>> +};
>>> +
>>> +static struct bmp280_chip_info bmp280_chip_info_table[] = {
>>> + [bmp280] = {
>>> + .id = BMP280_CHIP_ID,
>>> + .num_channels = 2,
>>> + },
>>> + [bme280] = {
>>> + .id = BME280_CHIP_ID,
>>> + .num_channels = 2,
>>> + },
>>> +};
>>> +
>>> /*
>>> * These enums are used for indexing into the array of compensation
>>> * parameters.
>>> @@ -344,6 +365,20 @@ static int bmp280_chip_init(struct bmp280_data *data)
>>> return ret;
>>> }
>>>
>>> +static int bmp280_match_acpi_device(struct device *dev,
>>> + struct bmp280_chip_info **chipset)
>>> +{
>>> + const struct acpi_device_id *id;
>>> +
>>> + id = acpi_match_device(dev->driver->acpi_match_table, dev);
>>> + if (!id)
>>> + return -ENODEV;
>>> +
>>> + *chipset = &bmp280_chip_info_table[id->driver_data];
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static int bmp280_probe(struct i2c_client *client,
>>> const struct i2c_device_id *id)
>>> {
>>> @@ -357,13 +392,25 @@ static int bmp280_probe(struct i2c_client *client,
>>> return -ENOMEM;
>>>
>>> data = iio_priv(indio_dev);
>>> +
>>> + if (id) {
>>> + data->chip = &bmp280_chip_info_table[id->driver_data];
>>> + } else if (ACPI_HANDLE(&client->dev)) {
>>> + ret = bmp280_match_acpi_device(&client->dev, &data->chip);
>>> + if (ret < 0)
>>> + return ret;
>>> + } else {
>>> + /* Don't break sysfs registration of BMP280 devices */
>>> + data->chip = &bmp280_chip_info_table[bmp280];
>>> + }
>>> +
>>> mutex_init(&data->lock);
>>> data->client = client;
>>>
>>> indio_dev->dev.parent = &client->dev;
>>> indio_dev->name = id->name;
>>> indio_dev->channels = bmp280_channels;
>>> - indio_dev->num_channels = ARRAY_SIZE(bmp280_channels);
>>> + indio_dev->num_channels = data->chip->num_channels;
>>> indio_dev->info = &bmp280_info;
>>> indio_dev->modes = INDIO_DIRECT_MODE;
>>>
>>> @@ -376,9 +423,9 @@ static int bmp280_probe(struct i2c_client *client,
>>> ret = regmap_read(data->regmap, BMP280_REG_ID, &chip_id);
>>> if (ret < 0)
>>> return ret;
>>> - if (chip_id != BMP280_CHIP_ID) {
>>> + if (chip_id != data->chip->id) {
>>> dev_err(&client->dev, "bad chip id. expected %x got %x\n",
>>> - BMP280_CHIP_ID, chip_id);
>>> + data->chip->id, chip_id);
>>> return -EINVAL;
>>> }
>>>
>>> @@ -390,13 +437,15 @@ static int bmp280_probe(struct i2c_client *client,
>>> }
>>>
>>> static const struct acpi_device_id bmp280_acpi_match[] = {
>>> - {"BMP0280", 0},
>>> + {"BMP0280", bmp280},
>>> + {"BME0280", bme280},
>>> { },
>>> };
>>> MODULE_DEVICE_TABLE(acpi, bmp280_acpi_match);
>>>
>>> static const struct i2c_device_id bmp280_id[] = {
>>> - {"bmp280", 0},
>>> + {"bmp280", bmp280},
>>> + {"bme280", bme280},
>>> { },
>>> };
>>> MODULE_DEVICE_TABLE(i2c, bmp280_id);
>>>
>>
>> --
>>
>> Peter Meerwald-Stadler
>> +43-664-2444418 (mobile)
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2016-04-17 11:51 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-12 5:21 [PATCH 0/3] iio: pressure: bmp280: add BME280 part support Matt Ranostay
2016-04-12 5:21 ` [PATCH 1/3] iio: pressure: bmp280: add initial support for multiple chips Matt Ranostay
2016-04-12 5:23 ` Peter Meerwald-Stadler
2016-04-12 5:27 ` Matt Ranostay
2016-04-17 11:51 ` Jonathan Cameron
2016-04-12 5:21 ` [PATCH 2/3] iio: pressure: bmp280: add per chip initialize function pointer Matt Ranostay
2016-04-12 5:17 ` Peter Meerwald-Stadler
2016-04-12 5:21 ` [PATCH 3/3] iio: pressure: bmp280: add humidity support Matt Ranostay
2016-04-12 5:21 ` Peter Meerwald-Stadler
2016-04-12 5:42 ` Matt Ranostay
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.