]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/mips/cpu/xburst/timer.c
karo: tx51: justify and adjust the delay required before releasing the ETN PHY strap...
[karo-tx-uboot.git] / arch / mips / cpu / xburst / timer.c
1 /*
2  *  Copyright (c) 2006
3  *  Ingenic Semiconductor, <jlwei@ingenic.cn>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <config.h>
9 #include <common.h>
10 #include <asm/io.h>
11
12 #include <asm/jz4740.h>
13
14 #define TIMER_CHAN  0
15 #define TIMER_FDATA 0xffff  /* Timer full data value */
16
17 DECLARE_GLOBAL_DATA_PTR;
18
19 static struct jz4740_tcu *tcu = (struct jz4740_tcu *)JZ4740_TCU_BASE;
20
21 void reset_timer_masked(void)
22 {
23         /* reset time */
24         gd->arch.lastinc = readl(&tcu->tcnt0);
25         gd->arch.tbl = 0;
26 }
27
28 ulong get_timer_masked(void)
29 {
30         ulong now = readl(&tcu->tcnt0);
31
32         if (gd->arch.lastinc <= now)
33                 gd->arch.tbl += now - gd->arch.lastinc; /* normal mode */
34         else {
35                 /* we have an overflow ... */
36                 gd->arch.tbl += TIMER_FDATA + now - gd->arch.lastinc;
37         }
38
39         gd->arch.lastinc = now;
40
41         return gd->arch.tbl;
42 }
43
44 void udelay_masked(unsigned long usec)
45 {
46         ulong tmo;
47         ulong endtime;
48         signed long diff;
49
50         /* normalize */
51         if (usec >= 1000) {
52                 tmo = usec / 1000;
53                 tmo *= CONFIG_SYS_HZ;
54                 tmo /= 1000;
55         } else {
56                 if (usec > 1) {
57                         tmo = usec * CONFIG_SYS_HZ;
58                         tmo /= 1000*1000;
59                 } else
60                         tmo = 1;
61         }
62
63         endtime = get_timer_masked() + tmo;
64
65         do {
66                 ulong now = get_timer_masked();
67                 diff = endtime - now;
68         } while (diff >= 0);
69 }
70
71 int timer_init(void)
72 {
73         writel(TCU_TCSR_PRESCALE256 | TCU_TCSR_EXT_EN, &tcu->tcsr0);
74
75         writel(0, &tcu->tcnt0);
76         writel(0, &tcu->tdhr0);
77         writel(TIMER_FDATA, &tcu->tdfr0);
78
79         /* mask irqs */
80         writel((1 << TIMER_CHAN) | (1 << (TIMER_CHAN + 16)), &tcu->tmsr);
81         writel(1 << TIMER_CHAN, &tcu->tscr); /* enable timer clock */
82         writeb(1 << TIMER_CHAN, &tcu->tesr); /* start counting up */
83
84         gd->arch.lastinc = 0;
85         gd->arch.tbl = 0;
86
87         return 0;
88 }
89
90 void reset_timer(void)
91 {
92         reset_timer_masked();
93 }
94
95 ulong get_timer(ulong base)
96 {
97         return get_timer_masked() - base;
98 }
99
100 void set_timer(ulong t)
101 {
102         gd->arch.tbl = t;
103 }
104
105 void __udelay(unsigned long usec)
106 {
107         ulong tmo, tmp;
108
109         /* normalize */
110         if (usec >= 1000) {
111                 tmo = usec / 1000;
112                 tmo *= CONFIG_SYS_HZ;
113                 tmo /= 1000;
114         } else {
115                 if (usec >= 1) {
116                         tmo = usec * CONFIG_SYS_HZ;
117                         tmo /= 1000 * 1000;
118                 } else
119                         tmo = 1;
120         }
121
122         /* check for rollover during this delay */
123         tmp = get_timer(0);
124         if ((tmp + tmo) < tmp)
125                 reset_timer_masked();  /* timer would roll over */
126         else
127                 tmo += tmp;
128
129         while (get_timer_masked() < tmo)
130                 ;
131 }
132
133 /*
134  * This function is derived from PowerPC code (read timebase as long long).
135  * On MIPS it just returns the timer value.
136  */
137 unsigned long long get_ticks(void)
138 {
139         return get_timer(0);
140 }
141
142 /*
143  * This function is derived from PowerPC code (timebase clock frequency).
144  * On MIPS it returns the number of timer ticks per second.
145  */
146 ulong get_tbclk(void)
147 {
148         return CONFIG_SYS_HZ;
149 }