summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/g/i2cs.c13
-rw-r--r--chip/g/i2cs.h9
-rw-r--r--common/i2cs_tpm.c47
3 files changed, 48 insertions, 21 deletions
diff --git a/chip/g/i2cs.c b/chip/g/i2cs.c
index 5c54af9d9d..38668ac932 100644
--- a/chip/g/i2cs.c
+++ b/chip/g/i2cs.c
@@ -290,7 +290,7 @@ int i2cs_register_write_complete_handler(wr_complete_handler_f wc_handler)
return 0;
}
-size_t i2cs_get_read_fifo_buffer_depth(void)
+size_t i2cs_zero_read_fifo_buffer_depth(void)
{
uint32_t hw_read_pointer;
size_t depth;
@@ -303,6 +303,15 @@ size_t i2cs_get_read_fifo_buffer_depth(void)
hw_read_pointer = GREAD(I2CS, READ_PTR) >> 3;
/* Determine the number of bytes buffered in the HW fifo */
depth = (last_read_pointer - hw_read_pointer) & REGISTER_FILE_MASK;
-
+ /*
+ * If queue depth is not zero, force it to 0 by adjusting
+ * last_read_pointer to where the hw read pointer is.
+ */
+ if (depth)
+ last_read_pointer = (uint16_t)hw_read_pointer;
+ /*
+ * Return number of bytes queued when this funciton is called so it can
+ * be tracked or logged by caller if desired.
+ */
return depth;
}
diff --git a/chip/g/i2cs.h b/chip/g/i2cs.h
index 76e8117be0..809e4127a0 100644
--- a/chip/g/i2cs.h
+++ b/chip/g/i2cs.h
@@ -31,11 +31,14 @@ void i2cs_post_read_data(uint8_t byte_to_read);
void i2cs_set_pinmux(void);
/*
- * Determine the number of bytes currently buffered in the I2CS READ fifo. This
+ * Ensure no bytes are currently buffered in the I2CS READ fifo. This
* value is calculated by finding the difference between read pointer that's
- * used by FW to add bytes to the HW fifo and the HW's read pointer.
+ * used by FW to add bytes to the HW fifo and the current value of the
+ * I2CS_READ_PTR register.
+ *
+ * @returns: the number of bytes buffered when the function is called
*/
-size_t i2cs_get_read_fifo_buffer_depth(void);
+size_t i2cs_zero_read_fifo_buffer_depth(void);
/*
* Write buffer of data into the I2CS HW read fifo. The function will operate a
diff --git a/common/i2cs_tpm.c b/common/i2cs_tpm.c
index 9b41f3c9ec..274e6b6ba0 100644
--- a/common/i2cs_tpm.c
+++ b/common/i2cs_tpm.c
@@ -79,6 +79,9 @@ static const struct i2c_tpm_reg_map i2c_to_tpm[] = {
{0xf, 0, 0xf90}, /* TPM_FW_VER */
};
+/* Used to track number of times i2cs hw read fifo was adjusted */
+static uint32_t i2cs_fifo_adjust_count;
+
static void process_read_access(uint16_t reg_size,
uint16_t tpm_reg, uint8_t *data)
{
@@ -92,6 +95,15 @@ static void process_read_access(uint16_t reg_size,
if (reg_size == 1 || reg_size == 4) {
/* Always read regsize number of bytes */
tpm_register_get(tpm_reg, reg_value, reg_size);
+ /*
+ * For 1 or 4 byte register reads there should not be any data
+ * buffered in the i2cs hw read fifo. This function will check
+ * the current fifo queue depth and if non-zero, will adjust the
+ * fw pointer to force it to 0.
+ */
+ if (i2cs_zero_read_fifo_buffer_depth())
+ /* Count each instance that fifo was adjusted */
+ i2cs_fifo_adjust_count++;
for (i = 0; i < reg_size; i++)
i2cs_post_read_data(reg_value[i]);
return;
@@ -105,22 +117,6 @@ static void process_read_access(uint16_t reg_size,
reg_size = tpm_get_burst_size();
/*
- * For TPM fifo reads, if there is already data pending in the I2CS hw
- * fifo, then don't read any more TPM fifo data until the I2CS hw fifo
- * has been fully drained.
- *
- * The Host will only read only enough data to extract the full TPM
- * message length. However, Cr50 will fill the I2CS hw fifo with
- * 'burstsize' amount of bytes. The 2nd fifo access for a given TPM
- * repsonse by the Host will extract the queued up data. Following
- * this, the Host will then read 'burstcount' amount of data for
- * subsequent fifo accesses until the response has been fully read.
- */
- if (i2cs_get_read_fifo_buffer_depth())
- /* Data is already in the queue, just return */
- return;
-
- /*
* Now, this is a hack, but we are short on SRAM, so let's reuse the
* receive buffer for the FIFO data sotrage. We know that the ISR has
* a 64 byte buffer were it moves received data.
@@ -226,5 +222,24 @@ static void i2cs_if_register(void)
return;
tpm_register_interface(i2cs_tpm_enable);
+ i2cs_fifo_adjust_count = 0;
}
DECLARE_HOOK(HOOK_INIT, i2cs_if_register, HOOK_PRIO_LAST);
+
+static int command_i2cs(int argc, char **argv)
+{
+ ccprintf("fifo adjust count = %d\n", i2cs_fifo_adjust_count);
+ if (argc < 2)
+ return EC_SUCCESS;
+
+ if (!strcasecmp(argv[1], "rst")) {
+ i2cs_fifo_adjust_count = 0;
+ ccprintf("fifo adjust count reset to 0\n");
+ } else
+ return EC_ERROR_PARAM1;
+
+ return EC_SUCCESS;
+}
+DECLARE_SAFE_CONSOLE_COMMAND(i2cs, command_i2cs,
+ "rst",
+ "Display fifo adjust count");