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 <devicetree.h> 7 #include <asm/gic.h> 8 #include <asm/io.h> 9 10 struct gicv2_data gicv2_data; 11 12 /* 13 * Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt 14 */ 15 static bool 16 gic_get_dt_bases(const char *compatible, void **base1, void **base2) 17 { 18 struct dt_pbus_reg reg; 19 struct dt_device gic; 20 struct dt_bus bus; 21 int node, ret; 22 23 dt_bus_init_defaults(&bus); 24 dt_device_init(&gic, &bus, NULL); 25 26 node = dt_device_find_compatible(&gic, compatible); 27 assert(node >= 0 || node == -FDT_ERR_NOTFOUND); 28 29 if (node == -FDT_ERR_NOTFOUND) 30 return false; 31 32 dt_device_bind_node(&gic, node); 33 34 ret = dt_pbus_translate(&gic, 0, ®); 35 assert(ret == 0); 36 *base1 = ioremap(reg.addr, reg.size); 37 38 ret = dt_pbus_translate(&gic, 1, ®); 39 assert(ret == 0); 40 *base2 = ioremap(reg.addr, reg.size); 41 42 return true; 43 } 44 45 int gicv2_init(void) 46 { 47 return gic_get_dt_bases("arm,cortex-a15-gic", 48 &gicv2_data.dist_base, &gicv2_data.cpu_base); 49 } 50 51 int gic_init(void) 52 { 53 if (gicv2_init()) 54 return 2; 55 return 0; 56 } 57 58 void gicv2_enable_defaults(void) 59 { 60 void *dist = gicv2_dist_base(); 61 void *cpu_base = gicv2_cpu_base(); 62 unsigned int i; 63 64 gicv2_data.irq_nr = GICD_TYPER_IRQS(readl(dist + GICD_TYPER)); 65 if (gicv2_data.irq_nr > 1020) 66 gicv2_data.irq_nr = 1020; 67 68 for (i = 0; i < gicv2_data.irq_nr; i += 4) 69 writel(GICD_INT_DEF_PRI_X4, dist + GICD_IPRIORITYR + i); 70 71 writel(GICD_INT_EN_SET_SGI, dist + GICD_ISENABLER + 0); 72 writel(GICD_ENABLE, dist + GICD_CTLR); 73 74 writel(GICC_INT_PRI_THRESHOLD, cpu_base + GICC_PMR); 75 writel(GICC_ENABLE, cpu_base + GICC_CTLR); 76 } 77