Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq fixes from Thomas Gleixner: "Three fixes for the ARM GIC interrupt controller from Marc addressing various shortcomings versus boot initialization and suspend/resume" * 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: irqchip/gic: Add save/restore of the active state irqchip/gic: Clear enable bits before restoring them irqchip/gic: Make sure all interrupts are deactivated at boot
This commit is contained in:
commit
4143fc83bb
2 changed files with 45 additions and 6 deletions
|
@ -84,12 +84,15 @@ void __init gic_dist_config(void __iomem *base, int gic_irqs,
|
||||||
writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i);
|
writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable all interrupts. Leave the PPI and SGIs alone
|
* Deactivate and disable all SPIs. Leave the PPI and SGIs
|
||||||
* as they are enabled by redistributor registers.
|
* alone as they are in the redistributor registers on GICv3.
|
||||||
*/
|
*/
|
||||||
for (i = 32; i < gic_irqs; i += 32)
|
for (i = 32; i < gic_irqs; i += 32) {
|
||||||
writel_relaxed(GICD_INT_EN_CLR_X32,
|
writel_relaxed(GICD_INT_EN_CLR_X32,
|
||||||
base + GIC_DIST_ENABLE_CLEAR + i / 8);
|
base + GIC_DIST_ACTIVE_CLEAR + i / 8);
|
||||||
|
writel_relaxed(GICD_INT_EN_CLR_X32,
|
||||||
|
base + GIC_DIST_ENABLE_CLEAR + i / 8);
|
||||||
|
}
|
||||||
|
|
||||||
if (sync_access)
|
if (sync_access)
|
||||||
sync_access();
|
sync_access();
|
||||||
|
@ -102,7 +105,9 @@ void gic_cpu_config(void __iomem *base, void (*sync_access)(void))
|
||||||
/*
|
/*
|
||||||
* Deal with the banked PPI and SGI interrupts - disable all
|
* Deal with the banked PPI and SGI interrupts - disable all
|
||||||
* PPI interrupts, ensure all SGI interrupts are enabled.
|
* PPI interrupts, ensure all SGI interrupts are enabled.
|
||||||
|
* Make sure everything is deactivated.
|
||||||
*/
|
*/
|
||||||
|
writel_relaxed(GICD_INT_EN_CLR_X32, base + GIC_DIST_ACTIVE_CLEAR);
|
||||||
writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR);
|
writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR);
|
||||||
writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);
|
writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);
|
||||||
|
|
||||||
|
|
|
@ -73,9 +73,11 @@ struct gic_chip_data {
|
||||||
union gic_base cpu_base;
|
union gic_base cpu_base;
|
||||||
#ifdef CONFIG_CPU_PM
|
#ifdef CONFIG_CPU_PM
|
||||||
u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
|
u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
|
||||||
|
u32 saved_spi_active[DIV_ROUND_UP(1020, 32)];
|
||||||
u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
|
u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
|
||||||
u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
|
u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
|
||||||
u32 __percpu *saved_ppi_enable;
|
u32 __percpu *saved_ppi_enable;
|
||||||
|
u32 __percpu *saved_ppi_active;
|
||||||
u32 __percpu *saved_ppi_conf;
|
u32 __percpu *saved_ppi_conf;
|
||||||
#endif
|
#endif
|
||||||
struct irq_domain *domain;
|
struct irq_domain *domain;
|
||||||
|
@ -566,6 +568,10 @@ static void gic_dist_save(unsigned int gic_nr)
|
||||||
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
|
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
|
||||||
gic_data[gic_nr].saved_spi_enable[i] =
|
gic_data[gic_nr].saved_spi_enable[i] =
|
||||||
readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
|
readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
|
||||||
|
|
||||||
|
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
|
||||||
|
gic_data[gic_nr].saved_spi_active[i] =
|
||||||
|
readl_relaxed(dist_base + GIC_DIST_ACTIVE_SET + i * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -604,9 +610,19 @@ static void gic_dist_restore(unsigned int gic_nr)
|
||||||
writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
|
writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
|
||||||
dist_base + GIC_DIST_TARGET + i * 4);
|
dist_base + GIC_DIST_TARGET + i * 4);
|
||||||
|
|
||||||
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
|
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) {
|
||||||
|
writel_relaxed(GICD_INT_EN_CLR_X32,
|
||||||
|
dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
|
||||||
writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
|
writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
|
||||||
dist_base + GIC_DIST_ENABLE_SET + i * 4);
|
dist_base + GIC_DIST_ENABLE_SET + i * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) {
|
||||||
|
writel_relaxed(GICD_INT_EN_CLR_X32,
|
||||||
|
dist_base + GIC_DIST_ACTIVE_CLEAR + i * 4);
|
||||||
|
writel_relaxed(gic_data[gic_nr].saved_spi_active[i],
|
||||||
|
dist_base + GIC_DIST_ACTIVE_SET + i * 4);
|
||||||
|
}
|
||||||
|
|
||||||
writel_relaxed(GICD_ENABLE, dist_base + GIC_DIST_CTRL);
|
writel_relaxed(GICD_ENABLE, dist_base + GIC_DIST_CTRL);
|
||||||
}
|
}
|
||||||
|
@ -631,6 +647,10 @@ static void gic_cpu_save(unsigned int gic_nr)
|
||||||
for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
|
for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
|
||||||
ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
|
ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
|
||||||
|
|
||||||
|
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_active);
|
||||||
|
for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
|
||||||
|
ptr[i] = readl_relaxed(dist_base + GIC_DIST_ACTIVE_SET + i * 4);
|
||||||
|
|
||||||
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
|
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
|
||||||
for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
|
for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
|
||||||
ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
|
ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
|
||||||
|
@ -654,8 +674,18 @@ static void gic_cpu_restore(unsigned int gic_nr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
|
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
|
||||||
for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
|
for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
|
||||||
|
writel_relaxed(GICD_INT_EN_CLR_X32,
|
||||||
|
dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
|
||||||
writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
|
writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_active);
|
||||||
|
for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
|
||||||
|
writel_relaxed(GICD_INT_EN_CLR_X32,
|
||||||
|
dist_base + GIC_DIST_ACTIVE_CLEAR + i * 4);
|
||||||
|
writel_relaxed(ptr[i], dist_base + GIC_DIST_ACTIVE_SET + i * 4);
|
||||||
|
}
|
||||||
|
|
||||||
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
|
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
|
||||||
for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
|
for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
|
||||||
|
@ -710,6 +740,10 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
|
||||||
sizeof(u32));
|
sizeof(u32));
|
||||||
BUG_ON(!gic->saved_ppi_enable);
|
BUG_ON(!gic->saved_ppi_enable);
|
||||||
|
|
||||||
|
gic->saved_ppi_active = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
|
||||||
|
sizeof(u32));
|
||||||
|
BUG_ON(!gic->saved_ppi_active);
|
||||||
|
|
||||||
gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
|
gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
|
||||||
sizeof(u32));
|
sizeof(u32));
|
||||||
BUG_ON(!gic->saved_ppi_conf);
|
BUG_ON(!gic->saved_ppi_conf);
|
||||||
|
|
Loading…
Add table
Reference in a new issue