linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC] iio: st: Add lsm9ds0 support for gyro accel and magn
@ 2016-04-13 19:01 Crestez Dan Leonard
  2016-04-17 11:44 ` Jonathan Cameron
  0 siblings, 1 reply; 11+ messages in thread
From: Crestez Dan Leonard @ 2016-04-13 19:01 UTC (permalink / raw)
  To: Jonathan Cameron, linux-iio, Giuseppe Barba, Denis Ciocca
  Cc: linux-kernel, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Daniel Baluta, Crestez Dan Leonard

Device is an integrated gyro/accel/magn and temperature sensor. The
device has two i2c/spi interfaces: one for the gyro and one for the
accel/magn/temp sensor.

Datasheet: http://www2.st.com/resource/en/datasheet/lsm9ds0.pdf

The patch uses existing iio st_sensor infrastructure and just adds a
bunch of new device IDs and the new register mappings.

Temperature support is not included.

Signed-off-by: Crestez Dan Leonard <leonard.crestez@intel.com>
---

I tested basic reading of values using software triggers and i2c and the values
seems plausible.

I tested lsm9ds0-accel and lsm9ds0-magn separately because I don't know how to
instantiate two iio drivers for the same I2C device using devicetree. Can you
provide a sample of this or is this not currently supported?

It seems to me that the LSM303AGR device has the same problem: it's an
accel+magn combo behind a single I2C address. How is that supposed to be
instantiated? Other supported combo devices seem to have multiple I2C
addresses.

It's also not clear how to properly deal with bits shared between the accel and
magn part like "block data update" or "interrupt polarity".

 .../devicetree/bindings/iio/st-sensors.txt         |   3 +
 drivers/iio/accel/st_accel.h                       |   1 +
 drivers/iio/accel/st_accel_core.c                  | 122 ++++++++++++++++++++
 drivers/iio/accel/st_accel_i2c.c                   |   5 +
 drivers/iio/accel/st_accel_spi.c                   |   1 +
 drivers/iio/gyro/st_gyro.h                         |   1 +
 drivers/iio/gyro/st_gyro_core.c                    |   1 +
 drivers/iio/gyro/st_gyro_i2c.c                     |   5 +
 drivers/iio/gyro/st_gyro_spi.c                     |   1 +
 drivers/iio/magnetometer/st_magn.h                 |   1 +
 drivers/iio/magnetometer/st_magn_core.c            | 123 +++++++++++++++++++++
 drivers/iio/magnetometer/st_magn_i2c.c             |   5 +
 drivers/iio/magnetometer/st_magn_spi.c             |   1 +
 13 files changed, 270 insertions(+)

diff --git a/Documentation/devicetree/bindings/iio/st-sensors.txt b/Documentation/devicetree/bindings/iio/st-sensors.txt
index 71b7bdf..65339ef 100644
--- a/Documentation/devicetree/bindings/iio/st-sensors.txt
+++ b/Documentation/devicetree/bindings/iio/st-sensors.txt
@@ -38,6 +38,7 @@ Accelerometers:
 - st,lsm303agr-accel
 - st,lis2dh12-accel
 - st,h3lis331dl-accel
+- st,lsm9ds0-accel
 
 Gyroscopes:
 - st,l3g4200d-gyro
@@ -47,6 +48,7 @@ Gyroscopes:
 - st,l3gd20-gyro
 - st,l3g4is-gyro
 - st,lsm330-gyro
+- st,lsm9ds0-gyro
 
 Magnetometers:
 - st,lsm303agr-magn
@@ -54,6 +56,7 @@ Magnetometers:
 - st,lsm303dlhc-magn
 - st,lsm303dlm-magn
 - st,lis3mdl-magn
+- st,lsm9ds0-magn
 
 Pressure sensors:
 - st,lps001wp-press
diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h
index 57f83a6..e90cd6a 100644
--- a/drivers/iio/accel/st_accel.h
+++ b/drivers/iio/accel/st_accel.h
@@ -29,6 +29,7 @@
 #define LSM330_ACCEL_DEV_NAME		"lsm330_accel"
 #define LSM303AGR_ACCEL_DEV_NAME	"lsm303agr_accel"
 #define LIS2DH12_ACCEL_DEV_NAME		"lis2dh12_accel"
+#define LSM9DS0_ACCEL_DEV_NAME		"lsm9ds0_accel"
 
 /**
 * struct st_sensors_platform_data - default accel platform data
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index fee32e3..0941b46 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -211,6 +211,50 @@
 #define ST_ACCEL_6_IHL_IRQ_MASK			0x80
 #define ST_ACCEL_6_MULTIREAD_BIT		true
 
+/* CUSTOM VALUES FOR SENSOR 7 */
+#define ST_ACCEL_7_WAI_EXP			0x49
+#define ST_ACCEL_7_ODR_ADDR			0x20
+#define ST_ACCEL_7_ODR_MASK			0xf0
+#define ST_ACCEL_7_ODR_AVL_3HZ_VAL		0x01
+#define ST_ACCEL_7_ODR_AVL_6HZ_VAL		0x02
+#define ST_ACCEL_7_ODR_AVL_12HZ_VAL		0x03
+#define ST_ACCEL_7_ODR_AVL_25HZ_VAL		0x04
+#define ST_ACCEL_7_ODR_AVL_50HZ_VAL		0x05
+#define ST_ACCEL_7_ODR_AVL_100HZ_VAL		0x06
+#define ST_ACCEL_7_ODR_AVL_200HZ_VAL		0x07
+#define ST_ACCEL_7_ODR_AVL_400HZ_VAL		0x08
+#define ST_ACCEL_7_ODR_AVL_800HZ_VAL		0x09
+#define ST_ACCEL_7_ODR_AVL_1600HZ_VAL		0x0a
+#define ST_ACCEL_7_FS_ADDR			0x21
+#define ST_ACCEL_7_FS_MASK			0x38
+#define ST_ACCEL_7_FS_AVL_2_VAL			0x00
+#define ST_ACCEL_7_FS_AVL_4_VAL			0x01
+#define ST_ACCEL_7_FS_AVL_6_VAL			0x02
+#define ST_ACCEL_7_FS_AVL_8_VAL			0x03
+#define ST_ACCEL_7_FS_AVL_16_VAL		0x04
+#define ST_ACCEL_7_FS_AVL_2_GAIN		IIO_G_TO_M_S_2(61)
+#define ST_ACCEL_7_FS_AVL_4_GAIN		IIO_G_TO_M_S_2(122)
+#define ST_ACCEL_7_FS_AVL_6_GAIN		IIO_G_TO_M_S_2(183)
+#define ST_ACCEL_7_FS_AVL_8_GAIN		IIO_G_TO_M_S_2(244)
+#define ST_ACCEL_7_FS_AVL_16_GAIN		IIO_G_TO_M_S_2(732)
+#define ST_ACCEL_7_BDU_ADDR			0x20
+#define ST_ACCEL_7_BDU_MASK			0x08
+#define ST_ACCEL_7_DRDY_IRQ_ADDR		0x22
+#define ST_ACCEL_7_DRDY_IRQ_INT1_MASK		0x04
+/* INT2 is actually at another address. Not supported by driver */
+/*
+#define ST_ACCEL_7_DRDY_IRQ_INT2_ADDR		0x23
+#define ST_ACCEL_7_DRDY_IRQ_INT2_MASK		0x08
+ */
+/* Common to magnetometer so not supported */
+/*
+#define ST_ACCEL_7_IHL_IRQ_ADDR			0x12
+#define ST_ACCEL_7_IHL_IRQ_MASK			0x80
+ */
+#define ST_ACCEL_7_IG1_EN_ADDR			0x22
+#define ST_ACCEL_7_IG1_EN_MASK			0x20
+#define ST_ACCEL_7_MULTIREAD_BIT		true
+
 static const struct iio_chan_spec st_accel_8bit_channels[] = {
 	ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
@@ -649,6 +693,84 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
 		.multi_read_bit = ST_ACCEL_6_MULTIREAD_BIT,
 		.bootime = 2,
 	},
+	{
+		.wai = ST_ACCEL_7_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
+		.sensors_supported = {
+			[0] = LSM9DS0_ACCEL_DEV_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_accel_16bit_channels,
+		.odr = {
+			.addr = ST_ACCEL_7_ODR_ADDR,
+			.mask = ST_ACCEL_7_ODR_MASK,
+			.odr_avl = {
+				{ 3, ST_ACCEL_7_ODR_AVL_3HZ_VAL },
+				{ 6, ST_ACCEL_7_ODR_AVL_6HZ_VAL, },
+				{ 12, ST_ACCEL_7_ODR_AVL_12HZ_VAL, },
+				{ 25, ST_ACCEL_7_ODR_AVL_25HZ_VAL, },
+				{ 50, ST_ACCEL_7_ODR_AVL_50HZ_VAL, },
+				{ 100, ST_ACCEL_7_ODR_AVL_100HZ_VAL, },
+				{ 200, ST_ACCEL_7_ODR_AVL_200HZ_VAL, },
+				{ 400, ST_ACCEL_7_ODR_AVL_400HZ_VAL, },
+				{ 800, ST_ACCEL_7_ODR_AVL_800HZ_VAL, },
+				{ 1600, ST_ACCEL_7_ODR_AVL_1600HZ_VAL, },
+			},
+		},
+		.pw = {
+			.addr = ST_ACCEL_7_ODR_ADDR,
+			.mask = ST_ACCEL_7_ODR_MASK,
+			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+		},
+		.enable_axis = {
+			.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
+			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
+		},
+		.fs = {
+			.addr = ST_ACCEL_7_FS_ADDR,
+			.mask = ST_ACCEL_7_FS_MASK,
+			.fs_avl = {
+				[0] = {
+					.num = ST_ACCEL_FS_AVL_2G,
+					.value = ST_ACCEL_7_FS_AVL_2_VAL,
+					.gain = ST_ACCEL_7_FS_AVL_2_GAIN,
+				},
+				[1] = {
+					.num = ST_ACCEL_FS_AVL_4G,
+					.value = ST_ACCEL_7_FS_AVL_4_VAL,
+					.gain = ST_ACCEL_7_FS_AVL_4_GAIN,
+				},
+				[2] = {
+					.num = ST_ACCEL_FS_AVL_6G,
+					.value = ST_ACCEL_7_FS_AVL_6_VAL,
+					.gain = ST_ACCEL_7_FS_AVL_6_GAIN,
+				},
+				[3] = {
+					.num = ST_ACCEL_FS_AVL_8G,
+					.value = ST_ACCEL_7_FS_AVL_8_VAL,
+					.gain = ST_ACCEL_7_FS_AVL_8_GAIN,
+				},
+				[4] = {
+					.num = ST_ACCEL_FS_AVL_16G,
+					.value = ST_ACCEL_7_FS_AVL_16_VAL,
+					.gain = ST_ACCEL_7_FS_AVL_16_GAIN,
+				},
+			},
+		},
+		.bdu = {
+			.addr = ST_ACCEL_7_BDU_ADDR,
+			.mask = ST_ACCEL_7_BDU_MASK,
+		},
+		.drdy_irq = {
+			.addr = ST_ACCEL_7_DRDY_IRQ_ADDR,
+			.mask_int1 = ST_ACCEL_7_DRDY_IRQ_INT1_MASK,
+			.ig1 = {
+				.en_addr = ST_ACCEL_7_IG1_EN_ADDR,
+				.en_mask = ST_ACCEL_7_IG1_EN_MASK,
+			},
+		},
+		.multi_read_bit = ST_ACCEL_7_MULTIREAD_BIT,
+		.bootime = 2,
+	},
 };
 
 static int st_accel_read_raw(struct iio_dev *indio_dev,
diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c
index 7333ee9..7a2a3ab 100644
--- a/drivers/iio/accel/st_accel_i2c.c
+++ b/drivers/iio/accel/st_accel_i2c.c
@@ -80,6 +80,10 @@ static const struct of_device_id st_accel_of_match[] = {
 		.compatible = "st,h3lis331dl-accel",
 		.data = H3LIS331DL_DRIVER_NAME,
 	},
+	{
+		.compatible = "st,lsm9ds0-accel",
+		.data = LSM9DS0_ACCEL_DEV_NAME,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, st_accel_of_match);
@@ -130,6 +134,7 @@ static const struct i2c_device_id st_accel_id_table[] = {
 	{ LSM330_ACCEL_DEV_NAME },
 	{ LSM303AGR_ACCEL_DEV_NAME },
 	{ LIS2DH12_ACCEL_DEV_NAME },
+	{ LSM9DS0_ACCEL_DEV_NAME },
 	{},
 };
 MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c
index fcd5847..2fc32c92f 100644
--- a/drivers/iio/accel/st_accel_spi.c
+++ b/drivers/iio/accel/st_accel_spi.c
@@ -59,6 +59,7 @@ static const struct spi_device_id st_accel_id_table[] = {
 	{ LSM330_ACCEL_DEV_NAME },
 	{ LSM303AGR_ACCEL_DEV_NAME },
 	{ LIS2DH12_ACCEL_DEV_NAME },
+	{ LSM9DS0_ACCEL_DEV_NAME },
 	{},
 };
 MODULE_DEVICE_TABLE(spi, st_accel_id_table);
diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h
index 5353d63..a5c5c4e 100644
--- a/drivers/iio/gyro/st_gyro.h
+++ b/drivers/iio/gyro/st_gyro.h
@@ -21,6 +21,7 @@
 #define L3GD20_GYRO_DEV_NAME		"l3gd20"
 #define L3G4IS_GYRO_DEV_NAME		"l3g4is_ui"
 #define LSM330_GYRO_DEV_NAME		"lsm330_gyro"
+#define LSM9DS0_GYRO_DEV_NAME		"lsm9ds0_gyro"
 
 /**
  * struct st_sensors_platform_data - gyro platform data
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
index 110f95b..9589ba9 100644
--- a/drivers/iio/gyro/st_gyro_core.c
+++ b/drivers/iio/gyro/st_gyro_core.c
@@ -203,6 +203,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
 			[2] = LSM330DLC_GYRO_DEV_NAME,
 			[3] = L3G4IS_GYRO_DEV_NAME,
 			[4] = LSM330_GYRO_DEV_NAME,
+			[5] = LSM9DS0_GYRO_DEV_NAME,
 		},
 		.ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
 		.odr = {
diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c
index 6848451..40056b8 100644
--- a/drivers/iio/gyro/st_gyro_i2c.c
+++ b/drivers/iio/gyro/st_gyro_i2c.c
@@ -48,6 +48,10 @@ static const struct of_device_id st_gyro_of_match[] = {
 		.compatible = "st,lsm330-gyro",
 		.data = LSM330_GYRO_DEV_NAME,
 	},
+	{
+		.compatible = "st,lsm9ds0-gyro",
+		.data = LSM9DS0_GYRO_DEV_NAME,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, st_gyro_of_match);
@@ -93,6 +97,7 @@ static const struct i2c_device_id st_gyro_id_table[] = {
 	{ L3GD20_GYRO_DEV_NAME },
 	{ L3G4IS_GYRO_DEV_NAME },
 	{ LSM330_GYRO_DEV_NAME },
+	{ LSM9DS0_GYRO_DEV_NAME },
 	{},
 };
 MODULE_DEVICE_TABLE(i2c, st_gyro_id_table);
diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c
index d2b7a5f..fbf2fae 100644
--- a/drivers/iio/gyro/st_gyro_spi.c
+++ b/drivers/iio/gyro/st_gyro_spi.c
@@ -54,6 +54,7 @@ static const struct spi_device_id st_gyro_id_table[] = {
 	{ L3GD20_GYRO_DEV_NAME },
 	{ L3G4IS_GYRO_DEV_NAME },
 	{ LSM330_GYRO_DEV_NAME },
+	{ LSM9DS0_GYRO_DEV_NAME },
 	{},
 };
 MODULE_DEVICE_TABLE(spi, st_gyro_id_table);
diff --git a/drivers/iio/magnetometer/st_magn.h b/drivers/iio/magnetometer/st_magn.h
index 06a4d9c..2176064 100644
--- a/drivers/iio/magnetometer/st_magn.h
+++ b/drivers/iio/magnetometer/st_magn.h
@@ -19,6 +19,7 @@
 #define LSM303DLM_MAGN_DEV_NAME		"lsm303dlm_magn"
 #define LIS3MDL_MAGN_DEV_NAME		"lis3mdl"
 #define LSM303AGR_MAGN_DEV_NAME		"lsm303agr_magn"
+#define LSM9DS0_MAGN_DEV_NAME		"lsm9ds0_magn"
 
 int st_magn_common_probe(struct iio_dev *indio_dev);
 void st_magn_common_remove(struct iio_dev *indio_dev);
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
index 501f858..da3f29a 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -36,6 +36,7 @@
 /* FULLSCALE */
 #define ST_MAGN_FS_AVL_1300MG			1300
 #define ST_MAGN_FS_AVL_1900MG			1900
+#define ST_MAGN_FS_AVL_2000MG			2000
 #define ST_MAGN_FS_AVL_2500MG			2500
 #define ST_MAGN_FS_AVL_4000MG			4000
 #define ST_MAGN_FS_AVL_4700MG			4700
@@ -183,6 +184,50 @@
 #define ST_MAGN_3_OUT_Y_L_ADDR			0x6a
 #define ST_MAGN_3_OUT_Z_L_ADDR			0x6c
 
+/* CUSTOM VALUES FOR SENSOR 4 */
+#define ST_MAGN_4_WAI_EXP			0x49
+#define ST_MAGN_4_ODR_ADDR			0x24
+#define ST_MAGN_4_ODR_MASK			0x1c
+#define ST_MAGN_4_ODR_AVL_3HZ_VAL		0x00
+#define ST_MAGN_4_ODR_AVL_6HZ_VAL		0x01
+#define ST_MAGN_4_ODR_AVL_12HZ_VAL		0x02
+#define ST_MAGN_4_ODR_AVL_25HZ_VAL		0x03
+#define ST_MAGN_4_ODR_AVL_50HZ_VAL		0x04
+#define ST_MAGN_4_ODR_AVL_100HZ_VAL		0x05
+#define ST_MAGN_4_PW_ADDR			0x26
+#define ST_MAGN_4_PW_MASK			0x03
+#define ST_MAGN_4_PW_ON				0x00
+#define ST_MAGN_4_PW_OFF			0x03
+#define ST_MAGN_4_FS_ADDR			0x25
+#define ST_MAGN_4_FS_MASK			0x60
+#define ST_MAGN_4_FS_AVL_2000_VAL		0x00
+#define ST_MAGN_4_FS_AVL_4000_VAL		0x01
+#define ST_MAGN_4_FS_AVL_8000_VAL		0x02
+#define ST_MAGN_4_FS_AVL_12000_VAL		0x03
+#define ST_MAGN_4_FS_AVL_2000_GAIN		73
+#define ST_MAGN_4_FS_AVL_4000_GAIN		146
+#define ST_MAGN_4_FS_AVL_8000_GAIN		292
+#define ST_MAGN_4_FS_AVL_12000_GAIN		438
+/* Shared with accelerometer */
+#define ST_MAGN_4_BDU_ADDR			0x20
+#define ST_MAGN_4_BDU_MASK			0x08
+#define ST_MAGN_4_DRDY_IRQ_ADDR			0x22
+#define ST_MAGN_4_DRDY_INT_MASK			0x01
+/* INT2 is actually at another address. Not supported by driver */
+/*
+#define ST_MAGN_4_DRDY_IRQ_INT2_ADDR		0x23
+#define ST_MAGN_4_DRDY_IRQ_INT2_MASK		0x04
+ */
+/* Common to accelerometer so not supported */
+/*
+#define ST_MAGN_4_IHL_IRQ_ADDR			0x12
+#define ST_MAGN_4_IHL_IRQ_MASK			0x80
+ */
+#define ST_MAGN_4_MULTIREAD_BIT			true
+#define ST_MAGN_4_OUT_X_L_ADDR			0x08
+#define ST_MAGN_4_OUT_Y_L_ADDR			0x0a
+#define ST_MAGN_4_OUT_Z_L_ADDR			0x0c
+
 static const struct iio_chan_spec st_magn_16bit_channels[] = {
 	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
@@ -231,6 +276,22 @@ static const struct iio_chan_spec st_magn_3_16bit_channels[] = {
 	IIO_CHAN_SOFT_TIMESTAMP(3)
 };
 
+static const struct iio_chan_spec st_magn_4_16bit_channels[] = {
+	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
+			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+			ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
+			ST_MAGN_4_OUT_X_L_ADDR),
+	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
+			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+			ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
+			ST_MAGN_4_OUT_Y_L_ADDR),
+	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
+			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+			ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
+			ST_MAGN_4_OUT_Z_L_ADDR),
+	IIO_CHAN_SOFT_TIMESTAMP(3)
+};
+
 static const struct st_sensor_settings st_magn_sensors_settings[] = {
 	{
 		.wai = 0, /* This sensor has no valid WhoAmI report 0 */
@@ -488,6 +549,68 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
 		.multi_read_bit = ST_MAGN_3_MULTIREAD_BIT,
 		.bootime = 2,
 	},
+	{
+		.wai = ST_MAGN_4_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
+		.sensors_supported = {
+			[0] = LSM9DS0_MAGN_DEV_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_magn_4_16bit_channels,
+		.odr = {
+			.addr = ST_MAGN_4_ODR_ADDR,
+			.mask = ST_MAGN_4_ODR_MASK,
+			.odr_avl = {
+				{ 3, ST_MAGN_4_ODR_AVL_3HZ_VAL, },
+				{ 6, ST_MAGN_4_ODR_AVL_6HZ_VAL, },
+				{ 12, ST_MAGN_4_ODR_AVL_12HZ_VAL, },
+				{ 25, ST_MAGN_4_ODR_AVL_25HZ_VAL, },
+				{ 50, ST_MAGN_4_ODR_AVL_50HZ_VAL, },
+				{ 100, ST_MAGN_4_ODR_AVL_100HZ_VAL, },
+			},
+		},
+		.pw = {
+			.addr = ST_MAGN_4_PW_ADDR,
+			.mask = ST_MAGN_4_PW_MASK,
+			.value_on = ST_MAGN_4_PW_ON,
+			.value_off = ST_MAGN_4_PW_OFF,
+		},
+		.fs = {
+			.addr = ST_MAGN_4_FS_ADDR,
+			.mask = ST_MAGN_4_FS_MASK,
+			.fs_avl = {
+				[0] = {
+					.num = ST_MAGN_FS_AVL_2000MG,
+					.value = ST_MAGN_4_FS_AVL_2000_VAL,
+					.gain = ST_MAGN_4_FS_AVL_2000_GAIN,
+				},
+				[1] = {
+					.num = ST_MAGN_FS_AVL_4000MG,
+					.value = ST_MAGN_4_FS_AVL_4000_VAL,
+					.gain = ST_MAGN_4_FS_AVL_4000_GAIN,
+				},
+				[2] = {
+					.num = ST_MAGN_FS_AVL_8000MG,
+					.value = ST_MAGN_4_FS_AVL_8000_VAL,
+					.gain = ST_MAGN_4_FS_AVL_8000_GAIN,
+				},
+				[3] = {
+					.num = ST_MAGN_FS_AVL_12000MG,
+					.value = ST_MAGN_4_FS_AVL_12000_VAL,
+					.gain = ST_MAGN_4_FS_AVL_12000_GAIN,
+				},
+			},
+		},
+		.bdu = {
+			.addr = ST_MAGN_4_BDU_ADDR,
+			.mask = ST_MAGN_4_BDU_MASK,
+		},
+		.drdy_irq = {
+			.addr = ST_MAGN_4_DRDY_IRQ_ADDR,
+			.mask_int1 = ST_MAGN_4_DRDY_INT_MASK,
+		},
+		.multi_read_bit = ST_MAGN_4_MULTIREAD_BIT,
+		.bootime = 2,
+	},
 };
 
 static int st_magn_read_raw(struct iio_dev *indio_dev,
diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c
index 8aa37af..1c7c487 100644
--- a/drivers/iio/magnetometer/st_magn_i2c.c
+++ b/drivers/iio/magnetometer/st_magn_i2c.c
@@ -40,6 +40,10 @@ static const struct of_device_id st_magn_of_match[] = {
 		.compatible = "st,lsm303agr-magn",
 		.data = LSM303AGR_MAGN_DEV_NAME,
 	},
+	{
+		.compatible = "st,lsm9ds0-magn",
+		.data = LSM9DS0_MAGN_DEV_NAME,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, st_magn_of_match);
@@ -84,6 +88,7 @@ static const struct i2c_device_id st_magn_id_table[] = {
 	{ LSM303DLM_MAGN_DEV_NAME },
 	{ LIS3MDL_MAGN_DEV_NAME },
 	{ LSM303AGR_MAGN_DEV_NAME },
+	{ LSM9DS0_MAGN_DEV_NAME },
 	{},
 };
 MODULE_DEVICE_TABLE(i2c, st_magn_id_table);
diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c
index 6325e7d..8c4e1d6 100644
--- a/drivers/iio/magnetometer/st_magn_spi.c
+++ b/drivers/iio/magnetometer/st_magn_spi.c
@@ -52,6 +52,7 @@ static const struct spi_device_id st_magn_id_table[] = {
 	{ LSM303DLM_MAGN_DEV_NAME },
 	{ LIS3MDL_MAGN_DEV_NAME },
 	{ LSM303AGR_MAGN_DEV_NAME },
+	{ LSM9DS0_MAGN_DEV_NAME },
 	{},
 };
 MODULE_DEVICE_TABLE(spi, st_magn_id_table);
-- 
2.5.5

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

* Re: [RFC] iio: st: Add lsm9ds0 support for gyro accel and magn
  2016-04-13 19:01 [RFC] iio: st: Add lsm9ds0 support for gyro accel and magn Crestez Dan Leonard
@ 2016-04-17 11:44 ` Jonathan Cameron
  2016-04-17 12:25   ` Wolfram Sang
                     ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Jonathan Cameron @ 2016-04-17 11:44 UTC (permalink / raw)
  To: Crestez Dan Leonard, linux-iio, Giuseppe Barba, Denis Ciocca
  Cc: linux-kernel, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Daniel Baluta, Lars-Peter Clausen,
	Peter Rosin, Wolfram Sang

On 13/04/16 20:01, Crestez Dan Leonard wrote:
> Device is an integrated gyro/accel/magn and temperature sensor. The
> device has two i2c/spi interfaces: one for the gyro and one for the
> accel/magn/temp sensor.
> 
> Datasheet: http://www2.st.com/resource/en/datasheet/lsm9ds0.pdf
> 
> The patch uses existing iio st_sensor infrastructure and just adds a
> bunch of new device IDs and the new register mappings.
> 
> Temperature support is not included.
> 
> Signed-off-by: Crestez Dan Leonard <leonard.crestez@intel.com>
This looks fine to me.  Needs acks from Denis though.
Also, clearly your questions need addressing.
> ---
> 
> I tested basic reading of values using software triggers and i2c and the values
> seems plausible.
> 
> I tested lsm9ds0-accel and lsm9ds0-magn separately because I don't know how to
> instantiate two iio drivers for the same I2C device using devicetree. Can you
> provide a sample of this or is this not currently supported?
> 
> It seems to me that the LSM303AGR device has the same problem: it's an
> accel+magn combo behind a single I2C address. How is that supposed to be
> instantiated? Other supported combo devices seem to have multiple I2C
> addresses.
Excellent question. I'd not picked up on this before.
It could be done with a 'dummy mux' I guess though that's messy.
Guiseppe how are you doing it for the lsm303agr?

Cc'd Peter Rosin who has kindly walked into maintainer I2C mux
support recently ;) An Wolfram for obvious reasons..
To bring you two up to date, we have effectively two separate devices
(very nearly) sat behind a single i2c address.  They have non overlapping
register maps.
We have a big overarching st_sensors driver framework which contains numerous
examples of parts with just a magnetometer or just an accelerometer but in this
case they have combined these two.  It would be nice to reuse the infrastructure
without having to have a separate version for the two cases that exist so far. 
I suppose such a separate handling wouldn't be too terrible if we have to do it
though - just a new device implementation of magnaccel for the st-sensors.
> 
> It's also not clear how to properly deal with bits shared between the accel and
> magn part like "block data update" or "interrupt polarity".

Perhaps just document that it's not allowed to have different choices for them
in the bindings?
Jonathan
> 
>  .../devicetree/bindings/iio/st-sensors.txt         |   3 +
>  drivers/iio/accel/st_accel.h                       |   1 +
>  drivers/iio/accel/st_accel_core.c                  | 122 ++++++++++++++++++++
>  drivers/iio/accel/st_accel_i2c.c                   |   5 +
>  drivers/iio/accel/st_accel_spi.c                   |   1 +
>  drivers/iio/gyro/st_gyro.h                         |   1 +
>  drivers/iio/gyro/st_gyro_core.c                    |   1 +
>  drivers/iio/gyro/st_gyro_i2c.c                     |   5 +
>  drivers/iio/gyro/st_gyro_spi.c                     |   1 +
>  drivers/iio/magnetometer/st_magn.h                 |   1 +
>  drivers/iio/magnetometer/st_magn_core.c            | 123 +++++++++++++++++++++
>  drivers/iio/magnetometer/st_magn_i2c.c             |   5 +
>  drivers/iio/magnetometer/st_magn_spi.c             |   1 +
>  13 files changed, 270 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/iio/st-sensors.txt b/Documentation/devicetree/bindings/iio/st-sensors.txt
> index 71b7bdf..65339ef 100644
> --- a/Documentation/devicetree/bindings/iio/st-sensors.txt
> +++ b/Documentation/devicetree/bindings/iio/st-sensors.txt
> @@ -38,6 +38,7 @@ Accelerometers:
>  - st,lsm303agr-accel
>  - st,lis2dh12-accel
>  - st,h3lis331dl-accel
> +- st,lsm9ds0-accel
>  
>  Gyroscopes:
>  - st,l3g4200d-gyro
> @@ -47,6 +48,7 @@ Gyroscopes:
>  - st,l3gd20-gyro
>  - st,l3g4is-gyro
>  - st,lsm330-gyro
> +- st,lsm9ds0-gyro
>  
>  Magnetometers:
>  - st,lsm303agr-magn
> @@ -54,6 +56,7 @@ Magnetometers:
>  - st,lsm303dlhc-magn
>  - st,lsm303dlm-magn
>  - st,lis3mdl-magn
> +- st,lsm9ds0-magn
>  
>  Pressure sensors:
>  - st,lps001wp-press
> diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h
> index 57f83a6..e90cd6a 100644
> --- a/drivers/iio/accel/st_accel.h
> +++ b/drivers/iio/accel/st_accel.h
> @@ -29,6 +29,7 @@
>  #define LSM330_ACCEL_DEV_NAME		"lsm330_accel"
>  #define LSM303AGR_ACCEL_DEV_NAME	"lsm303agr_accel"
>  #define LIS2DH12_ACCEL_DEV_NAME		"lis2dh12_accel"
> +#define LSM9DS0_ACCEL_DEV_NAME		"lsm9ds0_accel"
>  
>  /**
>  * struct st_sensors_platform_data - default accel platform data
> diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
> index fee32e3..0941b46 100644
> --- a/drivers/iio/accel/st_accel_core.c
> +++ b/drivers/iio/accel/st_accel_core.c
> @@ -211,6 +211,50 @@
>  #define ST_ACCEL_6_IHL_IRQ_MASK			0x80
>  #define ST_ACCEL_6_MULTIREAD_BIT		true
>  
> +/* CUSTOM VALUES FOR SENSOR 7 */
> +#define ST_ACCEL_7_WAI_EXP			0x49
> +#define ST_ACCEL_7_ODR_ADDR			0x20
> +#define ST_ACCEL_7_ODR_MASK			0xf0
> +#define ST_ACCEL_7_ODR_AVL_3HZ_VAL		0x01
> +#define ST_ACCEL_7_ODR_AVL_6HZ_VAL		0x02
> +#define ST_ACCEL_7_ODR_AVL_12HZ_VAL		0x03
> +#define ST_ACCEL_7_ODR_AVL_25HZ_VAL		0x04
> +#define ST_ACCEL_7_ODR_AVL_50HZ_VAL		0x05
> +#define ST_ACCEL_7_ODR_AVL_100HZ_VAL		0x06
> +#define ST_ACCEL_7_ODR_AVL_200HZ_VAL		0x07
> +#define ST_ACCEL_7_ODR_AVL_400HZ_VAL		0x08
> +#define ST_ACCEL_7_ODR_AVL_800HZ_VAL		0x09
> +#define ST_ACCEL_7_ODR_AVL_1600HZ_VAL		0x0a
> +#define ST_ACCEL_7_FS_ADDR			0x21
> +#define ST_ACCEL_7_FS_MASK			0x38
> +#define ST_ACCEL_7_FS_AVL_2_VAL			0x00
> +#define ST_ACCEL_7_FS_AVL_4_VAL			0x01
> +#define ST_ACCEL_7_FS_AVL_6_VAL			0x02
> +#define ST_ACCEL_7_FS_AVL_8_VAL			0x03
> +#define ST_ACCEL_7_FS_AVL_16_VAL		0x04
> +#define ST_ACCEL_7_FS_AVL_2_GAIN		IIO_G_TO_M_S_2(61)
> +#define ST_ACCEL_7_FS_AVL_4_GAIN		IIO_G_TO_M_S_2(122)
> +#define ST_ACCEL_7_FS_AVL_6_GAIN		IIO_G_TO_M_S_2(183)
> +#define ST_ACCEL_7_FS_AVL_8_GAIN		IIO_G_TO_M_S_2(244)
> +#define ST_ACCEL_7_FS_AVL_16_GAIN		IIO_G_TO_M_S_2(732)
> +#define ST_ACCEL_7_BDU_ADDR			0x20
> +#define ST_ACCEL_7_BDU_MASK			0x08
> +#define ST_ACCEL_7_DRDY_IRQ_ADDR		0x22
> +#define ST_ACCEL_7_DRDY_IRQ_INT1_MASK		0x04
> +/* INT2 is actually at another address. Not supported by driver */
> +/*
> +#define ST_ACCEL_7_DRDY_IRQ_INT2_ADDR		0x23
> +#define ST_ACCEL_7_DRDY_IRQ_INT2_MASK		0x08
> + */
> +/* Common to magnetometer so not supported */
> +/*
> +#define ST_ACCEL_7_IHL_IRQ_ADDR			0x12
> +#define ST_ACCEL_7_IHL_IRQ_MASK			0x80
> + */
> +#define ST_ACCEL_7_IG1_EN_ADDR			0x22
> +#define ST_ACCEL_7_IG1_EN_MASK			0x20
> +#define ST_ACCEL_7_MULTIREAD_BIT		true
> +
>  static const struct iio_chan_spec st_accel_8bit_channels[] = {
>  	ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
>  			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> @@ -649,6 +693,84 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
>  		.multi_read_bit = ST_ACCEL_6_MULTIREAD_BIT,
>  		.bootime = 2,
>  	},
> +	{
> +		.wai = ST_ACCEL_7_WAI_EXP,
> +		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
> +		.sensors_supported = {
> +			[0] = LSM9DS0_ACCEL_DEV_NAME,
> +		},
> +		.ch = (struct iio_chan_spec *)st_accel_16bit_channels,
> +		.odr = {
> +			.addr = ST_ACCEL_7_ODR_ADDR,
> +			.mask = ST_ACCEL_7_ODR_MASK,
> +			.odr_avl = {
> +				{ 3, ST_ACCEL_7_ODR_AVL_3HZ_VAL },
> +				{ 6, ST_ACCEL_7_ODR_AVL_6HZ_VAL, },
> +				{ 12, ST_ACCEL_7_ODR_AVL_12HZ_VAL, },
> +				{ 25, ST_ACCEL_7_ODR_AVL_25HZ_VAL, },
> +				{ 50, ST_ACCEL_7_ODR_AVL_50HZ_VAL, },
> +				{ 100, ST_ACCEL_7_ODR_AVL_100HZ_VAL, },
> +				{ 200, ST_ACCEL_7_ODR_AVL_200HZ_VAL, },
> +				{ 400, ST_ACCEL_7_ODR_AVL_400HZ_VAL, },
> +				{ 800, ST_ACCEL_7_ODR_AVL_800HZ_VAL, },
> +				{ 1600, ST_ACCEL_7_ODR_AVL_1600HZ_VAL, },
> +			},
> +		},
> +		.pw = {
> +			.addr = ST_ACCEL_7_ODR_ADDR,
> +			.mask = ST_ACCEL_7_ODR_MASK,
> +			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
> +		},
> +		.enable_axis = {
> +			.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
> +			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
> +		},
> +		.fs = {
> +			.addr = ST_ACCEL_7_FS_ADDR,
> +			.mask = ST_ACCEL_7_FS_MASK,
> +			.fs_avl = {
> +				[0] = {
> +					.num = ST_ACCEL_FS_AVL_2G,
> +					.value = ST_ACCEL_7_FS_AVL_2_VAL,
> +					.gain = ST_ACCEL_7_FS_AVL_2_GAIN,
> +				},
> +				[1] = {
> +					.num = ST_ACCEL_FS_AVL_4G,
> +					.value = ST_ACCEL_7_FS_AVL_4_VAL,
> +					.gain = ST_ACCEL_7_FS_AVL_4_GAIN,
> +				},
> +				[2] = {
> +					.num = ST_ACCEL_FS_AVL_6G,
> +					.value = ST_ACCEL_7_FS_AVL_6_VAL,
> +					.gain = ST_ACCEL_7_FS_AVL_6_GAIN,
> +				},
> +				[3] = {
> +					.num = ST_ACCEL_FS_AVL_8G,
> +					.value = ST_ACCEL_7_FS_AVL_8_VAL,
> +					.gain = ST_ACCEL_7_FS_AVL_8_GAIN,
> +				},
> +				[4] = {
> +					.num = ST_ACCEL_FS_AVL_16G,
> +					.value = ST_ACCEL_7_FS_AVL_16_VAL,
> +					.gain = ST_ACCEL_7_FS_AVL_16_GAIN,
> +				},
> +			},
> +		},
> +		.bdu = {
> +			.addr = ST_ACCEL_7_BDU_ADDR,
> +			.mask = ST_ACCEL_7_BDU_MASK,
> +		},
> +		.drdy_irq = {
> +			.addr = ST_ACCEL_7_DRDY_IRQ_ADDR,
> +			.mask_int1 = ST_ACCEL_7_DRDY_IRQ_INT1_MASK,
> +			.ig1 = {
> +				.en_addr = ST_ACCEL_7_IG1_EN_ADDR,
> +				.en_mask = ST_ACCEL_7_IG1_EN_MASK,
> +			},
> +		},
> +		.multi_read_bit = ST_ACCEL_7_MULTIREAD_BIT,
> +		.bootime = 2,
> +	},
>  };
>  
>  static int st_accel_read_raw(struct iio_dev *indio_dev,
> diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c
> index 7333ee9..7a2a3ab 100644
> --- a/drivers/iio/accel/st_accel_i2c.c
> +++ b/drivers/iio/accel/st_accel_i2c.c
> @@ -80,6 +80,10 @@ static const struct of_device_id st_accel_of_match[] = {
>  		.compatible = "st,h3lis331dl-accel",
>  		.data = H3LIS331DL_DRIVER_NAME,
>  	},
> +	{
> +		.compatible = "st,lsm9ds0-accel",
> +		.data = LSM9DS0_ACCEL_DEV_NAME,
> +	},
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, st_accel_of_match);
> @@ -130,6 +134,7 @@ static const struct i2c_device_id st_accel_id_table[] = {
>  	{ LSM330_ACCEL_DEV_NAME },
>  	{ LSM303AGR_ACCEL_DEV_NAME },
>  	{ LIS2DH12_ACCEL_DEV_NAME },
> +	{ LSM9DS0_ACCEL_DEV_NAME },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
> diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c
> index fcd5847..2fc32c92f 100644
> --- a/drivers/iio/accel/st_accel_spi.c
> +++ b/drivers/iio/accel/st_accel_spi.c
> @@ -59,6 +59,7 @@ static const struct spi_device_id st_accel_id_table[] = {
>  	{ LSM330_ACCEL_DEV_NAME },
>  	{ LSM303AGR_ACCEL_DEV_NAME },
>  	{ LIS2DH12_ACCEL_DEV_NAME },
> +	{ LSM9DS0_ACCEL_DEV_NAME },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(spi, st_accel_id_table);
> diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h
> index 5353d63..a5c5c4e 100644
> --- a/drivers/iio/gyro/st_gyro.h
> +++ b/drivers/iio/gyro/st_gyro.h
> @@ -21,6 +21,7 @@
>  #define L3GD20_GYRO_DEV_NAME		"l3gd20"
>  #define L3G4IS_GYRO_DEV_NAME		"l3g4is_ui"
>  #define LSM330_GYRO_DEV_NAME		"lsm330_gyro"
> +#define LSM9DS0_GYRO_DEV_NAME		"lsm9ds0_gyro"
>  
>  /**
>   * struct st_sensors_platform_data - gyro platform data
> diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
> index 110f95b..9589ba9 100644
> --- a/drivers/iio/gyro/st_gyro_core.c
> +++ b/drivers/iio/gyro/st_gyro_core.c
> @@ -203,6 +203,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
>  			[2] = LSM330DLC_GYRO_DEV_NAME,
>  			[3] = L3G4IS_GYRO_DEV_NAME,
>  			[4] = LSM330_GYRO_DEV_NAME,
> +			[5] = LSM9DS0_GYRO_DEV_NAME,
>  		},
>  		.ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
>  		.odr = {
> diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c
> index 6848451..40056b8 100644
> --- a/drivers/iio/gyro/st_gyro_i2c.c
> +++ b/drivers/iio/gyro/st_gyro_i2c.c
> @@ -48,6 +48,10 @@ static const struct of_device_id st_gyro_of_match[] = {
>  		.compatible = "st,lsm330-gyro",
>  		.data = LSM330_GYRO_DEV_NAME,
>  	},
> +	{
> +		.compatible = "st,lsm9ds0-gyro",
> +		.data = LSM9DS0_GYRO_DEV_NAME,
> +	},
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, st_gyro_of_match);
> @@ -93,6 +97,7 @@ static const struct i2c_device_id st_gyro_id_table[] = {
>  	{ L3GD20_GYRO_DEV_NAME },
>  	{ L3G4IS_GYRO_DEV_NAME },
>  	{ LSM330_GYRO_DEV_NAME },
> +	{ LSM9DS0_GYRO_DEV_NAME },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(i2c, st_gyro_id_table);
> diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c
> index d2b7a5f..fbf2fae 100644
> --- a/drivers/iio/gyro/st_gyro_spi.c
> +++ b/drivers/iio/gyro/st_gyro_spi.c
> @@ -54,6 +54,7 @@ static const struct spi_device_id st_gyro_id_table[] = {
>  	{ L3GD20_GYRO_DEV_NAME },
>  	{ L3G4IS_GYRO_DEV_NAME },
>  	{ LSM330_GYRO_DEV_NAME },
> +	{ LSM9DS0_GYRO_DEV_NAME },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(spi, st_gyro_id_table);
> diff --git a/drivers/iio/magnetometer/st_magn.h b/drivers/iio/magnetometer/st_magn.h
> index 06a4d9c..2176064 100644
> --- a/drivers/iio/magnetometer/st_magn.h
> +++ b/drivers/iio/magnetometer/st_magn.h
> @@ -19,6 +19,7 @@
>  #define LSM303DLM_MAGN_DEV_NAME		"lsm303dlm_magn"
>  #define LIS3MDL_MAGN_DEV_NAME		"lis3mdl"
>  #define LSM303AGR_MAGN_DEV_NAME		"lsm303agr_magn"
> +#define LSM9DS0_MAGN_DEV_NAME		"lsm9ds0_magn"
>  
>  int st_magn_common_probe(struct iio_dev *indio_dev);
>  void st_magn_common_remove(struct iio_dev *indio_dev);
> diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
> index 501f858..da3f29a 100644
> --- a/drivers/iio/magnetometer/st_magn_core.c
> +++ b/drivers/iio/magnetometer/st_magn_core.c
> @@ -36,6 +36,7 @@
>  /* FULLSCALE */
>  #define ST_MAGN_FS_AVL_1300MG			1300
>  #define ST_MAGN_FS_AVL_1900MG			1900
> +#define ST_MAGN_FS_AVL_2000MG			2000
>  #define ST_MAGN_FS_AVL_2500MG			2500
>  #define ST_MAGN_FS_AVL_4000MG			4000
>  #define ST_MAGN_FS_AVL_4700MG			4700
> @@ -183,6 +184,50 @@
>  #define ST_MAGN_3_OUT_Y_L_ADDR			0x6a
>  #define ST_MAGN_3_OUT_Z_L_ADDR			0x6c
>  
> +/* CUSTOM VALUES FOR SENSOR 4 */
> +#define ST_MAGN_4_WAI_EXP			0x49
> +#define ST_MAGN_4_ODR_ADDR			0x24
> +#define ST_MAGN_4_ODR_MASK			0x1c
> +#define ST_MAGN_4_ODR_AVL_3HZ_VAL		0x00
> +#define ST_MAGN_4_ODR_AVL_6HZ_VAL		0x01
> +#define ST_MAGN_4_ODR_AVL_12HZ_VAL		0x02
> +#define ST_MAGN_4_ODR_AVL_25HZ_VAL		0x03
> +#define ST_MAGN_4_ODR_AVL_50HZ_VAL		0x04
> +#define ST_MAGN_4_ODR_AVL_100HZ_VAL		0x05
> +#define ST_MAGN_4_PW_ADDR			0x26
> +#define ST_MAGN_4_PW_MASK			0x03
> +#define ST_MAGN_4_PW_ON				0x00
> +#define ST_MAGN_4_PW_OFF			0x03
> +#define ST_MAGN_4_FS_ADDR			0x25
> +#define ST_MAGN_4_FS_MASK			0x60
> +#define ST_MAGN_4_FS_AVL_2000_VAL		0x00
> +#define ST_MAGN_4_FS_AVL_4000_VAL		0x01
> +#define ST_MAGN_4_FS_AVL_8000_VAL		0x02
> +#define ST_MAGN_4_FS_AVL_12000_VAL		0x03
> +#define ST_MAGN_4_FS_AVL_2000_GAIN		73
> +#define ST_MAGN_4_FS_AVL_4000_GAIN		146
> +#define ST_MAGN_4_FS_AVL_8000_GAIN		292
> +#define ST_MAGN_4_FS_AVL_12000_GAIN		438
> +/* Shared with accelerometer */
> +#define ST_MAGN_4_BDU_ADDR			0x20
> +#define ST_MAGN_4_BDU_MASK			0x08
> +#define ST_MAGN_4_DRDY_IRQ_ADDR			0x22
> +#define ST_MAGN_4_DRDY_INT_MASK			0x01
> +/* INT2 is actually at another address. Not supported by driver */
> +/*
> +#define ST_MAGN_4_DRDY_IRQ_INT2_ADDR		0x23
> +#define ST_MAGN_4_DRDY_IRQ_INT2_MASK		0x04
> + */
> +/* Common to accelerometer so not supported */
> +/*
> +#define ST_MAGN_4_IHL_IRQ_ADDR			0x12
> +#define ST_MAGN_4_IHL_IRQ_MASK			0x80
> + */
> +#define ST_MAGN_4_MULTIREAD_BIT			true
> +#define ST_MAGN_4_OUT_X_L_ADDR			0x08
> +#define ST_MAGN_4_OUT_Y_L_ADDR			0x0a
> +#define ST_MAGN_4_OUT_Z_L_ADDR			0x0c
> +
>  static const struct iio_chan_spec st_magn_16bit_channels[] = {
>  	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
>  			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> @@ -231,6 +276,22 @@ static const struct iio_chan_spec st_magn_3_16bit_channels[] = {
>  	IIO_CHAN_SOFT_TIMESTAMP(3)
>  };
>  
> +static const struct iio_chan_spec st_magn_4_16bit_channels[] = {
> +	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
> +			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> +			ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
> +			ST_MAGN_4_OUT_X_L_ADDR),
> +	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
> +			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> +			ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
> +			ST_MAGN_4_OUT_Y_L_ADDR),
> +	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
> +			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> +			ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
> +			ST_MAGN_4_OUT_Z_L_ADDR),
> +	IIO_CHAN_SOFT_TIMESTAMP(3)
> +};
> +
>  static const struct st_sensor_settings st_magn_sensors_settings[] = {
>  	{
>  		.wai = 0, /* This sensor has no valid WhoAmI report 0 */
> @@ -488,6 +549,68 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
>  		.multi_read_bit = ST_MAGN_3_MULTIREAD_BIT,
>  		.bootime = 2,
>  	},
> +	{
> +		.wai = ST_MAGN_4_WAI_EXP,
> +		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
> +		.sensors_supported = {
> +			[0] = LSM9DS0_MAGN_DEV_NAME,
> +		},
> +		.ch = (struct iio_chan_spec *)st_magn_4_16bit_channels,
> +		.odr = {
> +			.addr = ST_MAGN_4_ODR_ADDR,
> +			.mask = ST_MAGN_4_ODR_MASK,
> +			.odr_avl = {
> +				{ 3, ST_MAGN_4_ODR_AVL_3HZ_VAL, },
> +				{ 6, ST_MAGN_4_ODR_AVL_6HZ_VAL, },
> +				{ 12, ST_MAGN_4_ODR_AVL_12HZ_VAL, },
> +				{ 25, ST_MAGN_4_ODR_AVL_25HZ_VAL, },
> +				{ 50, ST_MAGN_4_ODR_AVL_50HZ_VAL, },
> +				{ 100, ST_MAGN_4_ODR_AVL_100HZ_VAL, },
> +			},
> +		},
> +		.pw = {
> +			.addr = ST_MAGN_4_PW_ADDR,
> +			.mask = ST_MAGN_4_PW_MASK,
> +			.value_on = ST_MAGN_4_PW_ON,
> +			.value_off = ST_MAGN_4_PW_OFF,
> +		},
> +		.fs = {
> +			.addr = ST_MAGN_4_FS_ADDR,
> +			.mask = ST_MAGN_4_FS_MASK,
> +			.fs_avl = {
> +				[0] = {
> +					.num = ST_MAGN_FS_AVL_2000MG,
> +					.value = ST_MAGN_4_FS_AVL_2000_VAL,
> +					.gain = ST_MAGN_4_FS_AVL_2000_GAIN,
> +				},
> +				[1] = {
> +					.num = ST_MAGN_FS_AVL_4000MG,
> +					.value = ST_MAGN_4_FS_AVL_4000_VAL,
> +					.gain = ST_MAGN_4_FS_AVL_4000_GAIN,
> +				},
> +				[2] = {
> +					.num = ST_MAGN_FS_AVL_8000MG,
> +					.value = ST_MAGN_4_FS_AVL_8000_VAL,
> +					.gain = ST_MAGN_4_FS_AVL_8000_GAIN,
> +				},
> +				[3] = {
> +					.num = ST_MAGN_FS_AVL_12000MG,
> +					.value = ST_MAGN_4_FS_AVL_12000_VAL,
> +					.gain = ST_MAGN_4_FS_AVL_12000_GAIN,
> +				},
> +			},
> +		},
> +		.bdu = {
> +			.addr = ST_MAGN_4_BDU_ADDR,
> +			.mask = ST_MAGN_4_BDU_MASK,
> +		},
> +		.drdy_irq = {
> +			.addr = ST_MAGN_4_DRDY_IRQ_ADDR,
> +			.mask_int1 = ST_MAGN_4_DRDY_INT_MASK,
> +		},
> +		.multi_read_bit = ST_MAGN_4_MULTIREAD_BIT,
> +		.bootime = 2,
> +	},
>  };
>  
>  static int st_magn_read_raw(struct iio_dev *indio_dev,
> diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c
> index 8aa37af..1c7c487 100644
> --- a/drivers/iio/magnetometer/st_magn_i2c.c
> +++ b/drivers/iio/magnetometer/st_magn_i2c.c
> @@ -40,6 +40,10 @@ static const struct of_device_id st_magn_of_match[] = {
>  		.compatible = "st,lsm303agr-magn",
>  		.data = LSM303AGR_MAGN_DEV_NAME,
>  	},
> +	{
> +		.compatible = "st,lsm9ds0-magn",
> +		.data = LSM9DS0_MAGN_DEV_NAME,
> +	},
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, st_magn_of_match);
> @@ -84,6 +88,7 @@ static const struct i2c_device_id st_magn_id_table[] = {
>  	{ LSM303DLM_MAGN_DEV_NAME },
>  	{ LIS3MDL_MAGN_DEV_NAME },
>  	{ LSM303AGR_MAGN_DEV_NAME },
> +	{ LSM9DS0_MAGN_DEV_NAME },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(i2c, st_magn_id_table);
> diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c
> index 6325e7d..8c4e1d6 100644
> --- a/drivers/iio/magnetometer/st_magn_spi.c
> +++ b/drivers/iio/magnetometer/st_magn_spi.c
> @@ -52,6 +52,7 @@ static const struct spi_device_id st_magn_id_table[] = {
>  	{ LSM303DLM_MAGN_DEV_NAME },
>  	{ LIS3MDL_MAGN_DEV_NAME },
>  	{ LSM303AGR_MAGN_DEV_NAME },
> +	{ LSM9DS0_MAGN_DEV_NAME },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(spi, st_magn_id_table);
> 

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

* Re: [RFC] iio: st: Add lsm9ds0 support for gyro accel and magn
  2016-04-17 11:44 ` Jonathan Cameron
