linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure
@ 2017-09-01 18:57 Thierry Reding
  2017-09-01 18:57 ` [PATCH 01/16] gpio: Implement tighter IRQ chip integration Thierry Reding
                   ` (16 more replies)
  0 siblings, 17 replies; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

Hi Linus,

here's the latest series of patches that implement the tighter IRQ chip
integration as well as the banked GPIO infrastructure that we had
discussed a couple of weeks/months back.

The first couple of patches are mostly preparatory work in order to
consolidate all IRQ chip related fields in a new structure and create
the base functionality for adding IRQ chips.

After that, I've added the Tegra186 GPIO support patch that makes use of
the new tight integration.

To round things off the new banked GPIO infrastructure is added (along
with some more preparatory work), followed by the conversion of the two
Tegra GPIO drivers to the new infrastructure.

Any thoughts on this? I'd like to target 4.15 with this, unless you'd be
willing to take this into 4.14, which I doubt at this point. The absence
of a GPIO driver has been hampering Tegra186 support upstream for a
while now, so it'd be good to make progress on this.

All of the patches are bisectible, at least to the point where I was
able to compile (there are a couple of odd users of linux/gpio/driver.h
that I either couldn't figure out the right Kconfig options to enable or
didn't have a cross-compiler for). I've carried these patches in my
development tree for a couple of weeks now, though, and the 0-day
builder hasn't had any complaints in a while. I also have a local cocci
patch for the move of fields to struct gpio_irq_chip and it gives an
empty patch when run on top of these patches on top of linux-next, so I
am fairly confident that this is all good to go.

Thierry

Thierry Reding (16):
  gpio: Implement tighter IRQ chip integration
  gpio: Move irqchip into struct gpio_irq_chip
  gpio: Move irqdomain into struct gpio_irq_chip
  gpio: Move irq_base to struct gpio_irq_chip
  gpio: Move irq_handler to struct gpio_irq_chip
  gpio: Move irq_default_type to struct gpio_irq_chip
  gpio: Move irq_chained_parent to struct gpio_irq_chip
  gpio: Move irq_nested into struct gpio_irq_chip
  gpio: Move irq_valid_mask into struct gpio_irq_chip
  gpio: Move lock_key into struct gpio_irq_chip
  gpio: Add Tegra186 support
  gpio: omap: Fix checkpatch warnings
  gpio: omap: Rename struct gpio_bank to struct omap_gpio_bank
  gpio: Add support for banked GPIO controllers
  gpio: tegra: Use banked GPIO infrastructure
  gpio: tegra186: Use banked GPIO infrastructure

 Documentation/gpio/driver.txt               |   6 +-
 drivers/bcma/driver_gpio.c                  |   2 +-
 drivers/gpio/Kconfig                        |  10 +
 drivers/gpio/Makefile                       |   1 +
 drivers/gpio/gpio-104-dio-48e.c             |   2 +-
 drivers/gpio/gpio-104-idi-48.c              |   2 +-
 drivers/gpio/gpio-104-idio-16.c             |   2 +-
 drivers/gpio/gpio-adnp.c                    |   2 +-
 drivers/gpio/gpio-altera.c                  |   4 +-
 drivers/gpio/gpio-aspeed.c                  |   6 +-
 drivers/gpio/gpio-ath79.c                   |   2 +-
 drivers/gpio/gpio-brcmstb.c                 |   2 +-
 drivers/gpio/gpio-crystalcove.c             |   2 +-
 drivers/gpio/gpio-dln2.c                    |   2 +-
 drivers/gpio/gpio-ftgpio010.c               |   2 +-
 drivers/gpio/gpio-ingenic.c                 |   2 +-
 drivers/gpio/gpio-intel-mid.c               |   2 +-
 drivers/gpio/gpio-lynxpoint.c               |   2 +-
 drivers/gpio/gpio-max732x.c                 |   2 +-
 drivers/gpio/gpio-merrifield.c              |   2 +-
 drivers/gpio/gpio-omap.c                    | 222 ++++++-----
 drivers/gpio/gpio-pca953x.c                 |   2 +-
 drivers/gpio/gpio-pcf857x.c                 |   2 +-
 drivers/gpio/gpio-pci-idio-16.c             |   2 +-
 drivers/gpio/gpio-pl061.c                   |   2 +-
 drivers/gpio/gpio-rcar.c                    |   2 +-
 drivers/gpio/gpio-reg.c                     |   4 +-
 drivers/gpio/gpio-stmpe.c                   |   6 +-
 drivers/gpio/gpio-tc3589x.c                 |   2 +-
 drivers/gpio/gpio-tegra.c                   | 203 +++++-----
 drivers/gpio/gpio-tegra186.c                | 571 ++++++++++++++++++++++++++++
 drivers/gpio/gpio-vf610.c                   |   2 +-
 drivers/gpio/gpio-wcove.c                   |   2 +-
 drivers/gpio/gpio-ws16c48.c                 |   2 +-
 drivers/gpio/gpio-xgene-sb.c                |   2 +-
 drivers/gpio/gpio-xlp.c                     |   2 +-
 drivers/gpio/gpio-zx.c                      |   2 +-
 drivers/gpio/gpio-zynq.c                    |   2 +-
 drivers/gpio/gpiolib-of.c                   | 101 +++++
 drivers/gpio/gpiolib.c                      | 320 ++++++++++++++--
 drivers/pinctrl/bcm/pinctrl-bcm2835.c       |   4 +-
 drivers/pinctrl/bcm/pinctrl-iproc-gpio.c    |   2 +-
 drivers/pinctrl/intel/pinctrl-baytrail.c    |   6 +-
 drivers/pinctrl/intel/pinctrl-cherryview.c  |   6 +-
 drivers/pinctrl/intel/pinctrl-intel.c       |   2 +-
 drivers/pinctrl/mvebu/pinctrl-armada-37xx.c |   4 +-
 drivers/pinctrl/nomadik/pinctrl-nomadik.c   |   4 +-
 drivers/pinctrl/pinctrl-amd.c               |   2 +-
 drivers/pinctrl/pinctrl-at91.c              |   2 +-
 drivers/pinctrl/pinctrl-coh901.c            |   2 +-
 drivers/pinctrl/pinctrl-mcp23s08.c          |   2 +-
 drivers/pinctrl/pinctrl-oxnas.c             |   2 +-
 drivers/pinctrl/pinctrl-pic32.c             |   2 +-
 drivers/pinctrl/pinctrl-pistachio.c         |   2 +-
 drivers/pinctrl/pinctrl-st.c                |   2 +-
 drivers/pinctrl/pinctrl-sx150x.c            |   2 +-
 drivers/pinctrl/qcom/pinctrl-msm.c          |   2 +-
 drivers/pinctrl/sirf/pinctrl-atlas7.c       |   2 +-
 drivers/pinctrl/sirf/pinctrl-sirf.c         |   2 +-
 drivers/pinctrl/spear/pinctrl-plgpio.c      |   2 +-
 drivers/platform/x86/intel_int0002_vgpio.c  |   6 +-
 include/linux/gpio/driver.h                 | 272 +++++++++++--
 include/linux/of_gpio.h                     |  10 +
 63 files changed, 1504 insertions(+), 348 deletions(-)
 create mode 100644 drivers/gpio/gpio-tegra186.c

-- 
2.13.3

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 01/16] gpio: Implement tighter IRQ chip integration
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-01 18:57 ` [PATCH 02/16] gpio: Move irqchip into struct gpio_irq_chip Thierry Reding
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

Currently GPIO drivers are required to a GPIO chip and the corresponding
IRQ chip separately, which can result in a lot of boilerplate. Introduce
a new struct gpio_irq_chip, embedded in a struct gpio_chip, that drivers
can fill in if they want the GPIO core to automatically register the IRQ
chip associated with a GPIO chip.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpio/gpiolib.c      | 146 +++++++++++++++++++++++++++++++++++++++++++-
 include/linux/gpio/driver.h |  64 +++++++++++++++++++
 2 files changed, 207 insertions(+), 3 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 18bba1748a35..abc0f72e9950 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -72,6 +72,7 @@ static LIST_HEAD(gpio_lookup_list);
 LIST_HEAD(gpio_devices);
 
 static void gpiochip_free_hogs(struct gpio_chip *chip);
+static int gpiochip_add_irqchip(struct gpio_chip *gpiochip);
 static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip);
 static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip);
 static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip);
@@ -1271,6 +1272,10 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
 	if (status)
 		goto err_remove_from_list;
 
+	status = gpiochip_add_irqchip(chip);
+	if (status)
+		goto err_remove_chip;
+
 	status = of_gpiochip_add(chip);
 	if (status)
 		goto err_remove_chip;
@@ -1637,8 +1642,8 @@ EXPORT_SYMBOL_GPL(gpiochip_set_nested_irqchip);
  * gpiochip by assigning the gpiochip as chip data, and using the irqchip
  * stored inside the gpiochip.
  */
-static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
-			    irq_hw_number_t hwirq)
+int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
+		     irq_hw_number_t hwirq)
 {
 	struct gpio_chip *chip = d->host_data;
 
@@ -1666,8 +1671,9 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(gpiochip_irq_map);
 
-static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
+void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
 {
 	struct gpio_chip *chip = d->host_data;
 
@@ -1676,6 +1682,7 @@ static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
 	irq_set_chip_and_handler(irq, NULL, NULL);
 	irq_set_chip_data(irq, NULL);
 }
+EXPORT_SYMBOL_GPL(gpiochip_irq_unmap);
 
 static const struct irq_domain_ops gpiochip_domain_ops = {
 	.map	= gpiochip_irq_map,
@@ -1717,6 +1724,124 @@ static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
 }
 
 /**
+ * gpiochip_add_irqchip() - adds an IRQ chip to a GPIO chip
+ * @gpiochip: the GPIO chip to add the IRQ chip to
+ */
+static int gpiochip_add_irqchip(struct gpio_chip *gpiochip)
+{
+	struct irq_chip *irqchip = gpiochip->irqchip;
+	const struct irq_domain_ops *ops;
+	struct device_node *np;
+	unsigned int type;
+	unsigned int i;
+
+	if (!irqchip)
+		return 0;
+
+	if (gpiochip->irq.parent_handler && gpiochip->can_sleep) {
+		chip_err(gpiochip, "you cannot have chained interrupts on a "
+			 "chip that may sleep\n");
+		return -EINVAL;
+	}
+
+	type = gpiochip->irq_default_type;
+	np = gpiochip->parent->of_node;
+
+#ifdef CONFIG_OF_GPIO
+	/*
+	 * If the gpiochip has an assigned OF node this takes precedence
+	 * FIXME: get rid of this and use gpiochip->parent->of_node
+	 * everywhere
+	 */
+	if (gpiochip->of_node)
+		np = gpiochip->of_node;
+#endif
+
+	/*
+	 * Specifying a default trigger is a terrible idea if DT or ACPI is
+	 * used to configure the interrupts, as you may end up with
+	 * conflicting triggers. Tell the user, and reset to NONE.
+	 */
+	if (WARN(np && type != IRQ_TYPE_NONE,
+		 "%s: Ignoring %u default trigger\n", np->full_name, type))
+		type = IRQ_TYPE_NONE;
+
+	if (has_acpi_companion(gpiochip->parent) && type != IRQ_TYPE_NONE) {
+		acpi_handle_warn(ACPI_HANDLE(gpiochip->parent),
+				 "Ignoring %u default trigger\n", type);
+		type = IRQ_TYPE_NONE;
+	}
+
+	gpiochip->to_irq = gpiochip_to_irq;
+	gpiochip->irq_default_type = type;
+
+	if (gpiochip->irq.domain_ops)
+		ops = gpiochip->irq.domain_ops;
+	else
+		ops = &gpiochip_domain_ops;
+
+	gpiochip->irqdomain = irq_domain_add_simple(np, gpiochip->ngpio,
+						    gpiochip->irq_base,
+						    ops, gpiochip);
+	if (!gpiochip->irqdomain)
+		return -EINVAL;
+
+	/*
+	 * 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;
+	}
+
+	if (gpiochip->irq.parent_handler) {
+		void *data = gpiochip->irq.parent_handler_data ?: gpiochip;
+
+		for (i = 0; i < gpiochip->irq.num_parents; i++) {
+			/*
+			 * The parent IRQ chip is already using the chip_data
+			 * for this IRQ chip, so our callbacks simply use the
+			 * handler_data.
+			 */
+			irq_set_chained_handler_and_data(gpiochip->irq.parents[i],
+							 gpiochip->irq.parent_handler,
+							 data);
+		}
+
+		gpiochip->irq_nested = false;
+	} else {
+		gpiochip->irq_nested = true;
+	}
+
+	/*
+	 * Prepare the mapping since the IRQ chip shall be orthogonal to any
+	 * GPIO chip calls.
+	 */
+	for (i = 0; i < gpiochip->ngpio; i++) {
+		unsigned int irq;
+
+		if (!gpiochip_irqchip_irq_valid(gpiochip, i))
+			continue;
+
+		irq = irq_create_mapping(gpiochip->irqdomain, i);
+		if (!irq) {
+			chip_err(gpiochip,
+				 "failed to create IRQ mapping for GPIO#%u\n",
+				 i);
+			continue;
+		}
+
+		irq_set_parent(irq, gpiochip->irq.map[i]);
+	}
+
+	acpi_gpiochip_request_interrupts(gpiochip);
+
+	return 0;
+}
+
+/**
  * gpiochip_irqchip_remove() - removes an irqchip added to a gpiochip
  * @gpiochip: the gpiochip to remove the irqchip from
  *
@@ -1733,6 +1858,16 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
 		irq_set_handler_data(gpiochip->irq_chained_parent, NULL);
 	}
 
+	if (gpiochip->irqchip) {
+		struct gpio_irq_chip *irq = &gpiochip->irq;
+		unsigned int i;
+
+		for (i = 0; i < irq->num_parents; i++) {
+			irq_set_chained_handler(irq->parents[i], NULL);
+			irq_set_handler_data(irq->parents[i], NULL);
+		}
+	}
+
 	/* Remove all IRQ mappings and delete the domain */
 	if (gpiochip->irqdomain) {
 		for (offset = 0; offset < gpiochip->ngpio; offset++) {
@@ -1853,6 +1988,11 @@ EXPORT_SYMBOL_GPL(gpiochip_irqchip_add_key);
 
 #else /* CONFIG_GPIOLIB_IRQCHIP */
 
+static inline int gpiochip_add_irqchip(struct gpio_chip *gpiochip)
+{
+	return 0;
+}
+
 static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {}
 static inline int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip)
 {
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index c97f8325e8bf..6100b171817e 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -19,6 +19,58 @@ struct module;
 
 #ifdef CONFIG_GPIOLIB
 
+#ifdef CONFIG_GPIOLIB_IRQCHIP
+/**
+ * struct gpio_irq_chip - GPIO interrupt controller
+ */
+struct gpio_irq_chip {
+	/**
+	 * @domain_ops:
+	 *
+	 * Table of interrupt domain operations for this IRQ chip.
+	 */
+	const struct irq_domain_ops *domain_ops;
+
+	/**
+	 * @parent_handler:
+	 *
+	 * The interrupt handler for the GPIO chip's parent interrupts, may be
+	 * NULL if the parent interrupts are nested rather than cascaded.
+	 */
+	irq_flow_handler_t parent_handler;
+
+	/**
+	 * @parent_handler_data:
+	 *
+	 * Data associated, and passed to, the handler for the parent
+	 * interrupt.
+	 */
+	void *parent_handler_data;
+
+	/**
+	 * @num_parents:
+	 *
+	 * The number of interrupt parents of a GPIO chip.
+	 */
+	unsigned int num_parents;
+
+	/**
+	 * @parents:
+	 *
+	 * A list of interrupt parents of a GPIO chip. This is owned by the
+	 * driver, so the core will only reference this list, not modify it.
+	 */
+	unsigned int *parents;
+
+	/**
+	 * @map:
+	 *
+	 * A list of interrupt parents for each line of a GPIO chip.
+	 */
+	unsigned int *map;
+};
+#endif
+
 /**
  * struct gpio_chip - abstract a GPIO controller
  * @label: a functional name for the GPIO device, such as a part
@@ -173,6 +225,14 @@ struct gpio_chip {
 	bool			irq_need_valid_mask;
 	unsigned long		*irq_valid_mask;
 	struct lock_class_key	*lock_key;
+
+	/**
+	 * @irq:
+	 *
+	 * Integrates interrupt chip functionality with the GPIO chip. Can be
+	 * used to handle IRQs for most practical cases.
+	 */
+	struct gpio_irq_chip irq;
 #endif
 
 #if defined(CONFIG_OF_GPIO)
@@ -264,6 +324,10 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev,
 
 #ifdef CONFIG_GPIOLIB_IRQCHIP
 
+int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
+		     irq_hw_number_t hwirq);
+void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq);
+
 void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
 		struct irq_chip *irqchip,
 		unsigned int parent_irq,
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 02/16] gpio: Move irqchip into struct gpio_irq_chip
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
  2017-09-01 18:57 ` [PATCH 01/16] gpio: Implement tighter IRQ chip integration Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-01 18:57 ` [PATCH 03/16] gpio: Move irqdomain " Thierry Reding
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

In order to consolidate the multiple ways to associate an IRQ chip with
a GPIO chip, move more fields into the new struct gpio_irq_chip.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpio/gpiolib.c      | 18 +++++++++---------
 include/linux/gpio/driver.h | 14 ++++++++++++--
 2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index abc0f72e9950..4058adde7dc6 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1656,7 +1656,7 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
 	 * 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);
+	irq_set_chip_and_handler(irq, chip->irq.chip, chip->irq_handler);
 	/* Chips that use nested thread handlers have them marked */
 	if (chip->irq_nested)
 		irq_set_nested_thread(irq, 1);
@@ -1729,7 +1729,7 @@ static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
  */
 static int gpiochip_add_irqchip(struct gpio_chip *gpiochip)
 {
-	struct irq_chip *irqchip = gpiochip->irqchip;
+	struct irq_chip *irqchip = gpiochip->irq.chip;
 	const struct irq_domain_ops *ops;
 	struct device_node *np;
 	unsigned int type;
@@ -1858,7 +1858,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
 		irq_set_handler_data(gpiochip->irq_chained_parent, NULL);
 	}
 
-	if (gpiochip->irqchip) {
+	if (gpiochip->irq.chip) {
 		struct gpio_irq_chip *irq = &gpiochip->irq;
 		unsigned int i;
 
@@ -1879,10 +1879,10 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
 		irq_domain_remove(gpiochip->irqdomain);
 	}
 
-	if (gpiochip->irqchip) {
-		gpiochip->irqchip->irq_request_resources = NULL;
-		gpiochip->irqchip->irq_release_resources = NULL;
-		gpiochip->irqchip = NULL;
+	if (gpiochip->irq.chip) {
+		gpiochip->irq.chip->irq_request_resources = NULL;
+		gpiochip->irq.chip->irq_release_resources = NULL;
+		gpiochip->irq.chip = NULL;
 	}
 
 	gpiochip_irqchip_free_valid_mask(gpiochip);
@@ -1957,7 +1957,7 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
 		type = IRQ_TYPE_NONE;
 	}
 
-	gpiochip->irqchip = irqchip;
+	gpiochip->irq.chip = irqchip;
 	gpiochip->irq_handler = handler;
 	gpiochip->irq_default_type = type;
 	gpiochip->to_irq = gpiochip_to_irq;
@@ -1966,7 +1966,7 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
 					gpiochip->ngpio, first_irq,
 					&gpiochip_domain_ops, gpiochip);
 	if (!gpiochip->irqdomain) {
-		gpiochip->irqchip = NULL;
+		gpiochip->irq.chip = NULL;
 		return -EINVAL;
 	}
 
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 6100b171817e..974247646886 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -25,6 +25,13 @@ struct module;
  */
 struct gpio_irq_chip {
 	/**
+	 * @chip:
+	 *
+	 * GPIO IRQ chip implementation, provided by GPIO driver.
+	 */
+	struct irq_chip *chip;
+
+	/**
 	 * @domain_ops:
 	 *
 	 * Table of interrupt domain operations for this IRQ chip.
@@ -69,6 +76,11 @@ struct gpio_irq_chip {
 	 */
 	unsigned int *map;
 };
+
+static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)
+{
+	return container_of(chip, struct gpio_irq_chip, chip);
+}
 #endif
 
 /**
@@ -132,7 +144,6 @@ struct gpio_irq_chip {
  *	safely.
  * @bgpio_dir: shadowed direction register for generic GPIO to clear/set
  *	direction safely.
- * @irqchip: GPIO IRQ chip impl, provided by GPIO driver
  * @irqdomain: Interrupt translation domain; responsible for mapping
  *	between GPIO hwirq number and linux irq number
  * @irq_base: first linux IRQ number assigned to GPIO IRQ chip (deprecated)
@@ -215,7 +226,6 @@ struct gpio_chip {
 	 * With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
 	 * to handle IRQs for most practical cases.
 	 */
-	struct irq_chip		*irqchip;
 	struct irq_domain	*irqdomain;
 	unsigned int		irq_base;
 	irq_flow_handler_t	irq_handler;
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 03/16] gpio: Move irqdomain into struct gpio_irq_chip
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
  2017-09-01 18:57 ` [PATCH 01/16] gpio: Implement tighter IRQ chip integration Thierry Reding
  2017-09-01 18:57 ` [PATCH 02/16] gpio: Move irqchip into struct gpio_irq_chip Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-01 18:57 ` [PATCH 04/16] gpio: Move irq_base to " Thierry Reding
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

In order to consolidate the multiple ways to associate an IRQ chip with
a GPIO chip, move more fields into the new struct gpio_irq_chip.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 Documentation/gpio/driver.txt               |  2 +-
 drivers/bcma/driver_gpio.c                  |  2 +-
 drivers/gpio/gpio-104-dio-48e.c             |  2 +-
 drivers/gpio/gpio-104-idi-48.c              |  2 +-
 drivers/gpio/gpio-104-idio-16.c             |  2 +-
 drivers/gpio/gpio-adnp.c                    |  2 +-
 drivers/gpio/gpio-altera.c                  |  4 ++--
 drivers/gpio/gpio-aspeed.c                  |  2 +-
 drivers/gpio/gpio-ath79.c                   |  2 +-
 drivers/gpio/gpio-brcmstb.c                 |  2 +-
 drivers/gpio/gpio-crystalcove.c             |  2 +-
 drivers/gpio/gpio-dln2.c                    |  2 +-
 drivers/gpio/gpio-ftgpio010.c               |  2 +-
 drivers/gpio/gpio-ingenic.c                 |  2 +-
 drivers/gpio/gpio-intel-mid.c               |  2 +-
 drivers/gpio/gpio-lynxpoint.c               |  2 +-
 drivers/gpio/gpio-max732x.c                 |  2 +-
 drivers/gpio/gpio-merrifield.c              |  2 +-
 drivers/gpio/gpio-omap.c                    |  2 +-
 drivers/gpio/gpio-pca953x.c                 |  2 +-
 drivers/gpio/gpio-pcf857x.c                 |  2 +-
 drivers/gpio/gpio-pci-idio-16.c             |  2 +-
 drivers/gpio/gpio-pl061.c                   |  2 +-
 drivers/gpio/gpio-rcar.c                    |  2 +-
 drivers/gpio/gpio-reg.c                     |  4 ++--
 drivers/gpio/gpio-stmpe.c                   |  2 +-
 drivers/gpio/gpio-tc3589x.c                 |  2 +-
 drivers/gpio/gpio-vf610.c                   |  2 +-
 drivers/gpio/gpio-wcove.c                   |  2 +-
 drivers/gpio/gpio-ws16c48.c                 |  2 +-
 drivers/gpio/gpio-xgene-sb.c                |  2 +-
 drivers/gpio/gpio-xlp.c                     |  2 +-
 drivers/gpio/gpio-zx.c                      |  2 +-
 drivers/gpio/gpio-zynq.c                    |  2 +-
 drivers/gpio/gpiolib.c                      | 32 +++++++++++++++--------------
 drivers/pinctrl/bcm/pinctrl-bcm2835.c       |  4 ++--
 drivers/pinctrl/bcm/pinctrl-iproc-gpio.c    |  2 +-
 drivers/pinctrl/intel/pinctrl-baytrail.c    |  2 +-
 drivers/pinctrl/intel/pinctrl-cherryview.c  |  2 +-
 drivers/pinctrl/intel/pinctrl-intel.c       |  2 +-
 drivers/pinctrl/mvebu/pinctrl-armada-37xx.c |  2 +-
 drivers/pinctrl/nomadik/pinctrl-nomadik.c   |  4 ++--
 drivers/pinctrl/pinctrl-amd.c               |  2 +-
 drivers/pinctrl/pinctrl-at91.c              |  2 +-
 drivers/pinctrl/pinctrl-coh901.c            |  2 +-
 drivers/pinctrl/pinctrl-mcp23s08.c          |  2 +-
 drivers/pinctrl/pinctrl-oxnas.c             |  2 +-
 drivers/pinctrl/pinctrl-pic32.c             |  2 +-
 drivers/pinctrl/pinctrl-pistachio.c         |  2 +-
 drivers/pinctrl/pinctrl-st.c                |  2 +-
 drivers/pinctrl/pinctrl-sx150x.c            |  2 +-
 drivers/pinctrl/qcom/pinctrl-msm.c          |  2 +-
 drivers/pinctrl/sirf/pinctrl-atlas7.c       |  2 +-
 drivers/pinctrl/sirf/pinctrl-sirf.c         |  2 +-
 drivers/pinctrl/spear/pinctrl-plgpio.c      |  2 +-
 drivers/platform/x86/intel_int0002_vgpio.c  |  2 +-
 include/linux/gpio/driver.h                 | 11 +++++++---
 57 files changed, 84 insertions(+), 77 deletions(-)

diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt
index fc1d2f83564d..dcf6af1d9e56 100644
--- a/Documentation/gpio/driver.txt
+++ b/Documentation/gpio/driver.txt
@@ -254,7 +254,7 @@ GPIO irqchips usually fall in one of two categories:
 	static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
 		unsigned long wa_lock_flags;
 		raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags);
-		generic_handle_irq(irq_find_mapping(bank->chip.irqdomain, bit));
+		generic_handle_irq(irq_find_mapping(bank->chip.irq.domain, bit));
 		raw_spin_unlock_irqrestore(&bank->wa_lock, wa_lock_flags);
 
 * GENERIC CHAINED GPIO irqchips: these are the same as "CHAINED GPIO irqchips",
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
index 982d5781d3ce..2c0ffb77d738 100644
--- a/drivers/bcma/driver_gpio.c
+++ b/drivers/bcma/driver_gpio.c
@@ -113,7 +113,7 @@ static irqreturn_t bcma_gpio_irq_handler(int irq, void *dev_id)
 		return IRQ_NONE;
 
 	for_each_set_bit(gpio, &irqs, gc->ngpio)
-		generic_handle_irq(irq_find_mapping(gc->irqdomain, gpio));
+		generic_handle_irq(irq_find_mapping(gc->irq.domain, gpio));
 	bcma_chipco_gpio_polarity(cc, irqs, val & irqs);
 
 	return IRQ_HANDLED;
diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c
index 598e209efa2d..bab3b94c5cbc 100644
--- a/drivers/gpio/gpio-104-dio-48e.c
+++ b/drivers/gpio/gpio-104-dio-48e.c
@@ -326,7 +326,7 @@ static irqreturn_t dio48e_irq_handler(int irq, void *dev_id)
 	unsigned long gpio;
 
 	for_each_set_bit(gpio, &irq_mask, 2)
-		generic_handle_irq(irq_find_mapping(chip->irqdomain,
+		generic_handle_irq(irq_find_mapping(chip->irq.domain,
 			19 + gpio*24));
 
 	raw_spin_lock(&dio48egpio->lock);
diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c
index 51f046e29ff7..add859d59766 100644
--- a/drivers/gpio/gpio-104-idi-48.c
+++ b/drivers/gpio/gpio-104-idi-48.c
@@ -209,7 +209,7 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
 		for_each_set_bit(bit_num, &irq_mask, 8) {
 			gpio = bit_num + boundary * 8;
 
-			generic_handle_irq(irq_find_mapping(chip->irqdomain,
+			generic_handle_irq(irq_find_mapping(chip->irq.domain,
 				gpio));
 		}
 	}
diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c
index ec2ce34ff473..2f16638a0589 100644
--- a/drivers/gpio/gpio-104-idio-16.c
+++ b/drivers/gpio/gpio-104-idio-16.c
@@ -199,7 +199,7 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
 	int gpio;
 
 	for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
-		generic_handle_irq(irq_find_mapping(chip->irqdomain, gpio));
+		generic_handle_irq(irq_find_mapping(chip->irq.domain, gpio));
 
 	raw_spin_lock(&idio16gpio->lock);
 
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index 89863ea25de1..9d143ae4219f 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -323,7 +323,7 @@ static irqreturn_t adnp_irq(int irq, void *data)
 
 		for_each_set_bit(bit, &pending, 8) {
 			unsigned int child_irq;
-			child_irq = irq_find_mapping(adnp->gpio.irqdomain,
+			child_irq = irq_find_mapping(adnp->gpio.irq.domain,
 						     base + bit);
 			handle_nested_irq(child_irq);
 		}
diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c
index ccc02ed65b3c..8e76d390e653 100644
--- a/drivers/gpio/gpio-altera.c
+++ b/drivers/gpio/gpio-altera.c
@@ -211,7 +211,7 @@ static void altera_gpio_irq_edge_handler(struct irq_desc *desc)
 	altera_gc = gpiochip_get_data(irq_desc_get_handler_data(desc));
 	chip = irq_desc_get_chip(desc);
 	mm_gc = &altera_gc->mmchip;
-	irqdomain = altera_gc->mmchip.gc.irqdomain;
+	irqdomain = altera_gc->mmchip.gc.irq.domain;
 
 	chained_irq_enter(chip, desc);
 
@@ -239,7 +239,7 @@ static void altera_gpio_irq_leveL_high_handler(struct irq_desc *desc)
 	altera_gc = gpiochip_get_data(irq_desc_get_handler_data(desc));
 	chip = irq_desc_get_chip(desc);
 	mm_gc = &altera_gc->mmchip;
-	irqdomain = altera_gc->mmchip.gc.irqdomain;
+	irqdomain = altera_gc->mmchip.gc.irq.domain;
 
 	chained_irq_enter(chip, desc);
 
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index bfc53995064a..a9342b471359 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -466,7 +466,7 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc)
 		reg = ioread32(bank_irq_reg(data, bank, GPIO_IRQ_STATUS));
 
 		for_each_set_bit(p, &reg, 32) {
-			girq = irq_find_mapping(gc->irqdomain, i * 32 + p);
+			girq = irq_find_mapping(gc->irq.domain, i * 32 + p);
 			generic_handle_irq(girq);
 		}
 
diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c
index f33d4a5fe671..299e9f7b6b9d 100644
--- a/drivers/gpio/gpio-ath79.c
+++ b/drivers/gpio/gpio-ath79.c
@@ -208,7 +208,7 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc)
 	if (pending) {
 		for_each_set_bit(irq, &pending, gc->ngpio)
 			generic_handle_irq(
-				irq_linear_revmap(gc->irqdomain, irq));
+				irq_linear_revmap(gc->irq.domain, irq));
 	}
 
 	chained_irq_exit(irqchip, desc);
diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c
index dd0308cc8bb0..4aadbae3c43f 100644
--- a/drivers/gpio/gpio-brcmstb.c
+++ b/drivers/gpio/gpio-brcmstb.c
@@ -202,7 +202,7 @@ static irqreturn_t brcmstb_gpio_wake_irq_handler(int irq, void *data)
 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->gc.irqdomain;
+	struct irq_domain *irq_domain = bank->gc.irq.domain;
 	void __iomem *reg_base = priv->reg_base;
 	unsigned long status;
 	unsigned long flags;
diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c
index e60156ec0c18..b6f0f729656c 100644
--- a/drivers/gpio/gpio-crystalcove.c
+++ b/drivers/gpio/gpio-crystalcove.c
@@ -295,7 +295,7 @@ static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data)
 
 	for (gpio = 0; gpio < CRYSTALCOVE_GPIO_NUM; gpio++) {
 		if (pending & BIT(gpio)) {
-			virq = irq_find_mapping(cg->chip.irqdomain, gpio);
+			virq = irq_find_mapping(cg->chip.irq.domain, gpio);
 			handle_nested_irq(virq);
 		}
 	}
