gpio: omap: rework omap_gpio_request to touch only gpio specific registers
[firefly-linux-kernel-4.4.55.git] / drivers / gpio / gpio-omap.c
index 6efee35f0ad44da69399161f6d35887a6de6a7e3..606b401d201739fca6454dff0f3ec0686f2636ed 100644 (file)
@@ -488,9 +488,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;
 
@@ -498,12 +495,18 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
                (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
                return -EINVAL;
 
+       if (!BANK_USED(bank))
+               pm_runtime_get_sync(bank->dev);
+
        spin_lock_irqsave(&bank->lock, flags);
        retval = omap_set_gpio_triggering(bank, offset, type);
+       if (retval)
+               goto error;
        omap_gpio_init_irq(bank, offset);
        if (!omap_gpio_is_input(bank, offset)) {
                spin_unlock_irqrestore(&bank->lock, flags);
-               return -EINVAL;
+               retval = -EINVAL;
+               goto error;
        }
        spin_unlock_irqrestore(&bank->lock, flags);
 
@@ -512,6 +515,11 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
        else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
                __irq_set_handler_locked(d->irq, handle_edge_irq);
 
+       return 0;
+
+error:
+       if (!BANK_USED(bank))
+               pm_runtime_put(bank->dev);
        return retval;
 }
 
@@ -638,15 +646,6 @@ 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)
 {
@@ -669,14 +668,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
                pm_runtime_get_sync(bank->dev);
 
        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);
        spin_unlock_irqrestore(&bank->lock, flags);
 
@@ -690,8 +682,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);
 
        /*
@@ -810,8 +805,12 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
 
        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);
        spin_unlock_irqrestore(&bank->lock, flags);
 
        /*