summaryrefslogtreecommitdiff
path: root/drivers/iio/chemical/bme680_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/chemical/bme680_core.c')
-rw-r--r--drivers/iio/chemical/bme680_core.c487
1 files changed, 411 insertions, 76 deletions
diff --git a/drivers/iio/chemical/bme680_core.c b/drivers/iio/chemical/bme680_core.c
index 0b96534c6867..70f81c4a96ba 100644
--- a/drivers/iio/chemical/bme680_core.c
+++ b/drivers/iio/chemical/bme680_core.c
@@ -14,10 +14,16 @@
#include <linux/device.h>
#include <linux/log2.h>
#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#include <linux/unaligned.h>
@@ -95,6 +101,21 @@ struct bme680_calib {
s8 range_sw_err;
};
+/* values of CTRL_MEAS register */
+enum bme680_op_mode {
+ BME680_MODE_SLEEP = 0,
+ BME680_MODE_FORCED = 1,
+};
+
+enum bme680_scan {
+ BME680_TEMP,
+ BME680_PRESS,
+ BME680_HUMID,
+ BME680_GAS,
+};
+
+static const char *const bme680_supply_names[] = { "vdd", "vddio" };
+
struct bme680_data {
struct regmap *regmap;
struct bme680_calib bme680;
@@ -102,11 +123,17 @@ struct bme680_data {
u8 oversampling_temp;
u8 oversampling_press;
u8 oversampling_humid;
+ u8 preheat_curr_mA;
u16 heater_dur;
u16 heater_temp;
+ struct {
+ s32 chan[4];
+ aligned_s64 ts;
+ } scan;
+
union {
- u8 buf[3];
+ u8 buf[BME680_NUM_BULK_READ_REGS];
unsigned int check;
__be16 be16;
u8 bme680_cal_buf_1[BME680_CALIB_RANGE_1_LEN];
@@ -131,29 +158,73 @@ const struct regmap_config bme680_regmap_config = {
.val_bits = 8,
.max_register = 0xef,
.volatile_table = &bme680_volatile_table,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
-EXPORT_SYMBOL_NS(bme680_regmap_config, IIO_BME680);
+EXPORT_SYMBOL_NS(bme680_regmap_config, "IIO_BME680");
static const struct iio_chan_spec bme680_channels[] = {
{
.type = IIO_TEMP,
+ /* PROCESSED maintained for ABI backwards compatibility */
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
},
{
.type = IIO_PRESSURE,
+ /* PROCESSED maintained for ABI backwards compatibility */
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
},
{
.type = IIO_HUMIDITYRELATIVE,
+ /* PROCESSED maintained for ABI backwards compatibility */
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 2,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
},
{
.type = IIO_RESISTANCE,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .scan_index = 3,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+ {
+ .type = IIO_CURRENT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .output = 1,
+ .scan_index = -1,
},
};
@@ -224,7 +295,7 @@ static int bme680_read_calib(struct bme680_data *data,
calib->res_heat_val = data->bme680_cal_buf_3[RES_HEAT_VAL];
calib->res_heat_range = FIELD_GET(BME680_RHRANGE_MASK,
- data->bme680_cal_buf_3[RES_HEAT_RANGE]);
+ data->bme680_cal_buf_3[RES_HEAT_RANGE]);
calib->range_sw_err = FIELD_GET(BME680_RSERROR_MASK,
data->bme680_cal_buf_3[RANGE_SW_ERR]);
@@ -438,19 +509,19 @@ static u32 bme680_compensate_gas(struct bme680_data *data, u16 gas_res_adc,
u32 calc_gas_res;
/* Look up table for the possible gas range values */
- static const u32 lookupTable[16] = {2147483647u, 2147483647u,
- 2147483647u, 2147483647u, 2147483647u,
- 2126008810u, 2147483647u, 2130303777u,
- 2147483647u, 2147483647u, 2143188679u,
- 2136746228u, 2147483647u, 2126008810u,
- 2147483647u, 2147483647u};
-
- var1 = ((1340 + (5 * (s64) calib->range_sw_err)) *
- ((s64) lookupTable[gas_range])) >> 16;
+ static const u32 lookup_table[16] = {
+ 2147483647u, 2147483647u, 2147483647u, 2147483647u,
+ 2147483647u, 2126008810u, 2147483647u, 2130303777u,
+ 2147483647u, 2147483647u, 2143188679u, 2136746228u,
+ 2147483647u, 2126008810u, 2147483647u, 2147483647u
+ };
+
+ var1 = ((1340LL + (5 * calib->range_sw_err)) *
+ (lookup_table[gas_range])) >> 16;
var2 = ((gas_res_adc << 15) - 16777216) + var1;
var3 = ((125000 << (15 - gas_range)) * var1) >> 9;
var3 += (var2 >> 1);
- calc_gas_res = div64_s64(var3, (s64) var2);
+ calc_gas_res = div64_s64(var3, (s64)var2);
return calc_gas_res;
}
@@ -468,7 +539,7 @@ static u8 bme680_calc_heater_res(struct bme680_data *data, u16 temp)
if (temp > 400) /* Cap temperature */
temp = 400;
- var1 = (((s32) BME680_AMB_TEMP * calib->par_gh3) / 1000) * 256;
+ var1 = (((s32)BME680_AMB_TEMP * calib->par_gh3) / 1000) * 256;
var2 = (calib->par_gh1 + 784) * (((((calib->par_gh2 + 154009) *
temp * 5) / 100)
+ 3276800) / 10);
@@ -502,23 +573,22 @@ static u8 bme680_calc_heater_dur(u16 dur)
return durval;
}
-static int bme680_set_mode(struct bme680_data *data, bool mode)
+/* Taken from datasheet, section 5.3.3 */
+static u8 bme680_calc_heater_preheat_current(u8 curr)
+{
+ return 8 * curr - 1;
+}
+
+static int bme680_set_mode(struct bme680_data *data, enum bme680_op_mode mode)
{
struct device *dev = regmap_get_device(data->regmap);
int ret;
- if (mode) {
- ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
- BME680_MODE_MASK, BME680_MODE_FORCED);
- if (ret < 0)
- dev_err(dev, "failed to set forced mode\n");
-
- } else {
- ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
- BME680_MODE_MASK, BME680_MODE_SLEEP);
- if (ret < 0)
- dev_err(dev, "failed to set sleep mode\n");
-
+ ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
+ BME680_MODE_MASK, mode);
+ if (ret < 0) {
+ dev_err(dev, "failed to set ctrl_meas register\n");
+ return ret;
}
return ret;
@@ -546,7 +616,7 @@ static int bme680_wait_for_eoc(struct bme680_data *data)
data->oversampling_humid) * 1936) + (477 * 4) +
(477 * 5) + 1000 + (data->heater_dur * 1000);
- usleep_range(wait_eoc_us, wait_eoc_us + 100);
+ fsleep(wait_eoc_us);
ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &data->check);
if (ret) {
@@ -571,9 +641,8 @@ static int bme680_chip_config(struct bme680_data *data)
int ret;
u8 osrs;
- osrs = FIELD_PREP(
- BME680_OSRS_HUMIDITY_MASK,
- bme680_oversampling_to_reg(data->oversampling_humid));
+ osrs = FIELD_PREP(BME680_OSRS_HUMIDITY_MASK,
+ bme680_oversampling_to_reg(data->oversampling_humid));
/*
* Highly recommended to set oversampling of humidity before
* temperature/pressure oversampling.
@@ -587,8 +656,7 @@ static int bme680_chip_config(struct bme680_data *data)
/* IIR filter settings */
ret = regmap_update_bits(data->regmap, BME680_REG_CONFIG,
- BME680_FILTER_MASK,
- BME680_FILTER_COEFF_VAL);
+ BME680_FILTER_MASK, BME680_FILTER_COEFF_VAL);
if (ret < 0) {
dev_err(dev, "failed to write config register\n");
return ret;
@@ -609,14 +677,27 @@ static int bme680_chip_config(struct bme680_data *data)
return 0;
}
+static int bme680_preheat_curr_config(struct bme680_data *data, u8 val)
+{
+ struct device *dev = regmap_get_device(data->regmap);
+ u8 heatr_curr;
+ int ret;
+
+ heatr_curr = bme680_calc_heater_preheat_current(val);
+ ret = regmap_write(data->regmap, BME680_REG_IDAC_HEAT_0, heatr_curr);
+ if (ret < 0)
+ dev_err(dev, "failed to write idac_heat_0 register\n");
+
+ return ret;
+}
+
static int bme680_gas_config(struct bme680_data *data)
{
struct device *dev = regmap_get_device(data->regmap);
int ret;
u8 heatr_res, heatr_dur;
- /* Go to sleep */
- ret = bme680_set_mode(data, false);
+ ret = bme680_set_mode(data, BME680_MODE_SLEEP);
if (ret < 0)
return ret;
@@ -638,6 +719,10 @@ static int bme680_gas_config(struct bme680_data *data)
return ret;
}
+ ret = bme680_preheat_curr_config(data, data->preheat_curr_mA);
+ if (ret)
+ return ret;
+
/* Enable the gas sensor and select heater profile set-point 0 */
ret = regmap_update_bits(data->regmap, BME680_REG_CTRL_GAS_1,
BME680_RUN_GAS_MASK | BME680_NB_CONV_MASK,
@@ -649,23 +734,20 @@ static int bme680_gas_config(struct bme680_data *data)
return ret;
}
-static int bme680_read_temp(struct bme680_data *data, int *val)
+static int bme680_read_temp(struct bme680_data *data, s16 *comp_temp)
{
int ret;
u32 adc_temp;
- s16 comp_temp;
ret = bme680_read_temp_adc(data, &adc_temp);
if (ret)
return ret;
- comp_temp = bme680_compensate_temp(data, adc_temp);
- *val = comp_temp * 10; /* Centidegrees to millidegrees */
- return IIO_VAL_INT;
+ *comp_temp = bme680_compensate_temp(data, adc_temp);
+ return 0;
}
-static int bme680_read_press(struct bme680_data *data,
- int *val, int *val2)
+static int bme680_read_press(struct bme680_data *data, u32 *comp_press)
{
int ret;
u32 adc_press;
@@ -679,16 +761,14 @@ static int bme680_read_press(struct bme680_data *data,
if (ret)
return ret;
- *val = bme680_compensate_press(data, adc_press, t_fine);
- *val2 = 1000;
- return IIO_VAL_FRACTIONAL;
+ *comp_press = bme680_compensate_press(data, adc_press, t_fine);
+ return 0;
}
-static int bme680_read_humid(struct bme680_data *data,
- int *val, int *val2)
+static int bme680_read_humid(struct bme680_data *data, u32 *comp_humidity)
{
int ret;
- u32 adc_humidity, comp_humidity;
+ u32 adc_humidity;
s32 t_fine;
ret = bme680_get_t_fine(data, &t_fine);
@@ -699,15 +779,11 @@ static int bme680_read_humid(struct bme680_data *data,
if (ret)
return ret;
- comp_humidity = bme680_compensate_humid(data, adc_humidity, t_fine);
-
- *val = comp_humidity;
- *val2 = 1000;
- return IIO_VAL_FRACTIONAL;
+ *comp_humidity = bme680_compensate_humid(data, adc_humidity, t_fine);
+ return 0;
}
-static int bme680_read_gas(struct bme680_data *data,
- int *val)
+static int bme680_read_gas(struct bme680_data *data, int *comp_gas_res)
{
struct device *dev = regmap_get_device(data->regmap);
int ret;
@@ -742,22 +818,21 @@ static int bme680_read_gas(struct bme680_data *data,
}
gas_range = FIELD_GET(BME680_GAS_RANGE_MASK, gas_regs_val);
-
- *val = bme680_compensate_gas(data, adc_gas_res, gas_range);
- return IIO_VAL_INT;
+ *comp_gas_res = bme680_compensate_gas(data, adc_gas_res, gas_range);
+ return 0;
}
-static int bme680_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val, int *val2, long mask)
+static int __bme680_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
{
struct bme680_data *data = iio_priv(indio_dev);
- int ret;
+ int chan_val, ret;
+ s16 temp_chan_val;
guard(mutex)(&data->lock);
- /* set forced mode to trigger measurement */
- ret = bme680_set_mode(data, true);
+ ret = bme680_set_mode(data, BME680_MODE_FORCED);
if (ret < 0)
return ret;
@@ -769,13 +844,77 @@ static int bme680_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_PROCESSED:
switch (chan->type) {
case IIO_TEMP:
- return bme680_read_temp(data, val);
+ ret = bme680_read_temp(data, &temp_chan_val);
+ if (ret)
+ return ret;
+
+ *val = temp_chan_val * 10;
+ return IIO_VAL_INT;
case IIO_PRESSURE:
- return bme680_read_press(data, val, val2);
+ ret = bme680_read_press(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
case IIO_HUMIDITYRELATIVE:
- return bme680_read_humid(data, val, val2);
+ ret = bme680_read_humid(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
case IIO_RESISTANCE:
- return bme680_read_gas(data, val);
+ ret = bme680_read_gas(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_TEMP:
+ ret = bme680_read_temp(data, &temp_chan_val);
+ if (ret)
+ return ret;
+
+ *val = temp_chan_val;
+ return IIO_VAL_INT;
+ case IIO_PRESSURE:
+ ret = bme680_read_press(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ case IIO_HUMIDITYRELATIVE:
+ ret = bme680_read_humid(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ *val = 10;
+ return IIO_VAL_INT;
+ case IIO_PRESSURE:
+ *val = 1;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_HUMIDITYRELATIVE:
+ *val = 1;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
default:
return -EINVAL;
}
@@ -798,14 +937,32 @@ static int bme680_read_raw(struct iio_dev *indio_dev,
}
}
+static int bme680_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct bme680_data *data = iio_priv(indio_dev);
+ struct device *dev = regmap_get_device(data->regmap);
+ int ret;
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return ret;
+
+ ret = __bme680_read_raw(indio_dev, chan, val, val2, mask);
+ pm_runtime_put_autosuspend(dev);
+
+ return ret;
+}
+
static bool bme680_is_valid_oversampling(int rate)
{
return (rate > 0 && rate <= 16 && is_power_of_2(rate));
}
-static int bme680_write_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int val, int val2, long mask)
+static int __bme680_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
{
struct bme680_data *data = iio_priv(indio_dev);
@@ -836,11 +993,38 @@ static int bme680_write_raw(struct iio_dev *indio_dev,
return bme680_chip_config(data);
}
+ case IIO_CHAN_INFO_PROCESSED:
+ {
+ switch (chan->type) {
+ case IIO_CURRENT:
+ return bme680_preheat_curr_config(data, (u8)val);
+ default:
+ return -EINVAL;
+ }
+ }
default:
return -EINVAL;
}
}
+static int bme680_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct bme680_data *data = iio_priv(indio_dev);
+ struct device *dev = regmap_get_device(data->regmap);
+ int ret;
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return ret;
+
+ ret = __bme680_write_raw(indio_dev, chan, val, val2, mask);
+ pm_runtime_put_autosuspend(dev);
+
+ return ret;
+}
+
static const char bme680_oversampling_ratio_show[] = "1 2 4 8 16";
static IIO_CONST_ATTR(oversampling_ratio_available,
@@ -861,6 +1045,108 @@ static const struct iio_info bme680_info = {
.attrs = &bme680_attribute_group,
};
+static const unsigned long bme680_avail_scan_masks[] = {
+ BIT(BME680_GAS) | BIT(BME680_HUMID) | BIT(BME680_PRESS) | BIT(BME680_TEMP),
+ 0
+};
+
+static irqreturn_t bme680_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct bme680_data *data = iio_priv(indio_dev);
+ struct device *dev = regmap_get_device(data->regmap);
+ u32 adc_temp, adc_press, adc_humid;
+ u16 adc_gas_res, gas_regs_val;
+ u8 gas_range;
+ s32 t_fine;
+ int ret;
+
+ guard(mutex)(&data->lock);
+
+ ret = bme680_set_mode(data, BME680_MODE_FORCED);
+ if (ret < 0)
+ goto out;
+
+ ret = bme680_wait_for_eoc(data);
+ if (ret)
+ goto out;
+
+ ret = regmap_bulk_read(data->regmap, BME680_REG_MEAS_STAT_0,
+ data->buf, sizeof(data->buf));
+ if (ret) {
+ dev_err(dev, "failed to burst read sensor data\n");
+ goto out;
+ }
+ if (data->buf[0] & BME680_GAS_MEAS_BIT) {
+ dev_err(dev, "gas measurement incomplete\n");
+ goto out;
+ }
+
+ /* Temperature calculations */
+ adc_temp = FIELD_GET(BME680_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[5]));
+ if (adc_temp == BME680_MEAS_SKIPPED) {
+ dev_err(dev, "reading temperature skipped\n");
+ goto out;
+ }
+ data->scan.chan[0] = bme680_compensate_temp(data, adc_temp);
+ t_fine = bme680_calc_t_fine(data, adc_temp);
+
+ /* Pressure calculations */
+ adc_press = FIELD_GET(BME680_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[2]));
+ if (adc_press == BME680_MEAS_SKIPPED) {
+ dev_err(dev, "reading pressure skipped\n");
+ goto out;
+ }
+ data->scan.chan[1] = bme680_compensate_press(data, adc_press, t_fine);
+
+ /* Humidity calculations */
+ adc_humid = get_unaligned_be16(&data->buf[8]);
+ if (adc_humid == BME680_MEAS_SKIPPED) {
+ dev_err(dev, "reading humidity skipped\n");
+ goto out;
+ }
+ data->scan.chan[2] = bme680_compensate_humid(data, adc_humid, t_fine);
+
+ /* Gas calculations */
+ gas_regs_val = get_unaligned_be16(&data->buf[13]);
+ adc_gas_res = FIELD_GET(BME680_ADC_GAS_RES, gas_regs_val);
+ if ((gas_regs_val & BME680_GAS_STAB_BIT) == 0) {
+ dev_err(dev, "heater failed to reach the target temperature\n");
+ goto out;
+ }
+ gas_range = FIELD_GET(BME680_GAS_RANGE_MASK, gas_regs_val);
+ data->scan.chan[3] = bme680_compensate_gas(data, adc_gas_res, gas_range);
+
+ iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan),
+ iio_get_time_ns(indio_dev));
+out:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int bme680_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct bme680_data *data = iio_priv(indio_dev);
+ struct device *dev = regmap_get_device(data->regmap);
+
+ return pm_runtime_resume_and_get(dev);
+}
+
+static int bme680_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct bme680_data *data = iio_priv(indio_dev);
+ struct device *dev = regmap_get_device(data->regmap);
+
+ pm_runtime_put_autosuspend(dev);
+ return 0;
+}
+
+static const struct iio_buffer_setup_ops bme680_buffer_setup_ops = {
+ .preenable = bme680_buffer_preenable,
+ .postdisable = bme680_buffer_postdisable,
+};
+
int bme680_core_probe(struct device *dev, struct regmap *regmap,
const char *name)
{
@@ -879,6 +1165,7 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
indio_dev->name = name;
indio_dev->channels = bme680_channels;
indio_dev->num_channels = ARRAY_SIZE(bme680_channels);
+ indio_dev->available_scan_masks = bme680_avail_scan_masks;
indio_dev->info = &bme680_info;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -888,13 +1175,21 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
data->oversampling_temp = 8; /* 8X oversampling rate */
data->heater_temp = 320; /* degree Celsius */
data->heater_dur = 150; /* milliseconds */
+ data->preheat_curr_mA = 0;
+
+ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(bme680_supply_names),
+ bme680_supply_names);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to get and enable supplies.\n");
- ret = regmap_write(regmap, BME680_REG_SOFT_RESET,
- BME680_CMD_SOFTRESET);
+ fsleep(BME680_STARTUP_TIME_US);
+
+ ret = regmap_write(regmap, BME680_REG_SOFT_RESET, BME680_CMD_SOFTRESET);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to reset chip\n");
- usleep_range(BME680_STARTUP_TIME_US, BME680_STARTUP_TIME_US + 1000);
+ fsleep(BME680_STARTUP_TIME_US);
ret = regmap_read(regmap, BME680_REG_CHIP_ID, &data->check);
if (ret < 0)
@@ -922,9 +1217,49 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
return dev_err_probe(dev, ret,
"failed to set gas config data\n");
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ bme680_trigger_handler,
+ &bme680_buffer_setup_ops);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "iio triggered buffer setup failed\n");
+
+ /* Enable runtime PM */
+ pm_runtime_set_autosuspend_delay(dev, BME680_STARTUP_TIME_US);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_active(dev);
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(bme680_core_probe, IIO_BME680);
+EXPORT_SYMBOL_NS_GPL(bme680_core_probe, "IIO_BME680");
+
+static int bme680_runtime_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct bme680_data *data = iio_priv(indio_dev);
+
+ return bme680_set_mode(data, BME680_MODE_SLEEP);
+}
+
+static int bme680_runtime_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct bme680_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = bme680_chip_config(data);
+ if (ret)
+ return ret;
+
+ return bme680_gas_config(data);
+}
+
+EXPORT_RUNTIME_DEV_PM_OPS(bme680_dev_pm_ops, bme680_runtime_suspend,
+ bme680_runtime_resume, NULL);
MODULE_AUTHOR("Himanshu Jha <himanshujha199640@gmail.com>");
MODULE_DESCRIPTION("Bosch BME680 Driver");