[PATCH v3 1/2] gpio: tegra: add multiple interrupt support

From: Prathamesh Shete
Date: Tue Sep 07 2021 - 03:32:57 EST


From: pshete <pshete@xxxxxxxxxx>

T19x GPIO controller's support multiple interrupts. The GPIO
controller is capable to route 8 interrupts per controller in
case of NON-AON GPIO's and 4 interrupts per controller in AON GPIO.
This is new feature starting Tegra194
The interrupt route map determines which interrupt line is to be used.

Signed-off-by: Prathamesh Shete <pshete@xxxxxxxxxx>
---
drivers/gpio/gpio-tegra186.c | 27 ++++++++++++++++++++++-----
1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
index d38980b9923a..c1172da9aebf 100644
--- a/drivers/gpio/gpio-tegra186.c
+++ b/drivers/gpio/gpio-tegra186.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2016-2017 NVIDIA Corporation
+ * Copyright (c) 2016-2021 NVIDIA Corporation
*
* Author: Thierry Reding <treding@xxxxxxxxxx>
*/
@@ -68,6 +68,7 @@ struct tegra_gpio_soc {
unsigned int num_ports;
const char *name;
unsigned int instance;
+ bool multi_ints;

const struct tegra186_pin_range *pin_ranges;
unsigned int num_pin_ranges;
@@ -450,7 +451,8 @@ static void tegra186_gpio_irq(struct irq_desc *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;
+ unsigned int i, j, offset = 0;
+ int intr_cntr;

chained_irq_enter(chip, desc);

@@ -462,9 +464,20 @@ static void tegra186_gpio_irq(struct irq_desc *desc)

base = gpio->base + port->bank * 0x1000 + port->port * 0x200;

- /* skip ports that are not associated with this bank */
- if (parent != gpio->irq[port->bank])
- goto skip;
+ if (!gpio->soc->multi_ints) {
+ /* skip ports that are not associated with this bank */
+ if (parent != gpio->irq[port->bank])
+ goto skip;
+
+ } else {
+ intr_cntr = 0;
+ for (j = 0; j < 8; j++) {
+ if (parent != gpio->irq[(port->bank * 8) + j])
+ intr_cntr++;
+ }
+ if (!(intr_cntr & 0xF))
+ goto skip;
+ }

value = readl(base + TEGRA186_GPIO_INTERRUPT_STATUS(1));

@@ -772,6 +785,7 @@ static const struct tegra_gpio_soc tegra186_main_soc = {
.ports = tegra186_main_ports,
.name = "tegra186-gpio",
.instance = 0,
+ .multi_ints = false,
};

#define TEGRA186_AON_GPIO_PORT(_name, _bank, _port, _pins) \
@@ -798,6 +812,7 @@ static const struct tegra_gpio_soc tegra186_aon_soc = {
.ports = tegra186_aon_ports,
.name = "tegra186-gpio-aon",
.instance = 1,
+ .multi_ints = false,
};

#define TEGRA194_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \
@@ -852,6 +867,7 @@ static const struct tegra_gpio_soc tegra194_main_soc = {
.num_pin_ranges = ARRAY_SIZE(tegra194_main_pin_ranges),
.pin_ranges = tegra194_main_pin_ranges,
.pinmux = "nvidia,tegra194-pinmux",
+ .multi_ints = true,
};

#define TEGRA194_AON_GPIO_PORT(_name, _bank, _port, _pins) \
@@ -875,6 +891,7 @@ static const struct tegra_gpio_soc tegra194_aon_soc = {
.ports = tegra194_aon_ports,
.name = "tegra194-gpio-aon",
.instance = 1,
+ .multi_ints = true,
};

static const struct of_device_id tegra186_gpio_of_match[] = {
--
2.17.1