]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/mips/cpu/xburst/timer.c
Merge branch 'master' of git://git.denx.de/u-boot-mips
[karo-tx-uboot.git] / arch / mips / cpu / xburst / timer.c
1 /*
2  *  Copyright (c) 2006
3  *  Ingenic Semiconductor, <jlwei@ingenic.cn>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of
8  * the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA
19  */
20
21 #include <config.h>
22 #include <common.h>
23 #include <asm/io.h>
24
25 #include <asm/jz4740.h>
26
27 #define TIMER_CHAN  0
28 #define TIMER_FDATA 0xffff  /* Timer full data value */
29
30 DECLARE_GLOBAL_DATA_PTR;
31
32 static struct jz4740_tcu *tcu = (struct jz4740_tcu *)JZ4740_TCU_BASE;
33
34 void reset_timer_masked(void)
35 {
36         /* reset time */
37         gd->lastinc = readl(&tcu->tcnt0);
38         gd->tbl = 0;
39 }
40
41 ulong get_timer_masked(void)
42 {
43         ulong now = readl(&tcu->tcnt0);
44
45         if (gd->lastinc <= now)
46                 gd->tbl += now - gd->lastinc; /* normal mode */
47         else {
48                 /* we have an overflow ... */
49                 gd->tbl += TIMER_FDATA + now - gd->lastinc;
50         }
51
52         gd->lastinc = now;
53
54         return gd->tbl;
55 }
56
57 void udelay_masked(unsigned long usec)
58 {
59         ulong tmo;
60         ulong endtime;
61         signed long diff;
62
63         /* normalize */
64         if (usec >= 1000) {
65                 tmo = usec / 1000;
66                 tmo *= CONFIG_SYS_HZ;
67                 tmo /= 1000;
68         } else {
69                 if (usec > 1) {
70                         tmo = usec * CONFIG_SYS_HZ;
71                         tmo /= 1000*1000;
72                 } else
73                         tmo = 1;
74         }
75
76         endtime = get_timer_masked() + tmo;
77
78         do {
79                 ulong now = get_timer_masked();
80                 diff = endtime - now;
81         } while (diff >= 0);
82 }
83
84 int timer_init(void)
85 {
86         writel(TCU_TCSR_PRESCALE256 | TCU_TCSR_EXT_EN, &tcu->tcsr0);
87
88         writel(0, &tcu->tcnt0);
89         writel(0, &tcu->tdhr0);
90         writel(TIMER_FDATA, &tcu->tdfr0);
91
92         /* mask irqs */
93         writel((1 << TIMER_CHAN) | (1 << (TIMER_CHAN + 16)), &tcu->tmsr);
94         writel(1 << TIMER_CHAN, &tcu->tscr); /* enable timer clock */
95         writeb(1 << TIMER_CHAN, &tcu->tesr); /* start counting up */
96
97         gd->lastinc = 0;
98         gd->tbl = 0;
99
100         return 0;
101 }
102
103 void reset_timer(void)
104 {
105         reset_timer_masked();
106 }
107
108 ulong get_timer(ulong base)
109 {
110         return get_timer_masked() - base;
111 }
112
113 void set_timer(ulong t)
114 {
115         gd->tbl = t;
116 }
117
118 void __udelay(unsigned long usec)
119 {
120         ulong tmo, tmp;
121
122         /* normalize */
123         if (usec >= 1000) {
124                 tmo = usec / 1000;
125                 tmo *= CONFIG_SYS_HZ;
126                 tmo /= 1000;
127         } else {
128                 if (usec >= 1) {
129                         tmo = usec * CONFIG_SYS_HZ;
130                         tmo /= 1000 * 1000;
131                 } else
132                         tmo = 1;
133         }
134
135         /* check for rollover during this delay */
136         tmp = get_timer(0);
137         if ((tmp + tmo) < tmp)
138                 reset_timer_masked();  /* timer would roll over */
139         else
140                 tmo += tmp;
141
142         while (get_timer_masked() < tmo)
143                 ;
144 }
145
146 /*
147  * This function is derived from PowerPC code (read timebase as long long).
148  * On MIPS it just returns the timer value.
149  */
150 unsigned long long get_ticks(void)
151 {
152         return get_timer(0);
153 }
154
155 /*
156  * This function is derived from PowerPC code (timebase clock frequency).
157  * On MIPS it returns the number of timer ticks per second.
158  */
159 ulong get_tbclk(void)
160 {
161         return CONFIG_SYS_HZ;
162 }