drivers/char/tpm/tpm_crb.c

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

File Facts

System
Linux kernel
Corpus path
drivers/char/tpm/tpm_crb.c
Extension
.c
Size
23180 bytes
Lines
936
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 crb_regs_head {
	u32 loc_state;
	u32 reserved1;
	u32 loc_ctrl;
	u32 loc_sts;
	u8 reserved2[32];
	u64 intf_id;
	u64 ctrl_ext;
} __packed;

struct crb_regs_tail {
	u32 ctrl_req;
	u32 ctrl_sts;
	u32 ctrl_cancel;
	u32 ctrl_start;
	u32 ctrl_int_enable;
	u32 ctrl_int_sts;
	u32 ctrl_cmd_size;
	u32 ctrl_cmd_pa_low;
	u32 ctrl_cmd_pa_high;
	u32 ctrl_rsp_size;
	u64 ctrl_rsp_pa;
} __packed;

enum crb_status {
	CRB_DRV_STS_COMPLETE	= BIT(0),
};

struct crb_priv {
	u32 sm;
	const char *hid;
	struct crb_regs_head __iomem *regs_h;
	struct crb_regs_tail __iomem *regs_t;
	u8 __iomem *cmd;
	u8 __iomem *rsp;
	u32 cmd_size;
	u32 smc_func_id;
	u32 __iomem *pluton_start_addr;
	u32 __iomem *pluton_reply_addr;
	u8 ffa_flags;
	u8 ffa_attributes;
};

struct tpm2_crb_smc {
	u32 interrupt;
	u8 interrupt_flags;
	u8 op_flags;
	u16 reserved2;
	u32 smc_func_id;
};

/* CRB over FFA start method parameters in TCG2 ACPI table */
struct tpm2_crb_ffa {
	u8 flags;
	u8 attributes;
	u16 partition_id;
	u8 reserved[8];
};

struct tpm2_crb_pluton {
	u64 start_addr;
	u64 reply_addr;
};

/*
 * Returns true if the start method supports idle.
 */
static inline bool tpm_crb_has_idle(u32 start_method)
{
	return !(start_method == ACPI_TPM2_START_METHOD ||
	       start_method == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD ||
	       start_method == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC);
}

static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
				unsigned long timeout)
{
	ktime_t start;
	ktime_t stop;

	start = ktime_get();
	stop = ktime_add(start, ms_to_ktime(timeout));

	do {
		if ((ioread32(reg) & mask) == value)
			return true;

		usleep_range(50, 100);
	} while (ktime_before(ktime_get(), stop));

Annotation

Implementation Notes