#include <common.h> | |
#include <config.h> | |
#include <ubi_uboot.h> | |
#include <asm/arch/cpu.h> | |
#include <asm/io.h> | |
#include <malloc.h> | |
#include "asr_geu.h" | |
#include "asr_fuse.h" | |
struct efuse_data efuse_data; | |
static uint32_t fuse_bank0_read32(uint32_t word) | |
{ | |
uint32_t value = 0; | |
switch(word) | |
{ | |
case 0: | |
//CP config[15:0] | |
value = (geu_read32(GEU_FUSE_APCFG3) >> 16)& 0xFFFF; | |
//AP config[15:0] | |
value |= (geu_read32(GEU_FUSE_APCFG1) & 0xFFFF) << 16; | |
break; | |
case 1: | |
//AP config[31:16] | |
value = (geu_read32(GEU_FUSE_APCFG1) >> 16)& 0xFFFF; | |
//AP config[47:32] | |
value |= (geu_read32(GEU_FUSE_APCFG2) & 0xFFFF)<< 16; | |
break; | |
case 2: | |
//AP config[63:48] | |
value = (geu_read32(GEU_FUSE_APCFG2) >> 16) & 0xFFFF; | |
//AP config[79:64] | |
value |= (geu_read32(GEU_FUSE_APCFG3) & 0xFFFF)<< 16; | |
break; | |
case 3: | |
value = geu_read32(GEU_FUSE_BANK0_127_96); | |
break; | |
case 4: | |
value = geu_read32(GEU_FUSE_BANK0_159_128); | |
break; | |
case 5: | |
value = geu_read32(GEU_FUSE_BANK0_191_160); | |
break; | |
case 6: | |
value = (geu_read32(GEU_FUSE_BANK0_239_208) & 0xFFFF) << 16; | |
value |= geu_read32(GEU_FUSE_BANK0_207_192) & 0xFFFF; | |
break; | |
case 7: | |
value = (geu_read32(GEU_FUSE_BANK0_255_240) &0xFFFF) << 16; | |
value |= (geu_read32(GEU_FUSE_BANK0_239_208) >> 16) & 0xFFFF; | |
break; | |
default: | |
printf("Read wrong word of bank0"); | |
break; | |
} | |
return value; | |
} | |
static uint32_t fuse_bank1_read32(uint32_t word) | |
{ | |
uint32_t value; | |
if( word > 7 ) | |
printf("Read wrong word of bank1"); | |
value = geu_read32(GEU_FUSE_VAL_ROOT_KEY(word)); | |
return value; | |
} | |
static uint32_t fuse_bank2_read32(uint32_t word) | |
{ | |
uint32_t value; | |
if( word > 7 ) | |
printf("Read wrong word of bank2"); | |
value = geu_read32(GEU_FUSE_VAL_OEM_HASH_KEY(word)); | |
return value; | |
} | |
static int fuse_bank3_read32(uint32_t word) | |
{ | |
uint32_t value = 0; | |
switch(word) | |
{ | |
case 0 ... 5: | |
value = geu_read32(GEU_BLOCK3_RESERVED(word)); | |
break; | |
case 6: | |
value = geu_read32(GEU_FUSE_BANK3_223_192); | |
break; | |
case 7: | |
value = geu_read32(GEU_FUSE_BANK3_255_224); | |
break; | |
default: | |
printf("Read wrong word of bank2"); | |
break; | |
} | |
return value; | |
} | |
int fuse_bank_read(uint32_t bank, uint8_t *buffer) | |
{ | |
uint32_t (*bank_read)(uint32_t); | |
uint32_t word[EFUSE_BANK_LEN_IN_WORD]; | |
bank_read = fuse_bank0_read32; | |
switch(bank) { | |
case 0: | |
bank_read = fuse_bank0_read32; | |
break; | |
case 1: | |
bank_read = fuse_bank1_read32; | |
break; | |
case 2: | |
bank_read = fuse_bank2_read32; | |
break; | |
case 3: | |
bank_read = fuse_bank3_read32; | |
break; | |
default: | |
return -1; | |
} | |
for(int i = 0; i < EFUSE_BANK_LEN_IN_WORD; i++) | |
word[i] = bank_read(i); | |
memcpy(buffer, word, EFUSE_BANK_LEN_IN_BYTE); | |
return 0; | |
} | |
int asr_rkek_burned(void) | |
{ | |
uint32_t val; | |
/* If RKEK is burned, SW access to it must be disabled as well */ | |
if (cpu_is_asr1901() || cpu_is_asr1906()) { | |
/* check if LCS_DM is burned */ | |
val = geu_read32(GEU_KSTR_BANK6_LCS); | |
val >>= GEU_KSTR_LCS_DM_BASE; | |
val &= GEU_KSTR_LCS_MASK; | |
if (hweight32(val) > 1) | |
return 1; | |
} else { /* 1803, 1806, 1828, 1903 */ | |
/* check if secure key access disable is burned */ | |
val = geu_read32(GEU_FUSE_APCFG2); | |
if (val & GEU_SECURE_KEY_ACCESS_DISABLED) | |
return 1; | |
} | |
return 0; | |
} | |
int fuse_get_sim_lock(int *sim_lock) | |
{ | |
uint32_t value; | |
geu_enable_clk(); | |
value = geu_read32(GEU_FUSE_APCFG1); | |
if(cpu_is_asr1826s() || cpu_is_asr1806() || | |
cpu_is_asr1803() || cpu_is_asr1903()) { | |
value &= 1; | |
} else if (cpu_is_asr1901() || cpu_is_asr1906()) { | |
value = geu_read32(GEU_FUSE_WORD_BANK0); | |
value &= (1 << 23); /* bit23: sim lock */ | |
value = (value) ? 1:0; | |
} else { | |
printf("sim lock is not supported by this platform\n"); | |
value = -1; | |
} | |
*sim_lock = value; | |
geu_disable_clk(); | |
return 0; | |
} | |
void geu_fuse_test(void) | |
{ | |
uint8_t bank_buf[EFUSE_BANK_LEN_IN_BYTE]; | |
memset(bank_buf, 0, EFUSE_BANK_LEN_IN_BYTE); | |
for (uint32_t bank = 0; bank < 4; bank++) { | |
if (0 > fuse_bank_read(bank, bank_buf)) { | |
printf("fuse back bank read failed\n"); | |
goto err; | |
} | |
for (uint32_t i = 0; i < EFUSE_BANK_LEN_IN_BYTE; i++) { | |
printf("%.2x", bank_buf[i]); | |
if ((i+1) % 4 == 0) | |
printf(" "); | |
} | |
printf("\n"); | |
} | |
return; | |
err: | |
return; | |
} |