@ 2016-04-17 12:25   ` Wolfram Sang
  2016-04-17 14:21   ` Peter Rosin
  2016-04-18  6:07   ` [RFC] iio: st: Add lsm9ds0 support for gyro accel and magny Denis Ciocca
  2 siblings, 0 replies; 11+ messages in thread
From: Wolfram Sang @ 2016-04-17 12:25 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Crestez Dan Leonard, linux-iio, Giuseppe Barba, Denis Ciocca,
	linux-kernel, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Daniel Baluta, Peter Rosin

[-- Attachment #1: Type: text/plain, Size: 317 bytes --]


> To bring you two up to date, we have effectively two separate devices
> (very nearly) sat behind a single i2c address.  They have non overlapping
> register maps.

I think the MFD subsystem should have a few multifunction I2C devices
handled already. You migh get ideas there. Never needed it myself yet,
though.


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [RFC] iio: st: Add lsm9ds0 support for gyro accel and magn
  2016-04-17 11:44 ` Jonathan Cameron
  2016-04-17 12:25   ` Wolfram Sang
@ 2016-04-17 14:21   ` Peter Rosin
  2016-04-18  6:07   ` [RFC] iio: st: Add lsm9ds0 support for gyro accel and magny Denis Ciocca
  2 siblings, 0 replies; 11+ messages in thread
From: Peter Rosin @ 2016-04-17 14:21 UTC (permalink / raw)
  To: Jonathan Cameron, Crestez Dan Leonard, linux-iio, Giuseppe Barba,
	Denis Ciocca
  Cc: linux-kernel, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Daniel Baluta, Wolfram Sang



On 2016-04-17 13:44, Jonathan Cameron wrote:
> On 13/04/16 20:01, Crestez Dan Leonard wrote:
>> Device is an integrated gyro/accel/magn and temperature sensor. The
>> device has two i2c/spi interfaces: one for the gyro and one for the
>> accel/magn/temp sensor.
>>
>> Datasheet: http://www2.st.com/resource/en/datasheet/lsm9ds0.pdf
>>
>> The patch uses existing iio st_sensor infrastructure and just adds a
>> bunch of new device IDs and the new register mappings.
>>
>> Temperature support is not included.
>>
>> Signed-off-by: Crestez Dan Leonard <leonard.crestez@intel.com>
> This looks fine to me.  Needs acks from Denis though.
> Also, clearly your questions need addressing.
>> ---
>>
>> I tested basic reading of values using software triggers and i2c and the values
>> seems plausible.
>>
>> I tested lsm9ds0-accel and lsm9ds0-magn separately because I don't know how to
>> instantiate two iio drivers for the same I2C device using devicetree. Can you
>> provide a sample of this or is this not currently supported?
>>
>> It seems to me that the LSM303AGR device has the same problem: it's an
>> accel+magn combo behind a single I2C address. How is that supposed to be
>> instantiated? Other supported combo devices seem to have multiple I2C
>> addresses.
> Excellent question. I'd not picked up on this before.
> It could be done with a 'dummy mux' I guess though that's messy.
> Guiseppe how are you doing it for the lsm303agr?
> 
> Cc'd Peter Rosin who has kindly walked into maintainer I2C mux
> support recently ;) An Wolfram for obvious reasons..
> To bring you two up to date, we have effectively two separate devices
> (very nearly) sat behind a single i2c address.  They have non overlapping
> register maps.
> We have a big overarching st_sensors driver framework which contains numerous
> examples of parts with just a magnetometer or just an accelerometer but in this
> case they have combined these two.  It would be nice to reuse the infrastructure
> without having to have a separate version for the two cases that exist so far. 
> I suppose such a separate handling wouldn't be too terrible if we have to do it
> though - just a new device implementation of magnaccel for the st-sensors.

My knee-jerk was also mfd, just like Wolfram already said, but I do not know
if mfd covers sub-devices with the same i2c address?

The reason I also answered is to say that adding a dummy i2c-mux to the
device tree just so that you can instantiate two drivers for one device
is (ab)using the dt to describe the software, where its purpose is to
describe hw. I think that is frown upon by the dt crowd?

Cheers,
Peter

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

* Re: [RFC] iio: st: Add lsm9ds0 support for gyro accel and magny
  2016-04-17 11:44 ` Jonathan Cameron
  2016-04-17 12:25   ` Wolfram Sang
  2016-04-17 14:21   ` Peter Rosin
