]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - arch/x86/lib/timer.c
fb11bfe88b45aa0c91c2a9fb14b10fbc9e1a5cdb
[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 DECLARE_GLOBAL_DATA_PTR;
34
35 struct timer_isr_function {
36         struct timer_isr_function *next;
37         timer_fnc_t *isr_func;
38 };
39
40 static struct timer_isr_function *first_timer_isr;
41 static unsigned long system_ticks;
42
43 /*
44  * register_timer_isr() allows multiple architecture and board specific
45  * functions to be called every millisecond. Keep the execution time of
46  * each function as low as possible
47  */
48 int register_timer_isr(timer_fnc_t *isr_func)
49 {
50         struct timer_isr_function *new_func;
51         struct timer_isr_function *temp;
52         int flag;
53
54         new_func = malloc(sizeof(struct timer_isr_function));
55
56         if (new_func == NULL)
57                 return 1;
58
59         new_func->isr_func = isr_func;
60         new_func->next = NULL;
61
62         /*
63          *  Don't allow timer interrupts while the
64          *  linked list is being modified
65          */
66         flag = disable_interrupts();
67
68         if (first_timer_isr == NULL) {
69                 first_timer_isr = new_func;
70         } else {
71                 temp = first_timer_isr;
72                 while (temp->next != NULL)
73                         temp = temp->next;
74                 temp->next = new_func;
75         }
76
77         if (flag)
78                 enable_interrupts();
79
80         return 0;
81 }
82
83 /*
84  * timer_isr() MUST be the registered interrupt handler for
85  */
86 void timer_isr(void *unused)
87 {
88         struct timer_isr_function *temp = first_timer_isr;
89
90         system_ticks++;
91
92         /* Execute each registered function */
93         while (temp != NULL) {
94                 temp->isr_func();
95                 temp = temp->next;
96         }
97 }
98
99 ulong get_timer(ulong base)
100 {
101         return system_ticks - base;
102 }
103
104 void timer_set_tsc_base(uint64_t new_base)
105 {
106         gd->arch.tsc_base = new_base;
107 }
108
109 uint64_t timer_get_tsc(void)
110 {
111         uint64_t time_now;
112
113         time_now = rdtsc();
114         if (!gd->arch.tsc_base)
115                 gd->arch.tsc_base = time_now;
116
117         return time_now - gd->arch.tsc_base;
118 }