Ejemplo n.º 1
0
static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
{
	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
	u32 ipif_ier;
	u32 cr;
	int len = 0;

	cr = spi_regr(xspi, XSPI_CR_OFFSET);
	if (cr & XSPI_CR_MASTER_MODE) { /* We're a SPI master */
		/* We get here with transmitter inhibited */
		xspi->tx_ptr = t->tx_buf;
		xspi->remaining_bytes = t->len;
		xspi->rx_ptr = t->rx_buf;
		INIT_COMPLETION(xspi->done);
		xilinx_spi_fill_tx_fifo(xspi);

		/* Enable the transmit empty interrupt, which we use to determine
		 * progress on the transmission.
		 */
		ipif_ier = spi_regr(xspi, XIPIF_V123B_IIER_OFFSET);
		spi_regw(xspi, XIPIF_V123B_IIER_OFFSET, ipif_ier | XSPI_INTR_TX_EMPTY);

		/* Start the transfer by not inhibiting the transmitter any longer */
		spi_regw(xspi, XSPI_CR_OFFSET, cr & ~XSPI_CR_TRANS_INHIBIT);
		wait_for_completion(&xspi->done);
		/* Disable the interrupt */
		spi_regw(xspi, XIPIF_V123B_IIER_OFFSET, ipif_ier);
		len = t->len - xspi->remaining_bytes;
	} else { /* We're a SPI slave */
		if (t->tx_buf != NULL) {
			/* Make a local copy of the data to transmit, since we can't be sure the
			 * caller's buffer will still be around when the transfer occurs.
			 */
			len = min((size_t)t->len, sizeof(xspi->slave_tx_buf));
			memcpy(xspi->slave_tx_buf, t->tx_buf, len);
			xspi->tx_ptr = xspi->slave_tx_buf;
			xspi->remaining_bytes = len;
			xspi->tx_len = len;
			/* Clear out old transmit contents */
			spi_regw(xspi, XSPI_CR_OFFSET, cr | XSPI_CR_TXFIFO_RESET);
			xilinx_spi_fill_tx_fifo(xspi);
		}
		if (t->rx_buf != NULL) {
			len = min((int)t->len, (int)(xspi->rx_ptr - xspi->slave_rx_buf));
			/* Clear out old receive contents */
			spi_regw(xspi, XSPI_CR_OFFSET, cr | XSPI_CR_RXFIFO_RESET);
			memcpy(t->rx_buf, xspi->slave_rx_buf, len);
			if (len < xspi->rx_ptr - xspi->slave_rx_buf) {
				memcpy(xspi->slave_rx_buf, xspi->slave_rx_buf + len,
						(xspi->rx_ptr - xspi->slave_rx_buf) - len);
			}
			xspi->rx_ptr -= len;
		}
	}
	return len;
}
Ejemplo n.º 2
0
static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
{
	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
	u32 ipif_ier;
	u16 cr;

	/* We get here with transmitter inhibited */

	xspi->tx_ptr = t->tx_buf;
	xspi->rx_ptr = t->rx_buf;
	xspi->remaining_bytes = t->len;
	INIT_COMPLETION(xspi->done);

	xilinx_spi_fill_tx_fifo(xspi);

	/* Enable the transmit empty interrupt, which we use to determine
	 * progress on the transmission.
	 */
	ipif_ier = xspi->read_fn(xspi->regs + XIPIF_V123B_IIER_OFFSET);
	xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY,
		xspi->regs + XIPIF_V123B_IIER_OFFSET);

	/* Start the transfer by not inhibiting the transmitter any longer */
	cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
		~XSPI_CR_TRANS_INHIBIT;
	xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);

	wait_for_completion(&xspi->done);

	/* Disable the transmit empty interrupt */
	xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET);

	return t->len - xspi->remaining_bytes;
}
static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
{
	struct xilinx_spi *xspi = dev_id;
	u32 ipif_isr;

	
	ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
	xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET);

	if (ipif_isr & XSPI_INTR_TX_EMPTY) {	
		u16 cr;
		u8 sr;

		cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
		xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
			xspi->regs + XSPI_CR_OFFSET);

		
		sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
		while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
			xspi->rx_fn(xspi);
			sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
		}

		
		if (xspi->remaining_bytes > 0) {
			xilinx_spi_fill_tx_fifo(xspi);
			xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
		} else {
			complete(&xspi->done);
		}
	}

	return IRQ_HANDLED;
}
static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
{
	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
	u32 ipif_ier;
	u16 cr;

	

	xspi->tx_ptr = t->tx_buf;
	xspi->rx_ptr = t->rx_buf;
	xspi->remaining_bytes = t->len;
	INIT_COMPLETION(xspi->done);

	xilinx_spi_fill_tx_fifo(xspi);

	ipif_ier = xspi->read_fn(xspi->regs + XIPIF_V123B_IIER_OFFSET);
	xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY,
		xspi->regs + XIPIF_V123B_IIER_OFFSET);

	
	cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
		~XSPI_CR_TRANS_INHIBIT;
	xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);

	wait_for_completion(&xspi->done);

	
	xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET);

	return t->len - xspi->remaining_bytes;
}
Ejemplo n.º 5
0
static void xspi_reset_transmit_buffer(struct xilinx_spi *xspi)
{
	xspi->tx_ptr = xspi->slave_tx_buf;
	xspi->remaining_bytes = xspi->tx_len;
	/* Clear out old transmit contents */
	spi_regw(xspi, XSPI_CR_OFFSET, spi_regr(xspi, XSPI_CR_OFFSET) | XSPI_CR_TXFIFO_RESET);
	xilinx_spi_fill_tx_fifo(xspi);
}
Ejemplo n.º 6
0
/* This driver supports single master mode only. Hence Tx FIFO Empty
 * is the only interrupt we care about.
 * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave Mode
 * Fault are not to happen.
 */
