drivers/char/tpm/tpm_i2c_atmel.c
Source file repositories/reference/linux-study-clean/drivers/char/tpm/tpm_i2c_atmel.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/char/tpm/tpm_i2c_atmel.c- Extension
.c- Size
- 6026 bytes
- Lines
- 233
- 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.
- 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.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/init.hlinux/module.hlinux/moduleparam.hlinux/slab.hlinux/i2c.htpm.h
Detected Declarations
struct priv_datafunction i2c_atmel_sendfunction i2c_atmel_recvfunction i2c_atmel_cancelfunction i2c_atmel_read_statusfunction i2c_atmel_req_canceledfunction i2c_atmel_probefunction i2c_atmel_remove
Annotated Snippet
struct priv_data {
size_t len;
/*
* This is the amount we read on the first try. 25 was chosen to fit a
* fair number of read responses in the buffer so a 2nd retry can be
* avoided in small message cases.
*/
u8 buffer[sizeof(struct tpm_header) + 25];
};
static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz,
size_t len)
{
struct priv_data *priv = dev_get_drvdata(&chip->dev);
struct i2c_client *client = to_i2c_client(chip->dev.parent);
s32 status;
priv->len = 0;
if (len <= 2)
return -EIO;
status = i2c_master_send(client, buf, len);
dev_dbg(&chip->dev,
"%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__,
(int)min_t(size_t, 64, len), buf, len, status);
if (status < 0)
return status;
/*
* The upper layer does not support incomplete sends.
*/
if (status != len)
return -E2BIG;
return 0;
}
static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{
struct priv_data *priv = dev_get_drvdata(&chip->dev);
struct i2c_client *client = to_i2c_client(chip->dev.parent);
struct tpm_header *hdr = (struct tpm_header *)priv->buffer;
u32 expected_len;
int rc;
if (priv->len == 0)
return -EIO;
/*
* Get the message size from the message header, if we didn't get the
* whole message in read_status then we need to re-read the
* message.
*/
expected_len = be32_to_cpu(hdr->length);
if (expected_len > count)
return -ENOMEM;
if (priv->len >= expected_len) {
dev_dbg(&chip->dev,
"%s early(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
(int)min_t(size_t, 64, expected_len), buf, count,
expected_len);
memcpy(buf, priv->buffer, expected_len);
return expected_len;
}
rc = i2c_master_recv(client, buf, expected_len);
dev_dbg(&chip->dev,
"%s reread(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
(int)min_t(size_t, 64, expected_len), buf, count,
expected_len);
return rc;
}
static void i2c_atmel_cancel(struct tpm_chip *chip)
{
dev_err(&chip->dev, "TPM operation cancellation was requested, but is not supported");
}
static u8 i2c_atmel_read_status(struct tpm_chip *chip)
{
struct priv_data *priv = dev_get_drvdata(&chip->dev);
struct i2c_client *client = to_i2c_client(chip->dev.parent);
int rc;
/*
* The TPM fails the I2C read until it is ready, so we do the entire
Annotation
- Immediate include surface: `linux/init.h`, `linux/module.h`, `linux/moduleparam.h`, `linux/slab.h`, `linux/i2c.h`, `tpm.h`.
- Detected declarations: `struct priv_data`, `function i2c_atmel_send`, `function i2c_atmel_recv`, `function i2c_atmel_cancel`, `function i2c_atmel_read_status`, `function i2c_atmel_req_canceled`, `function i2c_atmel_probe`, `function i2c_atmel_remove`.
- Atlas domain: Driver Families / drivers/char.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.