rewrite the gic implementation, some other fix ups
[lunaix-os.git] / lunaix-os / arch / aarch64 / soc / gic / gic-common.h
1 #ifndef __LUNAIX_GIC_COMMON_H
2 #define __LUNAIX_GIC_COMMON_H
3
4 #include <lunaix/types.h>
5 #include <lunaix/status.h>
6 #include <hal/irq.h>
7
8 #define PAD(body, name, offset)   \
9     struct { char _pad_##name[offset]; body; } compact
10
11 #define PAD_STRUCT(body, name, offset)  \
12     PAD(struct body, name, offset)
13
14 #define FIELD_AT(type, field, offset)   \
15     PAD(volatile type field, field, offset)
16
17 #define ARRAY_AT(type, arr, offset, end)   \
18     PAD(volatile type arr[((end) - (offset)) / sizeof(type) + 1], arr, offset)
19
20
21 typedef unsigned int intid_t;
22
23 struct gic_pe;
24 struct gic_int_class;
25
26 enum gic_intkind
27 {
28     GIC_INT_SGI = 0,
29     GIC_INT_PPI,
30     GIC_INT_PPI_EXT,
31     GIC_INT_LPI,
32     GIC_INT_SPI,
33     GIC_INT_SPI_EXT,
34     GIC_INT_COUNT
35 };
36
37 enum gic_intgrp
38 {
39     GIC_INT_GROUP0,
40     GIC_INT_GROUP1_S,
41     GIC_INT_GROUP1_NS,
42 };
43
44 enum gic_trigger
45 {
46     GIC_TRIG_LEVEL,
47     GIC_TRIG_EDGE,
48 };
49
50 struct gic_interrupt
51 {
52     intid_t intid;
53
54     enum gic_intgrp grp;
55     enum gic_intkind kind;
56     enum gic_trigger trig;
57     int priority;
58     bool nmi;
59     bool enabled;
60
61     union {
62         u64_t raw_val;
63         struct gic_pe* pe;
64     } affinity;
65     
66     struct irq_object* irq;
67 };
68 #define GIC_INTR_RAW_AFF    1
69
70 struct gic_int_class_ops
71 {
72     int (*set_enabled)(struct gic_int_class*, intid_t, bool);
73     int (*set_prority)(struct gic_int_class*, intid_t, int);
74     int (*set_nmi)(struct gic_int_class*, intid_t, bool);
75     int (*set_route)(struct gic_int_class*,intid_t, struct gic_pe*);
76     int (*set_trigger)(struct gic_int_class*,intid_t, enum gic_trigger);
77
78     int (*retrieve)(struct gic_int_class*, struct gic_interrupt*, intid_t);
79     int (*install)(struct gic_int_class*, struct gic_interrupt*);
80     int (*delete)(struct gic_int_class*, intid_t);
81
82     int (*fire)(struct gic_int_class*, intid_t);
83 };
84 extern const struct gic_int_class_ops aa64_gic_fallback_ops;
85
86 struct gic;
87 struct gic_pe;
88 struct gic_int_class
89 {
90     enum gic_intkind kind;
91     
92     struct {
93         intid_t start;
94         intid_t stop;
95     } range;
96
97     struct gic_int_class_ops* ops;
98 };
99
100 struct gic_pe_ops
101 {
102     bool (*ack_int)(struct gic_pe*);
103     int (*notify_eoi)(struct gic_pe*);
104     int (*set_priority_mask)(struct gic_pe*, int);
105 };
106
107 struct gic_pe
108 {
109     union {
110         struct {
111             struct gic_int_class sgi;
112             struct gic_int_class ppi;
113             struct gic_int_class ppi_e;
114             struct gic_int_class lpi;
115         };
116         struct gic_int_class classes[4];
117     };
118
119     struct {
120         union {
121             intid_t active_id;
122             struct gic_interrupt active_int;
123         };
124         bool has_active_int;
125     };
126
127     void* impl;
128
129     int index;
130     int affinity;
131
132     struct gic* distr;
133     struct gic_pe_ops* ops;
134 };
135
136 struct gic
137 {
138     int nr_cpus;
139     struct gic_pe** cores;
140
141     union {
142         struct {
143             struct gic_int_class spi;
144             struct gic_int_class spi_e;
145         };
146         struct gic_int_class classes[2];
147     };
148
149     void* impl;
150
151     struct irq_domain* domain;
152 };
153
154 static inline void
155 gic_init_int_class(struct gic_int_class* class, 
156                    enum gic_intkind kind, intid_t start, intid_t end)
157 {
158     *class = (struct gic_int_class) {
159         .range.start = start,
160         .range.stop  = end,
161         .kind = kind
162     };
163 }
164
165 static inline bool
166 gic_valid_int_class(struct gic_int_class* class) {
167     return class->ops && (class->range.start < class->range.stop);
168 }
169
170 static inline void
171 gic_intr_set_raw_affval(struct gic_interrupt* intr, u32_t affval)
172 {
173     intr->affinity.raw_val = ((u64_t)affval << 1) | GIC_INTR_RAW_AFF;
174 }
175
176 static inline int
177 gic_assign_intid(struct gic_int_class* class, irq_t irq)
178 {
179     int err;
180     struct gic* gic;
181
182     if (!gic_valid_int_class(class)) {
183         // selected class not present or disabled
184         return ENOENT;
185     }
186
187     gic = gic_global_context_of(class);
188     err = irq_alloc_id(gic->domain, irq, 
189                         class->range.start, class->range.stop);
190
191     return err;
192 }
193
194 struct gic_pe*
195 gic_create_pe_context(struct gic* gic, void* pe_impl);
196
197 struct gic_pe*
198 gic_local_context_of(struct gic_int_class* int_class);
199
200 struct gic*
201 gic_global_context_of(struct gic_int_class* int_class);
202
203 int
204 gic_get_interrupt(struct gic* gic, intid_t id, struct gic_interrupt* intr_out);
205
206 struct gic*
207 gic_create_context(struct device* gicdev);
208
209
210 // default ops
211
212 int 
213 __fallback_set_enabled(struct gic_int_class* class, intid_t intid, bool en);
214
215 int 
216 __fallback_set_prority(struct gic_int_class* class, intid_t intid, int prio);
217
218 int 
219 __fallback_set_nmi(struct gic_int_class* class, intid_t intid, bool nmi);
220
221 int 
222 __fallback_set_route(struct gic_int_class* class, 
223                 intid_t intid, struct gic_pe* target);
224
225 int 
226 __fallback_set_trigger(struct gic_int_class* class, 
227                   intid_t intid, enum gic_trigger trig);
228
229
230 int 
231 __fallback_retrieve(struct gic_int_class* class, 
232                struct gic_interrupt*, intid_t intid);
233
234 int 
235 __fallback_install(struct gic_int_class* class, struct gic_interrupt* gic);
236
237 int 
238 __fallback_delete(struct gic_int_class* class, intid_t intid);
239 #endif /* __LUNAIX_GIC_COMMON_H */