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