These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpio / gpio-omap.c
index a0ace27..f7fbb46 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/platform_data/gpio-omap.h>
 
 #define OFF_MODE       1
+#define OMAP4_GPIO_DEBOUNCINGTIME_MASK 0xFF
 
 static LIST_HEAD(omap_gpio_list);
 
@@ -50,7 +51,7 @@ struct gpio_regs {
 struct gpio_bank {
        struct list_head node;
        void __iomem *base;
-       u16 irq;
+       int irq;
        u32 non_wakeup_gpios;
        u32 enabled_non_wakeup_gpios;
        struct gpio_regs context;
@@ -58,6 +59,7 @@ struct gpio_bank {
        u32 level_mask;
        u32 toggle_mask;
        raw_spinlock_t lock;
+       raw_spinlock_t wa_lock;
        struct gpio_chip chip;
        struct clk *dbck;
        u32 mod_usage;
@@ -175,7 +177,7 @@ static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set
 static inline void omap_gpio_dbck_enable(struct gpio_bank *bank)
 {
        if (bank->dbck_enable_mask && !bank->dbck_enabled) {
-               clk_prepare_enable(bank->dbck);
+               clk_enable(bank->dbck);
                bank->dbck_enabled = true;
 
                writel_relaxed(bank->dbck_enable_mask,
@@ -193,7 +195,7 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
                 */
                writel_relaxed(0, bank->base + bank->regs->debounce_en);
 
-               clk_disable_unprepare(bank->dbck);
+               clk_disable(bank->dbck);
                bank->dbck_enabled = false;
        }
 }
@@ -204,8 +206,9 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
  * @offset: the gpio number on this @bank
  * @debounce: debounce time to use
  *
- * OMAP's debounce time is in 31us steps so we need
- * to convert and round up to the closest unit.
+ * OMAP's debounce time is in 31us steps
+ *   <debounce time> = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) x 31
+ * so we need to convert and round up to the closest unit.
  */
 static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
                                    unsigned debounce)
@@ -213,34 +216,33 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
        void __iomem            *reg;
        u32                     val;
        u32                     l;
+       bool                    enable = !!debounce;
 
        if (!bank->dbck_flag)
                return;
 
-       if (debounce < 32)
-               debounce = 0x01;
-       else if (debounce > 7936)
-               debounce = 0xff;
-       else
-               debounce = (debounce / 0x1f) - 1;
+       if (enable) {
+               debounce = DIV_ROUND_UP(debounce, 31) - 1;
+               debounce &= OMAP4_GPIO_DEBOUNCINGTIME_MASK;
+       }
 
        l = BIT(offset);
 
-       clk_prepare_enable(bank->dbck);
+       clk_enable(bank->dbck);
        reg = bank->base + bank->regs->debounce;
        writel_relaxed(debounce, reg);
 
        reg = bank->base + bank->regs->debounce_en;
        val = readl_relaxed(reg);
 
-       if (debounce)
+       if (enable)
                val |= l;
        else
                val &= ~l;
        bank->dbck_enable_mask = val;
 
        writel_relaxed(val, reg);
-       clk_disable_unprepare(bank->dbck);
+       clk_disable(bank->dbck);
        /*
         * Enable debounce clock per module.
         * This call is mandatory because in omap_gpio_request() when
@@ -285,7 +287,7 @@ static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned offset)
                bank->context.debounce = 0;
                writel_relaxed(bank->context.debounce, bank->base +
                             bank->regs->debounce);
-               clk_disable_unprepare(bank->dbck);
+               clk_disable(bank->dbck);
                bank->dbck_enabled = false;
        }
 }
@@ -488,9 +490,6 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
        unsigned long flags;
        unsigned offset = d->hwirq;
 
-       if (!BANK_USED(bank))
-               pm_runtime_get_sync(bank->dev);
-
        if (type & ~IRQ_TYPE_SENSE_MASK)
                return -EINVAL;
 
@@ -500,18 +499,26 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
 
        raw_spin_lock_irqsave(&bank->lock, flags);
        retval = omap_set_gpio_triggering(bank, offset, type);
+       if (retval) {
+               raw_spin_unlock_irqrestore(&bank->lock, flags);
+               goto error;
+       }
        omap_gpio_init_irq(bank, offset);
        if (!omap_gpio_is_input(bank, offset)) {
                raw_spin_unlock_irqrestore(&bank->lock, flags);
-               return -EINVAL;
+               retval = -EINVAL;
+               goto error;
        }
        raw_spin_unlock_irqrestore(&bank->lock, flags);
 
        if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-               __irq_set_handler_locked(d->irq, handle_level_irq);
+               irq_set_handler_locked(d, handle_level_irq);
        else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               irq_set_handler_locked(d, handle_edge_irq);
+
+       return 0;
 
+error:
        return retval;
 }
 
@@ -638,22 +645,18 @@ static int omap_set_gpio_wakeup(struct gpio_bank *bank, unsigned offset,
        return 0;
 }
 
-static void omap_reset_gpio(struct gpio_bank *bank, unsigned offset)
-{
-       omap_set_gpio_direction(bank, offset, 1);
-       omap_set_gpio_irqenable(bank, offset, 0);
-       omap_clear_gpio_irqstatus(bank, offset);
-       omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
-       omap_clear_gpio_debounce(bank, offset);
-}
-
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
 static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable)
 {
        struct gpio_bank *bank = omap_irq_data_get_bank(d);
        unsigned offset = d->hwirq;
+       int ret;
+
+       ret = omap_set_gpio_wakeup(bank, offset, enable);
+       if (!ret)
+               ret = irq_set_irq_wake(bank->irq, enable);
 
-       return omap_set_gpio_wakeup(bank, offset, enable);
+       return ret;
 }
 
 static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -669,14 +672,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
                pm_runtime_get_sync(bank->dev);
 
        raw_spin_lock_irqsave(&bank->lock, flags);
-       /* Set trigger to none. You need to enable the desired trigger with
-        * request_irq() or set_irq_type(). Only do this if the IRQ line has
-        * not already been requested.
-        */
-       if (!LINE_USED(bank->irq_usage, offset)) {
-               omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
-               omap_enable_gpio_module(bank, offset);
-       }
+       omap_enable_gpio_module(bank, offset);
        bank->mod_usage |= BIT(offset);
        raw_spin_unlock_irqrestore(&bank->lock, flags);
 
@@ -690,8 +686,11 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
 
        raw_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);
        raw_spin_unlock_irqrestore(&bank->lock, flags);
 
        /*
@@ -711,29 +710,27 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
  * line's interrupt handler has been run, we may miss some nested
  * interrupts.
  */
-static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
 {
        void __iomem *isr_reg = NULL;
        u32 isr;
        unsigned int bit;
-       struct gpio_bank *bank;
-       int unmasked = 0;
-       struct irq_chip *irqchip = irq_desc_get_chip(desc);
-       struct gpio_chip *chip = irq_get_handler_data(irq);
+       struct gpio_bank *bank = gpiobank;
+       unsigned long wa_lock_flags;
+       unsigned long lock_flags;
 
-       chained_irq_enter(irqchip, desc);
-
-       bank = container_of(chip, struct gpio_bank, chip);
        isr_reg = bank->base + bank->regs->irqstatus;
-       pm_runtime_get_sync(bank->dev);
-
        if (WARN_ON(!isr_reg))
                goto exit;
 
+       pm_runtime_get_sync(bank->dev);
+
        while (1) {
                u32 isr_saved, level_mask = 0;
                u32 enabled;
 
+               raw_spin_lock_irqsave(&bank->lock, lock_flags);
+
                enabled = omap_get_gpio_irqbank_mask(bank);
                isr_saved = isr = readl_relaxed(isr_reg) & enabled;
 
@@ -747,12 +744,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
                omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask);
 
-               /* if there is only edge sensitive GPIO pin interrupts
-               configured, we could unmask GPIO bank interrupt immediately */
-               if (!level_mask && !unmasked) {
-                       unmasked = 1;
-                       chained_irq_exit(irqchip, desc);
-               }
+               raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
 
                if (!isr)
                        break;
@@ -761,6 +753,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                        bit = __ffs(isr);
                        isr &= ~(BIT(bit));
 
+                       raw_spin_lock_irqsave(&bank->lock, lock_flags);
                        /*
                         * Some chips can't respond to both rising and falling
                         * at the same time.  If this irq was requested with
@@ -771,18 +764,20 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                        if (bank->toggle_mask & (BIT(bit)))
                                omap_toggle_gpio_edge_triggering(bank, bit);
 
+                       raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
+
+                       raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags);
+
                        generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
                                                            bit));
+
+                       raw_spin_unlock_irqrestore(&bank->wa_lock,
+                                                  wa_lock_flags);
                }
        }
-       /* if bank has any level sensitive GPIO pin interrupt
-       configured, we must unmask the bank interrupt only after
-       handler(s) are executed in order to avoid spurious bank
-       interrupt */
 exit:
-       if (!unmasked)
-               chained_irq_exit(irqchip, desc);
        pm_runtime_put(bank->dev);
+       return IRQ_HANDLED;
 }
 
 static unsigned int omap_gpio_irq_startup(struct irq_data *d)
@@ -791,15 +786,22 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)
        unsigned long flags;
        unsigned offset = d->hwirq;
 
