[coreboot-gerrit] Change in coreboot[master]: drivers/spi/tpm: Clean up SPI TPM driver

Furquan Shaikh (Code Review) gerrit at coreboot.org
Thu Apr 13 05:04:18 CEST 2017


Furquan Shaikh has submitted this change and it was merged. ( https://review.coreboot.org/19213 )

Change subject: drivers/spi/tpm: Clean up SPI TPM driver
......................................................................


drivers/spi/tpm: Clean up SPI TPM driver

1. Move common TIS macros to include/tpm.h.
2. Use common TIS macros while referring to status and access registers.
3. Add a new function claim_locality to properly check for required
access bits and claim locality 0.

BUG=b:36873582

Change-Id: I11bf3e8b6e1f50b7868c9fe4394a858488367287
Signed-off-by: Furquan Shaikh <furquan at chromium.org>
Reviewed-on: https://review.coreboot.org/19213
Tested-by: build bot (Jenkins)
Reviewed-by: Duncan Laurie <dlaurie at chromium.org>
---
M src/drivers/i2c/tpm/cr50.c
M src/drivers/i2c/tpm/tpm.c
M src/drivers/i2c/tpm/tpm.h
M src/drivers/spi/tpm/tpm.c
M src/include/tpm.h
5 files changed, 85 insertions(+), 80 deletions(-)

Approvals:
  Duncan Laurie: Looks good to me, approved
  build bot (Jenkins): Verified



diff --git a/src/drivers/i2c/tpm/cr50.c b/src/drivers/i2c/tpm/cr50.c
index 42c82d6..ce30bf1 100644
--- a/src/drivers/i2c/tpm/cr50.c
+++ b/src/drivers/i2c/tpm/cr50.c
@@ -39,6 +39,7 @@
 #include <device/i2c.h>
 #include <endian.h>
 #include <timer.h>
+#include <tpm.h>
 #include "tpm.h"
 
 #if IS_ENABLED(CONFIG_ARCH_X86)
diff --git a/src/drivers/i2c/tpm/tpm.c b/src/drivers/i2c/tpm/tpm.c
index e804d6f..5350695 100644
--- a/src/drivers/i2c/tpm/tpm.c
+++ b/src/drivers/i2c/tpm/tpm.c
@@ -38,6 +38,7 @@
 #include <device/i2c.h>
 #include <endian.h>
 #include <timer.h>
+#include <tpm.h>
 #include "tpm.h"
 
 /* max. number of iterations after I2C NAK */
diff --git a/src/drivers/i2c/tpm/tpm.h b/src/drivers/i2c/tpm/tpm.h
index 3a9a2ab..e511e0d 100644
--- a/src/drivers/i2c/tpm/tpm.h
+++ b/src/drivers/i2c/tpm/tpm.h
@@ -47,21 +47,6 @@
 #define TPM_RSP_SIZE_BYTE 2
 #define TPM_RSP_RC_BYTE 6
 
-enum tis_access {
-	TPM_ACCESS_VALID = 0x80,
-	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
-	TPM_ACCESS_REQUEST_PENDING = 0x04,
-	TPM_ACCESS_REQUEST_USE = 0x02,
-};
-
-enum tis_status {
-	TPM_STS_VALID = 0x80,
-	TPM_STS_COMMAND_READY = 0x40,
-	TPM_STS_GO = 0x20,
-	TPM_STS_DATA_AVAIL = 0x10,
-	TPM_STS_DATA_EXPECT = 0x08,
-};
-
 #define	TPM_ACCESS(l)			(0x0000 | ((l) << 4))
 #define	TPM_STS(l)			(0x0001 | ((l) << 4))
 #define	TPM_DATA_FIFO(l)		(0x0005 | ((l) << 4))
diff --git a/src/drivers/spi/tpm/tpm.c b/src/drivers/spi/tpm/tpm.c
index 1c5e535..0b5a835 100644
--- a/src/drivers/spi/tpm/tpm.c
+++ b/src/drivers/spi/tpm/tpm.c
@@ -16,6 +16,7 @@
  */
 
 #include <arch/early_variables.h>
+#include <assert.h>
 #include <commonlib/endian.h>
 #include <console/console.h>
 #include <delay.h>
@@ -47,35 +48,6 @@
  * debug traces. Right now it is either 0 or 1.
  */
 static const int debug_level_ = CONFIG_DEBUG_TPM;
-
-/* Locality management bits (in TPM_ACCESS_REG) */
-enum tpm_access_bits {
-	tpm_reg_valid_sts = (1 << 7),
-	active_locality = (1 << 5),
-	request_use = (1 << 1),
-	tpm_establishment = (1 << 0),
-};
-
-/*
- * Variuous fields of the TPM status register, arguably the most important
- * register when interfacing to a TPM.
- */
-enum tpm_sts_bits {
-	tpm_family_shift = 26,
-	tpm_family_mask = ((1 << 2) - 1),  /* 2 bits wide. */
-	tpm_family_tpm2 = 1,
-	reset_establishment_bit = (1 << 25),
-	command_cancel = (1 << 24),
-	burst_count_shift = 8,
-	burst_count_mask = ((1 << 16) - 1),  /* 16 bits wide. */
-	sts_valid = (1 << 7),
-	command_ready = (1 << 6),
-	tpm_go = (1 << 5),
-	data_avail = (1 << 4),
-	expect = (1 << 3),
-	self_test_done = (1 << 2),
-	response_retry = (1 << 1),
-};
 
 /*
  * SPI frame header for TPM transactions is 4 bytes in size, it is described
@@ -113,7 +85,7 @@
 {
 	struct stopwatch sw;
 
-	stopwatch_init_usecs_expire(&sw, 10 * 1000);
+	stopwatch_init_msecs_expire(&sw, 10);
 	while (!tis_plat_irq_status()) {
 		if (stopwatch_expired(&sw)) {
 			printk(BIOS_ERR, "Timeout wait for tpm irq!\n");
@@ -347,7 +319,53 @@
 	uint32_t status;
 
 	read_tpm_sts(&status);
-	return (status >> burst_count_shift) & burst_count_mask;
+	return (status & TPM_STS_BURST_COUNT_MASK) >> TPM_STS_BURST_COUNT_SHIFT;
+}
+
+static uint8_t tpm2_read_access_reg(void)
+{
+	uint8_t access;
+	tpm2_read_reg(TPM_ACCESS_REG, &access, sizeof(access));
+	/* We do not care about access establishment bit state. Ignore it. */
+	return access & ~TPM_ACCESS_ESTABLISHMENT;
+}
+
+static void tpm2_write_access_reg(uint8_t cmd)
+{
+	/* Writes to access register can set only 1 bit at a time. */
+	assert (!(cmd & (cmd - 1)));
+
+	tpm2_write_reg(TPM_ACCESS_REG, &cmd, sizeof(cmd));
+}
+
+static int tpm2_claim_locality(void)
+{
+	uint8_t access;
+
+	access = tpm2_read_access_reg();
+	/*
+	 * If active locality is set (maybe reset line is not connected?),
+	 * release the locality and try again.
+	 */
+	if (access & TPM_ACCESS_ACTIVE_LOCALITY) {
+		tpm2_write_access_reg(TPM_ACCESS_ACTIVE_LOCALITY);
+		access = tpm2_read_access_reg();
+	}
+
+	if (access != TPM_ACCESS_VALID) {
+		printk(BIOS_ERR, "Invalid reset status: %#x\n", access);
+		return 0;
+	}
+
+	tpm2_write_access_reg(TPM_ACCESS_REQUEST_USE);
+	access = tpm2_read_access_reg();
+	if (access != (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {
+		printk(BIOS_ERR, "Failed to claim locality 0, status: %#x\n",
+		       access);
+		return 0;
+	}
+
+	return 1;
 }
 
 int tpm2_init(struct spi_slave *spi_if)
@@ -366,38 +384,12 @@
 	if (!tpm2_read_reg(TPM_DID_VID_REG, &did_vid, sizeof(did_vid)))
 		return -1;
 
-	/* Try claiming locality zero. */
-	tpm2_read_reg(TPM_ACCESS_REG, &cmd, sizeof(cmd));
-	if ((cmd & (active_locality & tpm_reg_valid_sts)) ==
-	    (active_locality & tpm_reg_valid_sts)) {
-		/*
-		 * Locality active - maybe reset line is not connected?
-		 * Release the locality and try again
-		 */
-		cmd = active_locality;
-		tpm2_write_reg(TPM_ACCESS_REG, &cmd, sizeof(cmd));
-		tpm2_read_reg(TPM_ACCESS_REG, &cmd, sizeof(cmd));
-	}
-
-	/* The tpm_establishment bit can be either set or not, ignore it. */
-	if ((cmd & ~tpm_establishment) != tpm_reg_valid_sts) {
-		printk(BIOS_ERR, "invalid reset status: %#x\n", cmd);
+	/* Claim locality 0. */
+	if (!tpm2_claim_locality())
 		return -1;
-	}
-
-	cmd = request_use;
-	tpm2_write_reg(TPM_ACCESS_REG, &cmd, sizeof(cmd));
-	tpm2_read_reg(TPM_ACCESS_REG, &cmd, sizeof(cmd));
-	if ((cmd &  ~tpm_establishment) !=
-	    (tpm_reg_valid_sts | active_locality)) {
-		printk(BIOS_ERR, "failed to claim locality 0, status: %#x\n",
-		       cmd);
-		return -1;
-	}
 
 	read_tpm_sts(&status);
-	if (((status >> tpm_family_shift) & tpm_family_mask) !=
-	    tpm_family_tpm2) {
+	if ((status & TPM_STS_FAMILY_MASK) != TPM_STS_FAMILY_TPM_2_0) {
 		printk(BIOS_ERR, "unexpected TPM family value, status: %#x\n",
 		       status);
 		return -1;
@@ -563,7 +555,7 @@
 	}
 
 	/* Let the TPM know that the command is coming. */
-	write_tpm_sts(command_ready);
+	write_tpm_sts(TPM_STS_COMMAND_READY);
 
 	/*
 	 * Tpm commands and responses written to and read from the FIFO
@@ -580,10 +572,10 @@
 	fifo_transfer(command_size, fifo_buffer, fifo_transmit);
 
 	/* Now tell the TPM it can start processing the command. */
-	write_tpm_sts(tpm_go);
+	write_tpm_sts(TPM_STS_GO);
 
 	/* Now wait for it to report that the response is ready. */
-	expected_status_bits = sts_valid | data_avail;
+	expected_status_bits = TPM_STS_VALID | TPM_STS_DATA_AVAIL;
 	if (!wait_for_status(expected_status_bits, expected_status_bits)) {
 		/*
 		 * If timed out, which should never happen, let's at least
@@ -642,13 +634,13 @@
 
 	/* Verify that 'data available' is not asseretd any more. */
 	read_tpm_sts(&status);
-	if ((status & expected_status_bits) != sts_valid) {
+	if ((status & expected_status_bits) != TPM_STS_VALID) {
 		printk(BIOS_ERR, "unexpected final status %#x\n", status);
 		return 0;
 	}
 
 	/* Move the TPM back to idle state. */
-	write_tpm_sts(command_ready);
+	write_tpm_sts(TPM_STS_COMMAND_READY);
 
 	return payload_size;
 }
diff --git a/src/include/tpm.h b/src/include/tpm.h
index bd85b43..32a44c1 100644
--- a/src/include/tpm.h
+++ b/src/include/tpm.h
@@ -19,6 +19,32 @@
 #include <stddef.h>
 #include <stdint.h>
 
+enum tis_access {
+	TPM_ACCESS_VALID = (1 << 7),
+	TPM_ACCESS_ACTIVE_LOCALITY = (1 << 5),
+	TPM_ACCESS_REQUEST_PENDING = (1 << 2),
+	TPM_ACCESS_REQUEST_USE = (1 << 1),
+	TPM_ACCESS_ESTABLISHMENT = (1 << 0),
+};
+
+enum tis_status {
+	TPM_STS_FAMILY_SHIFT = 26,
+	TPM_STS_FAMILY_MASK = (0x3 << TPM_STS_FAMILY_SHIFT),
+	TPM_STS_FAMILY_TPM_2_0 = (1 << TPM_STS_FAMILY_SHIFT),
+	TPM_STS_FAMILY_TPM_1_2 = (0 << TPM_STS_FAMILY_SHIFT),
+	TPM_STS_RESET_ESTABLISHMENT = (1 << 25),
+	TPM_STS_COMMAND_CANCEL = (1 << 24),
+	TPM_STS_BURST_COUNT_SHIFT = 8,
+	TPM_STS_BURST_COUNT_MASK = (0xFFFF << TPM_STS_BURST_COUNT_SHIFT),
+	TPM_STS_VALID = (1 << 7),
+	TPM_STS_COMMAND_READY = (1 << 6),
+	TPM_STS_GO = (1 << 5),
+	TPM_STS_DATA_AVAIL = (1 << 4),
+	TPM_STS_DATA_EXPECT = (1 << 3),
+	TPM_STS_SELF_TEST_DONE = (1 << 2),
+	TPM_STS_RESPONSE_RETRY = (1 << 1),
+};
+
 /*
  * tis_init()
  *

-- 
To view, visit https://review.coreboot.org/19213
To unsubscribe, visit https://review.coreboot.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I11bf3e8b6e1f50b7868c9fe4394a858488367287
Gerrit-PatchSet: 5
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Owner: Furquan Shaikh <furquan at google.com>
Gerrit-Reviewer: Aaron Durbin <adurbin at chromium.org>
Gerrit-Reviewer: Duncan Laurie <dlaurie at chromium.org>
Gerrit-Reviewer: Furquan Shaikh <furquan at google.com>
Gerrit-Reviewer: Paul Menzel <paulepanter at users.sourceforge.net>
Gerrit-Reviewer: Philipp Deppenwiese <zaolin.daisuki at gmail.com>
Gerrit-Reviewer: build bot (Jenkins)



More information about the coreboot-gerrit mailing list