]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/arm/bsp/omap3/timer-arm-omap3.cpp
ee0947f69f8766154427f18850065b1efe11f1fc
[l4.git] / kernel / fiasco / src / kern / arm / bsp / omap3 / timer-arm-omap3.cpp
1 // --------------------------------------------------------------------------
2 INTERFACE [arm && omap3]:
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     TIOCP_CFG = Kmem::Timer_base + 0x010, // config
13     TISTAT    = Kmem::Timer_base + 0x014, // non-interrupt status
14     TISR      = Kmem::Timer_base + 0x018, // pending interrupts
15     TIER      = Kmem::Timer_base + 0x01c, // enable/disable of interrupt events
16     TWER      = Kmem::Timer_base + 0x020, // wake-up features
17     TCLR      = Kmem::Timer_base + 0x024, // optional features
18     TCRR      = Kmem::Timer_base + 0x028, // internal counter
19     TLDR      = Kmem::Timer_base + 0x02c, // timer load value
20     TTGR      = Kmem::Timer_base + 0x030, // trigger reload by writing
21     TWPS      = Kmem::Timer_base + 0x034, // write-posted pending
22     TMAR      = Kmem::Timer_base + 0x038, // compare value
23     TCAR1     = Kmem::Timer_base + 0x03c, // first capture value of the counter
24     TCAR2     = Kmem::Timer_base + 0x044, // second capture value of the counter
25     TPIR      = Kmem::Timer_base + 0x048, // positive inc, gpt1, 2 and 10 only
26     TNIR      = Kmem::Timer_base + 0x04C, // negative inc, gpt1, 2 and 10 only
27
28
29     CM_CLKSEL_WKUP = Kmem::Wkup_cm_map_base + 0x40,
30   };
31
32   static Irq_base *irq;
33 };
34
35 // -----------------------------------------------------------------------
36 IMPLEMENTATION [arm && omap3]:
37
38 #include "config.h"
39 #include "kip.h"
40 #include "irq_chip.h"
41 #include "io.h"
42
43 #include <cstdio>
44
45 Irq_base *Timer::irq;
46
47 IMPLEMENT
48 void Timer::init()
49 {
50   // reset
51   Io::write<Mword>(1, TIOCP_CFG);
52   while (!Io::read<Mword>(TISTAT))
53     ;
54   // reset done
55
56   // overflow mode
57   Io::write<Mword>(0x2, TIER);
58   // no wakeup
59   Io::write<Mword>(0x0, TWER);
60
61   // select 32768 Hz input to GPTimer1 (timer1 only!)
62   Io::write<Mword>(~1 & Io::read<Mword>(CM_CLKSEL_WKUP), CM_CLKSEL_WKUP);
63
64   // program 1000 Hz timer frequency
65   Io::write<Mword>(232000, TPIR); // gpt1, gpt2 and gpt10 only
66   Io::write<Mword>(-768000, TNIR); // gpt1, gpt2 and gpt10 only
67   Io::write<Mword>(0xffffffe0, TCRR);
68   Io::write<Mword>(0xffffffe0, TLDR);
69
70   // enable
71   Io::write<Mword>(1 | 2, TCLR);
72
73   Irq_chip::hw_chip->reserve(Config::Scheduling_irq);
74
75   static Irq_base ib;
76   Irq_chip::hw_chip->setup(&ib, Config::Scheduling_irq);
77   irq = &ib;
78 }
79
80 static inline
81 Unsigned64
82 Timer::timer_to_us(Unsigned32 /*cr*/)
83 { return 0; }
84
85 static inline
86 Unsigned64
87 Timer::us_to_timer(Unsigned64 us)
88 { (void)us; return 0; }
89
90 IMPLEMENT inline NEEDS["config.h", "io.h"]
91 void Timer::acknowledge()
92 {
93   // XXX: there's a update_system_clock function !?!?!?!
94   //if (!Config::scheduler_one_shot)
95   //  Kip::k()->clock += Config::scheduler_granularity;
96
97   Io::write<Mword>(2, TISR);
98   irq->pin()->ack();
99 }
100
101 IMPLEMENT inline
102 void Timer::enable()
103 {
104   irq->pin()->unmask();
105 }
106
107 IMPLEMENT inline
108 void Timer::disable()
109 {
110   irq->pin()->mask();
111 }
112
113 IMPLEMENT inline NEEDS["kip.h", "io.h", Timer::timer_to_us, Timer::us_to_timer]
114 void
115 Timer::update_one_shot(Unsigned64 wakeup)
116 {
117   Unsigned32 apic;
118   //Kip::k()->clock += timer_to_us(Io::read<Unsigned32>(OSCR));
119   Unsigned64 now = Kip::k()->clock;
120
121   if (EXPECT_FALSE (wakeup <= now) )
122     // already expired
123     apic = 1;
124   else
125     {
126       apic = us_to_timer(wakeup - now);
127       if (EXPECT_FALSE(apic > 0x0ffffffff))
128         apic = 0x0ffffffff;
129       if (EXPECT_FALSE (apic < 1) )
130         // timeout too small
131         apic = 1;
132     }
133 }
134
135 IMPLEMENT inline NEEDS["config.h", "kip.h"]
136 Unsigned64
137 Timer::system_clock()
138 {
139   if (Config::scheduler_one_shot)
140     return 0;
141   else
142     return Kip::k()->clock;
143 }