/**
*
* This function checks the power state of one or more power islands and
* powers them up if required.
*
* @param	Mask of Island(s) that need to be powered up
*
* @return	XFSBL_SUCCESS for successful power up or
* 		    XFSBL_FAILURE otherwise.
*
* @note		None.
*
****************************************************************************/
u32 XFsbl_PowerUpIsland(u32 PwrIslandMask)
{

	u32 RegVal;
	u32 Status = XFSBL_SUCCESS;

	/* Skip power-up request for QEMU */
	if (XGet_Zynq_UltraMp_Platform_info() != (u32)XPLAT_ZYNQ_ULTRA_MPQEMU)
	{
		/* There is a single island for both R5_0 and R5_1 */
		if ((PwrIslandMask & PMU_GLOBAL_PWR_STATE_R5_1_MASK) ==
				PMU_GLOBAL_PWR_STATE_R5_1_MASK) {
			PwrIslandMask &= ~(PMU_GLOBAL_PWR_STATE_R5_1_MASK);
			PwrIslandMask |= PMU_GLOBAL_PWR_STATE_R5_0_MASK;
		}

		/* Power up request enable */
		XFsbl_Out32(PMU_GLOBAL_REQ_PWRUP_INT_EN, PwrIslandMask);

		/* Trigger power up request */
		XFsbl_Out32(PMU_GLOBAL_REQ_PWRUP_TRIG, PwrIslandMask);

		/* Poll for Power up complete */
		do {
			RegVal = XFsbl_In32(PMU_GLOBAL_REQ_PWRUP_STATUS) & PwrIslandMask;
		} while (RegVal != 0x0U);
	}

	return Status;
}
Exemple #2
0
/**
 * This function is used to provide Reset to USB Phy on ZCU102 board.
 *
 * @param none
 *
 * @return none
 *
 *****************************************************************************/
void XFsbl_UsbPhyReset(void)
{

	/* USB PHY Reset */
	XFsbl_Out32(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOTMODE_1_HI);
	(void)usleep(DELAY_1_US);
	XFsbl_Out32(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOTMODE_1_LO);
	(void)usleep(DELAY_5_US);
	XFsbl_Out32(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOTMODE_1_HI);

}
Exemple #3
0
/** This is the function to write data to PCAP interface
 *
 * @param	WrSize: Number of 32bit words that the DMA should write to
 *          the PCAP interface
 * @param   WrAddr: Linear memory space from where CSUDMA will read
 *	        the data to be written to PCAP interface
 *
 * @return	None
 *
 *****************************************************************************/
u32 XFsbl_WriteToPcap(u32 WrSize, u8 *WrAddr) {
	u32 RegVal;
	u32 Status = XFSBL_SUCCESS;

	/*
	 * Setup the  SSS, setup the PCAP to receive from DMA source
	 */
	RegVal = XFsbl_In32(CSU_CSU_SSS_CFG) & CSU_CSU_SSS_CFG_PCAP_SSS_MASK;
	RegVal = RegVal
			| (XFSBL_CSU_SSS_SRC_SRC_DMA << CSU_CSU_SSS_CFG_PCAP_SSS_SHIFT);
	XFsbl_Out32(CSU_CSU_SSS_CFG, RegVal);

	/* Setup the source DMA channel */
	XCsuDma_Transfer(&CsuDma, XCSUDMA_SRC_CHANNEL, (PTRSIZE) WrAddr, WrSize, 0);

	/* wait for the SRC_DMA to complete and the pcap to be IDLE */
	XCsuDma_WaitForDone(&CsuDma, XCSUDMA_SRC_CHANNEL);

	/* Acknowledge the transfer has completed */
	XCsuDma_IntrClear(&CsuDma, XCSUDMA_SRC_CHANNEL, XCSUDMA_IXR_DONE_MASK);

	XFsbl_Printf(DEBUG_GENERAL, "DMA transfer done \r\n");
	Status = XFsbl_PcapWaitForDone();
	if (Status != XFSBL_SUCCESS) {
		goto END;
	}

	END: return Status;
}
/******************************************************************************
*
* This function is used to stop Watchdog
*
* @param	None
*
* @return   None
*
* @note		None
*
*******************************************************************************/
void XFsbl_StopWdt(void)
{
	u32 RegValue;

	XWdtPs_Stop(&Watchdog);

	/* Disable LPD System Watchdog Timer Error */
	RegValue = XFsbl_In32(PMU_GLOBAL_ERROR_EN_1);
	RegValue &= ~(PMU_GLOBAL_ERROR_EN_1_LPD_SWDT_MASK);
	XFsbl_Out32(PMU_GLOBAL_ERROR_EN_1, RegValue);

	/* Disable generation of system reset by PMU due to LPD SWDT */
	RegValue = XFsbl_In32(PMU_GLOBAL_ERROR_SRST_DIS_1);
	RegValue |= PMU_GLOBAL_ERROR_SRST_DIS_1_LPD_SWDT_MASK;
	XFsbl_Out32(PMU_GLOBAL_ERROR_SRST_DIS_1, RegValue);
}
Exemple #5
0
/** This function does the necessary initialization of PCAP interface
 *
 * @param	None
 *
 * @return	error status based on implemented functionality (SUCCESS by default)
 *
 *****************************************************************************/
u32 XFsbl_PcapInit(void) {
	u32 RegVal;
	u32 Status = XFSBL_SUCCESS;

	/* Take PCAP out of Reset */
	RegVal = XFsbl_In32(CSU_PCAP_RESET);
	RegVal &= (~CSU_PCAP_RESET_RESET_MASK);
	XFsbl_Out32(CSU_PCAP_RESET, RegVal);

	/* Select PCAP mode and change PCAP to write mode */
	RegVal = CSU_PCAP_CTRL_PCAP_PR_MASK;
	XFsbl_Out32(CSU_PCAP_CTRL, RegVal);
	XFsbl_Out32(CSU_PCAP_RDWR, 0x0);

	Status = XFsbl_PowerUpIsland(PMU_GLOBAL_PWR_STATE_PL_MASK);

	if (Status != XFSBL_SUCCESS) {
		Status = XFSBL_ERROR_PL_POWER_UP;
		XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_PL_POWER_UP\r\n");
			goto END;
	}

	/* Reset PL */
	XFsbl_Out32(CSU_PCAP_PROG, 0x0U);

	usleep(PL_RESET_PERIOD_IN_US);

	XFsbl_Out32(CSU_PCAP_PROG, CSU_PCAP_PROG_PCFG_PROG_B_MASK);

	/*
	 *  Wait for PL_init completion
	 *  Bypass this check in platforms not supporting PCAP interface
	 */
	if ((XFSBL_PLATFORM != XFSBL_PLATFORM_REMUS)
			&& (XFSBL_PLATFORM != XFSBL_PLATFORM_QEMU)) {
		RegVal = 0U;
		do {
			RegVal = XFsbl_In32(CSU_PCAP_STATUS) &
			CSU_PCAP_STATUS_PL_INIT_MASK;
		} while (RegVal != CSU_PCAP_STATUS_PL_INIT_MASK);
	} else {
		XFsbl_Printf(DEBUG_GENERAL,
				"PCAP interface is not supported in this platform \r\n");
	}
END:
	return Status;
}
Exemple #6
0
/**
 * This function is used to provide PCIe reset on ZCU102 board.
 *
 * @param none
 *
 * @return none
 *
 *****************************************************************************/
void XFsbl_PcieReset(void)
{

	u32 RegVal = 0;
	u32 ICMCfg0;
	u32 ICMCfg1;

	ICMCfg0 = XFsbl_In32(SERDES_ICM_CFG0) &
			(SERDES_ICM_CFG0_L0_ICM_CFG_MASK | SERDES_ICM_CFG0_L1_ICM_CFG_MASK);

	ICMCfg1 = XFsbl_In32(SERDES_ICM_CFG1) &
			(SERDES_ICM_CFG1_L2_ICM_CFG_MASK | SERDES_ICM_CFG1_L3_ICM_CFG_MASK);

	/* Give reset only if we have PCIe in design */
	if ((ICMCfg0 == ICM_CFG0_PCIE_PCIE) || (ICMCfg1 == ICM_CFG1_PCIE_PCIE))
	{

		/* Set MIO31 direction as output */
		XFsbl_Out32(GPIO_DIRM_1, GPIO_MIO31_MASK);

		/* Set MIO31 output enable */
		XFsbl_Out32(GPIO_OEN_1, GPIO_MIO31_MASK);

		/* Set MIO31 to HIGH */
		RegVal = XFsbl_In32(GPIO_DATA_1) | GPIO_MIO31_MASK;
		XFsbl_Out32(GPIO_DATA_1, RegVal);

		(void)usleep(DELAY_1_US);

		/* Set MIO31 to LOW */
		RegVal = XFsbl_In32(GPIO_DATA_1) & ~(GPIO_MIO31_MASK);
		XFsbl_Out32(GPIO_DATA_1, RegVal);

		(void)usleep(DELAY_5_US);

		/* Set MIO31 to HIGH */
		RegVal = XFsbl_In32(GPIO_DATA_1) | GPIO_MIO31_MASK;
		XFsbl_Out32(GPIO_DATA_1, RegVal);
	}

}
/**
 * This function is called in FSBL error cases. Error status
 * register is updated and fallback is applied
 *
 * @param ErrorStatus is the error code which is written to the
 * 		  error status register
 *
 * @return none
 *
 * @note Fallback is applied only for fallback supported bootmodes
 *****************************************************************************/
void XFsbl_ErrorLockDown(u32 ErrorStatus)
{
	u32 BootMode=0U;

	/**
	 * Print the FSBL error
	 */
	XFsbl_Printf(DEBUG_GENERAL,"Fsbl Error Status: 0x%08lx\r\n",
		ErrorStatus);

	/**
	 * Update the error status register
	 * and Fsbl instance structure
	 */
	XFsbl_Out32(XFSBL_ERROR_STATUS_REGISTER_OFFSET, ErrorStatus);
	FsblInstancePtr.ErrorCode = ErrorStatus;

	/**
	 * Read Boot Mode register
	 */
	BootMode = XFsbl_In32(CRL_APB_BOOT_MODE_USER) &
			CRL_APB_BOOT_MODE_USER_BOOT_MODE_MASK;

	/**
	 * Fallback if bootmode supports
	 */
	if ( (BootMode == XFSBL_QSPI24_BOOT_MODE) ||
			(BootMode == XFSBL_QSPI32_BOOT_MODE) ||
			(BootMode == XFSBL_NAND_BOOT_MODE) ||
			(BootMode == XFSBL_SD0_BOOT_MODE) ||
			(BootMode == XFSBL_EMMC_BOOT_MODE) ||
			(BootMode == XFSBL_SD1_BOOT_MODE) ||
			(BootMode == XFSBL_SD1_LS_BOOT_MODE) )
	{
		XFsbl_FallBack();
	} else {
		/**
		 * Be in while loop if fallback is not supported
		 */
		XFsbl_Printf(DEBUG_GENERAL,"Fallback not supported \n\r");

		/**
		 * Exit FSBL
		 */
		XFsbl_HandoffExit(0U, XFSBL_NO_HANDOFFEXIT);
	}

	/**
	 * Should never be here
	 */
	return ;
}
void XFsbl_UpdateMultiBoot(u32 MultiBootValue)
{
	u32 RegValue;

	XFsbl_Out32(CSU_CSU_MULTI_BOOT, MultiBootValue);

	/* make sure every thing completes */
	dsb();
	isb();

	/* Soft reset the system */
	XFsbl_Printf(DEBUG_GENERAL,"Performing System Soft Reset\n\r");
	RegValue = XFsbl_In32(CRL_APB_RESET_CTRL);
	XFsbl_Out32(CRL_APB_RESET_CTRL,
			RegValue|CRL_APB_RESET_CTRL_SOFT_RESET_MASK);

	/* wait here until reset happens */
	while(1);

	return;

}
static u32 XFsbl_ResetValidation(XFsblPs * FsblInstancePtr)
{
	u32 Status =  XFSBL_SUCCESS;
	u32 FsblErrorStatus=0U;
	u32 ResetReasonValue=0U;
	u32 ErrStatusRegValue;

	/**
	 *  Read the Error Status register
	 *  If WDT reset, do fallback
	 */
	FsblErrorStatus = XFsbl_In32(XFSBL_ERROR_STATUS_REGISTER_OFFSET);

	ResetReasonValue = XFsbl_In32(CRL_APB_RESET_REASON);
	ErrStatusRegValue = XFsbl_In32(PMU_GLOBAL_ERROR_STATUS_1);

	/**
	 * Check if the reset is due to system WDT during
	 * previous FSBL execution
	 */
	if (((ResetReasonValue & CRL_APB_RESET_REASON_PMU_SYS_RESET_MASK)
			== CRL_APB_RESET_REASON_PMU_SYS_RESET_MASK) &&
			((ErrStatusRegValue & PMU_GLOBAL_ERROR_STATUS_1_LPD_SWDT_MASK)
			== PMU_GLOBAL_ERROR_STATUS_1_LPD_SWDT_MASK) &&
			(FsblErrorStatus == XFSBL_RUNNING)) {
		/**
		 * reset is due to System WDT.
		 * Do a fallback
		 */
		Status = XFSBL_ERROR_SYSTEM_WDT_RESET;
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_SYSTEM_WDT_RESET\n\r");
		goto END;
	}

	/**
	 * Mark FSBL running in error status register to
	 * detect the WDT reset while FSBL execution
	 */
	if (FsblErrorStatus != XFSBL_RUNNING) {
		XFsbl_Out32(XFSBL_ERROR_STATUS_REGISTER_OFFSET,
						  XFSBL_RUNNING);
	}

	/**
	 *  Read system error status register
	 * 	provide FsblHook function for any action
	 */

END:
	return Status;
}
/**
*
* This function is used to request isolation restore, through PMU
*
* @param	Mask of the entries for which isolation is to be restored
*
* @return	XFSBL_SUCCESS (for now always returns this)
*
* @note		None.
*
****************************************************************************/
u32 XFsbl_IsolationRestore(u32 IsolationMask)
{

	u32 RegVal;
	u32 Status = XFSBL_SUCCESS;

	/* Skip power-up request for QEMU */
	if (XGet_Zynq_UltraMp_Platform_info() != (u32)XPLAT_ZYNQ_ULTRA_MPQEMU)
	{

		/* Isolation request enable */
		XFsbl_Out32(PMU_GLOBAL_REQ_ISO_INT_EN, IsolationMask);

		/* Trigger Isolation request */
		XFsbl_Out32(PMU_GLOBAL_REQ_ISO_TRIG, IsolationMask);

		/* Poll for Isolation complete */
		do {
			RegVal = XFsbl_In32(PMU_GLOBAL_REQ_ISO_STATUS) & IsolationMask;
		} while (RegVal != 0x0U);
	}

	return Status;
}
/**
 * This function is used to get the Reset Reason
 *
 * @param  None
 *
 * @return Reset Reason
 *
 * @note
 *
 *****************************************************************************/
static u32 XFsbl_GetResetReason (void)
{
	u32 Val;
	u32 Ret = 0;

	Val = XFsbl_In32(CRL_APB_RESET_REASON);

	if (Val & CRL_APB_RESET_REASON_PSONLY_RESET_REQ_MASK) {
		/* Clear the PS Only reset bit as it is sticky */
		Val = CRL_APB_RESET_REASON_PSONLY_RESET_REQ_MASK;
		XFsbl_Out32(CRL_APB_RESET_REASON, Val);
		Ret = PS_ONLY_RESET;
	}

	return Ret;
}
/**
 * This function checks if PMU FW is loaded and gives handoff to PMU Microblaze
 *
 * @param	FsblInstancePtr is pointer to the XFsbl Instance
 *
 * @param	PartitionNum is the partition number of the image
 *
 * @return	None
 *
 *****************************************************************************/
static void XFsbl_CheckPmuFw(XFsblPs * FsblInstancePtr, u32 PartitionNum)
{

	u32 DestinationDev;
	u32 DestinationDevNxt = 0;
	u32 PmuFwLoadDone = FALSE;

	DestinationDev = XFsbl_GetDestinationDevice(
			&FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum]);

	if (DestinationDev == XIH_PH_ATTRB_DEST_DEVICE_PMU) {
		if ((PartitionNum + 1) <
				(FsblInstancePtr->
						ImageHeader.ImageHeaderTable.NoOfPartitions-1U)) {
			DestinationDevNxt = XFsbl_GetDestinationDevice(
					&FsblInstancePtr->
					ImageHeader.PartitionHeader[PartitionNum + 1]);
			if (DestinationDevNxt != XIH_PH_ATTRB_DEST_DEVICE_PMU) {
				/* there is a partition after this but that is not PMU FW */
				PmuFwLoadDone = TRUE;
			}
		}
		else
		{
			/* the current partition is last PMU FW partition */
			PmuFwLoadDone = TRUE;
		}
	}

	/* If all partitions of PMU FW loaded, handoff it to PMU MicroBlaze */
	if (TRUE == PmuFwLoadDone)
	{
		/* Wakeup the processor */
		XFsbl_Out32(PMU_GLOBAL_GLOBAL_CNTRL,
				XFsbl_In32(PMU_GLOBAL_GLOBAL_CNTRL) | 0x1);

		/* wait until done waking up */
		while((XFsbl_In32(PMU_GLOBAL_GLOBAL_CNTRL) &
				PMU_GLOBAL_GLOBAL_CNTRL_FW_IS_PRESENT_MASK) !=
						PMU_GLOBAL_GLOBAL_CNTRL_FW_IS_PRESENT_MASK ) {;}

	}

}
void XFsbl_EccInitialize(u32 Address, u32 Length)
{
	u32 Index=0U;

	/* Disable cache to ensure proper ECC initialization */
	Xil_DCacheDisable();
	while (Index<Length)
	{
		XFsbl_Out32(Address+Index, 1U) ;
		Index += 4U;
	}
	Xil_DCacheEnable();

	XFsbl_Printf(DEBUG_INFO,
	  "Address 0x%0lx, Length %0lx, ECC initialized \r\n",
		Address, Length);

	return ;
}
Exemple #14
0
/**
 * This function waits for PL Done bit to be set or till timeout and resets
 * PCAP after this.
 *
 * @param	None
 *
 * @return	error status based on implemented functionality (SUCCESS by default)
 *
 *****************************************************************************/
u32 XFsbl_PLWaitForDone(void) {
	u32 Status = XFSBL_SUCCESS;
	u32 PollCount;
	u32 RegVal;

	PollCount = (PL_DONE_POLL_COUNT);
	while (PollCount) {
		/* Read PCAP Status register and check for PL_DONE bit */
		RegVal = XFsbl_In32(CSU_PCAP_STATUS);
		RegVal &= CSU_PCAP_STATUS_PL_DONE_MASK;
		if (RegVal == CSU_PCAP_STATUS_PL_DONE_MASK) {
			break;
		}
		PollCount--;
	}

	if (RegVal == CSU_PCAP_STATUS_PL_DONE_MASK) {
		XFsbl_Printf(DEBUG_GENERAL, "PL Configuration done successfully \r\n");
	} else {
		Status = XFSBL_ERROR_BITSTREAM_LOAD_FAIL;
		XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_BITSTREAM_LOAD_FAIL\r\n");
		goto END;
	}

	/* Reset PCAP after data transfer */
	RegVal = XFsbl_In32(CSU_PCAP_RESET);
	RegVal = RegVal | CSU_PCAP_RESET_RESET_MASK;
	XFsbl_Out32(CSU_PCAP_RESET, RegVal);

	do {
		RegVal = XFsbl_In32(CSU_PCAP_RESET);
		RegVal = RegVal & CSU_PCAP_RESET_RESET_MASK;
	} while (RegVal != CSU_PCAP_RESET_RESET_MASK);

	END:
	return Status;
}
/**
 * This function is used to initialize the system
 *
 * @param	None
 *
 * @return	None
 *
 *****************************************************************************/
