summaryrefslogtreecommitdiff
path: root/src/drivers/spi
diff options
context:
space:
mode:
authorPatrick Rudolph <patrick.rudolph@9elements.com>2020-03-20 09:55:43 +0100
committerPhilipp Deppenwiese <zaolin.daisuki@gmail.com>2020-04-28 01:19:15 +0000
commit7bcd9a1d91f10c6c58cd4c2b4e0583eec221810c (patch)
tree588b3f13a87659ad30bb207eaac341b39435cb4d /src/drivers/spi
parentfd50aea03e57e8efda5bc33f1cbbcd6f2a62e66b (diff)
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> Reviewed-on: https://review.coreboot.org/c/coreboot/+/39693 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com> Reviewed-by: Julius Werner <jwerner@chromium.org>
Diffstat (limited to 'src/drivers/spi')
-rw-r--r--src/drivers/spi/tpm/Kconfig7
-rw-r--r--src/drivers/spi/tpm/tis.c1
-rw-r--r--src/drivers/spi/tpm/tpm.c102
3 files changed, 71 insertions, 39 deletions
diff --git a/src/drivers/spi/tpm/Kconfig b/src/drivers/spi/tpm/Kconfig
index be43e2314d..8c39a4a44a 100644
--- a/src/drivers/spi/tpm/Kconfig
+++ b/src/drivers/spi/tpm/Kconfig
@@ -16,6 +16,13 @@ config DRIVER_TPM_SPI_CHIP
config MAINBOARD_HAS_SPI_TPM_CR50
bool
default n
+ select MAINBOARD_HAS_SPI_TPM
+ help
+ Board has a CR50 SPI TPM
+
+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 6230751fb1..60dc705bee 100644
--- a/src/drivers/spi/tpm/tis.c
+++ b/src/drivers/spi/tpm/tis.c
@@ -18,6 +18,7 @@ static const struct {
} 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 8f93e2a71a..c47aed312c 100644
--- a/src/drivers/spi/tpm/tpm.c
+++ b/src/drivers/spi/tpm/tpm.c
@@ -104,47 +104,51 @@ static int tpm_sync(void)
*/
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;
+ int ret;
struct stopwatch sw;
static int tpm_sync_needed;
static struct stopwatch wake_up_sw;
- /*
- * 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;
- /* Wait for TPM to finish previous transaction if needed */
- if (tpm_sync_needed) {
- tpm_sync();
+ if (CONFIG(TPM_CR50)) {
/*
- * During the first invocation of this function on each stage
- * this if () clause code does not run (as tpm_sync_needed
- * value is zero), during all following invocations the
- * stopwatch below is guaranteed to be started.
+ * First Cr50 access in each coreboot stage where TPM is used will be
+ * prepended by a wake up pulse on the CS line.
*/
- if (!stopwatch_expired(&wake_up_sw))
- wakeup_needed = 0;
- } else {
- tpm_sync_needed = 1;
- }
+ int wakeup_needed = 1;
- if (wakeup_needed) {
- /* Just in case Cr50 is asleep. */
- spi_claim_bus(&spi_slave);
- udelay(1);
- spi_release_bus(&spi_slave);
- udelay(100);
- }
+ /* Wait for TPM to finish previous transaction if needed */
+ if (tpm_sync_needed) {
+ tpm_sync();
+ /*
+ * During the first invocation of this function on each stage
+ * this if () clause code does not run (as tpm_sync_needed
+ * value is zero), during all following invocations the
+ * stopwatch below is guaranteed to be started.
+ */
+ if (!stopwatch_expired(&wake_up_sw))
+ wakeup_needed = 0;
+ } else {
+ tpm_sync_needed = 1;
+ }
- /*
- * The Cr50 on H1 does not go to sleep for 1 second after any
- * SPI slave activity, let's be conservative and limit the
- * window to 900 ms.
- */
- stopwatch_init_msecs_expire(&wake_up_sw, 900);
+ if (wakeup_needed) {
+ /* Just in case Cr50 is asleep. */
+ spi_claim_bus(&spi_slave);
+ udelay(1);
+ spi_release_bus(&spi_slave);
+ udelay(100);
+ }
+
+ /*
+ * The Cr50 on H1 does not go to sleep for 1 second after any
+ * SPI slave activity, let's be conservative and limit the
+ * window to 900 ms.
+ */
+ stopwatch_init_msecs_expire(&wake_up_sw, 900);
+ }
/*
* The first byte of the frame header encodes the transaction type
@@ -181,16 +185,30 @@ static int start_transaction(int read_write, size_t bytes, unsigned int addr)
* 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);
+
+ header_resp.body[3] = 0;
+ if (CONFIG(TPM_CR50))
+ ret = spi_xfer(&spi_slave, header.body, sizeof(header.body), NULL, 0);
+ else
+ ret = spi_xfer(&spi_slave, header.body, sizeof(header.body),
+ header_resp.body, sizeof(header_resp.body));
+ if (ret) {
+ printk(BIOS_ERR, "SPI-TPM: transfer error\n");
+ spi_release_bus(&spi_slave);
+ return 0;
+ }
+
+ if (header_resp.body[3] & 1)
+ return 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.
+ * ms to sort it out - it could be saving stuff in nvram at some point.
*/
stopwatch_init_msecs_expire(&sw, 100);
do {
@@ -201,6 +219,7 @@ static int start_transaction(int read_write, size_t bytes, unsigned int addr)
}
spi_xfer(&spi_slave, NULL, 0, &byte, 1);
} while (!(byte & 1));
+
return 1;
}
@@ -408,7 +427,8 @@ static int tpm2_claim_locality(void)
/* 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 +474,8 @@ int tpm2_init(struct spi_slave *spi_if)
printk(BIOS_INFO, " done!\n");
- if (ENV_SEPARATE_VERSTAGE || ENV_BOOTBLOCK)
+ // FIXME: Move this to tpm_setup()
+ if (ENV_SEPARATE_VERSTAGE || ENV_BOOTBLOCK || !CONFIG(VBOOT))
/*
* Claim locality 0, do it only during the first
* initialization after reset.
@@ -462,7 +483,10 @@ int tpm2_init(struct spi_slave *spi_if)
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);