pinctrl/at91: convert driver to use gpiolib irqchip
authorAlexander Stein <alexanders83@web.de>
Tue, 15 Apr 2014 20:09:41 +0000 (22:09 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Tue, 22 Apr 2014 21:37:21 +0000 (23:37 +0200)
This converts the AT91 pin control driver to register its
chained irq handler and irqchip using the helpers in the
gpiolib core.

Signed-off-by: Alexander Stein <alexanders83@web.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/pinctrl/Kconfig
drivers/pinctrl/pinctrl-at91.c

index fbd7eda7e94640df6f195bbcf203827a532b90b2..8b6597c7bbc2893da1d0c30562ebbc1022f77f4c 100644 (file)
@@ -84,6 +84,9 @@ config PINCTRL_AT91
        depends on ARCH_AT91
        select PINMUX
        select PINCONF
+       select GPIOLIB
+       select OF_GPIO
+       select GPIOLIB_IRQCHIP
        help
          Say Y here to enable the at91 pinctrl driver
 
index 5d24aaec5dbcba04f5669b4d58cef60d844a18a4..0cd8faf5ddd463d260d7a4ce8245966f64700787 100644 (file)
@@ -16,9 +16,6 @@
 #include <linux/of_irq.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/irqchip/chained_irq.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/pinctrl/machine.h>
@@ -47,7 +44,6 @@ struct at91_gpio_chip {
        int                     pioc_idx;       /* PIO bank index */
        void __iomem            *regbase;       /* PIO bank virtual address */
        struct clk              *clock;         /* associated clock */
-       struct irq_domain       *domain;        /* associated irq domain */
        struct at91_pinctrl_mux_ops *ops;       /* ops */
 };
 
@@ -1192,21 +1188,6 @@ static int at91_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
        return 0;
 }
 
-static int at91_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-       int virq;
-
-       if (offset < chip->ngpio)
-               virq = irq_create_mapping(at91_gpio->domain, offset);
-       else
-               virq = -ENXIO;
-
-       dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
-                               chip->label, offset + chip->base, virq);
-       return virq;
-}
-
 #ifdef CONFIG_DEBUG_FS
 static void at91_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 {
@@ -1336,6 +1317,11 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
        return 0;
 }
 
+static void gpio_irq_ack(struct irq_data *d)
+{
+       /* the interrupt is already cleared before by reading ISR */
+}
+
 static unsigned int gpio_irq_startup(struct irq_data *d)
 {
        struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
@@ -1435,6 +1421,7 @@ void at91_pinctrl_gpio_resume(void)
 
 static struct irq_chip gpio_irqchip = {
        .name           = "GPIO",
+       .irq_ack        = gpio_irq_ack,
        .irq_startup    = gpio_irq_startup,
        .irq_shutdown   = gpio_irq_shutdown,
        .irq_disable    = gpio_irq_mask,
@@ -1446,9 +1433,11 @@ static struct irq_chip gpio_irqchip = {
 
 static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = irq_desc_get_chip(desc);
-       struct irq_data *idata = irq_desc_get_irq_data(desc);
-       struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
+       struct irq_chip *chip = irq_get_chip(irq);
+       struct gpio_chip *gpio_chip = irq_desc_get_handler_data(desc);
+       struct at91_gpio_chip *at91_gpio = container_of(gpio_chip,
+                                          struct at91_gpio_chip, chip);
+
        void __iomem    *pio = at91_gpio->regbase;
        unsigned long   isr;
        int             n;
@@ -1469,81 +1458,19 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
                }
 
                for_each_set_bit(n, &isr, BITS_PER_LONG) {
-                       generic_handle_irq(irq_find_mapping(at91_gpio->domain, n));
+                       generic_handle_irq(irq_find_mapping(
+                                          gpio_chip->irqdomain, n));
                }
        }
        chained_irq_exit(chip, desc);
        /* now it may re-trigger */
 }
 
