diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-04 10:07:45 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-04 10:07:45 -0700 |
commit | 8d2faea672606827c2018143ec7d88c760f2d6de (patch) | |
tree | ca92a524910afbd68b87a800fba64ad93abf5d67 /drivers | |
parent | 02cf1da2548d318ad4db9eb4cf8656e24b11aefc (diff) | |
parent | 01e2dae991771adb1257eb5cd3cecfda1aa09ba9 (diff) | |
download | linux-8d2faea672606827c2018143ec7d88c760f2d6de.tar.bz2 |
Merge tag 'gpio-v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij:
"This is the bulk of GPIO changes for the v4.3 kernel cycle.
There is quite a lot going on in the GPIO subsystem this merge window,
so the main matter is decribed below.
The hits in other subsystems when making the GPIO flags optional are
all ACKed by their respective subsystem maintainers.
Core changes:
- Root out the wrapper devm_gpiod_get() and gpiod_get() etc versions
of the descriptor calls that did not use the flags argument on the
end. This was around for too long and eventually Uwe Kleine-König
took the time to clean it out and the last users are removed along
with the macros in this tag. In several cases the use of flags
simplifies the code. For this reason we have (ACKed) patches
hitting in DRM, IIO, media, NFC, USB+PHY up until we hammer in the
nail with removing the macros.
- Add a fat document describing how much ready-made GPIO stuff we
have i the kernel to discourage people from reinventing a square
wheel in userspace, as so often happens.
- Create a separate lockdep class for each instance of a GPIO IRQ
chip instead of using one class for all chips, as the current code
will not work with systems with several GPIO chips doing lockdep
debugging.
- Protect against driver unloading also when a GPIO line is only used
as IRQ for the GPIOLIB_IRQCHIP helpers.
- If the GPIO chip has no designated owner, assign the parent device
driver owner as owner.
- Consolidation of chained IRQ handler install/remove replacing all
call sites where irq_set_handler_data() and
irq_set_chained_handler() were done in succession with a combined
call to irq_set_chained_handler_and_data().
This series was created by Thomas Gleixner after the problem was
observed by Russell King.
- Tglx also made another series of patches switching
__irq_set_handler_locked() for irq_set_handler_locked() which is
way cleaner.
- Tglx and Jiang Liu wrote a good bunch of patches to make use of
irq_desc_get_xxx() accessors and avoid looking up irq_descs from
IRQ numbers. The goal is to get rid of the irq number from the
handlers in the IRQ flow which is nice.
- Rob Herring killed off the set_irq_flags() for all GPIO drivers.
This was an ARM specific function that is replaced with the generic
irq_modify_status() where special flags are actually needed.
- When an OF node has a pin range for its GPIOs, return -EPROBE_DEFER
if the pin controller isn't available. Pretty logical, yet needed
to be fixed.
- If a driver using GPIOLIB_IRQCHIP has its own irq_*_resources call
back, then call these instead of the defaults provided by the
GPIOLIB.
- Fix an undocumented ABI hole: named GPIOs were not properly
documented.
Driver improvements:
- Add get_direction() support to the generic GPIO driver, it's
strange that we didn't have that before.
- Make it possible to have input-only GPIO chips using the generic
GPIO driver.
- Clean out platform data support from the Emma Mobile (EM) driver
- Finegrained runtime PM support for the RCAR driver.
- Support r8a7795 (R-car H3) in the RCAR driver.
- Support interrupts on GPIOs 16 thru 31 in the DaVinci driver.
- Some consolidation and new support in the MPC8xxx driver, we now
support MPC5125.
- Preempt-RT-friendly patches: the OMAP, MPC8xxx, drivers uses raw
spinlocks making it work better with the realime patches.
- Interrupt support for the EXTRAXFS GPIO driver.
- Make the ETRAXFS GPIO driver support also ARTPEC-3.
- Interrupt and wakeup support for the BRCMSTB driver, also for
wakeup from S5 cold boot.
- Mask MXC IRQs during suspend.
- Improve OMAP2 GPIO set_debounce() to work according to spec.
- The VF610 driver handles IRQs properly.
New drivers:
- ZTE ZX GPIO driver"
* tag 'gpio-v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (87 commits)
Revert "gpio: extraxfs: fix returnvar.cocci warnings"
gpio: tc3589x: use static container helper
gpio: xlp: fix error return code
gpio: vf610: handle level IRQ's properly
gpio: max732x: Fix error handling in probe()
gpio: omap: fix clk_prepare/unprepare usage
gpio: omap: protect regs access in omap_gpio_irq_handler
gpio: omap: fix omap2_set_gpio_debounce
gpio: omap: switch to use platform_get_irq
gpio: omap: remove wrong irq_domain_remove usage in probe
gpiolib: add description for gpio irqchip fields in struct gpio_chip
gpio: extraxfs: fix returnvar.cocci warnings
gpiolib: irqchip: use different lockdep class for each gpio irqchip
gpio/grgpio: fix deadlock in grgpio_irq_unmap()
Documentation: gpio: consumer: describe active low property
gpio: mxc: fix section mismatch warning
gpio/mxc: mask gpio interrupts in suspend
gpio: omap: Fix missing raw locks conversion
gpio: brcmstb: support wakeup from S5 cold boot
gpio: brcmstb: Add interrupt and wakeup source support
...
Diffstat (limited to 'drivers')
46 files changed, 1390 insertions, 419 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8f1fe739c985..b4fc9e4d24c6 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -113,7 +113,6 @@ config GPIO_74XX_MMIO config GPIO_ALTERA tristate "Altera GPIO" depends on OF_GPIO - select GPIO_GENERIC select GPIOLIB_IRQCHIP help Say Y or M here to build support for the Altera PIO device. @@ -131,6 +130,7 @@ config GPIO_BRCMSTB default y if ARCH_BRCMSTB depends on OF_GPIO && (ARCH_BRCMSTB || COMPILE_TEST) select GPIO_GENERIC + select GPIOLIB_IRQCHIP help Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs. @@ -172,6 +172,7 @@ config GPIO_ETRAXFS depends on CRIS || COMPILE_TEST depends on OF select GPIO_GENERIC + select GPIOLIB_IRQCHIP help Say yes here to support the GPIO controller on Axis ETRAX FS SoCs. @@ -308,7 +309,6 @@ config GPIO_MVEBU def_bool y depends on PLAT_ORION depends on OF - select GPIO_GENERIC select GENERIC_IRQ_CHIP config GPIO_MXC @@ -1005,6 +1005,12 @@ config GPIO_MC33880 SPI driver for Freescale MC33880 high-side/low-side switch. This provides GPIO interface supporting inputs and outputs. +config GPIO_ZX + bool "ZTE ZX GPIO support" + select GPIOLIB_IRQCHIP + help + Say yes here to support the GPIO device on ZTE ZX SoCs. + endmenu menu "USB GPIO expanders" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 2b64f6177e33..f79a7c482a99 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -117,3 +117,4 @@ obj-$(CONFIG_GPIO_XLP) += gpio-xlp.o obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o +obj-$(CONFIG_GPIO_ZX) += gpio-zx.o diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c index 07ba82317ece..903fcf4d04a0 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c @@ -59,13 +59,13 @@ static int devm_gpiod_match_array(struct device *dev, void *res, void *data) * automatically disposed on driver detach. See gpiod_get() for detailed * information about behavior and return values. */ -struct gpio_desc *__must_check __devm_gpiod_get(struct device *dev, +struct gpio_desc *__must_check devm_gpiod_get(struct device *dev, const char *con_id, enum gpiod_flags flags) { return devm_gpiod_get_index(dev, con_id, 0, flags); } -EXPORT_SYMBOL(__devm_gpiod_get); +EXPORT_SYMBOL(devm_gpiod_get); /** * devm_gpiod_get_optional - Resource-managed gpiod_get_optional() @@ -77,13 +77,13 @@ EXPORT_SYMBOL(__devm_gpiod_get); * are automatically disposed on driver detach. See gpiod_get_optional() for * detailed information about behavior and return values. */ -struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev, +struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev, const char *con_id, enum gpiod_flags flags) { return devm_gpiod_get_index_optional(dev, con_id, 0, flags); } -EXPORT_SYMBOL(__devm_gpiod_get_optional); +EXPORT_SYMBOL(devm_gpiod_get_optional); /** * devm_gpiod_get_index - Resource-managed gpiod_get_index() @@ -96,7 +96,7 @@ EXPORT_SYMBOL(__devm_gpiod_get_optional); * automatically disposed on driver detach. See gpiod_get_index() for detailed * information about behavior and return values. */ -struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev, +struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, const char *con_id, unsigned int idx, enum gpiod_flags flags) @@ -120,7 +120,7 @@ struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev, return desc; } -EXPORT_SYMBOL(__devm_gpiod_get_index); +EXPORT_SYMBOL(devm_gpiod_get_index); /** * devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node @@ -182,10 +182,10 @@ EXPORT_SYMBOL(devm_get_gpiod_from_child); * gpiod_get_index_optional() for detailed information about behavior and * return values. */ -struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *dev, +struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev, const char *con_id, unsigned int index, - enum gpiod_flags flags) + enum gpiod_flags flags) { struct gpio_desc *desc; @@ -197,7 +197,7 @@ struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *de return desc; } -EXPORT_SYMBOL(__devm_gpiod_get_index_optional); +EXPORT_SYMBOL(devm_gpiod_get_index_optional); /** * devm_gpiod_get_array - Resource-managed gpiod_get_array() diff --git a/drivers/gpio/gpio-74xx-mmio.c b/drivers/gpio/gpio-74xx-mmio.c index 0763655cca6c..6ed7c0fb3378 100644 --- a/drivers/gpio/gpio-74xx-mmio.c +++ b/drivers/gpio/gpio-74xx-mmio.c @@ -129,7 +129,7 @@ static int mmio_74xx_gpio_probe(struct platform_device *pdev) if (IS_ERR(dat)) return PTR_ERR(dat); - priv->flags = (unsigned)of_id->data; + priv->flags = (uintptr_t) of_id->data; err = bgpio_init(&priv->bgc, &pdev->dev, DIV_ROUND_UP(MMIO_74XX_BIT_CNT(priv->flags), 8), diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c index d3fe6a6776da..984186ee58a0 100644 --- a/drivers/gpio/gpio-adp5588.c +++ b/drivers/gpio/gpio-adp5588.c @@ -305,15 +305,7 @@ static int adp5588_irq_setup(struct adp5588_gpio *dev) irq_set_chip_and_handler(irq, &adp5588_irq_chip, handle_level_irq); irq_set_nested_thread(irq, 1); -#ifdef CONFIG_ARM - /* - * ARM needs us to explicitly flag the IRQ as VALID, - * once we do so, it will also set the noprobe. - */ - set_irq_flags(irq, IRQF_VALID); -#else - irq_set_noprobe(irq); -#endif + irq_modify_status(irq, IRQ_NOREQUEST, IRQ_NOPROBE); } ret = request_threaded_irq(client->irq, diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c index 0f3d336d6303..9b7e0b3db387 100644 --- a/drivers/gpio/gpio-altera.c +++ b/drivers/gpio/gpio-altera.c @@ -338,9 +338,9 @@ static int altera_gpio_remove(struct platform_device *pdev) { struct altera_gpio_chip *altera_gc = platform_get_drvdata(pdev); - gpiochip_remove(&altera_gc->mmchip.gc); + of_mm_gpiochip_remove(&altera_gc->mmchip); - return -EIO; + return 0; } static const struct of_device_id altera_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index 40343fa92c7b..31b90ac15204 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -438,7 +438,7 @@ static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) void __iomem *reg_base; int bit, bank_id; unsigned long sta; - struct bcm_kona_gpio_bank *bank = irq_get_handler_data(irq); + struct bcm_kona_gpio_bank *bank = irq_desc_get_handler_data(desc); struct irq_chip *chip = irq_desc_get_chip(desc); chained_irq_enter(chip, desc); @@ -525,11 +525,7 @@ static int bcm_kona_gpio_irq_map(struct irq_domain *d, unsigned int irq, return ret; irq_set_lockdep_class(irq, &gpio_lock_class); irq_set_chip_and_handler(irq, &bcm_gpio_irq_chip, handle_simple_irq); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else irq_set_noprobe(irq); -#endif return 0; } @@ -644,17 +640,6 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev) dev_err(dev, "Couldn't add GPIO chip -- %d\n", ret); goto err_irq_domain; } - for (i = 0; i < chip->ngpio; i++) { - int irq = bcm_kona_gpio_to_irq(chip, i); - irq_set_lockdep_class(irq, &gpio_lock_class); - irq_set_chip_and_handler(irq, &bcm_gpio_irq_chip, - handle_simple_irq); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else - irq_set_noprobe(irq); -#endif - } for (i = 0; i < kona_gpio->num_bank; i++) { bank = &kona_gpio->banks[i]; irq_set_chained_handler_and_data(bank->irq, diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index 4630a8133ea6..9ea86d2ac054 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -17,6 +17,10 @@ #include <linux/of_irq.h> #include <linux/module.h> #include <linux/basic_mmio_gpio.h> +#include <linux/irqdomain.h> +#include <linux/irqchip/chained_irq.h> +#include <linux/interrupt.h> +#include <linux/reboot.h> #define GIO_BANK_SIZE 0x20 #define GIO_ODEN(bank) (((bank) * GIO_BANK_SIZE) + 0x00) @@ -34,14 +38,18 @@ struct brcmstb_gpio_bank { struct bgpio_chip bgc; struct brcmstb_gpio_priv *parent_priv; u32 width; + struct irq_chip irq_chip; }; struct brcmstb_gpio_priv { struct list_head bank_list; void __iomem *reg_base; - int num_banks; struct platform_device *pdev; + int parent_irq; int gpio_base; + bool can_wake; + int parent_wake_irq; + struct notifier_block reboot_notifier; }; #define MAX_GPIO_PER_BANK 32 @@ -63,6 +71,203 @@ brcmstb_gpio_gc_to_priv(struct gpio_chip *gc) return bank->parent_priv; } +static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank, + unsigned int offset, bool enable) +{ + struct bgpio_chip *bgc = &bank->bgc; + struct brcmstb_gpio_priv *priv = bank->parent_priv; + u32 mask = bgc->pin2mask(bgc, offset); + u32 imask; + unsigned long flags; + + spin_lock_irqsave(&bgc->lock, flags); + imask = bgc->read_reg(priv->reg_base + GIO_MASK(bank->id)); + if (enable) + imask |= mask; + else + imask &= ~mask; + bgc->write_reg(priv->reg_base + GIO_MASK(bank->id), imask); + spin_unlock_irqrestore(&bgc->lock, flags); +} + +/* -------------------- IRQ chip functions -------------------- */ + +static void brcmstb_gpio_irq_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc); + + brcmstb_gpio_set_imask(bank, d->hwirq, false); +} + +static void brcmstb_gpio_irq_unmask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc); + + brcmstb_gpio_set_imask(bank, d->hwirq, true); +} + +static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc); + struct brcmstb_gpio_priv *priv = bank->parent_priv; + u32 mask = BIT(d->hwirq); + u32 edge_insensitive, iedge_insensitive; + u32 edge_config, iedge_config; + u32 level, ilevel; + unsigned long flags; + + switch (type) { + case IRQ_TYPE_LEVEL_LOW: + level = 0; + edge_config = 0; + edge_insensitive = 0; + break; + case IRQ_TYPE_LEVEL_HIGH: + level = mask; + edge_config = 0; + edge_insensitive = 0; + break; + case IRQ_TYPE_EDGE_FALLING: + level = 0; + edge_config = 0; + edge_insensitive = 0; + break; + case IRQ_TYPE_EDGE_RISING: + level = 0; + edge_config = mask; + edge_insensitive = 0; + break; + case IRQ_TYPE_EDGE_BOTH: + level = 0; + edge_config = 0; /* don't care, but want known value */ + edge_insensitive = mask; + break; + default: + return -EINVAL; + } + + spin_lock_irqsave(&bank->bgc.lock, flags); + + iedge_config = bank->bgc.read_reg(priv->reg_base + + GIO_EC(bank->id)) & ~mask; + iedge_insensitive = bank->bgc.read_reg(priv->reg_base + + GIO_EI(bank->id)) & ~mask; + ilevel = bank->bgc.read_reg(priv->reg_base + + GIO_LEVEL(bank->id)) & ~mask; + + bank->bgc.write_reg(priv->reg_base + GIO_EC(bank->id), + iedge_config | edge_config); + bank->bgc.write_reg(priv->reg_base + GIO_EI(bank->id), + iedge_insensitive | edge_insensitive); + bank->bgc.write_reg(priv->reg_base + GIO_LEVEL(bank->id), + ilevel | level); + + spin_unlock_irqrestore(&bank->bgc.lock, flags); + return 0; +} + +static int brcmstb_gpio_priv_set_wake(struct brcmstb_gpio_priv *priv, + unsigned int enable) +{ + int ret = 0; + + /* + * Only enable wake IRQ once for however many hwirqs can wake + * since they all use the same wake IRQ. Mask will be set + * up appropriately thanks to IRQCHIP_MASK_ON_SUSPEND flag. + */ + if (enable) + ret = enable_irq_wake(priv->parent_wake_irq); + else + ret = disable_irq_wake(priv->parent_wake_irq); + if (ret) + dev_err(&priv->pdev->dev, "failed to %s wake-up interrupt\n", + enable ? "enable" : "disable"); + return ret; +} + +static int brcmstb_gpio_irq_set_wake(struct irq_data *d, unsigned int enable) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc); + + return brcmstb_gpio_priv_set_wake(priv, enable); +} + +static irqreturn_t brcmstb_gpio_wake_irq_handler(int irq, void *data) +{ + struct brcmstb_gpio_priv *priv = data; + + if (!priv || irq != priv->parent_wake_irq) + return IRQ_NONE; + pm_wakeup_event(&priv->pdev->dev, 0); + return IRQ_HANDLED; +} + +static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank) +{ + struct brcmstb_gpio_priv *priv = bank->parent_priv; + struct irq_domain *irq_domain = bank->bgc.gc.irqdomain; + void __iomem *reg_base = priv->reg_base; + unsigned long status; + unsigned long flags; + + spin_lock_irqsave(&bank->bgc.lock, flags); + while ((status = bank->bgc.read_reg(reg_base + GIO_STAT(bank->id)) & + bank->bgc.read_reg(reg_base + GIO_MASK(bank->id)))) { + int bit; + + for_each_set_bit(bit, &status, 32) { + u32 stat = bank->bgc.read_reg(reg_base + + GIO_STAT(bank->id)); + if (bit >= bank->width) + dev_warn(&priv->pdev->dev, + "IRQ for invalid GPIO (bank=%d, offset=%d)\n", + bank->id, bit); + bank->bgc.write_reg(reg_base + GIO_STAT(bank->id), + stat | BIT(bit)); + generic_handle_irq(irq_find_mapping(irq_domain, bit)); + } + } + spin_unlock_irqrestore(&bank->bgc.lock, flags); +} + +/* Each UPG GIO block has one IRQ for all banks */ +static void brcmstb_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc); + struct irq_chip *chip = irq_desc_get_chip(desc); + struct list_head *pos; + + /* Interrupts weren't properly cleared during probe */ + BUG_ON(!priv || !chip); + + chained_irq_enter(chip, desc); + list_for_each(pos, &priv->bank_list) { + struct brcmstb_gpio_bank *bank = + list_entry(pos, struct brcmstb_gpio_bank, node); + brcmstb_gpio_irq_bank_handler(bank); + } + chained_irq_exit(chip, desc); +} + +static int brcmstb_gpio_reboot(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct brcmstb_gpio_priv *priv = + container_of(nb, struct brcmstb_gpio_priv, reboot_notifier); + + /* Enable GPIO for S5 cold boot */ + if (action == SYS_POWER_OFF) + brcmstb_gpio_priv_set_wake(priv, 1); + + return NOTIFY_DONE; +} + /* Make sure that the number of banks matches up between properties */ static int brcmstb_gpio_sanity_check_banks(struct device *dev, struct device_node *np, struct resource *res) @@ -100,7 +305,13 @@ static int brcmstb_gpio_remove(struct platform_device *pdev) bank = list_entry(pos, struct brcmstb_gpio_bank, node); ret = bgpio_remove(&bank->bgc); if (ret) - dev_err(&pdev->dev, "gpiochip_remove fail in cleanup"); + dev_err(&pdev->dev, "gpiochip_remove fail in cleanup\n"); + } + if (priv->reboot_notifier.notifier_call) { + ret = unregister_reboot_notifier(&priv->reboot_notifier); + if (ret) + dev_err(&pdev->dev, + "failed to unregister reboot notifier\n"); } return ret; } @@ -121,7 +332,7 @@ static int brcmstb_gpio_of_xlate(struct gpio_chip *gc, return -EINVAL; offset = gpiospec->args[0] - (gc->base - priv->gpio_base); - if (offset >= gc->ngpio) + if (offset >= gc->ngpio || offset < 0) return -EINVAL; if (unlikely(offset >= bank->width)) { @@ -136,6 +347,65 @@ static int brcmstb_gpio_of_xlate(struct gpio_chip *gc, return offset; } +/* Before calling, must have bank->parent_irq set and gpiochip registered */ +static int brcmstb_gpio_irq_setup(struct platform_device *pdev, + struct brcmstb_gpio_bank *bank) +{ + struct brcmstb_gpio_priv *priv = bank->parent_priv; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + + bank->irq_chip.name = dev_name(dev); + bank->irq_chip.irq_mask = brcmstb_gpio_irq_mask; + bank->irq_chip.irq_unmask = brcmstb_gpio_irq_unmask; + bank->irq_chip.irq_set_type = brcmstb_gpio_irq_set_type; + + /* Ensures that all non-wakeup IRQs are disabled at suspend */ + bank->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND; + + if (IS_ENABLED(CONFIG_PM_SLEEP) && !priv->can_wake && + of_property_read_bool(np, "wakeup-source")) { + priv->parent_wake_irq = platform_get_irq(pdev, 1); + if (priv->parent_wake_irq < 0) { + dev_warn(dev, + "Couldn't get wake IRQ - GPIOs will not be able to wake from sleep"); + } else { + int err; + + /* + * Set wakeup capability before requesting wakeup + * interrupt, so we can process boot-time "wakeups" + * (e.g., from S5 cold boot) + */ + device_set_wakeup_capable(dev, true); + device_wakeup_enable(dev); + err = devm_request_irq(dev, priv->parent_wake_irq, + brcmstb_gpio_wake_irq_handler, 0, + "brcmstb-gpio-wake", priv); + + if (err < 0) { + dev_err(dev, "Couldn't request wake IRQ"); + return err; + } + + priv->reboot_notifier.notifier_call = + brcmstb_gpio_reboot; + register_reboot_notifier(&priv->reboot_notifier); + priv->can_wake = true; + } + } + + if (priv->can_wake) + bank->irq_chip.irq_set_wake = brcmstb_gpio_irq_set_wake; + + gpiochip_irqchip_add(&bank->bgc.gc, &bank->irq_chip, 0, + handle_simple_irq, IRQ_TYPE_NONE); + gpiochip_set_chained_irqchip(&bank->bgc.gc, &bank->irq_chip, + priv->parent_irq, brcmstb_gpio_irq_handler); + + return 0; +} + static int brcmstb_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -146,6 +416,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) struct property *prop; const __be32 *p; u32 bank_width; + int num_banks = 0; int err; static int gpio_base; @@ -164,6 +435,16 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) priv->reg_base = reg_base; priv->pdev = pdev; + if (of_property_read_bool(np, "interrupt-controller")) { + priv->parent_irq = platform_get_irq(pdev, 0); + if (priv->parent_irq <= 0) { + dev_err(dev, "Couldn't get IRQ"); + return -ENOENT; + } + } else { + priv->parent_irq = -ENOENT; + } + if (brcmstb_gpio_sanity_check_banks(dev, np, res)) return -EINVAL; @@ -180,7 +461,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) } bank->parent_priv = priv; - bank->id = priv->num_banks; + bank->id = num_banks; if (bank_width <= 0 || bank_width > MAX_GPIO_PER_BANK) { dev_err(dev, "Invalid bank width %d\n", bank_width); goto fail; @@ -212,6 +493,12 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) /* not all ngpio lines are valid, will use bank width later */ gc->ngpio = MAX_GPIO_PER_BANK; + /* + * Mask all interrupts by default, since wakeup interrupts may + * be retained from S5 cold boot + */ + bank->bgc.write_reg(reg_base + GIO_MASK(bank->id), 0); + err = gpiochip_add(gc); if (err) { dev_err(dev, "Could not add gpiochip for bank %d\n", @@ -219,17 +506,24 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) goto fail; } gpio_base += gc->ngpio; + + if (priv->parent_irq > 0) { + err = brcmstb_gpio_irq_setup(pdev, bank); + if (err) + goto fail; + } + dev_dbg(dev, "bank=%d, base=%d, ngpio=%d, width=%d\n", bank->id, gc->base, gc->ngpio, bank->width); /* Everything looks good, so add bank to list */ list_add(&bank->node, &priv->bank_list); - priv->num_banks++; + num_banks++; } dev_info(dev, "Registered %d banks (GPIO(s): %d-%d)\n", - priv->num_banks, priv->gpio_base, gpio_base - 1); + num_banks, priv->gpio_base, gpio_base - 1); return 0; diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index c246ac3dda7c..94b0ab709721 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -65,11 +65,11 @@ static struct davinci_gpio_regs __iomem *gpio2regs(unsigned gpio) return ptr; } -static inline struct davinci_gpio_regs __iomem *irq2regs(int irq) +static inline struct davinci_gpio_regs __iomem *irq2regs(struct irq_data *d) { struct davinci_gpio_regs __iomem *g; - g = (__force struct davinci_gpio_regs __iomem *)irq_get_chip_data(irq); + g = (__force struct davinci_gpio_regs __iomem *)irq_data_get_irq_chip_data(d); return g; } @@ -287,7 +287,7 @@ static int davinci_gpio_probe(struct platform_device *pdev) static void gpio_irq_disable(struct irq_data *d) { - struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); + struct davinci_gpio_regs __iomem *g = irq2regs(d); u32 mask = (u32) irq_data_get_irq_handler_data(d); writel_relaxed(mask, &g->clr_falling); @@ -296,7 +296,7 @@ static void gpio_irq_disable(struct irq_data *d) static void gpio_irq_enable(struct irq_data *d) { - struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); + struct davinci_gpio_regs __iomem *g = irq2regs(d); u32 mask = (u32) irq_data_get_irq_handler_data(d); unsigned status = irqd_get_trigger_type(d); @@ -327,8 +327,9 @@ static struct irq_chip gpio_irqchip = { }; static void -gpio_irq_handler(unsigned irq, struct irq_desc *desc) +gpio_irq_handler(unsigned __irq, struct irq_desc *desc) { + unsigned int irq = irq_desc_get_irq(desc); struct davinci_gpio_regs __iomem *g; u32 mask = 0xffff; struct davinci_gpio_controller *d; @@ -396,7 +397,7 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger) struct davinci_gpio_regs __iomem *g; u32 mask; - d = (struct davinci_gpio_controller *)data->handler_data; + d = (struct davinci_gpio_controller *)irq_data_get_irq_handler_data(data); g = (struct davinci_gpio_regs __iomem *)d->regs; mask = __gpio_mask(data->irq - d->gpio_irq); @@ -422,7 +423,6 @@ davinci_gpio_irq_map(struct irq_domain *d, unsigned int irq, irq_set_irq_type(irq, IRQ_TYPE_NONE); irq_set_chip_data(irq, (__force void *)g); irq_set_handler_data(irq, (void *)__gpio_mask(hw)); - set_irq_flags(irq, IRQF_VALID); return 0; } @@ -545,7 +545,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) chips[0].chip.to_irq = gpio_to_irq_unbanked; chips[0].gpio_irq = bank_irq; chips[0].gpio_unbanked = pdata->gpio_unbanked; - binten = BIT(0); + binten = GENMASK(pdata->gpio_unbanked / 16, 0); /* AINTC handles mask/unmask; GPIO handles triggering */ irq = bank_irq; diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 55fa9853a7f2..c5be4b9b8baf 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -149,7 +149,7 @@ static u32 dwapb_do_irq(struct dwapb_gpio *gpio) static void dwapb_irq_handler(u32 irq, struct irq_desc *desc) { - struct dwapb_gpio *gpio = irq_get_handler_data(irq); + struct dwapb_gpio *gpio = irq_desc_get_handler_data(desc); struct irq_chip *chip = irq_desc_get_chip(desc); dwapb_do_irq(gpio); diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index fbf287307c4c..6bca1e125e12 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -31,7 +31,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/pinctrl/consumer.h> -#include <linux/platform_data/gpio-em.h> struct em_gio_priv { void __iomem *base0; @@ -262,7 +261,6 @@ static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int irq, irq_set_chip_data(irq, h->host_data); irq_set_chip_and_handler(irq, &p->irq_chip, handle_level_irq); - set_irq_flags(irq, IRQF_VALID); /* kill me now */ return 0; } @@ -273,13 +271,12 @@ static const struct irq_domain_ops em_gio_irq_domain_ops = { static int em_gio_probe(struct platform_device *pdev) { - struct gpio_em_config pdata_dt; - struct gpio_em_config *pdata = dev_get_platdata(&pdev->dev); struct em_gio_priv *p; struct resource *io[2], *irq[2]; struct gpio_chip *gpio_chip; struct irq_chip *irq_chip; const char *name = dev_name(&pdev->dev); + unsigned int ngpios; int ret; p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); @@ -319,18 +316,10 @@ static int em_gio_probe(struct platform_device *pdev) goto err0; } - if (!pdata) { - memset(&pdata_dt, 0, sizeof(pdata_dt)); - pdata = &pdata_dt; - - if (of_property_read_u32(pdev->dev.of_node, "ngpios", - &pdata->number_of_pins)) { - dev_err(&pdev->dev, "Missing ngpios OF property\n"); - ret = -EINVAL; - goto err0; - } - - pdata->gpio_base = -1; + if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) { + dev_err(&pdev->dev, "Missing ngpios OF property\n"); + ret = -EINVAL; + goto err0; } gpio_chip = &p->gpio_chip; @@ -345,8 +334,8 @@ static int em_gio_probe(struct platform_device *pdev) gpio_chip->label = name; gpio_chip->dev = &pdev->dev; gpio_chip->owner = THIS_MODULE; - gpio_chip->base = pdata->gpio_base; - gpio_chip->ngpio = pdata->number_of_pins; + gpio_chip->base = -1; + gpio_chip->ngpio = ngpios; irq_chip = &p->irq_chip; irq_chip->name = name; @@ -357,9 +346,7 @@ static int em_gio_probe(struct platform_device *pdev) irq_chip->irq_release_resources = em_gio_irq_relres; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; - p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, - pdata->number_of_pins, - pdata->irq_base, + p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, ngpios, 0, &em_gio_irq_domain_ops, p); if (!p->irq_domain) { ret = -ENXIO; @@ -387,12 +374,6 @@ static int em_gio_probe(struct platform_device *pdev) goto err1; } - if (pdata->pctl_name) { - ret = gpiochip_add_pin_range(gpio_chip, pdata->pctl_name, 0, - gpio_chip->base, gpio_chip->ngpio); - if (ret < 0) - dev_warn(&pdev->dev, "failed to add pin range\n"); - } return 0; err1: diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c index 45684f36ddb1..9d90366ea259 100644 --- a/drivers/gpio/gpio-ep93xx.c +++ b/drivers/gpio/gpio-ep93xx.c @@ -100,13 +100,15 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) } } -static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) +static void ep93xx_gpio_f_irq_handler(unsigned int __irq, + struct irq_desc *desc) { /* * map discontiguous hw irq range to continuous sw irq range: * * IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7}) */ + unsigned int irq = irq_desc_get_irq(desc); int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */ int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx; @@ -208,7 +210,7 @@ static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type) return -EINVAL; } - __irq_set_handler_locked(d->irq, handler); + irq_set_handler_locked(d, handler); gpio_int_enabled[port] |= port_mask; @@ -234,7 +236,7 @@ static void ep93xx_gpio_init_irq(void) gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) { irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip, handle_level_irq); - set_irq_flags(gpio_irq, IRQF_VALID); + irq_clear_status_flags(gpio_irq, IRQ_NOREQUEST); } irq_set_chained_handler(IRQ_EP93XX_GPIO_AB, diff --git a/drivers/gpio/gpio-etraxfs.c b/drivers/gpio/gpio-etraxfs.c index 28071f4a5672..2ffcd9fdd1f2 100644 --- a/drivers/gpio/gpio-etraxfs.c +++ b/drivers/gpio/gpio-etraxfs.c @@ -1,8 +1,10 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/gpio.h> +#include <linux/gpio/driver.h> #include <linux/of_gpio.h> #include <linux/io.h> +#include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/basic_mmio_gpio.h> @@ -13,6 +15,7 @@ #define ETRAX_FS_rw_intr_mask 16 #define ETRAX_FS_rw_ack_intr 20 #define ETRAX_FS_r_intr 24 +#define ETRAX_FS_r_masked_intr 28 #define ETRAX_FS_rw_pb_dout 32 #define ETRAX_FS_r_pb_din 36 #define ETRAX_FS_rw_pb_oe 40 @@ -26,6 +29,48 @@ #define ETRAX_FS_r_pe_din 84 #define ETRAX_FS_rw_pe_oe 88 +#define ARTPEC3_r_pa_din 0 +#define ARTPEC3_rw_pa_dout 4 +#define ARTPEC3_rw_pa_oe 8 +#define ARTPEC3_r_pb_din 44 +#define ARTPEC3_rw_pb_dout 48 +#define ARTPEC3_rw_pb_oe 52 +#define ARTPEC3_r_pc_din 88 +#define ARTPEC3_rw_pc_dout 92 +#define ARTPEC3_rw_pc_oe 96 +#define ARTPEC3_r_pd_din 116 +#define ARTPEC3_rw_intr_cfg 120 +#define ARTPEC3_rw_intr_pins 124 +#define ARTPEC3_rw_intr_mask 128 +#define ARTPEC3_rw_ack_intr 132 +#define ARTPEC3_r_masked_intr 140 + +#define GIO_CFG_OFF 0 +#define GIO_CFG_HI 1 +#define GIO_CFG_LO 2 +#define GIO_CFG_SET 3 +#define GIO_CFG_POSEDGE 5 +#define GIO_CFG_NEGEDGE 6 +#define GIO_CFG_ANYEDGE 7 + +struct etraxfs_gpio_info; + +struct etraxfs_gpio_block { + spinlock_t lock; + u32 mask; + u32 cfg; + u32 pins; + unsigned int group[8]; + + void __iomem *regs; + const struct etraxfs_gpio_info *info; +}; + +struct etraxfs_gpio_chip { + struct bgpio_chip bgc; + struct etraxfs_gpio_block *block; +}; + struct etraxfs_gpio_port { const char *label; unsigned int oe; @@ -37,6 +82,12 @@ struct etraxfs_gpio_port { struct etraxfs_gpio_info { unsigned int num_ports; const struct etraxfs_gpio_port *ports; + + unsigned int rw_ack_intr; + unsigned int rw_intr_mask; + unsigned int rw_intr_cfg; + unsigned int rw_intr_pins; + unsigned int r_masked_intr; }; static const struct etraxfs_gpio_port etraxfs_gpio_etraxfs_ports[] = { @@ -80,8 +131,56 @@ static const struct etraxfs_gpio_port etraxfs_gpio_etraxfs_ports[] = { static const struct etraxfs_gpio_info etraxfs_gpio_etraxfs = { .num_ports = ARRAY_SIZE(etraxfs_gpio_etraxfs_ports), .ports = etraxfs_gpio_etraxfs_ports, + .rw_ack_intr = ETRAX_FS_rw_ack_intr, + .rw_intr_mask = ETRAX_FS_rw_intr_mask, + .rw_intr_cfg = ETRAX_FS_rw_intr_cfg, + .r_masked_intr = ETRAX_FS_r_masked_intr, +}; + +static const struct etraxfs_gpio_port etraxfs_gpio_artpec3_ports[] = { + { + .label = "A", + .ngpio = 32, + .oe = ARTPEC3_rw_pa_oe, + .dout = ARTPEC3_rw_pa_dout, + .din = ARTPEC3_r_pa_din, + }, + { + .label = "B", + .ngpio = 32, + .oe = ARTPEC3_rw_pb_oe, + .dout = ARTPEC3_rw_pb_dout, + .din = ARTPEC3_r_pb_din, + }, + { + .label = "C", + .ngpio = 16, + .oe = ARTPEC3_rw_pc_oe, + .dout = ARTPEC3_rw_pc_dout, + .din = ARTPEC3_r_pc_din, + }, + { + .label = "D", + .ngpio = 32, + .din = ARTPEC3_r_pd_din, + }, +}; + +static const struct etraxfs_gpio_info etraxfs_gpio_artpec3 = { + .num_ports = ARRAY_SIZE(etraxfs_gpio_artpec3_ports), + .ports = etraxfs_gpio_artpec3_ports, + .rw_ack_intr = ARTPEC3_rw_ack_intr, + .rw_intr_mask = ARTPEC3_rw_intr_mask, + .rw_intr_cfg = ARTPEC3_rw_intr_cfg, + .r_masked_intr = ARTPEC3_r_masked_intr, + .rw_intr_pins = ARTPEC3_rw_intr_pins, }; +static unsigned int etraxfs_gpio_chip_to_port(struct gpio_chip *gc) +{ + return gc->label[0] - 'A'; +} + static int etraxfs_gpio_of_xlate(struct gpio_chip *gc, const struct of_phandle_args *gpiospec, u32 *flags) @@ -90,7 +189,7 @@ static int etraxfs_gpio_of_xlate(struct gpio_chip *gc, * Port numbers are A to E, and the properties are integers, so we * specify them as 0xA - 0xE. */ - if (gc->label[0] - 'A' + 0xA != gpiospec->args[2]) + if (etraxfs_gpio_chip_to_port(gc) + 0xA != gpiospec->args[2]) return -EINVAL; return of_gpio_simple_xlate(gc, gpiospec, flags); @@ -101,24 +200,174 @@ static const struct of_device_id etraxfs_gpio_of_table[] = { .compatible = "axis,etraxfs-gio", .data = &etraxfs_gpio_etraxfs, }, + { + .compatible = "axis,artpec3-gio", + .data = &etraxfs_gpio_artpec3, + }, {}, }; +static unsigned int etraxfs_gpio_to_group_irq(unsigned int gpio) +{ + return gpio % 8; +} + +static unsigned int etraxfs_gpio_to_group_pin(struct etraxfs_gpio_chip *chip, + unsigned int gpio) +{ + return 4 * etraxfs_gpio_chip_to_port(&chip->bgc.gc) + gpio / 8; +} + +static void etraxfs_gpio_irq_ack(struct irq_data *d) +{ + struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct etraxfs_gpio_block *block = chip->block; + unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); + + writel(BIT(grpirq), block->regs + block->info->rw_ack_intr); +} + +static void etraxfs_gpio_irq_mask(struct irq_data *d) +{ + struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct etraxfs_gpio_block *block = chip->block; + unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); + + spin_lock(&block->lock); + block->mask &= ~BIT(grpirq); + writel(block->mask, block->regs + block->info->rw_intr_mask); + spin_unlock(&block->lock); +} + +static void etraxfs_gpio_irq_unmask(struct irq_data *d) +{ + struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct etraxfs_gpio_block *block = chip->block; + unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); + + spin_lock(&block->lock); + block->mask |= BIT(grpirq); + writel(block->mask, block->regs + block->info->rw_intr_mask); + spin_unlock(&block->lock); +} + +static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type) +{ + struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct etraxfs_gpio_block *block = chip->block; + unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); + u32 cfg; + + switch (type) { + case IRQ_TYPE_EDGE_RISING: + cfg = GIO_CFG_POSEDGE; + break; + case IRQ_TYPE_EDGE_FALLING: + cfg = GIO_CFG_NEGEDGE; + break; + case IRQ_TYPE_EDGE_BOTH: + cfg = GIO_CFG_ANYEDGE; + break; + case IRQ_TYPE_LEVEL_LOW: + cfg = GIO_CFG_LO; + break; + case IRQ_TYPE_LEVEL_HIGH: + cfg = GIO_CFG_HI; + break; + default: + return -EINVAL; + } + + spin_lock(&block->lock); + block->cfg &= ~(0x7 << (grpirq * 3)); + block->cfg |= (cfg << (grpirq * 3)); + writel(block->cfg, block->regs + block->info->rw_intr_cfg); + spin_unlock(&block->lock); + + return 0; +} + +static int etraxfs_gpio_irq_request_resources(struct irq_data *d) +{ + struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct etraxfs_gpio_block *block = chip->block; + unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); + int ret = -EBUSY; + + spin_lock(&block->lock); + if (block->group[grpirq]) + goto out; + + ret = gpiochip_lock_as_irq(&chip->bgc.gc, d->hwirq); + if (ret) + goto out; + + block->group[grpirq] = d->irq; + if (block->info->rw_intr_pins) { + unsigned int pin = etraxfs_gpio_to_group_pin(chip, d->hwirq); + + block->pins &= ~(0xf << (grpirq * 4)); + block->pins |= (pin << (grpirq * 4)); + + writel(block->pins, block->regs + block->info->rw_intr_pins); + } + +out: + spin_unlock(&block->lock); + return ret; +} + +static void etraxfs_gpio_irq_release_resources(struct irq_data *d) +{ + struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct etraxfs_gpio_block *block = chip->block; + unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); + + spin_lock(&block->lock); + block->group[grpirq] = 0; + gpiochip_unlock_as_irq(&chip->bgc.gc, d->hwirq); + spin_unlock(&block->lock); +} + +static struct irq_chip etraxfs_gpio_irq_chip = { + .name = "gpio-etraxfs", + .irq_ack = etraxfs_gpio_irq_ack, + .irq_mask = etraxfs_gpio_irq_mask, + .irq_unmask = etraxfs_gpio_irq_unmask, + .irq_set_type = etraxfs_gpio_irq_set_type, + .irq_request_resources = etraxfs_gpio_irq_request_resources, + .irq_release_resources = etraxfs_gpio_irq_release_resources, +}; + +static irqreturn_t etraxfs_gpio_interrupt(int irq, void *dev_id) +{ + struct etraxfs_gpio_block *block = dev_id; + unsigned long intr = readl(block->regs + block->info->r_masked_intr); + int bit; + + for_each_set_bit(bit, &intr, 8) + generic_handle_irq(block->group[bit]); + + return IRQ_RETVAL(intr & 0xff); +} + static int etraxfs_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct etraxfs_gpio_info *info; const struct of_device_id *match; - struct bgpio_chip *chips; - struct resource *res; + struct etraxfs_gpio_block *block; + struct etraxfs_gpio_chip *chips; + struct resource *res, *irq; + bool allportsirq = false; void __iomem *regs; int ret; int i; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(dev, res); - if (!regs) - return -ENOMEM; + if (IS_ERR(regs)) + return PTR_ERR(regs); match = of_match_node(etraxfs_gpio_of_table, dev->of_node); if (!match) @@ -130,19 +379,57 @@ static int etraxfs_gpio_probe(struct platform_device *pdev) if (!chips) return -ENOMEM; + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!irq) + return -EINVAL; + + block = devm_kzalloc(dev, sizeof(*block), GFP_KERNEL); + if (!block) + return -ENOMEM; + + spin_lock_init(&block->lock); + + block->regs = regs; + block->info = info; + + writel(0, block->regs + info->rw_intr_mask); + writel(0, block->regs + info->rw_intr_cfg); + if (info->rw_intr_pins) { + allportsirq = true; + writel(0, block->regs + info->rw_intr_pins); + } + + ret = devm_request_irq(dev, irq->start, etraxfs_gpio_interrupt, + IRQF_SHARED, dev_name(dev), block); + if (ret) { + dev_err(dev, "Unable to request irq %d\n", ret); + return ret; + } + for (i = 0; i < info->num_ports; i++) { - struct bgpio_chip *bgc = &chips[i]; + struct etraxfs_gpio_chip *chip = &chips[i]; + struct bgpio_chip *bgc = &chip->bgc; const struct etraxfs_gpio_port *port = &info->ports[i]; + unsigned long flags = BGPIOF_READ_OUTPUT_REG_SET; + void __iomem *dat = regs + port->din; + void __iomem *set = regs + port->dout; + void __iomem *dirout = regs + port->oe; + + chip->block = block; + + if (dirout == set) { + dirout = set = NULL; + flags = BGPIOF_NO_OUTPUT; + } ret = bgpio_init(bgc, dev, 4, - regs + port->din, /* dat */ - regs + port->dout, /* set */ - NULL, /* clr */ - regs + port->oe, /* dirout */ - NULL, /* dirin */ - BGPIOF_UNREADABLE_REG_SET); - if (ret) - return ret; + dat, set, NULL, dirout, NULL, + flags); + if (ret) { + dev_err(dev, "Unable to init port %s\n", + port->label); + continue; + } bgc->gc.ngpio = port->ngpio; bgc->gc.label = port->label; @@ -152,9 +439,21 @@ static int etraxfs_gpio_probe(struct platform_device *pdev) bgc->gc.of_xlate = etraxfs_gpio_of_xlate; ret = gpiochip_add(&bgc->gc); - if (ret) + if (ret) { dev_err(dev, "Unable to register port %s\n", bgc->gc.label); + continue; + } + + if (i > 0 && !allportsirq) + continue; + + ret = gpiochip_irqchip_add(&bgc->gc, &etraxfs_gpio_irq_chip, 0, + handle_level_irq, IRQ_TYPE_NONE); + if (ret) { + dev_err(dev, "Unable to add irqchip to port %s\n", + bgc->gc.label); + } } return 0; diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c index 9bda3727fac1..a3f07537fe62 100644 --- a/drivers/gpio/gpio-generic.c +++ b/drivers/gpio/gpio-generic.c @@ -153,6 +153,10 @@ static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) return !!(bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio)); } +static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val) +{ +} + static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { struct bgpio_chip *bgc = to_bgpio_chip(gc); @@ -279,6 +283,12 @@ static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) return 0; } +static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio, + int val) +{ + return -EINVAL; +} + static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { @@ -302,6 +312,14 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) return 0; } +static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) +{ + struct bgpio_chip *bgc = to_bgpio_chip(gc); + + return (bgc->read_reg(bgc->reg_dir) & bgc->pin2mask(bgc, gpio)) ? + GPIOF_DIR_OUT : GPIOF_DIR_IN; +} + static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { struct bgpio_chip *bgc = to_bgpio_chip(gc); @@ -351,6 +369,14 @@ static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val) return 0; } +static int bgpio_get_dir_inv(struct gpio_chip *gc, unsigned int gpio) +{ + struct bgpio_chip *bgc = to_bgpio_chip(gc); + + return (bgc->read_reg(bgc->reg_dir) & bgc->pin2mask(bgc, gpio)) ? + GPIOF_DIR_IN : GPIOF_DIR_OUT; +} + static int bgpio_setup_accessors(struct device *dev, struct bgpio_chip *bgc, bool bit_be, @@ -444,6 +470,9 @@ static int bgpio_setup_io(struct bgpio_chip *bgc, bgc->reg_set = set; bgc->gc.set = bgpio_set_set; bgc->gc.set_multiple = bgpio_set_multiple_set; + } else if (flags & BGPIOF_NO_OUTPUT) { + bgc->gc.set = bgpio_set_none; + bgc->gc.set_multiple = NULL; } else { bgc->gc.set = bgpio_set; bgc->gc.set_multiple = bgpio_set_multiple; @@ -460,7 +489,8 @@ static int bgpio_setup_io(struct bgpio_chip *bgc, static int bgpio_setup_direction(struct bgpio_chip *bgc, void __iomem *dirout, - void __iomem *dirin) + void __iomem *dirin, + unsigned long flags) { if (dirout && dirin) { return -EINVAL; @@ -468,12 +498,17 @@ static int bgpio_setup_direction(struct bgpio_chip *bgc, bgc->reg_dir = dirout; bgc->gc.direction_output = bgpio_dir_out; bgc->gc.direction_input = bgpio_dir_in; + bgc->gc.get_direction = bgpio_get_dir; } else if (dirin) { bgc->reg_dir = dirin; bgc->gc.direction_output = bgpio_dir_out_inv; bgc->gc.direction_input = bgpio_dir_in_inv; + bgc->gc.get_direction = bgpio_get_dir_inv; } else { - bgc->gc.direction_output = bgpio_simple_dir_out; + if (flags & BGPIOF_NO_OUTPUT) + bgc->gc.direction_output = bgpio_dir_out_err; + else + bgc->gc.direction_output = bgpio_simple_dir_out; bgc->gc.direction_input = bgpio_simple_dir_in; } @@ -525,7 +560,7 @@ int bgpio_init(struct bgpio_chip *bgc, struct device *dev, if (ret) return ret; - ret = bgpio_setup_direction(bgc, dirout, dirin); + ret = bgpio_setup_direction(bgc, dirout, dirin, flags); if (ret) return ret; diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c index 0a8f7617e72e..801423fe8143 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -104,17 +104,12 @@ static void grgpio_set_imask(struct grgpio_priv *priv, unsigned int offset, { struct bgpio_chip *bgc = &priv->bgc; unsigned long mask = bgc->pin2mask(bgc, offset); - unsigned long flags; - - spin_lock_irqsave(&bgc->lock, flags); if (val) priv->imask |= mask; else priv->imask &= ~mask; bgc->write_reg(priv->regs + GRGPIO_IMASK, priv->imask); - - spin_unlock_irqrestore(&bgc->lock, flags); } static int grgpio_to_irq(struct gpio_chip *gc, unsigned offset) @@ -180,16 +175,26 @@ static void grgpio_irq_mask(struct irq_data *d) { struct grgpio_priv *priv = irq_data_get_irq_chip_data(d); int offset = d->hwirq; + unsigned long flags; + + spin_lock_irqsave(&priv->bgc.lock, flags); grgpio_set_imask(priv, offset, 0); + + spin_unlock_irqrestore(&priv->bgc.lock, flags); } static void grgpio_irq_unmask(struct irq_data *d) { struct grgpio_priv *priv = irq_data_get_irq_chip_data(d); int offset = d->hwirq; + unsigned long flags; + + spin_lock_irqsave(&priv->bgc.lock, flags); grgpio_set_imask(priv, offset, 1); + + spin_unlock_irqrestore(&priv->bgc.lock, flags); } static struct irq_chip grgpio_irq_chip = { @@ -281,12 +286,7 @@ static int grgpio_irq_map(struct irq_domain *d, unsigned int irq, irq_set_chip_data(irq, priv); irq_set_chip_and_handler(irq, &grgpio_irq_chip, handle_simple_irq); - irq_clear_status_flags(irq, IRQ_NOREQUEST); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else irq_set_noprobe(irq); -#endif return ret; } @@ -301,9 +301,6 @@ static void grgpio_irq_unmap(struct irq_domain *d, unsigned int irq) int ngpio = priv->bgc.gc.ngpio; int i; -#ifdef CONFIG_ARM - set_irq_flags(irq, 0); -#endif irq_set_chip_and_handler(irq, NULL, NULL); irq_set_chip_data(irq, NULL); diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index 7d3c90e9da71..8c5252c6c327 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -685,9 +685,14 @@ static int max732x_probe(struct i2c_client *client, mutex_init(&chip->lock); - max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]); - if (nr_port > 8) - max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]); + ret = max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]); + if (ret) + goto out_failed; + if (nr_port > 8) { + ret = max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]); + if (ret) + goto out_failed; + } ret = gpiochip_add(&chip->gpio_chip); if (ret) diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 2fc7ff852d16..73db7ecd7ffd 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -507,11 +507,7 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp) irq_set_chip_data(irq, mcp); irq_set_chip(irq, &mcp23s08_irq_chip); irq_set_nested_thread(irq, true); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else irq_set_noprobe(irq); -#endif } return 0; } diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 20aa66f34f6e..8ef7a12de983 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -32,7 +32,7 @@ struct mpc8xxx_gpio_chip { struct of_mm_gpio_chip mm_gc; - spinlock_t lock; + raw_spinlock_t lock; /* * shadowed data register to be able to clear/set output pins in @@ -95,7 +95,7 @@ static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); unsigned long flags; - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); if (val) mpc8xxx_gc->data |= mpc8xxx_gpio2mask(gpio); @@ -104,7 +104,7 @@ static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); } static void mpc8xxx_gpio_set_multiple(struct gpio_chip *gc, @@ -115,7 +115,7 @@ static void mpc8xxx_gpio_set_multiple(struct gpio_chip *gc, unsigned long flags; int i; - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); for (i = 0; i < gc->ngpio; i++) { if (*mask == 0) @@ -130,7 +130,7 @@ static void mpc8xxx_gpio_set_multiple(struct gpio_chip *gc, out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); } static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) @@ -139,11 +139,11 @@ static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); unsigned long flags; - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); return 0; } @@ -156,11 +156,11 @@ static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val mpc8xxx_gpio_set(gc, gpio, val); - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); return 0; } @@ -174,6 +174,15 @@ static int mpc5121_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val return mpc8xxx_gpio_dir_out(gc, gpio, val); } +static int mpc5125_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) +{ + /* GPIO 0..3 are input only on MPC5125 */ + if (gpio <= 3) + return -EINVAL; + + return mpc8xxx_gpio_dir_out(gc, gpio, val); +} + static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset) { struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); @@ -206,11 +215,11 @@ static void mpc8xxx_irq_unmask(struct irq_data *d) struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; unsigned long flags; - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); } static void mpc8xxx_irq_mask(struct irq_data *d) @@ -219,11 +228,11 @@ static void mpc8xxx_irq_mask(struct irq_data *d) struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; unsigned long flags; - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); } static void mpc8xxx_irq_ack(struct irq_data *d) @@ -242,17 +251,17 @@ static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type) switch (flow_type) { case IRQ_TYPE_EDGE_FALLING: - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); setbits32(mm->regs + GPIO_ICR, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); break; case IRQ_TYPE_EDGE_BOTH: - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); clrbits32(mm->regs + GPIO_ICR, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); break; default: @@ -282,22 +291,22 @@ static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type) switch (flow_type) { case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_LEVEL_LOW: - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); clrsetbits_be32(reg, 3 << shift, 2 << shift); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); break; case IRQ_TYPE_EDGE_RISING: case IRQ_TYPE_LEVEL_HIGH: - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); clrsetbits_be32(reg, 3 << shift, 1 << shift); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); break; case IRQ_TYPE_EDGE_BOTH: - spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); clrbits32(reg, 3 << shift); - spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); break; default: @@ -312,17 +321,13 @@ static struct irq_chip mpc8xxx_irq_chip = { .irq_unmask = mpc8xxx_irq_unmask, .irq_mask = mpc8xxx_irq_mask, .irq_ack = mpc8xxx_irq_ack, + /* this might get overwritten in mpc8xxx_probe() */ .irq_set_type = mpc8xxx_irq_set_type, }; static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int irq, irq_hw_number_t hwirq) { - struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data; - - if (mpc8xxx_gc->of_dev_id_data) - mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data; - irq_set_chip_data(irq, h->host_data); irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_level_irq); @@ -334,11 +339,38 @@ static const struct irq_domain_ops mpc8xxx_gpio_irq_ops = { .xlate = irq_domain_xlate_twocell, }; -static struct of_device_id mpc8xxx_gpio_ids[] = { +struct mpc8xxx_gpio_devtype { + int (*gpio_dir_out)(struct gpio_chip *, unsigned int, int); + int (*gpio_get)(struct gpio_chip *, unsigned int); + int (*irq_set_type)(struct irq_data *, unsigned int); +}; + +static const struct mpc8xxx_gpio_devtype mpc512x_gpio_devtype = { + .gpio_dir_out = mpc5121_gpio_dir_out, + .irq_set_type = mpc512x_irq_set_type, +}; + +static const struct mpc8xxx_gpio_devtype mpc5125_gpio_devtype = { + .gpio_dir_out = mpc5125_gpio_dir_out, + .irq_set_type = mpc512x_irq_set_type, +}; + +static const struct mpc8xxx_gpio_devtype mpc8572_gpio_devtype = { + .gpio_get = mpc8572_gpio_get, +}; + +static const struct mpc8xxx_gpio_devtype mpc8xxx_gpio_devtype_default = { + .gpio_dir_out = mpc8xxx_gpio_dir_out, + .gpio_get = mpc8xxx_gpio_get, + .irq_set_type = mpc8xxx_irq_set_type, +}; + +static const struct of_device_id mpc8xxx_gpio_ids[] = { { .compatible = "fsl,mpc8349-gpio", }, - { .compatible = "fsl,mpc8572-gpio", }, + { .compatible = "fsl,mpc8572-gpio", .data = &mpc8572_gpio_devtype, }, { .compatible = "fsl,mpc8610-gpio", }, - { .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, }, + { .compatible = "fsl,mpc5121-gpio", .data = &mpc512x_gpio_devtype, }, + { .compatible = "fsl,mpc5125-gpio", .data = &mpc5125_gpio_devtype, }, { .compatible = "fsl,pq3-gpio", }, { .compatible = "fsl,qoriq-gpio", }, {} @@ -351,6 +383,8 @@ static int mpc8xxx_probe(struct platform_device *pdev) struct of_mm_gpio_chip *mm_gc; struct gpio_chip *gc; const struct of_device_id *id; + const struct mpc8xxx_gpio_devtype *devtype = + of_device_get_match_data(&pdev->dev); int ret; mpc8xxx_gc = devm_kzalloc(&pdev->dev, sizeof(*mpc8xxx_gc), GFP_KERNEL); @@ -359,7 +393,7 @@ static int mpc8xxx_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mpc8xxx_gc); - spin_lock_init(&mpc8xxx_gc->lock); + raw_spin_lock_init(&mpc8xxx_gc->lock); mm_gc = &mpc8xxx_gc->mm_gc; gc = &mm_gc->gc; @@ -367,10 +401,18 @@ static int mpc8xxx_probe(struct platform_device *pdev) mm_gc->save_regs = mpc8xxx_gpio_save_regs; gc->ngpio = MPC8XXX_GPIO_PINS; gc->direction_input = mpc8xxx_gpio_dir_in; - gc->direction_output = of_device_is_compatible(np, "fsl,mpc5121-gpio") ? - mpc5121_gpio_dir_out : mpc8xxx_gpio_dir_out; - gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ? - mpc8572_gpio_get : mpc8xxx_gpio_get; + + if (!devtype) + devtype = &mpc8xxx_gpio_devtype_default; + + /* + * It's assumed that only a single type of gpio controller is available + * on the current machine, so overwriting global data is fine. + */ + mpc8xxx_irq_chip.irq_set_type = devtype->irq_set_type; + + gc->direction_output = devtype->gpio_dir_out ?: mpc8xxx_gpio_dir_out; + gc->get = devtype->gpio_get ?: mpc8xxx_gpio_get; gc->set = mpc8xxx_gpio_set; gc->set_multiple = mpc8xxx_gpio_set_multiple; gc->to_irq = mpc8xxx_gpio_to_irq; @@ -396,8 +438,8 @@ static int mpc8xxx_probe(struct platform_device *pdev) out_be32(mm_gc->regs + GPIO_IER, 0xffffffff); out_be32(mm_gc->regs + GPIO_IMR, 0); - irq_set_handler_data(mpc8xxx_gc->irqn, mpc8xxx_gc); - irq_set_chained_handler(mpc8xxx_gc->irqn, mpc8xxx_gpio_irq_cascade); + irq_set_chained_handler_and_data(mpc8xxx_gc->irqn, + mpc8xxx_gpio_irq_cascade, mpc8xxx_gc); return 0; } @@ -407,8 +449,7 @@ static int mpc8xxx_remove(struct platform_device *pdev) struct mpc8xxx_gpio_chip *mpc8xxx_gc = platform_get_drvdata(pdev); if (mpc8xxx_gc->irq) { - irq_set_handler_data(mpc8xxx_gc->irqn, NULL); - irq_set_chained_handler(mpc8xxx_gc->irqn, NULL); + irq_set_chained_handler_and_data(mpc8xxx_gc->irqn, NULL, NULL); irq_domain_remove(mpc8xxx_gc->irq); } diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c index 52ff18229fdc..d2012cfb5571 100644 --- a/drivers/gpio/gpio-msm-v2.c +++ b/drivers/gpio/gpio-msm-v2.c @@ -187,14 +187,6 @@ static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset) return irq_create_mapping(domain, offset); } -static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq) -{ - struct irq_data *irq_data = irq_get_irq_data(irq); - - return irq_data->hwirq; -} - - /* For dual-edge interrupts in software, since the hardware has no * such support: * @@ -238,7 +230,7 @@ static void msm_gpio_update_dual_edge_pos(unsigned gpio) static void msm_gpio_irq_ack(struct irq_data *d) { - int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); + int gpio = d->hwirq; writel(BIT(INTR_STATUS), GPIO_INTR_STATUS(gpio)); if (test_bit(gpio, msm_gpio.dual_edge_irqs)) @@ -247,8 +239,8 @@ static void msm_gpio_irq_ack(struct irq_data *d) static void msm_gpio_irq_mask(struct irq_data *d) { - int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); unsigned long irq_flags; + int gpio = d->hwirq; spin_lock_irqsave(&tlmm_lock, irq_flags); writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio)); @@ -259,8 +251,8 @@ static void msm_gpio_irq_mask(struct irq_data *d) static void msm_gpio_irq_unmask(struct irq_data *d) { - int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); unsigned long irq_flags; + int gpio = d->hwirq; spin_lock_irqsave(&tlmm_lock, irq_flags); __set_bit(gpio, msm_gpio.enabled_irqs); @@ -271,8 +263,8 @@ static void msm_gpio_irq_unmask(struct irq_data *d) static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) { - int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); unsigned long irq_flags; + int gpio = d->hwirq; uint32_t bits; spin_lock_irqsave(&tlmm_lock, irq_flags); @@ -281,14 +273,14 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) if (flow_type & IRQ_TYPE_EDGE_BOTH) { bits |= BIT(INTR_DECT_CTL); - __irq_set_handler_locked(d->irq, handle_edge_irq); + irq_set_handler_locked(d, handle_edge_irq); if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) __set_bit(gpio, msm_gpio.dual_edge_irqs); else __clear_bit(gpio, msm_gpio.dual_edge_irqs); } else { bits &= ~BIT(INTR_DECT_CTL); - __irq_set_handler_locked(d->irq, handle_level_irq); + irq_set_handler_locked(d, handle_level_irq); __clear_bit(gpio, msm_gpio.dual_edge_irqs); } @@ -331,7 +323,7 @@ static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc) static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) { - int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); + int gpio = d->hwirq; if (on) { if (bitmap_empty(msm_gpio.wake_irqs, MAX_NR_GPIO)) @@ -363,7 +355,6 @@ static int msm_gpio_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_set_lockdep_class(irq, &msm_gpio_lock_class); irq_set_chip_and_handler(irq, &msm_gpio_irq_chip, handle_level_irq); - set_irq_flags(irq, IRQF_VALID); return 0; } diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 1a54205860f5..b396bf3bf294 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -458,9 +458,9 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type) return 0; } -static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +static void mvebu_gpio_irq_handler(unsigned int __irq, struct irq_desc *desc) { - struct mvebu_gpio_chip *mvchip = irq_get_handler_data(irq); + struct mvebu_gpio_chip *mvchip = irq_desc_get_handler_data(desc); struct irq_chip *chip = irq_desc_get_chip(desc); u32 cause, type; int i; @@ -787,8 +787,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev) if (irq < 0) continue; - irq_set_handler_data(irq, mvchip); - irq_set_chained_handler(irq, mvebu_gpio_irq_handler); + irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler, + mvchip); } mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index ec1eb1b7250f..b752b560126e 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -275,8 +275,8 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat) static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc) { u32 irq_stat; - struct mxc_gpio_port *port = irq_get_handler_data(irq); - struct irq_chip *chip = irq_get_chip(irq); + struct mxc_gpio_port *port = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); chained_irq_enter(chip, desc); @@ -292,7 +292,7 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc) { u32 irq_msk, irq_stat; struct mxc_gpio_port *port; - struct irq_chip *chip = irq_get_chip(irq); + struct irq_chip *chip = irq_desc_get_chip(desc); chained_irq_enter(chip, desc); @@ -339,7 +339,7 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable) return 0; } -static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base) +static void mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base) { struct irq_chip_generic *gc; struct irq_chip_type *ct; @@ -354,6 +354,7 @@ static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base) ct->chip.irq_unmask = irq_gc_mask_set_bit; ct->chip.irq_set_type = gpio_set_irq_type; ct->chip.irq_set_wake = gpio_set_wake_irq; + ct->chip.flags = IRQCHIP_MASK_ON_SUSPEND; ct->regs.ack = GPIO_ISR; ct->regs.mask = GPIO_IMR; diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 551d15d7c369..b7f383eb18d9 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -157,7 +157,7 @@ static void mxs_flip_edge(struct mxs_gpio_port *port, u32 gpio) static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) { u32 irq_stat; - struct mxs_gpio_port *port = irq_get_handler_data(irq); + struct mxs_gpio_port *port = irq_desc_get_handler_data(desc); desc->irq_data.chip->irq_ack(&desc->irq_data); diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 61a731ff9a07..2ae0d47e9554 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -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); @@ -57,7 +58,7 @@ struct gpio_bank { u32 saved_datain; u32 level_mask; u32 toggle_mask; - spinlock_t lock; + raw_spinlock_t lock; struct gpio_chip chip; struct clk *dbck; u32 mod_usage; @@ -175,7 +176,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 +194,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 +205,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 +215,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 +286,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; } } @@ -498,24 +499,24 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) if (!BANK_USED(bank)) pm_runtime_get_sync(bank->dev); - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); retval = omap_set_gpio_triggering(bank, offset, type); if (retval) { - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); goto error; } omap_gpio_init_irq(bank, offset); if (!omap_gpio_is_input(bank, offset)) { - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); retval = -EINVAL; goto error; } - spin_unlock_irqrestore(&bank->lock, flags); + 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; @@ -636,14 +637,14 @@ static int omap_set_gpio_wakeup(struct gpio_bank *bank, unsigned offset, return -EINVAL; } - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); if (enable) bank->context.wake_en |= gpio_bit; else bank->context.wake_en &= ~gpio_bit; writel_relaxed(bank->context.wake_en, bank->base + bank->regs->wkup_en); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); return 0; } @@ -669,10 +670,10 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) if (!BANK_USED(bank)) pm_runtime_get_sync(bank->dev); - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); omap_enable_gpio_module(bank, offset); bank->mod_usage |= BIT(offset); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); return 0; } @@ -682,14 +683,14 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip); unsigned long flags; - spin_lock_irqsave(&bank->lock, flags); + 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); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); /* * If this is the last gpio to be freed in the bank, @@ -716,7 +717,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) 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_chip *chip = irq_desc_get_handler_data(desc); + unsigned long lock_flags; chained_irq_enter(irqchip, desc); @@ -731,6 +733,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) 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; @@ -744,6 +748,8 @@ 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); + raw_spin_unlock_irqrestore(&bank->lock, lock_flags); + /* if there is only edge sensitive GPIO pin interrupts configured, we could unmask GPIO bank interrupt immediately */ if (!level_mask && !unmasked) { @@ -758,6 +764,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 @@ -768,6 +775,8 @@ 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); + generic_handle_irq(irq_find_mapping(bank->chip.irqdomain, bit)); } @@ -791,7 +800,7 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d) if (!BANK_USED(bank)) pm_runtime_get_sync(bank->dev); - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); if (!LINE_USED(bank->mod_usage, offset)) omap_set_gpio_direction(bank, offset, 1); @@ -800,12 +809,12 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d) omap_enable_gpio_module(bank, offset); bank->irq_usage |= BIT(offset); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); omap_gpio_unmask_irq(d); return 0; err: - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); if (!BANK_USED(bank)) pm_runtime_put(bank->dev); return -EINVAL; @@ -817,7 +826,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d) unsigned long flags; unsigned offset = d->hwirq; - spin_lock_irqsave(&bank->lock, flags); + 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); @@ -825,7 +834,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d) if (!LINE_USED(bank->mod_usage, offset)) omap_clear_gpio_debounce(bank, offset); omap_disable_gpio_module(bank, offset); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); /* * If this is the last IRQ to be freed in the bank, @@ -849,10 +858,10 @@ static void omap_gpio_mask_irq(struct irq_data *d) unsigned offset = d->hwirq; unsigned long flags; - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); omap_set_gpio_irqenable(bank, offset, 0); omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); } static void omap_gpio_unmask_irq(struct irq_data *d) @@ -862,7 +871,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d) u32 trigger = irqd_get_trigger_type(d); unsigned long flags; - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); if (trigger) omap_set_gpio_triggering(bank, offset, trigger); @@ -874,7 +883,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d) } omap_set_gpio_irqenable(bank, offset, 1); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); } /*---------------------------------------------------------------------*/ @@ -887,9 +896,9 @@ static int omap_mpuio_suspend_noirq(struct device *dev) OMAP_MPUIO_GPIO_MASKIT / bank->stride; unsigned long flags; - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); writel_relaxed(0xffff & ~bank->context.wake_en, mask_reg); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); return 0; } @@ -902,9 +911,9 @@ static int omap_mpuio_resume_noirq(struct device *dev) OMAP_MPUIO_GPIO_MASKIT / bank->stride; unsigned long flags; - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); writel_relaxed(bank->context.wake_en, mask_reg); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); return 0; } @@ -950,9 +959,9 @@ static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset) bank = container_of(chip, struct gpio_bank, chip); reg = bank->base + bank->regs->direction; - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); dir = !!(readl_relaxed(reg) & BIT(offset)); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); return dir; } @@ -962,9 +971,9 @@ static int omap_gpio_input(struct gpio_chip *chip, unsigned offset) unsigned long flags; bank = container_of(chip, struct gpio_bank, chip); - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); omap_set_gpio_direction(bank, offset, 1); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); return 0; } @@ -986,10 +995,10 @@ static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value) unsigned long flags; bank = container_of(chip, struct gpio_bank, chip); - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); bank->set_dataout(bank, offset, value); omap_set_gpio_direction(bank, offset, 0); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); return 0; } @@ -1001,9 +1010,9 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset, bank = container_of(chip, struct gpio_bank, chip); - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); omap2_set_gpio_debounce(bank, offset, debounce); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); return 0; } @@ -1014,9 +1023,9 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value) unsigned long flags; bank = container_of(chip, struct gpio_bank, chip); - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); bank->set_dataout(bank, offset, value); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); } /*---------------------------------------------------------------------*/ @@ -1061,10 +1070,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) @@ -1178,13 +1183,16 @@ static int omap_gpio_probe(struct platform_device *pdev) irqc->irq_set_wake = omap_gpio_wake_enable, 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; @@ -1213,16 +1221,26 @@ static int omap_gpio_probe(struct platform_device *pdev) else bank->set_dataout = omap_set_gpio_dataout_mask; - spin_lock_init(&bank->lock); + raw_spin_lock_init(&bank->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); @@ -1254,6 +1272,8 @@ static int omap_gpio_remove(struct platform_device *pdev) list_del(&bank->node); gpiochip_remove(&bank->chip); pm_runtime_disable(bank->dev); + if (bank->dbck_flag) + clk_unprepare(bank->dbck); return 0; } @@ -1271,7 +1291,7 @@ static int omap_gpio_runtime_suspend(struct device *dev) unsigned long flags; u32 wake_low, wake_hi; - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); /* * Only edges can generate a wakeup event to the PRCM. @@ -1324,7 +1344,7 @@ update_gpio_context_count: bank->get_context_loss_count(bank->dev); omap_gpio_dbck_disable(bank); - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); return 0; } @@ -1339,7 +1359,7 @@ static int omap_gpio_runtime_resume(struct device *dev) unsigned long flags; int c; - spin_lock_irqsave(&bank->lock, flags); + raw_spin_lock_irqsave(&bank->lock, flags); /* * On the first resume during the probe, the context has not @@ -1375,14 +1395,14 @@ static int omap_gpio_runtime_resume(struct device *dev) if (c != bank->context_loss_count) { omap_gpio_restore_context(bank); } else { - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); return 0; } } } if (!bank->workaround_enabled) { - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); return 0; } @@ -1437,7 +1457,7 @@ static int omap_gpio_runtime_resume(struct device *dev) } bank->workaround_enabled = false; - spin_unlock_irqrestore(&bank->lock, flags); + raw_spin_unlock_irqrestore(&bank->lock, flags); return 0; } diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 404f3c61ef9b..1d4d9bc8b69d 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -88,7 +88,6 @@ struct pcf857x { struct gpio_chip chip; struct i2c_client *client; struct mutex lock; /* protect 'out' */ - spinlock_t slock; /* protect irq demux */ unsigned out; /* software latch */ unsigned status; /* current status */ unsigned int irq_parent; @@ -185,23 +184,21 @@ static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value) static irqreturn_t pcf857x_irq(int irq, void *data) { struct pcf857x *gpio = data; - unsigned long change, i, status, flags; + unsigned long change, i, status; status = gpio->read(gpio->client); - spin_lock_irqsave(&gpio->slock, flags); - /* * call the interrupt handler iff gpio is used as * interrupt source, just to avoid bad irqs */ - + mutex_lock(&gpio->lock); change = (gpio->status ^ status) & gpio->irq_enabled; - for_each_set_bit(i, &change, gpio->chip.ngpio) - handle_nested_irq(irq_find_mapping(gpio->chip.irqdomain, i)); gpio->status = status; + mutex_unlock(&gpio->lock); - spin_unlock_irqrestore(&gpio->slock, flags); + for_each_set_bit(i, &change, gpio->chip.ngpio) + handle_nested_irq(irq_find_mapping(gpio->chip.irqdomain, i)); return IRQ_HANDLED; } @@ -293,7 +290,6 @@ static int pcf857x_probe(struct i2c_client *client, return -ENOMEM; mutex_init(&gpio->lock); - spin_lock_init(&gpio->slock); gpio->chip.base = pdata ? pdata->gpio_base : -1; gpio->chip.can_sleep = true; diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 2d9a950ca2d4..34ed176df15a 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -281,9 +281,9 @@ static int pch_irq_type(struct irq_data *d, unsigned int type) /* And the handler */ 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); unlock: spin_unlock_irqrestore(&chip->spinlock, flags); diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index cdbbcf0faf9d..55a11de3d5b7 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -524,7 +524,7 @@ static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq, { irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, handle_edge_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_set_noprobe(irq); return 0; } @@ -643,20 +643,20 @@ static int pxa_gpio_probe(struct platform_device *pdev) irq = gpio_to_irq(0); irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, handle_edge_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } if (irq1 > 0) { irq = gpio_to_irq(1); irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, handle_edge_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } for (irq = gpio_to_irq(gpio_offset); irq <= gpio_to_irq(pxa_last_gpio); irq++) { irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, handle_edge_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } } diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 1e14a6c74ed1..2a8122444614 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -251,17 +251,32 @@ static void gpio_rcar_config_general_input_output_mode(struct gpio_chip *chip, static int gpio_rcar_request(struct gpio_chip *chip, unsigned offset) { - return pinctrl_request_gpio(chip->base + offset); + struct gpio_rcar_priv *p = gpio_to_priv(chip); + int error; + + error = pm_runtime_get_sync(&p->pdev->dev); + if (error < 0) + return error; + + error = pinctrl_request_gpio(chip->base + offset); + if (error) + pm_runtime_put(&p->pdev->dev); + + return error; } static void gpio_rcar_free(struct gpio_chip *chip, unsigned offset) { + struct gpio_rcar_priv *p = gpio_to_priv(chip); + pinctrl_free_gpio(chip->base + offset); /* Set the GPIO as an input to ensure that the next GPIO request won't * drive the GPIO pin as an output. */ gpio_rcar_config_general_input_output_mode(chip, offset, false); + + pm_runtime_put(&p->pdev->dev); } static int gpio_rcar_direction_input(struct gpio_chip *chip, unsigned offset) @@ -327,6 +342,10 @@ static const struct of_device_id gpio_rcar_of_table[] = { .compatible = "renesas,gpio-r8a7794", .data = &gpio_rcar_info_gen2, }, { + .compatible = "renesas,gpio-r8a7795", + /* Gen3 GPIO is identical to Gen2. */ + .data = &gpio_rcar_info_gen2, + }, { .compatible = "renesas,gpio-rcar", .data = &gpio_rcar_info_gen1, }, { @@ -405,7 +424,6 @@ static int gpio_rcar_probe(struct platform_device *pdev) } pm_runtime_enable(dev); - pm_runtime_get_sync(dev); io = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); @@ -487,7 +505,6 @@ static int gpio_rcar_probe(struct platform_device *pdev) err1: gpiochip_remove(gpio_chip); err0: - pm_runtime_put(dev); pm_runtime_disable(dev); return ret; } @@ -498,7 +515,6 @@ static int gpio_rcar_remove(struct platform_device *pdev) gpiochip_remove(&p->gpio_chip); - pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); return 0; } diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c index 3fa22dade243..67bd2f5d89e8 100644 --- a/drivers/gpio/gpio-sa1100.c +++ b/drivers/gpio/gpio-sa1100.c @@ -155,7 +155,7 @@ static int sa1100_gpio_irqdomain_map(struct irq_domain *d, { irq_set_chip_and_handler(irq, &sa1100_gpio_irq_chip, handle_edge_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_set_noprobe(irq); return 0; } @@ -173,9 +173,9 @@ static struct irq_domain *sa1100_gpio_irqdomain; * and call the handler. */ static void -sa1100_gpio_handler(unsigned int irq, struct irq_desc *desc) +sa1100_gpio_handler(unsigned int __irq, struct irq_desc *desc) { - unsigned int mask; + unsigned int irq, mask; mask = GEDR; do { diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index 18579ac65b2b..55e47828ddfc 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -346,7 +346,7 @@ static void gsta_alloc_irq_chip(struct gsta_gpio *chip) i = chip->irq_base + j; irq_set_chip_and_handler(i, &ct->chip, ct->handler); irq_set_chip_data(i, gc); - irq_modify_status(i, IRQ_NOREQUEST | IRQ_NOPROBE, 0); + irq_clear_status_flags(i, IRQ_NOREQUEST | IRQ_NOPROBE); } gc->irq_cnt = i - gc->irq_base; } diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 31b244cffabb..d1d585ddb9ab 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -102,7 +102,7 @@ static struct gpio_chip template_chip = { static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip); + struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(gc); int offset = d->hwirq; int regoffset = offset / 8; int mask = 1 << (offset % 8); @@ -130,7 +130,7 @@ static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type) static void tc3589x_gpio_irq_lock(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip); + struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(gc); mutex_lock(&tc3589x_gpio->irq_lock); } @@ -138,7 +138,7 @@ static void tc3589x_gpio_irq_lock(struct irq_data *d) static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip); + struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(gc); struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; static const u8 regmap[] = { [REG_IBE] = TC3589x_GPIOIBE0, @@ -167,7 +167,7 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d) static void tc3589x_gpio_irq_mask(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip); + struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(gc); int offset = d->hwirq; int regoffset = offset / 8; int mask = 1 << (offset % 8); @@ -178,7 +178,7 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d) static void tc3589x_gpio_irq_unmask(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip); + struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(gc); int offset = d->hwirq; int regoffset = offset / 8; int mask = 1 << (offset % 8); diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 9b25c90f725c..9b14aafb576d 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -252,9 +252,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) tegra_gpio_enable(gpio); 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; } @@ -268,16 +268,14 @@ static void tegra_gpio_irq_shutdown(struct irq_data *d) static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) { - struct tegra_gpio_bank *bank; int port; int pin; int unmasked = 0; struct irq_chip *chip = irq_desc_get_chip(desc); + struct tegra_gpio_bank *bank = irq_desc_get_handler_data(desc); chained_irq_enter(chip, desc); - bank = irq_get_handler_data(irq); - for (port = 0; port < 4; port++) { int gpio = tegra_gpio_compose(bank->bank, port, 0); unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) & @@ -509,7 +507,6 @@ static int tegra_gpio_probe(struct platform_device *pdev) irq_set_chip_data(irq, bank); irq_set_chip_and_handler(irq, &tegra_gpio_irq_chip, handle_simple_irq); - set_irq_flags(irq, IRQF_VALID); } for (i = 0; i < tegra_gpio_bank_count; i++) { diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index e8f97e03c9bb..5a492054589f 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -194,11 +194,12 @@ out: static void timbgpio_irq(unsigned int irq, struct irq_desc *desc) { - struct timbgpio *tgpio = irq_get_handler_data(irq); + struct timbgpio *tgpio = irq_desc_get_handler_data(desc); + struct irq_data *data = irq_desc_get_irq_data(desc); unsigned long ipr; int offset; - desc->irq_data.chip->irq_ack(irq_get_irq_data(irq)); + data->chip->irq_ack(data); ipr = ioread32(tgpio->membase + TGPIO_IPR); iowrite32(ipr, tgpio->membase + TGPIO_ICR); @@ -294,13 +295,10 @@ static int timbgpio_probe(struct platform_device *pdev) irq_set_chip_and_handler(tgpio->irq_base + i, &timbgpio_irqchip, handle_simple_irq); irq_set_chip_data(tgpio->irq_base + i, tgpio); -#ifdef CONFIG_ARM - set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE); -#endif + irq_clear_status_flags(tgpio->irq_base + i, IRQ_NOREQUEST | IRQ_NOPROBE); } - irq_set_handler_data(irq, tgpio); - irq_set_chained_handler(irq, timbgpio_irq); + irq_set_chained_handler_and_data(irq, timbgpio_irq, tgpio); return 0; } diff --git a/drivers/gpio/gpio-tz1090.c b/drivers/gpio/gpio-tz1090.c index 445660adc898..bbac92ae4c32 100644 --- a/drivers/gpio/gpio-tz1090.c +++ b/drivers/gpio/gpio-tz1090.c @@ -510,8 +510,8 @@ static int tz1090_gpio_bank_probe(struct tz1090_gpio_bank_info *info) gc->chip_types[1].chip.flags = IRQCHIP_MASK_ON_SUSPEND; /* Setup chained handler for this GPIO bank */ - irq_set_handler_data(bank->irq, bank); - irq_set_chained_handler(bank->irq, tz1090_gpio_irq_handler); + irq_set_chained_handler_and_data(bank->irq, tz1090_gpio_irq_handler, + bank); return 0; } diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 7bd9f209ffa8..3d5714d4f405 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -60,6 +60,8 @@ struct vf610_gpio_port { #define PORT_INT_EITHER_EDGE 0xb #define PORT_INT_LOGIC_ONE 0xc +static struct irq_chip vf610_gpio_irq_chip; + static const struct of_device_id vf610_gpio_dt_ids[] = { { .compatible = "fsl,vf610-gpio" }, { /* sentinel */ } @@ -120,7 +122,7 @@ static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, static void vf610_gpio_irq_handler(u32 irq, struct irq_desc *desc) { - struct vf610_gpio_port *port = irq_get_handler_data(irq); + struct vf610_gpio_port *port = irq_desc_get_handler_data(desc); struct irq_chip *chip = irq_desc_get_chip(desc); int pin; unsigned long irq_isfr; @@ -173,6 +175,11 @@ static int vf610_gpio_irq_set_type(struct irq_data *d, u32 type) port->irqc[d->hwirq] = irqc; + if (type & IRQ_TYPE_LEVEL_MASK) + __irq_set_handler_locked(d->irq, handle_level_irq); + else + __irq_set_handler_locked(d->irq, handle_edge_irq); + return 0; } @@ -263,7 +270,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) vf610_gpio_writel(~0, port->base + PORT_ISFR); ret = gpiochip_irqchip_add(gc, &vf610_gpio_irq_chip, 0, - handle_simple_irq, IRQ_TYPE_NONE); + handle_edge_irq, IRQ_TYPE_NONE); if (ret) { dev_err(dev, "failed to add irqchip\n"); gpiochip_remove(gc); diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c index 9bdab7203d65..e02499a15e72 100644 --- a/drivers/gpio/gpio-xlp.c +++ b/drivers/gpio/gpio-xlp.c @@ -387,7 +387,7 @@ static int xlp_gpio_probe(struct platform_device *pdev) irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0); if (irq_base < 0) { dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n"); - return err; + return -ENODEV; } err = gpiochip_add(gc); diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c new file mode 100644 index 000000000000..12ee1969298c --- /dev/null +++ b/drivers/gpio/gpio-zx.c @@ -0,0 +1,324 @@ +/* + * Copyright (C) 2015 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/gpio/driver.h> +#include <linux/irqchip/chained_irq.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/pinctrl/consumer.h> +#include <linux/platform_device.h> +#include <linux/pm.h> +#include <linux/slab.h> +#include <linux/spinlock.h> + +#define ZX_GPIO_DIR 0x00 +#define ZX_GPIO_IVE 0x04 +#define ZX_GPIO_IV 0x08 +#define ZX_GPIO_IEP 0x0C +#define ZX_GPIO_IEN 0x10 +#define ZX_GPIO_DI 0x14 +#define ZX_GPIO_DO1 0x18 +#define ZX_GPIO_DO0 0x1C +#define ZX_GPIO_DO 0x20 + +#define ZX_GPIO_IM 0x28 +#define ZX_GPIO_IE 0x2C + +#define ZX_GPIO_MIS 0x30 +#define ZX_GPIO_IC 0x34 + +#define ZX_GPIO_NR 16 + +struct zx_gpio { + spinlock_t lock; + + void __iomem *base; + struct gpio_chip gc; + bool uses_pinctrl; +}; + +static inline struct zx_gpio *to_zx(struct gpio_chip *gc) +{ + return container_of(gc, struct zx_gpio, gc); +} + +static int zx_gpio_request(struct gpio_chip *gc, unsigned offset) +{ + struct zx_gpio *chip = to_zx(gc); + int gpio = gc->base + offset; + + if (chip->uses_pinctrl) + return pinctrl_request_gpio(gpio); + return 0; +} + +static void zx_gpio_free(struct gpio_chip *gc, unsigned offset) +{ + struct zx_gpio *chip = to_zx(gc); + int gpio = gc->base + offset; + + if (chip->uses_pinctrl) + pinctrl_free_gpio(gpio); +} + +static int zx_direction_input(struct gpio_chip *gc, unsigned offset) +{ + struct zx_gpio *chip = to_zx(gc); + unsigned long flags; + u16 gpiodir; + + if (offset >= gc->ngpio) + return -EINVAL; + + spin_lock_irqsave(&chip->lock, flags); + gpiodir = readw_relaxed(chip->base + ZX_GPIO_DIR); + gpiodir &= ~BIT(offset); + writew_relaxed(gpiodir, chip->base + ZX_GPIO_DIR); + spin_unlock_irqrestore(&chip->lock, flags); + + return 0; +} + +static int zx_direction_output(struct gpio_chip *gc, unsigned offset, + int value) +{ + struct zx_gpio *chip = to_zx(gc); + unsigned long flags; + u16 gpiodir; + + if (offset >= gc->ngpio) + return -EINVAL; + + spin_lock_irqsave(&chip->lock, flags); + gpiodir = readw_relaxed(chip->base + ZX_GPIO_DIR); + gpiodir |= BIT(offset); + writew_relaxed(gpiodir, chip->base + ZX_GPIO_DIR); + + if (value) + writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO1); + else + writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO0); + spin_unlock_irqrestore(&chip->lock, flags); + + return 0; +} + +static int zx_get_value(struct gpio_chip *gc, unsigned offset) +{ + struct zx_gpio *chip = to_zx(gc); + + return !!(readw_relaxed(chip->base + ZX_GPIO_DI) & BIT(offset)); +} + +static void zx_set_value(struct gpio_chip *gc, unsigned offset, int value) +{ + struct zx_gpio *chip = to_zx(gc); + + if (value) + writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO1); + else + writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO0); +} + +static int zx_irq_type(struct irq_data *d, unsigned trigger) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct zx_gpio *chip = to_zx(gc); + int offset = irqd_to_hwirq(d); + unsigned long flags; + u16 gpiois, gpioi_epos, gpioi_eneg, gpioiev; + u16 bit = BIT(offset); + + if (offset < 0 || offset >= ZX_GPIO_NR) + return -EINVAL; + + spin_lock_irqsave(&chip->lock, flags); + + gpioiev = readw_relaxed(chip->base + ZX_GPIO_IV); + gpiois = readw_relaxed(chip->base + ZX_GPIO_IVE); + gpioi_epos = readw_relaxed(chip->base + ZX_GPIO_IEP); + gpioi_eneg = readw_relaxed(chip->base + ZX_GPIO_IEN); + + if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { + gpiois |= bit; + if (trigger & IRQ_TYPE_LEVEL_HIGH) + gpioiev |= bit; + else + gpioiev &= ~bit; + } else + gpiois &= ~bit; + + if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { + gpioi_epos |= bit; + gpioi_eneg |= bit; + } else { + if (trigger & IRQ_TYPE_EDGE_RISING) { + gpioi_epos |= bit; + gpioi_eneg &= ~bit; + } else if (trigger & IRQ_TYPE_EDGE_FALLING) { + gpioi_eneg |= bit; + gpioi_epos &= ~bit; + } + } + + writew_relaxed(gpiois, chip->base + ZX_GPIO_IVE); + writew_relaxed(gpioi_epos, chip->base + ZX_GPIO_IEP); + writew_relaxed(gpioi_eneg, chip->base + ZX_GPIO_IEN); + writew_relaxed(gpioiev, chip->base + ZX_GPIO_IV); + spin_unlock_irqrestore(&chip->lock, flags); + + return 0; +} + +static void zx_irq_handler(unsigned irq, struct irq_desc *desc) +{ + unsigned long pending; + int offset; + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct zx_gpio *chip = to_zx(gc); + struct irq_chip *irqchip = irq_desc_get_chip(desc); + + chained_irq_enter(irqchip, desc); + + pending = readw_relaxed(chip->base + ZX_GPIO_MIS); + writew_relaxed(pending, chip->base + ZX_GPIO_IC); + if (pending) { + for_each_set_bit(offset, &pending, ZX_GPIO_NR) + generic_handle_irq(irq_find_mapping(gc->irqdomain, + offset)); + } + + chained_irq_exit(irqchip, desc); +} + +static void zx_irq_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct zx_gpio *chip = to_zx(gc); + u16 mask = BIT(irqd_to_hwirq(d) % ZX_GPIO_NR); + u16 gpioie; + + spin_lock(&chip->lock); + gpioie = readw_relaxed(chip->base + ZX_GPIO_IM) | mask; + writew_relaxed(gpioie, chip->base + ZX_GPIO_IM); + gpioie = readw_relaxed(chip->base + ZX_GPIO_IE) & ~mask; + writew_relaxed(gpioie, chip->base + ZX_GPIO_IE); + spin_unlock(&chip->lock); +} + +static void zx_irq_unmask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct zx_gpio *chip = to_zx(gc); + u16 mask = BIT(irqd_to_hwirq(d) % ZX_GPIO_NR); + u16 gpioie; + + spin_lock(&chip->lock); + gpioie = readw_relaxed(chip->base + ZX_GPIO_IM) & ~mask; + writew_relaxed(gpioie, chip->base + ZX_GPIO_IM); + gpioie = readw_relaxed(chip->base + ZX_GPIO_IE) | mask; + writew_relaxed(gpioie, chip->base + ZX_GPIO_IE); + spin_unlock(&chip->lock); +} + +static struct irq_chip zx_irqchip = { + .name = "zx-gpio", + .irq_mask = zx_irq_mask, + .irq_unmask = zx_irq_unmask, + .irq_set_type = zx_irq_type, +}; + +static int zx_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct zx_gpio *chip; + struct resource *res; + int irq, id, ret; + + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + chip->base = devm_ioremap_resource(dev, res); + if (IS_ERR(chip->base)) + return PTR_ERR(chip->base); + + spin_lock_init(&chip->lock); + if (of_property_read_bool(dev->of_node, "gpio-ranges")) + chip->uses_pinctrl = true; + + id = of_alias_get_id(dev->of_node, "gpio"); + chip->gc.request = zx_gpio_request; + chip->gc.free = zx_gpio_free; + chip->gc.direction_input = zx_direction_input; + chip->gc.direction_output = zx_direction_output; + chip->gc.get = zx_get_value; + chip->gc.set = zx_set_value; + chip->gc.base = ZX_GPIO_NR * id; + chip->gc.ngpio = ZX_GPIO_NR; + chip->gc.label = dev_name(dev); + chip->gc.dev = dev; + chip->gc.owner = THIS_MODULE; + + ret = gpiochip_add(&chip->gc); + if (ret) + return ret; + + /* + * irq_chip support + */ + writew_relaxed(0xffff, chip->base + ZX_GPIO_IM); + writew_relaxed(0, chip->base + ZX_GPIO_IE); + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(dev, "invalid IRQ\n"); + gpiochip_remove(&chip->gc); + return -ENODEV; + } + + ret = gpiochip_irqchip_add(&chip->gc, &zx_irqchip, + 0, handle_simple_irq, + IRQ_TYPE_NONE); + if (ret) { + dev_err(dev, "could not add irqchip\n"); + gpiochip_remove(&chip->gc); + return ret; + } + gpiochip_set_chained_irqchip(&chip->gc, &zx_irqchip, + irq, zx_irq_handler); + + platform_set_drvdata(pdev, chip); + dev_info(dev, "ZX GPIO chip registered\n"); + + return 0; +} + +static const struct of_device_id zx_gpio_match[] = { + { + .compatible = "zte,zx296702-gpio", + }, + { }, +}; +MODULE_DEVICE_TABLE(of, zx_gpio_match); + +static struct platform_driver zx_gpio_driver = { + .probe = zx_gpio_probe, + .driver = { + .name = "zx_gpio", + .of_match_table = of_match_ptr(zx_gpio_match), + }, +}; + +module_platform_driver(zx_gpio_driver) + +MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>"); +MODULE_DESCRIPTION("ZTE ZX296702 GPIO driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index a78882389836..27348e7cb705 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -441,10 +441,10 @@ static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type) gpio->base_addr + ZYNQ_GPIO_INTANY_OFFSET(bank_num)); if (type & IRQ_TYPE_LEVEL_MASK) { - __irq_set_chip_handler_name_locked(irq_data->irq, + irq_set_chip_handler_name_locked(irq_data, &zynq_gpio_level_irqchip, handle_fasteoi_irq, NULL); } else { - __irq_set_chip_handler_name_locked(irq_data->irq, + irq_set_chip_handler_name_locked(irq_data, &zynq_gpio_edge_irqchip, handle_level_irq, NULL); } @@ -518,7 +518,7 @@ static void zynq_gpio_irqhandler(unsigned int irq, struct irq_desc *desc) { u32 int_sts, int_enb; unsigned int bank_num; - struct zynq_gpio *gpio = irq_get_handler_data(irq); + struct zynq_gpio *gpio = irq_desc_get_handler_data(desc); struct irq_chip *irqchip = irq_desc_get_chip(desc); chained_irq_enter(irqchip, desc); @@ -782,6 +782,12 @@ static int __init zynq_gpio_init(void) } postcore_initcall(zynq_gpio_init); +static void __exit zynq_gpio_exit(void) +{ + platform_driver_unregister(&zynq_gpio_driver); +} +module_exit(zynq_gpio_exit); + MODULE_AUTHOR("Xilinx Inc."); MODULE_DESCRIPTION("Zynq GPIO driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 9a0ec48a4737..fa6e3c8823d6 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -136,7 +136,6 @@ static struct gpio_desc *of_get_gpio_hog(struct device_node *np, { struct device_node *chip_np; enum of_gpio_flags xlate_flags; - struct gpio_desc *desc; struct gg_data gg_data = { .flags = &xlate_flags, }; @@ -193,9 +192,7 @@ static struct gpio_desc *of_get_gpio_hog(struct device_node *np, if (name && of_property_read_string(np, "line-name", name)) *name = np->name; - desc = gg_data.out_gpio; - - return desc; + return gg_data.out_gpio; } /** @@ -338,7 +335,7 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc) EXPORT_SYMBOL(of_mm_gpiochip_remove); #ifdef CONFIG_PINCTRL -static void of_gpiochip_add_pin_range(struct gpio_chip *chip) +static int of_gpiochip_add_pin_range(struct gpio_chip *chip) { struct device_node *np = chip->of_node; struct of_phandle_args pinspec; @@ -349,7 +346,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) struct property *group_names; if (!np) - return; + return 0; group_names = of_find_property(np, group_names_propname, NULL); @@ -361,11 +358,11 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) pctldev = of_pinctrl_get(pinspec.np); if (!pctldev) - break; + return -EPROBE_DEFER; if (pinspec.args[2]) { if (group_names) { - ret = of_property_read_string_index(np, + of_property_read_string_index(np, group_names_propname, index, &name); if (strlen(name)) { @@ -381,7 +378,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) pinspec.args[1], pinspec.args[2]); if (ret) - break; + return ret; } else { /* npins == 0: special range */ if (pinspec.args[1]) { @@ -411,32 +408,41 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) ret = gpiochip_add_pingroup_range(chip, pctldev, pinspec.args[0], name); if (ret) - break; + return ret; } } + + return 0; } #else -static void of_gpiochip_add_pin_range(struct gpio_chip *chip) {} +static int of_gpiochip_add_pin_range(struct gpio_chip *chip) { return 0; } #endif -void of_gpiochip_add(struct gpio_chip *chip) +int of_gpiochip_add(struct gpio_chip *chip) { + int status; + if ((!chip->of_node) && (chip->dev)) chip->of_node = chip->dev->of_node; if (!chip->of_node) - return; + return 0; if (!chip->of_xlate) { chip->of_gpio_n_cells = 2; chip->of_xlate = of_gpio_simple_xlate; } - of_gpiochip_add_pin_range(chip); + status = of_gpiochip_add_pin_range(chip); + if (status) + return status; + of_node_get(chip->of_node); of_gpiochip_scan_hogs(chip); + + return 0; } void of_gpiochip_remove(struct gpio_chip *chip) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index bf4bd1d120c3..b562dd36c4af 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -190,7 +190,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_direction); */ static int gpiochip_add_to_list(struct gpio_chip *chip) { - struct list_head *pos = &gpio_chips; + struct list_head *pos; struct gpio_chip *_chip; int err = 0; @@ -287,7 +287,13 @@ int gpiochip_add(struct gpio_chip *chip) INIT_LIST_HEAD(&chip->pin_ranges); #endif - of_gpiochip_add(chip); + if (!chip->owner && chip->dev && chip->dev->driver) + chip->owner = chip->dev->driver->owner; + + status = of_gpiochip_add(chip); + if (status) + goto err_remove_chip; + acpi_gpiochip_add(chip); status = gpiochip_sysfs_register(chip); @@ -443,8 +449,8 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, * The parent irqchip is already using the chip_data for this * irqchip, so our callbacks simply use the handler_data. */ - irq_set_handler_data(parent_irq, gpiochip); - irq_set_chained_handler(parent_irq, parent_handler); + irq_set_chained_handler_and_data(parent_irq, parent_handler, + gpiochip); gpiochip->irq_parent = parent_irq; } @@ -456,12 +462,6 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, } EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip); -/* - * This lock class tells lockdep that GPIO irqs are in a different - * category than their parents, so it won't report false recursion. - */ -static struct lock_class_key gpiochip_irq_lock_class; - /** * gpiochip_irq_map() - maps an IRQ into a GPIO irqchip * @d: the irqdomain used by this irqchip @@ -478,16 +478,17 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, struct gpio_chip *chip = d->host_data; irq_set_chip_data(irq, chip); - irq_set_lockdep_class(irq, &gpiochip_irq_lock_class); + /* + * This lock class tells lockdep that GPIO irqs are in a different + * category than their parents, so it won't report false recursion. + */ + irq_set_lockdep_class(irq, chip->lock_key); irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler); /* Chips that can sleep need nested thread handlers */ if (chip->can_sleep && !chip->irq_not_threaded) irq_set_nested_thread(irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else irq_set_noprobe(irq); -#endif + /* * No set-up of the hardware will happen if IRQ_TYPE_NONE * is passed as default type. @@ -502,9 +503,6 @@ static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq) { struct gpio_chip *chip = d->host_data; -#ifdef CONFIG_ARM - set_irq_flags(irq, 0); -#endif if (chip->can_sleep) irq_set_nested_thread(irq, 0); irq_set_chip_and_handler(irq, NULL, NULL); @@ -522,10 +520,14 @@ static int gpiochip_irq_reqres(struct irq_data *d) { struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + if (!try_module_get(chip->owner)) + return -ENODEV; + if (gpiochip_lock_as_irq(chip, d->hwirq)) { chip_err(chip, "unable to lock HW IRQ %lu for IRQ\n", d->hwirq); + module_put(chip->owner); return -EINVAL; } return 0; @@ -536,6 +538,7 @@ static void gpiochip_irq_relres(struct irq_data *d) struct gpio_chip *chip = irq_data_get_irq_chip_data(d); gpiochip_unlock_as_irq(chip, d->hwirq); + module_put(chip->owner); } static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) @@ -584,6 +587,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) * @handler: the irq handler to use (often a predefined irq core function) * @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE * to have the core avoid setting up any default type in the hardware. + * @lock_key: lockdep class * * This function closely associates a certain irqchip with a certain * gpiochip, providing an irq domain to translate the local IRQs to @@ -599,11 +603,12 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) * the pins on the gpiochip can generate a unique IRQ. Everything else * need to be open coded. */ -int gpiochip_irqchip_add(struct gpio_chip *gpiochip, - struct irq_chip *irqchip, - unsigned int first_irq, - irq_flow_handler_t handler, - unsigned int type) +int _gpiochip_irqchip_add(struct gpio_chip *gpiochip, + struct irq_chip *irqchip, + unsigned int first_irq, + irq_flow_handler_t handler, + unsigned int type, + struct lock_class_key *lock_key) { struct device_node *of_node; unsigned int offset; @@ -629,6 +634,7 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip, gpiochip->irq_handler = handler; gpiochip->irq_default_type = type; gpiochip->to_irq = gpiochip_to_irq; + gpiochip->lock_key = lock_key; gpiochip->irqdomain = irq_domain_add_simple(of_node, gpiochip->ngpio, first_irq, &gpiochip_domain_ops, gpiochip); @@ -636,8 +642,16 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip, gpiochip->irqchip = NULL; return -EINVAL; } - irqchip->irq_request_resources = gpiochip_irq_reqres; - irqchip->irq_release_resources = gpiochip_irq_relres; + + /* + * It is possible for a driver to override this, but only if the + * alternative functions are both implemented. + */ + if (!irqchip->irq_request_resources && + !irqchip->irq_release_resources) { + irqchip->irq_request_resources = gpiochip_irq_reqres; + irqchip->irq_release_resources = gpiochip_irq_relres; + } /* * Prepare the mapping since the irqchip shall be orthogonal to @@ -658,7 +672,7 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip, return 0; } -EXPORT_SYMBOL_GPL(gpiochip_irqchip_add); +EXPORT_SYMBOL_GPL(_gpiochip_irqchip_add); #else /* CONFIG_GPIOLIB_IRQCHIP */ @@ -671,7 +685,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {} /** * gpiochip_add_pingroup_range() - add a range for GPIO <-> pin mapping * @chip: the gpiochip to add the range for - * @pinctrl: the dev_name() of the pin controller to map to + * @pctldev: the pin controller to map to * @gpio_offset: the start offset in the current gpio_chip number space * @pin_group: name of the pin group inside the pin controller */ @@ -1894,12 +1908,12 @@ EXPORT_SYMBOL_GPL(gpiod_count); * dev, -ENOENT if no GPIO has been assigned to the requested function, or * another IS_ERR() code if an error occurred while trying to acquire the GPIO. */ -struct gpio_desc *__must_check __gpiod_get(struct device *dev, const char *con_id, +struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id, enum gpiod_flags flags) { return gpiod_get_index(dev, con_id, 0, flags); } -EXPORT_SYMBOL_GPL(__gpiod_get); +EXPORT_SYMBOL_GPL(gpiod_get); /** * gpiod_get_optional - obtain an optional GPIO for a given GPIO function @@ -1911,13 +1925,13 @@ EXPORT_SYMBOL_GPL(__gpiod_get); * the requested function it will return NULL. This is convenient for drivers * that need to handle optional GPIOs. */ -struct gpio_desc *__must_check __gpiod_get_optional(struct device *dev, +struct gpio_desc *__must_check gpiod_get_optional(struct device *dev, const char *con_id, enum gpiod_flags flags) { return gpiod_get_index_optional(dev, con_id, 0, flags); } -EXPORT_SYMBOL_GPL(__gpiod_get_optional); +EXPORT_SYMBOL_GPL(gpiod_get_optional); /** @@ -1974,7 +1988,7 @@ static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, * requested function and/or index, or another IS_ERR() code if an error * occurred while trying to acquire the GPIO. */ -struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, +struct gpio_desc *__must_check gpiod_get_index(struct device *dev, const char *con_id, unsigned int idx, enum gpiod_flags flags) @@ -2023,7 +2037,7 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, return desc; } -EXPORT_SYMBOL_GPL(__gpiod_get_index); +EXPORT_SYMBOL_GPL(gpiod_get_index); /** * fwnode_get_named_gpiod - obtain a GPIO from firmware node @@ -2092,7 +2106,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod); * specified index was assigned to the requested function it will return NULL. * This is convenient for drivers that need to handle optional GPIOs. */ -struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev, +struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev, const char *con_id, unsigned int index, enum gpiod_flags flags) @@ -2107,7 +2121,7 @@ struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev, return desc; } -EXPORT_SYMBOL_GPL(__gpiod_get_index_optional); +EXPORT_SYMBOL_GPL(gpiod_get_index_optional); /** * gpiod_hog - Hog the specified GPIO desc given the provided flags diff --git a/drivers/gpu/drm/msm/edp/edp_ctrl.c b/drivers/gpu/drm/msm/edp/edp_ctrl.c index 7991069dd492..81200e9be382 100644 --- a/drivers/gpu/drm/msm/edp/edp_ctrl.c +++ b/drivers/gpu/drm/msm/edp/edp_ctrl.c @@ -373,7 +373,7 @@ static int edp_gpio_config(struct edp_ctrl *ctrl) struct device *dev = &ctrl->pdev->dev; int ret; - ctrl->panel_hpd_gpio = devm_gpiod_get(dev, "panel-hpd"); + ctrl->panel_hpd_gpio = devm_gpiod_get(dev, "panel-hpd", GPIOD_IN); if (IS_ERR(ctrl->panel_hpd_gpio)) { ret = PTR_ERR(ctrl->panel_hpd_gpio); ctrl->panel_hpd_gpio = NULL; @@ -381,13 +381,7 @@ static int edp_gpio_config(struct edp_ctrl *ctrl) return ret; } - ret = gpiod_direction_input(ctrl->panel_hpd_gpio); - if (ret) { - pr_err("%s: Set direction for hpd failed, %d\n", __func__, ret); - return ret; - } - - ctrl->panel_en_gpio = devm_gpiod_get(dev, "panel-en"); + ctrl->panel_en_gpio = devm_gpiod_get(dev, "panel-en", GPIOD_OUT_LOW); if (IS_ERR(ctrl->panel_en_gpio)) { ret = PTR_ERR(ctrl->panel_en_gpio); ctrl->panel_en_gpio = NULL; @@ -395,13 +389,6 @@ static int edp_gpio_config(struct edp_ctrl *ctrl) return ret; } - ret = gpiod_direction_output(ctrl->panel_en_gpio, 0); - if (ret) { - pr_err("%s: Set direction for panel_en failed, %d\n", - __func__, ret); - return ret; - } - DBG("gpio on"); return 0; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c index 7a0315855e90..0af8bed7ce1e 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c @@ -375,25 +375,17 @@ static int panel_probe(struct platform_device *pdev) dev_info(&pdev->dev, "found backlight\n"); } - panel_mod->enable_gpio = devm_gpiod_get(&pdev->dev, "enable"); + panel_mod->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable", + GPIOD_OUT_LOW); if (IS_ERR(panel_mod->enable_gpio)) { ret = PTR_ERR(panel_mod->enable_gpio); - if (ret != -ENOENT) { - dev_err(&pdev->dev, "failed to request enable GPIO\n"); - goto fail_backlight; - } - - /* Optional GPIO is not here, continue silently. */ - panel_mod->enable_gpio = NULL; - } else { - ret = gpiod_direction_output(panel_mod->enable_gpio, 0); - if (ret < 0) { - dev_err(&pdev->dev, "failed to setup GPIO\n"); - goto fail_backlight; - } - dev_info(&pdev->dev, "found enable GPIO\n"); + dev_err(&pdev->dev, "failed to request enable GPIO\n"); + goto fail_backlight; } + if (panel_mod->enable_gpio) + dev_info(&pdev->dev, "found enable GPIO\n"); + mod = &panel_mod->base; pdev->dev.platform_data = mod; diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index f101bb5bddc7..993eb201148e 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c @@ -469,16 +469,12 @@ static int stk3310_gpio_probe(struct i2c_client *client) dev = &client->dev; /* gpio interrupt pin */ - gpio = devm_gpiod_get_index(dev, STK3310_GPIO, 0); + gpio = devm_gpiod_get_index(dev, STK3310_GPIO, 0, GPIOD_IN); if (IS_ERR(gpio)) { dev_err(dev, "acpi gpio get index failed\n"); return PTR_ERR(gpio); } - ret = gpiod_direction_input(gpio); - if (ret) - return ret; - ret = gpiod_to_irq(gpio); dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c index e330205f8194..d8e614ca069f 100644 --- a/drivers/iio/magnetometer/bmc150_magn.c +++ b/drivers/iio/magnetometer/bmc150_magn.c @@ -845,16 +845,12 @@ static int bmc150_magn_gpio_probe(struct i2c_client *client) dev = &client->dev; /* data ready GPIO interrupt pin */ - gpio = devm_gpiod_get_index(dev, BMC150_MAGN_GPIO_INT, 0); + gpio = devm_gpiod_get_index(dev, BMC150_MAGN_GPIO_INT, 0, GPIOD_IN); if (IS_ERR(gpio)) { dev_err(dev, "ACPI GPIO get index failed\n"); return PTR_ERR(gpio); } - ret = gpiod_direction_input(gpio); - if (ret) - return ret; - ret = gpiod_to_irq(gpio); dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c index c70ababce954..5dd39775d6ca 100644 --- a/drivers/media/i2c/adp1653.c +++ b/drivers/media/i2c/adp1653.c @@ -465,7 +465,7 @@ static int adp1653_of_init(struct i2c_client *client, of_node_put(child); - pd->enable_gpio = devm_gpiod_get(&client->dev, "enable"); + pd->enable_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW); if (!pd->enable_gpio) { dev_err(&client->dev, "Error getting GPIO\n"); return -EINVAL; diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index 2f77f1d03638..fac80c691914 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -318,19 +318,15 @@ static int nxp_nci_i2c_acpi_config(struct nxp_nci_i2c_phy *phy) struct i2c_client *client = phy->i2c_dev; struct gpio_desc *gpiod_en, *gpiod_fw, *gpiod_irq; - gpiod_en = devm_gpiod_get_index(&client->dev, NULL, 2); - gpiod_fw = devm_gpiod_get_index(&client->dev, NULL, 1); - gpiod_irq = devm_gpiod_get_index(&client->dev, NULL, 0); + gpiod_en = devm_gpiod_get_index(&client->dev, NULL, 2, GPIOD_OUT_LOW); + gpiod_fw = devm_gpiod_get_index(&client->dev, NULL, 1, GPIOD_OUT_LOW); + gpiod_irq = devm_gpiod_get_index(&client->dev, NULL, 0, GPIOD_IN); if (IS_ERR(gpiod_en) || IS_ERR(gpiod_fw) || IS_ERR(gpiod_irq)) { nfc_err(&client->dev, "No GPIOs\n"); return -EINVAL; } - gpiod_direction_output(gpiod_en, 0); - gpiod_direction_output(gpiod_fw, 0); - gpiod_direction_input(gpiod_irq); - client->irq = gpiod_to_irq(gpiod_irq); if (client->irq < 0) { nfc_err(&client->dev, "No IRQ\n"); diff --git a/drivers/phy/phy-tusb1210.c b/drivers/phy/phy-tusb1210.c index 2535d792d57a..4f6d5e71507d 100644 --- a/drivers/phy/phy-tusb1210.c +++ b/drivers/phy/phy-tusb1210.c @@ -61,32 +61,26 @@ static const struct phy_ops phy_ops = { static int tusb1210_probe(struct ulpi *ulpi) { - struct gpio_desc *gpio; struct tusb1210 *tusb; u8 val, reg; - int ret; tusb = devm_kzalloc(&ulpi->dev, sizeof(*tusb), GFP_KERNEL); if (!tusb) return -ENOMEM; - gpio = devm_gpiod_get(&ulpi->dev, "reset"); - if (!IS_ERR(gpio)) { - ret = gpiod_direction_output(gpio, 0); - if (ret) - return ret; - gpiod_set_value_cansleep(gpio, 1); - tusb->gpio_reset = gpio; - } + tusb->gpio_reset = devm_gpiod_get_optional(&ulpi->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(tusb->gpio_reset)) + return PTR_ERR(tusb->gpio_reset); - gpio = devm_gpiod_get(&ulpi->dev, "cs"); - if (!IS_ERR(gpio)) { - ret = gpiod_direction_output(gpio, 0); - if (ret) - return ret; - gpiod_set_value_cansleep(gpio, 1); - tusb->gpio_cs = gpio; - } + gpiod_set_value_cansleep(tusb->gpio_reset, 1); + + tusb->gpio_cs = devm_gpiod_get_optional(&ulpi->dev, "cs", + GPIOD_OUT_LOW); + if (IS_ERR(tusb->gpio_cs)) + return PTR_ERR(tusb->gpio_cs); + + gpiod_set_value_cansleep(tusb->gpio_cs, 1); /* * VENDOR_SPECIFIC2 register in TUSB1210 can be used for configuring eye |