Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1196419 > unrolled thread
| Started by | Dmitry Torokhov <dmitry.torokhov@gmail.com> |
|---|---|
| First post | 2015-07-30 22:20 +0200 |
| Last post | 2015-08-03 22:10 +0200 |
| Articles | 3 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH] i2c: allow specifying separate wakeup interrupt in device tree Dmitry Torokhov <dmitry.torokhov@gmail.com> - 2015-07-30 22:20 +0200
Re: [PATCH] i2c: allow specifying separate wakeup interrupt in device tree Tony Lindgren <tony@atomide.com> - 2015-08-03 12:30 +0200
Re: [PATCH] i2c: allow specifying separate wakeup interrupt in device tree Dmitry Torokhov <dmitry.torokhov@gmail.com> - 2015-08-03 22:10 +0200
| From | Dmitry Torokhov <dmitry.torokhov@gmail.com> |
|---|---|
| Date | 2015-07-30 22:20 +0200 |
| Subject | [PATCH] i2c: allow specifying separate wakeup interrupt in device tree |
| Message-ID | <pS2t5-pi-23@gated-at.bofh.it> |
Instead of having each i2c driver individually parse device tree data in
case it or platform supports separate wakeup interrupt, and handle
enabling and disabling wakeup interrupts in their power management
routines, let's have i2c core do that for us.
Platforms wishing to specify separate wakeup interrupt for the device
should use named interrupt syntax in their DTSes:
interrupt-parent = <&intc1>;
interrupts = <5 0>, <6 0>;
interrupt-names = "irq", "wakeup";
This patch is inspired by work done by Vignesh R <vigneshr@ti.com> for
pixcir_i2c_ts driver.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/i2c/i2c-core.c | 46 ++++++++++++++++++++++++++++++++++++++++------
1 file changed, 40 insertions(+), 6 deletions(-)
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index e6d4935..19e7a17 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -47,6 +47,7 @@
#include <linux/rwsem.h>
#include <linux/pm_runtime.h>
#include <linux/pm_domain.h>
+#include <linux/pm_wakeirq.h>
#include <linux/acpi.h>
#include <linux/jump_label.h>
#include <asm/uaccess.h>
@@ -639,11 +640,13 @@ static int i2c_device_probe(struct device *dev)
if (!client->irq) {
int irq = -ENOENT;
- if (dev->of_node)
- irq = of_irq_get(dev->of_node, 0);
- else if (ACPI_COMPANION(dev))
+ if (dev->of_node) {
+ irq = of_irq_get_byname(dev->of_node, "irq");
+ if (irq == -EINVAL || irq == -ENODATA)
+ irq = of_irq_get(dev->of_node, 0);
+ } else if (ACPI_COMPANION(dev)) {
irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0);
-
+ }
if (irq == -EPROBE_DEFER)
return irq;
if (irq < 0)
@@ -659,20 +662,47 @@ static int i2c_device_probe(struct device *dev)
if (!device_can_wakeup(&client->dev))
device_init_wakeup(&client->dev,
client->flags & I2C_CLIENT_WAKE);
+
+ if (device_can_wakeup(&client->dev)) {
+ int wakeirq = -ENOENT;
+
+ if (dev->of_node) {
+ wakeirq = of_irq_get_byname(dev->of_node, "wakeup");
+ if (wakeirq == -EPROBE_DEFER)
+ return wakeirq;
+ }
+
+ if (wakeirq > 0 && wakeirq != client->irq)
+ status = dev_pm_set_dedicated_wake_irq(dev, wakeirq);
+ else if (client->irq > 0)
+ status = dev_pm_set_wake_irq(dev, wakeirq);
+ else
+ status = 0;
+
+ if (status)
+ dev_warn(&client->dev, "failed to set up wakeup irq");
+ }
+
dev_dbg(dev, "probe\n");
status = of_clk_set_defaults(dev->of_node, false);
if (status < 0)
- return status;
+ goto err_clear_wakeup_irq;
status = dev_pm_domain_attach(&client->dev, true);
if (status != -EPROBE_DEFER) {
status = driver->probe(client, i2c_match_id(driver->id_table,
client));
if (status)
- dev_pm_domain_detach(&client->dev, true);
+ goto err_detach_pm_domain;
}
+ return 0;
+
+err_detach_pm_domain:
+ dev_pm_domain_detach(&client->dev, true);
+err_clear_wakeup_irq:
+ dev_pm_clear_wake_irq(&client->dev);
return status;
}
@@ -692,6 +722,10 @@ static int i2c_device_remove(struct device *dev)
}
dev_pm_domain_detach(&client->dev, true);
+
+ dev_pm_clear_wake_irq(&client->dev);
+ device_init_wakeup(&client->dev, 0);
+
return status;
}
--
2.5.0.rc2.392.g76e840b
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Tony Lindgren <tony@atomide.com> |
|---|---|
| Date | 2015-08-03 12:30 +0200 |
| Subject | Re: [PATCH] i2c: allow specifying separate wakeup interrupt in device tree |
| Message-ID | <pTlai-fp-19@gated-at.bofh.it> |
| In reply to | #1196419 |
* Vignesh R <vigneshr@ti.com> [150731 04:00]:
> On 07/31/2015 01:44 AM, Dmitry Torokhov wrote:
> > Instead of having each i2c driver individually parse device tree data in
> > case it or platform supports separate wakeup interrupt, and handle
> > enabling and disabling wakeup interrupts in their power management
> > routines, let's have i2c core do that for us.
Good idea, yes the dedicated wake-up interrupts can be handled
at the bus level to keep device drivers generic.
One question below though..
> > @@ -639,11 +640,13 @@ static int i2c_device_probe(struct device *dev)
> > if (!client->irq) {
> > int irq = -ENOENT;
> >
> > - if (dev->of_node)
> > - irq = of_irq_get(dev->of_node, 0);
> > - else if (ACPI_COMPANION(dev))
> > + if (dev->of_node) {
> > + irq = of_irq_get_byname(dev->of_node, "irq");
> > + if (irq == -EINVAL || irq == -ENODATA)
> > + irq = of_irq_get(dev->of_node, 0);
> > + } else if (ACPI_COMPANION(dev)) {
> > irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0);
> > -
> > + }
> > if (irq == -EPROBE_DEFER)
> > return irq;
> > if (irq < 0)
> > @@ -659,20 +662,47 @@ static int i2c_device_probe(struct device *dev)
> > if (!device_can_wakeup(&client->dev))
> > device_init_wakeup(&client->dev,
> > client->flags & I2C_CLIENT_WAKE);
> > +
> > + if (device_can_wakeup(&client->dev)) {
> > + int wakeirq = -ENOENT;
> > +
> > + if (dev->of_node) {
> > + wakeirq = of_irq_get_byname(dev->of_node, "wakeup");
> > + if (wakeirq == -EPROBE_DEFER)
> > + return wakeirq;
> > + }
> > +
> > + if (wakeirq > 0 && wakeirq != client->irq)
> > + status = dev_pm_set_dedicated_wake_irq(dev, wakeirq);
> > + else if (client->irq > 0)
> > + status = dev_pm_set_wake_irq(dev, wakeirq);
> > + else
> > + status = 0;
Hmm why do we need the check for if (device_can_wakeup(&client->dev)))?
Also wondering about the dev vs &client->dev usage here.. But I take
you have checked that we end up calling the runtime PM calls of the
client instead of the i2c bus controller :)
Regards,
Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Dmitry Torokhov <dmitry.torokhov@gmail.com> |
|---|---|
| Date | 2015-08-03 22:10 +0200 |
| Subject | Re: [PATCH] i2c: allow specifying separate wakeup interrupt in device tree |
| Message-ID | <pTudA-4Zd-17@gated-at.bofh.it> |
| In reply to | #1198714 |
Hi Tony,
On Mon, Aug 03, 2015 at 03:21:21AM -0700, Tony Lindgren wrote:
> * Vignesh R <vigneshr@ti.com> [150731 04:00]:
> > On 07/31/2015 01:44 AM, Dmitry Torokhov wrote:
> > > Instead of having each i2c driver individually parse device tree data in
> > > case it or platform supports separate wakeup interrupt, and handle
> > > enabling and disabling wakeup interrupts in their power management
> > > routines, let's have i2c core do that for us.
>
> Good idea, yes the dedicated wake-up interrupts can be handled
> at the bus level to keep device drivers generic.
>
> One question below though..
>
> > > @@ -639,11 +640,13 @@ static int i2c_device_probe(struct device *dev)
> > > if (!client->irq) {
> > > int irq = -ENOENT;
> > >
> > > - if (dev->of_node)
> > > - irq = of_irq_get(dev->of_node, 0);
> > > - else if (ACPI_COMPANION(dev))
> > > + if (dev->of_node) {
> > > + irq = of_irq_get_byname(dev->of_node, "irq");
> > > + if (irq == -EINVAL || irq == -ENODATA)
> > > + irq = of_irq_get(dev->of_node, 0);
> > > + } else if (ACPI_COMPANION(dev)) {
> > > irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0);
> > > -
> > > + }
> > > if (irq == -EPROBE_DEFER)
> > > return irq;
> > > if (irq < 0)
> > > @@ -659,20 +662,47 @@ static int i2c_device_probe(struct device *dev)
> > > if (!device_can_wakeup(&client->dev))
> > > device_init_wakeup(&client->dev,
> > > client->flags & I2C_CLIENT_WAKE);
> > > +
> > > + if (device_can_wakeup(&client->dev)) {
> > > + int wakeirq = -ENOENT;
> > > +
> > > + if (dev->of_node) {
> > > + wakeirq = of_irq_get_byname(dev->of_node, "wakeup");
> > > + if (wakeirq == -EPROBE_DEFER)
> > > + return wakeirq;
> > > + }
> > > +
> > > + if (wakeirq > 0 && wakeirq != client->irq)
> > > + status = dev_pm_set_dedicated_wake_irq(dev, wakeirq);
> > > + else if (client->irq > 0)
> > > + status = dev_pm_set_wake_irq(dev, wakeirq);
> > > + else
> > > + status = 0;
>
> Hmm why do we need the check for if (device_can_wakeup(&client->dev)))?
Because of the code in device_wakeup_attach_irq():
ws = dev->power.wakeup;
if (!ws) {
dev_err(dev, "forgot to call call device_init_wakeup?\n");
return -EINVAL;
}
>
> Also wondering about the dev vs &client->dev usage here.. But I take
> you have checked that we end up calling the runtime PM calls of the
> client instead of the i2c bus controller :)
dev *is* clent->dev in this context:
struct i2c_client *client = i2c_verify_client(dev);
Thanks!
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web