--- /dev/null
+From eebc6573ad940b62a87776db3917e912b4f52d78 Mon Sep 17 00:00:00 2001
+From: Tom Rix <trix@redhat.com>
+Date: Sun, 11 Jun 2023 15:03:05 +0100
+Subject: [PATCH] nvmem: imx-ocotp: set varaiable imx_ocotp_layout
+ storage-class-specifier to static
+
+smatch reports
+drivers/nvmem/imx-ocotp.c:599:21: warning: symbol
+ 'imx_ocotp_layout' was not declared. Should it be static?
+
+This variable is only used in one file so should be static.
+
+Signed-off-by: Tom Rix <trix@redhat.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Message-ID: <20230611140330.154222-2-srinivas.kandagatla@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/imx-ocotp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/imx-ocotp.c
++++ b/drivers/nvmem/imx-ocotp.c
+@@ -596,7 +596,7 @@ static void imx_ocotp_fixup_cell_info(st
+ cell->read_post_process = imx_ocotp_cell_pp;
+ }
+
+-struct nvmem_layout imx_ocotp_layout = {
++static struct nvmem_layout imx_ocotp_layout = {
+ .fixup_cell_info = imx_ocotp_fixup_cell_info,
+ };
+
--- /dev/null
+From 8a00fc606312c68b98add8fe8e6f7a013ce29e78 Mon Sep 17 00:00:00 2001
+From: Alexander Stein <alexander.stein@ew.tq-group.com>
+Date: Sun, 11 Jun 2023 15:03:06 +0100
+Subject: [PATCH] nvmem: imx-ocotp: Reverse MAC addresses on all i.MX derivates
+
+Not just i.MX8M, but all i.MX6/7 (and subtypes) need to reverse the
+MAC address read from fuses. Exceptions are i.MX6SLL and i.MX7ULP which
+do not support ethernet at all.
+
+Fixes: d0221a780cbc ("nvmem: imx-ocotp: add support for post processing")
+Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
+Tested-by: Richard Leitner <richard.leitner@skidata.com> # imx6q
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Message-ID: <20230611140330.154222-3-srinivas.kandagatla@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/imx-ocotp.c | 8 +-------
+ 1 file changed, 1 insertion(+), 7 deletions(-)
+
+--- a/drivers/nvmem/imx-ocotp.c
++++ b/drivers/nvmem/imx-ocotp.c
+@@ -97,7 +97,6 @@ struct ocotp_params {
+ unsigned int bank_address_words;
+ void (*set_timing)(struct ocotp_priv *priv);
+ struct ocotp_ctrl_reg ctrl;
+- bool reverse_mac_address;
+ };
+
+ static int imx_ocotp_wait_for_busy(struct ocotp_priv *priv, u32 flags)
+@@ -545,7 +544,6 @@ static const struct ocotp_params imx8mq_
+ .bank_address_words = 0,
+ .set_timing = imx_ocotp_set_imx6_timing,
+ .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
+- .reverse_mac_address = true,
+ };
+
+ static const struct ocotp_params imx8mm_params = {
+@@ -553,7 +551,6 @@ static const struct ocotp_params imx8mm_
+ .bank_address_words = 0,
+ .set_timing = imx_ocotp_set_imx6_timing,
+ .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
+- .reverse_mac_address = true,
+ };
+
+ static const struct ocotp_params imx8mn_params = {
+@@ -561,7 +558,6 @@ static const struct ocotp_params imx8mn_
+ .bank_address_words = 0,
+ .set_timing = imx_ocotp_set_imx6_timing,
+ .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
+- .reverse_mac_address = true,
+ };
+
+ static const struct ocotp_params imx8mp_params = {
+@@ -569,7 +565,6 @@ static const struct ocotp_params imx8mp_
+ .bank_address_words = 0,
+ .set_timing = imx_ocotp_set_imx6_timing,
+ .ctrl = IMX_OCOTP_BM_CTRL_8MP,
+- .reverse_mac_address = true,
+ };
+
+ static const struct of_device_id imx_ocotp_dt_ids[] = {
+@@ -624,8 +619,7 @@ static int imx_ocotp_probe(struct platfo
+ imx_ocotp_nvmem_config.size = 4 * priv->params->nregs;
+ imx_ocotp_nvmem_config.dev = dev;
+ imx_ocotp_nvmem_config.priv = priv;
+- if (priv->params->reverse_mac_address)
+- imx_ocotp_nvmem_config.layout = &imx_ocotp_layout;
++ imx_ocotp_nvmem_config.layout = &imx_ocotp_layout;
+
+ priv->config = &imx_ocotp_nvmem_config;
+
--- /dev/null
+From 73bcd133c910bff3b6d3b3834d0d14be9444e90a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Sun, 11 Jun 2023 15:03:08 +0100
+Subject: [PATCH] nvmem: brcm_nvram: add .read_post_process() for MACs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+1. Parse ASCII MAC format into byte based
+2. Calculate relative addresses based on index argument
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Message-ID: <20230611140330.154222-5-srinivas.kandagatla@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/Kconfig | 1 +
+ drivers/nvmem/brcm_nvram.c | 28 ++++++++++++++++++++++++++++
+ 2 files changed, 29 insertions(+)
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -55,6 +55,7 @@ config NVMEM_BRCM_NVRAM
+ tristate "Broadcom's NVRAM support"
+ depends on ARCH_BCM_5301X || COMPILE_TEST
+ depends on HAS_IOMEM
++ select GENERIC_NET_UTILS
+ help
+ This driver provides support for Broadcom's NVRAM that can be accessed
+ using I/O mapping.
+--- a/drivers/nvmem/brcm_nvram.c
++++ b/drivers/nvmem/brcm_nvram.c
+@@ -4,6 +4,8 @@
+ */
+
+ #include <linux/bcm47xx_nvram.h>
++#include <linux/etherdevice.h>
++#include <linux/if_ether.h>
+ #include <linux/io.h>
+ #include <linux/mod_devicetable.h>
+ #include <linux/module.h>
+@@ -42,6 +44,25 @@ static int brcm_nvram_read(void *context
+ return 0;
+ }
+
++static int brcm_nvram_read_post_process_macaddr(void *context, const char *id, int index,
++ unsigned int offset, void *buf, size_t bytes)
++{
++ u8 mac[ETH_ALEN];
++
++ if (bytes != 3 * ETH_ALEN - 1)
++ return -EINVAL;
++
++ if (!mac_pton(buf, mac))
++ return -EINVAL;
++
++ if (index)
++ eth_addr_add(mac, index);
++
++ ether_addr_copy(buf, mac);
++
++ return 0;
++}
++
+ static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data,
+ size_t len)
+ {
+@@ -75,6 +96,13 @@ static int brcm_nvram_add_cells(struct b
+ priv->cells[idx].offset = value - (char *)data;
+ priv->cells[idx].bytes = strlen(value);
+ priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
++ if (!strcmp(var, "et0macaddr") ||
++ !strcmp(var, "et1macaddr") ||
++ !strcmp(var, "et2macaddr")) {
++ priv->cells[idx].raw_len = strlen(value);
++ priv->cells[idx].bytes = ETH_ALEN;
++ priv->cells[idx].read_post_process = brcm_nvram_read_post_process_macaddr;
++ }
+ }
+
+ return 0;
--- /dev/null
+From 8dc61364164e79e44c07fa2ac0a7b6939f00d5db Mon Sep 17 00:00:00 2001
+From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+Date: Sun, 11 Jun 2023 15:03:13 +0100
+Subject: [PATCH] nvmem: rockchip-otp: Add clks and reg_read to rockchip_data
+
+In preparation to support new Rockchip OTP memory devices with different
+clock configurations and register layout, extend rockchip_data struct
+with the related members: clks, num_clks, reg_read.
+
+Additionally, to avoid managing redundant driver data, drop num_clks
+member from rockchip_otp struct and update all references to point to
+the equivalent member in rockchip_data.
+
+Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+Tested-by: Vincent Legoll <vincent.legoll@gmail.com>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Message-ID: <20230611140330.154222-10-srinivas.kandagatla@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/rockchip-otp.c | 79 ++++++++++++++++++++++--------------
+ 1 file changed, 49 insertions(+), 30 deletions(-)
+
+--- a/drivers/nvmem/rockchip-otp.c
++++ b/drivers/nvmem/rockchip-otp.c
+@@ -54,21 +54,19 @@
+
+ #define OTPC_TIMEOUT 10000
+
++struct rockchip_data {
++ int size;
++ const char * const *clks;
++ int num_clks;
++ nvmem_reg_read_t reg_read;
++};
++
+ struct rockchip_otp {
+ struct device *dev;
+ void __iomem *base;
+- struct clk_bulk_data *clks;
+- int num_clks;
++ struct clk_bulk_data *clks;
+ struct reset_control *rst;
+-};
+-
+-/* list of required clocks */
+-static const char * const rockchip_otp_clocks[] = {
+- "otp", "apb_pclk", "phy",
+-};
+-
+-struct rockchip_data {
+- int size;
++ const struct rockchip_data *data;
+ };
+
+ static int rockchip_otp_reset(struct rockchip_otp *otp)
+@@ -132,29 +130,23 @@ static int rockchip_otp_ecc_enable(struc
+ return ret;
+ }
+
+-static int rockchip_otp_read(void *context, unsigned int offset,
+- void *val, size_t bytes)
++static int px30_otp_read(void *context, unsigned int offset,
++ void *val, size_t bytes)
+ {
+ struct rockchip_otp *otp = context;
+ u8 *buf = val;
+- int ret = 0;
+-
+- ret = clk_bulk_prepare_enable(otp->num_clks, otp->clks);
+- if (ret < 0) {
+- dev_err(otp->dev, "failed to prepare/enable clks\n");
+- return ret;
+- }
++ int ret;
+
+ ret = rockchip_otp_reset(otp);
+ if (ret) {
+ dev_err(otp->dev, "failed to reset otp phy\n");
+- goto disable_clks;
++ return ret;
+ }
+
+ ret = rockchip_otp_ecc_enable(otp, false);
+ if (ret < 0) {
+ dev_err(otp->dev, "rockchip_otp_ecc_enable err\n");
+- goto disable_clks;
++ return ret;
+ }
+
+ writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
+@@ -174,8 +166,28 @@ static int rockchip_otp_read(void *conte
+
+ read_end:
+ writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
+-disable_clks:
+- clk_bulk_disable_unprepare(otp->num_clks, otp->clks);
++
++ return ret;
++}
++
++static int rockchip_otp_read(void *context, unsigned int offset,
++ void *val, size_t bytes)
++{
++ struct rockchip_otp *otp = context;
++ int ret;
++
++ if (!otp->data || !otp->data->reg_read)
++ return -EINVAL;
++
++ ret = clk_bulk_prepare_enable(otp->data->num_clks, otp->clks);
++ if (ret < 0) {
++ dev_err(otp->dev, "failed to prepare/enable clks\n");
++ return ret;
++ }
++
++ ret = otp->data->reg_read(context, offset, val, bytes);
++
++ clk_bulk_disable_unprepare(otp->data->num_clks, otp->clks);
+
+ return ret;
+ }
+@@ -189,8 +201,15 @@ static struct nvmem_config otp_config =
+ .reg_read = rockchip_otp_read,
+ };
+
++static const char * const px30_otp_clocks[] = {
++ "otp", "apb_pclk", "phy",
++};
++
+ static const struct rockchip_data px30_data = {
+ .size = 0x40,
++ .clks = px30_otp_clocks,
++ .num_clks = ARRAY_SIZE(px30_otp_clocks),
++ .reg_read = px30_otp_read,
+ };
+
+ static const struct of_device_id rockchip_otp_match[] = {
+@@ -225,21 +244,21 @@ static int rockchip_otp_probe(struct pla
+ if (!otp)
+ return -ENOMEM;
+
++ otp->data = data;
+ otp->dev = dev;
+ otp->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(otp->base))
+ return PTR_ERR(otp->base);
+
+- otp->num_clks = ARRAY_SIZE(rockchip_otp_clocks);
+- otp->clks = devm_kcalloc(dev, otp->num_clks,
+- sizeof(*otp->clks), GFP_KERNEL);
++ otp->clks = devm_kcalloc(dev, data->num_clks, sizeof(*otp->clks),
++ GFP_KERNEL);
+ if (!otp->clks)
+ return -ENOMEM;
+
+- for (i = 0; i < otp->num_clks; ++i)
+- otp->clks[i].id = rockchip_otp_clocks[i];
++ for (i = 0; i < data->num_clks; ++i)
++ otp->clks[i].id = data->clks[i];
+
+- ret = devm_clk_bulk_get(dev, otp->num_clks, otp->clks);
++ ret = devm_clk_bulk_get(dev, data->num_clks, otp->clks);
+ if (ret)
+ return ret;
+
--- /dev/null
+From 30fd21cfb1e64ef20035559a8246f5fbf682c40e Mon Sep 17 00:00:00 2001
+From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+Date: Sun, 11 Jun 2023 15:03:14 +0100
+Subject: [PATCH] nvmem: rockchip-otp: Generalize rockchip_otp_wait_status()
+
+In preparation to support additional Rockchip OTP memory devices with
+different register layout, generalize rockchip_otp_wait_status() to
+accept a new parameter for specifying the offset of the status register.
+
+Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+Tested-by: Vincent Legoll <vincent.legoll@gmail.com>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Message-ID: <20230611140330.154222-11-srinivas.kandagatla@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/rockchip-otp.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/nvmem/rockchip-otp.c
++++ b/drivers/nvmem/rockchip-otp.c
+@@ -90,18 +90,19 @@ static int rockchip_otp_reset(struct roc
+ return 0;
+ }
+
+-static int rockchip_otp_wait_status(struct rockchip_otp *otp, u32 flag)
++static int rockchip_otp_wait_status(struct rockchip_otp *otp,
++ unsigned int reg, u32 flag)
+ {
+ u32 status = 0;
+ int ret;
+
+- ret = readl_poll_timeout_atomic(otp->base + OTPC_INT_STATUS, status,
++ ret = readl_poll_timeout_atomic(otp->base + reg, status,
+ (status & flag), 1, OTPC_TIMEOUT);
+ if (ret)
+ return ret;
+
+ /* clean int status */
+- writel(flag, otp->base + OTPC_INT_STATUS);
++ writel(flag, otp->base + reg);
+
+ return 0;
+ }
+@@ -123,7 +124,7 @@ static int rockchip_otp_ecc_enable(struc
+
+ writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
+
+- ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE);
++ ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_SBPI_DONE);
+ if (ret < 0)
+ dev_err(otp->dev, "timeout during ecc_enable\n");
+
+@@ -156,7 +157,7 @@ static int px30_otp_read(void *context,
+ otp->base + OTPC_USER_ADDR);
+ writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
+ otp->base + OTPC_USER_ENABLE);
+- ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE);
++ ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_USER_DONE);
+ if (ret < 0) {
+ dev_err(otp->dev, "timeout during read setup\n");
+ goto read_end;
--- /dev/null
+From d325c9dd2b6e94040ca722ddcadcd6af358dd2be Mon Sep 17 00:00:00 2001
+From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+Date: Sun, 11 Jun 2023 15:03:15 +0100
+Subject: [PATCH] nvmem: rockchip-otp: Use
+ devm_reset_control_array_get_exclusive()
+
+In preparation to support new Rockchip OTP memory devices having
+specific reset configurations, switch devm_reset_control_get() to
+devm_reset_control_array_get_exclusive().
+
+Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+Tested-by: Vincent Legoll <vincent.legoll@gmail.com>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Message-ID: <20230611140330.154222-12-srinivas.kandagatla@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/rockchip-otp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/rockchip-otp.c
++++ b/drivers/nvmem/rockchip-otp.c
+@@ -263,7 +263,7 @@ static int rockchip_otp_probe(struct pla
+ if (ret)
+ return ret;
+
+- otp->rst = devm_reset_control_get(dev, "phy");
++ otp->rst = devm_reset_control_array_get_exclusive(dev);
+ if (IS_ERR(otp->rst))
+ return PTR_ERR(otp->rst);
+
--- /dev/null
+From 912517345b867a69542dc9f5c2cc3e9d8beaccf5 Mon Sep 17 00:00:00 2001
+From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+Date: Sun, 11 Jun 2023 15:03:16 +0100
+Subject: [PATCH] nvmem: rockchip-otp: Improve probe error handling
+
+Enhance error handling in the probe function by making use of
+dev_err_probe(), which ensures the error code is always printed, in
+addition to the specified error message.
+
+Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+Tested-by: Vincent Legoll <vincent.legoll@gmail.com>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Message-ID: <20230611140330.154222-13-srinivas.kandagatla@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/rockchip-otp.c | 21 ++++++++++++---------
+ 1 file changed, 12 insertions(+), 9 deletions(-)
+
+--- a/drivers/nvmem/rockchip-otp.c
++++ b/drivers/nvmem/rockchip-otp.c
+@@ -235,10 +235,8 @@ static int rockchip_otp_probe(struct pla
+ int ret, i;
+
+ data = of_device_get_match_data(dev);
+- if (!data) {
+- dev_err(dev, "failed to get match data\n");
+- return -EINVAL;
+- }
++ if (!data)
++ return dev_err_probe(dev, -EINVAL, "failed to get match data\n");
+
+ otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp),
+ GFP_KERNEL);
+@@ -249,7 +247,8 @@ static int rockchip_otp_probe(struct pla
+ otp->dev = dev;
+ otp->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(otp->base))
+- return PTR_ERR(otp->base);
++ return dev_err_probe(dev, PTR_ERR(otp->base),
++ "failed to ioremap resource\n");
+
+ otp->clks = devm_kcalloc(dev, data->num_clks, sizeof(*otp->clks),
+ GFP_KERNEL);
+@@ -261,18 +260,22 @@ static int rockchip_otp_probe(struct pla
+
+ ret = devm_clk_bulk_get(dev, data->num_clks, otp->clks);
+ if (ret)
+- return ret;
++ return dev_err_probe(dev, ret, "failed to get clocks\n");
+
+ otp->rst = devm_reset_control_array_get_exclusive(dev);
+ if (IS_ERR(otp->rst))
+- return PTR_ERR(otp->rst);
++ return dev_err_probe(dev, PTR_ERR(otp->rst),
++ "failed to get resets\n");
+
+ otp_config.size = data->size;
+ otp_config.priv = otp;
+ otp_config.dev = dev;
+- nvmem = devm_nvmem_register(dev, &otp_config);
+
+- return PTR_ERR_OR_ZERO(nvmem);
++ nvmem = devm_nvmem_register(dev, &otp_config);
++ if (IS_ERR(nvmem))
++ return dev_err_probe(dev, PTR_ERR(nvmem),
++ "failed to register nvmem device\n");
++ return 0;
+ }
+
+ static struct platform_driver rockchip_otp_driver = {
--- /dev/null
+From 8ab099fafbbc8c9607c399d21a774784a6cb8b45 Mon Sep 17 00:00:00 2001
+From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+Date: Sun, 11 Jun 2023 15:03:17 +0100
+Subject: [PATCH] nvmem: rockchip-otp: Add support for RK3588
+
+Add support for the OTP memory device found on the Rockchip RK3588 SoC.
+
+While here, remove the unnecessary 'void *' casts in the OF device ID
+table.
+
+Co-developed-by: Finley Xiao <finley.xiao@rock-chips.com>
+Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
+Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+Tested-by: Vincent Legoll <vincent.legoll@gmail.com>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Message-ID: <20230611140330.154222-14-srinivas.kandagatla@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/rockchip-otp.c | 78 +++++++++++++++++++++++++++++++++++-
+ 1 file changed, 76 insertions(+), 2 deletions(-)
+
+--- a/drivers/nvmem/rockchip-otp.c
++++ b/drivers/nvmem/rockchip-otp.c
+@@ -54,6 +54,19 @@
+
+ #define OTPC_TIMEOUT 10000
+
++/* RK3588 Register */
++#define RK3588_OTPC_AUTO_CTRL 0x04
++#define RK3588_OTPC_AUTO_EN 0x08
++#define RK3588_OTPC_INT_ST 0x84
++#define RK3588_OTPC_DOUT0 0x20
++#define RK3588_NO_SECURE_OFFSET 0x300
++#define RK3588_NBYTES 4
++#define RK3588_BURST_NUM 1
++#define RK3588_BURST_SHIFT 8
++#define RK3588_ADDR_SHIFT 16
++#define RK3588_AUTO_EN BIT(0)
++#define RK3588_RD_DONE BIT(1)
++
+ struct rockchip_data {
+ int size;
+ const char * const *clks;
+@@ -171,6 +184,52 @@ read_end:
+ return ret;
+ }
+
++static int rk3588_otp_read(void *context, unsigned int offset,
++ void *val, size_t bytes)
++{
++ struct rockchip_otp *otp = context;
++ unsigned int addr_start, addr_end, addr_len;
++ int ret, i = 0;
++ u32 data;
++ u8 *buf;
++
++ addr_start = round_down(offset, RK3588_NBYTES) / RK3588_NBYTES;
++ addr_end = round_up(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES;
++ addr_len = addr_end - addr_start;
++ addr_start += RK3588_NO_SECURE_OFFSET;
++
++ buf = kzalloc(array_size(addr_len, RK3588_NBYTES), GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ while (addr_len--) {
++ writel((addr_start << RK3588_ADDR_SHIFT) |
++ (RK3588_BURST_NUM << RK3588_BURST_SHIFT),
++ otp->base + RK3588_OTPC_AUTO_CTRL);
++ writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN);
++
++ ret = rockchip_otp_wait_status(otp, RK3588_OTPC_INT_ST,
++ RK3588_RD_DONE);
++ if (ret < 0) {
++ dev_err(otp->dev, "timeout during read setup\n");
++ goto read_end;
++ }
++
++ data = readl(otp->base + RK3588_OTPC_DOUT0);
++ memcpy(&buf[i], &data, RK3588_NBYTES);
++
++ i += RK3588_NBYTES;
++ addr_start++;
++ }
++
++ memcpy(val, buf + offset % RK3588_NBYTES, bytes);
++
++read_end:
++ kfree(buf);
++
++ return ret;
++}
++
+ static int rockchip_otp_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+ {
+@@ -213,14 +272,29 @@ static const struct rockchip_data px30_d
+ .reg_read = px30_otp_read,
+ };
+
++static const char * const rk3588_otp_clocks[] = {
++ "otp", "apb_pclk", "phy", "arb",
++};
++
++static const struct rockchip_data rk3588_data = {
++ .size = 0x400,
++ .clks = rk3588_otp_clocks,
++ .num_clks = ARRAY_SIZE(rk3588_otp_clocks),
++ .reg_read = rk3588_otp_read,
++};
++
+ static const struct of_device_id rockchip_otp_match[] = {
+ {
+ .compatible = "rockchip,px30-otp",
+- .data = (void *)&px30_data,
++ .data = &px30_data,
+ },
+ {
+ .compatible = "rockchip,rk3308-otp",
+- .data = (void *)&px30_data,
++ .data = &px30_data,
++ },
++ {
++ .compatible = "rockchip,rk3588-otp",
++ .data = &rk3588_data,
+ },
+ { /* sentinel */ },
+ };
--- /dev/null
+From 9734408969e978a1c0d5d752be63dd638288e374 Mon Sep 17 00:00:00 2001
+From: Michal Simek <michal.simek@amd.com>
+Date: Sun, 11 Jun 2023 15:03:23 +0100
+Subject: [PATCH] nvmem: zynqmp: Switch @xilinx.com emails to @amd.com
+
+@xilinx.com is still working but better to switch to new amd.com after
+AMD/Xilinx acquisition.
+
+Signed-off-by: Michal Simek <michal.simek@amd.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Message-ID: <20230611140330.154222-20-srinivas.kandagatla@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/zynqmp_nvmem.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvmem/zynqmp_nvmem.c
++++ b/drivers/nvmem/zynqmp_nvmem.c
+@@ -76,6 +76,6 @@ static struct platform_driver zynqmp_nvm
+
+ module_platform_driver(zynqmp_nvmem_driver);
+
+-MODULE_AUTHOR("Michal Simek <michal.simek@xilinx.com>, Nava kishore Manne <navam@xilinx.com>");
++MODULE_AUTHOR("Michal Simek <michal.simek@amd.com>, Nava kishore Manne <nava.kishore.manne@amd.com>");
+ MODULE_DESCRIPTION("ZynqMP NVMEM driver");
+ MODULE_LICENSE("GPL");
--- /dev/null
+From 22e9e6fcfb5042cb6d6c7874c459b034800092f1 Mon Sep 17 00:00:00 2001
+From: Peng Fan <peng.fan@nxp.com>
+Date: Sun, 11 Jun 2023 15:03:25 +0100
+Subject: [PATCH] nvmem: imx: support i.MX93 OCOTP
+
+Add i.MX93 OCOTP support. i.MX93 OCOTP has two parts: Fuse shadow
+block(fsb) and fuse managed by ELE. The FSB part could be directly
+accessed with MMIO, the ELE could only be accessed with ELE API.
+
+Currently the ELE API is not ready, so NULL function callback is used,
+but it was tested with downstream ELE API.
+
+Signed-off-by: Peng Fan <peng.fan@nxp.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Message-ID: <20230611140330.154222-22-srinivas.kandagatla@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/Kconfig | 9 ++
+ drivers/nvmem/Makefile | 2 +
+ drivers/nvmem/imx-ocotp-ele.c | 175 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 186 insertions(+)
+ create mode 100644 drivers/nvmem/imx-ocotp-ele.c
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -83,6 +83,15 @@ config NVMEM_IMX_OCOTP
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-imx-ocotp.
+
++config NVMEM_IMX_OCOTP_ELE
++ tristate "i.MX On-Chip OTP Controller support"
++ depends on ARCH_MXC || COMPILE_TEST
++ depends on HAS_IOMEM
++ depends on OF
++ help
++ This is a driver for the On-Chip OTP Controller (OCOTP)
++ available on i.MX SoCs which has ELE.
++
+ config NVMEM_IMX_OCOTP_SCU
+ tristate "i.MX8 SCU On-Chip OTP Controller support"
+ depends on IMX_SCU
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -18,6 +18,8 @@ obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-im
+ nvmem-imx-iim-y := imx-iim.o
+ obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-imx-ocotp.o
+ nvmem-imx-ocotp-y := imx-ocotp.o
++obj-$(CONFIG_NVMEM_IMX_OCOTP_ELE) += nvmem-imx-ocotp-ele.o
++nvmem-imx-ocotp-ele-y := imx-ocotp-ele.o
+ obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvmem-imx-ocotp-scu.o
+ nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o
+ obj-$(CONFIG_NVMEM_JZ4780_EFUSE) += nvmem_jz4780_efuse.o
+--- /dev/null
++++ b/drivers/nvmem/imx-ocotp-ele.c
+@@ -0,0 +1,175 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * i.MX9 OCOTP fusebox driver
++ *
++ * Copyright 2023 NXP
++ */
++
++#include <linux/device.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++enum fuse_type {
++ FUSE_FSB = 1,
++ FUSE_ELE = 2,
++ FUSE_INVALID = -1
++};
++
++struct ocotp_map_entry {
++ u32 start; /* start word */
++ u32 num; /* num words */
++ enum fuse_type type;
++};
++
++struct ocotp_devtype_data {
++ u32 reg_off;
++ char *name;
++ u32 size;
++ u32 num_entry;
++ u32 flag;
++ nvmem_reg_read_t reg_read;
++ struct ocotp_map_entry entry[];
++};
++
++struct imx_ocotp_priv {
++ struct device *dev;
++ void __iomem *base;
++ struct nvmem_config config;
++ struct mutex lock;
++ const struct ocotp_devtype_data *data;
++};
++
++static enum fuse_type imx_ocotp_fuse_type(void *context, u32 index)
++{
++ struct imx_ocotp_priv *priv = context;
++ const struct ocotp_devtype_data *data = priv->data;
++ u32 start, end;
++ int i;
++
++ for (i = 0; i < data->num_entry; i++) {
++ start = data->entry[i].start;
++ end = data->entry[i].start + data->entry[i].num;
++
++ if (index >= start && index < end)
++ return data->entry[i].type;
++ }
++
++ return FUSE_INVALID;
++}
++
++static int imx_ocotp_reg_read(void *context, unsigned int offset, void *val, size_t bytes)
++{
++ struct imx_ocotp_priv *priv = context;
++ void __iomem *reg = priv->base + priv->data->reg_off;
++ u32 count, index, num_bytes;
++ enum fuse_type type;
++ u32 *buf;
++ void *p;
++ int i;
++
++ index = offset;
++ num_bytes = round_up(bytes, 4);
++ count = num_bytes >> 2;
++
++ if (count > ((priv->data->size >> 2) - index))
++ count = (priv->data->size >> 2) - index;
++
++ p = kzalloc(num_bytes, GFP_KERNEL);
++ if (!p)
++ return -ENOMEM;
++
++ mutex_lock(&priv->lock);
++
++ buf = p;
++
++ for (i = index; i < (index + count); i++) {
++ type = imx_ocotp_fuse_type(context, i);
++ if (type == FUSE_INVALID || type == FUSE_ELE) {
++ *buf++ = 0;
++ continue;
++ }
++
++ *buf++ = readl_relaxed(reg + (i << 2));
++ }
++
++ memcpy(val, (u8 *)p, bytes);
++
++ mutex_unlock(&priv->lock);
++
++ kfree(p);
++
++ return 0;
++};
++
++static int imx_ele_ocotp_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct imx_ocotp_priv *priv;
++ struct nvmem_device *nvmem;
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->data = of_device_get_match_data(dev);
++
++ priv->base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(priv->base))
++ return PTR_ERR(priv->base);
++
++ priv->config.dev = dev;
++ priv->config.name = "ELE-OCOTP";
++ priv->config.id = NVMEM_DEVID_AUTO;
++ priv->config.owner = THIS_MODULE;
++ priv->config.size = priv->data->size;
++ priv->config.reg_read = priv->data->reg_read;
++ priv->config.word_size = 4;
++ priv->config.stride = 1;
++ priv->config.priv = priv;
++ priv->config.read_only = true;
++ mutex_init(&priv->lock);
++
++ nvmem = devm_nvmem_register(dev, &priv->config);
++ if (IS_ERR(nvmem))
++ return PTR_ERR(nvmem);
++
++ return 0;
++}
++
++static const struct ocotp_devtype_data imx93_ocotp_data = {
++ .reg_off = 0x8000,
++ .reg_read = imx_ocotp_reg_read,
++ .size = 2048,
++ .num_entry = 6,
++ .entry = {
++ { 0, 52, FUSE_FSB },
++ { 63, 1, FUSE_ELE},
++ { 128, 16, FUSE_ELE },
++ { 182, 1, FUSE_ELE },
++ { 188, 1, FUSE_ELE },
++ { 312, 200, FUSE_FSB }
++ },
++};
++
++static const struct of_device_id imx_ele_ocotp_dt_ids[] = {
++ { .compatible = "fsl,imx93-ocotp", .data = &imx93_ocotp_data, },
++ {},
++};
++MODULE_DEVICE_TABLE(of, imx_ele_ocotp_dt_ids);
++
++static struct platform_driver imx_ele_ocotp_driver = {
++ .driver = {
++ .name = "imx_ele_ocotp",
++ .of_match_table = imx_ele_ocotp_dt_ids,
++ },
++ .probe = imx_ele_ocotp_probe,
++};
++module_platform_driver(imx_ele_ocotp_driver);
++
++MODULE_DESCRIPTION("i.MX OCOTP/ELE driver");
++MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
++MODULE_LICENSE("GPL");
--- /dev/null
+From 27f699e578b1a72df89dfa3bc42e093a01dc8d10 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Sun, 11 Jun 2023 15:03:29 +0100
+Subject: [PATCH] nvmem: core: add support for fixed cells *layout*
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This adds support for the "fixed-layout" NVMEM layout binding. It allows
+defining NVMEM cells in a layout DT node named "nvmem-layout".
+
+While NVMEM subsystem supports layout drivers it has been discussed that
+"fixed-layout" may actually be supperted internally. It's because:
+1. It's a very basic layout
+2. It allows sharing code with legacy syntax parsing
+3. It's safer for soc_device_match() due to -EPROBE_DEFER
+4. This will make the syntax transition easier
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Reviewed-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Message-ID: <20230611140330.154222-26-srinivas.kandagatla@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 32 +++++++++++++++++++++++++++++---
+ 1 file changed, 29 insertions(+), 3 deletions(-)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -696,7 +696,7 @@ static int nvmem_validate_keepouts(struc
+ return 0;
+ }
+
+-static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
++static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np)
+ {
+ struct nvmem_layout *layout = nvmem->layout;
+ struct device *dev = &nvmem->dev;
+@@ -704,7 +704,7 @@ static int nvmem_add_cells_from_of(struc
+ const __be32 *addr;
+ int len, ret;
+
+- for_each_child_of_node(dev->of_node, child) {
++ for_each_child_of_node(np, child) {
+ struct nvmem_cell_info info = {0};
+
+ addr = of_get_property(child, "reg", &len);
+@@ -742,6 +742,28 @@ static int nvmem_add_cells_from_of(struc
+ return 0;
+ }
+
++static int nvmem_add_cells_from_legacy_of(struct nvmem_device *nvmem)
++{
++ return nvmem_add_cells_from_dt(nvmem, nvmem->dev.of_node);
++}
++
++static int nvmem_add_cells_from_fixed_layout(struct nvmem_device *nvmem)
++{
++ struct device_node *layout_np;
++ int err = 0;
++
++ layout_np = of_nvmem_layout_get_container(nvmem);
++ if (!layout_np)
++ return 0;
++
++ if (of_device_is_compatible(layout_np, "fixed-layout"))
++ err = nvmem_add_cells_from_dt(nvmem, layout_np);
++
++ of_node_put(layout_np);
++
++ return err;
++}
++
+ int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner)
+ {
+ layout->owner = owner;
+@@ -972,7 +994,7 @@ struct nvmem_device *nvmem_register(cons
+ if (rval)
+ goto err_remove_cells;
+
+- rval = nvmem_add_cells_from_of(nvmem);
++ rval = nvmem_add_cells_from_legacy_of(nvmem);
+ if (rval)
+ goto err_remove_cells;
+
+@@ -982,6 +1004,10 @@ struct nvmem_device *nvmem_register(cons
+ if (rval)
+ goto err_remove_cells;
+
++ rval = nvmem_add_cells_from_fixed_layout(nvmem);
++ if (rval)
++ goto err_remove_cells;
++
+ rval = nvmem_add_cells_from_layout(nvmem);
+ if (rval)
+ goto err_remove_cells;
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Thu, 6 Apr 2023 12:46:16 +0200
-Subject: [PATCH] nvmem: brcm_nvram: add .read_post_process() for MACs
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-1. Parse ASCII MAC format into byte based
-2. Calculate relative addresses based on index argument
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
----
- drivers/nvmem/Kconfig | 1 +
- drivers/nvmem/brcm_nvram.c | 28 ++++++++++++++++++++++++++++
- 2 files changed, 29 insertions(+)
-
---- a/drivers/nvmem/Kconfig
-+++ b/drivers/nvmem/Kconfig
-@@ -55,6 +55,7 @@ config NVMEM_BRCM_NVRAM
- tristate "Broadcom's NVRAM support"
- depends on ARCH_BCM_5301X || COMPILE_TEST
- depends on HAS_IOMEM
-+ select GENERIC_NET_UTILS
- help
- This driver provides support for Broadcom's NVRAM that can be accessed
- using I/O mapping.
---- a/drivers/nvmem/brcm_nvram.c
-+++ b/drivers/nvmem/brcm_nvram.c
-@@ -4,6 +4,8 @@
- */
-
- #include <linux/bcm47xx_nvram.h>
-+#include <linux/etherdevice.h>
-+#include <linux/if_ether.h>
- #include <linux/io.h>
- #include <linux/mod_devicetable.h>
- #include <linux/module.h>
-@@ -42,6 +44,25 @@ static int brcm_nvram_read(void *context
- return 0;
- }
-
-+static int brcm_nvram_read_post_process_macaddr(void *context, const char *id, int index,
-+ unsigned int offset, void *buf, size_t bytes)
-+{
-+ u8 mac[ETH_ALEN];
-+
-+ if (bytes != 3 * ETH_ALEN - 1)
-+ return -EINVAL;
-+
-+ if (!mac_pton(buf, mac))
-+ return -EINVAL;
-+
-+ if (index)
-+ eth_addr_add(mac, index);
-+
-+ ether_addr_copy(buf, mac);
-+
-+ return 0;
-+}
-+
- static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data,
- size_t len)
- {
-@@ -75,6 +96,13 @@ static int brcm_nvram_add_cells(struct b
- priv->cells[idx].offset = value - (char *)data;
- priv->cells[idx].bytes = strlen(value);
- priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
-+ if (!strcmp(var, "et0macaddr") ||
-+ !strcmp(var, "et1macaddr") ||
-+ !strcmp(var, "et2macaddr")) {
-+ priv->cells[idx].raw_len = strlen(value);
-+ priv->cells[idx].bytes = ETH_ALEN;
-+ priv->cells[idx].read_post_process = brcm_nvram_read_post_process_macaddr;
-+ }
- }
-
- return 0;
CONFIG_NVMEM=y
# CONFIG_NVMEM_IMX_IIM is not set
CONFIG_NVMEM_IMX_OCOTP=y
+# CONFIG_NVMEM_IMX_OCOTP_ELE is not set
# CONFIG_NVMEM_SNVS_LPGPR is not set
CONFIG_NVMEM_SYSFS=y
CONFIG_OF=y
CONFIG_NTFS_FS=y
CONFIG_NVMEM=y
# CONFIG_NVMEM_IMX_IIM is not set
+# CONFIG_NVMEM_IMX_OCOTP_ELE is not set
# CONFIG_NVMEM_SNVS_LPGPR is not set
# CONFIG_NVMEM_SPMI_SDAM is not set
CONFIG_NVMEM_SYSFS=y