xref: /linux/drivers/char/tpm/tpm_infineon.c (revision 44f57d78)
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");
626