diff options
author | Furquan Shaikh <furquan@chromium.org> | 2017-04-07 13:26:01 -0700 |
---|---|---|
committer | Furquan Shaikh <furquan@google.com> | 2017-04-13 05:04:13 +0200 |
commit | 260b297a8969d7119d514272af7abacd12c8c42d (patch) | |
tree | 4e17674a8ad483059c66a74959c7f436c82ad61c /src/drivers | |
parent | bf6dfaefc2fd2f22e55e3227d8b023bcd992cae5 (diff) | |
download | coreboot-260b297a8969d7119d514272af7abacd12c8c42d.tar.xz |
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@chromium.org>
Reviewed-on: https://review.coreboot.org/19213
Tested-by: build bot (Jenkins)
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
Diffstat (limited to 'src/drivers')
-rw-r--r-- | src/drivers/i2c/tpm/cr50.c | 1 | ||||
-rw-r--r-- | src/drivers/i2c/tpm/tpm.c | 1 | ||||
-rw-r--r-- | src/drivers/i2c/tpm/tpm.h | 15 | ||||
-rw-r--r-- | src/drivers/spi/tpm/tpm.c | 122 |
4 files changed, 59 insertions, 80 deletions
diff --git a/src/drivers/i2c/tpm/cr50.c b/src/drivers/i2c/tpm/cr50.c index 42c82d6fec..ce30bf1b7c 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 e804d6fc60..5350695922 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 3a9a2ab949..e511e0df22 100644 --- a/src/drivers/i2c/tpm/tpm.h +++ b/src/drivers/i2c/tpm/tpm.h @@ -47,21 +47,6 @@ enum tpm_timeout { #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 1c5e5353ad..0b5a835837 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> @@ -48,35 +49,6 @@ static struct tpm2_info g_tpm_info CAR_GLOBAL; */ 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 * in section "6.4.6 Spi Bit Protocol". @@ -113,7 +85,7 @@ static int tpm_sync(void) { 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 @@ static uint32_t get_burst_count(void) 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 @@ int tpm2_init(struct spi_slave *spi_if) 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 @@ size_t tpm2_process_command(const void *tpm2_command, size_t command_size, } /* 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 @@ size_t tpm2_process_command(const void *tpm2_command, size_t command_size, 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 @@ size_t tpm2_process_command(const void *tpm2_command, size_t command_size, /* 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; } |