1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12
13#include <assert.h>
14#include <camkes.h>
15#include <sel4/sel4.h>
16#include <stdbool.h>
17#include <stddef.h>
18#include <utils/util.h>
19#include <platsupport/irq.h>
20#include <camkes/irq.h>
21
22/*? macros.show_includes(me.instance.type.includes) ?*/
23/*- set ntfn_obj = alloc_obj('ntfn', seL4_NotificationObject) -*/
24/*- set ntfn = alloc_cap('ntfn', ntfn_obj, read=True) -*/
25
26/*- set type_attr = '%s_irq_type' % me.parent.from_interface.name -*/
27/*- set type = configuration[me.parent.from_instance.name].get(type_attr, 'simple') -*/
28
29/*- if type == 'simple' -*/
30    /*- set attr = '%s_irq_number' % me.parent.from_interface.name -*/
31    /*- set _irq = configuration[me.parent.from_instance.name].get(attr) -*/
32    /*- if _irq is none -*/
33        /*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not defined' % (me.parent.from_instance.name, attr))) ?*/
34    /*- endif -*/
35    /*- if not isinstance(_irq, numbers.Integral) -*/
36        /*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not an integer' % (me.parent.from_instance.name, attr))) ?*/
37    /*- endif -*/
38    /*- set spi_attr = '%s_spi_number' % me.parent.from_interface.name -*/
39    /*- set _irq_spi = configuration[me.parent.from_instance.name].get(spi_attr) -*/
40    /*- if (isinstance(_irq_spi, numbers.Integral)) and (_irq_spi == 0) -*/
41        /*- set _irq = _irq + 32 -*/
42    /*- endif -*/
43    /*- set irq = alloc('irq', seL4_IRQHandler, number=_irq, notification=my_cnode[ntfn]) -*/
44/*- elif type in ['arm'] -*/
45    /*- set attr = '%s_irq_trigger' % me.parent.from_interface.name -*/
46    /*- set trigger = configuration[me.parent.from_instance.name].get(attr, "level") -*/
47    /*- if trigger == "level" -*/
48        /*- set trigger = seL4_ARM_IRQ_LEVEL -*/
49        /*- set sel4_trigger_param = 0 -*/
50    /*- elif trigger == "edge" -*/
51        /*- set trigger = seL4_ARM_IRQ_EDGE -*/
52        /*- set sel4_trigger_param = 1 -*/
53    /*- else -*/
54        /*? raise(TemplateError('Setting %s.%s that should specify an IRQ trigger mode can only be "edge" or "level" but is set to: %s' % (me.parent.from_instance.name, attr, trigger))) ?*/
55    /*- endif -*/
56    /*- set attr = '%s_irq_number' % me.parent.from_interface.name -*/
57    /*- set _irq = configuration[me.parent.from_instance.name].get(attr) -*/
58    /*- if _irq is none -*/
59        /*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not defined' % (me.parent.from_instance.name, attr))) ?*/
60    /*- endif -*/
61    /*- if not isinstance(_irq, numbers.Integral) -*/
62        /*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not an integer' % (me.parent.from_instance.name, attr))) ?*/
63    /*- endif -*/
64    /*- set attr = '%s_irq_target' % me.parent.from_interface.name -*/
65    /*- set target = configuration[me.parent.from_instance.name].get(attr, 0) -*/
66    /*- if not isinstance(target, numbers.Integral) -*/
67        /*? raise(TemplateError('Setting %s.%s that should specify a target core is not an integer' % (me.parent.from_instance.name, attr))) ?*/
68    /*- endif -*/
69    /*- set irq = alloc('irq', seL4_IRQHandler, number=_irq, trigger=trigger, target=target, notification=my_cnode[ntfn]) -*/
70/*- elif type in ['ioapic','isa','pci'] -*/
71    /*- if type == 'isa' -*/
72        /*- set level = 0 -*/
73        /*- set polarity = 0 -*/
74    /*- elif type == 'pci' -*/
75        /*- set level = 1 -*/
76        /*- set polarity = 1 -*/
77    /*- else -*/
78        /*- set attr = '%s_irq_level' % me.parent.from_interface.name -*/
79        /*- set level = configuration[me.parent.from_instance.name].get(attr) -*/
80        /*- if level is none -*/
81            /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt level is not defined' % (me.parent.from_instance.name, attr))) ?*/
82        /*- endif -*/
83        /*- if not isinstance(level, numbers.Integral) -*/
84            /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt level is not an integer' % (me.parent.from_instance.name, attr))) ?*/
85        /*- endif -*/
86        /*- set attr = '%s_irq_polarity' % me.parent.from_interface.name -*/
87        /*- set polarity = configuration[me.parent.from_instance.name].get(attr) -*/
88        /*- if polarity is none -*/
89            /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt polarity is not defined' % (me.parent.from_instance.name, attr))) ?*/
90        /*- endif -*/
91        /*- if not isinstance(polarity, numbers.Integral) -*/
92            /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt polarity is not an integer' % (me.parent.from_instance.name, attr))) ?*/
93        /*- endif -*/
94    /*- endif -*/
95    /*- set attr = '%s_irq_ioapic' % me.parent.from_interface.name -*/
96    /*- set ioapic = configuration[me.parent.from_instance.name].get(attr) -*/
97    /*- if ioapic is none -*/
98        /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC controller number is not defined' % (me.parent.from_instance.name, attr))) ?*/
99    /*- endif -*/
100    /*- if not isinstance(ioapic, numbers.Integral) -*/
101        /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC controller number is not an integer' % (me.parent.from_instance.name, attr))) ?*/
102    /*- endif -*/
103    /*- set attr = '%s_irq_ioapic_pin' % me.parent.from_interface.name -*/
104    /*- set ioapic_pin = configuration[me.parent.from_instance.name].get(attr) -*/
105    /*- if ioapic_pin is none -*/
106        /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC pin number is not defined' % (me.parent.from_instance.name, attr))) ?*/
107    /*- endif -*/
108    /*- if not isinstance(ioapic_pin, numbers.Integral) -*/
109        /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC pin number is not an integer' % (me.parent.from_instance.name, attr))) ?*/
110    /*- endif -*/
111    /*- set attr = '%s_irq_vector' % me.parent.from_interface.name -*/
112    /*- set vector = configuration[me.parent.from_instance.name].get(attr) -*/
113    /*- if vector is none -*/
114        /*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not defined' % (me.parent.from_instance.name, attr))) ?*/
115    /*- endif -*/
116    /*- if not isinstance(vector, numbers.Integral) -*/
117        /*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not an integer' % (me.parent.from_instance.name, attr))) ?*/
118    /*- endif -*/
119    /*- set irq = alloc('irq', seL4_IRQHandler, vector=vector, ioapic=ioapic, ioapic_pin=ioapic_pin, level=level, polarity=polarity, notification=my_cnode[ntfn]) -*/
120/*- elif type == 'msi' -*/
121    /*- set attr = '%s_irq_handle' % me.parent.from_interface.name -*/
122    /*- set handle = configuration[me.parent.from_instance.name].get(attr) -*/
123    /*- if handle is none -*/
124        /*? raise(TemplateError('Setting %s.%s that should specify an MSI handle is not defined' % (me.parent.from_instance.name, attr))) ?*/
125    /*- endif -*/
126    /*- if not isinstance(handle, numbers.Integral) -*/
127        /*? raise(TemplateError('Setting %s.%s that should specify an MSI handle is not an integer' % (me.parent.from_instance.name, attr))) ?*/
128    /*- endif -*/
129    /*- set attr = '%s_irq_pci_bus' % me.parent.from_interface.name -*/
130    /*- set pci_bus = configuration[me.parent.from_instance.name].get(attr) -*/
131    /*- if pci_bus is none -*/
132        /*? raise(TemplateError('Setting %s.%s that should specify a PCI bus is not defined' % (me.parent.from_instance.name, attr))) ?*/
133    /*- endif -*/
134    /*- if not isinstance(pci_bus, numbers.Integral) -*/
135        /*? raise(TemplateError('Setting %s.%s that should specify a PCI bus is not an integer' % (me.parent.from_instance.name, attr))) ?*/
136    /*- endif -*/
137    /*- set attr = '%s_irq_pci_dev' % me.parent.from_interface.name -*/
138    /*- set pci_dev = configuration[me.parent.from_instance.name].get(attr) -*/
139    /*- if pci_dev is none -*/
140        /*? raise(TemplateError('Setting %s.%s that should specify a PCI device is not defined' % (me.parent.from_instance.name, attr))) ?*/
141    /*- endif -*/
142    /*- if not isinstance(pci_dev, numbers.Integral) -*/
143        /*? raise(TemplateError('Setting %s.%s that should specify a PCI device is not an integer' % (me.parent.from_instance.name, attr))) ?*/
144    /*- endif -*/
145    /*- set attr = '%s_irq_pci_fun' % me.parent.from_interface.name -*/
146    /*- set pci_fun = configuration[me.parent.from_instance.name].get(attr) -*/
147    /*- if pci_fun is none -*/
148        /*? raise(TemplateError('Setting %s.%s that should specify a PCI function is not defined' % (me.parent.from_instance.name, attr))) ?*/
149    /*- endif -*/
150    /*- if not isinstance(pci_fun, numbers.Integral) -*/
151        /*? raise(TemplateError('Setting %s.%s that should specify a PCI function is not an integer' % (me.parent.from_instance.name, attr))) ?*/
152    /*- endif -*/
153    /*- set attr = '%s_irq_vector' % me.parent.from_interface.name -*/
154    /*- set vector = configuration[me.parent.from_instance.name].get(attr) -*/
155    /*- if vector is none -*/
156        /*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not defined' % (me.parent.from_instance.name, attr))) ?*/
157    /*- endif -*/
158    /*- if not isinstance(vector, numbers.Integral) -*/
159        /*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not an integer' % (me.parent.from_instance.name, attr))) ?*/
160    /*- endif -*/
161    /*- set irq = alloc('irq', seL4_IRQHandler, vector=vector, handle=handle, pci_bus=pci_bus, pci_dev=pci_dev, pci_fun=pci_fun, notification=my_cnode[ntfn]) -*/
162/*- else -*/
163    /*? raise(TemplateError('Unknown irq type specified by %s.%s' % (me.parent.from_instance.name, type_attr))) ?*/
164/*- endif -*/
165
166/*# Add an entry to the allocated_irqs ELF section #*/
167/*- set irq_struct_name = '%s_irq' % me.interface.name -*/
168static allocated_irq_t /*? irq_struct_name ?*/ = {
169    .irq_handler = /*? irq ?*/,
170/*- if type == 'simple' -*/
171    .irq = { .type = PS_INTERRUPT, .irq = { .number = /*? _irq ?*/ }},
172/*- elif type in ['ioapic','isa','pci'] -*/
173    .irq = { .type = PS_IOAPIC, .ioapic = { .ioapic = /*? ioapic ?*/, .pin = /*? ioapic_pin ?*/,
174                                            .level = /*? level ?*/, .polarity = /*? polarity ?*/,
175                                            .vector = /*? vector ?*/ }},
176/*- elif type == 'msi' -*/
177    .irq = { .type = PS_MSI, .msi = { .pci_bus = /*? pci_bus ?*/, .pci_dev = /*? pci_dev ?*/,
178                                      .pci_func = /*? pci_fun ?*/, .handle = /*? handle ?*/,
179                                      .vector = /*? vector ?*/ }},
180/*- elif type == 'arm' -*/
181    .irq = { .type = PS_TRIGGER, .cpu = { .trigger = /*? trigger.value ?*/, .cpu_idx= /*? target ?*/, .number = /*? _irq ?*/ }},
182/*- endif -*/
183    .is_allocated = false,
184    .callback_fn = NULL,
185    .callback_data = NULL
186};
187USED SECTION("_allocated_irqs")
188allocated_irq_t * /*? irq_struct_name ?*/_ptr = &/*? irq_struct_name ?*/;
189
190int /*? me.interface.name ?*/_poll(void) {
191    assert(!"not implemented for this connector");
192    return 0;
193}
194
195void /*? me.interface.name ?*/_wait(void) {
196    assert(!"not implemented for this connector");
197    while (true);
198}
199
200int /*? me.interface.name ?*/_reg_callback(void (*callback)(void*) UNUSED,
201        void *arg UNUSED) {
202    assert(!"not implemented for this connector");
203    return -1;
204}
205
206int /*? me.interface.name ?*/_acknowledge(void) {
207    return seL4_IRQHandler_Ack(/*? irq ?*/);
208}
209
210static int /*? me.interface.name ?*/_acknowledge_cb(UNUSED void* cookie) {
211    return seL4_IRQHandler_Ack(/*? irq ?*/);
212}
213
214int /*? me.interface.name ?*/__run(void) {
215    while (true) {
216        seL4_Wait(/*? ntfn ?*/, NULL);
217        if (/*? me.interface.name ?*/_handle && /*? irq_struct_name ?*/.is_allocated) {
218            ZF_LOGF("Both IRQ interface and 'handle' function is in use! "
219                    "These are mutually exclusive, use one or the other.");
220        } else if (/*? me.interface.name ?*/_handle) {
221            /*? me.interface.name ?*/_handle();
222        } else if (/*? irq_struct_name ?*/.is_allocated) {
223            /*? irq_struct_name ?*/.callback_fn(/*? irq_struct_name ?*/.callback_data,
224                                                /*? me.interface.name ?*/_acknowledge_cb,
225                                                NULL);
226        } else {
227            ZF_LOGE("No mechanism exists to handle this interrupt, it will be ignored");
228        }
229    }
230
231    UNREACHABLE();
232}
233