Skip to content

Commit 14beaa8

Browse files
Matt Ranostayjic23
authored andcommitted
iio: pressure: bmp280: add humidity support
Enable humidity support for the BME280 part Signed-off-by: Matt Ranostay <[email protected]> Acked-by: Vlad Dogaru <[email protected]> Signed-off-by: Jonathan Cameron <[email protected]>
1 parent b7a96bb commit 14beaa8

File tree

2 files changed

+200
-3
lines changed

2 files changed

+200
-3
lines changed

drivers/iio/pressure/Kconfig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ config BMP280
1212
select REGMAP_I2C
1313
help
1414
Say yes here to build support for Bosch Sensortec BMP180 and BMP280
15-
pressure and temperature sensors.
15+
pressure and temperature sensors. Also supports the BE280 with
16+
an additional humidty sensor channel.
1617

1718
To compile this driver as a module, choose M here: the module
1819
will be called bmp280.

drivers/iio/pressure/bmp280.c

Lines changed: 198 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* Datasheet:
1111
* https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP180-DS000-121.pdf
1212
* https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP280-DS001-12.pdf
13+
* https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME280_DS001-11.pdf
1314
*/
1415

1516
#define pr_fmt(fmt) "bmp280: " fmt
@@ -23,6 +24,8 @@
2324
#include <linux/iio/sysfs.h>
2425

2526
/* BMP280 specific registers */
27+
#define BMP280_REG_HUMIDITY_LSB 0xFE
28+
#define BMP280_REG_HUMIDITY_MSB 0xFD
2629
#define BMP280_REG_TEMP_XLSB 0xFC
2730
#define BMP280_REG_TEMP_LSB 0xFB
2831
#define BMP280_REG_TEMP_MSB 0xFA
@@ -31,7 +34,17 @@
3134
#define BMP280_REG_PRESS_MSB 0xF7
3235

3336
#define BMP280_REG_CONFIG 0xF5
37+
#define BMP280_REG_CTRL_MEAS 0xF4
3438
#define BMP280_REG_STATUS 0xF3
39+
#define BMP280_REG_CTRL_HUMIDITY 0xF2
40+
41+
/* Due to non linear mapping, and data sizes we can't do a bulk read */
42+
#define BMP280_REG_COMP_H1 0xA1
43+
#define BMP280_REG_COMP_H2 0xE1
44+
#define BMP280_REG_COMP_H3 0xE3
45+
#define BMP280_REG_COMP_H4 0xE4
46+
#define BMP280_REG_COMP_H5 0xE5
47+
#define BMP280_REG_COMP_H6 0xE7
3548

3649
#define BMP280_REG_COMP_TEMP_START 0x88
3750
#define BMP280_COMP_TEMP_REG_COUNT 6
@@ -46,6 +59,15 @@
4659
#define BMP280_FILTER_8X (BIT(3) | BIT(2))
4760
#define BMP280_FILTER_16X BIT(4)
4861

62+
#define BMP280_OSRS_HUMIDITY_MASK (BIT(2) | BIT(1) | BIT(0))
63+
#define BMP280_OSRS_HUMIDITIY_X(osrs_h) ((osrs_h) << 0)
64+
#define BMP280_OSRS_HUMIDITY_SKIP 0
65+
#define BMP280_OSRS_HUMIDITY_1X BMP280_OSRS_HUMIDITIY_X(1)
66+
#define BMP280_OSRS_HUMIDITY_2X BMP280_OSRS_HUMIDITIY_X(2)
67+
#define BMP280_OSRS_HUMIDITY_4X BMP280_OSRS_HUMIDITIY_X(3)
68+
#define BMP280_OSRS_HUMIDITY_8X BMP280_OSRS_HUMIDITIY_X(4)
69+
#define BMP280_OSRS_HUMIDITY_16X BMP280_OSRS_HUMIDITIY_X(5)
70+
4971
#define BMP280_OSRS_TEMP_MASK (BIT(7) | BIT(6) | BIT(5))
5072
#define BMP280_OSRS_TEMP_SKIP 0
5173
#define BMP280_OSRS_TEMP_X(osrs_t) ((osrs_t) << 5)
@@ -92,6 +114,7 @@
92114

93115
#define BMP180_CHIP_ID 0x55
94116
#define BMP280_CHIP_ID 0x58
117+
#define BME280_CHIP_ID 0x60
95118
#define BMP280_SOFT_RESET_VAL 0xB6
96119

