summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorPali Rohár <pali@kernel.org>2022-09-22 13:43:44 +0200
committerStefan Roese <sr@denx.de>2022-10-06 10:15:35 +0200
commit3b44b3fdf2b01f1d50a4325460a36550821ff920 (patch)
treeb2899dba68f126334d2cd3c77486bf6a1752a649 /arch
parent37bb396669b27aa62fe8bc5eeb6bfde92e09c2d3 (diff)
arm: mvebu: Add support for programming LD0 and LD1 eFuse
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@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-mvebu/efuse.c43
-rw-r--r--arch/arm/mach-mvebu/include/mach/efuse.h4
2 files changed, 47 insertions, 0 deletions
diff --git a/arch/arm/mach-mvebu/efuse.c b/arch/arm/mach-mvebu/efuse.c
index 80318c339eb..4b043378217 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 122e735f2fc..b125c30beb8 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