blob: 79f34f00c9f14bd6329658c7f6b37587da2c2c2b [file] [log] [blame]
Xiangfu Liu80421fc2011-10-12 12:24:06 +08001/*
2 * Copyright (c) 2006
3 * Ingenic Semiconductor, <jlwei@ingenic.cn>
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
Xiangfu Liu80421fc2011-10-12 12:24:06 +08006 */
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
17DECLARE_GLOBAL_DATA_PTR;
18
19static struct jz4740_tcu *tcu = (struct jz4740_tcu *)JZ4740_TCU_BASE;
20
21void reset_timer_masked(void)
22{
23 /* reset time */
Simon Glass582601d2012-12-13 20:48:35 +000024 gd->arch.lastinc = readl(&tcu->tcnt0);
Simon Glass66ee6922012-12-13 20:48:34 +000025 gd->arch.tbl = 0;
Xiangfu Liu80421fc2011-10-12 12:24:06 +080026}
27
28ulong get_timer_masked(void)
29{
Marek Vasut8b82cef2012-08-12 16:53:35 +020030 ulong now = readl(&tcu->tcnt0);
Xiangfu Liu80421fc2011-10-12 12:24:06 +080031
Simon Glass582601d2012-12-13 20:48:35 +000032 if (gd->arch.lastinc <= now)
33 gd->arch.tbl += now - gd->arch.lastinc; /* normal mode */
Xiangfu Liu80421fc2011-10-12 12:24:06 +080034 else {
35 /* we have an overflow ... */
Simon Glass582601d2012-12-13 20:48:35 +000036 gd->arch.tbl += TIMER_FDATA + now - gd->arch.lastinc;
Xiangfu Liu80421fc2011-10-12 12:24:06 +080037 }
38
Simon Glass582601d2012-12-13 20:48:35 +000039 gd->arch.lastinc = now;
Xiangfu Liu80421fc2011-10-12 12:24:06 +080040
Simon Glass66ee6922012-12-13 20:48:34 +000041 return gd->arch.tbl;
Xiangfu Liu80421fc2011-10-12 12:24:06 +080042}
43
44void 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
71int timer_init(void)
72{
Marek Vasut8b82cef2012-08-12 16:53:35 +020073 writel(TCU_TCSR_PRESCALE256 | TCU_TCSR_EXT_EN, &tcu->tcsr0);
Xiangfu Liu80421fc2011-10-12 12:24:06 +080074
Marek Vasut8b82cef2012-08-12 16:53:35 +020075 writel(0, &tcu->tcnt0);
76 writel(0, &tcu->tdhr0);
77 writel(TIMER_FDATA, &tcu->tdfr0);
Xiangfu Liu80421fc2011-10-12 12:24:06 +080078
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
Simon Glass582601d2012-12-13 20:48:35 +000084 gd->arch.lastinc = 0;
Simon Glass66ee6922012-12-13 20:48:34 +000085 gd->arch.tbl = 0;
Xiangfu Liu80421fc2011-10-12 12:24:06 +080086
87 return 0;
88}
89
90void reset_timer(void)
91{
92 reset_timer_masked();
93}
94
95ulong get_timer(ulong base)
96{
97 return get_timer_masked() - base;
98}
99
100void set_timer(ulong t)
101{
Simon Glass66ee6922012-12-13 20:48:34 +0000102 gd->arch.tbl = t;
Xiangfu Liu80421fc2011-10-12 12:24:06 +0800103}
104
105void __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 */
137unsigned 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 */
146ulong get_tbclk(void)
147{
148 return CONFIG_SYS_HZ;
149}