diff mbox

[RFC] gpio/omap: fix pm_runtime for IRQ functions

Message ID 50FCE27D.7060500@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Santosh Shilimkar Jan. 21, 2013, 6:38 a.m. UTC
On Friday 18 January 2013 11:19 PM, Jan Luebbe wrote:
> Other devices in the device tree can use omap-gpio as an interrupt
> controller with something like:
> 	interrupt-parent = <&gpio1>;
> 	interrupts = <19 8>;
> (in this case with #interrupt-cells = <2> in the gpio node to be able
> to configure the IRQ flags in DT)
>
> Currently this triggers an unhandled fault (external abort on non-
> linefetch) because the gpio bank has been disabled by runtime pm.
> The current driver keeps a reference count in omap_gpio_request
> and omap_gpio_free, but these are not called when configuring
> an IRQ via device tree. The current code expects that users
> always request a gpio before trying to use the IRQ functions.
> When using DT, this is no longer the case.
>
> To fix this problem, I changed bank->mod_usage from per pin flags
> to a simple refcount and update it from gpio_unmask_irq and
> gpio_mask_irq, as well. Depending on the content of bank->mod_usage,
> pm_runtime_get_sync and pm_runtime_put are called.
>
> I'm unsure about the code to en-/disable the module clock gate.
> Maybe it should be moved to omap_gpio_runtime_{suspend,resume} or
> separate helpers?
> Another unclear point is whether the pm_runtime_* calls have a too
> large overhead for unmask/mask.
>
> Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
> ---
The main issue is the request_gpio() isn't getting triggered in the
DT case. GPIO driver do expect users to do request_gpio() to be called
for any further usage.
IIRC, similar issue was discussed previously without any conclusion.

Grant/Linus,
Whats your suggestion on above mentioned issue. How gpio_request()
can be triggered from the framework when a gpio irq binding is found
in DT blob() ? Rajendra cooked up a patch while back on the same
topic which am attaching for the reference. Please let us know
your input whether attached patch make sense or any other
alternative you have.

Regards
Santosh

Comments

Linus Walleij Jan. 22, 2013, 8:22 a.m. UTC | #1
On Mon, Jan 21, 2013 at 7:38 AM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:

Need Grant to look at this too...

> Whats your suggestion on above mentioned issue. How gpio_request()
> can be triggered from the framework when a gpio irq binding is found
> in DT blob() ?

Just as usual the GPIO has to be requested.

In the Nomadik I had a similar situation with a GPIO used for the
ethernet IRQ. I put the GPIO number in a special board-specific
node and added this to the machine, but it could as well be in a device
driver:

/*
 * The SMSC911x IRQ is connected to a GPIO pin, but the driver expects
 * to simply request an IRQ passed as a resource. So the GPIO pin needs
 * to be requested by this hog and set as input.
 */
static int __init cpu8815_eth_init(void)
{
        struct device_node *eth;
        int gpio, irq, err;

        eth = of_find_node_by_path("/usb-s8815/ethernet-gpio");
        if (!eth) {
                pr_info("could not find any ethernet GPIO\n");
                return 0;
        }
        gpio = of_get_gpio(eth, 0);
        err = gpio_request(gpio, "eth_irq");
        if (err) {
                pr_info("failed to request ethernet GPIO\n");
                return -ENODEV;
        }
        err = gpio_direction_input(gpio);
        if (err) {
                pr_info("failed to set ethernet GPIO as input\n");
                return -ENODEV;
        }
        irq = gpio_to_irq(gpio);
        pr_info("enabled USB-S8815 ethernet GPIO %d, IRQ %d\n", gpio, irq);
        return 0;
}
device_initcall(cpu8815_eth_init);

Note that I just map the IRQ to print it, the actual request of that IRQ
is done elsewhere.

I think something like the above should be added to:

1) The device driver, if an interrupt source on a GPIO pin is
   "normal" for this device, i.e. if the GPIO is part of that device's
   DT node. No need to use of_find_node_by_path().

