[U-Boot] [PATCH] Improve DaVinci SPI speed
Paulraj, Sandeep
s-paulraj at ti.com
Thu May 13 17:10:56 CEST 2010
>
> 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 at 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 */
> + o_cnt++;
> }
> }
> return 0;
> --
> 1.6.3.3
>
More information about the U-Boot
mailing list