UPSTREAM: gpio: support threaded interrupts in irqchip helpers
Some off-chip GPIO expanders need to be communicated by I2C or
SPI traffic, but may still support IRQs. By the sleeping nature
of such buses, such IRQ handlers need to be threaded. Support
such handlers in the gpiochip irqchip helpers by flagging IRQs
as threaded if the .can_sleep property of the gpiochip is
true.
Helpfully deny registration of chained IRQ handlers if the
.can_sleep property is set, as such chips will invariably need
a nested handler rather than a chained handler.
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
(cherry picked from commit 1c8732bb03)
Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
BUG=chrome-os-partner:30840
TEST=builds
Change-Id: I7d4e53c668470c9282054ddcfa825e43181246fb
Reviewed-on: https://chromium-review.googlesource.com/238904
Reviewed-by: Olof Johansson <olofj@chromium.org>
Tested-by: Andrew Bresticker <abrestic@chromium.org>
Commit-Queue: Andrew Bresticker <abrestic@chromium.org>
This commit is contained in:
committed by
ChromeOS Commit Bot
parent
f85fe74cff
commit
ad3aa9930c
@@ -1363,6 +1363,11 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
|
||||
int parent_irq,
|
||||
irq_flow_handler_t parent_handler)
|
||||
{
|
||||
if (gpiochip->can_sleep) {
|
||||
chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n");
|
||||
return;
|
||||
}
|
||||
|
||||
irq_set_chained_handler(parent_irq, parent_handler);
|
||||
/*
|
||||
* The parent irqchip is already using the chip_data for this
|
||||
@@ -1389,6 +1394,9 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
|
||||
|
||||
irq_set_chip_data(irq, chip);
|
||||
irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
|
||||
/* Chips that can sleep need nested thread handlers */
|
||||
if (chip->can_sleep)
|
||||
irq_set_nested_thread(irq, 1);
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(irq, IRQF_VALID);
|
||||
#else
|
||||
@@ -1401,9 +1409,13 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
|
||||
|
||||
static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
|
||||
{
|
||||
struct gpio_chip *chip = d->host_data;
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(irq, 0);
|
||||
#endif
|
||||
if (chip->can_sleep)
|
||||
irq_set_nested_thread(irq, 0);
|
||||
irq_set_chip_and_handler(irq, NULL, NULL);
|
||||
irq_set_chip_data(irq, NULL);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,10 @@ struct seq_file;
|
||||
* format specifier for an unsigned int. It is substituted by the actual
|
||||
* number of the gpio.
|
||||
* @can_sleep: flag must be set iff get()/set() methods sleep, as they
|
||||
* must while accessing GPIO expander chips over I2C or SPI
|
||||
* must while accessing GPIO expander chips over I2C or SPI. This
|
||||
* implies that if the chip supports IRQs, these IRQs need to be threaded
|
||||
* as the chip access may sleep when e.g. reading out the IRQ status
|
||||
* registers.
|
||||
* @exported: flags if the gpiochip is exported for use from sysfs. Private.
|
||||
*
|
||||
* A gpio_chip can help platforms abstract various sources of GPIOs so
|
||||
|
||||
Reference in New Issue
Block a user