1 #include <lunaix/types.h>
2 #include <lunaix/mm/mmio.h>
3 #include <asm/soc/gic.h>
5 #include <klibc/string.h>
8 __gic_predicate(struct dt_node_iter* iter, struct dt_node_base* pos)
10 if (likely(!pos->intr_controll)) {
14 return strneq(pos->compat.str_val, "arm,gic-", 8);
18 __its_predicate(struct dt_node_iter* iter, struct dt_node_base* pos)
20 return strneq(pos->compat.str_val, "arm,gic-v3-its", 14);
24 __setup_pe_rdist(struct arm_gic* gic, struct dt_prop_iter* prop, int cpu)
29 base = dtprop_reg_nextaddr(prop);
30 len = dtprop_reg_nextlen(prop);
32 gic->pes[cpu]._rd = (struct gic_rd*)ioremap(base, len);
36 __create_its(struct arm_gic* gic, struct dt_node* gic_node)
38 struct dt_node* its_node;
39 struct dt_node_iter iter;
40 struct dt_prop_iter prop;
45 dt_begin_find(&iter, gic_node, __its_predicate, NULL);
47 while (dt_find_next(&iter, (struct dt_node_base**)&its_node))
49 dt_decode_reg(&prop, its_node, reg);
51 its_base = dtprop_reg_nextaddr(&prop);
52 its_size = dtprop_reg_nextlen(&prop);
54 its = gic_its_create(gic, ioremap(its_base, its_size));
55 dt_bind_object(&its_node->base, its);
62 gic_create_from_dt(struct arm_gic* gic)
64 struct dt_node* gic_node;
65 struct dt_node_iter iter;
66 struct dt_prop_iter prop;
70 dt_begin_find(&iter, NULL, __gic_predicate, NULL);
72 if (!dt_find_next(&iter, (struct dt_node_base**)&gic_node)) {
73 fail("expected 'arm,gic-*' compatible node, but found none");
78 dt_decode_reg(&prop, gic_node, reg);
80 ptr = dtprop_reg_nextaddr(&prop);
81 sz = dtprop_reg_nextlen(&prop);
82 gic->mmrs.dist_base = (gicreg_t*)ioremap(ptr, sz);
84 for (int i = 0; i < NR_CPU; i++) {
85 __setup_pe_rdist(gic, &prop, i);
88 // ignore cpu_if, as we use sysreg to access them
89 // ignore vcpu_if, as we dont do any EL2 stuff
91 __create_its(gic, gic_node);
93 dt_bind_object(&gic_node->base, gic);
97 gic_dtprop_interpret(struct gic_int_param* param,
98 struct dt_prop_val* val, int width)
100 struct dt_prop_iter iter;
103 dt_decode_simple(&iter, val);
105 v = dtprop_u32_at(&iter, 0);
109 param->class = GIC_SPI;
112 param->class = GIC_PPI;
115 param->class = GIC_SPI;
116 param->ext_range = true;
119 fail("invalid interrupt type");
123 v = dtprop_u32_at(&iter, 2);
124 param->trigger = v == 1 ? GIC_TRIG_EDGE : GIC_TRIG_LEVEL;
126 param->group = GIC_G1NS;
127 param->rel_intid = dtprop_u32_at(&iter, 1);
129 return param->rel_intid;