drivers/nvmem/brcm_nvram.c

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

File Facts

System
Linux kernel
Corpus path
drivers/nvmem/brcm_nvram.c
Extension
.c
Size
6148 bytes
Lines
260
Domain
Driver Families
Bucket
drivers/nvmem
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 brcm_nvram {
	struct device *dev;
	size_t nvmem_size;
	uint8_t *data;
	size_t data_len;
	uint8_t padding_byte;
	struct nvmem_cell_info *cells;
	int ncells;
};

struct brcm_nvram_header {
	char magic[4];
	__le32 len;
	__le32 crc_ver_init;	/* 0:7 crc, 8:15 ver, 16:31 sdram_init */
	__le32 config_refresh;	/* 0:15 sdram_config, 16:31 sdram_refresh */
	__le32 config_ncdl;	/* ncdl values for memc */
};

static int brcm_nvram_read(void *context, unsigned int offset, void *val,
			   size_t bytes)
{
	struct brcm_nvram *priv = context;
	size_t to_copy;

	if (offset + bytes > priv->data_len)
		to_copy = max_t(ssize_t, (ssize_t)priv->data_len - offset, 0);
	else
		to_copy = bytes;

	memcpy(val, priv->data + offset, to_copy);

	memset((uint8_t *)val + to_copy, priv->padding_byte, bytes - to_copy);

	return 0;
}

static int brcm_nvram_copy_data(struct brcm_nvram *priv, struct platform_device *pdev)
{
	struct resource *res;
	void __iomem *base;

	base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
	if (IS_ERR(base))
		return PTR_ERR(base);

	priv->nvmem_size = resource_size(res);

	priv->padding_byte = readb(base + priv->nvmem_size - 1);
	for (priv->data_len = priv->nvmem_size;
	     priv->data_len;
	     priv->data_len--) {
		if (readb(base + priv->data_len - 1) != priv->padding_byte)
			break;
	}
	WARN(priv->data_len > SZ_128K, "Unexpected (big) NVRAM size: %zu B\n", priv->data_len);

	priv->data = devm_kzalloc(priv->dev, priv->data_len, GFP_KERNEL);
	if (!priv->data)
		return -ENOMEM;

	memcpy_fromio(priv->data, base, priv->data_len);

	bcm47xx_nvram_init_from_iomem(base, priv->data_len);

	return 0;
}

static int brcm_nvram_read_post_process_macaddr(void *context, const char *id, int index,
						unsigned int offset, void *buf, size_t bytes)
{
	u8 mac[ETH_ALEN];

	if (bytes != MAC_ADDR_STR_LEN)
		return -EINVAL;

	if (!mac_pton(buf, mac))
		return -EINVAL;

	if (index)
		eth_addr_add(mac, index);

	ether_addr_copy(buf, mac);

	return 0;
}

static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data,
				size_t len)
{
	struct device *dev = priv->dev;

Annotation

Implementation Notes