[U-Boot] [PATCH] Improve DaVinci SPI speed
Delio Brignoli
dbrignoli at audioscience.com
Thu May 13 18:23:12 CEST 2010
Hello Paulraj,
On 13/05/2010, at 17:10, Paulraj, Sandeep wrote:
>> 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.
Sure, it was tested on a LogicPD Zoom™ OMAP-L138 eXperimenter Kit
(da850_omapl138_evm_config).
--
Delio
>> 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