mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 1/5] ARM: i.MX: ele: move ELE_READ_SHADOW_REQ definition
@ 2024-03-11 10:21 Sascha Hauer
  2024-03-11 10:21 ` [PATCH 2/5] ARM: i.MX: ele: add function comments Sascha Hauer
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Sascha Hauer @ 2024-03-11 10:21 UTC (permalink / raw)
  To: Barebox List

The ELE request defines are in include/mach/imx/ele.h, move definition
of ELE_READ_SHADOW_REQ there as well.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/ele.c | 2 --
 include/mach/imx/ele.h  | 1 +
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/arm/mach-imx/ele.c b/arch/arm/mach-imx/ele.c
index ab3958cbd3..095eaec8f6 100644
--- a/arch/arm/mach-imx/ele.c
+++ b/arch/arm/mach-imx/ele.c
@@ -228,8 +228,6 @@ int ele_read_common_fuse(u16 fuse_id, u32 *fuse_word, u32 *response)
 	return ret;
 }
 
-#define ELE_READ_SHADOW_REQ 0xf3
-
 int ele_read_shadow_fuse(u16 fuse_id, u32 *fuse_word, u32 *response)
 {
 	struct ele_msg msg;
diff --git a/include/mach/imx/ele.h b/include/mach/imx/ele.h
index 0c863f6cb3..da4b0aa50d 100644
--- a/include/mach/imx/ele.h
+++ b/include/mach/imx/ele.h
@@ -45,6 +45,7 @@
 #define ELE_ATTEST_REQ (0xDB)
 #define ELE_RELEASE_PATCH_REQ (0xDC)
 #define ELE_OTP_SEQ_SWITH_REQ (0xDD)
+#define ELE_READ_SHADOW_REQ (0xF3)
 
 /* ELE failure indications */
 #define ELE_ROM_PING_FAILURE_IND (0x0A)
-- 
2.39.2




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 2/5] ARM: i.MX: ele: add function comments
  2024-03-11 10:21 [PATCH 1/5] ARM: i.MX: ele: move ELE_READ_SHADOW_REQ definition Sascha Hauer
@ 2024-03-11 10:21 ` Sascha Hauer
  2024-03-11 10:21 ` [PATCH 3/5] ARM: i.MX: ele: add ele_write_shadow_fuse Sascha Hauer
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2024-03-11 10:21 UTC (permalink / raw)
  To: Barebox List

i.MX fuse numbers are sometimes referred to as the index of the 32bit
word, sometimes as bit offsets and the device in /dev/imx_ocotp counts
in bytes. To avoid more confusion add some comments to the function
headers of functions reading/writing the fuses that clearly state that
they take the 32bit word number as input.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/ele.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/ele.c b/arch/arm/mach-imx/ele.c
index 095eaec8f6..ce5ad287d8 100644
--- a/arch/arm/mach-imx/ele.c
+++ b/arch/arm/mach-imx/ele.c
@@ -207,6 +207,16 @@ int imx93_ele_load_fw(void *bl33)
 	return 0;
 }
 
+/*
+ * ele_read_common_fuse - read a fuse
+ * @fuse_id: The fuse to read (in 32bit word number)
+ * fuse_word: The value read from the fuse
+ * @response: on return contains the response from ELE
+ *
+ * This reads the shadow value of the fuse @fuse_id.
+ *
+ * Return: 0 when the ELE call succeeds, negative error code otherwise
+ */
 int ele_read_common_fuse(u16 fuse_id, u32 *fuse_word, u32 *response)
 {
 	struct ele_msg msg;
@@ -228,6 +238,16 @@ int ele_read_common_fuse(u16 fuse_id, u32 *fuse_word, u32 *response)
 	return ret;
 }
 
+/*
+ * ele_read_shadow_fuse - read a fuse
+ * @fuse_id: The fuse to read (in 32bit word number)
+ * fuse_word: The value read from the fuse
+ * @response: on return contains the response from ELE
+ *
+ * This reads the shadow value of the fuse @fuse_id.
+ *
+ * Return: 0 when the ELE call succeeds, negative error code otherwise
+ */
 int ele_read_shadow_fuse(u16 fuse_id, u32 *fuse_word, u32 *response)
 {
 	struct ele_msg msg;
@@ -251,7 +271,7 @@ int ele_read_shadow_fuse(u16 fuse_id, u32 *fuse_word, u32 *response)
 
 /*
  * ele_write_fuse - write a fuse
- * @fuse_id: The fuse to write to
+ * @fuse_id: The fuse to write to (in 32bit word number)
  * @fuse_val: The value to write to the fuse
  * @lock: lock fuse after writing
  * @response: on return contains the response from ELE
-- 
2.39.2




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 3/5] ARM: i.MX: ele: add ele_write_shadow_fuse
  2024-03-11 10:21 [PATCH 1/5] ARM: i.MX: ele: move ELE_READ_SHADOW_REQ definition Sascha Hauer
  2024-03-11 10:21 ` [PATCH 2/5] ARM: i.MX: ele: add function comments Sascha Hauer
