Loading...
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");
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 <m.selhorst@sirrix.com>
8 * Sirrix AG - security technologies, http://www.sirrix.com 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
39struct 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
54static struct tpm_inf_dev tpm_dev;
55
56static 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
64static 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
72static 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
80static 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 */
89enum 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
107enum infineon_tpm_register {
108 WRFIFO = 0x00,
109 RDFIFO = 0x01,
110 STAT = 0x02,
111 CMD = 0x03
112};
113
114enum infineon_tpm_command_bits {
115 CMD_DIS = 0x00,
116 CMD_LP = 0x01,
117 CMD_RES = 0x02,
118 CMD_IRQC = 0x06
119};
120
121enum 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 */
131enum 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
146static int number_of_wtx;
147
148static 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
185static 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
206static 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
220static 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
232static 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
243static 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
250recv_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
313static 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
360static 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
369static u8 tpm_inf_status(struct tpm_chip *chip)
370{
371 return tpm_data_in(STAT);
372}
373
374static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
375static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
376static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
377static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
378
379static 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
387static struct attribute_group inf_attr_grp = {.attrs = inf_attrs };
388
389static 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
398static 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
409static const struct pnp_device_id tpm_inf_pnp_tbl[] = {
410 /* Infineon TPMs */
411 {"IFX0101", 0},
412 {"IFX0102", 0},
413 {"", 0}
414};
415
416MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl);
417
418static 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
584err_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
593err_last:
594 return rc;
595}
596
597static __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_dev_vendor_release(chip);
611 tpm_remove_hardware(chip->dev);
612 }
613}
614
615static 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
635static 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
652static 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
661static int __init init_inf(void)
662{
663 return pnp_register_driver(&tpm_inf_pnp_driver);
664}
665
666static void __exit cleanup_inf(void)
667{
668 pnp_unregister_driver(&tpm_inf_pnp_driver);
669}
670
671module_init(init_inf);
672module_exit(cleanup_inf);
673
674MODULE_AUTHOR("Marcel Selhorst <m.selhorst@sirrix.com>");
675MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
676MODULE_VERSION("1.9.2");
677MODULE_LICENSE("GPL");