blob: 452af3c20369112c72792bc25098ba612d46f449 [file] [log] [blame]
// FuseReadMethods.c
//
/******************************************************************************
*
* (C)Copyright 2005 - 2011 Marvell. All Rights Reserved.
*
* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL.
* The copyright notice above does not evidence any actual or intended
* publication of such source code.
* This Module contains Proprietary Information of Marvell and should be
* treated as Confidential.
* The information in this file is provided for the exclusive use of the
* licensees of Marvell.
* Such users have the right to use, modify, and incorporate this code into
* products for purposes authorized by the license agreement provided they
* include this notice and the associated copyright notice with any such
* product.
* The information in this file is provided "AS IS" without warranty.
******************************************************************************/
#include <Typedef.h>
#include <predefines.h>
#include <Errors.h>
#include "GEU.h"
#include "platform_geu_fuse_internal.h"
#include "geu_interface.h"
#include "GEU_FuseReadMethods.h"
// returns number of ones set in value
UINT_T countOnes(UINT_T value)
{
UINT_T i=0;
for(i=0;value;i++)
value &=(value-1);
return i;
}
/************************************
* Returns current Lifecycle
************************************/
UINT_T GEU_ReadLifeCycle()
{
UINT_T regValue, lifeCycleCount = 0;
GEU_REG_READ(GEU_FUSE_VAL_LIFECYCLE_DM_CM, regValue);
// Check CM
//lifeCycleCount += countOnes((regValue & GEU_FUSE_VAL_LIFECYCLE_CM_MSK) >> GEU_FUSE_VAL_LIFECYCLE_CM_BASE);
lifeCycleCount += PHYSICAL_TO_LOGICAL((regValue & GEU_FUSE_VAL_LIFECYCLE_CM_MSK) >> GEU_FUSE_VAL_LIFECYCLE_CM_BASE);
// Check DM
lifeCycleCount += PHYSICAL_TO_LOGICAL((regValue & GEU_FUSE_VAL_LIFECYCLE_DM_MSK) >> GEU_FUSE_VAL_LIFECYCLE_DM_BASE);
GEU_REG_READ(GEU_FUSE_VAL_LIFECYCLE_JPD_FA_DD_OEM_UID_ECC, regValue);
// Check DD
lifeCycleCount += PHYSICAL_TO_LOGICAL((regValue & GEU_FUSE_VAL_LIFECYCLE_DD_MSK) >> GEU_FUSE_VAL_LIFECYCLE_DD_BASE);
// Check FA
lifeCycleCount += PHYSICAL_TO_LOGICAL((regValue & GEU_FUSE_VAL_LIFECYCLE_FA_MSK) >> GEU_FUSE_VAL_LIFECYCLE_FA_BASE);
// Check JPD
lifeCycleCount += PHYSICAL_TO_LOGICAL((regValue & GEU_FUSE_VAL_LIFECYCLE_JPD_MSK) >> GEU_FUSE_VAL_LIFECYCLE_JPD_BASE);
return lifeCycleCount;
}
/***********************************************************
* Function:
* GEU_GenerateRandomNumber
*
* Description:
* Generates a random number.
*
*
* Input:
* Seed - Seed number. Range 0-255. Larger number takes
* less time to generate result.
* Output:
* none
* Returns:
* Returns 32 bit random number.
*
************************************************************/
UINT_T GEU_GenerateRandomNumber (UINT_T Seed)
{
UINT_T OldNumber, NewNumber;
GEU_REG_READ(GEU_HW_RANDOM_NUM_GEN, OldNumber);
GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+0, (Seed & 0x000000FF));
GEU_REG_READ(GEU_HW_RANDOM_NUM_GEN, NewNumber);
while (OldNumber == NewNumber)
{
GEU_REG_READ(GEU_HW_RANDOM_NUM_GEN, NewNumber);
}
return(NewNumber);
};
/***********************************************************
* Function:
* FUSE_ReadSOCConfigFuseBits
*
* Description:
* Reads the AP Config fuse bits (80 bits/10 bytes).
*
* Input:
* pBuffer - Pointer to buffer to write the requested data.
* Size - Size of buffer in bytes (Must be > K_AP_CONFIG_FUSE_SIZE).
* Output:
* none
* Returns:
* NoError
* FUSE_BufferTooSmall
* FUSE_UncorrectableEccError
*
************************************************************/
UINT_T GEU_ReadAPCPConfigFuseBits(UINT_T* pBuffer, UINT_T Size)
{
UINT_T scratch;
if (Size < K_APCP_CONFIG_FUSE_SIZE)
{
return (FUSE_BufferTooSmall);
}
GEU_REG_READ(GEU_FUSE_VAL_APCFG1, pBuffer[0]);
GEU_REG_READ(GEU_FUSE_VAL_APCFG2, pBuffer[1]);
GEU_REG_READ(GEU_FUSE_VAL_APCFG3, pBuffer[2]);
// Check if ECC enabled and any uncorrectable errors
GEU_REG_READ(GEU_AP_CP_MP_ECC, scratch);
if ((scratch & GEU_AP_CP_MP_ECC_MASK) != 0)
{
GEU_REG_READ(GEU_ECC_STATUS0, scratch);
if (scratch & K_APCPMP0_UNCORRECTABLE_ECC_ERROR_MASK)
{
return FUSE_UncorrectableEccError;
}
}
return NoError;
};
/***********************************************************
* Function:
* GEU_ReadApConfigFuseBits
*
* Description:
* Reads the AP Config fuse bits (80 bits/10 bytes).
*
* Input:
* pBuffer - Pointer to buffer to write the requested data.
* Size - Size of buffer in bytes (Must be > K_AP_CONFIG_FUSE_SIZE).
* Output:
* none
* Returns:
* NoError
* FUSE_BufferTooSmall
* FUSE_UncorrectableEccError
*
************************************************************/
UINT_T GEU_ReadApConfigFuseBits(UINT_T* pBuffer, UINT_T Size)
{
UINT_T scratch;
if (Size < K_AP_CONFIG_FUSE_SIZE)
{
return (FUSE_BufferTooSmall);
}
/*
GEU_REG_READ(GEU_FUSE_VAL_APCFG1, pBuffer[0]);
GEU_REG_READ(GEU_FUSE_VAL_APCFG2, pBuffer[1]);
GEU_REG_READ(GEU_FUSE_VAL_APCFG3, scratch);
//AP is lower 16 bits - mask out upper 16 bits(CP)
pBuffer[2] = scratch & GEU_APCFG3_AP_MASK;
*/
//JML CP is lower 16 bits at APCFG1, so shift in all values 16 bits at a time
GEU_REG_READ(GEU_FUSE_VAL_APCFG1, scratch);
pBuffer[0] = ((scratch & (SHIFT16(0xffff))) >> 16);
//Lower 16 bits of APCFG2 to upper 16 bits of Buffer[0]
GEU_REG_READ(GEU_FUSE_VAL_APCFG2, scratch);
pBuffer[0] |= ((scratch & (SHIFT0(0xffff))) << 16);
//Upper 16 bits of APCFG2 to lower 16 bits of Buffer[1]
pBuffer[1] = ((scratch & (SHIFT16(0xffff))) >> 16);
//Lower 16 bits of APCFG3 to upper 16 bits of Buffer[1]
GEU_REG_READ(GEU_FUSE_VAL_APCFG3, scratch);
pBuffer[1] |= ((scratch & (SHIFT0(0xffff))) << 16);
//Upper 16 bits of APCFG3 to lower 16 bits of Buffer[2]
pBuffer[2] = ((scratch & (SHIFT16(0xffff))) >> 16);
// Check if ECC enabled and any uncorrectable errors
GEU_REG_READ(GEU_FUSE_VAL_APCPMP_ECC, scratch);
if ((scratch & GEU_AP_CP_MP_ECC_MASK) != 0)
{
// ECC enabled - Check the ECC_STATUS value
GEU_REG_READ(GEU_ECC_STATUS, scratch);
if (scratch & K_APCPMP0_UNCORRECTABLE_ECC_ERROR_MASK)
{
return FUSE_UncorrectableEccError;
}
}
return NoError;
};
/***********************************************************
* Function:
* GEU_ReadCpConfigFuseBits
*
* Description:
* Reads the CP Config fuse bits (16 bits/2 bytes).
*
* Input:
* pBuffer - Pointer to buffer to write the requested data.
* Size - Size of buffer in bytes (Must be > K_CP_CONFIG_FUSE_SIZE).
* Output:
* none
* Returns:
* NoError
* FUSE_BufferTooSmall
* FUSE_UncorrectableEccError
*
************************************************************/
UINT_T GEU_ReadCpConfigFuseBits(UINT_T* pBuffer, UINT_T Size)
{
UINT_T scratch;
if (Size < K_CP_CONFIG_FUSE_SIZE)
{
return (FUSE_BufferTooSmall);
}
GEU_REG_READ(GEU_FUSE_VAL_APCFG1, scratch);
//CP is upper 16 bits - just shift right by base offset to normalize
//pBuffer[0] = (scratch >> GEU_APCFG1_CP_BASE_OFFSET);
// JML CP is lower 16 bits, so mask
pBuffer[0] = (scratch & GEU_APCFG1_CP_MASK);
// Check if ECC enabled and any uncorrectable errors
GEU_REG_READ(GEU_FUSE_VAL_APCPMP_ECC, scratch);
if ((scratch & GEU_AP_CP_MP_ECC_MASK) != 0)
{
// ECC enabled - Check the ECC_STATUS value
GEU_REG_READ(GEU_ECC_STATUS, scratch);
if (scratch & K_APCPMP0_UNCORRECTABLE_ECC_ERROR_MASK)
{
return FUSE_UncorrectableEccError;
}
}
return NoError;
};
/***********************************************************
* Function:
* FUSE_ReadOemHashKeyFuseBits
*
* Description:
* Reads the OEM Hash key fuse bits (256 bits/32 bytes).
*
* Input:
* pBuffer - Pointer to buffer to write the requested data.
* Size - Size of buffer in bytes (Must be >= 32).
* Output:
* none
* Returns:
* NoError
* FUSE_BufferTooSmall
* FUSE_UncorrectableEccError
*
************************************************************/
UINT_T GEU_ReadOemHashKeyFuseBits(UINT_T* pBuffer, UINT_T Size)
{
UINT_T scratch;
if (!((Size == K_SHA1_SIZE)||(Size == K_SHA256_SIZE)))
{
return (FUSE_InvalidBufferSize);
}
// return 20 bytes regardless of size
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY0+0, pBuffer[0]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY0+4, pBuffer[1]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY0+8, pBuffer[2]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY0+12, pBuffer[3]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY0+16, pBuffer[4]);
if (Size == K_SHA256_SIZE) //32
{
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY0+20, pBuffer[5]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY0+24, pBuffer[6]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY0+28, pBuffer[7]);
}
// Check if ECC enabled and any uncorrectable errors
// Regardless of key size, always check ECC on OEM Hash Key 0 only (Fuse Block 2)
// Check for errors on all 4 64bit blocks.
// This is more than the 20 bytes required but the best that we can do.
// Check ECC value on OEM Hash Key 0(Fuse Block 2)
GEU_REG_READ(GEU_FUSE_VAL_OEM_KEY0_HASH_ECC, scratch);
if (scratch !=0)
{
// ECC enabled (in use) - Check the ECC_STATUS on OEM Hash Key 0(Fuse Block 2)
GEU_REG_READ(GEU_ECC_STATUS0, scratch);
if (scratch & K_OEM_KEY_HASH0_UNCORRECTABLE_ECC_ERROR_MASK)
{
return FUSE_UncorrectableEccError;
}
}
return NoError;
};
/***********************************************************
* Function:
* FUSE_ReadOemJtagHashKeyFuseBits
*
* Description:
* Reads the OEM JTAG Hash key fuse bits.
*
* Input:
* pBuffer - Pointer to buffer to write the requested data.
* Size - Size of buffer in bytes (Must be equal to the requested field size).
* Output:
* none
* Returns:
* NoError
* FUSE_InvalidBufferSize
* FUSE_UncorrectableEccError
* FUSE_InvalidFuseBlockField
*
************************************************************/
UINT_T GEU_ReadOemJtagHashKeyFuseBits(UINT_T* pBuffer, UINT_T Size)
{
UINT_T scratch;
if (!((Size == K_SHA1_SIZE)||(Size == K_SHA256_SIZE)))
{
return (FUSE_InvalidBufferSize);
}
// return 20 bytes regardless of size
GEU_REG_READ(GEU_FUSE_VAL_OEM_JTAG_HASH_KEY0+0, pBuffer[0]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_JTAG_HASH_KEY0+4, pBuffer[1]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_JTAG_HASH_KEY0+8, pBuffer[2]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_JTAG_HASH_KEY0+12, pBuffer[3]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_JTAG_HASH_KEY0+16, pBuffer[4]);
if (Size == K_SHA256_SIZE) //32
{
GEU_REG_READ(GEU_FUSE_VAL_OEM_JTAG_HASH_KEY0+20, pBuffer[5]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_JTAG_HASH_KEY0+24, pBuffer[6]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_JTAG_HASH_KEY0+28, pBuffer[7]);
}
// Check if ECC enabled and any uncorrectable errors
// Regardless of key size, always check ECC on OEM Hash Key 0 only (Fuse Block 2)
// Check for errors on all 4 64bit blocks.
// This is more than the 20 bytes required but the best that we can do.
// Check ECC value on OEM Hash Key 0(Fuse Block 2)
GEU_REG_READ(GEU_FUSE_VAL_OEM_KEY0_HASH_ECC, scratch);
if (scratch !=0)
{
// ECC enabled (in use) - Check the ECC_STATUS on OEM Hash Key 0(Fuse Block 2)
GEU_REG_READ(GEU_ECC_STATUS0, scratch);
if (scratch & K_JTAG_KEY_HASH0_UNCORRECTABLE_ECC_ERROR_MASK)
{
return FUSE_UncorrectableEccError;
}
}
return NoError;
}
/***********************************************************
* Function:
* FUSE_ReadUsbIdFuseBits
*
* Description:
* Reads the USB Id fuse bits (32 bits/4 bytes).
* Bootrom only supports 32 bits so only read 32 bits.
*
* Input:
* pBuffer - Pointer to buffer to write the requested data.
* Size - Size of buffer in bytes (Must be > K_USBID_FUSE_SIZE).
* Output:
* none
* Returns:
* NoError
* FUSE_BufferTooSmall
* FUSE_UncorrectableEccError
*
************************************************************/
UINT_T GEU_ReadUsbIdFuseBits(UINT_T* pBuffer, UINT_T Size)
{
UINT_T scratch;
if (Size != K_USBID_FUSE_SIZE)
{
return (FUSE_InvalidBufferSize);
}
// Bootrom only supports 32 bits so only read one register (32 bts of ID).
GEU_REG_READ(GEU_FUSE_VAL_USB_VER_ID, pBuffer[0]);
// Check if ECC enabled (ECC field non-zero) and any uncorrectable errors
// Read ECC field for both USB ID and SECURE_CONFIG fields as they are covered by the same ECC field
GEU_REG_READ(GEU_FUSE_VAL_SECURITY_USB_ECC, scratch);
if ((scratch & GEU_SECURITY_USB_ECC_MASK) != 0)
{
GEU_REG_READ(GEU_ECC_STATUS0, scratch);
scratch = (scratch & K_USBID_SECURITYCFG_UNCORRECTABLE_ECC_ERROR_MASK); // Test only ECC bits non-zero
if (scratch != 0)
{
return FUSE_UncorrectableEccError;
}
}
return NoError;
}
/***********************************************************
* Function:
* GEU_ReadSecurityConfigFuseBits
*
* Description:
* Reads the USB Id fuse bits (32 bits/4 bytes).
* Bootrom only supports 32 bits so only read 32 bits.
*
* Input:
* pBuffer - Pointer to buffer to write the requested data.
* Size - Size of buffer in bytes (Must be > K_USBID_FUSE_SIZE).
* Output:
* none
* Returns:
* NoError
* FUSE_BufferTooSmall
* FUSE_UncorrectableEccError
*
************************************************************/
UINT_T GEU_ReadSecurityConfigFuseBits(UINT_T* pBuffer, UINT_T Size)
{
UINT_T scratch;
if (Size != K_SECURITY_CONFIG_FUSE_SIZE)
{
return (FUSE_InvalidBufferSize);
}
GEU_REG_READ(GEU_FUSE_VAL_SECURITY_CONFIG, pBuffer[0]);
// Check if ECC enabled (ECC field non-zero) and any uncorrectable errors
// Read ECC field for both USB ID and SECURE_CONFIG fields as they are covered by the same ECC field
GEU_REG_READ(GEU_FUSE_VAL_SECURITY_USB_ECC, scratch);
if ((scratch & GEU_SECURITY_USB_ECC_MASK)!= 0) // Test only ECC bits non-zero
{
GEU_REG_READ(GEU_ECC_STATUS0, scratch);
scratch = (scratch & K_USBID_SECURITYCFG_UNCORRECTABLE_ECC_ERROR_MASK);
if (scratch != 0)
{
return FUSE_UncorrectableEccError;
}
}
return NoError;
};
// Paul's
/************************************************************
* Function:
* GEU_ReadOemUidFuseBits
*
* Description:
* Reads the OEM unique id.
*
* Input:
* pBuffer - Pointer to buffer to write the requested data.
* Size - Size of buffer in bytes (Must be >= 8).
* Output:
* none
* Returns:
* NoError
* FUSE_BufferTooSmall
*
*/
UINT_T GEU_ReadOemUidFuseBits(UINT_T* pBuffer, UINT_T Size)
{
UINT_T scratch;
if (Size != K_OEM_UNIQUE_ID_FUSE_SIZE)
{
return (FUSE_InvalidBufferSize);
}
GEU_REG_READ(GEU_FUSE_VAL_OEM_UID_L, pBuffer[0]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_UID_H, pBuffer[1]);
GEU_REG_READ(GEU_FUSE_VAL_LIFECYCLE_JPD_FA_DD_OEM_UID_ECC, scratch);
scratch &= GEU_OEM_UID_ECC_MSK;
if (scratch != 0)
{
GEU_REG_READ(GEU_ECC_STATUS0, scratch);
scratch = (scratch & K_OEM_UID_UNCORRECTABLE_ECC_ERROR_MASK);
if (scratch != 0)
{
return FUSE_UncorrectableEccError;
}
}
return NoError;
};
// Paul's
/************************************************************
* Function:
* GEU_ReadOemUidEccFuseBits
*
* Description:
* Reads the OEM unique id ECC.
*
* Input:
* pBuffer - Pointer to buffer to write the requested data.
* Size - Size of buffer in bytes (Must be >= 2).
* Output:
* none
* Returns:
* NoError
* FUSE_BufferTooSmall
*
*/
UINT_T GEU_ReadOemUidEccFuseBits(UINT_T* pBuffer, UINT_T Size)
{
if (Size < K_OEM_UNIQUE_ID_ECC_FUSE_SIZE) {
return FUSE_BufferTooSmall;
}
GEU_REG_READ(GEU_FUSE_VAL_LIFECYCLE_JPD_FA_DD_OEM_UID_ECC, pBuffer[0]);
pBuffer[0] >>= 16;
return NoError;
}