#include #include namespace GIC { /* This code (correctly) assumes that initial registers' values are 0x0, * thus does not work (read: correctly overwrite) with subsequent changes, * but since GIC is prepared at system startup and then never touched again, * this should not be a problem */ void enableInterrupt(const uint16_t m, const TargetCPU target, const Sensitivity sensitivity) { /* register offset (used in an uint32_t array, so no need to multiply by 4) */ uint16_t n; /* Enable interrupt m */ n = m / 32; distributor[GICD_ISENABLER + n] = distributor[GICD_ISENABLER + n] | (1 << (m % 32)); /* Set target CPU */ n = m / 4; distributor[GICD_ITARGETSR + n] = distributor[GICD_ITARGETSR + n] | (target << ((m % 4) * 8)); /* Edge or level triggered? */ n = m / 16; distributor[GICD_ICFGR + n] = distributor[GICD_ICFGR + n] | (sensitivity << (2 * (m % 16) + 1)); /* Enable all priorities */ cpuInterface[1] = 0xff; } void enable(void) { /* Enable distributor and CPU interfaces * Call this function always at the end, * since writing on GIC registers is not allowed when it is enabled */ distributor[0] = distributor[GICD_CTLR] | 0x1; cpuInterface[0] = cpuInterface[GICC_CTLR] | 0x1; } }