set_core_timer() now takes a periodic flag
[akaros.git] / kern / arch / sparc / timer.c
1 #include <arch/timer.h>
2 #include <ros/common.h>
3 #include <arch/trap.h>
4 #include <arch/arch.h>
5 #include <stdio.h>
6 #include <assert.h>
7
8 #ifdef __SHARC__
9 #pragma nosharc
10 #endif
11
12 system_timing_t system_timing = {0};
13
14 void
15 timer_init(void)
16 {       
17         system_timing.tsc_freq = TSC_HZ;
18         cprintf("TSC Frequency: %llu\n", system_timing.tsc_freq);
19 }
20
21 /* Warning!  Sparc is unable to do a one-shot timer, so all timers are periodic,
22  * though that is not normally what we want. */
23 void
24 set_core_timer(uint32_t usec, bool periodic)
25 {
26         set_timer(usec);
27 }
28
29 void
30 set_timer(uint32_t usec)
31 {
32         uint32_t clocks =  (uint64_t)usec*TSC_HZ/1000000;
33         if(clocks & (clocks-1))
34                 clocks = ROUNDUPPWR2(clocks);
35
36         if(clocks > TIMER_MAX_PERIOD)
37         {
38                 clocks = TIMER_MAX_PERIOD;
39                 warn("set_timer: truncating to %d usec",
40                      (uint64_t)clocks*1000000/TSC_HZ);
41         }
42         sparc_set_timer(clocks,!!clocks);
43 }
44
45 void
46 udelay(uint64_t usec)
47 {
48         if (system_timing.tsc_freq != 0)
49         {
50                 uint64_t start, end, now;
51         
52                 start = read_tsc();
53                 end = start + (system_timing.tsc_freq * usec) / 1000000;
54
55                 do
56                 {
57                         cpu_relax();
58                         now = read_tsc();
59                 } while (now < end || (now > start && end < start));
60         }
61         else panic("udelay() was called before timer_init(), moron!");
62 }