diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 3 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-etraxfs.c | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-ftgpio010.c | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-omap.c | 24 | ||||
-rw-r--r-- | drivers/gpio/gpio-tegra186.c | 3 | ||||
-rw-r--r-- | drivers/gpio/gpio-uniphier.c | 5 | ||||
-rw-r--r-- | drivers/gpio/gpio-xgene-sb.c | 8 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 13 |
10 files changed, 41 insertions, 20 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 03e34d9ca778..d6a8e851ad13 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -461,7 +461,8 @@ config GPIO_TS4800 config GPIO_THUNDERX tristate "Cavium ThunderX/OCTEON-TX GPIO" depends on ARCH_THUNDER || (64BIT && COMPILE_TEST) - depends on PCI_MSI && IRQ_DOMAIN_HIERARCHY + depends on PCI_MSI + select IRQ_DOMAIN_HIERARCHY select IRQ_FASTEOI_HIERARCHY_HANDLERS help Say yes here to support the on-chip GPIO lines on the ThunderX diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 120e79c0ebb2..4bc24febb889 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # generic gpio support: platform drivers, dedicated expander chips, etc ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG diff --git a/drivers/gpio/gpio-etraxfs.c b/drivers/gpio/gpio-etraxfs.c index 14c6aac26780..94db1bf4bfdb 100644 --- a/drivers/gpio/gpio-etraxfs.c +++ b/drivers/gpio/gpio-etraxfs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 #include <linux/kernel.h> #include <linux/init.h> #include <linux/gpio/driver.h> diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c index b7896bae83ca..7b3394fdc624 100644 --- a/drivers/gpio/gpio-ftgpio010.c +++ b/drivers/gpio/gpio-ftgpio010.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Faraday Technolog FTGPIO010 gpiochip and interrupt routines * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index ce27d6a586bf..e136d666f1e5 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -518,7 +518,13 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) irq_set_handler_locked(d, handle_level_irq); else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) - irq_set_handler_locked(d, handle_edge_irq); + /* + * Edge IRQs are already cleared/acked in irq_handler and + * not need to be masked, as result handle_edge_irq() + * logic is excessed here and may cause lose of interrupts. + * So just use handle_simple_irq. + */ + irq_set_handler_locked(d, handle_simple_irq); return 0; @@ -678,7 +684,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) { void __iomem *isr_reg = NULL; - u32 isr; + u32 enabled, isr, level_mask; unsigned int bit; struct gpio_bank *bank = gpiobank; unsigned long wa_lock_flags; @@ -691,23 +697,21 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) pm_runtime_get_sync(bank->chip.parent); while (1) { - u32 isr_saved, level_mask = 0; - u32 enabled; - raw_spin_lock_irqsave(&bank->lock, lock_flags); enabled = omap_get_gpio_irqbank_mask(bank); - isr_saved = isr = readl_relaxed(isr_reg) & enabled; + isr = readl_relaxed(isr_reg) & enabled; if (bank->level_mask) level_mask = bank->level_mask & enabled; + else + level_mask = 0; /* clear edge sensitive interrupts before handler(s) are called so that we don't miss any interrupt occurred while executing them */ - omap_disable_gpio_irqbank(bank, isr_saved & ~level_mask); - omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask); - omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask); + if (isr & ~level_mask) + omap_clear_gpio_irqbank(bank, isr & ~level_mask); raw_spin_unlock_irqrestore(&bank->lock, lock_flags); @@ -1010,7 +1014,7 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value) /*---------------------------------------------------------------------*/ -static void __init omap_gpio_show_rev(struct gpio_bank *bank) +static void omap_gpio_show_rev(struct gpio_bank *bank) { static bool called; u32 rev; diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index b55b5ca882c7..7f1aa4c21e0d 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -404,8 +404,6 @@ static const struct irq_domain_ops tegra186_gpio_irq_domain_ops = { .xlate = tegra186_gpio_irq_domain_xlate, }; -static struct lock_class_key tegra186_gpio_lock_class; - static int tegra186_gpio_probe(struct platform_device *pdev) { unsigned int i, j, offset; @@ -496,7 +494,6 @@ static int tegra186_gpio_probe(struct platform_device *pdev) irq->chip = &gpio->intc; irq->domain_ops = &tegra186_gpio_irq_domain_ops; irq->handler = handle_simple_irq; - irq->lock_key = &tegra186_gpio_lock_class; irq->default_type = IRQ_TYPE_NONE; irq->parent_handler = tegra186_gpio_irq; irq->parent_handler_data = gpio; diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c index d62cea4ed6b7..016d7427ebfa 100644 --- a/drivers/gpio/gpio-uniphier.c +++ b/drivers/gpio/gpio-uniphier.c @@ -300,13 +300,14 @@ static int uniphier_gpio_irq_domain_alloc(struct irq_domain *domain, return irq_domain_alloc_irqs_parent(domain, virq, 1, &parent_fwspec); } -static void uniphier_gpio_irq_domain_activate(struct irq_domain *domain, - struct irq_data *data) +static int uniphier_gpio_irq_domain_activate(struct irq_domain *domain, + struct irq_data *data, bool early) { struct uniphier_gpio_priv *priv = domain->host_data; struct gpio_chip *chip = &priv->chip; gpiochip_lock_as_irq(chip, data->hwirq + UNIPHIER_GPIO_IRQ_OFFSET); + return 0; } static void uniphier_gpio_irq_domain_deactivate(struct irq_domain *domain, diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c index 4f2623c2393e..2313af82fad3 100644 --- a/drivers/gpio/gpio-xgene-sb.c +++ b/drivers/gpio/gpio-xgene-sb.c @@ -137,8 +137,9 @@ static int xgene_gpio_sb_to_irq(struct gpio_chip *gc, u32 gpio) return irq_create_fwspec_mapping(&fwspec); } -static void xgene_gpio_sb_domain_activate(struct irq_domain *d, - struct irq_data *irq_data) +static int xgene_gpio_sb_domain_activate(struct irq_domain *d, + struct irq_data *irq_data, + bool early) { struct xgene_gpio_sb *priv = d->host_data; u32 gpio = HWIRQ_TO_GPIO(priv, irq_data->hwirq); @@ -147,11 +148,12 @@ static void xgene_gpio_sb_domain_activate(struct irq_domain *d, dev_err(priv->gc.parent, "Unable to configure XGene GPIO standby pin %d as IRQ\n", gpio); - return; + return -ENOSPC; } xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_SEL_LO, gpio * 2, 1); + return 0; } static void xgene_gpio_sb_domain_deactivate(struct irq_domain *d, diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 4d2113530735..eb4528c87c0b 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -203,7 +203,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, if (pin <= 255) { char ev_name[5]; - sprintf(ev_name, "_%c%02X", + sprintf(ev_name, "_%c%02hhX", agpio->triggering == ACPI_EDGE_SENSITIVE ? 'E' : 'L', pin); if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle))) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 7397260141b4..aad84a6306c4 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3528,8 +3528,21 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, if (lflags & GPIO_ACTIVE_LOW) set_bit(FLAG_ACTIVE_LOW, &desc->flags); + if (lflags & GPIO_OPEN_DRAIN) set_bit(FLAG_OPEN_DRAIN, &desc->flags); + else if (dflags & GPIOD_FLAGS_BIT_OPEN_DRAIN) { + /* + * This enforces open drain mode from the consumer side. + * This is necessary for some busses like I2C, but the lookup + * should *REALLY* have specified them as open drain in the + * first place, so print a little warning here. + */ + set_bit(FLAG_OPEN_DRAIN, &desc->flags); + gpiod_warn(desc, + "enforced open drain please flag it properly in DT/ACPI DSDT/board file\n"); + } + if (lflags & GPIO_OPEN_SOURCE) set_bit(FLAG_OPEN_SOURCE, &desc->flags); if (lflags & GPIO_SLEEP_MAY_LOSE_VALUE) |