TPM: Wait for TPM_ACCESS tpmRegValidSts to go high at startup
[cascardo/linux.git] / drivers / char / tpm / tpm_tis.c
index ae91c11..6c69ad7 100644 (file)
@@ -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;