linux-iio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Introduce support for INV MPU6050 secondary I2C master
@ 2016-03-17 16:32 Daniel Baluta
  2016-03-17 16:32 ` [PATCH 1/3] iio: imu: mpu6050: Fix name/chip_id when using ACPI Daniel Baluta
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Daniel Baluta @ 2016-03-17 16:32 UTC (permalink / raw)
  To: jic23
  Cc: knaack.h, lars, pmeerw, daniel.baluta, matt.ranostay,
	lucas.demarchi, cmo, linux-iio, ggao, srinivas.pandruvada,
	adi.reus

This patch series adds support for attaching external sensors to INV MPU6050
secondary I2C interface (acting as an I2C bus).

First patch fixes a bug when using ACPI, the second one moves the interrupt out
of probe trigger code preparing the third patch which actually does $Subject.

I2C secondary bus can support up to 5 slaves. Slaves 0-3 have a common way
of operation while the 4 one is completely different. This patch series
only implements support for the 4th slave because it has a cleaner interface
(although less efficent for bulk transfer) and also provides a way of
signalling when data recevied from slave is available.

Ge,

In order to prepare support for slaves 0-3 we need to find the answer for
the following questions:
	* when doing a read transaction after preparing I2C address, I2C
        remote register, etc how do we know when to read for available data?
	* how can we benefit from INV MPU6050 FIFO in case of external sensors?
	(will look into in-kernel buffer consumers)

Daniel Baluta (3):
  iio: imu: mpu6050: Fix name/chip_id when using ACPI
  iio: imu: mpu6050: Request IRQ outside of probe trigger
  iio: imu: mpu6050: Add support for auxiliary I2C master

 drivers/iio/imu/inv_mpu6050/inv_mpu_core.c    | 139 ++++++++++++++++++++++++++
 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c     |  29 +++++-
 drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h     |  38 +++++++
 drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c |   8 --
 4 files changed, 203 insertions(+), 11 deletions(-)

-- 
2.5.0


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

* [PATCH 1/3] iio: imu: mpu6050: Fix name/chip_id when using ACPI
  2016-03-17 16:32 [PATCH 0/3] Introduce support for INV MPU6050 secondary I2C master Daniel Baluta
@ 2016-03-17 16:32 ` Daniel Baluta
  2016-03-17 17:21   ` Matt Ranostay
  2016-03-17 16:32 ` [PATCH 2/3] iio: imu: mpu6050: Move request IRQ outside of probe trigger Daniel Baluta
  2016-03-17 16:32 ` [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C master Daniel Baluta
  2 siblings, 1 reply; 16+ messages in thread
From: Daniel Baluta @ 2016-03-17 16:32 UTC (permalink / raw)
  To: jic23
  Cc: knaack.h, lars, pmeerw, daniel.baluta, matt.ranostay,
	lucas.demarchi, cmo, linux-iio, ggao, srinivas.pandruvada,
	adi.reus

When using ACPI, id is NULL and the current code automatically
defaults name to NULL and chip id to 0. We should instead use
the data provided in the ACPI device table.

Fixes: c816d9e7a57b ("iio: imu: mpu6050: fix possible NULL dereferences")
Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
---
 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index d0c0e20..5ee4e0d 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -104,6 +104,19 @@ static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
 	return 0;
 }
 
+static const char *inv_mpu_match_acpi_device(struct device *dev, int *chip_id)
+{
+	const struct acpi_device_id *id;
+
+	id = acpi_match_device(dev->driver->acpi_match_table, dev);
+	if (!id)
+		return NULL;
+
+	*chip_id = (int)id->driver_data;
+
+	return dev_name(dev);
+}
+
 /**
  *  inv_mpu_probe() - probe function.
  *  @client:          i2c client.
@@ -115,15 +128,25 @@ static int inv_mpu_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct inv_mpu6050_state *st;
-	int result;
-	const char *name = id ? id->name : NULL;
-	const int chip_type = id ? id->driver_data : 0;
+	int result, chip_type;
 	struct regmap *regmap;
+	const char *name;
 
 	if (!i2c_check_functionality(client->adapter,
 				     I2C_FUNC_SMBUS_I2C_BLOCK))
 		return -EOPNOTSUPP;
 
+	if (id) {
+		chip_type = (int)id->driver_data;
+		name = id->name;
+	} else if (ACPI_HANDLE(&client->dev)) {
+		name = inv_mpu_match_acpi_device(&client->dev, &chip_type);
+		if (!name)
+			return -ENODEV;
+	} else {
+		return -ENOSYS;
+	}
+
 	regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config);
 	if (IS_ERR(regmap)) {
 		dev_err(&client->dev, "Failed to register i2c regmap %d\n",
-- 
2.5.0


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

* [PATCH 2/3] iio: imu: mpu6050: Move request IRQ outside of probe trigger
  2016-03-17 16:32 [PATCH 0/3] Introduce support for INV MPU6050 secondary I2C master Daniel Baluta
  2016-03-17 16:32 ` [PATCH 1/3] iio: imu: mpu6050: Fix name/chip_id when using ACPI Daniel Baluta
@ 2016-03-17 16:32 ` Daniel Baluta
  2016-03-17 17:24   ` Matt Ranostay
  2016-03-17 16:32 ` [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C master Daniel Baluta
  2 siblings, 1 reply; 16+ messages in thread
From: Daniel Baluta @ 2016-03-17 16:32 UTC (permalink / raw)
  To: jic23
  Cc: knaack.h, lars, pmeerw, daniel.baluta, matt.ranostay,
	lucas.demarchi, cmo, linux-iio, ggao, srinivas.pandruvada,
	adi.reus

Besides signalling data ready, IRQ line of Invensense MPU
can also signal the status of slaves attached on secondary
I2C bus.

In order to prepare supporting secondary I2C interface we need
to detach IRQ request from data ready trigger creation.

Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
---
 drivers/iio/imu/inv_mpu6050/inv_mpu_core.c    | 8 ++++++++
 drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 8 --------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index d192953..659a4be 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -823,6 +823,14 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
 		goto out_unreg_ring;
 	}
 
+	result = devm_request_irq(&indio_dev->dev, st->irq,
+				  &iio_trigger_generic_data_rdy_poll,
+				  IRQF_TRIGGER_RISING, "inv_mpu", st->trig);
+	if (result) {
+		dev_err(dev, "request irq fail %d\n", result);
+		goto out_remove_trigger;
+	}
+
 	INIT_KFIFO(st->timestamps);
 	spin_lock_init(&st->time_stamp_lock);
 	result = iio_device_register(indio_dev);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index e8818d4..acfa513 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -123,14 +123,6 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev)
 	if (!st->trig)
 		return -ENOMEM;
 
-	ret = devm_request_irq(&indio_dev->dev, st->irq,
-			       &iio_trigger_generic_data_rdy_poll,
-			       IRQF_TRIGGER_RISING,
-			       "inv_mpu",
-			       st->trig);
-	if (ret)
-		return ret;
-
 	st->trig->dev.parent = regmap_get_device(st->map);
 	st->trig->ops = &inv_mpu_trigger_ops;
 	iio_trigger_set_drvdata(st->trig, indio_dev);
-- 
2.5.0


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

* [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C master
  2016-03-17 16:32 [PATCH 0/3] Introduce support for INV MPU6050 secondary I2C master Daniel Baluta
  2016-03-17 16:32 ` [PATCH 1/3] iio: imu: mpu6050: Fix name/chip_id when using ACPI Daniel Baluta
  2016-03-17 16:32 ` [PATCH 2/3] iio: imu: mpu6050: Move request IRQ outside of probe trigger Daniel Baluta
@ 2016-03-17 16:32 ` Daniel Baluta
  2016-03-17 17:28   ` Matt Ranostay
  2016-03-20 10:47   ` Jonathan Cameron
  2 siblings, 2 replies; 16+ messages in thread
From: Daniel Baluta @ 2016-03-17 16:32 UTC (permalink / raw)
  To: jic23
  Cc: knaack.h, lars, pmeerw, daniel.baluta, matt.ranostay,
	lucas.demarchi, cmo, linux-iio, ggao, srinivas.pandruvada,
	adi.reus

The MPU-60X0 [1] has an auxiliary I2C bus for connecting external
sensors. This bus has two operating modes:
	* pass-through, which connects the primary and auxiliary busses
	together [already implemented]
	* I2C master mode, where MPU60X0 acts as a master to any
	external connected sensors [implemented in this patch]

I2C master supports up to 5 slaves. Slaves 0-3 have a common operating
mode while slave 4 is different.

This patch only adds support for slave 4 because it has a cleaner
interface and it has an interrupt that signals when data from slave
to master arrived.

Registers are described here [2].

We use threaded handler for reading slave4 done interrupt bit.

[1]
https://www.cdiweb.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf
[2]
http://www6.in.tum.de/pub/Main/TeachingWs2015SeminarAuonomousFahren/RM-MPU-6000A.pdf

Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
---
 drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 137 ++++++++++++++++++++++++++++-
 drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  |  38 ++++++++
 2 files changed, 172 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 659a4be..a89854c 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -25,6 +25,8 @@
 #include <linux/iio/iio.h>
 #include <linux/i2c-mux.h>
 #include <linux/acpi.h>
+#include <linux/completion.h>
+
 #include "inv_mpu_iio.h"
 
 /*
@@ -57,6 +59,12 @@ static const struct inv_mpu6050_reg_map reg_set_6500 = {
 	.int_pin_cfg		= INV_MPU6050_REG_INT_PIN_CFG,
 	.accl_offset		= INV_MPU6500_REG_ACCEL_OFFSET,
 	.gyro_offset		= INV_MPU6050_REG_GYRO_OFFSET,
+	.slv4_addr		= INV_MPU6050_REG_I2C_SLV4_ADDR,
+	.slv4_reg		= INV_MPU6050_REG_I2C_SLV4_REG,
+	.slv4_do		= INV_MPU6050_REG_I2C_SLV4_DO,
+	.slv4_ctrl		= INV_MPU6050_REG_I2C_SLV4_CTRL,
+	.slv4_di		= INV_MPU6050_REG_I2C_SLV4_DI,
+	.mst_status		= INV_MPU6050_REG_I2C_MST_STATUS,
 };
 
 static const struct inv_mpu6050_reg_map reg_set_6050 = {
@@ -77,6 +85,12 @@ static const struct inv_mpu6050_reg_map reg_set_6050 = {
 	.int_pin_cfg		= INV_MPU6050_REG_INT_PIN_CFG,
 	.accl_offset		= INV_MPU6050_REG_ACCEL_OFFSET,
 	.gyro_offset		= INV_MPU6050_REG_GYRO_OFFSET,
+	.slv4_addr		= INV_MPU6050_REG_I2C_SLV4_ADDR,
+	.slv4_reg		= INV_MPU6050_REG_I2C_SLV4_REG,
+	.slv4_do		= INV_MPU6050_REG_I2C_SLV4_DO,
+	.slv4_ctrl		= INV_MPU6050_REG_I2C_SLV4_CTRL,
+	.slv4_di		= INV_MPU6050_REG_I2C_SLV4_DI,
+	.mst_status		= INV_MPU6050_REG_I2C_MST_STATUS,
 };
 
 static const struct inv_mpu6050_chip_config chip_config_6050 = {
@@ -761,6 +775,114 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
 	return 0;
 }
 
+static irqreturn_t inv_mpu_datardy_irq_handler(int irq, void *private)
+{
+	struct inv_mpu6050_state *st = (struct inv_mpu6050_state *)private;
+
+	iio_trigger_poll(st->trig);
+
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t inv_mpu_datardy_thread_handler(int irq, void *private)
+{
+	struct inv_mpu6050_state *st = (struct inv_mpu6050_state *)private;
+	int ret, val;
+
+	ret = regmap_read(st->map, st->reg->mst_status, &val);
+	if (ret < 0)
+		return ret;
+
+	if (val & INV_MPU6050_BIT_I2C_SLV4_DONE)
+		complete(&st->slv4_done);
+
+	return IRQ_HANDLED;
+}
+
+static u32 inv_mpu_i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA;
+}
+
+static int
+inv_mpu_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+		       unsigned short flags, char read_write, u8 command,
+		       int size, union i2c_smbus_data *data)
+{
+	struct inv_mpu6050_state *st = i2c_get_adapdata(adap);
+
+	unsigned long time_left;
+	int ret, val;
+	u8 ctrl;
+
+	ret = inv_mpu6050_set_power_itg(st, true);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_update_bits(st->map, st->reg->user_ctrl,
+				 INV_MPU6050_BIT_I2C_MST_EN,
+				 INV_MPU6050_BIT_I2C_MST_EN);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_update_bits(st->map, st->reg->int_enable,
+				 INV_MPU6050_BIT_MST_INT_EN,
+				 INV_MPU6050_BIT_MST_INT_EN);
+	if (ret < 0)
+		return ret;
+
+	if (read_write == I2C_SMBUS_WRITE)
+		addr |= INV_MPU6050_BIT_I2C_SLV4_W;
+	else
+		addr |= INV_MPU6050_BIT_I2C_SLV4_R;
+
+	ret = regmap_write(st->map, st->reg->slv4_addr, addr);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_write(st->map, st->reg->slv4_reg, command);
+	if (ret < 0)
+		return ret;
+
+	if (read_write == I2C_SMBUS_WRITE) {
+		ret = regmap_write(st->map, st->reg->slv4_do, data->byte);
+		if (ret < 0)
+			return ret;
+	}
+
+	ctrl = INV_MPU6050_BIT_SLV4_EN | INV_MPU6050_BIT_SLV4_INT_EN;
+	ret = regmap_write(st->map, st->reg->slv4_ctrl, ctrl);
+	if (ret < 0)
+		return ret;
+	if (read_write == I2C_SMBUS_READ) {
+		time_left = wait_for_completion_timeout(&st->slv4_done, HZ);
+		if (!time_left)
+			return -ETIMEDOUT;
+
+		ret = regmap_read(st->map, st->reg->slv4_di, &val);
+		if (ret < 0)
+			return ret;
+		data->byte = val;
+	}
+
+	ret = inv_mpu6050_set_power_itg(st, false);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static const struct i2c_algorithm inv_mpu_i2c_algo = {
+	.smbus_xfer	=	inv_mpu_i2c_smbus_xfer,
+	.functionality	=	inv_mpu_i2c_functionality,
+};
+
+static struct i2c_adapter inv_mpu_i2c_adapter = {
+	.owner		= THIS_MODULE,
+	.class		= I2C_CLASS_HWMON,
+	.algo		= &inv_mpu_i2c_algo,
+	.name		= "INV MPU secondary I2C",
+};
+
 int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
 		int (*inv_mpu_bus_setup)(struct iio_dev *), int chip_type)
 {
@@ -796,6 +918,13 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
 		return result;
 	}
 
+	init_completion(&st->slv4_done);
+
+	result = i2c_add_adapter(&inv_mpu_i2c_adapter);
+	if (result < 0)
+		return result;
+
+	i2c_set_adapdata(&inv_mpu_i2c_adapter, st);
 	dev_set_drvdata(dev, indio_dev);
 	indio_dev->dev.parent = dev;
 	/* name will be NULL when enumerated via ACPI */
@@ -823,9 +952,11 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
 		goto out_unreg_ring;
 	}
 
