]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
pinctrl: nomadik: convert driver to use gpiolib irqchip
authorLinus Walleij <linus.walleij@linaro.org>
Tue, 25 Mar 2014 09:44:09 +0000 (10:44 +0100)
committerLinus Walleij <linus.walleij@linaro.org>
Wed, 26 Mar 2014 09:31:33 +0000 (10:31 +0100)
This converts the Nomadik pin control driver to register its
chained irq handler and irqchip using the helpers in the
gpiolib core.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/pinctrl/Kconfig
drivers/pinctrl/pinctrl-nomadik.c

index 1e4e69384baaed11ae859ce6a784eef0d8fa0f9c..a05087bd1955c1bad21e280ed8685c5fdcd53827 100644 (file)
@@ -235,6 +235,9 @@ config PINCTRL_NOMADIK
        depends on ARCH_U8500 || ARCH_NOMADIK
        select PINMUX
        select PINCONF
+       select GPIOLIB
+       select OF_GPIO
+       select GPIOLIB_IRQCHIP
 
 config PINCTRL_STN8815
        bool "STN8815 pin controller driver"
index 98a36a0969f9e4e30e9bbbc2ee59402c6ea0d2a4..db0cc30c82de5d79fefefb56fa70fd194d2177d5 100644 (file)
@@ -21,9 +21,6 @@
 #include <linux/gpio.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/irqchip/chained_irq.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
 #include <linux/of_address.h>
@@ -248,7 +245,6 @@ enum nmk_gpio_slpm {
 
 struct nmk_gpio_chip {
        struct gpio_chip chip;
-       struct irq_domain *domain;
        void __iomem *addr;
        struct clk *clk;
        unsigned int bank;
@@ -419,7 +415,7 @@ nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset)
        u32 falling = nmk_chip->fimsc & BIT(offset);
        u32 rising = nmk_chip->rimsc & BIT(offset);
        int gpio = nmk_chip->chip.base + offset;
-       int irq = irq_find_mapping(nmk_chip->domain, offset);
+       int irq = irq_find_mapping(nmk_chip->chip.irqdomain, offset);
        struct irq_data *d = irq_get_irq_data(irq);
 
        if (!rising && !falling)
@@ -647,11 +643,8 @@ static inline int nmk_gpio_get_bitmask(int gpio)
 
 static void nmk_gpio_irq_ack(struct irq_data *d)
 {
-       struct nmk_gpio_chip *nmk_chip;
-
-       nmk_chip = irq_data_get_irq_chip_data(d);
-       if (!nmk_chip)
-               return;
+       struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+       struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
 
        clk_enable(nmk_chip->clk);
        writel(nmk_gpio_get_bitmask(d->hwirq), nmk_chip->addr + NMK_GPIO_IC);
@@ -848,26 +841,6 @@ static void nmk_gpio_irq_shutdown(struct irq_data *d)
        clk_disable(nmk_chip->clk);
 }
 
-static int nmk_gpio_irq_reqres(struct irq_data *d)
-{
-       struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
-
-       if (gpio_lock_as_irq(&nmk_chip->chip, d->hwirq)) {
-               dev_err(nmk_chip->chip.dev,
-                       "unable to lock HW IRQ %lu for IRQ\n",
-                       d->hwirq);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static void nmk_gpio_irq_relres(struct irq_data *d)
-{
-       struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
-
-       gpio_unlock_as_irq(&nmk_chip->chip, d->hwirq);
-}
-
 static struct irq_chip nmk_gpio_irq_chip = {
        .name           = "Nomadik-GPIO",
        .irq_ack        = nmk_gpio_irq_ack,
@@ -877,24 +850,21 @@ static struct irq_chip nmk_gpio_irq_chip = {
        .irq_set_wake   = nmk_gpio_irq_set_wake,
        .irq_startup    = nmk_gpio_irq_startup,
        .irq_shutdown   = nmk_gpio_irq_shutdown,
-       .irq_request_resources = nmk_gpio_irq_reqres,
-       .irq_release_resources = nmk_gpio_irq_relres,
        .flags          = IRQCHIP_MASK_ON_SUSPEND,
 };
 
 static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
                                   u32 status)
 {
-       struct nmk_gpio_chip *nmk_chip;
        struct irq_chip *host_chip = irq_get_chip(irq);
+       struct gpio_chip *chip = irq_desc_get_handler_data(desc);
 
        chained_irq_enter(host_chip, desc);
 
-       nmk_chip = irq_get_handler_data(irq);
        while (status) {
                int bit = __ffs(status);
 
-               generic_handle_irq(irq_find_mapping(nmk_chip->domain, bit));
+               generic_handle_irq(irq_find_mapping(chip->irqdomain, bit));
                status &= ~BIT(bit);
        }
 
@@ -903,9 +873,11 @@ static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
 
 static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
-       struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
+       struct gpio_chip *chip = irq_desc_get_handler_data(desc);
+       struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
        u32 status;
 
+       pr_err("PLONK IRQ %d\n", irq);
        clk_enable(nmk_chip->clk);
        status = readl(nmk_chip->addr + NMK_GPIO_IS);
        clk_disable(nmk_chip->clk);
@@ -916,26 +888,13 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 static void nmk_gpio_latent_irq_handler(unsigned int irq,
                                           struct irq_desc *desc)
 {
-       struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
+       struct gpio_chip *chip = irq_desc_get_handler_data(desc);
+       struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
        u32 status = nmk_chip->get_latent_status(nmk_chip->bank);
 
        __nmk_gpio_irq_handler(irq, desc, status);
 }
 
-static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
-{
-       irq_set_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler);
-       irq_set_handler_data(nmk_chip->parent_irq, nmk_chip);
-
-       if (nmk_chip->latent_parent_irq >= 0) {
-               irq_set_chained_handler(nmk_chip->latent_parent_irq,
-                                       nmk_gpio_latent_irq_handler);
-               irq_set_handler_data(nmk_chip->latent_parent_irq, nmk_chip);
-       }
-
-       return 0;
-}
-
 /* I/O Functions */
 
 static int nmk_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -1014,14 +973,6 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
        return 0;
 }
 
-static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct nmk_gpio_chip *nmk_chip =
-               container_of(chip, struct nmk_gpio_chip, chip);
-
-       return irq_create_mapping(nmk_chip->domain, offset);
-}
-
 #ifdef CONFIG_DEBUG_FS
 
 #include <linux/seq_file.h>
@@ -1120,7 +1071,6 @@ static struct gpio_chip nmk_gpio_template = {
        .get                    = nmk_gpio_get_input,
        .direction_output       = nmk_gpio_make_output,
        .set                    = nmk_gpio_set_output,
-       .to_irq                 = nmk_gpio_to_irq,
        .dbg_show               = nmk_gpio_dbg_show,
        .can_sleep              = false,
 };
@@ -1221,27 +1171,6 @@ void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up)
        }
 }
 
