diff mbox series

[2/3] amd64: zynqmp: Add command to program efuses

Message ID 20240514140416.156747-3-lukas.funke-oss@weidmueller.com
State Superseded
Delegated to: Michal Simek
Headers show
Series Add eFuse access for ZynqMP | expand

Commit Message

Lukas Funke May 14, 2024, 2:04 p.m. UTC
From: Lukas Funke <lukas.funke@weidmueller.com>

Add subcommands to read/write eFuses using u-boot. The subcommands
through the 'zynqmp' command.

Example:

=> zynqmp efuse_read 0xc 0xc
00000000: 85 36 b1 3c 34 f2 3b 01 00 00 00 40              .f.<D.:....@

Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>
---

 board/xilinx/zynqmp/cmds.c | 101 +++++++++++++++++++++++++++++++++++++
 1 file changed, 101 insertions(+)
diff mbox series

Patch

diff --git a/board/xilinx/zynqmp/cmds.c b/board/xilinx/zynqmp/cmds.c
index bf39c5472ea..e8d70ffecd6 100644
--- a/board/xilinx/zynqmp/cmds.c
+++ b/board/xilinx/zynqmp/cmds.c
@@ -16,6 +16,9 @@ 
 #include <asm/arch/sys_proto.h>
 #include <asm/io.h>
 #include <mach/zynqmp_aes.h>
+#include <misc.h>
+#include <hexdump.h>
+#include <dm.h>
 
 static int do_zynqmp_verify_secure(struct cmd_tbl *cmdtp, int flag, int argc,
 				   char *const argv[])
@@ -340,6 +343,99 @@  static int do_zynqmp_sha3(struct cmd_tbl *cmdtp, int flag,
 	return CMD_RET_SUCCESS;
 }
 
+static int do_zynqmp_efuse_read(struct cmd_tbl *cmdtp, int flag,
+				int argc, char * const argv[])
+{
+	struct udevice *dev;
+	u32 offset, len;
+	u8 buf[32];
+	int ret;
+
+	if (!CONFIG_IS_ENABLED(ZYNQMP_EFUSE)) {
+		printf("Failed: not supported\n");
+		return CMD_RET_FAILURE;
+	}
+
+	if (argc > cmdtp->maxargs || argc < (cmdtp->maxargs - 1))
+		return CMD_RET_USAGE;
+
+	memset(buf, 0, sizeof(buf));
+
+	offset = hextoul(argv[2], NULL);
+	len = hextoul(argv[3], NULL);
+
+	if (len > sizeof(buf)) {
+		printf("Failed: length exceeds buffer size");
+		return CMD_RET_FAILURE;
+	}
+
+	ret = uclass_get_device_by_driver(UCLASS_MISC,
+					  DM_DRIVER_GET(zynqmp_efuse), &dev);
+	if (ret) {
+		printf("Failed to initialize zynqmp_efuse: %d\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	ret = misc_read(dev, offset, (void *)buf, len);
+	if (ret) {
+		printf("Failed: cannot read efuse at 0x%x, errocode %d\n",
+		       offset, ret);
+		return CMD_RET_FAILURE;
+	}
+
+	if (CONFIG_IS_ENABLED(HEXDUMP))
+		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_zynqmp_efuse_write(struct cmd_tbl *cmdtp, int flag,
+				 int argc, char * const argv[])
+{
+	struct udevice *dev;
+	u64 value;
+	u32 offset, len;
+	u8 buf[sizeof(u64)];
+	int ret;
+
+	if (!CONFIG_IS_ENABLED(ZYNQMP_EFUSE)) {
+		printf("Failed: not supported\n");
+		return CMD_RET_FAILURE;
+	}
+
+	if (argc > cmdtp->maxargs || argc < (cmdtp->maxargs - 1))
+		return CMD_RET_USAGE;
+
+	memset(buf, 0, sizeof(buf));
+
+	offset = hextoul(argv[2], NULL);
+	len = hextoul(argv[3], NULL);
+
+	if (len <= sizeof(u64)) {
+		value = hextoul(argv[4], NULL);
+		memcpy(buf, &value, sizeof(value));
+	} else {
+		printf("Cannot write more than %zu byte to efuse\n", sizeof(u64));
+		return CMD_RET_FAILURE;
+	}
+
+	ret = uclass_get_device_by_driver(UCLASS_MISC,
+					  DM_DRIVER_GET(zynqmp_efuse), &dev);
+	if (ret) {
+		printf("Failed to initialize zynqmp_efuse: %d\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	ret = misc_write(dev, offset, (void *)buf, sizeof(buf));
+	if (ret) {
+		printf("Failed: cannot read efuse at 0x%x, errocode 0x%x\n",
+		       offset, ret);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
 static struct cmd_tbl cmd_zynqmp_sub[] = {
 	U_BOOT_CMD_MKENT(secure, 5, 0, do_zynqmp_verify_secure, "", ""),
 	U_BOOT_CMD_MKENT(pmufw, 4, 0, do_zynqmp_pmufw, "", ""),
@@ -348,6 +444,8 @@  static struct cmd_tbl cmd_zynqmp_sub[] = {
 	U_BOOT_CMD_MKENT(aes, 9, 0, do_zynqmp_aes, "", ""),
 	U_BOOT_CMD_MKENT(rsa, 7, 0, do_zynqmp_rsa, "", ""),
 	U_BOOT_CMD_MKENT(sha3, 5, 0, do_zynqmp_sha3, "", ""),
+	U_BOOT_CMD_MKENT(efuse_read, 4, 0, do_zynqmp_efuse_read, "", ""),
+	U_BOOT_CMD_MKENT(efuse_write, 5, 0, do_zynqmp_efuse_write, "", ""),
 #ifdef CONFIG_DEFINE_TCM_OCM_MMAP
 	U_BOOT_CMD_MKENT(tcminit, 3, 0, do_zynqmp_tcm_init, "", ""),
 #endif
@@ -422,6 +520,9 @@  U_BOOT_LONGHELP(zynqmp,
 	"	48 bytes hash value into srcaddr\n"
 	"	Optional key_addr can be specified for saving sha3 hash value\n"
 	"	Note: srcaddr/srclen should not be 0\n"
+	"zynqmp efuse_read offset len - read efuse at given offset\n"
+	"zynqmp efuse_write offset len value - write value of length <len>\n"
+	"		       to efuse at given offset\n"
 	);
 
 U_BOOT_CMD(