Skip to content

Commit 4a169a9

Browse files
mkshahcMarc Zyngier
authored andcommitted
genirq: Introduce irq_chip_get/set_parent_state calls
On certain QTI chipsets some GPIOs are direct-connect interrupts to the GIC to be used as regular interrupt lines. When the GPIOs are not used for interrupt generation the interrupt line is disabled. But disabling the interrupt at GIC does not prevent the interrupt to be reported as pending at GIC_ISPEND. Later, when drivers call enable_irq() on the interrupt, an unwanted interrupt occurs. Introduce get and set methods for irqchip's parent to clear it's pending irq state. This then can be invoked by the GPIO interrupt controller on the parents in it hierarchy to clear the interrupt before enabling the interrupt. Signed-off-by: Maulik Shah <[email protected]> Signed-off-by: Lina Iyer <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Reviewed-by: Stephen Boyd <[email protected]> Link: https://lore.kernel.org/r/[email protected] [updated commit text and minor code fixes]
1 parent d46bca2 commit 4a169a9

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

include/linux/irq.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,12 @@ extern int irq_chip_pm_put(struct irq_data *data);
610610
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
611611
extern void handle_fasteoi_ack_irq(struct irq_desc *desc);
612612
extern void handle_fasteoi_mask_irq(struct irq_desc *desc);
613+
extern int irq_chip_set_parent_state(struct irq_data *data,
614+
enum irqchip_irq_state which,
615+
bool val);
616+
extern int irq_chip_get_parent_state(struct irq_data *data,
617+
enum irqchip_irq_state which,
618+
bool *state);
613619
extern void irq_chip_enable_parent(struct irq_data *data);
614620
extern void irq_chip_disable_parent(struct irq_data *data);
615621
extern void irq_chip_ack_parent(struct irq_data *data);

kernel/irq/chip.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,6 +1297,50 @@ EXPORT_SYMBOL_GPL(handle_fasteoi_mask_irq);
12971297

12981298
#endif /* CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS */
12991299

1300+
/**
1301+
* irq_chip_set_parent_state - set the state of a parent interrupt.
1302+
*
1303+
* @data: Pointer to interrupt specific data
1304+
* @which: State to be restored (one of IRQCHIP_STATE_*)
1305+
* @val: Value corresponding to @which
1306+
*
1307+
* Conditional success, if the underlying irqchip does not implement it.
1308+
*/
1309+
int irq_chip_set_parent_state(struct irq_data *data,
1310+
enum irqchip_irq_state which,
1311+
bool val)
1312+
{
1313+
data = data->parent_data;
1314+
1315+
if (!data || !data->chip->irq_set_irqchip_state)
1316+
return 0;
1317+
1318+
return data->chip->irq_set_irqchip_state(data, which, val);
1319+
}
1320+
EXPORT_SYMBOL_GPL(irq_chip_set_parent_state);
1321+
1322+
/**
1323+
* irq_chip_get_parent_state - get the state of a parent interrupt.
1324+
*
1325+
* @data: Pointer to interrupt specific data
1326+
* @which: one of IRQCHIP_STATE_* the caller wants to know
1327+
* @state: a pointer to a boolean where the state is to be stored
1328+
*
1329+
* Conditional success, if the underlying irqchip does not implement it.
1330+
*/
1331+
int irq_chip_get_parent_state(struct irq_data *data,
1332+
enum irqchip_irq_state which,
1333+
bool *state)
1334+
{
1335+
data = data->parent_data;
1336+
1337+
if (!data || !data->chip->irq_get_irqchip_state)
1338+
return 0;
1339+
1340+
return data->chip->irq_get_irqchip_state(data, which, state);
1341+
}
1342+
EXPORT_SYMBOL_GPL(irq_chip_get_parent_state);
1343+
13001344
/**
13011345
* irq_chip_enable_parent - Enable the parent interrupt (defaults to unmask if
13021346
* NULL)

0 commit comments

Comments
 (0)