kernel: backport NVMEM patches queued for the v6.5

This includes some driver changes and support for fixed cells layout.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
This commit is contained in:
Rafał Miłecki 2023-06-16 09:16:39 +02:00
parent b57703264f
commit 07bdc55515
24 changed files with 1838 additions and 2 deletions

View File

@ -0,0 +1,31 @@
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,
};

View File

@ -0,0 +1,71 @@
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;

View File

@ -1,5 +1,6 @@
From 73bcd133c910bff3b6d3b3834d0d14be9444e90a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
Date: Thu, 6 Apr 2023 12:46:16 +0200
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
@ -9,6 +10,9 @@ Content-Transfer-Encoding: 8bit
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 ++++++++++++++++++++++++++++

View File

@ -0,0 +1,166 @@
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;

View File

@ -0,0 +1,62 @@
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;

View File

@ -0,0 +1,31 @@
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);

View File

@ -0,0 +1,71 @@
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 = {

View File

@ -0,0 +1,129 @@
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 */ },
};

View File

@ -0,0 +1,26 @@
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");

View File

@ -0,0 +1,230 @@
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");

View File

@ -0,0 +1,96 @@
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;

View File

@ -0,0 +1,31 @@
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,
};

View File

@ -0,0 +1,71 @@
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;

View File

@ -1,5 +1,6 @@
From 73bcd133c910bff3b6d3b3834d0d14be9444e90a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
Date: Thu, 6 Apr 2023 12:46:16 +0200
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
@ -9,6 +10,9 @@ Content-Transfer-Encoding: 8bit
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 ++++++++++++++++++++++++++++

View File

@ -0,0 +1,166 @@
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;

View File

@ -0,0 +1,62 @@
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;

View File

@ -0,0 +1,31 @@
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);

View File

@ -0,0 +1,71 @@
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 = {

View File

@ -0,0 +1,129 @@
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 */ },
};

View File

@ -0,0 +1,26 @@
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");

View File

@ -0,0 +1,230 @@
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");

View File

@ -0,0 +1,96 @@
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;

View File

@ -295,6 +295,7 @@ CONFIG_NR_CPUS=4
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

View File

@ -413,6 +413,7 @@ CONFIG_NR_CPUS=16
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