/* * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include #include "cc_pal_types.h" #include "dx_env.h" #include "dx_reg_base_host.h" #include "cc_regs.h" #include "dx_host.h" #include "tests_hw_access.h" #include "tests_phys_map.h" #include "test_log.h" #include "dx_crys_kernel.h" ///////////////////////////////////// // macro defines // ///////////////////////////////////// /*************************/ /* Global variables */ /*************************/ /******************************/ /* function definitions */ /*****************************/ unsigned int testCheckLcs(unsigned int nextLcs) { unsigned int regVal = 0; unsigned int error = TEST_OK; /* Wait on LCS valid before reading the LCS register */ do { regVal = READ_REG(CC_REG_OFFSET(HOST_RGF, LCS_IS_VALID)); regVal = CC_REG_FLD_GET(0, LCS_IS_VALID, VALUE, regVal); }while (!regVal); /* Read the LCS register */ regVal = READ_REG(CC_REG_OFFSET(HOST_RGF, LCS_REG)); regVal = CC_REG_FLD_GET(0, LCS_REG, LCS_REG, regVal); TEST_PRINTF_ERROR("regVal is 0x%x", regVal); /* Verify lcs */ if(regVal != nextLcs) { TEST_PRINTF_ERROR("Failed to verify new LCS !!!\n"); return TEST_BURN_OTP_LCS_ERR; } /* Check HW errors */ switch(nextLcs){ case TESTS_LCS_SEC_ENABLED: /* Check RKEK error bit */ regVal = READ_REG(CC_REG_OFFSET(HOST_RGF, LCS_REG)); regVal = CC_REG_FLD_GET(0, LCS_REG, ERROR_KDR_ZERO_CNT, regVal); if (regVal) { error = TEST_BURN_OTP_KDR_ERR; break; } /* FALLTHROUGH */ case TESTS_LCS_DM: /* Check Provision (Scp) error bit */ regVal = READ_REG(CC_REG_OFFSET(HOST_RGF, LCS_REG)); regVal = CC_REG_FLD_GET(0, LCS_REG, ERROR_PROV_ZERO_CNT, regVal); if (regVal) { error = TEST_BURN_OTP_SCP_ERR; } break; default: break; } return error; } /* Global Reset of CC and AO and env regs */ void performPowerOnReset(void) { /* Call sw reset to reset the CC before starting to work with it */ WRITE_ENV(DX_ENV_CC_POR_N_ADDR_REG_OFFSET , 0x1UL); usleep(1000); WRITE_REG(CC_REG_OFFSET(HOST_RGF, AXIM_CACHE_PARAMS), 0x277UL); usleep(1000); #ifdef BIG__ENDIAN /* Set DMA endianess to big */ WRITE_REG(CC_REG_OFFSET(HOST_RGF, HOST_ENDIAN) , 0xCCUL); #else /* LITTLE__ENDIAN */ WRITE_REG(CC_REG_OFFSET(HOST_RGF, HOST_ENDIAN) , 0x00UL); #endif return; } /* Reset both CC and AO regs */ void performColdReset(void) { /* perform global reset */ WRITE_ENV(DX_ENV_CC_COLD_RST_REG_OFFSET , 0x1UL); usleep(1000); WRITE_REG(CC_REG_OFFSET(HOST_RGF, AXIM_CACHE_PARAMS), 0x277UL); usleep(1000); #ifdef BIG__ENDIAN /* Set DMA endianess to big */ WRITE_REG(CC_REG_OFFSET(HOST_RGF, HOST_ENDIAN) , 0xCCUL); #else /* LITTLE__ENDIAN */ WRITE_REG(CC_REG_OFFSET(HOST_RGF, HOST_ENDIAN) , 0x00UL); #endif return; } /* Reset only CC regs */ void performWarmReset(void) { WRITE_ENV(DX_ENV_CC_RST_N_REG_OFFSET , 0x1UL); usleep(1000); WRITE_REG(CC_REG_OFFSET(HOST_RGF, AXIM_CACHE_PARAMS), 0x277UL); usleep(1000); #ifdef BIG__ENDIAN /* Set DMA endianess to big */ WRITE_REG(CC_REG_OFFSET(HOST_RGF, HOST_ENDIAN) , 0xCCUL); #else /* LITTLE__ENDIAN */ WRITE_REG(CC_REG_OFFSET(HOST_RGF, HOST_ENDIAN) , 0x00UL); #endif return; } unsigned int testBurnOtp(unsigned int *otp, unsigned int nextLcs) { CCError_t error = TEST_OK; unsigned int i = 0; #if 0 /* Clear OTP is not needed any more since we call to powerOnReset to clear env regs */ error = testClearOtp(); if (error) { TEST_PRINTF_ERROR("Failed to clear OTP!!!\n"); return error; } #endif /* Perform SW reset to reach CM LCS */ performPowerOnReset(); for (i = 0; i < TEST_OTP_SIZE_IN_WORDS; i++) { TEST_PRINTF("writing Otp [%d] 0x%X", i, otp[i]); WRITE_OTP(i, otp[i]); usleep(1000); } #ifdef DEBUG uint32_t tempOtp; for (i = 0; i < TEST_OTP_SIZE_IN_WORDS; i++) { tempOtp = READ_OTP(i); TEST_PRINTF_ERROR("tempOtp [%d] 0x%X", i, tempOtp); } #endif /* Perform SW reset after writing to OTP new values */ performPowerOnReset(); /* verify LCS */ error = testCheckLcs(nextLcs); if (error == TEST_OK) { TEST_PRINTF(" OTP burn succeeded with new LCS = 0x%02x \n", nextLcs); } else { TEST_PRINTF_ERROR("Error: Failed to burn OTP lcs is %d!!!\n", nextLcs); } return error; } unsigned int testClearOtp(void) { CCError_t error = TEST_OK; unsigned int i = 0; /* Perform SW reset to reach CM LCS */ performPowerOnReset(); for (i = 0; i < TEST_OTP_SIZE_IN_WORDS; i++) { WRITE_OTP(i, 0); usleep(1000); } #ifdef DEBUG uint32_t tempOtp; for (i = 0; i < TEST_OTP_SIZE_IN_WORDS; i++) { tempOtp = READ_OTP(i); TEST_PRINTF_ERROR("tempOtp [%d] 0x%X", i, tempOtp); } #endif /* Perform SW reset after writing to OTP new values */ performPowerOnReset(); /* verify LCS */ error = testCheckLcs(0); if (error == TEST_OK) { TEST_PRINTF(" OTP burn succeeded with new LCS = CM \n"); } else { TEST_PRINTF_ERROR("Error: Failed to burn OTP \n"); } return error; } unsigned int testSetScpInOtpBuff(unsigned int *otp, unsigned char *scpBuff) { int i = 0; int zeroCount = 0; int scpZeroSize = ((0x1 << OTP_MANUFACTOR_FLAG_SCP_ZEROS_NUM_BITS)-1); int scpZeroMask = (scpZeroSize << OTP_MANUFACTOR_FLAG_SCP_ZEROS_BIT_OFFSET); if ((NULL == otp) || (NULL == scpBuff)) { TEST_PRINTF_ERROR("testSetScpInOtpBuff ilegal params\n"); return TEST_INVALID_PARAM_ERR; } for (i=0; i< OTP_SCP_SIZE_IN_WORDS; i++) { TEST_CONVERT_BYTE_ARR_TO_WORD(&scpBuff[i*sizeof(uint32_t)], otp[OTP_SCP_START_WORD_OFFSET+i]) } TEST_CALC_BUFF_ZEROS(&otp[OTP_SCP_START_WORD_OFFSET], OTP_SCP_SIZE_IN_WORDS, zeroCount); otp[OTP_MANUFACTOR_FLAG_START_WORD_OFFSET] &= ~(scpZeroMask); otp[OTP_MANUFACTOR_FLAG_START_WORD_OFFSET] |= (zeroCount)<