root/drivers/char/tpm/tpm_infineon.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tpm_data_out
  2. tpm_data_in
  3. tpm_config_out
  4. tpm_config_in
  5. empty_fifo
  6. wait
  7. wait_and_send
  8. tpm_wtx
  9. tpm_wtx_abort
  10. tpm_inf_recv
  11. tpm_inf_send
  12. tpm_inf_cancel
  13. tpm_inf_status
  14. tpm_inf_pnp_probe
  15. tpm_inf_pnp_remove
  16. tpm_inf_resume

   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 
  35 struct 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 
  50 static struct tpm_inf_dev tpm_dev;
  51 
  52 static 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 
  60 static 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 
  68 static 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 
  76 static 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 */
  85 enum 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 
 103 enum infineon_tpm_register {
 104         WRFIFO = 0x00,
 105         RDFIFO = 0x01,
 106         STAT = 0x02,
 107         CMD = 0x03
 108 };
 109 
 110 enum infineon_tpm_command_bits {
 111         CMD_DIS = 0x00,
 112         CMD_LP = 0x01,
 113         CMD_RES = 0x02,
 114         CMD_IRQC = 0x06
 115 };
 116 
 117 enum 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 */
 127 enum 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 
 142 static int number_of_wtx;
 143 
 144 static 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 
 181 static 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 
 202 static 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 
 216 static 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 
 228 static 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 
 239 static 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 
 246 recv_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 
 309 static 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 
 356 static 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 
 365 static u8 tpm_inf_status(struct tpm_chip *chip)
 366 {
 367         return tpm_data_in(STAT);
 368 }
 369 
 370 static 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 
 379 static const struct pnp_device_id tpm_inf_pnp_tbl[] = {
 380         /* Infineon TPMs */
 381         {"IFX0101", 0},
 382         {"IFX0102", 0},
 383         {"", 0}
 384 };
 385 
 386 MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl);
 387 
 388 static 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 
 561 err_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 
 570 err_last:
 571         return rc;
 572 }
 573 
 574 static 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
 591 static 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
 608 static SIMPLE_DEV_PM_OPS(tpm_inf_pm, tpm_pm_suspend, tpm_inf_resume);
 609 
 610 static 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 
 620 module_pnp_driver(tpm_inf_pnp_driver);
 621 
 622 MODULE_AUTHOR("Marcel Selhorst <tpmdd@sirrix.com>");
 623 MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
 624 MODULE_VERSION("1.9.2");
 625 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */