diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/tpm/tpm_tis.c | 112 |
1 files changed, 89 insertions, 23 deletions
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 239cf0bbc1a1..20a61bc98db8 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2005, 2006 IBM Corporation | 2 | * Copyright (C) 2005, 2006 IBM Corporation |
3 | * Copyright (C) 2014 Intel Corporation | ||
3 | * | 4 | * |
4 | * Authors: | 5 | * Authors: |
5 | * Leendert van Doorn <leendert@watson.ibm.com> | 6 | * Leendert van Doorn <leendert@watson.ibm.com> |
@@ -64,12 +65,22 @@ enum tis_defaults { | |||
64 | TIS_LONG_TIMEOUT = 2000, /* 2 sec */ | 65 | TIS_LONG_TIMEOUT = 2000, /* 2 sec */ |
65 | }; | 66 | }; |
66 | 67 | ||
68 | |||
69 | /* Some timeout values are needed before it is known whether the chip is | ||
70 | * TPM 1.0 or TPM 2.0. | ||
71 | */ | ||
72 | #define TIS_TIMEOUT_A_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_A) | ||
73 | #define TIS_TIMEOUT_B_MAX max(TIS_LONG_TIMEOUT, TPM2_TIMEOUT_B) | ||
74 | #define TIS_TIMEOUT_C_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_C) | ||
75 | #define TIS_TIMEOUT_D_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_D) | ||
76 | |||
67 | #define TPM_ACCESS(l) (0x0000 | ((l) << 12)) | 77 | #define TPM_ACCESS(l) (0x0000 | ((l) << 12)) |
68 | #define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) | 78 | #define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) |
69 | #define TPM_INT_VECTOR(l) (0x000C | ((l) << 12)) | 79 | #define TPM_INT_VECTOR(l) (0x000C | ((l) << 12)) |
70 | #define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) | 80 | #define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) |
71 | #define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) | 81 | #define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) |
72 | #define TPM_STS(l) (0x0018 | ((l) << 12)) | 82 | #define TPM_STS(l) (0x0018 | ((l) << 12)) |
83 | #define TPM_STS3(l) (0x001b | ((l) << 12)) | ||
73 | #define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) | 84 | #define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) |
74 | 85 | ||
75 | #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) | 86 | #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) |
@@ -363,6 +374,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) | |||
363 | { | 374 | { |
364 | int rc; | 375 | int rc; |
365 | u32 ordinal; | 376 | u32 ordinal; |
377 | unsigned long dur; | ||
366 | 378 | ||
367 | rc = tpm_tis_send_data(chip, buf, len); | 379 | rc = tpm_tis_send_data(chip, buf, len); |
368 | if (rc < 0) | 380 | if (rc < 0) |
@@ -374,9 +386,14 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) | |||
374 | 386 | ||
375 | if (chip->vendor.irq) { | 387 | if (chip->vendor.irq) { |
376 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); | 388 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); |
389 | |||
390 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | ||
391 | dur = tpm2_calc_ordinal_duration(chip, ordinal); | ||
392 | else | ||
393 | dur = tpm_calc_ordinal_duration(chip, ordinal); | ||
394 | |||
377 | if (wait_for_tpm_stat | 395 | if (wait_for_tpm_stat |
378 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, | 396 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, |
379 | tpm_calc_ordinal_duration(chip, ordinal), | ||
380 | &chip->vendor.read_queue, false) < 0) { | 397 | &chip->vendor.read_queue, false) < 0) { |
381 | rc = -ETIME; | 398 | rc = -ETIME; |
382 | goto out_err; | 399 | goto out_err; |
@@ -598,17 +615,19 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, | |||
598 | return PTR_ERR(chip); | 615 | return PTR_ERR(chip); |
599 | 616 | ||
600 | chip->vendor.priv = priv; | 617 | chip->vendor.priv = priv; |
618 | #ifdef CONFIG_ACPI | ||
601 | chip->acpi_dev_handle = acpi_dev_handle; | 619 | chip->acpi_dev_handle = acpi_dev_handle; |
620 | #endif | ||
602 | 621 | ||
603 | chip->vendor.iobase = devm_ioremap(dev, start, len); | 622 | chip->vendor.iobase = devm_ioremap(dev, start, len); |
604 | if (!chip->vendor.iobase) | 623 | if (!chip->vendor.iobase) |
605 | return -EIO; | 624 | return -EIO; |
606 | 625 | ||
607 | /* Default timeouts */ | 626 | /* Maximum timeouts */ |
608 | chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | 627 | chip->vendor.timeout_a = TIS_TIMEOUT_A_MAX; |
609 | chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); | 628 | chip->vendor.timeout_b = TIS_TIMEOUT_B_MAX; |
610 | chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | 629 | chip->vendor.timeout_c = TIS_TIMEOUT_C_MAX; |
611 | chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | 630 | chip->vendor.timeout_d = TIS_TIMEOUT_D_MAX; |
612 | 631 | ||
613 | if (wait_startup(chip, 0) != 0) { | 632 | if (wait_startup(chip, 0) != 0) { |
614 | rc = -ENODEV; | 633 | rc = -ENODEV; |
@@ -620,11 +639,18 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, | |||
620 | goto out_err; | 639 | goto out_err; |
621 | } | 640 | } |
622 | 641 | ||
642 | /* Every TPM 2.x command has a higher ordinal than TPM 1.x commands. | ||
643 | * Therefore, we can use an idempotent TPM 2.x command to probe TPM 2.x. | ||
644 | */ | ||
645 | rc = tpm2_gen_interrupt(chip, true); | ||
646 | if (rc == 0 || rc == TPM2_RC_INITIALIZE) | ||
647 | chip->flags |= TPM_CHIP_FLAG_TPM2; | ||
648 | |||
623 | vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); | 649 | vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); |
624 | chip->vendor.manufacturer_id = vendor; | 650 | chip->vendor.manufacturer_id = vendor; |
625 | 651 | ||
626 | dev_info(dev, | 652 | dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n", |
627 | "1.2 TPM (device-id 0x%X, rev-id %d)\n", | 653 | (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2", |
628 | vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); | 654 | vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); |
629 | 655 | ||
630 | if (!itpm) { | 656 | if (!itpm) { |
@@ -720,7 +746,10 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, | |||
720 | chip->vendor.probed_irq = 0; | 746 | chip->vendor.probed_irq = 0; |
721 | 747 | ||
722 | /* Generate Interrupts */ | 748 | /* Generate Interrupts */ |
723 | tpm_gen_interrupt(chip); | 749 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
750 | tpm2_gen_interrupt(chip, false); | ||
751 | else | ||
752 | tpm_gen_interrupt(chip); | ||
724 | 753 | ||
725 | chip->vendor.irq = chip->vendor.probed_irq; | 754 | chip->vendor.irq = chip->vendor.probed_irq; |
726 | 755 | ||
@@ -765,16 +794,44 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, | |||
765 | } | 794 | } |
766 | } | 795 | } |
767 | 796 | ||
768 | if (tpm_get_timeouts(chip)) { | 797 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
769 | dev_err(dev, "Could not get TPM timeouts and durations\n"); | 798 | chip->vendor.timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A); |
770 | rc = -ENODEV; | 799 | chip->vendor.timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B); |
771 | goto out_err; | 800 | chip->vendor.timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C); |
772 | } | 801 | chip->vendor.timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D); |
802 | chip->vendor.duration[TPM_SHORT] = | ||
803 | msecs_to_jiffies(TPM2_DURATION_SHORT); | ||
804 | chip->vendor.duration[TPM_MEDIUM] = | ||
805 | msecs_to_jiffies(TPM2_DURATION_MEDIUM); | ||
806 | chip->vendor.duration[TPM_LONG] = | ||
807 | msecs_to_jiffies(TPM2_DURATION_LONG); | ||
808 | |||
809 | rc = tpm2_do_selftest(chip); | ||
810 | if (rc == TPM2_RC_INITIALIZE) { | ||
811 | dev_warn(dev, "Firmware has not started TPM\n"); | ||
812 | rc = tpm2_startup(chip, TPM2_SU_CLEAR); | ||
813 | if (!rc) | ||
814 | rc = tpm2_do_selftest(chip); | ||
815 | } | ||
773 | 816 | ||
774 | if (tpm_do_selftest(chip)) { | 817 | if (rc) { |
775 | dev_err(dev, "TPM self test failed\n"); | 818 | dev_err(dev, "TPM self test failed\n"); |
776 | rc = -ENODEV; | 819 | if (rc > 0) |
777 | goto out_err; | 820 | rc = -ENODEV; |
821 | goto out_err; | ||
822 | } | ||
823 | } else { | ||
824 | if (tpm_get_timeouts(chip)) { | ||
825 | dev_err(dev, "Could not get TPM timeouts and durations\n"); | ||
826 | rc = -ENODEV; | ||
827 | goto out_err; | ||
828 | } | ||
829 | |||
830 | if (tpm_do_selftest(chip)) { | ||
831 | dev_err(dev, "TPM self test failed\n"); | ||
832 | rc = -ENODEV; | ||
833 | goto out_err; | ||
834 | } | ||
778 | } | 835 | } |
779 | 836 | ||
780 | return tpm_chip_register(chip); | 837 | return tpm_chip_register(chip); |
@@ -808,14 +865,23 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) | |||
808 | static int tpm_tis_resume(struct device *dev) | 865 | static int tpm_tis_resume(struct device *dev) |
809 | { | 866 | { |
810 | struct tpm_chip *chip = dev_get_drvdata(dev); | 867 | struct tpm_chip *chip = dev_get_drvdata(dev); |
811 | int ret; | 868 | int ret = 0; |
812 | 869 | ||
813 | if (chip->vendor.irq) | 870 | if (chip->vendor.irq) |
814 | tpm_tis_reenable_interrupts(chip); | 871 | tpm_tis_reenable_interrupts(chip); |
815 | 872 | ||
816 | ret = tpm_pm_resume(dev); | 873 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
817 | if (!ret) | 874 | /* NOP if firmware properly does this. */ |
818 | tpm_do_selftest(chip); | 875 | tpm2_startup(chip, TPM2_SU_STATE); |
876 | |||
877 | ret = tpm2_shutdown(chip, TPM2_SU_STATE); | ||
878 | if (!ret) | ||
879 | ret = tpm2_do_selftest(chip); | ||
880 | } else { | ||
881 | ret = tpm_pm_resume(dev); | ||
882 | if (!ret) | ||
883 | tpm_do_selftest(chip); | ||
884 | } | ||
819 | 885 | ||
820 | return ret; | 886 | return ret; |
821 | } | 887 | } |