1 /*- 2 * Copyright (c) 2005 Poul-Henning Kamp 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: src/sys/dev/acpica/acpi_hpet.c,v 1.12.2.1.2.1 2008/11/25 02:59:29 kensmith Exp $ 27 */ 28 29 #include "opt_acpi.h" 30 31 #include <sys/param.h> 32 #include <sys/bus.h> 33 #include <sys/kernel.h> 34 #include <sys/module.h> 35 #include <sys/systimer.h> 36 #include <sys/rman.h> 37 38 #if !defined(KLD_MODULE) 39 #include <machine/pmap.h> 40 #endif 41 42 #include "acpi.h" 43 #include "accommon.h" 44 #include "acpivar.h" 45 #include "acpi_hpet.h" 46 47 #if !defined(KLD_MODULE) 48 #include <platform/pc64/acpica/acpi_sdt_var.h> 49 #endif 50 51 /* Hooks for the ACPICA debugging infrastructure */ 52 #define _COMPONENT ACPI_TIMER 53 ACPI_MODULE_NAME("HPET") 54 55 static bus_space_handle_t acpi_hpet_bsh; 56 static bus_space_tag_t acpi_hpet_bst; 57 static u_long acpi_hpet_res_start; 58 59 struct acpi_hpet_softc { 60 device_t dev; 61 struct resource *mem_res; 62 ACPI_HANDLE handle; 63 }; 64 65 #define DEV_HPET(x) (acpi_get_magic(x) == (uintptr_t)&acpi_hpet_devclass) 66 67 static sysclock_t acpi_hpet_get_timecount(void); 68 static void acpi_hpet_construct(struct cputimer *, sysclock_t); 69 70 static int acpi_hpet_identify(driver_t *, device_t); 71 static int acpi_hpet_probe(device_t); 72 static int acpi_hpet_attach(device_t); 73 static int acpi_hpet_resume(device_t); 74 static int acpi_hpet_suspend(device_t); 75 76 static void acpi_hpet_test(struct acpi_hpet_softc *sc); 77 static u_int acpi_hpet_read(void); 78 static void acpi_hpet_enable(struct acpi_hpet_softc *); 79 static void acpi_hpet_disable(struct acpi_hpet_softc *); 80 81 static char *hpet_ids[] = { "PNP0103", NULL }; 82 83 static struct cputimer acpi_hpet_timer = { 84 .next = SLIST_ENTRY_INITIALIZER, 85 .name = "HPET", 86 .pri = CPUTIMER_PRI_HPET, 87 .type = CPUTIMER_HPET, 88 .count = acpi_hpet_get_timecount, 89 .fromhz = cputimer_default_fromhz, 90 .fromus = cputimer_default_fromus, 91 .construct = acpi_hpet_construct, 92 .destruct = cputimer_default_destruct, 93 .freq = 0 /* determined later */ 94 }; 95 96 static device_method_t acpi_hpet_methods[] = { 97 DEVMETHOD(device_identify, acpi_hpet_identify), 98 DEVMETHOD(device_probe, acpi_hpet_probe), 99 DEVMETHOD(device_attach, acpi_hpet_attach), 100 DEVMETHOD(device_suspend, acpi_hpet_suspend), 101 DEVMETHOD(device_resume, acpi_hpet_resume), 102 DEVMETHOD_END 103 }; 104 105 static driver_t acpi_hpet_driver = { 106 "acpi_hpet", 107 acpi_hpet_methods, 108 sizeof(struct acpi_hpet_softc), 109 .gpri = KOBJ_GPRI_ACPI+2 110 }; 111 112 static devclass_t acpi_hpet_devclass; 113 DRIVER_MODULE(acpi_hpet, acpi, acpi_hpet_driver, acpi_hpet_devclass, NULL, NULL); 114 MODULE_DEPEND(acpi_hpet, acpi, 1, 1, 1); 115 116 static u_int 117 acpi_hpet_read(void) 118 { 119 return bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, 120 HPET_MAIN_COUNTER); 121 } 122 123 #if !defined(KLD_MODULE) 124 extern int i8254_cputimer_disable; 125 126 static vm_offset_t ptr = 0; 127 128 static int acpi_hpet_for_calibration = 1; 129 TUNABLE_INT("hw.calibrate_timers_with_hpet", &acpi_hpet_for_calibration); 130 131 static sysclock_t 132 acpi_hpet_early_get_timecount(void) 133 { 134 sysclock_t last_counter; 135 sysclock_t next_counter; 136 uint32_t counter; 137 138 last_counter = acpi_hpet_timer.base; 139 for (;;) { 140 cpu_ccfence(); 141 counter = readl(ptr + HPET_MAIN_COUNTER); 142 if (counter < (last_counter & 0xFFFFFFFFU)) 143 next_counter = ((last_counter + 0x0100000000U) & 144 0xFFFFFFFF00000000LU) | counter; 145 else 146 next_counter = (last_counter & 147 0xFFFFFFFF00000000LU) | counter; 148 if (atomic_fcmpset_long(&acpi_hpet_timer.base, &last_counter, 149 next_counter)) { 150 break; 151 } 152 } 153 return next_counter; 154 } 155 156 static void 157 acpi_hpet_early_construct(struct cputimer *timer, sysclock_t oldclock) 158 { 159 uint32_t val; 160 161 val = readl(ptr + HPET_CONFIG); 162 writel(ptr + HPET_CONFIG, val | HPET_CNF_ENABLE); 163 164 timer->base = 0; 165 timer->base = oldclock - acpi_hpet_early_get_timecount(); 166 } 167 168 static void 169 acpi_hpet_early_destruct(struct cputimer *timer) 170 { 171 uint32_t val; 172 173 val = readl(ptr + HPET_CONFIG); 174 writel(ptr + HPET_CONFIG, val & ~HPET_CNF_ENABLE); 175 } 176 177 static int 178 acpi_hpet_early_init(void) 179 { 180 uintmax_t freq; 181 uint64_t old_tsc, new_tsc; 182 uint32_t val, val2; 183 184 val = readl(ptr + HPET_CONFIG); 185 writel(ptr + HPET_CONFIG, val | HPET_CNF_ENABLE); 186 187 /* Read basic statistics about the timer. */ 188 val = readl(ptr + HPET_PERIOD); 189 if (val == 0) { 190 kprintf("acpi_hpet: invalid period\n"); 191 val = readl(ptr + HPET_CONFIG); 192 writel(ptr + HPET_CONFIG, val & ~HPET_CNF_ENABLE); 193 return ENXIO; 194 } 195 196 freq = (1000000000000000LL + val / 2) / val; 197 if (bootverbose) { 198 val = readl(ptr + HPET_CAPABILITIES); 199 kprintf("acpi_hpet: " 200 "vend: 0x%x, rev: 0x%x, num: %d, opts:%s%s\n", 201 val >> 16, val & HPET_CAP_REV_ID, 202 (val & HPET_CAP_NUM_TIM) >> 8, 203 (val & HPET_CAP_LEG_RT) ? " legacy_route" : "", 204 (val & HPET_CAP_COUNT_SIZE) ? " 64-bit" : ""); 205 } 206 207 #if 0 208 if (ktestenv("debug.acpi.hpet_test")) 209 acpi_hpet_test(sc); 210 #endif 211 212 /* 213 * Don't attach if the timer never increments. Since the spec 214 * requires it to be at least 10 MHz, it has to change in 1 us. 215 */ 216 val = readl(ptr + HPET_MAIN_COUNTER); 217 /* This delay correspond to 1us, even at 6 GHz TSC. */ 218 old_tsc = rdtsc(); 219 do { 220 cpu_pause(); 221 new_tsc = rdtsc(); 222 } while (new_tsc - old_tsc < 6000); 223 val2 = readl(ptr + HPET_MAIN_COUNTER); 224 if (val == val2) { 225 kprintf("acpi_hpet: HPET never increments, disabling\n"); 226 val = readl(ptr + HPET_CONFIG); 227 writel(ptr + HPET_CONFIG, val & ~HPET_CNF_ENABLE); 228 return ENXIO; 229 } 230 231 val = readl(ptr + HPET_CONFIG); 232 writel(ptr + HPET_CONFIG, val & ~HPET_CNF_ENABLE); 233 acpi_hpet_timer.freq = freq; 234 kprintf("acpi_hpet: frequency %lu\n", acpi_hpet_timer.freq); 235 236 acpi_hpet_timer.count = acpi_hpet_early_get_timecount; 237 acpi_hpet_timer.construct = acpi_hpet_early_construct; 238 acpi_hpet_timer.destruct = acpi_hpet_early_destruct; 239 240 cputimer_register(&acpi_hpet_timer); 241 cputimer_select(&acpi_hpet_timer, 0); 242 return 0; 243 } 244 245 static void 246 acpi_hpet_cputimer_register(void) 247 { 248 ACPI_TABLE_HPET *hpet; 249 vm_paddr_t hpet_paddr; 250 251 if (acpi_hpet_for_calibration == 0) 252 return; 253 254 if (acpi_disabled("hpet")) 255 return; 256 257 hpet_paddr = sdt_search(ACPI_SIG_HPET); 258 if (hpet_paddr == 0) { 259 if (bootverbose) 260 kprintf("acpi_hpet: can't locate HPET\n"); 261 return; 262 } 263 264 hpet = sdt_sdth_map(hpet_paddr); 265 if (hpet == NULL) 266 return; 267 268 if (hpet->Header.Length < 56) { 269 kprintf("acpi_hpet: HPET table too short. Length: 0x%x\n", 270 hpet->Header.Length); 271 return; 272 } 273 274 if (hpet->Sequence != 0) { 275 kprintf("acpi_hpet: " 276 "HPET table Sequence not 0. Sequence: 0x%x\n", hpet->Id); 277 goto done; 278 } 279 280 acpi_hpet_res_start = hpet->Address.Address; 281 if (acpi_hpet_res_start == 0) 282 goto done; 283 284 ptr = (vm_offset_t)pmap_mapdev(acpi_hpet_res_start, HPET_MEM_WIDTH); 285 if (acpi_hpet_early_init() == 0) { 286 i8254_cputimer_disable = 1; 287 } else { 288 pmap_unmapdev(ptr, HPET_MEM_WIDTH); 289 ptr = 0; 290 } 291 292 done: 293 sdt_sdth_unmap(&hpet->Header); 294 return; 295 } 296 297 TIMECOUNTER_INIT(acpi_hpet_init, acpi_hpet_cputimer_register); 298 #endif 299 300 /* 301 * Locate the ACPI timer using the FADT, set up and allocate the I/O resources 302 * we will be using. 303 */ 304 static int 305 acpi_hpet_identify(driver_t *driver, device_t parent) 306 { 307 ACPI_TABLE_HPET *hpet; 308 ACPI_TABLE_HEADER *hdr; 309 ACPI_STATUS status; 310 device_t child; 311 312 /* 313 * Just try once, do nothing if the 'acpi' bus is rescanned. 314 */ 315 if (device_get_state(parent) == DS_ATTACHED) 316 return 0; 317 318 ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); 319 320 /* Only one HPET device can be added. */ 321 if (devclass_get_device(acpi_hpet_devclass, 0)) 322 return ENXIO; 323 324 #if !defined(KLD_MODULE) 325 if (ptr != 0) { 326 /* Use data from early boot for attachment. */ 327 child = BUS_ADD_CHILD(parent, parent, 0, "acpi_hpet", 0); 328 if (child == NULL) { 329 device_printf(parent, "%s: can't add acpi_hpet0\n", 330 __func__); 331 return ENXIO; 332 } 333 334 /* Record a magic value so we can detect this device later. */ 335 acpi_set_magic(child, (uintptr_t)&acpi_hpet_devclass); 336 337 if (bus_set_resource(child, SYS_RES_MEMORY, 0, 338 acpi_hpet_res_start, HPET_MEM_WIDTH, -1)) { 339 device_printf(child, 340 "could not set iomem resources: 0x%jx, %d\n", 341 (uintmax_t)acpi_hpet_res_start, HPET_MEM_WIDTH); 342 return ENOMEM; 343 } 344 345 return 0; 346 } 347 #endif 348 349 /* Currently, ID and minimum clock tick info is unused. */ 350 351 status = AcpiGetTable(ACPI_SIG_HPET, 1, &hdr); 352 if (ACPI_FAILURE(status)) 353 return ENXIO; 354 355 /* 356 * The unit number could be derived from hdr->Sequence but we only 357 * support one HPET device. 358 */ 359 hpet = (ACPI_TABLE_HPET *)hdr; 360 if (hpet->Sequence != 0) { 361 kprintf("ACPI HPET table warning: Sequence is non-zero (%d)\n", 362 hpet->Sequence); 363 } 364 365 child = BUS_ADD_CHILD(parent, parent, 0, "acpi_hpet", 0); 366 if (child == NULL) { 367 device_printf(parent, "%s: can't add acpi_hpet0\n", __func__); 368 return ENXIO; 369 } 370 371 /* Record a magic value so we can detect this device later. */ 372 acpi_set_magic(child, (uintptr_t)&acpi_hpet_devclass); 373 374 acpi_hpet_res_start = hpet->Address.Address; 375 if (bus_set_resource(child, SYS_RES_MEMORY, 0, 376 hpet->Address.Address, HPET_MEM_WIDTH, -1)) { 377 device_printf(child, "could not set iomem resources: " 378 "0x%jx, %d\n", (uintmax_t)hpet->Address.Address, 379 HPET_MEM_WIDTH); 380 return ENOMEM; 381 } 382 return 0; 383 } 384 385 static int 386 acpi_hpet_probe(device_t dev) 387 { 388 ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); 389 390 if (acpi_disabled("hpet")) 391 return ENXIO; 392 393 if (!DEV_HPET(dev) && 394 (ACPI_ID_PROBE(device_get_parent(dev), dev, hpet_ids) == NULL || 395 device_get_unit(dev) != 0)) 396 return ENXIO; 397 398 device_set_desc(dev, "High Precision Event Timer"); 399 return 0; 400 } 401 402 static int 403 acpi_hpet_attach(device_t dev) 404 { 405 struct acpi_hpet_softc *sc; 406 int rid; 407 uint32_t val, val2; 408 uintmax_t freq; 409 410 ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); 411 412 sc = device_get_softc(dev); 413 sc->dev = dev; 414 sc->handle = acpi_get_handle(dev); 415 416 rid = 0; 417 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 418 RF_ACTIVE); 419 if (sc->mem_res == NULL) { 420 /* 421 * We only need to make sure that main counter 422 * is accessable. 423 */ 424 device_printf(dev, "can't map %dB register space, try %dB\n", 425 HPET_MEM_WIDTH, HPET_MEM_WIDTH_MIN); 426 rid = 0; 427 sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 428 acpi_hpet_res_start, 429 acpi_hpet_res_start + HPET_MEM_WIDTH_MIN - 1, 430 HPET_MEM_WIDTH_MIN, RF_ACTIVE); 431 if (sc->mem_res == NULL) 432 return ENOMEM; 433 } 434 435 /* Validate that we can access the whole region. */ 436 if (rman_get_size(sc->mem_res) < HPET_MEM_WIDTH_MIN) { 437 device_printf(dev, "memory region width %ld too small\n", 438 rman_get_size(sc->mem_res)); 439 bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->mem_res); 440 return ENXIO; 441 } 442 443 acpi_hpet_bsh = rman_get_bushandle(sc->mem_res); 444 acpi_hpet_bst = rman_get_bustag(sc->mem_res); 445 446 #if !defined(KLD_MODULE) 447 if (ptr != 0) { 448 /* Use data from early boot for attachment. */ 449 if (ktestenv("debug.acpi.hpet_test")) 450 acpi_hpet_test(sc); 451 return 0; 452 } 453 #endif 454 455 /* Be sure timer is enabled. */ 456 acpi_hpet_enable(sc); 457 458 /* Read basic statistics about the timer. */ 459 val = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, HPET_PERIOD); 460 if (val == 0) { 461 device_printf(dev, "invalid period\n"); 462 acpi_hpet_disable(sc); 463 bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->mem_res); 464 return ENXIO; 465 } 466 467 freq = (1000000000000000LL + val / 2) / val; 468 if (bootverbose) { 469 val = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, 470 HPET_CAPABILITIES); 471 device_printf(dev, 472 "vend: 0x%x, rev: 0x%x, num: %d, opts:%s%s\n", 473 val >> 16, val & HPET_CAP_REV_ID, 474 (val & HPET_CAP_NUM_TIM) >> 8, 475 (val & HPET_CAP_LEG_RT) ? " legacy_route" : "", 476 (val & HPET_CAP_COUNT_SIZE) ? " 64-bit" : ""); 477 } 478 479 if (ktestenv("debug.acpi.hpet_test")) 480 acpi_hpet_test(sc); 481 482 /* 483 * Don't attach if the timer never increments. Since the spec 484 * requires it to be at least 10 MHz, it has to change in 1 us. 485 */ 486 val = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, 487 HPET_MAIN_COUNTER); 488 DELAY(1); 489 val2 = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, 490 HPET_MAIN_COUNTER); 491 if (val == val2) { 492 device_printf(dev, "HPET never increments, disabling\n"); 493 acpi_hpet_disable(sc); 494 bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->mem_res); 495 return ENXIO; 496 } 497 498 acpi_hpet_timer.freq = freq; 499 device_printf(dev, "frequency %lu\n", acpi_hpet_timer.freq); 500 501 cputimer_register(&acpi_hpet_timer); 502 cputimer_select(&acpi_hpet_timer, 0); 503 504 return 0; 505 } 506 507 /* 508 * Construct the timer. Adjust the base so the system clock does not 509 * jump weirdly. 510 */ 511 static void 512 acpi_hpet_construct(struct cputimer *timer, sysclock_t oldclock) 513 { 514 timer->base = 0; 515 timer->base = oldclock - acpi_hpet_get_timecount(); 516 } 517 518 static sysclock_t 519 acpi_hpet_get_timecount(void) 520 { 521 sysclock_t last_counter; 522 sysclock_t next_counter; 523 uint32_t counter; 524 525 last_counter = acpi_hpet_timer.base; 526 for (;;) { 527 cpu_ccfence(); 528 counter = acpi_hpet_read(); 529 if (counter < (last_counter & 0xFFFFFFFFU)) 530 next_counter = ((last_counter + 0x0100000000U) & 531 0xFFFFFFFF00000000LU) | counter; 532 else 533 next_counter = (last_counter & 534 0xFFFFFFFF00000000LU) | counter; 535 if (atomic_fcmpset_long(&acpi_hpet_timer.base, &last_counter, 536 next_counter)) { 537 break; 538 } 539 } 540 return next_counter; 541 } 542 543 static void 544 acpi_hpet_enable(struct acpi_hpet_softc *sc) 545 { 546 uint32_t val; 547 548 val = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, HPET_CONFIG); 549 bus_space_write_4(acpi_hpet_bst, acpi_hpet_bsh, HPET_CONFIG, 550 val | HPET_CNF_ENABLE); 551 } 552 553 static void 554 acpi_hpet_disable(struct acpi_hpet_softc *sc) 555 { 556 uint32_t val; 557 558 val = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, HPET_CONFIG); 559 bus_space_write_4(acpi_hpet_bst, acpi_hpet_bsh, HPET_CONFIG, 560 val & ~HPET_CNF_ENABLE); 561 } 562 563 static int 564 acpi_hpet_suspend(device_t dev) 565 { 566 /* 567 * According to IA-PC HPET specification rev 1.0a 568 * 569 * Page 10, 2.3.3: 570 * "1. The Event Timer registers (including the main counter) 571 * are not expected to be preserved through an S3, S4, or S5 572 * state." 573 * 574 * Page 11, 2.3.3: 575 * "3. The main counter is permitted, but not required, to run 576 * during S1 or S2 states. ..." 577 * 578 * These mean we are not allowed to enter any of Sx states, 579 * if HPET is used as the sys_cputimer. 580 */ 581 if (sys_cputimer != &acpi_hpet_timer) { 582 struct acpi_hpet_softc *sc; 583 584 sc = device_get_softc(dev); 585 acpi_hpet_disable(sc); 586 587 return 0; 588 } else { 589 return EOPNOTSUPP; 590 } 591 } 592 593 static int 594 acpi_hpet_resume(device_t dev) 595 { 596 if (sys_cputimer != &acpi_hpet_timer) { 597 struct acpi_hpet_softc *sc; 598 599 sc = device_get_softc(dev); 600 acpi_hpet_enable(sc); 601 } 602 return 0; 603 } 604 605 /* Print some basic latency/rate information to assist in debugging. */ 606 static void 607 acpi_hpet_test(struct acpi_hpet_softc *sc) 608 { 609 int i; 610 uint32_t u1, u2; 611 struct timeval b0, b1, b2; 612 struct timespec ts; 613 614 microuptime(&b0); 615 microuptime(&b0); 616 microuptime(&b1); 617 u1 = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, HPET_MAIN_COUNTER); 618 for (i = 1; i < 1000; i++) { 619 u2 = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, 620 HPET_MAIN_COUNTER); 621 } 622 microuptime(&b2); 623 u2 = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, HPET_MAIN_COUNTER); 624 625 timevalsub(&b2, &b1); 626 timevalsub(&b1, &b0); 627 timevalsub(&b2, &b1); 628 629 TIMEVAL_TO_TIMESPEC(&b2, &ts); 630 631 device_printf(sc->dev, "%ld.%09ld: %u ... %u = %u\n", 632 (long)b2.tv_sec, b2.tv_usec, u1, u2, u2 - u1); 633 634 device_printf(sc->dev, "time per call: %ld ns\n", ts.tv_nsec / 1000); 635 } 636