linux-iio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jonathan Cameron <jic23@kernel.org>
To: Laurentiu Palcu <laurentiu.palcu@intel.com>, linux-iio@vger.kernel.org
Cc: srinivas.pandruvada@linux.intel.com, knaack.h@gmx.de,
	lars@metafoo.de, pmeerw@pmeerw.net, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 3/3] iio: accel: BMC150: add support for other Bosch chips
Date: Sat, 30 Aug 2014 11:54:05 +0100	[thread overview]
Message-ID: <5401AD4D.3060607@kernel.org> (raw)
In-Reply-To: <1409301488-22166-4-git-send-email-laurentiu.palcu@intel.com>

On 29/08/14 09:38, Laurentiu Palcu wrote:
> The following chips are either similar or have only the resolution
> different. Hence, change this driver to support these chips too:
>
> BMI055  - combo chip (accelerometer part is identical to BMC150's)
> BMA255  - identical to BMC150's accelerometer
> BMA222E - 8 bit resolution
> BMA250E - 10 bit resolution
> BMA280  - 14 bit resolution
>
> Additionally:
>  * add bmc150_accel_match_acpi_device() function to check that the device
>    has been enumerated through ACPI;
>  * rename bmc150_accel_acpi_gpio_probe() to bmc150_accel_gpio_probe()
>    since the ACPI matching has been moved to the new function.  Also, this
>    will allow for the GPIO matching to be done against a device tree too, not only
>    ACPI tree;
>
A few minor bits and more const char * casting to char * and back again that
needs looking at.  As it's Srinivas' driver, I'd like an ack from him if
possible.

I'm lazy so didn't actually check all those scale values etc :)

Thanks,

Jonathan

> Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
> ---
>  drivers/iio/accel/bmc150-accel.c | 229 ++++++++++++++++++++++++++++++---------
>  1 file changed, 176 insertions(+), 53 deletions(-)
>
> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> index 0e6566a..ffe619c 100644
> --- a/drivers/iio/accel/bmc150-accel.c
> +++ b/drivers/iio/accel/bmc150-accel.c
> @@ -1,5 +1,12 @@
>  /*
> - * BMC150 3-axis accelerometer driver
> + * 3-axis accelerometer driver supporting following Bosch-Sensortec chips:
> + *  - BMC150
> + *  - BMI055
> + *  - BMA255
> + *  - BMA250E
> + *  - BMA222E
> + *  - BMA280
> + *
>   * Copyright (c) 2014, Intel Corporation.
>   *
>   * This program is free software; you can redistribute it and/or modify it
> @@ -35,6 +42,11 @@
>
>  #define BMC150_ACCEL_REG_CHIP_ID		0x00
>  #define BMC150_ACCEL_CHIP_ID_VAL		0xFA
> +#define BMA255_ACCEL_CHIP_ID_VAL		0xFA
> +#define BMI055_ACCEL_CHIP_ID_VAL		0xFA
> +#define BMA222E_ACCEL_CHIP_ID_VAL		0xF8
> +#define BMA250E_ACCEL_CHIP_ID_VAL		0xF9
> +#define BMA280_ACCEL_CHIP_ID_VAL		0xFB
These only turn up in one place and it's obvious what their meaning
is there, so why not just put the id's directly into that table?
>
>  #define BMC150_ACCEL_REG_INT_STATUS_2		0x0B
>  #define BMC150_ACCEL_ANY_MOTION_MASK		0x07
> @@ -126,6 +138,18 @@ enum bmc150_power_modes {
>  	BMC150_ACCEL_SLEEP_MODE_SUSPEND = 0x04,
>  };
>
> +struct bmc150_scale_info {
> +	int scale;
> +	int range;
> +};
> +
> +struct bmc150_accel_chip_info {
> +	u8 chip_id;
> +	const struct iio_chan_spec *channels;
> +	int num_channels;
> +	const struct bmc150_scale_info scale_table[4];
> +};
> +
>  struct bmc150_accel_data {
>  	struct i2c_client *client;
>  	struct iio_trigger *dready_trig;
> @@ -140,6 +164,7 @@ struct bmc150_accel_data {
>  	bool dready_trigger_on;
>  	bool motion_trigger_on;
>  	int64_t timestamp;
> +	const struct bmc150_accel_chip_info *chip_info;
>  };
>
>  static const struct {
> @@ -168,14 +193,6 @@ static const struct {
>  				     {0x0F, 1} };
>
>  static const struct {
> -	int scale;
> -	int range;
> -} bmc150_accel_scale_table[] = { {9610, BMC150_ACCEL_DEF_RANGE_2G},
> -				 {19122, BMC150_ACCEL_DEF_RANGE_4G},
> -				 {38344, BMC150_ACCEL_DEF_RANGE_8G},
> -				 {76590, BMC150_ACCEL_DEF_RANGE_16G} };
> -
> -static const struct {
>  	int sleep_dur;
>  	int reg_value;
>  } bmc150_accel_sleep_value_table[] = { {0, 0},
> @@ -267,7 +284,7 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
>  	}
>
>  	dev_dbg(&data->client->dev, "Chip Id %x\n", ret);
> -	if (ret != BMC150_ACCEL_CHIP_ID_VAL) {
> +	if (ret != data->chip_info->chip_id) {
>  		dev_err(&data->client->dev, "Invalid chip %x\n", ret);
>  		return -ENODEV;
>  	}
> @@ -541,19 +558,19 @@ static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
>  {
>  	int ret, i;
>
> -	for (i = 0; i < ARRAY_SIZE(bmc150_accel_scale_table); ++i) {
> -		if (bmc150_accel_scale_table[i].scale == val) {
> +	for (i = 0; i < ARRAY_SIZE(data->chip_info->scale_table); ++i) {
> +		if (data->chip_info->scale_table[i].scale == val) {
>  			ret = i2c_smbus_write_byte_data(
>  					data->client,
>  					BMC150_ACCEL_REG_PMU_RANGE,
> -					bmc150_accel_scale_table[i].range);
> +					data->chip_info->scale_table[i].range);
>  			if (ret < 0) {
>  				dev_err(&data->client->dev,
>  					"Error writing pmu_range\n");
>  				return ret;
>  			}
>
> -			data->range = bmc150_accel_scale_table[i].range;
> +			data->range = data->chip_info->scale_table[i].range;
>  			return 0;
>  		}
>  	}
> @@ -580,10 +597,12 @@ static int bmc150_accel_get_temp(struct bmc150_accel_data *data, int *val)
>  	return IIO_VAL_INT;
>  }
>
> -static int bmc150_accel_get_axis(struct bmc150_accel_data *data, int axis,
> +static int bmc150_accel_get_axis(struct bmc150_accel_data *data,
> +				 struct iio_chan_spec const *chan,
>  				 int *val)
>  {
>  	int ret;
> +	int axis = chan->scan_index;
>
>  	mutex_lock(&data->mutex);
>  	ret = bmc150_accel_set_power_state(data, true);
> @@ -600,7 +619,8 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data, int axis,
>  		mutex_unlock(&data->mutex);
>  		return ret;
>  	}
> -	*val = sign_extend32(ret >> 4, 11);
> +	*val = sign_extend32(ret >> chan->scan_type.shift,
> +			     chan->scan_type.realbits - 1);
>  	ret = bmc150_accel_set_power_state(data, false);
>  	mutex_unlock(&data->mutex);
>  	if (ret < 0)
> @@ -625,9 +645,7 @@ static int bmc150_accel_read_raw(struct iio_dev *indio_dev,
>  			if (iio_buffer_enabled(indio_dev))
>  				return -EBUSY;
>  			else
> -				return bmc150_accel_get_axis(data,
> -							     chan->scan_index,
> -							     val);
> +				return bmc150_accel_get_axis(data, chan, val);
>  		default:
>  			return -EINVAL;
>  		}
> @@ -647,12 +665,13 @@ static int bmc150_accel_read_raw(struct iio_dev *indio_dev,
>  		{
>  			int i;
>
> -			for (i = 0; i < ARRAY_SIZE(bmc150_accel_scale_table);
> -									 ++i) {
> -				if (bmc150_accel_scale_table[i].range ==
> +			for (i = 0;
> +			     i < ARRAY_SIZE(data->chip_info->scale_table);
> +			     ++i) {
> +				if (data->chip_info->scale_table[i].range ==
>  								data->range) {
>  					*val2 =
> -					bmc150_accel_scale_table[i].scale;
> +					data->chip_info->scale_table[i].scale;
>  					return IIO_VAL_INT_PLUS_MICRO;
>  				}
>  			}
> @@ -840,7 +859,7 @@ static const struct iio_event_spec bmc150_accel_event = {
>  				 BIT(IIO_EV_INFO_PERIOD)
>  };
>
> -#define BMC150_ACCEL_CHANNEL(_axis) {					\
> +#define BMC150_ACCEL_CHANNEL(_axis, bits) {				\
>  	.type = IIO_ACCEL,						\
>  	.modified = 1,							\
>  	.channel2 = IIO_MOD_##_axis,					\
> @@ -850,26 +869,101 @@ static const struct iio_event_spec bmc150_accel_event = {
>  	.scan_index = AXIS_##_axis,					\
>  	.scan_type = {							\
>  		.sign = 's',						\
> -		.realbits = 12,					\
> +		.realbits = (bits),					\
>  		.storagebits = 16,					\
> -		.shift = 4,						\
> +		.shift = 16 - (bits),					\
>  	},								\
>  	.event_spec = &bmc150_accel_event,				\
>  	.num_event_specs = 1						\
>  }
>
> -static const struct iio_chan_spec bmc150_accel_channels[] = {
> -	{
> -		.type = IIO_TEMP,
> -		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> -				      BIT(IIO_CHAN_INFO_SCALE) |
> -				      BIT(IIO_CHAN_INFO_OFFSET),
> -		.scan_index = -1,
> +#define BMC150_ACCEL_CHANNELS(bits) {					\
> +	{								\
> +		.type = IIO_TEMP,					\
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
> +				      BIT(IIO_CHAN_INFO_SCALE) |	\
> +				      BIT(IIO_CHAN_INFO_OFFSET),	\
> +		.scan_index = -1,					\
> +	},								\
> +	BMC150_ACCEL_CHANNEL(X, bits),					\
> +	BMC150_ACCEL_CHANNEL(Y, bits),					\
> +	BMC150_ACCEL_CHANNEL(Z, bits),					\
> +	IIO_CHAN_SOFT_TIMESTAMP(3),					\
> +}
> +
> +static const struct iio_chan_spec bma222e_accel_channels[] =
> +	BMC150_ACCEL_CHANNELS(8);
> +static const struct iio_chan_spec bma250e_accel_channels[] =
> +	BMC150_ACCEL_CHANNELS(10);
> +static const struct iio_chan_spec bmc150_accel_channels[] =
> +	BMC150_ACCEL_CHANNELS(12);
> +static const struct iio_chan_spec bma280_accel_channels[] =
> +	BMC150_ACCEL_CHANNELS(14);
> +
> +enum {
> +	bmc150,
> +	bmi055,
> +	bma255,
> +	bma250e,
> +	bma222e,
> +	bma280,
> +};
> +
> +static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
> +	[bmc150] = {
> +		.chip_id = BMC150_ACCEL_CHIP_ID_VAL,
> +		.channels = bmc150_accel_channels,
> +		.num_channels = ARRAY_SIZE(bmc150_accel_channels),
> +		.scale_table = { {9610, BMC150_ACCEL_DEF_RANGE_2G},
> +				 {19122, BMC150_ACCEL_DEF_RANGE_4G},
> +				 {38344, BMC150_ACCEL_DEF_RANGE_8G},
> +				 {76590, BMC150_ACCEL_DEF_RANGE_16G} },
> +	},
> +	[bmi055] = {
> +		.chip_id = BMI055_ACCEL_CHIP_ID_VAL,
> +		.channels = bmc150_accel_channels,
> +		.num_channels = ARRAY_SIZE(bmc150_accel_channels),
> +		.scale_table = { {9610, BMC150_ACCEL_DEF_RANGE_2G},
> +				 {19122, BMC150_ACCEL_DEF_RANGE_4G},
> +				 {38344, BMC150_ACCEL_DEF_RANGE_8G},
> +				 {76590, BMC150_ACCEL_DEF_RANGE_16G} },
> +	},
> +	[bma255] = {
> +		.chip_id = BMA255_ACCEL_CHIP_ID_VAL,
> +		.channels = bmc150_accel_channels,
> +		.num_channels = ARRAY_SIZE(bmc150_accel_channels),
> +		.scale_table = { {9610, BMC150_ACCEL_DEF_RANGE_2G},
> +				 {19122, BMC150_ACCEL_DEF_RANGE_4G},
> +				 {38344, BMC150_ACCEL_DEF_RANGE_8G},
> +				 {76590, BMC150_ACCEL_DEF_RANGE_16G} },
> +	},
> +	[bma250e] = {
> +		.chip_id = BMA250E_ACCEL_CHIP_ID_VAL,
> +		.channels = bma250e_accel_channels,
> +		.num_channels = ARRAY_SIZE(bma250e_accel_channels),
> +		.scale_table = { {38344, BMC150_ACCEL_DEF_RANGE_2G},
> +				 {76590, BMC150_ACCEL_DEF_RANGE_4G},
> +				 {153277, BMC150_ACCEL_DEF_RANGE_8G},
> +				 {306457, BMC150_ACCEL_DEF_RANGE_16G} },
> +	},
> +	[bma222e] = {
> +		.chip_id = BMA222E_ACCEL_CHIP_ID_VAL,
> +		.channels = bma222e_accel_channels,
> +		.num_channels = ARRAY_SIZE(bma222e_accel_channels),
> +		.scale_table = { {153277, BMC150_ACCEL_DEF_RANGE_2G},
> +				 {306457, BMC150_ACCEL_DEF_RANGE_4G},
> +				 {612915, BMC150_ACCEL_DEF_RANGE_8G},
> +				 {1225831, BMC150_ACCEL_DEF_RANGE_16G} },
> +	},
> +	[bma280] = {
> +		.chip_id = BMA280_ACCEL_CHIP_ID_VAL,
> +		.channels = bma280_accel_channels,
> +		.num_channels = ARRAY_SIZE(bma280_accel_channels),
> +		.scale_table = { {2392, BMC150_ACCEL_DEF_RANGE_2G},
> +				 {4785, BMC150_ACCEL_DEF_RANGE_4G},
> +				 {9581, BMC150_ACCEL_DEF_RANGE_8G},
> +				 {19152, BMC150_ACCEL_DEF_RANGE_16G} },
>  	},
> -	BMC150_ACCEL_CHANNEL(X),
> -	BMC150_ACCEL_CHANNEL(Y),
> -	BMC150_ACCEL_CHANNEL(Z),
> -	IIO_CHAN_SOFT_TIMESTAMP(3),
>  };
>
>  static const struct iio_info bmc150_accel_info = {
> @@ -1040,10 +1134,23 @@ static irqreturn_t bmc150_accel_data_rdy_trig_poll(int irq, void *private)
>  		return IRQ_HANDLED;
>  }
>
> -static int bmc150_accel_acpi_gpio_probe(struct i2c_client *client,
> -					struct bmc150_accel_data *data)
> +static char *bmc150_accel_match_acpi_device(struct device *dev, int *data)
>  {
>  	const struct acpi_device_id *id;
> +
> +	id = acpi_match_device(dev->driver->acpi_match_table, dev);
> +
> +	if (!id)
> +		return NULL;
> +
> +	*data = (int) id->driver_data;
> +
> +	return (char *) dev_name(dev);
> +}
> +
> +static int bmc150_accel_gpio_probe(struct i2c_client *client,
> +					struct bmc150_accel_data *data)
> +{
>  	struct device *dev;
>  	struct gpio_desc *gpio;
>  	int ret;
> @@ -1052,17 +1159,11 @@ static int bmc150_accel_acpi_gpio_probe(struct i2c_client *client,
>  		return -EINVAL;
>
>  	dev = &client->dev;
> -	if (!ACPI_HANDLE(dev))
> -		return -ENODEV;
> -
> -	id = acpi_match_device(dev->driver->acpi_match_table, dev);
> -	if (!id)
> -		return -ENODEV;
>
>  	/* data ready gpio interrupt pin */
>  	gpio = devm_gpiod_get_index(dev, BMC150_ACCEL_GPIO_NAME, 0);
>  	if (IS_ERR(gpio)) {
> -		dev_err(dev, "Failed: acpi gpio get index\n");
> +		dev_err(dev, "Failed: gpio get index\n");
>  		return PTR_ERR(gpio);
>  	}
>
> @@ -1083,6 +1184,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
>  	struct bmc150_accel_data *data;
>  	struct iio_dev *indio_dev;
>  	int ret;
> +	char *name = NULL;
More fun with const char * vs char *.  Same question as in my earlier
review.  Do we need it for some reason that I'm missing this morning?
> +	int chip_id = 0;
>
>  	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
>  	if (!indio_dev)
> @@ -1092,6 +1195,16 @@ static int bmc150_accel_probe(struct i2c_client *client,
>  	i2c_set_clientdata(client, indio_dev);
>  	data->client = client;
>
> +	if (id) {
> +		name = (char *) id->name;
> +		chip_id = id->driver_data;
> +	}
> +
> +	if (ACPI_HANDLE(&client->dev))
> +		name = bmc150_accel_match_acpi_device(&client->dev, &chip_id);
> +
> +	data->chip_info = &bmc150_accel_chip_info_tbl[chip_id];
> +
>  	ret = bmc150_accel_chip_init(data);
>  	if (ret < 0)
>  		return ret;
> @@ -1099,14 +1212,14 @@ static int bmc150_accel_probe(struct i2c_client *client,
>  	mutex_init(&data->mutex);
>
>  	indio_dev->dev.parent = &client->dev;
> -	indio_dev->channels = bmc150_accel_channels;
> -	indio_dev->num_channels = ARRAY_SIZE(bmc150_accel_channels);
> -	indio_dev->name = BMC150_ACCEL_DRV_NAME;
> +	indio_dev->channels = data->chip_info->channels;
> +	indio_dev->num_channels = data->chip_info->num_channels;
> +	indio_dev->name = name;
>  	indio_dev->modes = INDIO_DIRECT_MODE;
>  	indio_dev->info = &bmc150_accel_info;
>
>  	if (client->irq < 0)
> -		client->irq = bmc150_accel_acpi_gpio_probe(client, data);
> +		client->irq = bmc150_accel_gpio_probe(client, data);
>
>  	if (client->irq >= 0) {
>  		ret = devm_request_threaded_irq(
> @@ -1284,14 +1397,24 @@ static const struct dev_pm_ops bmc150_accel_pm_ops = {
>  };
>
>  static const struct acpi_device_id bmc150_accel_acpi_match[] = {
> -	{"BSBA0150", 0},
> -	{"BMC150A", 0},
> +	{"BSBA0150",	bmc150},
> +	{"BMC150A",	bmc150},
> +	{"BMI055A",	bmi055},
> +	{"BMA0255",	bma255},
> +	{"BMA250E",	bma250e},
> +	{"BMA222E",	bma222e},
> +	{"BMA0280",	bma280},
>  	{ },
>  };
>  MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
>
>  static const struct i2c_device_id bmc150_accel_id[] = {
> -	{"bmc150_accel", 0},
> +	{"bmc150_accel",	bmc150},
> +	{"bmi055_accel",	bmi055},
> +	{"bma255",		bma255},
> +	{"bma250e",		bma250e},
> +	{"bma222e",		bma222e},
> +	{"bma280",		bma280},
>  	{}
>  };
>
>

  reply	other threads:[~2014-08-30 10:54 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-29  8:38 [PATCH v2 0/3] iio: accel: BMC150: add support for more Bosch chips Laurentiu Palcu
2014-08-29  8:38 ` [PATCH v2 1/3] iio: accel: BMC150: fix scale value for 16G Laurentiu Palcu
2014-08-30 10:36   ` Jonathan Cameron
2014-08-29  8:38 ` [PATCH v2 2/3] iio: accel: BMC150: fix issues when CONFIG_PM_RUNTIME is not set Laurentiu Palcu
2014-08-30 10:45   ` Jonathan Cameron
2014-09-01  9:24     ` Laurentiu Palcu
2014-08-29  8:38 ` [PATCH v2 3/3] iio: accel: BMC150: add support for other Bosch chips Laurentiu Palcu
2014-08-30 10:54   ` Jonathan Cameron [this message]
2014-09-01  9:11   ` [PATCH v3 " Laurentiu Palcu
2014-09-01 11:02     ` Peter Meerwald
2014-09-01 12:55       ` Laurentiu Palcu
2014-09-01 13:03         ` Laurentiu Palcu
2014-09-01 14:29     ` [PATCH v4 " Laurentiu Palcu
2014-09-02  9:30       ` [PATCH v5 " Laurentiu Palcu
2014-09-10 19:35         ` Jonathan Cameron
2014-09-10 19:43           ` Srinivas Pandruvada
2014-09-13 20:37             ` Jonathan Cameron
2014-09-01 15:36     ` [PATCH v3 " Joe Perches
2014-09-01 15:51       ` Srinivas Pandruvada
2014-09-02 10:30         ` Laurentiu Palcu
2014-09-10 19:32           ` Jonathan Cameron

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=5401AD4D.3060607@kernel.org \
    --to=jic23@kernel.org \
    --cc=knaack.h@gmx.de \
    --cc=lars@metafoo.de \
    --cc=laurentiu.palcu@intel.com \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pmeerw@pmeerw.net \
    --cc=srinivas.pandruvada@linux.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).