hwtimer.c revision 278970
152419Sjulian/******************************************************************************
252419Sjulian *
352419Sjulian * Name: hwtimer.c - ACPI Power Management Timer Interface
452419Sjulian *
552419Sjulian *****************************************************************************/
652419Sjulian
752419Sjulian/*
852419Sjulian * Copyright (C) 2000 - 2015, Intel Corp.
952419Sjulian * All rights reserved.
1052419Sjulian *
1152419Sjulian * Redistribution and use in source and binary forms, with or without
1252419Sjulian * modification, are permitted provided that the following conditions
1352419Sjulian * are met:
1452419Sjulian * 1. Redistributions of source code must retain the above copyright
1552419Sjulian *    notice, this list of conditions, and the following disclaimer,
1652419Sjulian *    without modification.
1752419Sjulian * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1852419Sjulian *    substantially similar to the "NO WARRANTY" disclaimer below
1952419Sjulian *    ("Disclaimer") and any redistribution must be conditioned upon
2052419Sjulian *    including a substantially similar Disclaimer requirement for further
2152419Sjulian *    binary redistribution.
2252419Sjulian * 3. Neither the names of the above-listed copyright holders nor the names
2352419Sjulian *    of any contributors may be used to endorse or promote products derived
2452419Sjulian *    from this software without specific prior written permission.
2552419Sjulian *
2652419Sjulian * Alternatively, this software may be distributed under the terms of the
2752419Sjulian * GNU General Public License ("GPL") version 2 as published by the Free
2852419Sjulian * Software Foundation.
2952419Sjulian *
3052419Sjulian * NO WARRANTY
3152419Sjulian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3252419Sjulian * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3352419Sjulian * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3452419Sjulian * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3552419Sjulian * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3652419Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3752419Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3852419Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3952419Sjulian * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4052419Sjulian * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4152419Sjulian * POSSIBILITY OF SUCH DAMAGES.
4252419Sjulian */
4352419Sjulian
4452419Sjulian#define EXPORT_ACPI_INTERFACES
4552419Sjulian
4652419Sjulian#include <contrib/dev/acpica/include/acpi.h>
4752419Sjulian#include <contrib/dev/acpica/include/accommon.h>
4852419Sjulian
4952419Sjulian#define _COMPONENT          ACPI_HARDWARE
5052562Sjulian        ACPI_MODULE_NAME    ("hwtimer")
5152419Sjulian
5252419Sjulian
5352419Sjulian#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
5452419Sjulian/******************************************************************************
5552419Sjulian *
5652419Sjulian * FUNCTION:    AcpiGetTimerResolution
5752419Sjulian *
5852419Sjulian * PARAMETERS:  Resolution          - Where the resolution is returned
5952419Sjulian *
6052419Sjulian * RETURN:      Status and timer resolution
6152419Sjulian *
6252419Sjulian * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
6352419Sjulian *
6452419Sjulian ******************************************************************************/
6552419Sjulian
6652419SjulianACPI_STATUS
6752419SjulianAcpiGetTimerResolution (
6852419Sjulian    UINT32                  *Resolution)
6952441Sjulian{
7052419Sjulian    ACPI_FUNCTION_TRACE (AcpiGetTimerResolution);
7152419Sjulian
7252419Sjulian
7352419Sjulian    if (!Resolution)
7452419Sjulian    {
7552419Sjulian        return_ACPI_STATUS (AE_BAD_PARAMETER);
7652419Sjulian    }
7752419Sjulian
7852419Sjulian    if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0)
7952419Sjulian    {
8052419Sjulian        *Resolution = 24;
8152419Sjulian    }
8252419Sjulian    else
8352419Sjulian    {
8452562Sjulian        *Resolution = 32;
8552722Sjulian    }
8652722Sjulian
8752419Sjulian    return_ACPI_STATUS (AE_OK);
8852419Sjulian}
8952419Sjulian
9052419SjulianACPI_EXPORT_SYMBOL (AcpiGetTimerResolution)
9152419Sjulian
9252419Sjulian
9352419Sjulian/******************************************************************************
9452419Sjulian *
9552419Sjulian * FUNCTION:    AcpiGetTimer
9652419Sjulian *
9753042Sjulian * PARAMETERS:  Ticks               - Where the timer value is returned
9852419Sjulian *
9952419Sjulian * RETURN:      Status and current timer value (ticks)
10052419Sjulian *
10152419Sjulian * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
10252419Sjulian *
10352419Sjulian ******************************************************************************/
10452419Sjulian
10552419SjulianACPI_STATUS
10652419SjulianAcpiGetTimer (
10752562Sjulian    UINT32                  *Ticks)
10852419Sjulian{
10952419Sjulian    ACPI_STATUS             Status;
11052419Sjulian
11152419Sjulian
11252419Sjulian    ACPI_FUNCTION_TRACE (AcpiGetTimer);
11352419Sjulian
11452419Sjulian
11552419Sjulian    if (!Ticks)
11652419Sjulian    {
11752419Sjulian        return_ACPI_STATUS (AE_BAD_PARAMETER);
11852562Sjulian    }
11952419Sjulian
12052419Sjulian    /* ACPI 5.0A: PM Timer is optional */
12152419Sjulian
12252419Sjulian    if (!AcpiGbl_FADT.XPmTimerBlock.Address)
12352419Sjulian    {
12452562Sjulian        return_ACPI_STATUS (AE_SUPPORT);
12552419Sjulian    }
12652419Sjulian
12752419Sjulian    Status = AcpiHwRead (Ticks, &AcpiGbl_FADT.XPmTimerBlock);
12852419Sjulian    return_ACPI_STATUS (Status);
12952419Sjulian}
13052419Sjulian
13152419SjulianACPI_EXPORT_SYMBOL (AcpiGetTimer)
13252419Sjulian
13352419Sjulian
13452419Sjulian/******************************************************************************
13552419Sjulian *
13652419Sjulian * FUNCTION:    AcpiGetTimerDuration
13752419Sjulian *
13852419Sjulian * PARAMETERS:  StartTicks          - Starting timestamp
13952419Sjulian *              EndTicks            - End timestamp
14052419Sjulian *              TimeElapsed         - Where the elapsed time is returned
14152419Sjulian *
14252419Sjulian * RETURN:      Status and TimeElapsed
14352419Sjulian *
14452419Sjulian * DESCRIPTION: Computes the time elapsed (in microseconds) between two
14552419Sjulian *              PM Timer time stamps, taking into account the possibility of
14652419Sjulian *              rollovers, the timer resolution, and timer frequency.
14752419Sjulian *
14852419Sjulian *              The PM Timer's clock ticks at roughly 3.6 times per
14952419Sjulian *              _microsecond_, and its clock continues through Cx state
15052562Sjulian *              transitions (unlike many CPU timestamp counters) -- making it
15152562Sjulian *              a versatile and accurate timer.
15252419Sjulian *
15352419Sjulian *              Note that this function accommodates only a single timer
15452419Sjulian *              rollover. Thus for 24-bit timers, this function should only
15552419Sjulian *              be used for calculating durations less than ~4.6 seconds
15652419Sjulian *              (~20 minutes for 32-bit timers) -- calculations below:
15752419Sjulian *
15852419Sjulian *              2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
15952419Sjulian *              2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
16052419Sjulian *
16152419Sjulian ******************************************************************************/
16252419Sjulian
16352419SjulianACPI_STATUS
16452562SjulianAcpiGetTimerDuration (
16552562Sjulian    UINT32                  StartTicks,
16652419Sjulian    UINT32                  EndTicks,
16752419Sjulian    UINT32                  *TimeElapsed)
16852419Sjulian{
16952419Sjulian    ACPI_STATUS             Status;
17052419Sjulian    UINT32                  DeltaTicks;
17152419Sjulian    UINT64                  Quotient;
17252419Sjulian
17352419Sjulian
17452419Sjulian    ACPI_FUNCTION_TRACE (AcpiGetTimerDuration);
17552419Sjulian
17652419Sjulian
17752419Sjulian    if (!TimeElapsed)
17852419Sjulian    {
17952419Sjulian        return_ACPI_STATUS (AE_BAD_PARAMETER);
18052419Sjulian    }
18152419Sjulian
18252419Sjulian    /* ACPI 5.0A: PM Timer is optional */
18352419Sjulian
18452419Sjulian    if (!AcpiGbl_FADT.XPmTimerBlock.Address)
18552419Sjulian    {
18652419Sjulian        return_ACPI_STATUS (AE_SUPPORT);
18752419Sjulian    }
18852419Sjulian
18952419Sjulian    /*
19052419Sjulian     * Compute Tick Delta:
19152419Sjulian     * Handle (max one) timer rollovers on 24-bit versus 32-bit timers.
19252419Sjulian     */
19352419Sjulian    if (StartTicks < EndTicks)
19452419Sjulian    {
19552419Sjulian        DeltaTicks = EndTicks - StartTicks;
19652419Sjulian    }
19752419Sjulian    else if (StartTicks > EndTicks)
19852419Sjulian    {
19952419Sjulian        if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0)
20052419Sjulian        {
20152419Sjulian            /* 24-bit Timer */
20252419Sjulian
20352419Sjulian            DeltaTicks = (((0x00FFFFFF - StartTicks) + EndTicks) & 0x00FFFFFF);
20452419Sjulian        }
20552419Sjulian        else
20652419Sjulian        {
20752419Sjulian            /* 32-bit Timer */
20852419Sjulian
20952419Sjulian            DeltaTicks = (0xFFFFFFFF - StartTicks) + EndTicks;
21052419Sjulian        }
21152419Sjulian    }
21252419Sjulian    else /* StartTicks == EndTicks */
21352419Sjulian    {
21452419Sjulian        *TimeElapsed = 0;
21552419Sjulian        return_ACPI_STATUS (AE_OK);
21652419Sjulian    }
21752419Sjulian
21852419Sjulian    /*
21952419Sjulian     * Compute Duration (Requires a 64-bit multiply and divide):
22052419Sjulian     *
22152419Sjulian     * TimeElapsed (microseconds) =
22252419Sjulian     *  (DeltaTicks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY;
22352419Sjulian     */
22452419Sjulian    Status = AcpiUtShortDivide (((UINT64) DeltaTicks) * ACPI_USEC_PER_SEC,
225                ACPI_PM_TIMER_FREQUENCY, &Quotient, NULL);
226
227    *TimeElapsed = (UINT32) Quotient;
228    return_ACPI_STATUS (Status);
229}
230
231ACPI_EXPORT_SYMBOL (AcpiGetTimerDuration)
232
233#endif /* !ACPI_REDUCED_HARDWARE */
234