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/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
38 #define PHND_NULL    ((dt_phnd_t)-1)
39
40 struct fdt_header {
41     u32_t magic;
42     u32_t totalsize;
43     u32_t off_dt_struct;
44     u32_t off_dt_strings;
45     u32_t off_mem_rsvmap;
46     u32_t version;
47     u32_t last_comp_version;
48     u32_t boot_cpuid_phys;
49     u32_t size_dt_strings;
50     u32_t size_dt_struct;
51 };
52
53 struct fdt_memrsvd_ent 
54 {
55     u64_t addr;
56     u64_t size;
57 } align(8);
58
59 struct fdt_token 
60 {
61     u32_t token;
62 } compact align(4);
63
64 struct fdt_node_head
65 {
66     struct fdt_token token;
67     char name[0];
68 };
69
70 struct fdt_prop 
71 {
72     struct fdt_token token;
73     u32_t len;
74     u32_t nameoff;
75 } compact align(4);
76
77 struct dt_prop_val
78 {
79     struct {
80         union
81         {
82             union {
83                 const char*  str_val;
84                 const char** str_lst;
85             };
86             ptr_t        ptr_val;
87             
88             union {
89                 dt_enc_t     encoded;
90                 dt_phnd_t    phandle;
91             };
92             u32_t        u32_val;
93
94             u64_t        u64_val;
95         };
96         unsigned int size;
97     };
98 };
99
100
101 struct dt_prop
102 {
103     struct hlist_node   ht;
104     struct hstr         key;
105     struct dt_prop_val  val;
106 };
107
108 struct dt_node_base
109 {
110     union {
111         struct {
112             unsigned char addr_c;
113             unsigned char sz_c;
114             unsigned char intr_c;
115             unsigned char status;
116         };
117         unsigned int _std;
118     };
119
120     union {
121         struct {
122             bool dma_coherent  : 1;
123             bool dma_ncoherent : 1;
124             bool intr_controll : 1;
125             unsigned int other : 29;
126         };
127         unsigned int    flags;
128     };
129
130     struct dt_node_base  *parent;
131     struct llist_header   children;
132     struct llist_header   siblings;
133     struct llist_header   nodes;
134     struct hlist_node     phnd_link;
135
136     const char*           name;
137
138     struct dt_prop_val    compat;
139     const char*           model;
140     dt_phnd_t             phandle;
141
142     union {
143         struct hbucket    other_props[0];
144         struct hbucket    _op_bucket[8];
145     };
146 };
147
148 struct dt_root
149 {
150     struct dt_node_base base;
151
152     const char*         serial;
153     const char*         chassis;
154 };
155
156 struct dt_intr_prop;
157
158 struct dt_intr_node
159 {
160     union {
161         struct dt_intr_node *parent;
162         dt_phnd_t parent_hnd;
163     };
164
165     struct {
166         bool extended;
167         union {
168             struct dt_prop_val   arr;
169             struct llist_header  values; 
170         };
171     } intr;
172
173     struct dt_prop_val       intr_map;
174     struct dt_prop_val       intr_map_mask;
175 };
176 #define DT_NODE(intr_node) \
177         (container_of(intr_node, struct dt_node, intr))
178
179
180 struct dt_node
181 {
182     struct dt_node_base base;
183     struct dt_intr_node intr;
184     
185     struct dt_prop_val  reg;
186     struct dt_prop_val  vreg;
187
188     struct dt_prop_val  ranges;
189     struct dt_prop_val  dma_ranges;
190 };
191
192
193 struct dt_intr_prop
194 {
195     struct dt_intr_node *master;
196
197     struct llist_header  props;
198     struct dt_prop_val   val;
199 };
200
201 struct dt_prop_iter
202 {
203     struct dt_prop_val     *prop;
204     struct dt_node_base    *node;
205     dt_enc_t                prop_loc;
206     dt_enc_t                prop_loc_next;
207     unsigned int            ent_sz;
208 };
209
210 struct dt_context
211 {
212     union {
213         ptr_t reloacted_dtb;
214         struct fdt_header* fdt;
215     };
216
217     struct llist_header   nodes;
218     struct dt_root       *root;
219     struct hbucket        phnds_table[16];
220     const char           *str_block;
221 };
222
223 struct fdt_iter
224 {
225     union {
226         struct fdt_token      *pos;
227         struct fdt_prop       *prop;
228         struct fdt_node_head  *node_head;
229     };
230
231     const char* str_block;
232     int depth;
233 };
234
235 struct fdt_memrsvd_iter
236 {
237     struct fdt_memrsvd_ent *block;
238 };
239
240 struct dt_node_iter
241 {
242     struct dt_node_base* head;
243     struct dt_node_base* matched;
244     const char *name;
245 };
246
247 #define dtnode_child_foreach(node_base, pos, n)  \
248         llist_for_each(pos, n, &(node_base)->children, siblings)
249
250 #define fdt_prop(tok) ((tok)->token == FDT_PROP)
251 #define fdt_node(tok) ((tok)->token == FDT_NOD_BEGIN)
252 #define fdt_node_end(tok) ((tok)->token == FDT_NOD_END)
253 #define fdt_nope(tok) ((tok)->token == FDT_NOP)
254
255 void 
256 fdt_itbegin(struct fdt_iter* fdti, struct fdt_header* fdt_hdr);
257
258 void 
259 fdt_itend(struct fdt_iter* fdti);
260
261 bool 
262 fdt_itnext(struct fdt_iter* fdti);
263
264 bool 
265 fdt_itnext_at(struct fdt_iter* fdti, int level);
266
267 void
268 fdt_memrsvd_itbegin(struct fdt_memrsvd_iter* rsvdi, 
269                     struct fdt_header* fdt_hdr);
270
271 bool
272 fdt_memrsvd_itnext(struct fdt_memrsvd_iter* rsvdi);
273
274 void
275 fdt_memrsvd_itend(struct fdt_memrsvd_iter* rsvdi);
276
277
278 bool
279 dt_load(ptr_t dtb_dropoff);
280
281 struct dt_node*
282 dt_resolve_phandle(dt_phnd_t phandle);
283
284 struct dt_prop_val*
285 dt_getprop(struct dt_node* node, const char* name);
286
287 void
288 dt_begin_find(struct dt_node_iter* iter, 
289               struct dt_node* node, const char* name);
290
291 bool
292 dt_find_next(struct dt_node_iter* iter,
293              struct dt_node_base** matched);
294
295 static inline bool
296 dt_found_any(struct dt_node_iter* iter)
297 {
298     return !!iter->matched;
299 }
300
301
302 static inline char*
303 fdtit_prop_key(struct fdt_iter* fdti)
304 {
305     return &fdti->str_block[fdti->prop->nameoff];
306 }
307
308 static inline void
309 dt_decode(struct dt_prop_iter* dtpi, struct dt_node_base* node, 
310                 struct dt_prop_val* val, unsigned int ent_sz)
311 {
312     *dtpi = (struct dt_prop_iter) {
313         .prop = val,
314         .node = node,
315         .prop_loc = val->encoded,
316         .prop_loc_next = val->encoded,
317         .ent_sz = ent_sz
318     };
319 }
320
321 #define dt_decode_reg(dtpi, node, field) \
322             dt_decode(dtpi, &(node)->base, (node)->(field), \
323                             (node)->base.sz_c + (node)->base.addr_c);
324
325 #define dt_decode_range(dtpi, node, field) \
326             dt_decode(dtpi, &(node)->base, (node)->field, \
327                             (node)->base.sz_c * 2 + (node)->base.addr_c);
328
329 static inline void
330 dt_decode_intrmap(struct dt_prop_iter* dtpi, 
331                   struct dt_intr_node* intr_node)
332 {
333     unsigned int size;
334     struct dt_node* node;
335     struct dt_node_base* base;
336     
337     node = DT_NODE(intr_node);
338     base = &node->base;
339     size = (base->addr_c + base->intr_c) * 2 + 1;
340
341     dt_decode(dtpi, base, &intr_node->intr_map, size);
342 }
343
344 #define dtprop_off(dtpi) \
345             (unsigned int)(\
346                 __ptr(dtpi->prop_loc_next) - __ptr(dtpi->prop->encoded) \
347             )
348
349 #define dtprop_extract(dtpi, off) \
350             ( (dt_enc_t) (&(dtpi)->prop_loc[(off)]) )
351
352 static inline bool
353 dtprop_next_n(struct dt_prop_iter* dtpi, int n)
354 {
355     unsigned int off;
356
357     dtpi->prop_loc = dtpi->prop_loc_next;
358     dtpi->prop_loc_next += n;
359
360     off = dtprop_off(dtpi);
361     return off >= dtpi->prop->size;
362 }
363
364 static inline bool
365 dtprop_prev_n(struct dt_prop_iter* dtpi, int n)
366 {
367     unsigned int off;
368
369     off = dtprop_off(dtpi);
370     if (!off || off > dtpi->prop->size) {
371         return false;
372     }
373
374     dtpi->prop_loc = dtpi->prop_loc_next;
375     dtpi->prop_loc_next -= n;
376
377     return true;
378 }
379
380 static inline bool
381 dtprop_next(struct dt_prop_iter* dtpi)
382 {
383     return dtprop_next_n(dtpi, dtpi->ent_sz);
384 }
385
386 static inline bool
387 dtprop_prev(struct dt_prop_iter* dtpi)
388 {
389     return dtprop_prev_n(dtpi, dtpi->ent_sz);
390 }
391
392 static inline unsigned int
393 dtprop_to_u32(dt_enc_t enc_val)
394 {
395     return le(*enc_val);
396 }
397
398 #define dtprop_to_phnd(enc_val) \
399             (dt_phnd_t)dtprop_to_u32(enc_val)
400
401 static inline u64_t
402 dtprop_to_u64(dt_enc_t enc_val)
403 {
404     return le64(*(u64_t*)enc_val);
405 }
406
407 static inline dt_enc_t
408 dtprop_reg_addr(struct dt_prop_iter* dtpi)
409 {
410     return dtprop_extract(dtpi, 0);
411 }
412
413 static inline dt_enc_t
414 dtprop_reg_len(struct dt_prop_iter* dtpi)
415 {
416     return dtprop_extract(dtpi, dtpi->node->addr_c);
417 }
418
419 static inline dt_enc_t
420 dtprop_range_childbus(struct dt_prop_iter* dtpi)
421 {
422     return dtprop_extract(dtpi, 0);
423 }
424
425 static inline dt_enc_t
426 dtprop_range_parentbus(struct dt_prop_iter* dtpi)
427 {
428     return dtprop_extract(dtpi, dtpi->node->addr_c);
429 }
430
431 static inline dt_enc_t
432 dtprop_range_len(struct dt_prop_iter* dtpi)
433 {
434     return dtprop_extract(dtpi, dtpi->node->addr_c * 2);
435 }
436
437 static inline dt_enc_t
438 dtprop_intr_cuaddr(struct dt_prop_iter* dtpi)
439 {
440     return dtprop_extract(dtpi, 0);
441 }
442
443 static inline dt_enc_t
444 dtprop_intr_cispec(struct dt_prop_iter* dtpi)
445 {
446     return dtprop_extract(dtpi, dtpi->node->addr_c);
447 }
448
449 static inline struct dt_intr_node*
450 dtprop_intr_parent(struct dt_prop_iter* dtpi)
451 {
452     unsigned off;
453     struct dt_node* node;
454     dt_enc_t enc_val;
455
456     off = dtpi->node->addr_c + dtpi->node->intr_c;
457     enc_val = dtprop_extract(dtpi, off);
458     node = dt_resolve_phandle(dtprop_to_phnd(enc_val));
459     
460     return &node->intr;
461 }
462
463 static inline dt_enc_t
464 dtprop_intr_puaddr(struct dt_prop_iter* dtpi)
465 {
466     unsigned off;
467
468     off = dtpi->node->addr_c + dtpi->node->intr_c + 1;
469     return dtprop_extract(dtpi, off);
470 }
471
472 static inline dt_enc_t
473 dtprop_intr_pispec(struct dt_prop_iter* dtpi)
474 {
475     unsigned off;
476
477     off = dtpi->node->addr_c * 2 + dtpi->node->intr_c + 1;
478     return dtprop_extract(dtpi, off);
479 }
480
481 #endif /* __LUNAIX_DEVTREE_H */