Merge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
[linux-2.6] / drivers / char / tpm / tpm_infineon.c
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 <selhorst@crypto.rub.de>
8  * Sirrix AG - security technologies, http://www.sirrix.com and
9  * Applied Data Security Group, Ruhr-University Bochum, Germany
10  * Project-Homepage: http://www.prosec.rub.de/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 */
89 enum infineon_tpm_header {
90         TPM_VL_VER = 0x01,
91         TPM_VL_CHANNEL_CONTROL = 0x07,
92         TPM_VL_CHANNEL_PERSONALISATION = 0x0A,
93         TPM_VL_CHANNEL_TPM = 0x0B,
94         TPM_VL_CONTROL = 0x00,
95         TPM_INF_NAK = 0x15,
96         TPM_CTRL_WTX = 0x10,
97         TPM_CTRL_WTX_ABORT = 0x18,
98         TPM_CTRL_WTX_ABORT_ACK = 0x18,
99         TPM_CTRL_ERROR = 0x20,
100         TPM_CTRL_CHAININGACK = 0x40,
101         TPM_CTRL_CHAINING = 0x80,
102         TPM_CTRL_DATA = 0x04,
103         TPM_CTRL_DATA_CHA = 0x84,
104         TPM_CTRL_DATA_CHA_ACK = 0xC4
105 };
106
107 enum infineon_tpm_register {
108         WRFIFO = 0x00,
109         RDFIFO = 0x01,
110         STAT = 0x02,
111         CMD = 0x03
112 };
113
114 enum infineon_tpm_command_bits {
115         CMD_DIS = 0x00,
116         CMD_LP = 0x01,
117         CMD_RES = 0x02,
118         CMD_IRQC = 0x06
119 };
120
121 enum infineon_tpm_status_bits {
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 */
131 enum infineon_tpm_values {
132         CHIP_ID1 = 0x20,
133         CHIP_ID2 = 0x21,
134         TPM_DAR = 0x30,
135         RESET_LP_IRQC_DISABLE = 0x41,
136         ENABLE_REGISTER_PAIR = 0x55,
137         IOLIMH = 0x60,
138         IOLIML = 0x61,
139         DISABLE_REGISTER_PAIR = 0xAA,
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;
194                 msleep(TPM_MSLEEP_TIME);
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);
229         msleep(TPM_WTX_MSLEEP_TIME);
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;
240         msleep(TPM_WTX_MSLEEP_TIME);
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);
376 static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
377 static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
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_pnp_tbl[] = {
410         /* Infineon TPMs */
411         {"IFX0101", 0},
412         {"IFX0102", 0},
413         {"", 0}
414 };
415
416 MODULE_DEVICE_TABLE(pnp, tpm_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                 }
610                 tpm_remove_hardware(chip->dev);
611         }
612 }
613
614 static struct pnp_driver tpm_inf_pnp_driver = {
615         .name = "tpm_inf_pnp",
616         .driver = {
617                 .owner = THIS_MODULE,
618                 .suspend = tpm_pm_suspend,
619                 .resume = tpm_pm_resume,
620         },
621         .id_table = tpm_pnp_tbl,
622         .probe = tpm_inf_pnp_probe,
623         .remove = __devexit_p(tpm_inf_pnp_remove),
624 };
625
626 static int __init init_inf(void)
627 {
628         return pnp_register_driver(&tpm_inf_pnp_driver);
629 }
630
631 static void __exit cleanup_inf(void)
632 {
633         pnp_unregister_driver(&tpm_inf_pnp_driver);
634 }
635
636 module_init(init_inf);
637 module_exit(cleanup_inf);
638
639 MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
640 MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
641 MODULE_VERSION("1.9");
642 MODULE_LICENSE("GPL");