| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- From 6e977eaa8280e957b87904b536661550f2a6b3e8 Mon Sep 17 00:00:00 2001
- From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
- Date: Fri, 25 Feb 2022 17:58:20 +0000
- Subject: [PATCH] nvmem: brcm_nvram: parse NVRAM content into NVMEM cells
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- NVRAM consist of header and NUL separated key-value pairs. Parse it and
- create NVMEM cell for every key-value entry.
- Signed-off-by: Rafał Miłecki <[email protected]>
- Signed-off-by: Srinivas Kandagatla <[email protected]>
- Link: https://lore.kernel.org/r/[email protected]
- Signed-off-by: Greg Kroah-Hartman <[email protected]>
- ---
- drivers/nvmem/brcm_nvram.c | 90 ++++++++++++++++++++++++++++++++++++++
- 1 file changed, 90 insertions(+)
- --- a/drivers/nvmem/brcm_nvram.c
- +++ b/drivers/nvmem/brcm_nvram.c
- @@ -6,12 +6,26 @@
- #include <linux/io.h>
- #include <linux/mod_devicetable.h>
- #include <linux/module.h>
- +#include <linux/nvmem-consumer.h>
- #include <linux/nvmem-provider.h>
- #include <linux/platform_device.h>
- +#include <linux/slab.h>
- +
- +#define NVRAM_MAGIC "FLSH"
-
- struct brcm_nvram {
- struct device *dev;
- void __iomem *base;
- + 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,
- @@ -26,6 +40,75 @@ static int brcm_nvram_read(void *context
- return 0;
- }
-
- +static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data,
- + size_t len)
- +{
- + struct device *dev = priv->dev;
- + char *var, *value, *eq;
- + int idx;
- +
- + priv->ncells = 0;
- + for (var = data + sizeof(struct brcm_nvram_header);
- + var < (char *)data + len && *var;
- + var += strlen(var) + 1) {
- + priv->ncells++;
- + }
- +
- + priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL);
- + if (!priv->cells)
- + return -ENOMEM;
- +
- + for (var = data + sizeof(struct brcm_nvram_header), idx = 0;
- + var < (char *)data + len && *var;
- + var = value + strlen(value) + 1, idx++) {
- + eq = strchr(var, '=');
- + if (!eq)
- + break;
- + *eq = '\0';
- + value = eq + 1;
- +
- + priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL);
- + if (!priv->cells[idx].name)
- + return -ENOMEM;
- + priv->cells[idx].offset = value - (char *)data;
- + priv->cells[idx].bytes = strlen(value);
- + }
- +
- + return 0;
- +}
- +
- +static int brcm_nvram_parse(struct brcm_nvram *priv)
- +{
- + struct device *dev = priv->dev;
- + struct brcm_nvram_header header;
- + uint8_t *data;
- + size_t len;
- + int err;
- +
- + memcpy_fromio(&header, priv->base, sizeof(header));
- +
- + if (memcmp(header.magic, NVRAM_MAGIC, 4)) {
- + dev_err(dev, "Invalid NVRAM magic\n");
- + return -EINVAL;
- + }
- +
- + len = le32_to_cpu(header.len);
- +
- + data = kcalloc(1, len, GFP_KERNEL);
- + memcpy_fromio(data, priv->base, len);
- + data[len - 1] = '\0';
- +
- + err = brcm_nvram_add_cells(priv, data, len);
- + if (err) {
- + dev_err(dev, "Failed to add cells: %d\n", err);
- + return err;
- + }
- +
- + kfree(data);
- +
- + return 0;
- +}
- +
- static int brcm_nvram_probe(struct platform_device *pdev)
- {
- struct nvmem_config config = {
- @@ -35,6 +118,7 @@ static int brcm_nvram_probe(struct platf
- struct device *dev = &pdev->dev;
- struct resource *res;
- struct brcm_nvram *priv;
- + int err;
-
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- @@ -46,7 +130,13 @@ static int brcm_nvram_probe(struct platf
- if (IS_ERR(priv->base))
- return PTR_ERR(priv->base);
-
- + err = brcm_nvram_parse(priv);
- + if (err)
- + return err;
- +
- config.dev = dev;
- + config.cells = priv->cells;
- + config.ncells = priv->ncells;
- config.priv = priv;
- config.size = resource_size(res);
-
|