/** * * This function reads the requested data from NAND FLASH interface. * This function does not handle bad blocks. Return what it is. * * @param Address into the FLASH data space * * @return Data at the provided offset in the FLASH * * @note None. * ****************************************************************************/ u32 ReadNand(u32 Address, u32 *Data) { u32 Status; u32 Page; u32 *WordPtr; fsbl_printf(DEBUG_INFO,"ReadNand: Address = 0x%.8x\r\n", Address); WordPtr = (u32 *)NandInstance.DataBuf; Page = (Address)/(NandInstance.Geometry.BytesPerPage); Status = XNandPs_Read(NandInstPtr, (u64)(Page * (NandInstance.Geometry.BytesPerPage)), NandInstance.Geometry.BytesPerPage, NandInstance.DataBuf,NULL); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_GENERAL,"ReadNand Failed: Status = 0x%.8x\r\n", Status); return XST_FAILURE; } *Data = WordPtr[((Address) & (NandInstance.Geometry.BytesPerPage - 1))/4]; return Status; } /* End of ReadNand function */
/** * * This function initializes the controller for the SD FLASH interface. * * @param filename of the file that is to be used * * @return * - XST_SUCCESS if the controller initializes correctly * - XST_FAILURE if the controller fails to initializes correctly * * @note None. * ****************************************************************************/ u32 InitSD(const char *filename) { FRESULT rc; TCHAR *path = "0:/"; /* Logical drive number is 0 */ /* Register volume work area, initialize device */ rc = f_mount(&fatfs, path, 0); fsbl_printf(DEBUG_INFO,"SD: rc= %.8x\n\r", rc); if (rc != FR_OK) { return XST_FAILURE; } strcpy_rom(buffer, filename); boot_file = (char *)buffer; FlashReadBaseAddress = XPAR_PS7_SD_0_S_AXI_BASEADDR; rc = f_open(&fil, boot_file, FA_READ); if (rc) { fsbl_printf(DEBUG_GENERAL,"SD: Unable to open file %s: %d\n", boot_file, rc); return XST_FAILURE; } return XST_SUCCESS; }
/** * * This function validates the partition header. * * @param Header Partition header pointer * * @return * - XST_FAILURE if bad header. * - XST_SUCCESS if successful. * * @note None * *******************************************************************************/ u32 ValidateHeader(PartHeader *Header) { struct HeaderArray *Hap; Hap = (struct HeaderArray *)Header; /* * If there are no partitions to load, fail */ if (IsEmptyHeader(Hap) == XST_SUCCESS) { fsbl_printf(DEBUG_GENERAL, "IMAGE_HAS_NO_PARTITIONS\r\n"); return XST_FAILURE; } /* * Validate partition header checksum */ if (ValidatePartitionHeaderChecksum(Hap) != XST_SUCCESS) { fsbl_printf(DEBUG_GENERAL, "PARTITION_HEADER_CORRUPTION\r\n"); return XST_FAILURE; } /* * Validate partition data size */ if (Header->ImageWordLen > MAXIMUM_IMAGE_WORD_LEN) { fsbl_printf(DEBUG_GENERAL, "INVALID_PARTITION_LENGTH\r\n"); return XST_FAILURE; } return XST_SUCCESS; }
/** * * This function goes to the partition header of the specified partition * * @param ImageAddress is the start address of the image * @param PartNum is the partition number to go to * * @return Partition header address of the partition * * @note None * ****************************************************************************/ static u32 GoToPartition(u32 ImageAddress, int PartNum) { u32 HdrAddr; fsbl_printf(DEBUG_INFO,"ImageAddress = 0x%x \r \n",ImageAddress); MoveImage(ImageAddress + IMAGE_PHDR_OFFSET, (u32)&HdrAddr, 4); fsbl_printf(DEBUG_INFO,"Partition hdr for %d: %x\n\r", PartNum, ImageAddress + HdrAddr + PARTITION_HDR_TOTAL_LEN * (PartNum + 1)); return (ImageAddress + HdrAddr + PARTITION_HDR_TOTAL_LEN * (PartNum + 1)); }
/****************************************************************************** * * This function reads serial FLASH ID connected to the SPI interface. * It then deduces the make and size of the flash and obtains the * connection mode to point to corresponding parameters in the flash * configuration table. The flash driver will function based on this and * it presently supports Micron and Spansion - 128, 256 and 512Mbit and * Winbond 128Mbit * * @param none * * @return XST_SUCCESS if read id, otherwise XST_FAILURE. * * @note None. * ******************************************************************************/ u32 FlashReadID(void) { u32 Status; /* * Read ID in Auto mode. */ WriteBuffer[COMMAND_OFFSET] = READ_ID_CMD; WriteBuffer[ADDRESS_1_OFFSET] = 0x00; /* 3 dummy bytes */ WriteBuffer[ADDRESS_2_OFFSET] = 0x00; WriteBuffer[ADDRESS_3_OFFSET] = 0x00; Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, ReadBuffer, RD_ID_SIZE); if (Status != XST_SUCCESS) { return XST_FAILURE; } fsbl_printf(DEBUG_INFO,"Single Flash Information\r\n"); fsbl_printf(DEBUG_INFO,"FlashID=0x%x 0x%x 0x%x\r\n", ReadBuffer[1], ReadBuffer[2], ReadBuffer[3]); /* * Deduce flash make */ if (ReadBuffer[1] == MICRON_ID) { QspiFlashMake = MICRON_ID; fsbl_printf(DEBUG_INFO, "MICRON "); } else if(ReadBuffer[1] == SPANSION_ID) { QspiFlashMake = SPANSION_ID; fsbl_printf(DEBUG_INFO, "SPANSION "); } else if(ReadBuffer[1] == WINBOND_ID) { QspiFlashMake = WINBOND_ID; fsbl_printf(DEBUG_INFO, "WINBOND "); } /* * Deduce flash Size */ if (ReadBuffer[3] == FLASH_SIZE_ID_128M) { QspiFlashSize = FLASH_SIZE_128M; fsbl_printf(DEBUG_INFO, "128M Bits\r\n"); } else if (ReadBuffer[3] == FLASH_SIZE_ID_256M) { QspiFlashSize = FLASH_SIZE_256M; fsbl_printf(DEBUG_INFO, "256M Bits\r\n"); } else if (ReadBuffer[3] == FLASH_SIZE_ID_512M) { QspiFlashSize = FLASH_SIZE_512M; fsbl_printf(DEBUG_INFO, "512M Bits\r\n"); } else if (ReadBuffer[3] == FLASH_SIZE_ID_1G) { QspiFlashSize = FLASH_SIZE_1G; fsbl_printf(DEBUG_INFO, "1G Bits\r\n"); } return XST_SUCCESS; }
/** * * This function validates the partition header. * * @param Partition header pointer * * @return * - MOVE_IMAGE_FAIL if bad header. * - XST_SUCCESS if successful. * * @note None * *******************************************************************************/ u32 ValidateHeader(struct PartHeader *Header) { struct HeaderArray *Hap; u32 ImageLength; u32 PartitionLength; Hap = (struct HeaderArray *)Header; /* If there are no partitions to load, fail */ if (IsLastPartition(Hap) || IsEmptyHeader(Hap)) { fsbl_printf(DEBUG_GENERAL,"IMAGE_HAS_NO_PARTITIONS\r\n"); OutputStatus(IMAGE_HAS_NO_PARTITIONS); return MOVE_IMAGE_FAIL; } /* Validate Checksum of partition header */ if (PartitionHeaderChecksum(Hap) == XST_FAILURE) { fsbl_printf(DEBUG_GENERAL,"PARTITION_HEADER_CORRUPTION\r\n"); OutputStatus(PARTITION_HEADER_CORRUPTION); return MOVE_IMAGE_FAIL; } ImageLength = Header->ImageWordLen; PartitionLength = Header->PartitionWordLen; if (ImageLength > MAXIMUM_IMAGE_WORD_LEN) { fsbl_printf(DEBUG_GENERAL,"INVALID_PARTITION_LENGTH\r\n"); OutputStatus(INVALID_PARTITION_LENGTH); return MOVE_IMAGE_FAIL; } /* For current tool implementation, partition header is not * encrypted. If the tool will encrypt the partition header, * the following should be overwritten after header decryption */ if (ImageLength == 0) { /* if it is an empty partition, it is OK */ if (PartitionLength != 0) { fsbl_printf(DEBUG_INFO,"PartitionImageMove:" "0 Image Length, " "non-zero partition Length\r\n"); fsbl_printf(DEBUG_GENERAL,"INVALID_PARTITION_HEADER\r\n"); OutputStatus(INVALID_PARTITION_HEADER); return MOVE_IMAGE_FAIL; } } return XST_SUCCESS; } /* end of ValidateHeader */
/** * * This function initializes the controller for the NAND FLASH interface. * * @param none * * @return * - XST_SUCCESS if the controller initializes correctly * - XST_FAILURE if the controller fails to initializes correctly * * @note none. * ****************************************************************************/ u32 InitNand(void) { u32 Status; XNandPs_Config *ConfigPtr; /* * Set up pointers to instance and the config structure */ NandInstPtr = &NandInstance; /* * Initialize the flash driver. */ ConfigPtr = XNandPs_LookupConfig(NAND_DEVICE_ID); if (ConfigPtr == NULL) { fsbl_printf(DEBUG_GENERAL,"Nand Driver failed \n \r"); return XST_FAILURE; } Status = XNandPs_CfgInitialize(NandInstPtr, ConfigPtr, ConfigPtr->SmcBase,ConfigPtr->FlashBase); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_GENERAL,"NAND intialization failed \n \r"); return XST_FAILURE; } /* * Set up base address for access */ FlashReadBaseAddress = XPS_NAND_BASEADDR; fsbl_printf(DEBUG_INFO,"InitNand: Geometry = 0x%x\r\n", NandInstPtr->Geometry.FlashWidth); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_GENERAL,"InitNand: Status = 0x%.8x\r\n", Status); return XST_FAILURE; } /* * set up the FLASH access pointers */ fsbl_printf(DEBUG_INFO,"Nand driver initialized \n\r"); return XST_SUCCESS; }
/** * * This function dumps the partition header. * * @param Partition header pointer * * @return None * * @note None * *******************************************************************************/ void DumpHeader(struct PartHeader *Header) { fsbl_printf(DEBUG_INFO,"Image Word Len:%08x\n\r", Header->ImageWordLen); fsbl_printf(DEBUG_INFO,"Data Word Len: %08x\n\r", Header->DataWordLen); fsbl_printf(DEBUG_INFO,"Partition Word Len:%08x\n\r", Header->DataWordLen); fsbl_printf(DEBUG_INFO,"Load Addr:%08x\n\r", Header->LoadAddr); fsbl_printf(DEBUG_INFO,"Exec Addr:%08x\n\r", Header->ExecAddr); fsbl_printf(DEBUG_INFO,"Partition Start:%08x\n\r", Header->PartitionStart); fsbl_printf(DEBUG_INFO,"Partition Attr:%08x\n\r", Header->PartitionAttr); fsbl_printf(DEBUG_INFO,"Section Count:%08x\n\r", Header->SectionCount); fsbl_printf(DEBUG_INFO,"Checksum:%08x\n\r", Header->CheckSum); }
/** * * This function checks the header checksum If the header checksum is not valid * XST_FAILURE is returned. * * @param H is a pointer to struct HeaderArray * * @return * - XST_SUCCESS is header checksum is ok * - XST_FAILURE if the header checksum is not correct * * @note None. * ****************************************************************************/ static u32 PartitionHeaderChecksum(struct HeaderArray *H) { u32 Checksum; u32 Count; Checksum = 0; for (Count = 0; Count < PARTITION_HDR_CHECKSUM_WORD_COUNT; Count++) { /* Read the word from the header */ Checksum += H->Fields[Count]; } /* Invert checksum, last bit of error checking */ Checksum ^= 0xFFFFFFFF; /* Validate the checksum */ if (H->Fields[PARTITION_HDR_CHECKSUM_WORD_COUNT] != Checksum) { fsbl_printf(DEBUG_GENERAL,"Checksum %8.8x != %8.8x\r\n", Checksum, H->Fields[PARTITION_HDR_CHECKSUM_WORD_COUNT]); return XST_FAILURE; } return XST_SUCCESS; }
void FsblPrintArray (u8 *Buf, u32 Len, char *Str) { #ifdef FSBL_DEBUG_RSA int Index; fsbl_printf(DEBUG_INFO, "%s START\r\n", Str); for (Index=0;Index<Len;Index++) { fsbl_printf(DEBUG_INFO, "%02x",Buf[Index]); if ((Index+1)%16 == 0){ fsbl_printf(DEBUG_INFO, "\r\n"); } } fsbl_printf(DEBUG_INFO, "\r\n %s END\r\n",Str); #endif return; }
/** * * This function Validate Partition Data by using checksum preset in image * * @param Partition header pointer * @param Partition check sum offset * @return * - XST_SUCCESS if partition data is ok * - XST_FAILURE if partition data is corrupted * * @note None * *******************************************************************************/ u32 ValidateParition(u32 StartAddr, u32 Length, u32 ChecksumOffset) { u8 Checksum[MD5_CHECKSUM_SIZE]; u8 CalcChecksum[MD5_CHECKSUM_SIZE]; u32 Status; u32 Index; #ifdef XPAR_XWDTPS_0_BASEADDR /* * Prevent WDT reset */ XWdtPs_RestartWdt(&Watchdog); #endif /* * Get checksum from flash */ Status = GetPartitionChecksum(ChecksumOffset, &Checksum[0]); if(Status != XST_SUCCESS) { return XST_FAILURE; } fsbl_printf(DEBUG_INFO, "Actual checksum\r\n"); for (Index = 0; Index < MD5_CHECKSUM_SIZE; Index++) { fsbl_printf(DEBUG_INFO, "0x%0x ",Checksum[Index]); } fsbl_printf(DEBUG_INFO, "\r\n"); /* * Calculate checksum for the partition */ Status = CalcPartitionChecksum(StartAddr, Length, &CalcChecksum[0]); if(Status != XST_SUCCESS) { return XST_FAILURE; } fsbl_printf(DEBUG_INFO, "Calculated checksum\r\n"); for (Index = 0; Index < MD5_CHECKSUM_SIZE; Index++) { fsbl_printf(DEBUG_INFO, "0x%0x ",CalcChecksum[Index]); } fsbl_printf(DEBUG_INFO, "\r\n"); /* * Compare actual checksum with the calculated checksum */ for (Index = 0; Index < MD5_CHECKSUM_SIZE; Index++) { if(Checksum[Index] != CalcChecksum[Index]) { fsbl_printf(DEBUG_GENERAL, "Error: " "Partition DataChecksum 0x%0x!= 0x%0x\r\n", Checksum[Index], CalcChecksum[Index]); return XST_FAILURE; } } return XST_SUCCESS; }
/****************************************************************************** * This function is the hook which will be called in case FSBL fall back * * @param None * * @return None * ****************************************************************************/ void FsblHookFallback(void) { /* * User logic to be added here. * Errors to be stored in the status variable and returned */ fsbl_printf(DEBUG_INFO,"In FsblHookFallback function \r\n"); while(1); }
/****************************************************************************** * This function is the hook which will be called before the bitstream download. * The user can add all the customized code required to be executed before the * bitstream download to this routine. * * @param None * * @return * - XST_SUCCESS to indicate success * - XST_FAILURE.to indicate failure * ****************************************************************************/ u32 FsblHookBeforeBitstreamDload(void) { u32 Status; Status = XST_SUCCESS; /* User logic to be added here. Errors to be stored in the status variable * and returned */ fsbl_printf(DEBUG_INFO,"In FsblHookBeforeBitstreamDload function \r\n"); return (Status); } /* End of FsblHookBeforeBitstreamDload */
/** * * This function provides the SD FLASH interface for the Simplified header * functionality. * * @param SourceAddress is address in FLASH data space * @param DestinationAddress is address in OCM data space * @param LengthBytes is the number of bytes to move * * @return * - XST_SUCCESS if the write completes correctly * - XST_FAILURE if the write fails to completes correctly * * @note None. * ****************************************************************************/ u32 SDAccess( u32 SourceAddress, u32 DestinationAddress, u32 LengthBytes) { FRESULT rc; /* Result code */ UINT br; rc = f_lseek(&fil, SourceAddress); if (rc) { fsbl_printf(DEBUG_INFO,"SD: Unable to seek to %x\n", SourceAddress); return XST_FAILURE; } rc = f_read(&fil, (void*)DestinationAddress, LengthBytes, &br); if (rc) { fsbl_printf(DEBUG_GENERAL,"*** ERROR: f_read returned %d\r\n", rc); } return XST_SUCCESS; } /* End of SDAccess */
/** * * This function goes to the partition header of the specified partition * * @param ImageAddress is the start address of the image * * @return Offset to Image header table address of the image * * @return - XST_SUCCESS if Get Partition Header start address successful * - XST_FAILURE if Get Partition Header start address failed * * @note None * ****************************************************************************/ u32 GetImageHeaderStartAddr(u32 ImageAddress, u32 *Offset) { u32 Status; Status = MoveImage(ImageAddress + IMAGE_HDR_OFFSET, (u32)Offset, 4); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_GENERAL,"Move Image failed\r\n"); return XST_FAILURE; } return XST_SUCCESS; }
/** * * This function get the header information of the all the partitions and load into * global array * * @param PartHeaderOffset Offset address where the header information present * * @param Header Partition header pointer * * @return - XST_SUCCESS if Load Partitions Header information successful * - XST_FAILURE if Load Partitions Header information failed * * @note None * ****************************************************************************/ u32 LoadPartitionsHeaderInfo(u32 PartHeaderOffset, PartHeader *Header) { u32 Status; Status = MoveImage(PartHeaderOffset, (u32)Header, sizeof(PartHeader)*MAX_PARTITION_NUMBER); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_GENERAL,"Move Image failed\r\n"); return XST_FAILURE; } return XST_SUCCESS; }
/** * * This function initializes the controller for the QSPI interface. * * @param None * * @return None * * @note None * ****************************************************************************/ void InitQspi(void) { #ifdef XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR u32 QspiControlReg = 0; u32 QspiDelayReg = 0; u32 Prescaler = XQSPIPS_CLK_PRESCALE_8; /* Fix for CR #664560 */ QspiControlReg = Xil_In32((XPS_QSPI_BASEADDR + XQSPIPS_CR_OFFSET)); /* Change the baud rate to DIV/8 prescaler value */ QspiControlReg &= ~XQSPIPS_CR_PRESC_MASK; QspiControlReg |= (u32) (Prescaler & XQSPIPS_CR_PRESC_MAXIMUM) << XQSPIPS_CR_PRESC_SHIFT; Xil_Out32((XPS_QSPI_BASEADDR + XQSPIPS_CR_OFFSET), QspiControlReg); /* * Set the USE loopback bit * Fix for the CR #664560 * Delay DLY1 = 0 * Delay DLY0 = 0 */ QspiDelayReg = Xil_In32((XPS_QSPI_BASEADDR + XQSPIPS_LPBK_DLY_ADJ_OFFSET)); QspiDelayReg &= FSBL_XQSPIPS_LPBK_DLY_ADJ_DLY_VALUE; Xil_Out32((XPS_QSPI_BASEADDR + XQSPIPS_LPBK_DLY_ADJ_OFFSET), QspiDelayReg); fsbl_printf(DEBUG_INFO, "QSPI initialized with Control value = 0x%x \n \r", Xil_In32(XPS_QSPI_BASEADDR + XQSPIPS_CR_OFFSET)); fsbl_printf(DEBUG_INFO, "QSPI loopback register value = 0x%x \n \r", Xil_In32(XPS_QSPI_BASEADDR + XQSPIPS_LPBK_DLY_ADJ_OFFSET)); #endif }
/** * * This function gets the length of the FSBL * * @param ImageAddress is the start address of the image * * @return FsblLength is the length of the fsbl * * @return - XST_SUCCESS if fsbl length reading is successful * - XST_FAILURE if fsbl length reading failed * * @note None * ****************************************************************************/ u32 GetFsblLength(u32 ImageAddress, u32 *FsblLength) { u32 Status; Status = MoveImage(ImageAddress + IMAGE_TOT_BYTE_LEN_OFFSET, (u32)FsblLength, 4); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_GENERAL,"Move Image failed reading FsblLength\r\n"); return XST_FAILURE; } return XST_SUCCESS; }
/****************************************************************************** * This function is the hook which will be called before the FSBL does a handoff * to the application. The user can add all the customized code required to be * executed before the handoff to this routine. * * @param None * * @return * - XST_SUCCESS to indicate success * - XST_FAILURE.to indicate failure * ****************************************************************************/ u32 FsblHookBeforeHandoff(void) { u32 Status; Status = XST_SUCCESS; /* * User logic to be added here. * Errors to be stored in the status variable and returned */ fsbl_printf(DEBUG_INFO,"In FsblHookBeforeHandoff function \r\n"); return (Status); }
/** * * This function goes to read the image headers and its signature. Image * header consists of image header table, image headers, partition * headers * * @param ImageBaseAddress is the start address of the image header * * @return Offset Partition header address of the image * * @return - XST_SUCCESS if Get Partition Header start address successful * - XST_FAILURE if Get Partition Header start address failed * * @note None * ****************************************************************************/ u32 GetImageHeaderAndSignature(u32 ImageBaseAddress, u32 *Offset) { u32 Status; u32 ImageHeaderOffset; /* * Get the start address of the partition header table */ Status = GetImageHeaderStartAddr(ImageBaseAddress, &ImageHeaderOffset); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_GENERAL, "Get Header Start Address Failed\r\n"); return XST_FAILURE; } Status = MoveImage(ImageBaseAddress+ImageHeaderOffset, (u32)Offset, TOTAL_HEADER_SIZE + RSA_SIGNATURE_SIZE); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_GENERAL,"Move Image failed\r\n"); return XST_FAILURE; } return XST_SUCCESS; }
/** * * This function Polls for the DMA done or FPGA done. * * @param none * * @return * - XST_SUCCESS if polling for DMA/FPGA done is successful * - XST_FAILURE if polling for DMA/FPGA done fails * * @note none * ****************************************************************************/ int XDcfgPollDone(u32 MaskValue, u32 MaxCount) { int Count = MaxCount; u32 IntrStsReg = 0; /* * poll for the DMA done */ IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr); while ((IntrStsReg & MaskValue) != MaskValue) { IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr); Count -=1; if (IntrStsReg & FSBL_XDCFG_IXR_ERROR_FLAGS_MASK) { fsbl_printf(DEBUG_INFO,"FATAL errors in PCAP %x\r\n", IntrStsReg); PcapDumpRegisters(); return XST_FAILURE; } if(!Count) { fsbl_printf(DEBUG_GENERAL,"PCAP transfer timed out \r\n"); return XST_FAILURE; } if (Count > (MAX_COUNT-100)) { fsbl_printf(DEBUG_GENERAL,"."); } } fsbl_printf(DEBUG_GENERAL,"\n\r"); XDcfg_IntrClear(DcfgInstPtr, IntrStsReg & MaskValue); return XST_SUCCESS; }
/** * * This function load the decrypts partition * * @param StartAddr Source start address * @param DataLength Data length in words * @param ImageLength Image length in words * * @return * - XST_SUCCESS if decryption successful * - XST_FAILURE if decryption failed * * @note None * *******************************************************************************/ u32 DecryptPartition(u32 StartAddr, u32 DataLength, u32 ImageLength) { u32 Status; u8 SecureTransferFlag =1; /* * Data transfer using PCAP */ Status = PcapDataTransfer((u32*)StartAddr, (u32*)StartAddr, ImageLength, DataLength, SecureTransferFlag); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_GENERAL,"PCAP Data Transfer failed \r\n"); return XST_FAILURE; } return XST_SUCCESS; }
/** * * This function Initializes the PCAP driver. * * @param none * * @return * - XST_SUCCESS if the pcap driver initialization is successful * - XST_FAILURE if the pcap driver initialization fails * * @note none * ****************************************************************************/ int InitPcap(void) { XDcfg_Config *ConfigPtr; int Status = XST_SUCCESS; DcfgInstPtr = &DcfgInstance; /* * Initialize the Device Configuration Interface driver. */ ConfigPtr = XDcfg_LookupConfig(DCFG_DEVICE_ID); Status = XDcfg_CfgInitialize(DcfgInstPtr, ConfigPtr, ConfigPtr->BaseAddr); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO, "XDcfg_CfgInitialize failed \n\r"); return XST_FAILURE; } return XST_SUCCESS; }
/** * * This function loads PL partition using PCAP * * @param SourceDataPtr is a pointer to where the data is read from * @param DestinationDataPtr is a pointer to where the data is written to * @param SourceLength is the length of the data to be moved in words * @param DestinationLength is the length of the data to be moved in words * @param SecureTransfer indicated the encryption key location, 0 for * non-encrypted * * @return * - XST_SUCCESS if the transfer is successful * - XST_FAILURE if the transfer fails * * @note None * ****************************************************************************/ u32 PcapLoadPartition(u32 *SourceDataPtr, u32 *DestinationDataPtr, u32 SourceLength, u32 DestinationLength, u32 SecureTransfer) { u32 Status; u32 IntrStsReg; u32 PcapTransferType = XDCFG_NON_SECURE_PCAP_WRITE; /* * Check for secure transfer */ if (SecureTransfer) { PcapTransferType = XDCFG_SECURE_PCAP_WRITE; } #ifdef FSBL_PERF XTime tXferCur = 0; FsblGetGlobalTime(&tXferCur); #endif /* * Clear the PCAP status registers */ Status = ClearPcapStatus(); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO,"PCAP_CLEAR_STATUS_FAIL \r\n"); return XST_FAILURE; } /* * For Bitstream case destination address will be 0xFFFFFFFF */ DestinationDataPtr = (u32*)XDCFG_DMA_INVALID_ADDRESS; /* * New Bitstream download initialization sequence */ FabricInit(); #ifdef XPAR_XWDTPS_0_BASEADDR /* * Prevent WDT reset */ XWdtPs_RestartWdt(&Watchdog); #endif /* * PCAP single DMA transfer setup */ SourceDataPtr = (u32*)((u32)SourceDataPtr | PCAP_LAST_TRANSFER); DestinationDataPtr = (u32*)((u32)DestinationDataPtr | PCAP_LAST_TRANSFER); /* * Transfer using Device Configuration */ Status = XDcfg_Transfer(DcfgInstPtr, (u8 *)SourceDataPtr, SourceLength, (u8 *)DestinationDataPtr, DestinationLength, PcapTransferType); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO,"Status of XDcfg_Transfer = %d \r \n",Status); return XST_FAILURE; } /* * Dump the PCAP registers */ PcapDumpRegisters(); /* * Poll for the DMA done */ Status = XDcfgPollDone(XDCFG_IXR_DMA_DONE_MASK, MAX_COUNT); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO,"PCAP_DMA_DONE_FAIL \r\n"); return XST_FAILURE; } fsbl_printf(DEBUG_INFO,"DMA Done ! \n\r"); /* * Poll for FPGA Done */ Status = XDcfgPollDone(XDCFG_IXR_PCFG_DONE_MASK, MAX_COUNT); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO,"PCAP_FPGA_DONE_FAIL\r\n"); return XST_FAILURE; } fsbl_printf(DEBUG_INFO,"FPGA Done ! \n\r"); /* * Check for errors */ IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr); if (IntrStsReg & FSBL_XDCFG_IXR_ERROR_FLAGS_MASK) { fsbl_printf(DEBUG_INFO,"Errors in PCAP \r\n"); return XST_FAILURE; } /* * For Performance measurement */ #ifdef FSBL_PERF XTime tXferEnd = 0; fsbl_printf(DEBUG_GENERAL,"Time taken is "); FsblMeasurePerfTime(tXferCur,tXferEnd); #endif return XST_SUCCESS; }
/****************************************************************************** * * This functions selects the current bank * * @param BankSel is the bank to be selected in the flash device(s). * * @return XST_SUCCESS if bank selected * XST_FAILURE if selection failed * @note None. * ******************************************************************************/ u32 SendBankSelect(u8 BankSel) { u32 Status; /* * bank select commands for Micron and Spansion are different */ if (QspiFlashMake == MICRON_ID) { /* * For micron command WREN should be sent first * except for some specific feature set */ WriteBuffer[COMMAND_OFFSET] = WRITE_ENABLE_CMD; Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, NULL, WRITE_ENABLE_CMD_SIZE); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Send the Extended address register write command * written, no receive buffer required */ WriteBuffer[COMMAND_OFFSET] = EXTADD_REG_WR; WriteBuffer[ADDRESS_1_OFFSET] = BankSel; Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, NULL, BANK_SEL_SIZE); if (Status != XST_SUCCESS) { return XST_FAILURE; } } if (QspiFlashMake == SPANSION_ID) { WriteBuffer[COMMAND_OFFSET] = BANK_REG_WR; WriteBuffer[ADDRESS_1_OFFSET] = BankSel; /* * Send the Extended address register write command * written, no receive buffer required */ Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, NULL, BANK_SEL_SIZE); if (Status != XST_SUCCESS) { return XST_FAILURE; } } /* * For testing - Read bank to verify */ if (QspiFlashMake == SPANSION_ID) { WriteBuffer[COMMAND_OFFSET] = BANK_REG_RD; WriteBuffer[ADDRESS_1_OFFSET] = 0x00; /* * Send the Extended address register write command * written, no receive buffer required */ Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, ReadBuffer, BANK_SEL_SIZE); if (Status != XST_SUCCESS) { return XST_FAILURE; } } if (QspiFlashMake == MICRON_ID) { WriteBuffer[COMMAND_OFFSET] = EXTADD_REG_RD; WriteBuffer[ADDRESS_1_OFFSET] = 0x00; /* * Send the Extended address register write command * written, no receive buffer required */ Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, ReadBuffer, BANK_SEL_SIZE); if (Status != XST_SUCCESS) { return XST_FAILURE; } } if (ReadBuffer[1] != BankSel) { fsbl_printf(DEBUG_INFO, "BankSel %d != Register Read %d\n\r", BankSel, ReadBuffer[1]); return XST_FAILURE; } return XST_SUCCESS; }
/** * * This function provides the QSPI FLASH interface for the Simplified header * functionality. * * @param SourceAddress is address in FLASH data space * @param DestinationAddress is address in DDR data space * @param LengthBytes is the length of the data in Bytes * * @return * - XST_SUCCESS if the write completes correctly * - XST_FAILURE if the write fails to completes correctly * * @note none. * ****************************************************************************/ u32 QspiAccess( u32 SourceAddress, u32 DestinationAddress, u32 LengthBytes) { u8 *BufferPtr; u32 Length = 0; u32 BankSel = 0; u32 LqspiCrReg; u32 Status; u8 BankSwitchFlag = 1; /* * Linear access check */ if (LinearBootDeviceFlag == 1) { /* * Check for non-word tail, add bytes to cover the end */ if ((LengthBytes%4) != 0){ LengthBytes += (4 - (LengthBytes & 0x00000003)); } memcpy((void*)DestinationAddress, (const void*)(SourceAddress + FlashReadBaseAddress), (size_t)LengthBytes); } else { /* * Non Linear access */ BufferPtr = (u8*)DestinationAddress; /* * Dual parallel connection actual flash is half */ if (XPAR_PS7_QSPI_0_QSPI_MODE == DUAL_PARALLEL_CONNECTION) { SourceAddress = SourceAddress/2; } while(LengthBytes > 0) { /* * Local of DATA_SIZE size used for read/write buffer */ if(LengthBytes > DATA_SIZE) { Length = DATA_SIZE; } else { Length = LengthBytes; } /* * Dual stack connection */ if (XPAR_PS7_QSPI_0_QSPI_MODE == DUAL_STACK_CONNECTION) { /* * Get the current LQSPI configuration value */ LqspiCrReg = XQspiPs_GetLqspiConfigReg(QspiInstancePtr); /* * Select lower or upper Flash based on sector address */ if (SourceAddress >= (QspiFlashSize/2)) { /* * Set selection to U_PAGE */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, LqspiCrReg | XQSPIPS_LQSPI_CR_U_PAGE_MASK); /* * Subtract first flash size when accessing second flash */ SourceAddress = SourceAddress - (QspiFlashSize/2); fsbl_printf(DEBUG_INFO, "stacked - upper CS \n\r"); /* * Assert the FLASH chip select. */ XQspiPs_SetSlaveSelect(QspiInstancePtr); } } /* * Select bank */ if ((SourceAddress >= FLASH_SIZE_16MB) && (BankSwitchFlag == 1)) { BankSel = SourceAddress/FLASH_SIZE_16MB; fsbl_printf(DEBUG_INFO, "Bank Selection %d\n\r", BankSel); Status = SendBankSelect(BankSel); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO, "Bank Selection Failed\n\r"); return XST_FAILURE; } BankSwitchFlag = 0; } /* * If data to be read spans beyond the current bank, then * calculate length in current bank else no change in length */ if (XPAR_PS7_QSPI_0_QSPI_MODE == DUAL_PARALLEL_CONNECTION) { /* * In dual parallel mode, check should be for half * the length. */ if((SourceAddress & BANKMASK) != ((SourceAddress + (Length/2)) & BANKMASK)) { Length = (SourceAddress & BANKMASK) + FLASH_SIZE_16MB - SourceAddress; /* * Above length calculated is for single flash * Length should be doubled since dual parallel */ Length = Length * 2; BankSwitchFlag = 1; } } else { if((SourceAddress & BANKMASK) != ((SourceAddress + Length) & BANKMASK)) { Length = (SourceAddress & BANKMASK) + FLASH_SIZE_16MB - SourceAddress; BankSwitchFlag = 1; } } /* * Copying the image to local buffer */ FlashRead(SourceAddress, Length); /* * Moving the data from local buffer to DDR destination address */ memcpy(BufferPtr, &ReadBuffer[DATA_OFFSET + DUMMY_SIZE], Length); /* * Updated the variables */ LengthBytes -= Length; /* * For Dual parallel connection address increment should be half */ if (XPAR_PS7_QSPI_0_QSPI_MODE == DUAL_PARALLEL_CONNECTION) { SourceAddress += Length/2; } else { SourceAddress += Length; } BufferPtr = (u8*)((u32)BufferPtr + Length); } /* * Reset Bank selection to zero */ Status = SendBankSelect(0); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO, "Bank Selection Reset Failed\n\r"); return XST_FAILURE; } if (XPAR_PS7_QSPI_0_QSPI_MODE == DUAL_STACK_CONNECTION) { /* * Reset selection to L_PAGE */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, LqspiCrReg & (~XQSPIPS_LQSPI_CR_U_PAGE_MASK)); fsbl_printf(DEBUG_INFO, "stacked - lower CS \n\r"); /* * Assert the FLASH chip select. */ XQspiPs_SetSlaveSelect(QspiInstancePtr); } } return XST_SUCCESS; }
/** * * This function initializes the controller for the QSPI interface. * * @param None * * @return None * * @note None * ****************************************************************************/ u32 InitQspi(void) { XQspiPs_Config *QspiConfig; int Status; QspiInstancePtr = &QspiInstance; /* * Set up the base address for access */ FlashReadBaseAddress = XPS_QSPI_LINEAR_BASEADDR; /* * Initialize the QSPI driver so that it's ready to use */ QspiConfig = XQspiPs_LookupConfig(QSPI_DEVICE_ID); if (NULL == QspiConfig) { return XST_FAILURE; } Status = XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig, QspiConfig->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Set Manual Chip select options and drive HOLD_B pin high. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); /* * Set the prescaler for QSPI clock */ XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8); /* * Assert the FLASH chip select. */ XQspiPs_SetSlaveSelect(QspiInstancePtr); /* * Read Flash ID and extract Manufacture and Size information */ Status = FlashReadID(); if (Status != XST_SUCCESS) { return XST_FAILURE; } if (XPAR_PS7_QSPI_0_QSPI_MODE == SINGLE_FLASH_CONNECTION) { fsbl_printf(DEBUG_INFO,"QSPI is in single flash connection\r\n"); /* * For Flash size <128Mbit controller configured in linear mode */ if (QspiFlashSize <= FLASH_SIZE_16MB) { LinearBootDeviceFlag = 1; /* * Enable linear mode */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); /* * Single linear read */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, SINGLE_QSPI_CONFIG_QUAD_READ); /* * Enable the controller */ XQspiPs_Enable(QspiInstancePtr); } else { /* * Single flash IO read */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, SINGLE_QSPI_IO_CONFIG_QUAD_READ); /* * Enable the controller */ XQspiPs_Enable(QspiInstancePtr); } } if (XPAR_PS7_QSPI_0_QSPI_MODE == DUAL_PARALLEL_CONNECTION) { fsbl_printf(DEBUG_INFO,"QSPI is in Dual Parallel connection\r\n"); /* * For Single Flash size <128Mbit controller configured in linear mode */ if (QspiFlashSize <= FLASH_SIZE_16MB) { /* * Setting linear access flag */ LinearBootDeviceFlag = 1; /* * Enable linear mode */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); /* * Dual linear read */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_CONFIG_QUAD_READ); /* * Enable the controller */ XQspiPs_Enable(QspiInstancePtr); } else { /* * Dual flash IO read */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_IO_CONFIG_QUAD_READ); /* * Enable the controller */ XQspiPs_Enable(QspiInstancePtr); } /* * Total flash size is two time of single flash size */ QspiFlashSize = 2 * QspiFlashSize; } /* * It is expected to same flash size for both chip selection */ if (XPAR_PS7_QSPI_0_QSPI_MODE == DUAL_STACK_CONNECTION) { fsbl_printf(DEBUG_INFO,"QSPI is in Dual Stack connection\r\n"); QspiFlashSize = 2 * QspiFlashSize; /* * Enable two flash memories on separate buses */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_STACK_CONFIG_READ); } return XST_SUCCESS; }
/** * * This function prints PCAP register status. * * @param none * * @return none * * @note none * ****************************************************************************/ void PcapDumpRegisters (void) { fsbl_printf(DEBUG_INFO,"PCAP register dump:\r\n"); fsbl_printf(DEBUG_INFO,"PCAP CTRL 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_CTRL_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_CTRL_OFFSET)); fsbl_printf(DEBUG_INFO,"PCAP LOCK 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_LOCK_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_LOCK_OFFSET)); fsbl_printf(DEBUG_INFO,"PCAP CONFIG 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_CFG_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_CFG_OFFSET)); fsbl_printf(DEBUG_INFO,"PCAP ISR 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_INT_STS_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_INT_STS_OFFSET)); fsbl_printf(DEBUG_INFO,"PCAP IMR 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_INT_MASK_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_INT_MASK_OFFSET)); fsbl_printf(DEBUG_INFO,"PCAP STATUS 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_STATUS_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_STATUS_OFFSET)); fsbl_printf(DEBUG_INFO,"PCAP DMA SRC ADDR 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_SRC_ADDR_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_SRC_ADDR_OFFSET)); fsbl_printf(DEBUG_INFO,"PCAP DMA DEST ADDR 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_DEST_ADDR_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_DEST_ADDR_OFFSET)); fsbl_printf(DEBUG_INFO,"PCAP DMA SRC LEN 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_SRC_LEN_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_SRC_LEN_OFFSET)); fsbl_printf(DEBUG_INFO,"PCAP DMA DEST LEN 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_DEST_LEN_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_DEST_LEN_OFFSET)); fsbl_printf(DEBUG_INFO,"PCAP ROM SHADOW CTRL 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_ROM_SHADOW_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_ROM_SHADOW_OFFSET)); fsbl_printf(DEBUG_INFO,"PCAP MBOOT 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_MULTIBOOT_ADDR_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_MULTIBOOT_ADDR_OFFSET)); fsbl_printf(DEBUG_INFO,"PCAP SW ID 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_SW_ID_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_SW_ID_OFFSET)); fsbl_printf(DEBUG_INFO,"PCAP UNLOCK 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_UNLOCK_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_UNLOCK_OFFSET)); fsbl_printf(DEBUG_INFO,"PCAP MCTRL 0x%x: 0x%08x\r\n", XPS_DEV_CFG_APB_BASEADDR + XDCFG_MCTRL_OFFSET, Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_MCTRL_OFFSET)); }
/** * * This function Clears the PCAP status registers. * * @param None * * @return * - XST_SUCCESS if the pcap status registers are cleared * - XST_FAILURE if errors are there * - XST_DEVICE_BUSY if Pcap device is busy * @note None * ****************************************************************************/ u32 ClearPcapStatus(void) { u32 StatusReg; u32 IntStatusReg; /* * Clear it all, so if Boot ROM comes back, it can proceed */ XDcfg_IntrClear(DcfgInstPtr, 0xFFFFFFFF); /* * Get PCAP Interrupt Status Register */ IntStatusReg = XDcfg_IntrGetStatus(DcfgInstPtr); if (IntStatusReg & FSBL_XDCFG_IXR_ERROR_FLAGS_MASK) { fsbl_printf(DEBUG_INFO,"FATAL errors in PCAP %x\r\n", IntStatusReg); return XST_FAILURE; } /* * Read the PCAP status register for DMA status */ StatusReg = XDcfg_GetStatusRegister(DcfgInstPtr); fsbl_printf(DEBUG_INFO,"PCAP:StatusReg = 0x%.8x\r\n", StatusReg); /* * If the queue is full, return w/ XST_DEVICE_BUSY */ if ((StatusReg & XDCFG_STATUS_DMA_CMD_Q_F_MASK) == XDCFG_STATUS_DMA_CMD_Q_F_MASK) { fsbl_printf(DEBUG_INFO,"PCAP_DEVICE_BUSY\r\n"); return XST_DEVICE_BUSY; } fsbl_printf(DEBUG_INFO,"PCAP:device ready\r\n"); /* * There are unacknowledged DMA commands outstanding */ if ((StatusReg & XDCFG_STATUS_DMA_CMD_Q_E_MASK) != XDCFG_STATUS_DMA_CMD_Q_E_MASK) { IntStatusReg = XDcfg_IntrGetStatus(DcfgInstPtr); if ((IntStatusReg & XDCFG_IXR_DMA_DONE_MASK) != XDCFG_IXR_DMA_DONE_MASK){ /* * Error state, transfer cannot occur */ fsbl_printf(DEBUG_INFO,"PCAP:IntStatus indicates error\r\n"); return XST_FAILURE; } else { /* * clear out the status */ XDcfg_IntrClear(DcfgInstPtr, XDCFG_IXR_DMA_DONE_MASK); } } if ((StatusReg & XDCFG_STATUS_DMA_DONE_CNT_MASK) != 0) { XDcfg_SetStatusRegister(DcfgInstPtr, StatusReg | XDCFG_STATUS_DMA_DONE_CNT_MASK); } fsbl_printf(DEBUG_INFO,"PCAP:Clear done\r\n"); return XST_SUCCESS; }
/** * * This function programs the Fabric for use. * * @param None * * @return None * - XST_SUCCESS if the Fabric initialization is successful * - XST_FAILURE if the Fabric initialization fails * @note None * ****************************************************************************/ void FabricInit(void) { u32 PcapReg; u32 PcapCtrlRegVal; u32 StatusReg; /* * Set Level Shifters DT618760 - PS to PL enabling */ Xil_Out32(PS_LVL_SHFTR_EN, LVL_PS_PL); fsbl_printf(DEBUG_INFO,"Level Shifter Value = 0x%x \r\n", Xil_In32(PS_LVL_SHFTR_EN)); /* * Get DEVCFG controller settings */ PcapReg = XDcfg_ReadReg(DcfgInstPtr->Config.BaseAddr, XDCFG_CTRL_OFFSET); /* * Setting PCFG_PROG_B signal to high */ XDcfg_WriteReg(DcfgInstPtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, (PcapReg | XDCFG_CTRL_PCFG_PROG_B_MASK)); /* * Check for AES source key */ PcapCtrlRegVal = XDcfg_GetControlRegister(DcfgInstPtr); if (PcapCtrlRegVal & XDCFG_CTRL_PCFG_AES_FUSE_MASK) { /* * 5msec delay */ usleep(5000); } /* * Setting PCFG_PROG_B signal to low */ XDcfg_WriteReg(DcfgInstPtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, (PcapReg & ~XDCFG_CTRL_PCFG_PROG_B_MASK)); /* * Check for AES source key */ if (PcapCtrlRegVal & XDCFG_CTRL_PCFG_AES_FUSE_MASK) { /* * 5msec delay */ usleep(5000); } /* * Polling the PCAP_INIT status for Reset */ while(XDcfg_GetStatusRegister(DcfgInstPtr) & XDCFG_STATUS_PCFG_INIT_MASK); /* * Setting PCFG_PROG_B signal to high */ XDcfg_WriteReg(DcfgInstPtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, (PcapReg | XDCFG_CTRL_PCFG_PROG_B_MASK)); /* * Polling the PCAP_INIT status for Set */ while(!(XDcfg_GetStatusRegister(DcfgInstPtr) & XDCFG_STATUS_PCFG_INIT_MASK)); /* * Get Device configuration status */ StatusReg = XDcfg_GetStatusRegister(DcfgInstPtr); fsbl_printf(DEBUG_INFO,"Devcfg Status register = 0x%x \r\n",StatusReg); fsbl_printf(DEBUG_INFO,"PCAP:Fabric is Initialized done\r\n"); }