devtree: fix addr/size cells should use parent's
[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         };
129         unsigned int    flags;
130     };
131
132     struct dt_node_base  *parent;
133     struct llist_header   children;
134     struct llist_header   siblings;
135     struct llist_header   nodes;
136     struct hlist_node     phnd_link;
137
138     const char*           name;
139
140     struct dt_prop_val    compat;
141     const char*           model;
142     dt_phnd_t             phandle;
143
144     union {
145         struct hbucket    other_props[0];
146         struct hbucket    _op_bucket[8];
147     };
148
149     void* obj;
150 };
151
152 struct dt_root
153 {
154     struct dt_node_base base;
155
156     const char*         serial;
157     const char*         chassis;
158 };
159
160 struct dt_intr_prop;
161
162 struct dt_intr_mapkey
163 {
164     unsigned int* val;
165     unsigned int  size;
166 };
167
168 struct dt_intr_mapent
169 {
170     struct llist_header ents;
171
172     struct dt_intr_mapkey key;
173
174     struct dt_node_base* parent;
175     struct dt_prop_val parent_props;
176 };
177
178 struct dt_intr_map 
179 {
180     struct dt_prop_val       raw;
181     struct dt_prop_val       raw_mask;
182
183     struct dt_intr_mapkey    key_mask;
184     struct llist_header      mapent;
185
186     bool resolved;
187 };
188
189 struct dt_intr_node
190 {
191     union {
192         struct dt_intr_node *parent;
193         dt_phnd_t parent_hnd;
194     };
195
196     struct {
197         bool extended;
198         bool valid;
199         union {
200             struct dt_prop_val   arr;
201             struct llist_header  values; 
202         };
203     } intr;
204
205     struct dt_intr_map* map;
206 };
207 #define INTR_TO_DTNODE(intr_node) \
208         (container_of(intr_node, struct dt_node, intr))
209
210 #define BASE_TO_DTNODE(base_node) \
211         (container_of(base_node, struct dt_node, base))
212
213 struct dt_node
214 {
215     struct dt_node_base base;
216     struct dt_intr_node intr;
217     
218     struct dt_prop_val  reg;
219     struct dt_prop_val  vreg;
220
221     struct dt_prop_val  ranges;
222     struct dt_prop_val  dma_ranges;
223 };
224
225
226 struct dt_intr_prop
227 {
228     struct dt_intr_node *master;
229
230     struct llist_header  props;
231     struct dt_prop_val   val;
232 };
233
234 struct dt_prop_iter
235 {
236     struct dt_prop_val     *prop;
237     struct dt_node_base    *node;
238     dt_enc_t                prop_loc;
239     dt_enc_t                prop_loc_next;
240     unsigned int            ent_sz;
241 };
242
243 struct dt_context
244 {
245     union {
246         ptr_t reloacted_dtb;
247         struct fdt_header* fdt;
248     };
249
250     struct llist_header   nodes;
251     struct dt_root       *root;
252     struct hbucket        phnds_table[16];
253     const char           *str_block;
254 };
255
256 struct fdt_iter
257 {
258     union {
259         struct fdt_token      *pos;
260         struct fdt_prop       *prop;
261         struct fdt_node_head  *node_head;
262     };
263
264     const char* str_block;
265     int depth;
266 };
267
268 struct fdt_memrsvd_iter
269 {
270     struct fdt_memrsvd_ent *block;
271 };
272
273 struct dt_node_iter
274 {
275     struct dt_node_base* head;
276     struct dt_node_base* matched;
277     void* closure;
278     node_predicate_t pred;
279 };
280
281
282
283 /****
284  * FDT Related
285  ****/
286
287 #define fdt_prop(tok) ((tok)->token == FDT_PROP)
288 #define fdt_node(tok) ((tok)->token == FDT_NOD_BEGIN)
289 #define fdt_node_end(tok) ((tok)->token == FDT_NOD_END)
290 #define fdt_nope(tok) ((tok)->token == FDT_NOP)
291
292 void 
293 fdt_itbegin(struct fdt_iter* fdti, struct fdt_header* fdt_hdr);
294
295 void 
296 fdt_itend(struct fdt_iter* fdti);
297
298 bool 
299 fdt_itnext(struct fdt_iter* fdti);
300
301 bool 
302 fdt_itnext_at(struct fdt_iter* fdti, int level);
303
304 void
305 fdt_memrsvd_itbegin(struct fdt_memrsvd_iter* rsvdi, 
306                     struct fdt_header* fdt_hdr);
307
308 bool
309 fdt_memrsvd_itnext(struct fdt_memrsvd_iter* rsvdi);
310
311 void
312 fdt_memrsvd_itend(struct fdt_memrsvd_iter* rsvdi);
313
314 static inline char*
315 fdtit_prop_key(struct fdt_iter* fdti)
316 {
317     return &fdti->str_block[fdti->prop->nameoff];
318 }
319
320
321 /****
322  * DT Main Functions: General
323  ****/
324
325 bool
326 dt_load(ptr_t dtb_dropoff);
327
328 struct dt_node*
329 dt_resolve_phandle(dt_phnd_t phandle);
330
331 struct dt_prop_val*
332 dt_getprop(struct dt_node_base* base, const char* name);
333
334 struct dt_prop_val*
335 dt_resolve_interrupt(struct dt_node* node);
336
337 void
338 dt_resolve_interrupt_map(struct dt_node* node);
339
340 static inline unsigned int
341 dt_addr_cells(struct dt_node_base* base)
342 {
343     return base->parent ? base->parent->addr_c : base->addr_c;
344 }
345
346 static inline unsigned int
347 dt_size_cells(struct dt_node_base* base)
348 {
349     return base->parent ? base->parent->sz_c : base->sz_c;
350 }
351
352
353 /****
354  * DT Main Functions: Node-finder
355  ****/
356
357 void
358 dt_begin_find_byname(struct dt_node_iter* iter, 
359                      struct dt_node* node, const char* name);
360
361 void
362 dt_begin_find(struct dt_node_iter* iter, struct dt_node* node, 
363               node_predicate_t pred, void* closure);
364
365 static inline void
366 dt_end_find(struct dt_node_iter* iter)
367 {
368     // currently do nothing, keep only for semantic
369 }
370
371 bool
372 dt_find_next(struct dt_node_iter* iter,
373              struct dt_node_base** matched);
374
375 static inline bool
376 dt_found_any(struct dt_node_iter* iter)
377 {
378     return !!iter->matched;
379 }
380
381
382 /****
383  * DT Main Functions: Node-binding
384  ****/
385
386 static inline void
387 dt_bind_object(struct dt_node_base* base, void* obj)
388 {
389     base->obj = obj;
390 }
391
392 static inline bool
393 dt_has_binding(struct dt_node_base* base) 
394 {
395     return base->obj != NULL;
396 }
397
398 #define dt_binding_of(node_base, type)  \
399     ((type)(node_base)->obj)
400
401
402 /****
403  * DT Main Functions: Prop decoders
404  ****/
405
406 static inline void
407 dt_decode(struct dt_prop_iter* dtpi, struct dt_node_base* node, 
408                 struct dt_prop_val* val, unsigned int ent_sz)
409 {
410     *dtpi = (struct dt_prop_iter) {
411         .prop = val,
412         .node = node,
413         .prop_loc = val->encoded,
414         .prop_loc_next = val->encoded,
415         .ent_sz = ent_sz
416     };
417 }
418
419 #define dt_decode_reg(dtpi, node, field) \
420             dt_decode(dtpi, &(node)->base, &(node)->field, \
421                         dt_size_cells(&(node)->base) \
422                             + dt_addr_cells(&(node)->base))
423
424 #define dt_decode_range(dtpi, node, field) \
425             dt_decode(dtpi, &(node)->base, &(node)->field, \
426                         dt_size_cells(&(node)->base) * 2 \
427                             + dt_addr_cells(&(node)->base))
428
429 #define dt_decode_simple(dtpi, prop) \
430             dt_decode(dtpi, NULL, prop, 1);
431
432 #define dtprop_off(dtpi) \
433             (unsigned int)(\
434                 __ptr(dtpi->prop_loc_next) - __ptr(dtpi->prop->encoded) \
435             )
436
437 #define dtprop_extract(dtpi, off) \
438             ( (dt_enc_t) (&(dtpi)->prop_loc[(off)]) )
439
440 static inline bool
441 dtprop_next_n(struct dt_prop_iter* dtpi, int n)
442 {
443     unsigned int off;
444
445     dtpi->prop_loc = dtpi->prop_loc_next;
446     dtpi->prop_loc_next += n;
447
448     off = dtprop_off(dtpi);
449     return off >= dtpi->prop->size;
450 }
451
452 static inline bool
453 dtprop_prev_n(struct dt_prop_iter* dtpi, int n)
454 {
455     unsigned int off;
456
457     off = dtprop_off(dtpi);
458     if (!off || off > dtpi->prop->size) {
459         return false;
460     }
461
462     dtpi->prop_loc = dtpi->prop_loc_next;
463     dtpi->prop_loc_next -= n;
464
465     return true;
466 }
467
468 static inline bool
469 dtprop_next(struct dt_prop_iter* dtpi)
470 {
471     return dtprop_next_n(dtpi, dtpi->ent_sz);
472 }
473
474 static inline bool
475 dtprop_prev(struct dt_prop_iter* dtpi)
476 {
477     return dtprop_prev_n(dtpi, dtpi->ent_sz);
478 }
479
480 static inline unsigned int
481 dtprop_to_u32(dt_enc_t enc_val)
482 {
483     return le(*enc_val);
484 }
485
486 #define dtprop_to_phnd(enc_val) \
487             (dt_phnd_t)dtprop_to_u32(enc_val)
488
489 static inline u64_t
490 dtprop_to_u64(dt_enc_t enc_val)
491 {
492     return le64(*(u64_t*)enc_val);
493 }
494
495 static inline u32_t
496 dtprop_u32_at(struct dt_prop_iter* dtpi, int index)
497 {
498     return dtprop_to_u32(dtprop_extract(dtpi, index));
499 }
500
501 static inline u32_t
502 dtprop_u64_at(struct dt_prop_iter* dtpi, int index)
503 {
504     return dtprop_to_u64(dtprop_extract(dtpi, index));
505 }
506
507 static inline dt_enc_t
508 dtprop_reg_addr(struct dt_prop_iter* dtpi)
509 {
510     return dtprop_extract(dtpi, 0);
511 }
512
513 static inline ptr_t
514 dtprop_reg_nextaddr(struct dt_prop_iter* dtpi)
515 {
516     ptr_t t;
517
518     t = (ptr_t)dtprop_to_u64(dtprop_reg_addr(dtpi));
519     dtprop_next_n(dtpi, dt_addr_cells(dtpi->node));
520
521     return t;
522 }
523
524 static inline dt_enc_t
525 dtprop_reg_len(struct dt_prop_iter* dtpi)
526 {
527     return dtprop_extract(dtpi, dtpi->node->addr_c);
528 }
529
530 static inline size_t
531 dtprop_reg_nextlen(struct dt_prop_iter* dtpi)
532 {
533     size_t t;
534
535     t = (size_t)dtprop_to_u64(dtprop_reg_len(dtpi));
536     dtprop_next_n(dtpi, dt_size_cells(dtpi->node));
537
538     return t;
539 }
540
541 static inline dt_enc_t
542 dtprop_range_childbus(struct dt_prop_iter* dtpi)
543 {
544     return dtprop_extract(dtpi, 0);
545 }
546
547 static inline dt_enc_t
548 dtprop_range_parentbus(struct dt_prop_iter* dtpi)
549 {
550     return dtprop_extract(dtpi, dt_addr_cells(dtpi->node));
551 }
552
553 static inline dt_enc_t
554 dtprop_range_len(struct dt_prop_iter* dtpi)
555 {
556     return dtprop_extract(dtpi, dt_addr_cells(dtpi->node) * 2);
557 }
558
559 #endif /* __LUNAIX_DEVTREE_H */