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