Kernel/ARMv7 - Hacky (non-atomic) sync_and_fetch_4
[tpg/acess2.git] / KernelLand / Kernel / arch / armv7 / platform_realview_pb.c
1 /*
2  * Acess2 Kernel ARMv7 Port
3  * - By John Hodge (thePowersGang)
4  *
5  * platform_realviewpb.c
6  * - RealviewPB core code
7  */
8 #include <acess.h>
9
10 // === IMPORTS ===
11 extern tTime    giTimestamp;
12
13 // === PROTOTYPES ===
14 void    Time_Setup(void);       // TODO: Should be in header
15 void    Time_int_RTCIRQHandler(int IRQ, void *unused);
16 void    Time_int_TimerIRQHandler(int IRQ, void *unused);
17 tTime   Time_GetTickOffset(void);       // TODO: Should be in header
18
19 // === GLOBALS ===
20 tTime   giTimeBase;
21 Uint32  giTime_PartMS;
22 tPAddr  gGIC_DistributorAddr = 0x1e001000;
23 tPAddr  gGIC_InterfaceAddr = 0x1e000000;
24
25 #define DIVISOR_ENC     1
26 #define DIVISOR_REAL    (1 << (4*DIVISOR_ENC))
27 #define TICKS_PER_SECOND        (1000000/DIVISOR_REAL)
28 #define TICKS_PER_IRQ   (TICKS_PER_SECOND/2)    // Tick twice a second
29 #define TICKS_PER_MS    (TICKS_PER_SECOND/1000)
30 #define MS_PER_IRQ      (TICKS_PER_IRQ*1000/TICKS_PER_SECOND)   // (TICKS_PER_IRQ/(TICKS_PER_SECOND/1000))
31 #define PART_PER_IRQ    (TICKS_PER_IRQ%(TICKS_PER_SECOND/1000)) // (TICKS_PER_IRQ%(TICKS_PER_SECOND/1000))
32
33 // RTC
34 #define PL031_BASE      0x10017000
35 #define PL031_IRQ       10
36 volatile struct {
37         Uint32  DR;
38         Uint32  MR;
39         Uint32  LR;
40         Uint32  CR;
41         Uint32  IMSC;
42         Uint32  IS;
43         Uint32  MIS;
44         Uint32  ICR;
45 } *gTime_PL031;
46 // Timer
47 #define SP804_BASE      0x10011000
48 #define SP805_IRQ       4
49 volatile struct {
50         struct {
51                 Uint32  Load;
52                 Uint32  Value;
53                 Uint32  Control;
54                 Uint32  CIS;
55                 Uint32  RIS;
56                 Uint32  MIS;
57                 Uint32  BGLoad;
58                 Uint32  _unused2;
59         } Timers[2];
60 } *gTime_SP804;
61
62 // === CODE ===
63 void Time_int_RTCIRQHandler(int IRQ, void *unused)
64 {
65         if( !(gTime_PL031->IS & 1) ) {
66                 return ;
67         }
68         gTime_PL031->ICR = 1;   // Clear interrupt
69 //      giTimestamp = (Uint64)gTime_PL031->DR * 1000 - giTimeBase;
70 }
71
72 void Time_int_TimerIRQHandler(int IRQ, void *unused)
73 {
74         if( !(gTime_SP804->Timers[0].RIS) ) {
75                 return ;
76         }
77         gTime_SP804->Timers[0].CIS = 1;
78         giTime_PartMS += PART_PER_IRQ;
79         giTimestamp += MS_PER_IRQ;
80         while( giTime_PartMS > TICKS_PER_MS ) {
81                 giTime_PartMS -= TICKS_PER_MS;
82                 giTimestamp ++;
83         }
84 }
85
86 void Time_Setup(void)
87 {
88         // PL031 RTC
89         gTime_PL031 = MM_MapHWPages(PL031_BASE, 1);
90         //IRQ_AddHandler(PL031_IRQ, Time_int_RTCIRQHandler, NULL);
91         gTime_PL031->IMSC = 1;
92         gTime_PL031->ICR = 1;
93 //      giTimestamp = (Uint64)gTime_PL031->DR * 1000;
94         
95         // SP804 Timer (Contains two basic ARM timers, each at 1MHz base)
96         gTime_SP804 = MM_MapHWPages(SP804_BASE, 1);
97         // - Use the first to maintain the system clock
98         gTime_SP804->Timers[0].Load = TICKS_PER_IRQ;
99         //  > Enable,Periodic,IE,Div=1,32bit
100         gTime_SP804->Timers[0].Control = (1<<7)|(1<<6)|(1<<5)|(DIVISOR_ENC<<2)|(1<<1);
101         IRQ_AddHandler(SP805_IRQ, Time_int_TimerIRQHandler, NULL);
102         gTime_SP804->Timers[0].CIS = 1;
103         // - TODO: use the second for short events (and use RTC for long events)
104 }
105
106 tTime Time_GetTickOffset(void)
107 {
108         if( !gTime_SP804 )
109                 return 0;
110         // Want count of ms since last tick
111         return (giTime_PartMS + gTime_SP804->Timers[0].Value) / TICKS_PER_MS;
112 }

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