gpio: omap: fix omap_gpio_free to not clean up irq configuration
[deliverable/linux.git] / drivers / gpio / gpio-omap.c
index cd1d5bf48f36e8a490e6a99fbafdf98c4b2abadf..505266153b4c7036445517118acae3d02ffd36f4 100644 (file)
@@ -690,8 +690,11 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
 
        spin_lock_irqsave(&bank->lock, flags);
        bank->mod_usage &= ~(BIT(offset));
+       if (!LINE_USED(bank->irq_usage, offset)) {
+               omap_set_gpio_direction(bank, offset, 1);
+               omap_clear_gpio_debounce(bank, offset);
+       }
        omap_disable_gpio_module(bank, offset);
-       omap_reset_gpio(bank, offset);
        spin_unlock_irqrestore(&bank->lock, flags);
 
        /*
@@ -1054,38 +1057,8 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
                dev_err(bank->dev, "Could not get gpio dbck\n");
 }
 
-static void
-omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
-                   unsigned int num)
-{
-       struct irq_chip_generic *gc;
-       struct irq_chip_type *ct;
-
-       gc = irq_alloc_generic_chip("MPUIO", 1, irq_start, bank->base,
-                                   handle_simple_irq);
-       if (!gc) {
-               dev_err(bank->dev, "Memory alloc failed for gc\n");
-               return;
-       }
-
-       ct = gc->chip_types;
-
-       /* NOTE: No ack required, reading IRQ status clears it. */
-       ct->chip.irq_mask = irq_gc_mask_set_bit;
-       ct->chip.irq_unmask = irq_gc_mask_clr_bit;
-       ct->chip.irq_set_type = omap_gpio_irq_type;
-
-       if (bank->regs->wkup_en)
-               ct->chip.irq_set_wake = omap_gpio_wake_enable;
-
-       ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride;
-       irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
-                              IRQ_NOREQUEST | IRQ_NOPROBE, 0);
-}
-
 static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
 {
-       int j;
        static int gpio;
        int irq_base = 0;
        int ret;
@@ -1132,6 +1105,15 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
        }
 #endif
 
+       /* MPUIO is a bit different, reading IRQ status clears it */
+       if (bank->is_mpuio) {
+               irqc->irq_ack = dummy_irq_chip.irq_ack;
+               irqc->irq_mask = irq_gc_mask_set_bit;
+               irqc->irq_unmask = irq_gc_mask_clr_bit;
+               if (!bank->regs->wkup_en)
+                       irqc->irq_set_wake = NULL;
+       }
+
        ret = gpiochip_irqchip_add(&bank->chip, irqc,
                                   irq_base, omap_gpio_irq_handler,
                                   IRQ_TYPE_NONE);
@@ -1145,15 +1127,6 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
        gpiochip_set_chained_irqchip(&bank->chip, irqc,
                                     bank->irq, omap_gpio_irq_handler);
 
-       for (j = 0; j < bank->width; j++) {
-               int irq = irq_find_mapping(bank->chip.irqdomain, j);
-               if (bank->is_mpuio) {
-                       omap_mpuio_alloc_gc(bank, irq, bank->width);
-                       irq_set_chip_and_handler(irq, NULL, NULL);
-                       set_irq_flags(irq, 0);
-               }
-       }
-
        return 0;
 }
 
@@ -1263,6 +1236,17 @@ static int omap_gpio_probe(struct platform_device *pdev)
        return 0;
 }
 
+static int omap_gpio_remove(struct platform_device *pdev)
+{
+       struct gpio_bank *bank = platform_get_drvdata(pdev);
+
+       list_del(&bank->node);
+       gpiochip_remove(&bank->chip);
+       pm_runtime_disable(bank->dev);
+
+       return 0;
+}
+
 #ifdef CONFIG_ARCH_OMAP2PLUS
 
 #if defined(CONFIG_PM)
@@ -1448,6 +1432,7 @@ static int omap_gpio_runtime_resume(struct device *dev)
 }
 #endif /* CONFIG_PM */
 
+#if IS_BUILTIN(CONFIG_GPIO_OMAP)
 void omap2_gpio_prepare_for_idle(int pwr_mode)
 {
        struct gpio_bank *bank;
@@ -1473,6 +1458,7 @@ void omap2_gpio_resume_after_idle(void)
                pm_runtime_get_sync(bank->dev);
        }
 }
+#endif
 
 #if defined(CONFIG_PM)
 static void omap_gpio_init_context(struct gpio_bank *p)
@@ -1628,6 +1614,7 @@ MODULE_DEVICE_TABLE(of, omap_gpio_match);
 
 static struct platform_driver omap_gpio_driver = {
        .probe          = omap_gpio_probe,
+       .remove         = omap_gpio_remove,
        .driver         = {
                .name   = "omap_gpio",
                .pm     = &gpio_pm_ops,
@@ -1645,3 +1632,13 @@ static int __init omap_gpio_drv_reg(void)
        return platform_driver_register(&omap_gpio_driver);
 }
 postcore_initcall(omap_gpio_drv_reg);
+
+static void __exit omap_gpio_exit(void)
+{
+       platform_driver_unregister(&omap_gpio_driver);
+}
+module_exit(omap_gpio_exit);
+
+MODULE_DESCRIPTION("omap gpio driver");
+MODULE_ALIAS("platform:gpio-omap");
+MODULE_LICENSE("GPL v2");
This page took 0.025185 seconds and 5 git commands to generate.