/** * * This function sets the number of lanes to be used by DisplayPort TX Subsystem * core. * * @param InstancePtr is a pointer to the XDpTxSs instance. * @param LaneCount is the number of lanes to be used. * - 1 = XDPTXSS_LANE_COUNT_SET_1 * - 2 = XDPTXSS_LANE_COUNT_SET_2 * - 4 = XDPTXSS_LANE_COUNT_SET_4 * @return * - XST_SUCCESS if setting the new lane count was successful. * - XST_FAILURE otherwise. * * @note Maximum supported lane count is used if given lane count is * greater than the maximum supported lane count. * ******************************************************************************/ u32 XDpTxSs_SetLaneCount(XDpTxSs *InstancePtr, u8 LaneCount) { u32 Status; /* Verify arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid((LaneCount == XDPTXSS_LANE_COUNT_SET_1) || (LaneCount == XDPTXSS_LANE_COUNT_SET_2) || (LaneCount == XDPTXSS_LANE_COUNT_SET_4)); /* Check for maximum supported lane count */ if (LaneCount > InstancePtr->DpPtr->Config.MaxLaneCount) { xdbg_printf(XDBG_DEBUG_GENERAL,"SS info: This lane count is " "not supported by Source/Sink.\n\rMax Supported lane " "count is 0x%x.\n\rSetting maximum supported lane " "count.\n\r", InstancePtr->DpPtr->Config.MaxLaneCount); LaneCount = InstancePtr->DpPtr->Config.MaxLaneCount; } /* Set lane count */ Status = XDp_TxSetLaneCount(InstancePtr->DpPtr, LaneCount); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR: Setting lane count " "failed.\n\r"); Status = XST_FAILURE; } return Status; }
/** * * This function sets the data rate to be used by the DisplayPort TX Subsystem * core. * * @param InstancePtr is a pointer to the XDpTxSs instance. * @param LinkRate is the rate at which link needs to be driven. * - XDPTXSS_LINK_BW_SET_162GBPS = 0x06(for a 1.62 Gbps data rate) * - XDPTXSS_LINK_BW_SET_270GBPS = 0x0A(for a 2.70 Gbps data rate) * - XDPTXSS_LINK_BW_SET_540GBPS = 0x14(for a 5.40 Gbps data rate) * * @return * - XST_SUCCESS if setting the new lane rate was successful. * - XST_FAILURE otherwise. * * @note Maximum supported link rate is used if given link rate is * greater than the maximum supported link rate. * ******************************************************************************/ u32 XDpTxSs_SetLinkRate(XDpTxSs *InstancePtr, u8 LinkRate) { u32 Status; /* Verify arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid((LinkRate == XDPTXSS_LINK_BW_SET_162GBPS) || (LinkRate == XDPTXSS_LINK_BW_SET_270GBPS) || (LinkRate == XDPTXSS_LINK_BW_SET_540GBPS)); /* Check for maximum supported link rate */ if (LinkRate > InstancePtr->DpPtr->Config.MaxLinkRate) { xdbg_printf(XDBG_DEBUG_GENERAL,"SS info: This link rate is " "not supported by Source/Sink.\n\rMax Supported link " "rate is 0x%x.\n\rSetting maximum supported link " "rate.\n\r", InstancePtr->DpPtr->Config.MaxLinkRate); LinkRate = InstancePtr->DpPtr->Config.MaxLinkRate; } /* Set link rate */ Status = XDp_TxSetLinkRate(InstancePtr->DpPtr, LinkRate); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR: Setting link rate " "failed.\n\r"); Status = XST_FAILURE; } return Status; }
/* * Check for transfer completion. * * If the DMA engine has errors or any of the finished BDs has error bit set, * then the example should fail. * * @param InstancePtr is pointer to the XAxiCdma instance. * * @return Number of Bds that have been completed by hardware. * * @note None * ******************************************************************************/ static int CheckCompletion(XAxiCdma *InstancePtr) { int BdCount; XAxiCdma_Bd *BdPtr; XAxiCdma_Bd *BdCurPtr; int Status; int Index; /* Check whether the hardware has encountered any problems. * In some error cases, the DMA engine may not able to update the * BD that has caused the problem. */ if (XAxiCdma_GetError(InstancePtr) != 0x0) { xdbg_printf(XDBG_DEBUG_ERROR, "Transfer error %x\r\n", (unsigned int)XAxiCdma_GetError(InstancePtr)); Error = 1; return 0; } /* Get all processed BDs from hardware */ BdCount = XAxiCdma_BdRingFromHw(InstancePtr, XAXICDMA_ALL_BDS, &BdPtr); /* Check finished BDs then release them */ if(BdCount > 0) { BdCurPtr = BdPtr; for (Index = 0; Index < BdCount; Index++) { /* If the completed BD has error bit set, * then the example fails */ if (XAxiCdma_BdGetSts(BdCurPtr) & XAXICDMA_BD_STS_ALL_ERR_MASK) { Error = 1; return 0; } BdCurPtr = XAxiCdma_BdRingNext(InstancePtr, BdCurPtr); } /* Release the BDs so later submission can use them */ Status = XAxiCdma_BdRingFree(InstancePtr, BdCount, BdPtr); if(Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_ERROR, "Error free BD %x\r\n", Status); Error = 1; return 0; } Done += BdCount; } return Done; }
/** * * This function sets up the DMA engine to be ready for scatter gather transfer * * @param InstancePtr is pointer to the XAxiCdma instance. * * @return * - XST_SUCCESS if the setup is successful * - XST_FAILURE if error occurs * * @note None * ******************************************************************************/ static int SetupTransfer(XAxiCdma * InstancePtr) { int Status; XAxiCdma_Bd BdTemplate; int BdCount; u8 *SrcBufferPtr; int Index; /* Disable all interrupts */ XAxiCdma_IntrDisable(InstancePtr, XAXICDMA_XR_IRQ_ALL_MASK); /* Setup BD ring */ BdCount = XAxiCdma_BdRingCntCalc(XAXICDMA_BD_MINIMUM_ALIGNMENT, BD_SPACE_HIGH - BD_SPACE_BASE + 1, (u32)BD_SPACE_BASE); Status = XAxiCdma_BdRingCreate(InstancePtr, BD_SPACE_BASE, BD_SPACE_BASE, XAXICDMA_BD_MINIMUM_ALIGNMENT, BdCount); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_ERROR, "Create BD ring failed %d\r\n", Status); return XST_FAILURE; } /* * Setup a BD template to copy to every BD. */ XAxiCdma_BdClear(&BdTemplate); Status = XAxiCdma_BdRingClone(InstancePtr, &BdTemplate); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_ERROR, "Clone BD ring failed %d\r\n", Status); return XST_FAILURE; } /* Initialize receive buffer to 0's and transmit buffer with pattern */ memset((void *)ReceiveBufferPtr, 0, MAX_PKT_LEN * NUMBER_OF_BDS_TO_TRANSFER); SrcBufferPtr = (u8 *)TransmitBufferPtr; for(Index = 0; Index < MAX_PKT_LEN * NUMBER_OF_BDS_TO_TRANSFER; Index++) { SrcBufferPtr[Index] = Index & 0xFF; } /* Flush the SrcBuffer before the DMA transfer, in case the Data Cache * is enabled */ Xil_DCacheFlushRange((UINTPTR)TransmitBufferPtr, MAX_PKT_LEN * NUMBER_OF_BDS_TO_TRANSFER); #ifdef __aarch64__ Xil_DCacheFlushRange((UINTPTR)ReceiveBufferPtr, MAX_PKT_LEN * NUMBER_OF_BDS_TO_TRANSFER); #endif return XST_SUCCESS; }
/** * Configure buffer addresses for one DMA channel * * The buffer addresses are physical addresses. * Access to 32 Frame Buffer Addresses in direct mode is done through * XAxiVdma_ChannelHiFrmAddrEnable/Disable Functions. * 0 - Access Bank0 Registers (0x5C - 0x98) * 1 - Access Bank1 Registers (0x5C - 0x98) * * @param Channel is the pointer to the channel to work on * @param BufferAddrSet is the set of addresses for the transfers * @param NumFrames is the number of frames to set the address * * @return * - XST_SUCCESS if successful * - XST_FAILURE if channel has not being initialized * - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used * - XST_INVAID_PARAM if buffer address not valid, for example, unaligned * address with no DRE built in the hardware * *****************************************************************************/ int XAxiVdma_ChannelSetBufferAddr(XAxiVdma_Channel *Channel, u32 *BufferAddrSet, int NumFrames) { int i; u32 WordLenBits; int HiFrmAddr = 0; int FrmBound = (XAXIVDMA_MAX_FRAMESTORE)/2 - 1; int Loop16 = 0; if (!Channel->IsValid) { xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n"); return XST_FAILURE; } WordLenBits = (u32)(Channel->WordLength - 1); /* If hardware has no DRE, then buffer addresses must * be word-aligned */ for (i = 0; i < NumFrames; i++) { if (!Channel->HasDRE) { if (BufferAddrSet[i] & WordLenBits) { xdbg_printf(XDBG_DEBUG_ERROR, "Unaligned address %d: %x without DRE\r\n", i, BufferAddrSet[i]); return XST_INVALID_PARAM; } } } for (i = 0; i < NumFrames; i++, Loop16++) { XAxiVdma_Bd *BdPtr = (XAxiVdma_Bd *)(Channel->HeadBdAddr + i * sizeof(XAxiVdma_Bd)); if (Channel->HasSG) { XAxiVdma_BdSetAddr(BdPtr, BufferAddrSet[i]); } else { if ((i > FrmBound) && !HiFrmAddr) { XAxiVdma_ChannelHiFrmAddrEnable(Channel); HiFrmAddr = 1; Loop16 = 0; } XAxiVdma_WriteReg(Channel->StartAddrBase, XAXIVDMA_START_ADDR_OFFSET + Loop16 * XAXIVDMA_START_ADDR_LEN, BufferAddrSet[i]); if ((NumFrames > FrmBound) && (i == (NumFrames - 1))) XAxiVdma_ChannelHiFrmAddrDisable(Channel); } } return XST_SUCCESS; }
/* * This function does a multi-BD scatter gather transfer * * @param InstancePtr points to the DMA engine instance * * @return * - XST_SUCCESS if transfer finishes successfully * - XST_FAILURE if transfer has errors * * @note None. * ******************************************************************************/ static int DoSgTransfer(XAxiCdma * InstancePtr) { int Status; u8 *SrcPtr; u8 *DstPtr; SrcPtr = (u8 *)TransmitBufferPtr; DstPtr = (u8 *)ReceiveBufferPtr; /* Setup the BD ring */ Status = SetupSgTransfer(InstancePtr); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_ERROR, "Setup BD ring failed with %d\r\n", Status); return XST_FAILURE; } /* Submit BDs to the hardware */ Status = SubmitSgTransfer(InstancePtr); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_ERROR, "Submit transfer failed with %d\r\n", Status); return XST_FAILURE; } /* Wait until the DMA transfer is done */ while ((Done < NUMBER_OF_BDS_TO_TRANSFER) && !Error) { /* Wait */ } if(Error) { xdbg_printf(XDBG_DEBUG_ERROR, "SG transfer has error %x\r\n", (unsigned int)XAxiCdma_GetError(InstancePtr)); return XST_FAILURE; } /* Transfer completes successfully, check data */ Status = CheckData(SrcPtr, DstPtr, MAX_PKT_LEN * NUMBER_OF_BDS_TO_TRANSFER); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_ERROR, "Check data failed for sg " "transfer\r\n"); return XST_FAILURE; } /* Transfer finishes successfully */ return XST_SUCCESS; }
/** * * This function sets up the TX channel of a DMA engine to be ready for packet * transmission * * @param AxiDmaInstPtr is the instance pointer to the DMA engine. * * @return XST_SUCCESS if the setup is successful, XST_FAILURE otherwise. * * @note None. * ******************************************************************************/ static int TxSetup(XAxiDma * AxiDmaInstPtr) { XAxiDma_BdRing *TxRingPtr; XAxiDma_Bd BdTemplate; int Delay = 0; int Coalesce = 1; int Status; u32 BdCount; TxRingPtr = XAxiDma_GetTxRing(&AxiDma); /* Disable all TX interrupts before TxBD space setup */ XAxiDma_BdRingIntDisable(TxRingPtr, XAXIDMA_IRQ_ALL_MASK); /* Set TX delay and coalesce */ XAxiDma_BdRingSetCoalesce(TxRingPtr, Coalesce, Delay); /* Setup TxBD space */ BdCount = XAxiDma_BdRingCntCalc(XAXIDMA_BD_MINIMUM_ALIGNMENT, TX_BD_SPACE_HIGH - TX_BD_SPACE_BASE + 1); Status = XAxiDma_BdRingCreate(TxRingPtr, TX_BD_SPACE_BASE, TX_BD_SPACE_BASE, XAXIDMA_BD_MINIMUM_ALIGNMENT, BdCount); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_ERROR, "failed create BD ring in txsetup\r\n"); return XST_FAILURE; } /* * We create an all-zero BD as the template. */ XAxiDma_BdClear(&BdTemplate); Status = XAxiDma_BdRingClone(TxRingPtr, &BdTemplate); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_ERROR, "failed bdring clone in txsetup %d\r\n", Status); return XST_FAILURE; } /* Start the TX channel */ Status = XAxiDma_BdRingStart(TxRingPtr); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_ERROR, "failed start bdring txsetup %d\r\n", Status); return XST_FAILURE; } return XST_SUCCESS; }
/* * * This function initializes a rxMapleBus instance/driver. * All members of the rxMapleBus instance structure are initialized. * * @param InstancePtr is a pointer to the rxMapleBus instance. * @param ConfigPtr points to the rxMapleBus device configuration structure. * @param EffectiveAddr is the device base address in the virtual memory * address space. If the address translation is not used then the * physical address should be passed. Unexpected errors may occur * if the address mapping is changed after this function is invoked. * * @return XST_SUCCESS always. * * @note None. * ******************************************************************************/ int rxMapleBus_CfgInitialize(rxMapleBus *InstancePtr, rxMapleBus_Config *ConfigPtr, u32 EffectiveAddr) { u32 reg; u32 timeout; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(ConfigPtr != NULL); /* * Set some default values for instance data, don't indicate the device * is ready to use until everything has been initialized successfully. */ InstancePtr->IsReady = 0; InstancePtr->MapleBusConfig.BaseAddr = EffectiveAddr; InstancePtr->MapleBusConfig.DeviceId = ConfigPtr->DeviceId; //InstancePtr->Handler = StubHandler; //TODO: We need to wait until TX and RX are 0 before we continue rxMapleBus_WriteReg(InstancePtr->MapleBusConfig.BaseAddr, RXMAPLEBUS_REG0_OFFSET, RXMAPLEBUS_RESET_TX | RXMAPLEBUS_RESET_RX); for (timeout = 10; timeout > 0; --timeout) { reg = rxMapleBus_ReadReg(InstancePtr->MapleBusConfig.BaseAddr, RXMAPLEBUS_REG1_OFFSET); if (!reg) { break; } } if (!timeout) { xdbg_printf(XDBG_DEBUG_ERROR, "rxMapleBus failed reset in initialize\r\n"); /* Need system hard reset to recover */ return XST_FAILURE; } rxMapleBus_WriteReg(InstancePtr->MapleBusConfig.BaseAddr, RXMAPLEBUS_REG0_OFFSET, RXMAPLEBUS_ENABLE_LOOPBACK); reg = rxMapleBus_ReadReg(InstancePtr->MapleBusConfig.BaseAddr, RXMAPLEBUS_REG0_OFFSET); if (reg != RXMAPLEBUS_ENABLE_LOOPBACK) { xdbg_printf(XDBG_DEBUG_ERROR, "rxMapleBus failed setup in initialize\r\n"); /* Hardware error */ return XST_FAILURE; } /* * Indicate the component is now ready to use. */ InstancePtr->IsReady = XIL_COMPONENT_IS_READY; return XST_SUCCESS; }
/** * * Default Prefetch abort handler which prints prefetch fault status register through * which information about instruction prefetch fault can be acquired * * @param None * * @return None. * * @note None. * ****************************************************************************/ void Xil_PrefetchAbortHandler(void *CallBackRef){ u32 FaultStatus; #ifdef __GNUC__ FaultStatus = mfcp(XREG_CP15_INST_FAULT_STATUS); #elif defined (__ICCARM__) mfcp(XREG_CP15_INST_FAULT_STATUS,FaultStatus); #else { volatile register u32 Reg __asm(XREG_CP15_INST_FAULT_STATUS); FaultStatus = Reg; } #endif xdbg_printf(XDBG_DEBUG_GENERAL, "Prefetch abort with Instruction Fault Status Register %x\n",FaultStatus); xdbg_printf(XDBG_DEBUG_GENERAL, "Address of Instrcution causing Prefetch abort %x\n",PrefetchAbortAddr); while(1) { ; } }
/** * @brief Update the MPU configuration for the requested region number in * the global MPU configuration table. * * @param reg_num: The requested region number to be updated information for. * @param address: 32 bit address for start of the region. * @param size: Requested size of the region. * @param attrib: Attribute for the corresponding region. * @return XST_FAILURE: When the requested region number if 16 or more. * XST_SUCCESS: When the MPU configuration table is updated. * * ******************************************************************************/ u32 Xil_UpdateMPUConfig(u32 reg_num, INTPTR address, u32 size, u32 attrib) { u32 ReturnVal = XST_SUCCESS; u32 Tempsize = size; u32 Index; if (reg_num >= MAX_POSSIBLE_MPU_REGS) { xdbg_printf(DEBUG, "Invalid region number\r\n"); ReturnVal = XST_FAILURE; goto exit; } if (size & REGION_EN) { Mpu_Config[reg_num].RegionStatus = MPU_REG_ENABLED; Mpu_Config[reg_num].BaseAddress = address; Tempsize &= (~REGION_EN); Tempsize >>= 1; /* Lookup the size. */ for (Index = 0; Index < sizeof region_size / sizeof region_size[0]; Index++) { if (Tempsize <= region_size[Index].encoding) { Mpu_Config[reg_num].Size = region_size[Index].size; break; } } Mpu_Config[reg_num].Attribute = attrib; } else {
/** * * Default undefined exception handler which prints address of the undefined * instruction if debug prints are enabled * * @param None * * @return None. * * @note None. * ****************************************************************************/ void Xil_UndefinedExceptionHandler(void *CallBackRef){ xdbg_printf(XDBG_DEBUG_GENERAL, "Address of the undefined instruction %x\n",UndefinedExceptionAddr); while(1) { ; } }
/** * * Main function * * This function is the main entry of the tests on DMA core. It sets up * DMA engine to be ready to receive and send packets, then a packet is * transmitted and will be verified after it is received via the loopback on the * Local Link interface of the DMA. * * @return 0 if tests pass, 1 otherwise. * * @note None. * ******************************************************************************/ int main(void) { int Status; XAxiDma_Config *Config; #if defined(XPAR_UARTNS550_0_BASEADDR) Uart550_Setup(); #endif xil_printf("\r\n--- Entering main() --- \r\n"); Config = XAxiDma_LookupConfig(DMA_DEV_ID); if (!Config) { xdbg_printf(XDBG_DEBUG_ERROR, "No config found for %d\r\n", DMA_DEV_ID); return 1; } /* Initialize DMA engine */ Status = XAxiDma_CfgInitialize(&AxiDma, Config); if (Status != XST_SUCCESS) { xil_printf("Initialization failed %d\r\n", Status); return 1; } Status = TxSetup(&AxiDma); if (Status != XST_SUCCESS) { return 1; } Status = RxSetup(&AxiDma); if (Status != XST_SUCCESS) { return 1; } /* Send a packet */ Status = SendPacket(&AxiDma); if (Status != XST_SUCCESS) { return 1; } /* Check DMA transfer result */ Status = CheckDmaResult(&AxiDma); xil_printf("Test %s\r\n", (Status == XST_SUCCESS)? "passed":"failed"); xil_printf("--- Exiting main() --- \r\n"); if (Status != XST_SUCCESS) { return XST_FAILURE; } return 0; }
/** * Start a transfer * * This function setup the DMA engine and start the engine to do the transfer. * * @param Channel is the pointer to the channel to work on * @param ChannelCfgPtr is the pointer to the setup structure * * @return * - XST_SUCCESS for a successful submission * - XST_FAILURE if channel has not being initialized * - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used * - XST_INVAID_PARAM if parameters in config structure not valid * *****************************************************************************/ int XAxiVdma_ChannelStartTransfer(XAxiVdma_Channel *Channel, XAxiVdma_ChannelSetup *ChannelCfgPtr) { int Status; if (!Channel->IsValid) { xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n"); return XST_FAILURE; } if (Channel->HasSG && XAxiVdma_ChannelIsBusy(Channel)) { xdbg_printf(XDBG_DEBUG_ERROR, "Channel is busy, cannot setup engine for transfer\r\n"); return XST_DEVICE_BUSY; } Status = XAxiVdma_ChannelConfig(Channel, ChannelCfgPtr); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_ERROR, "Channel config failed %d\r\n", Status); return Status; } Status = XAxiVdma_ChannelSetBufferAddr(Channel, ChannelCfgPtr->FrameStoreStartAddr, Channel->AllCnt); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_ERROR, "Channel setup buffer addr failed %d\r\n", Status); return Status; } Status = XAxiVdma_ChannelStart(Channel); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_ERROR, "Channel start failed %d\r\n", Status); return Status; } return XST_SUCCESS; }
/** * * This function performs self test on DisplayPort Receiver Subsystem * sub-cores. * * @param InstancePtr is a pointer to the XDpRxSs core instance. * * @return * - XST_SUCCESS if self test passed. * - Otherwise, prints self test failed message. * * @note None. * ******************************************************************************/ u32 XDpRxSs_SelfTest(XDpRxSs *InstancePtr) { u32 Status; /* Verify argument. */ Xil_AssertNonvoid(InstancePtr != NULL); /* Check DP availability */ if (InstancePtr->DpPtr) { Status = XDp_SelfTest(InstancePtr->DpPtr); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_GENERAL,"ERR::DP Self test " "failed\n\r"); } } #if (XPAR_XHDCP_NUM_INSTANCES > 0) if ((InstancePtr->Hdcp1xPtr) && (InstancePtr->Config.HdcpEnable)) { Status = XHdcp1x_SelfTest(InstancePtr->Hdcp1xPtr); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_GENERAL,"ERR::HDCP Self test " "failed\r\n"); } } if (InstancePtr->TmrCtrPtr) { Status = XTmrCtr_SelfTest(InstancePtr->TmrCtrPtr, 0); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_GENERAL,"ERR::Timer Counter " "Self test failed\r\n"); } } #endif /* Check IIC availability */ if (InstancePtr->IicPtr) { Status = (u32)XIic_SelfTest(InstancePtr->IicPtr); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_GENERAL,"ERR::IIC Self test " "failed\n\r"); } } return XST_SUCCESS; }
/** * * This function sets transport mode (SST/MST). * * @param InstancePtr is a pointer to the XDpTxSs core instance. * @param Mode specifies the type of transport mode that will be set. * - 0 = Single-Stream Transport mode, * - 1 = Multi-Stream Transport mode, * * @return * - XST_SUCCESS, if transport mode is set successfully to either * MST or SST when RX device is MST and mode is less than or * equal to supported mode. * - XST_FAILURE, if setting to already set mode or mode is * greater than supported mode. * * @note Transport mode is set to either MST or SST when system is MST * and RX device is MST capable. * ******************************************************************************/ u32 XDpTxSs_SetTransportMode(XDpTxSs *InstancePtr, u8 Mode) { u32 Status; /* Verify arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid((Mode == 0x0) || (Mode == 0x1)); /* Check for MST */ if (Mode == InstancePtr->UsrOpt.MstSupport) { xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:Subsystem is " "already in %s mode \n\r",Mode?"MST":"SST"); Status = XST_FAILURE; } /* Check for mode less than supported mode */ else if (Mode <= InstancePtr->Config.MstSupport) { /* Check RX device is MST capable */ Status = XDp_TxMstCapable(InstancePtr->DpPtr); if ((Status != XST_SUCCESS) && (Mode > InstancePtr->UsrOpt.MstSupport)) { xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO: RX device " "is SST capable. No change in mode.\n\r"); Status = XST_FAILURE; } else if ((Status == XST_SUCCESS) && ((Mode < InstancePtr->UsrOpt.MstSupport) || (Mode > InstancePtr->UsrOpt.MstSupport))) { xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO::setting " "Subsystem mode from %s to %s mode \n\r", (InstancePtr->UsrOpt.MstSupport?"MST":"SST"), (Mode?"MST":"SST")); InstancePtr->UsrOpt.MstSupport = Mode; Status = XST_SUCCESS; } } /* Everything else */ else { xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR::Subsystem does not " "support %s \n\r", Mode?"MST":"SST"); Status = XST_FAILURE; } return Status; }
void Xil_DataAbortHandler(void *CallBackRef){ u32 FaultStatus; xdbg_printf(XDBG_DEBUG_ERROR, "Data abort \n"); #ifdef __GNUC__ FaultStatus = mfcp(XREG_CP15_DATA_FAULT_STATUS); #elif defined (__ICCARM__) mfcp(XREG_CP15_DATA_FAULT_STATUS,FaultStatus); #else { volatile register u32 Reg __asm(XREG_CP15_DATA_FAULT_STATUS); FaultStatus = Reg; } #endif xdbg_printf(XDBG_DEBUG_GENERAL, "Data abort with Data Fault Status Register %x\n",FaultStatus); xdbg_printf(XDBG_DEBUG_GENERAL, "Address of Instrcution causing Data abort %x\n",DataAbortAddr); while(1) { ; } }
/** * Set the frame counter and delay counter for one channel * * @param Channel is the pointer to the channel to work on * @param FrmCnt is the frame counter value to be set * @param DlyCnt is the delay counter value to be set * * @return * - XST_SUCCESS if setup finishes successfully * - XST_FAILURE if channel is not initialized * - XST_INVALID_PARAM if the configuration structure has invalid values * - XST_NO_FEATURE if Frame Counter or Delay Counter is disabled * *****************************************************************************/ int XAxiVdma_ChannelSetFrmCnt(XAxiVdma_Channel *Channel, u8 FrmCnt, u8 DlyCnt) { u32 CrBits; if (!Channel->IsValid) { xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n"); return XST_FAILURE; } if (!FrmCnt) { xdbg_printf(XDBG_DEBUG_ERROR, "Frame counter value must be non-zero\r\n"); return XST_INVALID_PARAM; } CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) & ~(XAXIVDMA_DELAY_MASK | XAXIVDMA_FRMCNT_MASK); if (Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_FRM_CNTR) { CrBits |= (FrmCnt << XAXIVDMA_FRMCNT_SHIFT); } else { xdbg_printf(XDBG_DEBUG_ERROR, "Channel Frame counter is disabled\r\n"); return XST_NO_FEATURE; } if (Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_DLY_CNTR) { CrBits |= (DlyCnt << XAXIVDMA_DELAY_SHIFT); } else { xdbg_printf(XDBG_DEBUG_ERROR, "Channel Delay counter is disabled\r\n"); return XST_NO_FEATURE; } XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET, CrBits); return XST_SUCCESS; }
/** * * Default Prefetch abort handler which prints prefetch fault status register through * which information about instruction prefetch fault can be acquired * * @param None * * @return None. * * @note None. * ****************************************************************************/ void Xil_PrefetchAbortHandler(void *CallBackRef){ u32 FaultStatus; #ifdef __GNUC__ FaultStatus = mfcp(XREG_CP15_INST_FAULT_STATUS); #elif defined (__ICCARM__) mfcp(XREG_CP15_INST_FAULT_STATUS,FaultStatus); #else { volatile register unsigned int Reg __asm(XREG_CP15_INST_FAULT_STATUS); FaultStatus = Reg; } #endif xdbg_printf(XDBG_DEBUG_ERROR, "Prefetch abort with Instruction Fault Status Register %x\n",FaultStatus); while(1); }
/** * Set the APP word at the specified APP word offset for a BD. * * @param BdPtr is the BD to operate on. * @param Offset is the offset inside the APP word, it is valid from * 0 to 4 * @param Word is the value to set * * @returns * - XST_SUCCESS for success * - XST_INVALID_PARAM under following error conditions: * 1) StsCntrlStrm is not built in hardware * 2) Offset is not in valid range * * @note * If the hardware build has C_SG_USE_STSAPP_LENGTH set to 1, * then the last APP word, XAXIDMA_LAST_APPWORD, must have * non-zero value when AND with 0x7FFFFF. Not doing so will cause * the hardware to stall. * This function can be used only when DMA is in SG mode * *****************************************************************************/ int XAxiDma_BdSetAppWord(XAxiDma_Bd* BdPtr, int Offset, u32 Word) { if (XAxiDma_BdRead(BdPtr, XAXIDMA_BD_HAS_STSCNTRL_OFFSET) == 0) { xdbg_printf(XDBG_DEBUG_ERROR, "BdRingSetAppWord: no sts cntrl" "stream in hardware build, cannot set app word\r\n"); return XST_INVALID_PARAM; } if ((Offset < 0) || (Offset > XAXIDMA_LAST_APPWORD)) { xdbg_printf(XDBG_DEBUG_ERROR, "BdRingSetAppWord: invalid" "offset %d",Offset); return XST_INVALID_PARAM; } XAxiDma_BdWrite(BdPtr, XAXIDMA_BD_USR0_OFFSET + Offset * 4, Word); return XST_SUCCESS; }
/* * Callback function for the scatter gather transfer. * It is called by the driver's interrupt handler. * * @param CallBackRef is the reference pointer registered through * transfer submission. In this case, it is the pointer to the * driver instance * @param IrqMask is the interrupt mask the driver interrupt handler * passes to the callback function. * @param NumBdPtr is the pointer to number of BDs this handler handles * * @return None * * @note None. * ******************************************************************************/ static void Example_SgCallBack(void *CallBackRef, u32 IrqMask, int *NumBdPtr) { XAxiCdma *InstancePtr; int BdCount; XAxiCdma_Bd *BdPtr; int Status; int Tmp; InstancePtr = (XAxiCdma *)CallBackRef; Tmp = *NumBdPtr; /* If error interrupt happened, the driver interrupt handler * has already reset the hardware */ if (IrqMask & XAXICDMA_XR_IRQ_ERROR_MASK) { Error = 1; } if (IrqMask & XAXICDMA_XR_IRQ_IOC_MASK) { /* Get all processed BDs from hardware */ BdCount = XAxiCdma_BdRingFromHw(InstancePtr, Tmp, &BdPtr); /* Release finished BDs * * It is ok if BdCount is zero as a previous callback may * have ripen all finished BDs */ if(BdCount > 0) { Status = XAxiCdma_BdRingFree(InstancePtr, BdCount, BdPtr); if(Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_ERROR, "Error free BD %x\r\n", Status); Error = 1; return; } Done += BdCount; *NumBdPtr = Tmp - BdCount; } } return; }
/** * This function configures KeyHole Write/Read Feature * * @param InstancePtr is the driver instance we are working on * * @param Direction is WRITE/READ * @Select Select is the option to enable (TRUE) or disable (FALSE). * * @return - XST_SUCCESS for success * - XST_DEVICE_BUSY when transfer is in progress * - XST_NO_FEATURE when not configured with feature * * @note None. * *****************************************************************************/ int XAxiCdma_SelectKeyHole(XAxiCdma *InstancePtr, u32 Direction, u32 Select) { u32 Value; if (XAxiCdma_IsBusy(InstancePtr)) { xdbg_printf(XDBG_DEBUG_ERROR, "KeyHole: Transfer is in Progress\n\r"); return XST_DEVICE_BUSY; } Value = XAxiCdma_ReadReg(InstancePtr->BaseAddr, XAXICDMA_CR_OFFSET); if (Select) { if (XPAR_AXICDMA_0_M_AXI_MAX_BURST_LEN == 16) { if (Direction == XAXICDMA_KEYHOLE_WRITE) Value |= XAXICDMA_CR_KHOLE_WR_MASK; else Value |= XAXICDMA_CR_KHOLE_RD_MASK; } else { xdbg_printf(XDBG_DEBUG_ERROR, "KeyHole: Max Burst length should be 16\n\r"); return XST_NO_FEATURE; } } else { if (Direction == XAXICDMA_KEYHOLE_WRITE) Value &= ~XAXICDMA_CR_KHOLE_WR_MASK; else Value &= ~XAXICDMA_CR_KHOLE_RD_MASK; } XAxiCdma_WriteReg(InstancePtr->BaseAddr, XAXICDMA_CR_OFFSET, Value); return XST_SUCCESS; }
/** * Interrupt handler for the write channel * * @param InstancePtr is the pointer to the DMA engine to work on * * @return * None * * @note * If the channel is invalid, then no interrupt handling *****************************************************************************/ void XAxiVdma_WriteIntrHandler(void * InstancePtr) { XAxiVdma *DmaPtr; XAxiVdma_Channel *Channel; XAxiVdma_ChannelCallBack *CallBack; u32 PendingIntr; DmaPtr = (XAxiVdma *)InstancePtr; Channel = XAxiVdma_GetChannel(DmaPtr, XAXIVDMA_WRITE); if (!Channel->IsValid) { xdbg_printf(XDBG_DEBUG_ERROR, "Write channel is invalid, no intr handling\n\r"); return; } PendingIntr = XAxiVdma_ChannelGetPendingIntr(Channel); PendingIntr &= XAxiVdma_ChannelGetEnabledIntr(Channel); XAxiVdma_ChannelIntrClear(Channel, PendingIntr); CallBack = &(DmaPtr->WriteCallBack); if (!CallBack->CompletionCallBack) { return; } if (!PendingIntr || (PendingIntr & XAXIVDMA_IXR_ERROR_MASK)) { CallBack->ErrCallBack(CallBack->ErrRef, PendingIntr & XAXIVDMA_IXR_ERROR_MASK); /* The channel's error callback should reset the channel * There is no need to handle other interrupts */ return; } if (PendingIntr & XAXIVDMA_IXR_COMPLETION_MASK) { CallBack->CompletionCallBack(CallBack->CompletionRef, PendingIntr); } return; }
/** * Setup BD addresses to a different memory region * * In some systems, it is convenient to put BDs into a certain region of the * memory. This function enables that. * * @param Channel is the pointer to the channel to work on * @param BdAddrPhys is the physical starting address for BDs * @param BdAddrVirt is the Virtual starting address for BDs. For systems that * do not use MMU, then virtual address is the same as physical address * * @return * - XST_SUCCESS for a successful setup * - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used * * @notes * We assume that the memory region starting from BdAddrPhys is large enough * to hold all the BDs. * *****************************************************************************/ int XAxiVdma_ChannelSetBdAddrs(XAxiVdma_Channel *Channel, UINTPTR BdAddrPhys, UINTPTR BdAddrVirt) { int NumFrames = Channel->AllCnt; int i; UINTPTR NextPhys = BdAddrPhys; UINTPTR CurrVirt = BdAddrVirt; if (Channel->HasSG && XAxiVdma_ChannelIsBusy(Channel)) { xdbg_printf(XDBG_DEBUG_ERROR, "Channel is busy, cannot setup engine for transfer\r\n"); return XST_DEVICE_BUSY; } memset((void *)BdAddrPhys, 0, NumFrames * sizeof(XAxiVdma_Bd)); memset((void *)BdAddrVirt, 0, NumFrames * sizeof(XAxiVdma_Bd)); /* Set up the BD link list */ for (i = 0; i < NumFrames; i++) { XAxiVdma_Bd *BdPtr; BdPtr = (XAxiVdma_Bd *)CurrVirt; /* The last BD connects to the first BD */ if (i == (NumFrames - 1)) { NextPhys = BdAddrPhys; } else { NextPhys += sizeof(XAxiVdma_Bd); } XAxiVdma_BdSetNextPtr(BdPtr, NextPhys); CurrVirt += sizeof(XAxiVdma_Bd); } /* Setup the BD addresses so that access the head/tail BDs fast * */ Channel->HeadBdPhysAddr = BdAddrPhys; Channel->HeadBdAddr = BdAddrVirt; Channel->TailBdPhysAddr = BdAddrPhys + (NumFrames - 1) * sizeof(XAxiVdma_Bd); Channel->TailBdAddr = BdAddrVirt + (NumFrames - 1) * sizeof(XAxiVdma_Bd); return XST_SUCCESS; }
/** * Get the APP word at the specified APP word offset for a BD. * * @param BdPtr is the BD to operate on. * @param Offset is the offset inside the APP word, it is valid from * 0 to 4 * @param Valid is to tell the caller whether parameters are valid * * @returns * The APP word. Passed in parameter Valid holds 0 for failure, * and 1 for success. * * @note This function can be used only when DMA is in SG mode * *****************************************************************************/ u32 XAxiDma_BdGetAppWord(XAxiDma_Bd* BdPtr, int Offset, int *Valid) { *Valid = 0; if (XAxiDma_BdRead(BdPtr, XAXIDMA_BD_HAS_STSCNTRL_OFFSET) == 0) { xdbg_printf(XDBG_DEBUG_ERROR, "BdRingGetAppWord: no sts cntrl " "stream in hardware build, no app word available\r\n"); return (u32)0; } if((Offset < 0) || (Offset > XAXIDMA_LAST_APPWORD)) { xdbg_printf(XDBG_DEBUG_ERROR, "BdRingGetAppWord: invalid" " offset %d", Offset); return (u32)0; } *Valid = 1; return XAxiDma_BdRead(BdPtr, XAXIDMA_BD_USR0_OFFSET + Offset * 4); }
/** * Set the length field for the given BD. * * Length has to be non-zero and less than LengthMask. * * For TX channels, the value passed in should be the number of bytes to * transmit from the TX buffer associated with the given BD. * * For RX channels, the value passed in should be the size of the RX buffer * associated with the given BD in bytes. This is to notify the RX channel * the capability of the RX buffer to avoid buffer overflow. * * The actual receive length can be equal or smaller than the specified length. * The actual transfer length will be updated by the hardware in the * XAXIDMA_BD_STS_OFFSET word in the BD. * * @param BdPtr is the BD to operate on. * @param LenBytes is the requested transfer length * @param LengthMask is the maximum transfer length * * @returns * - XST_SUCCESS for success * - XST_INVALID_PARAM for invalid BD length * * @note This function can be used only when DMA is in SG mode * *****************************************************************************/ int XAxiDma_BdSetLength(XAxiDma_Bd *BdPtr, u32 LenBytes, u32 LengthMask) { if (LenBytes <= 0 || (LenBytes > LengthMask)) { xdbg_printf(XDBG_DEBUG_ERROR, "invalid length %d\n", (int)LenBytes); return XST_INVALID_PARAM; } XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_CTRL_LEN_OFFSET, ((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_CTRL_LEN_OFFSET) & \ ~LengthMask)) | LenBytes); return XST_SUCCESS; }
/** * Get a channel * * @param InstancePtr is the DMA engine to work on * @param Direction is the direction for the channel to get * * @return * The pointer to the channel. Upon error, return NULL. * * @note * Since this function is internally used, we assume Direction is valid *****************************************************************************/ XAxiVdma_Channel *XAxiVdma_GetChannel(XAxiVdma *InstancePtr, u16 Direction) { if (Direction == XAXIVDMA_READ) { return &(InstancePtr->ReadChannel); } else if (Direction == XAXIVDMA_WRITE) { return &(InstancePtr->WriteChannel); } else { xdbg_printf(XDBG_DEBUG_ERROR, "Invalid direction %x\r\n", Direction); return NULL; } }
/** * Get the frame counter and delay counter for both channels * * @param Channel is the pointer to the channel to work on * @param FrmCnt is the pointer for the returning frame counter value * @param DlyCnt is the pointer for the returning delay counter value * * @return * None * * @note * If FrmCnt return as 0, then the channel is not initialized *****************************************************************************/ void XAxiVdma_ChannelGetFrmCnt(XAxiVdma_Channel *Channel, u8 *FrmCnt, u8 *DlyCnt) { u32 CrBits; if (!Channel->IsValid) { xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n"); *FrmCnt = 0; return; } CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET); if (Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_FRM_CNTR) { *FrmCnt = (CrBits & XAXIVDMA_FRMCNT_MASK) >> XAXIVDMA_FRMCNT_SHIFT; } else {
/** * Set the channel to run in parking mode * * @param Channel is the pointer to the channel to work on * * @return * - XST_SUCCESS if everything is fine * - XST_FAILURE if hardware is not running * *****************************************************************************/ int XAxiVdma_ChannelStartParking(XAxiVdma_Channel *Channel) { u32 CrBits; if (!XAxiVdma_ChannelIsRunning(Channel)) { xdbg_printf(XDBG_DEBUG_ERROR, "Channel is not running, cannot start park mode\r\n"); return XST_FAILURE; } CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) & ~XAXIVDMA_CR_TAIL_EN_MASK; XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET, CrBits); return XST_SUCCESS; }
/* * This function checks that two buffers have the same data * * @param SrcPtr is the source buffer * @param DestPtr is the destination buffer * @param Length is the length of the buffer to check * * @return * - XST_SUCCESS if the two buffer matches * - XST_FAILURE otherwise * * @note None * ******************************************************************************/ static int CheckData(u8 *SrcPtr, u8 *DestPtr, int Length) { int Index; /* Invalidate the DestBuffer before receiving the data, in case the * Data Cache is enabled */ Xil_DCacheInvalidateRange((u32)DestPtr, Length); for (Index = 0; Index < Length; Index++) { if ( DestPtr[Index] != SrcPtr[Index]) { xdbg_printf(XDBG_DEBUG_ERROR, "Data check failure %d: %x/%x\r\n", Index, DestPtr[Index], SrcPtr[Index]); return XST_FAILURE; } } return XST_SUCCESS; }
/** * @brief Set the memory attributes for a section of memory in the * translation table. * * @param Addr: 32-bit address for which memory attributes need to be set.. * @param size: size is the size of the region. * @param attrib: Attribute for the given memory region. * @return None. * * ******************************************************************************/ u32 Xil_SetMPURegion(INTPTR addr, u64 size, u32 attrib) { u32 Regionsize = 0; INTPTR Localaddr = addr; u32 NextAvailableMemRegion; unsigned int i; NextAvailableMemRegion = Xil_GetNextMPURegion(); if (NextAvailableMemRegion == 0xFF) { xdbg_printf(DEBUG, "No regions available\r\n"); return XST_FAILURE; } Xil_DCacheFlush(); Xil_ICacheInvalidate(); mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,NextAvailableMemRegion); isb(); /* Lookup the size. */ for (i = 0; i < sizeof region_size / sizeof region_size[0]; i++) { if (size <= region_size[i].size) { Regionsize = region_size[i].encoding; break; } } Localaddr &= ~(region_size[i].size - 1); Regionsize <<= 1; Regionsize |= REGION_EN; dsb(); mtcp(XREG_CP15_MPU_REG_BASEADDR, Localaddr); /* Set base address of a region */ mtcp(XREG_CP15_MPU_REG_ACCESS_CTRL, attrib); /* Set the control attribute */ mtcp(XREG_CP15_MPU_REG_SIZE_EN, Regionsize); /* set the region size and enable it*/ dsb(); isb(); Xil_UpdateMPUConfig(NextAvailableMemRegion, Localaddr, Regionsize, attrib); return XST_SUCCESS; }