-	result = devm_request_irq(&indio_dev->dev, st->irq,
-				  &iio_trigger_generic_data_rdy_poll,
-				  IRQF_TRIGGER_RISING, "inv_mpu", st->trig);
+	result = devm_request_threaded_irq(&indio_dev->dev, st->irq,
+					   &inv_mpu_datardy_irq_handler,
+					   &inv_mpu_datardy_thread_handler,
+					   IRQF_TRIGGER_RISING, "inv_mpu",
+					   st);
 	if (result) {
 		dev_err(dev, "request irq fail %d\n", result);
 		goto out_remove_trigger;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index e302a49..5c3ea9a 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -42,6 +42,13 @@
  *  @int_pin_cfg;	Controls interrupt pin configuration.
  *  @accl_offset:	Controls the accelerometer calibration offset.
  *  @gyro_offset:	Controls the gyroscope calibration offset.
+ *  @mst_status:	secondary I2C master interrupt source status
+ *  @slv4_addr:		I2C slave address for slave 4 transaction
+ *  @slv4_reg:		I2C register used with slave 4 transaction
+ *  @slv4_di:		I2C data in register for slave 4 transaction
+ *  @slv4_ctrl:		I2C slave 4 control register
+ *  @slv4_do:		I2C data out register for slave 4 transaction
+
  */
 struct inv_mpu6050_reg_map {
 	u8 sample_rate_div;
@@ -61,6 +68,15 @@ struct inv_mpu6050_reg_map {
 	u8 int_pin_cfg;
 	u8 accl_offset;
 	u8 gyro_offset;
+	u8 mst_status;
+
+	/* slave 4 registers */
+	u8 slv4_addr;
+	u8 slv4_reg;
+	u8 slv4_di; /* data in */
+	u8 slv4_ctrl;
+	u8 slv4_do; /* data out */
+
 };
 
 /*device enum */
@@ -133,6 +149,7 @@ struct inv_mpu6050_state {
 	struct inv_mpu6050_platform_data plat_data;
 	DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
 	struct regmap *map;
+	struct completion slv4_done;
 	int irq;
 };
 
@@ -149,9 +166,30 @@ struct inv_mpu6050_state {
 #define INV_MPU6050_BIT_ACCEL_OUT           0x08
 #define INV_MPU6050_BITS_GYRO_OUT           0x70
 
+#define INV_MPU6050_REG_I2C_SLV4_ADDR       0x31
+#define INV_MPU6050_BIT_I2C_SLV4_R          0x80
+#define INV_MPU6050_BIT_I2C_SLV4_W          0x00
+
+#define INV_MPU6050_REG_I2C_SLV4_REG        0x32
+#define INV_MPU6050_REG_I2C_SLV4_DO         0x33
+#define INV_MPU6050_REG_I2C_SLV4_CTRL       0x34
+
+#define INV_MPU6050_BIT_SLV4_EN             0x80
+#define INV_MPU6050_BIT_SLV4_INT_EN         0x40
+#define INV_MPU6050_BIT_SLV4_DIS            0x20
+
+#define INV_MPU6050_REG_I2C_SLV4_DI         0x35
+
+#define INV_MPU6050_REG_I2C_MST_STATUS      0x36
+#define INV_MPU6050_BIT_I2C_SLV4_DONE       0x40
+
 #define INV_MPU6050_REG_INT_ENABLE          0x38
 #define INV_MPU6050_BIT_DATA_RDY_EN         0x01
 #define INV_MPU6050_BIT_DMP_INT_EN          0x02
+#define INV_MPU6050_BIT_MST_INT_EN          0x08
+
+#define INV_MPU6050_REG_INT_STATUS          0x3A
+#define INV_MPU6050_BIT_MST_INT             0x08
 
 #define INV_MPU6050_REG_RAW_ACCEL           0x3B
 #define INV_MPU6050_REG_TEMPERATURE         0x41
-- 
2.5.0


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

* Re: [PATCH 1/3] iio: imu: mpu6050: Fix name/chip_id when using ACPI
  2016-03-17 16:32 ` [PATCH 1/3] iio: imu: mpu6050: Fix name/chip_id when using ACPI Daniel Baluta
@ 2016-03-17 17:21   ` Matt Ranostay
  2016-03-20 10:40     ` Jonathan Cameron
  0 siblings, 1 reply; 16+ messages in thread
From: Matt Ranostay @ 2016-03-17 17:21 UTC (permalink / raw)
  To: Daniel Baluta
  Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Matt Ranostay, Lucas De Marchi, cmo,
	linux-iio@vger.kernel.org, ggao, srinivas.pandruvada, adi.reus

Reviewed-By: Matt Ranostay <matt.ranostay@intel.com>

On Thu, Mar 17, 2016 at 9:32 AM, Daniel Baluta <daniel.baluta@intel.com> wrote:
> When using ACPI, id is NULL and the current code automatically
> defaults name to NULL and chip id to 0. We should instead use
> the data provided in the ACPI device table.
>
> Fixes: c816d9e7a57b ("iio: imu: mpu6050: fix possible NULL dereferences")
> Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
> ---
>  drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 29 ++++++++++++++++++++++++++---
>  1 file changed, 26 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
> index d0c0e20..5ee4e0d 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
> @@ -104,6 +104,19 @@ static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
>         return 0;
>  }
>
> +static const char *inv_mpu_match_acpi_device(struct device *dev, int *chip_id)
> +{
> +       const struct acpi_device_id *id;
> +
> +       id = acpi_match_device(dev->driver->acpi_match_table, dev);
> +       if (!id)
> +               return NULL;
> +
> +       *chip_id = (int)id->driver_data;
> +
> +       return dev_name(dev);
> +}
> +
>  /**
>   *  inv_mpu_probe() - probe function.
>   *  @client:          i2c client.
> @@ -115,15 +128,25 @@ static int inv_mpu_probe(struct i2c_client *client,
>                          const struct i2c_device_id *id)
>  {
>         struct inv_mpu6050_state *st;
> -       int result;
> -       const char *name = id ? id->name : NULL;
> -       const int chip_type = id ? id->driver_data : 0;
> +       int result, chip_type;
>         struct regmap *regmap;
> +       const char *name;
>
>         if (!i2c_check_functionality(client->adapter,
>                                      I2C_FUNC_SMBUS_I2C_BLOCK))
>                 return -EOPNOTSUPP;
>
> +       if (id) {
> +               chip_type = (int)id->driver_data;
> +               name = id->name;
> +       } else if (ACPI_HANDLE(&client->dev)) {
> +               name = inv_mpu_match_acpi_device(&client->dev, &chip_type);
> +               if (!name)
> +                       return -ENODEV;
> +       } else {
> +               return -ENOSYS;
> +       }
> +
>         regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config);
>         if (IS_ERR(regmap)) {
>                 dev_err(&client->dev, "Failed to register i2c regmap %d\n",
> --
> 2.5.0
>
> --
> 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] 16+ messages in thread

* Re: [PATCH 2/3] iio: imu: mpu6050: Move request IRQ outside of probe trigger
  2016-03-17 16:32 ` [PATCH 2/3] iio: imu: mpu6050: Move request IRQ outside of probe trigger Daniel Baluta
@ 2016-03-17 17:24   ` Matt Ranostay
  0 siblings, 0 replies; 16+ messages in thread
From: Matt Ranostay @ 2016-03-17 17:24 UTC (permalink / raw)
  To: Daniel Baluta
  Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Matt Ranostay, Lucas De Marchi, cmo,
	linux-iio@vger.kernel.org, ggao, srinivas.pandruvada, adi.reus

Acked-By: Matt Ranostay <matt.ranostay@intel.com>

On Thu, Mar 17, 2016 at 9:32 AM, Daniel Baluta <daniel.baluta@intel.com> wrote:
> Besides signalling data ready, IRQ line of Invensense MPU
> can also signal the status of slaves attached on secondary
> I2C bus.
>
> In order to prepare supporting secondary I2C interface we need
> to detach IRQ request from data ready trigger creation.
>
> Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
> ---
>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c    | 8 ++++++++
>  drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 8 --------
>  2 files changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> index d192953..659a4be 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> @@ -823,6 +823,14 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
>                 goto out_unreg_ring;
>         }
>
> +       result = devm_request_irq(&indio_dev->dev, st->irq,
> +                                 &iio_trigger_generic_data_rdy_poll,
> +                                 IRQF_TRIGGER_RISING, "inv_mpu", st->trig);
> +       if (result) {
> +               dev_err(dev, "request irq fail %d\n", result);
> +               goto out_remove_trigger;
> +       }
> +
>         INIT_KFIFO(st->timestamps);
>         spin_lock_init(&st->time_stamp_lock);
>         result = iio_device_register(indio_dev);
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> index e8818d4..acfa513 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> @@ -123,14 +123,6 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev)
>         if (!st->trig)
>                 return -ENOMEM;
>
> -       ret = devm_request_irq(&indio_dev->dev, st->irq,
> -                              &iio_trigger_generic_data_rdy_poll,
> -                              IRQF_TRIGGER_RISING,
> -                              "inv_mpu",
> -                              st->trig);
> -       if (ret)
> -               return ret;
> -
>         st->trig->dev.parent = regmap_get_device(st->map);
>         st->trig->ops = &inv_mpu_trigger_ops;
>         iio_trigger_set_drvdata(st->trig, indio_dev);
> --
> 2.5.0
>
> --
> 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] 16+ messages in thread

* Re: [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C master
  2016-03-17 16:32 ` [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C master Daniel Baluta
@ 2016-03-17 17:28   ` Matt Ranostay
  2016-03-17 18:11     ` Ge Gao
  2016-03-20 10:47   ` Jonathan Cameron
  1 sibling, 1 reply; 16+ messages in thread
From: Matt Ranostay @ 2016-03-17 17:28 UTC (permalink / raw)
  To: Daniel Baluta
  Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Matt Ranostay, Lucas De Marchi, cmo,
	linux-iio@vger.kernel.org, ggao, srinivas.pandruvada, adi.reus

Reviewed-by: Matt Ranostay <matt.ranostay@intel.com>

On Thu, Mar 17, 2016 at 9:32 AM, Daniel Baluta <daniel.baluta@intel.com> wrote:
> The MPU-60X0 [1] has an auxiliary I2C bus for connecting external
> sensors. This bus has two operating modes:
>         * pass-through, which connects the primary and auxiliary busses
>         together [already implemented]
>         * I2C master mode, where MPU60X0 acts as a master to any
>         external connected sensors [implemented in this patch]
>
> I2C master supports up to 5 slaves. Slaves 0-3 have a common operating
> mode while slave 4 is different.
>
> This patch only adds support for slave 4 because it has a cleaner
> interface and it has an interrupt that signals when data from slave
> to master arrived.
>
> Registers are described here [2].
>
> We use threaded handler for reading slave4 done interrupt bit.
>
> [1]
> https://www.cdiweb.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf
> [2]
> http://www6.in.tum.de/pub/Main/TeachingWs2015SeminarAuonomousFahren/RM-MPU-6000A.pdf
>
> Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
> ---
>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 137 ++++++++++++++++++++++++++++-
>  drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  |  38 ++++++++
>  2 files changed, 172 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> index 659a4be..a89854c 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> @@ -25,6 +25,8 @@
>  #include <linux/iio/iio.h>
>  #include <linux/i2c-mux.h>
>  #include <linux/acpi.h>
> +#include <linux/completion.h>
> +
>  #include "inv_mpu_iio.h"
>
>  /*
> @@ -57,6 +59,12 @@ static const struct inv_mpu6050_reg_map reg_set_6500 = {
>         .int_pin_cfg            = INV_MPU6050_REG_INT_PIN_CFG,
>         .accl_offset            = INV_MPU6500_REG_ACCEL_OFFSET,
>         .gyro_offset            = INV_MPU6050_REG_GYRO_OFFSET,
> +       .slv4_addr              = INV_MPU6050_REG_I2C_SLV4_ADDR,
> +       .slv4_reg               = INV_MPU6050_REG_I2C_SLV4_REG,
> +       .slv4_do                = INV_MPU6050_REG_I2C_SLV4_DO,
> +       .slv4_ctrl              = INV_MPU6050_REG_I2C_SLV4_CTRL,
> +       .slv4_di                = INV_MPU6050_REG_I2C_SLV4_DI,
> +       .mst_status             = INV_MPU6050_REG_I2C_MST_STATUS,
>  };
>
>  static const struct inv_mpu6050_reg_map reg_set_6050 = {
> @@ -77,6 +85,12 @@ static const struct inv_mpu6050_reg_map reg_set_6050 = {
>         .int_pin_cfg            = INV_MPU6050_REG_INT_PIN_CFG,
>         .accl_offset            = INV_MPU6050_REG_ACCEL_OFFSET,
>         .gyro_offset            = INV_MPU6050_REG_GYRO_OFFSET,
> +       .slv4_addr              = INV_MPU6050_REG_I2C_SLV4_ADDR,
> +       .slv4_reg               = INV_MPU6050_REG_I2C_SLV4_REG,
> +       .slv4_do                = INV_MPU6050_REG_I2C_SLV4_DO,
> +       .slv4_ctrl              = INV_MPU6050_REG_I2C_SLV4_CTRL,
> +       .slv4_di                = INV_MPU6050_REG_I2C_SLV4_DI,
> +       .mst_status             = INV_MPU6050_REG_I2C_MST_STATUS,
>  };
>
>  static const struct inv_mpu6050_chip_config chip_config_6050 = {
> @@ -761,6 +775,114 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
>         return 0;
>  }
>
> +static irqreturn_t inv_mpu_datardy_irq_handler(int irq, void *private)
> +{
> +       struct inv_mpu6050_state *st = (struct inv_mpu6050_state *)private;
> +
> +       iio_trigger_poll(st->trig);
> +
> +       return IRQ_WAKE_THREAD;
> +}
> +
> +static irqreturn_t inv_mpu_datardy_thread_handler(int irq, void *private)
> +{
> +       struct inv_mpu6050_state *st = (struct inv_mpu6050_state *)private;
> +       int ret, val;
> +
> +       ret = regmap_read(st->map, st->reg->mst_status, &val);
> +       if (ret < 0)
> +               return ret;
> +
> +       if (val & INV_MPU6050_BIT_I2C_SLV4_DONE)
> +               complete(&st->slv4_done);
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static u32 inv_mpu_i2c_functionality(struct i2c_adapter *adap)
> +{
> +       return I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA;
> +}
> +
> +static int
> +inv_mpu_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr,
> +                      unsigned short flags, char read_write, u8 command,
> +                      int size, union i2c_smbus_data *data)
> +{
> +       struct inv_mpu6050_state *st = i2c_get_adapdata(adap);
> +
> +       unsigned long time_left;
> +       int ret, val;
> +       u8 ctrl;
> +
> +       ret = inv_mpu6050_set_power_itg(st, true);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = regmap_update_bits(st->map, st->reg->user_ctrl,
> +                                INV_MPU6050_BIT_I2C_MST_EN,
> +                                INV_MPU6050_BIT_I2C_MST_EN);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = regmap_update_bits(st->map, st->reg->int_enable,
> +                                INV_MPU6050_BIT_MST_INT_EN,
> +                                INV_MPU6050_BIT_MST_INT_EN);
> +       if (ret < 0)
> +               return ret;
> +
> +       if (read_write == I2C_SMBUS_WRITE)
> +               addr |= INV_MPU6050_BIT_I2C_SLV4_W;
> +       else
> +               addr |= INV_MPU6050_BIT_I2C_SLV4_R;
> +
> +       ret = regmap_write(st->map, st->reg->slv4_addr, addr);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = regmap_write(st->map, st->reg->slv4_reg, command);
> +       if (ret < 0)
> +               return ret;
> +
> +       if (read_write == I2C_SMBUS_WRITE) {
> +               ret = regmap_write(st->map, st->reg->slv4_do, data->byte);
> +               if (ret < 0)
> +                       return ret;
> +       }
> +
> +       ctrl = INV_MPU6050_BIT_SLV4_EN | INV_MPU6050_BIT_SLV4_INT_EN;
> +       ret = regmap_write(st->map, st->reg->slv4_ctrl, ctrl);
> +       if (ret < 0)
> +               return ret;
> +       if (read_write == I2C_SMBUS_READ) {
> +               time_left = wait_for_completion_timeout(&st->slv4_done, HZ);
> +               if (!time_left)
> +                       return -ETIMEDOUT;
> +
> +               ret = regmap_read(st->map, st->reg->slv4_di, &val);
> +               if (ret < 0)
> +                       return ret;
> +               data->byte = val;
> +       }
> +
> +       ret = inv_mpu6050_set_power_itg(st, false);
> +       if (ret < 0)
> +               return ret;
> +       return 0;
> +}
> +
> +static const struct i2c_algorithm inv_mpu_i2c_algo = {
> +       .smbus_xfer     =       inv_mpu_i2c_smbus_xfer,
> +       .functionality  =       inv_mpu_i2c_functionality,
> +};
> +
> +static struct i2c_adapter inv_mpu_i2c_adapter = {
> +       .owner          = THIS_MODULE,
> +       .class          = I2C_CLASS_HWMON,
> +       .algo           = &inv_mpu_i2c_algo,
> +       .name           = "INV MPU secondary I2C",
> +};
> +
>  int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
>                 int (*inv_mpu_bus_setup)(struct iio_dev *), int chip_type)
>  {
> @@ -796,6 +918,13 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
>                 return result;
>         }
>
> +       init_completion(&st->slv4_done);
> +
> +       result = i2c_add_adapter(&inv_mpu_i2c_adapter);
> +       if (result < 0)
> +               return result;
> +
> +       i2c_set_adapdata(&inv_mpu_i2c_adapter, st);
>         dev_set_drvdata(dev, indio_dev);
>         indio_dev->dev.parent = dev;
>         /* name will be NULL when enumerated via ACPI */
> @@ -823,9 +952,11 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
>                 goto out_unreg_ring;
>         }
>
> -       result = devm_request_irq(&indio_dev->dev, st->irq,
> -                                 &iio_trigger_generic_data_rdy_poll,
> -                                 IRQF_TRIGGER_RISING, "inv_mpu", st->trig);
> +       result = devm_request_threaded_irq(&indio_dev->dev, st->irq,
> +                                          &inv_mpu_datardy_irq_handler,
> +                                          &inv_mpu_datardy_thread_handler,
> +                                          IRQF_TRIGGER_RISING, "inv_mpu",
> +                                          st);
>         if (result) {
>                 dev_err(dev, "request irq fail %d\n", result);
>                 goto out_remove_trigger;
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> index e302a49..5c3ea9a 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> @@ -42,6 +42,13 @@
>   *  @int_pin_cfg;      Controls interrupt pin configuration.
>   *  @accl_offset:      Controls the accelerometer calibration offset.
>   *  @gyro_offset:      Controls the gyroscope calibration offset.
> + *  @mst_status:       secondary I2C master interrupt source status
> + *  @slv4_addr:                I2C slave address for slave 4 transaction
> + *  @slv4_reg:         I2C register used with slave 4 transaction
> + *  @slv4_di:          I2C data in register for slave 4 transaction
> + *  @slv4_ctrl:                I2C slave 4 control register
> + *  @slv4_do:          I2C data out register for slave 4 transaction
> +
>   */
>  struct inv_mpu6050_reg_map {
>         u8 sample_rate_div;
> @@ -61,6 +68,15 @@ struct inv_mpu6050_reg_map {
>         u8 int_pin_cfg;
>         u8 accl_offset;
>         u8 gyro_offset;
> +       u8 mst_status;
> +
> +       /* slave 4 registers */
> +       u8 slv4_addr;
> +       u8 slv4_reg;
> +       u8 slv4_di; /* data in */
> +       u8 slv4_ctrl;
> +       u8 slv4_do; /* data out */
> +
>  };
>
>  /*device enum */
> @@ -133,6 +149,7 @@ struct inv_mpu6050_state {
>         struct inv_mpu6050_platform_data plat_data;
>         DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
>         struct regmap *map;
> +       struct completion slv4_done;
>         int irq;
>  };
>
> @@ -149,9 +166,30 @@ struct inv_mpu6050_state {
>  #define INV_MPU6050_BIT_ACCEL_OUT           0x08
>  #define INV_MPU6050_BITS_GYRO_OUT           0x70
>
> +#define INV_MPU6050_REG_I2C_SLV4_ADDR       0x31
> +#define INV_MPU6050_BIT_I2C_SLV4_R          0x80
> +#define INV_MPU6050_BIT_I2C_SLV4_W          0x00
> +
> +#define INV_MPU6050_REG_I2C_SLV4_REG        0x32
> +#define INV_MPU6050_REG_I2C_SLV4_DO         0x33
> +#define INV_MPU6050_REG_I2C_SLV4_CTRL       0x34
> +
> +#define INV_MPU6050_BIT_SLV4_EN             0x80
> +#define INV_MPU6050_BIT_SLV4_INT_EN         0x40
> +#define INV_MPU6050_BIT_SLV4_DIS            0x20
> +
> +#define INV_MPU6050_REG_I2C_SLV4_DI         0x35
> +
> +#define INV_MPU6050_REG_I2C_MST_STATUS      0x36
> +#define INV_MPU6050_BIT_I2C_SLV4_DONE       0x40
> +
>  #define INV_MPU6050_REG_INT_ENABLE          0x38
>  #define INV_MPU6050_BIT_DATA_RDY_EN         0x01
>  #define INV_MPU6050_BIT_DMP_INT_EN          0x02
> +#define INV_MPU6050_BIT_MST_INT_EN          0x08
> +
> +#define INV_MPU6050_REG_INT_STATUS          0x3A
> +#define INV_MPU6050_BIT_MST_INT             0x08
>
>  #define INV_MPU6050_REG_RAW_ACCEL           0x3B
>  #define INV_MPU6050_REG_TEMPERATURE         0x41
> --
> 2.5.0
>
> --
> 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] 16+ messages in thread

* RE: [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C master
  2016-03-17 17:28   ` Matt Ranostay
@ 2016-03-17 18:11     ` Ge Gao
  2016-03-17 18:13       ` Matt Ranostay
                         ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Ge Gao @ 2016-03-17 18:11 UTC (permalink / raw)
  To: Matt Ranostay, Daniel Baluta
  Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Matt Ranostay, Lucas De Marchi,
	cmo@melexis.com, linux-iio@vger.kernel.org,
	srinivas.pandruvada@linux.intel.com, adi.reus@gmail.com

SGkgTWF0dCwNCglJIGFtIG5vdCBzdXJlIGFib3V0IHNsYXZlIDQuIEkgYWx3YXlzIHVzZSBzbGF2
ZTB+My4gTVBVNjA1MCBjYW4gY29ubmVjdCB1cCB0byA0IHNsYXZlcyBieSB1c2luZyBzbGF2ZSAw
fjMuIEhvd2V2ZXIsIHdlIG9ubHkgdXNlIDMgc2xhdmVzLiBFYWNoIHNsYXZlIGNhbiBiZSBjb25m
aWd1cmVkIGFzIHJlYWQgb3Igd3JpdGUgaW5kZXBlbmRlbnRseS4gRm9yIGV4YW1wbGUsIEFLTTg5
NzMgY29tcGFzcyBhcyBhIHNsYXZlLCBJIHVzdWFsbHkgY29uZmlndXJlIHNsYXZlMCBhcyByZWFk
IGFuZCBzbGF2ZSAxIGFzIHdyaXRlLiBUaGUgcmF0ZSBpcyAxMDBIeiwgZm9yIGV4YW1wbGUsIHRo
ZSByZWFkIHdpbGwgcmVhZCBmaXJzdCBhbmQgd3JpdGUgaGFwcGVucyBzdWJzZXF1ZW50bHkuIE9m
IGNvdXJzZSwgdGhlIHJlYWQgd2lsbCByZWFkIGEgZHVtbXkgZGF0YSBmb3IgdGhlIGZpcnN0IHRp
bWUuIEhvd2V2ZXIsIGFmdGVyIGZpcnN0IHJlYWQsIGl0IHdpbGwgcmVhZCB0aGUgY29ycmVjdCBk
YXRhLiBXcml0ZSB3aWxsIHNlbmQgQUtNIHRoZSBtZWFzdXJlIGNvbW1hbmQuIFRoZSBtZWFzdXJl
bWVudCB0YWtlcyBzZXZlcmFsIG1pbGktc2Vjb25kcyB0byBmaW5pc2guIFRoYXQgaXMgd2h5IHdl
IHJlYWQgbGlrZSB0aGF0Lg0KCUZvciBwcmVzc3VyZSBzZW5zb3Igb3IgQUxTKGxpZ2h0L3Byb3hp
bWl0eSBzZW5zb3IpLCB0aGV5IGFsbCBoYXZlIGF1dG9ub21vdXMgbW9kZS4gQXMgbG9uZyBhcyB0
aGUgc2FtcGxlIHBlcmlvZCBpcyBsb25nZXIgdGhhbiB0aGUgb3V0cHV0IHJhdGUsIHRoZSBkYXRh
IGlzIGd1YXJhbnRlZWQgdG8gYmUgbmV3IGRhdGEuDQoJVGhhbmtzLg0KDQpHZQ0KDQoNCi0tLS0t
T3JpZ2luYWwgTWVzc2FnZS0tLS0tDQpGcm9tOiBNYXR0IFJhbm9zdGF5IFttYWlsdG86bXJhbm9z
dGF5QGdtYWlsLmNvbV0gDQpTZW50OiBUaHVyc2RheSwgTWFyY2ggMTcsIDIwMTYgMTA6MjggQU0N
ClRvOiBEYW5pZWwgQmFsdXRhDQpDYzogSm9uYXRoYW4gQ2FtZXJvbjsgSGFydG11dCBLbmFhY2s7
IExhcnMtUGV0ZXIgQ2xhdXNlbjsgUGV0ZXIgTWVlcndhbGQtU3RhZGxlcjsgTWF0dCBSYW5vc3Rh
eTsgTHVjYXMgRGUgTWFyY2hpOyBjbW9AbWVsZXhpcy5jb207IGxpbnV4LWlpb0B2Z2VyLmtlcm5l
bC5vcmc7IEdlIEdhbzsgc3Jpbml2YXMucGFuZHJ1dmFkYUBsaW51eC5pbnRlbC5jb207IGFkaS5y
ZXVzQGdtYWlsLmNvbQ0KU3ViamVjdDogUmU6IFtQQVRDSCAzLzNdIGlpbzogaW11OiBtcHU2MDUw
OiBBZGQgc3VwcG9ydCBmb3IgYXV4aWxpYXJ5IEkyQyBtYXN0ZXINCg0KUmV2aWV3ZWQtYnk6IE1h
dHQgUmFub3N0YXkgPG1hdHQucmFub3N0YXlAaW50ZWwuY29tPg0KDQpPbiBUaHUsIE1hciAxNywg
MjAxNiBhdCA5OjMyIEFNLCBEYW5pZWwgQmFsdXRhIDxkYW5pZWwuYmFsdXRhQGludGVsLmNvbT4g
d3JvdGU6DQo+IFRoZSBNUFUtNjBYMCBbMV0gaGFzIGFuIGF1eGlsaWFyeSBJMkMgYnVzIGZvciBj
b25uZWN0aW5nIGV4dGVybmFsIA0KPiBzZW5zb3JzLiBUaGlzIGJ1cyBoYXMgdHdvIG9wZXJhdGlu
ZyBtb2RlczoNCj4gICAgICAgICAqIHBhc3MtdGhyb3VnaCwgd2hpY2ggY29ubmVjdHMgdGhlIHBy
aW1hcnkgYW5kIGF1eGlsaWFyeSBidXNzZXMNCj4gICAgICAgICB0b2dldGhlciBbYWxyZWFkeSBp
bXBsZW1lbnRlZF0NCj4gICAgICAgICAqIEkyQyBtYXN0ZXIgbW9kZSwgd2hlcmUgTVBVNjBYMCBh
Y3RzIGFzIGEgbWFzdGVyIHRvIGFueQ0KPiAgICAgICAgIGV4dGVybmFsIGNvbm5lY3RlZCBzZW5z
b3JzIFtpbXBsZW1lbnRlZCBpbiB0aGlzIHBhdGNoXQ0KPg0KPiBJMkMgbWFzdGVyIHN1cHBvcnRz
IHVwIHRvIDUgc2xhdmVzLiBTbGF2ZXMgMC0zIGhhdmUgYSBjb21tb24gb3BlcmF0aW5nIA0KPiBt
b2RlIHdoaWxlIHNsYXZlIDQgaXMgZGlmZmVyZW50Lg0KPg0KPiBUaGlzIHBhdGNoIG9ubHkgYWRk
cyBzdXBwb3J0IGZvciBzbGF2ZSA0IGJlY2F1c2UgaXQgaGFzIGEgY2xlYW5lciANCj4gaW50ZXJm
YWNlIGFuZCBpdCBoYXMgYW4gaW50ZXJydXB0IHRoYXQgc2lnbmFscyB3aGVuIGRhdGEgZnJvbSBz
bGF2ZSB0byANCj4gbWFzdGVyIGFycml2ZWQuDQo+DQo+IFJlZ2lzdGVycyBhcmUgZGVzY3JpYmVk
IGhlcmUgWzJdLg0KPg0KPiBXZSB1c2UgdGhyZWFkZWQgaGFuZGxlciBmb3IgcmVhZGluZyBzbGF2
ZTQgZG9uZSBpbnRlcnJ1cHQgYml0Lg0KPg0KPiBbMV0NCj4gaHR0cHM6Ly93d3cuY2Rpd2ViLmNv
bS9kYXRhc2hlZXRzL2ludmVuc2Vuc2UvTVBVLTYwNTBfRGF0YVNoZWV0X1YzJTIwNA0KPiAucGRm
DQo+IFsyXQ0KPiBodHRwOi8vd3d3Ni5pbi50dW0uZGUvcHViL01haW4vVGVhY2hpbmdXczIwMTVT
ZW1pbmFyQXVvbm9tb3VzRmFocmVuL1JNDQo+IC1NUFUtNjAwMEEucGRmDQo+DQo+IFNpZ25lZC1v
ZmYtYnk6IERhbmllbCBCYWx1dGEgPGRhbmllbC5iYWx1dGFAaW50ZWwuY29tPg0KPiAtLS0NCj4g
IGRyaXZlcnMvaWlvL2ltdS9pbnZfbXB1NjA1MC9pbnZfbXB1X2NvcmUuYyB8IDEzNyANCj4gKysr
KysrKysrKysrKysrKysrKysrKysrKysrKy0gIA0KPiBkcml2ZXJzL2lpby9pbXUvaW52X21wdTYw
NTAvaW52X21wdV9paW8uaCAgfCAgMzggKysrKysrKysNCj4gIDIgZmlsZXMgY2hhbmdlZCwgMTcy
IGluc2VydGlvbnMoKyksIDMgZGVsZXRpb25zKC0pDQo+DQo+IGRpZmYgLS1naXQgYS9kcml2ZXJz
L2lpby9pbXUvaW52X21wdTYwNTAvaW52X21wdV9jb3JlLmMgDQo+IGIvZHJpdmVycy9paW8vaW11
L2ludl9tcHU2MDUwL2ludl9tcHVfY29yZS5jDQo+IGluZGV4IDY1OWE0YmUuLmE4OTg1NGMgMTAw
NjQ0DQo+IC0tLSBhL2RyaXZlcnMvaWlvL2ltdS9pbnZfbXB1NjA1MC9pbnZfbXB1X2NvcmUuYw0K
PiArKysgYi9kcml2ZXJzL2lpby9pbXUvaW52X21wdTYwNTAvaW52X21wdV9jb3JlLmMNCj4gQEAg
LTI1LDYgKzI1LDggQEANCj4gICNpbmNsdWRlIDxsaW51eC9paW8vaWlvLmg+DQo+ICAjaW5jbHVk
ZSA8bGludXgvaTJjLW11eC5oPg0KPiAgI2luY2x1ZGUgPGxpbnV4L2FjcGkuaD4NCj4gKyNpbmNs
dWRlIDxsaW51eC9jb21wbGV0aW9uLmg+DQo+ICsNCj4gICNpbmNsdWRlICJpbnZfbXB1X2lpby5o
Ig0KPg0KPiAgLyoNCj4gQEAgLTU3LDYgKzU5LDEyIEBAIHN0YXRpYyBjb25zdCBzdHJ1Y3QgaW52
X21wdTYwNTBfcmVnX21hcCByZWdfc2V0XzY1MDAgPSB7DQo+ICAgICAgICAgLmludF9waW5fY2Zn
ICAgICAgICAgICAgPSBJTlZfTVBVNjA1MF9SRUdfSU5UX1BJTl9DRkcsDQo+ICAgICAgICAgLmFj
Y2xfb2Zmc2V0ICAgICAgICAgICAgPSBJTlZfTVBVNjUwMF9SRUdfQUNDRUxfT0ZGU0VULA0KPiAg
ICAgICAgIC5neXJvX29mZnNldCAgICAgICAgICAgID0gSU5WX01QVTYwNTBfUkVHX0dZUk9fT0ZG
U0VULA0KPiArICAgICAgIC5zbHY0X2FkZHIgICAgICAgICAgICAgID0gSU5WX01QVTYwNTBfUkVH
X0kyQ19TTFY0X0FERFIsDQo+ICsgICAgICAgLnNsdjRfcmVnICAgICAgICAgICAgICAgPSBJTlZf
TVBVNjA1MF9SRUdfSTJDX1NMVjRfUkVHLA0KPiArICAgICAgIC5zbHY0X2RvICAgICAgICAgICAg
ICAgID0gSU5WX01QVTYwNTBfUkVHX0kyQ19TTFY0X0RPLA0KPiArICAgICAgIC5zbHY0X2N0cmwg
ICAgICAgICAgICAgID0gSU5WX01QVTYwNTBfUkVHX0kyQ19TTFY0X0NUUkwsDQo+ICsgICAgICAg
LnNsdjRfZGkgICAgICAgICAgICAgICAgPSBJTlZfTVBVNjA1MF9SRUdfSTJDX1NMVjRfREksDQo+
ICsgICAgICAgLm1zdF9zdGF0dXMgICAgICAgICAgICAgPSBJTlZfTVBVNjA1MF9SRUdfSTJDX01T
VF9TVEFUVVMsDQo+ICB9Ow0KPg0KPiAgc3RhdGljIGNvbnN0IHN0cnVjdCBpbnZfbXB1NjA1MF9y
ZWdfbWFwIHJlZ19zZXRfNjA1MCA9IHsgQEAgLTc3LDYgDQo+ICs4NSwxMiBAQCBzdGF0aWMgY29u
c3Qgc3RydWN0IGludl9tcHU2MDUwX3JlZ19tYXAgcmVnX3NldF82MDUwID0gew0KPiAgICAgICAg
IC5pbnRfcGluX2NmZyAgICAgICAgICAgID0gSU5WX01QVTYwNTBfUkVHX0lOVF9QSU5fQ0ZHLA0K
PiAgICAgICAgIC5hY2NsX29mZnNldCAgICAgICAgICAgID0gSU5WX01QVTYwNTBfUkVHX0FDQ0VM
X09GRlNFVCwNCj4gICAgICAgICAuZ3lyb19vZmZzZXQgICAgICAgICAgICA9IElOVl9NUFU2MDUw
X1JFR19HWVJPX09GRlNFVCwNCj4gKyAgICAgICAuc2x2NF9hZGRyICAgICAgICAgICAgICA9IElO
Vl9NUFU2MDUwX1JFR19JMkNfU0xWNF9BRERSLA0KPiArICAgICAgIC5zbHY0X3JlZyAgICAgICAg
ICAgICAgID0gSU5WX01QVTYwNTBfUkVHX0kyQ19TTFY0X1JFRywNCj4gKyAgICAgICAuc2x2NF9k
byAgICAgICAgICAgICAgICA9IElOVl9NUFU2MDUwX1JFR19JMkNfU0xWNF9ETywNCj4gKyAgICAg
ICAuc2x2NF9jdHJsICAgICAgICAgICAgICA9IElOVl9NUFU2MDUwX1JFR19JMkNfU0xWNF9DVFJM
LA0KPiArICAgICAgIC5zbHY0X2RpICAgICAgICAgICAgICAgID0gSU5WX01QVTYwNTBfUkVHX0ky
Q19TTFY0X0RJLA0KPiArICAgICAgIC5tc3Rfc3RhdHVzICAgICAgICAgICAgID0gSU5WX01QVTYw
NTBfUkVHX0kyQ19NU1RfU1RBVFVTLA0KPiAgfTsNCj4NCj4gIHN0YXRpYyBjb25zdCBzdHJ1Y3Qg
aW52X21wdTYwNTBfY2hpcF9jb25maWcgY2hpcF9jb25maWdfNjA1MCA9IHsgQEAgDQo+IC03NjEs
NiArNzc1LDExNCBAQCBzdGF0aWMgaW50IGludl9jaGVja19hbmRfc2V0dXBfY2hpcChzdHJ1Y3Qg
aW52X21wdTYwNTBfc3RhdGUgKnN0KQ0KPiAgICAgICAgIHJldHVybiAwOw0KPiAgfQ0KPg0KPiAr
c3RhdGljIGlycXJldHVybl90IGludl9tcHVfZGF0YXJkeV9pcnFfaGFuZGxlcihpbnQgaXJxLCB2
b2lkIA0KPiArKnByaXZhdGUpIHsNCj4gKyAgICAgICBzdHJ1Y3QgaW52X21wdTYwNTBfc3RhdGUg
KnN0ID0gKHN0cnVjdCBpbnZfbXB1NjA1MF9zdGF0ZSANCj4gKyopcHJpdmF0ZTsNCj4gKw0KPiAr
ICAgICAgIGlpb190cmlnZ2VyX3BvbGwoc3QtPnRyaWcpOw0KPiArDQo+ICsgICAgICAgcmV0dXJu
IElSUV9XQUtFX1RIUkVBRDsNCj4gK30NCj4gKw0KPiArc3RhdGljIGlycXJldHVybl90IGludl9t
cHVfZGF0YXJkeV90aHJlYWRfaGFuZGxlcihpbnQgaXJxLCB2b2lkIA0KPiArKnByaXZhdGUpIHsN
Cj4gKyAgICAgICBzdHJ1Y3QgaW52X21wdTYwNTBfc3RhdGUgKnN0ID0gKHN0cnVjdCBpbnZfbXB1
NjA1MF9zdGF0ZSAqKXByaXZhdGU7DQo+ICsgICAgICAgaW50IHJldCwgdmFsOw0KPiArDQo+ICsg
ICAgICAgcmV0ID0gcmVnbWFwX3JlYWQoc3QtPm1hcCwgc3QtPnJlZy0+bXN0X3N0YXR1cywgJnZh
bCk7DQo+ICsgICAgICAgaWYgKHJldCA8IDApDQo+ICsgICAgICAgICAgICAgICByZXR1cm4gcmV0
Ow0KPiArDQo+ICsgICAgICAgaWYgKHZhbCAmIElOVl9NUFU2MDUwX0JJVF9JMkNfU0xWNF9ET05F
KQ0KPiArICAgICAgICAgICAgICAgY29tcGxldGUoJnN0LT5zbHY0X2RvbmUpOw0KPiArDQo+ICsg
ICAgICAgcmV0dXJuIElSUV9IQU5ETEVEOw0KPiArfQ0KPiArDQo+ICtzdGF0aWMgdTMyIGludl9t
cHVfaTJjX2Z1bmN0aW9uYWxpdHkoc3RydWN0IGkyY19hZGFwdGVyICphZGFwKSB7DQo+ICsgICAg
ICAgcmV0dXJuIEkyQ19GVU5DX1NNQlVTX0JZVEUgfCBJMkNfRlVOQ19TTUJVU19CWVRFX0RBVEE7
IH0NCj4gKw0KPiArc3RhdGljIGludA0KPiAraW52X21wdV9pMmNfc21idXNfeGZlcihzdHJ1Y3Qg
aTJjX2FkYXB0ZXIgKmFkYXAsIHUxNiBhZGRyLA0KPiArICAgICAgICAgICAgICAgICAgICAgIHVu
c2lnbmVkIHNob3J0IGZsYWdzLCBjaGFyIHJlYWRfd3JpdGUsIHU4IGNvbW1hbmQsDQo+ICsgICAg
ICAgICAgICAgICAgICAgICAgaW50IHNpemUsIHVuaW9uIGkyY19zbWJ1c19kYXRhICpkYXRhKSB7
DQo+ICsgICAgICAgc3RydWN0IGludl9tcHU2MDUwX3N0YXRlICpzdCA9IGkyY19nZXRfYWRhcGRh
dGEoYWRhcCk7DQo+ICsNCj4gKyAgICAgICB1bnNpZ25lZCBsb25nIHRpbWVfbGVmdDsNCj4gKyAg
ICAgICBpbnQgcmV0LCB2YWw7DQo+ICsgICAgICAgdTggY3RybDsNCj4gKw0KPiArICAgICAgIHJl
dCA9IGludl9tcHU2MDUwX3NldF9wb3dlcl9pdGcoc3QsIHRydWUpOw0KPiArICAgICAgIGlmIChy
ZXQgPCAwKQ0KPiArICAgICAgICAgICAgICAgcmV0dXJuIHJldDsNCj4gKw0KPiArICAgICAgIHJl
dCA9IHJlZ21hcF91cGRhdGVfYml0cyhzdC0+bWFwLCBzdC0+cmVnLT51c2VyX2N0cmwsDQo+ICsg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIElOVl9NUFU2MDUwX0JJVF9JMkNfTVNUX0VO
LA0KPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJTlZfTVBVNjA1MF9CSVRfSTJD
X01TVF9FTik7DQo+ICsgICAgICAgaWYgKHJldCA8IDApDQo+ICsgICAgICAgICAgICAgICByZXR1
cm4gcmV0Ow0KPiArDQo+ICsgICAgICAgcmV0ID0gcmVnbWFwX3VwZGF0ZV9iaXRzKHN0LT5tYXAs
IHN0LT5yZWctPmludF9lbmFibGUsDQo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
IElOVl9NUFU2MDUwX0JJVF9NU1RfSU5UX0VOLA0KPiArICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICBJTlZfTVBVNjA1MF9CSVRfTVNUX0lOVF9FTik7DQo+ICsgICAgICAgaWYgKHJldCA8
IDApDQo+ICsgICAgICAgICAgICAgICByZXR1cm4gcmV0Ow0KPiArDQo+ICsgICAgICAgaWYgKHJl
YWRfd3JpdGUgPT0gSTJDX1NNQlVTX1dSSVRFKQ0KPiArICAgICAgICAgICAgICAgYWRkciB8PSBJ
TlZfTVBVNjA1MF9CSVRfSTJDX1NMVjRfVzsNCj4gKyAgICAgICBlbHNlDQo+ICsgICAgICAgICAg
ICAgICBhZGRyIHw9IElOVl9NUFU2MDUwX0JJVF9JMkNfU0xWNF9SOw0KPiArDQo+ICsgICAgICAg
cmV0ID0gcmVnbWFwX3dyaXRlKHN0LT5tYXAsIHN0LT5yZWctPnNsdjRfYWRkciwgYWRkcik7DQo+
ICsgICAgICAgaWYgKHJldCA8IDApDQo+ICsgICAgICAgICAgICAgICByZXR1cm4gcmV0Ow0KPiAr
DQo+ICsgICAgICAgcmV0ID0gcmVnbWFwX3dyaXRlKHN0LT5tYXAsIHN0LT5yZWctPnNsdjRfcmVn
LCBjb21tYW5kKTsNCj4gKyAgICAgICBpZiAocmV0IDwgMCkNCj4gKyAgICAgICAgICAgICAgIHJl
dHVybiByZXQ7DQo+ICsNCj4gKyAgICAgICBpZiAocmVhZF93cml0ZSA9PSBJMkNfU01CVVNfV1JJ
VEUpIHsNCj4gKyAgICAgICAgICAgICAgIHJldCA9IHJlZ21hcF93cml0ZShzdC0+bWFwLCBzdC0+
cmVnLT5zbHY0X2RvLCBkYXRhLT5ieXRlKTsNCj4gKyAgICAgICAgICAgICAgIGlmIChyZXQgPCAw
KQ0KPiArICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmV0Ow0KPiArICAgICAgIH0NCj4g
Kw0KPiArICAgICAgIGN0cmwgPSBJTlZfTVBVNjA1MF9CSVRfU0xWNF9FTiB8IElOVl9NUFU2MDUw
X0JJVF9TTFY0X0lOVF9FTjsNCj4gKyAgICAgICByZXQgPSByZWdtYXBfd3JpdGUoc3QtPm1hcCwg
c3QtPnJlZy0+c2x2NF9jdHJsLCBjdHJsKTsNCj4gKyAgICAgICBpZiAocmV0IDwgMCkNCj4gKyAg
ICAgICAgICAgICAgIHJldHVybiByZXQ7DQo+ICsgICAgICAgaWYgKHJlYWRfd3JpdGUgPT0gSTJD
X1NNQlVTX1JFQUQpIHsNCj4gKyAgICAgICAgICAgICAgIHRpbWVfbGVmdCA9IHdhaXRfZm9yX2Nv
bXBsZXRpb25fdGltZW91dCgmc3QtPnNsdjRfZG9uZSwgSFopOw0KPiArICAgICAgICAgICAgICAg
aWYgKCF0aW1lX2xlZnQpDQo+ICsgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAtRVRJTUVE
T1VUOw0KPiArDQo+ICsgICAgICAgICAgICAgICByZXQgPSByZWdtYXBfcmVhZChzdC0+bWFwLCBz
dC0+cmVnLT5zbHY0X2RpLCAmdmFsKTsNCj4gKyAgICAgICAgICAgICAgIGlmIChyZXQgPCAwKQ0K
PiArICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmV0Ow0KPiArICAgICAgICAgICAgICAg
ZGF0YS0+Ynl0ZSA9IHZhbDsNCj4gKyAgICAgICB9DQo+ICsNCj4gKyAgICAgICByZXQgPSBpbnZf
bXB1NjA1MF9zZXRfcG93ZXJfaXRnKHN0LCBmYWxzZSk7DQo+ICsgICAgICAgaWYgKHJldCA8IDAp
DQo+ICsgICAgICAgICAgICAgICByZXR1cm4gcmV0Ow0KPiArICAgICAgIHJldHVybiAwOw0KPiAr
fQ0KPiArDQo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGkyY19hbGdvcml0aG0gaW52X21wdV9pMmNf
YWxnbyA9IHsNCj4gKyAgICAgICAuc21idXNfeGZlciAgICAgPSAgICAgICBpbnZfbXB1X2kyY19z
bWJ1c194ZmVyLA0KPiArICAgICAgIC5mdW5jdGlvbmFsaXR5ICA9ICAgICAgIGludl9tcHVfaTJj
X2Z1bmN0aW9uYWxpdHksDQo+ICt9Ow0KPiArDQo+ICtzdGF0aWMgc3RydWN0IGkyY19hZGFwdGVy
IGludl9tcHVfaTJjX2FkYXB0ZXIgPSB7DQo+ICsgICAgICAgLm93bmVyICAgICAgICAgID0gVEhJ
U19NT0RVTEUsDQo+ICsgICAgICAgLmNsYXNzICAgICAgICAgID0gSTJDX0NMQVNTX0hXTU9OLA0K
PiArICAgICAgIC5hbGdvICAgICAgICAgICA9ICZpbnZfbXB1X2kyY19hbGdvLA0KPiArICAgICAg
IC5uYW1lICAgICAgICAgICA9ICJJTlYgTVBVIHNlY29uZGFyeSBJMkMiLA0KPiArfTsNCj4gKw0K
PiAgaW50IGludl9tcHVfY29yZV9wcm9iZShzdHJ1Y3QgcmVnbWFwICpyZWdtYXAsIGludCBpcnEs
IGNvbnN0IGNoYXIgKm5hbWUsDQo+ICAgICAgICAgICAgICAgICBpbnQgKCppbnZfbXB1X2J1c19z
ZXR1cCkoc3RydWN0IGlpb19kZXYgKiksIGludCANCj4gY2hpcF90eXBlKSAgeyBAQCAtNzk2LDYg
KzkxOCwxMyBAQCBpbnQgaW52X21wdV9jb3JlX3Byb2JlKHN0cnVjdCANCj4gcmVnbWFwICpyZWdt
YXAsIGludCBpcnEsIGNvbnN0IGNoYXIgKm5hbWUsDQo+ICAgICAgICAgICAgICAgICByZXR1cm4g
cmVzdWx0Ow0KPiAgICAgICAgIH0NCj4NCj4gKyAgICAgICBpbml0X2NvbXBsZXRpb24oJnN0LT5z
bHY0X2RvbmUpOw0KPiArDQo+ICsgICAgICAgcmVzdWx0ID0gaTJjX2FkZF9hZGFwdGVyKCZpbnZf
bXB1X2kyY19hZGFwdGVyKTsNCj4gKyAgICAgICBpZiAocmVzdWx0IDwgMCkNCj4gKyAgICAgICAg
ICAgICAgIHJldHVybiByZXN1bHQ7DQo+ICsNCj4gKyAgICAgICBpMmNfc2V0X2FkYXBkYXRhKCZp
bnZfbXB1X2kyY19hZGFwdGVyLCBzdCk7DQo+ICAgICAgICAgZGV2X3NldF9kcnZkYXRhKGRldiwg
aW5kaW9fZGV2KTsNCj4gICAgICAgICBpbmRpb19kZXYtPmRldi5wYXJlbnQgPSBkZXY7DQo+ICAg
ICAgICAgLyogbmFtZSB3aWxsIGJlIE5VTEwgd2hlbiBlbnVtZXJhdGVkIHZpYSBBQ1BJICovIEBA
IC04MjMsOSANCj4gKzk1MiwxMSBAQCBpbnQgaW52X21wdV9jb3JlX3Byb2JlKHN0cnVjdCByZWdt
YXAgKnJlZ21hcCwgaW50IGlycSwgY29uc3QgY2hhciAqbmFtZSwNCj4gICAgICAgICAgICAgICAg
IGdvdG8gb3V0X3VucmVnX3Jpbmc7DQo+ICAgICAgICAgfQ0KPg0KPiAtICAgICAgIHJlc3VsdCA9
IGRldm1fcmVxdWVzdF9pcnEoJmluZGlvX2Rldi0+ZGV2LCBzdC0+aXJxLA0KPiAtICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgJmlpb190cmlnZ2VyX2dlbmVyaWNfZGF0YV9yZHlfcG9s
bCwNCj4gLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIElSUUZfVFJJR0dFUl9SSVNJ
TkcsICJpbnZfbXB1Iiwgc3QtPnRyaWcpOw0KPiArICAgICAgIHJlc3VsdCA9IGRldm1fcmVxdWVz
dF90aHJlYWRlZF9pcnEoJmluZGlvX2Rldi0+ZGV2LCBzdC0+aXJxLA0KPiArICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJmludl9tcHVfZGF0YXJkeV9pcnFfaGFuZGxl
ciwNCj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICZpbnZfbXB1
X2RhdGFyZHlfdGhyZWFkX2hhbmRsZXIsDQo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICBJUlFGX1RSSUdHRVJfUklTSU5HLCAiaW52X21wdSIsDQo+ICsgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdCk7DQo+ICAgICAgICAgaWYgKHJl
c3VsdCkgew0KPiAgICAgICAgICAgICAgICAgZGV2X2VycihkZXYsICJyZXF1ZXN0IGlycSBmYWls
ICVkXG4iLCByZXN1bHQpOw0KPiAgICAgICAgICAgICAgICAgZ290byBvdXRfcmVtb3ZlX3RyaWdn
ZXI7IGRpZmYgLS1naXQgDQo+IGEvZHJpdmVycy9paW8vaW11L2ludl9tcHU2MDUwL2ludl9tcHVf
aWlvLmggDQo+IGIvZHJpdmVycy9paW8vaW11L2ludl9tcHU2MDUwL2ludl9tcHVfaWlvLmgNCj4g
aW5kZXggZTMwMmE0OS4uNWMzZWE5YSAxMDA2NDQNCj4gLS0tIGEvZHJpdmVycy9paW8vaW11L2lu
dl9tcHU2MDUwL2ludl9tcHVfaWlvLmgNCj4gKysrIGIvZHJpdmVycy9paW8vaW11L2ludl9tcHU2
MDUwL2ludl9tcHVfaWlvLmgNCj4gQEAgLTQyLDYgKzQyLDEzIEBADQo+ICAgKiAgQGludF9waW5f
Y2ZnOyAgICAgIENvbnRyb2xzIGludGVycnVwdCBwaW4gY29uZmlndXJhdGlvbi4NCj4gICAqICBA
YWNjbF9vZmZzZXQ6ICAgICAgQ29udHJvbHMgdGhlIGFjY2VsZXJvbWV0ZXIgY2FsaWJyYXRpb24g
b2Zmc2V0Lg0KPiAgICogIEBneXJvX29mZnNldDogICAgICBDb250cm9scyB0aGUgZ3lyb3Njb3Bl
IGNhbGlicmF0aW9uIG9mZnNldC4NCj4gKyAqICBAbXN0X3N0YXR1czogICAgICAgc2Vjb25kYXJ5
IEkyQyBtYXN0ZXIgaW50ZXJydXB0IHNvdXJjZSBzdGF0dXMNCj4gKyAqICBAc2x2NF9hZGRyOiAg
ICAgICAgICAgICAgICBJMkMgc2xhdmUgYWRkcmVzcyBmb3Igc2xhdmUgNCB0cmFuc2FjdGlvbg0K
PiArICogIEBzbHY0X3JlZzogICAgICAgICBJMkMgcmVnaXN0ZXIgdXNlZCB3aXRoIHNsYXZlIDQg
dHJhbnNhY3Rpb24NCj4gKyAqICBAc2x2NF9kaTogICAgICAgICAgSTJDIGRhdGEgaW4gcmVnaXN0
ZXIgZm9yIHNsYXZlIDQgdHJhbnNhY3Rpb24NCj4gKyAqICBAc2x2NF9jdHJsOiAgICAgICAgICAg
ICAgICBJMkMgc2xhdmUgNCBjb250cm9sIHJlZ2lzdGVyDQo+ICsgKiAgQHNsdjRfZG86ICAgICAg
ICAgIEkyQyBkYXRhIG91dCByZWdpc3RlciBmb3Igc2xhdmUgNCB0cmFuc2FjdGlvbg0KPiArDQo+
ICAgKi8NCj4gIHN0cnVjdCBpbnZfbXB1NjA1MF9yZWdfbWFwIHsNCj4gICAgICAgICB1OCBzYW1w
bGVfcmF0ZV9kaXY7DQo+IEBAIC02MSw2ICs2OCwxNSBAQCBzdHJ1Y3QgaW52X21wdTYwNTBfcmVn
X21hcCB7DQo+ICAgICAgICAgdTggaW50X3Bpbl9jZmc7DQo+ICAgICAgICAgdTggYWNjbF9vZmZz
ZXQ7DQo+ICAgICAgICAgdTggZ3lyb19vZmZzZXQ7DQo+ICsgICAgICAgdTggbXN0X3N0YXR1czsN
Cj4gKw0KPiArICAgICAgIC8qIHNsYXZlIDQgcmVnaXN0ZXJzICovDQo+ICsgICAgICAgdTggc2x2
NF9hZGRyOw0KPiArICAgICAgIHU4IHNsdjRfcmVnOw0KPiArICAgICAgIHU4IHNsdjRfZGk7IC8q
IGRhdGEgaW4gKi8NCj4gKyAgICAgICB1OCBzbHY0X2N0cmw7DQo+ICsgICAgICAgdTggc2x2NF9k
bzsgLyogZGF0YSBvdXQgKi8NCj4gKw0KPiAgfTsNCj4NCj4gIC8qZGV2aWNlIGVudW0gKi8NCj4g
QEAgLTEzMyw2ICsxNDksNyBAQCBzdHJ1Y3QgaW52X21wdTYwNTBfc3RhdGUgew0KPiAgICAgICAg
IHN0cnVjdCBpbnZfbXB1NjA1MF9wbGF0Zm9ybV9kYXRhIHBsYXRfZGF0YTsNCj4gICAgICAgICBE
RUNMQVJFX0tGSUZPKHRpbWVzdGFtcHMsIGxvbmcgbG9uZywgVElNRVNUQU1QX0ZJRk9fU0laRSk7
DQo+ICAgICAgICAgc3RydWN0IHJlZ21hcCAqbWFwOw0KPiArICAgICAgIHN0cnVjdCBjb21wbGV0
aW9uIHNsdjRfZG9uZTsNCj4gICAgICAgICBpbnQgaXJxOw0KPiAgfTsNCj4NCj4gQEAgLTE0OSw5
ICsxNjYsMzAgQEAgc3RydWN0IGludl9tcHU2MDUwX3N0YXRlIHsNCj4gICNkZWZpbmUgSU5WX01Q
VTYwNTBfQklUX0FDQ0VMX09VVCAgICAgICAgICAgMHgwOA0KPiAgI2RlZmluZSBJTlZfTVBVNjA1
MF9CSVRTX0dZUk9fT1VUICAgICAgICAgICAweDcwDQo+DQo+ICsjZGVmaW5lIElOVl9NUFU2MDUw
X1JFR19JMkNfU0xWNF9BRERSICAgICAgIDB4MzENCj4gKyNkZWZpbmUgSU5WX01QVTYwNTBfQklU
X0kyQ19TTFY0X1IgICAgICAgICAgMHg4MA0KPiArI2RlZmluZSBJTlZfTVBVNjA1MF9CSVRfSTJD
X1NMVjRfVyAgICAgICAgICAweDAwDQo+ICsNCj4gKyNkZWZpbmUgSU5WX01QVTYwNTBfUkVHX0ky
Q19TTFY0X1JFRyAgICAgICAgMHgzMg0KPiArI2RlZmluZSBJTlZfTVBVNjA1MF9SRUdfSTJDX1NM
VjRfRE8gICAgICAgICAweDMzDQo+ICsjZGVmaW5lIElOVl9NUFU2MDUwX1JFR19JMkNfU0xWNF9D
VFJMICAgICAgIDB4MzQNCj4gKw0KPiArI2RlZmluZSBJTlZfTVBVNjA1MF9CSVRfU0xWNF9FTiAg
ICAgICAgICAgICAweDgwDQo+ICsjZGVmaW5lIElOVl9NUFU2MDUwX0JJVF9TTFY0X0lOVF9FTiAg
ICAgICAgIDB4NDANCj4gKyNkZWZpbmUgSU5WX01QVTYwNTBfQklUX1NMVjRfRElTICAgICAgICAg
ICAgMHgyMA0KPiArDQo+ICsjZGVmaW5lIElOVl9NUFU2MDUwX1JFR19JMkNfU0xWNF9ESSAgICAg
ICAgIDB4MzUNCj4gKw0KPiArI2RlZmluZSBJTlZfTVBVNjA1MF9SRUdfSTJDX01TVF9TVEFUVVMg
ICAgICAweDM2DQo+ICsjZGVmaW5lIElOVl9NUFU2MDUwX0JJVF9JMkNfU0xWNF9ET05FICAgICAg
IDB4NDANCj4gKw0KPiAgI2RlZmluZSBJTlZfTVBVNjA1MF9SRUdfSU5UX0VOQUJMRSAgICAgICAg
ICAweDM4DQo+ICAjZGVmaW5lIElOVl9NUFU2MDUwX0JJVF9EQVRBX1JEWV9FTiAgICAgICAgIDB4
MDENCj4gICNkZWZpbmUgSU5WX01QVTYwNTBfQklUX0RNUF9JTlRfRU4gICAgICAgICAgMHgwMg0K
PiArI2RlZmluZSBJTlZfTVBVNjA1MF9CSVRfTVNUX0lOVF9FTiAgICAgICAgICAweDA4DQo+ICsN
Cj4gKyNkZWZpbmUgSU5WX01QVTYwNTBfUkVHX0lOVF9TVEFUVVMgICAgICAgICAgMHgzQQ0KPiAr
I2RlZmluZSBJTlZfTVBVNjA1MF9CSVRfTVNUX0lOVCAgICAgICAgICAgICAweDA4DQo+DQo+ICAj
ZGVmaW5lIElOVl9NUFU2MDUwX1JFR19SQVdfQUNDRUwgICAgICAgICAgIDB4M0INCj4gICNkZWZp
bmUgSU5WX01QVTYwNTBfUkVHX1RFTVBFUkFUVVJFICAgICAgICAgMHg0MQ0KPiAtLQ0KPiAyLjUu
MA0KPg0KPiAtLQ0KPiBUbyB1bnN1YnNjcmliZSBmcm9tIHRoaXMgbGlzdDogc2VuZCB0aGUgbGlu
ZSAidW5zdWJzY3JpYmUgbGludXgtaWlvIiANCj4gaW4gdGhlIGJvZHkgb2YgYSBtZXNzYWdlIHRv
IG1ham9yZG9tb0B2Z2VyLmtlcm5lbC5vcmcgTW9yZSBtYWpvcmRvbW8gDQo+IGluZm8gYXQgIGh0
dHA6Ly92Z2VyLmtlcm5lbC5vcmcvbWFqb3Jkb21vLWluZm8uaHRtbA0K

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

* Re: [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C master
  2016-03-17 18:11     ` Ge Gao
@ 2016-03-17 18:13       ` Matt Ranostay
  2016-03-17 21:15       ` De Marchi, Lucas
  2016-03-20 10:54       ` Jonathan Cameron
  2 siblings, 0 replies; 16+ messages in thread
From: Matt Ranostay @ 2016-03-17 18:13 UTC (permalink / raw)
  To: Ge Gao
  Cc: Daniel Baluta, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Matt Ranostay,
	Lucas De Marchi, cmo@melexis.com, linux-iio@vger.kernel.org,
	srinivas.pandruvada@linux.intel.com, adi.reus@gmail.com

On Thu, Mar 17, 2016 at 11:11 AM, Ge Gao <GGao@invensense.com> wrote:
> Hi Matt,

You probably mean to direct this at Daniel :)

>         I am not sure about slave 4. I always use slave0~3. MPU6050 can c=
onnect up to 4 slaves by using slave 0~3. However, we only use 3 slaves. Ea=
ch slave can be configured as read or write independently. For example, AKM=
8973 compass as a slave, I usually configure slave0 as read and slave 1 as =
write. The rate is 100Hz, for example, the read will read first and write h=
appens subsequently. Of course, the read will read a dummy data for the fir=
st time. However, after first read, it will read the correct data. Write wi=
ll send AKM the measure command. The measurement takes several mili-seconds=
 to finish. That is why we read like that.
>         For pressure sensor or ALS(light/proximity sensor), they all have=
 autonomous mode. As long as the sample period is longer than the output ra=
te, the data is guaranteed to be new data.
>         Thanks.
>
> Ge
>
>
> -----Original Message-----
> From: Matt Ranostay [mailto:mranostay@gmail.com]
> Sent: Thursday, March 17, 2016 10:28 AM
> To: Daniel Baluta
> Cc: Jonathan Cameron; Hartmut Knaack; Lars-Peter Clausen; Peter Meerwald-=
Stadler; Matt Ranostay; Lucas De Marchi; cmo@melexis.com; linux-iio@vger.ke=
rnel.org; Ge Gao; srinivas.pandruvada@linux.intel.com; adi.reus@gmail.com
> Subject: Re: [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C=
 master
>
> Reviewed-by: Matt Ranostay <matt.ranostay@intel.com>
>
> On Thu, Mar 17, 2016 at 9:32 AM, Daniel Baluta <daniel.baluta@intel.com> =
wrote:
>> The MPU-60X0 [1] has an auxiliary I2C bus for connecting external
>> sensors. This bus has two operating modes:
>>         * pass-through, which connects the primary and auxiliary busses
>>         together [already implemented]
>>         * I2C master mode, where MPU60X0 acts as a master to any
>>         external connected sensors [implemented in this patch]
>>
>> I2C master supports up to 5 slaves. Slaves 0-3 have a common operating
>> mode while slave 4 is different.
>>
>> This patch only adds support for slave 4 because it has a cleaner
>> interface and it has an interrupt that signals when data from slave to
>> master arrived.
>>
>> Registers are described here [2].
>>
>> We use threaded handler for reading slave4 done interrupt bit.
>>
>> [1]
>> https://www.cdiweb.com/datasheets/invensense/MPU-6050_DataSheet_V3%204
>> .pdf
>> [2]
>> http://www6.in.tum.de/pub/Main/TeachingWs2015SeminarAuonomousFahren/RM
>> -MPU-6000A.pdf
>>
>> Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
>> ---
>>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 137
>> ++++++++++++++++++++++++++++-
>> drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  |  38 ++++++++
>>  2 files changed, 172 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
>> b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
>> index 659a4be..a89854c 100644
>> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
>> @@ -25,6 +25,8 @@
>>  #include <linux/iio/iio.h>
>>  #include <linux/i2c-mux.h>
>>  #include <linux/acpi.h>
>> +#include <linux/completion.h>
>> +
>>  #include "inv_mpu_iio.h"
>>
>>  /*
>> @@ -57,6 +59,12 @@ static const struct inv_mpu6050_reg_map reg_set_6500 =
=3D {
>>         .int_pin_cfg            =3D INV_MPU6050_REG_INT_PIN_CFG,
>>         .accl_offset            =3D INV_MPU6500_REG_ACCEL_OFFSET,
>>         .gyro_offset            =3D INV_MPU6050_REG_GYRO_OFFSET,
>> +       .slv4_addr              =3D INV_MPU6050_REG_I2C_SLV4_ADDR,
>> +       .slv4_reg               =3D INV_MPU6050_REG_I2C_SLV4_REG,
>> +       .slv4_do                =3D INV_MPU6050_REG_I2C_SLV4_DO,
>> +       .slv4_ctrl              =3D INV_MPU6050_REG_I2C_SLV4_CTRL,
>> +       .slv4_di                =3D INV_MPU6050_REG_I2C_SLV4_DI,
>> +       .mst_status             =3D INV_MPU6050_REG_I2C_MST_STATUS,
>>  };
>>
>>  static const struct inv_mpu6050_reg_map reg_set_6050 =3D { @@ -77,6
>> +85,12 @@ static const struct inv_mpu6050_reg_map reg_set_6050 =3D {
>>         .int_pin_cfg            =3D INV_MPU6050_REG_INT_PIN_CFG,
>>         .accl_offset            =3D INV_MPU6050_REG_ACCEL_OFFSET,
>>         .gyro_offset            =3D INV_MPU6050_REG_GYRO_OFFSET,
>> +       .slv4_addr              =3D INV_MPU6050_REG_I2C_SLV4_ADDR,
>> +       .slv4_reg               =3D INV_MPU6050_REG_I2C_SLV4_REG,
>> +       .slv4_do                =3D INV_MPU6050_REG_I2C_SLV4_DO,
>> +       .slv4_ctrl              =3D INV_MPU6050_REG_I2C_SLV4_CTRL,
>> +       .slv4_di                =3D INV_MPU6050_REG_I2C_SLV4_DI,
>> +       .mst_status             =3D INV_MPU6050_REG_I2C_MST_STATUS,
>>  };
>>
>>  static const struct inv_mpu6050_chip_config chip_config_6050 =3D { @@
>> -761,6 +775,114 @@ static int inv_check_and_setup_chip(struct inv_mpu605=
0_state *st)
>>         return 0;
>>  }
>>
>> +static irqreturn_t inv_mpu_datardy_irq_handler(int irq, void
>> +*private) {
>> +       struct inv_mpu6050_state *st =3D (struct inv_mpu6050_state
>> +*)private;
>> +
>> +       iio_trigger_poll(st->trig);
>> +
>> +       return IRQ_WAKE_THREAD;
>> +}
>> +
>> +static irqreturn_t inv_mpu_datardy_thread_handler(int irq, void
>> +*private) {
>> +       struct inv_mpu6050_state *st =3D (struct inv_mpu6050_state *)pri=
vate;
>> +       int ret, val;
>> +
>> +       ret =3D regmap_read(st->map, st->reg->mst_status, &val);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       if (val & INV_MPU6050_BIT_I2C_SLV4_DONE)
>> +               complete(&st->slv4_done);
>> +
>> +       return IRQ_HANDLED;
>> +}
>> +
>> +static u32 inv_mpu_i2c_functionality(struct i2c_adapter *adap) {
>> +       return I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA; }
>> +
>> +static int
>> +inv_mpu_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr,
>> +                      unsigned short flags, char read_write, u8 command=
,
>> +                      int size, union i2c_smbus_data *data) {
>> +       struct inv_mpu6050_state *st =3D i2c_get_adapdata(adap);
>> +
>> +       unsigned long time_left;
>> +       int ret, val;
>> +       u8 ctrl;
>> +
>> +       ret =3D inv_mpu6050_set_power_itg(st, true);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       ret =3D regmap_update_bits(st->map, st->reg->user_ctrl,
>> +                                INV_MPU6050_BIT_I2C_MST_EN,
>> +                                INV_MPU6050_BIT_I2C_MST_EN);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       ret =3D regmap_update_bits(st->map, st->reg->int_enable,
>> +                                INV_MPU6050_BIT_MST_INT_EN,
>> +                                INV_MPU6050_BIT_MST_INT_EN);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       if (read_write =3D=3D I2C_SMBUS_WRITE)
>> +               addr |=3D INV_MPU6050_BIT_I2C_SLV4_W;
>> +       else
>> +               addr |=3D INV_MPU6050_BIT_I2C_SLV4_R;
>> +
>> +       ret =3D regmap_write(st->map, st->reg->slv4_addr, addr);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       ret =3D regmap_write(st->map, st->reg->slv4_reg, command);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       if (read_write =3D=3D I2C_SMBUS_WRITE) {
>> +               ret =3D regmap_write(st->map, st->reg->slv4_do, data->by=
te);
>> +               if (ret < 0)
>> +                       return ret;
>> +       }
>> +
>> +       ctrl =3D INV_MPU6050_BIT_SLV4_EN | INV_MPU6050_BIT_SLV4_INT_EN;
>> +       ret =3D regmap_write(st->map, st->reg->slv4_ctrl, ctrl);
>> +       if (ret < 0)
>> +               return ret;
>> +       if (read_write =3D=3D I2C_SMBUS_READ) {
>> +               time_left =3D wait_for_completion_timeout(&st->slv4_done=
, HZ);
>> +               if (!time_left)
>> +                       return -ETIMEDOUT;
>> +
>> +               ret =3D regmap_read(st->map, st->reg->slv4_di, &val);
>> +               if (ret < 0)
>> +                       return ret;
>> +               data->byte =3D val;
>> +       }
>> +
>> +       ret =3D inv_mpu6050_set_power_itg(st, false);
>> +       if (ret < 0)
>> +               return ret;
>> +       return 0;
>> +}
>> +
>> +static const struct i2c_algorithm inv_mpu_i2c_algo =3D {
>> +       .smbus_xfer     =3D       inv_mpu_i2c_smbus_xfer,
>> +       .functionality  =3D       inv_mpu_i2c_functionality,
>> +};
>> +
>> +static struct i2c_adapter inv_mpu_i2c_adapter =3D {
>> +       .owner          =3D THIS_MODULE,
>> +       .class          =3D I2C_CLASS_HWMON,
>> +       .algo           =3D &inv_mpu_i2c_algo,
>> +       .name           =3D "INV MPU secondary I2C",
>> +};
>> +
>>  int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name=
,
>>                 int (*inv_mpu_bus_setup)(struct iio_dev *), int
>> chip_type)  { @@ -796,6 +918,13 @@ int inv_mpu_core_probe(struct
>> regmap *regmap, int irq, const char *name,
>>                 return result;
>>         }
>>
>> +       init_completion(&st->slv4_done);
>> +
>> +       result =3D i2c_add_adapter(&inv_mpu_i2c_adapter);
>> +       if (result < 0)
>> +               return result;
>> +
>> +       i2c_set_adapdata(&inv_mpu_i2c_adapter, st);
>>         dev_set_drvdata(dev, indio_dev);
>>         indio_dev->dev.parent =3D dev;
>>         /* name will be NULL when enumerated via ACPI */ @@ -823,9
>> +952,11 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const =
char *name,
>>                 goto out_unreg_ring;
>>         }
>>
>> -       result =3D devm_request_irq(&indio_dev->dev, st->irq,
>> -                                 &iio_trigger_generic_data_rdy_poll,
>> -                                 IRQF_TRIGGER_RISING, "inv_mpu", st->tr=
ig);
>> +       result =3D devm_request_threaded_irq(&indio_dev->dev, st->irq,
>> +                                          &inv_mpu_datardy_irq_handler,
>> +                                          &inv_mpu_datardy_thread_handl=
er,
>> +                                          IRQF_TRIGGER_RISING, "inv_mpu=
",
>> +                                          st);
>>         if (result) {
>>                 dev_err(dev, "request irq fail %d\n", result);
>>                 goto out_remove_trigger; diff --git
>> a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>> b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>> index e302a49..5c3ea9a 100644
>> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>> @@ -42,6 +42,13 @@
>>   *  @int_pin_cfg;      Controls interrupt pin configuration.
>>   *  @accl_offset:      Controls the accelerometer calibration offset.
>>   *  @gyro_offset:      Controls the gyroscope calibration offset.
>> + *  @mst_status:       secondary I2C master interrupt source status
>> + *  @slv4_addr:                I2C slave address for slave 4 transactio=
n
>> + *  @slv4_reg:         I2C register used with slave 4 transaction
>> + *  @slv4_di:          I2C data in register for slave 4 transaction
>> + *  @slv4_ctrl:                I2C slave 4 control register
>> + *  @slv4_do:          I2C data out register for slave 4 transaction
>> +
>>   */
>>  struct inv_mpu6050_reg_map {
>>         u8 sample_rate_div;
>> @@ -61,6 +68,15 @@ struct inv_mpu6050_reg_map {
>>         u8 int_pin_cfg;
>>         u8 accl_offset;
>>         u8 gyro_offset;
>> +       u8 mst_status;
>> +
>> +       /* slave 4 registers */
>> +       u8 slv4_addr;
>> +       u8 slv4_reg;
>> +       u8 slv4_di; /* data in */
>> +       u8 slv4_ctrl;
>> +       u8 slv4_do; /* data out */
>> +
>>  };
>>
>>  /*device enum */
>> @@ -133,6 +149,7 @@ struct inv_mpu6050_state {
>>         struct inv_mpu6050_platform_data plat_data;
>>         DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
>>         struct regmap *map;
>> +       struct completion slv4_done;
>>         int irq;
>>  };
>>
>> @@ -149,9 +166,30 @@ struct inv_mpu6050_state {
>>  #define INV_MPU6050_BIT_ACCEL_OUT           0x08
>>  #define INV_MPU6050_BITS_GYRO_OUT           0x70
>>
>> +#define INV_MPU6050_REG_I2C_SLV4_ADDR       0x31
>> +#define INV_MPU6050_BIT_I2C_SLV4_R          0x80
>> +#define INV_MPU6050_BIT_I2C_SLV4_W          0x00
>> +
>> +#define INV_MPU6050_REG_I2C_SLV4_REG        0x32
>> +#define INV_MPU6050_REG_I2C_SLV4_DO         0x33
>> +#define INV_MPU6050_REG_I2C_SLV4_CTRL       0x34
>> +
>> +#define INV_MPU6050_BIT_SLV4_EN             0x80
>> +#define INV_MPU6050_BIT_SLV4_INT_EN         0x40
>> +#define INV_MPU6050_BIT_SLV4_DIS            0x20
>> +
>> +#define INV_MPU6050_REG_I2C_SLV4_DI         0x35
>> +
>> +#define INV_MPU6050_REG_I2C_MST_STATUS      0x36
>> +#define INV_MPU6050_BIT_I2C_SLV4_DONE       0x40
>> +
>>  #define INV_MPU6050_REG_INT_ENABLE          0x38
>>  #define INV_MPU6050_BIT_DATA_RDY_EN         0x01
>>  #define INV_MPU6050_BIT_DMP_INT_EN          0x02
>> +#define INV_MPU6050_BIT_MST_INT_EN          0x08
>> +
>> +#define INV_MPU6050_REG_INT_STATUS          0x3A
>> +#define INV_MPU6050_BIT_MST_INT             0x08
>>
>>  #define INV_MPU6050_REG_RAW_ACCEL           0x3B
>>  #define INV_MPU6050_REG_TEMPERATURE         0x41
>> --
>> 2.5.0
>>
>> --
>> 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] 16+ messages in thread

* Re: [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C master
  2016-03-17 18:11     ` Ge Gao
  2016-03-17 18:13       ` Matt Ranostay
@ 2016-03-17 21:15       ` De Marchi, Lucas
  2016-03-20 10:54       ` Jonathan Cameron
  2 siblings, 0 replies; 16+ messages in thread
From: De Marchi, Lucas @ 2016-03-17 21:15 UTC (permalink / raw)
  To: Baluta, Daniel, mranostay@gmail.com, GGao@invensense.com
  Cc: lars@metafoo.de, knaack.h@gmx.de, jic23@kernel.org,
	cmo@melexis.com, linux-iio@vger.kernel.org, adi.reus@gmail.com,
	srinivas.pandruvada@linux.intel.com, pmeerw@pmeerw.net,
	Ranostay, Matt

SGksDQoNCk9uIFRodSwgMjAxNi0wMy0xNyBhdCAxODoxMSArMDAwMCwgR2UgR2FvIHdyb3RlOg0K
PiBIaSBNYXR0LA0KPiAJSSBhbSBub3Qgc3VyZSBhYm91dCBzbGF2ZSA0LiBJIGFsd2F5cyB1c2Ug
c2xhdmUwfjMuIE1QVTYwNTAgY2FuDQo+IGNvbm5lY3QgdXAgdG8gNCBzbGF2ZXMgYnkgdXNpbmcg
c2xhdmUgMH4zLiBIb3dldmVyLCB3ZSBvbmx5IHVzZSAzIHNsYXZlcy4NCj4gRWFjaCBzbGF2ZSBj
YW4gYmUgY29uZmlndXJlZCBhcyByZWFkIG9yIHdyaXRlIGluZGVwZW5kZW50bHkuIEZvciBleGFt
cGxlLA0KPiBBS004OTczIGNvbXBhc3MgYXMgYSBzbGF2ZSwgSSB1c3VhbGx5IGNvbmZpZ3VyZSBz
bGF2ZTAgYXMgcmVhZCBhbmQgc2xhdmUgMSANCg0KSSBhbHNvIHVzdWFsbHkgdXNlIHNsYXZlcyAw
fjMuIEhvd2V2ZXIgbm93IHlvdSBtZW50aW9uIGl0IGFzIGJlaW5nIDEwMEh6Li4uDQpkb2Vzbid0
IHRoaXMgZGVwZW5kIG9uIGEpIHRoZSByYXRlIGNvbmZpZ3VyZWQgaW4gTVBVIGFuZCBiKSB0aGUg
cGFydCBpdHNlbGYNCihNUFU5MjUwIGhhcyBhIGRpZmZlcmVudCBpbnRlcm5hbCBzYW1wbGluZyBy
YXRlKT8NCg0KPiAJRm9yIHByZXNzdXJlIHNlbnNvciBvciBBTFMobGlnaHQvcHJveGltaXR5IHNl
bnNvciksIHRoZXkgYWxsIGhhdmUNCj4gYXV0b25vbW91cyBtb2RlLiBBcyBsb25nIGFzIHRoZSBz
YW1wbGUgcGVyaW9kIGlzIGxvbmdlciB0aGFuIHRoZSBvdXRwdXQNCj4gcmF0ZSwgdGhlIGRhdGEg
aXMgZ3VhcmFudGVlZCB0byBiZSBuZXcgZGF0YS4NCg0KSSB0aGluayBoaXMgdXNlIG9mIHNsYXZl
NCBpcyBtb3N0bHkgYmVjYXVzZSBvZiB0aGUgaW50ZXJydXB0IHRoYXQgaXMgYXZhaWxhYmUuDQpE
ZXBlbmRpbmcgb24gdGhlIHNlbnNvciB5b3UgYXJlIGNvbm5lY3RpbmcsIHRoZSBzYW1wbGUgcmF0
ZXMgbm90IG1hdGNoaW5nIG1heQ0KYmUgYSBwcm9ibGVtLg0KDQpTdXBwb3NlIHlvdXIgc2Vuc29y
IGlzIGdpdmluZyB5b3UgZGF0YSBhdCAxMjVIei4gVGhpcyBtZWFucyBldmVyeSB+NCBzYW1wbGVz
IHlvdSB3aWxsIGxvb3NlIG9uZSBzYW1wbGUuIMKgVGhlIG90aGVyIGNhc2Ugb2Ygc2Vuc29yIHdp
dGggdXBkYXRlIGF0IDc1SHogaXMgYWxzbyBwcm9ibGVtYXRpYyBzaW5jZSB5b3UgbWF5IGdldCBv
bGQgZGF0YSAtIGFuZCBkZXBlbmRpbmcgb24gdGhlIHNlbnNvciB5b3UgZG9uJ3QgaGF2ZSBhIHdh
eSB0byBrbm93IGlmIHRoZSBkYXRhIGlzIGludmFsaWQuDQoNCldoYXQgYW0gSSBtaXNzaW5nPw0K
DQoNCnRoYW5rcw0KDQpMdWNhcyBEZSBNYXJjaGk=

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

* Re: [PATCH 1/3] iio: imu: mpu6050: Fix name/chip_id when using ACPI
  2016-03-17 17:21   ` Matt Ranostay
@ 2016-03-20 10:40     ` Jonathan Cameron
  2016-03-21 10:16       ` Daniel Baluta
  0 siblings, 1 reply; 16+ messages in thread
From: Jonathan Cameron @ 2016-03-20 10:40 UTC (permalink / raw)
  To: Matt Ranostay, Daniel Baluta
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Matt Ranostay, Lucas De Marchi, cmo, linux-iio@vger.kernel.org,
	ggao, srinivas.pandruvada, adi.reus

On 17/03/16 17:21, Matt Ranostay wrote:
> Reviewed-By: Matt Ranostay <matt.ranostay@intel.com>
I'm guessing this may at some point want backporting, but right now it only
applies to my togreg branch (due to prior changes) so that's where I've applied
this.  If you want a faster path to mainline, the please send me the backport.

Jonathan
> 
> On Thu, Mar 17, 2016 at 9:32 AM, Daniel Baluta <daniel.baluta@intel.com> wrote:
>> When using ACPI, id is NULL and the current code automatically
>> defaults name to NULL and chip id to 0. We should instead use
>> the data provided in the ACPI device table.
>>
>> Fixes: c816d9e7a57b ("iio: imu: mpu6050: fix possible NULL dereferences")
>> Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
>> ---
>>  drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 29 ++++++++++++++++++++++++++---
>>  1 file changed, 26 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
>> index d0c0e20..5ee4e0d 100644
>> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
>> @@ -104,6 +104,19 @@ static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
>>         return 0;
>>  }
>>
>> +static const char *inv_mpu_match_acpi_device(struct device *dev, int *chip_id)
>> +{
>> +       const struct acpi_device_id *id;
>> +
>> +       id = acpi_match_device(dev->driver->acpi_match_table, dev);
>> +       if (!id)
>> +               return NULL;
>> +
>> +       *chip_id = (int)id->driver_data;
>> +
>> +       return dev_name(dev);
>> +}
>> +
>>  /**
>>   *  inv_mpu_probe() - probe function.
>>   *  @client:          i2c client.
>> @@ -115,15 +128,25 @@ static int inv_mpu_probe(struct i2c_client *client,
>>                          const struct i2c_device_id *id)
>>  {
>>         struct inv_mpu6050_state *st;
>> -       int result;
>> -       const char *name = id ? id->name : NULL;
>> -       const int chip_type = id ? id->driver_data : 0;
>> +       int result, chip_type;
>>         struct regmap *regmap;
>> +       const char *name;
>>
>>         if (!i2c_check_functionality(client->adapter,
>>                                      I2C_FUNC_SMBUS_I2C_BLOCK))
>>                 return -EOPNOTSUPP;
>>
>> +       if (id) {
>> +               chip_type = (int)id->driver_data;
>> +               name = id->name;
>> +       } else if (ACPI_HANDLE(&client->dev)) {
>> +               name = inv_mpu_match_acpi_device(&client->dev, &chip_type);
>> +               if (!name)
>> +                       return -ENODEV;
>> +       } else {
>> +               return -ENOSYS;
>> +       }
>> +
>>         regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config);
>>         if (IS_ERR(regmap)) {
>>                 dev_err(&client->dev, "Failed to register i2c regmap %d\n",
>> --
>> 2.5.0
>>
>> --
>> 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] 16+ messages in thread

* Re: [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C master
  2016-03-17 16:32 ` [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C master Daniel Baluta
  2016-03-17 17:28   ` Matt Ranostay
@ 2016-03-20 10:47   ` Jonathan Cameron
  2016-03-23 12:32     ` Daniel Baluta
  1 sibling, 1 reply; 16+ messages in thread
From: Jonathan Cameron @ 2016-03-20 10:47 UTC (permalink / raw)
  To: Daniel Baluta
  Cc: knaack.h, lars, pmeerw, matt.ranostay, lucas.demarchi, cmo,
	linux-iio, ggao, srinivas.pandruvada, adi.reus, Wolfram Sang,
	Linux I2C

On 17/03/16 16:32, Daniel Baluta wrote:
> The MPU-60X0 [1] has an auxiliary I2C bus for connecting external
> sensors. This bus has two operating modes:
> 	* pass-through, which connects the primary and auxiliary busses
> 	together [already implemented]
> 	* I2C master mode, where MPU60X0 acts as a master to any
> 	external connected sensors [implemented in this patch]
> 
> I2C master supports up to 5 slaves. Slaves 0-3 have a common operating
> mode while slave 4 is different.
> 
> This patch only adds support for slave 4 because it has a cleaner
> interface and it has an interrupt that signals when data from slave
> to master arrived.
> 
> Registers are described here [2].
> 
> We use threaded handler for reading slave4 done interrupt bit.
> 
> [1]
> https://www.cdiweb.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf
> [2]
> http://www6.in.tum.de/pub/Main/TeachingWs2015SeminarAuonomousFahren/RM-MPU-6000A.pdf
> 
> Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
hmm. Daniel - this is an i2c driver (be it within an IIO driver) so you need
to cc Wolfram and the i2c list.

I'll be needing an Ack from Wolfram if I am to take this,

Jonathan
> ---
>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 137 ++++++++++++++++++++++++++++-
>  drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  |  38 ++++++++
>  2 files changed, 172 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> index 659a4be..a89854c 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> @@ -25,6 +25,8 @@
>  #include <linux/iio/iio.h>
>  #include <linux/i2c-mux.h>
>  #include <linux/acpi.h>
> +#include <linux/completion.h>
> +
>  #include "inv_mpu_iio.h"
>  
>  /*
> @@ -57,6 +59,12 @@ static const struct inv_mpu6050_reg_map reg_set_6500 = {
>  	.int_pin_cfg		= INV_MPU6050_REG_INT_PIN_CFG,
>  	.accl_offset		= INV_MPU6500_REG_ACCEL_OFFSET,
>  	.gyro_offset		= INV_MPU6050_REG_GYRO_OFFSET,
> +	.slv4_addr		= INV_MPU6050_REG_I2C_SLV4_ADDR,
> +	.slv4_reg		= INV_MPU6050_REG_I2C_SLV4_REG,
> +	.slv4_do		= INV_MPU6050_REG_I2C_SLV4_DO,
> +	.slv4_ctrl		= INV_MPU6050_REG_I2C_SLV4_CTRL,
> +	.slv4_di		= INV_MPU6050_REG_I2C_SLV4_DI,
> +	.mst_status		= INV_MPU6050_REG_I2C_MST_STATUS,
>  };
>  
>  static const struct inv_mpu6050_reg_map reg_set_6050 = {
> @@ -77,6 +85,12 @@ static const struct inv_mpu6050_reg_map reg_set_6050 = {
>  	.int_pin_cfg		= INV_MPU6050_REG_INT_PIN_CFG,
>  	.accl_offset		= INV_MPU6050_REG_ACCEL_OFFSET,
>  	.gyro_offset		= INV_MPU6050_REG_GYRO_OFFSET,
> +	.slv4_addr		= INV_MPU6050_REG_I2C_SLV4_ADDR,
> +	.slv4_reg		= INV_MPU6050_REG_I2C_SLV4_REG,
> +	.slv4_do		= INV_MPU6050_REG_I2C_SLV4_DO,
> +	.slv4_ctrl		= INV_MPU6050_REG_I2C_SLV4_CTRL,
> +	.slv4_di		= INV_MPU6050_REG_I2C_SLV4_DI,
> +	.mst_status		= INV_MPU6050_REG_I2C_MST_STATUS,
>  };
>  
>  static const struct inv_mpu6050_chip_config chip_config_6050 = {
> @@ -761,6 +775,114 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
>  	return 0;
>  }
>  
> +static irqreturn_t inv_mpu_datardy_irq_handler(int irq, void *private)
> +{
> +	struct inv_mpu6050_state *st = (struct inv_mpu6050_state *)private;
> +
> +	iio_trigger_poll(st->trig);
> +
> +	return IRQ_WAKE_THREAD;
> +}
> +
> +static irqreturn_t inv_mpu_datardy_thread_handler(int irq, void *private)
> +{
> +	struct inv_mpu6050_state *st = (struct inv_mpu6050_state *)private;
> +	int ret, val;
> +
> +	ret = regmap_read(st->map, st->reg->mst_status, &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (val & INV_MPU6050_BIT_I2C_SLV4_DONE)
> +		complete(&st->slv4_done);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static u32 inv_mpu_i2c_functionality(struct i2c_adapter *adap)
> +{
> +	return I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA;
> +}
> +
> +static int
> +inv_mpu_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr,
> +		       unsigned short flags, char read_write, u8 command,
> +		       int size, union i2c_smbus_data *data)
> +{
> +	struct inv_mpu6050_state *st = i2c_get_adapdata(adap);
> +
> +	unsigned long time_left;
> +	int ret, val;
> +	u8 ctrl;
> +
> +	ret = inv_mpu6050_set_power_itg(st, true);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = regmap_update_bits(st->map, st->reg->user_ctrl,
> +				 INV_MPU6050_BIT_I2C_MST_EN,
> +				 INV_MPU6050_BIT_I2C_MST_EN);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = regmap_update_bits(st->map, st->reg->int_enable,
> +				 INV_MPU6050_BIT_MST_INT_EN,
> +				 INV_MPU6050_BIT_MST_INT_EN);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (read_write == I2C_SMBUS_WRITE)
> +		addr |= INV_MPU6050_BIT_I2C_SLV4_W;
> +	else
> +		addr |= INV_MPU6050_BIT_I2C_SLV4_R;
> +
> +	ret = regmap_write(st->map, st->reg->slv4_addr, addr);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = regmap_write(st->map, st->reg->slv4_reg, command);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (read_write == I2C_SMBUS_WRITE) {
> +		ret = regmap_write(st->map, st->reg->slv4_do, data->byte);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	ctrl = INV_MPU6050_BIT_SLV4_EN | INV_MPU6050_BIT_SLV4_INT_EN;
> +	ret = regmap_write(st->map, st->reg->slv4_ctrl, ctrl);
> +	if (ret < 0)
> +		return ret;
> +	if (read_write == I2C_SMBUS_READ) {
> +		time_left = wait_for_completion_timeout(&st->slv4_done, HZ);
> +		if (!time_left)
> +			return -ETIMEDOUT;
> +
> +		ret = regmap_read(st->map, st->reg->slv4_di, &val);
> +		if (ret < 0)
> +			return ret;
> +		data->byte = val;
> +	}
> +
> +	ret = inv_mpu6050_set_power_itg(st, false);
> +	if (ret < 0)
> +		return ret;
> +	return 0;
> +}
> +
> +static const struct i2c_algorithm inv_mpu_i2c_algo = {
> +	.smbus_xfer	=	inv_mpu_i2c_smbus_xfer,
> +	.functionality	=	inv_mpu_i2c_functionality,
> +};
> +
> +static struct i2c_adapter inv_mpu_i2c_adapter = {
> +	.owner		= THIS_MODULE,
> +	.class		= I2C_CLASS_HWMON,
> +	.algo		= &inv_mpu_i2c_algo,
> +	.name		= "INV MPU secondary I2C",
> +};
> +
>  int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
>  		int (*inv_mpu_bus_setup)(struct iio_dev *), int chip_type)
>  {
> @@ -796,6 +918,13 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
>  		return result;
>  	}
>  
> +	init_completion(&st->slv4_done);
> +
> +	result = i2c_add_adapter(&inv_mpu_i2c_adapter);
> +	if (result < 0)
> +		return result;
> +
> +	i2c_set_adapdata(&inv_mpu_i2c_adapter, st);
>  	dev_set_drvdata(dev, indio_dev);
>  	indio_dev->dev.parent = dev;
>  	/* name will be NULL when enumerated via ACPI */
> @@ -823,9 +952,11 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
>  		goto out_unreg_ring;
>  	}
>  
> -	result = devm_request_irq(&indio_dev->dev, st->irq,
> -				  &iio_trigger_generic_data_rdy_poll,
> -				  IRQF_TRIGGER_RISING, "inv_mpu", st->trig);
> +	result = devm_request_threaded_irq(&indio_dev->dev, st->irq,
> +					   &inv_mpu_datardy_irq_handler,
> +					   &inv_mpu_datardy_thread_handler,
> +					   IRQF_TRIGGER_RISING, "inv_mpu",
> +					   st);
>  	if (result) {
>  		dev_err(dev, "request irq fail %d\n", result);
>  		goto out_remove_trigger;
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> index e302a49..5c3ea9a 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> @@ -42,6 +42,13 @@
>   *  @int_pin_cfg;	Controls interrupt pin configuration.
>   *  @accl_offset:	Controls the accelerometer calibration offset.
>   *  @gyro_offset:	Controls the gyroscope calibration offset.
> + *  @mst_status:	secondary I2C master interrupt source status
> + *  @slv4_addr:		I2C slave address for slave 4 transaction
> + *  @slv4_reg:		I2C register used with slave 4 transaction
> + *  @slv4_di:		I2C data in register for slave 4 transaction
> + *  @slv4_ctrl:		I2C slave 4 control register
> + *  @slv4_do:		I2C data out register for slave 4 transaction
> +
>   */
>  struct inv_mpu6050_reg_map {
>  	u8 sample_rate_div;
> @@ -61,6 +68,15 @@ struct inv_mpu6050_reg_map {
>  	u8 int_pin_cfg;
>  	u8 accl_offset;
>  	u8 gyro_offset;
> +	u8 mst_status;
> +
> +	/* slave 4 registers */
> +	u8 slv4_addr;
> +	u8 slv4_reg;
> +	u8 slv4_di; /* data in */
> +	u8 slv4_ctrl;
> +	u8 slv4_do; /* data out */
> +
>  };
>  
>  /*device enum */
> @@ -133,6 +149,7 @@ struct inv_mpu6050_state {
>  	struct inv_mpu6050_platform_data plat_data;
>  	DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
>  	struct regmap *map;
> +	struct completion slv4_done;
>  	int irq;
>  };
>  
> @@ -149,9 +166,30 @@ struct inv_mpu6050_state {
>  #define INV_MPU6050_BIT_ACCEL_OUT           0x08
>  #define INV_MPU6050_BITS_GYRO_OUT           0x70
>  
> +#define INV_MPU6050_REG_I2C_SLV4_ADDR       0x31
> +#define INV_MPU6050_BIT_I2C_SLV4_R          0x80
> +#define INV_MPU6050_BIT_I2C_SLV4_W          0x00
> +
> +#define INV_MPU6050_REG_I2C_SLV4_REG        0x32
> +#define INV_MPU6050_REG_I2C_SLV4_DO         0x33
> +#define INV_MPU6050_REG_I2C_SLV4_CTRL       0x34
> +
> +#define INV_MPU6050_BIT_SLV4_EN             0x80
> +#define INV_MPU6050_BIT_SLV4_INT_EN         0x40
> +#define INV_MPU6050_BIT_SLV4_DIS            0x20
> +
> +#define INV_MPU6050_REG_I2C_SLV4_DI         0x35
> +
> +#define INV_MPU6050_REG_I2C_MST_STATUS      0x36
> +#define INV_MPU6050_BIT_I2C_SLV4_DONE       0x40
> +
>  #define INV_MPU6050_REG_INT_ENABLE          0x38
>  #define INV_MPU6050_BIT_DATA_RDY_EN         0x01
>  #define INV_MPU6050_BIT_DMP_INT_EN          0x02
> +#define INV_MPU6050_BIT_MST_INT_EN          0x08
> +
> +#define INV_MPU6050_REG_INT_STATUS          0x3A
> +#define INV_MPU6050_BIT_MST_INT             0x08
>  
>  #define INV_MPU6050_REG_RAW_ACCEL           0x3B
>  #define INV_MPU6050_REG_TEMPERATURE         0x41
> 


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

* Re: [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C master
  2016-03-17 18:11     ` Ge Gao
  2016-03-17 18:13       ` Matt Ranostay
  2016-03-17 21:15       ` De Marchi, Lucas
@ 2016-03-20 10:54       ` Jonathan Cameron
  2 siblings, 0 replies; 16+ messages in thread
From: Jonathan Cameron @ 2016-03-20 10:54 UTC (permalink / raw)
  To: Ge Gao, Matt Ranostay, Daniel Baluta
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Matt Ranostay, Lucas De Marchi, cmo@melexis.com,
	linux-iio@vger.kernel.org, srinivas.pandruvada@linux.intel.com,
	adi.reus@gmail.com, Wolfram Sang, Linux I2C

On 17/03/16 18:11, Ge Gao wrote:
> Hi Matt, I am not sure about slave 4. I always use slave0~3. MPU6050
> can connect up to 4 slaves by using slave 0~3. However, we only use 3
> slaves. Each slave can be configured as read or write independently.
> For example, AKM8973 compass as a slave, I usually configure slave0
> as read and slave 1 as write. The rate is 100Hz, for example, the
> read will read first and write happens subsequently. Of course, the
> read will read a dummy data for the first time. However, after first
> read, it will read the correct data. Write will send AKM the measure
> command. The measurement takes several mili-seconds to finish. That
> is why we read like that. For pressure sensor or ALS(light/proximity
> sensor), they all have autonomous mode. As long as the sample period
> is longer than the output rate, the data is guaranteed to be new
> data. 
Thanks.

Weird ;)

Anyhow, the upshot is that practically these are autonomous once setup
and will on a cycle continuously 'pinging' the device.  If we want to do
this in a generic way (i.e. not have to have large amounts of additional
code in every driver for devices on the end of this) it will be interesting!

Lars, superficially this sounds a bit like it could be done in a similar
way to SPI offload.  What do you think?

Maybe we just ultimately conclude these are too weird to support in any
generic way (which would be a pain).

Jonathan
> Ge
> 
> 
> -----Original Message-----
> From: Matt Ranostay [mailto:mranostay@gmail.com] 
> Sent: Thursday, March 17, 2016 10:28 AM
> To: Daniel Baluta
> Cc: Jonathan Cameron; Hartmut Knaack; Lars-Peter Clausen; Peter Meerwald-Stadler; Matt Ranostay; Lucas De Marchi; cmo@melexis.com; linux-iio@vger.kernel.org; Ge Gao; srinivas.pandruvada@linux.intel.com; adi.reus@gmail.com
> Subject: Re: [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C master
> 
> Reviewed-by: Matt Ranostay <matt.ranostay@intel.com>
> 
> On Thu, Mar 17, 2016 at 9:32 AM, Daniel Baluta <daniel.baluta@intel.com> wrote:
>> The MPU-60X0 [1] has an auxiliary I2C bus for connecting external 
>> sensors. This bus has two operating modes:
>>         * pass-through, which connects the primary and auxiliary busses
>>         together [already implemented]
>>         * I2C master mode, where MPU60X0 acts as a master to any
>>         external connected sensors [implemented in this patch]
>>
>> I2C master supports up to 5 slaves. Slaves 0-3 have a common operating 
>> mode while slave 4 is different.
>>
>> This patch only adds support for slave 4 because it has a cleaner 
>> interface and it has an interrupt that signals when data from slave to 
>> master arrived.
>>
>> Registers are described here [2].
>>
>> We use threaded handler for reading slave4 done interrupt bit.
>>
>> [1]
>> https://www.cdiweb.com/datasheets/invensense/MPU-6050_DataSheet_V3%204
>> .pdf
>> [2]
>> http://www6.in.tum.de/pub/Main/TeachingWs2015SeminarAuonomousFahren/RM
>> -MPU-6000A.pdf
>>
>> Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
>> ---
>>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 137 
>> ++++++++++++++++++++++++++++-  
>> drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  |  38 ++++++++
>>  2 files changed, 172 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c 
>> b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
>> index 659a4be..a89854c 100644
>> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
>> @@ -25,6 +25,8 @@
>>  #include <linux/iio/iio.h>
>>  #include <linux/i2c-mux.h>
>>  #include <linux/acpi.h>
>> +#include <linux/completion.h>
>> +
>>  #include "inv_mpu_iio.h"
>>
>>  /*
>> @@ -57,6 +59,12 @@ static const struct inv_mpu6050_reg_map reg_set_6500 = {
>>         .int_pin_cfg            = INV_MPU6050_REG_INT_PIN_CFG,
>>         .accl_offset            = INV_MPU6500_REG_ACCEL_OFFSET,
>>         .gyro_offset            = INV_MPU6050_REG_GYRO_OFFSET,
>> +       .slv4_addr              = INV_MPU6050_REG_I2C_SLV4_ADDR,
>> +       .slv4_reg               = INV_MPU6050_REG_I2C_SLV4_REG,
>> +       .slv4_do                = INV_MPU6050_REG_I2C_SLV4_DO,
>> +       .slv4_ctrl              = INV_MPU6050_REG_I2C_SLV4_CTRL,
>> +       .slv4_di                = INV_MPU6050_REG_I2C_SLV4_DI,
>> +       .mst_status             = INV_MPU6050_REG_I2C_MST_STATUS,
>>  };
>>
>>  static const struct inv_mpu6050_reg_map reg_set_6050 = { @@ -77,6 
>> +85,12 @@ static const struct inv_mpu6050_reg_map reg_set_6050 = {
>>         .int_pin_cfg            = INV_MPU6050_REG_INT_PIN_CFG,
>>         .accl_offset            = INV_MPU6050_REG_ACCEL_OFFSET,
>>         .gyro_offset            = INV_MPU6050_REG_GYRO_OFFSET,
>> +       .slv4_addr              = INV_MPU6050_REG_I2C_SLV4_ADDR,
>> +       .slv4_reg               = INV_MPU6050_REG_I2C_SLV4_REG,
>> +       .slv4_do                = INV_MPU6050_REG_I2C_SLV4_DO,
>> +       .slv4_ctrl              = INV_MPU6050_REG_I2C_SLV4_CTRL,
>> +       .slv4_di                = INV_MPU6050_REG_I2C_SLV4_DI,
>> +       .mst_status             = INV_MPU6050_REG_I2C_MST_STATUS,
>>  };
>>
>>  static const struct inv_mpu6050_chip_config chip_config_6050 = { @@ 
>> -761,6 +775,114 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
>>         return 0;
>>  }
>>
>> +static irqreturn_t inv_mpu_datardy_irq_handler(int irq, void 
>> +*private) {
>> +       struct inv_mpu6050_state *st = (struct inv_mpu6050_state 
>> +*)private;
>> +
>> +       iio_trigger_poll(st->trig);
>> +
>> +       return IRQ_WAKE_THREAD;
>> +}
>> +
>> +static irqreturn_t inv_mpu_datardy_thread_handler(int irq, void 
>> +*private) {
>> +       struct inv_mpu6050_state *st = (struct inv_mpu6050_state *)private;
>> +       int ret, val;
>> +
>> +       ret = regmap_read(st->map, st->reg->mst_status, &val);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       if (val & INV_MPU6050_BIT_I2C_SLV4_DONE)
>> +               complete(&st->slv4_done);
>> +
>> +       return IRQ_HANDLED;
>> +}
>> +
>> +static u32 inv_mpu_i2c_functionality(struct i2c_adapter *adap) {
>> +       return I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA; }
>> +
>> +static int
>> +inv_mpu_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr,
>> +                      unsigned short flags, char read_write, u8 command,
>> +                      int size, union i2c_smbus_data *data) {
>> +       struct inv_mpu6050_state *st = i2c_get_adapdata(adap);
>> +
>> +       unsigned long time_left;
>> +       int ret, val;
>> +       u8 ctrl;
>> +
>> +       ret = inv_mpu6050_set_power_itg(st, true);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       ret = regmap_update_bits(st->map, st->reg->user_ctrl,
>> +                                INV_MPU6050_BIT_I2C_MST_EN,
>> +                                INV_MPU6050_BIT_I2C_MST_EN);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       ret = regmap_update_bits(st->map, st->reg->int_enable,
>> +                                INV_MPU6050_BIT_MST_INT_EN,
>> +                                INV_MPU6050_BIT_MST_INT_EN);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       if (read_write == I2C_SMBUS_WRITE)
>> +               addr |= INV_MPU6050_BIT_I2C_SLV4_W;
>> +       else
>> +               addr |= INV_MPU6050_BIT_I2C_SLV4_R;
>> +
>> +       ret = regmap_write(st->map, st->reg->slv4_addr, addr);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       ret = regmap_write(st->map, st->reg->slv4_reg, command);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       if (read_write == I2C_SMBUS_WRITE) {
>> +               ret = regmap_write(st->map, st->reg->slv4_do, data->byte);
>> +               if (ret < 0)
>> +                       return ret;
>> +       }
>> +
>> +       ctrl = INV_MPU6050_BIT_SLV4_EN | INV_MPU6050_BIT_SLV4_INT_EN;
>> +       ret = regmap_write(st->map, st->reg->slv4_ctrl, ctrl);
>> +       if (ret < 0)
>> +               return ret;
>> +       if (read_write == I2C_SMBUS_READ) {
>> +               time_left = wait_for_completion_timeout(&st->slv4_done, HZ);
>> +               if (!time_left)
>> +                       return -ETIMEDOUT;
>> +
>> +               ret = regmap_read(st->map, st->reg->slv4_di, &val);
>> +               if (ret < 0)
>> +                       return ret;
>> +               data->byte = val;
>> +       }
>> +
>> +       ret = inv_mpu6050_set_power_itg(st, false);
>> +       if (ret < 0)
>> +               return ret;
>> +       return 0;
>> +}
>> +
>> +static const struct i2c_algorithm inv_mpu_i2c_algo = {
>> +       .smbus_xfer     =       inv_mpu_i2c_smbus_xfer,
>> +       .functionality  =       inv_mpu_i2c_functionality,
>> +};
>> +
>> +static struct i2c_adapter inv_mpu_i2c_adapter = {
>> +       .owner          = THIS_MODULE,
>> +       .class          = I2C_CLASS_HWMON,
>> +       .algo           = &inv_mpu_i2c_algo,
>> +       .name           = "INV MPU secondary I2C",
>> +};
>> +
>>  int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
>>                 int (*inv_mpu_bus_setup)(struct iio_dev *), int 
>> chip_type)  { @@ -796,6 +918,13 @@ int inv_mpu_core_probe(struct 
>> regmap *regmap, int irq, const char *name,
>>                 return result;
>>         }
>>
>> +       init_completion(&st->slv4_done);
>> +
>> +       result = i2c_add_adapter(&inv_mpu_i2c_adapter);
>> +       if (result < 0)
>> +               return result;
>> +
>> +       i2c_set_adapdata(&inv_mpu_i2c_adapter, st);
>>         dev_set_drvdata(dev, indio_dev);
>>         indio_dev->dev.parent = dev;
>>         /* name will be NULL when enumerated via ACPI */ @@ -823,9 
>> +952,11 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
>>                 goto out_unreg_ring;
>>         }
>>
>> -       result = devm_request_irq(&indio_dev->dev, st->irq,
>> -                                 &iio_trigger_generic_data_rdy_poll,
>> -                                 IRQF_TRIGGER_RISING, "inv_mpu", st->trig);
>> +       result = devm_request_threaded_irq(&indio_dev->dev, st->irq,
>> +                                          &inv_mpu_datardy_irq_handler,
>> +                                          &inv_mpu_datardy_thread_handler,
>> +                                          IRQF_TRIGGER_RISING, "inv_mpu",
>> +                                          st);
>>         if (result) {
>>                 dev_err(dev, "request irq fail %d\n", result);
>>                 goto out_remove_trigger; diff --git 
>> a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h 
>> b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>> index e302a49..5c3ea9a 100644
>> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>> @@ -42,6 +42,13 @@
>>   *  @int_pin_cfg;      Controls interrupt pin configuration.
>>   *  @accl_offset:      Controls the accelerometer calibration offset.
>>   *  @gyro_offset:      Controls the gyroscope calibration offset.
>> + *  @mst_status:       secondary I2C master interrupt source status
>> + *  @slv4_addr:                I2C slave address for slave 4 transaction
>> + *  @slv4_reg:         I2C register used with slave 4 transaction
>> + *  @slv4_di:          I2C data in register for slave 4 transaction
>> + *  @slv4_ctrl:                I2C slave 4 control register
>> + *  @slv4_do:          I2C data out register for slave 4 transaction
>> +
>>   */
>>  struct inv_mpu6050_reg_map {
>>         u8 sample_rate_div;
>> @@ -61,6 +68,15 @@ struct inv_mpu6050_reg_map {
>>         u8 int_pin_cfg;
>>         u8 accl_offset;
>>         u8 gyro_offset;
>> +       u8 mst_status;
>> +
>> +       /* slave 4 registers */
>> +       u8 slv4_addr;
>> +       u8 slv4_reg;
>> +       u8 slv4_di; /* data in */
>> +       u8 slv4_ctrl;
>> +       u8 slv4_do; /* data out */
>> +
>>  };
>>
>>  /*device enum */
>> @@ -133,6 +149,7 @@ struct inv_mpu6050_state {
>>         struct inv_mpu6050_platform_data plat_data;
>>         DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
>>         struct regmap *map;
>> +       struct completion slv4_done;
>>         int irq;
>>  };
>>
>> @@ -149,9 +166,30 @@ struct inv_mpu6050_state {
>>  #define INV_MPU6050_BIT_ACCEL_OUT           0x08
>>  #define INV_MPU6050_BITS_GYRO_OUT           0x70
>>
>> +#define INV_MPU6050_REG_I2C_SLV4_ADDR       0x31
>> +#define INV_MPU6050_BIT_I2C_SLV4_R          0x80
>> +#define INV_MPU6050_BIT_I2C_SLV4_W          0x00
>> +
>> +#define INV_MPU6050_REG_I2C_SLV4_REG        0x32
>> +#define INV_MPU6050_REG_I2C_SLV4_DO         0x33
>> +#define INV_MPU6050_REG_I2C_SLV4_CTRL       0x34
>> +
>> +#define INV_MPU6050_BIT_SLV4_EN             0x80
>> +#define INV_MPU6050_BIT_SLV4_INT_EN         0x40
>> +#define INV_MPU6050_BIT_SLV4_DIS            0x20
>> +
>> +#define INV_MPU6050_REG_I2C_SLV4_DI         0x35
>> +
>> +#define INV_MPU6050_REG_I2C_MST_STATUS      0x36
>> +#define INV_MPU6050_BIT_I2C_SLV4_DONE       0x40
>> +
>>  #define INV_MPU6050_REG_INT_ENABLE          0x38
>>  #define INV_MPU6050_BIT_DATA_RDY_EN         0x01
>>  #define INV_MPU6050_BIT_DMP_INT_EN          0x02
>> +#define INV_MPU6050_BIT_MST_INT_EN          0x08
>> +
>> +#define INV_MPU6050_REG_INT_STATUS          0x3A
>> +#define INV_MPU6050_BIT_MST_INT             0x08
>>
>>  #define INV_MPU6050_REG_RAW_ACCEL           0x3B
>>  #define INV_MPU6050_REG_TEMPERATURE         0x41
>> --
>> 2.5.0
>>
>> --
>> 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] 16+ messages in thread

* Re: [PATCH 1/3] iio: imu: mpu6050: Fix name/chip_id when using ACPI
  2016-03-20 10:40     ` Jonathan Cameron
@ 2016-03-21 10:16       ` Daniel Baluta
  2016-03-21 18:58         ` Jonathan Cameron
  0 siblings, 1 reply; 16+ messages in thread
From: Daniel Baluta @ 2016-03-21 10:16 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Matt Ranostay, Daniel Baluta, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Matt Ranostay, Lucas De Marchi, Crt Mori,
	linux-iio@vger.kernel.org, Ge Gao, Srinivas Pandruvada,
	Adriana Reus

On Sun, Mar 20, 2016 at 12:40 PM, Jonathan Cameron <jic23@kernel.org> wrote:
> On 17/03/16 17:21, Matt Ranostay wrote:
>> Reviewed-By: Matt Ranostay <matt.ranostay@intel.com>
> I'm guessing this may at some point want backporting, but right now it only
> applies to my togreg branch (due to prior changes) so that's where I've applied
> this.  If you want a faster path to mainline, the please send me the backport.

Sure. One thing: on which branch should I rebase the changes?

fixes or fixes-togreg?

Daniel.

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

* Re: [PATCH 1/3] iio: imu: mpu6050: Fix name/chip_id when using ACPI
  2016-03-21 10:16       ` Daniel Baluta
@ 2016-03-21 18:58         ` Jonathan Cameron
  0 siblings, 0 replies; 16+ messages in thread
From: Jonathan Cameron @ 2016-03-21 18:58 UTC (permalink / raw)
  To: Daniel Baluta
  Cc: Matt Ranostay, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Matt Ranostay, Lucas De Marchi, Crt Mori,
	linux-iio@vger.kernel.org, Ge Gao, Srinivas Pandruvada,
	Adriana Reus

On 21/03/16 10:16, Daniel Baluta wrote:
> On Sun, Mar 20, 2016 at 12:40 PM, Jonathan Cameron <jic23@kernel.org> wrote:
>> On 17/03/16 17:21, Matt Ranostay wrote:
>>> Reviewed-By: Matt Ranostay <matt.ranostay@intel.com>
>> I'm guessing this may at some point want backporting, but right now it only
>> applies to my togreg branch (due to prior changes) so that's where I've applied
>> this.  If you want a faster path to mainline, the please send me the backport.
> 
> Sure. One thing: on which branch should I rebase the changes?
> 
> fixes or fixes-togreg?
Doh, fixes was a mistype at somepoint.  Now gone from backend, should
clear off front end shortly.

Jonathan
> 
> Daniel.
> 


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

* Re: [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C master
  2016-03-20 10:47   ` Jonathan Cameron
@ 2016-03-23 12:32     ` Daniel Baluta
  0 siblings, 0 replies; 16+ messages in thread
From: Daniel Baluta @ 2016-03-23 12:32 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Daniel Baluta, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Matt Ranostay, Lucas De Marchi, Crt Mori,
	linux-iio@vger.kernel.org, Ge Gao, Srinivas Pandruvada,
	Adriana Reus, Wolfram Sang, Linux I2C

On Sun, Mar 20, 2016 at 12:47 PM, Jonathan Cameron <jic23@kernel.org> wrote:
> On 17/03/16 16:32, Daniel Baluta wrote:
>> The MPU-60X0 [1] has an auxiliary I2C bus for connecting external
>> sensors. This bus has two operating modes:
>>       * pass-through, which connects the primary and auxiliary busses
>>       together [already implemented]
>>       * I2C master mode, where MPU60X0 acts as a master to any
>>       external connected sensors [implemented in this patch]
>>
>> I2C master supports up to 5 slaves. Slaves 0-3 have a common operating
>> mode while slave 4 is different.
>>
>> This patch only adds support for slave 4 because it has a cleaner
>> interface and it has an interrupt that signals when data from slave
>> to master arrived.
>>
>> Registers are described here [2].
>>
>> We use threaded handler for reading slave4 done interrupt bit.
>>
>> [1]
>> https://www.cdiweb.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf
>> [2]
>> http://www6.in.tum.de/pub/Main/TeachingWs2015SeminarAuonomousFahren/RM-MPU-6000A.pdf
>>
>> Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
> hmm. Daniel - this is an i2c driver (be it within an IIO driver) so you need
> to cc Wolfram and the i2c list.
>
> I'll be needing an Ack from Wolfram if I am to take this,

Will do with v2.

Daniel.

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

end of thread, other threads:[~2016-03-23 12:32 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-17 16:32 [PATCH 0/3] Introduce support for INV MPU6050 secondary I2C master Daniel Baluta
2016-03-17 16:32 ` [PATCH 1/3] iio: imu: mpu6050: Fix name/chip_id when using ACPI Daniel Baluta
2016-03-17 17:21   ` Matt Ranostay
2016-03-20 10:40     ` Jonathan Cameron
2016-03-21 10:16       ` Daniel Baluta
2016-03-21 18:58         ` Jonathan Cameron
2016-03-17 16:32 ` [PATCH 2/3] iio: imu: mpu6050: Move request IRQ outside of probe trigger Daniel Baluta
2016-03-17 17:24   ` Matt Ranostay
2016-03-17 16:32 ` [PATCH 3/3] iio: imu: mpu6050: Add support for auxiliary I2C master Daniel Baluta
2016-03-17 17:28   ` Matt Ranostay
2016-03-17 18:11     ` Ge Gao
2016-03-17 18:13       ` Matt Ranostay
2016-03-17 21:15       ` De Marchi, Lucas
2016-03-20 10:54       ` Jonathan Cameron
2016-03-20 10:47   ` Jonathan Cameron
2016-03-23 12:32     ` Daniel Baluta

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).