diff --git a/src/arch/arm64/armv8/secmon/Makefile.inc b/src/arch/arm64/armv8/secmon/Makefile.inc index 5284d39f39..ace00b441e 100644 --- a/src/arch/arm64/armv8/secmon/Makefile.inc +++ b/src/arch/arm64/armv8/secmon/Makefile.inc @@ -39,6 +39,7 @@ secmon-y += ../cpu.S secmon-y += ../exception.c secmon-y += ../../cpu.c secmon-y += ../../transition_asm.S ../../transition.c +secmon-y += ../../../../drivers/gic/gic.c ramstage-srcs += $(SECMON_RAMSTAGE) diff --git a/src/arch/arm64/armv8/secmon/psci.c b/src/arch/arm64/armv8/secmon/psci.c index a651b6e152..70251b2b06 100644 --- a/src/arch/arm64/armv8/secmon/psci.c +++ b/src/arch/arm64/armv8/secmon/psci.c @@ -17,6 +17,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA */ +#include #include #include #include @@ -231,6 +232,7 @@ void psci_turn_on_self(const struct cpu_action *action) void psci_cpu_entry(void) { + gic_enable(); /* * Just wait for an action to be performed. Only CPU_ON is supported * initially. i.e. no power down then wake. @@ -327,6 +329,8 @@ static int psci_turn_off_node(struct psci_node *e, int level, if (ret != PSCI_RET_SUCCESS) return ret; + gic_disable(); + /* Should never return. */ ret = soc_psci_ops.cmd_commit(&cmd); diff --git a/src/drivers/gic/gic.c b/src/drivers/gic/gic.c index 8972d04617..71073a580a 100644 --- a/src/drivers/gic/gic.c +++ b/src/drivers/gic/gic.c @@ -59,6 +59,11 @@ static struct gic *gic_get(void) return &gic; } +static inline uint32_t gic_read(uint32_t *base) +{ + return read32(base); +} + static inline void gic_write(uint32_t *base, uint32_t val) { write32(base, val); @@ -118,3 +123,31 @@ void gic_init(void) /* Allow Non-secure access to everything. */ gic_write_regs(&gicd->nsacr[0], gic->num_interrupts / 16, ~0x0); } + +void gic_disable(void) +{ + struct gic *gic; + struct gicc_mmio *gicc; + + gic = gic_get(); + gicc = gic->gicc; + + /* Disable secure, non-secure interrupts. */ + uint32_t val = gic_read(&gicc->ctlr); + val &= ~(ENABLE_GRP0 | ENABLE_GRP1); + gic_write(&gicc->ctlr, val); +} + +void gic_enable(void) +{ + struct gic *gic; + struct gicc_mmio *gicc; + + gic = gic_get(); + gicc = gic->gicc; + + /* Enable secure, non-secure interrupts. */ + uint32_t val = gic_read(&gicc->ctlr); + val |= (ENABLE_GRP0 | ENABLE_GRP1); + gic_write(&gicc->ctlr, val); +} diff --git a/src/include/gic.h b/src/include/gic.h index 22c5631473..2514420563 100644 --- a/src/include/gic.h +++ b/src/include/gic.h @@ -24,6 +24,8 @@ /* Initialize the GIC on the currently processor, including GICD and GICC. */ void gic_init(void); +void gic_disable(void); +void gic_enable(void); /* Return a pointer to the base of the GIC distributor mmio region. */ void *gicd_base(void); @@ -34,6 +36,7 @@ void *gicc_base(void); #else /* CONFIG_GIC */ static inline void gic_init(void) {} +static inline void gic_disable(void) {} #endif /* CONFIG_GIC */