embeddedsw/lib/sw_services/xilskey/src/xilskey_epl.c
Jagannadha Sutradharudu Teki 2c8f92039d embeddesw: Add initial code support
Added initial support Xilinx Embedded Software.

Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
2014-06-24 16:45:01 +05:30

1342 lines
No EOL
38 KiB
C
Executable file

/******************************************************************************
*
* Copyright (C) 2013 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file
* xilskey_epl.c
* @note
*
* Contains the function definitions for the PL eFUSE functionality.
*
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- --------------------------------------------------------
* 1.00a rpoolla 04/26/13 First release
* 1.02a hk 10/28/13 Added API's to read status bits and key.PR# 735957
* 2.00 hk 22/01/14 Corrected PL voltage checks to VCCINT and VCCAUX.
* CR#768077
*
*
****************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h"
#include "xil_types.h"
#include "xilskey_utils.h"
#include "xilskey_epl.h"
/************************** Constant Definitions *****************************/
#define XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW (0) /**< Fuse Ctrl Row*/
#define XSK_EFUSEPL_ARRAY_FUSE_AES_KEY_SIZE (256) /**< AES Key size*/
#define XSK_EFUSEPL_ARRAY_FUSE_USER_KEY_SIZE (32) /**< User key size*/
#define XSK_EFUSEPL_ARRAY_MAX_ROW (32) /**< PLeFUSE Max Rows*/
#define XSK_EFUSEPL_ARRAY_MAX_COL (32) /**< PLeFUSE Max Columns*/
#define XSK_EFUSEPL_ARRAY_AES_DATA_ROW_START (20) /**< AES Data Start Row*/
#define XSK_EFUSEPL_ARRAY_AES_DATA_ROW_END (30) /**< AES Data End Row*/
#define XSK_EFUSEPL_ARRAY_USER_DATA_START_ROW (31) /**< User Data Start Row*/
#define XSK_EFUSEPL_ARRAY_AES_DATA_BITS_IN_30th_ROW (16) /**< AES Data bits
* count in 30th Row
*/
#define XSK_EFUSEPL_ARRAY_USER_DATA_BITS_IN_30th_ROW (8) /**< User Data bits
* count in 30th Row
*/
#define XSK_EFUSEPL_ARRAY_MAX_PAYLAOD_BITS_IN_A_ROW (24)/**< Max Pay load
* in Row
*/
#define XSK_EFUSEPL_ARRAY_MAX_ECC_BITS_IN_A_ROW (6) /**< Max ECC bits
* in a Row
*/
#define XSK_EFUSEPL_ARRAY_ECC_START_BIT_IN_A_ROW (24)/**< ECC Start Bit
* position in
* a Row
*/
#define XSK_EFUSEPL_ARRAY_ECC_END_BIT_IN_A_ROW (29)/**< ECC End Bit
* position in
* a Row
*/
#define XSK_EFUSEPL_ARRAY_FUSE_CNTRL_MAX_BITS (11)/**< Fuse Control max
* bits
*/
#define XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_INDEX (14)/**< Redundant bit
* Index
*/
#define XSK_EFUSEPL_ARRAY_FUSE_CNTRL_START_BIT (0) /**< Fuse Control
* Start bit
*/
#define XSK_EFUSEPL_ARRAY_FUSE_CNTRL_END_BIT (10) /**< Fuse Control
* Start bit
*/
#define XSK_EFUSEPL_ARRAY_UNSUPPORTED_BIT6 (6) /**< Unsupported bit*/
#define XSK_EFUSEPL_ARRAY_UNSUPPORTED_BIT7 (7) /**< Unsupporte bit*/
#define XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_START_BIT (14)/**< Redundant
* bit start Index
*/
#define XSK_EFUSEPL_ARRAY_UNSUPPORTED_RED_FOR_BIT6 (20)/**< Unsupported bit*/
#define XSK_EFUSEPL_ARRAY_UNSUPPORTED_RED_FOR_BIT7 (21)/**< Unsupported bit*/
#define XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_END_BIT (24)/**< Redundant bit
* End Index
*/
#define XSK_EFUSEPL_MAX_REF_CLK_FREQ 60000000 /**< Max Ref Clk Frequency */
#define XSK_EFUSEPL_MIN_REF_CLK_FREQ 20000000 /**< Min Ref Clk Frequency */
/**************************** Type Definitions ******************************/
/**
* Read or Write eFUSE Margin Options
*/
typedef enum {
XSK_EFUSEPL_READ_NORMAL = 0x1, /**< Margin 1*/
XSK_EFUSEPL_READ_MARGIN_1 = 0x2, /**< Margin 2*/
XSK_EFUSEPL_READ_MARGIN_2 = 0x4, /**< Margin 4*/
XSK_EFUSEPL_READ_MARGIN_MAX = 0x7 /**< Max Margin 7*/
}XSK_EfusePl_MarginOption;
/**
* Fuse Control Row Bit Indices
*/
typedef enum {
XSK_EFUSEPL_CNTRL_FORCE_PCYCLE_RECONFIG = 0x01,/**< Bit1 of Fuse Ctrl Row*/
XSK_EFUSEPL_CNTRL_DISABLE_KEY_WRITE, /**< Bit2 of Fuse Ctrl Row*/
XSK_EFUSEPL_CNTRL_DISABLE_AES_KEY_READ, /**< Bit3 of Fuse Ctrl Row*/
XSK_EFUSEPL_CNTRL_DISABLE_USER_KEY_READ, /**< Bit4 of Fuse Ctrl Row*/
XSK_EFUSEPL_CNTRL_DISABLE_FUSE_CNTRL_WRITE, /**< Bit5 of Fuse Ctrl Row*/
XSK_EFUSEPL_CNTRL_FORCE_USE_AES_ONLY = 0x08, /**< Bit8 of Fuse Ctrl Row*/
XSK_EFUSEPL_CNTRL_JTAG_CHAIN_DISABLE, /**< Bit9 of Fuse Ctrl Row*/
XSK_EFUSEPL_CNTRL_BBRAM_KEY_DISABLE /**< Bit10 of Fuse Ctrl Row*/
}XSKEfusePl_FuseCntrlBits;
/***************** Macros (Inline Functions) Definitions ********************/
/************************** Variable Definitions ****************************/
u32 ErrorCode; /**< Global variable which holds the error key*/
static u8 AesDataInBytes[XSK_EFUSEPL_ARRAY_FUSE_AES_KEY_SIZE];
static u8 UserDataInBytes[XSK_EFUSEPL_ARRAY_FUSE_USER_KEY_SIZE];
/************************** Function Prototypes *****************************/
/**
* PL eFUSE interface functions
*/
static u8 XilSKey_EfusePl_ProgramBit(u8 Row, u8 Bit);
static u8 XilSKey_EfusePl_ProgramRow(u8 Row, u8 *RowData);
static u8 XilSKey_EfusePl_ProgramControlRegister(u8 *CtrlData);
static u8 XilSKey_EfusePl_ReadBit(u8 Row, u8 Bit, u8 MarginOption, u8 *BitData);
static u8 XilSKey_EfusePl_ReadRow(u32 Row, u8 MarginOption, u8 *RowData);
static u8 XilSKey_EfusePl_ReadControlRegister(u8 *CtrlData);
static u8 XilSKey_EfusePl_VerifyBit(u8 Row, u8 Bit, u8 MarginOption);
static u8 XilSKey_EfusePl_IsVectorAllZeros(u8 *RowDataPtr);
static void XilSKey_EfusePl_CalculateEcc(u8 *RowData, u8 *ECCData);
/**
* JTAG Server Initialization routine
*/
extern int JtagServerInit(XilSKey_EPl *PlInstancePtr);
/**
* JTAG Server Write routine
*/
extern void JtagWrite(unsigned char row, unsigned char bit);
/**
* JTAG Server Read routine
*/
extern void JtagRead(unsigned char row, unsigned int * row_data, unsigned char marginOption);
/***************************************************************************/
/****************************************************************************/
/**
*
*
* Programs PL eFUSE with input data given
*
*
* @param InstancePtr - Input data to be written to PL eFUSE
*
* @return
*
* - XST_FAILURE - In case of failure
* - XST_SUCCESS - In case of Success
*
*
* @note Updates the global variable ErrorCode with error code(if any).
*
*****************************************************************************/
u32 XilSKey_EfusePl_Program(XilSKey_EPl *InstancePtr)
{
u32 Row = 0;
u8 RowData[XSK_EFUSEPL_ARRAY_MAX_COL]={0};
u8 CtrlData[XSK_EFUSEPL_ARRAY_FUSE_CNTRL_MAX_BITS]={0};
u32 Index = 0;
u32 Status;
u32 RefClk;
u32 ArmPllFDiv,ArmClkDivisor;
ErrorCode = XSK_EFUSEPL_ERROR_NONE;
if(NULL == InstancePtr) {
return XSK_EFUSEPL_ERROR_PL_STRUCT_NULL;
}
if(!(InstancePtr->SystemInitDone))
{
/**
* Extract PLL FDIV value from ARM PLL Control Register
*/
ArmPllFDiv = (Xil_In32(XSK_ARM_PLL_CTRL_REG)>>12 & 0x7F);
/**
* Extract Clock divisor value from ARM Clock Control Register
*/
ArmClkDivisor = (Xil_In32(XSK_ARM_CLK_CTRL_REG)>>8 & 0x3F);
/**
* Initialize the variables
*/
RefClk = ((XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ *
ArmClkDivisor)/ ArmPllFDiv);
/**
* Return error if the reference clock frequency is not in
* between 20 & 60MHz
*/
if((RefClk < XSK_EFUSEPL_MIN_REF_CLK_FREQ) ||
(RefClk > XSK_EFUSEPL_MAX_REF_CLK_FREQ)) {
return XSK_EFUSEPL_ERROR_INVALID_REF_CLK;
}
/**
* Initialize the system ,
* which means initialize the timer, xadc, and jtag
* server using the passed info.
*/
XilSKey_Efuse_StartTimer(RefClk);
Status = XilSKey_EfusePs_XAdcInit();
if(Status != XST_SUCCESS) {
ErrorCode = Status;
return (XSK_EFUSEPL_ERROR_XADC + ErrorCode);
}
/**
* Start using the Jtag server to read the JTAG ID and
* compare with the stored ID, if it not matches return with
* unique error code.
* By reading the Jtag ID we will be sure that the JTAG related
* stuff is working as expected.
*/
if(JtagServerInit(InstancePtr) != XST_SUCCESS) {
return XSK_EFUSEPL_ERROR_JTAG_SERVER_INIT;
}
InstancePtr->SystemInitDone = 1;
}
/**
* Read the FUSE_CNTL register bits [5:2], and if any of them is found to
* be set to 1 then we can not write to the eFUSE, so return with unique
* error.
*
* If everything is well above then start programming with FUSE_AES key as
* passed to this function, followed by FUSE_USER if selected.
*
* AES key is 256 bits, but has to be written across many rows, in the PL
* eFUSE each row has 24 bits of data bits and 6 bits of ecc bits.
* So for 256 bits we will need full 10 rows(240 bits) and extra 1 row for
* remaining 16 bits, but rest 8 bits will be taken from the FUSE_USER key
* value[7:0]
*
* check if FUSE_CNTRL allows us to read and write the AES and USER eFUSE
* array.
*/
if(XilSKey_EfusePl_ReadControlRegister(CtrlData) != XST_SUCCESS) {
return (XSK_EFUSEPL_ERROR_READING_FUSE_CNTRL + ErrorCode);
}
if (((CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_AES_KEY_READ] == TRUE) ||
(CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_USER_KEY_READ] == TRUE)||
(CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_KEY_WRITE]== TRUE)) &&
((InstancePtr->ProgAESandUserLowKey == TRUE) ||
(InstancePtr->ProgUserHighKey == TRUE))) {
return (XSK_EFUSEPL_ERROR_DATA_PROGRAMMING_NOT_ALLOWED + ErrorCode);
}
if((CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_KEY_WRITE] == TRUE) &&
((InstancePtr->ForcePowerCycle == TRUE)||
(InstancePtr->KeyWrite == TRUE)||
(InstancePtr->AESKeyRead == TRUE)||
(InstancePtr->UserKeyRead == TRUE)||
(InstancePtr->UseAESOnly == TRUE)||
(InstancePtr->JtagDisable == TRUE)||
(InstancePtr->AESKeyExclusive == TRUE))) {
return (XSK_EFUSEPL_ERROR_FUSE_CTRL_WRITE_NOT_ALLOWED + ErrorCode);
}
/**
* convert each aes data bits to bytes.
*/
XilSKey_Efuse_ConvertBitsToBytes(&InstancePtr->AESKey[0],
AesDataInBytes,
XSK_EFUSEPL_ARRAY_FUSE_AES_KEY_SIZE);
/**
* convert each user data bits to bytes.
*/
XilSKey_Efuse_ConvertBitsToBytes(&InstancePtr->UserKey[0],
UserDataInBytes,
XSK_EFUSEPL_ARRAY_FUSE_USER_KEY_SIZE);
if(InstancePtr->ProgAESandUserLowKey == TRUE) {
/**
* check if row 20 to 30 are empty before programming AES and
* USER low key.
*/
for(Row=XSK_EFUSEPL_ARRAY_AES_DATA_ROW_START;
Row<=XSK_EFUSEPL_ARRAY_AES_DATA_ROW_END;
Row++) {
if(XilSKey_EfusePl_ReadRow(Row, XSK_EFUSEPL_READ_NORMAL,
RowData) != XST_SUCCESS) {
return (XSK_EFUSEPL_ERROR_READING_FUSE_AES_ROW + ErrorCode);
}
if(XilSKey_EfusePl_IsVectorAllZeros(RowData) != XST_SUCCESS) {
return (XSK_EFUSEPL_ERROR_AES_ROW_NOT_EMPTY + ErrorCode);
}
}
/**
* program AES_KEY 256 bits and USER_KEY lower 8 bits first.
*/
for(Row=XSK_EFUSEPL_ARRAY_AES_DATA_ROW_START;
Row<=XSK_EFUSEPL_ARRAY_AES_DATA_ROW_END;
Row++) {
if(Row < XSK_EFUSEPL_ARRAY_AES_DATA_ROW_END) {
/**
* prepare row data for row from 20 to 29.
*/
for(Index=0;
Index<XSK_EFUSEPL_ARRAY_MAX_PAYLAOD_BITS_IN_A_ROW;
Index++) {
RowData[Index] = AesDataInBytes[
(Index +
((Row -
XSK_EFUSEPL_ARRAY_AES_DATA_ROW_START) *
XSK_EFUSEPL_ARRAY_MAX_PAYLAOD_BITS_IN_A_ROW))];
}
}
else
{
/**
* prepare row data for row 30.
*/
for(Index=0;
Index<XSK_EFUSEPL_ARRAY_MAX_PAYLAOD_BITS_IN_A_ROW;
Index++) {
if(Index < XSK_EFUSEPL_ARRAY_AES_DATA_BITS_IN_30th_ROW) {
RowData[Index] =
AesDataInBytes[
(Index +
((Row -
XSK_EFUSEPL_ARRAY_AES_DATA_ROW_START) *
XSK_EFUSEPL_ARRAY_MAX_PAYLAOD_BITS_IN_A_ROW))];
}
else {
RowData[Index] =
UserDataInBytes[Index -
XSK_EFUSEPL_ARRAY_AES_DATA_BITS_IN_30th_ROW];
}
}
}
if(XilSKey_EfusePl_ProgramRow(Row, RowData) != XST_SUCCESS) {
return (XSK_EFUSEPL_ERROR_PROGRAMMING_FUSE_AES_ROW +
ErrorCode);
}
}
}
if(InstancePtr->ProgUserHighKey == TRUE) {
/**
* check if 31 is empty before programming USER high key.
*/
if(XilSKey_EfusePl_ReadRow(XSK_EFUSEPL_ARRAY_USER_DATA_START_ROW,
XSK_EFUSEPL_READ_NORMAL, RowData) !=
XST_SUCCESS) {
return (XSK_EFUSEPL_ERROR_READING_FUSE_USER_DATA_ROW + ErrorCode);
}
if(XilSKey_EfusePl_IsVectorAllZeros(RowData) != XST_SUCCESS) {
return (XSK_EFUSEPL_ERROR_USER_DATA_ROW_NOT_EMPTY + ErrorCode);
}
/**
* Program USER_KEY high 24 bits next.
* Prepare row data for row 31.
*/
for(Index=0; Index<XSK_EFUSEPL_ARRAY_MAX_PAYLAOD_BITS_IN_A_ROW; Index++) {
RowData[Index] =
UserDataInBytes[Index +
XSK_EFUSEPL_ARRAY_USER_DATA_BITS_IN_30th_ROW];
}
if(XilSKey_EfusePl_ProgramRow(XSK_EFUSEPL_ARRAY_USER_DATA_START_ROW,
RowData) != XST_SUCCESS) {
return (XSK_EFUSEPL_ERROR_PROGRAMMING_FUSE_DATA_ROW + ErrorCode);
}
}
CtrlData[XSK_EFUSEPL_CNTRL_FORCE_PCYCLE_RECONFIG] = InstancePtr->ForcePowerCycle;
CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_KEY_WRITE] = InstancePtr->KeyWrite;
CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_AES_KEY_READ] = InstancePtr->AESKeyRead;
CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_USER_KEY_READ] = InstancePtr->UserKeyRead;
CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_FUSE_CNTRL_WRITE] = InstancePtr->CtrlWrite;
CtrlData[XSK_EFUSEPL_CNTRL_FORCE_USE_AES_ONLY] = InstancePtr->UseAESOnly;
CtrlData[XSK_EFUSEPL_CNTRL_JTAG_CHAIN_DISABLE] = InstancePtr->JtagDisable;
CtrlData[XSK_EFUSEPL_CNTRL_BBRAM_KEY_DISABLE] = InstancePtr->AESKeyExclusive;
if(XilSKey_EfusePl_ProgramControlRegister(CtrlData) != XST_SUCCESS) {
return (XSK_EFUSEPL_ERROR_PROGRAMMING_FUSE_CNTRL_ROW + ErrorCode);
}
/**
* If everything is ok then return PASS.
*/
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* Checks whether data bits (0-29) of an PL eFUSE row are all zeroes or not
*
*
*
* @param RowDataPtr - row data pointer
*
* @return
*
* - XST_FAILURE - In case of failure
* - XST_SUCCESS - In case of Success
*
* @note None.
*
*****************************************************************************/
u8 XilSKey_EfusePl_IsVectorAllZeros(u8 *RowDataPtr)
{
u32 Index;
for(Index=0; Index<=XSK_EFUSEPL_ARRAY_ECC_END_BIT_IN_A_ROW; Index++) {
if(RowDataPtr[Index] != 0) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* Programs a bit of PL eFUSE row
*
*
*
* @param Row - row number
* @param Bit - bit position
*
* @return
*
* - XST_FAILURE - In case of failure
* - XST_SUCCESS - In case of Success
*
*
* @note Updates the global variable ErrorCode with error code(if any).
*
*****************************************************************************/
u8 XilSKey_EfusePl_ProgramBit(u8 Row, u8 Bit)
{
XSKEfusePs_XAdc PL_XAdc;
/**
*Check if the row position is valid.
*/
if( (Row > XSK_EFUSEPL_ARRAY_USER_DATA_START_ROW) ||
( (Row > XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW)
&& (Row < XSK_EFUSEPL_ARRAY_AES_DATA_ROW_START)
)
)
{
ErrorCode = XSK_EFUSEPL_ERROR_WRITE_ROW_OUT_OF_RANGE;
return XST_FAILURE;
}
/**
* Check if the bit position is valid.
*/
if((Bit < XSK_EFUSEPL_ARRAY_FUSE_CNTRL_START_BIT) ||
(Bit > XSK_EFUSEPL_ARRAY_ECC_END_BIT_IN_A_ROW)) {
ErrorCode = XSK_EFUSEPL_ERROR_WRITE_BIT_OUT_OF_RANGE;
return XST_FAILURE;
}
/**
* If row=0 then bit should be either 1 to 5 and 8 to 10, 15 to 19 and
* 22 to 24 rest all are not supported
*/
if(Row == XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW) {
if((Bit == XSK_EFUSEPL_ARRAY_FUSE_CNTRL_START_BIT) ||
(Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_BIT6) ||
(Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_BIT7)||
(Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_RED_FOR_BIT6)||
(Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_RED_FOR_BIT7)) {
ErrorCode = XSK_EFUSEPL_ERROR_WRITE_BIT_OUT_OF_RANGE;
return XST_FAILURE;
}
if((Bit > XSK_EFUSEPL_ARRAY_FUSE_CNTRL_END_BIT) &&
(Bit < XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_START_BIT)) {
ErrorCode = XSK_EFUSEPL_ERROR_WRITE_BIT_OUT_OF_RANGE;
return XST_FAILURE;
}
if(Bit > XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_END_BIT){
ErrorCode = XSK_EFUSEPL_ERROR_WRITE_BIT_OUT_OF_RANGE;
return XST_FAILURE;
}
}
/**
* Monitor the Voltage and temperature using XADC, if out of range return
* unique error.
*/
PL_XAdc.VType = XSK_EFUSEPS_VAUX;
XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc);
if((PL_XAdc.Temp < XSK_EFUSEPL_WRITE_TEMP_MIN_RAW) ||
(PL_XAdc.Temp > XSK_EFUSEPL_WRITE_TEMP_MAX_RAW)) {
ErrorCode = XSK_EFUSEPL_ERROR_WRITE_TMEPERATURE_OUT_OF_RANGE;
return XST_FAILURE;
}
if((PL_XAdc.V < XSK_EFUSEPL_WRITE_VOLTAGE_VCCAUX_MIN_RAW) ||
(PL_XAdc.V > XSK_EFUSEPL_WRITE_VOLTAGE_VCCAUX_MAX_RAW)) {
ErrorCode = XSK_EFUSEPL_ERROR_WRITE_VCCAUX_VOLTAGE_OUT_OF_RANGE;
return XST_FAILURE;
}
PL_XAdc.VType = XSK_EFUSEPS_VINT;
XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc);
if((PL_XAdc.V < XSK_EFUSEPL_WRITE_VOLTAGE_VCCINT_MIN_RAW) ||
(PL_XAdc.V > XSK_EFUSEPL_WRITE_VOLTAGE_VCCINT_MAX_RAW)) {
ErrorCode = XSK_EFUSEPL_ERROR_WRITE_VCCINT_VOLTAGE_OUT_OF_RANGE;
return XST_FAILURE;
}
JtagWrite(Row, Bit);
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* Programs PL eFUSE row
*
*
*
* @param Row - row number
* @param RowData- row data pointer
*
* @return
*
* - XST_FAILURE - In case of failure
* - XST_SUCCESS - In case of Success
*
*
* @note Updates the global variable ErrorCode with error code(if any).
*
*****************************************************************************/
u8 XilSKey_EfusePl_ProgramRow(u8 Row, u8 *RowData)
{
u32 Bit = 0;
u8 ECCData[XSK_EFUSEPL_ARRAY_MAX_ECC_BITS_IN_A_ROW] = {0};
/**
* check if row_data is not NULL
*/
if(NULL == RowData) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_BUFFER_NULL;
return XST_FAILURE;
}
if(Row == XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW) {
ErrorCode = XSK_EFUSEPL_ERROR_WRITE_ROW_OUT_OF_RANGE;
return XST_FAILURE;
}
for(Bit=0; Bit < XSK_EFUSEPL_ARRAY_MAX_PAYLAOD_BITS_IN_A_ROW ; Bit++ ) {
if(RowData[Bit]) {
if(XilSKey_EfusePl_ProgramBit(Row, Bit) != XST_SUCCESS) {
return XST_FAILURE;
}
if(XilSKey_EfusePl_VerifyBit(Row, Bit, XSK_EFUSEPL_READ_NORMAL)
!= XST_SUCCESS) {
return XST_FAILURE;
}
if(XilSKey_EfusePl_VerifyBit(Row,Bit,XSK_EFUSEPL_READ_MARGIN_1)
!= XST_SUCCESS) {
return XST_FAILURE;
}
}
}
XilSKey_EfusePl_CalculateEcc(RowData, ECCData);
for(Bit=XSK_EFUSEPL_ARRAY_ECC_START_BIT_IN_A_ROW;
Bit <= XSK_EFUSEPL_ARRAY_ECC_END_BIT_IN_A_ROW;
Bit++) {
if(ECCData[Bit - XSK_EFUSEPL_ARRAY_ECC_START_BIT_IN_A_ROW]) {
if(XilSKey_EfusePl_ProgramBit(Row, Bit) != XST_SUCCESS) {
return XST_FAILURE;
}
if(XilSKey_EfusePl_VerifyBit(Row, Bit, XSK_EFUSEPL_READ_NORMAL)
!= XST_SUCCESS) {
return XST_FAILURE;
}
if(XilSKey_EfusePl_VerifyBit(Row,Bit,XSK_EFUSEPL_READ_MARGIN_1)
!= XST_SUCCESS) {
return XST_FAILURE;
}
}
}
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* Programs PL eFUSE Control Register
*
*
*
* @param CtrlData - Control data pointer
*
* @return
*
* - XST_FAILURE - In case of failure
* - XST_SUCCESS - In case of Success
*
*
* @note Updates the global variable ErrorCode with error code(if any).
*
*****************************************************************************/
u8 XilSKey_EfusePl_ProgramControlRegister(u8 *CtrlData)
{
u8 TmpCtrlData[XSK_EFUSEPL_ARRAY_FUSE_CNTRL_MAX_BITS]={0};
u32 Index = 0;
/**
* check if cntrl_data is not NULL
*/
if(NULL == CtrlData) {
ErrorCode = XSK_EFUSEPL_ERROR_CNTRL_WRITE_BUFFER_NULL;
return XST_FAILURE;
}
/**
* Read the FUSE_CNTRL register
*/
if(XilSKey_EfusePl_ReadControlRegister(TmpCtrlData) != XST_SUCCESS) {
return XST_FAILURE;
}
/**
* check if FUSE_CNTRL allows us to write FUSE_CNTRL eFUSE array.
*/
if(TmpCtrlData[XSK_EFUSEPL_CNTRL_DISABLE_FUSE_CNTRL_WRITE] == TRUE) {
/**
* This means we cannot program FUSE_CNTRL register
*/
ErrorCode = XSK_EFUSEPL_ERROR_FUSE_CNTRL_WRITE_DISABLED;
return XST_FAILURE;
}
for(Index=1;Index<XSK_EFUSEPL_ARRAY_FUSE_CNTRL_MAX_BITS;Index++) {
if((Index == 6) || (Index == 7)) {
continue;
}
if((CtrlData[Index] == TRUE) && (TmpCtrlData[Index] == FALSE)) {
if(XilSKey_EfusePl_ProgramBit(XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW,
Index) != XST_SUCCESS) {
return XST_FAILURE;
}
if(XilSKey_EfusePl_VerifyBit(XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW,
Index, XSK_EFUSEPL_READ_NORMAL) != XST_SUCCESS) {
return XST_FAILURE;
}
if(XilSKey_EfusePl_VerifyBit(XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW,
Index, XSK_EFUSEPL_READ_MARGIN_1) != XST_SUCCESS) {
return XST_FAILURE;
}
if(XilSKey_EfusePl_ProgramBit(XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW,
Index +
XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_START_BIT)
!= XST_SUCCESS) {
return XST_FAILURE;
}
if(XilSKey_EfusePl_VerifyBit(XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW,
(Index +
XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_START_BIT),
XSK_EFUSEPL_READ_NORMAL) != XST_SUCCESS) {
return XST_FAILURE;
}
if(XilSKey_EfusePl_VerifyBit(XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW,
(Index +
XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_START_BIT),
XSK_EFUSEPL_READ_MARGIN_1) != XST_SUCCESS) {
return XST_FAILURE;
}
}
}
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* Reads a PL eFUSE bit & stores.
*
*
* @param Row - row number
* @param Bit - bit position in the specified row
* @param MarginOption- Margin Option(One of the reading method of PLeFUSE)
* @param BitData - Place holder to store the read value
*
* @return
*
* - XST_FAILURE - In case of failure
* - XST_SUCCESS - In case of Success
*
*
* @note Updates the global variable ErrorCode with error code(if any).
*
*****************************************************************************/
u8 XilSKey_EfusePl_ReadBit(u8 Row, u8 Bit, u8 MarginOption, u8 *BitData)
{
u8 RowData[XSK_EFUSEPL_ARRAY_MAX_COL]={0};
/**
* check if row_data is not NULL
*/
if(NULL == BitData) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_BUFFER_NULL;
return XST_FAILURE;
}
/**
*Check if the bit position is valid.
*/
if((Bit < XSK_EFUSEPL_ARRAY_FUSE_CNTRL_START_BIT) ||
(Bit > XSK_EFUSEPL_ARRAY_ECC_END_BIT_IN_A_ROW)) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_BIT_OUT_OF_RANGE;
return XST_FAILURE;
}
/**
* If row=0 then bit should be either 1 to 5 and 8 to 10, 15 to 19 and
* 22 to 24 rest all are not supported
*/
if(Row == XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW) {
if((Bit == XSK_EFUSEPL_ARRAY_FUSE_CNTRL_START_BIT) ||
(Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_BIT6) ||
(Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_BIT7)||
(Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_RED_FOR_BIT6)||
(Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_RED_FOR_BIT7)) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_BIT_OUT_OF_RANGE;
return XST_FAILURE;
}
if((Bit > XSK_EFUSEPL_ARRAY_FUSE_CNTRL_END_BIT) &&
(Bit < XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_START_BIT)) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_BIT_OUT_OF_RANGE;
return XST_FAILURE;
}
if(Bit > XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_END_BIT) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_BIT_OUT_OF_RANGE;
return XST_FAILURE;
}
}
if(XilSKey_EfusePl_ReadRow(Row, MarginOption,RowData) != XST_SUCCESS) {
return XST_FAILURE;
}
*BitData = RowData[Bit];
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* Reads row data of a specified row
*
*
* @param Row - row number
* @param MarginOption - Margin Option(One of the reading method of PLeFUSE)
* @param RowDataBytes - To store the read data bytes of specified row.
*
* @return
*
* - XST_FAILURE - In case of failure
* - XST_SUCCESS - In case of Success
*
*
* @note Read data will be stored @row_data_bytes
*
*****************************************************************************/
u8 XilSKey_EfusePl_ReadRow(u32 Row, u8 MarginOption, u8 *RowDataBytes)
{
XSKEfusePs_XAdc PL_XAdc;
u32 RowDataBits=0;
/**
* Check if the row position is valid.
*/
if((Row > XSK_EFUSEPL_ARRAY_USER_DATA_START_ROW) ||
((Row > XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW) &&
(Row < XSK_EFUSEPL_ARRAY_AES_DATA_ROW_START))) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_ROW_OUT_OF_RANGE;
return XST_FAILURE;
}
/**
* Check the read margin option.
*/
if( (MarginOption != XSK_EFUSEPL_READ_NORMAL ) &&
(MarginOption != XSK_EFUSEPL_READ_MARGIN_1)&&
(MarginOption != XSK_EFUSEPL_READ_MARGIN_2))
{
ErrorCode = XSK_EFUSEPL_ERROR_READ_MARGIN_OUT_OF_RANGE;
return XST_FAILURE;
}
/**
* check if row_data is not NULL
*/
if(NULL == RowDataBytes)
{
ErrorCode = XSK_EFUSEPL_ERROR_READ_BUFFER_NULL;
return XST_FAILURE;
}
/**
* Monitor the Voltage and temperature using XADC, if out of range return
* unique error.
*/
PL_XAdc.VType = XSK_EFUSEPS_VAUX;
XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc);
if((PL_XAdc.Temp < XSK_EFUSEPL_READ_TEMP_MIN_RAW) ||
(PL_XAdc.Temp > XSK_EFUSEPL_READ_TEMP_MAX_RAW)) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_TMEPERATURE_OUT_OF_RANGE;
return XST_FAILURE;
}
if((PL_XAdc.V < XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MIN_RAW) ||
(PL_XAdc.V > XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MAX_RAW)) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_VCCAUX_VOLTAGE_OUT_OF_RANGE;
return XST_FAILURE;
}
PL_XAdc.VType = XSK_EFUSEPS_VINT;
XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc);
if((PL_XAdc.V < XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MIN_RAW) ||
(PL_XAdc.V > XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MAX_RAW)) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_VCCINT_VOLTAGE_OUT_OF_RANGE;
return XST_FAILURE;
}
/**
* Here we have to use the impact algorithm to read the eFUSE row.
* and return the data in row_data.
*/
if((MarginOption & XSK_EFUSEPL_READ_NORMAL) == XSK_EFUSEPL_READ_NORMAL) {
JtagRead(Row, (unsigned int *)&RowDataBits, 0);
}
else if((MarginOption & XSK_EFUSEPL_READ_MARGIN_1) ==
XSK_EFUSEPL_READ_MARGIN_1) {
JtagRead(Row, (unsigned int *)&RowDataBits, 1);
}
else if((MarginOption & XSK_EFUSEPL_READ_MARGIN_2) ==
XSK_EFUSEPL_READ_MARGIN_2) {
JtagRead(Row, (unsigned int *)&RowDataBits, 2);
}
XilSKey_Efuse_ConvertBitsToBytes((u8 *)&RowDataBits, RowDataBytes, 32);
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* Reads PL eFUSE Control Register data
*
*
* @param CtrlData - Place holder to store the read data (control register)
*
* @return
*
* - XST_FAILURE - In case of failure
* - XST_SUCCESS - In case of Success
*
*
* @note Updates the global variable ErrorCode with error code (if any)
*
*****************************************************************************/
u8 XilSKey_EfusePl_ReadControlRegister(u8 *CtrlData)
{
u8 RowData[XSK_EFUSEPL_ARRAY_MAX_COL]={0};
u32 Index=0;
/**
* check if cntrl_data is not NULL
*/
if(NULL == CtrlData) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_BUFFER_NULL;
return XST_FAILURE;
}
if(XilSKey_EfusePl_ReadRow(XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW,
XSK_EFUSEPL_READ_NORMAL,
RowData) != XST_SUCCESS)
{
return XST_FAILURE;
}
for(Index=0; Index < XSK_EFUSEPL_ARRAY_FUSE_CNTRL_MAX_BITS; Index++)
{
CtrlData[Index] = RowData[Index] |
RowData[Index +
XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_START_BIT];
}
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
*
* Verify the PL eFUSE bit blown by reading it back
*
*
* @param Row - row number
* @param Bit - bit position of the specified row
* @param MarginOption - Margin Option(One of the reading method of PLeFUSE)
*
* @return
*
* - XST_FAILURE - In case of failure
* - XST_SUCCESS - In case of Success
*
*
* @note Updates the global variable ErrorCode with error code(if any).
*
*****************************************************************************/
u8 XilSKey_EfusePl_VerifyBit(u8 Row, u8 Bit, u8 MarginOption)
{
u8 BitData = 0;
if(XilSKey_EfusePl_ReadBit(Row, Bit, MarginOption, &BitData)
!= XST_SUCCESS) {
return XST_FAILURE;
}
if(BitData == FALSE) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_BIT_VALUE_NOT_SET;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* Calculates and stores the ECC data of row data
*
*
* @param RowData - Pointer to row data on which ECC will be calculated
* @param ECCData - Pointer to store the calculated ECC
*
* @return
*
* None
*
* @note None.
*
*****************************************************************************/
void XilSKey_EfusePl_CalculateEcc(u8 *RowData, u8 *ECCData)
{
ECCData[0] = RowData[0] ^ RowData[1] ^ RowData[2] ^
RowData[3] ^ RowData[8] ^ RowData[9] ^
RowData[10] ^ RowData[11] ^ RowData[12] ^
RowData[13] ^ RowData[14] ^ RowData[15] ^
RowData[16] ^ RowData[17];
ECCData[1] = RowData[1] ^ RowData[2] ^ RowData[3] ^
RowData[5] ^ RowData[6] ^ RowData[7] ^
RowData[11] ^ RowData[12] ^ RowData[13] ^
RowData[14] ^ RowData[18] ^ RowData[19] ^
RowData[20];
ECCData[2] = RowData[0] ^ RowData[2] ^ RowData[3] ^
RowData[4] ^ RowData[6] ^ RowData[7] ^
RowData[9] ^ RowData[10] ^ RowData[13] ^
RowData[15] ^ RowData[18] ^ RowData[21] ^
RowData[22];
ECCData[3] = RowData[0] ^ RowData[1] ^ RowData[3] ^
RowData[4] ^ RowData[5] ^ RowData[7] ^
RowData[8] ^ RowData[10] ^ RowData[12] ^
RowData[16] ^ RowData[19] ^ RowData[21] ^
RowData[23];
ECCData[4] = RowData[0] ^ RowData[1] ^ RowData[2] ^
RowData[4] ^ RowData[5] ^ RowData[6] ^
RowData[8] ^ RowData[9] ^ RowData[11] ^
RowData[17] ^ RowData[20] ^ RowData[22] ^
RowData[23];
/**
* This is the DED data
*/
ECCData[5] = RowData[0] ^ RowData[1] ^ RowData[2] ^
RowData[3] ^ RowData[4] ^ RowData[5] ^
RowData[6] ^ RowData[7] ^ RowData[8] ^
RowData[9] ^ RowData[10] ^ RowData[11] ^
RowData[12] ^ RowData[13] ^ RowData[14] ^
RowData[15] ^ RowData[16] ^ RowData[17] ^
RowData[18] ^ RowData[19] ^ RowData[20] ^
RowData[21] ^ RowData[22] ^ RowData[23] ^
ECCData[0] ^ ECCData[1] ^ ECCData[2] ^
ECCData[3] ^ ECCData[4];
}
/****************************************************************************/
/**
*
*
* Reads the PL efuse status bits
*
*
* @param InstancePtr - Input data to be written to PL eFUSE
* @param StatusBits - Variable to store the status bits read.
*
* @return
*
* - XST_FAILURE - In case of failure
* - XST_SUCCESS - In case of Success
*
*
* @note Updates the global variable ErrorCode with error code(if any).
*
*****************************************************************************/
u32 XilSKey_EfusePl_ReadStatus(XilSKey_EPl *InstancePtr, u32 *StatusBits)
{
u32 RefClk;
u32 ArmPllFdiv;
u32 ArmClkDivisor;
unsigned int RowData;
u32 Status;
XSKEfusePs_XAdc PL_XAdc;
if(NULL == InstancePtr) {
return XSK_EFUSEPL_ERROR_PL_STRUCT_NULL;
}
if(!(InstancePtr->SystemInitDone))
{
/**
* Extract PLL FDIV value from ARM PLL Control Register
*/
ArmPllFdiv = (Xil_In32(XSK_ARM_PLL_CTRL_REG)>>12 & 0x7F);
/**
* Extract Clock divisor value from ARM Clock Control Register
*/
ArmClkDivisor = (Xil_In32(XSK_ARM_CLK_CTRL_REG)>>8 & 0x3F);
/**
* Initialize the variables
*/
RefClk = ((XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ * ArmClkDivisor)/
ArmPllFdiv);
/**
* Return error if the reference clock frequency is not in
* between 20 & 60MHz
*/
if((RefClk < XSK_EFUSEPL_MIN_REF_CLK_FREQ) ||
(RefClk > XSK_EFUSEPL_MAX_REF_CLK_FREQ)) {
return XSK_EFUSEPL_ERROR_INVALID_REF_CLK;
}
/**
* Initialize the timer, XADC and jtag server
*/
XilSKey_Efuse_StartTimer(RefClk);
Status = XilSKey_EfusePs_XAdcInit();
if(Status != XST_SUCCESS) {
ErrorCode = Status;
return (XSK_EFUSEPL_ERROR_XADC + ErrorCode);
}
if(JtagServerInit(InstancePtr) != XST_SUCCESS) {
return XSK_EFUSEPL_ERROR_JTAG_SERVER_INIT;
}
InstancePtr->SystemInitDone = 1;
}
/**
* Monitor the Voltage and temperature using XADC, if out of range return
* unique error.
*/
PL_XAdc.VType = XSK_EFUSEPS_VAUX;
XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc);
if((PL_XAdc.Temp < XSK_EFUSEPL_READ_TEMP_MIN_RAW) ||
(PL_XAdc.Temp > XSK_EFUSEPL_READ_TEMP_MAX_RAW)) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_TMEPERATURE_OUT_OF_RANGE;
return XST_FAILURE;
}
if((PL_XAdc.V < XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MIN_RAW) ||
(PL_XAdc.V > XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MAX_RAW)) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_VCCAUX_VOLTAGE_OUT_OF_RANGE;
return XST_FAILURE;
}
PL_XAdc.VType = XSK_EFUSEPS_VINT;
XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc);
if((PL_XAdc.V < XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MIN_RAW) ||
(PL_XAdc.V > XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MAX_RAW)) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_VCCINT_VOLTAGE_OUT_OF_RANGE;
return XST_FAILURE;
}
/*
* Read row 0 for status bits
*/
JtagRead(0, &RowData, 0);
*StatusBits = RowData & 0xFFFFFF;
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
*
* Reads the PL efuse key (AES and user)
*
*
* @param InstancePtr - Input data to be written to PL eFUSE
*
* @return
*
* - XST_FAILURE - In case of failure
* - XST_SUCCESS - In case of Success
*
*
* @note Updates the global variable ErrorCode with error code(if any).
*
*****************************************************************************/
u32 XilSKey_EfusePl_ReadKey(XilSKey_EPl *InstancePtr)
{
u32 RefClk;
u32 ArmPllFdiv;
u32 ArmClkDivisor;
u32 RowCount;
unsigned int RowData;
u32 KeyCnt;
u32 Status;
XSKEfusePs_XAdc PL_XAdc;
if(NULL == InstancePtr) {
return XSK_EFUSEPL_ERROR_PL_STRUCT_NULL;
}
if(!(InstancePtr->SystemInitDone))
{
/**
* Extract PLL FDIV value from ARM PLL Control Register
*/
ArmPllFdiv = (Xil_In32(XSK_ARM_PLL_CTRL_REG)>>12 & 0x7F);
/**
* Extract Clock divisor value from ARM Clock Control Register
*/
ArmClkDivisor = (Xil_In32(XSK_ARM_CLK_CTRL_REG)>>8 & 0x3F);
/**
* Initialize the variables
*/
RefClk = ((XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ * ArmClkDivisor)/
ArmPllFdiv);
/**
* Return error if the reference clock frequency is not in
* between 20 & 60MHz
*/
if((RefClk < XSK_EFUSEPL_MIN_REF_CLK_FREQ) ||
(RefClk > XSK_EFUSEPL_MAX_REF_CLK_FREQ)) {
return XSK_EFUSEPL_ERROR_INVALID_REF_CLK;
}
/**
* Initialize the timer and jtag server
*/
XilSKey_Efuse_StartTimer(RefClk);
Status = XilSKey_EfusePs_XAdcInit();
if(Status != XST_SUCCESS) {
ErrorCode = Status;
return (XSK_EFUSEPL_ERROR_XADC + ErrorCode);
}
if(JtagServerInit(InstancePtr) != XST_SUCCESS) {
return XSK_EFUSEPL_ERROR_JTAG_SERVER_INIT;
}
InstancePtr->SystemInitDone = 1;
}
/**
* Monitor the Voltage and temperature using XADC, if out of range return
* unique error.
*/
PL_XAdc.VType = XSK_EFUSEPS_VAUX;
XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc);
if((PL_XAdc.Temp < XSK_EFUSEPL_READ_TEMP_MIN_RAW) ||
(PL_XAdc.Temp > XSK_EFUSEPL_READ_TEMP_MAX_RAW)) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_TMEPERATURE_OUT_OF_RANGE;
return XST_FAILURE;
}
if((PL_XAdc.V < XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MIN_RAW) ||
(PL_XAdc.V > XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MAX_RAW)) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_VCCAUX_VOLTAGE_OUT_OF_RANGE;
return XST_FAILURE;
}
PL_XAdc.VType = XSK_EFUSEPS_VINT;
XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc);
if((PL_XAdc.V < XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MIN_RAW) ||
(PL_XAdc.V > XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MAX_RAW)) {
ErrorCode = XSK_EFUSEPL_ERROR_READ_VCCINT_VOLTAGE_OUT_OF_RANGE;
return XST_FAILURE;
}
/*
* Read AES key and User Key and
* store them in the variables in instance structure
*/
/*
* AES key 4 bytes
*/
KeyCnt = 0;
/*
* Read row 20 to 29
*/
for(RowCount = 20; RowCount <= 29; RowCount++)
{
JtagRead(RowCount, &RowData, 0);
InstancePtr->AESKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF);
RowData = RowData >> 8;
InstancePtr->AESKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF);
RowData = RowData >> 8;
InstancePtr->AESKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF);
}
/*
* Read row 30
*/
JtagRead(30, &RowData, 0);
InstancePtr->AESKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF);
RowData = RowData >> 8;
InstancePtr->AESKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF);
/*
* User key 4 bytes
*/
KeyCnt = 0;
RowData = RowData >> 8;
InstancePtr->UserKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF);
/*
* Read row 31
*/
JtagRead(31, &RowData, 0);
InstancePtr->UserKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF);
RowData = RowData >> 8;
InstancePtr->UserKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF);
RowData = RowData >> 8;
InstancePtr->UserKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF);
return XST_SUCCESS;
}