All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] iio: accel: BMC150: add support for more Bosch chips
@ 2014-08-29  8:38 Laurentiu Palcu
  2014-08-29  8:38 ` [PATCH v2 1/3] iio: accel: BMC150: fix scale value for 16G Laurentiu Palcu
                   ` (2 more replies)
  0 siblings, 3 replies; 21+ messages in thread
From: Laurentiu Palcu @ 2014-08-29  8:38 UTC (permalink / raw)
  To: jic23, linux-iio
  Cc: srinivas.pandruvada, knaack.h, lars, pmeerw, laurentiu.palcu,
	linux-kernel

v2:
 * fixed the sensitivity value: 75590 -> 76590
 * changed comments, commit messages and IDs to reflect that BMA250E and BMA222E
   are the chips supported (not BMA250/BMA222);

To ease reviewers' job (I should've done that from the very beginning, sorry), here's
where you cand find the registers table for each chip. It's easier to compare:

BMC150:  [1] - page 66
BMI055:  [2] - page 46
BMA250E: [3] - page 49
BMA222E: [4] - page 49
BMA280:  [5] - page 49
BMA255:  [6] - page 49

[1] http://ae-bst.resource.bosch.com/media/products/dokumente/bmc150/BST-BMC150-DS000-04.pdf
[2] http://ae-bst.resource.bosch.com/media/products/dokumente/bmi055/BST-BMI055-DS000-06.pdf
[3] http://ae-bst.resource.bosch.com/media/products/dokumente/bma250e/BST-BMA250E-DS004-05_published.pdf
[4] http://ae-bst.resource.bosch.com/media/products/dokumente/bma222e/BST-BMA222E-DS004-05_published.pdf
[5] http://ae-bst.resource.bosch.com/media/products/dokumente/bma280/BST-BMA280-DS000-11_published.pdf
[6] http://ae-bst.resource.bosch.com/media/products/dokumente/bma255/BST-BMA255-DS004-05_published.pdf

laurentiu

Laurentiu Palcu (3):
  iio: accel: BMC150: fix scale value for 16G
  iio: accel: BMC150: fix issues when CONFIG_PM_RUNTIME is not set
  iio: accel: BMC150: add support for other Bosch chips

 drivers/iio/accel/bmc150-accel.c | 236 ++++++++++++++++++++++++++++++---------
 1 file changed, 183 insertions(+), 53 deletions(-)

-- 
1.9.1


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 1/3] iio: accel: BMC150: fix scale value for 16G
  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 ` 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-29  8:38 ` [PATCH v2 3/3] iio: accel: BMC150: add support for other Bosch chips Laurentiu Palcu
  2 siblings, 1 reply; 21+ messages in thread
From: Laurentiu Palcu @ 2014-08-29  8:38 UTC (permalink / raw)
  To: jic23, linux-iio
  Cc: srinivas.pandruvada, knaack.h, lars, pmeerw, laurentiu.palcu,
	linux-kernel

According to documentation ([1] - page 27), the range for 16G is
7.81mg/LSB. Converted to SI, this is:
    7.81 * 10^-3 * 9.80665 m/s^2 / LSB = 0.0765899365 m/s^2 / LSB

[1] http://ae-bst.resource.bosch.com/media/products/dokumente/bmc150/BST-BMC150-DS000-04.pdf

Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
---
 drivers/iio/accel/bmc150-accel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
index 23ae334..ccb6cf8 100644
--- a/drivers/iio/accel/bmc150-accel.c
+++ b/drivers/iio/accel/bmc150-accel.c
@@ -173,7 +173,7 @@ static const struct {
 } bmc150_accel_scale_table[] = { {9610, BMC150_ACCEL_DEF_RANGE_2G},
 				 {19122, BMC150_ACCEL_DEF_RANGE_4G},
 				 {38344, BMC150_ACCEL_DEF_RANGE_8G},
-				 {77057, BMC150_ACCEL_DEF_RANGE_16G} };
+				 {76590, BMC150_ACCEL_DEF_RANGE_16G} };
 
 static const struct {
 	int sleep_dur;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 2/3] iio: accel: BMC150: fix issues when CONFIG_PM_RUNTIME is not set
  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-29  8:38 ` Laurentiu Palcu
  2014-08-30 10:45   ` Jonathan Cameron
  2014-08-29  8:38 ` [PATCH v2 3/3] iio: accel: BMC150: add support for other Bosch chips Laurentiu Palcu
  2 siblings, 1 reply; 21+ messages in thread
From: Laurentiu Palcu @ 2014-08-29  8:38 UTC (permalink / raw)
  To: jic23, linux-iio
  Cc: srinivas.pandruvada, knaack.h, lars, pmeerw, laurentiu.palcu,
	linux-kernel

When CONFIG_PM_RUNTIME is not set, the following issues are seen:
 * warning message at compilation time:
    warning: 'bmc150_accel_get_startup_times' defined but not used [-Wunused-function]
 * bmc150_accel_set_power_state() will always fail and reading the
   accelerometer data is impossible;

This commit fixes these.

Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
---
 drivers/iio/accel/bmc150-accel.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
index ccb6cf8..0e6566a 100644
--- a/drivers/iio/accel/bmc150-accel.c
+++ b/drivers/iio/accel/bmc150-accel.c
@@ -499,6 +499,7 @@ static int bmc150_accel_get_bw(struct bmc150_accel_data *data, int *val,
 	return -EINVAL;
 }
 
+#ifdef CONFIG_PM_RUNTIME
 static int bmc150_accel_get_startup_times(struct bmc150_accel_data *data)
 {
 	int i;
@@ -529,6 +530,12 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
 
 	return 0;
 }
+#else
+static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
+{
+	return 0;
+}
+#endif
 
 static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
 {
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 3/3] iio: accel: BMC150: add support for other Bosch chips
  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-29  8:38 ` [PATCH v2 2/3] iio: accel: BMC150: fix issues when CONFIG_PM_RUNTIME is not set Laurentiu Palcu
