drivers/nvmem/layouts/sl28vpd.c

Source file repositories/reference/linux-study-clean/drivers/nvmem/layouts/sl28vpd.c

File Facts

System
Linux kernel
Corpus path
drivers/nvmem/layouts/sl28vpd.c
Extension
.c
Size
3756 bytes
Lines
170
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 sl28vpd_header {
	u8 magic;
	u8 version;
} __packed;

struct sl28vpd_v1 {
	struct sl28vpd_header header;
	char serial_number[15];
	u8 base_mac_address[ETH_ALEN];
	u8 crc8;
} __packed;

static int sl28vpd_mac_address_pp(void *priv, const char *id, int index,
				  unsigned int offset, void *buf,
				  size_t bytes)
{
	if (bytes != ETH_ALEN)
		return -EINVAL;

	if (index < 0)
		return -EINVAL;

	if (!is_valid_ether_addr(buf))
		return -EINVAL;

	eth_addr_add(buf, index);

	return 0;
}

static const struct nvmem_cell_info sl28vpd_v1_entries[] = {
	{
		.name = "serial-number",
		.offset = offsetof(struct sl28vpd_v1, serial_number),
		.bytes = sizeof_field(struct sl28vpd_v1, serial_number),
	},
	{
		.name = "base-mac-address",
		.offset = offsetof(struct sl28vpd_v1, base_mac_address),
		.bytes = sizeof_field(struct sl28vpd_v1, base_mac_address),
		.read_post_process = sl28vpd_mac_address_pp,
	},
};

static int sl28vpd_v1_check_crc(struct device *dev, struct nvmem_device *nvmem)
{
	struct sl28vpd_v1 data_v1;
	u8 table[CRC8_TABLE_SIZE];
	int ret;
	u8 crc;

	crc8_populate_msb(table, 0x07);

	ret = nvmem_device_read(nvmem, 0, sizeof(data_v1), &data_v1);
	if (ret < 0)
		return ret;
	else if (ret != sizeof(data_v1))
		return -EIO;

	crc = crc8(table, (void *)&data_v1, sizeof(data_v1) - 1, 0);

	if (crc != data_v1.crc8) {
		dev_err(dev,
			"Checksum is invalid (got %02x, expected %02x).\n",
			crc, data_v1.crc8);
		return -EINVAL;
	}

	return 0;
}

static int sl28vpd_add_cells(struct nvmem_layout *layout)
{
	struct nvmem_device *nvmem = layout->nvmem;
	struct device *dev = &layout->dev;
	const struct nvmem_cell_info *pinfo;
	struct nvmem_cell_info info = {0};
	struct device_node *layout_np;
	struct sl28vpd_header hdr;
	int ret, i;

	/* check header */
	ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr);
	if (ret < 0)
		return ret;
	else if (ret != sizeof(hdr))
		return -EIO;

	if (hdr.magic != SL28VPD_MAGIC) {
		dev_err(dev, "Invalid magic value (%02x)\n", hdr.magic);

Annotation

Implementation Notes