]>
Commit | Line | Data |
---|---|---|
e0f1fd4c SK |
1 | /* |
2 | * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> | |
3 | * (C) Copyright 2011, Julius Baxter <julius@opencores.org> | |
4 | * (C) Copyright 2003 | |
5 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
6 | * | |
1a459660 | 7 | * SPDX-License-Identifier: GPL-2.0+ |
e0f1fd4c SK |
8 | */ |
9 | ||
10 | #include <common.h> | |
11 | #include <asm/system.h> | |
12 | #include <asm/openrisc_exc.h> | |
13 | ||
14 | static ulong timestamp; | |
15 | ||
16 | /* how many counter cycles in a jiffy */ | |
17 | #define TIMER_COUNTER_CYCLES (CONFIG_SYS_CLK_FREQ/CONFIG_SYS_OPENRISC_TMR_HZ) | |
18 | /* how many ms elapses between each timer interrupt */ | |
19 | #define TIMER_TIMESTAMP_INC (1000/CONFIG_SYS_OPENRISC_TMR_HZ) | |
20 | /* how many cycles per ms */ | |
21 | #define TIMER_CYCLES_MS (CONFIG_SYS_CLK_FREQ/1000) | |
22 | /* how many cycles per us */ | |
23 | #define TIMER_CYCLES_US (CONFIG_SYS_CLK_FREQ/1000000uL) | |
24 | ||
25 | void timer_isr(void) | |
26 | { | |
27 | timestamp += TIMER_TIMESTAMP_INC; | |
28 | mtspr(SPR_TTMR, SPR_TTMR_IE | SPR_TTMR_RT | | |
29 | (TIMER_COUNTER_CYCLES & SPR_TTMR_TP)); | |
30 | } | |
31 | ||
32 | int timer_init(void) | |
33 | { | |
34 | /* Install timer exception handler */ | |
35 | exception_install_handler(EXC_TIMER, timer_isr); | |
36 | ||
37 | /* Set up the timer for the first expiration. */ | |
38 | timestamp = 0; | |
39 | ||
40 | mtspr(SPR_TTMR, SPR_TTMR_IE | SPR_TTMR_RT | | |
41 | (TIMER_COUNTER_CYCLES & SPR_TTMR_TP)); | |
42 | ||
43 | /* Enable tick timer exception in supervisor register */ | |
44 | mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_TEE); | |
45 | ||
46 | return 0; | |
47 | } | |
48 | ||
49 | void reset_timer(void) | |
50 | { | |
51 | timestamp = 0; | |
52 | ||
53 | mtspr(SPR_TTMR, SPR_TTMR_IE | SPR_TTMR_RT | | |
54 | (TIMER_COUNTER_CYCLES & SPR_TTMR_TP)); | |
55 | } | |
56 | ||
57 | /* | |
58 | * The timer value in ms is calculated by taking the | |
59 | * value accumulated by full timer revolutions plus the value | |
60 | * accumulated in this period | |
61 | */ | |
62 | ulong get_timer(ulong base) | |
63 | { | |
64 | return timestamp + mfspr(SPR_TTCR)/TIMER_CYCLES_MS - base; | |
65 | } | |
66 | ||
67 | void set_timer(ulong t) | |
68 | { | |
69 | reset_timer(); | |
70 | timestamp = t; | |
71 | } | |
72 | ||
2bcffa6f SK |
73 | unsigned long long get_ticks(void) |
74 | { | |
75 | return get_timer(0); | |
76 | } | |
77 | ||
78 | ulong get_tbclk(void) | |
79 | { | |
80 | return CONFIG_SYS_HZ; | |
81 | } | |
82 | ||
e0f1fd4c SK |
83 | void __udelay(ulong usec) |
84 | { | |
85 | ulong elapsed = 0; | |
86 | ulong tick; | |
87 | ulong last_tick; | |
88 | ||
89 | last_tick = mfspr(SPR_TTCR); | |
90 | while ((elapsed / TIMER_CYCLES_US) < usec) { | |
91 | tick = mfspr(SPR_TTCR); | |
92 | if (tick >= last_tick) | |
93 | elapsed += (tick - last_tick); | |
94 | else | |
95 | elapsed += TIMER_COUNTER_CYCLES - (last_tick - tick); | |
96 | last_tick = tick; | |
97 | } | |
98 | } |