drivers/i2c/tpm: Fix early TPM probe
The early TPM probe was done directly in tis.c ignoring the lower layer that provides appropriate access to the chip. Move this into a tpm_vendor_probe() function so it can use iic_tpm_read() with all of the built-in delays and semantics instead of calling i2c_readb() directly from the wrong layer. This fixes early init failures that were seen with the cr50 i2c tpm on the reef mainboard. Change-Id: I9bb3b820d10f6e2ea24c57b90cf0edc813cdc7e0 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://review.coreboot.org/16527 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@chromium.org> Reviewed-by: Furquan Shaikh <furquan@google.com> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
This commit is contained in:
parent
7fbdad80fd
commit
1ca196841a
|
@ -31,7 +31,6 @@ static struct tpm_chip g_chip CAR_GLOBAL;
|
|||
|
||||
#define TPM_CMD_COUNT_BYTE 2
|
||||
#define TPM_CMD_ORDINAL_BYTE 6
|
||||
#define TPM_VALID_STATUS (1 << 7)
|
||||
|
||||
int tis_open(void)
|
||||
{
|
||||
|
@ -69,38 +68,8 @@ int tis_close(void)
|
|||
|
||||
int tis_init(void)
|
||||
{
|
||||
int bus = CONFIG_DRIVER_TPM_I2C_BUS;
|
||||
int chip = CONFIG_DRIVER_TPM_I2C_ADDR;
|
||||
struct stopwatch sw;
|
||||
uint8_t buf = 0;
|
||||
int ret;
|
||||
long sw_run_duration = 750;
|
||||
|
||||
/*
|
||||
* Probe TPM. Check if the TPM_ACCESS register's ValidSts bit is set(1)
|
||||
* If the bit remains clear(0) then claim that init has failed.
|
||||
*/
|
||||
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 0;
|
||||
return tpm_vendor_probe(CONFIG_DRIVER_TPM_I2C_BUS,
|
||||
CONFIG_DRIVER_TPM_I2C_ADDR);
|
||||
}
|
||||
|
||||
static ssize_t tpm_transmit(const uint8_t *buf, size_t bufsiz)
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#define SLEEP_DURATION 60 /* in usec */
|
||||
#define SLEEP_DURATION_LONG 210 /* in usec */
|
||||
#define SLEEP_DURATION_SAFE 750 /* in usec */
|
||||
#define SLEEP_DURATION_PROBE_MS 1000 /* in msec */
|
||||
|
||||
/* max. number of iterations after I2C NAK for 'long' commands
|
||||
* we need this especially for sending TPM_READY, since the cleanup after the
|
||||
|
@ -695,6 +696,47 @@ out:
|
|||
|
||||
/* Initialization of I2C TPM */
|
||||
|
||||
int tpm_vendor_probe(unsigned bus, uint32_t addr)
|
||||
{
|
||||
struct tpm_inf_dev *tpm_dev = car_get_var_ptr(&g_tpm_dev);
|
||||
struct stopwatch sw;
|
||||
uint8_t buf = 0;
|
||||
int ret;
|
||||
long sw_run_duration = SLEEP_DURATION_PROBE_MS;
|
||||
|
||||
tpm_dev->chip_type = UNKNOWN;
|
||||
tpm_dev->bus = bus;
|
||||
tpm_dev->addr = addr;
|
||||
tpm_dev->sleep_short = SLEEP_DURATION_SAFE;
|
||||
tpm_dev->sleep_long = SLEEP_DURATION_SAFE * 2;
|
||||
|
||||
/*
|
||||
* Probe TPM. Check if the TPM_ACCESS register's ValidSts bit is set(1)
|
||||
* If the bit remains clear(0) then claim that init has failed.
|
||||
*/
|
||||
stopwatch_init_msecs_expire(&sw, sw_run_duration);
|
||||
do {
|
||||
ret = iic_tpm_read(TPM_ACCESS(0), &buf, 1);
|
||||
if (!ret && (buf & TPM_STS_VALID)) {
|
||||
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_STS_VALID) ? "set" : "clear",
|
||||
(buf & TPM_STS_VALID) >> 7, sw_run_duration);
|
||||
|
||||
/*
|
||||
* Claim failure if the ValidSts (bit 7) is clear.
|
||||
*/
|
||||
if (!(buf & TPM_STS_VALID))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpm_vendor_init(struct tpm_chip *chip, unsigned bus, uint32_t dev_addr)
|
||||
{
|
||||
struct tpm_inf_dev *tpm_dev = car_get_var_ptr(&g_tpm_dev);
|
||||
|
|
|
@ -121,6 +121,8 @@ struct tpm_cmd_t {
|
|||
|
||||
/* ---------- Interface for TPM vendor ------------ */
|
||||
|
||||
int tpm_vendor_probe(unsigned bus, uint32_t addr);
|
||||
|
||||
int tpm_vendor_init(struct tpm_chip *chip, unsigned bus, uint32_t dev_addr);
|
||||
|
||||
void tpm_vendor_cleanup(struct tpm_chip *chip);
|
||||
|
|
Loading…
Reference in New Issue