spi/tpm: Make sure AP properly syncs up with Cr50
When Cr50 TPM is being reset, it continues replying to the SPI bus requests, sends wrong register values in response to read requests. This patch makes sure that the TPM driver does not proceed unless proper value is read from the TPM device identification register. If the read value is still wrong after 10 retries taken with 10 ms intervals, the driver gives up and declares TPM broken/unavailable. BRANCH=cr50 BUG=b:68012381 TEST=ran a script resetting the Fizz device as soon as the "index 0x1007 return code 0" string shows up in the AP console output. The script keeps rebooting the Fizz indefinitely, before this script Fizz would fail to read TPM properly and fall into recovery after no more than four reboots. Change-Id: I7e67ec62c2bf31077b9ae558e09214d07eccf96b Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://review.coreboot.org/22231 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
parent
d2c636582d
commit
9a506d5c9a
|
@ -280,7 +280,8 @@ static int tpm2_write_reg(unsigned reg_number, const void *buffer, size_t bytes)
|
||||||
* To read a register, start transaction, transfer data from the TPM, deassert
|
* To read a register, start transaction, transfer data from the TPM, deassert
|
||||||
* CS when done.
|
* CS when done.
|
||||||
*
|
*
|
||||||
* Returns one to indicate success, zero to indicate failure.
|
* Returns one to indicate success, zero to indicate failure. In case of
|
||||||
|
* failure zero out the user buffer.
|
||||||
*/
|
*/
|
||||||
static int tpm2_read_reg(unsigned reg_number, void *buffer, size_t bytes)
|
static int tpm2_read_reg(unsigned reg_number, void *buffer, size_t bytes)
|
||||||
{
|
{
|
||||||
|
@ -368,21 +369,52 @@ static int tpm2_claim_locality(void)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Device/vendor ID values of the TPM devices this driver supports. */
|
||||||
|
static const uint32_t supported_did_vids[] = {
|
||||||
|
0x00281ae0 /* H1 based Cr50 security chip. */
|
||||||
|
};
|
||||||
|
|
||||||
int tpm2_init(struct spi_slave *spi_if)
|
int tpm2_init(struct spi_slave *spi_if)
|
||||||
{
|
{
|
||||||
uint32_t did_vid, status;
|
uint32_t did_vid, status;
|
||||||
uint8_t cmd;
|
uint8_t cmd;
|
||||||
|
int retries;
|
||||||
struct tpm2_info *tpm_info = car_get_var_ptr(&g_tpm_info);
|
struct tpm2_info *tpm_info = car_get_var_ptr(&g_tpm_info);
|
||||||
struct spi_slave *spi_slave = car_get_var_ptr(&g_spi_slave);
|
struct spi_slave *spi_slave = car_get_var_ptr(&g_spi_slave);
|
||||||
|
|
||||||
memcpy(spi_slave, spi_if, sizeof(*spi_if));
|
memcpy(spi_slave, spi_if, sizeof(*spi_if));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It is enough to check the first register read error status to bail
|
* 150 ms should be enough to synchronize with the TPM even under the
|
||||||
* out in case of malfunctioning TPM.
|
* worst nested reset request conditions. In vast majority of cases
|
||||||
|
* there would be no wait at all.
|
||||||
*/
|
*/
|
||||||
if (!tpm2_read_reg(TPM_DID_VID_REG, &did_vid, sizeof(did_vid)))
|
printk(BIOS_INFO, "Probing TPM: ");
|
||||||
|
for (retries = 15; retries > 0; retries--) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* In case of falure to read div_vid is set to zero. */
|
||||||
|
tpm2_read_reg(TPM_DID_VID_REG, &did_vid, sizeof(did_vid));
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(supported_did_vids); i++)
|
||||||
|
if (did_vid == supported_did_vids[i])
|
||||||
|
break; /* Tpm is up and ready. */
|
||||||
|
|
||||||
|
if (i < ARRAY_SIZE(supported_did_vids))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* TPM might be resetting, let's retry in a bit. */
|
||||||
|
mdelay(10);
|
||||||
|
printk(BIOS_INFO, ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!retries) {
|
||||||
|
printk(BIOS_ERR, "\n%s: Failed to connect to the TPM\n",
|
||||||
|
__func__);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk(BIOS_INFO, " done!\n");
|
||||||
|
|
||||||
/* Claim locality 0. */
|
/* Claim locality 0. */
|
||||||
if (!tpm2_claim_locality())
|
if (!tpm2_claim_locality())
|
||||||
|
|
Loading…
Reference in New Issue