diff options
Diffstat (limited to 'drivers/irqchip/irq-gic-v3.c')
-rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 32533650494c..3923b2a2150c 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -110,8 +110,33 @@ static void gic_redist_wait_for_rwp(void) static u64 __maybe_unused gic_read_iar(void) { u64 irqstat; + u64 __maybe_unused daif; + u64 __maybe_unused pmr; + u64 __maybe_unused default_pmr_value = DEFAULT_PMR_VALUE; +#ifndef CONFIG_USE_ICC_SYSREGS_FOR_IRQFLAGS asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat)); +#else + /* + * The PMR may be configured to mask interrupts when this code is + * called, thus in order to acknowledge interrupts we must set the + * PMR to its default value before reading from the IAR. + * + * To do this without taking an interrupt we also ensure the I bit + * is set whilst we are interfering with the value of the PMR. + */ + asm volatile( + "mrs %1, daif\n" /* save I bit */ + "msr daifset, #2\n" /* set I bit */ + "mrs_s %2, " __stringify(ICC_PMR_EL1) "\n" /* save PMR */ + "msr_s " __stringify(ICC_PMR_EL1) ",%3\n" /* set PMR */ + "mrs_s %0, " __stringify(ICC_IAR1_EL1) "\n" /* ack int */ + "msr_s " __stringify(ICC_PMR_EL1) ",%2\n" /* restore PMR */ + "isb\n" + "msr daif, %1" /* restore I */ + : "=r" (irqstat), "=&r" (daif), "=&r" (pmr) + : "r" (default_pmr_value)); +#endif return irqstat; } @@ -142,7 +167,7 @@ static void __maybe_unused gic_write_sgi1r(u64 val) asm volatile("msr_s " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val)); } -static void gic_enable_sre(void) +static void __maybe_unused gic_enable_sre(void) { u64 val; @@ -382,11 +407,13 @@ static int gic_populate_rdist(void) static void gic_cpu_sys_reg_init(void) { +#ifndef CONFIG_USE_ICC_SYSREGS_FOR_IRQFLAGS /* Enable system registers */ gic_enable_sre(); /* Set priority mask register */ gic_write_pmr(DEFAULT_PMR_VALUE); +#endif /* * On FVP, CPU 0 arrives in the kernel with its BPR changed from the |