u32 XFsbl_InitWdt(void)
{
	s32 Status;
	u32 UStatus;
	XWdtPs_Config *ConfigPtr; 	/* Config structure of the WatchDog Timer */
	u32 CounterValue;
	u32 RegValue;


	/**
	 * Initialize the WDT timer
	 */
	ConfigPtr = XWdtPs_LookupConfig(XFSBL_WDT_DEVICE_ID);

	if(ConfigPtr==NULL) {
		UStatus = XFSBL_WDT_INIT_FAILED;
		goto END;
	}

	Status = XWdtPs_CfgInitialize(&Watchdog,
			ConfigPtr,
			ConfigPtr->BaseAddress);
	if (Status != XFSBL_SUCCESS) {
		XFsbl_Printf(DEBUG_INFO, "XFSBL_WDT_INIT_FAILED\n\r");
		UStatus = XFSBL_WDT_INIT_FAILED;
		goto END;
	}

	/**
	 * Setting the divider value
	 */
	XWdtPs_SetControlValue(&Watchdog,
			XWDTPS_CLK_PRESCALE,
			XWDTPS_CCR_PSCALE_4096);
	/**
	 * Convert time to  Watchdog counter reset value
	 */
	CounterValue = XFsbl_ConvertTime_WdtCounter(XFSBL_WDT_EXPIRE_TIME);

	/**
	 * Set the Watchdog counter reset value
	 */
	XWdtPs_SetControlValue(&Watchdog,
			XWDTPS_COUNTER_RESET,
			CounterValue);
	/**
	 * enable reset output, as we are only using this as a basic counter
	 */
	XWdtPs_EnableOutput(&Watchdog, XWDTPS_RESET_SIGNAL);

	/* Enable generation of system reset by PMU due to LPD SWDT */
	RegValue = XFsbl_In32(PMU_GLOBAL_ERROR_SRST_EN_1);
	RegValue |= PMU_GLOBAL_ERROR_SRST_EN_1_LPD_SWDT_MASK;
	XFsbl_Out32(PMU_GLOBAL_ERROR_SRST_EN_1, RegValue);

	/* Enable LPD System Watchdog Timer Error */
	RegValue = XFsbl_In32(PMU_GLOBAL_ERROR_EN_1);
	RegValue |= PMU_GLOBAL_ERROR_EN_1_LPD_SWDT_MASK;
	XFsbl_Out32(PMU_GLOBAL_ERROR_EN_1, RegValue);

	/**
	 * Start the Watchdog timer
	 */
	XWdtPs_Start(&Watchdog);

	XWdtPs_RestartWdt(&Watchdog);

	UStatus = XFSBL_SUCCESS;
END:
	return UStatus;
}
/**
*
* @param
*
* @return
*
* @note
*
*
*****************************************************************************/
static void XFsbl_UpdateResetVector (u64 HandOffAddress, u32 CpuSettings,
		u32 HandoffType, u32 Vector)
{
	u32 HandOffAddressLow;
	u32 HandOffAddressHigh;
	u32 LowAddressReg;
	u32 HighAddressReg;
	u32 CpuId;
	u32 RegVal;
	u32 ExecState;

	CpuId = CpuSettings & XIH_PH_ATTRB_DEST_CPU_MASK;
	ExecState = CpuSettings & XIH_PH_ATTRB_A53_EXEC_ST_MASK;

	/**
	 * Put R5 or A53-32 in Lovec/Hivec
	 */
	if ((CpuId == XIH_PH_ATTRB_DEST_CPU_R5_0)
			|| (CpuId == XIH_PH_ATTRB_DEST_CPU_R5_L)) {
		RegVal = XFsbl_In32(RPU_RPU_0_CFG);
		RegVal &= ~RPU_RPU_0_CFG_VINITHI_MASK;
		RegVal |= (Vector << RPU_RPU_0_CFG_VINITHI_SHIFT);
		XFsbl_Out32(RPU_RPU_0_CFG, RegVal);
	}

	else if ((CpuId == XIH_PH_ATTRB_DEST_CPU_R5_1)
			|| (CpuId == XIH_PH_ATTRB_DEST_CPU_R5_L)) {
		RegVal = XFsbl_In32(RPU_RPU_1_CFG);
		RegVal &= ~RPU_RPU_1_CFG_VINITHI_MASK;
		RegVal |= (Vector << RPU_RPU_1_CFG_VINITHI_SHIFT);
		XFsbl_Out32(RPU_RPU_1_CFG, RegVal);
	}

	else if ((CpuId == XIH_PH_ATTRB_DEST_CPU_A53_0)
		&& (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32)) {
		RegVal = XFsbl_In32(APU_CONFIG_0);
		RegVal &= ~APU_CONFIG_0_VINITHI_MASK_CPU0;
		RegVal |= (Vector << APU_CONFIG_0_VINITHI_SHIFT_CPU0);
		XFsbl_Out32(APU_CONFIG_0, RegVal);
	}

	else if ((CpuId == XIH_PH_ATTRB_DEST_CPU_A53_1)
		&& (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32)) {
		RegVal = XFsbl_In32(APU_CONFIG_0);
		RegVal &= ~APU_CONFIG_0_VINITHI_MASK_CPU1;
		RegVal |= (Vector << APU_CONFIG_0_VINITHI_SHIFT_CPU1);
		XFsbl_Out32(APU_CONFIG_0, RegVal);
	}

	else if ((CpuId == XIH_PH_ATTRB_DEST_CPU_A53_2)
			&& (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32)) {
		RegVal = XFsbl_In32(APU_CONFIG_0);
		RegVal &= ~APU_CONFIG_0_VINITHI_MASK_CPU2;
		RegVal |= (Vector << APU_CONFIG_0_VINITHI_SHIFT_CPU2);
		XFsbl_Out32(APU_CONFIG_0, RegVal);
		}

	else if ((CpuId == XIH_PH_ATTRB_DEST_CPU_A53_3)
		&& (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32)) {
		RegVal = XFsbl_In32(APU_CONFIG_0);
		RegVal &= ~APU_CONFIG_0_VINITHI_MASK_CPU3;
		RegVal |= (Vector << APU_CONFIG_0_VINITHI_SHIFT_CPU3);
		XFsbl_Out32(APU_CONFIG_0, RegVal);
	}
	else
	{
		/* for MISRA C compliance */
	}

	if ((XFsbl_Is32BitCpu(CpuSettings)==FALSE)
			&& (HandoffType != A53_0_32_HANDOFF_TO_A53_0_64))
	{
		/**
		 * for A53 cpu, write 64bit handoff address
		 * to the RVBARADDR in APU
		 */

		HandOffAddressLow = (u32 )(HandOffAddress & 0xFFFFFFFFU);
		HandOffAddressHigh = (u32 )((HandOffAddress>>32)
							& 0xFFFFFFFFU);
		switch (CpuId)
		{
			case XIH_PH_ATTRB_DEST_CPU_A53_0:
				LowAddressReg = APU_RVBARADDR0L;
				HighAddressReg = APU_RVBARADDR0H;
				break;
			case XIH_PH_ATTRB_DEST_CPU_A53_1:
				LowAddressReg = APU_RVBARADDR1L;
				HighAddressReg = APU_RVBARADDR1H;
				break;
			case XIH_PH_ATTRB_DEST_CPU_A53_2:
				LowAddressReg = APU_RVBARADDR2L;
				HighAddressReg = APU_RVBARADDR2H;
				break;
			case XIH_PH_ATTRB_DEST_CPU_A53_3:
				LowAddressReg = APU_RVBARADDR3L;
				HighAddressReg = APU_RVBARADDR3H;
				break;
			default:
				/**
				 * error can be triggered here
				 */
				LowAddressReg = 0U;
				HighAddressReg = 0U;
				break;
		}
		XFsbl_Out32(LowAddressReg, HandOffAddressLow);
		XFsbl_Out32(HighAddressReg, HandOffAddressHigh);
	}
static u32 XFsbl_SetCpuPwrSettings (u32 CpuSettings, u32 Flags)
{
	u32 RegValue;
	u32 Status;
	u32 CpuId;
	u32 ExecState;
	u32 PwrStateMask;

	/**
	 * Reset the CPU
	 */
	if ((Flags & XFSBL_CPU_SWRST) != 0U)
	{
	CpuId = CpuSettings & XIH_PH_ATTRB_DEST_CPU_MASK;
		ExecState = CpuSettings & XIH_PH_ATTRB_A53_EXEC_ST_MASK;
		switch(CpuId)
		{

			case XIH_PH_ATTRB_DEST_CPU_A53_0:

			PwrStateMask = PMU_GLOBAL_PWR_STATE_ACPU0_MASK |
				PMU_GLOBAL_PWR_STATE_FP_MASK |
				PMU_GLOBAL_PWR_STATE_L2_BANK0_MASK;

			Status = XFsbl_PowerUpIsland(PwrStateMask);
			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_A53_0_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_A53_0_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Set to Aarch32 if enabled
			 */
			if (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32)
			{
				RegValue = XFsbl_In32(APU_CONFIG_0);
				RegValue &= ~(APU_CONFIG_0_AA64N32_MASK_CPU0);
				XFsbl_Out32(APU_CONFIG_0, RegValue);
			}

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRF_APB_ACPU_CTRL);
			RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK |
			             CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK);
			XFsbl_Out32(CRF_APB_ACPU_CTRL, RegValue);

			/**
			 * Release reset
			 */
			RegValue = XFsbl_In32(CRF_APB_RST_FPD_APU);
			RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU0_RESET_MASK |
					CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK |
					CRF_APB_RST_FPD_APU_ACPU0_PWRON_RESET_MASK);
			XFsbl_Out32(CRF_APB_RST_FPD_APU, RegValue);

			break;

		case XIH_PH_ATTRB_DEST_CPU_A53_1:

			PwrStateMask = PMU_GLOBAL_PWR_STATE_ACPU1_MASK |
				PMU_GLOBAL_PWR_STATE_FP_MASK |
				PMU_GLOBAL_PWR_STATE_L2_BANK0_MASK;

			Status = XFsbl_PowerUpIsland(PwrStateMask);
			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_A53_1_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_A53_1_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Set to Aarch32 if enabled
			 */
			if (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32)
			{
				RegValue = XFsbl_In32(APU_CONFIG_0);
				RegValue &= ~(APU_CONFIG_0_AA64N32_MASK_CPU1);
				XFsbl_Out32(APU_CONFIG_0, RegValue);
			}

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRF_APB_ACPU_CTRL);
			RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK |
			             CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK);
			XFsbl_Out32(CRF_APB_ACPU_CTRL, RegValue);

			/**
			 * Release reset
			 */
			RegValue = XFsbl_In32(CRF_APB_RST_FPD_APU);
			RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU1_RESET_MASK |
					CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK |
					CRF_APB_RST_FPD_APU_ACPU1_PWRON_RESET_MASK);
			XFsbl_Out32(CRF_APB_RST_FPD_APU, RegValue);

			break;

		case XIH_PH_ATTRB_DEST_CPU_A53_2:

			PwrStateMask = PMU_GLOBAL_PWR_STATE_ACPU2_MASK |
				PMU_GLOBAL_PWR_STATE_FP_MASK |
				PMU_GLOBAL_PWR_STATE_L2_BANK0_MASK;

			Status = XFsbl_PowerUpIsland(PwrStateMask);
			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_A53_2_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_A53_2_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Set to Aarch32 if enabled
			 */
			if (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32)
			{
				RegValue = XFsbl_In32(APU_CONFIG_0);
				RegValue &= ~(APU_CONFIG_0_AA64N32_MASK_CPU2);
				XFsbl_Out32(APU_CONFIG_0, RegValue);
			}

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRF_APB_ACPU_CTRL);
			RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK |
			             CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK);
			XFsbl_Out32(CRF_APB_ACPU_CTRL, RegValue);

			/**
			 * Release reset
			 */
			RegValue = XFsbl_In32(CRF_APB_RST_FPD_APU);
			RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU2_RESET_MASK |
					CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK |
					CRF_APB_RST_FPD_APU_ACPU2_PWRON_RESET_MASK);

			XFsbl_Out32(CRF_APB_RST_FPD_APU, RegValue);

			break;

		case XIH_PH_ATTRB_DEST_CPU_A53_3:

			PwrStateMask = PMU_GLOBAL_PWR_STATE_ACPU3_MASK |
				PMU_GLOBAL_PWR_STATE_FP_MASK |
				PMU_GLOBAL_PWR_STATE_L2_BANK0_MASK;

			Status = XFsbl_PowerUpIsland(PwrStateMask);
			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_A53_3_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_A53_3_POWER_UP\r\n");
				goto END;
			}


			/**
			 * Set to Aarch32 if enabled
			 */
			if (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32)
			{
				RegValue = XFsbl_In32(APU_CONFIG_0);
				RegValue &= ~(APU_CONFIG_0_AA64N32_MASK_CPU3);
				XFsbl_Out32(APU_CONFIG_0, RegValue);
			}

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRF_APB_ACPU_CTRL);
			RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK |
			             CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK);
			XFsbl_Out32(CRF_APB_ACPU_CTRL, RegValue);

			/**
			 * Release reset
			 */
			RegValue = XFsbl_In32(CRF_APB_RST_FPD_APU);
			RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU3_RESET_MASK |
					CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK |
					CRF_APB_RST_FPD_APU_ACPU3_PWRON_RESET_MASK);

			XFsbl_Out32(CRF_APB_RST_FPD_APU, RegValue);

			break;

		case XIH_PH_ATTRB_DEST_CPU_R5_0:

			Status = XFsbl_PowerUpIsland(PMU_GLOBAL_PWR_STATE_R5_0_MASK);
			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_R5_0_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_R5_0_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Place R5, TCM's in split mode
			 */
			RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL);
			RegValue |= (RPU_RPU_GLBL_CNTL_SLSPLIT_MASK);
			RegValue &= ~(RPU_RPU_GLBL_CNTL_TCM_COMB_MASK);
			RegValue &= ~(RPU_RPU_GLBL_CNTL_SLCLAMP_MASK);
			XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue);

			/**
			 * Place R5-0 in HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_0_CFG);
			RegValue &= ~(RPU_RPU_0_CFG_NCPUHALT_MASK);
			XFsbl_Out32(RPU_RPU_0_CFG, RegValue);

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL);
			RegValue |= (CRL_APB_CPU_R5_CTRL_CLKACT_MASK);
			XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue);

			/**
			 * Provide some delay,
			 * so that clock propogates properly.
			 */
			(void)usleep(0x50U);


			/**
			 * Release reset to R5-0
			 */
			RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R50_RESET_MASK);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK);
			XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue);


			/**
			 * Take R5-0 out of HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_0_CFG);
			RegValue |= RPU_RPU_0_CFG_NCPUHALT_MASK;
			XFsbl_Out32(RPU_RPU_0_CFG, RegValue);
			break;

		case XIH_PH_ATTRB_DEST_CPU_R5_1:

			Status = XFsbl_PowerUpIsland(PMU_GLOBAL_PWR_STATE_R5_1_MASK);
			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_R5_1_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_R5_1_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Place R5, TCM's in split mode
			 */
			RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL);
			RegValue |= RPU_RPU_GLBL_CNTL_SLSPLIT_MASK;
			RegValue &= ~(RPU_RPU_GLBL_CNTL_TCM_COMB_MASK);
			RegValue &= ~(RPU_RPU_GLBL_CNTL_SLCLAMP_MASK);
			XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue);

			/**
			 * Place R5-1 in HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_1_CFG);
			RegValue &= ~(RPU_RPU_1_CFG_NCPUHALT_MASK);
			XFsbl_Out32(RPU_RPU_1_CFG, RegValue);

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL);
			RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK;
			XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue);

			/**
			 * Provide some delay,
			 * so that clock propogates properly.
			 */
			(void)usleep(0x50U);

			/**
			 * Release reset to R5-1
			 */
			RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R51_RESET_MASK);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK);
			XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue);


			/**
			 * Take R5-1 out of HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_1_CFG);
			RegValue |= RPU_RPU_1_CFG_NCPUHALT_MASK;
			XFsbl_Out32(RPU_RPU_1_CFG, RegValue);
			break;
		case XIH_PH_ATTRB_DEST_CPU_R5_L:

			Status = XFsbl_PowerUpIsland(PMU_GLOBAL_PWR_STATE_R5_0_MASK);
			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_R5_L_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_R5_L_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Place R5, TCM's in safe mode
			 */
			RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL);
			RegValue &= ~(RPU_RPU_GLBL_CNTL_SLSPLIT_MASK);
			RegValue |= RPU_RPU_GLBL_CNTL_TCM_COMB_MASK;
			RegValue |= RPU_RPU_GLBL_CNTL_SLCLAMP_MASK;
			XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue);

			/**
			 * Place R5-0 in HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_0_CFG);
			RegValue &= ~(RPU_RPU_0_CFG_NCPUHALT_MASK);
			XFsbl_Out32(RPU_RPU_0_CFG, RegValue);

			/**
			 * Place R5-1 in HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_1_CFG);
			RegValue &= ~(RPU_RPU_1_CFG_NCPUHALT_MASK);
			XFsbl_Out32(RPU_RPU_1_CFG, RegValue);

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL);
			RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK;
			XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue);

			/**
			 * Provide some delay,
			 * so that clock propogates properly.
			 */
			(void )usleep(0x50U);

			/**
			 * Release reset to R5-0, R5-1
			 */
			RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R50_RESET_MASK);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R51_RESET_MASK);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK);
			XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue);


			/**
			 * Take R5-0 out of HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_0_CFG);
			RegValue |= RPU_RPU_0_CFG_NCPUHALT_MASK;
			XFsbl_Out32(RPU_RPU_0_CFG, RegValue);

			/**
			 * Take R5-1 out of HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_1_CFG);
			RegValue |= RPU_RPU_1_CFG_NCPUHALT_MASK;
			XFsbl_Out32(RPU_RPU_1_CFG, RegValue);
			break;

		default:
			XFsbl_Printf(DEBUG_GENERAL,
			    "XFSBL_ERROR_HANDOFF_CPUID\n\r");
			Status = XFSBL_ERROR_HANDOFF_CPUID;
			break;
		}

	}
	else
	{
		Status = XFSBL_SUCCESS;
	}
END:
	return Status;
}
/**
 * This function validates the partition
 *
 * @param	FsblInstancePtr is pointer to the XFsbl Instance
 *
 * @param	PartitionNum is the partition number in the image to be loaded
 *
 * @return	returns the error codes described in xfsbl_error.h on any error
 * 			returns XFSBL_SUCCESS on success
 *
 *****************************************************************************/
