/****************************************************************************** * This function sets the SPI interrupt handler and SPI options. This function * shall be used after the interrupts are registered. * * @param psSpi is the pointer to the SPI driver structure. * * @return XST_SUCCESS - Everything went well * XST_FAILURE - Failure *****************************************************************************/ XStatus fnOledDriverOptions(XSpi *psSpi) { XStatus Status; // Set the handler for the SPI that will be called from the interrupt // context XSpi_SetStatusHandler(psSpi, psSpi, (XSpi_StatusHandler)fnOledSpiIsr); // Set SPI device as master Status = XSpi_SetOptions(psSpi, XSP_MASTER_OPTION | XSP_MANUAL_SSELECT_OPTION); if(Status != XST_SUCCESS) { return XST_FAILURE; } // Select the slave on the SPI bus (although the SS pin is not connected) Status = XSpi_SetSlaveSelect(psSpi, 0x01); if(Status != XST_SUCCESS) { return XST_FAILURE; } // Start the SPI driver XSpi_Start(psSpi); return XST_SUCCESS; }
/** * * This function does a minimal test on the Spi device and driver as a design * example. The purpose of this function is to illustrate the device slave * functionality in interrupt mode. This function receives data from a master and * prints the received data. * * @param SpiInstancePtr is a pointer to the instance of Spi component. * @param SpiDeviceId is the Device ID of the Spi Device and is the * XPAR_<SPI_instance>_DEVICE_ID value from xparameters.h. * * @return XST_SUCCESS if successful, otherwise XST_FAILURE. * * @note This function contains an infinite loop such that if the Spi * device doesn't receive any data or if the interrupts are not * working, it may never return. * ******************************************************************************/ static int SpiSlaveIntrExample(XSpi *SpiInstancePtr, u16 SpiDeviceId) { XSpi_Config *ConfigPtr; int Status; u32 Count; xil_printf("\r\nEntering the Spi Slave Interrupt Example.\r\n"); xil_printf("Waiting for data from SPI master\r\n"); /* * Initialize the SPI driver so that it's ready to use, specify the * device ID that is generated in xparameters.h. */ ConfigPtr = XSpi_LookupConfig(SpiDeviceId); if (ConfigPtr == NULL) { return XST_FAILURE; } Status = XSpi_CfgInitialize(SpiInstancePtr, ConfigPtr, ConfigPtr->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Connect the SPI driver to the interrupt subsystem such that * interrupts can occur. This function is application specific. */ Status = SetupInterruptSystem(SpiInstancePtr); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Setup the handler for the SPI that will be called from the interrupt * context when an SPI status occurs, specify a pointer to the SPI * driver instance as the callback reference so the handler is able to * access the instance data. */ XSpi_SetStatusHandler(SpiInstancePtr,SpiInstancePtr,(XSpi_StatusHandler) SpiHandler); /* * The SPI device is a slave by default and the clock phase and polarity * have to be set according to its master. In this example, CPOL is set * to active low and CPHA is set to 1. */ Status = XSpi_SetOptions(SpiInstancePtr, XSP_CLK_PHASE_1_OPTION | XSP_CLK_ACTIVE_LOW_OPTION); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Start the SPI driver so that the device is enabled. */ XSpi_Start(SpiInstancePtr); /* * Enable the DTR half-empty interrupt while transfering more than * FIFO_DEPTH number of bytes in slave mode, so that the Tx FIFO * is never empty during a transfer. If the Tx FIFO is empty during * a transfer, it results in master receiving invalid data. */ XSpi_IntrEnable(SpiInstancePtr, XSP_INTR_TX_HALF_EMPTY_MASK); /* * Initialize the write buffer with pattern to write, initialize the * read buffer to zero so it can be verified after the read. */ Test = 0x50; for (Count = 0; Count < BUFFER_SIZE; Count++) { WriteBuffer[Count] = (u8)(Count + Test); ReadBuffer[Count] = 0; } /* * Transmit data as a slave, when the master starts sending data. */ TransferInProgress = TRUE; Status = XSpi_Transfer(SpiInstancePtr, WriteBuffer, ReadBuffer, BUFFER_SIZE); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the transfer is complete. */ while (TransferInProgress == TRUE); /* * Print all the data received from the master. */ xil_printf("\r\nReceived data is:\r\n"); for (Count = 0; Count < BUFFER_SIZE; Count++) { xil_printf("0x%x \r\n", ReadBuffer[Count]); } xil_printf("\r\nExiting the Spi Slave Interrupt Example.\r\n"); return XST_SUCCESS; }
static int xspi_probe(struct device *dev) { dev_t devt; XSpi_Config xspi_cfg; struct platform_device *pdev = to_platform_device(dev); struct xspi_platform_data *pdata; struct xspi_instance *inst; struct resource *irq_res, *regs_res; unsigned long remap_size; int retval; if (!dev) return -EINVAL; pdata = (struct xspi_platform_data *) pdev->dev.platform_data; if (!pdata) { printk(KERN_ERR XSPI_NAME " %d: Couldn't find platform data.\n", pdev->id); return -ENODEV; } devt = MKDEV(xspi_major, xspi_minor + pdev->id); inst = kzalloc(sizeof(struct xspi_instance), GFP_KERNEL); if (!inst) { printk(KERN_ERR XSPI_NAME " #%d: Could not allocate device.\n", pdev->id); return -ENOMEM; } dev_set_drvdata(dev, (void *)inst); init_MUTEX(&inst->sem); init_waitqueue_head(&inst->waitq); /* Find irq number, map the control registers in */ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs_res || !irq_res) { printk(KERN_ERR XSPI_NAME" #%d: IO resource(s) not found\n", pdev->id); retval = -EFAULT; goto failed1; } inst->irq = irq_res->start; remap_size = regs_res->end - regs_res->start + 1; if (!request_mem_region(regs_res->start, remap_size, XSPI_NAME)) { printk(KERN_ERR XSPI_NAME " #%d: Couldn't lock memory region at 0x%08lX\n", pdev->id, regs_res->start); retval = -EBUSY; goto failed1; } inst->remap_size = remap_size; inst->phys_addr = regs_res->start; inst->device_id = pdev->id; xspi_cfg.DeviceId = pdev->id; xspi_cfg.HasFifos = (pdata->device_flags & XSPI_HAS_FIFOS) ? 1 : 0; xspi_cfg.SlaveOnly = (pdata->device_flags & XSPI_SLAVE_ONLY) ? 1 : 0; xspi_cfg.NumSlaveBits = pdata->num_slave_bits; if(check_spi_config(&xspi_cfg)) { printk(KERN_ERR XSPI_NAME " #%d: Unsupported hardware configuration\n", pdev->id); retval = -ENODEV; goto failed1; } xspi_cfg.BaseAddress = (u32) ioremap(regs_res->start, remap_size); if (xspi_cfg.BaseAddress == 0) { printk(KERN_ERR XSPI_NAME " #%d: Couldn't ioremap memory at 0x%08lX\n", pdev->id, regs_res->start); retval = -EFAULT; goto failed2; } /* Tell the Xilinx code to bring this SPI interface up. */ if (XSpi_CfgInitialize(&inst->Spi, &xspi_cfg) != XST_SUCCESS) { printk(KERN_ERR XSPI_NAME " #%d: Could not initialize device.\n", pdev->id); retval = -ENODEV; goto failed3; } /* Set interrupt callback */ XSpi_SetStatusHandler(&inst->Spi, inst, xspi_status_handler); /* request_irq() is done in open() */ cdev_init(&inst->cdev, &xspi_fops); inst->cdev.owner = THIS_MODULE; retval = cdev_add(&inst->cdev, devt, 1); if (retval) { printk(KERN_ERR XSPI_NAME " #%d: cdev_add() failed\n", pdev->id); goto failed3; } printk(KERN_INFO XSPI_NAME " %d: at 0x%08X mapped to 0x%08X, irq=%d\n", pdev->id, inst->phys_addr, inst->Spi.BaseAddr, inst->irq); return 0; /* success */ failed3: iounmap((void *) (xspi_cfg.BaseAddress)); failed2: release_mem_region(regs_res->start, remap_size); failed1: kfree(inst); return retval; }
/** * * This function does a minimal test on the Spi device and driver as a * design example. The purpose of this function is to illustrate how to use * the XSpi component using the interrupt mode. * * This function sends data and expects to receive the same data. * * * @param IntcInstancePtr is a pointer to the instance of the INTC * component. * @param SpiInstancePtr is a pointer to the instance of Spi component. * @param SpiDeviceId is the Device ID of the Spi Device and is the * XPAR_<SPI_instance>_DEVICE_ID value from xparameters.h. * @param SpiIntrId is the interrupt Id and is typically * XPAR_<INTC_instance>_<SPI_instance>_VEC_ID value from * xparameters.h . * * @return XST_SUCCESS if successful, otherwise XST_FAILURE. * * @note * * This function contains an infinite loop such that if interrupts are not * working it may never return. * ******************************************************************************/ int SpiIntrExample(XIntc *IntcInstancePtr, XSpi *SpiInstancePtr, u16 SpiDeviceId, u16 SpiIntrId) { int Status; u32 Count; u8 Test; XSpi_Config *ConfigPtr; /* Pointer to Configuration data */ /* * Initialize the SPI driver so that it is ready to use. */ ConfigPtr = XSpi_LookupConfig(SpiDeviceId); if (ConfigPtr == NULL) { return XST_DEVICE_NOT_FOUND; } Status = XSpi_CfgInitialize(SpiInstancePtr, ConfigPtr, ConfigPtr->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Perform a self-test to ensure that the hardware was built correctly. */ Status = XSpi_SelfTest(SpiInstancePtr); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Run loopback test only in case of standard SPI mode. */ if (SpiInstancePtr->SpiMode != XSP_STANDARD_MODE) { return XST_SUCCESS; } /* * Connect the Spi device to the interrupt subsystem such that * interrupts can occur. This function is application specific. */ Status = SpiSetupIntrSystem(IntcInstancePtr, SpiInstancePtr, SpiIntrId); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Setup the handler for the SPI that will be called from the interrupt * context when an SPI status occurs, specify a pointer to the SPI * driver instance as the callback reference so the handler is able to * access the instance data. */ XSpi_SetStatusHandler(SpiInstancePtr, SpiInstancePtr, (XSpi_StatusHandler) SpiIntrHandler); /* * Set the Spi device as a master and in loopback mode. */ Status = XSpi_SetOptions(SpiInstancePtr, XSP_MASTER_OPTION | XSP_LOOPBACK_OPTION); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Start the SPI driver so that interrupts and the device are enabled. */ XSpi_Start(SpiInstancePtr); /* * Initialize the write buffer with pattern to write, initialize the * read buffer to zero so it can be verified after the read, the * Test value that is added to the unique value allows the value to be * changed in a debug environment. */ Test = 0x10; for (Count = 0; Count < BUFFER_SIZE; Count++) { WriteBuffer[Count] = (u8)(Count + Test); ReadBuffer[Count] = 0; } /* * Transmit the data. */ TransferInProgress = TRUE; XSpi_Transfer(SpiInstancePtr, WriteBuffer, ReadBuffer, BUFFER_SIZE); /* * Wait for the transmission to be complete. */ while (TransferInProgress); /* * Disable the Spi interrupt. */ SpiDisableIntrSystem(IntcInstancePtr, SpiIntrId); /* * Compare the data received with the data that was transmitted. */ for (Count = 0; Count < BUFFER_SIZE; Count++) { if (WriteBuffer[Count] != ReadBuffer[Count]) { return XST_FAILURE; } } return XST_SUCCESS; }