@ 2016-04-18  6:07   ` Denis Ciocca
  2016-04-18 10:25     ` Crestez Dan Leonard
  2 siblings, 1 reply; 11+ messages in thread
From: Denis Ciocca @ 2016-04-18  6:07 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Crestez Dan Leonard, linux-iio, Giuseppe BARBA, linux-kernel,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Daniel Baluta, Peter Rosin, Wolfram Sang

Hi Leonard and Jonathan,

basically the patch can not work.
Current ST infrastructure needs to use one i2c slave per driver (accel or magn or gyro).
All sensors currently supported (including lsm303agr) have one i2c address per sensor type (for example in lsm303agr, accel has one i2c address, magn has another one).

What you are doing now it is not possible with current implementation. You can't have two drivers that manage one singol i2c device.
A possible solution is to use MDF device that let IIO drivers probe, the only driver that really manage i2c is MDF (check HID implementation), But I'm not sure it is ok because in combo device (two sensors sharing same i2c address) maybe you have some constrains you should verify (for example one odr is related to the other one, ...), you can't basically try to use those as totally separated.

I've started months ago to modify ST infrastructure in order to manage combo device but so far it is still work in progess...


BR,
Denis


On |17 Apr 16 @ 13:44|, Jonathan Cameron wrote:
> On 13/04/16 20:01, Crestez Dan Leonard wrote:
> > Device is an integrated gyro/accel/magn and temperature sensor. The
> > device has two i2c/spi interfaces: one for the gyro and one for the
> > accel/magn/temp sensor.
> >
> > Datasheet: http://www2.st.com/resource/en/datasheet/lsm9ds0.pdf
> >
> > The patch uses existing iio st_sensor infrastructure and just adds a
> > bunch of new device IDs and the new register mappings.
> >
> > Temperature support is not included.
> >
> > Signed-off-by: Crestez Dan Leonard <leonard.crestez@intel.com>
> This looks fine to me.  Needs acks from Denis though.
> Also, clearly your questions need addressing.
> > ---
> >
> > I tested basic reading of values using software triggers and i2c and the values
> > seems plausible.
> >
> > I tested lsm9ds0-accel and lsm9ds0-magn separately because I don't know how to
> > instantiate two iio drivers for the same I2C device using devicetree. Can you
> > provide a sample of this or is this not currently supported?
> >
> > It seems to me that the LSM303AGR device has the same problem: it's an
> > accel+magn combo behind a single I2C address. How is that supposed to be
> > instantiated? Other supported combo devices seem to have multiple I2C
> > addresses.
> Excellent question. I'd not picked up on this before.
> It could be done with a 'dummy mux' I guess though that's messy.
> Guiseppe how are you doing it for the lsm303agr?
> 
> Cc'd Peter Rosin who has kindly walked into maintainer I2C mux
> support recently ;) An Wolfram for obvious reasons..
> To bring you two up to date, we have effectively two separate devices
> (very nearly) sat behind a single i2c address.  They have non overlapping
> register maps.
> We have a big overarching st_sensors driver framework which contains numerous
> examples of parts with just a magnetometer or just an accelerometer but in this
> case they have combined these two.  It would be nice to reuse the infrastructure
> without having to have a separate version for the two cases that exist so far.
> I suppose such a separate handling wouldn't be too terrible if we have to do it
> though - just a new device implementation of magnaccel for the st-sensors.
> >
> > It's also not clear how to properly deal with bits shared between the accel and
> > magn part like "block data update" or "interrupt polarity".
> 
> Perhaps just document that it's not allowed to have different choices for them
> in the bindings?
> Jonathan
> >
> >  .../devicetree/bindings/iio/st-sensors.txt         |   3 +
> >  drivers/iio/accel/st_accel.h                       |   1 +
> >  drivers/iio/accel/st_accel_core.c                  | 122 ++++++++++++++++++++
> >  drivers/iio/accel/st_accel_i2c.c                   |   5 +
> >  drivers/iio/accel/st_accel_spi.c                   |   1 +
> >  drivers/iio/gyro/st_gyro.h                         |   1 +
> >  drivers/iio/gyro/st_gyro_core.c                    |   1 +
> >  drivers/iio/gyro/st_gyro_i2c.c                     |   5 +
> >  drivers/iio/gyro/st_gyro_spi.c                     |   1 +
> >  drivers/iio/magnetometer/st_magn.h                 |   1 +
> >  drivers/iio/magnetometer/st_magn_core.c            | 123 +++++++++++++++++++++
> >  drivers/iio/magnetometer/st_magn_i2c.c             |   5 +
> >  drivers/iio/magnetometer/st_magn_spi.c             |   1 +
> >  13 files changed, 270 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/iio/st-sensors.txt b/Documentation/devicetree/bindings/iio/st-sensors.txt
> > index 71b7bdf..65339ef 100644
> > --- a/Documentation/devicetree/bindings/iio/st-sensors.txt
> > +++ b/Documentation/devicetree/bindings/iio/st-sensors.txt
> > @@ -38,6 +38,7 @@ Accelerometers:
> >  - st,lsm303agr-accel
> >  - st,lis2dh12-accel
> >  - st,h3lis331dl-accel
> > +- st,lsm9ds0-accel
> >
> >  Gyroscopes:
> >  - st,l3g4200d-gyro
> > @@ -47,6 +48,7 @@ Gyroscopes:
> >  - st,l3gd20-gyro
> >  - st,l3g4is-gyro
> >  - st,lsm330-gyro
> > +- st,lsm9ds0-gyro
> >
> >  Magnetometers:
> >  - st,lsm303agr-magn
> > @@ -54,6 +56,7 @@ Magnetometers:
> >  - st,lsm303dlhc-magn
> >  - st,lsm303dlm-magn
> >  - st,lis3mdl-magn
> > +- st,lsm9ds0-magn
> >
> >  Pressure sensors:
> >  - st,lps001wp-press
> > diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h
> > index 57f83a6..e90cd6a 100644
> > --- a/drivers/iio/accel/st_accel.h
> > +++ b/drivers/iio/accel/st_accel.h
> > @@ -29,6 +29,7 @@
> >  #define LSM330_ACCEL_DEV_NAME                "lsm330_accel"
> >  #define LSM303AGR_ACCEL_DEV_NAME     "lsm303agr_accel"
> >  #define LIS2DH12_ACCEL_DEV_NAME              "lis2dh12_accel"
> > +#define LSM9DS0_ACCEL_DEV_NAME               "lsm9ds0_accel"
> >
> >  /**
> >  * struct st_sensors_platform_data - default accel platform data
> > diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
> > index fee32e3..0941b46 100644
> > --- a/drivers/iio/accel/st_accel_core.c
> > +++ b/drivers/iio/accel/st_accel_core.c
> > @@ -211,6 +211,50 @@
> >  #define ST_ACCEL_6_IHL_IRQ_MASK                      0x80
> >  #define ST_ACCEL_6_MULTIREAD_BIT             true
> >
> > +/* CUSTOM VALUES FOR SENSOR 7 */
> > +#define ST_ACCEL_7_WAI_EXP                   0x49
> > +#define ST_ACCEL_7_ODR_ADDR                  0x20
> > +#define ST_ACCEL_7_ODR_MASK                  0xf0
> > +#define ST_ACCEL_7_ODR_AVL_3HZ_VAL           0x01
> > +#define ST_ACCEL_7_ODR_AVL_6HZ_VAL           0x02
> > +#define ST_ACCEL_7_ODR_AVL_12HZ_VAL          0x03
> > +#define ST_ACCEL_7_ODR_AVL_25HZ_VAL          0x04
> > +#define ST_ACCEL_7_ODR_AVL_50HZ_VAL          0x05
> > +#define ST_ACCEL_7_ODR_AVL_100HZ_VAL         0x06
> > +#define ST_ACCEL_7_ODR_AVL_200HZ_VAL         0x07
> > +#define ST_ACCEL_7_ODR_AVL_400HZ_VAL         0x08
> > +#define ST_ACCEL_7_ODR_AVL_800HZ_VAL         0x09
> > +#define ST_ACCEL_7_ODR_AVL_1600HZ_VAL                0x0a
> > +#define ST_ACCEL_7_FS_ADDR                   0x21
> > +#define ST_ACCEL_7_FS_MASK                   0x38
> > +#define ST_ACCEL_7_FS_AVL_2_VAL                      0x00
> > +#define ST_ACCEL_7_FS_AVL_4_VAL                      0x01
> > +#define ST_ACCEL_7_FS_AVL_6_VAL                      0x02
> > +#define ST_ACCEL_7_FS_AVL_8_VAL                      0x03
> > +#define ST_ACCEL_7_FS_AVL_16_VAL             0x04
> > +#define ST_ACCEL_7_FS_AVL_2_GAIN             IIO_G_TO_M_S_2(61)
> > +#define ST_ACCEL_7_FS_AVL_4_GAIN             IIO_G_TO_M_S_2(122)
> > +#define ST_ACCEL_7_FS_AVL_6_GAIN             IIO_G_TO_M_S_2(183)
> > +#define ST_ACCEL_7_FS_AVL_8_GAIN             IIO_G_TO_M_S_2(244)
> > +#define ST_ACCEL_7_FS_AVL_16_GAIN            IIO_G_TO_M_S_2(732)
> > +#define ST_ACCEL_7_BDU_ADDR                  0x20
> > +#define ST_ACCEL_7_BDU_MASK                  0x08
> > +#define ST_ACCEL_7_DRDY_IRQ_ADDR             0x22
> > +#define ST_ACCEL_7_DRDY_IRQ_INT1_MASK                0x04
> > +/* INT2 is actually at another address. Not supported by driver */
> > +/*
> > +#define ST_ACCEL_7_DRDY_IRQ_INT2_ADDR                0x23
> > +#define ST_ACCEL_7_DRDY_IRQ_INT2_MASK                0x08
> > + */
> > +/* Common to magnetometer so not supported */
> > +/*
> > +#define ST_ACCEL_7_IHL_IRQ_ADDR                      0x12
> > +#define ST_ACCEL_7_IHL_IRQ_MASK                      0x80
> > + */
> > +#define ST_ACCEL_7_IG1_EN_ADDR                       0x22
> > +#define ST_ACCEL_7_IG1_EN_MASK                       0x20
> > +#define ST_ACCEL_7_MULTIREAD_BIT             true
> > +
> >  static const struct iio_chan_spec st_accel_8bit_channels[] = {
> >       ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
> >                       BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> > @@ -649,6 +693,84 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
> >               .multi_read_bit = ST_ACCEL_6_MULTIREAD_BIT,
> >               .bootime = 2,
> >       },
> > +     {
> > +             .wai = ST_ACCEL_7_WAI_EXP,
> > +             .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
> > +             .sensors_supported = {
> > +                     [0] = LSM9DS0_ACCEL_DEV_NAME,
> > +             },
> > +             .ch = (struct iio_chan_spec *)st_accel_16bit_channels,
> > +             .odr = {
> > +                     .addr = ST_ACCEL_7_ODR_ADDR,
> > +                     .mask = ST_ACCEL_7_ODR_MASK,
> > +                     .odr_avl = {
> > +                             { 3, ST_ACCEL_7_ODR_AVL_3HZ_VAL },
> > +                             { 6, ST_ACCEL_7_ODR_AVL_6HZ_VAL, },
> > +                             { 12, ST_ACCEL_7_ODR_AVL_12HZ_VAL, },
> > +                             { 25, ST_ACCEL_7_ODR_AVL_25HZ_VAL, },
> > +                             { 50, ST_ACCEL_7_ODR_AVL_50HZ_VAL, },
> > +                             { 100, ST_ACCEL_7_ODR_AVL_100HZ_VAL, },
> > +                             { 200, ST_ACCEL_7_ODR_AVL_200HZ_VAL, },
> > +                             { 400, ST_ACCEL_7_ODR_AVL_400HZ_VAL, },
> > +                             { 800, ST_ACCEL_7_ODR_AVL_800HZ_VAL, },
> > +                             { 1600, ST_ACCEL_7_ODR_AVL_1600HZ_VAL, },
> > +                     },
> > +             },
> > +             .pw = {
> > +                     .addr = ST_ACCEL_7_ODR_ADDR,
> > +                     .mask = ST_ACCEL_7_ODR_MASK,
> > +                     .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
> > +             },
> > +             .enable_axis = {
> > +                     .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
> > +                     .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
> > +             },
> > +             .fs = {
> > +                     .addr = ST_ACCEL_7_FS_ADDR,
> > +                     .mask = ST_ACCEL_7_FS_MASK,
> > +                     .fs_avl = {
> > +                             [0] = {
> > +                                     .num = ST_ACCEL_FS_AVL_2G,
> > +                                     .value = ST_ACCEL_7_FS_AVL_2_VAL,
> > +                                     .gain = ST_ACCEL_7_FS_AVL_2_GAIN,
> > +                             },
> > +                             [1] = {
> > +                                     .num = ST_ACCEL_FS_AVL_4G,
> > +                                     .value = ST_ACCEL_7_FS_AVL_4_VAL,
> > +                                     .gain = ST_ACCEL_7_FS_AVL_4_GAIN,
> > +                             },
> > +                             [2] = {
> > +                                     .num = ST_ACCEL_FS_AVL_6G,
> > +                                     .value = ST_ACCEL_7_FS_AVL_6_VAL,
> > +                                     .gain = ST_ACCEL_7_FS_AVL_6_GAIN,
> > +                             },
> > +                             [3] = {
> > +                                     .num = ST_ACCEL_FS_AVL_8G,
> > +                                     .value = ST_ACCEL_7_FS_AVL_8_VAL,
> > +                                     .gain = ST_ACCEL_7_FS_AVL_8_GAIN,
> > +                             },
> > +                             [4] = {
> > +                                     .num = ST_ACCEL_FS_AVL_16G,
> > +                                     .value = ST_ACCEL_7_FS_AVL_16_VAL,
> > +                                     .gain = ST_ACCEL_7_FS_AVL_16_GAIN,
> > +                             },
> > +                     },
> > +             },
> > +             .bdu = {
> > +                     .addr = ST_ACCEL_7_BDU_ADDR,
> > +                     .mask = ST_ACCEL_7_BDU_MASK,
> > +             },
> > +             .drdy_irq = {
> > +                     .addr = ST_ACCEL_7_DRDY_IRQ_ADDR,
> > +                     .mask_int1 = ST_ACCEL_7_DRDY_IRQ_INT1_MASK,
> > +                     .ig1 = {
> > +                             .en_addr = ST_ACCEL_7_IG1_EN_ADDR,
> > +                             .en_mask = ST_ACCEL_7_IG1_EN_MASK,
> > +                     },
> > +             },
> > +             .multi_read_bit = ST_ACCEL_7_MULTIREAD_BIT,
> > +             .bootime = 2,
> > +     },
> >  };
> >
> >  static int st_accel_read_raw(struct iio_dev *indio_dev,
> > diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c
> > index 7333ee9..7a2a3ab 100644
> > --- a/drivers/iio/accel/st_accel_i2c.c
> > +++ b/drivers/iio/accel/st_accel_i2c.c
> > @@ -80,6 +80,10 @@ static const struct of_device_id st_accel_of_match[] = {
> >               .compatible = "st,h3lis331dl-accel",
> >               .data = H3LIS331DL_DRIVER_NAME,
> >       },
> > +     {
> > +             .compatible = "st,lsm9ds0-accel",
> > +             .data = LSM9DS0_ACCEL_DEV_NAME,
> > +     },
> >       {},
> >  };
> >  MODULE_DEVICE_TABLE(of, st_accel_of_match);
> > @@ -130,6 +134,7 @@ static const struct i2c_device_id st_accel_id_table[] = {
> >       { LSM330_ACCEL_DEV_NAME },
> >       { LSM303AGR_ACCEL_DEV_NAME },
> >       { LIS2DH12_ACCEL_DEV_NAME },
> > +     { LSM9DS0_ACCEL_DEV_NAME },
> >       {},
> >  };
> >  MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
> > diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c
> > index fcd5847..2fc32c92f 100644
> > --- a/drivers/iio/accel/st_accel_spi.c
> > +++ b/drivers/iio/accel/st_accel_spi.c
> > @@ -59,6 +59,7 @@ static const struct spi_device_id st_accel_id_table[] = {
> >       { LSM330_ACCEL_DEV_NAME },
> >       { LSM303AGR_ACCEL_DEV_NAME },
> >       { LIS2DH12_ACCEL_DEV_NAME },
> > +     { LSM9DS0_ACCEL_DEV_NAME },
> >       {},
> >  };
> >  MODULE_DEVICE_TABLE(spi, st_accel_id_table);
> > diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h
> > index 5353d63..a5c5c4e 100644
> > --- a/drivers/iio/gyro/st_gyro.h
> > +++ b/drivers/iio/gyro/st_gyro.h
> > @@ -21,6 +21,7 @@
> >  #define L3GD20_GYRO_DEV_NAME         "l3gd20"
> >  #define L3G4IS_GYRO_DEV_NAME         "l3g4is_ui"
> >  #define LSM330_GYRO_DEV_NAME         "lsm330_gyro"
> > +#define LSM9DS0_GYRO_DEV_NAME                "lsm9ds0_gyro"
> >
> >  /**
> >   * struct st_sensors_platform_data - gyro platform data
> > diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
> > index 110f95b..9589ba9 100644
> > --- a/drivers/iio/gyro/st_gyro_core.c
> > +++ b/drivers/iio/gyro/st_gyro_core.c
> > @@ -203,6 +203,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
> >                       [2] = LSM330DLC_GYRO_DEV_NAME,
> >                       [3] = L3G4IS_GYRO_DEV_NAME,
> >                       [4] = LSM330_GYRO_DEV_NAME,
> > +                     [5] = LSM9DS0_GYRO_DEV_NAME,
> >               },
> >               .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
> >               .odr = {
> > diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c
> > index 6848451..40056b8 100644
> > --- a/drivers/iio/gyro/st_gyro_i2c.c
> > +++ b/drivers/iio/gyro/st_gyro_i2c.c
> > @@ -48,6 +48,10 @@ static const struct of_device_id st_gyro_of_match[] = {
> >               .compatible = "st,lsm330-gyro",
> >               .data = LSM330_GYRO_DEV_NAME,
> >       },
> > +     {
> > +             .compatible = "st,lsm9ds0-gyro",
> > +             .data = LSM9DS0_GYRO_DEV_NAME,
> > +     },
> >       {},
> >  };
> >  MODULE_DEVICE_TABLE(of, st_gyro_of_match);
> > @@ -93,6 +97,7 @@ static const struct i2c_device_id st_gyro_id_table[] = {
> >       { L3GD20_GYRO_DEV_NAME },
> >       { L3G4IS_GYRO_DEV_NAME },
> >       { LSM330_GYRO_DEV_NAME },
> > +     { LSM9DS0_GYRO_DEV_NAME },
> >       {},
> >  };
> >  MODULE_DEVICE_TABLE(i2c, st_gyro_id_table);
> > diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c
> > index d2b7a5f..fbf2fae 100644
> > --- a/drivers/iio/gyro/st_gyro_spi.c
> > +++ b/drivers/iio/gyro/st_gyro_spi.c
> > @@ -54,6 +54,7 @@ static const struct spi_device_id st_gyro_id_table[] = {
> >       { L3GD20_GYRO_DEV_NAME },
> >       { L3G4IS_GYRO_DEV_NAME },
> >       { LSM330_GYRO_DEV_NAME },
> > +     { LSM9DS0_GYRO_DEV_NAME },
> >       {},
> >  };
> >  MODULE_DEVICE_TABLE(spi, st_gyro_id_table);
> > diff --git a/drivers/iio/magnetometer/st_magn.h b/drivers/iio/magnetometer/st_magn.h
> > index 06a4d9c..2176064 100644
> > --- a/drivers/iio/magnetometer/st_magn.h
> > +++ b/drivers/iio/magnetometer/st_magn.h
> > @@ -19,6 +19,7 @@
> >  #define LSM303DLM_MAGN_DEV_NAME              "lsm303dlm_magn"
> >  #define LIS3MDL_MAGN_DEV_NAME                "lis3mdl"
> >  #define LSM303AGR_MAGN_DEV_NAME              "lsm303agr_magn"
> > +#define LSM9DS0_MAGN_DEV_NAME                "lsm9ds0_magn"
> >
> >  int st_magn_common_probe(struct iio_dev *indio_dev);
> >  void st_magn_common_remove(struct iio_dev *indio_dev);
> > diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
> > index 501f858..da3f29a 100644
> > --- a/drivers/iio/magnetometer/st_magn_core.c
> > +++ b/drivers/iio/magnetometer/st_magn_core.c
> > @@ -36,6 +36,7 @@
> >  /* FULLSCALE */
> >  #define ST_MAGN_FS_AVL_1300MG                        1300
> >  #define ST_MAGN_FS_AVL_1900MG                        1900
> > +#define ST_MAGN_FS_AVL_2000MG                        2000
> >  #define ST_MAGN_FS_AVL_2500MG                        2500
> >  #define ST_MAGN_FS_AVL_4000MG                        4000
> >  #define ST_MAGN_FS_AVL_4700MG                        4700
> > @@ -183,6 +184,50 @@
> >  #define ST_MAGN_3_OUT_Y_L_ADDR                       0x6a
> >  #define ST_MAGN_3_OUT_Z_L_ADDR                       0x6c
> >
> > +/* CUSTOM VALUES FOR SENSOR 4 */
> > +#define ST_MAGN_4_WAI_EXP                    0x49
> > +#define ST_MAGN_4_ODR_ADDR                   0x24
> > +#define ST_MAGN_4_ODR_MASK                   0x1c
> > +#define ST_MAGN_4_ODR_AVL_3HZ_VAL            0x00
> > +#define ST_MAGN_4_ODR_AVL_6HZ_VAL            0x01
> > +#define ST_MAGN_4_ODR_AVL_12HZ_VAL           0x02
> > +#define ST_MAGN_4_ODR_AVL_25HZ_VAL           0x03
> > +#define ST_MAGN_4_ODR_AVL_50HZ_VAL           0x04
> > +#define ST_MAGN_4_ODR_AVL_100HZ_VAL          0x05
> > +#define ST_MAGN_4_PW_ADDR                    0x26
> > +#define ST_MAGN_4_PW_MASK                    0x03
> > +#define ST_MAGN_4_PW_ON                              0x00
> > +#define ST_MAGN_4_PW_OFF                     0x03
> > +#define ST_MAGN_4_FS_ADDR                    0x25
> > +#define ST_MAGN_4_FS_MASK                    0x60
> > +#define ST_MAGN_4_FS_AVL_2000_VAL            0x00
> > +#define ST_MAGN_4_FS_AVL_4000_VAL            0x01
> > +#define ST_MAGN_4_FS_AVL_8000_VAL            0x02
> > +#define ST_MAGN_4_FS_AVL_12000_VAL           0x03
> > +#define ST_MAGN_4_FS_AVL_2000_GAIN           73
> > +#define ST_MAGN_4_FS_AVL_4000_GAIN           146
> > +#define ST_MAGN_4_FS_AVL_8000_GAIN           292
> > +#define ST_MAGN_4_FS_AVL_12000_GAIN          438
> > +/* Shared with accelerometer */
> > +#define ST_MAGN_4_BDU_ADDR                   0x20
> > +#define ST_MAGN_4_BDU_MASK                   0x08
> > +#define ST_MAGN_4_DRDY_IRQ_ADDR                      0x22
> > +#define ST_MAGN_4_DRDY_INT_MASK                      0x01
> > +/* INT2 is actually at another address. Not supported by driver */
> > +/*
> > +#define ST_MAGN_4_DRDY_IRQ_INT2_ADDR         0x23
> > +#define ST_MAGN_4_DRDY_IRQ_INT2_MASK         0x04
> > + */
> > +/* Common to accelerometer so not supported */
> > +/*
> > +#define ST_MAGN_4_IHL_IRQ_ADDR                       0x12
> > +#define ST_MAGN_4_IHL_IRQ_MASK                       0x80
> > + */
> > +#define ST_MAGN_4_MULTIREAD_BIT                      true
> > +#define ST_MAGN_4_OUT_X_L_ADDR                       0x08
> > +#define ST_MAGN_4_OUT_Y_L_ADDR                       0x0a
> > +#define ST_MAGN_4_OUT_Z_L_ADDR                       0x0c
> > +
> >  static const struct iio_chan_spec st_magn_16bit_channels[] = {
> >       ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
> >                       BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> > @@ -231,6 +276,22 @@ static const struct iio_chan_spec st_magn_3_16bit_channels[] = {
> >       IIO_CHAN_SOFT_TIMESTAMP(3)
> >  };
> >
> > +static const struct iio_chan_spec st_magn_4_16bit_channels[] = {
> > +     ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
> > +                     BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> > +                     ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
> > +                     ST_MAGN_4_OUT_X_L_ADDR),
> > +     ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
> > +                     BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> > +                     ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
> > +                     ST_MAGN_4_OUT_Y_L_ADDR),
> > +     ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
> > +                     BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> > +                     ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
> > +                     ST_MAGN_4_OUT_Z_L_ADDR),
> > +     IIO_CHAN_SOFT_TIMESTAMP(3)
> > +};
> > +
> >  static const struct st_sensor_settings st_magn_sensors_settings[] = {
> >       {
> >               .wai = 0, /* This sensor has no valid WhoAmI report 0 */
> > @@ -488,6 +549,68 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
> >               .multi_read_bit = ST_MAGN_3_MULTIREAD_BIT,
> >               .bootime = 2,
> >       },
> > +     {
> > +             .wai = ST_MAGN_4_WAI_EXP,
> > +             .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
> > +             .sensors_supported = {
> > +                     [0] = LSM9DS0_MAGN_DEV_NAME,
> > +             },
> > +             .ch = (struct iio_chan_spec *)st_magn_4_16bit_channels,
> > +             .odr = {
> > +                     .addr = ST_MAGN_4_ODR_ADDR,
> > +                     .mask = ST_MAGN_4_ODR_MASK,
> > +                     .odr_avl = {
> > +                             { 3, ST_MAGN_4_ODR_AVL_3HZ_VAL, },
> > +                             { 6, ST_MAGN_4_ODR_AVL_6HZ_VAL, },
> > +                             { 12, ST_MAGN_4_ODR_AVL_12HZ_VAL, },
> > +                             { 25, ST_MAGN_4_ODR_AVL_25HZ_VAL, },
> > +                             { 50, ST_MAGN_4_ODR_AVL_50HZ_VAL, },
> > +                             { 100, ST_MAGN_4_ODR_AVL_100HZ_VAL, },
> > +                     },
> > +             },
> > +             .pw = {
> > +                     .addr = ST_MAGN_4_PW_ADDR,
> > +                     .mask = ST_MAGN_4_PW_MASK,
> > +                     .value_on = ST_MAGN_4_PW_ON,
> > +                     .value_off = ST_MAGN_4_PW_OFF,
> > +             },
> > +             .fs = {
> > +                     .addr = ST_MAGN_4_FS_ADDR,
> > +                     .mask = ST_MAGN_4_FS_MASK,
> > +                     .fs_avl = {
> > +                             [0] = {
> > +                                     .num = ST_MAGN_FS_AVL_2000MG,
> > +                                     .value = ST_MAGN_4_FS_AVL_2000_VAL,
> > +                                     .gain = ST_MAGN_4_FS_AVL_2000_GAIN,
> > +                             },
> > +                             [1] = {
> > +                                     .num = ST_MAGN_FS_AVL_4000MG,
> > +                                     .value = ST_MAGN_4_FS_AVL_4000_VAL,
> > +                                     .gain = ST_MAGN_4_FS_AVL_4000_GAIN,
> > +                             },
> > +                             [2] = {
> > +                                     .num = ST_MAGN_FS_AVL_8000MG,
> > +                                     .value = ST_MAGN_4_FS_AVL_8000_VAL,
> > +                                     .gain = ST_MAGN_4_FS_AVL_8000_GAIN,
> > +                             },
> > +                             [3] = {
> > +                                     .num = ST_MAGN_FS_AVL_12000MG,
> > +                                     .value = ST_MAGN_4_FS_AVL_12000_VAL,
> > +                                     .gain = ST_MAGN_4_FS_AVL_12000_GAIN,
> > +                             },
> > +                     },
> > +             },
> > +             .bdu = {
> > +                     .addr = ST_MAGN_4_BDU_ADDR,
> > +                     .mask = ST_MAGN_4_BDU_MASK,
> > +             },
> > +             .drdy_irq = {
> > +                     .addr = ST_MAGN_4_DRDY_IRQ_ADDR,
> > +                     .mask_int1 = ST_MAGN_4_DRDY_INT_MASK,
> > +             },
> > +             .multi_read_bit = ST_MAGN_4_MULTIREAD_BIT,
> > +             .bootime = 2,
> > +     },
> >  };
> >
> >  static int st_magn_read_raw(struct iio_dev *indio_dev,
> > diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c
> > index 8aa37af..1c7c487 100644
> > --- a/drivers/iio/magnetometer/st_magn_i2c.c
> > +++ b/drivers/iio/magnetometer/st_magn_i2c.c
> > @@ -40,6 +40,10 @@ static const struct of_device_id st_magn_of_match[] = {
> >               .compatible = "st,lsm303agr-magn",
> >               .data = LSM303AGR_MAGN_DEV_NAME,
> >       },
> > +     {
> > +             .compatible = "st,lsm9ds0-magn",
> > +             .data = LSM9DS0_MAGN_DEV_NAME,
> > +     },
> >       {},
> >  };
> >  MODULE_DEVICE_TABLE(of, st_magn_of_match);
> > @@ -84,6 +88,7 @@ static const struct i2c_device_id st_magn_id_table[] = {
> >       { LSM303DLM_MAGN_DEV_NAME },
> >       { LIS3MDL_MAGN_DEV_NAME },
> >       { LSM303AGR_MAGN_DEV_NAME },
> > +     { LSM9DS0_MAGN_DEV_NAME },
> >       {},
> >  };
> >  MODULE_DEVICE_TABLE(i2c, st_magn_id_table);
> > diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c
> > index 6325e7d..8c4e1d6 100644
> > --- a/drivers/iio/magnetometer/st_magn_spi.c
> > +++ b/drivers/iio/magnetometer/st_magn_spi.c
> > @@ -52,6 +52,7 @@ static const struct spi_device_id st_magn_id_table[] = {
> >       { LSM303DLM_MAGN_DEV_NAME },
> >       { LIS3MDL_MAGN_DEV_NAME },
> >       { LSM303AGR_MAGN_DEV_NAME },
> > +     { LSM9DS0_MAGN_DEV_NAME },
> >       {},
> >  };
> >  MODULE_DEVICE_TABLE(spi, st_magn_id_table);
> >
> 

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

* Re: [RFC] iio: st: Add lsm9ds0 support for gyro accel and magny
  2016-04-18  6:07   ` [RFC] iio: st: Add lsm9ds0 support for gyro accel and magny Denis Ciocca
@ 2016-04-18 10:25     ` Crestez Dan Leonard
  2016-04-18 19:51       ` Jonathan Cameron
  0 siblings, 1 reply; 11+ messages in thread
From: Crestez Dan Leonard @ 2016-04-18 10:25 UTC (permalink / raw)
  To: Denis Ciocca, Jonathan Cameron
  Cc: linux-iio, Giuseppe BARBA, linux-kernel, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Daniel Baluta,
	Peter Rosin, Wolfram Sang

On 04/18/2016 09:07 AM, Denis Ciocca wrote:
> Hi Leonard and Jonathan,
>
> basically the patch can not work.
Well, it can work as long as you don't initialize both the accel and the
magn at the same time. There is no issue with the gyro driver. Would it
be OK if I resend this as a [PATCH] intended for inclusion?

There are small some issues that I found in further testing and fixed
locally.

> Current ST infrastructure needs to use one i2c slave per driver (accel or magn or gyro).
> All sensors currently supported (including lsm303agr) have one i2c address per sensor type (for example in lsm303agr, accel has one i2c address, magn has another one).

I was skimming multiple datasheets from ST and missed the fact that
lsm303agr has two I2C addresses. The accel and magn parts have distinct
register ranges (despite being separated by address anyway) and that
threw me off

> What you are doing now it is not possible with current implementation. You can't have two drivers that manage one singol i2c device.
> A possible solution is to use MDF device that let IIO drivers probe, the only driver that really manage i2c is MDF (check HID implementation), But I'm not sure it is ok because in combo device (two sensors sharing same i2c address) maybe you have some constrains you should verify (for example one odr is related to the other one, ...), you can't basically try to use those as totally separated.
>
> I've started months ago to modify ST infrastructure in order to manage combo device but so far it is still work in progess...

This device has some bits and registers that are shared between the
accel/magn part and this kind of stuff will have to be dealt with.
Attempting to treat the two parts can sort of work but it's not a very
good solution.

I agree that the good solution would be to create some sort of st_combo
infrastructure (perhaps in drivers/iio/imu) and have a single iio_dev
which contains multiple st_sensor_data structs inside priv. Something
like this:

struct st_combo_sensor_data {
    struct st_sensor_data *accel;
    struct st_sensor_data *magn;
}

Then st_combo_* implementation functions would forward to st_magn_* or
st_accel_* depending on chan->type. Does this make sense?

--
Regards,
Leonard

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

* Re: [RFC] iio: st: Add lsm9ds0 support for gyro accel and magny
  2016-04-18 10:25     ` Crestez Dan Leonard
