arm: mvebu: Add support for reading LD0 and LD1 eFuse
authorPali Rohár <pali@kernel.org>
Wed, 6 Apr 2022 12:18:18 +0000 (14:18 +0200)
committerStefan Roese <sr@denx.de>
Thu, 21 Apr 2022 10:31:36 +0000 (12:31 +0200)
Armada 385 contains 64 lines of HD eFuse and 2 lines of LD eFuse. HD eFuse
is used for secure boot and each line is 64 bits long + 1 lock bit. LD
eFuse lines are 256 bits long + 1 lock bit. LD 0 line is reserved for
Marvell Internal Use and LD 1 line is for General Purpose Data. U-Boot
already contains HD eFuse reading and programming support.

This patch implements LD eFuse reading support. LD 0 line is mapped to
U-Boot fuse bank 64 and LD 1 line to fuse bank 65.

LD 0 Marvell Internal Use line seems that was burned in factory with some
data and can be read by U-Boot fuse command:

  => fuse read 64 0 9

LD 1 General Purpose Data line is by default empty and can be read by
U-Boot fuse command:

  => fuse read 65 0 9

Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
arch/arm/mach-mvebu/efuse.c
arch/arm/mach-mvebu/include/mach/efuse.h

index c79eee9..80318c3 100644 (file)
@@ -27,6 +27,7 @@
 
 enum {
        MVEBU_EFUSE_CTRL_PROGRAM_ENABLE = (1 << 31),
+       MVEBU_EFUSE_LD1_SELECT          = (1 <<  6),
 };
 
 struct mvebu_hd_efuse {
@@ -39,8 +40,10 @@ struct mvebu_hd_efuse {
 #ifndef DRY_RUN
 static struct mvebu_hd_efuse *efuses =
        (struct mvebu_hd_efuse *)(MBUS_EFUSE_BASE + 0xF9000);
+static u32 *ld_efuses = (void *)MBUS_EFUSE_BASE + 0xF8F00;
 #else
 static struct mvebu_hd_efuse efuses[EFUSE_LINE_MAX + 1];
+static u32 ld_efuses[EFUSE_LD_WORDS];
 #endif
 
 static int efuse_initialised;
@@ -169,6 +172,21 @@ int mvebu_read_efuse(int nr, struct efuse_val *val)
        return 0;
 }
 
+void mvebu_read_ld_efuse(int ld1, u32 *line)
+{
+       int i;
+
+#ifndef DRY_RUN
+       if (ld1)
+               setbits_le32(MVEBU_EFUSE_CONTROL, MVEBU_EFUSE_LD1_SELECT);
+       else
+               clrbits_le32(MVEBU_EFUSE_CONTROL, MVEBU_EFUSE_LD1_SELECT);
+#endif
+
+       for (i = 0; i < EFUSE_LD_WORDS; i++)
+               line[i] = readl(ld_efuses + i);
+}
+
 int mvebu_write_efuse(int nr, struct efuse_val *val)
 {
        return prog_efuse(nr, val, ~0, ~0);
@@ -199,8 +217,18 @@ static int valid_prog_words;
 int fuse_read(u32 bank, u32 word, u32 *val)
 {
        struct efuse_val fuse_line;
+       u32 ld_line[EFUSE_LD_WORDS];
        int res;
 
+       if ((bank == EFUSE_LD0_LINE || bank == EFUSE_LD1_LINE) && word < EFUSE_LD_WORDS) {
+               res = mvebu_efuse_init_hw();
+               if (res)
+                       return res;
+               mvebu_read_ld_efuse(bank == EFUSE_LD1_LINE, ld_line);
+               *val = ld_line[word];
+               return 0;
+       }
+
        if (bank < EFUSE_LINE_MIN || bank > EFUSE_LINE_MAX || word > 2)
                return -EINVAL;
 
index bbc5844..122e735 100644 (file)
@@ -53,8 +53,13 @@ enum efuse_line {
 
        EFUSE_LINE_MIN = 0,
        EFUSE_LINE_MAX = 63,
+
+       EFUSE_LD0_LINE = 64,
+       EFUSE_LD1_LINE = 65,
 };
 
+#define EFUSE_LD_WORDS 9
+
 #endif
 
 int mvebu_efuse_init_hw(void);