97120
struct bmp280_data {
@@ -103,6 +126,7 @@ struct bmp280_data {
103126
/* log of base 2 of oversampling rate */
104127
u8 oversampling_press;
105128
u8 oversampling_temp;
129+
u8 oversampling_humid;
106130

107131
/*
108132
* Carryover value from temperature conversion, used in pressure
@@ -120,9 +144,13 @@ struct bmp280_chip_info {
120144
const int *oversampling_press_avail;
121145
int num_oversampling_press_avail;
122146

147+
const int *oversampling_humid_avail;
148+
int num_oversampling_humid_avail;
149+
123150
int (*chip_config)(struct bmp280_data *);
124151
int (*read_temp)(struct bmp280_data *, int *);
125152
int (*read_press)(struct bmp280_data *, int *, int *);
153+
int (*read_humid)(struct bmp280_data *, int *, int *);
126154
};
127155

128156
/*
@@ -143,12 +171,18 @@ static const struct iio_chan_spec bmp280_channels[] = {
143171
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
144172
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
145173
},
174+
{
175+
.type = IIO_HUMIDITYRELATIVE,
176+
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
177+
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
178+
},
146179
};
147180

148181
static bool bmp280_is_writeable_reg(struct device *dev, unsigned int reg)
149182
{
150183
switch (reg) {
151184
case BMP280_REG_CONFIG:
185+
case BMP280_REG_CTRL_HUMIDITY:
152186
case BMP280_REG_CTRL_MEAS:
153187
case BMP280_REG_RESET:
154188
return true;
@@ -160,6 +194,8 @@ static bool bmp280_is_writeable_reg(struct device *dev, unsigned int reg)
160194
static bool bmp280_is_volatile_reg(struct device *dev, unsigned int reg)
161195
{
162196
switch (reg) {
197+
case BMP280_REG_HUMIDITY_LSB:
198+
case BMP280_REG_HUMIDITY_MSB:
163199
case BMP280_REG_TEMP_XLSB:
164200
case BMP280_REG_TEMP_LSB:
165201
case BMP280_REG_TEMP_MSB:
@@ -177,13 +213,77 @@ static const struct regmap_config bmp280_regmap_config = {
177213
.reg_bits = 8,
178214
.val_bits = 8,
179215

180-
.max_register = BMP280_REG_TEMP_XLSB,
216+
.max_register = BMP280_REG_HUMIDITY_LSB,
181217
.cache_type = REGCACHE_RBTREE,
182218

183219
.writeable_reg = bmp280_is_writeable_reg,
184220
.volatile_reg = bmp280_is_volatile_reg,
185221
};
186222

223+
/*
224+
* Returns humidity in percent, resolution is 0.01 percent. Output value of
225+
* "47445" represents 47445/1024 = 46.333 %RH.
226+
*
227+
* Taken from BME280 datasheet, Section 4.2.3, "Compensation formula".
228+
*/
229+
230+
static u32 bmp280_compensate_humidity(struct bmp280_data *data,
231+
s32 adc_humidity)
232+
{
233+
struct device *dev = &data->client->dev;
234+
unsigned int H1, H3, tmp;
235+
int H2, H4, H5, H6, ret, var;
236+
237+
ret = regmap_read(data->regmap, BMP280_REG_COMP_H1, &H1);
238+
if (ret < 0) {
239+
dev_err(dev, "failed to read H1 comp value\n");
240+
return ret;
241+
}
242+
243+
ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H2, &tmp, 2);
244+
if (ret < 0) {
245+
dev_err(dev, "failed to read H2 comp value\n");
246+
return ret;
247+
}
248+
H2 = sign_extend32(le16_to_cpu(tmp), 15);
249+
250+
ret = regmap_read(data->regmap, BMP280_REG_COMP_H3, &H3);
251+
if (ret < 0) {
252+
dev_err(dev, "failed to read H3 comp value\n");
253+
return ret;
254+
}
255+
256+
ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H4, &tmp, 2);
257+
if (ret < 0) {
258+
dev_err(dev, "failed to read H4 comp value\n");
259+
return ret;
260+
}
261+
H4 = sign_extend32(((be16_to_cpu(tmp) >> 4) & 0xff0) |
262+
(be16_to_cpu(tmp) & 0xf), 11);
263+
264+
ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H5, &tmp, 2);
265+
if (ret < 0) {
266+
dev_err(dev, "failed to read H5 comp value\n");
267+
return ret;
268+
}
269+
H5 = sign_extend32(((le16_to_cpu(tmp) >> 4) & 0xfff), 11);
270+
271+
ret = regmap_read(data->regmap, BMP280_REG_COMP_H6, &tmp);
272+
if (ret < 0) {
273+
dev_err(dev, "failed to read H6 comp value\n");
274+
return ret;
275+
}
276+
H6 = sign_extend32(tmp, 7);
277+
278+
var = ((s32)data->t_fine) - 76800;
279+
var = ((((adc_humidity << 14) - (H4 << 20) - (H5 * var)) + 16384) >> 15)
280+
* (((((((var * H6) >> 10) * (((var * H3) >> 11) + 32768)) >> 10)
281+
+ 2097152) * H2 + 8192) >> 14);
282+
var -= ((((var >> 15) * (var >> 15)) >> 7) * H1) >> 4;
283+
284+
return var >> 12;
285+
};
286+
187287
/*
188288
* Returns temperature in DegC, resolution is 0.01 DegC. Output value of
189289
* "5123" equals 51.23 DegC. t_fine carries fine temperature as global
@@ -324,6 +424,34 @@ static int bmp280_read_press(struct bmp280_data *data,
324424
return IIO_VAL_FRACTIONAL;
325425
}
326426

427+
static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
428+
{
429+
int ret;
430+
__be16 tmp = 0;
431+
s32 adc_humidity;
432+
u32 comp_humidity;
433+
434+
/* Read and compensate temperature so we get a reading of t_fine. */
435+
ret = bmp280_read_temp(data, NULL);
436+
if (ret < 0)
437+
return ret;
438+
439+
ret = regmap_bulk_read(data->regmap, BMP280_REG_HUMIDITY_MSB,
440+
(u8 *) &tmp, 2);
441+
if (ret < 0) {
442+
dev_err(&data->client->dev, "failed to read humidity\n");
443+
return ret;
444+
}
445+
446+
adc_humidity = be16_to_cpu(tmp);
447+
comp_humidity = bmp280_compensate_humidity(data, adc_humidity);
448+
449+
*val = comp_humidity;
450+
*val2 = 1024;
451+
452+
return IIO_VAL_FRACTIONAL;
453+
}
454+
327455
static int bmp280_read_raw(struct iio_dev *indio_dev,
328456
struct iio_chan_spec const *chan,
329457
int *val, int *val2, long mask)
@@ -336,6 +464,9 @@ static int bmp280_read_raw(struct iio_dev *indio_dev,
336464
switch (mask) {
337465
case IIO_CHAN_INFO_PROCESSED:
338466
switch (chan->type) {
467+
case IIO_HUMIDITYRELATIVE:
468+
ret = data->chip_info->read_humid(data, val, val2);
469+
break;
339470
case IIO_PRESSURE:
340471
ret = data->chip_info->read_press(data, val, val2);
341472
break;
@@ -349,6 +480,10 @@ static int bmp280_read_raw(struct iio_dev *indio_dev,
349480
break;
350481
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
351482
switch (chan->type) {
483+
case IIO_HUMIDITYRELATIVE:
484+
*val = 1 << data->oversampling_humid;
485+
ret = IIO_VAL_INT;
486+
break;
352487
case IIO_PRESSURE:
353488
*val = 1 << data->oversampling_press;
354489
ret = IIO_VAL_INT;
@@ -372,6 +507,23 @@ static int bmp280_read_raw(struct iio_dev *indio_dev,
372507
return ret;
373508
}
374509

510+
static int bmp280_write_oversampling_ratio_humid(struct bmp280_data *data,
511+
int val)
512+
{
513+
int i;
514+
const int *avail = data->chip_info->oversampling_humid_avail;
515+
const int n = data->chip_info->num_oversampling_humid_avail;
516+
517+
for (i = 0; i < n; i++) {
518+
if (avail[i] == val) {
519+
data->oversampling_humid = ilog2(val);
520+
521+
return data->chip_info->chip_config(data);
522+
}
523+
}
524+
return -EINVAL;
525+
}
526+
375527
static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data,
376528
int val)
377529
{
@@ -417,6 +569,9 @@ static int bmp280_write_raw(struct iio_dev *indio_dev,
417569
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
418570
mutex_lock(&data->lock);
419571
switch (chan->type) {
572+
case IIO_HUMIDITYRELATIVE:
573+
ret = bmp280_write_oversampling_ratio_humid(data, val);
574+
break;
420575
case IIO_PRESSURE:
421576
ret = bmp280_write_oversampling_ratio_press(data, val);
422577
break;
@@ -535,6 +690,37 @@ static const struct bmp280_chip_info bmp280_chip_info = {
535690
.read_press = bmp280_read_press,
536691
};
537692

693+
static int bme280_chip_config(struct bmp280_data *data)
694+
{
695+
int ret = bmp280_chip_config(data);
696+
u8 osrs = BMP280_OSRS_HUMIDITIY_X(data->oversampling_humid + 1);
697+
698+
if (ret < 0)
699+
return ret;
700+
701+
return regmap_update_bits(data->regmap, BMP280_REG_CTRL_HUMIDITY,
702+
BMP280_OSRS_HUMIDITY_MASK, osrs);
703+
}
704+
705+
static const struct bmp280_chip_info bme280_chip_info = {
706+
.regmap_config = &bmp280_regmap_config,
707+
708+
.oversampling_temp_avail = bmp280_oversampling_avail,
709+
.num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail),
710+
711+
.oversampling_press_avail = bmp280_oversampling_avail,
712+
.num_oversampling_press_avail = ARRAY_SIZE(bmp280_oversampling_avail),
713+
714+
.oversampling_humid_avail = bmp280_oversampling_avail,
715+
.num_oversampling_humid_avail = ARRAY_SIZE(bmp280_oversampling_avail),
716+
717+
.chip_config = bme280_chip_config,
718+
.read_temp = bmp280_read_temp,
719+
.read_press = bmp280_read_press,
720+
.read_humid = bmp280_read_humid,
721+
};
722+
723+
538724
static bool bmp180_is_writeable_reg(struct device *dev, unsigned int reg)
539725
{
540726
switch (reg) {
@@ -849,21 +1035,29 @@ static int bmp280_probe(struct i2c_client *client,
8491035
indio_dev->dev.parent = &client->dev;
8501036
indio_dev->name = id->name;
8511037
indio_dev->channels = bmp280_channels;
852-
indio_dev->num_channels = ARRAY_SIZE(bmp280_channels);
8531038
indio_dev->info = &bmp280_info;
8541039
indio_dev->modes = INDIO_DIRECT_MODE;
8551040

8561041
switch (id->driver_data) {
8571042
case BMP180_CHIP_ID:
1043+
indio_dev->num_channels = 2;
8581044
data->chip_info = &bmp180_chip_info;
8591045
data->oversampling_press = ilog2(8);
8601046
data->oversampling_temp = ilog2(1);
8611047
break;
8621048
case BMP280_CHIP_ID:
1049+
indio_dev->num_channels = 2;
8631050
data->chip_info = &bmp280_chip_info;
8641051
data->oversampling_press = ilog2(16);
8651052
data->oversampling_temp = ilog2(2);
8661053
break;
1054+
case BME280_CHIP_ID:
1055+
indio_dev->num_channels = 3;
1056+
data->chip_info = &bme280_chip_info;
1057+
data->oversampling_press = ilog2(16);
1058+
data->oversampling_humid = ilog2(16);
1059+
data->oversampling_temp = ilog2(2);
1060+
break;
8671061
default:
8681062
return -EINVAL;
8691063
}
@@ -895,6 +1089,7 @@ static const struct acpi_device_id bmp280_acpi_match[] = {
8951089
{"BMP0280", BMP280_CHIP_ID },
8961090
{"BMP0180", BMP180_CHIP_ID },
8971091
{"BMP0085", BMP180_CHIP_ID },
1092+
{"BME0280", BME280_CHIP_ID },
8981093
{ },
8991094
};
9001095
MODULE_DEVICE_TABLE(acpi, bmp280_acpi_match);
@@ -903,6 +1098,7 @@ static const struct i2c_device_id bmp280_id[] = {
9031098
{"bmp280", BMP280_CHIP_ID },
9041099
{"bmp180", BMP180_CHIP_ID },
9051100
{"bmp085", BMP180_CHIP_ID },
1101+
{"bme280", BME280_CHIP_ID },
9061102
{ },
9071103
};
9081104
MODULE_DEVICE_TABLE(i2c, bmp280_id);

0 commit comments

Comments
 (0)