xref: /kvm-unit-tests/lib/arm/gic-v3.c (revision 91a6c3cead72494724d563c19c6aebd2efd14d4e)
1*91a6c3ceSAndrew Jones /*
2*91a6c3ceSAndrew Jones  * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
3*91a6c3ceSAndrew Jones  *
4*91a6c3ceSAndrew Jones  * This work is licensed under the terms of the GNU LGPL, version 2.
5*91a6c3ceSAndrew Jones  */
6*91a6c3ceSAndrew Jones #include <asm/gic.h>
7*91a6c3ceSAndrew Jones #include <asm/io.h>
8*91a6c3ceSAndrew Jones 
9*91a6c3ceSAndrew Jones void gicv3_set_redist_base(size_t stride)
10*91a6c3ceSAndrew Jones {
11*91a6c3ceSAndrew Jones 	u32 aff = mpidr_compress(get_mpidr());
12*91a6c3ceSAndrew Jones 	void *ptr = gicv3_data.redist_base[0];
13*91a6c3ceSAndrew Jones 	u64 typer;
14*91a6c3ceSAndrew Jones 
15*91a6c3ceSAndrew Jones 	do {
16*91a6c3ceSAndrew Jones 		typer = gicv3_read_typer(ptr + GICR_TYPER);
17*91a6c3ceSAndrew Jones 		if ((typer >> 32) == aff) {
18*91a6c3ceSAndrew Jones 			gicv3_redist_base() = ptr;
19*91a6c3ceSAndrew Jones 			return;
20*91a6c3ceSAndrew Jones 		}
21*91a6c3ceSAndrew Jones 		ptr += stride; /* skip RD_base, SGI_base, etc. */
22*91a6c3ceSAndrew Jones 	} while (!(typer & GICR_TYPER_LAST));
23*91a6c3ceSAndrew Jones 
24*91a6c3ceSAndrew Jones 	/* should never reach here */
25*91a6c3ceSAndrew Jones 	assert(0);
26*91a6c3ceSAndrew Jones }
27*91a6c3ceSAndrew Jones 
28*91a6c3ceSAndrew Jones void gicv3_enable_defaults(void)
29*91a6c3ceSAndrew Jones {
30*91a6c3ceSAndrew Jones 	void *dist = gicv3_dist_base();
31*91a6c3ceSAndrew Jones 	void *sgi_base;
32*91a6c3ceSAndrew Jones 	unsigned int i;
33*91a6c3ceSAndrew Jones 
34*91a6c3ceSAndrew Jones 	gicv3_data.irq_nr = GICD_TYPER_IRQS(readl(dist + GICD_TYPER));
35*91a6c3ceSAndrew Jones 	if (gicv3_data.irq_nr > 1020)
36*91a6c3ceSAndrew Jones 		gicv3_data.irq_nr = 1020;
37*91a6c3ceSAndrew Jones 
38*91a6c3ceSAndrew Jones 	writel(0, dist + GICD_CTLR);
39*91a6c3ceSAndrew Jones 	gicv3_dist_wait_for_rwp();
40*91a6c3ceSAndrew Jones 
41*91a6c3ceSAndrew Jones 	writel(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1,
42*91a6c3ceSAndrew Jones 	       dist + GICD_CTLR);
43*91a6c3ceSAndrew Jones 	gicv3_dist_wait_for_rwp();
44*91a6c3ceSAndrew Jones 
45*91a6c3ceSAndrew Jones 	for (i = 0; i < gicv3_data.irq_nr; i += 4)
46*91a6c3ceSAndrew Jones 		writel(~0, dist + GICD_IGROUPR + i);
47*91a6c3ceSAndrew Jones 
48*91a6c3ceSAndrew Jones 	if (!gicv3_redist_base())
49*91a6c3ceSAndrew Jones 		gicv3_set_redist_base(SZ_64K * 2);
50*91a6c3ceSAndrew Jones 	sgi_base = gicv3_sgi_base();
51*91a6c3ceSAndrew Jones 
52*91a6c3ceSAndrew Jones 	writel(~0, sgi_base + GICR_IGROUPR0);
53*91a6c3ceSAndrew Jones 
54*91a6c3ceSAndrew Jones 	for (i = 0; i < 16; i += 4)
55*91a6c3ceSAndrew Jones 		writel(GICD_INT_DEF_PRI_X4, sgi_base + GICR_IPRIORITYR0 + i);
56*91a6c3ceSAndrew Jones 
57*91a6c3ceSAndrew Jones 	writel(GICD_INT_EN_SET_SGI, sgi_base + GICR_ISENABLER0);
58*91a6c3ceSAndrew Jones 
59*91a6c3ceSAndrew Jones 	gicv3_write_pmr(GICC_INT_PRI_THRESHOLD);
60*91a6c3ceSAndrew Jones 	gicv3_write_grpen1(1);
61*91a6c3ceSAndrew Jones }
62