drivers/misc/eeprom/at25.c
Source file repositories/reference/linux-study-clean/drivers/misc/eeprom/at25.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/misc/eeprom/at25.c- Extension
.c- Size
- 15000 bytes
- Lines
- 586
- Domain
- Driver Families
- Bucket
- drivers/misc
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- 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/bits.hlinux/cleanup.hlinux/delay.hlinux/device.hlinux/iopoll.hlinux/kernel.hlinux/module.hlinux/property.hlinux/sched.hlinux/slab.hlinux/spi/eeprom.hlinux/spi/spi.hlinux/spi/spi-mem.hlinux/nvmem-provider.h
Detected Declarations
struct at25_datafunction at25_instrfunction at25_ee_readfunction fm25_aux_readfunction sernum_showfunction jedec_id_showfunction at25_wait_readyfunction at25_ee_writefunction at25_fw_to_chipfunction at25_fram_to_chipfunction at25_probe
Annotated Snippet
struct at25_data {
struct spi_eeprom chip;
struct spi_mem *spimem;
struct mutex lock;
unsigned addrlen;
struct nvmem_config nvmem_config;
struct nvmem_device *nvmem;
u8 sernum[FM25_SN_LEN];
u8 id[FM25_MAX_ID_LEN];
u8 id_len;
};
#define AT25_WREN 0x06 /* latch the write enable */
#define AT25_WRDI 0x04 /* reset the write enable */
#define AT25_RDSR 0x05 /* read status register */
#define AT25_WRSR 0x01 /* write status register */
#define AT25_READ 0x03 /* read byte(s) */
#define AT25_WRITE 0x02 /* write byte(s)/sector */
#define FM25_SLEEP 0xb9 /* enter sleep mode */
#define FM25_RDID 0x9f /* read device ID */
#define FM25_RDSN 0xc3 /* read S/N */
#define AT25_SR_nRDY 0x01 /* nRDY = write-in-progress */
#define AT25_SR_WEN 0x02 /* write enable (latched) */
#define AT25_SR_BP0 0x04 /* BP for software writeprotect */
#define AT25_SR_BP1 0x08
#define AT25_SR_WPEN 0x80 /* writeprotect enable */
#define AT25_INSTR_BIT3 0x08 /* additional address bit in instr */
/*
* Specs often allow 5ms for a page write, sometimes 20ms;
* it's important to recover from write timeouts.
*/
#define EE_TIMEOUT 25
/*-------------------------------------------------------------------------*/
#define io_limit PAGE_SIZE /* bytes */
/* Handle the address MSB as part of instruction byte */
static u8 at25_instr(struct at25_data *at25, u8 instr, unsigned int off)
{
if (!(at25->chip.flags & EE_INSTR_BIT3_IS_ADDR))
return instr;
if (off < BIT(at25->addrlen * 8))
return instr;
return instr | AT25_INSTR_BIT3;
}
static int at25_ee_read(void *priv, unsigned int offset,
void *val, size_t count)
{
u8 *bounce __free(kfree) = kmalloc(min(count, io_limit), GFP_KERNEL);
struct at25_data *at25 = priv;
char *buf = val;
unsigned int msg_offset = offset;
size_t bytes_left = count;
size_t segment;
int status;
if (!bounce)
return -ENOMEM;
if (unlikely(offset >= at25->chip.byte_len))
return -EINVAL;
if ((offset + count) > at25->chip.byte_len)
count = at25->chip.byte_len - offset;
if (unlikely(!count))
return -EINVAL;
do {
struct spi_mem_op op;
segment = min(bytes_left, io_limit);
op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(at25_instr(at25, AT25_READ,
msg_offset), 1),
SPI_MEM_OP_ADDR(at25->addrlen, msg_offset, 1),
SPI_MEM_OP_NO_DUMMY,
SPI_MEM_OP_DATA_IN(segment, bounce, 1));
status = spi_mem_adjust_op_size(at25->spimem, &op);
if (status)
return status;
segment = op.data.nbytes;
mutex_lock(&at25->lock);
status = spi_mem_exec_op(at25->spimem, &op);
mutex_unlock(&at25->lock);
Annotation
- Immediate include surface: `linux/bits.h`, `linux/cleanup.h`, `linux/delay.h`, `linux/device.h`, `linux/iopoll.h`, `linux/kernel.h`, `linux/module.h`, `linux/property.h`.
- Detected declarations: `struct at25_data`, `function at25_instr`, `function at25_ee_read`, `function fm25_aux_read`, `function sernum_show`, `function jedec_id_show`, `function at25_wait_ready`, `function at25_ee_write`, `function at25_fw_to_chip`, `function at25_fram_to_chip`.
- Atlas domain: Driver Families / drivers/misc.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
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.