linux/drivers/char/tpm/tpm_infineon.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Description:
   4 * Device Driver for the Infineon Technologies
   5 * SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module
   6 * Specifications at www.trustedcomputinggroup.org
   7 *
   8 * Copyright (C) 2005, Marcel Selhorst <tpmdd@selhorst.net>
   9 * Sirrix AG - security technologies <tpmdd@sirrix.com> and
  10 * Applied Data Security Group, Ruhr-University Bochum, Germany
  11 * Project-Homepage: http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/ 
  12 */
  13
  14#include <linux/init.h>
  15#include <linux/pnp.h>
  16#include "tpm.h"
  17
  18/* Infineon specific definitions */
  19/* maximum number of WTX-packages */
  20#define TPM_MAX_WTX_PACKAGES    50
  21/* msleep-Time for WTX-packages */
  22#define TPM_WTX_MSLEEP_TIME     20
  23/* msleep-Time --> Interval to check status register */
  24#define TPM_MSLEEP_TIME         3
  25/* gives number of max. msleep()-calls before throwing timeout */
  26#define TPM_MAX_TRIES           5000
  27#define TPM_INFINEON_DEV_VEN_VALUE      0x15D1
  28
  29#define TPM_INF_IO_PORT         0x0
  30#define TPM_INF_IO_MEM          0x1
  31
  32#define TPM_INF_ADDR            0x0
  33#define TPM_INF_DATA            0x1
  34
  35struct tpm_inf_dev {
  36        int iotype;
  37
  38        void __iomem *mem_base; /* MMIO ioremap'd addr */
  39        unsigned long map_base; /* phys MMIO base */
  40        unsigned long map_size; /* MMIO region size */
  41        unsigned int index_off; /* index register offset */
  42
  43        unsigned int data_regs; /* Data registers */
  44        unsigned int data_size;
  45
  46        unsigned int config_port;       /* IO Port config index reg */
  47        unsigned int config_size;
  48};
  49
  50static struct tpm_inf_dev tpm_dev;
  51
  52static inline void tpm_data_out(unsigned char data, unsigned char offset)
  53{
  54        if (tpm_dev.iotype == TPM_INF_IO_PORT)
  55                outb(data, tpm_dev.data_regs + offset);
  56        else
  57                writeb(data, tpm_dev.mem_base + tpm_dev.data_regs + offset);
  58}
  59
  60static inline unsigned char tpm_data_in(unsigned char offset)
  61{
  62        if (tpm_dev.iotype == TPM_INF_IO_PORT)
  63                return inb(tpm_dev.data_regs + offset);
  64        else
  65                return readb(tpm_dev.mem_base + tpm_dev.data_regs + offset);
  66}
  67
  68static inline void tpm_config_out(unsigned char data, unsigned char offset)
  69{
  70        if (tpm_dev.iotype == TPM_INF_IO_PORT)
  71                outb(data, tpm_dev.config_port + offset);
  72        else
  73                writeb(data, tpm_dev.mem_base + tpm_dev.index_off + offset);
  74}
  75
  76static inline unsigned char tpm_config_in(unsigned char offset)
  77{
  78        if (tpm_dev.iotype == TPM_INF_IO_PORT)
  79                return inb(tpm_dev.config_port + offset);
  80        else
  81                return readb(tpm_dev.mem_base + tpm_dev.index_off + offset);
  82}
  83
  84/* TPM header definitions */
  85enum infineon_tpm_header {
  86        TPM_VL_VER = 0x01,
  87        TPM_VL_CHANNEL_CONTROL = 0x07,
  88        TPM_VL_CHANNEL_PERSONALISATION = 0x0A,
  89        TPM_VL_CHANNEL_TPM = 0x0B,
  90        TPM_VL_CONTROL = 0x00,
  91        TPM_INF_NAK = 0x15,
  92        TPM_CTRL_WTX = 0x10,
  93        TPM_CTRL_WTX_ABORT = 0x18,
  94        TPM_CTRL_WTX_ABORT_ACK = 0x18,
  95        TPM_CTRL_ERROR = 0x20,
  96        TPM_CTRL_CHAININGACK = 0x40,
  97        TPM_CTRL_CHAINING = 0x80,
  98        TPM_CTRL_DATA = 0x04,
  99        TPM_CTRL_DATA_CHA = 0x84,
 100        TPM_CTRL_DATA_CHA_ACK = 0xC4
 101};
 102
 103enum infineon_tpm_register {
 104        WRFIFO = 0x00,
 105        RDFIFO = 0x01,
 106        STAT = 0x02,
 107        CMD = 0x03
 108};
 109
 110enum infineon_tpm_command_bits {
 111        CMD_DIS = 0x00,
 112        CMD_LP = 0x01,
 113        CMD_RES = 0x02,
 114        CMD_IRQC = 0x06
 115};
 116
 117enum infineon_tpm_status_bits {
 118        STAT_XFE = 0x00,
 119        STAT_LPA = 0x01,
 120        STAT_FOK = 0x02,
 121        STAT_TOK = 0x03,
 122        STAT_IRQA = 0x06,
 123        STAT_RDA = 0x07
 124};
 125
 126/* some outgoing values */
 127enum infineon_tpm_values {
 128        CHIP_ID1 = 0x20,
 129        CHIP_ID2 = 0x21,
 130        TPM_DAR = 0x30,
 131        RESET_LP_IRQC_DISABLE = 0x41,
 132        ENABLE_REGISTER_PAIR = 0x55,
 133        IOLIMH = 0x60,
 134        IOLIML = 0x61,
 135        DISABLE_REGISTER_PAIR = 0xAA,
 136        IDVENL = 0xF1,
 137        IDVENH = 0xF2,
 138        IDPDL = 0xF3,
 139        IDPDH = 0xF4
 140};
 141
 142static int number_of_wtx;
 143
 144static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
 145{
 146        int status;
 147        int check = 0;
 148        int i;
 149
 150        if (clear_wrfifo) {
 151                for (i = 0; i < 4096; i++) {
 152                        status = tpm_data_in(WRFIFO);
 153                        if (status == 0xff) {
 154                                if (check == 5)
 155                                        break;
 156                                else
 157                                        check++;
 158                        }
 159                }
 160        }
 161        /* Note: The values which are currently in the FIFO of the TPM
 162           are thrown away since there is no usage for them. Usually,
 163           this has nothing to say, since the TPM will give its answer
 164           immediately or will be aborted anyway, so the data here is
 165           usually garbage and useless.
 166           We have to clean this, because the next communication with
 167           the TPM would be rubbish, if there is still some old data
 168           in the Read FIFO.
 169         */
 170        i = 0;
 171        do {
 172                status = tpm_data_in(RDFIFO);
 173                status = tpm_data_in(STAT);
 174                i++;
 175                if (i == TPM_MAX_TRIES)
 176                        return -EIO;
 177        } while ((status & (1 << STAT_RDA)) != 0);
 178        return 0;
 179}
 180
 181static int wait(struct tpm_chip *chip, int wait_for_bit)
 182{
 183        int status;
 184        int i;
 185        for (i = 0; i < TPM_MAX_TRIES; i++) {
 186                status = tpm_data_in(STAT);
 187                /* check the status-register if wait_for_bit is set */
 188                if (status & 1 << wait_for_bit)
 189                        break;
 190                tpm_msleep(TPM_MSLEEP_TIME);
 191        }
 192        if (i == TPM_MAX_TRIES) {       /* timeout occurs */
 193                if (wait_for_bit == STAT_XFE)
 194                        dev_err(&chip->dev, "Timeout in wait(STAT_XFE)\n");
 195                if (wait_for_bit == STAT_RDA)
 196                        dev_err(&chip->dev, "Timeout in wait(STAT_RDA)\n");
 197                return -EIO;
 198        }
 199        return 0;
 200};
 201
 202static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
 203{
 204        wait(chip, STAT_XFE);
 205        tpm_data_out(sendbyte, WRFIFO);
 206}
 207
 208    /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
 209       calculation time, it sends a WTX-package, which has to be acknowledged
 210       or aborted. This usually occurs if you are hammering the TPM with key
 211       creation. Set the maximum number of WTX-packages in the definitions
 212       above, if the number is reached, the waiting-time will be denied
 213       and the TPM command has to be resend.
 214     */
 215
 216static void tpm_wtx(struct tpm_chip *chip)
 217{
 218        number_of_wtx++;
 219        dev_info(&chip->dev, "Granting WTX (%02d / %02d)\n",
 220                 number_of_wtx, TPM_MAX_WTX_PACKAGES);
 221        wait_and_send(chip, TPM_VL_VER);
 222        wait_and_send(chip, TPM_CTRL_WTX);
 223        wait_and_send(chip, 0x00);
 224        wait_and_send(chip, 0x00);
 225        tpm_msleep(TPM_WTX_MSLEEP_TIME);
 226}
 227
 228static void tpm_wtx_abort(struct tpm_chip *chip)
 229{
 230        dev_info(&chip->dev, "Aborting WTX\n");
 231        wait_and_send(chip, TPM_VL_VER);
 232        wait_and_send(chip, TPM_CTRL_WTX_ABORT);
 233        wait_and_send(chip, 0x00);
 234        wait_and_send(chip, 0x00);
 235        number_of_wtx = 0;
 236        tpm_msleep(TPM_WTX_MSLEEP_TIME);
 237}
 238
 239static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
 240{
 241        int i;
 242        int ret;
 243        u32 size = 0;
 244        number_of_wtx = 0;
 245
 246recv_begin:
 247        /* start receiving header */
 248        for (i = 0; i < 4; i++) {
 249                ret = wait(chip, STAT_RDA);
 250                if (ret)
 251                        return -EIO;
 252                buf[i] = tpm_data_in(RDFIFO);
 253        }
 254
 255        if (buf[0] != TPM_VL_VER) {
 256                dev_err(&chip->dev,
 257                        "Wrong transport protocol implementation!\n");
 258                return -EIO;
 259        }
 260
 261        if (buf[1] == TPM_CTRL_DATA) {
 262                /* size of the data received */
 263                size = ((buf[2] << 8) | buf[3]);
 264
 265                for (i = 0; i < size; i++) {
 266                        wait(chip, STAT_RDA);
 267                        buf[i] = tpm_data_in(RDFIFO);
 268                }
 269
 270                if ((size == 0x6D00) && (buf[1] == 0x80)) {
 271                        dev_err(&chip->dev, "Error handling on vendor layer!\n");
 272                        return -EIO;
 273                }
 274
 275                for (i = 0; i < size; i++)
 276                        buf[i] = buf[i + 6];
 277
 278                size = size - 6;
 279                return size;
 280        }
 281
 282        if (buf[1] == TPM_CTRL_WTX) {
 283                dev_info(&chip->dev, "WTX-package received\n");
 284                if (number_of_wtx < TPM_MAX_WTX_PACKAGES) {
 285                        tpm_wtx(chip);
 286                        goto recv_begin;
 287                } else {
 288                        tpm_wtx_abort(chip);
 289                        goto recv_begin;
 290                }
 291        }
 292
 293        if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) {
 294                dev_info(&chip->dev, "WTX-abort acknowledged\n");
 295                return size;
 296        }
 297
 298        if (buf[1] == TPM_CTRL_ERROR) {
 299                dev_err(&chip->dev, "ERROR-package received:\n");
 300                if (buf[4] == TPM_INF_NAK)
 301                        dev_err(&chip->dev,
 302                                "-> Negative acknowledgement"
 303                                " - retransmit command!\n");
 304                return -EIO;
 305        }
 306        return -EIO;
 307}
 308
 309static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
 310{
 311        int i;
 312        int ret;
 313        u8 count_high, count_low, count_4, count_3, count_2, count_1;
 314
 315        /* Disabling Reset, LP and IRQC */
 316        tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
 317
 318        ret = empty_fifo(chip, 1);
 319        if (ret) {
 320                dev_err(&chip->dev, "Timeout while clearing FIFO\n");
 321                return -EIO;
 322        }
 323
 324        ret = wait(chip, STAT_XFE);
 325        if (ret)
 326                return -EIO;
 327
 328        count_4 = (count & 0xff000000) >> 24;
 329        count_3 = (count & 0x00ff0000) >> 16;
 330        count_2 = (count & 0x0000ff00) >> 8;
 331        count_1 = (count & 0x000000ff);
 332        count_high = ((count + 6) & 0xffffff00) >> 8;
 333        count_low = ((count + 6) & 0x000000ff);
 334
 335        /* Sending Header */
 336        wait_and_send(chip, TPM_VL_VER);
 337        wait_and_send(chip, TPM_CTRL_DATA);
 338        wait_and_send(chip, count_high);
 339        wait_and_send(chip, count_low);
 340
 341        /* Sending Data Header */
 342        wait_and_send(chip, TPM_VL_VER);
 343        wait_and_send(chip, TPM_VL_CHANNEL_TPM);
 344        wait_and_send(chip, count_4);
 345        wait_and_send(chip, count_3);
 346        wait_and_send(chip, count_2);
 347        wait_and_send(chip, count_1);
 348
 349        /* Sending Data */
 350        for (i = 0; i < count; i++) {
 351                wait_and_send(chip, buf[i]);
 352        }
 353        return 0;
 354}
 355
 356static void tpm_inf_cancel(struct tpm_chip *chip)
 357{
 358        /*
 359           Since we are using the legacy mode to communicate
 360           with the TPM, we have no cancel functions, but have
 361           a workaround for interrupting the TPM through WTX.
 362         */
 363}
 364
 365static u8 tpm_inf_status(struct tpm_chip *chip)
 366{
 367        return tpm_data_in(STAT);
 368}
 369
 370static const struct tpm_class_ops tpm_inf = {
 371        .recv = tpm_inf_recv,
 372        .send = tpm_inf_send,
 373        .cancel = tpm_inf_cancel,
 374        .status = tpm_inf_status,
 375        .req_complete_mask = 0,
 376        .req_complete_val = 0,
 377};
 378
 379static const struct pnp_device_id tpm_inf_pnp_tbl[] = {
 380        /* Infineon TPMs */
 381        {"IFX0101", 0},
 382        {"IFX0102", 0},
 383        {"", 0}
 384};
 385
 386MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl);
 387
 388static int tpm_inf_pnp_probe(struct pnp_dev *dev,
 389                                       const struct pnp_device_id *dev_id)
 390{
 391        int rc = 0;
 392        u8 iol, ioh;
 393        int vendorid[2];
 394        int version[2];
 395        int productid[2];
 396        const char *chipname;
 397        struct tpm_chip *chip;
 398
 399        /* read IO-ports through PnP */
 400        if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
 401            !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
 402
 403                tpm_dev.iotype = TPM_INF_IO_PORT;
 404
 405                tpm_dev.config_port = pnp_port_start(dev, 0);
 406                tpm_dev.config_size = pnp_port_len(dev, 0);
 407                tpm_dev.data_regs = pnp_port_start(dev, 1);
 408                tpm_dev.data_size = pnp_port_len(dev, 1);
 409                if ((tpm_dev.data_size < 4) || (tpm_dev.config_size < 2)) {
 410                        rc = -EINVAL;
 411                        goto err_last;
 412                }
 413                dev_info(&dev->dev, "Found %s with ID %s\n",
 414                         dev->name, dev_id->id);
 415                if (!((tpm_dev.data_regs >> 8) & 0xff)) {
 416                        rc = -EINVAL;
 417                        goto err_last;
 418                }
 419                /* publish my base address and request region */
 420                if (request_region(tpm_dev.data_regs, tpm_dev.data_size,
 421                                   "tpm_infineon0") == NULL) {
 422                        rc = -EINVAL;
 423                        goto err_last;
 424                }
 425                if (request_region(tpm_dev.config_port, tpm_dev.config_size,
 426                                   "tpm_infineon0") == NULL) {
 427                        release_region(tpm_dev.data_regs, tpm_dev.data_size);
 428                        rc = -EINVAL;
 429                        goto err_last;
 430                }
 431        } else if (pnp_mem_valid(dev, 0) &&
 432                   !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) {
 433
 434                tpm_dev.iotype = TPM_INF_IO_MEM;
 435
 436                tpm_dev.map_base = pnp_mem_start(dev, 0);
 437                tpm_dev.map_size = pnp_mem_len(dev, 0);
 438
 439                dev_info(&dev->dev, "Found %s with ID %s\n",
 440                         dev->name, dev_id->id);
 441
 442                /* publish my base address and request region */
 443                if (request_mem_region(tpm_dev.map_base, tpm_dev.map_size,
 444                                       "tpm_infineon0") == NULL) {
 445                        rc = -EINVAL;
 446                        goto err_last;
 447                }
 448
 449                tpm_dev.mem_base = ioremap(tpm_dev.map_base, tpm_dev.map_size);
 450                if (tpm_dev.mem_base == NULL) {
 451                        release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
 452                        rc = -EINVAL;
 453                        goto err_last;
 454                }
 455
 456                /*
 457                 * The only known MMIO based Infineon TPM system provides
 458                 * a single large mem region with the device config
 459                 * registers at the default TPM_ADDR.  The data registers
 460                 * seem like they could be placed anywhere within the MMIO
 461                 * region, but lets just put them at zero offset.
 462                 */
 463                tpm_dev.index_off = TPM_ADDR;
 464                tpm_dev.data_regs = 0x0;
 465        } else {
 466                rc = -EINVAL;
 467                goto err_last;
 468        }
 469
 470        /* query chip for its vendor, its version number a.s.o. */
 471        tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
 472        tpm_config_out(IDVENL, TPM_INF_ADDR);
 473        vendorid[1] = tpm_config_in(TPM_INF_DATA);
 474        tpm_config_out(IDVENH, TPM_INF_ADDR);
 475        vendorid[0] = tpm_config_in(TPM_INF_DATA);
 476        tpm_config_out(IDPDL, TPM_INF_ADDR);
 477        productid[1] = tpm_config_in(TPM_INF_DATA);
 478        tpm_config_out(IDPDH, TPM_INF_ADDR);
 479        productid[0] = tpm_config_in(TPM_INF_DATA);
 480        tpm_config_out(CHIP_ID1, TPM_INF_ADDR);
 481        version[1] = tpm_config_in(TPM_INF_DATA);
 482        tpm_config_out(CHIP_ID2, TPM_INF_ADDR);
 483        version[0] = tpm_config_in(TPM_INF_DATA);
 484
 485        switch ((productid[0] << 8) | productid[1]) {
 486        case 6:
 487                chipname = " (SLD 9630 TT 1.1)";
 488                break;
 489        case 11:
 490                chipname = " (SLB 9635 TT 1.2)";
 491                break;
 492        default:
 493                chipname = " (unknown chip)";
 494                break;
 495        }
 496
 497        if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
 498
 499                /* configure TPM with IO-ports */
 500                tpm_config_out(IOLIMH, TPM_INF_ADDR);
 501                tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
 502                tpm_config_out(IOLIML, TPM_INF_ADDR);
 503                tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
 504
 505                /* control if IO-ports are set correctly */
 506                tpm_config_out(IOLIMH, TPM_INF_ADDR);
 507                ioh = tpm_config_in(TPM_INF_DATA);
 508                tpm_config_out(IOLIML, TPM_INF_ADDR);
 509                iol = tpm_config_in(TPM_INF_DATA);
 510
 511                if ((ioh << 8 | iol) != tpm_dev.data_regs) {
 512                        dev_err(&dev->dev,
 513                                "Could not set IO-data registers to 0x%x\n",
 514                                tpm_dev.data_regs);
 515                        rc = -EIO;
 516                        goto err_release_region;
 517                }
 518
 519                /* activate register */
 520                tpm_config_out(TPM_DAR, TPM_INF_ADDR);
 521                tpm_config_out(0x01, TPM_INF_DATA);
 522                tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
 523
 524                /* disable RESET, LP and IRQC */
 525                tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
 526
 527                /* Finally, we're done, print some infos */
 528                dev_info(&dev->dev, "TPM found: "
 529                         "config base 0x%lx, "
 530                         "data base 0x%lx, "
 531                         "chip version 0x%02x%02x, "
 532                         "vendor id 0x%x%x (Infineon), "
 533                         "product id 0x%02x%02x"
 534                         "%s\n",
 535                         tpm_dev.iotype == TPM_INF_IO_PORT ?
 536                         tpm_dev.config_port :
 537                         tpm_dev.map_base + tpm_dev.index_off,
 538                         tpm_dev.iotype == TPM_INF_IO_PORT ?
 539                         tpm_dev.data_regs :
 540                         tpm_dev.map_base + tpm_dev.data_regs,
 541                         version[0], version[1],
 542                         vendorid[0], vendorid[1],
 543                         productid[0], productid[1], chipname);
 544
 545                chip = tpmm_chip_alloc(&dev->dev, &tpm_inf);
 546                if (IS_ERR(chip)) {
 547                        rc = PTR_ERR(chip);
 548                        goto err_release_region;
 549                }
 550
 551                rc = tpm_chip_register(chip);
 552                if (rc)
 553                        goto err_release_region;
 554
 555                return 0;
 556        } else {
 557                rc = -ENODEV;
 558                goto err_release_region;
 559        }
 560
 561err_release_region:
 562        if (tpm_dev.iotype == TPM_INF_IO_PORT) {
 563                release_region(tpm_dev.data_regs, tpm_dev.data_size);
 564                release_region(tpm_dev.config_port, tpm_dev.config_size);
 565        } else {
 566                iounmap(tpm_dev.mem_base);
 567                release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
 568        }
 569
 570err_last:
 571        return rc;
 572}
 573
 574static void tpm_inf_pnp_remove(struct pnp_dev *dev)
 575{
 576        struct tpm_chip *chip = pnp_get_drvdata(dev);
 577
 578        tpm_chip_unregister(chip);
 579
 580        if (tpm_dev.iotype == TPM_INF_IO_PORT) {
 581                release_region(tpm_dev.data_regs, tpm_dev.data_size);
 582                release_region(tpm_dev.config_port,
 583                               tpm_dev.config_size);
 584        } else {
 585                iounmap(tpm_dev.mem_base);
 586                release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
 587        }
 588}
 589
 590#ifdef CONFIG_PM_SLEEP
 591static int tpm_inf_resume(struct device *dev)
 592{
 593        /* Re-configure TPM after suspending */
 594        tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
 595        tpm_config_out(IOLIMH, TPM_INF_ADDR);
 596        tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
 597        tpm_config_out(IOLIML, TPM_INF_ADDR);
 598        tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
 599        /* activate register */
 600        tpm_config_out(TPM_DAR, TPM_INF_ADDR);
 601        tpm_config_out(0x01, TPM_INF_DATA);
 602        tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
 603        /* disable RESET, LP and IRQC */
 604        tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
 605        return tpm_pm_resume(dev);
 606}
 607#endif
 608static SIMPLE_DEV_PM_OPS(tpm_inf_pm, tpm_pm_suspend, tpm_inf_resume);
 609
 610static struct pnp_driver tpm_inf_pnp_driver = {
 611        .name = "tpm_inf_pnp",
 612        .id_table = tpm_inf_pnp_tbl,
 613        .probe = tpm_inf_pnp_probe,
 614        .remove = tpm_inf_pnp_remove,
 615        .driver = {
 616                .pm = &tpm_inf_pm,
 617        }
 618};
 619
 620module_pnp_driver(tpm_inf_pnp_driver);
 621
 622MODULE_AUTHOR("Marcel Selhorst <tpmdd@sirrix.com>");
 623MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
 624MODULE_VERSION("1.9.2");
 625MODULE_LICENSE("GPL");
 626