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> 1124b852a7SSimon Glass #include <console.h> 1216f47c9cSNobuhiro Iwamatsu #include <malloc.h> 1316f47c9cSNobuhiro Iwamatsu #include <spi.h> 1422e75d6dSNobuhiro Iwamatsu #include <asm/arch/rmobile.h> 1516f47c9cSNobuhiro Iwamatsu #include <asm/io.h> 1616f47c9cSNobuhiro Iwamatsu 1716f47c9cSNobuhiro Iwamatsu /* SH QSPI register bit masks <REG>_<BIT> */ 1816f47c9cSNobuhiro Iwamatsu #define SPCR_MSTR 0x08 1916f47c9cSNobuhiro Iwamatsu #define SPCR_SPE 0x40 2016f47c9cSNobuhiro Iwamatsu #define SPSR_SPRFF 0x80 2116f47c9cSNobuhiro Iwamatsu #define SPSR_SPTEF 0x20 2216f47c9cSNobuhiro Iwamatsu #define SPPCR_IO3FV 0x04 2316f47c9cSNobuhiro Iwamatsu #define SPPCR_IO2FV 0x02 2416f47c9cSNobuhiro Iwamatsu #define SPPCR_IO1FV 0x01 25ccaa9485SJagan Teki #define SPBDCR_RXBC0 BIT(0) 26ccaa9485SJagan Teki #define SPCMD_SCKDEN BIT(15) 27ccaa9485SJagan Teki #define SPCMD_SLNDEN BIT(14) 28ccaa9485SJagan Teki #define SPCMD_SPNDEN BIT(13) 29ccaa9485SJagan Teki #define SPCMD_SSLKP BIT(7) 30ccaa9485SJagan Teki #define SPCMD_BRDV0 BIT(2) 3116f47c9cSNobuhiro Iwamatsu #define SPCMD_INIT1 SPCMD_SCKDEN | SPCMD_SLNDEN | \ 3216f47c9cSNobuhiro Iwamatsu SPCMD_SPNDEN | SPCMD_SSLKP | \ 3316f47c9cSNobuhiro Iwamatsu SPCMD_BRDV0 3416f47c9cSNobuhiro Iwamatsu #define SPCMD_INIT2 SPCMD_SPNDEN | SPCMD_SSLKP | \ 3516f47c9cSNobuhiro Iwamatsu SPCMD_BRDV0 36ccaa9485SJagan Teki #define SPBFCR_TXRST BIT(7) 37ccaa9485SJagan Teki #define SPBFCR_RXRST BIT(6) 3816f47c9cSNobuhiro Iwamatsu 3916f47c9cSNobuhiro Iwamatsu /* SH QSPI register set */ 4016f47c9cSNobuhiro Iwamatsu struct sh_qspi_regs { 41*0e6fa20bSMarek Vasut u8 spcr; 42*0e6fa20bSMarek Vasut u8 sslp; 43*0e6fa20bSMarek Vasut u8 sppcr; 44*0e6fa20bSMarek Vasut u8 spsr; 45*0e6fa20bSMarek Vasut u32 spdr; 46*0e6fa20bSMarek Vasut u8 spscr; 47*0e6fa20bSMarek Vasut u8 spssr; 48*0e6fa20bSMarek Vasut u8 spbr; 49*0e6fa20bSMarek Vasut u8 spdcr; 50*0e6fa20bSMarek Vasut u8 spckd; 51*0e6fa20bSMarek Vasut u8 sslnd; 52*0e6fa20bSMarek Vasut u8 spnd; 53*0e6fa20bSMarek Vasut u8 dummy0; 54*0e6fa20bSMarek Vasut u16 spcmd0; 55*0e6fa20bSMarek Vasut u16 spcmd1; 56*0e6fa20bSMarek Vasut u16 spcmd2; 57*0e6fa20bSMarek Vasut u16 spcmd3; 58*0e6fa20bSMarek Vasut u8 spbfcr; 59*0e6fa20bSMarek Vasut u8 dummy1; 60*0e6fa20bSMarek Vasut u16 spbdcr; 61*0e6fa20bSMarek Vasut u32 spbmul0; 62*0e6fa20bSMarek Vasut u32 spbmul1; 63*0e6fa20bSMarek Vasut u32 spbmul2; 64*0e6fa20bSMarek Vasut u32 spbmul3; 6516f47c9cSNobuhiro Iwamatsu }; 6616f47c9cSNobuhiro Iwamatsu 6716f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave { 6816f47c9cSNobuhiro Iwamatsu struct spi_slave slave; 6916f47c9cSNobuhiro Iwamatsu struct sh_qspi_regs *regs; 7016f47c9cSNobuhiro Iwamatsu }; 7116f47c9cSNobuhiro Iwamatsu 7216f47c9cSNobuhiro Iwamatsu static inline struct sh_qspi_slave *to_sh_qspi(struct spi_slave *slave) 7316f47c9cSNobuhiro Iwamatsu { 7416f47c9cSNobuhiro Iwamatsu return container_of(slave, struct sh_qspi_slave, slave); 7516f47c9cSNobuhiro Iwamatsu } 7616f47c9cSNobuhiro Iwamatsu 7716f47c9cSNobuhiro Iwamatsu static void sh_qspi_init(struct sh_qspi_slave *ss) 7816f47c9cSNobuhiro Iwamatsu { 7916f47c9cSNobuhiro Iwamatsu /* QSPI initialize */ 8016f47c9cSNobuhiro Iwamatsu /* Set master mode only */ 8116f47c9cSNobuhiro Iwamatsu writeb(SPCR_MSTR, &ss->regs->spcr); 8216f47c9cSNobuhiro Iwamatsu 8316f47c9cSNobuhiro Iwamatsu /* Set SSL signal level */ 8416f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->sslp); 8516f47c9cSNobuhiro Iwamatsu 8616f47c9cSNobuhiro Iwamatsu /* Set MOSI signal value when transfer is in idle state */ 8716f47c9cSNobuhiro Iwamatsu writeb(SPPCR_IO3FV|SPPCR_IO2FV, &ss->regs->sppcr); 8816f47c9cSNobuhiro Iwamatsu 8916f47c9cSNobuhiro Iwamatsu /* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */ 9016f47c9cSNobuhiro Iwamatsu writeb(0x01, &ss->regs->spbr); 9116f47c9cSNobuhiro Iwamatsu 9216f47c9cSNobuhiro Iwamatsu /* Disable Dummy Data Transmission */ 9316f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spdcr); 9416f47c9cSNobuhiro Iwamatsu 9516f47c9cSNobuhiro Iwamatsu /* Set clock delay value */ 9616f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spckd); 9716f47c9cSNobuhiro Iwamatsu 9816f47c9cSNobuhiro Iwamatsu /* Set SSL negation delay value */ 9916f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->sslnd); 10016f47c9cSNobuhiro Iwamatsu 10116f47c9cSNobuhiro Iwamatsu /* Set next-access delay value */ 10216f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spnd); 10316f47c9cSNobuhiro Iwamatsu 10416f47c9cSNobuhiro Iwamatsu /* Set equence command */ 10516f47c9cSNobuhiro Iwamatsu writew(SPCMD_INIT2, &ss->regs->spcmd0); 10616f47c9cSNobuhiro Iwamatsu 10716f47c9cSNobuhiro Iwamatsu /* Reset transfer and receive Buffer */ 10816f47c9cSNobuhiro Iwamatsu setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST); 10916f47c9cSNobuhiro Iwamatsu 11016f47c9cSNobuhiro Iwamatsu /* Clear transfer and receive Buffer control bit */ 11116f47c9cSNobuhiro Iwamatsu clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST); 11216f47c9cSNobuhiro Iwamatsu 11316f47c9cSNobuhiro Iwamatsu /* Set equence control method. Use equence0 only */ 11416f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spscr); 11516f47c9cSNobuhiro Iwamatsu 11616f47c9cSNobuhiro Iwamatsu /* Enable SPI function */ 11716f47c9cSNobuhiro Iwamatsu setbits_8(&ss->regs->spcr, SPCR_SPE); 11816f47c9cSNobuhiro Iwamatsu } 11916f47c9cSNobuhiro Iwamatsu 12016f47c9cSNobuhiro Iwamatsu int spi_cs_is_valid(unsigned int bus, unsigned int cs) 12116f47c9cSNobuhiro Iwamatsu { 12216f47c9cSNobuhiro Iwamatsu return 1; 12316f47c9cSNobuhiro Iwamatsu } 12416f47c9cSNobuhiro Iwamatsu 12516f47c9cSNobuhiro Iwamatsu void spi_cs_activate(struct spi_slave *slave) 12616f47c9cSNobuhiro Iwamatsu { 12716f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *ss = to_sh_qspi(slave); 12816f47c9cSNobuhiro Iwamatsu 12916f47c9cSNobuhiro Iwamatsu /* Set master mode only */ 13016f47c9cSNobuhiro Iwamatsu writeb(SPCR_MSTR, &ss->regs->spcr); 13116f47c9cSNobuhiro Iwamatsu 13216f47c9cSNobuhiro Iwamatsu /* Set command */ 13316f47c9cSNobuhiro Iwamatsu writew(SPCMD_INIT1, &ss->regs->spcmd0); 13416f47c9cSNobuhiro Iwamatsu 13516f47c9cSNobuhiro Iwamatsu /* Reset transfer and receive Buffer */ 13616f47c9cSNobuhiro Iwamatsu setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST); 13716f47c9cSNobuhiro Iwamatsu 13816f47c9cSNobuhiro Iwamatsu /* Clear transfer and receive Buffer control bit */ 13916f47c9cSNobuhiro Iwamatsu clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST); 14016f47c9cSNobuhiro Iwamatsu 14116f47c9cSNobuhiro Iwamatsu /* Set equence control method. Use equence0 only */ 14216f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spscr); 14316f47c9cSNobuhiro Iwamatsu 14416f47c9cSNobuhiro Iwamatsu /* Enable SPI function */ 14516f47c9cSNobuhiro Iwamatsu setbits_8(&ss->regs->spcr, SPCR_SPE); 14616f47c9cSNobuhiro Iwamatsu } 14716f47c9cSNobuhiro Iwamatsu 14816f47c9cSNobuhiro Iwamatsu void spi_cs_deactivate(struct spi_slave *slave) 14916f47c9cSNobuhiro Iwamatsu { 15016f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *ss = to_sh_qspi(slave); 15116f47c9cSNobuhiro Iwamatsu 15216f47c9cSNobuhiro Iwamatsu /* Disable SPI Function */ 15316f47c9cSNobuhiro Iwamatsu clrbits_8(&ss->regs->spcr, SPCR_SPE); 15416f47c9cSNobuhiro Iwamatsu } 15516f47c9cSNobuhiro Iwamatsu 15616f47c9cSNobuhiro Iwamatsu void spi_init(void) 15716f47c9cSNobuhiro Iwamatsu { 15816f47c9cSNobuhiro Iwamatsu /* nothing to do */ 15916f47c9cSNobuhiro Iwamatsu } 16016f47c9cSNobuhiro Iwamatsu 16116f47c9cSNobuhiro Iwamatsu struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, 16216f47c9cSNobuhiro Iwamatsu unsigned int max_hz, unsigned int mode) 16316f47c9cSNobuhiro Iwamatsu { 16416f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *ss; 16516f47c9cSNobuhiro Iwamatsu 16616f47c9cSNobuhiro Iwamatsu if (!spi_cs_is_valid(bus, cs)) 16716f47c9cSNobuhiro Iwamatsu return NULL; 16816f47c9cSNobuhiro Iwamatsu 16916f47c9cSNobuhiro Iwamatsu ss = spi_alloc_slave(struct sh_qspi_slave, bus, cs); 17016f47c9cSNobuhiro Iwamatsu if (!ss) { 17116f47c9cSNobuhiro Iwamatsu printf("SPI_error: Fail to allocate sh_qspi_slave\n"); 17216f47c9cSNobuhiro Iwamatsu return NULL; 17316f47c9cSNobuhiro Iwamatsu } 17416f47c9cSNobuhiro Iwamatsu 17522e75d6dSNobuhiro Iwamatsu ss->regs = (struct sh_qspi_regs *)SH_QSPI_BASE; 17616f47c9cSNobuhiro Iwamatsu 17716f47c9cSNobuhiro Iwamatsu /* Init SH QSPI */ 17816f47c9cSNobuhiro Iwamatsu sh_qspi_init(ss); 17916f47c9cSNobuhiro Iwamatsu 18016f47c9cSNobuhiro Iwamatsu return &ss->slave; 18116f47c9cSNobuhiro Iwamatsu } 18216f47c9cSNobuhiro Iwamatsu 18316f47c9cSNobuhiro Iwamatsu void spi_free_slave(struct spi_slave *slave) 18416f47c9cSNobuhiro Iwamatsu { 18516f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *spi = to_sh_qspi(slave); 18616f47c9cSNobuhiro Iwamatsu 18716f47c9cSNobuhiro Iwamatsu free(spi); 18816f47c9cSNobuhiro Iwamatsu } 18916f47c9cSNobuhiro Iwamatsu 19016f47c9cSNobuhiro Iwamatsu int spi_claim_bus(struct spi_slave *slave) 19116f47c9cSNobuhiro Iwamatsu { 19216f47c9cSNobuhiro Iwamatsu return 0; 19316f47c9cSNobuhiro Iwamatsu } 19416f47c9cSNobuhiro Iwamatsu 19516f47c9cSNobuhiro Iwamatsu void spi_release_bus(struct spi_slave *slave) 19616f47c9cSNobuhiro Iwamatsu { 19716f47c9cSNobuhiro Iwamatsu } 19816f47c9cSNobuhiro Iwamatsu 19916f47c9cSNobuhiro Iwamatsu int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, 20016f47c9cSNobuhiro Iwamatsu void *din, unsigned long flags) 20116f47c9cSNobuhiro Iwamatsu { 20216f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *ss = to_sh_qspi(slave); 203*0e6fa20bSMarek Vasut u32 nbyte; 20416f47c9cSNobuhiro Iwamatsu int ret = 0; 205*0e6fa20bSMarek Vasut u8 dtdata = 0, drdata; 206*0e6fa20bSMarek Vasut u8 *tdata = &dtdata, *rdata = &drdata; 207*0e6fa20bSMarek Vasut u32 *spbmul0 = &ss->regs->spbmul0; 20816f47c9cSNobuhiro Iwamatsu 20916f47c9cSNobuhiro Iwamatsu if (dout == NULL && din == NULL) { 21016f47c9cSNobuhiro Iwamatsu if (flags & SPI_XFER_END) 21116f47c9cSNobuhiro Iwamatsu spi_cs_deactivate(slave); 21216f47c9cSNobuhiro Iwamatsu return 0; 21316f47c9cSNobuhiro Iwamatsu } 21416f47c9cSNobuhiro Iwamatsu 21516f47c9cSNobuhiro Iwamatsu if (bitlen % 8) { 21616f47c9cSNobuhiro Iwamatsu printf("%s: bitlen is not 8bit alined %d", __func__, bitlen); 21716f47c9cSNobuhiro Iwamatsu return 1; 21816f47c9cSNobuhiro Iwamatsu } 21916f47c9cSNobuhiro Iwamatsu 22016f47c9cSNobuhiro Iwamatsu nbyte = bitlen / 8; 22116f47c9cSNobuhiro Iwamatsu 22216f47c9cSNobuhiro Iwamatsu if (flags & SPI_XFER_BEGIN) { 22316f47c9cSNobuhiro Iwamatsu spi_cs_activate(slave); 22416f47c9cSNobuhiro Iwamatsu 22516f47c9cSNobuhiro Iwamatsu /* Set 1048576 byte */ 22616f47c9cSNobuhiro Iwamatsu writel(0x100000, spbmul0); 22716f47c9cSNobuhiro Iwamatsu } 22816f47c9cSNobuhiro Iwamatsu 22916f47c9cSNobuhiro Iwamatsu if (flags & SPI_XFER_END) 23016f47c9cSNobuhiro Iwamatsu writel(nbyte, spbmul0); 23116f47c9cSNobuhiro Iwamatsu 23216f47c9cSNobuhiro Iwamatsu if (dout != NULL) 233*0e6fa20bSMarek Vasut tdata = (u8 *)dout; 23416f47c9cSNobuhiro Iwamatsu 23516f47c9cSNobuhiro Iwamatsu if (din != NULL) 23616f47c9cSNobuhiro Iwamatsu rdata = din; 23716f47c9cSNobuhiro Iwamatsu 23816f47c9cSNobuhiro Iwamatsu while (nbyte > 0) { 23916f47c9cSNobuhiro Iwamatsu while (!(readb(&ss->regs->spsr) & SPSR_SPTEF)) { 24016f47c9cSNobuhiro Iwamatsu if (ctrlc()) { 24116f47c9cSNobuhiro Iwamatsu puts("abort\n"); 24216f47c9cSNobuhiro Iwamatsu return 1; 24316f47c9cSNobuhiro Iwamatsu } 24416f47c9cSNobuhiro Iwamatsu udelay(10); 24516f47c9cSNobuhiro Iwamatsu } 24616f47c9cSNobuhiro Iwamatsu 247*0e6fa20bSMarek Vasut writeb(*tdata, (u8 *)(&ss->regs->spdr)); 24816f47c9cSNobuhiro Iwamatsu 24916f47c9cSNobuhiro Iwamatsu while ((readw(&ss->regs->spbdcr) != SPBDCR_RXBC0)) { 25016f47c9cSNobuhiro Iwamatsu if (ctrlc()) { 25116f47c9cSNobuhiro Iwamatsu puts("abort\n"); 25216f47c9cSNobuhiro Iwamatsu return 1; 25316f47c9cSNobuhiro Iwamatsu } 25416f47c9cSNobuhiro Iwamatsu udelay(1); 25516f47c9cSNobuhiro Iwamatsu } 25616f47c9cSNobuhiro Iwamatsu 25716f47c9cSNobuhiro Iwamatsu while (!(readb(&ss->regs->spsr) & SPSR_SPRFF)) { 25816f47c9cSNobuhiro Iwamatsu if (ctrlc()) { 25916f47c9cSNobuhiro Iwamatsu puts("abort\n"); 26016f47c9cSNobuhiro Iwamatsu return 1; 26116f47c9cSNobuhiro Iwamatsu } 26216f47c9cSNobuhiro Iwamatsu udelay(10); 26316f47c9cSNobuhiro Iwamatsu } 26416f47c9cSNobuhiro Iwamatsu 265*0e6fa20bSMarek Vasut *rdata = readb((u8 *)(&ss->regs->spdr)); 26616f47c9cSNobuhiro Iwamatsu 26716f47c9cSNobuhiro Iwamatsu if (dout != NULL) 26816f47c9cSNobuhiro Iwamatsu tdata++; 26916f47c9cSNobuhiro Iwamatsu if (din != NULL) 27016f47c9cSNobuhiro Iwamatsu rdata++; 27116f47c9cSNobuhiro Iwamatsu 27216f47c9cSNobuhiro Iwamatsu nbyte--; 27316f47c9cSNobuhiro Iwamatsu } 27416f47c9cSNobuhiro Iwamatsu 27516f47c9cSNobuhiro Iwamatsu if (flags & SPI_XFER_END) 27616f47c9cSNobuhiro Iwamatsu spi_cs_deactivate(slave); 27716f47c9cSNobuhiro Iwamatsu 27816f47c9cSNobuhiro Iwamatsu return ret; 27916f47c9cSNobuhiro Iwamatsu } 280