2 * Acess2 Kernel ARMv7 Port
3 * - By John Hodge (thePowersGang)
9 #include <timers.h> // MicroSleep
10 #include "platform_tegra2.h"
11 #include "include/options.h"
14 #define TIMER0_INT (0*32+0) // Pri #0
15 #define TIMER1_INT (0*32+1) // Pri #1
16 #define TIMER2_INT (1*32+9) // Sec #9
17 #define TIMER3_INT (1*32+10) // Sec #10
20 extern volatile Sint64 giTimestamp;
21 extern volatile Uint64 giTicks;
22 extern volatile Uint64 giPartMiliseconds;
23 extern void Timer_CallTimers(void);
25 // === PROTORTYPES ===
26 void Timer_IRQHandler_SysClock(int IRQ, void *_unused);
27 void Timer_IRQHandler_Timer2(int IRQ, void *_unused);
28 void Timer_IRQHandler_Timer3(int IRQ, void *_unused);
29 void Timer_IRQHandler_Timer4(int IRQ, void *_unused);
30 void Time_Setup(void);
31 tTime Time_GetTickOffset(void); // TODO: move to header
34 // - Addresses for the GIC to use
35 tPAddr gGIC_InterfaceAddr = GICI_PADDR;
36 tPAddr gGIC_DistributorAddr = GICD_PADDR;
37 // - Map of timer registers
38 volatile struct sTimersMap *gpTimersMap;
39 volatile struct sClockResetMap *gpClockResetMap;
40 // - Interrupt controller code commented out, because the Tegra2 also has a GIC
42 struct sIRQMap gpIRQMap;
48 void Timer_IRQHandler_SysClock(int IRQ, void *_unused)
51 gpTimersMap->TMR1.PCR_0 = (1<<30);
55 void Timer_IRQHandler_Timer2(int IRQ, void *_unused)
57 Log_Debug("Tegra2Tme", "Timer 2");
59 void Timer_IRQHandler_Timer3(int IRQ, void *_unused)
61 Log_Debug("Tegra2Tme", "Timer 3");
63 void Timer_IRQHandler_Timer4(int IRQ, void *_unused)
65 Log_Debug("Tegra2Tme", "Timer 4");
68 void Time_MicroSleep(Uint16 Microsecs)
70 Uint32 cur_ts = gpTimersMap->TIMERUS.CNTR_1US;
71 Uint32 tgt_ts = cur_ts + Microsecs;
73 while( gpTimersMap->TIMERUS.CNTR_1US > cur_ts )
75 while( gpTimersMap->TIMERUS.CNTR_1US < tgt_ts )
79 tTime Time_GetTickOffset(void)
81 return (gpTimersMap->TIMERUS.CNTR_1US/1000) % 100;
86 gpTimersMap = (void*)MM_MapHWPages(0x60005000, 1);
87 gpClockResetMap = (void*)MM_MapHWPages(0x60006000, 1);
89 // Timer 1 (used for system timekeeping)
90 IRQ_AddHandler(0*32+0, Timer_IRQHandler_SysClock, NULL);
91 IRQ_AddHandler(0*32+1, Timer_IRQHandler_Timer2, NULL);
92 IRQ_AddHandler(1*32+9, Timer_IRQHandler_Timer3, NULL);
93 IRQ_AddHandler(1*32+10, Timer_IRQHandler_Timer4, NULL);
94 gpTimersMap->TMR1.PTV_0 = (1<<31)|(1<<30)|(100*1000-1); // enable, periodic, 100 ms
95 gpTimersMap->TMR1.PCR_0 = (1<<30);
96 Log_Debug("Tegra2Tme", "TMR0.PCR = 0x%x", gpTimersMap->TMR1.PCR_0);
98 // Disabled until IRQs work
99 //gpClockResetMap->RST_Source = (1 << 5)|(0<<4)|(7); // Full reset on watchdog timeout
101 Log_Debug("Tegra2Tme", "TIMERUS_USEC_CFG = 0x%x", gpTimersMap->TIMERUS.USEC_CFG);
102 Log_Debug("Tegra2Tme", "TIMERUS_CNTR_1US = 0x%x", gpTimersMap->TIMERUS.CNTR_1US);
103 Log_Debug("Tegra2Tme", "TMR0.PCR = 0x%x", gpTimersMap->TMR1.PCR_0);
104 Log_Debug("Tegra2Tme", "TMR0.PTV = 0x%x", gpTimersMap->TMR1.PTV_0);
105 for( int i = 0; i < 5; i ++ ) {
106 for( int j = 0; j < 1000*1000; j ++ )
108 __asm__ __volatile__ ("mov r0, r0");
109 __asm__ __volatile__ ("mov r0, r0");
110 __asm__ __volatile__ ("mov r0, r0");
112 Log_Debug("Tegra2Tme", "TMR0.PCR = 0x%x", gpTimersMap->TMR1.PCR_0);
114 Log_Debug("Tegra2Tme", "TMR0.PCR = 0x%x", gpTimersMap->TMR1.PCR_0);
115 Log_Debug("Tegra2Tme", "GICC_HPPIR = 0x%x", *(Uint32*)(0xF0000000 + 0x18));
116 Log_Debug("Tegra2Tme", "GICC_IAR = 0x%x", *(Uint32*)(0xF0000000 + 0xC));
117 Log_Debug("Tegra2Tme", "GICD_ISPENDR0 = 0x%x", *(Uint32*)(0xF0001000 + 0x200 + 0*4));
118 Log_Debug("Tegra2Tme", "GICD_ISPENDR1 = 0x%x", *(Uint32*)(0xF0001000 + 0x200 + 1*4));
122 // -- Interrupt Controller --
123 void IRQ_CtrlrHandler(struct sIRQRegs *Ctrlr, int Ofs)
129 void IRQ_RootHandler(void)
131 IRQ_CtrlrHandler(&gpIRQMap->Pri, 0*32);
132 IRQ_CtrlrHandler(&gpIRQMap->Sec, 1*32);
133 IRQ_CtrlrHandler(&gpIRQMap->Tri, 2*32);
134 IRQ_CtrlrHandler(&gpIRQMap->Quad, 3*32);
139 gpIRQMap = (void*)MM_MapHWPages(0x60004000, 1);
141 gpIRQHandler = IRQ_RootHandler;