Re: [PATCH 3/3] iio: pressure: bmp280: add humidity support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Apr 11, 2016 at 10:21 PM, Peter Meerwald-Stadler
<pmeerw@xxxxxxxxxx> 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@xxxxxxxxx>
>> ---
>>  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@xxxxxxxxxxxxxxx
> 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@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux