All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jonathan Cameron <jic23@kernel.org>
To: Akinobu Mita <akinobu.mita@gmail.com>, linux-iio@vger.kernel.org
Cc: Vlad Dogaru <vlad.dogaru@intel.com>,
	Christoph Mair <christoph.mair@gmail.com>,
	Hartmut Knaack <knaack.h@gmx.de>,
	Lars-Peter Clausen <lars@metafoo.de>,
	Peter Meerwald <pmeerw@pmeerw.net>
Subject: Re: [PATCH v2 2/2] iio: pressure: bmp280: add ability to control oversampling rate
Date: Sat, 16 Apr 2016 11:08:47 +0100	[thread overview]
Message-ID: <57120F2F.1040302@kernel.org> (raw)
In-Reply-To: <1460742827-6502-3-git-send-email-akinobu.mita@gmail.com>

On 15/04/16 18:53, Akinobu Mita wrote:
> This adds ability to control the oversampling ratio of the temperature
> and pressure measurement for both bmp180 and bmp280.
> (bmp280 is untested for now)
> 
> Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
> Cc: Vlad Dogaru <vlad.dogaru@intel.com>
> Cc: Christoph Mair <christoph.mair@gmail.com>
> Cc: Jonathan Cameron <jic23@kernel.org>
> Cc: Hartmut Knaack <knaack.h@gmx.de>
> Cc: Lars-Peter Clausen <lars@metafoo.de>
> Cc: Peter Meerwald <pmeerw@pmeerw.net>
This looks good to me...

Jonathan
> ---
>  drivers/iio/pressure/bmp280.c | 202 ++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 184 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c
> index 28daa74..fd931c7 100644
> --- a/drivers/iio/pressure/bmp280.c
> +++ b/drivers/iio/pressure/bmp280.c
> @@ -50,19 +50,21 @@
>  
>  #define BMP280_OSRS_TEMP_MASK		(BIT(7) | BIT(6) | BIT(5))
>  #define BMP280_OSRS_TEMP_SKIP		0
> -#define BMP280_OSRS_TEMP_1X		BIT(5)
> -#define BMP280_OSRS_TEMP_2X		BIT(6)
> -#define BMP280_OSRS_TEMP_4X		(BIT(6) | BIT(5))
> -#define BMP280_OSRS_TEMP_8X		BIT(7)
> -#define BMP280_OSRS_TEMP_16X		(BIT(7) | BIT(5))
> +#define BMP280_OSRS_TEMP_X(osrs_t)	((osrs_t) << 5)
> +#define BMP280_OSRS_TEMP_1X		BMP280_OSRS_TEMP_X(1)
> +#define BMP280_OSRS_TEMP_2X		BMP280_OSRS_TEMP_X(2)
> +#define BMP280_OSRS_TEMP_4X		BMP280_OSRS_TEMP_X(3)
> +#define BMP280_OSRS_TEMP_8X		BMP280_OSRS_TEMP_X(4)
> +#define BMP280_OSRS_TEMP_16X		BMP280_OSRS_TEMP_X(5)
>  
>  #define BMP280_OSRS_PRESS_MASK		(BIT(4) | BIT(3) | BIT(2))
>  #define BMP280_OSRS_PRESS_SKIP		0
> -#define BMP280_OSRS_PRESS_1X		BIT(2)
> -#define BMP280_OSRS_PRESS_2X		BIT(3)
> -#define BMP280_OSRS_PRESS_4X		(BIT(3) | BIT(2))
> -#define BMP280_OSRS_PRESS_8X		BIT(4)
> -#define BMP280_OSRS_PRESS_16X		(BIT(4) | BIT(2))
> +#define BMP280_OSRS_PRESS_X(osrs_p)	((osrs_p) << 2)
> +#define BMP280_OSRS_PRESS_1X		BMP280_OSRS_PRESS_X(1)
> +#define BMP280_OSRS_PRESS_2X		BMP280_OSRS_PRESS_X(2)
> +#define BMP280_OSRS_PRESS_4X		BMP280_OSRS_PRESS_X(3)
> +#define BMP280_OSRS_PRESS_8X		BMP280_OSRS_PRESS_X(4)
> +#define BMP280_OSRS_PRESS_16X		BMP280_OSRS_PRESS_X(5)
>  
>  #define BMP280_MODE_MASK		(BIT(1) | BIT(0))
>  #define BMP280_MODE_SLEEP		0
> @@ -104,6 +106,9 @@ struct bmp280_data {
>  	struct regmap *regmap;
>  	const struct bmp280_chip_info *chip_info;
>  
> +	u8 oversampling_press;
> +	u8 oversampling_temp;
> +
>  	/*
>  	 * Carryover value from temperature conversion, used in pressure
>  	 * calculation.
> @@ -114,6 +119,12 @@ struct bmp280_data {
>  struct bmp280_chip_info {
>  	const struct regmap_config *regmap_config;
>  
> +	const int *oversampling_temp_avail;
> +	int num_oversampling_temp_avail;
> +
> +	const int *oversampling_press_avail;
> +	int num_oversampling_press_avail;
> +
>  	int (*chip_config)(struct bmp280_data *);
>  	int (*read_temp)(struct bmp280_data *, int *);
>  	int (*read_press)(struct bmp280_data *, int *, int *);
> @@ -129,11 +140,13 @@ 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),
> +		.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),
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
> +				      BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
>  	},
>  };
>  
> @@ -339,6 +352,21 @@ static int bmp280_read_raw(struct iio_dev *indio_dev,
>  			break;
>  		}
>  		break;
> +	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> +		switch (chan->type) {
> +		case IIO_PRESSURE:
> +			*val = 1 << data->oversampling_press;
> +			ret = IIO_VAL_INT;
> +			break;
> +		case IIO_TEMP:
> +			*val = 1 << data->oversampling_temp;
> +			ret = IIO_VAL_INT;
> +			break;
> +		default:
> +			ret = -EINVAL;
> +			break;
> +		}
> +		break;
>  	default:
>  		ret = -EINVAL;
>  		break;
> @@ -349,22 +377,135 @@ static int bmp280_read_raw(struct iio_dev *indio_dev,
>  	return ret;
>  }
>  
> +static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data,
> +					       int val)
> +{
> +	int i;
> +	const int *avail = data->chip_info->oversampling_temp_avail;
> +	const int n = data->chip_info->num_oversampling_temp_avail;
> +
> +	for (i = 0; i < n; i++) {
> +		if (avail[i] == val) {
> +			data->oversampling_temp = ilog2(val);
> +
> +			return data->chip_info->chip_config(data);
> +		}
> +	}
> +	return -EINVAL;
> +}
> +
> +static int bmp280_write_oversampling_ratio_press(struct bmp280_data *data,
> +					       int val)
> +{
> +	int i;
> +	const int *avail = data->chip_info->oversampling_press_avail;
> +	const int n = data->chip_info->num_oversampling_press_avail;
> +
> +	for (i = 0; i < n; i++) {
> +		if (avail[i] == val) {
> +			data->oversampling_press = ilog2(val);
> +
> +			return data->chip_info->chip_config(data);
> +		}
> +	}
> +	return -EINVAL;
> +}
> +
> +static int bmp280_write_raw(struct iio_dev *indio_dev,
> +			    struct iio_chan_spec const *chan,
> +			    int val, int val2, long mask)
> +{
> +	int ret = 0;
> +	struct bmp280_data *data = iio_priv(indio_dev);
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> +		mutex_lock(&data->lock);
> +		switch (chan->type) {
> +		case IIO_PRESSURE:
> +			ret = bmp280_write_oversampling_ratio_press(data, val);
> +			break;
> +		case IIO_TEMP:
> +			ret = bmp280_write_oversampling_ratio_temp(data, val);
> +			break;
> +		default:
> +			ret = -EINVAL;
> +			break;
> +		}
> +		mutex_unlock(&data->lock);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
> +static ssize_t bmp280_show_avail(char *buf, const int *vals, const int n)
> +{
> +	size_t len = 0;
> +	int i;
> +
> +	for (i = 0; i < n; i++)
> +		len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", vals[i]);
> +
> +	buf[len - 1] = '\n';
> +
> +	return len;
> +}
> +
> +static ssize_t bmp280_show_temp_oversampling_avail(struct device *dev,
> +				struct device_attribute *attr, char *buf)
> +{
> +	struct bmp280_data *data = iio_priv(dev_to_iio_dev(dev));
> +
> +	return bmp280_show_avail(buf, data->chip_info->oversampling_temp_avail,
> +				 data->chip_info->num_oversampling_temp_avail);
> +}
> +
> +static ssize_t bmp280_show_press_oversampling_avail(struct device *dev,
> +				struct device_attribute *attr, char *buf)
> +{
> +	struct bmp280_data *data = iio_priv(dev_to_iio_dev(dev));
> +
> +	return bmp280_show_avail(buf, data->chip_info->oversampling_press_avail,
> +				 data->chip_info->num_oversampling_press_avail);
> +}
> +
> +static IIO_DEVICE_ATTR(in_temp_oversampling_ratio_available,
> +	S_IRUGO, bmp280_show_temp_oversampling_avail, NULL, 0);
> +
> +static IIO_DEVICE_ATTR(in_pressure_oversampling_ratio_available,
> +	S_IRUGO, bmp280_show_press_oversampling_avail, NULL, 0);
> +
> +static struct attribute *bmp280_attributes[] = {
> +	&iio_dev_attr_in_temp_oversampling_ratio_available.dev_attr.attr,
> +	&iio_dev_attr_in_pressure_oversampling_ratio_available.dev_attr.attr,
> +	NULL,
> +};
> +
> +static const struct attribute_group bmp280_attrs_group = {
> +	.attrs = bmp280_attributes,
> +};
> +
>  static const struct iio_info bmp280_info = {
>  	.driver_module = THIS_MODULE,
>  	.read_raw = &bmp280_read_raw,
> +	.write_raw = &bmp280_write_raw,
> +	.attrs = &bmp280_attrs_group,
>  };
>  
>  static int bmp280_chip_config(struct bmp280_data *data)
>  {
>  	int ret;
> +	u8 osrs = BMP280_OSRS_TEMP_X(data->oversampling_temp) |
> +		  BMP280_OSRS_PRESS_X(data->oversampling_press);
>  
>  	ret = regmap_update_bits(data->regmap, BMP280_REG_CTRL_MEAS,
>  				 BMP280_OSRS_TEMP_MASK |
>  				 BMP280_OSRS_PRESS_MASK |
>  				 BMP280_MODE_MASK,
> -				 BMP280_OSRS_TEMP_2X |
> -				 BMP280_OSRS_PRESS_16X |
> -				 BMP280_MODE_NORMAL);
> +				 osrs | BMP280_MODE_NORMAL);
>  	if (ret < 0) {
>  		dev_err(&data->client->dev,
>  			"failed to write ctrl_meas register\n");
> @@ -383,8 +524,17 @@ static int bmp280_chip_config(struct bmp280_data *data)
>  	return ret;
>  }
>  
> +static const int bmp280_oversampling_avail[] = { 1, 2, 4, 8, 16 };
> +
>  static const struct bmp280_chip_info bmp280_chip_info = {
>  	.regmap_config = &bmp280_regmap_config,
> +
> +	.oversampling_temp_avail = bmp280_oversampling_avail,
> +	.num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail),
> +
> +	.oversampling_press_avail = bmp280_oversampling_avail,
> +	.num_oversampling_press_avail = ARRAY_SIZE(bmp280_oversampling_avail),
> +
>  	.chip_config = bmp280_chip_config,
>  	.read_temp = bmp280_read_temp,
>  	.read_press = bmp280_read_press,
> @@ -439,7 +589,7 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
>  	if (ctrl_meas == BMP180_MEAS_TEMP)
>  		delay_us = 4500;
>  	else
> -		delay_us = conversion_time_max[ilog2(8)];
> +		delay_us = conversion_time_max[data->oversampling_press];
>  
>  	usleep_range(delay_us, delay_us + 1000);
>  
> @@ -591,7 +741,7 @@ static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
>  {
>  	int ret;
>  	__be32 tmp = 0;
> -	u8 oss = ilog2(8);
> +	u8 oss = data->oversampling_press;
>  
>  	ret = bmp180_measure(data, BMP180_MEAS_PRESS_X(oss));
>  	if (ret)
> @@ -617,7 +767,7 @@ static u32 bmp180_compensate_press(struct bmp280_data *data, s32 adc_press)
>  	s32 x1, x2, x3, p;
>  	s32 b3, b6;
>  	u32 b4, b7;
> -	s32 oss = ilog2(8);
> +	s32 oss = data->oversampling_press;
>  	struct bmp180_calib calib;
>  
>  	ret = bmp180_read_calib(data, &calib);
> @@ -678,8 +828,20 @@ static int bmp180_chip_config(struct bmp280_data *data)
>  	return 0;
>  }
>  
> +static const int bmp180_oversampling_temp_avail[] = { 1 };
> +static const int bmp180_oversampling_press_avail[] = { 1, 2, 4, 8 };
> +
>  static const struct bmp280_chip_info bmp180_chip_info = {
>  	.regmap_config = &bmp180_regmap_config,
> +
> +	.oversampling_temp_avail = bmp180_oversampling_temp_avail,
> +	.num_oversampling_temp_avail =
> +		ARRAY_SIZE(bmp180_oversampling_temp_avail),
> +
> +	.oversampling_press_avail = bmp180_oversampling_press_avail,
> +	.num_oversampling_press_avail =
> +		ARRAY_SIZE(bmp180_oversampling_press_avail),
> +
>  	.chip_config = bmp180_chip_config,
>  	.read_temp = bmp180_read_temp,
>  	.read_press = bmp180_read_press,
> @@ -711,9 +873,13 @@ static int bmp280_probe(struct i2c_client *client,
>  	switch (id->driver_data) {
>  	case BMP180_CHIP_ID:
>  		data->chip_info = &bmp180_chip_info;
> +		data->oversampling_press = ilog2(8);
> +		data->oversampling_temp = ilog2(1);
>  		break;
>  	case BMP280_CHIP_ID:
>  		data->chip_info = &bmp280_chip_info;
> +		data->oversampling_press = ilog2(16);
> +		data->oversampling_temp = ilog2(2);
>  		break;
>  	default:
>  		return -EINVAL;
> 


  reply	other threads:[~2016-04-16 10:08 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-15 17:53 [PATCH v2 0/2] iio: pressure: bmp280: add support for BMP180 and oversampling rate control Akinobu Mita
2016-04-15 17:53 ` [PATCH v2 1/2] iio: pressure: bmp280: add support for BMP180 Akinobu Mita
2016-04-16 10:04   ` Jonathan Cameron
2016-04-18 12:01     ` Vlad Dogaru
2016-04-18 13:47       ` jic23
2016-04-15 17:53 ` [PATCH v2 2/2] iio: pressure: bmp280: add ability to control oversampling rate Akinobu Mita
2016-04-16 10:08   ` Jonathan Cameron [this message]
2016-04-18 11:52   ` Vlad Dogaru
2016-04-18 13:46     ` Akinobu Mita

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=57120F2F.1040302@kernel.org \
    --to=jic23@kernel.org \
    --cc=akinobu.mita@gmail.com \
    --cc=christoph.mair@gmail.com \
    --cc=knaack.h@gmx.de \
    --cc=lars@metafoo.de \
    --cc=linux-iio@vger.kernel.org \
    --cc=pmeerw@pmeerw.net \
    --cc=vlad.dogaru@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.