* [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
* 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 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
* [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
* 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 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 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
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.