diff options
author | Rafał Miłecki <rafal@milecki.pl> | 2023-04-06 09:15:49 +0200 |
---|---|---|
committer | Rafał Miłecki <rafal@milecki.pl> | 2023-04-06 12:13:22 +0200 |
commit | 323072f3a6fb709d5a20dbd1375816e8c041a85b (patch) | |
tree | 5ec6de04cfb3fd1ca4a36fa817dd9ce2b9dcd1bf /target/linux | |
parent | b67ba02fc848cee5175cfdefe81e10adf195c435 (diff) | |
download | upstream-323072f3a6fb709d5a20dbd1375816e8c041a85b.tar.gz upstream-323072f3a6fb709d5a20dbd1375816e8c041a85b.tar.bz2 upstream-323072f3a6fb709d5a20dbd1375816e8c041a85b.zip |
kernel: backport NVMEM patches queued for the v6.4
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>
Diffstat (limited to 'target/linux')
46 files changed, 3960 insertions, 0 deletions
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 index 0000000000..8328e87c0a --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch @@ -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 index 0000000000..8b886aea2e --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch @@ -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 index 0000000000..6fa7b6382d --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch @@ -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 index 0000000000..b9341666f9 --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0004-nvmem-core-request-layout-modules-loading.patch @@ -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 index 0000000000..53628cd4e4 --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch @@ -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 index 0000000000..32990148c8 --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch @@ -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 index 0000000000..2a5fa618ea --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch @@ -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 index 0000000000..eac202b882 --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch @@ -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 index 0000000000..46b30a2ed9 --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch @@ -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 index 0000000000..7d97658b60 --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch @@ -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 index 0000000000..ca8b4bc069 --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch @@ -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 index 0000000000..94a0911d73 --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch @@ -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 index 0000000000..abda402bdd --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch @@ -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 index 0000000000..a0874f73d1 --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch @@ -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 index 0000000000..890dacd08d --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch @@ -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 index 0000000000..3f5d3c1ad4 --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch @@ -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 index 0000000000..eeb407e9bb --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch @@ -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 index 0000000000..7c6fe22b5f --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch @@ -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 index 0000000000..06646dd68b --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch @@ -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 index 0000000000..826f4378c2 --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch @@ -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 index 0000000000..f20db85ceb --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch @@ -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 index 0000000000..5cf847b57a --- /dev/null +++ b/target/linux/generic/backport-5.10/814-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch @@ -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 index 0000000000..8328e87c0a --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch @@ -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 index 0000000000..23518d21f7 --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch @@ -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 index 0000000000..6fa7b6382d --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch @@ -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 index 0000000000..b9341666f9 --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch @@ -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 index 0000000000..53628cd4e4 --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch @@ -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 index 0000000000..32990148c8 --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch @@ -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 index 0000000000..2a5fa618ea --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch @@ -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 index 0000000000..eac202b882 --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch @@ -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 index 0000000000..46b30a2ed9 --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch @@ -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 index 0000000000..7d97658b60 --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch @@ -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 index 0000000000..ca8b4bc069 --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch @@ -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 index 0000000000..94a0911d73 --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch @@ -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 index 0000000000..abda402bdd --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch @@ -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 index 0000000000..a0874f73d1 --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch @@ -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 index 0000000000..890dacd08d --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch @@ -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 index 0000000000..3f5d3c1ad4 --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch @@ -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 index 0000000000..eeb407e9bb --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch @@ -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 index 0000000000..7c6fe22b5f --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch @@ -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 index 0000000000..06646dd68b --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch @@ -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 index 0000000000..826f4378c2 --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch @@ -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 index 0000000000..f20db85ceb --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch @@ -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 index 0000000000..5cf847b57a --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch @@ -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/config-5.10 b/target/linux/generic/config-5.10 index df93e4d956..cde0fdb0a0 100644 --- a/target/linux/generic/config-5.10 +++ b/target/linux/generic/config-5.10 @@ -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 diff --git a/target/linux/generic/config-5.15 b/target/linux/generic/config-5.15 index c9581ba5d4..a03f65f4d7 100644 --- a/target/linux/generic/config-5.15 +++ b/target/linux/generic/config-5.15 @@ -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 |