@@ -476,6 +476,8 @@ struct irq_chip {
* IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip
* IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask
* IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode
+ * IRQCHIP_GENERIC_SUSPEND: Use the suspend/resume callbacks in
+ * device_irq_suspend/resume
*/
enum {
IRQCHIP_SET_TYPE_MASKED = (1 << 0),
@@ -485,6 +487,7 @@ enum {
IRQCHIP_SKIP_SET_WAKE = (1 << 4),
IRQCHIP_ONESHOT_SAFE = (1 << 5),
IRQCHIP_EOI_THREADED = (1 << 6),
+ IRQCHIP_GENERIC_SUSPEND = (1 << 7),
};
#include <linux/irqdesc.h>
@@ -70,6 +70,8 @@ void irq_pm_remove_action(struct irq_des
static bool suspend_device_irq(struct irq_desc *desc)
{
+ struct irq_chip *chip;
+
if (!desc->action || irq_desc_is_chained(desc) ||
desc->no_suspend_depth)
return false;
@@ -94,8 +96,13 @@ static bool suspend_device_irq(struct ir
* chip level. The chip implementation indicates that with
* IRQCHIP_MASK_ON_SUSPEND.
*/
- if (irq_desc_get_chip(desc)->flags & IRQCHIP_MASK_ON_SUSPEND)
+ chip = irq_desc_get_chip(desc);
+ if (chip->flags & IRQCHIP_MASK_ON_SUSPEND)
mask_irq(desc);
+
+ if ((chip->flags & IRQCHIP_GENERIC_SUSPEND) && chip->irq_suspend)
+ chip->irq_suspend(&desc->irq_data);
+
return true;
}
@@ -138,6 +145,8 @@ EXPORT_SYMBOL_GPL(suspend_device_irqs);
static void resume_irq(struct irq_desc *desc)
{
+ struct irq_chip *chip;
+
irqd_clear(&desc->irq_data, IRQD_WAKEUP_ARMED);
if (desc->istate & IRQS_SUSPENDED)
@@ -150,6 +159,10 @@ static void resume_irq(struct irq_desc *
/* Pretend that it got disabled ! */
desc->depth++;
resume:
+ chip = irq_desc_get_chip(desc);
+ if ((chip->flags & IRQCHIP_GENERIC_SUSPEND) && chip->irq_resume)
+ chip->irq_resume(&desc->irq_data);
+
desc->istate &= ~IRQS_SUSPENDED;
__enable_irq(desc);
}