xref: /rk3399_rockchip-uboot/arch/sh/lib/time.c (revision 861bd4bcf7e7eba165b42e79cea005486851d69b)
1ea0364f1SPeter Tyser /*
2ea0364f1SPeter Tyser  * (C) Copyright 2009
3ea0364f1SPeter Tyser  * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
4ea0364f1SPeter Tyser  *
573f35e0bSNobuhiro Iwamatsu  * (C) Copyright 2007-2012
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  *
111a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
12ea0364f1SPeter Tyser  */
13ea0364f1SPeter Tyser 
14ea0364f1SPeter Tyser #include <common.h>
15ea0364f1SPeter Tyser #include <div64.h>
16ea0364f1SPeter Tyser #include <asm/processor.h>
17ea0364f1SPeter Tyser #include <asm/io.h>
1873f35e0bSNobuhiro Iwamatsu #include <sh_tmu.h>
1973f35e0bSNobuhiro Iwamatsu 
20*861bd4bcSNobuhiro Iwamatsu #define TCR_TPSC 0x07
21*861bd4bcSNobuhiro Iwamatsu 
2273f35e0bSNobuhiro Iwamatsu static struct tmu_regs *tmu = (struct tmu_regs *)TMU_BASE;
23ea0364f1SPeter Tyser 
24d4430426SNobuhiro Iwamatsu static u16 bit;
2561973afcSNobuhiro Iwamatsu static unsigned long last_tcnt;
2661973afcSNobuhiro Iwamatsu static unsigned long long overflow_ticks;
27ea0364f1SPeter Tyser 
28d4430426SNobuhiro Iwamatsu unsigned long get_tbclk(void)
29d4430426SNobuhiro Iwamatsu {
30d4430426SNobuhiro Iwamatsu 	return get_tmu0_clk_rate() >> ((bit + 1) * 2);
31d4430426SNobuhiro Iwamatsu }
32d4430426SNobuhiro Iwamatsu 
33ea0364f1SPeter Tyser static inline unsigned long long tick_to_time(unsigned long long tick)
34ea0364f1SPeter Tyser {
35ea0364f1SPeter Tyser 	tick *= CONFIG_SYS_HZ;
36d4430426SNobuhiro Iwamatsu 	do_div(tick, get_tbclk());
37ea0364f1SPeter Tyser 
38ea0364f1SPeter Tyser 	return tick;
39ea0364f1SPeter Tyser }
40ea0364f1SPeter Tyser 
41ea0364f1SPeter Tyser static inline unsigned long long usec_to_tick(unsigned long long usec)
42ea0364f1SPeter Tyser {
43d4430426SNobuhiro Iwamatsu 	usec *= get_tbclk();
44ea0364f1SPeter Tyser 	do_div(usec, 1000000);
45ea0364f1SPeter Tyser 
46ea0364f1SPeter Tyser 	return usec;
47ea0364f1SPeter Tyser }
48ea0364f1SPeter Tyser 
49ea0364f1SPeter Tyser static void tmu_timer_start(unsigned int timer)
50ea0364f1SPeter Tyser {
51ea0364f1SPeter Tyser 	if (timer > 2)
52ea0364f1SPeter Tyser 		return;
5373f35e0bSNobuhiro Iwamatsu 	writeb(readb(&tmu->tstr) | (1 << timer), &tmu->tstr);
54ea0364f1SPeter Tyser }
55ea0364f1SPeter Tyser 
56ea0364f1SPeter Tyser static void tmu_timer_stop(unsigned int timer)
57ea0364f1SPeter Tyser {
58ea0364f1SPeter Tyser 	if (timer > 2)
59ea0364f1SPeter Tyser 		return;
6073f35e0bSNobuhiro Iwamatsu 	writeb(readb(&tmu->tstr) & ~(1 << timer), &tmu->tstr);
61ea0364f1SPeter Tyser }
62ea0364f1SPeter Tyser 
63ea0364f1SPeter Tyser int timer_init(void)
64ea0364f1SPeter Tyser {
65d4430426SNobuhiro Iwamatsu 	bit = (ffs(CONFIG_SYS_TMU_CLK_DIV) >> 1) - 1;
66*861bd4bcSNobuhiro Iwamatsu 	writew((readw(&tmu->tcr0) & ~TCR_TPSC) | bit, &tmu->tcr0);
67ea0364f1SPeter Tyser 
68ea0364f1SPeter Tyser 	tmu_timer_stop(0);
69ea0364f1SPeter Tyser 	tmu_timer_start(0);
70ea0364f1SPeter Tyser 
7161973afcSNobuhiro Iwamatsu 	last_tcnt = 0;
7261973afcSNobuhiro Iwamatsu 	overflow_ticks = 0;
7361973afcSNobuhiro Iwamatsu 
74ea0364f1SPeter Tyser 	return 0;
75ea0364f1SPeter Tyser }
76ea0364f1SPeter Tyser 
77ea0364f1SPeter Tyser unsigned long long get_ticks(void)
78ea0364f1SPeter Tyser {
7973f35e0bSNobuhiro Iwamatsu 	unsigned long tcnt = 0 - readl(&tmu->tcnt0);
8061973afcSNobuhiro Iwamatsu 
8178df8c68SNobuhiro Iwamatsu 	if (last_tcnt > tcnt) /* overflow */
8261973afcSNobuhiro Iwamatsu 		overflow_ticks++;
8361973afcSNobuhiro Iwamatsu 	last_tcnt = tcnt;
8461973afcSNobuhiro Iwamatsu 
8561973afcSNobuhiro Iwamatsu 	return (overflow_ticks << 32) | tcnt;
86ea0364f1SPeter Tyser }
87ea0364f1SPeter Tyser 
88ea0364f1SPeter Tyser void __udelay(unsigned long usec)
89ea0364f1SPeter Tyser {
90ea0364f1SPeter Tyser 	unsigned long long tmp;
91ea0364f1SPeter Tyser 	ulong tmo;
92ea0364f1SPeter Tyser 
93ea0364f1SPeter Tyser 	tmo = usec_to_tick(usec);
94ea0364f1SPeter Tyser 	tmp = get_ticks() + tmo;	/* get current timestamp */
95ea0364f1SPeter Tyser 
96ea0364f1SPeter Tyser 	while (get_ticks() < tmp)	/* loop till event */
97ea0364f1SPeter Tyser 		 /*NOP*/;
98ea0364f1SPeter Tyser }
99ea0364f1SPeter Tyser 
100ea0364f1SPeter Tyser unsigned long get_timer(unsigned long base)
101ea0364f1SPeter Tyser {
102ea0364f1SPeter Tyser 	/* return msec */
103ea0364f1SPeter Tyser 	return tick_to_time(get_ticks()) - base;
104ea0364f1SPeter Tyser }
105ea0364f1SPeter Tyser 
106d4430426SNobuhiro Iwamatsu void set_timer(unsigned long t)
107ea0364f1SPeter Tyser {
108d4430426SNobuhiro Iwamatsu 	writel((0 - t), &tmu->tcnt0);
109d4430426SNobuhiro Iwamatsu }
110d4430426SNobuhiro Iwamatsu 
111d4430426SNobuhiro Iwamatsu void reset_timer(void)
112d4430426SNobuhiro Iwamatsu {
113d4430426SNobuhiro Iwamatsu 	tmu_timer_stop(0);
114d4430426SNobuhiro Iwamatsu 	set_timer(0);
115d4430426SNobuhiro Iwamatsu 	tmu_timer_start(0);
116ea0364f1SPeter Tyser }
117