diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-06 15:40:55 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-06 15:40:55 -0700 |
commit | 30c67e93c526639aaac90fa873800104b7c16d16 (patch) | |
tree | 6d8d0fd248d4e60bdc175dacbd196fc44f23ce11 /drivers/gpio/gpio-omap.c | |
parent | f87bb9ee62700fa11713c630ac5671f253233b94 (diff) | |
parent | 08ffb2229fafc2c3a696b325a74bf4198d6b91d7 (diff) |
Merge tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux
Pull GPIO changes from Grant Likely:
"The usual selection of bug fixes and driver updates for GPIO. Nothing
really stands out except the addition of the GRGPIO driver and some
enhacements to ACPI support"
I'm pulling this despite the earlier mess. Let's hope it compiles these
days.
* tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux: (46 commits)
gpio: grgpio: Add irq support
gpio: grgpio: Add device driver for GRGPIO cores
gpiolib-acpi: introduce acpi_get_gpio_by_index() helper
GPIO: gpio-generic: remove kfree() from bgpio_remove call
gpio / ACPI: Handle ACPI events in accordance with the spec
gpio: lpc32xx: Fix off-by-one valid range checking for bank
gpio: mcp23s08: convert driver to DT
gpio/omap: force restore if context loss is not detectable
gpio/omap: optimise interrupt service routine
gpio/omap: remove extra context restores in *_runtime_resume()
gpio/omap: free irq domain in probe() failure paths
gpio: gpio-generic: Add 16 and 32 bit big endian byte order support
gpio: samsung: Add terminating entry for exynos_pinctrl_ids
gpio: mvebu: add dbg_show function
MAX7301 GPIO: Do not force SPI speed when using OF Platform
gpio: gpio-tps65910.c: fix checkpatch error
gpio: gpio-timberdale.c: fix checkpatch error
gpio: gpio-tc3589x.c: fix checkpatch errors
gpio: gpio-stp-xway.c: fix checkpatch error
gpio: gpio-sch.c: fix checkpatch error
...
Diffstat (limited to 'drivers/gpio/gpio-omap.c')
-rw-r--r-- | drivers/gpio/gpio-omap.c | 116 |
1 files changed, 58 insertions, 58 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index a612ea1c53cb..2050891d9c65 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -52,7 +52,6 @@ struct gpio_bank { struct list_head node; void __iomem *base; u16 irq; - int irq_base; struct irq_domain *domain; u32 non_wakeup_gpios; u32 enabled_non_wakeup_gpios; @@ -88,7 +87,14 @@ struct gpio_bank { static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq) { - return gpio_irq - bank->irq_base + bank->chip.base; + return bank->chip.base + gpio_irq; +} + +static int omap_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip); + + return irq_find_mapping(bank->domain, offset); } static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) @@ -420,13 +426,16 @@ static int gpio_irq_type(struct irq_data *d, unsigned type) int retval; unsigned long flags; + if (WARN_ON(!bank->mod_usage)) + return -EINVAL; + #ifdef CONFIG_ARCH_OMAP1 if (d->irq > IH_MPUIO_BASE) gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE); #endif if (!gpio) - gpio = irq_to_gpio(bank, d->irq); + gpio = irq_to_gpio(bank, d->hwirq); if (type & ~IRQ_TYPE_SENSE_MASK) return -EINVAL; @@ -579,7 +588,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio) static int gpio_wake_enable(struct irq_data *d, unsigned int enable) { struct gpio_bank *bank = irq_data_get_irq_chip_data(d); - unsigned int gpio = irq_to_gpio(bank, d->irq); + unsigned int gpio = irq_to_gpio(bank, d->hwirq); return _set_gpio_wakeup(bank, gpio, enable); } @@ -679,7 +688,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) { void __iomem *isr_reg = NULL; u32 isr; - unsigned int gpio_irq, gpio_index; + unsigned int bit; struct gpio_bank *bank; int unmasked = 0; struct irq_chip *chip = irq_desc_get_chip(desc); @@ -693,7 +702,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) if (WARN_ON(!isr_reg)) goto exit; - while(1) { + while (1) { u32 isr_saved, level_mask = 0; u32 enabled; @@ -720,14 +729,9 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) if (!isr) break; - gpio_irq = bank->irq_base; - for (; isr != 0; isr >>= 1, gpio_irq++) { - int gpio = irq_to_gpio(bank, gpio_irq); - - if (!(isr & 1)) - continue; - - gpio_index = GPIO_INDEX(bank, gpio); + while (isr) { + bit = __ffs(isr); + isr &= ~(1 << bit); /* * Some chips can't respond to both rising and falling @@ -736,10 +740,10 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) * to respond to the IRQ for the opposite direction. * This will be indicated in the bank toggle_mask. */ - if (bank->toggle_mask & (1 << gpio_index)) - _toggle_gpio_edge_triggering(bank, gpio_index); + if (bank->toggle_mask & (1 << bit)) + _toggle_gpio_edge_triggering(bank, bit); - generic_handle_irq(gpio_irq); + generic_handle_irq(irq_find_mapping(bank->domain, bit)); } } /* if bank has any level sensitive GPIO pin interrupt @@ -755,7 +759,7 @@ exit: static void gpio_irq_shutdown(struct irq_data *d) { struct gpio_bank *bank = irq_data_get_irq_chip_data(d); - unsigned int gpio = irq_to_gpio(bank, d->irq); + unsigned int gpio = irq_to_gpio(bank, d->hwirq); unsigned long flags; spin_lock_irqsave(&bank->lock, flags); @@ -766,7 +770,7 @@ static void gpio_irq_shutdown(struct irq_data *d) static void gpio_ack_irq(struct irq_data *d) { struct gpio_bank *bank = irq_data_get_irq_chip_data(d); - unsigned int gpio = irq_to_gpio(bank, d->irq); + unsigned int gpio = irq_to_gpio(bank, d->hwirq); _clear_gpio_irqstatus(bank, gpio); } @@ -774,7 +778,7 @@ static void gpio_ack_irq(struct irq_data *d) static void gpio_mask_irq(struct irq_data *d) { struct gpio_bank *bank = irq_data_get_irq_chip_data(d); - unsigned int gpio = irq_to_gpio(bank, d->irq); + unsigned int gpio = irq_to_gpio(bank, d->hwirq); unsigned long flags; spin_lock_irqsave(&bank->lock, flags); @@ -786,7 +790,7 @@ static void gpio_mask_irq(struct irq_data *d) static void gpio_unmask_irq(struct irq_data *d) { struct gpio_bank *bank = irq_data_get_irq_chip_data(d); - unsigned int gpio = irq_to_gpio(bank, d->irq); + unsigned int gpio = irq_to_gpio(bank, d->hwirq); unsigned int irq_mask = GPIO_BIT(bank, gpio); u32 trigger = irqd_get_trigger_type(d); unsigned long flags; @@ -952,14 +956,6 @@ static void gpio_set(struct gpio_chip *chip, unsigned offset, int value) spin_unlock_irqrestore(&bank->lock, flags); } -static int gpio_2irq(struct gpio_chip *chip, unsigned offset) -{ - struct gpio_bank *bank; - - bank = container_of(chip, struct gpio_bank, chip); - return bank->irq_base + offset; -} - /*---------------------------------------------------------------------*/ static void __init omap_gpio_show_rev(struct gpio_bank *bank) @@ -1056,7 +1052,7 @@ static void omap_gpio_chip_init(struct gpio_bank *bank) bank->chip.direction_output = gpio_output; bank->chip.set_debounce = gpio_debounce; bank->chip.set = gpio_set; - bank->chip.to_irq = gpio_2irq; + bank->chip.to_irq = omap_gpio_to_irq; if (bank->is_mpuio) { bank->chip.label = "mpuio"; if (bank->regs->wkup_en) @@ -1071,15 +1067,16 @@ static void omap_gpio_chip_init(struct gpio_bank *bank) gpiochip_add(&bank->chip); - for (j = bank->irq_base; j < bank->irq_base + bank->width; j++) { - irq_set_lockdep_class(j, &gpio_lock_class); - irq_set_chip_data(j, bank); + for (j = 0; j < bank->width; j++) { + int irq = irq_create_mapping(bank->domain, j); + irq_set_lockdep_class(irq, &gpio_lock_class); + irq_set_chip_data(irq, bank); if (bank->is_mpuio) { - omap_mpuio_alloc_gc(bank, j, bank->width); + omap_mpuio_alloc_gc(bank, irq, bank->width); } else { - irq_set_chip(j, &gpio_irq_chip); - irq_set_handler(j, handle_simple_irq); - set_irq_flags(j, IRQF_VALID); + irq_set_chip_and_handler(irq, &gpio_irq_chip, + handle_simple_irq); + set_irq_flags(irq, IRQF_VALID); } } irq_set_chained_handler(bank->irq, gpio_irq_handler); @@ -1096,7 +1093,6 @@ static int omap_gpio_probe(struct platform_device *pdev) const struct omap_gpio_platform_data *pdata; struct resource *res; struct gpio_bank *bank; - int ret = 0; match = of_match_device(of_match_ptr(omap_gpio_match), dev); @@ -1123,20 +1119,22 @@ static int omap_gpio_probe(struct platform_device *pdev) bank->width = pdata->bank_width; bank->is_mpuio = pdata->is_mpuio; bank->non_wakeup_gpios = pdata->non_wakeup_gpios; - bank->loses_context = pdata->loses_context; bank->regs = pdata->regs; #ifdef CONFIG_OF_GPIO bank->chip.of_node = of_node_get(node); #endif - - bank->irq_base = irq_alloc_descs(-1, 0, bank->width, 0); - if (bank->irq_base < 0) { - dev_err(dev, "Couldn't allocate IRQ numbers\n"); - return -ENODEV; + if (node) { + if (!of_property_read_bool(node, "ti,gpio-always-on")) + bank->loses_context = true; + } else { + bank->loses_context = pdata->loses_context; } - bank->domain = irq_domain_add_legacy(node, bank->width, bank->irq_base, - 0, &irq_domain_simple_ops, NULL); + + bank->domain = irq_domain_add_linear(node, bank->width, + &irq_domain_simple_ops, NULL); + if (!bank->domain) + return -ENODEV; if (bank->regs->set_dataout && bank->regs->clr_dataout) bank->set_dataout = _set_gpio_dataout_reg; @@ -1149,18 +1147,21 @@ static int omap_gpio_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (unlikely(!res)) { dev_err(dev, "Invalid mem resource\n"); + irq_domain_remove(bank->domain); return -ENODEV; } if (!devm_request_mem_region(dev, res->start, resource_size(res), pdev->name)) { dev_err(dev, "Region already claimed\n"); + irq_domain_remove(bank->domain); return -EBUSY; } bank->base = devm_ioremap(dev, res->start, resource_size(res)); if (!bank->base) { dev_err(dev, "Could not ioremap\n"); + irq_domain_remove(bank->domain); return -ENOMEM; } @@ -1184,7 +1185,7 @@ static int omap_gpio_probe(struct platform_device *pdev) list_add_tail(&bank->node, &omap_gpio_list); - return ret; + return 0; } #ifdef CONFIG_ARCH_OMAP2PLUS @@ -1262,9 +1263,9 @@ static int omap_gpio_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct gpio_bank *bank = platform_get_drvdata(pdev); - int context_lost_cnt_after; u32 l = 0, gen, gen0, gen1; unsigned long flags; + int c; spin_lock_irqsave(&bank->lock, flags); _gpio_dbck_enable(bank); @@ -1280,14 +1281,17 @@ static int omap_gpio_runtime_resume(struct device *dev) __raw_writel(bank->context.risingdetect, bank->base + bank->regs->risingdetect); - if (bank->get_context_loss_count) { - context_lost_cnt_after = - bank->get_context_loss_count(bank->dev); - if (context_lost_cnt_after != bank->context_loss_count) { + if (bank->loses_context) { + if (!bank->get_context_loss_count) { omap_gpio_restore_context(bank); } else { - spin_unlock_irqrestore(&bank->lock, flags); - return 0; + c = bank->get_context_loss_count(bank->dev); + if (c != bank->context_loss_count) { + omap_gpio_restore_context(bank); + } else { + spin_unlock_irqrestore(&bank->lock, flags); + return 0; + } } } @@ -1296,10 +1300,6 @@ static int omap_gpio_runtime_resume(struct device *dev) return 0; } - __raw_writel(bank->context.fallingdetect, - bank->base + bank->regs->fallingdetect); - __raw_writel(bank->context.risingdetect, - bank->base + bank->regs->risingdetect); l = __raw_readl(bank->base + bank->regs->datain); /* |