@ 2016-04-18 19:51       ` Jonathan Cameron
  2016-04-19  5:10         ` Lucas De Marchi
  0 siblings, 1 reply; 11+ messages in thread
From: Jonathan Cameron @ 2016-04-18 19:51 UTC (permalink / raw)
  To: Crestez Dan Leonard, Denis Ciocca
  Cc: linux-iio, Giuseppe BARBA, linux-kernel, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Daniel Baluta,
	Peter Rosin, Wolfram Sang

On 18/04/16 11:25, Crestez Dan Leonard wrote:
> On 04/18/2016 09:07 AM, Denis Ciocca wrote:
>> Hi Leonard and Jonathan,
>>
>> basically the patch can not work.
> Well, it can work as long as you don't initialize both the accel and the
> magn at the same time. There is no issue with the gyro driver. Would it
> be OK if I resend this as a [PATCH] intended for inclusion?
> 
> There are small some issues that I found in further testing and fixed
> locally.
> 
>> Current ST infrastructure needs to use one i2c slave per driver (accel or magn or gyro).
>> All sensors currently supported (including lsm303agr) have one i2c address per sensor type (for example in lsm303agr, accel has one i2c address, magn has another one).
> 
> I was skimming multiple datasheets from ST and missed the fact that
> lsm303agr has two I2C addresses. The accel and magn parts have distinct
> register ranges (despite being separated by address anyway) and that
> threw me off
> 
>> What you are doing now it is not possible with current implementation. You can't have two drivers that manage one singol i2c device.
>> A possible solution is to use MDF device that let IIO drivers probe, the only driver that really manage i2c is MDF (check HID implementation), But I'm not sure it is ok because in combo device (two sensors sharing same i2c address) maybe you have some constrains you should verify (for example one odr is related to the other one, ...), you can't basically try to use those as totally separated.
>>
>> I've started months ago to modify ST infrastructure in order to manage combo device but so far it is still work in progess...
> 
> This device has some bits and registers that are shared between the
> accel/magn part and this kind of stuff will have to be dealt with.
> Attempting to treat the two parts can sort of work but it's not a very
> good solution.
> 
> I agree that the good solution would be to create some sort of st_combo
> infrastructure (perhaps in drivers/iio/imu) and have a single iio_dev
> which contains multiple st_sensor_data structs inside priv. Something
> like this:
> 
> struct st_combo_sensor_data {
>     struct st_sensor_data *accel;
>     struct st_sensor_data *magn;
> }
> 
> Then st_combo_* implementation functions would forward to st_magn_* or
> st_accel_* depending on chan->type. Does this make sense?
Perhaps. If you have a short term need for this perhaps Denis and you can
work together to speed up what he has 'in the works' for this?
No point in duplicating work!

The gyro element can go forward separately in the meantime.

Jonathan
> 
> --
> Regards,
> Leonard
> 

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

* Re: [RFC] iio: st: Add lsm9ds0 support for gyro accel and magny
  2016-04-18 19:51       ` Jonathan Cameron
@ 2016-04-19  5:10         ` Lucas De Marchi
  2016-04-19  6:05           ` [RFC] iio: st: Add lsm9ds0 support for gyro accel and magn Denis Ciocca
  2016-04-19 10:53           ` [RFC] iio: st: Add lsm9ds0 support for gyro accel and magny Crestez Dan Leonard
  0 siblings, 2 replies; 11+ messages in thread
From: Lucas De Marchi @ 2016-04-19  5:10 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Crestez Dan Leonard, Denis Ciocca, linux-iio, Giuseppe BARBA,
	linux-kernel, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Daniel Baluta, Peter Rosin, Wolfram Sang

On Mon, Apr 18, 2016 at 4:51 PM, Jonathan Cameron <jic23@kernel.org> wrote:
> On 18/04/16 11:25, Crestez Dan Leonard wrote:
>> On 04/18/2016 09:07 AM, Denis Ciocca wrote:
>> Then st_combo_* implementation functions would forward to st_magn_* or
>> st_accel_* depending on chan->type. Does this make sense?
> Perhaps. If you have a short term need for this perhaps Denis and you can
> work together to speed up what he has 'in the works' for this?
> No point in duplicating work!
>
> The gyro element can go forward separately in the meantime.

Isn't LSM9DS0 just a package of LSM303D and L3GD20 that could reuse
the drivers already present?


Lucas De Marchi

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

* Re: [RFC] iio: st: Add lsm9ds0 support for gyro accel and magn
  2016-04-19  5:10         ` Lucas De Marchi
@ 2016-04-19  6:05           ` Denis Ciocca
  2016-04-19 10:53           ` [RFC] iio: st: Add lsm9ds0 support for gyro accel and magny Crestez Dan Leonard
  1 sibling, 0 replies; 11+ messages in thread
From: Denis Ciocca @ 2016-04-19  6:05 UTC (permalink / raw)
  To: Lucas De Marchi
  Cc: Jonathan Cameron, Crestez Dan Leonard, linux-iio, Giuseppe BARBA,
	linux-kernel, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Daniel Baluta, Peter Rosin, Wolfram Sang

Hi Lucas,

yup. Just need to add the lsm9ds0_gyro entry in the same table of l3gd20.

Thanks,
Denis


On |19 Apr 16 @ 07:10|, Lucas De Marchi wrote:
> On Mon, Apr 18, 2016 at 4:51 PM, Jonathan Cameron <jic23@kernel.org> wrote:
> > On 18/04/16 11:25, Crestez Dan Leonard wrote:
> >> On 04/18/2016 09:07 AM, Denis Ciocca wrote:
> >> Then st_combo_* implementation functions would forward to st_magn_* or
> >> st_accel_* depending on chan->type. Does this make sense?
> > Perhaps. If you have a short term need for this perhaps Denis and you can
> > work together to speed up what he has 'in the works' for this?
> > No point in duplicating work!
> >
> > The gyro element can go forward separately in the meantime.
> 
> Isn't LSM9DS0 just a package of LSM303D and L3GD20 that could reuse
> the drivers already present?
> 
> 
> Lucas De Marchi

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

* Re: [RFC] iio: st: Add lsm9ds0 support for gyro accel and magny
  2016-04-19  5:10         ` Lucas De Marchi
  2016-04-19  6:05           ` [RFC] iio: st: Add lsm9ds0 support for gyro accel and magn Denis Ciocca
@ 2016-04-19 10:53           ` Crestez Dan Leonard
  2016-04-19 11:22             ` Denis Ciocca
  1 sibling, 1 reply; 11+ messages in thread
From: Crestez Dan Leonard @ 2016-04-19 10:53 UTC (permalink / raw)
  To: Lucas De Marchi, Jonathan Cameron
  Cc: Denis Ciocca, linux-iio, Giuseppe BARBA, linux-kernel,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Daniel Baluta, Peter Rosin, Wolfram Sang

On 04/19/2016 08:10 AM, Lucas De Marchi wrote:
> On Mon, Apr 18, 2016 at 4:51 PM, Jonathan Cameron <jic23@kernel.org> wrote:
>> On 18/04/16 11:25, Crestez Dan Leonard wrote:
>>> On 04/18/2016 09:07 AM, Denis Ciocca wrote:
>>> Then st_combo_* implementation functions would forward to st_magn_* or
>>> st_accel_* depending on chan->type. Does this make sense?
>> Perhaps. If you have a short term need for this perhaps Denis and you can
>> work together to speed up what he has 'in the works' for this?
>> No point in duplicating work!
>>
>> The gyro element can go forward separately in the meantime.
> 
> Isn't LSM9DS0 just a package of LSM303D and L3GD20 that could reuse
> the drivers already present?

That doesn't seem to be mentioned in the datasheets but I guessed that
is a repacking of existing devices.

The gyro part of the patch only adds IDs. It's ~10 lines spread around
many files.

For accel/magn parts there is a WHOAMI different from all others present
and some registers also seem to be different. There doesn't seem to be
explicit support for "LSM303D".

I have no urgent need for this to work, I'm fine with waiting some time
for st_sensor combo support.

I can repost the gyro and accel+magn parts separately. But it's not
clear that supporting an accel-only device would still make sense once
combo support is available. So maybe I should just repost the gyro patch
adding IDs?

Regards,
Leonard

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

* Re: [RFC] iio: st: Add lsm9ds0 support for gyro accel and magny
  2016-04-19 10:53           ` [RFC] iio: st: Add lsm9ds0 support for gyro accel and magny Crestez Dan Leonard
