From cd5953d9191d508379792b3b09f00f307667984e Mon Sep 17 00:00:00 2001 From: Claudio Carvalho Date: Mon, 28 Nov 2016 01:08:05 -0200 Subject: tpm_i2c_nuvoton: isolate the code that handles the TPM_TIMEOUT_D timeout TPM_TIMEOUT_D timeout is only related to burst_count polling. This moves the burstCount polling code to tpm_read_burst_count() in order to isolate the code that is related to TPM_TIMEOUT_D. Signed-off-by: Claudio Carvalho Signed-off-by: Stewart Smith --- libstb/drivers/tpm_i2c_nuvoton.c | 219 +++++++++++++++++---------------------- 1 file changed, 95 insertions(+), 124 deletions(-) (limited to 'libstb') diff --git a/libstb/drivers/tpm_i2c_nuvoton.c b/libstb/drivers/tpm_i2c_nuvoton.c index 05a90fc..eb96f5e 100644 --- a/libstb/drivers/tpm_i2c_nuvoton.c +++ b/libstb/drivers/tpm_i2c_nuvoton.c @@ -217,19 +217,51 @@ static int tpm_poll_for_data_avail(void) static int tpm_read_burst_count(uint8_t* burst_count) { - int rc = 0; - /* In i2C, burstCount is 1 byte */ - rc = tpm_status_read_byte(TPM_BURST_COUNT, burst_count); - DBG("---- burst_count=%d rc=%d\n", *burst_count, rc); - if (rc < 0) - *burst_count = 0; - return rc; + int rc, delay; + uint8_t bc; + + delay = 0; + *burst_count = 0; + + do { + /* In i2C, burstCount is 1 byte */ + rc = tpm_status_read_byte(TPM_BURST_COUNT, &bc); + if (rc == 0 && bc > 0) { + DBG("---- burst_count=%d, delay=%d/%d\n", + delay, TPM_TIMEOUT_D); + *burst_count = bc; + return 0; + } + if (rc < 0) { + /** + * @fwts-label TPMReadBurstCount + * @fwts-advice Either the tpm device or the tpm-i2c + * interface doesn't seem to be working properly. Check + * the return code (rc) for further details. + */ + prlog(PR_ERR, "NUVOTON: fail to read sts.burstCount, " + "rc=%d\n", rc); + return STB_DRIVER_ERROR; + } + time_wait_ms(TPM_TIMEOUT_INTERVAL); + delay += TPM_TIMEOUT_INTERVAL; + + } while (delay < TPM_TIMEOUT_D); + + /** + * @fwts-label TPMBurstCountTimeout + * @fwts-advice The burstcount bit of the tpm status register is + * taking longer to be settled. Either the wait time need to be + * increased or the TPM device is not functional. + */ + prlog(PR_ERR, "NUVOTON: timeout on sts.burstCount, delay=%d/%d\n", + delay, TPM_TIMEOUT_D); + return STB_TPM_TIMEOUT; } static int tpm_write_fifo(uint8_t* buf, size_t buflen) { uint8_t burst_count = 0; - int delay = 0; int rc; size_t curByte = 0; uint8_t* bytePtr = buf; @@ -244,14 +276,8 @@ static int tpm_write_fifo(uint8_t* buf, size_t buflen) do { rc = tpm_read_burst_count(&burst_count); - if (rc < 0) { + if (rc < 0) return rc; - } else if (burst_count == 0) { - /* Need to delay to allow the TPM time */ - time_wait_ms(TPM_TIMEOUT_INTERVAL); - delay += TPM_TIMEOUT_INTERVAL; - continue; - } /* * Send in some data */ @@ -263,11 +289,8 @@ static int tpm_write_fifo(uint8_t* buf, size_t buflen) SMBUS_WRITE, TPM_DATA_FIFO_W, 1, curBytePtr, tx_len); curByte += tx_len; - DBG("%s write FIFO sent %zd bytes." - " burstcount polling delay=%d/%d, rc=%d\n", - (rc) ? "!!!!" : "----", curByte, delay, - TPM_TIMEOUT_D, rc); - delay = 0; + DBG("%s write FIFO sent %zd bytes, rc=%d\n", + (rc) ? "!!!!" : "----", curByte, TPM_TIMEOUT_D, rc); if (rc < 0) return rc; @@ -281,51 +304,23 @@ static int tpm_write_fifo(uint8_t* buf, size_t buflen) prlog(PR_ERR, "TPM: write FIFO overflow1\n"); return STB_TPM_OVERFLOW; } - /* Everything but the last byte sent? */ - if (curByte >= length) - break; - } while (delay < TPM_TIMEOUT_D); + } while (curByte < length); - if (delay < TPM_TIMEOUT_D) { - /* - * Send the final byte - */ - delay = 0; - do { - rc = tpm_read_burst_count(&burst_count); - if (rc < 0) { - return rc; - } else if (burst_count == 0) { - /* Need to delay to allow the TPM time */ - time_wait_ms(TPM_TIMEOUT_INTERVAL); - delay += TPM_TIMEOUT_INTERVAL; - continue; - } - curBytePtr = &(bytePtr[curByte]); - rc = tpm_i2c_request_send(tpm_device->bus_id, - tpm_device->xscom_base, - SMBUS_WRITE, - TPM_DATA_FIFO_W, 1, - curBytePtr, 1); - DBG("%s write FIFO sent last byte, delay=%d/%d," - " rc=%d\n", - (rc) ? "!!!!" : "----", delay, - TPM_TIMEOUT_D, rc); - break; - } while (delay < TPM_TIMEOUT_D); - } + /* + * Send the final byte + */ + rc = tpm_read_burst_count(&burst_count); + if (rc < 0) + return rc; + curBytePtr = &(bytePtr[curByte]); + rc = tpm_i2c_request_send(tpm_device->bus_id, + tpm_device->xscom_base, + SMBUS_WRITE, + TPM_DATA_FIFO_W, 1, + curBytePtr, 1); + DBG("%s write FIFO sent last byte, rc=%d\n", + (rc) ? "!!!!" : "----", TPM_TIMEOUT_D, rc); - if (delay >= TPM_TIMEOUT_D) { - /** - * @fwts-label TPMWriteBurstcountBitTimeout - * @fwts-advice The burstcount bit of the tpm status register is - * taking longer to be settled. Either the wait time need to be - * increased or the TPM device is not functional. - */ - prlog(PR_ERR, "TPM: write FIFO, burstcount polling timeout." - " delay=%d/%d\n", delay, TPM_TIMEOUT_D); - return STB_TPM_TIMEOUT; - } if (rc == 0) { if (tpm_is_expecting(&rc)) { /** @@ -346,75 +341,51 @@ static int tpm_read_fifo(uint8_t* buf, size_t* buflen) { int rc; uint8_t burst_count; - int delay = 0; size_t curByte = 0; uint8_t* bytePtr = (uint8_t*)buf; uint8_t* curBytePtr = NULL; rc = tpm_poll_for_data_avail(); + if (rc < 0) + goto error; - if (rc == 0) { - do { - rc = tpm_read_burst_count(&burst_count); - if (rc < 0) { - break; - } else if (burst_count == 0) { - /* Need to delay to allow the TPM time */ - time_wait_ms(TPM_TIMEOUT_INTERVAL); - delay += TPM_TIMEOUT_INTERVAL; - continue; - } - /* Buffer overflow check */ - if (curByte + burst_count > *buflen) - { - /** - * @fwts-label TPMReadFifoOverflow1 - * @fwts-advice The read from TPM FIFO overflowed. It is - * expecting more data even though we think we are done. - * This indicates a bug in the TPM device driver. - */ - prlog(PR_ERR, "TPM: read FIFO overflow1. delay %d/%d\n", - delay, TPM_TIMEOUT_D); - rc = STB_TPM_OVERFLOW; - } - /* - * Read some data + do { + rc = tpm_read_burst_count(&burst_count); + if (rc < 0) + goto error; + /* Buffer overflow check */ + if (curByte + burst_count > *buflen) + { + /** + * @fwts-label TPMReadFifoOverflow1 + * @fwts-advice The read from TPM FIFO overflowed. It is + * expecting more data even though we think we are done. + * This indicates a bug in the TPM device driver. */ - curBytePtr = &(bytePtr[curByte]); - rc = tpm_i2c_request_send(tpm_device->bus_id, - tpm_device->xscom_base, - SMBUS_READ, - TPM_DATA_FIFO_R, 1, - curBytePtr, burst_count); - curByte += burst_count; - DBG("%s read FIFO. received %zd bytes. burstcount" - " polling delay=%d/%d, rc=%d\n", - (rc) ? "!!!!" : "----", curByte, delay, - TPM_TIMEOUT_D, rc); - delay = 0; - if (rc < 0) - break; - if (!tpm_is_data_avail(&rc)) - break; - } while (delay < TPM_TIMEOUT_D); - } - - if (rc == 0 && delay >= TPM_TIMEOUT_D) { - /** - * @fwts-label TPMReadBurstcountBitTimeout - * @fwts-advice The burstcount bit of the tpm status register is - * taking longer to be settled. Either the wait time needs to be - * increased or the TPM device is not functional. + prlog(PR_ERR, "TPM: read FIFO overflow1\n"); + rc = STB_TPM_OVERFLOW; + } + /* + * Read some data */ - prlog(PR_ERR, "TPM: read FIFO, burstcount polling timeout." - " delay=%d/%d\n", - delay, TPM_TIMEOUT_D); - return STB_TPM_TIMEOUT; - } - if (rc == 0) - *buflen = curByte; - else - *buflen = 0; + curBytePtr = &(bytePtr[curByte]); + rc = tpm_i2c_request_send(tpm_device->bus_id, + tpm_device->xscom_base, + SMBUS_READ, + TPM_DATA_FIFO_R, 1, + curBytePtr, burst_count); + curByte += burst_count; + DBG("%s read FIFO. received %zd bytes, rc=%d\n", + (rc) ? "!!!!" : "----", curByte, rc); + if (rc < 0) + goto error; + } while (tpm_is_data_avail(&rc)); + + *buflen = curByte; + return 0; + +error: + *buflen = 0; return rc; } -- cgit v1.1