diff --git a/drivers/gpio/gpio-dln2.c b/drivers/gpio/gpio-dln2.c
index aecb847166f5..1dada68b9a27 100644
--- a/drivers/gpio/gpio-dln2.c
+++ b/drivers/gpio/gpio-dln2.c
@@ -420,7 +420,7 @@ static void dln2_gpio_event(struct platform_device *pdev, u16 echo,
 		return;
 	}
 
-	irq = irq_find_mapping(dln2->gpio.irqdomain, pin);
+	irq = irq_find_mapping(dln2->gpio.irq.domain, pin);
 	if (!irq) {
 		dev_err(dln2->gpio.parent, "pin %d not mapped to IRQ\n", pin);
 		return;
diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c
index e9386f8b67f5..b7896bae83ca 100644
--- a/drivers/gpio/gpio-ftgpio010.c
+++ b/drivers/gpio/gpio-ftgpio010.c
@@ -149,7 +149,7 @@ static void ftgpio_gpio_irq_handler(struct irq_desc *desc)
 	stat = readl(g->base + GPIO_INT_STAT);
 	if (stat)
 		for_each_set_bit(offset, &stat, gc->ngpio)
-			generic_handle_irq(irq_find_mapping(gc->irqdomain,
+			generic_handle_irq(irq_find_mapping(gc->irq.domain,
 							    offset));
 
 	chained_irq_exit(irqchip, desc);
diff --git a/drivers/gpio/gpio-ingenic.c b/drivers/gpio/gpio-ingenic.c
index 254780730b95..15fb2bc796a8 100644
--- a/drivers/gpio/gpio-ingenic.c
+++ b/drivers/gpio/gpio-ingenic.c
@@ -242,7 +242,7 @@ static void ingenic_gpio_irq_handler(struct irq_desc *desc)
 		flag = gpio_ingenic_read_reg(jzgc, JZ4740_GPIO_FLAG);
 
 	for_each_set_bit(i, &flag, 32)
-		generic_handle_irq(irq_linear_revmap(gc->irqdomain, i));
+		generic_handle_irq(irq_linear_revmap(gc->irq.domain, i));
 	chained_irq_exit(irq_chip, desc);
 }
 
diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c
index b76ecee82c3f..629575ea46a0 100644
--- a/drivers/gpio/gpio-intel-mid.c
+++ b/drivers/gpio/gpio-intel-mid.c
@@ -295,7 +295,7 @@ static void intel_mid_irq_handler(struct irq_desc *desc)
 			mask = BIT(gpio);
 			/* Clear before handling so we can't lose an edge */
 			writel(mask, gedr);
-			generic_handle_irq(irq_find_mapping(gc->irqdomain,
+			generic_handle_irq(irq_find_mapping(gc->irq.domain,
 							    base + gpio));
 		}
 	}
diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c
index fbd393b46ce0..1e557b10d73e 100644
--- a/drivers/gpio/gpio-lynxpoint.c
+++ b/drivers/gpio/gpio-lynxpoint.c
@@ -255,7 +255,7 @@ static void lp_gpio_irq_handler(struct irq_desc *desc)
 			mask = BIT(pin);
 			/* Clear before handling so we don't lose an edge */
 			outl(mask, reg);
-			irq = irq_find_mapping(lg->chip.irqdomain, base + pin);
+			irq = irq_find_mapping(lg->chip.irq.domain, base + pin);
 			generic_handle_irq(irq);
 		}
 	}
diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
index 7f4d26ce5f23..c04fae1ba32a 100644
--- a/drivers/gpio/gpio-max732x.c
+++ b/drivers/gpio/gpio-max732x.c
@@ -486,7 +486,7 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid)
 
 	do {
 		level = __ffs(pending);
-		handle_nested_irq(irq_find_mapping(chip->gpio_chip.irqdomain,
+		handle_nested_irq(irq_find_mapping(chip->gpio_chip.irq.domain,
 						   level));
 
 		pending &= ~(1 << level);
diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c
index ec8560298805..dd67a31ac337 100644
--- a/drivers/gpio/gpio-merrifield.c
+++ b/drivers/gpio/gpio-merrifield.c
@@ -357,7 +357,7 @@ static void mrfld_irq_handler(struct irq_desc *desc)
 		for_each_set_bit(gpio, &pending, 32) {
 			unsigned int irq;
 
-			irq = irq_find_mapping(gc->irqdomain, base + gpio);
+			irq = irq_find_mapping(gc->irq.domain, base + gpio);
 			generic_handle_irq(irq);
 		}
 	}
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index dbf869fb63ce..ce27d6a586bf 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -733,7 +733,7 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
 
 			raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags);
 
-			generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
+			generic_handle_irq(irq_find_mapping(bank->chip.irq.domain,
 							    bit));
 
 			raw_spin_unlock_irqrestore(&bank->wa_lock,
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 1b9dbf691ae7..babb7bd2ba59 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -608,7 +608,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
 	for (i = 0; i < NBANK(chip); i++) {
 		while (pending[i]) {
 			level = __ffs(pending[i]);
-			handle_nested_irq(irq_find_mapping(chip->gpio_chip.irqdomain,
+			handle_nested_irq(irq_find_mapping(chip->gpio_chip.irq.domain,
 							level + (BANK_SZ * i)));
 			pending[i] &= ~(1 << level);
 			nhandled++;
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index a4fd78b9c0e4..38fbb420c6cd 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -196,7 +196,7 @@ static irqreturn_t pcf857x_irq(int irq, void *data)
 	mutex_unlock(&gpio->lock);
 
 	for_each_set_bit(i, &change, gpio->chip.ngpio)
-		handle_nested_irq(irq_find_mapping(gpio->chip.irqdomain, i));
+		handle_nested_irq(irq_find_mapping(gpio->chip.irq.domain, i));
 
 	return IRQ_HANDLED;
 }
diff --git a/drivers/gpio/gpio-pci-idio-16.c b/drivers/gpio/gpio-pci-idio-16.c
index 7de4f6a2cb49..57d1b7fbf07b 100644
--- a/drivers/gpio/gpio-pci-idio-16.c
+++ b/drivers/gpio/gpio-pci-idio-16.c
@@ -240,7 +240,7 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
 		return IRQ_NONE;
 
 	for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
-		generic_handle_irq(irq_find_mapping(chip->irqdomain, gpio));
+		generic_handle_irq(irq_find_mapping(chip->irq.domain, gpio));
 
 	raw_spin_lock(&idio16gpio->lock);
 
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index 3d3d6b6645a7..646a5a12dd7b 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -221,7 +221,7 @@ static void pl061_irq_handler(struct irq_desc *desc)
 	pending = readb(pl061->base + GPIOMIS);
 	if (pending) {
 		for_each_set_bit(offset, &pending, PL061_GPIO_NR)
-			generic_handle_irq(irq_find_mapping(gc->irqdomain,
+			generic_handle_irq(irq_find_mapping(gc->irq.domain,
 							    offset));
 	}
 
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index 1f0871553fd2..5bd1339d5a48 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -206,7 +206,7 @@ static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
 			  gpio_rcar_read(p, INTMSK))) {
 		offset = __ffs(pending);
 		gpio_rcar_write(p, INTCLR, BIT(offset));
-		generic_handle_irq(irq_find_mapping(p->gpio_chip.irqdomain,
+		generic_handle_irq(irq_find_mapping(p->gpio_chip.irq.domain,
 						    offset));
 		irqs_handled++;
 	}
diff --git a/drivers/gpio/gpio-reg.c b/drivers/gpio/gpio-reg.c
index e85903eddc68..23e771dba4c1 100644
--- a/drivers/gpio/gpio-reg.c
+++ b/drivers/gpio/gpio-reg.c
@@ -103,8 +103,8 @@ static int gpio_reg_to_irq(struct gpio_chip *gc, unsigned offset)
 	struct gpio_reg *r = to_gpio_reg(gc);
 	int irq = r->irqs[offset];
 
-	if (irq >= 0 && r->irqdomain)
-		irq = irq_find_mapping(r->irqdomain, irq);
+	if (irq >= 0 && r->irq.domain)
+		irq = irq_find_mapping(r->irq.domain, irq);
 
 	return irq;
 }
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index 16cbc5702865..5aee24fe0254 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -397,7 +397,7 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
 		while (stat) {
 			int bit = __ffs(stat);
 			int line = bank * 8 + bit;
-			int child_irq = irq_find_mapping(stmpe_gpio->chip.irqdomain,
+			int child_irq = irq_find_mapping(stmpe_gpio->chip.irq.domain,
 							 line);
 
 			handle_nested_irq(child_irq);
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index 433b45ef332e..91a8ef8e7f3f 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -268,7 +268,7 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
 		while (stat) {
 			int bit = __ffs(stat);
 			int line = i * 8 + bit;
-			int irq = irq_find_mapping(tc3589x_gpio->chip.irqdomain,
+			int irq = irq_find_mapping(tc3589x_gpio->chip.irq.domain,
 						   line);
 
 			handle_nested_irq(irq);
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
index cbe9e06861de..4610cc2938ad 100644
--- a/drivers/gpio/gpio-vf610.c
+++ b/drivers/gpio/gpio-vf610.c
@@ -160,7 +160,7 @@ static void vf610_gpio_irq_handler(struct irq_desc *desc)
 	for_each_set_bit(pin, &irq_isfr, VF610_GPIO_PER_PORT) {
 		vf610_gpio_writel(BIT(pin), port->base + PORT_ISFR);
 
-		generic_handle_irq(irq_find_mapping(port->gc.irqdomain, pin));
+		generic_handle_irq(irq_find_mapping(port->gc.irq.domain, pin));
 	}
 
 	chained_irq_exit(chip, desc);
diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c
index 85341eab795d..dde7c6aecbb5 100644
--- a/drivers/gpio/gpio-wcove.c
+++ b/drivers/gpio/gpio-wcove.c
@@ -350,7 +350,7 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data)
 			offset = (gpio > GROUP0_NR_IRQS) ? 1 : 0;
 			mask = (offset == 1) ? BIT(gpio - GROUP0_NR_IRQS) :
 								BIT(gpio);
-			virq = irq_find_mapping(wg->chip.irqdomain, gpio);
+			virq = irq_find_mapping(wg->chip.irq.domain, gpio);
 			handle_nested_irq(virq);
 			regmap_update_bits(wg->regmap, IRQ_STATUS_BASE + offset,
 								mask, mask);
diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c
index 5037974ac063..746648244bf3 100644
--- a/drivers/gpio/gpio-ws16c48.c
+++ b/drivers/gpio/gpio-ws16c48.c
@@ -332,7 +332,7 @@ static irqreturn_t ws16c48_irq_handler(int irq, void *dev_id)
 			int_id = inb(ws16c48gpio->base + 8 + port);
 			for_each_set_bit(gpio, &int_id, 8)
 				generic_handle_irq(irq_find_mapping(
-					chip->irqdomain, gpio + 8*port));
+					chip->irq.domain, gpio + 8*port));
 		}
 
 		int_pending = inb(ws16c48gpio->base + 6) & 0x7;
diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c
index 033258634b8c..e761fd7c5728 100644
--- a/drivers/gpio/gpio-xgene-sb.c
+++ b/drivers/gpio/gpio-xgene-sb.c
@@ -296,7 +296,7 @@ static int xgene_gpio_sb_probe(struct platform_device *pdev)
 	if (!priv->irq_domain)
 		return -ENODEV;
 
-	priv->gc.irqdomain = priv->irq_domain;
+	priv->gc.irq.domain = priv->irq_domain;
 
 	ret = devm_gpiochip_add_data(&pdev->dev, &priv->gc, priv);
 	if (ret) {
diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c
index d857e1d8e731..e74bd43a6974 100644
--- a/drivers/gpio/gpio-xlp.c
+++ b/drivers/gpio/gpio-xlp.c
@@ -225,7 +225,7 @@ static void xlp_gpio_generic_handler(struct irq_desc *desc)
 
 		if (gpio_stat & BIT(gpio % XLP_GPIO_REGSZ))
 			generic_handle_irq(irq_find_mapping(
-						priv->chip.irqdomain, gpio));
+						priv->chip.irq.domain, gpio));
 	}
 	chained_irq_exit(irqchip, desc);
 }
diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c
index be3a87da8438..5eacad9b2692 100644
--- a/drivers/gpio/gpio-zx.c
+++ b/drivers/gpio/gpio-zx.c
@@ -170,7 +170,7 @@ static void zx_irq_handler(struct irq_desc *desc)
 	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,
+			generic_handle_irq(irq_find_mapping(gc->irq.domain,
 							    offset));
 	}
 
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index b3cc948a2d8b..75ee877e5cd5 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -562,7 +562,7 @@ static void zynq_gpio_handle_bank_irq(struct zynq_gpio *gpio,
 				      unsigned long pending)
 {
 	unsigned int bank_offset = gpio->p_data->bank_min[bank_num];
-	struct irq_domain *irqdomain = gpio->chip.irqdomain;
+	struct irq_domain *irqdomain = gpio->chip.irq.domain;
 	int offset;
 
 	if (!pending)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 4058adde7dc6..d8ea8a292978 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1560,7 +1560,7 @@ static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip,
 {
 	unsigned int offset;
 
-	if (!gpiochip->irqdomain) {
+	if (!gpiochip->irq.domain) {
 		chip_err(gpiochip, "called %s before setting up irqchip\n",
 			 __func__);
 		return;
@@ -1587,7 +1587,7 @@ static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip,
 	for (offset = 0; offset < gpiochip->ngpio; offset++) {
 		if (!gpiochip_irqchip_irq_valid(gpiochip, offset))
 			continue;
-		irq_set_parent(irq_find_mapping(gpiochip->irqdomain, offset),
+		irq_set_parent(irq_find_mapping(gpiochip->irq.domain, offset),
 			       parent_irq);
 	}
 }
@@ -1720,7 +1720,7 @@ static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
 {
 	if (!gpiochip_irqchip_irq_valid(chip, offset))
 		return -ENXIO;
-	return irq_create_mapping(chip->irqdomain, offset);
+	return irq_create_mapping(chip->irq.domain, offset);
 }
 
 /**
@@ -1780,10 +1780,10 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip)
 	else
 		ops = &gpiochip_domain_ops;
 
-	gpiochip->irqdomain = irq_domain_add_simple(np, gpiochip->ngpio,
-						    gpiochip->irq_base,
-						    ops, gpiochip);
-	if (!gpiochip->irqdomain)
+	gpiochip->irq.domain = irq_domain_add_simple(np, gpiochip->ngpio,
+						     gpiochip->irq_base,
+						     ops, gpiochip);
+	if (!gpiochip->irq.domain)
 		return -EINVAL;
 
 	/*
@@ -1825,7 +1825,7 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip)
 		if (!gpiochip_irqchip_irq_valid(gpiochip, i))
 			continue;
 
-		irq = irq_create_mapping(gpiochip->irqdomain, i);
+		irq = irq_create_mapping(gpiochip->irq.domain, i);
 		if (!irq) {
 			chip_err(gpiochip,
 				 "failed to create IRQ mapping for GPIO#%u\n",
@@ -1849,7 +1849,7 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip)
  */
 static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
 {
-	unsigned int offset;
+	unsigned int offset, irq;
 
 	acpi_gpiochip_free_interrupts(gpiochip);
 
@@ -1869,14 +1869,16 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
 	}
 
 	/* Remove all IRQ mappings and delete the domain */
-	if (gpiochip->irqdomain) {
+	if (gpiochip->irq.domain) {
 		for (offset = 0; offset < gpiochip->ngpio; offset++) {
 			if (!gpiochip_irqchip_irq_valid(gpiochip, offset))
 				continue;
-			irq_dispose_mapping(
-				irq_find_mapping(gpiochip->irqdomain, offset));
+
+			irq = irq_find_mapping(gpiochip->irq.domain, offset);
+			irq_dispose_mapping(irq);
 		}
-		irq_domain_remove(gpiochip->irqdomain);
+
+		irq_domain_remove(gpiochip->irq.domain);
 	}
 
 	if (gpiochip->irq.chip) {
@@ -1962,10 +1964,10 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
 	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->irq.domain = irq_domain_add_simple(of_node,
 					gpiochip->ngpio, first_irq,
 					&gpiochip_domain_ops, gpiochip);
-	if (!gpiochip->irqdomain) {
+	if (!gpiochip->irq.domain) {
 		gpiochip->irq.chip = NULL;
 		return -EINVAL;
 	}
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index 0944310225db..72d122748293 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -383,7 +383,7 @@ static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
 		/* FIXME: no clue why the code looks up the type here */
 		type = pc->irq_type[gpio];
 
-		generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irqdomain,
+		generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irq.domain,
 						     gpio));
 	}
 }
@@ -665,7 +665,7 @@ static void bcm2835_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
 	enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset);
 	const char *fname = bcm2835_functions[fsel];
 	int value = bcm2835_gpio_get_bit(pc, GPLEV0, offset);
-	int irq = irq_find_mapping(chip->irqdomain, offset);
+	int irq = irq_find_mapping(chip->irq.domain, offset);
 
 	seq_printf(s, "function %s in %s; irq %d (%s)",
 		fname, value ? "hi" : "lo",
diff --git a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
index 85a8c97d9dfe..b93f62dc8733 100644
--- a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
+++ b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
@@ -172,7 +172,7 @@ static void iproc_gpio_irq_handler(struct irq_desc *desc)
 
 		for_each_set_bit(bit, &val, NGPIOS_PER_BANK) {
 			unsigned pin = NGPIOS_PER_BANK * i + bit;
-			int child_irq = irq_find_mapping(gc->irqdomain, pin);
+			int child_irq = irq_find_mapping(gc->irq.domain, pin);
 
 			/*
 			 * Clear the interrupt before invoking the
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index 0f3a02495aeb..5897981e5ed3 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -1627,7 +1627,7 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
 		pending = readl(reg);
 		raw_spin_unlock(&vg->lock);
 		for_each_set_bit(pin, &pending, 32) {
-			virq = irq_find_mapping(vg->chip.irqdomain, base + pin);
+			virq = irq_find_mapping(vg->chip.irq.domain, base + pin);
 			generic_handle_irq(virq);
 		}
 	}
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 04e929fd0ffe..1cd7043edbc1 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -1523,7 +1523,7 @@ static void chv_gpio_irq_handler(struct irq_desc *desc)
 		unsigned irq, offset;
 
 		offset = pctrl->intr_lines[intr_line];
-		irq = irq_find_mapping(gc->irqdomain, offset);
+		irq = irq_find_mapping(gc->irq.domain, offset);
 		generic_handle_irq(irq);
 	}
 
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 8f8721538616..e4e167650f8a 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -1000,7 +1000,7 @@ static irqreturn_t intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
 			if (padno >= community->npins)
 				break;
 
-			irq = irq_find_mapping(gc->irqdomain,
+			irq = irq_find_mapping(gc->irq.domain,
 					       community->pin_base + padno);
 			generic_handle_irq(irq);
 
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
index b8b6ab072cd0..e66ff18ee362 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -592,7 +592,7 @@ static void armada_37xx_irq_handler(struct irq_desc *desc)
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct armada_37xx_pinctrl *info = gpiochip_get_data(gc);
-	struct irq_domain *d = gc->irqdomain;
+	struct irq_domain *d = gc->irq.domain;
 	int i;
 
 	chained_irq_enter(chip, desc);
diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
index a53f1a9b1ed2..f0e7a8c114b2 100644
--- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c
+++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
@@ -413,7 +413,7 @@ nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset)
 	u32 falling = nmk_chip->fimsc & BIT(offset);
 	u32 rising = nmk_chip->rimsc & BIT(offset);
 	int gpio = nmk_chip->chip.base + offset;
-	int irq = irq_find_mapping(nmk_chip->chip.irqdomain, offset);
+	int irq = irq_find_mapping(nmk_chip->chip.irq.domain, offset);
 	struct irq_data *d = irq_get_irq_data(irq);
 
 	if (!rising && !falling)
@@ -815,7 +815,7 @@ static void __nmk_gpio_irq_handler(struct irq_desc *desc, u32 status)
 	while (status) {
 		int bit = __ffs(status);
 
-		generic_handle_irq(irq_find_mapping(chip->irqdomain, bit));
+		generic_handle_irq(irq_find_mapping(chip->irq.domain, bit));
 		status &= ~BIT(bit);
 	}
 
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 38af1ec2df0c..11f05f1e33b3 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -531,7 +531,7 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
 			regval = readl(regs + i);
 			if (!(regval & PIN_IRQ_PENDING))
 				continue;
-			irq = irq_find_mapping(gc->irqdomain, irqnr + i);
+			irq = irq_find_mapping(gc->irq.domain, irqnr + i);
 			generic_handle_irq(irq);
 			/* Clear interrupt */
 			writel(regval, regs + i);
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index 569bc28cb909..03492e3c09fa 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -1603,7 +1603,7 @@ static void gpio_irq_handler(struct irq_desc *desc)
 
 		for_each_set_bit(n, &isr, BITS_PER_LONG) {
 			generic_handle_irq(irq_find_mapping(
-					   gpio_chip->irqdomain, n));
+					   gpio_chip->irq.domain, n));
 		}
 	}
 	chained_irq_exit(chip, desc);
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index ac155e7d3412..7939b178c6ae 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -517,7 +517,7 @@ static void u300_gpio_irq_handler(struct irq_desc *desc)
 
 		for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) {
 			int offset = pinoffset + irqoffset;
-			int pin_irq = irq_find_mapping(chip->irqdomain, offset);
+			int pin_irq = irq_find_mapping(chip->irq.domain, offset);
 
 			dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n",
 				pin_irq, offset);
diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c
index 3e40d4245512..db19a2f2f575 100644
--- a/drivers/pinctrl/pinctrl-mcp23s08.c
+++ b/drivers/pinctrl/pinctrl-mcp23s08.c
@@ -537,7 +537,7 @@ static irqreturn_t mcp23s08_irq(int irq, void *data)
 		    ((gpio_bit_changed || intcap_changed) &&
 			(BIT(i) & mcp->irq_fall) && !gpio_set) ||
 		    defval_changed) {
-			child_irq = irq_find_mapping(mcp->chip.irqdomain, i);
+			child_irq = irq_find_mapping(mcp->chip.irq.domain, i);
 			handle_nested_irq(child_irq);
 		}
 	}
diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c
index 494ec9a7573a..53ec22a51f5c 100644
--- a/drivers/pinctrl/pinctrl-oxnas.c
+++ b/drivers/pinctrl/pinctrl-oxnas.c
@@ -1064,7 +1064,7 @@ static void oxnas_gpio_irq_handler(struct irq_desc *desc)
 	stat = readl(bank->reg_base + IRQ_PENDING);
 
 	for_each_set_bit(pin, &stat, BITS_PER_LONG)
-		generic_handle_irq(irq_linear_revmap(gc->irqdomain, pin));
+		generic_handle_irq(irq_linear_revmap(gc->irq.domain, pin));
 
 	chained_irq_exit(chip, desc);
 }
diff --git a/drivers/pinctrl/pinctrl-pic32.c b/drivers/pinctrl/pinctrl-pic32.c
index 31ceb958b3fe..96390228d388 100644
--- a/drivers/pinctrl/pinctrl-pic32.c
+++ b/drivers/pinctrl/pinctrl-pic32.c
@@ -2106,7 +2106,7 @@ static void pic32_gpio_irq_handler(struct irq_desc *desc)
 	pending = pic32_gpio_get_pending(gc, stat);
 
 	for_each_set_bit(pin, &pending, BITS_PER_LONG)
-		generic_handle_irq(irq_linear_revmap(gc->irqdomain, pin));
+		generic_handle_irq(irq_linear_revmap(gc->irq.domain, pin));
 
 	chained_irq_exit(chip, desc);
 }
diff --git a/drivers/pinctrl/pinctrl-pistachio.c b/drivers/pinctrl/pinctrl-pistachio.c
index 55375b1b3cc8..302190d1558d 100644
--- a/drivers/pinctrl/pinctrl-pistachio.c
+++ b/drivers/pinctrl/pinctrl-pistachio.c
@@ -1307,7 +1307,7 @@ static void pistachio_gpio_irq_handler(struct irq_desc *desc)
 	pending = gpio_readl(bank, GPIO_INTERRUPT_STATUS) &
 		gpio_readl(bank, GPIO_INTERRUPT_EN);
 	for_each_set_bit(pin, &pending, 16)
-		generic_handle_irq(irq_linear_revmap(gc->irqdomain, pin));
+		generic_handle_irq(irq_linear_revmap(gc->irq.domain, pin));
 	chained_irq_exit(chip, desc);
 }
 
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
index a5205b94b2e6..2081c67667a8 100644
--- a/drivers/pinctrl/pinctrl-st.c
+++ b/drivers/pinctrl/pinctrl-st.c
@@ -1408,7 +1408,7 @@ static void __gpio_irq_handler(struct st_gpio_bank *bank)
 					continue;
 			}
 
-			generic_handle_irq(irq_find_mapping(bank->gpio_chip.irqdomain, n));
+			generic_handle_irq(irq_find_mapping(bank->gpio_chip.irq.domain, n));
 		}
 	}
 }
diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c
index 7450f5118445..7db4f6a6eb17 100644
--- a/drivers/pinctrl/pinctrl-sx150x.c
+++ b/drivers/pinctrl/pinctrl-sx150x.c
@@ -561,7 +561,7 @@ static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id)
 
 	status = val;
 	for_each_set_bit(n, &status, pctl->data->ngpios)
-		handle_nested_irq(irq_find_mapping(pctl->gpio.irqdomain, n));
+		handle_nested_irq(irq_find_mapping(pctl->gpio.irq.domain, n));
 
 	return IRQ_HANDLED;
 }
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index ff491da64dab..7a960590ecaa 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -795,7 +795,7 @@ static void msm_gpio_irq_handler(struct irq_desc *desc)
 		g = &pctrl->soc->groups[i];
 		val = readl(pctrl->regs + g->intr_status_reg);
 		if (val & BIT(g->intr_status_bit)) {
-			irq_pin = irq_find_mapping(gc->irqdomain, i);
+			irq_pin = irq_find_mapping(gc->irq.domain, i);
 			generic_handle_irq(irq_pin);
 			handled++;
 		}
diff --git a/drivers/pinctrl/sirf/pinctrl-atlas7.c b/drivers/pinctrl/sirf/pinctrl-atlas7.c
index 4db9323251e3..f5cef6e5fa3e 100644
--- a/drivers/pinctrl/sirf/pinctrl-atlas7.c
+++ b/drivers/pinctrl/sirf/pinctrl-atlas7.c
@@ -5820,7 +5820,7 @@ static void atlas7_gpio_handle_irq(struct irq_desc *desc)
 				__func__, gc->label,
 				bank->gpio_offset + pin_in_bank);
 			generic_handle_irq(
-				irq_find_mapping(gc->irqdomain,
+				irq_find_mapping(gc->irq.domain,
 					bank->gpio_offset + pin_in_bank));
 		}
 
diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c
index d3ef05973901..8b14a1f1e671 100644
--- a/drivers/pinctrl/sirf/pinctrl-sirf.c
+++ b/drivers/pinctrl/sirf/pinctrl-sirf.c
@@ -587,7 +587,7 @@ static void sirfsoc_gpio_handle_irq(struct irq_desc *desc)
 		if ((status & 0x1) && (ctrl & SIRFSOC_GPIO_CTL_INTR_EN_MASK)) {
 			pr_debug("%s: gpio id %d idx %d happens\n",
 				__func__, bank->id, idx);
-			generic_handle_irq(irq_find_mapping(gc->irqdomain, idx +
+			generic_handle_irq(irq_find_mapping(gc->irq.domain, idx +
 					bank->id * SIRFSOC_GPIO_BANK_SIZE));
 		}
 
diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c
index cf6d68c7345b..72ae6bccee55 100644
--- a/drivers/pinctrl/spear/pinctrl-plgpio.c
+++ b/drivers/pinctrl/spear/pinctrl-plgpio.c
@@ -401,7 +401,7 @@ static void plgpio_irq_handler(struct irq_desc *desc)
 			/* get correct irq line number */
 			pin = i * MAX_GPIO_PER_REG + pin;
 			generic_handle_irq(
-				irq_find_mapping(gc->irqdomain, pin));
+				irq_find_mapping(gc->irq.domain, pin));
 		}
 	}
 	chained_irq_exit(irqchip, desc);
diff --git a/drivers/platform/x86/intel_int0002_vgpio.c b/drivers/platform/x86/intel_int0002_vgpio.c
index 92dc230ef5b2..f6b3af73dea5 100644
--- a/drivers/platform/x86/intel_int0002_vgpio.c
+++ b/drivers/platform/x86/intel_int0002_vgpio.c
@@ -119,7 +119,7 @@ static irqreturn_t int0002_irq(int irq, void *data)
 	if (!(gpe_sts_reg & GPE0A_PME_B0_STS_BIT))
 		return IRQ_NONE;
 
