tpm_tis.c revision 342084
1342084Smw/*- 2342084Smw * Copyright (c) 2018 Stormshield. 3342084Smw * Copyright (c) 2018 Semihalf. 4342084Smw * All rights reserved. 5342084Smw * 6342084Smw * Redistribution and use in source and binary forms, with or without 7342084Smw * modification, are permitted provided that the following conditions 8342084Smw * are met: 9342084Smw * 1. Redistributions of source code must retain the above copyright 10342084Smw * notice, this list of conditions and the following disclaimer. 11342084Smw * 2. Redistributions in binary form must reproduce the above copyright 12342084Smw * notice, this list of conditions and the following disclaimer in the 13342084Smw * documentation and/or other materials provided with the distribution. 14342084Smw * 15342084Smw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16342084Smw * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17342084Smw * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18342084Smw * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19342084Smw * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20342084Smw * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21342084Smw * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22342084Smw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23342084Smw * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24342084Smw * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25342084Smw * POSSIBILITY OF SUCH DAMAGE. 26342084Smw */ 27342084Smw 28342084Smw#include <sys/cdefs.h> 29342084Smw__FBSDID("$FreeBSD: head/sys/dev/tpm/tpm_tis.c 342084 2018-12-14 16:14:36Z mw $"); 30342084Smw 31342084Smw#include "tpm20.h" 32342084Smw 33342084Smw/* 34342084Smw * TIS register space as defined in 35342084Smw * TCG_PC_Client_Platform_TPM_Profile_PTP_2.0_r1.03_v22 36342084Smw */ 37342084Smw#define TPM_ACCESS 0x0 38342084Smw#define TPM_INT_ENABLE 0x8 39342084Smw#define TPM_INT_VECTOR 0xc 40342084Smw#define TPM_INT_STS 0x10 41342084Smw#define TPM_INTF_CAPS 0x14 42342084Smw#define TPM_STS 0x18 43342084Smw#define TPM_DATA_FIFO 0x24 44342084Smw#define TPM_INTF_ID 0x30 45342084Smw#define TPM_XDATA_FIFO 0x80 46342084Smw#define TPM_DID_VID 0xF00 47342084Smw#define TPM_RID 0xF04 48342084Smw 49342084Smw#define TPM_ACCESS_LOC_REQ BIT(1) 50342084Smw#define TPM_ACCESS_LOC_Seize BIT(3) 51342084Smw#define TPM_ACCESS_LOC_ACTIVE BIT(5) 52342084Smw#define TPM_ACCESS_LOC_RELINQUISH BIT(5) 53342084Smw#define TPM_ACCESS_VALID BIT(7) 54342084Smw 55342084Smw#define TPM_INT_ENABLE_GLOBAL_ENABLE BIT(31) 56342084Smw#define TPM_INT_ENABLE_CMD_RDY BIT(7) 57342084Smw#define TPM_INT_ENABLE_LOC_CHANGE BIT(2) 58342084Smw#define TPM_INT_ENABLE_STS_VALID BIT(1) 59342084Smw#define TPM_INT_ENABLE_DATA_AVAIL BIT(0) 60342084Smw 61342084Smw#define TPM_INT_STS_CMD_RDY BIT(7) 62342084Smw#define TPM_INT_STS_LOC_CHANGE BIT(2) 63342084Smw#define TPM_INT_STS_VALID BIT(1) 64342084Smw#define TPM_INT_STS_DATA_AVAIL BIT(0) 65342084Smw 66342084Smw#define TPM_INTF_CAPS_VERSION 0x70000000 67342084Smw#define TPM_INTF_CAPS_TPM20 0x30000000 68342084Smw 69342084Smw#define TPM_STS_VALID BIT(7) 70342084Smw#define TPM_STS_CMD_RDY BIT(6) 71342084Smw#define TPM_STS_CMD_START BIT(5) 72342084Smw#define TPM_STS_DATA_AVAIL BIT(4) 73342084Smw#define TPM_STS_DATA_EXPECTED BIT(3) 74342084Smw#define TPM_STS_BURST_MASK 0xFFFF00 75342084Smw#define TPM_STS_BURST_OFFSET 0x8 76342084Smw 77342084Smwstatic int tpmtis_transmit(struct tpm_sc *sc, size_t length); 78342084Smw 79342084Smwstatic int tpmtis_acpi_probe(device_t dev); 80342084Smwstatic int tpmtis_attach(device_t dev); 81342084Smwstatic int tpmtis_detach(device_t dev); 82342084Smw 83342084Smwstatic void tpmtis_intr_handler(void *arg); 84342084Smw 85342084Smwstatic ACPI_STATUS tpmtis_get_SIRQ_channel(ACPI_RESOURCE *res, void *arg); 86342084Smwstatic bool tpmtis_setup_intr(struct tpm_sc *sc); 87342084Smw 88342084Smwstatic bool tpmtis_read_bytes(struct tpm_sc *sc, size_t count, uint8_t *buf); 89342084Smwstatic bool tpmtis_write_bytes(struct tpm_sc *sc, size_t count, uint8_t *buf); 90342084Smwstatic bool tpmtis_request_locality(struct tpm_sc *sc, int locality); 91342084Smwstatic void tpmtis_relinquish_locality(struct tpm_sc *sc); 92342084Smwstatic bool tpmtis_go_ready(struct tpm_sc *sc); 93342084Smw 94342084Smwstatic bool tpm_wait_for_u32(struct tpm_sc *sc, bus_size_t off, 95342084Smw uint32_t mask, uint32_t val, int32_t timeout); 96342084Smwstatic uint16_t tpmtis_wait_for_burst(struct tpm_sc *sc); 97342084Smw 98342084Smwchar *tpmtis_ids[] = {"MSFT0101", NULL}; 99342084Smw 100342084Smwstatic int 101342084Smwtpmtis_acpi_probe(device_t dev) 102342084Smw{ 103342084Smw struct resource *res; 104342084Smw int rid = 0; 105342084Smw uint32_t caps; 106342084Smw 107342084Smw if (ACPI_ID_PROBE(device_get_parent(dev), dev, tpmtis_ids) == NULL) 108342084Smw return (ENXIO); 109342084Smw 110342084Smw /* Check if device is in TPM 2.0 TIS mode */ 111342084Smw res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 112342084Smw if (res == NULL) 113342084Smw return (ENXIO); 114342084Smw 115342084Smw caps = bus_read_4(res, TPM_INTF_CAPS); 116342084Smw bus_release_resource(dev, SYS_RES_MEMORY, rid, res); 117342084Smw if ((caps & TPM_INTF_CAPS_VERSION) != TPM_INTF_CAPS_TPM20) 118342084Smw return (ENXIO); 119342084Smw 120342084Smw device_set_desc(dev, "Trusted Platform Module 2.0, FIFO mode"); 121342084Smw return (BUS_PROBE_DEFAULT); 122342084Smw} 123342084Smw 124342084Smwstatic int 125342084Smwtpmtis_attach(device_t dev) 126342084Smw{ 127342084Smw struct tpm_sc *sc; 128342084Smw int result; 129342084Smw 130342084Smw sc = device_get_softc(dev); 131342084Smw sc->dev = dev; 132342084Smw 133342084Smw sc->mem_rid = 0; 134342084Smw sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid, 135342084Smw RF_ACTIVE); 136342084Smw if (sc->mem_res == NULL) 137342084Smw return (ENXIO); 138342084Smw 139342084Smw sc->irq_rid = 0; 140342084Smw sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid, 141342084Smw RF_ACTIVE | RF_SHAREABLE); 142342084Smw if (sc->irq_res != NULL) { 143342084Smw if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 144342084Smw NULL, tpmtis_intr_handler, sc, &sc->intr_cookie)) 145342084Smw sc->interrupts = false; 146342084Smw else 147342084Smw sc->interrupts = tpmtis_setup_intr(sc); 148342084Smw } else { 149342084Smw sc->interrupts = false; 150342084Smw } 151342084Smw 152342084Smw sc->intr_type = -1; 153342084Smw 154342084Smw sc->transmit = tpmtis_transmit; 155342084Smw 156342084Smw result = tpm20_init(sc); 157342084Smw if (result != 0) 158342084Smw tpmtis_detach(dev); 159342084Smw 160342084Smw return (result); 161342084Smw} 162342084Smw 163342084Smwstatic int 164342084Smwtpmtis_detach(device_t dev) 165342084Smw{ 166342084Smw struct tpm_sc *sc; 167342084Smw 168342084Smw sc = device_get_softc(dev); 169342084Smw 170342084Smw if (sc->intr_cookie != NULL) 171342084Smw bus_teardown_intr(dev, sc->irq_res, sc->intr_cookie); 172342084Smw 173342084Smw if (sc->irq_res != NULL) 174342084Smw bus_release_resource(dev, SYS_RES_IRQ, 175342084Smw sc->irq_rid, sc->irq_res); 176342084Smw 177342084Smw if (sc->mem_res != NULL) 178342084Smw bus_release_resource(dev, SYS_RES_MEMORY, 179342084Smw sc->mem_rid, sc->mem_res); 180342084Smw 181342084Smw tpm20_release(sc); 182342084Smw return (0); 183342084Smw} 184342084Smw 185342084Smwstatic ACPI_STATUS 186342084Smwtpmtis_get_SIRQ_channel(ACPI_RESOURCE *res, void *arg) 187342084Smw{ 188342084Smw struct tpm_sc *sc; 189342084Smw uint8_t channel; 190342084Smw 191342084Smw sc = (struct tpm_sc *)arg; 192342084Smw 193342084Smw switch (res->Type) { 194342084Smw case ACPI_RESOURCE_TYPE_IRQ: 195342084Smw channel = res->Data.Irq.Interrupts[0]; 196342084Smw break; 197342084Smw case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 198342084Smw channel = res->Data.ExtendedIrq.Interrupts[0]; 199342084Smw break; 200342084Smw default: 201342084Smw return (AE_OK); 202342084Smw } 203342084Smw 204342084Smw WR1(sc, TPM_INT_VECTOR, channel); 205342084Smw return (AE_OK); 206342084Smw} 207342084Smw 208342084Smwstatic bool 209342084Smwtpmtis_setup_intr(struct tpm_sc *sc) 210342084Smw{ 211342084Smw ACPI_STATUS status; 212342084Smw ACPI_HANDLE handle; 213342084Smw uint32_t irq_mask; 214342084Smw 215342084Smw handle = acpi_get_handle(sc->dev); 216342084Smw 217342084Smw if(!tpmtis_request_locality(sc, 0)) 218342084Smw return (false); 219342084Smw 220342084Smw irq_mask = RD4(sc, TPM_INT_ENABLE); 221342084Smw irq_mask |= TPM_INT_ENABLE_GLOBAL_ENABLE | 222342084Smw TPM_INT_ENABLE_DATA_AVAIL | 223342084Smw TPM_INT_ENABLE_LOC_CHANGE | 224342084Smw TPM_INT_ENABLE_CMD_RDY | 225342084Smw TPM_INT_ENABLE_STS_VALID; 226342084Smw WR4(sc, TPM_INT_ENABLE, irq_mask); 227342084Smw 228342084Smw status = AcpiWalkResources(handle, "_CRS", 229342084Smw tpmtis_get_SIRQ_channel, (void *)sc); 230342084Smw 231342084Smw tpmtis_relinquish_locality(sc); 232342084Smw 233342084Smw return (ACPI_SUCCESS(status)); 234342084Smw} 235342084Smw 236342084Smwstatic void 237342084Smwtpmtis_intr_handler(void *arg) 238342084Smw{ 239342084Smw struct tpm_sc *sc; 240342084Smw uint32_t status; 241342084Smw 242342084Smw sc = (struct tpm_sc *)arg; 243342084Smw status = RD4(sc, TPM_INT_STS); 244342084Smw 245342084Smw WR4(sc, TPM_INT_STS, status); 246342084Smw if (sc->intr_type != -1 && sc->intr_type & status) 247342084Smw wakeup(sc); 248342084Smw} 249342084Smw 250342084Smwstatic bool 251342084Smwtpm_wait_for_u32(struct tpm_sc *sc, bus_size_t off, uint32_t mask, uint32_t val, 252342084Smw int32_t timeout) 253342084Smw{ 254342084Smw 255342084Smw /* Check for condition */ 256342084Smw if ((RD4(sc, off) & mask) == val) 257342084Smw return (true); 258342084Smw 259342084Smw /* If interrupts are enabled sleep for timeout duration */ 260342084Smw if(sc->interrupts && sc->intr_type != -1) { 261342084Smw tsleep(sc, PWAIT, "TPM WITH INTERRUPTS", timeout / tick); 262342084Smw 263342084Smw sc->intr_type = -1; 264342084Smw return ((RD4(sc, off) & mask) == val); 265342084Smw } 266342084Smw 267342084Smw /* If we don't have interrupts poll the device every tick */ 268342084Smw while (timeout > 0) { 269342084Smw if ((RD4(sc, off) & mask) == val) 270342084Smw return (true); 271342084Smw 272342084Smw pause("TPM POLLING", 1); 273342084Smw timeout -= tick; 274342084Smw } 275342084Smw return (false); 276342084Smw} 277342084Smw 278342084Smwstatic uint16_t 279342084Smwtpmtis_wait_for_burst(struct tpm_sc *sc) 280342084Smw{ 281342084Smw int timeout; 282342084Smw uint16_t burst_count; 283342084Smw 284342084Smw timeout = TPM_TIMEOUT_A; 285342084Smw 286342084Smw while (timeout-- > 0) { 287342084Smw burst_count = (RD4(sc, TPM_STS) & TPM_STS_BURST_MASK) >> 288342084Smw TPM_STS_BURST_OFFSET; 289342084Smw if (burst_count > 0) 290342084Smw break; 291342084Smw 292342084Smw DELAY(1); 293342084Smw } 294342084Smw return (burst_count); 295342084Smw} 296342084Smw 297342084Smwstatic bool 298342084Smwtpmtis_read_bytes(struct tpm_sc *sc, size_t count, uint8_t *buf) 299342084Smw{ 300342084Smw uint16_t burst_count; 301342084Smw 302342084Smw while (count > 0) { 303342084Smw burst_count = tpmtis_wait_for_burst(sc); 304342084Smw if (burst_count == 0) 305342084Smw return (false); 306342084Smw 307342084Smw burst_count = MIN(burst_count, count); 308342084Smw count -= burst_count; 309342084Smw 310342084Smw while (burst_count-- > 0) 311342084Smw *buf++ = RD1(sc, TPM_DATA_FIFO); 312342084Smw } 313342084Smw 314342084Smw return (true); 315342084Smw} 316342084Smw 317342084Smwstatic bool 318342084Smwtpmtis_write_bytes(struct tpm_sc *sc, size_t count, uint8_t *buf) 319342084Smw{ 320342084Smw uint16_t burst_count; 321342084Smw 322342084Smw while (count > 0) { 323342084Smw burst_count = tpmtis_wait_for_burst(sc); 324342084Smw if (burst_count == 0) 325342084Smw return (false); 326342084Smw 327342084Smw burst_count = MIN(burst_count, count); 328342084Smw count -= burst_count; 329342084Smw 330342084Smw while (burst_count-- > 0) 331342084Smw WR1(sc, TPM_DATA_FIFO, *buf++); 332342084Smw } 333342084Smw 334342084Smw return (true); 335342084Smw} 336342084Smw 337342084Smw 338342084Smwstatic bool 339342084Smwtpmtis_request_locality(struct tpm_sc *sc, int locality) 340342084Smw{ 341342084Smw uint8_t mask; 342342084Smw int timeout; 343342084Smw 344342084Smw /* Currently we only support Locality 0 */ 345342084Smw if (locality != 0) 346342084Smw return (false); 347342084Smw 348342084Smw mask = TPM_ACCESS_LOC_ACTIVE | TPM_ACCESS_VALID; 349342084Smw timeout = TPM_TIMEOUT_A; 350342084Smw sc->intr_type = TPM_INT_STS_LOC_CHANGE; 351342084Smw 352342084Smw WR1(sc, TPM_ACCESS, TPM_ACCESS_LOC_REQ); 353342084Smw bus_barrier(sc->mem_res, TPM_ACCESS, 1, BUS_SPACE_BARRIER_WRITE); 354342084Smw if(sc->interrupts) { 355342084Smw tsleep(sc, PWAIT, "TPMLOCREQUEST with INTR", timeout / tick); 356342084Smw return ((RD1(sc, TPM_ACCESS) & mask) == mask); 357342084Smw } else { 358342084Smw while(timeout > 0) { 359342084Smw if ((RD1(sc, TPM_ACCESS) & mask) == mask) 360342084Smw return (true); 361342084Smw 362342084Smw pause("TPMLOCREQUEST POLLING", 1); 363342084Smw timeout -= tick; 364342084Smw } 365342084Smw } 366342084Smw 367342084Smw return (false); 368342084Smw} 369342084Smw 370342084Smwstatic void 371342084Smwtpmtis_relinquish_locality(struct tpm_sc *sc) 372342084Smw{ 373342084Smw 374342084Smw /* 375342084Smw * Interrupts can only be cleared when a locality is active. 376342084Smw * Clear them now in case interrupt handler didn't make it in time. 377342084Smw */ 378342084Smw if(sc->interrupts) 379342084Smw AND4(sc, TPM_INT_STS, RD4(sc, TPM_INT_STS)); 380342084Smw 381342084Smw OR1(sc, TPM_ACCESS, TPM_ACCESS_LOC_RELINQUISH); 382342084Smw} 383342084Smw 384342084Smwstatic bool 385342084Smwtpmtis_go_ready(struct tpm_sc *sc) 386342084Smw{ 387342084Smw uint32_t mask; 388342084Smw 389342084Smw mask = TPM_STS_CMD_RDY; 390342084Smw sc->intr_type = TPM_INT_STS_CMD_RDY; 391342084Smw 392342084Smw OR4(sc, TPM_STS, TPM_STS_CMD_RDY); 393342084Smw bus_barrier(sc->mem_res, TPM_STS, 4, BUS_SPACE_BARRIER_WRITE); 394342084Smw if (!tpm_wait_for_u32(sc, TPM_STS, mask, mask, TPM_TIMEOUT_B)) 395342084Smw return (false); 396342084Smw 397342084Smw AND4(sc, TPM_STS, ~TPM_STS_CMD_RDY); 398342084Smw return (true); 399342084Smw} 400342084Smw 401342084Smwstatic int 402342084Smwtpmtis_transmit(struct tpm_sc *sc, size_t length) 403342084Smw{ 404342084Smw size_t bytes_available; 405342084Smw uint32_t mask, curr_cmd; 406342084Smw int timeout; 407342084Smw 408342084Smw sx_assert(&sc->dev_lock, SA_XLOCKED); 409342084Smw 410342084Smw if (!tpmtis_request_locality(sc, 0)) { 411342084Smw device_printf(sc->dev, 412342084Smw "Failed to obtain locality\n"); 413342084Smw return (EIO); 414342084Smw } 415342084Smw if (!tpmtis_go_ready(sc)) { 416342084Smw device_printf(sc->dev, 417342084Smw "Failed to switch to ready state\n"); 418342084Smw return (EIO); 419342084Smw } 420342084Smw if (!tpmtis_write_bytes(sc, length, sc->buf)) { 421342084Smw device_printf(sc->dev, 422342084Smw "Failed to write cmd to device\n"); 423342084Smw return (EIO); 424342084Smw } 425342084Smw 426342084Smw mask = TPM_STS_VALID; 427342084Smw sc->intr_type = TPM_INT_STS_VALID; 428342084Smw if (!tpm_wait_for_u32(sc, TPM_STS, mask, mask, TPM_TIMEOUT_C)) { 429342084Smw device_printf(sc->dev, 430342084Smw "Timeout while waiting for valid bit\n"); 431342084Smw return (EIO); 432342084Smw } 433342084Smw if (RD4(sc, TPM_STS) & TPM_STS_DATA_EXPECTED) { 434342084Smw device_printf(sc->dev, 435342084Smw "Device expects more data even though we already" 436342084Smw " sent everything we had\n"); 437342084Smw return (EIO); 438342084Smw } 439342084Smw 440342084Smw /* 441342084Smw * Calculate timeout for current command. 442342084Smw * Command code is passed in bytes 6-10. 443342084Smw */ 444342084Smw curr_cmd = be32toh(*(uint32_t *) (&sc->buf[6])); 445342084Smw timeout = tpm20_get_timeout(curr_cmd); 446342084Smw 447342084Smw WR4(sc, TPM_STS, TPM_STS_CMD_START); 448342084Smw bus_barrier(sc->mem_res, TPM_STS, 4, BUS_SPACE_BARRIER_WRITE); 449342084Smw 450342084Smw mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID; 451342084Smw sc->intr_type = TPM_INT_STS_DATA_AVAIL; 452342084Smw if (!tpm_wait_for_u32(sc, TPM_STS, mask, mask, timeout)) { 453342084Smw device_printf(sc->dev, 454342084Smw "Timeout while waiting for device to process cmd\n"); 455342084Smw /* 456342084Smw * Switching to ready state also cancels processing 457342084Smw * current command 458342084Smw */ 459342084Smw if (!tpmtis_go_ready(sc)) 460342084Smw return (EIO); 461342084Smw 462342084Smw /* 463342084Smw * After canceling a command we should get a response, 464342084Smw * check if there is one. 465342084Smw */ 466342084Smw sc->intr_type = TPM_INT_STS_DATA_AVAIL; 467342084Smw if (!tpm_wait_for_u32(sc, TPM_STS, mask, mask, TPM_TIMEOUT_C)) 468342084Smw return (EIO); 469342084Smw } 470342084Smw /* Read response header. Length is passed in bytes 2 - 6. */ 471342084Smw if(!tpmtis_read_bytes(sc, TPM_HEADER_SIZE, sc->buf)) { 472342084Smw device_printf(sc->dev, 473342084Smw "Failed to read response header\n"); 474342084Smw return (EIO); 475342084Smw } 476342084Smw bytes_available = be32toh(*(uint32_t *) (&sc->buf[2])); 477342084Smw 478342084Smw if (bytes_available > TPM_BUFSIZE || bytes_available < TPM_HEADER_SIZE) { 479342084Smw device_printf(sc->dev, 480342084Smw "Incorrect response size: %zu\n", 481342084Smw bytes_available); 482342084Smw return (EIO); 483342084Smw } 484342084Smw if(!tpmtis_read_bytes(sc, bytes_available - TPM_HEADER_SIZE, 485342084Smw &sc->buf[TPM_HEADER_SIZE])) { 486342084Smw device_printf(sc->dev, 487342084Smw "Failed to read response\n"); 488342084Smw return (EIO); 489342084Smw } 490342084Smw tpmtis_relinquish_locality(sc); 491342084Smw sc->pending_data_length = bytes_available; 492342084Smw 493342084Smw return (0); 494342084Smw} 495342084Smw 496342084Smw/* ACPI Driver */ 497342084Smwstatic device_method_t tpmtis_methods[] = { 498342084Smw DEVMETHOD(device_probe, tpmtis_acpi_probe), 499342084Smw DEVMETHOD(device_attach, tpmtis_attach), 500342084Smw DEVMETHOD(device_detach, tpmtis_detach), 501342084Smw DEVMETHOD(device_shutdown, tpm20_shutdown), 502342084Smw DEVMETHOD(device_suspend, tpm20_suspend), 503342084Smw {0, 0} 504342084Smw}; 505342084Smwstatic driver_t tpmtis_driver = { 506342084Smw "tpmtis", tpmtis_methods, sizeof(struct tpm_sc), 507342084Smw}; 508342084Smw 509342084Smwdevclass_t tpmtis_devclass; 510342084SmwDRIVER_MODULE(tpmtis, acpi, tpmtis_driver, tpmtis_devclass, 0, 0); 511