2 /******************************************************************************
4 * Name: hwtimer.c - ACPI Power Management Timer Interface
7 *****************************************************************************/
10 * Copyright (C) 2000, 2001 R. Byron Moore
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #define _COMPONENT ACPI_HARDWARE
30 MODULE_NAME ("hwtimer")
33 /******************************************************************************
35 * FUNCTION: Acpi_get_timer_resolution
39 * RETURN: Number of bits of resolution in the PM Timer (24 or 32).
41 * DESCRIPTION: Obtains resolution of the ACPI PM Timer.
43 ******************************************************************************/
46 acpi_get_timer_resolution (
50 return (AE_BAD_PARAMETER
);
53 if (0 == acpi_gbl_FADT
->tmr_val_ext
) {
64 /******************************************************************************
66 * FUNCTION: Acpi_get_timer
70 * RETURN: Current value of the ACPI PM Timer (in ticks).
72 * DESCRIPTION: Obtains current value of ACPI PM Timer.
74 ******************************************************************************/
81 return (AE_BAD_PARAMETER
);
84 *ticks
= acpi_os_in32 ((ACPI_IO_ADDRESS
) ACPI_GET_ADDRESS (acpi_gbl_FADT
->Xpm_tmr_blk
.address
));
90 /******************************************************************************
92 * FUNCTION: Acpi_get_timer_duration
94 * PARAMETERS: Start_ticks
98 * RETURN: Time_elapsed
100 * DESCRIPTION: Computes the time elapsed (in microseconds) between two
101 * PM Timer time stamps, taking into account the possibility of
102 * rollovers, the timer resolution, and timer frequency.
104 * The PM Timer's clock ticks at roughly 3.6 times per
105 * _microsecond_, and its clock continues through Cx state
106 * transitions (unlike many CPU timestamp counters) -- making it
107 * a versatile and accurate timer.
109 * Note that this function accomodates only a single timer
110 * rollover. Thus for 24-bit timers, this function should only
111 * be used for calculating durations less than ~4.6 seconds
112 * (~20 hours for 32-bit timers).
114 ******************************************************************************/
117 acpi_get_timer_duration (
124 u32 milliseconds
= 0;
125 u32 microseconds
= 0;
129 return (AE_BAD_PARAMETER
);
133 * Compute Tick Delta:
134 * -------------------
135 * Handle (max one) timer rollovers on 24- versus 32-bit timers.
137 if (start_ticks
< end_ticks
) {
138 delta_ticks
= end_ticks
- start_ticks
;
140 else if (start_ticks
> end_ticks
) {
142 if (0 == acpi_gbl_FADT
->tmr_val_ext
) {
143 delta_ticks
= (((0x00FFFFFF - start_ticks
) + end_ticks
) & 0x00FFFFFF);
147 delta_ticks
= (0xFFFFFFFF - start_ticks
) + end_ticks
;
158 * Since certain compilers (gcc/Linux, argh!) don't support 64-bit
159 * divides in kernel-space we have to do some trickery to preserve
160 * accuracy while using 32-bit math.
162 * TODO: Change to use 64-bit math when supported.
164 * The process is as follows:
165 * 1. Compute the number of seconds by dividing Delta Ticks by
166 * the timer frequency.
167 * 2. Compute the number of milliseconds in the remainder from step #1
168 * by multiplying by 1000 and then dividing by the timer frequency.
169 * 3. Compute the number of microseconds in the remainder from step #2
170 * by multiplying by 1000 and then dividing by the timer frequency.
171 * 4. Add the results from steps 1, 2, and 3 to get the total duration.
173 * Example: The time elapsed for Delta_ticks = 0xFFFFFFFF should be
174 * 1199864031 microseconds. This is computed as follows:
175 * Step #1: Seconds = 1199; Remainder = 3092840
176 * Step #2: Milliseconds = 864; Remainder = 113120
177 * Step #3: Microseconds = 31; Remainder = <don't care!>
181 seconds
= delta_ticks
/ PM_TIMER_FREQUENCY
;
182 remainder
= delta_ticks
% PM_TIMER_FREQUENCY
;
185 milliseconds
= (remainder
* 1000) / PM_TIMER_FREQUENCY
;
186 remainder
= (remainder
* 1000) % PM_TIMER_FREQUENCY
;
189 microseconds
= (remainder
* 1000) / PM_TIMER_FREQUENCY
;
192 *time_elapsed
= seconds
* 1000000;
193 *time_elapsed
+= milliseconds
* 1000;
194 *time_elapsed
+= microseconds
;