예제 #1
0
/**
*
* Handle cleanup when a data transfer is complete. This means intializing the
* state variables, disabling the data-buffer-ready interrupt, and sending the
* event to the user.
*
* @param InstancePtr is a pointer to the XSysAce instance to be worked on.
*
* @return
*
* None.
*
* @note
*
* None.
*
******************************************************************************/
static void
DataComplete(XSysAce * InstancePtr)
{
	InstancePtr->NumRequested = 0;
	InstancePtr->NumRemaining = 0;
	InstancePtr->BufferPtr = NULL;

	/*
	 * Disable the data-buffer-ready interrupt. This isn't necessary when
	 * reading since the DATABUFRDY status bit is cleared by the ACE after
	 * the last data buffer is read.  However, the ACE isn't currently
	 * smart enough to clear the DATABUFRDY status bit after the last data
	 * buffer is written during a write operation.  So, we need to use the
	 * enable/disable interrupt bit to control its usefulness.
	 */
	XSysAce_mAndControlReg(InstancePtr->BaseAddress,
			       ~XSA_CR_DATARDYIRQ_MASK);

	/*
	 * The same code is executed for JTAG configuration as well as CompactFlash
	 * transfers, so we need to distinguish between JTAG config done and CF
	 * data transfer done. We look at the CFGSEL value in the control register
	 * to determine if an MPU JTAG config process has just completed. The
	 * CFG_DONE event is passed up later by the main interrupt handler.
	 */
	if ((XSysAce_mGetControlReg(InstancePtr->BaseAddress)
	     & XSA_CR_CFGSEL_MASK) == 0) {
		/* no JTAG configuration in progress */
		InstancePtr->EventHandler(InstancePtr->EventRef,
					  XSA_EVENT_DATA_DONE);
	}
}
예제 #2
0
/**
*
* Set the start mode for configuration of the target FPGA chain from
* CompactFlash. The configuration process only starts after a reset. The
* user can indicate that the configuration should start immediately after a
* reset, or the configuration process can be delayed until the user commands
* it to start (using this function). The configuration controller can be
* reset using XSysAce_ResetCfg().
*
* The user can select which configuration file on the CompactFlash to use using
* the XSysAce_SetCfgAddr() function. If the user intends to configure the target
* FPGA chain directly from the MPU port, this function is not needed. Instead,
* the user would simply call XSysAce_ProgramChain().
*
* The user can use XSysAce_IsCfgDone() when in polled mode to determine if
* the configuration is complete. If in interrupt mode, the event
* XSA_EVENT_CFG_DONE will be returned asynchronously to the user when the
* configuration is complete. The user must call XSysAce_EnableInterrupt() to put
* the device/driver into interrupt mode.
*
* @param InstancePtr is a pointer to the XSysAce instance to be worked on.
* @param ImmedOnReset can be set to TRUE to indicate the configuration process
*        will start immediately after a reset of the ACE configuration
*        controller, or it can be set to FALSE to indicate the configuration
*        process is delayed after a reset until the user starts it (using this
*        function).
* @param StartCfg is a boolean indicating whether to start the configuration
*        process or not. When ImmedOnReset is set to TRUE, this value is
*        ignored. When ImmedOnReset is set to FALSE, then this value controls
*        when the configuration process is started. When set to TRUE the
*        configuration process starts (assuming a reset of the device has
*        occurred), and when set to FALSE the configuration process does not
*        start.
*
* @return
*
* None.
*
* @note
*
* None.
*
******************************************************************************/
void
XSysAce_SetStartMode(XSysAce * InstancePtr, u32 ImmedOnReset, u32 StartCfg)
{
	u32 Control;

	XASSERT_VOID(InstancePtr != NULL);
	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	/* Get the current contents of the control register */
	Control = XSysAce_mGetControlReg(InstancePtr->BaseAddress);

	/*
	 * Since the user has called this function, we want to tell the ACE
	 * controller to look at the CFGMODE bit of the control register rather
	 * than the CFGMODE pin of the device to determine when to start a
	 * configuration process.
	 */
	Control |= XSA_CR_FORCECFGMODE_MASK;

	/* Set or clear the CFGMODE bit of the control register */
	if (ImmedOnReset) {
		Control |= XSA_CR_CFGMODE_MASK;	/* immediate on reset */
	} else {
		Control &= ~XSA_CR_CFGMODE_MASK;	/* wait for start bit */
	}

	/* Set or clear the CFGSTART bit of the control register */
	if (StartCfg) {
		Control |= XSA_CR_CFGSTART_MASK;
	} else {
		Control &= ~XSA_CR_CFGSTART_MASK;
	}

	XSysAce_mSetControlReg(InstancePtr->BaseAddress, Control);
}
예제 #3
0
static unsigned int XSysAce_GetCfgAddr(XSysAce * InstancePtr)
{
	u32 Status;

	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	Status = XSysAce_mGetControlReg(InstancePtr->BaseAddress);
	if (!(Status & XSA_CR_FORCECFGADDR_MASK))
		Status = XSysAce_mGetStatusReg(InstancePtr->BaseAddress);

	return (unsigned int)((Status & XSA_SR_CFGADDR_MASK) >>
			      XSA_CR_CFGADDR_SHIFT);
}
예제 #4
0
/**
*
* The interrupt handler for the System ACE driver. This handler must be
* connected by the user to an interrupt controller or source. This function
* does not save or restore context.
*
* This function continues reading or writing to the compact flash if such an
* operation is in progress, and notifies the upper layer software through
* the event handler once the operation is complete or an error occurs. On an
* error, any command currently in progress is aborted.
*
* @param InstancePtr is a pointer to the XSysAce instance that just interrupted.
*
* @return
*
* None.
*
* @note
*
* None.
*
******************************************************************************/
void
XSysAce_InterruptHandler(void *InstancePtr)
{
	u32 StatusReg;
	XSysAce *AcePtr = (XSysAce *) InstancePtr;

	XASSERT_VOID(InstancePtr != NULL);

	/*
	 * Get the status in order to process each interrupt that has occurred
	 */
	StatusReg = XSysAce_mGetStatusReg(AcePtr->BaseAddress);

	/*
	 * Reset the interrupt line to effectively clear the interrupt conditions.
	 * We need to set the bit to clear the interrupts, then clear the bit so
	 * that new interrupts can be generated.
	 */
	XSysAce_mOrControlReg(AcePtr->BaseAddress, XSA_CR_RESETIRQ_MASK);
	XSysAce_mAndControlReg(AcePtr->BaseAddress, ~XSA_CR_RESETIRQ_MASK);

	/*
	 * Check for data buffer ready, which means an operation (either read or
	 * write) is in progress.
	 */
	if (StatusReg & XSA_SR_DATABUFRDY_MASK) {
		/*
		 * Handles the data buffer, and invokes the callback to the user for
		 * data transfer completion.
		 */
		HandleDataBuffer(AcePtr, StatusReg);
	}

	/*
	 * Check for completion of JTAG configuration and report the event up.
	 * We only do this if the CFGDONE interrupt is enabled since the CFGDONE
	 * status only gets cleared when the confguration controller is reset,
	 * which we do not do unless requested by the user because it may cause
	 * a configuration process to start. We could have gotten into this
	 * interrupt handler by another interrupt, yet have a leftover CFGDONE
	 * status from an earlier configuration process.
	 */
	if ((StatusReg & XSA_SR_CFGDONE_MASK) &&
	    (XSysAce_mGetControlReg(AcePtr->BaseAddress) &
	     XSA_CR_CFGDONEIRQ_MASK)) {
		/*
		 * Clear the bit indicating MPU is the source of configuration data
		 * since we're done configuring from the MPU for now. Also clear the
		 * force CFGMODE bit and the CFGSTART bit, basically undoing what was
		 * done in XSysAce_ProgramChain(). Disable the interrupts since the
		 * CFGDONE status does not get cleared unless a reset occurs - and in
		 * the meantime we may get into this interrupt handler again.
		 */
		XSysAce_mAndControlReg(AcePtr->BaseAddress,
				       ~(XSA_CR_CFGSEL_MASK |
					 XSA_CR_CFGSTART_MASK |
					 XSA_CR_CFGDONEIRQ_MASK |
					 XSA_CR_DATARDYIRQ_MASK |
					 XSA_CR_FORCECFGMODE_MASK));

		AcePtr->EventHandler(AcePtr->EventRef, XSA_EVENT_CFG_DONE);
	}

	/*
	 * Check for errors and report the event (the user is responsible for
	 * retrieving and interpreting the errors). We only do this if the error
	 * interrupt is enabled since the error status only gets cleared when the
	 * CompactFlash or confguration controller is reset, which we do not do
	 * because it may cause a configuration process to start. We could have
	 * entered this interrupt handler by another interrupt and have a leftover
	 * error status from a previous error.
	 */
	if ((StatusReg & (XSA_SR_CFGERROR_MASK | XSA_SR_CFCERROR_MASK)) &&
	    (XSysAce_mGetControlReg(AcePtr->BaseAddress) &
	     XSA_CR_ERRORIRQ_MASK)) {
		/* Clear the transfer state to effectively abort the operation */
		AcePtr->NumRequested = 0;
		AcePtr->NumRemaining = 0;
		AcePtr->BufferPtr = NULL;

		/*
		 * Disable the error interrupt since the only way to clear the
		 * error status is to reset the CF or the configuration controller,
		 * neither of which we want to do here since the consequences may
		 * be undesirable (i.e., may cause a reconfiguration). The user
		 * will need to perform the reset based on the error event.
		 */
		XSysAce_mAndControlReg(AcePtr->BaseAddress,
				       ~XSA_CR_ERRORIRQ_MASK);

		AcePtr->EventHandler(AcePtr->EventRef, XSA_EVENT_ERROR);
	}
}
예제 #5
0
/**
*
* Program the target FPGA chain through the configuration JTAG port. This
* allows the user to program the devices on the target FPGA chain from the MPU
* port instead of from CompactFlash. The user specifies a buffer and the number
* of bytes to write. The buffer should be equivalent to an ACE (.ace) file.
*
* Note that when loading the ACE file via the MPU port, the first sector of the
* ACE file is discarded. The CF filesystem controller in the System ACE device
* knows to skip the first sector when the ACE file comes from the CF, but the
* CF filesystem controller is bypassed when the ACE file comes from the MPU
* port. For this reason, this function skips the first sector of the buffer
* passed in.
*
* In polled mode, the write is blocking. In interrupt mode, the write is
* non-blocking and an event, XSA_EVENT_CFG_DONE, is returned to the user in
* the asynchronous event handler when the configuration is complete.
*
* An MPU lock, obtained using XSysAce_Lock(), must be granted before calling
* this function. If a lock has not been granted, no action is taken and an
* error is returned.
*
* @param InstancePtr is a pointer to the XSysAce instance to be worked on.
* @param BufferPtr is a pointer to a buffer that will be used to program
*        the configuration JTAG devices.
* @param NumBytes is the number of bytes in the buffer. We assume that there
*        is at least one sector of data in the .ace file, which is the
*        information sector.
*
* @return
*
* - XST_SUCCESS if the write was successful. In interrupt mode, this does not
*   mean the write is complete, only that it has begun. An event is returned
*   to the user when the write is complete.
* - XST_SYSACE_NO_LOCK if no MPU lock has yet been granted
* - XST_FAILURE if an error occurred during the write. The user should call
*   XSysAce_GetErrors() to determine the cause of the error.
*
* @note
*
* None.
*
* @internal
*
* The System ACE controller has a 32-byte buffer which holds data. The entire
* buffer must be written to ensure that it gets sent to the configuration
* JTAG port. If the number of bytes specified by the user is not a multiple
* of 32, the driver will pad the remaining bytes of the System ACE buffer with
* zeroes in order to write the entire buffer.
*
******************************************************************************/
XStatus
XSysAce_ProgramChain(XSysAce * InstancePtr, u8 * BufferPtr, int NumBytes)
{
	u32 ControlMask;
	int BytesToSend;
	int NumSent;

	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID(BufferPtr != NULL);
	XASSERT_NONVOID(NumBytes > XSA_CF_SECTOR_SIZE);
	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	/* If a lock has not been granted, return an error */
	if (!XSysAce_mIsMpuLocked(InstancePtr->BaseAddress)) {
		return XST_SYSACE_NO_LOCK;
	}

	/*
	 * Set up the configuration controller to use the MPU port as the
	 * source of configuration data (instead of the CF). The following
	 * control flow comes directly from the System ACE specification, except
	 * the reset was moved to after the other control register bits are set.
	 * Putting it into reset before the bits are set seemed to produce
	 * configuration errors occasionally.
	 */
	ControlMask = XSysAce_mGetControlReg(InstancePtr->BaseAddress);

	/* Select MPU as the source */
	ControlMask |= XSA_CR_CFGSEL_MASK;
	XSysAce_mSetControlReg(InstancePtr->BaseAddress, ControlMask);

	/* Tell controller to wait for start bit from MPU */
	ControlMask |= XSA_CR_FORCECFGMODE_MASK;
	ControlMask &= ~XSA_CR_CFGMODE_MASK;
	XSysAce_mSetControlReg(InstancePtr->BaseAddress, ControlMask);

	/* Set the start bit */
	ControlMask |= XSA_CR_CFGSTART_MASK;
	XSysAce_mSetControlReg(InstancePtr->BaseAddress, ControlMask);

	/* Put the configuration controller into a reset condition */
	ControlMask |= XSA_CR_CFGRESET_MASK;
	XSysAce_mSetControlReg(InstancePtr->BaseAddress, ControlMask);

	/* Clear the reset condition, which starts the process */
	ControlMask &= ~XSA_CR_CFGRESET_MASK;
	XSysAce_mSetControlReg(InstancePtr->BaseAddress, ControlMask);

	/*
	 * Set up number of bytes to send. Default to the entire buffer, which
	 * will be true in polled mode. In interrupt mode, modify this value to
	 * send only one data buffer of data.  Always skip the first sector per
	 * the comment above.
	 */
	BytesToSend = NumBytes - XSA_CF_SECTOR_SIZE;

	/*
	 * The number of bytes to write depends on interrupt or polled mode
	 */
	if (XSysAce_mIsIntrEnabled(InstancePtr->BaseAddress)) {
		/*
		 * In interrupt mode, so enable the data-buffer-ready and
		 * configuration-done interrupts. Also, set up the state variables for
		 * the interrupt handler to transfer the remaining data after the
		 * initial write below. We need to write one data buffer here in this
		 * function in order to cause the data-buffer-ready interrupt to occur
		 * for subsequent writes.
		 */
		ControlMask |= XSA_CR_DATARDYIRQ_MASK | XSA_CR_CFGDONEIRQ_MASK;
		XSysAce_mSetControlReg(InstancePtr->BaseAddress, ControlMask);

		/* Send only one data buffer to begin with (if there is that much) */
		if (BytesToSend > XSA_DATA_BUFFER_SIZE) {
			BytesToSend = XSA_DATA_BUFFER_SIZE;
		}

		/*
		 * Setup state variables for the interrupt handler. Skip the first
		 * sector per the comment above, and also skip the first data buffer
		 * since it is written below.
		 */
		InstancePtr->NumRequested = NumBytes - XSA_CF_SECTOR_SIZE;
		InstancePtr->BufferPtr =
		    BufferPtr + XSA_CF_SECTOR_SIZE + BytesToSend;
		InstancePtr->NumRemaining =
		    NumBytes - XSA_CF_SECTOR_SIZE - BytesToSend;
	}

	NumSent = XSysAce_WriteDataBuffer(InstancePtr->BaseAddress,
					  BufferPtr + XSA_CF_SECTOR_SIZE,
					  BytesToSend);
	if (NumSent != BytesToSend) {
		/* an error occurred, report this to the user */
		return XST_FAILURE;
	}

	/*
	 * If in polled mode, restore the control register to the way it was
	 */
	if (!XSysAce_mIsIntrEnabled(InstancePtr->BaseAddress)) {
		/*
		 * Unselect MPU as the source, tell controller to use CFGMODE pin,
		 * and clear the start bit.
		 */
		ControlMask &= ~(XSA_CR_CFGSEL_MASK | XSA_CR_FORCECFGMODE_MASK |
				 XSA_CR_CFGSTART_MASK);
		XSysAce_mSetControlReg(InstancePtr->BaseAddress, ControlMask);
	}

	return XST_SUCCESS;
}