/*
* Copyright (c) 2010 Christoph Mair <christoph.mair@gmail.com>
* Copyright (c) 2012 Bosch Sensortec GmbH
* Copyright (c) 2012 Unixphere AB
* Copyright (c) 2014 Intel Corporation
* Copyright (c) 2016 Linus Walleij <linus.walleij@linaro.org>
*
* Driver for Bosch Sensortec BMP180 and BMP280 digital pressure sensor.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Datasheet:
* https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP180-DS000-121.pdf
* https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP280-DS001-12.pdf
* https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME280_DS001-11.pdf
*/
#define pr_fmt(fmt) "bmp280: " fmt
#include <linux/device.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/gpio/consumer.h>
#include <linux/regulator/consumer.h>
#include <linux/interrupt.h>
#include <linux/irq.h> /* For irq_get_irq_data() */
#include <linux/completion.h>
#include "bmp280.h"
struct bmp280_data {
struct device *dev;
struct mutex lock;
struct regmap *regmap;
struct completion done;
bool use_eoc;
const struct bmp280_chip_info *chip_info;
struct regulator *vddd;
struct regulator *vdda;
unsigned int start_up_time; /* in milliseconds */
/* log of base 2 of oversampling rate */
u8 oversampling_press;
u8 oversampling_temp;
u8 oversampling_humid;
/*
* Carryover value from temperature conversion, used in pressure
* calculation.
*/
s32 t_fine;
};
struct bmp280_chip_info {
const int *oversampling_temp_avail;
int num_oversampling_temp_avail;
const int *oversampling_press_avail;
int num_oversampling_press_avail;
const int *oversampling_humid_avail;
int num_oversampling_humid_avail;
int (*chip_config)(struct bmp280_data *);
int (*read_temp)(struct bmp280_data *, int *);
int (*read_press)(struct bmp280_data *, int *, int *);
int (*read_humid)(struct bmp280_data *, int *, int *);
};
/*
* These enums are used for indexing into the array of compensation
* parameters for BMP280.
*/
enum { T1, T2, T3 };
enum { P1, P2, P3, P4, P5, P6, P7, P8, P9 };
static const struct iio_chan_spec bmp280_channels[] = {
{
.type = IIO_PRESSURE,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
},
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
},
{
.type = IIO_HUMIDITYRELATIVE,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
},
};
/*
* Returns humidity in percent, resolution is 0.01 percent. Output value of
* "47445" represents 47445/1024 = 46.333 %RH.
*
* Taken from BME280 datasheet, Section 4.2.3, "Compensation formula".
*/
static u32 bmp280_compensate_humidity(struct bmp280_data *data,
s32 adc_humidity)
{
struct device *dev = data->dev;
unsigned int H1, H3, tmp;
int H2, H4, H5, H6, ret, var;
ret = regmap_read(data->regmap, BMP280_REG_COMP_H1, &H1);
if (ret < 0) {
dev_err(dev, "failed to read H1 comp value\n");
return ret;
}
ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H2, &tmp, 2);
if (ret < 0) {
dev_err(dev, "failed to read H2 comp value\n");
return ret;
}
H2 = sign_extend32(le16_to_cpu(tmp), 15);
ret = regmap_read(data->regmap, BMP280_REG_COMP_H3, &H3);
if (ret < 0) {
dev_err(dev, "failed to read H3 comp value\n");
return ret;
}
ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H4, &tmp, 2);
if (ret < 0) {
dev_err(dev, "failed to read H4 comp value\n");
return ret;
}
H4 = sign_extend32(((be16_to_cpu(tmp) >> 4)