X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fspi%2Fsh_qspi.c;h=e9123e2c39c5a917f6277e07d5bfd2354fb87da7;hb=7da7ff54914ca58a289bd8e0fda6e7240c545826;hp=7209e1d319e3a527251b65fa7aa143bb9820abd4;hpb=0eb4cf9c14315e1976a116de75da6f420ac0e8dd;p=u-boot diff --git a/drivers/spi/sh_qspi.c b/drivers/spi/sh_qspi.c index 7209e1d319..e9123e2c39 100644 --- a/drivers/spi/sh_qspi.c +++ b/drivers/spi/sh_qspi.c @@ -1,15 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 /* * SH QSPI (Quad SPI) driver * * Copyright (C) 2013 Renesas Electronics Corporation * Copyright (C) 2013 Nobuhiro Iwamatsu - * - * SPDX-License-Identifier: GPL-2.0 */ #include +#include #include #include +#include #include #include @@ -34,33 +35,35 @@ 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 { - unsigned char spcr; - unsigned char sslp; - unsigned char sppcr; - unsigned char spsr; - unsigned long spdr; - unsigned char spscr; - unsigned char spssr; - unsigned char spbr; - unsigned char spdcr; - unsigned char spckd; - unsigned char sslnd; - unsigned char spnd; - unsigned char dummy0; - unsigned short spcmd0; - unsigned short spcmd1; - unsigned short spcmd2; - unsigned short spcmd3; - unsigned char spbfcr; - unsigned char dummy1; - unsigned short spbdcr; - unsigned long spbmul0; - unsigned long spbmul1; - unsigned long spbmul2; - unsigned long spbmul3; + u8 spcr; + u8 sslp; + u8 sppcr; + u8 spsr; + u32 spdr; + u8 spscr; + u8 spssr; + u8 spbr; + u8 spdcr; + u8 spckd; + u8 sslnd; + u8 spnd; + u8 dummy0; + u16 spcmd0; + u16 spcmd1; + u16 spcmd2; + u16 spcmd3; + u8 spbfcr; + u8 dummy1; + u16 spbdcr; + u32 spbmul0; + u32 spbmul1; + u32 spbmul2; + u32 spbmul3; }; struct sh_qspi_slave { @@ -199,11 +202,11 @@ 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); - unsigned long nbyte; - int ret = 0; - unsigned char dtdata = 0, drdata; - unsigned char *tdata = &dtdata, *rdata = &drdata; - unsigned long *spbmul0 = &ss->regs->spbmul0; + u32 nbyte, chunk; + int i, ret = 0; + u8 dtdata = 0, drdata; + u8 *tdata = &dtdata, *rdata = &drdata; + u32 *spbmul0 = &ss->regs->spbmul0; if (dout == NULL && din == NULL) { if (flags & SPI_XFER_END) @@ -229,46 +232,44 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, writel(nbyte, spbmul0); if (dout != NULL) - tdata = (unsigned char *)dout; + tdata = (u8 *)dout; if (din != NULL) 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, (unsigned char *)(&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((unsigned char *)(&ss->regs->spdr)); - - if (dout != NULL) - tdata++; - if (din != NULL) - rdata++; - - nbyte--; + nbyte -= chunk; } if (flags & SPI_XFER_END)