xref: /openbmc/linux/drivers/acpi/acpica/hwtimer.c (revision c41679a4)
195b482a8SLen Brown /******************************************************************************
295b482a8SLen Brown  *
395b482a8SLen Brown  * Name: hwtimer.c - ACPI Power Management Timer Interface
495b482a8SLen Brown  *
595b482a8SLen Brown  *****************************************************************************/
695b482a8SLen Brown 
795b482a8SLen Brown /*
877848130SBob Moore  * Copyright (C) 2000 - 2012, 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 
44214f2c90SPaul Gortmaker #include <linux/export.h>
4595b482a8SLen Brown #include <acpi/acpi.h>
46e2f7a777SLen Brown #include "accommon.h"
4795b482a8SLen Brown 
4895b482a8SLen Brown #define _COMPONENT          ACPI_HARDWARE
4995b482a8SLen Brown ACPI_MODULE_NAME("hwtimer")
5095b482a8SLen Brown 
5133620c54SBob Moore #if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
5295b482a8SLen Brown /******************************************************************************
5395b482a8SLen Brown  *
5495b482a8SLen Brown  * FUNCTION:    acpi_get_timer_resolution
5595b482a8SLen Brown  *
56ba494beeSBob Moore  * PARAMETERS:  resolution          - Where the resolution is returned
5795b482a8SLen Brown  *
5895b482a8SLen Brown  * RETURN:      Status and timer resolution
5995b482a8SLen Brown  *
6095b482a8SLen Brown  * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
6195b482a8SLen Brown  *
6295b482a8SLen Brown  ******************************************************************************/
6395b482a8SLen Brown acpi_status acpi_get_timer_resolution(u32 * resolution)
6495b482a8SLen Brown {
6595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_get_timer_resolution);
6695b482a8SLen Brown 
6795b482a8SLen Brown 	if (!resolution) {
6895b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
6995b482a8SLen Brown 	}
7095b482a8SLen Brown 
7195b482a8SLen Brown 	if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) {
7295b482a8SLen Brown 		*resolution = 24;
7395b482a8SLen Brown 	} else {
7495b482a8SLen Brown 		*resolution = 32;
7595b482a8SLen Brown 	}
7695b482a8SLen Brown 
7795b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
7895b482a8SLen Brown }
7995b482a8SLen Brown 
8095b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_timer_resolution)
8195b482a8SLen Brown 
8295b482a8SLen Brown /******************************************************************************
8395b482a8SLen Brown  *
8495b482a8SLen Brown  * FUNCTION:    acpi_get_timer
8595b482a8SLen Brown  *
86ba494beeSBob Moore  * PARAMETERS:  ticks               - Where the timer value is returned
8795b482a8SLen Brown  *
8895b482a8SLen Brown  * RETURN:      Status and current timer value (ticks)
8995b482a8SLen Brown  *
9095b482a8SLen Brown  * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
9195b482a8SLen Brown  *
9295b482a8SLen Brown  ******************************************************************************/
9395b482a8SLen Brown acpi_status acpi_get_timer(u32 * ticks)
9495b482a8SLen Brown {
9595b482a8SLen Brown 	acpi_status status;
9695b482a8SLen Brown 
9795b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_get_timer);
9895b482a8SLen Brown 
9995b482a8SLen Brown 	if (!ticks) {
10095b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
10195b482a8SLen Brown 	}
10295b482a8SLen Brown 
1031f86e8c1SLv Zheng 	status = acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block);
10495b482a8SLen Brown 
10595b482a8SLen Brown 	return_ACPI_STATUS(status);
10695b482a8SLen Brown }
10795b482a8SLen Brown 
10895b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_timer)
10995b482a8SLen Brown 
11095b482a8SLen Brown /******************************************************************************
11195b482a8SLen Brown  *
11295b482a8SLen Brown  * FUNCTION:    acpi_get_timer_duration
11395b482a8SLen Brown  *
11495b482a8SLen Brown  * PARAMETERS:  start_ticks         - Starting timestamp
11595b482a8SLen Brown  *              end_ticks           - End timestamp
11695b482a8SLen Brown  *              time_elapsed        - Where the elapsed time is returned
11795b482a8SLen Brown  *
11895b482a8SLen Brown  * RETURN:      Status and time_elapsed
11995b482a8SLen Brown  *
12095b482a8SLen Brown  * DESCRIPTION: Computes the time elapsed (in microseconds) between two
12195b482a8SLen Brown  *              PM Timer time stamps, taking into account the possibility of
12295b482a8SLen Brown  *              rollovers, the timer resolution, and timer frequency.
12395b482a8SLen Brown  *
12495b482a8SLen Brown  *              The PM Timer's clock ticks at roughly 3.6 times per
12595b482a8SLen Brown  *              _microsecond_, and its clock continues through Cx state
12695b482a8SLen Brown  *              transitions (unlike many CPU timestamp counters) -- making it
12795b482a8SLen Brown  *              a versatile and accurate timer.
12895b482a8SLen Brown  *
12995b482a8SLen Brown  *              Note that this function accommodates only a single timer
13095b482a8SLen Brown  *              rollover. Thus for 24-bit timers, this function should only
13195b482a8SLen Brown  *              be used for calculating durations less than ~4.6 seconds
13295b482a8SLen Brown  *              (~20 minutes for 32-bit timers) -- calculations below:
13395b482a8SLen Brown  *
13495b482a8SLen Brown  *              2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
13595b482a8SLen Brown  *              2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
13695b482a8SLen Brown  *
13795b482a8SLen Brown  ******************************************************************************/
13895b482a8SLen Brown acpi_status
13995b482a8SLen Brown acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed)
14095b482a8SLen Brown {
14195b482a8SLen Brown 	acpi_status status;
14295b482a8SLen Brown 	u32 delta_ticks;
1435df7e6cbSBob Moore 	u64 quotient;
14495b482a8SLen Brown 
14595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_get_timer_duration);
14695b482a8SLen Brown 
14795b482a8SLen Brown 	if (!time_elapsed) {
14895b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
14995b482a8SLen Brown 	}
15095b482a8SLen Brown 
15195b482a8SLen Brown 	/*
15295b482a8SLen Brown 	 * Compute Tick Delta:
15395b482a8SLen Brown 	 * Handle (max one) timer rollovers on 24-bit versus 32-bit timers.
15495b482a8SLen Brown 	 */
15595b482a8SLen Brown 	if (start_ticks < end_ticks) {
15695b482a8SLen Brown 		delta_ticks = end_ticks - start_ticks;
15795b482a8SLen Brown 	} else if (start_ticks > end_ticks) {
15895b482a8SLen Brown 		if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) {
15995b482a8SLen Brown 
16095b482a8SLen Brown 			/* 24-bit Timer */
16195b482a8SLen Brown 
16295b482a8SLen Brown 			delta_ticks =
16395b482a8SLen Brown 			    (((0x00FFFFFF - start_ticks) +
16495b482a8SLen Brown 			      end_ticks) & 0x00FFFFFF);
16595b482a8SLen Brown 		} else {
16695b482a8SLen Brown 			/* 32-bit Timer */
16795b482a8SLen Brown 
16895b482a8SLen Brown 			delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks;
16995b482a8SLen Brown 		}
17095b482a8SLen Brown 	} else {		/* start_ticks == end_ticks */
17195b482a8SLen Brown 
17295b482a8SLen Brown 		*time_elapsed = 0;
17395b482a8SLen Brown 		return_ACPI_STATUS(AE_OK);
17495b482a8SLen Brown 	}
17595b482a8SLen Brown 
17695b482a8SLen Brown 	/*
17795b482a8SLen Brown 	 * Compute Duration (Requires a 64-bit multiply and divide):
17895b482a8SLen Brown 	 *
179c41679a4SBob Moore 	 * time_elapsed (microseconds) =
180c41679a4SBob Moore 	 *  (delta_ticks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY;
18195b482a8SLen Brown 	 */
182c41679a4SBob Moore 	status = acpi_ut_short_divide(((u64)delta_ticks) * ACPI_USEC_PER_SEC,
183c41679a4SBob Moore 				      ACPI_PM_TIMER_FREQUENCY, &quotient, NULL);
18495b482a8SLen Brown 
18595b482a8SLen Brown 	*time_elapsed = (u32) quotient;
18695b482a8SLen Brown 	return_ACPI_STATUS(status);
18795b482a8SLen Brown }
18895b482a8SLen Brown 
18995b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_timer_duration)
19033620c54SBob Moore #endif				/* !ACPI_REDUCED_HARDWARE */
191