Merge tag 'arc-v3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc
[firefly-linux-kernel-4.4.55.git] / drivers / pinctrl / pinctrl-nomadik.c
index 53a11114927fc2278456444dc22ae6ac8f1af964..208341fd57d27f9f7dc3ed3df63783bac5a09fd1 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>
@@ -246,28 +243,14 @@ enum nmk_gpio_slpm {
        NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
 };
 
-/*
- * Platform data to register a block: only the initial gpio/irq number.
- */
-struct nmk_gpio_platform_data {
-       char *name;
-       int first_gpio;
-       int first_irq;
-       int num_gpio;
-       u32 (*get_secondary_status)(unsigned int bank);
-       void (*set_ioforce)(bool enable);
-       bool supports_sleepmode;
-};
-
 struct nmk_gpio_chip {
        struct gpio_chip chip;
-       struct irq_domain *domain;
        void __iomem *addr;
        struct clk *clk;
        unsigned int bank;
        unsigned int parent_irq;
-       int secondary_parent_irq;
-       u32 (*get_secondary_status)(unsigned int bank);
+       int latent_parent_irq;
+       u32 (*get_latent_status)(unsigned int bank);
        void (*set_ioforce)(bool enable);
        spinlock_t lock;
        bool sleepmode;
@@ -432,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)
@@ -660,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,10 +828,6 @@ static unsigned int nmk_gpio_irq_startup(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);
        clk_enable(nmk_chip->clk);
        nmk_gpio_irq_unmask(d);
        return 0;
@@ -863,7 +839,6 @@ static void nmk_gpio_irq_shutdown(struct irq_data *d)
 
        nmk_gpio_irq_mask(d);
        clk_disable(nmk_chip->clk);
-       gpio_unlock_as_irq(&nmk_chip->chip, d->hwirq);
 }
 
 static struct irq_chip nmk_gpio_irq_chip = {
@@ -881,16 +856,15 @@ static struct irq_chip nmk_gpio_irq_chip = {
 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);
        }
 
@@ -899,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);
@@ -909,29 +885,16 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
        __nmk_gpio_irq_handler(irq, desc, status);
 }
 
-static void nmk_gpio_secondary_irq_handler(unsigned int irq,
+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);
-       u32 status = nmk_chip->get_secondary_status(nmk_chip->bank);
+       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->secondary_parent_irq >= 0) {
-               irq_set_chained_handler(nmk_chip->secondary_parent_irq,
-                                       nmk_gpio_secondary_irq_handler);
-               irq_set_handler_data(nmk_chip->secondary_parent_irq, nmk_chip);
-       }
-
-       return 0;
-}
-
 /* I/O Functions */
 
 static int nmk_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -1010,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>
@@ -1116,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,
 };
@@ -1217,62 +1171,35 @@ 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 nmk_gpio_platform_data *pdata;
        struct device_node *np = dev->dev.of_node;
        struct nmk_gpio_chip *nmk_chip;
        struct gpio_chip *chip;
        struct resource *res;
        struct clk *clk;
-       int secondary_irq;
+       int latent_irq;
+       bool supports_sleepmode;
        void __iomem *base;
        int irq;
        int ret;
 
-       pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
-       if (!pdata)
-               return -ENOMEM;
-
        if (of_get_property(np, "st,supports-sleepmode", NULL))
-               pdata->supports_sleepmode = true;
+               supports_sleepmode = true;
+       else
+               supports_sleepmode = false;
 
        if (of_property_read_u32(np, "gpio-bank", &dev->id)) {
                dev_err(&dev->dev, "gpio-bank property not found\n");
                return -EINVAL;
        }
 
-       pdata->first_gpio = dev->id * NMK_GPIO_PER_CHIP;
-       pdata->num_gpio = NMK_GPIO_PER_CHIP;
-
        irq = platform_get_irq(dev, 0);
        if (irq < 0)
                return irq;
 
-       secondary_irq = platform_get_irq(dev, 1);
-       if (secondary_irq >= 0 && !pdata->get_secondary_status)
-               return -EINVAL;
+       /* It's OK for this IRQ not to be present */
+       latent_irq = platform_get_irq(dev, 1);
 
        res = platform_get_resource(dev, IORESOURCE_MEM, 0);
        base = devm_ioremap_resource(&dev->dev, res);
@@ -1297,16 +1224,14 @@ static int nmk_gpio_probe(struct platform_device *dev)
        nmk_chip->addr = base;
        nmk_chip->chip = nmk_gpio_template;
        nmk_chip->parent_irq = irq;
-       nmk_chip->secondary_parent_irq = secondary_irq;
-       nmk_chip->get_secondary_status = pdata->get_secondary_status;
-       nmk_chip->set_ioforce = pdata->set_ioforce;
-       nmk_chip->sleepmode = pdata->supports_sleepmode;
+       nmk_chip->latent_parent_irq = latent_irq;
+       nmk_chip->sleepmode = supports_sleepmode;
        spin_lock_init(&nmk_chip->lock);
 
        chip = &nmk_chip->chip;
-       chip->base = pdata->first_gpio;
-       chip->ngpio = pdata->num_gpio;
-       chip->label = pdata->name ?: dev_name(&dev->dev);
+       chip->base = dev->id * NMK_GPIO_PER_CHIP;
+       chip->ngpio = NMK_GPIO_PER_CHIP;
+       chip->label = dev_name(&dev->dev);
        chip->dev = &dev->dev;
        chip->owner = THIS_MODULE;
 
@@ -1325,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);
 
@@ -2035,27 +1974,29 @@ static const struct of_device_id nmk_pinctrl_match[] = {
        {},
 };
 
-static int nmk_pinctrl_suspend(struct platform_device *pdev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int nmk_pinctrl_suspend(struct device *dev)
 {
        struct nmk_pinctrl *npct;
 
-       npct = platform_get_drvdata(pdev);
+       npct = dev_get_drvdata(dev);
        if (!npct)
                return -EINVAL;
 
        return pinctrl_force_sleep(npct->pctl);
 }
 
-static int nmk_pinctrl_resume(struct platform_device *pdev)
+static int nmk_pinctrl_resume(struct device *dev)
 {
        struct nmk_pinctrl *npct;
 
-       npct = platform_get_drvdata(pdev);
+       npct = dev_get_drvdata(dev);
        if (!npct)
                return -EINVAL;
 
        return pinctrl_force_default(npct->pctl);
 }
+#endif
 
 static int nmk_pinctrl_probe(struct platform_device *pdev)
 {
@@ -2144,17 +2085,18 @@ static struct platform_driver nmk_gpio_driver = {
        .probe = nmk_gpio_probe,
 };
 
+static SIMPLE_DEV_PM_OPS(nmk_pinctrl_pm_ops,
+                       nmk_pinctrl_suspend,
+                       nmk_pinctrl_resume);
+
 static struct platform_driver nmk_pinctrl_driver = {
        .driver = {
                .owner = THIS_MODULE,
                .name = "pinctrl-nomadik",
                .of_match_table = nmk_pinctrl_match,
+               .pm = &nmk_pinctrl_pm_ops,
        },
        .probe = nmk_pinctrl_probe,
-#ifdef CONFIG_PM
-       .suspend = nmk_pinctrl_suspend,
-       .resume = nmk_pinctrl_resume,
-#endif
 };
 
 static int __init nmk_gpio_init(void)