@ 2024-03-11 10:21 ` Sascha Hauer
  2024-03-11 10:21 ` [PATCH 4/5] nvmem: add nvmem_device_get_device() Sascha Hauer
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2024-03-11 10:21 UTC (permalink / raw)
  To: Barebox List

The ocotp fuses have shadow values. For some fuses the shadow values
can be read from and written to. While it's not really clear where
the ROM really uses these shadow values, it still helps reading and
writing them to get an idea if we are about to write the correct
fuses before we finally enable permanent write.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/ele.c | 33 +++++++++++++++++++++++++++++++++
 include/mach/imx/ele.h  |  2 ++
 2 files changed, 35 insertions(+)

diff --git a/arch/arm/mach-imx/ele.c b/arch/arm/mach-imx/ele.c
index ce5ad287d8..58cffad797 100644
--- a/arch/arm/mach-imx/ele.c
+++ b/arch/arm/mach-imx/ele.c
@@ -305,6 +305,39 @@ int ele_write_fuse(u16 fuse_id, u32 fuse_val, bool lock, u32 *response)
 	return ret;
 }
 
+/*
+ * ele_write_shadow_fuse - write a fuse
+ * @fuse_id: The fuse to write to
+ * @fuse_val: The value to write to the fuse
+ * @lock: lock fuse after writing
+ * @response: on return contains the response from ELE
+ *
+ * This writes the 32bit given in @fuse_val to the fuses at @fuse_id. This is
+ * a permanent change, be careful.
+ *
+ * Return: 0 when the ELE call succeeds, negative error code otherwise
+ */
+int ele_write_shadow_fuse(u16 fuse_id, u32 fuse_val, u32 *response)
+{
+	struct ele_msg msg;
+	int ret;
+
+	msg.version = ELE_VERSION;
+	msg.tag = ELE_CMD_TAG;
+	msg.size = 3;
+	msg.command = ELE_WRITE_SHADOW_REQ;
+	msg.data[0] = fuse_id;
+
+	msg.data[1] = fuse_val;
+
+	ret = imx9_s3mua_call(&msg);
+
+	if (response)
+		*response = msg.data[0];
+
+	return ret;
+}
+
 /*
  * ele_forward_lifecycle - forward lifecycle
  * @lc: The lifecycle value to forward to
diff --git a/include/mach/imx/ele.h b/include/mach/imx/ele.h
index da4b0aa50d..7ba8afde20 100644
--- a/include/mach/imx/ele.h
+++ b/include/mach/imx/ele.h
@@ -45,6 +45,7 @@
 #define ELE_ATTEST_REQ (0xDB)
 #define ELE_RELEASE_PATCH_REQ (0xDC)
 #define ELE_OTP_SEQ_SWITH_REQ (0xDD)
+#define ELE_WRITE_SHADOW_REQ (0xF2)
 #define ELE_READ_SHADOW_REQ (0xF3)
 
 /* ELE failure indications */
@@ -152,6 +153,7 @@ int ele_call(struct ele_msg *msg);
 int ele_read_common_fuse(u16 fuse_id, u32 *fuse_word, u32 *response);
 int ele_release_rdc(u8 core_id, u8 xrdc, u32 *response);
 int ele_read_shadow_fuse(u16 fuse_id, u32 *fuse_word, u32 *response);
+int ele_write_shadow_fuse(u16 fuse_id, u32 fuse_val, u32 *response);
 int ele_get_info(struct ele_get_info_data *info);
 int ele_write_fuse(u16 fuse_id, u32 fuse_val, bool lock, u32 *response);
 int ele_authenticate_container(unsigned long addr, u32 *response);
-- 
2.39.2




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 4/5] nvmem: add nvmem_device_get_device()
  2024-03-11 10:21 [PATCH 1/5] ARM: i.MX: ele: move ELE_READ_SHADOW_REQ definition Sascha Hauer
  2024-03-11 10:21 ` [PATCH 2/5] ARM: i.MX: ele: add function comments Sascha Hauer
  2024-03-11 10:21 ` [PATCH 3/5] ARM: i.MX: ele: add ele_write_shadow_fuse Sascha Hauer