@ 2014-08-29  8:38 ` Laurentiu Palcu
  2014-08-30 10:54   ` Jonathan Cameron
  2014-09-01  9:11   ` [PATCH v3 " Laurentiu Palcu
  2 siblings, 2 replies; 21+ messages in thread
From: Laurentiu Palcu @ 2014-08-29  8:38 UTC (permalink / raw)
  To: jic23, linux-iio
  Cc: srinivas.pandruvada, knaack.h, lars, pmeerw, laurentiu.palcu,
	linux-kernel

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;

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
 
 #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;
+	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},
 	{}
 };
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 1/3] iio: accel: BMC150: fix scale value for 16G
  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
  0 siblings, 0 replies; 21+ messages in thread
From: Jonathan Cameron @ 2014-08-30 10:36 UTC (permalink / raw)
  To: Laurentiu Palcu, linux-iio
  Cc: srinivas.pandruvada, knaack.h, lars, pmeerw, linux-kernel

On 29/08/14 09:38, Laurentiu Palcu wrote:
> According to documentation ([1] - page 27), the range for 16G is
> 7.81mg/LSB. Converted to SI, this is:
>     7.81 * 10^-3 * 9.80665 m/s^2 / LSB = 0.0765899365 m/s^2 / LSB
> 
> [1] http://ae-bst.resource.bosch.com/media/products/dokumente/bmc150/BST-BMC150-DS000-04.pdf
> 
> Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
Applied to the togreg branch of iio.git - initially pushed out as testing for the autobuilders
to play.

I could only track down one previous datasheet version and that had the
same value, so perhaps a typo was responsible for this error.

Jonathan
> ---
>  drivers/iio/accel/bmc150-accel.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> index 23ae334..ccb6cf8 100644
> --- a/drivers/iio/accel/bmc150-accel.c
> +++ b/drivers/iio/accel/bmc150-accel.c
> @@ -173,7 +173,7 @@ static const struct {
>  } bmc150_accel_scale_table[] = { {9610, BMC150_ACCEL_DEF_RANGE_2G},
>  				 {19122, BMC150_ACCEL_DEF_RANGE_4G},
>  				 {38344, BMC150_ACCEL_DEF_RANGE_8G},
> -				 {77057, BMC150_ACCEL_DEF_RANGE_16G} };
> +				 {76590, BMC150_ACCEL_DEF_RANGE_16G} };
>  
>  static const struct {
>  	int sleep_dur;
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 2/3] iio: accel: BMC150: fix issues when CONFIG_PM_RUNTIME is not set
  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
  0 siblings, 1 reply; 21+ messages in thread
From: Jonathan Cameron @ 2014-08-30 10:45 UTC (permalink / raw)
  To: Laurentiu Palcu, linux-iio
  Cc: srinivas.pandruvada, knaack.h, lars, pmeerw, linux-kernel

On 29/08/14 09:38, Laurentiu Palcu wrote:
> When CONFIG_PM_RUNTIME is not set, the following issues are seen:
>  * warning message at compilation time:
>     warning: 'bmc150_accel_get_startup_times' defined but not used [-Wunused-function]
>  * bmc150_accel_set_power_state() will always fail and reading the
>    accelerometer data is impossible;
Why? Would be good to have an explanation here...

If on is true then it will call pm_runtime_get_sync which calls __pm_runtime_resume
which when CONFIG_PM_RUNTIME is not defined returns 1 which is not an error.

In the on = false case it calls pm_runtime_put_autosuspend which calls __pm_runtime_suspend
which returns -ENOSYS and gives our error.

I'll add something to the patch description to this effect.
> 
> This commit fixes these.
> 
> Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
> ---
>  drivers/iio/accel/bmc150-accel.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> index ccb6cf8..0e6566a 100644
> --- a/drivers/iio/accel/bmc150-accel.c
> +++ b/drivers/iio/accel/bmc150-accel.c
> @@ -499,6 +499,7 @@ static int bmc150_accel_get_bw(struct bmc150_accel_data *data, int *val,
>  	return -EINVAL;
>  }
>  
> +#ifdef CONFIG_PM_RUNTIME
>  static int bmc150_accel_get_startup_times(struct bmc150_accel_data *data)
>  {
>  	int i;
> @@ -529,6 +530,12 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
>  
>  	return 0;
>  }
> +#else
> +static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
> +{
> +	return 0;
> +}
> +#endif
>  
>  static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
>  {
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 3/3] iio: accel: BMC150: add support for other Bosch chips
  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
  2014-09-01  9:11   ` [PATCH v3 " Laurentiu Palcu
  1 sibling, 0 replies; 21+ messages in thread
From: Jonathan Cameron @ 2014-08-30 10:54 UTC (permalink / raw)
  To: Laurentiu Palcu, linux-iio
  Cc: srinivas.pandruvada, knaack.h, lars, pmeerw, linux-kernel

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},
>  	{}
>  };
>
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 3/3] iio: accel: BMC150: add support for other Bosch chips
  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
@ 2014-09-01  9:11   ` Laurentiu Palcu
  2014-09-01 11:02     ` Peter Meerwald
                       ` (2 more replies)
  1 sibling, 3 replies; 21+ messages in thread
From: Laurentiu Palcu @ 2014-09-01  9:11 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald,
	Laurentiu Palcu, Srinivas Pandruvada, linux-iio, linux-kernel

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;

Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
---

Changes in v3:
 * remove the chip id macros since they were not used anywhere else and put the id
   values directly in the chip info table;
 * fix the unnecessary casting from const char * to char * and back;

Thank you Jonathan for the reviews,
laurentiu

 drivers/iio/accel/bmc150-accel.c | 225 +++++++++++++++++++++++++++++----------
 1 file changed, 171 insertions(+), 54 deletions(-)

diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
index 0e6566a..72f4250 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
@@ -34,7 +41,6 @@
 #define BMC150_ACCEL_GPIO_NAME			"bmc150_accel_int"
 
 #define BMC150_ACCEL_REG_CHIP_ID		0x00
-#define BMC150_ACCEL_CHIP_ID_VAL		0xFA
 
 #define BMC150_ACCEL_REG_INT_STATUS_2		0x0B
 #define BMC150_ACCEL_ANY_MOTION_MASK		0x07
@@ -126,6 +132,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 +158,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 +187,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 +278,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 +552,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 +591,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 +613,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 +639,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 +659,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 +853,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 +863,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 = 0xFA,
+		.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 = 0xFA,
+		.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 = 0xFA,
+		.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 = 0xF9,
+		.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 = 0xF8,
+		.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 = 0xFB,
+		.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 +1128,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 const 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 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 +1153,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 +1178,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
 	struct bmc150_accel_data *data;
 	struct iio_dev *indio_dev;
 	int ret;
+	const char *name = NULL;
+	int chip_id = 0;
 
 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 	if (!indio_dev)
@@ -1092,6 +1189,16 @@ static int bmc150_accel_probe(struct i2c_client *client,
 	i2c_set_clientdata(client, indio_dev);
 	data->client = client;
 
+	if (id) {
+		name = 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 +1206,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 +1391,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},
 	{}
 };
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 2/3] iio: accel: BMC150: fix issues when CONFIG_PM_RUNTIME is not set
  2014-08-30 10:45   ` Jonathan Cameron
@ 2014-09-01  9:24     ` Laurentiu Palcu
  0 siblings, 0 replies; 21+ messages in thread
From: Laurentiu Palcu @ 2014-09-01  9:24 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, srinivas.pandruvada, knaack.h, lars, pmeerw, linux-kernel

On Sat, Aug 30, 2014 at 11:45:33AM +0100, Jonathan Cameron wrote:
> On 29/08/14 09:38, Laurentiu Palcu wrote:
> > When CONFIG_PM_RUNTIME is not set, the following issues are seen:
> >  * warning message at compilation time:
> >     warning: 'bmc150_accel_get_startup_times' defined but not used [-Wunused-function]
> >  * bmc150_accel_set_power_state() will always fail and reading the
> >    accelerometer data is impossible;
> Why? Would be good to have an explanation here...
> 
> If on is true then it will call pm_runtime_get_sync which calls __pm_runtime_resume
> which when CONFIG_PM_RUNTIME is not defined returns 1 which is not an error.
> 
> In the on = false case it calls pm_runtime_put_autosuspend which calls __pm_runtime_suspend
> which returns -ENOSYS and gives our error.
> 
> I'll add something to the patch description to this effect.
Thank you! I'll try to better describe my changes next time.

laurentiu

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 3/3] iio: accel: BMC150: add support for other Bosch chips
  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 14:29     ` [PATCH v4 " Laurentiu Palcu
  2014-09-01 15:36     ` [PATCH v3 " Joe Perches
  2 siblings, 1 reply; 21+ messages in thread
From: Peter Meerwald @ 2014-09-01 11:02 UTC (permalink / raw)
  To: Laurentiu Palcu
  Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Srinivas Pandruvada, linux-iio


> 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;

similar comment below
 
> Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
> ---
> 
> Changes in v3:
>  * remove the chip id macros since they were not used anywhere else and put the id
>    values directly in the chip info table;
>  * fix the unnecessary casting from const char * to char * and back;
> 
> Thank you Jonathan for the reviews,
> laurentiu
> 
>  drivers/iio/accel/bmc150-accel.c | 225 +++++++++++++++++++++++++++++----------
>  1 file changed, 171 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> index 0e6566a..72f4250 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
> @@ -34,7 +41,6 @@
>  #define BMC150_ACCEL_GPIO_NAME			"bmc150_accel_int"
>  
>  #define BMC150_ACCEL_REG_CHIP_ID		0x00
> -#define BMC150_ACCEL_CHIP_ID_VAL		0xFA
>  
>  #define BMC150_ACCEL_REG_INT_STATUS_2		0x0B
>  #define BMC150_ACCEL_ANY_MOTION_MASK		0x07
> @@ -126,6 +132,18 @@ enum bmc150_power_modes {
>  	BMC150_ACCEL_SLEEP_MODE_SUSPEND = 0x04,
>  };
>  
> +struct bmc150_scale_info {
> +	int scale;
> +	int range;

range could be u8 and probably named reg_range to have the same naming 
convention for these mappings (see below, reg_value)

> +};
> +
> +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 +158,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 +187,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;

reg_value could be u8

>  } bmc150_accel_sleep_value_table[] = { {0, 0},
> @@ -267,7 +278,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 +552,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 +591,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 +613,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 +639,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 +659,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 +853,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 +863,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 = 0xFA,
> +		.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 = 0xFA,
> +		.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 = 0xFA,
> +		.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 = 0xF9,
> +		.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 = 0xF8,
> +		.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 = 0xFB,
> +		.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 +1128,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 const 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 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 +1153,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 +1178,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
>  	struct bmc150_accel_data *data;
>  	struct iio_dev *indio_dev;
>  	int ret;
> +	const char *name = NULL;
> +	int chip_id = 0;
>  
>  	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
>  	if (!indio_dev)
> @@ -1092,6 +1189,16 @@ static int bmc150_accel_probe(struct i2c_client *client,
>  	i2c_set_clientdata(client, indio_dev);
>  	data->client = client;
>  
> +	if (id) {
> +		name = 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 +1206,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 +1391,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},
>  	{}
>  };
>  
> 

-- 

Peter Meerwald
+43-664-2444418 (mobile)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 3/3] iio: accel: BMC150: add support for other Bosch chips
  2014-09-01 11:02     ` Peter Meerwald
@ 2014-09-01 12:55       ` Laurentiu Palcu
  2014-09-01 13:03         ` Laurentiu Palcu
  0 siblings, 1 reply; 21+ messages in thread
From: Laurentiu Palcu @ 2014-09-01 12:55 UTC (permalink / raw)
  To: Peter Meerwald
  Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Srinivas Pandruvada, linux-iio

Hi Peter,

On Mon, Sep 01, 2014 at 01:02:02PM +0200, Peter Meerwald 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;
> 
> similar comment below
>  
> > Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
> > ---
> > 
> > Changes in v3:
> >  * remove the chip id macros since they were not used anywhere else and put the id
> >    values directly in the chip info table;
> >  * fix the unnecessary casting from const char * to char * and back;
> > 
> > Thank you Jonathan for the reviews,
> > laurentiu
> > 
> >  drivers/iio/accel/bmc150-accel.c | 225 +++++++++++++++++++++++++++++----------
> >  1 file changed, 171 insertions(+), 54 deletions(-)
> > 
> > diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> > index 0e6566a..72f4250 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
> > @@ -34,7 +41,6 @@
> >  #define BMC150_ACCEL_GPIO_NAME			"bmc150_accel_int"
> >  
> >  #define BMC150_ACCEL_REG_CHIP_ID		0x00
> > -#define BMC150_ACCEL_CHIP_ID_VAL		0xFA
> >  
> >  #define BMC150_ACCEL_REG_INT_STATUS_2		0x0B
> >  #define BMC150_ACCEL_ANY_MOTION_MASK		0x07
> > @@ -126,6 +132,18 @@ enum bmc150_power_modes {
> >  	BMC150_ACCEL_SLEEP_MODE_SUSPEND = 0x04,
> >  };
> >  
> > +struct bmc150_scale_info {
> > +	int scale;
> > +	int range;
> 
> range could be u8 and probably named reg_range to have the same naming 
> convention for these mappings (see below, reg_value)
I'm not keen on changing unrelated things in the same patch, since this
declaration existed in the original patch and I only moved it several
line up, but I agree that the naming should be consistent.

However, I would rename it 'reg_value' too, as it's done below, not
'reg_range', because it represents the value we write in the register for
a certain scale.

I'll send a v4 with this renaming and, also, change it from int to u8.

laurentiu

> 
> > +};
> > +
> > +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 +158,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 +187,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;
> 
> reg_value could be u8
> 
> >  } bmc150_accel_sleep_value_table[] = { {0, 0},
> > @@ -267,7 +278,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 +552,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 +591,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 +613,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 +639,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 +659,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 +853,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 +863,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 = 0xFA,
> > +		.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 = 0xFA,
> > +		.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 = 0xFA,
> > +		.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 = 0xF9,
> > +		.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 = 0xF8,
> > +		.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 = 0xFB,
> > +		.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 +1128,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 const 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 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 +1153,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 +1178,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
> >  	struct bmc150_accel_data *data;
> >  	struct iio_dev *indio_dev;
> >  	int ret;
> > +	const char *name = NULL;
> > +	int chip_id = 0;
> >  
> >  	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> >  	if (!indio_dev)
> > @@ -1092,6 +1189,16 @@ static int bmc150_accel_probe(struct i2c_client *client,
> >  	i2c_set_clientdata(client, indio_dev);
> >  	data->client = client;
> >  
> > +	if (id) {
> > +		name = 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 +1206,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 +1391,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},
> >  	{}
> >  };
> >  
> > 
> 
> -- 
> 
> Peter Meerwald
> +43-664-2444418 (mobile)
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 3/3] iio: accel: BMC150: add support for other Bosch chips
  2014-09-01 12:55       ` Laurentiu Palcu
@ 2014-09-01 13:03         ` Laurentiu Palcu
  0 siblings, 0 replies; 21+ messages in thread
From: Laurentiu Palcu @ 2014-09-01 13:03 UTC (permalink / raw)
  To: Peter Meerwald
  Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Srinivas Pandruvada, linux-iio

On Mon, Sep 01, 2014 at 03:55:09PM +0300, Laurentiu Palcu wrote:
> Hi Peter,
> 
> On Mon, Sep 01, 2014 at 01:02:02PM +0200, Peter Meerwald 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;
> > 
> > similar comment below
> >  
> > > Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
> > > ---
> > > 
> > > Changes in v3:
> > >  * remove the chip id macros since they were not used anywhere else and put the id
> > >    values directly in the chip info table;
> > >  * fix the unnecessary casting from const char * to char * and back;
> > > 
> > > Thank you Jonathan for the reviews,
> > > laurentiu
> > > 
> > >  drivers/iio/accel/bmc150-accel.c | 225 +++++++++++++++++++++++++++++----------
> > >  1 file changed, 171 insertions(+), 54 deletions(-)
> > > 
> > > diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> > > index 0e6566a..72f4250 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
> > > @@ -34,7 +41,6 @@
> > >  #define BMC150_ACCEL_GPIO_NAME			"bmc150_accel_int"
> > >  
> > >  #define BMC150_ACCEL_REG_CHIP_ID		0x00
> > > -#define BMC150_ACCEL_CHIP_ID_VAL		0xFA
> > >  
> > >  #define BMC150_ACCEL_REG_INT_STATUS_2		0x0B
> > >  #define BMC150_ACCEL_ANY_MOTION_MASK		0x07
> > > @@ -126,6 +132,18 @@ enum bmc150_power_modes {
> > >  	BMC150_ACCEL_SLEEP_MODE_SUSPEND = 0x04,
> > >  };
> > >  
> > > +struct bmc150_scale_info {
> > > +	int scale;
> > > +	int range;
> > 
> > range could be u8 and probably named reg_range to have the same naming 
> > convention for these mappings (see below, reg_value)
> I'm not keen on changing unrelated things in the same patch, since this
> declaration existed in the original patch and I only moved it several
> line up, but I agree that the naming should be consistent.
> 
> However, I would rename it 'reg_value' too, as it's done below, not
> 'reg_range', because it represents the value we write in the register for
> a certain scale.
My bad. I spoke too fast... :/ I guess reg_range is fine here.

laurentiu

> 
> I'll send a v4 with this renaming and, also, change it from int to u8.
> 
> laurentiu
> 
> > 
> > > +};
> > > +
> > > +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 +158,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 +187,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;
> > 
> > reg_value could be u8
> > 
> > >  } bmc150_accel_sleep_value_table[] = { {0, 0},
> > > @@ -267,7 +278,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 +552,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 +591,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 +613,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 +639,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 +659,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 +853,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 +863,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 = 0xFA,
> > > +		.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 = 0xFA,
> > > +		.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 = 0xFA,
> > > +		.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 = 0xF9,
> > > +		.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 = 0xF8,
> > > +		.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 = 0xFB,
> > > +		.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 +1128,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 const 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 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 +1153,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 +1178,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
> > >  	struct bmc150_accel_data *data;
> > >  	struct iio_dev *indio_dev;
> > >  	int ret;
> > > +	const char *name = NULL;
> > > +	int chip_id = 0;
> > >  
> > >  	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> > >  	if (!indio_dev)
> > > @@ -1092,6 +1189,16 @@ static int bmc150_accel_probe(struct i2c_client *client,
> > >  	i2c_set_clientdata(client, indio_dev);
> > >  	data->client = client;
> > >  
> > > +	if (id) {
> > > +		name = 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 +1206,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 +1391,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},
> > >  	{}
> > >  };
> > >  
> > > 
> > 
> > -- 
> > 
> > Peter Meerwald
> > +43-664-2444418 (mobile)
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v4 3/3] iio: accel: BMC150: add support for other Bosch chips
  2014-09-01  9:11   ` [PATCH v3 " Laurentiu Palcu
  2014-09-01 11:02     ` Peter Meerwald
@ 2014-09-01 14:29     ` Laurentiu Palcu
  2014-09-02  9:30       ` [PATCH v5 " Laurentiu Palcu
  2014-09-01 15:36     ` [PATCH v3 " Joe Perches
  2 siblings, 1 reply; 21+ messages in thread
From: Laurentiu Palcu @ 2014-09-01 14:29 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald,
	Laurentiu Palcu, Srinivas Pandruvada, linux-iio, linux-kernel

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;
 * rename bmc150_scale_info struct member 'range' to 'reg_range' to be
   consistent with the naming convention used elsewhere in the driver
   and declare it u8, instead of int.

Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
---

Changes in v4:
 * address Peter's comments: see 3rd bullet in the commit's message. As a result, do
   some re-indentation to make lines fit 80 chars;

Changes in v3:
 * remove the chip id macros since they were not used anywhere else and put the id
   values directly in the chip info table;
 * fix the unnecessary casting from const char * to char * and back;

laurentiu

 drivers/iio/accel/bmc150-accel.c | 231 +++++++++++++++++++++++++++++----------
 1 file changed, 174 insertions(+), 57 deletions(-)

diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
index 0e6566a..c3ae335 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
@@ -34,7 +41,6 @@
 #define BMC150_ACCEL_GPIO_NAME			"bmc150_accel_int"
 
 #define BMC150_ACCEL_REG_CHIP_ID		0x00
-#define BMC150_ACCEL_CHIP_ID_VAL		0xFA
 
 #define BMC150_ACCEL_REG_INT_STATUS_2		0x0B
 #define BMC150_ACCEL_ANY_MOTION_MASK		0x07
@@ -126,6 +132,18 @@ enum bmc150_power_modes {
 	BMC150_ACCEL_SLEEP_MODE_SUSPEND = 0x04,
 };
 
+struct bmc150_scale_info {
+	int scale;
+	u8 reg_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 +158,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,16 +187,8 @@ 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;
+	u8 reg_value;
 } bmc150_accel_sleep_value_table[] = { {0, 0},
 				       {500, BMC150_ACCEL_SLEEP_500_MICRO},
 				       {1000, BMC150_ACCEL_SLEEP_1_MS},
@@ -267,7 +278,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 +552,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->client,
+				     BMC150_ACCEL_REG_PMU_RANGE,
+				     data->chip_info->scale_table[i].reg_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].reg_range;
 			return 0;
 		}
 	}
@@ -580,10 +591,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 +613,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 +639,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 +659,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].reg_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 +853,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 +863,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 = 0xFA,
+		.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 = 0xFA,
+		.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 = 0xFA,
+		.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 = 0xF9,
+		.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 = 0xF8,
+		.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 = 0xFB,
+		.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 +1128,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 const 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 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 +1153,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 +1178,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
 	struct bmc150_accel_data *data;
 	struct iio_dev *indio_dev;
 	int ret;
+	const char *name = NULL;
+	int chip_id = 0;
 
 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 	if (!indio_dev)
@@ -1092,6 +1189,16 @@ static int bmc150_accel_probe(struct i2c_client *client,
 	i2c_set_clientdata(client, indio_dev);
 	data->client = client;
 
+	if (id) {
+		name = 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 +1206,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 +1391,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},
 	{}
 };
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 3/3] iio: accel: BMC150: add support for other Bosch chips
  2014-09-01  9:11   ` [PATCH v3 " Laurentiu Palcu
  2014-09-01 11:02     ` Peter Meerwald
  2014-09-01 14:29     ` [PATCH v4 " Laurentiu Palcu
@ 2014-09-01 15:36     ` Joe Perches
  2014-09-01 15:51       ` Srinivas Pandruvada
  2 siblings, 1 reply; 21+ messages in thread
From: Joe Perches @ 2014-09-01 15:36 UTC (permalink / raw)
  To: Laurentiu Palcu
  Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald, Srinivas Pandruvada, linux-iio, linux-kernel

On Mon, 2014-09-01 at 12:11 +0300, 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;
[]
> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
[]
> @@ -647,12 +659,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;
>  				}
>  			}

This looks like it would read a lot better with
a temporary for data->chip_info->scale_table[i]

so these could become:

			for (i = 0; i < etc; i++) {
				type *temp = &data->chip_info->scale_table[i];
				if (temp->range == data->range) {
					*val2 = temp->scale;
					return IIO_VAL_INT_PLUS_MICRO;
				}

Maybe all the bmc150_ variable names could be removed.
The prefixes don't seem to serve a purpose other than
to make the code longer.

The filename could be changed to be more generic.



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 3/3] iio: accel: BMC150: add support for other Bosch chips
  2014-09-01 15:36     ` [PATCH v3 " Joe Perches
@ 2014-09-01 15:51       ` Srinivas Pandruvada
  2014-09-02 10:30         ` Laurentiu Palcu
  0 siblings, 1 reply; 21+ messages in thread
From: Srinivas Pandruvada @ 2014-09-01 15:51 UTC (permalink / raw)
  To: Joe Perches
  Cc: Laurentiu Palcu, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald, linux-iio, linux-kernel

On Mon, 2014-09-01 at 08:36 -0700, Joe Perches wrote:
> On Mon, 2014-09-01 at 12:11 +0300, 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;
> []
> > diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> []
> > @@ -647,12 +659,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;
> >  				}
> >  			}
> 
> This looks like it would read a lot better with
> a temporary for data->chip_info->scale_table[i]
> 
> so these could become:
> 
> 			for (i = 0; i < etc; i++) {
> 				type *temp = &data->chip_info->scale_table[i];
> 				if (temp->range == data->range) {
> 					*val2 = temp->scale;
> 					return IIO_VAL_INT_PLUS_MICRO;
> 				}
> 
> Maybe all the bmc150_ variable names could be removed.
> The prefixes don't seem to serve a purpose other than
> to make the code longer.
> 
> The filename could be changed to be more generic.
Then this will also require change in the CONFIG name to match. This
will require all current users to change the config file once they
update to new version of the driver, which they don't like to change
once product config is finalized. Since the most of the chips will just
differ by a number at the end and they may not be compatible to each
other, finding a common name will be challenge.
Instead the CONFIG description for this module should explicitly state
the names of chips it is compatible to.

Thanks,
Srinivas
> 
> 



^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v5 3/3] iio: accel: BMC150: add support for other Bosch chips
  2014-09-01 14:29     ` [PATCH v4 " Laurentiu Palcu
@ 2014-09-02  9:30       ` Laurentiu Palcu
  2014-09-10 19:35         ` Jonathan Cameron
  0 siblings, 1 reply; 21+ messages in thread
From: Laurentiu Palcu @ 2014-09-02  9:30 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald,
	Laurentiu Palcu, Srinivas Pandruvada, linux-iio, linux-kernel

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;
 * rename bmc150_scale_info struct member 'range' to 'reg_range' to be
   consistent with the naming convention used elsewhere in the driver
   and declare it u8, instead of int;
 * change CONFIG description to list all supported chips;

Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
---

Changes in v5:
 * addressed Joe's suggestion to rewrite a small portion of the code to make it
   more readable;
 * changed the CONFIG description according to Srinivas's advise;

Changes in v4:
 * address Peter's comments: see 3rd bullet in the commit's message. As a result, do
   some re-indentation to make lines fit 80 chars;

Changes in v3:
 * remove the chip id macros since they were not used anywhere else and put the id
   values directly in the chip info table;
 * fix the unnecessary casting from const char * to char * and back;

laurentiu

 drivers/iio/accel/Kconfig        |   4 +-
 drivers/iio/accel/bmc150-accel.c | 234 +++++++++++++++++++++++++++++----------
 2 files changed, 178 insertions(+), 60 deletions(-)

diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 01b857e..01a2151 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -23,7 +23,9 @@ config BMC150_ACCEL
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	help
-	  Say yes here to build support for the Bosch BMC150 accelerometer.
+	  Say yes here to build support for the following Bosch accelerometers:
+	  BMC150, BMI055, BMA250E, BMA222E, BMA255, BMA280.
+
 	  Currently this only supports the device via an i2c interface.
 
 	  This is a combo module with both accelerometer and magnetometer.
diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
index 0e6566a..22c096c 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
@@ -34,7 +41,6 @@
 #define BMC150_ACCEL_GPIO_NAME			"bmc150_accel_int"
 
 #define BMC150_ACCEL_REG_CHIP_ID		0x00
-#define BMC150_ACCEL_CHIP_ID_VAL		0xFA
 
 #define BMC150_ACCEL_REG_INT_STATUS_2		0x0B
 #define BMC150_ACCEL_ANY_MOTION_MASK		0x07
@@ -126,6 +132,18 @@ enum bmc150_power_modes {
 	BMC150_ACCEL_SLEEP_MODE_SUSPEND = 0x04,
 };
 
+struct bmc150_scale_info {
+	int scale;
+	u8 reg_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 +158,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,16 +187,8 @@ 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;
+	u8 reg_value;
 } bmc150_accel_sleep_value_table[] = { {0, 0},
 				       {500, BMC150_ACCEL_SLEEP_500_MICRO},
 				       {1000, BMC150_ACCEL_SLEEP_1_MS},
@@ -267,7 +278,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 +552,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->client,
+				     BMC150_ACCEL_REG_PMU_RANGE,
+				     data->chip_info->scale_table[i].reg_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].reg_range;
 			return 0;
 		}
 	}
@@ -580,10 +591,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 +613,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 +639,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;
 		}
@@ -646,13 +658,13 @@ static int bmc150_accel_read_raw(struct iio_dev *indio_dev,
 		case IIO_ACCEL:
 		{
 			int i;
+			const struct bmc150_scale_info *si;
+			int st_size = ARRAY_SIZE(data->chip_info->scale_table);
 
-			for (i = 0; i < ARRAY_SIZE(bmc150_accel_scale_table);
-									 ++i) {
-				if (bmc150_accel_scale_table[i].range ==
-								data->range) {
-					*val2 =
-					bmc150_accel_scale_table[i].scale;
+			for (i = 0; i < st_size; ++i) {
+				si = &data->chip_info->scale_table[i];
+				if (si->reg_range == data->range) {
+					*val2 = si->scale;
 					return IIO_VAL_INT_PLUS_MICRO;
 				}
 			}
@@ -840,7 +852,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 +862,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 = 0xFA,
+		.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 = 0xFA,
+		.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 = 0xFA,
+		.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 = 0xF9,
+		.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 = 0xF8,
+		.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 = 0xFB,
+		.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 +1127,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 const 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 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 +1152,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 +1177,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
 	struct bmc150_accel_data *data;
 	struct iio_dev *indio_dev;
 	int ret;
+	const char *name = NULL;
+	int chip_id = 0;
 
 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 	if (!indio_dev)
@@ -1092,6 +1188,16 @@ static int bmc150_accel_probe(struct i2c_client *client,
 	i2c_set_clientdata(client, indio_dev);
 	data->client = client;
 
+	if (id) {
+		name = 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 +1205,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 +1390,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},
 	{}
 };
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 3/3] iio: accel: BMC150: add support for other Bosch chips
  2014-09-01 15:51       ` Srinivas Pandruvada
@ 2014-09-02 10:30         ` Laurentiu Palcu
  2014-09-10 19:32           ` Jonathan Cameron
  0 siblings, 1 reply; 21+ messages in thread
From: Laurentiu Palcu @ 2014-09-02 10:30 UTC (permalink / raw)
  To: Srinivas Pandruvada, Joe Perches
  Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald, linux-iio, linux-kernel

On Mon, Sep 01, 2014 at 08:51:36AM -0700, Srinivas Pandruvada wrote:
> On Mon, 2014-09-01 at 08:36 -0700, Joe Perches wrote:
> > On Mon, 2014-09-01 at 12:11 +0300, 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;
> > []
> > > diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> > []
> > > @@ -647,12 +659,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;
> > >  				}
> > >  			}
> > 
> > This looks like it would read a lot better with
> > a temporary for data->chip_info->scale_table[i]
> > 
> > so these could become:
> > 
> > 			for (i = 0; i < etc; i++) {
> > 				type *temp = &data->chip_info->scale_table[i];
> > 				if (temp->range == data->range) {
> > 					*val2 = temp->scale;
> > 					return IIO_VAL_INT_PLUS_MICRO;
> > 				}
Rewrote this part in v5. Thanks for the suggestion.

> > 
> > Maybe all the bmc150_ variable names could be removed.
> > The prefixes don't seem to serve a purpose other than
> > to make the code longer.
> > 
> > The filename could be changed to be more generic.
> Then this will also require change in the CONFIG name to match. This
> will require all current users to change the config file once they
> update to new version of the driver, which they don't like to change
> once product config is finalized. Since the most of the chips will just
> differ by a number at the end and they may not be compatible to each
> other, finding a common name will be challenge.
> Instead the CONFIG description for this module should explicitly state
> the names of chips it is compatible to.
v5 contains the changed CONFIG description that includes the new added chips.

thanks,
laurentiu


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 3/3] iio: accel: BMC150: add support for other Bosch chips
  2014-09-02 10:30         ` Laurentiu Palcu
@ 2014-09-10 19:32           ` Jonathan Cameron
  0 siblings, 0 replies; 21+ messages in thread
From: Jonathan Cameron @ 2014-09-10 19:32 UTC (permalink / raw)
  To: Laurentiu Palcu, Srinivas Pandruvada, Joe Perches
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald, linux-iio,
	linux-kernel

On 02/09/14 11:30, Laurentiu Palcu wrote:
> On Mon, Sep 01, 2014 at 08:51:36AM -0700, Srinivas Pandruvada wrote:
>> On Mon, 2014-09-01 at 08:36 -0700, Joe Perches wrote:
>>> On Mon, 2014-09-01 at 12:11 +0300, 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;
>>> []
>>>> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
>>> []
>>>> @@ -647,12 +659,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;
>>>>  				}
>>>>  			}
>>>
>>> This looks like it would read a lot better with
>>> a temporary for data->chip_info->scale_table[i]
>>>
>>> so these could become:
>>>
>>> 			for (i = 0; i < etc; i++) {
>>> 				type *temp = &data->chip_info->scale_table[i];
>>> 				if (temp->range == data->range) {
>>> 					*val2 = temp->scale;
>>> 					return IIO_VAL_INT_PLUS_MICRO;
>>> 				}
> Rewrote this part in v5. Thanks for the suggestion.
> 
>>>
>>> Maybe all the bmc150_ variable names could be removed.
>>> The prefixes don't seem to serve a purpose other than
>>> to make the code longer.
>>>
>>> The filename could be changed to be more generic.
>> Then this will also require change in the CONFIG name to match. This
>> will require all current users to change the config file once they
>> update to new version of the driver, which they don't like to change
>> once product config is finalized. Since the most of the chips will just
>> differ by a number at the end and they may not be compatible to each
>> other, finding a common name will be challenge.
>> Instead the CONFIG description for this module should explicitly state
>> the names of chips it is compatible to.
> v5 contains the changed CONFIG description that includes the new added chips.
Agreed. Don't rename the driver.  Now, if companies went with naming based on
the interface it might be a good idea.  In reality it is a nightmare so much
better to keep to a name that covers one part and as you say, make it clear
in the Kconfig help what other parts are supported...

Jonathan
> 
> thanks,
> laurentiu
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v5 3/3] iio: accel: BMC150: add support for other Bosch chips
  2014-09-02  9:30       ` [PATCH v5 " Laurentiu Palcu
@ 2014-09-10 19:35         ` Jonathan Cameron
  2014-09-10 19:43           ` Srinivas Pandruvada
  0 siblings, 1 reply; 21+ messages in thread
From: Jonathan Cameron @ 2014-09-10 19:35 UTC (permalink / raw)
  To: Laurentiu Palcu
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald,
	Srinivas Pandruvada, linux-iio, linux-kernel

On 02/09/14 10:30, 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;
>  * rename bmc150_scale_info struct member 'range' to 'reg_range' to be
>    consistent with the naming convention used elsewhere in the driver
>    and declare it u8, instead of int;
>  * change CONFIG description to list all supported chips;
> 
> Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
Looks fine to me, though I'm not really in a fit state to review right now.
Srinivas, do you want to give an Ack?
> ---
> 
> Changes in v5:
>  * addressed Joe's suggestion to rewrite a small portion of the code to make it
>    more readable;
>  * changed the CONFIG description according to Srinivas's advise;
> 
> Changes in v4:
>  * address Peter's comments: see 3rd bullet in the commit's message. As a result, do
>    some re-indentation to make lines fit 80 chars;
> 
> Changes in v3:
>  * remove the chip id macros since they were not used anywhere else and put the id
>    values directly in the chip info table;
>  * fix the unnecessary casting from const char * to char * and back;
> 
> laurentiu
> 
>  drivers/iio/accel/Kconfig        |   4 +-
>  drivers/iio/accel/bmc150-accel.c | 234 +++++++++++++++++++++++++++++----------
>  2 files changed, 178 insertions(+), 60 deletions(-)
> 
> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
> index 01b857e..01a2151 100644
> --- a/drivers/iio/accel/Kconfig
> +++ b/drivers/iio/accel/Kconfig
> @@ -23,7 +23,9 @@ config BMC150_ACCEL
>  	select IIO_BUFFER
>  	select IIO_TRIGGERED_BUFFER
>  	help
> -	  Say yes here to build support for the Bosch BMC150 accelerometer.
> +	  Say yes here to build support for the following Bosch accelerometers:
> +	  BMC150, BMI055, BMA250E, BMA222E, BMA255, BMA280.
> +
>  	  Currently this only supports the device via an i2c interface.
>  
>  	  This is a combo module with both accelerometer and magnetometer.
> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> index 0e6566a..22c096c 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
> @@ -34,7 +41,6 @@
>  #define BMC150_ACCEL_GPIO_NAME			"bmc150_accel_int"
>  
>  #define BMC150_ACCEL_REG_CHIP_ID		0x00
> -#define BMC150_ACCEL_CHIP_ID_VAL		0xFA
>  
>  #define BMC150_ACCEL_REG_INT_STATUS_2		0x0B
>  #define BMC150_ACCEL_ANY_MOTION_MASK		0x07
> @@ -126,6 +132,18 @@ enum bmc150_power_modes {
>  	BMC150_ACCEL_SLEEP_MODE_SUSPEND = 0x04,
>  };
>  
> +struct bmc150_scale_info {
> +	int scale;
> +	u8 reg_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 +158,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,16 +187,8 @@ 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;
> +	u8 reg_value;
>  } bmc150_accel_sleep_value_table[] = { {0, 0},
>  				       {500, BMC150_ACCEL_SLEEP_500_MICRO},
>  				       {1000, BMC150_ACCEL_SLEEP_1_MS},
> @@ -267,7 +278,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 +552,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->client,
> +				     BMC150_ACCEL_REG_PMU_RANGE,
> +				     data->chip_info->scale_table[i].reg_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].reg_range;
>  			return 0;
>  		}
>  	}
> @@ -580,10 +591,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 +613,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 +639,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;
>  		}
> @@ -646,13 +658,13 @@ static int bmc150_accel_read_raw(struct iio_dev *indio_dev,
>  		case IIO_ACCEL:
>  		{
>  			int i;
> +			const struct bmc150_scale_info *si;
> +			int st_size = ARRAY_SIZE(data->chip_info->scale_table);
>  
> -			for (i = 0; i < ARRAY_SIZE(bmc150_accel_scale_table);
> -									 ++i) {
> -				if (bmc150_accel_scale_table[i].range ==
> -								data->range) {
> -					*val2 =
> -					bmc150_accel_scale_table[i].scale;
> +			for (i = 0; i < st_size; ++i) {
> +				si = &data->chip_info->scale_table[i];
> +				if (si->reg_range == data->range) {
> +					*val2 = si->scale;
>  					return IIO_VAL_INT_PLUS_MICRO;
>  				}
>  			}
> @@ -840,7 +852,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 +862,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 = 0xFA,
> +		.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 = 0xFA,
> +		.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 = 0xFA,
> +		.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 = 0xF9,
> +		.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 = 0xF8,
> +		.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 = 0xFB,
> +		.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 +1127,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 const 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 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 +1152,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 +1177,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
>  	struct bmc150_accel_data *data;
>  	struct iio_dev *indio_dev;
>  	int ret;
> +	const char *name = NULL;
> +	int chip_id = 0;
>  
>  	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
>  	if (!indio_dev)
> @@ -1092,6 +1188,16 @@ static int bmc150_accel_probe(struct i2c_client *client,
>  	i2c_set_clientdata(client, indio_dev);
>  	data->client = client;
>  
> +	if (id) {
> +		name = 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 +1205,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 +1390,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},
>  	{}
>  };
>  
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v5 3/3] iio: accel: BMC150: add support for other Bosch chips
  2014-09-10 19:35         ` Jonathan Cameron
@ 2014-09-10 19:43           ` Srinivas Pandruvada
  2014-09-13 20:37             ` Jonathan Cameron
  0 siblings, 1 reply; 21+ messages in thread
From: Srinivas Pandruvada @ 2014-09-10 19:43 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Laurentiu Palcu, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald, linux-iio, linux-kernel

On Wed, 2014-09-10 at 20:35 +0100, Jonathan Cameron wrote:
> On 02/09/14 10:30, 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;
> >  * rename bmc150_scale_info struct member 'range' to 'reg_range' to be
> >    consistent with the naming convention used elsewhere in the driver
> >    and declare it u8, instead of int;
> >  * change CONFIG description to list all supported chips;
> > 
> > Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
> Looks fine to me, though I'm not really in a fit state to review right now.
> Srinivas, do you want to give an Ack?
Sure

Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>

> > ---
> > 
> > Changes in v5:
> >  * addressed Joe's suggestion to rewrite a small portion of the code to make it
> >    more readable;
> >  * changed the CONFIG description according to Srinivas's advise;
> > 
> > Changes in v4:
> >  * address Peter's comments: see 3rd bullet in the commit's message. As a result, do
> >    some re-indentation to make lines fit 80 chars;
> > 
> > Changes in v3:
> >  * remove the chip id macros since they were not used anywhere else and put the id
> >    values directly in the chip info table;
> >  * fix the unnecessary casting from const char * to char * and back;
> > 
> > laurentiu
> > 
> >  drivers/iio/accel/Kconfig        |   4 +-
> >  drivers/iio/accel/bmc150-accel.c | 234 +++++++++++++++++++++++++++++----------
> >  2 files changed, 178 insertions(+), 60 deletions(-)
> > 
> > diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
> > index 01b857e..01a2151 100644
> > --- a/drivers/iio/accel/Kconfig
> > +++ b/drivers/iio/accel/Kconfig
> > @@ -23,7 +23,9 @@ config BMC150_ACCEL
> >  	select IIO_BUFFER
> >  	select IIO_TRIGGERED_BUFFER
> >  	help
> > -	  Say yes here to build support for the Bosch BMC150 accelerometer.
> > +	  Say yes here to build support for the following Bosch accelerometers:
> > +	  BMC150, BMI055, BMA250E, BMA222E, BMA255, BMA280.
> > +
> >  	  Currently this only supports the device via an i2c interface.
> >  
> >  	  This is a combo module with both accelerometer and magnetometer.
> > diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> > index 0e6566a..22c096c 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
> > @@ -34,7 +41,6 @@
> >  #define BMC150_ACCEL_GPIO_NAME			"bmc150_accel_int"
> >  
> >  #define BMC150_ACCEL_REG_CHIP_ID		0x00
> > -#define BMC150_ACCEL_CHIP_ID_VAL		0xFA
> >  
> >  #define BMC150_ACCEL_REG_INT_STATUS_2		0x0B
> >  #define BMC150_ACCEL_ANY_MOTION_MASK		0x07
> > @@ -126,6 +132,18 @@ enum bmc150_power_modes {
> >  	BMC150_ACCEL_SLEEP_MODE_SUSPEND = 0x04,
> >  };
> >  
> > +struct bmc150_scale_info {
> > +	int scale;
> > +	u8 reg_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 +158,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,16 +187,8 @@ 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;
> > +	u8 reg_value;
> >  } bmc150_accel_sleep_value_table[] = { {0, 0},
> >  				       {500, BMC150_ACCEL_SLEEP_500_MICRO},
> >  				       {1000, BMC150_ACCEL_SLEEP_1_MS},
> > @@ -267,7 +278,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 +552,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->client,
> > +				     BMC150_ACCEL_REG_PMU_RANGE,
> > +				     data->chip_info->scale_table[i].reg_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].reg_range;
> >  			return 0;
> >  		}
> >  	}
> > @@ -580,10 +591,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 +613,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 +639,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;
> >  		}
> > @@ -646,13 +658,13 @@ static int bmc150_accel_read_raw(struct iio_dev *indio_dev,
> >  		case IIO_ACCEL:
> >  		{
> >  			int i;
> > +			const struct bmc150_scale_info *si;
> > +			int st_size = ARRAY_SIZE(data->chip_info->scale_table);
> >  
> > -			for (i = 0; i < ARRAY_SIZE(bmc150_accel_scale_table);
> > -									 ++i) {
> > -				if (bmc150_accel_scale_table[i].range ==
> > -								data->range) {
> > -					*val2 =
> > -					bmc150_accel_scale_table[i].scale;
> > +			for (i = 0; i < st_size; ++i) {
> > +				si = &data->chip_info->scale_table[i];
> > +				if (si->reg_range == data->range) {
> > +					*val2 = si->scale;
> >  					return IIO_VAL_INT_PLUS_MICRO;
> >  				}
> >  			}
> > @@ -840,7 +852,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 +862,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 = 0xFA,
> > +		.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 = 0xFA,
> > +		.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 = 0xFA,
> > +		.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 = 0xF9,
> > +		.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 = 0xF8,
> > +		.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 = 0xFB,
> > +		.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 +1127,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 const 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 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 +1152,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 +1177,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
> >  	struct bmc150_accel_data *data;
> >  	struct iio_dev *indio_dev;
> >  	int ret;
> > +	const char *name = NULL;
> > +	int chip_id = 0;
> >  
> >  	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> >  	if (!indio_dev)
> > @@ -1092,6 +1188,16 @@ static int bmc150_accel_probe(struct i2c_client *client,
> >  	i2c_set_clientdata(client, indio_dev);
> >  	data->client = client;
> >  
> > +	if (id) {
> > +		name = 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 +1205,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 +1390,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},
> >  	{}
> >  };
> >  
> > 



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v5 3/3] iio: accel: BMC150: add support for other Bosch chips
  2014-09-10 19:43           ` Srinivas Pandruvada
@ 2014-09-13 20:37             ` Jonathan Cameron
  0 siblings, 0 replies; 21+ messages in thread
From: Jonathan Cameron @ 2014-09-13 20:37 UTC (permalink / raw)
  To: Srinivas Pandruvada
  Cc: Laurentiu Palcu, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald, linux-iio, linux-kernel

On 10/09/14 20:43, Srinivas Pandruvada wrote:
> On Wed, 2014-09-10 at 20:35 +0100, Jonathan Cameron wrote:
>> On 02/09/14 10:30, 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;
>>>  * rename bmc150_scale_info struct member 'range' to 'reg_range' to be
>>>    consistent with the naming convention used elsewhere in the driver
>>>    and declare it u8, instead of int;
>>>  * change CONFIG description to list all supported chips;
>>>
>>> Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
>> Looks fine to me, though I'm not really in a fit state to review right now.
>> Srinivas, do you want to give an Ack?
> Sure
> 
> Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Applied to the togreg branch of iio.git - initially pushed out as testing
for the autobuilders to play.

Thanks,

Jonathan
> 
>>> ---
>>>
>>> Changes in v5:
>>>  * addressed Joe's suggestion to rewrite a small portion of the code to make it
>>>    more readable;
>>>  * changed the CONFIG description according to Srinivas's advise;
>>>
>>> Changes in v4:
>>>  * address Peter's comments: see 3rd bullet in the commit's message. As a result, do
>>>    some re-indentation to make lines fit 80 chars;
>>>
>>> Changes in v3:
>>>  * remove the chip id macros since they were not used anywhere else and put the id
>>>    values directly in the chip info table;
>>>  * fix the unnecessary casting from const char * to char * and back;
>>>
>>> laurentiu
>>>
>>>  drivers/iio/accel/Kconfig        |   4 +-
>>>  drivers/iio/accel/bmc150-accel.c | 234 +++++++++++++++++++++++++++++----------
>>>  2 files changed, 178 insertions(+), 60 deletions(-)
>>>
>>> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
>>> index 01b857e..01a2151 100644
>>> --- a/drivers/iio/accel/Kconfig
>>> +++ b/drivers/iio/accel/Kconfig
>>> @@ -23,7 +23,9 @@ config BMC150_ACCEL
>>>  	select IIO_BUFFER
>>>  	select IIO_TRIGGERED_BUFFER
>>>  	help
>>> -	  Say yes here to build support for the Bosch BMC150 accelerometer.
>>> +	  Say yes here to build support for the following Bosch accelerometers:
>>> +	  BMC150, BMI055, BMA250E, BMA222E, BMA255, BMA280.
>>> +
>>>  	  Currently this only supports the device via an i2c interface.
>>>  
>>>  	  This is a combo module with both accelerometer and magnetometer.
>>> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
>>> index 0e6566a..22c096c 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
>>> @@ -34,7 +41,6 @@
>>>  #define BMC150_ACCEL_GPIO_NAME			"bmc150_accel_int"
>>>  
>>>  #define BMC150_ACCEL_REG_CHIP_ID		0x00
>>> -#define BMC150_ACCEL_CHIP_ID_VAL		0xFA
>>>  
>>>  #define BMC150_ACCEL_REG_INT_STATUS_2		0x0B
>>>  #define BMC150_ACCEL_ANY_MOTION_MASK		0x07
>>> @@ -126,6 +132,18 @@ enum bmc150_power_modes {
>>>  	BMC150_ACCEL_SLEEP_MODE_SUSPEND = 0x04,
>>>  };
>>>  
>>> +struct bmc150_scale_info {
>>> +	int scale;
>>> +	u8 reg_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 +158,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,16 +187,8 @@ 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;
>>> +	u8 reg_value;
>>>  } bmc150_accel_sleep_value_table[] = { {0, 0},
>>>  				       {500, BMC150_ACCEL_SLEEP_500_MICRO},
>>>  				       {1000, BMC150_ACCEL_SLEEP_1_MS},
>>> @@ -267,7 +278,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 +552,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->client,
>>> +				     BMC150_ACCEL_REG_PMU_RANGE,
>>> +				     data->chip_info->scale_table[i].reg_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].reg_range;
>>>  			return 0;
>>>  		}
>>>  	}
>>> @@ -580,10 +591,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 +613,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 +639,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;
>>>  		}
>>> @@ -646,13 +658,13 @@ static int bmc150_accel_read_raw(struct iio_dev *indio_dev,
>>>  		case IIO_ACCEL:
>>>  		{
>>>  			int i;
>>> +			const struct bmc150_scale_info *si;
>>> +			int st_size = ARRAY_SIZE(data->chip_info->scale_table);
>>>  
>>> -			for (i = 0; i < ARRAY_SIZE(bmc150_accel_scale_table);
>>> -									 ++i) {
>>> -				if (bmc150_accel_scale_table[i].range ==
>>> -								data->range) {
>>> -					*val2 =
>>> -					bmc150_accel_scale_table[i].scale;
>>> +			for (i = 0; i < st_size; ++i) {
>>> +				si = &data->chip_info->scale_table[i];
>>> +				if (si->reg_range == data->range) {
>>> +					*val2 = si->scale;
>>>  					return IIO_VAL_INT_PLUS_MICRO;
>>>  				}
>>>  			}
>>> @@ -840,7 +852,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 +862,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 = 0xFA,
>>> +		.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 = 0xFA,
>>> +		.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 = 0xFA,
>>> +		.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 = 0xF9,
>>> +		.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 = 0xF8,
>>> +		.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 = 0xFB,
>>> +		.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 +1127,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 const 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 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 +1152,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 +1177,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
>>>  	struct bmc150_accel_data *data;
>>>  	struct iio_dev *indio_dev;
>>>  	int ret;
>>> +	const char *name = NULL;
>>> +	int chip_id = 0;
>>>  
>>>  	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
>>>  	if (!indio_dev)
>>> @@ -1092,6 +1188,16 @@ static int bmc150_accel_probe(struct i2c_client *client,
>>>  	i2c_set_clientdata(client, indio_dev);
>>>  	data->client = client;
>>>  
>>> +	if (id) {
>>> +		name = 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 +1205,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 +1390,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},
>>>  	{}
>>>  };
>>>  
>>>
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2014-09-13 20:37 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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

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.