static u32 XFsbl_PartitionValidation(XFsblPs * FsblInstancePtr,
						u32 PartitionNum)
{
	u32 Status=XFSBL_SUCCESS;
	u32 ChecksumType=0U;
	s32 IsEncryptionEnabled=FALSE;
	s32 IsAuthenticationEnabled=FALSE;
	u32 DestinationDevice=0U;
	u32 DestinationCpu=0U;
	u32 ExecState=0U;
	u32 CpuNo=0U;
	XFsblPs_PartitionHeader * PartitionHeader;
#if defined(XFSBL_RSA)
	u32 HashLen=0U;
#endif
#if defined(XFSBL_AES)
	u32 ImageOffset = 0U;
	u32 FsblIv[XIH_BH_IV_LENGTH / 4U];
	u32 UnencryptedLength = 0;
	u32 IvLocation;
#endif
#if defined(XFSBL_RSA) || defined(XFSBL_AES)
	u32 Length=0U;
#endif
#if defined(XFSBL_RSA) || defined(XFSBL_AES) || defined(XFSBL_BS)
	PTRSIZE LoadAddress=0U;
#endif
#if defined(XFSBL_BS)
	u32 BitstreamWordSize = 0;
#endif

	/**
	 * Update the variables
	 */
	PartitionHeader =
	    &FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum];
	ChecksumType = XFsbl_GetChecksumType(PartitionHeader);

	/**
	 * Check the encryption status
	 */
	if (XFsbl_IsEncrypted(PartitionHeader) ==
			XIH_PH_ATTRB_ENCRYPTION )
	{
		IsEncryptionEnabled = TRUE;

#ifdef XFSBL_AES
		/* Copy the Iv from Flash into local memory */
		IvLocation = ImageOffset + XIH_BH_IV_OFFSET;

		Status = FsblInstancePtr->DeviceOps.DeviceCopy(IvLocation,
				(PTRSIZE) FsblIv, XIH_BH_IV_LENGTH);

		if (Status != XFSBL_SUCCESS) {
			XFsbl_Printf(DEBUG_GENERAL,
					"XFSBL_ERROR_DECRYPTION_IV_COPY_FAIL \r\n");
			Status = XFSBL_ERROR_DECRYPTION_IV_COPY_FAIL;
			goto END;
		}
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_AES_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_AES_NOT_ENABLED;
		goto END;
#endif
	}

	/**
	 * check the authentication status
	 */
	if (XFsbl_IsRsaSignaturePresent(PartitionHeader) ==
			XIH_PH_ATTRB_RSA_SIGNATURE )
	{
		IsAuthenticationEnabled = TRUE;
	}
	DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader);
	DestinationCpu = XFsbl_GetDestinationCpu(PartitionHeader);


	/**
         * Get the execution state
         */
        ExecState = XFsbl_GetA53ExecState(PartitionHeader);

	/**
	 * if destination cpu is not present, it means it is for same cpu
	 */
	if (DestinationCpu == XIH_PH_ATTRB_DEST_CPU_NONE)
	{
		DestinationCpu = FsblInstancePtr->ProcessorID;
	}


	/**
	 * Checksum Validation
	 */
	if (ChecksumType == XIH_PH_ATTRB_CHECKSUM_MD5)
	{
		/**
		 * Do the checksum validation
		 */
	}

#if defined(XFSBL_RSA) || defined(XFSBL_AES)
	if ((IsAuthenticationEnabled == TRUE) || (IsEncryptionEnabled == TRUE))
	{
		LoadAddress = PartitionHeader->DestinationLoadAddress;
		Length = PartitionHeader->TotalDataWordLength * 4U;
		Status = XFsbl_GetLoadAddress(DestinationCpu,
				&LoadAddress, Length);
		if (XFSBL_SUCCESS != Status)
		{
			goto END;
		}
	}
#endif

#ifdef XFSBL_BS
	if ((DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL) &&
			(LoadAddress == 0U))
	{
		LoadAddress = XFSBL_DDR_TEMP_ADDRESS;
	}
#endif

	/**
	 * Authentication Check
	 */
	if (IsAuthenticationEnabled == TRUE)
	{
		XFsbl_Printf(DEBUG_INFO,"Authentication Enabled\r\n");
#ifdef XFSBL_RSA
		/**
		 * Get the Sha type to be used from
		 * boot header attributes
		 */
		if ((FsblInstancePtr->BootHdrAttributes &
			XIH_BH_IMAGE_ATTRB_SHA2_MASK) ==
			XIH_BH_IMAGE_ATTRB_SHA2_MASK)
		{
			HashLen = XFSBL_HASH_TYPE_SHA2;
		} else {
			HashLen = XFSBL_HASH_TYPE_SHA3;
		}

		/**
		 * cache disbale can be removed
		 */
		Xil_DCacheDisable();

		/**
		 * Do the authentication validation
		 */
		Status = XFsbl_Authentication(FsblInstancePtr, LoadAddress, Length,
			(LoadAddress + Length) - XFSBL_AUTH_CERT_MIN_SIZE,
			HashLen);

		if (Status != XFSBL_SUCCESS)
                {
                        goto END;
                }
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_RSA_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_RSA_NOT_ENABLED;
		goto END;
#endif
	}

	/**
	 * Decrypt image through CSU DMA
	 */
	if (IsEncryptionEnabled == TRUE) {
		XFsbl_Printf(DEBUG_INFO, "Decryption Enabled\r\n");
#ifdef XFSBL_AES

		/* AES expects IV in big endian form */
		FsblIv[0] = Xil_Htonl(FsblIv[0]);
		FsblIv[1] = Xil_Htonl(FsblIv[1]);
		FsblIv[2] = Xil_Htonl(FsblIv[2]);

		/* Initialize the Aes Instance so that it's ready to use */
		XSecure_AesInitialize(&SecureAes, &CsuDma,
		 XSECURE_CSU_AES_KEY_SRC_DEV, FsblIv, NULL);

		XFsbl_Printf(DEBUG_INFO, " Aes initialized \r\n");

		UnencryptedLength = PartitionHeader->UnEncryptedDataWordLength * 4U;


		if (DestinationDevice != XIH_PH_ATTRB_DEST_DEVICE_PL) {
			Status = XSecure_AesDecrypt(&SecureAes, (u8 *) LoadAddress,
					(u8 *) LoadAddress, UnencryptedLength);

			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_DECRYPTION_FAIL;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_DECRYPTION_FAIL\r\n");
				goto END;
			} else {
				XFsbl_Printf(DEBUG_GENERAL, "Decryption Successful\r\n");
			}
		}
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_AES_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_AES_NOT_ENABLED;
		goto END;
#endif
	}

#ifdef XFSBL_BS
	/**
	 * for PL image use CSU DMA to route to PL
	 */
	if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL)
	{
		/**
		 * Fsbl hook before bit stream download
		 */
		Status = XFsbl_HookBeforeBSDownload();
		if (Status != XFSBL_SUCCESS)
		{
			Status = XFSBL_ERROR_HOOK_BEFORE_BITSTREAM_DOWNLOAD;
			XFsbl_Printf(DEBUG_GENERAL,
			 "XFSBL_ERROR_HOOK_BEFORE_BITSTREAM_DOWNLOAD\r\n");
			goto END;
		}

		XFsbl_Printf(DEBUG_GENERAL, "Bitstream download to start now\r\n");

		Status = XFsbl_PcapInit();
		if (Status != XFSBL_SUCCESS) {
			goto END;
		}

		if (IsEncryptionEnabled == TRUE) {
#ifdef XFSBL_AES
			/*
			 * The secure bitstream would be sent through CSU DMA to AES
			 * and the decrypted bitstream is sent directly to PCAP
			 * by configuring SSS appropriately
			 */
			Status = XSecure_AesDecrypt(&SecureAes,
					(u8 *) XFSBL_DESTINATION_PCAP_ADDR,
					(u8 *) LoadAddress, UnencryptedLength);

			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_BITSTREAM_DECRYPTION_FAIL;
				XFsbl_Printf(DEBUG_GENERAL,
						"XFSBL_ERROR_BITSTREAM_DECRYPTION_FAIL\r\n");
				/* Reset PL */
				XFsbl_Out32(CSU_PCAP_PROG, 0x0);
				goto END;
			} else {
				XFsbl_Printf(DEBUG_GENERAL,
						"Bitstream decryption Successful\r\n");
			}
#endif
		}
		else {

			/* Use CSU DMA to load Bit stream to PL */
			BitstreamWordSize = PartitionHeader->UnEncryptedDataWordLength;

			Status = XFsbl_WriteToPcap(BitstreamWordSize, (u8 *) LoadAddress);
			if (Status != XFSBL_SUCCESS) {
				goto END;
			}
		}

		Status = XFsbl_PLWaitForDone();
		if (Status != XFSBL_SUCCESS) {
			goto END;
		}

		/**
		 * Fsbl hook after bit stream download
		 */
		Status = XFsbl_HookAfterBSDownload();
		if (Status != XFSBL_SUCCESS)
		{
			Status = XFSBL_ERROR_HOOK_AFTER_BITSTREAM_DOWNLOAD;
			XFsbl_Printf(DEBUG_GENERAL,
			 "XFSBL_ERROR_HOOK_AFTER_BITSTREAM_DOWNLOAD\r\n");
			goto END;
		}
	}
#endif

	/**
	 * Update the handoff details
	 */
	if ((DestinationDevice != XIH_PH_ATTRB_DEST_DEVICE_PL) &&
			(DestinationDevice != XIH_PH_ATTRB_DEST_DEVICE_PMU))
	{
		CpuNo = FsblInstancePtr->HandoffCpuNo;
		if (XFsbl_CheckHandoffCpu(FsblInstancePtr,
				DestinationCpu) == XFSBL_SUCCESS)
		{
			FsblInstancePtr->HandoffValues[CpuNo].CpuSettings =
					DestinationCpu | ExecState;
			FsblInstancePtr->HandoffValues[CpuNo].HandoffAddress =
					PartitionHeader->DestinationExecutionAddress;
			FsblInstancePtr->HandoffCpuNo += 1U;
		}
	}

END:
	return Status;
}
/**
 * This function copies the partition to specified destination
 *
 * @param	FsblInstancePtr is pointer to the XFsbl Instance
 *
 * @param	PartitionNum is the partition number in the image to be loaded
 *
 * @return	returns the error codes described in xfsbl_error.h on any error
 * 			returns XFSBL_SUCCESS on success
 *****************************************************************************/
static u32 XFsbl_PartitionCopy(XFsblPs * FsblInstancePtr, u32 PartitionNum)
{
	u32 Status=XFSBL_SUCCESS;
	u32 DestinationCpu=0U;
	u32 CpuNo=0U;
	u32 DestinationDevice=0U;
	u32 ExecState=0U;
	XFsblPs_PartitionHeader * PartitionHeader;
	u32 SrcAddress=0U;
	PTRSIZE LoadAddress=0U;
	u32 Length=0U;
	u32 RunningCpu=0U;

	/**
	 * Assign the partition header to local variable
	 */
	PartitionHeader =
		&FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum];

	RunningCpu = FsblInstancePtr->ProcessorID;

	/**
	 * Check for XIP image
	 * No need to copy for XIP image
	 */
	DestinationCpu = XFsbl_GetDestinationCpu(PartitionHeader);

	/**
	 * Get the execution state
	 */
	ExecState = XFsbl_GetA53ExecState(PartitionHeader);

	/**
	 * if destination cpu is not present, it means it is for same cpu
	 */
	if (DestinationCpu == XIH_PH_ATTRB_DEST_CPU_NONE)
	{
		DestinationCpu = FsblInstancePtr->ProcessorID;
	}

	if (PartitionHeader->UnEncryptedDataWordLength == 0U)
	{
		/**
		 * Update the Handoff address only for the first application
		 * of that cpu
		 * This is for XIP image. For other partitions it handoff
		 * address is updated after partition validation
		 */
		CpuNo = FsblInstancePtr->HandoffCpuNo;
		if (XFsbl_CheckHandoffCpu(FsblInstancePtr,
				DestinationCpu) == XFSBL_SUCCESS)
		{
			FsblInstancePtr->HandoffValues[CpuNo].CpuSettings =
			        DestinationCpu | ExecState;
			FsblInstancePtr->HandoffValues[CpuNo].HandoffAddress =
				PartitionHeader->DestinationExecutionAddress;
			FsblInstancePtr->HandoffCpuNo += 1U;
		} else {
			/**
			 *
			 * if two partitions has same destination cpu, error can
			 * be triggered here
			 */
		}
		Status = XFSBL_SUCCESS;
		goto END;
	}

	/**
	 * Copy the PL to temporary DDR Address
	 * Copy the PS to Load Address
	 * Copy the PMU firmware to PMU RAM
	 */
	DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader);
	LoadAddress = PartitionHeader->DestinationLoadAddress;

	if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL)
	{
#ifdef XFSBL_BS

		if (LoadAddress == XFSBL_DUMMY_PL_ADDR)
		{
			LoadAddress = XFSBL_DDR_TEMP_ADDRESS;
		}
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_PL_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_PL_NOT_ENABLED;
		goto END;
#endif
	}

	/**
	 * Get the source(flash offset) address where it needs to copy
	 */
	SrcAddress = FsblInstancePtr->ImageOffsetAddress +
				((PartitionHeader->DataWordOffset) *
					XIH_PARTITION_WORD_LENGTH);

	/**
	 * Length of the partition to be copied
	 */
	Length  = (PartitionHeader->TotalDataWordLength) *
					XIH_PARTITION_WORD_LENGTH;


	/**
	 * When destination device is R5-0/R5-1/R5-L and load address is in TCM
	 * copy to high address of TCM address map
	 * Update the LoadAddress
	 */
	Status = XFsbl_GetLoadAddress(DestinationCpu, &LoadAddress, Length);
	if (XFSBL_SUCCESS != Status)
	{
		goto END;
	}

	/**
	 * Configure the memory
	 */
	XFsbl_ConfigureMemory(RunningCpu, DestinationCpu,
						LoadAddress, Length);

	/**
	 *
	 * Do not copy the IVT if FSBL is running in R5-0/R5-L at 0x0 TCM
	 * Update the SrcAddress, LoadAddress and Len based on the
	 * above condition
	 */
#if 1
	if (((FsblInstancePtr->ProcessorID ==
			XIH_PH_ATTRB_DEST_CPU_R5_0) ||
		(FsblInstancePtr->ProcessorID ==
				XIH_PH_ATTRB_DEST_CPU_R5_L)) &&
		((LoadAddress > XFSBL_R50_HIGH_TCM_START_ADDRESS) &&
		(LoadAddress <
			XFSBL_R50_HIGH_TCM_START_ADDRESS + XFSBL_IVT_LENGTH)))
	{

		/**
		 * Get the length of the IVT area to be
		 * skipped from Load Address
		 */
		TcmSkipAddress = LoadAddress/XFSBL_IVT_LENGTH;
		TcmSkipLength = XFSBL_IVT_LENGTH - TcmSkipAddress;

		/**
		 * Check if Length is less than SkipLength
		 */
		if (TcmSkipLength > Length)
		{
			TcmSkipLength = Length;
		}

		/**
		 * Copy the Skip length to a local array
		 */
		Status = FsblInstancePtr->DeviceOps.DeviceCopy(SrcAddress,
				(PTRSIZE )TcmVectorArray, TcmSkipLength);
		if (XFSBL_SUCCESS != Status)
		{
			goto END;
		}

		SrcAddress += TcmSkipLength;
		LoadAddress +=  TcmSkipLength;
		Length -= TcmSkipLength;
	}
#endif

	if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PMU)
	{
		/* Enable PMU_0 IPI */
		XFsbl_Out32(IPI_PMU_0_IER, IPI_PMU_0_IER_PMU_0_MASK);

		/* Trigger PMU0 IPI in PMU IPI TRIG Reg */
		XFsbl_Out32(IPI_PMU_0_TRIG, IPI_PMU_0_TRIG_PMU_0_MASK);

		/**
		 * Wait until PMU Microblaze goes to sleep state,
		 * before starting firmware download to PMU RAM
		 */
		while((XFsbl_In32(PMU_GLOBAL_GLOBAL_CNTRL) &
				PMU_GLOBAL_GLOBAL_CNTRL_MB_SLEEP_MASK) !=
						PMU_GLOBAL_GLOBAL_CNTRL_MB_SLEEP_MASK ) {;}
	}

	/**
	 * Copy the partition to PS_DDR/PL_DDR/TCM
	 */
	Status = FsblInstancePtr->DeviceOps.DeviceCopy(SrcAddress,
					LoadAddress, Length);
	if (XFSBL_SUCCESS != Status)
	{
		goto END;
	}

END:
	return Status;
}
/**
 * This function initializes the system using the psu_init()
 *
 * @param	FsblInstancePtr is pointer to the XFsbl Instance
 *
 * @return	returns the error codes described in xfsbl_error.h on any error
 * 			returns XFSBL_SUCCESS on success
 *
 ******************************************************************************/
