]>
Commit | Line | Data |
---|---|---|
1d5d0ae9 | 1 | /** @file |
2 | ||
3 | Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR> | |
4 | ||
5 | This program and the accompanying materials | |
6 | are licensed and made available under the terms and conditions of the BSD License | |
7 | which accompanies this distribution. The full text of the license may be found at | |
8 | http://opensource.org/licenses/bsd-license.php | |
9 | ||
10 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
11 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
12 | ||
13 | **/ | |
14 | ||
15 | #include <Base.h> | |
16 | ||
17 | #include <Library/BaseLib.h> | |
18 | #include <Library/TimerLib.h> | |
19 | #include <Library/DebugLib.h> | |
20 | #include <Library/PcdLib.h> | |
21 | #include <Library/IoLib.h> | |
22 | #include <Drivers/SP804Timer.h> | |
5cc45b70 | 23 | |
9e4a626c | 24 | #define SP804_TIMER_METRONOME_BASE ((UINTN)PcdGet32 (PcdSP804TimerMetronomeBase)) |
25 | #define SP804_TIMER_PERFORMANCE_BASE ((UINTN)PcdGet32 (PcdSP804TimerPerformanceBase)) | |
1d5d0ae9 | 26 | |
27 | // Setup SP810's Timer2 for managing delay functions. And Timer3 for Performance counter | |
28 | // Note: ArmVE's Timer0 and Timer1 are used by TimerDxe. | |
29 | RETURN_STATUS | |
30 | EFIAPI | |
31 | TimerConstructor ( | |
32 | VOID | |
33 | ) | |
34 | { | |
9e4a626c | 35 | // Check if the Metronome Timer is already initialized |
5cc45b70 | 36 | if (MmioRead32(SP804_TIMER_METRONOME_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) { |
23792dea | 37 | return RETURN_SUCCESS; |
38 | } else { | |
9e4a626c | 39 | // Configure the Metronome Timer for one shot operation, 32 bits, no prescaler, and interrupt disabled |
5cc45b70 | 40 | MmioOr32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_ONESHOT | SP804_TIMER_CTRL_32BIT | SP804_PRESCALE_DIV_1); |
1d5d0ae9 | 41 | |
23792dea | 42 | // Preload the timer count register |
5cc45b70 | 43 | MmioWrite32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_LOAD_REG, 1); |
1d5d0ae9 | 44 | |
23792dea | 45 | // Enable the timer |
5cc45b70 | 46 | MmioOr32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_ENABLE); |
23792dea | 47 | } |
1d5d0ae9 | 48 | |
9e4a626c | 49 | // Check if the Performance Timer is already initialized |
5cc45b70 | 50 | if (MmioRead32(SP804_TIMER_PERFORMANCE_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) { |
23792dea | 51 | return RETURN_SUCCESS; |
52 | } else { | |
9e4a626c | 53 | // Configure the Performance timer for free running operation, 32 bits, no prescaler, interrupt disabled |
5cc45b70 | 54 | MmioOr32 (SP804_TIMER_PERFORMANCE_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_32BIT | SP804_PRESCALE_DIV_1); |
1d5d0ae9 | 55 | |
9e4a626c | 56 | // Start the Performance Timer ticking |
5cc45b70 | 57 | MmioOr32 (SP804_TIMER_PERFORMANCE_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_ENABLE); |
23792dea | 58 | } |
1d5d0ae9 | 59 | |
23792dea | 60 | return RETURN_SUCCESS; |
1d5d0ae9 | 61 | } |
62 | ||
63 | /** | |
64 | Stalls the CPU for at least the given number of microseconds. | |
65 | ||
66 | Stalls the CPU for the number of microseconds specified by MicroSeconds. | |
67 | ||
68 | @param MicroSeconds The minimum number of microseconds to delay. | |
69 | ||
70 | @return The value of MicroSeconds inputted. | |
71 | ||
72 | **/ | |
73 | UINTN | |
74 | EFIAPI | |
75 | MicroSecondDelay ( | |
76 | IN UINTN MicroSeconds | |
77 | ) | |
78 | { | |
ce9cc403 | 79 | UINTN Index; |
1d5d0ae9 | 80 | |
ce9cc403 | 81 | // Reload the counter for each 1Mhz to avoid an overflow in the load value |
5cc45b70 | 82 | for (Index = 0; Index < (UINTN)PcdGet32(PcdSP804TimerFrequencyInMHz); Index++) { |
ce9cc403 | 83 | // load the timer count register |
5cc45b70 | 84 | MmioWrite32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_LOAD_REG, MicroSeconds); |
ce9cc403 | 85 | |
5cc45b70 | 86 | while (MmioRead32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CURRENT_REG) > 0) { |
ce9cc403 | 87 | ; |
88 | } | |
1d5d0ae9 | 89 | } |
90 | ||
91 | return MicroSeconds; | |
92 | } | |
93 | ||
94 | /** | |
95 | Stalls the CPU for at least the given number of nanoseconds. | |
96 | ||
97 | Stalls the CPU for the number of nanoseconds specified by NanoSeconds. | |
98 | ||
99 | @param NanoSeconds The minimum number of nanoseconds to delay. | |
100 | ||
101 | @return The value of NanoSeconds inputted. | |
102 | ||
103 | **/ | |
104 | UINTN | |
105 | EFIAPI | |
106 | NanoSecondDelay ( | |
107 | IN UINTN NanoSeconds | |
108 | ) | |
109 | { | |
ce9cc403 | 110 | UINTN Index; |
111 | UINT32 MicroSeconds; | |
1d5d0ae9 | 112 | |
113 | // Round up to 1us Tick Number | |
114 | MicroSeconds = (UINT32)NanoSeconds / 1000; | |
115 | MicroSeconds += ((UINT32)NanoSeconds % 1000) == 0 ? 0 : 1; | |
116 | ||
ce9cc403 | 117 | // Reload the counter for each 1Mhz to avoid an overflow in the load value |
5cc45b70 | 118 | for (Index = 0; Index < (UINTN)PcdGet32(PcdSP804TimerFrequencyInMHz); Index++) { |
ce9cc403 | 119 | // load the timer count register |
5cc45b70 | 120 | MmioWrite32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_LOAD_REG, MicroSeconds); |
1d5d0ae9 | 121 | |
5cc45b70 | 122 | while (MmioRead32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CURRENT_REG) > 0) { |
ce9cc403 | 123 | ; |
124 | } | |
1d5d0ae9 | 125 | } |
126 | ||
127 | return NanoSeconds; | |
128 | } | |
129 | ||
130 | /** | |
131 | Retrieves the current value of a 64-bit free running performance counter. | |
132 | ||
133 | The counter can either count up by 1 or count down by 1. If the physical | |
134 | performance counter counts by a larger increment, then the counter values | |
135 | must be translated. The properties of the counter can be retrieved from | |
136 | GetPerformanceCounterProperties(). | |
137 | ||
138 | @return The current value of the free running performance counter. | |
139 | ||
140 | **/ | |
141 | UINT64 | |
142 | EFIAPI | |
143 | GetPerformanceCounter ( | |
144 | VOID | |
145 | ) | |
146 | { | |
147 | // Free running 64-bit/32-bit counter is needed here. | |
148 | // Don't think we need this to boot, just to do performance profile | |
23792dea | 149 | UINT64 Value; |
5cc45b70 | 150 | Value = MmioRead32 (SP804_TIMER_PERFORMANCE_BASE + SP804_TIMER_CURRENT_REG); |
23792dea | 151 | ASSERT(Value > 0); |
152 | return Value; | |
1d5d0ae9 | 153 | } |
154 | ||
155 | ||
156 | /** | |
157 | Retrieves the 64-bit frequency in Hz and the range of performance counter | |
158 | values. | |
159 | ||
160 | If StartValue is not NULL, then the value that the performance counter starts | |
161 | with immediately after is it rolls over is returned in StartValue. If | |
162 | EndValue is not NULL, then the value that the performance counter end with | |
163 | immediately before it rolls over is returned in EndValue. The 64-bit | |
164 | frequency of the performance counter in Hz is always returned. If StartValue | |
165 | is less than EndValue, then the performance counter counts up. If StartValue | |
166 | is greater than EndValue, then the performance counter counts down. For | |
167 | example, a 64-bit free running counter that counts up would have a StartValue | |
168 | of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter | |
169 | that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0. | |
170 | ||
171 | @param StartValue The value the performance counter starts with when it | |
172 | rolls over. | |
173 | @param EndValue The value that the performance counter ends with before | |
174 | it rolls over. | |
175 | ||
176 | @return The frequency in Hz. | |
177 | ||
178 | **/ | |
179 | UINT64 | |
180 | EFIAPI | |
181 | GetPerformanceCounterProperties ( | |
182 | OUT UINT64 *StartValue, OPTIONAL | |
183 | OUT UINT64 *EndValue OPTIONAL | |
184 | ) | |
185 | { | |
186 | if (StartValue != NULL) { | |
187 | // Timer starts with the reload value | |
bcd8fa79 | 188 | *StartValue = 0xFFFFFFFF; |
1d5d0ae9 | 189 | } |
190 | ||
191 | if (EndValue != NULL) { | |
bcd8fa79 | 192 | // Timer counts down to 0x0 |
193 | *EndValue = (UINT64)0ULL; | |
1d5d0ae9 | 194 | } |
195 | ||
ce9cc403 | 196 | return PcdGet64 (PcdEmbeddedPerformanceCounterFrequencyInHz); |
1d5d0ae9 | 197 | } |