From: Rafał Miłecki Date: Tue, 10 Sep 2024 11:42:55 +0000 (+0200) Subject: kernel: backport nvmem changes from v6.9 X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=944dfb1ed6556cc0d7c3d2de46b31daf6b533674;p=openwrt%2Fstaging%2Fxback.git kernel: backport nvmem changes from v6.9 Signed-off-by: Rafał Miłecki --- diff --git a/target/linux/generic/backport-5.15/836-v6.9-0002-nvmem-mtk-efuse-Register-MediaTek-socinfo-driver-fro.patch b/target/linux/generic/backport-5.15/836-v6.9-0002-nvmem-mtk-efuse-Register-MediaTek-socinfo-driver-fro.patch new file mode 100644 index 0000000000..8e7c8233e2 --- /dev/null +++ b/target/linux/generic/backport-5.15/836-v6.9-0002-nvmem-mtk-efuse-Register-MediaTek-socinfo-driver-fro.patch @@ -0,0 +1,69 @@ +From 998f0633773b3432829fe45d2cd2ffb842f3c78e Mon Sep 17 00:00:00 2001 +From: William-tw Lin +Date: Sat, 24 Feb 2024 11:45:07 +0000 +Subject: [PATCH] nvmem: mtk-efuse: Register MediaTek socinfo driver from efuse + +The socinfo driver reads chip information from eFuses and does not need +any devicetree node. Register it from mtk-efuse. + +While at it, also add the name for this driver's nvmem_config. + +Signed-off-by: William-tw Lin +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/mtk-efuse.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +--- a/drivers/nvmem/mtk-efuse.c ++++ b/drivers/nvmem/mtk-efuse.c +@@ -68,6 +68,7 @@ static int mtk_efuse_probe(struct platfo + struct nvmem_config econfig = {}; + struct mtk_efuse_priv *priv; + const struct mtk_efuse_pdata *pdata; ++ struct platform_device *socinfo; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -85,11 +86,20 @@ static int mtk_efuse_probe(struct platfo + econfig.size = resource_size(res); + econfig.priv = priv; + econfig.dev = dev; ++ econfig.name = "mtk-efuse"; + if (pdata->uses_post_processing) + econfig.fixup_dt_cell_info = &mtk_efuse_fixup_dt_cell_info; + nvmem = devm_nvmem_register(dev, &econfig); ++ if (IS_ERR(nvmem)) ++ return PTR_ERR(nvmem); + +- return PTR_ERR_OR_ZERO(nvmem); ++ socinfo = platform_device_register_data(&pdev->dev, "mtk-socinfo", ++ PLATFORM_DEVID_AUTO, NULL, 0); ++ if (IS_ERR(socinfo)) ++ dev_info(dev, "MediaTek SoC Information will be unavailable\n"); ++ ++ platform_set_drvdata(pdev, socinfo); ++ return 0; + } + + static const struct mtk_efuse_pdata mtk_mt8186_efuse_pdata = { +@@ -108,8 +118,17 @@ static const struct of_device_id mtk_efu + }; + MODULE_DEVICE_TABLE(of, mtk_efuse_of_match); + ++static void mtk_efuse_remove(struct platform_device *pdev) ++{ ++ struct platform_device *socinfo = platform_get_drvdata(pdev); ++ ++ if (!IS_ERR_OR_NULL(socinfo)) ++ platform_device_unregister(socinfo); ++} ++ + static struct platform_driver mtk_efuse_driver = { + .probe = mtk_efuse_probe, ++ .remove_new = mtk_efuse_remove, + .driver = { + .name = "mediatek,efuse", + .of_match_table = mtk_efuse_of_match, diff --git a/target/linux/generic/backport-5.15/836-v6.9-0003-nvmem-zynqmp_nvmem-zynqmp_nvmem_probe-cleanup.patch b/target/linux/generic/backport-5.15/836-v6.9-0003-nvmem-zynqmp_nvmem-zynqmp_nvmem_probe-cleanup.patch new file mode 100644 index 0000000000..0f90e548a2 --- /dev/null +++ b/target/linux/generic/backport-5.15/836-v6.9-0003-nvmem-zynqmp_nvmem-zynqmp_nvmem_probe-cleanup.patch @@ -0,0 +1,97 @@ +From 29be47fcd6a06ea2e79eeeca6e69ad1e23254a69 Mon Sep 17 00:00:00 2001 +From: Praveen Teja Kundanala +Date: Sat, 24 Feb 2024 11:45:11 +0000 +Subject: [PATCH] nvmem: zynqmp_nvmem: zynqmp_nvmem_probe cleanup + +- Remove static nvmem_config declaration +- Remove zynqmp_nvmem_data + +Signed-off-by: Praveen Teja Kundanala +Acked-by: Kalyani Akula +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-7-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/zynqmp_nvmem.c | 37 ++++++++++++------------------------ + 1 file changed, 12 insertions(+), 25 deletions(-) + +--- a/drivers/nvmem/zynqmp_nvmem.c ++++ b/drivers/nvmem/zynqmp_nvmem.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0+ + /* + * Copyright (C) 2019 Xilinx, Inc. ++ * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc. + */ + + #include +@@ -11,36 +12,25 @@ + + #define SILICON_REVISION_MASK 0xF + +-struct zynqmp_nvmem_data { +- struct device *dev; +- struct nvmem_device *nvmem; +-}; + + static int zynqmp_nvmem_read(void *context, unsigned int offset, + void *val, size_t bytes) + { ++ struct device *dev = context; + int ret; +- int idcode, version; +- struct zynqmp_nvmem_data *priv = context; ++ int idcode; ++ int version; + + ret = zynqmp_pm_get_chipid(&idcode, &version); + if (ret < 0) + return ret; + +- dev_dbg(priv->dev, "Read chipid val %x %x\n", idcode, version); ++ dev_dbg(dev, "Read chipid val %x %x\n", idcode, version); + *(int *)val = version & SILICON_REVISION_MASK; + + return 0; + } + +-static struct nvmem_config econfig = { +- .name = "zynqmp-nvmem", +- .owner = THIS_MODULE, +- .word_size = 1, +- .size = 1, +- .read_only = true, +-}; +- + static const struct of_device_id zynqmp_nvmem_match[] = { + { .compatible = "xlnx,zynqmp-nvmem-fw", }, + { /* sentinel */ }, +@@ -50,21 +40,18 @@ MODULE_DEVICE_TABLE(of, zynqmp_nvmem_mat + static int zynqmp_nvmem_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- struct zynqmp_nvmem_data *priv; ++ struct nvmem_config econfig = {}; + +- priv = devm_kzalloc(dev, sizeof(struct zynqmp_nvmem_data), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- +- priv->dev = dev; ++ econfig.name = "zynqmp-nvmem"; ++ econfig.owner = THIS_MODULE; ++ econfig.word_size = 1; ++ econfig.size = 1; + econfig.dev = dev; + econfig.add_legacy_fixed_of_cells = true; ++ econfig.read_only = true; + econfig.reg_read = zynqmp_nvmem_read; +- econfig.priv = priv; +- +- priv->nvmem = devm_nvmem_register(dev, &econfig); + +- return PTR_ERR_OR_ZERO(priv->nvmem); ++ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &econfig)); + } + + static struct platform_driver zynqmp_nvmem_driver = { diff --git a/target/linux/generic/backport-5.15/836-v6.9-0004-nvmem-zynqmp_nvmem-Add-support-to-access-efuse.patch b/target/linux/generic/backport-5.15/836-v6.9-0004-nvmem-zynqmp_nvmem-Add-support-to-access-efuse.patch new file mode 100644 index 0000000000..39c2f17835 --- /dev/null +++ b/target/linux/generic/backport-5.15/836-v6.9-0004-nvmem-zynqmp_nvmem-Add-support-to-access-efuse.patch @@ -0,0 +1,243 @@ +From 737c0c8d07b5f671c0a33cec95965fcb2d2ea893 Mon Sep 17 00:00:00 2001 +From: Praveen Teja Kundanala +Date: Sat, 24 Feb 2024 11:45:12 +0000 +Subject: [PATCH] nvmem: zynqmp_nvmem: Add support to access efuse + +Add support to read/write efuse memory map of ZynqMP. +Below are the offsets of ZynqMP efuse memory map + 0 - SOC version(read only) + 0xC - 0xFC -ZynqMP specific purpose efuses + 0x100 - 0x17F - Physical Unclonable Function(PUF) + efuses repurposed as user efuses + +Signed-off-by: Praveen Teja Kundanala +Acked-by: Kalyani Akula +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-8-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/zynqmp_nvmem.c | 186 +++++++++++++++++++++++++++++++++-- + 1 file changed, 176 insertions(+), 10 deletions(-) + +--- a/drivers/nvmem/zynqmp_nvmem.c ++++ b/drivers/nvmem/zynqmp_nvmem.c +@@ -4,6 +4,7 @@ + * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc. + */ + ++#include + #include + #include + #include +@@ -11,24 +12,189 @@ + #include + + #define SILICON_REVISION_MASK 0xF ++#define P_USER_0_64_UPPER_MASK GENMASK(31, 16) ++#define P_USER_127_LOWER_4_BIT_MASK GENMASK(3, 0) ++#define WORD_INBYTES 4 ++#define SOC_VER_SIZE 0x4 ++#define EFUSE_MEMORY_SIZE 0x177 ++#define UNUSED_SPACE 0x8 ++#define ZYNQMP_NVMEM_SIZE (SOC_VER_SIZE + UNUSED_SPACE + \ ++ EFUSE_MEMORY_SIZE) ++#define SOC_VERSION_OFFSET 0x0 ++#define EFUSE_START_OFFSET 0xC ++#define EFUSE_END_OFFSET 0xFC ++#define EFUSE_PUF_START_OFFSET 0x100 ++#define EFUSE_PUF_MID_OFFSET 0x140 ++#define EFUSE_PUF_END_OFFSET 0x17F ++#define EFUSE_NOT_ENABLED 29 + ++/* ++ * efuse access type ++ */ ++enum efuse_access { ++ EFUSE_READ = 0, ++ EFUSE_WRITE ++}; ++ ++/** ++ * struct xilinx_efuse - the basic structure ++ * @src: address of the buffer to store the data to be write/read ++ * @size: read/write word count ++ * @offset: read/write offset ++ * @flag: 0 - represents efuse read and 1- represents efuse write ++ * @pufuserfuse:0 - represents non-puf efuses, offset is used for read/write ++ * 1 - represents puf user fuse row number. ++ * ++ * this structure stores all the required details to ++ * read/write efuse memory. ++ */ ++struct xilinx_efuse { ++ u64 src; ++ u32 size; ++ u32 offset; ++ enum efuse_access flag; ++ u32 pufuserfuse; ++}; ++ ++static int zynqmp_efuse_access(void *context, unsigned int offset, ++ void *val, size_t bytes, enum efuse_access flag, ++ unsigned int pufflag) ++{ ++ struct device *dev = context; ++ struct xilinx_efuse *efuse; ++ dma_addr_t dma_addr; ++ dma_addr_t dma_buf; ++ size_t words = bytes / WORD_INBYTES; ++ int ret; ++ int value; ++ char *data; + +-static int zynqmp_nvmem_read(void *context, unsigned int offset, +- void *val, size_t bytes) ++ if (bytes % WORD_INBYTES != 0) { ++ dev_err(dev, "Bytes requested should be word aligned\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (pufflag == 0 && offset % WORD_INBYTES) { ++ dev_err(dev, "Offset requested should be word aligned\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (pufflag == 1 && flag == EFUSE_WRITE) { ++ memcpy(&value, val, bytes); ++ if ((offset == EFUSE_PUF_START_OFFSET || ++ offset == EFUSE_PUF_MID_OFFSET) && ++ value & P_USER_0_64_UPPER_MASK) { ++ dev_err(dev, "Only lower 4 bytes are allowed to be programmed in P_USER_0 & P_USER_64\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (offset == EFUSE_PUF_END_OFFSET && ++ (value & P_USER_127_LOWER_4_BIT_MASK)) { ++ dev_err(dev, "Only MSB 28 bits are allowed to be programmed for P_USER_127\n"); ++ return -EOPNOTSUPP; ++ } ++ } ++ ++ efuse = dma_alloc_coherent(dev, sizeof(struct xilinx_efuse), ++ &dma_addr, GFP_KERNEL); ++ if (!efuse) ++ return -ENOMEM; ++ ++ data = dma_alloc_coherent(dev, sizeof(bytes), ++ &dma_buf, GFP_KERNEL); ++ if (!data) { ++ ret = -ENOMEM; ++ goto efuse_data_fail; ++ } ++ ++ if (flag == EFUSE_WRITE) { ++ memcpy(data, val, bytes); ++ efuse->flag = EFUSE_WRITE; ++ } else { ++ efuse->flag = EFUSE_READ; ++ } ++ ++ efuse->src = dma_buf; ++ efuse->size = words; ++ efuse->offset = offset; ++ efuse->pufuserfuse = pufflag; ++ ++ zynqmp_pm_efuse_access(dma_addr, (u32 *)&ret); ++ if (ret != 0) { ++ if (ret == EFUSE_NOT_ENABLED) { ++ dev_err(dev, "efuse access is not enabled\n"); ++ ret = -EOPNOTSUPP; ++ } else { ++ dev_err(dev, "Error in efuse read %x\n", ret); ++ ret = -EPERM; ++ } ++ goto efuse_access_err; ++ } ++ ++ if (flag == EFUSE_READ) ++ memcpy(val, data, bytes); ++efuse_access_err: ++ dma_free_coherent(dev, sizeof(bytes), ++ data, dma_buf); ++efuse_data_fail: ++ dma_free_coherent(dev, sizeof(struct xilinx_efuse), ++ efuse, dma_addr); ++ ++ return ret; ++} ++ ++static int zynqmp_nvmem_read(void *context, unsigned int offset, void *val, size_t bytes) + { + struct device *dev = context; + int ret; ++ int pufflag = 0; + int idcode; + int version; + +- ret = zynqmp_pm_get_chipid(&idcode, &version); +- if (ret < 0) +- return ret; ++ if (offset >= EFUSE_PUF_START_OFFSET && offset <= EFUSE_PUF_END_OFFSET) ++ pufflag = 1; ++ ++ switch (offset) { ++ /* Soc version offset is zero */ ++ case SOC_VERSION_OFFSET: ++ if (bytes != SOC_VER_SIZE) ++ return -EOPNOTSUPP; ++ ++ ret = zynqmp_pm_get_chipid((u32 *)&idcode, (u32 *)&version); ++ if (ret < 0) ++ return ret; ++ ++ dev_dbg(dev, "Read chipid val %x %x\n", idcode, version); ++ *(int *)val = version & SILICON_REVISION_MASK; ++ break; ++ /* Efuse offset starts from 0xc */ ++ case EFUSE_START_OFFSET ... EFUSE_END_OFFSET: ++ case EFUSE_PUF_START_OFFSET ... EFUSE_PUF_END_OFFSET: ++ ret = zynqmp_efuse_access(context, offset, val, ++ bytes, EFUSE_READ, pufflag); ++ break; ++ default: ++ *(u32 *)val = 0xDEADBEEF; ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static int zynqmp_nvmem_write(void *context, ++ unsigned int offset, void *val, size_t bytes) ++{ ++ int pufflag = 0; ++ ++ if (offset < EFUSE_START_OFFSET || offset > EFUSE_PUF_END_OFFSET) ++ return -EOPNOTSUPP; + +- dev_dbg(dev, "Read chipid val %x %x\n", idcode, version); +- *(int *)val = version & SILICON_REVISION_MASK; ++ if (offset >= EFUSE_PUF_START_OFFSET && offset <= EFUSE_PUF_END_OFFSET) ++ pufflag = 1; + +- return 0; ++ return zynqmp_efuse_access(context, offset, ++ val, bytes, EFUSE_WRITE, pufflag); + } + + static const struct of_device_id zynqmp_nvmem_match[] = { +@@ -45,11 +211,11 @@ static int zynqmp_nvmem_probe(struct pla + econfig.name = "zynqmp-nvmem"; + econfig.owner = THIS_MODULE; + econfig.word_size = 1; +- econfig.size = 1; ++ econfig.size = ZYNQMP_NVMEM_SIZE; + econfig.dev = dev; + econfig.add_legacy_fixed_of_cells = true; +- econfig.read_only = true; + econfig.reg_read = zynqmp_nvmem_read; ++ econfig.reg_write = zynqmp_nvmem_write; + + return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &econfig)); + } diff --git a/target/linux/generic/backport-5.15/836-v6.9-0005-nvmem-mtk-efuse-Drop-NVMEM-device-name.patch b/target/linux/generic/backport-5.15/836-v6.9-0005-nvmem-mtk-efuse-Drop-NVMEM-device-name.patch new file mode 100644 index 0000000000..c67399cb13 --- /dev/null +++ b/target/linux/generic/backport-5.15/836-v6.9-0005-nvmem-mtk-efuse-Drop-NVMEM-device-name.patch @@ -0,0 +1,35 @@ +From 76c345edef754b16cab81ad9452cc49c09e67066 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Sat, 24 Feb 2024 11:45:14 +0000 +Subject: [PATCH] nvmem: mtk-efuse: Drop NVMEM device name +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The MT8183 has not one but two efuse devices. The static name and ID +causes the second efuse device to fail to probe, due to duplicate sysfs +entries. + +With the rework of the mtk-socinfo driver, lookup by name is no longer +necessary. The custom name can simply be dropped. + +Signed-off-by: Chen-Yu Tsai +Reviewed-by: AngeloGioacchino Del Regno +Tested-by: "Nícolas F. R. A. Prado" +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-10-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/mtk-efuse.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/nvmem/mtk-efuse.c ++++ b/drivers/nvmem/mtk-efuse.c +@@ -86,7 +86,6 @@ static int mtk_efuse_probe(struct platfo + econfig.size = resource_size(res); + econfig.priv = priv; + econfig.dev = dev; +- econfig.name = "mtk-efuse"; + if (pdata->uses_post_processing) + econfig.fixup_dt_cell_info = &mtk_efuse_fixup_dt_cell_info; + nvmem = devm_nvmem_register(dev, &econfig); diff --git a/target/linux/generic/backport-5.15/836-v6.9-0007-nvmem-core-Print-error-on-wrong-bits-DT-property.patch b/target/linux/generic/backport-5.15/836-v6.9-0007-nvmem-core-Print-error-on-wrong-bits-DT-property.patch new file mode 100644 index 0000000000..47787d9ad2 --- /dev/null +++ b/target/linux/generic/backport-5.15/836-v6.9-0007-nvmem-core-Print-error-on-wrong-bits-DT-property.patch @@ -0,0 +1,32 @@ +From def3173d4f17b37cecbd74d7c269a080b0b01598 Mon Sep 17 00:00:00 2001 +From: Markus Schneider-Pargmann +Date: Sat, 24 Feb 2024 11:45:16 +0000 +Subject: [PATCH] nvmem: core: Print error on wrong bits DT property + +The algorithms in nvmem core are built with the constraint that +bit_offset < 8. If bit_offset is greater the results are wrong. Print an +error if the devicetree 'bits' property is outside of the valid range +and abort parsing. + +Signed-off-by: Markus Schneider-Pargmann +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-12-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -807,6 +807,11 @@ static int nvmem_add_cells_from_dt(struc + if (addr && len == (2 * sizeof(u32))) { + info.bit_offset = be32_to_cpup(addr++); + info.nbits = be32_to_cpup(addr); ++ if (info.bit_offset >= BITS_PER_BYTE || info.nbits < 1) { ++ dev_err(dev, "nvmem: invalid bits on %pOF\n", child); ++ of_node_put(child); ++ return -EINVAL; ++ } + } + + info.np = of_node_get(child); diff --git a/target/linux/generic/backport-6.1/823-v6.9-0002-nvmem-mtk-efuse-Register-MediaTek-socinfo-driver-fro.patch b/target/linux/generic/backport-6.1/823-v6.9-0002-nvmem-mtk-efuse-Register-MediaTek-socinfo-driver-fro.patch new file mode 100644 index 0000000000..8e7c8233e2 --- /dev/null +++ b/target/linux/generic/backport-6.1/823-v6.9-0002-nvmem-mtk-efuse-Register-MediaTek-socinfo-driver-fro.patch @@ -0,0 +1,69 @@ +From 998f0633773b3432829fe45d2cd2ffb842f3c78e Mon Sep 17 00:00:00 2001 +From: William-tw Lin +Date: Sat, 24 Feb 2024 11:45:07 +0000 +Subject: [PATCH] nvmem: mtk-efuse: Register MediaTek socinfo driver from efuse + +The socinfo driver reads chip information from eFuses and does not need +any devicetree node. Register it from mtk-efuse. + +While at it, also add the name for this driver's nvmem_config. + +Signed-off-by: William-tw Lin +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/mtk-efuse.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +--- a/drivers/nvmem/mtk-efuse.c ++++ b/drivers/nvmem/mtk-efuse.c +@@ -68,6 +68,7 @@ static int mtk_efuse_probe(struct platfo + struct nvmem_config econfig = {}; + struct mtk_efuse_priv *priv; + const struct mtk_efuse_pdata *pdata; ++ struct platform_device *socinfo; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -85,11 +86,20 @@ static int mtk_efuse_probe(struct platfo + econfig.size = resource_size(res); + econfig.priv = priv; + econfig.dev = dev; ++ econfig.name = "mtk-efuse"; + if (pdata->uses_post_processing) + econfig.fixup_dt_cell_info = &mtk_efuse_fixup_dt_cell_info; + nvmem = devm_nvmem_register(dev, &econfig); ++ if (IS_ERR(nvmem)) ++ return PTR_ERR(nvmem); + +- return PTR_ERR_OR_ZERO(nvmem); ++ socinfo = platform_device_register_data(&pdev->dev, "mtk-socinfo", ++ PLATFORM_DEVID_AUTO, NULL, 0); ++ if (IS_ERR(socinfo)) ++ dev_info(dev, "MediaTek SoC Information will be unavailable\n"); ++ ++ platform_set_drvdata(pdev, socinfo); ++ return 0; + } + + static const struct mtk_efuse_pdata mtk_mt8186_efuse_pdata = { +@@ -108,8 +118,17 @@ static const struct of_device_id mtk_efu + }; + MODULE_DEVICE_TABLE(of, mtk_efuse_of_match); + ++static void mtk_efuse_remove(struct platform_device *pdev) ++{ ++ struct platform_device *socinfo = platform_get_drvdata(pdev); ++ ++ if (!IS_ERR_OR_NULL(socinfo)) ++ platform_device_unregister(socinfo); ++} ++ + static struct platform_driver mtk_efuse_driver = { + .probe = mtk_efuse_probe, ++ .remove_new = mtk_efuse_remove, + .driver = { + .name = "mediatek,efuse", + .of_match_table = mtk_efuse_of_match, diff --git a/target/linux/generic/backport-6.1/823-v6.9-0003-nvmem-zynqmp_nvmem-zynqmp_nvmem_probe-cleanup.patch b/target/linux/generic/backport-6.1/823-v6.9-0003-nvmem-zynqmp_nvmem-zynqmp_nvmem_probe-cleanup.patch new file mode 100644 index 0000000000..0f90e548a2 --- /dev/null +++ b/target/linux/generic/backport-6.1/823-v6.9-0003-nvmem-zynqmp_nvmem-zynqmp_nvmem_probe-cleanup.patch @@ -0,0 +1,97 @@ +From 29be47fcd6a06ea2e79eeeca6e69ad1e23254a69 Mon Sep 17 00:00:00 2001 +From: Praveen Teja Kundanala +Date: Sat, 24 Feb 2024 11:45:11 +0000 +Subject: [PATCH] nvmem: zynqmp_nvmem: zynqmp_nvmem_probe cleanup + +- Remove static nvmem_config declaration +- Remove zynqmp_nvmem_data + +Signed-off-by: Praveen Teja Kundanala +Acked-by: Kalyani Akula +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-7-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/zynqmp_nvmem.c | 37 ++++++++++++------------------------ + 1 file changed, 12 insertions(+), 25 deletions(-) + +--- a/drivers/nvmem/zynqmp_nvmem.c ++++ b/drivers/nvmem/zynqmp_nvmem.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0+ + /* + * Copyright (C) 2019 Xilinx, Inc. ++ * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc. + */ + + #include +@@ -11,36 +12,25 @@ + + #define SILICON_REVISION_MASK 0xF + +-struct zynqmp_nvmem_data { +- struct device *dev; +- struct nvmem_device *nvmem; +-}; + + static int zynqmp_nvmem_read(void *context, unsigned int offset, + void *val, size_t bytes) + { ++ struct device *dev = context; + int ret; +- int idcode, version; +- struct zynqmp_nvmem_data *priv = context; ++ int idcode; ++ int version; + + ret = zynqmp_pm_get_chipid(&idcode, &version); + if (ret < 0) + return ret; + +- dev_dbg(priv->dev, "Read chipid val %x %x\n", idcode, version); ++ dev_dbg(dev, "Read chipid val %x %x\n", idcode, version); + *(int *)val = version & SILICON_REVISION_MASK; + + return 0; + } + +-static struct nvmem_config econfig = { +- .name = "zynqmp-nvmem", +- .owner = THIS_MODULE, +- .word_size = 1, +- .size = 1, +- .read_only = true, +-}; +- + static const struct of_device_id zynqmp_nvmem_match[] = { + { .compatible = "xlnx,zynqmp-nvmem-fw", }, + { /* sentinel */ }, +@@ -50,21 +40,18 @@ MODULE_DEVICE_TABLE(of, zynqmp_nvmem_mat + static int zynqmp_nvmem_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- struct zynqmp_nvmem_data *priv; ++ struct nvmem_config econfig = {}; + +- priv = devm_kzalloc(dev, sizeof(struct zynqmp_nvmem_data), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- +- priv->dev = dev; ++ econfig.name = "zynqmp-nvmem"; ++ econfig.owner = THIS_MODULE; ++ econfig.word_size = 1; ++ econfig.size = 1; + econfig.dev = dev; + econfig.add_legacy_fixed_of_cells = true; ++ econfig.read_only = true; + econfig.reg_read = zynqmp_nvmem_read; +- econfig.priv = priv; +- +- priv->nvmem = devm_nvmem_register(dev, &econfig); + +- return PTR_ERR_OR_ZERO(priv->nvmem); ++ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &econfig)); + } + + static struct platform_driver zynqmp_nvmem_driver = { diff --git a/target/linux/generic/backport-6.1/823-v6.9-0004-nvmem-zynqmp_nvmem-Add-support-to-access-efuse.patch b/target/linux/generic/backport-6.1/823-v6.9-0004-nvmem-zynqmp_nvmem-Add-support-to-access-efuse.patch new file mode 100644 index 0000000000..39c2f17835 --- /dev/null +++ b/target/linux/generic/backport-6.1/823-v6.9-0004-nvmem-zynqmp_nvmem-Add-support-to-access-efuse.patch @@ -0,0 +1,243 @@ +From 737c0c8d07b5f671c0a33cec95965fcb2d2ea893 Mon Sep 17 00:00:00 2001 +From: Praveen Teja Kundanala +Date: Sat, 24 Feb 2024 11:45:12 +0000 +Subject: [PATCH] nvmem: zynqmp_nvmem: Add support to access efuse + +Add support to read/write efuse memory map of ZynqMP. +Below are the offsets of ZynqMP efuse memory map + 0 - SOC version(read only) + 0xC - 0xFC -ZynqMP specific purpose efuses + 0x100 - 0x17F - Physical Unclonable Function(PUF) + efuses repurposed as user efuses + +Signed-off-by: Praveen Teja Kundanala +Acked-by: Kalyani Akula +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-8-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/zynqmp_nvmem.c | 186 +++++++++++++++++++++++++++++++++-- + 1 file changed, 176 insertions(+), 10 deletions(-) + +--- a/drivers/nvmem/zynqmp_nvmem.c ++++ b/drivers/nvmem/zynqmp_nvmem.c +@@ -4,6 +4,7 @@ + * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc. + */ + ++#include + #include + #include + #include +@@ -11,24 +12,189 @@ + #include + + #define SILICON_REVISION_MASK 0xF ++#define P_USER_0_64_UPPER_MASK GENMASK(31, 16) ++#define P_USER_127_LOWER_4_BIT_MASK GENMASK(3, 0) ++#define WORD_INBYTES 4 ++#define SOC_VER_SIZE 0x4 ++#define EFUSE_MEMORY_SIZE 0x177 ++#define UNUSED_SPACE 0x8 ++#define ZYNQMP_NVMEM_SIZE (SOC_VER_SIZE + UNUSED_SPACE + \ ++ EFUSE_MEMORY_SIZE) ++#define SOC_VERSION_OFFSET 0x0 ++#define EFUSE_START_OFFSET 0xC ++#define EFUSE_END_OFFSET 0xFC ++#define EFUSE_PUF_START_OFFSET 0x100 ++#define EFUSE_PUF_MID_OFFSET 0x140 ++#define EFUSE_PUF_END_OFFSET 0x17F ++#define EFUSE_NOT_ENABLED 29 + ++/* ++ * efuse access type ++ */ ++enum efuse_access { ++ EFUSE_READ = 0, ++ EFUSE_WRITE ++}; ++ ++/** ++ * struct xilinx_efuse - the basic structure ++ * @src: address of the buffer to store the data to be write/read ++ * @size: read/write word count ++ * @offset: read/write offset ++ * @flag: 0 - represents efuse read and 1- represents efuse write ++ * @pufuserfuse:0 - represents non-puf efuses, offset is used for read/write ++ * 1 - represents puf user fuse row number. ++ * ++ * this structure stores all the required details to ++ * read/write efuse memory. ++ */ ++struct xilinx_efuse { ++ u64 src; ++ u32 size; ++ u32 offset; ++ enum efuse_access flag; ++ u32 pufuserfuse; ++}; ++ ++static int zynqmp_efuse_access(void *context, unsigned int offset, ++ void *val, size_t bytes, enum efuse_access flag, ++ unsigned int pufflag) ++{ ++ struct device *dev = context; ++ struct xilinx_efuse *efuse; ++ dma_addr_t dma_addr; ++ dma_addr_t dma_buf; ++ size_t words = bytes / WORD_INBYTES; ++ int ret; ++ int value; ++ char *data; + +-static int zynqmp_nvmem_read(void *context, unsigned int offset, +- void *val, size_t bytes) ++ if (bytes % WORD_INBYTES != 0) { ++ dev_err(dev, "Bytes requested should be word aligned\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (pufflag == 0 && offset % WORD_INBYTES) { ++ dev_err(dev, "Offset requested should be word aligned\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (pufflag == 1 && flag == EFUSE_WRITE) { ++ memcpy(&value, val, bytes); ++ if ((offset == EFUSE_PUF_START_OFFSET || ++ offset == EFUSE_PUF_MID_OFFSET) && ++ value & P_USER_0_64_UPPER_MASK) { ++ dev_err(dev, "Only lower 4 bytes are allowed to be programmed in P_USER_0 & P_USER_64\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (offset == EFUSE_PUF_END_OFFSET && ++ (value & P_USER_127_LOWER_4_BIT_MASK)) { ++ dev_err(dev, "Only MSB 28 bits are allowed to be programmed for P_USER_127\n"); ++ return -EOPNOTSUPP; ++ } ++ } ++ ++ efuse = dma_alloc_coherent(dev, sizeof(struct xilinx_efuse), ++ &dma_addr, GFP_KERNEL); ++ if (!efuse) ++ return -ENOMEM; ++ ++ data = dma_alloc_coherent(dev, sizeof(bytes), ++ &dma_buf, GFP_KERNEL); ++ if (!data) { ++ ret = -ENOMEM; ++ goto efuse_data_fail; ++ } ++ ++ if (flag == EFUSE_WRITE) { ++ memcpy(data, val, bytes); ++ efuse->flag = EFUSE_WRITE; ++ } else { ++ efuse->flag = EFUSE_READ; ++ } ++ ++ efuse->src = dma_buf; ++ efuse->size = words; ++ efuse->offset = offset; ++ efuse->pufuserfuse = pufflag; ++ ++ zynqmp_pm_efuse_access(dma_addr, (u32 *)&ret); ++ if (ret != 0) { ++ if (ret == EFUSE_NOT_ENABLED) { ++ dev_err(dev, "efuse access is not enabled\n"); ++ ret = -EOPNOTSUPP; ++ } else { ++ dev_err(dev, "Error in efuse read %x\n", ret); ++ ret = -EPERM; ++ } ++ goto efuse_access_err; ++ } ++ ++ if (flag == EFUSE_READ) ++ memcpy(val, data, bytes); ++efuse_access_err: ++ dma_free_coherent(dev, sizeof(bytes), ++ data, dma_buf); ++efuse_data_fail: ++ dma_free_coherent(dev, sizeof(struct xilinx_efuse), ++ efuse, dma_addr); ++ ++ return ret; ++} ++ ++static int zynqmp_nvmem_read(void *context, unsigned int offset, void *val, size_t bytes) + { + struct device *dev = context; + int ret; ++ int pufflag = 0; + int idcode; + int version; + +- ret = zynqmp_pm_get_chipid(&idcode, &version); +- if (ret < 0) +- return ret; ++ if (offset >= EFUSE_PUF_START_OFFSET && offset <= EFUSE_PUF_END_OFFSET) ++ pufflag = 1; ++ ++ switch (offset) { ++ /* Soc version offset is zero */ ++ case SOC_VERSION_OFFSET: ++ if (bytes != SOC_VER_SIZE) ++ return -EOPNOTSUPP; ++ ++ ret = zynqmp_pm_get_chipid((u32 *)&idcode, (u32 *)&version); ++ if (ret < 0) ++ return ret; ++ ++ dev_dbg(dev, "Read chipid val %x %x\n", idcode, version); ++ *(int *)val = version & SILICON_REVISION_MASK; ++ break; ++ /* Efuse offset starts from 0xc */ ++ case EFUSE_START_OFFSET ... EFUSE_END_OFFSET: ++ case EFUSE_PUF_START_OFFSET ... EFUSE_PUF_END_OFFSET: ++ ret = zynqmp_efuse_access(context, offset, val, ++ bytes, EFUSE_READ, pufflag); ++ break; ++ default: ++ *(u32 *)val = 0xDEADBEEF; ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static int zynqmp_nvmem_write(void *context, ++ unsigned int offset, void *val, size_t bytes) ++{ ++ int pufflag = 0; ++ ++ if (offset < EFUSE_START_OFFSET || offset > EFUSE_PUF_END_OFFSET) ++ return -EOPNOTSUPP; + +- dev_dbg(dev, "Read chipid val %x %x\n", idcode, version); +- *(int *)val = version & SILICON_REVISION_MASK; ++ if (offset >= EFUSE_PUF_START_OFFSET && offset <= EFUSE_PUF_END_OFFSET) ++ pufflag = 1; + +- return 0; ++ return zynqmp_efuse_access(context, offset, ++ val, bytes, EFUSE_WRITE, pufflag); + } + + static const struct of_device_id zynqmp_nvmem_match[] = { +@@ -45,11 +211,11 @@ static int zynqmp_nvmem_probe(struct pla + econfig.name = "zynqmp-nvmem"; + econfig.owner = THIS_MODULE; + econfig.word_size = 1; +- econfig.size = 1; ++ econfig.size = ZYNQMP_NVMEM_SIZE; + econfig.dev = dev; + econfig.add_legacy_fixed_of_cells = true; +- econfig.read_only = true; + econfig.reg_read = zynqmp_nvmem_read; ++ econfig.reg_write = zynqmp_nvmem_write; + + return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &econfig)); + } diff --git a/target/linux/generic/backport-6.1/823-v6.9-0005-nvmem-mtk-efuse-Drop-NVMEM-device-name.patch b/target/linux/generic/backport-6.1/823-v6.9-0005-nvmem-mtk-efuse-Drop-NVMEM-device-name.patch new file mode 100644 index 0000000000..c67399cb13 --- /dev/null +++ b/target/linux/generic/backport-6.1/823-v6.9-0005-nvmem-mtk-efuse-Drop-NVMEM-device-name.patch @@ -0,0 +1,35 @@ +From 76c345edef754b16cab81ad9452cc49c09e67066 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Sat, 24 Feb 2024 11:45:14 +0000 +Subject: [PATCH] nvmem: mtk-efuse: Drop NVMEM device name +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The MT8183 has not one but two efuse devices. The static name and ID +causes the second efuse device to fail to probe, due to duplicate sysfs +entries. + +With the rework of the mtk-socinfo driver, lookup by name is no longer +necessary. The custom name can simply be dropped. + +Signed-off-by: Chen-Yu Tsai +Reviewed-by: AngeloGioacchino Del Regno +Tested-by: "Nícolas F. R. A. Prado" +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-10-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/mtk-efuse.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/nvmem/mtk-efuse.c ++++ b/drivers/nvmem/mtk-efuse.c +@@ -86,7 +86,6 @@ static int mtk_efuse_probe(struct platfo + econfig.size = resource_size(res); + econfig.priv = priv; + econfig.dev = dev; +- econfig.name = "mtk-efuse"; + if (pdata->uses_post_processing) + econfig.fixup_dt_cell_info = &mtk_efuse_fixup_dt_cell_info; + nvmem = devm_nvmem_register(dev, &econfig); diff --git a/target/linux/generic/backport-6.1/823-v6.9-0007-nvmem-core-Print-error-on-wrong-bits-DT-property.patch b/target/linux/generic/backport-6.1/823-v6.9-0007-nvmem-core-Print-error-on-wrong-bits-DT-property.patch new file mode 100644 index 0000000000..17bab24802 --- /dev/null +++ b/target/linux/generic/backport-6.1/823-v6.9-0007-nvmem-core-Print-error-on-wrong-bits-DT-property.patch @@ -0,0 +1,32 @@ +From def3173d4f17b37cecbd74d7c269a080b0b01598 Mon Sep 17 00:00:00 2001 +From: Markus Schneider-Pargmann +Date: Sat, 24 Feb 2024 11:45:16 +0000 +Subject: [PATCH] nvmem: core: Print error on wrong bits DT property + +The algorithms in nvmem core are built with the constraint that +bit_offset < 8. If bit_offset is greater the results are wrong. Print an +error if the devicetree 'bits' property is outside of the valid range +and abort parsing. + +Signed-off-by: Markus Schneider-Pargmann +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-12-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -806,6 +806,11 @@ static int nvmem_add_cells_from_dt(struc + if (addr && len == (2 * sizeof(u32))) { + info.bit_offset = be32_to_cpup(addr++); + info.nbits = be32_to_cpup(addr); ++ if (info.bit_offset >= BITS_PER_BYTE || info.nbits < 1) { ++ dev_err(dev, "nvmem: invalid bits on %pOF\n", child); ++ of_node_put(child); ++ return -EINVAL; ++ } + } + + info.np = of_node_get(child); diff --git a/target/linux/generic/backport-6.6/820-v6.9-0002-nvmem-mtk-efuse-Register-MediaTek-socinfo-driver-fro.patch b/target/linux/generic/backport-6.6/820-v6.9-0002-nvmem-mtk-efuse-Register-MediaTek-socinfo-driver-fro.patch new file mode 100644 index 0000000000..8e7c8233e2 --- /dev/null +++ b/target/linux/generic/backport-6.6/820-v6.9-0002-nvmem-mtk-efuse-Register-MediaTek-socinfo-driver-fro.patch @@ -0,0 +1,69 @@ +From 998f0633773b3432829fe45d2cd2ffb842f3c78e Mon Sep 17 00:00:00 2001 +From: William-tw Lin +Date: Sat, 24 Feb 2024 11:45:07 +0000 +Subject: [PATCH] nvmem: mtk-efuse: Register MediaTek socinfo driver from efuse + +The socinfo driver reads chip information from eFuses and does not need +any devicetree node. Register it from mtk-efuse. + +While at it, also add the name for this driver's nvmem_config. + +Signed-off-by: William-tw Lin +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/mtk-efuse.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +--- a/drivers/nvmem/mtk-efuse.c ++++ b/drivers/nvmem/mtk-efuse.c +@@ -68,6 +68,7 @@ static int mtk_efuse_probe(struct platfo + struct nvmem_config econfig = {}; + struct mtk_efuse_priv *priv; + const struct mtk_efuse_pdata *pdata; ++ struct platform_device *socinfo; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -85,11 +86,20 @@ static int mtk_efuse_probe(struct platfo + econfig.size = resource_size(res); + econfig.priv = priv; + econfig.dev = dev; ++ econfig.name = "mtk-efuse"; + if (pdata->uses_post_processing) + econfig.fixup_dt_cell_info = &mtk_efuse_fixup_dt_cell_info; + nvmem = devm_nvmem_register(dev, &econfig); ++ if (IS_ERR(nvmem)) ++ return PTR_ERR(nvmem); + +- return PTR_ERR_OR_ZERO(nvmem); ++ socinfo = platform_device_register_data(&pdev->dev, "mtk-socinfo", ++ PLATFORM_DEVID_AUTO, NULL, 0); ++ if (IS_ERR(socinfo)) ++ dev_info(dev, "MediaTek SoC Information will be unavailable\n"); ++ ++ platform_set_drvdata(pdev, socinfo); ++ return 0; + } + + static const struct mtk_efuse_pdata mtk_mt8186_efuse_pdata = { +@@ -108,8 +118,17 @@ static const struct of_device_id mtk_efu + }; + MODULE_DEVICE_TABLE(of, mtk_efuse_of_match); + ++static void mtk_efuse_remove(struct platform_device *pdev) ++{ ++ struct platform_device *socinfo = platform_get_drvdata(pdev); ++ ++ if (!IS_ERR_OR_NULL(socinfo)) ++ platform_device_unregister(socinfo); ++} ++ + static struct platform_driver mtk_efuse_driver = { + .probe = mtk_efuse_probe, ++ .remove_new = mtk_efuse_remove, + .driver = { + .name = "mediatek,efuse", + .of_match_table = mtk_efuse_of_match, diff --git a/target/linux/generic/backport-6.6/820-v6.9-0003-nvmem-zynqmp_nvmem-zynqmp_nvmem_probe-cleanup.patch b/target/linux/generic/backport-6.6/820-v6.9-0003-nvmem-zynqmp_nvmem-zynqmp_nvmem_probe-cleanup.patch new file mode 100644 index 0000000000..0f90e548a2 --- /dev/null +++ b/target/linux/generic/backport-6.6/820-v6.9-0003-nvmem-zynqmp_nvmem-zynqmp_nvmem_probe-cleanup.patch @@ -0,0 +1,97 @@ +From 29be47fcd6a06ea2e79eeeca6e69ad1e23254a69 Mon Sep 17 00:00:00 2001 +From: Praveen Teja Kundanala +Date: Sat, 24 Feb 2024 11:45:11 +0000 +Subject: [PATCH] nvmem: zynqmp_nvmem: zynqmp_nvmem_probe cleanup + +- Remove static nvmem_config declaration +- Remove zynqmp_nvmem_data + +Signed-off-by: Praveen Teja Kundanala +Acked-by: Kalyani Akula +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-7-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/zynqmp_nvmem.c | 37 ++++++++++++------------------------ + 1 file changed, 12 insertions(+), 25 deletions(-) + +--- a/drivers/nvmem/zynqmp_nvmem.c ++++ b/drivers/nvmem/zynqmp_nvmem.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0+ + /* + * Copyright (C) 2019 Xilinx, Inc. ++ * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc. + */ + + #include +@@ -11,36 +12,25 @@ + + #define SILICON_REVISION_MASK 0xF + +-struct zynqmp_nvmem_data { +- struct device *dev; +- struct nvmem_device *nvmem; +-}; + + static int zynqmp_nvmem_read(void *context, unsigned int offset, + void *val, size_t bytes) + { ++ struct device *dev = context; + int ret; +- int idcode, version; +- struct zynqmp_nvmem_data *priv = context; ++ int idcode; ++ int version; + + ret = zynqmp_pm_get_chipid(&idcode, &version); + if (ret < 0) + return ret; + +- dev_dbg(priv->dev, "Read chipid val %x %x\n", idcode, version); ++ dev_dbg(dev, "Read chipid val %x %x\n", idcode, version); + *(int *)val = version & SILICON_REVISION_MASK; + + return 0; + } + +-static struct nvmem_config econfig = { +- .name = "zynqmp-nvmem", +- .owner = THIS_MODULE, +- .word_size = 1, +- .size = 1, +- .read_only = true, +-}; +- + static const struct of_device_id zynqmp_nvmem_match[] = { + { .compatible = "xlnx,zynqmp-nvmem-fw", }, + { /* sentinel */ }, +@@ -50,21 +40,18 @@ MODULE_DEVICE_TABLE(of, zynqmp_nvmem_mat + static int zynqmp_nvmem_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- struct zynqmp_nvmem_data *priv; ++ struct nvmem_config econfig = {}; + +- priv = devm_kzalloc(dev, sizeof(struct zynqmp_nvmem_data), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- +- priv->dev = dev; ++ econfig.name = "zynqmp-nvmem"; ++ econfig.owner = THIS_MODULE; ++ econfig.word_size = 1; ++ econfig.size = 1; + econfig.dev = dev; + econfig.add_legacy_fixed_of_cells = true; ++ econfig.read_only = true; + econfig.reg_read = zynqmp_nvmem_read; +- econfig.priv = priv; +- +- priv->nvmem = devm_nvmem_register(dev, &econfig); + +- return PTR_ERR_OR_ZERO(priv->nvmem); ++ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &econfig)); + } + + static struct platform_driver zynqmp_nvmem_driver = { diff --git a/target/linux/generic/backport-6.6/820-v6.9-0004-nvmem-zynqmp_nvmem-Add-support-to-access-efuse.patch b/target/linux/generic/backport-6.6/820-v6.9-0004-nvmem-zynqmp_nvmem-Add-support-to-access-efuse.patch new file mode 100644 index 0000000000..39c2f17835 --- /dev/null +++ b/target/linux/generic/backport-6.6/820-v6.9-0004-nvmem-zynqmp_nvmem-Add-support-to-access-efuse.patch @@ -0,0 +1,243 @@ +From 737c0c8d07b5f671c0a33cec95965fcb2d2ea893 Mon Sep 17 00:00:00 2001 +From: Praveen Teja Kundanala +Date: Sat, 24 Feb 2024 11:45:12 +0000 +Subject: [PATCH] nvmem: zynqmp_nvmem: Add support to access efuse + +Add support to read/write efuse memory map of ZynqMP. +Below are the offsets of ZynqMP efuse memory map + 0 - SOC version(read only) + 0xC - 0xFC -ZynqMP specific purpose efuses + 0x100 - 0x17F - Physical Unclonable Function(PUF) + efuses repurposed as user efuses + +Signed-off-by: Praveen Teja Kundanala +Acked-by: Kalyani Akula +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-8-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/zynqmp_nvmem.c | 186 +++++++++++++++++++++++++++++++++-- + 1 file changed, 176 insertions(+), 10 deletions(-) + +--- a/drivers/nvmem/zynqmp_nvmem.c ++++ b/drivers/nvmem/zynqmp_nvmem.c +@@ -4,6 +4,7 @@ + * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc. + */ + ++#include + #include + #include + #include +@@ -11,24 +12,189 @@ + #include + + #define SILICON_REVISION_MASK 0xF ++#define P_USER_0_64_UPPER_MASK GENMASK(31, 16) ++#define P_USER_127_LOWER_4_BIT_MASK GENMASK(3, 0) ++#define WORD_INBYTES 4 ++#define SOC_VER_SIZE 0x4 ++#define EFUSE_MEMORY_SIZE 0x177 ++#define UNUSED_SPACE 0x8 ++#define ZYNQMP_NVMEM_SIZE (SOC_VER_SIZE + UNUSED_SPACE + \ ++ EFUSE_MEMORY_SIZE) ++#define SOC_VERSION_OFFSET 0x0 ++#define EFUSE_START_OFFSET 0xC ++#define EFUSE_END_OFFSET 0xFC ++#define EFUSE_PUF_START_OFFSET 0x100 ++#define EFUSE_PUF_MID_OFFSET 0x140 ++#define EFUSE_PUF_END_OFFSET 0x17F ++#define EFUSE_NOT_ENABLED 29 + ++/* ++ * efuse access type ++ */ ++enum efuse_access { ++ EFUSE_READ = 0, ++ EFUSE_WRITE ++}; ++ ++/** ++ * struct xilinx_efuse - the basic structure ++ * @src: address of the buffer to store the data to be write/read ++ * @size: read/write word count ++ * @offset: read/write offset ++ * @flag: 0 - represents efuse read and 1- represents efuse write ++ * @pufuserfuse:0 - represents non-puf efuses, offset is used for read/write ++ * 1 - represents puf user fuse row number. ++ * ++ * this structure stores all the required details to ++ * read/write efuse memory. ++ */ ++struct xilinx_efuse { ++ u64 src; ++ u32 size; ++ u32 offset; ++ enum efuse_access flag; ++ u32 pufuserfuse; ++}; ++ ++static int zynqmp_efuse_access(void *context, unsigned int offset, ++ void *val, size_t bytes, enum efuse_access flag, ++ unsigned int pufflag) ++{ ++ struct device *dev = context; ++ struct xilinx_efuse *efuse; ++ dma_addr_t dma_addr; ++ dma_addr_t dma_buf; ++ size_t words = bytes / WORD_INBYTES; ++ int ret; ++ int value; ++ char *data; + +-static int zynqmp_nvmem_read(void *context, unsigned int offset, +- void *val, size_t bytes) ++ if (bytes % WORD_INBYTES != 0) { ++ dev_err(dev, "Bytes requested should be word aligned\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (pufflag == 0 && offset % WORD_INBYTES) { ++ dev_err(dev, "Offset requested should be word aligned\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (pufflag == 1 && flag == EFUSE_WRITE) { ++ memcpy(&value, val, bytes); ++ if ((offset == EFUSE_PUF_START_OFFSET || ++ offset == EFUSE_PUF_MID_OFFSET) && ++ value & P_USER_0_64_UPPER_MASK) { ++ dev_err(dev, "Only lower 4 bytes are allowed to be programmed in P_USER_0 & P_USER_64\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (offset == EFUSE_PUF_END_OFFSET && ++ (value & P_USER_127_LOWER_4_BIT_MASK)) { ++ dev_err(dev, "Only MSB 28 bits are allowed to be programmed for P_USER_127\n"); ++ return -EOPNOTSUPP; ++ } ++ } ++ ++ efuse = dma_alloc_coherent(dev, sizeof(struct xilinx_efuse), ++ &dma_addr, GFP_KERNEL); ++ if (!efuse) ++ return -ENOMEM; ++ ++ data = dma_alloc_coherent(dev, sizeof(bytes), ++ &dma_buf, GFP_KERNEL); ++ if (!data) { ++ ret = -ENOMEM; ++ goto efuse_data_fail; ++ } ++ ++ if (flag == EFUSE_WRITE) { ++ memcpy(data, val, bytes); ++ efuse->flag = EFUSE_WRITE; ++ } else { ++ efuse->flag = EFUSE_READ; ++ } ++ ++ efuse->src = dma_buf; ++ efuse->size = words; ++ efuse->offset = offset; ++ efuse->pufuserfuse = pufflag; ++ ++ zynqmp_pm_efuse_access(dma_addr, (u32 *)&ret); ++ if (ret != 0) { ++ if (ret == EFUSE_NOT_ENABLED) { ++ dev_err(dev, "efuse access is not enabled\n"); ++ ret = -EOPNOTSUPP; ++ } else { ++ dev_err(dev, "Error in efuse read %x\n", ret); ++ ret = -EPERM; ++ } ++ goto efuse_access_err; ++ } ++ ++ if (flag == EFUSE_READ) ++ memcpy(val, data, bytes); ++efuse_access_err: ++ dma_free_coherent(dev, sizeof(bytes), ++ data, dma_buf); ++efuse_data_fail: ++ dma_free_coherent(dev, sizeof(struct xilinx_efuse), ++ efuse, dma_addr); ++ ++ return ret; ++} ++ ++static int zynqmp_nvmem_read(void *context, unsigned int offset, void *val, size_t bytes) + { + struct device *dev = context; + int ret; ++ int pufflag = 0; + int idcode; + int version; + +- ret = zynqmp_pm_get_chipid(&idcode, &version); +- if (ret < 0) +- return ret; ++ if (offset >= EFUSE_PUF_START_OFFSET && offset <= EFUSE_PUF_END_OFFSET) ++ pufflag = 1; ++ ++ switch (offset) { ++ /* Soc version offset is zero */ ++ case SOC_VERSION_OFFSET: ++ if (bytes != SOC_VER_SIZE) ++ return -EOPNOTSUPP; ++ ++ ret = zynqmp_pm_get_chipid((u32 *)&idcode, (u32 *)&version); ++ if (ret < 0) ++ return ret; ++ ++ dev_dbg(dev, "Read chipid val %x %x\n", idcode, version); ++ *(int *)val = version & SILICON_REVISION_MASK; ++ break; ++ /* Efuse offset starts from 0xc */ ++ case EFUSE_START_OFFSET ... EFUSE_END_OFFSET: ++ case EFUSE_PUF_START_OFFSET ... EFUSE_PUF_END_OFFSET: ++ ret = zynqmp_efuse_access(context, offset, val, ++ bytes, EFUSE_READ, pufflag); ++ break; ++ default: ++ *(u32 *)val = 0xDEADBEEF; ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static int zynqmp_nvmem_write(void *context, ++ unsigned int offset, void *val, size_t bytes) ++{ ++ int pufflag = 0; ++ ++ if (offset < EFUSE_START_OFFSET || offset > EFUSE_PUF_END_OFFSET) ++ return -EOPNOTSUPP; + +- dev_dbg(dev, "Read chipid val %x %x\n", idcode, version); +- *(int *)val = version & SILICON_REVISION_MASK; ++ if (offset >= EFUSE_PUF_START_OFFSET && offset <= EFUSE_PUF_END_OFFSET) ++ pufflag = 1; + +- return 0; ++ return zynqmp_efuse_access(context, offset, ++ val, bytes, EFUSE_WRITE, pufflag); + } + + static const struct of_device_id zynqmp_nvmem_match[] = { +@@ -45,11 +211,11 @@ static int zynqmp_nvmem_probe(struct pla + econfig.name = "zynqmp-nvmem"; + econfig.owner = THIS_MODULE; + econfig.word_size = 1; +- econfig.size = 1; ++ econfig.size = ZYNQMP_NVMEM_SIZE; + econfig.dev = dev; + econfig.add_legacy_fixed_of_cells = true; +- econfig.read_only = true; + econfig.reg_read = zynqmp_nvmem_read; ++ econfig.reg_write = zynqmp_nvmem_write; + + return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &econfig)); + } diff --git a/target/linux/generic/backport-6.6/820-v6.9-0005-nvmem-mtk-efuse-Drop-NVMEM-device-name.patch b/target/linux/generic/backport-6.6/820-v6.9-0005-nvmem-mtk-efuse-Drop-NVMEM-device-name.patch new file mode 100644 index 0000000000..c67399cb13 --- /dev/null +++ b/target/linux/generic/backport-6.6/820-v6.9-0005-nvmem-mtk-efuse-Drop-NVMEM-device-name.patch @@ -0,0 +1,35 @@ +From 76c345edef754b16cab81ad9452cc49c09e67066 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Sat, 24 Feb 2024 11:45:14 +0000 +Subject: [PATCH] nvmem: mtk-efuse: Drop NVMEM device name +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The MT8183 has not one but two efuse devices. The static name and ID +causes the second efuse device to fail to probe, due to duplicate sysfs +entries. + +With the rework of the mtk-socinfo driver, lookup by name is no longer +necessary. The custom name can simply be dropped. + +Signed-off-by: Chen-Yu Tsai +Reviewed-by: AngeloGioacchino Del Regno +Tested-by: "Nícolas F. R. A. Prado" +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-10-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/mtk-efuse.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/nvmem/mtk-efuse.c ++++ b/drivers/nvmem/mtk-efuse.c +@@ -86,7 +86,6 @@ static int mtk_efuse_probe(struct platfo + econfig.size = resource_size(res); + econfig.priv = priv; + econfig.dev = dev; +- econfig.name = "mtk-efuse"; + if (pdata->uses_post_processing) + econfig.fixup_dt_cell_info = &mtk_efuse_fixup_dt_cell_info; + nvmem = devm_nvmem_register(dev, &econfig); diff --git a/target/linux/generic/backport-6.6/820-v6.9-0006-nvmem-core-make-nvmem_layout_bus_type-const.patch b/target/linux/generic/backport-6.6/820-v6.9-0006-nvmem-core-make-nvmem_layout_bus_type-const.patch new file mode 100644 index 0000000000..506092e359 --- /dev/null +++ b/target/linux/generic/backport-6.6/820-v6.9-0006-nvmem-core-make-nvmem_layout_bus_type-const.patch @@ -0,0 +1,33 @@ +From 8ec0faf2572216b4e25d6829cd41cf3ee2dab979 Mon Sep 17 00:00:00 2001 +From: "Ricardo B. Marliere" +Date: Sat, 24 Feb 2024 11:45:15 +0000 +Subject: [PATCH] nvmem: core: make nvmem_layout_bus_type const + +Since commit d492cc2573a0 ("driver core: device.h: make struct bus_type +a const *"), the driver core can properly handle constant struct +bus_type, move the nvmem_layout_bus_type variable to be a constant +structure as well, placing it into read-only memory which can not be +modified at runtime. + +Cc: Greg Kroah-Hartman +Suggested-by: Greg Kroah-Hartman +Signed-off-by: "Ricardo B. Marliere" +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-11-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/layouts.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/layouts.c ++++ b/drivers/nvmem/layouts.c +@@ -45,7 +45,7 @@ static void nvmem_layout_bus_remove(stru + return drv->remove(layout); + } + +-static struct bus_type nvmem_layout_bus_type = { ++static const struct bus_type nvmem_layout_bus_type = { + .name = "nvmem-layout", + .match = nvmem_layout_bus_match, + .probe = nvmem_layout_bus_probe, diff --git a/target/linux/generic/backport-6.6/820-v6.9-0007-nvmem-core-Print-error-on-wrong-bits-DT-property.patch b/target/linux/generic/backport-6.6/820-v6.9-0007-nvmem-core-Print-error-on-wrong-bits-DT-property.patch new file mode 100644 index 0000000000..aa4e0ab04a --- /dev/null +++ b/target/linux/generic/backport-6.6/820-v6.9-0007-nvmem-core-Print-error-on-wrong-bits-DT-property.patch @@ -0,0 +1,32 @@ +From def3173d4f17b37cecbd74d7c269a080b0b01598 Mon Sep 17 00:00:00 2001 +From: Markus Schneider-Pargmann +Date: Sat, 24 Feb 2024 11:45:16 +0000 +Subject: [PATCH] nvmem: core: Print error on wrong bits DT property + +The algorithms in nvmem core are built with the constraint that +bit_offset < 8. If bit_offset is greater the results are wrong. Print an +error if the devicetree 'bits' property is outside of the valid range +and abort parsing. + +Signed-off-by: Markus Schneider-Pargmann +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114516.86365-12-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -805,6 +805,11 @@ static int nvmem_add_cells_from_dt(struc + if (addr && len == (2 * sizeof(u32))) { + info.bit_offset = be32_to_cpup(addr++); + info.nbits = be32_to_cpup(addr); ++ if (info.bit_offset >= BITS_PER_BYTE || info.nbits < 1) { ++ dev_err(dev, "nvmem: invalid bits on %pOF\n", child); ++ of_node_put(child); ++ return -EINVAL; ++ } + } + + info.np = of_node_get(child); diff --git a/target/linux/generic/pending-5.15/804-nvmem-core-support-mac-base-fixed-layout-cells.patch b/target/linux/generic/pending-5.15/804-nvmem-core-support-mac-base-fixed-layout-cells.patch index 9bb94a28b5..8c5d3c266e 100644 --- a/target/linux/generic/pending-5.15/804-nvmem-core-support-mac-base-fixed-layout-cells.patch +++ b/target/linux/generic/pending-5.15/804-nvmem-core-support-mac-base-fixed-layout-cells.patch @@ -96,7 +96,7 @@ string. static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np) { struct device *dev = &nvmem->dev; -@@ -814,6 +873,25 @@ static int nvmem_add_cells_from_dt(struc +@@ -819,6 +878,25 @@ static int nvmem_add_cells_from_dt(struc if (nvmem->fixup_dt_cell_info) nvmem->fixup_dt_cell_info(nvmem, &info); diff --git a/target/linux/generic/pending-6.1/804-nvmem-core-support-mac-base-fixed-layout-cells.patch b/target/linux/generic/pending-6.1/804-nvmem-core-support-mac-base-fixed-layout-cells.patch index da25b39ae9..d6a471d576 100644 --- a/target/linux/generic/pending-6.1/804-nvmem-core-support-mac-base-fixed-layout-cells.patch +++ b/target/linux/generic/pending-6.1/804-nvmem-core-support-mac-base-fixed-layout-cells.patch @@ -96,7 +96,7 @@ string. static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np) { struct device *dev = &nvmem->dev; -@@ -813,6 +872,25 @@ static int nvmem_add_cells_from_dt(struc +@@ -818,6 +877,25 @@ static int nvmem_add_cells_from_dt(struc if (nvmem->fixup_dt_cell_info) nvmem->fixup_dt_cell_info(nvmem, &info); diff --git a/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch b/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch index 44b9862654..df724521be 100644 --- a/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch +++ b/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch @@ -96,7 +96,7 @@ string. static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np) { struct device *dev = &nvmem->dev; -@@ -812,6 +871,25 @@ static int nvmem_add_cells_from_dt(struc +@@ -817,6 +876,25 @@ static int nvmem_add_cells_from_dt(struc if (nvmem->fixup_dt_cell_info) nvmem->fixup_dt_cell_info(nvmem, &info);