예제 #1
0
파일: spi-oc-tiny.c 프로젝트: 3null/linux
static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
{
	struct tiny_spi *hw = tiny_spi_to_hw(spi);
	const u8 *txp = t->tx_buf;
	u8 *rxp = t->rx_buf;
	unsigned int i;

	if (hw->irq >= 0) {
		/* use interrupt driven data transfer */
		hw->len = t->len;
		hw->txp = t->tx_buf;
		hw->rxp = t->rx_buf;
		hw->txc = 0;
		hw->rxc = 0;

		/* send the first byte */
		if (t->len > 1) {
			writeb(hw->txp ? *hw->txp++ : 0,
			       hw->base + TINY_SPI_TXDATA);
			hw->txc++;
			writeb(hw->txp ? *hw->txp++ : 0,
			       hw->base + TINY_SPI_TXDATA);
			hw->txc++;
			writeb(TINY_SPI_STATUS_TXR, hw->base + TINY_SPI_STATUS);
		} else {
			writeb(hw->txp ? *hw->txp++ : 0,
			       hw->base + TINY_SPI_TXDATA);
			hw->txc++;
			writeb(TINY_SPI_STATUS_TXE, hw->base + TINY_SPI_STATUS);
		}

		wait_for_completion(&hw->done);
	} else {
		/* we need to tighten the transfer loop */
		writeb(txp ? *txp++ : 0, hw->base + TINY_SPI_TXDATA);
		for (i = 1; i < t->len; i++) {
			writeb(txp ? *txp++ : 0, hw->base + TINY_SPI_TXDATA);

			if (rxp || (i != t->len - 1))
				tiny_spi_wait_txr(hw);
			if (rxp)
				*rxp++ = readb(hw->base + TINY_SPI_TXDATA);
		}
		tiny_spi_wait_txe(hw);
		if (rxp)
			*rxp++ = readb(hw->base + TINY_SPI_RXDATA);
	}

	return t->len;
}
static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
{
	struct tiny_spi *hw = tiny_spi_to_hw(spi);
	const u8 *txp = t->tx_buf;
	u8 *rxp = t->rx_buf;
	unsigned int i;

	if (hw->irq >= 0) {
		
		hw->len = t->len;
		hw->txp = t->tx_buf;
		hw->rxp = t->rx_buf;
		hw->txc = 0;
		hw->rxc = 0;

		
		if (t->len > 1) {
			writeb(hw->txp ? *hw->txp++ : 0,
			       hw->base + TINY_SPI_TXDATA);
			hw->txc++;
			writeb(hw->txp ? *hw->txp++ : 0,
			       hw->base + TINY_SPI_TXDATA);
			hw->txc++;
			writeb(TINY_SPI_STATUS_TXR, hw->base + TINY_SPI_STATUS);
		} else {
			writeb(hw->txp ? *hw->txp++ : 0,
			       hw->base + TINY_SPI_TXDATA);
			hw->txc++;
			writeb(TINY_SPI_STATUS_TXE, hw->base + TINY_SPI_STATUS);
		}

		wait_for_completion(&hw->done);
	} else if (txp && rxp) {
		
		writeb(*txp++, hw->base + TINY_SPI_TXDATA);
		if (t->len > 1) {
			writeb(*txp++, hw->base + TINY_SPI_TXDATA);
			for (i = 2; i < t->len; i++) {
				u8 rx, tx = *txp++;
				tiny_spi_wait_txr(hw);
				rx = readb(hw->base + TINY_SPI_TXDATA);
				writeb(tx, hw->base + TINY_SPI_TXDATA);
				*rxp++ = rx;
			}
			tiny_spi_wait_txr(hw);
			*rxp++ = readb(hw->base + TINY_SPI_TXDATA);
		}
		tiny_spi_wait_txe(hw);
		*rxp++ = readb(hw->base + TINY_SPI_RXDATA);
	} else if (rxp) {
		writeb(0, hw->base + TINY_SPI_TXDATA);
		if (t->len > 1) {
			writeb(0,
			       hw->base + TINY_SPI_TXDATA);
			for (i = 2; i < t->len; i++) {
				u8 rx;
				tiny_spi_wait_txr(hw);
				rx = readb(hw->base + TINY_SPI_TXDATA);
				writeb(0, hw->base + TINY_SPI_TXDATA);
				*rxp++ = rx;
			}
			tiny_spi_wait_txr(hw);
			*rxp++ = readb(hw->base + TINY_SPI_TXDATA);
		}
		tiny_spi_wait_txe(hw);
		*rxp++ = readb(hw->base + TINY_SPI_RXDATA);
	} else if (txp) {
		writeb(*txp++, hw->base + TINY_SPI_TXDATA);
		if (t->len > 1) {
			writeb(*txp++, hw->base + TINY_SPI_TXDATA);
			for (i = 2; i < t->len; i++) {
				u8 tx = *txp++;
				tiny_spi_wait_txr(hw);
				writeb(tx, hw->base + TINY_SPI_TXDATA);
			}
		}
		tiny_spi_wait_txe(hw);
	} else {
		writeb(0, hw->base + TINY_SPI_TXDATA);
		if (t->len > 1) {
			writeb(0, hw->base + TINY_SPI_TXDATA);
			for (i = 2; i < t->len; i++) {
				tiny_spi_wait_txr(hw);
				writeb(0, hw->base + TINY_SPI_TXDATA);
			}
		}
		tiny_spi_wait_txe(hw);
	}
	return t->len;
}