@ 2024-03-11 10:21 ` Sascha Hauer
  2024-03-11 10:21 ` [PATCH 5/5] nvmem: imx-ocotp-ele: implement permanent write support Sascha Hauer
  2024-03-13  7:42 ` [PATCH 1/5] ARM: i.MX: ele: move ELE_READ_SHADOW_REQ definition Sascha Hauer
  4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2024-03-11 10:21 UTC (permalink / raw)
  To: Barebox List

We'll want to add a device parameter to the imx_ocotp0 device in the
next step, but the device is private to the nvmem core. Add a getter
function for it.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/nvmem/core.c           | 6 ++++++
 include/linux/nvmem-provider.h | 5 +++++
 2 files changed, 11 insertions(+)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 67bb1d7993..ad145a4242 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -858,3 +858,9 @@ int nvmem_cell_read_variable_le_u32(struct device *dev, const char *cell_id,
 	return 0;
 }
 EXPORT_SYMBOL_GPL(nvmem_cell_read_variable_le_u32);
+
+struct device *nvmem_device_get_device(struct nvmem_device *nvmem)
+{
+	return &nvmem->dev;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_get_device);
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 3c30e18409..b3b4372d30 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -48,6 +48,7 @@ struct nvmem_device *nvmem_regmap_register(struct regmap *regmap, const char *na
 struct nvmem_device *nvmem_regmap_register_with_pp(struct regmap *regmap,
 		const char *name, nvmem_cell_post_process_t cell_post_process);
 struct nvmem_device *nvmem_partition_register(struct cdev *cdev);
+struct device *nvmem_device_get_device(struct nvmem_device *nvmem);
 
 #else
 
@@ -73,5 +74,9 @@ static inline struct nvmem_device *nvmem_partition_register(struct cdev *cdev)
 	return ERR_PTR(-ENOSYS);
 }
 
+static struct device *nvmem_device_get_device(struct nvmem_device *nvmem)
+{
+	return ERR_PTR(-ENOSYS);
+}
 #endif /* CONFIG_NVMEM */
 #endif  /* ifndef _LINUX_NVMEM_PROVIDER_H */
-- 
2.39.2




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 5/5] nvmem: imx-ocotp-ele: implement permanent write support
  2024-03-11 10:21 [PATCH 1/5] ARM: i.MX: ele: move ELE_READ_SHADOW_REQ definition Sascha Hauer
                   ` (2 preceding siblings ...)
  2024-03-11 10:21 ` [PATCH 4/5] nvmem: add nvmem_device_get_device() Sascha Hauer
@ 2024-03-11 10:21 ` Sascha Hauer
  2024-03-13  7:42 ` [PATCH 1/5] ARM: i.MX: ele: move ELE_READ_SHADOW_REQ definition Sascha Hauer
  4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2024-03-11 10:21 UTC (permalink / raw)
  To: Barebox List

This implements write support to imx-ocotp-ele. By default only the
shadow values are written which is harmless and nearly useless (as the
ROM doesn't seem use these values). Real write support is enabled by
setting imx_ocotp0.permanent_write_enable to true. A big warning is
printed and the next write access to /dev/imx_ocotp will then really
burn fuses.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/nvmem/imx-ocotp-ele.c | 36 ++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/nvmem/imx-ocotp-ele.c b/drivers/nvmem/imx-ocotp-ele.c
index 9708d3f4bb..b25ab32fea 100644
--- a/drivers/nvmem/imx-ocotp-ele.c
+++ b/drivers/nvmem/imx-ocotp-ele.c
@@ -41,6 +41,7 @@ struct imx_ocotp_priv {
 	void __iomem *base;
 	const struct ocotp_devtype_data *data;
 	struct regmap_config map_config;
+	int permanent_write_enable;
 };
 
 static enum fuse_type imx_ocotp_fuse_type(struct imx_ocotp_priv *priv, u32 index)
@@ -92,6 +93,22 @@ static int imx_ocotp_reg_read(void *context, unsigned int offset, unsigned int *
 	return 0;
 };
 
+static int imx_ocotp_reg_write(void *context, unsigned int offset, unsigned int val)
+{
+	struct imx_ocotp_priv *priv = context;
+	u32 index;
+	int ret;
+
+	index = offset >> 2;
+
+	if (priv->permanent_write_enable)
+		ret = ele_write_fuse(index, val, false, NULL);
+	else
+		ret = ele_write_shadow_fuse(index, val, NULL);
+
+	return ret;
+}
+
 static int imx_ocotp_cell_pp(void *context, const char *id, unsigned int offset,
 			     void *data, size_t bytes)
 {
@@ -116,6 +133,7 @@ static int imx_ocotp_cell_pp(void *context, const char *id, unsigned int offset,
 }
 
 static struct regmap_bus imx_ocotp_regmap_bus = {
+	.reg_write = imx_ocotp_reg_write,
 	.reg_read = imx_ocotp_reg_read,
 };
 
@@ -132,6 +150,18 @@ static void imx_ocotp_set_unique_machine_id(struct imx_ocotp_priv *priv)
 	machine_id_set_hashable(unique_id_parts, sizeof(unique_id_parts));
 }
 
+static int permanent_write_enable_set(struct param_d *param, void *ctx)
+{
+	struct imx_ocotp_priv *priv = ctx;
+
+	if (priv->permanent_write_enable) {
+		dev_warn(priv->dev, "Enabling permanent write on fuses.\n");
+		dev_warn(priv->dev, "Writing fuses may damage your device. Be careful!\n");
+	}
+
+	return 0;
+}
+
 static int imx_ele_ocotp_probe(struct device *dev)
 {
 	struct imx_ocotp_priv *priv;
@@ -141,6 +171,7 @@ static int imx_ele_ocotp_probe(struct device *dev)
 	int ret;
 
 	priv = xzalloc(sizeof(*priv));
+	priv->dev = dev;
 
 	ret = dev_get_drvdata(dev, (const void **)&data);
 	if (ret)
@@ -165,11 +196,14 @@ static int imx_ele_ocotp_probe(struct device *dev)
 	if (IS_ENABLED(CONFIG_MACHINE_ID))
 		imx_ocotp_set_unique_machine_id(priv);
 
-	nvmem = nvmem_regmap_register_with_pp(priv->map, "imx-ocotp",
+	nvmem = nvmem_regmap_register_with_pp(priv->map, "imx_ocotp",
 					      imx_ocotp_cell_pp);
 	if (IS_ERR(nvmem))
 		return PTR_ERR(nvmem);
 
+	dev_add_param_bool(nvmem_device_get_device(nvmem), "permanent_write_enable",
+			permanent_write_enable_set, NULL, &priv->permanent_write_enable, priv);
+
 	return 0;
 }
 
-- 
2.39.2




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/5] ARM: i.MX: ele: move ELE_READ_SHADOW_REQ definition
  2024-03-11 10:21 [PATCH 1/5] ARM: i.MX: ele: move ELE_READ_SHADOW_REQ definition Sascha Hauer
                   ` (3 preceding siblings ...)
  2024-03-11 10:21 ` [PATCH 5/5] nvmem: imx-ocotp-ele: implement permanent write support Sascha Hauer
@ 2024-03-13  7:42 ` Sascha Hauer
  4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2024-03-13  7:42 UTC (permalink / raw)
  To: Barebox List, Sascha Hauer


