Ejemplo n.º 1
0
/**
*
* This function initiates a transfer on the bus and enables interrupts.
* The transfer is completed by the interrupt handler. The messages passed are
* all transferred on the bus between one CS assert and de-assert.
*
* @param	InstancePtr is a pointer to the XQspiPsu instance.
* @param	Msg is a pointer to the structure containing transfer data.
* @param	NumMsg is the number of messages to be transferred.
*
* @return
*		- XST_SUCCESS if successful.
*		- XST_FAILURE if transfer fails.
*		- XST_DEVICE_BUSY if a transfer is already in progress.
*
* @note		None.
*
******************************************************************************/
s32 XQspiPsu_InterruptTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
				u32 NumMsg)
{
	u32 StatusReg;
	u32 ConfigReg;
	s32 Index;
	u32 BaseAddress;
	s32 Status;

	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
	for (Index = 0; Index < (s32)NumMsg; Index++) {
		Xil_AssertNonvoid(Msg[Index].ByteCount > 0U);
	}

	/* Check whether there is another transfer in progress. Not thread-safe */
	if (InstancePtr->IsBusy == TRUE) {
		return (s32)XST_DEVICE_BUSY;
	}

	/* Check for ByteCount upper limit - 2^28 for DMA */
	for (Index = 0; Index < (s32)NumMsg; Index++) {
		if ((Msg[Index].ByteCount > XQSPIPSU_DMA_BYTES_MAX) &&
				((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
			return (s32)XST_FAILURE;
		}
	}

	/*
	 * Set the busy flag, which will be cleared when the transfer is
	 * entirely done.
	 */
	InstancePtr->IsBusy = TRUE;

	BaseAddress = InstancePtr->Config.BaseAddress;

	InstancePtr->Msg = Msg;
	InstancePtr->NumMsg = (s32)NumMsg;
	InstancePtr->MsgCnt = 0;

	/* Enable */
	XQspiPsu_Enable(InstancePtr);

	/* Select slave */
	XQspiPsu_GenFifoEntryCSAssert(InstancePtr);

	/* This might not work if not manual start */
	/* Put first message in FIFO along with the above slave select */
	XQspiPsu_GenFifoEntryData(InstancePtr, Msg, 0);

	if (InstancePtr->IsManualstart == TRUE) {
#ifdef DEBUG
	xil_printf("\nManual Start\r\n");
#endif
		XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
			XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) |
				XQSPIPSU_CFG_START_GEN_FIFO_MASK);
	}

	/* Enable interrupts */
	XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_IER_OFFSET,
		(u32)XQSPIPSU_IER_TXNOT_FULL_MASK | (u32)XQSPIPSU_IER_TXEMPTY_MASK |
		(u32)XQSPIPSU_IER_RXNEMPTY_MASK | (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
		(u32)XQSPIPSU_IER_RXEMPTY_MASK);

	if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
		XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_QSPIDMA_DST_I_EN_OFFSET,
				XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
	}

	return XST_SUCCESS;
}
Ejemplo n.º 2
0
/**
*
* This function initiates a transfer on the bus and enables interrupts.
* The transfer is completed by the interrupt handler. The messages passed are
* all transferred on the bus between one CS assert and de-assert.
*
* @param	InstancePtr is a pointer to the XQspiPsu instance.
* @param	Msg is a pointer to the structure containing transfer data.
* @param	NumMsg is the number of messages to be transferred.
*
* @return
*		- XST_SUCCESS if successful.
*		- XST_FAILURE if transfer fails.
*		- XST_DEVICE_BUSY if a transfer is already in progress.
*
* @note		None.
*
******************************************************************************/
int XQspiPsu_InterruptTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
                               unsigned NumMsg)
{
    u32 StatusReg;
    u32 ConfigReg;
    int Index;
    u8 IsManualStart = FALSE;
    u32 BaseAddress;
    int Status;

    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
    for (Index = 0; Index < NumMsg; Index++) {
        Xil_AssertNonvoid(Msg[Index].ByteCount > 0);
    }

    /* Check whether there is another transfer in progress. Not thread-safe */
    if (InstancePtr->IsBusy) {
        return XST_DEVICE_BUSY;
    }

    /*
     * Set the busy flag, which will be cleared when the transfer is
     * entirely done.
     */
    InstancePtr->IsBusy = TRUE;

    BaseAddress = InstancePtr->Config.BaseAddress;

    /* Start if manual start */
    IsManualStart = XQspiPsu_IsManualStart(InstancePtr);

    InstancePtr->Msg = Msg;
    InstancePtr->NumMsg = NumMsg;
    InstancePtr->MsgCnt = 0;

    /* Enable */
    XQspiPsu_Enable(InstancePtr);

    /* Select slave */
    XQspiPsu_GenFifoEntryCSAssert(InstancePtr);

    /* This might not work if not manual start */
    /* Put first message in FIFO along with the above slave select */
    Status = XQspiPsu_GenFifoEntryData(InstancePtr, Msg, 0);
    if (Status != XST_SUCCESS) {
        return Status;
    }

    if (IsManualStart) {
        XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
                          XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) |
                          XQSPIPSU_CFG_START_GEN_FIFO_MASK);
    }

    /* Enable interrupts */
    XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_IER_OFFSET,
                      XQSPIPSU_IER_TXNOT_FULL_MASK | XQSPIPSU_IER_TXEMPTY_MASK |
                      XQSPIPSU_IER_RXNEMPTY_MASK | XQSPIPSU_IER_GENFIFOEMPTY_MASK);

    if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
        XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_QSPIDMA_DST_I_EN_OFFSET,
                          XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
    }

    return XST_SUCCESS;
}
Ejemplo n.º 3
-1
/**
*
* Handles interrupt based transfers by acting on GENFIFO and DMA interurpts.
*
* @param	InstancePtr is a pointer to the XQspiPsu instance.
*
* @return
*		- XST_SUCCESS if successful.
*		- XST_FAILURE if transfer fails.
*
* @note		None.
*
******************************************************************************/
s32 XQspiPsu_InterruptHandler(XQspiPsu *InstancePtr)
{
	u32 QspiPsuStatusReg, DmaIntrStatusReg = 0;
	u32 BaseAddress;
	XQspiPsu_Msg *Msg;
	s32 NumMsg;
	s32 MsgCnt;
	u8 DeltaMsgCnt = 0;
	s32 RxThr;
	u32 TxRxFlag;

	Xil_AssertNonvoid(InstancePtr != NULL);

	BaseAddress = InstancePtr->Config.BaseAddress;
	Msg = InstancePtr->Msg;
	NumMsg = InstancePtr->NumMsg;
	MsgCnt = InstancePtr->MsgCnt;
	TxRxFlag = Msg[MsgCnt].Flags;

	/* QSPIPSU Intr cleared on read */
	QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_ISR_OFFSET);
	if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
		/* DMA Intr write to clear */
		DmaIntrStatusReg = XQspiPsu_ReadReg(BaseAddress,
					XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);

		XQspiPsu_WriteReg(BaseAddress,
			XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET, DmaIntrStatusReg);
	}
	if (((QspiPsuStatusReg & XQSPIPSU_ISR_POLL_TIME_EXPIRE_MASK) != FALSE) ||
		((DmaIntrStatusReg & XQSPIPSU_QSPIDMA_DST_INTR_ERR_MASK) != FALSE)) {
		/* Call status handler to indicate error */
		InstancePtr->StatusHandler(InstancePtr->StatusRef,
					XST_SPI_COMMAND_ERROR, 0);
	}

	/* Fill more data to be txed if required */
	if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
		((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) != FALSE) &&
		(InstancePtr->TxBytes > 0)) {
		XQspiPsu_FillTxFifo(InstancePtr, &Msg[MsgCnt],
				XQSPIPSU_TXD_DEPTH);
	}

	/*
	 * Check if the entry is ONLY TX and increase MsgCnt.
	 * This is to allow TX and RX together in one entry - corner case.
	 */
	if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
		((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) != FALSE) &&
		((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE) &&
		(InstancePtr->TxBytes == 0) &&
		((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) == FALSE)) {
		MsgCnt += 1;
		DeltaMsgCnt = 1U;
	}

	if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) &&
		(MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
		if ((DmaIntrStatusReg & XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != FALSE) {
				/* Read remaining bytes using IO mode */
			if((InstancePtr->RxBytes % 4) != 0 ) {
				XQspiPsu_WriteReg(BaseAddress,
					XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(
					BaseAddress, XQSPIPSU_CFG_OFFSET) &
					~XQSPIPSU_CFG_MODE_EN_MASK));
				InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
				Msg[MsgCnt].ByteCount = (InstancePtr->RxBytes % 4);
				Msg[MsgCnt].RxBfrPtr += (InstancePtr->RxBytes -
						(InstancePtr->RxBytes % 4));
				InstancePtr->IsUnaligned = 1;
				XQspiPsu_GenFifoEntryData(InstancePtr, Msg,
						MsgCnt);
				if(InstancePtr->IsManualstart == TRUE) {
#ifdef DEBUG
	xil_printf("\nManual Start\r\n");
#endif
					XQspiPsu_WriteReg(BaseAddress,
						XQSPIPSU_CFG_OFFSET,
						XQspiPsu_ReadReg(BaseAddress,
						XQSPIPSU_CFG_OFFSET) |
						XQSPIPSU_CFG_START_GEN_FIFO_MASK);
				}
			}
			else {
				InstancePtr->RxBytes = 0;
				MsgCnt += 1;
				DeltaMsgCnt = 1U;
			}
		}
	} else {
		if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
			if (InstancePtr->RxBytes != 0) {
				if ((QspiPsuStatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK)
								!= FALSE) {
					RxThr = (s32)XQspiPsu_ReadReg(BaseAddress,
								XQSPIPSU_RX_THRESHOLD_OFFSET);
					XQspiPsu_ReadRxFifo(InstancePtr, &Msg[MsgCnt],
						RxThr*4);
				} else {
					if (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE) &&
						((QspiPsuStatusReg & XQSPIPSU_ISR_RXEMPTY_MASK) == FALSE)) {
						XQspiPsu_ReadRxFifo(InstancePtr, &Msg[MsgCnt],
							InstancePtr->RxBytes);
					}
				}
				if (InstancePtr->RxBytes == 0) {
					MsgCnt += 1;
					DeltaMsgCnt = 1U;
				}
			}
		}
	}

	/*
	 * Dummy byte transfer
	 * MsgCnt < NumMsg check is to ensure is it a valid dummy cycle message
	 * If one of the above conditions increased MsgCnt, then
	 * the new message is yet to be placed in the FIFO; hence !DeltaMsgCnt.
	 */
	if ((MsgCnt < NumMsg) && (DeltaMsgCnt == FALSE) &&
		((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) == FALSE) &&
		((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) == FALSE) &&
		((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE)) {
		MsgCnt += 1;
		DeltaMsgCnt = 1U;
	}
	InstancePtr->MsgCnt = MsgCnt;

	/*
	 * DeltaMsgCnt is to handle conditions where genfifo empty can be set
	 * while tx is still not empty or rx dma is not yet done.
	 * MsgCnt > NumMsg indicates CS de-assert entry was also executed.
	 */
	if (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE) &&
		((DeltaMsgCnt != FALSE) || (MsgCnt > NumMsg))) {
		if (MsgCnt < NumMsg) {
			if(InstancePtr->IsUnaligned != 0) {
				InstancePtr->IsUnaligned = 0;
				XQspiPsu_WriteReg(InstancePtr->Config.
					BaseAddress, XQSPIPSU_CFG_OFFSET,
					(XQspiPsu_ReadReg(InstancePtr->Config.
					BaseAddress, XQSPIPSU_CFG_OFFSET) |
					XQSPIPSU_CFG_MODE_EN_DMA_MASK));
				InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
			}
			/* This might not work if not manual start */
			XQspiPsu_GenFifoEntryData(InstancePtr, Msg, MsgCnt);

			if (InstancePtr->IsManualstart == TRUE) {
#ifdef DEBUG
	xil_printf("\nManual Start\r\n");
#endif
				XQspiPsu_WriteReg(BaseAddress,
					XQSPIPSU_CFG_OFFSET,
					XQspiPsu_ReadReg(BaseAddress,
						XQSPIPSU_CFG_OFFSET) |
						XQSPIPSU_CFG_START_GEN_FIFO_MASK);
			}
		} else if (MsgCnt == NumMsg) {
			/* This is just to keep track of the de-assert entry */
			MsgCnt += 1;
			InstancePtr->MsgCnt = MsgCnt;

			/* De-select slave */
			XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);

			if (InstancePtr->IsManualstart == TRUE) {
#ifdef DEBUG
	xil_printf("\nManual Start\r\n");
#endif
				XQspiPsu_WriteReg(BaseAddress,
					XQSPIPSU_CFG_OFFSET,
					XQspiPsu_ReadReg(BaseAddress,
						XQSPIPSU_CFG_OFFSET) |
						XQSPIPSU_CFG_START_GEN_FIFO_MASK);
			}
		} else {
			/* Disable interrupts */
			XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_IDR_OFFSET,
					(u32)XQSPIPSU_IER_TXNOT_FULL_MASK |
					(u32)XQSPIPSU_IER_TXEMPTY_MASK |
					(u32)XQSPIPSU_IER_RXNEMPTY_MASK |
					(u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
					(u32)XQSPIPSU_IER_RXEMPTY_MASK);
			if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
				XQspiPsu_WriteReg(BaseAddress,
					XQSPIPSU_QSPIDMA_DST_I_DIS_OFFSET,
					XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
			}

			/* Clear the busy flag. */
			InstancePtr->IsBusy = FALSE;

			/* Disable the device. */
			XQspiPsu_Disable(InstancePtr);

			/* Call status handler to indicate completion */
			InstancePtr->StatusHandler(InstancePtr->StatusRef,
						XST_SPI_TRANSFER_DONE, 0);
		}
	}

	return XST_SUCCESS;
}
Ejemplo n.º 4
-1
/**
*
* This function performs a transfer on the bus in polled mode. The messages
* passed are all transferred on the bus between one CS assert and de-assert.
*
* @param	InstancePtr is a pointer to the XQspiPsu instance.
* @param	Msg is a pointer to the structure containing transfer data.
* @param	NumMsg is the number of messages to be transferred.
*
* @return
*		- XST_SUCCESS if successful.
*		- XST_FAILURE if transfer fails.
*		- XST_DEVICE_BUSY if a transfer is already in progress.
*
* @note		None.
*
******************************************************************************/
s32 XQspiPsu_PolledTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
				u32 NumMsg)
{
	u32 StatusReg;
	u32 ConfigReg;
	s32 Index;
	u32 QspiPsuStatusReg, DmaStatusReg;
	u32 BaseAddress;
	s32 Status;
	s32 RxThr;
	u32 IOPending = (u32)FALSE;

	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
	for (Index = 0; Index < (s32)NumMsg; Index++) {
		Xil_AssertNonvoid(Msg[Index].ByteCount > 0U);
	}

	/* Check whether there is another transfer in progress. Not thread-safe */
	if (InstancePtr->IsBusy == TRUE) {
		return (s32)XST_DEVICE_BUSY;
	}

	/* Check for ByteCount upper limit - 2^28 for DMA */
	for (Index = 0; Index < (s32)NumMsg; Index++) {
		if ((Msg[Index].ByteCount > XQSPIPSU_DMA_BYTES_MAX) &&
				((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
			return (s32)XST_FAILURE;
		}
	}

	/*
	 * Set the busy flag, which will be cleared when the transfer is
	 * entirely done.
	 */
	InstancePtr->IsBusy = TRUE;

	BaseAddress = InstancePtr->Config.BaseAddress;

	/* Enable */
	XQspiPsu_Enable(InstancePtr);

	/* Select slave */
	XQspiPsu_GenFifoEntryCSAssert(InstancePtr);

	/* list */
	Index = 0;
	while (Index < (s32)NumMsg) {
		XQspiPsu_GenFifoEntryData(InstancePtr, Msg, Index);

		if (InstancePtr->IsManualstart == TRUE) {
#ifdef DEBUG
	xil_printf("\nManual Start\r\n");
#endif
			XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
				XQspiPsu_ReadReg(BaseAddress,
					XQSPIPSU_CFG_OFFSET) |
					XQSPIPSU_CFG_START_GEN_FIFO_MASK);
		}

		/* Use thresholds here */
		/* If there is more data to be transmitted */
		do {
			QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress,
						XQSPIPSU_ISR_OFFSET);

			/* Transmit more data if left */
			if (((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) != FALSE) &&
				((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
				(InstancePtr->TxBytes > 0)) {
				XQspiPsu_FillTxFifo(InstancePtr, &Msg[Index],
						XQSPIPSU_TXD_DEPTH);
			}

			/* Check if DMA RX is complete and update RxBytes */
			if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) &&
				((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
				u32 DmaIntrSts;
				DmaIntrSts = XQspiPsu_ReadReg(BaseAddress,
								XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
				if ((DmaIntrSts & XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != FALSE) {
					XQspiPsu_WriteReg(BaseAddress,
						XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET,
						DmaIntrSts);
					/* Read remaining bytes using IO mode */
					if((InstancePtr->RxBytes % 4) != 0 ) {
						XQspiPsu_WriteReg(BaseAddress,
							XQSPIPSU_CFG_OFFSET,
							(XQspiPsu_ReadReg(BaseAddress,
							XQSPIPSU_CFG_OFFSET) &
							~XQSPIPSU_CFG_MODE_EN_MASK));
						InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
						Msg[Index].ByteCount =
							(InstancePtr->RxBytes % 4);
						Msg[Index].RxBfrPtr += (InstancePtr->RxBytes -
								(InstancePtr->RxBytes % 4));
						InstancePtr->IsUnaligned = 1;
						IOPending = (u32)TRUE;
						break;
					}
					InstancePtr->RxBytes = 0;
				}
			} else {
				if ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE) {
					/* Check if PIO RX is complete and update RxBytes */
					RxThr = (s32)XQspiPsu_ReadReg(BaseAddress,
							XQSPIPSU_RX_THRESHOLD_OFFSET);
					if ((QspiPsuStatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK)
									!= 0U) {
						XQspiPsu_ReadRxFifo(InstancePtr,
								&Msg[Index], RxThr*4);

					} else {
						if ((QspiPsuStatusReg &
							XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != 0U) {
								XQspiPsu_ReadRxFifo(InstancePtr,
									&Msg[Index], InstancePtr->RxBytes);
						}
					}
				}
			}
		} while (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == FALSE) ||
			(InstancePtr->TxBytes != 0) ||
			((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) == FALSE) ||
			(InstancePtr->RxBytes != 0));

		if((InstancePtr->IsUnaligned != 0) && (IOPending == (u32)FALSE)) {
			InstancePtr->IsUnaligned = 0;
			XQspiPsu_WriteReg(BaseAddress,
				XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(
				BaseAddress,
				XQSPIPSU_CFG_OFFSET) |
				XQSPIPSU_CFG_MODE_EN_DMA_MASK));
			InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
		}

		if (IOPending == (u32)TRUE) {
			IOPending = (u32)FALSE;
		} else {
			Index++;
		}
	}

	/* De-select slave */
	XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);

	if (InstancePtr->IsManualstart == TRUE) {
#ifdef DEBUG
	xil_printf("\nManual Start\r\n");
#endif
		XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
			XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) |
				XQSPIPSU_CFG_START_GEN_FIFO_MASK);
	}

	QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_ISR_OFFSET);
	while ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == FALSE) {
		QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress,
						XQSPIPSU_ISR_OFFSET);
	}

	/* Clear the busy flag. */
	InstancePtr->IsBusy = FALSE;

	/* Disable the device. */
	XQspiPsu_Disable(InstancePtr);

	return XST_SUCCESS;
}
Ejemplo n.º 5
-1
/**
*
* This function performs a transfer on the bus in polled mode. The messages
* passed are all transferred on the bus between one CS assert and de-assert.
*
* @param	InstancePtr is a pointer to the XQspiPsu instance.
* @param	Msg is a pointer to the structure containing transfer data.
* @param	NumMsg is the number of messages to be transferred.
*
* @return
*		- XST_SUCCESS if successful.
*		- XST_FAILURE if transfer fails.
*		- XST_DEVICE_BUSY if a transfer is already in progress.
*
* @note		None.
*
******************************************************************************/
int XQspiPsu_PolledTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
                            unsigned NumMsg)
{
    u32 StatusReg;
    u32 ConfigReg;
    int Index;
    u8 IsManualStart = FALSE;
    u32 QspiPsuStatusReg, DmaStatusReg;
    u32 BaseAddress;
    int Status;
    u32 RxThr;

    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
    for (Index = 0; Index < NumMsg; Index++) {
        Xil_AssertNonvoid(Msg[Index].ByteCount > 0);
    }

    /* Check whether there is another transfer in progress. Not thread-safe */
    if (InstancePtr->IsBusy) {
        return XST_DEVICE_BUSY;
    }

    /*
     * Set the busy flag, which will be cleared when the transfer is
     * entirely done.
     */
    InstancePtr->IsBusy = TRUE;

    BaseAddress = InstancePtr->Config.BaseAddress;

    /* Start if manual start */
    IsManualStart = XQspiPsu_IsManualStart(InstancePtr);

    /* Enable */
    XQspiPsu_Enable(InstancePtr);

    /* Select slave */
    XQspiPsu_GenFifoEntryCSAssert(InstancePtr);

    /* list */
    for (Index = 0; Index < NumMsg; Index++) {

GENFIFO:
        Status = XQspiPsu_GenFifoEntryData(InstancePtr, Msg, Index);
        if (Status != XST_SUCCESS) {
            return Status;
        }

        if (IsManualStart) {
            XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
                              XQspiPsu_ReadReg(BaseAddress,
                                               XQSPIPSU_CFG_OFFSET) |
                              XQSPIPSU_CFG_START_GEN_FIFO_MASK);
        }

        /* Use thresholds here */
        /* If there is more data to be transmitted */
        do {
            QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress,
                                                XQSPIPSU_ISR_OFFSET);

            /* Transmit more data if left */
            if ((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) &&
                    (Msg[Index].TxBfrPtr != NULL) &&
                    (InstancePtr->TxBytes > 0)) {
                XQspiPsu_FillTxFifo(InstancePtr, &Msg[Index],
                                    XQSPIPSU_TXD_DEPTH);
            }

            /* Check if DMA RX is complete and update RxBytes */
            if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) &&
                    (Msg[Index].RxBfrPtr != NULL)) {
                u32 DmaIntrSts;
                DmaIntrSts = XQspiPsu_ReadReg(BaseAddress,
                                              XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
                if (DmaIntrSts & XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) {
                    XQspiPsu_WriteReg(BaseAddress,
                                      XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET,
                                      DmaIntrSts);
                    /* Read remaining bytes using IO mode */
                    if(InstancePtr->RxBytes % 4 != 0 ) {
                        XQspiPsu_WriteReg(BaseAddress,
                                          XQSPIPSU_CFG_OFFSET,
                                          (XQspiPsu_ReadReg(BaseAddress,
                                                            XQSPIPSU_CFG_OFFSET) &
                                           ~XQSPIPSU_CFG_MODE_EN_MASK));
                        InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
                        Msg[Index].ByteCount =
                            (InstancePtr->RxBytes % 4);
                        Msg[Index].RxBfrPtr += (InstancePtr->RxBytes -
                                                (InstancePtr->RxBytes % 4));
                        InstancePtr->IsUnaligned = 1;
                        goto GENFIFO;
                    }
                    InstancePtr->RxBytes = 0;
                }
            } else if (Msg[Index].RxBfrPtr != NULL) {
                /* Check if PIO RX is complete and update RxBytes */
                RxThr = XQspiPsu_ReadReg(BaseAddress,
                                         XQSPIPSU_RX_THRESHOLD_OFFSET);
                if ((QspiPsuStatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK)
                        != 0U) {
                    XQspiPsu_ReadRxFifo(InstancePtr,
                                        &Msg[Index], RxThr);

                } else if ((QspiPsuStatusReg &
                            XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != 0U) {
                    XQspiPsu_ReadRxFifo(InstancePtr,
                                        &Msg[Index], InstancePtr->RxBytes);
                }
            }
        } while (!(QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) ||
                 (InstancePtr->TxBytes != 0) ||
                 !(QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) ||
                 (InstancePtr->RxBytes != 0));

        if(InstancePtr->IsUnaligned) {
            InstancePtr->IsUnaligned = 0;
            XQspiPsu_WriteReg(BaseAddress,
                              XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(
                                      BaseAddress,
                                      XQSPIPSU_CFG_OFFSET) |
                                                    XQSPIPSU_CFG_MODE_EN_DMA_MASK));
            InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
        }
    }

    /* De-select slave */
    XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);

    if (IsManualStart) {
        XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
                          XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) |
                          XQSPIPSU_CFG_START_GEN_FIFO_MASK);
    }

    QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_ISR_OFFSET);
    while (!(QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK)) {
        QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress,
                                            XQSPIPSU_ISR_OFFSET);
    }

    /* Clear the busy flag. */
    InstancePtr->IsBusy = FALSE;

    /* Disable the device. */
    XQspiPsu_Disable(InstancePtr);

    return XST_SUCCESS;
}