hwtimer.c revision 231844
171867Smsmith
271867Smsmith/******************************************************************************
371867Smsmith *
471867Smsmith * Name: hwtimer.c - ACPI Power Management Timer Interface
571867Smsmith *
671867Smsmith *****************************************************************************/
771867Smsmith
8217365Sjkim/*
9229989Sjkim * Copyright (C) 2000 - 2012, Intel Corp.
1071867Smsmith * All rights reserved.
1171867Smsmith *
12217365Sjkim * Redistribution and use in source and binary forms, with or without
13217365Sjkim * modification, are permitted provided that the following conditions
14217365Sjkim * are met:
15217365Sjkim * 1. Redistributions of source code must retain the above copyright
16217365Sjkim *    notice, this list of conditions, and the following disclaimer,
17217365Sjkim *    without modification.
18217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
20217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
21217365Sjkim *    including a substantially similar Disclaimer requirement for further
22217365Sjkim *    binary redistribution.
23217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
24217365Sjkim *    of any contributors may be used to endorse or promote products derived
25217365Sjkim *    from this software without specific prior written permission.
2671867Smsmith *
27217365Sjkim * Alternatively, this software may be distributed under the terms of the
28217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
29217365Sjkim * Software Foundation.
3071867Smsmith *
31217365Sjkim * NO WARRANTY
32217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
43217365Sjkim */
4471867Smsmith
45193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
46193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
4771867Smsmith
4877424Smsmith#define _COMPONENT          ACPI_HARDWARE
4991116Smsmith        ACPI_MODULE_NAME    ("hwtimer")
5071867Smsmith
5171867Smsmith
52231844Sjkim#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
5371867Smsmith/******************************************************************************
5471867Smsmith *
5571867Smsmith * FUNCTION:    AcpiGetTimerResolution
5671867Smsmith *
57138287Smarks * PARAMETERS:  Resolution          - Where the resolution is returned
5871867Smsmith *
59138287Smarks * RETURN:      Status and timer resolution
6071867Smsmith *
61138287Smarks * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
6271867Smsmith *
6371867Smsmith ******************************************************************************/
6471867Smsmith
6571867SmsmithACPI_STATUS
6671867SmsmithAcpiGetTimerResolution (
6771867Smsmith    UINT32                  *Resolution)
6871867Smsmith{
69167802Sjkim    ACPI_FUNCTION_TRACE (AcpiGetTimerResolution);
7071867Smsmith
7177424Smsmith
7271867Smsmith    if (!Resolution)
7371867Smsmith    {
7471867Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
7571867Smsmith    }
7671867Smsmith
77167802Sjkim    if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0)
7871867Smsmith    {
7971867Smsmith        *Resolution = 24;
8071867Smsmith    }
8171867Smsmith    else
8271867Smsmith    {
8371867Smsmith        *Resolution = 32;
8471867Smsmith    }
8571867Smsmith
8671867Smsmith    return_ACPI_STATUS (AE_OK);
8771867Smsmith}
8871867Smsmith
89167802SjkimACPI_EXPORT_SYMBOL (AcpiGetTimerResolution)
9071867Smsmith
91167802Sjkim
9271867Smsmith/******************************************************************************
9371867Smsmith *
9471867Smsmith * FUNCTION:    AcpiGetTimer
9571867Smsmith *
96138287Smarks * PARAMETERS:  Ticks               - Where the timer value is returned
9771867Smsmith *
98151937Sjkim * RETURN:      Status and current timer value (ticks)
9971867Smsmith *
100138287Smarks * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
10171867Smsmith *
10271867Smsmith ******************************************************************************/
10371867Smsmith
10471867SmsmithACPI_STATUS
10571867SmsmithAcpiGetTimer (
10671867Smsmith    UINT32                  *Ticks)
10771867Smsmith{
10899679Siwasaki    ACPI_STATUS             Status;
10999679Siwasaki
11099679Siwasaki
111167802Sjkim    ACPI_FUNCTION_TRACE (AcpiGetTimer);
11271867Smsmith
11383174Smsmith
11471867Smsmith    if (!Ticks)
11571867Smsmith    {
11671867Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
11771867Smsmith    }
11871867Smsmith
119197104Sjkim    Status = AcpiHwRead (Ticks, &AcpiGbl_FADT.XPmTimerBlock);
12071867Smsmith
12199679Siwasaki    return_ACPI_STATUS (Status);
12271867Smsmith}
12371867Smsmith
124167802SjkimACPI_EXPORT_SYMBOL (AcpiGetTimer)
12571867Smsmith
126167802Sjkim
12771867Smsmith/******************************************************************************
12871867Smsmith *
12971867Smsmith * FUNCTION:    AcpiGetTimerDuration
13071867Smsmith *
131138287Smarks * PARAMETERS:  StartTicks          - Starting timestamp
132138287Smarks *              EndTicks            - End timestamp
133138287Smarks *              TimeElapsed         - Where the elapsed time is returned
13471867Smsmith *
135138287Smarks * RETURN:      Status and TimeElapsed
13671867Smsmith *
13771867Smsmith * DESCRIPTION: Computes the time elapsed (in microseconds) between two
13871867Smsmith *              PM Timer time stamps, taking into account the possibility of
13977424Smsmith *              rollovers, the timer resolution, and timer frequency.
14077424Smsmith *
14177424Smsmith *              The PM Timer's clock ticks at roughly 3.6 times per
14271867Smsmith *              _microsecond_, and its clock continues through Cx state
14371867Smsmith *              transitions (unlike many CPU timestamp counters) -- making it
14471867Smsmith *              a versatile and accurate timer.
14571867Smsmith *
146114237Snjl *              Note that this function accommodates only a single timer
14771867Smsmith *              rollover.  Thus for 24-bit timers, this function should only
14877424Smsmith *              be used for calculating durations less than ~4.6 seconds
149138287Smarks *              (~20 minutes for 32-bit timers) -- calculations below:
15071867Smsmith *
151114237Snjl *              2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
152114237Snjl *              2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
153114237Snjl *
15471867Smsmith ******************************************************************************/
15571867Smsmith
15671867SmsmithACPI_STATUS
15771867SmsmithAcpiGetTimerDuration (
15871867Smsmith    UINT32                  StartTicks,
15971867Smsmith    UINT32                  EndTicks,
16071867Smsmith    UINT32                  *TimeElapsed)
16171867Smsmith{
16291116Smsmith    ACPI_STATUS             Status;
163138287Smarks    UINT32                  DeltaTicks;
164202771Sjkim    UINT64                  Quotient;
16571867Smsmith
16678986Smsmith
167167802Sjkim    ACPI_FUNCTION_TRACE (AcpiGetTimerDuration);
16871867Smsmith
16980062Smsmith
17077424Smsmith    if (!TimeElapsed)
17171867Smsmith    {
17271867Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
17371867Smsmith    }
17471867Smsmith
17577424Smsmith    /*
17671867Smsmith     * Compute Tick Delta:
177138287Smarks     * Handle (max one) timer rollovers on 24-bit versus 32-bit timers.
17871867Smsmith     */
17971867Smsmith    if (StartTicks < EndTicks)
18071867Smsmith    {
18171867Smsmith        DeltaTicks = EndTicks - StartTicks;
18271867Smsmith    }
18377424Smsmith    else if (StartTicks > EndTicks)
18471867Smsmith    {
185167802Sjkim        if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0)
18671867Smsmith        {
18791116Smsmith            /* 24-bit Timer */
18891116Smsmith
18973561Smsmith            DeltaTicks = (((0x00FFFFFF - StartTicks) + EndTicks) & 0x00FFFFFF);
19071867Smsmith        }
19177424Smsmith        else
19271867Smsmith        {
19391116Smsmith            /* 32-bit Timer */
19491116Smsmith
19571867Smsmith            DeltaTicks = (0xFFFFFFFF - StartTicks) + EndTicks;
19671867Smsmith        }
19771867Smsmith    }
198138287Smarks    else /* StartTicks == EndTicks */
19973561Smsmith    {
20073561Smsmith        *TimeElapsed = 0;
20173561Smsmith        return_ACPI_STATUS (AE_OK);
20273561Smsmith    }
20371867Smsmith
20477424Smsmith    /*
205138287Smarks     * Compute Duration (Requires a 64-bit multiply and divide):
20671867Smsmith     *
20791116Smsmith     * TimeElapsed = (DeltaTicks * 1000000) / PM_TIMER_FREQUENCY;
20871867Smsmith     */
209138287Smarks    Status = AcpiUtShortDivide (((UINT64) DeltaTicks) * 1000000,
210138287Smarks                PM_TIMER_FREQUENCY, &Quotient, NULL);
21171867Smsmith
212138287Smarks    *TimeElapsed = (UINT32) Quotient;
21391116Smsmith    return_ACPI_STATUS (Status);
21471867Smsmith}
21571867Smsmith
216167802SjkimACPI_EXPORT_SYMBOL (AcpiGetTimerDuration)
21771867Smsmith
218231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */
219