CONFIG_NEED_PER_CPU_KM=y
CONFIG_NLS=y
CONFIG_NVMEM=y
+# CONFIG_NVMEM_MICROCHIP_OTPC is not set
CONFIG_NVMEM_SYSFS=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
CONFIG_NVMEM=y
+# CONFIG_NVMEM_MICROCHIP_OTPC is not set
CONFIG_NVMEM_SYSFS=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
CONFIG_NVMEM=y
+# CONFIG_NVMEM_MICROCHIP_OTPC is not set
CONFIG_NVMEM_SYSFS=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
+++ /dev/null
-From 6e977eaa8280e957b87904b536661550f2a6b3e8 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-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 <rafal@milecki.pl>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-Link: https://lore.kernel.org/r/20220225175822.8293-3-srinivas.kandagatla@linaro.org
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- 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);
-
+++ /dev/null
-From 207775f7e17b8fd0426a2ac4a5b81e4e1d71849e Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Fri, 29 Apr 2022 17:26:47 +0100
-Subject: [PATCH] nvmem: brcm_nvram: find Device Tree nodes for NVMEM cells
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-DT binding for Broadcom's NVRAM supports specifying NVMEM cells as NVMEM
-device (provider) subnodes. Look for such subnodes when collecing NVMEM
-cells. This allows NVMEM consumers to use NVRAM variables.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-Link: https://lore.kernel.org/r/20220429162701.2222-3-srinivas.kandagatla@linaro.org
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/nvmem/brcm_nvram.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/nvmem/brcm_nvram.c
-+++ b/drivers/nvmem/brcm_nvram.c
-@@ -8,6 +8,7 @@
- #include <linux/module.h>
- #include <linux/nvmem-consumer.h>
- #include <linux/nvmem-provider.h>
-+#include <linux/of.h>
- #include <linux/platform_device.h>
- #include <linux/slab.h>
-
-@@ -72,6 +73,7 @@ static int brcm_nvram_add_cells(struct b
- return -ENOMEM;
- priv->cells[idx].offset = value - (char *)data;
- priv->cells[idx].bytes = strlen(value);
-+ priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
- }
-
- return 0;
+++ /dev/null
-From 6e977eaa8280e957b87904b536661550f2a6b3e8 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-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 <rafal@milecki.pl>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-Link: https://lore.kernel.org/r/20220225175822.8293-3-srinivas.kandagatla@linaro.org
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- 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);
-
+++ /dev/null
-From 207775f7e17b8fd0426a2ac4a5b81e4e1d71849e Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Fri, 29 Apr 2022 17:26:47 +0100
-Subject: [PATCH] nvmem: brcm_nvram: find Device Tree nodes for NVMEM cells
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-DT binding for Broadcom's NVRAM supports specifying NVMEM cells as NVMEM
-device (provider) subnodes. Look for such subnodes when collecing NVMEM
-cells. This allows NVMEM consumers to use NVRAM variables.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-Link: https://lore.kernel.org/r/20220429162701.2222-3-srinivas.kandagatla@linaro.org
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/nvmem/brcm_nvram.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/nvmem/brcm_nvram.c
-+++ b/drivers/nvmem/brcm_nvram.c
-@@ -8,6 +8,7 @@
- #include <linux/module.h>
- #include <linux/nvmem-consumer.h>
- #include <linux/nvmem-provider.h>
-+#include <linux/of.h>
- #include <linux/platform_device.h>
- #include <linux/slab.h>
-
-@@ -72,6 +73,7 @@ static int brcm_nvram_add_cells(struct b
- return -ENOMEM;
- priv->cells[idx].offset = value - (char *)data;
- priv->cells[idx].bytes = strlen(value);
-+ priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
- }
-
- return 0;
--- /dev/null
+From 7ae6478b304bc004c3139b422665b0e23b57f05c Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Date: Wed, 13 Oct 2021 14:19:55 +0100
+Subject: [PATCH] nvmem: core: rework nvmem cell instance creation
+
+In the existing design, we do not create a instance per nvmem cell consumer
+but we directly refer cell from nvmem cell list that are added to provider.
+
+However this design has some limitations when consumers want to assign name
+or connection id the nvmem cell instance, ex: via "nvmem-cell-names" or
+id in nvmem_cell_get(id).
+
+Having a name associated with nvmem cell consumer instance will help
+provider drivers in performing post processing of nvmem cell data if required
+before data is seen by the consumers. This is pretty normal with some vendors
+storing nvmem cells like mac-address in a vendor specific data layouts that
+are not directly usable by the consumer drivers.
+
+With this patch nvmem cell will be created dynamically during nvmem_cell_get
+and destroyed in nvmem_cell_put, allowing consumers to associate name with
+nvmem cell consumer instance.
+
+With this patch a new struct nvmem_cell_entry replaces struct nvmem_cell
+for storing nvmem cell information within the core.
+This patch does not change nvmem-consumer interface based on nvmem_cell.
+
+Tested-by: Joakim Zhang <qiangqing.zhang@nxp.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20211013131957.30271-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 165 +++++++++++++++++++++++++++----------------
+ 1 file changed, 105 insertions(+), 60 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -45,8 +45,7 @@ struct nvmem_device {
+ #define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
+
+ #define FLAG_COMPAT BIT(0)
+-
+-struct nvmem_cell {
++struct nvmem_cell_entry {
+ const char *name;
+ int offset;
+ int bytes;
+@@ -57,6 +56,11 @@ struct nvmem_cell {
+ struct list_head node;
+ };
+
++struct nvmem_cell {
++ struct nvmem_cell_entry *entry;
++ const char *id;
++};
++
+ static DEFINE_MUTEX(nvmem_mutex);
+ static DEFINE_IDA(nvmem_ida);
+
+@@ -424,7 +428,7 @@ static struct bus_type nvmem_bus_type =
+ .name = "nvmem",
+ };
+
+-static void nvmem_cell_drop(struct nvmem_cell *cell)
++static void nvmem_cell_entry_drop(struct nvmem_cell_entry *cell)
+ {
+ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_REMOVE, cell);
+ mutex_lock(&nvmem_mutex);
+@@ -437,13 +441,13 @@ static void nvmem_cell_drop(struct nvmem
+
+ static void nvmem_device_remove_all_cells(const struct nvmem_device *nvmem)
+ {
+- struct nvmem_cell *cell, *p;
++ struct nvmem_cell_entry *cell, *p;
+
+ list_for_each_entry_safe(cell, p, &nvmem->cells, node)
+- nvmem_cell_drop(cell);
++ nvmem_cell_entry_drop(cell);
+ }
+
+-static void nvmem_cell_add(struct nvmem_cell *cell)
++static void nvmem_cell_entry_add(struct nvmem_cell_entry *cell)
+ {
+ mutex_lock(&nvmem_mutex);
+ list_add_tail(&cell->node, &cell->nvmem->cells);
+@@ -451,9 +455,9 @@ static void nvmem_cell_add(struct nvmem_
+ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
+ }
+
+-static int nvmem_cell_info_to_nvmem_cell_nodup(struct nvmem_device *nvmem,
+- const struct nvmem_cell_info *info,
+- struct nvmem_cell *cell)
++static int nvmem_cell_info_to_nvmem_cell_entry_nodup(struct nvmem_device *nvmem,
++ const struct nvmem_cell_info *info,
++ struct nvmem_cell_entry *cell)
+ {
+ cell->nvmem = nvmem;
+ cell->offset = info->offset;
+@@ -477,13 +481,13 @@ static int nvmem_cell_info_to_nvmem_cell
+ return 0;
+ }
+
+-static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+- const struct nvmem_cell_info *info,
+- struct nvmem_cell *cell)
++static int nvmem_cell_info_to_nvmem_cell_entry(struct nvmem_device *nvmem,
++ const struct nvmem_cell_info *info,
++ struct nvmem_cell_entry *cell)
+ {
+ int err;
+
+- err = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, cell);
++ err = nvmem_cell_info_to_nvmem_cell_entry_nodup(nvmem, info, cell);
+ if (err)
+ return err;
+
+@@ -507,7 +511,7 @@ static int nvmem_add_cells(struct nvmem_
+ const struct nvmem_cell_info *info,
+ int ncells)
+ {
+- struct nvmem_cell **cells;
++ struct nvmem_cell_entry **cells;
+ int i, rval;
+
+ cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL);
+@@ -521,13 +525,13 @@ static int nvmem_add_cells(struct nvmem_
+ goto err;
+ }
+
+- rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]);
++ rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, &info[i], cells[i]);
+ if (rval) {
+ kfree(cells[i]);
+ goto err;
+ }
+
+- nvmem_cell_add(cells[i]);
++ nvmem_cell_entry_add(cells[i]);
+ }
+
+ /* remove tmp array */
+@@ -536,7 +540,7 @@ static int nvmem_add_cells(struct nvmem_
+ return 0;
+ err:
+ while (i--)
+- nvmem_cell_drop(cells[i]);
++ nvmem_cell_entry_drop(cells[i]);
+
+ kfree(cells);
+
+@@ -573,7 +577,7 @@ static int nvmem_add_cells_from_table(st
+ {
+ const struct nvmem_cell_info *info;
+ struct nvmem_cell_table *table;
+- struct nvmem_cell *cell;
++ struct nvmem_cell_entry *cell;
+ int rval = 0, i;
+
+ mutex_lock(&nvmem_cell_mutex);
+@@ -588,15 +592,13 @@ static int nvmem_add_cells_from_table(st
+ goto out;
+ }
+
+- rval = nvmem_cell_info_to_nvmem_cell(nvmem,
+- info,
+- cell);
++ rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, info, cell);
+ if (rval) {
+ kfree(cell);
+ goto out;
+ }
+
+- nvmem_cell_add(cell);
++ nvmem_cell_entry_add(cell);
+ }
+ }
+ }
+@@ -606,10 +608,10 @@ out:
+ return rval;
+ }
+
+-static struct nvmem_cell *
+-nvmem_find_cell_by_name(struct nvmem_device *nvmem, const char *cell_id)
++static struct nvmem_cell_entry *
++nvmem_find_cell_entry_by_name(struct nvmem_device *nvmem, const char *cell_id)
+ {
+- struct nvmem_cell *iter, *cell = NULL;
++ struct nvmem_cell_entry *iter, *cell = NULL;
+
+ mutex_lock(&nvmem_mutex);
+ list_for_each_entry(iter, &nvmem->cells, node) {
+@@ -680,7 +682,7 @@ static int nvmem_add_cells_from_of(struc
+ {
+ struct device_node *parent, *child;
+ struct device *dev = &nvmem->dev;
+- struct nvmem_cell *cell;
++ struct nvmem_cell_entry *cell;
+ const __be32 *addr;
+ int len;
+
+@@ -729,7 +731,7 @@ static int nvmem_add_cells_from_of(struc
+ }
+
+ cell->np = of_node_get(child);
+- nvmem_cell_add(cell);
++ nvmem_cell_entry_add(cell);
+ }
+
+ return 0;
+@@ -1144,9 +1146,33 @@ struct nvmem_device *devm_nvmem_device_g
+ }
+ EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
+
++static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, const char *id)
++{
++ struct nvmem_cell *cell;
++ const char *name = NULL;
++
++ cell = kzalloc(sizeof(*cell), GFP_KERNEL);
++ if (!cell)
++ return ERR_PTR(-ENOMEM);
++
++ if (id) {
++ name = kstrdup_const(id, GFP_KERNEL);
++ if (!name) {
++ kfree(cell);
++ return ERR_PTR(-ENOMEM);
++ }
++ }
++
++ cell->id = name;
++ cell->entry = entry;
++
++ return cell;
++}
++
+ static struct nvmem_cell *
+ nvmem_cell_get_from_lookup(struct device *dev, const char *con_id)
+ {
++ struct nvmem_cell_entry *cell_entry;
+ struct nvmem_cell *cell = ERR_PTR(-ENOENT);
+ struct nvmem_cell_lookup *lookup;
+ struct nvmem_device *nvmem;
+@@ -1171,11 +1197,15 @@ nvmem_cell_get_from_lookup(struct device
+ break;
+ }
+
+- cell = nvmem_find_cell_by_name(nvmem,
+- lookup->cell_name);
+- if (!cell) {
++ cell_entry = nvmem_find_cell_entry_by_name(nvmem,
++ lookup->cell_name);
++ if (!cell_entry) {
+ __nvmem_device_put(nvmem);
+ cell = ERR_PTR(-ENOENT);
++ } else {
++ cell = nvmem_create_cell(cell_entry, con_id);
++ if (IS_ERR(cell))
++ __nvmem_device_put(nvmem);
+ }
+ break;
+ }
+@@ -1186,10 +1216,10 @@ nvmem_cell_get_from_lookup(struct device
+ }
+
+ #if IS_ENABLED(CONFIG_OF)
+-static struct nvmem_cell *
+-nvmem_find_cell_by_node(struct nvmem_device *nvmem, struct device_node *np)
++static struct nvmem_cell_entry *
++nvmem_find_cell_entry_by_node(struct nvmem_device *nvmem, struct device_node *np)
+ {
+- struct nvmem_cell *iter, *cell = NULL;
++ struct nvmem_cell_entry *iter, *cell = NULL;
+
+ mutex_lock(&nvmem_mutex);
+ list_for_each_entry(iter, &nvmem->cells, node) {
+@@ -1219,6 +1249,7 @@ struct nvmem_cell *of_nvmem_cell_get(str
+ {
+ struct device_node *cell_np, *nvmem_np;
+ struct nvmem_device *nvmem;
++ struct nvmem_cell_entry *cell_entry;
+ struct nvmem_cell *cell;
+ int index = 0;
+
+@@ -1239,12 +1270,16 @@ struct nvmem_cell *of_nvmem_cell_get(str
+ if (IS_ERR(nvmem))
+ return ERR_CAST(nvmem);
+
+- cell = nvmem_find_cell_by_node(nvmem, cell_np);
+- if (!cell) {
++ cell_entry = nvmem_find_cell_entry_by_node(nvmem, cell_np);
++ if (!cell_entry) {
+ __nvmem_device_put(nvmem);
+ return ERR_PTR(-ENOENT);
+ }
+
++ cell = nvmem_create_cell(cell_entry, id);
++ if (IS_ERR(cell))
++ __nvmem_device_put(nvmem);
++
+ return cell;
+ }
+ EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
+@@ -1350,13 +1385,17 @@ EXPORT_SYMBOL(devm_nvmem_cell_put);
+ */
+ void nvmem_cell_put(struct nvmem_cell *cell)
+ {
+- struct nvmem_device *nvmem = cell->nvmem;
++ struct nvmem_device *nvmem = cell->entry->nvmem;
++
++ if (cell->id)
++ kfree_const(cell->id);
+
++ kfree(cell);
+ __nvmem_device_put(nvmem);
+ }
+ EXPORT_SYMBOL_GPL(nvmem_cell_put);
+
+-static void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, void *buf)
++static void nvmem_shift_read_buffer_in_place(struct nvmem_cell_entry *cell, void *buf)
+ {
+ u8 *p, *b;
+ int i, extra, bit_offset = cell->bit_offset;
+@@ -1390,8 +1429,8 @@ static void nvmem_shift_read_buffer_in_p
+ }
+
+ static int __nvmem_cell_read(struct nvmem_device *nvmem,
+- struct nvmem_cell *cell,
+- void *buf, size_t *len)
++ struct nvmem_cell_entry *cell,
++ void *buf, size_t *len, const char *id)
+ {
+ int rc;
+
+@@ -1422,18 +1461,18 @@ static int __nvmem_cell_read(struct nvme
+ */
+ void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
+ {
+- struct nvmem_device *nvmem = cell->nvmem;
++ struct nvmem_device *nvmem = cell->entry->nvmem;
+ u8 *buf;
+ int rc;
+
+ if (!nvmem)
+ return ERR_PTR(-EINVAL);
+
+- buf = kzalloc(cell->bytes, GFP_KERNEL);
++ buf = kzalloc(cell->entry->bytes, GFP_KERNEL);
+ if (!buf)
+ return ERR_PTR(-ENOMEM);
+
+- rc = __nvmem_cell_read(nvmem, cell, buf, len);
++ rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id);
+ if (rc) {
+ kfree(buf);
+ return ERR_PTR(rc);
+@@ -1443,7 +1482,7 @@ void *nvmem_cell_read(struct nvmem_cell
+ }
+ EXPORT_SYMBOL_GPL(nvmem_cell_read);
+
+-static void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
++static void *nvmem_cell_prepare_write_buffer(struct nvmem_cell_entry *cell,
+ u8 *_buf, int len)
+ {
+ struct nvmem_device *nvmem = cell->nvmem;
+@@ -1496,16 +1535,7 @@ err:
+ return ERR_PTR(rc);
+ }
+
+-/**
+- * nvmem_cell_write() - Write to a given nvmem cell
+- *
+- * @cell: nvmem cell to be written.
+- * @buf: Buffer to be written.
+- * @len: length of buffer to be written to nvmem cell.
+- *
+- * Return: length of bytes written or negative on failure.
+- */
+-int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
++static int __nvmem_cell_entry_write(struct nvmem_cell_entry *cell, void *buf, size_t len)
+ {
+ struct nvmem_device *nvmem = cell->nvmem;
+ int rc;
+@@ -1531,6 +1561,21 @@ int nvmem_cell_write(struct nvmem_cell *
+
+ return len;
+ }
++
++/**
++ * nvmem_cell_write() - Write to a given nvmem cell
++ *
++ * @cell: nvmem cell to be written.
++ * @buf: Buffer to be written.
++ * @len: length of buffer to be written to nvmem cell.
++ *
++ * Return: length of bytes written or negative on failure.
++ */
++int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
++{
++ return __nvmem_cell_entry_write(cell->entry, buf, len);
++}
++
+ EXPORT_SYMBOL_GPL(nvmem_cell_write);
+
+ static int nvmem_cell_read_common(struct device *dev, const char *cell_id,
+@@ -1633,7 +1678,7 @@ static const void *nvmem_cell_read_varia
+ if (IS_ERR(cell))
+ return cell;
+
+- nbits = cell->nbits;
++ nbits = cell->entry->nbits;
+ buf = nvmem_cell_read(cell, len);
+ nvmem_cell_put(cell);
+ if (IS_ERR(buf))
+@@ -1729,18 +1774,18 @@ EXPORT_SYMBOL_GPL(nvmem_cell_read_variab
+ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info, void *buf)
+ {
+- struct nvmem_cell cell;
++ struct nvmem_cell_entry cell;
+ int rc;
+ ssize_t len;
+
+ if (!nvmem)
+ return -EINVAL;
+
+- rc = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, &cell);
++ rc = nvmem_cell_info_to_nvmem_cell_entry_nodup(nvmem, info, &cell);
+ if (rc)
+ return rc;
+
+- rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
++ rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL);
+ if (rc)
+ return rc;
+
+@@ -1760,17 +1805,17 @@ EXPORT_SYMBOL_GPL(nvmem_device_cell_read
+ int nvmem_device_cell_write(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info, void *buf)
+ {
+- struct nvmem_cell cell;
++ struct nvmem_cell_entry cell;
+ int rc;
+
+ if (!nvmem)
+ return -EINVAL;
+
+- rc = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, &cell);
++ rc = nvmem_cell_info_to_nvmem_cell_entry_nodup(nvmem, info, &cell);
+ if (rc)
+ return rc;
+
+- return nvmem_cell_write(&cell, buf, cell.bytes);
++ return __nvmem_cell_entry_write(&cell, buf, cell.bytes);
+ }
+ EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
+
--- /dev/null
+From 5008062f1c3f5af3acf86164aa6fcc77b0c7bdce Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Date: Wed, 13 Oct 2021 14:19:56 +0100
+Subject: [PATCH] nvmem: core: add nvmem cell post processing callback
+
+Some NVMEM providers have certain nvmem cells encoded, which requires
+post processing before actually using it.
+
+For example mac-address is stored in either in ascii or delimited or reverse-order.
+
+Having a post-process callback hook to provider drivers would enable them to
+do this vendor specific post processing before nvmem consumers see it.
+
+Tested-by: Joakim Zhang <qiangqing.zhang@nxp.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20211013131957.30271-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 9 +++++++++
+ include/linux/nvmem-provider.h | 5 +++++
+ 2 files changed, 14 insertions(+)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -38,6 +38,7 @@ struct nvmem_device {
+ unsigned int nkeepout;
+ nvmem_reg_read_t reg_read;
+ nvmem_reg_write_t reg_write;
++ nvmem_cell_post_process_t cell_post_process;
+ struct gpio_desc *wp_gpio;
+ void *priv;
+ };
+@@ -798,6 +799,7 @@ struct nvmem_device *nvmem_register(cons
+ nvmem->type = config->type;
+ nvmem->reg_read = config->reg_read;
+ nvmem->reg_write = config->reg_write;
++ nvmem->cell_post_process = config->cell_post_process;
+ nvmem->keepout = config->keepout;
+ nvmem->nkeepout = config->nkeepout;
+ if (config->of_node)
+@@ -1443,6 +1445,13 @@ static int __nvmem_cell_read(struct nvme
+ if (cell->bit_offset || cell->nbits)
+ nvmem_shift_read_buffer_in_place(cell, buf);
+
++ if (nvmem->cell_post_process) {
++ rc = nvmem->cell_post_process(nvmem->priv, id,
++ cell->offset, buf, cell->bytes);
++ if (rc)
++ return rc;
++ }
++
+ if (len)
+ *len = cell->bytes;
+
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -19,6 +19,9 @@ typedef int (*nvmem_reg_read_t)(void *pr
+ void *val, size_t bytes);
+ typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
+ void *val, size_t bytes);
++/* used for vendor specific post processing of cell data */
++typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, unsigned int offset,
++ void *buf, size_t bytes);
+
+ enum nvmem_type {
+ NVMEM_TYPE_UNKNOWN = 0,
+@@ -62,6 +65,7 @@ struct nvmem_keepout {
+ * @no_of_node: Device should not use the parent's of_node even if it's !NULL.
+ * @reg_read: Callback to read data.
+ * @reg_write: Callback to write data.
++ * @cell_post_process: Callback for vendor specific post processing of cell data
+ * @size: Device size.
+ * @word_size: Minimum read/write access granularity.
+ * @stride: Minimum read/write access stride.
+@@ -92,6 +96,7 @@ struct nvmem_config {
+ bool no_of_node;
+ nvmem_reg_read_t reg_read;
+ nvmem_reg_write_t reg_write;
++ nvmem_cell_post_process_t cell_post_process;
+ int size;
+ int word_size;
+ int stride;
--- /dev/null
+From d0221a780cbc99fec6c27a98dba2828dc5735c00 Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Date: Wed, 13 Oct 2021 14:19:57 +0100
+Subject: [PATCH] nvmem: imx-ocotp: add support for post processing
+
+Add .cell_post_process callback for imx-ocotp to deal with MAC address,
+since MAC address need to be reversed byte for some i.MX SoCs.
+
+Tested-by: Joakim Zhang <qiangqing.zhang@nxp.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20211013131957.30271-4-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/imx-ocotp.c | 25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+--- a/drivers/nvmem/imx-ocotp.c
++++ b/drivers/nvmem/imx-ocotp.c
+@@ -97,6 +97,7 @@ struct ocotp_params {
+ unsigned int bank_address_words;
+ void (*set_timing)(struct ocotp_priv *priv);
+ struct ocotp_ctrl_reg ctrl;
++ bool reverse_mac_address;
+ };
+
+ static int imx_ocotp_wait_for_busy(struct ocotp_priv *priv, u32 flags)
+@@ -221,6 +222,25 @@ read_end:
+ return ret;
+ }
+
++static int imx_ocotp_cell_pp(void *context, const char *id, unsigned int offset,
++ void *data, size_t bytes)
++{
++ struct ocotp_priv *priv = context;
++
++ /* Deal with some post processing of nvmem cell data */
++ if (id && !strcmp(id, "mac-address")) {
++ if (priv->params->reverse_mac_address) {
++ u8 *buf = data;
++ int i;
++
++ for (i = 0; i < bytes/2; i++)
++ swap(buf[i], buf[bytes - i - 1]);
++ }
++ }
++
++ return 0;
++}
++
+ static void imx_ocotp_set_imx6_timing(struct ocotp_priv *priv)
+ {
+ unsigned long clk_rate;
+@@ -468,6 +488,7 @@ static struct nvmem_config imx_ocotp_nvm
+ .stride = 1,
+ .reg_read = imx_ocotp_read,
+ .reg_write = imx_ocotp_write,
++ .cell_post_process = imx_ocotp_cell_pp,
+ };
+
+ static const struct ocotp_params imx6q_params = {
+@@ -530,6 +551,7 @@ static const struct ocotp_params imx8mq_
+ .bank_address_words = 0,
+ .set_timing = imx_ocotp_set_imx6_timing,
+ .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
++ .reverse_mac_address = true,
+ };
+
+ static const struct ocotp_params imx8mm_params = {
+@@ -537,6 +559,7 @@ static const struct ocotp_params imx8mm_
+ .bank_address_words = 0,
+ .set_timing = imx_ocotp_set_imx6_timing,
+ .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
++ .reverse_mac_address = true,
+ };
+
+ static const struct ocotp_params imx8mn_params = {
+@@ -544,6 +567,7 @@ static const struct ocotp_params imx8mn_
+ .bank_address_words = 0,
+ .set_timing = imx_ocotp_set_imx6_timing,
+ .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
++ .reverse_mac_address = true,
+ };
+
+ static const struct ocotp_params imx8mp_params = {
+@@ -551,6 +575,7 @@ static const struct ocotp_params imx8mp_
+ .bank_address_words = 0,
+ .set_timing = imx_ocotp_set_imx6_timing,
+ .ctrl = IMX_OCOTP_BM_CTRL_8MP,
++ .reverse_mac_address = true,
+ };
+
+ static const struct of_device_id imx_ocotp_dt_ids[] = {
--- /dev/null
+From 98e2c4efae214fb7086cac9117616eb6ea11475d Mon Sep 17 00:00:00 2001
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Date: Thu, 9 Dec 2021 17:42:34 +0000
+Subject: [PATCH] nvmem: mtk-efuse: support minimum one byte access stride and
+ granularity
+
+In order to support nvmem bits property, should support minimum 1 byte
+read stride and minimum 1 byte read granularity at the same time.
+
+Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20211209174235.14049-4-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/mtk-efuse.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/drivers/nvmem/mtk-efuse.c
++++ b/drivers/nvmem/mtk-efuse.c
+@@ -19,11 +19,12 @@ static int mtk_reg_read(void *context,
+ unsigned int reg, void *_val, size_t bytes)
+ {
+ struct mtk_efuse_priv *priv = context;
+- u32 *val = _val;
+- int i = 0, words = bytes / 4;
++ void __iomem *addr = priv->base + reg;
++ u8 *val = _val;
++ int i;
+
+- while (words--)
+- *val++ = readl(priv->base + reg + (i++ * 4));
++ for (i = 0; i < bytes; i++, val++)
++ *val = readb(addr + i);
+
+ return 0;
+ }
+@@ -45,8 +46,8 @@ static int mtk_efuse_probe(struct platfo
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+- econfig.stride = 4;
+- econfig.word_size = 4;
++ econfig.stride = 1;
++ econfig.word_size = 1;
+ econfig.reg_read = mtk_reg_read;
+ econfig.size = resource_size(res);
+ econfig.priv = priv;
--- /dev/null
+From f6c052afe6f802d87c74153b7a57c43b2e9faf07 Mon Sep 17 00:00:00 2001
+From: Christophe Kerello <christophe.kerello@foss.st.com>
+Date: Sun, 20 Feb 2022 15:14:31 +0000
+Subject: [PATCH] nvmem: core: Fix a conflict between MTD and NVMEM on wp-gpios
+ property
+
+Wp-gpios property can be used on NVMEM nodes and the same property can
+be also used on MTD NAND nodes. In case of the wp-gpios property is
+defined at NAND level node, the GPIO management is done at NAND driver
+level. Write protect is disabled when the driver is probed or resumed
+and is enabled when the driver is released or suspended.
+
+When no partitions are defined in the NAND DT node, then the NAND DT node
+will be passed to NVMEM framework. If wp-gpios property is defined in
+this node, the GPIO resource is taken twice and the NAND controller
+driver fails to probe.
+
+It would be possible to set config->wp_gpio at MTD level before calling
+nvmem_register function but NVMEM framework will toggle this GPIO on
+each write when this GPIO should only be controlled at NAND level driver
+to ensure that the Write Protect has not been enabled.
+
+A way to fix this conflict is to add a new boolean flag in nvmem_config
+named ignore_wp. In case ignore_wp is set, the GPIO resource will
+be managed by the provider.
+
+Fixes: 2a127da461a9 ("nvmem: add support for the write-protect pin")
+Cc: stable@vger.kernel.org
+Signed-off-by: Christophe Kerello <christophe.kerello@foss.st.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151432.16605-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 2 +-
+ include/linux/nvmem-provider.h | 4 +++-
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -771,7 +771,7 @@ struct nvmem_device *nvmem_register(cons
+
+ if (config->wp_gpio)
+ nvmem->wp_gpio = config->wp_gpio;
+- else
++ else if (!config->ignore_wp)
+ nvmem->wp_gpio = gpiod_get_optional(config->dev, "wp",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(nvmem->wp_gpio)) {
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -70,7 +70,8 @@ struct nvmem_keepout {
+ * @word_size: Minimum read/write access granularity.
+ * @stride: Minimum read/write access stride.
+ * @priv: User context passed to read/write callbacks.
+- * @wp-gpio: Write protect pin
++ * @wp-gpio: Write protect pin
++ * @ignore_wp: Write Protect pin is managed by the provider.
+ *
+ * Note: A default "nvmem<id>" name will be assigned to the device if
+ * no name is specified in its configuration. In such case "<id>" is
+@@ -92,6 +93,7 @@ struct nvmem_config {
+ enum nvmem_type type;
+ bool read_only;
+ bool root_only;
++ bool ignore_wp;
+ struct device_node *of_node;
+ bool no_of_node;
+ nvmem_reg_read_t reg_read;
--- /dev/null
+From 190fae468592bc2f0efc8b928920f8f712b5831e Mon Sep 17 00:00:00 2001
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Date: Sun, 20 Feb 2022 15:15:15 +0000
+Subject: [PATCH] nvmem: core: Remove unused devm_nvmem_unregister()
+
+There are no users and seems no will come of the devm_nvmem_unregister().
+Remove the function and remove the unused devm_nvmem_match() along with it.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151527.17216-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 22 ----------------------
+ include/linux/nvmem-provider.h | 8 --------
+ 2 files changed, 30 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -945,28 +945,6 @@ struct nvmem_device *devm_nvmem_register
+ }
+ EXPORT_SYMBOL_GPL(devm_nvmem_register);
+
+-static int devm_nvmem_match(struct device *dev, void *res, void *data)
+-{
+- struct nvmem_device **r = res;
+-
+- return *r == data;
+-}
+-
+-/**
+- * devm_nvmem_unregister() - Unregister previously registered managed nvmem
+- * device.
+- *
+- * @dev: Device that uses the nvmem device.
+- * @nvmem: Pointer to previously registered nvmem device.
+- *
+- * Return: Will be negative on error or zero on success.
+- */
+-int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
+-{
+- return devres_release(dev, devm_nvmem_release, devm_nvmem_match, nvmem);
+-}
+-EXPORT_SYMBOL(devm_nvmem_unregister);
+-
+ static struct nvmem_device *__nvmem_device_get(void *data,
+ int (*match)(struct device *dev, const void *data))
+ {
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -135,8 +135,6 @@ void nvmem_unregister(struct nvmem_devic
+ struct nvmem_device *devm_nvmem_register(struct device *dev,
+ const struct nvmem_config *cfg);
+
+-int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem);
+-
+ void nvmem_add_cell_table(struct nvmem_cell_table *table);
+ void nvmem_del_cell_table(struct nvmem_cell_table *table);
+
+@@ -155,12 +153,6 @@ devm_nvmem_register(struct device *dev,
+ return nvmem_register(c);
+ }
+
+-static inline int
+-devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
+-{
+- return -EOPNOTSUPP;
+-}
+-
+ static inline void nvmem_add_cell_table(struct nvmem_cell_table *table) {}
+ static inline void nvmem_del_cell_table(struct nvmem_cell_table *table) {}
+
--- /dev/null
+From 5825b2c6762611e67ccaf3ccf64485365a120f0b Mon Sep 17 00:00:00 2001
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Date: Sun, 20 Feb 2022 15:15:16 +0000
+Subject: [PATCH] nvmem: core: Use devm_add_action_or_reset()
+
+Slightly simplify the devm_nvmem_register() by using the
+devm_add_action_or_reset().
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151527.17216-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 22 +++++++++-------------
+ 1 file changed, 9 insertions(+), 13 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -907,9 +907,9 @@ void nvmem_unregister(struct nvmem_devic
+ }
+ EXPORT_SYMBOL_GPL(nvmem_unregister);
+
+-static void devm_nvmem_release(struct device *dev, void *res)
++static void devm_nvmem_unregister(void *nvmem)
+ {
+- nvmem_unregister(*(struct nvmem_device **)res);
++ nvmem_unregister(nvmem);
+ }
+
+ /**
+@@ -926,20 +926,16 @@ static void devm_nvmem_release(struct de
+ struct nvmem_device *devm_nvmem_register(struct device *dev,
+ const struct nvmem_config *config)
+ {
+- struct nvmem_device **ptr, *nvmem;
+-
+- ptr = devres_alloc(devm_nvmem_release, sizeof(*ptr), GFP_KERNEL);
+- if (!ptr)
+- return ERR_PTR(-ENOMEM);
++ struct nvmem_device *nvmem;
++ int ret;
+
+ nvmem = nvmem_register(config);
++ if (IS_ERR(nvmem))
++ return nvmem;
+
+- if (!IS_ERR(nvmem)) {
+- *ptr = nvmem;
+- devres_add(dev, ptr);
+- } else {
+- devres_free(ptr);
+- }
++ ret = devm_add_action_or_reset(dev, devm_nvmem_unregister, nvmem);
++ if (ret)
++ return ERR_PTR(ret);
+
+ return nvmem;
+ }
--- /dev/null
+From 8c751e0d9a5264376935a84429a2d468c8877d99 Mon Sep 17 00:00:00 2001
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Date: Sun, 20 Feb 2022 15:15:17 +0000
+Subject: [PATCH] nvmem: core: Check input parameter for NULL in
+ nvmem_unregister()
+
+nvmem_unregister() frees resources and standard pattern is to allow
+caller to not care if it's NULL or not. This will reduce burden on
+the callers to perform this check.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151527.17216-4-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -903,7 +903,8 @@ static void nvmem_device_release(struct
+ */
+ void nvmem_unregister(struct nvmem_device *nvmem)
+ {
+- kref_put(&nvmem->refcnt, nvmem_device_release);
++ if (nvmem)
++ kref_put(&nvmem->refcnt, nvmem_device_release);
+ }
+ EXPORT_SYMBOL_GPL(nvmem_unregister);
+
--- /dev/null
+From 05196facc052385960028ac634447ecf6c764ec3 Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Date: Sun, 20 Feb 2022 15:15:18 +0000
+Subject: [PATCH] nvmem: qfprom: fix kerneldoc warning
+
+This patch fixes below kernel doc warning,
+warning: expecting prototype for qfprom_efuse_reg_write().
+Prototype was for qfprom_reg_write() instead
+
+No code changes.
+
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151527.17216-5-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/qfprom.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/qfprom.c
++++ b/drivers/nvmem/qfprom.c
+@@ -244,7 +244,7 @@ err_clk_prepared:
+ }
+
+ /**
+- * qfprom_efuse_reg_write() - Write to fuses.
++ * qfprom_reg_write() - Write to fuses.
+ * @context: Our driver data.
+ * @reg: The offset to write at.
+ * @_val: Pointer to data to write.
--- /dev/null
+From 07ae4fde9efada7878e1383d6ccc7da70315ca23 Mon Sep 17 00:00:00 2001
+From: Samuel Holland <samuel@sholland.org>
+Date: Sun, 20 Feb 2022 15:15:20 +0000
+Subject: [PATCH] nvmem: sunxi_sid: Add support for D1 variant
+
+D1 has a smaller eFuse block than some other recent SoCs, and it no
+longer requires a workaround to read the eFuse data.
+
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151527.17216-7-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/sunxi_sid.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/nvmem/sunxi_sid.c
++++ b/drivers/nvmem/sunxi_sid.c
+@@ -184,6 +184,11 @@ static const struct sunxi_sid_cfg sun8i_
+ .need_register_readout = true,
+ };
+
++static const struct sunxi_sid_cfg sun20i_d1_cfg = {
++ .value_offset = 0x200,
++ .size = 0x100,
++};
++
+ static const struct sunxi_sid_cfg sun50i_a64_cfg = {
+ .value_offset = 0x200,
+ .size = 0x100,
+@@ -200,6 +205,7 @@ static const struct of_device_id sunxi_s
+ { .compatible = "allwinner,sun7i-a20-sid", .data = &sun7i_a20_cfg },
+ { .compatible = "allwinner,sun8i-a83t-sid", .data = &sun50i_a64_cfg },
+ { .compatible = "allwinner,sun8i-h3-sid", .data = &sun8i_h3_cfg },
++ { .compatible = "allwinner,sun20i-d1-sid", .data = &sun20i_d1_cfg },
+ { .compatible = "allwinner,sun50i-a64-sid", .data = &sun50i_a64_cfg },
+ { .compatible = "allwinner,sun50i-h5-sid", .data = &sun50i_a64_cfg },
+ { .compatible = "allwinner,sun50i-h6-sid", .data = &sun50i_h6_cfg },
--- /dev/null
+From 4dc8d89faed9bb05f116fa1794fc955b14910386 Mon Sep 17 00:00:00 2001
+From: Xiaoke Wang <xkernel.wang@foxmail.com>
+Date: Sun, 20 Feb 2022 15:15:21 +0000
+Subject: [PATCH] nvmem: meson-mx-efuse: replace unnecessary devm_kstrdup()
+
+Replace unnecessary devm_kstrdup() so to avoid redundant memory allocation.
+
+Suggested-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+Signed-off-by: Xiaoke Wang <xkernel.wang@foxmail.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151527.17216-8-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/meson-mx-efuse.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/nvmem/meson-mx-efuse.c
++++ b/drivers/nvmem/meson-mx-efuse.c
+@@ -209,8 +209,7 @@ static int meson_mx_efuse_probe(struct p
+ if (IS_ERR(efuse->base))
+ return PTR_ERR(efuse->base);
+
+- efuse->config.name = devm_kstrdup(&pdev->dev, drvdata->name,
+- GFP_KERNEL);
++ efuse->config.name = drvdata->name;
+ efuse->config.owner = THIS_MODULE;
+ efuse->config.dev = &pdev->dev;
+ efuse->config.priv = efuse;
--- /dev/null
+From f78451012b9e159afdba31c3eb69f223a9f42adc Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Sun, 20 Feb 2022 15:15:23 +0000
+Subject: [PATCH] nvmem: add driver for Layerscape SFP (Security Fuse
+ Processor)
+
+Add support for the Security Fuse Processor found on Layerscape SoCs.
+This driver implements basic read access.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151527.17216-10-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/Kconfig | 12 +++++
+ drivers/nvmem/Makefile | 2 +
+ drivers/nvmem/layerscape-sfp.c | 89 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 103 insertions(+)
+ create mode 100644 drivers/nvmem/layerscape-sfp.c
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -300,4 +300,16 @@ config NVMEM_BRCM_NVRAM
+ This driver provides support for Broadcom's NVRAM that can be accessed
+ using I/O mapping.
+
++config NVMEM_LAYERSCAPE_SFP
++ tristate "Layerscape SFP (Security Fuse Processor) support"
++ depends on ARCH_LAYERSCAPE || COMPILE_TEST
++ depends on HAS_IOMEM
++ help
++ This driver provides support to read the eFuses on Freescale
++ Layerscape SoC's. For example, the vendor provides a per part
++ unique ID there.
++
++ This driver can also be built as a module. If so, the module
++ will be called layerscape-sfp.
++
+ endif
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -61,3 +61,5 @@ obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.
+ nvmem-rmem-y := rmem.o
+ obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_brcm_nvram.o
+ nvmem_brcm_nvram-y := brcm_nvram.o
++obj-$(CONFIG_NVMEM_LAYERSCAPE_SFP) += nvmem-layerscape-sfp.o
++nvmem-layerscape-sfp-y := layerscape-sfp.o
+--- /dev/null
++++ b/drivers/nvmem/layerscape-sfp.c
+@@ -0,0 +1,89 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Layerscape SFP driver
++ *
++ * Copyright (c) 2022 Michael Walle <michael@walle.cc>
++ *
++ */
++
++#include <linux/device.h>
++#include <linux/io.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/nvmem-provider.h>
++#include <linux/platform_device.h>
++#include <linux/property.h>
++
++#define LAYERSCAPE_SFP_OTP_OFFSET 0x0200
++
++struct layerscape_sfp_priv {
++ void __iomem *base;
++};
++
++struct layerscape_sfp_data {
++ int size;
++};
++
++static int layerscape_sfp_read(void *context, unsigned int offset, void *val,
++ size_t bytes)
++{
++ struct layerscape_sfp_priv *priv = context;
++
++ memcpy_fromio(val, priv->base + LAYERSCAPE_SFP_OTP_OFFSET + offset,
++ bytes);
++
++ return 0;
++}
++
++static struct nvmem_config layerscape_sfp_nvmem_config = {
++ .name = "fsl-sfp",
++ .reg_read = layerscape_sfp_read,
++};
++
++static int layerscape_sfp_probe(struct platform_device *pdev)
++{
++ const struct layerscape_sfp_data *data;
++ struct layerscape_sfp_priv *priv;
++ struct nvmem_device *nvmem;
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(priv->base))
++ return PTR_ERR(priv->base);
++
++ data = device_get_match_data(&pdev->dev);
++
++ layerscape_sfp_nvmem_config.size = data->size;
++ layerscape_sfp_nvmem_config.dev = &pdev->dev;
++ layerscape_sfp_nvmem_config.priv = priv;
++
++ nvmem = devm_nvmem_register(&pdev->dev, &layerscape_sfp_nvmem_config);
++
++ return PTR_ERR_OR_ZERO(nvmem);
++}
++
++static const struct layerscape_sfp_data ls1028a_data = {
++ .size = 0x88,
++};
++
++static const struct of_device_id layerscape_sfp_dt_ids[] = {
++ { .compatible = "fsl,ls1028a-sfp", .data = &ls1028a_data },
++ {},
++};
++MODULE_DEVICE_TABLE(of, layerscape_sfp_dt_ids);
++
++static struct platform_driver layerscape_sfp_driver = {
++ .probe = layerscape_sfp_probe,
++ .driver = {
++ .name = "layerscape_sfp",
++ .of_match_table = layerscape_sfp_dt_ids,
++ },
++};
++module_platform_driver(layerscape_sfp_driver);
++
++MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
++MODULE_DESCRIPTION("Layerscape Security Fuse Processor driver");
++MODULE_LICENSE("GPL");
--- /dev/null
+From bc5c75e0a5a9400f81a987cc720100ac475fa4d8 Mon Sep 17 00:00:00 2001
+From: Knox Chiou <knoxchiou@chromium.org>
+Date: Wed, 23 Feb 2022 22:35:00 +0000
+Subject: [PATCH] nvmem: qfprom: Increase fuse blow timeout to prevent write
+ fail
+
+sc7180 blow fuses got slightly chances to hit qfprom_reg_write timeout.
+Current timeout is simply too low. Since blowing fuses is a
+very rare operation, so the risk associated with overestimating this
+number is low.
+Increase fuse blow timeout from 1ms to 10ms.
+
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Knox Chiou <knoxchiou@chromium.org>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220223223502.29454-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/qfprom.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/qfprom.c
++++ b/drivers/nvmem/qfprom.c
+@@ -22,7 +22,7 @@
+
+ /* Amount of time required to hold charge to blow fuse in micro-seconds */
+ #define QFPROM_FUSE_BLOW_POLL_US 100
+-#define QFPROM_FUSE_BLOW_TIMEOUT_US 1000
++#define QFPROM_FUSE_BLOW_TIMEOUT_US 10000
+
+ #define QFPROM_BLOW_STATUS_OFFSET 0x048
+ #define QFPROM_BLOW_STATUS_BUSY 0x1
--- /dev/null
+From 8747ec2e9762ed9ae53b3a590938f454b6a1abdf Mon Sep 17 00:00:00 2001
+From: Vincent Shih <vincent.sunplus@gmail.com>
+Date: Wed, 23 Feb 2022 22:35:01 +0000
+Subject: [PATCH] nvmem: Add driver for OCOTP in Sunplus SP7021
+
+Add driver for OCOTP in Sunplus SP7021
+
+Signed-off-by: Vincent Shih <vincent.sunplus@gmail.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220223223502.29454-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ MAINTAINERS | 5 +
+ drivers/nvmem/Kconfig | 12 ++
+ drivers/nvmem/Makefile | 2 +
+ drivers/nvmem/sunplus-ocotp.c | 228 ++++++++++++++++++++++++++++++++++
+ 4 files changed, 247 insertions(+)
+ create mode 100644 drivers/nvmem/sunplus-ocotp.c
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -312,4 +312,16 @@ config NVMEM_LAYERSCAPE_SFP
+ This driver can also be built as a module. If so, the module
+ will be called layerscape-sfp.
+
++config NVMEM_SUNPLUS_OCOTP
++ tristate "Sunplus SoC OTP support"
++ depends on SOC_SP7021 || COMPILE_TEST
++ depends on HAS_IOMEM
++ help
++ This is a driver for the On-chip OTP controller (OCOTP) available
++ on Sunplus SoCs. It provides access to 128 bytes of one-time
++ programmable eFuse.
++
++ This driver can also be built as a module. If so, the module
++ will be called nvmem-sunplus-ocotp.
++
+ endif
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -63,3 +63,5 @@ obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_
+ nvmem_brcm_nvram-y := brcm_nvram.o
+ obj-$(CONFIG_NVMEM_LAYERSCAPE_SFP) += nvmem-layerscape-sfp.o
+ nvmem-layerscape-sfp-y := layerscape-sfp.o
++obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvmem_sunplus_ocotp.o
++nvmem_sunplus_ocotp-y := sunplus-ocotp.o
+--- /dev/null
++++ b/drivers/nvmem/sunplus-ocotp.c
+@@ -0,0 +1,228 @@
++// SPDX-License-Identifier: GPL-2.0
++
++/*
++ * The OCOTP driver for Sunplus SP7021
++ *
++ * Copyright (C) 2019 Sunplus Technology Inc., All rights reserved.
++ */
++
++#include <linux/bitfield.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/io.h>
++#include <linux/iopoll.h>
++#include <linux/module.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++
++/*
++ * OTP memory
++ * Each bank contains 4 words (32 bits).
++ * Bank 0 starts at offset 0 from the base.
++ */
++
++#define OTP_WORDS_PER_BANK 4
++#define OTP_WORD_SIZE sizeof(u32)
++#define OTP_BIT_ADDR_OF_BANK (8 * OTP_WORD_SIZE * OTP_WORDS_PER_BANK)
++#define QAC628_OTP_NUM_BANKS 8
++#define QAC628_OTP_SIZE (QAC628_OTP_NUM_BANKS * OTP_WORDS_PER_BANK * OTP_WORD_SIZE)
++#define OTP_READ_TIMEOUT_US 200000
++
++/* HB_GPIO */
++#define ADDRESS_8_DATA 0x20
++
++/* OTP_RX */
++#define OTP_CONTROL_2 0x48
++#define OTP_RD_PERIOD GENMASK(15, 8)
++#define OTP_RD_PERIOD_MASK ~GENMASK(15, 8)
++#define CPU_CLOCK FIELD_PREP(OTP_RD_PERIOD, 30)
++#define SEL_BAK_KEY2 BIT(5)
++#define SEL_BAK_KEY2_MASK ~BIT(5)
++#define SW_TRIM_EN BIT(4)
++#define SW_TRIM_EN_MASK ~BIT(4)
++#define SEL_BAK_KEY BIT(3)
++#define SEL_BAK_KEY_MASK ~BIT(3)
++#define OTP_READ BIT(2)
++#define OTP_LOAD_SECURE_DATA BIT(1)
++#define OTP_LOAD_SECURE_DATA_MASK ~BIT(1)
++#define OTP_DO_CRC BIT(0)
++#define OTP_DO_CRC_MASK ~BIT(0)
++#define OTP_STATUS 0x4c
++#define OTP_READ_DONE BIT(4)
++#define OTP_READ_DONE_MASK ~BIT(4)
++#define OTP_LOAD_SECURE_DONE_MASK ~BIT(2)
++#define OTP_READ_ADDRESS 0x50
++
++enum base_type {
++ HB_GPIO,
++ OTPRX,
++ BASEMAX,
++};
++
++struct sp_ocotp_priv {
++ struct device *dev;
++ void __iomem *base[BASEMAX];
++ struct clk *clk;
++};
++
++struct sp_ocotp_data {
++ int size;
++};
++
++const struct sp_ocotp_data sp_otp_v0 = {
++ .size = QAC628_OTP_SIZE,
++};
++
++static int sp_otp_read_real(struct sp_ocotp_priv *otp, int addr, char *value)
++{
++ unsigned int addr_data;
++ unsigned int byte_shift;
++ unsigned int status;
++ int ret;
++
++ addr_data = addr % (OTP_WORD_SIZE * OTP_WORDS_PER_BANK);
++ addr_data = addr_data / OTP_WORD_SIZE;
++
++ byte_shift = addr % (OTP_WORD_SIZE * OTP_WORDS_PER_BANK);
++ byte_shift = byte_shift % OTP_WORD_SIZE;
++
++ addr = addr / (OTP_WORD_SIZE * OTP_WORDS_PER_BANK);
++ addr = addr * OTP_BIT_ADDR_OF_BANK;
++
++ writel(readl(otp->base[OTPRX] + OTP_STATUS) & OTP_READ_DONE_MASK &
++ OTP_LOAD_SECURE_DONE_MASK, otp->base[OTPRX] + OTP_STATUS);
++ writel(addr, otp->base[OTPRX] + OTP_READ_ADDRESS);
++ writel(readl(otp->base[OTPRX] + OTP_CONTROL_2) | OTP_READ,
++ otp->base[OTPRX] + OTP_CONTROL_2);
++ writel(readl(otp->base[OTPRX] + OTP_CONTROL_2) & SEL_BAK_KEY2_MASK & SW_TRIM_EN_MASK
++ & SEL_BAK_KEY_MASK & OTP_LOAD_SECURE_DATA_MASK & OTP_DO_CRC_MASK,
++ otp->base[OTPRX] + OTP_CONTROL_2);
++ writel((readl(otp->base[OTPRX] + OTP_CONTROL_2) & OTP_RD_PERIOD_MASK) | CPU_CLOCK,
++ otp->base[OTPRX] + OTP_CONTROL_2);
++
++ ret = readl_poll_timeout(otp->base[OTPRX] + OTP_STATUS, status,
++ status & OTP_READ_DONE, 10, OTP_READ_TIMEOUT_US);
++
++ if (ret < 0)
++ return ret;
++
++ *value = (readl(otp->base[HB_GPIO] + ADDRESS_8_DATA + addr_data * OTP_WORD_SIZE)
++ >> (8 * byte_shift)) & 0xff;
++
++ return ret;
++}
++
++static int sp_ocotp_read(void *priv, unsigned int offset, void *value, size_t bytes)
++{
++ struct sp_ocotp_priv *otp = priv;
++ unsigned int addr;
++ char *buf = value;
++ char val[4];
++ int ret;
++
++ ret = clk_enable(otp->clk);
++ if (ret)
++ return ret;
++
++ *buf = 0;
++ for (addr = offset; addr < (offset + bytes); addr++) {
++ ret = sp_otp_read_real(otp, addr, val);
++ if (ret < 0) {
++ dev_err(otp->dev, "OTP read fail:%d at %d", ret, addr);
++ goto disable_clk;
++ }
++
++ *buf++ = *val;
++ }
++
++disable_clk:
++ clk_disable(otp->clk);
++
++ return ret;
++}
++
++static struct nvmem_config sp_ocotp_nvmem_config = {
++ .name = "sp-ocotp",
++ .read_only = true,
++ .word_size = 1,
++ .size = QAC628_OTP_SIZE,
++ .stride = 1,
++ .reg_read = sp_ocotp_read,
++ .owner = THIS_MODULE,
++};
++
++static int sp_ocotp_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct nvmem_device *nvmem;
++ struct sp_ocotp_priv *otp;
++ struct resource *res;
++ int ret;
++
++ otp = devm_kzalloc(dev, sizeof(*otp), GFP_KERNEL);
++ if (!otp)
++ return -ENOMEM;
++
++ otp->dev = dev;
++
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hb_gpio");
++ otp->base[HB_GPIO] = devm_ioremap_resource(dev, res);
++ if (IS_ERR(otp->base[HB_GPIO]))
++ return PTR_ERR(otp->base[HB_GPIO]);
++
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otprx");
++ otp->base[OTPRX] = devm_ioremap_resource(dev, res);
++ if (IS_ERR(otp->base[OTPRX]))
++ return PTR_ERR(otp->base[OTPRX]);
++
++ otp->clk = devm_clk_get(&pdev->dev, NULL);
++ if (IS_ERR(otp->clk))
++ return dev_err_probe(&pdev->dev, PTR_ERR(otp->clk),
++ "devm_clk_get fail\n");
++
++ ret = clk_prepare(otp->clk);
++ if (ret < 0) {
++ dev_err(dev, "failed to prepare clk: %d\n", ret);
++ return ret;
++ }
++
++ sp_ocotp_nvmem_config.priv = otp;
++ sp_ocotp_nvmem_config.dev = dev;
++
++ nvmem = devm_nvmem_register(dev, &sp_ocotp_nvmem_config);
++ if (IS_ERR(nvmem))
++ return dev_err_probe(&pdev->dev, PTR_ERR(nvmem),
++ "register nvmem device fail\n");
++
++ platform_set_drvdata(pdev, nvmem);
++
++ dev_dbg(dev, "banks:%d x wpb:%d x wsize:%d = %d",
++ (int)QAC628_OTP_NUM_BANKS, (int)OTP_WORDS_PER_BANK,
++ (int)OTP_WORD_SIZE, (int)QAC628_OTP_SIZE);
++
++ dev_info(dev, "by Sunplus (C) 2020");
++
++ return 0;
++}
++
++static const struct of_device_id sp_ocotp_dt_ids[] = {
++ { .compatible = "sunplus,sp7021-ocotp", .data = &sp_otp_v0 },
++ { }
++};
++MODULE_DEVICE_TABLE(of, sp_ocotp_dt_ids);
++
++static struct platform_driver sp_otp_driver = {
++ .probe = sp_ocotp_probe,
++ .driver = {
++ .name = "sunplus,sp7021-ocotp",
++ .of_match_table = sp_ocotp_dt_ids,
++ }
++};
++module_platform_driver(sp_otp_driver);
++
++MODULE_AUTHOR("Vincent Shih <vincent.sunplus@gmail.com>");
++MODULE_DESCRIPTION("Sunplus On-Chip OTP driver");
++MODULE_LICENSE("GPL");
++
--- /dev/null
+From 6e977eaa8280e957b87904b536661550f2a6b3e8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+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 <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220225175822.8293-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
+
--- /dev/null
+From 6bd0ffeaa389866089e9573b2298ae58d6359b75 Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzk@kernel.org>
+Date: Mon, 21 Mar 2022 12:03:24 +0100
+Subject: [PATCH] nvmem: bcm-ocotp: mark ACPI device ID table as maybe unused
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+"bcm_otpc_acpi_ids" is used with ACPI_PTR, so a build with !CONFIG_ACPI
+has a warning:
+
+ drivers/nvmem/bcm-ocotp.c:247:36: error:
+ ‘bcm_otpc_acpi_ids’ defined but not used [-Werror=unused-const-variable=]
+
+Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
+Link: https://lore.kernel.org/r/20220321110326.44652-1-krzk@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/bcm-ocotp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/bcm-ocotp.c
++++ b/drivers/nvmem/bcm-ocotp.c
+@@ -244,7 +244,7 @@ static const struct of_device_id bcm_otp
+ };
+ MODULE_DEVICE_TABLE(of, bcm_otpc_dt_ids);
+
+-static const struct acpi_device_id bcm_otpc_acpi_ids[] = {
++static const struct acpi_device_id bcm_otpc_acpi_ids[] __maybe_unused = {
+ { .id = "BRCM0700", .driver_data = (kernel_ulong_t)&otp_map },
+ { .id = "BRCM0701", .driver_data = (kernel_ulong_t)&otp_map_v2 },
+ { /* sentinel */ }
--- /dev/null
+From 1066f8156351fcd997125257cea47cf805ba4f6d Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzk@kernel.org>
+Date: Mon, 21 Mar 2022 12:03:25 +0100
+Subject: [PATCH] nvmem: sunplus-ocotp: staticize sp_otp_v0
+
+The "sp_otp_v0" file scope variable is not used outside, so make it
+static to fix warning:
+
+ drivers/nvmem/sunplus-ocotp.c:74:29: sparse:
+ sparse: symbol 'sp_otp_v0' was not declared. Should it be static?
+
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
+Link: https://lore.kernel.org/r/20220321110326.44652-2-krzk@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/sunplus-ocotp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/sunplus-ocotp.c
++++ b/drivers/nvmem/sunplus-ocotp.c
+@@ -71,7 +71,7 @@ struct sp_ocotp_data {
+ int size;
+ };
+
+-const struct sp_ocotp_data sp_otp_v0 = {
++static const struct sp_ocotp_data sp_otp_v0 = {
+ .size = QAC628_OTP_SIZE,
+ };
+
--- /dev/null
+From 874dfbcf219ccc42a2cbd187d087c7db82c3024b Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzk@kernel.org>
+Date: Mon, 21 Mar 2022 12:03:26 +0100
+Subject: [PATCH] nvmem: sunplus-ocotp: drop useless probe confirmation
+
+Printing probe success is discouraged, because we can use tracing for
+this purpose. Remove useless print message after Sunplus OCOTP driver
+probe.
+
+Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
+Link: https://lore.kernel.org/r/20220321110326.44652-3-krzk@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/sunplus-ocotp.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/nvmem/sunplus-ocotp.c
++++ b/drivers/nvmem/sunplus-ocotp.c
+@@ -202,8 +202,6 @@ static int sp_ocotp_probe(struct platfor
+ (int)QAC628_OTP_NUM_BANKS, (int)OTP_WORDS_PER_BANK,
+ (int)OTP_WORD_SIZE, (int)QAC628_OTP_SIZE);
+
+- dev_info(dev, "by Sunplus (C) 2020");
+-
+ return 0;
+ }
+
--- /dev/null
+From dbc2f62061c6bfba0aee93161ee3194dcee84bd0 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 29 Apr 2022 17:26:46 +0100
+Subject: [PATCH] nvmem: core: support passing DT node in cell info
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Some hardware may have NVMEM cells described in Device Tree using
+individual nodes. Let drivers pass such nodes to the NVMEM subsystem so
+they can be later used by NVMEM consumers.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220429162701.2222-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 1 +
+ include/linux/nvmem-consumer.h | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -467,6 +467,7 @@ static int nvmem_cell_info_to_nvmem_cell
+
+ cell->bit_offset = info->bit_offset;
+ cell->nbits = info->nbits;
++ cell->np = info->np;
+
+ if (cell->nbits)
+ cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
+--- a/include/linux/nvmem-consumer.h
++++ b/include/linux/nvmem-consumer.h
+@@ -25,6 +25,7 @@ struct nvmem_cell_info {
+ unsigned int bytes;
+ unsigned int bit_offset;
+ unsigned int nbits;
++ struct device_node *np;
+ };
+
+ /**
--- /dev/null
+From 207775f7e17b8fd0426a2ac4a5b81e4e1d71849e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 29 Apr 2022 17:26:47 +0100
+Subject: [PATCH] nvmem: brcm_nvram: find Device Tree nodes for NVMEM cells
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+DT binding for Broadcom's NVRAM supports specifying NVMEM cells as NVMEM
+device (provider) subnodes. Look for such subnodes when collecing NVMEM
+cells. This allows NVMEM consumers to use NVRAM variables.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220429162701.2222-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/brcm_nvram.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/nvmem/brcm_nvram.c
++++ b/drivers/nvmem/brcm_nvram.c
+@@ -8,6 +8,7 @@
+ #include <linux/module.h>
+ #include <linux/nvmem-consumer.h>
+ #include <linux/nvmem-provider.h>
++#include <linux/of.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
+
+@@ -72,6 +73,7 @@ static int brcm_nvram_add_cells(struct b
+ return -ENOMEM;
+ priv->cells[idx].offset = value - (char *)data;
+ priv->cells[idx].bytes = strlen(value);
++ priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
+ }
+
+ return 0;
--- /dev/null
+From b6b7ef932ae838209254f016ecf8862d716a5ced Mon Sep 17 00:00:00 2001
+From: Sven Peter <sven@svenpeter.dev>
+Date: Fri, 29 Apr 2022 17:26:50 +0100
+Subject: [PATCH] nvmem: Add Apple eFuse driver
+
+Apple SoCs contain eFuses used to store factory-programmed data such
+as calibration values for the PCIe or the Type-C PHY. They are organized
+as 32bit values exposed as MMIO.
+
+Signed-off-by: Sven Peter <sven@svenpeter.dev>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220429162701.2222-6-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/Kconfig | 12 ++++++
+ drivers/nvmem/Makefile | 2 +
+ drivers/nvmem/apple-efuses.c | 80 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 94 insertions(+)
+ create mode 100644 drivers/nvmem/apple-efuses.c
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -324,4 +324,16 @@ config NVMEM_SUNPLUS_OCOTP
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-sunplus-ocotp.
+
++config NVMEM_APPLE_EFUSES
++ tristate "Apple eFuse support"
++ depends on ARCH_APPLE || COMPILE_TEST
++ default ARCH_APPLE
++ help
++ Say y here to enable support for reading eFuses on Apple SoCs
++ such as the M1. These are e.g. used to store factory programmed
++ calibration data required for the PCIe or the USB-C PHY.
++
++ This driver can also be built as a module. If so, the module will
++ be called nvmem-apple-efuses.
++
+ endif
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -65,3 +65,5 @@ obj-$(CONFIG_NVMEM_LAYERSCAPE_SFP) += nv
+ nvmem-layerscape-sfp-y := layerscape-sfp.o
+ obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvmem_sunplus_ocotp.o
+ nvmem_sunplus_ocotp-y := sunplus-ocotp.o
++obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
++nvmem-apple-efuses-y := apple-efuses.o
+--- /dev/null
++++ b/drivers/nvmem/apple-efuses.c
+@@ -0,0 +1,80 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Apple SoC eFuse driver
++ *
++ * Copyright (C) The Asahi Linux Contributors
++ */
++
++#include <linux/io.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/nvmem-provider.h>
++#include <linux/platform_device.h>
++
++struct apple_efuses_priv {
++ void __iomem *fuses;
++};
++
++static int apple_efuses_read(void *context, unsigned int offset, void *val,
++ size_t bytes)
++{
++ struct apple_efuses_priv *priv = context;
++ u32 *dst = val;
++
++ while (bytes >= sizeof(u32)) {
++ *dst++ = readl_relaxed(priv->fuses + offset);
++ bytes -= sizeof(u32);
++ offset += sizeof(u32);
++ }
++
++ return 0;
++}
++
++static int apple_efuses_probe(struct platform_device *pdev)
++{
++ struct apple_efuses_priv *priv;
++ struct resource *res;
++ struct nvmem_config config = {
++ .dev = &pdev->dev,
++ .read_only = true,
++ .reg_read = apple_efuses_read,
++ .stride = sizeof(u32),
++ .word_size = sizeof(u32),
++ .name = "apple_efuses_nvmem",
++ .id = NVMEM_DEVID_AUTO,
++ .root_only = true,
++ };
++
++ priv = devm_kzalloc(config.dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->fuses = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
++ if (IS_ERR(priv->fuses))
++ return PTR_ERR(priv->fuses);
++
++ config.priv = priv;
++ config.size = resource_size(res);
++
++ return PTR_ERR_OR_ZERO(devm_nvmem_register(config.dev, &config));
++}
++
++static const struct of_device_id apple_efuses_of_match[] = {
++ { .compatible = "apple,efuses", },
++ {}
++};
++
++MODULE_DEVICE_TABLE(of, apple_efuses_of_match);
++
++static struct platform_driver apple_efuses_driver = {
++ .driver = {
++ .name = "apple_efuses",
++ .of_match_table = apple_efuses_of_match,
++ },
++ .probe = apple_efuses_probe,
++};
++
++module_platform_driver(apple_efuses_driver);
++
++MODULE_AUTHOR("Sven Peter <sven@svenpeter.dev>");
++MODULE_LICENSE("GPL");
--- /dev/null
+From 517f6e2641a2802dce5a5aa0d18c7d37a35678d2 Mon Sep 17 00:00:00 2001
+From: Minghao Chi <chi.minghao@zte.com.cn>
+Date: Fri, 29 Apr 2022 17:26:54 +0100
+Subject: [PATCH] nvmem: qfprom: using pm_runtime_resume_and_get instead of
+ pm_runtime_get_sync
+
+Using pm_runtime_resume_and_get is more appropriate
+for simplifing code
+
+Reported-by: Zeal Robot <zealci@zte.com.cn>
+Signed-off-by: Minghao Chi <chi.minghao@zte.com.cn>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220429162701.2222-10-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/qfprom.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/nvmem/qfprom.c
++++ b/drivers/nvmem/qfprom.c
+@@ -217,9 +217,8 @@ static int qfprom_enable_fuse_blowing(co
+ goto err_clk_rate_set;
+ }
+
+- ret = pm_runtime_get_sync(priv->dev);
++ ret = pm_runtime_resume_and_get(priv->dev);
+ if (ret < 0) {
+- pm_runtime_put_noidle(priv->dev);
+ dev_err(priv->dev, "Failed to enable power-domain\n");
+ goto err_reg_enable;
+ }
--- /dev/null
+From 943eadbdb11314b41eacbcc484dfb7f93e271ff4 Mon Sep 17 00:00:00 2001
+From: Sean Anderson <sean.anderson@seco.com>
+Date: Fri, 29 Apr 2022 17:27:00 +0100
+Subject: [PATCH] nvmem: sfp: Use regmap
+
+This converts the SFP driver to use regmap. This will allow easily
+supporting devices with different endians. We disallow byte-level
+access, as regmap_bulk_read doesn't support it (and it's unclear what
+the correct result would be when we have an endianness difference).
+
+Signed-off-by: Sean Anderson <sean.anderson@seco.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220429162701.2222-16-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/Kconfig | 1 +
+ drivers/nvmem/layerscape-sfp.c | 30 ++++++++++++++++++++++--------
+ 2 files changed, 23 insertions(+), 8 deletions(-)
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -304,6 +304,7 @@ config NVMEM_LAYERSCAPE_SFP
+ tristate "Layerscape SFP (Security Fuse Processor) support"
+ depends on ARCH_LAYERSCAPE || COMPILE_TEST
+ depends on HAS_IOMEM
++ select REGMAP_MMIO
+ help
+ This driver provides support to read the eFuses on Freescale
+ Layerscape SoC's. For example, the vendor provides a per part
+--- a/drivers/nvmem/layerscape-sfp.c
++++ b/drivers/nvmem/layerscape-sfp.c
+@@ -13,15 +13,17 @@
+ #include <linux/nvmem-provider.h>
+ #include <linux/platform_device.h>
+ #include <linux/property.h>
++#include <linux/regmap.h>
+
+ #define LAYERSCAPE_SFP_OTP_OFFSET 0x0200
+
+ struct layerscape_sfp_priv {
+- void __iomem *base;
++ struct regmap *regmap;
+ };
+
+ struct layerscape_sfp_data {
+ int size;
++ enum regmap_endian endian;
+ };
+
+ static int layerscape_sfp_read(void *context, unsigned int offset, void *val,
+@@ -29,15 +31,16 @@ static int layerscape_sfp_read(void *con
+ {
+ struct layerscape_sfp_priv *priv = context;
+
+- memcpy_fromio(val, priv->base + LAYERSCAPE_SFP_OTP_OFFSET + offset,
+- bytes);
+-
+- return 0;
++ return regmap_bulk_read(priv->regmap,
++ LAYERSCAPE_SFP_OTP_OFFSET + offset, val,
++ bytes / 4);
+ }
+
+ static struct nvmem_config layerscape_sfp_nvmem_config = {
+ .name = "fsl-sfp",
+ .reg_read = layerscape_sfp_read,
++ .word_size = 4,
++ .stride = 4,
+ };
+
+ static int layerscape_sfp_probe(struct platform_device *pdev)
+@@ -45,16 +48,26 @@ static int layerscape_sfp_probe(struct p
+ const struct layerscape_sfp_data *data;
+ struct layerscape_sfp_priv *priv;
+ struct nvmem_device *nvmem;
++ struct regmap_config config = { 0 };
++ void __iomem *base;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+- priv->base = devm_platform_ioremap_resource(pdev, 0);
+- if (IS_ERR(priv->base))
+- return PTR_ERR(priv->base);
++ base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(base))
++ return PTR_ERR(base);
+
+ data = device_get_match_data(&pdev->dev);
++ config.reg_bits = 32;
++ config.reg_stride = 4;
++ config.val_bits = 32;
++ config.val_format_endian = data->endian;
++ config.max_register = LAYERSCAPE_SFP_OTP_OFFSET + data->size - 4;
++ priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, &config);
++ if (IS_ERR(priv->regmap))
++ return PTR_ERR(priv->regmap);
+
+ layerscape_sfp_nvmem_config.size = data->size;
+ layerscape_sfp_nvmem_config.dev = &pdev->dev;
+@@ -67,6 +80,7 @@ static int layerscape_sfp_probe(struct p
+
+ static const struct layerscape_sfp_data ls1028a_data = {
+ .size = 0x88,
++ .endian = REGMAP_ENDIAN_LITTLE,
+ };
+
+ static const struct of_device_id layerscape_sfp_dt_ids[] = {
--- /dev/null
+From 33a1c6618677fe33f8e84cb7bedc45abbce89a50 Mon Sep 17 00:00:00 2001
+From: Sean Anderson <sean.anderson@seco.com>
+Date: Fri, 29 Apr 2022 17:27:01 +0100
+Subject: [PATCH] nvmem: sfp: Add support for TA 2.1 devices
+
+This adds support for Trust Architecture (TA) 2.1 devices to the SFP driver.
+There are few differences between TA 2.1 and TA 3.0, especially for
+read-only support, so just re-use the existing data.
+
+Signed-off-by: Sean Anderson <sean.anderson@seco.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220429162701.2222-17-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/layerscape-sfp.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/nvmem/layerscape-sfp.c
++++ b/drivers/nvmem/layerscape-sfp.c
+@@ -78,12 +78,18 @@ static int layerscape_sfp_probe(struct p
+ return PTR_ERR_OR_ZERO(nvmem);
+ }
+
++static const struct layerscape_sfp_data ls1021a_data = {
++ .size = 0x88,
++ .endian = REGMAP_ENDIAN_BIG,
++};
++
+ static const struct layerscape_sfp_data ls1028a_data = {
+ .size = 0x88,
+ .endian = REGMAP_ENDIAN_LITTLE,
+ };
+
+ static const struct of_device_id layerscape_sfp_dt_ids[] = {
++ { .compatible = "fsl,ls1021a-sfp", .data = &ls1021a_data },
+ { .compatible = "fsl,ls1028a-sfp", .data = &ls1028a_data },
+ {},
+ };
+++ /dev/null
-From 2d5ba37461013253d2ff0a3641b727fd32ea97a9 Mon Sep 17 00:00:00 2001
-From: Florian Fainelli <florian@openwrt.org>
-Date: Tue, 23 Feb 2021 18:44:53 +0100
-Subject: [PATCH 1/3] usb: ehci: add spurious flag to disable overcurrent
- checking
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This patch adds an ignore_oc flag which can be set by EHCI controller
-not supporting or wanting to disable overcurrent checking. The EHCI
-platform data in include/linux/usb/ehci_pdriver.h is also augmented to
-take advantage of this new flag.
-
-Signed-off-by: Florian Fainelli <florian@openwrt.org>
-Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
-Link: https://lore.kernel.org/r/20210223174455.1378-2-noltari@gmail.com
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/usb/host/ehci-hcd.c | 2 +-
- drivers/usb/host/ehci-hub.c | 4 ++--
- drivers/usb/host/ehci-platform.c | 2 ++
- drivers/usb/host/ehci.h | 1 +
- include/linux/usb/ehci_pdriver.h | 1 +
- 5 files changed, 7 insertions(+), 3 deletions(-)
-
---- a/drivers/usb/host/ehci-hcd.c
-+++ b/drivers/usb/host/ehci-hcd.c
-@@ -660,7 +660,7 @@ static int ehci_run (struct usb_hcd *hcd
- "USB %x.%x started, EHCI %x.%02x%s\n",
- ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
- temp >> 8, temp & 0xff,
-- ignore_oc ? ", overcurrent ignored" : "");
-+ (ignore_oc || ehci->spurious_oc) ? ", overcurrent ignored" : "");
-
- ehci_writel(ehci, INTR_MASK,
- &ehci->regs->intr_enable); /* Turn On Interrupts */
---- a/drivers/usb/host/ehci-hub.c
-+++ b/drivers/usb/host/ehci-hub.c
-@@ -643,7 +643,7 @@ ehci_hub_status_data (struct usb_hcd *hc
- * always set, seem to clear PORT_OCC and PORT_CSC when writing to
- * PORT_POWER; that's surprising, but maybe within-spec.
- */
-- if (!ignore_oc)
-+ if (!ignore_oc && !ehci->spurious_oc)
- mask = PORT_CSC | PORT_PEC | PORT_OCC;
- else
- mask = PORT_CSC | PORT_PEC;
-@@ -1013,7 +1013,7 @@ int ehci_hub_control(
- if (temp & PORT_PEC)
- status |= USB_PORT_STAT_C_ENABLE << 16;
-
-- if ((temp & PORT_OCC) && !ignore_oc){
-+ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->spurious_oc)){
- status |= USB_PORT_STAT_C_OVERCURRENT << 16;
-
- /*
---- a/drivers/usb/host/ehci-platform.c
-+++ b/drivers/usb/host/ehci-platform.c
-@@ -333,6 +333,8 @@ static int ehci_platform_probe(struct pl
- hcd->has_tt = 1;
- if (pdata->reset_on_resume)
- priv->reset_on_resume = true;
-+ if (pdata->spurious_oc)
-+ ehci->spurious_oc = 1;
-
- #ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
- if (ehci->big_endian_mmio) {
---- a/drivers/usb/host/ehci.h
-+++ b/drivers/usb/host/ehci.h
-@@ -219,6 +219,7 @@ struct ehci_hcd { /* one per controlle
- unsigned need_oc_pp_cycle:1; /* MPC834X port power */
- unsigned imx28_write_fix:1; /* For Freescale i.MX28 */
- unsigned is_aspeed:1;
-+ unsigned spurious_oc:1;
-
- /* required for usb32 quirk */
- #define OHCI_CTRL_HCFS (3 << 6)
---- a/include/linux/usb/ehci_pdriver.h
-+++ b/include/linux/usb/ehci_pdriver.h
-@@ -50,6 +50,7 @@ struct usb_ehci_pdata {
- unsigned no_io_watchdog:1;
- unsigned reset_on_resume:1;
- unsigned dma_mask_64:1;
-+ unsigned spurious_oc:1;
-
- /* Turn on all power and clocks */
- int (*power_on)(struct platform_device *pdev);
--- /dev/null
+From 98830350d3fc824c1ff5c338140fe20f041a5916 Mon Sep 17 00:00:00 2001
+From: Claudiu Beznea <claudiu.beznea@microchip.com>
+Date: Wed, 6 Jul 2022 11:06:22 +0100
+Subject: [PATCH] nvmem: microchip-otpc: add support
+
+Add support for Microchip OTP controller available on SAMA7G5. The OTPC
+controls the access to a non-volatile memory. The memory behind OTPC is
+organized into packets, packets are composed by a fixed length header
+(4 bytes long) and a variable length payload (payload length is available
+in the header). When software request the data at an offset in memory
+the OTPC will return (via header + data registers) the whole packet that
+has a word at that offset. For the OTP memory layout like below:
+
+offset OTP Memory layout
+
+ . .
+ . ... .
+ . .
+0x0E +-----------+ <--- packet X
+ | header X |
+0x12 +-----------+
+ | payload X |
+0x16 | |
+ | |
+0x1A | |
+ +-----------+
+ . .
+ . ... .
+ . .
+
+if user requests data at address 0x16 the data started at 0x0E will be
+returned by controller. User will be able to fetch the whole packet
+starting at 0x0E (or parts of the packet) via proper registers. The same
+packet will be returned if software request the data at offset 0x0E or
+0x12 or 0x1A.
+
+The OTP will be populated by Microchip with at least 2 packets first one
+being boot configuration packet and the 2nd one being temperature
+calibration packet. The packet order will be preserved b/w different chip
+revisions but the packet sizes may change.
+
+For the above reasons and to keep the same software able to work on all
+chip variants the read function of the driver is working with a packet
+id instead of an offset in OTP memory.
+
+Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220706100627.6534-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ MAINTAINERS | 8 +
+ drivers/nvmem/Kconfig | 7 +
+ drivers/nvmem/Makefile | 2 +
+ drivers/nvmem/microchip-otpc.c | 288 +++++++++++++++++++++++++++++++++
+ 4 files changed, 305 insertions(+)
+ create mode 100644 drivers/nvmem/microchip-otpc.c
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -11565,6 +11565,14 @@ S: Supported
+ F: Documentation/devicetree/bindings/mtd/atmel-nand.txt
+ F: drivers/mtd/nand/raw/atmel/*
+
++MICROCHIP OTPC DRIVER
++M: Claudiu Beznea <claudiu.beznea@microchip.com>
++L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
++S: Supported
++F: Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
++F: drivers/nvmem/microchip-otpc.c
++F: dt-bindings/nvmem/microchip,sama7g5-otpc.h
++
+ MICROCHIP PWM DRIVER
+ M: Claudiu Beznea <claudiu.beznea@microchip.com>
+ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -107,6 +107,13 @@ config MTK_EFUSE
+ This driver can also be built as a module. If so, the module
+ will be called efuse-mtk.
+
++config MICROCHIP_OTPC
++ tristate "Microchip OTPC support"
++ depends on ARCH_AT91 || COMPILE_TEST
++ help
++ This driver enable the OTP controller available on Microchip SAMA7G5
++ SoCs. It controlls the access to the OTP memory connected to it.
++
+ config NVMEM_NINTENDO_OTP
+ tristate "Nintendo Wii and Wii U OTP Support"
+ depends on WII || COMPILE_TEST
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -67,3 +67,5 @@ obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvm
+ nvmem_sunplus_ocotp-y := sunplus-ocotp.o
+ obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
+ nvmem-apple-efuses-y := apple-efuses.o
++obj-$(CONFIG_MICROCHIP_OTPC) += nvmem-microchip-otpc.o
++nvmem-microchip-otpc-y := microchip-otpc.o
+--- /dev/null
++++ b/drivers/nvmem/microchip-otpc.c
+@@ -0,0 +1,288 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * OTP Memory controller
++ *
++ * Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries
++ *
++ * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
++ */
++
++#include <linux/bitfield.h>
++#include <linux/iopoll.h>
++#include <linux/module.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++
++#define MCHP_OTPC_CR (0x0)
++#define MCHP_OTPC_CR_READ BIT(6)
++#define MCHP_OTPC_MR (0x4)
++#define MCHP_OTPC_MR_ADDR GENMASK(31, 16)
++#define MCHP_OTPC_AR (0x8)
++#define MCHP_OTPC_SR (0xc)
++#define MCHP_OTPC_SR_READ BIT(6)
++#define MCHP_OTPC_HR (0x20)
++#define MCHP_OTPC_HR_SIZE GENMASK(15, 8)
++#define MCHP_OTPC_DR (0x24)
++
++#define MCHP_OTPC_NAME "mchp-otpc"
++#define MCHP_OTPC_SIZE (11 * 1024)
++
++/**
++ * struct mchp_otpc - OTPC private data structure
++ * @base: base address
++ * @dev: struct device pointer
++ * @packets: list of packets in OTP memory
++ * @npackets: number of packets in OTP memory
++ */
++struct mchp_otpc {
++ void __iomem *base;
++ struct device *dev;
++ struct list_head packets;
++ u32 npackets;
++};
++
++/**
++ * struct mchp_otpc_packet - OTPC packet data structure
++ * @list: list head
++ * @id: packet ID
++ * @offset: packet offset (in words) in OTP memory
++ */
++struct mchp_otpc_packet {
++ struct list_head list;
++ u32 id;
++ u32 offset;
++};
++
++static struct mchp_otpc_packet *mchp_otpc_id_to_packet(struct mchp_otpc *otpc,
++ u32 id)
++{
++ struct mchp_otpc_packet *packet;
++
++ if (id >= otpc->npackets)
++ return NULL;
++
++ list_for_each_entry(packet, &otpc->packets, list) {
++ if (packet->id == id)
++ return packet;
++ }
++
++ return NULL;
++}
++
++static int mchp_otpc_prepare_read(struct mchp_otpc *otpc,
++ unsigned int offset)
++{
++ u32 tmp;
++
++ /* Set address. */
++ tmp = readl_relaxed(otpc->base + MCHP_OTPC_MR);
++ tmp &= ~MCHP_OTPC_MR_ADDR;
++ tmp |= FIELD_PREP(MCHP_OTPC_MR_ADDR, offset);
++ writel_relaxed(tmp, otpc->base + MCHP_OTPC_MR);
++
++ /* Set read. */
++ tmp = readl_relaxed(otpc->base + MCHP_OTPC_CR);
++ tmp |= MCHP_OTPC_CR_READ;
++ writel_relaxed(tmp, otpc->base + MCHP_OTPC_CR);
++
++ /* Wait for packet to be transferred into temporary buffers. */
++ return read_poll_timeout(readl_relaxed, tmp, !(tmp & MCHP_OTPC_SR_READ),
++ 10000, 2000, false, otpc->base + MCHP_OTPC_SR);
++}
++
++/*
++ * OTPC memory is organized into packets. Each packets contains a header and
++ * a payload. Header is 4 bytes long and contains the size of the payload.
++ * Payload size varies. The memory footprint is something as follows:
++ *
++ * Memory offset Memory footprint Packet ID
++ * ------------- ---------------- ---------
++ *
++ * 0x0 +------------+ <-- packet 0
++ * | header 0 |
++ * 0x4 +------------+
++ * | payload 0 |
++ * . .
++ * . ... .
++ * . .
++ * offset1 +------------+ <-- packet 1
++ * | header 1 |
++ * offset1 + 0x4 +------------+
++ * | payload 1 |
++ * . .
++ * . ... .
++ * . .
++ * offset2 +------------+ <-- packet 2
++ * . .
++ * . ... .
++ * . .
++ * offsetN +------------+ <-- packet N
++ * | header N |
++ * offsetN + 0x4 +------------+
++ * | payload N |
++ * . .
++ * . ... .
++ * . .
++ * +------------+
++ *
++ * where offset1, offset2, offsetN depends on the size of payload 0, payload 1,
++ * payload N-1.
++ *
++ * The access to memory is done on a per packet basis: the control registers
++ * need to be updated with an offset address (within a packet range) and the
++ * data registers will be update by controller with information contained by
++ * that packet. E.g. if control registers are updated with any address within
++ * the range [offset1, offset2) the data registers are updated by controller
++ * with packet 1. Header data is accessible though MCHP_OTPC_HR register.
++ * Payload data is accessible though MCHP_OTPC_DR and MCHP_OTPC_AR registers.
++ * There is no direct mapping b/w the offset requested by software and the
++ * offset returned by hardware.
++ *
++ * For this, the read function will return the first requested bytes in the
++ * packet. The user will have to be aware of the memory footprint before doing
++ * the read request.
++ */
++static int mchp_otpc_read(void *priv, unsigned int off, void *val,
++ size_t bytes)
++{
++ struct mchp_otpc *otpc = priv;
++ struct mchp_otpc_packet *packet;
++ u32 *buf = val;
++ u32 offset;
++ size_t len = 0;
++ int ret, payload_size;
++
++ /*
++ * We reach this point with off being multiple of stride = 4 to
++ * be able to cross the subsystem. Inside the driver we use continuous
++ * unsigned integer numbers for packet id, thus devide off by 4
++ * before passing it to mchp_otpc_id_to_packet().
++ */
++ packet = mchp_otpc_id_to_packet(otpc, off / 4);
++ if (!packet)
++ return -EINVAL;
++ offset = packet->offset;
++
++ while (len < bytes) {
++ ret = mchp_otpc_prepare_read(otpc, offset);
++ if (ret)
++ return ret;
++
++ /* Read and save header content. */
++ *buf++ = readl_relaxed(otpc->base + MCHP_OTPC_HR);
++ len += sizeof(*buf);
++ offset++;
++ if (len >= bytes)
++ break;
++
++ /* Read and save payload content. */
++ payload_size = FIELD_GET(MCHP_OTPC_HR_SIZE, *(buf - 1));
++ writel_relaxed(0UL, otpc->base + MCHP_OTPC_AR);
++ do {
++ *buf++ = readl_relaxed(otpc->base + MCHP_OTPC_DR);
++ len += sizeof(*buf);
++ offset++;
++ payload_size--;
++ } while (payload_size >= 0 && len < bytes);
++ }
++
++ return 0;
++}
++
++static int mchp_otpc_init_packets_list(struct mchp_otpc *otpc, u32 *size)
++{
++ struct mchp_otpc_packet *packet;
++ u32 word, word_pos = 0, id = 0, npackets = 0, payload_size;
++ int ret;
++
++ INIT_LIST_HEAD(&otpc->packets);
++ *size = 0;
++
++ while (*size < MCHP_OTPC_SIZE) {
++ ret = mchp_otpc_prepare_read(otpc, word_pos);
++ if (ret)
++ return ret;
++
++ word = readl_relaxed(otpc->base + MCHP_OTPC_HR);
++ payload_size = FIELD_GET(MCHP_OTPC_HR_SIZE, word);
++ if (!payload_size)
++ break;
++
++ packet = devm_kzalloc(otpc->dev, sizeof(*packet), GFP_KERNEL);
++ if (!packet)
++ return -ENOMEM;
++
++ packet->id = id++;
++ packet->offset = word_pos;
++ INIT_LIST_HEAD(&packet->list);
++ list_add_tail(&packet->list, &otpc->packets);
++
++ /* Count size by adding header and paload sizes. */
++ *size += 4 * (payload_size + 1);
++ /* Next word: this packet (header, payload) position + 1. */
++ word_pos += payload_size + 2;
++
++ npackets++;
++ }
++
++ otpc->npackets = npackets;
++
++ return 0;
++}
++
++static struct nvmem_config mchp_nvmem_config = {
++ .name = MCHP_OTPC_NAME,
++ .type = NVMEM_TYPE_OTP,
++ .read_only = true,
++ .word_size = 4,
++ .stride = 4,
++ .reg_read = mchp_otpc_read,
++};
++
++static int mchp_otpc_probe(struct platform_device *pdev)
++{
++ struct nvmem_device *nvmem;
++ struct mchp_otpc *otpc;
++ u32 size;
++ int ret;
++
++ otpc = devm_kzalloc(&pdev->dev, sizeof(*otpc), GFP_KERNEL);
++ if (!otpc)
++ return -ENOMEM;
++
++ otpc->base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(otpc->base))
++ return PTR_ERR(otpc->base);
++
++ otpc->dev = &pdev->dev;
++ ret = mchp_otpc_init_packets_list(otpc, &size);
++ if (ret)
++ return ret;
++
++ mchp_nvmem_config.dev = otpc->dev;
++ mchp_nvmem_config.size = size;
++ mchp_nvmem_config.priv = otpc;
++ nvmem = devm_nvmem_register(&pdev->dev, &mchp_nvmem_config);
++
++ return PTR_ERR_OR_ZERO(nvmem);
++}
++
++static const struct of_device_id __maybe_unused mchp_otpc_ids[] = {
++ { .compatible = "microchip,sama7g5-otpc", },
++ { },
++};
++MODULE_DEVICE_TABLE(of, mchp_otpc_ids);
++
++static struct platform_driver mchp_otpc_driver = {
++ .probe = mchp_otpc_probe,
++ .driver = {
++ .name = MCHP_OTPC_NAME,
++ .of_match_table = of_match_ptr(mchp_otpc_ids),
++ },
++};
++module_platform_driver(mchp_otpc_driver);
++
++MODULE_AUTHOR("Claudiu Beznea <claudiu.beznea@microchip.com>");
++MODULE_DESCRIPTION("Microchip SAMA7G5 OTPC driver");
++MODULE_LICENSE("GPL");
--- /dev/null
+From f5c97da8037b18d1256a58459fa96ed68e50fb41 Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Wed, 6 Jul 2022 11:06:27 +0100
+Subject: [PATCH] nvmem: mtk-efuse: Simplify with
+ devm_platform_get_and_ioremap_resource()
+
+Convert platform_get_resource(), devm_ioremap_resource() to a single
+call to devm_platform_get_and_ioremap_resource(), as this is exactly
+what this function does.
+
+No functional changes.
+
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220706100627.6534-8-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/mtk-efuse.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/nvmem/mtk-efuse.c
++++ b/drivers/nvmem/mtk-efuse.c
+@@ -41,8 +41,7 @@ static int mtk_efuse_probe(struct platfo
+ if (!priv)
+ return -ENOMEM;
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- priv->base = devm_ioremap_resource(dev, res);
++ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+++ /dev/null
-From 4da57dbbffdfa7fe4e2b70b047fc5ff95ff25a3d Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
-Date: Tue, 23 Feb 2021 18:44:55 +0100
-Subject: [PATCH 3/3] usb: host: ehci-platform: add spurious_oc DT support
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Over-current reporting isn't supported on some platforms such as bcm63xx.
-These devices will incorrectly report over-current if this flag isn't properly
-activated.
-
-Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
-Link: https://lore.kernel.org/r/20210223174455.1378-4-noltari@gmail.com
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/usb/host/ehci-platform.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/drivers/usb/host/ehci-platform.c
-+++ b/drivers/usb/host/ehci-platform.c
-@@ -286,6 +286,9 @@ static int ehci_platform_probe(struct pl
- if (of_property_read_bool(dev->dev.of_node, "big-endian"))
- ehci->big_endian_mmio = ehci->big_endian_desc = 1;
-
-+ if (of_property_read_bool(dev->dev.of_node, "spurious-oc"))
-+ ehci->spurious_oc = 1;
-+
- if (of_property_read_bool(dev->dev.of_node,
- "needs-reset-on-resume"))
- priv->reset_on_resume = true;
--- /dev/null
+From bd1244561fa2a4531ded40dbf09c9599084f8b29 Mon Sep 17 00:00:00 2001
+From: Gaosheng Cui <cuigaosheng1@huawei.com>
+Date: Fri, 16 Sep 2022 13:04:02 +0100
+Subject: [PATCH] nvmem: core: Fix memleak in nvmem_register()
+
+dev_set_name will alloc memory for nvmem->dev.kobj.name in
+nvmem_register, when nvmem_validate_keepouts failed, nvmem's
+memory will be freed and return, but nobody will free memory
+for nvmem->dev.kobj.name, there will be memleak, so moving
+nvmem_validate_keepouts() after device_register() and let
+the device core deal with cleaning name in error cases.
+
+Fixes: de0534df9347 ("nvmem: core: fix error handling while validating keepout regions")
+Cc: stable@vger.kernel.org
+Signed-off-by: Gaosheng Cui <cuigaosheng1@huawei.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916120402.38753-1-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 15 ++++++---------
+ 1 file changed, 6 insertions(+), 9 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -829,21 +829,18 @@ struct nvmem_device *nvmem_register(cons
+ nvmem->dev.groups = nvmem_dev_groups;
+ #endif
+
+- if (nvmem->nkeepout) {
+- rval = nvmem_validate_keepouts(nvmem);
+- if (rval) {
+- ida_free(&nvmem_ida, nvmem->id);
+- kfree(nvmem);
+- return ERR_PTR(rval);
+- }
+- }
+-
+ dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
+
+ rval = device_register(&nvmem->dev);
+ if (rval)
+ goto err_put_device;
+
++ if (nvmem->nkeepout) {
++ rval = nvmem_validate_keepouts(nvmem);
++ if (rval)
++ goto err_device_del;
++ }
++
+ if (config->compat) {
+ rval = nvmem_sysfs_setup_compat(nvmem, config);
+ if (rval)
--- /dev/null
+From d5542923f200f95bddf524f36fd495f78aa28e3c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 16 Sep 2022 13:20:48 +0100
+Subject: [PATCH] nvmem: add driver handling U-Boot environment variables
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+U-Boot stores its setup as environment variables. It's a list of
+key-value pairs stored on flash device with a custom header.
+
+This commit adds an NVMEM driver that:
+1. Provides NVMEM access to environment vars binary data
+2. Extracts variables as NVMEM cells
+
+Current Linux's NVMEM sysfs API allows reading whole NVMEM data block.
+It can be used by user-space tools for reading U-Boot env vars block
+without the hassle of finding its location. Parsing will still need to
+be re-done there.
+
+Kernel-parsed NVMEM cells can be read however by Linux drivers. This may
+be useful for Ethernet drivers for reading device MAC address which is
+often stored as U-Boot env variable.
+
+Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ MAINTAINERS | 1 +
+ drivers/nvmem/Kconfig | 13 +++
+ drivers/nvmem/Makefile | 2 +
+ drivers/nvmem/u-boot-env.c | 218 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 234 insertions(+)
+ create mode 100644 drivers/nvmem/u-boot-env.c
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -344,4 +344,17 @@ config NVMEM_APPLE_EFUSES
+ This driver can also be built as a module. If so, the module will
+ be called nvmem-apple-efuses.
+
++config NVMEM_U_BOOT_ENV
++ tristate "U-Boot environment variables support"
++ depends on OF && MTD
++ select CRC32
++ help
++ U-Boot stores its setup as environment variables. This driver adds
++ support for verifying & exporting such data. It also exposes variables
++ as NVMEM cells so they can be referenced by other drivers.
++
++ Currently this drivers works only with env variables on top of MTD.
++
++ If compiled as module it will be called nvmem_u-boot-env.
++
+ endif
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -69,3 +69,5 @@ obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvme
+ nvmem-apple-efuses-y := apple-efuses.o
+ obj-$(CONFIG_MICROCHIP_OTPC) += nvmem-microchip-otpc.o
+ nvmem-microchip-otpc-y := microchip-otpc.o
++obj-$(CONFIG_NVMEM_U_BOOT_ENV) += nvmem_u-boot-env.o
++nvmem_u-boot-env-y := u-boot-env.o
+--- /dev/null
++++ b/drivers/nvmem/u-boot-env.c
+@@ -0,0 +1,218 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Copyright (C) 2022 Rafał Miłecki <rafal@milecki.pl>
++ */
++
++#include <linux/crc32.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/mtd/mtd.h>
++#include <linux/nvmem-consumer.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++enum u_boot_env_format {
++ U_BOOT_FORMAT_SINGLE,
++ U_BOOT_FORMAT_REDUNDANT,
++};
++
++struct u_boot_env {
++ struct device *dev;
++ enum u_boot_env_format format;
++
++ struct mtd_info *mtd;
++
++ /* Cells */
++ struct nvmem_cell_info *cells;
++ int ncells;
++};
++
++struct u_boot_env_image_single {
++ __le32 crc32;
++ uint8_t data[];
++} __packed;
++
++struct u_boot_env_image_redundant {
++ __le32 crc32;
++ u8 mark;
++ uint8_t data[];
++} __packed;
++
++static int u_boot_env_read(void *context, unsigned int offset, void *val,
++ size_t bytes)
++{
++ struct u_boot_env *priv = context;
++ struct device *dev = priv->dev;
++ size_t bytes_read;
++ int err;
++
++ err = mtd_read(priv->mtd, offset, bytes, &bytes_read, val);
++ if (err && !mtd_is_bitflip(err)) {
++ dev_err(dev, "Failed to read from mtd: %d\n", err);
++ return err;
++ }
++
++ if (bytes_read != bytes) {
++ dev_err(dev, "Failed to read %zu bytes\n", bytes);
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf,
++ size_t data_offset, size_t data_len)
++{
++ struct device *dev = priv->dev;
++ char *data = buf + data_offset;
++ char *var, *value, *eq;
++ int idx;
++
++ priv->ncells = 0;
++ for (var = data; var < data + 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, idx = 0;
++ var < data + 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 = data_offset + value - data;
++ priv->cells[idx].bytes = strlen(value);
++ }
++
++ if (WARN_ON(idx != priv->ncells))
++ priv->ncells = idx;
++
++ return 0;
++}
++
++static int u_boot_env_parse(struct u_boot_env *priv)
++{
++ struct device *dev = priv->dev;
++ size_t crc32_data_offset;
++ size_t crc32_data_len;
++ size_t crc32_offset;
++ size_t data_offset;
++ size_t data_len;
++ uint32_t crc32;
++ uint32_t calc;
++ size_t bytes;
++ uint8_t *buf;
++ int err;
++
++ buf = kcalloc(1, priv->mtd->size, GFP_KERNEL);
++ if (!buf) {
++ err = -ENOMEM;
++ goto err_out;
++ }
++
++ err = mtd_read(priv->mtd, 0, priv->mtd->size, &bytes, buf);
++ if ((err && !mtd_is_bitflip(err)) || bytes != priv->mtd->size) {
++ dev_err(dev, "Failed to read from mtd: %d\n", err);
++ goto err_kfree;
++ }
++
++ switch (priv->format) {
++ case U_BOOT_FORMAT_SINGLE:
++ crc32_offset = offsetof(struct u_boot_env_image_single, crc32);
++ crc32_data_offset = offsetof(struct u_boot_env_image_single, data);
++ data_offset = offsetof(struct u_boot_env_image_single, data);
++ break;
++ case U_BOOT_FORMAT_REDUNDANT:
++ crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32);
++ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, mark);
++ data_offset = offsetof(struct u_boot_env_image_redundant, data);
++ break;
++ }
++ crc32 = le32_to_cpu(*(uint32_t *)(buf + crc32_offset));
++ crc32_data_len = priv->mtd->size - crc32_data_offset;
++ data_len = priv->mtd->size - data_offset;
++
++ calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L;
++ if (calc != crc32) {
++ dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32);
++ err = -EINVAL;
++ goto err_kfree;
++ }
++
++ buf[priv->mtd->size - 1] = '\0';
++ err = u_boot_env_add_cells(priv, buf, data_offset, data_len);
++ if (err)
++ dev_err(dev, "Failed to add cells: %d\n", err);
++
++err_kfree:
++ kfree(buf);
++err_out:
++ return err;
++}
++
++static int u_boot_env_probe(struct platform_device *pdev)
++{
++ struct nvmem_config config = {
++ .name = "u-boot-env",
++ .reg_read = u_boot_env_read,
++ };
++ struct device *dev = &pdev->dev;
++ struct device_node *np = dev->of_node;
++ struct u_boot_env *priv;
++ int err;
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++ priv->dev = dev;
++
++ priv->format = (uintptr_t)of_device_get_match_data(dev);
++
++ priv->mtd = of_get_mtd_device_by_node(np);
++ if (IS_ERR(priv->mtd)) {
++ dev_err_probe(dev, PTR_ERR(priv->mtd), "Failed to get %pOF MTD\n", np);
++ return PTR_ERR(priv->mtd);
++ }
++
++ err = u_boot_env_parse(priv);
++ if (err)
++ return err;
++
++ config.dev = dev;
++ config.cells = priv->cells;
++ config.ncells = priv->ncells;
++ config.priv = priv;
++ config.size = priv->mtd->size;
++
++ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config));
++}
++
++static const struct of_device_id u_boot_env_of_match_table[] = {
++ { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, },
++ { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
++ { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
++ {},
++};
++
++static struct platform_driver u_boot_env_driver = {
++ .probe = u_boot_env_probe,
++ .driver = {
++ .name = "u_boot_env",
++ .of_match_table = u_boot_env_of_match_table,
++ },
++};
++module_platform_driver(u_boot_env_driver);
++
++MODULE_AUTHOR("Rafał Miłecki");
++MODULE_LICENSE("GPL");
++MODULE_DEVICE_TABLE(of, u_boot_env_of_match_table);
--- /dev/null
+From 5544e90c81261e82e02bbf7c6015a4b9c8c825ef Mon Sep 17 00:00:00 2001
+From: Gaosheng Cui <cuigaosheng1@huawei.com>
+Date: Fri, 16 Sep 2022 13:20:50 +0100
+Subject: [PATCH] nvmem: core: add error handling for dev_set_name
+
+The type of return value of dev_set_name is int, which may return
+wrong result, so we add error handling for it to reclaim memory
+of nvmem resource, and return early when an error occurs.
+
+Signed-off-by: Gaosheng Cui <cuigaosheng1@huawei.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-4-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -810,18 +810,24 @@ struct nvmem_device *nvmem_register(cons
+
+ switch (config->id) {
+ case NVMEM_DEVID_NONE:
+- dev_set_name(&nvmem->dev, "%s", config->name);
++ rval = dev_set_name(&nvmem->dev, "%s", config->name);
+ break;
+ case NVMEM_DEVID_AUTO:
+- dev_set_name(&nvmem->dev, "%s%d", config->name, nvmem->id);
++ rval = dev_set_name(&nvmem->dev, "%s%d", config->name, nvmem->id);
+ break;
+ default:
+- dev_set_name(&nvmem->dev, "%s%d",
++ rval = dev_set_name(&nvmem->dev, "%s%d",
+ config->name ? : "nvmem",
+ config->name ? config->id : nvmem->id);
+ break;
+ }
+
++ if (rval) {
++ ida_free(&nvmem_ida, nvmem->id);
++ kfree(nvmem);
++ return ERR_PTR(rval);
++ }
++
+ nvmem->read_only = device_property_present(config->dev, "read-only") ||
+ config->read_only || !nvmem->reg_write;
+
--- /dev/null
+From d3524bb5b9a0c567b853a0024526afe87dde01ed Mon Sep 17 00:00:00 2001
+From: Kenneth Lee <klee33@uw.edu>
+Date: Fri, 16 Sep 2022 13:20:52 +0100
+Subject: [PATCH] nvmem: brcm_nvram: Use kzalloc for allocating only one
+ element
+
+Use kzalloc(...) rather than kcalloc(1, ...) because the number of
+elements we are specifying in this case is 1, so kzalloc would
+accomplish the same thing and we can simplify.
+
+Signed-off-by: Kenneth Lee <klee33@uw.edu>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-6-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/brcm_nvram.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/brcm_nvram.c
++++ b/drivers/nvmem/brcm_nvram.c
+@@ -96,7 +96,7 @@ static int brcm_nvram_parse(struct brcm_
+
+ len = le32_to_cpu(header.len);
+
+- data = kcalloc(1, len, GFP_KERNEL);
++ data = kzalloc(len, GFP_KERNEL);
+ memcpy_fromio(data, priv->base, len);
+ data[len - 1] = '\0';
+
--- /dev/null
+From 28fc7c986f01fdcfd28af648be2597624cac0e27 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 16 Sep 2022 13:20:54 +0100
+Subject: [PATCH] nvmem: prefix all symbols with NVMEM_
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This unifies all NVMEM symbols. They follow one style now.
+
+Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-8-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/configs/multi_v7_defconfig | 6 +++---
+ arch/arm/configs/qcom_defconfig | 2 +-
+ arch/arm64/configs/defconfig | 10 +++++-----
+ arch/mips/configs/ci20_defconfig | 2 +-
+ drivers/cpufreq/Kconfig.arm | 2 +-
+ drivers/nvmem/Kconfig | 24 ++++++++++++------------
+ drivers/nvmem/Makefile | 24 ++++++++++++------------
+ drivers/soc/mediatek/Kconfig | 2 +-
+ drivers/thermal/qcom/Kconfig | 2 +-
+ 9 files changed, 37 insertions(+), 37 deletions(-)
+
+--- a/arch/arm/configs/multi_v7_defconfig
++++ b/arch/arm/configs/multi_v7_defconfig
+@@ -1085,10 +1085,10 @@ CONFIG_OMAP_USB2=y
+ CONFIG_TI_PIPE3=y
+ CONFIG_TWL4030_USB=m
+ CONFIG_NVMEM_IMX_OCOTP=y
+-CONFIG_ROCKCHIP_EFUSE=m
++CONFIG_NVMEM_ROCKCHIP_EFUSE=m
+ CONFIG_NVMEM_SUNXI_SID=y
+ CONFIG_NVMEM_VF610_OCOTP=y
+-CONFIG_MESON_MX_EFUSE=m
++CONFIG_NVMEM_MESON_MX_EFUSE=m
+ CONFIG_FSI=m
+ CONFIG_FSI_MASTER_GPIO=m
+ CONFIG_FSI_MASTER_HUB=m
+--- a/arch/arm/configs/qcom_defconfig
++++ b/arch/arm/configs/qcom_defconfig
+@@ -257,7 +257,7 @@ CONFIG_PHY_QCOM_APQ8064_SATA=y
+ CONFIG_PHY_QCOM_IPQ806X_SATA=y
+ CONFIG_PHY_QCOM_USB_HS=y
+ CONFIG_PHY_QCOM_USB_HSIC=y
+-CONFIG_QCOM_QFPROM=y
++CONFIG_NVMEM_QCOM_QFPROM=y
+ CONFIG_INTERCONNECT=y
+ CONFIG_INTERCONNECT_QCOM=y
+ CONFIG_INTERCONNECT_QCOM_MSM8974=m
+--- a/arch/arm64/configs/defconfig
++++ b/arch/arm64/configs/defconfig
+@@ -1022,11 +1022,11 @@ CONFIG_QCOM_L2_PMU=y
+ CONFIG_QCOM_L3_PMU=y
+ CONFIG_NVMEM_IMX_OCOTP=y
+ CONFIG_NVMEM_IMX_OCOTP_SCU=y
+-CONFIG_QCOM_QFPROM=y
+-CONFIG_ROCKCHIP_EFUSE=y
++CONFIG_NVMEM_QCOM_QFPROM=y
++CONFIG_NVMEM_ROCKCHIP_EFUSE=y
+ CONFIG_NVMEM_SUNXI_SID=y
+-CONFIG_UNIPHIER_EFUSE=y
+-CONFIG_MESON_EFUSE=m
++CONFIG_NVMEM_UNIPHIER_EFUSE=y
++CONFIG_NVMEM_MESON_EFUSE=m
+ CONFIG_FPGA=y
+ CONFIG_FPGA_MGR_STRATIX10_SOC=m
+ CONFIG_FPGA_BRIDGE=m
+--- a/drivers/cpufreq/Kconfig.arm
++++ b/drivers/cpufreq/Kconfig.arm
+@@ -131,7 +131,7 @@ config ARM_OMAP2PLUS_CPUFREQ
+ config ARM_QCOM_CPUFREQ_NVMEM
+ tristate "Qualcomm nvmem based CPUFreq"
+ depends on ARCH_QCOM
+- depends on QCOM_QFPROM
++ depends on NVMEM_QCOM_QFPROM
+ depends on QCOM_SMEM
+ select PM_OPP
+ help
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -52,7 +52,7 @@ config NVMEM_IMX_OCOTP_SCU
+ This is a driver for the SCU On-Chip OTP Controller (OCOTP)
+ available on i.MX8 SoCs.
+
+-config JZ4780_EFUSE
++config NVMEM_JZ4780_EFUSE
+ tristate "JZ4780 EFUSE Memory Support"
+ depends on MACH_INGENIC || COMPILE_TEST
+ depends on HAS_IOMEM
+@@ -96,7 +96,7 @@ config NVMEM_MXS_OCOTP
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-mxs-ocotp.
+
+-config MTK_EFUSE
++config NVMEM_MTK_EFUSE
+ tristate "Mediatek SoCs EFUSE support"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ depends on HAS_IOMEM
+@@ -107,7 +107,7 @@ config MTK_EFUSE
+ This driver can also be built as a module. If so, the module
+ will be called efuse-mtk.
+
+-config MICROCHIP_OTPC
++config NVMEM_MICROCHIP_OTPC
+ tristate "Microchip OTPC support"
+ depends on ARCH_AT91 || COMPILE_TEST
+ help
+@@ -126,7 +126,7 @@ config NVMEM_NINTENDO_OTP
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-nintendo-otp.
+
+-config QCOM_QFPROM
++config NVMEM_QCOM_QFPROM
+ tristate "QCOM QFPROM Support"
+ depends on ARCH_QCOM || COMPILE_TEST
+ depends on HAS_IOMEM
+@@ -145,7 +145,7 @@ config NVMEM_SPMI_SDAM
+ Qualcomm Technologies, Inc. PMICs. It provides the clients
+ an interface to read/write to the SDAM module's shared memory.
+
+-config ROCKCHIP_EFUSE
++config NVMEM_ROCKCHIP_EFUSE
+ tristate "Rockchip eFuse Support"
+ depends on ARCH_ROCKCHIP || COMPILE_TEST
+ depends on HAS_IOMEM
+@@ -156,7 +156,7 @@ config ROCKCHIP_EFUSE
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_rockchip_efuse.
+
+-config ROCKCHIP_OTP
++config NVMEM_ROCKCHIP_OTP
+ tristate "Rockchip OTP controller support"
+ depends on ARCH_ROCKCHIP || COMPILE_TEST
+ depends on HAS_IOMEM
+@@ -199,7 +199,7 @@ config NVMEM_SUNXI_SID
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_sunxi_sid.
+
+-config UNIPHIER_EFUSE
++config NVMEM_UNIPHIER_EFUSE
+ tristate "UniPhier SoCs eFuse support"
+ depends on ARCH_UNIPHIER || COMPILE_TEST
+ depends on HAS_IOMEM
+@@ -221,7 +221,7 @@ config NVMEM_VF610_OCOTP
+ This driver can also be build as a module. If so, the module will
+ be called nvmem-vf610-ocotp.
+
+-config MESON_EFUSE
++config NVMEM_MESON_EFUSE
+ tristate "Amlogic Meson GX eFuse Support"
+ depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM
+ help
+@@ -231,7 +231,7 @@ config MESON_EFUSE
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_meson_efuse.
+
+-config MESON_MX_EFUSE
++config NVMEM_MESON_MX_EFUSE
+ tristate "Amlogic Meson6/Meson8/Meson8b eFuse Support"
+ depends on ARCH_MESON || COMPILE_TEST
+ help
+@@ -251,13 +251,13 @@ config NVMEM_SNVS_LPGPR
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-snvs-lpgpr.
+
+-config RAVE_SP_EEPROM
++config NVMEM_RAVE_SP_EEPROM
+ tristate "Rave SP EEPROM Support"
+ depends on RAVE_SP_CORE
+ help
+ Say y here to enable Rave SP EEPROM support.
+
+-config SC27XX_EFUSE
++config NVMEM_SC27XX_EFUSE
+ tristate "Spreadtrum SC27XX eFuse Support"
+ depends on MFD_SC27XX_PMIC || COMPILE_TEST
+ depends on HAS_IOMEM
+@@ -278,7 +278,7 @@ config NVMEM_ZYNQMP
+
+ If sure, say yes. If unsure, say no.
+
+-config SPRD_EFUSE
++config NVMEM_SPRD_EFUSE
+ tristate "Spreadtrum SoC eFuse Support"
+ depends on ARCH_SPRD || COMPILE_TEST
+ depends on HAS_IOMEM
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -15,7 +15,7 @@ obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-i
+ nvmem-imx-ocotp-y := imx-ocotp.o
+ obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvmem-imx-ocotp-scu.o
+ nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o
+-obj-$(CONFIG_JZ4780_EFUSE) += nvmem_jz4780_efuse.o
++obj-$(CONFIG_NVMEM_JZ4780_EFUSE) += nvmem_jz4780_efuse.o
+ nvmem_jz4780_efuse-y := jz4780-efuse.o
+ obj-$(CONFIG_NVMEM_LPC18XX_EEPROM) += nvmem_lpc18xx_eeprom.o
+ nvmem_lpc18xx_eeprom-y := lpc18xx_eeprom.o
+@@ -25,37 +25,37 @@ obj-$(CONFIG_NVMEM_MXS_OCOTP) += nvmem-m
+ nvmem-mxs-ocotp-y := mxs-ocotp.o
+ obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvmem-nintendo-otp.o
+ nvmem-nintendo-otp-y := nintendo-otp.o
+-obj-$(CONFIG_MTK_EFUSE) += nvmem_mtk-efuse.o
++obj-$(CONFIG_NVMEM_MTK_EFUSE) += nvmem_mtk-efuse.o
+ nvmem_mtk-efuse-y := mtk-efuse.o
+-obj-$(CONFIG_QCOM_QFPROM) += nvmem_qfprom.o
++obj-$(CONFIG_NVMEM_QCOM_QFPROM) += nvmem_qfprom.o
+ nvmem_qfprom-y := qfprom.o
+ obj-$(CONFIG_NVMEM_SPMI_SDAM) += nvmem_qcom-spmi-sdam.o
+ nvmem_qcom-spmi-sdam-y += qcom-spmi-sdam.o
+-obj-$(CONFIG_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o
++obj-$(CONFIG_NVMEM_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o
+ nvmem_rockchip_efuse-y := rockchip-efuse.o
+-obj-$(CONFIG_ROCKCHIP_OTP) += nvmem-rockchip-otp.o
++obj-$(CONFIG_NVMEM_ROCKCHIP_OTP) += nvmem-rockchip-otp.o
+ nvmem-rockchip-otp-y := rockchip-otp.o
+ obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o
+ nvmem_stm32_romem-y := stm32-romem.o
+ obj-$(CONFIG_NVMEM_STM32_ROMEM) += nvmem_stm32_romem.o
+ nvmem_sunxi_sid-y := sunxi_sid.o
+-obj-$(CONFIG_UNIPHIER_EFUSE) += nvmem-uniphier-efuse.o
++obj-$(CONFIG_NVMEM_UNIPHIER_EFUSE) += nvmem-uniphier-efuse.o
+ nvmem-uniphier-efuse-y := uniphier-efuse.o
+ obj-$(CONFIG_NVMEM_VF610_OCOTP) += nvmem-vf610-ocotp.o
+ nvmem-vf610-ocotp-y := vf610-ocotp.o
+-obj-$(CONFIG_MESON_EFUSE) += nvmem_meson_efuse.o
++obj-$(CONFIG_NVMEM_MESON_EFUSE) += nvmem_meson_efuse.o
+ nvmem_meson_efuse-y := meson-efuse.o
+-obj-$(CONFIG_MESON_MX_EFUSE) += nvmem_meson_mx_efuse.o
++obj-$(CONFIG_NVMEM_MESON_MX_EFUSE) += nvmem_meson_mx_efuse.o
+ nvmem_meson_mx_efuse-y := meson-mx-efuse.o
+ obj-$(CONFIG_NVMEM_SNVS_LPGPR) += nvmem_snvs_lpgpr.o
+ nvmem_snvs_lpgpr-y := snvs_lpgpr.o
+-obj-$(CONFIG_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
++obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
+ nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
+-obj-$(CONFIG_SC27XX_EFUSE) += nvmem-sc27xx-efuse.o
++obj-$(CONFIG_NVMEM_SC27XX_EFUSE) += nvmem-sc27xx-efuse.o
+ nvmem-sc27xx-efuse-y := sc27xx-efuse.o
+ obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynqmp_nvmem.o
+ nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o
+-obj-$(CONFIG_SPRD_EFUSE) += nvmem_sprd_efuse.o
++obj-$(CONFIG_NVMEM_SPRD_EFUSE) += nvmem_sprd_efuse.o
+ nvmem_sprd_efuse-y := sprd-efuse.o
+ obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o
+ nvmem-rmem-y := rmem.o
+@@ -67,7 +67,7 @@ obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvm
+ nvmem_sunplus_ocotp-y := sunplus-ocotp.o
+ obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
+ nvmem-apple-efuses-y := apple-efuses.o
+-obj-$(CONFIG_MICROCHIP_OTPC) += nvmem-microchip-otpc.o
++obj-$(CONFIG_NVMEM_MICROCHIP_OTPC) += nvmem-microchip-otpc.o
+ nvmem-microchip-otpc-y := microchip-otpc.o
+ obj-$(CONFIG_NVMEM_U_BOOT_ENV) += nvmem_u-boot-env.o
+ nvmem_u-boot-env-y := u-boot-env.o
+--- a/drivers/thermal/qcom/Kconfig
++++ b/drivers/thermal/qcom/Kconfig
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ config QCOM_TSENS
+ tristate "Qualcomm TSENS Temperature Alarm"
+- depends on QCOM_QFPROM
++ depends on NVMEM_QCOM_QFPROM
+ depends on ARCH_QCOM || COMPILE_TEST
+ help
+ This enables the thermal sysfs driver for the TSENS device. It shows
--- /dev/null
+From a06d9e5a63b7c2f622c908cd9600ce735e70f7c6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 16 Sep 2022 13:20:55 +0100
+Subject: [PATCH] nvmem: sort config symbols alphabetically
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+1. Match what most subsystems do
+2. Simplify maintenance a bit
+3. Reduce amount of conflicts for new drivers patches
+
+While at it unify indent level in Makefile.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-9-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/Kconfig | 300 +++++++++++++++++++++--------------------
+ drivers/nvmem/Makefile | 114 ++++++++--------
+ 2 files changed, 208 insertions(+), 206 deletions(-)
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -21,6 +21,40 @@ config NVMEM_SYSFS
+ This interface is mostly used by userspace applications to
+ read/write directly into nvmem.
+
++# Devices
++
++config NVMEM_APPLE_EFUSES
++ tristate "Apple eFuse support"
++ depends on ARCH_APPLE || COMPILE_TEST
++ default ARCH_APPLE
++ help
++ Say y here to enable support for reading eFuses on Apple SoCs
++ such as the M1. These are e.g. used to store factory programmed
++ calibration data required for the PCIe or the USB-C PHY.
++
++ This driver can also be built as a module. If so, the module will
++ be called nvmem-apple-efuses.
++
++config NVMEM_BCM_OCOTP
++ tristate "Broadcom On-Chip OTP Controller support"
++ depends on ARCH_BCM_IPROC || COMPILE_TEST
++ depends on HAS_IOMEM
++ default ARCH_BCM_IPROC
++ help
++ Say y here to enable read/write access to the Broadcom OTP
++ controller.
++
++ This driver can also be built as a module. If so, the module
++ will be called nvmem-bcm-ocotp.
++
++config NVMEM_BRCM_NVRAM
++ tristate "Broadcom's NVRAM support"
++ depends on ARCH_BCM_5301X || COMPILE_TEST
++ depends on HAS_IOMEM
++ help
++ This driver provides support for Broadcom's NVRAM that can be accessed
++ using I/O mapping.
++
+ config NVMEM_IMX_IIM
+ tristate "i.MX IC Identification Module support"
+ depends on ARCH_MXC || COMPILE_TEST
+@@ -64,6 +98,19 @@ config NVMEM_JZ4780_EFUSE
+ To compile this driver as a module, choose M here: the module
+ will be called nvmem_jz4780_efuse.
+
++config NVMEM_LAYERSCAPE_SFP
++ tristate "Layerscape SFP (Security Fuse Processor) support"
++ depends on ARCH_LAYERSCAPE || COMPILE_TEST
++ depends on HAS_IOMEM
++ select REGMAP_MMIO
++ help
++ This driver provides support to read the eFuses on Freescale
++ Layerscape SoC's. For example, the vendor provides a per part
++ unique ID there.
++
++ This driver can also be built as a module. If so, the module
++ will be called layerscape-sfp.
++
+ config NVMEM_LPC18XX_EEPROM
+ tristate "NXP LPC18XX EEPROM Memory Support"
+ depends on ARCH_LPC18XX || COMPILE_TEST
+@@ -84,17 +131,32 @@ config NVMEM_LPC18XX_OTP
+ To compile this driver as a module, choose M here: the module
+ will be called nvmem_lpc18xx_otp.
+
+-config NVMEM_MXS_OCOTP
+- tristate "Freescale MXS On-Chip OTP Memory Support"
+- depends on ARCH_MXS || COMPILE_TEST
+- depends on HAS_IOMEM
++config NVMEM_MESON_EFUSE
++ tristate "Amlogic Meson GX eFuse Support"
++ depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM
+ help
+- If you say Y here, you will get readonly access to the
+- One Time Programmable memory pages that are stored
+- on the Freescale i.MX23/i.MX28 processor.
++ This is a driver to retrieve specific values from the eFuse found on
++ the Amlogic Meson GX SoCs.
+
+ This driver can also be built as a module. If so, the module
+- will be called nvmem-mxs-ocotp.
++ will be called nvmem_meson_efuse.
++
++config NVMEM_MESON_MX_EFUSE
++ tristate "Amlogic Meson6/Meson8/Meson8b eFuse Support"
++ depends on ARCH_MESON || COMPILE_TEST
++ help
++ This is a driver to retrieve specific values from the eFuse found on
++ the Amlogic Meson6, Meson8 and Meson8b SoCs.
++
++ This driver can also be built as a module. If so, the module
++ will be called nvmem_meson_mx_efuse.
++
++config NVMEM_MICROCHIP_OTPC
++ tristate "Microchip OTPC support"
++ depends on ARCH_AT91 || COMPILE_TEST
++ help
++ This driver enable the OTP controller available on Microchip SAMA7G5
++ SoCs. It controlls the access to the OTP memory connected to it.
+
+ config NVMEM_MTK_EFUSE
+ tristate "Mediatek SoCs EFUSE support"
+@@ -107,12 +169,17 @@ config NVMEM_MTK_EFUSE
+ This driver can also be built as a module. If so, the module
+ will be called efuse-mtk.
+
+-config NVMEM_MICROCHIP_OTPC
+- tristate "Microchip OTPC support"
+- depends on ARCH_AT91 || COMPILE_TEST
++config NVMEM_MXS_OCOTP
++ tristate "Freescale MXS On-Chip OTP Memory Support"
++ depends on ARCH_MXS || COMPILE_TEST
++ depends on HAS_IOMEM
+ help
+- This driver enable the OTP controller available on Microchip SAMA7G5
+- SoCs. It controlls the access to the OTP memory connected to it.
++ If you say Y here, you will get readonly access to the
++ One Time Programmable memory pages that are stored
++ on the Freescale i.MX23/i.MX28 processor.
++
++ This driver can also be built as a module. If so, the module
++ will be called nvmem-mxs-ocotp.
+
+ config NVMEM_NINTENDO_OTP
+ tristate "Nintendo Wii and Wii U OTP Support"
+@@ -137,13 +204,21 @@ config NVMEM_QCOM_QFPROM
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_qfprom.
+
+-config NVMEM_SPMI_SDAM
+- tristate "SPMI SDAM Support"
+- depends on SPMI
++config NVMEM_RAVE_SP_EEPROM
++ tristate "Rave SP EEPROM Support"
++ depends on RAVE_SP_CORE
+ help
+- This driver supports the Shared Direct Access Memory Module on
+- Qualcomm Technologies, Inc. PMICs. It provides the clients
+- an interface to read/write to the SDAM module's shared memory.
++ Say y here to enable Rave SP EEPROM support.
++
++config NVMEM_RMEM
++ tristate "Reserved Memory Based Driver Support"
++ depends on HAS_IOMEM
++ help
++ This driver maps reserved memory into an nvmem device. It might be
++ useful to expose information left by firmware in memory.
++
++ This driver can also be built as a module. If so, the module
++ will be called nvmem-rmem.
+
+ config NVMEM_ROCKCHIP_EFUSE
+ tristate "Rockchip eFuse Support"
+@@ -167,79 +242,16 @@ config NVMEM_ROCKCHIP_OTP
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_rockchip_otp.
+
+-config NVMEM_BCM_OCOTP
+- tristate "Broadcom On-Chip OTP Controller support"
+- depends on ARCH_BCM_IPROC || COMPILE_TEST
+- depends on HAS_IOMEM
+- default ARCH_BCM_IPROC
+- help
+- Say y here to enable read/write access to the Broadcom OTP
+- controller.
+-
+- This driver can also be built as a module. If so, the module
+- will be called nvmem-bcm-ocotp.
+-
+-config NVMEM_STM32_ROMEM
+- tristate "STMicroelectronics STM32 factory-programmed memory support"
+- depends on ARCH_STM32 || COMPILE_TEST
+- help
+- Say y here to enable read-only access for STMicroelectronics STM32
+- factory-programmed memory area.
+-
+- This driver can also be built as a module. If so, the module
+- will be called nvmem-stm32-romem.
+-
+-config NVMEM_SUNXI_SID
+- tristate "Allwinner SoCs SID support"
+- depends on ARCH_SUNXI
+- help
+- This is a driver for the 'security ID' available on various Allwinner
+- devices.
+-
+- This driver can also be built as a module. If so, the module
+- will be called nvmem_sunxi_sid.
+-
+-config NVMEM_UNIPHIER_EFUSE
+- tristate "UniPhier SoCs eFuse support"
+- depends on ARCH_UNIPHIER || COMPILE_TEST
+- depends on HAS_IOMEM
+- help
+- This is a simple driver to dump specified values of UniPhier SoC
+- from eFuse.
+-
+- This driver can also be built as a module. If so, the module
+- will be called nvmem-uniphier-efuse.
+-
+-config NVMEM_VF610_OCOTP
+- tristate "VF610 SoC OCOTP support"
+- depends on SOC_VF610 || COMPILE_TEST
++config NVMEM_SC27XX_EFUSE
++ tristate "Spreadtrum SC27XX eFuse Support"
++ depends on MFD_SC27XX_PMIC || COMPILE_TEST
+ depends on HAS_IOMEM
+ help
+- This is a driver for the 'OCOTP' peripheral available on Vybrid
+- devices like VF5xx and VF6xx.
+-
+- This driver can also be build as a module. If so, the module will
+- be called nvmem-vf610-ocotp.
+-
+-config NVMEM_MESON_EFUSE
+- tristate "Amlogic Meson GX eFuse Support"
+- depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM
+- help
+- This is a driver to retrieve specific values from the eFuse found on
+- the Amlogic Meson GX SoCs.
+-
+- This driver can also be built as a module. If so, the module
+- will be called nvmem_meson_efuse.
+-
+-config NVMEM_MESON_MX_EFUSE
+- tristate "Amlogic Meson6/Meson8/Meson8b eFuse Support"
+- depends on ARCH_MESON || COMPILE_TEST
+- help
+- This is a driver to retrieve specific values from the eFuse found on
+- the Amlogic Meson6, Meson8 and Meson8b SoCs.
++ This is a simple driver to dump specified values of Spreadtrum
++ SC27XX PMICs from eFuse.
+
+ This driver can also be built as a module. If so, the module
+- will be called nvmem_meson_mx_efuse.
++ will be called nvmem-sc27xx-efuse.
+
+ config NVMEM_SNVS_LPGPR
+ tristate "Support for Low Power General Purpose Register"
+@@ -251,32 +263,13 @@ config NVMEM_SNVS_LPGPR
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-snvs-lpgpr.
+
+-config NVMEM_RAVE_SP_EEPROM
+- tristate "Rave SP EEPROM Support"
+- depends on RAVE_SP_CORE
+- help
+- Say y here to enable Rave SP EEPROM support.
+-
+-config NVMEM_SC27XX_EFUSE
+- tristate "Spreadtrum SC27XX eFuse Support"
+- depends on MFD_SC27XX_PMIC || COMPILE_TEST
+- depends on HAS_IOMEM
+- help
+- This is a simple driver to dump specified values of Spreadtrum
+- SC27XX PMICs from eFuse.
+-
+- This driver can also be built as a module. If so, the module
+- will be called nvmem-sc27xx-efuse.
+-
+-config NVMEM_ZYNQMP
+- bool "Xilinx ZYNQMP SoC nvmem firmware support"
+- depends on ARCH_ZYNQMP
++config NVMEM_SPMI_SDAM
++ tristate "SPMI SDAM Support"
++ depends on SPMI
+ help
+- This is a driver to access hardware related data like
+- soc revision, IDCODE... etc by using the firmware
+- interface.
+-
+- If sure, say yes. If unsure, say no.
++ This driver supports the Shared Direct Access Memory Module on
++ Qualcomm Technologies, Inc. PMICs. It provides the clients
++ an interface to read/write to the SDAM module's shared memory.
+
+ config NVMEM_SPRD_EFUSE
+ tristate "Spreadtrum SoC eFuse Support"
+@@ -289,36 +282,15 @@ config NVMEM_SPRD_EFUSE
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-sprd-efuse.
+
+-config NVMEM_RMEM
+- tristate "Reserved Memory Based Driver Support"
+- depends on HAS_IOMEM
+- help
+- This driver maps reserved memory into an nvmem device. It might be
+- useful to expose information left by firmware in memory.
+-
+- This driver can also be built as a module. If so, the module
+- will be called nvmem-rmem.
+-
+-config NVMEM_BRCM_NVRAM
+- tristate "Broadcom's NVRAM support"
+- depends on ARCH_BCM_5301X || COMPILE_TEST
+- depends on HAS_IOMEM
+- help
+- This driver provides support for Broadcom's NVRAM that can be accessed
+- using I/O mapping.
+-
+-config NVMEM_LAYERSCAPE_SFP
+- tristate "Layerscape SFP (Security Fuse Processor) support"
+- depends on ARCH_LAYERSCAPE || COMPILE_TEST
+- depends on HAS_IOMEM
+- select REGMAP_MMIO
++config NVMEM_STM32_ROMEM
++ tristate "STMicroelectronics STM32 factory-programmed memory support"
++ depends on ARCH_STM32 || COMPILE_TEST
+ help
+- This driver provides support to read the eFuses on Freescale
+- Layerscape SoC's. For example, the vendor provides a per part
+- unique ID there.
++ Say y here to enable read-only access for STMicroelectronics STM32
++ factory-programmed memory area.
+
+ This driver can also be built as a module. If so, the module
+- will be called layerscape-sfp.
++ will be called nvmem-stm32-romem.
+
+ config NVMEM_SUNPLUS_OCOTP
+ tristate "Sunplus SoC OTP support"
+@@ -332,17 +304,15 @@ config NVMEM_SUNPLUS_OCOTP
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-sunplus-ocotp.
+
+-config NVMEM_APPLE_EFUSES
+- tristate "Apple eFuse support"
+- depends on ARCH_APPLE || COMPILE_TEST
+- default ARCH_APPLE
++config NVMEM_SUNXI_SID
++ tristate "Allwinner SoCs SID support"
++ depends on ARCH_SUNXI
+ help
+- Say y here to enable support for reading eFuses on Apple SoCs
+- such as the M1. These are e.g. used to store factory programmed
+- calibration data required for the PCIe or the USB-C PHY.
++ This is a driver for the 'security ID' available on various Allwinner
++ devices.
+
+- This driver can also be built as a module. If so, the module will
+- be called nvmem-apple-efuses.
++ This driver can also be built as a module. If so, the module
++ will be called nvmem_sunxi_sid.
+
+ config NVMEM_U_BOOT_ENV
+ tristate "U-Boot environment variables support"
+@@ -357,4 +327,36 @@ config NVMEM_U_BOOT_ENV
+
+ If compiled as module it will be called nvmem_u-boot-env.
+
++config NVMEM_UNIPHIER_EFUSE
++ tristate "UniPhier SoCs eFuse support"
++ depends on ARCH_UNIPHIER || COMPILE_TEST
++ depends on HAS_IOMEM
++ help
++ This is a simple driver to dump specified values of UniPhier SoC
++ from eFuse.
++
++ This driver can also be built as a module. If so, the module
++ will be called nvmem-uniphier-efuse.
++
++config NVMEM_VF610_OCOTP
++ tristate "VF610 SoC OCOTP support"
++ depends on SOC_VF610 || COMPILE_TEST
++ depends on HAS_IOMEM
++ help
++ This is a driver for the 'OCOTP' peripheral available on Vybrid
++ devices like VF5xx and VF6xx.
++
++ This driver can also be build as a module. If so, the module will
++ be called nvmem-vf610-ocotp.
++
++config NVMEM_ZYNQMP
++ bool "Xilinx ZYNQMP SoC nvmem firmware support"
++ depends on ARCH_ZYNQMP
++ help
++ This is a driver to access hardware related data like
++ soc revision, IDCODE... etc by using the firmware
++ interface.
++
++ If sure, say yes. If unsure, say no.
++
+ endif
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -7,67 +7,67 @@ obj-$(CONFIG_NVMEM) += nvmem_core.o
+ nvmem_core-y := core.o
+
+ # Devices
+-obj-$(CONFIG_NVMEM_BCM_OCOTP) += nvmem-bcm-ocotp.o
+-nvmem-bcm-ocotp-y := bcm-ocotp.o
+-obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-imx-iim.o
+-nvmem-imx-iim-y := imx-iim.o
+-obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-imx-ocotp.o
+-nvmem-imx-ocotp-y := imx-ocotp.o
++obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
++nvmem-apple-efuses-y := apple-efuses.o
++obj-$(CONFIG_NVMEM_BCM_OCOTP) += nvmem-bcm-ocotp.o
++nvmem-bcm-ocotp-y := bcm-ocotp.o
++obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_brcm_nvram.o
++nvmem_brcm_nvram-y := brcm_nvram.o
++obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-imx-iim.o
++nvmem-imx-iim-y := imx-iim.o
++obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-imx-ocotp.o
++nvmem-imx-ocotp-y := imx-ocotp.o
+ obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvmem-imx-ocotp-scu.o
+-nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o
+-obj-$(CONFIG_NVMEM_JZ4780_EFUSE) += nvmem_jz4780_efuse.o
+-nvmem_jz4780_efuse-y := jz4780-efuse.o
++nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o
++obj-$(CONFIG_NVMEM_JZ4780_EFUSE) += nvmem_jz4780_efuse.o
++nvmem_jz4780_efuse-y := jz4780-efuse.o
++obj-$(CONFIG_NVMEM_LAYERSCAPE_SFP) += nvmem-layerscape-sfp.o
++nvmem-layerscape-sfp-y := layerscape-sfp.o
+ obj-$(CONFIG_NVMEM_LPC18XX_EEPROM) += nvmem_lpc18xx_eeprom.o
+-nvmem_lpc18xx_eeprom-y := lpc18xx_eeprom.o
+-obj-$(CONFIG_NVMEM_LPC18XX_OTP) += nvmem_lpc18xx_otp.o
+-nvmem_lpc18xx_otp-y := lpc18xx_otp.o
+-obj-$(CONFIG_NVMEM_MXS_OCOTP) += nvmem-mxs-ocotp.o
+-nvmem-mxs-ocotp-y := mxs-ocotp.o
+-obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvmem-nintendo-otp.o
+-nvmem-nintendo-otp-y := nintendo-otp.o
++nvmem_lpc18xx_eeprom-y := lpc18xx_eeprom.o
++obj-$(CONFIG_NVMEM_LPC18XX_OTP) += nvmem_lpc18xx_otp.o
++nvmem_lpc18xx_otp-y := lpc18xx_otp.o
++obj-$(CONFIG_NVMEM_MESON_EFUSE) += nvmem_meson_efuse.o
++nvmem_meson_efuse-y := meson-efuse.o
++obj-$(CONFIG_NVMEM_MESON_MX_EFUSE) += nvmem_meson_mx_efuse.o
++nvmem_meson_mx_efuse-y := meson-mx-efuse.o
++obj-$(CONFIG_NVMEM_MICROCHIP_OTPC) += nvmem-microchip-otpc.o
++nvmem-microchip-otpc-y := microchip-otpc.o
+ obj-$(CONFIG_NVMEM_MTK_EFUSE) += nvmem_mtk-efuse.o
+-nvmem_mtk-efuse-y := mtk-efuse.o
+-obj-$(CONFIG_NVMEM_QCOM_QFPROM) += nvmem_qfprom.o
+-nvmem_qfprom-y := qfprom.o
+-obj-$(CONFIG_NVMEM_SPMI_SDAM) += nvmem_qcom-spmi-sdam.o
+-nvmem_qcom-spmi-sdam-y += qcom-spmi-sdam.o
++nvmem_mtk-efuse-y := mtk-efuse.o
++obj-$(CONFIG_NVMEM_MXS_OCOTP) += nvmem-mxs-ocotp.o
++nvmem-mxs-ocotp-y := mxs-ocotp.o
++obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvmem-nintendo-otp.o
++nvmem-nintendo-otp-y := nintendo-otp.o
++obj-$(CONFIG_NVMEM_QCOM_QFPROM) += nvmem_qfprom.o
++nvmem_qfprom-y := qfprom.o
++obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
++nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
++obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o
++nvmem-rmem-y := rmem.o
+ obj-$(CONFIG_NVMEM_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o
+-nvmem_rockchip_efuse-y := rockchip-efuse.o
++nvmem_rockchip_efuse-y := rockchip-efuse.o
+ obj-$(CONFIG_NVMEM_ROCKCHIP_OTP) += nvmem-rockchip-otp.o
+-nvmem-rockchip-otp-y := rockchip-otp.o
+-obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o
+-nvmem_stm32_romem-y := stm32-romem.o
+-obj-$(CONFIG_NVMEM_STM32_ROMEM) += nvmem_stm32_romem.o
+-nvmem_sunxi_sid-y := sunxi_sid.o
+-obj-$(CONFIG_NVMEM_UNIPHIER_EFUSE) += nvmem-uniphier-efuse.o
+-nvmem-uniphier-efuse-y := uniphier-efuse.o
+-obj-$(CONFIG_NVMEM_VF610_OCOTP) += nvmem-vf610-ocotp.o
+-nvmem-vf610-ocotp-y := vf610-ocotp.o
+-obj-$(CONFIG_NVMEM_MESON_EFUSE) += nvmem_meson_efuse.o
+-nvmem_meson_efuse-y := meson-efuse.o
+-obj-$(CONFIG_NVMEM_MESON_MX_EFUSE) += nvmem_meson_mx_efuse.o
+-nvmem_meson_mx_efuse-y := meson-mx-efuse.o
+-obj-$(CONFIG_NVMEM_SNVS_LPGPR) += nvmem_snvs_lpgpr.o
+-nvmem_snvs_lpgpr-y := snvs_lpgpr.o
+-obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
+-nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
++nvmem-rockchip-otp-y := rockchip-otp.o
+ obj-$(CONFIG_NVMEM_SC27XX_EFUSE) += nvmem-sc27xx-efuse.o
+-nvmem-sc27xx-efuse-y := sc27xx-efuse.o
+-obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynqmp_nvmem.o
+-nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o
+-obj-$(CONFIG_NVMEM_SPRD_EFUSE) += nvmem_sprd_efuse.o
+-nvmem_sprd_efuse-y := sprd-efuse.o
+-obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o
+-nvmem-rmem-y := rmem.o
+-obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_brcm_nvram.o
+-nvmem_brcm_nvram-y := brcm_nvram.o
+-obj-$(CONFIG_NVMEM_LAYERSCAPE_SFP) += nvmem-layerscape-sfp.o
+-nvmem-layerscape-sfp-y := layerscape-sfp.o
++nvmem-sc27xx-efuse-y := sc27xx-efuse.o
++obj-$(CONFIG_NVMEM_SNVS_LPGPR) += nvmem_snvs_lpgpr.o
++nvmem_snvs_lpgpr-y := snvs_lpgpr.o
++obj-$(CONFIG_NVMEM_SPMI_SDAM) += nvmem_qcom-spmi-sdam.o
++nvmem_qcom-spmi-sdam-y += qcom-spmi-sdam.o
++obj-$(CONFIG_NVMEM_SPRD_EFUSE) += nvmem_sprd_efuse.o
++nvmem_sprd_efuse-y := sprd-efuse.o
++obj-$(CONFIG_NVMEM_STM32_ROMEM) += nvmem_stm32_romem.o
++nvmem_stm32_romem-y := stm32-romem.o
+ obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvmem_sunplus_ocotp.o
+-nvmem_sunplus_ocotp-y := sunplus-ocotp.o
+-obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
+-nvmem-apple-efuses-y := apple-efuses.o
+-obj-$(CONFIG_NVMEM_MICROCHIP_OTPC) += nvmem-microchip-otpc.o
+-nvmem-microchip-otpc-y := microchip-otpc.o
+-obj-$(CONFIG_NVMEM_U_BOOT_ENV) += nvmem_u-boot-env.o
+-nvmem_u-boot-env-y := u-boot-env.o
++nvmem_sunplus_ocotp-y := sunplus-ocotp.o
++obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o
++nvmem_sunxi_sid-y := sunxi_sid.o
++obj-$(CONFIG_NVMEM_U_BOOT_ENV) += nvmem_u-boot-env.o
++nvmem_u-boot-env-y := u-boot-env.o
++obj-$(CONFIG_NVMEM_UNIPHIER_EFUSE) += nvmem-uniphier-efuse.o
++nvmem-uniphier-efuse-y := uniphier-efuse.o
++obj-$(CONFIG_NVMEM_VF610_OCOTP) += nvmem-vf610-ocotp.o
++nvmem-vf610-ocotp-y := vf610-ocotp.o
++obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynqmp_nvmem.o
++nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o
--- /dev/null
+From d4d432670f7dee0a5432fcffcfc8699b25181ace Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 16 Sep 2022 13:20:57 +0100
+Subject: [PATCH] nvmem: u-boot-env: find Device Tree nodes for NVMEM cells
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+DT binding allows specifying NVMEM cells as NVMEM device (provider)
+subnodes. Looks for such subnodes when building NVMEM cells.
+
+This allows NVMEM consumers to use U-Boot environment variables.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-11-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/u-boot-env.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/nvmem/u-boot-env.c
++++ b/drivers/nvmem/u-boot-env.c
+@@ -92,6 +92,7 @@ static int u_boot_env_add_cells(struct u
+ return -ENOMEM;
+ priv->cells[idx].offset = data_offset + value - data;
+ priv->cells[idx].bytes = strlen(value);
++ priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
+ }
+
+ if (WARN_ON(idx != priv->ncells))
--- /dev/null
+From 9e8f208ad5229ddda97cd4a83ecf89c735d99592 Mon Sep 17 00:00:00 2001
+From: Horatiu Vultur <horatiu.vultur@microchip.com>
+Date: Fri, 16 Sep 2022 13:20:59 +0100
+Subject: [PATCH] nvmem: lan9662-otp: add support
+
+Add support for OTP controller available on LAN9662. The OTPC controls
+the access to a non-volatile memory. The size of the memory is 8KB.
+The OTPC can access the memory based on an offset.
+Implement both the read and the write functionality.
+
+Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-13-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/Kconfig | 8 ++
+ drivers/nvmem/Makefile | 2 +
+ drivers/nvmem/lan9662-otpc.c | 222 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 232 insertions(+)
+ create mode 100644 drivers/nvmem/lan9662-otpc.c
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -98,6 +98,14 @@ config NVMEM_JZ4780_EFUSE
+ To compile this driver as a module, choose M here: the module
+ will be called nvmem_jz4780_efuse.
+
++config NVMEM_LAN9662_OTPC
++ tristate "Microchip LAN9662 OTP controller support"
++ depends on SOC_LAN966 || COMPILE_TEST
++ depends on HAS_IOMEM
++ help
++ This driver enables the OTP controller available on Microchip LAN9662
++ SoCs. It controls the access to the OTP memory connected to it.
++
+ config NVMEM_LAYERSCAPE_SFP
+ tristate "Layerscape SFP (Security Fuse Processor) support"
+ depends on ARCH_LAYERSCAPE || COMPILE_TEST
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -21,6 +21,8 @@ obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvm
+ nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o
+ obj-$(CONFIG_NVMEM_JZ4780_EFUSE) += nvmem_jz4780_efuse.o
+ nvmem_jz4780_efuse-y := jz4780-efuse.o
++obj-$(CONFIG_NVMEM_LAN9662_OTPC) += nvmem-lan9662-otpc.o
++nvmem-lan9662-otpc-y := lan9662-otpc.o
+ obj-$(CONFIG_NVMEM_LAYERSCAPE_SFP) += nvmem-layerscape-sfp.o
+ nvmem-layerscape-sfp-y := layerscape-sfp.o
+ obj-$(CONFIG_NVMEM_LPC18XX_EEPROM) += nvmem_lpc18xx_eeprom.o
+--- /dev/null
++++ b/drivers/nvmem/lan9662-otpc.c
+@@ -0,0 +1,222 @@
++// SPDX-License-Identifier: GPL-2.0
++
++#include <linux/iopoll.h>
++#include <linux/module.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++
++#define OTP_OTP_PWR_DN(t) (t + 0x00)
++#define OTP_OTP_PWR_DN_OTP_PWRDN_N BIT(0)
++#define OTP_OTP_ADDR_HI(t) (t + 0x04)
++#define OTP_OTP_ADDR_LO(t) (t + 0x08)
++#define OTP_OTP_PRGM_DATA(t) (t + 0x10)
++#define OTP_OTP_PRGM_MODE(t) (t + 0x14)
++#define OTP_OTP_PRGM_MODE_OTP_PGM_MODE_BYTE BIT(0)
++#define OTP_OTP_RD_DATA(t) (t + 0x18)
++#define OTP_OTP_FUNC_CMD(t) (t + 0x20)
++#define OTP_OTP_FUNC_CMD_OTP_PROGRAM BIT(1)
++#define OTP_OTP_FUNC_CMD_OTP_READ BIT(0)
++#define OTP_OTP_CMD_GO(t) (t + 0x28)
++#define OTP_OTP_CMD_GO_OTP_GO BIT(0)
++#define OTP_OTP_PASS_FAIL(t) (t + 0x2c)
++#define OTP_OTP_PASS_FAIL_OTP_READ_PROHIBITED BIT(3)
++#define OTP_OTP_PASS_FAIL_OTP_WRITE_PROHIBITED BIT(2)
++#define OTP_OTP_PASS_FAIL_OTP_FAIL BIT(0)
++#define OTP_OTP_STATUS(t) (t + 0x30)
++#define OTP_OTP_STATUS_OTP_CPUMPEN BIT(1)
++#define OTP_OTP_STATUS_OTP_BUSY BIT(0)
++
++#define OTP_MEM_SIZE 8192
++#define OTP_SLEEP_US 10
++#define OTP_TIMEOUT_US 500000
++
++struct lan9662_otp {
++ struct device *dev;
++ void __iomem *base;
++};
++
++static bool lan9662_otp_wait_flag_clear(void __iomem *reg, u32 flag)
++{
++ u32 val;
++
++ return readl_poll_timeout(reg, val, !(val & flag),
++ OTP_SLEEP_US, OTP_TIMEOUT_US);
++}
++
++static int lan9662_otp_power(struct lan9662_otp *otp, bool up)
++{
++ void __iomem *pwrdn = OTP_OTP_PWR_DN(otp->base);
++
++ if (up) {
++ writel(readl(pwrdn) & ~OTP_OTP_PWR_DN_OTP_PWRDN_N, pwrdn);
++ if (lan9662_otp_wait_flag_clear(OTP_OTP_STATUS(otp->base),
++ OTP_OTP_STATUS_OTP_CPUMPEN))
++ return -ETIMEDOUT;
++ } else {
++ writel(readl(pwrdn) | OTP_OTP_PWR_DN_OTP_PWRDN_N, pwrdn);
++ }
++
++ return 0;
++}
++
++static int lan9662_otp_execute(struct lan9662_otp *otp)
++{
++ if (lan9662_otp_wait_flag_clear(OTP_OTP_CMD_GO(otp->base),
++ OTP_OTP_CMD_GO_OTP_GO))
++ return -ETIMEDOUT;
++
++ if (lan9662_otp_wait_flag_clear(OTP_OTP_STATUS(otp->base),
++ OTP_OTP_STATUS_OTP_BUSY))
++ return -ETIMEDOUT;
++
++ return 0;
++}
++
++static void lan9662_otp_set_address(struct lan9662_otp *otp, u32 offset)
++{
++ writel(0xff & (offset >> 8), OTP_OTP_ADDR_HI(otp->base));
++ writel(0xff & offset, OTP_OTP_ADDR_LO(otp->base));
++}
++
++static int lan9662_otp_read_byte(struct lan9662_otp *otp, u32 offset, u8 *dst)
++{
++ u32 pass;
++ int rc;
++
++ lan9662_otp_set_address(otp, offset);
++ writel(OTP_OTP_FUNC_CMD_OTP_READ, OTP_OTP_FUNC_CMD(otp->base));
++ writel(OTP_OTP_CMD_GO_OTP_GO, OTP_OTP_CMD_GO(otp->base));
++ rc = lan9662_otp_execute(otp);
++ if (!rc) {
++ pass = readl(OTP_OTP_PASS_FAIL(otp->base));
++ if (pass & OTP_OTP_PASS_FAIL_OTP_READ_PROHIBITED)
++ return -EACCES;
++ *dst = (u8) readl(OTP_OTP_RD_DATA(otp->base));
++ }
++ return rc;
++}
++
++static int lan9662_otp_write_byte(struct lan9662_otp *otp, u32 offset, u8 data)
++{
++ u32 pass;
++ int rc;
++
++ lan9662_otp_set_address(otp, offset);
++ writel(OTP_OTP_PRGM_MODE_OTP_PGM_MODE_BYTE, OTP_OTP_PRGM_MODE(otp->base));
++ writel(data, OTP_OTP_PRGM_DATA(otp->base));
++ writel(OTP_OTP_FUNC_CMD_OTP_PROGRAM, OTP_OTP_FUNC_CMD(otp->base));
++ writel(OTP_OTP_CMD_GO_OTP_GO, OTP_OTP_CMD_GO(otp->base));
++
++ rc = lan9662_otp_execute(otp);
++ if (!rc) {
++ pass = readl(OTP_OTP_PASS_FAIL(otp->base));
++ if (pass & OTP_OTP_PASS_FAIL_OTP_WRITE_PROHIBITED)
++ return -EACCES;
++ if (pass & OTP_OTP_PASS_FAIL_OTP_FAIL)
++ return -EIO;
++ }
++ return rc;
++}
++
++static int lan9662_otp_read(void *context, unsigned int offset,
++ void *_val, size_t bytes)
++{
++ struct lan9662_otp *otp = context;
++ u8 *val = _val;
++ uint8_t data;
++ int i, rc = 0;
++
++ lan9662_otp_power(otp, true);
++ for (i = 0; i < bytes; i++) {
++ rc = lan9662_otp_read_byte(otp, offset + i, &data);
++ if (rc < 0)
++ break;
++ *val++ = data;
++ }
++ lan9662_otp_power(otp, false);
++
++ return rc;
++}
++
++static int lan9662_otp_write(void *context, unsigned int offset,
++ void *_val, size_t bytes)
++{
++ struct lan9662_otp *otp = context;
++ u8 *val = _val;
++ u8 data, newdata;
++ int i, rc = 0;
++
++ lan9662_otp_power(otp, true);
++ for (i = 0; i < bytes; i++) {
++ /* Skip zero bytes */
++ if (val[i]) {
++ rc = lan9662_otp_read_byte(otp, offset + i, &data);
++ if (rc < 0)
++ break;
++
++ newdata = data | val[i];
++ if (newdata == data)
++ continue;
++
++ rc = lan9662_otp_write_byte(otp, offset + i,
++ newdata);
++ if (rc < 0)
++ break;
++ }
++ }
++ lan9662_otp_power(otp, false);
++
++ return rc;
++}
++
++static struct nvmem_config otp_config = {
++ .name = "lan9662-otp",
++ .stride = 1,
++ .word_size = 1,
++ .reg_read = lan9662_otp_read,
++ .reg_write = lan9662_otp_write,
++ .size = OTP_MEM_SIZE,
++};
++
++static int lan9662_otp_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct nvmem_device *nvmem;
++ struct lan9662_otp *otp;
++
++ otp = devm_kzalloc(&pdev->dev, sizeof(*otp), GFP_KERNEL);
++ if (!otp)
++ return -ENOMEM;
++
++ otp->dev = dev;
++ otp->base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(otp->base))
++ return PTR_ERR(otp->base);
++
++ otp_config.priv = otp;
++ otp_config.dev = dev;
++
++ nvmem = devm_nvmem_register(dev, &otp_config);
++
++ return PTR_ERR_OR_ZERO(nvmem);
++}
++
++static const struct of_device_id lan9662_otp_match[] = {
++ { .compatible = "microchip,lan9662-otp", },
++ { },
++};
++MODULE_DEVICE_TABLE(of, lan9662_otp_match);
++
++static struct platform_driver lan9662_otp_driver = {
++ .probe = lan9662_otp_probe,
++ .driver = {
++ .name = "lan9662-otp",
++ .of_match_table = lan9662_otp_match,
++ },
++};
++module_platform_driver(lan9662_otp_driver);
++
++MODULE_AUTHOR("Horatiu Vultur <horatiu.vultur@microchip.com>");
++MODULE_DESCRIPTION("lan9662 OTP driver");
++MODULE_LICENSE("GPL");
--- /dev/null
+From 3717ca3e0cc8683f93b41d3f06ca79631eb58715 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 16 Sep 2022 13:21:00 +0100
+Subject: [PATCH] nvmem: u-boot-env: fix crc32 casting type
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This fixes:
+drivers/nvmem/u-boot-env.c:141:17: sparse: sparse: cast to restricted __le32
+
+Fixes: d5542923f200 ("nvmem: add driver handling U-Boot environment variables")
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-14-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/u-boot-env.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/u-boot-env.c
++++ b/drivers/nvmem/u-boot-env.c
+@@ -139,7 +139,7 @@ static int u_boot_env_parse(struct u_boo
+ data_offset = offsetof(struct u_boot_env_image_redundant, data);
+ break;
+ }
+- crc32 = le32_to_cpu(*(uint32_t *)(buf + crc32_offset));
++ crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset));
+ crc32_data_len = priv->mtd->size - crc32_data_offset;
+ data_len = priv->mtd->size - data_offset;
+
--- /dev/null
+From 1aeb122d214b92474c86fde00a03d6e2d69381b5 Mon Sep 17 00:00:00 2001
+From: Horatiu Vultur <horatiu.vultur@microchip.com>
+Date: Wed, 28 Sep 2022 21:51:12 +0200
+Subject: [PATCH] nvmem: lan9662-otp: Fix compatible string
+
+The device tree bindings for lan9662-otp expects the compatible string
+to be one of following compatible strings:
+microchip,lan9662-otpc
+microchip,lan9668-otpc
+
+The problem is that the lan9662-otp driver contains the
+microchip,lan9662-otp compatible string instead of
+microchip,lan9662-otpc.
+Fix this by updating the compatible string in the driver.
+
+Fixes: 9e8f208ad5229d ("nvmem: lan9662-otp: add support")
+Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
+Link: https://lore.kernel.org/r/20220928195112.630351-1-horatiu.vultur@microchip.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/lan9662-otpc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/lan9662-otpc.c
++++ b/drivers/nvmem/lan9662-otpc.c
+@@ -203,7 +203,7 @@ static int lan9662_otp_probe(struct plat
+ }
+
+ static const struct of_device_id lan9662_otp_match[] = {
+- { .compatible = "microchip,lan9662-otp", },
++ { .compatible = "microchip,lan9662-otpc", },
+ { },
+ };
+ MODULE_DEVICE_TABLE(of, lan9662_otp_match);
--- /dev/null
+From ee424f7d3960152f5f862bbb6943e59828dc7917 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Fri, 4 Nov 2022 17:52:03 +0100
+Subject: [PATCH] nvmem: u-boot-env: fix crc32_data_offset on redundant
+ u-boot-env
+
+The Western Digital MyBook Live (PowerPC 464/APM82181)
+has a set of redundant u-boot-env. Loading up the driver
+the following error:
+
+| u_boot_env: Invalid calculated CRC32: 0x4f8f2c86 (expected: 0x98b14514)
+| u_boot_env: probe of partition@1e000 failed with error -22
+
+Looking up the userspace libubootenv utilities source [0],
+it looks like the "mark" or "flag" is not part of the
+crc32 sum... which is unfortunate :(
+
+|static int libuboot_load(struct uboot_ctx *ctx)
+|{
+|[...]
+| if (ctx->redundant) {
+| [...]
+| offsetdata = offsetof(struct uboot_env_redund, data);
+| [...] //-----^^
+| }
+| usable_envsize = ctx->size - offsetdata;
+| buf[0] = malloc(bufsize);
+|[...]
+| for (i = 0; i < copies; i++) {
+| data = (uint8_t *)(buf[i] + offsetdata);
+| uint32_t crc;
+|
+| ret = devread(ctx, i, buf[i]);
+| [...]
+| crc = *(uint32_t *)(buf[i] + offsetcrc);
+| dev->crc = crc32(0, (uint8_t *)data, usable_envsize);
+|
+
+[0] https://github.com/sbabic/libubootenv/blob/master/src/uboot_env.c#L951
+
+Fixes: d5542923f200 ("nvmem: add driver handling U-Boot environment variables")
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Link: https://lore.kernel.org/r/70a16eae113e08db2390b76e174f4837caa135c3.1667580636.git.chunkeey@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/u-boot-env.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/u-boot-env.c
++++ b/drivers/nvmem/u-boot-env.c
+@@ -135,7 +135,7 @@ static int u_boot_env_parse(struct u_boo
+ break;
+ case U_BOOT_FORMAT_REDUNDANT:
+ crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32);
+- crc32_data_offset = offsetof(struct u_boot_env_image_redundant, mark);
++ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data);
+ data_offset = offsetof(struct u_boot_env_image_redundant, data);
+ break;
+ }
--- /dev/null
+From 58e92c4a496b27156020a59a98c7f4a92c2b1533 Mon Sep 17 00:00:00 2001
+From: Wei Yongjun <weiyongjun1@huawei.com>
+Date: Fri, 18 Nov 2022 06:38:38 +0000
+Subject: [PATCH] nvmem: rmem: Fix return value check in rmem_read()
+
+In case of error, the function memremap() returns NULL pointer
+not ERR_PTR(). The IS_ERR() test in the return value check
+should be replaced with NULL test.
+
+Fixes: 5a3fa75a4d9c ("nvmem: Add driver to expose reserved memory as nvmem")
+Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Cc: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063840.6357-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/rmem.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/nvmem/rmem.c
++++ b/drivers/nvmem/rmem.c
+@@ -37,9 +37,9 @@ static int rmem_read(void *context, unsi
+ * but as of Dec 2020 this isn't possible on arm64.
+ */
+ addr = memremap(priv->mem->base, available, MEMREMAP_WB);
+- if (IS_ERR(addr)) {
++ if (!addr) {
+ dev_err(priv->dev, "Failed to remap memory region\n");
+- return PTR_ERR(addr);
++ return -ENOMEM;
+ }
+
+ count = memory_read_from_buffer(val, bytes, &off, addr, available);
--- /dev/null
+From 022b68f271de0e53024e6d5e96fee8e76d25eb95 Mon Sep 17 00:00:00 2001
+From: Horatiu Vultur <horatiu.vultur@microchip.com>
+Date: Fri, 18 Nov 2022 06:38:40 +0000
+Subject: [PATCH] nvmem: lan9662-otp: Change return type of
+ lan9662_otp_wait_flag_clear()
+
+The blamed commit introduced the following smatch warning in the
+function lan9662_otp_wait_flag_clear:
+drivers/nvmem/lan9662-otpc.c:43 lan9662_otp_wait_flag_clear() warn: signedness bug returning '(-110)'
+
+Fix this by changing the return type of the function
+lan9662_otp_wait_flag_clear() to be int instead of bool.
+
+Fixes: 9e8f208ad5229d ("nvmem: lan9662-otp: add support")
+Reported-by: kernel test robot <lkp@intel.com>
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063840.6357-5-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/lan9662-otpc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/lan9662-otpc.c
++++ b/drivers/nvmem/lan9662-otpc.c
+@@ -36,7 +36,7 @@ struct lan9662_otp {
+ void __iomem *base;
+ };
+
+-static bool lan9662_otp_wait_flag_clear(void __iomem *reg, u32 flag)
++static int lan9662_otp_wait_flag_clear(void __iomem *reg, u32 flag)
+ {
+ u32 val;
+
--- /dev/null
+From fbfc4ca465a1f8d81bf2d67d95bf7fc67c3cf0c2 Mon Sep 17 00:00:00 2001
+From: Patrick Delaunay <patrick.delaunay@foss.st.com>
+Date: Fri, 18 Nov 2022 06:39:20 +0000
+Subject: [PATCH] nvmem: stm32: move STM32MP15_BSEC_NUM_LOWER in config
+
+Support STM32MP15_BSEC_NUM_LOWER in stm32 romem config to prepare
+the next SoC in STM32MP family.
+
+Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063932.6418-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/stm32-romem.c | 21 ++++++++++++++++-----
+ 1 file changed, 16 insertions(+), 5 deletions(-)
+
+--- a/drivers/nvmem/stm32-romem.c
++++ b/drivers/nvmem/stm32-romem.c
+@@ -22,16 +22,15 @@
+ /* shadow registers offest */
+ #define STM32MP15_BSEC_DATA0 0x200
+
+-/* 32 (x 32-bits) lower shadow registers */
+-#define STM32MP15_BSEC_NUM_LOWER 32
+-
+ struct stm32_romem_cfg {
+ int size;
++ u8 lower;
+ };
+
+ struct stm32_romem_priv {
+ void __iomem *base;
+ struct nvmem_config cfg;
++ u8 lower;
+ };
+
+ static int stm32_romem_read(void *context, unsigned int offset, void *buf,
+@@ -85,7 +84,7 @@ static int stm32_bsec_read(void *context
+ for (i = roffset; (i < roffset + rbytes); i += 4) {
+ u32 otp = i >> 2;
+
+- if (otp < STM32MP15_BSEC_NUM_LOWER) {
++ if (otp < priv->lower) {
+ /* read lower data from shadow registers */
+ val = readl_relaxed(
+ priv->base + STM32MP15_BSEC_DATA0 + i);
+@@ -159,6 +158,8 @@ static int stm32_romem_probe(struct plat
+ priv->cfg.priv = priv;
+ priv->cfg.owner = THIS_MODULE;
+
++ priv->lower = 0;
++
+ cfg = (const struct stm32_romem_cfg *)
+ of_match_device(dev->driver->of_match_table, dev)->data;
+ if (!cfg) {
+@@ -167,6 +168,7 @@ static int stm32_romem_probe(struct plat
+ priv->cfg.reg_read = stm32_romem_read;
+ } else {
+ priv->cfg.size = cfg->size;
++ priv->lower = cfg->lower;
+ priv->cfg.reg_read = stm32_bsec_read;
+ priv->cfg.reg_write = stm32_bsec_write;
+ }
+@@ -174,8 +176,17 @@ static int stm32_romem_probe(struct plat
+ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg));
+ }
+
++/*
++ * STM32MP15 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits)
++ * => 96 x 32-bits data words
++ * - Lower: 1K bits, 2:1 redundancy, incremental bit programming
++ * => 32 (x 32-bits) lower shadow registers = words 0 to 31
++ * - Upper: 2K bits, ECC protection, word programming only
++ * => 64 (x 32-bits) = words 32 to 95
++ */
+ static const struct stm32_romem_cfg stm32mp15_bsec_cfg = {
+- .size = 384, /* 96 x 32-bits data words */
++ .size = 384,
++ .lower = 32,
+ };
+
+ static const struct of_device_id stm32_romem_of_match[] = {
--- /dev/null
+From d61784e6410f3df2028e6eb91b06ffed37a660e0 Mon Sep 17 00:00:00 2001
+From: Patrick Delaunay <patrick.delaunay@foss.st.com>
+Date: Fri, 18 Nov 2022 06:39:21 +0000
+Subject: [PATCH] nvmem: stm32: add warning when upper OTPs are updated
+
+As the upper OTPs are ECC protected, they support only one 32 bits word
+programming.
+For a second modification of this word, these ECC become invalid and
+this OTP will be no more accessible, the shadowed value is invalid.
+
+This patch adds a warning to indicate an upper OTP update, because this
+operation is dangerous as OTP is not locked by the driver after the first
+update to avoid a second update.
+
+Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063932.6418-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/stm32-romem.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/nvmem/stm32-romem.c
++++ b/drivers/nvmem/stm32-romem.c
+@@ -132,6 +132,9 @@ static int stm32_bsec_write(void *contex
+ }
+ }
+
++ if (offset + bytes >= priv->lower * 4)
++ dev_warn(dev, "Update of upper OTPs with ECC protection (word programming, only once)\n");
++
+ return 0;
+ }
+
--- /dev/null
+From a3816a7d7c097c1da46aad5f5d1e229b607dce04 Mon Sep 17 00:00:00 2001
+From: Patrick Delaunay <patrick.delaunay@foss.st.com>
+Date: Fri, 18 Nov 2022 06:39:22 +0000
+Subject: [PATCH] nvmem: stm32: add nvmem type attribute
+
+Inform NVMEM framework of type attribute for stm32-romem as NVMEM_TYPE_OTP
+so userspace is able to know how the data is stored in BSEC.
+
+Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063932.6418-4-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/stm32-romem.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/nvmem/stm32-romem.c
++++ b/drivers/nvmem/stm32-romem.c
+@@ -160,6 +160,7 @@ static int stm32_romem_probe(struct plat
+ priv->cfg.dev = dev;
+ priv->cfg.priv = priv;
+ priv->cfg.owner = THIS_MODULE;
++ priv->cfg.type = NVMEM_TYPE_OTP;
+
+ priv->lower = 0;
+
--- /dev/null
+From 06aac0e11960a7ddccc1888326b5906d017e0f24 Mon Sep 17 00:00:00 2001
+From: Jiangshan Yi <yijiangshan@kylinos.cn>
+Date: Fri, 18 Nov 2022 06:39:24 +0000
+Subject: [PATCH] nvmem: stm32: fix spelling typo in comment
+
+Fix spelling typo in comment.
+
+Reported-by: k2ci <kernel-bot@kylinos.cn>
+Signed-off-by: Jiangshan Yi <yijiangshan@kylinos.cn>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063932.6418-6-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/stm32-romem.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/stm32-romem.c
++++ b/drivers/nvmem/stm32-romem.c
+@@ -19,7 +19,7 @@
+ #define STM32_SMC_WRITE_SHADOW 0x03
+ #define STM32_SMC_READ_OTP 0x04
+
+-/* shadow registers offest */
++/* shadow registers offset */
+ #define STM32MP15_BSEC_DATA0 0x200
+
+ struct stm32_romem_cfg {
--- /dev/null
+From fb817c4ef63e8cfb6e77ae4a2875ae854c80708f Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.i.king@gmail.com>
+Date: Fri, 18 Nov 2022 06:39:26 +0000
+Subject: [PATCH] nvmem: Kconfig: Fix spelling mistake "controlls" ->
+ "controls"
+
+There is a spelling mistake in a Kconfig description. Fix it.
+
+Signed-off-by: Colin Ian King <colin.i.king@gmail.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063932.6418-8-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -164,7 +164,7 @@ config NVMEM_MICROCHIP_OTPC
+ depends on ARCH_AT91 || COMPILE_TEST
+ help
+ This driver enable the OTP controller available on Microchip SAMA7G5
+- SoCs. It controlls the access to the OTP memory connected to it.
++ SoCs. It controls the access to the OTP memory connected to it.
+
+ config NVMEM_MTK_EFUSE
+ tristate "Mediatek SoCs EFUSE support"
--- /dev/null
+From ada84d07af6097b2addd18262668ce6cb9e15206 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 18 Nov 2022 06:39:27 +0000
+Subject: [PATCH] nvmem: u-boot-env: add Broadcom format support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Broadcom uses U-Boot for a lot of their bcmbca familiy chipsets. They
+decided to store U-Boot environment data inside U-Boot partition and to
+use a custom header (with "uEnv" magic and env data length).
+
+Add support for Broadcom's specific binding and their custom format.
+
+Ref: 6b0584c19d87 ("dt-bindings: nvmem: u-boot,env: add Broadcom's variant binding")
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063932.6418-9-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/u-boot-env.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/drivers/nvmem/u-boot-env.c
++++ b/drivers/nvmem/u-boot-env.c
+@@ -16,6 +16,7 @@
+ enum u_boot_env_format {
+ U_BOOT_FORMAT_SINGLE,
+ U_BOOT_FORMAT_REDUNDANT,
++ U_BOOT_FORMAT_BROADCOM,
+ };
+
+ struct u_boot_env {
+@@ -40,6 +41,13 @@ struct u_boot_env_image_redundant {
+ uint8_t data[];
+ } __packed;
+
++struct u_boot_env_image_broadcom {
++ __le32 magic;
++ __le32 len;
++ __le32 crc32;
++ uint8_t data[0];
++} __packed;
++
+ static int u_boot_env_read(void *context, unsigned int offset, void *val,
+ size_t bytes)
+ {
+@@ -138,6 +146,11 @@ static int u_boot_env_parse(struct u_boo
+ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data);
+ data_offset = offsetof(struct u_boot_env_image_redundant, data);
+ break;
++ case U_BOOT_FORMAT_BROADCOM:
++ crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32);
++ crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data);
++ data_offset = offsetof(struct u_boot_env_image_broadcom, data);
++ break;
+ }
+ crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset));
+ crc32_data_len = priv->mtd->size - crc32_data_offset;
+@@ -202,6 +215,7 @@ static const struct of_device_id u_boot_
+ { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, },
+ { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
+ { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
++ { .compatible = "brcm,env", .data = (void *)U_BOOT_FORMAT_BROADCOM, },
+ {},
+ };
+
--- /dev/null
+From 0e71cac033bb7689c4dfa2e6814191337ef770f5 Mon Sep 17 00:00:00 2001
+From: INAGAKI Hiroshi <musashino.open@gmail.com>
+Date: Thu, 13 Oct 2022 00:51:33 +0900
+Subject: [PATCH] nvmem: u-boot-env: align endianness of crc32 values
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch fixes crc32 error on Big-Endianness system by conversion of
+calculated crc32 value.
+
+Little-Endianness system:
+
+ obtained crc32: Little
+calculated crc32: Little
+
+Big-Endianness system:
+
+ obtained crc32: Little
+calculated crc32: Big
+
+log (APRESIA ApresiaLightGS120GT-SS, RTL8382M, Big-Endianness):
+
+[ 8.570000] u_boot_env 18001200.spi:flash@0:partitions:partition@c0000: Invalid calculated CRC32: 0x88cd6f09 (expected: 0x096fcd88)
+[ 8.580000] u_boot_env: probe of 18001200.spi:flash@0:partitions:partition@c0000 failed with error -22
+
+Fixes: f955dc1445069 ("nvmem: add driver handling U-Boot environment variables")
+
+Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
+Acked-by: Rafał Miłecki <rafal@milecki.pl>
+Tested-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+---
+ drivers/nvmem/u-boot-env.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/u-boot-env.c
++++ b/drivers/nvmem/u-boot-env.c
+@@ -156,7 +156,7 @@ static int u_boot_env_parse(struct u_boo
+ crc32_data_len = priv->mtd->size - crc32_data_offset;
+ data_len = priv->mtd->size - data_offset;
+
+- calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L;
++ calc = le32_to_cpu((__le32)crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L);
+ if (calc != crc32) {
+ dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32);
+ err = -EINVAL;
--- /dev/null
+From 2d5ba37461013253d2ff0a3641b727fd32ea97a9 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Tue, 23 Feb 2021 18:44:53 +0100
+Subject: [PATCH 1/3] usb: ehci: add spurious flag to disable overcurrent
+ checking
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch adds an ignore_oc flag which can be set by EHCI controller
+not supporting or wanting to disable overcurrent checking. The EHCI
+platform data in include/linux/usb/ehci_pdriver.h is also augmented to
+take advantage of this new flag.
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+Link: https://lore.kernel.org/r/20210223174455.1378-2-noltari@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/ehci-hcd.c | 2 +-
+ drivers/usb/host/ehci-hub.c | 4 ++--
+ drivers/usb/host/ehci-platform.c | 2 ++
+ drivers/usb/host/ehci.h | 1 +
+ include/linux/usb/ehci_pdriver.h | 1 +
+ 5 files changed, 7 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -660,7 +660,7 @@ static int ehci_run (struct usb_hcd *hcd
+ "USB %x.%x started, EHCI %x.%02x%s\n",
+ ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
+ temp >> 8, temp & 0xff,
+- ignore_oc ? ", overcurrent ignored" : "");
++ (ignore_oc || ehci->spurious_oc) ? ", overcurrent ignored" : "");
+
+ ehci_writel(ehci, INTR_MASK,
+ &ehci->regs->intr_enable); /* Turn On Interrupts */
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -643,7 +643,7 @@ ehci_hub_status_data (struct usb_hcd *hc
+ * always set, seem to clear PORT_OCC and PORT_CSC when writing to
+ * PORT_POWER; that's surprising, but maybe within-spec.
+ */
+- if (!ignore_oc)
++ if (!ignore_oc && !ehci->spurious_oc)
+ mask = PORT_CSC | PORT_PEC | PORT_OCC;
+ else
+ mask = PORT_CSC | PORT_PEC;
+@@ -1013,7 +1013,7 @@ int ehci_hub_control(
+ if (temp & PORT_PEC)
+ status |= USB_PORT_STAT_C_ENABLE << 16;
+
+- if ((temp & PORT_OCC) && !ignore_oc){
++ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->spurious_oc)){
+ status |= USB_PORT_STAT_C_OVERCURRENT << 16;
+
+ /*
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -333,6 +333,8 @@ static int ehci_platform_probe(struct pl
+ hcd->has_tt = 1;
+ if (pdata->reset_on_resume)
+ priv->reset_on_resume = true;
++ if (pdata->spurious_oc)
++ ehci->spurious_oc = 1;
+
+ #ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
+ if (ehci->big_endian_mmio) {
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -219,6 +219,7 @@ struct ehci_hcd { /* one per controlle
+ unsigned need_oc_pp_cycle:1; /* MPC834X port power */
+ unsigned imx28_write_fix:1; /* For Freescale i.MX28 */
+ unsigned is_aspeed:1;
++ unsigned spurious_oc:1;
+
+ /* required for usb32 quirk */
+ #define OHCI_CTRL_HCFS (3 << 6)
+--- a/include/linux/usb/ehci_pdriver.h
++++ b/include/linux/usb/ehci_pdriver.h
+@@ -50,6 +50,7 @@ struct usb_ehci_pdata {
+ unsigned no_io_watchdog:1;
+ unsigned reset_on_resume:1;
+ unsigned dma_mask_64:1;
++ unsigned spurious_oc:1;
+
+ /* Turn on all power and clocks */
+ int (*power_on)(struct platform_device *pdev);
--- /dev/null
+From 4da57dbbffdfa7fe4e2b70b047fc5ff95ff25a3d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
+Date: Tue, 23 Feb 2021 18:44:55 +0100
+Subject: [PATCH 3/3] usb: host: ehci-platform: add spurious_oc DT support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Over-current reporting isn't supported on some platforms such as bcm63xx.
+These devices will incorrectly report over-current if this flag isn't properly
+activated.
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+Link: https://lore.kernel.org/r/20210223174455.1378-4-noltari@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/ehci-platform.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -286,6 +286,9 @@ static int ehci_platform_probe(struct pl
+ if (of_property_read_bool(dev->dev.of_node, "big-endian"))
+ ehci->big_endian_mmio = ehci->big_endian_desc = 1;
+
++ if (of_property_read_bool(dev->dev.of_node, "spurious-oc"))
++ ehci->spurious_oc = 1;
++
+ if (of_property_read_bool(dev->dev.of_node,
+ "needs-reset-on-resume"))
+ priv->reset_on_resume = true;
+++ /dev/null
-From f955dc14450695564926711cf9fa8e1d5d854302 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Wed, 15 Jun 2022 21:43:00 +0200
-Subject: [PATCH] nvmem: add driver handling U-Boot environment variables
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-U-Boot stores its setup as environment variables. It's a list of
-key-value pairs stored on flash device with a custom header.
-
-This commit adds an NVMEM driver that:
-1. Provides NVMEM access to environment vars binary data
-2. Extracts variables as NVMEM cells
-
-Current Linux's NVMEM sysfs API allows reading whole NVMEM data block.
-It can be used by user-space tools for reading U-Boot env vars block
-without the hassle of finding its location. Parsing will still need to
-be re-done there.
-
-Kernel-parsed NVMEM cells can be read however by Linux drivers. This may
-be useful for Ethernet drivers for reading device MAC address which is
-often stored as U-Boot env variable.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
----
-
---- a/drivers/nvmem/Kconfig
-+++ b/drivers/nvmem/Kconfig
-@@ -300,4 +300,17 @@ config NVMEM_BRCM_NVRAM
- This driver provides support for Broadcom's NVRAM that can be accessed
- using I/O mapping.
-
-+config NVMEM_U_BOOT_ENV
-+ tristate "U-Boot environment variables support"
-+ depends on OF && MTD
-+ select CRC32
-+ help
-+ U-Boot stores its setup as environment variables. This driver adds
-+ support for verifying & exporting such data. It also exposes variables
-+ as NVMEM cells so they can be referenced by other drivers.
-+
-+ Currently this drivers works only with env variables on top of MTD.
-+
-+ If compiled as module it will be called nvmem_u-boot-env.
-+
- endif
---- a/drivers/nvmem/Makefile
-+++ b/drivers/nvmem/Makefile
-@@ -61,3 +61,5 @@ obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.
- nvmem-rmem-y := rmem.o
- obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_brcm_nvram.o
- nvmem_brcm_nvram-y := brcm_nvram.o
-+obj-$(CONFIG_NVMEM_U_BOOT_ENV) += nvmem_u-boot-env.o
-+nvmem_u-boot-env-y := u-boot-env.o
---- /dev/null
-+++ b/drivers/nvmem/u-boot-env.c
-@@ -0,0 +1,218 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+/*
-+ * Copyright (C) 2022 Rafał Miłecki <rafal@milecki.pl>
-+ */
-+
-+#include <linux/crc32.h>
-+#include <linux/mod_devicetable.h>
-+#include <linux/module.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/nvmem-consumer.h>
-+#include <linux/nvmem-provider.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_device.h>
-+#include <linux/slab.h>
-+
-+enum u_boot_env_format {
-+ U_BOOT_FORMAT_SINGLE,
-+ U_BOOT_FORMAT_REDUNDANT,
-+};
-+
-+struct u_boot_env {
-+ struct device *dev;
-+ enum u_boot_env_format format;
-+
-+ struct mtd_info *mtd;
-+
-+ /* Cells */
-+ struct nvmem_cell_info *cells;
-+ int ncells;
-+};
-+
-+struct u_boot_env_image_single {
-+ __le32 crc32;
-+ uint8_t data[];
-+} __packed;
-+
-+struct u_boot_env_image_redundant {
-+ __le32 crc32;
-+ u8 mark;
-+ uint8_t data[];
-+} __packed;
-+
-+static int u_boot_env_read(void *context, unsigned int offset, void *val,
-+ size_t bytes)
-+{
-+ struct u_boot_env *priv = context;
-+ struct device *dev = priv->dev;
-+ size_t bytes_read;
-+ int err;
-+
-+ err = mtd_read(priv->mtd, offset, bytes, &bytes_read, val);
-+ if (err && !mtd_is_bitflip(err)) {
-+ dev_err(dev, "Failed to read from mtd: %d\n", err);
-+ return err;
-+ }
-+
-+ if (bytes_read != bytes) {
-+ dev_err(dev, "Failed to read %zu bytes\n", bytes);
-+ return -EIO;
-+ }
-+
-+ return 0;
-+}
-+
-+static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf,
-+ size_t data_offset, size_t data_len)
-+{
-+ struct device *dev = priv->dev;
-+ char *data = buf + data_offset;
-+ char *var, *value, *eq;
-+ int idx;
-+
-+ priv->ncells = 0;
-+ for (var = data; var < data + 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, idx = 0;
-+ var < data + 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 = data_offset + value - data;
-+ priv->cells[idx].bytes = strlen(value);
-+ }
-+
-+ if (WARN_ON(idx != priv->ncells))
-+ priv->ncells = idx;
-+
-+ return 0;
-+}
-+
-+static int u_boot_env_parse(struct u_boot_env *priv)
-+{
-+ struct device *dev = priv->dev;
-+ size_t crc32_data_offset;
-+ size_t crc32_data_len;
-+ size_t crc32_offset;
-+ size_t data_offset;
-+ size_t data_len;
-+ uint32_t crc32;
-+ uint32_t calc;
-+ size_t bytes;
-+ uint8_t *buf;
-+ int err;
-+
-+ buf = kcalloc(1, priv->mtd->size, GFP_KERNEL);
-+ if (!buf) {
-+ err = -ENOMEM;
-+ goto err_out;
-+ }
-+
-+ err = mtd_read(priv->mtd, 0, priv->mtd->size, &bytes, buf);
-+ if ((err && !mtd_is_bitflip(err)) || bytes != priv->mtd->size) {
-+ dev_err(dev, "Failed to read from mtd: %d\n", err);
-+ goto err_kfree;
-+ }
-+
-+ switch (priv->format) {
-+ case U_BOOT_FORMAT_SINGLE:
-+ crc32_offset = offsetof(struct u_boot_env_image_single, crc32);
-+ crc32_data_offset = offsetof(struct u_boot_env_image_single, data);
-+ data_offset = offsetof(struct u_boot_env_image_single, data);
-+ break;
-+ case U_BOOT_FORMAT_REDUNDANT:
-+ crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32);
-+ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, mark);
-+ data_offset = offsetof(struct u_boot_env_image_redundant, data);
-+ break;
-+ }
-+ crc32 = le32_to_cpu(*(uint32_t *)(buf + crc32_offset));
-+ crc32_data_len = priv->mtd->size - crc32_data_offset;
-+ data_len = priv->mtd->size - data_offset;
-+
-+ calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L;
-+ if (calc != crc32) {
-+ dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32);
-+ err = -EINVAL;
-+ goto err_kfree;
-+ }
-+
-+ buf[priv->mtd->size - 1] = '\0';
-+ err = u_boot_env_add_cells(priv, buf, data_offset, data_len);
-+ if (err)
-+ dev_err(dev, "Failed to add cells: %d\n", err);
-+
-+err_kfree:
-+ kfree(buf);
-+err_out:
-+ return err;
-+}
-+
-+static int u_boot_env_probe(struct platform_device *pdev)
-+{
-+ struct nvmem_config config = {
-+ .name = "u-boot-env",
-+ .reg_read = u_boot_env_read,
-+ };
-+ struct device *dev = &pdev->dev;
-+ struct device_node *np = dev->of_node;
-+ struct u_boot_env *priv;
-+ int err;
-+
-+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+ if (!priv)
-+ return -ENOMEM;
-+ priv->dev = dev;
-+
-+ priv->format = (uintptr_t)of_device_get_match_data(dev);
-+
-+ priv->mtd = of_get_mtd_device_by_node(np);
-+ if (IS_ERR(priv->mtd)) {
-+ dev_err_probe(dev, PTR_ERR(priv->mtd), "Failed to get %pOF MTD\n", np);
-+ return PTR_ERR(priv->mtd);
-+ }
-+
-+ err = u_boot_env_parse(priv);
-+ if (err)
-+ return err;
-+
-+ config.dev = dev;
-+ config.cells = priv->cells;
-+ config.ncells = priv->ncells;
-+ config.priv = priv;
-+ config.size = priv->mtd->size;
-+
-+ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config));
-+}
-+
-+static const struct of_device_id u_boot_env_of_match_table[] = {
-+ { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, },
-+ { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
-+ { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
-+ {},
-+};
-+
-+static struct platform_driver u_boot_env_driver = {
-+ .probe = u_boot_env_probe,
-+ .driver = {
-+ .name = "u_boot_env",
-+ .of_match_table = u_boot_env_of_match_table,
-+ },
-+};
-+module_platform_driver(u_boot_env_driver);
-+
-+MODULE_AUTHOR("Rafał Miłecki");
-+MODULE_LICENSE("GPL");
-+MODULE_DEVICE_TABLE(of, u_boot_env_of_match_table);
+++ /dev/null
-From d69efcf951df4dcc74a0e1554969c533aec8aa9b Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Thu, 15 Sep 2022 22:06:29 +0200
-Subject: [PATCH] nvmem: u-boot-env: find Device Tree nodes for NVMEM cells
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-DT binding allows specifying NVMEM cells as NVMEM device (provider)
-subnodes. Looks for such subnodes when building NVMEM cells.
-
-This allows NVMEM consumers to use U-Boot environment variables.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
----
- drivers/nvmem/u-boot-env.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/nvmem/u-boot-env.c
-+++ b/drivers/nvmem/u-boot-env.c
-@@ -92,6 +92,7 @@ static int u_boot_env_add_cells(struct u
- return -ENOMEM;
- priv->cells[idx].offset = data_offset + value - data;
- priv->cells[idx].bytes = strlen(value);
-+ priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
- }
-
- if (WARN_ON(idx != priv->ncells))
+++ /dev/null
-From 60bbaad38109684b156e21112322e0a922f92cde Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Thu, 18 Aug 2022 06:38:37 +0200
-Subject: [PATCH] nvmem: u-boot-env: fix crc32 casting type
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This fixes:
-drivers/nvmem/u-boot-env.c:141:17: sparse: sparse: cast to restricted __le32
-
-Reported-by: kernel test robot <lkp@intel.com>
-Fixes: f955dc1445069 ("nvmem: add driver handling U-Boot environment variables")
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
----
- drivers/nvmem/u-boot-env.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/nvmem/u-boot-env.c
-+++ b/drivers/nvmem/u-boot-env.c
-@@ -139,7 +139,7 @@ static int u_boot_env_parse(struct u_boo
- data_offset = offsetof(struct u_boot_env_image_redundant, data);
- break;
- }
-- crc32 = le32_to_cpu(*(uint32_t *)(buf + crc32_offset));
-+ crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset));
- crc32_data_len = priv->mtd->size - crc32_data_offset;
- data_len = priv->mtd->size - data_offset;
-
+++ /dev/null
-From dbc2f62061c6bfba0aee93161ee3194dcee84bd0 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Fri, 29 Apr 2022 17:26:46 +0100
-Subject: [PATCH] nvmem: core: support passing DT node in cell info
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Some hardware may have NVMEM cells described in Device Tree using
-individual nodes. Let drivers pass such nodes to the NVMEM subsystem so
-they can be later used by NVMEM consumers.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-Link: https://lore.kernel.org/r/20220429162701.2222-2-srinivas.kandagatla@linaro.org
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/nvmem/core.c | 1 +
- include/linux/nvmem-consumer.h | 1 +
- 2 files changed, 2 insertions(+)
-
---- a/drivers/nvmem/core.c
-+++ b/drivers/nvmem/core.c
-@@ -462,6 +462,7 @@ static int nvmem_cell_info_to_nvmem_cell
-
- cell->bit_offset = info->bit_offset;
- cell->nbits = info->nbits;
-+ cell->np = info->np;
-
- if (cell->nbits)
- cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
---- a/include/linux/nvmem-consumer.h
-+++ b/include/linux/nvmem-consumer.h
-@@ -25,6 +25,7 @@ struct nvmem_cell_info {
- unsigned int bytes;
- unsigned int bit_offset;
- unsigned int nbits;
-+ struct device_node *np;
- };
-
- /**
+++ /dev/null
-From 7a69ff9c9bde03a690ea783970f664782fc303d8 Mon Sep 17 00:00:00 2001
-From: Christian Lamparter <chunkeey@gmail.com>
-Date: Fri, 4 Nov 2022 17:52:03 +0100
-Subject: [PATCH] nvmem: u-boot-env: fix crc32_data_offset on redundant
- u-boot-env
-
-The Western Digital MyBook Live (PowerPC 464/APM82181)
-has a set of redundant u-boot-env. Loading up the driver
-the following error:
-
-| u_boot_env: Invalid calculated CRC32: 0x4f8f2c86 (expected: 0x98b14514)
-| u_boot_env: probe of partition@1e000 failed with error -22
-
-Looking up the userspace libubootenv utilities source [0],
-it looks like the "mark" or "flag" is not part of the
-crc32 sum... which is unfortunate :(
-
-|static int libuboot_load(struct uboot_ctx *ctx)
-|{
-|[...]
-| if (ctx->redundant) {
-| [...]
-| offsetdata = offsetof(struct uboot_env_redund, data);
-| [...] //-----^^
-| }
-| usable_envsize = ctx->size - offsetdata;
-| buf[0] = malloc(bufsize);
-|[...]
-| for (i = 0; i < copies; i++) {
-| data = (uint8_t *)(buf[i] + offsetdata);
-| uint32_t crc;
-|
-| ret = devread(ctx, i, buf[i]);
-| [...]
-| crc = *(uint32_t *)(buf[i] + offsetcrc);
-| dev->crc = crc32(0, (uint8_t *)data, usable_envsize);
-|
-
-[0] https://github.com/sbabic/libubootenv/blob/master/src/uboot_env.c#L951
-Fixes: d5542923f200 ("nvmem: add driver handling U-Boot environment variables")
-Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
----
- drivers/nvmem/u-boot-env.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/nvmem/u-boot-env.c
-+++ b/drivers/nvmem/u-boot-env.c
-@@ -135,7 +135,7 @@ static int u_boot_env_parse(struct u_boo
- break;
- case U_BOOT_FORMAT_REDUNDANT:
- crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32);
-- crc32_data_offset = offsetof(struct u_boot_env_image_redundant, mark);
-+ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data);
- data_offset = offsetof(struct u_boot_env_image_redundant, data);
- break;
- }
+++ /dev/null
-From 0e71cac033bb7689c4dfa2e6814191337ef770f5 Mon Sep 17 00:00:00 2001
-From: INAGAKI Hiroshi <musashino.open@gmail.com>
-Date: Thu, 13 Oct 2022 00:51:33 +0900
-Subject: [PATCH] nvmem: u-boot-env: align endianness of crc32 values
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This patch fixes crc32 error on Big-Endianness system by conversion of
-calculated crc32 value.
-
-Little-Endianness system:
-
- obtained crc32: Little
-calculated crc32: Little
-
-Big-Endianness system:
-
- obtained crc32: Little
-calculated crc32: Big
-
-log (APRESIA ApresiaLightGS120GT-SS, RTL8382M, Big-Endianness):
-
-[ 8.570000] u_boot_env 18001200.spi:flash@0:partitions:partition@c0000: Invalid calculated CRC32: 0x88cd6f09 (expected: 0x096fcd88)
-[ 8.580000] u_boot_env: probe of 18001200.spi:flash@0:partitions:partition@c0000 failed with error -22
-
-Fixes: f955dc1445069 ("nvmem: add driver handling U-Boot environment variables")
-
-Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
-Acked-by: Rafał Miłecki <rafal@milecki.pl>
-Tested-by: Christian Lamparter <chunkeey@gmail.com>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
----
- drivers/nvmem/u-boot-env.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/nvmem/u-boot-env.c
-+++ b/drivers/nvmem/u-boot-env.c
-@@ -143,7 +143,7 @@ static int u_boot_env_parse(struct u_boo
- crc32_data_len = priv->mtd->size - crc32_data_offset;
- data_len = priv->mtd->size - data_offset;
-
-- calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L;
-+ calc = le32_to_cpu((__le32)crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L);
- if (calc != crc32) {
- dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32);
- err = -EINVAL;
+++ /dev/null
-From 5b4eaafbeac472fc19049152f18e88aecb2b2829 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Mon, 17 Oct 2022 09:17:22 +0200
-Subject: [PATCH] nvmem: u-boot-env: add Broadcom format support
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Broadcom uses U-Boot for a lot of their bcmbca familiy chipsets. They
-decided to store U-Boot environment data inside U-Boot partition and to
-use a custom header (with "uEnv" magic and env data length).
-
-Add support for Broadcom's specific binding and their custom format.
-
-Ref: 6b0584c19d87 ("dt-bindings: nvmem: u-boot,env: add Broadcom's variant binding")
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
----
- drivers/nvmem/u-boot-env.c | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
---- a/drivers/nvmem/u-boot-env.c
-+++ b/drivers/nvmem/u-boot-env.c
-@@ -16,6 +16,7 @@
- enum u_boot_env_format {
- U_BOOT_FORMAT_SINGLE,
- U_BOOT_FORMAT_REDUNDANT,
-+ U_BOOT_FORMAT_BROADCOM,
- };
-
- struct u_boot_env {
-@@ -40,6 +41,13 @@ struct u_boot_env_image_redundant {
- uint8_t data[];
- } __packed;
-
-+struct u_boot_env_image_broadcom {
-+ __le32 magic;
-+ __le32 len;
-+ __le32 crc32;
-+ uint8_t data[0];
-+} __packed;
-+
- static int u_boot_env_read(void *context, unsigned int offset, void *val,
- size_t bytes)
- {
-@@ -138,6 +146,11 @@ static int u_boot_env_parse(struct u_boo
- crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data);
- data_offset = offsetof(struct u_boot_env_image_redundant, data);
- break;
-+ case U_BOOT_FORMAT_BROADCOM:
-+ crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32);
-+ crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data);
-+ data_offset = offsetof(struct u_boot_env_image_broadcom, data);
-+ break;
- }
- crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset));
- crc32_data_len = priv->mtd->size - crc32_data_offset;
-@@ -202,6 +215,7 @@ static const struct of_device_id u_boot_
- { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, },
- { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
- { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
-+ { .compatible = "brcm,env", .data = (void *)U_BOOT_FORMAT_BROADCOM, },
- {},
- };
-
--- /dev/null
+From 7ae6478b304bc004c3139b422665b0e23b57f05c Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Date: Wed, 13 Oct 2021 14:19:55 +0100
+Subject: [PATCH] nvmem: core: rework nvmem cell instance creation
+
+In the existing design, we do not create a instance per nvmem cell consumer
+but we directly refer cell from nvmem cell list that are added to provider.
+
+However this design has some limitations when consumers want to assign name
+or connection id the nvmem cell instance, ex: via "nvmem-cell-names" or
+id in nvmem_cell_get(id).
+
+Having a name associated with nvmem cell consumer instance will help
+provider drivers in performing post processing of nvmem cell data if required
+before data is seen by the consumers. This is pretty normal with some vendors
+storing nvmem cells like mac-address in a vendor specific data layouts that
+are not directly usable by the consumer drivers.
+
+With this patch nvmem cell will be created dynamically during nvmem_cell_get
+and destroyed in nvmem_cell_put, allowing consumers to associate name with
+nvmem cell consumer instance.
+
+With this patch a new struct nvmem_cell_entry replaces struct nvmem_cell
+for storing nvmem cell information within the core.
+This patch does not change nvmem-consumer interface based on nvmem_cell.
+
+Tested-by: Joakim Zhang <qiangqing.zhang@nxp.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20211013131957.30271-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 165 +++++++++++++++++++++++++++----------------
+ 1 file changed, 105 insertions(+), 60 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -45,8 +45,7 @@ struct nvmem_device {
+ #define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
+
+ #define FLAG_COMPAT BIT(0)
+-
+-struct nvmem_cell {
++struct nvmem_cell_entry {
+ const char *name;
+ int offset;
+ int bytes;
+@@ -57,6 +56,11 @@ struct nvmem_cell {
+ struct list_head node;
+ };
+
++struct nvmem_cell {
++ struct nvmem_cell_entry *entry;
++ const char *id;
++};
++
+ static DEFINE_MUTEX(nvmem_mutex);
+ static DEFINE_IDA(nvmem_ida);
+
+@@ -424,7 +428,7 @@ static struct bus_type nvmem_bus_type =
+ .name = "nvmem",
+ };
+
+-static void nvmem_cell_drop(struct nvmem_cell *cell)
++static void nvmem_cell_entry_drop(struct nvmem_cell_entry *cell)
+ {
+ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_REMOVE, cell);
+ mutex_lock(&nvmem_mutex);
+@@ -437,13 +441,13 @@ static void nvmem_cell_drop(struct nvmem
+
+ static void nvmem_device_remove_all_cells(const struct nvmem_device *nvmem)
+ {
+- struct nvmem_cell *cell, *p;
++ struct nvmem_cell_entry *cell, *p;
+
+ list_for_each_entry_safe(cell, p, &nvmem->cells, node)
+- nvmem_cell_drop(cell);
++ nvmem_cell_entry_drop(cell);
+ }
+
+-static void nvmem_cell_add(struct nvmem_cell *cell)
++static void nvmem_cell_entry_add(struct nvmem_cell_entry *cell)
+ {
+ mutex_lock(&nvmem_mutex);
+ list_add_tail(&cell->node, &cell->nvmem->cells);
+@@ -451,9 +455,9 @@ static void nvmem_cell_add(struct nvmem_
+ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
+ }
+
+-static int nvmem_cell_info_to_nvmem_cell_nodup(struct nvmem_device *nvmem,
+- const struct nvmem_cell_info *info,
+- struct nvmem_cell *cell)
++static int nvmem_cell_info_to_nvmem_cell_entry_nodup(struct nvmem_device *nvmem,
++ const struct nvmem_cell_info *info,
++ struct nvmem_cell_entry *cell)
+ {
+ cell->nvmem = nvmem;
+ cell->offset = info->offset;
+@@ -477,13 +481,13 @@ static int nvmem_cell_info_to_nvmem_cell
+ return 0;
+ }
+
+-static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+- const struct nvmem_cell_info *info,
+- struct nvmem_cell *cell)
++static int nvmem_cell_info_to_nvmem_cell_entry(struct nvmem_device *nvmem,
++ const struct nvmem_cell_info *info,
++ struct nvmem_cell_entry *cell)
+ {
+ int err;
+
+- err = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, cell);
++ err = nvmem_cell_info_to_nvmem_cell_entry_nodup(nvmem, info, cell);
+ if (err)
+ return err;
+
+@@ -507,7 +511,7 @@ static int nvmem_add_cells(struct nvmem_
+ const struct nvmem_cell_info *info,
+ int ncells)
+ {
+- struct nvmem_cell **cells;
++ struct nvmem_cell_entry **cells;
+ int i, rval;
+
+ cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL);
+@@ -521,13 +525,13 @@ static int nvmem_add_cells(struct nvmem_
+ goto err;
+ }
+
+- rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]);
++ rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, &info[i], cells[i]);
+ if (rval) {
+ kfree(cells[i]);
+ goto err;
+ }
+
+- nvmem_cell_add(cells[i]);
++ nvmem_cell_entry_add(cells[i]);
+ }
+
+ /* remove tmp array */
+@@ -536,7 +540,7 @@ static int nvmem_add_cells(struct nvmem_
+ return 0;
+ err:
+ while (i--)
+- nvmem_cell_drop(cells[i]);
++ nvmem_cell_entry_drop(cells[i]);
+
+ kfree(cells);
+
+@@ -573,7 +577,7 @@ static int nvmem_add_cells_from_table(st
+ {
+ const struct nvmem_cell_info *info;
+ struct nvmem_cell_table *table;
+- struct nvmem_cell *cell;
++ struct nvmem_cell_entry *cell;
+ int rval = 0, i;
+
+ mutex_lock(&nvmem_cell_mutex);
+@@ -588,15 +592,13 @@ static int nvmem_add_cells_from_table(st
+ goto out;
+ }
+
+- rval = nvmem_cell_info_to_nvmem_cell(nvmem,
+- info,
+- cell);
++ rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, info, cell);
+ if (rval) {
+ kfree(cell);
+ goto out;
+ }
+
+- nvmem_cell_add(cell);
++ nvmem_cell_entry_add(cell);
+ }
+ }
+ }
+@@ -606,10 +608,10 @@ out:
+ return rval;
+ }
+
+-static struct nvmem_cell *
+-nvmem_find_cell_by_name(struct nvmem_device *nvmem, const char *cell_id)
++static struct nvmem_cell_entry *
++nvmem_find_cell_entry_by_name(struct nvmem_device *nvmem, const char *cell_id)
+ {
+- struct nvmem_cell *iter, *cell = NULL;
++ struct nvmem_cell_entry *iter, *cell = NULL;
+
+ mutex_lock(&nvmem_mutex);
+ list_for_each_entry(iter, &nvmem->cells, node) {
+@@ -680,7 +682,7 @@ static int nvmem_add_cells_from_of(struc
+ {
+ struct device_node *parent, *child;
+ struct device *dev = &nvmem->dev;
+- struct nvmem_cell *cell;
++ struct nvmem_cell_entry *cell;
+ const __be32 *addr;
+ int len;
+
+@@ -729,7 +731,7 @@ static int nvmem_add_cells_from_of(struc
+ }
+
+ cell->np = of_node_get(child);
+- nvmem_cell_add(cell);
++ nvmem_cell_entry_add(cell);
+ }
+
+ return 0;
+@@ -1141,9 +1143,33 @@ struct nvmem_device *devm_nvmem_device_g
+ }
+ EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
+
++static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, const char *id)
++{
++ struct nvmem_cell *cell;
++ const char *name = NULL;
++
++ cell = kzalloc(sizeof(*cell), GFP_KERNEL);
++ if (!cell)
++ return ERR_PTR(-ENOMEM);
++
++ if (id) {
++ name = kstrdup_const(id, GFP_KERNEL);
++ if (!name) {
++ kfree(cell);
++ return ERR_PTR(-ENOMEM);
++ }
++ }
++
++ cell->id = name;
++ cell->entry = entry;
++
++ return cell;
++}
++
+ static struct nvmem_cell *
+ nvmem_cell_get_from_lookup(struct device *dev, const char *con_id)
+ {
++ struct nvmem_cell_entry *cell_entry;
+ struct nvmem_cell *cell = ERR_PTR(-ENOENT);
+ struct nvmem_cell_lookup *lookup;
+ struct nvmem_device *nvmem;
+@@ -1168,11 +1194,15 @@ nvmem_cell_get_from_lookup(struct device
+ break;
+ }
+
+- cell = nvmem_find_cell_by_name(nvmem,
+- lookup->cell_name);
+- if (!cell) {
++ cell_entry = nvmem_find_cell_entry_by_name(nvmem,
++ lookup->cell_name);
++ if (!cell_entry) {
+ __nvmem_device_put(nvmem);
+ cell = ERR_PTR(-ENOENT);
++ } else {
++ cell = nvmem_create_cell(cell_entry, con_id);
++ if (IS_ERR(cell))
++ __nvmem_device_put(nvmem);
+ }
+ break;
+ }
+@@ -1183,10 +1213,10 @@ nvmem_cell_get_from_lookup(struct device
+ }
+
+ #if IS_ENABLED(CONFIG_OF)
+-static struct nvmem_cell *
+-nvmem_find_cell_by_node(struct nvmem_device *nvmem, struct device_node *np)
++static struct nvmem_cell_entry *
++nvmem_find_cell_entry_by_node(struct nvmem_device *nvmem, struct device_node *np)
+ {
+- struct nvmem_cell *iter, *cell = NULL;
++ struct nvmem_cell_entry *iter, *cell = NULL;
+
+ mutex_lock(&nvmem_mutex);
+ list_for_each_entry(iter, &nvmem->cells, node) {
+@@ -1216,6 +1246,7 @@ struct nvmem_cell *of_nvmem_cell_get(str
+ {
+ struct device_node *cell_np, *nvmem_np;
+ struct nvmem_device *nvmem;
++ struct nvmem_cell_entry *cell_entry;
+ struct nvmem_cell *cell;
+ int index = 0;
+
+@@ -1236,12 +1267,16 @@ struct nvmem_cell *of_nvmem_cell_get(str
+ if (IS_ERR(nvmem))
+ return ERR_CAST(nvmem);
+
+- cell = nvmem_find_cell_by_node(nvmem, cell_np);
+- if (!cell) {
++ cell_entry = nvmem_find_cell_entry_by_node(nvmem, cell_np);
++ if (!cell_entry) {
+ __nvmem_device_put(nvmem);
+ return ERR_PTR(-ENOENT);
+ }
+
++ cell = nvmem_create_cell(cell_entry, id);
++ if (IS_ERR(cell))
++ __nvmem_device_put(nvmem);
++
+ return cell;
+ }
+ EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
+@@ -1347,13 +1382,17 @@ EXPORT_SYMBOL(devm_nvmem_cell_put);
+ */
+ void nvmem_cell_put(struct nvmem_cell *cell)
+ {
+- struct nvmem_device *nvmem = cell->nvmem;
++ struct nvmem_device *nvmem = cell->entry->nvmem;
++
++ if (cell->id)
++ kfree_const(cell->id);
+
++ kfree(cell);
+ __nvmem_device_put(nvmem);
+ }
+ EXPORT_SYMBOL_GPL(nvmem_cell_put);
+
+-static void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, void *buf)
++static void nvmem_shift_read_buffer_in_place(struct nvmem_cell_entry *cell, void *buf)
+ {
+ u8 *p, *b;
+ int i, extra, bit_offset = cell->bit_offset;
+@@ -1387,8 +1426,8 @@ static void nvmem_shift_read_buffer_in_p
+ }
+
+ static int __nvmem_cell_read(struct nvmem_device *nvmem,
+- struct nvmem_cell *cell,
+- void *buf, size_t *len)
++ struct nvmem_cell_entry *cell,
++ void *buf, size_t *len, const char *id)
+ {
+ int rc;
+
+@@ -1419,18 +1458,18 @@ static int __nvmem_cell_read(struct nvme
+ */
+ void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
+ {
+- struct nvmem_device *nvmem = cell->nvmem;
++ struct nvmem_device *nvmem = cell->entry->nvmem;
+ u8 *buf;
+ int rc;
+
+ if (!nvmem)
+ return ERR_PTR(-EINVAL);
+
+- buf = kzalloc(cell->bytes, GFP_KERNEL);
++ buf = kzalloc(cell->entry->bytes, GFP_KERNEL);
+ if (!buf)
+ return ERR_PTR(-ENOMEM);
+
+- rc = __nvmem_cell_read(nvmem, cell, buf, len);
++ rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id);
+ if (rc) {
+ kfree(buf);
+ return ERR_PTR(rc);
+@@ -1440,7 +1479,7 @@ void *nvmem_cell_read(struct nvmem_cell
+ }
+ EXPORT_SYMBOL_GPL(nvmem_cell_read);
+
+-static void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
++static void *nvmem_cell_prepare_write_buffer(struct nvmem_cell_entry *cell,
+ u8 *_buf, int len)
+ {
+ struct nvmem_device *nvmem = cell->nvmem;
+@@ -1493,16 +1532,7 @@ err:
+ return ERR_PTR(rc);
+ }
+
+-/**
+- * nvmem_cell_write() - Write to a given nvmem cell
+- *
+- * @cell: nvmem cell to be written.
+- * @buf: Buffer to be written.
+- * @len: length of buffer to be written to nvmem cell.
+- *
+- * Return: length of bytes written or negative on failure.
+- */
+-int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
++static int __nvmem_cell_entry_write(struct nvmem_cell_entry *cell, void *buf, size_t len)
+ {
+ struct nvmem_device *nvmem = cell->nvmem;
+ int rc;
+@@ -1528,6 +1558,21 @@ int nvmem_cell_write(struct nvmem_cell *
+
+ return len;
+ }
++
++/**
++ * nvmem_cell_write() - Write to a given nvmem cell
++ *
++ * @cell: nvmem cell to be written.
++ * @buf: Buffer to be written.
++ * @len: length of buffer to be written to nvmem cell.
++ *
++ * Return: length of bytes written or negative on failure.
++ */
++int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
++{
++ return __nvmem_cell_entry_write(cell->entry, buf, len);
++}
++
+ EXPORT_SYMBOL_GPL(nvmem_cell_write);
+
+ static int nvmem_cell_read_common(struct device *dev, const char *cell_id,
+@@ -1630,7 +1675,7 @@ static const void *nvmem_cell_read_varia
+ if (IS_ERR(cell))
+ return cell;
+
+- nbits = cell->nbits;
++ nbits = cell->entry->nbits;
+ buf = nvmem_cell_read(cell, len);
+ nvmem_cell_put(cell);
+ if (IS_ERR(buf))
+@@ -1726,18 +1771,18 @@ EXPORT_SYMBOL_GPL(nvmem_cell_read_variab
+ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info, void *buf)
+ {
+- struct nvmem_cell cell;
++ struct nvmem_cell_entry cell;
+ int rc;
+ ssize_t len;
+
+ if (!nvmem)
+ return -EINVAL;
+
+- rc = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, &cell);
++ rc = nvmem_cell_info_to_nvmem_cell_entry_nodup(nvmem, info, &cell);
+ if (rc)
+ return rc;
+
+- rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
++ rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL);
+ if (rc)
+ return rc;
+
+@@ -1757,17 +1802,17 @@ EXPORT_SYMBOL_GPL(nvmem_device_cell_read
+ int nvmem_device_cell_write(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info, void *buf)
+ {
+- struct nvmem_cell cell;
++ struct nvmem_cell_entry cell;
+ int rc;
+
+ if (!nvmem)
+ return -EINVAL;
+
+- rc = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, &cell);
++ rc = nvmem_cell_info_to_nvmem_cell_entry_nodup(nvmem, info, &cell);
+ if (rc)
+ return rc;
+
+- return nvmem_cell_write(&cell, buf, cell.bytes);
++ return __nvmem_cell_entry_write(&cell, buf, cell.bytes);
+ }
+ EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
+
--- /dev/null
+From 5008062f1c3f5af3acf86164aa6fcc77b0c7bdce Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Date: Wed, 13 Oct 2021 14:19:56 +0100
+Subject: [PATCH] nvmem: core: add nvmem cell post processing callback
+
+Some NVMEM providers have certain nvmem cells encoded, which requires
+post processing before actually using it.
+
+For example mac-address is stored in either in ascii or delimited or reverse-order.
+
+Having a post-process callback hook to provider drivers would enable them to
+do this vendor specific post processing before nvmem consumers see it.
+
+Tested-by: Joakim Zhang <qiangqing.zhang@nxp.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20211013131957.30271-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 9 +++++++++
+ include/linux/nvmem-provider.h | 5 +++++
+ 2 files changed, 14 insertions(+)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -38,6 +38,7 @@ struct nvmem_device {
+ unsigned int nkeepout;
+ nvmem_reg_read_t reg_read;
+ nvmem_reg_write_t reg_write;
++ nvmem_cell_post_process_t cell_post_process;
+ struct gpio_desc *wp_gpio;
+ void *priv;
+ };
+@@ -798,6 +799,7 @@ struct nvmem_device *nvmem_register(cons
+ nvmem->type = config->type;
+ nvmem->reg_read = config->reg_read;
+ nvmem->reg_write = config->reg_write;
++ nvmem->cell_post_process = config->cell_post_process;
+ nvmem->keepout = config->keepout;
+ nvmem->nkeepout = config->nkeepout;
+ if (config->of_node)
+@@ -1440,6 +1442,13 @@ static int __nvmem_cell_read(struct nvme
+ if (cell->bit_offset || cell->nbits)
+ nvmem_shift_read_buffer_in_place(cell, buf);
+
++ if (nvmem->cell_post_process) {
++ rc = nvmem->cell_post_process(nvmem->priv, id,
++ cell->offset, buf, cell->bytes);
++ if (rc)
++ return rc;
++ }
++
+ if (len)
+ *len = cell->bytes;
+
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -19,6 +19,9 @@ typedef int (*nvmem_reg_read_t)(void *pr
+ void *val, size_t bytes);
+ typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
+ void *val, size_t bytes);
++/* used for vendor specific post processing of cell data */
++typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, unsigned int offset,
++ void *buf, size_t bytes);
+
+ enum nvmem_type {
+ NVMEM_TYPE_UNKNOWN = 0,
+@@ -62,6 +65,7 @@ struct nvmem_keepout {
+ * @no_of_node: Device should not use the parent's of_node even if it's !NULL.
+ * @reg_read: Callback to read data.
+ * @reg_write: Callback to write data.
++ * @cell_post_process: Callback for vendor specific post processing of cell data
+ * @size: Device size.
+ * @word_size: Minimum read/write access granularity.
+ * @stride: Minimum read/write access stride.
+@@ -94,6 +98,7 @@ struct nvmem_config {
+ bool no_of_node;
+ nvmem_reg_read_t reg_read;
+ nvmem_reg_write_t reg_write;
++ nvmem_cell_post_process_t cell_post_process;
+ int size;
+ int word_size;
+ int stride;
--- /dev/null
+From d0221a780cbc99fec6c27a98dba2828dc5735c00 Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Date: Wed, 13 Oct 2021 14:19:57 +0100
+Subject: [PATCH] nvmem: imx-ocotp: add support for post processing
+
+Add .cell_post_process callback for imx-ocotp to deal with MAC address,
+since MAC address need to be reversed byte for some i.MX SoCs.
+
+Tested-by: Joakim Zhang <qiangqing.zhang@nxp.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20211013131957.30271-4-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/imx-ocotp.c | 25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+--- a/drivers/nvmem/imx-ocotp.c
++++ b/drivers/nvmem/imx-ocotp.c
+@@ -97,6 +97,7 @@ struct ocotp_params {
+ unsigned int bank_address_words;
+ void (*set_timing)(struct ocotp_priv *priv);
+ struct ocotp_ctrl_reg ctrl;
++ bool reverse_mac_address;
+ };
+
+ static int imx_ocotp_wait_for_busy(struct ocotp_priv *priv, u32 flags)
+@@ -221,6 +222,25 @@ read_end:
+ return ret;
+ }
+
++static int imx_ocotp_cell_pp(void *context, const char *id, unsigned int offset,
++ void *data, size_t bytes)
++{
++ struct ocotp_priv *priv = context;
++
++ /* Deal with some post processing of nvmem cell data */
++ if (id && !strcmp(id, "mac-address")) {
++ if (priv->params->reverse_mac_address) {
++ u8 *buf = data;
++ int i;
++
++ for (i = 0; i < bytes/2; i++)
++ swap(buf[i], buf[bytes - i - 1]);
++ }
++ }
++
++ return 0;
++}
++
+ static void imx_ocotp_set_imx6_timing(struct ocotp_priv *priv)
+ {
+ unsigned long clk_rate;
+@@ -468,6 +488,7 @@ static struct nvmem_config imx_ocotp_nvm
+ .stride = 1,
+ .reg_read = imx_ocotp_read,
+ .reg_write = imx_ocotp_write,
++ .cell_post_process = imx_ocotp_cell_pp,
+ };
+
+ static const struct ocotp_params imx6q_params = {
+@@ -530,6 +551,7 @@ static const struct ocotp_params imx8mq_
+ .bank_address_words = 0,
+ .set_timing = imx_ocotp_set_imx6_timing,
+ .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
++ .reverse_mac_address = true,
+ };
+
+ static const struct ocotp_params imx8mm_params = {
+@@ -537,6 +559,7 @@ static const struct ocotp_params imx8mm_
+ .bank_address_words = 0,
+ .set_timing = imx_ocotp_set_imx6_timing,
+ .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
++ .reverse_mac_address = true,
+ };
+
+ static const struct ocotp_params imx8mn_params = {
+@@ -544,6 +567,7 @@ static const struct ocotp_params imx8mn_
+ .bank_address_words = 0,
+ .set_timing = imx_ocotp_set_imx6_timing,
+ .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
++ .reverse_mac_address = true,
+ };
+
+ static const struct ocotp_params imx8mp_params = {
+@@ -551,6 +575,7 @@ static const struct ocotp_params imx8mp_
+ .bank_address_words = 0,
+ .set_timing = imx_ocotp_set_imx6_timing,
+ .ctrl = IMX_OCOTP_BM_CTRL_8MP,
++ .reverse_mac_address = true,
+ };
+
+ static const struct of_device_id imx_ocotp_dt_ids[] = {
+++ /dev/null
-From f955dc14450695564926711cf9fa8e1d5d854302 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Wed, 15 Jun 2022 21:43:00 +0200
-Subject: [PATCH] nvmem: add driver handling U-Boot environment variables
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-U-Boot stores its setup as environment variables. It's a list of
-key-value pairs stored on flash device with a custom header.
-
-This commit adds an NVMEM driver that:
-1. Provides NVMEM access to environment vars binary data
-2. Extracts variables as NVMEM cells
-
-Current Linux's NVMEM sysfs API allows reading whole NVMEM data block.
-It can be used by user-space tools for reading U-Boot env vars block
-without the hassle of finding its location. Parsing will still need to
-be re-done there.
-
-Kernel-parsed NVMEM cells can be read however by Linux drivers. This may
-be useful for Ethernet drivers for reading device MAC address which is
-often stored as U-Boot env variable.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
----
-
---- a/drivers/nvmem/Kconfig
-+++ b/drivers/nvmem/Kconfig
-@@ -300,4 +300,17 @@ config NVMEM_BRCM_NVRAM
- This driver provides support for Broadcom's NVRAM that can be accessed
- using I/O mapping.
-
-+config NVMEM_U_BOOT_ENV
-+ tristate "U-Boot environment variables support"
-+ depends on OF && MTD
-+ select CRC32
-+ help
-+ U-Boot stores its setup as environment variables. This driver adds
-+ support for verifying & exporting such data. It also exposes variables
-+ as NVMEM cells so they can be referenced by other drivers.
-+
-+ Currently this drivers works only with env variables on top of MTD.
-+
-+ If compiled as module it will be called nvmem_u-boot-env.
-+
- endif
---- a/drivers/nvmem/Makefile
-+++ b/drivers/nvmem/Makefile
-@@ -61,3 +61,5 @@ obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.
- nvmem-rmem-y := rmem.o
- obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_brcm_nvram.o
- nvmem_brcm_nvram-y := brcm_nvram.o
-+obj-$(CONFIG_NVMEM_U_BOOT_ENV) += nvmem_u-boot-env.o
-+nvmem_u-boot-env-y := u-boot-env.o
---- /dev/null
-+++ b/drivers/nvmem/u-boot-env.c
-@@ -0,0 +1,218 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+/*
-+ * Copyright (C) 2022 Rafał Miłecki <rafal@milecki.pl>
-+ */
-+
-+#include <linux/crc32.h>
-+#include <linux/mod_devicetable.h>
-+#include <linux/module.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/nvmem-consumer.h>
-+#include <linux/nvmem-provider.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_device.h>
-+#include <linux/slab.h>
-+
-+enum u_boot_env_format {
-+ U_BOOT_FORMAT_SINGLE,
-+ U_BOOT_FORMAT_REDUNDANT,
-+};
-+
-+struct u_boot_env {
-+ struct device *dev;
-+ enum u_boot_env_format format;
-+
-+ struct mtd_info *mtd;
-+
-+ /* Cells */
-+ struct nvmem_cell_info *cells;
-+ int ncells;
-+};
-+
-+struct u_boot_env_image_single {
-+ __le32 crc32;
-+ uint8_t data[];
-+} __packed;
-+
-+struct u_boot_env_image_redundant {
-+ __le32 crc32;
-+ u8 mark;
-+ uint8_t data[];
-+} __packed;
-+
-+static int u_boot_env_read(void *context, unsigned int offset, void *val,
-+ size_t bytes)
-+{
-+ struct u_boot_env *priv = context;
-+ struct device *dev = priv->dev;
-+ size_t bytes_read;
-+ int err;
-+
-+ err = mtd_read(priv->mtd, offset, bytes, &bytes_read, val);
-+ if (err && !mtd_is_bitflip(err)) {
-+ dev_err(dev, "Failed to read from mtd: %d\n", err);
-+ return err;
-+ }
-+
-+ if (bytes_read != bytes) {
-+ dev_err(dev, "Failed to read %zu bytes\n", bytes);
-+ return -EIO;
-+ }
-+
-+ return 0;
-+}
-+
-+static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf,
-+ size_t data_offset, size_t data_len)
-+{
-+ struct device *dev = priv->dev;
-+ char *data = buf + data_offset;
-+ char *var, *value, *eq;
-+ int idx;
-+
-+ priv->ncells = 0;
-+ for (var = data; var < data + 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, idx = 0;
-+ var < data + 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 = data_offset + value - data;
-+ priv->cells[idx].bytes = strlen(value);
-+ }
-+
-+ if (WARN_ON(idx != priv->ncells))
-+ priv->ncells = idx;
-+
-+ return 0;
-+}
-+
-+static int u_boot_env_parse(struct u_boot_env *priv)
-+{
-+ struct device *dev = priv->dev;
-+ size_t crc32_data_offset;
-+ size_t crc32_data_len;
-+ size_t crc32_offset;
-+ size_t data_offset;
-+ size_t data_len;
-+ uint32_t crc32;
-+ uint32_t calc;
-+ size_t bytes;
-+ uint8_t *buf;
-+ int err;
-+
-+ buf = kcalloc(1, priv->mtd->size, GFP_KERNEL);
-+ if (!buf) {
-+ err = -ENOMEM;
-+ goto err_out;
-+ }
-+
-+ err = mtd_read(priv->mtd, 0, priv->mtd->size, &bytes, buf);
-+ if ((err && !mtd_is_bitflip(err)) || bytes != priv->mtd->size) {
-+ dev_err(dev, "Failed to read from mtd: %d\n", err);
-+ goto err_kfree;
-+ }
-+
-+ switch (priv->format) {
-+ case U_BOOT_FORMAT_SINGLE:
-+ crc32_offset = offsetof(struct u_boot_env_image_single, crc32);
-+ crc32_data_offset = offsetof(struct u_boot_env_image_single, data);
-+ data_offset = offsetof(struct u_boot_env_image_single, data);
-+ break;
-+ case U_BOOT_FORMAT_REDUNDANT:
-+ crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32);
-+ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, mark);
-+ data_offset = offsetof(struct u_boot_env_image_redundant, data);
-+ break;
-+ }
-+ crc32 = le32_to_cpu(*(uint32_t *)(buf + crc32_offset));
-+ crc32_data_len = priv->mtd->size - crc32_data_offset;
-+ data_len = priv->mtd->size - data_offset;
-+
-+ calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L;
-+ if (calc != crc32) {
-+ dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32);
-+ err = -EINVAL;
-+ goto err_kfree;
-+ }
-+
-+ buf[priv->mtd->size - 1] = '\0';
-+ err = u_boot_env_add_cells(priv, buf, data_offset, data_len);
-+ if (err)
-+ dev_err(dev, "Failed to add cells: %d\n", err);
-+
-+err_kfree:
-+ kfree(buf);
-+err_out:
-+ return err;
-+}
-+
-+static int u_boot_env_probe(struct platform_device *pdev)
-+{
-+ struct nvmem_config config = {
-+ .name = "u-boot-env",
-+ .reg_read = u_boot_env_read,
-+ };
-+ struct device *dev = &pdev->dev;
-+ struct device_node *np = dev->of_node;
-+ struct u_boot_env *priv;
-+ int err;
-+
-+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+ if (!priv)
-+ return -ENOMEM;
-+ priv->dev = dev;
-+
-+ priv->format = (uintptr_t)of_device_get_match_data(dev);
-+
-+ priv->mtd = of_get_mtd_device_by_node(np);
-+ if (IS_ERR(priv->mtd)) {
-+ dev_err_probe(dev, PTR_ERR(priv->mtd), "Failed to get %pOF MTD\n", np);
-+ return PTR_ERR(priv->mtd);
-+ }
-+
-+ err = u_boot_env_parse(priv);
-+ if (err)
-+ return err;
-+
-+ config.dev = dev;
-+ config.cells = priv->cells;
-+ config.ncells = priv->ncells;
-+ config.priv = priv;
-+ config.size = priv->mtd->size;
-+
-+ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config));
-+}
-+
-+static const struct of_device_id u_boot_env_of_match_table[] = {
-+ { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, },
-+ { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
-+ { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
-+ {},
-+};
-+
-+static struct platform_driver u_boot_env_driver = {
-+ .probe = u_boot_env_probe,
-+ .driver = {
-+ .name = "u_boot_env",
-+ .of_match_table = u_boot_env_of_match_table,
-+ },
-+};
-+module_platform_driver(u_boot_env_driver);
-+
-+MODULE_AUTHOR("Rafał Miłecki");
-+MODULE_LICENSE("GPL");
-+MODULE_DEVICE_TABLE(of, u_boot_env_of_match_table);
+++ /dev/null
-From d69efcf951df4dcc74a0e1554969c533aec8aa9b Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Thu, 15 Sep 2022 22:06:29 +0200
-Subject: [PATCH] nvmem: u-boot-env: find Device Tree nodes for NVMEM cells
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-DT binding allows specifying NVMEM cells as NVMEM device (provider)
-subnodes. Looks for such subnodes when building NVMEM cells.
-
-This allows NVMEM consumers to use U-Boot environment variables.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
----
- drivers/nvmem/u-boot-env.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/nvmem/u-boot-env.c
-+++ b/drivers/nvmem/u-boot-env.c
-@@ -92,6 +92,7 @@ static int u_boot_env_add_cells(struct u
- return -ENOMEM;
- priv->cells[idx].offset = data_offset + value - data;
- priv->cells[idx].bytes = strlen(value);
-+ priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
- }
-
- if (WARN_ON(idx != priv->ncells))
+++ /dev/null
-From 60bbaad38109684b156e21112322e0a922f92cde Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Thu, 18 Aug 2022 06:38:37 +0200
-Subject: [PATCH] nvmem: u-boot-env: fix crc32 casting type
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This fixes:
-drivers/nvmem/u-boot-env.c:141:17: sparse: sparse: cast to restricted __le32
-
-Reported-by: kernel test robot <lkp@intel.com>
-Fixes: f955dc1445069 ("nvmem: add driver handling U-Boot environment variables")
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
----
- drivers/nvmem/u-boot-env.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/nvmem/u-boot-env.c
-+++ b/drivers/nvmem/u-boot-env.c
-@@ -139,7 +139,7 @@ static int u_boot_env_parse(struct u_boo
- data_offset = offsetof(struct u_boot_env_image_redundant, data);
- break;
- }
-- crc32 = le32_to_cpu(*(uint32_t *)(buf + crc32_offset));
-+ crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset));
- crc32_data_len = priv->mtd->size - crc32_data_offset;
- data_len = priv->mtd->size - data_offset;
-
--- /dev/null
+From 98e2c4efae214fb7086cac9117616eb6ea11475d Mon Sep 17 00:00:00 2001
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Date: Thu, 9 Dec 2021 17:42:34 +0000
+Subject: [PATCH] nvmem: mtk-efuse: support minimum one byte access stride and
+ granularity
+
+In order to support nvmem bits property, should support minimum 1 byte
+read stride and minimum 1 byte read granularity at the same time.
+
+Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20211209174235.14049-4-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/mtk-efuse.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/drivers/nvmem/mtk-efuse.c
++++ b/drivers/nvmem/mtk-efuse.c
+@@ -19,11 +19,12 @@ static int mtk_reg_read(void *context,
+ unsigned int reg, void *_val, size_t bytes)
+ {
+ struct mtk_efuse_priv *priv = context;
+- u32 *val = _val;
+- int i = 0, words = bytes / 4;
++ void __iomem *addr = priv->base + reg;
++ u8 *val = _val;
++ int i;
+
+- while (words--)
+- *val++ = readl(priv->base + reg + (i++ * 4));
++ for (i = 0; i < bytes; i++, val++)
++ *val = readb(addr + i);
+
+ return 0;
+ }
+@@ -45,8 +46,8 @@ static int mtk_efuse_probe(struct platfo
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+- econfig.stride = 4;
+- econfig.word_size = 4;
++ econfig.stride = 1;
++ econfig.word_size = 1;
+ econfig.reg_read = mtk_reg_read;
+ econfig.size = resource_size(res);
+ econfig.priv = priv;
+++ /dev/null
-From dbc2f62061c6bfba0aee93161ee3194dcee84bd0 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Fri, 29 Apr 2022 17:26:46 +0100
-Subject: [PATCH] nvmem: core: support passing DT node in cell info
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Some hardware may have NVMEM cells described in Device Tree using
-individual nodes. Let drivers pass such nodes to the NVMEM subsystem so
-they can be later used by NVMEM consumers.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-Link: https://lore.kernel.org/r/20220429162701.2222-2-srinivas.kandagatla@linaro.org
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/nvmem/core.c | 1 +
- include/linux/nvmem-consumer.h | 1 +
- 2 files changed, 2 insertions(+)
-
---- a/drivers/nvmem/core.c
-+++ b/drivers/nvmem/core.c
-@@ -462,6 +462,7 @@ static int nvmem_cell_info_to_nvmem_cell
-
- cell->bit_offset = info->bit_offset;
- cell->nbits = info->nbits;
-+ cell->np = info->np;
-
- if (cell->nbits)
- cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
---- a/include/linux/nvmem-consumer.h
-+++ b/include/linux/nvmem-consumer.h
-@@ -25,6 +25,7 @@ struct nvmem_cell_info {
- unsigned int bytes;
- unsigned int bit_offset;
- unsigned int nbits;
-+ struct device_node *np;
- };
-
- /**
--- /dev/null
+From 190fae468592bc2f0efc8b928920f8f712b5831e Mon Sep 17 00:00:00 2001
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Date: Sun, 20 Feb 2022 15:15:15 +0000
+Subject: [PATCH] nvmem: core: Remove unused devm_nvmem_unregister()
+
+There are no users and seems no will come of the devm_nvmem_unregister().
+Remove the function and remove the unused devm_nvmem_match() along with it.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151527.17216-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 22 ----------------------
+ include/linux/nvmem-provider.h | 8 --------
+ 2 files changed, 30 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -942,28 +942,6 @@ struct nvmem_device *devm_nvmem_register
+ }
+ EXPORT_SYMBOL_GPL(devm_nvmem_register);
+
+-static int devm_nvmem_match(struct device *dev, void *res, void *data)
+-{
+- struct nvmem_device **r = res;
+-
+- return *r == data;
+-}
+-
+-/**
+- * devm_nvmem_unregister() - Unregister previously registered managed nvmem
+- * device.
+- *
+- * @dev: Device that uses the nvmem device.
+- * @nvmem: Pointer to previously registered nvmem device.
+- *
+- * Return: Will be negative on error or zero on success.
+- */
+-int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
+-{
+- return devres_release(dev, devm_nvmem_release, devm_nvmem_match, nvmem);
+-}
+-EXPORT_SYMBOL(devm_nvmem_unregister);
+-
+ static struct nvmem_device *__nvmem_device_get(void *data,
+ int (*match)(struct device *dev, const void *data))
+ {
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -135,8 +135,6 @@ void nvmem_unregister(struct nvmem_devic
+ struct nvmem_device *devm_nvmem_register(struct device *dev,
+ const struct nvmem_config *cfg);
+
+-int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem);
+-
+ void nvmem_add_cell_table(struct nvmem_cell_table *table);
+ void nvmem_del_cell_table(struct nvmem_cell_table *table);
+
+@@ -155,12 +153,6 @@ devm_nvmem_register(struct device *dev,
+ return nvmem_register(c);
+ }
+
+-static inline int
+-devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
+-{
+- return -EOPNOTSUPP;
+-}
+-
+ static inline void nvmem_add_cell_table(struct nvmem_cell_table *table) {}
+ static inline void nvmem_del_cell_table(struct nvmem_cell_table *table) {}
+
--- /dev/null
+From 5825b2c6762611e67ccaf3ccf64485365a120f0b Mon Sep 17 00:00:00 2001
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Date: Sun, 20 Feb 2022 15:15:16 +0000
+Subject: [PATCH] nvmem: core: Use devm_add_action_or_reset()
+
+Slightly simplify the devm_nvmem_register() by using the
+devm_add_action_or_reset().
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151527.17216-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 22 +++++++++-------------
+ 1 file changed, 9 insertions(+), 13 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -904,9 +904,9 @@ void nvmem_unregister(struct nvmem_devic
+ }
+ EXPORT_SYMBOL_GPL(nvmem_unregister);
+
+-static void devm_nvmem_release(struct device *dev, void *res)
++static void devm_nvmem_unregister(void *nvmem)
+ {
+- nvmem_unregister(*(struct nvmem_device **)res);
++ nvmem_unregister(nvmem);
+ }
+
+ /**
+@@ -923,20 +923,16 @@ static void devm_nvmem_release(struct de
+ struct nvmem_device *devm_nvmem_register(struct device *dev,
+ const struct nvmem_config *config)
+ {
+- struct nvmem_device **ptr, *nvmem;
+-
+- ptr = devres_alloc(devm_nvmem_release, sizeof(*ptr), GFP_KERNEL);
+- if (!ptr)
+- return ERR_PTR(-ENOMEM);
++ struct nvmem_device *nvmem;
++ int ret;
+
+ nvmem = nvmem_register(config);
++ if (IS_ERR(nvmem))
++ return nvmem;
+
+- if (!IS_ERR(nvmem)) {
+- *ptr = nvmem;
+- devres_add(dev, ptr);
+- } else {
+- devres_free(ptr);
+- }
++ ret = devm_add_action_or_reset(dev, devm_nvmem_unregister, nvmem);
++ if (ret)
++ return ERR_PTR(ret);
+
+ return nvmem;
+ }
--- /dev/null
+From 8c751e0d9a5264376935a84429a2d468c8877d99 Mon Sep 17 00:00:00 2001
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Date: Sun, 20 Feb 2022 15:15:17 +0000
+Subject: [PATCH] nvmem: core: Check input parameter for NULL in
+ nvmem_unregister()
+
+nvmem_unregister() frees resources and standard pattern is to allow
+caller to not care if it's NULL or not. This will reduce burden on
+the callers to perform this check.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151527.17216-4-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -900,7 +900,8 @@ static void nvmem_device_release(struct
+ */
+ void nvmem_unregister(struct nvmem_device *nvmem)
+ {
+- kref_put(&nvmem->refcnt, nvmem_device_release);
++ if (nvmem)
++ kref_put(&nvmem->refcnt, nvmem_device_release);
+ }
+ EXPORT_SYMBOL_GPL(nvmem_unregister);
+
--- /dev/null
+From 05196facc052385960028ac634447ecf6c764ec3 Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Date: Sun, 20 Feb 2022 15:15:18 +0000
+Subject: [PATCH] nvmem: qfprom: fix kerneldoc warning
+
+This patch fixes below kernel doc warning,
+warning: expecting prototype for qfprom_efuse_reg_write().
+Prototype was for qfprom_reg_write() instead
+
+No code changes.
+
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151527.17216-5-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/qfprom.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/qfprom.c
++++ b/drivers/nvmem/qfprom.c
+@@ -244,7 +244,7 @@ err_clk_prepared:
+ }
+
+ /**
+- * qfprom_efuse_reg_write() - Write to fuses.
++ * qfprom_reg_write() - Write to fuses.
+ * @context: Our driver data.
+ * @reg: The offset to write at.
+ * @_val: Pointer to data to write.
--- /dev/null
+From 07ae4fde9efada7878e1383d6ccc7da70315ca23 Mon Sep 17 00:00:00 2001
+From: Samuel Holland <samuel@sholland.org>
+Date: Sun, 20 Feb 2022 15:15:20 +0000
+Subject: [PATCH] nvmem: sunxi_sid: Add support for D1 variant
+
+D1 has a smaller eFuse block than some other recent SoCs, and it no
+longer requires a workaround to read the eFuse data.
+
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151527.17216-7-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/sunxi_sid.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/nvmem/sunxi_sid.c
++++ b/drivers/nvmem/sunxi_sid.c
+@@ -184,6 +184,11 @@ static const struct sunxi_sid_cfg sun8i_
+ .need_register_readout = true,
+ };
+
++static const struct sunxi_sid_cfg sun20i_d1_cfg = {
++ .value_offset = 0x200,
++ .size = 0x100,
++};
++
+ static const struct sunxi_sid_cfg sun50i_a64_cfg = {
+ .value_offset = 0x200,
+ .size = 0x100,
+@@ -200,6 +205,7 @@ static const struct of_device_id sunxi_s
+ { .compatible = "allwinner,sun7i-a20-sid", .data = &sun7i_a20_cfg },
+ { .compatible = "allwinner,sun8i-a83t-sid", .data = &sun50i_a64_cfg },
+ { .compatible = "allwinner,sun8i-h3-sid", .data = &sun8i_h3_cfg },
++ { .compatible = "allwinner,sun20i-d1-sid", .data = &sun20i_d1_cfg },
+ { .compatible = "allwinner,sun50i-a64-sid", .data = &sun50i_a64_cfg },
+ { .compatible = "allwinner,sun50i-h5-sid", .data = &sun50i_a64_cfg },
+ { .compatible = "allwinner,sun50i-h6-sid", .data = &sun50i_h6_cfg },
--- /dev/null
+From 4dc8d89faed9bb05f116fa1794fc955b14910386 Mon Sep 17 00:00:00 2001
+From: Xiaoke Wang <xkernel.wang@foxmail.com>
+Date: Sun, 20 Feb 2022 15:15:21 +0000
+Subject: [PATCH] nvmem: meson-mx-efuse: replace unnecessary devm_kstrdup()
+
+Replace unnecessary devm_kstrdup() so to avoid redundant memory allocation.
+
+Suggested-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+Signed-off-by: Xiaoke Wang <xkernel.wang@foxmail.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151527.17216-8-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/meson-mx-efuse.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/nvmem/meson-mx-efuse.c
++++ b/drivers/nvmem/meson-mx-efuse.c
+@@ -209,8 +209,7 @@ static int meson_mx_efuse_probe(struct p
+ if (IS_ERR(efuse->base))
+ return PTR_ERR(efuse->base);
+
+- efuse->config.name = devm_kstrdup(&pdev->dev, drvdata->name,
+- GFP_KERNEL);
++ efuse->config.name = drvdata->name;
+ efuse->config.owner = THIS_MODULE;
+ efuse->config.dev = &pdev->dev;
+ efuse->config.priv = efuse;
--- /dev/null
+From f78451012b9e159afdba31c3eb69f223a9f42adc Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Sun, 20 Feb 2022 15:15:23 +0000
+Subject: [PATCH] nvmem: add driver for Layerscape SFP (Security Fuse
+ Processor)
+
+Add support for the Security Fuse Processor found on Layerscape SoCs.
+This driver implements basic read access.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220220151527.17216-10-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/Kconfig | 12 +++++
+ drivers/nvmem/Makefile | 2 +
+ drivers/nvmem/layerscape-sfp.c | 89 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 103 insertions(+)
+ create mode 100644 drivers/nvmem/layerscape-sfp.c
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -300,4 +300,16 @@ config NVMEM_BRCM_NVRAM
+ This driver provides support for Broadcom's NVRAM that can be accessed
+ using I/O mapping.
+
++config NVMEM_LAYERSCAPE_SFP
++ tristate "Layerscape SFP (Security Fuse Processor) support"
++ depends on ARCH_LAYERSCAPE || COMPILE_TEST
++ depends on HAS_IOMEM
++ help
++ This driver provides support to read the eFuses on Freescale
++ Layerscape SoC's. For example, the vendor provides a per part
++ unique ID there.
++
++ This driver can also be built as a module. If so, the module
++ will be called layerscape-sfp.
++
+ endif
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -61,3 +61,5 @@ obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.
+ nvmem-rmem-y := rmem.o
+ obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_brcm_nvram.o
+ nvmem_brcm_nvram-y := brcm_nvram.o
++obj-$(CONFIG_NVMEM_LAYERSCAPE_SFP) += nvmem-layerscape-sfp.o
++nvmem-layerscape-sfp-y := layerscape-sfp.o
+--- /dev/null
++++ b/drivers/nvmem/layerscape-sfp.c
+@@ -0,0 +1,89 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Layerscape SFP driver
++ *
++ * Copyright (c) 2022 Michael Walle <michael@walle.cc>
++ *
++ */
++
++#include <linux/device.h>
++#include <linux/io.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/nvmem-provider.h>
++#include <linux/platform_device.h>
++#include <linux/property.h>
++
++#define LAYERSCAPE_SFP_OTP_OFFSET 0x0200
++
++struct layerscape_sfp_priv {
++ void __iomem *base;
++};
++
++struct layerscape_sfp_data {
++ int size;
++};
++
++static int layerscape_sfp_read(void *context, unsigned int offset, void *val,
++ size_t bytes)
++{
++ struct layerscape_sfp_priv *priv = context;
++
++ memcpy_fromio(val, priv->base + LAYERSCAPE_SFP_OTP_OFFSET + offset,
++ bytes);
++
++ return 0;
++}
++
++static struct nvmem_config layerscape_sfp_nvmem_config = {
++ .name = "fsl-sfp",
++ .reg_read = layerscape_sfp_read,
++};
++
++static int layerscape_sfp_probe(struct platform_device *pdev)
++{
++ const struct layerscape_sfp_data *data;
++ struct layerscape_sfp_priv *priv;
++ struct nvmem_device *nvmem;
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(priv->base))
++ return PTR_ERR(priv->base);
++
++ data = device_get_match_data(&pdev->dev);
++
++ layerscape_sfp_nvmem_config.size = data->size;
++ layerscape_sfp_nvmem_config.dev = &pdev->dev;
++ layerscape_sfp_nvmem_config.priv = priv;
++
++ nvmem = devm_nvmem_register(&pdev->dev, &layerscape_sfp_nvmem_config);
++
++ return PTR_ERR_OR_ZERO(nvmem);
++}
++
++static const struct layerscape_sfp_data ls1028a_data = {
++ .size = 0x88,
++};
++
++static const struct of_device_id layerscape_sfp_dt_ids[] = {
++ { .compatible = "fsl,ls1028a-sfp", .data = &ls1028a_data },
++ {},
++};
++MODULE_DEVICE_TABLE(of, layerscape_sfp_dt_ids);
++
++static struct platform_driver layerscape_sfp_driver = {
++ .probe = layerscape_sfp_probe,
++ .driver = {
++ .name = "layerscape_sfp",
++ .of_match_table = layerscape_sfp_dt_ids,
++ },
++};
++module_platform_driver(layerscape_sfp_driver);
++
++MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
++MODULE_DESCRIPTION("Layerscape Security Fuse Processor driver");
++MODULE_LICENSE("GPL");
--- /dev/null
+From bc5c75e0a5a9400f81a987cc720100ac475fa4d8 Mon Sep 17 00:00:00 2001
+From: Knox Chiou <knoxchiou@chromium.org>
+Date: Wed, 23 Feb 2022 22:35:00 +0000
+Subject: [PATCH] nvmem: qfprom: Increase fuse blow timeout to prevent write
+ fail
+
+sc7180 blow fuses got slightly chances to hit qfprom_reg_write timeout.
+Current timeout is simply too low. Since blowing fuses is a
+very rare operation, so the risk associated with overestimating this
+number is low.
+Increase fuse blow timeout from 1ms to 10ms.
+
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Knox Chiou <knoxchiou@chromium.org>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220223223502.29454-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/qfprom.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/qfprom.c
++++ b/drivers/nvmem/qfprom.c
+@@ -22,7 +22,7 @@
+
+ /* Amount of time required to hold charge to blow fuse in micro-seconds */
+ #define QFPROM_FUSE_BLOW_POLL_US 100
+-#define QFPROM_FUSE_BLOW_TIMEOUT_US 1000
++#define QFPROM_FUSE_BLOW_TIMEOUT_US 10000
+
+ #define QFPROM_BLOW_STATUS_OFFSET 0x048
+ #define QFPROM_BLOW_STATUS_BUSY 0x1
--- /dev/null
+From 8747ec2e9762ed9ae53b3a590938f454b6a1abdf Mon Sep 17 00:00:00 2001
+From: Vincent Shih <vincent.sunplus@gmail.com>
+Date: Wed, 23 Feb 2022 22:35:01 +0000
+Subject: [PATCH] nvmem: Add driver for OCOTP in Sunplus SP7021
+
+Add driver for OCOTP in Sunplus SP7021
+
+Signed-off-by: Vincent Shih <vincent.sunplus@gmail.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220223223502.29454-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ MAINTAINERS | 5 +
+ drivers/nvmem/Kconfig | 12 ++
+ drivers/nvmem/Makefile | 2 +
+ drivers/nvmem/sunplus-ocotp.c | 228 ++++++++++++++++++++++++++++++++++
+ 4 files changed, 247 insertions(+)
+ create mode 100644 drivers/nvmem/sunplus-ocotp.c
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -17953,6 +17953,11 @@ L: netdev@vger.kernel.org
+ S: Maintained
+ F: drivers/net/ethernet/dlink/sundance.c
+
++SUNPLUS OCOTP DRIVER
++M: Vincent Shih <vincent.sunplus@gmail.com>
++S: Maintained
++F: drivers/nvmem/sunplus-ocotp.c
++
+ SUPERH
+ M: Yoshinori Sato <ysato@users.sourceforge.jp>
+ M: Rich Felker <dalias@libc.org>
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -312,4 +312,16 @@ config NVMEM_LAYERSCAPE_SFP
+ This driver can also be built as a module. If so, the module
+ will be called layerscape-sfp.
+
++config NVMEM_SUNPLUS_OCOTP
++ tristate "Sunplus SoC OTP support"
++ depends on SOC_SP7021 || COMPILE_TEST
++ depends on HAS_IOMEM
++ help
++ This is a driver for the On-chip OTP controller (OCOTP) available
++ on Sunplus SoCs. It provides access to 128 bytes of one-time
++ programmable eFuse.
++
++ This driver can also be built as a module. If so, the module
++ will be called nvmem-sunplus-ocotp.
++
+ endif
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -63,3 +63,5 @@ obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_
+ nvmem_brcm_nvram-y := brcm_nvram.o
+ obj-$(CONFIG_NVMEM_LAYERSCAPE_SFP) += nvmem-layerscape-sfp.o
+ nvmem-layerscape-sfp-y := layerscape-sfp.o
++obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvmem_sunplus_ocotp.o
++nvmem_sunplus_ocotp-y := sunplus-ocotp.o
+--- /dev/null
++++ b/drivers/nvmem/sunplus-ocotp.c
+@@ -0,0 +1,228 @@
++// SPDX-License-Identifier: GPL-2.0
++
++/*
++ * The OCOTP driver for Sunplus SP7021
++ *
++ * Copyright (C) 2019 Sunplus Technology Inc., All rights reserved.
++ */
++
++#include <linux/bitfield.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/io.h>
++#include <linux/iopoll.h>
++#include <linux/module.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++
++/*
++ * OTP memory
++ * Each bank contains 4 words (32 bits).
++ * Bank 0 starts at offset 0 from the base.
++ */
++
++#define OTP_WORDS_PER_BANK 4
++#define OTP_WORD_SIZE sizeof(u32)
++#define OTP_BIT_ADDR_OF_BANK (8 * OTP_WORD_SIZE * OTP_WORDS_PER_BANK)
++#define QAC628_OTP_NUM_BANKS 8
++#define QAC628_OTP_SIZE (QAC628_OTP_NUM_BANKS * OTP_WORDS_PER_BANK * OTP_WORD_SIZE)
++#define OTP_READ_TIMEOUT_US 200000
++
++/* HB_GPIO */
++#define ADDRESS_8_DATA 0x20
++
++/* OTP_RX */
++#define OTP_CONTROL_2 0x48
++#define OTP_RD_PERIOD GENMASK(15, 8)
++#define OTP_RD_PERIOD_MASK ~GENMASK(15, 8)
++#define CPU_CLOCK FIELD_PREP(OTP_RD_PERIOD, 30)
++#define SEL_BAK_KEY2 BIT(5)
++#define SEL_BAK_KEY2_MASK ~BIT(5)
++#define SW_TRIM_EN BIT(4)
++#define SW_TRIM_EN_MASK ~BIT(4)
++#define SEL_BAK_KEY BIT(3)
++#define SEL_BAK_KEY_MASK ~BIT(3)
++#define OTP_READ BIT(2)
++#define OTP_LOAD_SECURE_DATA BIT(1)
++#define OTP_LOAD_SECURE_DATA_MASK ~BIT(1)
++#define OTP_DO_CRC BIT(0)
++#define OTP_DO_CRC_MASK ~BIT(0)
++#define OTP_STATUS 0x4c
++#define OTP_READ_DONE BIT(4)
++#define OTP_READ_DONE_MASK ~BIT(4)
++#define OTP_LOAD_SECURE_DONE_MASK ~BIT(2)
++#define OTP_READ_ADDRESS 0x50
++
++enum base_type {
++ HB_GPIO,
++ OTPRX,
++ BASEMAX,
++};
++
++struct sp_ocotp_priv {
++ struct device *dev;
++ void __iomem *base[BASEMAX];
++ struct clk *clk;
++};
++
++struct sp_ocotp_data {
++ int size;
++};
++
++const struct sp_ocotp_data sp_otp_v0 = {
++ .size = QAC628_OTP_SIZE,
++};
++
++static int sp_otp_read_real(struct sp_ocotp_priv *otp, int addr, char *value)
++{
++ unsigned int addr_data;
++ unsigned int byte_shift;
++ unsigned int status;
++ int ret;
++
++ addr_data = addr % (OTP_WORD_SIZE * OTP_WORDS_PER_BANK);
++ addr_data = addr_data / OTP_WORD_SIZE;
++
++ byte_shift = addr % (OTP_WORD_SIZE * OTP_WORDS_PER_BANK);
++ byte_shift = byte_shift % OTP_WORD_SIZE;
++
++ addr = addr / (OTP_WORD_SIZE * OTP_WORDS_PER_BANK);
++ addr = addr * OTP_BIT_ADDR_OF_BANK;
++
++ writel(readl(otp->base[OTPRX] + OTP_STATUS) & OTP_READ_DONE_MASK &
++ OTP_LOAD_SECURE_DONE_MASK, otp->base[OTPRX] + OTP_STATUS);
++ writel(addr, otp->base[OTPRX] + OTP_READ_ADDRESS);
++ writel(readl(otp->base[OTPRX] + OTP_CONTROL_2) | OTP_READ,
++ otp->base[OTPRX] + OTP_CONTROL_2);
++ writel(readl(otp->base[OTPRX] + OTP_CONTROL_2) & SEL_BAK_KEY2_MASK & SW_TRIM_EN_MASK
++ & SEL_BAK_KEY_MASK & OTP_LOAD_SECURE_DATA_MASK & OTP_DO_CRC_MASK,
++ otp->base[OTPRX] + OTP_CONTROL_2);
++ writel((readl(otp->base[OTPRX] + OTP_CONTROL_2) & OTP_RD_PERIOD_MASK) | CPU_CLOCK,
++ otp->base[OTPRX] + OTP_CONTROL_2);
++
++ ret = readl_poll_timeout(otp->base[OTPRX] + OTP_STATUS, status,
++ status & OTP_READ_DONE, 10, OTP_READ_TIMEOUT_US);
++
++ if (ret < 0)
++ return ret;
++
++ *value = (readl(otp->base[HB_GPIO] + ADDRESS_8_DATA + addr_data * OTP_WORD_SIZE)
++ >> (8 * byte_shift)) & 0xff;
++
++ return ret;
++}
++
++static int sp_ocotp_read(void *priv, unsigned int offset, void *value, size_t bytes)
++{
++ struct sp_ocotp_priv *otp = priv;
++ unsigned int addr;
++ char *buf = value;
++ char val[4];
++ int ret;
++
++ ret = clk_enable(otp->clk);
++ if (ret)
++ return ret;
++
++ *buf = 0;
++ for (addr = offset; addr < (offset + bytes); addr++) {
++ ret = sp_otp_read_real(otp, addr, val);
++ if (ret < 0) {
++ dev_err(otp->dev, "OTP read fail:%d at %d", ret, addr);
++ goto disable_clk;
++ }
++
++ *buf++ = *val;
++ }
++
++disable_clk:
++ clk_disable(otp->clk);
++
++ return ret;
++}
++
++static struct nvmem_config sp_ocotp_nvmem_config = {
++ .name = "sp-ocotp",
++ .read_only = true,
++ .word_size = 1,
++ .size = QAC628_OTP_SIZE,
++ .stride = 1,
++ .reg_read = sp_ocotp_read,
++ .owner = THIS_MODULE,
++};
++
++static int sp_ocotp_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct nvmem_device *nvmem;
++ struct sp_ocotp_priv *otp;
++ struct resource *res;
++ int ret;
++
++ otp = devm_kzalloc(dev, sizeof(*otp), GFP_KERNEL);
++ if (!otp)
++ return -ENOMEM;
++
++ otp->dev = dev;
++
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hb_gpio");
++ otp->base[HB_GPIO] = devm_ioremap_resource(dev, res);
++ if (IS_ERR(otp->base[HB_GPIO]))
++ return PTR_ERR(otp->base[HB_GPIO]);
++
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otprx");
++ otp->base[OTPRX] = devm_ioremap_resource(dev, res);
++ if (IS_ERR(otp->base[OTPRX]))
++ return PTR_ERR(otp->base[OTPRX]);
++
++ otp->clk = devm_clk_get(&pdev->dev, NULL);
++ if (IS_ERR(otp->clk))
++ return dev_err_probe(&pdev->dev, PTR_ERR(otp->clk),
++ "devm_clk_get fail\n");
++
++ ret = clk_prepare(otp->clk);
++ if (ret < 0) {
++ dev_err(dev, "failed to prepare clk: %d\n", ret);
++ return ret;
++ }
++
++ sp_ocotp_nvmem_config.priv = otp;
++ sp_ocotp_nvmem_config.dev = dev;
++
++ nvmem = devm_nvmem_register(dev, &sp_ocotp_nvmem_config);
++ if (IS_ERR(nvmem))
++ return dev_err_probe(&pdev->dev, PTR_ERR(nvmem),
++ "register nvmem device fail\n");
++
++ platform_set_drvdata(pdev, nvmem);
++
++ dev_dbg(dev, "banks:%d x wpb:%d x wsize:%d = %d",
++ (int)QAC628_OTP_NUM_BANKS, (int)OTP_WORDS_PER_BANK,
++ (int)OTP_WORD_SIZE, (int)QAC628_OTP_SIZE);
++
++ dev_info(dev, "by Sunplus (C) 2020");
++
++ return 0;
++}
++
++static const struct of_device_id sp_ocotp_dt_ids[] = {
++ { .compatible = "sunplus,sp7021-ocotp", .data = &sp_otp_v0 },
++ { }
++};
++MODULE_DEVICE_TABLE(of, sp_ocotp_dt_ids);
++
++static struct platform_driver sp_otp_driver = {
++ .probe = sp_ocotp_probe,
++ .driver = {
++ .name = "sunplus,sp7021-ocotp",
++ .of_match_table = sp_ocotp_dt_ids,
++ }
++};
++module_platform_driver(sp_otp_driver);
++
++MODULE_AUTHOR("Vincent Shih <vincent.sunplus@gmail.com>");
++MODULE_DESCRIPTION("Sunplus On-Chip OTP driver");
++MODULE_LICENSE("GPL");
++
--- /dev/null
+From 6e977eaa8280e957b87904b536661550f2a6b3e8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+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 <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220225175822.8293-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
+
+++ /dev/null
-From 7a69ff9c9bde03a690ea783970f664782fc303d8 Mon Sep 17 00:00:00 2001
-From: Christian Lamparter <chunkeey@gmail.com>
-Date: Fri, 4 Nov 2022 17:52:03 +0100
-Subject: [PATCH] nvmem: u-boot-env: fix crc32_data_offset on redundant
- u-boot-env
-
-The Western Digital MyBook Live (PowerPC 464/APM82181)
-has a set of redundant u-boot-env. Loading up the driver
-the following error:
-
-| u_boot_env: Invalid calculated CRC32: 0x4f8f2c86 (expected: 0x98b14514)
-| u_boot_env: probe of partition@1e000 failed with error -22
-
-Looking up the userspace libubootenv utilities source [0],
-it looks like the "mark" or "flag" is not part of the
-crc32 sum... which is unfortunate :(
-
-|static int libuboot_load(struct uboot_ctx *ctx)
-|{
-|[...]
-| if (ctx->redundant) {
-| [...]
-| offsetdata = offsetof(struct uboot_env_redund, data);
-| [...] //-----^^
-| }
-| usable_envsize = ctx->size - offsetdata;
-| buf[0] = malloc(bufsize);
-|[...]
-| for (i = 0; i < copies; i++) {
-| data = (uint8_t *)(buf[i] + offsetdata);
-| uint32_t crc;
-|
-| ret = devread(ctx, i, buf[i]);
-| [...]
-| crc = *(uint32_t *)(buf[i] + offsetcrc);
-| dev->crc = crc32(0, (uint8_t *)data, usable_envsize);
-|
-
-[0] https://github.com/sbabic/libubootenv/blob/master/src/uboot_env.c#L951
-Fixes: d5542923f200 ("nvmem: add driver handling U-Boot environment variables")
-Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
----
- drivers/nvmem/u-boot-env.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/nvmem/u-boot-env.c
-+++ b/drivers/nvmem/u-boot-env.c
-@@ -135,7 +135,7 @@ static int u_boot_env_parse(struct u_boo
- break;
- case U_BOOT_FORMAT_REDUNDANT:
- crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32);
-- crc32_data_offset = offsetof(struct u_boot_env_image_redundant, mark);
-+ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data);
- data_offset = offsetof(struct u_boot_env_image_redundant, data);
- break;
- }
+++ /dev/null
-From 0e71cac033bb7689c4dfa2e6814191337ef770f5 Mon Sep 17 00:00:00 2001
-From: INAGAKI Hiroshi <musashino.open@gmail.com>
-Date: Thu, 13 Oct 2022 00:51:33 +0900
-Subject: [PATCH] nvmem: u-boot-env: align endianness of crc32 values
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This patch fixes crc32 error on Big-Endianness system by conversion of
-calculated crc32 value.
-
-Little-Endianness system:
-
- obtained crc32: Little
-calculated crc32: Little
-
-Big-Endianness system:
-
- obtained crc32: Little
-calculated crc32: Big
-
-log (APRESIA ApresiaLightGS120GT-SS, RTL8382M, Big-Endianness):
-
-[ 8.570000] u_boot_env 18001200.spi:flash@0:partitions:partition@c0000: Invalid calculated CRC32: 0x88cd6f09 (expected: 0x096fcd88)
-[ 8.580000] u_boot_env: probe of 18001200.spi:flash@0:partitions:partition@c0000 failed with error -22
-
-Fixes: f955dc1445069 ("nvmem: add driver handling U-Boot environment variables")
-
-Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
-Acked-by: Rafał Miłecki <rafal@milecki.pl>
-Tested-by: Christian Lamparter <chunkeey@gmail.com>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
----
- drivers/nvmem/u-boot-env.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/nvmem/u-boot-env.c
-+++ b/drivers/nvmem/u-boot-env.c
-@@ -143,7 +143,7 @@ static int u_boot_env_parse(struct u_boo
- crc32_data_len = priv->mtd->size - crc32_data_offset;
- data_len = priv->mtd->size - data_offset;
-
-- calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L;
-+ calc = le32_to_cpu((__le32)crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L);
- if (calc != crc32) {
- dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32);
- err = -EINVAL;
+++ /dev/null
-From 5b4eaafbeac472fc19049152f18e88aecb2b2829 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Mon, 17 Oct 2022 09:17:22 +0200
-Subject: [PATCH] nvmem: u-boot-env: add Broadcom format support
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Broadcom uses U-Boot for a lot of their bcmbca familiy chipsets. They
-decided to store U-Boot environment data inside U-Boot partition and to
-use a custom header (with "uEnv" magic and env data length).
-
-Add support for Broadcom's specific binding and their custom format.
-
-Ref: 6b0584c19d87 ("dt-bindings: nvmem: u-boot,env: add Broadcom's variant binding")
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
----
- drivers/nvmem/u-boot-env.c | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
---- a/drivers/nvmem/u-boot-env.c
-+++ b/drivers/nvmem/u-boot-env.c
-@@ -16,6 +16,7 @@
- enum u_boot_env_format {
- U_BOOT_FORMAT_SINGLE,
- U_BOOT_FORMAT_REDUNDANT,
-+ U_BOOT_FORMAT_BROADCOM,
- };
-
- struct u_boot_env {
-@@ -40,6 +41,13 @@ struct u_boot_env_image_redundant {
- uint8_t data[];
- } __packed;
-
-+struct u_boot_env_image_broadcom {
-+ __le32 magic;
-+ __le32 len;
-+ __le32 crc32;
-+ uint8_t data[0];
-+} __packed;
-+
- static int u_boot_env_read(void *context, unsigned int offset, void *val,
- size_t bytes)
- {
-@@ -138,6 +146,11 @@ static int u_boot_env_parse(struct u_boo
- crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data);
- data_offset = offsetof(struct u_boot_env_image_redundant, data);
- break;
-+ case U_BOOT_FORMAT_BROADCOM:
-+ crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32);
-+ crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data);
-+ data_offset = offsetof(struct u_boot_env_image_broadcom, data);
-+ break;
- }
- crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset));
- crc32_data_len = priv->mtd->size - crc32_data_offset;
-@@ -202,6 +215,7 @@ static const struct of_device_id u_boot_
- { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, },
- { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
- { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
-+ { .compatible = "brcm,env", .data = (void *)U_BOOT_FORMAT_BROADCOM, },
- {},
- };
-
--- /dev/null
+From 6bd0ffeaa389866089e9573b2298ae58d6359b75 Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzk@kernel.org>
+Date: Mon, 21 Mar 2022 12:03:24 +0100
+Subject: [PATCH] nvmem: bcm-ocotp: mark ACPI device ID table as maybe unused
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+"bcm_otpc_acpi_ids" is used with ACPI_PTR, so a build with !CONFIG_ACPI
+has a warning:
+
+ drivers/nvmem/bcm-ocotp.c:247:36: error:
+ ‘bcm_otpc_acpi_ids’ defined but not used [-Werror=unused-const-variable=]
+
+Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
+Link: https://lore.kernel.org/r/20220321110326.44652-1-krzk@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/bcm-ocotp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/bcm-ocotp.c
++++ b/drivers/nvmem/bcm-ocotp.c
+@@ -244,7 +244,7 @@ static const struct of_device_id bcm_otp
+ };
+ MODULE_DEVICE_TABLE(of, bcm_otpc_dt_ids);
+
+-static const struct acpi_device_id bcm_otpc_acpi_ids[] = {
++static const struct acpi_device_id bcm_otpc_acpi_ids[] __maybe_unused = {
+ { .id = "BRCM0700", .driver_data = (kernel_ulong_t)&otp_map },
+ { .id = "BRCM0701", .driver_data = (kernel_ulong_t)&otp_map_v2 },
+ { /* sentinel */ }
--- /dev/null
+From 1066f8156351fcd997125257cea47cf805ba4f6d Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzk@kernel.org>
+Date: Mon, 21 Mar 2022 12:03:25 +0100
+Subject: [PATCH] nvmem: sunplus-ocotp: staticize sp_otp_v0
+
+The "sp_otp_v0" file scope variable is not used outside, so make it
+static to fix warning:
+
+ drivers/nvmem/sunplus-ocotp.c:74:29: sparse:
+ sparse: symbol 'sp_otp_v0' was not declared. Should it be static?
+
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
+Link: https://lore.kernel.org/r/20220321110326.44652-2-krzk@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/sunplus-ocotp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/sunplus-ocotp.c
++++ b/drivers/nvmem/sunplus-ocotp.c
+@@ -71,7 +71,7 @@ struct sp_ocotp_data {
+ int size;
+ };
+
+-const struct sp_ocotp_data sp_otp_v0 = {
++static const struct sp_ocotp_data sp_otp_v0 = {
+ .size = QAC628_OTP_SIZE,
+ };
+
--- /dev/null
+From 874dfbcf219ccc42a2cbd187d087c7db82c3024b Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzk@kernel.org>
+Date: Mon, 21 Mar 2022 12:03:26 +0100
+Subject: [PATCH] nvmem: sunplus-ocotp: drop useless probe confirmation
+
+Printing probe success is discouraged, because we can use tracing for
+this purpose. Remove useless print message after Sunplus OCOTP driver
+probe.
+
+Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
+Link: https://lore.kernel.org/r/20220321110326.44652-3-krzk@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/sunplus-ocotp.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/nvmem/sunplus-ocotp.c
++++ b/drivers/nvmem/sunplus-ocotp.c
+@@ -202,8 +202,6 @@ static int sp_ocotp_probe(struct platfor
+ (int)QAC628_OTP_NUM_BANKS, (int)OTP_WORDS_PER_BANK,
+ (int)OTP_WORD_SIZE, (int)QAC628_OTP_SIZE);
+
+- dev_info(dev, "by Sunplus (C) 2020");
+-
+ return 0;
+ }
+
--- /dev/null
+From dbc2f62061c6bfba0aee93161ee3194dcee84bd0 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 29 Apr 2022 17:26:46 +0100
+Subject: [PATCH] nvmem: core: support passing DT node in cell info
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Some hardware may have NVMEM cells described in Device Tree using
+individual nodes. Let drivers pass such nodes to the NVMEM subsystem so
+they can be later used by NVMEM consumers.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220429162701.2222-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 1 +
+ include/linux/nvmem-consumer.h | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -467,6 +467,7 @@ static int nvmem_cell_info_to_nvmem_cell
+
+ cell->bit_offset = info->bit_offset;
+ cell->nbits = info->nbits;
++ cell->np = info->np;
+
+ if (cell->nbits)
+ cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
+--- a/include/linux/nvmem-consumer.h
++++ b/include/linux/nvmem-consumer.h
+@@ -25,6 +25,7 @@ struct nvmem_cell_info {
+ unsigned int bytes;
+ unsigned int bit_offset;
+ unsigned int nbits;
++ struct device_node *np;
+ };
+
+ /**
--- /dev/null
+From 207775f7e17b8fd0426a2ac4a5b81e4e1d71849e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 29 Apr 2022 17:26:47 +0100
+Subject: [PATCH] nvmem: brcm_nvram: find Device Tree nodes for NVMEM cells
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+DT binding for Broadcom's NVRAM supports specifying NVMEM cells as NVMEM
+device (provider) subnodes. Look for such subnodes when collecing NVMEM
+cells. This allows NVMEM consumers to use NVRAM variables.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220429162701.2222-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/brcm_nvram.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/nvmem/brcm_nvram.c
++++ b/drivers/nvmem/brcm_nvram.c
+@@ -8,6 +8,7 @@
+ #include <linux/module.h>
+ #include <linux/nvmem-consumer.h>
+ #include <linux/nvmem-provider.h>
++#include <linux/of.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
+
+@@ -72,6 +73,7 @@ static int brcm_nvram_add_cells(struct b
+ return -ENOMEM;
+ priv->cells[idx].offset = value - (char *)data;
+ priv->cells[idx].bytes = strlen(value);
++ priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
+ }
+
+ return 0;
--- /dev/null
+From b6b7ef932ae838209254f016ecf8862d716a5ced Mon Sep 17 00:00:00 2001
+From: Sven Peter <sven@svenpeter.dev>
+Date: Fri, 29 Apr 2022 17:26:50 +0100
+Subject: [PATCH] nvmem: Add Apple eFuse driver
+
+Apple SoCs contain eFuses used to store factory-programmed data such
+as calibration values for the PCIe or the Type-C PHY. They are organized
+as 32bit values exposed as MMIO.
+
+Signed-off-by: Sven Peter <sven@svenpeter.dev>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220429162701.2222-6-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/Kconfig | 12 ++++++
+ drivers/nvmem/Makefile | 2 +
+ drivers/nvmem/apple-efuses.c | 80 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 94 insertions(+)
+ create mode 100644 drivers/nvmem/apple-efuses.c
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -324,4 +324,16 @@ config NVMEM_SUNPLUS_OCOTP
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-sunplus-ocotp.
+
++config NVMEM_APPLE_EFUSES
++ tristate "Apple eFuse support"
++ depends on ARCH_APPLE || COMPILE_TEST
++ default ARCH_APPLE
++ help
++ Say y here to enable support for reading eFuses on Apple SoCs
++ such as the M1. These are e.g. used to store factory programmed
++ calibration data required for the PCIe or the USB-C PHY.
++
++ This driver can also be built as a module. If so, the module will
++ be called nvmem-apple-efuses.
++
+ endif
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -65,3 +65,5 @@ obj-$(CONFIG_NVMEM_LAYERSCAPE_SFP) += nv
+ nvmem-layerscape-sfp-y := layerscape-sfp.o
+ obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvmem_sunplus_ocotp.o
+ nvmem_sunplus_ocotp-y := sunplus-ocotp.o
++obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
++nvmem-apple-efuses-y := apple-efuses.o
+--- /dev/null
++++ b/drivers/nvmem/apple-efuses.c
+@@ -0,0 +1,80 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Apple SoC eFuse driver
++ *
++ * Copyright (C) The Asahi Linux Contributors
++ */
++
++#include <linux/io.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/nvmem-provider.h>
++#include <linux/platform_device.h>
++
++struct apple_efuses_priv {
++ void __iomem *fuses;
++};
++
++static int apple_efuses_read(void *context, unsigned int offset, void *val,
++ size_t bytes)
++{
++ struct apple_efuses_priv *priv = context;
++ u32 *dst = val;
++
++ while (bytes >= sizeof(u32)) {
++ *dst++ = readl_relaxed(priv->fuses + offset);
++ bytes -= sizeof(u32);
++ offset += sizeof(u32);
++ }
++
++ return 0;
++}
++
++static int apple_efuses_probe(struct platform_device *pdev)
++{
++ struct apple_efuses_priv *priv;
++ struct resource *res;
++ struct nvmem_config config = {
++ .dev = &pdev->dev,
++ .read_only = true,
++ .reg_read = apple_efuses_read,
++ .stride = sizeof(u32),
++ .word_size = sizeof(u32),
++ .name = "apple_efuses_nvmem",
++ .id = NVMEM_DEVID_AUTO,
++ .root_only = true,
++ };
++
++ priv = devm_kzalloc(config.dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->fuses = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
++ if (IS_ERR(priv->fuses))
++ return PTR_ERR(priv->fuses);
++
++ config.priv = priv;
++ config.size = resource_size(res);
++
++ return PTR_ERR_OR_ZERO(devm_nvmem_register(config.dev, &config));
++}
++
++static const struct of_device_id apple_efuses_of_match[] = {
++ { .compatible = "apple,efuses", },
++ {}
++};
++
++MODULE_DEVICE_TABLE(of, apple_efuses_of_match);
++
++static struct platform_driver apple_efuses_driver = {
++ .driver = {
++ .name = "apple_efuses",
++ .of_match_table = apple_efuses_of_match,
++ },
++ .probe = apple_efuses_probe,
++};
++
++module_platform_driver(apple_efuses_driver);
++
++MODULE_AUTHOR("Sven Peter <sven@svenpeter.dev>");
++MODULE_LICENSE("GPL");
--- /dev/null
+From 517f6e2641a2802dce5a5aa0d18c7d37a35678d2 Mon Sep 17 00:00:00 2001
+From: Minghao Chi <chi.minghao@zte.com.cn>
+Date: Fri, 29 Apr 2022 17:26:54 +0100
+Subject: [PATCH] nvmem: qfprom: using pm_runtime_resume_and_get instead of
+ pm_runtime_get_sync
+
+Using pm_runtime_resume_and_get is more appropriate
+for simplifing code
+
+Reported-by: Zeal Robot <zealci@zte.com.cn>
+Signed-off-by: Minghao Chi <chi.minghao@zte.com.cn>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220429162701.2222-10-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/qfprom.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/nvmem/qfprom.c
++++ b/drivers/nvmem/qfprom.c
+@@ -217,9 +217,8 @@ static int qfprom_enable_fuse_blowing(co
+ goto err_clk_rate_set;
+ }
+
+- ret = pm_runtime_get_sync(priv->dev);
++ ret = pm_runtime_resume_and_get(priv->dev);
+ if (ret < 0) {
+- pm_runtime_put_noidle(priv->dev);
+ dev_err(priv->dev, "Failed to enable power-domain\n");
+ goto err_reg_enable;
+ }
--- /dev/null
+From 943eadbdb11314b41eacbcc484dfb7f93e271ff4 Mon Sep 17 00:00:00 2001
+From: Sean Anderson <sean.anderson@seco.com>
+Date: Fri, 29 Apr 2022 17:27:00 +0100
+Subject: [PATCH] nvmem: sfp: Use regmap
+
+This converts the SFP driver to use regmap. This will allow easily
+supporting devices with different endians. We disallow byte-level
+access, as regmap_bulk_read doesn't support it (and it's unclear what
+the correct result would be when we have an endianness difference).
+
+Signed-off-by: Sean Anderson <sean.anderson@seco.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220429162701.2222-16-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/Kconfig | 1 +
+ drivers/nvmem/layerscape-sfp.c | 30 ++++++++++++++++++++++--------
+ 2 files changed, 23 insertions(+), 8 deletions(-)
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -304,6 +304,7 @@ config NVMEM_LAYERSCAPE_SFP
+ tristate "Layerscape SFP (Security Fuse Processor) support"
+ depends on ARCH_LAYERSCAPE || COMPILE_TEST
+ depends on HAS_IOMEM
++ select REGMAP_MMIO
+ help
+ This driver provides support to read the eFuses on Freescale
+ Layerscape SoC's. For example, the vendor provides a per part
+--- a/drivers/nvmem/layerscape-sfp.c
++++ b/drivers/nvmem/layerscape-sfp.c
+@@ -13,15 +13,17 @@
+ #include <linux/nvmem-provider.h>
+ #include <linux/platform_device.h>
+ #include <linux/property.h>
++#include <linux/regmap.h>
+
+ #define LAYERSCAPE_SFP_OTP_OFFSET 0x0200
+
+ struct layerscape_sfp_priv {
+- void __iomem *base;
++ struct regmap *regmap;
+ };
+
+ struct layerscape_sfp_data {
+ int size;
++ enum regmap_endian endian;
+ };
+
+ static int layerscape_sfp_read(void *context, unsigned int offset, void *val,
+@@ -29,15 +31,16 @@ static int layerscape_sfp_read(void *con
+ {
+ struct layerscape_sfp_priv *priv = context;
+
+- memcpy_fromio(val, priv->base + LAYERSCAPE_SFP_OTP_OFFSET + offset,
+- bytes);
+-
+- return 0;
++ return regmap_bulk_read(priv->regmap,
++ LAYERSCAPE_SFP_OTP_OFFSET + offset, val,
++ bytes / 4);
+ }
+
+ static struct nvmem_config layerscape_sfp_nvmem_config = {
+ .name = "fsl-sfp",
+ .reg_read = layerscape_sfp_read,
++ .word_size = 4,
++ .stride = 4,
+ };
+
+ static int layerscape_sfp_probe(struct platform_device *pdev)
+@@ -45,16 +48,26 @@ static int layerscape_sfp_probe(struct p
+ const struct layerscape_sfp_data *data;
+ struct layerscape_sfp_priv *priv;
+ struct nvmem_device *nvmem;
++ struct regmap_config config = { 0 };
++ void __iomem *base;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+- priv->base = devm_platform_ioremap_resource(pdev, 0);
+- if (IS_ERR(priv->base))
+- return PTR_ERR(priv->base);
++ base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(base))
++ return PTR_ERR(base);
+
+ data = device_get_match_data(&pdev->dev);
++ config.reg_bits = 32;
++ config.reg_stride = 4;
++ config.val_bits = 32;
++ config.val_format_endian = data->endian;
++ config.max_register = LAYERSCAPE_SFP_OTP_OFFSET + data->size - 4;
++ priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, &config);
++ if (IS_ERR(priv->regmap))
++ return PTR_ERR(priv->regmap);
+
+ layerscape_sfp_nvmem_config.size = data->size;
+ layerscape_sfp_nvmem_config.dev = &pdev->dev;
+@@ -67,6 +80,7 @@ static int layerscape_sfp_probe(struct p
+
+ static const struct layerscape_sfp_data ls1028a_data = {
+ .size = 0x88,
++ .endian = REGMAP_ENDIAN_LITTLE,
+ };
+
+ static const struct of_device_id layerscape_sfp_dt_ids[] = {
--- /dev/null
+From 33a1c6618677fe33f8e84cb7bedc45abbce89a50 Mon Sep 17 00:00:00 2001
+From: Sean Anderson <sean.anderson@seco.com>
+Date: Fri, 29 Apr 2022 17:27:01 +0100
+Subject: [PATCH] nvmem: sfp: Add support for TA 2.1 devices
+
+This adds support for Trust Architecture (TA) 2.1 devices to the SFP driver.
+There are few differences between TA 2.1 and TA 3.0, especially for
+read-only support, so just re-use the existing data.
+
+Signed-off-by: Sean Anderson <sean.anderson@seco.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220429162701.2222-17-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/layerscape-sfp.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/nvmem/layerscape-sfp.c
++++ b/drivers/nvmem/layerscape-sfp.c
+@@ -78,12 +78,18 @@ static int layerscape_sfp_probe(struct p
+ return PTR_ERR_OR_ZERO(nvmem);
+ }
+
++static const struct layerscape_sfp_data ls1021a_data = {
++ .size = 0x88,
++ .endian = REGMAP_ENDIAN_BIG,
++};
++
+ static const struct layerscape_sfp_data ls1028a_data = {
+ .size = 0x88,
+ .endian = REGMAP_ENDIAN_LITTLE,
+ };
+
+ static const struct of_device_id layerscape_sfp_dt_ids[] = {
++ { .compatible = "fsl,ls1021a-sfp", .data = &ls1021a_data },
+ { .compatible = "fsl,ls1028a-sfp", .data = &ls1028a_data },
+ {},
+ };
--- /dev/null
+From 98830350d3fc824c1ff5c338140fe20f041a5916 Mon Sep 17 00:00:00 2001
+From: Claudiu Beznea <claudiu.beznea@microchip.com>
+Date: Wed, 6 Jul 2022 11:06:22 +0100
+Subject: [PATCH] nvmem: microchip-otpc: add support
+
+Add support for Microchip OTP controller available on SAMA7G5. The OTPC
+controls the access to a non-volatile memory. The memory behind OTPC is
+organized into packets, packets are composed by a fixed length header
+(4 bytes long) and a variable length payload (payload length is available
+in the header). When software request the data at an offset in memory
+the OTPC will return (via header + data registers) the whole packet that
+has a word at that offset. For the OTP memory layout like below:
+
+offset OTP Memory layout
+
+ . .
+ . ... .
+ . .
+0x0E +-----------+ <--- packet X
+ | header X |
+0x12 +-----------+
+ | payload X |
+0x16 | |
+ | |
+0x1A | |
+ +-----------+
+ . .
+ . ... .
+ . .
+
+if user requests data at address 0x16 the data started at 0x0E will be
+returned by controller. User will be able to fetch the whole packet
+starting at 0x0E (or parts of the packet) via proper registers. The same
+packet will be returned if software request the data at offset 0x0E or
+0x12 or 0x1A.
+
+The OTP will be populated by Microchip with at least 2 packets first one
+being boot configuration packet and the 2nd one being temperature
+calibration packet. The packet order will be preserved b/w different chip
+revisions but the packet sizes may change.
+
+For the above reasons and to keep the same software able to work on all
+chip variants the read function of the driver is working with a packet
+id instead of an offset in OTP memory.
+
+Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220706100627.6534-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ MAINTAINERS | 8 +
+ drivers/nvmem/Kconfig | 7 +
+ drivers/nvmem/Makefile | 2 +
+ drivers/nvmem/microchip-otpc.c | 288 +++++++++++++++++++++++++++++++++
+ 4 files changed, 305 insertions(+)
+ create mode 100644 drivers/nvmem/microchip-otpc.c
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -12353,6 +12353,14 @@ S: Supported
+ F: Documentation/devicetree/bindings/mtd/atmel-nand.txt
+ F: drivers/mtd/nand/raw/atmel/*
+
++MICROCHIP OTPC DRIVER
++M: Claudiu Beznea <claudiu.beznea@microchip.com>
++L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
++S: Supported
++F: Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
++F: drivers/nvmem/microchip-otpc.c
++F: dt-bindings/nvmem/microchip,sama7g5-otpc.h
++
+ MICROCHIP PWM DRIVER
+ M: Claudiu Beznea <claudiu.beznea@microchip.com>
+ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -107,6 +107,13 @@ config MTK_EFUSE
+ This driver can also be built as a module. If so, the module
+ will be called efuse-mtk.
+
++config MICROCHIP_OTPC
++ tristate "Microchip OTPC support"
++ depends on ARCH_AT91 || COMPILE_TEST
++ help
++ This driver enable the OTP controller available on Microchip SAMA7G5
++ SoCs. It controlls the access to the OTP memory connected to it.
++
+ config NVMEM_NINTENDO_OTP
+ tristate "Nintendo Wii and Wii U OTP Support"
+ depends on WII || COMPILE_TEST
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -67,3 +67,5 @@ obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvm
+ nvmem_sunplus_ocotp-y := sunplus-ocotp.o
+ obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
+ nvmem-apple-efuses-y := apple-efuses.o
++obj-$(CONFIG_MICROCHIP_OTPC) += nvmem-microchip-otpc.o
++nvmem-microchip-otpc-y := microchip-otpc.o
+--- /dev/null
++++ b/drivers/nvmem/microchip-otpc.c
+@@ -0,0 +1,288 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * OTP Memory controller
++ *
++ * Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries
++ *
++ * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
++ */
++
++#include <linux/bitfield.h>
++#include <linux/iopoll.h>
++#include <linux/module.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++
++#define MCHP_OTPC_CR (0x0)
++#define MCHP_OTPC_CR_READ BIT(6)
++#define MCHP_OTPC_MR (0x4)
++#define MCHP_OTPC_MR_ADDR GENMASK(31, 16)
++#define MCHP_OTPC_AR (0x8)
++#define MCHP_OTPC_SR (0xc)
++#define MCHP_OTPC_SR_READ BIT(6)
++#define MCHP_OTPC_HR (0x20)
++#define MCHP_OTPC_HR_SIZE GENMASK(15, 8)
++#define MCHP_OTPC_DR (0x24)
++
++#define MCHP_OTPC_NAME "mchp-otpc"
++#define MCHP_OTPC_SIZE (11 * 1024)
++
++/**
++ * struct mchp_otpc - OTPC private data structure
++ * @base: base address
++ * @dev: struct device pointer
++ * @packets: list of packets in OTP memory
++ * @npackets: number of packets in OTP memory
++ */
++struct mchp_otpc {
++ void __iomem *base;
++ struct device *dev;
++ struct list_head packets;
++ u32 npackets;
++};
++
++/**
++ * struct mchp_otpc_packet - OTPC packet data structure
++ * @list: list head
++ * @id: packet ID
++ * @offset: packet offset (in words) in OTP memory
++ */
++struct mchp_otpc_packet {
++ struct list_head list;
++ u32 id;
++ u32 offset;
++};
++
++static struct mchp_otpc_packet *mchp_otpc_id_to_packet(struct mchp_otpc *otpc,
++ u32 id)
++{
++ struct mchp_otpc_packet *packet;
++
++ if (id >= otpc->npackets)
++ return NULL;
++
++ list_for_each_entry(packet, &otpc->packets, list) {
++ if (packet->id == id)
++ return packet;
++ }
++
++ return NULL;
++}
++
++static int mchp_otpc_prepare_read(struct mchp_otpc *otpc,
++ unsigned int offset)
++{
++ u32 tmp;
++
++ /* Set address. */
++ tmp = readl_relaxed(otpc->base + MCHP_OTPC_MR);
++ tmp &= ~MCHP_OTPC_MR_ADDR;
++ tmp |= FIELD_PREP(MCHP_OTPC_MR_ADDR, offset);
++ writel_relaxed(tmp, otpc->base + MCHP_OTPC_MR);
++
++ /* Set read. */
++ tmp = readl_relaxed(otpc->base + MCHP_OTPC_CR);
++ tmp |= MCHP_OTPC_CR_READ;
++ writel_relaxed(tmp, otpc->base + MCHP_OTPC_CR);
++
++ /* Wait for packet to be transferred into temporary buffers. */
++ return read_poll_timeout(readl_relaxed, tmp, !(tmp & MCHP_OTPC_SR_READ),
++ 10000, 2000, false, otpc->base + MCHP_OTPC_SR);
++}
++
++/*
++ * OTPC memory is organized into packets. Each packets contains a header and
++ * a payload. Header is 4 bytes long and contains the size of the payload.
++ * Payload size varies. The memory footprint is something as follows:
++ *
++ * Memory offset Memory footprint Packet ID
++ * ------------- ---------------- ---------
++ *
++ * 0x0 +------------+ <-- packet 0
++ * | header 0 |
++ * 0x4 +------------+
++ * | payload 0 |
++ * . .
++ * . ... .
++ * . .
++ * offset1 +------------+ <-- packet 1
++ * | header 1 |
++ * offset1 + 0x4 +------------+
++ * | payload 1 |
++ * . .
++ * . ... .
++ * . .
++ * offset2 +------------+ <-- packet 2
++ * . .
++ * . ... .
++ * . .
++ * offsetN +------------+ <-- packet N
++ * | header N |
++ * offsetN + 0x4 +------------+
++ * | payload N |
++ * . .
++ * . ... .
++ * . .
++ * +------------+
++ *
++ * where offset1, offset2, offsetN depends on the size of payload 0, payload 1,
++ * payload N-1.
++ *
++ * The access to memory is done on a per packet basis: the control registers
++ * need to be updated with an offset address (within a packet range) and the
++ * data registers will be update by controller with information contained by
++ * that packet. E.g. if control registers are updated with any address within
++ * the range [offset1, offset2) the data registers are updated by controller
++ * with packet 1. Header data is accessible though MCHP_OTPC_HR register.
++ * Payload data is accessible though MCHP_OTPC_DR and MCHP_OTPC_AR registers.
++ * There is no direct mapping b/w the offset requested by software and the
++ * offset returned by hardware.
++ *
++ * For this, the read function will return the first requested bytes in the
++ * packet. The user will have to be aware of the memory footprint before doing
++ * the read request.
++ */
++static int mchp_otpc_read(void *priv, unsigned int off, void *val,
++ size_t bytes)
++{
++ struct mchp_otpc *otpc = priv;
++ struct mchp_otpc_packet *packet;
++ u32 *buf = val;
++ u32 offset;
++ size_t len = 0;
++ int ret, payload_size;
++
++ /*
++ * We reach this point with off being multiple of stride = 4 to
++ * be able to cross the subsystem. Inside the driver we use continuous
++ * unsigned integer numbers for packet id, thus devide off by 4
++ * before passing it to mchp_otpc_id_to_packet().
++ */
++ packet = mchp_otpc_id_to_packet(otpc, off / 4);
++ if (!packet)
++ return -EINVAL;
++ offset = packet->offset;
++
++ while (len < bytes) {
++ ret = mchp_otpc_prepare_read(otpc, offset);
++ if (ret)
++ return ret;
++
++ /* Read and save header content. */
++ *buf++ = readl_relaxed(otpc->base + MCHP_OTPC_HR);
++ len += sizeof(*buf);
++ offset++;
++ if (len >= bytes)
++ break;
++
++ /* Read and save payload content. */
++ payload_size = FIELD_GET(MCHP_OTPC_HR_SIZE, *(buf - 1));
++ writel_relaxed(0UL, otpc->base + MCHP_OTPC_AR);
++ do {
++ *buf++ = readl_relaxed(otpc->base + MCHP_OTPC_DR);
++ len += sizeof(*buf);
++ offset++;
++ payload_size--;
++ } while (payload_size >= 0 && len < bytes);
++ }
++
++ return 0;
++}
++
++static int mchp_otpc_init_packets_list(struct mchp_otpc *otpc, u32 *size)
++{
++ struct mchp_otpc_packet *packet;
++ u32 word, word_pos = 0, id = 0, npackets = 0, payload_size;
++ int ret;
++
++ INIT_LIST_HEAD(&otpc->packets);
++ *size = 0;
++
++ while (*size < MCHP_OTPC_SIZE) {
++ ret = mchp_otpc_prepare_read(otpc, word_pos);
++ if (ret)
++ return ret;
++
++ word = readl_relaxed(otpc->base + MCHP_OTPC_HR);
++ payload_size = FIELD_GET(MCHP_OTPC_HR_SIZE, word);
++ if (!payload_size)
++ break;
++
++ packet = devm_kzalloc(otpc->dev, sizeof(*packet), GFP_KERNEL);
++ if (!packet)
++ return -ENOMEM;
++
++ packet->id = id++;
++ packet->offset = word_pos;
++ INIT_LIST_HEAD(&packet->list);
++ list_add_tail(&packet->list, &otpc->packets);
++
++ /* Count size by adding header and paload sizes. */
++ *size += 4 * (payload_size + 1);
++ /* Next word: this packet (header, payload) position + 1. */
++ word_pos += payload_size + 2;
++
++ npackets++;
++ }
++
++ otpc->npackets = npackets;
++
++ return 0;
++}
++
++static struct nvmem_config mchp_nvmem_config = {
++ .name = MCHP_OTPC_NAME,
++ .type = NVMEM_TYPE_OTP,
++ .read_only = true,
++ .word_size = 4,
++ .stride = 4,
++ .reg_read = mchp_otpc_read,
++};
++
++static int mchp_otpc_probe(struct platform_device *pdev)
++{
++ struct nvmem_device *nvmem;
++ struct mchp_otpc *otpc;
++ u32 size;
++ int ret;
++
++ otpc = devm_kzalloc(&pdev->dev, sizeof(*otpc), GFP_KERNEL);
++ if (!otpc)
++ return -ENOMEM;
++
++ otpc->base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(otpc->base))
++ return PTR_ERR(otpc->base);
++
++ otpc->dev = &pdev->dev;
++ ret = mchp_otpc_init_packets_list(otpc, &size);
++ if (ret)
++ return ret;
++
++ mchp_nvmem_config.dev = otpc->dev;
++ mchp_nvmem_config.size = size;
++ mchp_nvmem_config.priv = otpc;
++ nvmem = devm_nvmem_register(&pdev->dev, &mchp_nvmem_config);
++
++ return PTR_ERR_OR_ZERO(nvmem);
++}
++
++static const struct of_device_id __maybe_unused mchp_otpc_ids[] = {
++ { .compatible = "microchip,sama7g5-otpc", },
++ { },
++};
++MODULE_DEVICE_TABLE(of, mchp_otpc_ids);
++
++static struct platform_driver mchp_otpc_driver = {
++ .probe = mchp_otpc_probe,
++ .driver = {
++ .name = MCHP_OTPC_NAME,
++ .of_match_table = of_match_ptr(mchp_otpc_ids),
++ },
++};
++module_platform_driver(mchp_otpc_driver);
++
++MODULE_AUTHOR("Claudiu Beznea <claudiu.beznea@microchip.com>");
++MODULE_DESCRIPTION("Microchip SAMA7G5 OTPC driver");
++MODULE_LICENSE("GPL");
--- /dev/null
+From f5c97da8037b18d1256a58459fa96ed68e50fb41 Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Wed, 6 Jul 2022 11:06:27 +0100
+Subject: [PATCH] nvmem: mtk-efuse: Simplify with
+ devm_platform_get_and_ioremap_resource()
+
+Convert platform_get_resource(), devm_ioremap_resource() to a single
+call to devm_platform_get_and_ioremap_resource(), as this is exactly
+what this function does.
+
+No functional changes.
+
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220706100627.6534-8-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/mtk-efuse.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/nvmem/mtk-efuse.c
++++ b/drivers/nvmem/mtk-efuse.c
+@@ -41,8 +41,7 @@ static int mtk_efuse_probe(struct platfo
+ if (!priv)
+ return -ENOMEM;
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- priv->base = devm_ioremap_resource(dev, res);
++ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
--- /dev/null
+From d5542923f200f95bddf524f36fd495f78aa28e3c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 16 Sep 2022 13:20:48 +0100
+Subject: [PATCH] nvmem: add driver handling U-Boot environment variables
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+U-Boot stores its setup as environment variables. It's a list of
+key-value pairs stored on flash device with a custom header.
+
+This commit adds an NVMEM driver that:
+1. Provides NVMEM access to environment vars binary data
+2. Extracts variables as NVMEM cells
+
+Current Linux's NVMEM sysfs API allows reading whole NVMEM data block.
+It can be used by user-space tools for reading U-Boot env vars block
+without the hassle of finding its location. Parsing will still need to
+be re-done there.
+
+Kernel-parsed NVMEM cells can be read however by Linux drivers. This may
+be useful for Ethernet drivers for reading device MAC address which is
+often stored as U-Boot env variable.
+
+Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ MAINTAINERS | 1 +
+ drivers/nvmem/Kconfig | 13 +++
+ drivers/nvmem/Makefile | 2 +
+ drivers/nvmem/u-boot-env.c | 218 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 234 insertions(+)
+ create mode 100644 drivers/nvmem/u-boot-env.c
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -344,4 +344,17 @@ config NVMEM_APPLE_EFUSES
+ This driver can also be built as a module. If so, the module will
+ be called nvmem-apple-efuses.
+
++config NVMEM_U_BOOT_ENV
++ tristate "U-Boot environment variables support"
++ depends on OF && MTD
++ select CRC32
++ help
++ U-Boot stores its setup as environment variables. This driver adds
++ support for verifying & exporting such data. It also exposes variables
++ as NVMEM cells so they can be referenced by other drivers.
++
++ Currently this drivers works only with env variables on top of MTD.
++
++ If compiled as module it will be called nvmem_u-boot-env.
++
+ endif
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -69,3 +69,5 @@ obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvme
+ nvmem-apple-efuses-y := apple-efuses.o
+ obj-$(CONFIG_MICROCHIP_OTPC) += nvmem-microchip-otpc.o
+ nvmem-microchip-otpc-y := microchip-otpc.o
++obj-$(CONFIG_NVMEM_U_BOOT_ENV) += nvmem_u-boot-env.o
++nvmem_u-boot-env-y := u-boot-env.o
+--- /dev/null
++++ b/drivers/nvmem/u-boot-env.c
+@@ -0,0 +1,218 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Copyright (C) 2022 Rafał Miłecki <rafal@milecki.pl>
++ */
++
++#include <linux/crc32.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/mtd/mtd.h>
++#include <linux/nvmem-consumer.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++enum u_boot_env_format {
++ U_BOOT_FORMAT_SINGLE,
++ U_BOOT_FORMAT_REDUNDANT,
++};
++
++struct u_boot_env {
++ struct device *dev;
++ enum u_boot_env_format format;
++
++ struct mtd_info *mtd;
++
++ /* Cells */
++ struct nvmem_cell_info *cells;
++ int ncells;
++};
++
++struct u_boot_env_image_single {
++ __le32 crc32;
++ uint8_t data[];
++} __packed;
++
++struct u_boot_env_image_redundant {
++ __le32 crc32;
++ u8 mark;
++ uint8_t data[];
++} __packed;
++
++static int u_boot_env_read(void *context, unsigned int offset, void *val,
++ size_t bytes)
++{
++ struct u_boot_env *priv = context;
++ struct device *dev = priv->dev;
++ size_t bytes_read;
++ int err;
++
++ err = mtd_read(priv->mtd, offset, bytes, &bytes_read, val);
++ if (err && !mtd_is_bitflip(err)) {
++ dev_err(dev, "Failed to read from mtd: %d\n", err);
++ return err;
++ }
++
++ if (bytes_read != bytes) {
++ dev_err(dev, "Failed to read %zu bytes\n", bytes);
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf,
++ size_t data_offset, size_t data_len)
++{
++ struct device *dev = priv->dev;
++ char *data = buf + data_offset;
++ char *var, *value, *eq;
++ int idx;
++
++ priv->ncells = 0;
++ for (var = data; var < data + 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, idx = 0;
++ var < data + 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 = data_offset + value - data;
++ priv->cells[idx].bytes = strlen(value);
++ }
++
++ if (WARN_ON(idx != priv->ncells))
++ priv->ncells = idx;
++
++ return 0;
++}
++
++static int u_boot_env_parse(struct u_boot_env *priv)
++{
++ struct device *dev = priv->dev;
++ size_t crc32_data_offset;
++ size_t crc32_data_len;
++ size_t crc32_offset;
++ size_t data_offset;
++ size_t data_len;
++ uint32_t crc32;
++ uint32_t calc;
++ size_t bytes;
++ uint8_t *buf;
++ int err;
++
++ buf = kcalloc(1, priv->mtd->size, GFP_KERNEL);
++ if (!buf) {
++ err = -ENOMEM;
++ goto err_out;
++ }
++
++ err = mtd_read(priv->mtd, 0, priv->mtd->size, &bytes, buf);
++ if ((err && !mtd_is_bitflip(err)) || bytes != priv->mtd->size) {
++ dev_err(dev, "Failed to read from mtd: %d\n", err);
++ goto err_kfree;
++ }
++
++ switch (priv->format) {
++ case U_BOOT_FORMAT_SINGLE:
++ crc32_offset = offsetof(struct u_boot_env_image_single, crc32);
++ crc32_data_offset = offsetof(struct u_boot_env_image_single, data);
++ data_offset = offsetof(struct u_boot_env_image_single, data);
++ break;
++ case U_BOOT_FORMAT_REDUNDANT:
++ crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32);
++ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, mark);
++ data_offset = offsetof(struct u_boot_env_image_redundant, data);
++ break;
++ }
++ crc32 = le32_to_cpu(*(uint32_t *)(buf + crc32_offset));
++ crc32_data_len = priv->mtd->size - crc32_data_offset;
++ data_len = priv->mtd->size - data_offset;
++
++ calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L;
++ if (calc != crc32) {
++ dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32);
++ err = -EINVAL;
++ goto err_kfree;
++ }
++
++ buf[priv->mtd->size - 1] = '\0';
++ err = u_boot_env_add_cells(priv, buf, data_offset, data_len);
++ if (err)
++ dev_err(dev, "Failed to add cells: %d\n", err);
++
++err_kfree:
++ kfree(buf);
++err_out:
++ return err;
++}
++
++static int u_boot_env_probe(struct platform_device *pdev)
++{
++ struct nvmem_config config = {
++ .name = "u-boot-env",
++ .reg_read = u_boot_env_read,
++ };
++ struct device *dev = &pdev->dev;
++ struct device_node *np = dev->of_node;
++ struct u_boot_env *priv;
++ int err;
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++ priv->dev = dev;
++
++ priv->format = (uintptr_t)of_device_get_match_data(dev);
++
++ priv->mtd = of_get_mtd_device_by_node(np);
++ if (IS_ERR(priv->mtd)) {
++ dev_err_probe(dev, PTR_ERR(priv->mtd), "Failed to get %pOF MTD\n", np);
++ return PTR_ERR(priv->mtd);
++ }
++
++ err = u_boot_env_parse(priv);
++ if (err)
++ return err;
++
++ config.dev = dev;
++ config.cells = priv->cells;
++ config.ncells = priv->ncells;
++ config.priv = priv;
++ config.size = priv->mtd->size;
++
++ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config));
++}
++
++static const struct of_device_id u_boot_env_of_match_table[] = {
++ { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, },
++ { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
++ { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
++ {},
++};
++
++static struct platform_driver u_boot_env_driver = {
++ .probe = u_boot_env_probe,
++ .driver = {
++ .name = "u_boot_env",
++ .of_match_table = u_boot_env_of_match_table,
++ },
++};
++module_platform_driver(u_boot_env_driver);
++
++MODULE_AUTHOR("Rafał Miłecki");
++MODULE_LICENSE("GPL");
++MODULE_DEVICE_TABLE(of, u_boot_env_of_match_table);
--- /dev/null
+From 5544e90c81261e82e02bbf7c6015a4b9c8c825ef Mon Sep 17 00:00:00 2001
+From: Gaosheng Cui <cuigaosheng1@huawei.com>
+Date: Fri, 16 Sep 2022 13:20:50 +0100
+Subject: [PATCH] nvmem: core: add error handling for dev_set_name
+
+The type of return value of dev_set_name is int, which may return
+wrong result, so we add error handling for it to reclaim memory
+of nvmem resource, and return early when an error occurs.
+
+Signed-off-by: Gaosheng Cui <cuigaosheng1@huawei.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-4-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -810,18 +810,24 @@ struct nvmem_device *nvmem_register(cons
+
+ switch (config->id) {
+ case NVMEM_DEVID_NONE:
+- dev_set_name(&nvmem->dev, "%s", config->name);
++ rval = dev_set_name(&nvmem->dev, "%s", config->name);
+ break;
+ case NVMEM_DEVID_AUTO:
+- dev_set_name(&nvmem->dev, "%s%d", config->name, nvmem->id);
++ rval = dev_set_name(&nvmem->dev, "%s%d", config->name, nvmem->id);
+ break;
+ default:
+- dev_set_name(&nvmem->dev, "%s%d",
++ rval = dev_set_name(&nvmem->dev, "%s%d",
+ config->name ? : "nvmem",
+ config->name ? config->id : nvmem->id);
+ break;
+ }
+
++ if (rval) {
++ ida_free(&nvmem_ida, nvmem->id);
++ kfree(nvmem);
++ return ERR_PTR(rval);
++ }
++
+ nvmem->read_only = device_property_present(config->dev, "read-only") ||
+ config->read_only || !nvmem->reg_write;
+
--- /dev/null
+From d3524bb5b9a0c567b853a0024526afe87dde01ed Mon Sep 17 00:00:00 2001
+From: Kenneth Lee <klee33@uw.edu>
+Date: Fri, 16 Sep 2022 13:20:52 +0100
+Subject: [PATCH] nvmem: brcm_nvram: Use kzalloc for allocating only one
+ element
+
+Use kzalloc(...) rather than kcalloc(1, ...) because the number of
+elements we are specifying in this case is 1, so kzalloc would
+accomplish the same thing and we can simplify.
+
+Signed-off-by: Kenneth Lee <klee33@uw.edu>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-6-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/brcm_nvram.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/brcm_nvram.c
++++ b/drivers/nvmem/brcm_nvram.c
+@@ -96,7 +96,7 @@ static int brcm_nvram_parse(struct brcm_
+
+ len = le32_to_cpu(header.len);
+
+- data = kcalloc(1, len, GFP_KERNEL);
++ data = kzalloc(len, GFP_KERNEL);
+ memcpy_fromio(data, priv->base, len);
+ data[len - 1] = '\0';
+
--- /dev/null
+From 28fc7c986f01fdcfd28af648be2597624cac0e27 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 16 Sep 2022 13:20:54 +0100
+Subject: [PATCH] nvmem: prefix all symbols with NVMEM_
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This unifies all NVMEM symbols. They follow one style now.
+
+Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-8-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/configs/multi_v7_defconfig | 6 +++---
+ arch/arm/configs/qcom_defconfig | 2 +-
+ arch/arm64/configs/defconfig | 10 +++++-----
+ arch/mips/configs/ci20_defconfig | 2 +-
+ drivers/cpufreq/Kconfig.arm | 2 +-
+ drivers/nvmem/Kconfig | 24 ++++++++++++------------
+ drivers/nvmem/Makefile | 24 ++++++++++++------------
+ drivers/soc/mediatek/Kconfig | 2 +-
+ drivers/thermal/qcom/Kconfig | 2 +-
+ 9 files changed, 37 insertions(+), 37 deletions(-)
+
+--- a/arch/arm/configs/multi_v7_defconfig
++++ b/arch/arm/configs/multi_v7_defconfig
+@@ -1125,10 +1125,10 @@ CONFIG_TI_PIPE3=y
+ CONFIG_TWL4030_USB=m
+ CONFIG_RAS=y
+ CONFIG_NVMEM_IMX_OCOTP=y
+-CONFIG_ROCKCHIP_EFUSE=m
++CONFIG_NVMEM_ROCKCHIP_EFUSE=m
+ CONFIG_NVMEM_SUNXI_SID=y
+ CONFIG_NVMEM_VF610_OCOTP=y
+-CONFIG_MESON_MX_EFUSE=m
++CONFIG_NVMEM_MESON_MX_EFUSE=m
+ CONFIG_NVMEM_RMEM=m
+ CONFIG_FSI=m
+ CONFIG_FSI_MASTER_GPIO=m
+--- a/arch/arm/configs/qcom_defconfig
++++ b/arch/arm/configs/qcom_defconfig
+@@ -274,7 +274,7 @@ CONFIG_PHY_QCOM_USB_HS=y
+ CONFIG_PHY_QCOM_USB_HSIC=y
+ CONFIG_PHY_QCOM_QMP=y
+ CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=y
+-CONFIG_QCOM_QFPROM=y
++CONFIG_NVMEM_QCOM_QFPROM=y
+ CONFIG_INTERCONNECT=y
+ CONFIG_INTERCONNECT_QCOM=y
+ CONFIG_INTERCONNECT_QCOM_MSM8974=m
+--- a/arch/arm64/configs/defconfig
++++ b/arch/arm64/configs/defconfig
+@@ -1135,11 +1135,11 @@ CONFIG_QCOM_L3_PMU=y
+ CONFIG_NVMEM_IMX_OCOTP=y
+ CONFIG_NVMEM_IMX_OCOTP_SCU=y
+ CONFIG_QCOM_QFPROM=y
+-CONFIG_MTK_EFUSE=y
+-CONFIG_ROCKCHIP_EFUSE=y
++CONFIG_NVMEM_MTK_EFUSE=y
++CONFIG_NVMEM_ROCKCHIP_EFUSE=y
+ CONFIG_NVMEM_SUNXI_SID=y
+-CONFIG_UNIPHIER_EFUSE=y
+-CONFIG_MESON_EFUSE=m
++CONFIG_NVMEM_UNIPHIER_EFUSE=y
++CONFIG_NVMEM_MESON_EFUSE=m
+ CONFIG_NVMEM_RMEM=m
+ CONFIG_FPGA=y
+ CONFIG_FPGA_MGR_STRATIX10_SOC=m
+--- a/arch/mips/configs/ci20_defconfig
++++ b/arch/mips/configs/ci20_defconfig
+@@ -137,7 +137,7 @@ CONFIG_MEMORY=y
+ CONFIG_JZ4780_NEMC=y
+ CONFIG_PWM=y
+ CONFIG_PWM_JZ4740=m
+-CONFIG_JZ4780_EFUSE=y
++CONFIG_NVMEM_JZ4780_EFUSE=y
+ CONFIG_JZ4770_PHY=y
+ CONFIG_EXT4_FS=y
+ # CONFIG_DNOTIFY is not set
+--- a/drivers/cpufreq/Kconfig.arm
++++ b/drivers/cpufreq/Kconfig.arm
+@@ -153,7 +153,7 @@ config ARM_OMAP2PLUS_CPUFREQ
+ config ARM_QCOM_CPUFREQ_NVMEM
+ tristate "Qualcomm nvmem based CPUFreq"
+ depends on ARCH_QCOM
+- depends on QCOM_QFPROM
++ depends on NVMEM_QCOM_QFPROM
+ depends on QCOM_SMEM
+ select PM_OPP
+ help
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -52,7 +52,7 @@ config NVMEM_IMX_OCOTP_SCU
+ This is a driver for the SCU On-Chip OTP Controller (OCOTP)
+ available on i.MX8 SoCs.
+
+-config JZ4780_EFUSE
++config NVMEM_JZ4780_EFUSE
+ tristate "JZ4780 EFUSE Memory Support"
+ depends on MACH_INGENIC || COMPILE_TEST
+ depends on HAS_IOMEM
+@@ -96,7 +96,7 @@ config NVMEM_MXS_OCOTP
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-mxs-ocotp.
+
+-config MTK_EFUSE
++config NVMEM_MTK_EFUSE
+ tristate "Mediatek SoCs EFUSE support"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ depends on HAS_IOMEM
+@@ -107,7 +107,7 @@ config MTK_EFUSE
+ This driver can also be built as a module. If so, the module
+ will be called efuse-mtk.
+
+-config MICROCHIP_OTPC
++config NVMEM_MICROCHIP_OTPC
+ tristate "Microchip OTPC support"
+ depends on ARCH_AT91 || COMPILE_TEST
+ help
+@@ -126,7 +126,7 @@ config NVMEM_NINTENDO_OTP
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-nintendo-otp.
+
+-config QCOM_QFPROM
++config NVMEM_QCOM_QFPROM
+ tristate "QCOM QFPROM Support"
+ depends on ARCH_QCOM || COMPILE_TEST
+ depends on HAS_IOMEM
+@@ -145,7 +145,7 @@ config NVMEM_SPMI_SDAM
+ Qualcomm Technologies, Inc. PMICs. It provides the clients
+ an interface to read/write to the SDAM module's shared memory.
+
+-config ROCKCHIP_EFUSE
++config NVMEM_ROCKCHIP_EFUSE
+ tristate "Rockchip eFuse Support"
+ depends on ARCH_ROCKCHIP || COMPILE_TEST
+ depends on HAS_IOMEM
+@@ -156,7 +156,7 @@ config ROCKCHIP_EFUSE
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_rockchip_efuse.
+
+-config ROCKCHIP_OTP
++config NVMEM_ROCKCHIP_OTP
+ tristate "Rockchip OTP controller support"
+ depends on ARCH_ROCKCHIP || COMPILE_TEST
+ depends on HAS_IOMEM
+@@ -199,7 +199,7 @@ config NVMEM_SUNXI_SID
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_sunxi_sid.
+
+-config UNIPHIER_EFUSE
++config NVMEM_UNIPHIER_EFUSE
+ tristate "UniPhier SoCs eFuse support"
+ depends on ARCH_UNIPHIER || COMPILE_TEST
+ depends on HAS_IOMEM
+@@ -221,7 +221,7 @@ config NVMEM_VF610_OCOTP
+ This driver can also be build as a module. If so, the module will
+ be called nvmem-vf610-ocotp.
+
+-config MESON_EFUSE
++config NVMEM_MESON_EFUSE
+ tristate "Amlogic Meson GX eFuse Support"
+ depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM
+ help
+@@ -231,7 +231,7 @@ config MESON_EFUSE
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_meson_efuse.
+
+-config MESON_MX_EFUSE
++config NVMEM_MESON_MX_EFUSE
+ tristate "Amlogic Meson6/Meson8/Meson8b eFuse Support"
+ depends on ARCH_MESON || COMPILE_TEST
+ help
+@@ -251,13 +251,13 @@ config NVMEM_SNVS_LPGPR
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-snvs-lpgpr.
+
+-config RAVE_SP_EEPROM
++config NVMEM_RAVE_SP_EEPROM
+ tristate "Rave SP EEPROM Support"
+ depends on RAVE_SP_CORE
+ help
+ Say y here to enable Rave SP EEPROM support.
+
+-config SC27XX_EFUSE
++config NVMEM_SC27XX_EFUSE
+ tristate "Spreadtrum SC27XX eFuse Support"
+ depends on MFD_SC27XX_PMIC || COMPILE_TEST
+ depends on HAS_IOMEM
+@@ -278,7 +278,7 @@ config NVMEM_ZYNQMP
+
+ If sure, say yes. If unsure, say no.
+
+-config SPRD_EFUSE
++config NVMEM_SPRD_EFUSE
+ tristate "Spreadtrum SoC eFuse Support"
+ depends on ARCH_SPRD || COMPILE_TEST
+ depends on HAS_IOMEM
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -15,7 +15,7 @@ obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-i
+ nvmem-imx-ocotp-y := imx-ocotp.o
+ obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvmem-imx-ocotp-scu.o
+ nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o
+-obj-$(CONFIG_JZ4780_EFUSE) += nvmem_jz4780_efuse.o
++obj-$(CONFIG_NVMEM_JZ4780_EFUSE) += nvmem_jz4780_efuse.o
+ nvmem_jz4780_efuse-y := jz4780-efuse.o
+ obj-$(CONFIG_NVMEM_LPC18XX_EEPROM) += nvmem_lpc18xx_eeprom.o
+ nvmem_lpc18xx_eeprom-y := lpc18xx_eeprom.o
+@@ -25,37 +25,37 @@ obj-$(CONFIG_NVMEM_MXS_OCOTP) += nvmem-m
+ nvmem-mxs-ocotp-y := mxs-ocotp.o
+ obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvmem-nintendo-otp.o
+ nvmem-nintendo-otp-y := nintendo-otp.o
+-obj-$(CONFIG_MTK_EFUSE) += nvmem_mtk-efuse.o
++obj-$(CONFIG_NVMEM_MTK_EFUSE) += nvmem_mtk-efuse.o
+ nvmem_mtk-efuse-y := mtk-efuse.o
+-obj-$(CONFIG_QCOM_QFPROM) += nvmem_qfprom.o
++obj-$(CONFIG_NVMEM_QCOM_QFPROM) += nvmem_qfprom.o
+ nvmem_qfprom-y := qfprom.o
+ obj-$(CONFIG_NVMEM_SPMI_SDAM) += nvmem_qcom-spmi-sdam.o
+ nvmem_qcom-spmi-sdam-y += qcom-spmi-sdam.o
+-obj-$(CONFIG_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o
++obj-$(CONFIG_NVMEM_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o
+ nvmem_rockchip_efuse-y := rockchip-efuse.o
+-obj-$(CONFIG_ROCKCHIP_OTP) += nvmem-rockchip-otp.o
++obj-$(CONFIG_NVMEM_ROCKCHIP_OTP) += nvmem-rockchip-otp.o
+ nvmem-rockchip-otp-y := rockchip-otp.o
+ obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o
+ nvmem_stm32_romem-y := stm32-romem.o
+ obj-$(CONFIG_NVMEM_STM32_ROMEM) += nvmem_stm32_romem.o
+ nvmem_sunxi_sid-y := sunxi_sid.o
+-obj-$(CONFIG_UNIPHIER_EFUSE) += nvmem-uniphier-efuse.o
++obj-$(CONFIG_NVMEM_UNIPHIER_EFUSE) += nvmem-uniphier-efuse.o
+ nvmem-uniphier-efuse-y := uniphier-efuse.o
+ obj-$(CONFIG_NVMEM_VF610_OCOTP) += nvmem-vf610-ocotp.o
+ nvmem-vf610-ocotp-y := vf610-ocotp.o
+-obj-$(CONFIG_MESON_EFUSE) += nvmem_meson_efuse.o
++obj-$(CONFIG_NVMEM_MESON_EFUSE) += nvmem_meson_efuse.o
+ nvmem_meson_efuse-y := meson-efuse.o
+-obj-$(CONFIG_MESON_MX_EFUSE) += nvmem_meson_mx_efuse.o
++obj-$(CONFIG_NVMEM_MESON_MX_EFUSE) += nvmem_meson_mx_efuse.o
+ nvmem_meson_mx_efuse-y := meson-mx-efuse.o
+ obj-$(CONFIG_NVMEM_SNVS_LPGPR) += nvmem_snvs_lpgpr.o
+ nvmem_snvs_lpgpr-y := snvs_lpgpr.o
+-obj-$(CONFIG_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
++obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
+ nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
+-obj-$(CONFIG_SC27XX_EFUSE) += nvmem-sc27xx-efuse.o
++obj-$(CONFIG_NVMEM_SC27XX_EFUSE) += nvmem-sc27xx-efuse.o
+ nvmem-sc27xx-efuse-y := sc27xx-efuse.o
+ obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynqmp_nvmem.o
+ nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o
+-obj-$(CONFIG_SPRD_EFUSE) += nvmem_sprd_efuse.o
++obj-$(CONFIG_NVMEM_SPRD_EFUSE) += nvmem_sprd_efuse.o
+ nvmem_sprd_efuse-y := sprd-efuse.o
+ obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o
+ nvmem-rmem-y := rmem.o
+@@ -67,7 +67,7 @@ obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvm
+ nvmem_sunplus_ocotp-y := sunplus-ocotp.o
+ obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
+ nvmem-apple-efuses-y := apple-efuses.o
+-obj-$(CONFIG_MICROCHIP_OTPC) += nvmem-microchip-otpc.o
++obj-$(CONFIG_NVMEM_MICROCHIP_OTPC) += nvmem-microchip-otpc.o
+ nvmem-microchip-otpc-y := microchip-otpc.o
+ obj-$(CONFIG_NVMEM_U_BOOT_ENV) += nvmem_u-boot-env.o
+ nvmem_u-boot-env-y := u-boot-env.o
+--- a/drivers/thermal/qcom/Kconfig
++++ b/drivers/thermal/qcom/Kconfig
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ config QCOM_TSENS
+ tristate "Qualcomm TSENS Temperature Alarm"
+- depends on QCOM_QFPROM
++ depends on NVMEM_QCOM_QFPROM
+ depends on ARCH_QCOM || COMPILE_TEST
+ help
+ This enables the thermal sysfs driver for the TSENS device. It shows
--- /dev/null
+From a06d9e5a63b7c2f622c908cd9600ce735e70f7c6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 16 Sep 2022 13:20:55 +0100
+Subject: [PATCH] nvmem: sort config symbols alphabetically
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+1. Match what most subsystems do
+2. Simplify maintenance a bit
+3. Reduce amount of conflicts for new drivers patches
+
+While at it unify indent level in Makefile.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-9-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/Kconfig | 300 +++++++++++++++++++++--------------------
+ drivers/nvmem/Makefile | 114 ++++++++--------
+ 2 files changed, 208 insertions(+), 206 deletions(-)
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -21,6 +21,40 @@ config NVMEM_SYSFS
+ This interface is mostly used by userspace applications to
+ read/write directly into nvmem.
+
++# Devices
++
++config NVMEM_APPLE_EFUSES
++ tristate "Apple eFuse support"
++ depends on ARCH_APPLE || COMPILE_TEST
++ default ARCH_APPLE
++ help
++ Say y here to enable support for reading eFuses on Apple SoCs
++ such as the M1. These are e.g. used to store factory programmed
++ calibration data required for the PCIe or the USB-C PHY.
++
++ This driver can also be built as a module. If so, the module will
++ be called nvmem-apple-efuses.
++
++config NVMEM_BCM_OCOTP
++ tristate "Broadcom On-Chip OTP Controller support"
++ depends on ARCH_BCM_IPROC || COMPILE_TEST
++ depends on HAS_IOMEM
++ default ARCH_BCM_IPROC
++ help
++ Say y here to enable read/write access to the Broadcom OTP
++ controller.
++
++ This driver can also be built as a module. If so, the module
++ will be called nvmem-bcm-ocotp.
++
++config NVMEM_BRCM_NVRAM
++ tristate "Broadcom's NVRAM support"
++ depends on ARCH_BCM_5301X || COMPILE_TEST
++ depends on HAS_IOMEM
++ help
++ This driver provides support for Broadcom's NVRAM that can be accessed
++ using I/O mapping.
++
+ config NVMEM_IMX_IIM
+ tristate "i.MX IC Identification Module support"
+ depends on ARCH_MXC || COMPILE_TEST
+@@ -64,6 +98,19 @@ config NVMEM_JZ4780_EFUSE
+ To compile this driver as a module, choose M here: the module
+ will be called nvmem_jz4780_efuse.
+
++config NVMEM_LAYERSCAPE_SFP
++ tristate "Layerscape SFP (Security Fuse Processor) support"
++ depends on ARCH_LAYERSCAPE || COMPILE_TEST
++ depends on HAS_IOMEM
++ select REGMAP_MMIO
++ help
++ This driver provides support to read the eFuses on Freescale
++ Layerscape SoC's. For example, the vendor provides a per part
++ unique ID there.
++
++ This driver can also be built as a module. If so, the module
++ will be called layerscape-sfp.
++
+ config NVMEM_LPC18XX_EEPROM
+ tristate "NXP LPC18XX EEPROM Memory Support"
+ depends on ARCH_LPC18XX || COMPILE_TEST
+@@ -84,17 +131,32 @@ config NVMEM_LPC18XX_OTP
+ To compile this driver as a module, choose M here: the module
+ will be called nvmem_lpc18xx_otp.
+
+-config NVMEM_MXS_OCOTP
+- tristate "Freescale MXS On-Chip OTP Memory Support"
+- depends on ARCH_MXS || COMPILE_TEST
+- depends on HAS_IOMEM
++config NVMEM_MESON_EFUSE
++ tristate "Amlogic Meson GX eFuse Support"
++ depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM
+ help
+- If you say Y here, you will get readonly access to the
+- One Time Programmable memory pages that are stored
+- on the Freescale i.MX23/i.MX28 processor.
++ This is a driver to retrieve specific values from the eFuse found on
++ the Amlogic Meson GX SoCs.
+
+ This driver can also be built as a module. If so, the module
+- will be called nvmem-mxs-ocotp.
++ will be called nvmem_meson_efuse.
++
++config NVMEM_MESON_MX_EFUSE
++ tristate "Amlogic Meson6/Meson8/Meson8b eFuse Support"
++ depends on ARCH_MESON || COMPILE_TEST
++ help
++ This is a driver to retrieve specific values from the eFuse found on
++ the Amlogic Meson6, Meson8 and Meson8b SoCs.
++
++ This driver can also be built as a module. If so, the module
++ will be called nvmem_meson_mx_efuse.
++
++config NVMEM_MICROCHIP_OTPC
++ tristate "Microchip OTPC support"
++ depends on ARCH_AT91 || COMPILE_TEST
++ help
++ This driver enable the OTP controller available on Microchip SAMA7G5
++ SoCs. It controlls the access to the OTP memory connected to it.
+
+ config NVMEM_MTK_EFUSE
+ tristate "Mediatek SoCs EFUSE support"
+@@ -107,12 +169,17 @@ config NVMEM_MTK_EFUSE
+ This driver can also be built as a module. If so, the module
+ will be called efuse-mtk.
+
+-config NVMEM_MICROCHIP_OTPC
+- tristate "Microchip OTPC support"
+- depends on ARCH_AT91 || COMPILE_TEST
++config NVMEM_MXS_OCOTP
++ tristate "Freescale MXS On-Chip OTP Memory Support"
++ depends on ARCH_MXS || COMPILE_TEST
++ depends on HAS_IOMEM
+ help
+- This driver enable the OTP controller available on Microchip SAMA7G5
+- SoCs. It controlls the access to the OTP memory connected to it.
++ If you say Y here, you will get readonly access to the
++ One Time Programmable memory pages that are stored
++ on the Freescale i.MX23/i.MX28 processor.
++
++ This driver can also be built as a module. If so, the module
++ will be called nvmem-mxs-ocotp.
+
+ config NVMEM_NINTENDO_OTP
+ tristate "Nintendo Wii and Wii U OTP Support"
+@@ -137,13 +204,21 @@ config NVMEM_QCOM_QFPROM
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_qfprom.
+
+-config NVMEM_SPMI_SDAM
+- tristate "SPMI SDAM Support"
+- depends on SPMI
++config NVMEM_RAVE_SP_EEPROM
++ tristate "Rave SP EEPROM Support"
++ depends on RAVE_SP_CORE
+ help
+- This driver supports the Shared Direct Access Memory Module on
+- Qualcomm Technologies, Inc. PMICs. It provides the clients
+- an interface to read/write to the SDAM module's shared memory.
++ Say y here to enable Rave SP EEPROM support.
++
++config NVMEM_RMEM
++ tristate "Reserved Memory Based Driver Support"
++ depends on HAS_IOMEM
++ help
++ This driver maps reserved memory into an nvmem device. It might be
++ useful to expose information left by firmware in memory.
++
++ This driver can also be built as a module. If so, the module
++ will be called nvmem-rmem.
+
+ config NVMEM_ROCKCHIP_EFUSE
+ tristate "Rockchip eFuse Support"
+@@ -167,79 +242,16 @@ config NVMEM_ROCKCHIP_OTP
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_rockchip_otp.
+
+-config NVMEM_BCM_OCOTP
+- tristate "Broadcom On-Chip OTP Controller support"
+- depends on ARCH_BCM_IPROC || COMPILE_TEST
+- depends on HAS_IOMEM
+- default ARCH_BCM_IPROC
+- help
+- Say y here to enable read/write access to the Broadcom OTP
+- controller.
+-
+- This driver can also be built as a module. If so, the module
+- will be called nvmem-bcm-ocotp.
+-
+-config NVMEM_STM32_ROMEM
+- tristate "STMicroelectronics STM32 factory-programmed memory support"
+- depends on ARCH_STM32 || COMPILE_TEST
+- help
+- Say y here to enable read-only access for STMicroelectronics STM32
+- factory-programmed memory area.
+-
+- This driver can also be built as a module. If so, the module
+- will be called nvmem-stm32-romem.
+-
+-config NVMEM_SUNXI_SID
+- tristate "Allwinner SoCs SID support"
+- depends on ARCH_SUNXI
+- help
+- This is a driver for the 'security ID' available on various Allwinner
+- devices.
+-
+- This driver can also be built as a module. If so, the module
+- will be called nvmem_sunxi_sid.
+-
+-config NVMEM_UNIPHIER_EFUSE
+- tristate "UniPhier SoCs eFuse support"
+- depends on ARCH_UNIPHIER || COMPILE_TEST
+- depends on HAS_IOMEM
+- help
+- This is a simple driver to dump specified values of UniPhier SoC
+- from eFuse.
+-
+- This driver can also be built as a module. If so, the module
+- will be called nvmem-uniphier-efuse.
+-
+-config NVMEM_VF610_OCOTP
+- tristate "VF610 SoC OCOTP support"
+- depends on SOC_VF610 || COMPILE_TEST
++config NVMEM_SC27XX_EFUSE
++ tristate "Spreadtrum SC27XX eFuse Support"
++ depends on MFD_SC27XX_PMIC || COMPILE_TEST
+ depends on HAS_IOMEM
+ help
+- This is a driver for the 'OCOTP' peripheral available on Vybrid
+- devices like VF5xx and VF6xx.
+-
+- This driver can also be build as a module. If so, the module will
+- be called nvmem-vf610-ocotp.
+-
+-config NVMEM_MESON_EFUSE
+- tristate "Amlogic Meson GX eFuse Support"
+- depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM
+- help
+- This is a driver to retrieve specific values from the eFuse found on
+- the Amlogic Meson GX SoCs.
+-
+- This driver can also be built as a module. If so, the module
+- will be called nvmem_meson_efuse.
+-
+-config NVMEM_MESON_MX_EFUSE
+- tristate "Amlogic Meson6/Meson8/Meson8b eFuse Support"
+- depends on ARCH_MESON || COMPILE_TEST
+- help
+- This is a driver to retrieve specific values from the eFuse found on
+- the Amlogic Meson6, Meson8 and Meson8b SoCs.
++ This is a simple driver to dump specified values of Spreadtrum
++ SC27XX PMICs from eFuse.
+
+ This driver can also be built as a module. If so, the module
+- will be called nvmem_meson_mx_efuse.
++ will be called nvmem-sc27xx-efuse.
+
+ config NVMEM_SNVS_LPGPR
+ tristate "Support for Low Power General Purpose Register"
+@@ -251,32 +263,13 @@ config NVMEM_SNVS_LPGPR
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-snvs-lpgpr.
+
+-config NVMEM_RAVE_SP_EEPROM
+- tristate "Rave SP EEPROM Support"
+- depends on RAVE_SP_CORE
+- help
+- Say y here to enable Rave SP EEPROM support.
+-
+-config NVMEM_SC27XX_EFUSE
+- tristate "Spreadtrum SC27XX eFuse Support"
+- depends on MFD_SC27XX_PMIC || COMPILE_TEST
+- depends on HAS_IOMEM
+- help
+- This is a simple driver to dump specified values of Spreadtrum
+- SC27XX PMICs from eFuse.
+-
+- This driver can also be built as a module. If so, the module
+- will be called nvmem-sc27xx-efuse.
+-
+-config NVMEM_ZYNQMP
+- bool "Xilinx ZYNQMP SoC nvmem firmware support"
+- depends on ARCH_ZYNQMP
++config NVMEM_SPMI_SDAM
++ tristate "SPMI SDAM Support"
++ depends on SPMI
+ help
+- This is a driver to access hardware related data like
+- soc revision, IDCODE... etc by using the firmware
+- interface.
+-
+- If sure, say yes. If unsure, say no.
++ This driver supports the Shared Direct Access Memory Module on
++ Qualcomm Technologies, Inc. PMICs. It provides the clients
++ an interface to read/write to the SDAM module's shared memory.
+
+ config NVMEM_SPRD_EFUSE
+ tristate "Spreadtrum SoC eFuse Support"
+@@ -289,36 +282,15 @@ config NVMEM_SPRD_EFUSE
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-sprd-efuse.
+
+-config NVMEM_RMEM
+- tristate "Reserved Memory Based Driver Support"
+- depends on HAS_IOMEM
+- help
+- This driver maps reserved memory into an nvmem device. It might be
+- useful to expose information left by firmware in memory.
+-
+- This driver can also be built as a module. If so, the module
+- will be called nvmem-rmem.
+-
+-config NVMEM_BRCM_NVRAM
+- tristate "Broadcom's NVRAM support"
+- depends on ARCH_BCM_5301X || COMPILE_TEST
+- depends on HAS_IOMEM
+- help
+- This driver provides support for Broadcom's NVRAM that can be accessed
+- using I/O mapping.
+-
+-config NVMEM_LAYERSCAPE_SFP
+- tristate "Layerscape SFP (Security Fuse Processor) support"
+- depends on ARCH_LAYERSCAPE || COMPILE_TEST
+- depends on HAS_IOMEM
+- select REGMAP_MMIO
++config NVMEM_STM32_ROMEM
++ tristate "STMicroelectronics STM32 factory-programmed memory support"
++ depends on ARCH_STM32 || COMPILE_TEST
+ help
+- This driver provides support to read the eFuses on Freescale
+- Layerscape SoC's. For example, the vendor provides a per part
+- unique ID there.
++ Say y here to enable read-only access for STMicroelectronics STM32
++ factory-programmed memory area.
+
+ This driver can also be built as a module. If so, the module
+- will be called layerscape-sfp.
++ will be called nvmem-stm32-romem.
+
+ config NVMEM_SUNPLUS_OCOTP
+ tristate "Sunplus SoC OTP support"
+@@ -332,17 +304,15 @@ config NVMEM_SUNPLUS_OCOTP
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-sunplus-ocotp.
+
+-config NVMEM_APPLE_EFUSES
+- tristate "Apple eFuse support"
+- depends on ARCH_APPLE || COMPILE_TEST
+- default ARCH_APPLE
++config NVMEM_SUNXI_SID
++ tristate "Allwinner SoCs SID support"
++ depends on ARCH_SUNXI
+ help
+- Say y here to enable support for reading eFuses on Apple SoCs
+- such as the M1. These are e.g. used to store factory programmed
+- calibration data required for the PCIe or the USB-C PHY.
++ This is a driver for the 'security ID' available on various Allwinner
++ devices.
+
+- This driver can also be built as a module. If so, the module will
+- be called nvmem-apple-efuses.
++ This driver can also be built as a module. If so, the module
++ will be called nvmem_sunxi_sid.
+
+ config NVMEM_U_BOOT_ENV
+ tristate "U-Boot environment variables support"
+@@ -357,4 +327,36 @@ config NVMEM_U_BOOT_ENV
+
+ If compiled as module it will be called nvmem_u-boot-env.
+
++config NVMEM_UNIPHIER_EFUSE
++ tristate "UniPhier SoCs eFuse support"
++ depends on ARCH_UNIPHIER || COMPILE_TEST
++ depends on HAS_IOMEM
++ help
++ This is a simple driver to dump specified values of UniPhier SoC
++ from eFuse.
++
++ This driver can also be built as a module. If so, the module
++ will be called nvmem-uniphier-efuse.
++
++config NVMEM_VF610_OCOTP
++ tristate "VF610 SoC OCOTP support"
++ depends on SOC_VF610 || COMPILE_TEST
++ depends on HAS_IOMEM
++ help
++ This is a driver for the 'OCOTP' peripheral available on Vybrid
++ devices like VF5xx and VF6xx.
++
++ This driver can also be build as a module. If so, the module will
++ be called nvmem-vf610-ocotp.
++
++config NVMEM_ZYNQMP
++ bool "Xilinx ZYNQMP SoC nvmem firmware support"
++ depends on ARCH_ZYNQMP
++ help
++ This is a driver to access hardware related data like
++ soc revision, IDCODE... etc by using the firmware
++ interface.
++
++ If sure, say yes. If unsure, say no.
++
+ endif
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -7,67 +7,67 @@ obj-$(CONFIG_NVMEM) += nvmem_core.o
+ nvmem_core-y := core.o
+
+ # Devices
+-obj-$(CONFIG_NVMEM_BCM_OCOTP) += nvmem-bcm-ocotp.o
+-nvmem-bcm-ocotp-y := bcm-ocotp.o
+-obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-imx-iim.o
+-nvmem-imx-iim-y := imx-iim.o
+-obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-imx-ocotp.o
+-nvmem-imx-ocotp-y := imx-ocotp.o
++obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
++nvmem-apple-efuses-y := apple-efuses.o
++obj-$(CONFIG_NVMEM_BCM_OCOTP) += nvmem-bcm-ocotp.o
++nvmem-bcm-ocotp-y := bcm-ocotp.o
++obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_brcm_nvram.o
++nvmem_brcm_nvram-y := brcm_nvram.o
++obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-imx-iim.o
++nvmem-imx-iim-y := imx-iim.o
++obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-imx-ocotp.o
++nvmem-imx-ocotp-y := imx-ocotp.o
+ obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvmem-imx-ocotp-scu.o
+-nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o
+-obj-$(CONFIG_NVMEM_JZ4780_EFUSE) += nvmem_jz4780_efuse.o
+-nvmem_jz4780_efuse-y := jz4780-efuse.o
++nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o
++obj-$(CONFIG_NVMEM_JZ4780_EFUSE) += nvmem_jz4780_efuse.o
++nvmem_jz4780_efuse-y := jz4780-efuse.o
++obj-$(CONFIG_NVMEM_LAYERSCAPE_SFP) += nvmem-layerscape-sfp.o
++nvmem-layerscape-sfp-y := layerscape-sfp.o
+ obj-$(CONFIG_NVMEM_LPC18XX_EEPROM) += nvmem_lpc18xx_eeprom.o
+-nvmem_lpc18xx_eeprom-y := lpc18xx_eeprom.o
+-obj-$(CONFIG_NVMEM_LPC18XX_OTP) += nvmem_lpc18xx_otp.o
+-nvmem_lpc18xx_otp-y := lpc18xx_otp.o
+-obj-$(CONFIG_NVMEM_MXS_OCOTP) += nvmem-mxs-ocotp.o
+-nvmem-mxs-ocotp-y := mxs-ocotp.o
+-obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvmem-nintendo-otp.o
+-nvmem-nintendo-otp-y := nintendo-otp.o
++nvmem_lpc18xx_eeprom-y := lpc18xx_eeprom.o
++obj-$(CONFIG_NVMEM_LPC18XX_OTP) += nvmem_lpc18xx_otp.o
++nvmem_lpc18xx_otp-y := lpc18xx_otp.o
++obj-$(CONFIG_NVMEM_MESON_EFUSE) += nvmem_meson_efuse.o
++nvmem_meson_efuse-y := meson-efuse.o
++obj-$(CONFIG_NVMEM_MESON_MX_EFUSE) += nvmem_meson_mx_efuse.o
++nvmem_meson_mx_efuse-y := meson-mx-efuse.o
++obj-$(CONFIG_NVMEM_MICROCHIP_OTPC) += nvmem-microchip-otpc.o
++nvmem-microchip-otpc-y := microchip-otpc.o
+ obj-$(CONFIG_NVMEM_MTK_EFUSE) += nvmem_mtk-efuse.o
+-nvmem_mtk-efuse-y := mtk-efuse.o
+-obj-$(CONFIG_NVMEM_QCOM_QFPROM) += nvmem_qfprom.o
+-nvmem_qfprom-y := qfprom.o
+-obj-$(CONFIG_NVMEM_SPMI_SDAM) += nvmem_qcom-spmi-sdam.o
+-nvmem_qcom-spmi-sdam-y += qcom-spmi-sdam.o
++nvmem_mtk-efuse-y := mtk-efuse.o
++obj-$(CONFIG_NVMEM_MXS_OCOTP) += nvmem-mxs-ocotp.o
++nvmem-mxs-ocotp-y := mxs-ocotp.o
++obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvmem-nintendo-otp.o
++nvmem-nintendo-otp-y := nintendo-otp.o
++obj-$(CONFIG_NVMEM_QCOM_QFPROM) += nvmem_qfprom.o
++nvmem_qfprom-y := qfprom.o
++obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
++nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
++obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o
++nvmem-rmem-y := rmem.o
+ obj-$(CONFIG_NVMEM_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o
+-nvmem_rockchip_efuse-y := rockchip-efuse.o
++nvmem_rockchip_efuse-y := rockchip-efuse.o
+ obj-$(CONFIG_NVMEM_ROCKCHIP_OTP) += nvmem-rockchip-otp.o
+-nvmem-rockchip-otp-y := rockchip-otp.o
+-obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o
+-nvmem_stm32_romem-y := stm32-romem.o
+-obj-$(CONFIG_NVMEM_STM32_ROMEM) += nvmem_stm32_romem.o
+-nvmem_sunxi_sid-y := sunxi_sid.o
+-obj-$(CONFIG_NVMEM_UNIPHIER_EFUSE) += nvmem-uniphier-efuse.o
+-nvmem-uniphier-efuse-y := uniphier-efuse.o
+-obj-$(CONFIG_NVMEM_VF610_OCOTP) += nvmem-vf610-ocotp.o
+-nvmem-vf610-ocotp-y := vf610-ocotp.o
+-obj-$(CONFIG_NVMEM_MESON_EFUSE) += nvmem_meson_efuse.o
+-nvmem_meson_efuse-y := meson-efuse.o
+-obj-$(CONFIG_NVMEM_MESON_MX_EFUSE) += nvmem_meson_mx_efuse.o
+-nvmem_meson_mx_efuse-y := meson-mx-efuse.o
+-obj-$(CONFIG_NVMEM_SNVS_LPGPR) += nvmem_snvs_lpgpr.o
+-nvmem_snvs_lpgpr-y := snvs_lpgpr.o
+-obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
+-nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
++nvmem-rockchip-otp-y := rockchip-otp.o
+ obj-$(CONFIG_NVMEM_SC27XX_EFUSE) += nvmem-sc27xx-efuse.o
+-nvmem-sc27xx-efuse-y := sc27xx-efuse.o
+-obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynqmp_nvmem.o
+-nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o
+-obj-$(CONFIG_NVMEM_SPRD_EFUSE) += nvmem_sprd_efuse.o
+-nvmem_sprd_efuse-y := sprd-efuse.o
+-obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o
+-nvmem-rmem-y := rmem.o
+-obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_brcm_nvram.o
+-nvmem_brcm_nvram-y := brcm_nvram.o
+-obj-$(CONFIG_NVMEM_LAYERSCAPE_SFP) += nvmem-layerscape-sfp.o
+-nvmem-layerscape-sfp-y := layerscape-sfp.o
++nvmem-sc27xx-efuse-y := sc27xx-efuse.o
++obj-$(CONFIG_NVMEM_SNVS_LPGPR) += nvmem_snvs_lpgpr.o
++nvmem_snvs_lpgpr-y := snvs_lpgpr.o
++obj-$(CONFIG_NVMEM_SPMI_SDAM) += nvmem_qcom-spmi-sdam.o
++nvmem_qcom-spmi-sdam-y += qcom-spmi-sdam.o
++obj-$(CONFIG_NVMEM_SPRD_EFUSE) += nvmem_sprd_efuse.o
++nvmem_sprd_efuse-y := sprd-efuse.o
++obj-$(CONFIG_NVMEM_STM32_ROMEM) += nvmem_stm32_romem.o
++nvmem_stm32_romem-y := stm32-romem.o
+ obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvmem_sunplus_ocotp.o
+-nvmem_sunplus_ocotp-y := sunplus-ocotp.o
+-obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
+-nvmem-apple-efuses-y := apple-efuses.o
+-obj-$(CONFIG_NVMEM_MICROCHIP_OTPC) += nvmem-microchip-otpc.o
+-nvmem-microchip-otpc-y := microchip-otpc.o
+-obj-$(CONFIG_NVMEM_U_BOOT_ENV) += nvmem_u-boot-env.o
+-nvmem_u-boot-env-y := u-boot-env.o
++nvmem_sunplus_ocotp-y := sunplus-ocotp.o
++obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o
++nvmem_sunxi_sid-y := sunxi_sid.o
++obj-$(CONFIG_NVMEM_U_BOOT_ENV) += nvmem_u-boot-env.o
++nvmem_u-boot-env-y := u-boot-env.o
++obj-$(CONFIG_NVMEM_UNIPHIER_EFUSE) += nvmem-uniphier-efuse.o
++nvmem-uniphier-efuse-y := uniphier-efuse.o
++obj-$(CONFIG_NVMEM_VF610_OCOTP) += nvmem-vf610-ocotp.o
++nvmem-vf610-ocotp-y := vf610-ocotp.o
++obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynqmp_nvmem.o
++nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o
--- /dev/null
+From d4d432670f7dee0a5432fcffcfc8699b25181ace Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 16 Sep 2022 13:20:57 +0100
+Subject: [PATCH] nvmem: u-boot-env: find Device Tree nodes for NVMEM cells
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+DT binding allows specifying NVMEM cells as NVMEM device (provider)
+subnodes. Looks for such subnodes when building NVMEM cells.
+
+This allows NVMEM consumers to use U-Boot environment variables.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-11-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/u-boot-env.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/nvmem/u-boot-env.c
++++ b/drivers/nvmem/u-boot-env.c
+@@ -92,6 +92,7 @@ static int u_boot_env_add_cells(struct u
+ return -ENOMEM;
+ priv->cells[idx].offset = data_offset + value - data;
+ priv->cells[idx].bytes = strlen(value);
++ priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
+ }
+
+ if (WARN_ON(idx != priv->ncells))
--- /dev/null
+From 9e8f208ad5229ddda97cd4a83ecf89c735d99592 Mon Sep 17 00:00:00 2001
+From: Horatiu Vultur <horatiu.vultur@microchip.com>
+Date: Fri, 16 Sep 2022 13:20:59 +0100
+Subject: [PATCH] nvmem: lan9662-otp: add support
+
+Add support for OTP controller available on LAN9662. The OTPC controls
+the access to a non-volatile memory. The size of the memory is 8KB.
+The OTPC can access the memory based on an offset.
+Implement both the read and the write functionality.
+
+Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-13-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/Kconfig | 8 ++
+ drivers/nvmem/Makefile | 2 +
+ drivers/nvmem/lan9662-otpc.c | 222 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 232 insertions(+)
+ create mode 100644 drivers/nvmem/lan9662-otpc.c
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -98,6 +98,14 @@ config NVMEM_JZ4780_EFUSE
+ To compile this driver as a module, choose M here: the module
+ will be called nvmem_jz4780_efuse.
+
++config NVMEM_LAN9662_OTPC
++ tristate "Microchip LAN9662 OTP controller support"
++ depends on SOC_LAN966 || COMPILE_TEST
++ depends on HAS_IOMEM
++ help
++ This driver enables the OTP controller available on Microchip LAN9662
++ SoCs. It controls the access to the OTP memory connected to it.
++
+ config NVMEM_LAYERSCAPE_SFP
+ tristate "Layerscape SFP (Security Fuse Processor) support"
+ depends on ARCH_LAYERSCAPE || COMPILE_TEST
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -21,6 +21,8 @@ obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvm
+ nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o
+ obj-$(CONFIG_NVMEM_JZ4780_EFUSE) += nvmem_jz4780_efuse.o
+ nvmem_jz4780_efuse-y := jz4780-efuse.o
++obj-$(CONFIG_NVMEM_LAN9662_OTPC) += nvmem-lan9662-otpc.o
++nvmem-lan9662-otpc-y := lan9662-otpc.o
+ obj-$(CONFIG_NVMEM_LAYERSCAPE_SFP) += nvmem-layerscape-sfp.o
+ nvmem-layerscape-sfp-y := layerscape-sfp.o
+ obj-$(CONFIG_NVMEM_LPC18XX_EEPROM) += nvmem_lpc18xx_eeprom.o
+--- /dev/null
++++ b/drivers/nvmem/lan9662-otpc.c
+@@ -0,0 +1,222 @@
++// SPDX-License-Identifier: GPL-2.0
++
++#include <linux/iopoll.h>
++#include <linux/module.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++
++#define OTP_OTP_PWR_DN(t) (t + 0x00)
++#define OTP_OTP_PWR_DN_OTP_PWRDN_N BIT(0)
++#define OTP_OTP_ADDR_HI(t) (t + 0x04)
++#define OTP_OTP_ADDR_LO(t) (t + 0x08)
++#define OTP_OTP_PRGM_DATA(t) (t + 0x10)
++#define OTP_OTP_PRGM_MODE(t) (t + 0x14)
++#define OTP_OTP_PRGM_MODE_OTP_PGM_MODE_BYTE BIT(0)
++#define OTP_OTP_RD_DATA(t) (t + 0x18)
++#define OTP_OTP_FUNC_CMD(t) (t + 0x20)
++#define OTP_OTP_FUNC_CMD_OTP_PROGRAM BIT(1)
++#define OTP_OTP_FUNC_CMD_OTP_READ BIT(0)
++#define OTP_OTP_CMD_GO(t) (t + 0x28)
++#define OTP_OTP_CMD_GO_OTP_GO BIT(0)
++#define OTP_OTP_PASS_FAIL(t) (t + 0x2c)
++#define OTP_OTP_PASS_FAIL_OTP_READ_PROHIBITED BIT(3)
++#define OTP_OTP_PASS_FAIL_OTP_WRITE_PROHIBITED BIT(2)
++#define OTP_OTP_PASS_FAIL_OTP_FAIL BIT(0)
++#define OTP_OTP_STATUS(t) (t + 0x30)
++#define OTP_OTP_STATUS_OTP_CPUMPEN BIT(1)
++#define OTP_OTP_STATUS_OTP_BUSY BIT(0)
++
++#define OTP_MEM_SIZE 8192
++#define OTP_SLEEP_US 10
++#define OTP_TIMEOUT_US 500000
++
++struct lan9662_otp {
++ struct device *dev;
++ void __iomem *base;
++};
++
++static bool lan9662_otp_wait_flag_clear(void __iomem *reg, u32 flag)
++{
++ u32 val;
++
++ return readl_poll_timeout(reg, val, !(val & flag),
++ OTP_SLEEP_US, OTP_TIMEOUT_US);
++}
++
++static int lan9662_otp_power(struct lan9662_otp *otp, bool up)
++{
++ void __iomem *pwrdn = OTP_OTP_PWR_DN(otp->base);
++
++ if (up) {
++ writel(readl(pwrdn) & ~OTP_OTP_PWR_DN_OTP_PWRDN_N, pwrdn);
++ if (lan9662_otp_wait_flag_clear(OTP_OTP_STATUS(otp->base),
++ OTP_OTP_STATUS_OTP_CPUMPEN))
++ return -ETIMEDOUT;
++ } else {
++ writel(readl(pwrdn) | OTP_OTP_PWR_DN_OTP_PWRDN_N, pwrdn);
++ }
++
++ return 0;
++}
++
++static int lan9662_otp_execute(struct lan9662_otp *otp)
++{
++ if (lan9662_otp_wait_flag_clear(OTP_OTP_CMD_GO(otp->base),
++ OTP_OTP_CMD_GO_OTP_GO))
++ return -ETIMEDOUT;
++
++ if (lan9662_otp_wait_flag_clear(OTP_OTP_STATUS(otp->base),
++ OTP_OTP_STATUS_OTP_BUSY))
++ return -ETIMEDOUT;
++
++ return 0;
++}
++
++static void lan9662_otp_set_address(struct lan9662_otp *otp, u32 offset)
++{
++ writel(0xff & (offset >> 8), OTP_OTP_ADDR_HI(otp->base));
++ writel(0xff & offset, OTP_OTP_ADDR_LO(otp->base));
++}
++
++static int lan9662_otp_read_byte(struct lan9662_otp *otp, u32 offset, u8 *dst)
++{
++ u32 pass;
++ int rc;
++
++ lan9662_otp_set_address(otp, offset);
++ writel(OTP_OTP_FUNC_CMD_OTP_READ, OTP_OTP_FUNC_CMD(otp->base));
++ writel(OTP_OTP_CMD_GO_OTP_GO, OTP_OTP_CMD_GO(otp->base));
++ rc = lan9662_otp_execute(otp);
++ if (!rc) {
++ pass = readl(OTP_OTP_PASS_FAIL(otp->base));
++ if (pass & OTP_OTP_PASS_FAIL_OTP_READ_PROHIBITED)
++ return -EACCES;
++ *dst = (u8) readl(OTP_OTP_RD_DATA(otp->base));
++ }
++ return rc;
++}
++
++static int lan9662_otp_write_byte(struct lan9662_otp *otp, u32 offset, u8 data)
++{
++ u32 pass;
++ int rc;
++
++ lan9662_otp_set_address(otp, offset);
++ writel(OTP_OTP_PRGM_MODE_OTP_PGM_MODE_BYTE, OTP_OTP_PRGM_MODE(otp->base));
++ writel(data, OTP_OTP_PRGM_DATA(otp->base));
++ writel(OTP_OTP_FUNC_CMD_OTP_PROGRAM, OTP_OTP_FUNC_CMD(otp->base));
++ writel(OTP_OTP_CMD_GO_OTP_GO, OTP_OTP_CMD_GO(otp->base));
++
++ rc = lan9662_otp_execute(otp);
++ if (!rc) {
++ pass = readl(OTP_OTP_PASS_FAIL(otp->base));
++ if (pass & OTP_OTP_PASS_FAIL_OTP_WRITE_PROHIBITED)
++ return -EACCES;
++ if (pass & OTP_OTP_PASS_FAIL_OTP_FAIL)
++ return -EIO;
++ }
++ return rc;
++}
++
++static int lan9662_otp_read(void *context, unsigned int offset,
++ void *_val, size_t bytes)
++{
++ struct lan9662_otp *otp = context;
++ u8 *val = _val;
++ uint8_t data;
++ int i, rc = 0;
++
++ lan9662_otp_power(otp, true);
++ for (i = 0; i < bytes; i++) {
++ rc = lan9662_otp_read_byte(otp, offset + i, &data);
++ if (rc < 0)
++ break;
++ *val++ = data;
++ }
++ lan9662_otp_power(otp, false);
++
++ return rc;
++}
++
++static int lan9662_otp_write(void *context, unsigned int offset,
++ void *_val, size_t bytes)
++{
++ struct lan9662_otp *otp = context;
++ u8 *val = _val;
++ u8 data, newdata;
++ int i, rc = 0;
++
++ lan9662_otp_power(otp, true);
++ for (i = 0; i < bytes; i++) {
++ /* Skip zero bytes */
++ if (val[i]) {
++ rc = lan9662_otp_read_byte(otp, offset + i, &data);
++ if (rc < 0)
++ break;
++
++ newdata = data | val[i];
++ if (newdata == data)
++ continue;
++
++ rc = lan9662_otp_write_byte(otp, offset + i,
++ newdata);
++ if (rc < 0)
++ break;
++ }
++ }
++ lan9662_otp_power(otp, false);
++
++ return rc;
++}
++
++static struct nvmem_config otp_config = {
++ .name = "lan9662-otp",
++ .stride = 1,
++ .word_size = 1,
++ .reg_read = lan9662_otp_read,
++ .reg_write = lan9662_otp_write,
++ .size = OTP_MEM_SIZE,
++};
++
++static int lan9662_otp_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct nvmem_device *nvmem;
++ struct lan9662_otp *otp;
++
++ otp = devm_kzalloc(&pdev->dev, sizeof(*otp), GFP_KERNEL);
++ if (!otp)
++ return -ENOMEM;
++
++ otp->dev = dev;
++ otp->base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(otp->base))
++ return PTR_ERR(otp->base);
++
++ otp_config.priv = otp;
++ otp_config.dev = dev;
++
++ nvmem = devm_nvmem_register(dev, &otp_config);
++
++ return PTR_ERR_OR_ZERO(nvmem);
++}
++
++static const struct of_device_id lan9662_otp_match[] = {
++ { .compatible = "microchip,lan9662-otp", },
++ { },
++};
++MODULE_DEVICE_TABLE(of, lan9662_otp_match);
++
++static struct platform_driver lan9662_otp_driver = {
++ .probe = lan9662_otp_probe,
++ .driver = {
++ .name = "lan9662-otp",
++ .of_match_table = lan9662_otp_match,
++ },
++};
++module_platform_driver(lan9662_otp_driver);
++
++MODULE_AUTHOR("Horatiu Vultur <horatiu.vultur@microchip.com>");
++MODULE_DESCRIPTION("lan9662 OTP driver");
++MODULE_LICENSE("GPL");
--- /dev/null
+From 3717ca3e0cc8683f93b41d3f06ca79631eb58715 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 16 Sep 2022 13:21:00 +0100
+Subject: [PATCH] nvmem: u-boot-env: fix crc32 casting type
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This fixes:
+drivers/nvmem/u-boot-env.c:141:17: sparse: sparse: cast to restricted __le32
+
+Fixes: d5542923f200 ("nvmem: add driver handling U-Boot environment variables")
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20220916122100.170016-14-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/u-boot-env.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/u-boot-env.c
++++ b/drivers/nvmem/u-boot-env.c
+@@ -139,7 +139,7 @@ static int u_boot_env_parse(struct u_boo
+ data_offset = offsetof(struct u_boot_env_image_redundant, data);
+ break;
+ }
+- crc32 = le32_to_cpu(*(uint32_t *)(buf + crc32_offset));
++ crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset));
+ crc32_data_len = priv->mtd->size - crc32_data_offset;
+ data_len = priv->mtd->size - data_offset;
+
--- /dev/null
+From 1aeb122d214b92474c86fde00a03d6e2d69381b5 Mon Sep 17 00:00:00 2001
+From: Horatiu Vultur <horatiu.vultur@microchip.com>
+Date: Wed, 28 Sep 2022 21:51:12 +0200
+Subject: [PATCH] nvmem: lan9662-otp: Fix compatible string
+
+The device tree bindings for lan9662-otp expects the compatible string
+to be one of following compatible strings:
+microchip,lan9662-otpc
+microchip,lan9668-otpc
+
+The problem is that the lan9662-otp driver contains the
+microchip,lan9662-otp compatible string instead of
+microchip,lan9662-otpc.
+Fix this by updating the compatible string in the driver.
+
+Fixes: 9e8f208ad5229d ("nvmem: lan9662-otp: add support")
+Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
+Link: https://lore.kernel.org/r/20220928195112.630351-1-horatiu.vultur@microchip.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/lan9662-otpc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/lan9662-otpc.c
++++ b/drivers/nvmem/lan9662-otpc.c
+@@ -203,7 +203,7 @@ static int lan9662_otp_probe(struct plat
+ }
+
+ static const struct of_device_id lan9662_otp_match[] = {
+- { .compatible = "microchip,lan9662-otp", },
++ { .compatible = "microchip,lan9662-otpc", },
+ { },
+ };
+ MODULE_DEVICE_TABLE(of, lan9662_otp_match);
--- /dev/null
+From ee424f7d3960152f5f862bbb6943e59828dc7917 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Fri, 4 Nov 2022 17:52:03 +0100
+Subject: [PATCH] nvmem: u-boot-env: fix crc32_data_offset on redundant
+ u-boot-env
+
+The Western Digital MyBook Live (PowerPC 464/APM82181)
+has a set of redundant u-boot-env. Loading up the driver
+the following error:
+
+| u_boot_env: Invalid calculated CRC32: 0x4f8f2c86 (expected: 0x98b14514)
+| u_boot_env: probe of partition@1e000 failed with error -22
+
+Looking up the userspace libubootenv utilities source [0],
+it looks like the "mark" or "flag" is not part of the
+crc32 sum... which is unfortunate :(
+
+|static int libuboot_load(struct uboot_ctx *ctx)
+|{
+|[...]
+| if (ctx->redundant) {
+| [...]
+| offsetdata = offsetof(struct uboot_env_redund, data);
+| [...] //-----^^
+| }
+| usable_envsize = ctx->size - offsetdata;
+| buf[0] = malloc(bufsize);
+|[...]
+| for (i = 0; i < copies; i++) {
+| data = (uint8_t *)(buf[i] + offsetdata);
+| uint32_t crc;
+|
+| ret = devread(ctx, i, buf[i]);
+| [...]
+| crc = *(uint32_t *)(buf[i] + offsetcrc);
+| dev->crc = crc32(0, (uint8_t *)data, usable_envsize);
+|
+
+[0] https://github.com/sbabic/libubootenv/blob/master/src/uboot_env.c#L951
+
+Fixes: d5542923f200 ("nvmem: add driver handling U-Boot environment variables")
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Link: https://lore.kernel.org/r/70a16eae113e08db2390b76e174f4837caa135c3.1667580636.git.chunkeey@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/u-boot-env.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/u-boot-env.c
++++ b/drivers/nvmem/u-boot-env.c
+@@ -135,7 +135,7 @@ static int u_boot_env_parse(struct u_boo
+ break;
+ case U_BOOT_FORMAT_REDUNDANT:
+ crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32);
+- crc32_data_offset = offsetof(struct u_boot_env_image_redundant, mark);
++ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data);
+ data_offset = offsetof(struct u_boot_env_image_redundant, data);
+ break;
+ }
--- /dev/null
+From 022b68f271de0e53024e6d5e96fee8e76d25eb95 Mon Sep 17 00:00:00 2001
+From: Horatiu Vultur <horatiu.vultur@microchip.com>
+Date: Fri, 18 Nov 2022 06:38:40 +0000
+Subject: [PATCH] nvmem: lan9662-otp: Change return type of
+ lan9662_otp_wait_flag_clear()
+
+The blamed commit introduced the following smatch warning in the
+function lan9662_otp_wait_flag_clear:
+drivers/nvmem/lan9662-otpc.c:43 lan9662_otp_wait_flag_clear() warn: signedness bug returning '(-110)'
+
+Fix this by changing the return type of the function
+lan9662_otp_wait_flag_clear() to be int instead of bool.
+
+Fixes: 9e8f208ad5229d ("nvmem: lan9662-otp: add support")
+Reported-by: kernel test robot <lkp@intel.com>
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063840.6357-5-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/lan9662-otpc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/lan9662-otpc.c
++++ b/drivers/nvmem/lan9662-otpc.c
+@@ -36,7 +36,7 @@ struct lan9662_otp {
+ void __iomem *base;
+ };
+
+-static bool lan9662_otp_wait_flag_clear(void __iomem *reg, u32 flag)
++static int lan9662_otp_wait_flag_clear(void __iomem *reg, u32 flag)
+ {
+ u32 val;
+
--- /dev/null
+From fbfc4ca465a1f8d81bf2d67d95bf7fc67c3cf0c2 Mon Sep 17 00:00:00 2001
+From: Patrick Delaunay <patrick.delaunay@foss.st.com>
+Date: Fri, 18 Nov 2022 06:39:20 +0000
+Subject: [PATCH] nvmem: stm32: move STM32MP15_BSEC_NUM_LOWER in config
+
+Support STM32MP15_BSEC_NUM_LOWER in stm32 romem config to prepare
+the next SoC in STM32MP family.
+
+Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063932.6418-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/stm32-romem.c | 21 ++++++++++++++++-----
+ 1 file changed, 16 insertions(+), 5 deletions(-)
+
+--- a/drivers/nvmem/stm32-romem.c
++++ b/drivers/nvmem/stm32-romem.c
+@@ -22,16 +22,15 @@
+ /* shadow registers offest */
+ #define STM32MP15_BSEC_DATA0 0x200
+
+-/* 32 (x 32-bits) lower shadow registers */
+-#define STM32MP15_BSEC_NUM_LOWER 32
+-
+ struct stm32_romem_cfg {
+ int size;
++ u8 lower;
+ };
+
+ struct stm32_romem_priv {
+ void __iomem *base;
+ struct nvmem_config cfg;
++ u8 lower;
+ };
+
+ static int stm32_romem_read(void *context, unsigned int offset, void *buf,
+@@ -85,7 +84,7 @@ static int stm32_bsec_read(void *context
+ for (i = roffset; (i < roffset + rbytes); i += 4) {
+ u32 otp = i >> 2;
+
+- if (otp < STM32MP15_BSEC_NUM_LOWER) {
++ if (otp < priv->lower) {
+ /* read lower data from shadow registers */
+ val = readl_relaxed(
+ priv->base + STM32MP15_BSEC_DATA0 + i);
+@@ -159,6 +158,8 @@ static int stm32_romem_probe(struct plat
+ priv->cfg.priv = priv;
+ priv->cfg.owner = THIS_MODULE;
+
++ priv->lower = 0;
++
+ cfg = (const struct stm32_romem_cfg *)
+ of_match_device(dev->driver->of_match_table, dev)->data;
+ if (!cfg) {
+@@ -167,6 +168,7 @@ static int stm32_romem_probe(struct plat
+ priv->cfg.reg_read = stm32_romem_read;
+ } else {
+ priv->cfg.size = cfg->size;
++ priv->lower = cfg->lower;
+ priv->cfg.reg_read = stm32_bsec_read;
+ priv->cfg.reg_write = stm32_bsec_write;
+ }
+@@ -174,8 +176,17 @@ static int stm32_romem_probe(struct plat
+ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg));
+ }
+
++/*
++ * STM32MP15 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits)
++ * => 96 x 32-bits data words
++ * - Lower: 1K bits, 2:1 redundancy, incremental bit programming
++ * => 32 (x 32-bits) lower shadow registers = words 0 to 31
++ * - Upper: 2K bits, ECC protection, word programming only
++ * => 64 (x 32-bits) = words 32 to 95
++ */
+ static const struct stm32_romem_cfg stm32mp15_bsec_cfg = {
+- .size = 384, /* 96 x 32-bits data words */
++ .size = 384,
++ .lower = 32,
+ };
+
+ static const struct of_device_id stm32_romem_of_match[] = {
--- /dev/null
+From d61784e6410f3df2028e6eb91b06ffed37a660e0 Mon Sep 17 00:00:00 2001
+From: Patrick Delaunay <patrick.delaunay@foss.st.com>
+Date: Fri, 18 Nov 2022 06:39:21 +0000
+Subject: [PATCH] nvmem: stm32: add warning when upper OTPs are updated
+
+As the upper OTPs are ECC protected, they support only one 32 bits word
+programming.
+For a second modification of this word, these ECC become invalid and
+this OTP will be no more accessible, the shadowed value is invalid.
+
+This patch adds a warning to indicate an upper OTP update, because this
+operation is dangerous as OTP is not locked by the driver after the first
+update to avoid a second update.
+
+Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063932.6418-3-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/stm32-romem.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/nvmem/stm32-romem.c
++++ b/drivers/nvmem/stm32-romem.c
+@@ -132,6 +132,9 @@ static int stm32_bsec_write(void *contex
+ }
+ }
+
++ if (offset + bytes >= priv->lower * 4)
++ dev_warn(dev, "Update of upper OTPs with ECC protection (word programming, only once)\n");
++
+ return 0;
+ }
+
--- /dev/null
+From a3816a7d7c097c1da46aad5f5d1e229b607dce04 Mon Sep 17 00:00:00 2001
+From: Patrick Delaunay <patrick.delaunay@foss.st.com>
+Date: Fri, 18 Nov 2022 06:39:22 +0000
+Subject: [PATCH] nvmem: stm32: add nvmem type attribute
+
+Inform NVMEM framework of type attribute for stm32-romem as NVMEM_TYPE_OTP
+so userspace is able to know how the data is stored in BSEC.
+
+Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063932.6418-4-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/stm32-romem.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/nvmem/stm32-romem.c
++++ b/drivers/nvmem/stm32-romem.c
+@@ -160,6 +160,7 @@ static int stm32_romem_probe(struct plat
+ priv->cfg.dev = dev;
+ priv->cfg.priv = priv;
+ priv->cfg.owner = THIS_MODULE;
++ priv->cfg.type = NVMEM_TYPE_OTP;
+
+ priv->lower = 0;
+
--- /dev/null
+From 06aac0e11960a7ddccc1888326b5906d017e0f24 Mon Sep 17 00:00:00 2001
+From: Jiangshan Yi <yijiangshan@kylinos.cn>
+Date: Fri, 18 Nov 2022 06:39:24 +0000
+Subject: [PATCH] nvmem: stm32: fix spelling typo in comment
+
+Fix spelling typo in comment.
+
+Reported-by: k2ci <kernel-bot@kylinos.cn>
+Signed-off-by: Jiangshan Yi <yijiangshan@kylinos.cn>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063932.6418-6-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/stm32-romem.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/stm32-romem.c
++++ b/drivers/nvmem/stm32-romem.c
+@@ -19,7 +19,7 @@
+ #define STM32_SMC_WRITE_SHADOW 0x03
+ #define STM32_SMC_READ_OTP 0x04
+
+-/* shadow registers offest */
++/* shadow registers offset */
+ #define STM32MP15_BSEC_DATA0 0x200
+
+ struct stm32_romem_cfg {
--- /dev/null
+From fb817c4ef63e8cfb6e77ae4a2875ae854c80708f Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.i.king@gmail.com>
+Date: Fri, 18 Nov 2022 06:39:26 +0000
+Subject: [PATCH] nvmem: Kconfig: Fix spelling mistake "controlls" ->
+ "controls"
+
+There is a spelling mistake in a Kconfig description. Fix it.
+
+Signed-off-by: Colin Ian King <colin.i.king@gmail.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063932.6418-8-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -164,7 +164,7 @@ config NVMEM_MICROCHIP_OTPC
+ depends on ARCH_AT91 || COMPILE_TEST
+ help
+ This driver enable the OTP controller available on Microchip SAMA7G5
+- SoCs. It controlls the access to the OTP memory connected to it.
++ SoCs. It controls the access to the OTP memory connected to it.
+
+ config NVMEM_MTK_EFUSE
+ tristate "Mediatek SoCs EFUSE support"
--- /dev/null
+From ada84d07af6097b2addd18262668ce6cb9e15206 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 18 Nov 2022 06:39:27 +0000
+Subject: [PATCH] nvmem: u-boot-env: add Broadcom format support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Broadcom uses U-Boot for a lot of their bcmbca familiy chipsets. They
+decided to store U-Boot environment data inside U-Boot partition and to
+use a custom header (with "uEnv" magic and env data length).
+
+Add support for Broadcom's specific binding and their custom format.
+
+Ref: 6b0584c19d87 ("dt-bindings: nvmem: u-boot,env: add Broadcom's variant binding")
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20221118063932.6418-9-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/u-boot-env.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/drivers/nvmem/u-boot-env.c
++++ b/drivers/nvmem/u-boot-env.c
+@@ -16,6 +16,7 @@
+ enum u_boot_env_format {
+ U_BOOT_FORMAT_SINGLE,
+ U_BOOT_FORMAT_REDUNDANT,
++ U_BOOT_FORMAT_BROADCOM,
+ };
+
+ struct u_boot_env {
+@@ -40,6 +41,13 @@ struct u_boot_env_image_redundant {
+ uint8_t data[];
+ } __packed;
+
++struct u_boot_env_image_broadcom {
++ __le32 magic;
++ __le32 len;
++ __le32 crc32;
++ uint8_t data[0];
++} __packed;
++
+ static int u_boot_env_read(void *context, unsigned int offset, void *val,
+ size_t bytes)
+ {
+@@ -138,6 +146,11 @@ static int u_boot_env_parse(struct u_boo
+ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data);
+ data_offset = offsetof(struct u_boot_env_image_redundant, data);
+ break;
++ case U_BOOT_FORMAT_BROADCOM:
++ crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32);
++ crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data);
++ data_offset = offsetof(struct u_boot_env_image_broadcom, data);
++ break;
+ }
+ crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset));
+ crc32_data_len = priv->mtd->size - crc32_data_offset;
+@@ -202,6 +215,7 @@ static const struct of_device_id u_boot_
+ { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, },
+ { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
+ { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, },
++ { .compatible = "brcm,env", .data = (void *)U_BOOT_FORMAT_BROADCOM, },
+ {},
+ };
+
--- /dev/null
+From 0e71cac033bb7689c4dfa2e6814191337ef770f5 Mon Sep 17 00:00:00 2001
+From: INAGAKI Hiroshi <musashino.open@gmail.com>
+Date: Thu, 13 Oct 2022 00:51:33 +0900
+Subject: [PATCH] nvmem: u-boot-env: align endianness of crc32 values
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch fixes crc32 error on Big-Endianness system by conversion of
+calculated crc32 value.
+
+Little-Endianness system:
+
+ obtained crc32: Little
+calculated crc32: Little
+
+Big-Endianness system:
+
+ obtained crc32: Little
+calculated crc32: Big
+
+log (APRESIA ApresiaLightGS120GT-SS, RTL8382M, Big-Endianness):
+
+[ 8.570000] u_boot_env 18001200.spi:flash@0:partitions:partition@c0000: Invalid calculated CRC32: 0x88cd6f09 (expected: 0x096fcd88)
+[ 8.580000] u_boot_env: probe of 18001200.spi:flash@0:partitions:partition@c0000 failed with error -22
+
+Fixes: f955dc1445069 ("nvmem: add driver handling U-Boot environment variables")
+
+Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
+Acked-by: Rafał Miłecki <rafal@milecki.pl>
+Tested-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+---
+ drivers/nvmem/u-boot-env.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/u-boot-env.c
++++ b/drivers/nvmem/u-boot-env.c
+@@ -156,7 +156,7 @@ static int u_boot_env_parse(struct u_boo
+ crc32_data_len = priv->mtd->size - crc32_data_offset;
+ data_len = priv->mtd->size - data_offset;
+
+- calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L;
++ calc = le32_to_cpu((__le32)crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L);
+ if (calc != crc32) {
+ dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32);
+ err = -EINVAL;
CONFIG_NUMA_BALANCING=y
CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y
CONFIG_NVMEM=y
+# CONFIG_NVMEM_LAYERSCAPE_SFP is not set
# CONFIG_NVMEM_SPMI_SDAM is not set
CONFIG_NVMEM_SYSFS=y
CONFIG_OF=y
+++ /dev/null
-From 98e2c4efae214fb7086cac9117616eb6ea11475d Mon Sep 17 00:00:00 2001
-From: Chunfeng Yun <chunfeng.yun@mediatek.com>
-Date: Thu, 9 Dec 2021 17:42:34 +0000
-Subject: [PATCH] nvmem: mtk-efuse: support minimum one byte access stride and
- granularity
-
-In order to support nvmem bits property, should support minimum 1 byte
-read stride and minimum 1 byte read granularity at the same time.
-
-Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-Link: https://lore.kernel.org/r/20211209174235.14049-4-srinivas.kandagatla@linaro.org
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/nvmem/mtk-efuse.c | 13 +++++++------
- 1 file changed, 7 insertions(+), 6 deletions(-)
-
---- a/drivers/nvmem/mtk-efuse.c
-+++ b/drivers/nvmem/mtk-efuse.c
-@@ -19,11 +19,12 @@ static int mtk_reg_read(void *context,
- unsigned int reg, void *_val, size_t bytes)
- {
- struct mtk_efuse_priv *priv = context;
-- u32 *val = _val;
-- int i = 0, words = bytes / 4;
-+ void __iomem *addr = priv->base + reg;
-+ u8 *val = _val;
-+ int i;
-
-- while (words--)
-- *val++ = readl(priv->base + reg + (i++ * 4));
-+ for (i = 0; i < bytes; i++, val++)
-+ *val = readb(addr + i);
-
- return 0;
- }
-@@ -45,8 +46,8 @@ static int mtk_efuse_probe(struct platfo
- if (IS_ERR(priv->base))
- return PTR_ERR(priv->base);
-
-- econfig.stride = 4;
-- econfig.word_size = 4;
-+ econfig.stride = 1;
-+ econfig.word_size = 1;
- econfig.reg_read = mtk_reg_read;
- econfig.size = resource_size(res);
- econfig.priv = priv;