-	generic_handle_irq(irq_find_mapping(chip->irqdomain,
+	generic_handle_irq(irq_find_mapping(chip->irq.domain,
 					    GPE0A_PME_B0_VIRT_GPIO_PIN));
 
 	pm_system_wakeup();
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 974247646886..031037bb8670 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -32,6 +32,14 @@ struct gpio_irq_chip {
 	struct irq_chip *chip;
 
 	/**
+	 * @domain:
+	 *
+	 * Interrupt translation domain; responsible for mapping between GPIO
+	 * hwirq number and Linux IRQ number.
+	 */
+	struct irq_domain *domain;
+
+	/**
 	 * @domain_ops:
 	 *
 	 * Table of interrupt domain operations for this IRQ chip.
@@ -144,8 +152,6 @@ static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)
  *	safely.
  * @bgpio_dir: shadowed direction register for generic GPIO to clear/set
  *	direction safely.
- * @irqdomain: Interrupt translation domain; responsible for mapping
- *	between GPIO hwirq number and linux irq number
  * @irq_base: first linux IRQ number assigned to GPIO IRQ chip (deprecated)
  * @irq_handler: the irq handler to use (often a predefined irq core function)
  *	for GPIO IRQs, provided by GPIO driver
@@ -226,7 +232,6 @@ struct gpio_chip {
 	 * With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
 	 * to handle IRQs for most practical cases.
 	 */
-	struct irq_domain	*irqdomain;
 	unsigned int		irq_base;
 	irq_flow_handler_t	irq_handler;
 	unsigned int		irq_default_type;
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 04/16] gpio: Move irq_base to struct gpio_irq_chip
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
                   ` (2 preceding siblings ...)
  2017-09-01 18:57 ` [PATCH 03/16] gpio: Move irqdomain " Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-01 18:57 ` [PATCH 05/16] gpio: Move irq_handler " Thierry Reding
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

In order to consolidate the multiple ways to associate an IRQ chip with
a GPIO chip, move more fields into the new struct gpio_irq_chip.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpio/gpiolib.c                      |  2 +-
 drivers/pinctrl/mvebu/pinctrl-armada-37xx.c |  2 +-
 include/linux/gpio/driver.h                 | 10 ++++++++--
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index d8ea8a292978..e5ad28978d5c 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1781,7 +1781,7 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip)
 		ops = &gpiochip_domain_ops;
 
 	gpiochip->irq.domain = irq_domain_add_simple(np, gpiochip->ngpio,
-						     gpiochip->irq_base,
+						     gpiochip->irq.first,
 						     ops, gpiochip);
 	if (!gpiochip->irq.domain)
 		return -EINVAL;
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
index e66ff18ee362..8df8a4998f48 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -681,7 +681,7 @@ static int armada_37xx_irqchip_register(struct platform_device *pdev,
 	 * the chained irq with all of them.
 	 */
 	for (i = 0; i < nrirqs; i++) {
-		struct irq_data *d = irq_get_irq_data(gc->irq_base + i);
+		struct irq_data *d = irq_get_irq_data(gc->irq.first + i);
 
 		/*
 		 * The mask field is a "precomputed bitmask for
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 031037bb8670..9389406df0b1 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -47,6 +47,14 @@ struct gpio_irq_chip {
 	const struct irq_domain_ops *domain_ops;
 
 	/**
+	 * @first:
+	 *
+	 * If not dynamically assigned, the base (first) IRQ to allocate GPIO
+	 * chip IRQs from (deprecated).
+	 */
+	unsigned int first;
+
+	/**
 	 * @parent_handler:
 	 *
 	 * The interrupt handler for the GPIO chip's parent interrupts, may be
@@ -152,7 +160,6 @@ static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)
  *	safely.
  * @bgpio_dir: shadowed direction register for generic GPIO to clear/set
  *	direction safely.
- * @irq_base: first linux IRQ number assigned to GPIO IRQ chip (deprecated)
  * @irq_handler: the irq handler to use (often a predefined irq core function)
  *	for GPIO IRQs, provided by GPIO driver
  * @irq_default_type: default IRQ triggering type applied during GPIO driver
@@ -232,7 +239,6 @@ struct gpio_chip {
 	 * With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
 	 * to handle IRQs for most practical cases.
 	 */
-	unsigned int		irq_base;
 	irq_flow_handler_t	irq_handler;
 	unsigned int		irq_default_type;
 	unsigned int		irq_chained_parent;
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 05/16] gpio: Move irq_handler to struct gpio_irq_chip
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
                   ` (3 preceding siblings ...)
  2017-09-01 18:57 ` [PATCH 04/16] gpio: Move irq_base to " Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-01 18:57 ` [PATCH 06/16] gpio: Move irq_default_type " Thierry Reding
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

In order to consolidate the multiple ways to associate an IRQ chip with
a GPIO chip, move more fields into the new struct gpio_irq_chip.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpio/gpiolib.c      |  4 ++--
 include/linux/gpio/driver.h | 11 ++++++++---
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index e5ad28978d5c..75fa734cfa98 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1656,7 +1656,7 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
 	 * 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->irq.chip, chip->irq_handler);
+	irq_set_chip_and_handler(irq, chip->irq.chip, chip->irq.handler);
 	/* Chips that use nested thread handlers have them marked */
 	if (chip->irq_nested)
 		irq_set_nested_thread(irq, 1);
@@ -1960,7 +1960,7 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
 	}
 
 	gpiochip->irq.chip = irqchip;
-	gpiochip->irq_handler = handler;
+	gpiochip->irq.handler = handler;
 	gpiochip->irq_default_type = type;
 	gpiochip->to_irq = gpiochip_to_irq;
 	gpiochip->lock_key = lock_key;
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 9389406df0b1..b1398ea0c32a 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -55,6 +55,14 @@ struct gpio_irq_chip {
 	unsigned int first;
 
 	/**
+	 * @handler:
+	 *
+	 * The IRQ handler to use (often a predefined IRQ core function) for
+	 * GPIO IRQs, provided by GPIO driver.
+	 */
+	irq_flow_handler_t handler;
+
+	/**
 	 * @parent_handler:
 	 *
 	 * The interrupt handler for the GPIO chip's parent interrupts, may be
@@ -160,8 +168,6 @@ static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)
  *	safely.
  * @bgpio_dir: shadowed direction register for generic GPIO to clear/set
  *	direction safely.
- * @irq_handler: the irq handler to use (often a predefined irq core function)
- *	for GPIO IRQs, provided by GPIO driver
  * @irq_default_type: default IRQ triggering type applied during GPIO driver
  *	initialization, provided by GPIO driver
  * @irq_chained_parent: GPIO IRQ chip parent/bank linux irq number,
@@ -239,7 +245,6 @@ struct gpio_chip {
 	 * With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
 	 * to handle IRQs for most practical cases.
 	 */
-	irq_flow_handler_t	irq_handler;
 	unsigned int		irq_default_type;
 	unsigned int		irq_chained_parent;
 	bool			irq_nested;
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 06/16] gpio: Move irq_default_type to struct gpio_irq_chip
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
                   ` (4 preceding siblings ...)
  2017-09-01 18:57 ` [PATCH 05/16] gpio: Move irq_handler " Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-01 18:57 ` [PATCH 07/16] gpio: Move irq_chained_parent " Thierry Reding
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

In order to consolidate the multiple ways to associate an IRQ chip with
a GPIO chip, move more fields into the new struct gpio_irq_chip.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpio/gpiolib.c      | 10 +++++-----
 include/linux/gpio/driver.h | 11 ++++++++---
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 75fa734cfa98..774d6047116a 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1666,8 +1666,8 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
 	 * No set-up of the hardware will happen if IRQ_TYPE_NONE
 	 * is passed as default type.
 	 */
-	if (chip->irq_default_type != IRQ_TYPE_NONE)
-		irq_set_irq_type(irq, chip->irq_default_type);
+	if (chip->irq.default_type != IRQ_TYPE_NONE)
+		irq_set_irq_type(irq, chip->irq.default_type);
 
 	return 0;
 }
@@ -1744,7 +1744,7 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip)
 		return -EINVAL;
 	}
 
-	type = gpiochip->irq_default_type;
+	type = gpiochip->irq.default_type;
 	np = gpiochip->parent->of_node;
 
 #ifdef CONFIG_OF_GPIO
@@ -1773,7 +1773,7 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip)
 	}
 
 	gpiochip->to_irq = gpiochip_to_irq;
-	gpiochip->irq_default_type = type;
+	gpiochip->irq.default_type = type;
 
 	if (gpiochip->irq.domain_ops)
 		ops = gpiochip->irq.domain_ops;
@@ -1961,7 +1961,7 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
 
 	gpiochip->irq.chip = irqchip;
 	gpiochip->irq.handler = handler;
-	gpiochip->irq_default_type = type;
+	gpiochip->irq.default_type = type;
 	gpiochip->to_irq = gpiochip_to_irq;
 	gpiochip->lock_key = lock_key;
 	gpiochip->irq.domain = irq_domain_add_simple(of_node,
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index b1398ea0c32a..bcf93afddfa6 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -63,6 +63,14 @@ struct gpio_irq_chip {
 	irq_flow_handler_t handler;
 
 	/**
+	 * @default_type:
+	 *
+	 * Default IRQ triggering type applied during GPIO driver
+	 * initialization, provided by GPIO driver.
+	 */
+	unsigned int default_type;
+
+	/**
 	 * @parent_handler:
 	 *
 	 * The interrupt handler for the GPIO chip's parent interrupts, may be
@@ -168,8 +176,6 @@ static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)
  *	safely.
  * @bgpio_dir: shadowed direction register for generic GPIO to clear/set
  *	direction safely.
- * @irq_default_type: default IRQ triggering type applied during GPIO driver
- *	initialization, provided by GPIO driver
  * @irq_chained_parent: GPIO IRQ chip parent/bank linux irq number,
  *	provided by GPIO driver for chained interrupt (not for nested
  *	interrupts).
@@ -245,7 +251,6 @@ struct gpio_chip {
 	 * With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
 	 * to handle IRQs for most practical cases.
 	 */
-	unsigned int		irq_default_type;
 	unsigned int		irq_chained_parent;
 	bool			irq_nested;
 	bool			irq_need_valid_mask;
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 07/16] gpio: Move irq_chained_parent to struct gpio_irq_chip
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
                   ` (5 preceding siblings ...)
  2017-09-01 18:57 ` [PATCH 06/16] gpio: Move irq_default_type " Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-01 18:57 ` [PATCH 08/16] gpio: Move irq_nested into " Thierry Reding
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

In order to consolidate the multiple ways to associate an IRQ chip with
a GPIO chip, move more fields into the new struct gpio_irq_chip.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpio/gpiolib.c      | 8 ++------
 include/linux/gpio/driver.h | 4 ----
 2 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 774d6047116a..f09cc89929f0 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1580,7 +1580,8 @@ static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip,
 		irq_set_chained_handler_and_data(parent_irq, parent_handler,
 						 gpiochip);
 
-		gpiochip->irq_chained_parent = parent_irq;
+		gpiochip->irq.parents = &parent_irq;
+		gpiochip->irq.num_parents = 1;
 	}
 
 	/* Set the parent IRQ for all affected IRQs */
@@ -1853,11 +1854,6 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
 
 	acpi_gpiochip_free_interrupts(gpiochip);
 
-	if (gpiochip->irq_chained_parent) {
-		irq_set_chained_handler(gpiochip->irq_chained_parent, NULL);
-		irq_set_handler_data(gpiochip->irq_chained_parent, NULL);
-	}
-
 	if (gpiochip->irq.chip) {
 		struct gpio_irq_chip *irq = &gpiochip->irq;
 		unsigned int i;
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index bcf93afddfa6..c3eafd874884 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -176,9 +176,6 @@ static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)
  *	safely.
  * @bgpio_dir: shadowed direction register for generic GPIO to clear/set
  *	direction safely.
- * @irq_chained_parent: GPIO IRQ chip parent/bank linux irq number,
- *	provided by GPIO driver for chained interrupt (not for nested
- *	interrupts).
  * @irq_nested: True if set the interrupt handling is nested.
  * @irq_need_valid_mask: If set core allocates @irq_valid_mask with all
  *	bits set to one
@@ -251,7 +248,6 @@ struct gpio_chip {
 	 * With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
 	 * to handle IRQs for most practical cases.
 	 */
-	unsigned int		irq_chained_parent;
 	bool			irq_nested;
 	bool			irq_need_valid_mask;
 	unsigned long		*irq_valid_mask;
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 08/16] gpio: Move irq_nested into struct gpio_irq_chip
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
                   ` (6 preceding siblings ...)
  2017-09-01 18:57 ` [PATCH 07/16] gpio: Move irq_chained_parent " Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-01 18:57 ` [PATCH 09/16] gpio: Move irq_valid_mask " Thierry Reding
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

In order to consolidate the multiple ways to associate an IRQ chip with
a GPIO chip, move more fields into the new struct gpio_irq_chip.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpio/gpiolib.c      | 12 ++++++------
 include/linux/gpio/driver.h |  9 +++++++--
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index f09cc89929f0..f506473f5c70 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1624,7 +1624,7 @@ void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
 				 struct irq_chip *irqchip,
 				 unsigned int parent_irq)
 {
-	if (!gpiochip->irq_nested) {
+	if (!gpiochip->irq.nested) {
 		chip_err(gpiochip, "tried to nest a chained gpiochip\n");
 		return;
 	}
@@ -1659,7 +1659,7 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
 	irq_set_lockdep_class(irq, chip->lock_key);
 	irq_set_chip_and_handler(irq, chip->irq.chip, chip->irq.handler);
 	/* Chips that use nested thread handlers have them marked */
-	if (chip->irq_nested)
+	if (chip->irq.nested)
 		irq_set_nested_thread(irq, 1);
 	irq_set_noprobe(irq);
 
@@ -1678,7 +1678,7 @@ void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
 {
 	struct gpio_chip *chip = d->host_data;
 
-	if (chip->irq_nested)
+	if (chip->irq.nested)
 		irq_set_nested_thread(irq, 0);
 	irq_set_chip_and_handler(irq, NULL, NULL);
 	irq_set_chip_data(irq, NULL);
@@ -1811,9 +1811,9 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip)
 							 data);
 		}
 
-		gpiochip->irq_nested = false;
+		gpiochip->irq.nested = false;
 	} else {
-		gpiochip->irq_nested = true;
+		gpiochip->irq.nested = true;
 	}
 
 	/*
@@ -1930,7 +1930,7 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
 		pr_err("missing gpiochip .dev parent pointer\n");
 		return -EINVAL;
 	}
-	gpiochip->irq_nested = nested;
+	gpiochip->irq.nested = nested;
 	of_node = gpiochip->parent->of_node;
 #ifdef CONFIG_OF_GPIO
 	/*
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index c3eafd874884..7d632a8932be 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -107,6 +107,13 @@ struct gpio_irq_chip {
 	 * A list of interrupt parents for each line of a GPIO chip.
 	 */
 	unsigned int *map;
+
+	/**
+	 * @nested:
+	 *
+	 * True if set the interrupt handling is nested.
+	 */
+	bool nested;
 };
 
 static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)
@@ -176,7 +183,6 @@ static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)
  *	safely.
  * @bgpio_dir: shadowed direction register for generic GPIO to clear/set
  *	direction safely.
- * @irq_nested: True if set the interrupt handling is nested.
  * @irq_need_valid_mask: If set core allocates @irq_valid_mask with all
  *	bits set to one
  * @irq_valid_mask: If not %NULL holds bitmask of GPIOs which are valid to
@@ -248,7 +254,6 @@ struct gpio_chip {
 	 * With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
 	 * to handle IRQs for most practical cases.
 	 */
-	bool			irq_nested;
 	bool			irq_need_valid_mask;
 	unsigned long		*irq_valid_mask;
 	struct lock_class_key	*lock_key;
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 09/16] gpio: Move irq_valid_mask into struct gpio_irq_chip
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
                   ` (7 preceding siblings ...)
  2017-09-01 18:57 ` [PATCH 08/16] gpio: Move irq_nested into " Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-01 18:57 ` [PATCH 10/16] gpio: Move lock_key " Thierry Reding
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

In order to consolidate the multiple ways to associate an IRQ chip with
a GPIO chip, move more fields into the new struct gpio_irq_chip.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 Documentation/gpio/driver.txt              |  4 ++--
 drivers/gpio/gpio-aspeed.c                 |  4 ++--
 drivers/gpio/gpio-stmpe.c                  |  4 ++--
 drivers/gpio/gpiolib.c                     | 16 ++++++++--------
 drivers/pinctrl/intel/pinctrl-baytrail.c   |  4 ++--
 drivers/pinctrl/intel/pinctrl-cherryview.c |  4 ++--
 drivers/platform/x86/intel_int0002_vgpio.c |  4 ++--
 include/linux/gpio/driver.h                | 21 +++++++++++++++------
 8 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt
index dcf6af1d9e56..d8de1c7de85a 100644
--- a/Documentation/gpio/driver.txt
+++ b/Documentation/gpio/driver.txt
@@ -313,8 +313,8 @@ symbol:
   mark all the child IRQs as having the other IRQ as parent.
 
 If there is a need to exclude certain GPIOs from the IRQ domain, you can
-set .irq_need_valid_mask of the gpiochip before gpiochip_add_data() is
-called. This allocates an .irq_valid_mask with as many bits set as there
+set .irq.need_valid_mask of the gpiochip before gpiochip_add_data() is
+called. This allocates an .irq.valid_mask with as many bits set as there
 are GPIOs in the chip. Drivers can exclude GPIOs by clearing bits from this
 mask. The mask must be filled in before gpiochip_irqchip_add() or
 gpiochip_irqchip_add_nested() is called.
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index a9342b471359..fbd551a0c634 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -498,7 +498,7 @@ static void set_irq_valid_mask(struct aspeed_gpio *gpio)
 			if (i >= gpio->config->nr_gpios)
 				break;
 
-			clear_bit(i, gpio->chip.irq_valid_mask);
+			clear_bit(i, gpio->chip.irq.valid_mask);
 		}
 
 		props++;
@@ -853,7 +853,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
 	gpio->chip.set_config = aspeed_gpio_set_config;
 	gpio->chip.label = dev_name(&pdev->dev);
 	gpio->chip.base = -1;
-	gpio->chip.irq_need_valid_mask = true;
+	gpio->chip.irq.need_valid_mask = true;
 
 	rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
 	if (rc < 0)
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index 5aee24fe0254..5b99ff7e75ef 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -451,7 +451,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
 	of_property_read_u32(np, "st,norequest-mask",
 			&stmpe_gpio->norequest_mask);
 	if (stmpe_gpio->norequest_mask)
-		stmpe_gpio->chip.irq_need_valid_mask = true;
+		stmpe_gpio->chip.irq.need_valid_mask = true;
 
 	if (irq < 0)
 		dev_info(&pdev->dev,
@@ -482,7 +482,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
 			/* Forbid unused lines to be mapped as IRQs */
 			for (i = 0; i < sizeof(u32); i++)
 				if (stmpe_gpio->norequest_mask & BIT(i))
-					clear_bit(i, stmpe_gpio->chip.irq_valid_mask);
+					clear_bit(i, stmpe_gpio->chip.irq.valid_mask);
 		}
 		ret =  gpiochip_irqchip_add_nested(&stmpe_gpio->chip,
 						   &stmpe_gpio_irq_chip,
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index f506473f5c70..6cec36126f44 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1514,33 +1514,33 @@ static struct gpio_chip *find_chip_by_name(const char *name)
 
 static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip)
 {
-	if (!gpiochip->irq_need_valid_mask)
+	if (!gpiochip->irq.need_valid_mask)
 		return 0;
 
-	gpiochip->irq_valid_mask = kcalloc(BITS_TO_LONGS(gpiochip->ngpio),
+	gpiochip->irq.valid_mask = kcalloc(BITS_TO_LONGS(gpiochip->ngpio),
 					   sizeof(long), GFP_KERNEL);
-	if (!gpiochip->irq_valid_mask)
+	if (!gpiochip->irq.valid_mask)
 		return -ENOMEM;
 
 	/* Assume by default all GPIOs are valid */
-	bitmap_fill(gpiochip->irq_valid_mask, gpiochip->ngpio);
+	bitmap_fill(gpiochip->irq.valid_mask, gpiochip->ngpio);
 
 	return 0;
 }
 
 static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip)
 {
-	kfree(gpiochip->irq_valid_mask);
-	gpiochip->irq_valid_mask = NULL;
+	kfree(gpiochip->irq.valid_mask);
+	gpiochip->irq.valid_mask = NULL;
 }
 
 static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
 				       unsigned int offset)
 {
 	/* No mask means all valid */
-	if (likely(!gpiochip->irq_valid_mask))
+	if (likely(!gpiochip->irq.valid_mask))
 		return true;
-	return test_bit(offset, gpiochip->irq_valid_mask);
+	return test_bit(offset, gpiochip->irq.valid_mask);
 }
 
 /**
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index 5897981e5ed3..9c1ca29c60b7 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -1660,7 +1660,7 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
 
 		value = readl(reg);
 		if (value & BYT_DIRECT_IRQ_EN) {
-			clear_bit(i, gc->irq_valid_mask);
+			clear_bit(i, gc->irq.valid_mask);
 			dev_dbg(dev, "excluding GPIO %d from IRQ domain\n", i);
 		} else if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i)) {
 			byt_gpio_clear_triggering(vg, i);
@@ -1703,7 +1703,7 @@ static int byt_gpio_probe(struct byt_gpio *vg)
 	gc->can_sleep	= false;
 	gc->parent	= &vg->pdev->dev;
 	gc->ngpio	= vg->soc_data->npins;
-	gc->irq_need_valid_mask	= true;
+	gc->irq.need_valid_mask	= true;
 
 #ifdef CONFIG_PM_SLEEP
 	vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio,
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 1cd7043edbc1..e23def322de2 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -1584,7 +1584,7 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
 	chip->label = dev_name(pctrl->dev);
 	chip->parent = pctrl->dev;
 	chip->base = -1;
-	chip->irq_need_valid_mask = need_valid_mask;
+	chip->irq.need_valid_mask = need_valid_mask;
 
 	ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl);
 	if (ret) {
@@ -1616,7 +1616,7 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
 		intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
 
 		if (need_valid_mask && intsel >= pctrl->community->nirqs)
-			clear_bit(i, chip->irq_valid_mask);
+			clear_bit(i, chip->irq.valid_mask);
 	}
 
 	/* Clear all interrupts */
diff --git a/drivers/platform/x86/intel_int0002_vgpio.c b/drivers/platform/x86/intel_int0002_vgpio.c
index f6b3af73dea5..f7b67e898abc 100644
--- a/drivers/platform/x86/intel_int0002_vgpio.c
+++ b/drivers/platform/x86/intel_int0002_vgpio.c
@@ -165,7 +165,7 @@ static int int0002_probe(struct platform_device *pdev)
 	chip->direction_output = int0002_gpio_direction_output;
 	chip->base = -1;
 	chip->ngpio = GPE0A_PME_B0_VIRT_GPIO_PIN + 1;
-	chip->irq_need_valid_mask = true;
+	chip->irq.need_valid_mask = true;
 
 	ret = devm_gpiochip_add_data(&pdev->dev, chip, NULL);
 	if (ret) {
@@ -173,7 +173,7 @@ static int int0002_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	bitmap_clear(chip->irq_valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN);
+	bitmap_clear(chip->irq.valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN);
 
 	/*
 	 * We manually request the irq here instead of passing a flow-handler
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 7d632a8932be..f8d31e7da9cc 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -114,6 +114,21 @@ struct gpio_irq_chip {
 	 * True if set the interrupt handling is nested.
 	 */
 	bool nested;
+
+	/**
+	 * @need_valid_mask:
+	 *
+	 * If set core allocates @valid_mask with all bits set to one.
+	 */
+	bool need_valid_mask;
+
+	/**
+	 * @valid_mask:
+	 *
+	 * If not %NULL holds bitmask of GPIOs which are valid to be included
+	 * in IRQ domain of the chip.
+	 */
+	unsigned long *valid_mask;
 };
 
 static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)
@@ -183,10 +198,6 @@ static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)
  *	safely.
  * @bgpio_dir: shadowed direction register for generic GPIO to clear/set
  *	direction safely.
- * @irq_need_valid_mask: If set core allocates @irq_valid_mask with all
- *	bits set to one
- * @irq_valid_mask: If not %NULL holds bitmask of GPIOs which are valid to
- *	be included in IRQ domain of the chip
  * @lock_key: per GPIO IRQ chip lockdep class
  *
  * A gpio_chip can help platforms abstract various sources of GPIOs so
