static int i2c_nuvoton_send()

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;
}