#ifndef __LUNAIX_GIC_COMMON_H #define __LUNAIX_GIC_COMMON_H #include #include #include #define PAD(body, name, offset) \ struct { char _pad_##name[offset]; body; } compact #define PAD_STRUCT(body, name, offset) \ PAD(struct body, name, offset) #define FIELD_AT(type, field, offset) \ PAD(volatile type field, field, offset) #define ARRAY_AT(type, arr, offset, end) \ PAD(volatile type arr[((end) - (offset)) / sizeof(type) + 1], arr, offset) typedef unsigned int intid_t; struct gic_pe; struct gic_int_class; enum gic_intkind { GIC_INT_SGI = 0, GIC_INT_PPI, GIC_INT_PPI_EXT, GIC_INT_LPI, GIC_INT_SPI, GIC_INT_SPI_EXT, GIC_INT_COUNT }; enum gic_intgrp { GIC_INT_GROUP0, GIC_INT_GROUP1_S, GIC_INT_GROUP1_NS, }; enum gic_trigger { GIC_TRIG_LEVEL, GIC_TRIG_EDGE, }; struct gic_interrupt { intid_t intid; enum gic_intgrp grp; enum gic_intkind kind; enum gic_trigger trig; int priority; bool nmi; bool enabled; union { u64_t raw_val; struct gic_pe* pe; } affinity; struct irq_object* irq; }; #define GIC_INTR_RAW_AFF 1 struct gic_int_class_ops { int (*set_enabled)(struct gic_int_class*, intid_t, bool); int (*set_prority)(struct gic_int_class*, intid_t, int); int (*set_nmi)(struct gic_int_class*, intid_t, bool); int (*set_route)(struct gic_int_class*,intid_t, struct gic_pe*); int (*set_trigger)(struct gic_int_class*,intid_t, enum gic_trigger); int (*retrieve)(struct gic_int_class*, struct gic_interrupt*, intid_t); int (*install)(struct gic_int_class*, struct gic_interrupt*); int (*delete)(struct gic_int_class*, intid_t); int (*fire)(struct gic_int_class*, intid_t); }; extern const struct gic_int_class_ops aa64_gic_fallback_ops; struct gic; struct gic_pe; struct gic_int_class { enum gic_intkind kind; struct { intid_t start; intid_t stop; } range; struct gic_int_class_ops* ops; }; struct gic_pe_ops { bool (*ack_int)(struct gic_pe*); int (*notify_eoi)(struct gic_pe*); int (*set_priority_mask)(struct gic_pe*, int); }; struct gic_pe { union { struct { struct gic_int_class sgi; struct gic_int_class ppi; struct gic_int_class ppi_e; struct gic_int_class lpi; }; struct gic_int_class classes[4]; }; struct { union { intid_t active_id; struct gic_interrupt active_int; }; bool has_active_int; }; void* impl; int index; int affinity; struct gic* distr; struct gic_pe_ops* ops; }; struct gic { int nr_cpus; struct gic_pe** cores; union { struct { struct gic_int_class spi; struct gic_int_class spi_e; }; struct gic_int_class classes[2]; }; void* impl; struct irq_domain* domain; }; static inline void gic_init_int_class(struct gic_int_class* class, enum gic_intkind kind, intid_t start, intid_t end) { *class = (struct gic_int_class) { .range.start = start, .range.stop = end, .kind = kind }; } static inline bool gic_valid_int_class(struct gic_int_class* class) { return class->ops && (class->range.start < class->range.stop); } static inline void gic_intr_set_raw_affval(struct gic_interrupt* intr, u32_t affval) { intr->affinity.raw_val = ((u64_t)affval << 1) | GIC_INTR_RAW_AFF; } static inline int gic_assign_intid(struct gic_int_class* class, irq_t irq) { int err; struct gic* gic; if (!gic_valid_int_class(class)) { // selected class not present or disabled return ENOENT; } gic = gic_global_context_of(class); err = irq_alloc_id(gic->domain, irq, class->range.start, class->range.stop); return err; } struct gic_pe* gic_create_pe_context(struct gic* gic, void* pe_impl); struct gic_pe* gic_local_context_of(struct gic_int_class* int_class); struct gic* gic_global_context_of(struct gic_int_class* int_class); int gic_get_interrupt(struct gic* gic, intid_t id, struct gic_interrupt* intr_out); struct gic* gic_create_context(struct device* gicdev); // default ops int __fallback_set_enabled(struct gic_int_class* class, intid_t intid, bool en); int __fallback_set_prority(struct gic_int_class* class, intid_t intid, int prio); int __fallback_set_nmi(struct gic_int_class* class, intid_t intid, bool nmi); int __fallback_set_route(struct gic_int_class* class, intid_t intid, struct gic_pe* target); int __fallback_set_trigger(struct gic_int_class* class, intid_t intid, enum gic_trigger trig); int __fallback_retrieve(struct gic_int_class* class, struct gic_interrupt*, intid_t intid); int __fallback_install(struct gic_int_class* class, struct gic_interrupt* gic); int __fallback_delete(struct gic_int_class* class, intid_t intid); #endif /* __LUNAIX_GIC_COMMON_H */