[PATCH 1/3] arm: mvebu: Add support for programming LD0 and LD1 eFuse

Pali Rohár pali at kernel.org
Thu Sep 22 13:43:44 CEST 2022


This patch implements LD eFuse programming support. Armada 385 contains two
LD eFuse lines, each is 256 bit long with one additional lock bit. LD 0
line is mapped to U-Boot fuse bank 64 and LD 1 line to fuse bank 65. U-Boot
32-bit fuse words 0-8 are mapped to LD eFuse line bits 0-255. U-Boot fuse
word 9 is mapped to LD eFuse line lock bit.

So to program LD 1 General Purpose Data line, use U-Boot fuse command:

    => fuse prog -y 65 0 0x76543210
    => fuse prog -y 65 1 0xfedcba98
    => fuse prog -y 65 2 0x76543210
    => fuse prog -y 65 3 0xfedcba98
    => fuse prog -y 65 4 0x76543210
    => fuse prog -y 65 5 0xfedcba98
    => fuse prog -y 65 6 0x76543210
    => fuse prog -y 65 7 0xfedcba98
    => fuse prog -y 65 8 0x1

Signed-off-by: Pali Rohár <pali at kernel.org>
---
 arch/arm/mach-mvebu/efuse.c              | 43 ++++++++++++++++++++++++
 arch/arm/mach-mvebu/include/mach/efuse.h |  4 +++
 2 files changed, 47 insertions(+)

diff --git a/arch/arm/mach-mvebu/efuse.c b/arch/arm/mach-mvebu/efuse.c
index 80318c339eb7..4b0433782171 100644
--- a/arch/arm/mach-mvebu/efuse.c
+++ b/arch/arm/mach-mvebu/efuse.c
@@ -132,6 +132,46 @@ static int prog_efuse(int nr, struct efuse_val *new_val, u32 mask0, u32 mask1)
 	return res;
 }
 
+int mvebu_prog_ld_efuse(int ld1, u32 word, u32 val)
+{
+	int i, res;
+	u32 line[EFUSE_LD_WORDS];
+
+	res = mvebu_efuse_init_hw();
+	if (res)
+		return res;
+
+	mvebu_read_ld_efuse(ld1, line);
+
+	/* check if lock bit is already programmed */
+	if (line[EFUSE_LD_WORDS - 1])
+		return -EPERM;
+
+	/* check if word is valid */
+	if (word >= EFUSE_LD_WORDS)
+		return -EINVAL;
+
+	/* check if there is some bit for programming */
+	if (val == (line[word] & val))
+		return 0;
+
+	enable_efuse_program();
+
+	mvebu_read_ld_efuse(ld1, line);
+	line[word] |= val;
+
+	for (i = 0; i < EFUSE_LD_WORDS; i++) {
+		writel(line[i], ld_efuses + i);
+		mdelay(1);
+	}
+
+	mdelay(5);
+
+	disable_efuse_program();
+
+	return 0;
+}
+
 int mvebu_efuse_init_hw(void)
 {
 	int ret;
@@ -254,6 +294,9 @@ int fuse_prog(u32 bank, u32 word, u32 val)
 {
 	int res = 0;
 
+	if (bank == EFUSE_LD0_LINE || bank == EFUSE_LD1_LINE)
+		return mvebu_prog_ld_efuse(bank == EFUSE_LD1_LINE, word, val);
+
 	/*
 	 * NOTE: Fuse line should be written as whole.
 	 * So how can we do that with this API?
diff --git a/arch/arm/mach-mvebu/include/mach/efuse.h b/arch/arm/mach-mvebu/include/mach/efuse.h
index 122e735f2fc7..b125c30beb8c 100644
--- a/arch/arm/mach-mvebu/include/mach/efuse.h
+++ b/arch/arm/mach-mvebu/include/mach/efuse.h
@@ -70,4 +70,8 @@ int mvebu_write_efuse(int nr, struct efuse_val *val);
 
 int mvebu_lock_efuse(int nr);
 
+void mvebu_read_ld_efuse(int ld1, u32 *line);
+
+int mvebu_prog_ld_efuse(int ld1, u32 word, u32 val);
+
 #endif
-- 
2.20.1



More information about the U-Boot mailing list