xref: /OK3568_Linux_fs/u-boot/arch/arm/mach-davinci/timer.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2003
3*4882a593Smuzhiyun  * Texas Instruments <www.ti.com>
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * (C) Copyright 2002
6*4882a593Smuzhiyun  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
7*4882a593Smuzhiyun  * Marius Groeger <mgroeger@sysgo.de>
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * (C) Copyright 2002
10*4882a593Smuzhiyun  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
11*4882a593Smuzhiyun  * Alex Zuepke <azu@sysgo.de>
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * (C) Copyright 2002-2004
14*4882a593Smuzhiyun  * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * (C) Copyright 2004
17*4882a593Smuzhiyun  * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
18*4882a593Smuzhiyun  *
19*4882a593Smuzhiyun  * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
22*4882a593Smuzhiyun  */
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #include <common.h>
25*4882a593Smuzhiyun #include <asm/io.h>
26*4882a593Smuzhiyun #include <asm/arch/timer_defs.h>
27*4882a593Smuzhiyun #include <div64.h>
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun static struct davinci_timer * const timer =
32*4882a593Smuzhiyun 	(struct davinci_timer *)CONFIG_SYS_TIMERBASE;
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define TIMER_LOAD_VAL	0xffffffff
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #define TIM_CLK_DIV	16
37*4882a593Smuzhiyun 
timer_init(void)38*4882a593Smuzhiyun int timer_init(void)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun 	/* We are using timer34 in unchained 32-bit mode, full speed */
41*4882a593Smuzhiyun 	writel(0x0, &timer->tcr);
42*4882a593Smuzhiyun 	writel(0x0, &timer->tgcr);
43*4882a593Smuzhiyun 	writel(0x06 | ((TIM_CLK_DIV - 1) << 8), &timer->tgcr);
44*4882a593Smuzhiyun 	writel(0x0, &timer->tim34);
45*4882a593Smuzhiyun 	writel(TIMER_LOAD_VAL, &timer->prd34);
46*4882a593Smuzhiyun 	writel(2 << 22, &timer->tcr);
47*4882a593Smuzhiyun 	gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK / TIM_CLK_DIV;
48*4882a593Smuzhiyun 	gd->arch.timer_reset_value = 0;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	return(0);
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun /*
54*4882a593Smuzhiyun  * Get the current 64 bit timer tick count
55*4882a593Smuzhiyun  */
get_ticks(void)56*4882a593Smuzhiyun unsigned long long get_ticks(void)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun 	unsigned long now = readl(&timer->tim34);
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	/* increment tbu if tbl has rolled over */
61*4882a593Smuzhiyun 	if (now < gd->arch.tbl)
62*4882a593Smuzhiyun 		gd->arch.tbu++;
63*4882a593Smuzhiyun 	gd->arch.tbl = now;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun 
get_timer(ulong base)68*4882a593Smuzhiyun ulong get_timer(ulong base)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	unsigned long long timer_diff;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	timer_diff = get_ticks() - gd->arch.timer_reset_value;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	return lldiv(timer_diff,
75*4882a593Smuzhiyun 		     (gd->arch.timer_rate_hz / CONFIG_SYS_HZ)) - base;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun 
__udelay(unsigned long usec)78*4882a593Smuzhiyun void __udelay(unsigned long usec)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun 	unsigned long long endtime;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	endtime = lldiv((unsigned long long)usec * gd->arch.timer_rate_hz,
83*4882a593Smuzhiyun 			1000000UL);
84*4882a593Smuzhiyun 	endtime += get_ticks();
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	while (get_ticks() < endtime)
87*4882a593Smuzhiyun 		;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun /*
91*4882a593Smuzhiyun  * This function is derived from PowerPC code (timebase clock frequency).
92*4882a593Smuzhiyun  * On ARM it returns the number of timer ticks per second.
93*4882a593Smuzhiyun  */
get_tbclk(void)94*4882a593Smuzhiyun ulong get_tbclk(void)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	return gd->arch.timer_rate_hz;
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun #ifdef CONFIG_HW_WATCHDOG
100*4882a593Smuzhiyun static struct davinci_timer * const wdttimer =
101*4882a593Smuzhiyun 	(struct davinci_timer *)CONFIG_SYS_WDTTIMERBASE;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun /*
104*4882a593Smuzhiyun  * See prufw2.pdf for using Timer as a WDT
105*4882a593Smuzhiyun  */
davinci_hw_watchdog_enable(void)106*4882a593Smuzhiyun void davinci_hw_watchdog_enable(void)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun 	writel(0x0, &wdttimer->tcr);
109*4882a593Smuzhiyun 	writel(0x0, &wdttimer->tgcr);
110*4882a593Smuzhiyun 	/* TIMMODE = 2h */
111*4882a593Smuzhiyun 	writel(0x08 | 0x03 | ((TIM_CLK_DIV - 1) << 8), &wdttimer->tgcr);
112*4882a593Smuzhiyun 	writel(CONFIG_SYS_WDT_PERIOD_LOW, &wdttimer->prd12);
113*4882a593Smuzhiyun 	writel(CONFIG_SYS_WDT_PERIOD_HIGH, &wdttimer->prd34);
114*4882a593Smuzhiyun 	writel(2 << 22, &wdttimer->tcr);
115*4882a593Smuzhiyun 	writel(0x0, &wdttimer->tim12);
116*4882a593Smuzhiyun 	writel(0x0, &wdttimer->tim34);
117*4882a593Smuzhiyun 	/* set WDEN bit, WDKEY 0xa5c6 */
118*4882a593Smuzhiyun 	writel(0xa5c64000, &wdttimer->wdtcr);
119*4882a593Smuzhiyun 	/* clear counter register */
120*4882a593Smuzhiyun 	writel(0xda7e4000, &wdttimer->wdtcr);
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun 
davinci_hw_watchdog_reset(void)123*4882a593Smuzhiyun void davinci_hw_watchdog_reset(void)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun 	writel(0xa5c64000, &wdttimer->wdtcr);
126*4882a593Smuzhiyun 	writel(0xda7e4000, &wdttimer->wdtcr);
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun #endif
129