]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/arm/bsp/realview/timer-arm-realview.cpp
update
[l4.git] / kernel / fiasco / src / kern / arm / bsp / realview / timer-arm-realview.cpp
1 // --------------------------------------------------------------------------
2 INTERFACE [arm && sp804]:
3
4 #include "irq_chip.h"
5 #include "irq_pin.h"
6 #include "kmem.h"
7
8 EXTENSION class Timer
9 {
10 private:
11   enum {
12     System_control = Kmem::System_ctrl_map_base,
13
14     Refclk = 0,
15     Timclk = 1,
16
17     Timer1_enable = 15,
18     Timer2_enable = 17,
19     Timer3_enable = 19,
20     Timer4_enable = 21,
21
22     Timer_load   = 0x00,
23     Timer_value  = 0x04,
24     Timer_ctrl   = 0x08,
25     Timer_intclr = 0x0c,
26
27     Load_0 = Kmem::Timer0_map_base + Timer_load,
28     Load_1 = Kmem::Timer1_map_base + Timer_load,
29     Load_2 = Kmem::Timer2_map_base + Timer_load,
30     Load_3 = Kmem::Timer3_map_base + Timer_load,
31
32     Value_0 = Kmem::Timer0_map_base + Timer_value,
33     Value_1 = Kmem::Timer1_map_base + Timer_value,
34     Value_2 = Kmem::Timer2_map_base + Timer_value,
35     Value_3 = Kmem::Timer3_map_base + Timer_value,
36
37     Ctrl_0 = Kmem::Timer0_map_base + Timer_ctrl,
38     Ctrl_1 = Kmem::Timer1_map_base + Timer_ctrl,
39     Ctrl_2 = Kmem::Timer2_map_base + Timer_ctrl,
40     Ctrl_3 = Kmem::Timer3_map_base + Timer_ctrl,
41
42     Intclr_0 = Kmem::Timer0_map_base + Timer_intclr,
43     Intclr_1 = Kmem::Timer1_map_base + Timer_intclr,
44     Intclr_2 = Kmem::Timer2_map_base + Timer_intclr,
45     Intclr_3 = Kmem::Timer3_map_base + Timer_intclr,
46
47     Interval = 1000,
48
49     Ctrl_ie        = 1 << 5,
50     Ctrl_periodic  = 1 << 6,
51     Ctrl_enable    = 1 << 7,
52   };
53
54   static Irq_base *irq;
55 };
56
57 // -----------------------------------------------------------------------
58 IMPLEMENTATION [arm && sp804]:
59
60 #include "config.h"
61 #include "kip.h"
62 #include "io.h"
63
64 #include <cstdio>
65
66 Irq_base *Timer::irq;
67
68 IMPLEMENT
69 void Timer::init()
70 {
71   Mword v;
72
73   v = Io::read<Mword>(System_control);
74   v |= Timclk << Timer1_enable;
75   Io::write<Mword>(v, System_control);
76
77   // all timers off
78   Io::write<Mword>(0, Ctrl_0);
79   Io::write<Mword>(0, Ctrl_1);
80   Io::write<Mword>(0, Ctrl_2);
81   Io::write<Mword>(0, Ctrl_3);
82
83   Io::write<Mword>(Interval, Load_0);
84   Io::write<Mword>(Interval, Value_0);
85   Io::write<Mword>(Ctrl_enable | Ctrl_periodic | Ctrl_ie, Ctrl_0);
86
87   if (!current_cpu())
88     {
89       Irq_chip::hw_chip->reserve(Config::Scheduling_irq);
90
91       static Irq_base ib;
92       Irq_chip::hw_chip->setup(&ib, Config::Scheduling_irq);
93       irq = &ib;
94     }
95 }
96
97 static inline
98 Unsigned64
99 Timer::timer_to_us(Unsigned32 /*cr*/)
100 { return 0; }
101
102 static inline
103 Unsigned64
104 Timer::us_to_timer(Unsigned64 us)
105 { (void)us; return 0; }
106
107 IMPLEMENT inline NEEDS["io.h"]
108 void Timer::acknowledge()
109 {
110   Io::write<Mword>(0, Intclr_0);
111   irq->pin()->ack();
112 }
113
114 IMPLEMENT inline
115 void Timer::enable()
116 {
117   irq->pin()->unmask();
118 }
119
120 IMPLEMENT inline
121 void Timer::disable()
122 {
123   irq->pin()->mask();
124 }
125
126 IMPLEMENT inline NEEDS["kip.h", "io.h", Timer::timer_to_us, Timer::us_to_timer]
127 void
128 Timer::update_one_shot(Unsigned64 wakeup)
129 {
130   Unsigned32 apic;
131   //Kip::k()->clock += timer_to_us(Io::read<Unsigned32>(Oscr));
132   Unsigned64 now = Kip::k()->clock;
133
134   if (EXPECT_FALSE (wakeup <= now) )
135     // already expired
136     apic = 1;
137   else
138     {
139       apic = us_to_timer(wakeup - now);
140       if (EXPECT_FALSE(apic > 0x0ffffffff))
141         apic = 0x0ffffffff;
142       if (EXPECT_FALSE (apic < 1) )
143         // timeout too small
144         apic = 1;
145     }
146 }
147
148 IMPLEMENT inline NEEDS["config.h", "kip.h"]
149 Unsigned64
150 Timer::system_clock()
151 {
152   if (Config::scheduler_one_shot)
153     return 0;
154   else
155     return Kip::k()->clock;
156 }