Kernel/ARMv7 - Call timers on tegra2
[tpg/acess2.git] / KernelLand / Kernel / arch / armv7 / platform_tegra2.c
1 /*
2  * Acess2 Kernel ARMv7 Port
3  * - By John Hodge (thePowersGang)
4  *
5  * platform_tegra2.c
6  * - Tegra2 Core code
7  */
8 #include <acess.h>
9 #include <timers.h>     // MicroSleep
10 #include "platform_tegra2.h"
11 #include "include/options.h"
12
13 // === CONSTANTS ===
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
18
19 // === Imports ===
20 extern volatile Sint64  giTimestamp;
21 extern volatile Uint64  giTicks;
22 extern volatile Uint64  giPartMiliseconds;
23 extern void     Timer_CallTimers(void);
24
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
32
33 // === GLOBALS ===
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
41 #if 0
42 struct sIRQMap  gpIRQMap;
43 #endif
44
45 // === CODE ===
46
47 // -- Timers --
48 void Timer_IRQHandler_SysClock(int IRQ, void *_unused)
49 {
50         giTimestamp += 100;
51         gpTimersMap->TMR1.PCR_0 = (1<<30);
52         Timer_CallTimers();
53 }
54
55 void Timer_IRQHandler_Timer2(int IRQ, void *_unused)
56 {
57         Log_Debug("Tegra2Tme", "Timer 2");
58 }
59 void Timer_IRQHandler_Timer3(int IRQ, void *_unused)
60 {
61         Log_Debug("Tegra2Tme", "Timer 3");
62 }
63 void Timer_IRQHandler_Timer4(int IRQ, void *_unused)
64 {
65         Log_Debug("Tegra2Tme", "Timer 4");
66 }
67
68 void Time_MicroSleep(Uint16 Microsecs)
69 {
70         Uint32  cur_ts = gpTimersMap->TIMERUS.CNTR_1US;
71         Uint32  tgt_ts = cur_ts + Microsecs;
72         if( tgt_ts < cur_ts )
73                 while( gpTimersMap->TIMERUS.CNTR_1US > cur_ts )
74                         ;
75         while( gpTimersMap->TIMERUS.CNTR_1US < tgt_ts )
76                 ;
77 }
78
79 tTime Time_GetTickOffset(void)
80 {
81         return (gpTimersMap->TIMERUS.CNTR_1US/1000) % 100;
82 }
83
84 void Time_Setup(void)
85 {
86         gpTimersMap = (void*)MM_MapHWPages(0x60005000, 1);
87         gpClockResetMap = (void*)MM_MapHWPages(0x60006000, 1);
88         
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);
97
98         // Disabled until IRQs work
99         //gpClockResetMap->RST_Source = (1 << 5)|(0<<4)|(7);    // Full reset on watchdog timeout
100
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 ++ )
107                 {
108                         __asm__ __volatile__ ("mov r0, r0");
109                         __asm__ __volatile__ ("mov r0, r0");
110                         __asm__ __volatile__ ("mov r0, r0");
111                 }
112                 Log_Debug("Tegra2Tme", "TMR0.PCR = 0x%x", gpTimersMap->TMR1.PCR_0);
113         }
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));
119 }
120
121 #if 0
122 // -- Interrupt Controller --
123 void IRQ_CtrlrHandler(struct sIRQRegs *Ctrlr, int Ofs)
124 {
125         // Primary CPU only?
126         // TODO: 
127 }
128
129 void IRQ_RootHandler(void)
130 {
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);
135 }
136
137 void IRQ_Setup(void)
138 {
139         gpIRQMap = (void*)MM_MapHWPages(0x60004000, 1);
140         
141         gpIRQHandler = IRQ_RootHandler;
142 }
143 #endif

UCC git Repository :: git.ucc.asn.au