rework parsing of interupt-map in interrupt node.
[lunaix-os.git] / lunaix-os / includes / hal / devtree.h
1 #ifndef __LUNAIX_DEVTREE_H
2 #define __LUNAIX_DEVTREE_H
3
4 #include <lunaix/types.h>
5 #include <lunaix/ds/llist.h>
6 #include <lunaix/ds/hstr.h>
7 #include <lunaix/ds/hashtable.h>
8 #include <lunaix/boot_generic.h>
9
10 #define le(v) ((((v) >> 24) & 0x000000ff)  |\
11                (((v) << 8)  & 0x00ff0000)  |\
12                (((v) >> 8)  & 0x0000ff00)  |\
13                (((v) << 24) & 0xff000000))
14
15 #define le64(v) (((u64_t)le(v & 0xffffffff) << 32) | le(v >> 32))
16
17 #define be(v) ((((v) << 24) & 0x000000ff)  |\
18                (((v) >> 8)  & 0x00ff0000)  |\
19                (((v) << 8)  & 0x0000ff00)  |\
20                (((v) >> 24) & 0xff000000))
21
22 #define FDT_MAGIC       be(0xd00dfeed)
23 #define FDT_NOD_BEGIN   be(0x00000001)
24 #define FDT_NOD_END     be(0x00000002)
25 #define FDT_PROP        be(0x00000003)
26 #define FDT_NOP         be(0x00000004)
27 #define FDT_END         be(0x00000009)
28
29 #define STATUS_OK       0
30 #define STATUS_DISABLE  1
31 #define STATUS_RSVD     2
32 #define STATUS_FAIL     3
33
34
35 typedef unsigned int* dt_enc_t;
36 typedef unsigned int  dt_phnd_t;
37 typedef bool (*node_predicate_t)(struct dt_node_iter*, struct dt_node*);
38
39
40 #define PHND_NULL    ((dt_phnd_t)-1)
41
42 struct fdt_header {
43     u32_t magic;
44     u32_t totalsize;
45     u32_t off_dt_struct;
46     u32_t off_dt_strings;
47     u32_t off_mem_rsvmap;
48     u32_t version;
49     u32_t last_comp_version;
50     u32_t boot_cpuid_phys;
51     u32_t size_dt_strings;
52     u32_t size_dt_struct;
53 };
54
55 struct fdt_memrsvd_ent 
56 {
57     u64_t addr;
58     u64_t size;
59 } align(8);
60
61 struct fdt_token 
62 {
63     u32_t token;
64 } compact align(4);
65
66 struct fdt_node_head
67 {
68     struct fdt_token token;
69     char name[0];
70 };
71
72 struct fdt_prop 
73 {
74     struct fdt_token token;
75     u32_t len;
76     u32_t nameoff;
77 } compact align(4);
78
79 struct dt_prop_val
80 {
81     struct {
82         union
83         {
84             union {
85                 const char*  str_val;
86                 const char** str_lst;
87             };
88             ptr_t        ptr_val;
89             
90             union {
91                 dt_enc_t     encoded;
92                 dt_phnd_t    phandle;
93             };
94             u32_t        u32_val;
95
96             u64_t        u64_val;
97         };
98         unsigned int size;
99     };
100 };
101
102
103 struct dt_prop
104 {
105     struct hlist_node   ht;
106     struct hstr         key;
107     struct dt_prop_val  val;
108 };
109
110 struct dt_node_base
111 {
112     union {
113         struct {
114             unsigned char addr_c;
115             unsigned char sz_c;
116             unsigned char intr_c;
117             unsigned char status;
118         };
119         unsigned int _std;
120     };
121
122     union {
123         struct {
124             bool dma_coherent  : 1;
125             bool dma_ncoherent : 1;
126             bool intr_controll : 1;
127             bool intr_neuxs    : 1;
128             unsigned int other : 29;
129         };
130         unsigned int    flags;
131     };
132
133     struct dt_node_base  *parent;
134     struct llist_header   children;
135     struct llist_header   siblings;
136     struct llist_header   nodes;
137     struct hlist_node     phnd_link;
138
139     const char*           name;
140
141     struct dt_prop_val    compat;
142     const char*           model;
143     dt_phnd_t             phandle;
144
145     union {
146         struct hbucket    other_props[0];
147         struct hbucket    _op_bucket[8];
148     };
149
150     void* obj;
151 };
152
153 struct dt_root
154 {
155     struct dt_node_base base;
156
157     const char*         serial;
158     const char*         chassis;
159 };
160
161 struct dt_intr_prop;
162
163 struct dt_intr_mapkey
164 {
165     unsigned int* val;
166     unsigned int  size;
167 };
168
169 struct dt_intr_mapent
170 {
171     struct llist_header ents;
172
173     struct dt_intr_mapkey key;
174
175     struct dt_node_base* parent;
176     struct dt_prop_val parent_props;
177 };
178
179 struct dt_intr_map 
180 {
181     struct dt_prop_val       raw;
182     struct dt_prop_val       raw_mask;
183
184     struct dt_intr_mapkey    key_mask;
185     struct llist_header      mapent;
186
187     bool resolved;
188 };
189
190 struct dt_intr_node
191 {
192     union {
193         struct dt_intr_node *parent;
194         dt_phnd_t parent_hnd;
195     };
196
197     struct {
198         bool extended;
199         bool valid;
200         union {
201             struct dt_prop_val   arr;
202             struct llist_header  values; 
203         };
204     } intr;
205
206     struct dt_intr_map* map;
207 };
208 #define INTR_TO_DTNODE(intr_node) \
209         (container_of(intr_node, struct dt_node, intr))
210
211 #define BASE_TO_DTNODE(base_node) \
212         (container_of(base_node, struct dt_node, base))
213
214 struct dt_node
215 {
216     struct dt_node_base base;
217     struct dt_intr_node intr;
218     
219     struct dt_prop_val  reg;
220     struct dt_prop_val  vreg;
221
222     struct dt_prop_val  ranges;
223     struct dt_prop_val  dma_ranges;
224 };
225
226
227 struct dt_intr_prop
228 {
229     struct dt_intr_node *master;
230
231     struct llist_header  props;
232     struct dt_prop_val   val;
233 };
234
235 struct dt_prop_iter
236 {
237     struct dt_prop_val     *prop;
238     struct dt_node_base    *node;
239     dt_enc_t                prop_loc;
240     dt_enc_t                prop_loc_next;
241     unsigned int            ent_sz;
242 };
243
244 struct dt_context
245 {
246     union {
247         ptr_t reloacted_dtb;
248         struct fdt_header* fdt;
249     };
250
251     struct llist_header   nodes;
252     struct dt_root       *root;
253     struct hbucket        phnds_table[16];
254     const char           *str_block;
255 };
256
257 struct fdt_iter
258 {
259     union {
260         struct fdt_token      *pos;
261         struct fdt_prop       *prop;
262         struct fdt_node_head  *node_head;
263     };
264
265     const char* str_block;
266     int depth;
267 };
268
269 struct fdt_memrsvd_iter
270 {
271     struct fdt_memrsvd_ent *block;
272 };
273
274 struct dt_node_iter
275 {
276     struct dt_node_base* head;
277     struct dt_node_base* matched;
278     void* closure;
279     node_predicate_t pred;
280 };
281
282 #define dtnode_child_foreach(node_base, pos, n)  \
283         llist_for_each(pos, n, &(node_base)->children, siblings)
284
285 #define fdt_prop(tok) ((tok)->token == FDT_PROP)
286 #define fdt_node(tok) ((tok)->token == FDT_NOD_BEGIN)
287 #define fdt_node_end(tok) ((tok)->token == FDT_NOD_END)
288 #define fdt_nope(tok) ((tok)->token == FDT_NOP)
289
290 void 
291 fdt_itbegin(struct fdt_iter* fdti, struct fdt_header* fdt_hdr);
292
293 void 
294 fdt_itend(struct fdt_iter* fdti);
295
296 bool 
297 fdt_itnext(struct fdt_iter* fdti);
298
299 bool 
300 fdt_itnext_at(struct fdt_iter* fdti, int level);
301
302 void
303 fdt_memrsvd_itbegin(struct fdt_memrsvd_iter* rsvdi, 
304                     struct fdt_header* fdt_hdr);
305
306 bool
307 fdt_memrsvd_itnext(struct fdt_memrsvd_iter* rsvdi);
308
309 void
310 fdt_memrsvd_itend(struct fdt_memrsvd_iter* rsvdi);
311
312
313 bool
314 dt_load(ptr_t dtb_dropoff);
315
316 struct dt_node*
317 dt_resolve_phandle(dt_phnd_t phandle);
318
319 struct dt_prop_val*
320 dt_getprop(struct dt_node_base* base, const char* name);
321
322 void
323 dt_begin_find_byname(struct dt_node_iter* iter, 
324                      struct dt_node* node, const char* name);
325
326 void
327 dt_begin_find(struct dt_node_iter* iter, struct dt_node* node, 
328               node_predicate_t pred, void* closure);
329
330 struct dt_prop_val*
331 resolve_interrupt(struct dt_node* node);
332
333 void
334 resolve_interrupt_map(struct dt_node* node);
335
336 static inline void
337 dt_end_find(struct dt_node_iter* iter)
338 {
339     // currently do nothing, keep only for semantic
340 }
341
342 bool
343 dt_find_next(struct dt_node_iter* iter,
344              struct dt_node_base** matched);
345
346 static inline bool
347 dt_found_any(struct dt_node_iter* iter)
348 {
349     return !!iter->matched;
350 }
351
352
353 static inline void
354 dt_bind_object(struct dt_node_base* base, void* obj)
355 {
356     base->obj = obj;
357 }
358
359 static inline bool
360 dt_has_binding(struct dt_node_base* base) 
361 {
362     return base->obj != NULL;
363 }
364
365 #define dt_binding_of(node_base, type)  \
366     ((type)(node_base)->obj)
367
368 static inline char*
369 fdtit_prop_key(struct fdt_iter* fdti)
370 {
371     return &fdti->str_block[fdti->prop->nameoff];
372 }
373
374 static inline void
375 dt_decode(struct dt_prop_iter* dtpi, struct dt_node_base* node, 
376                 struct dt_prop_val* val, unsigned int ent_sz)
377 {
378     *dtpi = (struct dt_prop_iter) {
379         .prop = val,
380         .node = node,
381         .prop_loc = val->encoded,
382         .prop_loc_next = val->encoded,
383         .ent_sz = ent_sz
384     };
385 }
386
387 #define dt_decode_reg(dtpi, node, field) \
388             dt_decode(dtpi, &(node)->base, &(node)->field, \
389                             (node)->base.sz_c + (node)->base.addr_c);
390
391 #define dt_decode_range(dtpi, node, field) \
392             dt_decode(dtpi, &(node)->base, &(node)->field, \
393                             (node)->base.sz_c * 2 + (node)->base.addr_c);
394
395 #define dtprop_off(dtpi) \
396             (unsigned int)(\
397                 __ptr(dtpi->prop_loc_next) - __ptr(dtpi->prop->encoded) \
398             )
399
400 #define dtprop_extract(dtpi, off) \
401             ( (dt_enc_t) (&(dtpi)->prop_loc[(off)]) )
402
403 static inline bool
404 dtprop_next_n(struct dt_prop_iter* dtpi, int n)
405 {
406     unsigned int off;
407
408     dtpi->prop_loc = dtpi->prop_loc_next;
409     dtpi->prop_loc_next += n;
410
411     off = dtprop_off(dtpi);
412     return off >= dtpi->prop->size;
413 }
414
415 static inline bool
416 dtprop_prev_n(struct dt_prop_iter* dtpi, int n)
417 {
418     unsigned int off;
419
420     off = dtprop_off(dtpi);
421     if (!off || off > dtpi->prop->size) {
422         return false;
423     }
424
425     dtpi->prop_loc = dtpi->prop_loc_next;
426     dtpi->prop_loc_next -= n;
427
428     return true;
429 }
430
431 static inline bool
432 dtprop_next(struct dt_prop_iter* dtpi)
433 {
434     return dtprop_next_n(dtpi, dtpi->ent_sz);
435 }
436
437 static inline bool
438 dtprop_prev(struct dt_prop_iter* dtpi)
439 {
440     return dtprop_prev_n(dtpi, dtpi->ent_sz);
441 }
442
443 static inline unsigned int
444 dtprop_to_u32(dt_enc_t enc_val)
445 {
446     return le(*enc_val);
447 }
448
449 #define dtprop_to_phnd(enc_val) \
450             (dt_phnd_t)dtprop_to_u32(enc_val)
451
452 static inline u64_t
453 dtprop_to_u64(dt_enc_t enc_val)
454 {
455     return le64(*(u64_t*)enc_val);
456 }
457
458 static inline u32_t
459 dtprop_u32_at(struct dt_prop_iter* dtpi, int index)
460 {
461     return dtprop_to_u32(dtprop_extract(dtpi, index));
462 }
463
464 static inline u32_t
465 dtprop_u64_at(struct dt_prop_iter* dtpi, int index)
466 {
467     return dtprop_to_u64(dtprop_extract(dtpi, index));
468 }
469
470 static inline dt_enc_t
471 dtprop_reg_addr(struct dt_prop_iter* dtpi)
472 {
473     return dtprop_extract(dtpi, 0);
474 }
475
476 static inline ptr_t
477 dtprop_reg_nextaddr(struct dt_prop_iter* dtpi)
478 {
479     ptr_t t;
480
481     t = (ptr_t)dtprop_to_u64(dtprop_reg_addr(dtpi));
482     dtprop_next(dtpi);
483
484     return t;
485 }
486
487 static inline dt_enc_t
488 dtprop_reg_len(struct dt_prop_iter* dtpi)
489 {
490     return dtprop_extract(dtpi, dtpi->node->addr_c);
491 }
492
493 static inline size_t
494 dtprop_reg_nextlen(struct dt_prop_iter* dtpi)
495 {
496     size_t t;
497
498     t = (size_t)dtprop_to_u64(dtprop_reg_len(dtpi));
499     dtprop_next(dtpi);
500
501     return t;
502 }
503
504 static inline dt_enc_t
505 dtprop_range_childbus(struct dt_prop_iter* dtpi)
506 {
507     return dtprop_extract(dtpi, 0);
508 }
509
510 static inline dt_enc_t
511 dtprop_range_parentbus(struct dt_prop_iter* dtpi)
512 {
513     return dtprop_extract(dtpi, dtpi->node->addr_c);
514 }
515
516 static inline dt_enc_t
517 dtprop_range_len(struct dt_prop_iter* dtpi)
518 {
519     return dtprop_extract(dtpi, dtpi->node->addr_c * 2);
520 }
521
522 #endif /* __LUNAIX_DEVTREE_H */