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