]>
Commit | Line | Data |
---|---|---|
65458987 AL |
1 | /* |
2 | * U-boot - interrupts.c Interrupt related routines | |
3 | * | |
9171fc81 | 4 | * Copyright (c) 2005-2008 Analog Devices Inc. |
65458987 AL |
5 | * |
6 | * This file is based on interrupts.c | |
7 | * Copyright 1996 Roman Zippel | |
8 | * Copyright 1999 D. Jeff Dionne <jeff@uclinux.org> | |
9 | * Copyright 2000-2001 Lineo, Inc. D. Jefff Dionne <jeff@lineo.ca> | |
10 | * Copyright 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca> | |
11 | * Copyright 2003 Metrowerks/Motorola | |
12 | * Copyright 2003 Bas Vermeulen <bas@buyways.nl>, | |
13 | * BuyWays B.V. (www.buyways.nl) | |
14 | * | |
15 | * (C) Copyright 2000-2004 | |
16 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
65458987 | 17 | * |
9171fc81 | 18 | * Licensed under the GPL-2 or later. |
65458987 AL |
19 | */ |
20 | ||
21 | #include <common.h> | |
65458987 AL |
22 | #include <config.h> |
23 | #include <asm/blackfin.h> | |
24 | #include "cpu.h" | |
25 | ||
26 | static ulong timestamp; | |
27 | static ulong last_time; | |
28 | static int int_flag; | |
29 | ||
30 | int irq_flags; /* needed by asm-blackfin/system.h */ | |
31 | ||
32 | /* Functions just to satisfy the linker */ | |
33 | ||
34 | /* | |
35 | * This function is derived from PowerPC code (read timebase as long long). | |
9171fc81 | 36 | * On Blackfin it just returns the timer value. |
65458987 AL |
37 | */ |
38 | unsigned long long get_ticks(void) | |
39 | { | |
40 | return get_timer(0); | |
41 | } | |
42 | ||
43 | /* | |
44 | * This function is derived from PowerPC code (timebase clock frequency). | |
9171fc81 | 45 | * On Blackfin it returns the number of timer ticks per second. |
65458987 AL |
46 | */ |
47 | ulong get_tbclk(void) | |
48 | { | |
49 | ulong tbclk; | |
50 | ||
6d0f6bcf | 51 | tbclk = CONFIG_SYS_HZ; |
65458987 AL |
52 | return tbclk; |
53 | } | |
54 | ||
55 | void enable_interrupts(void) | |
56 | { | |
9171fc81 | 57 | local_irq_restore(int_flag); |
65458987 AL |
58 | } |
59 | ||
60 | int disable_interrupts(void) | |
61 | { | |
9171fc81 | 62 | local_irq_save(int_flag); |
65458987 AL |
63 | return 1; |
64 | } | |
65 | ||
65458987 AL |
66 | void udelay(unsigned long usec) |
67 | { | |
68 | unsigned long delay, start, stop; | |
69 | unsigned long cclk; | |
70 | cclk = (CONFIG_CCLK_HZ); | |
71 | ||
72 | while (usec > 1) { | |
73 | /* | |
74 | * how many clock ticks to delay? | |
75 | * - request(in useconds) * clock_ticks(Hz) / useconds/second | |
76 | */ | |
77 | if (usec < 1000) { | |
78 | delay = (usec * (cclk / 244)) >> 12; | |
79 | usec = 0; | |
80 | } else { | |
81 | delay = (1000 * (cclk / 244)) >> 12; | |
82 | usec -= 1000; | |
83 | } | |
84 | ||
9171fc81 | 85 | asm volatile (" %0 = CYCLES;" : "=r" (start)); |
65458987 | 86 | do { |
9171fc81 | 87 | asm volatile (" %0 = CYCLES; " : "=r" (stop)); |
65458987 AL |
88 | } while (stop - start < delay); |
89 | } | |
90 | ||
91 | return; | |
92 | } | |
93 | ||
9171fc81 MF |
94 | #define MAX_TIM_LOAD 0xFFFFFFFF |
95 | int timer_init(void) | |
65458987 AL |
96 | { |
97 | *pTCNTL = 0x1; | |
98 | *pTSCALE = 0x0; | |
99 | *pTCOUNT = MAX_TIM_LOAD; | |
100 | *pTPERIOD = MAX_TIM_LOAD; | |
101 | *pTCNTL = 0x7; | |
102 | asm("CSYNC;"); | |
103 | ||
104 | timestamp = 0; | |
105 | last_time = 0; | |
9171fc81 MF |
106 | |
107 | return 0; | |
65458987 AL |
108 | } |
109 | ||
110 | /* | |
111 | * Any network command or flash | |
112 | * command is started get_timer shall | |
113 | * be called before TCOUNT gets reset, | |
114 | * to implement the accurate timeouts. | |
115 | * | |
116 | * How ever milliconds doesn't return | |
117 | * the number that has been elapsed from | |
118 | * the last reset. | |
119 | * | |
120 | * As get_timer is used in the u-boot | |
121 | * only for timeouts this should be | |
122 | * sufficient | |
123 | */ | |
124 | ulong get_timer(ulong base) | |
125 | { | |
126 | ulong milisec; | |
127 | ||
128 | /* Number of clocks elapsed */ | |
129 | ulong clocks = (MAX_TIM_LOAD - (*pTCOUNT)); | |
130 | ||
131 | /* | |
132 | * Find if the TCOUNT is reset | |
133 | * timestamp gives the number of times | |
134 | * TCOUNT got reset | |
135 | */ | |
136 | if (clocks < last_time) | |
137 | timestamp++; | |
138 | last_time = clocks; | |
139 | ||
140 | /* Get the number of milliseconds */ | |
141 | milisec = clocks / (CONFIG_CCLK_HZ / 1000); | |
142 | ||
143 | /* | |
9171fc81 MF |
144 | * Find the number of millisonds that |
145 | * got elapsed before this TCOUNT cycle | |
65458987 AL |
146 | */ |
147 | milisec += timestamp * (MAX_TIM_LOAD / (CONFIG_CCLK_HZ / 1000)); | |
148 | ||
149 | return (milisec - base); | |
150 | } | |
9171fc81 MF |
151 | |
152 | void reset_timer(void) | |
153 | { | |
154 | timestamp = 0; | |
155 | } |