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