On Mon, 11 Mar 2024 11:21:48 +0100, Sascha Hauer wrote:
> The ELE request defines are in include/mach/imx/ele.h, move definition
> of ELE_READ_SHADOW_REQ there as well.
> 
> 

Applied, thanks!

[1/5] ARM: i.MX: ele: move ELE_READ_SHADOW_REQ definition
      https://git.pengutronix.de/cgit/barebox/commit/?id=2ec5d544549e (link may not be stable)
[2/5] ARM: i.MX: ele: add function comments
      https://git.pengutronix.de/cgit/barebox/commit/?id=f95b4906c0f7 (link may not be stable)
[3/5] ARM: i.MX: ele: add ele_write_shadow_fuse
      https://git.pengutronix.de/cgit/barebox/commit/?id=2554f8daa381 (link may not be stable)
[4/5] nvmem: add nvmem_device_get_device()
      https://git.pengutronix.de/cgit/barebox/commit/?id=50c4a22e1232 (link may not be stable)
[5/5] nvmem: imx-ocotp-ele: implement permanent write support
      https://git.pengutronix.de/cgit/barebox/commit/?id=9b799d058e46 (link may not be stable)

Best regards,
-- 
Sascha Hauer <s.hauer@pengutronix.de>




^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2024-03-13  7:42 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-11 10:21 [PATCH 1/5] ARM: i.MX: ele: move ELE_READ_SHADOW_REQ definition Sascha Hauer
2024-03-11 10:21 ` [PATCH 2/5] ARM: i.MX: ele: add function comments Sascha Hauer
2024-03-11 10:21 ` [PATCH 3/5] ARM: i.MX: ele: add ele_write_shadow_fuse Sascha Hauer
2024-03-11 10:21 ` [PATCH 4/5] nvmem: add nvmem_device_get_device() Sascha Hauer
2024-03-11 10:21 ` [PATCH 5/5] nvmem: imx-ocotp-ele: implement permanent write support Sascha Hauer
2024-03-13  7:42 ` [PATCH 1/5] ARM: i.MX: ele: move ELE_READ_SHADOW_REQ definition Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox