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> 131b3bd859SHimanshu Jha #include <linux/device.h> 141b3bd859SHimanshu Jha #include <linux/module.h> 151b3bd859SHimanshu Jha #include <linux/log2.h> 161b3bd859SHimanshu Jha #include <linux/regmap.h> 171b3bd859SHimanshu Jha #include <linux/iio/iio.h> 181b3bd859SHimanshu Jha #include <linux/iio/sysfs.h> 191b3bd859SHimanshu Jha 201b3bd859SHimanshu Jha #include "bme680.h" 211b3bd859SHimanshu Jha 221b3bd859SHimanshu Jha struct bme680_calib { 231b3bd859SHimanshu Jha u16 par_t1; 241b3bd859SHimanshu Jha s16 par_t2; 251b3bd859SHimanshu Jha s8 par_t3; 261b3bd859SHimanshu Jha u16 par_p1; 271b3bd859SHimanshu Jha s16 par_p2; 281b3bd859SHimanshu Jha s8 par_p3; 291b3bd859SHimanshu Jha s16 par_p4; 301b3bd859SHimanshu Jha s16 par_p5; 311b3bd859SHimanshu Jha s8 par_p6; 321b3bd859SHimanshu Jha s8 par_p7; 331b3bd859SHimanshu Jha s16 par_p8; 341b3bd859SHimanshu Jha s16 par_p9; 351b3bd859SHimanshu Jha u8 par_p10; 361b3bd859SHimanshu Jha u16 par_h1; 371b3bd859SHimanshu Jha u16 par_h2; 381b3bd859SHimanshu Jha s8 par_h3; 391b3bd859SHimanshu Jha s8 par_h4; 401b3bd859SHimanshu Jha s8 par_h5; 411b3bd859SHimanshu Jha s8 par_h6; 421b3bd859SHimanshu Jha s8 par_h7; 431b3bd859SHimanshu Jha s8 par_gh1; 441b3bd859SHimanshu Jha s16 par_gh2; 451b3bd859SHimanshu Jha s8 par_gh3; 461b3bd859SHimanshu Jha u8 res_heat_range; 471b3bd859SHimanshu Jha s8 res_heat_val; 481b3bd859SHimanshu Jha s8 range_sw_err; 491b3bd859SHimanshu Jha }; 501b3bd859SHimanshu Jha 511b3bd859SHimanshu Jha struct bme680_data { 521b3bd859SHimanshu Jha struct regmap *regmap; 531b3bd859SHimanshu Jha struct bme680_calib bme680; 541b3bd859SHimanshu Jha u8 oversampling_temp; 551b3bd859SHimanshu Jha u8 oversampling_press; 561b3bd859SHimanshu Jha u8 oversampling_humid; 571b3bd859SHimanshu Jha u16 heater_dur; 581b3bd859SHimanshu Jha u16 heater_temp; 591b3bd859SHimanshu Jha /* 601b3bd859SHimanshu Jha * Carryover value from temperature conversion, used in pressure 611b3bd859SHimanshu Jha * and humidity compensation calculations. 621b3bd859SHimanshu Jha */ 631b3bd859SHimanshu Jha s32 t_fine; 641b3bd859SHimanshu Jha }; 651b3bd859SHimanshu Jha 6673f3bc6dSMike Looijmans static const struct regmap_range bme680_volatile_ranges[] = { 6773f3bc6dSMike Looijmans regmap_reg_range(BME680_REG_MEAS_STAT_0, BME680_REG_GAS_R_LSB), 6873f3bc6dSMike Looijmans regmap_reg_range(BME680_REG_STATUS, BME680_REG_STATUS), 6973f3bc6dSMike Looijmans regmap_reg_range(BME680_T2_LSB_REG, BME680_GH3_REG), 7073f3bc6dSMike Looijmans }; 7173f3bc6dSMike Looijmans 7273f3bc6dSMike Looijmans static const struct regmap_access_table bme680_volatile_table = { 7373f3bc6dSMike Looijmans .yes_ranges = bme680_volatile_ranges, 7473f3bc6dSMike Looijmans .n_yes_ranges = ARRAY_SIZE(bme680_volatile_ranges), 7573f3bc6dSMike Looijmans }; 7673f3bc6dSMike Looijmans 771b3bd859SHimanshu Jha const struct regmap_config bme680_regmap_config = { 781b3bd859SHimanshu Jha .reg_bits = 8, 791b3bd859SHimanshu Jha .val_bits = 8, 8073f3bc6dSMike Looijmans .max_register = 0xef, 8173f3bc6dSMike Looijmans .volatile_table = &bme680_volatile_table, 8273f3bc6dSMike Looijmans .cache_type = REGCACHE_RBTREE, 831b3bd859SHimanshu Jha }; 841b3bd859SHimanshu Jha EXPORT_SYMBOL(bme680_regmap_config); 851b3bd859SHimanshu Jha 861b3bd859SHimanshu Jha static const struct iio_chan_spec bme680_channels[] = { 871b3bd859SHimanshu Jha { 881b3bd859SHimanshu Jha .type = IIO_TEMP, 891b3bd859SHimanshu Jha .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | 901b3bd859SHimanshu Jha BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), 911b3bd859SHimanshu Jha }, 921b3bd859SHimanshu Jha { 931b3bd859SHimanshu Jha .type = IIO_PRESSURE, 941b3bd859SHimanshu Jha .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | 951b3bd859SHimanshu Jha BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), 961b3bd859SHimanshu Jha }, 971b3bd859SHimanshu Jha { 981b3bd859SHimanshu Jha .type = IIO_HUMIDITYRELATIVE, 991b3bd859SHimanshu Jha .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | 1001b3bd859SHimanshu Jha BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), 1011b3bd859SHimanshu Jha }, 1021b3bd859SHimanshu Jha { 1031b3bd859SHimanshu Jha .type = IIO_RESISTANCE, 1041b3bd859SHimanshu Jha .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), 1051b3bd859SHimanshu Jha }, 1061b3bd859SHimanshu Jha }; 1071b3bd859SHimanshu Jha 1081b3bd859SHimanshu Jha static int bme680_read_calib(struct bme680_data *data, 1091b3bd859SHimanshu Jha struct bme680_calib *calib) 1101b3bd859SHimanshu Jha { 1111b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap); 1121b3bd859SHimanshu Jha unsigned int tmp, tmp_msb, tmp_lsb; 1131b3bd859SHimanshu Jha int ret; 1141b3bd859SHimanshu Jha __le16 buf; 1151b3bd859SHimanshu Jha 1161b3bd859SHimanshu Jha /* Temperature related coefficients */ 117ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_T1_LSB_REG, 118ce968fb6SJonathan Cameron &buf, sizeof(buf)); 1191b3bd859SHimanshu Jha if (ret < 0) { 1201b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_T1_LSB_REG\n"); 1211b3bd859SHimanshu Jha return ret; 1221b3bd859SHimanshu Jha } 1231b3bd859SHimanshu Jha calib->par_t1 = le16_to_cpu(buf); 1241b3bd859SHimanshu Jha 125ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_T2_LSB_REG, 126ce968fb6SJonathan Cameron &buf, sizeof(buf)); 1271b3bd859SHimanshu Jha if (ret < 0) { 1281b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_T2_LSB_REG\n"); 1291b3bd859SHimanshu Jha return ret; 1301b3bd859SHimanshu Jha } 1311b3bd859SHimanshu Jha calib->par_t2 = le16_to_cpu(buf); 1321b3bd859SHimanshu Jha 1331b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_T3_REG, &tmp); 1341b3bd859SHimanshu Jha if (ret < 0) { 1351b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_T3_REG\n"); 1361b3bd859SHimanshu Jha return ret; 1371b3bd859SHimanshu Jha } 1381b3bd859SHimanshu Jha calib->par_t3 = tmp; 1391b3bd859SHimanshu Jha 1401b3bd859SHimanshu Jha /* Pressure related coefficients */ 141ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_P1_LSB_REG, 142ce968fb6SJonathan Cameron &buf, sizeof(buf)); 1431b3bd859SHimanshu Jha if (ret < 0) { 1441b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P1_LSB_REG\n"); 1451b3bd859SHimanshu Jha return ret; 1461b3bd859SHimanshu Jha } 1471b3bd859SHimanshu Jha calib->par_p1 = le16_to_cpu(buf); 1481b3bd859SHimanshu Jha 149ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_P2_LSB_REG, 150ce968fb6SJonathan Cameron &buf, sizeof(buf)); 1511b3bd859SHimanshu Jha if (ret < 0) { 1521b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P2_LSB_REG\n"); 1531b3bd859SHimanshu Jha return ret; 1541b3bd859SHimanshu Jha } 1551b3bd859SHimanshu Jha calib->par_p2 = le16_to_cpu(buf); 1561b3bd859SHimanshu Jha 1571b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_P3_REG, &tmp); 1581b3bd859SHimanshu Jha if (ret < 0) { 1591b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P3_REG\n"); 1601b3bd859SHimanshu Jha return ret; 1611b3bd859SHimanshu Jha } 1621b3bd859SHimanshu Jha calib->par_p3 = tmp; 1631b3bd859SHimanshu Jha 164ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_P4_LSB_REG, 165ce968fb6SJonathan Cameron &buf, sizeof(buf)); 1661b3bd859SHimanshu Jha if (ret < 0) { 1671b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P4_LSB_REG\n"); 1681b3bd859SHimanshu Jha return ret; 1691b3bd859SHimanshu Jha } 1701b3bd859SHimanshu Jha calib->par_p4 = le16_to_cpu(buf); 1711b3bd859SHimanshu Jha 172ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_P5_LSB_REG, 173ce968fb6SJonathan Cameron &buf, sizeof(buf)); 1741b3bd859SHimanshu Jha if (ret < 0) { 1751b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P5_LSB_REG\n"); 1761b3bd859SHimanshu Jha return ret; 1771b3bd859SHimanshu Jha } 1781b3bd859SHimanshu Jha calib->par_p5 = le16_to_cpu(buf); 1791b3bd859SHimanshu Jha 1801b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_P6_REG, &tmp); 1811b3bd859SHimanshu Jha if (ret < 0) { 1821b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P6_REG\n"); 1831b3bd859SHimanshu Jha return ret; 1841b3bd859SHimanshu Jha } 1851b3bd859SHimanshu Jha calib->par_p6 = tmp; 1861b3bd859SHimanshu Jha 1871b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_P7_REG, &tmp); 1881b3bd859SHimanshu Jha if (ret < 0) { 1891b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P7_REG\n"); 1901b3bd859SHimanshu Jha return ret; 1911b3bd859SHimanshu Jha } 1921b3bd859SHimanshu Jha calib->par_p7 = tmp; 1931b3bd859SHimanshu Jha 194ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_P8_LSB_REG, 195ce968fb6SJonathan Cameron &buf, sizeof(buf)); 1961b3bd859SHimanshu Jha if (ret < 0) { 1971b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P8_LSB_REG\n"); 1981b3bd859SHimanshu Jha return ret; 1991b3bd859SHimanshu Jha } 2001b3bd859SHimanshu Jha calib->par_p8 = le16_to_cpu(buf); 2011b3bd859SHimanshu Jha 202ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_P9_LSB_REG, 203ce968fb6SJonathan Cameron &buf, sizeof(buf)); 2041b3bd859SHimanshu Jha if (ret < 0) { 2051b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P9_LSB_REG\n"); 2061b3bd859SHimanshu Jha return ret; 2071b3bd859SHimanshu Jha } 2081b3bd859SHimanshu Jha calib->par_p9 = le16_to_cpu(buf); 2091b3bd859SHimanshu Jha 2101b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_P10_REG, &tmp); 2111b3bd859SHimanshu Jha if (ret < 0) { 2121b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_P10_REG\n"); 2131b3bd859SHimanshu Jha return ret; 2141b3bd859SHimanshu Jha } 2151b3bd859SHimanshu Jha calib->par_p10 = tmp; 2161b3bd859SHimanshu Jha 2171b3bd859SHimanshu Jha /* Humidity related coefficients */ 2181b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H1_MSB_REG, &tmp_msb); 2191b3bd859SHimanshu Jha if (ret < 0) { 2201b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H1_MSB_REG\n"); 2211b3bd859SHimanshu Jha return ret; 2221b3bd859SHimanshu Jha } 2231b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H1_LSB_REG, &tmp_lsb); 2241b3bd859SHimanshu Jha if (ret < 0) { 2251b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H1_LSB_REG\n"); 2261b3bd859SHimanshu Jha return ret; 2271b3bd859SHimanshu Jha } 2281b3bd859SHimanshu Jha calib->par_h1 = (tmp_msb << BME680_HUM_REG_SHIFT_VAL) | 229a24b4d70SDavid Frey (tmp_lsb & BME680_BIT_H1_DATA_MASK); 2301b3bd859SHimanshu Jha 2311b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H2_MSB_REG, &tmp_msb); 2321b3bd859SHimanshu Jha if (ret < 0) { 2331b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H2_MSB_REG\n"); 2341b3bd859SHimanshu Jha return ret; 2351b3bd859SHimanshu Jha } 2361b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H2_LSB_REG, &tmp_lsb); 2371b3bd859SHimanshu Jha if (ret < 0) { 2381b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H2_LSB_REG\n"); 2391b3bd859SHimanshu Jha return ret; 2401b3bd859SHimanshu Jha } 2411b3bd859SHimanshu Jha calib->par_h2 = (tmp_msb << BME680_HUM_REG_SHIFT_VAL) | 2421b3bd859SHimanshu Jha (tmp_lsb >> BME680_HUM_REG_SHIFT_VAL); 2431b3bd859SHimanshu Jha 2441b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H3_REG, &tmp); 2451b3bd859SHimanshu Jha if (ret < 0) { 2461b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H3_REG\n"); 2471b3bd859SHimanshu Jha return ret; 2481b3bd859SHimanshu Jha } 2491b3bd859SHimanshu Jha calib->par_h3 = tmp; 2501b3bd859SHimanshu Jha 2511b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H4_REG, &tmp); 2521b3bd859SHimanshu Jha if (ret < 0) { 2531b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H4_REG\n"); 2541b3bd859SHimanshu Jha return ret; 2551b3bd859SHimanshu Jha } 2561b3bd859SHimanshu Jha calib->par_h4 = tmp; 2571b3bd859SHimanshu Jha 2581b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H5_REG, &tmp); 2591b3bd859SHimanshu Jha if (ret < 0) { 2601b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H5_REG\n"); 2611b3bd859SHimanshu Jha return ret; 2621b3bd859SHimanshu Jha } 2631b3bd859SHimanshu Jha calib->par_h5 = tmp; 2641b3bd859SHimanshu Jha 2651b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H6_REG, &tmp); 2661b3bd859SHimanshu Jha if (ret < 0) { 2671b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H6_REG\n"); 2681b3bd859SHimanshu Jha return ret; 2691b3bd859SHimanshu Jha } 2701b3bd859SHimanshu Jha calib->par_h6 = tmp; 2711b3bd859SHimanshu Jha 2721b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_H7_REG, &tmp); 2731b3bd859SHimanshu Jha if (ret < 0) { 2741b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_H7_REG\n"); 2751b3bd859SHimanshu Jha return ret; 2761b3bd859SHimanshu Jha } 2771b3bd859SHimanshu Jha calib->par_h7 = tmp; 2781b3bd859SHimanshu Jha 2791b3bd859SHimanshu Jha /* Gas heater related coefficients */ 2801b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_GH1_REG, &tmp); 2811b3bd859SHimanshu Jha if (ret < 0) { 2821b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_GH1_REG\n"); 2831b3bd859SHimanshu Jha return ret; 2841b3bd859SHimanshu Jha } 2851b3bd859SHimanshu Jha calib->par_gh1 = tmp; 2861b3bd859SHimanshu Jha 287ce968fb6SJonathan Cameron ret = regmap_bulk_read(data->regmap, BME680_GH2_LSB_REG, 288ce968fb6SJonathan Cameron &buf, sizeof(buf)); 2891b3bd859SHimanshu Jha if (ret < 0) { 2901b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_GH2_LSB_REG\n"); 2911b3bd859SHimanshu Jha return ret; 2921b3bd859SHimanshu Jha } 2931b3bd859SHimanshu Jha calib->par_gh2 = le16_to_cpu(buf); 2941b3bd859SHimanshu Jha 2951b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_GH3_REG, &tmp); 2961b3bd859SHimanshu Jha if (ret < 0) { 2971b3bd859SHimanshu Jha dev_err(dev, "failed to read BME680_GH3_REG\n"); 2981b3bd859SHimanshu Jha return ret; 2991b3bd859SHimanshu Jha } 3001b3bd859SHimanshu Jha calib->par_gh3 = tmp; 3011b3bd859SHimanshu Jha 3021b3bd859SHimanshu Jha /* Other coefficients */ 3031b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_REG_RES_HEAT_RANGE, &tmp); 3041b3bd859SHimanshu Jha if (ret < 0) { 3051b3bd859SHimanshu Jha dev_err(dev, "failed to read resistance heat range\n"); 3061b3bd859SHimanshu Jha return ret; 3071b3bd859SHimanshu Jha } 3083dcb60cdSDavid Frey calib->res_heat_range = FIELD_GET(BME680_RHRANGE_MASK, tmp); 3091b3bd859SHimanshu Jha 3101b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_REG_RES_HEAT_VAL, &tmp); 3111b3bd859SHimanshu Jha if (ret < 0) { 3121b3bd859SHimanshu Jha dev_err(dev, "failed to read resistance heat value\n"); 3131b3bd859SHimanshu Jha return ret; 3141b3bd859SHimanshu Jha } 3151b3bd859SHimanshu Jha calib->res_heat_val = tmp; 3161b3bd859SHimanshu Jha 3171b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_REG_RANGE_SW_ERR, &tmp); 3181b3bd859SHimanshu Jha if (ret < 0) { 3191b3bd859SHimanshu Jha dev_err(dev, "failed to read range software error\n"); 3201b3bd859SHimanshu Jha return ret; 3211b3bd859SHimanshu Jha } 3223dcb60cdSDavid Frey calib->range_sw_err = FIELD_GET(BME680_RSERROR_MASK, tmp); 3231b3bd859SHimanshu Jha 3241b3bd859SHimanshu Jha return 0; 3251b3bd859SHimanshu Jha } 3261b3bd859SHimanshu Jha 3271b3bd859SHimanshu Jha /* 3281b3bd859SHimanshu Jha * Taken from Bosch BME680 API: 3291b3bd859SHimanshu Jha * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L876 3301b3bd859SHimanshu Jha * 3311b3bd859SHimanshu Jha * Returns temperature measurement in DegC, resolutions is 0.01 DegC. Therefore, 3321b3bd859SHimanshu Jha * output value of "3233" represents 32.33 DegC. 3331b3bd859SHimanshu Jha */ 3341b3bd859SHimanshu Jha static s16 bme680_compensate_temp(struct bme680_data *data, 3351b3bd859SHimanshu Jha s32 adc_temp) 3361b3bd859SHimanshu Jha { 3371b3bd859SHimanshu Jha struct bme680_calib *calib = &data->bme680; 3381b3bd859SHimanshu Jha s64 var1, var2, var3; 3391b3bd859SHimanshu Jha s16 calc_temp; 3401b3bd859SHimanshu Jha 34173f3bc6dSMike Looijmans /* If the calibration is invalid, attempt to reload it */ 34273f3bc6dSMike Looijmans if (!calib->par_t2) 34373f3bc6dSMike Looijmans bme680_read_calib(data, calib); 34473f3bc6dSMike Looijmans 3451b3bd859SHimanshu Jha var1 = (adc_temp >> 3) - (calib->par_t1 << 1); 3461b3bd859SHimanshu Jha var2 = (var1 * calib->par_t2) >> 11; 3471b3bd859SHimanshu Jha var3 = ((var1 >> 1) * (var1 >> 1)) >> 12; 3481b3bd859SHimanshu Jha var3 = (var3 * (calib->par_t3 << 4)) >> 14; 3491b3bd859SHimanshu Jha data->t_fine = var2 + var3; 3501b3bd859SHimanshu Jha calc_temp = (data->t_fine * 5 + 128) >> 8; 3511b3bd859SHimanshu Jha 3521b3bd859SHimanshu Jha return calc_temp; 3531b3bd859SHimanshu Jha } 3541b3bd859SHimanshu Jha 3551b3bd859SHimanshu Jha /* 3561b3bd859SHimanshu Jha * Taken from Bosch BME680 API: 3571b3bd859SHimanshu Jha * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L896 3581b3bd859SHimanshu Jha * 3591b3bd859SHimanshu Jha * Returns pressure measurement in Pa. Output value of "97356" represents 3601b3bd859SHimanshu Jha * 97356 Pa = 973.56 hPa. 3611b3bd859SHimanshu Jha */ 3621b3bd859SHimanshu Jha static u32 bme680_compensate_press(struct bme680_data *data, 3631b3bd859SHimanshu Jha u32 adc_press) 3641b3bd859SHimanshu Jha { 3651b3bd859SHimanshu Jha struct bme680_calib *calib = &data->bme680; 3661b3bd859SHimanshu Jha s32 var1, var2, var3, press_comp; 3671b3bd859SHimanshu Jha 3681b3bd859SHimanshu Jha var1 = (data->t_fine >> 1) - 64000; 3691b3bd859SHimanshu Jha var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * calib->par_p6) >> 2; 3701b3bd859SHimanshu Jha var2 = var2 + (var1 * calib->par_p5 << 1); 3711b3bd859SHimanshu Jha var2 = (var2 >> 2) + (calib->par_p4 << 16); 3721b3bd859SHimanshu Jha var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) * 3731b3bd859SHimanshu Jha (calib->par_p3 << 5)) >> 3) + 3741b3bd859SHimanshu Jha ((calib->par_p2 * var1) >> 1); 3751b3bd859SHimanshu Jha var1 = var1 >> 18; 3761b3bd859SHimanshu Jha var1 = ((32768 + var1) * calib->par_p1) >> 15; 3771b3bd859SHimanshu Jha press_comp = 1048576 - adc_press; 3781b3bd859SHimanshu Jha press_comp = ((press_comp - (var2 >> 12)) * 3125); 3791b3bd859SHimanshu Jha 3801b3bd859SHimanshu Jha if (press_comp >= BME680_MAX_OVERFLOW_VAL) 3811b3bd859SHimanshu Jha press_comp = ((press_comp / (u32)var1) << 1); 3821b3bd859SHimanshu Jha else 3831b3bd859SHimanshu Jha press_comp = ((press_comp << 1) / (u32)var1); 3841b3bd859SHimanshu Jha 3851b3bd859SHimanshu Jha var1 = (calib->par_p9 * (((press_comp >> 3) * 3861b3bd859SHimanshu Jha (press_comp >> 3)) >> 13)) >> 12; 3871b3bd859SHimanshu Jha var2 = ((press_comp >> 2) * calib->par_p8) >> 13; 3881b3bd859SHimanshu Jha var3 = ((press_comp >> 8) * (press_comp >> 8) * 3891b3bd859SHimanshu Jha (press_comp >> 8) * calib->par_p10) >> 17; 3901b3bd859SHimanshu Jha 3911b3bd859SHimanshu Jha press_comp += (var1 + var2 + var3 + (calib->par_p7 << 7)) >> 4; 3921b3bd859SHimanshu Jha 3931b3bd859SHimanshu Jha return press_comp; 3941b3bd859SHimanshu Jha } 3951b3bd859SHimanshu Jha 3961b3bd859SHimanshu Jha /* 3971b3bd859SHimanshu Jha * Taken from Bosch BME680 API: 3981b3bd859SHimanshu Jha * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L937 3991b3bd859SHimanshu Jha * 4001b3bd859SHimanshu Jha * Returns humidity measurement in percent, resolution is 0.001 percent. Output 4011b3bd859SHimanshu Jha * value of "43215" represents 43.215 %rH. 4021b3bd859SHimanshu Jha */ 4031b3bd859SHimanshu Jha static u32 bme680_compensate_humid(struct bme680_data *data, 4041b3bd859SHimanshu Jha u16 adc_humid) 4051b3bd859SHimanshu Jha { 4061b3bd859SHimanshu Jha struct bme680_calib *calib = &data->bme680; 4071b3bd859SHimanshu Jha s32 var1, var2, var3, var4, var5, var6, temp_scaled, calc_hum; 4081b3bd859SHimanshu Jha 4091b3bd859SHimanshu Jha temp_scaled = (data->t_fine * 5 + 128) >> 8; 4101b3bd859SHimanshu Jha var1 = (adc_humid - ((s32) ((s32) calib->par_h1 * 16))) - 4111b3bd859SHimanshu Jha (((temp_scaled * (s32) calib->par_h3) / 100) >> 1); 4121b3bd859SHimanshu Jha var2 = ((s32) calib->par_h2 * 4131b3bd859SHimanshu Jha (((temp_scaled * calib->par_h4) / 100) + 4141b3bd859SHimanshu Jha (((temp_scaled * ((temp_scaled * calib->par_h5) / 100)) 4151b3bd859SHimanshu Jha >> 6) / 100) + (1 << 14))) >> 10; 4161b3bd859SHimanshu Jha var3 = var1 * var2; 4171b3bd859SHimanshu Jha var4 = calib->par_h6 << 7; 4181b3bd859SHimanshu Jha var4 = (var4 + ((temp_scaled * calib->par_h7) / 100)) >> 4; 4191b3bd859SHimanshu Jha var5 = ((var3 >> 14) * (var3 >> 14)) >> 10; 4201b3bd859SHimanshu Jha var6 = (var4 * var5) >> 1; 4211b3bd859SHimanshu Jha calc_hum = (((var3 + var6) >> 10) * 1000) >> 12; 4221b3bd859SHimanshu Jha 4238a0ae7d8SDavid Frey calc_hum = clamp(calc_hum, 0, 100000); /* clamp between 0-100 %rH */ 4241b3bd859SHimanshu Jha 4251b3bd859SHimanshu Jha return calc_hum; 4261b3bd859SHimanshu Jha } 4271b3bd859SHimanshu Jha 4281b3bd859SHimanshu Jha /* 4291b3bd859SHimanshu Jha * Taken from Bosch BME680 API: 4301b3bd859SHimanshu Jha * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L973 4311b3bd859SHimanshu Jha * 4321b3bd859SHimanshu Jha * Returns gas measurement in Ohm. Output value of "82986" represent 82986 ohms. 4331b3bd859SHimanshu Jha */ 4341b3bd859SHimanshu Jha static u32 bme680_compensate_gas(struct bme680_data *data, u16 gas_res_adc, 4351b3bd859SHimanshu Jha u8 gas_range) 4361b3bd859SHimanshu Jha { 4371b3bd859SHimanshu Jha struct bme680_calib *calib = &data->bme680; 4381b3bd859SHimanshu Jha s64 var1; 4391b3bd859SHimanshu Jha u64 var2; 4401b3bd859SHimanshu Jha s64 var3; 4411b3bd859SHimanshu Jha u32 calc_gas_res; 4421b3bd859SHimanshu Jha 4431b3bd859SHimanshu Jha /* Look up table for the possible gas range values */ 4441b3bd859SHimanshu Jha const u32 lookupTable[16] = {2147483647u, 2147483647u, 4451b3bd859SHimanshu Jha 2147483647u, 2147483647u, 2147483647u, 4461b3bd859SHimanshu Jha 2126008810u, 2147483647u, 2130303777u, 4471b3bd859SHimanshu Jha 2147483647u, 2147483647u, 2143188679u, 4481b3bd859SHimanshu Jha 2136746228u, 2147483647u, 2126008810u, 4491b3bd859SHimanshu Jha 2147483647u, 2147483647u}; 4501b3bd859SHimanshu Jha 4511b3bd859SHimanshu Jha var1 = ((1340 + (5 * (s64) calib->range_sw_err)) * 4521b3bd859SHimanshu Jha ((s64) lookupTable[gas_range])) >> 16; 4531b3bd859SHimanshu Jha var2 = ((gas_res_adc << 15) - 16777216) + var1; 4541b3bd859SHimanshu Jha var3 = ((125000 << (15 - gas_range)) * var1) >> 9; 4551b3bd859SHimanshu Jha var3 += (var2 >> 1); 4561b3bd859SHimanshu Jha calc_gas_res = div64_s64(var3, (s64) var2); 4571b3bd859SHimanshu Jha 4581b3bd859SHimanshu Jha return calc_gas_res; 4591b3bd859SHimanshu Jha } 4601b3bd859SHimanshu Jha 4611b3bd859SHimanshu Jha /* 4621b3bd859SHimanshu Jha * Taken from Bosch BME680 API: 4631b3bd859SHimanshu Jha * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L1002 4641b3bd859SHimanshu Jha */ 4651b3bd859SHimanshu Jha static u8 bme680_calc_heater_res(struct bme680_data *data, u16 temp) 4661b3bd859SHimanshu Jha { 4671b3bd859SHimanshu Jha struct bme680_calib *calib = &data->bme680; 4681b3bd859SHimanshu Jha s32 var1, var2, var3, var4, var5, heatr_res_x100; 4691b3bd859SHimanshu Jha u8 heatr_res; 4701b3bd859SHimanshu Jha 4711b3bd859SHimanshu Jha if (temp > 400) /* Cap temperature */ 4721b3bd859SHimanshu Jha temp = 400; 4731b3bd859SHimanshu Jha 4741b3bd859SHimanshu Jha var1 = (((s32) BME680_AMB_TEMP * calib->par_gh3) / 1000) * 256; 4751b3bd859SHimanshu Jha var2 = (calib->par_gh1 + 784) * (((((calib->par_gh2 + 154009) * 4761b3bd859SHimanshu Jha temp * 5) / 100) 4771b3bd859SHimanshu Jha + 3276800) / 10); 4781b3bd859SHimanshu Jha var3 = var1 + (var2 / 2); 4791b3bd859SHimanshu Jha var4 = (var3 / (calib->res_heat_range + 4)); 4801b3bd859SHimanshu Jha var5 = 131 * calib->res_heat_val + 65536; 4811b3bd859SHimanshu Jha heatr_res_x100 = ((var4 / var5) - 250) * 34; 482*166549bbSLars-Peter Clausen heatr_res = DIV_ROUND_CLOSEST(heatr_res_x100, 100); 4831b3bd859SHimanshu Jha 4841b3bd859SHimanshu Jha return heatr_res; 4851b3bd859SHimanshu Jha } 4861b3bd859SHimanshu Jha 4871b3bd859SHimanshu Jha /* 4881b3bd859SHimanshu Jha * Taken from Bosch BME680 API: 4891b3bd859SHimanshu Jha * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L1188 4901b3bd859SHimanshu Jha */ 4911b3bd859SHimanshu Jha static u8 bme680_calc_heater_dur(u16 dur) 4921b3bd859SHimanshu Jha { 4931b3bd859SHimanshu Jha u8 durval, factor = 0; 4941b3bd859SHimanshu Jha 4951b3bd859SHimanshu Jha if (dur >= 0xfc0) { 4961b3bd859SHimanshu Jha durval = 0xff; /* Max duration */ 4971b3bd859SHimanshu Jha } else { 4981b3bd859SHimanshu Jha while (dur > 0x3F) { 4991b3bd859SHimanshu Jha dur = dur / 4; 5001b3bd859SHimanshu Jha factor += 1; 5011b3bd859SHimanshu Jha } 5021b3bd859SHimanshu Jha durval = dur + (factor * 64); 5031b3bd859SHimanshu Jha } 5041b3bd859SHimanshu Jha 5051b3bd859SHimanshu Jha return durval; 5061b3bd859SHimanshu Jha } 5071b3bd859SHimanshu Jha 5081b3bd859SHimanshu Jha static int bme680_set_mode(struct bme680_data *data, bool mode) 5091b3bd859SHimanshu Jha { 5101b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap); 5111b3bd859SHimanshu Jha int ret; 5121b3bd859SHimanshu Jha 5131b3bd859SHimanshu Jha if (mode) { 5141b3bd859SHimanshu Jha ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS, 5151b3bd859SHimanshu Jha BME680_MODE_MASK, BME680_MODE_FORCED); 5161b3bd859SHimanshu Jha if (ret < 0) 5171b3bd859SHimanshu Jha dev_err(dev, "failed to set forced mode\n"); 5181b3bd859SHimanshu Jha 5191b3bd859SHimanshu Jha } else { 5201b3bd859SHimanshu Jha ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS, 5211b3bd859SHimanshu Jha BME680_MODE_MASK, BME680_MODE_SLEEP); 5221b3bd859SHimanshu Jha if (ret < 0) 5231b3bd859SHimanshu Jha dev_err(dev, "failed to set sleep mode\n"); 5241b3bd859SHimanshu Jha 5251b3bd859SHimanshu Jha } 5261b3bd859SHimanshu Jha 5271b3bd859SHimanshu Jha return ret; 5281b3bd859SHimanshu Jha } 5291b3bd859SHimanshu Jha 53079fd571bSDavid Frey static u8 bme680_oversampling_to_reg(u8 val) 53179fd571bSDavid Frey { 53279fd571bSDavid Frey return ilog2(val) + 1; 53379fd571bSDavid Frey } 53479fd571bSDavid Frey 5351b3bd859SHimanshu Jha static int bme680_chip_config(struct bme680_data *data) 5361b3bd859SHimanshu Jha { 5371b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap); 5381b3bd859SHimanshu Jha int ret; 53979fd571bSDavid Frey u8 osrs; 54079fd571bSDavid Frey 54179fd571bSDavid Frey osrs = FIELD_PREP( 54279fd571bSDavid Frey BME680_OSRS_HUMIDITY_MASK, 54379fd571bSDavid Frey bme680_oversampling_to_reg(data->oversampling_humid)); 5441b3bd859SHimanshu Jha /* 5451b3bd859SHimanshu Jha * Highly recommended to set oversampling of humidity before 5461b3bd859SHimanshu Jha * temperature/pressure oversampling. 5471b3bd859SHimanshu Jha */ 5481b3bd859SHimanshu Jha ret = regmap_update_bits(data->regmap, BME680_REG_CTRL_HUMIDITY, 5491b3bd859SHimanshu Jha BME680_OSRS_HUMIDITY_MASK, osrs); 5501b3bd859SHimanshu Jha if (ret < 0) { 5511b3bd859SHimanshu Jha dev_err(dev, "failed to write ctrl_hum register\n"); 5521b3bd859SHimanshu Jha return ret; 5531b3bd859SHimanshu Jha } 5541b3bd859SHimanshu Jha 5551b3bd859SHimanshu Jha /* IIR filter settings */ 5561b3bd859SHimanshu Jha ret = regmap_update_bits(data->regmap, BME680_REG_CONFIG, 5571b3bd859SHimanshu Jha BME680_FILTER_MASK, 5581b3bd859SHimanshu Jha BME680_FILTER_COEFF_VAL); 5591b3bd859SHimanshu Jha if (ret < 0) { 5601b3bd859SHimanshu Jha dev_err(dev, "failed to write config register\n"); 5611b3bd859SHimanshu Jha return ret; 5621b3bd859SHimanshu Jha } 5631b3bd859SHimanshu Jha 56479fd571bSDavid Frey osrs = FIELD_PREP(BME680_OSRS_TEMP_MASK, 56579fd571bSDavid Frey bme680_oversampling_to_reg(data->oversampling_temp)) | 56679fd571bSDavid Frey FIELD_PREP(BME680_OSRS_PRESS_MASK, 56779fd571bSDavid Frey bme680_oversampling_to_reg(data->oversampling_press)); 5681b3bd859SHimanshu Jha ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS, 56979fd571bSDavid Frey BME680_OSRS_TEMP_MASK | BME680_OSRS_PRESS_MASK, 5701b3bd859SHimanshu Jha osrs); 5711b3bd859SHimanshu Jha if (ret < 0) 5721b3bd859SHimanshu Jha dev_err(dev, "failed to write ctrl_meas register\n"); 5731b3bd859SHimanshu Jha 5741b3bd859SHimanshu Jha return ret; 5751b3bd859SHimanshu Jha } 5761b3bd859SHimanshu Jha 5771b3bd859SHimanshu Jha static int bme680_gas_config(struct bme680_data *data) 5781b3bd859SHimanshu Jha { 5791b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap); 5801b3bd859SHimanshu Jha int ret; 5811b3bd859SHimanshu Jha u8 heatr_res, heatr_dur; 5821b3bd859SHimanshu Jha 5831b3bd859SHimanshu Jha heatr_res = bme680_calc_heater_res(data, data->heater_temp); 5841b3bd859SHimanshu Jha 5851b3bd859SHimanshu Jha /* set target heater temperature */ 5861b3bd859SHimanshu Jha ret = regmap_write(data->regmap, BME680_REG_RES_HEAT_0, heatr_res); 5871b3bd859SHimanshu Jha if (ret < 0) { 5881b3bd859SHimanshu Jha dev_err(dev, "failed to write res_heat_0 register\n"); 5891b3bd859SHimanshu Jha return ret; 5901b3bd859SHimanshu Jha } 5911b3bd859SHimanshu Jha 5921b3bd859SHimanshu Jha heatr_dur = bme680_calc_heater_dur(data->heater_dur); 5931b3bd859SHimanshu Jha 5941b3bd859SHimanshu Jha /* set target heating duration */ 5951b3bd859SHimanshu Jha ret = regmap_write(data->regmap, BME680_REG_GAS_WAIT_0, heatr_dur); 5961b3bd859SHimanshu Jha if (ret < 0) { 5975e457296SColin Ian King dev_err(dev, "failed to write gas_wait_0 register\n"); 5981b3bd859SHimanshu Jha return ret; 5991b3bd859SHimanshu Jha } 6001b3bd859SHimanshu Jha 6011691d4caSDavid Frey /* Enable the gas sensor and select heater profile set-point 0 */ 6021b3bd859SHimanshu Jha ret = regmap_update_bits(data->regmap, BME680_REG_CTRL_GAS_1, 6031b3bd859SHimanshu Jha BME680_RUN_GAS_MASK | BME680_NB_CONV_MASK, 6041691d4caSDavid Frey FIELD_PREP(BME680_RUN_GAS_MASK, 1) | 6051691d4caSDavid Frey FIELD_PREP(BME680_NB_CONV_MASK, 0)); 6061b3bd859SHimanshu Jha if (ret < 0) 6071b3bd859SHimanshu Jha dev_err(dev, "failed to write ctrl_gas_1 register\n"); 6081b3bd859SHimanshu Jha 6091b3bd859SHimanshu Jha return ret; 6101b3bd859SHimanshu Jha } 6111b3bd859SHimanshu Jha 6129436f45dSMike Looijmans static int bme680_read_temp(struct bme680_data *data, int *val) 6131b3bd859SHimanshu Jha { 6141b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap); 6151b3bd859SHimanshu Jha int ret; 6161b3bd859SHimanshu Jha __be32 tmp = 0; 6171b3bd859SHimanshu Jha s32 adc_temp; 6181b3bd859SHimanshu Jha s16 comp_temp; 6191b3bd859SHimanshu Jha 6201b3bd859SHimanshu Jha /* set forced mode to trigger measurement */ 6211b3bd859SHimanshu Jha ret = bme680_set_mode(data, true); 6221b3bd859SHimanshu Jha if (ret < 0) 6231b3bd859SHimanshu Jha return ret; 6241b3bd859SHimanshu Jha 6251b3bd859SHimanshu Jha ret = regmap_bulk_read(data->regmap, BME680_REG_TEMP_MSB, 626ce968fb6SJonathan Cameron &tmp, 3); 6271b3bd859SHimanshu Jha if (ret < 0) { 6281b3bd859SHimanshu Jha dev_err(dev, "failed to read temperature\n"); 6291b3bd859SHimanshu Jha return ret; 6301b3bd859SHimanshu Jha } 6311b3bd859SHimanshu Jha 6321b3bd859SHimanshu Jha adc_temp = be32_to_cpu(tmp) >> 12; 6331b3bd859SHimanshu Jha if (adc_temp == BME680_MEAS_SKIPPED) { 6341b3bd859SHimanshu Jha /* reading was skipped */ 6351b3bd859SHimanshu Jha dev_err(dev, "reading temperature skipped\n"); 6361b3bd859SHimanshu Jha return -EINVAL; 6371b3bd859SHimanshu Jha } 6381b3bd859SHimanshu Jha comp_temp = bme680_compensate_temp(data, adc_temp); 6391b3bd859SHimanshu Jha /* 6401b3bd859SHimanshu Jha * val might be NULL if we're called by the read_press/read_humid 6411b3bd859SHimanshu Jha * routine which is callled to get t_fine value used in 6421b3bd859SHimanshu Jha * compensate_press/compensate_humid to get compensated 6431b3bd859SHimanshu Jha * pressure/humidity readings. 6441b3bd859SHimanshu Jha */ 6459436f45dSMike Looijmans if (val) { 6469436f45dSMike Looijmans *val = comp_temp * 10; /* Centidegrees to millidegrees */ 6479436f45dSMike Looijmans return IIO_VAL_INT; 6481b3bd859SHimanshu Jha } 6491b3bd859SHimanshu Jha 6501b3bd859SHimanshu Jha return ret; 6511b3bd859SHimanshu Jha } 6521b3bd859SHimanshu Jha 6531b3bd859SHimanshu Jha static int bme680_read_press(struct bme680_data *data, 6541b3bd859SHimanshu Jha int *val, int *val2) 6551b3bd859SHimanshu Jha { 6561b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap); 6571b3bd859SHimanshu Jha int ret; 6581b3bd859SHimanshu Jha __be32 tmp = 0; 6591b3bd859SHimanshu Jha s32 adc_press; 6601b3bd859SHimanshu Jha 6611b3bd859SHimanshu Jha /* Read and compensate temperature to get a reading of t_fine */ 6629436f45dSMike Looijmans ret = bme680_read_temp(data, NULL); 6631b3bd859SHimanshu Jha if (ret < 0) 6641b3bd859SHimanshu Jha return ret; 6651b3bd859SHimanshu Jha 6661b3bd859SHimanshu Jha ret = regmap_bulk_read(data->regmap, BME680_REG_PRESS_MSB, 667ce968fb6SJonathan Cameron &tmp, 3); 6681b3bd859SHimanshu Jha if (ret < 0) { 6691b3bd859SHimanshu Jha dev_err(dev, "failed to read pressure\n"); 6701b3bd859SHimanshu Jha return ret; 6711b3bd859SHimanshu Jha } 6721b3bd859SHimanshu Jha 6731b3bd859SHimanshu Jha adc_press = be32_to_cpu(tmp) >> 12; 6741b3bd859SHimanshu Jha if (adc_press == BME680_MEAS_SKIPPED) { 6751b3bd859SHimanshu Jha /* reading was skipped */ 6761b3bd859SHimanshu Jha dev_err(dev, "reading pressure skipped\n"); 6771b3bd859SHimanshu Jha return -EINVAL; 6781b3bd859SHimanshu Jha } 6791b3bd859SHimanshu Jha 6801b3bd859SHimanshu Jha *val = bme680_compensate_press(data, adc_press); 6811b3bd859SHimanshu Jha *val2 = 100; 6821b3bd859SHimanshu Jha return IIO_VAL_FRACTIONAL; 6831b3bd859SHimanshu Jha } 6841b3bd859SHimanshu Jha 6851b3bd859SHimanshu Jha static int bme680_read_humid(struct bme680_data *data, 6861b3bd859SHimanshu Jha int *val, int *val2) 6871b3bd859SHimanshu Jha { 6881b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap); 6891b3bd859SHimanshu Jha int ret; 6901b3bd859SHimanshu Jha __be16 tmp = 0; 6911b3bd859SHimanshu Jha s32 adc_humidity; 6921b3bd859SHimanshu Jha u32 comp_humidity; 6931b3bd859SHimanshu Jha 6941b3bd859SHimanshu Jha /* Read and compensate temperature to get a reading of t_fine */ 6959436f45dSMike Looijmans ret = bme680_read_temp(data, NULL); 6961b3bd859SHimanshu Jha if (ret < 0) 6971b3bd859SHimanshu Jha return ret; 6981b3bd859SHimanshu Jha 6991b3bd859SHimanshu Jha ret = regmap_bulk_read(data->regmap, BM6880_REG_HUMIDITY_MSB, 700ce968fb6SJonathan Cameron &tmp, sizeof(tmp)); 7011b3bd859SHimanshu Jha if (ret < 0) { 7021b3bd859SHimanshu Jha dev_err(dev, "failed to read humidity\n"); 7031b3bd859SHimanshu Jha return ret; 7041b3bd859SHimanshu Jha } 7051b3bd859SHimanshu Jha 7061b3bd859SHimanshu Jha adc_humidity = be16_to_cpu(tmp); 7071b3bd859SHimanshu Jha if (adc_humidity == BME680_MEAS_SKIPPED) { 7081b3bd859SHimanshu Jha /* reading was skipped */ 7091b3bd859SHimanshu Jha dev_err(dev, "reading humidity skipped\n"); 7101b3bd859SHimanshu Jha return -EINVAL; 7111b3bd859SHimanshu Jha } 7121b3bd859SHimanshu Jha comp_humidity = bme680_compensate_humid(data, adc_humidity); 7131b3bd859SHimanshu Jha 7141b3bd859SHimanshu Jha *val = comp_humidity; 7151b3bd859SHimanshu Jha *val2 = 1000; 7161b3bd859SHimanshu Jha return IIO_VAL_FRACTIONAL; 7171b3bd859SHimanshu Jha } 7181b3bd859SHimanshu Jha 7191b3bd859SHimanshu Jha static int bme680_read_gas(struct bme680_data *data, 7201b3bd859SHimanshu Jha int *val) 7211b3bd859SHimanshu Jha { 7221b3bd859SHimanshu Jha struct device *dev = regmap_get_device(data->regmap); 7231b3bd859SHimanshu Jha int ret; 7241b3bd859SHimanshu Jha __be16 tmp = 0; 7251b3bd859SHimanshu Jha unsigned int check; 7261b3bd859SHimanshu Jha u16 adc_gas_res; 7271b3bd859SHimanshu Jha u8 gas_range; 7281b3bd859SHimanshu Jha 7291b3bd859SHimanshu Jha /* Set heater settings */ 7301b3bd859SHimanshu Jha ret = bme680_gas_config(data); 7311b3bd859SHimanshu Jha if (ret < 0) { 7321b3bd859SHimanshu Jha dev_err(dev, "failed to set gas config\n"); 7331b3bd859SHimanshu Jha return ret; 7341b3bd859SHimanshu Jha } 7351b3bd859SHimanshu Jha 7361b3bd859SHimanshu Jha /* set forced mode to trigger measurement */ 7371b3bd859SHimanshu Jha ret = bme680_set_mode(data, true); 7381b3bd859SHimanshu Jha if (ret < 0) 7391b3bd859SHimanshu Jha return ret; 7401b3bd859SHimanshu Jha 7411b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &check); 7421b3bd859SHimanshu Jha if (check & BME680_GAS_MEAS_BIT) { 7431b3bd859SHimanshu Jha dev_err(dev, "gas measurement incomplete\n"); 7441b3bd859SHimanshu Jha return -EBUSY; 7451b3bd859SHimanshu Jha } 7461b3bd859SHimanshu Jha 7471b3bd859SHimanshu Jha ret = regmap_read(data->regmap, BME680_REG_GAS_R_LSB, &check); 7481b3bd859SHimanshu Jha if (ret < 0) { 7491b3bd859SHimanshu Jha dev_err(dev, "failed to read gas_r_lsb register\n"); 7501b3bd859SHimanshu Jha return ret; 7511b3bd859SHimanshu Jha } 7521b3bd859SHimanshu Jha 7531b3bd859SHimanshu Jha /* 7541b3bd859SHimanshu Jha * occurs if either the gas heating duration was insuffient 7551b3bd859SHimanshu Jha * to reach the target heater temperature or the target 7561b3bd859SHimanshu Jha * heater temperature was too high for the heater sink to 7571b3bd859SHimanshu Jha * reach. 7581b3bd859SHimanshu Jha */ 7591b3bd859SHimanshu Jha if ((check & BME680_GAS_STAB_BIT) == 0) { 7601b3bd859SHimanshu Jha dev_err(dev, "heater failed to reach the target temperature\n"); 7611b3bd859SHimanshu Jha return -EINVAL; 7621b3bd859SHimanshu Jha } 7631b3bd859SHimanshu Jha 7641b3bd859SHimanshu Jha ret = regmap_bulk_read(data->regmap, BME680_REG_GAS_MSB, 765ce968fb6SJonathan Cameron &tmp, sizeof(tmp)); 7661b3bd859SHimanshu Jha if (ret < 0) { 7671b3bd859SHimanshu Jha dev_err(dev, "failed to read gas resistance\n"); 7681b3bd859SHimanshu Jha return ret; 7691b3bd859SHimanshu Jha } 7701b3bd859SHimanshu Jha 7711b3bd859SHimanshu Jha gas_range = check & BME680_GAS_RANGE_MASK; 7721b3bd859SHimanshu Jha adc_gas_res = be16_to_cpu(tmp) >> BME680_ADC_GAS_RES_SHIFT; 7731b3bd859SHimanshu Jha 7741b3bd859SHimanshu Jha *val = bme680_compensate_gas(data, adc_gas_res, gas_range); 7751b3bd859SHimanshu Jha return IIO_VAL_INT; 7761b3bd859SHimanshu Jha } 7771b3bd859SHimanshu Jha 7781b3bd859SHimanshu Jha static int bme680_read_raw(struct iio_dev *indio_dev, 7791b3bd859SHimanshu Jha struct iio_chan_spec const *chan, 7801b3bd859SHimanshu Jha int *val, int *val2, long mask) 7811b3bd859SHimanshu Jha { 7821b3bd859SHimanshu Jha struct bme680_data *data = iio_priv(indio_dev); 7831b3bd859SHimanshu Jha 7841b3bd859SHimanshu Jha switch (mask) { 7851b3bd859SHimanshu Jha case IIO_CHAN_INFO_PROCESSED: 7861b3bd859SHimanshu Jha switch (chan->type) { 7871b3bd859SHimanshu Jha case IIO_TEMP: 7889436f45dSMike Looijmans return bme680_read_temp(data, val); 7891b3bd859SHimanshu Jha case IIO_PRESSURE: 7901b3bd859SHimanshu Jha return bme680_read_press(data, val, val2); 7911b3bd859SHimanshu Jha case IIO_HUMIDITYRELATIVE: 7921b3bd859SHimanshu Jha return bme680_read_humid(data, val, val2); 7931b3bd859SHimanshu Jha case IIO_RESISTANCE: 7941b3bd859SHimanshu Jha return bme680_read_gas(data, val); 7951b3bd859SHimanshu Jha default: 7961b3bd859SHimanshu Jha return -EINVAL; 7971b3bd859SHimanshu Jha } 7981b3bd859SHimanshu Jha case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 7991b3bd859SHimanshu Jha switch (chan->type) { 8001b3bd859SHimanshu Jha case IIO_TEMP: 80179fd571bSDavid Frey *val = data->oversampling_temp; 8021b3bd859SHimanshu Jha return IIO_VAL_INT; 8031b3bd859SHimanshu Jha case IIO_PRESSURE: 80479fd571bSDavid Frey *val = data->oversampling_press; 8051b3bd859SHimanshu Jha return IIO_VAL_INT; 8061b3bd859SHimanshu Jha case IIO_HUMIDITYRELATIVE: 80779fd571bSDavid Frey *val = data->oversampling_humid; 8081b3bd859SHimanshu Jha return IIO_VAL_INT; 8091b3bd859SHimanshu Jha default: 8101b3bd859SHimanshu Jha return -EINVAL; 8111b3bd859SHimanshu Jha } 8121b3bd859SHimanshu Jha default: 8131b3bd859SHimanshu Jha return -EINVAL; 8141b3bd859SHimanshu Jha } 8151b3bd859SHimanshu Jha } 8161b3bd859SHimanshu Jha 81779fd571bSDavid Frey static bool bme680_is_valid_oversampling(int rate) 8181b3bd859SHimanshu Jha { 81979fd571bSDavid Frey return (rate > 0 && rate <= 16 && is_power_of_2(rate)); 8201b3bd859SHimanshu Jha } 8211b3bd859SHimanshu Jha 8221b3bd859SHimanshu Jha static int bme680_write_raw(struct iio_dev *indio_dev, 8231b3bd859SHimanshu Jha struct iio_chan_spec const *chan, 8241b3bd859SHimanshu Jha int val, int val2, long mask) 8251b3bd859SHimanshu Jha { 8261b3bd859SHimanshu Jha struct bme680_data *data = iio_priv(indio_dev); 8271b3bd859SHimanshu Jha 828892e62faSHimanshu Jha if (val2 != 0) 829892e62faSHimanshu Jha return -EINVAL; 830892e62faSHimanshu Jha 8311b3bd859SHimanshu Jha switch (mask) { 8321b3bd859SHimanshu Jha case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 83379fd571bSDavid Frey { 83479fd571bSDavid Frey if (!bme680_is_valid_oversampling(val)) 83579fd571bSDavid Frey return -EINVAL; 83679fd571bSDavid Frey 8371b3bd859SHimanshu Jha switch (chan->type) { 8381b3bd859SHimanshu Jha case IIO_TEMP: 83979fd571bSDavid Frey data->oversampling_temp = val; 84079fd571bSDavid Frey break; 8411b3bd859SHimanshu Jha case IIO_PRESSURE: 84279fd571bSDavid Frey data->oversampling_press = val; 84379fd571bSDavid Frey break; 8441b3bd859SHimanshu Jha case IIO_HUMIDITYRELATIVE: 84579fd571bSDavid Frey data->oversampling_humid = val; 84679fd571bSDavid Frey break; 8471b3bd859SHimanshu Jha default: 8481b3bd859SHimanshu Jha return -EINVAL; 8491b3bd859SHimanshu Jha } 85079fd571bSDavid Frey 85179fd571bSDavid Frey return bme680_chip_config(data); 85279fd571bSDavid Frey } 8531b3bd859SHimanshu Jha default: 8541b3bd859SHimanshu Jha return -EINVAL; 8551b3bd859SHimanshu Jha } 8561b3bd859SHimanshu Jha } 8571b3bd859SHimanshu Jha 8581b3bd859SHimanshu Jha static const char bme680_oversampling_ratio_show[] = "1 2 4 8 16"; 8591b3bd859SHimanshu Jha 8601b3bd859SHimanshu Jha static IIO_CONST_ATTR(oversampling_ratio_available, 8611b3bd859SHimanshu Jha bme680_oversampling_ratio_show); 8621b3bd859SHimanshu Jha 8631b3bd859SHimanshu Jha static struct attribute *bme680_attributes[] = { 8641b3bd859SHimanshu Jha &iio_const_attr_oversampling_ratio_available.dev_attr.attr, 8651b3bd859SHimanshu Jha NULL, 8661b3bd859SHimanshu Jha }; 8671b3bd859SHimanshu Jha 8681b3bd859SHimanshu Jha static const struct attribute_group bme680_attribute_group = { 8691b3bd859SHimanshu Jha .attrs = bme680_attributes, 8701b3bd859SHimanshu Jha }; 8711b3bd859SHimanshu Jha 8721b3bd859SHimanshu Jha static const struct iio_info bme680_info = { 8731b3bd859SHimanshu Jha .read_raw = &bme680_read_raw, 8741b3bd859SHimanshu Jha .write_raw = &bme680_write_raw, 8751b3bd859SHimanshu Jha .attrs = &bme680_attribute_group, 8761b3bd859SHimanshu Jha }; 8771b3bd859SHimanshu Jha 8781b3bd859SHimanshu Jha static const char *bme680_match_acpi_device(struct device *dev) 8791b3bd859SHimanshu Jha { 8801b3bd859SHimanshu Jha const struct acpi_device_id *id; 8811b3bd859SHimanshu Jha 8821b3bd859SHimanshu Jha id = acpi_match_device(dev->driver->acpi_match_table, dev); 8831b3bd859SHimanshu Jha if (!id) 8841b3bd859SHimanshu Jha return NULL; 8851b3bd859SHimanshu Jha 8861b3bd859SHimanshu Jha return dev_name(dev); 8871b3bd859SHimanshu Jha } 8881b3bd859SHimanshu Jha 8891b3bd859SHimanshu Jha int bme680_core_probe(struct device *dev, struct regmap *regmap, 8901b3bd859SHimanshu Jha const char *name) 8911b3bd859SHimanshu Jha { 8921b3bd859SHimanshu Jha struct iio_dev *indio_dev; 8931b3bd859SHimanshu Jha struct bme680_data *data; 89473f3bc6dSMike Looijmans unsigned int val; 8951b3bd859SHimanshu Jha int ret; 8961b3bd859SHimanshu Jha 89773f3bc6dSMike Looijmans ret = regmap_write(regmap, BME680_REG_SOFT_RESET, 89873f3bc6dSMike Looijmans BME680_CMD_SOFTRESET); 89973f3bc6dSMike Looijmans if (ret < 0) { 90073f3bc6dSMike Looijmans dev_err(dev, "Failed to reset chip\n"); 90173f3bc6dSMike Looijmans return ret; 90273f3bc6dSMike Looijmans } 90373f3bc6dSMike Looijmans 90473f3bc6dSMike Looijmans ret = regmap_read(regmap, BME680_REG_CHIP_ID, &val); 90573f3bc6dSMike Looijmans if (ret < 0) { 90673f3bc6dSMike Looijmans dev_err(dev, "Error reading chip ID\n"); 90773f3bc6dSMike Looijmans return ret; 90873f3bc6dSMike Looijmans } 90973f3bc6dSMike Looijmans 91073f3bc6dSMike Looijmans if (val != BME680_CHIP_ID_VAL) { 91173f3bc6dSMike Looijmans dev_err(dev, "Wrong chip ID, got %x expected %x\n", 91273f3bc6dSMike Looijmans val, BME680_CHIP_ID_VAL); 91373f3bc6dSMike Looijmans return -ENODEV; 91473f3bc6dSMike Looijmans } 91573f3bc6dSMike Looijmans 9161b3bd859SHimanshu Jha indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 9171b3bd859SHimanshu Jha if (!indio_dev) 9181b3bd859SHimanshu Jha return -ENOMEM; 9191b3bd859SHimanshu Jha 9201b3bd859SHimanshu Jha if (!name && ACPI_HANDLE(dev)) 9211b3bd859SHimanshu Jha name = bme680_match_acpi_device(dev); 9221b3bd859SHimanshu Jha 9231b3bd859SHimanshu Jha data = iio_priv(indio_dev); 9241b3bd859SHimanshu Jha dev_set_drvdata(dev, indio_dev); 9251b3bd859SHimanshu Jha data->regmap = regmap; 9261b3bd859SHimanshu Jha indio_dev->name = name; 9271b3bd859SHimanshu Jha indio_dev->channels = bme680_channels; 9281b3bd859SHimanshu Jha indio_dev->num_channels = ARRAY_SIZE(bme680_channels); 9291b3bd859SHimanshu Jha indio_dev->info = &bme680_info; 9301b3bd859SHimanshu Jha indio_dev->modes = INDIO_DIRECT_MODE; 9311b3bd859SHimanshu Jha 9321b3bd859SHimanshu Jha /* default values for the sensor */ 93379fd571bSDavid Frey data->oversampling_humid = 2; /* 2X oversampling rate */ 93479fd571bSDavid Frey data->oversampling_press = 4; /* 4X oversampling rate */ 93579fd571bSDavid Frey data->oversampling_temp = 8; /* 8X oversampling rate */ 9361b3bd859SHimanshu Jha data->heater_temp = 320; /* degree Celsius */ 9371b3bd859SHimanshu Jha data->heater_dur = 150; /* milliseconds */ 9381b3bd859SHimanshu Jha 9391b3bd859SHimanshu Jha ret = bme680_chip_config(data); 9401b3bd859SHimanshu Jha if (ret < 0) { 9411b3bd859SHimanshu Jha dev_err(dev, "failed to set chip_config data\n"); 9421b3bd859SHimanshu Jha return ret; 9431b3bd859SHimanshu Jha } 9441b3bd859SHimanshu Jha 9451b3bd859SHimanshu Jha ret = bme680_gas_config(data); 9461b3bd859SHimanshu Jha if (ret < 0) { 9471b3bd859SHimanshu Jha dev_err(dev, "failed to set gas config data\n"); 9481b3bd859SHimanshu Jha return ret; 9491b3bd859SHimanshu Jha } 9501b3bd859SHimanshu Jha 9511b3bd859SHimanshu Jha ret = bme680_read_calib(data, &data->bme680); 9521b3bd859SHimanshu Jha if (ret < 0) { 9531b3bd859SHimanshu Jha dev_err(dev, 9541b3bd859SHimanshu Jha "failed to read calibration coefficients at probe\n"); 9551b3bd859SHimanshu Jha return ret; 9561b3bd859SHimanshu Jha } 9571b3bd859SHimanshu Jha 9581b3bd859SHimanshu Jha return devm_iio_device_register(dev, indio_dev); 9591b3bd859SHimanshu Jha } 9601b3bd859SHimanshu Jha EXPORT_SYMBOL_GPL(bme680_core_probe); 9611b3bd859SHimanshu Jha 9621b3bd859SHimanshu Jha MODULE_AUTHOR("Himanshu Jha <himanshujha199640@gmail.com>"); 9631b3bd859SHimanshu Jha MODULE_DESCRIPTION("Bosch BME680 Driver"); 9641b3bd859SHimanshu Jha MODULE_LICENSE("GPL v2"); 965