move gic to new devtree interface
[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/changeling.h>
9
10 #include <klibc/string.h>
11
12 #define FDT_MAGIC       0xd00dfeedU
13 #define FDT_NOD_BEGIN   0x00000001U
14 #define FDT_NOD_END     0x00000002U
15 #define FDT_PROP        0x00000003U
16 #define FDT_NOP         0x00000004U
17 #define FDT_END         0x00000009U
18
19 #define STATUS_OK       0
20 #define STATUS_DISABLE  1
21 #define STATUS_RSVD     2
22 #define STATUS_FAIL     3
23
24 #define PHND_NULL    ((dt_phnd_t)-1)
25
26 /////////////////////////////////
27 ///     DT Primitives
28 /////////////////////////////////
29
30 typedef unsigned int*     dt_enc_t;
31 typedef unsigned int      dt_phnd_t;
32
33 struct dtn_base;
34 struct dtn_iter;
35 typedef bool (*node_predicate_t)(struct dtn_iter*, struct dtn_base*);
36
37 union dtp_baseval
38 {
39     u32_t        u32_val;
40     u64_t        u64_val;
41     dt_phnd_t    phandle;
42     u32_t        raw[0];
43 } _be;
44
45 struct dtp_val
46 {
47     union
48     {
49         union {
50             const char*  str_val;
51             const char*  str_lst;
52         };
53         ptr_t        ptr_val;
54         dt_enc_t     encoded;
55         
56         union dtp_baseval* ref;
57     };
58     unsigned int size;
59 };
60
61 struct dtpropi
62 {
63     struct dtp_val     prop;
64     off_t loc;
65 };
66
67 /////////////////////////////////
68 ///     FDT Constructs
69 /////////////////////////////////
70
71 struct fdt_header {
72     u32_t magic;
73     u32_t totalsize;
74     u32_t off_dt_struct;
75     u32_t off_dt_strings;
76     u32_t off_mem_rsvmap;
77     u32_t version;
78     u32_t last_comp_version;
79     u32_t boot_cpuid_phys;
80     u32_t size_dt_strings;
81     u32_t size_dt_struct;
82 } _be;
83
84 struct fdt_memrsvd_ent 
85 {
86     u64_t addr;
87     u64_t size;
88 } _be align(8);
89
90
91 struct fdt_token 
92 {
93     u32_t token;
94 } _be compact align(4);
95
96 struct fdt_prop
97 {
98     struct fdt_token token;
99     u32_t len;
100     u32_t nameoff;
101
102     union {
103         u32_t val[0];
104         char  val_str[0];
105     } _be;
106 } _be compact align(4);
107
108 struct fdt_loc
109 {
110     union {
111         struct fdt_token        *token;
112         struct fdt_prop         *prop;
113         struct fdt_memrsvd_ent  *rsvd_ent;
114         ptr_t                    ptr;
115         struct {
116             struct fdt_token token;
117             char name[0];
118         } *node;
119     };
120 };
121 typedef struct fdt_loc fdt_loc_t;
122
123
124 enum fdt_state {
125     FDT_STATE_START,
126     FDT_STATE_NODE,
127     FDT_STATE_NODE_EXIT,
128     FDT_STATE_PROP,
129     FDT_STATE_END,
130 };
131
132 enum fdtit_mode {
133     FDT_RSVDMEM,
134     FDT_STRUCT,
135 };
136
137 enum fdt_mem_type {
138     FDT_MEM_RSVD,
139     FDT_MEM_RSVD_DYNAMIC,
140     FDT_MEM_FREE
141 };
142
143 struct fdt_rsvdmem_attrs
144 {
145     size_t total_size;
146     ptr_t alignment;
147     
148     union {
149         struct {
150             bool nomap    : 1;
151             bool reusable : 1;
152         };
153         int flags;
154     };
155 };
156
157 struct dt_memory_node
158 {
159     ptr_t base;
160     ptr_t size;
161     enum fdt_mem_type type;
162
163     struct fdt_rsvdmem_attrs dyn_alloc_attr;
164 };
165
166 struct fdt_rsvd_mem
167 {
168     u64_t base;
169     u64_t size;
170 } _be align(8);
171
172 struct fdt_blob
173 {
174     union {
175         struct fdt_header* header;
176         ptr_t fdt_base;
177     };
178
179     fdt_loc_t root;
180     union {
181         const char* str_block;
182         ptr_t str_block_base;
183     };
184
185
186     union {
187         struct fdt_rsvd_mem* plat_rsvd;
188         ptr_t plat_rsvd_base;
189     };
190 };
191
192 struct fdt_memscan
193 {
194     fdt_loc_t loc;
195     fdt_loc_t found;
196     
197     struct dtpropi regit;
198
199     u32_t root_addr_c;
200     u32_t root_size_c;
201     enum fdt_mem_type node_type;
202
203     struct fdt_rsvdmem_attrs node_attr;
204 };
205
206 struct fdt_memrsvd_iter
207 {
208     struct fdt_memrsvd_ent *block;
209 };
210
211
212 /////////////////////////////////
213 ///     DT Construct
214 /////////////////////////////////
215
216 struct dtp
217 {
218     struct hlist_node   ht;
219     struct hstr         key;
220     struct dtp_val  val;
221 };
222
223 struct dtp_table
224 {
225     union {
226         struct hbucket    other_props[0];
227         struct hbucket    _op_bucket[8];
228     };
229 };
230
231 struct dtn_base
232 {
233     morph_t mobj;
234
235     union {
236         struct {
237             unsigned char addr_c;
238             unsigned char sz_c;
239             unsigned char intr_c;
240             unsigned char status;
241         };
242         unsigned int _std;
243     };
244
245     union {
246         struct {
247             bool dma_coherent  : 1;
248             bool dma_ncoherent : 1;
249             bool intr_controll : 1;
250         };
251         unsigned int    flags;
252     };
253
254     struct dtn_base         *parent;
255     struct llist_header      nodes;
256
257     struct dtp_val           compat;
258     dt_phnd_t                phandle;
259
260     struct dtp_table        *props;
261
262     morph_t                 *binded_obj;
263 };
264
265 struct dtspec_key
266 {
267     union {
268         union dtp_baseval *bval;
269         unsigned int*      val;
270     };
271     unsigned int      size;
272 };
273
274 struct dtspec_mapent
275 {
276     struct llist_header ents;
277     const struct dtspec_key child_spec;
278     
279     struct dtn* parent;
280     const struct dtspec_key parent_spec;
281 };
282
283 struct dtspec_map
284 {
285     const struct dtspec_key mask;
286     const struct dtspec_key pass_thru;
287
288     struct llist_header ents;
289 };
290
291 struct dtspec_intr
292 {
293     struct dtn *domain;
294
295     struct llist_header  ispecs;
296     struct dtp_val   val;
297 };
298
299 struct dtn_intr
300 {
301     union {
302         struct dtn *parent;
303         dt_phnd_t parent_hnd;
304     };
305
306     union {
307         struct {
308             bool extended : 1;
309             bool valid : 1;
310         };
311         int flags;
312     };
313
314     union {
315         struct dtp_val       raw_ispecs;
316         struct llist_header  ext_ispecs; 
317     };
318     
319     int nr_intrs;
320
321     struct dtspec_map* map;
322 };
323
324 struct dtn
325 {
326     union {
327         morph_t mobj;
328         struct dtn_base base;
329     };
330     
331     struct dtn_intr intr;
332     
333     struct dtp_val  reg;
334
335     struct dtp_val  ranges;
336     struct dtp_val  dma_ranges;
337 };
338 #define dt_parent(node)  ((node)->base.parent)
339 #define dt_morpher       morphable_attrs(dtn, mobj)
340 #define dt_mobj(node)    (&(node)->mobj)
341 #define dt_name(node)    morpher_name(dt_mobj(node))
342 #define dtn_from(base_node) \
343         (container_of(base_node, struct dtn, base))
344
345 struct dtn_iter
346 {
347     struct dtn_base* head;
348     struct dtn_base* matched;
349     void* closure;
350     node_predicate_t pred;
351 };
352
353 struct dt_context
354 {
355     struct fdt_blob         fdt;
356
357     struct llist_header     nodes;
358     struct dtn             *root;
359     struct hbucket          phnds_table[16];
360     const char             *str_block;
361 };
362
363
364 /////////////////////////////////
365 ///     FDT Methods
366 /////////////////////////////////
367
368 #define fdt_prop(tok) ((tok)->token == FDT_PROP)
369 #define fdt_node(tok) ((tok)->token == FDT_NOD_BEGIN)
370 #define fdt_nope(tok) ((tok)->token == FDT_NOP)
371 #define fdt_eof(tok)  ((tok)->token == FDT_END)
372 #define fdt_node_end(tok) \
373     ((tok)->token == FDT_NOD_END || (tok)->token == FDT_END)
374
375 void
376 fdt_load(struct fdt_blob* fdt, ptr_t base);
377
378 fdt_loc_t
379 fdt_next_token(fdt_loc_t loc, int* depth);
380
381 bool
382 fdt_next_sibling(fdt_loc_t loc, fdt_loc_t* loc_out);
383
384 bool
385 fdt_next_boot_rsvdmem(struct fdt_blob*, fdt_loc_t*, struct dt_memory_node*);
386
387 fdt_loc_t
388 fdt_descend_into(fdt_loc_t loc);
389
390 static inline fdt_loc_t
391 fdt_ascend_from(fdt_loc_t loc) 
392 {
393     while (fdt_next_sibling(loc, &loc));
394
395     loc.token++;
396     return loc;
397 }
398
399 bool
400 fdt_memscan_begin(struct fdt_memscan*, const struct fdt_blob*);
401
402 bool
403 fdt_memscan_nextnode(struct fdt_memscan*, struct fdt_blob*);
404
405 bool
406 fdt_memscan_nextrange(struct fdt_memscan*, struct dt_memory_node*);
407
408 bool
409 fdt_find_prop(const struct fdt_blob*, fdt_loc_t, 
410               const char*, struct dtp_val*);
411
412 static inline char*
413 fdt_prop_key(struct fdt_blob* fdt, fdt_loc_t loc)
414 {
415     return &fdt->str_block[loc.prop->nameoff];
416 }
417
418
419 /////////////////////////////////
420 ///     DT General Methods
421 /////////////////////////////////
422
423 bool
424 dt_load(ptr_t dtb_dropoff);
425
426 struct dtn*
427 dt_resolve_phandle(dt_phnd_t phandle);
428
429 struct dtp_val*
430 dt_getprop(struct dtn_base* base, const char* name);
431
432 void
433 dt_resolve_interrupt_map(struct dtn* node);
434
435 struct dtn* 
436 dt_interrupt_at(struct dtn* node, int idx, struct dtp_val* int_spec);
437
438 static inline void
439 dtp_val_set(struct dtp_val* val, dt_enc_t raw, unsigned cells)
440 {
441     val->encoded = raw;
442     val->size = cells * sizeof(u32_t);
443 }
444
445 static inline void
446 dtn_bind_object(struct dtn* node, morph_t* mobj)
447 {
448     node->base.binded_obj = changeling_ref(mobj);
449 }
450
451
452 //////////////////////////////////////
453 ///     DT Methods: Specifier Map
454 //////////////////////////////////////
455
456
457 struct dtspec_create_ops
458 {
459     int (*child_keysz)(struct dtn*);
460     int (*parent_keysz)(struct dtn*);
461     struct dtp_val* (*get_mask)(struct dtn*);
462     struct dtp_val* (*get_passthru)(struct dtn*);
463 };
464
465 struct dtspec_map*
466 dtspec_create(struct dtn* node, struct dtp_val* map,
467               const struct dtspec_create_ops* ops);
468
469 struct dtspec_mapent*
470 dtspec_lookup(struct dtspec_map*, struct dtspec_key*);
471
472 void
473 dtspec_applymask(struct dtspec_map*, struct dtspec_key*);
474
475 void
476 dtspec_free(struct dtspec_map*);
477
478 void
479 dtspec_cpykey(struct dtspec_key* dest, struct dtspec_key* src);
480
481 void
482 dtspec_freekey(struct dtspec_key* key);
483
484 static inline bool
485 dtspec_nullkey(struct dtspec_key* key)
486 {
487     return !key || !key->size;
488 }
489
490
491 //////////////////////////////////////
492 ///     DT Methods: Node query
493 //////////////////////////////////////
494
495 void
496 dt_begin_find_byname(struct dtn_iter* iter, 
497                      struct dtn* node, const char* name);
498
499 void
500 dt_begin_find(struct dtn_iter* iter, struct dtn* node, 
501               node_predicate_t pred, void* closure);
502
503 static inline void
504 dt_end_find(struct dtn_iter* iter)
505 {
506     // currently do nothing, keep only for semantic
507 }
508
509 bool
510 dt_find_next(struct dtn_iter* iter,
511              struct dtn_base** matched);
512
513 static inline bool
514 dt_found_any(struct dtn_iter* iter)
515 {
516     return !!iter->matched;
517 }
518
519 struct dt_context*
520 dt_main_context();
521
522 static inline u32_t
523 dtp_u32(struct dtp_val* val)
524 {
525     return val->ref->u32_val;
526 }
527
528 static inline u64_t
529 dtp_u64(struct dtp_val* val)
530 {
531     return val->ref->u64_val;
532 }
533
534 static inline void
535 dtp_speckey(struct dtspec_key* key, struct dtp_val* prop)
536 {
537     key->size = prop->size / sizeof(u32_t);
538     key->val  = prop->encoded;
539 }
540
541
542 //////////////////////////////////////
543 ///     DT Prop Extractor
544 //////////////////////////////////////
545
546 enum dtprop_types
547 {
548     DTP_END = 0,
549     DTP_U32,
550     DTP_U64,
551     DTP_PHANDLE,
552     DTP_COMPX,
553 };
554
555 struct dtprop_def
556 {
557     unsigned int cell;
558     unsigned int acc_sz;
559     enum dtprop_types type;
560 };
561
562 typedef struct dtprop_def dt_proplet[];
563
564 struct dtprop_xval
565 {
566     union {
567         u32_t u32;
568         ptr_t u64;
569         struct dtn* phandle;
570         union {
571             dt_enc_t composite;
572             union dtp_baseval* cval;
573         };
574     };
575     struct dtprop_def* archetype;
576 };
577
578 struct dtpropx
579 {
580     const struct dtprop_def* proplet;
581     int proplet_len;
582     int proplet_sz;
583
584     struct dtp_val* raw;
585     off_t row_loc;
586 };
587
588 #define dtprop_u32              (struct dtprop_def){ 1, 0, DTP_U32 }
589 #define dtprop_u64              (struct dtprop_def){ 2, 0, DTP_U64 }
590 #define dtprop_handle           (struct dtprop_def){ 1, 0, DTP_PHANDLE }
591 #define dtprop_compx(cell)      (struct dtprop_def){ cell, 0, DTP_COMPX }
592 #define dtprop_end              (struct dtprop_def){ 0, 0, DTP_END }
593 #define dtprop_(type, cell)     (struct dtprop_def){ cell, 0, type }
594
595 #define dtprop_reglike(base)                    \
596     ({                                          \
597         dt_proplet p = {                        \
598             dtprop_compx((base)->addr_c),       \
599             dtprop_compx((base)->sz_c),         \
600             dtprop_end                          \
601         };                                      \
602         p;                             \
603     })
604
605 #define dtprop_rangelike(node)                  \
606     ({                                          \
607         dt_proplet p = {                        \
608             dtprop_compx(base->addr_c),         \
609             dtprop_compx(base->parent->addr_c), \
610             dtprop_compx(base->sz_c),           \
611             dtprop_end                          \
612         };                                      \
613         p;                             \
614     })
615
616 #define dtprop_strlst_foreach(pos, prop)    \
617         for (pos = (prop)->str_lst; \
618              pos <= &(prop)->str_lst[(prop)->size - 1]; \
619              pos = &pos[strlen(pos) + 1])
620
621 void
622 dtpx_compile_proplet(struct dtprop_def* proplet);
623
624 void
625 dtpx_prepare_with(struct dtpropx* propx, struct dtp_val* prop,
626                   struct dtprop_def* proplet);
627
628 #define dtproplet_compile(proplet)   \
629         dtpx_compile_proplet(proplet, \
630                           sizeof(proplet) / sizeof(struct dtprop_def))
631
632 bool
633 dtpx_goto_row(struct dtpropx*, int row);
634
635 bool
636 dtpx_next_row(struct dtpropx*);
637
638 bool
639 dtpx_extract_at(struct dtpropx*, struct dtprop_xval*, int col);
640
641 bool
642 dtpx_extract_loc(struct dtpropx*, struct dtprop_xval*, 
643                  int row, int col);
644
645 bool
646 dtpx_extract_row(struct dtpropx*, struct dtprop_xval*, int len);
647
648 static inline u32_t
649 dtpx_xvalu32(struct dtprop_xval* val){
650     return val->archetype->type == DTP_COMPX ?
651             val->cval->u32_val : val->u32;
652 }
653
654 static inline u64_t
655 dtpx_xvalu64(struct dtprop_xval* val){
656     return val->archetype->type == DTP_COMPX ?
657             val->cval->u64_val : val->u64;
658 }
659
660
661 //////////////////////////////////////
662 ///     DT Prop Iterator
663 //////////////////////////////////////
664
665 static inline void
666 dtpi_init(struct dtpropi* dtpi, struct dtp_val* val)
667 {
668     *dtpi = (struct dtpropi) {
669         .prop = *val,
670         .loc = 0
671     };
672 }
673
674 static inline void
675 dtpi_init_empty(struct dtpropi* dtpi)
676 {
677     *dtpi = (struct dtpropi) {
678         .prop = { 0, 0 },
679         .loc = 0
680     };
681 }
682
683 static inline bool
684 dtpi_is_empty(struct dtpropi* dtpi)
685 {
686     return !dtpi->prop.size;
687 }
688
689 static inline bool
690 dtpi_has_next(struct dtpropi* dtpi)
691 {
692     return dtpi->loc < dtpi->prop.size / sizeof(u32_t);
693 }
694
695 static inline u32_t
696 dtpi_next_u32(struct dtpropi* dtpi) 
697 {
698     union dtp_baseval* val;
699     val = (union dtp_baseval*)&dtpi->prop.encoded[dtpi->loc++];
700     return val->u32_val;
701 }
702
703 static inline u64_t
704 dtpi_next_u64(struct dtpropi* dtpi) 
705 {
706     union dtp_baseval* val;
707     off_t loc = dtpi->loc;
708     dtpi->loc += 2;
709     val = (union dtp_baseval*)&dtpi->prop.encoded[loc];
710     
711     return val->u64_val;
712 }
713
714 static inline struct dtn*
715 dtpi_next_hnd(struct dtpropi* dtpi) 
716 {
717     u32_t phandle;
718     phandle = dtpi_next_u32(dtpi);
719     return dt_resolve_phandle(phandle);
720 }
721
722 static inline bool
723 dtpi_next_val(struct dtpropi* dtpi, struct dtp_val* val, int cells) 
724 {
725     if (!dtpi_has_next(dtpi)) {
726         return false;
727     }
728
729     off_t loc = dtpi->loc;
730     dtp_val_set(val, &dtpi->prop.encoded[loc], cells);
731
732     dtpi->loc += cells;
733     return true;
734 }
735
736 #endif /* __LUNAIX_DEVTREE_H */