blob: 7144f331be7b5207bebf9f4e14b0f7c424218e7c [file] [log] [blame]
#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;
}