drivers/char/tpm/tpm_i2c_nuvoton.c

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

File Facts

System
Linux kernel
Corpus path
drivers/char/tpm/tpm_i2c_nuvoton.c
Extension
.c
Size
18514 bytes
Lines
661
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 priv_data {
	int irq;
	unsigned int intrs;
	wait_queue_head_t read_queue;
};

static s32 i2c_nuvoton_read_buf(struct i2c_client *client, u8 offset, u8 size,
				u8 *data)
{
	s32 status;

	status = i2c_smbus_read_i2c_block_data(client, offset, size, data);
	dev_dbg(&client->dev,
		"%s(offset=%u size=%u data=%*ph) -> sts=%d\n", __func__,
		offset, size, (int)size, data, status);
	return status;
}

static s32 i2c_nuvoton_write_buf(struct i2c_client *client, u8 offset, u8 size,
				 u8 *data)
{
	s32 status;

	status = i2c_smbus_write_i2c_block_data(client, offset, size, data);
	dev_dbg(&client->dev,
		"%s(offset=%u size=%u data=%*ph) -> sts=%d\n", __func__,
		offset, size, (int)size, data, status);
	return status;
}

#define TPM_STS_VALID          0x80
#define TPM_STS_COMMAND_READY  0x40
#define TPM_STS_GO             0x20
#define TPM_STS_DATA_AVAIL     0x10
#define TPM_STS_EXPECT         0x08
#define TPM_STS_RESPONSE_RETRY 0x02
#define TPM_STS_ERR_VAL        0x07    /* bit2...bit0 reads always 0 */

#define TPM_I2C_SHORT_TIMEOUT  750     /* ms */
#define TPM_I2C_LONG_TIMEOUT   2000    /* 2 sec */

/* read TPM_STS register */
static u8 i2c_nuvoton_read_status(struct tpm_chip *chip)
{
	struct i2c_client *client = to_i2c_client(chip->dev.parent);
	s32 status;
	u8 data;

	status = i2c_nuvoton_read_buf(client, TPM_STS, 1, &data);
	if (status <= 0) {
		dev_err(&chip->dev, "%s() error return %d\n", __func__,
			status);
		data = TPM_STS_ERR_VAL;
	}

	return data;
}

/* write byte to TPM_STS register */
static s32 i2c_nuvoton_write_status(struct i2c_client *client, u8 data)
{
	s32 status;
	int i;

	/* this causes the current command to be aborted */
	for (i = 0, status = -1; i < TPM_I2C_RETRY_COUNT && status < 0; i++) {
		status = i2c_nuvoton_write_buf(client, TPM_STS, 1, &data);
		if (status < 0)
			usleep_range(TPM_I2C_BUS_DELAY, TPM_I2C_BUS_DELAY
				     + TPM_I2C_DELAY_RANGE);
	}
	return status;
}

/* write commandReady to TPM_STS register */
static void i2c_nuvoton_ready(struct tpm_chip *chip)
{
	struct i2c_client *client = to_i2c_client(chip->dev.parent);
	s32 status;

	/* this causes the current command to be aborted */
	status = i2c_nuvoton_write_status(client, TPM_STS_COMMAND_READY);
	if (status < 0)
		dev_err(&chip->dev,
			"%s() fail to write TPM_STS.commandReady\n", __func__);
}

/* read burstCount field from TPM_STS register
 * return -1 on fail to read */
static int i2c_nuvoton_get_burstcount(struct i2c_client *client,

Annotation

Implementation Notes