xref: /OK3568_Linux_fs/u-boot/arch/arm/cpu/armv7/vf610/timer.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2013 Freescale Semiconductor, Inc.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <asm/io.h>
9*4882a593Smuzhiyun #include <div64.h>
10*4882a593Smuzhiyun #include <asm/arch/imx-regs.h>
11*4882a593Smuzhiyun #include <asm/arch/clock.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun static struct pit_reg *cur_pit = (struct pit_reg *)PIT_BASE_ADDR;
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define TIMER_LOAD_VAL	0xffffffff
18*4882a593Smuzhiyun 
tick_to_time(unsigned long long tick)19*4882a593Smuzhiyun static inline unsigned long long tick_to_time(unsigned long long tick)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun 	tick *= CONFIG_SYS_HZ;
22*4882a593Smuzhiyun 	do_div(tick, mxc_get_clock(MXC_IPG_CLK));
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun 	return tick;
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun 
us_to_tick(unsigned long long usec)27*4882a593Smuzhiyun static inline unsigned long long us_to_tick(unsigned long long usec)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun 	usec = usec * mxc_get_clock(MXC_IPG_CLK)  + 999999;
30*4882a593Smuzhiyun 	do_div(usec, 1000000);
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun 	return usec;
33*4882a593Smuzhiyun }
34*4882a593Smuzhiyun 
timer_init(void)35*4882a593Smuzhiyun int timer_init(void)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun 	__raw_writel(0, &cur_pit->mcr);
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	__raw_writel(TIMER_LOAD_VAL, &cur_pit->ldval1);
40*4882a593Smuzhiyun 	__raw_writel(0, &cur_pit->tctrl1);
41*4882a593Smuzhiyun 	__raw_writel(1, &cur_pit->tctrl1);
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	gd->arch.tbl = 0;
44*4882a593Smuzhiyun 	gd->arch.tbu = 0;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	return 0;
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun 
get_ticks(void)49*4882a593Smuzhiyun unsigned long long get_ticks(void)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	ulong now = TIMER_LOAD_VAL - __raw_readl(&cur_pit->cval1);
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	/* increment tbu if tbl has rolled over */
54*4882a593Smuzhiyun 	if (now < gd->arch.tbl)
55*4882a593Smuzhiyun 		gd->arch.tbu++;
56*4882a593Smuzhiyun 	gd->arch.tbl = now;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
get_timer_masked(void)61*4882a593Smuzhiyun ulong get_timer_masked(void)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	return tick_to_time(get_ticks());
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun 
get_timer(ulong base)66*4882a593Smuzhiyun ulong get_timer(ulong base)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun 	return get_timer_masked() - base;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun /* delay x useconds AND preserve advance timstamp value */
__udelay(unsigned long usec)72*4882a593Smuzhiyun void __udelay(unsigned long usec)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	unsigned long long start;
75*4882a593Smuzhiyun 	ulong tmo;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	start = get_ticks();			/* get current timestamp */
78*4882a593Smuzhiyun 	tmo = us_to_tick(usec);			/* convert usecs to ticks */
79*4882a593Smuzhiyun 	while ((get_ticks() - start) < tmo)
80*4882a593Smuzhiyun 		;				/* loop till time has passed */
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun /*
84*4882a593Smuzhiyun  * This function is derived from PowerPC code (timebase clock frequency).
85*4882a593Smuzhiyun  * On ARM it returns the number of timer ticks per second.
86*4882a593Smuzhiyun  */
get_tbclk(void)87*4882a593Smuzhiyun ulong get_tbclk(void)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun 	return mxc_get_clock(MXC_IPG_CLK);
90*4882a593Smuzhiyun }
91