diff options
author | Michael Ryleev <gmar@google.com> | 2019-11-08 14:29:36 -0800 |
---|---|---|
committer | Michael Ryleev <gmar@google.com> | 2019-12-04 00:32:40 +0000 |
commit | 8f0686c4fc48c77edce19fbde74fd7c576a05f64 (patch) | |
tree | 9882997ff3159b475ebfad4a379cc0da80e1aaa2 /dev/interrupt | |
parent | a0cad1bd0d4d5b8c0c85d1f0165f49ef52104b5b (diff) | |
download | common-8f0686c4fc48c77edce19fbde74fd7c576a05f64.tar.gz |
[dev][interrupt] Add suspend/resume hooks for GICv3
Bug: 138743238
Change-Id: I103142fabfc6e050689ef0cc8c56d77f1e0cf063
Diffstat (limited to 'dev/interrupt')
-rw-r--r-- | dev/interrupt/arm_gic/arm_gic.c | 18 | ||||
-rw-r--r-- | dev/interrupt/arm_gic/gic_v3.c | 29 | ||||
-rw-r--r-- | dev/interrupt/arm_gic/gic_v3.h | 2 |
3 files changed, 49 insertions, 0 deletions
diff --git a/dev/interrupt/arm_gic/arm_gic.c b/dev/interrupt/arm_gic/arm_gic.c index c55a46b5..0022724c 100644 --- a/dev/interrupt/arm_gic/arm_gic.c +++ b/dev/interrupt/arm_gic/arm_gic.c @@ -205,6 +205,9 @@ LK_INIT_HOOK_FLAGS(arm_gic_init_percpu, static void arm_gic_suspend_cpu(uint level) { +#if GIC_VERSION > 2 + arm_gicv3_suspend_cpu(arch_curr_cpu_num()); +#endif suspend_resume_fiq(false, false); } @@ -229,6 +232,21 @@ static void arm_gic_resume_cpu(uint level) } else { arm_gic_init_percpu(0); } + +#if GIC_VERSION > 2 + { + uint cpu = arch_curr_cpu_num(); + uint max_irq = resume_gicd ? MAX_INT : GIC_MAX_PER_CPU_INT; + + for (uint v = 0; v < max_irq; v++) { + struct int_handler_struct *h = get_int_handler(v, cpu); + if (h->handler) { + arm_gicv3_configure_irq_locked(cpu, v); + } + } + arm_gicv3_resume_cpu_locked(cpu, resume_gicd); + } +#endif spin_unlock_restore(&gicd_lock, state, GICD_LOCK_FLAGS); suspend_resume_fiq(false, resume_gicd); } diff --git a/dev/interrupt/arm_gic/gic_v3.c b/dev/interrupt/arm_gic/gic_v3.c index 2dc045ae..ddf28423 100644 --- a/dev/interrupt/arm_gic/gic_v3.c +++ b/dev/interrupt/arm_gic/gic_v3.c @@ -249,3 +249,32 @@ void arm_gicv3_configure_irq_locked(unsigned int cpu, unsigned int vector) { } } +static uint32_t enabled_spi_mask[DIV_ROUND_UP(MAX_INT, 32)]; +static uint32_t enabled_ppi_mask[SMP_MAX_CPUS]; + +void arm_gicv3_suspend_cpu(unsigned int cpu) { + uint32_t i; + ASSERT(cpu < SMP_MAX_CPUS); + + if (cpu == 0) { + /* also save gicd */ + for (i = 32; i < MAX_INT; i += 32) { + enabled_spi_mask[i / 32] = GICDREG_READ(0, GICD_ISENABLER(i / 32)); + } + } + enabled_ppi_mask[cpu] = GICRREG_READ(0, cpu, GICR_ISENABLER0); +} + +void arm_gicv3_resume_cpu_locked(unsigned int cpu, bool gicd) { + uint32_t i; + ASSERT(cpu < SMP_MAX_CPUS); + + GICRREG_WRITE(0, cpu, GICR_ISENABLER0, enabled_ppi_mask[cpu]); + + if (gicd) { + /* also resume gicd */ + for (i = 32; i < MAX_INT; i += 32) { + GICDREG_WRITE(0, GICD_ISENABLER(i / 32), enabled_spi_mask[i / 32]); + } + } +} diff --git a/dev/interrupt/arm_gic/gic_v3.h b/dev/interrupt/arm_gic/gic_v3.h index 3bfb40b2..1f3c6358 100644 --- a/dev/interrupt/arm_gic/gic_v3.h +++ b/dev/interrupt/arm_gic/gic_v3.h @@ -26,3 +26,5 @@ void arm_gicv3_init(void); void arm_gicv3_init_percpu(void); void arm_gicv3_configure_irq_locked(unsigned int cpu, unsigned int vector); +void arm_gicv3_suspend_cpu(unsigned int cpu); +void arm_gicv3_resume_cpu_locked(unsigned int cpu, bool gicd); |