xref: /illumos-gate/usr/src/uts/i86pc/sys/hpet_acpi.h (revision fdcca78f)
10e751525SEric Saxe /*
20e751525SEric Saxe  * CDDL HEADER START
30e751525SEric Saxe  *
40e751525SEric Saxe  * The contents of this file are subject to the terms of the
50e751525SEric Saxe  * Common Development and Distribution License (the "License").
60e751525SEric Saxe  * You may not use this file except in compliance with the License.
70e751525SEric Saxe  *
80e751525SEric Saxe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90e751525SEric Saxe  * or http://www.opensolaris.org/os/licensing.
100e751525SEric Saxe  * See the License for the specific language governing permissions
110e751525SEric Saxe  * and limitations under the License.
120e751525SEric Saxe  *
130e751525SEric Saxe  * When distributing Covered Code, include this CDDL HEADER in each
140e751525SEric Saxe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150e751525SEric Saxe  * If applicable, add the following below this CDDL HEADER, with the
160e751525SEric Saxe  * fields enclosed by brackets "[]" replaced with your own identifying
170e751525SEric Saxe  * information: Portions Copyright [yyyy] [name of copyright owner]
180e751525SEric Saxe  *
190e751525SEric Saxe  * CDDL HEADER END
200e751525SEric Saxe  */
210e751525SEric Saxe /*
225cd376e8SJimmy Vetayases  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
230e751525SEric Saxe  */
240e751525SEric Saxe 
250e751525SEric Saxe #ifndef	_HPET_ACPI_H
260e751525SEric Saxe #define	_HPET_ACPI_H
270e751525SEric Saxe 
280e751525SEric Saxe #if defined(_KERNEL)
290e751525SEric Saxe #include <sys/acpi/acpi.h>
300e751525SEric Saxe #include <sys/acpi/actbl1.h>
310e751525SEric Saxe #include <sys/acpica.h>
320e751525SEric Saxe #endif	/* defined(_KERNEL) */
330e751525SEric Saxe 
340e751525SEric Saxe #ifdef __cplusplus
350e751525SEric Saxe extern "C" {
360e751525SEric Saxe #endif
370e751525SEric Saxe 
380e751525SEric Saxe /*
39*fdcca78fSJoshua M. Clulow  * illumos uses an HPET Timer to generate interrupts for CPUs in Deep C-state
400e751525SEric Saxe  * with stalled LAPIC Timers.  All CPUs use one HPET timer.  The timer's
410e751525SEric Saxe  * interrupt targets one CPU (via the I/O APIC).  The one CPU that receives
420e751525SEric Saxe  * the HPET's interrupt wakes up other CPUs as needed during the HPET Interrupt
430e751525SEric Saxe  * Service Routing.  The HPET ISR uses poke_cpus to wake up other CPUs with an
440e751525SEric Saxe  * Inter Processor Interrupt.
450e751525SEric Saxe  *
460e751525SEric Saxe  * Please see the Intel Programmer's guides.  Interrupts are disabled before
470e751525SEric Saxe  * a CPU Halts into Deep C-state.  (This allows CPU-hardware-specific cleanup
480e751525SEric Saxe  * before servicing interrupts.)  When a Deep C-state CPU wakes up (due to
49*fdcca78fSJoshua M. Clulow  * an externally generated interrupt), it resumes execution where it halted.
500e751525SEric Saxe  * The CPU returning from Deep C-state must enable interrupts before it will
510e751525SEric Saxe  * handle the pending interrupt that woke it from Deep C-state.
520e751525SEric Saxe  *
530e751525SEric Saxe  *
540e751525SEric Saxe  * HPET bits as defined in the Intel IA-PC HPET Specification Rev 1.0a.
550e751525SEric Saxe  *
560e751525SEric Saxe  * The physical address space layout of the memory mapped HPET looks like this:
570e751525SEric Saxe  *
580e751525SEric Saxe  * struct hpet {
590e751525SEric Saxe  *	uint64_t	gen_cap;
600e751525SEric Saxe  *	uint64_t	res1;
610e751525SEric Saxe  *	uint64_t	gen_config;
620e751525SEric Saxe  *	uint64_t	res2;
630e751525SEric Saxe  *	uint64_t	gen_inter_stat;
640e751525SEric Saxe  *	uint64_t	res3;
650e751525SEric Saxe  *	uint64_t	main_counter_value;
660e751525SEric Saxe  *	uint64_t	res4;
670e751525SEric Saxe  *	stuct hpet_timer {
680e751525SEric Saxe  *		uint64_t	config_and_capability;
690e751525SEric Saxe  *		uint64_t	comparator_value;
700e751525SEric Saxe  *		uint64_t	FSB_interrupt_route;
710e751525SEric Saxe  *		uint64_t	reserved;
720e751525SEric Saxe  *	} timers[32];
730e751525SEric Saxe  * }
740e751525SEric Saxe  *
75*fdcca78fSJoshua M. Clulow  * There are 32 possible timers in an HPET.  Only the first 3 timers are
760e751525SEric Saxe  * required.  The other 29 timers are optional.
770e751525SEric Saxe  *
780e751525SEric Saxe  * HPETs can have 64-bit or 32-bit timers.  Timers/compare registers can
790e751525SEric Saxe  * be 64-bit or 32-bit and can be a mixture of both.
800e751525SEric Saxe  * The first two timers are not used.  The HPET spec intends the first two
810e751525SEric Saxe  * timers to be used as "legacy replacement" for the PIT and RTC timers.
820e751525SEric Saxe  *
83*fdcca78fSJoshua M. Clulow  * illumos uses the first available non-legacy replacement timer as a proxy
840e751525SEric Saxe  * timer for processor Local APIC Timers that stop in deep idle C-states.
850e751525SEric Saxe  */
860e751525SEric Saxe 
870e751525SEric Saxe /*
880e751525SEric Saxe  * We only use HPET table 1 on x86.  Typical x86 systems only have 1 HPET.
890e751525SEric Saxe  * ACPI allows for multiple HPET tables to describe multiple HPETs.
900e751525SEric Saxe  */
910e751525SEric Saxe #define	HPET_TABLE_1		(1)
920e751525SEric Saxe 
930e751525SEric Saxe /*
940e751525SEric Saxe  * HPET Specification 1.0a defines the HPET to occupy 1024 bytes regardless of
950e751525SEric Saxe  * the number of counters (3 to 32) in this implementation.
960e751525SEric Saxe  */
970e751525SEric Saxe #define	HPET_SIZE		(1024)
980e751525SEric Saxe 
990e751525SEric Saxe /*
100*fdcca78fSJoshua M. Clulow  * Offsets of HPET registers and macros to access them from HPET base address.
1010e751525SEric Saxe  */
1020e751525SEric Saxe #define	HPET_GEN_CAP_OFFSET		(0)
1030e751525SEric Saxe #define	HPET_GEN_CONFIG_OFFSET		(0x10)
1040e751525SEric Saxe #define	HPET_GEN_INTR_STAT_OFFSET	(0x20)
1050e751525SEric Saxe #define	HPET_MAIN_COUNTER_OFFSET	(0xF0)
1060e751525SEric Saxe #define	HPET_TIMER_N_CONF_OFFSET(n)	(0x100 + (n * 0x20))
1070e751525SEric Saxe #define	HPET_TIMER_N_COMP_OFFSET(n)	(0x108 + (n * 0x20))
1080e751525SEric Saxe 
1090e751525SEric Saxe #define	OFFSET_ADDR(a, o)		(((uintptr_t)(a)) + (o))
1100e751525SEric Saxe #define	HPET_GEN_CAP_ADDRESS(la)				\
1110e751525SEric Saxe 		    OFFSET_ADDR(la, HPET_GEN_CAP_OFFSET)
1120e751525SEric Saxe #define	HPET_GEN_CONFIG_ADDRESS(la)				\
1130e751525SEric Saxe 		    OFFSET_ADDR(la, HPET_GEN_CONFIG_OFFSET)
1140e751525SEric Saxe #define	HPET_GEN_INTR_STAT_ADDRESS(la)				\
1150e751525SEric Saxe 		    OFFSET_ADDR(la, HPET_GEN_INTR_STAT_OFFSET)
1160e751525SEric Saxe #define	HPET_MAIN_COUNTER_ADDRESS(la)				\
1170e751525SEric Saxe 		    OFFSET_ADDR(la, HPET_MAIN_COUNTER_OFFSET)
1180e751525SEric Saxe #define	HPET_TIMER_N_CONF_ADDRESS(la, n)			\
1190e751525SEric Saxe 		    OFFSET_ADDR(la, HPET_TIMER_N_CONF_OFFSET(n))
1200e751525SEric Saxe #define	HPET_TIMER_N_COMP_ADDRESS(la, n)			\
1210e751525SEric Saxe 		    OFFSET_ADDR(la, HPET_TIMER_N_COMP_OFFSET(n))
1220e751525SEric Saxe 
1230e751525SEric Saxe /*
1240e751525SEric Saxe  * HPET General Capabilities and ID Register
1250e751525SEric Saxe  */
1260e751525SEric Saxe typedef struct hpet_gen_cap {
1270e751525SEric Saxe 	uint32_t	counter_clk_period;	/* period in femtoseconds */
1280e751525SEric Saxe 	uint32_t	vendor_id	:16;	/* vendor */
1290e751525SEric Saxe 	uint32_t	leg_route_cap	:1;	/* 1=LegacyReplacemnt support */
1300e751525SEric Saxe 	uint32_t	res1		:1;	/* reserved */
1310e751525SEric Saxe 	uint32_t	count_size_cap	:1;	/* 0=32bit, 1=64bit wide */
1320e751525SEric Saxe 	uint32_t	num_tim_cap	:5;	/* number of timers -1 */
1330e751525SEric Saxe 	uint32_t	rev_id		:8;	/* revision number */
1340e751525SEric Saxe } hpet_gen_cap_t;
1350e751525SEric Saxe 
1360e751525SEric Saxe /*
1370e751525SEric Saxe  * Macros to parse fields of the hpet General Capabilities and ID Register.
1380e751525SEric Saxe  */
1390e751525SEric Saxe #define	HPET_GCAP_CNTR_CLK_PERIOD(l)	(l >> 32)
1400e751525SEric Saxe #define	HPET_GCAP_VENDOR_ID(l)		BITX(l, 31, 16)
1410e751525SEric Saxe #define	HPET_GCAP_LEG_ROUTE_CAP(l)	BITX(l, 15, 15)
1420e751525SEric Saxe #define	HPET_GCAP_CNT_SIZE_CAP(l)	BITX(l, 13, 13)
1430e751525SEric Saxe #define	HPET_GCAP_NUM_TIM_CAP(l)	BITX(l, 12, 8)
1440e751525SEric Saxe #define	HPET_GCAP_REV_ID(l)		BITX(l, 7, 0)
1450e751525SEric Saxe 
1460e751525SEric Saxe /*
1470e751525SEric Saxe  * From HPET spec "The value in this field must be less than or equal to":
1480e751525SEric Saxe  */
1490e751525SEric Saxe #define	HPET_MAX_CLK_PERIOD	(0x5F5E100)
1500e751525SEric Saxe 
1510e751525SEric Saxe /*
1520e751525SEric Saxe  * Femto seconds in a second.
1530e751525SEric Saxe  */
1540e751525SEric Saxe #if defined(__i386)
1550e751525SEric Saxe #define	HPET_FEMTO_TO_NANO	(1000000LL)
1560e751525SEric Saxe #define	HRTIME_TO_HPET_TICKS(t)	(((t) * HPET_FEMTO_TO_NANO) / hpet_info.period)
1570e751525SEric Saxe #else
1580e751525SEric Saxe #define	HPET_FEMTO_TO_NANO	(1000000L)
1590e751525SEric Saxe #define	HRTIME_TO_HPET_TICKS(t)	(((t) * HPET_FEMTO_TO_NANO) / hpet_info.period)
1600e751525SEric Saxe #endif	/* (__i386) */
1610e751525SEric Saxe 
1620e751525SEric Saxe /*
1630e751525SEric Saxe  * HPET General Configuration Register
1640e751525SEric Saxe  */
1650e751525SEric Saxe typedef struct hpet_gen_config_bitfield {
1660e751525SEric Saxe 	uint32_t	leg_rt_cnf :1;		/* legacy replacement route */
1670e751525SEric Saxe 	uint32_t	enable_cnf :1;		/* overal enable */
1680e751525SEric Saxe } hpet_gen_conf_t;
1690e751525SEric Saxe 
1700e751525SEric Saxe /*
1710e751525SEric Saxe  * General Configuration Register fields.
1720e751525SEric Saxe  */
1730e751525SEric Saxe #define	HPET_GCFR_LEG_RT_CNF		(0x2)		/* bit field value */
1740e751525SEric Saxe #define	HPET_GCFR_ENABLE_CNF		(0x1)		/* bit field value */
1750e751525SEric Saxe #define	HPET_GCFR_LEG_RT_CNF_BITX(l)	BITX(l, 1, 1)
1760e751525SEric Saxe #define	HPET_GCFR_ENABLE_CNF_BITX(l)	BITX(l, 0, 0)
1770e751525SEric Saxe 
1780e751525SEric Saxe /*
1790e751525SEric Saxe  * General Interrupt Status Register.
1800e751525SEric Saxe  */
1810e751525SEric Saxe #define	HPET_GIS_T2_INT_STS(l)		BITX(l, 2, 2)
1820e751525SEric Saxe #define	HPET_GIS_T1_INT_STS(l)		BITX(l, 1, 1)
1830e751525SEric Saxe #define	HPET_GIS_T0_INT_STS(l)		BITX(l, 0, 0)
1840e751525SEric Saxe #define	HPET_GIS_TN_INT_STS(l, n)	BITX(l, n, n)
1850e751525SEric Saxe 
1860e751525SEric Saxe #define	HPET_INTR_STATUS_MASK(timer)	((uint64_t)1 << (timer))
1870e751525SEric Saxe 
1880e751525SEric Saxe /*
1890e751525SEric Saxe  * HPET Timer N Configuration and Capabilities Register
1900e751525SEric Saxe  */
1910e751525SEric Saxe typedef struct hpet_TN_conf_cap {
1920e751525SEric Saxe 	uint32_t	int_route_cap;		/* available I/O APIC intrups */
1930e751525SEric Saxe 	uint32_t	res1		:16;	/* reserved */
1940e751525SEric Saxe 	uint32_t	fsb_int_del_cap	:1;	/* FSB interrupt supported */
1950e751525SEric Saxe 	uint32_t	fsb_int_en_cnf	:1;	/* Set FSB intr delivery */
1960e751525SEric Saxe 	uint32_t	int_route_cnf	:5;	/* I/O APIC interrupt to use */
1970e751525SEric Saxe 	uint32_t	mode32_cnf	:1;	/* Force 32-bit mode */
1980e751525SEric Saxe 	uint32_t	res2		:1;	/* reserved */
1990e751525SEric Saxe 	uint32_t	val_set_cnf	:1;	/* Set periodic mode accumula */
2000e751525SEric Saxe 	uint32_t	size_cap	:1;	/* 1=64bit, 0=32bit timer */
2010e751525SEric Saxe 	uint32_t	per_int_cap	:1;	/* 1=periodic mode supported */
2020e751525SEric Saxe 	uint32_t	type_cnf	:1;	/* Enable periodic mode */
2030e751525SEric Saxe 	uint32_t	int_enb_cnf	:1;	/* Enable interrupt generat */
2040e751525SEric Saxe 	uint32_t	int_type_cnf	:1;	/* 0=edge, 1=level triggered */
2050e751525SEric Saxe 	uint32_t	res3		:1;	/* reserved */
2060e751525SEric Saxe } hpet_TN_conf_cap_t;
2070e751525SEric Saxe 
2080e751525SEric Saxe /*
2090e751525SEric Saxe  * There are 3 to 32 timers on each HPET.
2100e751525SEric Saxe  */
2110e751525SEric Saxe #define	HPET_TIMER_N_INT_ROUTE_CAP(l)	(l >> 32)
2120e751525SEric Saxe #define	HPET_TIMER_N_INT_TYPE_CNF(l)	BITX(l, 1, 1)
2130e751525SEric Saxe #define	HPET_TIMER_N_INT_ENB_CNF(l)	BITX(l, 2, 2)
2140e751525SEric Saxe #define	HPET_TIMER_N_TYPE_CNF(l)	BITX(l, 3, 3)
2150e751525SEric Saxe #define	HPET_TIMER_N_PER_INT_CAP(l)	BITX(l, 4, 4)
2160e751525SEric Saxe #define	HPET_TIMER_N_SIZE_CAP(l)	BITX(l, 5, 5)
2170e751525SEric Saxe #define	HPET_TIMER_N_VAL_SET_CNF(l)	BITX(l, 6, 6)
2180e751525SEric Saxe #define	HPET_TIMER_N_MODE32_CNF(l)	BITX(l, 8, 8)
2190e751525SEric Saxe #define	HPET_TIMER_N_INT_ROUTE_CNF(l)	BITX(l, 13, 9)
2200e751525SEric Saxe #define	HPET_TIMER_N_FSB_EN_CNF(l)	BITX(l, 14, 14)
2210e751525SEric Saxe #define	HPET_TIMER_N_FSB_INT_DEL_CAP(l)	BITX(l, 15, 15)
2220e751525SEric Saxe 
2230e751525SEric Saxe #define	HPET_TIMER_N_INT_TYPE_CNF_BIT	(1 << 1)
2240e751525SEric Saxe #define	HPET_TIMER_N_INT_ENB_CNF_BIT	(1 << 2)
2250e751525SEric Saxe #define	HPET_TIMER_N_TYPE_CNF_BIT	(1 << 3)
2260e751525SEric Saxe #define	HPET_TIMER_N_FSB_EN_CNF_BIT	(1 << 14)
2270e751525SEric Saxe #define	HPET_TIMER_N_INT_ROUTE_SHIFT(i)	(i << 9)
2280e751525SEric Saxe 
2290e751525SEric Saxe /*
2300e751525SEric Saxe  * HPET Spec reserves timers 0 and 1 for legacy timer replacement (PIT and RTC).
2310e751525SEric Saxe  * Available timers for other use such as LACPI proxy during Deep C-State
2320e751525SEric Saxe  * start at timer 2.
2330e751525SEric Saxe  */
2340e751525SEric Saxe #define	HPET_FIRST_NON_LEGACY_TIMER	(2)
2350e751525SEric Saxe 
2360e751525SEric Saxe /*
2370e751525SEric Saxe  * HPET timer and interrupt used as LAPIC proxy during deep C-State.
2380e751525SEric Saxe  */
2390e751525SEric Saxe typedef struct cstate_timer {
2400e751525SEric Saxe 	int	timer;
2410e751525SEric Saxe 	int	intr;
2420e751525SEric Saxe } cstate_timer_t;
2430e751525SEric Saxe 
2440e751525SEric Saxe /*
2450e751525SEric Saxe  * Data structure of useful HPET device information.
2460e751525SEric Saxe  */
2470e751525SEric Saxe typedef struct hpet_info {
2480e751525SEric Saxe 	hpet_gen_cap_t	gen_cap;
2490e751525SEric Saxe 	hpet_gen_conf_t	gen_config;
2500e751525SEric Saxe 	uint64_t	gen_intrpt_stat;
2510e751525SEric Saxe 	uint64_t	main_counter_value;
2520e751525SEric Saxe 	void		*logical_address;	/* HPET VA memory map */
2530e751525SEric Saxe 	hpet_TN_conf_cap_t *timer_n_config;	/* N Timer config and cap */
2540e751525SEric Saxe 	uint32_t	num_timers;		/* number of timers */
2550e751525SEric Saxe 	uint32_t	allocated_timers;	/* bitmap of timers in use */
2560e751525SEric Saxe 	cstate_timer_t	cstate_timer;	/* HPET Timer used for LAPIC proxy */
2570e751525SEric Saxe 	uint64_t	hpet_main_counter_reads[2];
2580e751525SEric Saxe 	hrtime_t	tsc[3];
2590e751525SEric Saxe 	hrtime_t	period;		/* counter_clk_period in Femto Secs */
2600e751525SEric Saxe } hpet_info_t;
2610e751525SEric Saxe 
2620e751525SEric Saxe #if defined(_KERNEL)
2630e751525SEric Saxe 
2640e751525SEric Saxe /*
2650e751525SEric Saxe  * Spin mutexes are used in several places because idle threads cannot block.
2660e751525SEric Saxe  * These defines provide a mechanism to break out of spin loops to prevent
2670e751525SEric Saxe  * system hangs if a CPU can never get the lock (due to an unknown
2680e751525SEric Saxe  * hardware/software bug).  100 microsecond was chosen after extensive stress
2690e751525SEric Saxe  * testing.
2700e751525SEric Saxe  */
2710e751525SEric Saxe #define	HPET_SPIN_CHECK		(1000)
2720e751525SEric Saxe #define	HPET_SPIN_TIMEOUT	(100000)
2730e751525SEric Saxe 
2740e751525SEric Saxe /*
2750e751525SEric Saxe  * There is one of these per CPU using the HPET as a proxy for its stalled
2760e751525SEric Saxe  * local APIC while in c-state >= C2.
2770e751525SEric Saxe  */
2780e751525SEric Saxe typedef hrtime_t hpet_proxy_t;
2790e751525SEric Saxe 
2800e751525SEric Saxe extern ACPI_TABLE_HPET	*hpet_table;
2810e751525SEric Saxe extern hpet_info_t	hpet_info;
2820e751525SEric Saxe 
2830e751525SEric Saxe #endif	/* defined(_KERNEL) */
2840e751525SEric Saxe 
2850e751525SEric Saxe #ifdef __cplusplus
2860e751525SEric Saxe }
2870e751525SEric Saxe #endif
2880e751525SEric Saxe 
2890e751525SEric Saxe #endif	/* _HPET_ACPI_H */
290