// GEU_FuseWriteMethods.c | |
// | |
/****************************************************************************** | |
* | |
* (C)Copyright 2022 ASR. All Rights Reserved. | |
* | |
******************************************************************************/ | |
#include <Typedef.h> | |
#include <predefines.h> | |
#include <geu_interface.h> | |
#include <Errors.h> | |
#include <timer.h> | |
#include <PMUA.h> | |
#include <GEU.h> | |
#include <platform_geu_fuse_internal.h> | |
#include <GEU_FuseReadMethods.h> | |
#include "GEU_Provisioning.h" | |
static struct GEU_FuseGlobalData g_ActiveFuseData = {0xF /*ActiveFuseBlock*/ }; | |
struct GEU_FuseGlobalData *pActiveFuseData = &g_ActiveFuseData; | |
static struct GEU_FuseBurnStatus g_FuseBurnStatus; | |
struct GEU_FuseBurnStatus *pFuseBurnStatus = &g_FuseBurnStatus; | |
UINT_T GEU_EnableFuseBurnPower() | |
{ | |
//UINT_T result = NoError; | |
UINT_T scratch, clock_divider; | |
static UINT_T check=0; | |
if (check == 0) { | |
scratch = BIT_5 | BIT_4; | |
//Enable clock | |
GEU_REG_WRITE(PMUA_AES_CLK_RES_CTRL, scratch); | |
} | |
check++; | |
return NoError; | |
} | |
UINT_T GEU_DisablePowerForFuseBurning() | |
{ | |
return NoError; | |
} | |
UINT_T GEU_SetActiveFuseBlock(UINT_T n) | |
{ | |
UINT_T scratch; | |
if (pActiveFuseData->ActiveFuseBlock != n) | |
{ | |
// Clear the Fuse Burn Status Block | |
_geuClearFuseBurnStatus(pFuseBurnStatus); | |
// Clear the ActiveFuseData | |
_geuClearActiveFuseData(pActiveFuseData); | |
// Clear VAL1 & VAL2 register sets | |
_geuClearVal1Val2RegisterSets(); | |
pActiveFuseData->ActiveFuseBlock = n; | |
pActiveFuseData->ActiveFuseBlockField = K_UNDEFINED_FUSEBLOCK_FIELD; | |
}//EndIf BlockNotActive | |
return 0; | |
}//End Routine SetActiveFuseBlock | |
UINT_T GEU_ReadActiveFuseBlockNumber() | |
{ | |
return (pActiveFuseData->ActiveFuseBlock); | |
} | |
UINT_T GEU_SetupApConfigFuseBits(UINT_T* pBuffer, UINT_T Size) | |
{ | |
UINT_T scratch; | |
UINT_T temp[3]; | |
UINT_T read_back[3]; | |
if (Size != K_AP_CONFIG_FUSE_SIZE) | |
{ | |
return FUSE_BufferTooSmall; | |
} | |
// Confirm this fuseblock is active | |
if (g_ActiveFuseData.ActiveFuseBlock != K_AP_CONFIG_FUSEBLOCK) | |
{ | |
return (FUSE_FuseBlockNotActive); | |
} | |
// Check and Set Active FuseBlock Field | |
if (!(pActiveFuseData->ActiveFuseBlockField & K_AP_FUSEBLOCK_FIELD)) | |
{ | |
pActiveFuseData->ActiveFuseBlockField |= K_AP_FUSEBLOCK_FIELD; | |
} | |
//Low16 bit is CP configs | |
temp[0] = (pBuffer[0] & 0xFFFF) << 16; | |
temp[1] = (pBuffer[0] >> 16) & 0xFFFF; | |
temp[1] |= (pBuffer[1] & 0xFFFF) << 16; | |
temp[2] = (pBuffer[1] >> 16) & 0xFFFF; | |
temp[2] |= (pBuffer[2] & 0xFFFF) << 16; | |
//Save the setup data to GEU_FUSE_PROG_VAL1/VAL2/VAL3 | |
_geuUpdateRegister(GEU_FUSE_PROG_VAL1+0, temp[0], 0xFFFF0000); //bit 16-31 are AP config | |
_geuUpdateRegister(GEU_FUSE_PROG_VAL1+4, temp[1], 0xFFFFFFFF); | |
_geuUpdateRegister(GEU_FUSE_PROG_VAL1+8, temp[2], 0xFFFFFFFF); | |
//In case that AP config is not empty | |
GEU_ReadApConfigFuseBits(&read_back[0], K_AP_CONFIG_FUSE_SIZE); | |
// Save to Active fuseblock for burn validation later | |
pActiveFuseData->ApConfigSave[0] = pBuffer[0] | read_back[0]; | |
pActiveFuseData->ApConfigSave[1] = pBuffer[1] | read_back[1]; | |
pActiveFuseData->ApConfigSave[2] = pBuffer[2] | read_back[2]; | |
//Set Burn Request | |
pActiveFuseData->BurnRequest |= K_AP_CONFIG_BURN_REQUEST_MASK; | |
return 0; | |
} | |
UINT_T GEU_SetupTopConfigFuseBits(UINT_T* pBuffer, UINT_T Size) | |
{ | |
UINT_T scratch; | |
UINT_T temp; | |
UINT_T read_back; | |
if (Size != K_TOP_CONFIG_FUSE_SIZE) | |
{ | |
return FUSE_BufferTooSmall; | |
} | |
// Confirm this fuseblock is active | |
if (g_ActiveFuseData.ActiveFuseBlock != K_TOP_CONFIG_FUSEBLOCK) | |
{ | |
return (FUSE_FuseBlockNotActive); | |
} | |
// Check and Set Active FuseBlock Field | |
if (!(pActiveFuseData->ActiveFuseBlockField & K_TOP_FUSEBLOCK_FIELD)) | |
{ | |
pActiveFuseData->ActiveFuseBlockField |= K_TOP_FUSEBLOCK_FIELD; | |
} | |
//Low16 bit is CP configs | |
temp = pBuffer[0] & 0xFFFF; | |
//Save the setup data to GEU_FUSE_PROG_VAL1 | |
_geuUpdateRegister(GEU_FUSE_PROG_VAL1+0, temp, 0x0000FFFF); | |
//In case that AP config is not empty | |
GEU_ReadCpConfigFuseBits(&read_back, K_TOP_CONFIG_FUSE_SIZE); | |
// Save to Active fuseblock for burn validation later | |
pActiveFuseData->TopConfigSave[0] = pBuffer[0] | read_back; | |
//Set Burn Request | |
pActiveFuseData->BurnRequest |= K_TOP_CONFIG_BURN_REQUEST_MASK; | |
return 0; | |
} | |
UINT_T GEU_SetupLifeCycleFuseBits(UINT_T* pBuffer, UINT_T Size) | |
{ | |
UINT_T lcs; | |
UINT_T read_back; | |
if (Size != K_LCS_FUSE_SIZE) | |
{ | |
return FUSE_BufferTooSmall; | |
} | |
lcs = pBuffer[0]; | |
// Confirm this fuseblock is active | |
if (g_ActiveFuseData.ActiveFuseBlock != K_LIFECYCLE_FUSEBLOCK) | |
{ | |
return (FUSE_FuseBlockNotActive); | |
} | |
// Check and Set Active FuseBlock Field | |
if (!(pActiveFuseData->ActiveFuseBlockField & K_LIFECYCLE_FUSEBLOCK_FIELD)) | |
{ | |
pActiveFuseData->ActiveFuseBlockField |= K_LIFECYCLE_FUSEBLOCK_FIELD; | |
} | |
read_back = GEU_ReadLifeCycleState(); | |
pActiveFuseData->LifeCycleSave = lcs | read_back; | |
//Save the setup data to GEU_FUSE_PROG_VAL1 | |
_geuUpdateRegister(GEU_FUSE_PROG_VAL1+4, lcs, 0x0000FFFF); | |
//Set Burn Request | |
pActiveFuseData->BurnRequest |= K_LIFECYCLE_BURN_REQUEST_MASK; | |
return 0; | |
} | |
UINT_T GEU_SetupHWLockFuseBits(UINT_T* pBuffer, UINT_T Size) | |
{ | |
UINT_T HwLock; | |
UINT_T read_back; | |
if (Size != K_HWLOCK_FUSE_SIZE) | |
{ | |
return FUSE_BufferTooSmall; | |
} | |
HwLock = pBuffer[0]; | |
// Confirm this fuseblock is active | |
if (g_ActiveFuseData.ActiveFuseBlock != K_HWLOCK_FUSEBLOCK) | |
{ | |
return (FUSE_FuseBlockNotActive); | |
} | |
// Check and Set Active FuseBlock Field | |
if (!(pActiveFuseData->ActiveFuseBlockField & K_HWLOCK_FUSEBLOCK_FIELD)) | |
{ | |
pActiveFuseData->ActiveFuseBlockField |= K_HWLOCK_FUSEBLOCK_FIELD; | |
} | |
read_back = GEU_ReadHWLockState(); | |
pActiveFuseData->HWLockSave = HwLock | read_back; | |
//Save the setup data to GEU_FUSE_PROG_VAL1 | |
_geuUpdateRegister(GEU_FUSE_PROG_VAL1+0, HwLock, 0x0000FFFF); | |
//Set Burn Request | |
pActiveFuseData->BurnRequest |= K_HWLOCK_BURN_REQUEST_MASK; | |
return 0; | |
} | |
UINT_T GEU_SetupOemHashKeyFuseBits(UINT_T* pBuffer, UINT_T Size) | |
{ | |
UINT_T scratch; | |
if (Size != K_OEM_HASH_FUSE_SIZE) | |
{ | |
return FUSE_InvalidBufferSize; | |
} | |
// Confirm this fuseblock is active | |
if (g_ActiveFuseData.ActiveFuseBlock != K_OEM_FUSEBLOCK) | |
{ | |
return (FUSE_FuseBlockNotActive); | |
} | |
// Check and Set Active FuseBlock Field | |
if (!(pActiveFuseData->ActiveFuseBlockField & K_OEM0_FUSEBLOCK_FIELD)) | |
{ | |
pActiveFuseData->ActiveFuseBlockField |= K_OEM0_FUSEBLOCK_FIELD; | |
} | |
// Clear Burn Data in the Active Fuse Data Structure | |
// JLC: _geuClearActiveFuseData(); | |
// Save to Active fuseblock for burn validation later | |
pActiveFuseData->FuseBlockSave[0] = pBuffer[0]; | |
pActiveFuseData->FuseBlockSave[1] = pBuffer[1]; | |
pActiveFuseData->FuseBlockSave[2] = pBuffer[2]; | |
pActiveFuseData->FuseBlockSave[3] = pBuffer[3]; | |
pActiveFuseData->FuseBlockSave[4] = pBuffer[4]; | |
pActiveFuseData->FuseBlockSave[5] = pBuffer[5]; | |
pActiveFuseData->FuseBlockSave[6] = pBuffer[6]; | |
pActiveFuseData->FuseBlockSave[7] = pBuffer[7]; | |
//Save the setup data to GEU_FUSE_PROG_VAL1/VAL2 | |
GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+0, pBuffer[0]); | |
GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+4, pBuffer[1]); | |
GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+8, pBuffer[2]); | |
GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+12, pBuffer[3]); | |
GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+0, pBuffer[4]); | |
GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+4, pBuffer[5]); | |
GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+8, pBuffer[6]); | |
GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+12, pBuffer[7]); | |
//Set Burn Request | |
pActiveFuseData->BurnRequest |= K_OEM_KEY0_BURN_REQUEST_MASK; | |
return 0; | |
}//End Routine GEU_SetupOemHashFuseBits | |
UINT_T GEU_SetupPlatVersionFuseBits(UINT_T* pBuffer, UINT_T Size) | |
{ | |
UINT_T temp[2]; | |
UINT_T read_back; | |
if (Size != K_PLAT_VERSION_FUSE_SIZE) | |
{ | |
return FUSE_BufferTooSmall; | |
} | |
// Confirm this fuseblock is active | |
if (g_ActiveFuseData.ActiveFuseBlock != K_PLAT_VERSION_FUSEBLOCK) | |
{ | |
return (FUSE_FuseBlockNotActive); | |
} | |
// Check and Set Active FuseBlock Field | |
if (!(pActiveFuseData->ActiveFuseBlockField & K_PLAT_VERSION_FUSEBLOCK_FIELD)) | |
{ | |
pActiveFuseData->ActiveFuseBlockField |= K_PLAT_VERSION_FUSEBLOCK_FIELD; | |
} | |
//Low16 bit is CP configs | |
temp[0] = (pBuffer[0] & 0xFFFF) << 16; | |
temp[1] = (pBuffer[0] >> 16) & 0xFFFF; | |
//Save the setup data to GEU_FUSE_PROG_VAL6/VAL7 | |
_geuUpdateRegister(GEU_FUSE_PROG_VAL1+24, temp[0], 0xFFFF0000); | |
_geuUpdateRegister(GEU_FUSE_PROG_VAL1+28, temp[1], 0x0000FFFF); | |
//In case that AP config is not empty | |
read_back = GEU_ReadSoftwareVersion(); | |
// Save to Active fuseblock for burn validation later | |
pActiveFuseData->SoftwareVersionSave[0] = pBuffer[0] | read_back; | |
pActiveFuseData->SoftwareVersionSave[1] = 0; | |
//Set Burn Request | |
pActiveFuseData->BurnRequest |= K_PLAT_VERSION_BURN_REQUEST_MASK; | |
return 0; | |
} | |
UINT_T GEU_BurnFuseBlock_OemHashKey(struct GEU_FuseBurnStatus * pUserFuseBurnStatus) | |
{ | |
UINT_T temp[8]; // temp buffer for fuse block compares | |
UINT_T status; | |
// Confirm this fuseblock is active | |
if (pActiveFuseData->ActiveFuseBlock != K_OEM_FUSEBLOCK) | |
{ | |
return (FUSE_FuseBlockNotActive); | |
} | |
// Save the burn request in the FuseBurnStatus | |
pFuseBurnStatus->SavedBurnRequest = pActiveFuseData->BurnRequest; | |
if ((pActiveFuseData->BurnRequest & K_OEM_KEY0_BURN_REQUEST_MASK) == 0) | |
{ | |
pFuseBurnStatus->FinalBurnStatus = FUSE_NoBurnRequest ; | |
return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus)); | |
} | |
// Burn Count = 0 | |
pActiveFuseData->BurnCount = 0; | |
while (pActiveFuseData->BurnRequest) | |
{ | |
//++ ****** Burn ********** | |
status = _geuBurnFuse(K_OEM_FUSEBLOCK, 0); // Burn and NOT Lock OEM Key Hash | |
//-- ****** Burn ********** | |
if (status != 0) | |
{ | |
pFuseBurnStatus->DebugStatus = status; | |
} | |
// Burn Count++ | |
pActiveFuseData->BurnCount++; | |
if (pActiveFuseData->BurnCount > 1) | |
{ | |
pFuseBurnStatus->DebugStatus |= K_MULTIPLE_BURN_COUNT; | |
} | |
//******************************************************************** | |
// Validate the OEM Hash Burn | |
//******************************************************************** | |
if ((pActiveFuseData->BurnRequest & K_OEM_KEY0_BURN_REQUEST_MASK) != 0) | |
{ | |
//Compare Burned value with Saved value | |
status = GEU_ReadOemHashKeyFuseBits(&temp[0], K_FUSEBLOCK_SIZE); | |
status = _geu_compare(&pActiveFuseData->FuseBlockSave[0], | |
&temp[0], | |
K_FUSEBLOCK_SIZE); | |
if (status == 0) | |
{ | |
// AP Burn Good - Clear the Burn Request | |
pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest | |
& ~K_OEM_KEY0_BURN_REQUEST_MASK; | |
} | |
else | |
{ | |
// If the BurnCount is 1, leave the burn request set | |
// for another try. | |
// Else | |
if (pActiveFuseData->BurnCount >= 2) | |
{ | |
// Burn Failed two times - Clear the burn Request | |
pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest | |
& ~K_OEM_KEY0_BURN_REQUEST_MASK; | |
// Set the AP Raw Burn Status to indicate Failure | |
pFuseBurnStatus->RawBurnStatus = pFuseBurnStatus->RawBurnStatus | | |
K_OEM_KEY0_STATUS_BIT_MASK; | |
} | |
}//EndIfElse | |
}//Endif | |
}//End While | |
// Set status | |
pFuseBurnStatus->CorrectedBurnStatus = pFuseBurnStatus->RawBurnStatus; | |
pFuseBurnStatus->FinalBurnStatus = NoError; | |
if(pFuseBurnStatus->CorrectedBurnStatus != 0) | |
{ | |
pFuseBurnStatus->FinalBurnStatus = FUSE_BurnError; | |
} | |
return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus)); | |
}// End Routine GEU_BurnFuseBlock_OEM_Platform_Hash | |
UINT_T GEU_BurnFuseBlock_SocConfig(struct GEU_FuseBurnStatus * pUserFuseBurnStatus) | |
{ | |
UINT_T temp[8]; // temp buffer for fuse block compares | |
UINT_T status; | |
// Confirm this fuseblock is active | |
if (pActiveFuseData->ActiveFuseBlock != K_AP_CONFIG_FUSEBLOCK) | |
{ | |
return (FUSE_FuseBlockNotActive); | |
} | |
// Confirm bandgap from USB PHY is enabled for the fuse power regulator | |
if( _geuConfirmPowerEnabledForFuseBurning() == 0) | |
{ | |
pFuseBurnStatus->FinalBurnStatus = FUSE_FuseBurnPowerNotEnabled; | |
return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus)); | |
} | |
// Save the burn request in the FuseBurnStatus | |
pFuseBurnStatus->SavedBurnRequest = pActiveFuseData->BurnRequest; | |
if (pActiveFuseData->BurnRequest & K_AP_CONFIG_BURN_REQUEST_MASK == 0) | |
{ | |
pFuseBurnStatus->FinalBurnStatus = FUSE_IncompleteFuseFieldsSetup; | |
return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus)); | |
} | |
// Burn Count = 0 | |
pActiveFuseData->BurnCount = 0; | |
while (pActiveFuseData->BurnRequest) | |
{ | |
//++ ****** Burn ********** | |
status = _geuBurnFuse(K_AP_CONFIG_FUSEBLOCK, 0); | |
//-- ****** Burn ********** | |
if (status != 0) | |
{ | |
pFuseBurnStatus->DebugStatus = status; | |
} | |
// Burn Count++ | |
pActiveFuseData->BurnCount++; | |
if (pActiveFuseData->BurnCount > 1) | |
{ | |
pFuseBurnStatus->DebugStatus |= K_MULTIPLE_BURN_COUNT; | |
} | |
//******************************************************************** | |
// Validate the components burned (ones with a burn request) | |
//******************************************************************** | |
// Validate Security CONFIG Burn Request | |
//******************************************************************** | |
//++ | |
if ((pActiveFuseData->BurnRequest & K_AP_CONFIG_BURN_REQUEST_MASK) != 0) | |
{ | |
//Compare Burned Security with Saved Security Config Bits | |
status = GEU_ReadApConfigFuseBits(&temp[0], | |
K_AP_CONFIG_FUSE_SIZE); | |
// Ignore status - whatever we read, we read | |
status = _geu_compare(&pActiveFuseData->ApConfigSave[0], | |
&temp[0], | |
K_AP_CONFIG_FUSE_SIZE); | |
if (status == 0) | |
{ | |
// Security Config Burn Good - Clear the Burn Request | |
pActiveFuseData->BurnRequest &= ~K_AP_CONFIG_BURN_REQUEST_MASK; | |
} | |
else | |
{ | |
// If the BurnCount is 1, leave the burn request set | |
// for another try. | |
// Else | |
if (pActiveFuseData->BurnCount >= 2) | |
{ | |
// Security Burn Failed two times - Clear the burn Request | |
pActiveFuseData->BurnRequest &= ~K_AP_CONFIG_BURN_REQUEST_MASK; | |
// Set the Security Raw Burn Status to indicate Failure | |
pFuseBurnStatus->RawBurnStatus |= K_AP_CONFIG_BURN_REQUEST_MASK; | |
} | |
}//EndIfElse | |
}//Endif | |
//-- Validate AP CONFIG Burn Request | |
if ((pActiveFuseData->BurnRequest & K_TOP_CONFIG_BURN_REQUEST_MASK) != 0) | |
{ | |
status = GEU_ReadCpConfigFuseBits(&temp[0], | |
K_TOP_CONFIG_FUSE_SIZE); | |
// Ignore status - whatever we read, we read | |
status = _geu_compare(&pActiveFuseData->TopConfigSave[0], | |
&temp[0], | |
K_TOP_CONFIG_FUSE_SIZE); | |
if (status == 0) | |
{ | |
// TOP Config Burn Good - Clear the Burn Request | |
pActiveFuseData->BurnRequest &= ~K_TOP_CONFIG_BURN_REQUEST_MASK; | |
} | |
else | |
{ | |
// If the BurnCount is 1, leave the burn request set | |
// for another try. | |
// Else | |
if (pActiveFuseData->BurnCount >= 2) | |
{ | |
// Security Burn Failed two times - Clear the burn Request | |
pActiveFuseData->BurnRequest &= ~K_TOP_CONFIG_BURN_REQUEST_MASK; | |
// Set the Security Raw Burn Status to indicate Failure | |
pFuseBurnStatus->RawBurnStatus |= K_TOP_CONFIG_BURN_REQUEST_MASK; | |
} | |
}//EndIfElse | |
}//Endif | |
//-- Validate TOP CONFIG Burn Request | |
if ((pActiveFuseData->BurnRequest & K_PLAT_VERSION_BURN_REQUEST_MASK) != 0 ) | |
{ | |
//Compare Burned Security with Saved Security Config Bits | |
temp[0] = GEU_ReadSoftwareVersion(); | |
// Ignore status - whatever we read, we read | |
status = _geu_compare(&pActiveFuseData->SoftwareVersionSave[0], | |
&temp[0], | |
K_PLAT_VERSION_FUSE_SIZE); | |
if (status == 0) | |
{ | |
pActiveFuseData->BurnRequest &= ~K_PLAT_VERSION_BURN_REQUEST_MASK; | |
} | |
else | |
{ | |
if (pActiveFuseData->BurnCount >= 2) | |
{ | |
// LCS Burn Failed two times - Clear the burn Request | |
pActiveFuseData->BurnRequest &= ~K_PLAT_VERSION_BURN_REQUEST_MASK; | |
// Set the Raw Burn Status to indicate Failure | |
pFuseBurnStatus->RawBurnStatus |= K_PLAT_VERSION_BURN_REQUEST_MASK; | |
} | |
}//EndIfElse | |
}//Endif | |
} | |
// Set status | |
pFuseBurnStatus->CorrectedBurnStatus = pFuseBurnStatus->RawBurnStatus; | |
if(pFuseBurnStatus->CorrectedBurnStatus != 0) | |
{ | |
pFuseBurnStatus->FinalBurnStatus = FUSE_BurnError; | |
} | |
return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus)); | |
}//End Routine GEU_BurnFuseBlock_SocConfig | |
UINT_T GEU_BurnFuseBlock_MISCConfig(struct GEU_FuseBurnStatus * pUserFuseBurnStatus) | |
{ | |
UINT_T temp[2]; // temp buffer for fuse block compares | |
UINT_T status; | |
// Confirm this fuseblock is active | |
if (pActiveFuseData->ActiveFuseBlock != K_HWLOCK_LCS_FUSEBLOCK) | |
{ | |
return (FUSE_FuseBlockNotActive); | |
} | |
// Confirm bandgap from USB PHY is enabled for the fuse power regulator | |
if( _geuConfirmPowerEnabledForFuseBurning() == 0) | |
{ | |
pFuseBurnStatus->FinalBurnStatus = FUSE_FuseBurnPowerNotEnabled; | |
return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus)); | |
} | |
// Save the burn request in the FuseBurnStatus | |
pFuseBurnStatus->SavedBurnRequest = pActiveFuseData->BurnRequest; | |
if (pActiveFuseData->BurnRequest & K_HWLOCK_LCS_BURN_REQUEST_MASK == 0) | |
{ | |
return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus)); | |
} | |
pActiveFuseData->BurnCount = 0; | |
while (pActiveFuseData->BurnRequest) | |
{ | |
//++ ****** Burn ********** | |
status = _geuBurnFuse(K_HWLOCK_LCS_FUSEBLOCK, 0); | |
//-- ****** Burn ********** | |
if (status != 0) | |
{ | |
pFuseBurnStatus->DebugStatus = status; | |
} | |
// Burn Count++ | |
pActiveFuseData->BurnCount++; | |
if (pActiveFuseData->BurnCount > 1) | |
{ | |
pFuseBurnStatus->DebugStatus |= K_MULTIPLE_BURN_COUNT; | |
} | |
//******************************************************************** | |
// Validate the components burned (ones with a burn request) | |
//******************************************************************** | |
if ((pActiveFuseData->BurnRequest & K_LIFECYCLE_BURN_REQUEST_MASK) != 0) | |
{ | |
temp[0] = GEU_ReadLifeCycleState(); | |
// Ignore status - whatever we read, we read | |
status = _geu_compare(&pActiveFuseData->LifeCycleSave, | |
&temp[0], | |
K_LCS_FUSE_SIZE); | |
if (status == 0) | |
{ | |
// Security Config Burn Good - Clear the Burn Request | |
pActiveFuseData->BurnRequest &= ~K_LIFECYCLE_BURN_REQUEST_MASK; | |
} | |
else | |
{ | |
// If the BurnCount is 1, leave the burn request set | |
// for another try. | |
// Else | |
if (pActiveFuseData->BurnCount >= 2) | |
{ | |
// Security Burn Failed two times - Clear the burn Request | |
pActiveFuseData->BurnRequest &= ~K_LIFECYCLE_BURN_REQUEST_MASK; | |
// Set the Security Raw Burn Status to indicate Failure | |
pFuseBurnStatus->RawBurnStatus |= K_LIFECYCLE_BURN_REQUEST_MASK; | |
} | |
}//EndIfElse | |
}//Endif | |
if ((pActiveFuseData->BurnRequest & K_HWLOCK_BURN_REQUEST_MASK) != 0) | |
{ | |
temp[1] = GEU_ReadHWLockState(); | |
// Ignore status - whatever we read, we read | |
status = _geu_compare(&pActiveFuseData->HWLockSave, | |
&temp[1], | |
K_HWLOCK_FUSE_SIZE); | |
if (status == 0) | |
{ | |
// TOP Config Burn Good - Clear the Burn Request | |
pActiveFuseData->BurnRequest &= ~K_HWLOCK_BURN_REQUEST_MASK; | |
} | |
else | |
{ | |
// If the BurnCount is 1, leave the burn request set | |
// for another try. | |
// Else | |
if (pActiveFuseData->BurnCount >= 2) | |
{ | |
// Security Burn Failed two times - Clear the burn Request | |
pActiveFuseData->BurnRequest &= ~K_HWLOCK_BURN_REQUEST_MASK; | |
// Set the Security Raw Burn Status to indicate Failure | |
pFuseBurnStatus->RawBurnStatus |= K_HWLOCK_BURN_REQUEST_MASK; | |
} | |
}//EndIfElse | |
}//Endif | |
} | |
// Set status | |
pFuseBurnStatus->CorrectedBurnStatus = pFuseBurnStatus->RawBurnStatus; | |
if(pFuseBurnStatus->CorrectedBurnStatus != 0) | |
{ | |
pFuseBurnStatus->FinalBurnStatus = FUSE_BurnError; | |
} | |
return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus)); | |
}//End Routine GEU_BurnFuseBlock_HwLockLCS |