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