static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
{
	struct xilinx_spi *xspi = dev_id;
	u32 ipif_isr;

	/* Get the IPIF interrupts, and clear them immediately */
	ipif_isr = in_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET);
	out_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET, ipif_isr);

	if (ipif_isr & XSPI_INTR_TX_EMPTY) {	/* Transmission completed */
		u16 cr;
		u8 sr;

		/* A transmit has just completed. Process received data and
		 * check for more data to transmit. Always inhibit the
		 * transmitter while the Isr refills the transmit register/FIFO,
		 * or make sure it is stopped if we're done.
		 */
		cr = in_be16(xspi->regs + XSPI_CR_OFFSET);
		out_be16(xspi->regs + XSPI_CR_OFFSET,
			 cr | XSPI_CR_TRANS_INHIBIT);

		/* Read out all the data from the Rx FIFO */
		sr = in_8(xspi->regs + XSPI_SR_OFFSET);
		while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
			u8 data;

			data = in_8(xspi->regs + XSPI_RXD_OFFSET);
			if (xspi->rx_ptr) {
				*xspi->rx_ptr++ = data;
			}
			sr = in_8(xspi->regs + XSPI_SR_OFFSET);
		}

		/* See if there is more data to send */
		if (xspi->remaining_bytes > 0) {
			xilinx_spi_fill_tx_fifo(xspi);
			/* Start the transfer by not inhibiting the
			 * transmitter any longer
			 */
			out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
		} else {
			/* No more data to send.
			 * Indicate the transfer is completed.
			 */
			complete(&xspi->done);
		}
	}

	return IRQ_HANDLED;
}
Ejemplo n.º 7
0
static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
{
	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
	u32 ipif_ier;

	/* We get here with transmitter inhibited */

	xspi->tx_ptr = t->tx_buf;
	xspi->rx_ptr = t->rx_buf;
	xspi->remaining_bytes = t->len;
	reinit_completion(&xspi->done);


	/* Enable the transmit empty interrupt, which we use to determine
	 * progress on the transmission.
	 */
	ipif_ier = xspi->read_fn(xspi->regs + XIPIF_V123B_IIER_OFFSET);
	xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY,
		xspi->regs + XIPIF_V123B_IIER_OFFSET);

	for (;;) {
		u16 cr;
		u8 sr;

		xilinx_spi_fill_tx_fifo(xspi);

		/* Start the transfer by not inhibiting the transmitter any
		 * longer
		 */
		cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
							~XSPI_CR_TRANS_INHIBIT;
		xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);

		wait_for_completion(&xspi->done);

		/* A transmit has just completed. Process received data and
		 * check for more data to transmit. Always inhibit the
		 * transmitter while the Isr refills the transmit register/FIFO,
		 * or make sure it is stopped if we're done.
		 */
		cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
		xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
			       xspi->regs + XSPI_CR_OFFSET);

		/* Read out all the data from the Rx FIFO */
		sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
		while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
			xspi->rx_fn(xspi);
			sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
		}

		/* See if there is more data to send */
		if (xspi->remaining_bytes <= 0)
			break;
	}

	/* Disable the transmit empty interrupt */
	xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET);

	return t->len - xspi->remaining_bytes;
}
Ejemplo n.º 8
0
/* In single master mode, Tx FIFO Empty is the only interrupt we care about.
 * As a slave, Receive FIFO Not Empty and (possibly) Slave Sel Asserted interrupts used.
 * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave Mode
 * Fault are not to happen.
 */
static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
{
	struct xilinx_spi *xspi = dev_id;
	u32 ipif_isr;
	u32 cr;
	u32 sr;

	/* Get the IPIF interrupts, and clear them immediately */
	ipif_isr = spi_regr(xspi, XIPIF_V123B_IISR_OFFSET);
	spi_regw(xspi, XIPIF_V123B_IISR_OFFSET, ipif_isr);
	cr = spi_regr(xspi, XSPI_CR_OFFSET);

	if (cr & XSPI_CR_MASTER_MODE) { /* We're a SPI master */

		if (ipif_isr & XSPI_INTR_TX_EMPTY) {	/* Transmission completed */

			/* A transmit has just completed. Process received data and
			 * check for more data to transmit. Always inhibit the
			 * transmitter while the Isr refills the transmit register/FIFO,
			 * or make sure it is stopped if we're done.
			 */
			spi_regw(xspi, XSPI_CR_OFFSET, cr | XSPI_CR_TRANS_INHIBIT);

			/* Read out all the data from the Rx FIFO */
			sr = spi_regr(xspi, XSPI_SR_OFFSET);
			while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
				u32 data;

				data = spi_regr(xspi, XSPI_RXD_OFFSET);
				#ifdef XSPI_DEBUG_FIFOIO
				printk("<%02x>", data & 0xff);
				#endif
				if (xspi->rx_ptr) {
					*xspi->rx_ptr++ = (u8)(data & 0xFF);
				}
				sr = spi_regr(xspi, XSPI_SR_OFFSET);
			}

			/* See if there is more data to send */
			if (xspi->remaining_bytes > 0) {
				xilinx_spi_fill_tx_fifo(xspi);
				/* Start the transfer by not inhibiting the
				 * transmitter any longer
				 */
				spi_regw(xspi, XSPI_CR_OFFSET, cr);
			} else {
				/* No more data to send.
				 * Indicate the transfer is completed.
				 */
				complete(&xspi->done);
			}
		}
	} else { /* We're a SPI slave */

		if (ipif_isr & XSPI_INTR_SLAVE_SEL_ASSERT) {
			xspi_reset_transmit_buffer(xspi);
		}
		if (ipif_isr & XSPI_INTR_RX_NOT_EMPTY) {	/* Byte received */
			/* Read out all the data from the Rx FIFO */
			sr = spi_regr(xspi, XSPI_SR_OFFSET);
			while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
				u32 data;

				data = spi_regr(xspi, XSPI_RXD_OFFSET);
				#ifdef XSPI_DEBUG_FIFOIO
				printk("{%02x}", data & 0xff);
				#endif
				if (xspi->rx_ptr - xspi->slave_rx_buf < sizeof(xspi->slave_rx_buf)) {
					*xspi->rx_ptr++ = (u8)(data & 0xFF);
				}
				/* Check if the transfer is completed. */
				sr = spi_regr(xspi, XSPI_SR_OFFSET);
			}
			if (xspi->remaining_bytes > 0) {
				xilinx_spi_fill_tx_fifo(xspi);
			}
		}
	}

	return IRQ_HANDLED;
}