080-v5.18-nvmem-brcm_nvram-parse-NVRAM-content-into-NVMEM-cell.patch 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. From 6e977eaa8280e957b87904b536661550f2a6b3e8 Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
  3. Date: Fri, 25 Feb 2022 17:58:20 +0000
  4. Subject: [PATCH] nvmem: brcm_nvram: parse NVRAM content into NVMEM cells
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. NVRAM consist of header and NUL separated key-value pairs. Parse it and
  9. create NVMEM cell for every key-value entry.
  10. Signed-off-by: Rafał Miłecki <[email protected]>
  11. Signed-off-by: Srinivas Kandagatla <[email protected]>
  12. Link: https://lore.kernel.org/r/[email protected]
  13. Signed-off-by: Greg Kroah-Hartman <[email protected]>
  14. ---
  15. drivers/nvmem/brcm_nvram.c | 90 ++++++++++++++++++++++++++++++++++++++
  16. 1 file changed, 90 insertions(+)
  17. --- a/drivers/nvmem/brcm_nvram.c
  18. +++ b/drivers/nvmem/brcm_nvram.c
  19. @@ -6,12 +6,26 @@
  20. #include <linux/io.h>
  21. #include <linux/mod_devicetable.h>
  22. #include <linux/module.h>
  23. +#include <linux/nvmem-consumer.h>
  24. #include <linux/nvmem-provider.h>
  25. #include <linux/platform_device.h>
  26. +#include <linux/slab.h>
  27. +
  28. +#define NVRAM_MAGIC "FLSH"
  29. struct brcm_nvram {
  30. struct device *dev;
  31. void __iomem *base;
  32. + struct nvmem_cell_info *cells;
  33. + int ncells;
  34. +};
  35. +
  36. +struct brcm_nvram_header {
  37. + char magic[4];
  38. + __le32 len;
  39. + __le32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
  40. + __le32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
  41. + __le32 config_ncdl; /* ncdl values for memc */
  42. };
  43. static int brcm_nvram_read(void *context, unsigned int offset, void *val,
  44. @@ -26,6 +40,75 @@ static int brcm_nvram_read(void *context
  45. return 0;
  46. }
  47. +static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data,
  48. + size_t len)
  49. +{
  50. + struct device *dev = priv->dev;
  51. + char *var, *value, *eq;
  52. + int idx;
  53. +
  54. + priv->ncells = 0;
  55. + for (var = data + sizeof(struct brcm_nvram_header);
  56. + var < (char *)data + len && *var;
  57. + var += strlen(var) + 1) {
  58. + priv->ncells++;
  59. + }
  60. +
  61. + priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL);
  62. + if (!priv->cells)
  63. + return -ENOMEM;
  64. +
  65. + for (var = data + sizeof(struct brcm_nvram_header), idx = 0;
  66. + var < (char *)data + len && *var;
  67. + var = value + strlen(value) + 1, idx++) {
  68. + eq = strchr(var, '=');
  69. + if (!eq)
  70. + break;
  71. + *eq = '\0';
  72. + value = eq + 1;
  73. +
  74. + priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL);
  75. + if (!priv->cells[idx].name)
  76. + return -ENOMEM;
  77. + priv->cells[idx].offset = value - (char *)data;
  78. + priv->cells[idx].bytes = strlen(value);
  79. + }
  80. +
  81. + return 0;
  82. +}
  83. +
  84. +static int brcm_nvram_parse(struct brcm_nvram *priv)
  85. +{
  86. + struct device *dev = priv->dev;
  87. + struct brcm_nvram_header header;
  88. + uint8_t *data;
  89. + size_t len;
  90. + int err;
  91. +
  92. + memcpy_fromio(&header, priv->base, sizeof(header));
  93. +
  94. + if (memcmp(header.magic, NVRAM_MAGIC, 4)) {
  95. + dev_err(dev, "Invalid NVRAM magic\n");
  96. + return -EINVAL;
  97. + }
  98. +
  99. + len = le32_to_cpu(header.len);
  100. +
  101. + data = kcalloc(1, len, GFP_KERNEL);
  102. + memcpy_fromio(data, priv->base, len);
  103. + data[len - 1] = '\0';
  104. +
  105. + err = brcm_nvram_add_cells(priv, data, len);
  106. + if (err) {
  107. + dev_err(dev, "Failed to add cells: %d\n", err);
  108. + return err;
  109. + }
  110. +
  111. + kfree(data);
  112. +
  113. + return 0;
  114. +}
  115. +
  116. static int brcm_nvram_probe(struct platform_device *pdev)
  117. {
  118. struct nvmem_config config = {
  119. @@ -35,6 +118,7 @@ static int brcm_nvram_probe(struct platf
  120. struct device *dev = &pdev->dev;
  121. struct resource *res;
  122. struct brcm_nvram *priv;
  123. + int err;
  124. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  125. if (!priv)
  126. @@ -46,7 +130,13 @@ static int brcm_nvram_probe(struct platf
  127. if (IS_ERR(priv->base))
  128. return PTR_ERR(priv->base);
  129. + err = brcm_nvram_parse(priv);
  130. + if (err)
  131. + return err;
  132. +
  133. config.dev = dev;
  134. + config.cells = priv->cells;
  135. + config.ncells = priv->ncells;
  136. config.priv = priv;
  137. config.size = resource_size(res);