]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
c74b2108 SK |
2 | /* |
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 <[email protected]> | |
9 | * | |
10 | * (C) Copyright 2002 | |
11 | * Sysgo Real-Time Solutions, GmbH <www.elinos.com> | |
12 | * Alex Zuepke <[email protected]> | |
13 | * | |
14 | * (C) Copyright 2002-2004 | |
792a09eb | 15 | * Gary Jennejohn, DENX Software Engineering, <[email protected]> |
c74b2108 SK |
16 | * |
17 | * (C) Copyright 2004 | |
18 | * Philippe Robin, ARM Ltd. <[email protected]> | |
19 | * | |
20 | * Copyright (C) 2007 Sergey Kubushyn <[email protected]> | |
c74b2108 SK |
21 | */ |
22 | ||
23 | #include <common.h> | |
691d719d | 24 | #include <init.h> |
1045315d | 25 | #include <time.h> |
401d1c4f | 26 | #include <asm/global_data.h> |
9868a36d | 27 | #include <asm/io.h> |
de23e722 | 28 | #include <asm/arch/timer_defs.h> |
e21b3dfb | 29 | #include <div64.h> |
c05ed00a | 30 | #include <linux/delay.h> |
c74b2108 | 31 | |
e465cf23 NT |
32 | DECLARE_GLOBAL_DATA_PTR; |
33 | ||
9868a36d NT |
34 | static struct davinci_timer * const timer = |
35 | (struct davinci_timer *)CONFIG_SYS_TIMERBASE; | |
c74b2108 | 36 | |
e465cf23 | 37 | #define TIMER_LOAD_VAL 0xffffffff |
ea686f52 | 38 | |
e465cf23 | 39 | #define TIM_CLK_DIV 16 |
c74b2108 SK |
40 | |
41 | int timer_init(void) | |
42 | { | |
43 | /* We are using timer34 in unchained 32-bit mode, full speed */ | |
9868a36d NT |
44 | writel(0x0, &timer->tcr); |
45 | writel(0x0, &timer->tgcr); | |
46 | writel(0x06 | ((TIM_CLK_DIV - 1) << 8), &timer->tgcr); | |
47 | writel(0x0, &timer->tim34); | |
48 | writel(TIMER_LOAD_VAL, &timer->prd34); | |
9868a36d | 49 | writel(2 << 22, &timer->tcr); |
b339051c | 50 | gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK / TIM_CLK_DIV; |
5f70714c | 51 | gd->arch.timer_reset_value = 0; |
c74b2108 SK |
52 | |
53 | return(0); | |
54 | } | |
55 | ||
e465cf23 NT |
56 | /* |
57 | * Get the current 64 bit timer tick count | |
58 | */ | |
59 | unsigned long long get_ticks(void) | |
c74b2108 | 60 | { |
e465cf23 NT |
61 | unsigned long now = readl(&timer->tim34); |
62 | ||
63 | /* increment tbu if tbl has rolled over */ | |
66ee6923 | 64 | if (now < gd->arch.tbl) |
8ff43b03 | 65 | gd->arch.tbu++; |
66ee6923 | 66 | gd->arch.tbl = now; |
e465cf23 | 67 | |
66ee6923 | 68 | return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl; |
c74b2108 SK |
69 | } |
70 | ||
80c40b76 DB |
71 | ulong get_timer(ulong base) |
72 | { | |
e465cf23 | 73 | unsigned long long timer_diff; |
80c40b76 | 74 | |
5f70714c | 75 | timer_diff = get_ticks() - gd->arch.timer_reset_value; |
e465cf23 | 76 | |
b339051c SG |
77 | return lldiv(timer_diff, |
78 | (gd->arch.timer_rate_hz / CONFIG_SYS_HZ)) - base; | |
c74b2108 SK |
79 | } |
80 | ||
3eb90bad | 81 | void __udelay(unsigned long usec) |
c74b2108 | 82 | { |
e465cf23 | 83 | unsigned long long endtime; |
c74b2108 | 84 | |
b339051c | 85 | endtime = lldiv((unsigned long long)usec * gd->arch.timer_rate_hz, |
e21b3dfb | 86 | 1000000UL); |
e465cf23 | 87 | endtime += get_ticks(); |
c74b2108 | 88 | |
e465cf23 NT |
89 | while (get_ticks() < endtime) |
90 | ; | |
c74b2108 SK |
91 | } |
92 | ||
93 | /* | |
94 | * This function is derived from PowerPC code (timebase clock frequency). | |
95 | * On ARM it returns the number of timer ticks per second. | |
96 | */ | |
97 | ulong get_tbclk(void) | |
98 | { | |
b339051c | 99 | return gd->arch.timer_rate_hz; |
c74b2108 | 100 | } |
bf569ac8 HS |
101 | |
102 | #ifdef CONFIG_HW_WATCHDOG | |
103 | static struct davinci_timer * const wdttimer = | |
104 | (struct davinci_timer *)CONFIG_SYS_WDTTIMERBASE; | |
105 | ||
106 | /* | |
107 | * See prufw2.pdf for using Timer as a WDT | |
108 | */ | |
109 | void davinci_hw_watchdog_enable(void) | |
110 | { | |
111 | writel(0x0, &wdttimer->tcr); | |
112 | writel(0x0, &wdttimer->tgcr); | |
113 | /* TIMMODE = 2h */ | |
114 | writel(0x08 | 0x03 | ((TIM_CLK_DIV - 1) << 8), &wdttimer->tgcr); | |
115 | writel(CONFIG_SYS_WDT_PERIOD_LOW, &wdttimer->prd12); | |
116 | writel(CONFIG_SYS_WDT_PERIOD_HIGH, &wdttimer->prd34); | |
117 | writel(2 << 22, &wdttimer->tcr); | |
118 | writel(0x0, &wdttimer->tim12); | |
119 | writel(0x0, &wdttimer->tim34); | |
120 | /* set WDEN bit, WDKEY 0xa5c6 */ | |
121 | writel(0xa5c64000, &wdttimer->wdtcr); | |
122 | /* clear counter register */ | |
123 | writel(0xda7e4000, &wdttimer->wdtcr); | |
124 | } | |
125 | ||
126 | void davinci_hw_watchdog_reset(void) | |
127 | { | |
128 | writel(0xa5c64000, &wdttimer->wdtcr); | |
129 | writel(0xda7e4000, &wdttimer->wdtcr); | |
130 | } | |
131 | #endif |