1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Bosch BME680 - Temperature, Pressure, Humidity & Gas Sensor |
4 | * |
5 | * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH |
6 | * Copyright (C) 2018 Himanshu Jha <himanshujha199640@gmail.com> |
7 | * |
8 | * Datasheet: |
9 | * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME680-DS001-00.pdf |
10 | */ |
11 | #include <linux/acpi.h> |
12 | #include <linux/bitfield.h> |
13 | #include <linux/device.h> |
14 | #include <linux/module.h> |
15 | #include <linux/log2.h> |
16 | #include <linux/regmap.h> |
17 | #include <linux/iio/iio.h> |
18 | #include <linux/iio/sysfs.h> |
19 | |
20 | #include "bme680.h" |
21 | |
22 | struct bme680_calib { |
23 | u16 par_t1; |
24 | s16 par_t2; |
25 | s8 par_t3; |
26 | u16 par_p1; |
27 | s16 par_p2; |
28 | s8 par_p3; |
29 | s16 par_p4; |
30 | s16 par_p5; |
31 | s8 par_p6; |
32 | s8 par_p7; |
33 | s16 par_p8; |
34 | s16 par_p9; |
35 | u8 par_p10; |
36 | u16 par_h1; |
37 | u16 par_h2; |
38 | s8 par_h3; |
39 | s8 par_h4; |
40 | s8 par_h5; |
41 | s8 par_h6; |
42 | s8 par_h7; |
43 | s8 par_gh1; |
44 | s16 par_gh2; |
45 | s8 par_gh3; |
46 | u8 res_heat_range; |
47 | s8 res_heat_val; |
48 | s8 range_sw_err; |
49 | }; |
50 | |
51 | struct bme680_data { |
52 | struct regmap *regmap; |
53 | struct bme680_calib bme680; |
54 | u8 oversampling_temp; |
55 | u8 oversampling_press; |
56 | u8 oversampling_humid; |
57 | u16 heater_dur; |
58 | u16 heater_temp; |
59 | /* |
60 | * Carryover value from temperature conversion, used in pressure |
61 | * and humidity compensation calculations. |
62 | */ |
63 | s32 t_fine; |
64 | }; |
65 | |
66 | static const struct regmap_range bme680_volatile_ranges[] = { |
67 | regmap_reg_range(BME680_REG_MEAS_STAT_0, BME680_REG_GAS_R_LSB), |
68 | regmap_reg_range(BME680_REG_STATUS, BME680_REG_STATUS), |
69 | regmap_reg_range(BME680_T2_LSB_REG, BME680_GH3_REG), |
70 | }; |
71 | |
72 | static const struct regmap_access_table bme680_volatile_table = { |
73 | .yes_ranges = bme680_volatile_ranges, |
74 | .n_yes_ranges = ARRAY_SIZE(bme680_volatile_ranges), |
75 | }; |
76 | |
77 | const struct regmap_config bme680_regmap_config = { |
78 | .reg_bits = 8, |
79 | .val_bits = 8, |
80 | .max_register = 0xef, |
81 | .volatile_table = &bme680_volatile_table, |
82 | .cache_type = REGCACHE_RBTREE, |
83 | }; |
84 | EXPORT_SYMBOL_NS(bme680_regmap_config, IIO_BME680); |
85 | |
86 | static const struct iio_chan_spec bme680_channels[] = { |
87 | { |
88 | .type = IIO_TEMP, |
89 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | |
90 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), |
91 | }, |
92 | { |
93 | .type = IIO_PRESSURE, |
94 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | |
95 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), |
96 | }, |
97 | { |
98 | .type = IIO_HUMIDITYRELATIVE, |
99 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | |
100 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), |
101 | }, |
102 | { |
103 | .type = IIO_RESISTANCE, |
104 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), |
105 | }, |
106 | }; |
107 | |
108 | static int bme680_read_calib(struct bme680_data *data, |
109 | struct bme680_calib *calib) |
110 | { |
111 | struct device *dev = regmap_get_device(map: data->regmap); |
112 | unsigned int tmp, tmp_msb, tmp_lsb; |
113 | int ret; |
114 | __le16 buf; |
115 | |
116 | /* Temperature related coefficients */ |
117 | ret = regmap_bulk_read(map: data->regmap, BME680_T1_LSB_REG, |
118 | val: &buf, val_count: sizeof(buf)); |
119 | if (ret < 0) { |
120 | dev_err(dev, "failed to read BME680_T1_LSB_REG\n" ); |
121 | return ret; |
122 | } |
123 | calib->par_t1 = le16_to_cpu(buf); |
124 | |
125 | ret = regmap_bulk_read(map: data->regmap, BME680_T2_LSB_REG, |
126 | val: &buf, val_count: sizeof(buf)); |
127 | if (ret < 0) { |
128 | dev_err(dev, "failed to read BME680_T2_LSB_REG\n" ); |
129 | return ret; |
130 | } |
131 | calib->par_t2 = le16_to_cpu(buf); |
132 | |
133 | ret = regmap_read(map: data->regmap, BME680_T3_REG, val: &tmp); |
134 | if (ret < 0) { |
135 | dev_err(dev, "failed to read BME680_T3_REG\n" ); |
136 | return ret; |
137 | } |
138 | calib->par_t3 = tmp; |
139 | |
140 | /* Pressure related coefficients */ |
141 | ret = regmap_bulk_read(map: data->regmap, BME680_P1_LSB_REG, |
142 | val: &buf, val_count: sizeof(buf)); |
143 | if (ret < 0) { |
144 | dev_err(dev, "failed to read BME680_P1_LSB_REG\n" ); |
145 | return ret; |
146 | } |
147 | calib->par_p1 = le16_to_cpu(buf); |
148 | |
149 | ret = regmap_bulk_read(map: data->regmap, BME680_P2_LSB_REG, |
150 | val: &buf, val_count: sizeof(buf)); |
151 | if (ret < 0) { |
152 | dev_err(dev, "failed to read BME680_P2_LSB_REG\n" ); |
153 | return ret; |
154 | } |
155 | calib->par_p2 = le16_to_cpu(buf); |
156 | |
157 | ret = regmap_read(map: data->regmap, BME680_P3_REG, val: &tmp); |
158 | if (ret < 0) { |
159 | dev_err(dev, "failed to read BME680_P3_REG\n" ); |
160 | return ret; |
161 | } |
162 | calib->par_p3 = tmp; |
163 | |
164 | ret = regmap_bulk_read(map: data->regmap, BME680_P4_LSB_REG, |
165 | val: &buf, val_count: sizeof(buf)); |
166 | if (ret < 0) { |
167 | dev_err(dev, "failed to read BME680_P4_LSB_REG\n" ); |
168 | return ret; |
169 | } |
170 | calib->par_p4 = le16_to_cpu(buf); |
171 | |
172 | ret = regmap_bulk_read(map: data->regmap, BME680_P5_LSB_REG, |
173 | val: &buf, val_count: sizeof(buf)); |
174 | if (ret < 0) { |
175 | dev_err(dev, "failed to read BME680_P5_LSB_REG\n" ); |
176 | return ret; |
177 | } |
178 | calib->par_p5 = le16_to_cpu(buf); |
179 | |
180 | ret = regmap_read(map: data->regmap, BME680_P6_REG, val: &tmp); |
181 | if (ret < 0) { |
182 | dev_err(dev, "failed to read BME680_P6_REG\n" ); |
183 | return ret; |
184 | } |
185 | calib->par_p6 = tmp; |
186 | |
187 | ret = regmap_read(map: data->regmap, BME680_P7_REG, val: &tmp); |
188 | if (ret < 0) { |
189 | dev_err(dev, "failed to read BME680_P7_REG\n" ); |
190 | return ret; |
191 | } |
192 | calib->par_p7 = tmp; |
193 | |
194 | ret = regmap_bulk_read(map: data->regmap, BME680_P8_LSB_REG, |
195 | val: &buf, val_count: sizeof(buf)); |
196 | if (ret < 0) { |
197 | dev_err(dev, "failed to read BME680_P8_LSB_REG\n" ); |
198 | return ret; |
199 | } |
200 | calib->par_p8 = le16_to_cpu(buf); |
201 | |
202 | ret = regmap_bulk_read(map: data->regmap, BME680_P9_LSB_REG, |
203 | val: &buf, val_count: sizeof(buf)); |
204 | if (ret < 0) { |
205 | dev_err(dev, "failed to read BME680_P9_LSB_REG\n" ); |
206 | return ret; |
207 | } |
208 | calib->par_p9 = le16_to_cpu(buf); |
209 | |
210 | ret = regmap_read(map: data->regmap, BME680_P10_REG, val: &tmp); |
211 | if (ret < 0) { |
212 | dev_err(dev, "failed to read BME680_P10_REG\n" ); |
213 | return ret; |
214 | } |
215 | calib->par_p10 = tmp; |
216 | |
217 | /* Humidity related coefficients */ |
218 | ret = regmap_read(map: data->regmap, BME680_H1_MSB_REG, val: &tmp_msb); |
219 | if (ret < 0) { |
220 | dev_err(dev, "failed to read BME680_H1_MSB_REG\n" ); |
221 | return ret; |
222 | } |
223 | ret = regmap_read(map: data->regmap, BME680_H1_LSB_REG, val: &tmp_lsb); |
224 | if (ret < 0) { |
225 | dev_err(dev, "failed to read BME680_H1_LSB_REG\n" ); |
226 | return ret; |
227 | } |
228 | calib->par_h1 = (tmp_msb << BME680_HUM_REG_SHIFT_VAL) | |
229 | (tmp_lsb & BME680_BIT_H1_DATA_MASK); |
230 | |
231 | ret = regmap_read(map: data->regmap, BME680_H2_MSB_REG, val: &tmp_msb); |
232 | if (ret < 0) { |
233 | dev_err(dev, "failed to read BME680_H2_MSB_REG\n" ); |
234 | return ret; |
235 | } |
236 | ret = regmap_read(map: data->regmap, BME680_H2_LSB_REG, val: &tmp_lsb); |
237 | if (ret < 0) { |
238 | dev_err(dev, "failed to read BME680_H2_LSB_REG\n" ); |
239 | return ret; |
240 | } |
241 | calib->par_h2 = (tmp_msb << BME680_HUM_REG_SHIFT_VAL) | |
242 | (tmp_lsb >> BME680_HUM_REG_SHIFT_VAL); |
243 | |
244 | ret = regmap_read(map: data->regmap, BME680_H3_REG, val: &tmp); |
245 | if (ret < 0) { |
246 | dev_err(dev, "failed to read BME680_H3_REG\n" ); |
247 | return ret; |
248 | } |
249 | calib->par_h3 = tmp; |
250 | |
251 | ret = regmap_read(map: data->regmap, BME680_H4_REG, val: &tmp); |
252 | if (ret < 0) { |
253 | dev_err(dev, "failed to read BME680_H4_REG\n" ); |
254 | return ret; |
255 | } |
256 | calib->par_h4 = tmp; |
257 | |
258 | ret = regmap_read(map: data->regmap, BME680_H5_REG, val: &tmp); |
259 | if (ret < 0) { |
260 | dev_err(dev, "failed to read BME680_H5_REG\n" ); |
261 | return ret; |
262 | } |
263 | calib->par_h5 = tmp; |
264 | |
265 | ret = regmap_read(map: data->regmap, BME680_H6_REG, val: &tmp); |
266 | if (ret < 0) { |
267 | dev_err(dev, "failed to read BME680_H6_REG\n" ); |
268 | return ret; |
269 | } |
270 | calib->par_h6 = tmp; |
271 | |
272 | ret = regmap_read(map: data->regmap, BME680_H7_REG, val: &tmp); |
273 | if (ret < 0) { |
274 | dev_err(dev, "failed to read BME680_H7_REG\n" ); |
275 | return ret; |
276 | } |
277 | calib->par_h7 = tmp; |
278 | |
279 | /* Gas heater related coefficients */ |
280 | ret = regmap_read(map: data->regmap, BME680_GH1_REG, val: &tmp); |
281 | if (ret < 0) { |
282 | dev_err(dev, "failed to read BME680_GH1_REG\n" ); |
283 | return ret; |
284 | } |
285 | calib->par_gh1 = tmp; |
286 | |
287 | ret = regmap_bulk_read(map: data->regmap, BME680_GH2_LSB_REG, |
288 | val: &buf, val_count: sizeof(buf)); |
289 | if (ret < 0) { |
290 | dev_err(dev, "failed to read BME680_GH2_LSB_REG\n" ); |
291 | return ret; |
292 | } |
293 | calib->par_gh2 = le16_to_cpu(buf); |
294 | |
295 | ret = regmap_read(map: data->regmap, BME680_GH3_REG, val: &tmp); |
296 | if (ret < 0) { |
297 | dev_err(dev, "failed to read BME680_GH3_REG\n" ); |
298 | return ret; |
299 | } |
300 | calib->par_gh3 = tmp; |
301 | |
302 | /* Other coefficients */ |
303 | ret = regmap_read(map: data->regmap, BME680_REG_RES_HEAT_RANGE, val: &tmp); |
304 | if (ret < 0) { |
305 | dev_err(dev, "failed to read resistance heat range\n" ); |
306 | return ret; |
307 | } |
308 | calib->res_heat_range = FIELD_GET(BME680_RHRANGE_MASK, tmp); |
309 | |
310 | ret = regmap_read(map: data->regmap, BME680_REG_RES_HEAT_VAL, val: &tmp); |
311 | if (ret < 0) { |
312 | dev_err(dev, "failed to read resistance heat value\n" ); |
313 | return ret; |
314 | } |
315 | calib->res_heat_val = tmp; |
316 | |
317 | ret = regmap_read(map: data->regmap, BME680_REG_RANGE_SW_ERR, val: &tmp); |
318 | if (ret < 0) { |
319 | dev_err(dev, "failed to read range software error\n" ); |
320 | return ret; |
321 | } |
322 | calib->range_sw_err = FIELD_GET(BME680_RSERROR_MASK, tmp); |
323 | |
324 | return 0; |
325 | } |
326 | |
327 | /* |
328 | * Taken from Bosch BME680 API: |
329 | * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L876 |
330 | * |
331 | * Returns temperature measurement in DegC, resolutions is 0.01 DegC. Therefore, |
332 | * output value of "3233" represents 32.33 DegC. |
333 | */ |
334 | static s16 bme680_compensate_temp(struct bme680_data *data, |
335 | s32 adc_temp) |
336 | { |
337 | struct bme680_calib *calib = &data->bme680; |
338 | s64 var1, var2, var3; |
339 | s16 calc_temp; |
340 | |
341 | /* If the calibration is invalid, attempt to reload it */ |
342 | if (!calib->par_t2) |
343 | bme680_read_calib(data, calib); |
344 | |
345 | var1 = (adc_temp >> 3) - (calib->par_t1 << 1); |
346 | var2 = (var1 * calib->par_t2) >> 11; |
347 | var3 = ((var1 >> 1) * (var1 >> 1)) >> 12; |
348 | var3 = (var3 * (calib->par_t3 << 4)) >> 14; |
349 | data->t_fine = var2 + var3; |
350 | calc_temp = (data->t_fine * 5 + 128) >> 8; |
351 | |
352 | return calc_temp; |
353 | } |
354 | |
355 | /* |
356 | * Taken from Bosch BME680 API: |
357 | * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L896 |
358 | * |
359 | * Returns pressure measurement in Pa. Output value of "97356" represents |
360 | * 97356 Pa = 973.56 hPa. |
361 | */ |
362 | static u32 bme680_compensate_press(struct bme680_data *data, |
363 | u32 adc_press) |
364 | { |
365 | struct bme680_calib *calib = &data->bme680; |
366 | s32 var1, var2, var3, press_comp; |
367 | |
368 | var1 = (data->t_fine >> 1) - 64000; |
369 | var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * calib->par_p6) >> 2; |
370 | var2 = var2 + (var1 * calib->par_p5 << 1); |
371 | var2 = (var2 >> 2) + (calib->par_p4 << 16); |
372 | var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) * |
373 | (calib->par_p3 << 5)) >> 3) + |
374 | ((calib->par_p2 * var1) >> 1); |
375 | var1 = var1 >> 18; |
376 | var1 = ((32768 + var1) * calib->par_p1) >> 15; |
377 | press_comp = 1048576 - adc_press; |
378 | press_comp = ((press_comp - (var2 >> 12)) * 3125); |
379 | |
380 | if (press_comp >= BME680_MAX_OVERFLOW_VAL) |
381 | press_comp = ((press_comp / (u32)var1) << 1); |
382 | else |
383 | press_comp = ((press_comp << 1) / (u32)var1); |
384 | |
385 | var1 = (calib->par_p9 * (((press_comp >> 3) * |
386 | (press_comp >> 3)) >> 13)) >> 12; |
387 | var2 = ((press_comp >> 2) * calib->par_p8) >> 13; |
388 | var3 = ((press_comp >> 8) * (press_comp >> 8) * |
389 | (press_comp >> 8) * calib->par_p10) >> 17; |
390 | |
391 | press_comp += (var1 + var2 + var3 + (calib->par_p7 << 7)) >> 4; |
392 | |
393 | return press_comp; |
394 | } |
395 | |
396 | /* |
397 | * Taken from Bosch BME680 API: |
398 | * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L937 |
399 | * |
400 | * Returns humidity measurement in percent, resolution is 0.001 percent. Output |
401 | * value of "43215" represents 43.215 %rH. |
402 | */ |
403 | static u32 bme680_compensate_humid(struct bme680_data *data, |
404 | u16 adc_humid) |
405 | { |
406 | struct bme680_calib *calib = &data->bme680; |
407 | s32 var1, var2, var3, var4, var5, var6, temp_scaled, calc_hum; |
408 | |
409 | temp_scaled = (data->t_fine * 5 + 128) >> 8; |
410 | var1 = (adc_humid - ((s32) ((s32) calib->par_h1 * 16))) - |
411 | (((temp_scaled * (s32) calib->par_h3) / 100) >> 1); |
412 | var2 = ((s32) calib->par_h2 * |
413 | (((temp_scaled * calib->par_h4) / 100) + |
414 | (((temp_scaled * ((temp_scaled * calib->par_h5) / 100)) |
415 | >> 6) / 100) + (1 << 14))) >> 10; |
416 | var3 = var1 * var2; |
417 | var4 = calib->par_h6 << 7; |
418 | var4 = (var4 + ((temp_scaled * calib->par_h7) / 100)) >> 4; |
419 | var5 = ((var3 >> 14) * (var3 >> 14)) >> 10; |
420 | var6 = (var4 * var5) >> 1; |
421 | calc_hum = (((var3 + var6) >> 10) * 1000) >> 12; |
422 | |
423 | calc_hum = clamp(calc_hum, 0, 100000); /* clamp between 0-100 %rH */ |
424 | |
425 | return calc_hum; |
426 | } |
427 | |
428 | /* |
429 | * Taken from Bosch BME680 API: |
430 | * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L973 |
431 | * |
432 | * Returns gas measurement in Ohm. Output value of "82986" represent 82986 ohms. |
433 | */ |
434 | static u32 bme680_compensate_gas(struct bme680_data *data, u16 gas_res_adc, |
435 | u8 gas_range) |
436 | { |
437 | struct bme680_calib *calib = &data->bme680; |
438 | s64 var1; |
439 | u64 var2; |
440 | s64 var3; |
441 | u32 calc_gas_res; |
442 | |
443 | /* Look up table for the possible gas range values */ |
444 | const u32 lookupTable[16] = {2147483647u, 2147483647u, |
445 | 2147483647u, 2147483647u, 2147483647u, |
446 | 2126008810u, 2147483647u, 2130303777u, |
447 | 2147483647u, 2147483647u, 2143188679u, |
448 | 2136746228u, 2147483647u, 2126008810u, |
449 | 2147483647u, 2147483647u}; |
450 | |
451 | var1 = ((1340 + (5 * (s64) calib->range_sw_err)) * |
452 | ((s64) lookupTable[gas_range])) >> 16; |
453 | var2 = ((gas_res_adc << 15) - 16777216) + var1; |
454 | var3 = ((125000 << (15 - gas_range)) * var1) >> 9; |
455 | var3 += (var2 >> 1); |
456 | calc_gas_res = div64_s64(dividend: var3, divisor: (s64) var2); |
457 | |
458 | return calc_gas_res; |
459 | } |
460 | |
461 | /* |
462 | * Taken from Bosch BME680 API: |
463 | * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L1002 |
464 | */ |
465 | static u8 bme680_calc_heater_res(struct bme680_data *data, u16 temp) |
466 | { |
467 | struct bme680_calib *calib = &data->bme680; |
468 | s32 var1, var2, var3, var4, var5, heatr_res_x100; |
469 | u8 heatr_res; |
470 | |
471 | if (temp > 400) /* Cap temperature */ |
472 | temp = 400; |
473 | |
474 | var1 = (((s32) BME680_AMB_TEMP * calib->par_gh3) / 1000) * 256; |
475 | var2 = (calib->par_gh1 + 784) * (((((calib->par_gh2 + 154009) * |
476 | temp * 5) / 100) |
477 | + 3276800) / 10); |
478 | var3 = var1 + (var2 / 2); |
479 | var4 = (var3 / (calib->res_heat_range + 4)); |
480 | var5 = 131 * calib->res_heat_val + 65536; |
481 | heatr_res_x100 = ((var4 / var5) - 250) * 34; |
482 | heatr_res = DIV_ROUND_CLOSEST(heatr_res_x100, 100); |
483 | |
484 | return heatr_res; |
485 | } |
486 | |
487 | /* |
488 | * Taken from Bosch BME680 API: |
489 | * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L1188 |
490 | */ |
491 | static u8 bme680_calc_heater_dur(u16 dur) |
492 | { |
493 | u8 durval, factor = 0; |
494 | |
495 | if (dur >= 0xfc0) { |
496 | durval = 0xff; /* Max duration */ |
497 | } else { |
498 | while (dur > 0x3F) { |
499 | dur = dur / 4; |
500 | factor += 1; |
501 | } |
502 | durval = dur + (factor * 64); |
503 | } |
504 | |
505 | return durval; |
506 | } |
507 | |
508 | static int bme680_set_mode(struct bme680_data *data, bool mode) |
509 | { |
510 | struct device *dev = regmap_get_device(map: data->regmap); |
511 | int ret; |
512 | |
513 | if (mode) { |
514 | ret = regmap_write_bits(map: data->regmap, BME680_REG_CTRL_MEAS, |
515 | BME680_MODE_MASK, BME680_MODE_FORCED); |
516 | if (ret < 0) |
517 | dev_err(dev, "failed to set forced mode\n" ); |
518 | |
519 | } else { |
520 | ret = regmap_write_bits(map: data->regmap, BME680_REG_CTRL_MEAS, |
521 | BME680_MODE_MASK, BME680_MODE_SLEEP); |
522 | if (ret < 0) |
523 | dev_err(dev, "failed to set sleep mode\n" ); |
524 | |
525 | } |
526 | |
527 | return ret; |
528 | } |
529 | |
530 | static u8 bme680_oversampling_to_reg(u8 val) |
531 | { |
532 | return ilog2(val) + 1; |
533 | } |
534 | |
535 | static int bme680_chip_config(struct bme680_data *data) |
536 | { |
537 | struct device *dev = regmap_get_device(map: data->regmap); |
538 | int ret; |
539 | u8 osrs; |
540 | |
541 | osrs = FIELD_PREP( |
542 | BME680_OSRS_HUMIDITY_MASK, |
543 | bme680_oversampling_to_reg(data->oversampling_humid)); |
544 | /* |
545 | * Highly recommended to set oversampling of humidity before |
546 | * temperature/pressure oversampling. |
547 | */ |
548 | ret = regmap_update_bits(map: data->regmap, BME680_REG_CTRL_HUMIDITY, |
549 | BME680_OSRS_HUMIDITY_MASK, val: osrs); |
550 | if (ret < 0) { |
551 | dev_err(dev, "failed to write ctrl_hum register\n" ); |
552 | return ret; |
553 | } |
554 | |
555 | /* IIR filter settings */ |
556 | ret = regmap_update_bits(map: data->regmap, BME680_REG_CONFIG, |
557 | BME680_FILTER_MASK, |
558 | BME680_FILTER_COEFF_VAL); |
559 | if (ret < 0) { |
560 | dev_err(dev, "failed to write config register\n" ); |
561 | return ret; |
562 | } |
563 | |
564 | osrs = FIELD_PREP(BME680_OSRS_TEMP_MASK, |
565 | bme680_oversampling_to_reg(data->oversampling_temp)) | |
566 | FIELD_PREP(BME680_OSRS_PRESS_MASK, |
567 | bme680_oversampling_to_reg(data->oversampling_press)); |
568 | ret = regmap_write_bits(map: data->regmap, BME680_REG_CTRL_MEAS, |
569 | BME680_OSRS_TEMP_MASK | BME680_OSRS_PRESS_MASK, |
570 | val: osrs); |
571 | if (ret < 0) |
572 | dev_err(dev, "failed to write ctrl_meas register\n" ); |
573 | |
574 | return ret; |
575 | } |
576 | |
577 | static int bme680_gas_config(struct bme680_data *data) |
578 | { |
579 | struct device *dev = regmap_get_device(map: data->regmap); |
580 | int ret; |
581 | u8 heatr_res, heatr_dur; |
582 | |
583 | heatr_res = bme680_calc_heater_res(data, temp: data->heater_temp); |
584 | |
585 | /* set target heater temperature */ |
586 | ret = regmap_write(map: data->regmap, BME680_REG_RES_HEAT_0, val: heatr_res); |
587 | if (ret < 0) { |
588 | dev_err(dev, "failed to write res_heat_0 register\n" ); |
589 | return ret; |
590 | } |
591 | |
592 | heatr_dur = bme680_calc_heater_dur(dur: data->heater_dur); |
593 | |
594 | /* set target heating duration */ |
595 | ret = regmap_write(map: data->regmap, BME680_REG_GAS_WAIT_0, val: heatr_dur); |
596 | if (ret < 0) { |
597 | dev_err(dev, "failed to write gas_wait_0 register\n" ); |
598 | return ret; |
599 | } |
600 | |
601 | /* Enable the gas sensor and select heater profile set-point 0 */ |
602 | ret = regmap_update_bits(map: data->regmap, BME680_REG_CTRL_GAS_1, |
603 | BME680_RUN_GAS_MASK | BME680_NB_CONV_MASK, |
604 | FIELD_PREP(BME680_RUN_GAS_MASK, 1) | |
605 | FIELD_PREP(BME680_NB_CONV_MASK, 0)); |
606 | if (ret < 0) |
607 | dev_err(dev, "failed to write ctrl_gas_1 register\n" ); |
608 | |
609 | return ret; |
610 | } |
611 | |
612 | static int bme680_read_temp(struct bme680_data *data, int *val) |
613 | { |
614 | struct device *dev = regmap_get_device(map: data->regmap); |
615 | int ret; |
616 | __be32 tmp = 0; |
617 | s32 adc_temp; |
618 | s16 comp_temp; |
619 | |
620 | /* set forced mode to trigger measurement */ |
621 | ret = bme680_set_mode(data, mode: true); |
622 | if (ret < 0) |
623 | return ret; |
624 | |
625 | ret = regmap_bulk_read(map: data->regmap, BME680_REG_TEMP_MSB, |
626 | val: &tmp, val_count: 3); |
627 | if (ret < 0) { |
628 | dev_err(dev, "failed to read temperature\n" ); |
629 | return ret; |
630 | } |
631 | |
632 | adc_temp = be32_to_cpu(tmp) >> 12; |
633 | if (adc_temp == BME680_MEAS_SKIPPED) { |
634 | /* reading was skipped */ |
635 | dev_err(dev, "reading temperature skipped\n" ); |
636 | return -EINVAL; |
637 | } |
638 | comp_temp = bme680_compensate_temp(data, adc_temp); |
639 | /* |
640 | * val might be NULL if we're called by the read_press/read_humid |
641 | * routine which is called to get t_fine value used in |
642 | * compensate_press/compensate_humid to get compensated |
643 | * pressure/humidity readings. |
644 | */ |
645 | if (val) { |
646 | *val = comp_temp * 10; /* Centidegrees to millidegrees */ |
647 | return IIO_VAL_INT; |
648 | } |
649 | |
650 | return ret; |
651 | } |
652 | |
653 | static int bme680_read_press(struct bme680_data *data, |
654 | int *val, int *val2) |
655 | { |
656 | struct device *dev = regmap_get_device(map: data->regmap); |
657 | int ret; |
658 | __be32 tmp = 0; |
659 | s32 adc_press; |
660 | |
661 | /* Read and compensate temperature to get a reading of t_fine */ |
662 | ret = bme680_read_temp(data, NULL); |
663 | if (ret < 0) |
664 | return ret; |
665 | |
666 | ret = regmap_bulk_read(map: data->regmap, BME680_REG_PRESS_MSB, |
667 | val: &tmp, val_count: 3); |
668 | if (ret < 0) { |
669 | dev_err(dev, "failed to read pressure\n" ); |
670 | return ret; |
671 | } |
672 | |
673 | adc_press = be32_to_cpu(tmp) >> 12; |
674 | if (adc_press == BME680_MEAS_SKIPPED) { |
675 | /* reading was skipped */ |
676 | dev_err(dev, "reading pressure skipped\n" ); |
677 | return -EINVAL; |
678 | } |
679 | |
680 | *val = bme680_compensate_press(data, adc_press); |
681 | *val2 = 100; |
682 | return IIO_VAL_FRACTIONAL; |
683 | } |
684 | |
685 | static int bme680_read_humid(struct bme680_data *data, |
686 | int *val, int *val2) |
687 | { |
688 | struct device *dev = regmap_get_device(map: data->regmap); |
689 | int ret; |
690 | __be16 tmp = 0; |
691 | s32 adc_humidity; |
692 | u32 comp_humidity; |
693 | |
694 | /* Read and compensate temperature to get a reading of t_fine */ |
695 | ret = bme680_read_temp(data, NULL); |
696 | if (ret < 0) |
697 | return ret; |
698 | |
699 | ret = regmap_bulk_read(map: data->regmap, BM6880_REG_HUMIDITY_MSB, |
700 | val: &tmp, val_count: sizeof(tmp)); |
701 | if (ret < 0) { |
702 | dev_err(dev, "failed to read humidity\n" ); |
703 | return ret; |
704 | } |
705 | |
706 | adc_humidity = be16_to_cpu(tmp); |
707 | if (adc_humidity == BME680_MEAS_SKIPPED) { |
708 | /* reading was skipped */ |
709 | dev_err(dev, "reading humidity skipped\n" ); |
710 | return -EINVAL; |
711 | } |
712 | comp_humidity = bme680_compensate_humid(data, adc_humid: adc_humidity); |
713 | |
714 | *val = comp_humidity; |
715 | *val2 = 1000; |
716 | return IIO_VAL_FRACTIONAL; |
717 | } |
718 | |
719 | static int bme680_read_gas(struct bme680_data *data, |
720 | int *val) |
721 | { |
722 | struct device *dev = regmap_get_device(map: data->regmap); |
723 | int ret; |
724 | __be16 tmp = 0; |
725 | unsigned int check; |
726 | u16 adc_gas_res; |
727 | u8 gas_range; |
728 | |
729 | /* Set heater settings */ |
730 | ret = bme680_gas_config(data); |
731 | if (ret < 0) { |
732 | dev_err(dev, "failed to set gas config\n" ); |
733 | return ret; |
734 | } |
735 | |
736 | /* set forced mode to trigger measurement */ |
737 | ret = bme680_set_mode(data, mode: true); |
738 | if (ret < 0) |
739 | return ret; |
740 | |
741 | ret = regmap_read(map: data->regmap, BME680_REG_MEAS_STAT_0, val: &check); |
742 | if (check & BME680_GAS_MEAS_BIT) { |
743 | dev_err(dev, "gas measurement incomplete\n" ); |
744 | return -EBUSY; |
745 | } |
746 | |
747 | ret = regmap_read(map: data->regmap, BME680_REG_GAS_R_LSB, val: &check); |
748 | if (ret < 0) { |
749 | dev_err(dev, "failed to read gas_r_lsb register\n" ); |
750 | return ret; |
751 | } |
752 | |
753 | /* |
754 | * occurs if either the gas heating duration was insuffient |
755 | * to reach the target heater temperature or the target |
756 | * heater temperature was too high for the heater sink to |
757 | * reach. |
758 | */ |
759 | if ((check & BME680_GAS_STAB_BIT) == 0) { |
760 | dev_err(dev, "heater failed to reach the target temperature\n" ); |
761 | return -EINVAL; |
762 | } |
763 | |
764 | ret = regmap_bulk_read(map: data->regmap, BME680_REG_GAS_MSB, |
765 | val: &tmp, val_count: sizeof(tmp)); |
766 | if (ret < 0) { |
767 | dev_err(dev, "failed to read gas resistance\n" ); |
768 | return ret; |
769 | } |
770 | |
771 | gas_range = check & BME680_GAS_RANGE_MASK; |
772 | adc_gas_res = be16_to_cpu(tmp) >> BME680_ADC_GAS_RES_SHIFT; |
773 | |
774 | *val = bme680_compensate_gas(data, gas_res_adc: adc_gas_res, gas_range); |
775 | return IIO_VAL_INT; |
776 | } |
777 | |
778 | static int bme680_read_raw(struct iio_dev *indio_dev, |
779 | struct iio_chan_spec const *chan, |
780 | int *val, int *val2, long mask) |
781 | { |
782 | struct bme680_data *data = iio_priv(indio_dev); |
783 | |
784 | switch (mask) { |
785 | case IIO_CHAN_INFO_PROCESSED: |
786 | switch (chan->type) { |
787 | case IIO_TEMP: |
788 | return bme680_read_temp(data, val); |
789 | case IIO_PRESSURE: |
790 | return bme680_read_press(data, val, val2); |
791 | case IIO_HUMIDITYRELATIVE: |
792 | return bme680_read_humid(data, val, val2); |
793 | case IIO_RESISTANCE: |
794 | return bme680_read_gas(data, val); |
795 | default: |
796 | return -EINVAL; |
797 | } |
798 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
799 | switch (chan->type) { |
800 | case IIO_TEMP: |
801 | *val = data->oversampling_temp; |
802 | return IIO_VAL_INT; |
803 | case IIO_PRESSURE: |
804 | *val = data->oversampling_press; |
805 | return IIO_VAL_INT; |
806 | case IIO_HUMIDITYRELATIVE: |
807 | *val = data->oversampling_humid; |
808 | return IIO_VAL_INT; |
809 | default: |
810 | return -EINVAL; |
811 | } |
812 | default: |
813 | return -EINVAL; |
814 | } |
815 | } |
816 | |
817 | static bool bme680_is_valid_oversampling(int rate) |
818 | { |
819 | return (rate > 0 && rate <= 16 && is_power_of_2(n: rate)); |
820 | } |
821 | |
822 | static int bme680_write_raw(struct iio_dev *indio_dev, |
823 | struct iio_chan_spec const *chan, |
824 | int val, int val2, long mask) |
825 | { |
826 | struct bme680_data *data = iio_priv(indio_dev); |
827 | |
828 | if (val2 != 0) |
829 | return -EINVAL; |
830 | |
831 | switch (mask) { |
832 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
833 | { |
834 | if (!bme680_is_valid_oversampling(rate: val)) |
835 | return -EINVAL; |
836 | |
837 | switch (chan->type) { |
838 | case IIO_TEMP: |
839 | data->oversampling_temp = val; |
840 | break; |
841 | case IIO_PRESSURE: |
842 | data->oversampling_press = val; |
843 | break; |
844 | case IIO_HUMIDITYRELATIVE: |
845 | data->oversampling_humid = val; |
846 | break; |
847 | default: |
848 | return -EINVAL; |
849 | } |
850 | |
851 | return bme680_chip_config(data); |
852 | } |
853 | default: |
854 | return -EINVAL; |
855 | } |
856 | } |
857 | |
858 | static const char bme680_oversampling_ratio_show[] = "1 2 4 8 16" ; |
859 | |
860 | static IIO_CONST_ATTR(oversampling_ratio_available, |
861 | bme680_oversampling_ratio_show); |
862 | |
863 | static struct attribute *bme680_attributes[] = { |
864 | &iio_const_attr_oversampling_ratio_available.dev_attr.attr, |
865 | NULL, |
866 | }; |
867 | |
868 | static const struct attribute_group bme680_attribute_group = { |
869 | .attrs = bme680_attributes, |
870 | }; |
871 | |
872 | static const struct iio_info bme680_info = { |
873 | .read_raw = &bme680_read_raw, |
874 | .write_raw = &bme680_write_raw, |
875 | .attrs = &bme680_attribute_group, |
876 | }; |
877 | |
878 | static const char *bme680_match_acpi_device(struct device *dev) |
879 | { |
880 | const struct acpi_device_id *id; |
881 | |
882 | id = acpi_match_device(ids: dev->driver->acpi_match_table, dev); |
883 | if (!id) |
884 | return NULL; |
885 | |
886 | return dev_name(dev); |
887 | } |
888 | |
889 | int bme680_core_probe(struct device *dev, struct regmap *regmap, |
890 | const char *name) |
891 | { |
892 | struct iio_dev *indio_dev; |
893 | struct bme680_data *data; |
894 | unsigned int val; |
895 | int ret; |
896 | |
897 | ret = regmap_write(map: regmap, BME680_REG_SOFT_RESET, |
898 | BME680_CMD_SOFTRESET); |
899 | if (ret < 0) { |
900 | dev_err(dev, "Failed to reset chip\n" ); |
901 | return ret; |
902 | } |
903 | |
904 | ret = regmap_read(map: regmap, BME680_REG_CHIP_ID, val: &val); |
905 | if (ret < 0) { |
906 | dev_err(dev, "Error reading chip ID\n" ); |
907 | return ret; |
908 | } |
909 | |
910 | if (val != BME680_CHIP_ID_VAL) { |
911 | dev_err(dev, "Wrong chip ID, got %x expected %x\n" , |
912 | val, BME680_CHIP_ID_VAL); |
913 | return -ENODEV; |
914 | } |
915 | |
916 | indio_dev = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(*data)); |
917 | if (!indio_dev) |
918 | return -ENOMEM; |
919 | |
920 | if (!name && ACPI_HANDLE(dev)) |
921 | name = bme680_match_acpi_device(dev); |
922 | |
923 | data = iio_priv(indio_dev); |
924 | dev_set_drvdata(dev, data: indio_dev); |
925 | data->regmap = regmap; |
926 | indio_dev->name = name; |
927 | indio_dev->channels = bme680_channels; |
928 | indio_dev->num_channels = ARRAY_SIZE(bme680_channels); |
929 | indio_dev->info = &bme680_info; |
930 | indio_dev->modes = INDIO_DIRECT_MODE; |
931 | |
932 | /* default values for the sensor */ |
933 | data->oversampling_humid = 2; /* 2X oversampling rate */ |
934 | data->oversampling_press = 4; /* 4X oversampling rate */ |
935 | data->oversampling_temp = 8; /* 8X oversampling rate */ |
936 | data->heater_temp = 320; /* degree Celsius */ |
937 | data->heater_dur = 150; /* milliseconds */ |
938 | |
939 | ret = bme680_chip_config(data); |
940 | if (ret < 0) { |
941 | dev_err(dev, "failed to set chip_config data\n" ); |
942 | return ret; |
943 | } |
944 | |
945 | ret = bme680_gas_config(data); |
946 | if (ret < 0) { |
947 | dev_err(dev, "failed to set gas config data\n" ); |
948 | return ret; |
949 | } |
950 | |
951 | ret = bme680_read_calib(data, calib: &data->bme680); |
952 | if (ret < 0) { |
953 | dev_err(dev, |
954 | "failed to read calibration coefficients at probe\n" ); |
955 | return ret; |
956 | } |
957 | |
958 | return devm_iio_device_register(dev, indio_dev); |
959 | } |
960 | EXPORT_SYMBOL_NS_GPL(bme680_core_probe, IIO_BME680); |
961 | |
962 | MODULE_AUTHOR("Himanshu Jha <himanshujha199640@gmail.com>" ); |
963 | MODULE_DESCRIPTION("Bosch BME680 Driver" ); |
964 | MODULE_LICENSE("GPL v2" ); |
965 | |