DaVinci: Improve DaVinci SPI speed.
I have updated this patch based on the comments [1] by Wolfgang Denk and removed unused variables. [1][http://lists.denx.de/pipermail/u-boot/2010-May/071728.html] 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. On LogicPD OMAP-L138 EVM, SPI read throughput goes up from ~0.8Mbyte/s to ~1.3Mbyte/s. Tested with a 2Mbyte image file. Remove unused variables in the spi_xfer() function. Signed-off-by: Delio Brignoli <dbrignoli@audioscience.com> Tested-by: Ben Gardiner <bengardiner@nanometrics.ca> Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
This commit is contained in:
parent
05ee415e31
commit
2391174048
|
@ -113,7 +113,8 @@ int spi_claim_bus(struct spi_slave *slave)
|
|||
writel(0, &ds->regs->lvl);
|
||||
|
||||
/* enable SPI */
|
||||
writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
|
||||
writel((readl(&ds->regs->gcr1) |
|
||||
SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -131,12 +132,10 @@ 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);
|
||||
int ret, i;
|
||||
unsigned int i_cnt = 0, o_cnt = 0, buf_reg_val;
|
||||
const u8 *txp = dout; /* dout can be NULL for read operation */
|
||||
u8 *rxp = din; /* din can be NULL for write operation */
|
||||
|
||||
ret = 0;
|
||||
|
||||
if (bitlen == 0)
|
||||
/* Finish any previously submitted transfers */
|
||||
goto out;
|
||||
|
@ -159,41 +158,51 @@ 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);
|
||||
while ((i_cnt < len) || (o_cnt < len)) {
|
||||
/* read RX buffer and flags */
|
||||
buf_reg_val = readl(&ds->regs->buf);
|
||||
|
||||
/* write the data */
|
||||
data1_reg_val &= ~0xFFFF;
|
||||
if (txp) {
|
||||
data1_reg_val |= *txp;
|
||||
txp++;
|
||||
/* 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;
|
||||
/* increment read words count */
|
||||
i_cnt++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to DAT1 is required to keep the serial transfer going.
|
||||
* 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++;
|
||||
/*
|
||||
* 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)) {
|
||||
if ((o_cnt == (len - 1)) && (flags & SPI_XFER_END)) {
|
||||
/* clear CS hold */
|
||||
writel(data1_reg_val &
|
||||
~(1 << SPIDAT1_CSHOLD_SHIFT), &ds->regs->dat1);
|
||||
~(1 << SPIDAT1_CSHOLD_SHIFT),
|
||||
&ds->regs->dat1);
|
||||
} else {
|
||||
/* enable CS hold */
|
||||
/* 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);
|
||||
/* increment written words count */
|
||||
o_cnt++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue