42 lines
1.4 KiB
C++
42 lines
1.4 KiB
C++
#include <gic.h>
|
|
#include <dbg.h>
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|