2) To the board file if it's something optional, like in this ethernet
   example, the IRQ for an SMSC91 is usually routed directly
   to the CPU, so having a GPIO IRQ being used instead is
   pretty odd and we set it up as input and the driver will just
   request it as "any irq".

> Rajendra cooked up a patch while back on the same
> topic which am attaching for the reference. Please let us know
> your input whether attached patch make sense or any other
> alternative you have.

This doesn't seem right. It changes the semantics of a DT kernel from
that of a non-DT kernel. It will certainly lead to breakage and
weirdness if we apply it.

But it does look convenient.

If we proceed in this way I would use a more cautious approach:
what about adding a GPIO irq-hog property to any GPIO controller?
So when registering that gpio_chip, gpiolib can optionally hog
and set up GPIOs as IRQs?

That would be an approach to set default values on some GPIOs
as well, and then set some to be used as IRQs and leave it at
that.

Such as:


        gpio0: gpio@101e4000 {
                compatible = "st,nomadik-gpio";
                reg =  <0x101e4000 0x80>;
                interrupt-parent = <&vica>;
                interrupts = <6>;
                interrupt-controller;
                #interrupt-cells = <2>;
                gpio-controller;
                #gpio-cells = <2>;
                gpio-bank = <0>;
+                input-hog-gpios = <4>, <5>;
+                output-low-hog-gpios = <8>, <9>;
+                output-high-hog-gpios = <10>, <11>;
        };

So in this case that GPIO, when being registered, would set
(local number!) pin 4,5 as inputs, pin 8,9 as outputs low,
and 10, 11 as outputs high.

This makes it possible to just request the IRQ on one
of the input pins (4, 5) later.

However it is a bit awkward since you're never using
gpio_to_irq() to figure out the IRQ number, so I still think
the explicit code up above is better.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rajendra Nayak Jan. 22, 2013, 9:54 a.m. UTC | #2
On Tuesday 22 January 2013 01:52 PM, Linus Walleij wrote:
> In the Nomadik I had a similar situation with a GPIO used for the
> ethernet IRQ. I put the GPIO number in a special board-specific
> node and added this to the machine,

Thanks Linus. Are there any bindings already available on how these
special board-specific nodes can be defined in the dts files?
Are there any using some such in the mainline already?

regards,
Rajendra
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Linus Walleij Jan. 22, 2013, 10:07 a.m. UTC | #3
On Tue, Jan 22, 2013 at 10:54 AM, Rajendra Nayak <rnayak@ti.com> wrote:
> On Tuesday 22 January 2013 01:52 PM, Linus Walleij wrote:
>>
>> In the Nomadik I had a similar situation with a GPIO used for the
>> ethernet IRQ. I put the GPIO number in a special board-specific
>> node and added this to the machine,
>
> Thanks Linus. Are there any bindings already available on how these
> special board-specific nodes can be defined in the dts files?

No generic bindings as they are per definition board-specific.

So in the Nomadik case it looks like this:

        /* Custom board node with GPIO pins to active etc */
        usb-s8815 {
                /* The S8815 is using this very GPIO pin for the SMSC91x IRQs */
                ethernet-gpio {
                        gpios = <&gpio3 19 0x1>;
                        interrupts = <19 0x1>;
                        interrupt-parent = <&gpio3>;
                };
                /* This will bias the MMC/SD card detect line */
                mmcsd-gpio {
                        gpios = <&gpio3 16 0x1>;
                };
        };

First I added custom nodes to the IP blocks, but it was no good idea
as it's not generic for that driver at all, just a board pecularity.

> Are there any using some such in the mainline already?

