drivers/i2c/tpm: Clean up handling of command ready
The TPM driver was largely ignoring the meaning of the command ready bit in the status register, instead just arbitrarily sending it at the end of every receive transaction. Instead of doing this have the command ready bit be set at the start of a transaction, and only clear it at the end of a transaction if it is still set, in case of failure. Also the cr50 function to wait for status and burst count was not waiting the full 2s that the existing driver does so that value is increased. Also, during the probe routine a delay is inserted after each status register read to ensure the TPM has time to actually start up. Change-Id: I1c66ea9849e6be537c7be06d57258f27c563c1c2 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://review.coreboot.org/16591 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@chromium.org> Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@googlemail.com>
This commit is contained in:
parent
f8a7b2c008
commit
fbce31a2cc
|
@ -539,7 +539,7 @@ static int cr50_wait_burst_status(struct tpm_chip *chip, uint8_t mask,
|
||||||
uint8_t buf[4];
|
uint8_t buf[4];
|
||||||
struct stopwatch sw;
|
struct stopwatch sw;
|
||||||
|
|
||||||
stopwatch_init_usecs_expire(&sw, 10 * SLEEP_DURATION_SAFE);
|
stopwatch_init_msecs_expire(&sw, 2000);
|
||||||
|
|
||||||
while (!stopwatch_expired(&sw)) {
|
while (!stopwatch_expired(&sw)) {
|
||||||
if (iic_tpm_read(TPM_STS(chip->vendor.locality),
|
if (iic_tpm_read(TPM_STS(chip->vendor.locality),
|
||||||
|
@ -628,7 +628,6 @@ static int cr50_tis_i2c_recv(struct tpm_chip *chip, uint8_t *buf,
|
||||||
ret = current;
|
ret = current;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
cr50_tis_i2c_ready(chip);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,17 +636,23 @@ static int cr50_tis_i2c_send(struct tpm_chip *chip, uint8_t *buf, size_t len)
|
||||||
int status;
|
int status;
|
||||||
size_t burstcnt, limit, sent = 0;
|
size_t burstcnt, limit, sent = 0;
|
||||||
uint8_t tpm_go[4] = { TPM_STS_GO };
|
uint8_t tpm_go[4] = { TPM_STS_GO };
|
||||||
|
struct stopwatch sw;
|
||||||
|
|
||||||
if (len > TPM_BUFSIZE)
|
if (len > TPM_BUFSIZE)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
stopwatch_init_msecs_expire(&sw, 2000);
|
||||||
|
|
||||||
/* Wait until TPM is ready for a command */
|
/* Wait until TPM is ready for a command */
|
||||||
status = cr50_tis_i2c_status(chip);
|
while (!(cr50_tis_i2c_status(chip) & TPM_STS_COMMAND_READY)) {
|
||||||
if (!(status & TPM_STS_COMMAND_READY)) {
|
if (stopwatch_expired(&sw)) {
|
||||||
|
printk(BIOS_ERR, "%s: Command ready timeout\n",
|
||||||
|
__func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
cr50_tis_i2c_ready(chip);
|
cr50_tis_i2c_ready(chip);
|
||||||
if (cr50_wait_burst_status(chip, TPM_STS_COMMAND_READY,
|
udelay(SLEEP_DURATION_SAFE);
|
||||||
&burstcnt, &status) < 0)
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
|
@ -690,7 +695,9 @@ static int cr50_tis_i2c_send(struct tpm_chip *chip, uint8_t *buf, size_t len)
|
||||||
return sent;
|
return sent;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
cr50_tis_i2c_ready(chip);
|
/* Abort current transaction if still pending */
|
||||||
|
if (cr50_tis_i2c_status(chip) & TPM_STS_COMMAND_READY)
|
||||||
|
cr50_tis_i2c_ready(chip);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -721,6 +728,7 @@ int tpm_vendor_probe(unsigned bus, uint32_t addr)
|
||||||
sw_run_duration = stopwatch_duration_msecs(&sw);
|
sw_run_duration = stopwatch_duration_msecs(&sw);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
udelay(SLEEP_DURATION_SAFE);
|
||||||
} while (!stopwatch_expired(&sw));
|
} while (!stopwatch_expired(&sw));
|
||||||
|
|
||||||
printk(BIOS_INFO,
|
printk(BIOS_INFO,
|
||||||
|
@ -747,6 +755,7 @@ int tpm_vendor_init(struct tpm_chip *chip, unsigned bus, uint32_t dev_addr)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tpm_dev->chip_type = UNKNOWN;
|
||||||
tpm_dev->bus = bus;
|
tpm_dev->bus = bus;
|
||||||
tpm_dev->addr = dev_addr;
|
tpm_dev->addr = dev_addr;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue