diff options
Diffstat (limited to 'drivers/gpio')
43 files changed, 1606 insertions, 363 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 f82cd678ce08..f79a7c482a99 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_GPIO_ADP5588)	+= gpio-adp5588.o  obj-$(CONFIG_GPIO_ALTERA)  	+= gpio-altera.o  obj-$(CONFIG_GPIO_AMD8111)	+= gpio-amd8111.o  obj-$(CONFIG_GPIO_ARIZONA)	+= gpio-arizona.o +obj-$(CONFIG_ATH79)		+= gpio-ath79.o  obj-$(CONFIG_GPIO_BCM_KONA)	+= gpio-bcm-kona.o  obj-$(CONFIG_GPIO_BRCMSTB)	+= gpio-brcmstb.o  obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o @@ -116,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-ath79.c b/drivers/gpio/gpio-ath79.c new file mode 100644 index 000000000000..03b995304ad6 --- /dev/null +++ b/drivers/gpio/gpio-ath79.c @@ -0,0 +1,204 @@ +/* + *  Atheros AR71XX/AR724X/AR913X GPIO API support + * + *  Copyright (C) 2010-2011 Jaiganesh Narayanan <[email protected]> + *  Copyright (C) 2008-2011 Gabor Juhos <[email protected]> + *  Copyright (C) 2008 Imre Kaloz <[email protected]> + * + *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP + * + *  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/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/spinlock.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/gpio.h> +#include <linux/platform_data/gpio-ath79.h> +#include <linux/of_device.h> + +#include <asm/mach-ath79/ar71xx_regs.h> + +static void __iomem *ath79_gpio_base; +static u32 ath79_gpio_count; +static DEFINE_SPINLOCK(ath79_gpio_lock); + +static void __ath79_gpio_set_value(unsigned gpio, int value) +{ +	void __iomem *base = ath79_gpio_base; + +	if (value) +		__raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET); +	else +		__raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR); +} + +static int __ath79_gpio_get_value(unsigned gpio) +{ +	return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1; +} + +static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset) +{ +	return __ath79_gpio_get_value(offset); +} + +static void ath79_gpio_set_value(struct gpio_chip *chip, +				  unsigned offset, int value) +{ +	__ath79_gpio_set_value(offset, value); +} + +static int ath79_gpio_direction_input(struct gpio_chip *chip, +				       unsigned offset) +{ +	void __iomem *base = ath79_gpio_base; +	unsigned long flags; + +	spin_lock_irqsave(&ath79_gpio_lock, flags); + +	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset), +		     base + AR71XX_GPIO_REG_OE); + +	spin_unlock_irqrestore(&ath79_gpio_lock, flags); + +	return 0; +} + +static int ath79_gpio_direction_output(struct gpio_chip *chip, +					unsigned offset, int value) +{ +	void __iomem *base = ath79_gpio_base; +	unsigned long flags; + +	spin_lock_irqsave(&ath79_gpio_lock, flags); + +	if (value) +		__raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET); +	else +		__raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR); + +	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset), +		     base + AR71XX_GPIO_REG_OE); + +	spin_unlock_irqrestore(&ath79_gpio_lock, flags); + +	return 0; +} + +static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ +	void __iomem *base = ath79_gpio_base; +	unsigned long flags; + +	spin_lock_irqsave(&ath79_gpio_lock, flags); + +	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset), +		     base + AR71XX_GPIO_REG_OE); + +	spin_unlock_irqrestore(&ath79_gpio_lock, flags); + +	return 0; +} + +static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset, +					int value) +{ +	void __iomem *base = ath79_gpio_base; +	unsigned long flags; + +	spin_lock_irqsave(&ath79_gpio_lock, flags); + +	if (value) +		__raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET); +	else +		__raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR); + +	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset), +		     base + AR71XX_GPIO_REG_OE); + +	spin_unlock_irqrestore(&ath79_gpio_lock, flags); + +	return 0; +} + +static struct gpio_chip ath79_gpio_chip = { +	.label			= "ath79", +	.get			= ath79_gpio_get_value, +	.set			= ath79_gpio_set_value, +	.direction_input	= ath79_gpio_direction_input, +	.direction_output	= ath79_gpio_direction_output, +	.base			= 0, +}; + +static const struct of_device_id ath79_gpio_of_match[] = { +	{ .compatible = "qca,ar7100-gpio" }, +	{ .compatible = "qca,ar9340-gpio" }, +	{}, +}; + +static int ath79_gpio_probe(struct platform_device *pdev) +{ +	struct ath79_gpio_platform_data *pdata = pdev->dev.platform_data; +	struct device_node *np = pdev->dev.of_node; +	struct resource *res; +	bool oe_inverted; +	int err; + +	if (np) { +		err = of_property_read_u32(np, "ngpios", &ath79_gpio_count); +		if (err) { +			dev_err(&pdev->dev, "ngpios property is not valid\n"); +			return err; +		} +		if (ath79_gpio_count >= 32) { +			dev_err(&pdev->dev, "ngpios must be less than 32\n"); +			return -EINVAL; +		} +		oe_inverted = of_device_is_compatible(np, "qca,ar9340-gpio"); +	} else if (pdata) { +		ath79_gpio_count = pdata->ngpios; +		oe_inverted = pdata->oe_inverted; +	} else { +		dev_err(&pdev->dev, "No DT node or platform data found\n"); +		return -EINVAL; +	} + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	ath79_gpio_base = devm_ioremap_nocache( +		&pdev->dev, res->start, resource_size(res)); +	if (!ath79_gpio_base) +		return -ENOMEM; + +	ath79_gpio_chip.dev = &pdev->dev; +	ath79_gpio_chip.ngpio = ath79_gpio_count; +	if (oe_inverted) { +		ath79_gpio_chip.direction_input = ar934x_gpio_direction_input; +		ath79_gpio_chip.direction_output = ar934x_gpio_direction_output; +	} + +	err = gpiochip_add(&ath79_gpio_chip); +	if (err) { +		dev_err(&pdev->dev, +			"cannot add AR71xx GPIO chip, error=%d", err); +		return err; +	} + +	return 0; +} + +static struct platform_driver ath79_gpio_driver = { +	.driver = { +		.name = "ath79-gpio", +		.of_match_table	= ath79_gpio_of_match, +	}, +	.probe = ath79_gpio_probe, +}; + +module_platform_driver(ath79_gpio_driver); 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 7a3cb1fa0a76..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) @@ -87,11 +292,26 @@ static int brcmstb_gpio_remove(struct platform_device *pdev)  	struct brcmstb_gpio_bank *bank;  	int ret = 0; +	if (!priv) { +		dev_err(&pdev->dev, "called %s without drvdata!\n", __func__); +		return -EFAULT; +	} + +	/* +	 * You can lose return values below, but we report all errors, and it's +	 * more important to actually perform all of the steps. +	 */  	list_for_each(pos, &priv->bank_list) {  		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;  } @@ -112,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)) { @@ -127,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; @@ -137,12 +416,15 @@ 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;  	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);  	if (!priv)  		return -ENOMEM; +	platform_set_drvdata(pdev, priv); +	INIT_LIST_HEAD(&priv->bank_list);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	reg_base = devm_ioremap_resource(dev, res); @@ -153,7 +435,16 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)  	priv->reg_base = reg_base;  	priv->pdev = pdev; -	INIT_LIST_HEAD(&priv->bank_list); +	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; @@ -170,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; @@ -202,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", @@ -209,19 +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); - -	platform_set_drvdata(pdev, priv); +			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 c5e05c82d67c..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; @@ -578,15 +578,13 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)  		writel_relaxed(~0, &g->clr_falling);  		writel_relaxed(~0, &g->clr_rising); -		/* set up all irqs in this bank */ -		irq_set_chained_handler(bank_irq, gpio_irq_handler); -  		/*  		 * Each chip handles 32 gpios, and each irq bank consists of 16  		 * gpio irqs. Pass the irq bank's corresponding controller to  		 * the chained irq handler.  		 */ -		irq_set_handler_data(bank_irq, &chips[gpio / 32]); +		irq_set_chained_handler_and_data(bank_irq, gpio_irq_handler, +						 &chips[gpio / 32]);  		binten |= BIT(bank);  	} 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 aed4ca9338bc..8c5252c6c327 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -603,6 +603,7 @@ static int max732x_setup_gpio(struct max732x_chip *chip,  	gc->base = gpio_start;  	gc->ngpio = port;  	gc->label = chip->client->name; +	gc->dev = &chip->client->dev;  	gc->owner = THIS_MODULE;  	return port; @@ -684,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 b0c57d505be7..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,22 +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) +	if (retval) { +		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; @@ -634,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;  } @@ -667,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;  } @@ -680,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, @@ -714,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); @@ -729,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; @@ -742,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) { @@ -756,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 @@ -766,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));  		} @@ -789,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); @@ -798,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; @@ -815,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); @@ -823,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, @@ -847,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) @@ -860,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); @@ -872,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);  }  /*---------------------------------------------------------------------*/ @@ -885,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;  } @@ -900,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;  } @@ -948,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;  } @@ -960,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;  } @@ -984,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;  } @@ -999,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;  } @@ -1012,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);  }  /*---------------------------------------------------------------------*/ @@ -1059,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) @@ -1176,15 +1183,19 @@ 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;  	bank->dbck_flag = pdata->dbck_flag;  	bank->stride = pdata->bank_stride;  	bank->width = pdata->bank_width; @@ -1210,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); @@ -1251,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;  } @@ -1268,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. @@ -1321,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;  } @@ -1336,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 @@ -1372,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;  	} @@ -1434,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-pca953x.c b/drivers/gpio/gpio-pca953x.c index d233eb3b8132..50caeb1ee350 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -570,6 +570,10 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,  				"could not connect irqchip to gpiochip\n");  			return ret;  		} + +		gpiochip_set_chained_irqchip(&chip->gpio_chip, +					     &pca953x_irq_chip, +					     client->irq, NULL);  	}  	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-xilinx.c b/drivers/gpio/gpio-xilinx.c index 77fe5d3cb105..d5284dfe01fe 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -220,9 +220,9 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc)  	if (!chip->gpio_width[1])  		return; -	xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + XGPIO_TRI_OFFSET, +	xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + XGPIO_CHANNEL_OFFSET,  		       chip->gpio_state[1]); -	xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET + XGPIO_TRI_OFFSET, +	xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET + XGPIO_CHANNEL_OFFSET,  		       chip->gpio_dir[1]);  } 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 <[email protected]>"); +MODULE_DESCRIPTION("ZTE ZX296702 GPIO driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 2e87c4b8da26..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); @@ -757,6 +757,7 @@ static int zynq_gpio_remove(struct platform_device *pdev)  	gpiochip_remove(&gpio->chip);  	clk_disable_unprepare(gpio->clk);  	device_set_wakeup_capable(&pdev->dev, 0); +	pm_runtime_disable(&pdev->dev);  	return 0;  } @@ -781,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-acpi.c b/drivers/gpio/gpiolib-acpi.c index 533fe5dbe6f8..143a9bdbaa53 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -68,7 +68,7 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)   * GPIO controller driver.   *   * Typically the returned offset is same as @pin, but if the GPIO - * controller uses pin controller and the mapping is not contigous the + * controller uses pin controller and the mapping is not contiguous the   * offset might be different.   */  static int acpi_gpiochip_pin_to_gpio_offset(struct gpio_chip *chip, int pin) 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..980c1f87866a 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   */ @@ -1672,6 +1686,19 @@ void gpiod_add_lookup_table(struct gpiod_lookup_table *table)  	mutex_unlock(&gpio_lookup_lock);  } +/** + * gpiod_remove_lookup_table() - unregister GPIO device consumers + * @table: table of consumers to unregister + */ +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) +{ +	mutex_lock(&gpio_lookup_lock); + +	list_del(&table->list); + +	mutex_unlock(&gpio_lookup_lock); +} +  static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,  				      unsigned int idx,  				      enum gpio_lookup_flags *flags) @@ -1894,12 +1921,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 +1938,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 +2001,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 +2050,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 +2119,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 +2134,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  |