xref: /rk3399_rockchip-uboot/arch/sh/lib/time.c (revision 78df8c68cd42c9db3601b331018b82e9627d08ce)
1ea0364f1SPeter Tyser /*
2ea0364f1SPeter Tyser  * (C) Copyright 2009
3ea0364f1SPeter Tyser  * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
4ea0364f1SPeter Tyser  *
561973afcSNobuhiro Iwamatsu  * (C) Copyright 2007-2010
6ea0364f1SPeter Tyser  * Nobobuhiro Iwamatsu <iwamatsu@nigauri.org>
7ea0364f1SPeter Tyser  *
8ea0364f1SPeter Tyser  * (C) Copyright 2003
9ea0364f1SPeter Tyser  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
10ea0364f1SPeter Tyser  *
11ea0364f1SPeter Tyser  * See file CREDITS for list of people who contributed to this
12ea0364f1SPeter Tyser  * project.
13ea0364f1SPeter Tyser  *
14ea0364f1SPeter Tyser  * This program is free software; you can redistribute it and/or
15ea0364f1SPeter Tyser  * modify it under the terms of the GNU General Public License as
16ea0364f1SPeter Tyser  * published by the Free Software Foundation; either version 2 of
17ea0364f1SPeter Tyser  * the License, or (at your option) any later version.
18ea0364f1SPeter Tyser  *
19ea0364f1SPeter Tyser  * This program is distributed in the hope that it will be useful,
20ea0364f1SPeter Tyser  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21ea0364f1SPeter Tyser  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22ea0364f1SPeter Tyser  * GNU General Public License for more details.
23ea0364f1SPeter Tyser  *
24ea0364f1SPeter Tyser  * You should have received a copy of the GNU General Public License
25ea0364f1SPeter Tyser  * along with this program; if not, write to the Free Software
26ea0364f1SPeter Tyser  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27ea0364f1SPeter Tyser  * MA 02111-1307 USA
28ea0364f1SPeter Tyser  */
29ea0364f1SPeter Tyser 
30ea0364f1SPeter Tyser #include <common.h>
31ea0364f1SPeter Tyser #include <div64.h>
32ea0364f1SPeter Tyser #include <asm/processor.h>
33ea0364f1SPeter Tyser #include <asm/clk.h>
34ea0364f1SPeter Tyser #include <asm/io.h>
35ea0364f1SPeter Tyser 
36ea0364f1SPeter Tyser #define TMU_MAX_COUNTER (~0UL)
37ea0364f1SPeter Tyser 
38ea0364f1SPeter Tyser static ulong timer_freq;
3961973afcSNobuhiro Iwamatsu static unsigned long last_tcnt;
4061973afcSNobuhiro Iwamatsu static unsigned long long overflow_ticks;
41ea0364f1SPeter Tyser 
42ea0364f1SPeter Tyser static inline unsigned long long tick_to_time(unsigned long long tick)
43ea0364f1SPeter Tyser {
44ea0364f1SPeter Tyser 	tick *= CONFIG_SYS_HZ;
45ea0364f1SPeter Tyser 	do_div(tick, timer_freq);
46ea0364f1SPeter Tyser 
47ea0364f1SPeter Tyser 	return tick;
48ea0364f1SPeter Tyser }
49ea0364f1SPeter Tyser 
50ea0364f1SPeter Tyser static inline unsigned long long usec_to_tick(unsigned long long usec)
51ea0364f1SPeter Tyser {
52ea0364f1SPeter Tyser 	usec *= timer_freq;
53ea0364f1SPeter Tyser 	do_div(usec, 1000000);
54ea0364f1SPeter Tyser 
55ea0364f1SPeter Tyser 	return usec;
56ea0364f1SPeter Tyser }
57ea0364f1SPeter Tyser 
58ea0364f1SPeter Tyser static void tmu_timer_start (unsigned int timer)
59ea0364f1SPeter Tyser {
60ea0364f1SPeter Tyser 	if (timer > 2)
61ea0364f1SPeter Tyser 		return;
62ea0364f1SPeter Tyser 	writeb(readb(TSTR) | (1 << timer), TSTR);
63ea0364f1SPeter Tyser }
64ea0364f1SPeter Tyser 
65ea0364f1SPeter Tyser static void tmu_timer_stop (unsigned int timer)
66ea0364f1SPeter Tyser {
67ea0364f1SPeter Tyser 	if (timer > 2)
68ea0364f1SPeter Tyser 		return;
69ea0364f1SPeter Tyser 	writeb(readb(TSTR) & ~(1 << timer), TSTR);
70ea0364f1SPeter Tyser }
71ea0364f1SPeter Tyser 
72ea0364f1SPeter Tyser int timer_init (void)
73ea0364f1SPeter Tyser {
74ea0364f1SPeter Tyser 	/* Divide clock by CONFIG_SYS_TMU_CLK_DIV */
75ea0364f1SPeter Tyser 	u16 bit = 0;
76ea0364f1SPeter Tyser 
77ea0364f1SPeter Tyser 	switch (CONFIG_SYS_TMU_CLK_DIV) {
78ea0364f1SPeter Tyser 	case 1024:
79ea0364f1SPeter Tyser 		bit = 4;
80ea0364f1SPeter Tyser 		break;
81ea0364f1SPeter Tyser 	case 256:
82ea0364f1SPeter Tyser 		bit = 3;
83ea0364f1SPeter Tyser 		break;
84ea0364f1SPeter Tyser 	case 64:
85ea0364f1SPeter Tyser 		bit = 2;
86ea0364f1SPeter Tyser 		break;
87ea0364f1SPeter Tyser 	case 16:
88ea0364f1SPeter Tyser 		bit = 1;
89ea0364f1SPeter Tyser 		break;
90ea0364f1SPeter Tyser 	case 4:
91ea0364f1SPeter Tyser 	default:
92ea0364f1SPeter Tyser 		break;
93ea0364f1SPeter Tyser 	}
94ea0364f1SPeter Tyser 	writew(readw(TCR0) | bit, TCR0);
95ea0364f1SPeter Tyser 
96ea0364f1SPeter Tyser 	/* Calc clock rate */
97ea0364f1SPeter Tyser 	timer_freq = get_tmu0_clk_rate() >> ((bit + 1) * 2);
98ea0364f1SPeter Tyser 
99ea0364f1SPeter Tyser 	tmu_timer_stop(0);
100ea0364f1SPeter Tyser 	tmu_timer_start(0);
101ea0364f1SPeter Tyser 
10261973afcSNobuhiro Iwamatsu 	last_tcnt = 0;
10361973afcSNobuhiro Iwamatsu 	overflow_ticks = 0;
10461973afcSNobuhiro Iwamatsu 
105ea0364f1SPeter Tyser 	return 0;
106ea0364f1SPeter Tyser }
107ea0364f1SPeter Tyser 
108ea0364f1SPeter Tyser unsigned long long get_ticks (void)
109ea0364f1SPeter Tyser {
11061973afcSNobuhiro Iwamatsu 	unsigned long tcnt = 0 - readl(TCNT0);
11161973afcSNobuhiro Iwamatsu 
112*78df8c68SNobuhiro Iwamatsu 	if (last_tcnt > tcnt) /* overflow */
11361973afcSNobuhiro Iwamatsu 		overflow_ticks++;
11461973afcSNobuhiro Iwamatsu 	last_tcnt = tcnt;
11561973afcSNobuhiro Iwamatsu 
11661973afcSNobuhiro Iwamatsu 	return (overflow_ticks << 32) | tcnt;
117ea0364f1SPeter Tyser }
118ea0364f1SPeter Tyser 
119ea0364f1SPeter Tyser void __udelay (unsigned long usec)
120ea0364f1SPeter Tyser {
121ea0364f1SPeter Tyser 	unsigned long long tmp;
122ea0364f1SPeter Tyser 	ulong tmo;
123ea0364f1SPeter Tyser 
124ea0364f1SPeter Tyser 	tmo = usec_to_tick(usec);
125ea0364f1SPeter Tyser 	tmp = get_ticks() + tmo;	/* get current timestamp */
126ea0364f1SPeter Tyser 
127ea0364f1SPeter Tyser 	while (get_ticks() < tmp)	/* loop till event */
128ea0364f1SPeter Tyser 		 /*NOP*/;
129ea0364f1SPeter Tyser }
130ea0364f1SPeter Tyser 
131ea0364f1SPeter Tyser unsigned long get_timer (unsigned long base)
132ea0364f1SPeter Tyser {
133ea0364f1SPeter Tyser 	/* return msec */
134ea0364f1SPeter Tyser 	return tick_to_time(get_ticks()) - base;
135ea0364f1SPeter Tyser }
136ea0364f1SPeter Tyser 
137ea0364f1SPeter Tyser unsigned long get_tbclk (void)
138ea0364f1SPeter Tyser {
139ea0364f1SPeter Tyser 	return timer_freq;
140ea0364f1SPeter Tyser }
141