提交 10b40ffb 编写于 作者: A Angel Iglesias 提交者: Jonathan Cameron

iio: pressure: bmp280: Add more tunable config parameters for BMP380

Allows sampling frequency and IIR filter coefficients configuration
using sysfs ABI.

The IIR filter coefficient is configurable using the sysfs attribute
"filter_low_pass_3db_frequency".
Signed-off-by: NAngel Iglesias <ang.iglesiasg@gmail.com>
Link: https://lore.kernel.org/r/876f8a2277f71672488e99aa02aae4239d530f51.1663025017.git.ang.iglesiasg@gmail.comSigned-off-by: NJonathan Cameron <Jonathan.Cameron@huawei.com>
上级 2a332dcd
...@@ -109,6 +109,27 @@ static const char *const bmp280_supply_names[] = { ...@@ -109,6 +109,27 @@ static const char *const bmp280_supply_names[] = {
#define BMP280_NUM_SUPPLIES ARRAY_SIZE(bmp280_supply_names) #define BMP280_NUM_SUPPLIES ARRAY_SIZE(bmp280_supply_names)
enum bmp380_odr {
BMP380_ODR_200HZ,
BMP380_ODR_100HZ,
BMP380_ODR_50HZ,
BMP380_ODR_25HZ,
BMP380_ODR_12_5HZ,
BMP380_ODR_6_25HZ,
BMP380_ODR_3_125HZ,
BMP380_ODR_1_5625HZ,
BMP380_ODR_0_78HZ,
BMP380_ODR_0_39HZ,
BMP380_ODR_0_2HZ,
BMP380_ODR_0_1HZ,
BMP380_ODR_0_05HZ,
BMP380_ODR_0_02HZ,
BMP380_ODR_0_01HZ,
BMP380_ODR_0_006HZ,
BMP380_ODR_0_003HZ,
BMP380_ODR_0_0015HZ,
};
struct bmp280_data { struct bmp280_data {
struct device *dev; struct device *dev;
struct mutex lock; struct mutex lock;
...@@ -128,6 +149,17 @@ struct bmp280_data { ...@@ -128,6 +149,17 @@ struct bmp280_data {
u8 oversampling_press; u8 oversampling_press;
u8 oversampling_temp; u8 oversampling_temp;
u8 oversampling_humid; u8 oversampling_humid;
u8 iir_filter_coeff;
/*
* BMP380 devices introduce sampling frequency configuration. See
* datasheet sections 3.3.3. and 4.3.19 for more details.
*
* BMx280 devices allowed indirect configuration of sampling frequency
* changing the t_standby duration between measurements, as detailed on
* section 3.6.3 of the datasheet.
*/
int sampling_freq;
/* /*
* Carryover value from temperature conversion, used in pressure * Carryover value from temperature conversion, used in pressure
...@@ -155,6 +187,7 @@ struct bmp280_data { ...@@ -155,6 +187,7 @@ struct bmp280_data {
struct bmp280_chip_info { struct bmp280_chip_info {
unsigned int id_reg; unsigned int id_reg;
const struct iio_chan_spec *channels;
int num_channels; int num_channels;
unsigned int start_up_time; unsigned int start_up_time;
...@@ -170,6 +203,14 @@ struct bmp280_chip_info { ...@@ -170,6 +203,14 @@ struct bmp280_chip_info {
int num_oversampling_humid_avail; int num_oversampling_humid_avail;
int oversampling_humid_default; int oversampling_humid_default;
const int *iir_filter_coeffs_avail;
int num_iir_filter_coeffs_avail;
int iir_filter_coeff_default;
const int (*sampling_freq_avail)[2];
int num_sampling_freq_avail;
int sampling_freq_default;
int (*chip_config)(struct bmp280_data *); int (*chip_config)(struct bmp280_data *);
int (*read_temp)(struct bmp280_data *, int *); int (*read_temp)(struct bmp280_data *, int *);
int (*read_press)(struct bmp280_data *, int *, int *); int (*read_press)(struct bmp280_data *, int *, int *);
...@@ -220,6 +261,30 @@ static const struct iio_chan_spec bmp280_channels[] = { ...@@ -220,6 +261,30 @@ static const struct iio_chan_spec bmp280_channels[] = {
}, },
}; };
static const struct iio_chan_spec bmp380_channels[] = {
{
.type = IIO_PRESSURE,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
},
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
},
{
.type = IIO_HUMIDITYRELATIVE,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
},
};
static int bmp280_read_calib(struct bmp280_data *data) static int bmp280_read_calib(struct bmp280_data *data)
{ {
struct bmp280_calib *calib = &data->calib.bmp280; struct bmp280_calib *calib = &data->calib.bmp280;
...@@ -550,6 +615,25 @@ static int bmp280_read_raw(struct iio_dev *indio_dev, ...@@ -550,6 +615,25 @@ static int bmp280_read_raw(struct iio_dev *indio_dev,
break; break;
} }
break; break;
case IIO_CHAN_INFO_SAMP_FREQ:
if (!data->chip_info->sampling_freq_avail) {
ret = -EINVAL;
break;
}
*val = data->chip_info->sampling_freq_avail[data->sampling_freq][0];
*val2 = data->chip_info->sampling_freq_avail[data->sampling_freq][1];
ret = IIO_VAL_INT_PLUS_MICRO;
break;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
if (!data->chip_info->iir_filter_coeffs_avail) {
ret = -EINVAL;
break;
}
*val = (1 << data->iir_filter_coeff) - 1;
ret = IIO_VAL_INT;
break;
default: default:
ret = -EINVAL; ret = -EINVAL;
break; break;
...@@ -567,13 +651,21 @@ static int bmp280_write_oversampling_ratio_humid(struct bmp280_data *data, ...@@ -567,13 +651,21 @@ static int bmp280_write_oversampling_ratio_humid(struct bmp280_data *data,
{ {
const int *avail = data->chip_info->oversampling_humid_avail; const int *avail = data->chip_info->oversampling_humid_avail;
const int n = data->chip_info->num_oversampling_humid_avail; const int n = data->chip_info->num_oversampling_humid_avail;
int ret, prev;
int i; int i;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (avail[i] == val) { if (avail[i] == val) {
prev = data->oversampling_humid;
data->oversampling_humid = ilog2(val); data->oversampling_humid = ilog2(val);
return data->chip_info->chip_config(data); ret = data->chip_info->chip_config(data);
if (ret) {
data->oversampling_humid = prev;
data->chip_info->chip_config(data);
return ret;
}
return 0;
} }
} }
return -EINVAL; return -EINVAL;
...@@ -584,13 +676,21 @@ static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data, ...@@ -584,13 +676,21 @@ static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data,
{ {
const int *avail = data->chip_info->oversampling_temp_avail; const int *avail = data->chip_info->oversampling_temp_avail;
const int n = data->chip_info->num_oversampling_temp_avail; const int n = data->chip_info->num_oversampling_temp_avail;
int ret, prev;
int i; int i;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (avail[i] == val) { if (avail[i] == val) {
prev = data->oversampling_temp;
data->oversampling_temp = ilog2(val); data->oversampling_temp = ilog2(val);
return data->chip_info->chip_config(data); ret = data->chip_info->chip_config(data);
if (ret) {
data->oversampling_temp = prev;
data->chip_info->chip_config(data);
return ret;
}
return 0;
} }
} }
return -EINVAL; return -EINVAL;
...@@ -601,13 +701,71 @@ static int bmp280_write_oversampling_ratio_press(struct bmp280_data *data, ...@@ -601,13 +701,71 @@ static int bmp280_write_oversampling_ratio_press(struct bmp280_data *data,
{ {
const int *avail = data->chip_info->oversampling_press_avail; const int *avail = data->chip_info->oversampling_press_avail;
const int n = data->chip_info->num_oversampling_press_avail; const int n = data->chip_info->num_oversampling_press_avail;
int ret, prev;
int i; int i;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (avail[i] == val) { if (avail[i] == val) {
prev = data->oversampling_press;
data->oversampling_press = ilog2(val); data->oversampling_press = ilog2(val);
return data->chip_info->chip_config(data); ret = data->chip_info->chip_config(data);
if (ret) {
data->oversampling_press = prev;
data->chip_info->chip_config(data);
return ret;
}
return 0;
}
}
return -EINVAL;
}
static int bmp280_write_sampling_frequency(struct bmp280_data *data,
int val, int val2)
{
const int (*avail)[2] = data->chip_info->sampling_freq_avail;
const int n = data->chip_info->num_sampling_freq_avail;
int ret, prev;
int i;
for (i = 0; i < n; i++) {
if (avail[i][0] == val && avail[i][1] == val2) {
prev = data->sampling_freq;
data->sampling_freq = i;
ret = data->chip_info->chip_config(data);
if (ret) {
data->sampling_freq = prev;
data->chip_info->chip_config(data);
return ret;
}
return 0;
}
}
return -EINVAL;
}
static int bmp280_write_iir_filter_coeffs(struct bmp280_data *data, int val)
{
const int *avail = data->chip_info->iir_filter_coeffs_avail;
const int n = data->chip_info->num_iir_filter_coeffs_avail;
int ret, prev;
int i;
for (i = 0; i < n; i++) {
if (avail[i] - 1 == val) {
prev = data->iir_filter_coeff;
data->iir_filter_coeff = i;
ret = data->chip_info->chip_config(data);
if (ret) {
data->iir_filter_coeff = prev;
data->chip_info->chip_config(data);
return ret;
}
return 0;
} }
} }
return -EINVAL; return -EINVAL;
...@@ -620,6 +778,12 @@ static int bmp280_write_raw(struct iio_dev *indio_dev, ...@@ -620,6 +778,12 @@ static int bmp280_write_raw(struct iio_dev *indio_dev,
struct bmp280_data *data = iio_priv(indio_dev); struct bmp280_data *data = iio_priv(indio_dev);
int ret = 0; int ret = 0;
/*
* Helper functions to update sensor running configuration.
* If an error happens applying new settings, will try restore
* previous parameters to ensure the sensor is left in a known
* working configuration.
*/
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_OVERSAMPLING_RATIO: case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
pm_runtime_get_sync(data->dev); pm_runtime_get_sync(data->dev);
...@@ -642,6 +806,22 @@ static int bmp280_write_raw(struct iio_dev *indio_dev, ...@@ -642,6 +806,22 @@ static int bmp280_write_raw(struct iio_dev *indio_dev,
pm_runtime_mark_last_busy(data->dev); pm_runtime_mark_last_busy(data->dev);
pm_runtime_put_autosuspend(data->dev); pm_runtime_put_autosuspend(data->dev);
break; break;
case IIO_CHAN_INFO_SAMP_FREQ:
pm_runtime_get_sync(data->dev);
mutex_lock(&data->lock);
ret = bmp280_write_sampling_frequency(data, val, val2);
mutex_unlock(&data->lock);
pm_runtime_mark_last_busy(data->dev);
pm_runtime_put_autosuspend(data->dev);
break;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
pm_runtime_get_sync(data->dev);
mutex_lock(&data->lock);
ret = bmp280_write_iir_filter_coeffs(data, val);
mutex_unlock(&data->lock);
pm_runtime_mark_last_busy(data->dev);
pm_runtime_put_autosuspend(data->dev);
break;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -672,6 +852,17 @@ static int bmp280_read_avail(struct iio_dev *indio_dev, ...@@ -672,6 +852,17 @@ static int bmp280_read_avail(struct iio_dev *indio_dev,
} }
*type = IIO_VAL_INT; *type = IIO_VAL_INT;
return IIO_AVAIL_LIST; return IIO_AVAIL_LIST;
case IIO_CHAN_INFO_SAMP_FREQ:
*vals = (const int *)data->chip_info->sampling_freq_avail;
*type = IIO_VAL_INT_PLUS_MICRO;
/* Values are stored in a 2D matrix */
*length = data->chip_info->num_sampling_freq_avail;
return IIO_AVAIL_LIST;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
*vals = data->chip_info->iir_filter_coeffs_avail;
*type = IIO_VAL_INT;
*length = data->chip_info->num_iir_filter_coeffs_avail;
return IIO_AVAIL_LIST;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -717,6 +908,7 @@ static const int bmp280_oversampling_avail[] = { 1, 2, 4, 8, 16 }; ...@@ -717,6 +908,7 @@ static const int bmp280_oversampling_avail[] = { 1, 2, 4, 8, 16 };
static const struct bmp280_chip_info bmp280_chip_info = { static const struct bmp280_chip_info bmp280_chip_info = {
.id_reg = BMP280_REG_ID, .id_reg = BMP280_REG_ID,
.start_up_time = 2000, .start_up_time = 2000,
.channels = bmp280_channels,
.num_channels = 2, .num_channels = 2,
.oversampling_temp_avail = bmp280_oversampling_avail, .oversampling_temp_avail = bmp280_oversampling_avail,
...@@ -764,6 +956,7 @@ static int bme280_chip_config(struct bmp280_data *data) ...@@ -764,6 +956,7 @@ static int bme280_chip_config(struct bmp280_data *data)
static const struct bmp280_chip_info bme280_chip_info = { static const struct bmp280_chip_info bme280_chip_info = {
.id_reg = BMP280_REG_ID, .id_reg = BMP280_REG_ID,
.start_up_time = 2000, .start_up_time = 2000,
.channels = bmp280_channels,
.num_channels = 3, .num_channels = 3,
.oversampling_temp_avail = bmp280_oversampling_avail, .oversampling_temp_avail = bmp280_oversampling_avail,
...@@ -1003,6 +1196,27 @@ static int bmp380_read_calib(struct bmp280_data *data) ...@@ -1003,6 +1196,27 @@ static int bmp380_read_calib(struct bmp280_data *data)
return 0; return 0;
} }
static const int bmp380_odr_table[][2] = {
[BMP380_ODR_200HZ] = {200, 0},
[BMP380_ODR_100HZ] = {100, 0},
[BMP380_ODR_50HZ] = {50, 0},
[BMP380_ODR_25HZ] = {25, 0},
[BMP380_ODR_12_5HZ] = {12, 500000},
[BMP380_ODR_6_25HZ] = {6, 250000},
[BMP380_ODR_3_125HZ] = {3, 125000},
[BMP380_ODR_1_5625HZ] = {1, 562500},
[BMP380_ODR_0_78HZ] = {0, 781250},
[BMP380_ODR_0_39HZ] = {0, 390625},
[BMP380_ODR_0_2HZ] = {0, 195313},
[BMP380_ODR_0_1HZ] = {0, 97656},
[BMP380_ODR_0_05HZ] = {0, 48828},
[BMP380_ODR_0_02HZ] = {0, 24414},
[BMP380_ODR_0_01HZ] = {0, 12207},
[BMP380_ODR_0_006HZ] = {0, 6104},
[BMP380_ODR_0_003HZ] = {0, 3052},
[BMP380_ODR_0_0015HZ] = {0, 1526},
};
static int bmp380_chip_config(struct bmp280_data *data) static int bmp380_chip_config(struct bmp280_data *data)
{ {
bool change = false, aux; bool change = false, aux;
...@@ -1036,21 +1250,23 @@ static int bmp380_chip_config(struct bmp280_data *data) ...@@ -1036,21 +1250,23 @@ static int bmp380_chip_config(struct bmp280_data *data)
change = change || aux; change = change || aux;
/* Configure output data rate */ /* Configure output data rate */
ret = regmap_update_bits(data->regmap, BMP380_REG_ODR, ret = regmap_update_bits_check(data->regmap, BMP380_REG_ODR,
BMP380_ODRS_MASK, BMP380_ODRS_50HZ); BMP380_ODRS_MASK, data->sampling_freq, &aux);
if (ret) { if (ret) {
dev_err(data->dev, "failed to write ODR selection register\n"); dev_err(data->dev, "failed to write ODR selection register\n");
return ret; return ret;
} }
change = change || aux;
/* Set filter data */ /* Set filter data */
ret = regmap_update_bits(data->regmap, BMP380_REG_CONFIG, ret = regmap_update_bits_check(data->regmap, BMP380_REG_CONFIG, BMP380_FILTER_MASK,
BMP380_FILTER_MASK, FIELD_PREP(BMP380_FILTER_MASK, data->iir_filter_coeff),
FIELD_PREP(BMP380_FILTER_MASK, BMP380_FILTER_3X)); &aux);
if (ret) { if (ret) {
dev_err(data->dev, "failed to write config register\n"); dev_err(data->dev, "failed to write config register\n");
return ret; return ret;
} }
change = change || aux;
if (change) { if (change) {
/* /*
...@@ -1101,10 +1317,12 @@ static int bmp380_chip_config(struct bmp280_data *data) ...@@ -1101,10 +1317,12 @@ static int bmp380_chip_config(struct bmp280_data *data)
} }
static const int bmp380_oversampling_avail[] = { 1, 2, 4, 8, 16, 32 }; static const int bmp380_oversampling_avail[] = { 1, 2, 4, 8, 16, 32 };
static const int bmp380_iir_filter_coeffs_avail[] = { 1, 2, 4, 8, 16, 32, 64, 128};
static const struct bmp280_chip_info bmp380_chip_info = { static const struct bmp280_chip_info bmp380_chip_info = {
.id_reg = BMP380_REG_ID, .id_reg = BMP380_REG_ID,
.start_up_time = 2000, .start_up_time = 2000,
.channels = bmp380_channels,
.num_channels = 2, .num_channels = 2,
.oversampling_temp_avail = bmp380_oversampling_avail, .oversampling_temp_avail = bmp380_oversampling_avail,
...@@ -1115,6 +1333,14 @@ static const struct bmp280_chip_info bmp380_chip_info = { ...@@ -1115,6 +1333,14 @@ static const struct bmp280_chip_info bmp380_chip_info = {
.num_oversampling_press_avail = ARRAY_SIZE(bmp380_oversampling_avail), .num_oversampling_press_avail = ARRAY_SIZE(bmp380_oversampling_avail),
.oversampling_press_default = ilog2(4), .oversampling_press_default = ilog2(4),
.sampling_freq_avail = bmp380_odr_table,
.num_sampling_freq_avail = ARRAY_SIZE(bmp380_odr_table) * 2,
.sampling_freq_default = BMP380_ODR_50HZ,
.iir_filter_coeffs_avail = bmp380_iir_filter_coeffs_avail,
.num_iir_filter_coeffs_avail = ARRAY_SIZE(bmp380_iir_filter_coeffs_avail),
.iir_filter_coeff_default = 2,
.chip_config = bmp380_chip_config, .chip_config = bmp380_chip_config,
.read_temp = bmp380_read_temp, .read_temp = bmp380_read_temp,
.read_press = bmp380_read_press, .read_press = bmp380_read_press,
...@@ -1356,6 +1582,7 @@ static const int bmp180_oversampling_press_avail[] = { 1, 2, 4, 8 }; ...@@ -1356,6 +1582,7 @@ static const int bmp180_oversampling_press_avail[] = { 1, 2, 4, 8 };
static const struct bmp280_chip_info bmp180_chip_info = { static const struct bmp280_chip_info bmp180_chip_info = {
.id_reg = BMP280_REG_ID, .id_reg = BMP280_REG_ID,
.start_up_time = 2000, .start_up_time = 2000,
.channels = bmp280_channels,
.num_channels = 2, .num_channels = 2,
.oversampling_temp_avail = bmp180_oversampling_temp_avail, .oversampling_temp_avail = bmp180_oversampling_temp_avail,
...@@ -1454,7 +1681,6 @@ int bmp280_common_probe(struct device *dev, ...@@ -1454,7 +1681,6 @@ int bmp280_common_probe(struct device *dev,
data->dev = dev; data->dev = dev;
indio_dev->name = name; indio_dev->name = name;
indio_dev->channels = bmp280_channels;
indio_dev->info = &bmp280_info; indio_dev->info = &bmp280_info;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
...@@ -1477,10 +1703,13 @@ int bmp280_common_probe(struct device *dev, ...@@ -1477,10 +1703,13 @@ int bmp280_common_probe(struct device *dev,
data->chip_info = chip_info; data->chip_info = chip_info;
/* Apply initial values from chip info structure */ /* Apply initial values from chip info structure */
indio_dev->channels = chip_info->channels;
indio_dev->num_channels = chip_info->num_channels; indio_dev->num_channels = chip_info->num_channels;
data->oversampling_press = chip_info->oversampling_press_default; data->oversampling_press = chip_info->oversampling_press_default;
data->oversampling_humid = chip_info->oversampling_humid_default; data->oversampling_humid = chip_info->oversampling_humid_default;
data->oversampling_temp = chip_info->oversampling_temp_default; data->oversampling_temp = chip_info->oversampling_temp_default;
data->iir_filter_coeff = chip_info->iir_filter_coeff_default;
data->sampling_freq = chip_info->sampling_freq_default;
data->start_up_time = chip_info->start_up_time; data->start_up_time = chip_info->start_up_time;
/* Bring up regulators */ /* Bring up regulators */
......
...@@ -54,24 +54,6 @@ ...@@ -54,24 +54,6 @@
#define BMP380_OSRS_PRESS_MASK GENMASK(2, 0) #define BMP380_OSRS_PRESS_MASK GENMASK(2, 0)
#define BMP380_ODRS_MASK GENMASK(4, 0) #define BMP380_ODRS_MASK GENMASK(4, 0)
#define BMP380_ODRS_200HZ 0x00
#define BMP380_ODRS_100HZ 0x01
#define BMP380_ODRS_50HZ 0x02
#define BMP380_ODRS_25HZ 0x03
#define BMP380_ODRS_12_5HZ 0x04
#define BMP380_ODRS_6_25HZ 0x05
#define BMP380_ODRS_3_1HZ 0x06
#define BMP380_ODRS_1_5HZ 0x07
#define BMP380_ODRS_0_78HZ 0x08
#define BMP380_ODRS_0_39HZ 0x09
#define BMP380_ODRS_0_2HZ 0x0A
#define BMP380_ODRS_0_1HZ 0x0B
#define BMP380_ODRS_0_05HZ 0x0C
#define BMP380_ODRS_0_02HZ 0x0D
#define BMP380_ODRS_0_01HZ 0x0E
#define BMP380_ODRS_0_006HZ 0x0F
#define BMP380_ODRS_0_003HZ 0x10
#define BMP380_ODRS_0_0015HZ 0x11
#define BMP380_CTRL_SENSORS_MASK GENMASK(1, 0) #define BMP380_CTRL_SENSORS_MASK GENMASK(1, 0)
#define BMP380_CTRL_SENSORS_PRESS_EN BIT(0) #define BMP380_CTRL_SENSORS_PRESS_EN BIT(0)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册