From 657d3fdc709962b88d0d20e0216603be26b316b2 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Fri, 14 Jun 2019 16:14:09 +0530 Subject: [PATCH] ANDROID: GKI: genirq: Introduce irq_chip_get/set_parent_state calls On certain QTI chipsets some GPIOs are direct-connect interrupts to the GIC. Even when GPIOs are not used for interrupt generation and interrupt line is disabled, it does not prevent interrupt to get pending at GIC_ISPEND. When drivers call enable_irq unwanted interrupt occures. Introduce irq_chip_get/set_parent_state calls to clear pending irq which can get called within irq_enable of child irq chip to clear any pending irq before enabling. Signed-off-by: Maulik Shah Bug: 150233439 Change-Id: Ie8559657bd8da926cc741514809ffe9adbd73a80 Signed-off-by: Will McVicker (cherry picked from commit d9233146224bdeec6a8a4cc684bec303e38fb9af) --- include/linux/irq.h | 6 ++++++ kernel/irq/chip.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/linux/irq.h b/include/linux/irq.h index 6ecaf056ab63..2e9da0eda9d1 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -617,6 +617,12 @@ extern int irq_chip_pm_put(struct irq_data *data); #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY extern void handle_fasteoi_ack_irq(struct irq_desc *desc); extern void handle_fasteoi_mask_irq(struct irq_desc *desc); +extern int irq_chip_set_parent_state(struct irq_data *data, + enum irqchip_irq_state which, + bool val); +extern int irq_chip_get_parent_state(struct irq_data *data, + enum irqchip_irq_state which, + bool *state); extern void irq_chip_enable_parent(struct irq_data *data); extern void irq_chip_disable_parent(struct irq_data *data); extern void irq_chip_ack_parent(struct irq_data *data); diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 09d914e486a2..068fc01885bb 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -1239,6 +1239,50 @@ EXPORT_SYMBOL_GPL(handle_fasteoi_mask_irq); #endif /* CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS */ +/** + * irq_chip_set_parent_state - set the state of a parent interrupt. + * @data: Pointer to interrupt specific data + * @which: State to be restored (one of IRQCHIP_STATE_*) + * @val: Value corresponding to @which + * + */ +int irq_chip_set_parent_state(struct irq_data *data, + enum irqchip_irq_state which, + bool val) +{ + data = data->parent_data; + if (!data) + return 0; + + if (data->chip->irq_set_irqchip_state) + return data->chip->irq_set_irqchip_state(data, which, val); + + return 0; +} +EXPORT_SYMBOL(irq_chip_set_parent_state); + +/** + * irq_chip_get_parent_state - get the state of a parent interrupt. + * @data: Pointer to interrupt specific data + * @which: one of IRQCHIP_STATE_* the caller wants to know + * @state: a pointer to a boolean where the state is to be stored + * + */ +int irq_chip_get_parent_state(struct irq_data *data, + enum irqchip_irq_state which, + bool *state) +{ + data = data->parent_data; + if (!data) + return 0; + + if (data->chip->irq_get_irqchip_state) + return data->chip->irq_get_irqchip_state(data, which, state); + + return 0; +} +EXPORT_SYMBOL(irq_chip_get_parent_state); + /** * irq_chip_enable_parent - Enable the parent interrupt (defaults to unmask if * NULL)