]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/arm926ejs/davinci/timer.c
e28e6e3a08f290c2c77552939c4ecddd0a635319
[karo-tx-uboot.git] / arch / arm / cpu / arm926ejs / davinci / timer.c
1 /*
2  * (C) Copyright 2003
3  * Texas Instruments <www.ti.com>
4  *
5  * (C) Copyright 2002
6  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
7  * Marius Groeger <mgroeger@sysgo.de>
8  *
9  * (C) Copyright 2002
10  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
11  * Alex Zuepke <azu@sysgo.de>
12  *
13  * (C) Copyright 2002-2004
14  * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
15  *
16  * (C) Copyright 2004
17  * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
18  *
19  * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
20  *
21  * See file CREDITS for list of people who contributed to this
22  * project.
23  *
24  * This program is free software; you can redistribute it and/or
25  * modify it under the terms of the GNU General Public License as
26  * published by the Free Software Foundation; either version 2 of
27  * the License, or (at your option) any later version.
28  *
29  * This program is distributed in the hope that it will be useful,
30  * but WITHOUT ANY WARRANTY; without even the implied warranty of
31  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32  * GNU General Public License for more details.
33  *
34  * You should have received a copy of the GNU General Public License
35  * along with this program; if not, write to the Free Software
36  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
37  * MA 02111-1307 USA
38  */
39
40 #include <common.h>
41 #include <asm/io.h>
42 #include <asm/arch/timer_defs.h>
43 #include <div64.h>
44
45 DECLARE_GLOBAL_DATA_PTR;
46
47 static struct davinci_timer * const timer =
48         (struct davinci_timer *)CONFIG_SYS_TIMERBASE;
49
50 #define TIMER_LOAD_VAL  0xffffffff
51
52 #define TIM_CLK_DIV     16
53
54 int timer_init(void)
55 {
56         /* We are using timer34 in unchained 32-bit mode, full speed */
57         writel(0x0, &timer->tcr);
58         writel(0x0, &timer->tgcr);
59         writel(0x06 | ((TIM_CLK_DIV - 1) << 8), &timer->tgcr);
60         writel(0x0, &timer->tim34);
61         writel(TIMER_LOAD_VAL, &timer->prd34);
62         writel(2 << 22, &timer->tcr);
63         gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK / TIM_CLK_DIV;
64         gd->timer_reset_value = 0;
65
66         return(0);
67 }
68
69 /*
70  * Get the current 64 bit timer tick count
71  */
72 unsigned long long get_ticks(void)
73 {
74         unsigned long now = readl(&timer->tim34);
75
76         /* increment tbu if tbl has rolled over */
77         if (now < gd->tbl)
78                 gd->arch.tbu++;
79         gd->tbl = now;
80
81         return (((unsigned long long)gd->arch.tbu) << 32) | gd->tbl;
82 }
83
84 ulong get_timer(ulong base)
85 {
86         unsigned long long timer_diff;
87
88         timer_diff = get_ticks() - gd->timer_reset_value;
89
90         return lldiv(timer_diff,
91                      (gd->arch.timer_rate_hz / CONFIG_SYS_HZ)) - base;
92 }
93
94 void __udelay(unsigned long usec)
95 {
96         unsigned long long endtime;
97
98         endtime = lldiv((unsigned long long)usec * gd->arch.timer_rate_hz,
99                         1000000UL);
100         endtime += get_ticks();
101
102         while (get_ticks() < endtime)
103                 ;
104 }
105
106 /*
107  * This function is derived from PowerPC code (timebase clock frequency).
108  * On ARM it returns the number of timer ticks per second.
109  */
110 ulong get_tbclk(void)
111 {
112         return gd->arch.timer_rate_hz;
113 }
114
115 #ifdef CONFIG_HW_WATCHDOG
116 static struct davinci_timer * const wdttimer =
117         (struct davinci_timer *)CONFIG_SYS_WDTTIMERBASE;
118
119 /*
120  * See prufw2.pdf for using Timer as a WDT
121  */
122 void davinci_hw_watchdog_enable(void)
123 {
124         writel(0x0, &wdttimer->tcr);
125         writel(0x0, &wdttimer->tgcr);
126         /* TIMMODE = 2h */
127         writel(0x08 | 0x03 | ((TIM_CLK_DIV - 1) << 8), &wdttimer->tgcr);
128         writel(CONFIG_SYS_WDT_PERIOD_LOW, &wdttimer->prd12);
129         writel(CONFIG_SYS_WDT_PERIOD_HIGH, &wdttimer->prd34);
130         writel(2 << 22, &wdttimer->tcr);
131         writel(0x0, &wdttimer->tim12);
132         writel(0x0, &wdttimer->tim34);
133         /* set WDEN bit, WDKEY 0xa5c6 */
134         writel(0xa5c64000, &wdttimer->wdtcr);
135         /* clear counter register */
136         writel(0xda7e4000, &wdttimer->wdtcr);
137 }
138
139 void davinci_hw_watchdog_reset(void)
140 {
141         writel(0xa5c64000, &wdttimer->wdtcr);
142         writel(0xda7e4000, &wdttimer->wdtcr);
143 }
144 #endif