PM / sleep: Asynchronous threads for suspend_noirq
[linux/fpc-iii.git] / drivers / char / tpm / tpm_infineon.c
blobdc0a2554034ea2fe1fc51a769d24c0d05805950a
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
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/
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.
18 #include <linux/init.h>
19 #include <linux/pnp.h>
20 #include "tpm.h"
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
33 #define TPM_INF_IO_PORT 0x0
34 #define TPM_INF_IO_MEM 0x1
36 #define TPM_INF_ADDR 0x0
37 #define TPM_INF_DATA 0x1
39 struct tpm_inf_dev {
40 int iotype;
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 */
47 unsigned int data_regs; /* Data registers */
48 unsigned int data_size;
50 unsigned int config_port; /* IO Port config index reg */
51 unsigned int config_size;
54 static struct tpm_inf_dev tpm_dev;
56 static inline void tpm_data_out(unsigned char data, unsigned char offset)
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);
64 static inline unsigned char tpm_data_in(unsigned char offset)
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);
72 static inline void tpm_config_out(unsigned char data, unsigned char offset)
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);
80 static inline unsigned char tpm_config_in(unsigned char offset)
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);
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
107 enum infineon_tpm_register {
108 WRFIFO = 0x00,
109 RDFIFO = 0x01,
110 STAT = 0x02,
111 CMD = 0x03
114 enum infineon_tpm_command_bits {
115 CMD_DIS = 0x00,
116 CMD_LP = 0x01,
117 CMD_RES = 0x02,
118 CMD_IRQC = 0x06
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
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
146 static int number_of_wtx;
148 static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
150 int status;
151 int check = 0;
152 int i;
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++;
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.
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;
185 static int wait(struct tpm_chip *chip, int wait_for_bit)
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);
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;
203 return 0;
206 static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
208 wait(chip, STAT_XFE);
209 tpm_data_out(sendbyte, WRFIFO);
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.
220 static void tpm_wtx(struct tpm_chip *chip)
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);
232 static void tpm_wtx_abort(struct tpm_chip *chip)
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);
243 static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
245 int i;
246 int ret;
247 u32 size = 0;
248 number_of_wtx = 0;
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);
259 if (buf[0] != TPM_VL_VER) {
260 dev_err(chip->dev,
261 "Wrong transport protocol implementation!\n");
262 return -EIO;
265 if (buf[1] == TPM_CTRL_DATA) {
266 /* size of the data received */
267 size = ((buf[2] << 8) | buf[3]);
269 for (i = 0; i < size; i++) {
270 wait(chip, STAT_RDA);
271 buf[i] = tpm_data_in(RDFIFO);
274 if ((size == 0x6D00) && (buf[1] == 0x80)) {
275 dev_err(chip->dev, "Error handling on vendor layer!\n");
276 return -EIO;
279 for (i = 0; i < size; i++)
280 buf[i] = buf[i + 6];
282 size = size - 6;
283 return size;
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;
297 if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) {
298 dev_info(chip->dev, "WTX-abort acknowledged\n");
299 return size;
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;
310 return -EIO;
313 static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
315 int i;
316 int ret;
317 u8 count_high, count_low, count_4, count_3, count_2, count_1;
319 /* Disabling Reset, LP and IRQC */
320 tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
322 ret = empty_fifo(chip, 1);
323 if (ret) {
324 dev_err(chip->dev, "Timeout while clearing FIFO\n");
325 return -EIO;
328 ret = wait(chip, STAT_XFE);
329 if (ret)
330 return -EIO;
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);
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);
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);
353 /* Sending Data */
354 for (i = 0; i < count; i++) {
355 wait_and_send(chip, buf[i]);
357 return count;
360 static void tpm_inf_cancel(struct tpm_chip *chip)
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.
369 static u8 tpm_inf_status(struct tpm_chip *chip)
371 return tpm_data_in(STAT);
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,
383 static const struct pnp_device_id tpm_inf_pnp_tbl[] = {
384 /* Infineon TPMs */
385 {"IFX0101", 0},
386 {"IFX0102", 0},
387 {"", 0}
390 MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl);
392 static int tpm_inf_pnp_probe(struct pnp_dev *dev,
393 const struct pnp_device_id *dev_id)
395 int rc = 0;
396 u8 iol, ioh;
397 int vendorid[2];
398 int version[2];
399 int productid[2];
400 char chipname[20];
401 struct tpm_chip *chip;
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)) {
407 tpm_dev.iotype = TPM_INF_IO_PORT;
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;
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;
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;
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;
435 } else if (pnp_mem_valid(dev, 0) &&
436 !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) {
438 tpm_dev.iotype = TPM_INF_IO_MEM;
440 tpm_dev.map_base = pnp_mem_start(dev, 0);
441 tpm_dev.map_size = pnp_mem_len(dev, 0);
443 dev_info(&dev->dev, "Found %s with ID %s\n",
444 dev->name, dev_id->id);
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;
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;
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.
467 tpm_dev.index_off = TPM_ADDR;
468 tpm_dev.data_regs = 0x0;
469 } else {
470 rc = -EINVAL;
471 goto err_last;
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);
489 switch ((productid[0] << 8) | productid[1]) {
490 case 6:
491 snprintf(chipname, sizeof(chipname), " (SLD 9630 TT 1.1)");
492 break;
493 case 11:
494 snprintf(chipname, sizeof(chipname), " (SLB 9635 TT 1.2)");
495 break;
496 default:
497 snprintf(chipname, sizeof(chipname), " (unknown chip)");
498 break;
501 if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
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);
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);
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;
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);
528 /* disable RESET, LP and IRQC */
529 tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
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);
549 if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf)))
550 goto err_release_region;
552 return 0;
553 } else {
554 rc = -ENODEV;
555 goto err_release_region;
558 err_release_region:
559 if (tpm_dev.iotype == TPM_INF_IO_PORT) {
560 release_region(tpm_dev.data_regs, tpm_dev.data_size);
561 release_region(tpm_dev.config_port, tpm_dev.config_size);
562 } else {
563 iounmap(tpm_dev.mem_base);
564 release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
567 err_last:
568 return rc;
571 static void tpm_inf_pnp_remove(struct pnp_dev *dev)
573 struct tpm_chip *chip = pnp_get_drvdata(dev);
575 if (chip) {
576 if (tpm_dev.iotype == TPM_INF_IO_PORT) {
577 release_region(tpm_dev.data_regs, tpm_dev.data_size);
578 release_region(tpm_dev.config_port,
579 tpm_dev.config_size);
580 } else {
581 iounmap(tpm_dev.mem_base);
582 release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
584 tpm_dev_vendor_release(chip);
585 tpm_remove_hardware(chip->dev);
589 static int tpm_inf_pnp_suspend(struct pnp_dev *dev, pm_message_t pm_state)
591 struct tpm_chip *chip = pnp_get_drvdata(dev);
592 int rc;
593 if (chip) {
594 u8 savestate[] = {
595 0, 193, /* TPM_TAG_RQU_COMMAND */
596 0, 0, 0, 10, /* blob length (in bytes) */
597 0, 0, 0, 152 /* TPM_ORD_SaveState */
599 dev_info(&dev->dev, "saving TPM state\n");
600 rc = tpm_inf_send(chip, savestate, sizeof(savestate));
601 if (rc < 0) {
602 dev_err(&dev->dev, "error while saving TPM state\n");
603 return rc;
606 return 0;
609 static int tpm_inf_pnp_resume(struct pnp_dev *dev)
611 /* Re-configure TPM after suspending */
612 tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
613 tpm_config_out(IOLIMH, TPM_INF_ADDR);
614 tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
615 tpm_config_out(IOLIML, TPM_INF_ADDR);
616 tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
617 /* activate register */
618 tpm_config_out(TPM_DAR, TPM_INF_ADDR);
619 tpm_config_out(0x01, TPM_INF_DATA);
620 tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
621 /* disable RESET, LP and IRQC */
622 tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
623 return tpm_pm_resume(&dev->dev);
626 static struct pnp_driver tpm_inf_pnp_driver = {
627 .name = "tpm_inf_pnp",
628 .id_table = tpm_inf_pnp_tbl,
629 .probe = tpm_inf_pnp_probe,
630 .suspend = tpm_inf_pnp_suspend,
631 .resume = tpm_inf_pnp_resume,
632 .remove = tpm_inf_pnp_remove
635 static int __init init_inf(void)
637 return pnp_register_driver(&tpm_inf_pnp_driver);
640 static void __exit cleanup_inf(void)
642 pnp_unregister_driver(&tpm_inf_pnp_driver);
645 module_init(init_inf);
646 module_exit(cleanup_inf);
648 MODULE_AUTHOR("Marcel Selhorst <tpmdd@sirrix.com>");
649 MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
650 MODULE_VERSION("1.9.2");
651 MODULE_LICENSE("GPL");