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