From 4fd4604c8bf2401cfb62c311dadf834606dfa32d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 21 Sep 2018 12:25:43 +0200 Subject: [PATCH] ANDROID: GKI: gpio: Add support for hierarchical IRQ domains Hierarchical IRQ domains can be used to stack different IRQ controllers on top of each other. One specific use-case where this can be useful is if a power management controller has top-level controls for wakeup interrupts. In such cases, the power management controller can be a parent to other interrupt controllers and program additional registers when an IRQ has its wake capability enabled or disabled. Bug: 150638297 Change-Id: I3f63cb13c0cd1b602d3205c40648d5e7d3c62d4d Patch-mainline: https://lore.kernel.org/patchwork/patch/989528/ Signed-off-by: Thierry Reding Signed-off-by: Lina Iyer Signed-off-by: Will McVicker (cherry picked commit from 789fe8a323e13bf5b15cf667bb7876554506c739) --- drivers/gpio/gpiolib.c | 15 +++++++++++---- include/linux/gpio/driver.h | 6 ++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 12472b84a71c..b453193154ae 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1909,7 +1909,9 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, type = IRQ_TYPE_NONE; } - gpiochip->to_irq = gpiochip_to_irq; + if (!gpiochip->to_irq) + gpiochip->to_irq = gpiochip_to_irq; + gpiochip->irq.default_type = type; gpiochip->irq.lock_key = lock_key; gpiochip->irq.request_key = request_key; @@ -1919,9 +1921,14 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, else ops = &gpiochip_domain_ops; - gpiochip->irq.domain = irq_domain_add_simple(np, gpiochip->ngpio, - gpiochip->irq.first, - ops, gpiochip); + if (gpiochip->irq.parent_domain) + gpiochip->irq.domain = irq_domain_add_hierarchy(gpiochip->irq.parent_domain, + 0, gpiochip->ngpio, + np, ops, gpiochip); + else + gpiochip->irq.domain = irq_domain_add_simple(np, gpiochip->ngpio, + gpiochip->irq.first, + ops, gpiochip); if (!gpiochip->irq.domain) return -EINVAL; diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index a4d5eb37744a..01106d1f7200 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -47,6 +47,12 @@ struct gpio_irq_chip { */ const struct irq_domain_ops *domain_ops; + /** + * @parent_domain: + * + */ + struct irq_domain *parent_domain; + /** * @handler: *