From: Rafał Miłecki Date: Fri, 6 Jan 2023 13:03:12 +0000 (+0100) Subject: kernel: 5.10: update nvmem subsystem to the 5.15 state X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=457cc597958748bd9a92bf2cb2e1f8b235124950;p=openwrt%2Fstaging%2Fblocktrron.git kernel: 5.10: update nvmem subsystem to the 5.15 state This allows cleanly backporting more recent stuff that's important for OpenWrt. Signed-off-by: Rafał Miłecki --- diff --git a/target/linux/bcm53xx/patches-5.10/080-v5.13-0002-nvmem-brcm_nvram-new-driver-exposing-Broadcom-s-NVRA.patch b/target/linux/bcm53xx/patches-5.10/080-v5.13-0002-nvmem-brcm_nvram-new-driver-exposing-Broadcom-s-NVRA.patch deleted file mode 100644 index 3a8940b36a..0000000000 --- a/target/linux/bcm53xx/patches-5.10/080-v5.13-0002-nvmem-brcm_nvram-new-driver-exposing-Broadcom-s-NVRA.patch +++ /dev/null @@ -1,124 +0,0 @@ -From b152bbeb0282bfcf6f91d0d5befd7582c1c3fc23 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Fri, 5 Mar 2021 19:32:36 +0100 -Subject: [PATCH] nvmem: brcm_nvram: new driver exposing Broadcom's NVRAM -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This driver provides access to Broadcom's NVRAM. - -Signed-off-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/Kconfig | 9 +++++ - drivers/nvmem/Makefile | 2 + - drivers/nvmem/brcm_nvram.c | 78 ++++++++++++++++++++++++++++++++++++++ - 3 files changed, 89 insertions(+) - create mode 100644 drivers/nvmem/brcm_nvram.c - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -283,4 +283,13 @@ config NVMEM_U_BOOT_ENV - - If compiled as module it will be called nvmem_u-boot-env. - -+ -+config NVMEM_BRCM_NVRAM -+ tristate "Broadcom's NVRAM support" -+ depends on ARCH_BCM_5301X || COMPILE_TEST -+ depends on HAS_IOMEM -+ help -+ This driver provides support for Broadcom's NVRAM that can be accessed -+ using I/O mapping. -+ - endif ---- a/drivers/nvmem/Makefile -+++ b/drivers/nvmem/Makefile -@@ -57,3 +57,5 @@ obj-$(CONFIG_SPRD_EFUSE) += nvmem_sprd_e - nvmem_sprd_efuse-y := sprd-efuse.o - obj-$(CONFIG_NVMEM_U_BOOT_ENV) += nvmem_u-boot-env.o - nvmem_u-boot-env-y := u-boot-env.o -+obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_brcm_nvram.o -+nvmem_brcm_nvram-y := brcm_nvram.o ---- /dev/null -+++ b/drivers/nvmem/brcm_nvram.c -@@ -0,0 +1,78 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2021 Rafał Miłecki -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+struct brcm_nvram { -+ struct device *dev; -+ void __iomem *base; -+}; -+ -+static int brcm_nvram_read(void *context, unsigned int offset, void *val, -+ size_t bytes) -+{ -+ struct brcm_nvram *priv = context; -+ u8 *dst = val; -+ -+ while (bytes--) -+ *dst++ = readb(priv->base + offset++); -+ -+ return 0; -+} -+ -+static int brcm_nvram_probe(struct platform_device *pdev) -+{ -+ struct nvmem_config config = { -+ .name = "brcm-nvram", -+ .reg_read = brcm_nvram_read, -+ }; -+ struct device *dev = &pdev->dev; -+ struct resource *res; -+ struct brcm_nvram *priv; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ priv->dev = dev; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ priv->base = devm_ioremap_resource(dev, res); -+ if (IS_ERR(priv->base)) -+ return PTR_ERR(priv->base); -+ -+ config.dev = dev; -+ config.priv = priv; -+ config.size = resource_size(res); -+ -+ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); -+} -+ -+static const struct of_device_id brcm_nvram_of_match_table[] = { -+ { .compatible = "brcm,nvram", }, -+ {}, -+}; -+ -+static struct platform_driver brcm_nvram_driver = { -+ .probe = brcm_nvram_probe, -+ .driver = { -+ .name = "brcm_nvram", -+ .of_match_table = brcm_nvram_of_match_table, -+ }, -+}; -+ -+static int __init brcm_nvram_init(void) -+{ -+ return platform_driver_register(&brcm_nvram_driver); -+} -+ -+subsys_initcall_sync(brcm_nvram_init); -+ -+MODULE_AUTHOR("Rafał Miłecki"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(of, brcm_nvram_of_match_table); diff --git a/target/linux/generic/backport-5.10/801-v5.11-0001-nvmem-core-Add-support-for-keepout-regions.patch b/target/linux/generic/backport-5.10/801-v5.11-0001-nvmem-core-Add-support-for-keepout-regions.patch new file mode 100644 index 0000000000..6fe5032f33 --- /dev/null +++ b/target/linux/generic/backport-5.10/801-v5.11-0001-nvmem-core-Add-support-for-keepout-regions.patch @@ -0,0 +1,267 @@ +From fd3bb8f54a88107570334c156efb0c724a261003 Mon Sep 17 00:00:00 2001 +From: Evan Green +Date: Fri, 27 Nov 2020 10:28:34 +0000 +Subject: [PATCH] nvmem: core: Add support for keepout regions + +Introduce support into the nvmem core for arrays of register ranges +that should not result in actual device access. For these regions a +constant byte (repeated) is returned instead on read, and writes are +quietly ignored and returned as successful. + +This is useful for instance if certain efuse regions are protected +from access by Linux because they contain secret info to another part +of the system (like an integrated modem). + +Signed-off-by: Evan Green +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20201127102837.19366-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 153 ++++++++++++++++++++++++++++++++- + include/linux/nvmem-provider.h | 17 ++++ + 2 files changed, 166 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -34,6 +34,8 @@ struct nvmem_device { + struct bin_attribute eeprom; + struct device *base_dev; + struct list_head cells; ++ const struct nvmem_keepout *keepout; ++ unsigned int nkeepout; + nvmem_reg_read_t reg_read; + nvmem_reg_write_t reg_write; + struct gpio_desc *wp_gpio; +@@ -66,8 +68,8 @@ static LIST_HEAD(nvmem_lookup_list); + + static BLOCKING_NOTIFIER_HEAD(nvmem_notifier); + +-static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, +- void *val, size_t bytes) ++static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, ++ void *val, size_t bytes) + { + if (nvmem->reg_read) + return nvmem->reg_read(nvmem->priv, offset, val, bytes); +@@ -75,8 +77,8 @@ static int nvmem_reg_read(struct nvmem_d + return -EINVAL; + } + +-static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset, +- void *val, size_t bytes) ++static int __nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset, ++ void *val, size_t bytes) + { + int ret; + +@@ -90,6 +92,88 @@ static int nvmem_reg_write(struct nvmem_ + return -EINVAL; + } + ++static int nvmem_access_with_keepouts(struct nvmem_device *nvmem, ++ unsigned int offset, void *val, ++ size_t bytes, int write) ++{ ++ ++ unsigned int end = offset + bytes; ++ unsigned int kend, ksize; ++ const struct nvmem_keepout *keepout = nvmem->keepout; ++ const struct nvmem_keepout *keepoutend = keepout + nvmem->nkeepout; ++ int rc; ++ ++ /* ++ * Skip all keepouts before the range being accessed. ++ * Keepouts are sorted. ++ */ ++ while ((keepout < keepoutend) && (keepout->end <= offset)) ++ keepout++; ++ ++ while ((offset < end) && (keepout < keepoutend)) { ++ /* Access the valid portion before the keepout. */ ++ if (offset < keepout->start) { ++ kend = min(end, keepout->start); ++ ksize = kend - offset; ++ if (write) ++ rc = __nvmem_reg_write(nvmem, offset, val, ksize); ++ else ++ rc = __nvmem_reg_read(nvmem, offset, val, ksize); ++ ++ if (rc) ++ return rc; ++ ++ offset += ksize; ++ val += ksize; ++ } ++ ++ /* ++ * Now we're aligned to the start of this keepout zone. Go ++ * through it. ++ */ ++ kend = min(end, keepout->end); ++ ksize = kend - offset; ++ if (!write) ++ memset(val, keepout->value, ksize); ++ ++ val += ksize; ++ offset += ksize; ++ keepout++; ++ } ++ ++ /* ++ * If we ran out of keepouts but there's still stuff to do, send it ++ * down directly ++ */ ++ if (offset < end) { ++ ksize = end - offset; ++ if (write) ++ return __nvmem_reg_write(nvmem, offset, val, ksize); ++ else ++ return __nvmem_reg_read(nvmem, offset, val, ksize); ++ } ++ ++ return 0; ++} ++ ++static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, ++ void *val, size_t bytes) ++{ ++ if (!nvmem->nkeepout) ++ return __nvmem_reg_read(nvmem, offset, val, bytes); ++ ++ return nvmem_access_with_keepouts(nvmem, offset, val, bytes, false); ++} ++ ++static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset, ++ void *val, size_t bytes) ++{ ++ if (!nvmem->nkeepout) ++ return __nvmem_reg_write(nvmem, offset, val, bytes); ++ ++ return nvmem_access_with_keepouts(nvmem, offset, val, bytes, true); ++} ++ + #ifdef CONFIG_NVMEM_SYSFS + static const char * const nvmem_type_str[] = { + [NVMEM_TYPE_UNKNOWN] = "Unknown", +@@ -535,6 +619,59 @@ nvmem_find_cell_by_name(struct nvmem_dev + return cell; + } + ++static int nvmem_validate_keepouts(struct nvmem_device *nvmem) ++{ ++ unsigned int cur = 0; ++ const struct nvmem_keepout *keepout = nvmem->keepout; ++ const struct nvmem_keepout *keepoutend = keepout + nvmem->nkeepout; ++ ++ while (keepout < keepoutend) { ++ /* Ensure keepouts are sorted and don't overlap. */ ++ if (keepout->start < cur) { ++ dev_err(&nvmem->dev, ++ "Keepout regions aren't sorted or overlap.\n"); ++ ++ return -ERANGE; ++ } ++ ++ if (keepout->end < keepout->start) { ++ dev_err(&nvmem->dev, ++ "Invalid keepout region.\n"); ++ ++ return -EINVAL; ++ } ++ ++ /* ++ * Validate keepouts (and holes between) don't violate ++ * word_size constraints. ++ */ ++ if ((keepout->end - keepout->start < nvmem->word_size) || ++ ((keepout->start != cur) && ++ (keepout->start - cur < nvmem->word_size))) { ++ ++ dev_err(&nvmem->dev, ++ "Keepout regions violate word_size constraints.\n"); ++ ++ return -ERANGE; ++ } ++ ++ /* Validate keepouts don't violate stride (alignment). */ ++ if (!IS_ALIGNED(keepout->start, nvmem->stride) || ++ !IS_ALIGNED(keepout->end, nvmem->stride)) { ++ ++ dev_err(&nvmem->dev, ++ "Keepout regions violate stride.\n"); ++ ++ return -EINVAL; ++ } ++ ++ cur = keepout->end; ++ keepout++; ++ } ++ ++ return 0; ++} ++ + static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) + { + struct device_node *parent, *child; +@@ -655,6 +792,8 @@ struct nvmem_device *nvmem_register(cons + nvmem->type = config->type; + nvmem->reg_read = config->reg_read; + nvmem->reg_write = config->reg_write; ++ nvmem->keepout = config->keepout; ++ nvmem->nkeepout = config->nkeepout; + if (!config->no_of_node) + nvmem->dev.of_node = config->dev->of_node; + +@@ -679,6 +818,12 @@ struct nvmem_device *nvmem_register(cons + nvmem->dev.groups = nvmem_dev_groups; + #endif + ++ if (nvmem->nkeepout) { ++ rval = nvmem_validate_keepouts(nvmem); ++ if (rval) ++ goto err_put_device; ++ } ++ + dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); + + rval = device_register(&nvmem->dev); +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -31,6 +31,19 @@ enum nvmem_type { + #define NVMEM_DEVID_AUTO (-2) + + /** ++ * struct nvmem_keepout - NVMEM register keepout range. ++ * ++ * @start: The first byte offset to avoid. ++ * @end: One beyond the last byte offset to avoid. ++ * @value: The byte to fill reads with for this region. ++ */ ++struct nvmem_keepout { ++ unsigned int start; ++ unsigned int end; ++ unsigned char value; ++}; ++ ++/** + * struct nvmem_config - NVMEM device configuration + * + * @dev: Parent device. +@@ -39,6 +52,8 @@ enum nvmem_type { + * @owner: Pointer to exporter module. Used for refcounting. + * @cells: Optional array of pre-defined NVMEM cells. + * @ncells: Number of elements in cells. ++ * @keepout: Optional array of keepout ranges (sorted ascending by start). ++ * @nkeepout: Number of elements in the keepout array. + * @type: Type of the nvmem storage + * @read_only: Device is read-only. + * @root_only: Device is accessibly to root only. +@@ -66,6 +81,8 @@ struct nvmem_config { + struct gpio_desc *wp_gpio; + const struct nvmem_cell_info *cells; + int ncells; ++ const struct nvmem_keepout *keepout; ++ unsigned int nkeepout; + enum nvmem_type type; + bool read_only; + bool root_only; diff --git a/target/linux/generic/backport-5.10/801-v5.11-0002-nvmem-qfprom-Don-t-touch-certain-fuses.patch b/target/linux/generic/backport-5.10/801-v5.11-0002-nvmem-qfprom-Don-t-touch-certain-fuses.patch new file mode 100644 index 0000000000..ae499e7498 --- /dev/null +++ b/target/linux/generic/backport-5.10/801-v5.11-0002-nvmem-qfprom-Don-t-touch-certain-fuses.patch @@ -0,0 +1,87 @@ +From 044ee8f85267599a9b0112911f5c16d4548b4289 Mon Sep 17 00:00:00 2001 +From: Evan Green +Date: Fri, 27 Nov 2020 10:28:36 +0000 +Subject: [PATCH] nvmem: qfprom: Don't touch certain fuses + +Some fuse ranges are protected by the XPU such that the AP cannot +access them. Attempting to do so causes an SError. Use the newly +introduced per-soc compatible string, and the newly introduced +nvmem keepout support to attach the set of regions +we should not access. + +Reviewed-by: Douglas Anderson +Signed-off-by: Evan Green +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20201127102837.19366-5-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/qfprom.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +--- a/drivers/nvmem/qfprom.c ++++ b/drivers/nvmem/qfprom.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + + /* Blow timer clock frequency in Mhz */ +@@ -89,6 +90,28 @@ struct qfprom_touched_values { + }; + + /** ++ * struct qfprom_soc_compatible_data - Data matched against the SoC ++ * compatible string. ++ * ++ * @keepout: Array of keepout regions for this SoC. ++ * @nkeepout: Number of elements in the keepout array. ++ */ ++struct qfprom_soc_compatible_data { ++ const struct nvmem_keepout *keepout; ++ unsigned int nkeepout; ++}; ++ ++static const struct nvmem_keepout sc7180_qfprom_keepout[] = { ++ {.start = 0x128, .end = 0x148}, ++ {.start = 0x220, .end = 0x228} ++}; ++ ++static const struct qfprom_soc_compatible_data sc7180_qfprom = { ++ .keepout = sc7180_qfprom_keepout, ++ .nkeepout = ARRAY_SIZE(sc7180_qfprom_keepout) ++}; ++ ++/** + * qfprom_disable_fuse_blowing() - Undo enabling of fuse blowing. + * @priv: Our driver data. + * @old: The data that was stashed from before fuse blowing. +@@ -302,6 +325,7 @@ static int qfprom_probe(struct platform_ + struct device *dev = &pdev->dev; + struct resource *res; + struct nvmem_device *nvmem; ++ const struct qfprom_soc_compatible_data *soc_data; + struct qfprom_priv *priv; + int ret; + +@@ -320,6 +344,11 @@ static int qfprom_probe(struct platform_ + econfig.priv = priv; + + priv->dev = dev; ++ soc_data = device_get_match_data(dev); ++ if (soc_data) { ++ econfig.keepout = soc_data->keepout; ++ econfig.nkeepout = soc_data->nkeepout; ++ } + + /* + * If more than one region is provided then the OS has the ability +@@ -375,6 +404,7 @@ static int qfprom_probe(struct platform_ + + static const struct of_device_id qfprom_of_match[] = { + { .compatible = "qcom,qfprom",}, ++ { .compatible = "qcom,sc7180-qfprom", .data = &sc7180_qfprom}, + {/* sentinel */}, + }; + MODULE_DEVICE_TABLE(of, qfprom_of_match); diff --git a/target/linux/generic/backport-5.10/801-v5.11-0003-nvmem-imx-ocotp-add-support-for-the-unaliged-word-co.patch b/target/linux/generic/backport-5.10/801-v5.11-0003-nvmem-imx-ocotp-add-support-for-the-unaliged-word-co.patch new file mode 100644 index 0000000000..0a05e0a97f --- /dev/null +++ b/target/linux/generic/backport-5.10/801-v5.11-0003-nvmem-imx-ocotp-add-support-for-the-unaliged-word-co.patch @@ -0,0 +1,105 @@ +From 3311bf18467272388039922a5e29c4925b291f73 Mon Sep 17 00:00:00 2001 +From: Peng Fan +Date: Fri, 27 Nov 2020 10:28:37 +0000 +Subject: [PATCH] nvmem: imx-ocotp: add support for the unaliged word count + +When offset is not 4 bytes aligned, directly shift righty by 2 bits +will cause reading out wrong data. Since imx ocotp only supports +4 bytes reading once, we need handle offset is not 4 bytes aligned +and enlarge the bytes to 4 bytes aligned. After reading finished, +copy the needed data from buffer to caller and free buffer. + +Signed-off-by: Peng Fan +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20201127102837.19366-6-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/imx-ocotp.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +--- a/drivers/nvmem/imx-ocotp.c ++++ b/drivers/nvmem/imx-ocotp.c +@@ -4,6 +4,8 @@ + * + * Copyright (c) 2015 Pengutronix, Philipp Zabel + * ++ * Copyright 2019 NXP ++ * + * Based on the barebox ocotp driver, + * Copyright (c) 2010 Baruch Siach , + * Orex Computed Radiography +@@ -158,22 +160,30 @@ static int imx_ocotp_read(void *context, + { + struct ocotp_priv *priv = context; + unsigned int count; +- u32 *buf = val; ++ u8 *buf, *p; + int i, ret; +- u32 index; ++ u32 index, num_bytes; + + index = offset >> 2; +- count = bytes >> 2; ++ num_bytes = round_up((offset % 4) + bytes, 4); ++ count = num_bytes >> 2; + + if (count > (priv->params->nregs - index)) + count = priv->params->nregs - index; + ++ p = kzalloc(num_bytes, GFP_KERNEL); ++ if (!p) ++ return -ENOMEM; ++ + mutex_lock(&ocotp_mutex); + ++ buf = p; ++ + ret = clk_prepare_enable(priv->clk); + if (ret < 0) { + mutex_unlock(&ocotp_mutex); + dev_err(priv->dev, "failed to prepare/enable ocotp clk\n"); ++ kfree(p); + return ret; + } + +@@ -184,7 +194,7 @@ static int imx_ocotp_read(void *context, + } + + for (i = index; i < (index + count); i++) { +- *buf++ = readl(priv->base + IMX_OCOTP_OFFSET_B0W0 + ++ *(u32 *)buf = readl(priv->base + IMX_OCOTP_OFFSET_B0W0 + + i * IMX_OCOTP_OFFSET_PER_WORD); + + /* 47.3.1.2 +@@ -193,13 +203,21 @@ static int imx_ocotp_read(void *context, + * software before any new write, read or reload access can be + * issued + */ +- if (*(buf - 1) == IMX_OCOTP_READ_LOCKED_VAL) ++ if (*((u32 *)buf) == IMX_OCOTP_READ_LOCKED_VAL) + imx_ocotp_clr_err_if_set(priv); ++ ++ buf += 4; + } + ++ index = offset % 4; ++ memcpy(val, &p[index], bytes); ++ + read_end: + clk_disable_unprepare(priv->clk); + mutex_unlock(&ocotp_mutex); ++ ++ kfree(p); ++ + return ret; + } + +@@ -447,7 +465,7 @@ static struct nvmem_config imx_ocotp_nvm + .name = "imx-ocotp", + .read_only = false, + .word_size = 4, +- .stride = 4, ++ .stride = 1, + .reg_read = imx_ocotp_read, + .reg_write = imx_ocotp_write, + }; diff --git a/target/linux/generic/backport-5.10/801-v6.1-0001-nvmem-add-driver-handling-U-Boot-environment-variabl.patch b/target/linux/generic/backport-5.10/801-v6.1-0001-nvmem-add-driver-handling-U-Boot-environment-variabl.patch deleted file mode 100644 index 1459d1184e..0000000000 --- a/target/linux/generic/backport-5.10/801-v6.1-0001-nvmem-add-driver-handling-U-Boot-environment-variabl.patch +++ /dev/null @@ -1,278 +0,0 @@ -From f955dc14450695564926711cf9fa8e1d5d854302 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Wed, 15 Jun 2022 21:43:00 +0200 -Subject: [PATCH] nvmem: add driver handling U-Boot environment variables -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -U-Boot stores its setup as environment variables. It's a list of -key-value pairs stored on flash device with a custom header. - -This commit adds an NVMEM driver that: -1. Provides NVMEM access to environment vars binary data -2. Extracts variables as NVMEM cells - -Current Linux's NVMEM sysfs API allows reading whole NVMEM data block. -It can be used by user-space tools for reading U-Boot env vars block -without the hassle of finding its location. Parsing will still need to -be re-done there. - -Kernel-parsed NVMEM cells can be read however by Linux drivers. This may -be useful for Ethernet drivers for reading device MAC address which is -often stored as U-Boot env variable. - -Signed-off-by: Rafał Miłecki -Reviewed-by: Ahmad Fatoum -Signed-off-by: Srinivas Kandagatla ---- - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -270,4 +270,17 @@ config SPRD_EFUSE - This driver can also be built as a module. If so, the module - will be called nvmem-sprd-efuse. - -+config NVMEM_U_BOOT_ENV -+ tristate "U-Boot environment variables support" -+ depends on OF && MTD -+ select CRC32 -+ help -+ U-Boot stores its setup as environment variables. This driver adds -+ support for verifying & exporting such data. It also exposes variables -+ as NVMEM cells so they can be referenced by other drivers. -+ -+ Currently this drivers works only with env variables on top of MTD. -+ -+ If compiled as module it will be called nvmem_u-boot-env. -+ - endif ---- a/drivers/nvmem/Makefile -+++ b/drivers/nvmem/Makefile -@@ -55,3 +55,5 @@ obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynq - nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o - obj-$(CONFIG_SPRD_EFUSE) += nvmem_sprd_efuse.o - nvmem_sprd_efuse-y := sprd-efuse.o -+obj-$(CONFIG_NVMEM_U_BOOT_ENV) += nvmem_u-boot-env.o -+nvmem_u-boot-env-y := u-boot-env.o ---- /dev/null -+++ b/drivers/nvmem/u-boot-env.c -@@ -0,0 +1,218 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2022 Rafał Miłecki -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+enum u_boot_env_format { -+ U_BOOT_FORMAT_SINGLE, -+ U_BOOT_FORMAT_REDUNDANT, -+}; -+ -+struct u_boot_env { -+ struct device *dev; -+ enum u_boot_env_format format; -+ -+ struct mtd_info *mtd; -+ -+ /* Cells */ -+ struct nvmem_cell_info *cells; -+ int ncells; -+}; -+ -+struct u_boot_env_image_single { -+ __le32 crc32; -+ uint8_t data[]; -+} __packed; -+ -+struct u_boot_env_image_redundant { -+ __le32 crc32; -+ u8 mark; -+ uint8_t data[]; -+} __packed; -+ -+static int u_boot_env_read(void *context, unsigned int offset, void *val, -+ size_t bytes) -+{ -+ struct u_boot_env *priv = context; -+ struct device *dev = priv->dev; -+ size_t bytes_read; -+ int err; -+ -+ err = mtd_read(priv->mtd, offset, bytes, &bytes_read, val); -+ if (err && !mtd_is_bitflip(err)) { -+ dev_err(dev, "Failed to read from mtd: %d\n", err); -+ return err; -+ } -+ -+ if (bytes_read != bytes) { -+ dev_err(dev, "Failed to read %zu bytes\n", bytes); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, -+ size_t data_offset, size_t data_len) -+{ -+ struct device *dev = priv->dev; -+ char *data = buf + data_offset; -+ char *var, *value, *eq; -+ int idx; -+ -+ priv->ncells = 0; -+ for (var = data; var < data + data_len && *var; var += strlen(var) + 1) -+ priv->ncells++; -+ -+ priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL); -+ if (!priv->cells) -+ return -ENOMEM; -+ -+ for (var = data, idx = 0; -+ var < data + data_len && *var; -+ var = value + strlen(value) + 1, idx++) { -+ eq = strchr(var, '='); -+ if (!eq) -+ break; -+ *eq = '\0'; -+ value = eq + 1; -+ -+ priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL); -+ if (!priv->cells[idx].name) -+ return -ENOMEM; -+ priv->cells[idx].offset = data_offset + value - data; -+ priv->cells[idx].bytes = strlen(value); -+ } -+ -+ if (WARN_ON(idx != priv->ncells)) -+ priv->ncells = idx; -+ -+ return 0; -+} -+ -+static int u_boot_env_parse(struct u_boot_env *priv) -+{ -+ struct device *dev = priv->dev; -+ size_t crc32_data_offset; -+ size_t crc32_data_len; -+ size_t crc32_offset; -+ size_t data_offset; -+ size_t data_len; -+ uint32_t crc32; -+ uint32_t calc; -+ size_t bytes; -+ uint8_t *buf; -+ int err; -+ -+ buf = kcalloc(1, priv->mtd->size, GFP_KERNEL); -+ if (!buf) { -+ err = -ENOMEM; -+ goto err_out; -+ } -+ -+ err = mtd_read(priv->mtd, 0, priv->mtd->size, &bytes, buf); -+ if ((err && !mtd_is_bitflip(err)) || bytes != priv->mtd->size) { -+ dev_err(dev, "Failed to read from mtd: %d\n", err); -+ goto err_kfree; -+ } -+ -+ switch (priv->format) { -+ case U_BOOT_FORMAT_SINGLE: -+ crc32_offset = offsetof(struct u_boot_env_image_single, crc32); -+ crc32_data_offset = offsetof(struct u_boot_env_image_single, data); -+ data_offset = offsetof(struct u_boot_env_image_single, data); -+ break; -+ case U_BOOT_FORMAT_REDUNDANT: -+ crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32); -+ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, mark); -+ data_offset = offsetof(struct u_boot_env_image_redundant, data); -+ break; -+ } -+ crc32 = le32_to_cpu(*(uint32_t *)(buf + crc32_offset)); -+ crc32_data_len = priv->mtd->size - crc32_data_offset; -+ data_len = priv->mtd->size - data_offset; -+ -+ calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; -+ if (calc != crc32) { -+ dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32); -+ err = -EINVAL; -+ goto err_kfree; -+ } -+ -+ buf[priv->mtd->size - 1] = '\0'; -+ err = u_boot_env_add_cells(priv, buf, data_offset, data_len); -+ if (err) -+ dev_err(dev, "Failed to add cells: %d\n", err); -+ -+err_kfree: -+ kfree(buf); -+err_out: -+ return err; -+} -+ -+static int u_boot_env_probe(struct platform_device *pdev) -+{ -+ struct nvmem_config config = { -+ .name = "u-boot-env", -+ .reg_read = u_boot_env_read, -+ }; -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct u_boot_env *priv; -+ int err; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ priv->dev = dev; -+ -+ priv->format = (uintptr_t)of_device_get_match_data(dev); -+ -+ priv->mtd = of_get_mtd_device_by_node(np); -+ if (IS_ERR(priv->mtd)) { -+ dev_err_probe(dev, PTR_ERR(priv->mtd), "Failed to get %pOF MTD\n", np); -+ return PTR_ERR(priv->mtd); -+ } -+ -+ err = u_boot_env_parse(priv); -+ if (err) -+ return err; -+ -+ config.dev = dev; -+ config.cells = priv->cells; -+ config.ncells = priv->ncells; -+ config.priv = priv; -+ config.size = priv->mtd->size; -+ -+ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); -+} -+ -+static const struct of_device_id u_boot_env_of_match_table[] = { -+ { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, }, -+ { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, -+ { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, -+ {}, -+}; -+ -+static struct platform_driver u_boot_env_driver = { -+ .probe = u_boot_env_probe, -+ .driver = { -+ .name = "u_boot_env", -+ .of_match_table = u_boot_env_of_match_table, -+ }, -+}; -+module_platform_driver(u_boot_env_driver); -+ -+MODULE_AUTHOR("Rafał Miłecki"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(of, u_boot_env_of_match_table); diff --git a/target/linux/generic/backport-5.10/801-v6.1-0002-nvmem-u-boot-env-find-Device-Tree-nodes-for-NVMEM-ce.patch b/target/linux/generic/backport-5.10/801-v6.1-0002-nvmem-u-boot-env-find-Device-Tree-nodes-for-NVMEM-ce.patch deleted file mode 100644 index 3a6b76a221..0000000000 --- a/target/linux/generic/backport-5.10/801-v6.1-0002-nvmem-u-boot-env-find-Device-Tree-nodes-for-NVMEM-ce.patch +++ /dev/null @@ -1,29 +0,0 @@ -From d69efcf951df4dcc74a0e1554969c533aec8aa9b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Thu, 15 Sep 2022 22:06:29 +0200 -Subject: [PATCH] nvmem: u-boot-env: find Device Tree nodes for NVMEM cells -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -DT binding allows specifying NVMEM cells as NVMEM device (provider) -subnodes. Looks for such subnodes when building NVMEM cells. - -This allows NVMEM consumers to use U-Boot environment variables. - -Signed-off-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/u-boot-env.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/nvmem/u-boot-env.c -+++ b/drivers/nvmem/u-boot-env.c -@@ -92,6 +92,7 @@ static int u_boot_env_add_cells(struct u - return -ENOMEM; - priv->cells[idx].offset = data_offset + value - data; - priv->cells[idx].bytes = strlen(value); -+ priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); - } - - if (WARN_ON(idx != priv->ncells)) diff --git a/target/linux/generic/backport-5.10/801-v6.1-0003-nvmem-u-boot-env-fix-crc32-casting-type.patch b/target/linux/generic/backport-5.10/801-v6.1-0003-nvmem-u-boot-env-fix-crc32-casting-type.patch deleted file mode 100644 index 6b40557116..0000000000 --- a/target/linux/generic/backport-5.10/801-v6.1-0003-nvmem-u-boot-env-fix-crc32-casting-type.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 60bbaad38109684b156e21112322e0a922f92cde Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Thu, 18 Aug 2022 06:38:37 +0200 -Subject: [PATCH] nvmem: u-boot-env: fix crc32 casting type -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This fixes: -drivers/nvmem/u-boot-env.c:141:17: sparse: sparse: cast to restricted __le32 - -Reported-by: kernel test robot -Fixes: f955dc1445069 ("nvmem: add driver handling U-Boot environment variables") -Signed-off-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/u-boot-env.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/u-boot-env.c -+++ b/drivers/nvmem/u-boot-env.c -@@ -139,7 +139,7 @@ static int u_boot_env_parse(struct u_boo - data_offset = offsetof(struct u_boot_env_image_redundant, data); - break; - } -- crc32 = le32_to_cpu(*(uint32_t *)(buf + crc32_offset)); -+ crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); - crc32_data_len = priv->mtd->size - crc32_data_offset; - data_len = priv->mtd->size - data_offset; - diff --git a/target/linux/generic/backport-5.10/802-v5.12-0002-nvmem-imx-iim-Use-of_device_get_match_data.patch b/target/linux/generic/backport-5.10/802-v5.12-0002-nvmem-imx-iim-Use-of_device_get_match_data.patch new file mode 100644 index 0000000000..9a7ba7f565 --- /dev/null +++ b/target/linux/generic/backport-5.10/802-v5.12-0002-nvmem-imx-iim-Use-of_device_get_match_data.patch @@ -0,0 +1,41 @@ +From 579db09c6106977c0496f2cca48606b289df4bdf Mon Sep 17 00:00:00 2001 +From: Fabio Estevam +Date: Fri, 29 Jan 2021 17:14:27 +0000 +Subject: [PATCH] nvmem: imx-iim: Use of_device_get_match_data() + +The retrieval of driver data via of_device_get_match_data() can make +the code simpler. + +Use of_device_get_match_data() to simplify the code. + +Signed-off-by: Fabio Estevam +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210129171430.11328-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/imx-iim.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +--- a/drivers/nvmem/imx-iim.c ++++ b/drivers/nvmem/imx-iim.c +@@ -96,7 +96,6 @@ MODULE_DEVICE_TABLE(of, imx_iim_dt_ids); + + static int imx_iim_probe(struct platform_device *pdev) + { +- const struct of_device_id *of_id; + struct device *dev = &pdev->dev; + struct iim_priv *iim; + struct nvmem_device *nvmem; +@@ -111,11 +110,7 @@ static int imx_iim_probe(struct platform + if (IS_ERR(iim->base)) + return PTR_ERR(iim->base); + +- of_id = of_match_device(imx_iim_dt_ids, dev); +- if (!of_id) +- return -ENODEV; +- +- drvdata = of_id->data; ++ drvdata = of_device_get_match_data(&pdev->dev); + + iim->clk = devm_clk_get(dev, NULL); + if (IS_ERR(iim->clk)) diff --git a/target/linux/generic/backport-5.10/802-v5.12-0003-nvmem-Add-driver-to-expose-reserved-memory-as-nvmem.patch b/target/linux/generic/backport-5.10/802-v5.12-0003-nvmem-Add-driver-to-expose-reserved-memory-as-nvmem.patch new file mode 100644 index 0000000000..f3ed563d20 --- /dev/null +++ b/target/linux/generic/backport-5.10/802-v5.12-0003-nvmem-Add-driver-to-expose-reserved-memory-as-nvmem.patch @@ -0,0 +1,160 @@ +From 5a3fa75a4d9cb6bcfc9081ef224a4cdcd4b3eafe Mon Sep 17 00:00:00 2001 +From: Nicolas Saenz Julienne +Date: Fri, 29 Jan 2021 17:14:29 +0000 +Subject: [PATCH] nvmem: Add driver to expose reserved memory as nvmem + +Firmware/co-processors might use reserved memory areas in order to pass +data stemming from an nvmem device otherwise non accessible to Linux. +For example an EEPROM memory only physically accessible to firmware, or +data only accessible early at boot time. + +In order to expose this data to other drivers and user-space, the driver +models the reserved memory area as an nvmem device. + +Tested-by: Tim Gover +Reviewed-by: Rob Herring +Signed-off-by: Nicolas Saenz Julienne +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210129171430.11328-5-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 8 ++++ + drivers/nvmem/Makefile | 2 + + drivers/nvmem/rmem.c | 97 ++++++++++++++++++++++++++++++++++++++++++ + drivers/of/platform.c | 1 + + 4 files changed, 108 insertions(+) + create mode 100644 drivers/nvmem/rmem.c + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -270,4 +270,12 @@ config SPRD_EFUSE + This driver can also be built as a module. If so, the module + will be called nvmem-sprd-efuse. + ++config NVMEM_RMEM ++ tristate "Reserved Memory Based Driver Support" ++ help ++ This drivers maps reserved memory into an nvmem device. It might be ++ useful to expose information left by firmware in memory. ++ ++ This driver can also be built as a module. If so, the module ++ will be called nvmem-rmem. + endif +--- a/drivers/nvmem/Makefile ++++ b/drivers/nvmem/Makefile +@@ -55,3 +55,5 @@ obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynq + nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o + obj-$(CONFIG_SPRD_EFUSE) += nvmem_sprd_efuse.o + nvmem_sprd_efuse-y := sprd-efuse.o ++obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o ++nvmem-rmem-y := rmem.o +--- /dev/null ++++ b/drivers/nvmem/rmem.c +@@ -0,0 +1,97 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright (C) 2020 Nicolas Saenz Julienne ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++struct rmem { ++ struct device *dev; ++ struct nvmem_device *nvmem; ++ struct reserved_mem *mem; ++ ++ phys_addr_t size; ++}; ++ ++static int rmem_read(void *context, unsigned int offset, ++ void *val, size_t bytes) ++{ ++ struct rmem *priv = context; ++ size_t available = priv->mem->size; ++ loff_t off = offset; ++ void *addr; ++ int count; ++ ++ /* ++ * Only map the reserved memory at this point to avoid potential rogue ++ * kernel threads inadvertently modifying it. Based on the current ++ * uses-cases for this driver, the performance hit isn't a concern. ++ * Nor is likely to be, given the nature of the subsystem. Most nvmem ++ * devices operate over slow buses to begin with. ++ * ++ * An alternative would be setting the memory as RO, set_memory_ro(), ++ * but as of Dec 2020 this isn't possible on arm64. ++ */ ++ addr = memremap(priv->mem->base, available, MEMREMAP_WB); ++ if (IS_ERR(addr)) { ++ dev_err(priv->dev, "Failed to remap memory region\n"); ++ return PTR_ERR(addr); ++ } ++ ++ count = memory_read_from_buffer(val, bytes, &off, addr, available); ++ ++ memunmap(addr); ++ ++ return count; ++} ++ ++static int rmem_probe(struct platform_device *pdev) ++{ ++ struct nvmem_config config = { }; ++ struct device *dev = &pdev->dev; ++ struct reserved_mem *mem; ++ struct rmem *priv; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ priv->dev = dev; ++ ++ mem = of_reserved_mem_lookup(dev->of_node); ++ if (!mem) { ++ dev_err(dev, "Failed to lookup reserved memory\n"); ++ return -EINVAL; ++ } ++ priv->mem = mem; ++ ++ config.dev = dev; ++ config.priv = priv; ++ config.name = "rmem"; ++ config.size = mem->size; ++ config.reg_read = rmem_read; ++ ++ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); ++} ++ ++static const struct of_device_id rmem_match[] = { ++ { .compatible = "nvmem-rmem", }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, rmem_match); ++ ++static struct platform_driver rmem_driver = { ++ .probe = rmem_probe, ++ .driver = { ++ .name = "rmem", ++ .of_match_table = rmem_match, ++ }, ++}; ++module_platform_driver(rmem_driver); ++ ++MODULE_AUTHOR("Nicolas Saenz Julienne "); ++MODULE_DESCRIPTION("Reserved Memory Based nvmem Driver"); ++MODULE_LICENSE("GPL"); +--- a/drivers/of/platform.c ++++ b/drivers/of/platform.c +@@ -511,6 +511,7 @@ static const struct of_device_id reserve + { .compatible = "qcom,rmtfs-mem" }, + { .compatible = "qcom,cmd-db" }, + { .compatible = "ramoops" }, ++ { .compatible = "nvmem-rmem" }, + {} + }; + diff --git a/target/linux/generic/backport-5.10/802-v5.12-0005-nvmem-Kconfig-Correct-typo-in-NVMEM_RMEM.patch b/target/linux/generic/backport-5.10/802-v5.12-0005-nvmem-Kconfig-Correct-typo-in-NVMEM_RMEM.patch new file mode 100644 index 0000000000..129d070a62 --- /dev/null +++ b/target/linux/generic/backport-5.10/802-v5.12-0005-nvmem-Kconfig-Correct-typo-in-NVMEM_RMEM.patch @@ -0,0 +1,28 @@ +From b31f1eb41c140d7979f855df73064b3a3ae8055a Mon Sep 17 00:00:00 2001 +From: Nicolas Saenz Julienne +Date: Fri, 5 Feb 2021 10:08:52 +0000 +Subject: [PATCH] nvmem: Kconfig: Correct typo in NVMEM_RMEM + +s/drivers/driver/ as the configuration selects a single driver. + +Suggested-by: Randy Dunlap +Acked-by: Randy Dunlap +Signed-off-by: Nicolas Saenz Julienne +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210205100853.32372-2-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -273,7 +273,7 @@ config SPRD_EFUSE + config NVMEM_RMEM + tristate "Reserved Memory Based Driver Support" + help +- This drivers maps reserved memory into an nvmem device. It might be ++ This driver maps reserved memory into an nvmem device. It might be + useful to expose information left by firmware in memory. + + This driver can also be built as a module. If so, the module diff --git a/target/linux/generic/backport-5.10/802-v5.19-nvmem-core-support-passing-DT-node-in-cell-info.patch b/target/linux/generic/backport-5.10/802-v5.19-nvmem-core-support-passing-DT-node-in-cell-info.patch deleted file mode 100644 index b7870eef4b..0000000000 --- a/target/linux/generic/backport-5.10/802-v5.19-nvmem-core-support-passing-DT-node-in-cell-info.patch +++ /dev/null @@ -1,41 +0,0 @@ -From dbc2f62061c6bfba0aee93161ee3194dcee84bd0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Fri, 29 Apr 2022 17:26:46 +0100 -Subject: [PATCH] nvmem: core: support passing DT node in cell info -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some hardware may have NVMEM cells described in Device Tree using -individual nodes. Let drivers pass such nodes to the NVMEM subsystem so -they can be later used by NVMEM consumers. - -Signed-off-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20220429162701.2222-2-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 1 + - include/linux/nvmem-consumer.h | 1 + - 2 files changed, 2 insertions(+) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -374,6 +374,7 @@ static int nvmem_cell_info_to_nvmem_cell - - cell->bit_offset = info->bit_offset; - cell->nbits = info->nbits; -+ cell->np = info->np; - - if (cell->nbits) - cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset, ---- a/include/linux/nvmem-consumer.h -+++ b/include/linux/nvmem-consumer.h -@@ -25,6 +25,7 @@ struct nvmem_cell_info { - unsigned int bytes; - unsigned int bit_offset; - unsigned int nbits; -+ struct device_node *np; - }; - - /** diff --git a/target/linux/generic/backport-5.10/803-v5.13-0001-nvmem-convert-comma-to-semicolon.patch b/target/linux/generic/backport-5.10/803-v5.13-0001-nvmem-convert-comma-to-semicolon.patch new file mode 100644 index 0000000000..b611ffe645 --- /dev/null +++ b/target/linux/generic/backport-5.10/803-v5.13-0001-nvmem-convert-comma-to-semicolon.patch @@ -0,0 +1,39 @@ +From e050f160d4832ce5227fb6ca934969cec0fc48be Mon Sep 17 00:00:00 2001 +From: Zheng Yongjun +Date: Tue, 30 Mar 2021 12:12:33 +0100 +Subject: [PATCH] nvmem: convert comma to semicolon + +Replace a comma between expression statements by a semicolon. + +Reviewed-by: Bjorn Andersson +Signed-off-by: Zheng Yongjun +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210330111241.19401-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/qcom-spmi-sdam.c | 2 +- + drivers/nvmem/snvs_lpgpr.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/nvmem/qcom-spmi-sdam.c ++++ b/drivers/nvmem/qcom-spmi-sdam.c +@@ -141,7 +141,7 @@ static int sdam_probe(struct platform_de + sdam->sdam_config.dev = &pdev->dev; + sdam->sdam_config.name = "spmi_sdam"; + sdam->sdam_config.id = NVMEM_DEVID_AUTO; +- sdam->sdam_config.owner = THIS_MODULE, ++ sdam->sdam_config.owner = THIS_MODULE; + sdam->sdam_config.stride = 1; + sdam->sdam_config.word_size = 1; + sdam->sdam_config.reg_read = sdam_read; +--- a/drivers/nvmem/snvs_lpgpr.c ++++ b/drivers/nvmem/snvs_lpgpr.c +@@ -123,7 +123,7 @@ static int snvs_lpgpr_probe(struct platf + cfg->dev = dev; + cfg->stride = 4; + cfg->word_size = 4; +- cfg->size = dcfg->size, ++ cfg->size = dcfg->size; + cfg->owner = THIS_MODULE; + cfg->reg_read = snvs_lpgpr_read; + cfg->reg_write = snvs_lpgpr_write; diff --git a/target/linux/generic/backport-5.10/803-v5.13-0003-nvmem-brcm_nvram-new-driver-exposing-Broadcom-s-NVRA.patch b/target/linux/generic/backport-5.10/803-v5.13-0003-nvmem-brcm_nvram-new-driver-exposing-Broadcom-s-NVRA.patch new file mode 100644 index 0000000000..17be01c14f --- /dev/null +++ b/target/linux/generic/backport-5.10/803-v5.13-0003-nvmem-brcm_nvram-new-driver-exposing-Broadcom-s-NVRA.patch @@ -0,0 +1,126 @@ +From 3fef9ed0627af30753a2404b8bd59d92cdb4c0ce Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 30 Mar 2021 12:12:36 +0100 +Subject: [PATCH] nvmem: brcm_nvram: new driver exposing Broadcom's NVRAM +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This driver provides access to Broadcom's NVRAM. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210330111241.19401-6-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 9 +++++ + drivers/nvmem/Makefile | 2 + + drivers/nvmem/brcm_nvram.c | 78 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 89 insertions(+) + create mode 100644 drivers/nvmem/brcm_nvram.c + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -278,4 +278,13 @@ config NVMEM_RMEM + + This driver can also be built as a module. If so, the module + will be called nvmem-rmem. ++ ++config NVMEM_BRCM_NVRAM ++ tristate "Broadcom's NVRAM support" ++ depends on ARCH_BCM_5301X || COMPILE_TEST ++ depends on HAS_IOMEM ++ help ++ This driver provides support for Broadcom's NVRAM that can be accessed ++ using I/O mapping. ++ + endif +--- a/drivers/nvmem/Makefile ++++ b/drivers/nvmem/Makefile +@@ -57,3 +57,5 @@ obj-$(CONFIG_SPRD_EFUSE) += nvmem_sprd_e + nvmem_sprd_efuse-y := sprd-efuse.o + obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o + nvmem-rmem-y := rmem.o ++obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_brcm_nvram.o ++nvmem_brcm_nvram-y := brcm_nvram.o +--- /dev/null ++++ b/drivers/nvmem/brcm_nvram.c +@@ -0,0 +1,78 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2021 Rafał Miłecki ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++struct brcm_nvram { ++ struct device *dev; ++ void __iomem *base; ++}; ++ ++static int brcm_nvram_read(void *context, unsigned int offset, void *val, ++ size_t bytes) ++{ ++ struct brcm_nvram *priv = context; ++ u8 *dst = val; ++ ++ while (bytes--) ++ *dst++ = readb(priv->base + offset++); ++ ++ return 0; ++} ++ ++static int brcm_nvram_probe(struct platform_device *pdev) ++{ ++ struct nvmem_config config = { ++ .name = "brcm-nvram", ++ .reg_read = brcm_nvram_read, ++ }; ++ struct device *dev = &pdev->dev; ++ struct resource *res; ++ struct brcm_nvram *priv; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ priv->dev = dev; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ priv->base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ config.dev = dev; ++ config.priv = priv; ++ config.size = resource_size(res); ++ ++ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); ++} ++ ++static const struct of_device_id brcm_nvram_of_match_table[] = { ++ { .compatible = "brcm,nvram", }, ++ {}, ++}; ++ ++static struct platform_driver brcm_nvram_driver = { ++ .probe = brcm_nvram_probe, ++ .driver = { ++ .name = "brcm_nvram", ++ .of_match_table = brcm_nvram_of_match_table, ++ }, ++}; ++ ++static int __init brcm_nvram_init(void) ++{ ++ return platform_driver_register(&brcm_nvram_driver); ++} ++ ++subsys_initcall_sync(brcm_nvram_init); ++ ++MODULE_AUTHOR("Rafał Miłecki"); ++MODULE_LICENSE("GPL"); ++MODULE_DEVICE_TABLE(of, brcm_nvram_of_match_table); diff --git a/target/linux/generic/backport-5.10/803-v5.13-0004-nvmem-core-Add-functions-to-make-number-reading-easy.patch b/target/linux/generic/backport-5.10/803-v5.13-0004-nvmem-core-Add-functions-to-make-number-reading-easy.patch new file mode 100644 index 0000000000..ff2456722f --- /dev/null +++ b/target/linux/generic/backport-5.10/803-v5.13-0004-nvmem-core-Add-functions-to-make-number-reading-easy.patch @@ -0,0 +1,174 @@ +From a28e824fb8270eda43fd0f65c2a5fdf33f55c5eb Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Tue, 30 Mar 2021 12:12:37 +0100 +Subject: [PATCH] nvmem: core: Add functions to make number reading easy + +Sometimes the clients of nvmem just want to get a number out of +nvmem. They don't want to think about exactly how many bytes the nvmem +cell took up. They just want the number. Let's make it easy. + +In general this concept is useful because nvmem space is precious and +usually the fewest bits are allocated that will hold a given value on +a given system. However, even though small numbers might be fine on +one system that doesn't mean that logically the number couldn't be +bigger. Imagine nvmem containing a max frequency for a component. On +one system perhaps that fits in 16 bits. On another system it might +fit in 32 bits. The code reading this number doesn't care--it just +wants the number. + +We'll provide two functions: nvmem_cell_read_variable_le_u32() and +nvmem_cell_read_variable_le_u64(). + +Comparing these to the existing functions like nvmem_cell_read_u32(): +* These new functions have no problems if the value was stored in + nvmem in fewer bytes. It's OK to use these function as long as the + value stored will fit in 32-bits (or 64-bits). +* These functions avoid problems that the earlier APIs had with bit + offsets. For instance, you can't use nvmem_cell_read_u32() to read a + value has nbits=32 and bit_offset=4 because the nvmem cell must be + at least 5 bytes big to hold this value. The new API accounts for + this and works fine. +* These functions make it very explicit that they assume that the + number was stored in little endian format. The old functions made + this assumption whenever bit_offset was non-zero (see + nvmem_shift_read_buffer_in_place()) but didn't whenever the + bit_offset was zero. + +NOTE: it's assumed that we don't need an 8-bit or 16-bit version of +this function. The 32-bit version of the function can be used to read +8-bit or 16-bit data. + +At the moment, I'm only adding the "unsigned" versions of these +functions, but if it ends up being useful someone could add a "signed" +version that did 2's complement sign extension. + +At the moment, I'm only adding the "little endian" versions of these +functions. Adding the "big endian" version would require adding "big +endian" support to nvmem_shift_read_buffer_in_place(). + +Signed-off-by: Douglas Anderson +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210330111241.19401-7-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 95 ++++++++++++++++++++++++++++++++++ + include/linux/nvmem-consumer.h | 4 ++ + 2 files changed, 99 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -1612,6 +1612,101 @@ int nvmem_cell_read_u64(struct device *d + } + EXPORT_SYMBOL_GPL(nvmem_cell_read_u64); + ++static void *nvmem_cell_read_variable_common(struct device *dev, ++ const char *cell_id, ++ size_t max_len, size_t *len) ++{ ++ struct nvmem_cell *cell; ++ int nbits; ++ void *buf; ++ ++ cell = nvmem_cell_get(dev, cell_id); ++ if (IS_ERR(cell)) ++ return cell; ++ ++ nbits = cell->nbits; ++ buf = nvmem_cell_read(cell, len); ++ nvmem_cell_put(cell); ++ if (IS_ERR(buf)) ++ return buf; ++ ++ /* ++ * If nbits is set then nvmem_cell_read() can significantly exaggerate ++ * the length of the real data. Throw away the extra junk. ++ */ ++ if (nbits) ++ *len = DIV_ROUND_UP(nbits, 8); ++ ++ if (*len > max_len) { ++ kfree(buf); ++ return ERR_PTR(-ERANGE); ++ } ++ ++ return buf; ++} ++ ++/** ++ * nvmem_cell_read_variable_le_u32() - Read up to 32-bits of data as a little endian number. ++ * ++ * @dev: Device that requests the nvmem cell. ++ * @cell_id: Name of nvmem cell to read. ++ * @val: pointer to output value. ++ * ++ * Return: 0 on success or negative errno. ++ */ ++int nvmem_cell_read_variable_le_u32(struct device *dev, const char *cell_id, ++ u32 *val) ++{ ++ size_t len; ++ u8 *buf; ++ int i; ++ ++ buf = nvmem_cell_read_variable_common(dev, cell_id, sizeof(*val), &len); ++ if (IS_ERR(buf)) ++ return PTR_ERR(buf); ++ ++ /* Copy w/ implicit endian conversion */ ++ *val = 0; ++ for (i = 0; i < len; i++) ++ *val |= buf[i] << (8 * i); ++ ++ kfree(buf); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nvmem_cell_read_variable_le_u32); ++ ++/** ++ * nvmem_cell_read_variable_le_u64() - Read up to 64-bits of data as a little endian number. ++ * ++ * @dev: Device that requests the nvmem cell. ++ * @cell_id: Name of nvmem cell to read. ++ * @val: pointer to output value. ++ * ++ * Return: 0 on success or negative errno. ++ */ ++int nvmem_cell_read_variable_le_u64(struct device *dev, const char *cell_id, ++ u64 *val) ++{ ++ size_t len; ++ u8 *buf; ++ int i; ++ ++ buf = nvmem_cell_read_variable_common(dev, cell_id, sizeof(*val), &len); ++ if (IS_ERR(buf)) ++ return PTR_ERR(buf); ++ ++ /* Copy w/ implicit endian conversion */ ++ *val = 0; ++ for (i = 0; i < len; i++) ++ *val |= buf[i] << (8 * i); ++ ++ kfree(buf); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nvmem_cell_read_variable_le_u64); ++ + /** + * nvmem_device_cell_read() - Read a given nvmem device and cell + * +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -65,6 +65,10 @@ int nvmem_cell_read_u8(struct device *de + int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val); + int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val); + int nvmem_cell_read_u64(struct device *dev, const char *cell_id, u64 *val); ++int nvmem_cell_read_variable_le_u32(struct device *dev, const char *cell_id, ++ u32 *val); ++int nvmem_cell_read_variable_le_u64(struct device *dev, const char *cell_id, ++ u64 *val); + + /* direct nvmem device read/write interface */ + struct nvmem_device *nvmem_device_get(struct device *dev, const char *name); diff --git a/target/linux/generic/backport-5.10/803-v5.13-0005-nvmem-core-Fix-unintentional-sign-extension-issue.patch b/target/linux/generic/backport-5.10/803-v5.13-0005-nvmem-core-Fix-unintentional-sign-extension-issue.patch new file mode 100644 index 0000000000..72133d3a35 --- /dev/null +++ b/target/linux/generic/backport-5.10/803-v5.13-0005-nvmem-core-Fix-unintentional-sign-extension-issue.patch @@ -0,0 +1,34 @@ +From 55022fdeace8e432f008787ce03703bdcc9c3ca9 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Tue, 30 Mar 2021 12:12:38 +0100 +Subject: [PATCH] nvmem: core: Fix unintentional sign extension issue + +The shifting of the u8 integer buf[3] by 24 bits to the left will +be promoted to a 32 bit signed int and then sign-extended to a +u64. In the event that the top bit of buf[3] is set then all +then all the upper 32 bits of the u64 end up as also being set +because of the sign-extension. Fix this by casting buf[i] to +a u64 before the shift. + +Fixes: a28e824fb827 ("nvmem: core: Add functions to make number reading easy") +Reviewed-by: Douglas Anderson +Signed-off-by: Colin Ian King +Signed-off-by: Srinivas Kandagatla +Addresses-Coverity: ("Unintended sign extension") +Link: https://lore.kernel.org/r/20210330111241.19401-8-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -1699,7 +1699,7 @@ int nvmem_cell_read_variable_le_u64(stru + /* Copy w/ implicit endian conversion */ + *val = 0; + for (i = 0; i < len; i++) +- *val |= buf[i] << (8 * i); ++ *val |= (uint64_t)buf[i] << (8 * i); + + kfree(buf); + diff --git a/target/linux/generic/backport-5.10/803-v5.13-0006-nvmem-rmem-fix-undefined-reference-to-memremap.patch b/target/linux/generic/backport-5.10/803-v5.13-0006-nvmem-rmem-fix-undefined-reference-to-memremap.patch new file mode 100644 index 0000000000..9e13fb6708 --- /dev/null +++ b/target/linux/generic/backport-5.10/803-v5.13-0006-nvmem-rmem-fix-undefined-reference-to-memremap.patch @@ -0,0 +1,29 @@ +From cc1bc56fdc76a55bb8fae9a145a2e60bf22fb129 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +Date: Tue, 30 Mar 2021 12:12:39 +0100 +Subject: [PATCH] nvmem: rmem: fix undefined reference to memremap + +Fix below error reporte by kernel test robot +rmem.c:(.text+0x14e): undefined reference to memremap +s390x-linux-gnu-ld: rmem.c:(.text+0x1b6): undefined reference to memunmap + +Fixes: 5a3fa75a4d9c ("nvmem: Add driver to expose reserved memory as nvmem") +Reported-by: kernel test robot +Reviewed-by: Nicolas Saenz Julienne +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210330111241.19401-9-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -272,6 +272,7 @@ config SPRD_EFUSE + + config NVMEM_RMEM + tristate "Reserved Memory Based Driver Support" ++ depends on HAS_IOMEM + help + This driver maps reserved memory into an nvmem device. It might be + useful to expose information left by firmware in memory. diff --git a/target/linux/generic/backport-5.10/803-v5.13-0007-nvmem-qfprom-Add-support-for-fuse-blowing-on-sc7280.patch b/target/linux/generic/backport-5.10/803-v5.13-0007-nvmem-qfprom-Add-support-for-fuse-blowing-on-sc7280.patch new file mode 100644 index 0000000000..0e75d4c93d --- /dev/null +++ b/target/linux/generic/backport-5.10/803-v5.13-0007-nvmem-qfprom-Add-support-for-fuse-blowing-on-sc7280.patch @@ -0,0 +1,102 @@ +From 5a1bea2a2572ce5eb4bdcf432a6929681ee381f2 Mon Sep 17 00:00:00 2001 +From: Rajendra Nayak +Date: Tue, 30 Mar 2021 12:12:41 +0100 +Subject: [PATCH] nvmem: qfprom: Add support for fuse blowing on sc7280 + +Handle the differences across LDO voltage needed for blowing fuses, +and the blow timer value, identified using a minor version of 15 +on sc7280. + +Signed-off-by: Rajendra Nayak +Signed-off-by: Ravi Kumar Bokka +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210330111241.19401-11-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/qfprom.c | 27 +++++++++++++++++++++++++-- + 1 file changed, 25 insertions(+), 2 deletions(-) + +--- a/drivers/nvmem/qfprom.c ++++ b/drivers/nvmem/qfprom.c +@@ -45,11 +45,13 @@ MODULE_PARM_DESC(read_raw_data, "Read ra + * @qfprom_blow_timer_value: The timer value of qfprom when doing efuse blow. + * @qfprom_blow_set_freq: The frequency required to set when we start the + * fuse blowing. ++ * @qfprom_blow_uV: LDO voltage to be set when doing efuse blow + */ + struct qfprom_soc_data { + u32 accel_value; + u32 qfprom_blow_timer_value; + u32 qfprom_blow_set_freq; ++ int qfprom_blow_uV; + }; + + /** +@@ -111,6 +113,15 @@ static const struct qfprom_soc_compatibl + .nkeepout = ARRAY_SIZE(sc7180_qfprom_keepout) + }; + ++static const struct nvmem_keepout sc7280_qfprom_keepout[] = { ++ {.start = 0x128, .end = 0x148}, ++ {.start = 0x238, .end = 0x248} ++}; ++ ++static const struct qfprom_soc_compatible_data sc7280_qfprom = { ++ .keepout = sc7280_qfprom_keepout, ++ .nkeepout = ARRAY_SIZE(sc7280_qfprom_keepout) ++}; + /** + * qfprom_disable_fuse_blowing() - Undo enabling of fuse blowing. + * @priv: Our driver data. +@@ -168,6 +179,7 @@ static int qfprom_enable_fuse_blowing(co + struct qfprom_touched_values *old) + { + int ret; ++ int qfprom_blow_uV = priv->soc_data->qfprom_blow_uV; + + ret = clk_prepare_enable(priv->secclk); + if (ret) { +@@ -187,9 +199,9 @@ static int qfprom_enable_fuse_blowing(co + * a rail shared do don't specify a max--regulator constraints + * will handle. + */ +- ret = regulator_set_voltage(priv->vcc, 1800000, INT_MAX); ++ ret = regulator_set_voltage(priv->vcc, qfprom_blow_uV, INT_MAX); + if (ret) { +- dev_err(priv->dev, "Failed to set 1.8 voltage\n"); ++ dev_err(priv->dev, "Failed to set %duV\n", qfprom_blow_uV); + goto err_clk_rate_set; + } + +@@ -311,6 +323,14 @@ static const struct qfprom_soc_data qfpr + .accel_value = 0xD10, + .qfprom_blow_timer_value = 25, + .qfprom_blow_set_freq = 4800000, ++ .qfprom_blow_uV = 1800000, ++}; ++ ++static const struct qfprom_soc_data qfprom_7_15_data = { ++ .accel_value = 0xD08, ++ .qfprom_blow_timer_value = 24, ++ .qfprom_blow_set_freq = 4800000, ++ .qfprom_blow_uV = 1900000, + }; + + static int qfprom_probe(struct platform_device *pdev) +@@ -379,6 +399,8 @@ static int qfprom_probe(struct platform_ + + if (major_version == 7 && minor_version == 8) + priv->soc_data = &qfprom_7_8_data; ++ if (major_version == 7 && minor_version == 15) ++ priv->soc_data = &qfprom_7_15_data; + + priv->vcc = devm_regulator_get(&pdev->dev, "vcc"); + if (IS_ERR(priv->vcc)) +@@ -405,6 +427,7 @@ static int qfprom_probe(struct platform_ + static const struct of_device_id qfprom_of_match[] = { + { .compatible = "qcom,qfprom",}, + { .compatible = "qcom,sc7180-qfprom", .data = &sc7180_qfprom}, ++ { .compatible = "qcom,sc7280-qfprom", .data = &sc7280_qfprom}, + {/* sentinel */}, + }; + MODULE_DEVICE_TABLE(of, qfprom_of_match); diff --git a/target/linux/generic/backport-5.10/803-v6.2-0001-nvmem-u-boot-env-fix-crc32_data_offset-on-redundant-.patch b/target/linux/generic/backport-5.10/803-v6.2-0001-nvmem-u-boot-env-fix-crc32_data_offset-on-redundant-.patch deleted file mode 100644 index 69d5a1b845..0000000000 --- a/target/linux/generic/backport-5.10/803-v6.2-0001-nvmem-u-boot-env-fix-crc32_data_offset-on-redundant-.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 7a69ff9c9bde03a690ea783970f664782fc303d8 Mon Sep 17 00:00:00 2001 -From: Christian Lamparter -Date: Fri, 4 Nov 2022 17:52:03 +0100 -Subject: [PATCH] nvmem: u-boot-env: fix crc32_data_offset on redundant - u-boot-env - -The Western Digital MyBook Live (PowerPC 464/APM82181) -has a set of redundant u-boot-env. Loading up the driver -the following error: - -| u_boot_env: Invalid calculated CRC32: 0x4f8f2c86 (expected: 0x98b14514) -| u_boot_env: probe of partition@1e000 failed with error -22 - -Looking up the userspace libubootenv utilities source [0], -it looks like the "mark" or "flag" is not part of the -crc32 sum... which is unfortunate :( - -|static int libuboot_load(struct uboot_ctx *ctx) -|{ -|[...] -| if (ctx->redundant) { -| [...] -| offsetdata = offsetof(struct uboot_env_redund, data); -| [...] //-----^^ -| } -| usable_envsize = ctx->size - offsetdata; -| buf[0] = malloc(bufsize); -|[...] -| for (i = 0; i < copies; i++) { -| data = (uint8_t *)(buf[i] + offsetdata); -| uint32_t crc; -| -| ret = devread(ctx, i, buf[i]); -| [...] -| crc = *(uint32_t *)(buf[i] + offsetcrc); -| dev->crc = crc32(0, (uint8_t *)data, usable_envsize); -| - -[0] https://github.com/sbabic/libubootenv/blob/master/src/uboot_env.c#L951 -Fixes: d5542923f200 ("nvmem: add driver handling U-Boot environment variables") -Signed-off-by: Christian Lamparter ---- - drivers/nvmem/u-boot-env.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/u-boot-env.c -+++ b/drivers/nvmem/u-boot-env.c -@@ -135,7 +135,7 @@ static int u_boot_env_parse(struct u_boo - break; - case U_BOOT_FORMAT_REDUNDANT: - crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32); -- crc32_data_offset = offsetof(struct u_boot_env_image_redundant, mark); -+ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); - data_offset = offsetof(struct u_boot_env_image_redundant, data); - break; - } diff --git a/target/linux/generic/backport-5.10/803-v6.2-0002-nvmem-u-boot-env-align-endianness-of-crc32-values.patch b/target/linux/generic/backport-5.10/803-v6.2-0002-nvmem-u-boot-env-align-endianness-of-crc32-values.patch deleted file mode 100644 index 7d6723bb8e..0000000000 --- a/target/linux/generic/backport-5.10/803-v6.2-0002-nvmem-u-boot-env-align-endianness-of-crc32-values.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0e71cac033bb7689c4dfa2e6814191337ef770f5 Mon Sep 17 00:00:00 2001 -From: INAGAKI Hiroshi -Date: Thu, 13 Oct 2022 00:51:33 +0900 -Subject: [PATCH] nvmem: u-boot-env: align endianness of crc32 values -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This patch fixes crc32 error on Big-Endianness system by conversion of -calculated crc32 value. - -Little-Endianness system: - - obtained crc32: Little -calculated crc32: Little - -Big-Endianness system: - - obtained crc32: Little -calculated crc32: Big - -log (APRESIA ApresiaLightGS120GT-SS, RTL8382M, Big-Endianness): - -[ 8.570000] u_boot_env 18001200.spi:flash@0:partitions:partition@c0000: Invalid calculated CRC32: 0x88cd6f09 (expected: 0x096fcd88) -[ 8.580000] u_boot_env: probe of 18001200.spi:flash@0:partitions:partition@c0000 failed with error -22 - -Fixes: f955dc1445069 ("nvmem: add driver handling U-Boot environment variables") - -Signed-off-by: INAGAKI Hiroshi -Acked-by: Rafał Miłecki -Tested-by: Christian Lamparter -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/u-boot-env.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/u-boot-env.c -+++ b/drivers/nvmem/u-boot-env.c -@@ -143,7 +143,7 @@ static int u_boot_env_parse(struct u_boo - crc32_data_len = priv->mtd->size - crc32_data_offset; - data_len = priv->mtd->size - data_offset; - -- calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; -+ calc = le32_to_cpu((__le32)crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L); - if (calc != crc32) { - dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32); - err = -EINVAL; diff --git a/target/linux/generic/backport-5.10/803-v6.2-0003-nvmem-u-boot-env-add-Broadcom-format-support.patch b/target/linux/generic/backport-5.10/803-v6.2-0003-nvmem-u-boot-env-add-Broadcom-format-support.patch deleted file mode 100644 index 429b24f0f3..0000000000 --- a/target/linux/generic/backport-5.10/803-v6.2-0003-nvmem-u-boot-env-add-Broadcom-format-support.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 5b4eaafbeac472fc19049152f18e88aecb2b2829 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Mon, 17 Oct 2022 09:17:22 +0200 -Subject: [PATCH] nvmem: u-boot-env: add Broadcom format support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Broadcom uses U-Boot for a lot of their bcmbca familiy chipsets. They -decided to store U-Boot environment data inside U-Boot partition and to -use a custom header (with "uEnv" magic and env data length). - -Add support for Broadcom's specific binding and their custom format. - -Ref: 6b0584c19d87 ("dt-bindings: nvmem: u-boot,env: add Broadcom's variant binding") -Signed-off-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/u-boot-env.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/nvmem/u-boot-env.c -+++ b/drivers/nvmem/u-boot-env.c -@@ -16,6 +16,7 @@ - enum u_boot_env_format { - U_BOOT_FORMAT_SINGLE, - U_BOOT_FORMAT_REDUNDANT, -+ U_BOOT_FORMAT_BROADCOM, - }; - - struct u_boot_env { -@@ -40,6 +41,13 @@ struct u_boot_env_image_redundant { - uint8_t data[]; - } __packed; - -+struct u_boot_env_image_broadcom { -+ __le32 magic; -+ __le32 len; -+ __le32 crc32; -+ uint8_t data[0]; -+} __packed; -+ - static int u_boot_env_read(void *context, unsigned int offset, void *val, - size_t bytes) - { -@@ -138,6 +146,11 @@ static int u_boot_env_parse(struct u_boo - crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); - data_offset = offsetof(struct u_boot_env_image_redundant, data); - break; -+ case U_BOOT_FORMAT_BROADCOM: -+ crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32); -+ crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data); -+ data_offset = offsetof(struct u_boot_env_image_broadcom, data); -+ break; - } - crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); - crc32_data_len = priv->mtd->size - crc32_data_offset; -@@ -202,6 +215,7 @@ static const struct of_device_id u_boot_ - { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, }, - { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, - { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, -+ { .compatible = "brcm,env", .data = (void *)U_BOOT_FORMAT_BROADCOM, }, - {}, - }; - diff --git a/target/linux/generic/backport-5.10/804-v5.14-0001-nvmem-core-allow-specifying-of_node.patch b/target/linux/generic/backport-5.10/804-v5.14-0001-nvmem-core-allow-specifying-of_node.patch new file mode 100644 index 0000000000..8c5a55e364 --- /dev/null +++ b/target/linux/generic/backport-5.10/804-v5.14-0001-nvmem-core-allow-specifying-of_node.patch @@ -0,0 +1,80 @@ +From 1333a6779501f4cc662ff5c8b36b0a22f3a7ddc6 Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Sat, 24 Apr 2021 13:06:04 +0200 +Subject: [PATCH] nvmem: core: allow specifying of_node + +Until now, the of_node of the parent device is used. Some devices +provide more than just the nvmem provider. To avoid name space clashes, +add a way to allow specifying the nvmem cells in subnodes. Consider the +following example: + + flash@0 { + compatible = "jedec,spi-nor"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x000000 0x010000>; + }; + }; + + otp { + compatible = "user-otp"; + #address-cells = <1>; + #size-cells = <1>; + + serial-number@0 { + reg = <0x0 0x8>; + }; + }; + }; + +There the nvmem provider might be the MTD partition or the OTP region of +the flash. + +Add a new config->of_node parameter, which if set, will be used instead +of the parent's of_node. + +Signed-off-by: Michael Walle +Acked-by: Srinivas Kandagatla +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20210424110608.15748-2-michael@walle.cc +--- + drivers/nvmem/core.c | 4 +++- + include/linux/nvmem-provider.h | 2 ++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -794,7 +794,9 @@ struct nvmem_device *nvmem_register(cons + nvmem->reg_write = config->reg_write; + nvmem->keepout = config->keepout; + nvmem->nkeepout = config->nkeepout; +- if (!config->no_of_node) ++ if (config->of_node) ++ nvmem->dev.of_node = config->of_node; ++ else if (!config->no_of_node) + nvmem->dev.of_node = config->dev->of_node; + + switch (config->id) { +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -57,6 +57,7 @@ struct nvmem_keepout { + * @type: Type of the nvmem storage + * @read_only: Device is read-only. + * @root_only: Device is accessibly to root only. ++ * @of_node: If given, this will be used instead of the parent's of_node. + * @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. +@@ -86,6 +87,7 @@ struct nvmem_config { + enum nvmem_type type; + bool read_only; + bool root_only; ++ struct device_node *of_node; + bool no_of_node; + nvmem_reg_read_t reg_read; + nvmem_reg_write_t reg_write; diff --git a/target/linux/generic/backport-5.10/804-v5.14-0002-nvmem-sprd-Fix-an-error-message.patch b/target/linux/generic/backport-5.10/804-v5.14-0002-nvmem-sprd-Fix-an-error-message.patch new file mode 100644 index 0000000000..db88328a11 --- /dev/null +++ b/target/linux/generic/backport-5.10/804-v5.14-0002-nvmem-sprd-Fix-an-error-message.patch @@ -0,0 +1,30 @@ +From 20be064ec864086bca7a4eb62c772a397b44afb7 Mon Sep 17 00:00:00 2001 +From: Christophe JAILLET +Date: Fri, 7 May 2021 19:02:48 +0200 +Subject: [PATCH] nvmem: sprd: Fix an error message + +'ret' is known to be 0 here. +The expected error status is stored in 'status', so use it instead. + +Also change %d in %u, because status is an u32, not a int. + +Fixes: 096030e7f449 ("nvmem: sprd: Add Spreadtrum SoCs eFuse support") +Acked-by: Chunyan Zhang +Signed-off-by: Christophe JAILLET +Link: https://lore.kernel.org/r/5bc44aace2fe7e1c91d8b35c8fe31e7134ceab2c.1620406852.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/sprd-efuse.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/sprd-efuse.c ++++ b/drivers/nvmem/sprd-efuse.c +@@ -234,7 +234,7 @@ static int sprd_efuse_raw_prog(struct sp + status = readl(efuse->base + SPRD_EFUSE_ERR_FLAG); + if (status) { + dev_err(efuse->dev, +- "write error status %d of block %d\n", ret, blk); ++ "write error status %u of block %d\n", status, blk); + + writel(SPRD_EFUSE_ERR_CLR_MASK, + efuse->base + SPRD_EFUSE_ERR_CLR); diff --git a/target/linux/generic/backport-5.10/804-v5.14-0003-nvmem-sunxi_sid-Set-type-to-OTP.patch b/target/linux/generic/backport-5.10/804-v5.14-0003-nvmem-sunxi_sid-Set-type-to-OTP.patch new file mode 100644 index 0000000000..37694e5424 --- /dev/null +++ b/target/linux/generic/backport-5.10/804-v5.14-0003-nvmem-sunxi_sid-Set-type-to-OTP.patch @@ -0,0 +1,27 @@ +From 78a005a22d5608b266eafa011b093a33284c52ce Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Fri, 11 Jun 2021 09:33:45 +0100 +Subject: [PATCH] nvmem: sunxi_sid: Set type to OTP + +This device currently reports an "Unknown" type in sysfs. +Since it is an eFuse hardware device, set its type to OTP. + +Signed-off-by: Samuel Holland +Acked-by: Chen-Yu Tsai +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210611083348.20170-7-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/sunxi_sid.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/nvmem/sunxi_sid.c ++++ b/drivers/nvmem/sunxi_sid.c +@@ -142,6 +142,7 @@ static int sunxi_sid_probe(struct platfo + + nvmem_cfg->dev = dev; + nvmem_cfg->name = "sunxi-sid"; ++ nvmem_cfg->type = NVMEM_TYPE_OTP; + nvmem_cfg->read_only = true; + nvmem_cfg->size = cfg->size; + nvmem_cfg->word_size = 1; diff --git a/target/linux/generic/backport-5.10/804-v5.14-0004-nvmem-qfprom-minor-nit-fixes.patch b/target/linux/generic/backport-5.10/804-v5.14-0004-nvmem-qfprom-minor-nit-fixes.patch new file mode 100644 index 0000000000..bcab3e41fd --- /dev/null +++ b/target/linux/generic/backport-5.10/804-v5.14-0004-nvmem-qfprom-minor-nit-fixes.patch @@ -0,0 +1,46 @@ +From c813bb37bd32cb967060a2c573fae4ea518d32eb Mon Sep 17 00:00:00 2001 +From: Rajendra Nayak +Date: Fri, 11 Jun 2021 09:33:46 +0100 +Subject: [PATCH] nvmem: qfprom: minor nit fixes + +Fix a missed newline, change an 'if' to 'else if' and update +a comment which is stale after the merge of '5a1bea2a: nvmem: +qfprom: Add support for fuseblowing on sc7280' + +Signed-off-by: Rajendra Nayak +Reviewed-by: Douglas Anderson +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210611083348.20170-8-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/qfprom.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/nvmem/qfprom.c ++++ b/drivers/nvmem/qfprom.c +@@ -122,6 +122,7 @@ static const struct qfprom_soc_compatibl + .keepout = sc7280_qfprom_keepout, + .nkeepout = ARRAY_SIZE(sc7280_qfprom_keepout) + }; ++ + /** + * qfprom_disable_fuse_blowing() - Undo enabling of fuse blowing. + * @priv: Our driver data. +@@ -195,7 +196,7 @@ static int qfprom_enable_fuse_blowing(co + } + + /* +- * Hardware requires 1.8V min for fuse blowing; this may be ++ * Hardware requires a min voltage for fuse blowing; this may be + * a rail shared do don't specify a max--regulator constraints + * will handle. + */ +@@ -399,7 +400,7 @@ static int qfprom_probe(struct platform_ + + if (major_version == 7 && minor_version == 8) + priv->soc_data = &qfprom_7_8_data; +- if (major_version == 7 && minor_version == 15) ++ else if (major_version == 7 && minor_version == 15) + priv->soc_data = &qfprom_7_15_data; + + priv->vcc = devm_regulator_get(&pdev->dev, "vcc"); diff --git a/target/linux/generic/backport-5.10/804-v5.14-0005-nvmem-core-constify-nvmem_cell_read_variable_common-.patch b/target/linux/generic/backport-5.10/804-v5.14-0005-nvmem-core-constify-nvmem_cell_read_variable_common-.patch new file mode 100644 index 0000000000..55c3c5d6fe --- /dev/null +++ b/target/linux/generic/backport-5.10/804-v5.14-0005-nvmem-core-constify-nvmem_cell_read_variable_common-.patch @@ -0,0 +1,52 @@ +From 1f7b4d87874624f4beb25253900a25306a193b8b Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Fri, 11 Jun 2021 09:33:47 +0100 +Subject: [PATCH] nvmem: core: constify nvmem_cell_read_variable_common() + return value + +The caller doesn't modify the memory pointed to by the pointer so it +can be const. + +Suggested-by: Stephen Boyd +Signed-off-by: Douglas Anderson +Reviewed-by: Stephen Boyd +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210611083348.20170-9-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -1614,9 +1614,9 @@ int nvmem_cell_read_u64(struct device *d + } + EXPORT_SYMBOL_GPL(nvmem_cell_read_u64); + +-static void *nvmem_cell_read_variable_common(struct device *dev, +- const char *cell_id, +- size_t max_len, size_t *len) ++static const void *nvmem_cell_read_variable_common(struct device *dev, ++ const char *cell_id, ++ size_t max_len, size_t *len) + { + struct nvmem_cell *cell; + int nbits; +@@ -1660,7 +1660,7 @@ int nvmem_cell_read_variable_le_u32(stru + u32 *val) + { + size_t len; +- u8 *buf; ++ const u8 *buf; + int i; + + buf = nvmem_cell_read_variable_common(dev, cell_id, sizeof(*val), &len); +@@ -1691,7 +1691,7 @@ int nvmem_cell_read_variable_le_u64(stru + u64 *val) + { + size_t len; +- u8 *buf; ++ const u8 *buf; + int i; + + buf = nvmem_cell_read_variable_common(dev, cell_id, sizeof(*val), &len); diff --git a/target/linux/generic/backport-5.10/804-v5.14-0006-nvmem-qfprom-Improve-the-comment-about-regulator-set.patch b/target/linux/generic/backport-5.10/804-v5.14-0006-nvmem-qfprom-Improve-the-comment-about-regulator-set.patch new file mode 100644 index 0000000000..d7ef8e620f --- /dev/null +++ b/target/linux/generic/backport-5.10/804-v5.14-0006-nvmem-qfprom-Improve-the-comment-about-regulator-set.patch @@ -0,0 +1,33 @@ +From 989f77e3fdee2e8f414dd1da9b6397d8763d414e Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Fri, 11 Jun 2021 09:33:48 +0100 +Subject: [PATCH] nvmem: qfprom: Improve the comment about regulator setting + +In review feedback Joe Perches found the existing comment +confusing. Let's use something based on the wording proposed by Joe. + +Suggested-by: Joe Perches +Signed-off-by: Douglas Anderson +Reviewed-by: Stephen Boyd +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210611083348.20170-10-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/qfprom.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/nvmem/qfprom.c ++++ b/drivers/nvmem/qfprom.c +@@ -196,9 +196,9 @@ static int qfprom_enable_fuse_blowing(co + } + + /* +- * Hardware requires a min voltage for fuse blowing; this may be +- * a rail shared do don't specify a max--regulator constraints +- * will handle. ++ * Hardware requires a minimum voltage for fuse blowing. ++ * This may be a shared rail so don't specify a maximum. ++ * Regulator constraints will cap to the actual maximum. + */ + ret = regulator_set_voltage(priv->vcc, qfprom_blow_uV, INT_MAX); + if (ret) { diff --git a/target/linux/generic/backport-5.10/804-v5.14-0007-nvmem-add-NVMEM_TYPE_FRAM.patch b/target/linux/generic/backport-5.10/804-v5.14-0007-nvmem-add-NVMEM_TYPE_FRAM.patch new file mode 100644 index 0000000000..06c541b8e6 --- /dev/null +++ b/target/linux/generic/backport-5.10/804-v5.14-0007-nvmem-add-NVMEM_TYPE_FRAM.patch @@ -0,0 +1,36 @@ +From: Rafał Miłecki +Subject: [PATCH] nvmem: add NVMEM_TYPE_FRAM + +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -180,6 +180,7 @@ static const char * const nvmem_type_str + [NVMEM_TYPE_EEPROM] = "EEPROM", + [NVMEM_TYPE_OTP] = "OTP", + [NVMEM_TYPE_BATTERY_BACKED] = "Battery backed", ++ [NVMEM_TYPE_FRAM] = "FRAM", + }; + + #ifdef CONFIG_DEBUG_LOCK_ALLOC +@@ -361,6 +362,9 @@ static int nvmem_sysfs_setup_compat(stru + if (!config->base_dev) + return -EINVAL; + ++ if (config->type == NVMEM_TYPE_FRAM) ++ bin_attr_nvmem_eeprom_compat.attr.name = "fram"; ++ + nvmem->eeprom = bin_attr_nvmem_eeprom_compat; + nvmem->eeprom.attr.mode = nvmem_bin_attr_get_umode(nvmem); + nvmem->eeprom.size = nvmem->size; +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -25,6 +25,7 @@ enum nvmem_type { + NVMEM_TYPE_EEPROM, + NVMEM_TYPE_OTP, + NVMEM_TYPE_BATTERY_BACKED, ++ NVMEM_TYPE_FRAM, + }; + + #define NVMEM_DEVID_NONE (-1) diff --git a/target/linux/generic/backport-5.10/805-v5.15-0002-nvmem-qfprom-sc7280-Handle-the-additional-power-doma.patch b/target/linux/generic/backport-5.10/805-v5.15-0002-nvmem-qfprom-sc7280-Handle-the-additional-power-doma.patch new file mode 100644 index 0000000000..b71edd0306 --- /dev/null +++ b/target/linux/generic/backport-5.10/805-v5.15-0002-nvmem-qfprom-sc7280-Handle-the-additional-power-doma.patch @@ -0,0 +1,89 @@ +From 7b808449f572d07bee840cd9da7e2fe6a1b8f4b5 Mon Sep 17 00:00:00 2001 +From: Rajendra Nayak +Date: Fri, 6 Aug 2021 09:59:46 +0100 +Subject: [PATCH] nvmem: qfprom: sc7280: Handle the additional power-domains + vote + +On sc7280, to reliably blow fuses, we need an additional vote +on max performance state of 'MX' power-domain. +Add support for power-domain performance state voting in the +driver. + +Reviewed-by: Douglas Anderson +Signed-off-by: Rajendra Nayak +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210806085947.22682-4-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/qfprom.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +--- a/drivers/nvmem/qfprom.c ++++ b/drivers/nvmem/qfprom.c +@@ -12,6 +12,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + +@@ -142,6 +144,9 @@ static void qfprom_disable_fuse_blowing( + writel(old->timer_val, priv->qfpconf + QFPROM_BLOW_TIMER_OFFSET); + writel(old->accel_val, priv->qfpconf + QFPROM_ACCEL_OFFSET); + ++ dev_pm_genpd_set_performance_state(priv->dev, 0); ++ pm_runtime_put(priv->dev); ++ + /* + * This may be a shared rail and may be able to run at a lower rate + * when we're not blowing fuses. At the moment, the regulator framework +@@ -212,6 +217,14 @@ static int qfprom_enable_fuse_blowing(co + goto err_clk_rate_set; + } + ++ ret = pm_runtime_get_sync(priv->dev); ++ if (ret < 0) { ++ pm_runtime_put_noidle(priv->dev); ++ dev_err(priv->dev, "Failed to enable power-domain\n"); ++ goto err_reg_enable; ++ } ++ dev_pm_genpd_set_performance_state(priv->dev, INT_MAX); ++ + old->timer_val = readl(priv->qfpconf + QFPROM_BLOW_TIMER_OFFSET); + old->accel_val = readl(priv->qfpconf + QFPROM_ACCEL_OFFSET); + writel(priv->soc_data->qfprom_blow_timer_value, +@@ -221,6 +234,8 @@ static int qfprom_enable_fuse_blowing(co + + return 0; + ++err_reg_enable: ++ regulator_disable(priv->vcc); + err_clk_rate_set: + clk_set_rate(priv->secclk, old->clk_rate); + err_clk_prepared: +@@ -320,6 +335,11 @@ static int qfprom_reg_read(void *context + return 0; + } + ++static void qfprom_runtime_disable(void *data) ++{ ++ pm_runtime_disable(data); ++} ++ + static const struct qfprom_soc_data qfprom_7_8_data = { + .accel_value = 0xD10, + .qfprom_blow_timer_value = 25, +@@ -420,6 +440,11 @@ static int qfprom_probe(struct platform_ + econfig.reg_write = qfprom_reg_write; + } + ++ pm_runtime_enable(dev); ++ ret = devm_add_action_or_reset(dev, qfprom_runtime_disable, dev); ++ if (ret) ++ return ret; ++ + nvmem = devm_nvmem_register(dev, &econfig); + + return PTR_ERR_OR_ZERO(nvmem); diff --git a/target/linux/generic/backport-5.10/805-v5.15-0003-nvmem-core-fix-error-handling-while-validating-keepo.patch b/target/linux/generic/backport-5.10/805-v5.15-0003-nvmem-core-fix-error-handling-while-validating-keepo.patch new file mode 100644 index 0000000000..59c9281cdb --- /dev/null +++ b/target/linux/generic/backport-5.10/805-v5.15-0003-nvmem-core-fix-error-handling-while-validating-keepo.patch @@ -0,0 +1,36 @@ +From de0534df93474f268486c486ea7e01b44a478026 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +Date: Fri, 6 Aug 2021 09:59:47 +0100 +Subject: [PATCH] nvmem: core: fix error handling while validating keepout + regions + +Current error path on failure of validating keepout regions is calling +put_device, eventhough the device is not even registered at that point. + +Fix this by adding proper error handling of freeing ida and nvmem. + +Fixes: fd3bb8f54a88 ("nvmem: core: Add support for keepout regions") +Cc: +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210806085947.22682-5-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -826,8 +826,11 @@ struct nvmem_device *nvmem_register(cons + + if (nvmem->nkeepout) { + rval = nvmem_validate_keepouts(nvmem); +- if (rval) +- goto err_put_device; ++ if (rval) { ++ ida_free(&nvmem_ida, nvmem->id); ++ kfree(nvmem); ++ return ERR_PTR(rval); ++ } + } + + dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); diff --git a/target/linux/generic/backport-5.10/805-v5.15-0004-nvmem-nintendo-otp-Add-new-driver-for-the-Wii-and-Wi.patch b/target/linux/generic/backport-5.10/805-v5.15-0004-nvmem-nintendo-otp-Add-new-driver-for-the-Wii-and-Wi.patch new file mode 100644 index 0000000000..62d9e2aa0f --- /dev/null +++ b/target/linux/generic/backport-5.10/805-v5.15-0004-nvmem-nintendo-otp-Add-new-driver-for-the-Wii-and-Wi.patch @@ -0,0 +1,191 @@ +From 3683b761fe3a10ad18515acd5368dd601268cfe5 Mon Sep 17 00:00:00 2001 +From: Emmanuel Gil Peyrot +Date: Tue, 10 Aug 2021 16:30:36 +0100 +Subject: [PATCH] nvmem: nintendo-otp: Add new driver for the Wii and Wii U OTP +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This OTP is read-only and contains various keys used by the console to +decrypt, encrypt or verify various pieces of storage. + +Its size depends on the console, it is 128 bytes on the Wii and +1024 bytes on the Wii U (split into eight 128 bytes banks). + +It can be used directly by writing into one register and reading from +the other one, without any additional synchronisation. + +This driver was written based on reversed documentation, see: +https://wiiubrew.org/wiki/Hardware/OTP + +Tested-by: Jonathan Neuschäfer # on Wii +Tested-by: Emmanuel Gil Peyrot # on Wii U +Signed-off-by: Emmanuel Gil Peyrot +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20210810153036.1494-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 11 ++++ + drivers/nvmem/Makefile | 2 + + drivers/nvmem/nintendo-otp.c | 124 +++++++++++++++++++++++++++++++++++ + 3 files changed, 137 insertions(+) + create mode 100644 drivers/nvmem/nintendo-otp.c + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -107,6 +107,17 @@ config MTK_EFUSE + This driver can also be built as a module. If so, the module + will be called efuse-mtk. + ++config NVMEM_NINTENDO_OTP ++ tristate "Nintendo Wii and Wii U OTP Support" ++ help ++ This is a driver exposing the OTP of a Nintendo Wii or Wii U console. ++ ++ This memory contains common and per-console keys, signatures and ++ related data required to access peripherals. ++ ++ This driver can also be built as a module. If so, the module ++ will be called nvmem-nintendo-otp. ++ + config QCOM_QFPROM + tristate "QCOM QFPROM Support" + depends on ARCH_QCOM || COMPILE_TEST +--- a/drivers/nvmem/Makefile ++++ b/drivers/nvmem/Makefile +@@ -23,6 +23,8 @@ obj-$(CONFIG_NVMEM_LPC18XX_OTP) += nvmem + nvmem_lpc18xx_otp-y := lpc18xx_otp.o + obj-$(CONFIG_NVMEM_MXS_OCOTP) += nvmem-mxs-ocotp.o + nvmem-mxs-ocotp-y := mxs-ocotp.o ++obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvmem-nintendo-otp.o ++nvmem-nintendo-otp-y := nintendo-otp.o + obj-$(CONFIG_MTK_EFUSE) += nvmem_mtk-efuse.o + nvmem_mtk-efuse-y := mtk-efuse.o + obj-$(CONFIG_QCOM_QFPROM) += nvmem_qfprom.o +--- /dev/null ++++ b/drivers/nvmem/nintendo-otp.c +@@ -0,0 +1,124 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Nintendo Wii and Wii U OTP driver ++ * ++ * This is a driver exposing the OTP of a Nintendo Wii or Wii U console. ++ * ++ * This memory contains common and per-console keys, signatures and ++ * related data required to access peripherals. ++ * ++ * Based on reversed documentation from https://wiiubrew.org/wiki/Hardware/OTP ++ * ++ * Copyright (C) 2021 Emmanuel Gil Peyrot ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define HW_OTPCMD 0 ++#define HW_OTPDATA 4 ++#define OTP_READ 0x80000000 ++#define BANK_SIZE 128 ++#define WORD_SIZE 4 ++ ++struct nintendo_otp_priv { ++ void __iomem *regs; ++}; ++ ++struct nintendo_otp_devtype_data { ++ const char *name; ++ unsigned int num_banks; ++}; ++ ++static const struct nintendo_otp_devtype_data hollywood_otp_data = { ++ .name = "wii-otp", ++ .num_banks = 1, ++}; ++ ++static const struct nintendo_otp_devtype_data latte_otp_data = { ++ .name = "wiiu-otp", ++ .num_banks = 8, ++}; ++ ++static int nintendo_otp_reg_read(void *context, ++ unsigned int reg, void *_val, size_t bytes) ++{ ++ struct nintendo_otp_priv *priv = context; ++ u32 *val = _val; ++ int words = bytes / WORD_SIZE; ++ u32 bank, addr; ++ ++ while (words--) { ++ bank = (reg / BANK_SIZE) << 8; ++ addr = (reg / WORD_SIZE) % (BANK_SIZE / WORD_SIZE); ++ iowrite32be(OTP_READ | bank | addr, priv->regs + HW_OTPCMD); ++ *val++ = ioread32be(priv->regs + HW_OTPDATA); ++ reg += WORD_SIZE; ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id nintendo_otp_of_table[] = { ++ { .compatible = "nintendo,hollywood-otp", .data = &hollywood_otp_data }, ++ { .compatible = "nintendo,latte-otp", .data = &latte_otp_data }, ++ {/* sentinel */}, ++}; ++MODULE_DEVICE_TABLE(of, nintendo_otp_of_table); ++ ++static int nintendo_otp_probe(struct platform_device *pdev) ++{ ++ 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; ++ ++ struct nvmem_config config = { ++ .stride = WORD_SIZE, ++ .word_size = WORD_SIZE, ++ .reg_read = nintendo_otp_reg_read, ++ .read_only = true, ++ .root_only = true, ++ }; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ priv->regs = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->regs)) ++ return PTR_ERR(priv->regs); ++ ++ if (of_id->data) { ++ const struct nintendo_otp_devtype_data *data = of_id->data; ++ config.name = data->name; ++ config.size = data->num_banks * BANK_SIZE; ++ } ++ ++ config.dev = dev; ++ config.priv = priv; ++ ++ nvmem = devm_nvmem_register(dev, &config); ++ ++ return PTR_ERR_OR_ZERO(nvmem); ++} ++ ++static struct platform_driver nintendo_otp_driver = { ++ .probe = nintendo_otp_probe, ++ .driver = { ++ .name = "nintendo-otp", ++ .of_match_table = nintendo_otp_of_table, ++ }, ++}; ++module_platform_driver(nintendo_otp_driver); ++MODULE_AUTHOR("Emmanuel Gil Peyrot "); ++MODULE_DESCRIPTION("Nintendo Wii and Wii U OTP driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/generic/backport-5.10/805-v5.15-0005-nvmem-NVMEM_NINTENDO_OTP-should-depend-on-WII.patch b/target/linux/generic/backport-5.10/805-v5.15-0005-nvmem-NVMEM_NINTENDO_OTP-should-depend-on-WII.patch new file mode 100644 index 0000000000..02f8b6c562 --- /dev/null +++ b/target/linux/generic/backport-5.10/805-v5.15-0005-nvmem-NVMEM_NINTENDO_OTP-should-depend-on-WII.patch @@ -0,0 +1,29 @@ +From 7af526c740bdbd5b4dcebba04ace5b3b0c07801f Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Tue, 14 Sep 2021 11:29:49 +0200 +Subject: [PATCH] nvmem: NVMEM_NINTENDO_OTP should depend on WII + +The Nintendo Wii and Wii U OTP is only present on Nintendo Wii and Wii U +consoles. Hence add a dependency on WII, to prevent asking the user +about this driver when configuring a kernel without Nintendo Wii and Wii +U console support. + +Fixes: 3683b761fe3a10ad ("nvmem: nintendo-otp: Add new driver for the Wii and Wii U OTP") +Reviewed-by: Emmanuel Gil Peyrot +Signed-off-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/01318920709dddc4d85fe895e2083ca0eee234d8.1631611652.git.geert+renesas@glider.be +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -109,6 +109,7 @@ config MTK_EFUSE + + config NVMEM_NINTENDO_OTP + tristate "Nintendo Wii and Wii U OTP Support" ++ depends on WII || COMPILE_TEST + help + This is a driver exposing the OTP of a Nintendo Wii or Wii U console. + diff --git a/target/linux/generic/backport-5.10/823-v6.1-0001-nvmem-add-driver-handling-U-Boot-environment-variabl.patch b/target/linux/generic/backport-5.10/823-v6.1-0001-nvmem-add-driver-handling-U-Boot-environment-variabl.patch new file mode 100644 index 0000000000..a40c61f929 --- /dev/null +++ b/target/linux/generic/backport-5.10/823-v6.1-0001-nvmem-add-driver-handling-U-Boot-environment-variabl.patch @@ -0,0 +1,278 @@ +From f955dc14450695564926711cf9fa8e1d5d854302 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Wed, 15 Jun 2022 21:43:00 +0200 +Subject: [PATCH] nvmem: add driver handling U-Boot environment variables +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +U-Boot stores its setup as environment variables. It's a list of +key-value pairs stored on flash device with a custom header. + +This commit adds an NVMEM driver that: +1. Provides NVMEM access to environment vars binary data +2. Extracts variables as NVMEM cells + +Current Linux's NVMEM sysfs API allows reading whole NVMEM data block. +It can be used by user-space tools for reading U-Boot env vars block +without the hassle of finding its location. Parsing will still need to +be re-done there. + +Kernel-parsed NVMEM cells can be read however by Linux drivers. This may +be useful for Ethernet drivers for reading device MAC address which is +often stored as U-Boot env variable. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Ahmad Fatoum +Signed-off-by: Srinivas Kandagatla +--- + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -300,4 +300,17 @@ config NVMEM_BRCM_NVRAM + This driver provides support for Broadcom's NVRAM that can be accessed + using I/O mapping. + ++config NVMEM_U_BOOT_ENV ++ tristate "U-Boot environment variables support" ++ depends on OF && MTD ++ select CRC32 ++ help ++ U-Boot stores its setup as environment variables. This driver adds ++ support for verifying & exporting such data. It also exposes variables ++ as NVMEM cells so they can be referenced by other drivers. ++ ++ Currently this drivers works only with env variables on top of MTD. ++ ++ If compiled as module it will be called nvmem_u-boot-env. ++ + endif +--- a/drivers/nvmem/Makefile ++++ b/drivers/nvmem/Makefile +@@ -61,3 +61,5 @@ obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem. + nvmem-rmem-y := rmem.o + obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_brcm_nvram.o + nvmem_brcm_nvram-y := brcm_nvram.o ++obj-$(CONFIG_NVMEM_U_BOOT_ENV) += nvmem_u-boot-env.o ++nvmem_u-boot-env-y := u-boot-env.o +--- /dev/null ++++ b/drivers/nvmem/u-boot-env.c +@@ -0,0 +1,218 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2022 Rafał Miłecki ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++enum u_boot_env_format { ++ U_BOOT_FORMAT_SINGLE, ++ U_BOOT_FORMAT_REDUNDANT, ++}; ++ ++struct u_boot_env { ++ struct device *dev; ++ enum u_boot_env_format format; ++ ++ struct mtd_info *mtd; ++ ++ /* Cells */ ++ struct nvmem_cell_info *cells; ++ int ncells; ++}; ++ ++struct u_boot_env_image_single { ++ __le32 crc32; ++ uint8_t data[]; ++} __packed; ++ ++struct u_boot_env_image_redundant { ++ __le32 crc32; ++ u8 mark; ++ uint8_t data[]; ++} __packed; ++ ++static int u_boot_env_read(void *context, unsigned int offset, void *val, ++ size_t bytes) ++{ ++ struct u_boot_env *priv = context; ++ struct device *dev = priv->dev; ++ size_t bytes_read; ++ int err; ++ ++ err = mtd_read(priv->mtd, offset, bytes, &bytes_read, val); ++ if (err && !mtd_is_bitflip(err)) { ++ dev_err(dev, "Failed to read from mtd: %d\n", err); ++ return err; ++ } ++ ++ if (bytes_read != bytes) { ++ dev_err(dev, "Failed to read %zu bytes\n", bytes); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, ++ size_t data_offset, size_t data_len) ++{ ++ struct device *dev = priv->dev; ++ char *data = buf + data_offset; ++ char *var, *value, *eq; ++ int idx; ++ ++ priv->ncells = 0; ++ for (var = data; var < data + data_len && *var; var += strlen(var) + 1) ++ priv->ncells++; ++ ++ priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL); ++ if (!priv->cells) ++ return -ENOMEM; ++ ++ for (var = data, idx = 0; ++ var < data + data_len && *var; ++ var = value + strlen(value) + 1, idx++) { ++ eq = strchr(var, '='); ++ if (!eq) ++ break; ++ *eq = '\0'; ++ value = eq + 1; ++ ++ priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL); ++ if (!priv->cells[idx].name) ++ return -ENOMEM; ++ priv->cells[idx].offset = data_offset + value - data; ++ priv->cells[idx].bytes = strlen(value); ++ } ++ ++ if (WARN_ON(idx != priv->ncells)) ++ priv->ncells = idx; ++ ++ return 0; ++} ++ ++static int u_boot_env_parse(struct u_boot_env *priv) ++{ ++ struct device *dev = priv->dev; ++ size_t crc32_data_offset; ++ size_t crc32_data_len; ++ size_t crc32_offset; ++ size_t data_offset; ++ size_t data_len; ++ uint32_t crc32; ++ uint32_t calc; ++ size_t bytes; ++ uint8_t *buf; ++ int err; ++ ++ buf = kcalloc(1, priv->mtd->size, GFP_KERNEL); ++ if (!buf) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ err = mtd_read(priv->mtd, 0, priv->mtd->size, &bytes, buf); ++ if ((err && !mtd_is_bitflip(err)) || bytes != priv->mtd->size) { ++ dev_err(dev, "Failed to read from mtd: %d\n", err); ++ goto err_kfree; ++ } ++ ++ switch (priv->format) { ++ case U_BOOT_FORMAT_SINGLE: ++ crc32_offset = offsetof(struct u_boot_env_image_single, crc32); ++ crc32_data_offset = offsetof(struct u_boot_env_image_single, data); ++ data_offset = offsetof(struct u_boot_env_image_single, data); ++ break; ++ case U_BOOT_FORMAT_REDUNDANT: ++ crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32); ++ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, mark); ++ data_offset = offsetof(struct u_boot_env_image_redundant, data); ++ break; ++ } ++ crc32 = le32_to_cpu(*(uint32_t *)(buf + crc32_offset)); ++ crc32_data_len = priv->mtd->size - crc32_data_offset; ++ data_len = priv->mtd->size - data_offset; ++ ++ calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; ++ if (calc != crc32) { ++ dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32); ++ err = -EINVAL; ++ goto err_kfree; ++ } ++ ++ buf[priv->mtd->size - 1] = '\0'; ++ err = u_boot_env_add_cells(priv, buf, data_offset, data_len); ++ if (err) ++ dev_err(dev, "Failed to add cells: %d\n", err); ++ ++err_kfree: ++ kfree(buf); ++err_out: ++ return err; ++} ++ ++static int u_boot_env_probe(struct platform_device *pdev) ++{ ++ struct nvmem_config config = { ++ .name = "u-boot-env", ++ .reg_read = u_boot_env_read, ++ }; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct u_boot_env *priv; ++ int err; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ priv->dev = dev; ++ ++ priv->format = (uintptr_t)of_device_get_match_data(dev); ++ ++ priv->mtd = of_get_mtd_device_by_node(np); ++ if (IS_ERR(priv->mtd)) { ++ dev_err_probe(dev, PTR_ERR(priv->mtd), "Failed to get %pOF MTD\n", np); ++ return PTR_ERR(priv->mtd); ++ } ++ ++ err = u_boot_env_parse(priv); ++ if (err) ++ return err; ++ ++ config.dev = dev; ++ config.cells = priv->cells; ++ config.ncells = priv->ncells; ++ config.priv = priv; ++ config.size = priv->mtd->size; ++ ++ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); ++} ++ ++static const struct of_device_id u_boot_env_of_match_table[] = { ++ { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, }, ++ { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, ++ { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, ++ {}, ++}; ++ ++static struct platform_driver u_boot_env_driver = { ++ .probe = u_boot_env_probe, ++ .driver = { ++ .name = "u_boot_env", ++ .of_match_table = u_boot_env_of_match_table, ++ }, ++}; ++module_platform_driver(u_boot_env_driver); ++ ++MODULE_AUTHOR("Rafał Miłecki"); ++MODULE_LICENSE("GPL"); ++MODULE_DEVICE_TABLE(of, u_boot_env_of_match_table); diff --git a/target/linux/generic/backport-5.10/823-v6.1-0002-nvmem-u-boot-env-find-Device-Tree-nodes-for-NVMEM-ce.patch b/target/linux/generic/backport-5.10/823-v6.1-0002-nvmem-u-boot-env-find-Device-Tree-nodes-for-NVMEM-ce.patch new file mode 100644 index 0000000000..3a6b76a221 --- /dev/null +++ b/target/linux/generic/backport-5.10/823-v6.1-0002-nvmem-u-boot-env-find-Device-Tree-nodes-for-NVMEM-ce.patch @@ -0,0 +1,29 @@ +From d69efcf951df4dcc74a0e1554969c533aec8aa9b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 15 Sep 2022 22:06:29 +0200 +Subject: [PATCH] nvmem: u-boot-env: find Device Tree nodes for NVMEM cells +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +DT binding allows specifying NVMEM cells as NVMEM device (provider) +subnodes. Looks for such subnodes when building NVMEM cells. + +This allows NVMEM consumers to use U-Boot environment variables. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/u-boot-env.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -92,6 +92,7 @@ static int u_boot_env_add_cells(struct u + return -ENOMEM; + priv->cells[idx].offset = data_offset + value - data; + priv->cells[idx].bytes = strlen(value); ++ priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); + } + + if (WARN_ON(idx != priv->ncells)) diff --git a/target/linux/generic/backport-5.10/823-v6.1-0003-nvmem-u-boot-env-fix-crc32-casting-type.patch b/target/linux/generic/backport-5.10/823-v6.1-0003-nvmem-u-boot-env-fix-crc32-casting-type.patch new file mode 100644 index 0000000000..6b40557116 --- /dev/null +++ b/target/linux/generic/backport-5.10/823-v6.1-0003-nvmem-u-boot-env-fix-crc32-casting-type.patch @@ -0,0 +1,30 @@ +From 60bbaad38109684b156e21112322e0a922f92cde Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 18 Aug 2022 06:38:37 +0200 +Subject: [PATCH] nvmem: u-boot-env: fix crc32 casting type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This fixes: +drivers/nvmem/u-boot-env.c:141:17: sparse: sparse: cast to restricted __le32 + +Reported-by: kernel test robot +Fixes: f955dc1445069 ("nvmem: add driver handling U-Boot environment variables") +Signed-off-by: Rafał Miłecki +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/u-boot-env.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -139,7 +139,7 @@ static int u_boot_env_parse(struct u_boo + data_offset = offsetof(struct u_boot_env_image_redundant, data); + break; + } +- crc32 = le32_to_cpu(*(uint32_t *)(buf + crc32_offset)); ++ crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); + crc32_data_len = priv->mtd->size - crc32_data_offset; + data_len = priv->mtd->size - data_offset; + diff --git a/target/linux/generic/backport-5.10/824-v5.19-nvmem-core-support-passing-DT-node-in-cell-info.patch b/target/linux/generic/backport-5.10/824-v5.19-nvmem-core-support-passing-DT-node-in-cell-info.patch new file mode 100644 index 0000000000..1acc6947fe --- /dev/null +++ b/target/linux/generic/backport-5.10/824-v5.19-nvmem-core-support-passing-DT-node-in-cell-info.patch @@ -0,0 +1,41 @@ +From dbc2f62061c6bfba0aee93161ee3194dcee84bd0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 29 Apr 2022 17:26:46 +0100 +Subject: [PATCH] nvmem: core: support passing DT node in cell info +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some hardware may have NVMEM cells described in Device Tree using +individual nodes. Let drivers pass such nodes to the NVMEM subsystem so +they can be later used by NVMEM consumers. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20220429162701.2222-2-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 1 + + include/linux/nvmem-consumer.h | 1 + + 2 files changed, 2 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -462,6 +462,7 @@ static int nvmem_cell_info_to_nvmem_cell + + cell->bit_offset = info->bit_offset; + cell->nbits = info->nbits; ++ cell->np = info->np; + + if (cell->nbits) + cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset, +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -25,6 +25,7 @@ struct nvmem_cell_info { + unsigned int bytes; + unsigned int bit_offset; + unsigned int nbits; ++ struct device_node *np; + }; + + /** diff --git a/target/linux/generic/backport-5.10/825-v6.2-0001-nvmem-u-boot-env-fix-crc32_data_offset-on-redundant-.patch b/target/linux/generic/backport-5.10/825-v6.2-0001-nvmem-u-boot-env-fix-crc32_data_offset-on-redundant-.patch new file mode 100644 index 0000000000..69d5a1b845 --- /dev/null +++ b/target/linux/generic/backport-5.10/825-v6.2-0001-nvmem-u-boot-env-fix-crc32_data_offset-on-redundant-.patch @@ -0,0 +1,56 @@ +From 7a69ff9c9bde03a690ea783970f664782fc303d8 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Fri, 4 Nov 2022 17:52:03 +0100 +Subject: [PATCH] nvmem: u-boot-env: fix crc32_data_offset on redundant + u-boot-env + +The Western Digital MyBook Live (PowerPC 464/APM82181) +has a set of redundant u-boot-env. Loading up the driver +the following error: + +| u_boot_env: Invalid calculated CRC32: 0x4f8f2c86 (expected: 0x98b14514) +| u_boot_env: probe of partition@1e000 failed with error -22 + +Looking up the userspace libubootenv utilities source [0], +it looks like the "mark" or "flag" is not part of the +crc32 sum... which is unfortunate :( + +|static int libuboot_load(struct uboot_ctx *ctx) +|{ +|[...] +| if (ctx->redundant) { +| [...] +| offsetdata = offsetof(struct uboot_env_redund, data); +| [...] //-----^^ +| } +| usable_envsize = ctx->size - offsetdata; +| buf[0] = malloc(bufsize); +|[...] +| for (i = 0; i < copies; i++) { +| data = (uint8_t *)(buf[i] + offsetdata); +| uint32_t crc; +| +| ret = devread(ctx, i, buf[i]); +| [...] +| crc = *(uint32_t *)(buf[i] + offsetcrc); +| dev->crc = crc32(0, (uint8_t *)data, usable_envsize); +| + +[0] https://github.com/sbabic/libubootenv/blob/master/src/uboot_env.c#L951 +Fixes: d5542923f200 ("nvmem: add driver handling U-Boot environment variables") +Signed-off-by: Christian Lamparter +--- + drivers/nvmem/u-boot-env.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -135,7 +135,7 @@ static int u_boot_env_parse(struct u_boo + break; + case U_BOOT_FORMAT_REDUNDANT: + crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32); +- crc32_data_offset = offsetof(struct u_boot_env_image_redundant, mark); ++ crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); + data_offset = offsetof(struct u_boot_env_image_redundant, data); + break; + } diff --git a/target/linux/generic/backport-5.10/825-v6.2-0002-nvmem-u-boot-env-align-endianness-of-crc32-values.patch b/target/linux/generic/backport-5.10/825-v6.2-0002-nvmem-u-boot-env-align-endianness-of-crc32-values.patch new file mode 100644 index 0000000000..7d6723bb8e --- /dev/null +++ b/target/linux/generic/backport-5.10/825-v6.2-0002-nvmem-u-boot-env-align-endianness-of-crc32-values.patch @@ -0,0 +1,47 @@ +From 0e71cac033bb7689c4dfa2e6814191337ef770f5 Mon Sep 17 00:00:00 2001 +From: INAGAKI Hiroshi +Date: Thu, 13 Oct 2022 00:51:33 +0900 +Subject: [PATCH] nvmem: u-boot-env: align endianness of crc32 values +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch fixes crc32 error on Big-Endianness system by conversion of +calculated crc32 value. + +Little-Endianness system: + + obtained crc32: Little +calculated crc32: Little + +Big-Endianness system: + + obtained crc32: Little +calculated crc32: Big + +log (APRESIA ApresiaLightGS120GT-SS, RTL8382M, Big-Endianness): + +[ 8.570000] u_boot_env 18001200.spi:flash@0:partitions:partition@c0000: Invalid calculated CRC32: 0x88cd6f09 (expected: 0x096fcd88) +[ 8.580000] u_boot_env: probe of 18001200.spi:flash@0:partitions:partition@c0000 failed with error -22 + +Fixes: f955dc1445069 ("nvmem: add driver handling U-Boot environment variables") + +Signed-off-by: INAGAKI Hiroshi +Acked-by: Rafał Miłecki +Tested-by: Christian Lamparter +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/u-boot-env.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -143,7 +143,7 @@ static int u_boot_env_parse(struct u_boo + crc32_data_len = priv->mtd->size - crc32_data_offset; + data_len = priv->mtd->size - data_offset; + +- calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; ++ calc = le32_to_cpu((__le32)crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L); + if (calc != crc32) { + dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32); + err = -EINVAL; diff --git a/target/linux/generic/backport-5.10/825-v6.2-0003-nvmem-u-boot-env-add-Broadcom-format-support.patch b/target/linux/generic/backport-5.10/825-v6.2-0003-nvmem-u-boot-env-add-Broadcom-format-support.patch new file mode 100644 index 0000000000..429b24f0f3 --- /dev/null +++ b/target/linux/generic/backport-5.10/825-v6.2-0003-nvmem-u-boot-env-add-Broadcom-format-support.patch @@ -0,0 +1,65 @@ +From 5b4eaafbeac472fc19049152f18e88aecb2b2829 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 17 Oct 2022 09:17:22 +0200 +Subject: [PATCH] nvmem: u-boot-env: add Broadcom format support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Broadcom uses U-Boot for a lot of their bcmbca familiy chipsets. They +decided to store U-Boot environment data inside U-Boot partition and to +use a custom header (with "uEnv" magic and env data length). + +Add support for Broadcom's specific binding and their custom format. + +Ref: 6b0584c19d87 ("dt-bindings: nvmem: u-boot,env: add Broadcom's variant binding") +Signed-off-by: Rafał Miłecki +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/u-boot-env.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -16,6 +16,7 @@ + enum u_boot_env_format { + U_BOOT_FORMAT_SINGLE, + U_BOOT_FORMAT_REDUNDANT, ++ U_BOOT_FORMAT_BROADCOM, + }; + + struct u_boot_env { +@@ -40,6 +41,13 @@ struct u_boot_env_image_redundant { + uint8_t data[]; + } __packed; + ++struct u_boot_env_image_broadcom { ++ __le32 magic; ++ __le32 len; ++ __le32 crc32; ++ uint8_t data[0]; ++} __packed; ++ + static int u_boot_env_read(void *context, unsigned int offset, void *val, + size_t bytes) + { +@@ -138,6 +146,11 @@ static int u_boot_env_parse(struct u_boo + crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); + data_offset = offsetof(struct u_boot_env_image_redundant, data); + break; ++ case U_BOOT_FORMAT_BROADCOM: ++ crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32); ++ crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data); ++ data_offset = offsetof(struct u_boot_env_image_broadcom, data); ++ break; + } + crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); + crc32_data_len = priv->mtd->size - crc32_data_offset; +@@ -202,6 +215,7 @@ static const struct of_device_id u_boot_ + { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, }, + { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, + { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, ++ { .compatible = "brcm,env", .data = (void *)U_BOOT_FORMAT_BROADCOM, }, + {}, + }; + diff --git a/target/linux/generic/config-5.10 b/target/linux/generic/config-5.10 index a2dc9b90b1..01bebbbab4 100644 --- a/target/linux/generic/config-5.10 +++ b/target/linux/generic/config-5.10 @@ -4244,6 +4244,7 @@ CONFIG_NMI_LOG_BUF_SHIFT=13 # CONFIG_NVMEM_BCM_OCOTP is not set # CONFIG_NVMEM_IMX_OCOTP is not set # CONFIG_NVMEM_REBOOT_MODE is not set +# CONFIG_NVMEM_RMEM is not set # CONFIG_NVMEM_SYSFS is not set # CONFIG_NVMEM_U_BOOT_ENV is not set # CONFIG_NVME_FC is not set