blob: 99f1eabf5f89a178e6777b3ccf4a5d8b60a9cc09 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Sergey Kubushyne8f39122007-08-10 20:26:18 +02002/*
3 * (C) Copyright 2003
4 * Texas Instruments <www.ti.com>
5 *
6 * (C) Copyright 2002
7 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
8 * Marius Groeger <mgroeger@sysgo.de>
9 *
10 * (C) Copyright 2002
11 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
12 * Alex Zuepke <azu@sysgo.de>
13 *
14 * (C) Copyright 2002-2004
Detlev Zundelf1b3f2b2009-05-13 10:54:10 +020015 * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
Sergey Kubushyne8f39122007-08-10 20:26:18 +020016 *
17 * (C) Copyright 2004
18 * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
19 *
20 * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
Sergey Kubushyne8f39122007-08-10 20:26:18 +020021 */
22
23#include <common.h>
Nick Thompson283398b2009-11-12 11:02:17 -050024#include <asm/io.h>
Heiko Schocher420cd0a2011-09-14 19:44:00 +000025#include <asm/arch/timer_defs.h>
Christian Riesch93757cf2011-12-09 16:54:01 +010026#include <div64.h>
Sergey Kubushyne8f39122007-08-10 20:26:18 +020027
Nick Thompson1c92d8e2010-12-11 10:46:46 -050028DECLARE_GLOBAL_DATA_PTR;
29
Nick Thompson283398b2009-11-12 11:02:17 -050030static struct davinci_timer * const timer =
31 (struct davinci_timer *)CONFIG_SYS_TIMERBASE;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020032
Nick Thompson1c92d8e2010-12-11 10:46:46 -050033#define TIMER_LOAD_VAL 0xffffffff
Peter Pearsee7680982008-02-01 16:50:24 +000034
Nick Thompson1c92d8e2010-12-11 10:46:46 -050035#define TIM_CLK_DIV 16
Sergey Kubushyne8f39122007-08-10 20:26:18 +020036
37int timer_init(void)
38{
39 /* We are using timer34 in unchained 32-bit mode, full speed */
Nick Thompson283398b2009-11-12 11:02:17 -050040 writel(0x0, &timer->tcr);
41 writel(0x0, &timer->tgcr);
42 writel(0x06 | ((TIM_CLK_DIV - 1) << 8), &timer->tgcr);
43 writel(0x0, &timer->tim34);
44 writel(TIMER_LOAD_VAL, &timer->prd34);
Nick Thompson283398b2009-11-12 11:02:17 -050045 writel(2 << 22, &timer->tcr);
Simon Glass6ed6e032012-12-13 20:48:32 +000046 gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK / TIM_CLK_DIV;
Simon Glass9cbe003a2012-12-13 20:48:36 +000047 gd->arch.timer_reset_value = 0;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020048
49 return(0);
50}
51
Nick Thompson1c92d8e2010-12-11 10:46:46 -050052/*
53 * Get the current 64 bit timer tick count
54 */
55unsigned long long get_ticks(void)
Sergey Kubushyne8f39122007-08-10 20:26:18 +020056{
Nick Thompson1c92d8e2010-12-11 10:46:46 -050057 unsigned long now = readl(&timer->tim34);
58
59 /* increment tbu if tbl has rolled over */
Simon Glass2655ee12012-12-13 20:48:34 +000060 if (now < gd->arch.tbl)
Simon Glass8ca15202012-12-13 20:48:33 +000061 gd->arch.tbu++;
Simon Glass2655ee12012-12-13 20:48:34 +000062 gd->arch.tbl = now;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020063
Simon Glass2655ee12012-12-13 20:48:34 +000064 return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020065}
66
Dirk Behme866c3212008-03-26 09:53:29 +010067ulong get_timer(ulong base)
68{
Nick Thompson1c92d8e2010-12-11 10:46:46 -050069 unsigned long long timer_diff;
Dirk Behme866c3212008-03-26 09:53:29 +010070
Simon Glass9cbe003a2012-12-13 20:48:36 +000071 timer_diff = get_ticks() - gd->arch.timer_reset_value;
Nick Thompson1c92d8e2010-12-11 10:46:46 -050072
Simon Glass6ed6e032012-12-13 20:48:32 +000073 return lldiv(timer_diff,
74 (gd->arch.timer_rate_hz / CONFIG_SYS_HZ)) - base;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020075}
76
Ingo van Lilf0f778a2009-11-24 14:09:21 +010077void __udelay(unsigned long usec)
Sergey Kubushyne8f39122007-08-10 20:26:18 +020078{
Nick Thompson1c92d8e2010-12-11 10:46:46 -050079 unsigned long long endtime;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020080
Simon Glass6ed6e032012-12-13 20:48:32 +000081 endtime = lldiv((unsigned long long)usec * gd->arch.timer_rate_hz,
Christian Riesch93757cf2011-12-09 16:54:01 +010082 1000000UL);
Nick Thompson1c92d8e2010-12-11 10:46:46 -050083 endtime += get_ticks();
Sergey Kubushyne8f39122007-08-10 20:26:18 +020084
Nick Thompson1c92d8e2010-12-11 10:46:46 -050085 while (get_ticks() < endtime)
86 ;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020087}
88
89/*
90 * This function is derived from PowerPC code (timebase clock frequency).
91 * On ARM it returns the number of timer ticks per second.
92 */
93ulong get_tbclk(void)
94{
Simon Glass6ed6e032012-12-13 20:48:32 +000095 return gd->arch.timer_rate_hz;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020096}
Heiko Schochera2cddad2011-09-14 19:44:02 +000097
98#ifdef CONFIG_HW_WATCHDOG
99static struct davinci_timer * const wdttimer =
100 (struct davinci_timer *)CONFIG_SYS_WDTTIMERBASE;
101
102/*
103 * See prufw2.pdf for using Timer as a WDT
104 */
105void davinci_hw_watchdog_enable(void)
106{
107 writel(0x0, &wdttimer->tcr);
108 writel(0x0, &wdttimer->tgcr);
109 /* TIMMODE = 2h */
110 writel(0x08 | 0x03 | ((TIM_CLK_DIV - 1) << 8), &wdttimer->tgcr);
111 writel(CONFIG_SYS_WDT_PERIOD_LOW, &wdttimer->prd12);
112 writel(CONFIG_SYS_WDT_PERIOD_HIGH, &wdttimer->prd34);
113 writel(2 << 22, &wdttimer->tcr);
114 writel(0x0, &wdttimer->tim12);
115 writel(0x0, &wdttimer->tim34);
116 /* set WDEN bit, WDKEY 0xa5c6 */
117 writel(0xa5c64000, &wdttimer->wdtcr);
118 /* clear counter register */
119 writel(0xda7e4000, &wdttimer->wdtcr);
120}
121
122void davinci_hw_watchdog_reset(void)
123{
124 writel(0xa5c64000, &wdttimer->wdtcr);
125 writel(0xda7e4000, &wdttimer->wdtcr);
126}
127#endif