/* * gic-v3.c * * Copyright (C) 2015 ARM Limited. All rights reserved. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE.txt file. */ #include #include #include #include #define GICD_CTLR 0x0 #define GICD_TYPER 0x4 #define GICD_IGROUP0 0x80 #define GICD_IGRPMOD0 0xd00 #define GICD_CTLR_EnableGrp0 (1 << 0) #define GICD_CTLR_EnableGrp1ns (1 << 1) #define GICD_CTLR_EnableGrp1s (1 << 2) #define GICD_CTLR_ARE_S (1 << 4) #define GICD_CTLR_ARE_NS (1 << 5) #define GICD_TYPER_ITLineNumber 0x1f #define GICR_WAKER 0x14 #define GICR_TYPER 0x8 #define GICR_IGROUP0 0x80 #define GICR_IGRPMOD0 0xD00 #define GICR_WAKER_ProcessorSleep (1 << 1) #define GICR_WAKER_ChildrenAsleep (1 << 2) #define GICR_TYPER_VLPIS (1 << 1) #define GICR_TYPER_Last (1 << 4) #define ICC_SRE_SRE (1 << 0) #define ICC_SRE_Enable (1 << 3) void gic_secure_init_primary(void) { unsigned int i; void *gicr_ptr = (void *)GIC_RDIST_BASE; void *gicd_base = (void *)GIC_DIST_BASE; uint32_t typer; raw_writel(GICD_CTLR_EnableGrp0 | GICD_CTLR_EnableGrp1ns | GICD_CTLR_EnableGrp1s | GICD_CTLR_ARE_S | GICD_CTLR_ARE_NS, gicd_base + GICD_CTLR); do { /* * Wake up redistributor: kick ProcessorSleep and wait for * ChildrenAsleep to be 0. */ uint32_t waker = raw_readl(gicr_ptr + GICR_WAKER); waker &= ~GICR_WAKER_ProcessorSleep; raw_writel(waker, gicr_ptr + GICR_WAKER); dsb(st); isb(); do { waker = raw_readl(gicr_ptr + GICR_WAKER); } while (waker & GICR_WAKER_ChildrenAsleep); /* * GICR_TYPER is 64-bit, but we do not need the upper half that * contains CPU affinity. */ typer = raw_readl(gicr_ptr + GICR_TYPER); gicr_ptr += 0x10000; /* Go to SGI_Base */ raw_writel(~0x0, gicr_ptr + GICR_IGROUP0); raw_writel(0x0, gicr_ptr + GICR_IGRPMOD0); /* Next redist */ gicr_ptr += 0x10000; if (typer & GICR_TYPER_VLPIS) gicr_ptr += 0x20000; } while (!(typer & GICR_TYPER_Last)); typer = raw_readl(gicd_base + GICD_TYPER); for (i = 1; i < (typer & GICD_TYPER_ITLineNumber); i++) { raw_writel(~0x0, gicd_base + GICD_IGROUP0 + i * 4); raw_writel(0x0, gicd_base + GICD_IGRPMOD0 + i * 4); } } void gic_secure_init(void) { uint32_t cpu = read_mpidr(); uint32_t sre; /* * If GICv3 is not available, skip initialisation. The OS will probably * fail with a warning, but this should be easier to debug than a * failure within the boot wrapper. */ if (!has_gicv3_sysreg()) return; if (cpu == 0) gic_secure_init_primary(); sre = gic_read_icc_sre(); sre |= ICC_SRE_Enable | ICC_SRE_SRE; gic_write_icc_sre(sre); isb(); gic_write_icc_ctlr(0); isb(); }