1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #ifndef _HPET_ACPI_H 27 #define _HPET_ACPI_H 28 29 #if defined(_KERNEL) 30 #include <sys/acpi/acpi.h> 31 #include <sys/acpi/actbl1.h> 32 #include <sys/acpica.h> 33 #endif /* defined(_KERNEL) */ 34 35 #ifdef __cplusplus 36 extern "C" { 37 #endif 38 39 /* 40 * Solaris uses an HPET Timer to generate interrupts for CPUs in Deep C-state 41 * with stalled LAPIC Timers. All CPUs use one HPET timer. The timer's 42 * interrupt targets one CPU (via the I/O APIC). The one CPU that receives 43 * the HPET's interrupt wakes up other CPUs as needed during the HPET Interrupt 44 * Service Routing. The HPET ISR uses poke_cpus to wake up other CPUs with an 45 * Inter Processor Interrupt. 46 * 47 * Please see the Intel Programmer's guides. Interrupts are disabled before 48 * a CPU Halts into Deep C-state. (This allows CPU-hardware-specific cleanup 49 * before servicing interrupts.) When a Deep C-state CPU wakes up (due to 50 * an externally generated interrupt), it resume execution where it halted. 51 * The CPU returning from Deep C-state must enable interrupts before it will 52 * handle the pending interrupt that woke it from Deep C-state. 53 * 54 * 55 * HPET bits as defined in the Intel IA-PC HPET Specification Rev 1.0a. 56 * 57 * The physical address space layout of the memory mapped HPET looks like this: 58 * 59 * struct hpet { 60 * uint64_t gen_cap; 61 * uint64_t res1; 62 * uint64_t gen_config; 63 * uint64_t res2; 64 * uint64_t gen_inter_stat; 65 * uint64_t res3; 66 * uint64_t main_counter_value; 67 * uint64_t res4; 68 * stuct hpet_timer { 69 * uint64_t config_and_capability; 70 * uint64_t comparator_value; 71 * uint64_t FSB_interrupt_route; 72 * uint64_t reserved; 73 * } timers[32]; 74 * } 75 * 76 * There are 32 possible timers in an hpet. Only the first 3 timers are 77 * required. The other 29 timers are optional. 78 * 79 * HPETs can have 64-bit or 32-bit timers. Timers/compare registers can 80 * be 64-bit or 32-bit and can be a mixture of both. 81 * The first two timers are not used. The HPET spec intends the first two 82 * timers to be used as "legacy replacement" for the PIT and RTC timers. 83 * 84 * Solaris uses the first available non-legacy replacement timer as a proxy 85 * timer for processor Local APIC Timers that stop in deep idle C-states. 86 */ 87 88 /* 89 * We only use HPET table 1 on x86. Typical x86 systems only have 1 HPET. 90 * ACPI allows for multiple HPET tables to describe multiple HPETs. 91 */ 92 #define HPET_TABLE_1 (1) 93 94 /* 95 * HPET Specification 1.0a defines the HPET to occupy 1024 bytes regardless of 96 * the number of counters (3 to 32) in this implementation. 97 */ 98 #define HPET_SIZE (1024) 99 100 /* 101 * Offsets of hpet registers and macros to access them from HPET base address. 102 */ 103 #define HPET_GEN_CAP_OFFSET (0) 104 #define HPET_GEN_CONFIG_OFFSET (0x10) 105 #define HPET_GEN_INTR_STAT_OFFSET (0x20) 106 #define HPET_MAIN_COUNTER_OFFSET (0xF0) 107 #define HPET_TIMER_N_CONF_OFFSET(n) (0x100 + (n * 0x20)) 108 #define HPET_TIMER_N_COMP_OFFSET(n) (0x108 + (n * 0x20)) 109 110 #define OFFSET_ADDR(a, o) (((uintptr_t)(a)) + (o)) 111 #define HPET_GEN_CAP_ADDRESS(la) \ 112 OFFSET_ADDR(la, HPET_GEN_CAP_OFFSET) 113 #define HPET_GEN_CONFIG_ADDRESS(la) \ 114 OFFSET_ADDR(la, HPET_GEN_CONFIG_OFFSET) 115 #define HPET_GEN_INTR_STAT_ADDRESS(la) \ 116 OFFSET_ADDR(la, HPET_GEN_INTR_STAT_OFFSET) 117 #define HPET_MAIN_COUNTER_ADDRESS(la) \ 118 OFFSET_ADDR(la, HPET_MAIN_COUNTER_OFFSET) 119 #define HPET_TIMER_N_CONF_ADDRESS(la, n) \ 120 OFFSET_ADDR(la, HPET_TIMER_N_CONF_OFFSET(n)) 121 #define HPET_TIMER_N_COMP_ADDRESS(la, n) \ 122 OFFSET_ADDR(la, HPET_TIMER_N_COMP_OFFSET(n)) 123 124 /* 125 * HPET General Capabilities and ID Register 126 */ 127 typedef struct hpet_gen_cap { 128 uint32_t counter_clk_period; /* period in femtoseconds */ 129 uint32_t vendor_id :16; /* vendor */ 130 uint32_t leg_route_cap :1; /* 1=LegacyReplacemnt support */ 131 uint32_t res1 :1; /* reserved */ 132 uint32_t count_size_cap :1; /* 0=32bit, 1=64bit wide */ 133 uint32_t num_tim_cap :5; /* number of timers -1 */ 134 uint32_t rev_id :8; /* revision number */ 135 } hpet_gen_cap_t; 136 137 /* 138 * Macros to parse fields of the hpet General Capabilities and ID Register. 139 */ 140 #define HPET_GCAP_CNTR_CLK_PERIOD(l) (l >> 32) 141 #define HPET_GCAP_VENDOR_ID(l) BITX(l, 31, 16) 142 #define HPET_GCAP_LEG_ROUTE_CAP(l) BITX(l, 15, 15) 143 #define HPET_GCAP_CNT_SIZE_CAP(l) BITX(l, 13, 13) 144 #define HPET_GCAP_NUM_TIM_CAP(l) BITX(l, 12, 8) 145 #define HPET_GCAP_REV_ID(l) BITX(l, 7, 0) 146 147 /* 148 * From HPET spec "The value in this field must be less than or equal to": 149 */ 150 #define HPET_MAX_CLK_PERIOD (0x5F5E100) 151 152 /* 153 * Femto seconds in a second. 154 */ 155 #if defined(__i386) 156 #define HPET_FEMTO_TO_NANO (1000000LL) 157 #define HRTIME_TO_HPET_TICKS(t) (((t) * HPET_FEMTO_TO_NANO) / hpet_info.period) 158 #else 159 #define HPET_FEMTO_TO_NANO (1000000L) 160 #define HRTIME_TO_HPET_TICKS(t) (((t) * HPET_FEMTO_TO_NANO) / hpet_info.period) 161 #endif /* (__i386) */ 162 163 /* 164 * HPET General Configuration Register 165 */ 166 typedef struct hpet_gen_config_bitfield { 167 uint32_t leg_rt_cnf :1; /* legacy replacement route */ 168 uint32_t enable_cnf :1; /* overal enable */ 169 } hpet_gen_conf_t; 170 171 /* 172 * General Configuration Register fields. 173 */ 174 #define HPET_GCFR_LEG_RT_CNF (0x2) /* bit field value */ 175 #define HPET_GCFR_ENABLE_CNF (0x1) /* bit field value */ 176 #define HPET_GCFR_LEG_RT_CNF_BITX(l) BITX(l, 1, 1) 177 #define HPET_GCFR_ENABLE_CNF_BITX(l) BITX(l, 0, 0) 178 179 /* 180 * General Interrupt Status Register. 181 */ 182 #define HPET_GIS_T2_INT_STS(l) BITX(l, 2, 2) 183 #define HPET_GIS_T1_INT_STS(l) BITX(l, 1, 1) 184 #define HPET_GIS_T0_INT_STS(l) BITX(l, 0, 0) 185 #define HPET_GIS_TN_INT_STS(l, n) BITX(l, n, n) 186 187 #define HPET_INTR_STATUS_MASK(timer) ((uint64_t)1 << (timer)) 188 189 /* 190 * HPET Timer N Configuration and Capabilities Register 191 */ 192 typedef struct hpet_TN_conf_cap { 193 uint32_t int_route_cap; /* available I/O APIC intrups */ 194 uint32_t res1 :16; /* reserved */ 195 uint32_t fsb_int_del_cap :1; /* FSB interrupt supported */ 196 uint32_t fsb_int_en_cnf :1; /* Set FSB intr delivery */ 197 uint32_t int_route_cnf :5; /* I/O APIC interrupt to use */ 198 uint32_t mode32_cnf :1; /* Force 32-bit mode */ 199 uint32_t res2 :1; /* reserved */ 200 uint32_t val_set_cnf :1; /* Set periodic mode accumula */ 201 uint32_t size_cap :1; /* 1=64bit, 0=32bit timer */ 202 uint32_t per_int_cap :1; /* 1=periodic mode supported */ 203 uint32_t type_cnf :1; /* Enable periodic mode */ 204 uint32_t int_enb_cnf :1; /* Enable interrupt generat */ 205 uint32_t int_type_cnf :1; /* 0=edge, 1=level triggered */ 206 uint32_t res3 :1; /* reserved */ 207 } hpet_TN_conf_cap_t; 208 209 /* 210 * There are 3 to 32 timers on each HPET. 211 */ 212 #define HPET_TIMER_N_INT_ROUTE_CAP(l) (l >> 32) 213 #define HPET_TIMER_N_INT_TYPE_CNF(l) BITX(l, 1, 1) 214 #define HPET_TIMER_N_INT_ENB_CNF(l) BITX(l, 2, 2) 215 #define HPET_TIMER_N_TYPE_CNF(l) BITX(l, 3, 3) 216 #define HPET_TIMER_N_PER_INT_CAP(l) BITX(l, 4, 4) 217 #define HPET_TIMER_N_SIZE_CAP(l) BITX(l, 5, 5) 218 #define HPET_TIMER_N_VAL_SET_CNF(l) BITX(l, 6, 6) 219 #define HPET_TIMER_N_MODE32_CNF(l) BITX(l, 8, 8) 220 #define HPET_TIMER_N_INT_ROUTE_CNF(l) BITX(l, 13, 9) 221 #define HPET_TIMER_N_FSB_EN_CNF(l) BITX(l, 14, 14) 222 #define HPET_TIMER_N_FSB_INT_DEL_CAP(l) BITX(l, 15, 15) 223 224 #define HPET_TIMER_N_INT_TYPE_CNF_BIT (1 << 1) 225 #define HPET_TIMER_N_INT_ENB_CNF_BIT (1 << 2) 226 #define HPET_TIMER_N_TYPE_CNF_BIT (1 << 3) 227 #define HPET_TIMER_N_FSB_EN_CNF_BIT (1 << 14) 228 #define HPET_TIMER_N_INT_ROUTE_SHIFT(i) (i << 9) 229 230 /* 231 * HPET Spec reserves timers 0 and 1 for legacy timer replacement (PIT and RTC). 232 * Available timers for other use such as LACPI proxy during Deep C-State 233 * start at timer 2. 234 */ 235 #define HPET_FIRST_NON_LEGACY_TIMER (2) 236 237 /* 238 * HPET timer and interrupt used as LAPIC proxy during deep C-State. 239 */ 240 typedef struct cstate_timer { 241 int timer; 242 int intr; 243 } cstate_timer_t; 244 245 /* 246 * Data structure of useful HPET device information. 247 */ 248 typedef struct hpet_info { 249 hpet_gen_cap_t gen_cap; 250 hpet_gen_conf_t gen_config; 251 uint64_t gen_intrpt_stat; 252 uint64_t main_counter_value; 253 void *logical_address; /* HPET VA memory map */ 254 hpet_TN_conf_cap_t *timer_n_config; /* N Timer config and cap */ 255 uint32_t num_timers; /* number of timers */ 256 uint32_t allocated_timers; /* bitmap of timers in use */ 257 cstate_timer_t cstate_timer; /* HPET Timer used for LAPIC proxy */ 258 uint64_t hpet_main_counter_reads[2]; 259 hrtime_t tsc[3]; 260 hrtime_t period; /* counter_clk_period in Femto Secs */ 261 } hpet_info_t; 262 263 #if defined(_KERNEL) 264 265 /* 266 * Spin mutexes are used in several places because idle threads cannot block. 267 * These defines provide a mechanism to break out of spin loops to prevent 268 * system hangs if a CPU can never get the lock (due to an unknown 269 * hardware/software bug). 100 microsecond was chosen after extensive stress 270 * testing. 271 */ 272 #define HPET_SPIN_CHECK (1000) 273 #define HPET_SPIN_TIMEOUT (100000) 274 275 /* 276 * There is one of these per CPU using the HPET as a proxy for its stalled 277 * local APIC while in c-state >= C2. 278 */ 279 typedef hrtime_t hpet_proxy_t; 280 281 extern ACPI_TABLE_HPET *hpet_table; 282 extern hpet_info_t hpet_info; 283 284 static int hpet_init_proxy(int *hpet_vect, iflag_t *hpet_flags); 285 static boolean_t hpet_install_proxy(void); 286 static boolean_t hpet_callback(int code); 287 static boolean_t hpet_cpr(int code); 288 static boolean_t hpet_resume(void); 289 static void hpet_cst_callback(uint32_t code); 290 static boolean_t hpet_deep_idle_config(int code); 291 static int hpet_validate_table(ACPI_TABLE_HPET *hpet_table); 292 static boolean_t hpet_checksum_table(unsigned char *table, unsigned int len); 293 static void *hpet_memory_map(ACPI_TABLE_HPET *hpet_table); 294 static int hpet_start_main_counter(hpet_info_t *hip); 295 static int hpet_stop_main_counter(hpet_info_t *hip); 296 static uint64_t hpet_read_main_counter_value(hpet_info_t *hip); 297 static uint64_t hpet_set_leg_rt_cnf(hpet_info_t *hip, uint32_t new_value); 298 static uint64_t hpet_read_gen_cap(hpet_info_t *hip); 299 static uint64_t hpet_read_gen_config(hpet_info_t *hip); 300 static uint64_t hpet_read_gen_intrpt_stat(hpet_info_t *hip); 301 static uint64_t hpet_read_timer_N_config(hpet_info_t *hip, uint_t n); 302 static hpet_TN_conf_cap_t hpet_convert_timer_N_config(uint64_t conf); 303 static uint64_t hpet_read_timer_N_comp(hpet_info_t *hip, uint_t n); 304 static void hpet_write_gen_cap(hpet_info_t *hip, uint64_t l); 305 static void hpet_write_gen_config(hpet_info_t *hip, uint64_t l); 306 static void hpet_write_gen_intrpt_stat(hpet_info_t *hip, uint64_t l); 307 static void hpet_write_timer_N_config(hpet_info_t *hip, uint_t n, uint64_t l); 308 static void hpet_write_timer_N_comp(hpet_info_t *hip, uint_t n, uint64_t l); 309 static void hpet_disable_timer(hpet_info_t *hip, uint32_t timer_n); 310 static void hpet_enable_timer(hpet_info_t *hip, uint32_t timer_n); 311 static void hpet_write_main_counter_value(hpet_info_t *hip, uint64_t l); 312 static int hpet_get_FSB_intr_capable_timer(hpet_info_t *hip, uint32_t mask); 313 static int hpet_get_IOAPIC_intr_capable_timer(hpet_info_t *hip); 314 static int hpet_timer_available(uint32_t allocated_timers, uint32_t n); 315 static void hpet_timer_alloc(uint32_t *allocated_timers, uint32_t n); 316 static void hpet_timer_set_up(hpet_info_t *hip, uint32_t timer_n, 317 uint32_t interrupt); 318 static uint_t hpet_isr(char *arg); 319 static uint32_t hpet_install_interrupt_handler(uint_t (*func)(char *), 320 int vector); 321 static void hpet_uninstall_interrupt_handler(void); 322 static void hpet_expire_all(void); 323 static boolean_t hpet_guaranteed_schedule(hrtime_t required_wakeup_time); 324 static boolean_t hpet_use_hpet_timer(hrtime_t *expire); 325 static void hpet_use_lapic_timer(hrtime_t expire); 326 static void hpet_init_proxy_data(void); 327 328 #endif /* defined(_KERNEL) */ 329 330 #ifdef __cplusplus 331 } 332 #endif 333 334 #endif /* _HPET_ACPI_H */ 335