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
gicv2_enable_defaults(void)9 void gicv2_enable_defaults(void)
10 {
11 void *dist = gicv2_dist_base();
12 void *cpu_base = gicv2_cpu_base();
13 unsigned int i;
14
15 gicv2_data.irq_nr = GICD_TYPER_IRQS(readl(dist + GICD_TYPER));
16 if (gicv2_data.irq_nr > 1020)
17 gicv2_data.irq_nr = 1020;
18
19 for (i = 0; i < gicv2_data.irq_nr; i += 4)
20 writel(GICD_INT_DEF_PRI_X4, dist + GICD_IPRIORITYR + i);
21
22 writel(GICD_INT_EN_SET_SGI, dist + GICD_ISENABLER + 0);
23 writel(GICD_ENABLE, dist + GICD_CTLR);
24
25 writel(GICC_INT_PRI_THRESHOLD, cpu_base + GICC_PMR);
26 writel(GICC_ENABLE, cpu_base + GICC_CTLR);
27 }
28
gicv2_read_iar(void)29 u32 gicv2_read_iar(void)
30 {
31 return readl(gicv2_cpu_base() + GICC_IAR);
32 }
33
gicv2_iar_irqnr(u32 iar)34 u32 gicv2_iar_irqnr(u32 iar)
35 {
36 return iar & GICC_IAR_INT_ID_MASK;
37 }
38
gicv2_write_eoir(u32 irqstat)39 void gicv2_write_eoir(u32 irqstat)
40 {
41 writel(irqstat, gicv2_cpu_base() + GICC_EOIR);
42 }
43
gicv2_ipi_send_single(int irq,int cpu)44 void gicv2_ipi_send_single(int irq, int cpu)
45 {
46 assert(cpu < 8);
47 assert(irq < 16);
48 /*
49 * The wmb() in writel and rmb() in readl() from gicv2_read_iar() are
50 * sufficient for ensuring that stores that happen in program order
51 * before the IPI will be visible after the interrupt is acknowledged.
52 */
53 writel(1 << (cpu + 16) | irq, gicv2_dist_base() + GICD_SGIR);
54 }
55
gicv2_ipi_send_mask(int irq,const cpumask_t * dest)56 void gicv2_ipi_send_mask(int irq, const cpumask_t *dest)
57 {
58 u8 tlist = (u8)cpumask_bits(dest)[0];
59
60 assert(irq < 16);
61 /* No barriers needed, same situation as gicv2_ipi_send_single() */
62 writel(tlist << 16 | irq, gicv2_dist_base() + GICD_SGIR);
63 }
64