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

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

 



> 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@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



[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