Patrick Rudolph has uploaded this change for review.

View Change

drivers/spi/tpm: Add support for non CR50 SPI TPM2

Add support for a STM SPI TPM2 by adding checks for CR50.
Tested using ST33HTPH2E32.

Change-Id: I015497ca078979a44ba2b84e4995493de1f7247b
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
---
M src/drivers/spi/tpm/Kconfig
M src/drivers/spi/tpm/tis.c
M src/drivers/spi/tpm/tpm.c
M src/security/tpm/Kconfig
4 files changed, 46 insertions(+), 25 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/93/39693/1
diff --git a/src/drivers/spi/tpm/Kconfig b/src/drivers/spi/tpm/Kconfig
index be43e23..8c4bace 100644
--- a/src/drivers/spi/tpm/Kconfig
+++ b/src/drivers/spi/tpm/Kconfig
@@ -19,3 +19,10 @@
select SPI_TPM
help
Board has SPI TPM support
+
+config MAINBOARD_HAS_SPI_TPM
+ bool
+ default n
+ select SPI_TPM
+ help
+ Board has SPI TPM support
diff --git a/src/drivers/spi/tpm/tis.c b/src/drivers/spi/tpm/tis.c
index 6230751..60dc705 100644
--- a/src/drivers/spi/tpm/tis.c
+++ b/src/drivers/spi/tpm/tis.c
@@ -18,6 +18,7 @@
} dev_map[] = {
{ 0x15d1, 0x001b, "SLB9670" },
{ 0x1ae0, 0x0028, "CR50" },
+ { 0x104a, 0x0000, "ST33HTPH2E32" },
};

