|  | #include <arch/arch.h> | 
|  | #include <arch/time.h> | 
|  | #include <assert.h> | 
|  | #include <ros/common.h> | 
|  | #include <ros/procinfo.h> | 
|  | #include <stdio.h> | 
|  | #include <trap.h> | 
|  |  | 
|  | void timer_init(void) | 
|  | { | 
|  | __proc_global_info.tsc_freq = TSC_HZ; | 
|  | cprintf("TSC Frequency: %llu\n", __proc_global_info.tsc_freq); | 
|  | } | 
|  |  | 
|  | void set_core_timer(uint32_t usec, bool periodic) | 
|  | { | 
|  | // we could implement periodic timers using one-shot timers, | 
|  | // but for now we only support one-shot | 
|  | assert(!periodic); | 
|  |  | 
|  | if (usec) { | 
|  | uint32_t clocks = (uint64_t)usec * TSC_HZ / 1000000; | 
|  |  | 
|  | int8_t irq_state = 0; | 
|  | disable_irqsave(&irq_state); | 
|  |  | 
|  | mtpcr(PCR_COUNT, 0); | 
|  | mtpcr(PCR_COMPARE, clocks); | 
|  | mtpcr(PCR_SR, mfpcr(PCR_SR) | (1 << (IRQ_TIMER + SR_IM_SHIFT))); | 
|  |  | 
|  | enable_irqsave(&irq_state); | 
|  | } else { | 
|  | mtpcr(PCR_SR, | 
|  | mfpcr(PCR_SR) & ~(1 << (IRQ_TIMER + SR_IM_SHIFT))); | 
|  | } | 
|  | } | 
|  |  | 
|  | void udelay(uint64_t usec) | 
|  | { | 
|  | if (__proc_global_info.tsc_freq != 0) { | 
|  | uint64_t start, end, now; | 
|  |  | 
|  | start = read_tsc(); | 
|  | end = start + (__proc_global_info.tsc_freq * usec) / 1000000; | 
|  |  | 
|  | do { | 
|  | cpu_relax(); | 
|  | now = read_tsc(); | 
|  | } while (now < end || (now > start && end < start)); | 
|  | } else | 
|  | panic("udelay() was called before timer_init(), moron!"); | 
|  | } | 
|  |  | 
|  | uint64_t read_persistent_clock(void) | 
|  | { | 
|  | return 1242129600 * 1000000000UL; /* nanwan's birthday */ | 
|  | } |