tpm: wait for valid bit to be set in TPM access register before using tpm

As per the TCG PC Client TPM Interface Specification v1.2, bit 7 of the
access register (tmpRegValiSts bit) stays "0" until the TPM has complete
through self test and initialization. This bit is set "1" to indicate that
the other bits in the register are valid.

BRANCH=chromeos-2013.04
BUG=chrome-os-partner:35328
TEST=Booted up storm p0.2 and whirwind sp3.
Verified TPM chip is detected and reported in coreboot logs.

Change-Id: I1049139fc155bfd2e1f29e3b8a7b9d2da6360857
Signed-off-by: Stefan Reinauer <reinauer@chromium.org>
Original-Commit-Id: 006fc93c6308d6f3fa220f00708708aa62cc676c
Original-Change-Id: I9df3388ee1ef6e4a9d200d99aea1838963747ecf
Original-Signed-off-by: Sourabh Banerjee <sbanerje@codeaurora.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/242222
Original-Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
Original-Commit-Queue: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: http://review.coreboot.org/9567
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
Sourabh Banerjee 2015-01-20 15:18:40 +05:30 committed by Patrick Georgi
parent 24d4dae00f
commit 8c916ec834
1 changed files with 26 additions and 3 deletions

View File

@ -29,6 +29,7 @@
#include <device/i2c.h> #include <device/i2c.h>
#include <tpm.h> #include <tpm.h>
#include "tpm.h" #include "tpm.h"
#include <timer.h>
#include <console/console.h> #include <console/console.h>
@ -37,6 +38,7 @@ struct tpm_chip g_chip;
#define TPM_CMD_COUNT_BYTE 2 #define TPM_CMD_COUNT_BYTE 2
#define TPM_CMD_ORDINAL_BYTE 6 #define TPM_CMD_ORDINAL_BYTE 6
#define TPM_VALID_STATUS (1 << 7)
int tis_open(void) int tis_open(void)
{ {
@ -74,12 +76,33 @@ int tis_init(void)
{ {
int bus = CONFIG_DRIVER_TPM_I2C_BUS; int bus = CONFIG_DRIVER_TPM_I2C_BUS;
int chip = CONFIG_DRIVER_TPM_I2C_ADDR; int chip = CONFIG_DRIVER_TPM_I2C_ADDR;
struct stopwatch sw;
uint8_t buf = 0;
int ret;
long sw_run_duration = 750;
/* /*
* Probe TPM twice; the first probing might fail because TPM is asleep, * Probe TPM. Check if the TPM_ACCESS register's ValidSts bit is set(1)
* and the probing can wake up TPM. * If the bit remains clear(0) then claim that init has failed.
*/ */
if (i2c_writeb(bus, chip, 0, 0) && i2c_writeb(bus, chip, 0, 0)) stopwatch_init_msecs_expire(&sw, sw_run_duration);
do {
ret = i2c_readb(bus, chip, 0, &buf);
if (!ret && (buf & TPM_VALID_STATUS)) {
sw_run_duration = stopwatch_duration_msecs(&sw);
break;
}
} while (!stopwatch_expired(&sw));
printk(BIOS_INFO,
"%s: ValidSts bit %s(%d) in TPM_ACCESS register after %ld ms\n",
__func__, (buf & TPM_VALID_STATUS) ? "set" : "clear",
(buf & TPM_VALID_STATUS) >> 7, sw_run_duration);
/*
* Claim failure if the ValidSts (bit 7) is clear.
*/
if (!(buf & TPM_VALID_STATUS))
return -1; return -1;
return 0; return 0;