@ 2016-04-19 11:22             ` Denis Ciocca
  0 siblings, 0 replies; 11+ messages in thread
From: Denis Ciocca @ 2016-04-19 11:22 UTC (permalink / raw)
  To: Crestez Dan Leonard
  Cc: Lucas De Marchi, Jonathan Cameron, linux-iio, Giuseppe BARBA,
	linux-kernel, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Daniel Baluta, Peter Rosin, Wolfram Sang

Hi Leonard,

On |19 Apr 16 @ 12:53|, Crestez Dan Leonard wrote:
> On 04/19/2016 08:10 AM, Lucas De Marchi wrote:
> > On Mon, Apr 18, 2016 at 4:51 PM, Jonathan Cameron <jic23@kernel.org> wrote:
> >> On 18/04/16 11:25, Crestez Dan Leonard wrote:
> >>> On 04/18/2016 09:07 AM, Denis Ciocca wrote:
> >>> Then st_combo_* implementation functions would forward to st_magn_* or
> >>> st_accel_* depending on chan->type. Does this make sense?
> >> Perhaps. If you have a short term need for this perhaps Denis and you can
> >> work together to speed up what he has 'in the works' for this?
> >> No point in duplicating work!
> >>
> >> The gyro element can go forward separately in the meantime.
> > 
> > Isn't LSM9DS0 just a package of LSM303D and L3GD20 that could reuse
> > the drivers already present?
> 
> That doesn't seem to be mentioned in the datasheets but I guessed that
> is a repacking of existing devices.

There is no such info. But since whoIam and register map is same, we can use
same table of l3gd20.



> 
> The gyro part of the patch only adds IDs. It's ~10 lines spread around
> many files.
> 
> For accel/magn parts there is a WHOAMI different from all others present
> and some registers also seem to be different. There doesn't seem to be
> explicit support for "LSM303D".

lsm303d is a combo device, not currently supported into ST architecture.
When it will be ok, we can support in same table lsm303d and lsm9ds0 (accel & magn)
if I remember corretly (since are sharing ID and register map).



> 
> I have no urgent need for this to work, I'm fine with waiting some time
> for st_sensor combo support.

That's great. I will keep you updated.



> 
> I can repost the gyro and accel+magn parts separately. But it's not
> clear that supporting an accel-only device would still make sense once
> combo support is available. So maybe I should just repost the gyro patch
> adding IDs?

I think we can proceed with gyro patch. So, you can provide a patch that adds
lsm9ds0_gyro part.


Thanks,
Denis


> 
> Regards,
> Leonard
> 
> 
> --
> 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] 11+ messages in thread

end of thread, other threads:[~2016-04-19 11:23 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-13 19:01 [RFC] iio: st: Add lsm9ds0 support for gyro accel and magn Crestez Dan Leonard
2016-04-17 11:44 ` Jonathan Cameron
2016-04-17 12:25   ` Wolfram Sang
2016-04-17 14:21   ` Peter Rosin
2016-04-18  6:07   ` [RFC] iio: st: Add lsm9ds0 support for gyro accel and magny Denis Ciocca
2016-04-18 10:25     ` Crestez Dan Leonard
2016-04-18 19:51       ` Jonathan Cameron
2016-04-19  5:10         ` Lucas De Marchi
2016-04-19  6:05           ` [RFC] iio: st: Add lsm9ds0 support for gyro accel and magn Denis Ciocca
2016-04-19 10:53           ` [RFC] iio: st: Add lsm9ds0 support for gyro accel and magny Crestez Dan Leonard
2016-04-19 11:22             ` Denis Ciocca

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).