diff options
author | Duncan Laurie <dlaurie@chromium.org> | 2016-09-19 17:19:10 -0700 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2016-09-21 10:45:24 +0200 |
commit | f235a9b1b06a6374d473c9f610eb945cf4633c74 (patch) | |
tree | 83f3854ba4bead9f49ab588da5482ead43f2d64c /src/drivers/i2c/tpm/cr50.c | |
parent | d3920e71d61e76d4e8ae30bd8466d22b7bf3432c (diff) |
drivers/i2c/tpm/cr50: Improve data handling and function names
Unify the function names to be consistent throughout the driver
and improve the handling while waiting for data available and
data expected flags from the TPM.
BUG=chrome-os-partner:53336
Change-Id: Ie2dfb7ede1bcda0e77070df945c47c1428115907
Signed-off-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: https://review.coreboot.org/16668
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/drivers/i2c/tpm/cr50.c')
-rw-r--r-- | src/drivers/i2c/tpm/cr50.c | 93 |
1 files changed, 45 insertions, 48 deletions
diff --git a/src/drivers/i2c/tpm/cr50.c b/src/drivers/i2c/tpm/cr50.c index a3ff7814de..37f0881980 100644 --- a/src/drivers/i2c/tpm/cr50.c +++ b/src/drivers/i2c/tpm/cr50.c @@ -189,7 +189,7 @@ static int request_locality(struct tpm_chip *chip, int loc) } /* cr50 requires all 4 bytes of status register to be read */ -static uint8_t cr50_tis_i2c_status(struct tpm_chip *chip) +static uint8_t cr50_i2c_tis_status(struct tpm_chip *chip) { uint8_t buf[4]; if (cr50_i2c_read(chip, TPM_STS(chip->vendor.locality), @@ -201,7 +201,7 @@ static uint8_t cr50_tis_i2c_status(struct tpm_chip *chip) } /* cr50 requires all 4 bytes of status register to be written */ -static void cr50_tis_i2c_ready(struct tpm_chip *chip) +static void cr50_i2c_tis_ready(struct tpm_chip *chip) { uint8_t buf[4] = { TPM_STS_COMMAND_READY }; cr50_i2c_write(chip, TPM_STS(chip->vendor.locality), buf, sizeof(buf)); @@ -210,7 +210,7 @@ static void cr50_tis_i2c_ready(struct tpm_chip *chip) /* cr50 uses bytes 3:2 of status register for burst count and * all 4 bytes must be read */ -static int cr50_wait_burst_status(struct tpm_chip *chip, uint8_t mask, +static int cr50_i2c_wait_burststs(struct tpm_chip *chip, uint8_t mask, size_t *burst, int *status) { uint8_t buf[4]; @@ -240,28 +240,26 @@ static int cr50_wait_burst_status(struct tpm_chip *chip, uint8_t mask, return -1; } -static int cr50_tis_i2c_recv(struct tpm_chip *chip, uint8_t *buf, +static int cr50_i2c_tis_recv(struct tpm_chip *chip, uint8_t *buf, size_t buf_len) { size_t burstcnt, current, len, expected; uint8_t addr = TPM_DATA_FIFO(chip->vendor.locality); + uint8_t mask = TPM_STS_VALID | TPM_STS_DATA_AVAIL; int status; - int ret = -1; if (buf_len < TPM_HEADER_SIZE) - goto out; + goto out_err; - if (cr50_wait_burst_status(chip, TPM_STS_VALID, &burstcnt, &status) < 0) - goto out; - if (!(status & TPM_STS_DATA_AVAIL)) { + if (cr50_i2c_wait_burststs(chip, mask, &burstcnt, &status) < 0) { printk(BIOS_ERR, "%s: First chunk not available\n", __func__); - goto out; + goto out_err; } /* Read first chunk of burstcnt bytes */ if (cr50_i2c_read(chip, addr, buf, burstcnt) != 0) { printk(BIOS_ERR, "%s: Read failed\n", __func__); - goto out; + goto out_err; } /* Determine expected data in the return buffer */ @@ -269,45 +267,43 @@ static int cr50_tis_i2c_recv(struct tpm_chip *chip, uint8_t *buf, if (expected > buf_len) { printk(BIOS_ERR, "%s: Too much data: %zu > %zu\n", __func__, expected, buf_len); - goto out; + goto out_err; } /* Now read the rest of the data */ current = burstcnt; while (current < expected) { /* Read updated burst count and check status */ - if (cr50_wait_burst_status(chip, TPM_STS_VALID, - &burstcnt, &status) < 0) - goto out; - if (!(status & TPM_STS_DATA_AVAIL)) { - printk(BIOS_ERR, "%s: Data not available\n", __func__); - goto out; - } + if (cr50_i2c_wait_burststs(chip, mask, &burstcnt, &status) < 0) + goto out_err; len = min(burstcnt, expected - current); if (cr50_i2c_read(chip, addr, buf + current, len) != 0) { printk(BIOS_ERR, "%s: Read failed\n", __func__); - goto out; + goto out_err; } current += len; } /* Ensure TPM is done reading data */ - if (cr50_wait_burst_status(chip, TPM_STS_VALID, &burstcnt, &status) < 0) - goto out; + if (cr50_i2c_wait_burststs(chip, TPM_STS_VALID, &burstcnt, &status) < 0) + goto out_err; if (status & TPM_STS_DATA_AVAIL) { printk(BIOS_ERR, "%s: Data still available\n", __func__); - goto out; + goto out_err; } - ret = current; + return current; -out: - return ret; +out_err: + /* Abort current transaction if still pending */ + if (cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY) + cr50_i2c_tis_ready(chip); + return -1; } -static int cr50_tis_i2c_send(struct tpm_chip *chip, uint8_t *buf, size_t len) +static int cr50_i2c_tis_send(struct tpm_chip *chip, uint8_t *buf, size_t len) { int status; size_t burstcnt, limit, sent = 0; @@ -317,25 +313,26 @@ static int cr50_tis_i2c_send(struct tpm_chip *chip, uint8_t *buf, size_t len) stopwatch_init_msecs_expire(&sw, CR50_TIMEOUT_LONG_MS); /* Wait until TPM is ready for a command */ - while (!(cr50_tis_i2c_status(chip) & TPM_STS_COMMAND_READY)) { + while (!(cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY)) { if (stopwatch_expired(&sw)) { printk(BIOS_ERR, "%s: Command ready timeout\n", __func__); return -1; } - cr50_tis_i2c_ready(chip); + cr50_i2c_tis_ready(chip); } while (len > 0) { + uint8_t mask = TPM_STS_VALID; + + /* Wait for data if this is not the first chunk */ + if (sent > 0) + mask |= TPM_STS_DATA_EXPECT; + /* Read burst count and check status */ - if (cr50_wait_burst_status(chip, TPM_STS_VALID, - &burstcnt, &status) < 0) - goto out; - if (sent > 0 && !(status & TPM_STS_DATA_EXPECT)) { - printk(BIOS_ERR, "%s: Data not expected\n", __func__); - goto out; - } + if (cr50_i2c_wait_burststs(chip, mask, &burstcnt, &status) < 0) + goto out_err; /* Use burstcnt - 1 to account for the address byte * that is inserted by cr50_i2c_write() */ @@ -343,7 +340,7 @@ static int cr50_tis_i2c_send(struct tpm_chip *chip, uint8_t *buf, size_t len) if (cr50_i2c_write(chip, TPM_DATA_FIFO(chip->vendor.locality), &buf[sent], limit) != 0) { printk(BIOS_ERR, "%s: Write failed\n", __func__); - goto out; + goto out_err; } sent += limit; @@ -351,25 +348,25 @@ static int cr50_tis_i2c_send(struct tpm_chip *chip, uint8_t *buf, size_t len) } /* Ensure TPM is not expecting more data */ - if (cr50_wait_burst_status(chip, TPM_STS_VALID, &burstcnt, &status) < 0) - goto out; + if (cr50_i2c_wait_burststs(chip, TPM_STS_VALID, &burstcnt, &status) < 0) + goto out_err; if (status & TPM_STS_DATA_EXPECT) { printk(BIOS_ERR, "%s: Data still expected\n", __func__); - goto out; + goto out_err; } /* Start the TPM command */ if (cr50_i2c_write(chip, TPM_STS(chip->vendor.locality), tpm_go, sizeof(tpm_go)) < 0) { printk(BIOS_ERR, "%s: Start command failed\n", __func__); - goto out; + goto out_err; } return sent; -out: +out_err: /* Abort current transaction if still pending */ - if (cr50_tis_i2c_status(chip) & TPM_STS_COMMAND_READY) - cr50_tis_i2c_ready(chip); + if (cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY) + cr50_i2c_tis_ready(chip); return -1; } @@ -379,10 +376,10 @@ static void cr50_vendor_init(struct tpm_chip *chip) chip->vendor.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID; chip->vendor.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID; chip->vendor.req_canceled = TPM_STS_COMMAND_READY; - chip->vendor.status = &cr50_tis_i2c_status; - chip->vendor.recv = &cr50_tis_i2c_recv; - chip->vendor.send = &cr50_tis_i2c_send; - chip->vendor.cancel = &cr50_tis_i2c_ready; + chip->vendor.status = &cr50_i2c_tis_status; + chip->vendor.recv = &cr50_i2c_tis_recv; + chip->vendor.send = &cr50_i2c_tis_send; + chip->vendor.cancel = &cr50_i2c_tis_ready; } int tpm_vendor_probe(unsigned bus, uint32_t addr) |