aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tpm
diff options
context:
space:
mode:
authorJason Gunthorpe <jgunthorpe@obsidianresearch.com>2012-12-06 17:44:54 -0500
committerKent Yoder <key@linux.vnet.ibm.com>2013-02-05 10:38:25 -0500
commit7240b98320a28f1d41b9361dc1cc8244dfda0272 (patch)
treecbe8d1548d15e66775b8f8f74cc734aa4e64b37e /drivers/char/tpm
parent78f09cc248731716633c0ef219613e762a9c4f2e (diff)
TPM: Wait for TPM_ACCESS tpmRegValidSts to go high at startup
The TIS specification (pg 47) says the valid bit must be set, but the TPM will not set it until it has completed its internal startup. The driver checks that the valid bit is set during request_locality, but it issues a TPM_ACCESS_REQUEST_USE without validating the valid bit is set. Some TPMs will ignore the TPM_ACCESS_REQUEST_USE, until valid is set which causes the request_locality to timeout, which breaks the driver attach. Wait one timeout unit for valid to assert. If valid does not assert then assume -ENODEV. Seen on embedded with a: 1.2 TPM (device-id 0x3204, rev-id 64) Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
Diffstat (limited to 'drivers/char/tpm')
-rw-r--r--drivers/char/tpm/tpm_tis.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index ae91c115c438..6c69ad72f82f 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -98,6 +98,22 @@ static inline int is_itpm(struct pnp_dev *dev)
98} 98}
99#endif 99#endif
100 100
101/* Before we attempt to access the TPM we must see that the valid bit is set.
102 * The specification says that this bit is 0 at reset and remains 0 until the
103 * 'TPM has gone through its self test and initialization and has established
104 * correct values in the other bits.' */
105static int wait_startup(struct tpm_chip *chip, int l)
106{
107 unsigned long stop = jiffies + chip->vendor.timeout_a;
108 do {
109 if (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
110 TPM_ACCESS_VALID)
111 return 0;
112 msleep(TPM_TIMEOUT);
113 } while (time_before(jiffies, stop));
114 return -1;
115}
116
101static int check_locality(struct tpm_chip *chip, int l) 117static int check_locality(struct tpm_chip *chip, int l)
102{ 118{
103 if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & 119 if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
@@ -541,6 +557,11 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
541 chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); 557 chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
542 chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); 558 chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
543 559
560 if (wait_startup(chip, 0) != 0) {
561 rc = -ENODEV;
562 goto out_err;
563 }
564
544 if (request_locality(chip, 0) != 0) { 565 if (request_locality(chip, 0) != 0) {
545 rc = -ENODEV; 566 rc = -ENODEV;
546 goto out_err; 567 goto out_err;