]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/arm/bsp/timer-arm-pxa_sa1100.cpp
update
[l4.git] / kernel / fiasco / src / kern / arm / bsp / timer-arm-pxa_sa1100.cpp
1 // ------------------------------------------------------------------------
2 INTERFACE [arm && (sa1100 || pxa)]:
3
4 #include "kmem.h"
5 #include "irq_chip.h"
6 #include "irq_pin.h"
7
8 EXTENSION class Timer
9 {
10 private:
11   enum {
12     Base = Kmem::Timer_map_base,
13   };
14   // Base = 0x0000000 must be set in ...
15   enum {
16     OSMR0 = Base + 0x00,
17     OSMR1 = Base + 0x04,
18     OSMR2 = Base + 0x08,
19     OSMR3 = Base + 0x0c,
20     OSCR  = Base + 0x10,
21     OSSR  = Base + 0x14,
22     OWER  = Base + 0x18,
23     OIER  = Base + 0x1c,
24
25
26     Timer_diff = (36864 * Config::scheduler_granularity) / 10000, // 36864MHz*1ms
27   };
28
29   static Irq_base *irq;
30 };
31
32
33 // -------------------------------------------------------------
34 IMPLEMENTATION [arm && (sa1100 || pxa)]:
35
36 #include "config.h"
37 #include "kip.h"
38 #include "irq_chip.h"
39 #include "pic.h"
40 #include "io.h"
41
42 Irq_base *Timer::irq;
43
44 IMPLEMENT
45 void Timer::init()
46 {
47   Io::write(1,          OIER); // enable OSMR0
48   Io::write(0,          OWER); // disable Watchdog
49   Io::write<Mword>(Timer_diff, OSMR0);
50   Io::write(0,          OSCR); // set timer counter to zero
51   Io::write(~0U,        OSSR); // clear all status bits
52
53   Irq_chip::hw_chip->reserve(26);
54
55   static Irq_base ib;
56   Irq_chip::hw_chip->setup(&ib, 26);
57   irq = &ib;
58 }
59
60 static inline
61 Unsigned64
62 Timer::timer_to_us(Unsigned32 cr)
63 { return (((Unsigned64)cr) << 14) / 60398; }
64
65 static inline
66 Unsigned64
67 Timer::us_to_timer(Unsigned64 us)
68 { return (us * 60398) >> 14; }
69
70 IMPLEMENT inline NEEDS["io.h", "pic.h", Timer::timer_to_us]
71 void Timer::acknowledge()
72 {
73   if (Config::scheduler_one_shot)
74     {
75       Kip::k()->clock += timer_to_us(Io::read<Unsigned32>(OSCR));
76       //puts("Reset timer");
77       Io::write(0, OSCR);
78       Io::write(0xffffffff, OSMR0);
79     }
80   else
81     Io::write(0, OSCR);
82   Io::write(1, OSSR); // clear all status bits
83   enable();
84 }
85
86 IMPLEMENT inline NEEDS["pic.h"]
87 void Timer::enable()
88 {
89   irq->pin()->unmask();
90 }
91
92 IMPLEMENT inline NEEDS["pic.h"]
93 void Timer::disable()
94 {
95   irq->pin()->mask();
96 }
97
98 IMPLEMENT inline NEEDS["kip.h", "io.h", Timer::timer_to_us, Timer::us_to_timer]
99 void
100 Timer::update_one_shot(Unsigned64 wakeup)
101 {
102   Unsigned32 apic;
103   Kip::k()->clock += timer_to_us(Io::read<Unsigned32>(OSCR));
104   Io::write(0, OSCR);
105   Unsigned64 now = Kip::k()->clock;
106
107   if (EXPECT_FALSE (wakeup <= now) )
108     // already expired
109     apic = 1;
110   else
111     {
112       apic = us_to_timer(wakeup - now);
113       if (EXPECT_FALSE(apic > 0x0ffffffff))
114         apic = 0x0ffffffff;
115       if (EXPECT_FALSE (apic < 1) )
116         // timeout too small
117         apic = 1;
118     }
119
120   //printf("%15lld: Set Timer to %lld [%08x]\n", now, wakeup, apic);
121
122   Io::write(apic, OSMR0);
123   Io::write(1, OSSR); // clear all status bits
124 }
125
126 IMPLEMENT inline NEEDS["config.h", "kip.h", "io.h", Timer::timer_to_us]
127 Unsigned64
128 Timer::system_clock()
129 {
130   if (Config::scheduler_one_shot)
131     return Kip::k()->clock + timer_to_us(Io::read<Unsigned32>(OSCR));
132   else
133     return Kip::k()->clock;
134 }