Cleaned up the 'timer interfaces'
[akaros.git] / kern / arch / riscv / time.c
1 #include <arch/time.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 system_timing_t system_timing = {0};
9
10 void
11 timer_init(void)
12 {       
13   mtpcr(PCR_COUNT, 0);
14   mtpcr(PCR_COMPARE, 0);
15         mtpcr(PCR_SR, mfpcr(PCR_SR) | (SR_IM & (1 << (TIMER_IRQ+SR_IM_SHIFT))));
16
17         system_timing.tsc_freq = TSC_HZ;
18         cprintf("TSC Frequency: %llu\n", system_timing.tsc_freq);
19 }
20
21 /* Warning: one-shot timers are unsupported; all timers are periodic.
22  * Perhaps this support could be added with a per_cpu boolean, set
23  * by set_core_timer, and interpreted by the interrupt handler. */
24 void
25 set_core_timer(uint32_t usec, bool periodic)
26 {
27         uint32_t clocks =  (uint64_t)usec*TSC_HZ/1000000;
28
29   int8_t irq_state = 0;
30         disable_irqsave(&irq_state);
31
32   mtpcr(PCR_COMPARE, mfpcr(PCR_COUNT) + clocks);
33
34         enable_irqsave(&irq_state);
35 }
36
37 void
38 udelay(uint64_t usec)
39 {
40         if (system_timing.tsc_freq != 0)
41         {
42                 uint64_t start, end, now;
43         
44                 start = read_tsc();
45                 end = start + (system_timing.tsc_freq * usec) / 1000000;
46
47                 do
48                 {
49                         cpu_relax();
50                         now = read_tsc();
51                 } while (now < end || (now > start && end < start));
52         }
53         else panic("udelay() was called before timer_init(), moron!");
54 }