-static int nmk_gpio_irq_map(struct irq_domain *d, unsigned int irq,
-                           irq_hw_number_t hwirq)
-{
-       struct nmk_gpio_chip *nmk_chip = d->host_data;
-
-       if (!nmk_chip)
-               return -EINVAL;
-
-       irq_set_chip_and_handler(irq, &nmk_gpio_irq_chip, handle_edge_irq);
-       set_irq_flags(irq, IRQF_VALID);
-       irq_set_chip_data(irq, nmk_chip);
-       irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING);
-
-       return 0;
-}
-
-static const struct irq_domain_ops nmk_gpio_irq_simple_ops = {
-       .map = nmk_gpio_irq_map,
-       .xlate = irq_domain_xlate_twocell,
-};
-
 static int nmk_gpio_probe(struct platform_device *dev)
 {
        struct device_node *np = dev->dev.of_node;
@@ -1321,17 +1250,31 @@ static int nmk_gpio_probe(struct platform_device *dev)
 
        platform_set_drvdata(dev, nmk_chip);
 
-       nmk_chip->domain = irq_domain_add_simple(np,
-                               NMK_GPIO_PER_CHIP, 0,
-                               &nmk_gpio_irq_simple_ops, nmk_chip);
-       if (!nmk_chip->domain) {
-               dev_err(&dev->dev, "failed to create irqdomain\n");
-               /* Just do this, no matter if it fails */
+       /*
+        * 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(&nmk_chip->chip,
+                                  &nmk_gpio_irq_chip,
+                                  0,
+                                  handle_edge_irq,
+                                  IRQ_TYPE_EDGE_FALLING);
+       if (ret) {
+               dev_err(&dev->dev, "could not add irqchip\n");
                ret = gpiochip_remove(&nmk_chip->chip);
-               return -ENOSYS;
+               return -ENODEV;
        }
-
-       nmk_gpio_init_irq(nmk_chip);
+       /* Then register the chain on the parent IRQ */
+       gpiochip_set_chained_irqchip(&nmk_chip->chip,
+                                    &nmk_gpio_irq_chip,
+                                    nmk_chip->parent_irq,
+                                    nmk_gpio_irq_handler);
+       if (nmk_chip->latent_parent_irq > 0)
+               gpiochip_set_chained_irqchip(&nmk_chip->chip,
+                                            &nmk_gpio_irq_chip,
+                                            nmk_chip->latent_parent_irq,
+                                            nmk_gpio_latent_irq_handler);
 
        dev_info(&dev->dev, "at address %p\n", nmk_chip->addr);