|
@@ -1440,7 +1440,7 @@ static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * gpiochip_set_chained_irqchip() - sets a chained irqchip to a gpiochip
|
|
|
+ * gpiochip_set_cascaded_irqchip() - connects a cascaded irqchip to a gpiochip
|
|
|
* @gpiochip: the gpiochip to set the irqchip chain to
|
|
|
* @irqchip: the irqchip to chain to the gpiochip
|
|
|
* @parent_irq: the irq number corresponding to the parent IRQ for this
|
|
@@ -1449,10 +1449,10 @@ static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
|
|
|
* coming out of the gpiochip. If the interrupt is nested rather than
|
|
|
* cascaded, pass NULL in this handler argument
|
|
|
*/
|
|
|
-void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
|
|
|
- struct irq_chip *irqchip,
|
|
|
- int parent_irq,
|
|
|
- irq_flow_handler_t parent_handler)
|
|
|
+static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip,
|
|
|
+ struct irq_chip *irqchip,
|
|
|
+ int parent_irq,
|
|
|
+ irq_flow_handler_t parent_handler)
|
|
|
{
|
|
|
unsigned int offset;
|
|
|
|
|
@@ -1476,7 +1476,7 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
|
|
|
irq_set_chained_handler_and_data(parent_irq, parent_handler,
|
|
|
gpiochip);
|
|
|
|
|
|
- gpiochip->irq_parent = parent_irq;
|
|
|
+ gpiochip->irq_chained_parent = parent_irq;
|
|
|
}
|
|
|
|
|
|
/* Set the parent IRQ for all affected IRQs */
|
|
@@ -1487,8 +1487,47 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
|
|
|
parent_irq);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+/**
|
|
|
+ * gpiochip_set_chained_irqchip() - connects a chained irqchip to a gpiochip
|
|
|
+ * @gpiochip: the gpiochip to set the irqchip chain to
|
|
|
+ * @irqchip: the irqchip to chain to the gpiochip
|
|
|
+ * @parent_irq: the irq number corresponding to the parent IRQ for this
|
|
|
+ * chained irqchip
|
|
|
+ * @parent_handler: the parent interrupt handler for the accumulated IRQ
|
|
|
+ * coming out of the gpiochip. If the interrupt is nested rather than
|
|
|
+ * cascaded, pass NULL in this handler argument
|
|
|
+ */
|
|
|
+void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
|
|
|
+ struct irq_chip *irqchip,
|
|
|
+ int parent_irq,
|
|
|
+ irq_flow_handler_t parent_handler)
|
|
|
+{
|
|
|
+ gpiochip_set_cascaded_irqchip(gpiochip, irqchip, parent_irq,
|
|
|
+ parent_handler);
|
|
|
+}
|
|
|
EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
|
|
|
|
|
|
+/**
|
|
|
+ * gpiochip_set_nested_irqchip() - connects a nested irqchip to a gpiochip
|
|
|
+ * @gpiochip: the gpiochip to set the irqchip nested handler to
|
|
|
+ * @irqchip: the irqchip to nest to the gpiochip
|
|
|
+ * @parent_irq: the irq number corresponding to the parent IRQ for this
|
|
|
+ * nested irqchip
|
|
|
+ */
|
|
|
+void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
|
|
|
+ struct irq_chip *irqchip,
|
|
|
+ int parent_irq)
|
|
|
+{
|
|
|
+ if (!gpiochip->irq_nested) {
|
|
|
+ chip_err(gpiochip, "tried to nest a chained gpiochip\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ gpiochip_set_cascaded_irqchip(gpiochip, irqchip, parent_irq,
|
|
|
+ NULL);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(gpiochip_set_nested_irqchip);
|
|
|
+
|
|
|
/**
|
|
|
* gpiochip_irq_map() - maps an IRQ into a GPIO irqchip
|
|
|
* @d: the irqdomain used by this irqchip
|
|
@@ -1511,8 +1550,8 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
|
|
|
*/
|
|
|
irq_set_lockdep_class(irq, chip->lock_key);
|
|
|
irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
|
|
|
- /* Chips that can sleep need nested thread handlers */
|
|
|
- if (chip->can_sleep && !chip->irq_not_threaded)
|
|
|
+ /* Chips that use nested thread handlers have them marked */
|
|
|
+ if (chip->irq_nested)
|
|
|
irq_set_nested_thread(irq, 1);
|
|
|
irq_set_noprobe(irq);
|
|
|
|
|
@@ -1530,7 +1569,7 @@ static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
|
|
|
{
|
|
|
struct gpio_chip *chip = d->host_data;
|
|
|
|
|
|
- if (chip->can_sleep)
|
|
|
+ if (chip->irq_nested)
|
|
|
irq_set_nested_thread(irq, 0);
|
|
|
irq_set_chip_and_handler(irq, NULL, NULL);
|
|
|
irq_set_chip_data(irq, NULL);
|
|
@@ -1585,9 +1624,9 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
|
|
|
|
|
|
acpi_gpiochip_free_interrupts(gpiochip);
|
|
|
|
|
|
- if (gpiochip->irq_parent) {
|
|
|
- irq_set_chained_handler(gpiochip->irq_parent, NULL);
|
|
|
- irq_set_handler_data(gpiochip->irq_parent, NULL);
|
|
|
+ if (gpiochip->irq_chained_parent) {
|
|
|
+ irq_set_chained_handler(gpiochip->irq_chained_parent, NULL);
|
|
|
+ irq_set_handler_data(gpiochip->irq_chained_parent, NULL);
|
|
|
}
|
|
|
|
|
|
/* Remove all IRQ mappings and delete the domain */
|
|
@@ -1611,7 +1650,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * gpiochip_irqchip_add() - adds an irqchip to a gpiochip
|
|
|
+ * _gpiochip_irqchip_add() - adds an irqchip to a gpiochip
|
|
|
* @gpiochip: the gpiochip to add the irqchip to
|
|
|
* @irqchip: the irqchip to add to the gpiochip
|
|
|
* @first_irq: if not dynamically assigned, the base (first) IRQ to
|
|
@@ -1619,6 +1658,8 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
|
|
|
* @handler: the irq handler to use (often a predefined irq core function)
|
|
|
* @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE
|
|
|
* to have the core avoid setting up any default type in the hardware.
|
|
|
+ * @nested: whether this is a nested irqchip calling handle_nested_irq()
|
|
|
+ * in its IRQ handler
|
|
|
* @lock_key: lockdep class
|
|
|
*
|
|
|
* This function closely associates a certain irqchip with a certain
|
|
@@ -1640,6 +1681,7 @@ int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
|
|
|
unsigned int first_irq,
|
|
|
irq_flow_handler_t handler,
|
|
|
unsigned int type,
|
|
|
+ bool nested,
|
|
|
struct lock_class_key *lock_key)
|
|
|
{
|
|
|
struct device_node *of_node;
|
|
@@ -1654,6 +1696,7 @@ int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
|
|
|
pr_err("missing gpiochip .dev parent pointer\n");
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
+ gpiochip->irq_nested = nested;
|
|
|
of_node = gpiochip->parent->of_node;
|
|
|
#ifdef CONFIG_OF_GPIO
|
|
|
/*
|