11b3bd859SHimanshu Jha // SPDX-License-Identifier: GPL-2.0
21b3bd859SHimanshu Jha /*
31b3bd859SHimanshu Jha * Bosch BME680 - Temperature, Pressure, Humidity & Gas Sensor
41b3bd859SHimanshu Jha *
51b3bd859SHimanshu Jha * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH
61b3bd859SHimanshu Jha * Copyright (C) 2018 Himanshu Jha <himanshujha199640@gmail.com>
71b3bd859SHimanshu Jha *
81b3bd859SHimanshu Jha * Datasheet:
91b3bd859SHimanshu Jha * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME680-DS001-00.pdf
101b3bd859SHimanshu Jha */
111b3bd859SHimanshu Jha #include <linux/acpi.h>
121b3bd859SHimanshu Jha #include <linux/bitfield.h>
13*2bc96d4eSVasileios Amoiridis #include <linux/cleanup.h>
14055b4e3dSVasileios Amoiridis #include <linux/delay.h>
151b3bd859SHimanshu Jha #include <linux/device.h>
161b3bd859SHimanshu Jha #include <linux/module.h>
171b3bd859SHimanshu Jha #include <linux/log2.h>
181b3bd859SHimanshu Jha #include <linux/regmap.h>
191b3bd859SHimanshu Jha #include <linux/iio/iio.h>
201b3bd859SHimanshu Jha #include <linux/iio/sysfs.h>
211b3bd859SHimanshu Jha
221b3bd859SHimanshu Jha #include "bme680.h"
231b3bd859SHimanshu Jha
241b3bd859SHimanshu Jha struct bme680_calib {
251b3bd859SHimanshu Jha u16 par_t1;
261b3bd859SHimanshu Jha s16 par_t2;
271b3bd859SHimanshu Jha s8 par_t3;
281b3bd859SHimanshu Jha u16 par_p1;
291b3bd859SHimanshu Jha s16 par_p2;
301b3bd859SHimanshu Jha s8 par_p3;
311b3bd859SHimanshu Jha s16 par_p4;
321b3bd859SHimanshu Jha s16 par_p5;
331b3bd859SHimanshu Jha s8 par_p6;
341b3bd859SHimanshu Jha s8 par_p7;
351b3bd859SHimanshu Jha s16 par_p8;
361b3bd859SHimanshu Jha s16 par_p9;
371b3bd859SHimanshu Jha u8 par_p10;
381b3bd859SHimanshu Jha u16 par_h1;
391b3bd859SHimanshu Jha u16 par_h2;
401b3bd859SHimanshu Jha s8 par_h3;
411b3bd859SHimanshu Jha s8 par_h4;
421b3bd859SHimanshu Jha s8 par_h5;
4393709966SVasileios Amoiridis u8 par_h6;
441b3bd859SHimanshu Jha s8 par_h7;
451b3bd859SHimanshu Jha s8 par_gh1;
461b3bd859SHimanshu Jha s16 par_gh2;
471b3bd859SHimanshu Jha s8 par_gh3;
481b3bd859SHimanshu Jha u8 res_heat_range;
491b3bd859SHimanshu Jha s8 res_heat_val;
501b3bd859SHimanshu Jha s8 range_sw_err;
511b3bd859SHimanshu Jha };
521b3bd859SHimanshu Jha
531b3bd859SHimanshu Jha struct bme680_data {
541b3bd859SHimanshu Jha struct regmap *regmap;
551b3bd859SHimanshu Jha struct bme680_calib bme680;
56*2bc96d4eSVasileios Amoiridis struct mutex lock; /* Protect multiple serial R/W ops to device. */
571b3bd859SHimanshu Jha u8 oversampling_temp;
581b3bd859SHimanshu Jha u8 oversampling_press;
591b3bd859SHimanshu Jha u8 oversampling_humid;
601b3bd859SHimanshu Jha u16 heater_dur;
611b3bd859SHimanshu Jha u16 heater_temp;
621b3bd859SHimanshu Jha /*
631b3bd859SHimanshu Jha * Carryover value from temperature conversion, used in pressure
641b3bd859SHimanshu Jha * and humidity compensation calculations.
651b3bd859SHimanshu Jha */
661b3bd859SHimanshu Jha s32 t_fine;
671b3bd859SHimanshu Jha };
681b3bd859SHimanshu Jha
6973f3bc6dSMike Looijmans static const struct regmap_range bme680_volatile_ranges[] = {
7073f3bc6dSMike Looijmans regmap_reg_range(BME680_REG_MEAS_STAT_0, BME680_REG_GAS_R_LSB),
7173f3bc6dSMike Looijmans regmap_reg_range(BME680_REG_STATUS, BME680_REG_STATUS),
7273f3bc6dSMike Looijmans regmap_reg_range(BME680_T2_LSB_REG, BME680_GH3_REG),
7373f3bc6dSMike Looijmans };
7473f3bc6dSMike Looijmans
7573f3bc6dSMike Looijmans static const struct regmap_access_table bme680_volatile_table = {
7673f3bc6dSMike Looijmans .yes_ranges = bme680_volatile_ranges,
7773f3bc6dSMike Looijmans .n_yes_ranges = ARRAY_SIZE(bme680_volatile_ranges),
7873f3bc6dSMike Looijmans };
7973f3bc6dSMike Looijmans
801b3bd859SHimanshu Jha const struct regmap_config bme680_regmap_config = {
811b3bd859SHimanshu Jha .reg_bits = 8,
821b3bd859SHimanshu Jha .val_bits = 8,
8373f3bc6dSMike Looijmans .max_register = 0xef,
8473f3bc6dSMike Looijmans .volatile_table = &bme680_volatile_table,
8573f3bc6dSMike Looijmans .cache_type = REGCACHE_RBTREE,
861b3bd859SHimanshu Jha };
87146b43d9SJonathan Cameron EXPORT_SYMBOL_NS(bme680_regmap_config, IIO_BME680);
881b3bd859SHimanshu Jha
891b3bd859SHimanshu Jha static const struct iio_chan_spec bme680_channels[] = {
901b3bd859SHimanshu Jha {
911b3bd859SHimanshu Jha .type = IIO_TEMP,
921b3bd859SHimanshu Jha .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
931b3bd859SHimanshu Jha BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
941b3bd859SHimanshu Jha },
951b3bd859SHimanshu Jha {
961b3bd859SHimanshu Jha .type = IIO_PRESSURE,
971b3bd859SHimanshu Jha .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
981b3bd859SHimanshu Jha BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
991b3bd859SHimanshu Jha },
1001b3bd859SHimanshu Jha {
1011b3bd859SHimanshu Jha .type = IIO_HUMIDITYRELATIVE,
1021b3bd859SHimanshu Jha .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
1031b3bd859SHimanshu Jha BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
1041b3bd859SHimanshu Jha },
1051b3bd859SHimanshu Jha {
1061b3bd859SHimanshu Jha .type = IIO_RESISTANCE,
1071b3bd859SHimanshu Jha .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
1081b3bd859SHimanshu Jha },
1091b3bd859SHimanshu Jha };
1101b3bd859SHimanshu Jha
bme680_read_calib(struct bme680_data * data,struct bme680_calib * calib)1111b3bd859SHimanshu Jha static int bme680_read_calib(struct bme680_data *data,
1121b3bd859SHimanshu Jha struct bme680_calib *calib)
1131b3bd859SHimanshu Jha {
1141b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap);
1151b3bd859SHimanshu Jha unsigned int tmp, tmp_msb, tmp_lsb;
1161b3bd859SHimanshu Jha int ret;
1171b3bd859SHimanshu Jha __le16 buf;
1181b3bd859SHimanshu Jha
1191b3bd859SHimanshu Jha /* Temperature related coefficients */
120ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_T1_LSB_REG,
121ce968fb6SJonathan Cameron &buf, sizeof(buf));
1221b3bd859SHimanshu Jha if (ret < 0) {
1231b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_T1_LSB_REG\n");
1241b3bd859SHimanshu Jha return ret;
1251b3bd859SHimanshu Jha }
1261b3bd859SHimanshu Jha calib->par_t1 = le16_to_cpu(buf);
1271b3bd859SHimanshu Jha
128ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_T2_LSB_REG,
129ce968fb6SJonathan Cameron &buf, sizeof(buf));
1301b3bd859SHimanshu Jha if (ret < 0) {
1311b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_T2_LSB_REG\n");
1321b3bd859SHimanshu Jha return ret;
1331b3bd859SHimanshu Jha }
1341b3bd859SHimanshu Jha calib->par_t2 = le16_to_cpu(buf);
1351b3bd859SHimanshu Jha
1361b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_T3_REG, &tmp);
1371b3bd859SHimanshu Jha if (ret < 0) {
1381b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_T3_REG\n");
1391b3bd859SHimanshu Jha return ret;
1401b3bd859SHimanshu Jha }
1411b3bd859SHimanshu Jha calib->par_t3 = tmp;
1421b3bd859SHimanshu Jha
1431b3bd859SHimanshu Jha /* Pressure related coefficients */
144ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_P1_LSB_REG,
145ce968fb6SJonathan Cameron &buf, sizeof(buf));
1461b3bd859SHimanshu Jha if (ret < 0) {
1471b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P1_LSB_REG\n");
1481b3bd859SHimanshu Jha return ret;
1491b3bd859SHimanshu Jha }
1501b3bd859SHimanshu Jha calib->par_p1 = le16_to_cpu(buf);
1511b3bd859SHimanshu Jha
152ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_P2_LSB_REG,
153ce968fb6SJonathan Cameron &buf, sizeof(buf));
1541b3bd859SHimanshu Jha if (ret < 0) {
1551b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P2_LSB_REG\n");
1561b3bd859SHimanshu Jha return ret;
1571b3bd859SHimanshu Jha }
1581b3bd859SHimanshu Jha calib->par_p2 = le16_to_cpu(buf);
1591b3bd859SHimanshu Jha
1601b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_P3_REG, &tmp);
1611b3bd859SHimanshu Jha if (ret < 0) {
1621b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P3_REG\n");
1631b3bd859SHimanshu Jha return ret;
1641b3bd859SHimanshu Jha }
1651b3bd859SHimanshu Jha calib->par_p3 = tmp;
1661b3bd859SHimanshu Jha
167ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_P4_LSB_REG,
168ce968fb6SJonathan Cameron &buf, sizeof(buf));
1691b3bd859SHimanshu Jha if (ret < 0) {
1701b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P4_LSB_REG\n");
1711b3bd859SHimanshu Jha return ret;
1721b3bd859SHimanshu Jha }
1731b3bd859SHimanshu Jha calib->par_p4 = le16_to_cpu(buf);
1741b3bd859SHimanshu Jha
175ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_P5_LSB_REG,
176ce968fb6SJonathan Cameron &buf, sizeof(buf));
1771b3bd859SHimanshu Jha if (ret < 0) {
1781b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P5_LSB_REG\n");
1791b3bd859SHimanshu Jha return ret;
1801b3bd859SHimanshu Jha }
1811b3bd859SHimanshu Jha calib->par_p5 = le16_to_cpu(buf);
1821b3bd859SHimanshu Jha
1831b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_P6_REG, &tmp);
1841b3bd859SHimanshu Jha if (ret < 0) {
1851b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P6_REG\n");
1861b3bd859SHimanshu Jha return ret;
1871b3bd859SHimanshu Jha }
1881b3bd859SHimanshu Jha calib->par_p6 = tmp;
1891b3bd859SHimanshu Jha
1901b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_P7_REG, &tmp);
1911b3bd859SHimanshu Jha if (ret < 0) {
1921b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P7_REG\n");
1931b3bd859SHimanshu Jha return ret;
1941b3bd859SHimanshu Jha }
1951b3bd859SHimanshu Jha calib->par_p7 = tmp;
1961b3bd859SHimanshu Jha
197ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_P8_LSB_REG,
198ce968fb6SJonathan Cameron &buf, sizeof(buf));
1991b3bd859SHimanshu Jha if (ret < 0) {
2001b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P8_LSB_REG\n");
2011b3bd859SHimanshu Jha return ret;
2021b3bd859SHimanshu Jha }
2031b3bd859SHimanshu Jha calib->par_p8 = le16_to_cpu(buf);
2041b3bd859SHimanshu Jha
205ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_P9_LSB_REG,
206ce968fb6SJonathan Cameron &buf, sizeof(buf));
2071b3bd859SHimanshu Jha if (ret < 0) {
2081b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P9_LSB_REG\n");
2091b3bd859SHimanshu Jha return ret;
2101b3bd859SHimanshu Jha }
2111b3bd859SHimanshu Jha calib->par_p9 = le16_to_cpu(buf);
2121b3bd859SHimanshu Jha
2131b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_P10_REG, &tmp);
2141b3bd859SHimanshu Jha if (ret < 0) {
2151b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P10_REG\n");
2161b3bd859SHimanshu Jha return ret;
2171b3bd859SHimanshu Jha }
2181b3bd859SHimanshu Jha calib->par_p10 = tmp;
2191b3bd859SHimanshu Jha
2201b3bd859SHimanshu Jha /* Humidity related coefficients */
2211b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H1_MSB_REG, &tmp_msb);
2221b3bd859SHimanshu Jha if (ret < 0) {
2231b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H1_MSB_REG\n");
2241b3bd859SHimanshu Jha return ret;
2251b3bd859SHimanshu Jha }
2261b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H1_LSB_REG, &tmp_lsb);
2271b3bd859SHimanshu Jha if (ret < 0) {
2281b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H1_LSB_REG\n");
2291b3bd859SHimanshu Jha return ret;
2301b3bd859SHimanshu Jha }
2311b3bd859SHimanshu Jha calib->par_h1 = (tmp_msb << BME680_HUM_REG_SHIFT_VAL) |
232a24b4d70SDavid Frey (tmp_lsb & BME680_BIT_H1_DATA_MASK);
2331b3bd859SHimanshu Jha
2341b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H2_MSB_REG, &tmp_msb);
2351b3bd859SHimanshu Jha if (ret < 0) {
2361b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H2_MSB_REG\n");
2371b3bd859SHimanshu Jha return ret;
2381b3bd859SHimanshu Jha }
2391b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H2_LSB_REG, &tmp_lsb);
2401b3bd859SHimanshu Jha if (ret < 0) {
2411b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H2_LSB_REG\n");
2421b3bd859SHimanshu Jha return ret;
2431b3bd859SHimanshu Jha }
2441b3bd859SHimanshu Jha calib->par_h2 = (tmp_msb << BME680_HUM_REG_SHIFT_VAL) |
2451b3bd859SHimanshu Jha (tmp_lsb >> BME680_HUM_REG_SHIFT_VAL);
2461b3bd859SHimanshu Jha
2471b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H3_REG, &tmp);
2481b3bd859SHimanshu Jha if (ret < 0) {
2491b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H3_REG\n");
2501b3bd859SHimanshu Jha return ret;
2511b3bd859SHimanshu Jha }
2521b3bd859SHimanshu Jha calib->par_h3 = tmp;
2531b3bd859SHimanshu Jha
2541b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H4_REG, &tmp);
2551b3bd859SHimanshu Jha if (ret < 0) {
2561b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H4_REG\n");
2571b3bd859SHimanshu Jha return ret;
2581b3bd859SHimanshu Jha }
2591b3bd859SHimanshu Jha calib->par_h4 = tmp;
2601b3bd859SHimanshu Jha
2611b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H5_REG, &tmp);
2621b3bd859SHimanshu Jha if (ret < 0) {
2631b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H5_REG\n");
2641b3bd859SHimanshu Jha return ret;
2651b3bd859SHimanshu Jha }
2661b3bd859SHimanshu Jha calib->par_h5 = tmp;
2671b3bd859SHimanshu Jha
2681b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H6_REG, &tmp);
2691b3bd859SHimanshu Jha if (ret < 0) {
2701b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H6_REG\n");
2711b3bd859SHimanshu Jha return ret;
2721b3bd859SHimanshu Jha }
2731b3bd859SHimanshu Jha calib->par_h6 = tmp;
2741b3bd859SHimanshu Jha
2751b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H7_REG, &tmp);
2761b3bd859SHimanshu Jha if (ret < 0) {
2771b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H7_REG\n");
2781b3bd859SHimanshu Jha return ret;
2791b3bd859SHimanshu Jha }
2801b3bd859SHimanshu Jha calib->par_h7 = tmp;
2811b3bd859SHimanshu Jha
2821b3bd859SHimanshu Jha /* Gas heater related coefficients */
2831b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_GH1_REG, &tmp);
2841b3bd859SHimanshu Jha if (ret < 0) {
2851b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_GH1_REG\n");
2861b3bd859SHimanshu Jha return ret;
2871b3bd859SHimanshu Jha }
2881b3bd859SHimanshu Jha calib->par_gh1 = tmp;
2891b3bd859SHimanshu Jha
290ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_GH2_LSB_REG,
291ce968fb6SJonathan Cameron &buf, sizeof(buf));
2921b3bd859SHimanshu Jha if (ret < 0) {
2931b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_GH2_LSB_REG\n");
2941b3bd859SHimanshu Jha return ret;
2951b3bd859SHimanshu Jha }
2961b3bd859SHimanshu Jha calib->par_gh2 = le16_to_cpu(buf);
2971b3bd859SHimanshu Jha
2981b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_GH3_REG, &tmp);
2991b3bd859SHimanshu Jha if (ret < 0) {
3001b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_GH3_REG\n");
3011b3bd859SHimanshu Jha return ret;
3021b3bd859SHimanshu Jha }
3031b3bd859SHimanshu Jha calib->par_gh3 = tmp;
3041b3bd859SHimanshu Jha
3051b3bd859SHimanshu Jha /* Other coefficients */
3061b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_REG_RES_HEAT_RANGE, &tmp);
3071b3bd859SHimanshu Jha if (ret < 0) {
3081b3bd859SHimanshu Jha dev_err(dev, "failed to read resistance heat range\n");
3091b3bd859SHimanshu Jha return ret;
3101b3bd859SHimanshu Jha }
3113dcb60cdSDavid Frey calib->res_heat_range = FIELD_GET(BME680_RHRANGE_MASK, tmp);
3121b3bd859SHimanshu Jha
3131b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_REG_RES_HEAT_VAL, &tmp);
3141b3bd859SHimanshu Jha if (ret < 0) {
3151b3bd859SHimanshu Jha dev_err(dev, "failed to read resistance heat value\n");
3161b3bd859SHimanshu Jha return ret;
3171b3bd859SHimanshu Jha }
3181b3bd859SHimanshu Jha calib->res_heat_val = tmp;
3191b3bd859SHimanshu Jha
3201b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_REG_RANGE_SW_ERR, &tmp);
3211b3bd859SHimanshu Jha if (ret < 0) {
3221b3bd859SHimanshu Jha dev_err(dev, "failed to read range software error\n");
3231b3bd859SHimanshu Jha return ret;
3241b3bd859SHimanshu Jha }
3253dcb60cdSDavid Frey calib->range_sw_err = FIELD_GET(BME680_RSERROR_MASK, tmp);
3261b3bd859SHimanshu Jha
3271b3bd859SHimanshu Jha return 0;
3281b3bd859SHimanshu Jha }
3291b3bd859SHimanshu Jha
3301b3bd859SHimanshu Jha /*
3311b3bd859SHimanshu Jha * Taken from Bosch BME680 API:
3321b3bd859SHimanshu Jha * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L876
3331b3bd859SHimanshu Jha *
3341b3bd859SHimanshu Jha * Returns temperature measurement in DegC, resolutions is 0.01 DegC. Therefore,
3351b3bd859SHimanshu Jha * output value of "3233" represents 32.33 DegC.
3361b3bd859SHimanshu Jha */
bme680_compensate_temp(struct bme680_data * data,s32 adc_temp)3371b3bd859SHimanshu Jha static s16 bme680_compensate_temp(struct bme680_data *data,
3381b3bd859SHimanshu Jha s32 adc_temp)
3391b3bd859SHimanshu Jha {
3401b3bd859SHimanshu Jha struct bme680_calib *calib = &data->bme680;
3411b3bd859SHimanshu Jha s64 var1, var2, var3;
3421b3bd859SHimanshu Jha s16 calc_temp;
3431b3bd859SHimanshu Jha
34473f3bc6dSMike Looijmans /* If the calibration is invalid, attempt to reload it */
34573f3bc6dSMike Looijmans if (!calib->par_t2)
34673f3bc6dSMike Looijmans bme680_read_calib(data, calib);
34773f3bc6dSMike Looijmans
348b5967393SVasileios Amoiridis var1 = (adc_temp >> 3) - ((s32)calib->par_t1 << 1);
3491b3bd859SHimanshu Jha var2 = (var1 * calib->par_t2) >> 11;
3501b3bd859SHimanshu Jha var3 = ((var1 >> 1) * (var1 >> 1)) >> 12;
351b5967393SVasileios Amoiridis var3 = (var3 * ((s32)calib->par_t3 << 4)) >> 14;
3521b3bd859SHimanshu Jha data->t_fine = var2 + var3;
3531b3bd859SHimanshu Jha calc_temp = (data->t_fine * 5 + 128) >> 8;
3541b3bd859SHimanshu Jha
3551b3bd859SHimanshu Jha return calc_temp;
3561b3bd859SHimanshu Jha }
3571b3bd859SHimanshu Jha
3581b3bd859SHimanshu Jha /*
3591b3bd859SHimanshu Jha * Taken from Bosch BME680 API:
3601b3bd859SHimanshu Jha * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L896
3611b3bd859SHimanshu Jha *
3621b3bd859SHimanshu Jha * Returns pressure measurement in Pa. Output value of "97356" represents
3631b3bd859SHimanshu Jha * 97356 Pa = 973.56 hPa.
3641b3bd859SHimanshu Jha */
bme680_compensate_press(struct bme680_data * data,u32 adc_press)3651b3bd859SHimanshu Jha static u32 bme680_compensate_press(struct bme680_data *data,
3661b3bd859SHimanshu Jha u32 adc_press)
3671b3bd859SHimanshu Jha {
3681b3bd859SHimanshu Jha struct bme680_calib *calib = &data->bme680;
3691b3bd859SHimanshu Jha s32 var1, var2, var3, press_comp;
3701b3bd859SHimanshu Jha
3711b3bd859SHimanshu Jha var1 = (data->t_fine >> 1) - 64000;
3721b3bd859SHimanshu Jha var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * calib->par_p6) >> 2;
3731b3bd859SHimanshu Jha var2 = var2 + (var1 * calib->par_p5 << 1);
374b5967393SVasileios Amoiridis var2 = (var2 >> 2) + ((s32)calib->par_p4 << 16);
3751b3bd859SHimanshu Jha var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) *
376b5967393SVasileios Amoiridis ((s32)calib->par_p3 << 5)) >> 3) +
3771b3bd859SHimanshu Jha ((calib->par_p2 * var1) >> 1);
3781b3bd859SHimanshu Jha var1 = var1 >> 18;
3791b3bd859SHimanshu Jha var1 = ((32768 + var1) * calib->par_p1) >> 15;
3801b3bd859SHimanshu Jha press_comp = 1048576 - adc_press;
3811b3bd859SHimanshu Jha press_comp = ((press_comp - (var2 >> 12)) * 3125);
3821b3bd859SHimanshu Jha
3831b3bd859SHimanshu Jha if (press_comp >= BME680_MAX_OVERFLOW_VAL)
3841b3bd859SHimanshu Jha press_comp = ((press_comp / (u32)var1) << 1);
3851b3bd859SHimanshu Jha else
3861b3bd859SHimanshu Jha press_comp = ((press_comp << 1) / (u32)var1);
3871b3bd859SHimanshu Jha
3881b3bd859SHimanshu Jha var1 = (calib->par_p9 * (((press_comp >> 3) *
3891b3bd859SHimanshu Jha (press_comp >> 3)) >> 13)) >> 12;
3901b3bd859SHimanshu Jha var2 = ((press_comp >> 2) * calib->par_p8) >> 13;
3911b3bd859SHimanshu Jha var3 = ((press_comp >> 8) * (press_comp >> 8) *
3921b3bd859SHimanshu Jha (press_comp >> 8) * calib->par_p10) >> 17;
3931b3bd859SHimanshu Jha
394b5967393SVasileios Amoiridis press_comp += (var1 + var2 + var3 + ((s32)calib->par_p7 << 7)) >> 4;
3951b3bd859SHimanshu Jha
3961b3bd859SHimanshu Jha return press_comp;
3971b3bd859SHimanshu Jha }
3981b3bd859SHimanshu Jha
3991b3bd859SHimanshu Jha /*
4001b3bd859SHimanshu Jha * Taken from Bosch BME680 API:
4011b3bd859SHimanshu Jha * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L937
4021b3bd859SHimanshu Jha *
4031b3bd859SHimanshu Jha * Returns humidity measurement in percent, resolution is 0.001 percent. Output
4041b3bd859SHimanshu Jha * value of "43215" represents 43.215 %rH.
4051b3bd859SHimanshu Jha */
bme680_compensate_humid(struct bme680_data * data,u16 adc_humid)4061b3bd859SHimanshu Jha static u32 bme680_compensate_humid(struct bme680_data *data,
4071b3bd859SHimanshu Jha u16 adc_humid)
4081b3bd859SHimanshu Jha {
4091b3bd859SHimanshu Jha struct bme680_calib *calib = &data->bme680;
4101b3bd859SHimanshu Jha s32 var1, var2, var3, var4, var5, var6, temp_scaled, calc_hum;
4111b3bd859SHimanshu Jha
4121b3bd859SHimanshu Jha temp_scaled = (data->t_fine * 5 + 128) >> 8;
4131b3bd859SHimanshu Jha var1 = (adc_humid - ((s32) ((s32) calib->par_h1 * 16))) -
4141b3bd859SHimanshu Jha (((temp_scaled * (s32) calib->par_h3) / 100) >> 1);
4151b3bd859SHimanshu Jha var2 = ((s32) calib->par_h2 *
4161b3bd859SHimanshu Jha (((temp_scaled * calib->par_h4) / 100) +
4171b3bd859SHimanshu Jha (((temp_scaled * ((temp_scaled * calib->par_h5) / 100))
4181b3bd859SHimanshu Jha >> 6) / 100) + (1 << 14))) >> 10;
4191b3bd859SHimanshu Jha var3 = var1 * var2;
420b5967393SVasileios Amoiridis var4 = (s32)calib->par_h6 << 7;
4211b3bd859SHimanshu Jha var4 = (var4 + ((temp_scaled * calib->par_h7) / 100)) >> 4;
4221b3bd859SHimanshu Jha var5 = ((var3 >> 14) * (var3 >> 14)) >> 10;
4231b3bd859SHimanshu Jha var6 = (var4 * var5) >> 1;
4241b3bd859SHimanshu Jha calc_hum = (((var3 + var6) >> 10) * 1000) >> 12;
4251b3bd859SHimanshu Jha
4268a0ae7d8SDavid Frey calc_hum = clamp(calc_hum, 0, 100000); /* clamp between 0-100 %rH */
4271b3bd859SHimanshu Jha
4281b3bd859SHimanshu Jha return calc_hum;
4291b3bd859SHimanshu Jha }
4301b3bd859SHimanshu Jha
4311b3bd859SHimanshu Jha /*
4321b3bd859SHimanshu Jha * Taken from Bosch BME680 API:
4331b3bd859SHimanshu Jha * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L973
4341b3bd859SHimanshu Jha *
4351b3bd859SHimanshu Jha * Returns gas measurement in Ohm. Output value of "82986" represent 82986 ohms.
4361b3bd859SHimanshu Jha */
bme680_compensate_gas(struct bme680_data * data,u16 gas_res_adc,u8 gas_range)4371b3bd859SHimanshu Jha static u32 bme680_compensate_gas(struct bme680_data *data, u16 gas_res_adc,
4381b3bd859SHimanshu Jha u8 gas_range)
4391b3bd859SHimanshu Jha {
4401b3bd859SHimanshu Jha struct bme680_calib *calib = &data->bme680;
4411b3bd859SHimanshu Jha s64 var1;
4421b3bd859SHimanshu Jha u64 var2;
4431b3bd859SHimanshu Jha s64 var3;
4441b3bd859SHimanshu Jha u32 calc_gas_res;
4451b3bd859SHimanshu Jha
4461b3bd859SHimanshu Jha /* Look up table for the possible gas range values */
4471b3bd859SHimanshu Jha const u32 lookupTable[16] = {2147483647u, 2147483647u,
4481b3bd859SHimanshu Jha 2147483647u, 2147483647u, 2147483647u,
4491b3bd859SHimanshu Jha 2126008810u, 2147483647u, 2130303777u,
4501b3bd859SHimanshu Jha 2147483647u, 2147483647u, 2143188679u,
4511b3bd859SHimanshu Jha 2136746228u, 2147483647u, 2126008810u,
4521b3bd859SHimanshu Jha 2147483647u, 2147483647u};
4531b3bd859SHimanshu Jha
4541b3bd859SHimanshu Jha var1 = ((1340 + (5 * (s64) calib->range_sw_err)) *
4551b3bd859SHimanshu Jha ((s64) lookupTable[gas_range])) >> 16;
4561b3bd859SHimanshu Jha var2 = ((gas_res_adc << 15) - 16777216) + var1;
4571b3bd859SHimanshu Jha var3 = ((125000 << (15 - gas_range)) * var1) >> 9;
4581b3bd859SHimanshu Jha var3 += (var2 >> 1);
4591b3bd859SHimanshu Jha calc_gas_res = div64_s64(var3, (s64) var2);
4601b3bd859SHimanshu Jha
4611b3bd859SHimanshu Jha return calc_gas_res;
4621b3bd859SHimanshu Jha }
4631b3bd859SHimanshu Jha
4641b3bd859SHimanshu Jha /*
4651b3bd859SHimanshu Jha * Taken from Bosch BME680 API:
4661b3bd859SHimanshu Jha * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L1002
4671b3bd859SHimanshu Jha */
bme680_calc_heater_res(struct bme680_data * data,u16 temp)4681b3bd859SHimanshu Jha static u8 bme680_calc_heater_res(struct bme680_data *data, u16 temp)
4691b3bd859SHimanshu Jha {
4701b3bd859SHimanshu Jha struct bme680_calib *calib = &data->bme680;
4711b3bd859SHimanshu Jha s32 var1, var2, var3, var4, var5, heatr_res_x100;
4721b3bd859SHimanshu Jha u8 heatr_res;
4731b3bd859SHimanshu Jha
4741b3bd859SHimanshu Jha if (temp > 400) /* Cap temperature */
4751b3bd859SHimanshu Jha temp = 400;
4761b3bd859SHimanshu Jha
4771b3bd859SHimanshu Jha var1 = (((s32) BME680_AMB_TEMP * calib->par_gh3) / 1000) * 256;
4781b3bd859SHimanshu Jha var2 = (calib->par_gh1 + 784) * (((((calib->par_gh2 + 154009) *
4791b3bd859SHimanshu Jha temp * 5) / 100)
4801b3bd859SHimanshu Jha + 3276800) / 10);
4811b3bd859SHimanshu Jha var3 = var1 + (var2 / 2);
4821b3bd859SHimanshu Jha var4 = (var3 / (calib->res_heat_range + 4));
4831b3bd859SHimanshu Jha var5 = 131 * calib->res_heat_val + 65536;
4841b3bd859SHimanshu Jha heatr_res_x100 = ((var4 / var5) - 250) * 34;
485166549bbSLars-Peter Clausen heatr_res = DIV_ROUND_CLOSEST(heatr_res_x100, 100);
4861b3bd859SHimanshu Jha
4871b3bd859SHimanshu Jha return heatr_res;
4881b3bd859SHimanshu Jha }
4891b3bd859SHimanshu Jha
4901b3bd859SHimanshu Jha /*
4911b3bd859SHimanshu Jha * Taken from Bosch BME680 API:
4921b3bd859SHimanshu Jha * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L1188
4931b3bd859SHimanshu Jha */
bme680_calc_heater_dur(u16 dur)4941b3bd859SHimanshu Jha static u8 bme680_calc_heater_dur(u16 dur)
4951b3bd859SHimanshu Jha {
4961b3bd859SHimanshu Jha u8 durval, factor = 0;
4971b3bd859SHimanshu Jha
4981b3bd859SHimanshu Jha if (dur >= 0xfc0) {
4991b3bd859SHimanshu Jha durval = 0xff; /* Max duration */
5001b3bd859SHimanshu Jha } else {
5011b3bd859SHimanshu Jha while (dur > 0x3F) {
5021b3bd859SHimanshu Jha dur = dur / 4;
5031b3bd859SHimanshu Jha factor += 1;
5041b3bd859SHimanshu Jha }
5051b3bd859SHimanshu Jha durval = dur + (factor * 64);
5061b3bd859SHimanshu Jha }
5071b3bd859SHimanshu Jha
5081b3bd859SHimanshu Jha return durval;
5091b3bd859SHimanshu Jha }
5101b3bd859SHimanshu Jha
bme680_set_mode(struct bme680_data * data,bool mode)5111b3bd859SHimanshu Jha static int bme680_set_mode(struct bme680_data *data, bool mode)
5121b3bd859SHimanshu Jha {
5131b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap);
5141b3bd859SHimanshu Jha int ret;
5151b3bd859SHimanshu Jha
5161b3bd859SHimanshu Jha if (mode) {
5171b3bd859SHimanshu Jha ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
5181b3bd859SHimanshu Jha BME680_MODE_MASK, BME680_MODE_FORCED);
5191b3bd859SHimanshu Jha if (ret < 0)
5201b3bd859SHimanshu Jha dev_err(dev, "failed to set forced mode\n");
5211b3bd859SHimanshu Jha
5221b3bd859SHimanshu Jha } else {
5231b3bd859SHimanshu Jha ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
5241b3bd859SHimanshu Jha BME680_MODE_MASK, BME680_MODE_SLEEP);
5251b3bd859SHimanshu Jha if (ret < 0)
5261b3bd859SHimanshu Jha dev_err(dev, "failed to set sleep mode\n");
5271b3bd859SHimanshu Jha
5281b3bd859SHimanshu Jha }
5291b3bd859SHimanshu Jha
5301b3bd859SHimanshu Jha return ret;
5311b3bd859SHimanshu Jha }
5321b3bd859SHimanshu Jha
bme680_oversampling_to_reg(u8 val)53379fd571bSDavid Frey static u8 bme680_oversampling_to_reg(u8 val)
53479fd571bSDavid Frey {
53579fd571bSDavid Frey return ilog2(val) + 1;
53679fd571bSDavid Frey }
53779fd571bSDavid Frey
538055b4e3dSVasileios Amoiridis /*
539055b4e3dSVasileios Amoiridis * Taken from Bosch BME680 API:
540055b4e3dSVasileios Amoiridis * https://github.com/boschsensortec/BME68x_SensorAPI/blob/v4.4.8/bme68x.c#L490
541055b4e3dSVasileios Amoiridis */
bme680_wait_for_eoc(struct bme680_data * data)542055b4e3dSVasileios Amoiridis static int bme680_wait_for_eoc(struct bme680_data *data)
543055b4e3dSVasileios Amoiridis {
544055b4e3dSVasileios Amoiridis struct device *dev = regmap_get_device(data->regmap);
545055b4e3dSVasileios Amoiridis unsigned int check;
546055b4e3dSVasileios Amoiridis int ret;
547055b4e3dSVasileios Amoiridis /*
548055b4e3dSVasileios Amoiridis * (Sum of oversampling ratios * time per oversampling) +
549055b4e3dSVasileios Amoiridis * TPH measurement + gas measurement + wait transition from forced mode
550055b4e3dSVasileios Amoiridis * + heater duration
551055b4e3dSVasileios Amoiridis */
552055b4e3dSVasileios Amoiridis int wait_eoc_us = ((data->oversampling_temp + data->oversampling_press +
553055b4e3dSVasileios Amoiridis data->oversampling_humid) * 1936) + (477 * 4) +
554055b4e3dSVasileios Amoiridis (477 * 5) + 1000 + (data->heater_dur * 1000);
555055b4e3dSVasileios Amoiridis
556055b4e3dSVasileios Amoiridis usleep_range(wait_eoc_us, wait_eoc_us + 100);
557055b4e3dSVasileios Amoiridis
558055b4e3dSVasileios Amoiridis ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &check);
559055b4e3dSVasileios Amoiridis if (ret) {
560055b4e3dSVasileios Amoiridis dev_err(dev, "failed to read measurement status register.\n");
561055b4e3dSVasileios Amoiridis return ret;
562055b4e3dSVasileios Amoiridis }
563055b4e3dSVasileios Amoiridis if (check & BME680_MEAS_BIT) {
564055b4e3dSVasileios Amoiridis dev_err(dev, "Device measurement cycle incomplete.\n");
565055b4e3dSVasileios Amoiridis return -EBUSY;
566055b4e3dSVasileios Amoiridis }
567055b4e3dSVasileios Amoiridis if (!(check & BME680_NEW_DATA_BIT)) {
568055b4e3dSVasileios Amoiridis dev_err(dev, "No new data available from the device.\n");
569055b4e3dSVasileios Amoiridis return -ENODATA;
570055b4e3dSVasileios Amoiridis }
571055b4e3dSVasileios Amoiridis
572055b4e3dSVasileios Amoiridis return 0;
573055b4e3dSVasileios Amoiridis }
574055b4e3dSVasileios Amoiridis
bme680_chip_config(struct bme680_data * data)5751b3bd859SHimanshu Jha static int bme680_chip_config(struct bme680_data *data)
5761b3bd859SHimanshu Jha {
5771b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap);
5781b3bd859SHimanshu Jha int ret;
57979fd571bSDavid Frey u8 osrs;
58079fd571bSDavid Frey
58179fd571bSDavid Frey osrs = FIELD_PREP(
58279fd571bSDavid Frey BME680_OSRS_HUMIDITY_MASK,
58379fd571bSDavid Frey bme680_oversampling_to_reg(data->oversampling_humid));
5841b3bd859SHimanshu Jha /*
5851b3bd859SHimanshu Jha * Highly recommended to set oversampling of humidity before
5861b3bd859SHimanshu Jha * temperature/pressure oversampling.
5871b3bd859SHimanshu Jha */
5881b3bd859SHimanshu Jha ret = regmap_update_bits(data->regmap, BME680_REG_CTRL_HUMIDITY,
5891b3bd859SHimanshu Jha BME680_OSRS_HUMIDITY_MASK, osrs);
5901b3bd859SHimanshu Jha if (ret < 0) {
5911b3bd859SHimanshu Jha dev_err(dev, "failed to write ctrl_hum register\n");
5921b3bd859SHimanshu Jha return ret;
5931b3bd859SHimanshu Jha }
5941b3bd859SHimanshu Jha
5951b3bd859SHimanshu Jha /* IIR filter settings */
5961b3bd859SHimanshu Jha ret = regmap_update_bits(data->regmap, BME680_REG_CONFIG,
5971b3bd859SHimanshu Jha BME680_FILTER_MASK,
5981b3bd859SHimanshu Jha BME680_FILTER_COEFF_VAL);
5991b3bd859SHimanshu Jha if (ret < 0) {
6001b3bd859SHimanshu Jha dev_err(dev, "failed to write config register\n");
6011b3bd859SHimanshu Jha return ret;
6021b3bd859SHimanshu Jha }
6031b3bd859SHimanshu Jha
60479fd571bSDavid Frey osrs = FIELD_PREP(BME680_OSRS_TEMP_MASK,
60579fd571bSDavid Frey bme680_oversampling_to_reg(data->oversampling_temp)) |
60679fd571bSDavid Frey FIELD_PREP(BME680_OSRS_PRESS_MASK,
60779fd571bSDavid Frey bme680_oversampling_to_reg(data->oversampling_press));
6081b3bd859SHimanshu Jha ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
60979fd571bSDavid Frey BME680_OSRS_TEMP_MASK | BME680_OSRS_PRESS_MASK,
6101b3bd859SHimanshu Jha osrs);
6111b3bd859SHimanshu Jha if (ret < 0)
6121b3bd859SHimanshu Jha dev_err(dev, "failed to write ctrl_meas register\n");
6131b3bd859SHimanshu Jha
6141b3bd859SHimanshu Jha return ret;
6151b3bd859SHimanshu Jha }
6161b3bd859SHimanshu Jha
bme680_gas_config(struct bme680_data * data)6171b3bd859SHimanshu Jha static int bme680_gas_config(struct bme680_data *data)
6181b3bd859SHimanshu Jha {
6191b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap);
6201b3bd859SHimanshu Jha int ret;
6211b3bd859SHimanshu Jha u8 heatr_res, heatr_dur;
6221b3bd859SHimanshu Jha
6231b3bd859SHimanshu Jha heatr_res = bme680_calc_heater_res(data, data->heater_temp);
6241b3bd859SHimanshu Jha
6251b3bd859SHimanshu Jha /* set target heater temperature */
6261b3bd859SHimanshu Jha ret = regmap_write(data->regmap, BME680_REG_RES_HEAT_0, heatr_res);
6271b3bd859SHimanshu Jha if (ret < 0) {
6281b3bd859SHimanshu Jha dev_err(dev, "failed to write res_heat_0 register\n");
6291b3bd859SHimanshu Jha return ret;
6301b3bd859SHimanshu Jha }
6311b3bd859SHimanshu Jha
6321b3bd859SHimanshu Jha heatr_dur = bme680_calc_heater_dur(data->heater_dur);
6331b3bd859SHimanshu Jha
6341b3bd859SHimanshu Jha /* set target heating duration */
6351b3bd859SHimanshu Jha ret = regmap_write(data->regmap, BME680_REG_GAS_WAIT_0, heatr_dur);
6361b3bd859SHimanshu Jha if (ret < 0) {
6375e457296SColin Ian King dev_err(dev, "failed to write gas_wait_0 register\n");
6381b3bd859SHimanshu Jha return ret;
6391b3bd859SHimanshu Jha }
6401b3bd859SHimanshu Jha
6411691d4caSDavid Frey /* Enable the gas sensor and select heater profile set-point 0 */
6421b3bd859SHimanshu Jha ret = regmap_update_bits(data->regmap, BME680_REG_CTRL_GAS_1,
6431b3bd859SHimanshu Jha BME680_RUN_GAS_MASK | BME680_NB_CONV_MASK,
6441691d4caSDavid Frey FIELD_PREP(BME680_RUN_GAS_MASK, 1) |
6451691d4caSDavid Frey FIELD_PREP(BME680_NB_CONV_MASK, 0));
6461b3bd859SHimanshu Jha if (ret < 0)
6471b3bd859SHimanshu Jha dev_err(dev, "failed to write ctrl_gas_1 register\n");
6481b3bd859SHimanshu Jha
6491b3bd859SHimanshu Jha return ret;
6501b3bd859SHimanshu Jha }
6511b3bd859SHimanshu Jha
bme680_read_temp(struct bme680_data * data,int * val)6529436f45dSMike Looijmans static int bme680_read_temp(struct bme680_data *data, int *val)
6531b3bd859SHimanshu Jha {
6541b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap);
6551b3bd859SHimanshu Jha int ret;
6561b3bd859SHimanshu Jha __be32 tmp = 0;
6571b3bd859SHimanshu Jha s32 adc_temp;
6581b3bd859SHimanshu Jha s16 comp_temp;
6591b3bd859SHimanshu Jha
6601b3bd859SHimanshu Jha /* set forced mode to trigger measurement */
6611b3bd859SHimanshu Jha ret = bme680_set_mode(data, true);
6621b3bd859SHimanshu Jha if (ret < 0)
6631b3bd859SHimanshu Jha return ret;
6641b3bd859SHimanshu Jha
665055b4e3dSVasileios Amoiridis ret = bme680_wait_for_eoc(data);
666055b4e3dSVasileios Amoiridis if (ret)
667055b4e3dSVasileios Amoiridis return ret;
668055b4e3dSVasileios Amoiridis
6691b3bd859SHimanshu Jha ret = regmap_bulk_read(data->regmap, BME680_REG_TEMP_MSB,
670ce968fb6SJonathan Cameron &tmp, 3);
6711b3bd859SHimanshu Jha if (ret < 0) {
6721b3bd859SHimanshu Jha dev_err(dev, "failed to read temperature\n");
6731b3bd859SHimanshu Jha return ret;
6741b3bd859SHimanshu Jha }
6751b3bd859SHimanshu Jha
6761b3bd859SHimanshu Jha adc_temp = be32_to_cpu(tmp) >> 12;
6771b3bd859SHimanshu Jha if (adc_temp == BME680_MEAS_SKIPPED) {
6781b3bd859SHimanshu Jha /* reading was skipped */
6791b3bd859SHimanshu Jha dev_err(dev, "reading temperature skipped\n");
6801b3bd859SHimanshu Jha return -EINVAL;
6811b3bd859SHimanshu Jha }
6821b3bd859SHimanshu Jha comp_temp = bme680_compensate_temp(data, adc_temp);
6831b3bd859SHimanshu Jha /*
6841b3bd859SHimanshu Jha * val might be NULL if we're called by the read_press/read_humid
68570db0e93SJulia Lawall * routine which is called to get t_fine value used in
6861b3bd859SHimanshu Jha * compensate_press/compensate_humid to get compensated
6871b3bd859SHimanshu Jha * pressure/humidity readings.
6881b3bd859SHimanshu Jha */
6899436f45dSMike Looijmans if (val) {
6909436f45dSMike Looijmans *val = comp_temp * 10; /* Centidegrees to millidegrees */
6919436f45dSMike Looijmans return IIO_VAL_INT;
6921b3bd859SHimanshu Jha }
6931b3bd859SHimanshu Jha
6941b3bd859SHimanshu Jha return ret;
6951b3bd859SHimanshu Jha }
6961b3bd859SHimanshu Jha
bme680_read_press(struct bme680_data * data,int * val,int * val2)6971b3bd859SHimanshu Jha static int bme680_read_press(struct bme680_data *data,
6981b3bd859SHimanshu Jha int *val, int *val2)
6991b3bd859SHimanshu Jha {
7001b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap);
7011b3bd859SHimanshu Jha int ret;
7021b3bd859SHimanshu Jha __be32 tmp = 0;
7031b3bd859SHimanshu Jha s32 adc_press;
7041b3bd859SHimanshu Jha
7051b3bd859SHimanshu Jha /* Read and compensate temperature to get a reading of t_fine */
7069436f45dSMike Looijmans ret = bme680_read_temp(data, NULL);
7071b3bd859SHimanshu Jha if (ret < 0)
7081b3bd859SHimanshu Jha return ret;
7091b3bd859SHimanshu Jha
7101b3bd859SHimanshu Jha ret = regmap_bulk_read(data->regmap, BME680_REG_PRESS_MSB,
711ce968fb6SJonathan Cameron &tmp, 3);
7121b3bd859SHimanshu Jha if (ret < 0) {
7131b3bd859SHimanshu Jha dev_err(dev, "failed to read pressure\n");
7141b3bd859SHimanshu Jha return ret;
7151b3bd859SHimanshu Jha }
7161b3bd859SHimanshu Jha
7171b3bd859SHimanshu Jha adc_press = be32_to_cpu(tmp) >> 12;
7181b3bd859SHimanshu Jha if (adc_press == BME680_MEAS_SKIPPED) {
7191b3bd859SHimanshu Jha /* reading was skipped */
7201b3bd859SHimanshu Jha dev_err(dev, "reading pressure skipped\n");
7211b3bd859SHimanshu Jha return -EINVAL;
7221b3bd859SHimanshu Jha }
7231b3bd859SHimanshu Jha
7241b3bd859SHimanshu Jha *val = bme680_compensate_press(data, adc_press);
72513382889SVasileios Amoiridis *val2 = 1000;
7261b3bd859SHimanshu Jha return IIO_VAL_FRACTIONAL;
7271b3bd859SHimanshu Jha }
7281b3bd859SHimanshu Jha
bme680_read_humid(struct bme680_data * data,int * val,int * val2)7291b3bd859SHimanshu Jha static int bme680_read_humid(struct bme680_data *data,
7301b3bd859SHimanshu Jha int *val, int *val2)
7311b3bd859SHimanshu Jha {
7321b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap);
7331b3bd859SHimanshu Jha int ret;
7341b3bd859SHimanshu Jha __be16 tmp = 0;
7351b3bd859SHimanshu Jha s32 adc_humidity;
7361b3bd859SHimanshu Jha u32 comp_humidity;
7371b3bd859SHimanshu Jha
7381b3bd859SHimanshu Jha /* Read and compensate temperature to get a reading of t_fine */
7399436f45dSMike Looijmans ret = bme680_read_temp(data, NULL);
7401b3bd859SHimanshu Jha if (ret < 0)
7411b3bd859SHimanshu Jha return ret;
7421b3bd859SHimanshu Jha
7431b3bd859SHimanshu Jha ret = regmap_bulk_read(data->regmap, BM6880_REG_HUMIDITY_MSB,
744ce968fb6SJonathan Cameron &tmp, sizeof(tmp));
7451b3bd859SHimanshu Jha if (ret < 0) {
7461b3bd859SHimanshu Jha dev_err(dev, "failed to read humidity\n");
7471b3bd859SHimanshu Jha return ret;
7481b3bd859SHimanshu Jha }
7491b3bd859SHimanshu Jha
7501b3bd859SHimanshu Jha adc_humidity = be16_to_cpu(tmp);
7511b3bd859SHimanshu Jha if (adc_humidity == BME680_MEAS_SKIPPED) {
7521b3bd859SHimanshu Jha /* reading was skipped */
7531b3bd859SHimanshu Jha dev_err(dev, "reading humidity skipped\n");
7541b3bd859SHimanshu Jha return -EINVAL;
7551b3bd859SHimanshu Jha }
7561b3bd859SHimanshu Jha comp_humidity = bme680_compensate_humid(data, adc_humidity);
7571b3bd859SHimanshu Jha
7581b3bd859SHimanshu Jha *val = comp_humidity;
7591b3bd859SHimanshu Jha *val2 = 1000;
7601b3bd859SHimanshu Jha return IIO_VAL_FRACTIONAL;
7611b3bd859SHimanshu Jha }
7621b3bd859SHimanshu Jha
bme680_read_gas(struct bme680_data * data,int * val)7631b3bd859SHimanshu Jha static int bme680_read_gas(struct bme680_data *data,
7641b3bd859SHimanshu Jha int *val)
7651b3bd859SHimanshu Jha {
7661b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap);
7671b3bd859SHimanshu Jha int ret;
7681b3bd859SHimanshu Jha __be16 tmp = 0;
7691b3bd859SHimanshu Jha unsigned int check;
7701b3bd859SHimanshu Jha u16 adc_gas_res;
7711b3bd859SHimanshu Jha u8 gas_range;
7721b3bd859SHimanshu Jha
7731b3bd859SHimanshu Jha /* Set heater settings */
7741b3bd859SHimanshu Jha ret = bme680_gas_config(data);
7751b3bd859SHimanshu Jha if (ret < 0) {
7761b3bd859SHimanshu Jha dev_err(dev, "failed to set gas config\n");
7771b3bd859SHimanshu Jha return ret;
7781b3bd859SHimanshu Jha }
7791b3bd859SHimanshu Jha
7801b3bd859SHimanshu Jha /* set forced mode to trigger measurement */
7811b3bd859SHimanshu Jha ret = bme680_set_mode(data, true);
7821b3bd859SHimanshu Jha if (ret < 0)
7831b3bd859SHimanshu Jha return ret;
7841b3bd859SHimanshu Jha
785055b4e3dSVasileios Amoiridis ret = bme680_wait_for_eoc(data);
786055b4e3dSVasileios Amoiridis if (ret)
787055b4e3dSVasileios Amoiridis return ret;
788055b4e3dSVasileios Amoiridis
7891b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &check);
7901b3bd859SHimanshu Jha if (check & BME680_GAS_MEAS_BIT) {
7911b3bd859SHimanshu Jha dev_err(dev, "gas measurement incomplete\n");
7921b3bd859SHimanshu Jha return -EBUSY;
7931b3bd859SHimanshu Jha }
7941b3bd859SHimanshu Jha
7951b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_REG_GAS_R_LSB, &check);
7961b3bd859SHimanshu Jha if (ret < 0) {
7971b3bd859SHimanshu Jha dev_err(dev, "failed to read gas_r_lsb register\n");
7981b3bd859SHimanshu Jha return ret;
7991b3bd859SHimanshu Jha }
8001b3bd859SHimanshu Jha
8011b3bd859SHimanshu Jha /*
8021b3bd859SHimanshu Jha * occurs if either the gas heating duration was insuffient
8031b3bd859SHimanshu Jha * to reach the target heater temperature or the target
8041b3bd859SHimanshu Jha * heater temperature was too high for the heater sink to
8051b3bd859SHimanshu Jha * reach.
8061b3bd859SHimanshu Jha */
8071b3bd859SHimanshu Jha if ((check & BME680_GAS_STAB_BIT) == 0) {
8081b3bd859SHimanshu Jha dev_err(dev, "heater failed to reach the target temperature\n");
8091b3bd859SHimanshu Jha return -EINVAL;
8101b3bd859SHimanshu Jha }
8111b3bd859SHimanshu Jha
8121b3bd859SHimanshu Jha ret = regmap_bulk_read(data->regmap, BME680_REG_GAS_MSB,
813ce968fb6SJonathan Cameron &tmp, sizeof(tmp));
8141b3bd859SHimanshu Jha if (ret < 0) {
8151b3bd859SHimanshu Jha dev_err(dev, "failed to read gas resistance\n");
8161b3bd859SHimanshu Jha return ret;
8171b3bd859SHimanshu Jha }
8181b3bd859SHimanshu Jha
8191b3bd859SHimanshu Jha gas_range = check & BME680_GAS_RANGE_MASK;
8201b3bd859SHimanshu Jha adc_gas_res = be16_to_cpu(tmp) >> BME680_ADC_GAS_RES_SHIFT;
8211b3bd859SHimanshu Jha
8221b3bd859SHimanshu Jha *val = bme680_compensate_gas(data, adc_gas_res, gas_range);
8231b3bd859SHimanshu Jha return IIO_VAL_INT;
8241b3bd859SHimanshu Jha }
8251b3bd859SHimanshu Jha
bme680_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)8261b3bd859SHimanshu Jha static int bme680_read_raw(struct iio_dev *indio_dev,
8271b3bd859SHimanshu Jha struct iio_chan_spec const *chan,
8281b3bd859SHimanshu Jha int *val, int *val2, long mask)
8291b3bd859SHimanshu Jha {
8301b3bd859SHimanshu Jha struct bme680_data *data = iio_priv(indio_dev);
8311b3bd859SHimanshu Jha
832*2bc96d4eSVasileios Amoiridis guard(mutex)(&data->lock);
833*2bc96d4eSVasileios Amoiridis
8341b3bd859SHimanshu Jha switch (mask) {
8351b3bd859SHimanshu Jha case IIO_CHAN_INFO_PROCESSED:
8361b3bd859SHimanshu Jha switch (chan->type) {
8371b3bd859SHimanshu Jha case IIO_TEMP:
8389436f45dSMike Looijmans return bme680_read_temp(data, val);
8391b3bd859SHimanshu Jha case IIO_PRESSURE:
8401b3bd859SHimanshu Jha return bme680_read_press(data, val, val2);
8411b3bd859SHimanshu Jha case IIO_HUMIDITYRELATIVE:
8421b3bd859SHimanshu Jha return bme680_read_humid(data, val, val2);
8431b3bd859SHimanshu Jha case IIO_RESISTANCE:
8441b3bd859SHimanshu Jha return bme680_read_gas(data, val);
8451b3bd859SHimanshu Jha default:
8461b3bd859SHimanshu Jha return -EINVAL;
8471b3bd859SHimanshu Jha }
8481b3bd859SHimanshu Jha case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
8491b3bd859SHimanshu Jha switch (chan->type) {
8501b3bd859SHimanshu Jha case IIO_TEMP:
85179fd571bSDavid Frey *val = data->oversampling_temp;
8521b3bd859SHimanshu Jha return IIO_VAL_INT;
8531b3bd859SHimanshu Jha case IIO_PRESSURE:
85479fd571bSDavid Frey *val = data->oversampling_press;
8551b3bd859SHimanshu Jha return IIO_VAL_INT;
8561b3bd859SHimanshu Jha case IIO_HUMIDITYRELATIVE:
85779fd571bSDavid Frey *val = data->oversampling_humid;
8581b3bd859SHimanshu Jha return IIO_VAL_INT;
8591b3bd859SHimanshu Jha default:
8601b3bd859SHimanshu Jha return -EINVAL;
8611b3bd859SHimanshu Jha }
8621b3bd859SHimanshu Jha default:
8631b3bd859SHimanshu Jha return -EINVAL;
8641b3bd859SHimanshu Jha }
8651b3bd859SHimanshu Jha }
8661b3bd859SHimanshu Jha
bme680_is_valid_oversampling(int rate)86779fd571bSDavid Frey static bool bme680_is_valid_oversampling(int rate)
8681b3bd859SHimanshu Jha {
86979fd571bSDavid Frey return (rate > 0 && rate <= 16 && is_power_of_2(rate));
8701b3bd859SHimanshu Jha }
8711b3bd859SHimanshu Jha
bme680_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)8721b3bd859SHimanshu Jha static int bme680_write_raw(struct iio_dev *indio_dev,
8731b3bd859SHimanshu Jha struct iio_chan_spec const *chan,
8741b3bd859SHimanshu Jha int val, int val2, long mask)
8751b3bd859SHimanshu Jha {
8761b3bd859SHimanshu Jha struct bme680_data *data = iio_priv(indio_dev);
8771b3bd859SHimanshu Jha
878*2bc96d4eSVasileios Amoiridis guard(mutex)(&data->lock);
879*2bc96d4eSVasileios Amoiridis
880892e62faSHimanshu Jha if (val2 != 0)
881892e62faSHimanshu Jha return -EINVAL;
882892e62faSHimanshu Jha
8831b3bd859SHimanshu Jha switch (mask) {
8841b3bd859SHimanshu Jha case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
88579fd571bSDavid Frey {
88679fd571bSDavid Frey if (!bme680_is_valid_oversampling(val))
88779fd571bSDavid Frey return -EINVAL;
88879fd571bSDavid Frey
8891b3bd859SHimanshu Jha switch (chan->type) {
8901b3bd859SHimanshu Jha case IIO_TEMP:
89179fd571bSDavid Frey data->oversampling_temp = val;
89279fd571bSDavid Frey break;
8931b3bd859SHimanshu Jha case IIO_PRESSURE:
89479fd571bSDavid Frey data->oversampling_press = val;
89579fd571bSDavid Frey break;
8961b3bd859SHimanshu Jha case IIO_HUMIDITYRELATIVE:
89779fd571bSDavid Frey data->oversampling_humid = val;
89879fd571bSDavid Frey break;
8991b3bd859SHimanshu Jha default:
9001b3bd859SHimanshu Jha return -EINVAL;
9011b3bd859SHimanshu Jha }
90279fd571bSDavid Frey
90379fd571bSDavid Frey return bme680_chip_config(data);
90479fd571bSDavid Frey }
9051b3bd859SHimanshu Jha default:
9061b3bd859SHimanshu Jha return -EINVAL;
9071b3bd859SHimanshu Jha }
9081b3bd859SHimanshu Jha }
9091b3bd859SHimanshu Jha
9101b3bd859SHimanshu Jha static const char bme680_oversampling_ratio_show[] = "1 2 4 8 16";
9111b3bd859SHimanshu Jha
9121b3bd859SHimanshu Jha static IIO_CONST_ATTR(oversampling_ratio_available,
9131b3bd859SHimanshu Jha bme680_oversampling_ratio_show);
9141b3bd859SHimanshu Jha
9151b3bd859SHimanshu Jha static struct attribute *bme680_attributes[] = {
9161b3bd859SHimanshu Jha &iio_const_attr_oversampling_ratio_available.dev_attr.attr,
9171b3bd859SHimanshu Jha NULL,
9181b3bd859SHimanshu Jha };
9191b3bd859SHimanshu Jha
9201b3bd859SHimanshu Jha static const struct attribute_group bme680_attribute_group = {
9211b3bd859SHimanshu Jha .attrs = bme680_attributes,
9221b3bd859SHimanshu Jha };
9231b3bd859SHimanshu Jha
9241b3bd859SHimanshu Jha static const struct iio_info bme680_info = {
9251b3bd859SHimanshu Jha .read_raw = &bme680_read_raw,
9261b3bd859SHimanshu Jha .write_raw = &bme680_write_raw,
9271b3bd859SHimanshu Jha .attrs = &bme680_attribute_group,
9281b3bd859SHimanshu Jha };
9291b3bd859SHimanshu Jha
bme680_match_acpi_device(struct device * dev)9301b3bd859SHimanshu Jha static const char *bme680_match_acpi_device(struct device *dev)
9311b3bd859SHimanshu Jha {
9321b3bd859SHimanshu Jha const struct acpi_device_id *id;
9331b3bd859SHimanshu Jha
9341b3bd859SHimanshu Jha id = acpi_match_device(dev->driver->acpi_match_table, dev);
9351b3bd859SHimanshu Jha if (!id)
9361b3bd859SHimanshu Jha return NULL;
9371b3bd859SHimanshu Jha
9381b3bd859SHimanshu Jha return dev_name(dev);
9391b3bd859SHimanshu Jha }
9401b3bd859SHimanshu Jha
bme680_core_probe(struct device * dev,struct regmap * regmap,const char * name)9411b3bd859SHimanshu Jha int bme680_core_probe(struct device *dev, struct regmap *regmap,
9421b3bd859SHimanshu Jha const char *name)
9431b3bd859SHimanshu Jha {
9441b3bd859SHimanshu Jha struct iio_dev *indio_dev;
9451b3bd859SHimanshu Jha struct bme680_data *data;
94673f3bc6dSMike Looijmans unsigned int val;
9471b3bd859SHimanshu Jha int ret;
9481b3bd859SHimanshu Jha
94973f3bc6dSMike Looijmans ret = regmap_write(regmap, BME680_REG_SOFT_RESET,
95073f3bc6dSMike Looijmans BME680_CMD_SOFTRESET);
95173f3bc6dSMike Looijmans if (ret < 0) {
95273f3bc6dSMike Looijmans dev_err(dev, "Failed to reset chip\n");
95373f3bc6dSMike Looijmans return ret;
95473f3bc6dSMike Looijmans }
95573f3bc6dSMike Looijmans
95673f3bc6dSMike Looijmans ret = regmap_read(regmap, BME680_REG_CHIP_ID, &val);
95773f3bc6dSMike Looijmans if (ret < 0) {
95873f3bc6dSMike Looijmans dev_err(dev, "Error reading chip ID\n");
95973f3bc6dSMike Looijmans return ret;
96073f3bc6dSMike Looijmans }
96173f3bc6dSMike Looijmans
96273f3bc6dSMike Looijmans if (val != BME680_CHIP_ID_VAL) {
96373f3bc6dSMike Looijmans dev_err(dev, "Wrong chip ID, got %x expected %x\n",
96473f3bc6dSMike Looijmans val, BME680_CHIP_ID_VAL);
96573f3bc6dSMike Looijmans return -ENODEV;
96673f3bc6dSMike Looijmans }
96773f3bc6dSMike Looijmans
9681b3bd859SHimanshu Jha indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
9691b3bd859SHimanshu Jha if (!indio_dev)
9701b3bd859SHimanshu Jha return -ENOMEM;
9711b3bd859SHimanshu Jha
9721b3bd859SHimanshu Jha if (!name && ACPI_HANDLE(dev))
9731b3bd859SHimanshu Jha name = bme680_match_acpi_device(dev);
9741b3bd859SHimanshu Jha
9751b3bd859SHimanshu Jha data = iio_priv(indio_dev);
976*2bc96d4eSVasileios Amoiridis mutex_init(&data->lock);
9771b3bd859SHimanshu Jha dev_set_drvdata(dev, indio_dev);
9781b3bd859SHimanshu Jha data->regmap = regmap;
9791b3bd859SHimanshu Jha indio_dev->name = name;
9801b3bd859SHimanshu Jha indio_dev->channels = bme680_channels;
9811b3bd859SHimanshu Jha indio_dev->num_channels = ARRAY_SIZE(bme680_channels);
9821b3bd859SHimanshu Jha indio_dev->info = &bme680_info;
9831b3bd859SHimanshu Jha indio_dev->modes = INDIO_DIRECT_MODE;
9841b3bd859SHimanshu Jha
9851b3bd859SHimanshu Jha /* default values for the sensor */
98679fd571bSDavid Frey data->oversampling_humid = 2; /* 2X oversampling rate */
98779fd571bSDavid Frey data->oversampling_press = 4; /* 4X oversampling rate */
98879fd571bSDavid Frey data->oversampling_temp = 8; /* 8X oversampling rate */
9891b3bd859SHimanshu Jha data->heater_temp = 320; /* degree Celsius */
9901b3bd859SHimanshu Jha data->heater_dur = 150; /* milliseconds */
9911b3bd859SHimanshu Jha
9921b3bd859SHimanshu Jha ret = bme680_chip_config(data);
9931b3bd859SHimanshu Jha if (ret < 0) {
9941b3bd859SHimanshu Jha dev_err(dev, "failed to set chip_config data\n");
9951b3bd859SHimanshu Jha return ret;
9961b3bd859SHimanshu Jha }
9971b3bd859SHimanshu Jha
9981b3bd859SHimanshu Jha ret = bme680_gas_config(data);
9991b3bd859SHimanshu Jha if (ret < 0) {
10001b3bd859SHimanshu Jha dev_err(dev, "failed to set gas config data\n");
10011b3bd859SHimanshu Jha return ret;
10021b3bd859SHimanshu Jha }
10031b3bd859SHimanshu Jha
10041b3bd859SHimanshu Jha ret = bme680_read_calib(data, &data->bme680);
10051b3bd859SHimanshu Jha if (ret < 0) {
10061b3bd859SHimanshu Jha dev_err(dev,
10071b3bd859SHimanshu Jha "failed to read calibration coefficients at probe\n");
10081b3bd859SHimanshu Jha return ret;
10091b3bd859SHimanshu Jha }
10101b3bd859SHimanshu Jha
10111b3bd859SHimanshu Jha return devm_iio_device_register(dev, indio_dev);
10121b3bd859SHimanshu Jha }
1013146b43d9SJonathan Cameron EXPORT_SYMBOL_NS_GPL(bme680_core_probe, IIO_BME680);
10141b3bd859SHimanshu Jha
10151b3bd859SHimanshu Jha MODULE_AUTHOR("Himanshu Jha <himanshujha199640@gmail.com>");
10161b3bd859SHimanshu Jha MODULE_DESCRIPTION("Bosch BME680 Driver");
10171b3bd859SHimanshu Jha MODULE_LICENSE("GPL v2");
1018