116f47c9cSNobuhiro Iwamatsu /* 216f47c9cSNobuhiro Iwamatsu * SH QSPI (Quad SPI) driver 316f47c9cSNobuhiro Iwamatsu * 416f47c9cSNobuhiro Iwamatsu * Copyright (C) 2013 Renesas Electronics Corporation 516f47c9cSNobuhiro Iwamatsu * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> 616f47c9cSNobuhiro Iwamatsu * 716f47c9cSNobuhiro Iwamatsu * SPDX-License-Identifier: GPL-2.0 816f47c9cSNobuhiro Iwamatsu */ 916f47c9cSNobuhiro Iwamatsu 1016f47c9cSNobuhiro Iwamatsu #include <common.h> 1116f47c9cSNobuhiro Iwamatsu #include <malloc.h> 1216f47c9cSNobuhiro Iwamatsu #include <spi.h> 13*22e75d6dSNobuhiro Iwamatsu #include <asm/arch/rmobile.h> 1416f47c9cSNobuhiro Iwamatsu #include <asm/io.h> 1516f47c9cSNobuhiro Iwamatsu 1616f47c9cSNobuhiro Iwamatsu /* SH QSPI register bit masks <REG>_<BIT> */ 1716f47c9cSNobuhiro Iwamatsu #define SPCR_MSTR 0x08 1816f47c9cSNobuhiro Iwamatsu #define SPCR_SPE 0x40 1916f47c9cSNobuhiro Iwamatsu #define SPSR_SPRFF 0x80 2016f47c9cSNobuhiro Iwamatsu #define SPSR_SPTEF 0x20 2116f47c9cSNobuhiro Iwamatsu #define SPPCR_IO3FV 0x04 2216f47c9cSNobuhiro Iwamatsu #define SPPCR_IO2FV 0x02 2316f47c9cSNobuhiro Iwamatsu #define SPPCR_IO1FV 0x01 2416f47c9cSNobuhiro Iwamatsu #define SPBDCR_RXBC0 (1 << 0) 2516f47c9cSNobuhiro Iwamatsu #define SPCMD_SCKDEN (1 << 15) 2616f47c9cSNobuhiro Iwamatsu #define SPCMD_SLNDEN (1 << 14) 2716f47c9cSNobuhiro Iwamatsu #define SPCMD_SPNDEN (1 << 13) 2816f47c9cSNobuhiro Iwamatsu #define SPCMD_SSLKP (1 << 7) 2916f47c9cSNobuhiro Iwamatsu #define SPCMD_BRDV0 (1 << 2) 3016f47c9cSNobuhiro Iwamatsu #define SPCMD_INIT1 SPCMD_SCKDEN | SPCMD_SLNDEN | \ 3116f47c9cSNobuhiro Iwamatsu SPCMD_SPNDEN | SPCMD_SSLKP | \ 3216f47c9cSNobuhiro Iwamatsu SPCMD_BRDV0 3316f47c9cSNobuhiro Iwamatsu #define SPCMD_INIT2 SPCMD_SPNDEN | SPCMD_SSLKP | \ 3416f47c9cSNobuhiro Iwamatsu SPCMD_BRDV0 3516f47c9cSNobuhiro Iwamatsu #define SPBFCR_TXRST (1 << 7) 3616f47c9cSNobuhiro Iwamatsu #define SPBFCR_RXRST (1 << 6) 3716f47c9cSNobuhiro Iwamatsu 3816f47c9cSNobuhiro Iwamatsu /* SH QSPI register set */ 3916f47c9cSNobuhiro Iwamatsu struct sh_qspi_regs { 4016f47c9cSNobuhiro Iwamatsu unsigned char spcr; 4116f47c9cSNobuhiro Iwamatsu unsigned char sslp; 4216f47c9cSNobuhiro Iwamatsu unsigned char sppcr; 4316f47c9cSNobuhiro Iwamatsu unsigned char spsr; 4416f47c9cSNobuhiro Iwamatsu unsigned long spdr; 4516f47c9cSNobuhiro Iwamatsu unsigned char spscr; 4616f47c9cSNobuhiro Iwamatsu unsigned char spssr; 4716f47c9cSNobuhiro Iwamatsu unsigned char spbr; 4816f47c9cSNobuhiro Iwamatsu unsigned char spdcr; 4916f47c9cSNobuhiro Iwamatsu unsigned char spckd; 5016f47c9cSNobuhiro Iwamatsu unsigned char sslnd; 5116f47c9cSNobuhiro Iwamatsu unsigned char spnd; 5216f47c9cSNobuhiro Iwamatsu unsigned char dummy0; 5316f47c9cSNobuhiro Iwamatsu unsigned short spcmd0; 5416f47c9cSNobuhiro Iwamatsu unsigned short spcmd1; 5516f47c9cSNobuhiro Iwamatsu unsigned short spcmd2; 5616f47c9cSNobuhiro Iwamatsu unsigned short spcmd3; 5716f47c9cSNobuhiro Iwamatsu unsigned char spbfcr; 5816f47c9cSNobuhiro Iwamatsu unsigned char dummy1; 5916f47c9cSNobuhiro Iwamatsu unsigned short spbdcr; 6016f47c9cSNobuhiro Iwamatsu unsigned long spbmul0; 6116f47c9cSNobuhiro Iwamatsu unsigned long spbmul1; 6216f47c9cSNobuhiro Iwamatsu unsigned long spbmul2; 6316f47c9cSNobuhiro Iwamatsu unsigned long spbmul3; 6416f47c9cSNobuhiro Iwamatsu }; 6516f47c9cSNobuhiro Iwamatsu 6616f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave { 6716f47c9cSNobuhiro Iwamatsu struct spi_slave slave; 6816f47c9cSNobuhiro Iwamatsu struct sh_qspi_regs *regs; 6916f47c9cSNobuhiro Iwamatsu }; 7016f47c9cSNobuhiro Iwamatsu 7116f47c9cSNobuhiro Iwamatsu static inline struct sh_qspi_slave *to_sh_qspi(struct spi_slave *slave) 7216f47c9cSNobuhiro Iwamatsu { 7316f47c9cSNobuhiro Iwamatsu return container_of(slave, struct sh_qspi_slave, slave); 7416f47c9cSNobuhiro Iwamatsu } 7516f47c9cSNobuhiro Iwamatsu 7616f47c9cSNobuhiro Iwamatsu static void sh_qspi_init(struct sh_qspi_slave *ss) 7716f47c9cSNobuhiro Iwamatsu { 7816f47c9cSNobuhiro Iwamatsu /* QSPI initialize */ 7916f47c9cSNobuhiro Iwamatsu /* Set master mode only */ 8016f47c9cSNobuhiro Iwamatsu writeb(SPCR_MSTR, &ss->regs->spcr); 8116f47c9cSNobuhiro Iwamatsu 8216f47c9cSNobuhiro Iwamatsu /* Set SSL signal level */ 8316f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->sslp); 8416f47c9cSNobuhiro Iwamatsu 8516f47c9cSNobuhiro Iwamatsu /* Set MOSI signal value when transfer is in idle state */ 8616f47c9cSNobuhiro Iwamatsu writeb(SPPCR_IO3FV|SPPCR_IO2FV, &ss->regs->sppcr); 8716f47c9cSNobuhiro Iwamatsu 8816f47c9cSNobuhiro Iwamatsu /* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */ 8916f47c9cSNobuhiro Iwamatsu writeb(0x01, &ss->regs->spbr); 9016f47c9cSNobuhiro Iwamatsu 9116f47c9cSNobuhiro Iwamatsu /* Disable Dummy Data Transmission */ 9216f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spdcr); 9316f47c9cSNobuhiro Iwamatsu 9416f47c9cSNobuhiro Iwamatsu /* Set clock delay value */ 9516f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spckd); 9616f47c9cSNobuhiro Iwamatsu 9716f47c9cSNobuhiro Iwamatsu /* Set SSL negation delay value */ 9816f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->sslnd); 9916f47c9cSNobuhiro Iwamatsu 10016f47c9cSNobuhiro Iwamatsu /* Set next-access delay value */ 10116f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spnd); 10216f47c9cSNobuhiro Iwamatsu 10316f47c9cSNobuhiro Iwamatsu /* Set equence command */ 10416f47c9cSNobuhiro Iwamatsu writew(SPCMD_INIT2, &ss->regs->spcmd0); 10516f47c9cSNobuhiro Iwamatsu 10616f47c9cSNobuhiro Iwamatsu /* Reset transfer and receive Buffer */ 10716f47c9cSNobuhiro Iwamatsu setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST); 10816f47c9cSNobuhiro Iwamatsu 10916f47c9cSNobuhiro Iwamatsu /* Clear transfer and receive Buffer control bit */ 11016f47c9cSNobuhiro Iwamatsu clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST); 11116f47c9cSNobuhiro Iwamatsu 11216f47c9cSNobuhiro Iwamatsu /* Set equence control method. Use equence0 only */ 11316f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spscr); 11416f47c9cSNobuhiro Iwamatsu 11516f47c9cSNobuhiro Iwamatsu /* Enable SPI function */ 11616f47c9cSNobuhiro Iwamatsu setbits_8(&ss->regs->spcr, SPCR_SPE); 11716f47c9cSNobuhiro Iwamatsu } 11816f47c9cSNobuhiro Iwamatsu 11916f47c9cSNobuhiro Iwamatsu int spi_cs_is_valid(unsigned int bus, unsigned int cs) 12016f47c9cSNobuhiro Iwamatsu { 12116f47c9cSNobuhiro Iwamatsu return 1; 12216f47c9cSNobuhiro Iwamatsu } 12316f47c9cSNobuhiro Iwamatsu 12416f47c9cSNobuhiro Iwamatsu void spi_cs_activate(struct spi_slave *slave) 12516f47c9cSNobuhiro Iwamatsu { 12616f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *ss = to_sh_qspi(slave); 12716f47c9cSNobuhiro Iwamatsu 12816f47c9cSNobuhiro Iwamatsu /* Set master mode only */ 12916f47c9cSNobuhiro Iwamatsu writeb(SPCR_MSTR, &ss->regs->spcr); 13016f47c9cSNobuhiro Iwamatsu 13116f47c9cSNobuhiro Iwamatsu /* Set command */ 13216f47c9cSNobuhiro Iwamatsu writew(SPCMD_INIT1, &ss->regs->spcmd0); 13316f47c9cSNobuhiro Iwamatsu 13416f47c9cSNobuhiro Iwamatsu /* Reset transfer and receive Buffer */ 13516f47c9cSNobuhiro Iwamatsu setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST); 13616f47c9cSNobuhiro Iwamatsu 13716f47c9cSNobuhiro Iwamatsu /* Clear transfer and receive Buffer control bit */ 13816f47c9cSNobuhiro Iwamatsu clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST); 13916f47c9cSNobuhiro Iwamatsu 14016f47c9cSNobuhiro Iwamatsu /* Set equence control method. Use equence0 only */ 14116f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spscr); 14216f47c9cSNobuhiro Iwamatsu 14316f47c9cSNobuhiro Iwamatsu /* Enable SPI function */ 14416f47c9cSNobuhiro Iwamatsu setbits_8(&ss->regs->spcr, SPCR_SPE); 14516f47c9cSNobuhiro Iwamatsu } 14616f47c9cSNobuhiro Iwamatsu 14716f47c9cSNobuhiro Iwamatsu void spi_cs_deactivate(struct spi_slave *slave) 14816f47c9cSNobuhiro Iwamatsu { 14916f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *ss = to_sh_qspi(slave); 15016f47c9cSNobuhiro Iwamatsu 15116f47c9cSNobuhiro Iwamatsu /* Disable SPI Function */ 15216f47c9cSNobuhiro Iwamatsu clrbits_8(&ss->regs->spcr, SPCR_SPE); 15316f47c9cSNobuhiro Iwamatsu } 15416f47c9cSNobuhiro Iwamatsu 15516f47c9cSNobuhiro Iwamatsu void spi_init(void) 15616f47c9cSNobuhiro Iwamatsu { 15716f47c9cSNobuhiro Iwamatsu /* nothing to do */ 15816f47c9cSNobuhiro Iwamatsu } 15916f47c9cSNobuhiro Iwamatsu 16016f47c9cSNobuhiro Iwamatsu struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, 16116f47c9cSNobuhiro Iwamatsu unsigned int max_hz, unsigned int mode) 16216f47c9cSNobuhiro Iwamatsu { 16316f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *ss; 16416f47c9cSNobuhiro Iwamatsu 16516f47c9cSNobuhiro Iwamatsu if (!spi_cs_is_valid(bus, cs)) 16616f47c9cSNobuhiro Iwamatsu return NULL; 16716f47c9cSNobuhiro Iwamatsu 16816f47c9cSNobuhiro Iwamatsu ss = spi_alloc_slave(struct sh_qspi_slave, bus, cs); 16916f47c9cSNobuhiro Iwamatsu if (!ss) { 17016f47c9cSNobuhiro Iwamatsu printf("SPI_error: Fail to allocate sh_qspi_slave\n"); 17116f47c9cSNobuhiro Iwamatsu return NULL; 17216f47c9cSNobuhiro Iwamatsu } 17316f47c9cSNobuhiro Iwamatsu 174*22e75d6dSNobuhiro Iwamatsu ss->regs = (struct sh_qspi_regs *)SH_QSPI_BASE; 17516f47c9cSNobuhiro Iwamatsu 17616f47c9cSNobuhiro Iwamatsu /* Init SH QSPI */ 17716f47c9cSNobuhiro Iwamatsu sh_qspi_init(ss); 17816f47c9cSNobuhiro Iwamatsu 17916f47c9cSNobuhiro Iwamatsu return &ss->slave; 18016f47c9cSNobuhiro Iwamatsu } 18116f47c9cSNobuhiro Iwamatsu 18216f47c9cSNobuhiro Iwamatsu void spi_free_slave(struct spi_slave *slave) 18316f47c9cSNobuhiro Iwamatsu { 18416f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *spi = to_sh_qspi(slave); 18516f47c9cSNobuhiro Iwamatsu 18616f47c9cSNobuhiro Iwamatsu free(spi); 18716f47c9cSNobuhiro Iwamatsu } 18816f47c9cSNobuhiro Iwamatsu 18916f47c9cSNobuhiro Iwamatsu int spi_claim_bus(struct spi_slave *slave) 19016f47c9cSNobuhiro Iwamatsu { 19116f47c9cSNobuhiro Iwamatsu return 0; 19216f47c9cSNobuhiro Iwamatsu } 19316f47c9cSNobuhiro Iwamatsu 19416f47c9cSNobuhiro Iwamatsu void spi_release_bus(struct spi_slave *slave) 19516f47c9cSNobuhiro Iwamatsu { 19616f47c9cSNobuhiro Iwamatsu } 19716f47c9cSNobuhiro Iwamatsu 19816f47c9cSNobuhiro Iwamatsu int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, 19916f47c9cSNobuhiro Iwamatsu void *din, unsigned long flags) 20016f47c9cSNobuhiro Iwamatsu { 20116f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *ss = to_sh_qspi(slave); 20216f47c9cSNobuhiro Iwamatsu unsigned long nbyte; 20316f47c9cSNobuhiro Iwamatsu int ret = 0; 20416f47c9cSNobuhiro Iwamatsu unsigned char dtdata = 0, drdata; 20516f47c9cSNobuhiro Iwamatsu unsigned char *tdata = &dtdata, *rdata = &drdata; 20616f47c9cSNobuhiro Iwamatsu unsigned long *spbmul0 = &ss->regs->spbmul0; 20716f47c9cSNobuhiro Iwamatsu 20816f47c9cSNobuhiro Iwamatsu if (dout == NULL && din == NULL) { 20916f47c9cSNobuhiro Iwamatsu if (flags & SPI_XFER_END) 21016f47c9cSNobuhiro Iwamatsu spi_cs_deactivate(slave); 21116f47c9cSNobuhiro Iwamatsu return 0; 21216f47c9cSNobuhiro Iwamatsu } 21316f47c9cSNobuhiro Iwamatsu 21416f47c9cSNobuhiro Iwamatsu if (bitlen % 8) { 21516f47c9cSNobuhiro Iwamatsu printf("%s: bitlen is not 8bit alined %d", __func__, bitlen); 21616f47c9cSNobuhiro Iwamatsu return 1; 21716f47c9cSNobuhiro Iwamatsu } 21816f47c9cSNobuhiro Iwamatsu 21916f47c9cSNobuhiro Iwamatsu nbyte = bitlen / 8; 22016f47c9cSNobuhiro Iwamatsu 22116f47c9cSNobuhiro Iwamatsu if (flags & SPI_XFER_BEGIN) { 22216f47c9cSNobuhiro Iwamatsu spi_cs_activate(slave); 22316f47c9cSNobuhiro Iwamatsu 22416f47c9cSNobuhiro Iwamatsu /* Set 1048576 byte */ 22516f47c9cSNobuhiro Iwamatsu writel(0x100000, spbmul0); 22616f47c9cSNobuhiro Iwamatsu } 22716f47c9cSNobuhiro Iwamatsu 22816f47c9cSNobuhiro Iwamatsu if (flags & SPI_XFER_END) 22916f47c9cSNobuhiro Iwamatsu writel(nbyte, spbmul0); 23016f47c9cSNobuhiro Iwamatsu 23116f47c9cSNobuhiro Iwamatsu if (dout != NULL) 23216f47c9cSNobuhiro Iwamatsu tdata = (unsigned char *)dout; 23316f47c9cSNobuhiro Iwamatsu 23416f47c9cSNobuhiro Iwamatsu if (din != NULL) 23516f47c9cSNobuhiro Iwamatsu rdata = din; 23616f47c9cSNobuhiro Iwamatsu 23716f47c9cSNobuhiro Iwamatsu while (nbyte > 0) { 23816f47c9cSNobuhiro Iwamatsu while (!(readb(&ss->regs->spsr) & SPSR_SPTEF)) { 23916f47c9cSNobuhiro Iwamatsu if (ctrlc()) { 24016f47c9cSNobuhiro Iwamatsu puts("abort\n"); 24116f47c9cSNobuhiro Iwamatsu return 1; 24216f47c9cSNobuhiro Iwamatsu } 24316f47c9cSNobuhiro Iwamatsu udelay(10); 24416f47c9cSNobuhiro Iwamatsu } 24516f47c9cSNobuhiro Iwamatsu 24616f47c9cSNobuhiro Iwamatsu writeb(*tdata, (unsigned char *)(&ss->regs->spdr)); 24716f47c9cSNobuhiro Iwamatsu 24816f47c9cSNobuhiro Iwamatsu while ((readw(&ss->regs->spbdcr) != SPBDCR_RXBC0)) { 24916f47c9cSNobuhiro Iwamatsu if (ctrlc()) { 25016f47c9cSNobuhiro Iwamatsu puts("abort\n"); 25116f47c9cSNobuhiro Iwamatsu return 1; 25216f47c9cSNobuhiro Iwamatsu } 25316f47c9cSNobuhiro Iwamatsu udelay(1); 25416f47c9cSNobuhiro Iwamatsu } 25516f47c9cSNobuhiro Iwamatsu 25616f47c9cSNobuhiro Iwamatsu while (!(readb(&ss->regs->spsr) & SPSR_SPRFF)) { 25716f47c9cSNobuhiro Iwamatsu if (ctrlc()) { 25816f47c9cSNobuhiro Iwamatsu puts("abort\n"); 25916f47c9cSNobuhiro Iwamatsu return 1; 26016f47c9cSNobuhiro Iwamatsu } 26116f47c9cSNobuhiro Iwamatsu udelay(10); 26216f47c9cSNobuhiro Iwamatsu } 26316f47c9cSNobuhiro Iwamatsu 26416f47c9cSNobuhiro Iwamatsu *rdata = readb((unsigned char *)(&ss->regs->spdr)); 26516f47c9cSNobuhiro Iwamatsu 26616f47c9cSNobuhiro Iwamatsu if (dout != NULL) 26716f47c9cSNobuhiro Iwamatsu tdata++; 26816f47c9cSNobuhiro Iwamatsu if (din != NULL) 26916f47c9cSNobuhiro Iwamatsu rdata++; 27016f47c9cSNobuhiro Iwamatsu 27116f47c9cSNobuhiro Iwamatsu nbyte--; 27216f47c9cSNobuhiro Iwamatsu } 27316f47c9cSNobuhiro Iwamatsu 27416f47c9cSNobuhiro Iwamatsu if (flags & SPI_XFER_END) 27516f47c9cSNobuhiro Iwamatsu spi_cs_deactivate(slave); 27616f47c9cSNobuhiro Iwamatsu 27716f47c9cSNobuhiro Iwamatsu return ret; 27816f47c9cSNobuhiro Iwamatsu } 279