* gic.c
* - GIC Core
*/
+#define DEBUG 1
+
#include <acess.h>
#include <modules.h>
+#include "gic.h"
+
+// === IMPORTS ===
+extern void *gpIRQHandler;
// === PROTOTYPES ===
int GIC_Install(char **Arguments);
+void GIC_IRQHandler(void);
// === GLOBALS ===
MODULE_DEFINE(0, 0x100, armv7_GIC, GIC_Install, NULL, NULL);
+Uint32 *gpGIC_DistributorBase;
+Uint32 *gpGIC_InterfaceBase;
+tPAddr gGIC_DistributorAddr;
+tPAddr gGIC_InterfaceAddr;
// === CODE ===
int GIC_Install(char **Arguments)
{
+ // Realview PB
+ gGIC_InterfaceAddr = 0x1e000000;
+ gGIC_DistributorAddr = 0x1e001000;
+
+ // Initialise
+ gpGIC_InterfaceBase = (void*)MM_MapHWPages(gGIC_InterfaceAddr, 1);
+ gpGIC_DistributorBase = (void*)MM_MapHWPages(gGIC_DistributorAddr, 1);
+
+ gpGIC_InterfaceBase[GICC_PMR] = 0xFF;
+ gpGIC_InterfaceBase[GICC_CTLR] = 1; // Enable CPU
+ gpGIC_DistributorBase[GICD_CTLR] = 1; // Enable Distributor
+
+ gpIRQHandler = GIC_IRQHandler;
+
+ __asm__ __volatile__ ("cpsie if"); // Enable IRQs and FIQs
+
return MODULE_ERR_OK;
}
+void GIC_IRQHandler(void)
+{
+ Uint32 num = gpGIC_InterfaceBase[GICC_IAR];
+ Log_Debug("GIC", "IRQ 0x%x", num);
+ gpGIC_InterfaceBase[GICC_EOIR] = 1;
+}
+
int IRQ_AddHandler(int IRQ, void (*Handler)(int, void*), void *Ptr)
{
+ LOG("IRQ = %i", IRQ);
+ IRQ += 32; // 32 internal IRQs
+ LOG("IRQ = %i (after adjust)", IRQ);
+ LOG("mask = 0x%x", 1 << (IRQ & (31-1)));
+ gpGIC_DistributorBase[GICD_ISENABLER0+IRQ/32] = 1 << (IRQ & (32-1));
+ ((Uint8*)&gpGIC_DistributorBase[GICD_ITARGETSR0])[IRQ] = 1;
Log_Warning("GIC", "TODO: Implement IRQ_AddHandler");
return 0;
}
--- /dev/null
+/*
+ * ARMv7 GIC Support
+ * - By John Hodge (thePowersGang)
+ *
+ * gic.h
+ * - GIC Core Definitions
+ */
+#ifndef _ARM7_GIC_H_
+#define _ARM7_GIC_H_
+
+enum eGICD_Registers
+{
+ GICD_CTLR = 0x000/4, // Distributor Control Register
+ GICD_TYPER = 0x004/4, // Interrupt Controller Type
+ GICD_IIDR = 0x008/4, // Distributor Implementer Identifcation
+
+ GICD_IGROUPR0 = 0x080/4, // Interrupt Group Register (#0)
+ GICD_ISENABLER0 = 0x100/4, // Interrupt Set-Enable Register #0 (128*8=1024)
+ GICD_ICENABLER0 = 0x180/4, // Interrupt Clear-Enable Register #0
+ GICD_ISPENDR0 = 0x200/4, // Interrupt Set-Pending Register #0
+ GICD_ICPENDR0 = 0x280/4, // Interrupt Clear-Pending Register #0
+ GICD_ISACTIVER0 = 0x300/4, // Interrupt Set-Active Register (GICv2)
+ GICD_ICACTIVER0 = 0x380/4, // Interrupt Clear-Active Register (GICv2)
+
+ GICD_IPRIORITYR0 = 0x400/4, // Interrupt priority registers (254*4 = )
+
+ GICD_ITARGETSR0 = 0x800/4, // Interrupt Processor Targets Register (8*4)
+
+ GICD_ICFGR0 = 0xC00/4, // Interrupt Configuration Register (64*4)
+ GICD_NSACR0 = 0xE00/4, // Non-secure Access Control Register (64*4)
+ GICD_SIGR = 0xF00/4, // Software Generated Interrupt Register (Write Only)
+ GICD_CPENDSGIR0 = 0xF10/4, // SGI Clear-Pending Registers (4*4)
+ GICD_SPENDSGIR0 = 0xF20/4, // SGI Set-Pending Registers (4*4)
+};
+
+enum eGICC_Registers
+{
+ GICC_CTLR = 0x000/4, // CPU Interface Control Register
+ GICC_PMR = 0x004/4, // Interrupt Priority Mask Register
+ GICC_BPR = 0x008/4, // Binary Point Register
+ GICC_IAR = 0x00C/4, // Interrupt Acknowledge Register
+ GICC_EOIR = 0x010/4, // End of Interrupt Register
+ GICC_RPR = 0x014/4, // Running Priority Register
+ GICC_HPPIR = 0x018/4, // Highest Priority Pending Interrupt Register
+ GICC_ABPR = 0x01C/4, // Aliased Binary Point Register
+ GICC_AIAR = 0x020/4, // Aliased Interrupt Acknowledge Register,
+ GICC_AEOIR = 0x024/4, // Aliased End of Interrupt Register
+ GICC_AHPPIR = 0x028/4, // Aliased Highest Priority Pending Interrupt Register
+
+ GICC_APR0 = 0x0D0/4, // Active Priorities Registers (4*4)
+ GICC_NSAPR0 = 0x0E0/4, // Non-secure Active Priorities Registers (4*4)
+
+ GICC_IIDR = 0x0FC/4, // CPU Interface Identifcation Register
+ GICC_DIR = 0x0FC/4, // Deactivate Interrupt Register (Write Only)
+};
+
+#endif