xref: /linux/drivers/char/tpm/tpm_infineon.c (revision 7aacf86b75bc5523d20fd9127104384fce51ce9c)
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 <tpmdd@selhorst.net>
8  * Sirrix AG - security technologies <tpmdd@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 
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 const struct tpm_class_ops tpm_inf = {
375 	.recv = tpm_inf_recv,
376 	.send = tpm_inf_send,
377 	.cancel = tpm_inf_cancel,
378 	.status = tpm_inf_status,
379 	.req_complete_mask = 0,
380 	.req_complete_val = 0,
381 };
382 
383 static const struct pnp_device_id tpm_inf_pnp_tbl[] = {
384 	/* Infineon TPMs */
385 	{"IFX0101", 0},
386 	{"IFX0102", 0},
387 	{"", 0}
388 };
389 
390 MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl);
391 
392 static int tpm_inf_pnp_probe(struct pnp_dev *dev,
393 				       const struct pnp_device_id *dev_id)
394 {
395 	int rc = 0;
396 	u8 iol, ioh;
397 	int vendorid[2];
398 	int version[2];
399 	int productid[2];
400 	const char *chipname;
401 	struct tpm_chip *chip;
402 
403 	/* read IO-ports through PnP */
404 	if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
405 	    !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
406 
407 		tpm_dev.iotype = TPM_INF_IO_PORT;
408 
409 		tpm_dev.config_port = pnp_port_start(dev, 0);
410 		tpm_dev.config_size = pnp_port_len(dev, 0);
411 		tpm_dev.data_regs = pnp_port_start(dev, 1);
412 		tpm_dev.data_size = pnp_port_len(dev, 1);
413 		if ((tpm_dev.data_size < 4) || (tpm_dev.config_size < 2)) {
414 			rc = -EINVAL;
415 			goto err_last;
416 		}
417 		dev_info(&dev->dev, "Found %s with ID %s\n",
418 			 dev->name, dev_id->id);
419 		if (!((tpm_dev.data_regs >> 8) & 0xff)) {
420 			rc = -EINVAL;
421 			goto err_last;
422 		}
423 		/* publish my base address and request region */
424 		if (request_region(tpm_dev.data_regs, tpm_dev.data_size,
425 				   "tpm_infineon0") == NULL) {
426 			rc = -EINVAL;
427 			goto err_last;
428 		}
429 		if (request_region(tpm_dev.config_port, tpm_dev.config_size,
430 				   "tpm_infineon0") == NULL) {
431 			release_region(tpm_dev.data_regs, tpm_dev.data_size);
432 			rc = -EINVAL;
433 			goto err_last;
434 		}
435 	} else if (pnp_mem_valid(dev, 0) &&
436 		   !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) {
437 
438 		tpm_dev.iotype = TPM_INF_IO_MEM;
439 
440 		tpm_dev.map_base = pnp_mem_start(dev, 0);
441 		tpm_dev.map_size = pnp_mem_len(dev, 0);
442 
443 		dev_info(&dev->dev, "Found %s with ID %s\n",
444 			 dev->name, dev_id->id);
445 
446 		/* publish my base address and request region */
447 		if (request_mem_region(tpm_dev.map_base, tpm_dev.map_size,
448 				       "tpm_infineon0") == NULL) {
449 			rc = -EINVAL;
450 			goto err_last;
451 		}
452 
453 		tpm_dev.mem_base = ioremap(tpm_dev.map_base, tpm_dev.map_size);
454 		if (tpm_dev.mem_base == NULL) {
455 			release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
456 			rc = -EINVAL;
457 			goto err_last;
458 		}
459 
460 		/*
461 		 * The only known MMIO based Infineon TPM system provides
462 		 * a single large mem region with the device config
463 		 * registers at the default TPM_ADDR.  The data registers
464 		 * seem like they could be placed anywhere within the MMIO
465 		 * region, but lets just put them at zero offset.
466 		 */
467 		tpm_dev.index_off = TPM_ADDR;
468 		tpm_dev.data_regs = 0x0;
469 	} else {
470 		rc = -EINVAL;
471 		goto err_last;
472 	}
473 
474 	/* query chip for its vendor, its version number a.s.o. */
475 	tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
476 	tpm_config_out(IDVENL, TPM_INF_ADDR);
477 	vendorid[1] = tpm_config_in(TPM_INF_DATA);
478 	tpm_config_out(IDVENH, TPM_INF_ADDR);
479 	vendorid[0] = tpm_config_in(TPM_INF_DATA);
480 	tpm_config_out(IDPDL, TPM_INF_ADDR);
481 	productid[1] = tpm_config_in(TPM_INF_DATA);
482 	tpm_config_out(IDPDH, TPM_INF_ADDR);
483 	productid[0] = tpm_config_in(TPM_INF_DATA);
484 	tpm_config_out(CHIP_ID1, TPM_INF_ADDR);
485 	version[1] = tpm_config_in(TPM_INF_DATA);
486 	tpm_config_out(CHIP_ID2, TPM_INF_ADDR);
487 	version[0] = tpm_config_in(TPM_INF_DATA);
488 
489 	switch ((productid[0] << 8) | productid[1]) {
490 	case 6:
491 		chipname = " (SLD 9630 TT 1.1)";
492 		break;
493 	case 11:
494 		chipname = " (SLB 9635 TT 1.2)";
495 		break;
496 	default:
497 		chipname = " (unknown chip)";
498 		break;
499 	}
500 
501 	if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
502 
503 		/* configure TPM with IO-ports */
504 		tpm_config_out(IOLIMH, TPM_INF_ADDR);
505 		tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
506 		tpm_config_out(IOLIML, TPM_INF_ADDR);
507 		tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
508 
509 		/* control if IO-ports are set correctly */
510 		tpm_config_out(IOLIMH, TPM_INF_ADDR);
511 		ioh = tpm_config_in(TPM_INF_DATA);
512 		tpm_config_out(IOLIML, TPM_INF_ADDR);
513 		iol = tpm_config_in(TPM_INF_DATA);
514 
515 		if ((ioh << 8 | iol) != tpm_dev.data_regs) {
516 			dev_err(&dev->dev,
517 				"Could not set IO-data registers to 0x%x\n",
518 				tpm_dev.data_regs);
519 			rc = -EIO;
520 			goto err_release_region;
521 		}
522 
523 		/* activate register */
524 		tpm_config_out(TPM_DAR, TPM_INF_ADDR);
525 		tpm_config_out(0x01, TPM_INF_DATA);
526 		tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
527 
528 		/* disable RESET, LP and IRQC */
529 		tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
530 
531 		/* Finally, we're done, print some infos */
532 		dev_info(&dev->dev, "TPM found: "
533 			 "config base 0x%lx, "
534 			 "data base 0x%lx, "
535 			 "chip version 0x%02x%02x, "
536 			 "vendor id 0x%x%x (Infineon), "
537 			 "product id 0x%02x%02x"
538 			 "%s\n",
539 			 tpm_dev.iotype == TPM_INF_IO_PORT ?
540 			 tpm_dev.config_port :
541 			 tpm_dev.map_base + tpm_dev.index_off,
542 			 tpm_dev.iotype == TPM_INF_IO_PORT ?
543 			 tpm_dev.data_regs :
544 			 tpm_dev.map_base + tpm_dev.data_regs,
545 			 version[0], version[1],
546 			 vendorid[0], vendorid[1],
547 			 productid[0], productid[1], chipname);
548 
549 		chip = tpmm_chip_alloc(&dev->dev, &tpm_inf);
550 		if (IS_ERR(chip)) {
551 			rc = PTR_ERR(chip);
552 			goto err_release_region;
553 		}
554 
555 		rc = tpm_chip_register(chip);
556 		if (rc)
557 			goto err_release_region;
558 
559 		return 0;
560 	} else {
561 		rc = -ENODEV;
562 		goto err_release_region;
563 	}
564 
565 err_release_region:
566 	if (tpm_dev.iotype == TPM_INF_IO_PORT) {
567 		release_region(tpm_dev.data_regs, tpm_dev.data_size);
568 		release_region(tpm_dev.config_port, tpm_dev.config_size);
569 	} else {
570 		iounmap(tpm_dev.mem_base);
571 		release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
572 	}
573 
574 err_last:
575 	return rc;
576 }
577 
578 static void tpm_inf_pnp_remove(struct pnp_dev *dev)
579 {
580 	struct tpm_chip *chip = pnp_get_drvdata(dev);
581 
582 	tpm_chip_unregister(chip);
583 
584 	if (tpm_dev.iotype == TPM_INF_IO_PORT) {
585 		release_region(tpm_dev.data_regs, tpm_dev.data_size);
586 		release_region(tpm_dev.config_port,
587 			       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 
594 #ifdef CONFIG_PM_SLEEP
595 static int tpm_inf_resume(struct device *dev)
596 {
597 	/* Re-configure TPM after suspending */
598 	tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
599 	tpm_config_out(IOLIMH, TPM_INF_ADDR);
600 	tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
601 	tpm_config_out(IOLIML, TPM_INF_ADDR);
602 	tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
603 	/* activate register */
604 	tpm_config_out(TPM_DAR, TPM_INF_ADDR);
605 	tpm_config_out(0x01, TPM_INF_DATA);
606 	tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
607 	/* disable RESET, LP and IRQC */
608 	tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
609 	return tpm_pm_resume(dev);
610 }
611 #endif
612 static SIMPLE_DEV_PM_OPS(tpm_inf_pm, tpm_pm_suspend, tpm_inf_resume);
613 
614 static struct pnp_driver tpm_inf_pnp_driver = {
615 	.name = "tpm_inf_pnp",
616 	.id_table = tpm_inf_pnp_tbl,
617 	.probe = tpm_inf_pnp_probe,
618 	.remove = tpm_inf_pnp_remove,
619 	.driver = {
620 		.pm = &tpm_inf_pm,
621 	}
622 };
623 
624 module_pnp_driver(tpm_inf_pnp_driver);
625 
626 MODULE_AUTHOR("Marcel Selhorst <tpmdd@sirrix.com>");
627 MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
628 MODULE_VERSION("1.9.2");
629 MODULE_LICENSE("GPL");
630