aboutsummaryrefslogtreecommitdiff
path: root/dev/interrupt
diff options
context:
space:
mode:
authorMichael Ryleev <gmar@google.com>2019-11-08 14:29:36 -0800
committerMichael Ryleev <gmar@google.com>2019-12-04 00:32:40 +0000
commit8f0686c4fc48c77edce19fbde74fd7c576a05f64 (patch)
tree9882997ff3159b475ebfad4a379cc0da80e1aaa2 /dev/interrupt
parenta0cad1bd0d4d5b8c0c85d1f0165f49ef52104b5b (diff)
downloadcommon-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.c18
-rw-r--r--dev/interrupt/arm_gic/gic_v3.c29
-rw-r--r--dev/interrupt/arm_gic/gic_v3.h2
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);