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