1 #include <lunaix/mm/valloc.h>
2 #include <lunaix/syslog.h>
4 #include "gic-common.h"
8 // FUTURE for now we assume uniprocessor
9 const int current_cpu = 0;
12 gic_create_pe_context(struct gic* gic, void* pe_impl)
16 pe = vzalloc(sizeof(*pe));
25 gic_local_context_of(struct gic_int_class* int_class)
27 switch (int_class->kind)
30 return container_of(int_class, struct gic_pe, ppi);
33 return container_of(int_class, struct gic_pe, ppi_e);
36 return container_of(int_class, struct gic_pe, sgi);
39 return container_of(int_class, struct gic_pe, lpi);
47 gic_global_context_of(struct gic_int_class* int_class)
51 switch (int_class->kind)
54 return container_of(int_class, struct gic, spi);
57 return container_of(int_class, struct gic, spi_e);
63 pe = gic_local_context_of(int_class);
65 return pe ? pe->distr : NULL;
69 gic_resolve_pe(struct gic* gic, struct gic_interrupt* intr_out)
74 if (!(intr_out->affinity.raw_val & GIC_INTR_RAW_AFF)) {
78 affval = (u32_t)(intr_out->affinity.raw_val >> 1);
79 for (int i = 0; i < gic->nr_cpus; i++, pe = NULL)
82 if (pe && pe->affinity == affval) {
90 intr_out->affinity.pe = pe;
96 __intclass_inrange(struct gic_int_class* int_class, intid_t id)
99 && (int_class->range.start <= id && id <= int_class->range.stop);
102 static inline enum gic_intkind
103 __get_intid_kind(struct gic* gic, intid_t id)
107 pe = gic->cores[current_cpu];
108 if (__intclass_inrang(&gic->spi, id)) {
112 if (__intclass_inrang(&gic->spi_e, id)) {
113 return GIC_INT_SPI_EXT;
116 if (__intclass_inrang(&pe->sgi, id)) {
120 if (__intclass_inrang(&pe->ppi, id)) {
124 if (__intclass_inrang(&pe->ppi_e, id)) {
125 return GIC_INT_PPI_EXT;
128 if (__intclass_inrang(&pe->lpi, id)) {
132 return GIC_INT_COUNT;
136 gic_get_interrupt(struct gic* gic, intid_t id, struct gic_interrupt* intr_out)
139 enum gic_intkind kind;
140 struct gic_int_class* class;
141 struct gic_pe* current_pe;
143 current_pe = gic->cores[current_cpu];
144 kind = __get_intid_kind(gic, id);
150 if (kind == GIC_INT_SPI || kind == GIC_INT_SPI_EXT) {
151 class = &gic->classes[kind - GIC_INT_SPI];
153 else if (kind < GIC_INT_SPI) {
154 class = ¤t_pe->classes[kind];
160 if (!gic_valid_int_class(class)) {
164 intr_out->intid = id;
165 intr_out->kind = kind;
167 err = class->ops->retrieve(class, intr_out, id);
171 err = gic_resolve_pe(gic, intr_out);
175 // TODO get irq object
181 __gic_create_profile(struct gic_interrupt* gint,
182 enum gic_intkind kind, irq_t irq)
185 gint->trig = irq->trig == IRQ_EDGE ? GIC_TRIG_EDGE : GIC_TRIG_LEVEL;
186 gint->grp = GIC_INT_GROUP1_NS;
187 gint->priority = 255;
188 gint->intid = irq->vector;
193 __gic_install_irq(struct irq_domain *domain, irq_t irq)
198 struct gic_interrupt gint;
199 struct gic_int_class* class;
201 gic = irq_domain_obj(domain, struct gic);
202 pe = gic->cores[current_cpu];
207 WARN("core-local interrupt not supported");
222 err = gic_assign_intid(class, irq);
226 __gic_create_profile(&gint, class->kind, irq);
228 err = class->ops->install(class, &gint);
232 return class->ops->set_enabled(class, gint.intid, true);
235 static const struct irq_domain_ops gic_domain_ops = {
236 .install_irq = __gic_install_irq
240 gic_create_context(struct device* gicdev)
243 struct irq_domain* domain;
245 gic = valloc(sizeof(*gic));
246 domain = irq_create_domain(gicdev, &gic_domain_ops);
248 irq_set_default_domain(domain);
249 irq_set_domain_object(gic, domain);
250 gic->domain = domain;
256 gic_handle_irq(struct hart_state* hs)
261 struct irq_domain* domain;
264 domain = irq_get_default_domain();
265 gic = irq_domain_obj(domain, struct gic);
267 pe = gic->cores[current_cpu];
268 if (!pe->ops->ack_int(pe)) {
272 err = gic_get_interrupt(gic, pe->active_id, &pe->active_int);
277 irq = pe->active_int.irq;
282 pe->has_active_int = false;
283 return pe->ops->notify_eoi(pe);