timer.c 2.42 KB
Newer Older
1
/*
2
3
 * (C) Copyright 2010,2011
 * Sergei Poselenov, Emcraft Systems, sposelenov@emcraft.com
4
5
6
7
8
9
10
11
12
13
14
15
16
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19
20
 */
#include <common.h>

21
22
23
24
/* Internal tick units */
static unsigned long long timestamp;	/* Monotonic incrementing timer */
static ulong              lastdec;	/* Last decrementer snapshot */

25
int timer_init()
26
{
27
28
29
30
31
32
33
34
	volatile struct cm3_systick *systick =
		(volatile struct cm3_systick *)CM3_SYSTICK_BASE;

	systick->load = CM3_SYSTICK_LOAD_RELOAD_MSK - 1;
	systick->val = 0;
	/* Use external clock, no ints */
	systick->ctrl = CM3_SYSTICK_CTRL_EN;
	timestamp = 0;
35
36
37
38

	return 0;
}

39
ulong get_timer(ulong base)
40
{
41
42
43
	volatile struct cm3_systick *systick =
		(volatile struct cm3_systick *)CM3_SYSTICK_BASE;
	ulong now = systick->val;
44

45
46
47
48
49
50
51
	if (lastdec >= now)
		timestamp += lastdec - now;
	else
		timestamp += lastdec + CM3_SYSTICK_LOAD_RELOAD_MSK - 1 - now;

	lastdec = now;

52
	return timestamp / (clock_get(CLOCK_SYSTICK) / CONFIG_SYS_HZ) - base;
53
54
55
56
}

void reset_timer(void)
{
57
58
59
60
	volatile struct cm3_systick *systick =
		(volatile struct cm3_systick *)(CM3_SYSTICK_BASE);
	lastdec = systick->val;
	timestamp = 0;
61
62
}

63
64
/* delay x useconds */
void __udelay(ulong usec)
65
{
66
67
68
69
70
	ulong clc, tmp;
	volatile struct cm3_systick *systick =
		(volatile struct cm3_systick *)(CM3_SYSTICK_BASE);


71
	clc = usec * (clock_get(CLOCK_SYSTICK) / 1000000);
72
73
74
75
76
77
78
79
80
81
82
83

	/* get current timestamp */
	tmp = systick->val;

	if (tmp < clc) {
		/* loop till event */
		while (systick->val < tmp ||
			   systick->val > (CM3_SYSTICK_LOAD_RELOAD_MSK - 1 -
				clc + tmp)) ;	/* nop */
	} else {
		while (systick->val > (tmp - clc)) ;
	}
84
85
86
87
88
89
}

/*
 * This function is derived from PowerPC code (timebase clock frequency).
 * On ARM it returns the number of timer ticks per second.
 */
90
ulong get_tbclk(void)
91
{
92
	return clock_get(CLOCK_SYSTICK);
93
}