static u32 XFsbl_SystemInit(XFsblPs * FsblInstancePtr)
{
	u32 Status =  XFSBL_SUCCESS;
#if defined (XPAR_PSU_DDR_0_S_AXI_BASEADDR) && !defined (ARMR5)
	u32 BlockNum;
#endif

	/**
	 * MIO33 can be used to control power to PL through PMU.
	 * For 1.0 and 2.0 Silicon, a workaround is needed to Powerup PL
	 * before MIO33 is configured. Hence, before MIO configuration,
	 * Powerup PL (but restore isolation).
	 */
	if (XGetPSVersion_Info() <= XPS_VERSION_2) {
		Status = XFsbl_PowerUpIsland(PMU_GLOBAL_PWR_STATE_PL_MASK);

		if (Status != XFSBL_SUCCESS) {
			Status = XFSBL_ERROR_PL_POWER_UP;
			XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_PL_POWER_UP\r\n");
			goto END;
		}

		/* For PS only reset, make sure FSBL exits with isolation removed */
		if (FsblInstancePtr->ResetReason != PS_ONLY_RESET) {
		XFsbl_IsolationRestore(PMU_GLOBAL_REQ_ISO_INT_EN_PL_NONPCAP_MASK);
		}
	}

	/**
	 * psu initialization
	 */
	Status = (u32)psu_init();
	if (XFSBL_SUCCESS != Status) {
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_PSU_INIT_FAILED\n\r");
		/**
		 * Need to check a way to communicate both FSBL code
		 * and PSU init error code
		 */
		Status = XFSBL_PSU_INIT_FAILED + Status;
		goto END;
	}

#ifdef XFSBL_PERF
	XTime_GetTime(&(FsblInstancePtr->PerfTime.tFsblStart));
#endif

#if defined (XPAR_PSU_DDR_0_S_AXI_BASEADDR) && !defined (ARMR5)
	/* For A53, mark DDR region as "Memory" as DDR initialization is done */

#ifdef ARMA53_64
	/* For A53 64bit*/
	for(BlockNum = 0; BlockNum < NUM_BLOCKS_A53_64; BlockNum++)
	{
		XFsbl_SetTlbAttributes(BlockNum * BLOCK_SIZE_A53_64, ATTRIB_MEMORY_A53_64);
	}
	Xil_DCacheFlush();
#else
	/* For A53 32bit*/
	for(BlockNum = 0; BlockNum < NUM_BLOCKS_A53_32; BlockNum++)
	{
		XFsbl_SetTlbAttributes(BlockNum * BLOCK_SIZE_A53_32, ATTRIB_MEMORY_A53_32);
	}
	Xil_DCacheFlush();
#endif
#endif


	/**
	 * Forcing the SD card detection signal to bypass the debouncing logic.
	 * This will ensure that SD controller doesn't end up waiting for long,
	 * fixed durations for card to be stable.
	 */
	XFsbl_Out32(IOU_SLCR_SD_CDN_CTRL,
			(IOU_SLCR_SD_CDN_CTRL_SD1_CDN_CTRL_MASK |
					IOU_SLCR_SD_CDN_CTRL_SD0_CDN_CTRL_MASK));

	/**
	 * DDR Check if present
	 */


	/**
	 * Poweroff the unused blocks as per PSU
	 */

END:
	return Status;
}
/**
 * This function checks the power state and reset for the memory type
 * and release the reset if required
 *
 * @param	MemoryType is the memory to be checked
 * 			- XFSBL_R5_0_TCM
 * 			- XFSBL_R5_1_TCM
 *				(to be added)
 *			- XFSBL_R5_0_TCMA
 *			- XFSBL_R5_0_TCMB
 *			- XFSBL_PS_DDR
 *			- XFSBL_PL_DDR
 *
 * @return	none
 *****************************************************************************/
static u32 XFsbl_PowerUpMemory(u32 MemoryType)
{
	u32 RegValue;
	u32 Status = XFSBL_SUCCESS;
	u32 PwrStateMask;

	/**
	 * Check the power status of the memory
	 * Power up if required
	 *
	 * Release the reset of the memory if present
	 */
	switch (MemoryType)
	{
		case XFSBL_R5_0_TCM:
		{

			PwrStateMask = PMU_GLOBAL_PWR_STATE_R5_0_MASK |
					PMU_GLOBAL_PWR_STATE_TCM0A_MASK |
					PMU_GLOBAL_PWR_STATE_TCM0B_MASK;

			Status = XFsbl_PowerUpIsland(PwrStateMask);

			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_R5_0_TCM_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_R5_0_TCM_POWER_UP\r\n");
				goto END;
			}

			/**
			 * To access TCM,
			 * 	Release reset to R5 and enable the clk
			 * 	R5 is under halt state
			 *
			 * 	If R5 are out of reset and clk is enabled so doing
			 * 	again is no issue. R5 might be under running state
			 */

			/**
			 * Place R5, TCM in split mode
			 */
			RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL);
			RegValue |= RPU_RPU_GLBL_CNTL_SLSPLIT_MASK;
			RegValue &= ~(RPU_RPU_GLBL_CNTL_TCM_COMB_MASK);
			RegValue &= ~(RPU_RPU_GLBL_CNTL_SLCLAMP_MASK);
			XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue);

			/**
			 * Place R5-0 in HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_0_CFG);
			RegValue &= ~(RPU_RPU_0_CFG_NCPUHALT_MASK);
			XFsbl_Out32(RPU_RPU_0_CFG, RegValue);

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL);
			RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK;
			XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue);

			/**
			 * Provide some delay,
			 * so that clock propogates properly.
			 */
			(void)usleep(0x50U);

			/**
			 * Release reset to R5-0
			 */
			RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R50_RESET_MASK);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK);
			XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue);
		} break;

		case XFSBL_R5_1_TCM:
		{

			PwrStateMask = PMU_GLOBAL_PWR_STATE_R5_1_MASK |
					PMU_GLOBAL_PWR_STATE_TCM1A_MASK |
					PMU_GLOBAL_PWR_STATE_TCM1B_MASK;

			Status = XFsbl_PowerUpIsland(PwrStateMask);

			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_R5_1_TCM_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_R5_1_TCM_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Place R5 in split mode
			 */
			RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL);
			RegValue |= RPU_RPU_GLBL_CNTL_SLSPLIT_MASK;
			RegValue &= ~(RPU_RPU_GLBL_CNTL_TCM_COMB_MASK);
			RegValue &= ~(RPU_RPU_GLBL_CNTL_SLCLAMP_MASK);
			XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue);

			/**
			 * Place R5-1 in HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_1_CFG);
			RegValue &= ~(RPU_RPU_1_CFG_NCPUHALT_MASK);
			XFsbl_Out32(RPU_RPU_1_CFG, RegValue);

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL);
			RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK;
			XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue);

			/**
			 * Provide some delay,
			 * so that clock propogates properly.
			 */
			(void )usleep(0x50U);

			/**
			 * Release reset to R5-1
			 */
			RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R51_RESET_MASK);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK);
			XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue);
		} break;

		case XFSBL_R5_L_TCM:
		{


			PwrStateMask = PMU_GLOBAL_PWR_STATE_R5_0_MASK |
					PMU_GLOBAL_PWR_STATE_TCM0A_MASK |
					PMU_GLOBAL_PWR_STATE_TCM0B_MASK |
					PMU_GLOBAL_PWR_STATE_TCM1A_MASK |
					PMU_GLOBAL_PWR_STATE_TCM1B_MASK;

			Status = XFsbl_PowerUpIsland(PwrStateMask);

			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_R5_L_TCM_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_R5_L_TCM_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Place R5 in lock step mode
			 * Combine TCM's
			 */
			RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL);
			RegValue |= RPU_RPU_GLBL_CNTL_SLCLAMP_MASK;
			RegValue &= ~(RPU_RPU_GLBL_CNTL_SLSPLIT_MASK);
			RegValue |= RPU_RPU_GLBL_CNTL_TCM_COMB_MASK;
			XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue);

			/**
                         * Place R5-0 in HALT state
                         */
                        RegValue = XFsbl_In32(RPU_RPU_0_CFG);
                        RegValue &= ~(RPU_RPU_0_CFG_NCPUHALT_MASK);
                        XFsbl_Out32(RPU_RPU_0_CFG, RegValue);

			/**
                         * Place R5-1 in HALT state
                         */
                        RegValue = XFsbl_In32(RPU_RPU_1_CFG);
                        RegValue &= ~(RPU_RPU_1_CFG_NCPUHALT_MASK);
                        XFsbl_Out32(RPU_RPU_1_CFG, RegValue);

                        /**
                         *  Enable the clock
                         */
                        RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL);
                        RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK;
                        XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue);

                        /**
                         * Provide some delay,
                         * so that clock propogates properly.
                         */
                        (void )usleep(0x50U);

                        /**
                         * Release reset to R5-0,R5-1
                         */
                        RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP);
                        RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R50_RESET_MASK);
                        RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R51_RESET_MASK);
                        RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK);
                        XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue);
		} break;

		default:
			/* nothing to do */
			break;
	}

END:
	return Status;
}
/******************************************************************************
*
* This function copies data memory to memory using ADMA.
*
* @param	DestPtr is a pointer to destination buffer to which data needs
*		to be copied.
* @param	SrcPtr is a pointer to the source buffer.
* @param	size holds the size of the data to be transfered.
*
* @return
*		Success on successful copy
*		Error on failure.
*
* @note		Cache invalidation and flushing should be taken care by user
*		Before calling this API ADMA also should be configured to
*		simple DMA.
*
******************************************************************************/
u32 XFsbl_AdmaCopy(void * DestPtr, void * SrcPtr, u32 Size)
{
	u32 RegVal;
	u64 SrcAddr = (UINTPTR)SrcPtr;
	u64 DstAddr = (UINTPTR)DestPtr;
	u32 Status = XFSBL_SUCCESS;

	/* Wait until the DMA is in idle state */
	do {
		RegVal = XFsbl_In32(ADMA_CH0_ZDMA_CH_STATUS);
		RegVal &= ADMA_CH0_ZDMA_CH_STATUS_STATE_MASK;
	} while ((RegVal != ADMA_CH0_ZDMA_CH_STATUS_STATE_DONE) &&
			(RegVal != ADMA_CH0_ZDMA_CH_STATUS_STATE_ERR));

	/* Write source Address */
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD0,
			(SrcAddr & ADMA_CH0_ZDMA_CH_DST_DSCR_WORD0_LSB_MASK));
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD1,
		(((u64)SrcAddr >> 32U) &
				ADMA_CH0_ZDMA_CH_DST_DSCR_WORD1_MSB_MASK));

	/* Write Destination Address */
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_DST_DSCR_WORD0,
		(u32)(DstAddr & ADMA_CH0_ZDMA_CH_DST_DSCR_WORD0_LSB_MASK));
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_DST_DSCR_WORD1,
			(u32)((DstAddr >> 32U) &
			ADMA_CH0_ZDMA_CH_DST_DSCR_WORD1_MSB_MASK));

	/* Size to be Transferred. Recommended to set both src and dest sizes */
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD2, Size);
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_DST_DSCR_WORD2, Size);


	/* coherence enable */
	RegVal = XFsbl_In32(ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD3);
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD3, RegVal | 0x1U);

	RegVal = XFsbl_In32(ADMA_CH0_ZDMA_CH_DST_DSCR_WORD3);
		XFsbl_Out32(ADMA_CH0_ZDMA_CH_DST_DSCR_WORD3, RegVal | 0x1U);

	/* DMA Enable */
	RegVal = XFsbl_In32(ADMA_CH0_ZDMA_CH_CTRL2);
	RegVal |= ADMA_CH0_ZDMA_CH_CTRL2_EN_MASK;
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_CTRL2, RegVal);

	/* Check the status of the transfer by polling on DMA Done */
	do {
		RegVal = XFsbl_In32(ADMA_CH0_ZDMA_CH_ISR);
		RegVal &= ADMA_CH0_ZDMA_CH_ISR_DMA_DONE_MASK;
	} while (RegVal != ADMA_CH0_ZDMA_CH_ISR_DMA_DONE_MASK);

	/* Clear DMA status */
	RegVal = XFsbl_In32(ADMA_CH0_ZDMA_CH_ISR);
	RegVal |= ADMA_CH0_ZDMA_CH_ISR_DMA_DONE_MASK;
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_ISR, ADMA_CH0_ZDMA_CH_ISR_DMA_DONE_MASK);

	/* Read the channel status for errors */
	RegVal = XFsbl_In32(ADMA_CH0_ZDMA_CH_STATUS);
	if (RegVal == ADMA_CH0_ZDMA_CH_STATUS_STATE_ERR) {
		Status = XFSBL_FAILURE;
	}

	/* Clear the TOTAL BYTE COUNT register to avoid the BYTE_CNT_OVRFLW
	*interupt from being set
	*/
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_CTRL0_TOTAL_BYTE_COUNT,0x00000000U);

	return Status;

}
/******************************************************************************
*
* This function re-authenticates the each chunk of the block and compares
* with the stored hash and sends the data AES engine if encryption exists
* and to PCAP directly in encryption is not existing.
*
* @param	PartitionParams is a pointer to XFsblPs_PlPartition
* @param	Address start address of the authentication block.
* @param	BlockLen size of the authentication block.
* @param	NoOfChunks holds the no of chunks for the provided block
*
* @return
* 		Error code on failure
* 		XFSBL_SUCESS on success
*
* @note		None.
*
******************************************************************************/
static u32 XFsbl_ReAuthenticationBlock(XFsblPs_PlPartition *PartitionParams,
				UINTPTR Address, u32 BlockLen, u32 NoOfChunks)
{
	u32 Status;
	u32 Index;
	u32 Len = PartitionParams->ChunkSize;;
	UINTPTR Offset;
	u8 ChunksHash[48];
	XSecure_Sha3 SecureSha3;
	u32 HashDataLen = BlockLen;
	u8 *HashStored = PartitionParams->PlAuth.HashsOfChunks;
	(void)memset(ChunksHash,0U,sizeof(ChunksHash));

	Status = XSecure_Sha3Initialize(&SecureSha3,
			PartitionParams->CsuDmaPtr);
	if (Status != XFSBL_SUCCESS) {
		return Status;
	}
	XSecure_Sha3Start(&SecureSha3);

	/* calculating hashs for all chunks copies to AES/PCAP */
	for (Index = 0; Index < NoOfChunks; Index++) {
			/* Last chunk */
			if (Index == NoOfChunks -1) {
				Len = HashDataLen;
			}
			Offset = (UINTPTR)Address +
				(u64)(PartitionParams->ChunkSize * Index);

			/* Copy from DDR or flash to Buffer */
			Status = XFsbl_CopyData(PartitionParams,
						PartitionParams->ChunkBuffer,
							(u8 *)Offset, Len);
			if (Status != XFSBL_SUCCESS) {
				return Status;
			}
			/* Calculating hash for each chunk */
			XSecure_Sha3Update(&SecureSha3,
				PartitionParams->ChunkBuffer, Len);
			XSecure_Sha3_ReadHash(&SecureSha3, (u8 *)ChunksHash);

			/* Comparing with stored Hashs */
			Status = XFsbl_CompareHashs(HashStored, ChunksHash,
					PartitionParams->PlAuth.AuthType);
			if (Status != XFSBL_SUCCESS) {
				XFsbl_Printf(DEBUG_GENERAL,
					"XFsbl_PlReAuth:"
				" XFSBL_ERROR_CHUNK_HASH_COMPARISON\r\n");
				XFsbl_PrintArray(DEBUG_INFO, HashStored,
					PartitionParams->PlAuth.AuthType,
					"Stored Chunk Hash");
				XFsbl_PrintArray(DEBUG_INFO, ChunksHash,
					PartitionParams->PlAuth.AuthType,
					"Calculated chunk Hash");
				Status = XFSBL_ERROR_CHUNK_HASH_COMPARISON;
				goto END;
			}
			/* Remaining block size will be in HashDataLen */
			HashDataLen = HashDataLen - PartitionParams->ChunkSize;
			if (Index+1 <= NoOfChunks - 1) {
				HashStored = HashStored +
					PartitionParams->PlAuth.AuthType;
			}

			/* If image is not encrypted */
			if (PartitionParams->IsEncrypted == FALSE) {
				/* Configure Secure stream swith to PCAP */
				XFsbl_Out32(CSU_CSU_SSS_CFG,
					XFSBL_CSU_SSS_SRC_SRC_DMA <<
					CSU_CSU_SSS_CFG_PCAP_SSS_SHIFT);

				/* Copy bitstream to PCAP */
				XFsbl_DmaPlCopy(PartitionParams->CsuDmaPtr,
					(UINTPTR)PartitionParams->ChunkBuffer,
						Len/4, 0);

				Status = XFsbl_PcapWaitForDone();
				if (Status != XFSBL_SUCCESS) {
					goto END;
				}
			}
			/* If image is encrypted */
			else {
				Status = XFsbl_DecrptPlChunks(PartitionParams,
					(UINTPTR)PartitionParams->ChunkBuffer, Len);
				if (Status != XFSBL_SUCCESS) {
					goto END;
				}
			}
		}

END:
	return Status;

}
/**
 * This function initializes the processor and updates the cluster id
 * which indicates CPU on which fsbl is running
 *
 * @param	FsblInstancePtr is pointer to the XFsbl Instance
 *
 * @return	returns the error codes described in xfsbl_error.h on any error
 * 			returns XFSBL_SUCCESS on success
 *
 ******************************************************************************/
