blob: e11f97b2d1eafb84610b6989a691d87bf44df896 [file] [log] [blame]
// 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