aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/cpu/arm926ejs/rda/timer.c
blob: a54081b7b2c0521507c47a5635308ab919bf0ced (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <common.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/rda_iomap.h>

DECLARE_GLOBAL_DATA_PTR;

typedef volatile struct
{
    REG32                          OSTimer_Ctrl;                 //0x00000000
    REG32                          OSTimer_CurVal;               //0x00000004
    REG32                          WDTimer_Ctrl;                 //0x00000008
    REG32                          WDTimer_LoadVal;              //0x0000000C
    REG32                          HWTimer_Ctrl;                 //0x00000010
    REG32                          HWTimer_CurVal;               //0x00000014
    REG32                          Timer_Irq_Mask_Set;           //0x00000018
    REG32                          Timer_Irq_Mask_Clr;           //0x0000001C
    REG32                          Timer_Irq_Clr;                //0x00000020
    REG32                          Timer_Irq_Cause;              //0x00000024
} HWP_TIMER_T;

#define hwp_timer                   ((HWP_TIMER_T*)(RDA_TIMER_BASE))

int timer_init(void)
{
	gd->timer_rate_hz = CONFIG_SYS_HZ_CLOCK;
	gd->timer_reset_value = 0;

	/* We are using timer34 in unchained 32-bit mode, full speed */
	return(0);
}

void reset_timer(void)
{
	gd->timer_reset_value = get_ticks();
}

/*
 * Get the current 64 bit timer tick count
 */
unsigned long long get_ticks(void)
{
	unsigned long now = hwp_timer->HWTimer_CurVal;

	/* increment tbu if tbl has rolled over */
	if (now < gd->tbl)
		gd->tbu++;
	gd->tbl = now;

	return (((unsigned long long)gd->tbu) << 32) | gd->tbl;
}

ulong get_timer(ulong base)
{
	unsigned long long timer_diff;

	timer_diff = get_ticks() - gd->timer_reset_value;

	return (timer_diff / (gd->timer_rate_hz / CONFIG_SYS_HZ)) - base;
}

#pragma GCC push_options
#pragma GCC optimize ("O0")

void __udelay(unsigned long usec)
{
#if 0 /* our timer is 16kHz, can NOT support udelay */
	unsigned long long endtime;

	endtime = ((unsigned long long)usec * gd->timer_rate_hz) / 1000000UL;
	endtime += get_ticks();

	while (get_ticks() < endtime)
		;
#else /* use loop instead */
#define USEC_LOOP (1)
	int i, j;
	for (i=0;i<(usec);i++)
		for (j=0;j<USEC_LOOP;j++)
			;
#endif
}

#pragma GCC pop_options

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