-       if (!BANK_USED(bank))
-               pm_runtime_get_sync(bank->dev);
-
        raw_spin_lock_irqsave(&bank->lock, flags);
-       omap_gpio_init_irq(bank, offset);
+
+       if (!LINE_USED(bank->mod_usage, offset))
+               omap_set_gpio_direction(bank, offset, 1);
+       else if (!omap_gpio_is_input(bank, offset))
+               goto err;
+       omap_enable_gpio_module(bank, offset);
+       bank->irq_usage |= BIT(offset);
+
        raw_spin_unlock_irqrestore(&bank->lock, flags);
        omap_gpio_unmask_irq(d);
 
        return 0;
+err:
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
+       return -EINVAL;
 }
 
 static void omap_gpio_irq_shutdown(struct irq_data *d)
@@ -810,9 +812,26 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
 
        raw_spin_lock_irqsave(&bank->lock, flags);
        bank->irq_usage &= ~(BIT(offset));
+       omap_set_gpio_irqenable(bank, offset, 0);
+       omap_clear_gpio_irqstatus(bank, offset);
+       omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
+       if (!LINE_USED(bank->mod_usage, offset))
+               omap_clear_gpio_debounce(bank, offset);
        omap_disable_gpio_module(bank, offset);
-       omap_reset_gpio(bank, offset);
        raw_spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static void omap_gpio_irq_bus_lock(struct irq_data *data)
