From: Alexander Stein <alexander.stein@ew.tq-group.com>
To: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Shawn Guo <shawnguo@kernel.org>,
Sascha Hauer <s.hauer@pengutronix.de>,
Pengutronix Kernel Team <kernel@pengutronix.de>,
Fabio Estevam <festevam@gmail.com>,
linux-arm-kernel@lists.infradead.org
Cc: devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, Peng Fan <peng.fan@nxp.com>,
"Peng Fan (OSS)" <peng.fan@oss.nxp.com>
Subject: Re: [PATCH v5 2/2] nvmem: imx-ocotp-ele: Support accessing controller for i.MX9
Date: Wed, 08 Jan 2025 11:15:40 +0100 [thread overview]
Message-ID: <3823142.MHq7AAxBmi@steina-w> (raw)
In-Reply-To: <20250108-imx-ocotp-v5-2-a6d90e18ebe9@nxp.com>
Hi Peng,
Am Mittwoch, 8. Januar 2025, 08:00:18 CET schrieb Peng Fan (OSS):
> From: Peng Fan <peng.fan@nxp.com>
>
> i.MX9 OCOTP supports a specific peripheral or function being fused
> which means disabled, so
> - Introduce ocotp_access_gates to be container of efuse gate info
> - Iterate all nodes to check accessing permission. If not
> allowed to be accessed, detach the node
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
> drivers/nvmem/imx-ocotp-ele.c | 172 +++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 171 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/nvmem/imx-ocotp-ele.c b/drivers/nvmem/imx-ocotp-ele.c
> index ca6dd71d8a2e29888c6e556aaea116c1a967cb5f..5ea6d959ce38760eeed44a989992fb35c462c0b4 100644
> --- a/drivers/nvmem/imx-ocotp-ele.c
> +++ b/drivers/nvmem/imx-ocotp-ele.c
> @@ -5,6 +5,8 @@
> * Copyright 2023 NXP
> */
>
> +#include <dt-bindings/nvmem/fsl,imx93-ocotp.h>
> +#include <dt-bindings/nvmem/fsl,imx95-ocotp.h>
> #include <linux/device.h>
> #include <linux/io.h>
> #include <linux/module.h>
> @@ -27,6 +29,7 @@ struct ocotp_map_entry {
> };
>
> struct ocotp_devtype_data {
> + const struct ocotp_access_gates *access_gates;
> u32 reg_off;
> char *name;
> u32 size;
> @@ -36,6 +39,20 @@ struct ocotp_devtype_data {
> struct ocotp_map_entry entry[];
> };
>
> +#define OCOTP_MAX_NUM_GATE_WORDS 4
> +
> +struct access_gate {
> + u32 word;
> + u32 mask;
> +};
> +
> +struct ocotp_access_gates {
> + u32 num_words;
> + u32 words[OCOTP_MAX_NUM_GATE_WORDS];
> + u32 num_gates;
> + struct access_gate *gates;
> +};
> +
> struct imx_ocotp_priv {
> struct device *dev;
> void __iomem *base;
> @@ -131,6 +148,82 @@ static void imx_ocotp_fixup_dt_cell_info(struct nvmem_device *nvmem,
> cell->read_post_process = imx_ocotp_cell_pp;
> }
>
> +static int imx_ele_ocotp_check_access(struct imx_ocotp_priv *priv, u32 id)
> +{
> + const struct ocotp_access_gates *access_gates = priv->data->access_gates;
> + void __iomem *reg = priv->base + priv->data->reg_off;
> + u32 word, mask, val;
> +
> + if (id >= access_gates->num_gates) {
> + dev_err(priv->config.dev, "Index %d too large\n", id);
> + return -EACCES;
> + }
> +
> + word = access_gates->gates[id].word;
> + mask = access_gates->gates[id].mask;
> +
> + reg = priv->base + priv->data->reg_off + (word << 2);
> + val = readl(reg);
> +
> + dev_dbg(priv->config.dev, "id:%d word:%d mask:0x%08x\n", id, word, mask);
> + /* true means not allow access */
> + if (val & mask)
> + return -EACCES;
> +
> + return 0;
> +}
> +
> +static int imx_ele_ocotp_grant_access(struct imx_ocotp_priv *priv, struct device_node *parent)
> +{
> + struct device *dev = priv->config.dev;
> +
> + for_each_available_child_of_node_scoped(parent, child) {
> + struct of_phandle_args args;
> + u32 id, idx = 0;
> +
> + while (!of_parse_phandle_with_args(child, "access-controllers",
> + "#access-controller-cells",
> + idx++, &args)) {
> + of_node_put(args.np);
> + if (args.np != dev->of_node)
> + continue;
> +
> + /* Only support one cell */
> + if (args.args_count != 1) {
> + dev_err(dev, "wrong args count\n");
> + continue;
> + }
> +
> + id = args.args[0];
> +
> + dev_dbg(dev, "Checking node: %pOF gate: %d\n", child, id);
> +
> + if (imx_ele_ocotp_check_access(priv, id)) {
> + of_detach_node(child);
> + dev_info(dev, "%pOF: Not granted, device driver will not be probed\n",
> + child);
> + }
> + }
> +
> + imx_ele_ocotp_grant_access(priv, child);
> + }
> +
> + return 0;
> +}
> +
> +static int imx_ele_ocotp_access_control(struct imx_ocotp_priv *priv)
> +{
> + struct device_node *root __free(device_node) = of_find_node_by_path("/");
> +
> + if (!priv->data->access_gates)
> + return 0;
> +
> + /* This should never happen */
> + WARN_ON(!root);
> +
> + return imx_ele_ocotp_grant_access(priv, root);
> +}
> +
> static int imx_ele_ocotp_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> @@ -161,14 +254,45 @@ static int imx_ele_ocotp_probe(struct platform_device *pdev)
> priv->config.fixup_dt_cell_info = imx_ocotp_fixup_dt_cell_info;
> mutex_init(&priv->lock);
>
> + platform_set_drvdata(pdev, priv);
> +
> nvmem = devm_nvmem_register(dev, &priv->config);
> if (IS_ERR(nvmem))
> return PTR_ERR(nvmem);
>
> - return 0;
> +
> + return imx_ele_ocotp_access_control(priv);
In [1] you mentioned devlink should solve the probe order. How does this
play when the driver is compiled in (e.g. ethernet for NFS boot) but
this OCOTP driver is just a module?
I'm not well versed with devlink, but is
> access-controllers = <&ocotp IMX93_OCOTP_ENET1_GATE>;
already enough to create that link?
Best regards,
Alexander
> }
>
> +struct access_gate imx93_access_gate[] = {
> + [IMX93_OCOTP_NPU_GATE] = { .word = 19, .mask = BIT(13) },
> + [IMX93_OCOTP_A550_GATE] = { .word = 19, .mask = BIT(14) },
> + [IMX93_OCOTP_A551_GATE] = { .word = 19, .mask = BIT(15) },
> + [IMX93_OCOTP_M33_GATE] = { .word = 19, .mask = BIT(24) },
> + [IMX93_OCOTP_CAN1_FD_GATE] = { .word = 19, .mask = BIT(28) },
> + [IMX93_OCOTP_CAN2_FD_GATE] = { .word = 19, .mask = BIT(29) },
> + [IMX93_OCOTP_CAN1_GATE] = { .word = 19, .mask = BIT(30) },
> + [IMX93_OCOTP_CAN2_GATE] = { .word = 19, .mask = BIT(31) },
> + [IMX93_OCOTP_USB1_GATE] = { .word = 20, .mask = BIT(3) },
> + [IMX93_OCOTP_USB2_GATE] = { .word = 20, .mask = BIT(4) },
> + [IMX93_OCOTP_ENET1_GATE] = { .word = 20, .mask = BIT(5) },
> + [IMX93_OCOTP_ENET2_GATE] = { .word = 20, .mask = BIT(6) },
> + [IMX93_OCOTP_PXP_GATE] = { .word = 20, .mask = BIT(10) },
> + [IMX93_OCOTP_MIPI_CSI1_GATE] = { .word = 20, .mask = BIT(17) },
> + [IMX93_OCOTP_MIPI_DSI1_GATE] = { .word = 20, .mask = BIT(19) },
> + [IMX93_OCOTP_LVDS1_GATE] = { .word = 20, .mask = BIT(24) },
> + [IMX93_OCOTP_ADC1_GATE] = { .word = 21, .mask = BIT(7) },
> +};
> +
> +static const struct ocotp_access_gates imx93_access_gates_info = {
> + .num_words = 3,
> + .words = {19, 20, 21},
> + .num_gates = ARRAY_SIZE(imx93_access_gate),
> + .gates = imx93_access_gate,
> +};
> +
> static const struct ocotp_devtype_data imx93_ocotp_data = {
> + .access_gates = &imx93_access_gates_info,
> .reg_off = 0x8000,
> .reg_read = imx_ocotp_reg_read,
> .size = 2048,
> @@ -183,7 +307,53 @@ static const struct ocotp_devtype_data imx93_ocotp_data = {
> },
> };
>
> +struct access_gate imx95_access_gate[] = {
> + [IMX95_OCOTP_CANFD1_GATE] = { .word = 17, .mask = BIT(20) },
> + [IMX95_OCOTP_CANFD2_GATE] = { .word = 17, .mask = BIT(21) },
> + [IMX95_OCOTP_CANFD3_GATE] = { .word = 17, .mask = BIT(22) },
> + [IMX95_OCOTP_CANFD4_GATE] = { .word = 17, .mask = BIT(23) },
> + [IMX95_OCOTP_CANFD5_GATE] = { .word = 17, .mask = BIT(24) },
> + [IMX95_OCOTP_CAN1_GATE] = { .word = 17, .mask = BIT(25) },
> + [IMX95_OCOTP_CAN2_GATE] = { .word = 17, .mask = BIT(26) },
> + [IMX95_OCOTP_CAN3_GATE] = { .word = 17, .mask = BIT(27) },
> + [IMX95_OCOTP_CAN4_GATE] = { .word = 17, .mask = BIT(28) },
> + [IMX95_OCOTP_CAN5_GATE] = { .word = 17, .mask = BIT(29) },
> + [IMX95_OCOTP_NPU_GATE] = { .word = 18, .mask = BIT(0) },
> + [IMX95_OCOTP_A550_GATE] = { .word = 18, .mask = BIT(1) },
> + [IMX95_OCOTP_A551_GATE] = { .word = 18, .mask = BIT(2) },
> + [IMX95_OCOTP_A552_GATE] = { .word = 18, .mask = BIT(3) },
> + [IMX95_OCOTP_A553_GATE] = { .word = 18, .mask = BIT(4) },
> + [IMX95_OCOTP_A554_GATE] = { .word = 18, .mask = BIT(5) },
> + [IMX95_OCOTP_A555_GATE] = { .word = 18, .mask = BIT(6) },
> + [IMX95_OCOTP_M7_GATE] = { .word = 18, .mask = BIT(9) },
> + [IMX95_OCOTP_DCSS_GATE] = { .word = 18, .mask = BIT(22) },
> + [IMX95_OCOTP_LVDS1_GATE] = { .word = 18, .mask = BIT(27) },
> + [IMX95_OCOTP_ISP_GATE] = { .word = 18, .mask = BIT(29) },
> + [IMX95_OCOTP_USB1_GATE] = { .word = 19, .mask = BIT(2) },
> + [IMX95_OCOTP_USB2_GATE] = { .word = 19, .mask = BIT(3) },
> + [IMX95_OCOTP_NETC_GATE] = { .word = 19, .mask = BIT(4) },
> + [IMX95_OCOTP_PCIE1_GATE] = { .word = 19, .mask = BIT(6) },
> + [IMX95_OCOTP_PCIE2_GATE] = { .word = 19, .mask = BIT(7) },
> + [IMX95_OCOTP_ADC1_GATE] = { .word = 19, .mask = BIT(8) },
> + [IMX95_OCOTP_EARC_RX_GATE] = { .word = 19, .mask = BIT(11) },
> + [IMX95_OCOTP_GPU3D_GATE] = { .word = 19, .mask = BIT(16) },
> + [IMX95_OCOTP_VPU_GATE] = { .word = 19, .mask = BIT(17) },
> + [IMX95_OCOTP_JPEG_ENC_GATE] = { .word = 19, .mask = BIT(18) },
> + [IMX95_OCOTP_JPEG_DEC_GATE] = { .word = 19, .mask = BIT(19) },
> + [IMX95_OCOTP_MIPI_CSI1_GATE] = { .word = 19, .mask = BIT(21) },
> + [IMX95_OCOTP_MIPI_CSI2_GATE] = { .word = 19, .mask = BIT(22) },
> + [IMX95_OCOTP_MIPI_DSI1_GATE] = { .word = 19, .mask = BIT(23) },
> +};
> +
> +static const struct ocotp_access_gates imx95_access_gates_info = {
> + .num_words = 3,
> + .words = {17, 18, 19},
> + .num_gates = ARRAY_SIZE(imx95_access_gate),
> + .gates = imx95_access_gate,
> +};
> +
> static const struct ocotp_devtype_data imx95_ocotp_data = {
> + .access_gates = &imx95_access_gates_info,
> .reg_off = 0x8000,
> .reg_read = imx_ocotp_reg_read,
> .size = 2048,
>
>
--
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
http://www.tq-group.com/
next prev parent reply other threads:[~2025-01-08 10:15 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-08 7:00 [PATCH v5 0/2] Make i.MX9 OCOTP work as accessing controller Peng Fan (OSS)
2025-01-08 7:00 ` [PATCH v5 1/2] dt-bindings: nvmem: imx-ocotp: Introduce #access-controller-cells Peng Fan (OSS)
2025-01-08 7:00 ` [PATCH v5 2/2] nvmem: imx-ocotp-ele: Support accessing controller for i.MX9 Peng Fan (OSS)
2025-01-08 10:15 ` Alexander Stein [this message]
2025-01-09 3:34 ` Peng Fan
2025-01-09 10:34 ` Alexander Stein
2025-01-11 12:41 ` Peng Fan
2025-01-13 12:16 ` Alexander Stein
2025-01-14 8:35 ` Peng Fan
2025-01-15 6:56 ` Alexander Stein
2025-01-16 2:09 ` Peng Fan
2025-01-16 15:47 ` Alexander Stein
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3823142.MHq7AAxBmi@steina-w \
--to=alexander.stein@ew.tq-group.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=festevam@gmail.com \
--cc=imx@lists.linux.dev \
--cc=kernel@pengutronix.de \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=peng.fan@nxp.com \
--cc=peng.fan@oss.nxp.com \
--cc=robh@kernel.org \
--cc=s.hauer@pengutronix.de \
--cc=shawnguo@kernel.org \
--cc=srinivas.kandagatla@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.