-/*
- * This lock class tells lockdep that GPIO irqs are in a different
- * category than their parents, so it won't report false recursion.
- */
-static struct lock_class_key gpio_lock_class;
-
-static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
-                                                       irq_hw_number_t hw)
-{
-       struct at91_gpio_chip   *at91_gpio = h->host_data;
-       void __iomem            *pio = at91_gpio->regbase;
-       u32                     mask = 1 << hw;
-
-       irq_set_lockdep_class(virq, &gpio_lock_class);
-
-       /*
-        * Can use the "simple" and not "edge" handler since it's
-        * shorter, and the AIC handles interrupts sanely.
-        */
-       irq_set_chip(virq, &gpio_irqchip);
-       if ((at91_gpio->ops == &at91sam9x5_ops) &&
-           (readl_relaxed(pio + PIO_AIMMR) & mask) &&
-           (readl_relaxed(pio + PIO_ELSR) & mask))
-               irq_set_handler(virq, handle_level_irq);
-       else
-               irq_set_handler(virq, handle_simple_irq);
-       set_irq_flags(virq, IRQF_VALID);
-       irq_set_chip_data(virq, at91_gpio);
-
-       return 0;
-}
-
-static int at91_gpio_irq_domain_xlate(struct irq_domain *d,
-                                     struct device_node *ctrlr,
-                                     const u32 *intspec, unsigned int intsize,
-                                     irq_hw_number_t *out_hwirq,
-                                     unsigned int *out_type)
-{
-       struct at91_gpio_chip *at91_gpio = d->host_data;
-       int ret;
-       int pin = at91_gpio->chip.base + intspec[0];
-
-       if (WARN_ON(intsize < 2))
-               return -EINVAL;
-       *out_hwirq = intspec[0];
-       *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
-
-       ret = gpio_request(pin, ctrlr->full_name);
-       if (ret)
-               return ret;
-
-       ret = gpio_direction_input(pin);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static struct irq_domain_ops at91_gpio_ops = {
-       .map    = at91_gpio_irq_map,
-       .xlate  = at91_gpio_irq_domain_xlate,
-};
-
 static int at91_gpio_of_irq_setup(struct device_node *node,
                                  struct at91_gpio_chip *at91_gpio)
 {
-       struct at91_gpio_chip   *prev = NULL;
        struct irq_data         *d = irq_get_irq_data(at91_gpio->pioc_virq);
+       int ret;
 
        at91_gpio->pioc_hwirq = irqd_to_hwirq(d);
 
@@ -1553,26 +1480,25 @@ static int at91_gpio_of_irq_setup(struct device_node *node,
        /* Disable irqs of this PIO controller */
        writel_relaxed(~0, at91_gpio->regbase + PIO_IDR);
 
-       /* Setup irq domain */
-       at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio,
-                                               &at91_gpio_ops, at91_gpio);
-       if (!at91_gpio->domain)
+       /*
+        * Let the generic code handle this edge IRQ, the the chained
+        * handler will perform the actual work of handling the parent
+        * interrupt.
+        */
+       ret = gpiochip_irqchip_add(&at91_gpio->chip,
+                                  &gpio_irqchip,
+                                  0,
+                                  handle_edge_irq,
+                                  IRQ_TYPE_EDGE_BOTH);
+       if (ret)
                panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n",
                        at91_gpio->pioc_idx);
 
-       /* Setup chained handler */
-       if (at91_gpio->pioc_idx)
-               prev = gpio_chips[at91_gpio->pioc_idx - 1];
-
-       /* The top level handler handles one bank of GPIOs, except
-        * on some SoC it can handle up to three...
-        * We only set up the handler for the first of the list.
-        */
-       if (prev && prev->next == at91_gpio)
-               return 0;
-
-       irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio);
-       irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler);
+       /* Then register the chain on the parent IRQ */
+       gpiochip_set_chained_irqchip(&at91_gpio->chip,
+                                    &gpio_irqchip,
+                                    at91_gpio->pioc_virq,
+                                    gpio_irq_handler);
 
        return 0;
 }
@@ -1586,7 +1512,6 @@ static struct gpio_chip at91_gpio_template = {
        .get                    = at91_gpio_get,
        .direction_output       = at91_gpio_direction_output,
        .set                    = at91_gpio_set,
-       .to_irq                 = at91_gpio_to_irq,
        .dbg_show               = at91_gpio_dbg_show,
        .can_sleep              = false,
        .ngpio                  = MAX_NB_GPIO_PER_BANK,