diff options
-rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index bbe434e00984..d6bd0c54c005 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -54,6 +54,10 @@ struct gic_chip_data { unsigned int wakeup_irqs[32]; unsigned int enabled_irqs[32]; #endif +#ifdef CONFIG_ARM_GIC_PANIC_HANDLER + u32 saved_dist_regs[0x400]; + u32 saved_router_regs[0x800]; +#endif }; static struct gic_chip_data gic_data __read_mostly; @@ -359,6 +363,29 @@ static inline void __iomem *gic_data_dist_base(struct gic_chip_data *data) return data->dist_base; } +#ifdef CONFIG_ARM_GIC_PANIC_HANDLER +static int gic_panic_handler(struct notifier_block *this, + unsigned long event, void *ptr) +{ + int i; + void __iomem *base; + + base = gic_data.dist_base; + for (i = 0; i < 0x400; i += 1) + gic_data.saved_dist_regs[i] = readl_relaxed(base + 4 * i); + + base = gic_data.dist_base + GICD_IROUTER; + for (i = 0; i < 0x800; i += 1) + gic_data.saved_router_regs[i] = readl_relaxed(base + 4 * i); + + return NOTIFY_DONE; +} + +static struct notifier_block gic_panic_blk = { + .notifier_call = gic_panic_handler, +}; +#endif + #ifdef CONFIG_PM static int gic_suspend_one(struct gic_chip_data *gic) { @@ -1047,6 +1074,10 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare gic_cpu_init(); gic_cpu_pm_init(); +#ifdef CONFIG_ARM_GIC_PANIC_HANDLER + atomic_notifier_chain_register(&panic_notifier_list, &gic_panic_blk); +#endif + return 0; out_free: |