diff --git a/chips/v851_v853.c b/chips/v851_v853.c index 5b43324..4072ee9 100644 --- a/chips/v851_v853.c +++ b/chips/v851_v853.c @@ -1614,13 +1614,67 @@ static int chip_spi_run(struct xfel_ctx_t * ctx, uint8_t * cbuf, uint32_t clen) return 1; } +enum { + SID_PRCTL = 0x03006000 + 0x040, + SID_PRKEY = 0x03006000 + 0x050, + SID_RDKEY = 0x03006000 + 0x060, + EFUSE_HV_SWITCH = 0x07090000 + 0x204, +}; + +static uint32_t efuse_read(struct xfel_ctx_t * ctx, uint32_t offset) +{ + uint32_t val; + + val = payload_read32(ctx, SID_PRCTL); + val &= ~((0x1ff << 16) | 0x3); + val |= offset << 16; + payload_write32(ctx, SID_PRCTL, val); + val &= ~((0xff << 8) | 0x3); + val |= (0xac << 8) | 0x2; + payload_write32(ctx, SID_PRCTL, val); + while(payload_read32(ctx, SID_PRCTL) & 0x2); + val &= ~((0x1ff << 16) | (0xff << 8) | 0x3); + payload_write32(ctx, SID_PRCTL, val); + val = payload_read32(ctx, SID_RDKEY); + + return val; +} + +static void efuse_write(struct xfel_ctx_t * ctx, uint32_t offset, uint32_t value) +{ + uint32_t val; + + payload_write32(ctx, EFUSE_HV_SWITCH, 0x1); + payload_write32(ctx, SID_PRKEY, value); + val = payload_read32(ctx, SID_PRCTL); + val &= ~((0x1ff << 16) | 0x3); + val |= offset << 16; + payload_write32(ctx, SID_PRCTL, val); + val &= ~((0xff << 8) | 0x3); + val |= (0xac << 8) | 0x1; + payload_write32(ctx, SID_PRCTL, val); + while(payload_read32(ctx, SID_PRCTL) & 0x1); + val &= ~((0x1ff << 16) | (0xff << 8) | 0x3); + payload_write32(ctx, SID_PRCTL, val); + payload_write32(ctx, EFUSE_HV_SWITCH, 0x0); +} + static const struct sid_section_t { char * name; uint32_t offset; uint32_t size_bits; } sids[] = { - { "chipid", 0x0000, 128 }, - { "unknown", 0x0010, 1920 }, + { "chipid", 0x0000, 128 }, + { "brom-conf-try", 0x0010, 32 }, + { "thermal-sensor", 0x0014, 64 }, + { "ft-zone", 0x001c, 128 }, + { "reserved1", 0x002c, 96 }, + { "write-protect", 0x0038, 32 }, + { "read-protect", 0x003c, 32 }, + { "lcjs", 0x0040, 32 }, + { "reserved2", 0x0044, 800 }, + { "rotpk", 0x00a8, 256 }, + { "reserved3", 0x00c8, 448 }, }; static int chip_extra(struct xfel_ctx_t * ctx, int argc, char * argv[]) @@ -1640,7 +1694,7 @@ static int chip_extra(struct xfel_ctx_t * ctx, int argc, char * argv[]) { uint32_t count = sids[n].size_bits / 32; for(int i = 0; i < count; i++) - buffer[i] = payload_read32(ctx, 0x03006200 + sids[n].offset + i * 4); + buffer[i] = efuse_read(ctx, sids[n].offset + i * 4); printf("%s:(0x%04x %d-bits)", sids[n].name, sids[n].offset, sids[n].size_bits); for(int i = 0; i < count; i++) { @@ -1652,11 +1706,56 @@ static int chip_extra(struct xfel_ctx_t * ctx, int argc, char * argv[]) } return 1; } + else if(!strcmp(argv[0], "read32") && (argc == 2)) + { + uint32_t offset = strtoul(argv[1], NULL, 0); + printf("0x%08x\r\n", efuse_read(ctx, offset)); + return 1; + } + else if(!strcmp(argv[0], "write32") && (argc == 3)) + { + uint32_t offset = strtoul(argv[1], NULL, 0); + size_t value = strtoul(argv[2], NULL, 0); + efuse_write(ctx, offset, value); + return 1; + } + else if(!strcmp(argv[0], "write") && (argc == 2)) + { + uint32_t offset = strtoul(argv[1], NULL, 0); + uint64_t len; + void * buf = file_load(argv[2], &len); + if(buf && (len > 0)) + { + uint8_t * p = buf; + uint32_t l = len; + uint32_t o = 0; + uint32_t v; + while(l >= 4) + { + v = *((uint32_t *)p); + efuse_write(ctx, offset + o, v); + l -= 4; + o += 4; + p += 4; + } + if(l > 0) + { + uint32_t v = 0; + for(int i = 0; i < l; i++) + v = ((v << 8) & 0xffffff00) | p[i]; + efuse_write(ctx, offset + o, v); + } + free(buf); + } + } } } } printf("usage:\r\n"); - printf(" xfel extra efuse dump - Dump all of the efuse information\r\n"); + printf(" xfel extra efuse dump - Dump all of the efuse information\r\n"); + printf(" xfel extra efuse read32 - Read 32-bits value from efuse\r\n"); + printf(" xfel extra efuse write32 - Write 32-bits value to efuse\r\n"); + printf(" xfel extra efuse write - Write file to efuse\r\n"); return 0; }