Merge branch 'master' into isa/arm64
[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_dev;
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
446 //////////////////////////////////////
447 ///     DT Methods: Specifier Map
448 //////////////////////////////////////
449
450
451 struct dtspec_create_ops
452 {
453     int (*child_keysz)(struct dtn*);
454     int (*parent_keysz)(struct dtn*);
455     struct dtp_val* (*get_mask)(struct dtn*);
456     struct dtp_val* (*get_passthru)(struct dtn*);
457 };
458
459 struct dtspec_map*
460 dtspec_create(struct dtn* node, struct dtp_val* map,
461               const struct dtspec_create_ops* ops);
462
463 struct dtspec_mapent*
464 dtspec_lookup(struct dtspec_map*, struct dtspec_key*);
465
466 void
467 dtspec_applymask(struct dtspec_map*, struct dtspec_key*);
468
469 void
470 dtspec_free(struct dtspec_map*);
471
472 void
473 dtspec_cpykey(struct dtspec_key* dest, struct dtspec_key* src);
474
475 void
476 dtspec_freekey(struct dtspec_key* key);
477
478 static inline bool
479 dtspec_nullkey(struct dtspec_key* key)
480 {
481     return !key || !key->size;
482 }
483
484
485 //////////////////////////////////////
486 ///     DT Methods: Node query
487 //////////////////////////////////////
488
489 void
490 dt_begin_find_byname(struct dtn_iter* iter, 
491                      struct dtn* node, const char* name);
492
493 void
494 dt_begin_find(struct dtn_iter* iter, struct dtn* node, 
495               node_predicate_t pred, void* closure);
496
497 static inline void
498 dt_end_find(struct dtn_iter* iter)
499 {
500     // currently do nothing, keep only for semantic
501 }
502
503 bool
504 dt_find_next(struct dtn_iter* iter,
505              struct dtn_base** matched);
506
507 static inline bool
508 dt_found_any(struct dtn_iter* iter)
509 {
510     return !!iter->matched;
511 }
512
513 struct dt_context*
514 dt_main_context();
515
516 static inline u32_t
517 dtp_u32(struct dtp_val* val)
518 {
519     return val->ref->u32_val;
520 }
521
522 static inline u64_t
523 dtp_u64(struct dtp_val* val)
524 {
525     return val->ref->u64_val;
526 }
527
528 static inline void
529 dtp_speckey(struct dtspec_key* key, struct dtp_val* prop)
530 {
531     key->size = prop->size / sizeof(u32_t);
532     key->val  = prop->encoded;
533 }
534
535
536 //////////////////////////////////////
537 ///     DT Prop Extractor
538 //////////////////////////////////////
539
540 enum dtprop_types
541 {
542     DTP_END = 0,
543     DTP_U32,
544     DTP_U64,
545     DTP_PHANDLE,
546     DTP_COMPX,
547 };
548
549 struct dtprop_def
550 {
551     unsigned int cell;
552     unsigned int acc_sz;
553     enum dtprop_types type;
554 };
555
556 typedef struct dtprop_def dt_proplet[];
557
558 struct dtprop_xval
559 {
560     union {
561         u32_t u32;
562         ptr_t u64;
563         struct dtn* phandle;
564         union {
565             dt_enc_t composite;
566             union dtp_baseval* cval;
567         };
568     };
569     struct dtprop_def* archetype;
570 };
571
572 struct dtpropx
573 {
574     const struct dtprop_def* proplet;
575     int proplet_len;
576     int proplet_sz;
577
578     struct dtp_val* raw;
579     off_t row_loc;
580 };
581
582 #define dtprop_u32              (struct dtprop_def){ 1, 0, DTP_U32 }
583 #define dtprop_u64              (struct dtprop_def){ 2, 0, DTP_U64 }
584 #define dtprop_handle           (struct dtprop_def){ 1, 0, DTP_PHANDLE }
585 #define dtprop_compx(cell)      (struct dtprop_def){ cell, 0, DTP_COMPX }
586 #define dtprop_end              (struct dtprop_def){ 0, 0, DTP_END }
587 #define dtprop_(type, cell)     (struct dtprop_def){ cell, 0, type }
588
589 #define dtprop_reglike(base)                    \
590     ({                                          \
591         dt_proplet p = {                        \
592             dtprop_compx(base->addr_c),         \
593             dtprop_compx(base->sz_c),           \
594             dtprop_end                          \
595         };                                      \
596         dt_proplet;                             \
597     })
598
599 #define dtprop_rangelike(node)                  \
600     ({                                          \
601         dt_proplet p = {                        \
602             dtprop_compx(base->addr_c),         \
603             dtprop_compx(base->parent->addr_c), \
604             dtprop_compx(base->sz_c),           \
605             dtprop_end                          \
606         };                                      \
607         dt_proplet;                             \
608     })
609
610 #define dtprop_strlst_foreach(pos, prop)    \
611         for (pos = (prop)->str_lst; \
612              pos <= &(prop)->str_lst[(prop)->size - 1]; \
613              pos = &pos[strlen(pos) + 1])
614
615 void
616 dtpx_compile_proplet(struct dtprop_def* proplet);
617
618 void
619 dtpx_prepare_with(struct dtpropx* propx, struct dtp_val* prop,
620                   struct dtprop_def* proplet);
621
622 #define dtproplet_compile(proplet)   \
623         dtpx_compile_proplet(proplet, \
624                           sizeof(proplet) / sizeof(struct dtprop_def))
625
626 bool
627 dtpx_goto_row(struct dtpropx*, int row);
628
629 bool
630 dtpx_next_row(struct dtpropx*);
631
632 bool
633 dtpx_extract_at(struct dtpropx*, struct dtprop_xval*, int col);
634
635 bool
636 dtpx_extract_loc(struct dtpropx*, struct dtprop_xval*, 
637                  int row, int col);
638
639 bool
640 dtpx_extract_row(struct dtpropx*, struct dtprop_xval*, int len);
641
642 static inline u32_t
643 dtpx_xvalu32(struct dtprop_xval* val){
644     return val->archetype->type == DTP_COMPX ?
645             val->cval->u32_val : val->u32;
646 }
647
648 static inline u64_t
649 dtpx_xvalu64(struct dtprop_xval* val){
650     return val->archetype->type == DTP_COMPX ?
651             val->cval->u64_val : val->u64;
652 }
653
654
655 //////////////////////////////////////
656 ///     DT Prop Iterator
657 //////////////////////////////////////
658
659 static inline void
660 dtpi_init(struct dtpropi* dtpi, struct dtp_val* val)
661 {
662     *dtpi = (struct dtpropi) {
663         .prop = *val,
664         .loc = 0
665     };
666 }
667
668 static inline void
669 dtpi_init_empty(struct dtpropi* dtpi)
670 {
671     *dtpi = (struct dtpropi) {
672         .prop = { 0, 0 },
673         .loc = 0
674     };
675 }
676
677 static inline bool
678 dtpi_is_empty(struct dtpropi* dtpi)
679 {
680     return !dtpi->prop.size;
681 }
682
683 static inline bool
684 dtpi_has_next(struct dtpropi* dtpi)
685 {
686     return dtpi->loc < dtpi->prop.size / sizeof(u32_t);
687 }
688
689 static inline u32_t
690 dtpi_next_u32(struct dtpropi* dtpi) 
691 {
692     union dtp_baseval* val;
693     val = (union dtp_baseval*)&dtpi->prop.encoded[dtpi->loc++];
694     return val->u32_val;
695 }
696
697 static inline u64_t
698 dtpi_next_u64(struct dtpropi* dtpi) 
699 {
700     union dtp_baseval* val;
701     off_t loc = dtpi->loc;
702     dtpi->loc += 2;
703     val = (union dtp_baseval*)&dtpi->prop.encoded[loc];
704     
705     return val->u64_val;
706 }
707
708 static inline struct dtn*
709 dtpi_next_hnd(struct dtpropi* dtpi) 
710 {
711     u32_t phandle;
712     phandle = dtpi_next_u32(dtpi);
713     return dt_resolve_phandle(phandle);
714 }
715
716 static inline bool
717 dtpi_next_val(struct dtpropi* dtpi, struct dtp_val* val, int cells) 
718 {
719     if (!dtpi_has_next(dtpi)) {
720         return false;
721     }
722
723     off_t loc = dtpi->loc;
724     dtp_val_set(val, &dtpi->prop.encoded[loc], cells);
725
726     dtpi->loc += cells;
727     return true;
728 }
729
730 #endif /* __LUNAIX_DEVTREE_H */