drivers/char/tpm/st33zp24/spi.c

Source file repositories/reference/linux-study-clean/drivers/char/tpm/st33zp24/spi.c

File Facts

System
Linux kernel
Corpus path
drivers/char/tpm/st33zp24/spi.c
Extension
.c
Size
8130 bytes
Lines
291
Domain
Driver Families
Bucket
drivers/char
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct st33zp24_spi_phy {
	struct spi_device *spi_device;

	u8 tx_buf[ST33ZP24_SPI_BUFFER_SIZE];
	u8 rx_buf[ST33ZP24_SPI_BUFFER_SIZE];

	int latency;
};

static int st33zp24_status_to_errno(u8 code)
{
	switch (code) {
	case ST33ZP24_OK:
		return 0;
	case ST33ZP24_UNDEFINED_ERR:
	case ST33ZP24_BADLOCALITY:
	case ST33ZP24_TISREGISTER_UNKNOWN:
	case ST33ZP24_LOCALITY_NOT_ACTIVATED:
	case ST33ZP24_HASH_END_BEFORE_HASH_START:
	case ST33ZP24_BAD_COMMAND_ORDER:
	case ST33ZP24_UNEXPECTED_READ_FIFO:
	case ST33ZP24_UNEXPECTED_WRITE_FIFO:
	case ST33ZP24_CMDRDY_SET_WHEN_PROCESSING_HASH_END:
		return -EPROTO;
	case ST33ZP24_INCORECT_RECEIVED_LENGTH:
	case ST33ZP24_TPM_FIFO_OVERFLOW:
		return -EMSGSIZE;
	case ST33ZP24_DUMMY_BYTES:
		return -ENOSYS;
	}
	return code;
}

/*
 * st33zp24_spi_send
 * Send byte to the TIS register according to the ST33ZP24 SPI protocol.
 * @param: phy_id, the phy description
 * @param: tpm_register, the tpm tis register where the data should be written
 * @param: tpm_data, the tpm_data to write inside the tpm_register
 * @param: tpm_size, The length of the data
 * @return: should be zero if success else a negative error code.
 */
static int st33zp24_spi_send(void *phy_id, u8 tpm_register, u8 *tpm_data,
			     int tpm_size)
{
	int total_length = 0, ret = 0;
	struct st33zp24_spi_phy *phy = phy_id;
	struct spi_device *dev = phy->spi_device;
	struct spi_transfer spi_xfer = {
		.tx_buf = phy->tx_buf,
		.rx_buf = phy->rx_buf,
	};

	/* Pre-Header */
	phy->tx_buf[total_length++] = TPM_WRITE_DIRECTION | LOCALITY0;
	phy->tx_buf[total_length++] = tpm_register;

	if (tpm_size > 0 && tpm_register == TPM_DATA_FIFO) {
		phy->tx_buf[total_length++] = tpm_size >> 8;
		phy->tx_buf[total_length++] = tpm_size;
	}

	memcpy(&phy->tx_buf[total_length], tpm_data, tpm_size);
	total_length += tpm_size;

	memset(&phy->tx_buf[total_length], TPM_DUMMY_BYTE, phy->latency);

	spi_xfer.len = total_length + phy->latency;

	ret = spi_sync_transfer(dev, &spi_xfer, 1);
	if (ret == 0)
		ret = phy->rx_buf[total_length + phy->latency - 1];

	return st33zp24_status_to_errno(ret);
} /* st33zp24_spi_send() */

/*
 * st33zp24_spi_read8_recv
 * Recv byte from the TIS register according to the ST33ZP24 SPI protocol.
 * @param: phy_id, the phy description
 * @param: tpm_register, the tpm tis register where the data should be read
 * @param: tpm_data, the TPM response
 * @param: tpm_size, tpm TPM response size to read.
 * @return: should be zero if success else a negative error code.
 */
static int st33zp24_spi_read8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data,
				  int tpm_size)
{
	int total_length = 0, ret;
	struct st33zp24_spi_phy *phy = phy_id;

Annotation

Implementation Notes