kernel: backport NVMEM patches queued for the v6.4
authorRafał Miłecki <rafal@milecki.pl>
Thu, 6 Apr 2023 07:15:49 +0000 (09:15 +0200)
committerRafał Miłecki <rafal@milecki.pl>
Thu, 6 Apr 2023 10:13:22 +0000 (12:13 +0200)
They add NVMEM layouts support. It allows handling NVMEM content
independently of NVMEM device access.

Skip U-Boot env data patch for now as it break our downstream MAC hacks.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
46 files changed:
target/linux/generic/backport-5.10/814-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0004-nvmem-core-request-layout-modules-loading.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/814-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch [new file with mode: 0644]
target/linux/generic/backport-5.15/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch [new file with mode: 0644]
target/linux/generic/config-5.10
target/linux/generic/config-5.15

diff --git a/target/linux/generic/backport-5.10/814-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch b/target/linux/generic/backport-5.10/814-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch
new file mode 100644 (file)
index 0000000..8328e87
--- /dev/null
@@ -0,0 +1,35 @@
+From bcd1fe07def0f070eb5f31594620aaee6f81d31a Mon Sep 17 00:00:00 2001
+From: Nick Alcock <nick.alcock@oracle.com>
+Date: Tue, 4 Apr 2023 18:21:11 +0100
+Subject: [PATCH] nvmem: xilinx: zynqmp: make modular
+
+This driver has a MODULE_LICENSE but is not tristate so cannot be
+built as a module, unlike all its peers: make it modular to match.
+
+Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
+Suggested-by: Michal Simek <michal.simek@amd.com>
+Cc: Luis Chamberlain <mcgrof@kernel.org>
+Cc: linux-modules@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org
+Cc: Hitomi Hasegawa <hasegawa-hitomi@fujitsu.com>
+Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Cc: Michal Simek <michal.simek@xilinx.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-4-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
+@@ -368,7 +368,7 @@ config NVMEM_VF610_OCOTP
+         be called nvmem-vf610-ocotp.
+ config NVMEM_ZYNQMP
+-      bool "Xilinx ZYNQMP SoC nvmem firmware support"
++      tristate "Xilinx ZYNQMP SoC nvmem firmware support"
+       depends on ARCH_ZYNQMP
+       help
+         This is a driver to access hardware related data like
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch b/target/linux/generic/backport-5.10/814-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch
new file mode 100644 (file)
index 0000000..8b886ae
--- /dev/null
@@ -0,0 +1,387 @@
+From 266570f496b90dea8fda893c2cf7c28d63ae2bd9 Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Tue, 4 Apr 2023 18:21:21 +0100
+Subject: [PATCH] nvmem: core: introduce NVMEM layouts
+
+NVMEM layouts are used to generate NVMEM cells during runtime. Think of
+an EEPROM with a well-defined conent. For now, the content can be
+described by a device tree or a board file. But this only works if the
+offsets and lengths are static and don't change. One could also argue
+that putting the layout of the EEPROM in the device tree is the wrong
+place. Instead, the device tree should just have a specific compatible
+string.
+
+Right now there are two use cases:
+ (1) The NVMEM cell needs special processing. E.g. if it only specifies
+     a base MAC address offset and you need to add an offset, or it
+     needs to parse a MAC from ASCII format or some proprietary format.
+     (Post processing of cells is added in a later commit).
+ (2) u-boot environment parsing. The cells don't have a particular
+     offset but it needs parsing the content to determine the offsets
+     and length.
+
+Co-developed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-14-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/driver-api/nvmem.rst |  15 ++++
+ drivers/nvmem/Kconfig              |   4 +
+ drivers/nvmem/Makefile             |   1 +
+ drivers/nvmem/core.c               | 120 +++++++++++++++++++++++++++++
+ drivers/nvmem/layouts/Kconfig      |   5 ++
+ drivers/nvmem/layouts/Makefile     |   4 +
+ include/linux/nvmem-consumer.h     |   7 ++
+ include/linux/nvmem-provider.h     |  51 ++++++++++++
+ 8 files changed, 207 insertions(+)
+ create mode 100644 drivers/nvmem/layouts/Kconfig
+ create mode 100644 drivers/nvmem/layouts/Makefile
+
+--- a/Documentation/driver-api/nvmem.rst
++++ b/Documentation/driver-api/nvmem.rst
+@@ -189,3 +189,18 @@ ex::
+ =====================
+ See Documentation/devicetree/bindings/nvmem/nvmem.txt
++
++8. NVMEM layouts
++================
++
++NVMEM layouts are yet another mechanism to create cells. With the device
++tree binding it is possible to specify simple cells by using an offset
++and a length. Sometimes, the cells doesn't have a static offset, but
++the content is still well defined, e.g. tag-length-values. In this case,
++the NVMEM device content has to be first parsed and the cells need to
++be added accordingly. Layouts let you read the content of the NVMEM device
++and let you add cells dynamically.
++
++Another use case for layouts is the post processing of cells. With layouts,
++it is possible to associate a custom post processing hook to a cell. It
++even possible to add this hook to cells not created by the layout itself.
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -21,6 +21,10 @@ config NVMEM_SYSFS
+        This interface is mostly used by userspace applications to
+        read/write directly into nvmem.
++# Layouts
++
++source "drivers/nvmem/layouts/Kconfig"
++
+ # Devices
+ config NVMEM_APPLE_EFUSES
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -5,6 +5,7 @@
+ obj-$(CONFIG_NVMEM)           += nvmem_core.o
+ nvmem_core-y                  := core.o
++obj-y                         += layouts/
+ # Devices
+ obj-$(CONFIG_NVMEM_APPLE_EFUSES)      += nvmem-apple-efuses.o
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -40,6 +40,7 @@ struct nvmem_device {
+       nvmem_reg_write_t       reg_write;
+       nvmem_cell_post_process_t cell_post_process;
+       struct gpio_desc        *wp_gpio;
++      struct nvmem_layout     *layout;
+       void *priv;
+ };
+@@ -74,6 +75,9 @@ static LIST_HEAD(nvmem_lookup_list);
+ static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
++static DEFINE_SPINLOCK(nvmem_layout_lock);
++static LIST_HEAD(nvmem_layouts);
++
+ static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
+                           void *val, size_t bytes)
+ {
+@@ -728,6 +732,101 @@ static int nvmem_add_cells_from_of(struc
+       return 0;
+ }
++int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner)
++{
++      layout->owner = owner;
++
++      spin_lock(&nvmem_layout_lock);
++      list_add(&layout->node, &nvmem_layouts);
++      spin_unlock(&nvmem_layout_lock);
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(__nvmem_layout_register);
++
++void nvmem_layout_unregister(struct nvmem_layout *layout)
++{
++      spin_lock(&nvmem_layout_lock);
++      list_del(&layout->node);
++      spin_unlock(&nvmem_layout_lock);
++}
++EXPORT_SYMBOL_GPL(nvmem_layout_unregister);
++
++static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem)
++{
++      struct device_node *layout_np, *np = nvmem->dev.of_node;
++      struct nvmem_layout *l, *layout = NULL;
++
++      layout_np = of_get_child_by_name(np, "nvmem-layout");
++      if (!layout_np)
++              return NULL;
++
++      spin_lock(&nvmem_layout_lock);
++
++      list_for_each_entry(l, &nvmem_layouts, node) {
++              if (of_match_node(l->of_match_table, layout_np)) {
++                      if (try_module_get(l->owner))
++                              layout = l;
++
++                      break;
++              }
++      }
++
++      spin_unlock(&nvmem_layout_lock);
++      of_node_put(layout_np);
++
++      return layout;
++}
++
++static void nvmem_layout_put(struct nvmem_layout *layout)
++{
++      if (layout)
++              module_put(layout->owner);
++}
++
++static int nvmem_add_cells_from_layout(struct nvmem_device *nvmem)
++{
++      struct nvmem_layout *layout = nvmem->layout;
++      int ret;
++
++      if (layout && layout->add_cells) {
++              ret = layout->add_cells(&nvmem->dev, nvmem, layout);
++              if (ret)
++                      return ret;
++      }
++
++      return 0;
++}
++
++#if IS_ENABLED(CONFIG_OF)
++/**
++ * of_nvmem_layout_get_container() - Get OF node to layout container.
++ *
++ * @nvmem: nvmem device.
++ *
++ * Return: a node pointer with refcount incremented or NULL if no
++ * container exists. Use of_node_put() on it when done.
++ */
++struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem)
++{
++      return of_get_child_by_name(nvmem->dev.of_node, "nvmem-layout");
++}
++EXPORT_SYMBOL_GPL(of_nvmem_layout_get_container);
++#endif
++
++const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem,
++                                      struct nvmem_layout *layout)
++{
++      struct device_node __maybe_unused *layout_np;
++      const struct of_device_id *match;
++
++      layout_np = of_nvmem_layout_get_container(nvmem);
++      match = of_match_node(layout->of_match_table, layout_np);
++
++      return match ? match->data : NULL;
++}
++EXPORT_SYMBOL_GPL(nvmem_layout_get_match_data);
++
+ /**
+  * nvmem_register() - Register a nvmem device for given nvmem_config.
+  * Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
+@@ -834,6 +933,12 @@ struct nvmem_device *nvmem_register(cons
+                       goto err_put_device;
+       }
++      /*
++       * If the driver supplied a layout by config->layout, the module
++       * pointer will be NULL and nvmem_layout_put() will be a noop.
++       */
++      nvmem->layout = config->layout ?: nvmem_layout_get(nvmem);
++
+       if (config->cells) {
+               rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
+               if (rval)
+@@ -854,12 +959,17 @@ struct nvmem_device *nvmem_register(cons
+       if (rval)
+               goto err_remove_cells;
++      rval = nvmem_add_cells_from_layout(nvmem);
++      if (rval)
++              goto err_remove_cells;
++
+       blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
+       return nvmem;
+ err_remove_cells:
+       nvmem_device_remove_all_cells(nvmem);
++      nvmem_layout_put(nvmem->layout);
+       if (config->compat)
+               nvmem_sysfs_remove_compat(nvmem, config);
+ err_put_device:
+@@ -881,6 +991,7 @@ static void nvmem_device_release(struct
+               device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
+       nvmem_device_remove_all_cells(nvmem);
++      nvmem_layout_put(nvmem->layout);
+       device_unregister(&nvmem->dev);
+ }
+@@ -1246,6 +1357,15 @@ struct nvmem_cell *of_nvmem_cell_get(str
+               return ERR_PTR(-EINVAL);
+       }
++      /* nvmem layouts produce cells within the nvmem-layout container */
++      if (of_node_name_eq(nvmem_np, "nvmem-layout")) {
++              nvmem_np = of_get_next_parent(nvmem_np);
++              if (!nvmem_np) {
++                      of_node_put(cell_np);
++                      return ERR_PTR(-EINVAL);
++              }
++      }
++
+       nvmem = __nvmem_device_get(nvmem_np, device_match_of_node);
+       of_node_put(nvmem_np);
+       if (IS_ERR(nvmem)) {
+--- /dev/null
++++ b/drivers/nvmem/layouts/Kconfig
+@@ -0,0 +1,5 @@
++# SPDX-License-Identifier: GPL-2.0
++
++menu "Layout Types"
++
++endmenu
+--- /dev/null
++++ b/drivers/nvmem/layouts/Makefile
+@@ -0,0 +1,4 @@
++# SPDX-License-Identifier: GPL-2.0
++#
++# Makefile for nvmem layouts.
++#
+--- a/include/linux/nvmem-consumer.h
++++ b/include/linux/nvmem-consumer.h
+@@ -225,6 +225,7 @@ struct nvmem_cell *of_nvmem_cell_get(str
+                                    const char *id);
+ struct nvmem_device *of_nvmem_device_get(struct device_node *np,
+                                        const char *name);
++struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem);
+ #else
+ static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+                                                  const char *id)
+@@ -237,6 +238,12 @@ static inline struct nvmem_device *of_nv
+ {
+       return ERR_PTR(-EOPNOTSUPP);
+ }
++
++static inline struct device_node *
++of_nvmem_layout_get_container(struct nvmem_device *nvmem)
++{
++      return ERR_PTR(-EOPNOTSUPP);
++}
+ #endif /* CONFIG_NVMEM && CONFIG_OF */
+ #endif  /* ifndef _LINUX_NVMEM_CONSUMER_H */
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -88,6 +88,7 @@ struct nvmem_cell_info {
+  * @stride:   Minimum read/write access stride.
+  * @priv:     User context passed to read/write callbacks.
+  * @ignore_wp:  Write Protect pin is managed by the provider.
++ * @layout:   Fixed layout associated with this nvmem device.
+  *
+  * 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
+@@ -110,6 +111,7 @@ struct nvmem_config {
+       bool                    root_only;
+       struct device_node      *of_node;
+       bool                    ignore_wp;
++      struct nvmem_layout     *layout;
+       bool                    no_of_node;
+       nvmem_reg_read_t        reg_read;
+       nvmem_reg_write_t       reg_write;
+@@ -142,6 +144,33 @@ struct nvmem_cell_table {
+       struct list_head        node;
+ };
++/**
++ * struct nvmem_layout - NVMEM layout definitions
++ *
++ * @name:             Layout name.
++ * @of_match_table:   Open firmware match table.
++ * @add_cells:                Will be called if a nvmem device is found which
++ *                    has this layout. The function will add layout
++ *                    specific cells with nvmem_add_one_cell().
++ * @owner:            Pointer to struct module.
++ * @node:             List node.
++ *
++ * A nvmem device can hold a well defined structure which can just be
++ * evaluated during runtime. For example a TLV list, or a list of "name=val"
++ * pairs. A nvmem layout can parse the nvmem device and add appropriate
++ * cells.
++ */
++struct nvmem_layout {
++      const char *name;
++      const struct of_device_id *of_match_table;
++      int (*add_cells)(struct device *dev, struct nvmem_device *nvmem,
++                       struct nvmem_layout *layout);
++
++      /* private */
++      struct module *owner;
++      struct list_head node;
++};
++
+ #if IS_ENABLED(CONFIG_NVMEM)
+ struct nvmem_device *nvmem_register(const struct nvmem_config *cfg);
+@@ -156,6 +185,14 @@ void nvmem_del_cell_table(struct nvmem_c
+ int nvmem_add_one_cell(struct nvmem_device *nvmem,
+                      const struct nvmem_cell_info *info);
++int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner);
++#define nvmem_layout_register(layout) \
++      __nvmem_layout_register(layout, THIS_MODULE)
++void nvmem_layout_unregister(struct nvmem_layout *layout);
++
++const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem,
++                                      struct nvmem_layout *layout);
++
+ #else
+ static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c)
+@@ -179,5 +216,19 @@ static inline int nvmem_add_one_cell(str
+       return -EOPNOTSUPP;
+ }
++static inline int nvmem_layout_register(struct nvmem_layout *layout)
++{
++      return -EOPNOTSUPP;
++}
++
++static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {}
++
++static inline const void *
++nvmem_layout_get_match_data(struct nvmem_device *nvmem,
++                          struct nvmem_layout *layout)
++{
++      return NULL;
++}
++
+ #endif /* CONFIG_NVMEM */
+ #endif  /* ifndef _LINUX_NVMEM_PROVIDER_H */
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch b/target/linux/generic/backport-5.10/814-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch
new file mode 100644 (file)
index 0000000..6fa7b63
--- /dev/null
@@ -0,0 +1,61 @@
+From 6468a6f45148fb5e95c86b4efebf63f9abcd2137 Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Tue, 4 Apr 2023 18:21:22 +0100
+Subject: [PATCH] nvmem: core: handle the absence of expected layouts
+
+Make nvmem_layout_get() return -EPROBE_DEFER while the expected layout
+is not available. This condition cannot be triggered today as nvmem
+layout drivers are initialed as part of an early init call, but soon
+these drivers will be converted into modules and be initialized with a
+standard priority, so the unavailability of the drivers might become a
+reality that must be taken care of.
+
+Let's anticipate this by telling the caller the layout might not yet be
+available. A probe deferral is requested in this case.
+
+Please note this does not affect any nvmem device not using layouts,
+because an early check against the "nvmem-layout" container presence
+will return NULL in this case.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Tested-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-15-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -755,7 +755,7 @@ EXPORT_SYMBOL_GPL(nvmem_layout_unregiste
+ static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem)
+ {
+       struct device_node *layout_np, *np = nvmem->dev.of_node;
+-      struct nvmem_layout *l, *layout = NULL;
++      struct nvmem_layout *l, *layout = ERR_PTR(-EPROBE_DEFER);
+       layout_np = of_get_child_by_name(np, "nvmem-layout");
+       if (!layout_np)
+@@ -938,6 +938,13 @@ struct nvmem_device *nvmem_register(cons
+        * pointer will be NULL and nvmem_layout_put() will be a noop.
+        */
+       nvmem->layout = config->layout ?: nvmem_layout_get(nvmem);
++      if (IS_ERR(nvmem->layout)) {
++              rval = PTR_ERR(nvmem->layout);
++              nvmem->layout = NULL;
++
++              if (rval == -EPROBE_DEFER)
++                      goto err_teardown_compat;
++      }
+       if (config->cells) {
+               rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
+@@ -970,6 +977,7 @@ struct nvmem_device *nvmem_register(cons
+ err_remove_cells:
+       nvmem_device_remove_all_cells(nvmem);
+       nvmem_layout_put(nvmem->layout);
++err_teardown_compat:
+       if (config->compat)
+               nvmem_sysfs_remove_compat(nvmem, config);
+ err_put_device:
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0004-nvmem-core-request-layout-modules-loading.patch b/target/linux/generic/backport-5.10/814-v6.4-0004-nvmem-core-request-layout-modules-loading.patch
new file mode 100644 (file)
index 0000000..b934166
--- /dev/null
@@ -0,0 +1,52 @@
+From b1c37bec1ccfe5ccab72bc0ddc0dfa45c43e2de2 Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Tue, 4 Apr 2023 18:21:23 +0100
+Subject: [PATCH] nvmem: core: request layout modules loading
+
+When a storage device like an eeprom or an mtd device probes, it
+registers an nvmem device if the nvmem subsystem has been enabled (bool
+symbol). During nvmem registration, if the device is using layouts to
+expose dynamic nvmem cells, the core will first try to get a reference
+over the layout driver callbacks. In practice there is not relationship
+that can be described between the storage driver and the nvmem
+layout. So there is no way we can enforce both drivers will be built-in
+or both will be modules. If the storage device driver is built-in but
+the layout is built as a module, instead of badly failing with an
+endless probe deferral loop, lets just make a modprobe call in case the
+driver was made available in an initramfs with
+of_device_node_request_module(), and offer a fully functional system to
+the user.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Tested-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-16-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -17,6 +17,7 @@
+ #include <linux/nvmem-provider.h>
+ #include <linux/gpio/consumer.h>
+ #include <linux/of.h>
++#include <linux/of_device.h>
+ #include <linux/slab.h>
+ struct nvmem_device {
+@@ -761,6 +762,13 @@ static struct nvmem_layout *nvmem_layout
+       if (!layout_np)
+               return NULL;
++      /*
++       * In case the nvmem device was built-in while the layout was built as a
++       * module, we shall manually request the layout driver loading otherwise
++       * we'll never have any match.
++       */
++      of_request_module(layout_np);
++
+       spin_lock(&nvmem_layout_lock);
+       list_for_each_entry(l, &nvmem_layouts, node) {
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch b/target/linux/generic/backport-5.10/814-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch
new file mode 100644 (file)
index 0000000..53628cd
--- /dev/null
@@ -0,0 +1,86 @@
+From 345ec382cd4b736c36e01f155d08c913b225b736 Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Tue, 4 Apr 2023 18:21:24 +0100
+Subject: [PATCH] nvmem: core: add per-cell post processing
+
+Instead of relying on the name the consumer is using for the cell, like
+it is done for the nvmem .cell_post_process configuration parameter,
+provide a per-cell post processing hook. This can then be populated by
+the NVMEM provider (or the NVMEM layout) when adding the cell.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-17-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c           | 17 +++++++++++++++++
+ include/linux/nvmem-provider.h |  3 +++
+ 2 files changed, 20 insertions(+)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -54,6 +54,7 @@ struct nvmem_cell_entry {
+       int                     bytes;
+       int                     bit_offset;
+       int                     nbits;
++      nvmem_cell_post_process_t read_post_process;
+       struct device_node      *np;
+       struct nvmem_device     *nvmem;
+       struct list_head        node;
+@@ -470,6 +471,7 @@ static int nvmem_cell_info_to_nvmem_cell
+       cell->offset = info->offset;
+       cell->bytes = info->bytes;
+       cell->name = info->name;
++      cell->read_post_process = info->read_post_process;
+       cell->bit_offset = info->bit_offset;
+       cell->nbits = info->nbits;
+@@ -1563,6 +1565,13 @@ static int __nvmem_cell_read(struct nvme
+       if (cell->bit_offset || cell->nbits)
+               nvmem_shift_read_buffer_in_place(cell, buf);
++      if (cell->read_post_process) {
++              rc = cell->read_post_process(nvmem->priv, id, index,
++                                           cell->offset, buf, cell->bytes);
++              if (rc)
++                      return rc;
++      }
++
+       if (nvmem->cell_post_process) {
+               rc = nvmem->cell_post_process(nvmem->priv, id, index,
+                                             cell->offset, buf, cell->bytes);
+@@ -1671,6 +1680,14 @@ static int __nvmem_cell_entry_write(stru
+           (cell->bit_offset == 0 && len != cell->bytes))
+               return -EINVAL;
++      /*
++       * Any cells which have a read_post_process hook are read-only because
++       * we cannot reverse the operation and it might affect other cells,
++       * too.
++       */
++      if (cell->read_post_process)
++              return -EINVAL;
++
+       if (cell->bit_offset || cell->nbits) {
+               buf = nvmem_cell_prepare_write_buffer(cell, buf, len);
+               if (IS_ERR(buf))
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -54,6 +54,8 @@ struct nvmem_keepout {
+  * @bit_offset:       Bit offset if cell is smaller than a byte.
+  * @nbits:    Number of bits.
+  * @np:               Optional device_node pointer.
++ * @read_post_process:        Callback for optional post processing of cell data
++ *                    on reads.
+  */
+ struct nvmem_cell_info {
+       const char              *name;
+@@ -62,6 +64,7 @@ struct nvmem_cell_info {
+       unsigned int            bit_offset;
+       unsigned int            nbits;
+       struct device_node      *np;
++      nvmem_cell_post_process_t read_post_process;
+ };
+ /**
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch b/target/linux/generic/backport-5.10/814-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch
new file mode 100644 (file)
index 0000000..3299014
--- /dev/null
@@ -0,0 +1,59 @@
+From de12c9691501ccba41a154c223869f82be4c12fd Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Tue, 4 Apr 2023 18:21:25 +0100
+Subject: [PATCH] nvmem: core: allow to modify a cell before adding it
+
+Provide a way to modify a cell before it will get added. This is useful
+to attach a custom post processing hook via a layout.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-18-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c           | 4 ++++
+ include/linux/nvmem-provider.h | 5 +++++
+ 2 files changed, 9 insertions(+)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -695,6 +695,7 @@ static int nvmem_validate_keepouts(struc
+ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
+ {
++      struct nvmem_layout *layout = nvmem->layout;
+       struct device *dev = &nvmem->dev;
+       struct device_node *child;
+       const __be32 *addr;
+@@ -724,6 +725,9 @@ static int nvmem_add_cells_from_of(struc
+               info.np = of_node_get(child);
++              if (layout && layout->fixup_cell_info)
++                      layout->fixup_cell_info(nvmem, layout, &info);
++
+               ret = nvmem_add_one_cell(nvmem, &info);
+               kfree(info.name);
+               if (ret) {
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -155,6 +155,8 @@ struct nvmem_cell_table {
+  * @add_cells:                Will be called if a nvmem device is found which
+  *                    has this layout. The function will add layout
+  *                    specific cells with nvmem_add_one_cell().
++ * @fixup_cell_info:  Will be called before a cell is added. Can be
++ *                    used to modify the nvmem_cell_info.
+  * @owner:            Pointer to struct module.
+  * @node:             List node.
+  *
+@@ -168,6 +170,9 @@ struct nvmem_layout {
+       const struct of_device_id *of_match_table;
+       int (*add_cells)(struct device *dev, struct nvmem_device *nvmem,
+                        struct nvmem_layout *layout);
++      void (*fixup_cell_info)(struct nvmem_device *nvmem,
++                              struct nvmem_layout *layout,
++                              struct nvmem_cell_info *cell);
+       /* private */
+       struct module *owner;
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch b/target/linux/generic/backport-5.10/814-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch
new file mode 100644 (file)
index 0000000..2a5fa61
--- /dev/null
@@ -0,0 +1,81 @@
+From 6c56a82d7895a213a43182a5d01a21a906a79847 Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Tue, 4 Apr 2023 18:21:26 +0100
+Subject: [PATCH] nvmem: imx-ocotp: replace global post processing with layouts
+
+In preparation of retiring the global post processing hook change this
+driver to use layouts. The layout will be supplied during registration
+and will be used to add the post processing hook to all added cells.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Tested-by: Michael Walle <michael@walle.cc> # on kontron-pitx-imx8m
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-19-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/imx-ocotp.c | 30 +++++++++++++++++++-----------
+ 1 file changed, 19 insertions(+), 11 deletions(-)
+
+--- a/drivers/nvmem/imx-ocotp.c
++++ b/drivers/nvmem/imx-ocotp.c
+@@ -225,18 +225,13 @@ read_end:
+ static int imx_ocotp_cell_pp(void *context, const char *id, int index,
+                            unsigned int offset, void *data, size_t bytes)
+ {
+-      struct ocotp_priv *priv = context;
++      u8 *buf = data;
++      int i;
+       /* 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]);
+-              }
+-      }
++      if (id && !strcmp(id, "mac-address"))
++              for (i = 0; i < bytes / 2; i++)
++                      swap(buf[i], buf[bytes - i - 1]);
+       return 0;
+ }
+@@ -488,7 +483,6 @@ 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 = {
+@@ -595,6 +589,17 @@ static const struct of_device_id imx_oco
+ };
+ MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids);
++static void imx_ocotp_fixup_cell_info(struct nvmem_device *nvmem,
++                                    struct nvmem_layout *layout,
++                                    struct nvmem_cell_info *cell)
++{
++      cell->read_post_process = imx_ocotp_cell_pp;
++}
++
++struct nvmem_layout imx_ocotp_layout = {
++      .fixup_cell_info = imx_ocotp_fixup_cell_info,
++};
++
+ static int imx_ocotp_probe(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+@@ -619,6 +624,9 @@ static int imx_ocotp_probe(struct platfo
+       imx_ocotp_nvmem_config.size = 4 * priv->params->nregs;
+       imx_ocotp_nvmem_config.dev = dev;
+       imx_ocotp_nvmem_config.priv = priv;
++      if (priv->params->reverse_mac_address)
++              imx_ocotp_nvmem_config.layout = &imx_ocotp_layout;
++
+       priv->config = &imx_ocotp_nvmem_config;
+       clk_prepare_enable(priv->clk);
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch b/target/linux/generic/backport-5.10/814-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch
new file mode 100644 (file)
index 0000000..eac202b
--- /dev/null
@@ -0,0 +1,68 @@
+From 011e40a166fdaa65fb9946b7cd91efec85b70dbb Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Tue, 4 Apr 2023 18:21:27 +0100
+Subject: [PATCH] nvmem: cell: drop global cell_post_process
+
+There are no users anymore for the global cell_post_process callback
+anymore. New users should use proper nvmem layouts.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-20-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c           | 9 ---------
+ include/linux/nvmem-provider.h | 2 --
+ 2 files changed, 11 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -39,7 +39,6 @@ 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;
+       struct nvmem_layout     *layout;
+       void *priv;
+@@ -903,7 +902,6 @@ 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)
+@@ -1575,13 +1573,6 @@ static int __nvmem_cell_read(struct nvme
+               if (rc)
+                       return rc;
+       }
+-
+-      if (nvmem->cell_post_process) {
+-              rc = nvmem->cell_post_process(nvmem->priv, id, index,
+-                                            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
+@@ -85,7 +85,6 @@ struct nvmem_cell_info {
+  * @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.
+@@ -118,7 +117,6 @@ 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;
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch b/target/linux/generic/backport-5.10/814-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch
new file mode 100644 (file)
index 0000000..46b30a2
--- /dev/null
@@ -0,0 +1,76 @@
+From 8a134fd9f9323f4c39ec27055b3d3723cfb5c1e9 Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Tue, 4 Apr 2023 18:21:28 +0100
+Subject: [PATCH] nvmem: core: provide own priv pointer in post process
+ callback
+
+It doesn't make any more sense to have a opaque pointer set up by the
+nvmem device. Usually, the layout isn't associated with a particular
+nvmem device. Instead, let the caller who set the post process callback
+provide the priv pointer.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-21-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c           | 4 +++-
+ include/linux/nvmem-provider.h | 5 ++++-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -54,6 +54,7 @@ struct nvmem_cell_entry {
+       int                     bit_offset;
+       int                     nbits;
+       nvmem_cell_post_process_t read_post_process;
++      void                    *priv;
+       struct device_node      *np;
+       struct nvmem_device     *nvmem;
+       struct list_head        node;
+@@ -471,6 +472,7 @@ static int nvmem_cell_info_to_nvmem_cell
+       cell->bytes = info->bytes;
+       cell->name = info->name;
+       cell->read_post_process = info->read_post_process;
++      cell->priv = info->priv;
+       cell->bit_offset = info->bit_offset;
+       cell->nbits = info->nbits;
+@@ -1568,7 +1570,7 @@ static int __nvmem_cell_read(struct nvme
+               nvmem_shift_read_buffer_in_place(cell, buf);
+       if (cell->read_post_process) {
+-              rc = cell->read_post_process(nvmem->priv, id, index,
++              rc = cell->read_post_process(cell->priv, id, index,
+                                            cell->offset, buf, cell->bytes);
+               if (rc)
+                       return rc;
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -20,7 +20,8 @@ typedef int (*nvmem_reg_write_t)(void *p
+                                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, int index,
+-                                       unsigned int offset, void *buf, size_t bytes);
++                                       unsigned int offset, void *buf,
++                                       size_t bytes);
+ enum nvmem_type {
+       NVMEM_TYPE_UNKNOWN = 0,
+@@ -56,6 +57,7 @@ struct nvmem_keepout {
+  * @np:               Optional device_node pointer.
+  * @read_post_process:        Callback for optional post processing of cell data
+  *                    on reads.
++ * @priv:     Opaque data passed to the read_post_process hook.
+  */
+ struct nvmem_cell_info {
+       const char              *name;
+@@ -65,6 +67,7 @@ struct nvmem_cell_info {
+       unsigned int            nbits;
+       struct device_node      *np;
+       nvmem_cell_post_process_t read_post_process;
++      void                    *priv;
+ };
+ /**
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch b/target/linux/generic/backport-5.10/814-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch
new file mode 100644 (file)
index 0000000..7d97658
--- /dev/null
@@ -0,0 +1,215 @@
+From d9fae023fe86069750092fc1c2f3a73e2fb18512 Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Tue, 4 Apr 2023 18:21:29 +0100
+Subject: [PATCH] nvmem: layouts: sl28vpd: Add new layout driver
+
+This layout applies to the VPD of the Kontron sl28 boards. The VPD only
+contains a base MAC address. Therefore, we have to add an individual
+offset to it. This is done by taking the second argument of the nvmem
+phandle into account. Also this let us checking the VPD version and the
+checksum.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-22-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/layouts/Kconfig   |   9 ++
+ drivers/nvmem/layouts/Makefile  |   2 +
+ drivers/nvmem/layouts/sl28vpd.c | 165 ++++++++++++++++++++++++++++++++
+ 3 files changed, 176 insertions(+)
+ create mode 100644 drivers/nvmem/layouts/sl28vpd.c
+
+--- a/drivers/nvmem/layouts/Kconfig
++++ b/drivers/nvmem/layouts/Kconfig
+@@ -2,4 +2,13 @@
+ menu "Layout Types"
++config NVMEM_LAYOUT_SL28_VPD
++      tristate "Kontron sl28 VPD layout support"
++      select CRC8
++      help
++        Say Y here if you want to support the VPD layout of the Kontron
++        SMARC-sAL28 boards.
++
++        If unsure, say N.
++
+ endmenu
+--- a/drivers/nvmem/layouts/Makefile
++++ b/drivers/nvmem/layouts/Makefile
+@@ -2,3 +2,5 @@
+ #
+ # Makefile for nvmem layouts.
+ #
++
++obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o
+--- /dev/null
++++ b/drivers/nvmem/layouts/sl28vpd.c
+@@ -0,0 +1,165 @@
++// SPDX-License-Identifier: GPL-2.0
++
++#include <linux/crc8.h>
++#include <linux/etherdevice.h>
++#include <linux/nvmem-consumer.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of.h>
++#include <uapi/linux/if_ether.h>
++
++#define SL28VPD_MAGIC 'V'
++
++struct sl28vpd_header {
++      u8 magic;
++      u8 version;
++} __packed;
++
++struct sl28vpd_v1 {
++      struct sl28vpd_header header;
++      char serial_number[15];
++      u8 base_mac_address[ETH_ALEN];
++      u8 crc8;
++} __packed;
++
++static int sl28vpd_mac_address_pp(void *priv, const char *id, int index,
++                                unsigned int offset, void *buf,
++                                size_t bytes)
++{
++      if (bytes != ETH_ALEN)
++              return -EINVAL;
++
++      if (index < 0)
++              return -EINVAL;
++
++      if (!is_valid_ether_addr(buf))
++              return -EINVAL;
++
++      eth_addr_add(buf, index);
++
++      return 0;
++}
++
++static const struct nvmem_cell_info sl28vpd_v1_entries[] = {
++      {
++              .name = "serial-number",
++              .offset = offsetof(struct sl28vpd_v1, serial_number),
++              .bytes = sizeof_field(struct sl28vpd_v1, serial_number),
++      },
++      {
++              .name = "base-mac-address",
++              .offset = offsetof(struct sl28vpd_v1, base_mac_address),
++              .bytes = sizeof_field(struct sl28vpd_v1, base_mac_address),
++              .read_post_process = sl28vpd_mac_address_pp,
++      },
++};
++
++static int sl28vpd_v1_check_crc(struct device *dev, struct nvmem_device *nvmem)
++{
++      struct sl28vpd_v1 data_v1;
++      u8 table[CRC8_TABLE_SIZE];
++      int ret;
++      u8 crc;
++
++      crc8_populate_msb(table, 0x07);
++
++      ret = nvmem_device_read(nvmem, 0, sizeof(data_v1), &data_v1);
++      if (ret < 0)
++              return ret;
++      else if (ret != sizeof(data_v1))
++              return -EIO;
++
++      crc = crc8(table, (void *)&data_v1, sizeof(data_v1) - 1, 0);
++
++      if (crc != data_v1.crc8) {
++              dev_err(dev,
++                      "Checksum is invalid (got %02x, expected %02x).\n",
++                      crc, data_v1.crc8);
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem,
++                           struct nvmem_layout *layout)
++{
++      const struct nvmem_cell_info *pinfo;
++      struct nvmem_cell_info info = {0};
++      struct device_node *layout_np;
++      struct sl28vpd_header hdr;
++      int ret, i;
++
++      /* check header */
++      ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr);
++      if (ret < 0)
++              return ret;
++      else if (ret != sizeof(hdr))
++              return -EIO;
++
++      if (hdr.magic != SL28VPD_MAGIC) {
++              dev_err(dev, "Invalid magic value (%02x)\n", hdr.magic);
++              return -EINVAL;
++      }
++
++      if (hdr.version != 1) {
++              dev_err(dev, "Version %d is unsupported.\n", hdr.version);
++              return -EINVAL;
++      }
++
++      ret = sl28vpd_v1_check_crc(dev, nvmem);
++      if (ret)
++              return ret;
++
++      layout_np = of_nvmem_layout_get_container(nvmem);
++      if (!layout_np)
++              return -ENOENT;
++
++      for (i = 0; i < ARRAY_SIZE(sl28vpd_v1_entries); i++) {
++              pinfo = &sl28vpd_v1_entries[i];
++
++              info.name = pinfo->name;
++              info.offset = pinfo->offset;
++              info.bytes = pinfo->bytes;
++              info.read_post_process = pinfo->read_post_process;
++              info.np = of_get_child_by_name(layout_np, pinfo->name);
++
++              ret = nvmem_add_one_cell(nvmem, &info);
++              if (ret) {
++                      of_node_put(layout_np);
++                      return ret;
++              }
++      }
++
++      of_node_put(layout_np);
++
++      return 0;
++}
++
++static const struct of_device_id sl28vpd_of_match_table[] = {
++      { .compatible = "kontron,sl28-vpd" },
++      {},
++};
++MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table);
++
++struct nvmem_layout sl28vpd_layout = {
++      .name = "sl28-vpd",
++      .of_match_table = sl28vpd_of_match_table,
++      .add_cells = sl28vpd_add_cells,
++};
++
++static int __init sl28vpd_init(void)
++{
++      return nvmem_layout_register(&sl28vpd_layout);
++}
++
++static void __exit sl28vpd_exit(void)
++{
++      nvmem_layout_unregister(&sl28vpd_layout);
++}
++
++module_init(sl28vpd_init);
++module_exit(sl28vpd_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
++MODULE_DESCRIPTION("NVMEM layout driver for the VPD of Kontron sl28 boards");
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch b/target/linux/generic/backport-5.10/814-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch
new file mode 100644 (file)
index 0000000..ca8b4bc
--- /dev/null
@@ -0,0 +1,306 @@
+From d3c0d12f6474216bf386101e2449cc73e5c5b61d Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Tue, 4 Apr 2023 18:21:31 +0100
+Subject: [PATCH] nvmem: layouts: onie-tlv: Add new layout driver
+
+This layout applies on top of any non volatile storage device containing
+an ONIE table factory flashed. This table follows the tlv
+(type-length-value) organization described in the link below. We cannot
+afford using regular parsers because the content of these tables is
+manufacturer specific and must be dynamically discovered.
+
+Link: https://opencomputeproject.github.io/onie/design-spec/hw_requirements.html
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-24-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/layouts/Kconfig    |   9 ++
+ drivers/nvmem/layouts/Makefile   |   1 +
+ drivers/nvmem/layouts/onie-tlv.c | 257 +++++++++++++++++++++++++++++++
+ 3 files changed, 267 insertions(+)
+ create mode 100644 drivers/nvmem/layouts/onie-tlv.c
+
+--- a/drivers/nvmem/layouts/Kconfig
++++ b/drivers/nvmem/layouts/Kconfig
+@@ -11,4 +11,13 @@ config NVMEM_LAYOUT_SL28_VPD
+         If unsure, say N.
++config NVMEM_LAYOUT_ONIE_TLV
++      tristate "ONIE tlv support"
++      select CRC32
++      help
++        Say Y here if you want to support the Open Compute Project ONIE
++        Type-Length-Value standard table.
++
++        If unsure, say N.
++
+ endmenu
+--- a/drivers/nvmem/layouts/Makefile
++++ b/drivers/nvmem/layouts/Makefile
+@@ -4,3 +4,4 @@
+ #
+ obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o
++obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o
+--- /dev/null
++++ b/drivers/nvmem/layouts/onie-tlv.c
+@@ -0,0 +1,257 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * ONIE tlv NVMEM cells provider
++ *
++ * Copyright (C) 2022 Open Compute Group ONIE
++ * Author: Miquel Raynal <miquel.raynal@bootlin.com>
++ * Based on the nvmem driver written by: Vadym Kochan <vadym.kochan@plvision.eu>
++ * Inspired by the first layout written by: Rafał Miłecki <rafal@milecki.pl>
++ */
++
++#include <linux/crc32.h>
++#include <linux/etherdevice.h>
++#include <linux/nvmem-consumer.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of.h>
++
++#define ONIE_TLV_MAX_LEN 2048
++#define ONIE_TLV_CRC_FIELD_SZ 6
++#define ONIE_TLV_CRC_SZ 4
++#define ONIE_TLV_HDR_ID       "TlvInfo"
++
++struct onie_tlv_hdr {
++      u8 id[8];
++      u8 version;
++      __be16 data_len;
++} __packed;
++
++struct onie_tlv {
++      u8 type;
++      u8 len;
++} __packed;
++
++static const char *onie_tlv_cell_name(u8 type)
++{
++      switch (type) {
++      case 0x21:
++              return "product-name";
++      case 0x22:
++              return "part-number";
++      case 0x23:
++              return "serial-number";
++      case 0x24:
++              return "mac-address";
++      case 0x25:
++              return "manufacture-date";
++      case 0x26:
++              return "device-version";
++      case 0x27:
++              return "label-revision";
++      case 0x28:
++              return "platform-name";
++      case 0x29:
++              return "onie-version";
++      case 0x2A:
++              return "num-macs";
++      case 0x2B:
++              return "manufacturer";
++      case 0x2C:
++              return "country-code";
++      case 0x2D:
++              return "vendor";
++      case 0x2E:
++              return "diag-version";
++      case 0x2F:
++              return "service-tag";
++      case 0xFD:
++              return "vendor-extension";
++      case 0xFE:
++              return "crc32";
++      default:
++              break;
++      }
++
++      return NULL;
++}
++
++static int onie_tlv_mac_read_cb(void *priv, const char *id, int index,
++                              unsigned int offset, void *buf,
++                              size_t bytes)
++{
++      eth_addr_add(buf, index);
++
++      return 0;
++}
++
++static nvmem_cell_post_process_t onie_tlv_read_cb(u8 type, u8 *buf)
++{
++      switch (type) {
++      case 0x24:
++              return &onie_tlv_mac_read_cb;
++      default:
++              break;
++      }
++
++      return NULL;
++}
++
++static int onie_tlv_add_cells(struct device *dev, struct nvmem_device *nvmem,
++                            size_t data_len, u8 *data)
++{
++      struct nvmem_cell_info cell = {};
++      struct device_node *layout;
++      struct onie_tlv tlv;
++      unsigned int hdr_len = sizeof(struct onie_tlv_hdr);
++      unsigned int offset = 0;
++      int ret;
++
++      layout = of_nvmem_layout_get_container(nvmem);
++      if (!layout)
++              return -ENOENT;
++
++      while (offset < data_len) {
++              memcpy(&tlv, data + offset, sizeof(tlv));
++              if (offset + tlv.len >= data_len) {
++                      dev_err(dev, "Out of bounds field (0x%x bytes at 0x%x)\n",
++                              tlv.len, hdr_len + offset);
++                      break;
++              }
++
++              cell.name = onie_tlv_cell_name(tlv.type);
++              if (!cell.name)
++                      continue;
++
++              cell.offset = hdr_len + offset + sizeof(tlv.type) + sizeof(tlv.len);
++              cell.bytes = tlv.len;
++              cell.np = of_get_child_by_name(layout, cell.name);
++              cell.read_post_process = onie_tlv_read_cb(tlv.type, data + offset + sizeof(tlv));
++
++              ret = nvmem_add_one_cell(nvmem, &cell);
++              if (ret) {
++                      of_node_put(layout);
++                      return ret;
++              }
++
++              offset += sizeof(tlv) + tlv.len;
++      }
++
++      of_node_put(layout);
++
++      return 0;
++}
++
++static bool onie_tlv_hdr_is_valid(struct device *dev, struct onie_tlv_hdr *hdr)
++{
++      if (memcmp(hdr->id, ONIE_TLV_HDR_ID, sizeof(hdr->id))) {
++              dev_err(dev, "Invalid header\n");
++              return false;
++      }
++
++      if (hdr->version != 0x1) {
++              dev_err(dev, "Invalid version number\n");
++              return false;
++      }
++
++      return true;
++}
++
++static bool onie_tlv_crc_is_valid(struct device *dev, size_t table_len, u8 *table)
++{
++      struct onie_tlv crc_hdr;
++      u32 read_crc, calc_crc;
++      __be32 crc_be;
++
++      memcpy(&crc_hdr, table + table_len - ONIE_TLV_CRC_FIELD_SZ, sizeof(crc_hdr));
++      if (crc_hdr.type != 0xfe || crc_hdr.len != ONIE_TLV_CRC_SZ) {
++              dev_err(dev, "Invalid CRC field\n");
++              return false;
++      }
++
++      /* The table contains a JAMCRC, which is XOR'ed compared to the original
++       * CRC32 implementation as known in the Ethernet world.
++       */
++      memcpy(&crc_be, table + table_len - ONIE_TLV_CRC_SZ, ONIE_TLV_CRC_SZ);
++      read_crc = be32_to_cpu(crc_be);
++      calc_crc = crc32(~0, table, table_len - ONIE_TLV_CRC_SZ) ^ 0xFFFFFFFF;
++      if (read_crc != calc_crc) {
++              dev_err(dev, "Invalid CRC read: 0x%08x, expected: 0x%08x\n",
++                      read_crc, calc_crc);
++              return false;
++      }
++
++      return true;
++}
++
++static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem,
++                              struct nvmem_layout *layout)
++{
++      struct onie_tlv_hdr hdr;
++      size_t table_len, data_len, hdr_len;
++      u8 *table, *data;
++      int ret;
++
++      ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr);
++      if (ret < 0)
++              return ret;
++
++      if (!onie_tlv_hdr_is_valid(dev, &hdr)) {
++              dev_err(dev, "Invalid ONIE TLV header\n");
++              return -EINVAL;
++      }
++
++      hdr_len = sizeof(hdr.id) + sizeof(hdr.version) + sizeof(hdr.data_len);
++      data_len = be16_to_cpu(hdr.data_len);
++      table_len = hdr_len + data_len;
++      if (table_len > ONIE_TLV_MAX_LEN) {
++              dev_err(dev, "Invalid ONIE TLV data length\n");
++              return -EINVAL;
++      }
++
++      table = devm_kmalloc(dev, table_len, GFP_KERNEL);
++      if (!table)
++              return -ENOMEM;
++
++      ret = nvmem_device_read(nvmem, 0, table_len, table);
++      if (ret != table_len)
++              return ret;
++
++      if (!onie_tlv_crc_is_valid(dev, table_len, table))
++              return -EINVAL;
++
++      data = table + hdr_len;
++      ret = onie_tlv_add_cells(dev, nvmem, data_len, data);
++      if (ret)
++              return ret;
++
++      return 0;
++}
++
++static const struct of_device_id onie_tlv_of_match_table[] = {
++      { .compatible = "onie,tlv-layout", },
++      {},
++};
++MODULE_DEVICE_TABLE(of, onie_tlv_of_match_table);
++
++static struct nvmem_layout onie_tlv_layout = {
++      .name = "ONIE tlv layout",
++      .of_match_table = onie_tlv_of_match_table,
++      .add_cells = onie_tlv_parse_table,
++};
++
++static int __init onie_tlv_init(void)
++{
++      return nvmem_layout_register(&onie_tlv_layout);
++}
++
++static void __exit onie_tlv_exit(void)
++{
++      nvmem_layout_unregister(&onie_tlv_layout);
++}
++
++module_init(onie_tlv_init);
++module_exit(onie_tlv_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
++MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing");
++MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing");
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch b/target/linux/generic/backport-5.10/814-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch
new file mode 100644 (file)
index 0000000..94a0911
--- /dev/null
@@ -0,0 +1,32 @@
+From a4fb434ef96ace5af758ca2c52c3a3f8f3abc87c Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Date: Tue, 4 Apr 2023 18:21:34 +0100
+Subject: [PATCH] nvmem: stm32-romem: mark OF related data as maybe unused
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The driver can be compile tested with !CONFIG_OF making certain data
+unused:
+
+  drivers/nvmem/stm32-romem.c:271:34: error: ‘stm32_romem_of_match’ defined but not used [-Werror=unused-const-variable=]
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-27-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
+@@ -268,7 +268,7 @@ static const struct stm32_romem_cfg stm3
+       .ta = true,
+ };
+-static const struct of_device_id stm32_romem_of_match[] = {
++static const struct of_device_id stm32_romem_of_match[] __maybe_unused = {
+       { .compatible = "st,stm32f4-otp", }, {
+               .compatible = "st,stm32mp15-bsec",
+               .data = (void *)&stm32mp15_bsec_cfg,
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch b/target/linux/generic/backport-5.10/814-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch
new file mode 100644 (file)
index 0000000..abda402
--- /dev/null
@@ -0,0 +1,120 @@
+From de6e05097f7db066afb0ad4c88b730949f7b7749 Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Tue, 4 Apr 2023 18:21:35 +0100
+Subject: [PATCH] nvmem: mtk-efuse: Support postprocessing for GPU speed
+ binning data
+
+On some MediaTek SoCs GPU speed binning data is available for read
+in the SoC's eFuse array but it has a format that is incompatible
+with what the OPP API expects, as we read a number from 0 to 7 but
+opp-supported-hw is expecting a bitmask to enable an OPP entry:
+being what we read limited to 0-7, it's straightforward to simply
+convert the value to BIT(value) as a post-processing action.
+
+So, introduce post-processing support and enable it by evaluating
+the newly introduced platform data's `uses_post_processing` member,
+currently enabled only for MT8186.
+
+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/20230404172148.82422-28-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/mtk-efuse.c | 53 +++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 51 insertions(+), 2 deletions(-)
+
+--- a/drivers/nvmem/mtk-efuse.c
++++ b/drivers/nvmem/mtk-efuse.c
+@@ -10,6 +10,11 @@
+ #include <linux/io.h>
+ #include <linux/nvmem-provider.h>
+ #include <linux/platform_device.h>
++#include <linux/property.h>
++
++struct mtk_efuse_pdata {
++      bool uses_post_processing;
++};
+ struct mtk_efuse_priv {
+       void __iomem *base;
+@@ -29,6 +34,37 @@ static int mtk_reg_read(void *context,
+       return 0;
+ }
++static int mtk_efuse_gpu_speedbin_pp(void *context, const char *id, int index,
++                                   unsigned int offset, void *data, size_t bytes)
++{
++      u8 *val = data;
++
++      if (val[0] < 8)
++              val[0] = BIT(val[0]);
++
++      return 0;
++}
++
++static void mtk_efuse_fixup_cell_info(struct nvmem_device *nvmem,
++                                    struct nvmem_layout *layout,
++                                    struct nvmem_cell_info *cell)
++{
++      size_t sz = strlen(cell->name);
++
++      /*
++       * On some SoCs, the GPU speedbin is not read as bitmask but as
++       * a number with range [0-7] (max 3 bits): post process to use
++       * it in OPP tables to describe supported-hw.
++       */
++      if (cell->nbits <= 3 &&
++          strncmp(cell->name, "gpu-speedbin", min(sz, strlen("gpu-speedbin"))) == 0)
++              cell->read_post_process = mtk_efuse_gpu_speedbin_pp;
++}
++
++static struct nvmem_layout mtk_efuse_layout = {
++      .fixup_cell_info = mtk_efuse_fixup_cell_info,
++};
++
+ static int mtk_efuse_probe(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+@@ -36,6 +72,7 @@ static int mtk_efuse_probe(struct platfo
+       struct nvmem_device *nvmem;
+       struct nvmem_config econfig = {};
+       struct mtk_efuse_priv *priv;
++      const struct mtk_efuse_pdata *pdata;
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+@@ -45,20 +82,32 @@ static int mtk_efuse_probe(struct platfo
+       if (IS_ERR(priv->base))
+               return PTR_ERR(priv->base);
++      pdata = device_get_match_data(dev);
+       econfig.stride = 1;
+       econfig.word_size = 1;
+       econfig.reg_read = mtk_reg_read;
+       econfig.size = resource_size(res);
+       econfig.priv = priv;
+       econfig.dev = dev;
++      if (pdata->uses_post_processing)
++              econfig.layout = &mtk_efuse_layout;
+       nvmem = devm_nvmem_register(dev, &econfig);
+       return PTR_ERR_OR_ZERO(nvmem);
+ }
++static const struct mtk_efuse_pdata mtk_mt8186_efuse_pdata = {
++      .uses_post_processing = true,
++};
++
++static const struct mtk_efuse_pdata mtk_efuse_pdata = {
++      .uses_post_processing = false,
++};
++
+ static const struct of_device_id mtk_efuse_of_match[] = {
+-      { .compatible = "mediatek,mt8173-efuse",},
+-      { .compatible = "mediatek,efuse",},
++      { .compatible = "mediatek,mt8173-efuse", .data = &mtk_efuse_pdata },
++      { .compatible = "mediatek,mt8186-efuse", .data = &mtk_mt8186_efuse_pdata },
++      { .compatible = "mediatek,efuse", .data = &mtk_efuse_pdata },
+       {/* sentinel */},
+ };
+ MODULE_DEVICE_TABLE(of, mtk_efuse_of_match);
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch b/target/linux/generic/backport-5.10/814-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch
new file mode 100644 (file)
index 0000000..a0874f7
--- /dev/null
@@ -0,0 +1,39 @@
+From 1dc552fa33cf98af3e784dbc0500da93cae3b24a Mon Sep 17 00:00:00 2001
+From: Yang Li <yang.lee@linux.alibaba.com>
+Date: Tue, 4 Apr 2023 18:21:38 +0100
+Subject: [PATCH] nvmem: bcm-ocotp: Use devm_platform_ioremap_resource()
+
+According to commit 7945f929f1a7 ("drivers: provide
+devm_platform_ioremap_resource()"), convert platform_get_resource(),
+devm_ioremap_resource() to a single call to use
+devm_platform_ioremap_resource(), as this is exactly what this function
+does.
+
+Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-31-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/bcm-ocotp.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/nvmem/bcm-ocotp.c
++++ b/drivers/nvmem/bcm-ocotp.c
+@@ -254,7 +254,6 @@ MODULE_DEVICE_TABLE(acpi, bcm_otpc_acpi_
+ static int bcm_otpc_probe(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+-      struct resource *res;
+       struct otpc_priv *priv;
+       struct nvmem_device *nvmem;
+       int err;
+@@ -269,8 +268,7 @@ static int bcm_otpc_probe(struct platfor
+               return -ENODEV;
+       /* Get OTP base address register. */
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      priv->base = devm_ioremap_resource(dev, res);
++      priv->base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(priv->base)) {
+               dev_err(dev, "unable to map I/O memory\n");
+               return PTR_ERR(priv->base);
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch b/target/linux/generic/backport-5.10/814-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch
new file mode 100644 (file)
index 0000000..890dacd
--- /dev/null
@@ -0,0 +1,39 @@
+From 649409990d2e93fac657be7c6960c28a2c601d65 Mon Sep 17 00:00:00 2001
+From: Yang Li <yang.lee@linux.alibaba.com>
+Date: Tue, 4 Apr 2023 18:21:39 +0100
+Subject: [PATCH] nvmem: nintendo-otp: Use devm_platform_ioremap_resource()
+
+According to commit 7945f929f1a7 ("drivers: provide
+devm_platform_ioremap_resource()"), convert platform_get_resource(),
+devm_ioremap_resource() to a single call to use
+devm_platform_ioremap_resource(), as this is exactly what this function
+does.
+
+Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-32-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/nintendo-otp.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/nvmem/nintendo-otp.c
++++ b/drivers/nvmem/nintendo-otp.c
+@@ -76,7 +76,6 @@ static int nintendo_otp_probe(struct pla
+       struct device *dev = &pdev->dev;
+       const struct of_device_id *of_id =
+               of_match_device(nintendo_otp_of_table, dev);
+-      struct resource *res;
+       struct nvmem_device *nvmem;
+       struct nintendo_otp_priv *priv;
+@@ -92,8 +91,7 @@ static int nintendo_otp_probe(struct pla
+       if (!priv)
+               return -ENOMEM;
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      priv->regs = devm_ioremap_resource(dev, res);
++      priv->regs = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(priv->regs))
+               return PTR_ERR(priv->regs);
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch b/target/linux/generic/backport-5.10/814-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch
new file mode 100644 (file)
index 0000000..3f5d3c1
--- /dev/null
@@ -0,0 +1,32 @@
+From c2367aa60d5e34d48582362c6de34b4131d92be7 Mon Sep 17 00:00:00 2001
+From: Yang Li <yang.lee@linux.alibaba.com>
+Date: Tue, 4 Apr 2023 18:21:40 +0100
+Subject: [PATCH] nvmem: vf610-ocotp: Use
+ devm_platform_get_and_ioremap_resource()
+
+According to commit 890cc39a8799 ("drivers: provide
+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.
+
+Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-33-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/vf610-ocotp.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/nvmem/vf610-ocotp.c
++++ b/drivers/nvmem/vf610-ocotp.c
+@@ -219,8 +219,7 @@ static int vf610_ocotp_probe(struct plat
+       if (!ocotp_dev)
+               return -ENOMEM;
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      ocotp_dev->base = devm_ioremap_resource(dev, res);
++      ocotp_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+       if (IS_ERR(ocotp_dev->base))
+               return PTR_ERR(ocotp_dev->base);
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch b/target/linux/generic/backport-5.10/814-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch
new file mode 100644 (file)
index 0000000..eeb407e
--- /dev/null
@@ -0,0 +1,115 @@
+From 55d4980ce55b6bb4be66877de4dbec513911b988 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Tue, 4 Apr 2023 18:21:42 +0100
+Subject: [PATCH] nvmem: core: support specifying both: cell raw data & post
+ read lengths
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Callback .read_post_process() is designed to modify raw cell content
+before providing it to the consumer. So far we were dealing with
+modifications that didn't affect cell size (length). In some cases
+however cell content needs to be reformatted and resized.
+
+It's required e.g. to provide properly formatted MAC address in case
+it's stored in a non-binary format (e.g. using ASCII).
+
+There were few discussions how to optimally handle that. Following
+possible solutions were considered:
+1. Allow .read_post_process() to realloc (resize) content buffer
+2. Allow .read_post_process() to adjust (decrease) just buffer length
+3. Register NVMEM cells using post-read sizes
+
+The preferred solution was the last one. The problem is that simply
+adjusting "bytes" in NVMEM providers would result in core code NOT
+passing whole raw data to .read_post_process() callbacks. It means
+callback functions couldn't do their job without somehow manually
+reading original cell content on their own.
+
+This patch deals with that by registering NVMEM cells with both lengths:
+raw content one and post read one. It allows:
+1. Core code to read whole raw cell content
+2. Callbacks to return content they want
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-35-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c           | 11 +++++++----
+ include/linux/nvmem-provider.h |  2 ++
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -50,6 +50,7 @@ struct nvmem_device {
+ struct nvmem_cell_entry {
+       const char              *name;
+       int                     offset;
++      size_t                  raw_len;
+       int                     bytes;
+       int                     bit_offset;
+       int                     nbits;
+@@ -469,6 +470,7 @@ static int nvmem_cell_info_to_nvmem_cell
+ {
+       cell->nvmem = nvmem;
+       cell->offset = info->offset;
++      cell->raw_len = info->raw_len ?: info->bytes;
+       cell->bytes = info->bytes;
+       cell->name = info->name;
+       cell->read_post_process = info->read_post_process;
+@@ -1560,7 +1562,7 @@ static int __nvmem_cell_read(struct nvme
+ {
+       int rc;
+-      rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes);
++      rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->raw_len);
+       if (rc)
+               return rc;
+@@ -1571,7 +1573,7 @@ static int __nvmem_cell_read(struct nvme
+       if (cell->read_post_process) {
+               rc = cell->read_post_process(cell->priv, id, index,
+-                                           cell->offset, buf, cell->bytes);
++                                           cell->offset, buf, cell->raw_len);
+               if (rc)
+                       return rc;
+       }
+@@ -1594,14 +1596,15 @@ static int __nvmem_cell_read(struct nvme
+  */
+ void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
+ {
+-      struct nvmem_device *nvmem = cell->entry->nvmem;
++      struct nvmem_cell_entry *entry = cell->entry;
++      struct nvmem_device *nvmem = entry->nvmem;
+       u8 *buf;
+       int rc;
+       if (!nvmem)
+               return ERR_PTR(-EINVAL);
+-      buf = kzalloc(cell->entry->bytes, GFP_KERNEL);
++      buf = kzalloc(max_t(size_t, entry->raw_len, entry->bytes), GFP_KERNEL);
+       if (!buf)
+               return ERR_PTR(-ENOMEM);
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -51,6 +51,7 @@ struct nvmem_keepout {
+  * struct nvmem_cell_info - NVMEM cell description
+  * @name:     Name.
+  * @offset:   Offset within the NVMEM device.
++ * @raw_len:  Length of raw data (without post processing).
+  * @bytes:    Length of the cell.
+  * @bit_offset:       Bit offset if cell is smaller than a byte.
+  * @nbits:    Number of bits.
+@@ -62,6 +63,7 @@ struct nvmem_keepout {
+ struct nvmem_cell_info {
+       const char              *name;
+       unsigned int            offset;
++      size_t                  raw_len;
+       unsigned int            bytes;
+       unsigned int            bit_offset;
+       unsigned int            nbits;
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch b/target/linux/generic/backport-5.10/814-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch
new file mode 100644 (file)
index 0000000..7c6fe22
--- /dev/null
@@ -0,0 +1,42 @@
+From 814c978f02db17f16e6aa2efa2a929372f06da09 Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Tue, 4 Apr 2023 18:21:44 +0100
+Subject: [PATCH] nvmem: Add macro to register nvmem layout drivers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Provide a module_nvmem_layout_driver() macro at the end of the
+nvmem-provider.h header to reduce the boilerplate when registering nvmem
+layout drivers.
+
+Suggested-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Acked-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-37-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/nvmem-provider.h | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -9,6 +9,7 @@
+ #ifndef _LINUX_NVMEM_PROVIDER_H
+ #define _LINUX_NVMEM_PROVIDER_H
++#include <linux/device/driver.h>
+ #include <linux/err.h>
+ #include <linux/errno.h>
+ #include <linux/gpio/consumer.h>
+@@ -242,4 +243,9 @@ nvmem_layout_get_match_data(struct nvmem
+ }
+ #endif /* CONFIG_NVMEM */
++
++#define module_nvmem_layout_driver(__layout_driver)           \
++      module_driver(__layout_driver, nvmem_layout_register,   \
++                    nvmem_layout_unregister)
++
+ #endif  /* ifndef _LINUX_NVMEM_PROVIDER_H */
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch b/target/linux/generic/backport-5.10/814-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch
new file mode 100644 (file)
index 0000000..06646dd
--- /dev/null
@@ -0,0 +1,39 @@
+From 0abdf99fe0c86252ba274703425f8d543d7e7f0d Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Tue, 4 Apr 2023 18:21:45 +0100
+Subject: [PATCH] nvmem: layouts: sl28vpd: Use module_nvmem_layout_driver()
+
+Stop open-coding the module init/exit functions. Use the
+module_nvmem_layout_driver() instead.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-38-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/layouts/sl28vpd.c | 14 +-------------
+ 1 file changed, 1 insertion(+), 13 deletions(-)
+
+--- a/drivers/nvmem/layouts/sl28vpd.c
++++ b/drivers/nvmem/layouts/sl28vpd.c
+@@ -146,19 +146,7 @@ struct nvmem_layout sl28vpd_layout = {
+       .of_match_table = sl28vpd_of_match_table,
+       .add_cells = sl28vpd_add_cells,
+ };
+-
+-static int __init sl28vpd_init(void)
+-{
+-      return nvmem_layout_register(&sl28vpd_layout);
+-}
+-
+-static void __exit sl28vpd_exit(void)
+-{
+-      nvmem_layout_unregister(&sl28vpd_layout);
+-}
+-
+-module_init(sl28vpd_init);
+-module_exit(sl28vpd_exit);
++module_nvmem_layout_driver(sl28vpd_layout);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch b/target/linux/generic/backport-5.10/814-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch
new file mode 100644 (file)
index 0000000..826f437
--- /dev/null
@@ -0,0 +1,39 @@
+From d119eb38faab61125aaa4f63c74eef61585cf34c Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Tue, 4 Apr 2023 18:21:46 +0100
+Subject: [PATCH] nvmem: layouts: onie-tlv: Use module_nvmem_layout_driver()
+
+Stop open-coding the module init/exit functions. Use the
+module_nvmem_layout_driver() instead.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-39-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/layouts/onie-tlv.c | 14 +-------------
+ 1 file changed, 1 insertion(+), 13 deletions(-)
+
+--- a/drivers/nvmem/layouts/onie-tlv.c
++++ b/drivers/nvmem/layouts/onie-tlv.c
+@@ -237,19 +237,7 @@ static struct nvmem_layout onie_tlv_layo
+       .of_match_table = onie_tlv_of_match_table,
+       .add_cells = onie_tlv_parse_table,
+ };
+-
+-static int __init onie_tlv_init(void)
+-{
+-      return nvmem_layout_register(&onie_tlv_layout);
+-}
+-
+-static void __exit onie_tlv_exit(void)
+-{
+-      nvmem_layout_unregister(&onie_tlv_layout);
+-}
+-
+-module_init(onie_tlv_init);
+-module_exit(onie_tlv_exit);
++module_nvmem_layout_driver(onie_tlv_layout);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch b/target/linux/generic/backport-5.10/814-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch
new file mode 100644 (file)
index 0000000..f20db85
--- /dev/null
@@ -0,0 +1,24 @@
+From 6b13e4b6a9a45028ac730e550380077df1845912 Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Tue, 4 Apr 2023 18:21:47 +0100
+Subject: [PATCH] nvmem: layouts: onie-tlv: Drop wrong module alias
+
+The MODULE_ALIAS macro is misused here as it carries the
+description. There is currently no relevant alias to provide so let's
+just drop it.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-40-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/layouts/onie-tlv.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/nvmem/layouts/onie-tlv.c
++++ b/drivers/nvmem/layouts/onie-tlv.c
+@@ -242,4 +242,3 @@ module_nvmem_layout_driver(onie_tlv_layo
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
+ MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing");
+-MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing");
diff --git a/target/linux/generic/backport-5.10/814-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch b/target/linux/generic/backport-5.10/814-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch
new file mode 100644 (file)
index 0000000..5cf847b
--- /dev/null
@@ -0,0 +1,31 @@
+From a8642cd11635a35a5f1dc31857887900d6610778 Mon Sep 17 00:00:00 2001
+From: Tom Rix <trix@redhat.com>
+Date: Tue, 4 Apr 2023 18:21:48 +0100
+Subject: [PATCH] nvmem: layouts: sl28vpd: set varaiable sl28vpd_layout
+ storage-class-specifier to static
+
+smatch reports
+drivers/nvmem/layouts/sl28vpd.c:144:21: warning: symbol
+  'sl28vpd_layout' was not declared. Should it be static?
+
+This variable is only used in one file so it should be static.
+
+Signed-off-by: Tom Rix <trix@redhat.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-41-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/layouts/sl28vpd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/layouts/sl28vpd.c
++++ b/drivers/nvmem/layouts/sl28vpd.c
+@@ -141,7 +141,7 @@ static const struct of_device_id sl28vpd
+ };
+ MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table);
+-struct nvmem_layout sl28vpd_layout = {
++static struct nvmem_layout sl28vpd_layout = {
+       .name = "sl28-vpd",
+       .of_match_table = sl28vpd_of_match_table,
+       .add_cells = sl28vpd_add_cells,
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch b/target/linux/generic/backport-5.15/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch
new file mode 100644 (file)
index 0000000..8328e87
--- /dev/null
@@ -0,0 +1,35 @@
+From bcd1fe07def0f070eb5f31594620aaee6f81d31a Mon Sep 17 00:00:00 2001
+From: Nick Alcock <nick.alcock@oracle.com>
+Date: Tue, 4 Apr 2023 18:21:11 +0100
+Subject: [PATCH] nvmem: xilinx: zynqmp: make modular
+
+This driver has a MODULE_LICENSE but is not tristate so cannot be
+built as a module, unlike all its peers: make it modular to match.
+
+Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
+Suggested-by: Michal Simek <michal.simek@amd.com>
+Cc: Luis Chamberlain <mcgrof@kernel.org>
+Cc: linux-modules@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org
+Cc: Hitomi Hasegawa <hasegawa-hitomi@fujitsu.com>
+Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Cc: Michal Simek <michal.simek@xilinx.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-4-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
+@@ -368,7 +368,7 @@ config NVMEM_VF610_OCOTP
+         be called nvmem-vf610-ocotp.
+ config NVMEM_ZYNQMP
+-      bool "Xilinx ZYNQMP SoC nvmem firmware support"
++      tristate "Xilinx ZYNQMP SoC nvmem firmware support"
+       depends on ARCH_ZYNQMP
+       help
+         This is a driver to access hardware related data like
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch b/target/linux/generic/backport-5.15/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch
new file mode 100644 (file)
index 0000000..23518d2
--- /dev/null
@@ -0,0 +1,387 @@
+From 266570f496b90dea8fda893c2cf7c28d63ae2bd9 Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Tue, 4 Apr 2023 18:21:21 +0100
+Subject: [PATCH] nvmem: core: introduce NVMEM layouts
+
+NVMEM layouts are used to generate NVMEM cells during runtime. Think of
+an EEPROM with a well-defined conent. For now, the content can be
+described by a device tree or a board file. But this only works if the
+offsets and lengths are static and don't change. One could also argue
+that putting the layout of the EEPROM in the device tree is the wrong
+place. Instead, the device tree should just have a specific compatible
+string.
+
+Right now there are two use cases:
+ (1) The NVMEM cell needs special processing. E.g. if it only specifies
+     a base MAC address offset and you need to add an offset, or it
+     needs to parse a MAC from ASCII format or some proprietary format.
+     (Post processing of cells is added in a later commit).
+ (2) u-boot environment parsing. The cells don't have a particular
+     offset but it needs parsing the content to determine the offsets
+     and length.
+
+Co-developed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-14-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/driver-api/nvmem.rst |  15 ++++
+ drivers/nvmem/Kconfig              |   4 +
+ drivers/nvmem/Makefile             |   1 +
+ drivers/nvmem/core.c               | 120 +++++++++++++++++++++++++++++
+ drivers/nvmem/layouts/Kconfig      |   5 ++
+ drivers/nvmem/layouts/Makefile     |   4 +
+ include/linux/nvmem-consumer.h     |   7 ++
+ include/linux/nvmem-provider.h     |  51 ++++++++++++
+ 8 files changed, 207 insertions(+)
+ create mode 100644 drivers/nvmem/layouts/Kconfig
+ create mode 100644 drivers/nvmem/layouts/Makefile
+
+--- a/Documentation/driver-api/nvmem.rst
++++ b/Documentation/driver-api/nvmem.rst
+@@ -189,3 +189,18 @@ ex::
+ =====================
+ See Documentation/devicetree/bindings/nvmem/nvmem.txt
++
++8. NVMEM layouts
++================
++
++NVMEM layouts are yet another mechanism to create cells. With the device
++tree binding it is possible to specify simple cells by using an offset
++and a length. Sometimes, the cells doesn't have a static offset, but
++the content is still well defined, e.g. tag-length-values. In this case,
++the NVMEM device content has to be first parsed and the cells need to
++be added accordingly. Layouts let you read the content of the NVMEM device
++and let you add cells dynamically.
++
++Another use case for layouts is the post processing of cells. With layouts,
++it is possible to associate a custom post processing hook to a cell. It
++even possible to add this hook to cells not created by the layout itself.
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -21,6 +21,10 @@ config NVMEM_SYSFS
+        This interface is mostly used by userspace applications to
+        read/write directly into nvmem.
++# Layouts
++
++source "drivers/nvmem/layouts/Kconfig"
++
+ # Devices
+ config NVMEM_APPLE_EFUSES
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -5,6 +5,7 @@
+ obj-$(CONFIG_NVMEM)           += nvmem_core.o
+ nvmem_core-y                  := core.o
++obj-y                         += layouts/
+ # Devices
+ obj-$(CONFIG_NVMEM_APPLE_EFUSES)      += nvmem-apple-efuses.o
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -40,6 +40,7 @@ struct nvmem_device {
+       nvmem_reg_write_t       reg_write;
+       nvmem_cell_post_process_t cell_post_process;
+       struct gpio_desc        *wp_gpio;
++      struct nvmem_layout     *layout;
+       void *priv;
+ };
+@@ -74,6 +75,9 @@ static LIST_HEAD(nvmem_lookup_list);
+ static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
++static DEFINE_SPINLOCK(nvmem_layout_lock);
++static LIST_HEAD(nvmem_layouts);
++
+ static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
+                           void *val, size_t bytes)
+ {
+@@ -728,6 +732,101 @@ static int nvmem_add_cells_from_of(struc
+       return 0;
+ }
++int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner)
++{
++      layout->owner = owner;
++
++      spin_lock(&nvmem_layout_lock);
++      list_add(&layout->node, &nvmem_layouts);
++      spin_unlock(&nvmem_layout_lock);
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(__nvmem_layout_register);
++
++void nvmem_layout_unregister(struct nvmem_layout *layout)
++{
++      spin_lock(&nvmem_layout_lock);
++      list_del(&layout->node);
++      spin_unlock(&nvmem_layout_lock);
++}
++EXPORT_SYMBOL_GPL(nvmem_layout_unregister);
++
++static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem)
++{
++      struct device_node *layout_np, *np = nvmem->dev.of_node;
++      struct nvmem_layout *l, *layout = NULL;
++
++      layout_np = of_get_child_by_name(np, "nvmem-layout");
++      if (!layout_np)
++              return NULL;
++
++      spin_lock(&nvmem_layout_lock);
++
++      list_for_each_entry(l, &nvmem_layouts, node) {
++              if (of_match_node(l->of_match_table, layout_np)) {
++                      if (try_module_get(l->owner))
++                              layout = l;
++
++                      break;
++              }
++      }
++
++      spin_unlock(&nvmem_layout_lock);
++      of_node_put(layout_np);
++
++      return layout;
++}
++
++static void nvmem_layout_put(struct nvmem_layout *layout)
++{
++      if (layout)
++              module_put(layout->owner);
++}
++
++static int nvmem_add_cells_from_layout(struct nvmem_device *nvmem)
++{
++      struct nvmem_layout *layout = nvmem->layout;
++      int ret;
++
++      if (layout && layout->add_cells) {
++              ret = layout->add_cells(&nvmem->dev, nvmem, layout);
++              if (ret)
++                      return ret;
++      }
++
++      return 0;
++}
++
++#if IS_ENABLED(CONFIG_OF)
++/**
++ * of_nvmem_layout_get_container() - Get OF node to layout container.
++ *
++ * @nvmem: nvmem device.
++ *
++ * Return: a node pointer with refcount incremented or NULL if no
++ * container exists. Use of_node_put() on it when done.
++ */
++struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem)
++{
++      return of_get_child_by_name(nvmem->dev.of_node, "nvmem-layout");
++}
++EXPORT_SYMBOL_GPL(of_nvmem_layout_get_container);
++#endif
++
++const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem,
++                                      struct nvmem_layout *layout)
++{
++      struct device_node __maybe_unused *layout_np;
++      const struct of_device_id *match;
++
++      layout_np = of_nvmem_layout_get_container(nvmem);
++      match = of_match_node(layout->of_match_table, layout_np);
++
++      return match ? match->data : NULL;
++}
++EXPORT_SYMBOL_GPL(nvmem_layout_get_match_data);
++
+ /**
+  * nvmem_register() - Register a nvmem device for given nvmem_config.
+  * Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
+@@ -834,6 +933,12 @@ struct nvmem_device *nvmem_register(cons
+                       goto err_put_device;
+       }
++      /*
++       * If the driver supplied a layout by config->layout, the module
++       * pointer will be NULL and nvmem_layout_put() will be a noop.
++       */
++      nvmem->layout = config->layout ?: nvmem_layout_get(nvmem);
++
+       if (config->cells) {
+               rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
+               if (rval)
+@@ -854,12 +959,17 @@ struct nvmem_device *nvmem_register(cons
+       if (rval)
+               goto err_remove_cells;
++      rval = nvmem_add_cells_from_layout(nvmem);
++      if (rval)
++              goto err_remove_cells;
++
+       blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
+       return nvmem;
+ err_remove_cells:
+       nvmem_device_remove_all_cells(nvmem);
++      nvmem_layout_put(nvmem->layout);
+       if (config->compat)
+               nvmem_sysfs_remove_compat(nvmem, config);
+ err_put_device:
+@@ -881,6 +991,7 @@ static void nvmem_device_release(struct
+               device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
+       nvmem_device_remove_all_cells(nvmem);
++      nvmem_layout_put(nvmem->layout);
+       device_unregister(&nvmem->dev);
+ }
+@@ -1246,6 +1357,15 @@ struct nvmem_cell *of_nvmem_cell_get(str
+               return ERR_PTR(-EINVAL);
+       }
++      /* nvmem layouts produce cells within the nvmem-layout container */
++      if (of_node_name_eq(nvmem_np, "nvmem-layout")) {
++              nvmem_np = of_get_next_parent(nvmem_np);
++              if (!nvmem_np) {
++                      of_node_put(cell_np);
++                      return ERR_PTR(-EINVAL);
++              }
++      }
++
+       nvmem = __nvmem_device_get(nvmem_np, device_match_of_node);
+       of_node_put(nvmem_np);
+       if (IS_ERR(nvmem)) {
+--- /dev/null
++++ b/drivers/nvmem/layouts/Kconfig
+@@ -0,0 +1,5 @@
++# SPDX-License-Identifier: GPL-2.0
++
++menu "Layout Types"
++
++endmenu
+--- /dev/null
++++ b/drivers/nvmem/layouts/Makefile
+@@ -0,0 +1,4 @@
++# SPDX-License-Identifier: GPL-2.0
++#
++# Makefile for nvmem layouts.
++#
+--- a/include/linux/nvmem-consumer.h
++++ b/include/linux/nvmem-consumer.h
+@@ -239,6 +239,7 @@ struct nvmem_cell *of_nvmem_cell_get(str
+                                    const char *id);
+ struct nvmem_device *of_nvmem_device_get(struct device_node *np,
+                                        const char *name);
++struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem);
+ #else
+ static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+                                                  const char *id)
+@@ -251,6 +252,12 @@ static inline struct nvmem_device *of_nv
+ {
+       return ERR_PTR(-EOPNOTSUPP);
+ }
++
++static inline struct device_node *
++of_nvmem_layout_get_container(struct nvmem_device *nvmem)
++{
++      return ERR_PTR(-EOPNOTSUPP);
++}
+ #endif /* CONFIG_NVMEM && CONFIG_OF */
+ #endif  /* ifndef _LINUX_NVMEM_CONSUMER_H */
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -88,6 +88,7 @@ struct nvmem_cell_info {
+  * @stride:   Minimum read/write access stride.
+  * @priv:     User context passed to read/write callbacks.
+  * @ignore_wp:  Write Protect pin is managed by the provider.
++ * @layout:   Fixed layout associated with this nvmem device.
+  *
+  * 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
+@@ -109,6 +110,7 @@ struct nvmem_config {
+       bool                    read_only;
+       bool                    root_only;
+       bool                    ignore_wp;
++      struct nvmem_layout     *layout;
+       struct device_node      *of_node;
+       bool                    no_of_node;
+       nvmem_reg_read_t        reg_read;
+@@ -142,6 +144,33 @@ struct nvmem_cell_table {
+       struct list_head        node;
+ };
++/**
++ * struct nvmem_layout - NVMEM layout definitions
++ *
++ * @name:             Layout name.
++ * @of_match_table:   Open firmware match table.
++ * @add_cells:                Will be called if a nvmem device is found which
++ *                    has this layout. The function will add layout
++ *                    specific cells with nvmem_add_one_cell().
++ * @owner:            Pointer to struct module.
++ * @node:             List node.
++ *
++ * A nvmem device can hold a well defined structure which can just be
++ * evaluated during runtime. For example a TLV list, or a list of "name=val"
++ * pairs. A nvmem layout can parse the nvmem device and add appropriate
++ * cells.
++ */
++struct nvmem_layout {
++      const char *name;
++      const struct of_device_id *of_match_table;
++      int (*add_cells)(struct device *dev, struct nvmem_device *nvmem,
++                       struct nvmem_layout *layout);
++
++      /* private */
++      struct module *owner;
++      struct list_head node;
++};
++
+ #if IS_ENABLED(CONFIG_NVMEM)
+ struct nvmem_device *nvmem_register(const struct nvmem_config *cfg);
+@@ -156,6 +185,14 @@ void nvmem_del_cell_table(struct nvmem_c
+ int nvmem_add_one_cell(struct nvmem_device *nvmem,
+                      const struct nvmem_cell_info *info);
++int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner);
++#define nvmem_layout_register(layout) \
++      __nvmem_layout_register(layout, THIS_MODULE)
++void nvmem_layout_unregister(struct nvmem_layout *layout);
++
++const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem,
++                                      struct nvmem_layout *layout);
++
+ #else
+ static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c)
+@@ -179,5 +216,19 @@ static inline int nvmem_add_one_cell(str
+       return -EOPNOTSUPP;
+ }
++static inline int nvmem_layout_register(struct nvmem_layout *layout)
++{
++      return -EOPNOTSUPP;
++}
++
++static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {}
++
++static inline const void *
++nvmem_layout_get_match_data(struct nvmem_device *nvmem,
++                          struct nvmem_layout *layout)
++{
++      return NULL;
++}
++
+ #endif /* CONFIG_NVMEM */
+ #endif  /* ifndef _LINUX_NVMEM_PROVIDER_H */
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch b/target/linux/generic/backport-5.15/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch
new file mode 100644 (file)
index 0000000..6fa7b63
--- /dev/null
@@ -0,0 +1,61 @@
+From 6468a6f45148fb5e95c86b4efebf63f9abcd2137 Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Tue, 4 Apr 2023 18:21:22 +0100
+Subject: [PATCH] nvmem: core: handle the absence of expected layouts
+
+Make nvmem_layout_get() return -EPROBE_DEFER while the expected layout
+is not available. This condition cannot be triggered today as nvmem
+layout drivers are initialed as part of an early init call, but soon
+these drivers will be converted into modules and be initialized with a
+standard priority, so the unavailability of the drivers might become a
+reality that must be taken care of.
+
+Let's anticipate this by telling the caller the layout might not yet be
+available. A probe deferral is requested in this case.
+
+Please note this does not affect any nvmem device not using layouts,
+because an early check against the "nvmem-layout" container presence
+will return NULL in this case.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Tested-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-15-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -755,7 +755,7 @@ EXPORT_SYMBOL_GPL(nvmem_layout_unregiste
+ static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem)
+ {
+       struct device_node *layout_np, *np = nvmem->dev.of_node;
+-      struct nvmem_layout *l, *layout = NULL;
++      struct nvmem_layout *l, *layout = ERR_PTR(-EPROBE_DEFER);
+       layout_np = of_get_child_by_name(np, "nvmem-layout");
+       if (!layout_np)
+@@ -938,6 +938,13 @@ struct nvmem_device *nvmem_register(cons
+        * pointer will be NULL and nvmem_layout_put() will be a noop.
+        */
+       nvmem->layout = config->layout ?: nvmem_layout_get(nvmem);
++      if (IS_ERR(nvmem->layout)) {
++              rval = PTR_ERR(nvmem->layout);
++              nvmem->layout = NULL;
++
++              if (rval == -EPROBE_DEFER)
++                      goto err_teardown_compat;
++      }
+       if (config->cells) {
+               rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
+@@ -970,6 +977,7 @@ struct nvmem_device *nvmem_register(cons
+ err_remove_cells:
+       nvmem_device_remove_all_cells(nvmem);
+       nvmem_layout_put(nvmem->layout);
++err_teardown_compat:
+       if (config->compat)
+               nvmem_sysfs_remove_compat(nvmem, config);
+ err_put_device:
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch b/target/linux/generic/backport-5.15/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch
new file mode 100644 (file)
index 0000000..b934166
--- /dev/null
@@ -0,0 +1,52 @@
+From b1c37bec1ccfe5ccab72bc0ddc0dfa45c43e2de2 Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Tue, 4 Apr 2023 18:21:23 +0100
+Subject: [PATCH] nvmem: core: request layout modules loading
+
+When a storage device like an eeprom or an mtd device probes, it
+registers an nvmem device if the nvmem subsystem has been enabled (bool
+symbol). During nvmem registration, if the device is using layouts to
+expose dynamic nvmem cells, the core will first try to get a reference
+over the layout driver callbacks. In practice there is not relationship
+that can be described between the storage driver and the nvmem
+layout. So there is no way we can enforce both drivers will be built-in
+or both will be modules. If the storage device driver is built-in but
+the layout is built as a module, instead of badly failing with an
+endless probe deferral loop, lets just make a modprobe call in case the
+driver was made available in an initramfs with
+of_device_node_request_module(), and offer a fully functional system to
+the user.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Tested-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-16-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -17,6 +17,7 @@
+ #include <linux/nvmem-provider.h>
+ #include <linux/gpio/consumer.h>
+ #include <linux/of.h>
++#include <linux/of_device.h>
+ #include <linux/slab.h>
+ struct nvmem_device {
+@@ -761,6 +762,13 @@ static struct nvmem_layout *nvmem_layout
+       if (!layout_np)
+               return NULL;
++      /*
++       * In case the nvmem device was built-in while the layout was built as a
++       * module, we shall manually request the layout driver loading otherwise
++       * we'll never have any match.
++       */
++      of_request_module(layout_np);
++
+       spin_lock(&nvmem_layout_lock);
+       list_for_each_entry(l, &nvmem_layouts, node) {
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch b/target/linux/generic/backport-5.15/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch
new file mode 100644 (file)
index 0000000..53628cd
--- /dev/null
@@ -0,0 +1,86 @@
+From 345ec382cd4b736c36e01f155d08c913b225b736 Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Tue, 4 Apr 2023 18:21:24 +0100
+Subject: [PATCH] nvmem: core: add per-cell post processing
+
+Instead of relying on the name the consumer is using for the cell, like
+it is done for the nvmem .cell_post_process configuration parameter,
+provide a per-cell post processing hook. This can then be populated by
+the NVMEM provider (or the NVMEM layout) when adding the cell.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-17-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c           | 17 +++++++++++++++++
+ include/linux/nvmem-provider.h |  3 +++
+ 2 files changed, 20 insertions(+)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -54,6 +54,7 @@ struct nvmem_cell_entry {
+       int                     bytes;
+       int                     bit_offset;
+       int                     nbits;
++      nvmem_cell_post_process_t read_post_process;
+       struct device_node      *np;
+       struct nvmem_device     *nvmem;
+       struct list_head        node;
+@@ -470,6 +471,7 @@ static int nvmem_cell_info_to_nvmem_cell
+       cell->offset = info->offset;
+       cell->bytes = info->bytes;
+       cell->name = info->name;
++      cell->read_post_process = info->read_post_process;
+       cell->bit_offset = info->bit_offset;
+       cell->nbits = info->nbits;
+@@ -1563,6 +1565,13 @@ static int __nvmem_cell_read(struct nvme
+       if (cell->bit_offset || cell->nbits)
+               nvmem_shift_read_buffer_in_place(cell, buf);
++      if (cell->read_post_process) {
++              rc = cell->read_post_process(nvmem->priv, id, index,
++                                           cell->offset, buf, cell->bytes);
++              if (rc)
++                      return rc;
++      }
++
+       if (nvmem->cell_post_process) {
+               rc = nvmem->cell_post_process(nvmem->priv, id, index,
+                                             cell->offset, buf, cell->bytes);
+@@ -1671,6 +1680,14 @@ static int __nvmem_cell_entry_write(stru
+           (cell->bit_offset == 0 && len != cell->bytes))
+               return -EINVAL;
++      /*
++       * Any cells which have a read_post_process hook are read-only because
++       * we cannot reverse the operation and it might affect other cells,
++       * too.
++       */
++      if (cell->read_post_process)
++              return -EINVAL;
++
+       if (cell->bit_offset || cell->nbits) {
+               buf = nvmem_cell_prepare_write_buffer(cell, buf, len);
+               if (IS_ERR(buf))
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -54,6 +54,8 @@ struct nvmem_keepout {
+  * @bit_offset:       Bit offset if cell is smaller than a byte.
+  * @nbits:    Number of bits.
+  * @np:               Optional device_node pointer.
++ * @read_post_process:        Callback for optional post processing of cell data
++ *                    on reads.
+  */
+ struct nvmem_cell_info {
+       const char              *name;
+@@ -62,6 +64,7 @@ struct nvmem_cell_info {
+       unsigned int            bit_offset;
+       unsigned int            nbits;
+       struct device_node      *np;
++      nvmem_cell_post_process_t read_post_process;
+ };
+ /**
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch b/target/linux/generic/backport-5.15/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch
new file mode 100644 (file)
index 0000000..3299014
--- /dev/null
@@ -0,0 +1,59 @@
+From de12c9691501ccba41a154c223869f82be4c12fd Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Tue, 4 Apr 2023 18:21:25 +0100
+Subject: [PATCH] nvmem: core: allow to modify a cell before adding it
+
+Provide a way to modify a cell before it will get added. This is useful
+to attach a custom post processing hook via a layout.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-18-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c           | 4 ++++
+ include/linux/nvmem-provider.h | 5 +++++
+ 2 files changed, 9 insertions(+)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -695,6 +695,7 @@ static int nvmem_validate_keepouts(struc
+ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
+ {
++      struct nvmem_layout *layout = nvmem->layout;
+       struct device *dev = &nvmem->dev;
+       struct device_node *child;
+       const __be32 *addr;
+@@ -724,6 +725,9 @@ static int nvmem_add_cells_from_of(struc
+               info.np = of_node_get(child);
++              if (layout && layout->fixup_cell_info)
++                      layout->fixup_cell_info(nvmem, layout, &info);
++
+               ret = nvmem_add_one_cell(nvmem, &info);
+               kfree(info.name);
+               if (ret) {
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -155,6 +155,8 @@ struct nvmem_cell_table {
+  * @add_cells:                Will be called if a nvmem device is found which
+  *                    has this layout. The function will add layout
+  *                    specific cells with nvmem_add_one_cell().
++ * @fixup_cell_info:  Will be called before a cell is added. Can be
++ *                    used to modify the nvmem_cell_info.
+  * @owner:            Pointer to struct module.
+  * @node:             List node.
+  *
+@@ -168,6 +170,9 @@ struct nvmem_layout {
+       const struct of_device_id *of_match_table;
+       int (*add_cells)(struct device *dev, struct nvmem_device *nvmem,
+                        struct nvmem_layout *layout);
++      void (*fixup_cell_info)(struct nvmem_device *nvmem,
++                              struct nvmem_layout *layout,
++                              struct nvmem_cell_info *cell);
+       /* private */
+       struct module *owner;
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch b/target/linux/generic/backport-5.15/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch
new file mode 100644 (file)
index 0000000..2a5fa61
--- /dev/null
@@ -0,0 +1,81 @@
+From 6c56a82d7895a213a43182a5d01a21a906a79847 Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Tue, 4 Apr 2023 18:21:26 +0100
+Subject: [PATCH] nvmem: imx-ocotp: replace global post processing with layouts
+
+In preparation of retiring the global post processing hook change this
+driver to use layouts. The layout will be supplied during registration
+and will be used to add the post processing hook to all added cells.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Tested-by: Michael Walle <michael@walle.cc> # on kontron-pitx-imx8m
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-19-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/imx-ocotp.c | 30 +++++++++++++++++++-----------
+ 1 file changed, 19 insertions(+), 11 deletions(-)
+
+--- a/drivers/nvmem/imx-ocotp.c
++++ b/drivers/nvmem/imx-ocotp.c
+@@ -225,18 +225,13 @@ read_end:
+ static int imx_ocotp_cell_pp(void *context, const char *id, int index,
+                            unsigned int offset, void *data, size_t bytes)
+ {
+-      struct ocotp_priv *priv = context;
++      u8 *buf = data;
++      int i;
+       /* 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]);
+-              }
+-      }
++      if (id && !strcmp(id, "mac-address"))
++              for (i = 0; i < bytes / 2; i++)
++                      swap(buf[i], buf[bytes - i - 1]);
+       return 0;
+ }
+@@ -488,7 +483,6 @@ 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 = {
+@@ -595,6 +589,17 @@ static const struct of_device_id imx_oco
+ };
+ MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids);
++static void imx_ocotp_fixup_cell_info(struct nvmem_device *nvmem,
++                                    struct nvmem_layout *layout,
++                                    struct nvmem_cell_info *cell)
++{
++      cell->read_post_process = imx_ocotp_cell_pp;
++}
++
++struct nvmem_layout imx_ocotp_layout = {
++      .fixup_cell_info = imx_ocotp_fixup_cell_info,
++};
++
+ static int imx_ocotp_probe(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+@@ -619,6 +624,9 @@ static int imx_ocotp_probe(struct platfo
+       imx_ocotp_nvmem_config.size = 4 * priv->params->nregs;
+       imx_ocotp_nvmem_config.dev = dev;
+       imx_ocotp_nvmem_config.priv = priv;
++      if (priv->params->reverse_mac_address)
++              imx_ocotp_nvmem_config.layout = &imx_ocotp_layout;
++
+       priv->config = &imx_ocotp_nvmem_config;
+       clk_prepare_enable(priv->clk);
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch b/target/linux/generic/backport-5.15/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch
new file mode 100644 (file)
index 0000000..eac202b
--- /dev/null
@@ -0,0 +1,68 @@
+From 011e40a166fdaa65fb9946b7cd91efec85b70dbb Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Tue, 4 Apr 2023 18:21:27 +0100
+Subject: [PATCH] nvmem: cell: drop global cell_post_process
+
+There are no users anymore for the global cell_post_process callback
+anymore. New users should use proper nvmem layouts.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-20-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c           | 9 ---------
+ include/linux/nvmem-provider.h | 2 --
+ 2 files changed, 11 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -39,7 +39,6 @@ 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;
+       struct nvmem_layout     *layout;
+       void *priv;
+@@ -903,7 +902,6 @@ 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)
+@@ -1575,13 +1573,6 @@ static int __nvmem_cell_read(struct nvme
+               if (rc)
+                       return rc;
+       }
+-
+-      if (nvmem->cell_post_process) {
+-              rc = nvmem->cell_post_process(nvmem->priv, id, index,
+-                                            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
+@@ -85,7 +85,6 @@ struct nvmem_cell_info {
+  * @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.
+@@ -118,7 +117,6 @@ 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;
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch b/target/linux/generic/backport-5.15/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch
new file mode 100644 (file)
index 0000000..46b30a2
--- /dev/null
@@ -0,0 +1,76 @@
+From 8a134fd9f9323f4c39ec27055b3d3723cfb5c1e9 Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Tue, 4 Apr 2023 18:21:28 +0100
+Subject: [PATCH] nvmem: core: provide own priv pointer in post process
+ callback
+
+It doesn't make any more sense to have a opaque pointer set up by the
+nvmem device. Usually, the layout isn't associated with a particular
+nvmem device. Instead, let the caller who set the post process callback
+provide the priv pointer.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-21-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c           | 4 +++-
+ include/linux/nvmem-provider.h | 5 ++++-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -54,6 +54,7 @@ struct nvmem_cell_entry {
+       int                     bit_offset;
+       int                     nbits;
+       nvmem_cell_post_process_t read_post_process;
++      void                    *priv;
+       struct device_node      *np;
+       struct nvmem_device     *nvmem;
+       struct list_head        node;
+@@ -471,6 +472,7 @@ static int nvmem_cell_info_to_nvmem_cell
+       cell->bytes = info->bytes;
+       cell->name = info->name;
+       cell->read_post_process = info->read_post_process;
++      cell->priv = info->priv;
+       cell->bit_offset = info->bit_offset;
+       cell->nbits = info->nbits;
+@@ -1568,7 +1570,7 @@ static int __nvmem_cell_read(struct nvme
+               nvmem_shift_read_buffer_in_place(cell, buf);
+       if (cell->read_post_process) {
+-              rc = cell->read_post_process(nvmem->priv, id, index,
++              rc = cell->read_post_process(cell->priv, id, index,
+                                            cell->offset, buf, cell->bytes);
+               if (rc)
+                       return rc;
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -20,7 +20,8 @@ typedef int (*nvmem_reg_write_t)(void *p
+                                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, int index,
+-                                       unsigned int offset, void *buf, size_t bytes);
++                                       unsigned int offset, void *buf,
++                                       size_t bytes);
+ enum nvmem_type {
+       NVMEM_TYPE_UNKNOWN = 0,
+@@ -56,6 +57,7 @@ struct nvmem_keepout {
+  * @np:               Optional device_node pointer.
+  * @read_post_process:        Callback for optional post processing of cell data
+  *                    on reads.
++ * @priv:     Opaque data passed to the read_post_process hook.
+  */
+ struct nvmem_cell_info {
+       const char              *name;
+@@ -65,6 +67,7 @@ struct nvmem_cell_info {
+       unsigned int            nbits;
+       struct device_node      *np;
+       nvmem_cell_post_process_t read_post_process;
++      void                    *priv;
+ };
+ /**
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch b/target/linux/generic/backport-5.15/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch
new file mode 100644 (file)
index 0000000..7d97658
--- /dev/null
@@ -0,0 +1,215 @@
+From d9fae023fe86069750092fc1c2f3a73e2fb18512 Mon Sep 17 00:00:00 2001
+From: Michael Walle <michael@walle.cc>
+Date: Tue, 4 Apr 2023 18:21:29 +0100
+Subject: [PATCH] nvmem: layouts: sl28vpd: Add new layout driver
+
+This layout applies to the VPD of the Kontron sl28 boards. The VPD only
+contains a base MAC address. Therefore, we have to add an individual
+offset to it. This is done by taking the second argument of the nvmem
+phandle into account. Also this let us checking the VPD version and the
+checksum.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-22-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/layouts/Kconfig   |   9 ++
+ drivers/nvmem/layouts/Makefile  |   2 +
+ drivers/nvmem/layouts/sl28vpd.c | 165 ++++++++++++++++++++++++++++++++
+ 3 files changed, 176 insertions(+)
+ create mode 100644 drivers/nvmem/layouts/sl28vpd.c
+
+--- a/drivers/nvmem/layouts/Kconfig
++++ b/drivers/nvmem/layouts/Kconfig
+@@ -2,4 +2,13 @@
+ menu "Layout Types"
++config NVMEM_LAYOUT_SL28_VPD
++      tristate "Kontron sl28 VPD layout support"
++      select CRC8
++      help
++        Say Y here if you want to support the VPD layout of the Kontron
++        SMARC-sAL28 boards.
++
++        If unsure, say N.
++
+ endmenu
+--- a/drivers/nvmem/layouts/Makefile
++++ b/drivers/nvmem/layouts/Makefile
+@@ -2,3 +2,5 @@
+ #
+ # Makefile for nvmem layouts.
+ #
++
++obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o
+--- /dev/null
++++ b/drivers/nvmem/layouts/sl28vpd.c
+@@ -0,0 +1,165 @@
++// SPDX-License-Identifier: GPL-2.0
++
++#include <linux/crc8.h>
++#include <linux/etherdevice.h>
++#include <linux/nvmem-consumer.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of.h>
++#include <uapi/linux/if_ether.h>
++
++#define SL28VPD_MAGIC 'V'
++
++struct sl28vpd_header {
++      u8 magic;
++      u8 version;
++} __packed;
++
++struct sl28vpd_v1 {
++      struct sl28vpd_header header;
++      char serial_number[15];
++      u8 base_mac_address[ETH_ALEN];
++      u8 crc8;
++} __packed;
++
++static int sl28vpd_mac_address_pp(void *priv, const char *id, int index,
++                                unsigned int offset, void *buf,
++                                size_t bytes)
++{
++      if (bytes != ETH_ALEN)
++              return -EINVAL;
++
++      if (index < 0)
++              return -EINVAL;
++
++      if (!is_valid_ether_addr(buf))
++              return -EINVAL;
++
++      eth_addr_add(buf, index);
++
++      return 0;
++}
++
++static const struct nvmem_cell_info sl28vpd_v1_entries[] = {
++      {
++              .name = "serial-number",
++              .offset = offsetof(struct sl28vpd_v1, serial_number),
++              .bytes = sizeof_field(struct sl28vpd_v1, serial_number),
++      },
++      {
++              .name = "base-mac-address",
++              .offset = offsetof(struct sl28vpd_v1, base_mac_address),
++              .bytes = sizeof_field(struct sl28vpd_v1, base_mac_address),
++              .read_post_process = sl28vpd_mac_address_pp,
++      },
++};
++
++static int sl28vpd_v1_check_crc(struct device *dev, struct nvmem_device *nvmem)
++{
++      struct sl28vpd_v1 data_v1;
++      u8 table[CRC8_TABLE_SIZE];
++      int ret;
++      u8 crc;
++
++      crc8_populate_msb(table, 0x07);
++
++      ret = nvmem_device_read(nvmem, 0, sizeof(data_v1), &data_v1);
++      if (ret < 0)
++              return ret;
++      else if (ret != sizeof(data_v1))
++              return -EIO;
++
++      crc = crc8(table, (void *)&data_v1, sizeof(data_v1) - 1, 0);
++
++      if (crc != data_v1.crc8) {
++              dev_err(dev,
++                      "Checksum is invalid (got %02x, expected %02x).\n",
++                      crc, data_v1.crc8);
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem,
++                           struct nvmem_layout *layout)
++{
++      const struct nvmem_cell_info *pinfo;
++      struct nvmem_cell_info info = {0};
++      struct device_node *layout_np;
++      struct sl28vpd_header hdr;
++      int ret, i;
++
++      /* check header */
++      ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr);
++      if (ret < 0)
++              return ret;
++      else if (ret != sizeof(hdr))
++              return -EIO;
++
++      if (hdr.magic != SL28VPD_MAGIC) {
++              dev_err(dev, "Invalid magic value (%02x)\n", hdr.magic);
++              return -EINVAL;
++      }
++
++      if (hdr.version != 1) {
++              dev_err(dev, "Version %d is unsupported.\n", hdr.version);
++              return -EINVAL;
++      }
++
++      ret = sl28vpd_v1_check_crc(dev, nvmem);
++      if (ret)
++              return ret;
++
++      layout_np = of_nvmem_layout_get_container(nvmem);
++      if (!layout_np)
++              return -ENOENT;
++
++      for (i = 0; i < ARRAY_SIZE(sl28vpd_v1_entries); i++) {
++              pinfo = &sl28vpd_v1_entries[i];
++
++              info.name = pinfo->name;
++              info.offset = pinfo->offset;
++              info.bytes = pinfo->bytes;
++              info.read_post_process = pinfo->read_post_process;
++              info.np = of_get_child_by_name(layout_np, pinfo->name);
++
++              ret = nvmem_add_one_cell(nvmem, &info);
++              if (ret) {
++                      of_node_put(layout_np);
++                      return ret;
++              }
++      }
++
++      of_node_put(layout_np);
++
++      return 0;
++}
++
++static const struct of_device_id sl28vpd_of_match_table[] = {
++      { .compatible = "kontron,sl28-vpd" },
++      {},
++};
++MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table);
++
++struct nvmem_layout sl28vpd_layout = {
++      .name = "sl28-vpd",
++      .of_match_table = sl28vpd_of_match_table,
++      .add_cells = sl28vpd_add_cells,
++};
++
++static int __init sl28vpd_init(void)
++{
++      return nvmem_layout_register(&sl28vpd_layout);
++}
++
++static void __exit sl28vpd_exit(void)
++{
++      nvmem_layout_unregister(&sl28vpd_layout);
++}
++
++module_init(sl28vpd_init);
++module_exit(sl28vpd_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
++MODULE_DESCRIPTION("NVMEM layout driver for the VPD of Kontron sl28 boards");
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch b/target/linux/generic/backport-5.15/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch
new file mode 100644 (file)
index 0000000..ca8b4bc
--- /dev/null
@@ -0,0 +1,306 @@
+From d3c0d12f6474216bf386101e2449cc73e5c5b61d Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Tue, 4 Apr 2023 18:21:31 +0100
+Subject: [PATCH] nvmem: layouts: onie-tlv: Add new layout driver
+
+This layout applies on top of any non volatile storage device containing
+an ONIE table factory flashed. This table follows the tlv
+(type-length-value) organization described in the link below. We cannot
+afford using regular parsers because the content of these tables is
+manufacturer specific and must be dynamically discovered.
+
+Link: https://opencomputeproject.github.io/onie/design-spec/hw_requirements.html
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-24-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/layouts/Kconfig    |   9 ++
+ drivers/nvmem/layouts/Makefile   |   1 +
+ drivers/nvmem/layouts/onie-tlv.c | 257 +++++++++++++++++++++++++++++++
+ 3 files changed, 267 insertions(+)
+ create mode 100644 drivers/nvmem/layouts/onie-tlv.c
+
+--- a/drivers/nvmem/layouts/Kconfig
++++ b/drivers/nvmem/layouts/Kconfig
+@@ -11,4 +11,13 @@ config NVMEM_LAYOUT_SL28_VPD
+         If unsure, say N.
++config NVMEM_LAYOUT_ONIE_TLV
++      tristate "ONIE tlv support"
++      select CRC32
++      help
++        Say Y here if you want to support the Open Compute Project ONIE
++        Type-Length-Value standard table.
++
++        If unsure, say N.
++
+ endmenu
+--- a/drivers/nvmem/layouts/Makefile
++++ b/drivers/nvmem/layouts/Makefile
+@@ -4,3 +4,4 @@
+ #
+ obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o
++obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o
+--- /dev/null
++++ b/drivers/nvmem/layouts/onie-tlv.c
+@@ -0,0 +1,257 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * ONIE tlv NVMEM cells provider
++ *
++ * Copyright (C) 2022 Open Compute Group ONIE
++ * Author: Miquel Raynal <miquel.raynal@bootlin.com>
++ * Based on the nvmem driver written by: Vadym Kochan <vadym.kochan@plvision.eu>
++ * Inspired by the first layout written by: Rafał Miłecki <rafal@milecki.pl>
++ */
++
++#include <linux/crc32.h>
++#include <linux/etherdevice.h>
++#include <linux/nvmem-consumer.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of.h>
++
++#define ONIE_TLV_MAX_LEN 2048
++#define ONIE_TLV_CRC_FIELD_SZ 6
++#define ONIE_TLV_CRC_SZ 4
++#define ONIE_TLV_HDR_ID       "TlvInfo"
++
++struct onie_tlv_hdr {
++      u8 id[8];
++      u8 version;
++      __be16 data_len;
++} __packed;
++
++struct onie_tlv {
++      u8 type;
++      u8 len;
++} __packed;
++
++static const char *onie_tlv_cell_name(u8 type)
++{
++      switch (type) {
++      case 0x21:
++              return "product-name";
++      case 0x22:
++              return "part-number";
++      case 0x23:
++              return "serial-number";
++      case 0x24:
++              return "mac-address";
++      case 0x25:
++              return "manufacture-date";
++      case 0x26:
++              return "device-version";
++      case 0x27:
++              return "label-revision";
++      case 0x28:
++              return "platform-name";
++      case 0x29:
++              return "onie-version";
++      case 0x2A:
++              return "num-macs";
++      case 0x2B:
++              return "manufacturer";
++      case 0x2C:
++              return "country-code";
++      case 0x2D:
++              return "vendor";
++      case 0x2E:
++              return "diag-version";
++      case 0x2F:
++              return "service-tag";
++      case 0xFD:
++              return "vendor-extension";
++      case 0xFE:
++              return "crc32";
++      default:
++              break;
++      }
++
++      return NULL;
++}
++
++static int onie_tlv_mac_read_cb(void *priv, const char *id, int index,
++                              unsigned int offset, void *buf,
++                              size_t bytes)
++{
++      eth_addr_add(buf, index);
++
++      return 0;
++}
++
++static nvmem_cell_post_process_t onie_tlv_read_cb(u8 type, u8 *buf)
++{
++      switch (type) {
++      case 0x24:
++              return &onie_tlv_mac_read_cb;
++      default:
++              break;
++      }
++
++      return NULL;
++}
++
++static int onie_tlv_add_cells(struct device *dev, struct nvmem_device *nvmem,
++                            size_t data_len, u8 *data)
++{
++      struct nvmem_cell_info cell = {};
++      struct device_node *layout;
++      struct onie_tlv tlv;
++      unsigned int hdr_len = sizeof(struct onie_tlv_hdr);
++      unsigned int offset = 0;
++      int ret;
++
++      layout = of_nvmem_layout_get_container(nvmem);
++      if (!layout)
++              return -ENOENT;
++
++      while (offset < data_len) {
++              memcpy(&tlv, data + offset, sizeof(tlv));
++              if (offset + tlv.len >= data_len) {
++                      dev_err(dev, "Out of bounds field (0x%x bytes at 0x%x)\n",
++                              tlv.len, hdr_len + offset);
++                      break;
++              }
++
++              cell.name = onie_tlv_cell_name(tlv.type);
++              if (!cell.name)
++                      continue;
++
++              cell.offset = hdr_len + offset + sizeof(tlv.type) + sizeof(tlv.len);
++              cell.bytes = tlv.len;
++              cell.np = of_get_child_by_name(layout, cell.name);
++              cell.read_post_process = onie_tlv_read_cb(tlv.type, data + offset + sizeof(tlv));
++
++              ret = nvmem_add_one_cell(nvmem, &cell);
++              if (ret) {
++                      of_node_put(layout);
++                      return ret;
++              }
++
++              offset += sizeof(tlv) + tlv.len;
++      }
++
++      of_node_put(layout);
++
++      return 0;
++}
++
++static bool onie_tlv_hdr_is_valid(struct device *dev, struct onie_tlv_hdr *hdr)
++{
++      if (memcmp(hdr->id, ONIE_TLV_HDR_ID, sizeof(hdr->id))) {
++              dev_err(dev, "Invalid header\n");
++              return false;
++      }
++
++      if (hdr->version != 0x1) {
++              dev_err(dev, "Invalid version number\n");
++              return false;
++      }
++
++      return true;
++}
++
++static bool onie_tlv_crc_is_valid(struct device *dev, size_t table_len, u8 *table)
++{
++      struct onie_tlv crc_hdr;
++      u32 read_crc, calc_crc;
++      __be32 crc_be;
++
++      memcpy(&crc_hdr, table + table_len - ONIE_TLV_CRC_FIELD_SZ, sizeof(crc_hdr));
++      if (crc_hdr.type != 0xfe || crc_hdr.len != ONIE_TLV_CRC_SZ) {
++              dev_err(dev, "Invalid CRC field\n");
++              return false;
++      }
++
++      /* The table contains a JAMCRC, which is XOR'ed compared to the original
++       * CRC32 implementation as known in the Ethernet world.
++       */
++      memcpy(&crc_be, table + table_len - ONIE_TLV_CRC_SZ, ONIE_TLV_CRC_SZ);
++      read_crc = be32_to_cpu(crc_be);
++      calc_crc = crc32(~0, table, table_len - ONIE_TLV_CRC_SZ) ^ 0xFFFFFFFF;
++      if (read_crc != calc_crc) {
++              dev_err(dev, "Invalid CRC read: 0x%08x, expected: 0x%08x\n",
++                      read_crc, calc_crc);
++              return false;
++      }
++
++      return true;
++}
++
++static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem,
++                              struct nvmem_layout *layout)
++{
++      struct onie_tlv_hdr hdr;
++      size_t table_len, data_len, hdr_len;
++      u8 *table, *data;
++      int ret;
++
++      ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr);
++      if (ret < 0)
++              return ret;
++
++      if (!onie_tlv_hdr_is_valid(dev, &hdr)) {
++              dev_err(dev, "Invalid ONIE TLV header\n");
++              return -EINVAL;
++      }
++
++      hdr_len = sizeof(hdr.id) + sizeof(hdr.version) + sizeof(hdr.data_len);
++      data_len = be16_to_cpu(hdr.data_len);
++      table_len = hdr_len + data_len;
++      if (table_len > ONIE_TLV_MAX_LEN) {
++              dev_err(dev, "Invalid ONIE TLV data length\n");
++              return -EINVAL;
++      }
++
++      table = devm_kmalloc(dev, table_len, GFP_KERNEL);
++      if (!table)
++              return -ENOMEM;
++
++      ret = nvmem_device_read(nvmem, 0, table_len, table);
++      if (ret != table_len)
++              return ret;
++
++      if (!onie_tlv_crc_is_valid(dev, table_len, table))
++              return -EINVAL;
++
++      data = table + hdr_len;
++      ret = onie_tlv_add_cells(dev, nvmem, data_len, data);
++      if (ret)
++              return ret;
++
++      return 0;
++}
++
++static const struct of_device_id onie_tlv_of_match_table[] = {
++      { .compatible = "onie,tlv-layout", },
++      {},
++};
++MODULE_DEVICE_TABLE(of, onie_tlv_of_match_table);
++
++static struct nvmem_layout onie_tlv_layout = {
++      .name = "ONIE tlv layout",
++      .of_match_table = onie_tlv_of_match_table,
++      .add_cells = onie_tlv_parse_table,
++};
++
++static int __init onie_tlv_init(void)
++{
++      return nvmem_layout_register(&onie_tlv_layout);
++}
++
++static void __exit onie_tlv_exit(void)
++{
++      nvmem_layout_unregister(&onie_tlv_layout);
++}
++
++module_init(onie_tlv_init);
++module_exit(onie_tlv_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
++MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing");
++MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing");
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch b/target/linux/generic/backport-5.15/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch
new file mode 100644 (file)
index 0000000..94a0911
--- /dev/null
@@ -0,0 +1,32 @@
+From a4fb434ef96ace5af758ca2c52c3a3f8f3abc87c Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Date: Tue, 4 Apr 2023 18:21:34 +0100
+Subject: [PATCH] nvmem: stm32-romem: mark OF related data as maybe unused
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The driver can be compile tested with !CONFIG_OF making certain data
+unused:
+
+  drivers/nvmem/stm32-romem.c:271:34: error: ‘stm32_romem_of_match’ defined but not used [-Werror=unused-const-variable=]
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-27-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
+@@ -268,7 +268,7 @@ static const struct stm32_romem_cfg stm3
+       .ta = true,
+ };
+-static const struct of_device_id stm32_romem_of_match[] = {
++static const struct of_device_id stm32_romem_of_match[] __maybe_unused = {
+       { .compatible = "st,stm32f4-otp", }, {
+               .compatible = "st,stm32mp15-bsec",
+               .data = (void *)&stm32mp15_bsec_cfg,
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch b/target/linux/generic/backport-5.15/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch
new file mode 100644 (file)
index 0000000..abda402
--- /dev/null
@@ -0,0 +1,120 @@
+From de6e05097f7db066afb0ad4c88b730949f7b7749 Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Tue, 4 Apr 2023 18:21:35 +0100
+Subject: [PATCH] nvmem: mtk-efuse: Support postprocessing for GPU speed
+ binning data
+
+On some MediaTek SoCs GPU speed binning data is available for read
+in the SoC's eFuse array but it has a format that is incompatible
+with what the OPP API expects, as we read a number from 0 to 7 but
+opp-supported-hw is expecting a bitmask to enable an OPP entry:
+being what we read limited to 0-7, it's straightforward to simply
+convert the value to BIT(value) as a post-processing action.
+
+So, introduce post-processing support and enable it by evaluating
+the newly introduced platform data's `uses_post_processing` member,
+currently enabled only for MT8186.
+
+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/20230404172148.82422-28-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/mtk-efuse.c | 53 +++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 51 insertions(+), 2 deletions(-)
+
+--- a/drivers/nvmem/mtk-efuse.c
++++ b/drivers/nvmem/mtk-efuse.c
+@@ -10,6 +10,11 @@
+ #include <linux/io.h>
+ #include <linux/nvmem-provider.h>
+ #include <linux/platform_device.h>
++#include <linux/property.h>
++
++struct mtk_efuse_pdata {
++      bool uses_post_processing;
++};
+ struct mtk_efuse_priv {
+       void __iomem *base;
+@@ -29,6 +34,37 @@ static int mtk_reg_read(void *context,
+       return 0;
+ }
++static int mtk_efuse_gpu_speedbin_pp(void *context, const char *id, int index,
++                                   unsigned int offset, void *data, size_t bytes)
++{
++      u8 *val = data;
++
++      if (val[0] < 8)
++              val[0] = BIT(val[0]);
++
++      return 0;
++}
++
++static void mtk_efuse_fixup_cell_info(struct nvmem_device *nvmem,
++                                    struct nvmem_layout *layout,
++                                    struct nvmem_cell_info *cell)
++{
++      size_t sz = strlen(cell->name);
++
++      /*
++       * On some SoCs, the GPU speedbin is not read as bitmask but as
++       * a number with range [0-7] (max 3 bits): post process to use
++       * it in OPP tables to describe supported-hw.
++       */
++      if (cell->nbits <= 3 &&
++          strncmp(cell->name, "gpu-speedbin", min(sz, strlen("gpu-speedbin"))) == 0)
++              cell->read_post_process = mtk_efuse_gpu_speedbin_pp;
++}
++
++static struct nvmem_layout mtk_efuse_layout = {
++      .fixup_cell_info = mtk_efuse_fixup_cell_info,
++};
++
+ static int mtk_efuse_probe(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+@@ -36,6 +72,7 @@ static int mtk_efuse_probe(struct platfo
+       struct nvmem_device *nvmem;
+       struct nvmem_config econfig = {};
+       struct mtk_efuse_priv *priv;
++      const struct mtk_efuse_pdata *pdata;
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+@@ -45,20 +82,32 @@ static int mtk_efuse_probe(struct platfo
+       if (IS_ERR(priv->base))
+               return PTR_ERR(priv->base);
++      pdata = device_get_match_data(dev);
+       econfig.stride = 1;
+       econfig.word_size = 1;
+       econfig.reg_read = mtk_reg_read;
+       econfig.size = resource_size(res);
+       econfig.priv = priv;
+       econfig.dev = dev;
++      if (pdata->uses_post_processing)
++              econfig.layout = &mtk_efuse_layout;
+       nvmem = devm_nvmem_register(dev, &econfig);
+       return PTR_ERR_OR_ZERO(nvmem);
+ }
++static const struct mtk_efuse_pdata mtk_mt8186_efuse_pdata = {
++      .uses_post_processing = true,
++};
++
++static const struct mtk_efuse_pdata mtk_efuse_pdata = {
++      .uses_post_processing = false,
++};
++
+ static const struct of_device_id mtk_efuse_of_match[] = {
+-      { .compatible = "mediatek,mt8173-efuse",},
+-      { .compatible = "mediatek,efuse",},
++      { .compatible = "mediatek,mt8173-efuse", .data = &mtk_efuse_pdata },
++      { .compatible = "mediatek,mt8186-efuse", .data = &mtk_mt8186_efuse_pdata },
++      { .compatible = "mediatek,efuse", .data = &mtk_efuse_pdata },
+       {/* sentinel */},
+ };
+ MODULE_DEVICE_TABLE(of, mtk_efuse_of_match);
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch b/target/linux/generic/backport-5.15/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch
new file mode 100644 (file)
index 0000000..a0874f7
--- /dev/null
@@ -0,0 +1,39 @@
+From 1dc552fa33cf98af3e784dbc0500da93cae3b24a Mon Sep 17 00:00:00 2001
+From: Yang Li <yang.lee@linux.alibaba.com>
+Date: Tue, 4 Apr 2023 18:21:38 +0100
+Subject: [PATCH] nvmem: bcm-ocotp: Use devm_platform_ioremap_resource()
+
+According to commit 7945f929f1a7 ("drivers: provide
+devm_platform_ioremap_resource()"), convert platform_get_resource(),
+devm_ioremap_resource() to a single call to use
+devm_platform_ioremap_resource(), as this is exactly what this function
+does.
+
+Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-31-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/bcm-ocotp.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/nvmem/bcm-ocotp.c
++++ b/drivers/nvmem/bcm-ocotp.c
+@@ -254,7 +254,6 @@ MODULE_DEVICE_TABLE(acpi, bcm_otpc_acpi_
+ static int bcm_otpc_probe(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+-      struct resource *res;
+       struct otpc_priv *priv;
+       struct nvmem_device *nvmem;
+       int err;
+@@ -269,8 +268,7 @@ static int bcm_otpc_probe(struct platfor
+               return -ENODEV;
+       /* Get OTP base address register. */
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      priv->base = devm_ioremap_resource(dev, res);
++      priv->base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(priv->base)) {
+               dev_err(dev, "unable to map I/O memory\n");
+               return PTR_ERR(priv->base);
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch b/target/linux/generic/backport-5.15/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch
new file mode 100644 (file)
index 0000000..890dacd
--- /dev/null
@@ -0,0 +1,39 @@
+From 649409990d2e93fac657be7c6960c28a2c601d65 Mon Sep 17 00:00:00 2001
+From: Yang Li <yang.lee@linux.alibaba.com>
+Date: Tue, 4 Apr 2023 18:21:39 +0100
+Subject: [PATCH] nvmem: nintendo-otp: Use devm_platform_ioremap_resource()
+
+According to commit 7945f929f1a7 ("drivers: provide
+devm_platform_ioremap_resource()"), convert platform_get_resource(),
+devm_ioremap_resource() to a single call to use
+devm_platform_ioremap_resource(), as this is exactly what this function
+does.
+
+Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-32-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/nintendo-otp.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/nvmem/nintendo-otp.c
++++ b/drivers/nvmem/nintendo-otp.c
+@@ -76,7 +76,6 @@ static int nintendo_otp_probe(struct pla
+       struct device *dev = &pdev->dev;
+       const struct of_device_id *of_id =
+               of_match_device(nintendo_otp_of_table, dev);
+-      struct resource *res;
+       struct nvmem_device *nvmem;
+       struct nintendo_otp_priv *priv;
+@@ -92,8 +91,7 @@ static int nintendo_otp_probe(struct pla
+       if (!priv)
+               return -ENOMEM;
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      priv->regs = devm_ioremap_resource(dev, res);
++      priv->regs = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(priv->regs))
+               return PTR_ERR(priv->regs);
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch b/target/linux/generic/backport-5.15/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch
new file mode 100644 (file)
index 0000000..3f5d3c1
--- /dev/null
@@ -0,0 +1,32 @@
+From c2367aa60d5e34d48582362c6de34b4131d92be7 Mon Sep 17 00:00:00 2001
+From: Yang Li <yang.lee@linux.alibaba.com>
+Date: Tue, 4 Apr 2023 18:21:40 +0100
+Subject: [PATCH] nvmem: vf610-ocotp: Use
+ devm_platform_get_and_ioremap_resource()
+
+According to commit 890cc39a8799 ("drivers: provide
+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.
+
+Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-33-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/vf610-ocotp.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/nvmem/vf610-ocotp.c
++++ b/drivers/nvmem/vf610-ocotp.c
+@@ -219,8 +219,7 @@ static int vf610_ocotp_probe(struct plat
+       if (!ocotp_dev)
+               return -ENOMEM;
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      ocotp_dev->base = devm_ioremap_resource(dev, res);
++      ocotp_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+       if (IS_ERR(ocotp_dev->base))
+               return PTR_ERR(ocotp_dev->base);
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch b/target/linux/generic/backport-5.15/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch
new file mode 100644 (file)
index 0000000..eeb407e
--- /dev/null
@@ -0,0 +1,115 @@
+From 55d4980ce55b6bb4be66877de4dbec513911b988 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Tue, 4 Apr 2023 18:21:42 +0100
+Subject: [PATCH] nvmem: core: support specifying both: cell raw data & post
+ read lengths
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Callback .read_post_process() is designed to modify raw cell content
+before providing it to the consumer. So far we were dealing with
+modifications that didn't affect cell size (length). In some cases
+however cell content needs to be reformatted and resized.
+
+It's required e.g. to provide properly formatted MAC address in case
+it's stored in a non-binary format (e.g. using ASCII).
+
+There were few discussions how to optimally handle that. Following
+possible solutions were considered:
+1. Allow .read_post_process() to realloc (resize) content buffer
+2. Allow .read_post_process() to adjust (decrease) just buffer length
+3. Register NVMEM cells using post-read sizes
+
+The preferred solution was the last one. The problem is that simply
+adjusting "bytes" in NVMEM providers would result in core code NOT
+passing whole raw data to .read_post_process() callbacks. It means
+callback functions couldn't do their job without somehow manually
+reading original cell content on their own.
+
+This patch deals with that by registering NVMEM cells with both lengths:
+raw content one and post read one. It allows:
+1. Core code to read whole raw cell content
+2. Callbacks to return content they want
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-35-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c           | 11 +++++++----
+ include/linux/nvmem-provider.h |  2 ++
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -50,6 +50,7 @@ struct nvmem_device {
+ struct nvmem_cell_entry {
+       const char              *name;
+       int                     offset;
++      size_t                  raw_len;
+       int                     bytes;
+       int                     bit_offset;
+       int                     nbits;
+@@ -469,6 +470,7 @@ static int nvmem_cell_info_to_nvmem_cell
+ {
+       cell->nvmem = nvmem;
+       cell->offset = info->offset;
++      cell->raw_len = info->raw_len ?: info->bytes;
+       cell->bytes = info->bytes;
+       cell->name = info->name;
+       cell->read_post_process = info->read_post_process;
+@@ -1560,7 +1562,7 @@ static int __nvmem_cell_read(struct nvme
+ {
+       int rc;
+-      rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes);
++      rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->raw_len);
+       if (rc)
+               return rc;
+@@ -1571,7 +1573,7 @@ static int __nvmem_cell_read(struct nvme
+       if (cell->read_post_process) {
+               rc = cell->read_post_process(cell->priv, id, index,
+-                                           cell->offset, buf, cell->bytes);
++                                           cell->offset, buf, cell->raw_len);
+               if (rc)
+                       return rc;
+       }
+@@ -1594,14 +1596,15 @@ static int __nvmem_cell_read(struct nvme
+  */
+ void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
+ {
+-      struct nvmem_device *nvmem = cell->entry->nvmem;
++      struct nvmem_cell_entry *entry = cell->entry;
++      struct nvmem_device *nvmem = entry->nvmem;
+       u8 *buf;
+       int rc;
+       if (!nvmem)
+               return ERR_PTR(-EINVAL);
+-      buf = kzalloc(cell->entry->bytes, GFP_KERNEL);
++      buf = kzalloc(max_t(size_t, entry->raw_len, entry->bytes), GFP_KERNEL);
+       if (!buf)
+               return ERR_PTR(-ENOMEM);
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -51,6 +51,7 @@ struct nvmem_keepout {
+  * struct nvmem_cell_info - NVMEM cell description
+  * @name:     Name.
+  * @offset:   Offset within the NVMEM device.
++ * @raw_len:  Length of raw data (without post processing).
+  * @bytes:    Length of the cell.
+  * @bit_offset:       Bit offset if cell is smaller than a byte.
+  * @nbits:    Number of bits.
+@@ -62,6 +63,7 @@ struct nvmem_keepout {
+ struct nvmem_cell_info {
+       const char              *name;
+       unsigned int            offset;
++      size_t                  raw_len;
+       unsigned int            bytes;
+       unsigned int            bit_offset;
+       unsigned int            nbits;
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch b/target/linux/generic/backport-5.15/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch
new file mode 100644 (file)
index 0000000..7c6fe22
--- /dev/null
@@ -0,0 +1,42 @@
+From 814c978f02db17f16e6aa2efa2a929372f06da09 Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Tue, 4 Apr 2023 18:21:44 +0100
+Subject: [PATCH] nvmem: Add macro to register nvmem layout drivers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Provide a module_nvmem_layout_driver() macro at the end of the
+nvmem-provider.h header to reduce the boilerplate when registering nvmem
+layout drivers.
+
+Suggested-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Acked-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-37-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/nvmem-provider.h | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -9,6 +9,7 @@
+ #ifndef _LINUX_NVMEM_PROVIDER_H
+ #define _LINUX_NVMEM_PROVIDER_H
++#include <linux/device/driver.h>
+ #include <linux/err.h>
+ #include <linux/errno.h>
+ #include <linux/gpio/consumer.h>
+@@ -242,4 +243,9 @@ nvmem_layout_get_match_data(struct nvmem
+ }
+ #endif /* CONFIG_NVMEM */
++
++#define module_nvmem_layout_driver(__layout_driver)           \
++      module_driver(__layout_driver, nvmem_layout_register,   \
++                    nvmem_layout_unregister)
++
+ #endif  /* ifndef _LINUX_NVMEM_PROVIDER_H */
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch b/target/linux/generic/backport-5.15/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch
new file mode 100644 (file)
index 0000000..06646dd
--- /dev/null
@@ -0,0 +1,39 @@
+From 0abdf99fe0c86252ba274703425f8d543d7e7f0d Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Tue, 4 Apr 2023 18:21:45 +0100
+Subject: [PATCH] nvmem: layouts: sl28vpd: Use module_nvmem_layout_driver()
+
+Stop open-coding the module init/exit functions. Use the
+module_nvmem_layout_driver() instead.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-38-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/layouts/sl28vpd.c | 14 +-------------
+ 1 file changed, 1 insertion(+), 13 deletions(-)
+
+--- a/drivers/nvmem/layouts/sl28vpd.c
++++ b/drivers/nvmem/layouts/sl28vpd.c
+@@ -146,19 +146,7 @@ struct nvmem_layout sl28vpd_layout = {
+       .of_match_table = sl28vpd_of_match_table,
+       .add_cells = sl28vpd_add_cells,
+ };
+-
+-static int __init sl28vpd_init(void)
+-{
+-      return nvmem_layout_register(&sl28vpd_layout);
+-}
+-
+-static void __exit sl28vpd_exit(void)
+-{
+-      nvmem_layout_unregister(&sl28vpd_layout);
+-}
+-
+-module_init(sl28vpd_init);
+-module_exit(sl28vpd_exit);
++module_nvmem_layout_driver(sl28vpd_layout);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch b/target/linux/generic/backport-5.15/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch
new file mode 100644 (file)
index 0000000..826f437
--- /dev/null
@@ -0,0 +1,39 @@
+From d119eb38faab61125aaa4f63c74eef61585cf34c Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Tue, 4 Apr 2023 18:21:46 +0100
+Subject: [PATCH] nvmem: layouts: onie-tlv: Use module_nvmem_layout_driver()
+
+Stop open-coding the module init/exit functions. Use the
+module_nvmem_layout_driver() instead.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-39-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/layouts/onie-tlv.c | 14 +-------------
+ 1 file changed, 1 insertion(+), 13 deletions(-)
+
+--- a/drivers/nvmem/layouts/onie-tlv.c
++++ b/drivers/nvmem/layouts/onie-tlv.c
+@@ -237,19 +237,7 @@ static struct nvmem_layout onie_tlv_layo
+       .of_match_table = onie_tlv_of_match_table,
+       .add_cells = onie_tlv_parse_table,
+ };
+-
+-static int __init onie_tlv_init(void)
+-{
+-      return nvmem_layout_register(&onie_tlv_layout);
+-}
+-
+-static void __exit onie_tlv_exit(void)
+-{
+-      nvmem_layout_unregister(&onie_tlv_layout);
+-}
+-
+-module_init(onie_tlv_init);
+-module_exit(onie_tlv_exit);
++module_nvmem_layout_driver(onie_tlv_layout);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch b/target/linux/generic/backport-5.15/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch
new file mode 100644 (file)
index 0000000..f20db85
--- /dev/null
@@ -0,0 +1,24 @@
+From 6b13e4b6a9a45028ac730e550380077df1845912 Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Tue, 4 Apr 2023 18:21:47 +0100
+Subject: [PATCH] nvmem: layouts: onie-tlv: Drop wrong module alias
+
+The MODULE_ALIAS macro is misused here as it carries the
+description. There is currently no relevant alias to provide so let's
+just drop it.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-40-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/layouts/onie-tlv.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/nvmem/layouts/onie-tlv.c
++++ b/drivers/nvmem/layouts/onie-tlv.c
+@@ -242,4 +242,3 @@ module_nvmem_layout_driver(onie_tlv_layo
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
+ MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing");
+-MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing");
diff --git a/target/linux/generic/backport-5.15/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch b/target/linux/generic/backport-5.15/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch
new file mode 100644 (file)
index 0000000..5cf847b
--- /dev/null
@@ -0,0 +1,31 @@
+From a8642cd11635a35a5f1dc31857887900d6610778 Mon Sep 17 00:00:00 2001
+From: Tom Rix <trix@redhat.com>
+Date: Tue, 4 Apr 2023 18:21:48 +0100
+Subject: [PATCH] nvmem: layouts: sl28vpd: set varaiable sl28vpd_layout
+ storage-class-specifier to static
+
+smatch reports
+drivers/nvmem/layouts/sl28vpd.c:144:21: warning: symbol
+  'sl28vpd_layout' was not declared. Should it be static?
+
+This variable is only used in one file so it should be static.
+
+Signed-off-by: Tom Rix <trix@redhat.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20230404172148.82422-41-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/layouts/sl28vpd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/layouts/sl28vpd.c
++++ b/drivers/nvmem/layouts/sl28vpd.c
+@@ -141,7 +141,7 @@ static const struct of_device_id sl28vpd
+ };
+ MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table);
+-struct nvmem_layout sl28vpd_layout = {
++static struct nvmem_layout sl28vpd_layout = {
+       .name = "sl28-vpd",
+       .of_match_table = sl28vpd_of_match_table,
+       .add_cells = sl28vpd_add_cells,
index df93e4d956b98d7521fa9cd46955b3c66a150564..cde0fdb0a04078fbd2483aed7e233c9151addefd 100644 (file)
@@ -4242,6 +4242,8 @@ CONFIG_NMI_LOG_BUF_SHIFT=13
 # CONFIG_NVMEM is not set
 # CONFIG_NVMEM_BCM_OCOTP is not set
 # CONFIG_NVMEM_IMX_OCOTP is not set
+# CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set
+# CONFIG_NVMEM_LAYOUT_SL28_VPD is not set
 # CONFIG_NVMEM_REBOOT_MODE is not set
 # CONFIG_NVMEM_RMEM is not set
 # CONFIG_NVMEM_SYSFS is not set
index c9581ba5d4a79b42aab24936b68755448a6c8e2e..a03f65f4d7734ff1052c5a95a7e16c2e7eb1b1d1 100644 (file)
@@ -4442,6 +4442,8 @@ CONFIG_NMI_LOG_BUF_SHIFT=13
 # CONFIG_NVMEM is not set
 # CONFIG_NVMEM_BCM_OCOTP is not set
 # CONFIG_NVMEM_IMX_OCOTP is not set
+# CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set
+# CONFIG_NVMEM_LAYOUT_SL28_VPD is not set
 # CONFIG_NVMEM_REBOOT_MODE is not set
 # CONFIG_NVMEM_RMEM is not set
 # CONFIG_NVMEM_SYSFS is not set