aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/tpm/tpm_infineon.c231
1 files changed, 165 insertions, 66 deletions
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 1353b5a6bae8..967002a5a1e5 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -30,12 +30,60 @@
30#define TPM_MAX_TRIES 5000 30#define TPM_MAX_TRIES 5000
31#define TPM_INFINEON_DEV_VEN_VALUE 0x15D1 31#define TPM_INFINEON_DEV_VEN_VALUE 0x15D1
32 32
33/* These values will be filled after PnP-call */ 33#define TPM_INF_IO_PORT 0x0
34static int TPM_INF_DATA; 34#define TPM_INF_IO_MEM 0x1
35static int TPM_INF_ADDR; 35
36static int TPM_INF_BASE; 36#define TPM_INF_ADDR 0x0
37static int TPM_INF_ADDR_LEN; 37#define TPM_INF_DATA 0x1
38static int TPM_INF_PORT_LEN; 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}
39 87
40/* TPM header definitions */ 88/* TPM header definitions */
41enum infineon_tpm_header { 89enum infineon_tpm_header {
@@ -105,7 +153,7 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
105 153
106 if (clear_wrfifo) { 154 if (clear_wrfifo) {
107 for (i = 0; i < 4096; i++) { 155 for (i = 0; i < 4096; i++) {
108 status = inb(chip->vendor.base + WRFIFO); 156 status = tpm_data_in(WRFIFO);
109 if (status == 0xff) { 157 if (status == 0xff) {
110 if (check == 5) 158 if (check == 5)
111 break; 159 break;
@@ -125,8 +173,8 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
125 */ 173 */
126 i = 0; 174 i = 0;
127 do { 175 do {
128 status = inb(chip->vendor.base + RDFIFO); 176 status = tpm_data_in(RDFIFO);
129 status = inb(chip->vendor.base + STAT); 177 status = tpm_data_in(STAT);
130 i++; 178 i++;
131 if (i == TPM_MAX_TRIES) 179 if (i == TPM_MAX_TRIES)
132 return -EIO; 180 return -EIO;
@@ -139,7 +187,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
139 int status; 187 int status;
140 int i; 188 int i;
141 for (i = 0; i < TPM_MAX_TRIES; i++) { 189 for (i = 0; i < TPM_MAX_TRIES; i++) {
142 status = inb(chip->vendor.base + STAT); 190 status = tpm_data_in(STAT);
143 /* check the status-register if wait_for_bit is set */ 191 /* check the status-register if wait_for_bit is set */
144 if (status & 1 << wait_for_bit) 192 if (status & 1 << wait_for_bit)
145 break; 193 break;
@@ -158,7 +206,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
158static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) 206static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
159{ 207{
160 wait(chip, STAT_XFE); 208 wait(chip, STAT_XFE);
161 outb(sendbyte, chip->vendor.base + WRFIFO); 209 tpm_data_out(sendbyte, WRFIFO);
162} 210}
163 211
164 /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more 212 /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
@@ -205,7 +253,7 @@ recv_begin:
205 ret = wait(chip, STAT_RDA); 253 ret = wait(chip, STAT_RDA);
206 if (ret) 254 if (ret)
207 return -EIO; 255 return -EIO;
208 buf[i] = inb(chip->vendor.base + RDFIFO); 256 buf[i] = tpm_data_in(RDFIFO);
209 } 257 }
210 258
211 if (buf[0] != TPM_VL_VER) { 259 if (buf[0] != TPM_VL_VER) {
@@ -220,7 +268,7 @@ recv_begin:
220 268
221 for (i = 0; i < size; i++) { 269 for (i = 0; i < size; i++) {
222 wait(chip, STAT_RDA); 270 wait(chip, STAT_RDA);
223 buf[i] = inb(chip->vendor.base + RDFIFO); 271 buf[i] = tpm_data_in(RDFIFO);
224 } 272 }
225 273
226 if ((size == 0x6D00) && (buf[1] == 0x80)) { 274 if ((size == 0x6D00) && (buf[1] == 0x80)) {
@@ -269,7 +317,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
269 u8 count_high, count_low, count_4, count_3, count_2, count_1; 317 u8 count_high, count_low, count_4, count_3, count_2, count_1;
270 318
271 /* Disabling Reset, LP and IRQC */ 319 /* Disabling Reset, LP and IRQC */
272 outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD); 320 tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
273 321
274 ret = empty_fifo(chip, 1); 322 ret = empty_fifo(chip, 1);
275 if (ret) { 323 if (ret) {
@@ -320,7 +368,7 @@ static void tpm_inf_cancel(struct tpm_chip *chip)
320 368
321static u8 tpm_inf_status(struct tpm_chip *chip) 369static u8 tpm_inf_status(struct tpm_chip *chip)
322{ 370{
323 return inb(chip->vendor.base + STAT); 371 return tpm_data_in(STAT);
324} 372}
325 373
326static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); 374static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
@@ -381,51 +429,88 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
381 /* read IO-ports through PnP */ 429 /* read IO-ports through PnP */
382 if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && 430 if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
383 !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) { 431 !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
384 TPM_INF_ADDR = pnp_port_start(dev, 0); 432
385 TPM_INF_ADDR_LEN = pnp_port_len(dev, 0); 433 tpm_dev.iotype = TPM_INF_IO_PORT;
386 TPM_INF_DATA = (TPM_INF_ADDR + 1); 434
387 TPM_INF_BASE = pnp_port_start(dev, 1); 435 tpm_dev.config_port = pnp_port_start(dev, 0);
388 TPM_INF_PORT_LEN = pnp_port_len(dev, 1); 436 tpm_dev.config_size = pnp_port_len(dev, 0);
389 if ((TPM_INF_PORT_LEN < 4) || (TPM_INF_ADDR_LEN < 2)) { 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)) {
390 rc = -EINVAL; 440 rc = -EINVAL;
391 goto err_last; 441 goto err_last;
392 } 442 }
393 dev_info(&dev->dev, "Found %s with ID %s\n", 443 dev_info(&dev->dev, "Found %s with ID %s\n",
394 dev->name, dev_id->id); 444 dev->name, dev_id->id);
395 if (!((TPM_INF_BASE >> 8) & 0xff)) { 445 if (!((tpm_dev.data_regs >> 8) & 0xff)) {
396 rc = -EINVAL; 446 rc = -EINVAL;
397 goto err_last; 447 goto err_last;
398 } 448 }
399 /* publish my base address and request region */ 449 /* publish my base address and request region */
400 if (request_region 450 if (request_region(tpm_dev.data_regs, tpm_dev.data_size,
401 (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { 451 "tpm_infineon0") == NULL) {
402 rc = -EINVAL; 452 rc = -EINVAL;
403 goto err_last; 453 goto err_last;
404 } 454 }
405 if (request_region 455 if (request_region(tpm_dev.config_port, tpm_dev.config_size,
406 (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) { 456 "tpm_infineon0") == NULL) {
457 release_region(tpm_dev.data_regs, tpm_dev.data_size);
407 rc = -EINVAL; 458 rc = -EINVAL;
408 goto err_last; 459 goto err_last;
409 } 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;
410 } else { 495 } else {
411 rc = -EINVAL; 496 rc = -EINVAL;
412 goto err_last; 497 goto err_last;
413 } 498 }
414 499
415 /* query chip for its vendor, its version number a.s.o. */ 500 /* query chip for its vendor, its version number a.s.o. */
416 outb(ENABLE_REGISTER_PAIR, TPM_INF_ADDR); 501 tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
417 outb(IDVENL, TPM_INF_ADDR); 502 tpm_config_out(IDVENL, TPM_INF_ADDR);
418 vendorid[1] = inb(TPM_INF_DATA); 503 vendorid[1] = tpm_config_in(TPM_INF_DATA);
419 outb(IDVENH, TPM_INF_ADDR); 504 tpm_config_out(IDVENH, TPM_INF_ADDR);
420 vendorid[0] = inb(TPM_INF_DATA); 505 vendorid[0] = tpm_config_in(TPM_INF_DATA);
421 outb(IDPDL, TPM_INF_ADDR); 506 tpm_config_out(IDPDL, TPM_INF_ADDR);
422 productid[1] = inb(TPM_INF_DATA); 507 productid[1] = tpm_config_in(TPM_INF_DATA);
423 outb(IDPDH, TPM_INF_ADDR); 508 tpm_config_out(IDPDH, TPM_INF_ADDR);
424 productid[0] = inb(TPM_INF_DATA); 509 productid[0] = tpm_config_in(TPM_INF_DATA);
425 outb(CHIP_ID1, TPM_INF_ADDR); 510 tpm_config_out(CHIP_ID1, TPM_INF_ADDR);
426 version[1] = inb(TPM_INF_DATA); 511 version[1] = tpm_config_in(TPM_INF_DATA);
427 outb(CHIP_ID2, TPM_INF_ADDR); 512 tpm_config_out(CHIP_ID2, TPM_INF_ADDR);
428 version[0] = inb(TPM_INF_DATA); 513 version[0] = tpm_config_in(TPM_INF_DATA);
429 514
430 switch ((productid[0] << 8) | productid[1]) { 515 switch ((productid[0] << 8) | productid[1]) {
431 case 6: 516 case 6:
@@ -442,51 +527,54 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
442 if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) { 527 if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
443 528
444 /* configure TPM with IO-ports */ 529 /* configure TPM with IO-ports */
445 outb(IOLIMH, TPM_INF_ADDR); 530 tpm_config_out(IOLIMH, TPM_INF_ADDR);
446 outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA); 531 tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
447 outb(IOLIML, TPM_INF_ADDR); 532 tpm_config_out(IOLIML, TPM_INF_ADDR);
448 outb((TPM_INF_BASE & 0xff), TPM_INF_DATA); 533 tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
449 534
450 /* control if IO-ports are set correctly */ 535 /* control if IO-ports are set correctly */
451 outb(IOLIMH, TPM_INF_ADDR); 536 tpm_config_out(IOLIMH, TPM_INF_ADDR);
452 ioh = inb(TPM_INF_DATA); 537 ioh = tpm_config_in(TPM_INF_DATA);
453 outb(IOLIML, TPM_INF_ADDR); 538 tpm_config_out(IOLIML, TPM_INF_ADDR);
454 iol = inb(TPM_INF_DATA); 539 iol = tpm_config_in(TPM_INF_DATA);
455 540
456 if ((ioh << 8 | iol) != TPM_INF_BASE) { 541 if ((ioh << 8 | iol) != tpm_dev.data_regs) {
457 dev_err(&dev->dev, 542 dev_err(&dev->dev,
458 "Could not set IO-ports to 0x%x\n", 543 "Could not set IO-data registers to 0x%x\n",
459 TPM_INF_BASE); 544 tpm_dev.data_regs);
460 rc = -EIO; 545 rc = -EIO;
461 goto err_release_region; 546 goto err_release_region;
462 } 547 }
463 548
464 /* activate register */ 549 /* activate register */
465 outb(TPM_DAR, TPM_INF_ADDR); 550 tpm_config_out(TPM_DAR, TPM_INF_ADDR);
466 outb(0x01, TPM_INF_DATA); 551 tpm_config_out(0x01, TPM_INF_DATA);
467 outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); 552 tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
468 553
469 /* disable RESET, LP and IRQC */ 554 /* disable RESET, LP and IRQC */
470 outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD); 555 tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
471 556
472 /* Finally, we're done, print some infos */ 557 /* Finally, we're done, print some infos */
473 dev_info(&dev->dev, "TPM found: " 558 dev_info(&dev->dev, "TPM found: "
474 "config base 0x%x, " 559 "config base 0x%lx, "
475 "io base 0x%x, " 560 "data base 0x%lx, "
476 "chip version 0x%02x%02x, " 561 "chip version 0x%02x%02x, "
477 "vendor id 0x%x%x (Infineon), " 562 "vendor id 0x%x%x (Infineon), "
478 "product id 0x%02x%02x" 563 "product id 0x%02x%02x"
479 "%s\n", 564 "%s\n",
480 TPM_INF_ADDR, 565 tpm_dev.iotype == TPM_INF_IO_PORT ?
481 TPM_INF_BASE, 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,
482 version[0], version[1], 571 version[0], version[1],
483 vendorid[0], vendorid[1], 572 vendorid[0], vendorid[1],
484 productid[0], productid[1], chipname); 573 productid[0], productid[1], chipname);
485 574
486 if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) { 575 if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf)))
487 goto err_release_region; 576 goto err_release_region;
488 } 577
489 chip->vendor.base = TPM_INF_BASE;
490 return 0; 578 return 0;
491 } else { 579 } else {
492 rc = -ENODEV; 580 rc = -ENODEV;
@@ -494,8 +582,13 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
494 } 582 }
495 583
496err_release_region: 584err_release_region:
497 release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); 585 if (tpm_dev.iotype == TPM_INF_IO_PORT) {
498 release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); 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 }
499 592
500err_last: 593err_last:
501 return rc; 594 return rc;
@@ -506,8 +599,14 @@ static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
506 struct tpm_chip *chip = pnp_get_drvdata(dev); 599 struct tpm_chip *chip = pnp_get_drvdata(dev);
507 600
508 if (chip) { 601 if (chip) {
509 release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); 602 if (tpm_dev.iotype == TPM_INF_IO_PORT) {
510 release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); 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 }
511 tpm_remove_hardware(chip->dev); 610 tpm_remove_hardware(chip->dev);
512 } 611 }
513} 612}
@@ -539,5 +638,5 @@ module_exit(cleanup_inf);
539 638
540MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); 639MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
541MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); 640MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
542MODULE_VERSION("1.8"); 641MODULE_VERSION("1.9");
543MODULE_LICENSE("GPL"); 642MODULE_LICENSE("GPL");