xref: /rk3399_rockchip-uboot/arch/arm/mach-orion5x/timer.c (revision b9cb64825b5e6efeb715abd8b48d9b12f98973e9)
1*3e93b4e6SMasahiro Yamada /*
2*3e93b4e6SMasahiro Yamada   * Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net>
3*3e93b4e6SMasahiro Yamada  *
4*3e93b4e6SMasahiro Yamada  * Based on original Kirkwood support which is
5*3e93b4e6SMasahiro Yamada  * Copyright (C) Marvell International Ltd. and its affiliates
6*3e93b4e6SMasahiro Yamada  * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
7*3e93b4e6SMasahiro Yamada  *
8*3e93b4e6SMasahiro Yamada  * SPDX-License-Identifier:	GPL-2.0+
9*3e93b4e6SMasahiro Yamada  */
10*3e93b4e6SMasahiro Yamada 
11*3e93b4e6SMasahiro Yamada #include <common.h>
12*3e93b4e6SMasahiro Yamada #include <asm/io.h>
13*3e93b4e6SMasahiro Yamada 
14*3e93b4e6SMasahiro Yamada #define UBOOT_CNTR	0	/* counter to use for uboot timer */
15*3e93b4e6SMasahiro Yamada 
16*3e93b4e6SMasahiro Yamada /* Timer reload and current value registers */
17*3e93b4e6SMasahiro Yamada struct orion5x_tmr_val {
18*3e93b4e6SMasahiro Yamada 	u32 reload;	/* Timer reload reg */
19*3e93b4e6SMasahiro Yamada 	u32 val;	/* Timer value reg */
20*3e93b4e6SMasahiro Yamada };
21*3e93b4e6SMasahiro Yamada 
22*3e93b4e6SMasahiro Yamada /* Timer registers */
23*3e93b4e6SMasahiro Yamada struct orion5x_tmr_registers {
24*3e93b4e6SMasahiro Yamada 	u32 ctrl;	/* Timer control reg */
25*3e93b4e6SMasahiro Yamada 	u32 pad[3];
26*3e93b4e6SMasahiro Yamada 	struct orion5x_tmr_val tmr[2];
27*3e93b4e6SMasahiro Yamada 	u32 wdt_reload;
28*3e93b4e6SMasahiro Yamada 	u32 wdt_val;
29*3e93b4e6SMasahiro Yamada };
30*3e93b4e6SMasahiro Yamada 
31*3e93b4e6SMasahiro Yamada struct orion5x_tmr_registers *orion5x_tmr_regs =
32*3e93b4e6SMasahiro Yamada 	(struct orion5x_tmr_registers *)ORION5X_TIMER_BASE;
33*3e93b4e6SMasahiro Yamada 
34*3e93b4e6SMasahiro Yamada /*
35*3e93b4e6SMasahiro Yamada  * ARM Timers Registers Map
36*3e93b4e6SMasahiro Yamada  */
37*3e93b4e6SMasahiro Yamada #define CNTMR_CTRL_REG			(&orion5x_tmr_regs->ctrl)
38*3e93b4e6SMasahiro Yamada #define CNTMR_RELOAD_REG(tmrnum)	(&orion5x_tmr_regs->tmr[tmrnum].reload)
39*3e93b4e6SMasahiro Yamada #define CNTMR_VAL_REG(tmrnum)		(&orion5x_tmr_regs->tmr[tmrnum].val)
40*3e93b4e6SMasahiro Yamada 
41*3e93b4e6SMasahiro Yamada /*
42*3e93b4e6SMasahiro Yamada  * ARM Timers Control Register
43*3e93b4e6SMasahiro Yamada  * CPU_TIMERS_CTRL_REG (CTCR)
44*3e93b4e6SMasahiro Yamada  */
45*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_EN_OFFS(cntr)	(cntr * 2)
46*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_EN_MASK(cntr)	(1 << CTCR_ARM_TIMER_EN_OFFS)
47*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_EN(cntr)		(1 << CTCR_ARM_TIMER_EN_OFFS(cntr))
48*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_DIS(cntr)	(0 << CTCR_ARM_TIMER_EN_OFFS(cntr))
49*3e93b4e6SMasahiro Yamada 
50*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_AUTO_OFFS(cntr)	((cntr * 2) + 1)
51*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_AUTO_MASK(cntr)	(1 << 1)
52*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_AUTO_EN(cntr)	(1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr))
53*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_AUTO_DIS(cntr)	(0 << CTCR_ARM_TIMER_AUTO_OFFS(cntr))
54*3e93b4e6SMasahiro Yamada 
55*3e93b4e6SMasahiro Yamada /*
56*3e93b4e6SMasahiro Yamada  * ARM Timer\Watchdog Reload Register
57*3e93b4e6SMasahiro Yamada  * CNTMR_RELOAD_REG (TRR)
58*3e93b4e6SMasahiro Yamada  */
59*3e93b4e6SMasahiro Yamada #define TRG_ARM_TIMER_REL_OFFS		0
60*3e93b4e6SMasahiro Yamada #define TRG_ARM_TIMER_REL_MASK		0xffffffff
61*3e93b4e6SMasahiro Yamada 
62*3e93b4e6SMasahiro Yamada /*
63*3e93b4e6SMasahiro Yamada  * ARM Timer\Watchdog Register
64*3e93b4e6SMasahiro Yamada  * CNTMR_VAL_REG (TVRG)
65*3e93b4e6SMasahiro Yamada  */
66*3e93b4e6SMasahiro Yamada #define TVR_ARM_TIMER_OFFS		0
67*3e93b4e6SMasahiro Yamada #define TVR_ARM_TIMER_MASK		0xffffffff
68*3e93b4e6SMasahiro Yamada #define TVR_ARM_TIMER_MAX		0xffffffff
69*3e93b4e6SMasahiro Yamada #define TIMER_LOAD_VAL 			0xffffffff
70*3e93b4e6SMasahiro Yamada 
read_timer(void)71*3e93b4e6SMasahiro Yamada static inline ulong read_timer(void)
72*3e93b4e6SMasahiro Yamada {
73*3e93b4e6SMasahiro Yamada 	return readl(CNTMR_VAL_REG(UBOOT_CNTR))
74*3e93b4e6SMasahiro Yamada 	      / (CONFIG_SYS_TCLK / 1000);
75*3e93b4e6SMasahiro Yamada }
76*3e93b4e6SMasahiro Yamada 
77*3e93b4e6SMasahiro Yamada DECLARE_GLOBAL_DATA_PTR;
78*3e93b4e6SMasahiro Yamada 
79*3e93b4e6SMasahiro Yamada #define timestamp gd->arch.tbl
80*3e93b4e6SMasahiro Yamada #define lastdec gd->arch.lastinc
81*3e93b4e6SMasahiro Yamada 
get_timer_masked(void)82*3e93b4e6SMasahiro Yamada ulong get_timer_masked(void)
83*3e93b4e6SMasahiro Yamada {
84*3e93b4e6SMasahiro Yamada 	ulong now = read_timer();
85*3e93b4e6SMasahiro Yamada 
86*3e93b4e6SMasahiro Yamada 	if (lastdec >= now) {
87*3e93b4e6SMasahiro Yamada 		/* normal mode */
88*3e93b4e6SMasahiro Yamada 		timestamp += lastdec - now;
89*3e93b4e6SMasahiro Yamada 	} else {
90*3e93b4e6SMasahiro Yamada 		/* we have an overflow ... */
91*3e93b4e6SMasahiro Yamada 		timestamp += lastdec +
92*3e93b4e6SMasahiro Yamada 			(TIMER_LOAD_VAL / (CONFIG_SYS_TCLK / 1000)) - now;
93*3e93b4e6SMasahiro Yamada 	}
94*3e93b4e6SMasahiro Yamada 	lastdec = now;
95*3e93b4e6SMasahiro Yamada 
96*3e93b4e6SMasahiro Yamada 	return timestamp;
97*3e93b4e6SMasahiro Yamada }
98*3e93b4e6SMasahiro Yamada 
get_timer(ulong base)99*3e93b4e6SMasahiro Yamada ulong get_timer(ulong base)
100*3e93b4e6SMasahiro Yamada {
101*3e93b4e6SMasahiro Yamada 	return get_timer_masked() - base;
102*3e93b4e6SMasahiro Yamada }
103*3e93b4e6SMasahiro Yamada 
uboot_cntr_val(void)104*3e93b4e6SMasahiro Yamada static inline ulong uboot_cntr_val(void)
105*3e93b4e6SMasahiro Yamada {
106*3e93b4e6SMasahiro Yamada 	return readl(CNTMR_VAL_REG(UBOOT_CNTR));
107*3e93b4e6SMasahiro Yamada }
108*3e93b4e6SMasahiro Yamada 
__udelay(unsigned long usec)109*3e93b4e6SMasahiro Yamada void __udelay(unsigned long usec)
110*3e93b4e6SMasahiro Yamada {
111*3e93b4e6SMasahiro Yamada 	uint current;
112*3e93b4e6SMasahiro Yamada 	ulong delayticks;
113*3e93b4e6SMasahiro Yamada 
114*3e93b4e6SMasahiro Yamada 	current = uboot_cntr_val();
115*3e93b4e6SMasahiro Yamada 	delayticks = (usec * (CONFIG_SYS_TCLK / 1000000));
116*3e93b4e6SMasahiro Yamada 
117*3e93b4e6SMasahiro Yamada 	if (current < delayticks) {
118*3e93b4e6SMasahiro Yamada 		delayticks -= current;
119*3e93b4e6SMasahiro Yamada 		while (uboot_cntr_val() < current)
120*3e93b4e6SMasahiro Yamada 			;
121*3e93b4e6SMasahiro Yamada 		while ((TIMER_LOAD_VAL - delayticks) < uboot_cntr_val())
122*3e93b4e6SMasahiro Yamada 			;
123*3e93b4e6SMasahiro Yamada 	} else {
124*3e93b4e6SMasahiro Yamada 		while (uboot_cntr_val() > (current - delayticks))
125*3e93b4e6SMasahiro Yamada 			;
126*3e93b4e6SMasahiro Yamada 	}
127*3e93b4e6SMasahiro Yamada }
128*3e93b4e6SMasahiro Yamada 
129*3e93b4e6SMasahiro Yamada /*
130*3e93b4e6SMasahiro Yamada  * init the counter
131*3e93b4e6SMasahiro Yamada  */
timer_init(void)132*3e93b4e6SMasahiro Yamada int timer_init(void)
133*3e93b4e6SMasahiro Yamada {
134*3e93b4e6SMasahiro Yamada 	unsigned int cntmrctrl;
135*3e93b4e6SMasahiro Yamada 
136*3e93b4e6SMasahiro Yamada 	/* load value into timer */
137*3e93b4e6SMasahiro Yamada 	writel(TIMER_LOAD_VAL, CNTMR_RELOAD_REG(UBOOT_CNTR));
138*3e93b4e6SMasahiro Yamada 	writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR));
139*3e93b4e6SMasahiro Yamada 
140*3e93b4e6SMasahiro Yamada 	/* enable timer in auto reload mode */
141*3e93b4e6SMasahiro Yamada 	cntmrctrl = readl(CNTMR_CTRL_REG);
142*3e93b4e6SMasahiro Yamada 	cntmrctrl |= CTCR_ARM_TIMER_EN(UBOOT_CNTR);
143*3e93b4e6SMasahiro Yamada 	cntmrctrl |= CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR);
144*3e93b4e6SMasahiro Yamada 	writel(cntmrctrl, CNTMR_CTRL_REG);
145*3e93b4e6SMasahiro Yamada 	return 0;
146*3e93b4e6SMasahiro Yamada }
147*3e93b4e6SMasahiro Yamada 
timer_init_r(void)148*3e93b4e6SMasahiro Yamada void timer_init_r(void)
149*3e93b4e6SMasahiro Yamada {
150*3e93b4e6SMasahiro Yamada 	/* init the timestamp and lastdec value */
151*3e93b4e6SMasahiro Yamada 	lastdec = read_timer();
152*3e93b4e6SMasahiro Yamada 	timestamp = 0;
153*3e93b4e6SMasahiro Yamada }
154*3e93b4e6SMasahiro Yamada 
155*3e93b4e6SMasahiro Yamada /*
156*3e93b4e6SMasahiro Yamada  * This function is derived from PowerPC code (read timebase as long long).
157*3e93b4e6SMasahiro Yamada  * On ARM it just returns the timer value.
158*3e93b4e6SMasahiro Yamada  */
get_ticks(void)159*3e93b4e6SMasahiro Yamada unsigned long long get_ticks(void)
160*3e93b4e6SMasahiro Yamada {
161*3e93b4e6SMasahiro Yamada 	return get_timer(0);
162*3e93b4e6SMasahiro Yamada }
163*3e93b4e6SMasahiro Yamada 
164*3e93b4e6SMasahiro Yamada /*
165*3e93b4e6SMasahiro Yamada  * This function is derived from PowerPC code (timebase clock frequency).
166*3e93b4e6SMasahiro Yamada  * On ARM it returns the number of timer ticks per second.
167*3e93b4e6SMasahiro Yamada  */
get_tbclk(void)168*3e93b4e6SMasahiro Yamada ulong get_tbclk (void)
169*3e93b4e6SMasahiro Yamada {
170*3e93b4e6SMasahiro Yamada 	return (ulong)CONFIG_SYS_HZ;
171*3e93b4e6SMasahiro Yamada }
172