in tpm/tpm_i2c_nuvoton.c [352:457]
static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
{
struct priv_data *priv = dev_get_drvdata(&chip->dev);
struct device *dev = chip->dev.parent;
struct i2c_client *client = to_i2c_client(dev);
u32 ordinal;
unsigned long duration;
size_t count = 0;
int burst_count, bytes2write, retries, rc = -EIO;
for (retries = 0; retries < TPM_RETRY; retries++) {
i2c_nuvoton_ready(chip);
if (i2c_nuvoton_wait_for_stat(chip, TPM_STS_COMMAND_READY,
TPM_STS_COMMAND_READY,
chip->timeout_b, NULL)) {
dev_err(dev, "%s() timeout on commandReady\n",
__func__);
rc = -EIO;
continue;
}
rc = 0;
while (count < len - 1) {
burst_count = i2c_nuvoton_get_burstcount(client,
chip);
if (burst_count < 0) {
dev_err(dev, "%s() fail get burstCount\n",
__func__);
rc = -EIO;
break;
}
bytes2write = min_t(size_t, burst_count,
len - 1 - count);
rc = i2c_nuvoton_write_buf(client, TPM_DATA_FIFO_W,
bytes2write, &buf[count]);
if (rc < 0) {
dev_err(dev, "%s() fail i2cWriteBuf\n",
__func__);
break;
}
dev_dbg(dev, "%s(%d):", __func__, bytes2write);
count += bytes2write;
rc = i2c_nuvoton_wait_for_stat(chip,
TPM_STS_VALID |
TPM_STS_EXPECT,
TPM_STS_VALID |
TPM_STS_EXPECT,
chip->timeout_c,
NULL);
if (rc < 0) {
dev_err(dev, "%s() timeout on Expect\n",
__func__);
rc = -ETIMEDOUT;
break;
}
}
if (rc < 0)
continue;
/* write last byte */
rc = i2c_nuvoton_write_buf(client, TPM_DATA_FIFO_W, 1,
&buf[count]);
if (rc < 0) {
dev_err(dev, "%s() fail to write last byte\n",
__func__);
rc = -EIO;
continue;
}
dev_dbg(dev, "%s(last): %02x", __func__, buf[count]);
rc = i2c_nuvoton_wait_for_stat(chip,
TPM_STS_VALID | TPM_STS_EXPECT,
TPM_STS_VALID,
chip->timeout_c, NULL);
if (rc) {
dev_err(dev, "%s() timeout on Expect to clear\n",
__func__);
rc = -ETIMEDOUT;
continue;
}
break;
}
if (rc < 0) {
/* retries == TPM_RETRY */
i2c_nuvoton_ready(chip);
return rc;
}
/* execute the TPM command */
rc = i2c_nuvoton_write_status(client, TPM_STS_GO);
if (rc < 0) {
dev_err(dev, "%s() fail to write Go\n", __func__);
i2c_nuvoton_ready(chip);
return rc;
}
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
duration = tpm_calc_ordinal_duration(chip, ordinal);
rc = i2c_nuvoton_wait_for_data_avail(chip, duration, &priv->read_queue);
if (rc) {
dev_err(dev, "%s() timeout command duration %ld\n",
__func__, duration);
i2c_nuvoton_ready(chip);
return rc;
}
dev_dbg(dev, "%s() -> %zd\n", __func__, len);
return 0;
}