+{
+       struct gpio_bank *bank = omap_irq_data_get_bank(data);
+
+       if (!BANK_USED(bank))
+               pm_runtime_get_sync(bank->dev);
+}
+
+static void gpio_irq_bus_sync_unlock(struct irq_data *data)
+{
+       struct gpio_bank *bank = omap_irq_data_get_bank(data);
 
        /*
         * If this is the last IRQ to be freed in the bank,
@@ -1048,10 +1067,6 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
         /* Initialize interface clk ungated, module enabled */
        if (bank->regs->ctrl)
                writel_relaxed(0, base + bank->regs->ctrl);
-
-       bank->dbck = clk_get(bank->dev, "dbclk");
-       if (IS_ERR(bank->dbck))
-               dev_err(bank->dev, "Could not get gpio dbck\n");
 }
 
 static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
@@ -1080,7 +1095,6 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
        } else {
                bank->chip.label = "gpio";
                bank->chip.base = gpio;
-               gpio += bank->width;
        }
        bank->chip.ngpio = bank->width;
 
@@ -1090,6 +1104,9 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
                return ret;
        }
 
+       if (!bank->is_mpuio)
+               gpio += bank->width;
+
 #ifdef CONFIG_ARCH_OMAP1
        /*
         * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
@@ -1105,14 +1122,12 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
        /* 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_base, handle_bad_irq,
                                   IRQ_TYPE_NONE);
 
        if (ret) {
@@ -1121,10 +1136,14 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
                return -ENODEV;
        }
 
-       gpiochip_set_chained_irqchip(&bank->chip, irqc,
-                                    bank->irq, omap_gpio_irq_handler);
+       gpiochip_set_chained_irqchip(&bank->chip, irqc, bank->irq, NULL);
 
-       return 0;
+       ret = devm_request_irq(bank->dev, bank->irq, omap_gpio_irq_handler,
+                              0, dev_name(bank->dev), bank);
+       if (ret)
+               gpiochip_remove(&bank->chip);
+
+       return ret;
 }
 
 static const struct of_device_id omap_gpio_match[];
@@ -1163,17 +1182,23 @@ static int omap_gpio_probe(struct platform_device *pdev)
        irqc->irq_unmask = omap_gpio_unmask_irq,
        irqc->irq_set_type = omap_gpio_irq_type,
        irqc->irq_set_wake = omap_gpio_wake_enable,
+       irqc->irq_bus_lock = omap_gpio_irq_bus_lock,
+       irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock,
        irqc->name = dev_name(&pdev->dev);
 
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (unlikely(!res)) {
-               dev_err(dev, "Invalid IRQ resource\n");
-               return -ENODEV;
+       bank->irq = platform_get_irq(pdev, 0);
+       if (bank->irq <= 0) {
+               if (!bank->irq)
+                       bank->irq = -ENXIO;
+               if (bank->irq != -EPROBE_DEFER)
+                       dev_err(dev,
+                               "can't get irq resource ret=%d\n", bank->irq);
+               return bank->irq;
        }
 
-       bank->irq = res->start;
        bank->dev = dev;
        bank->chip.dev = dev;
+       bank->chip.owner = THIS_MODULE;
        bank->dbck_flag = pdata->dbck_flag;
        bank->stride = pdata->bank_stride;
        bank->width = pdata->bank_width;
@@ -1200,15 +1225,26 @@ static int omap_gpio_probe(struct platform_device *pdev)
                bank->set_dataout = omap_set_gpio_dataout_mask;
 
        raw_spin_lock_init(&bank->lock);
+       raw_spin_lock_init(&bank->wa_lock);
 
        /* Static mapping, never released */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        bank->base = devm_ioremap_resource(dev, res);
        if (IS_ERR(bank->base)) {
-               irq_domain_remove(bank->chip.irqdomain);
                return PTR_ERR(bank->base);
        }
 
