5405de669dc565c1aeec9a4cfcdf43a640197119
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
30 #define _COMPONENT ACPI_HARDWARE
31 MODULE_NAME ("hwtimer")
34 /******************************************************************************
36 * FUNCTION: Acpi_get_timer_resolution
40 * RETURN: Number of bits of resolution in the PM Timer (24 or 32).
42 * DESCRIPTION: Obtains resolution of the ACPI PM Timer.
44 ******************************************************************************/
47 acpi_get_timer_resolution (
51 return (AE_BAD_PARAMETER
);
54 if (0 == acpi_gbl_FADT
->tmr_val_ext
) {
65 /******************************************************************************
67 * FUNCTION: Acpi_get_timer
71 * RETURN: Current value of the ACPI PM Timer (in ticks).
73 * DESCRIPTION: Obtains current value of ACPI PM Timer.
75 ******************************************************************************/
82 return (AE_BAD_PARAMETER
);
85 *ticks
= acpi_os_in32 ((ACPI_IO_ADDRESS
) ACPI_GET_ADDRESS (acpi_gbl_FADT
->Xpm_tmr_blk
.address
));
91 /******************************************************************************
93 * FUNCTION: Acpi_get_timer_duration
95 * PARAMETERS: Start_ticks
99 * RETURN: Time_elapsed
101 * DESCRIPTION: Computes the time elapsed (in microseconds) between two
102 * PM Timer time stamps, taking into account the possibility of
103 * rollovers, the timer resolution, and timer frequency.
105 * The PM Timer's clock ticks at roughly 3.6 times per
106 * _microsecond_, and its clock continues through Cx state
107 * transitions (unlike many CPU timestamp counters) -- making it
108 * a versatile and accurate timer.
110 * Note that this function accomodates only a single timer
111 * rollover. Thus for 24-bit timers, this function should only
112 * be used for calculating durations less than ~4.6 seconds
113 * (~20 hours for 32-bit timers).
115 ******************************************************************************/
118 acpi_get_timer_duration (
125 u32 milliseconds
= 0;
126 u32 microseconds
= 0;
130 return (AE_BAD_PARAMETER
);
134 * Compute Tick Delta:
135 * -------------------
136 * Handle (max one) timer rollovers on 24- versus 32-bit timers.
138 if (start_ticks
< end_ticks
) {
139 delta_ticks
= end_ticks
- start_ticks
;
141 else if (start_ticks
> end_ticks
) {
143 if (0 == acpi_gbl_FADT
->tmr_val_ext
) {
144 delta_ticks
= (((0x00FFFFFF - start_ticks
) + end_ticks
) & 0x00FFFFFF);
148 delta_ticks
= (0xFFFFFFFF - start_ticks
) + end_ticks
;
159 * Since certain compilers (gcc/Linux, argh!) don't support 64-bit
160 * divides in kernel-space we have to do some trickery to preserve
161 * accuracy while using 32-bit math.
163 * TODO: Change to use 64-bit math when supported.
165 * The process is as follows:
166 * 1. Compute the number of seconds by dividing Delta Ticks by
167 * the timer frequency.
168 * 2. Compute the number of milliseconds in the remainder from step #1
169 * by multiplying by 1000 and then dividing by the timer frequency.
170 * 3. Compute the number of microseconds in the remainder from step #2
171 * by multiplying by 1000 and then dividing by the timer frequency.
172 * 4. Add the results from steps 1, 2, and 3 to get the total duration.
174 * Example: The time elapsed for Delta_ticks = 0xFFFFFFFF should be
175 * 1199864031 microseconds. This is computed as follows:
176 * Step #1: Seconds = 1199; Remainder = 3092840
177 * Step #2: Milliseconds = 864; Remainder = 113120
178 * Step #3: Microseconds = 31; Remainder = <don't care!>
182 seconds
= delta_ticks
/ PM_TIMER_FREQUENCY
;
183 remainder
= delta_ticks
% PM_TIMER_FREQUENCY
;
186 milliseconds
= (remainder
* 1000) / PM_TIMER_FREQUENCY
;
187 remainder
= (remainder
* 1000) % PM_TIMER_FREQUENCY
;
190 microseconds
= (remainder
* 1000) / PM_TIMER_FREQUENCY
;
193 *time_elapsed
= seconds
* 1000000;
194 *time_elapsed
+= milliseconds
* 1000;
195 *time_elapsed
+= microseconds
;