xref: /openbmc/linux/drivers/acpi/acpica/hwtimer.c (revision da6f8320)
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, &quotient, 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