171867Smsmith/******************************************************************************
271867Smsmith *
371867Smsmith * Name: hwtimer.c - ACPI Power Management Timer Interface
471867Smsmith *
571867Smsmith *****************************************************************************/
671867Smsmith
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
971867Smsmith * All rights reserved.
1071867Smsmith *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
2571867Smsmith *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
2971867Smsmith *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
4371867Smsmith
44281075Sdim#define EXPORT_ACPI_INTERFACES
45281075Sdim
46193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
47193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
4871867Smsmith
4977424Smsmith#define _COMPONENT          ACPI_HARDWARE
5091116Smsmith        ACPI_MODULE_NAME    ("hwtimer")
5171867Smsmith
5271867Smsmith
53231844Sjkim#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
5471867Smsmith/******************************************************************************
5571867Smsmith *
5671867Smsmith * FUNCTION:    AcpiGetTimerResolution
5771867Smsmith *
58138287Smarks * PARAMETERS:  Resolution          - Where the resolution is returned
5971867Smsmith *
60138287Smarks * RETURN:      Status and timer resolution
6171867Smsmith *
62138287Smarks * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
6371867Smsmith *
6471867Smsmith ******************************************************************************/
6571867Smsmith
6671867SmsmithACPI_STATUS
6771867SmsmithAcpiGetTimerResolution (
6871867Smsmith    UINT32                  *Resolution)
6971867Smsmith{
70167802Sjkim    ACPI_FUNCTION_TRACE (AcpiGetTimerResolution);
7171867Smsmith
7277424Smsmith
7371867Smsmith    if (!Resolution)
7471867Smsmith    {
7571867Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
7671867Smsmith    }
7771867Smsmith
78167802Sjkim    if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0)
7971867Smsmith    {
8071867Smsmith        *Resolution = 24;
8171867Smsmith    }
8271867Smsmith    else
8371867Smsmith    {
8471867Smsmith        *Resolution = 32;
8571867Smsmith    }
8671867Smsmith
8771867Smsmith    return_ACPI_STATUS (AE_OK);
8871867Smsmith}
8971867Smsmith
90167802SjkimACPI_EXPORT_SYMBOL (AcpiGetTimerResolution)
9171867Smsmith
92167802Sjkim
9371867Smsmith/******************************************************************************
9471867Smsmith *
9571867Smsmith * FUNCTION:    AcpiGetTimer
9671867Smsmith *
97138287Smarks * PARAMETERS:  Ticks               - Where the timer value is returned
9871867Smsmith *
99151937Sjkim * RETURN:      Status and current timer value (ticks)
10071867Smsmith *
101138287Smarks * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
10271867Smsmith *
10371867Smsmith ******************************************************************************/
10471867Smsmith
10571867SmsmithACPI_STATUS
10671867SmsmithAcpiGetTimer (
10771867Smsmith    UINT32                  *Ticks)
10871867Smsmith{
10999679Siwasaki    ACPI_STATUS             Status;
11099679Siwasaki
11199679Siwasaki
112167802Sjkim    ACPI_FUNCTION_TRACE (AcpiGetTimer);
11371867Smsmith
11483174Smsmith
11571867Smsmith    if (!Ticks)
11671867Smsmith    {
11771867Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
11871867Smsmith    }
11971867Smsmith
120253690Sjkim    /* ACPI 5.0A: PM Timer is optional */
121253690Sjkim
122253690Sjkim    if (!AcpiGbl_FADT.XPmTimerBlock.Address)
123253690Sjkim    {
124253690Sjkim        return_ACPI_STATUS (AE_SUPPORT);
125253690Sjkim    }
126253690Sjkim
127197104Sjkim    Status = AcpiHwRead (Ticks, &AcpiGbl_FADT.XPmTimerBlock);
12899679Siwasaki    return_ACPI_STATUS (Status);
12971867Smsmith}
13071867Smsmith
131167802SjkimACPI_EXPORT_SYMBOL (AcpiGetTimer)
13271867Smsmith
133167802Sjkim
13471867Smsmith/******************************************************************************
13571867Smsmith *
13671867Smsmith * FUNCTION:    AcpiGetTimerDuration
13771867Smsmith *
138138287Smarks * PARAMETERS:  StartTicks          - Starting timestamp
139138287Smarks *              EndTicks            - End timestamp
140138287Smarks *              TimeElapsed         - Where the elapsed time is returned
14171867Smsmith *
142138287Smarks * RETURN:      Status and TimeElapsed
14371867Smsmith *
14471867Smsmith * DESCRIPTION: Computes the time elapsed (in microseconds) between two
14571867Smsmith *              PM Timer time stamps, taking into account the possibility of
14677424Smsmith *              rollovers, the timer resolution, and timer frequency.
14777424Smsmith *
14877424Smsmith *              The PM Timer's clock ticks at roughly 3.6 times per
14971867Smsmith *              _microsecond_, and its clock continues through Cx state
15071867Smsmith *              transitions (unlike many CPU timestamp counters) -- making it
15171867Smsmith *              a versatile and accurate timer.
15271867Smsmith *
153114237Snjl *              Note that this function accommodates only a single timer
154241973Sjkim *              rollover. Thus for 24-bit timers, this function should only
15577424Smsmith *              be used for calculating durations less than ~4.6 seconds
156138287Smarks *              (~20 minutes for 32-bit timers) -- calculations below:
15771867Smsmith *
158114237Snjl *              2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
159114237Snjl *              2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
160114237Snjl *
16171867Smsmith ******************************************************************************/
16271867Smsmith
16371867SmsmithACPI_STATUS
16471867SmsmithAcpiGetTimerDuration (
16571867Smsmith    UINT32                  StartTicks,
16671867Smsmith    UINT32                  EndTicks,
16771867Smsmith    UINT32                  *TimeElapsed)
16871867Smsmith{
16991116Smsmith    ACPI_STATUS             Status;
170138287Smarks    UINT32                  DeltaTicks;
171202771Sjkim    UINT64                  Quotient;
17271867Smsmith
17378986Smsmith
174167802Sjkim    ACPI_FUNCTION_TRACE (AcpiGetTimerDuration);
17571867Smsmith
17680062Smsmith
17777424Smsmith    if (!TimeElapsed)
17871867Smsmith    {
17971867Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
18071867Smsmith    }
18171867Smsmith
182253690Sjkim    /* ACPI 5.0A: PM Timer is optional */
183253690Sjkim
184253690Sjkim    if (!AcpiGbl_FADT.XPmTimerBlock.Address)
185253690Sjkim    {
186253690Sjkim        return_ACPI_STATUS (AE_SUPPORT);
187253690Sjkim    }
188253690Sjkim
18977424Smsmith    /*
19071867Smsmith     * Compute Tick Delta:
191138287Smarks     * Handle (max one) timer rollovers on 24-bit versus 32-bit timers.
19271867Smsmith     */
19371867Smsmith    if (StartTicks < EndTicks)
19471867Smsmith    {
19571867Smsmith        DeltaTicks = EndTicks - StartTicks;
19671867Smsmith    }
19777424Smsmith    else if (StartTicks > EndTicks)
19871867Smsmith    {
199167802Sjkim        if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0)
20071867Smsmith        {
20191116Smsmith            /* 24-bit Timer */
20291116Smsmith
20373561Smsmith            DeltaTicks = (((0x00FFFFFF - StartTicks) + EndTicks) & 0x00FFFFFF);
20471867Smsmith        }
20577424Smsmith        else
20671867Smsmith        {
20791116Smsmith            /* 32-bit Timer */
20891116Smsmith
20971867Smsmith            DeltaTicks = (0xFFFFFFFF - StartTicks) + EndTicks;
21071867Smsmith        }
21171867Smsmith    }
212138287Smarks    else /* StartTicks == EndTicks */
21373561Smsmith    {
21473561Smsmith        *TimeElapsed = 0;
21573561Smsmith        return_ACPI_STATUS (AE_OK);
21673561Smsmith    }
21771867Smsmith
21877424Smsmith    /*
219138287Smarks     * Compute Duration (Requires a 64-bit multiply and divide):
22071867Smsmith     *
221245582Sjkim     * TimeElapsed (microseconds) =
222245582Sjkim     *  (DeltaTicks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY;
22371867Smsmith     */
224245582Sjkim    Status = AcpiUtShortDivide (((UINT64) DeltaTicks) * ACPI_USEC_PER_SEC,
225245582Sjkim                ACPI_PM_TIMER_FREQUENCY, &Quotient, NULL);
22671867Smsmith
227138287Smarks    *TimeElapsed = (UINT32) Quotient;
22891116Smsmith    return_ACPI_STATUS (Status);
22971867Smsmith}
23071867Smsmith
231167802SjkimACPI_EXPORT_SYMBOL (AcpiGetTimerDuration)
23271867Smsmith
233231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */
234