{
        struct tpm_chip *chip = dev_get_drvdata(dev);
        struct tpm_cmd_t cmd;
-       int rc;
+       int rc, try;
 
        u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
 
        }
 
        /* now do the actual savestate */
-       cmd.header.in = savestate_header;
-       rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE,
-                         "sending savestate before suspend");
+       for (try = 0; try < TPM_RETRY; try++) {
+               cmd.header.in = savestate_header;
+               rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, NULL);
+
+               /*
+                * If the TPM indicates that it is too busy to respond to
+                * this command then retry before giving up.  It can take
+                * several seconds for this TPM to be ready.
+                *
+                * This can happen if the TPM has already been sent the
+                * SaveState command before the driver has loaded.  TCG 1.2
+                * specification states that any communication after SaveState
+                * may cause the TPM to invalidate previously saved state.
+                */
+               if (rc != TPM_WARN_RETRY)
+                       break;
+               msleep(TPM_TIMEOUT_RETRY);
+       }
+
+       if (rc)
+               dev_err(chip->dev,
+                       "Error (%d) sending savestate before suspend\n", rc);
+       else if (try > 0)
+               dev_warn(chip->dev, "TPM savestate took %dms\n",
+                        try * TPM_TIMEOUT_RETRY);
+
        return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_pm_suspend);
 
        TPM_MINOR = 224,        /* officially assigned */
        TPM_BUFSIZE = 4096,
        TPM_NUM_DEVICES = 256,
+       TPM_RETRY = 50,         /* 5 seconds */
 };
 
 enum tpm_timeout {
        TPM_TIMEOUT = 5,        /* msecs */
+       TPM_TIMEOUT_RETRY = 100 /* msecs */
 };
 
 /* TPM addresses */
        TPM_ADDR = 0x4E,
 };
 
+#define TPM_WARN_RETRY          0x800
 #define TPM_WARN_DOING_SELFTEST 0x802
 #define TPM_ERR_DEACTIVATED     0x6
 #define TPM_ERR_DISABLED        0x7