From: Hector Palacios <hector.palacios@digi.com>
To: linux-gpio@vger.kernel.org
Cc: linus.walleij@linaro.org,
"fabio.estevam@freescale.com" <fabio.estevam@freescale.com>,
zonque@gmail.com, "shawn.guo@linaro.org" <shawn.guo@linaro.org>
Subject: mxs gpios as wakeup interrupts and irq_set_wake() hook
Date: Thu, 21 Nov 2013 11:19:28 +0100 [thread overview]
Message-ID: <528DDE30.4090509@digi.com> (raw)
Hello,
I was trying to have GPIOs be able to wake up my ARM i.MX28 system from suspend but
noticed that the existing hook irq_set_wake() in the driver
ct->chip.irq_set_wake = mxs_gpio_set_wake_irq;
was never called when I enabled a gpio as wakeup via the sysfs:
echo enabled > /sys/class/gpio/gpio107/device/power/wakeup
The implementation of the hook itself is:
static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct mxs_gpio_port *port = gc->private;
if (enable)
enable_irq_wake(port->irq);
else
disable_irq_wake(port->irq);
return 0;
}
which looks to me like a cyclic call because the irq_set_wake() hook is called from
set_irq_wake_real() which is called from irq_set_irq_wake() which is called from
enable_irq_wake(). And this last function is what the driver's hook implementation is
doing.
I was expecting that enable_irq_wake() was fired somehow from the kernel when I enable
the wakeup descriptor in the sysfs, but I guess it works in a different way.
Instead, I implemented suspend/resume calls in the gpio driver that fire the
enable_irq_wake/disable_irq_wake if the device can_wakeup flag is set (this is what
the sysfs does). I took this model from the serial driver.
This works but, could anyone tell me if this approach correct for gpio?
@@ -174,6 +174,7 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
}
}
+#ifdef CONFIG_PM_SLEEP
/*
* Set interrupt number "irq" in the GPIO as a wake-up source.
* While system is running, all registered GPIO interrupts need to have
@@ -196,6 +197,33 @@ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int
enable)
return 0;
}
+static int mxs_gpio_suspend(struct device *dev)
+{
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
+ int irq = platform_get_irq(pdev, 0);
+
+ /* Enable wakeup irq before suspending, if device can wakeup */
+ if (device_may_wakeup(dev))
+ return enable_irq_wake(irq);
+
+ return 0;
+}
+
+static int mxs_gpio_resume(struct device *dev)
+{
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
+ int irq = platform_get_irq(pdev, 0);
+
+ /* Disable wakeup irq on resume, if device can wakeup */
+ if (device_may_wakeup(dev))
+ return disable_irq_wake(irq);
+
+ return 0;
+}
+#endif
+
static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
{
struct irq_chip_generic *gc;
@@ -210,7 +238,9 @@ static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port,
int irq_base)
ct->chip.irq_mask = irq_gc_mask_clr_bit;
ct->chip.irq_unmask = irq_gc_mask_set_bit;
ct->chip.irq_set_type = mxs_gpio_set_irq_type;
+#ifdef CONFIG_PM_SLEEP
ct->chip.irq_set_wake = mxs_gpio_set_wake_irq;
+#endif
ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR;
ct->regs.mask = PINCTRL_IRQEN(port);
@@ -320,6 +350,10 @@ static int mxs_gpio_probe(struct platform_device *pdev)
/* gpio-mxs can be a generic irq chip */
mxs_gpio_init_gc(port, irq_base);
+#ifdef CONFIG_PM_SLEEP
+ device_set_wakeup_capable(&pdev->dev, 1);
+#endif
+
/* setup one handler for each entry */
irq_set_chained_handler(port->irq, mxs_gpio_irq_handler);
irq_set_handler_data(port->irq, port);
@@ -348,11 +382,16 @@ out_irqdesc_free:
return err;
}
+static const struct dev_pm_ops mxs_gpio_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(mxs_gpio_suspend, mxs_gpio_resume)
+};
+
static struct platform_driver mxs_gpio_driver = {
.driver = {
.name = "gpio-mxs",
.owner = THIS_MODULE,
.of_match_table = mxs_gpio_dt_ids,
+ .pm = &mxs_gpio_pm_ops,
},
.probe = mxs_gpio_probe,
.id_table = mxs_gpio_ids,
Best regards,
--
Hector Palacios
next reply other threads:[~2013-11-21 10:26 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-11-21 10:19 Hector Palacios [this message]
2013-11-21 16:35 ` mxs gpios as wakeup interrupts and irq_set_wake() hook Fabio Estevam
2013-11-21 17:32 ` Hector Palacios
2013-11-21 17:45 ` Fabio Estevam
2013-11-27 14:00 ` Linus Walleij
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=528DDE30.4090509@digi.com \
--to=hector.palacios@digi.com \
--cc=fabio.estevam@freescale.com \
--cc=linus.walleij@linaro.org \
--cc=linux-gpio@vger.kernel.org \
--cc=shawn.guo@linaro.org \
--cc=zonque@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.