| // 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; | |
| } | |