@@ -254,8 +265,6 @@ struct gpio_chip {
 	 * With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
 	 * to handle IRQs for most practical cases.
 	 */
-	bool			irq_need_valid_mask;
-	unsigned long		*irq_valid_mask;
 	struct lock_class_key	*lock_key;
 
 	/**
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 10/16] gpio: Move lock_key into struct gpio_irq_chip
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
                   ` (8 preceding siblings ...)
  2017-09-01 18:57 ` [PATCH 09/16] gpio: Move irq_valid_mask " Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-01 18:57 ` [PATCH 11/16] gpio: Add Tegra186 support Thierry Reding
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

In order to consolidate the multiple ways to associate an IRQ chip with
a GPIO chip, move more fields into the new struct gpio_irq_chip.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpio/gpiolib.c      | 4 ++--
 include/linux/gpio/driver.h | 9 +++++++--
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 6cec36126f44..7a16dd37bd3d 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1656,7 +1656,7 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
 	 * 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_lockdep_class(irq, chip->irq.lock_key);
 	irq_set_chip_and_handler(irq, chip->irq.chip, chip->irq.handler);
 	/* Chips that use nested thread handlers have them marked */
 	if (chip->irq.nested)
@@ -1959,7 +1959,7 @@ int gpiochip_irqchip_add_key(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->irq.lock_key = lock_key;
 	gpiochip->irq.domain = irq_domain_add_simple(of_node,
 					gpiochip->ngpio, first_irq,
 					&gpiochip_domain_ops, gpiochip);
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index f8d31e7da9cc..c453e0716228 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -71,6 +71,13 @@ struct gpio_irq_chip {
 	unsigned int default_type;
 
 	/**
+	 * @lock_key:
+	 *
+	 * Per GPIO IRQ chip lockdep class.
+	 */
+	struct lock_class_key *lock_key;
+
+	/**
 	 * @parent_handler:
 	 *
 	 * The interrupt handler for the GPIO chip's parent interrupts, may be
@@ -198,7 +205,6 @@ static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)
  *	safely.
  * @bgpio_dir: shadowed direction register for generic GPIO to clear/set
  *	direction safely.
- * @lock_key: per GPIO IRQ chip lockdep class
  *
  * A gpio_chip can help platforms abstract various sources of GPIOs so
  * they can all be accessed through a common programing interface.
@@ -265,7 +271,6 @@ struct gpio_chip {
 	 * With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
 	 * to handle IRQs for most practical cases.
 	 */
-	struct lock_class_key	*lock_key;
 
 	/**
 	 * @irq:
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 11/16] gpio: Add Tegra186 support
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
                   ` (9 preceding siblings ...)
  2017-09-01 18:57 ` [PATCH 10/16] gpio: Move lock_key " Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-01 18:57 ` [PATCH 12/16] gpio: omap: Fix checkpatch warnings Thierry Reding
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

Tegra186 has two GPIO controllers that are largely register compatible
between one another but are completely different from the controller
found on earlier generations.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v4:
- use platform_irq_count() instead of of_irq_count()

Changes in v3:
- make use of GPIOLIB_IRQCHIP for IRQ chip handling

Changes in v2:
- add pin names to allow easy lookup using the chardev interface
- distinguish AON and main GPIO controllers by label
- use gpiochip_get_data() instead of container_of()
- use C99 initializers
---
 drivers/gpio/Kconfig         |   9 +
 drivers/gpio/Makefile        |   1 +
 drivers/gpio/gpio-tegra186.c | 624 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 634 insertions(+)
 create mode 100644 drivers/gpio/gpio-tegra186.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 3388d54ba114..f9e22c6fdd02 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -442,6 +442,15 @@ config GPIO_TEGRA
 	help
 	  Say yes here to support GPIO pins on NVIDIA Tegra SoCs.
 
+config GPIO_TEGRA186
+	tristate "NVIDIA Tegra186 GPIO support"
+	default ARCH_TEGRA_186_SOC
+	depends on ARCH_TEGRA_186_SOC || COMPILE_TEST
+	depends on OF_GPIO
+	select GPIOLIB_IRQCHIP
+	help
+	  Say yes here to support GPIO pins on NVIDIA Tegra186 SoCs.
+
 config GPIO_TS4800
 	tristate "TS-4800 DIO blocks and compatibles"
 	depends on OF_GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index aeb70e9de6f2..4cb7c9b93215 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -113,6 +113,7 @@ obj-$(CONFIG_GPIO_SYSCON)	+= gpio-syscon.o
 obj-$(CONFIG_GPIO_TB10X)	+= gpio-tb10x.o
 obj-$(CONFIG_GPIO_TC3589X)	+= gpio-tc3589x.o
 obj-$(CONFIG_GPIO_TEGRA)	+= gpio-tegra.o
+obj-$(CONFIG_GPIO_TEGRA186)	+= gpio-tegra186.o
 obj-$(CONFIG_GPIO_THUNDERX)	+= gpio-thunderx.o
 obj-$(CONFIG_GPIO_TIMBERDALE)	+= gpio-timberdale.o
 obj-$(CONFIG_GPIO_PALMAS)	+= gpio-palmas.o
diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
new file mode 100644
index 000000000000..162dc6b41ae8
--- /dev/null
+++ b/drivers/gpio/gpio-tegra186.c
@@ -0,0 +1,624 @@
+/*
+ * Copyright (c) 2016-2017 NVIDIA Corporation
+ *
+ * Author: Thierry Reding <treding@nvidia.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/gpio/tegra186-gpio.h>
+
+#define TEGRA186_GPIO_ENABLE_CONFIG 0x00
+#define  TEGRA186_GPIO_ENABLE_CONFIG_ENABLE BIT(0)
+#define  TEGRA186_GPIO_ENABLE_CONFIG_OUT BIT(1)
+#define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_NONE (0x0 << 2)
+#define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_LEVEL (0x1 << 2)
+#define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE (0x2 << 2)
+#define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_DOUBLE_EDGE (0x3 << 2)
+#define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_MASK (0x3 << 2)
+#define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL BIT(4)
+#define  TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT BIT(6)
+
+#define TEGRA186_GPIO_DEBOUNCE_CONTROL 0x04
+#define  TEGRA186_GPIO_DEBOUNCE_CONTROL_THRESHOLD(x) ((x) & 0xff)
+
+#define TEGRA186_GPIO_INPUT 0x08
+#define  TEGRA186_GPIO_INPUT_HIGH BIT(0)
+
+#define TEGRA186_GPIO_OUTPUT_CONTROL 0x0c
+#define  TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED BIT(0)
+
+#define TEGRA186_GPIO_OUTPUT_VALUE 0x10
+#define  TEGRA186_GPIO_OUTPUT_VALUE_HIGH BIT(0)
+
+#define TEGRA186_GPIO_INTERRUPT_CLEAR 0x14
+
+#define TEGRA186_GPIO_INTERRUPT_STATUS(x) (0x100 + (x) * 4)
+
+struct tegra_gpio_port {
+	const char *name;
+	unsigned int offset;
+	unsigned int pins;
+	unsigned int irq;
+};
+
+struct tegra_gpio_soc {
+	const struct tegra_gpio_port *ports;
+	unsigned int num_ports;
+	const char *name;
+};
+
+struct tegra_gpio {
+	struct gpio_chip gpio;
+	struct irq_chip intc;
+	unsigned int num_irq;
+	unsigned int *irq;
+
+	const struct tegra_gpio_soc *soc;
+
+	void __iomem *base;
+};
+
+static const struct tegra_gpio_port *
+tegra186_gpio_get_port(struct tegra_gpio *gpio, unsigned int *pin)
+{
+	unsigned int start = 0, i;
+
+	for (i = 0; i < gpio->soc->num_ports; i++) {
+		const struct tegra_gpio_port *port = &gpio->soc->ports[i];
+
+		if (*pin >= start && *pin < start + port->pins) {
+			*pin -= start;
+			return port;
+		}
+
+		start += port->pins;
+	}
+
+	return NULL;
+}
+
+static void __iomem *tegra186_gpio_get_base(struct tegra_gpio *gpio,
+					    unsigned int pin)
+{
+	const struct tegra_gpio_port *port;
+
+	port = tegra186_gpio_get_port(gpio, &pin);
+	if (!port)
+		return NULL;
+
+	return gpio->base + port->offset + pin * 0x20;
+}
+
+static int tegra186_gpio_get_direction(struct gpio_chip *chip,
+				       unsigned int offset)
+{
+	struct tegra_gpio *gpio = gpiochip_get_data(chip);
+	void __iomem *base;
+	u32 value;
+
+	base = tegra186_gpio_get_base(gpio, offset);
+	if (WARN_ON(base == NULL))
+		return -ENODEV;
+
+	value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
+	if (value & TEGRA186_GPIO_ENABLE_CONFIG_OUT)
+		return 0;
+
+	return 1;
+}
+
+static int tegra186_gpio_direction_input(struct gpio_chip *chip,
+					 unsigned int offset)
+{
+	struct tegra_gpio *gpio = gpiochip_get_data(chip);
+	void __iomem *base;
+	u32 value;
+
+	base = tegra186_gpio_get_base(gpio, offset);
+	if (WARN_ON(base == NULL))
+		return -ENODEV;
+
+	value = readl(base + TEGRA186_GPIO_OUTPUT_CONTROL);
+	value |= TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED;
+	writel(value, base + TEGRA186_GPIO_OUTPUT_CONTROL);
+
+	value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
+	value |= TEGRA186_GPIO_ENABLE_CONFIG_ENABLE;
+	value &= ~TEGRA186_GPIO_ENABLE_CONFIG_OUT;
+	writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);
+
+	return 0;
+}
+
+static int tegra186_gpio_direction_output(struct gpio_chip *chip,
+					  unsigned int offset, int level)
+{
+	struct tegra_gpio *gpio = gpiochip_get_data(chip);
+	void __iomem *base;
+	u32 value;
+
+	/* configure output level first */
+	chip->set(chip, offset, level);
+
+	base = tegra186_gpio_get_base(gpio, offset);
+	if (WARN_ON(base == NULL))
+		return -EINVAL;
+
+	/* set the direction */
+	value = readl(base + TEGRA186_GPIO_OUTPUT_CONTROL);
+	value &= ~TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED;
+	writel(value, base + TEGRA186_GPIO_OUTPUT_CONTROL);
+
+	value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
+	value |= TEGRA186_GPIO_ENABLE_CONFIG_ENABLE;
+	value |= TEGRA186_GPIO_ENABLE_CONFIG_OUT;
+	writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);
+
+	return 0;
+}
+
+static int tegra186_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+	struct tegra_gpio *gpio = gpiochip_get_data(chip);
+	void __iomem *base;
+	u32 value;
+
+	base = tegra186_gpio_get_base(gpio, offset);
+	if (WARN_ON(base == NULL))
+		return -ENODEV;
+
+	value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
+	if (value & TEGRA186_GPIO_ENABLE_CONFIG_OUT)
+		value = readl(base + TEGRA186_GPIO_OUTPUT_VALUE);
+	else
+		value = readl(base + TEGRA186_GPIO_INPUT);
+
+	return value & BIT(0);
+}
+
+static void tegra186_gpio_set(struct gpio_chip *chip, unsigned int offset,
+			      int level)
+{
+	struct tegra_gpio *gpio = gpiochip_get_data(chip);
+	void __iomem *base;
+	u32 value;
+
+	base = tegra186_gpio_get_base(gpio, offset);
+	if (WARN_ON(base == NULL))
+		return;
+
+	value = readl(base + TEGRA186_GPIO_OUTPUT_VALUE);
+	if (level == 0)
+		value &= ~TEGRA186_GPIO_OUTPUT_VALUE_HIGH;
+	else
+		value |= TEGRA186_GPIO_OUTPUT_VALUE_HIGH;
+
+	writel(value, base + TEGRA186_GPIO_OUTPUT_VALUE);
+}
+
+static int tegra186_gpio_of_xlate(struct gpio_chip *chip,
+				  const struct of_phandle_args *spec,
+				  u32 *flags)
+{
+	struct tegra_gpio *gpio = gpiochip_get_data(chip);
+	unsigned int port, pin, i, offset = 0;
+
+	if (WARN_ON(chip->of_gpio_n_cells < 2))
+		return -EINVAL;
+
+	if (WARN_ON(spec->args_count < chip->of_gpio_n_cells))
+		return -EINVAL;
+
+	port = spec->args[0] / 8;
+	pin = spec->args[0] % 8;
+
+	if (port >= gpio->soc->num_ports) {
+		dev_err(chip->parent, "invalid port number: %u\n", port);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < port; i++)
+		offset += gpio->soc->ports[i].pins;
+
+	if (flags)
+		*flags = spec->args[1];
+
+	return offset + pin;
+}
+
+static void tegra186_irq_ack(struct irq_data *data)
+{
+	struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
+	void __iomem *base;
+
+	base = tegra186_gpio_get_base(gpio, data->hwirq);
+	if (WARN_ON(base == NULL))
+		return;
+
+	writel(1, base + TEGRA186_GPIO_INTERRUPT_CLEAR);
+}
+
+static void tegra186_irq_mask(struct irq_data *data)
+{
+	struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
+	void __iomem *base;
+	u32 value;
+
+	base = tegra186_gpio_get_base(gpio, data->hwirq);
+	if (WARN_ON(base == NULL))
+		return;
+
+	value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
+	value &= ~TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT;
+	writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);
+}
+
+static void tegra186_irq_unmask(struct irq_data *data)
+{
+	struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
+	void __iomem *base;
+	u32 value;
+
+	base = tegra186_gpio_get_base(gpio, data->hwirq);
+	if (WARN_ON(base == NULL))
+		return;
+
+	value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
+	value |= TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT;
+	writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);
+}
+
+static int tegra186_irq_set_type(struct irq_data *data, unsigned int flow)
+{
+	struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
+	void __iomem *base;
+	u32 value;
+
+	base = tegra186_gpio_get_base(gpio, data->hwirq);
+	if (WARN_ON(base == NULL))
+		return -ENODEV;
+
+	value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
+	value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_MASK;
+	value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL;
+
+	switch (flow & IRQ_TYPE_SENSE_MASK) {
+	case IRQ_TYPE_NONE:
+		break;
+
+	case IRQ_TYPE_EDGE_RISING:
+		value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE;
+		value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL;
+		break;
+
+	case IRQ_TYPE_EDGE_FALLING:
+		value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE;
+		break;
+
+	case IRQ_TYPE_EDGE_BOTH:
+		value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_DOUBLE_EDGE;
+		break;
+
+	case IRQ_TYPE_LEVEL_HIGH:
+		value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_LEVEL;
+		value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL;
+		break;
+
+	case IRQ_TYPE_LEVEL_LOW:
+		value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_LEVEL;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);
+
+	if ((flow & IRQ_TYPE_EDGE_BOTH) == 0)
+		irq_set_handler_locked(data, handle_level_irq);
+	else
+		irq_set_handler_locked(data, handle_edge_irq);
+
+	return 0;
+}
+
+static void tegra186_gpio_irq(struct irq_desc *desc)
+{
+	struct tegra_gpio *gpio = irq_desc_get_handler_data(desc);
+	struct irq_domain *domain = gpio->gpio.irq.domain;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	unsigned int parent = irq_desc_get_irq(desc);
+	unsigned int i, offset = 0;
+
+	chained_irq_enter(chip, desc);
+
+	for (i = 0; i < gpio->soc->num_ports; i++) {
+		const struct tegra_gpio_port *port = &gpio->soc->ports[i];
+		void __iomem *base = gpio->base + port->offset;
+		unsigned int pin, irq;
+		unsigned long value;
+
+		/* skip ports that are not associated with this controller */
+		if (parent != gpio->irq[port->irq])
+			goto skip;
+
+		value = readl(base + TEGRA186_GPIO_INTERRUPT_STATUS(1));
+
+		for_each_set_bit(pin, &value, port->pins) {
+			irq = irq_find_mapping(domain, offset + pin);
+			if (WARN_ON(irq == 0))
+				continue;
+
+			generic_handle_irq(irq);
+		}
+
+skip:
+		offset += port->pins;
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
+static int tegra186_gpio_irq_domain_xlate(struct irq_domain *domain,
+					  struct device_node *np,
+					  const u32 *spec, unsigned int size,
+					  unsigned long *hwirq,
+					  unsigned int *type)
+{
+	struct tegra_gpio *gpio = gpiochip_get_data(domain->host_data);
+	unsigned int port, pin, i, offset = 0;
+
+	if (size < 2)
+		return -EINVAL;
+
+	port = spec[0] / 8;
+	pin = spec[0] % 8;
+
+	if (port >= gpio->soc->num_ports) {
+		dev_err(gpio->gpio.parent, "invalid port number: %u\n", port);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < port; i++)
+		offset += gpio->soc->ports[i].pins;
+
+	*type = spec[1] & IRQ_TYPE_SENSE_MASK;
+	*hwirq = offset + pin;
+
+	return 0;
+}
+
+static const struct irq_domain_ops tegra186_gpio_irq_domain_ops = {
+	.map = gpiochip_irq_map,
+	.unmap = gpiochip_irq_unmap,
+	.xlate = tegra186_gpio_irq_domain_xlate,
+};
+
+static struct lock_class_key tegra186_gpio_lock_class;
+
+static int tegra186_gpio_probe(struct platform_device *pdev)
+{
+	unsigned int i, j, offset;
+	struct gpio_irq_chip *irq;
+	struct tegra_gpio *gpio;
+	struct resource *res;
+	char **names;
+	int err;
+
+	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+	if (!gpio)
+		return -ENOMEM;
+
+	gpio->soc = of_device_get_match_data(&pdev->dev);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpio");
+	gpio->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(gpio->base))
+		return PTR_ERR(gpio->base);
+
+	err = platform_irq_count(pdev);
+	if (err < 0)
+		return err;
+
+	gpio->num_irq = err;
+
+	gpio->irq = devm_kcalloc(&pdev->dev, gpio->num_irq, sizeof(*gpio->irq),
+				 GFP_KERNEL);
+	if (!gpio->irq)
+		return -ENOMEM;
+
+	for (i = 0; i < gpio->num_irq; i++) {
+		err = platform_get_irq(pdev, i);
+		if (err < 0)
+			return err;
+
+		gpio->irq[i] = err;
+	}
+
+	gpio->gpio.label = gpio->soc->name;
+	gpio->gpio.parent = &pdev->dev;
+
+	gpio->gpio.get_direction = tegra186_gpio_get_direction;
+	gpio->gpio.direction_input = tegra186_gpio_direction_input;
+	gpio->gpio.direction_output = tegra186_gpio_direction_output;
+	gpio->gpio.get = tegra186_gpio_get,
+	gpio->gpio.set = tegra186_gpio_set;
+
+	gpio->gpio.base = -1;
+
+	for (i = 0; i < gpio->soc->num_ports; i++)
+		gpio->gpio.ngpio += gpio->soc->ports[i].pins;
+
+	names = devm_kcalloc(gpio->gpio.parent, gpio->gpio.ngpio,
+			     sizeof(*names), GFP_KERNEL);
+	if (!names)
+		return -ENOMEM;
+
+	for (i = 0, offset = 0; i < gpio->soc->num_ports; i++) {
+		const struct tegra_gpio_port *port = &gpio->soc->ports[i];
+		char *name;
+
+		for (j = 0; j < port->pins; j++) {
+			name = devm_kasprintf(gpio->gpio.parent, GFP_KERNEL,
+					      "P%s.%02x", port->name, j);
+			if (!name)
+				return -ENOMEM;
+
+			names[offset + j] = name;
+		}
+
+		offset += port->pins;
+	}
+
+	gpio->gpio.names = (const char * const *)names;
+
+	gpio->gpio.of_node = pdev->dev.of_node;
+	gpio->gpio.of_gpio_n_cells = 2;
+	gpio->gpio.of_xlate = tegra186_gpio_of_xlate;
+
+	gpio->intc.name = pdev->dev.of_node->name;
+	gpio->intc.irq_ack = tegra186_irq_ack;
+	gpio->intc.irq_mask = tegra186_irq_mask;
+	gpio->intc.irq_unmask = tegra186_irq_unmask;
+	gpio->intc.irq_set_type = tegra186_irq_set_type;
+
+	irq = &gpio->gpio.irq;
+	irq->chip = &gpio->intc;
+	irq->first = 0;
+	irq->domain_ops = &tegra186_gpio_irq_domain_ops;
+	irq->handler = handle_simple_irq;
+	irq->lock_key = &tegra186_gpio_lock_class;
+	irq->default_type = IRQ_TYPE_NONE;
+	irq->parent_handler = tegra186_gpio_irq;
+	irq->parent_handler_data = gpio;
+	irq->num_parents = gpio->num_irq;
+	irq->parents = gpio->irq;
+
+	irq->map = devm_kcalloc(&pdev->dev, gpio->gpio.ngpio,
+				sizeof(*irq->map), GFP_KERNEL);
+	if (!irq->map)
+		return -ENOMEM;
+
+	for (i = 0, offset = 0; i < gpio->soc->num_ports; i++) {
+		const struct tegra_gpio_port *port = &gpio->soc->ports[i];
+
+		for (j = 0; j < port->pins; j++)
+			irq->map[offset + j] = irq->parents[port->irq];
+
+		offset += port->pins;
+	}
+
+	platform_set_drvdata(pdev, gpio);
+
+	err = devm_gpiochip_add_data(&pdev->dev, &gpio->gpio, gpio);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int tegra186_gpio_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+#define TEGRA_MAIN_GPIO_PORT(port, base, count, controller)	\
+	[TEGRA_MAIN_GPIO_PORT_##port] = {			\
+		.name = #port,					\
+		.offset = base,					\
+		.pins = count,					\
+		.irq = controller,				\
+	}
+
+static const struct tegra_gpio_port tegra186_main_ports[] = {
+	TEGRA_MAIN_GPIO_PORT( A, 0x2000, 7, 2),
+	TEGRA_MAIN_GPIO_PORT( B, 0x3000, 7, 3),
+	TEGRA_MAIN_GPIO_PORT( C, 0x3200, 7, 3),
+	TEGRA_MAIN_GPIO_PORT( D, 0x3400, 6, 3),
+	TEGRA_MAIN_GPIO_PORT( E, 0x2200, 8, 2),
+	TEGRA_MAIN_GPIO_PORT( F, 0x2400, 6, 2),
+	TEGRA_MAIN_GPIO_PORT( G, 0x4200, 6, 4),
+	TEGRA_MAIN_GPIO_PORT( H, 0x1000, 7, 1),
+	TEGRA_MAIN_GPIO_PORT( I, 0x0800, 8, 0),
+	TEGRA_MAIN_GPIO_PORT( J, 0x5000, 8, 5),
+	TEGRA_MAIN_GPIO_PORT( K, 0x5200, 1, 5),
+	TEGRA_MAIN_GPIO_PORT( L, 0x1200, 8, 1),
+	TEGRA_MAIN_GPIO_PORT( M, 0x5600, 6, 5),
+	TEGRA_MAIN_GPIO_PORT( N, 0x0000, 7, 0),
+	TEGRA_MAIN_GPIO_PORT( O, 0x0200, 4, 0),
+	TEGRA_MAIN_GPIO_PORT( P, 0x4000, 7, 4),
+	TEGRA_MAIN_GPIO_PORT( Q, 0x0400, 6, 0),
+	TEGRA_MAIN_GPIO_PORT( R, 0x0a00, 6, 0),
+	TEGRA_MAIN_GPIO_PORT( T, 0x0600, 4, 0),
+	TEGRA_MAIN_GPIO_PORT( X, 0x1400, 8, 1),
+	TEGRA_MAIN_GPIO_PORT( Y, 0x1600, 7, 1),
+	TEGRA_MAIN_GPIO_PORT(BB, 0x2600, 2, 2),
+	TEGRA_MAIN_GPIO_PORT(CC, 0x5400, 4, 5),
+};
+
+static const struct tegra_gpio_soc tegra186_main_soc = {
+	.num_ports = ARRAY_SIZE(tegra186_main_ports),
+	.ports = tegra186_main_ports,
+	.name = "tegra186-gpio",
+};
+
+#define TEGRA_AON_GPIO_PORT(port, base, count, controller)	\
+	[TEGRA_AON_GPIO_PORT_##port] = {			\
+		.name = #port,					\
+		.offset = base,					\
+		.pins = count,					\
+		.irq = controller,				\
+	}
+
+static const struct tegra_gpio_port tegra186_aon_ports[] = {
+	TEGRA_AON_GPIO_PORT( S, 0x0200, 5, 0),
+	TEGRA_AON_GPIO_PORT( U, 0x0400, 6, 0),
+	TEGRA_AON_GPIO_PORT( V, 0x0800, 8, 0),
+	TEGRA_AON_GPIO_PORT( W, 0x0a00, 8, 0),
+	TEGRA_AON_GPIO_PORT( Z, 0x0e00, 4, 0),
+	TEGRA_AON_GPIO_PORT(AA, 0x0c00, 8, 0),
+	TEGRA_AON_GPIO_PORT(EE, 0x0600, 3, 0),
+	TEGRA_AON_GPIO_PORT(FF, 0x0000, 5, 0),
+};
+
+static const struct tegra_gpio_soc tegra186_aon_soc = {
+	.num_ports = ARRAY_SIZE(tegra186_aon_ports),
+	.ports = tegra186_aon_ports,
+	.name = "tegra186-gpio-aon",
+};
+
+static const struct of_device_id tegra186_gpio_of_match[] = {
+	{
+		.compatible = "nvidia,tegra186-gpio",
+		.data = &tegra186_main_soc
+	}, {
+		.compatible = "nvidia,tegra186-gpio-aon",
+		.data = &tegra186_aon_soc
+	}, {
+		/* sentinel */
+	}
+};
+
+static struct platform_driver tegra186_gpio_driver = {
+	.driver = {
+		.name = "tegra186-gpio",
+		.of_match_table = tegra186_gpio_of_match,
+	},
+	.probe = tegra186_gpio_probe,
+	.remove = tegra186_gpio_remove,
+};
+module_platform_driver(tegra186_gpio_driver);
+
+MODULE_DESCRIPTION("NVIDIA Tegra186 GPIO controller driver");
+MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
+MODULE_LICENSE("GPL v2");
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 12/16] gpio: omap: Fix checkpatch warnings
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
                   ` (10 preceding siblings ...)
  2017-09-01 18:57 ` [PATCH 11/16] gpio: Add Tegra186 support Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-15 22:23   ` Grygorii Strashko
  2017-09-01 18:57 ` [PATCH 13/16] gpio: omap: Rename struct gpio_bank to struct omap_gpio_bank Thierry Reding
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

Use unsigned int rather than unsigned, wrap lines longer than 80
characters and other minor coding style cleanups.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpio/gpio-omap.c | 113 ++++++++++++++++++++++++++---------------------
 1 file changed, 63 insertions(+), 50 deletions(-)

diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index ce27d6a586bf..7c600cec3e44 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -76,7 +76,8 @@ struct gpio_bank {
 	int power_mode;
 	bool workaround_enabled;
 
-	void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable);
+	void (*set_dataout)(struct gpio_bank *bank, unsigned int gpio,
+			    int enable);
 	int (*get_context_loss_count)(struct device *dev);
 
 	struct omap_gpio_reg_offs *regs;
@@ -92,6 +93,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d);
 static inline struct gpio_bank *omap_irq_data_get_bank(struct irq_data *d)
 {
 	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+
 	return gpiochip_get_data(chip);
 }
 
@@ -113,8 +115,8 @@ static void omap_set_gpio_direction(struct gpio_bank *bank, int gpio,
 
 
 /* set data out value using dedicate set/clear register */
-static void omap_set_gpio_dataout_reg(struct gpio_bank *bank, unsigned offset,
-				      int enable)
+static void omap_set_gpio_dataout_reg(struct gpio_bank *bank,
+				      unsigned int offset, int enable)
 {
 	void __iomem *reg = bank->base;
 	u32 l = BIT(offset);
@@ -131,8 +133,8 @@ static void omap_set_gpio_dataout_reg(struct gpio_bank *bank, unsigned offset,
 }
 
 /* set data out value using mask register */
-static void omap_set_gpio_dataout_mask(struct gpio_bank *bank, unsigned offset,
-				       int enable)
+static void omap_set_gpio_dataout_mask(struct gpio_bank *bank,
+				       unsigned int offset, int enable)
 {
 	void __iomem *reg = bank->base + bank->regs->dataout;
 	u32 gpio_bit = BIT(offset);
@@ -161,7 +163,8 @@ static int omap_get_gpio_dataout(struct gpio_bank *bank, int offset)
 	return (readl_relaxed(reg) & (BIT(offset))) != 0;
 }
 
-static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
+static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask,
+				 bool set)
 {
 	int l = readl_relaxed(base + reg);
 
@@ -211,8 +214,8 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
  *
  * Return: 0 on success, negative error otherwise.
  */
-static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
-				   unsigned debounce)
+static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned int offset,
+				   unsigned int debounce)
 {
 	void __iomem		*reg;
 	u32			val;
@@ -272,7 +275,8 @@ static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
  * time too. The debounce clock will also be disabled when calling this function
  * if this is the only gpio in the bank using debounce.
  */
-static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned offset)
+static void omap_clear_gpio_debounce(struct gpio_bank *bank,
+				     unsigned int offset)
 {
 	u32 gpio_bit = BIT(offset);
 
@@ -284,8 +288,8 @@ static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned offset)
 
 	bank->dbck_enable_mask &= ~gpio_bit;
 	bank->context.debounce_en &= ~gpio_bit;
-        writel_relaxed(bank->context.debounce_en,
-		     bank->base + bank->regs->debounce_en);
+	writel_relaxed(bank->context.debounce_en,
+		       bank->base + bank->regs->debounce_en);
 
 	if (!bank->dbck_enable_mask) {
 		bank->context.debounce = 0;
@@ -297,7 +301,7 @@ static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned offset)
 }
 
 static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
-						unsigned trigger)
+					 unsigned int trigger)
 {
 	void __iomem *base = bank->base;
 	u32 gpio_bit = BIT(gpio);
@@ -321,7 +325,8 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
 			readl_relaxed(bank->base + bank->regs->fallingdetect);
 
 	if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
-		omap_gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0);
+		omap_gpio_rmw(base, bank->regs->wkup_en, gpio_bit,
+			      trigger != 0);
 		bank->context.wake_en =
 			readl_relaxed(bank->base + bank->regs->wkup_en);
 	}
@@ -376,11 +381,13 @@ static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
 	writel_relaxed(l, reg);
 }
 #else
-static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {}
+static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
+{
+}
 #endif
 
 static int omap_set_gpio_triggering(struct gpio_bank *bank, int gpio,
-				    unsigned trigger)
+				    unsigned int trigger)
 {
 	void __iomem *reg = bank->base;
 	void __iomem *base = bank->base;
@@ -425,7 +432,7 @@ static int omap_set_gpio_triggering(struct gpio_bank *bank, int gpio,
 	return 0;
 }
 
-static void omap_enable_gpio_module(struct gpio_bank *bank, unsigned offset)
+static void omap_enable_gpio_module(struct gpio_bank *bank, unsigned int offset)
 {
 	if (bank->regs->pinctrl) {
 		void __iomem *reg = bank->base + bank->regs->pinctrl;
@@ -446,7 +453,8 @@ static void omap_enable_gpio_module(struct gpio_bank *bank, unsigned offset)
 	}
 }
 
-static void omap_disable_gpio_module(struct gpio_bank *bank, unsigned offset)
+static void omap_disable_gpio_module(struct gpio_bank *bank,
+				     unsigned int offset)
 {
 	void __iomem *base = bank->base;
 
@@ -471,14 +479,14 @@ static void omap_disable_gpio_module(struct gpio_bank *bank, unsigned offset)
 	}
 }
 
-static int omap_gpio_is_input(struct gpio_bank *bank, unsigned offset)
+static int omap_gpio_is_input(struct gpio_bank *bank, unsigned int offset)
 {
 	void __iomem *reg = bank->base + bank->regs->direction;
 
 	return readl_relaxed(reg) & BIT(offset);
 }
 
-static void omap_gpio_init_irq(struct gpio_bank *bank, unsigned offset)
+static void omap_gpio_init_irq(struct gpio_bank *bank, unsigned int offset)
 {
 	if (!LINE_USED(bank->mod_usage, offset)) {
 		omap_enable_gpio_module(bank, offset);
@@ -487,12 +495,12 @@ static void omap_gpio_init_irq(struct gpio_bank *bank, unsigned offset)
 	bank->irq_usage |= BIT(offset);
 }
 
-static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
+static int omap_gpio_irq_type(struct irq_data *d, unsigned int type)
 {
 	struct gpio_bank *bank = omap_irq_data_get_bank(d);
 	int retval;
 	unsigned long flags;
-	unsigned offset = d->hwirq;
+	unsigned int offset = d->hwirq;
 
 	if (type & ~IRQ_TYPE_SENSE_MASK)
 		return -EINVAL;
@@ -544,7 +552,7 @@ static void omap_clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
 }
 
 static inline void omap_clear_gpio_irqstatus(struct gpio_bank *bank,
-					     unsigned offset)
+					     unsigned int offset)
 {
 	omap_clear_gpio_irqbank(bank, BIT(offset));
 }
@@ -608,7 +616,7 @@ static void omap_disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
 }
 
 static inline void omap_set_gpio_irqenable(struct gpio_bank *bank,
-					   unsigned offset, int enable)
+					   unsigned int offset, int enable)
 {
 	if (enable)
 		omap_enable_gpio_irqbank(bank, BIT(offset));
@@ -624,7 +632,7 @@ static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable)
 	return irq_set_irq_wake(bank->irq, enable);
 }
 
-static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
+static int omap_gpio_request(struct gpio_chip *chip, unsigned int offset)
 {
 	struct gpio_bank *bank = gpiochip_get_data(chip);
 	unsigned long flags;
@@ -644,7 +652,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
 	return 0;
 }
 
-static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
+static void omap_gpio_free(struct gpio_chip *chip, unsigned int offset)
 {
 	struct gpio_bank *bank = gpiochip_get_data(chip);
 	unsigned long flags;
@@ -702,9 +710,11 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
 		if (bank->level_mask)
 			level_mask = bank->level_mask & enabled;
 
-		/* clear edge sensitive interrupts before handler(s) are
-		called so that we don't miss any interrupt occurred while
-		executing them */
+		/*
+		 * clear edge sensitive interrupts before handler(s) are
+		 * called so that we don't miss any interrupt occurred while
+		 * executing them
+		 */
 		omap_disable_gpio_irqbank(bank, isr_saved & ~level_mask);
 		omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
 		omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask);
@@ -715,6 +725,8 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
 			break;
 
 		while (isr) {
+			unsigned int irq;
+
 			bit = __ffs(isr);
 			isr &= ~(BIT(bit));
 
@@ -733,8 +745,8 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
 
 			raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags);
 
-			generic_handle_irq(irq_find_mapping(bank->chip.irq.domain,
-							    bit));
+			irq = irq_find_mapping(bank->chip.irq.domain, bit);
+			generic_handle_irq(irq);
 
 			raw_spin_unlock_irqrestore(&bank->wa_lock,
 						   wa_lock_flags);
