/** * Masks the S2MM error interrupt for the provided error mask value * * @param InstancePtr is the XAxiVdma instance to operate on * @param ErrorMask is the mask of error bits for which S2MM error * interrupt can be disabled. * @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE * * @return - XST_SUCCESS, when error bits are cleared. * - XST_INVALID_PARAM, when channel pointer is invalid. * - XST_DEVICE_NOT_FOUND, when the channel is not valid. * * @note The register S2MM_DMA_IRQ_MASK is only applicable from IPv6.01a * which is added at offset XAXIVDMA_S2MM_DMA_IRQ_MASK_OFFSET. * For older versions, this offset location is reserved and so * the API does not have any effect. * *****************************************************************************/ int XAxiVdma_MaskS2MMErrIntr(XAxiVdma *InstancePtr, u32 ErrorMask, u16 Direction) { XAxiVdma_Channel *Channel; if (Direction != XAXIVDMA_WRITE) { return XST_INVALID_PARAM; } Channel = XAxiVdma_GetChannel(InstancePtr, Direction); if (!Channel) { return XST_INVALID_PARAM; } if (Channel->IsValid) { XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_S2MM_DMA_IRQ_MASK_OFFSET, ErrorMask & XAXIVDMA_S2MM_IRQ_ERR_ALL_MASK); return XST_SUCCESS; } return XST_DEVICE_NOT_FOUND; }
/** * Clear the pending interrupts specified by the bit mask * * Interrupts not specified by the mask will not be affected * * @param InstancePtr is the pointer to the DMA engine to work on * @param Direction is the DMA channel, use XAXIVDMA_READ or XAXIVDMA_WRITE * @param IntrType is the bit mask for the interrups to be cleared * * @return * None * * @note * If channel is invalid, then nothing is done *****************************************************************************/ void XAxiVdma_IntrClear(XAxiVdma *InstancePtr, u32 IntrType, u16 Direction) { XAxiVdma_Channel *Channel; Channel = XAxiVdma_GetChannel(InstancePtr, Direction); if (Channel->IsValid) { XAxiVdma_ChannelIntrClear(Channel, IntrType); } return; }
/** * 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; }
/** * Get the pending interrupts of a channel * * @param InstancePtr is the pointer to the DMA engine to work on * @param Direction is the DMA channel, use XAXIVDMA_READ or XAXIVDMA_WRITE * * @return * The bit mask for the currently pending interrupts * * @note * If Direction is invalid, return 0 *****************************************************************************/ u32 XAxiVdma_IntrGetPending(XAxiVdma *InstancePtr, u16 Direction) { XAxiVdma_Channel *Channel; Channel = XAxiVdma_GetChannel(InstancePtr, Direction); if (!Channel) { xdbg_printf(XDBG_DEBUG_ERROR, "IntrGetPending: invalid direction %d\n\r", Direction); return 0; } if (Channel->IsValid) { return XAxiVdma_ChannelGetPendingIntr(Channel); } else { /* An invalid channel has no intr */ return 0; } }
/** * Initialize the driver with hardware configuration * * @param InstancePtr is the pointer to the DMA engine to work on * @param CfgPtr is the pointer to the hardware configuration structure * @param EffectiveAddr is the virtual address map for the device * * @return * - XST_SUCCESS if everything goes fine * - XST_FAILURE if reset the hardware failed, need system reset to recover * * @note * If channel fails reset, then it will be set as invalid *****************************************************************************/ int XAxiVdma_CfgInitialize(XAxiVdma *InstancePtr, XAxiVdma_Config *CfgPtr, u32 EffectiveAddr) { XAxiVdma_Channel *RdChannel; XAxiVdma_Channel *WrChannel; int Polls; /* Validate parameters */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(CfgPtr != NULL); /* Initially, no interrupt callback functions */ InstancePtr->ReadCallBack.CompletionCallBack = 0x0; InstancePtr->ReadCallBack.ErrCallBack = 0x0; InstancePtr->WriteCallBack.CompletionCallBack = 0x0; InstancePtr->WriteCallBack.ErrCallBack = 0x0; InstancePtr->BaseAddr = EffectiveAddr; InstancePtr->MaxNumFrames = CfgPtr->MaxFrameStoreNum; InstancePtr->HasMm2S = CfgPtr->HasMm2S; InstancePtr->HasS2Mm = CfgPtr->HasS2Mm; InstancePtr->UseFsync = CfgPtr->UseFsync; InstancePtr->InternalGenLock = CfgPtr->InternalGenLock; if (XAxiVdma_Major(InstancePtr) < 3) { InstancePtr->HasSG = 1; } else { InstancePtr->HasSG = CfgPtr->HasSG; } /* The channels are not valid until being initialized */ RdChannel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_READ); RdChannel->IsValid = 0; WrChannel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_WRITE); WrChannel->IsValid = 0; if (InstancePtr->HasMm2S) { RdChannel->ChanBase = InstancePtr->BaseAddr + XAXIVDMA_TX_OFFSET; RdChannel->InstanceBase = InstancePtr->BaseAddr; RdChannel->HasSG = InstancePtr->HasSG; RdChannel->IsRead = 1; RdChannel->StartAddrBase = InstancePtr->BaseAddr + XAXIVDMA_MM2S_ADDR_OFFSET; RdChannel->NumFrames = CfgPtr->MaxFrameStoreNum; /* Flush on Sync */ RdChannel->FlushonFsync = CfgPtr->FlushonFsync; /* Dynamic Line Buffers Depth */ RdChannel->LineBufDepth = CfgPtr->Mm2SBufDepth; if(RdChannel->LineBufDepth > 0) { RdChannel->LineBufThreshold = XAxiVdma_ReadReg(RdChannel->ChanBase, XAXIVDMA_BUFTHRES_OFFSET); xdbg_printf(XDBG_DEBUG_GENERAL, "Read Channel Buffer Threshold %d bytes\n\r", RdChannel->LineBufThreshold); } RdChannel->HasDRE = CfgPtr->HasMm2SDRE; RdChannel->WordLength = CfgPtr->Mm2SWordLen >> 3; RdChannel->StreamWidth = CfgPtr->Mm2SStreamWidth >> 3; /* Internal GenLock */ RdChannel->GenLock = CfgPtr->Mm2SGenLock; /* Debug Info Parameter flags */ if (!CfgPtr->EnableAllDbgFeatures) { if (CfgPtr->Mm2SThresRegEn) { RdChannel->DbgFeatureFlags |= XAXIVDMA_ENABLE_DBG_THRESHOLD_REG; } if (CfgPtr->Mm2SFrmStoreRegEn) { RdChannel->DbgFeatureFlags |= XAXIVDMA_ENABLE_DBG_FRMSTORE_REG; } if (CfgPtr->Mm2SDlyCntrEn) { RdChannel->DbgFeatureFlags |= XAXIVDMA_ENABLE_DBG_DLY_CNTR; } if (CfgPtr->Mm2SFrmCntrEn) { RdChannel->DbgFeatureFlags |= XAXIVDMA_ENABLE_DBG_FRM_CNTR; } } else { RdChannel->DbgFeatureFlags = XAXIVDMA_ENABLE_DBG_ALL_FEATURES; } XAxiVdma_ChannelInit(RdChannel); XAxiVdma_ChannelReset(RdChannel); /* At time of initialization, no transfers are going on, * reset is expected to be quick */ Polls = INITIALIZATION_POLLING; while (Polls && XAxiVdma_ChannelResetNotDone(RdChannel)) { Polls -= 1; } if (!Polls) { xdbg_printf(XDBG_DEBUG_ERROR, "Read channel reset failed %x\n\r", (unsigned int)XAxiVdma_ChannelGetStatus(RdChannel)); return XST_FAILURE; } }