]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/x86/lib/timer.c
x86: Add function to read time stamp counter
[karo-tx-uboot.git] / arch / x86 / lib / timer.c
1 /*
2  * (C) Copyright 2008,2009
3  * Graeme Russ, <graeme.russ@gmail.com>
4  *
5  * (C) Copyright 2002
6  * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26
27 #include <common.h>
28 #include <malloc.h>
29 #include <asm/io.h>
30 #include <asm/i8254.h>
31 #include <asm/ibmpc.h>
32
33 struct timer_isr_function {
34         struct timer_isr_function *next;
35         timer_fnc_t *isr_func;
36 };
37
38 static struct timer_isr_function *first_timer_isr;
39 static unsigned long system_ticks;
40 static uint64_t base_value;
41
42 /*
43  * register_timer_isr() allows multiple architecture and board specific
44  * functions to be called every millisecond. Keep the execution time of
45  * each function as low as possible
46  */
47 int register_timer_isr(timer_fnc_t *isr_func)
48 {
49         struct timer_isr_function *new_func;
50         struct timer_isr_function *temp;
51         int flag;
52
53         new_func = malloc(sizeof(struct timer_isr_function));
54
55         if (new_func == NULL)
56                 return 1;
57
58         new_func->isr_func = isr_func;
59         new_func->next = NULL;
60
61         /*
62          *  Don't allow timer interrupts while the
63          *  linked list is being modified
64          */
65         flag = disable_interrupts();
66
67         if (first_timer_isr == NULL) {
68                 first_timer_isr = new_func;
69         } else {
70                 temp = first_timer_isr;
71                 while (temp->next != NULL)
72                         temp = temp->next;
73                 temp->next = new_func;
74         }
75
76         if (flag)
77                 enable_interrupts();
78
79         return 0;
80 }
81
82 /*
83  * timer_isr() MUST be the registered interrupt handler for
84  */
85 void timer_isr(void *unused)
86 {
87         struct timer_isr_function *temp = first_timer_isr;
88
89         system_ticks++;
90
91         /* Execute each registered function */
92         while (temp != NULL) {
93                 temp->isr_func();
94                 temp = temp->next;
95         }
96 }
97
98 ulong get_timer(ulong base)
99 {
100         return system_ticks - base;
101 }
102
103 void timer_set_tsc_base(uint64_t new_base)
104 {
105         base_value = new_base;
106 }
107
108 uint64_t timer_get_tsc(void)
109 {
110         uint64_t time_now;
111
112         time_now = rdtsc();
113         if (!base_value)
114                 base_value = time_now;
115
116         return time_now - base_value;
117 }