+       if (bank->dbck_flag) {
+               bank->dbck = devm_clk_get(bank->dev, "dbclk");
+               if (IS_ERR(bank->dbck)) {
+                       dev_err(bank->dev,
+                               "Could not get gpio dbck. Disable debounce\n");
+                       bank->dbck_flag = false;
+               } else {
+                       clk_prepare(bank->dbck);
+               }
+       }
+
        platform_set_drvdata(pdev, bank);
 
        pm_runtime_enable(bank->dev);
@@ -1221,8 +1257,11 @@ static int omap_gpio_probe(struct platform_device *pdev)
        omap_gpio_mod_init(bank);
 
        ret = omap_gpio_chip_init(bank, irqc);
-       if (ret)
+       if (ret) {
+               pm_runtime_put_sync(bank->dev);
+               pm_runtime_disable(bank->dev);
                return ret;
+       }
 
        omap_gpio_show_rev(bank);
 
@@ -1233,6 +1272,19 @@ 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);
+       if (bank->dbck_flag)
+               clk_unprepare(bank->dbck);
+
+       return 0;
+}
+
 #ifdef CONFIG_ARCH_OMAP2PLUS
 
 #if defined(CONFIG_PM)
@@ -1418,6 +1470,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;
@@ -1443,6 +1496,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)
@@ -1598,6 +1652,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,
@@ -1615,3 +1670,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");