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