diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h index 83b72f4f85e4..623e57239821 100644 --- a/drivers/irqchip/irq-gic-common.h +++ b/drivers/irqchip/irq-gic-common.h @@ -30,6 +30,12 @@ struct gic_quirk { extern bool from_suspend; extern struct irq_chip gic_arch_extn; +#ifdef CONFIG_QCOM_SHOW_RESUME_IRQ +extern int msm_show_resume_irq_mask; +#else +#define msm_show_resume_irq_mask 0 +#endif + int gic_configure_irq(unsigned int irq, unsigned int type, void __iomem *base, void (*sync_access)(void)); void gic_dist_config(void __iomem *base, int gic_irqs, diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 65cb116ac0aa..dae3bddaa7fd 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -40,6 +40,8 @@ #include #include +#include + #include "irq-gic-common.h" struct redist_region { @@ -331,6 +333,69 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu) return 0; } +#ifdef CONFIG_PM + +static int gic_suspend(void) +{ + return 0; +} + +static void gic_show_resume_irq(struct gic_chip_data *gic) +{ + unsigned int i; + u32 enabled; + u32 pending[32]; + void __iomem *base = gic_data.dist_base; + + if (!msm_show_resume_irq_mask) + return; + + for (i = 0; i * 32 < gic->irq_nr; i++) { + enabled = readl_relaxed(base + GICD_ICENABLER + i * 4); + pending[i] = readl_relaxed(base + GICD_ISPENDR + i * 4); + pending[i] &= enabled; + } + + for (i = find_first_bit((unsigned long *)pending, gic->irq_nr); + i < gic->irq_nr; + i = find_next_bit((unsigned long *)pending, gic->irq_nr, i+1)) { + unsigned int irq = irq_find_mapping(gic->domain, i); + struct irq_desc *desc = irq_to_desc(irq); + const char *name = "null"; + + if (desc == NULL) + name = "stray irq"; + else if (desc->action && desc->action->name) + name = desc->action->name; + + pr_warn("%s: %d triggered %s\n", __func__, irq, name); + } +} + +static void gic_resume_one(struct gic_chip_data *gic) +{ + gic_show_resume_irq(gic); +} + +static void gic_resume(void) +{ + gic_resume_one(&gic_data); +} + +static struct syscore_ops gic_syscore_ops = { + .suspend = gic_suspend, + .resume = gic_resume, +}; + +static int __init gic_init_sys(void) +{ + register_syscore_ops(&gic_syscore_ops); + return 0; +} +arch_initcall(gic_init_sys); + +#endif + static u64 gic_mpidr_to_affinity(unsigned long mpidr) { u64 aff;