From: Frieder Schrempf <frieder@fris.de>
To: Peng Fan <peng.fan@nxp.com>, Pankaj Gupta <pankaj.gupta@nxp.com>,
linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev,
linux-kernel@vger.kernel.org,
Sascha Hauer <s.hauer@pengutronix.de>,
Shawn Guo <shawnguo@kernel.org>
Cc: Frieder Schrempf <frieder.schrempf@kontron.de>,
Fabio Estevam <festevam@gmail.com>, Frank Li <Frank.Li@nxp.com>,
Pengutronix Kernel Team <kernel@pengutronix.de>
Subject: [RFC PATCH 1/5] firmware: imx: ele: Add API functions for OCOTP fuse access
Date: Wed, 16 Apr 2025 16:26:20 +0200 [thread overview]
Message-ID: <20250416142715.1042363-2-frieder@fris.de> (raw)
In-Reply-To: <20250416142715.1042363-1-frieder@fris.de>
From: Frieder Schrempf <frieder.schrempf@kontron.de>
The ELE S400 API provides read and write access to the OCOTP fuse
registers. This adds the necessary API functions imx_se_read_fuse()
and imx_se_write_fuse() to be used by other drivers such as the
OCOTP S400 NVMEM driver.
This is ported from the downstream vendor kernel.
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
drivers/firmware/imx/ele_base_msg.c | 122 ++++++++++++++++++++++++++++
drivers/firmware/imx/ele_base_msg.h | 8 ++
include/linux/firmware/imx/se_api.h | 3 +
3 files changed, 133 insertions(+)
diff --git a/drivers/firmware/imx/ele_base_msg.c b/drivers/firmware/imx/ele_base_msg.c
index bed1a0459d8d..0dfd4d2fef5a 100644
--- a/drivers/firmware/imx/ele_base_msg.c
+++ b/drivers/firmware/imx/ele_base_msg.c
@@ -311,3 +311,125 @@ int ele_debug_dump(struct se_if_priv *priv)
return ret;
}
+
+static int ele_read_fuse(struct se_if_priv *priv, uint16_t fuse_id, u32 *value)
+{
+ struct se_api_msg *tx_msg __free(kfree) = NULL;
+ struct se_api_msg *rx_msg __free(kfree) = NULL;
+ int rx_msg_sz = ELE_READ_FUSE_RSP_MSG_SZ;
+ int ret = 0;
+
+ if (!priv)
+ return -EINVAL;
+
+ tx_msg = kzalloc(ELE_READ_FUSE_REQ_MSG_SZ, GFP_KERNEL);
+ if (!tx_msg)
+ return -ENOMEM;
+
+ rx_msg = kzalloc(rx_msg_sz, GFP_KERNEL);
+ if (!rx_msg)
+ return -ENOMEM;
+
+ ret = se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header,
+ ELE_READ_FUSE_REQ, ELE_READ_FUSE_REQ_MSG_SZ,
+ true);
+ if (ret)
+ return ret;
+
+ tx_msg->data[0] = fuse_id;
+
+ ret = ele_msg_send_rcv(priv->priv_dev_ctx, tx_msg,
+ ELE_READ_FUSE_REQ_MSG_SZ, rx_msg, rx_msg_sz);
+ if (ret < 0)
+ return ret;
+
+ ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_READ_FUSE_REQ,
+ rx_msg_sz, true);
+ if (ret)
+ return ret;
+
+ *value = rx_msg->data[1];
+
+ return 0;
+}
+
+/**
+ * imx_se_read_fuse() - API to request SE-FW to read the fuse(s) value.
+ * @void *se_if_data: refs to data attached to the se interface.
+ * @uint16_t fuse_id: Fuse identifier to read.
+ * @u32 *value: unsigned integer array to store the fuse values.
+ *
+ * Secure enclave like EdgeLock Enclave, manages the fuse. This API
+ * requests the FW to read the fuses. FW responds with the read
+ * values.
+ *
+ * Context:
+ *
+ * Return value:
+ * 0, means success.
+ * < 0, means failure.
+ */
+int imx_se_read_fuse(void *se_if_data, uint16_t fuse_id, u32 *value)
+{
+ return ele_read_fuse((struct se_if_priv *)se_if_data, fuse_id, value);
+}
+EXPORT_SYMBOL_GPL(imx_se_read_fuse);
+
+static int ele_write_fuse(struct se_if_priv *priv, uint16_t fuse_id, u32 value)
+{
+ struct se_api_msg *tx_msg __free(kfree) = NULL;
+ struct se_api_msg *rx_msg __free(kfree) = NULL;
+ int ret = 0;
+
+ if (!priv)
+ return -EINVAL;
+
+ tx_msg = kzalloc(ELE_WRITE_FUSE_REQ_MSG_SZ, GFP_KERNEL);
+ if (!tx_msg)
+ return -ENOMEM;
+
+ rx_msg = kzalloc(ELE_WRITE_FUSE_RSP_MSG_SZ, GFP_KERNEL);
+ if (!rx_msg)
+ return -ENOMEM;
+
+ ret = se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header,
+ ELE_WRITE_FUSE, ELE_WRITE_FUSE_REQ_MSG_SZ,
+ true);
+ if (ret)
+ return ret;
+
+ tx_msg->data[0] = (32 << 16) | (fuse_id << 5);
+ tx_msg->data[1] = value;
+
+ ret = ele_msg_send_rcv(priv->priv_dev_ctx, tx_msg,
+ ELE_WRITE_FUSE_REQ_MSG_SZ, rx_msg,
+ ELE_WRITE_FUSE_RSP_MSG_SZ);
+ if (ret < 0)
+ return ret;
+
+ ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_WRITE_FUSE,
+ ELE_WRITE_FUSE_RSP_MSG_SZ, true);
+
+ return ret;
+}
+
+/**
+ * imx_se_write_fuse() - API to request SE-FW to write to fuses.
+ * @void *se_if_data: refs to data attached to the se interface.
+ * @uint16_t fuse_id: Fuse identifier to write to.
+ * @u32 value: unsigned integer value that to be written to the fuse.
+ *
+ * Secure enclave like EdgeLock Enclave, manages the fuse. This API
+ * requests the FW to write the fuse with the given value.
+ *
+ * Context:
+ *
+ * Return value:
+ * 0, means success.
+ * < 0, means failure.
+ */
+int imx_se_write_fuse(void *se_if_data, uint16_t fuse_id, u32 value)
+{
+ return ele_write_fuse((struct se_if_priv *)se_if_data, fuse_id, value);
+}
+EXPORT_SYMBOL_GPL(imx_se_write_fuse);
diff --git a/drivers/firmware/imx/ele_base_msg.h b/drivers/firmware/imx/ele_base_msg.h
index dd89412f485e..22f553cdbc33 100644
--- a/drivers/firmware/imx/ele_base_msg.h
+++ b/drivers/firmware/imx/ele_base_msg.h
@@ -19,6 +19,14 @@
#define ELE_GET_INFO_REQ_MSG_SZ 0x10
#define ELE_GET_INFO_RSP_MSG_SZ 0x08
+#define ELE_WRITE_FUSE 0xD6
+#define ELE_WRITE_FUSE_REQ_MSG_SZ 12
+#define ELE_WRITE_FUSE_RSP_MSG_SZ 12
+
+#define ELE_READ_FUSE_REQ 0x97
+#define ELE_READ_FUSE_REQ_MSG_SZ 0x08
+#define ELE_READ_FUSE_RSP_MSG_SZ 0x0C
+
#define MAX_UID_SIZE (16)
#define DEV_GETINFO_ROM_PATCH_SHA_SZ (32)
#define DEV_GETINFO_FW_SHA_SZ (32)
diff --git a/include/linux/firmware/imx/se_api.h b/include/linux/firmware/imx/se_api.h
index b1c4c9115d7b..9503b9363593 100644
--- a/include/linux/firmware/imx/se_api.h
+++ b/include/linux/firmware/imx/se_api.h
@@ -11,4 +11,7 @@
#define SOC_ID_OF_IMX8ULP 0x084d
#define SOC_ID_OF_IMX93 0x9300
+int imx_se_write_fuse(void *se_if_data, uint16_t fuse_id, u32 value);
+int imx_se_read_fuse(void *se_if_data, uint16_t fuse_id, u32 *value);
+
#endif /* __SE_API_H__ */
--
2.49.0
next prev parent reply other threads:[~2025-04-16 14:37 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-16 14:26 [RFC PATCH 0/5] Add NVMEM driver for i.MX93 OTP access through ELE Frieder Schrempf
2025-04-16 14:26 ` Frieder Schrempf [this message]
2025-04-16 14:26 ` [RFC PATCH 2/5] nvmem: Add i.MX OCOTP fuse driver using ELE S400 API Frieder Schrempf
2025-04-16 14:26 ` [RFC PATCH 3/5] arm64: dts: imx93: Add node for EdgeLock Enclave (ELE) firmware driver Frieder Schrempf
2025-04-16 14:26 ` [RFC PATCH 4/5] arm64: dts: imx93: Add node for OCOTP S400 NVMEM driver Frieder Schrempf
2025-04-16 14:26 ` [RFC PATCH 5/5] arm64: dts: imx93-kontron: Add DMA memory region for ELE firmware Frieder Schrempf
2025-04-22 6:30 ` [RFC PATCH 0/5] Add NVMEM driver for i.MX93 OTP access through ELE Peng Fan
2025-04-22 7:33 ` Frieder Schrempf
2025-04-22 6:40 ` Arnd Bergmann
2025-04-22 7:37 ` Frieder Schrempf
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=20250416142715.1042363-2-frieder@fris.de \
--to=frieder@fris.de \
--cc=Frank.Li@nxp.com \
--cc=festevam@gmail.com \
--cc=frieder.schrempf@kontron.de \
--cc=imx@lists.linux.dev \
--cc=kernel@pengutronix.de \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pankaj.gupta@nxp.com \
--cc=peng.fan@nxp.com \
--cc=s.hauer@pengutronix.de \
--cc=shawnguo@kernel.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.