static u32 XFsbl_ProcessorInit(XFsblPs * FsblInstancePtr)
{
	u32 Status = XFSBL_SUCCESS;
	//u64 ClusterId=0U;
	PTRSIZE ClusterId=0U;
	u32 RegValue;
	u32 Index=0U;

	/**
	 * Read the cluster ID and Update the Processor ID
	 * Initialize the processor settings that are not done in
	 * BSP startup code
	 */
#ifdef ARMA53_64
	ClusterId = mfcp(MPIDR_EL1);
#else
	ClusterId = mfcp(XREG_CP15_MULTI_PROC_AFFINITY);
#endif

	XFsbl_Printf(DEBUG_INFO,"Cluster ID 0x%0lx\n\r", ClusterId);

	if (XGet_Zynq_UltraMp_Platform_info() == XPLAT_ZYNQ_ULTRA_MPQEMU) {
		/**
		 * Remmaping for R5 in QEMU
		 */
		if (ClusterId == 0x80000004U) {
			ClusterId = 0xC0000100U;
		} else if (ClusterId == 0x80000005U) {
			/* this corresponds to R5-1 */
			Status = XFSBL_ERROR_UNSUPPORTED_CLUSTER_ID;
			XFsbl_Printf(DEBUG_GENERAL,
					"XFSBL_ERROR_UNSUPPORTED_CLUSTER_ID\n\r");
			goto END;
		} else {
			/* For MISRA C compliance */
		}
	}

	/* store the processor ID based on the cluster ID */
	if ((ClusterId & XFSBL_CLUSTER_ID_MASK) == XFSBL_A53_PROCESSOR) {
		XFsbl_Printf(DEBUG_GENERAL,"Running on A53-0 ");
		FsblInstancePtr->ProcessorID =
				XIH_PH_ATTRB_DEST_CPU_A53_0;
#ifdef __aarch64__
		/* Running on A53 64-bit */
		XFsbl_Printf(DEBUG_GENERAL,"(64-bit) Processor \n\r");
		FsblInstancePtr->A53ExecState = XIH_PH_ATTRB_A53_EXEC_ST_AA64;
#else
		/* Running on A53 32-bit */
		XFsbl_Printf(DEBUG_GENERAL,"(32-bit) Processor \n\r");
		FsblInstancePtr->A53ExecState = XIH_PH_ATTRB_A53_EXEC_ST_AA32;
#endif

	} else if ((ClusterId & XFSBL_CLUSTER_ID_MASK) == XFSBL_R5_PROCESSOR) {
		/* A53ExecState is not valid for R5 */
		FsblInstancePtr->A53ExecState = XIH_INVALID_EXEC_ST;

		RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL);
		if ((RegValue & RPU_RPU_GLBL_CNTL_SLSPLIT_MASK) == 0U) {
			XFsbl_Printf(DEBUG_GENERAL,
				"Running on R5 Processor in Lockstep \n\r");
			FsblInstancePtr->ProcessorID =
				XIH_PH_ATTRB_DEST_CPU_R5_L;
		} else {
			XFsbl_Printf(DEBUG_GENERAL,
				"Running on R5-0 Processor \n\r");
			FsblInstancePtr->ProcessorID =
				XIH_PH_ATTRB_DEST_CPU_R5_0;
		}

		/**
		 * Update the Vector locations in R5 TCM
		 */
		while (Index<32U) {
			XFsbl_Out32(Index, XFSBL_R5_VECTOR_VALUE);
			Index += 4;
		}

	} else {
		Status = XFSBL_ERROR_UNSUPPORTED_CLUSTER_ID;
		XFsbl_Printf(DEBUG_GENERAL,
				"XFSBL_ERROR_UNSUPPORTED_CLUSTER_ID\n\r");
		goto END;
	}

	/**
	 * Register the exception handlers
	 */
	XFsbl_RegisterHandlers();

	/* Prints for the perf measurement */
#ifdef XFSBL_PERF

#if !defined(ARMR5)
	if (FsblInstancePtr->ProcessorID == XIH_PH_ATTRB_DEST_CPU_A53_0) {
		XFsbl_Printf(DEBUG_PRINT_ALWAYS, "Proc: A53-0 Freq: %d Hz",
				XPAR_CPU_CORTEXA53_0_CPU_CLK_FREQ_HZ);

		if (FsblInstancePtr->A53ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32) {
			XFsbl_Printf(DEBUG_PRINT_ALWAYS, " Arch: 32 \r\n");
		}
		else if (FsblInstancePtr->A53ExecState ==
				XIH_PH_ATTRB_A53_EXEC_ST_AA64) {
			XFsbl_Printf(DEBUG_PRINT_ALWAYS, " Arch: 64 \r\n");
		}
	}
#else
	if (FsblInstancePtr->ProcessorID == XIH_PH_ATTRB_DEST_CPU_R5_0) {
		XFsbl_Printf(DEBUG_PRINT_ALWAYS, "Proc: R5-0 Freq: %d Hz \r\n",
				XPAR_PSU_CORTEXR5_0_CPU_CLK_FREQ_HZ)
	}
	else if (FsblInstancePtr->ProcessorID == XIH_PH_ATTRB_DEST_CPU_R5_L) {
		XFsbl_Printf(DEBUG_PRINT_ALWAYS, "Proc: R5-Lockstep "
			"Freq: %d Hz \r\n", XPAR_PSU_CORTEXR5_0_CPU_CLK_FREQ_HZ);
	}
#endif

#endif

END:
	return Status;
}
/**
 * This function initializes the processor and updates the cluster id
 * which indicates CPU on which fsbl is running
 *
 * @param	FsblInstancePtr is pointer to the XFsbl Instance
 *
 * @return	returns the error codes described in xfsbl_error.h on any error
 * 			returns XFSBL_SUCCESS on success
 *
 ******************************************************************************/
