static int xspi_release(struct inode *inode, struct file *filp) { struct xspi_instance *dev = filp->private_data; func_enter(); if (down_interruptible(&dev->sem)) return -EINTR; if (--dev->use_count == 0) { /* This was the last closer: stop the device and free the IRQ */ if (wait_event_interruptible(dev->waitq, XSpi_Stop(&dev->Spi) != XST_DEVICE_BUSY) != 0) { /* Abort transfer by brute force */ XSpi_Abort(&dev->Spi); } disable_irq(dev->irq); free_irq(dev->irq, &dev->Spi); } up(&dev->sem); return 0; }
/* * This function is called back from the XSpi interrupt handler * when one of the following status events occures: * XST_SPI_TRANSFER_DONE - the requested data transfer is done, * XST_SPI_RECEIVE_OVERRUN - Rx FIFO overrun, transmission continues, * XST_SPI_MODE_FAULT - should not happen: the driver doesn't support multiple masters, * XST_SPI_TRANSMIT_UNDERRUN, * XST_SPI_SLAVE_MODE_FAULT - should not happen: the driver doesn't support slave mode. */ static void xspi_status_handler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount) { struct xspi_instance *dev = (struct xspi_instance *) CallBackRef; dev->completion_status = StatusEvent; if (StatusEvent == XST_SPI_TRANSFER_DONE) { dev->tx_count = (int) ByteCount; wake_up_interruptible(&dev->waitq); } else if (StatusEvent == XST_SPI_RECEIVE_OVERRUN) { /* As both Rx and Tx FIFO have the same sizes this should not happen in master mode. That is why we consider Rx overrun as severe error and abort the transfer */ dev->tx_count = (int) ByteCount; XSpi_Abort(&dev->Spi); wake_up_interruptible(&dev->waitq); printk(KERN_ERR XSPI_NAME " %d: Rx overrun!!!.\n", dev->device_id); } else if (StatusEvent == XST_SPI_MODE_FAULT) { wake_up_interruptible(&dev->waitq); } else { printk(KERN_ERR XSPI_NAME " %d: Invalid status event %u.\n", dev->device_id, StatusEvent); } }
/** * * Resets the SPI device by writing to the Software Reset register. Reset must * only be called after the driver has been initialized. The configuration of the * device after reset is the same as its configuration after initialization. * Refer to the XSpi_Initialize function for more details. This is a hard reset * of the device. Any data transfer that is in progress is aborted. * * The upper layer software is responsible for re-configuring (if necessary) * and restarting the SPI device after the reset. * * @param InstancePtr is a pointer to the XSpi instance to be worked on. * * @return None. * * @note None. * ******************************************************************************/ void XSpi_Reset(XSpi *InstancePtr) { Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Abort any transfer that is in progress. */ XSpi_Abort(InstancePtr); /* * Reset any values that are not reset by the hardware reset such that * the software state matches the hardware device. */ InstancePtr->IsStarted = 0; InstancePtr->SlaveSelectReg = InstancePtr->SlaveSelectMask; /* * Reset the device. */ XSpi_WriteReg(InstancePtr->BaseAddr, XSP_SRR_OFFSET, XSP_SRR_RESET_MASK); }