blob: 7de607181cee26c3818a616dcf5e3816e1bb9ef0 [file] [log] [blame]
Andrew Waterman944d9c42011-05-23 02:19:57 -07001#include <arch/arch.h>
Barret Rhodene2e76c32019-03-12 19:41:50 -04002#include <arch/time.h>
Andrew Waterman944d9c42011-05-23 02:19:57 -07003#include <assert.h>
Barret Rhodene2e76c32019-03-12 19:41:50 -04004#include <ros/common.h>
GanShun7058f672016-03-29 11:26:31 -07005#include <ros/procinfo.h>
Barret Rhodene2e76c32019-03-12 19:41:50 -04006#include <stdio.h>
7#include <trap.h>
Andrew Waterman944d9c42011-05-23 02:19:57 -07008
Barret Rhodene2e76c32019-03-12 19:41:50 -04009void timer_init(void)
Andrew Waterman006db382011-11-11 00:32:22 -080010{
GanShun7058f672016-03-29 11:26:31 -070011 __proc_global_info.tsc_freq = TSC_HZ;
12 cprintf("TSC Frequency: %llu\n", __proc_global_info.tsc_freq);
Andrew Waterman944d9c42011-05-23 02:19:57 -070013}
14
Barret Rhodene2e76c32019-03-12 19:41:50 -040015void set_core_timer(uint32_t usec, bool periodic)
Andrew Waterman944d9c42011-05-23 02:19:57 -070016{
Andrew Waterman2d74c3a2012-01-23 18:11:52 -080017 // we could implement periodic timers using one-shot timers,
18 // but for now we only support one-shot
19 assert(!periodic);
Andrew Waterman944d9c42011-05-23 02:19:57 -070020
Barret Rhodene2e76c32019-03-12 19:41:50 -040021 if (usec) {
22 uint32_t clocks = (uint64_t)usec * TSC_HZ / 1000000;
Andrew Waterman944d9c42011-05-23 02:19:57 -070023
Andrew Watermanfc1129d2012-05-11 17:56:25 -070024 int8_t irq_state = 0;
25 disable_irqsave(&irq_state);
Andrew Waterman944d9c42011-05-23 02:19:57 -070026
Andrew Watermanfc1129d2012-05-11 17:56:25 -070027 mtpcr(PCR_COUNT, 0);
28 mtpcr(PCR_COMPARE, clocks);
Barret Rhodene2e76c32019-03-12 19:41:50 -040029 mtpcr(PCR_SR, mfpcr(PCR_SR) | (1 << (IRQ_TIMER + SR_IM_SHIFT)));
Andrew Waterman2d74c3a2012-01-23 18:11:52 -080030
Andrew Watermanfc1129d2012-05-11 17:56:25 -070031 enable_irqsave(&irq_state);
Barret Rhodene2e76c32019-03-12 19:41:50 -040032 } else {
33 mtpcr(PCR_SR,
34 mfpcr(PCR_SR) & ~(1 << (IRQ_TIMER + SR_IM_SHIFT)));
Andrew Waterman2d74c3a2012-01-23 18:11:52 -080035 }
Andrew Waterman944d9c42011-05-23 02:19:57 -070036}
37
Barret Rhodene2e76c32019-03-12 19:41:50 -040038void udelay(uint64_t usec)
Andrew Waterman944d9c42011-05-23 02:19:57 -070039{
Barret Rhodene2e76c32019-03-12 19:41:50 -040040 if (__proc_global_info.tsc_freq != 0) {
Andrew Waterman944d9c42011-05-23 02:19:57 -070041 uint64_t start, end, now;
GanShun7058f672016-03-29 11:26:31 -070042
Andrew Waterman944d9c42011-05-23 02:19:57 -070043 start = read_tsc();
GanShun7058f672016-03-29 11:26:31 -070044 end = start + (__proc_global_info.tsc_freq * usec) / 1000000;
Andrew Waterman944d9c42011-05-23 02:19:57 -070045
Barret Rhodene2e76c32019-03-12 19:41:50 -040046 do {
Andrew Waterman944d9c42011-05-23 02:19:57 -070047 cpu_relax();
48 now = read_tsc();
49 } while (now < end || (now > start && end < start));
Barret Rhodene2e76c32019-03-12 19:41:50 -040050 } else
51 panic("udelay() was called before timer_init(), moron!");
Andrew Waterman944d9c42011-05-23 02:19:57 -070052}
Michael Davidson5aa00202016-04-28 17:11:30 -070053
54uint64_t read_persistent_clock(void)
55{
56 return 1242129600 * 1000000000UL; /* nanwan's birthday */
57}