blob: 991c6b5f68784f775eefde02c02e4db6946302c7 [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 = (1 << 3) | 1;
//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_APCP_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_SetupCpConfigFuseBits(UINT_T* pBuffer, UINT_T Size)
{
UINT_T scratch;
UINT_T temp;
UINT_T read_back;
if (Size != K_CP_CONFIG_FUSE_SIZE)
{
return FUSE_BufferTooSmall;
}
// Confirm this fuseblock is active
if (g_ActiveFuseData.ActiveFuseBlock != K_CP_CONFIG_FUSEBLOCK)
{
return (FUSE_FuseBlockNotActive);
}
// Check and Set Active FuseBlock Field
if (!(pActiveFuseData->ActiveFuseBlockField & K_CP_FUSEBLOCK_FIELD))
{
pActiveFuseData->ActiveFuseBlockField |= K_CP_FUSEBLOCK_FIELD;
}
// Clear Burn Data in the Active Fuse Data Structure
// JLC: _geuClearActiveFuseData();
//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_CP_CONFIG_FUSE_SIZE);
// Save to Active fuseblock for burn validation later
pActiveFuseData->CpConfigSave[0] = pBuffer[0] | read_back;
//Set Burn Request
pActiveFuseData->BurnRequest |= K_CP_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_VAL2+8, lcs, 0x0000FFFF);
//Set Burn Request
pActiveFuseData->BurnRequest |= K_LIFECYCLE_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_SetupRkekFuseBits(UINT_T* pBuffer, UINT_T Size)
{
UINT_T scratch;
if (Size != K_RKEK_FUSE_SIZE)
{
return FUSE_InvalidBufferSize;
}
// Confirm this fuseblock is active
if (g_ActiveFuseData.ActiveFuseBlock != K_RKEK_FUSEBLOCK)
{
return (FUSE_FuseBlockNotActive);
}
// Check and Set Active FuseBlock Field
if (!(pActiveFuseData->ActiveFuseBlockField & K_RKEK_FUSEBLOCK_FIELD))
{
pActiveFuseData->ActiveFuseBlockField |= K_RKEK_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_RKEK_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_RKEK(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_RKEK_FUSEBLOCK)
{
return (FUSE_FuseBlockNotActive);
}
// Save the burn request in the FuseBurnStatus
pFuseBurnStatus->SavedBurnRequest = pActiveFuseData->BurnRequest;
if ((pActiveFuseData->BurnRequest & K_RKEK_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_RKEK_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_RKEK_BURN_REQUEST_MASK) != 0)
{
//Compare Burned value with Saved value
status = GEU_ReadRkekFuseBits(&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_RKEK_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_RKEK_BURN_REQUEST_MASK;
// Set the AP Raw Burn Status to indicate Failure
pFuseBurnStatus->RawBurnStatus = pFuseBurnStatus->RawBurnStatus |
K_RKEK_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_SOC_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_SOC_COFNIG_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_CP_CONFIG_BURN_REQUEST_MASK) != 0)
{
status = GEU_ReadCpConfigFuseBits(&temp[0],
K_CP_CONFIG_FUSE_SIZE);
// Ignore status - whatever we read, we read
status = _geu_compare(&pActiveFuseData->CpConfigSave[0],
&temp[0],
K_CP_CONFIG_FUSE_SIZE);
if (status == 0)
{
// CP Config Burn Good - Clear the Burn Request
pActiveFuseData->BurnRequest &= ~K_CP_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_CP_CONFIG_BURN_REQUEST_MASK;
// Set the Security Raw Burn Status to indicate Failure
pFuseBurnStatus->RawBurnStatus |= K_CP_CONFIG_BURN_REQUEST_MASK;
}
}//EndIfElse
}//Endif
//-- Validate CP CONFIG Burn Request
#if CLOSE_JTAG
if ((pActiveFuseData->BurnRequest & K_LIFECYCLE_BURN_REQUEST_MASK) != 0)
{
//Compare Burned Security with Saved Security Config Bits
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)
{
// LCS 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)
{
// LCS Burn Failed two times - Clear the burn Request
pActiveFuseData->BurnRequest &= ~K_LIFECYCLE_BURN_REQUEST_MASK;
// Set the Raw Burn Status to indicate Failure
pFuseBurnStatus->RawBurnStatus |= K_LIFECYCLE_BURN_REQUEST_MASK;
}
}//EndIfElse
}//Endif
//-- Validate LCS Burn Request
#endif //CLOSE_JTAG
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
#if ENABLE_BITS_BURN
UINT_T GEU_FuseBankBitBurn(UINT_T BankNum, UINT_T StartBit, UINT_T BitCouts)
{
UINT_T result;
UINT_T status;
UINT_T BurnBuffer[8];
UINT_T ReadBuffer[8];
if (((StartBit + BitCouts) > 256) || (StartBit > 255) || (BitCouts == 0)) {
return FUSE_InvalidFuseBlockField;
}
/* make sure power supply required for fuse programming is enabled */
result = GEU_EnableFuseBurnPower();
if (result != NoError) {
return FUSE_FuseBurnPowerNotEnabled;
}
result = GEU_SetActiveFuseBlock(BankNum);
if (result != NoError) {
return result;
}
memset(BurnBuffer, 0, sizeof(BurnBuffer));
/* setup burn bits */
for (UINT_T i = StartBit; i < (StartBit + BitCouts); i++) {
BurnBuffer[i/32] |= (1 << (i%32));
}
for (UINT_T i = 0; i < 8; i++) {
GEU_REG_WRITE(GEU_FUSE_PROG_VAL1 + i*4, BurnBuffer[i]);
}
/* burn bits */
status = _geuBurnFuse(BankNum, 0);
if (status != 0) {
return FUSE_BurnError;
}
/* compare whether the burn is correct */
memset(ReadBuffer, 0, sizeof(ReadBuffer));
GEU_ReadFuseBank(ReadBuffer, BankNum);
for (UINT_T i = 0; i < 8; i++) {
if ((BurnBuffer[i] & ReadBuffer[i]) != BurnBuffer[i]) {
status = FUSE_BurnError;
break;
}
}
if (status == FUSE_BurnError) {
/* second burn bits */
status = _geuBurnFuse(BankNum, 0);
if (status != 0) {
return FUSE_BurnError;
}
/* compare whether the second burn is correct */
memset(ReadBuffer, 0, sizeof(ReadBuffer));
GEU_ReadFuseBank(ReadBuffer, BankNum);
for (UINT_T i = 0; i < 8; i++) {
if ((BurnBuffer[i] & ReadBuffer[i]) != BurnBuffer[i]) {
return FUSE_BurnError;
}
}
}
return NoError;
}
#endif