diff options
author | Rafał Miłecki <rafal@milecki.pl> | 2024-09-12 06:47:59 +0200 |
---|---|---|
committer | Rafał Miłecki <rafal@milecki.pl> | 2024-09-12 08:59:36 +0200 |
commit | e39ae96f88b75929c6c951feed2d52b1aebcc081 (patch) | |
tree | c434b88b069e7063957146db7a89ce8e57d49b03 | |
parent | c7ba5574f52f25334add66c15190b578ac873739 (diff) | |
download | openwrt-e39ae96f88b75929c6c951feed2d52b1aebcc081.tar.gz openwrt-e39ae96f88b75929c6c951feed2d52b1aebcc081.tar.bz2 openwrt-e39ae96f88b75929c6c951feed2d52b1aebcc081.zip |
kernel: backport nvmem changes from v6.12
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
19 files changed, 1935 insertions, 22 deletions
diff --git a/target/linux/generic/backport-5.15/837-v6.10-0001-nvmem-layouts-store-owner-from-modules-with-nvmem_la.patch b/target/linux/generic/backport-5.15/837-v6.10-0001-nvmem-layouts-store-owner-from-modules-with-nvmem_la.patch index 418d2c82b2..c15b4b2265 100644 --- a/target/linux/generic/backport-5.15/837-v6.10-0001-nvmem-layouts-store-owner-from-modules-with-nvmem_la.patch +++ b/target/linux/generic/backport-5.15/837-v6.10-0001-nvmem-layouts-store-owner-from-modules-with-nvmem_la.patch @@ -27,7 +27,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- a/drivers/nvmem/layouts.c +++ b/drivers/nvmem/layouts.c -@@ -52,13 +52,15 @@ static const struct bus_type nvmem_layou +@@ -52,13 +52,15 @@ static struct bus_type nvmem_layout_bus_ .remove = nvmem_layout_bus_remove, }; diff --git a/target/linux/generic/backport-5.15/839-v6.12-0001-nvmem-imx-ocotp-ele-support-i.MX95.patch b/target/linux/generic/backport-5.15/839-v6.12-0001-nvmem-imx-ocotp-ele-support-i.MX95.patch new file mode 100644 index 0000000000..c19931b3fa --- /dev/null +++ b/target/linux/generic/backport-5.15/839-v6.12-0001-nvmem-imx-ocotp-ele-support-i.MX95.patch @@ -0,0 +1,73 @@ +From c3f9b7b4e5f9de319d00784577cda42036ff243a Mon Sep 17 00:00:00 2001 +From: Peng Fan <peng.fan@nxp.com> +Date: Mon, 2 Sep 2024 15:29:45 +0100 +Subject: [PATCH] nvmem: imx-ocotp-ele: support i.MX95 + +i.MX95 OCOTP has same accessing method, so add an entry for i.MX95, but +some fuse has ECC feature, so only read out the lower 16bits for ECC fuses. + +Signed-off-by: Peng Fan <peng.fan@nxp.com> +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> +Link: https://lore.kernel.org/r/20240902142952.71639-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/nvmem/imx-ocotp-ele.c | 32 +++++++++++++++++++++++++++++--- + 1 file changed, 29 insertions(+), 3 deletions(-) + +--- a/drivers/nvmem/imx-ocotp-ele.c ++++ b/drivers/nvmem/imx-ocotp-ele.c +@@ -14,8 +14,9 @@ + #include <linux/slab.h> + + enum fuse_type { +- FUSE_FSB = 1, +- FUSE_ELE = 2, ++ FUSE_FSB = BIT(0), ++ FUSE_ELE = BIT(1), ++ FUSE_ECC = BIT(2), + FUSE_INVALID = -1 + }; + +@@ -93,7 +94,10 @@ static int imx_ocotp_reg_read(void *cont + continue; + } + +- *buf++ = readl_relaxed(reg + (i << 2)); ++ if (type & FUSE_ECC) ++ *buf++ = readl_relaxed(reg + (i << 2)) & GENMASK(15, 0); ++ else ++ *buf++ = readl_relaxed(reg + (i << 2)); + } + + memcpy(val, (u8 *)p, bytes); +@@ -155,8 +159,30 @@ static const struct ocotp_devtype_data i + }, + }; + ++static const struct ocotp_devtype_data imx95_ocotp_data = { ++ .reg_off = 0x8000, ++ .reg_read = imx_ocotp_reg_read, ++ .size = 2048, ++ .num_entry = 12, ++ .entry = { ++ { 0, 1, FUSE_FSB | FUSE_ECC }, ++ { 7, 1, FUSE_FSB | FUSE_ECC }, ++ { 9, 3, FUSE_FSB | FUSE_ECC }, ++ { 12, 24, FUSE_FSB }, ++ { 36, 2, FUSE_FSB | FUSE_ECC }, ++ { 38, 14, FUSE_FSB }, ++ { 63, 1, FUSE_ELE }, ++ { 128, 16, FUSE_ELE }, ++ { 188, 1, FUSE_ELE }, ++ { 317, 2, FUSE_FSB | FUSE_ECC }, ++ { 320, 7, FUSE_FSB }, ++ { 328, 184, FUSE_FSB } ++ }, ++}; ++ + static const struct of_device_id imx_ele_ocotp_dt_ids[] = { + { .compatible = "fsl,imx93-ocotp", .data = &imx93_ocotp_data, }, ++ { .compatible = "fsl,imx95-ocotp", .data = &imx95_ocotp_data, }, + {}, + }; + MODULE_DEVICE_TABLE(of, imx_ele_ocotp_dt_ids); diff --git a/target/linux/generic/backport-5.15/839-v6.12-0002-nvmem-sunplus-ocotp-Use-devm_platform_ioremap_resour.patch b/target/linux/generic/backport-5.15/839-v6.12-0002-nvmem-sunplus-ocotp-Use-devm_platform_ioremap_resour.patch new file mode 100644 index 0000000000..13ef50b157 --- /dev/null +++ b/target/linux/generic/backport-5.15/839-v6.12-0002-nvmem-sunplus-ocotp-Use-devm_platform_ioremap_resour.patch @@ -0,0 +1,44 @@ +From 98ee46391baf35987227236d0c3bb30ab6e758c8 Mon Sep 17 00:00:00 2001 +From: Zhang Zekun <zhangzekun11@huawei.com> +Date: Mon, 2 Sep 2024 15:29:50 +0100 +Subject: [PATCH] nvmem: sunplus-ocotp: Use + devm_platform_ioremap_resource_byname() helper function + +platform_get_resource_byname() and devm_ioremap_resource() can be +replaced by devm_platform_ioremap_resource_byname(), which can +simplify the code logic a bit, No functional change here. + +Signed-off-by: Zhang Zekun <zhangzekun11@huawei.com> +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> +Link: https://lore.kernel.org/r/20240902142952.71639-8-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/nvmem/sunplus-ocotp.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +--- a/drivers/nvmem/sunplus-ocotp.c ++++ b/drivers/nvmem/sunplus-ocotp.c +@@ -159,7 +159,6 @@ static int sp_ocotp_probe(struct platfor + struct device *dev = &pdev->dev; + struct nvmem_device *nvmem; + struct sp_ocotp_priv *otp; +- struct resource *res; + int ret; + + otp = devm_kzalloc(dev, sizeof(*otp), GFP_KERNEL); +@@ -168,13 +167,11 @@ static int sp_ocotp_probe(struct platfor + + otp->dev = dev; + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hb_gpio"); +- otp->base[HB_GPIO] = devm_ioremap_resource(dev, res); ++ otp->base[HB_GPIO] = devm_platform_ioremap_resource_byname(pdev, "hb_gpio"); + if (IS_ERR(otp->base[HB_GPIO])) + return PTR_ERR(otp->base[HB_GPIO]); + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otprx"); +- otp->base[OTPRX] = devm_ioremap_resource(dev, res); ++ otp->base[OTPRX] = devm_platform_ioremap_resource_byname(pdev, "otprx"); + if (IS_ERR(otp->base[OTPRX])) + return PTR_ERR(otp->base[OTPRX]); + diff --git a/target/linux/generic/backport-5.15/839-v6.12-0003-nvmem-layouts-add-U-Boot-env-layout.patch b/target/linux/generic/backport-5.15/839-v6.12-0003-nvmem-layouts-add-U-Boot-env-layout.patch new file mode 100644 index 0000000000..138e602a54 --- /dev/null +++ b/target/linux/generic/backport-5.15/839-v6.12-0003-nvmem-layouts-add-U-Boot-env-layout.patch @@ -0,0 +1,515 @@ +From 5f15811286aff4664bf275a7ede64e1b8858151b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl> +Date: Mon, 2 Sep 2024 15:29:47 +0100 +Subject: [PATCH] nvmem: layouts: add U-Boot env layout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +U-Boot environment variables are stored in a specific format. Actual +data can be placed in various storage sources (MTD, UBI volume, EEPROM, +NVRAM, etc.). + +Move all generic (NVMEM device independent) code from NVMEM device +driver to an NVMEM layout driver. Then add a simple NVMEM layout code on +top of it. + +This allows using NVMEM layout for parsing U-Boot env data stored in any +kind of NVMEM device. + +The old NVMEM glue driver stays in place for handling bindings in the +MTD context. To avoid code duplication it uses exported layout parsing +function. Please note that handling MTD & NVMEM layout bindings may be +refactored in the future. + +Signed-off-by: Rafał Miłecki <rafal@milecki.pl> +Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> +Link: https://lore.kernel.org/r/20240902142952.71639-5-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + MAINTAINERS | 1 + + drivers/nvmem/Kconfig | 3 +- + drivers/nvmem/layouts/Kconfig | 11 ++ + drivers/nvmem/layouts/Makefile | 1 + + drivers/nvmem/layouts/u-boot-env.c | 211 +++++++++++++++++++++++++++++ + drivers/nvmem/layouts/u-boot-env.h | 15 ++ + drivers/nvmem/u-boot-env.c | 165 +--------------------- + 7 files changed, 242 insertions(+), 165 deletions(-) + create mode 100644 drivers/nvmem/layouts/u-boot-env.c + create mode 100644 drivers/nvmem/layouts/u-boot-env.h + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -363,8 +363,7 @@ config NVMEM_SUNXI_SID + config NVMEM_U_BOOT_ENV + tristate "U-Boot environment variables support" + depends on OF && MTD +- select CRC32 +- select GENERIC_NET_UTILS ++ select NVMEM_LAYOUT_U_BOOT_ENV + help + U-Boot stores its setup as environment variables. This driver adds + support for verifying & exporting such data. It also exposes variables +--- a/drivers/nvmem/layouts/Kconfig ++++ b/drivers/nvmem/layouts/Kconfig +@@ -26,6 +26,17 @@ config NVMEM_LAYOUT_ONIE_TLV + + If unsure, say N. + ++config NVMEM_LAYOUT_U_BOOT_ENV ++ tristate "U-Boot environment variables layout" ++ select CRC32 ++ select GENERIC_NET_UTILS ++ help ++ U-Boot stores its setup as environment variables. This driver adds ++ support for verifying & exporting such data. It also exposes variables ++ as NVMEM cells so they can be referenced by other drivers. ++ ++ If unsure, say N. ++ + endmenu + + endif +--- a/drivers/nvmem/layouts/Makefile ++++ b/drivers/nvmem/layouts/Makefile +@@ -5,3 +5,4 @@ + + obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o + obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o ++obj-$(CONFIG_NVMEM_LAYOUT_U_BOOT_ENV) += u-boot-env.o +--- /dev/null ++++ b/drivers/nvmem/layouts/u-boot-env.c +@@ -0,0 +1,211 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2022 - 2023 Rafał Miłecki <rafal@milecki.pl> ++ */ ++ ++#include <linux/crc32.h> ++#include <linux/etherdevice.h> ++#include <linux/export.h> ++#include <linux/if_ether.h> ++#include <linux/nvmem-consumer.h> ++#include <linux/nvmem-provider.h> ++#include <linux/of.h> ++#include <linux/slab.h> ++ ++#include "u-boot-env.h" ++ ++struct u_boot_env_image_single { ++ __le32 crc32; ++ uint8_t data[]; ++} __packed; ++ ++struct u_boot_env_image_redundant { ++ __le32 crc32; ++ u8 mark; ++ uint8_t data[]; ++} __packed; ++ ++struct u_boot_env_image_broadcom { ++ __le32 magic; ++ __le32 len; ++ __le32 crc32; ++ DECLARE_FLEX_ARRAY(uint8_t, data); ++} __packed; ++ ++static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index, ++ unsigned int offset, void *buf, size_t bytes) ++{ ++ u8 mac[ETH_ALEN]; ++ ++ if (bytes != 3 * ETH_ALEN - 1) ++ return -EINVAL; ++ ++ if (!mac_pton(buf, mac)) ++ return -EINVAL; ++ ++ if (index) ++ eth_addr_add(mac, index); ++ ++ ether_addr_copy(buf, mac); ++ ++ return 0; ++} ++ ++static int u_boot_env_parse_cells(struct device *dev, struct nvmem_device *nvmem, uint8_t *buf, ++ size_t data_offset, size_t data_len) ++{ ++ char *data = buf + data_offset; ++ char *var, *value, *eq; ++ ++ for (var = data; ++ var < data + data_len && *var; ++ var = value + strlen(value) + 1) { ++ struct nvmem_cell_info info = {}; ++ ++ eq = strchr(var, '='); ++ if (!eq) ++ break; ++ *eq = '\0'; ++ value = eq + 1; ++ ++ info.name = devm_kstrdup(dev, var, GFP_KERNEL); ++ if (!info.name) ++ return -ENOMEM; ++ info.offset = data_offset + value - data; ++ info.bytes = strlen(value); ++ info.np = of_get_child_by_name(dev->of_node, info.name); ++ if (!strcmp(var, "ethaddr")) { ++ info.raw_len = strlen(value); ++ info.bytes = ETH_ALEN; ++ info.read_post_process = u_boot_env_read_post_process_ethaddr; ++ } ++ ++ nvmem_add_one_cell(nvmem, &info); ++ } ++ ++ return 0; ++} ++ ++int u_boot_env_parse(struct device *dev, struct nvmem_device *nvmem, ++ enum u_boot_env_format format) ++{ ++ size_t crc32_data_offset; ++ size_t crc32_data_len; ++ size_t crc32_offset; ++ __le32 *crc32_addr; ++ size_t data_offset; ++ size_t data_len; ++ size_t dev_size; ++ uint32_t crc32; ++ uint32_t calc; ++ uint8_t *buf; ++ int bytes; ++ int err; ++ ++ dev_size = nvmem_dev_size(nvmem); ++ ++ buf = kzalloc(dev_size, GFP_KERNEL); ++ if (!buf) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ bytes = nvmem_device_read(nvmem, 0, dev_size, buf); ++ if (bytes < 0) { ++ err = bytes; ++ goto err_kfree; ++ } else if (bytes != dev_size) { ++ err = -EIO; ++ goto err_kfree; ++ } ++ ++ switch (format) { ++ case U_BOOT_FORMAT_SINGLE: ++ crc32_offset = offsetof(struct u_boot_env_image_single, crc32); ++ crc32_data_offset = offsetof(struct u_boot_env_image_single, data); ++ data_offset = offsetof(struct u_boot_env_image_single, data); ++ break; ++ case U_BOOT_FORMAT_REDUNDANT: ++ crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32); ++ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); ++ data_offset = offsetof(struct u_boot_env_image_redundant, data); ++ break; ++ case U_BOOT_FORMAT_BROADCOM: ++ crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32); ++ crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data); ++ data_offset = offsetof(struct u_boot_env_image_broadcom, data); ++ break; ++ } ++ ++ if (dev_size < data_offset) { ++ dev_err(dev, "Device too small for u-boot-env\n"); ++ err = -EIO; ++ goto err_kfree; ++ } ++ ++ crc32_addr = (__le32 *)(buf + crc32_offset); ++ crc32 = le32_to_cpu(*crc32_addr); ++ crc32_data_len = dev_size - crc32_data_offset; ++ data_len = dev_size - data_offset; ++ ++ calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; ++ if (calc != crc32) { ++ dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32); ++ err = -EINVAL; ++ goto err_kfree; ++ } ++ ++ buf[dev_size - 1] = '\0'; ++ err = u_boot_env_parse_cells(dev, nvmem, buf, data_offset, data_len); ++ ++err_kfree: ++ kfree(buf); ++err_out: ++ return err; ++} ++EXPORT_SYMBOL_GPL(u_boot_env_parse); ++ ++static int u_boot_env_add_cells(struct nvmem_layout *layout) ++{ ++ struct device *dev = &layout->dev; ++ enum u_boot_env_format format; ++ ++ format = (uintptr_t)device_get_match_data(dev); ++ ++ return u_boot_env_parse(dev, layout->nvmem, format); ++} ++ ++static int u_boot_env_probe(struct nvmem_layout *layout) ++{ ++ layout->add_cells = u_boot_env_add_cells; ++ ++ return nvmem_layout_register(layout); ++} ++ ++static void u_boot_env_remove(struct nvmem_layout *layout) ++{ ++ nvmem_layout_unregister(layout); ++} ++ ++static const struct of_device_id u_boot_env_of_match_table[] = { ++ { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, }, ++ { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, ++ { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, ++ { .compatible = "brcm,env", .data = (void *)U_BOOT_FORMAT_BROADCOM, }, ++ {}, ++}; ++ ++static struct nvmem_layout_driver u_boot_env_layout = { ++ .driver = { ++ .name = "u-boot-env-layout", ++ .of_match_table = u_boot_env_of_match_table, ++ }, ++ .probe = u_boot_env_probe, ++ .remove = u_boot_env_remove, ++}; ++module_nvmem_layout_driver(u_boot_env_layout); ++ ++MODULE_AUTHOR("Rafał Miłecki"); ++MODULE_LICENSE("GPL"); ++MODULE_DEVICE_TABLE(of, u_boot_env_of_match_table); ++MODULE_DESCRIPTION("NVMEM layout driver for U-Boot environment variables"); +--- /dev/null ++++ b/drivers/nvmem/layouts/u-boot-env.h +@@ -0,0 +1,15 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#ifndef _LINUX_NVMEM_LAYOUTS_U_BOOT_ENV_H ++#define _LINUX_NVMEM_LAYOUTS_U_BOOT_ENV_H ++ ++enum u_boot_env_format { ++ U_BOOT_FORMAT_SINGLE, ++ U_BOOT_FORMAT_REDUNDANT, ++ U_BOOT_FORMAT_BROADCOM, ++}; ++ ++int u_boot_env_parse(struct device *dev, struct nvmem_device *nvmem, ++ enum u_boot_env_format format); ++ ++#endif /* ifndef _LINUX_NVMEM_LAYOUTS_U_BOOT_ENV_H */ +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -3,23 +3,15 @@ + * Copyright (C) 2022 Rafał Miłecki <rafal@milecki.pl> + */ + +-#include <linux/crc32.h> +-#include <linux/etherdevice.h> +-#include <linux/if_ether.h> + #include <linux/mod_devicetable.h> + #include <linux/module.h> + #include <linux/mtd/mtd.h> +-#include <linux/nvmem-consumer.h> + #include <linux/nvmem-provider.h> + #include <linux/of_device.h> + #include <linux/platform_device.h> + #include <linux/slab.h> + +-enum u_boot_env_format { +- U_BOOT_FORMAT_SINGLE, +- U_BOOT_FORMAT_REDUNDANT, +- U_BOOT_FORMAT_BROADCOM, +-}; ++#include "layouts/u-boot-env.h" + + struct u_boot_env { + struct device *dev; +@@ -29,24 +21,6 @@ struct u_boot_env { + struct mtd_info *mtd; + }; + +-struct u_boot_env_image_single { +- __le32 crc32; +- uint8_t data[]; +-} __packed; +- +-struct u_boot_env_image_redundant { +- __le32 crc32; +- u8 mark; +- uint8_t data[]; +-} __packed; +- +-struct u_boot_env_image_broadcom { +- __le32 magic; +- __le32 len; +- __le32 crc32; +- DECLARE_FLEX_ARRAY(uint8_t, data); +-} __packed; +- + static int u_boot_env_read(void *context, unsigned int offset, void *val, + size_t bytes) + { +@@ -69,141 +43,6 @@ static int u_boot_env_read(void *context + return 0; + } + +-static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index, +- unsigned int offset, void *buf, size_t bytes) +-{ +- u8 mac[ETH_ALEN]; +- +- if (bytes != 3 * ETH_ALEN - 1) +- return -EINVAL; +- +- if (!mac_pton(buf, mac)) +- return -EINVAL; +- +- if (index) +- eth_addr_add(mac, index); +- +- ether_addr_copy(buf, mac); +- +- return 0; +-} +- +-static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, +- size_t data_offset, size_t data_len) +-{ +- struct nvmem_device *nvmem = priv->nvmem; +- struct device *dev = priv->dev; +- char *data = buf + data_offset; +- char *var, *value, *eq; +- +- for (var = data; +- var < data + data_len && *var; +- var = value + strlen(value) + 1) { +- struct nvmem_cell_info info = {}; +- +- eq = strchr(var, '='); +- if (!eq) +- break; +- *eq = '\0'; +- value = eq + 1; +- +- info.name = devm_kstrdup(dev, var, GFP_KERNEL); +- if (!info.name) +- return -ENOMEM; +- info.offset = data_offset + value - data; +- info.bytes = strlen(value); +- info.np = of_get_child_by_name(dev->of_node, info.name); +- if (!strcmp(var, "ethaddr")) { +- info.raw_len = strlen(value); +- info.bytes = ETH_ALEN; +- info.read_post_process = u_boot_env_read_post_process_ethaddr; +- } +- +- nvmem_add_one_cell(nvmem, &info); +- } +- +- return 0; +-} +- +-static int u_boot_env_parse(struct u_boot_env *priv) +-{ +- struct nvmem_device *nvmem = priv->nvmem; +- struct device *dev = priv->dev; +- size_t crc32_data_offset; +- size_t crc32_data_len; +- size_t crc32_offset; +- __le32 *crc32_addr; +- size_t data_offset; +- size_t data_len; +- size_t dev_size; +- uint32_t crc32; +- uint32_t calc; +- uint8_t *buf; +- int bytes; +- int err; +- +- dev_size = nvmem_dev_size(nvmem); +- +- buf = kzalloc(dev_size, GFP_KERNEL); +- if (!buf) { +- err = -ENOMEM; +- goto err_out; +- } +- +- bytes = nvmem_device_read(nvmem, 0, dev_size, buf); +- if (bytes < 0) { +- err = bytes; +- goto err_kfree; +- } else if (bytes != dev_size) { +- err = -EIO; +- goto err_kfree; +- } +- +- switch (priv->format) { +- case U_BOOT_FORMAT_SINGLE: +- crc32_offset = offsetof(struct u_boot_env_image_single, crc32); +- crc32_data_offset = offsetof(struct u_boot_env_image_single, data); +- data_offset = offsetof(struct u_boot_env_image_single, data); +- break; +- case U_BOOT_FORMAT_REDUNDANT: +- crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32); +- crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); +- data_offset = offsetof(struct u_boot_env_image_redundant, data); +- break; +- case U_BOOT_FORMAT_BROADCOM: +- crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32); +- crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data); +- data_offset = offsetof(struct u_boot_env_image_broadcom, data); +- break; +- } +- +- if (dev_size < data_offset) { +- dev_err(dev, "Device too small for u-boot-env\n"); +- err = -EIO; +- goto err_kfree; +- } +- +- crc32_addr = (__le32 *)(buf + crc32_offset); +- crc32 = le32_to_cpu(*crc32_addr); +- crc32_data_len = dev_size - crc32_data_offset; +- data_len = dev_size - data_offset; +- +- calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; +- if (calc != crc32) { +- dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32); +- err = -EINVAL; +- goto err_kfree; +- } +- +- buf[dev_size - 1] = '\0'; +- err = u_boot_env_add_cells(priv, buf, data_offset, data_len); +- +-err_kfree: +- kfree(buf); +-err_out: +- return err; +-} +- + static int u_boot_env_probe(struct platform_device *pdev) + { + struct nvmem_config config = { +@@ -235,7 +74,7 @@ static int u_boot_env_probe(struct platf + if (IS_ERR(priv->nvmem)) + return PTR_ERR(priv->nvmem); + +- return u_boot_env_parse(priv); ++ return u_boot_env_parse(dev, priv->nvmem, priv->format); + } + + static const struct of_device_id u_boot_env_of_match_table[] = { diff --git a/target/linux/generic/backport-6.1/829-v6.10-0001-nvmem-layouts-store-owner-from-modules-with-nvmem_la.patch b/target/linux/generic/backport-6.1/829-v6.10-0001-nvmem-layouts-store-owner-from-modules-with-nvmem_la.patch index 418d2c82b2..c15b4b2265 100644 --- a/target/linux/generic/backport-6.1/829-v6.10-0001-nvmem-layouts-store-owner-from-modules-with-nvmem_la.patch +++ b/target/linux/generic/backport-6.1/829-v6.10-0001-nvmem-layouts-store-owner-from-modules-with-nvmem_la.patch @@ -27,7 +27,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- a/drivers/nvmem/layouts.c +++ b/drivers/nvmem/layouts.c -@@ -52,13 +52,15 @@ static const struct bus_type nvmem_layou +@@ -52,13 +52,15 @@ static struct bus_type nvmem_layout_bus_ .remove = nvmem_layout_bus_remove, }; diff --git a/target/linux/generic/backport-6.1/841-v6.12-0001-nvmem-imx-ocotp-ele-support-i.MX95.patch b/target/linux/generic/backport-6.1/841-v6.12-0001-nvmem-imx-ocotp-ele-support-i.MX95.patch new file mode 100644 index 0000000000..c19931b3fa --- /dev/null +++ b/target/linux/generic/backport-6.1/841-v6.12-0001-nvmem-imx-ocotp-ele-support-i.MX95.patch @@ -0,0 +1,73 @@ +From c3f9b7b4e5f9de319d00784577cda42036ff243a Mon Sep 17 00:00:00 2001 +From: Peng Fan <peng.fan@nxp.com> +Date: Mon, 2 Sep 2024 15:29:45 +0100 +Subject: [PATCH] nvmem: imx-ocotp-ele: support i.MX95 + +i.MX95 OCOTP has same accessing method, so add an entry for i.MX95, but +some fuse has ECC feature, so only read out the lower 16bits for ECC fuses. + +Signed-off-by: Peng Fan <peng.fan@nxp.com> +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> +Link: https://lore.kernel.org/r/20240902142952.71639-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/nvmem/imx-ocotp-ele.c | 32 +++++++++++++++++++++++++++++--- + 1 file changed, 29 insertions(+), 3 deletions(-) + +--- a/drivers/nvmem/imx-ocotp-ele.c ++++ b/drivers/nvmem/imx-ocotp-ele.c +@@ -14,8 +14,9 @@ + #include <linux/slab.h> + + enum fuse_type { +- FUSE_FSB = 1, +- FUSE_ELE = 2, ++ FUSE_FSB = BIT(0), ++ FUSE_ELE = BIT(1), ++ FUSE_ECC = BIT(2), + FUSE_INVALID = -1 + }; + +@@ -93,7 +94,10 @@ static int imx_ocotp_reg_read(void *cont + continue; + } + +- *buf++ = readl_relaxed(reg + (i << 2)); ++ if (type & FUSE_ECC) ++ *buf++ = readl_relaxed(reg + (i << 2)) & GENMASK(15, 0); ++ else ++ *buf++ = readl_relaxed(reg + (i << 2)); + } + + memcpy(val, (u8 *)p, bytes); +@@ -155,8 +159,30 @@ static const struct ocotp_devtype_data i + }, + }; + ++static const struct ocotp_devtype_data imx95_ocotp_data = { ++ .reg_off = 0x8000, ++ .reg_read = imx_ocotp_reg_read, ++ .size = 2048, ++ .num_entry = 12, ++ .entry = { ++ { 0, 1, FUSE_FSB | FUSE_ECC }, ++ { 7, 1, FUSE_FSB | FUSE_ECC }, ++ { 9, 3, FUSE_FSB | FUSE_ECC }, ++ { 12, 24, FUSE_FSB }, ++ { 36, 2, FUSE_FSB | FUSE_ECC }, ++ { 38, 14, FUSE_FSB }, ++ { 63, 1, FUSE_ELE }, ++ { 128, 16, FUSE_ELE }, ++ { 188, 1, FUSE_ELE }, ++ { 317, 2, FUSE_FSB | FUSE_ECC }, ++ { 320, 7, FUSE_FSB }, ++ { 328, 184, FUSE_FSB } ++ }, ++}; ++ + static const struct of_device_id imx_ele_ocotp_dt_ids[] = { + { .compatible = "fsl,imx93-ocotp", .data = &imx93_ocotp_data, }, ++ { .compatible = "fsl,imx95-ocotp", .data = &imx95_ocotp_data, }, + {}, + }; + MODULE_DEVICE_TABLE(of, imx_ele_ocotp_dt_ids); diff --git a/target/linux/generic/backport-6.1/841-v6.12-0002-nvmem-sunplus-ocotp-Use-devm_platform_ioremap_resour.patch b/target/linux/generic/backport-6.1/841-v6.12-0002-nvmem-sunplus-ocotp-Use-devm_platform_ioremap_resour.patch new file mode 100644 index 0000000000..13ef50b157 --- /dev/null +++ b/target/linux/generic/backport-6.1/841-v6.12-0002-nvmem-sunplus-ocotp-Use-devm_platform_ioremap_resour.patch @@ -0,0 +1,44 @@ +From 98ee46391baf35987227236d0c3bb30ab6e758c8 Mon Sep 17 00:00:00 2001 +From: Zhang Zekun <zhangzekun11@huawei.com> +Date: Mon, 2 Sep 2024 15:29:50 +0100 +Subject: [PATCH] nvmem: sunplus-ocotp: Use + devm_platform_ioremap_resource_byname() helper function + +platform_get_resource_byname() and devm_ioremap_resource() can be +replaced by devm_platform_ioremap_resource_byname(), which can +simplify the code logic a bit, No functional change here. + +Signed-off-by: Zhang Zekun <zhangzekun11@huawei.com> +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> +Link: https://lore.kernel.org/r/20240902142952.71639-8-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/nvmem/sunplus-ocotp.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +--- a/drivers/nvmem/sunplus-ocotp.c ++++ b/drivers/nvmem/sunplus-ocotp.c +@@ -159,7 +159,6 @@ static int sp_ocotp_probe(struct platfor + struct device *dev = &pdev->dev; + struct nvmem_device *nvmem; + struct sp_ocotp_priv *otp; +- struct resource *res; + int ret; + + otp = devm_kzalloc(dev, sizeof(*otp), GFP_KERNEL); +@@ -168,13 +167,11 @@ static int sp_ocotp_probe(struct platfor + + otp->dev = dev; + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hb_gpio"); +- otp->base[HB_GPIO] = devm_ioremap_resource(dev, res); ++ otp->base[HB_GPIO] = devm_platform_ioremap_resource_byname(pdev, "hb_gpio"); + if (IS_ERR(otp->base[HB_GPIO])) + return PTR_ERR(otp->base[HB_GPIO]); + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otprx"); +- otp->base[OTPRX] = devm_ioremap_resource(dev, res); ++ otp->base[OTPRX] = devm_platform_ioremap_resource_byname(pdev, "otprx"); + if (IS_ERR(otp->base[OTPRX])) + return PTR_ERR(otp->base[OTPRX]); + diff --git a/target/linux/generic/backport-6.1/841-v6.12-0003-nvmem-layouts-add-U-Boot-env-layout.patch b/target/linux/generic/backport-6.1/841-v6.12-0003-nvmem-layouts-add-U-Boot-env-layout.patch new file mode 100644 index 0000000000..e711c84c8d --- /dev/null +++ b/target/linux/generic/backport-6.1/841-v6.12-0003-nvmem-layouts-add-U-Boot-env-layout.patch @@ -0,0 +1,525 @@ +From 5f15811286aff4664bf275a7ede64e1b8858151b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl> +Date: Mon, 2 Sep 2024 15:29:47 +0100 +Subject: [PATCH] nvmem: layouts: add U-Boot env layout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +U-Boot environment variables are stored in a specific format. Actual +data can be placed in various storage sources (MTD, UBI volume, EEPROM, +NVRAM, etc.). + +Move all generic (NVMEM device independent) code from NVMEM device +driver to an NVMEM layout driver. Then add a simple NVMEM layout code on +top of it. + +This allows using NVMEM layout for parsing U-Boot env data stored in any +kind of NVMEM device. + +The old NVMEM glue driver stays in place for handling bindings in the +MTD context. To avoid code duplication it uses exported layout parsing +function. Please note that handling MTD & NVMEM layout bindings may be +refactored in the future. + +Signed-off-by: Rafał Miłecki <rafal@milecki.pl> +Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> +Link: https://lore.kernel.org/r/20240902142952.71639-5-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + MAINTAINERS | 1 + + drivers/nvmem/Kconfig | 3 +- + drivers/nvmem/layouts/Kconfig | 11 ++ + drivers/nvmem/layouts/Makefile | 1 + + drivers/nvmem/layouts/u-boot-env.c | 211 +++++++++++++++++++++++++++++ + drivers/nvmem/layouts/u-boot-env.h | 15 ++ + drivers/nvmem/u-boot-env.c | 165 +--------------------- + 7 files changed, 242 insertions(+), 165 deletions(-) + create mode 100644 drivers/nvmem/layouts/u-boot-env.c + create mode 100644 drivers/nvmem/layouts/u-boot-env.h + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -21033,6 +21033,7 @@ U-BOOT ENVIRONMENT VARIABLES + M: Rafał Miłecki <rafal@milecki.pl> + S: Maintained + F: Documentation/devicetree/bindings/nvmem/u-boot,env.yaml ++F: drivers/nvmem/layouts/u-boot-env.c + F: drivers/nvmem/u-boot-env.c + + UACCE ACCELERATOR FRAMEWORK +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -363,8 +363,7 @@ config NVMEM_SUNXI_SID + config NVMEM_U_BOOT_ENV + tristate "U-Boot environment variables support" + depends on OF && MTD +- select CRC32 +- select GENERIC_NET_UTILS ++ select NVMEM_LAYOUT_U_BOOT_ENV + help + U-Boot stores its setup as environment variables. This driver adds + support for verifying & exporting such data. It also exposes variables +--- a/drivers/nvmem/layouts/Kconfig ++++ b/drivers/nvmem/layouts/Kconfig +@@ -26,6 +26,17 @@ config NVMEM_LAYOUT_ONIE_TLV + + If unsure, say N. + ++config NVMEM_LAYOUT_U_BOOT_ENV ++ tristate "U-Boot environment variables layout" ++ select CRC32 ++ select GENERIC_NET_UTILS ++ help ++ U-Boot stores its setup as environment variables. This driver adds ++ support for verifying & exporting such data. It also exposes variables ++ as NVMEM cells so they can be referenced by other drivers. ++ ++ If unsure, say N. ++ + endmenu + + endif +--- a/drivers/nvmem/layouts/Makefile ++++ b/drivers/nvmem/layouts/Makefile +@@ -5,3 +5,4 @@ + + obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o + obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o ++obj-$(CONFIG_NVMEM_LAYOUT_U_BOOT_ENV) += u-boot-env.o +--- /dev/null ++++ b/drivers/nvmem/layouts/u-boot-env.c +@@ -0,0 +1,211 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2022 - 2023 Rafał Miłecki <rafal@milecki.pl> ++ */ ++ ++#include <linux/crc32.h> ++#include <linux/etherdevice.h> ++#include <linux/export.h> ++#include <linux/if_ether.h> ++#include <linux/nvmem-consumer.h> ++#include <linux/nvmem-provider.h> ++#include <linux/of.h> ++#include <linux/slab.h> ++ ++#include "u-boot-env.h" ++ ++struct u_boot_env_image_single { ++ __le32 crc32; ++ uint8_t data[]; ++} __packed; ++ ++struct u_boot_env_image_redundant { ++ __le32 crc32; ++ u8 mark; ++ uint8_t data[]; ++} __packed; ++ ++struct u_boot_env_image_broadcom { ++ __le32 magic; ++ __le32 len; ++ __le32 crc32; ++ DECLARE_FLEX_ARRAY(uint8_t, data); ++} __packed; ++ ++static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index, ++ unsigned int offset, void *buf, size_t bytes) ++{ ++ u8 mac[ETH_ALEN]; ++ ++ if (bytes != 3 * ETH_ALEN - 1) ++ return -EINVAL; ++ ++ if (!mac_pton(buf, mac)) ++ return -EINVAL; ++ ++ if (index) ++ eth_addr_add(mac, index); ++ ++ ether_addr_copy(buf, mac); ++ ++ return 0; ++} ++ ++static int u_boot_env_parse_cells(struct device *dev, struct nvmem_device *nvmem, uint8_t *buf, ++ size_t data_offset, size_t data_len) ++{ ++ char *data = buf + data_offset; ++ char *var, *value, *eq; ++ ++ for (var = data; ++ var < data + data_len && *var; ++ var = value + strlen(value) + 1) { ++ struct nvmem_cell_info info = {}; ++ ++ eq = strchr(var, '='); ++ if (!eq) ++ break; ++ *eq = '\0'; ++ value = eq + 1; ++ ++ info.name = devm_kstrdup(dev, var, GFP_KERNEL); ++ if (!info.name) ++ return -ENOMEM; ++ info.offset = data_offset + value - data; ++ info.bytes = strlen(value); ++ info.np = of_get_child_by_name(dev->of_node, info.name); ++ if (!strcmp(var, "ethaddr")) { ++ info.raw_len = strlen(value); ++ info.bytes = ETH_ALEN; ++ info.read_post_process = u_boot_env_read_post_process_ethaddr; ++ } ++ ++ nvmem_add_one_cell(nvmem, &info); ++ } ++ ++ return 0; ++} ++ ++int u_boot_env_parse(struct device *dev, struct nvmem_device *nvmem, ++ enum u_boot_env_format format) ++{ ++ size_t crc32_data_offset; ++ size_t crc32_data_len; ++ size_t crc32_offset; ++ __le32 *crc32_addr; ++ size_t data_offset; ++ size_t data_len; ++ size_t dev_size; ++ uint32_t crc32; ++ uint32_t calc; ++ uint8_t *buf; ++ int bytes; ++ int err; ++ ++ dev_size = nvmem_dev_size(nvmem); ++ ++ buf = kzalloc(dev_size, GFP_KERNEL); ++ if (!buf) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ bytes = nvmem_device_read(nvmem, 0, dev_size, buf); ++ if (bytes < 0) { ++ err = bytes; ++ goto err_kfree; ++ } else if (bytes != dev_size) { ++ err = -EIO; ++ goto err_kfree; ++ } ++ ++ switch (format) { ++ case U_BOOT_FORMAT_SINGLE: ++ crc32_offset = offsetof(struct u_boot_env_image_single, crc32); ++ crc32_data_offset = offsetof(struct u_boot_env_image_single, data); ++ data_offset = offsetof(struct u_boot_env_image_single, data); ++ break; ++ case U_BOOT_FORMAT_REDUNDANT: ++ crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32); ++ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); ++ data_offset = offsetof(struct u_boot_env_image_redundant, data); ++ break; ++ case U_BOOT_FORMAT_BROADCOM: ++ crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32); ++ crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data); ++ data_offset = offsetof(struct u_boot_env_image_broadcom, data); ++ break; ++ } ++ ++ if (dev_size < data_offset) { ++ dev_err(dev, "Device too small for u-boot-env\n"); ++ err = -EIO; ++ goto err_kfree; ++ } ++ ++ crc32_addr = (__le32 *)(buf + crc32_offset); ++ crc32 = le32_to_cpu(*crc32_addr); ++ crc32_data_len = dev_size - crc32_data_offset; ++ data_len = dev_size - data_offset; ++ ++ calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; ++ if (calc != crc32) { ++ dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32); ++ err = -EINVAL; ++ goto err_kfree; ++ } ++ ++ buf[dev_size - 1] = '\0'; ++ err = u_boot_env_parse_cells(dev, nvmem, buf, data_offset, data_len); ++ ++err_kfree: ++ kfree(buf); ++err_out: ++ return err; ++} ++EXPORT_SYMBOL_GPL(u_boot_env_parse); ++ ++static int u_boot_env_add_cells(struct nvmem_layout *layout) ++{ ++ struct device *dev = &layout->dev; ++ enum u_boot_env_format format; ++ ++ format = (uintptr_t)device_get_match_data(dev); ++ ++ return u_boot_env_parse(dev, layout->nvmem, format); ++} ++ ++static int u_boot_env_probe(struct nvmem_layout *layout) ++{ ++ layout->add_cells = u_boot_env_add_cells; ++ ++ return nvmem_layout_register(layout); ++} ++ ++static void u_boot_env_remove(struct nvmem_layout *layout) ++{ ++ nvmem_layout_unregister(layout); ++} ++ ++static const struct of_device_id u_boot_env_of_match_table[] = { ++ { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, }, ++ { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, ++ { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, ++ { .compatible = "brcm,env", .data = (void *)U_BOOT_FORMAT_BROADCOM, }, ++ {}, ++}; ++ ++static struct nvmem_layout_driver u_boot_env_layout = { ++ .driver = { ++ .name = "u-boot-env-layout", ++ .of_match_table = u_boot_env_of_match_table, ++ }, ++ .probe = u_boot_env_probe, ++ .remove = u_boot_env_remove, ++}; ++module_nvmem_layout_driver(u_boot_env_layout); ++ ++MODULE_AUTHOR("Rafał Miłecki"); ++MODULE_LICENSE("GPL"); ++MODULE_DEVICE_TABLE(of, u_boot_env_of_match_table); ++MODULE_DESCRIPTION("NVMEM layout driver for U-Boot environment variables"); +--- /dev/null ++++ b/drivers/nvmem/layouts/u-boot-env.h +@@ -0,0 +1,15 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#ifndef _LINUX_NVMEM_LAYOUTS_U_BOOT_ENV_H ++#define _LINUX_NVMEM_LAYOUTS_U_BOOT_ENV_H ++ ++enum u_boot_env_format { ++ U_BOOT_FORMAT_SINGLE, ++ U_BOOT_FORMAT_REDUNDANT, ++ U_BOOT_FORMAT_BROADCOM, ++}; ++ ++int u_boot_env_parse(struct device *dev, struct nvmem_device *nvmem, ++ enum u_boot_env_format format); ++ ++#endif /* ifndef _LINUX_NVMEM_LAYOUTS_U_BOOT_ENV_H */ +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -3,23 +3,15 @@ + * Copyright (C) 2022 Rafał Miłecki <rafal@milecki.pl> + */ + +-#include <linux/crc32.h> +-#include <linux/etherdevice.h> +-#include <linux/if_ether.h> + #include <linux/mod_devicetable.h> + #include <linux/module.h> + #include <linux/mtd/mtd.h> +-#include <linux/nvmem-consumer.h> + #include <linux/nvmem-provider.h> + #include <linux/of_device.h> + #include <linux/platform_device.h> + #include <linux/slab.h> + +-enum u_boot_env_format { +- U_BOOT_FORMAT_SINGLE, +- U_BOOT_FORMAT_REDUNDANT, +- U_BOOT_FORMAT_BROADCOM, +-}; ++#include "layouts/u-boot-env.h" + + struct u_boot_env { + struct device *dev; +@@ -29,24 +21,6 @@ struct u_boot_env { + struct mtd_info *mtd; + }; + +-struct u_boot_env_image_single { +- __le32 crc32; +- uint8_t data[]; +-} __packed; +- +-struct u_boot_env_image_redundant { +- __le32 crc32; +- u8 mark; +- uint8_t data[]; +-} __packed; +- +-struct u_boot_env_image_broadcom { +- __le32 magic; +- __le32 len; +- __le32 crc32; +- DECLARE_FLEX_ARRAY(uint8_t, data); +-} __packed; +- + static int u_boot_env_read(void *context, unsigned int offset, void *val, + size_t bytes) + { +@@ -69,141 +43,6 @@ static int u_boot_env_read(void *context + return 0; + } + +-static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index, +- unsigned int offset, void *buf, size_t bytes) +-{ +- u8 mac[ETH_ALEN]; +- +- if (bytes != 3 * ETH_ALEN - 1) +- return -EINVAL; +- +- if (!mac_pton(buf, mac)) +- return -EINVAL; +- +- if (index) +- eth_addr_add(mac, index); +- +- ether_addr_copy(buf, mac); +- +- return 0; +-} +- +-static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, +- size_t data_offset, size_t data_len) +-{ +- struct nvmem_device *nvmem = priv->nvmem; +- struct device *dev = priv->dev; +- char *data = buf + data_offset; +- char *var, *value, *eq; +- +- for (var = data; +- var < data + data_len && *var; +- var = value + strlen(value) + 1) { +- struct nvmem_cell_info info = {}; +- +- eq = strchr(var, '='); +- if (!eq) +- break; +- *eq = '\0'; +- value = eq + 1; +- +- info.name = devm_kstrdup(dev, var, GFP_KERNEL); +- if (!info.name) +- return -ENOMEM; +- info.offset = data_offset + value - data; +- info.bytes = strlen(value); +- info.np = of_get_child_by_name(dev->of_node, info.name); +- if (!strcmp(var, "ethaddr")) { +- info.raw_len = strlen(value); +- info.bytes = ETH_ALEN; +- info.read_post_process = u_boot_env_read_post_process_ethaddr; +- } +- +- nvmem_add_one_cell(nvmem, &info); +- } +- +- return 0; +-} +- +-static int u_boot_env_parse(struct u_boot_env *priv) +-{ +- struct nvmem_device *nvmem = priv->nvmem; +- struct device *dev = priv->dev; +- size_t crc32_data_offset; +- size_t crc32_data_len; +- size_t crc32_offset; +- __le32 *crc32_addr; +- size_t data_offset; +- size_t data_len; +- size_t dev_size; +- uint32_t crc32; +- uint32_t calc; +- uint8_t *buf; +- int bytes; +- int err; +- +- dev_size = nvmem_dev_size(nvmem); +- +- buf = kzalloc(dev_size, GFP_KERNEL); +- if (!buf) { +- err = -ENOMEM; +- goto err_out; +- } +- +- bytes = nvmem_device_read(nvmem, 0, dev_size, buf); +- if (bytes < 0) { +- err = bytes; +- goto err_kfree; +- } else if (bytes != dev_size) { +- err = -EIO; +- goto err_kfree; +- } +- +- switch (priv->format) { +- case U_BOOT_FORMAT_SINGLE: +- crc32_offset = offsetof(struct u_boot_env_image_single, crc32); +- crc32_data_offset = offsetof(struct u_boot_env_image_single, data); +- data_offset = offsetof(struct u_boot_env_image_single, data); +- break; +- case U_BOOT_FORMAT_REDUNDANT: +- crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32); +- crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); +- data_offset = offsetof(struct u_boot_env_image_redundant, data); +- break; +- case U_BOOT_FORMAT_BROADCOM: +- crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32); +- crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data); +- data_offset = offsetof(struct u_boot_env_image_broadcom, data); +- break; +- } +- +- if (dev_size < data_offset) { +- dev_err(dev, "Device too small for u-boot-env\n"); +- err = -EIO; +- goto err_kfree; +- } +- +- crc32_addr = (__le32 *)(buf + crc32_offset); +- crc32 = le32_to_cpu(*crc32_addr); +- crc32_data_len = dev_size - crc32_data_offset; +- data_len = dev_size - data_offset; +- +- calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; +- if (calc != crc32) { +- dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32); +- err = -EINVAL; +- goto err_kfree; +- } +- +- buf[dev_size - 1] = '\0'; +- err = u_boot_env_add_cells(priv, buf, data_offset, data_len); +- +-err_kfree: +- kfree(buf); +-err_out: +- return err; +-} +- + static int u_boot_env_probe(struct platform_device *pdev) + { + struct nvmem_config config = { +@@ -235,7 +74,7 @@ static int u_boot_env_probe(struct platf + if (IS_ERR(priv->nvmem)) + return PTR_ERR(priv->nvmem); + +- return u_boot_env_parse(priv); ++ return u_boot_env_parse(dev, priv->nvmem, priv->format); + } + + static const struct of_device_id u_boot_env_of_match_table[] = { diff --git a/target/linux/generic/backport-6.6/823-v6.12-0001-nvmem-imx-ocotp-ele-support-i.MX95.patch b/target/linux/generic/backport-6.6/823-v6.12-0001-nvmem-imx-ocotp-ele-support-i.MX95.patch new file mode 100644 index 0000000000..c19931b3fa --- /dev/null +++ b/target/linux/generic/backport-6.6/823-v6.12-0001-nvmem-imx-ocotp-ele-support-i.MX95.patch @@ -0,0 +1,73 @@ +From c3f9b7b4e5f9de319d00784577cda42036ff243a Mon Sep 17 00:00:00 2001 +From: Peng Fan <peng.fan@nxp.com> +Date: Mon, 2 Sep 2024 15:29:45 +0100 +Subject: [PATCH] nvmem: imx-ocotp-ele: support i.MX95 + +i.MX95 OCOTP has same accessing method, so add an entry for i.MX95, but +some fuse has ECC feature, so only read out the lower 16bits for ECC fuses. + +Signed-off-by: Peng Fan <peng.fan@nxp.com> +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> +Link: https://lore.kernel.org/r/20240902142952.71639-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/nvmem/imx-ocotp-ele.c | 32 +++++++++++++++++++++++++++++--- + 1 file changed, 29 insertions(+), 3 deletions(-) + +--- a/drivers/nvmem/imx-ocotp-ele.c ++++ b/drivers/nvmem/imx-ocotp-ele.c +@@ -14,8 +14,9 @@ + #include <linux/slab.h> + + enum fuse_type { +- FUSE_FSB = 1, +- FUSE_ELE = 2, ++ FUSE_FSB = BIT(0), ++ FUSE_ELE = BIT(1), ++ FUSE_ECC = BIT(2), + FUSE_INVALID = -1 + }; + +@@ -93,7 +94,10 @@ static int imx_ocotp_reg_read(void *cont + continue; + } + +- *buf++ = readl_relaxed(reg + (i << 2)); ++ if (type & FUSE_ECC) ++ *buf++ = readl_relaxed(reg + (i << 2)) & GENMASK(15, 0); ++ else ++ *buf++ = readl_relaxed(reg + (i << 2)); + } + + memcpy(val, (u8 *)p, bytes); +@@ -155,8 +159,30 @@ static const struct ocotp_devtype_data i + }, + }; + ++static const struct ocotp_devtype_data imx95_ocotp_data = { ++ .reg_off = 0x8000, ++ .reg_read = imx_ocotp_reg_read, ++ .size = 2048, ++ .num_entry = 12, ++ .entry = { ++ { 0, 1, FUSE_FSB | FUSE_ECC }, ++ { 7, 1, FUSE_FSB | FUSE_ECC }, ++ { 9, 3, FUSE_FSB | FUSE_ECC }, ++ { 12, 24, FUSE_FSB }, ++ { 36, 2, FUSE_FSB | FUSE_ECC }, ++ { 38, 14, FUSE_FSB }, ++ { 63, 1, FUSE_ELE }, ++ { 128, 16, FUSE_ELE }, ++ { 188, 1, FUSE_ELE }, ++ { 317, 2, FUSE_FSB | FUSE_ECC }, ++ { 320, 7, FUSE_FSB }, ++ { 328, 184, FUSE_FSB } ++ }, ++}; ++ + static const struct of_device_id imx_ele_ocotp_dt_ids[] = { + { .compatible = "fsl,imx93-ocotp", .data = &imx93_ocotp_data, }, ++ { .compatible = "fsl,imx95-ocotp", .data = &imx95_ocotp_data, }, + {}, + }; + MODULE_DEVICE_TABLE(of, imx_ele_ocotp_dt_ids); diff --git a/target/linux/generic/backport-6.6/823-v6.12-0002-nvmem-sunplus-ocotp-Use-devm_platform_ioremap_resour.patch b/target/linux/generic/backport-6.6/823-v6.12-0002-nvmem-sunplus-ocotp-Use-devm_platform_ioremap_resour.patch new file mode 100644 index 0000000000..13ef50b157 --- /dev/null +++ b/target/linux/generic/backport-6.6/823-v6.12-0002-nvmem-sunplus-ocotp-Use-devm_platform_ioremap_resour.patch @@ -0,0 +1,44 @@ +From 98ee46391baf35987227236d0c3bb30ab6e758c8 Mon Sep 17 00:00:00 2001 +From: Zhang Zekun <zhangzekun11@huawei.com> +Date: Mon, 2 Sep 2024 15:29:50 +0100 +Subject: [PATCH] nvmem: sunplus-ocotp: Use + devm_platform_ioremap_resource_byname() helper function + +platform_get_resource_byname() and devm_ioremap_resource() can be +replaced by devm_platform_ioremap_resource_byname(), which can +simplify the code logic a bit, No functional change here. + +Signed-off-by: Zhang Zekun <zhangzekun11@huawei.com> +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> +Link: https://lore.kernel.org/r/20240902142952.71639-8-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/nvmem/sunplus-ocotp.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +--- a/drivers/nvmem/sunplus-ocotp.c ++++ b/drivers/nvmem/sunplus-ocotp.c +@@ -159,7 +159,6 @@ static int sp_ocotp_probe(struct platfor + struct device *dev = &pdev->dev; + struct nvmem_device *nvmem; + struct sp_ocotp_priv *otp; +- struct resource *res; + int ret; + + otp = devm_kzalloc(dev, sizeof(*otp), GFP_KERNEL); +@@ -168,13 +167,11 @@ static int sp_ocotp_probe(struct platfor + + otp->dev = dev; + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hb_gpio"); +- otp->base[HB_GPIO] = devm_ioremap_resource(dev, res); ++ otp->base[HB_GPIO] = devm_platform_ioremap_resource_byname(pdev, "hb_gpio"); + if (IS_ERR(otp->base[HB_GPIO])) + return PTR_ERR(otp->base[HB_GPIO]); + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otprx"); +- otp->base[OTPRX] = devm_ioremap_resource(dev, res); ++ otp->base[OTPRX] = devm_platform_ioremap_resource_byname(pdev, "otprx"); + if (IS_ERR(otp->base[OTPRX])) + return PTR_ERR(otp->base[OTPRX]); + diff --git a/target/linux/generic/backport-6.6/823-v6.12-0003-nvmem-layouts-add-U-Boot-env-layout.patch b/target/linux/generic/backport-6.6/823-v6.12-0003-nvmem-layouts-add-U-Boot-env-layout.patch new file mode 100644 index 0000000000..15a0f77bb3 --- /dev/null +++ b/target/linux/generic/backport-6.6/823-v6.12-0003-nvmem-layouts-add-U-Boot-env-layout.patch @@ -0,0 +1,525 @@ +From 5f15811286aff4664bf275a7ede64e1b8858151b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl> +Date: Mon, 2 Sep 2024 15:29:47 +0100 +Subject: [PATCH] nvmem: layouts: add U-Boot env layout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +U-Boot environment variables are stored in a specific format. Actual +data can be placed in various storage sources (MTD, UBI volume, EEPROM, +NVRAM, etc.). + +Move all generic (NVMEM device independent) code from NVMEM device +driver to an NVMEM layout driver. Then add a simple NVMEM layout code on +top of it. + +This allows using NVMEM layout for parsing U-Boot env data stored in any +kind of NVMEM device. + +The old NVMEM glue driver stays in place for handling bindings in the +MTD context. To avoid code duplication it uses exported layout parsing +function. Please note that handling MTD & NVMEM layout bindings may be +refactored in the future. + +Signed-off-by: Rafał Miłecki <rafal@milecki.pl> +Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> +Link: https://lore.kernel.org/r/20240902142952.71639-5-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + MAINTAINERS | 1 + + drivers/nvmem/Kconfig | 3 +- + drivers/nvmem/layouts/Kconfig | 11 ++ + drivers/nvmem/layouts/Makefile | 1 + + drivers/nvmem/layouts/u-boot-env.c | 211 +++++++++++++++++++++++++++++ + drivers/nvmem/layouts/u-boot-env.h | 15 ++ + drivers/nvmem/u-boot-env.c | 165 +--------------------- + 7 files changed, 242 insertions(+), 165 deletions(-) + create mode 100644 drivers/nvmem/layouts/u-boot-env.c + create mode 100644 drivers/nvmem/layouts/u-boot-env.h + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -21988,6 +21988,7 @@ U-BOOT ENVIRONMENT VARIABLES + M: Rafał Miłecki <rafal@milecki.pl> + S: Maintained + F: Documentation/devicetree/bindings/nvmem/u-boot,env.yaml ++F: drivers/nvmem/layouts/u-boot-env.c + F: drivers/nvmem/u-boot-env.c + + UACCE ACCELERATOR FRAMEWORK +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -363,8 +363,7 @@ config NVMEM_SUNXI_SID + config NVMEM_U_BOOT_ENV + tristate "U-Boot environment variables support" + depends on OF && MTD +- select CRC32 +- select GENERIC_NET_UTILS ++ select NVMEM_LAYOUT_U_BOOT_ENV + help + U-Boot stores its setup as environment variables. This driver adds + support for verifying & exporting such data. It also exposes variables +--- a/drivers/nvmem/layouts/Kconfig ++++ b/drivers/nvmem/layouts/Kconfig +@@ -26,6 +26,17 @@ config NVMEM_LAYOUT_ONIE_TLV + + If unsure, say N. + ++config NVMEM_LAYOUT_U_BOOT_ENV ++ tristate "U-Boot environment variables layout" ++ select CRC32 ++ select GENERIC_NET_UTILS ++ help ++ U-Boot stores its setup as environment variables. This driver adds ++ support for verifying & exporting such data. It also exposes variables ++ as NVMEM cells so they can be referenced by other drivers. ++ ++ If unsure, say N. ++ + endmenu + + endif +--- a/drivers/nvmem/layouts/Makefile ++++ b/drivers/nvmem/layouts/Makefile +@@ -5,3 +5,4 @@ + + obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o + obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o ++obj-$(CONFIG_NVMEM_LAYOUT_U_BOOT_ENV) += u-boot-env.o +--- /dev/null ++++ b/drivers/nvmem/layouts/u-boot-env.c +@@ -0,0 +1,211 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2022 - 2023 Rafał Miłecki <rafal@milecki.pl> ++ */ ++ ++#include <linux/crc32.h> ++#include <linux/etherdevice.h> ++#include <linux/export.h> ++#include <linux/if_ether.h> ++#include <linux/nvmem-consumer.h> ++#include <linux/nvmem-provider.h> ++#include <linux/of.h> ++#include <linux/slab.h> ++ ++#include "u-boot-env.h" ++ ++struct u_boot_env_image_single { ++ __le32 crc32; ++ uint8_t data[]; ++} __packed; ++ ++struct u_boot_env_image_redundant { ++ __le32 crc32; ++ u8 mark; ++ uint8_t data[]; ++} __packed; ++ ++struct u_boot_env_image_broadcom { ++ __le32 magic; ++ __le32 len; ++ __le32 crc32; ++ DECLARE_FLEX_ARRAY(uint8_t, data); ++} __packed; ++ ++static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index, ++ unsigned int offset, void *buf, size_t bytes) ++{ ++ u8 mac[ETH_ALEN]; ++ ++ if (bytes != 3 * ETH_ALEN - 1) ++ return -EINVAL; ++ ++ if (!mac_pton(buf, mac)) ++ return -EINVAL; ++ ++ if (index) ++ eth_addr_add(mac, index); ++ ++ ether_addr_copy(buf, mac); ++ ++ return 0; ++} ++ ++static int u_boot_env_parse_cells(struct device *dev, struct nvmem_device *nvmem, uint8_t *buf, ++ size_t data_offset, size_t data_len) ++{ ++ char *data = buf + data_offset; ++ char *var, *value, *eq; ++ ++ for (var = data; ++ var < data + data_len && *var; ++ var = value + strlen(value) + 1) { ++ struct nvmem_cell_info info = {}; ++ ++ eq = strchr(var, '='); ++ if (!eq) ++ break; ++ *eq = '\0'; ++ value = eq + 1; ++ ++ info.name = devm_kstrdup(dev, var, GFP_KERNEL); ++ if (!info.name) ++ return -ENOMEM; ++ info.offset = data_offset + value - data; ++ info.bytes = strlen(value); ++ info.np = of_get_child_by_name(dev->of_node, info.name); ++ if (!strcmp(var, "ethaddr")) { ++ info.raw_len = strlen(value); ++ info.bytes = ETH_ALEN; ++ info.read_post_process = u_boot_env_read_post_process_ethaddr; ++ } ++ ++ nvmem_add_one_cell(nvmem, &info); ++ } ++ ++ return 0; ++} ++ ++int u_boot_env_parse(struct device *dev, struct nvmem_device *nvmem, ++ enum u_boot_env_format format) ++{ ++ size_t crc32_data_offset; ++ size_t crc32_data_len; ++ size_t crc32_offset; ++ __le32 *crc32_addr; ++ size_t data_offset; ++ size_t data_len; ++ size_t dev_size; ++ uint32_t crc32; ++ uint32_t calc; ++ uint8_t *buf; ++ int bytes; ++ int err; ++ ++ dev_size = nvmem_dev_size(nvmem); ++ ++ buf = kzalloc(dev_size, GFP_KERNEL); ++ if (!buf) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ bytes = nvmem_device_read(nvmem, 0, dev_size, buf); ++ if (bytes < 0) { ++ err = bytes; ++ goto err_kfree; ++ } else if (bytes != dev_size) { ++ err = -EIO; ++ goto err_kfree; ++ } ++ ++ switch (format) { ++ case U_BOOT_FORMAT_SINGLE: ++ crc32_offset = offsetof(struct u_boot_env_image_single, crc32); ++ crc32_data_offset = offsetof(struct u_boot_env_image_single, data); ++ data_offset = offsetof(struct u_boot_env_image_single, data); ++ break; ++ case U_BOOT_FORMAT_REDUNDANT: ++ crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32); ++ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); ++ data_offset = offsetof(struct u_boot_env_image_redundant, data); ++ break; ++ case U_BOOT_FORMAT_BROADCOM: ++ crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32); ++ crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data); ++ data_offset = offsetof(struct u_boot_env_image_broadcom, data); ++ break; ++ } ++ ++ if (dev_size < data_offset) { ++ dev_err(dev, "Device too small for u-boot-env\n"); ++ err = -EIO; ++ goto err_kfree; ++ } ++ ++ crc32_addr = (__le32 *)(buf + crc32_offset); ++ crc32 = le32_to_cpu(*crc32_addr); ++ crc32_data_len = dev_size - crc32_data_offset; ++ data_len = dev_size - data_offset; ++ ++ calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; ++ if (calc != crc32) { ++ dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32); ++ err = -EINVAL; ++ goto err_kfree; ++ } ++ ++ buf[dev_size - 1] = '\0'; ++ err = u_boot_env_parse_cells(dev, nvmem, buf, data_offset, data_len); ++ ++err_kfree: ++ kfree(buf); ++err_out: ++ return err; ++} ++EXPORT_SYMBOL_GPL(u_boot_env_parse); ++ ++static int u_boot_env_add_cells(struct nvmem_layout *layout) ++{ ++ struct device *dev = &layout->dev; ++ enum u_boot_env_format format; ++ ++ format = (uintptr_t)device_get_match_data(dev); ++ ++ return u_boot_env_parse(dev, layout->nvmem, format); ++} ++ ++static int u_boot_env_probe(struct nvmem_layout *layout) ++{ ++ layout->add_cells = u_boot_env_add_cells; ++ ++ return nvmem_layout_register(layout); ++} ++ ++static void u_boot_env_remove(struct nvmem_layout *layout) ++{ ++ nvmem_layout_unregister(layout); ++} ++ ++static const struct of_device_id u_boot_env_of_match_table[] = { ++ { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, }, ++ { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, ++ { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, ++ { .compatible = "brcm,env", .data = (void *)U_BOOT_FORMAT_BROADCOM, }, ++ {}, ++}; ++ ++static struct nvmem_layout_driver u_boot_env_layout = { ++ .driver = { ++ .name = "u-boot-env-layout", ++ .of_match_table = u_boot_env_of_match_table, ++ }, ++ .probe = u_boot_env_probe, ++ .remove = u_boot_env_remove, ++}; ++module_nvmem_layout_driver(u_boot_env_layout); ++ ++MODULE_AUTHOR("Rafał Miłecki"); ++MODULE_LICENSE("GPL"); ++MODULE_DEVICE_TABLE(of, u_boot_env_of_match_table); ++MODULE_DESCRIPTION("NVMEM layout driver for U-Boot environment variables"); +--- /dev/null ++++ b/drivers/nvmem/layouts/u-boot-env.h +@@ -0,0 +1,15 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#ifndef _LINUX_NVMEM_LAYOUTS_U_BOOT_ENV_H ++#define _LINUX_NVMEM_LAYOUTS_U_BOOT_ENV_H ++ ++enum u_boot_env_format { ++ U_BOOT_FORMAT_SINGLE, ++ U_BOOT_FORMAT_REDUNDANT, ++ U_BOOT_FORMAT_BROADCOM, ++}; ++ ++int u_boot_env_parse(struct device *dev, struct nvmem_device *nvmem, ++ enum u_boot_env_format format); ++ ++#endif /* ifndef _LINUX_NVMEM_LAYOUTS_U_BOOT_ENV_H */ +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -3,23 +3,15 @@ + * Copyright (C) 2022 Rafał Miłecki <rafal@milecki.pl> + */ + +-#include <linux/crc32.h> +-#include <linux/etherdevice.h> +-#include <linux/if_ether.h> + #include <linux/mod_devicetable.h> + #include <linux/module.h> + #include <linux/mtd/mtd.h> +-#include <linux/nvmem-consumer.h> + #include <linux/nvmem-provider.h> + #include <linux/of.h> + #include <linux/platform_device.h> + #include <linux/slab.h> + +-enum u_boot_env_format { +- U_BOOT_FORMAT_SINGLE, +- U_BOOT_FORMAT_REDUNDANT, +- U_BOOT_FORMAT_BROADCOM, +-}; ++#include "layouts/u-boot-env.h" + + struct u_boot_env { + struct device *dev; +@@ -29,24 +21,6 @@ struct u_boot_env { + struct mtd_info *mtd; + }; + +-struct u_boot_env_image_single { +- __le32 crc32; +- uint8_t data[]; +-} __packed; +- +-struct u_boot_env_image_redundant { +- __le32 crc32; +- u8 mark; +- uint8_t data[]; +-} __packed; +- +-struct u_boot_env_image_broadcom { +- __le32 magic; +- __le32 len; +- __le32 crc32; +- DECLARE_FLEX_ARRAY(uint8_t, data); +-} __packed; +- + static int u_boot_env_read(void *context, unsigned int offset, void *val, + size_t bytes) + { +@@ -69,141 +43,6 @@ static int u_boot_env_read(void *context + return 0; + } + +-static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index, +- unsigned int offset, void *buf, size_t bytes) +-{ +- u8 mac[ETH_ALEN]; +- +- if (bytes != 3 * ETH_ALEN - 1) +- return -EINVAL; +- +- if (!mac_pton(buf, mac)) +- return -EINVAL; +- +- if (index) +- eth_addr_add(mac, index); +- +- ether_addr_copy(buf, mac); +- +- return 0; +-} +- +-static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, +- size_t data_offset, size_t data_len) +-{ +- struct nvmem_device *nvmem = priv->nvmem; +- struct device *dev = priv->dev; +- char *data = buf + data_offset; +- char *var, *value, *eq; +- +- for (var = data; +- var < data + data_len && *var; +- var = value + strlen(value) + 1) { +- struct nvmem_cell_info info = {}; +- +- eq = strchr(var, '='); +- if (!eq) +- break; +- *eq = '\0'; +- value = eq + 1; +- +- info.name = devm_kstrdup(dev, var, GFP_KERNEL); +- if (!info.name) +- return -ENOMEM; +- info.offset = data_offset + value - data; +- info.bytes = strlen(value); +- info.np = of_get_child_by_name(dev->of_node, info.name); +- if (!strcmp(var, "ethaddr")) { +- info.raw_len = strlen(value); +- info.bytes = ETH_ALEN; +- info.read_post_process = u_boot_env_read_post_process_ethaddr; +- } +- +- nvmem_add_one_cell(nvmem, &info); +- } +- +- return 0; +-} +- +-static int u_boot_env_parse(struct u_boot_env *priv) +-{ +- struct nvmem_device *nvmem = priv->nvmem; +- struct device *dev = priv->dev; +- size_t crc32_data_offset; +- size_t crc32_data_len; +- size_t crc32_offset; +- __le32 *crc32_addr; +- size_t data_offset; +- size_t data_len; +- size_t dev_size; +- uint32_t crc32; +- uint32_t calc; +- uint8_t *buf; +- int bytes; +- int err; +- +- dev_size = nvmem_dev_size(nvmem); +- +- buf = kzalloc(dev_size, GFP_KERNEL); +- if (!buf) { +- err = -ENOMEM; +- goto err_out; +- } +- +- bytes = nvmem_device_read(nvmem, 0, dev_size, buf); +- if (bytes < 0) { +- err = bytes; +- goto err_kfree; +- } else if (bytes != dev_size) { +- err = -EIO; +- goto err_kfree; +- } +- +- switch (priv->format) { +- case U_BOOT_FORMAT_SINGLE: +- crc32_offset = offsetof(struct u_boot_env_image_single, crc32); +- crc32_data_offset = offsetof(struct u_boot_env_image_single, data); +- data_offset = offsetof(struct u_boot_env_image_single, data); +- break; +- case U_BOOT_FORMAT_REDUNDANT: +- crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32); +- crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); +- data_offset = offsetof(struct u_boot_env_image_redundant, data); +- break; +- case U_BOOT_FORMAT_BROADCOM: +- crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32); +- crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data); +- data_offset = offsetof(struct u_boot_env_image_broadcom, data); +- break; +- } +- +- if (dev_size < data_offset) { +- dev_err(dev, "Device too small for u-boot-env\n"); +- err = -EIO; +- goto err_kfree; +- } +- +- crc32_addr = (__le32 *)(buf + crc32_offset); +- crc32 = le32_to_cpu(*crc32_addr); +- crc32_data_len = dev_size - crc32_data_offset; +- data_len = dev_size - data_offset; +- +- calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; +- if (calc != crc32) { +- dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32); +- err = -EINVAL; +- goto err_kfree; +- } +- +- buf[dev_size - 1] = '\0'; +- err = u_boot_env_add_cells(priv, buf, data_offset, data_len); +- +-err_kfree: +- kfree(buf); +-err_out: +- return err; +-} +- + static int u_boot_env_probe(struct platform_device *pdev) + { + struct nvmem_config config = { +@@ -235,7 +74,7 @@ static int u_boot_env_probe(struct platf + if (IS_ERR(priv->nvmem)) + return PTR_ERR(priv->nvmem); + +- return u_boot_env_parse(priv); ++ return u_boot_env_parse(dev, priv->nvmem, priv->format); + } + + static const struct of_device_id u_boot_env_of_match_table[] = { diff --git a/target/linux/generic/config-5.15 b/target/linux/generic/config-5.15 index 9711b8372f..a34ba551be 100644 --- a/target/linux/generic/config-5.15 +++ b/target/linux/generic/config-5.15 @@ -4453,6 +4453,7 @@ CONFIG_NMI_LOG_BUF_SHIFT=13 # 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_LAYOUT_U_BOOT_ENV 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-6.1 b/target/linux/generic/config-6.1 index ef4ab7bac1..ef61717d78 100644 --- a/target/linux/generic/config-6.1 +++ b/target/linux/generic/config-6.1 @@ -4624,6 +4624,7 @@ CONFIG_NMI_LOG_BUF_SHIFT=13 # 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_LAYOUT_U_BOOT_ENV 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-6.6 b/target/linux/generic/config-6.6 index 0e41607260..71fdf59d33 100644 --- a/target/linux/generic/config-6.6 +++ b/target/linux/generic/config-6.6 @@ -4335,6 +4335,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # 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_LAYOUT_U_BOOT_ENV 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/pending-5.15/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch b/target/linux/generic/pending-5.15/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch index 46acd47f63..29fe668f8d 100644 --- a/target/linux/generic/pending-5.15/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch +++ b/target/linux/generic/pending-5.15/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch @@ -1,7 +1,7 @@ From 0e71cac033bb7689c4dfa2e6814191337ef770f5 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi <musashino.open@gmail.com> Date: Thu, 13 Oct 2022 00:51:33 +0900 -Subject: [PATCH] nvmem: u-boot-env: align endianness of crc32 values +Subject: [PATCH] nvmem: layouts: u-boot-env: align endianness of crc32 values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -31,12 +31,10 @@ Acked-by: Rafał Miłecki <rafal@milecki.pl> Tested-by: Christian Lamparter <chunkeey@gmail.com> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> --- - drivers/nvmem/u-boot-env.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) ---- a/drivers/nvmem/u-boot-env.c -+++ b/drivers/nvmem/u-boot-env.c -@@ -188,7 +188,7 @@ static int u_boot_env_parse(struct u_boo +--- a/drivers/nvmem/layouts/u-boot-env.c ++++ b/drivers/nvmem/layouts/u-boot-env.c +@@ -148,7 +148,7 @@ int u_boot_env_parse(struct device *dev, crc32_data_len = dev_size - crc32_data_offset; data_len = dev_size - data_offset; diff --git a/target/linux/generic/pending-6.1/510-block-add-uImage.FIT-subimage-block-driver.patch b/target/linux/generic/pending-6.1/510-block-add-uImage.FIT-subimage-block-driver.patch index 700eda1c8e..befc505dbc 100644 --- a/target/linux/generic/pending-6.1/510-block-add-uImage.FIT-subimage-block-driver.patch +++ b/target/linux/generic/pending-6.1/510-block-add-uImage.FIT-subimage-block-driver.patch @@ -36,7 +36,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org> --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -21059,6 +21059,12 @@ F: Documentation/filesystems/ubifs-authe +@@ -21060,6 +21060,12 @@ F: Documentation/filesystems/ubifs-authe F: Documentation/filesystems/ubifs.rst F: fs/ubifs/ diff --git a/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch b/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch index 46acd47f63..29fe668f8d 100644 --- a/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch +++ b/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch @@ -1,7 +1,7 @@ From 0e71cac033bb7689c4dfa2e6814191337ef770f5 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi <musashino.open@gmail.com> Date: Thu, 13 Oct 2022 00:51:33 +0900 -Subject: [PATCH] nvmem: u-boot-env: align endianness of crc32 values +Subject: [PATCH] nvmem: layouts: u-boot-env: align endianness of crc32 values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -31,12 +31,10 @@ Acked-by: Rafał Miłecki <rafal@milecki.pl> Tested-by: Christian Lamparter <chunkeey@gmail.com> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> --- - drivers/nvmem/u-boot-env.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) ---- a/drivers/nvmem/u-boot-env.c -+++ b/drivers/nvmem/u-boot-env.c -@@ -188,7 +188,7 @@ static int u_boot_env_parse(struct u_boo +--- a/drivers/nvmem/layouts/u-boot-env.c ++++ b/drivers/nvmem/layouts/u-boot-env.c +@@ -148,7 +148,7 @@ int u_boot_env_parse(struct device *dev, crc32_data_len = dev_size - crc32_data_offset; data_len = dev_size - data_offset; diff --git a/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch b/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch index 5cc85083d2..ff38964ece 100644 --- a/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch +++ b/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch @@ -36,7 +36,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org> --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -22014,6 +22014,12 @@ F: Documentation/filesystems/ubifs-authe +@@ -22015,6 +22015,12 @@ F: Documentation/filesystems/ubifs-authe F: Documentation/filesystems/ubifs.rst F: fs/ubifs/ diff --git a/target/linux/generic/pending-6.6/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch b/target/linux/generic/pending-6.6/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch index 46acd47f63..29fe668f8d 100644 --- a/target/linux/generic/pending-6.6/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch +++ b/target/linux/generic/pending-6.6/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch @@ -1,7 +1,7 @@ From 0e71cac033bb7689c4dfa2e6814191337ef770f5 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi <musashino.open@gmail.com> Date: Thu, 13 Oct 2022 00:51:33 +0900 -Subject: [PATCH] nvmem: u-boot-env: align endianness of crc32 values +Subject: [PATCH] nvmem: layouts: u-boot-env: align endianness of crc32 values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -31,12 +31,10 @@ Acked-by: Rafał Miłecki <rafal@milecki.pl> Tested-by: Christian Lamparter <chunkeey@gmail.com> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> --- - drivers/nvmem/u-boot-env.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) ---- a/drivers/nvmem/u-boot-env.c -+++ b/drivers/nvmem/u-boot-env.c -@@ -188,7 +188,7 @@ static int u_boot_env_parse(struct u_boo +--- a/drivers/nvmem/layouts/u-boot-env.c ++++ b/drivers/nvmem/layouts/u-boot-env.c +@@ -148,7 +148,7 @@ int u_boot_env_parse(struct device *dev, crc32_data_len = dev_size - crc32_data_offset; data_len = dev_size - data_offset; |