blob: 476f703231e04b6395afc7c7376655d1d30d29ba [file] [log] [blame]
/*
* 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 <stdint.h>
#include <cpu.h>
#include <asm/gic-v3.h>
#include <asm/io.h>
#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();
}