[PATCH 8/9] gpio: pl061: enable interrupts with DT style binding
Grant Likely
grant.likely at secretlab.ca
Wed Dec 14 16:39:26 EST 2011
On Wed, Dec 14, 2011 at 8:28 AM, Rob Herring <robherring2 at gmail.com> wrote:
> From: Rob Herring <rob.herring at calxeda.com>
>
> Enable DT interrupt binding support for pl061 gpio lines. If the gpio
> node has an interrupt-controller property, then it will be setup to
> handle interrupts on gpio lines.
>
> Signed-off-by: Rob Herring <rob.herring at calxeda.com>
> Cc: Grant Likely <grant.likely at secretlab.ca>
> Cc: Linus Walleij <linus.ml.walleij at gmail.com>
> ---
> .../devicetree/bindings/gpio/pl061-gpio.txt | 15 ++++++++++
> drivers/gpio/gpio-pl061.c | 29 +++++++++++--------
> 2 files changed, 32 insertions(+), 12 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/gpio/pl061-gpio.txt b/Documentation/devicetree/bindings/gpio/pl061-gpio.txt
> index a2c416b..9671d4e 100644
> --- a/Documentation/devicetree/bindings/gpio/pl061-gpio.txt
> +++ b/Documentation/devicetree/bindings/gpio/pl061-gpio.txt
> @@ -8,3 +8,18 @@ Required properties:
> - gpio-controller : Marks the device node as a GPIO controller.
> - interrupts : Interrupt mapping for GPIO IRQ.
>
> +Optional properties:
> +- interrupt-controller : Identifies the node as an interrupt controller. Must
> + be present if using gpios lines for interrupts.
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> + interrupt source. The type shall be a <u32> and the value shall be 2.
> +
> + The 1st cell contains the interrupt number 0-7 corresponding to the gpio
> + line.
> +
> + The 2nd cell is the flags, encoding trigger type and level flags.
> + 1 = low-to-high edge triggered
> + 2 = high-to-low edge triggered
> + 4 = active high level-sensitive
> + 8 = active low level-sensitive
> +
> diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
> index 4a1874f..0151798 100644
> --- a/drivers/gpio/gpio-pl061.c
> +++ b/drivers/gpio/gpio-pl061.c
> @@ -16,6 +16,8 @@
> #include <linux/io.h>
> #include <linux/ioport.h>
> #include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/of.h>
> #include <linux/bitops.h>
> #include <linux/workqueue.h>
> #include <linux/gpio.h>
> @@ -52,7 +54,7 @@ struct pl061_gpio {
> spinlock_t lock; /* GPIO registers */
>
> void __iomem *base;
> - int irq_base;
> + struct irq_domain *irq_domain;
> struct gpio_chip gc;
> };
>
> @@ -117,18 +119,16 @@ static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
> static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
> {
> struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
> -
> - if (chip->irq_base <= 0)
> - return -EINVAL;
> -
> - return chip->irq_base + offset;
> + if (!chip->irq_domain)
> + return -ENXIO;
> + return irq_domain_to_irq(chip->irq_domain, offset);
> }
>
> static int pl061_irq_type(struct irq_data *d, unsigned trigger)
> {
> struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
> struct pl061_gpio *chip = gc->private;
> - int offset = d->irq - chip->irq_base;
> + int offset = d->hwirq;
> unsigned long flags;
> u8 gpiois, gpioibe, gpioiev;
>
> @@ -212,6 +212,7 @@ static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
>
> irq_setup_generic_chip(gc, IRQ_MSK(PL061_GPIO_NR),
> IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
> + chip->irq_domain = gc->domain;
I would expect the driver to store chip->gc = gc instead. Then the
driver has access to both structures, and if ever needed, the gc could
be freed on driver release.
> }
>
> static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
> @@ -219,7 +220,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
> struct pl061_platform_data *pdata;
> struct pl061_gpio *chip;
> struct list_head *chip_list;
> - int ret, irq, i;
> + int ret, irq, i, irq_base;
> static DECLARE_BITMAP(init_irq, NR_IRQS);
>
> chip = kzalloc(sizeof(*chip), GFP_KERNEL);
> @@ -229,10 +230,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
> pdata = dev->dev.platform_data;
> if (pdata) {
> chip->gc.base = pdata->gpio_base;
> - chip->irq_base = pdata->irq_base;
> + irq_base = pdata->irq_base;
> } else if (dev->dev.of_node) {
> chip->gc.base = -1;
> - chip->irq_base = 0;
> + if (of_get_property(dev->dev.of_node, "interrupt-controller", NULL))
> + irq_base = -1;
> + else
> + irq_base = 0;
> } else {
> ret = -ENODEV;
> goto free_mem;
> @@ -271,10 +275,11 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
> * irq_chip support
> */
>
> - if (chip->irq_base <= 0)
> + if (!irq_base)
> return 0;
A comment would be useful here as it took a bit for me to work out
what the options are here. What are the possible values of irq_base
at this point, and what do they mean?
Otherwise looks pretty good.
g.
More information about the linux-arm-kernel
mailing list