
Reduce the number of reads per byte transferred on the BUF register from 2 to 1 and take advantage of the TX buffer in the SPI module.
May I ask which chip device this was tested on.
Signed-off-by: Delio Brignoli dbrignoli@audioscience.com
drivers/spi/davinci_spi.c | 67 +++++++++++++++++++++++-----------------
1 files changed, 35 insertions(+), 32 deletions(-)
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 60ba007..b4a74de 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -131,6 +131,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, { struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int len, data1_reg_val = readl(&ds->regs->dat1);
- unsigned int i_cnt = 0, o_cnt = 0, buf_reg_val; int ret, i; const u8 *txp = dout; /* dout can be NULL for read operation */ u8 *rxp = din; /* din can be NULL for write operation */
@@ -159,41 +160,43 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, readl(&ds->regs->buf);
/* keep writing and reading 1 byte until done */
- for (i = 0; i < len; i++) {
/* wait till TXFULL is asserted */
while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK);
/* write the data */
data1_reg_val &= ~0xFFFF;
if (txp) {
data1_reg_val |= *txp;
txp++;
- while((i_cnt < len) || (o_cnt < len)) {
/* read RX buffer and flags */
buf_reg_val = readl(&ds->regs->buf);
/* if data is available */
if ((i_cnt < len) && (buf_reg_val & SPIBUF_RXEMPTY_MASK) == 0)
{
/* if there is no read buffer simply ignore the read
character */
if(rxp) {
*rxp = buf_reg_val & 0xFF;
rxp++;
}
/* increment read words count */
}i_cnt++;
/*
* Write to DAT1 is required to keep the serial transfer going.
* We just terminate when we reach the end.
*/
if ((i == (len - 1)) && (flags & SPI_XFER_END)) {
/* clear CS hold */
writel(data1_reg_val &
~(1 << SPIDAT1_CSHOLD_SHIFT), &ds->regs->dat1);
} else {
/* enable CS hold */
data1_reg_val |= ((1 << SPIDAT1_CSHOLD_SHIFT) |
/* if the tx buffer is empty and there is still data to
transmit */
if ((o_cnt < len) && ((buf_reg_val & SPIBUF_TXFULL_MASK) ==
0)) {
/* write the data */
data1_reg_val &= ~0xFFFF;
if(txp) {
data1_reg_val |= *txp;
txp++;
}
/* write to DAT1 is required to keep the serial transfer
going */
/* we just terminate when we reach the end */
if((o_cnt == (len -1)) && (flags & SPI_XFER_END)) {
/* clear CS hold */
writel(data1_reg_val &
~(1 << SPIDAT1_CSHOLD_SHIFT), &ds->regs-
dat1);
} else {
/* enable CS hold and write TX register */
data1_reg_val |= ((1 << SPIDAT1_CSHOLD_SHIFT) | (slave->cs << SPIDAT1_CSNR_SHIFT));
writel(data1_reg_val, &ds->regs->dat1);
}
/* read the data - wait for data availability */
while (readl(&ds->regs->buf) & SPIBUF_RXEMPTY_MASK);
if (rxp) {
*rxp = readl(&ds->regs->buf) & 0xFF;
rxp++;
} else {
/* simply drop the read character */
readl(&ds->regs->buf);
writel(data1_reg_val, &ds->regs->dat1);
}
/* increment written words count */
} } return 0;o_cnt++;
-- 1.6.3.3