Merge remote-tracking branch 'origin/master' into isa/arm64
[lunaix-os.git] / lunaix-os / arch / aarch64 / soc / gic / gic_dt.c
1 #include <lunaix/types.h>
2 #include <lunaix/mm/mmio.h>
3 #include <asm/soc/gic.h>
4
5 #include <klibc/string.h>
6
7 static bool
8 __gic_predicate(struct dt_node_iter* iter, struct dt_node_base* pos)
9 {
10     if (likely(!pos->intr_controll)) {
11         return false;
12     }
13
14     return strneq(pos->compat.str_val, "arm,gic-", 8);
15 }
16
17 static bool
18 __its_predicate(struct dt_node_iter* iter, struct dt_node_base* pos)
19 {
20     return strneq(pos->compat.str_val, "arm,gic-v3-its", 14);
21 }
22
23 static void
24 __setup_pe_rdist(struct arm_gic* gic, struct dt_prop_iter* prop, int cpu)
25 {
26     ptr_t base;
27     size_t len;
28
29     base = dtprop_reg_nextaddr(prop);
30     len  = dtprop_reg_nextlen(prop);
31
32     gic->pes[cpu]._rd = (struct gic_rd*)ioremap(base, len);
33 }
34
35 static void
36 __create_its(struct arm_gic* gic, struct dt_node* gic_node)
37 {
38     struct dt_node* its_node;
39     struct dt_node_iter iter;
40     struct dt_prop_iter prop;
41     struct gic_its* its;
42     ptr_t its_base;
43     size_t its_size;
44
45     dt_begin_find(&iter, gic_node, __its_predicate, NULL);
46
47     while (dt_find_next(&iter, (struct dt_node_base**)&its_node))
48     {
49         dt_decode_reg(&prop, its_node, reg);
50
51         its_base = dtprop_reg_nextaddr(&prop);
52         its_size = dtprop_reg_nextlen(&prop);
53
54         its = gic_its_create(gic, ioremap(its_base, its_size));
55         dt_bind_object(&its_node->base, its);    
56     }
57     
58     dt_end_find(&iter);
59 }
60
61 void
62 gic_create_from_dt(struct arm_gic* gic)
63 {
64     struct dt_node* gic_node;
65     struct dt_node_iter iter;
66     struct dt_prop_iter prop;
67     ptr_t ptr;
68     size_t sz;
69
70     dt_begin_find(&iter, NULL, __gic_predicate, NULL);
71
72     if (!dt_find_next(&iter, (struct dt_node_base**)&gic_node)) {
73         fail("expected 'arm,gic-*' compatible node, but found none");
74     }
75
76     dt_end_find(&iter);
77
78     dt_decode_reg(&prop, gic_node, reg);
79
80     ptr = dtprop_reg_nextaddr(&prop);
81     sz  = dtprop_reg_nextlen(&prop);
82     gic->mmrs.dist_base = (gicreg_t*)ioremap(ptr, sz);
83
84     for (int i = 0; i < NR_CPU; i++) {
85         __setup_pe_rdist(gic, &prop, i);
86     }
87     
88     // ignore cpu_if, as we use sysreg to access them    
89     // ignore vcpu_if, as we dont do any EL2 stuff
90
91     __create_its(gic, gic_node);
92
93     dt_bind_object(&gic_node->base, gic);
94 }
95
96 unsigned int;
97 gic_dtprop_interpret(struct gic_int_param* param, 
98                      struct dt_prop_val* val, int width)
99 {
100     struct dt_prop_iter iter;
101     unsigned int v;
102
103     dt_decode_simple(&iter, val);
104
105     v = dtprop_u32_at(&iter, 0);
106     switch (v)
107     {
108     case 0:
109         param->class = GIC_SPI;
110         break;
111     case 1:
112         param->class = GIC_PPI;
113         break;
114     case 2:
115         param->class = GIC_SPI;
116         param->ext_range = true;
117     
118     default:
119         fail("invalid interrupt type");
120         break;
121     }
122
123     v = dtprop_u32_at(&iter, 2);
124     param->trigger = v == 1 ? GIC_TRIG_EDGE : GIC_TRIG_LEVEL;
125
126     param->group = GIC_G1NS;
127     param->rel_intid = dtprop_u32_at(&iter, 1);
128
129     return param->rel_intid;
130 }