make irq specifier to be provided when assigining irq
[lunaix-os.git] / lunaix-os / hal / devtree / dt_interrupt.c
1 #include "devtree.h"
2
3 #include <lunaix/mm/valloc.h>
4 #include <klibc/string.h>
5
6 static int 
7 __ispec_sz(struct dtn* node)
8 {
9     return node->base.intr_c + node->base.addr_c;
10 }
11
12 static struct dtp_val*
13 __ispec_mask(struct dtn* node)
14 {
15     return dt_getprop(&node->base, "interrupt-map-mask");
16 }
17
18 void
19 dt_resolve_interrupt_map(struct dtn* node)
20 {
21     struct dtp_val* map;
22     struct dtspec_create_ops ops = {};
23     
24     ops.child_keysz = __ispec_sz;
25     ops.parent_keysz = __ispec_sz;
26     ops.get_mask = __ispec_mask;
27     
28     map = dt_getprop(&node->base, "interrupt-map");
29     if (likely(!map)) {
30         return;
31     }
32
33     node->intr.map = dtspec_create(node, map, &ops);
34 }
35
36 struct dtn* 
37 dt_interrupt_at(struct dtn* node, int idx, struct dtp_val* int_spec)
38 {
39     int int_cells;
40     dt_enc_t raw_specs;
41     struct dtn_intr* intr;
42     struct dtn* intr_domain;
43
44     intr = &node->intr;
45     if (!intr->valid || idx >= intr->nr_intrs) {
46         return NULL;
47     }
48     
49     if (!intr->extended) {
50         intr_domain = intr->parent;
51         int_cells = intr_domain->base.intr_c;
52         
53         raw_specs = &intr->raw_ispecs.encoded[int_cells * idx];
54         dtp_val_set(int_spec, raw_specs, int_cells);
55
56         return intr_domain;
57     }
58
59     struct dtspec_intr *p, *n;
60     llist_for_each(p, n, &intr->ext_ispecs, ispecs)
61     {
62         if (!(idx--)) {
63             *int_spec = p->val;
64             return p->domain;
65         }
66     }
67
68     return NULL;
69 }
70
71 bool
72 parse_stdintr_prop(struct fdt_blob* fdt, fdt_loc_t loc, struct dtn_intr* node)
73 {
74     if (propeq(fdt, loc, "interrupt-parent")) {
75         node->parent_hnd = __prop_getu32(loc);
76     }
77
78     else if (propeq(fdt, loc, "interrupts-extended")) {
79         node->extended = true;
80         __mkprop_ptr(loc, &node->raw_ispecs);
81     }
82
83     else if (!node->extended && propeq(fdt, loc, "interrupts")) {
84         __mkprop_ptr(loc, &node->raw_ispecs);
85     }
86
87     else {
88         return false;
89     }
90
91     node->valid = true;
92     return true;
93 }