* mxs gpios as wakeup interrupts and irq_set_wake() hook
@ 2013-11-21 10:19 Hector Palacios
2013-11-21 16:35 ` Fabio Estevam
2013-11-27 14:00 ` Linus Walleij
0 siblings, 2 replies; 5+ messages in thread
From: Hector Palacios @ 2013-11-21 10:19 UTC (permalink / raw)
To: linux-gpio
Cc: linus.walleij, fabio.estevam@freescale.com, zonque,
shawn.guo@linaro.org
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
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: mxs gpios as wakeup interrupts and irq_set_wake() hook
2013-11-21 10:19 mxs gpios as wakeup interrupts and irq_set_wake() hook Hector Palacios
@ 2013-11-21 16:35 ` Fabio Estevam
2013-11-21 17:32 ` Hector Palacios
2013-11-27 14:00 ` Linus Walleij
1 sibling, 1 reply; 5+ messages in thread
From: Fabio Estevam @ 2013-11-21 16:35 UTC (permalink / raw)
To: Hector Palacios, linux-gpio
Cc: linus.walleij, festevam, zonque, shawn.guo@linaro.org
Hi Hector,
On 11/21/2013 08:19 AM, Hector Palacios wrote:
> 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
Does the existing code work if you pass 'gpio-key,wakeup' in the .dts file?
Regards,
Fabio Estevam
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: mxs gpios as wakeup interrupts and irq_set_wake() hook
2013-11-21 16:35 ` Fabio Estevam
@ 2013-11-21 17:32 ` Hector Palacios
2013-11-21 17:45 ` Fabio Estevam
0 siblings, 1 reply; 5+ messages in thread
From: Hector Palacios @ 2013-11-21 17:32 UTC (permalink / raw)
To: Fabio Estevam, linux-gpio@vger.kernel.org
Cc: linus.walleij@linaro.org, festevam@gmail.com, zonque@gmail.com,
shawn.guo@linaro.org
Hi Fabio,
On 11/21/2013 05:35 PM, Fabio Estevam wrote:
> Hi Hector,
>
> On 11/21/2013 08:19 AM, Hector Palacios wrote:
>> 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
>
> Does the existing code work if you pass 'gpio-key,wakeup' in the .dts file?
Do you mean to have an entry like this?
gpio_keys {
compatible = "gpio-keys";
#address-cells = <1>;
#size-cells = <0>;
autorepeat;
gpio-key,wakeup;
button@21 {
label = "GPIO Key UP";
linux,code = <103>;
gpios = <&gpio3 11 1>; /* gpio107 */
};
};
No it doesn't.
In any case what I wanted (maybe it's not standard) was to be able to export a GPIO,
configure it as interrupt, and enable it as wakeup, entirely from sysfs, without
needing to use a driver or defining an entry for a specific GPIO in the DT.
I achieved it with the code I sent but I guess the framework was not devised to use
gpios that way.
Have you tested if that irq_set_wake hook in the gpio-mxs.c driver is ever called?
Best regards,
--
Hector Palacios
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: mxs gpios as wakeup interrupts and irq_set_wake() hook
2013-11-21 17:32 ` Hector Palacios
@ 2013-11-21 17:45 ` Fabio Estevam
0 siblings, 0 replies; 5+ messages in thread
From: Fabio Estevam @ 2013-11-21 17:45 UTC (permalink / raw)
To: Hector Palacios
Cc: Fabio Estevam, linux-gpio@vger.kernel.org,
linus.walleij@linaro.org, zonque@gmail.com, shawn.guo@linaro.org
On Thu, Nov 21, 2013 at 3:32 PM, Hector Palacios
<hector.palacios@digi.com> wrote:
> Do you mean to have an entry like this?
>
> gpio_keys {
> compatible = "gpio-keys";
> #address-cells = <1>;
> #size-cells = <0>;
> autorepeat;
> gpio-key,wakeup;
> button@21 {
> label = "GPIO Key UP";
> linux,code = <103>;
> gpios = <&gpio3 11 1>; /* gpio107 */
> };
> };
Yes, this is what I meant.
>
> No it doesn't.
>
> In any case what I wanted (maybe it's not standard) was to be able to export
> a GPIO, configure it as interrupt, and enable it as wakeup, entirely from
> sysfs, without needing to use a driver or defining an entry for a specific
> GPIO in the DT.
> I achieved it with the code I sent but I guess the framework was not devised
> to use gpios that way.
>
> Have you tested if that irq_set_wake hook in the gpio-mxs.c driver is ever
> called?
On mx28evk I don't have any free GPIO I can use to wakeup the system,
so I have not tried it.
I have only used the serial port to wakeup the system.
Regards,
Fabio Estevam
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: mxs gpios as wakeup interrupts and irq_set_wake() hook
2013-11-21 10:19 mxs gpios as wakeup interrupts and irq_set_wake() hook Hector Palacios
2013-11-21 16:35 ` Fabio Estevam
@ 2013-11-27 14:00 ` Linus Walleij
1 sibling, 0 replies; 5+ messages in thread
From: Linus Walleij @ 2013-11-27 14:00 UTC (permalink / raw)
To: Hector Palacios
Cc: linux-gpio@vger.kernel.org, fabio.estevam@freescale.com,
Daniel Mack, shawn.guo@linaro.org
On Thu, Nov 21, 2013 at 11:19 AM, Hector Palacios
<hector.palacios@digi.com> wrote:
> +#ifdef CONFIG_PM_SLEEP
> ct->chip.irq_set_wake = mxs_gpio_set_wake_irq;
> +#endif
Don't bother ifdef:in this. Since that function is not #ifdef:ed
I guess you get a build warning of an unused function when
PM_SLEEP is not set?
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-11-27 14:00 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-11-21 10:19 mxs gpios as wakeup interrupts and irq_set_wake() hook Hector Palacios
2013-11-21 16:35 ` Fabio Estevam
2013-11-21 17:32 ` Hector Palacios
2013-11-21 17:45 ` Fabio Estevam
2013-11-27 14:00 ` Linus Walleij
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).