static u32 XFsbl_ProcessorInit(XFsblPs * FsblInstancePtr)
{
	u32 Status = XFSBL_SUCCESS;
	//u64 ClusterId=0U;
	PTRSIZE ClusterId=0U;
	u32 RegValue;
	u32 Index=0U;

	/**
	 * Read the cluster ID and Update the Processor ID
	 * Initialize the processor settings that are not done in
	 * BSP startup code
	 */
#ifdef XFSBL_A53
	ClusterId = mfcp(MPIDR_EL1);
#else
	ClusterId = mfcp(XREG_CP15_MULTI_PROC_AFFINITY);
#endif

	XFsbl_Printf(DEBUG_INFO,"Cluster ID 0x%0lx\n\r", ClusterId);

	if (XFSBL_PLATFORM == XFSBL_PLATFORM_QEMU) {
		/**
		 * Remmaping for R5 in QEMU
		 */
		if (ClusterId == 0x80000004U) {
			ClusterId = 0xC0000100U;
		} else if (ClusterId == 0x80000005U) {
			/* this corresponds to R5-1 */
			Status = XFSBL_ERROR_UNSUPPORTED_CLUSTER_ID;
			XFsbl_Printf(DEBUG_GENERAL,
					"XFSBL_ERROR_UNSUPPORTED_CLUSTER_ID\n\r");
			goto END;
		} else {
			/* For MISRA C compliance */
		}
	}

	/* store the processor ID based on the cluster ID */
	if ((ClusterId & XFSBL_CLUSTER_ID_MASK) == XFSBL_A53_PROCESSOR) {
		XFsbl_Printf(DEBUG_GENERAL,"Running on A53-0 ");
		FsblInstancePtr->ProcessorID =
				XIH_PH_ATTRB_DEST_CPU_A53_0;
#ifdef __aarch64__
		/* Running on A53 64-bit */
		XFsbl_Printf(DEBUG_GENERAL,"(64-bit) Processor \n\r");
		FsblInstancePtr->A53ExecState = XIH_PH_ATTRB_A53_EXEC_ST_AA64;
#else
		/* Running on A53 32-bit */
		XFsbl_Printf(DEBUG_GENERAL,"(32-bit) Processor \n\r");
		FsblInstancePtr->A53ExecState = XIH_PH_ATTRB_A53_EXEC_ST_AA32;
#endif

	} else if ((ClusterId & XFSBL_CLUSTER_ID_MASK) == XFSBL_R5_PROCESSOR) {
		/* A53ExecState is not valid for R5 */
		FsblInstancePtr->A53ExecState = XIH_INVALID_EXEC_ST;

		RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL);
		if ((RegValue & RPU_RPU_GLBL_CNTL_SLSPLIT_MASK) == 0U) {
			XFsbl_Printf(DEBUG_GENERAL,
				"Running on R5 Processor in Lockstep \n\r");
			FsblInstancePtr->ProcessorID =
				XIH_PH_ATTRB_DEST_CPU_R5_L;
		} else {
			XFsbl_Printf(DEBUG_GENERAL,
				"Running on R5-0 Processor \n\r");
			FsblInstancePtr->ProcessorID =
				XIH_PH_ATTRB_DEST_CPU_R5_0;
		}

		/**
		 * Update the Vector locations in R5 TCM
		 */
		while (Index<32U) {
			XFsbl_Out32(Index, 0U);
			XFsbl_Out32(Index, XFSBL_R5_VECTOR_VALUE);
			Index += 4;
		}

	} else {
		Status = XFSBL_ERROR_UNSUPPORTED_CLUSTER_ID;
		XFsbl_Printf(DEBUG_GENERAL,
				"XFSBL_ERROR_UNSUPPORTED_CLUSTER_ID\n\r");
		goto END;
	}

	/**
	 * Register the exception handlers
	 */
	XFsbl_RegisterHandlers();

END:
	return Status;
}
/**
* This function authenticates the bitstream in blocks. Sends the data to PCAP
* in blocks via AES engine if encryption exists or directly to PCAP by CSUDMA
* if an encryption is not enabled.
*
* @param	PartitionParams is pointer to XFsblPs_PlPartition structure
* 		which has to be initialized by required parameters.
*
* @return
* 		- XFSBL_SUCCESS on success
* 		- Returns error code on failure
*
* @note		Currently SHA2 is not been supported but gave option in
* 		structure and will be used later
*
******************************************************************************/
u32 XFsbl_SecPlPartition(XFsblPs * FsblInstancePtr,
			XFsblPs_PlPartition *PartitionParams)
{
	u32 Status = XFSBL_SUCCESS;
	u8 Index;
	u32 Len;
	UINTPTR SrcAddress = (u64)PartitionParams->StartAddress;
	UINTPTR CurrentAcOffset = PartitionParams->PlAuth.AcOfset;
	u8 IsLastBlock = FALSE;
	u32 RegVal;

	if (PartitionParams->IsAuthenticated != TRUE) {
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_SECURE_NOT_ENABLED"
				" for PL partition\r\n");
		Status = XFSBL_ERROR_SECURE_NOT_ENABLED;
		goto END;
	}

	/* AES initialization expects IV in required format */
	if (PartitionParams->IsEncrypted == TRUE) {
		PartitionParams->PlEncrypt.NextBlkLen = 0;
		if (PartitionParams->PlEncrypt.SecureAes == NULL) {
			XFsbl_Printf(DEBUG_GENERAL,
				"XFSBL_ERROR_SECURE_NOT_ENABLED"
					" for PL partition \r\n");
			Status = XFSBL_ERROR_SECURE_NOT_ENABLED;
			goto END;
		}
		if ((PartitionParams->PlEncrypt.SecureAes->KeySel
				== XSECURE_CSU_AES_KEY_SRC_KUP) &&
			(PartitionParams->PlEncrypt.SecureAes->Key == NULL)) {
			XFsbl_Printf(DEBUG_GENERAL,
				"KUP key is not been provided"
					" for PL partition\r\n");
			Status = XFSBL_FAILURE;
			goto END;
		}
	}

	/* Enable Simple DMA Mode for ADMA channel 0 */
	RegVal = XFsbl_In32(ADMA_CH0_ZDMA_CH_CTRL0);
	RegVal &= (ADMA_CH0_ZDMA_CH_CTRL0_POINT_TYPE_MASK |
			ADMA_CH0_ZDMA_CH_CTRL0_MODE_MASK);
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_CTRL0, RegVal);

	Xil_DCacheDisable();
	/* Loop for traversing all blocks */
	for (Len = PartitionParams->PlAuth.BlockSize, Index = 1;
			SrcAddress < PartitionParams->PlAuth.AcOfset; Index++) {
		Status = XFsbl_CopyData(PartitionParams,
			PartitionParams->PlAuth.AuthCertBuf,
			(u8 *)CurrentAcOffset, XFSBL_AUTH_CERT_MIN_SIZE);
		if (Status != XFSBL_SUCCESS) {
			XFsbl_Printf(DEBUG_GENERAL,
			"Copy of chunk from flash/DDR to OCM failed \r\n");
			return Status;
		}

		/*
		 * If the block start address + block size exceeds
		 * first AC address it is last block
		 */
		if (SrcAddress + PartitionParams->PlAuth.BlockSize >
					PartitionParams->PlAuth.AcOfset) {
			/*
			 * Data placed in last block might not be full block size
			 * TotalLen -
			 * (NoofBlocks)*(AC size) - (NoOfBlocks - 1)*BlockSize
			 */
			Len = (PartitionParams->TotalLen) -
				(Index) * (XFSBL_AUTH_CERT_MIN_SIZE) -
				(Index -1)*(PartitionParams->PlAuth.BlockSize);
			IsLastBlock = TRUE;
		}

		Status = XFsbl_PlBlockAuthentication(FsblInstancePtr,
				PartitionParams, SrcAddress, Len,
				(u8 *)PartitionParams->PlAuth.AuthCertBuf);
		if (Status != XFSBL_SUCCESS) {
			return Status;
		}

		if (IsLastBlock == FALSE) {
			CurrentAcOffset =
				CurrentAcOffset + XFSBL_AUTH_CERT_MIN_SIZE;
			SrcAddress =
				SrcAddress + PartitionParams->PlAuth.BlockSize;
		}
		else {
			/* Completed last block of bitstream */
			break;
		}
	}
	Xil_DCacheEnable();
#ifdef XFSBL_PS_DDR
	/* Restore reset values for the DMA registers used */
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_CTRL0, 0x00000080U);
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_DST_DSCR_WORD0, 0x00000000U);
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_DST_DSCR_WORD1, 0x00000000U);
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_DST_DSCR_WORD2, 0x00000000U);
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_DST_DSCR_WORD3, 0x00000000U);
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD0, 0x00000000U);
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD1, 0x00000000U);
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD2, 0x00000000U);
	XFsbl_Out32(ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD3, 0x00000000U);
#endif

END:

	return Status;

}
/**
 * This function does ECC Initialization of DDR memory
 *
 * @param none
 *
 * @return
 * 		- XFSBL_SUCCESS for successful ECC Initialization
 * 		-               or ECC is not enabled for DDR
 * 		- errors as mentioned in xfsbl_error.h
 *
 *****************************************************************************/
u32 XFsbl_DdrEccInit(void)
{
	u32 Status =  XFSBL_SUCCESS;
#if XPAR_PSU_DDRC_0_HAS_ECC
	u32 LengthBytes = XFSBL_PS_DDR_END_ADDRESS - XFSBL_PS_DDR_INIT_START_ADDRESS;
	u32 Length = 0;
	u32 DestAddr = XFSBL_PS_DDR_INIT_START_ADDRESS;
	u32 RegVal;

	XFsbl_Printf(DEBUG_GENERAL,"\n\rInitializing DDR ECC\n\r");

	Xil_DCacheDisable();

	while (LengthBytes > 0) {
		if (LengthBytes > GDMA_TRANSFER_MAX_LEN) {
			Length = GDMA_TRANSFER_MAX_LEN;
		} else {
			Length = LengthBytes;
		}

		/* Wait until the DMA is in idle state */
		do {
			RegVal = XFsbl_In32(GDMA_CH0_ZDMA_CH_STATUS);
			RegVal &= GDMA_CH0_ZDMA_CH_STATUS_STATE_MASK;
		} while ((RegVal != GDMA_CH0_ZDMA_CH_STATUS_STATE_DONE) &&
				(RegVal != GDMA_CH0_ZDMA_CH_STATUS_STATE_ERR));

		/* Enable Simple (Write Only) Mode */
		RegVal = XFsbl_In32(GDMA_CH0_ZDMA_CH_CTRL0);
		RegVal &= (GDMA_CH0_ZDMA_CH_CTRL0_POINT_TYPE_MASK |
				GDMA_CH0_ZDMA_CH_CTRL0_MODE_MASK);
		RegVal |= (GDMA_CH0_ZDMA_CH_CTRL0_POINT_TYPE_NORMAL |
				GDMA_CH0_ZDMA_CH_CTRL0_MODE_WR_ONLY);
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_CTRL0, RegVal);

		/* Fill in the data to be written */
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_WR_ONLY_WORD0, XFSBL_ECC_INIT_VAL_WORD);
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_WR_ONLY_WORD1, XFSBL_ECC_INIT_VAL_WORD);
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_WR_ONLY_WORD2, XFSBL_ECC_INIT_VAL_WORD);
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_WR_ONLY_WORD3, XFSBL_ECC_INIT_VAL_WORD);

		/* Write Destination Address */
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_DST_DSCR_WORD0, DestAddr);

		/* Size to be Transferred (for write-only mode, only dest is needed)*/
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_DST_DSCR_WORD2, Length);

		/* DMA Enable */
		RegVal = XFsbl_In32(GDMA_CH0_ZDMA_CH_CTRL2);
		RegVal |= GDMA_CH0_ZDMA_CH_CTRL2_EN_MASK;
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_CTRL2, RegVal);

		/* Check the status of the transfer by polling on DMA Done */
		do {
			RegVal = XFsbl_In32(GDMA_CH0_ZDMA_CH_ISR);
			RegVal &= GDMA_CH0_ZDMA_CH_ISR_DMA_DONE_MASK;
		} while (RegVal != GDMA_CH0_ZDMA_CH_ISR_DMA_DONE_MASK);

		/* Clear DMA status */
		RegVal = XFsbl_In32(GDMA_CH0_ZDMA_CH_ISR);
		RegVal |= GDMA_CH0_ZDMA_CH_ISR_DMA_DONE_MASK;
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_ISR, GDMA_CH0_ZDMA_CH_ISR_DMA_DONE_MASK);

		/* Read the channel status for errors */
		RegVal = XFsbl_In32(GDMA_CH0_ZDMA_CH_STATUS);
		if (RegVal == GDMA_CH0_ZDMA_CH_STATUS_STATE_ERR) {
			Status = XFSBL_ERROR_DDR_ECC_INIT;
			XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_DDR_ECC_INIT\n\r");
			Xil_DCacheEnable();
			goto END;
		}

		LengthBytes -= Length;
		DestAddr += Length;
	}

	Xil_DCacheEnable();

END:
#endif
	return Status;
}