diff mbox

[3/5] gpio: davinci: irq support for multiple gpio controllers

Message ID 1476855239-32730-4-git-send-email-j-keerthy@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

J, KEERTHY Oct. 19, 2016, 5:33 a.m. UTC
From: Grygorii Strashko <grygorii.strashko@ti.com>

The Davinci GPIO driver is implemented to work with one monolithic
Davinci GPIO platform device which may have up to Y(144) gpios.
The Davinci GPIO driver instantiates number of GPIO chips with
max 32 gpio pins per each during initialization and one IRQ domain.
So, the current GPIO's  opjects structure is:

<platform device> Davinci GPIO controller
 |- <gpio0_chip0> ------|
 ...                    |--- irq_domain (hwirq [0..143])
 |- <gpio0_chipN> ------|

The gpio2hwirq conversation is performing in the following way:
hwirq = gpio0_chipX.base + gpio_offsetN

where gpio_offsetN is gpio pin number inside gpio0_chipX
and gpio0_chipX.base can have values 0..128 with step 32.

Above will work properly only when one Davinci GPIO controller is
present, but if second one (68 gpios) is added IRQs will not work for it,
because gpio1_chipX.base will have values 144..208 with step 32 and
above formula will not work any more.

Hence, update Davinci GPIO driver to handle this situation properly:
- add new field in struct davinci_gpio_controller.ctrl_base and
  save Linux GPIO number of the first GPIO assigned to the Davinci GPIO
  controller in .probe() - value of static variable "bank_base";
- correct gpio2hwirq conversation formula as below
  hwirq = (gpio0_chipX.base - gpio_controller.ctrl_base) + gpio_offsetN

Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
[j-keerthy@ti.com added the ctrl_base to keep track of gpios per controller]
Signed-off-by: Keerthy <j-keerthy@ti.com>
---
 drivers/gpio/gpio-davinci.c                | 28 ++++++++++++++++++++++------
 include/linux/platform_data/gpio-davinci.h |  1 +
 2 files changed, 23 insertions(+), 6 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index 2654dae..2bc308a 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -176,7 +176,7 @@  static int davinci_gpio_of_xlate(struct gpio_chip *gc,
 
 static int davinci_gpio_probe(struct platform_device *pdev)
 {
-	int i, base;
+	int i, base, temp_ctrl_base;
 	unsigned ngpio, nbank;
 	struct davinci_gpio_controller *chips;
 	struct davinci_gpio_platform_data *pdata;
@@ -219,6 +219,8 @@  static int davinci_gpio_probe(struct platform_device *pdev)
 	if (IS_ERR(gpio_base))
 		return PTR_ERR(gpio_base);
 
+	temp_ctrl_base = bank_base;
+
 	for (i = 0, base = 0; base < ngpio; i++, base += 32) {
 		chips[i].chip.label = "DaVinci";
 
@@ -228,10 +230,13 @@  static int davinci_gpio_probe(struct platform_device *pdev)
 		chips[i].chip.set = davinci_gpio_set;
 
 		chips[i].chip.base = bank_base;
+		chips[i].ctrl_base = temp_ctrl_base;
 		bank_base += 32;
 		chips[i].chip.ngpio = ngpio - base;
 		if (chips[i].chip.ngpio > 32)
 			chips[i].chip.ngpio = 32;
+		else
+			bank_base = ngpio;
 
 #ifdef CONFIG_OF_GPIO
 		chips[i].chip.of_gpio_n_cells = 2;
@@ -329,6 +334,7 @@  static void gpio_irq_handler(struct irq_desc *desc)
 	while (1) {
 		u32		status;
 		int		bit;
+		irq_hw_number_t hw_irq;
 
 		/* ack any irqs */
 		status = readl_relaxed(&g->intstat) & mask;
@@ -341,9 +347,13 @@  static void gpio_irq_handler(struct irq_desc *desc)
 		while (status) {
 			bit = __ffs(status);
 			status &= ~BIT(bit);
+			/* Max number of gpios per controller is 144 so
+			 * hw_irq will be in [0..143]
+			 */
+			hw_irq = (d->chip.base - d->ctrl_base) + bit;
+
 			generic_handle_irq(
-				irq_find_mapping(d->irq_domain,
-						 d->chip.base + bit));
+				irq_find_mapping(d->irq_domain, hw_irq));
 		}
 	}
 	chained_irq_exit(irq_desc_get_chip(desc), desc);
@@ -353,11 +363,17 @@  static void gpio_irq_handler(struct irq_desc *desc)
 static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset)
 {
 	struct davinci_gpio_controller *d = gpiochip_get_data(chip);
+	irq_hw_number_t hw_irq;
 
-	if (d->irq_domain)
-		return irq_create_mapping(d->irq_domain, d->chip.base + offset);
-	else
+	if (d->irq_domain) {
+		/* Max number of gpios per controller is 144 so
+		 * hw_irq will be in [0..143]
+		 */
+		hw_irq = (d->chip.base - d->ctrl_base) + offset;
+		return irq_create_mapping(d->irq_domain, hw_irq);
+	} else {
 		return -ENXIO;
+	}
 }
 
 static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
diff --git a/include/linux/platform_data/gpio-davinci.h b/include/linux/platform_data/gpio-davinci.h
index 6ace3fd..0a0cdd7 100644
--- a/include/linux/platform_data/gpio-davinci.h
+++ b/include/linux/platform_data/gpio-davinci.h
@@ -38,6 +38,7 @@  struct davinci_gpio_controller {
 	void __iomem		*in_data;
 	int			gpio_unbanked;
 	unsigned		gpio_irq;
+	unsigned int		ctrl_base;
 };
 
 /*