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>
This commit is contained in:
parent
78f09cc248
commit
7240b98320
1 changed files with 21 additions and 0 deletions
|
@ -98,6 +98,22 @@ static inline int is_itpm(struct pnp_dev *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Before we attempt to access the TPM we must see that the valid bit is set.
|
||||
* The specification says that this bit is 0 at reset and remains 0 until the
|
||||
* 'TPM has gone through its self test and initialization and has established
|
||||
* correct values in the other bits.' */
|
||||
static int wait_startup(struct tpm_chip *chip, int l)
|
||||
{
|
||||
unsigned long stop = jiffies + chip->vendor.timeout_a;
|
||||
do {
|
||||
if (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
|
||||
TPM_ACCESS_VALID)
|
||||
return 0;
|
||||
msleep(TPM_TIMEOUT);
|
||||
} while (time_before(jiffies, stop));
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int check_locality(struct tpm_chip *chip, int l)
|
||||
{
|
||||
if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
|
||||
|
@ -541,6 +557,11 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
|
|||
chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
|
||||
chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
|
||||
|
||||
if (wait_startup(chip, 0) != 0) {
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (request_locality(chip, 0) != 0) {
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
|
|
Loading…
Reference in a new issue