xref: /kvm-unit-tests/lib/arm/gic-v2.c (revision 2e2d471d2aeb249869b525a42dcf22659d6c4bc7)
191a6c3ceSAndrew Jones /*
291a6c3ceSAndrew Jones  * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
391a6c3ceSAndrew Jones  *
491a6c3ceSAndrew Jones  * This work is licensed under the terms of the GNU LGPL, version 2.
591a6c3ceSAndrew Jones  */
691a6c3ceSAndrew Jones #include <asm/gic.h>
791a6c3ceSAndrew Jones #include <asm/io.h>
891a6c3ceSAndrew Jones 
991a6c3ceSAndrew Jones void gicv2_enable_defaults(void)
1091a6c3ceSAndrew Jones {
1191a6c3ceSAndrew Jones 	void *dist = gicv2_dist_base();
1291a6c3ceSAndrew Jones 	void *cpu_base = gicv2_cpu_base();
1391a6c3ceSAndrew Jones 	unsigned int i;
1491a6c3ceSAndrew Jones 
1591a6c3ceSAndrew Jones 	gicv2_data.irq_nr = GICD_TYPER_IRQS(readl(dist + GICD_TYPER));
1691a6c3ceSAndrew Jones 	if (gicv2_data.irq_nr > 1020)
1791a6c3ceSAndrew Jones 		gicv2_data.irq_nr = 1020;
1891a6c3ceSAndrew Jones 
1991a6c3ceSAndrew Jones 	for (i = 0; i < gicv2_data.irq_nr; i += 4)
2091a6c3ceSAndrew Jones 		writel(GICD_INT_DEF_PRI_X4, dist + GICD_IPRIORITYR + i);
2191a6c3ceSAndrew Jones 
2291a6c3ceSAndrew Jones 	writel(GICD_INT_EN_SET_SGI, dist + GICD_ISENABLER + 0);
2391a6c3ceSAndrew Jones 	writel(GICD_ENABLE, dist + GICD_CTLR);
2491a6c3ceSAndrew Jones 
2591a6c3ceSAndrew Jones 	writel(GICC_INT_PRI_THRESHOLD, cpu_base + GICC_PMR);
2691a6c3ceSAndrew Jones 	writel(GICC_ENABLE, cpu_base + GICC_CTLR);
2791a6c3ceSAndrew Jones }
28*2e2d471dSAndrew Jones 
29*2e2d471dSAndrew Jones u32 gicv2_read_iar(void)
30*2e2d471dSAndrew Jones {
31*2e2d471dSAndrew Jones 	return readl(gicv2_cpu_base() + GICC_IAR);
32*2e2d471dSAndrew Jones }
33*2e2d471dSAndrew Jones 
34*2e2d471dSAndrew Jones u32 gicv2_iar_irqnr(u32 iar)
35*2e2d471dSAndrew Jones {
36*2e2d471dSAndrew Jones 	return iar & GICC_IAR_INT_ID_MASK;
37*2e2d471dSAndrew Jones }
38*2e2d471dSAndrew Jones 
39*2e2d471dSAndrew Jones void gicv2_write_eoir(u32 irqstat)
40*2e2d471dSAndrew Jones {
41*2e2d471dSAndrew Jones 	writel(irqstat, gicv2_cpu_base() + GICC_EOIR);
42*2e2d471dSAndrew Jones }
43*2e2d471dSAndrew Jones 
44*2e2d471dSAndrew Jones void gicv2_ipi_send_single(int irq, int cpu)
45*2e2d471dSAndrew Jones {
46*2e2d471dSAndrew Jones 	assert(cpu < 8);
47*2e2d471dSAndrew Jones 	assert(irq < 16);
48*2e2d471dSAndrew Jones 	writel(1 << (cpu + 16) | irq, gicv2_dist_base() + GICD_SGIR);
49*2e2d471dSAndrew Jones }
50*2e2d471dSAndrew Jones 
51*2e2d471dSAndrew Jones void gicv2_ipi_send_mask(int irq, const cpumask_t *dest)
52*2e2d471dSAndrew Jones {
53*2e2d471dSAndrew Jones 	u8 tlist = (u8)cpumask_bits(dest)[0];
54*2e2d471dSAndrew Jones 
55*2e2d471dSAndrew Jones 	assert(irq < 16);
56*2e2d471dSAndrew Jones 	writel(tlist << 16 | irq, gicv2_dist_base() + GICD_SGIR);
57*2e2d471dSAndrew Jones }
58