]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/arm920t/s3c24x0/timer.c
patman: Allow use outside of u-boot tree
[karo-tx-uboot.git] / arch / arm / cpu / arm920t / s3c24x0 / timer.c
1 /*
2  * (C) Copyright 2002
3  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4  * Marius Groeger <mgroeger@sysgo.de>
5  *
6  * (C) Copyright 2002
7  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
8  * Alex Zuepke <azu@sysgo.de>
9  *
10  * (C) Copyright 2002
11  * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
12  *
13  * See file CREDITS for list of people who contributed to this
14  * project.
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License as
18  * published by the Free Software Foundation; either version 2 of
19  * the License, or (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29  * MA 02111-1307 USA
30  */
31
32 #include <common.h>
33 #ifdef CONFIG_S3C24X0
34
35 #include <asm/io.h>
36 #include <asm/arch/s3c24x0_cpu.h>
37
38 DECLARE_GLOBAL_DATA_PTR;
39
40 int timer_init(void)
41 {
42         struct s3c24x0_timers *timers = s3c24x0_get_base_timers();
43         ulong tmr;
44
45         /* use PWM Timer 4 because it has no output */
46         /* prescaler for Timer 4 is 16 */
47         writel(0x0f00, &timers->tcfg0);
48         if (gd->tbu == 0) {
49                 /*
50                  * for 10 ms clock period @ PCLK with 4 bit divider = 1/2
51                  * (default) and prescaler = 16. Should be 10390
52                  * @33.25MHz and 15625 @ 50 MHz
53                  */
54                 gd->tbu = get_PCLK() / (2 * 16 * 100);
55                 gd->timer_rate_hz = get_PCLK() / (2 * 16);
56         }
57         /* load value for 10 ms timeout */
58         writel(gd->tbu, &timers->tcntb4);
59         /* auto load, manual update of timer 4 */
60         tmr = (readl(&timers->tcon) & ~0x0700000) | 0x0600000;
61         writel(tmr, &timers->tcon);
62         /* auto load, start timer 4 */
63         tmr = (tmr & ~0x0700000) | 0x0500000;
64         writel(tmr, &timers->tcon);
65         gd->lastinc = 0;
66         gd->tbl = 0;
67
68         return 0;
69 }
70
71 /*
72  * timer without interrupts
73  */
74 ulong get_timer(ulong base)
75 {
76         return get_timer_masked() - base;
77 }
78
79 void __udelay (unsigned long usec)
80 {
81         ulong tmo;
82         ulong start = get_ticks();
83
84         tmo = usec / 1000;
85         tmo *= (gd->tbu * 100);
86         tmo /= 1000;
87
88         while ((ulong) (get_ticks() - start) < tmo)
89                 /*NOP*/;
90 }
91
92 ulong get_timer_masked(void)
93 {
94         ulong tmr = get_ticks();
95
96         return tmr / (gd->timer_rate_hz / CONFIG_SYS_HZ);
97 }
98
99 void udelay_masked(unsigned long usec)
100 {
101         ulong tmo;
102         ulong endtime;
103         signed long diff;
104
105         if (usec >= 1000) {
106                 tmo = usec / 1000;
107                 tmo *= (gd->tbu * 100);
108                 tmo /= 1000;
109         } else {
110                 tmo = usec * (gd->tbu * 100);
111                 tmo /= (1000 * 1000);
112         }
113
114         endtime = get_ticks() + tmo;
115
116         do {
117                 ulong now = get_ticks();
118                 diff = endtime - now;
119         } while (diff >= 0);
120 }
121
122 /*
123  * This function is derived from PowerPC code (read timebase as long long).
124  * On ARM it just returns the timer value.
125  */
126 unsigned long long get_ticks(void)
127 {
128         struct s3c24x0_timers *timers = s3c24x0_get_base_timers();
129         ulong now = readl(&timers->tcnto4) & 0xffff;
130
131         if (gd->lastinc >= now) {
132                 /* normal mode */
133                 gd->tbl += gd->lastinc - now;
134         } else {
135                 /* we have an overflow ... */
136                 gd->tbl += gd->lastinc + gd->tbu - now;
137         }
138         gd->lastinc = now;
139
140         return gd->tbl;
141 }
142
143 /*
144  * This function is derived from PowerPC code (timebase clock frequency).
145  * On ARM it returns the number of timer ticks per second.
146  */
147 ulong get_tbclk(void)
148 {
149         return CONFIG_SYS_HZ;
150 }
151
152 /*
153  * reset the cpu by setting up the watchdog timer and let him time out
154  */
155 void reset_cpu(ulong ignored)
156 {
157         struct s3c24x0_watchdog *watchdog;
158
159         watchdog = s3c24x0_get_base_watchdog();
160
161         /* Disable watchdog */
162         writel(0x0000, &watchdog->wtcon);
163
164         /* Initialize watchdog timer count register */
165         writel(0x0001, &watchdog->wtcnt);
166
167         /* Enable watchdog timer; assert reset at timer timeout */
168         writel(0x0021, &watchdog->wtcon);
169
170         while (1)
171                 /* loop forever and wait for reset to happen */;
172
173         /*NOTREACHED*/
174 }
175
176 #endif /* CONFIG_S3C24X0 */