xref: /rk3399_rockchip-uboot/arch/m68k/lib/time.c (revision 5c8404aff16c2a207a11e1af5843e1009bf9fb01)
1ea0364f1SPeter Tyser /*
2ea0364f1SPeter Tyser  * (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de>
3ea0364f1SPeter Tyser  *
4ea0364f1SPeter Tyser  * (C) Copyright 2000
5ea0364f1SPeter Tyser  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6ea0364f1SPeter Tyser  *
7ea0364f1SPeter Tyser  * See file CREDITS for list of people who contributed to this
8ea0364f1SPeter Tyser  * project.
9ea0364f1SPeter Tyser  *
10ea0364f1SPeter Tyser  * This program is free software; you can redistribute it and/or
11ea0364f1SPeter Tyser  * modify it under the terms of the GNU General Public License as
12ea0364f1SPeter Tyser  * published by the Free Software Foundation; either version 2 of
13ea0364f1SPeter Tyser  * the License, or (at your option) any later version.
14ea0364f1SPeter Tyser  *
15ea0364f1SPeter Tyser  * This program is distributed in the hope that it will be useful,
16ea0364f1SPeter Tyser  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17ea0364f1SPeter Tyser  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
18ea0364f1SPeter Tyser  * GNU General Public License for more details.
19ea0364f1SPeter Tyser  *
20ea0364f1SPeter Tyser  * You should have received a copy of the GNU General Public License
21ea0364f1SPeter Tyser  * along with this program; if not, write to the Free Software
22ea0364f1SPeter Tyser  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23ea0364f1SPeter Tyser  * MA 02111-1307 USA
24ea0364f1SPeter Tyser  */
25ea0364f1SPeter Tyser 
26ea0364f1SPeter Tyser #include <common.h>
27ea0364f1SPeter Tyser 
28ea0364f1SPeter Tyser #include <asm/timer.h>
29ea0364f1SPeter Tyser #include <asm/immap.h>
30ea0364f1SPeter Tyser #include <watchdog.h>
31ea0364f1SPeter Tyser 
32ea0364f1SPeter Tyser DECLARE_GLOBAL_DATA_PTR;
33ea0364f1SPeter Tyser 
34ea0364f1SPeter Tyser static volatile ulong timestamp = 0;
35ea0364f1SPeter Tyser 
36ea0364f1SPeter Tyser #ifndef CONFIG_SYS_WATCHDOG_FREQ
37ea0364f1SPeter Tyser #define CONFIG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
38ea0364f1SPeter Tyser #endif
39ea0364f1SPeter Tyser 
40ea0364f1SPeter Tyser #if defined(CONFIG_MCFTMR)
41ea0364f1SPeter Tyser #ifndef CONFIG_SYS_UDELAY_BASE
42ea0364f1SPeter Tyser #	error	"uDelay base not defined!"
43ea0364f1SPeter Tyser #endif
44ea0364f1SPeter Tyser 
45ea0364f1SPeter Tyser #if !defined(CONFIG_SYS_TMR_BASE) || !defined(CONFIG_SYS_INTR_BASE) || !defined(CONFIG_SYS_TMRINTR_NO) || !defined(CONFIG_SYS_TMRINTR_MASK)
46ea0364f1SPeter Tyser #	error	"TMR_BASE, INTR_BASE, TMRINTR_NO or TMRINTR_MASk not defined!"
47ea0364f1SPeter Tyser #endif
48ea0364f1SPeter Tyser extern void dtimer_intr_setup(void);
49ea0364f1SPeter Tyser 
50ea0364f1SPeter Tyser void __udelay(unsigned long usec)
51ea0364f1SPeter Tyser {
52ea0364f1SPeter Tyser 	volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_UDELAY_BASE);
53ea0364f1SPeter Tyser 	uint start, now, tmp;
54ea0364f1SPeter Tyser 
55ea0364f1SPeter Tyser 	while (usec > 0) {
56ea0364f1SPeter Tyser 		if (usec > 65000)
57ea0364f1SPeter Tyser 			tmp = 65000;
58ea0364f1SPeter Tyser 		else
59ea0364f1SPeter Tyser 			tmp = usec;
60ea0364f1SPeter Tyser 		usec = usec - tmp;
61ea0364f1SPeter Tyser 
62ea0364f1SPeter Tyser 		/* Set up TIMER 3 as timebase clock */
63ea0364f1SPeter Tyser 		timerp->tmr = DTIM_DTMR_RST_RST;
64ea0364f1SPeter Tyser 		timerp->tcn = 0;
65ea0364f1SPeter Tyser 		/* set period to 1 us */
66ea0364f1SPeter Tyser 		timerp->tmr =
67ea0364f1SPeter Tyser 		    CONFIG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 | DTIM_DTMR_FRR |
68ea0364f1SPeter Tyser 		    DTIM_DTMR_RST_EN;
69ea0364f1SPeter Tyser 
70ea0364f1SPeter Tyser 		start = now = timerp->tcn;
71ea0364f1SPeter Tyser 		while (now < start + tmp)
72ea0364f1SPeter Tyser 			now = timerp->tcn;
73ea0364f1SPeter Tyser 	}
74ea0364f1SPeter Tyser }
75ea0364f1SPeter Tyser 
76ea0364f1SPeter Tyser void dtimer_interrupt(void *not_used)
77ea0364f1SPeter Tyser {
78ea0364f1SPeter Tyser 	volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_TMR_BASE);
79ea0364f1SPeter Tyser 
80ea0364f1SPeter Tyser 	/* check for timer interrupt asserted */
81ea0364f1SPeter Tyser 	if ((CONFIG_SYS_TMRPND_REG & CONFIG_SYS_TMRINTR_MASK) == CONFIG_SYS_TMRINTR_PEND) {
82ea0364f1SPeter Tyser 		timerp->ter = (DTIM_DTER_CAP | DTIM_DTER_REF);
83ea0364f1SPeter Tyser 		timestamp++;
84ea0364f1SPeter Tyser 
85ea0364f1SPeter Tyser 		#if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG)
86ea0364f1SPeter Tyser 		if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0) {
87ea0364f1SPeter Tyser 			WATCHDOG_RESET ();
88ea0364f1SPeter Tyser 		}
89ea0364f1SPeter Tyser 		#endif    /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
90ea0364f1SPeter Tyser 		return;
91ea0364f1SPeter Tyser 	}
92ea0364f1SPeter Tyser }
93ea0364f1SPeter Tyser 
94ea0364f1SPeter Tyser void timer_init(void)
95ea0364f1SPeter Tyser {
96ea0364f1SPeter Tyser 	volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_TMR_BASE);
97ea0364f1SPeter Tyser 
98ea0364f1SPeter Tyser 	timestamp = 0;
99ea0364f1SPeter Tyser 
100ea0364f1SPeter Tyser 	timerp->tcn = 0;
101ea0364f1SPeter Tyser 	timerp->trr = 0;
102ea0364f1SPeter Tyser 
103ea0364f1SPeter Tyser 	/* Set up TIMER 4 as clock */
104ea0364f1SPeter Tyser 	timerp->tmr = DTIM_DTMR_RST_RST;
105ea0364f1SPeter Tyser 
106ea0364f1SPeter Tyser 	/* initialize and enable timer interrupt */
107ea0364f1SPeter Tyser 	irq_install_handler(CONFIG_SYS_TMRINTR_NO, dtimer_interrupt, 0);
108ea0364f1SPeter Tyser 
109ea0364f1SPeter Tyser 	timerp->tcn = 0;
110ea0364f1SPeter Tyser 	timerp->trr = 1000;	/* Interrupt every ms */
111ea0364f1SPeter Tyser 
112ea0364f1SPeter Tyser 	dtimer_intr_setup();
113ea0364f1SPeter Tyser 
114ea0364f1SPeter Tyser 	/* set a period of 1us, set timer mode to restart and enable timer and interrupt */
115ea0364f1SPeter Tyser 	timerp->tmr = CONFIG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 |
116ea0364f1SPeter Tyser 	    DTIM_DTMR_FRR | DTIM_DTMR_ORRI | DTIM_DTMR_RST_EN;
117ea0364f1SPeter Tyser }
118ea0364f1SPeter Tyser 
119ea0364f1SPeter Tyser void reset_timer(void)
120ea0364f1SPeter Tyser {
121ea0364f1SPeter Tyser 	timestamp = 0;
122ea0364f1SPeter Tyser }
123ea0364f1SPeter Tyser 
124ea0364f1SPeter Tyser ulong get_timer(ulong base)
125ea0364f1SPeter Tyser {
126ea0364f1SPeter Tyser 	return (timestamp - base);
127ea0364f1SPeter Tyser }
128ea0364f1SPeter Tyser 
129ea0364f1SPeter Tyser #endif				/* CONFIG_MCFTMR */
130ea0364f1SPeter Tyser 
131ea0364f1SPeter Tyser #if defined(CONFIG_MCFPIT)
132ea0364f1SPeter Tyser #if !defined(CONFIG_SYS_PIT_BASE)
133ea0364f1SPeter Tyser #	error	"CONFIG_SYS_PIT_BASE not defined!"
134ea0364f1SPeter Tyser #endif
135ea0364f1SPeter Tyser 
136ea0364f1SPeter Tyser static unsigned short lastinc;
137ea0364f1SPeter Tyser 
138ea0364f1SPeter Tyser void __udelay(unsigned long usec)
139ea0364f1SPeter Tyser {
140ea0364f1SPeter Tyser 	volatile pit_t *timerp = (pit_t *) (CONFIG_SYS_UDELAY_BASE);
141ea0364f1SPeter Tyser 	uint tmp;
142ea0364f1SPeter Tyser 
143ea0364f1SPeter Tyser 	while (usec > 0) {
144ea0364f1SPeter Tyser 		if (usec > 65000)
145ea0364f1SPeter Tyser 			tmp = 65000;
146ea0364f1SPeter Tyser 		else
147ea0364f1SPeter Tyser 			tmp = usec;
148ea0364f1SPeter Tyser 		usec = usec - tmp;
149ea0364f1SPeter Tyser 
150ea0364f1SPeter Tyser 		/* Set up TIMER 3 as timebase clock */
151ea0364f1SPeter Tyser 		timerp->pcsr = PIT_PCSR_OVW;
152ea0364f1SPeter Tyser 		timerp->pmr = 0;
153ea0364f1SPeter Tyser 		/* set period to 1 us */
154ea0364f1SPeter Tyser 		timerp->pcsr |= PIT_PCSR_PRE(CONFIG_SYS_PIT_PRESCALE) | PIT_PCSR_EN;
155ea0364f1SPeter Tyser 
156ea0364f1SPeter Tyser 		timerp->pmr = tmp;
157ea0364f1SPeter Tyser 		while (timerp->pcntr > 0) ;
158ea0364f1SPeter Tyser 	}
159ea0364f1SPeter Tyser }
160ea0364f1SPeter Tyser 
161ea0364f1SPeter Tyser void timer_init(void)
162ea0364f1SPeter Tyser {
163ea0364f1SPeter Tyser 	volatile pit_t *timerp = (pit_t *) (CONFIG_SYS_PIT_BASE);
164ea0364f1SPeter Tyser 	timestamp = 0;
165ea0364f1SPeter Tyser 
166ea0364f1SPeter Tyser 	/* Set up TIMER 4 as poll clock */
167ea0364f1SPeter Tyser 	timerp->pcsr = PIT_PCSR_OVW;
168ea0364f1SPeter Tyser 	timerp->pmr = lastinc = 0;
169ea0364f1SPeter Tyser 	timerp->pcsr |= PIT_PCSR_PRE(CONFIG_SYS_PIT_PRESCALE) | PIT_PCSR_EN;
170ea0364f1SPeter Tyser }
171ea0364f1SPeter Tyser 
172ea0364f1SPeter Tyser ulong get_timer(ulong base)
173ea0364f1SPeter Tyser {
174ea0364f1SPeter Tyser 	unsigned short now, diff;
175ea0364f1SPeter Tyser 	volatile pit_t *timerp = (pit_t *) (CONFIG_SYS_PIT_BASE);
176ea0364f1SPeter Tyser 
177ea0364f1SPeter Tyser 	now = timerp->pcntr;
178ea0364f1SPeter Tyser 	diff = -(now - lastinc);
179ea0364f1SPeter Tyser 
180ea0364f1SPeter Tyser 	timestamp += diff;
181ea0364f1SPeter Tyser 	lastinc = now;
182ea0364f1SPeter Tyser 	return timestamp - base;
183ea0364f1SPeter Tyser }
184ea0364f1SPeter Tyser 
185ea0364f1SPeter Tyser void wait_ticks(unsigned long ticks)
186ea0364f1SPeter Tyser {
187*5c8404afSGraeme Russ 	u32 start = get_timer(0);
188*5c8404afSGraeme Russ 	while (get_timer(start) < ticks) ;
189ea0364f1SPeter Tyser }
190ea0364f1SPeter Tyser #endif				/* CONFIG_MCFPIT */
191ea0364f1SPeter Tyser 
192ea0364f1SPeter Tyser /*
193ea0364f1SPeter Tyser  * This function is derived from PowerPC code (read timebase as long long).
194ea0364f1SPeter Tyser  * On M68K it just returns the timer value.
195ea0364f1SPeter Tyser  */
196ea0364f1SPeter Tyser unsigned long long get_ticks(void)
197ea0364f1SPeter Tyser {
198ea0364f1SPeter Tyser 	return get_timer(0);
199ea0364f1SPeter Tyser }
200ea0364f1SPeter Tyser 
201ea0364f1SPeter Tyser unsigned long usec2ticks(unsigned long usec)
202ea0364f1SPeter Tyser {
203ea0364f1SPeter Tyser 	return get_timer(usec);
204ea0364f1SPeter Tyser }
205ea0364f1SPeter Tyser 
206ea0364f1SPeter Tyser /*
207ea0364f1SPeter Tyser  * This function is derived from PowerPC code (timebase clock frequency).
208ea0364f1SPeter Tyser  * On M68K it returns the number of timer ticks per second.
209ea0364f1SPeter Tyser  */
210ea0364f1SPeter Tyser ulong get_tbclk(void)
211ea0364f1SPeter Tyser {
212ea0364f1SPeter Tyser 	ulong tbclk;
213ea0364f1SPeter Tyser 	tbclk = CONFIG_SYS_HZ;
214ea0364f1SPeter Tyser 	return tbclk;
215ea0364f1SPeter Tyser }
216