static const char *tis_get_dev_name(struct tpm2_info *info)
diff --git a/src/drivers/spi/tpm/tpm.c b/src/drivers/spi/tpm/tpm.c
index 62d1bba..7db92d5 100644
--- a/src/drivers/spi/tpm/tpm.c
+++ b/src/drivers/spi/tpm/tpm.c
@@ -104,7 +104,7 @@
*/
static int start_transaction(int read_write, size_t bytes, unsigned int addr)
{
- spi_frame_header header;
+ spi_frame_header header, header_resp;
uint8_t byte;
int i;
struct stopwatch sw;
@@ -114,7 +114,7 @@
* First Cr50 access in each coreboot stage where TPM is used will be
* prepended by a wake up pulse on the CS line.
*/
- int wakeup_needed = 1;
+ int wakeup_needed = CONFIG(TPM2_CR50);

/* Wait for TPM to finish previous transaction if needed */
if (tpm_sync_needed) {
@@ -181,26 +181,28 @@
* transmitted by the TPM during the transaction's last byte.
*
* We know that cr50 is guaranteed to set the flow control bit to 0
- * during the header transfer, but real TPM2 might be fast enough not
- * to require to stall the master, this would present an issue.
+ * during the header transfer. Real TPM2 are fast enough to not require
+ * to stall the master. They might still use this feature, so test the
+ * last bit after shifting in the address bytes.
* crosbug.com/p/52132 has been opened to track this.
*/
- spi_xfer(&spi_slave, header.body, sizeof(header.body), NULL, 0);
-
- /*
- * Now poll the bus until TPM removes the stall bit. Give it up to 100
- * ms to sort it out - it could be saving stuff in nvram at some
- * point.
- */
- stopwatch_init_msecs_expire(&sw, 100);
- do {
- if (stopwatch_expired(&sw)) {
- printk(BIOS_ERR, "TPM flow control failure\n");
- spi_release_bus(&spi_slave);
- return 0;
- }
- spi_xfer(&spi_slave, NULL, 0, &byte, 1);
- } while (!(byte & 1));
+ spi_xfer(&spi_slave, header.body, sizeof(header.body), &header_resp, sizeof(header_resp.body));
+ if (CONFIG(TPM2_CR50) || !(header_resp.body[3] & 1)) {
+ /*
+ * Now poll the bus until TPM removes the stall bit. Give it up to 100
+ * ms to sort it out - it could be saving stuff in nvram at some
+ * point.
+ */
+ stopwatch_init_msecs_expire(&sw, 100);
+ do {
+ if (stopwatch_expired(&sw)) {
+ printk(BIOS_ERR, "TPM flow control failure\n");
+ spi_release_bus(&spi_slave);
+ return 0;
+ }
+ spi_xfer(&spi_slave, NULL, 0, &byte, 1);
+ } while (!(byte & 1));
+ }
return 1;
}

@@ -408,7 +410,8 @@

/* Device/vendor ID values of the TPM devices this driver supports. */
static const uint32_t supported_did_vids[] = {
- 0x00281ae0 /* H1 based Cr50 security chip. */
+ 0x00281ae0, /* H1 based Cr50 security chip. */
+ 0x0000104a /* ST33HTPH2E32 */
};

int tpm2_init(struct spi_slave *spi_if)
@@ -454,7 +457,7 @@

printk(BIOS_INFO, " done!\n");

- if (ENV_VERSTAGE || ENV_BOOTBLOCK)
+ if (ENV_VERSTAGE || ENV_BOOTBLOCK || !CONFIG(VBOOT))
/*
* Claim locality 0, do it only during the first
* initialization after reset.
@@ -462,7 +465,10 @@
if (!tpm2_claim_locality())
return -1;

- read_tpm_sts(&status);
+ if (!read_tpm_sts(&status)) {
+ printk(BIOS_ERR, "Reading status reg failed\n");
+ return -1;
+ }
if ((status & TPM_STS_FAMILY_MASK) != TPM_STS_FAMILY_TPM_2_0) {
printk(BIOS_ERR, "unexpected TPM family value, status: %#x\n",
status);
diff --git a/src/security/tpm/Kconfig b/src/security/tpm/Kconfig
index 1766939..7baff87 100644
--- a/src/security/tpm/Kconfig
+++ b/src/security/tpm/Kconfig
@@ -26,7 +26,14 @@
default y if MAINBOARD_HAS_TPM2 || USER_TPM2
depends on MAINBOARD_HAS_I2C_TPM_GENERIC || MAINBOARD_HAS_LPC_TPM \
|| MAINBOARD_HAS_I2C_TPM_ATMEL || MAINBOARD_HAS_I2C_TPM_CR50 \
- || MAINBOARD_HAS_SPI_TPM_CR50 || MAINBOARD_HAS_CRB_TPM
+ || MAINBOARD_HAS_SPI_TPM_CR50 || MAINBOARD_HAS_CRB_TPM \
+ || MAINBOARD_HAS_SPI_TPM
+config TPM2_CR50
+ bool
+ default y if MAINBOARD_HAS_TPM2 || USER_TPM2
+ depends on MAINBOARD_HAS_I2C_TPM_CR50 || MAINBOARD_HAS_SPI_TPM_CR50
+ help
+ A software TPM2 running in Google's security chip.

config MAINBOARD_HAS_TPM1
bool
@@ -56,7 +63,7 @@
bool "2.0"
depends on MAINBOARD_HAS_I2C_TPM_GENERIC || MAINBOARD_HAS_LPC_TPM \
|| MAINBOARD_HAS_I2C_TPM_ATMEL || MAINBOARD_HAS_I2C_TPM_CR50 \
- || MAINBOARD_HAS_SPI_TPM_CR50 || MAINBOARD_HAS_CRB_TPM
+ || MAINBOARD_HAS_SPI_TPM_CR50 || MAINBOARD_HAS_CRB_TPM || MAINBOARD_HAS_SPI_TPM
help
Enable this option to enable TPM 2.0 support in coreboot.


To view, visit change 39693. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I015497ca078979a44ba2b84e4995493de1f7247b
Gerrit-Change-Number: 39693
Gerrit-PatchSet: 1
Gerrit-Owner: Patrick Rudolph <patrick.rudolph@9elements.com>
Gerrit-Reviewer: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Gerrit-MessageType: newchange