Example #1
0
/******************************************************************************
 * 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;
}
Example #3
0
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;
}