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