diff options
Diffstat (limited to 'drivers/gpio/gpio-omap.c')
| -rw-r--r-- | drivers/gpio/gpio-omap.c | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 30646cfe0efa..f476ae2eb0b3 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c | |||
| @@ -88,6 +88,8 @@ struct gpio_bank { | |||
| 88 | #define BANK_USED(bank) (bank->mod_usage || bank->irq_usage) | 88 | #define BANK_USED(bank) (bank->mod_usage || bank->irq_usage) |
| 89 | #define LINE_USED(line, offset) (line & (BIT(offset))) | 89 | #define LINE_USED(line, offset) (line & (BIT(offset))) |
| 90 | 90 | ||
| 91 | static void omap_gpio_unmask_irq(struct irq_data *d); | ||
| 92 | |||
| 91 | static int omap_irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq) | 93 | static int omap_irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq) |
| 92 | { | 94 | { |
| 93 | return bank->chip.base + gpio_irq; | 95 | return bank->chip.base + gpio_irq; |
| @@ -477,6 +479,16 @@ static int omap_gpio_is_input(struct gpio_bank *bank, int mask) | |||
| 477 | return readl_relaxed(reg) & mask; | 479 | return readl_relaxed(reg) & mask; |
| 478 | } | 480 | } |
| 479 | 481 | ||
| 482 | static void omap_gpio_init_irq(struct gpio_bank *bank, unsigned gpio, | ||
| 483 | unsigned offset) | ||
| 484 | { | ||
| 485 | if (!LINE_USED(bank->mod_usage, offset)) { | ||
| 486 | omap_enable_gpio_module(bank, offset); | ||
| 487 | omap_set_gpio_direction(bank, offset, 1); | ||
| 488 | } | ||
| 489 | bank->irq_usage |= BIT(GPIO_INDEX(bank, gpio)); | ||
| 490 | } | ||
| 491 | |||
| 480 | static int omap_gpio_irq_type(struct irq_data *d, unsigned type) | 492 | static int omap_gpio_irq_type(struct irq_data *d, unsigned type) |
| 481 | { | 493 | { |
| 482 | struct gpio_bank *bank = omap_irq_data_get_bank(d); | 494 | struct gpio_bank *bank = omap_irq_data_get_bank(d); |
| @@ -506,15 +518,11 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) | |||
| 506 | spin_lock_irqsave(&bank->lock, flags); | 518 | spin_lock_irqsave(&bank->lock, flags); |
| 507 | offset = GPIO_INDEX(bank, gpio); | 519 | offset = GPIO_INDEX(bank, gpio); |
| 508 | retval = omap_set_gpio_triggering(bank, offset, type); | 520 | retval = omap_set_gpio_triggering(bank, offset, type); |
| 509 | if (!LINE_USED(bank->mod_usage, offset)) { | 521 | omap_gpio_init_irq(bank, gpio, offset); |
| 510 | omap_enable_gpio_module(bank, offset); | 522 | if (!omap_gpio_is_input(bank, BIT(offset))) { |
| 511 | omap_set_gpio_direction(bank, offset, 1); | ||
| 512 | } else if (!omap_gpio_is_input(bank, BIT(offset))) { | ||
| 513 | spin_unlock_irqrestore(&bank->lock, flags); | 523 | spin_unlock_irqrestore(&bank->lock, flags); |
| 514 | return -EINVAL; | 524 | return -EINVAL; |
| 515 | } | 525 | } |
| 516 | |||
| 517 | bank->irq_usage |= BIT(GPIO_INDEX(bank, gpio)); | ||
| 518 | spin_unlock_irqrestore(&bank->lock, flags); | 526 | spin_unlock_irqrestore(&bank->lock, flags); |
| 519 | 527 | ||
| 520 | if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) | 528 | if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) |
| @@ -792,6 +800,24 @@ exit: | |||
| 792 | pm_runtime_put(bank->dev); | 800 | pm_runtime_put(bank->dev); |
| 793 | } | 801 | } |
| 794 | 802 | ||
| 803 | static unsigned int omap_gpio_irq_startup(struct irq_data *d) | ||
| 804 | { | ||
| 805 | struct gpio_bank *bank = omap_irq_data_get_bank(d); | ||
| 806 | unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq); | ||
| 807 | unsigned long flags; | ||
| 808 | unsigned offset = GPIO_INDEX(bank, gpio); | ||
| 809 | |||
| 810 | if (!BANK_USED(bank)) | ||
| 811 | pm_runtime_get_sync(bank->dev); | ||
| 812 | |||
| 813 | spin_lock_irqsave(&bank->lock, flags); | ||
| 814 | omap_gpio_init_irq(bank, gpio, offset); | ||
| 815 | spin_unlock_irqrestore(&bank->lock, flags); | ||
| 816 | omap_gpio_unmask_irq(d); | ||
| 817 | |||
| 818 | return 0; | ||
| 819 | } | ||
| 820 | |||
| 795 | static void omap_gpio_irq_shutdown(struct irq_data *d) | 821 | static void omap_gpio_irq_shutdown(struct irq_data *d) |
| 796 | { | 822 | { |
| 797 | struct gpio_bank *bank = omap_irq_data_get_bank(d); | 823 | struct gpio_bank *bank = omap_irq_data_get_bank(d); |
| @@ -1181,6 +1207,7 @@ static int omap_gpio_probe(struct platform_device *pdev) | |||
| 1181 | if (!irqc) | 1207 | if (!irqc) |
| 1182 | return -ENOMEM; | 1208 | return -ENOMEM; |
| 1183 | 1209 | ||
| 1210 | irqc->irq_startup = omap_gpio_irq_startup, | ||
| 1184 | irqc->irq_shutdown = omap_gpio_irq_shutdown, | 1211 | irqc->irq_shutdown = omap_gpio_irq_shutdown, |
| 1185 | irqc->irq_ack = omap_gpio_ack_irq, | 1212 | irqc->irq_ack = omap_gpio_ack_irq, |
| 1186 | irqc->irq_mask = omap_gpio_mask_irq, | 1213 | irqc->irq_mask = omap_gpio_mask_irq, |
