]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
pinctrl/coh901: use irqdomain, allocate irqdescs
authorLinus Walleij <linus.walleij@linaro.org>
Wed, 17 Oct 2012 16:31:20 +0000 (18:31 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Sun, 11 Nov 2012 18:06:02 +0000 (19:06 +0100)
This switches the COH 901 pinctrl driver to allocate its GPIO
IRQs dynamically, and start to use a linear irqdomain to map
from the hardware IRQs.

This way we can cut away the complex allocation of IRQ numbers
from the <mach/irqs.h> file.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
arch/arm/mach-u300/core.c
arch/arm/mach-u300/include/mach/irqs.h
drivers/pinctrl/pinctrl-coh901.c
include/linux/platform_data/pinctrl-coh901.h

index 603c08ec8786da77c414f968cf6368b2e46ed8c8..ce2de0d6f2ebaf2e6f4b50b6cb8a4c9ec98c7d2f 100644 (file)
@@ -1445,7 +1445,6 @@ static struct platform_device pinctrl_device = {
 static struct u300_gpio_platform u300_gpio_plat = {
        .ports = 7,
        .gpio_base = 0,
-       .gpio_irq_base = IRQ_U300_GPIO_BASE,
        .pinctrl_device = &pinctrl_device,
 };
 
index e85ec3868d049ad15d3cd00d659da9c3bb6c9095..21d5e76a6cd3da0f123233872c8ebbfa093fb3d5 100644 (file)
 #define IRQ_U300_GPIO_PORT6            87
 #define U300_VIC_IRQS_END              88
 
-/* Maximum 8*7 GPIO lines */
-#ifdef CONFIG_PINCTRL_COH901
-#define IRQ_U300_GPIO_BASE             (U300_VIC_IRQS_END)
-#define IRQ_U300_GPIO_END              (IRQ_U300_GPIO_BASE + 56)
-#else
-#define IRQ_U300_GPIO_END              (U300_VIC_IRQS_END)
-#endif
-
-#define NR_IRQS_U300                   (IRQ_U300_GPIO_END - IRQ_U300_INTCON0_START)
-
 #endif
index b446c9641212884f8cb2ff5e7df0d81aa032dca3..152efae3df8f39637f0ea750c90ca7dd99464170 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
@@ -67,7 +68,6 @@ struct u300_gpio {
        struct resource *memres;
        void __iomem *base;
        struct device *dev;
-       int irq_base;
        u32 stride;
        /* Register offsets */
        u32 pcr;
@@ -83,6 +83,7 @@ struct u300_gpio_port {
        struct list_head node;
        struct u300_gpio *gpio;
        char name[8];
+       struct irq_domain *domain;
        int irq;
        int number;
        u8 toggle_edge_mode;
@@ -314,10 +315,30 @@ static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
        struct u300_gpio *gpio = to_u300_gpio(chip);
-       int retirq = gpio->irq_base + offset;
+       int portno = offset >> 3;
+       struct u300_gpio_port *port = NULL;
+       struct list_head *p;
+       int retirq;
 
-       dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d\n", offset,
-               retirq);
+       list_for_each(p, &gpio->port_list) {
+               port = list_entry(p, struct u300_gpio_port, node);
+               if (port->number == portno)
+                       break;
+       }
+       if (port == NULL) {
+               dev_err(gpio->dev, "could not locate port for GPIO %d IRQ\n",
+                       offset);
+               return -EINVAL;
+       }
+
+       /*
+        * The local hwirqs on the port are the lower three bits, there
+        * are exactly 8 IRQs per port since they are 8-bit
+        */
+       retirq = irq_find_mapping(port->domain, (offset & 0x7));
+
+       dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d from port %d\n",
+               offset, retirq, port->number);
        return retirq;
 }
 
@@ -467,7 +488,7 @@ static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger)
 {
        struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
        struct u300_gpio *gpio = port->gpio;
-       int offset = d->irq - gpio->irq_base;
+       int offset = (port->number << 3) + d->hwirq;
        u32 val;
 
        if ((trigger & IRQF_TRIGGER_RISING) &&
@@ -503,10 +524,12 @@ static void u300_gpio_irq_enable(struct irq_data *d)
 {
        struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
        struct u300_gpio *gpio = port->gpio;
-       int offset = d->irq - gpio->irq_base;
+       int offset = (port->number << 3) + d->hwirq;
        u32 val;
        unsigned long flags;
 
+       dev_dbg(gpio->dev, "enable IRQ for hwirq %lu on port %s, offset %d\n",
+                d->hwirq, port->name, offset);
        local_irq_save(flags);
        val = readl(U300_PIN_REG(offset, ien));
        writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
@@ -517,7 +540,7 @@ static void u300_gpio_irq_disable(struct irq_data *d)
 {
        struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
        struct u300_gpio *gpio = port->gpio;
-       int offset = d->irq - gpio->irq_base;
+       int offset = (port->number << 3) + d->hwirq;
        u32 val;
        unsigned long flags;
 
@@ -555,8 +578,7 @@ static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
                int irqoffset;
 
                for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) {
-                       int pin_irq = gpio->irq_base + (port->number << 3)
-                               + irqoffset;
+                       int pin_irq = irq_find_mapping(port->domain, irqoffset);
                        int offset = pinoffset + irqoffset;
 
                        dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n",
@@ -631,6 +653,8 @@ static inline void u300_gpio_free_ports(struct u300_gpio *gpio)
        list_for_each_safe(p, n, &gpio->port_list) {
                port = list_entry(p, struct u300_gpio_port, node);
                list_del(&port->node);
+               if (port->domain)
+                       irq_domain_remove(port->domain);
                kfree(port);
        }
 }
@@ -653,7 +677,6 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
 
        gpio->chip = u300_gpio_chip;
        gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT;
-       gpio->irq_base = plat->gpio_irq_base;
        gpio->chip.dev = &pdev->dev;
        gpio->chip.base = plat->gpio_base;
        gpio->dev = &pdev->dev;
@@ -732,18 +755,26 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
                port->irq = platform_get_irq_byname(pdev,
                                                    port->name);
 
-               dev_dbg(gpio->dev, "register IRQ %d for %s\n", port->irq,
+               dev_dbg(gpio->dev, "register IRQ %d for port %s\n", port->irq,
                        port->name);
 
+               port->domain = irq_domain_add_linear(pdev->dev.of_node,
+                                                    U300_GPIO_PINS_PER_PORT,
+                                                    &irq_domain_simple_ops,
+                                                    port);
+               if (!port->domain)
+                       goto err_no_domain;
+
                irq_set_chained_handler(port->irq, u300_gpio_irq_handler);
                irq_set_handler_data(port->irq, port);
 
                /* For each GPIO pin set the unique IRQ handler */
                for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) {
-                       int irqno = gpio->irq_base + (portno << 3) + i;
+                       int irqno = irq_create_mapping(port->domain, i);
 
-                       dev_dbg(gpio->dev, "handler for IRQ %d on %s\n",
-                               irqno, port->name);
+                       dev_dbg(gpio->dev, "GPIO%d on port %s gets IRQ %d\n",
+                               gpio->chip.base + (port->number << 3) + i,
+                               port->name, irqno);
                        irq_set_chip_and_handler(irqno, &u300_gpio_irqchip,
                                                 handle_simple_irq);
                        set_irq_flags(irqno, IRQF_VALID);
@@ -776,6 +807,7 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
 err_no_pinctrl:
        err = gpiochip_remove(&gpio->chip);
 err_no_chip:
+err_no_domain:
 err_no_port:
        u300_gpio_free_ports(gpio);
        iounmap(gpio->base);
index 30dea251b835b3433af3fd93a840a2d70a91cc57..27a23b318cef9fcdc7f199cf320bb65f601ece9f 100644 (file)
  * struct u300_gpio_platform - U300 GPIO platform data
  * @ports: number of GPIO block ports
  * @gpio_base: first GPIO number for this block (use a free range)
- * @gpio_irq_base: first GPIO IRQ number for this block (use a free range)
  * @pinctrl_device: pin control device to spawn as child
  */
 struct u300_gpio_platform {
        u8 ports;
        int gpio_base;
-       int gpio_irq_base;
        struct platform_device *pinctrl_device;
 };