@@ -749,7 +761,7 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)
 {
 	struct gpio_bank *bank = omap_irq_data_get_bank(d);
 	unsigned long flags;
-	unsigned offset = d->hwirq;
+	unsigned int offset = d->hwirq;
 
 	raw_spin_lock_irqsave(&bank->lock, flags);
 
@@ -773,7 +785,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
 {
 	struct gpio_bank *bank = omap_irq_data_get_bank(d);
 	unsigned long flags;
-	unsigned offset = d->hwirq;
+	unsigned int offset = d->hwirq;
 
 	raw_spin_lock_irqsave(&bank->lock, flags);
 	bank->irq_usage &= ~(BIT(offset));
@@ -809,7 +821,7 @@ static void gpio_irq_bus_sync_unlock(struct irq_data *data)
 static void omap_gpio_ack_irq(struct irq_data *d)
 {
 	struct gpio_bank *bank = omap_irq_data_get_bank(d);
-	unsigned offset = d->hwirq;
+	unsigned int offset = d->hwirq;
 
 	omap_clear_gpio_irqstatus(bank, offset);
 }
@@ -817,7 +829,7 @@ static void omap_gpio_ack_irq(struct irq_data *d)
 static void omap_gpio_mask_irq(struct irq_data *d)
 {
 	struct gpio_bank *bank = omap_irq_data_get_bank(d);
-	unsigned offset = d->hwirq;
+	unsigned int offset = d->hwirq;
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&bank->lock, flags);
@@ -829,7 +841,7 @@ static void omap_gpio_mask_irq(struct irq_data *d)
 static void omap_gpio_unmask_irq(struct irq_data *d)
 {
 	struct gpio_bank *bank = omap_irq_data_get_bank(d);
-	unsigned offset = d->hwirq;
+	unsigned int offset = d->hwirq;
 	u32 trigger = irqd_get_trigger_type(d);
 	unsigned long flags;
 
@@ -837,8 +849,10 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
 	if (trigger)
 		omap_set_gpio_triggering(bank, offset, trigger);
 
-	/* For level-triggered GPIOs, the clearing must be done after
-	 * the HW source is cleared, thus after the handler has run */
+	/*
+	 * For level-triggered GPIOs, the clearing must be done after
+	 * the HW source is cleared, thus after the handler has run
+	 */
 	if (bank->level_mask & BIT(offset)) {
 		omap_set_gpio_irqenable(bank, offset, 0);
 		omap_clear_gpio_irqstatus(bank, offset);
@@ -912,7 +926,7 @@ static inline void omap_mpuio_init(struct gpio_bank *bank)
 
 /*---------------------------------------------------------------------*/
 
-static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
 {
 	struct gpio_bank *bank;
 	unsigned long flags;
@@ -927,7 +941,7 @@ static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
 	return dir;
 }
 
-static int omap_gpio_input(struct gpio_chip *chip, unsigned offset)
+static int omap_gpio_input(struct gpio_chip *chip, unsigned int offset)
 {
 	struct gpio_bank *bank;
 	unsigned long flags;
@@ -939,7 +953,7 @@ static int omap_gpio_input(struct gpio_chip *chip, unsigned offset)
 	return 0;
 }
 
-static int omap_gpio_get(struct gpio_chip *chip, unsigned offset)
+static int omap_gpio_get(struct gpio_chip *chip, unsigned int offset)
 {
 	struct gpio_bank *bank;
 
@@ -951,7 +965,8 @@ static int omap_gpio_get(struct gpio_chip *chip, unsigned offset)
 		return omap_get_gpio_dataout(bank, offset);
 }
 
-static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value)
+static int omap_gpio_output(struct gpio_chip *chip, unsigned int offset,
+			    int value)
 {
 	struct gpio_bank *bank;
 	unsigned long flags;
@@ -964,8 +979,8 @@ static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value)
 	return 0;
 }
 
-static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
-			      unsigned debounce)
+static int omap_gpio_debounce(struct gpio_chip *chip, unsigned int offset,
+			      unsigned int debounce)
 {
 	struct gpio_bank *bank;
 	unsigned long flags;
@@ -985,7 +1000,7 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
 	return ret;
 }
 
-static int omap_gpio_set_config(struct gpio_chip *chip, unsigned offset,
+static int omap_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
 				unsigned long config)
 {
 	u32 debounce;
@@ -997,7 +1012,8 @@ static int omap_gpio_set_config(struct gpio_chip *chip, unsigned offset,
 	return omap_gpio_debounce(chip, offset, debounce);
 }
 
-static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static void omap_gpio_set(struct gpio_chip *chip, unsigned int offset,
+			  int value)
 {
 	struct gpio_bank *bank;
 	unsigned long flags;
@@ -1153,10 +1169,8 @@ static int omap_gpio_probe(struct platform_device *pdev)
 		return -EINVAL;
 
 	bank = devm_kzalloc(dev, sizeof(struct gpio_bank), GFP_KERNEL);
-	if (!bank) {
-		dev_err(dev, "Memory alloc failed\n");
+	if (!bank)
 		return -ENOMEM;
-	}
 
 	irqc = devm_kzalloc(dev, sizeof(*irqc), GFP_KERNEL);
 	if (!irqc)
@@ -1217,9 +1231,8 @@ static int omap_gpio_probe(struct platform_device *pdev)
 	/* Static mapping, never released */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	bank->base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(bank->base)) {
+	if (IS_ERR(bank->base))
 		return PTR_ERR(bank->base);
-	}
 
 	if (bank->dbck_flag) {
 		bank->dbck = devm_clk_get(dev, "dbclk");
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 13/16] gpio: omap: Rename struct gpio_bank to struct omap_gpio_bank
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
                   ` (11 preceding siblings ...)
  2017-09-01 18:57 ` [PATCH 12/16] gpio: omap: Fix checkpatch warnings Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-15 22:23   ` Grygorii Strashko
  2017-09-01 18:57 ` [PATCH 14/16] gpio: Add support for banked GPIO controllers Thierry Reding
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

Subsequent patches will want to introduce a struct gpio_bank in core
code, so rename this to something driver-specific in order to avoid the
names from clashing.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpio/gpio-omap.c | 131 ++++++++++++++++++++++++-----------------------
 1 file changed, 68 insertions(+), 63 deletions(-)

diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 7c600cec3e44..0b80d929d892 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -48,7 +48,7 @@ struct gpio_regs {
 	u32 debounce_en;
 };
 
-struct gpio_bank {
+struct omap_gpio_bank {
 	struct list_head node;
 	void __iomem *base;
 	int irq;
@@ -76,7 +76,7 @@ struct gpio_bank {
 	int power_mode;
 	bool workaround_enabled;
 
-	void (*set_dataout)(struct gpio_bank *bank, unsigned int gpio,
+	void (*set_dataout)(struct omap_gpio_bank *bank, unsigned int gpio,
 			    int enable);
 	int (*get_context_loss_count)(struct device *dev);
 
@@ -90,14 +90,14 @@ struct gpio_bank {
 
 static void omap_gpio_unmask_irq(struct irq_data *d);
 
-static inline struct gpio_bank *omap_irq_data_get_bank(struct irq_data *d)
+static inline struct omap_gpio_bank *omap_irq_data_get_bank(struct irq_data *d)
 {
 	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
 
 	return gpiochip_get_data(chip);
 }
 
-static void omap_set_gpio_direction(struct gpio_bank *bank, int gpio,
+static void omap_set_gpio_direction(struct omap_gpio_bank *bank, int gpio,
 				    int is_input)
 {
 	void __iomem *reg = bank->base;
@@ -115,7 +115,7 @@ static void omap_set_gpio_direction(struct gpio_bank *bank, int gpio,
 
 
 /* set data out value using dedicate set/clear register */
-static void omap_set_gpio_dataout_reg(struct gpio_bank *bank,
+static void omap_set_gpio_dataout_reg(struct omap_gpio_bank *bank,
 				      unsigned int offset, int enable)
 {
 	void __iomem *reg = bank->base;
@@ -133,7 +133,7 @@ static void omap_set_gpio_dataout_reg(struct gpio_bank *bank,
 }
 
 /* set data out value using mask register */
-static void omap_set_gpio_dataout_mask(struct gpio_bank *bank,
+static void omap_set_gpio_dataout_mask(struct omap_gpio_bank *bank,
 				       unsigned int offset, int enable)
 {
 	void __iomem *reg = bank->base + bank->regs->dataout;
@@ -149,14 +149,14 @@ static void omap_set_gpio_dataout_mask(struct gpio_bank *bank,
 	bank->context.dataout = l;
 }
 
-static int omap_get_gpio_datain(struct gpio_bank *bank, int offset)
+static int omap_get_gpio_datain(struct omap_gpio_bank *bank, int offset)
 {
 	void __iomem *reg = bank->base + bank->regs->datain;
 
 	return (readl_relaxed(reg) & (BIT(offset))) != 0;
 }
 
-static int omap_get_gpio_dataout(struct gpio_bank *bank, int offset)
+static int omap_get_gpio_dataout(struct omap_gpio_bank *bank, int offset)
 {
 	void __iomem *reg = bank->base + bank->regs->dataout;
 
@@ -176,7 +176,7 @@ static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask,
 	writel_relaxed(l, base + reg);
 }
 
-static inline void omap_gpio_dbck_enable(struct gpio_bank *bank)
+static inline void omap_gpio_dbck_enable(struct omap_gpio_bank *bank)
 {
 	if (bank->dbck_enable_mask && !bank->dbck_enabled) {
 		clk_enable(bank->dbck);
@@ -187,7 +187,7 @@ static inline void omap_gpio_dbck_enable(struct gpio_bank *bank)
 	}
 }
 
-static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
+static inline void omap_gpio_dbck_disable(struct omap_gpio_bank *bank)
 {
 	if (bank->dbck_enable_mask && bank->dbck_enabled) {
 		/*
@@ -214,8 +214,8 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
  *
  * Return: 0 on success, negative error otherwise.
  */
-static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned int offset,
-				   unsigned int debounce)
+static int omap2_set_gpio_debounce(struct omap_gpio_bank *bank,
+				   unsigned int offset, unsigned int debounce)
 {
 	void __iomem		*reg;
 	u32			val;
@@ -275,7 +275,7 @@ static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned int offset,
  * time too. The debounce clock will also be disabled when calling this function
  * if this is the only gpio in the bank using debounce.
  */
-static void omap_clear_gpio_debounce(struct gpio_bank *bank,
+static void omap_clear_gpio_debounce(struct omap_gpio_bank *bank,
 				     unsigned int offset)
 {
 	u32 gpio_bit = BIT(offset);
@@ -300,7 +300,7 @@ static void omap_clear_gpio_debounce(struct gpio_bank *bank,
 	}
 }
 
-static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
+static inline void omap_set_gpio_trigger(struct omap_gpio_bank *bank, int gpio,
 					 unsigned int trigger)
 {
 	void __iomem *base = bank->base;
@@ -362,7 +362,8 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
  * This only applies to chips that can't do both rising and falling edge
  * detection at once.  For all other chips, this function is a noop.
  */
-static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
+static void omap_toggle_gpio_edge_triggering(struct omap_gpio_bank *bank,
+					     int gpio)
 {
 	void __iomem *reg = bank->base;
 	u32 l = 0;
@@ -381,12 +382,13 @@ static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
 	writel_relaxed(l, reg);
 }
 #else
-static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
+static void omap_toggle_gpio_edge_triggering(struct omap_gpio_bank *bank,
+					     int gpio)
 {
 }
 #endif
 
-static int omap_set_gpio_triggering(struct gpio_bank *bank, int gpio,
+static int omap_set_gpio_triggering(struct omap_gpio_bank *bank, int gpio,
 				    unsigned int trigger)
 {
 	void __iomem *reg = bank->base;
@@ -432,7 +434,8 @@ static int omap_set_gpio_triggering(struct gpio_bank *bank, int gpio,
 	return 0;
 }
 
-static void omap_enable_gpio_module(struct gpio_bank *bank, unsigned int offset)
+static void omap_enable_gpio_module(struct omap_gpio_bank *bank,
+				    unsigned int offset)
 {
 	if (bank->regs->pinctrl) {
 		void __iomem *reg = bank->base + bank->regs->pinctrl;
@@ -453,7 +456,7 @@ static void omap_enable_gpio_module(struct gpio_bank *bank, unsigned int offset)
 	}
 }
 
-static void omap_disable_gpio_module(struct gpio_bank *bank,
+static void omap_disable_gpio_module(struct omap_gpio_bank *bank,
 				     unsigned int offset)
 {
 	void __iomem *base = bank->base;
@@ -479,14 +482,14 @@ static void omap_disable_gpio_module(struct gpio_bank *bank,
 	}
 }
 
-static int omap_gpio_is_input(struct gpio_bank *bank, unsigned int offset)
+static int omap_gpio_is_input(struct omap_gpio_bank *bank, unsigned int offset)
 {
 	void __iomem *reg = bank->base + bank->regs->direction;
 
 	return readl_relaxed(reg) & BIT(offset);
 }
 
-static void omap_gpio_init_irq(struct gpio_bank *bank, unsigned int offset)
+static void omap_gpio_init_irq(struct omap_gpio_bank *bank, unsigned int offset)
 {
 	if (!LINE_USED(bank->mod_usage, offset)) {
 		omap_enable_gpio_module(bank, offset);
@@ -497,7 +500,7 @@ static void omap_gpio_init_irq(struct gpio_bank *bank, unsigned int offset)
 
 static int omap_gpio_irq_type(struct irq_data *d, unsigned int type)
 {
-	struct gpio_bank *bank = omap_irq_data_get_bank(d);
+	struct omap_gpio_bank *bank = omap_irq_data_get_bank(d);
 	int retval;
 	unsigned long flags;
 	unsigned int offset = d->hwirq;
@@ -534,7 +537,7 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned int type)
 	return retval;
 }
 
-static void omap_clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
+static void omap_clear_gpio_irqbank(struct omap_gpio_bank *bank, int gpio_mask)
 {
 	void __iomem *reg = bank->base;
 
@@ -551,13 +554,13 @@ static void omap_clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
 	readl_relaxed(reg);
 }
 
-static inline void omap_clear_gpio_irqstatus(struct gpio_bank *bank,
+static inline void omap_clear_gpio_irqstatus(struct omap_gpio_bank *bank,
 					     unsigned int offset)
 {
 	omap_clear_gpio_irqbank(bank, BIT(offset));
 }
 
-static u32 omap_get_gpio_irqbank_mask(struct gpio_bank *bank)
+static u32 omap_get_gpio_irqbank_mask(struct omap_gpio_bank *bank)
 {
 	void __iomem *reg = bank->base;
 	u32 l;
@@ -571,7 +574,7 @@ static u32 omap_get_gpio_irqbank_mask(struct gpio_bank *bank)
 	return l;
 }
 
-static void omap_enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
+static void omap_enable_gpio_irqbank(struct omap_gpio_bank *bank, int gpio_mask)
 {
 	void __iomem *reg = bank->base;
 	u32 l;
@@ -593,7 +596,8 @@ static void omap_enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
 	writel_relaxed(l, reg);
 }
 
-static void omap_disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
+static void omap_disable_gpio_irqbank(struct omap_gpio_bank *bank,
+				      int gpio_mask)
 {
 	void __iomem *reg = bank->base;
 	u32 l;
@@ -615,7 +619,7 @@ static void omap_disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
 	writel_relaxed(l, reg);
 }
 
-static inline void omap_set_gpio_irqenable(struct gpio_bank *bank,
+static inline void omap_set_gpio_irqenable(struct omap_gpio_bank *bank,
 					   unsigned int offset, int enable)
 {
 	if (enable)
@@ -627,14 +631,14 @@ static inline void omap_set_gpio_irqenable(struct gpio_bank *bank,
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
 static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable)
 {
-	struct gpio_bank *bank = omap_irq_data_get_bank(d);
+	struct omap_gpio_bank *bank = omap_irq_data_get_bank(d);
 
 	return irq_set_irq_wake(bank->irq, enable);
 }
 
 static int omap_gpio_request(struct gpio_chip *chip, unsigned int offset)
 {
-	struct gpio_bank *bank = gpiochip_get_data(chip);
+	struct omap_gpio_bank *bank = gpiochip_get_data(chip);
 	unsigned long flags;
 
 	/*
@@ -654,7 +658,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned int offset)
 
 static void omap_gpio_free(struct gpio_chip *chip, unsigned int offset)
 {
-	struct gpio_bank *bank = gpiochip_get_data(chip);
+	struct omap_gpio_bank *bank = gpiochip_get_data(chip);
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&bank->lock, flags);
@@ -688,7 +692,7 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
 	void __iomem *isr_reg = NULL;
 	u32 isr;
 	unsigned int bit;
-	struct gpio_bank *bank = gpiobank;
+	struct omap_gpio_bank *bank = gpiobank;
 	unsigned long wa_lock_flags;
 	unsigned long lock_flags;
 
@@ -759,7 +763,7 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
 
 static unsigned int omap_gpio_irq_startup(struct irq_data *d)
 {
-	struct gpio_bank *bank = omap_irq_data_get_bank(d);
+	struct omap_gpio_bank *bank = omap_irq_data_get_bank(d);
 	unsigned long flags;
 	unsigned int offset = d->hwirq;
 
@@ -783,7 +787,7 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)
 
 static void omap_gpio_irq_shutdown(struct irq_data *d)
 {
-	struct gpio_bank *bank = omap_irq_data_get_bank(d);
+	struct omap_gpio_bank *bank = omap_irq_data_get_bank(d);
 	unsigned long flags;
 	unsigned int offset = d->hwirq;
 
@@ -800,7 +804,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
 
 static void omap_gpio_irq_bus_lock(struct irq_data *data)
 {
-	struct gpio_bank *bank = omap_irq_data_get_bank(data);
+	struct omap_gpio_bank *bank = omap_irq_data_get_bank(data);
 
 	if (!BANK_USED(bank))
 		pm_runtime_get_sync(bank->chip.parent);
@@ -808,7 +812,7 @@ static void omap_gpio_irq_bus_lock(struct irq_data *data)
 
 static void gpio_irq_bus_sync_unlock(struct irq_data *data)
 {
-	struct gpio_bank *bank = omap_irq_data_get_bank(data);
+	struct omap_gpio_bank *bank = omap_irq_data_get_bank(data);
 
 	/*
 	 * If this is the last IRQ to be freed in the bank,
@@ -820,7 +824,7 @@ static void gpio_irq_bus_sync_unlock(struct irq_data *data)
 
 static void omap_gpio_ack_irq(struct irq_data *d)
 {
-	struct gpio_bank *bank = omap_irq_data_get_bank(d);
+	struct omap_gpio_bank *bank = omap_irq_data_get_bank(d);
 	unsigned int offset = d->hwirq;
 
 	omap_clear_gpio_irqstatus(bank, offset);
@@ -828,7 +832,7 @@ static void omap_gpio_ack_irq(struct irq_data *d)
 
 static void omap_gpio_mask_irq(struct irq_data *d)
 {
-	struct gpio_bank *bank = omap_irq_data_get_bank(d);
+	struct omap_gpio_bank *bank = omap_irq_data_get_bank(d);
 	unsigned int offset = d->hwirq;
 	unsigned long flags;
 
@@ -840,7 +844,7 @@ static void omap_gpio_mask_irq(struct irq_data *d)
 
 static void omap_gpio_unmask_irq(struct irq_data *d)
 {
-	struct gpio_bank *bank = omap_irq_data_get_bank(d);
+	struct omap_gpio_bank *bank = omap_irq_data_get_bank(d);
 	unsigned int offset = d->hwirq;
 	u32 trigger = irqd_get_trigger_type(d);
 	unsigned long flags;
@@ -867,7 +871,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
 static int omap_mpuio_suspend_noirq(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	struct gpio_bank	*bank = platform_get_drvdata(pdev);
+	struct omap_gpio_bank	*bank = platform_get_drvdata(pdev);
 	void __iomem		*mask_reg = bank->base +
 					OMAP_MPUIO_GPIO_MASKIT / bank->stride;
 	unsigned long		flags;
@@ -882,7 +886,7 @@ static int omap_mpuio_suspend_noirq(struct device *dev)
 static int omap_mpuio_resume_noirq(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	struct gpio_bank	*bank = platform_get_drvdata(pdev);
+	struct omap_gpio_bank	*bank = platform_get_drvdata(pdev);
 	void __iomem		*mask_reg = bank->base +
 					OMAP_MPUIO_GPIO_MASKIT / bank->stride;
 	unsigned long		flags;
@@ -916,7 +920,7 @@ static struct platform_device omap_mpuio_device = {
 	/* could list the /proc/iomem resources */
 };
 
-static inline void omap_mpuio_init(struct gpio_bank *bank)
+static inline void omap_mpuio_init(struct omap_gpio_bank *bank)
 {
 	platform_set_drvdata(&omap_mpuio_device, bank);
 
@@ -928,7 +932,7 @@ static inline void omap_mpuio_init(struct gpio_bank *bank)
 
 static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
 {
-	struct gpio_bank *bank;
+	struct omap_gpio_bank *bank;
 	unsigned long flags;
 	void __iomem *reg;
 	int dir;
@@ -943,7 +947,7 @@ static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
 
 static int omap_gpio_input(struct gpio_chip *chip, unsigned int offset)
 {
-	struct gpio_bank *bank;
+	struct omap_gpio_bank *bank;
 	unsigned long flags;
 
 	bank = gpiochip_get_data(chip);
@@ -955,7 +959,7 @@ static int omap_gpio_input(struct gpio_chip *chip, unsigned int offset)
 
 static int omap_gpio_get(struct gpio_chip *chip, unsigned int offset)
 {
-	struct gpio_bank *bank;
+	struct omap_gpio_bank *bank;
 
 	bank = gpiochip_get_data(chip);
 
@@ -968,7 +972,7 @@ static int omap_gpio_get(struct gpio_chip *chip, unsigned int offset)
 static int omap_gpio_output(struct gpio_chip *chip, unsigned int offset,
 			    int value)
 {
-	struct gpio_bank *bank;
+	struct omap_gpio_bank *bank;
 	unsigned long flags;
 
 	bank = gpiochip_get_data(chip);
@@ -982,7 +986,7 @@ static int omap_gpio_output(struct gpio_chip *chip, unsigned int offset,
 static int omap_gpio_debounce(struct gpio_chip *chip, unsigned int offset,
 			      unsigned int debounce)
 {
-	struct gpio_bank *bank;
+	struct omap_gpio_bank *bank;
 	unsigned long flags;
 	int ret;
 
@@ -1015,7 +1019,7 @@ static int omap_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
 static void omap_gpio_set(struct gpio_chip *chip, unsigned int offset,
 			  int value)
 {
-	struct gpio_bank *bank;
+	struct omap_gpio_bank *bank;
 	unsigned long flags;
 
 	bank = gpiochip_get_data(chip);
@@ -1026,7 +1030,7 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned int offset,
 
 /*---------------------------------------------------------------------*/
 
-static void __init omap_gpio_show_rev(struct gpio_bank *bank)
+static void __init omap_gpio_show_rev(struct omap_gpio_bank *bank)
 {
 	static bool called;
 	u32 rev;
@@ -1041,7 +1045,7 @@ static void __init omap_gpio_show_rev(struct gpio_bank *bank)
 	called = true;
 }
 
-static void omap_gpio_mod_init(struct gpio_bank *bank)
+static void omap_gpio_mod_init(struct omap_gpio_bank *bank)
 {
 	void __iomem *base = bank->base;
 	u32 l = 0xffffffff;
@@ -1068,7 +1072,8 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
 		writel_relaxed(0, base + bank->regs->ctrl);
 }
 
-static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
+static int omap_gpio_chip_init(struct omap_gpio_bank *bank,
+			       struct irq_chip *irqc)
 {
 	static int gpio;
 	int irq_base = 0;
@@ -1158,7 +1163,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
 	const struct of_device_id *match;
 	const struct omap_gpio_platform_data *pdata;
 	struct resource *res;
-	struct gpio_bank *bank;
+	struct omap_gpio_bank *bank;
 	struct irq_chip *irqc;
 	int ret;
 
@@ -1168,7 +1173,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
 	if (!pdata)
 		return -EINVAL;
 
-	bank = devm_kzalloc(dev, sizeof(struct gpio_bank), GFP_KERNEL);
+	bank = devm_kzalloc(dev, sizeof(struct omap_gpio_bank), GFP_KERNEL);
 	if (!bank)
 		return -ENOMEM;
 
@@ -1276,7 +1281,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
 
 static int omap_gpio_remove(struct platform_device *pdev)
 {
-	struct gpio_bank *bank = platform_get_drvdata(pdev);
+	struct omap_gpio_bank *bank = platform_get_drvdata(pdev);
 
 	list_del(&bank->node);
 	gpiochip_remove(&bank->chip);
@@ -1290,12 +1295,12 @@ static int omap_gpio_remove(struct platform_device *pdev)
 #ifdef CONFIG_ARCH_OMAP2PLUS
 
 #if defined(CONFIG_PM)
-static void omap_gpio_restore_context(struct gpio_bank *bank);
+static void omap_gpio_restore_context(struct omap_gpio_bank *bank);
 
 static int omap_gpio_runtime_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	struct gpio_bank *bank = platform_get_drvdata(pdev);
+	struct omap_gpio_bank *bank = platform_get_drvdata(pdev);
 	u32 l1 = 0, l2 = 0;
 	unsigned long flags;
 	u32 wake_low, wake_hi;
@@ -1358,12 +1363,12 @@ static int omap_gpio_runtime_suspend(struct device *dev)
 	return 0;
 }
 
-static void omap_gpio_init_context(struct gpio_bank *p);
+static void omap_gpio_init_context(struct omap_gpio_bank *p);
 
 static int omap_gpio_runtime_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	struct gpio_bank *bank = platform_get_drvdata(pdev);
+	struct omap_gpio_bank *bank = platform_get_drvdata(pdev);
 	u32 l = 0, gen, gen0, gen1;
 	unsigned long flags;
 	int c;
@@ -1475,7 +1480,7 @@ static int omap_gpio_runtime_resume(struct device *dev)
 #if IS_BUILTIN(CONFIG_GPIO_OMAP)
 void omap2_gpio_prepare_for_idle(int pwr_mode)
 {
-	struct gpio_bank *bank;
+	struct omap_gpio_bank *bank;
 
 	list_for_each_entry(bank, &omap_gpio_list, node) {
 		if (!BANK_USED(bank) || !bank->loses_context)
@@ -1489,7 +1494,7 @@ void omap2_gpio_prepare_for_idle(int pwr_mode)
 
 void omap2_gpio_resume_after_idle(void)
 {
-	struct gpio_bank *bank;
+	struct omap_gpio_bank *bank;
 
 	list_for_each_entry(bank, &omap_gpio_list, node) {
 		if (!BANK_USED(bank) || !bank->loses_context)
@@ -1501,7 +1506,7 @@ void omap2_gpio_resume_after_idle(void)
 #endif
 
 #if defined(CONFIG_PM)
-static void omap_gpio_init_context(struct gpio_bank *p)
+static void omap_gpio_init_context(struct omap_gpio_bank *p)
 {
 	struct omap_gpio_reg_offs *regs = p->regs;
 	void __iomem *base = p->base;
@@ -1524,7 +1529,7 @@ static void omap_gpio_init_context(struct gpio_bank *p)
 	p->context_valid = true;
 }
 
-static void omap_gpio_restore_context(struct gpio_bank *bank)
+static void omap_gpio_restore_context(struct omap_gpio_bank *bank)
 {
 	writel_relaxed(bank->context.wake_en,
 				bank->base + bank->regs->wkup_en);
@@ -1561,7 +1566,7 @@ static void omap_gpio_restore_context(struct gpio_bank *bank)
 #else
 #define omap_gpio_runtime_suspend NULL
 #define omap_gpio_runtime_resume NULL
-static inline void omap_gpio_init_context(struct gpio_bank *p) {}
+static inline void omap_gpio_init_context(struct omap_gpio_bank *p) {}
 #endif
 
 static const struct dev_pm_ops gpio_pm_ops = {
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 14/16] gpio: Add support for banked GPIO controllers
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
                   ` (12 preceding siblings ...)
  2017-09-01 18:57 ` [PATCH 13/16] gpio: omap: Rename struct gpio_bank to struct omap_gpio_bank Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-14 13:59   ` Linus Walleij
  2017-09-01 18:57 ` [PATCH 15/16] gpio: tegra: Use banked GPIO infrastructure Thierry Reding
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

Some GPIO controllers are subdivided into multiple logical blocks called
banks (or ports). This is often caused by the design assigning separate
resources, such as register regions or interrupts, to each bank, or some
set of banks.

This commit adds support for describing controllers that have such a
banked design and provides common code for dealing with them.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpio/gpiolib-of.c   | 101 +++++++++++++++++++++++++++++++++++++++++
 drivers/gpio/gpiolib.c      |  98 ++++++++++++++++++++++++++++++++++++++++
 include/linux/gpio/driver.h | 108 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_gpio.h     |  10 ++++
 4 files changed, 317 insertions(+)

diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index bfcd20699ec8..8b89f03076c2 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -310,6 +310,107 @@ int of_gpio_simple_xlate(struct gpio_chip *gc,
 EXPORT_SYMBOL(of_gpio_simple_xlate);
 
 /**
+ * gpio_banked_irq_domain_xlate - decode an IRQ specifier for banked chips
+ * @domain: IRQ domain
+ * @np: device tree node
+ * @spec: IRQ specifier
+ * @size: number of cells in IRQ specifier
+ * @hwirq: return location for the hardware IRQ number
+ * @type: return location for the IRQ type
+ *
+ * Translates the IRQ specifier found in device tree into a hardware IRQ
+ * number and an interrupt type.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int gpio_banked_irq_domain_xlate(struct irq_domain *domain,
+				 struct device_node *np,
+				 const u32 *spec, unsigned int size,
+				 unsigned long *hwirq,
+				 unsigned int *type)
+{
+	struct gpio_chip *gc = domain->host_data;
+	unsigned int bank, pin, i, offset = 0;
+
+	if (size < 2)
+		return -EINVAL;
+
+	bank = (spec[0] >> gc->of_gpio_bank_mask) & gc->of_gpio_bank_shift;
+	pin = (spec[0] >> gc->of_gpio_pin_mask) & gc->of_gpio_pin_shift;
+
+	if (bank >= gc->num_banks) {
+		dev_err(gc->parent, "invalid bank number: %u\n", bank);
+		return -EINVAL;
+	}
+
+	if (pin >= gc->banks[bank]->num_pins) {
+		dev_err(gc->parent, "invalid pin number: %u\n", pin);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < bank; i++)
+		offset += gc->banks[i]->num_pins;
+
+	*type = spec[1] & IRQ_TYPE_SENSE_MASK;
+	*hwirq = offset + pin;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(gpio_banked_irq_domain_xlate);
+
+/**
+ * of_gpio_banked_xlate - translate GPIO specifier to a GPIO number and flags
+ * @gc: GPIO chip
+ * @gpiospec: GPIO specifier
+ * @flags: return location for flags parsed from the GPIO specifier
+ *
+ * This translation function takes into account multiple banks that can make
+ * up a single controller. Each bank can contain one or more pins. A single
+ * cell in the specifier is used to represent a (bank, pin) pair, with each
+ * encoded in different fields. The &gpio_chip.of_gpio_bank_shift and
+ * &gpio_chip.of_gpio_bank_mask fields, and &gpio_chip.of_gpio_pin_shift and
+ * &gpio_chip.of_gpio_pin_mask are used to specify the encoding.
+ *
+ * Returns:
+ * The chip-relative index of the pin given by the GPIO specifier.
+ */
+int of_gpio_banked_xlate(struct gpio_chip *gc,
+			 const struct of_phandle_args *gpiospec, u32 *flags)
+{
+	unsigned int offset = 0, bank, pin, i;
+	const u32 *spec = gpiospec->args;
+
+	if (WARN_ON(gc->of_gpio_n_cells < 2))
+		return -EINVAL;
+
+	if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
+		return -EINVAL;
+
+	bank = (spec[0] >> gc->of_gpio_bank_shift) & gc->of_gpio_bank_mask;
+	pin = (spec[0] >> gc->of_gpio_pin_shift) & gc->of_gpio_pin_mask;
+
+	if (bank >= gc->num_banks) {
+		dev_err(gc->parent, "invalid bank number: %u\n", bank);
+		return -EINVAL;
+	}
+
+	if (pin >= gc->banks[bank]->num_pins) {
+		dev_err(gc->parent, "invalid pin number: %u\n", pin);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < bank; i++)
+		offset += gc->banks[i]->num_pins;
+
+	if (flags)
+		*flags = spec[1];
+
+	return offset + pin;
+}
+EXPORT_SYMBOL(of_gpio_banked_xlate);
+
+/**
  * of_mm_gpiochip_add_data - Add memory mapped GPIO chip (bank)
  * @np:		device node of the GPIO chip
  * @mm_gc:	pointer to the of_mm_gpio_chip allocated structure
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 7a16dd37bd3d..306c3a13e814 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1776,6 +1776,57 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip)
 	gpiochip->to_irq = gpiochip_to_irq;
 	gpiochip->irq.default_type = type;
 
+	if (gpiochip->num_banks > 0 && !gpiochip->irq.map) {
+		struct gpio_irq_chip *irq = &gpiochip->irq;
+		unsigned int i, j, offset = 0;
+
+		if (!irq->parents) {
+			chip_err(gpiochip, "no parent interrupts defined\n");
+			return -EINVAL;
+		}
+
+		irq->map = devm_kcalloc(gpiochip->parent, gpiochip->ngpio,
+					sizeof(*irq->map), GFP_KERNEL);
+		if (!irq->map)
+			return -ENOMEM;
+
+		for (i = 0; i < gpiochip->num_banks; i++) {
+			struct gpio_bank *bank = gpiochip->banks[i];
+			unsigned int parent = bank->parent_irq;
+
+			for (j = 0; j < bank->num_pins; j++) {
+				if (parent >= irq->num_parents) {
+					chip_err(gpiochip,
+						 "invalid parent interrupt: %u\n",
+						 parent);
+					return -EINVAL;
+				}
+
+				irq->map[offset + j] = irq->parents[parent];
+			}
+
+			offset += bank->num_pins;
+		}
+	}
+
+	if (gpiochip->num_banks > 0) {
+		unsigned int i;
+
+		for (i = 0; i < gpiochip->num_banks; i++) {
+			struct gpio_bank *bank = gpiochip->banks[i];
+			unsigned int num_pins = bank->num_pins;
+
+			bank->pending = devm_kcalloc(gpiochip->parent,
+						     BITS_TO_LONGS(num_pins),
+						     sizeof(unsigned long),
+						     GFP_KERNEL);
+			if (!bank->pending)
+				return -ENOMEM;
+
+			bank->chip = gpiochip;
+		}
+	}
+
 	if (gpiochip->irq.domain_ops)
 		ops = gpiochip->irq.domain_ops;
 	else
@@ -1984,6 +2035,53 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
 }
 EXPORT_SYMBOL_GPL(gpiochip_irqchip_add_key);
 
+/**
+ * gpio_irq_chip_banked_handler - interrupt handler for banked IRQ chips
+ * @desc: IRQ descriptor
+ *
+ * Drivers can use this interrupt handler for banked GPIO controllers. This
+ * implementation iterates over all banks and handles pending interrupts of
+ * the pins associated with the bank.
+ *
+ * This function uses driver specific parts, split out into the
+ * &gpio_chip.update_bank() callback, to retrieves the interrupt pending
+ * state for each of the GPIOs exposed by the given bank.
+ */
+void gpio_irq_chip_banked_handler(struct irq_desc *desc)
+{
+	struct gpio_chip *gpio = irq_desc_get_handler_data(desc);
+	struct irq_chip *irq = irq_desc_get_chip(desc);
+	unsigned int parent = irq_desc_get_irq(desc);
+	struct gpio_irq_chip *chip = &gpio->irq;
+	unsigned int i, offset = 0;
+
+	chained_irq_enter(irq, desc);
+
+	for (i = 0; i < gpio->num_banks; i++) {
+		struct gpio_bank *bank = gpio->banks[i];
+		unsigned int pin, virq;
+
+		if (parent != chip->parents[bank->parent_irq])
+			goto skip;
+
+		chip->update_bank(bank);
+
+		for_each_set_bit(pin, bank->pending, bank->num_pins) {
+			virq = irq_find_mapping(chip->domain, offset + pin);
+			if (WARN_ON(virq == 0))
+				continue;
+
+			generic_handle_irq(virq);
+		}
+
+skip:
+		offset += bank->num_pins;
+	}
+
+	chained_irq_exit(irq, desc);
+}
+EXPORT_SYMBOL_GPL(gpio_irq_chip_banked_handler);
+
 #else /* CONFIG_GPIOLIB_IRQCHIP */
 
 static inline int gpiochip_add_irqchip(struct gpio_chip *gpiochip)
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index c453e0716228..ecbeb50f8801 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -19,6 +19,47 @@ struct module;
 
 #ifdef CONFIG_GPIOLIB
 
+/**
+ * struct gpio_bank - GPIO bank
+ *
+ * A GPIO bank, sometimes also referred to as port, represents a subset of the
+ * pins of a GPIO controller. The separation into banks is often caused by the
+ * sharing of one or more resource (register region, interrupt, ...) for each
+ * of the pins in the bank.
+ *
+ * In many cases the banking is transparent, but when it is not, GPIO drivers
+ * can use this code, along with some supporting fields in &struct gpio_chip.
+ */
+struct gpio_bank {
+	/**
+	 * @chip:
+	 *
+	 * A pointer to the &struct gpio_chip that this bank belongs to.
+	 */
+	struct gpio_chip *chip;
+
+	/**
+	 * @parent_irq:
+	 *
+	 * The interrupt parent for this bank.
+	 */
+	unsigned int parent_irq;
+
+	/**
+	 * @num_pins:
+	 *
+	 * The number of pins provided by this bank.
+	 */
+	unsigned int num_pins;
+
+	/**
+	 * @pending:
+	 *
+	 * Current interrupt state of each pin in the bank.
+	 */
+	unsigned long *pending;
+};
+
 #ifdef CONFIG_GPIOLIB_IRQCHIP
 /**
  * struct gpio_irq_chip - GPIO interrupt controller
@@ -136,6 +177,15 @@ struct gpio_irq_chip {
 	 * in IRQ domain of the chip.
 	 */
 	unsigned long *valid_mask;
+
+	/**
+	 * @update_bank:
+	 *
+	 * Callback used by banked interrupt controllers. The driver updates
+	 * the &gpio_bank.pending field of the given @bank with the current
+	 * status for each of the GPIOs that it provides.
+	 */
+	void (*update_bank)(struct gpio_bank *bank);
 };
 
 static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)
@@ -281,6 +331,24 @@ struct gpio_chip {
 	struct gpio_irq_chip irq;
 #endif
 
+	/**
+	 * @banks:
+	 *
+	 * If a GPIO controller is subdivided into multiple banks, the driver
+	 * can use this field to store information about these banks.
+	 *
+	 * Note that the driver owns this field and the core will not modify
+	 * it, only reference it.
+	 */
+	struct gpio_bank **banks;
+
+	/**
+	 * @num_banks:
+	 *
+	 * The number of banks described in @banks.
+	 */
+	unsigned int num_banks;
+
 #if defined(CONFIG_OF_GPIO)
 	/*
 	 * If CONFIG_OF is enabled, then all GPIO controllers described in the
@@ -302,6 +370,38 @@ struct gpio_chip {
 	unsigned int of_gpio_n_cells;
 
 	/**
+	 * @of_gpio_bank_shift:
+	 *
+	 * The offset of the field in the cell denoting the bank number of a
+	 * specified GPIO.
+	 */
+	unsigned int of_gpio_bank_shift;
+
+	/**
+	 * @of_gpio_bank_mask:
+	 *
+	 * The mask of the field in the cell denoting the bank number of a
+	 * specified GPIO.
+	 */
+	unsigned int of_gpio_bank_mask;
+
+	/**
+	 * @of_gpio_pin_shift:
+	 *
+	 * The offset of the field in the cell denoting the pin number of a
+	 * specified GPIO within its bank.
+	 */
+	unsigned int of_gpio_pin_shift;
+
+	/**
+	 * @of_gpio_pin_mask:
+	 *
+	 * The mask of the field in the cell denoting the pin number of a
+	 * specified GPIO within its bank.
+	 */
+	unsigned int of_gpio_pin_mask;
+
+	/**
 	 * @of_xlate:
 	 *
 	 * Callback to translate a device tree GPIO specifier into a chip-
@@ -374,6 +474,12 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
 		     irq_hw_number_t hwirq);
 void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq);
 
+int gpio_banked_irq_domain_xlate(struct irq_domain *domain,
+				 struct device_node *np,
+				 const u32 *spec, unsigned int size,
+				 unsigned long *hwirq,
+				 unsigned int *type);
+
 void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
 		struct irq_chip *irqchip,
 		unsigned int parent_irq,
@@ -391,6 +497,8 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
 			     bool nested,
 			     struct lock_class_key *lock_key);
 
+void gpio_irq_chip_banked_handler(struct irq_desc *desc);
+
 #ifdef CONFIG_LOCKDEP
 
 /*
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index ca10f43564de..f85414dc31f4 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -66,6 +66,9 @@ extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc);
 extern int of_gpio_simple_xlate(struct gpio_chip *gc,
 				const struct of_phandle_args *gpiospec,
 				u32 *flags);
+extern int of_gpio_banked_xlate(struct gpio_chip *gc,
+				const struct of_phandle_args *gpiospec,
+				u32 *flags);
 
 #else /* CONFIG_OF_GPIO */
 
@@ -86,6 +89,13 @@ static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
 	return -ENOSYS;
 }
 
+static inline int of_gpio_banked_xlate(struct gpio_chip *gc,
+				       const struct of_phandle_args *gpiospec,
+				       u32 *flags)
+{
+	return -ENOSYS;
+}
+
 #endif /* CONFIG_OF_GPIO */
 
 /**
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 15/16] gpio: tegra: Use banked GPIO infrastructure
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
                   ` (13 preceding siblings ...)
  2017-09-01 18:57 ` [PATCH 14/16] gpio: Add support for banked GPIO controllers Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-01 18:57 ` [PATCH 16/16] gpio: tegra186: " Thierry Reding
  2017-09-14 13:54 ` [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Linus Walleij
  16 siblings, 0 replies; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

Convert the Tegra GPIO driver to use the banked GPIO infrastructure,
which simplifies some parts of the driver.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpio/Kconfig      |   1 +
 drivers/gpio/gpio-tegra.c | 203 ++++++++++++++++++++++------------------------
 2 files changed, 98 insertions(+), 106 deletions(-)

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index f9e22c6fdd02..9364f037fe86 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -439,6 +439,7 @@ config GPIO_TEGRA
 	default ARCH_TEGRA
 	depends on ARCH_TEGRA || COMPILE_TEST
 	depends on OF_GPIO
+	select GPIOLIB_IRQCHIP
 	help
 	  Say yes here to support GPIO pins on NVIDIA Tegra SoCs.
 
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index fbaf974277df..250cebc3ab60 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -67,8 +67,8 @@
 struct tegra_gpio_info;
 
 struct tegra_gpio_bank {
-	unsigned int bank;
-	unsigned int irq;
+	struct gpio_bank bank;
+	unsigned int index;
 	spinlock_t lvl_lock[4];
 	spinlock_t dbc_lock[4];	/* Lock for updating debounce count register */
 #ifdef CONFIG_PM_SLEEP
@@ -84,6 +84,11 @@ struct tegra_gpio_bank {
 	struct tegra_gpio_info *tgi;
 };
 
+static struct tegra_gpio_bank *to_tegra_gpio_bank(struct gpio_bank *bank)
+{
+	return container_of(bank, struct tegra_gpio_bank, bank);
+}
+
 struct tegra_gpio_soc_config {
 	bool debounce_supported;
 	u32 bank_stride;
@@ -98,9 +103,14 @@ struct tegra_gpio_info {
 	const struct tegra_gpio_soc_config	*soc;
 	struct gpio_chip			gc;
 	struct irq_chip				ic;
-	u32					bank_count;
 };
 
+static inline struct tegra_gpio_info *
+to_tegra_gpio_info(struct gpio_chip *chip)
+{
+	return container_of(chip, struct tegra_gpio_info, gc);
+}
+
 static inline void tegra_gpio_writel(struct tegra_gpio_info *tgi,
 				     u32 val, u32 reg)
 {
@@ -264,8 +274,8 @@ static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
 
 static void tegra_gpio_irq_ack(struct irq_data *d)
 {
-	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	struct tegra_gpio_info *tgi = bank->tgi;
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+	struct tegra_gpio_info *tgi = to_tegra_gpio_info(chip);
 	unsigned int gpio = d->hwirq;
 
 	tegra_gpio_writel(tgi, 1 << GPIO_BIT(gpio), GPIO_INT_CLR(tgi, gpio));
@@ -273,8 +283,8 @@ static void tegra_gpio_irq_ack(struct irq_data *d)
 
 static void tegra_gpio_irq_mask(struct irq_data *d)
 {
-	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	struct tegra_gpio_info *tgi = bank->tgi;
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+	struct tegra_gpio_info *tgi = to_tegra_gpio_info(chip);
 	unsigned int gpio = d->hwirq;
 
 	tegra_gpio_mask_write(tgi, GPIO_MSK_INT_ENB(tgi, gpio), gpio, 0);
@@ -282,8 +292,8 @@ static void tegra_gpio_irq_mask(struct irq_data *d)
 
 static void tegra_gpio_irq_unmask(struct irq_data *d)
 {
-	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	struct tegra_gpio_info *tgi = bank->tgi;
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+	struct tegra_gpio_info *tgi = to_tegra_gpio_info(chip);
 	unsigned int gpio = d->hwirq;
 
 	tegra_gpio_mask_write(tgi, GPIO_MSK_INT_ENB(tgi, gpio), gpio, 1);
@@ -292,12 +302,15 @@ static void tegra_gpio_irq_unmask(struct irq_data *d)
 static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
 	unsigned int gpio = d->hwirq, port = GPIO_PORT(gpio), lvl_type;
-	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	struct tegra_gpio_info *tgi = bank->tgi;
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+	struct tegra_gpio_info *tgi = to_tegra_gpio_info(chip);
+	struct tegra_gpio_bank *bank;
 	unsigned long flags;
 	u32 val;
 	int ret;
 
+	bank = &tgi->bank_info[GPIO_BANK(gpio)];
+
 	switch (type & IRQ_TYPE_SENSE_MASK) {
 	case IRQ_TYPE_EDGE_RISING:
 		lvl_type = GPIO_INT_LVL_EDGE_RISING;
@@ -352,52 +365,27 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 
 static void tegra_gpio_irq_shutdown(struct irq_data *d)
 {
-	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	struct tegra_gpio_info *tgi = bank->tgi;
-	unsigned int gpio = d->hwirq;
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
 
-	gpiochip_unlock_as_irq(&tgi->gc, gpio);
+	gpiochip_unlock_as_irq(chip, d->hwirq);
 }
 
-static void tegra_gpio_irq_handler(struct irq_desc *desc)
+static void tegra_gpio_update_bank(struct gpio_bank *bank)
 {
-	unsigned int port, pin, gpio;
-	bool unmasked = false;
-	u32 lvl;
-	unsigned long sta;
-	struct irq_chip *chip = irq_desc_get_chip(desc);
-	struct tegra_gpio_bank *bank = irq_desc_get_handler_data(desc);
-	struct tegra_gpio_info *tgi = bank->tgi;
-
-	chained_irq_enter(chip, desc);
+	struct tegra_gpio_info *tgi = to_tegra_gpio_info(bank->chip);
+	struct tegra_gpio_bank *b = to_tegra_gpio_bank(bank);
+	unsigned int port;
 
 	for (port = 0; port < 4; port++) {
-		gpio = tegra_gpio_compose(bank->bank, port, 0);
-		sta = tegra_gpio_readl(tgi, GPIO_INT_STA(tgi, gpio)) &
-			tegra_gpio_readl(tgi, GPIO_INT_ENB(tgi, gpio));
-		lvl = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio));
-
-		for_each_set_bit(pin, &sta, 8) {
-			tegra_gpio_writel(tgi, 1 << pin,
-					  GPIO_INT_CLR(tgi, gpio));
-
-			/* if gpio is edge triggered, clear condition
-			 * before executing the handler so that we don't
-			 * miss edges
-			 */
-			if (!unmasked && lvl & (0x100 << pin)) {
-				unmasked = true;
-				chained_irq_exit(chip, desc);
-			}
+		unsigned int gpio = tegra_gpio_compose(b->index, port, 0);
+		u8 *pending = (u8 *)bank->pending;
+		u32 status, enable;
 
-			generic_handle_irq(irq_find_mapping(tgi->irq_domain,
-							    gpio + pin));
-		}
-	}
-
-	if (!unmasked)
-		chained_irq_exit(chip, desc);
+		status = tegra_gpio_readl(tgi, GPIO_INT_STA(tgi, gpio));
+		enable = tegra_gpio_readl(tgi, GPIO_INT_ENB(tgi, gpio));
 
+		pending[port] = status & enable;
+	}
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -410,7 +398,7 @@ static int tegra_gpio_resume(struct device *dev)
 
 	local_irq_save(flags);
 
-	for (b = 0; b < tgi->bank_count; b++) {
+	for (b = 0; b < tgi->gc.num_banks; b++) {
 		struct tegra_gpio_bank *bank = &tgi->bank_info[b];
 
 		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
@@ -449,7 +437,7 @@ static int tegra_gpio_suspend(struct device *dev)
 	unsigned int b, p;
 
 	local_irq_save(flags);
-	for (b = 0; b < tgi->bank_count; b++) {
+	for (b = 0; b < tgi->gc.num_banks; b++) {
 		struct tegra_gpio_bank *bank = &tgi->bank_info[b];
 
 		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
@@ -484,20 +472,26 @@ static int tegra_gpio_suspend(struct device *dev)
 
 static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable)
 {
-	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	unsigned int gpio = d->hwirq;
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int gpio = d->hwirq, parent_irq;
+	struct tegra_gpio_bank *b;
+	struct gpio_bank *bank;
 	u32 port, bit, mask;
 
+	bank = chip->banks[GPIO_BANK(gpio)];
+	b = to_tegra_gpio_bank(bank);
 	port = GPIO_PORT(gpio);
 	bit = GPIO_BIT(gpio);
 	mask = BIT(bit);
 
 	if (enable)
-		bank->wake_enb[port] |= mask;
+		b->wake_enb[port] |= mask;
 	else
-		bank->wake_enb[port] &= ~mask;
+		b->wake_enb[port] &= ~mask;
+
+	parent_irq = chip->irq.parents[bank->parent_irq];
 
-	return irq_set_irq_wake(bank->irq, enable);
+	return irq_set_irq_wake(parent_irq, enable);
 }
 #endif
 
@@ -511,7 +505,7 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
 	struct tegra_gpio_info *tgi = s->private;
 	unsigned int i, j;
 
-	for (i = 0; i < tgi->bank_count; i++) {
+	for (i = 0; i < tgi->gc.num_banks; i++) {
 		for (j = 0; j < 4; j++) {
 			unsigned int gpio = tegra_gpio_compose(i, j, 0);
 
@@ -561,17 +555,18 @@ static const struct dev_pm_ops tegra_gpio_pm_ops = {
 };
 
 /*
- * This lock class tells lockdep that GPIO irqs are in a different category
+ * 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 gpio_lock_class;
+static struct lock_class_key tegra_gpio_lock_class;
 
 static int tegra_gpio_probe(struct platform_device *pdev)
 {
 	struct tegra_gpio_info *tgi;
 	struct resource *res;
 	struct tegra_gpio_bank *bank;
-	unsigned int gpio, i, j;
+	struct gpio_irq_chip *irq;
+	unsigned int i, j;
 	int ret;
 
 	tgi = devm_kzalloc(&pdev->dev, sizeof(*tgi), GFP_KERNEL);
@@ -580,14 +575,20 @@ static int tegra_gpio_probe(struct platform_device *pdev)
 
 	tgi->soc = of_device_get_match_data(&pdev->dev);
 	tgi->dev = &pdev->dev;
+	irq = &tgi->gc.irq;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	tgi->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(tgi->regs))
+		return PTR_ERR(tgi->regs);
 
 	ret = platform_irq_count(pdev);
 	if (ret < 0)
 		return ret;
 
-	tgi->bank_count = ret;
+	tgi->gc.num_banks = ret;
 
-	if (!tgi->bank_count) {
+	if (!tgi->gc.num_banks) {
 		dev_err(&pdev->dev, "Missing IRQ resource\n");
 		return -ENODEV;
 	}
@@ -602,7 +603,7 @@ static int tegra_gpio_probe(struct platform_device *pdev)
 	tgi->gc.get_direction		= tegra_gpio_get_direction;
 	tgi->gc.to_irq			= tegra_gpio_to_irq;
 	tgi->gc.base			= 0;
-	tgi->gc.ngpio			= tgi->bank_count * 32;
+	tgi->gc.ngpio			= tgi->gc.num_banks * 32;
 	tgi->gc.parent			= &pdev->dev;
 	tgi->gc.of_node			= pdev->dev.of_node;
 
@@ -616,76 +617,66 @@ static int tegra_gpio_probe(struct platform_device *pdev)
 	tgi->ic.irq_set_wake		= tegra_gpio_irq_set_wake;
 #endif
 
+	irq = &tgi->gc.irq;
+	irq->chip = &tgi->ic;
+	irq->handler = handle_simple_irq;
+	irq->lock_key = &tegra_gpio_lock_class;
+	irq->default_type = IRQ_TYPE_NONE;
+	irq->parent_handler = gpio_irq_chip_banked_handler;
+	irq->update_bank = tegra_gpio_update_bank;
+
+	irq->parents = devm_kcalloc(&pdev->dev, tgi->gc.num_banks,
+				    sizeof(unsigned int), GFP_KERNEL);
+	if (!irq->parents)
+		return -ENOMEM;
+
+	irq->num_parents = tgi->gc.num_banks;
+
 	platform_set_drvdata(pdev, tgi);
 
 	if (tgi->soc->debounce_supported)
 		tgi->gc.set_config = tegra_gpio_set_config;
 
-	tgi->bank_info = devm_kcalloc(&pdev->dev, tgi->bank_count,
+	tgi->bank_info = devm_kcalloc(&pdev->dev, tgi->gc.num_banks,
 				      sizeof(*tgi->bank_info), GFP_KERNEL);
 	if (!tgi->bank_info)
 		return -ENOMEM;
 
-	tgi->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
-						tgi->gc.ngpio,
-						&irq_domain_simple_ops, NULL);
-	if (!tgi->irq_domain)
-		return -ENODEV;
+	tgi->gc.banks = devm_kcalloc(&pdev->dev, tgi->gc.num_banks,
+				     sizeof(struct gpio_bank *),
+				     GFP_KERNEL);
+	if (!tgi->gc.banks)
+		return -ENOMEM;
 
-	for (i = 0; i < tgi->bank_count; i++) {
+	for (i = 0; i < tgi->gc.num_banks; i++) {
 		ret = platform_get_irq(pdev, i);
 		if (ret < 0) {
 			dev_err(&pdev->dev, "Missing IRQ resource: %d\n", ret);
 			return ret;
 		}
 
+		irq->parents[i] = ret;
+
 		bank = &tgi->bank_info[i];
-		bank->bank = i;
-		bank->irq = ret;
-		bank->tgi = tgi;
-	}
+		bank->bank.chip = &tgi->gc;
+		bank->bank.parent_irq = i;
+		bank->bank.num_pins = 32;
+		bank->index = i;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	tgi->regs = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(tgi->regs))
-		return PTR_ERR(tgi->regs);
+		tgi->gc.banks[i] = &bank->bank;
 
-	for (i = 0; i < tgi->bank_count; i++) {
 		for (j = 0; j < 4; j++) {
-			int gpio = tegra_gpio_compose(i, j, 0);
+			unsigned int gpio = tegra_gpio_compose(i, j, 0);
 
 			tegra_gpio_writel(tgi, 0x00, GPIO_INT_ENB(tgi, gpio));
+			spin_lock_init(&bank->lvl_lock[j]);
+			spin_lock_init(&bank->dbc_lock[j]);
 		}
 	}
 
 	ret = devm_gpiochip_add_data(&pdev->dev, &tgi->gc, tgi);
-	if (ret < 0) {
-		irq_domain_remove(tgi->irq_domain);
+	if (ret < 0)
 		return ret;
-	}
-
-	for (gpio = 0; gpio < tgi->gc.ngpio; gpio++) {
-		int irq = irq_create_mapping(tgi->irq_domain, gpio);
-		/* No validity check; all Tegra GPIOs are valid IRQs */
-
-		bank = &tgi->bank_info[GPIO_BANK(gpio)];
-
-		irq_set_lockdep_class(irq, &gpio_lock_class);
-		irq_set_chip_data(irq, bank);
-		irq_set_chip_and_handler(irq, &tgi->ic, handle_simple_irq);
-	}
-
-	for (i = 0; i < tgi->bank_count; i++) {
-		bank = &tgi->bank_info[i];
-
-		irq_set_chained_handler_and_data(bank->irq,
-						 tegra_gpio_irq_handler, bank);
-
-		for (j = 0; j < 4; j++) {
-			spin_lock_init(&bank->lvl_lock[j]);
-			spin_lock_init(&bank->dbc_lock[j]);
-		}
-	}
 
 	tegra_gpio_debuginit(tgi);
 
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 16/16] gpio: tegra186: Use banked GPIO infrastructure
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
                   ` (14 preceding siblings ...)
  2017-09-01 18:57 ` [PATCH 15/16] gpio: tegra: Use banked GPIO infrastructure Thierry Reding
@ 2017-09-01 18:57 ` Thierry Reding
  2017-09-14 13:54 ` [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Linus Walleij
  16 siblings, 0 replies; 27+ messages in thread
From: Thierry Reding @ 2017-09-01 18:57 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel

From: Thierry Reding <treding@nvidia.com>

Convert the Tegra186 GPIO driver to use the banked GPIO infrastructure,
which simplifies some parts of the driver.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpio/gpio-tegra186.c | 211 ++++++++++++++++---------------------------
 1 file changed, 79 insertions(+), 132 deletions(-)

diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
index 162dc6b41ae8..4926b98a05f6 100644
--- a/drivers/gpio/gpio-tegra186.c
+++ b/drivers/gpio/gpio-tegra186.c
@@ -13,6 +13,7 @@
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 
 #include <dt-bindings/gpio/tegra186-gpio.h>
@@ -44,15 +45,27 @@
 
 #define TEGRA186_GPIO_INTERRUPT_STATUS(x) (0x100 + (x) * 4)
 
-struct tegra_gpio_port {
+struct tegra_gpio_port_soc {
 	const char *name;
 	unsigned int offset;
 	unsigned int pins;
 	unsigned int irq;
 };
 
+struct tegra_gpio_port {
+	struct gpio_bank bank;
+	unsigned int offset;
+	const char *name;
+};
+
+static inline struct tegra_gpio_port *
+to_tegra_gpio_port(struct gpio_bank *bank)
+{
+	return container_of(bank, struct tegra_gpio_port, bank);
+}
+
 struct tegra_gpio_soc {
-	const struct tegra_gpio_port *ports;
+	const struct tegra_gpio_port_soc *ports;
 	unsigned int num_ports;
 	const char *name;
 };
@@ -60,21 +73,21 @@ struct tegra_gpio_soc {
 struct tegra_gpio {
 	struct gpio_chip gpio;
 	struct irq_chip intc;
-	unsigned int num_irq;
-	unsigned int *irq;
 
 	const struct tegra_gpio_soc *soc;
 
+	struct tegra_gpio_port *ports;
+
 	void __iomem *base;
 };
 
-static const struct tegra_gpio_port *
+static const struct tegra_gpio_port_soc *
 tegra186_gpio_get_port(struct tegra_gpio *gpio, unsigned int *pin)
 {
 	unsigned int start = 0, i;
 
 	for (i = 0; i < gpio->soc->num_ports; i++) {
-		const struct tegra_gpio_port *port = &gpio->soc->ports[i];
+		const struct tegra_gpio_port_soc *port = &gpio->soc->ports[i];
 
 		if (*pin >= start && *pin < start + port->pins) {
 			*pin -= start;
@@ -90,7 +103,7 @@ tegra186_gpio_get_port(struct tegra_gpio *gpio, unsigned int *pin)
 static void __iomem *tegra186_gpio_get_base(struct tegra_gpio *gpio,
 					    unsigned int pin)
 {
-	const struct tegra_gpio_port *port;
+	const struct tegra_gpio_port_soc *port;
 
 	port = tegra186_gpio_get_port(gpio, &pin);
 	if (!port)
@@ -206,39 +219,10 @@ static void tegra186_gpio_set(struct gpio_chip *chip, unsigned int offset,
 	writel(value, base + TEGRA186_GPIO_OUTPUT_VALUE);
 }
 
-static int tegra186_gpio_of_xlate(struct gpio_chip *chip,
-				  const struct of_phandle_args *spec,
-				  u32 *flags)
-{
-	struct tegra_gpio *gpio = gpiochip_get_data(chip);
-	unsigned int port, pin, i, offset = 0;
-
-	if (WARN_ON(chip->of_gpio_n_cells < 2))
-		return -EINVAL;
-
-	if (WARN_ON(spec->args_count < chip->of_gpio_n_cells))
-		return -EINVAL;
-
-	port = spec->args[0] / 8;
-	pin = spec->args[0] % 8;
-
-	if (port >= gpio->soc->num_ports) {
-		dev_err(chip->parent, "invalid port number: %u\n", port);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < port; i++)
-		offset += gpio->soc->ports[i].pins;
-
-	if (flags)
-		*flags = spec->args[1];
-
-	return offset + pin;
-}
-
 static void tegra186_irq_ack(struct irq_data *data)
 {
-	struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct tegra_gpio *gpio = gpiochip_get_data(chip);
 	void __iomem *base;
 
 	base = tegra186_gpio_get_base(gpio, data->hwirq);
@@ -250,7 +234,8 @@ static void tegra186_irq_ack(struct irq_data *data)
 
 static void tegra186_irq_mask(struct irq_data *data)
 {
-	struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct tegra_gpio *gpio = gpiochip_get_data(chip);
 	void __iomem *base;
 	u32 value;
 
@@ -265,7 +250,8 @@ static void tegra186_irq_mask(struct irq_data *data)
 
 static void tegra186_irq_unmask(struct irq_data *data)
 {
-	struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct tegra_gpio *gpio = gpiochip_get_data(chip);
 	void __iomem *base;
 	u32 value;
 
@@ -280,7 +266,8 @@ static void tegra186_irq_unmask(struct irq_data *data)
 
 static int tegra186_irq_set_type(struct irq_data *data, unsigned int flow)
 {
-	struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct tegra_gpio *gpio = gpiochip_get_data(chip);
 	void __iomem *base;
 	u32 value;
 
@@ -332,76 +319,22 @@ static int tegra186_irq_set_type(struct irq_data *data, unsigned int flow)
 	return 0;
 }
 
-static void tegra186_gpio_irq(struct irq_desc *desc)
-{
-	struct tegra_gpio *gpio = irq_desc_get_handler_data(desc);
-	struct irq_domain *domain = gpio->gpio.irq.domain;
-	struct irq_chip *chip = irq_desc_get_chip(desc);
-	unsigned int parent = irq_desc_get_irq(desc);
-	unsigned int i, offset = 0;
-
-	chained_irq_enter(chip, desc);
-
-	for (i = 0; i < gpio->soc->num_ports; i++) {
-		const struct tegra_gpio_port *port = &gpio->soc->ports[i];
-		void __iomem *base = gpio->base + port->offset;
-		unsigned int pin, irq;
-		unsigned long value;
-
-		/* skip ports that are not associated with this controller */
-		if (parent != gpio->irq[port->irq])
-			goto skip;
-
-		value = readl(base + TEGRA186_GPIO_INTERRUPT_STATUS(1));
-
-		for_each_set_bit(pin, &value, port->pins) {
-			irq = irq_find_mapping(domain, offset + pin);
-			if (WARN_ON(irq == 0))
-				continue;
-
-			generic_handle_irq(irq);
-		}
-
-skip:
-		offset += port->pins;
-	}
-
-	chained_irq_exit(chip, desc);
-}
-
-static int tegra186_gpio_irq_domain_xlate(struct irq_domain *domain,
-					  struct device_node *np,
-					  const u32 *spec, unsigned int size,
-					  unsigned long *hwirq,
-					  unsigned int *type)
+static void tegra186_gpio_update_bank(struct gpio_bank *bank)
 {
-	struct tegra_gpio *gpio = gpiochip_get_data(domain->host_data);
-	unsigned int port, pin, i, offset = 0;
-
-	if (size < 2)
-		return -EINVAL;
-
-	port = spec[0] / 8;
-	pin = spec[0] % 8;
-
-	if (port >= gpio->soc->num_ports) {
-		dev_err(gpio->gpio.parent, "invalid port number: %u\n", port);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < port; i++)
-		offset += gpio->soc->ports[i].pins;
+	struct tegra_gpio_port *port = to_tegra_gpio_port(bank);
+	struct tegra_gpio *gpio = gpiochip_get_data(bank->chip);
+	void __iomem *base = gpio->base + port->offset;
+	u32 value;
 
-	*type = spec[1] & IRQ_TYPE_SENSE_MASK;
-	*hwirq = offset + pin;
+	value = readl(base + TEGRA186_GPIO_INTERRUPT_STATUS(1));
 
-	return 0;
+	bank->pending[0] = value;
 }
 
 static const struct irq_domain_ops tegra186_gpio_irq_domain_ops = {
 	.map = gpiochip_irq_map,
 	.unmap = gpiochip_irq_unmap,
-	.xlate = tegra186_gpio_irq_domain_xlate,
+	.xlate = gpio_banked_irq_domain_xlate,
 };
 
 static struct lock_class_key tegra186_gpio_lock_class;
@@ -420,6 +353,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	gpio->soc = of_device_get_match_data(&pdev->dev);
+	irq = &gpio->gpio.irq;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpio");
 	gpio->base = devm_ioremap_resource(&pdev->dev, res);
@@ -430,21 +364,47 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
 	if (err < 0)
 		return err;
 
-	gpio->num_irq = err;
+	irq->num_parents = err;
 
-	gpio->irq = devm_kcalloc(&pdev->dev, gpio->num_irq, sizeof(*gpio->irq),
-				 GFP_KERNEL);
-	if (!gpio->irq)
+	irq->parents = devm_kcalloc(&pdev->dev, irq->num_parents,
+				    sizeof(*irq->parents), GFP_KERNEL);
+	if (!irq->parents)
 		return -ENOMEM;
 
-	for (i = 0; i < gpio->num_irq; i++) {
+	for (i = 0; i < irq->num_parents; i++) {
 		err = platform_get_irq(pdev, i);
 		if (err < 0)
 			return err;
 
-		gpio->irq[i] = err;
+		irq->parents[i] = err;
 	}
 
+	gpio->ports = devm_kcalloc(&pdev->dev, gpio->soc->num_ports,
+				   sizeof(struct tegra_gpio_port),
+				   GFP_KERNEL);
+	if (!gpio->ports)
+		return -ENOMEM;
+
+	gpio->gpio.banks = devm_kcalloc(&pdev->dev, gpio->soc->num_ports,
+					sizeof(struct gpio_bank *),
+					GFP_KERNEL);
+	if (!gpio->gpio.banks)
+		return -ENOMEM;
+
+	for (i = 0; i < gpio->soc->num_ports; i++) {
+		const struct tegra_gpio_port_soc *soc = &gpio->soc->ports[i];
+		struct tegra_gpio_port *port = &gpio->ports[i];
+
+		gpio->gpio.banks[i] = &port->bank;
+		port->bank.parent_irq = soc->irq;
+		port->bank.num_pins = soc->pins;
+
+		port->offset = soc->offset;
+		port->name = soc->name;
+	}
+
+	gpio->gpio.num_banks = gpio->soc->num_ports;
+
 	gpio->gpio.label = gpio->soc->name;
 	gpio->gpio.parent = &pdev->dev;
 
@@ -465,7 +425,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	for (i = 0, offset = 0; i < gpio->soc->num_ports; i++) {
-		const struct tegra_gpio_port *port = &gpio->soc->ports[i];
+		const struct tegra_gpio_port_soc *port = &gpio->soc->ports[i];
 		char *name;
 
 		for (j = 0; j < port->pins; j++) {
@@ -484,7 +444,11 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
 
 	gpio->gpio.of_node = pdev->dev.of_node;
 	gpio->gpio.of_gpio_n_cells = 2;
-	gpio->gpio.of_xlate = tegra186_gpio_of_xlate;
+	gpio->gpio.of_gpio_bank_shift = 3;
+	gpio->gpio.of_gpio_bank_mask = 0x1fffffff;
+	gpio->gpio.of_gpio_pin_shift = 0;
+	gpio->gpio.of_gpio_pin_mask = 0x7;
+	gpio->gpio.of_xlate = of_gpio_banked_xlate;
 
 	gpio->intc.name = pdev->dev.of_node->name;
 	gpio->intc.irq_ack = tegra186_irq_ack;
@@ -492,31 +456,14 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
 	gpio->intc.irq_unmask = tegra186_irq_unmask;
 	gpio->intc.irq_set_type = tegra186_irq_set_type;
 
-	irq = &gpio->gpio.irq;
 	irq->chip = &gpio->intc;
 	irq->first = 0;
 	irq->domain_ops = &tegra186_gpio_irq_domain_ops;
 	irq->handler = handle_simple_irq;
 	irq->lock_key = &tegra186_gpio_lock_class;
 	irq->default_type = IRQ_TYPE_NONE;
-	irq->parent_handler = tegra186_gpio_irq;
-	irq->parent_handler_data = gpio;
-	irq->num_parents = gpio->num_irq;
-	irq->parents = gpio->irq;
-
-	irq->map = devm_kcalloc(&pdev->dev, gpio->gpio.ngpio,
-				sizeof(*irq->map), GFP_KERNEL);
-	if (!irq->map)
-		return -ENOMEM;
-
-	for (i = 0, offset = 0; i < gpio->soc->num_ports; i++) {
-		const struct tegra_gpio_port *port = &gpio->soc->ports[i];
-
-		for (j = 0; j < port->pins; j++)
-			irq->map[offset + j] = irq->parents[port->irq];
-
-		offset += port->pins;
-	}
+	irq->parent_handler = gpio_irq_chip_banked_handler;
+	irq->update_bank = tegra186_gpio_update_bank;
 
 	platform_set_drvdata(pdev, gpio);
 
@@ -540,7 +487,7 @@ static int tegra186_gpio_remove(struct platform_device *pdev)
 		.irq = controller,				\
 	}
 
-static const struct tegra_gpio_port tegra186_main_ports[] = {
+static const struct tegra_gpio_port_soc tegra186_main_ports[] = {
 	TEGRA_MAIN_GPIO_PORT( A, 0x2000, 7, 2),
 	TEGRA_MAIN_GPIO_PORT( B, 0x3000, 7, 3),
 	TEGRA_MAIN_GPIO_PORT( C, 0x3200, 7, 3),
@@ -580,7 +527,7 @@ static const struct tegra_gpio_soc tegra186_main_soc = {
 		.irq = controller,				\
 	}
 
-static const struct tegra_gpio_port tegra186_aon_ports[] = {
+static const struct tegra_gpio_port_soc tegra186_aon_ports[] = {
 	TEGRA_AON_GPIO_PORT( S, 0x0200, 5, 0),
 	TEGRA_AON_GPIO_PORT( U, 0x0400, 6, 0),
 	TEGRA_AON_GPIO_PORT( V, 0x0800, 8, 0),
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure
  2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
                   ` (15 preceding siblings ...)
  2017-09-01 18:57 ` [PATCH 16/16] gpio: tegra186: " Thierry Reding
@ 2017-09-14 13:54 ` Linus Walleij
  2017-09-15 15:09   ` Thierry Reding
  16 siblings, 1 reply; 27+ messages in thread
From: Linus Walleij @ 2017-09-14 13:54 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel,
	ext Tony Lindgren

On Fri, Sep 1, 2017 at 8:57 PM, Thierry Reding <thierry.reding@gmail.com> wrote:

> here's the latest series of patches that implement the tighter IRQ chip
> integration as well as the banked GPIO infrastructure that we had
> discussed a couple of weeks/months back.

Yes it has become really tasty now, don't you think :)

I really like the series.

Banks are handled in the core, exactly as I wanted.

I will likely go in and change some things I don't like, like switching
num_pins in the bank to num_lines. I have preferred that terminology
to avoid confusion with pin control. So GPIO chips have lines, not pins.
But it's so minor that I can fix it up if you don't want to.

We also need to go in and patch Documentation/gpio/driver.txt
to represent the current best practice. But that can be later,
separate patch.

> The first couple of patches are mostly preparatory work in order to
> consolidate all IRQ chip related fields in a new structure and create
> the base functionality for adding IRQ chips.
>
> After that, I've added the Tegra186 GPIO support patch that makes use of
> the new tight integration.
>
> To round things off the new banked GPIO infrastructure is added (along
> with some more preparatory work), followed by the conversion of the two
> Tegra GPIO drivers to the new infrastructure.

I have put all on a branch for pushing to the test builders to begin with.

Then I plan to make one branch with all infrastructure patches
(patches 1-10, 12-14) and pull that into devel, then apply patch
11 and 15-16 directly on devel.

That way other subsystems (pinctrl ...) can pull in the infrastructure
for people adding new gpiochips this cycle.

> Any thoughts on this? I'd like to target 4.15 with this,

Me, too.

> unless you'd be
> willing to take this into 4.14, which I doubt at this point. The absence
> of a GPIO driver has been hampering Tegra186 support upstream for a
> while now, so it'd be good to make progress on this.

Sorry about that. Let's move ahead with this now, it is neat and
clean.

What I want (as maintainer) is a bit of fingerpointing at the drivers
that need to be converted to use the new banking infrastructure
so they don't stay with their old crappy design pattern. OMAP is
a clear candidate right? (Added Tony to CC...)

Who else?

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 14/16] gpio: Add support for banked GPIO controllers
  2017-09-01 18:57 ` [PATCH 14/16] gpio: Add support for banked GPIO controllers Thierry Reding
@ 2017-09-14 13:59   ` Linus Walleij
  2017-09-14 23:37     ` Tony Lindgren
  0 siblings, 1 reply; 27+ messages in thread
From: Linus Walleij @ 2017-09-14 13:59 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel,
	ext Tony Lindgren

On Fri, Sep 1, 2017 at 8:57 PM, Thierry Reding <thierry.reding@gmail.com> wrote:

> From: Thierry Reding <treding@nvidia.com>
>
> Some GPIO controllers are subdivided into multiple logical blocks called
> banks (or ports). This is often caused by the design assigning separate
> resources, such as register regions or interrupts, to each bank, or some
> set of banks.
>
> This commit adds support for describing controllers that have such a
> banked design and provides common code for dealing with them.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>

This patch makes me really happy.

It pulls in a lot of weirdness to the OF core and creates a coherent
way of handling these "banked" GPIO chips.

CC to Tony to make sure he checks that OMAP is ready to use this
too.

I would change num_pins to num_lines everywhere in this patch,
so if you resend the series, please fix that.

> +void gpio_irq_chip_banked_handler(struct irq_desc *desc)

Maybe we should name this gpio_irq_chip_banked_chained_handler()
since it only deals with chained IRQs?

Sooner or later we will have a nested bank too...

Otherwise it looks fine.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 14/16] gpio: Add support for banked GPIO controllers
  2017-09-14 13:59   ` Linus Walleij
@ 2017-09-14 23:37     ` Tony Lindgren
  2017-09-14 23:49       ` Tony Lindgren
  0 siblings, 1 reply; 27+ messages in thread
From: Tony Lindgren @ 2017-09-14 23:37 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Thierry Reding, Jonathan Hunter, linux-gpio, linux-tegra,
	linux-kernel, Grygorii Strashko, linux-omap

* Linus Walleij <linus.walleij@linaro.org> [170914 07:00]:
> On Fri, Sep 1, 2017 at 8:57 PM, Thierry Reding <thierry.reding@gmail.com> wrote:
> 
> > From: Thierry Reding <treding@nvidia.com>
> >
> > Some GPIO controllers are subdivided into multiple logical blocks called
> > banks (or ports). This is often caused by the design assigning separate
> > resources, such as register regions or interrupts, to each bank, or some
> > set of banks.
> >
> > This commit adds support for describing controllers that have such a
> > banked design and provides common code for dealing with them.
> >
> > Signed-off-by: Thierry Reding <treding@nvidia.com>
> 
> This patch makes me really happy.
> 
> It pulls in a lot of weirdness to the OF core and creates a coherent
> way of handling these "banked" GPIO chips.
> 
> CC to Tony to make sure he checks that OMAP is ready to use this
> too.

Adding Grygorii to Cc as well, we'll take a look.

Probably the runtime PM will be an issue here still. We must currently
do runtime PM on per GPIO bank basis instead of per GPIO pin level as
we constantly runtime_suspend/resume the whole GPIO bank for idle modes
on the SoCs that support PM. So the usage count for the bank needs to
be either 0 or 1 and cannot be the lines used in the bank.

Regards,

Tony

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 14/16] gpio: Add support for banked GPIO controllers
  2017-09-14 23:37     ` Tony Lindgren
@ 2017-09-14 23:49       ` Tony Lindgren
  0 siblings, 0 replies; 27+ messages in thread
From: Tony Lindgren @ 2017-09-14 23:49 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Thierry Reding, Jonathan Hunter, linux-gpio, linux-tegra,
	linux-kernel, Grygorii Strashko, linux-omap

* Tony Lindgren <tony@atomide.com> [170914 16:38]:
> * Linus Walleij <linus.walleij@linaro.org> [170914 07:00]:
> > On Fri, Sep 1, 2017 at 8:57 PM, Thierry Reding <thierry.reding@gmail.com> wrote:
> > 
> > > From: Thierry Reding <treding@nvidia.com>
> > >
> > > Some GPIO controllers are subdivided into multiple logical blocks called
> > > banks (or ports). This is often caused by the design assigning separate
> > > resources, such as register regions or interrupts, to each bank, or some
> > > set of banks.
> > >
> > > This commit adds support for describing controllers that have such a
> > > banked design and provides common code for dealing with them.
> > >
> > > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > 
> > This patch makes me really happy.
> > 
> > It pulls in a lot of weirdness to the OF core and creates a coherent
> > way of handling these "banked" GPIO chips.
> > 
> > CC to Tony to make sure he checks that OMAP is ready to use this
> > too.
> 
> Adding Grygorii to Cc as well, we'll take a look.
> 
> Probably the runtime PM will be an issue here still. We must currently
> do runtime PM on per GPIO bank basis instead of per GPIO pin level as
> we constantly runtime_suspend/resume the whole GPIO bank for idle modes
> on the SoCs that support PM. So the usage count for the bank needs to
> be either 0 or 1 and cannot be the lines used in the bank.

And based on a quick look at this series it should not cause
problems there. For managing the banks in a generic way, I
like the idea too.

Regards,

Tony

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure
  2017-09-14 13:54 ` [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Linus Walleij
@ 2017-09-15 15:09   ` Thierry Reding
  2017-09-15 16:57     ` Tony Lindgren
  0 siblings, 1 reply; 27+ messages in thread
From: Thierry Reding @ 2017-09-15 15:09 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel,
	ext Tony Lindgren

[-- Attachment #1: Type: text/plain, Size: 3411 bytes --]

On Thu, Sep 14, 2017 at 03:54:56PM +0200, Linus Walleij wrote:
> On Fri, Sep 1, 2017 at 8:57 PM, Thierry Reding <thierry.reding@gmail.com> wrote:
> 
> > here's the latest series of patches that implement the tighter IRQ chip
> > integration as well as the banked GPIO infrastructure that we had
> > discussed a couple of weeks/months back.
> 
> Yes it has become really tasty now, don't you think :)
> 
> I really like the series.
> 
> Banks are handled in the core, exactly as I wanted.
> 
> I will likely go in and change some things I don't like, like switching
> num_pins in the bank to num_lines. I have preferred that terminology
> to avoid confusion with pin control. So GPIO chips have lines, not pins.
> But it's so minor that I can fix it up if you don't want to.

I rebased this on today's linux-next and noticed that there was a small
conflict. I can rebase and work in the changes that you requested.

I'm travelling this week and next, so it may take until after -rc2 that
I can send out a new version that's properly build-tested.

> We also need to go in and patch Documentation/gpio/driver.txt
> to represent the current best practice. But that can be later,
> separate patch.
> 
> > The first couple of patches are mostly preparatory work in order to
> > consolidate all IRQ chip related fields in a new structure and create
> > the base functionality for adding IRQ chips.
> >
> > After that, I've added the Tegra186 GPIO support patch that makes use of
> > the new tight integration.
> >
> > To round things off the new banked GPIO infrastructure is added (along
> > with some more preparatory work), followed by the conversion of the two
> > Tegra GPIO drivers to the new infrastructure.
> 
> I have put all on a branch for pushing to the test builders to begin with.
> 
> Then I plan to make one branch with all infrastructure patches
> (patches 1-10, 12-14) and pull that into devel, then apply patch
> 11 and 15-16 directly on devel.
> 
> That way other subsystems (pinctrl ...) can pull in the infrastructure
> for people adding new gpiochips this cycle.

Sounds good.

> > Any thoughts on this? I'd like to target 4.15 with this,
> 
> Me, too.
> 
> > unless you'd be
> > willing to take this into 4.14, which I doubt at this point. The absence
> > of a GPIO driver has been hampering Tegra186 support upstream for a
> > while now, so it'd be good to make progress on this.
> 
> Sorry about that. Let's move ahead with this now, it is neat and
> clean.
> 
> What I want (as maintainer) is a bit of fingerpointing at the drivers
> that need to be converted to use the new banking infrastructure
> so they don't stay with their old crappy design pattern. OMAP is
> a clear candidate right? (Added Tony to CC...)

OMAP should be able to use this infrastructure, but it may not want to
because the semantics would change slightly. Currently OMAP registers a
GPIO chip for each bank, whereas this infrastructure exposes multiple
banks via a single chip.

There might be some userspace that relies on the existence of multiple
chips, but Tony can probably knows that better than I.

> Who else?

gpio-intel-mid.c and gpio-merrifield.c look like they could use this new
infrastructure. So do gpio-pca953x.c, gpio-stmpe.c and gpio-tc3589x.c.

gpio-ws16c48.c is another one that uses a similar pattern.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure
  2017-09-15 15:09   ` Thierry Reding
@ 2017-09-15 16:57     ` Tony Lindgren
  2017-09-15 22:26       ` Grygorii Strashko
  2017-09-21 12:06       ` Linus Walleij
  0 siblings, 2 replies; 27+ messages in thread
From: Tony Lindgren @ 2017-09-15 16:57 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Linus Walleij, Jonathan Hunter, linux-gpio, linux-tegra,
	linux-kernel, Grygorii Strashko, linux-omap

* Thierry Reding <thierry.reding@gmail.com> [170915 08:10]:
> On Thu, Sep 14, 2017 at 03:54:56PM +0200, Linus Walleij wrote:
> > Sorry about that. Let's move ahead with this now, it is neat and
> > clean.
> > 
> > What I want (as maintainer) is a bit of fingerpointing at the drivers
> > that need to be converted to use the new banking infrastructure
> > so they don't stay with their old crappy design pattern. OMAP is
> > a clear candidate right? (Added Tony to CC...)
> 
> OMAP should be able to use this infrastructure, but it may not want to
> because the semantics would change slightly. Currently OMAP registers a
> GPIO chip for each bank, whereas this infrastructure exposes multiple
> banks via a single chip.

Oh so you don't have separate interrupts for the instances?
Thanks for clarifying that.

> There might be some userspace that relies on the existence of multiple
> chips, but Tony can probably knows that better than I.

On omaps, each bank is a separate driver instance with it's own
interrupt. Maybe really all we need to do is get rid of the "bank"
naming, I think that's left over from 15 years ago when we did not
have separate driver instances. It seems we should s/bank/ddata/
on the driver to avoid confusion.

Grygorii, any comments?

Regards,

Tony

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 12/16] gpio: omap: Fix checkpatch warnings
  2017-09-01 18:57 ` [PATCH 12/16] gpio: omap: Fix checkpatch warnings Thierry Reding
@ 2017-09-15 22:23   ` Grygorii Strashko
  0 siblings, 0 replies; 27+ messages in thread
From: Grygorii Strashko @ 2017-09-15 22:23 UTC (permalink / raw)
  To: Thierry Reding, Linus Walleij
  Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel



On 09/01/2017 01:57 PM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> Use unsigned int rather than unsigned, wrap lines longer than 80
> characters and other minor coding style cleanups.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>

I think it can be separated from this series.
Acked-by: Grygorii Strashko <grygorii.strashko@ti.com>

> ---
>   drivers/gpio/gpio-omap.c | 113 ++++++++++++++++++++++++++---------------------
>   1 file changed, 63 insertions(+), 50 deletions(-)
> 
> diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
> index ce27d6a586bf..7c600cec3e44 100644
> --- a/drivers/gpio/gpio-omap.c
> +++ b/drivers/gpio/gpio-omap.c
> @@ -76,7 +76,8 @@ struct gpio_bank {
>   	int power_mode;
>   	bool workaround_enabled;
>   
> -	void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable);
> +	void (*set_dataout)(struct gpio_bank *bank, unsigned int gpio,
> +			    int enable);
>   	int (*get_context_loss_count)(struct device *dev);
>   
>   	struct omap_gpio_reg_offs *regs;
> @@ -92,6 +93,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d);
>   static inline struct gpio_bank *omap_irq_data_get_bank(struct irq_data *d)
>   {
>   	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
> +
>   	return gpiochip_get_data(chip);
>   }
>   
> @@ -113,8 +115,8 @@ static void omap_set_gpio_direction(struct gpio_bank *bank, int gpio,
>   
>   
>   /* set data out value using dedicate set/clear register */
> -static void omap_set_gpio_dataout_reg(struct gpio_bank *bank, unsigned offset,
> -				      int enable)
> +static void omap_set_gpio_dataout_reg(struct gpio_bank *bank,
> +				      unsigned int offset, int enable)
>   {
>   	void __iomem *reg = bank->base;
>   	u32 l = BIT(offset);
> @@ -131,8 +133,8 @@ static void omap_set_gpio_dataout_reg(struct gpio_bank *bank, unsigned offset,
>   }
>   
>   /* set data out value using mask register */
> -static void omap_set_gpio_dataout_mask(struct gpio_bank *bank, unsigned offset,
> -				       int enable)
> +static void omap_set_gpio_dataout_mask(struct gpio_bank *bank,
> +				       unsigned int offset, int enable)
>   {
>   	void __iomem *reg = bank->base + bank->regs->dataout;
>   	u32 gpio_bit = BIT(offset);
> @@ -161,7 +163,8 @@ static int omap_get_gpio_dataout(struct gpio_bank *bank, int offset)
>   	return (readl_relaxed(reg) & (BIT(offset))) != 0;
>   }
>   
> -static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
> +static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask,
> +				 bool set)
>   {
>   	int l = readl_relaxed(base + reg);
>   
> @@ -211,8 +214,8 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
>    *
>    * Return: 0 on success, negative error otherwise.
>    */
> -static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
> -				   unsigned debounce)
> +static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned int offset,
> +				   unsigned int debounce)
>   {
>   	void __iomem		*reg;
>   	u32			val;
> @@ -272,7 +275,8 @@ static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
>    * time too. The debounce clock will also be disabled when calling this function
>    * if this is the only gpio in the bank using debounce.
>    */
> -static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned offset)
> +static void omap_clear_gpio_debounce(struct gpio_bank *bank,
> +				     unsigned int offset)
>   {
>   	u32 gpio_bit = BIT(offset);
>   
> @@ -284,8 +288,8 @@ static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned offset)
>   
>   	bank->dbck_enable_mask &= ~gpio_bit;
>   	bank->context.debounce_en &= ~gpio_bit;
> -        writel_relaxed(bank->context.debounce_en,
> -		     bank->base + bank->regs->debounce_en);
> +	writel_relaxed(bank->context.debounce_en,
> +		       bank->base + bank->regs->debounce_en);
>   
>   	if (!bank->dbck_enable_mask) {
>   		bank->context.debounce = 0;
> @@ -297,7 +301,7 @@ static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned offset)
>   }
>   
>   static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
> -						unsigned trigger)
> +					 unsigned int trigger)
>   {
>   	void __iomem *base = bank->base;
>   	u32 gpio_bit = BIT(gpio);
> @@ -321,7 +325,8 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
>   			readl_relaxed(bank->base + bank->regs->fallingdetect);
>   
>   	if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
> -		omap_gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0);
> +		omap_gpio_rmw(base, bank->regs->wkup_en, gpio_bit,
> +			      trigger != 0);
>   		bank->context.wake_en =
>   			readl_relaxed(bank->base + bank->regs->wkup_en);
>   	}
> @@ -376,11 +381,13 @@ static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
>   	writel_relaxed(l, reg);
>   }
>   #else
> -static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {}
> +static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
> +{
> +}
>   #endif
>   
>   static int omap_set_gpio_triggering(struct gpio_bank *bank, int gpio,
> -				    unsigned trigger)
> +				    unsigned int trigger)
>   {
>   	void __iomem *reg = bank->base;
>   	void __iomem *base = bank->base;
> @@ -425,7 +432,7 @@ static int omap_set_gpio_triggering(struct gpio_bank *bank, int gpio,
>   	return 0;
>   }
>   
> -static void omap_enable_gpio_module(struct gpio_bank *bank, unsigned offset)
> +static void omap_enable_gpio_module(struct gpio_bank *bank, unsigned int offset)
>   {
>   	if (bank->regs->pinctrl) {
>   		void __iomem *reg = bank->base + bank->regs->pinctrl;
> @@ -446,7 +453,8 @@ static void omap_enable_gpio_module(struct gpio_bank *bank, unsigned offset)
>   	}
>   }
>   
> -static void omap_disable_gpio_module(struct gpio_bank *bank, unsigned offset)
> +static void omap_disable_gpio_module(struct gpio_bank *bank,
> +				     unsigned int offset)
>   {
>   	void __iomem *base = bank->base;
>   
> @@ -471,14 +479,14 @@ static void omap_disable_gpio_module(struct gpio_bank *bank, unsigned offset)
>   	}
>   }
>   
> -static int omap_gpio_is_input(struct gpio_bank *bank, unsigned offset)
> +static int omap_gpio_is_input(struct gpio_bank *bank, unsigned int offset)
>   {
>   	void __iomem *reg = bank->base + bank->regs->direction;
>   
>   	return readl_relaxed(reg) & BIT(offset);
>   }
>   
> -static void omap_gpio_init_irq(struct gpio_bank *bank, unsigned offset)
> +static void omap_gpio_init_irq(struct gpio_bank *bank, unsigned int offset)
>   {
>   	if (!LINE_USED(bank->mod_usage, offset)) {
>   		omap_enable_gpio_module(bank, offset);
> @@ -487,12 +495,12 @@ static void omap_gpio_init_irq(struct gpio_bank *bank, unsigned offset)
>   	bank->irq_usage |= BIT(offset);
>   }
>   
> -static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
> +static int omap_gpio_irq_type(struct irq_data *d, unsigned int type)
>   {
>   	struct gpio_bank *bank = omap_irq_data_get_bank(d);
>   	int retval;
>   	unsigned long flags;
> -	unsigned offset = d->hwirq;
> +	unsigned int offset = d->hwirq;
>   
>   	if (type & ~IRQ_TYPE_SENSE_MASK)
>   		return -EINVAL;
> @@ -544,7 +552,7 @@ static void omap_clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
>   }
>   
>   static inline void omap_clear_gpio_irqstatus(struct gpio_bank *bank,
> -					     unsigned offset)
> +					     unsigned int offset)
>   {
>   	omap_clear_gpio_irqbank(bank, BIT(offset));
>   }
> @@ -608,7 +616,7 @@ static void omap_disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
>   }
>   
>   static inline void omap_set_gpio_irqenable(struct gpio_bank *bank,
> -					   unsigned offset, int enable)
> +					   unsigned int offset, int enable)
>   {
>   	if (enable)
>   		omap_enable_gpio_irqbank(bank, BIT(offset));
> @@ -624,7 +632,7 @@ static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable)
>   	return irq_set_irq_wake(bank->irq, enable);
>   }
>   
> -static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
> +static int omap_gpio_request(struct gpio_chip *chip, unsigned int offset)
>   {
>   	struct gpio_bank *bank = gpiochip_get_data(chip);
>   	unsigned long flags;
> @@ -644,7 +652,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
>   	return 0;
>   }
>   
> -static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
> +static void omap_gpio_free(struct gpio_chip *chip, unsigned int offset)
>   {
>   	struct gpio_bank *bank = gpiochip_get_data(chip);
>   	unsigned long flags;
> @@ -702,9 +710,11 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
>   		if (bank->level_mask)
>   			level_mask = bank->level_mask & enabled;
>   
> -		/* clear edge sensitive interrupts before handler(s) are
> -		called so that we don't miss any interrupt occurred while
> -		executing them */
> +		/*
> +		 * clear edge sensitive interrupts before handler(s) are
> +		 * called so that we don't miss any interrupt occurred while
> +		 * executing them
> +		 */
>   		omap_disable_gpio_irqbank(bank, isr_saved & ~level_mask);
>   		omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
>   		omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask);
> @@ -715,6 +725,8 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
>   			break;
>   
>   		while (isr) {
> +			unsigned int irq;
> +
>   			bit = __ffs(isr);
>   			isr &= ~(BIT(bit));
>   
> @@ -733,8 +745,8 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
>   
>   			raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags);
>   
> -			generic_handle_irq(irq_find_mapping(bank->chip.irq.domain,
> -							    bit));
> +			irq = irq_find_mapping(bank->chip.irq.domain, bit);
> +			generic_handle_irq(irq);
>   
>   			raw_spin_unlock_irqrestore(&bank->wa_lock,
>   						   wa_lock_flags);
> @@ -749,7 +761,7 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)
>   {
>   	struct gpio_bank *bank = omap_irq_data_get_bank(d);
>   	unsigned long flags;
> -	unsigned offset = d->hwirq;
> +	unsigned int offset = d->hwirq;
>   
>   	raw_spin_lock_irqsave(&bank->lock, flags);
>   
> @@ -773,7 +785,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
>   {
>   	struct gpio_bank *bank = omap_irq_data_get_bank(d);
>   	unsigned long flags;
> -	unsigned offset = d->hwirq;
> +	unsigned int offset = d->hwirq;
>   
>   	raw_spin_lock_irqsave(&bank->lock, flags);
>   	bank->irq_usage &= ~(BIT(offset));
> @@ -809,7 +821,7 @@ static void gpio_irq_bus_sync_unlock(struct irq_data *data)
>   static void omap_gpio_ack_irq(struct irq_data *d)
>   {
>   	struct gpio_bank *bank = omap_irq_data_get_bank(d);
> -	unsigned offset = d->hwirq;
> +	unsigned int offset = d->hwirq;
>   
>   	omap_clear_gpio_irqstatus(bank, offset);
>   }
> @@ -817,7 +829,7 @@ static void omap_gpio_ack_irq(struct irq_data *d)
>   static void omap_gpio_mask_irq(struct irq_data *d)
>   {
>   	struct gpio_bank *bank = omap_irq_data_get_bank(d);
> -	unsigned offset = d->hwirq;
> +	unsigned int offset = d->hwirq;
>   	unsigned long flags;
>   
>   	raw_spin_lock_irqsave(&bank->lock, flags);
> @@ -829,7 +841,7 @@ static void omap_gpio_mask_irq(struct irq_data *d)
>   static void omap_gpio_unmask_irq(struct irq_data *d)
>   {
>   	struct gpio_bank *bank = omap_irq_data_get_bank(d);
> -	unsigned offset = d->hwirq;
> +	unsigned int offset = d->hwirq;
>   	u32 trigger = irqd_get_trigger_type(d);
>   	unsigned long flags;
>   
> @@ -837,8 +849,10 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
>   	if (trigger)
>   		omap_set_gpio_triggering(bank, offset, trigger);
>   
> -	/* For level-triggered GPIOs, the clearing must be done after
> -	 * the HW source is cleared, thus after the handler has run */
> +	/*
> +	 * For level-triggered GPIOs, the clearing must be done after
> +	 * the HW source is cleared, thus after the handler has run
> +	 */
>   	if (bank->level_mask & BIT(offset)) {
>   		omap_set_gpio_irqenable(bank, offset, 0);
>   		omap_clear_gpio_irqstatus(bank, offset);
> @@ -912,7 +926,7 @@ static inline void omap_mpuio_init(struct gpio_bank *bank)
>   
>   /*---------------------------------------------------------------------*/
>   
> -static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
> +static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
>   {
>   	struct gpio_bank *bank;
>   	unsigned long flags;
> @@ -927,7 +941,7 @@ static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
>   	return dir;
>   }
>   
> -static int omap_gpio_input(struct gpio_chip *chip, unsigned offset)
> +static int omap_gpio_input(struct gpio_chip *chip, unsigned int offset)
>   {
>   	struct gpio_bank *bank;
>   	unsigned long flags;
> @@ -939,7 +953,7 @@ static int omap_gpio_input(struct gpio_chip *chip, unsigned offset)
>   	return 0;
>   }
>   
> -static int omap_gpio_get(struct gpio_chip *chip, unsigned offset)
> +static int omap_gpio_get(struct gpio_chip *chip, unsigned int offset)
>   {
>   	struct gpio_bank *bank;
>   
> @@ -951,7 +965,8 @@ static int omap_gpio_get(struct gpio_chip *chip, unsigned offset)
>   		return omap_get_gpio_dataout(bank, offset);
>   }
>   
> -static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value)
> +static int omap_gpio_output(struct gpio_chip *chip, unsigned int offset,
> +			    int value)
>   {
>   	struct gpio_bank *bank;
>   	unsigned long flags;
> @@ -964,8 +979,8 @@ static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value)
>   	return 0;
>   }
>   
> -static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
> -			      unsigned debounce)
> +static int omap_gpio_debounce(struct gpio_chip *chip, unsigned int offset,
> +			      unsigned int debounce)
>   {
>   	struct gpio_bank *bank;
>   	unsigned long flags;
> @@ -985,7 +1000,7 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
>   	return ret;
>   }
>   
> -static int omap_gpio_set_config(struct gpio_chip *chip, unsigned offset,
> +static int omap_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
>   				unsigned long config)
>   {
>   	u32 debounce;
> @@ -997,7 +1012,8 @@ static int omap_gpio_set_config(struct gpio_chip *chip, unsigned offset,
>   	return omap_gpio_debounce(chip, offset, debounce);
>   }
>   
> -static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
> +static void omap_gpio_set(struct gpio_chip *chip, unsigned int offset,
> +			  int value)
>   {
>   	struct gpio_bank *bank;
>   	unsigned long flags;
> @@ -1153,10 +1169,8 @@ static int omap_gpio_probe(struct platform_device *pdev)
>   		return -EINVAL;
>   
>   	bank = devm_kzalloc(dev, sizeof(struct gpio_bank), GFP_KERNEL);
> -	if (!bank) {
> -		dev_err(dev, "Memory alloc failed\n");
> +	if (!bank)
>   		return -ENOMEM;
> -	}
>   
>   	irqc = devm_kzalloc(dev, sizeof(*irqc), GFP_KERNEL);
>   	if (!irqc)
> @@ -1217,9 +1231,8 @@ static int omap_gpio_probe(struct platform_device *pdev)
>   	/* Static mapping, never released */
>   	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>   	bank->base = devm_ioremap_resource(dev, res);
> -	if (IS_ERR(bank->base)) {
> +	if (IS_ERR(bank->base))
>   		return PTR_ERR(bank->base);
> -	}
>   
>   	if (bank->dbck_flag) {
>   		bank->dbck = devm_clk_get(dev, "dbclk");
> 

-- 
regards,
-grygorii

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 13/16] gpio: omap: Rename struct gpio_bank to struct omap_gpio_bank
  2017-09-01 18:57 ` [PATCH 13/16] gpio: omap: Rename struct gpio_bank to struct omap_gpio_bank Thierry Reding
@ 2017-09-15 22:23   ` Grygorii Strashko
  0 siblings, 0 replies; 27+ messages in thread
From: Grygorii Strashko @ 2017-09-15 22:23 UTC (permalink / raw)
  To: Thierry Reding, Linus Walleij
  Cc: Jonathan Hunter, linux-gpio, linux-tegra, linux-kernel



On 09/01/2017 01:57 PM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> Subsequent patches will want to introduce a struct gpio_bank in core
> code, so rename this to something driver-specific in order to avoid the
> names from clashing.

I think it can be separated from this series.
Acked-by: Grygorii Strashko <grygorii.strashko@ti.com>

> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>   drivers/gpio/gpio-omap.c | 131 ++++++++++++++++++++++++-----------------------
>   1 file changed, 68 insertions(+), 63 deletions(-)
> 
> diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
> index 7c600cec3e44..0b80d929d892 100644
> --- a/drivers/gpio/gpio-omap.c
> +++ b/drivers/gpio/gpio-omap.c
> @@ -48,7 +48,7 @@ struct gpio_regs {
>   	u32 debounce_en;
>   };
>   
> -struct gpio_bank {
> +struct omap_gpio_bank {
>   	struct list_head node;
>   	void __iomem *base;
>   	int irq;
> @@ -76,7 +76,7 @@ struct gpio_bank {
>   	int power_mode;
>   	bool workaround_enabled;
>   
> -	void (*set_dataout)(struct gpio_bank *bank, unsigned int gpio,
> +	void (*set_dataout)(struct omap_gpio_bank *bank, unsigned int gpio,
>   			    int enable);
>   	int (*get_context_loss_count)(struct device *dev);
>   
> @@ -90,14 +90,14 @@ struct gpio_bank {
>   
>   static void omap_gpio_unmask_irq(struct irq_data *d);
>   
> -static inline struct gpio_bank *omap_irq_data_get_bank(struct irq_data *d)
> +static inline struct omap_gpio_bank *omap_irq_data_get_bank(struct irq_data *d)
>   {
>   	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
>   
>   	return gpiochip_get_data(chip);
>   }
>   
> -static void omap_set_gpio_direction(struct gpio_bank *bank, int gpio,
> +static void omap_set_gpio_direction(struct omap_gpio_bank *bank, int gpio,
>   				    int is_input)
>   {
>   	void __iomem *reg = bank->base;
> @@ -115,7 +115,7 @@ static void omap_set_gpio_direction(struct gpio_bank *bank, int gpio,
>   
>   
>   /* set data out value using dedicate set/clear register */
> -static void omap_set_gpio_dataout_reg(struct gpio_bank *bank,
> +static void omap_set_gpio_dataout_reg(struct omap_gpio_bank *bank,
>   				      unsigned int offset, int enable)
>   {
>   	void __iomem *reg = bank->base;
> @@ -133,7 +133,7 @@ static void omap_set_gpio_dataout_reg(struct gpio_bank *bank,
>   }
>   
>   /* set data out value using mask register */
> -static void omap_set_gpio_dataout_mask(struct gpio_bank *bank,
> +static void omap_set_gpio_dataout_mask(struct omap_gpio_bank *bank,
>   				       unsigned int offset, int enable)
>   {
>   	void __iomem *reg = bank->base + bank->regs->dataout;
> @@ -149,14 +149,14 @@ static void omap_set_gpio_dataout_mask(struct gpio_bank *bank,
>   	bank->context.dataout = l;
>   }
>   
> -static int omap_get_gpio_datain(struct gpio_bank *bank, int offset)
> +static int omap_get_gpio_datain(struct omap_gpio_bank *bank, int offset)
>   {
>   	void __iomem *reg = bank->base + bank->regs->datain;
>   
>   	return (readl_relaxed(reg) & (BIT(offset))) != 0;
>   }
>   
> -static int omap_get_gpio_dataout(struct gpio_bank *bank, int offset)
> +static int omap_get_gpio_dataout(struct omap_gpio_bank *bank, int offset)
>   {
>   	void __iomem *reg = bank->base + bank->regs->dataout;
>   
> @@ -176,7 +176,7 @@ static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask,
>   	writel_relaxed(l, base + reg);
>   }
>   
> -static inline void omap_gpio_dbck_enable(struct gpio_bank *bank)
> +static inline void omap_gpio_dbck_enable(struct omap_gpio_bank *bank)
>   {
>   	if (bank->dbck_enable_mask && !bank->dbck_enabled) {
>   		clk_enable(bank->dbck);
> @@ -187,7 +187,7 @@ static inline void omap_gpio_dbck_enable(struct gpio_bank *bank)
>   	}
>   }
>   
> -static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
> +static inline void omap_gpio_dbck_disable(struct omap_gpio_bank *bank)
>   {
>   	if (bank->dbck_enable_mask && bank->dbck_enabled) {
>   		/*
> @@ -214,8 +214,8 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
>    *
>    * Return: 0 on success, negative error otherwise.
>    */
> -static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned int offset,
> -				   unsigned int debounce)
> +static int omap2_set_gpio_debounce(struct omap_gpio_bank *bank,
> +				   unsigned int offset, unsigned int debounce)
>   {
>   	void __iomem		*reg;
>   	u32			val;
> @@ -275,7 +275,7 @@ static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned int offset,
>    * time too. The debounce clock will also be disabled when calling this function
>    * if this is the only gpio in the bank using debounce.
>    */
> -static void omap_clear_gpio_debounce(struct gpio_bank *bank,
> +static void omap_clear_gpio_debounce(struct omap_gpio_bank *bank,
>   				     unsigned int offset)
>   {
>   	u32 gpio_bit = BIT(offset);
> @@ -300,7 +300,7 @@ static void omap_clear_gpio_debounce(struct gpio_bank *bank,
>   	}
>   }
>   
> -static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
> +static inline void omap_set_gpio_trigger(struct omap_gpio_bank *bank, int gpio,
>   					 unsigned int trigger)
>   {
>   	void __iomem *base = bank->base;
> @@ -362,7 +362,8 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
>    * This only applies to chips that can't do both rising and falling edge
>    * detection at once.  For all other chips, this function is a noop.
>    */
> -static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
> +static void omap_toggle_gpio_edge_triggering(struct omap_gpio_bank *bank,
> +					     int gpio)
>   {
>   	void __iomem *reg = bank->base;
>   	u32 l = 0;
> @@ -381,12 +382,13 @@ static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
>   	writel_relaxed(l, reg);
>   }
>   #else
> -static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
> +static void omap_toggle_gpio_edge_triggering(struct omap_gpio_bank *bank,
> +					     int gpio)
>   {
>   }
>   #endif
>   
> -static int omap_set_gpio_triggering(struct gpio_bank *bank, int gpio,
> +static int omap_set_gpio_triggering(struct omap_gpio_bank *bank, int gpio,
>   				    unsigned int trigger)
>   {
>   	void __iomem *reg = bank->base;
> @@ -432,7 +434,8 @@ static int omap_set_gpio_triggering(struct gpio_bank *bank, int gpio,
>   	return 0;
>   }
>   
> -static void omap_enable_gpio_module(struct gpio_bank *bank, unsigned int offset)
> +static void omap_enable_gpio_module(struct omap_gpio_bank *bank,
> +				    unsigned int offset)
>   {
>   	if (bank->regs->pinctrl) {
>   		void __iomem *reg = bank->base + bank->regs->pinctrl;
> @@ -453,7 +456,7 @@ static void omap_enable_gpio_module(struct gpio_bank *bank, unsigned int offset)
>   	}
>   }
>   
> -static void omap_disable_gpio_module(struct gpio_bank *bank,
> +static void omap_disable_gpio_module(struct omap_gpio_bank *bank,
>   				     unsigned int offset)
>   {
>   	void __iomem *base = bank->base;
> @@ -479,14 +482,14 @@ static void omap_disable_gpio_module(struct gpio_bank *bank,
>   	}
>   }
>   
> -static int omap_gpio_is_input(struct gpio_bank *bank, unsigned int offset)
> +static int omap_gpio_is_input(struct omap_gpio_bank *bank, unsigned int offset)
>   {
>   	void __iomem *reg = bank->base + bank->regs->direction;
>   
>   	return readl_relaxed(reg) & BIT(offset);
>   }
>   
> -static void omap_gpio_init_irq(struct gpio_bank *bank, unsigned int offset)
> +static void omap_gpio_init_irq(struct omap_gpio_bank *bank, unsigned int offset)
>   {
>   	if (!LINE_USED(bank->mod_usage, offset)) {
>   		omap_enable_gpio_module(bank, offset);
> @@ -497,7 +500,7 @@ static void omap_gpio_init_irq(struct gpio_bank *bank, unsigned int offset)
>   
>   static int omap_gpio_irq_type(struct irq_data *d, unsigned int type)
>   {
> -	struct gpio_bank *bank = omap_irq_data_get_bank(d);
> +	struct omap_gpio_bank *bank = omap_irq_data_get_bank(d);
>   	int retval;
>   	unsigned long flags;
>   	unsigned int offset = d->hwirq;
> @@ -534,7 +537,7 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned int type)
>   	return retval;
>   }
>   
> -static void omap_clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
> +static void omap_clear_gpio_irqbank(struct omap_gpio_bank *bank, int gpio_mask)
>   {
>   	void __iomem *reg = bank->base;
>   
> @@ -551,13 +554,13 @@ static void omap_clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
>   	readl_relaxed(reg);
>   }
>   
> -static inline void omap_clear_gpio_irqstatus(struct gpio_bank *bank,
> +static inline void omap_clear_gpio_irqstatus(struct omap_gpio_bank *bank,
>   					     unsigned int offset)
>   {
>   	omap_clear_gpio_irqbank(bank, BIT(offset));
>   }
>   
> -static u32 omap_get_gpio_irqbank_mask(struct gpio_bank *bank)
> +static u32 omap_get_gpio_irqbank_mask(struct omap_gpio_bank *bank)
>   {
>   	void __iomem *reg = bank->base;
>   	u32 l;
> @@ -571,7 +574,7 @@ static u32 omap_get_gpio_irqbank_mask(struct gpio_bank *bank)
>   	return l;
>   }
>   
> -static void omap_enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
> +static void omap_enable_gpio_irqbank(struct omap_gpio_bank *bank, int gpio_mask)
>   {
>   	void __iomem *reg = bank->base;
>   	u32 l;
> @@ -593,7 +596,8 @@ static void omap_enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
>   	writel_relaxed(l, reg);
>   }
>   
> -static void omap_disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
> +static void omap_disable_gpio_irqbank(struct omap_gpio_bank *bank,
> +				      int gpio_mask)
>   {
>   	void __iomem *reg = bank->base;
>   	u32 l;
> @@ -615,7 +619,7 @@ static void omap_disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
>   	writel_relaxed(l, reg);
>   }
>   
> -static inline void omap_set_gpio_irqenable(struct gpio_bank *bank,
> +static inline void omap_set_gpio_irqenable(struct omap_gpio_bank *bank,
>   					   unsigned int offset, int enable)
>   {
>   	if (enable)
> @@ -627,14 +631,14 @@ static inline void omap_set_gpio_irqenable(struct gpio_bank *bank,
>   /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
>   static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable)
>   {
> -	struct gpio_bank *bank = omap_irq_data_get_bank(d);
> +	struct omap_gpio_bank *bank = omap_irq_data_get_bank(d);
>   
>   	return irq_set_irq_wake(bank->irq, enable);
>   }
>   
>   static int omap_gpio_request(struct gpio_chip *chip, unsigned int offset)
>   {
> -	struct gpio_bank *bank = gpiochip_get_data(chip);
> +	struct omap_gpio_bank *bank = gpiochip_get_data(chip);
>   	unsigned long flags;
>   
>   	/*
> @@ -654,7 +658,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned int offset)
>   
>   static void omap_gpio_free(struct gpio_chip *chip, unsigned int offset)
>   {
> -	struct gpio_bank *bank = gpiochip_get_data(chip);
> +	struct omap_gpio_bank *bank = gpiochip_get_data(chip);
>   	unsigned long flags;
>   
>   	raw_spin_lock_irqsave(&bank->lock, flags);
> @@ -688,7 +692,7 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
>   	void __iomem *isr_reg = NULL;
>   	u32 isr;
>   	unsigned int bit;
> -	struct gpio_bank *bank = gpiobank;
> +	struct omap_gpio_bank *bank = gpiobank;
>   	unsigned long wa_lock_flags;
>   	unsigned long lock_flags;
>   
> @@ -759,7 +763,7 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
>   
>   static unsigned int omap_gpio_irq_startup(struct irq_data *d)
>   {
> -	struct gpio_bank *bank = omap_irq_data_get_bank(d);
> +	struct omap_gpio_bank *bank = omap_irq_data_get_bank(d);
>   	unsigned long flags;
>   	unsigned int offset = d->hwirq;
>   
> @@ -783,7 +787,7 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)
>   
>   static void omap_gpio_irq_shutdown(struct irq_data *d)
>   {
> -	struct gpio_bank *bank = omap_irq_data_get_bank(d);
> +	struct omap_gpio_bank *bank = omap_irq_data_get_bank(d);
>   	unsigned long flags;
>   	unsigned int offset = d->hwirq;
>   
> @@ -800,7 +804,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
>   
>   static void omap_gpio_irq_bus_lock(struct irq_data *data)
>   {
> -	struct gpio_bank *bank = omap_irq_data_get_bank(data);
> +	struct omap_gpio_bank *bank = omap_irq_data_get_bank(data);
>   
>   	if (!BANK_USED(bank))
>   		pm_runtime_get_sync(bank->chip.parent);
> @@ -808,7 +812,7 @@ static void omap_gpio_irq_bus_lock(struct irq_data *data)
>   
>   static void gpio_irq_bus_sync_unlock(struct irq_data *data)
>   {
> -	struct gpio_bank *bank = omap_irq_data_get_bank(data);
> +	struct omap_gpio_bank *bank = omap_irq_data_get_bank(data);
>   
>   	/*
>   	 * If this is the last IRQ to be freed in the bank,
> @@ -820,7 +824,7 @@ static void gpio_irq_bus_sync_unlock(struct irq_data *data)
>   
>   static void omap_gpio_ack_irq(struct irq_data *d)
>   {
> -	struct gpio_bank *bank = omap_irq_data_get_bank(d);
> +	struct omap_gpio_bank *bank = omap_irq_data_get_bank(d);
>   	unsigned int offset = d->hwirq;
>   
>   	omap_clear_gpio_irqstatus(bank, offset);
> @@ -828,7 +832,7 @@ static void omap_gpio_ack_irq(struct irq_data *d)
>   
>   static void omap_gpio_mask_irq(struct irq_data *d)
>   {
> -	struct gpio_bank *bank = omap_irq_data_get_bank(d);
> +	struct omap_gpio_bank *bank = omap_irq_data_get_bank(d);
>   	unsigned int offset = d->hwirq;
>   	unsigned long flags;
>   
> @@ -840,7 +844,7 @@ static void omap_gpio_mask_irq(struct irq_data *d)
>   
>   static void omap_gpio_unmask_irq(struct irq_data *d)
>   {
> -	struct gpio_bank *bank = omap_irq_data_get_bank(d);
> +	struct omap_gpio_bank *bank = omap_irq_data_get_bank(d);
>   	unsigned int offset = d->hwirq;
>   	u32 trigger = irqd_get_trigger_type(d);
>   	unsigned long flags;
> @@ -867,7 +871,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
>   static int omap_mpuio_suspend_noirq(struct device *dev)
>   {
>   	struct platform_device *pdev = to_platform_device(dev);
> -	struct gpio_bank	*bank = platform_get_drvdata(pdev);
> +	struct omap_gpio_bank	*bank = platform_get_drvdata(pdev);
>   	void __iomem		*mask_reg = bank->base +
>   					OMAP_MPUIO_GPIO_MASKIT / bank->stride;
>   	unsigned long		flags;
> @@ -882,7 +886,7 @@ static int omap_mpuio_suspend_noirq(struct device *dev)
>   static int omap_mpuio_resume_noirq(struct device *dev)
>   {
>   	struct platform_device *pdev = to_platform_device(dev);
> -	struct gpio_bank	*bank = platform_get_drvdata(pdev);
> +	struct omap_gpio_bank	*bank = platform_get_drvdata(pdev);
>   	void __iomem		*mask_reg = bank->base +
>   					OMAP_MPUIO_GPIO_MASKIT / bank->stride;
>   	unsigned long		flags;
> @@ -916,7 +920,7 @@ static struct platform_device omap_mpuio_device = {
>   	/* could list the /proc/iomem resources */
>   };
>   
> -static inline void omap_mpuio_init(struct gpio_bank *bank)
> +static inline void omap_mpuio_init(struct omap_gpio_bank *bank)
>   {
>   	platform_set_drvdata(&omap_mpuio_device, bank);
>   
> @@ -928,7 +932,7 @@ static inline void omap_mpuio_init(struct gpio_bank *bank)
>   
>   static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
>   {
> -	struct gpio_bank *bank;
> +	struct omap_gpio_bank *bank;
>   	unsigned long flags;
>   	void __iomem *reg;
>   	int dir;
> @@ -943,7 +947,7 @@ static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
>   
>   static int omap_gpio_input(struct gpio_chip *chip, unsigned int offset)
>   {
> -	struct gpio_bank *bank;
> +	struct omap_gpio_bank *bank;
>   	unsigned long flags;
>   
>   	bank = gpiochip_get_data(chip);
> @@ -955,7 +959,7 @@ static int omap_gpio_input(struct gpio_chip *chip, unsigned int offset)
>   
>   static int omap_gpio_get(struct gpio_chip *chip, unsigned int offset)
>   {
> -	struct gpio_bank *bank;
> +	struct omap_gpio_bank *bank;
>   
>   	bank = gpiochip_get_data(chip);
>   
> @@ -968,7 +972,7 @@ static int omap_gpio_get(struct gpio_chip *chip, unsigned int offset)
>   static int omap_gpio_output(struct gpio_chip *chip, unsigned int offset,
>   			    int value)
>   {
> -	struct gpio_bank *bank;
> +	struct omap_gpio_bank *bank;
>   	unsigned long flags;
>   
>   	bank = gpiochip_get_data(chip);
> @@ -982,7 +986,7 @@ static int omap_gpio_output(struct gpio_chip *chip, unsigned int offset,
>   static int omap_gpio_debounce(struct gpio_chip *chip, unsigned int offset,
>   			      unsigned int debounce)
>   {
> -	struct gpio_bank *bank;
> +	struct omap_gpio_bank *bank;
>   	unsigned long flags;
>   	int ret;
>   
> @@ -1015,7 +1019,7 @@ static int omap_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
>   static void omap_gpio_set(struct gpio_chip *chip, unsigned int offset,
>   			  int value)
>   {
> -	struct gpio_bank *bank;
> +	struct omap_gpio_bank *bank;
>   	unsigned long flags;
>   
>   	bank = gpiochip_get_data(chip);
> @@ -1026,7 +1030,7 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned int offset,
>   
>   /*---------------------------------------------------------------------*/
>   
> -static void __init omap_gpio_show_rev(struct gpio_bank *bank)
> +static void __init omap_gpio_show_rev(struct omap_gpio_bank *bank)
>   {
>   	static bool called;
>   	u32 rev;
> @@ -1041,7 +1045,7 @@ static void __init omap_gpio_show_rev(struct gpio_bank *bank)
>   	called = true;
>   }
>   
> -static void omap_gpio_mod_init(struct gpio_bank *bank)
> +static void omap_gpio_mod_init(struct omap_gpio_bank *bank)
>   {
>   	void __iomem *base = bank->base;
>   	u32 l = 0xffffffff;
> @@ -1068,7 +1072,8 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
>   		writel_relaxed(0, base + bank->regs->ctrl);
>   }
>   
> -static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
> +static int omap_gpio_chip_init(struct omap_gpio_bank *bank,
> +			       struct irq_chip *irqc)
>   {
>   	static int gpio;
>   	int irq_base = 0;
> @@ -1158,7 +1163,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
>   	const struct of_device_id *match;
>   	const struct omap_gpio_platform_data *pdata;
>   	struct resource *res;
> -	struct gpio_bank *bank;
> +	struct omap_gpio_bank *bank;
>   	struct irq_chip *irqc;
>   	int ret;
>   
> @@ -1168,7 +1173,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
>   	if (!pdata)
>   		return -EINVAL;
>   
> -	bank = devm_kzalloc(dev, sizeof(struct gpio_bank), GFP_KERNEL);
> +	bank = devm_kzalloc(dev, sizeof(struct omap_gpio_bank), GFP_KERNEL);
>   	if (!bank)
>   		return -ENOMEM;
>   
> @@ -1276,7 +1281,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
>   
>   static int omap_gpio_remove(struct platform_device *pdev)
>   {
> -	struct gpio_bank *bank = platform_get_drvdata(pdev);
> +	struct omap_gpio_bank *bank = platform_get_drvdata(pdev);
>   
>   	list_del(&bank->node);
>   	gpiochip_remove(&bank->chip);
> @@ -1290,12 +1295,12 @@ static int omap_gpio_remove(struct platform_device *pdev)
>   #ifdef CONFIG_ARCH_OMAP2PLUS
>   
>   #if defined(CONFIG_PM)
> -static void omap_gpio_restore_context(struct gpio_bank *bank);
> +static void omap_gpio_restore_context(struct omap_gpio_bank *bank);
>   
>   static int omap_gpio_runtime_suspend(struct device *dev)
>   {
>   	struct platform_device *pdev = to_platform_device(dev);
> -	struct gpio_bank *bank = platform_get_drvdata(pdev);
> +	struct omap_gpio_bank *bank = platform_get_drvdata(pdev);
>   	u32 l1 = 0, l2 = 0;
>   	unsigned long flags;
>   	u32 wake_low, wake_hi;
> @@ -1358,12 +1363,12 @@ static int omap_gpio_runtime_suspend(struct device *dev)
>   	return 0;
>   }
>   
> -static void omap_gpio_init_context(struct gpio_bank *p);
> +static void omap_gpio_init_context(struct omap_gpio_bank *p);
>   
>   static int omap_gpio_runtime_resume(struct device *dev)
>   {
>   	struct platform_device *pdev = to_platform_device(dev);
> -	struct gpio_bank *bank = platform_get_drvdata(pdev);
> +	struct omap_gpio_bank *bank = platform_get_drvdata(pdev);
>   	u32 l = 0, gen, gen0, gen1;
>   	unsigned long flags;
>   	int c;
> @@ -1475,7 +1480,7 @@ static int omap_gpio_runtime_resume(struct device *dev)
>   #if IS_BUILTIN(CONFIG_GPIO_OMAP)
>   void omap2_gpio_prepare_for_idle(int pwr_mode)
>   {
> -	struct gpio_bank *bank;
> +	struct omap_gpio_bank *bank;
>   
>   	list_for_each_entry(bank, &omap_gpio_list, node) {
>   		if (!BANK_USED(bank) || !bank->loses_context)
> @@ -1489,7 +1494,7 @@ void omap2_gpio_prepare_for_idle(int pwr_mode)
>   
>   void omap2_gpio_resume_after_idle(void)
>   {
> -	struct gpio_bank *bank;
> +	struct omap_gpio_bank *bank;
>   
>   	list_for_each_entry(bank, &omap_gpio_list, node) {
>   		if (!BANK_USED(bank) || !bank->loses_context)
> @@ -1501,7 +1506,7 @@ void omap2_gpio_resume_after_idle(void)
>   #endif
>   
>   #if defined(CONFIG_PM)
> -static void omap_gpio_init_context(struct gpio_bank *p)
> +static void omap_gpio_init_context(struct omap_gpio_bank *p)
>   {
>   	struct omap_gpio_reg_offs *regs = p->regs;
>   	void __iomem *base = p->base;
> @@ -1524,7 +1529,7 @@ static void omap_gpio_init_context(struct gpio_bank *p)
>   	p->context_valid = true;
>   }
>   
> -static void omap_gpio_restore_context(struct gpio_bank *bank)
> +static void omap_gpio_restore_context(struct omap_gpio_bank *bank)
>   {
>   	writel_relaxed(bank->context.wake_en,
>   				bank->base + bank->regs->wkup_en);
> @@ -1561,7 +1566,7 @@ static void omap_gpio_restore_context(struct gpio_bank *bank)
>   #else
>   #define omap_gpio_runtime_suspend NULL
>   #define omap_gpio_runtime_resume NULL
> -static inline void omap_gpio_init_context(struct gpio_bank *p) {}
> +static inline void omap_gpio_init_context(struct omap_gpio_bank *p) {}
>   #endif
>   
>   static const struct dev_pm_ops gpio_pm_ops = {
> 

-- 
regards,
-grygorii

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure
  2017-09-15 16:57     ` Tony Lindgren
@ 2017-09-15 22:26       ` Grygorii Strashko
  2017-09-21 12:06       ` Linus Walleij
  1 sibling, 0 replies; 27+ messages in thread
From: Grygorii Strashko @ 2017-09-15 22:26 UTC (permalink / raw)
  To: Tony Lindgren, Thierry Reding
  Cc: Linus Walleij, Jonathan Hunter, linux-gpio, linux-tegra,
	linux-kernel, linux-omap



On 09/15/2017 11:57 AM, Tony Lindgren wrote:
> * Thierry Reding <thierry.reding@gmail.com> [170915 08:10]:
>> On Thu, Sep 14, 2017 at 03:54:56PM +0200, Linus Walleij wrote:
>>> Sorry about that. Let's move ahead with this now, it is neat and
>>> clean.
>>>
>>> What I want (as maintainer) is a bit of fingerpointing at the drivers
>>> that need to be converted to use the new banking infrastructure
>>> so they don't stay with their old crappy design pattern. OMAP is
>>> a clear candidate right? (Added Tony to CC...)
>>
>> OMAP should be able to use this infrastructure, but it may not want to
>> because the semantics would change slightly. Currently OMAP registers a
>> GPIO chip for each bank, whereas this infrastructure exposes multiple
>> banks via a single chip.
> 
> Oh so you don't have separate interrupts for the instances?
> Thanks for clarifying that.
> 
>> There might be some userspace that relies on the existence of multiple
>> chips, but Tony can probably knows that better than I.
> 
> On omaps, each bank is a separate driver instance with it's own
> interrupt. Maybe really all we need to do is get rid of the "bank"
> naming, I think that's left over from 15 years ago when we did not
> have separate driver instances. It seems we should s/bank/ddata/
> on the driver to avoid confusion.
> 
> Grygorii, any comments?

Sry, for delayed reply - I've saw this series, but, honestly, it's very big 
change for review :(

So, can it be split? I think, patches which reorganize gpio irqchip specific fields placement 
and move them in gpio_irq_chip can be considered separately if they will not introduce
functional changes. Also, omap changes can be considered separately.
(Pay attention that new fields introduced in patch 1).  

Regarding OMAP GPIO - right now I do not see how it can be applied for OMAP :(
Each OMAP GPIO bank is standalone device which can be enabled/disabled, 
powered on/off in Linux. There are no contiguous MMIO space and each GPIO
bank have separate MMIO space.

I really, need more time to review this idea and I think that it can be done
more easily if series size will be reduced.

Few more notes:
- pay attention on commit dc749a0 "gpiolib: allow gpio irqchip to map irqs dynamically"
- good to see binding and DT examples
- not sure if I've got idea of encoding bank&pin in spec[0] :(

+	bank = (spec[0] >> gc->of_gpio_bank_mask) & gc->of_gpio_bank_shift;
+	pin = (spec[0] >> gc->of_gpio_pin_mask) & gc->of_gpio_pin_shift;

- irq "mapping" inside gpio_irq_chip is not clear :( does it static?
does it require one array item/per pin - sry, this is waste of memory?

irq->map[offset + j] = irq->parents[parent];

Potentially, this feature can be applied to Davinci GPIO driver, which
is GPIO controller divided in multiple logical banks and which also have
set of common registers for all logical banks. But, again, not sure how
effective this implementation is - need more time. As of now, we perfectly 
handle this in Davinci GPIO driver by creating only ONE gpio_chip which hides
HW details in driver and still uses standard irq DT mappings:
 <&gpio0 140 GPIO_ACTIVE_LOW>;

By the way Patch 14 adds 300 lines, while patch changes 200 lines, so
in terms of code lines this feature seems is not very efficient.
(same for Patch 15, 16)

-- 
regards,
-grygorii

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure
  2017-09-15 16:57     ` Tony Lindgren
  2017-09-15 22:26       ` Grygorii Strashko
@ 2017-09-21 12:06       ` Linus Walleij
  1 sibling, 0 replies; 27+ messages in thread
From: Linus Walleij @ 2017-09-21 12:06 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Thierry Reding, Jonathan Hunter, linux-gpio, linux-tegra,
	linux-kernel, Grygorii Strashko, Linux-OMAP

On Fri, Sep 15, 2017 at 6:57 PM, Tony Lindgren <tony@atomide.com> wrote:

> On omaps, each bank is a separate driver instance with it's own
> interrupt. Maybe really all we need to do is get rid of the "bank"
> naming, I think that's left over from 15 years ago when we did not
> have separate driver instances. It seems we should s/bank/ddata/
> on the driver to avoid confusion.

OK sorry maybe OMAP is not a target for this, I just thought so
since it was one of the platforms that is patches in the patch
series.

But I'm pretty sure we have chips with banking like this: separate
interrupts but a single device. I would have to read through them
all I guess.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2017-09-21 12:06 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-01 18:57 [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Thierry Reding
2017-09-01 18:57 ` [PATCH 01/16] gpio: Implement tighter IRQ chip integration Thierry Reding
2017-09-01 18:57 ` [PATCH 02/16] gpio: Move irqchip into struct gpio_irq_chip Thierry Reding
2017-09-01 18:57 ` [PATCH 03/16] gpio: Move irqdomain " Thierry Reding
2017-09-01 18:57 ` [PATCH 04/16] gpio: Move irq_base to " Thierry Reding
2017-09-01 18:57 ` [PATCH 05/16] gpio: Move irq_handler " Thierry Reding
2017-09-01 18:57 ` [PATCH 06/16] gpio: Move irq_default_type " Thierry Reding
2017-09-01 18:57 ` [PATCH 07/16] gpio: Move irq_chained_parent " Thierry Reding
2017-09-01 18:57 ` [PATCH 08/16] gpio: Move irq_nested into " Thierry Reding
2017-09-01 18:57 ` [PATCH 09/16] gpio: Move irq_valid_mask " Thierry Reding
2017-09-01 18:57 ` [PATCH 10/16] gpio: Move lock_key " Thierry Reding
2017-09-01 18:57 ` [PATCH 11/16] gpio: Add Tegra186 support Thierry Reding
2017-09-01 18:57 ` [PATCH 12/16] gpio: omap: Fix checkpatch warnings Thierry Reding
2017-09-15 22:23   ` Grygorii Strashko
2017-09-01 18:57 ` [PATCH 13/16] gpio: omap: Rename struct gpio_bank to struct omap_gpio_bank Thierry Reding
2017-09-15 22:23   ` Grygorii Strashko
2017-09-01 18:57 ` [PATCH 14/16] gpio: Add support for banked GPIO controllers Thierry Reding
2017-09-14 13:59   ` Linus Walleij
2017-09-14 23:37     ` Tony Lindgren
2017-09-14 23:49       ` Tony Lindgren
2017-09-01 18:57 ` [PATCH 15/16] gpio: tegra: Use banked GPIO infrastructure Thierry Reding
2017-09-01 18:57 ` [PATCH 16/16] gpio: tegra186: " Thierry Reding
2017-09-14 13:54 ` [PATCH 00/16] gpio: Tight IRQ chip integration and banked infrastructure Linus Walleij
2017-09-15 15:09   ` Thierry Reding
2017-09-15 16:57     ` Tony Lindgren
2017-09-15 22:26       ` Grygorii Strashko
2017-09-21 12:06       ` Linus Walleij

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).