diff options
-rw-r--r-- | drivers/char/tpm/tpm_infineon.c | 157 |
1 files changed, 59 insertions, 98 deletions
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 5c3aeaffaf88..d356f53c49b4 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * Specifications at www.trustedcomputinggroup.org | 5 | * Specifications at www.trustedcomputinggroup.org |
6 | * | 6 | * |
7 | * Copyright (C) 2005, Marcel Selhorst <selhorst@crypto.rub.de> | 7 | * Copyright (C) 2005, Marcel Selhorst <selhorst@crypto.rub.de> |
8 | * Sirrix AG - security technologies, http://www.sirrix.com and | ||
8 | * Applied Data Security Group, Ruhr-University Bochum, Germany | 9 | * Applied Data Security Group, Ruhr-University Bochum, Germany |
9 | * Project-Homepage: http://www.prosec.rub.de/tpm | 10 | * Project-Homepage: http://www.prosec.rub.de/tpm |
10 | * | 11 | * |
@@ -31,7 +32,8 @@ | |||
31 | /* These values will be filled after PnP-call */ | 32 | /* These values will be filled after PnP-call */ |
32 | static int TPM_INF_DATA = 0; | 33 | static int TPM_INF_DATA = 0; |
33 | static int TPM_INF_ADDR = 0; | 34 | static int TPM_INF_ADDR = 0; |
34 | static int pnp_registered = 0; | 35 | static int TPM_INF_BASE = 0; |
36 | static int TPM_INF_PORT_LEN = 0; | ||
35 | 37 | ||
36 | /* TPM header definitions */ | 38 | /* TPM header definitions */ |
37 | enum infineon_tpm_header { | 39 | enum infineon_tpm_header { |
@@ -143,11 +145,9 @@ static int wait(struct tpm_chip *chip, int wait_for_bit) | |||
143 | } | 145 | } |
144 | if (i == TPM_MAX_TRIES) { /* timeout occurs */ | 146 | if (i == TPM_MAX_TRIES) { /* timeout occurs */ |
145 | if (wait_for_bit == STAT_XFE) | 147 | if (wait_for_bit == STAT_XFE) |
146 | dev_err(chip->dev, | 148 | dev_err(chip->dev, "Timeout in wait(STAT_XFE)\n"); |
147 | "Timeout in wait(STAT_XFE)\n"); | ||
148 | if (wait_for_bit == STAT_RDA) | 149 | if (wait_for_bit == STAT_RDA) |
149 | dev_err(chip->dev, | 150 | dev_err(chip->dev, "Timeout in wait(STAT_RDA)\n"); |
150 | "Timeout in wait(STAT_RDA)\n"); | ||
151 | return -EIO; | 151 | return -EIO; |
152 | } | 152 | } |
153 | return 0; | 153 | return 0; |
@@ -221,8 +221,7 @@ recv_begin: | |||
221 | } | 221 | } |
222 | 222 | ||
223 | if ((size == 0x6D00) && (buf[1] == 0x80)) { | 223 | if ((size == 0x6D00) && (buf[1] == 0x80)) { |
224 | dev_err(chip->dev, | 224 | dev_err(chip->dev, "Error handling on vendor layer!\n"); |
225 | "Error handling on vendor layer!\n"); | ||
226 | return -EIO; | 225 | return -EIO; |
227 | } | 226 | } |
228 | 227 | ||
@@ -318,7 +317,7 @@ static void tpm_inf_cancel(struct tpm_chip *chip) | |||
318 | 317 | ||
319 | static u8 tpm_inf_status(struct tpm_chip *chip) | 318 | static u8 tpm_inf_status(struct tpm_chip *chip) |
320 | { | 319 | { |
321 | return inb(chip->vendor->base + 1); | 320 | return inb(chip->vendor->base + STAT); |
322 | } | 321 | } |
323 | 322 | ||
324 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); | 323 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); |
@@ -362,30 +361,11 @@ static const struct pnp_device_id tpm_pnp_tbl[] = { | |||
362 | {"IFX0102", 0}, | 361 | {"IFX0102", 0}, |
363 | {"", 0} | 362 | {"", 0} |
364 | }; | 363 | }; |
364 | |||
365 | MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl); | 365 | MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl); |
366 | 366 | ||
367 | static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | 367 | static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, |
368 | const struct pnp_device_id *dev_id) | 368 | const struct pnp_device_id *dev_id) |
369 | { | ||
370 | if (pnp_port_valid(dev, 0)) { | ||
371 | TPM_INF_ADDR = (pnp_port_start(dev, 0) & 0xff); | ||
372 | TPM_INF_DATA = ((TPM_INF_ADDR + 1) & 0xff); | ||
373 | tpm_inf.base = pnp_port_start(dev, 1); | ||
374 | dev_info(&dev->dev, "Found %s with ID %s\n", | ||
375 | dev->name, dev_id->id); | ||
376 | return 0; | ||
377 | } | ||
378 | return -ENODEV; | ||
379 | } | ||
380 | |||
381 | static struct pnp_driver tpm_inf_pnp = { | ||
382 | .name = "tpm_inf_pnp", | ||
383 | .id_table = tpm_pnp_tbl, | ||
384 | .probe = tpm_inf_pnp_probe, | ||
385 | }; | ||
386 | |||
387 | static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, | ||
388 | const struct pci_device_id *pci_id) | ||
389 | { | 369 | { |
390 | int rc = 0; | 370 | int rc = 0; |
391 | u8 iol, ioh; | 371 | u8 iol, ioh; |
@@ -394,30 +374,28 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, | |||
394 | int productid[2]; | 374 | int productid[2]; |
395 | char chipname[20]; | 375 | char chipname[20]; |
396 | 376 | ||
397 | rc = pci_enable_device(pci_dev); | 377 | /* read IO-ports through PnP */ |
398 | if (rc) | 378 | if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && |
399 | return rc; | 379 | !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) { |
400 | 380 | TPM_INF_ADDR = pnp_port_start(dev, 0); | |
401 | dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device); | 381 | TPM_INF_DATA = (TPM_INF_ADDR + 1); |
402 | 382 | TPM_INF_BASE = pnp_port_start(dev, 1); | |
403 | /* read IO-ports from PnP */ | 383 | TPM_INF_PORT_LEN = pnp_port_len(dev, 1); |
404 | rc = pnp_register_driver(&tpm_inf_pnp); | 384 | if (!TPM_INF_PORT_LEN) |
405 | if (rc < 0) { | 385 | return -EINVAL; |
406 | dev_err(&pci_dev->dev, | 386 | dev_info(&dev->dev, "Found %s with ID %s\n", |
407 | "Error %x from pnp_register_driver!\n",rc); | 387 | dev->name, dev_id->id); |
408 | goto error2; | 388 | if (!((TPM_INF_BASE >> 8) & 0xff)) |
409 | } | 389 | return -EINVAL; |
410 | if (!rc) { | 390 | /* publish my base address and request region */ |
411 | dev_info(&pci_dev->dev, "No Infineon TPM found!\n"); | 391 | tpm_inf.base = TPM_INF_BASE; |
412 | goto error; | 392 | if (request_region |
393 | (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { | ||
394 | release_region(tpm_inf.base, TPM_INF_PORT_LEN); | ||
395 | return -EINVAL; | ||
396 | } | ||
413 | } else { | 397 | } else { |
414 | pnp_registered = 1; | 398 | return -EINVAL; |
415 | } | ||
416 | |||
417 | /* Make sure, we have received valid config ports */ | ||
418 | if (!TPM_INF_ADDR) { | ||
419 | dev_err(&pci_dev->dev, "No valid IO-ports received!\n"); | ||
420 | goto error; | ||
421 | } | 399 | } |
422 | 400 | ||
423 | /* query chip for its vendor, its version number a.s.o. */ | 401 | /* query chip for its vendor, its version number a.s.o. */ |
@@ -449,10 +427,6 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, | |||
449 | 427 | ||
450 | if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) { | 428 | if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) { |
451 | 429 | ||
452 | if (tpm_inf.base == 0) { | ||
453 | dev_err(&pci_dev->dev, "No IO-ports found!\n"); | ||
454 | goto error; | ||
455 | } | ||
456 | /* configure TPM with IO-ports */ | 430 | /* configure TPM with IO-ports */ |
457 | outb(IOLIMH, TPM_INF_ADDR); | 431 | outb(IOLIMH, TPM_INF_ADDR); |
458 | outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA); | 432 | outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA); |
@@ -466,10 +440,11 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, | |||
466 | iol = inb(TPM_INF_DATA); | 440 | iol = inb(TPM_INF_DATA); |
467 | 441 | ||
468 | if ((ioh << 8 | iol) != tpm_inf.base) { | 442 | if ((ioh << 8 | iol) != tpm_inf.base) { |
469 | dev_err(&pci_dev->dev, | 443 | dev_err(&dev->dev, |
470 | "Could not set IO-ports to %04x\n", | 444 | "Could not set IO-ports to %04x\n", |
471 | tpm_inf.base); | 445 | tpm_inf.base); |
472 | goto error; | 446 | release_region(tpm_inf.base, TPM_INF_PORT_LEN); |
447 | return -EIO; | ||
473 | } | 448 | } |
474 | 449 | ||
475 | /* activate register */ | 450 | /* activate register */ |
@@ -481,7 +456,7 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, | |||
481 | outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD); | 456 | outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD); |
482 | 457 | ||
483 | /* Finally, we're done, print some infos */ | 458 | /* Finally, we're done, print some infos */ |
484 | dev_info(&pci_dev->dev, "TPM found: " | 459 | dev_info(&dev->dev, "TPM found: " |
485 | "config base 0x%x, " | 460 | "config base 0x%x, " |
486 | "io base 0x%x, " | 461 | "io base 0x%x, " |
487 | "chip version %02x%02x, " | 462 | "chip version %02x%02x, " |
@@ -489,67 +464,53 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, | |||
489 | "product id %02x%02x" | 464 | "product id %02x%02x" |
490 | "%s\n", | 465 | "%s\n", |
491 | TPM_INF_ADDR, | 466 | TPM_INF_ADDR, |
492 | tpm_inf.base, | 467 | TPM_INF_BASE, |
493 | version[0], version[1], | 468 | version[0], version[1], |
494 | vendorid[0], vendorid[1], | 469 | vendorid[0], vendorid[1], |
495 | productid[0], productid[1], chipname); | 470 | productid[0], productid[1], chipname); |
496 | 471 | ||
497 | rc = tpm_register_hardware(&pci_dev->dev, &tpm_inf); | 472 | rc = tpm_register_hardware(&dev->dev, &tpm_inf); |
498 | if (rc < 0) | 473 | if (rc < 0) { |
499 | goto error; | 474 | release_region(tpm_inf.base, TPM_INF_PORT_LEN); |
475 | return -ENODEV; | ||
476 | } | ||
500 | return 0; | 477 | return 0; |
501 | } else { | 478 | } else { |
502 | dev_info(&pci_dev->dev, "No Infineon TPM found!\n"); | 479 | dev_info(&dev->dev, "No Infineon TPM found!\n"); |
503 | error: | ||
504 | pnp_unregister_driver(&tpm_inf_pnp); | ||
505 | error2: | ||
506 | pci_disable_device(pci_dev); | ||
507 | pnp_registered = 0; | ||
508 | return -ENODEV; | 480 | return -ENODEV; |
509 | } | 481 | } |
510 | } | 482 | } |
511 | 483 | ||
512 | static __devexit void tpm_inf_remove(struct pci_dev* pci_dev) | 484 | static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev) |
513 | { | 485 | { |
514 | struct tpm_chip* chip = pci_get_drvdata(pci_dev); | 486 | struct tpm_chip *chip = pnp_get_drvdata(dev); |
515 | 487 | ||
516 | if( chip ) | 488 | if (chip) { |
489 | release_region(chip->vendor->base, TPM_INF_PORT_LEN); | ||
517 | tpm_remove_hardware(chip->dev); | 490 | tpm_remove_hardware(chip->dev); |
491 | } | ||
518 | } | 492 | } |
519 | 493 | ||
520 | static struct pci_device_id tpm_pci_tbl[] __devinitdata = { | 494 | static struct pnp_driver tpm_inf_pnp = { |
521 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)}, | 495 | .name = "tpm_inf_pnp", |
522 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)}, | 496 | .driver = { |
523 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)}, | 497 | .owner = THIS_MODULE, |
524 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)}, | 498 | .suspend = tpm_pm_suspend, |
525 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)}, | 499 | .resume = tpm_pm_resume, |
526 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)}, | 500 | }, |
527 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)}, | 501 | .id_table = tpm_pnp_tbl, |
528 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2)}, | 502 | .probe = tpm_inf_pnp_probe, |
529 | {0,} | 503 | .remove = tpm_inf_pnp_remove, |
530 | }; | ||
531 | |||
532 | MODULE_DEVICE_TABLE(pci, tpm_pci_tbl); | ||
533 | |||
534 | static struct pci_driver inf_pci_driver = { | ||
535 | .name = "tpm_inf", | ||
536 | .id_table = tpm_pci_tbl, | ||
537 | .probe = tpm_inf_probe, | ||
538 | .remove = __devexit_p(tpm_inf_remove), | ||
539 | .suspend = tpm_pm_suspend, | ||
540 | .resume = tpm_pm_resume, | ||
541 | }; | 504 | }; |
542 | 505 | ||
543 | static int __init init_inf(void) | 506 | static int __init init_inf(void) |
544 | { | 507 | { |
545 | return pci_register_driver(&inf_pci_driver); | 508 | return pnp_register_driver(&tpm_inf_pnp); |
546 | } | 509 | } |
547 | 510 | ||
548 | static void __exit cleanup_inf(void) | 511 | static void __exit cleanup_inf(void) |
549 | { | 512 | { |
550 | if (pnp_registered) | 513 | pnp_unregister_driver(&tpm_inf_pnp); |
551 | pnp_unregister_driver(&tpm_inf_pnp); | ||
552 | pci_unregister_driver(&inf_pci_driver); | ||
553 | } | 514 | } |
554 | 515 | ||
555 | module_init(init_inf); | 516 | module_init(init_inf); |
@@ -557,5 +518,5 @@ module_exit(cleanup_inf); | |||
557 | 518 | ||
558 | MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); | 519 | MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); |
559 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); | 520 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); |
560 | MODULE_VERSION("1.5"); | 521 | MODULE_VERSION("1.6"); |
561 | MODULE_LICENSE("GPL"); | 522 | MODULE_LICENSE("GPL"); |