195b482a8SLen Brown /****************************************************************************** 295b482a8SLen Brown * 395b482a8SLen Brown * Name: hwtimer.c - ACPI Power Management Timer Interface 495b482a8SLen Brown * 595b482a8SLen Brown *****************************************************************************/ 695b482a8SLen Brown 795b482a8SLen Brown /* 8da6f8320SBob Moore * Copyright (C) 2000 - 2018, Intel Corp. 995b482a8SLen Brown * All rights reserved. 1095b482a8SLen Brown * 1195b482a8SLen Brown * Redistribution and use in source and binary forms, with or without 1295b482a8SLen Brown * modification, are permitted provided that the following conditions 1395b482a8SLen Brown * are met: 1495b482a8SLen Brown * 1. Redistributions of source code must retain the above copyright 1595b482a8SLen Brown * notice, this list of conditions, and the following disclaimer, 1695b482a8SLen Brown * without modification. 1795b482a8SLen Brown * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1895b482a8SLen Brown * substantially similar to the "NO WARRANTY" disclaimer below 1995b482a8SLen Brown * ("Disclaimer") and any redistribution must be conditioned upon 2095b482a8SLen Brown * including a substantially similar Disclaimer requirement for further 2195b482a8SLen Brown * binary redistribution. 2295b482a8SLen Brown * 3. Neither the names of the above-listed copyright holders nor the names 2395b482a8SLen Brown * of any contributors may be used to endorse or promote products derived 2495b482a8SLen Brown * from this software without specific prior written permission. 2595b482a8SLen Brown * 2695b482a8SLen Brown * Alternatively, this software may be distributed under the terms of the 2795b482a8SLen Brown * GNU General Public License ("GPL") version 2 as published by the Free 2895b482a8SLen Brown * Software Foundation. 2995b482a8SLen Brown * 3095b482a8SLen Brown * NO WARRANTY 3195b482a8SLen Brown * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3295b482a8SLen Brown * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3395b482a8SLen Brown * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3495b482a8SLen Brown * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3595b482a8SLen Brown * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3695b482a8SLen Brown * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3795b482a8SLen Brown * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3895b482a8SLen Brown * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3995b482a8SLen Brown * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4095b482a8SLen Brown * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4195b482a8SLen Brown * POSSIBILITY OF SUCH DAMAGES. 4295b482a8SLen Brown */ 4395b482a8SLen Brown 44839e928fSLv Zheng #define EXPORT_ACPI_INTERFACES 45839e928fSLv Zheng 4695b482a8SLen Brown #include <acpi/acpi.h> 47e2f7a777SLen Brown #include "accommon.h" 4895b482a8SLen Brown 4995b482a8SLen Brown #define _COMPONENT ACPI_HARDWARE 5095b482a8SLen Brown ACPI_MODULE_NAME("hwtimer") 5195b482a8SLen Brown 5233620c54SBob Moore #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 5395b482a8SLen Brown /****************************************************************************** 5495b482a8SLen Brown * 5595b482a8SLen Brown * FUNCTION: acpi_get_timer_resolution 5695b482a8SLen Brown * 57ba494beeSBob Moore * PARAMETERS: resolution - Where the resolution is returned 5895b482a8SLen Brown * 5995b482a8SLen Brown * RETURN: Status and timer resolution 6095b482a8SLen Brown * 6195b482a8SLen Brown * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits). 6295b482a8SLen Brown * 6395b482a8SLen Brown ******************************************************************************/ 6495b482a8SLen Brown acpi_status acpi_get_timer_resolution(u32 * resolution) 6595b482a8SLen Brown { 6695b482a8SLen Brown ACPI_FUNCTION_TRACE(acpi_get_timer_resolution); 6795b482a8SLen Brown 6895b482a8SLen Brown if (!resolution) { 6995b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER); 7095b482a8SLen Brown } 7195b482a8SLen Brown 7295b482a8SLen Brown if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) { 7395b482a8SLen Brown *resolution = 24; 7495b482a8SLen Brown } else { 7595b482a8SLen Brown *resolution = 32; 7695b482a8SLen Brown } 7795b482a8SLen Brown 7895b482a8SLen Brown return_ACPI_STATUS(AE_OK); 7995b482a8SLen Brown } 8095b482a8SLen Brown 8195b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_timer_resolution) 8295b482a8SLen Brown 8395b482a8SLen Brown /****************************************************************************** 8495b482a8SLen Brown * 8595b482a8SLen Brown * FUNCTION: acpi_get_timer 8695b482a8SLen Brown * 87ba494beeSBob Moore * PARAMETERS: ticks - Where the timer value is returned 8895b482a8SLen Brown * 8995b482a8SLen Brown * RETURN: Status and current timer value (ticks) 9095b482a8SLen Brown * 9195b482a8SLen Brown * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks). 9295b482a8SLen Brown * 9395b482a8SLen Brown ******************************************************************************/ 9495b482a8SLen Brown acpi_status acpi_get_timer(u32 * ticks) 9595b482a8SLen Brown { 9695b482a8SLen Brown acpi_status status; 978092936dSBob Moore u64 timer_value; 9895b482a8SLen Brown 9995b482a8SLen Brown ACPI_FUNCTION_TRACE(acpi_get_timer); 10095b482a8SLen Brown 10195b482a8SLen Brown if (!ticks) { 10295b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER); 10395b482a8SLen Brown } 10495b482a8SLen Brown 1051d82980cSBob Moore /* ACPI 5.0A: PM Timer is optional */ 10695b482a8SLen Brown 1071d82980cSBob Moore if (!acpi_gbl_FADT.xpm_timer_block.address) { 1081d82980cSBob Moore return_ACPI_STATUS(AE_SUPPORT); 1091d82980cSBob Moore } 1101d82980cSBob Moore 1118092936dSBob Moore status = acpi_hw_read(&timer_value, &acpi_gbl_FADT.xpm_timer_block); 1128092936dSBob Moore if (ACPI_SUCCESS(status)) { 1138092936dSBob Moore 1148092936dSBob Moore /* ACPI PM Timer is defined to be 32 bits (PM_TMR_LEN) */ 1158092936dSBob Moore 1168092936dSBob Moore *ticks = (u32)timer_value; 1178092936dSBob Moore } 1188092936dSBob Moore 11995b482a8SLen Brown return_ACPI_STATUS(status); 12095b482a8SLen Brown } 12195b482a8SLen Brown 12295b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_timer) 12395b482a8SLen Brown 12495b482a8SLen Brown /****************************************************************************** 12595b482a8SLen Brown * 12695b482a8SLen Brown * FUNCTION: acpi_get_timer_duration 12795b482a8SLen Brown * 12895b482a8SLen Brown * PARAMETERS: start_ticks - Starting timestamp 12995b482a8SLen Brown * end_ticks - End timestamp 13095b482a8SLen Brown * time_elapsed - Where the elapsed time is returned 13195b482a8SLen Brown * 13295b482a8SLen Brown * RETURN: Status and time_elapsed 13395b482a8SLen Brown * 13495b482a8SLen Brown * DESCRIPTION: Computes the time elapsed (in microseconds) between two 13595b482a8SLen Brown * PM Timer time stamps, taking into account the possibility of 13695b482a8SLen Brown * rollovers, the timer resolution, and timer frequency. 13795b482a8SLen Brown * 13895b482a8SLen Brown * The PM Timer's clock ticks at roughly 3.6 times per 13995b482a8SLen Brown * _microsecond_, and its clock continues through Cx state 14095b482a8SLen Brown * transitions (unlike many CPU timestamp counters) -- making it 14195b482a8SLen Brown * a versatile and accurate timer. 14295b482a8SLen Brown * 14395b482a8SLen Brown * Note that this function accommodates only a single timer 14495b482a8SLen Brown * rollover. Thus for 24-bit timers, this function should only 14595b482a8SLen Brown * be used for calculating durations less than ~4.6 seconds 14695b482a8SLen Brown * (~20 minutes for 32-bit timers) -- calculations below: 14795b482a8SLen Brown * 14895b482a8SLen Brown * 2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec 14995b482a8SLen Brown * 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes 15095b482a8SLen Brown * 15195b482a8SLen Brown ******************************************************************************/ 15295b482a8SLen Brown acpi_status 15395b482a8SLen Brown acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 *time_elapsed) 15495b482a8SLen Brown { 15595b482a8SLen Brown acpi_status status; 1568f275615SJung-uk Kim u64 delta_ticks; 1575df7e6cbSBob Moore u64 quotient; 15895b482a8SLen Brown 15995b482a8SLen Brown ACPI_FUNCTION_TRACE(acpi_get_timer_duration); 16095b482a8SLen Brown 16195b482a8SLen Brown if (!time_elapsed) { 16295b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER); 16395b482a8SLen Brown } 16495b482a8SLen Brown 1651d82980cSBob Moore /* ACPI 5.0A: PM Timer is optional */ 1661d82980cSBob Moore 1671d82980cSBob Moore if (!acpi_gbl_FADT.xpm_timer_block.address) { 1681d82980cSBob Moore return_ACPI_STATUS(AE_SUPPORT); 1691d82980cSBob Moore } 1701d82980cSBob Moore 1718f275615SJung-uk Kim if (start_ticks == end_ticks) { 1728f275615SJung-uk Kim *time_elapsed = 0; 1738f275615SJung-uk Kim return_ACPI_STATUS(AE_OK); 1748f275615SJung-uk Kim } 1758f275615SJung-uk Kim 17695b482a8SLen Brown /* 17795b482a8SLen Brown * Compute Tick Delta: 17895b482a8SLen Brown * Handle (max one) timer rollovers on 24-bit versus 32-bit timers. 17995b482a8SLen Brown */ 1808f275615SJung-uk Kim delta_ticks = end_ticks; 1818f275615SJung-uk Kim if (start_ticks > end_ticks) { 18295b482a8SLen Brown if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) { 18395b482a8SLen Brown 18495b482a8SLen Brown /* 24-bit Timer */ 18595b482a8SLen Brown 1868f275615SJung-uk Kim delta_ticks |= (u64)1 << 24; 18795b482a8SLen Brown } else { 18895b482a8SLen Brown /* 32-bit Timer */ 18995b482a8SLen Brown 1908f275615SJung-uk Kim delta_ticks |= (u64)1 << 32; 19195b482a8SLen Brown } 19295b482a8SLen Brown } 1938f275615SJung-uk Kim delta_ticks -= start_ticks; 19495b482a8SLen Brown 19595b482a8SLen Brown /* 19695b482a8SLen Brown * Compute Duration (Requires a 64-bit multiply and divide): 19795b482a8SLen Brown * 198c41679a4SBob Moore * time_elapsed (microseconds) = 199c41679a4SBob Moore * (delta_ticks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY; 20095b482a8SLen Brown */ 2018f275615SJung-uk Kim status = acpi_ut_short_divide(delta_ticks * ACPI_USEC_PER_SEC, 202c41679a4SBob Moore ACPI_PM_TIMER_FREQUENCY, "ient, NULL); 20395b482a8SLen Brown 20495b482a8SLen Brown *time_elapsed = (u32)quotient; 20595b482a8SLen Brown return_ACPI_STATUS(status); 20695b482a8SLen Brown } 20795b482a8SLen Brown 20895b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_timer_duration) 20933620c54SBob Moore #endif /* !ACPI_REDUCED_HARDWARE */ 210