VFS_Init();
// Boot modules?
+ // - most ARMv7 configs use a GIC
Module_EnsureLoaded("armv7_GIC");
+
+ Time_Setup();
//
LogF("Moving to arch-independent init\n");
#if PLATFORM_is_tegra2
- System_Init("Acess2.armv7.bin /Acess=initrd: -VTerm:Video=Tegra2Vid -USB_EHCI:C5000000-14,C5004000-15");
+ System_Init("Acess2.armv7.bin /Acess=initrd: -VTerm:Video=Tegra2Vid");
#else
System_Init("Acess2.armv7.bin /Acess=initrd: -VTerm:Video=PL110");
#endif
tPAddr gGIC_InterfaceAddr = 0x50040000;
tPAddr gGIC_DistributorAddr = 0x50041000;
// - Map of timer registers
-struct sTimersMap *gpTimersMap;
+volatile struct sTimersMap *gpTimersMap;
+volatile struct sClockResetMap *gpClockResetMap;
// - Interrupt controller code commented out, because the Tegra2 also has a GIC
#if 0
struct sIRQMap gpIRQMap;
void Timer_IRQHandler_SysClock(int IRQ, void *_unused)
{
giTimestamp += 100;
- gpTimersMap->TMR0.PCR_0 = (1<<31);
+ gpTimersMap->TMR1.PCR_0 = (1<<30);
}
void Time_Setup(void)
{
gpTimersMap = (void*)MM_MapHWPages(0x60005000, 1);
+ gpClockResetMap = (void*)MM_MapHWPages(0x60006000, 1);
// Timer 1 (used for system timekeeping)
IRQ_AddHandler(0*32+0, Timer_IRQHandler_SysClock, NULL);
- gpTimersMap->TMR0.PTV_0 = (1<31)|(1<30)|(100*1000); // enable, periodic, 100 ms
+ gpTimersMap->TMR1.PTV_0 = (1<<31)|(1<<30)|(100*1000-1); // enable, periodic, 100 ms
+ gpTimersMap->TMR1.PCR_0 = (1<<30);
+ Log_Debug("Tegra2Tme", "TMR0.PCR = 0x%x", gpTimersMap->TMR1.PCR_0);
+
+ // Disabled until IRQs work
+ //gpClockResetMap->RST_Source = (1 << 5)|(0<<4)|(7); // Full reset on watchdog timeout
+
+ Log_Debug("Tegra2Tme", "TIMERUS_USEC_CFG = 0x%x", gpTimersMap->TIMERUS.USEC_CFG);
+ Log_Debug("Tegra2Tme", "TIMERUS_CNTR_1US = 0x%x", gpTimersMap->TIMERUS.CNTR_1US);
+ Log_Debug("Tegra2Tme", "TMR0.PCR = 0x%x", gpTimersMap->TMR1.PCR_0);
+ Log_Debug("Tegra2Tme", "TMR0.PTV = 0x%x", gpTimersMap->TMR1.PTV_0);
+ for( int i = 0; i < 5; i ++ ) {
+ for( int j = 0; j < 1000*1000; j ++ )
+ {
+ __asm__ __volatile__ ("mov r0, r0");
+ __asm__ __volatile__ ("mov r0, r0");
+ __asm__ __volatile__ ("mov r0, r0");
+ }
+ Log_Debug("Tegra2Tme", "TMR0.PCR = 0x%x", gpTimersMap->TMR1.PCR_0);
+ }
+ Log_Debug("Tegra2Tme", "TMR0.PCR = 0x%x", gpTimersMap->TMR1.PCR_0);
+ Log_Debug("Tegra2Tme", "GICC_HPPIR = 0x%x", *(Uint32*)(0xF0000000 + 0x18));
+ Log_Debug("Tegra2Tme", "GICC_IAR = 0x%x", *(Uint32*)(0xF0000000 + 0xC));
+ Log_Debug("Tegra2Tme", "GICD_ISPENDR0 = 0x%x", *(Uint32*)(0xF0001000 + 0x200 + 0*4));
+ Log_Debug("Tegra2Tme", "GICD_ISPENDR1 = 0x%x", *(Uint32*)(0xF0001000 + 0x200 + 1*4));
}
#if 0
Uint32 PTV_0; // Control / Target value
Uint32 PCR_0; // Current value / IRQ clear
};
+struct sTimerUSRegs
+{
+ Uint32 CNTR_1US; // 16:16 microsecond counter
+ Uint32 USEC_CFG; // 8:8 num/den (n+1)/(den+1) us per clock
+ Uint32 _padding[0x3c-0x8];
+ Uint32 CNTR_Freeze; // Freeze timers when in debug?
+};
struct sTimersMap
{
- struct sTimerRegs TMR0;
struct sTimerRegs TMR1;
- // TMRUS
- char _padding[ 0x50-0x10 ];
-
struct sTimerRegs TMR2;
+
+ struct sTimerUSRegs TIMERUS;
+
struct sTimerRegs TMR3;
+ struct sTimerRegs TMR4;
+};
+
+struct sClockResetMap
+{
+ Uint32 RST_Source;
+ Uint32 RST_Devices;
+ // ...
};
#if 0
@
mrc p15, 0, r0, c0, c1, 1
and r0, #0xF0
+ beq .no_sec_ext
@ - Present
- ldrne r0,=KERNEL_BASE
- mcrne p15, 0, r0, c12, c0, 0 @ Set the VBAR (brings exceptions into high memory)
+ ldr r0,=KERNEL_BASE
+ mcr p15, 0, r0, c12, c0, 0 @ Set the VBAR (brings exceptions into high memory)
+ b .exceptions_vectored
+.no_sec_ext:
@ - Absent
- mrceq p15, 0, r0, c1, c0, 0 @ Set SCTLR.V
- orreq r0, #0x2000
- mcreq p15, 0, r0, c1, c0, 0
+ mrc p15, 0, r0, c1, c0, 0 @ Set SCTLR.V
+ orr r0, #0x2000
+ mcr p15, 0, r0, c1, c0, 0
+.exceptions_vectored:
mov r1, #'-'
str r1, [r2]
// === GLOBALS ===
tVPCI_Device gaVPCI_Devices[] = {
- // NOTE: USB Controllers moved to command line arguments
#if 0
{
.Vendor=0x0ACE,.Device=0x1100,
- .Class = 0x0C032100, // Serial, USB, ECHI
+ .Class = 0x0C032000, // Serial, USB, ECHI
.BARs = {0xC5000000,0,0,0,0,0},
.IRQ = 0*32+20,
},
struct {
unsigned Group: 1; //!< Group (as opposed to user) flag
unsigned ID: 31; //!< ID of Group/User (-1 for nobody/world)
- };
+ } Ent;
struct {
unsigned Inv: 1; //!< Invert Permissions
unsigned Perms: 31; //!< Permission Flags
- };
+ } Perm;
} tVFS_ACL;
/**
gpTegra2Vid_IOMem = (void*)MM_MapHWPages(gTegra2Vid_PhysBase, 256/4);
#if DUMP_REGISTERS
- Tegra2Vid_int_DumpRegisters();
+// Tegra2Vid_int_DumpRegisters();
#endif
// HACK!!!
#endif
gpTegra2Vid_Cursor = (void*)MM_AllocDMA(1, 26, NULL);
+ Log_Debug("Tegra2Vid", "gpTegra2Vid_Cursor = %p", gpTegra2Vid_Cursor);
Tegra2Vid_int_SetMode(0);
{
Uint32 addr = PCI_GetBAR(id, 0);
if( addr == 0 ) {
- // Oops, PCI BIOS emulation time
+ // TODO: PCI BIOS emulation time
}
+ if( addr & 1 ) {
+ // TODO: Error
+ continue ;
+ }
+ addr &= ~0xF;
Uint8 irq = PCI_GetIRQ(id);
if( irq == 0 ) {
- // TODO: The same
+ // TODO: Error?
}
Log_Log("ECHI", "Controller at PCI %i 0x%x IRQ 0x%x",
}
}
- for( int i = 0; Arguments[i]; i ++ )
+ for( int i = 0; Arguments && Arguments[i]; i ++ )
{
char *pos = Arguments[i], *next;
LOG("pos = '%s'", pos);
cont->TDPool = NULL;
// -- Build up structure --
- cont->CapRegs = (void*)MM_MapHWPages(BaseAddress, 1);
+ cont->CapRegs = (void*)( MM_MapHWPages(BaseAddress, 1) + (BaseAddress % PAGE_SIZE) );
if( !cont->CapRegs ) {
Log_Warning("EHCI", "Can't map 1 page at %P into kernel space", BaseAddress);
goto _error;
BaseAddress, cont->CapRegs->CapLength);
goto _error;
}
+ if( BaseAddress % PAGE_SIZE + cont->CapRegs->CapLength + sizeof(tEHCI_CapRegs) > PAGE_SIZE ) {
+ Log_Warning("EHCI", "%P: Cap regs over page boundary (+0x%x bytes)",
+ BaseAddress % PAGE_SIZE + cont->CapRegs->CapLength + sizeof(tEHCI_CapRegs)
+ );
+ goto _error;
+ }
cont->OpRegs = (void*)( (Uint32*)cont->CapRegs + cont->CapRegs->CapLength / 4 );
// - Allocate periodic queue
tPAddr unused;
// === 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
+ Log_Debug("GIC", "Dist: %P, Interface: %P",
+ gGIC_DistributorAddr, gGIC_InterfaceAddr);
gpGIC_InterfaceBase = (void*)MM_MapHWPages(gGIC_InterfaceAddr, 1);
LOG("gpGIC_InterfaceBase = %p", gpGIC_InterfaceBase);
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
+ LOG("GICC_IAR = %x (CTLR=0)", gpGIC_InterfaceBase[GICC_IAR]);
+
+ 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);
+ Log_Debug("GIC", "IRQ 0x%x", num);
gaIRQ_Handlers[num]( num, gaIRQ_HandlerData[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));
-// 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);
+
+ // DEBUG! Trip the interrupt
+ gpGIC_DistributorBase[GICD_ISPENDR0+IRQ/32] = 1 << (IRQ & (32-1));
return 0;
}