xref: /kvm-unit-tests/lib/arm/gic.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 <devicetree.h>
7 #include <asm/gic.h>
8 #include <asm/io.h>
9 
10 struct gicv2_data gicv2_data;
11 struct gicv3_data gicv3_data;
12 
13 /*
14  * Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
15  * Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
16  */
17 static bool
18 gic_get_dt_bases(const char *compatible, void **base1, void **base2)
19 {
20 	struct dt_pbus_reg reg;
21 	struct dt_device gic;
22 	struct dt_bus bus;
23 	int node, ret;
24 
25 	dt_bus_init_defaults(&bus);
26 	dt_device_init(&gic, &bus, NULL);
27 
28 	node = dt_device_find_compatible(&gic, compatible);
29 	assert(node >= 0 || node == -FDT_ERR_NOTFOUND);
30 
31 	if (node == -FDT_ERR_NOTFOUND)
32 		return false;
33 
34 	dt_device_bind_node(&gic, node);
35 
36 	ret = dt_pbus_translate(&gic, 0, &reg);
37 	assert(ret == 0);
38 	*base1 = ioremap(reg.addr, reg.size);
39 
40 	ret = dt_pbus_translate(&gic, 1, &reg);
41 	assert(ret == 0);
42 	*base2 = ioremap(reg.addr, reg.size);
43 
44 	return true;
45 }
46 
47 int gicv2_init(void)
48 {
49 	return gic_get_dt_bases("arm,cortex-a15-gic",
50 			&gicv2_data.dist_base, &gicv2_data.cpu_base);
51 }
52 
53 int gicv3_init(void)
54 {
55 	return gic_get_dt_bases("arm,gic-v3", &gicv3_data.dist_base,
56 			&gicv3_data.redist_base[0]);
57 }
58 
59 int gic_init(void)
60 {
61 	if (gicv2_init())
62 		return 2;
63 	else if (gicv3_init())
64 		return 3;
65 	return 0;
66 }
67