/** * * 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); } }
/** * * 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); }
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); }
/** * * 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); } }
/** * * 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; }