]> git.sur5r.net Git - u-boot/blobdiff - drivers/spi/sh_qspi.c
dwc2 USB controller hangs with lan78xx
[u-boot] / drivers / spi / sh_qspi.c
index fc0e1fc336f0c24e4a17c84953cd25a0c90db19e..e9123e2c39c5a917f6277e07d5bfd2354fb87da7 100644 (file)
@@ -1,16 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH QSPI (Quad SPI) driver
  *
  * Copyright (C) 2013 Renesas Electronics Corporation
  * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
- *
- * SPDX-License-Identifier:    GPL-2.0
  */
 
 #include <common.h>
 #include <console.h>
 #include <malloc.h>
 #include <spi.h>
+#include <wait_bit.h>
 #include <asm/arch/rmobile.h>
 #include <asm/io.h>
 
@@ -35,6 +35,8 @@
                        SPCMD_BRDV0
 #define SPBFCR_TXRST   BIT(7)
 #define SPBFCR_RXRST   BIT(6)
+#define SPBFCR_TXTRG   0x30
+#define SPBFCR_RXTRG   0x07
 
 /* SH QSPI register set */
 struct sh_qspi_regs {
@@ -200,8 +202,8 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
             void *din, unsigned long flags)
 {
        struct sh_qspi_slave *ss = to_sh_qspi(slave);
-       u32 nbyte;
-       int ret = 0;
+       u32 nbyte, chunk;
+       int i, ret = 0;
        u8 dtdata = 0, drdata;
        u8 *tdata = &dtdata, *rdata = &drdata;
        u32 *spbmul0 = &ss->regs->spbmul0;
@@ -236,40 +238,38 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
                rdata = din;
 
        while (nbyte > 0) {
-               while (!(readb(&ss->regs->spsr) & SPSR_SPTEF)) {
-                       if (ctrlc()) {
-                               puts("abort\n");
-                               return 1;
-                       }
-                       udelay(10);
+               /*
+                * Check if there is 32 Byte chunk and if there is, transfer
+                * it in one burst, otherwise transfer on byte-by-byte basis.
+                */
+               chunk = (nbyte >= 32) ? 32 : 1;
+
+               clrsetbits_8(&ss->regs->spbfcr, SPBFCR_TXTRG | SPBFCR_RXTRG,
+                            chunk == 32 ? SPBFCR_TXTRG | SPBFCR_RXTRG : 0);
+
+               ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPTEF,
+                                    true, 1000, true);
+               if (ret)
+                       return ret;
+
+               for (i = 0; i < chunk; i++) {
+                       writeb(*tdata, &ss->regs->spdr);
+                       if (dout != NULL)
+                               tdata++;
                }
 
-               writeb(*tdata, (u8 *)(&ss->regs->spdr));
-
-               while ((readw(&ss->regs->spbdcr) != SPBDCR_RXBC0)) {
-                       if (ctrlc()) {
-                               puts("abort\n");
-                               return 1;
-                       }
-                       udelay(1);
-               }
+               ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPRFF,
+                                    true, 1000, true);
+               if (ret)
+                       return ret;
 
-               while (!(readb(&ss->regs->spsr) & SPSR_SPRFF)) {
-                       if (ctrlc()) {
-                               puts("abort\n");
-                               return 1;
-                       }
-                       udelay(10);
+               for (i = 0; i < chunk; i++) {
+                       *rdata = readb(&ss->regs->spdr);
+                       if (din != NULL)
+                               rdata++;
                }
 
-               *rdata = readb((u8 *)(&ss->regs->spdr));
-
-               if (dout != NULL)
-                       tdata++;
-               if (din != NULL)
-                       rdata++;
-
-               nbyte--;
+               nbyte -= chunk;
        }
 
        if (flags & SPI_XFER_END)