summaryrefslogtreecommitdiff
path: root/include/linux/gpio
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2016-11-24 10:57:25 +0100
committerLinus Walleij <linus.walleij@linaro.org>2016-11-25 15:12:27 +0100
commitd245b3f9bd36f02fd641cba9931d8b4c77126e74 (patch)
treefa9984376f28c4f6b8883aff8a704178aa68412f /include/linux/gpio
parent07d9a380680d1c0eb51ef87ff2eab5c994949e69 (diff)
downloadlwn-d245b3f9bd36f02fd641cba9931d8b4c77126e74.tar.gz
lwn-d245b3f9bd36f02fd641cba9931d8b4c77126e74.zip
gpio: simplify adding threaded interrupts
This tries to simplify the use of CONFIG_GPIOLIB_IRQCHIP when using threaded interrupts: add a new call gpiochip_irqchip_add_nested() to indicate that we're dealing with a nested rather than a chained irqchip, then create a separate gpiochip_set_nested_irqchip() to mirror the gpiochip_set_chained_irqchip() call to connect the parent and child interrupts. In the nested case gpiochip_set_nested_irqchip() does nothing more than call irq_set_parent() on each valid child interrupt, which has little semantic effect in the kernel, but this is probably still formally correct. Update all drivers using nested interrupts to use gpiochip_irqchip_add_nested() so we can now see clearly which these users are. The DLN2 driver can drop its specific hack with .irq_not_threaded as we now recognize whether a chip is threaded or not from its use of gpiochip_irqchip_add_nested() signature rather than from inspecting .can_sleep. We rename the .irq_parent to .irq_chained_parent since this parent IRQ is only really kept around for the chained interrupt handlers. Cc: Lars Poeschel <poeschel@lemonage.de> Cc: Octavian Purdila <octavian.purdila@intel.com> Cc: Daniel Baluta <daniel.baluta@intel.com> Cc: Bin Gao <bin.gao@linux.intel.com> Cc: Mika Westerberg <mika.westerberg@linux.intel.com> Cc: Ajay Thomas <ajay.thomas.david.rajamanickam@intel.com> Cc: Semen Protsenko <semen.protsenko@globallogic.com> Cc: Alexander Stein <alexander.stein@systec-electronic.com> Cc: Phil Reid <preid@electromag.com.au> Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com> Cc: Patrice Chotard <patrice.chotard@st.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'include/linux/gpio')
-rw-r--r--include/linux/gpio/driver.h32
1 files changed, 24 insertions, 8 deletions
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 24e2cc56beb1..4b20238e7570 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -82,8 +82,6 @@ enum single_ended_mode {
* 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.
- * @irq_not_threaded: flag must be set if @can_sleep is set but the
- * IRQs don't need to be threaded
* @read_reg: reader function for generic GPIO
* @write_reg: writer function for generic GPIO
* @pin2mask: some generic GPIO controllers work with the big-endian bits
@@ -109,8 +107,10 @@ enum single_ended_mode {
* for GPIO IRQs, provided by GPIO driver
* @irq_default_type: default IRQ triggering type applied during GPIO driver
* initialization, provided by GPIO driver
- * @irq_parent: GPIO IRQ chip parent/bank linux irq number,
- * 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).
+ * @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
@@ -166,7 +166,6 @@ struct gpio_chip {
u16 ngpio;
const char *const *names;
bool can_sleep;
- bool irq_not_threaded;
#if IS_ENABLED(CONFIG_GPIO_GENERIC)
unsigned long (*read_reg)(void __iomem *reg);
@@ -192,7 +191,8 @@ struct gpio_chip {
unsigned int irq_base;
irq_flow_handler_t irq_handler;
unsigned int irq_default_type;
- int irq_parent;
+ int irq_chained_parent;
+ bool irq_nested;
bool irq_need_valid_mask;
unsigned long *irq_valid_mask;
struct lock_class_key *lock_key;
@@ -270,24 +270,40 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
int parent_irq,
irq_flow_handler_t parent_handler);
+void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
+ struct irq_chip *irqchip,
+ int parent_irq);
+
int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
struct irq_chip *irqchip,
unsigned int first_irq,
irq_flow_handler_t handler,
unsigned int type,
+ bool nested,
struct lock_class_key *lock_key);
+/* FIXME: I assume threaded IRQchips do not have the lockdep problem */
+static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip,
+ struct irq_chip *irqchip,
+ unsigned int first_irq,
+ irq_flow_handler_t handler,
+ unsigned int type)
+{
+ return _gpiochip_irqchip_add(gpiochip, irqchip, first_irq,
+ handler, type, true, NULL);
+}
+
#ifdef CONFIG_LOCKDEP
#define gpiochip_irqchip_add(...) \
( \
({ \
static struct lock_class_key _key; \
- _gpiochip_irqchip_add(__VA_ARGS__, &_key); \
+ _gpiochip_irqchip_add(__VA_ARGS__, false, &_key); \
}) \
)
#else
#define gpiochip_irqchip_add(...) \
- _gpiochip_irqchip_add(__VA_ARGS__, NULL)
+ _gpiochip_irqchip_add(__VA_ARGS__, false, NULL)
#endif
#endif /* CONFIG_GPIOLIB_IRQCHIP */