drivers/char/tpm/tpm_tis_i2c_cr50.c

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

File Facts

System
Linux kernel
Corpus path
drivers/char/tpm/tpm_tis_i2c_cr50.c
Extension
.c
Size
21125 bytes
Lines
838
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 tpm_i2c_cr50_priv_data {
	int irq;
	struct completion tpm_ready;
	u8 buf[TPM_CR50_MAX_BUFSIZE];
};

/**
 * tpm_cr50_i2c_int_handler() - cr50 interrupt handler.
 * @dummy:	Unused parameter.
 * @tpm_info:	TPM chip information.
 *
 * The cr50 interrupt handler signals waiting threads that the
 * interrupt has been asserted. It does not do any interrupt triggered
 * processing but is instead used to avoid fixed delays.
 *
 * Return:
 *	IRQ_HANDLED signifies irq was handled by this device.
 */
static irqreturn_t tpm_cr50_i2c_int_handler(int dummy, void *tpm_info)
{
	struct tpm_chip *chip = tpm_info;
	struct tpm_i2c_cr50_priv_data *priv = dev_get_drvdata(&chip->dev);

	complete(&priv->tpm_ready);

	return IRQ_HANDLED;
}

/**
 * tpm_cr50_i2c_wait_tpm_ready() - Wait for tpm to signal ready.
 * @chip: A TPM chip.
 *
 * Wait for completion interrupt if available, otherwise use a fixed
 * delay for the TPM to be ready.
 *
 * Return:
 * - 0:		Success.
 * - -errno:	A POSIX error code.
 */
static int tpm_cr50_i2c_wait_tpm_ready(struct tpm_chip *chip)
{
	struct tpm_i2c_cr50_priv_data *priv = dev_get_drvdata(&chip->dev);

	/* Use a safe fixed delay if interrupt is not supported */
	if (priv->irq <= 0) {
		msleep(TPM_CR50_TIMEOUT_NOIRQ_MS);
		return 0;
	}

	/* Wait for interrupt to indicate TPM is ready to respond */
	if (!wait_for_completion_timeout(&priv->tpm_ready, chip->timeout_a)) {
		dev_warn(&chip->dev, "Timeout waiting for TPM ready\n");
		return -ETIMEDOUT;
	}

	return 0;
}

/**
 * tpm_cr50_i2c_enable_tpm_irq() - Enable TPM irq.
 * @chip: A TPM chip.
 */
static void tpm_cr50_i2c_enable_tpm_irq(struct tpm_chip *chip)
{
	struct tpm_i2c_cr50_priv_data *priv = dev_get_drvdata(&chip->dev);

	if (priv->irq > 0) {
		reinit_completion(&priv->tpm_ready);
		enable_irq(priv->irq);
	}
}

/**
 * tpm_cr50_i2c_disable_tpm_irq() - Disable TPM irq.
 * @chip: A TPM chip.
 */
static void tpm_cr50_i2c_disable_tpm_irq(struct tpm_chip *chip)
{
	struct tpm_i2c_cr50_priv_data *priv = dev_get_drvdata(&chip->dev);

	if (priv->irq > 0)
		disable_irq(priv->irq);
}

/**
 * tpm_cr50_i2c_transfer_message() - Transfer a message over i2c.
 * @dev:	Device information.
 * @adapter:	I2C adapter.
 * @msg:	Message to transfer.
 *

Annotation

Implementation Notes