// === GLOBALS ===
MODULE_DEFINE(0, 0x100, armv7_GIC, GIC_Install, NULL, NULL);
-Uint32 *gpGIC_DistributorBase;
-Uint32 *gpGIC_InterfaceBase;
+volatile Uint32 *gpGIC_DistributorBase;
+volatile Uint32 *gpGIC_InterfaceBase;
tIRQ_Handler gaIRQ_Handlers[N_IRQS];
void *gaIRQ_HandlerData[N_IRQS];
int GIC_Install(char **Arguments)
{
// Initialise
- gpGIC_InterfaceBase = (void*)MM_MapHWPages(gGIC_InterfaceAddr, 1);
- LOG("gpGIC_InterfaceBase = %p", gpGIC_InterfaceBase);
+ Log_Debug("GIC", "Dist: %P, Interface: %P",
+ gGIC_DistributorAddr, gGIC_InterfaceAddr);
+ gpGIC_InterfaceBase = (Uint32*)MM_MapHWPages(gGIC_InterfaceAddr, 1)
+ + (gGIC_InterfaceAddr & (PAGE_SIZE-1))/4;
gpGIC_DistributorBase = (void*)MM_MapHWPages(gGIC_DistributorAddr, 1);
- LOG("gpGIC_DistributorBase = %p", gpGIC_DistributorBase);
- gpGIC_InterfaceBase[GICC_PMR] = 0xFF;
+ gpGIC_InterfaceBase[GICC_CTLR] = 0; // Disable CPU interaface
+ gpGIC_InterfaceBase[GICC_PMR] = 0xFF; // Effectively disable prioritories
gpGIC_InterfaceBase[GICC_CTLR] = 1; // Enable CPU
gpGIC_DistributorBase[GICD_CTLR] = 1; // Enable Distributor
__asm__ __volatile__ ("cpsie if"); // Enable IRQs and FIQs
+#if 0
+ for( int i = 0; i < N_IRQS/32; i ++ ) {
+ Log_Debug("GIC", "GICD_ISENABLER%i %x = %08x",
+ i, GICD_ISENABLER0 + i,
+ gpGIC_DistributorBase[GICD_ISENABLER0+i]);
+ gpGIC_DistributorBase[GICD_ISENABLER0+i] = 0;
+ }
+#endif
+
+ #if 0
+ // Testing - First 32 actual interrupts enabled
+ gpGIC_DistributorBase[GICD_ISENABLER0+1] = 0xFFFFFFFF;
+ for( int i = 0; i < 32/4; i ++ )
+ gpGIC_DistributorBase[GICD_ITARGETSR0+8+i] = 0x01010101;
+ #endif
+
+ // Clear out pending IRQs.
+ gpGIC_InterfaceBase[GICC_EOIR] = gpGIC_InterfaceBase[GICC_IAR];
+
return MODULE_ERR_OK;
}
void GIC_IRQHandler(void)
{
Uint32 num = gpGIC_InterfaceBase[GICC_IAR];
-// Log_Debug("GIC", "IRQ 0x%x", num);
- gaIRQ_Handlers[num]( num, gaIRQ_HandlerData[num] );
+ if( gaIRQ_Handlers[num] ) {
+ gaIRQ_Handlers[num]( num, gaIRQ_HandlerData[num] );
+ }
+ else {
+ Log_Debug("GIC", "IRQ 0x%x unhandled", num);
+ }
gpGIC_InterfaceBase[GICC_EOIR] = num;
}
return 1;
}
- LOG("IRQ = %i", IRQ);
IRQ += 32; // 32 internal IRQs
- LOG("IRQ = %i (after adjust)", IRQ);
- LOG("mask = 0x%x", 1 << (IRQ & (31-1)));
+ // - Enable IRQ, clear pending and send to CPU 1 only
gpGIC_DistributorBase[GICD_ISENABLER0+IRQ/32] = 1 << (IRQ & (32-1));
((Uint8*)&gpGIC_DistributorBase[GICD_ITARGETSR0])[IRQ] = 1;
+ gpGIC_DistributorBase[GICD_ICPENDR0+IRQ/32] = 1 << (IRQ & (32-1));
+ gpGIC_DistributorBase[GICD_ICFGR0+IRQ/16] |= 2 << ((IRQ & 15)*2);
-// Log_Warning("GIC", "TODO: Implement IRQ_AddHandler");
-
- if( gaIRQ_Handlers[IRQ] )
+ // TODO: Does the GIC need to handle IRQ sharing?
+ if( gaIRQ_Handlers[IRQ] ) {
+ Log_Warning("GIC", "IRQ %i already handled by %p, %p ignored",
+ IRQ, gaIRQ_Handlers[IRQ], Handler);
return 2;
+ }
gaIRQ_Handlers[IRQ] = Handler;
gaIRQ_HandlerData[IRQ] = Ptr;
+ Log_Debug("GIC", "IRQ %i handled by %p(%p)", IRQ, Handler, Ptr);
return 0;
}