I just sent a pull request for the Nomadik example but I don't
know about any others.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Santosh Shilimkar Jan. 27, 2013, 1:05 p.m. UTC | #4
On Tuesday 22 January 2013 03:37 PM, Linus Walleij wrote:
> On Tue, Jan 22, 2013 at 10:54 AM, Rajendra Nayak <rnayak@ti.com> wrote:
>> On Tuesday 22 January 2013 01:52 PM, Linus Walleij wrote:
>>>
>>> In the Nomadik I had a similar situation with a GPIO used for the
>>> ethernet IRQ. I put the GPIO number in a special board-specific
>>> node and added this to the machine,
>>
>> Thanks Linus. Are there any bindings already available on how these
>> special board-specific nodes can be defined in the dts files?
>
> No generic bindings as they are per definition board-specific.
>
> So in the Nomadik case it looks like this:
>
>          /* Custom board node with GPIO pins to active etc */
>          usb-s8815 {
>                  /* The S8815 is using this very GPIO pin for the SMSC91x IRQs */
>                  ethernet-gpio {
>                          gpios = <&gpio3 19 0x1>;
>                          interrupts = <19 0x1>;
>                          interrupt-parent = <&gpio3>;
>                  };
>                  /* This will bias the MMC/SD card detect line */
>                  mmcsd-gpio {
>                          gpios = <&gpio3 16 0x1>;
>                  };
>          };
>
> First I added custom nodes to the IP blocks, but it was no good idea
> as it's not generic for that driver at all, just a board pecularity.
>
>> Are there any using some such in the mainline already?
>
> I just sent a pull request for the Nomadik example but I don't
> know about any others.
>
Thanks Linus for the pointer.

Regards
Santosh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

From 90290e5fac1673745f0bd38ac1cf49c4ce502593 Mon Sep 17 00:00:00 2001
From: Rajendra Nayak <rnayak@ti.com>
Date: Fri, 3 Aug 2012 16:33:54 +0530
Subject: [PATCH] irqdomain: Do a gpio_request in case of a gpio irq_chip

On architectures which support DT, and have devices which use gpios as irqs,
the irqdomain does the job of transalating the gpio number mapped to the
gpio based irq controller to a virtual irq number in the linux irq space.
A gpio_request in such cases though, seems to be missing.

Add a flag to irq_chip for identifying if its a gpio based irq_chip,
and use it to then do a gpio_request() from irq_domain.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Reported-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
Reported-by: Sourav Poddar <sourav.poddar@ti.com>
---
 include/linux/irq.h    |    1 +
 kernel/irq/irqdomain.c |    6 ++++++
 2 files changed, 7 insertions(+)

Index: linux-2.6/kernel/irq/irqdomain.c
===================================================================
--- linux-2.6.orig/kernel/irq/irqdomain.c	2012-08-07 18:52:18.347378581 +0530
+++ linux-2.6/kernel/irq/irqdomain.c	2012-08-07 18:55:12.618377958 +0530
@@ -15,6 +15,7 @@ 
 #include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/fs.h>
+#include <linux/gpio.h>
 
 #define IRQ_DOMAIN_MAP_LEGACY 0 /* driver allocated fixed range of irqs.
 				 * ie. legacy 8259, gets irqs 1..15 */
@@ -617,6 +618,7 @@ 
 				   const u32 *intspec, unsigned int intsize)
 {
 	struct irq_domain *domain;
+	struct irq_chip *chip;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
 	unsigned int virq;
@@ -654,6 +656,10 @@ 
 	if (!virq)
 		return virq;
 
+	chip = irq_get_chip(virq);
+	if (chip->flags & IRQCHIP_IS_GPIO)
+		gpio_request(irq_to_gpio(virq), "irq_domain");
+
 	/* Set type if specified and different than the current one */
 	if (type != IRQ_TYPE_NONE &&
 	    type != (irqd_get_trigger_type(irq_get_irq_data(virq))))
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h	2012-08-07 18:52:18.339378810 +0530
+++ linux-2.6/include/linux/irq.h	2012-08-07 18:52:59.434199592 +0530
@@ -349,6 +349,7 @@ 
 	IRQCHIP_MASK_ON_SUSPEND		= (1 <<  2),
 	IRQCHIP_ONOFFLINE_ENABLED	= (1 <<  3),
 	IRQCHIP_SKIP_SET_WAKE		= (1 <<  4),
+	IRQCHIP_IS_GPIO			= (1 <<  5),
 };
 
 /* This include will go away once we isolated irq_desc usage to core code */