drivers/nvmem/rave-sp-eeprom.c

Source file repositories/reference/linux-study-clean/drivers/nvmem/rave-sp-eeprom.c

File Facts

System
Linux kernel
Corpus path
drivers/nvmem/rave-sp-eeprom.c
Extension
.c
Size
9642 bytes
Lines
363
Domain
Driver Families
Bucket
drivers/nvmem
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 rave_sp_eeprom_page {
	u8  type;
	u8  success;
	u8  data[RAVE_SP_EEPROM_PAGE_SIZE];
} __packed;

/**
 * struct rave_sp_eeprom - RAVE SP EEPROM device
 *
 * @sp:			Pointer to parent RAVE SP device
 * @mutex:		Lock protecting access to EEPROM
 * @address:		EEPROM device address
 * @header_size:	Size of EEPROM command header for this device
 * @dev:		Pointer to corresponding struct device used for logging
 */
struct rave_sp_eeprom {
	struct rave_sp *sp;
	struct mutex mutex;
	u8 address;
	unsigned int header_size;
	struct device *dev;
};

/**
 * rave_sp_eeprom_io - Low-level part of EEPROM page access
 *
 * @eeprom:	EEPROM device to write to
 * @type:	EEPROM access type (read or write)
 * @idx:	number of the EEPROM page
 * @page:	Data to write or buffer to store result (via page->data)
 *
 * This function does all of the low-level work required to perform a
 * EEPROM access. This includes formatting correct command payload,
 * sending it and checking received results.
 *
 * Returns zero in case of success or negative error code in
 * case of failure.
 */
static int rave_sp_eeprom_io(struct rave_sp_eeprom *eeprom,
			     enum rave_sp_eeprom_access_type type,
			     u16 idx,
			     struct rave_sp_eeprom_page *page)
{
	const bool is_write = type == RAVE_SP_EEPROM_WRITE;
	const unsigned int data_size = is_write ? sizeof(page->data) : 0;
	const unsigned int cmd_size = eeprom->header_size + data_size;
	const unsigned int rsp_size =
		is_write ? sizeof(*page) - sizeof(page->data) : sizeof(*page);
	unsigned int offset = 0;
	u8 cmd[RAVE_SP_EEPROM_HEADER_MAX + sizeof(page->data)];
	int ret;

	if (WARN_ON(cmd_size > sizeof(cmd)))
		return -EINVAL;

	cmd[offset++] = eeprom->address;
	cmd[offset++] = 0;
	cmd[offset++] = type;
	cmd[offset++] = idx;

	/*
	 * If there's still room in this command's header it means we
	 * are talkin to EEPROM that uses 16-bit page numbers and we
	 * have to specify index's MSB in payload as well.
	 */
	if (offset < eeprom->header_size)
		cmd[offset++] = idx >> 8;
	/*
	 * Copy our data to write to command buffer first. In case of
	 * a read data_size should be zero and memcpy would become a
	 * no-op
	 */
	memcpy(&cmd[offset], page->data, data_size);

	ret = rave_sp_exec(eeprom->sp, cmd, cmd_size, page, rsp_size);
	if (ret)
		return ret;

	if (page->type != type)
		return -EPROTO;

	if (!page->success)
		return -EIO;

	return 0;
}

/**
 * rave_sp_eeprom_page_access - Access single EEPROM page
 *

Annotation

Implementation Notes