1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
4  * (C) Copyright 2012 Renesas Solutions Corp.
5  */
6 
7 #include <common.h>
8 #include <div64.h>
9 #include <init.h>
10 #include <time.h>
11 #include <asm/io.h>
12 #include <asm/arch-armv7/globaltimer.h>
13 #include <asm/arch/rmobile.h>
14 #include <linux/delay.h>
15 
16 static struct globaltimer *global_timer = \
17 		(struct globaltimer *)GLOBAL_TIMER_BASE_ADDR;
18 
19 #define CLK2MHZ(clk)	(clk / 1000 / 1000)
get_cpu_global_timer(void)20 static u64 get_cpu_global_timer(void)
21 {
22 	u32 low, high;
23 	u64 timer;
24 
25 	u32 old = readl(&global_timer->cnt_h);
26 	while (1) {
27 		low = readl(&global_timer->cnt_l);
28 		high = readl(&global_timer->cnt_h);
29 		if (old == high)
30 			break;
31 		else
32 			old = high;
33 	}
34 
35 	timer = high;
36 	return (u64)((timer << 32) | low);
37 }
38 
get_time_us(void)39 static u64 get_time_us(void)
40 {
41 	u64 timer = get_cpu_global_timer();
42 
43 	timer = ((timer << 2) + (CLK2MHZ(CONFIG_SYS_CPU_CLK) >> 1));
44 	do_div(timer, CLK2MHZ(CONFIG_SYS_CPU_CLK));
45 	return timer;
46 }
47 
get_time_ms(void)48 static ulong get_time_ms(void)
49 {
50 	u64 us = get_time_us();
51 
52 	do_div(us, 1000);
53 	return us;
54 }
55 
timer_init(void)56 int timer_init(void)
57 {
58 	writel(0x01, &global_timer->ctl);
59 	return 0;
60 }
61 
__udelay(unsigned long usec)62 void __udelay(unsigned long usec)
63 {
64 	u64 start, current;
65 	u64 wait;
66 
67 	start = get_cpu_global_timer();
68 	wait = (u64)((usec * CLK2MHZ(CONFIG_SYS_CPU_CLK)) >> 2);
69 	do {
70 		current = get_cpu_global_timer();
71 	} while ((current - start) < wait);
72 }
73 
get_timer(ulong base)74 ulong get_timer(ulong base)
75 {
76 	return get_time_ms() - base;
77 }
78 
get_ticks(void)79 unsigned long long get_ticks(void)
80 {
81 	return get_cpu_global_timer();
82 }
83 
get_tbclk(void)84 ulong get_tbclk(void)
85 {
86 	return (ulong)(CONFIG_SYS_CPU_CLK >> 2);
87 }
88