| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 1 | #include <arch/arch.h> |
| Barret Rhoden | e2e76c3 | 2019-03-12 19:41:50 -0400 | [diff] [blame] | 2 | #include <arch/time.h> |
| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 3 | #include <assert.h> |
| Barret Rhoden | e2e76c3 | 2019-03-12 19:41:50 -0400 | [diff] [blame] | 4 | #include <ros/common.h> |
| GanShun | 7058f67 | 2016-03-29 11:26:31 -0700 | [diff] [blame] | 5 | #include <ros/procinfo.h> |
| Barret Rhoden | e2e76c3 | 2019-03-12 19:41:50 -0400 | [diff] [blame] | 6 | #include <stdio.h> |
| 7 | #include <trap.h> |
| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 8 | |
| Barret Rhoden | e2e76c3 | 2019-03-12 19:41:50 -0400 | [diff] [blame] | 9 | void timer_init(void) |
| Andrew Waterman | 006db38 | 2011-11-11 00:32:22 -0800 | [diff] [blame] | 10 | { |
| GanShun | 7058f67 | 2016-03-29 11:26:31 -0700 | [diff] [blame] | 11 | __proc_global_info.tsc_freq = TSC_HZ; |
| 12 | cprintf("TSC Frequency: %llu\n", __proc_global_info.tsc_freq); |
| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 13 | } |
| 14 | |
| Barret Rhoden | e2e76c3 | 2019-03-12 19:41:50 -0400 | [diff] [blame] | 15 | void set_core_timer(uint32_t usec, bool periodic) |
| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 16 | { |
| Andrew Waterman | 2d74c3a | 2012-01-23 18:11:52 -0800 | [diff] [blame] | 17 | // we could implement periodic timers using one-shot timers, |
| 18 | // but for now we only support one-shot |
| 19 | assert(!periodic); |
| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 20 | |
| Barret Rhoden | e2e76c3 | 2019-03-12 19:41:50 -0400 | [diff] [blame] | 21 | if (usec) { |
| 22 | uint32_t clocks = (uint64_t)usec * TSC_HZ / 1000000; |
| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 23 | |
| Andrew Waterman | fc1129d | 2012-05-11 17:56:25 -0700 | [diff] [blame] | 24 | int8_t irq_state = 0; |
| 25 | disable_irqsave(&irq_state); |
| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 26 | |
| Andrew Waterman | fc1129d | 2012-05-11 17:56:25 -0700 | [diff] [blame] | 27 | mtpcr(PCR_COUNT, 0); |
| 28 | mtpcr(PCR_COMPARE, clocks); |
| Barret Rhoden | e2e76c3 | 2019-03-12 19:41:50 -0400 | [diff] [blame] | 29 | mtpcr(PCR_SR, mfpcr(PCR_SR) | (1 << (IRQ_TIMER + SR_IM_SHIFT))); |
| Andrew Waterman | 2d74c3a | 2012-01-23 18:11:52 -0800 | [diff] [blame] | 30 | |
| Andrew Waterman | fc1129d | 2012-05-11 17:56:25 -0700 | [diff] [blame] | 31 | enable_irqsave(&irq_state); |
| Barret Rhoden | e2e76c3 | 2019-03-12 19:41:50 -0400 | [diff] [blame] | 32 | } else { |
| 33 | mtpcr(PCR_SR, |
| 34 | mfpcr(PCR_SR) & ~(1 << (IRQ_TIMER + SR_IM_SHIFT))); |
| Andrew Waterman | 2d74c3a | 2012-01-23 18:11:52 -0800 | [diff] [blame] | 35 | } |
| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 36 | } |
| 37 | |
| Barret Rhoden | e2e76c3 | 2019-03-12 19:41:50 -0400 | [diff] [blame] | 38 | void udelay(uint64_t usec) |
| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 39 | { |
| Barret Rhoden | e2e76c3 | 2019-03-12 19:41:50 -0400 | [diff] [blame] | 40 | if (__proc_global_info.tsc_freq != 0) { |
| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 41 | uint64_t start, end, now; |
| GanShun | 7058f67 | 2016-03-29 11:26:31 -0700 | [diff] [blame] | 42 | |
| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 43 | start = read_tsc(); |
| GanShun | 7058f67 | 2016-03-29 11:26:31 -0700 | [diff] [blame] | 44 | end = start + (__proc_global_info.tsc_freq * usec) / 1000000; |
| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 45 | |
| Barret Rhoden | e2e76c3 | 2019-03-12 19:41:50 -0400 | [diff] [blame] | 46 | do { |
| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 47 | cpu_relax(); |
| 48 | now = read_tsc(); |
| 49 | } while (now < end || (now > start && end < start)); |
| Barret Rhoden | e2e76c3 | 2019-03-12 19:41:50 -0400 | [diff] [blame] | 50 | } else |
| 51 | panic("udelay() was called before timer_init(), moron!"); |
| Andrew Waterman | 944d9c4 | 2011-05-23 02:19:57 -0700 | [diff] [blame] | 52 | } |
| Michael Davidson | 5aa0020 | 2016-04-28 17:11:30 -0700 | [diff] [blame] | 53 | |
| 54 | uint64_t read_persistent_clock(void) |
| 55 | { |
| 56 | return 1242129600 * 1000000000UL; /* nanwan's birthday */ |
| 57 | } |