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>
149d14f4efSMarek Vasut #include <wait_bit.h>
1522e75d6dSNobuhiro Iwamatsu #include <asm/arch/rmobile.h>
1616f47c9cSNobuhiro Iwamatsu #include <asm/io.h>
1716f47c9cSNobuhiro Iwamatsu
1816f47c9cSNobuhiro Iwamatsu /* SH QSPI register bit masks <REG>_<BIT> */
1916f47c9cSNobuhiro Iwamatsu #define SPCR_MSTR 0x08
2016f47c9cSNobuhiro Iwamatsu #define SPCR_SPE 0x40
2116f47c9cSNobuhiro Iwamatsu #define SPSR_SPRFF 0x80
2216f47c9cSNobuhiro Iwamatsu #define SPSR_SPTEF 0x20
2316f47c9cSNobuhiro Iwamatsu #define SPPCR_IO3FV 0x04
2416f47c9cSNobuhiro Iwamatsu #define SPPCR_IO2FV 0x02
2516f47c9cSNobuhiro Iwamatsu #define SPPCR_IO1FV 0x01
26ccaa9485SJagan Teki #define SPBDCR_RXBC0 BIT(0)
27ccaa9485SJagan Teki #define SPCMD_SCKDEN BIT(15)
28ccaa9485SJagan Teki #define SPCMD_SLNDEN BIT(14)
29ccaa9485SJagan Teki #define SPCMD_SPNDEN BIT(13)
30ccaa9485SJagan Teki #define SPCMD_SSLKP BIT(7)
31ccaa9485SJagan Teki #define SPCMD_BRDV0 BIT(2)
3216f47c9cSNobuhiro Iwamatsu #define SPCMD_INIT1 SPCMD_SCKDEN | SPCMD_SLNDEN | \
3316f47c9cSNobuhiro Iwamatsu SPCMD_SPNDEN | SPCMD_SSLKP | \
3416f47c9cSNobuhiro Iwamatsu SPCMD_BRDV0
3516f47c9cSNobuhiro Iwamatsu #define SPCMD_INIT2 SPCMD_SPNDEN | SPCMD_SSLKP | \
3616f47c9cSNobuhiro Iwamatsu SPCMD_BRDV0
37ccaa9485SJagan Teki #define SPBFCR_TXRST BIT(7)
38ccaa9485SJagan Teki #define SPBFCR_RXRST BIT(6)
39*7f3cd1e4SMarek Vasut #define SPBFCR_TXTRG 0x30
40*7f3cd1e4SMarek Vasut #define SPBFCR_RXTRG 0x07
4116f47c9cSNobuhiro Iwamatsu
4216f47c9cSNobuhiro Iwamatsu /* SH QSPI register set */
4316f47c9cSNobuhiro Iwamatsu struct sh_qspi_regs {
447950bf5eSMarek Vasut u8 spcr;
457950bf5eSMarek Vasut u8 sslp;
467950bf5eSMarek Vasut u8 sppcr;
477950bf5eSMarek Vasut u8 spsr;
487950bf5eSMarek Vasut u32 spdr;
497950bf5eSMarek Vasut u8 spscr;
507950bf5eSMarek Vasut u8 spssr;
517950bf5eSMarek Vasut u8 spbr;
527950bf5eSMarek Vasut u8 spdcr;
537950bf5eSMarek Vasut u8 spckd;
547950bf5eSMarek Vasut u8 sslnd;
557950bf5eSMarek Vasut u8 spnd;
567950bf5eSMarek Vasut u8 dummy0;
577950bf5eSMarek Vasut u16 spcmd0;
587950bf5eSMarek Vasut u16 spcmd1;
597950bf5eSMarek Vasut u16 spcmd2;
607950bf5eSMarek Vasut u16 spcmd3;
617950bf5eSMarek Vasut u8 spbfcr;
627950bf5eSMarek Vasut u8 dummy1;
637950bf5eSMarek Vasut u16 spbdcr;
647950bf5eSMarek Vasut u32 spbmul0;
657950bf5eSMarek Vasut u32 spbmul1;
667950bf5eSMarek Vasut u32 spbmul2;
677950bf5eSMarek Vasut u32 spbmul3;
6816f47c9cSNobuhiro Iwamatsu };
6916f47c9cSNobuhiro Iwamatsu
7016f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave {
7116f47c9cSNobuhiro Iwamatsu struct spi_slave slave;
7216f47c9cSNobuhiro Iwamatsu struct sh_qspi_regs *regs;
7316f47c9cSNobuhiro Iwamatsu };
7416f47c9cSNobuhiro Iwamatsu
to_sh_qspi(struct spi_slave * slave)7516f47c9cSNobuhiro Iwamatsu static inline struct sh_qspi_slave *to_sh_qspi(struct spi_slave *slave)
7616f47c9cSNobuhiro Iwamatsu {
7716f47c9cSNobuhiro Iwamatsu return container_of(slave, struct sh_qspi_slave, slave);
7816f47c9cSNobuhiro Iwamatsu }
7916f47c9cSNobuhiro Iwamatsu
sh_qspi_init(struct sh_qspi_slave * ss)8016f47c9cSNobuhiro Iwamatsu static void sh_qspi_init(struct sh_qspi_slave *ss)
8116f47c9cSNobuhiro Iwamatsu {
8216f47c9cSNobuhiro Iwamatsu /* QSPI initialize */
8316f47c9cSNobuhiro Iwamatsu /* Set master mode only */
8416f47c9cSNobuhiro Iwamatsu writeb(SPCR_MSTR, &ss->regs->spcr);
8516f47c9cSNobuhiro Iwamatsu
8616f47c9cSNobuhiro Iwamatsu /* Set SSL signal level */
8716f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->sslp);
8816f47c9cSNobuhiro Iwamatsu
8916f47c9cSNobuhiro Iwamatsu /* Set MOSI signal value when transfer is in idle state */
9016f47c9cSNobuhiro Iwamatsu writeb(SPPCR_IO3FV|SPPCR_IO2FV, &ss->regs->sppcr);
9116f47c9cSNobuhiro Iwamatsu
9216f47c9cSNobuhiro Iwamatsu /* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */
9316f47c9cSNobuhiro Iwamatsu writeb(0x01, &ss->regs->spbr);
9416f47c9cSNobuhiro Iwamatsu
9516f47c9cSNobuhiro Iwamatsu /* Disable Dummy Data Transmission */
9616f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spdcr);
9716f47c9cSNobuhiro Iwamatsu
9816f47c9cSNobuhiro Iwamatsu /* Set clock delay value */
9916f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spckd);
10016f47c9cSNobuhiro Iwamatsu
10116f47c9cSNobuhiro Iwamatsu /* Set SSL negation delay value */
10216f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->sslnd);
10316f47c9cSNobuhiro Iwamatsu
10416f47c9cSNobuhiro Iwamatsu /* Set next-access delay value */
10516f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spnd);
10616f47c9cSNobuhiro Iwamatsu
10716f47c9cSNobuhiro Iwamatsu /* Set equence command */
10816f47c9cSNobuhiro Iwamatsu writew(SPCMD_INIT2, &ss->regs->spcmd0);
10916f47c9cSNobuhiro Iwamatsu
11016f47c9cSNobuhiro Iwamatsu /* Reset transfer and receive Buffer */
11116f47c9cSNobuhiro Iwamatsu setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
11216f47c9cSNobuhiro Iwamatsu
11316f47c9cSNobuhiro Iwamatsu /* Clear transfer and receive Buffer control bit */
11416f47c9cSNobuhiro Iwamatsu clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
11516f47c9cSNobuhiro Iwamatsu
11616f47c9cSNobuhiro Iwamatsu /* Set equence control method. Use equence0 only */
11716f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spscr);
11816f47c9cSNobuhiro Iwamatsu
11916f47c9cSNobuhiro Iwamatsu /* Enable SPI function */
12016f47c9cSNobuhiro Iwamatsu setbits_8(&ss->regs->spcr, SPCR_SPE);
12116f47c9cSNobuhiro Iwamatsu }
12216f47c9cSNobuhiro Iwamatsu
spi_cs_is_valid(unsigned int bus,unsigned int cs)12316f47c9cSNobuhiro Iwamatsu int spi_cs_is_valid(unsigned int bus, unsigned int cs)
12416f47c9cSNobuhiro Iwamatsu {
12516f47c9cSNobuhiro Iwamatsu return 1;
12616f47c9cSNobuhiro Iwamatsu }
12716f47c9cSNobuhiro Iwamatsu
spi_cs_activate(struct spi_slave * slave)12816f47c9cSNobuhiro Iwamatsu void spi_cs_activate(struct spi_slave *slave)
12916f47c9cSNobuhiro Iwamatsu {
13016f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *ss = to_sh_qspi(slave);
13116f47c9cSNobuhiro Iwamatsu
13216f47c9cSNobuhiro Iwamatsu /* Set master mode only */
13316f47c9cSNobuhiro Iwamatsu writeb(SPCR_MSTR, &ss->regs->spcr);
13416f47c9cSNobuhiro Iwamatsu
13516f47c9cSNobuhiro Iwamatsu /* Set command */
13616f47c9cSNobuhiro Iwamatsu writew(SPCMD_INIT1, &ss->regs->spcmd0);
13716f47c9cSNobuhiro Iwamatsu
13816f47c9cSNobuhiro Iwamatsu /* Reset transfer and receive Buffer */
13916f47c9cSNobuhiro Iwamatsu setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
14016f47c9cSNobuhiro Iwamatsu
14116f47c9cSNobuhiro Iwamatsu /* Clear transfer and receive Buffer control bit */
14216f47c9cSNobuhiro Iwamatsu clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
14316f47c9cSNobuhiro Iwamatsu
14416f47c9cSNobuhiro Iwamatsu /* Set equence control method. Use equence0 only */
14516f47c9cSNobuhiro Iwamatsu writeb(0x00, &ss->regs->spscr);
14616f47c9cSNobuhiro Iwamatsu
14716f47c9cSNobuhiro Iwamatsu /* Enable SPI function */
14816f47c9cSNobuhiro Iwamatsu setbits_8(&ss->regs->spcr, SPCR_SPE);
14916f47c9cSNobuhiro Iwamatsu }
15016f47c9cSNobuhiro Iwamatsu
spi_cs_deactivate(struct spi_slave * slave)15116f47c9cSNobuhiro Iwamatsu void spi_cs_deactivate(struct spi_slave *slave)
15216f47c9cSNobuhiro Iwamatsu {
15316f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *ss = to_sh_qspi(slave);
15416f47c9cSNobuhiro Iwamatsu
15516f47c9cSNobuhiro Iwamatsu /* Disable SPI Function */
15616f47c9cSNobuhiro Iwamatsu clrbits_8(&ss->regs->spcr, SPCR_SPE);
15716f47c9cSNobuhiro Iwamatsu }
15816f47c9cSNobuhiro Iwamatsu
spi_init(void)15916f47c9cSNobuhiro Iwamatsu void spi_init(void)
16016f47c9cSNobuhiro Iwamatsu {
16116f47c9cSNobuhiro Iwamatsu /* nothing to do */
16216f47c9cSNobuhiro Iwamatsu }
16316f47c9cSNobuhiro Iwamatsu
spi_setup_slave(unsigned int bus,unsigned int cs,unsigned int max_hz,unsigned int mode)16416f47c9cSNobuhiro Iwamatsu struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
16516f47c9cSNobuhiro Iwamatsu unsigned int max_hz, unsigned int mode)
16616f47c9cSNobuhiro Iwamatsu {
16716f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *ss;
16816f47c9cSNobuhiro Iwamatsu
16916f47c9cSNobuhiro Iwamatsu if (!spi_cs_is_valid(bus, cs))
17016f47c9cSNobuhiro Iwamatsu return NULL;
17116f47c9cSNobuhiro Iwamatsu
17216f47c9cSNobuhiro Iwamatsu ss = spi_alloc_slave(struct sh_qspi_slave, bus, cs);
17316f47c9cSNobuhiro Iwamatsu if (!ss) {
17416f47c9cSNobuhiro Iwamatsu printf("SPI_error: Fail to allocate sh_qspi_slave\n");
17516f47c9cSNobuhiro Iwamatsu return NULL;
17616f47c9cSNobuhiro Iwamatsu }
17716f47c9cSNobuhiro Iwamatsu
17822e75d6dSNobuhiro Iwamatsu ss->regs = (struct sh_qspi_regs *)SH_QSPI_BASE;
17916f47c9cSNobuhiro Iwamatsu
18016f47c9cSNobuhiro Iwamatsu /* Init SH QSPI */
18116f47c9cSNobuhiro Iwamatsu sh_qspi_init(ss);
18216f47c9cSNobuhiro Iwamatsu
18316f47c9cSNobuhiro Iwamatsu return &ss->slave;
18416f47c9cSNobuhiro Iwamatsu }
18516f47c9cSNobuhiro Iwamatsu
spi_free_slave(struct spi_slave * slave)18616f47c9cSNobuhiro Iwamatsu void spi_free_slave(struct spi_slave *slave)
18716f47c9cSNobuhiro Iwamatsu {
18816f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *spi = to_sh_qspi(slave);
18916f47c9cSNobuhiro Iwamatsu
19016f47c9cSNobuhiro Iwamatsu free(spi);
19116f47c9cSNobuhiro Iwamatsu }
19216f47c9cSNobuhiro Iwamatsu
spi_claim_bus(struct spi_slave * slave)19316f47c9cSNobuhiro Iwamatsu int spi_claim_bus(struct spi_slave *slave)
19416f47c9cSNobuhiro Iwamatsu {
19516f47c9cSNobuhiro Iwamatsu return 0;
19616f47c9cSNobuhiro Iwamatsu }
19716f47c9cSNobuhiro Iwamatsu
spi_release_bus(struct spi_slave * slave)19816f47c9cSNobuhiro Iwamatsu void spi_release_bus(struct spi_slave *slave)
19916f47c9cSNobuhiro Iwamatsu {
20016f47c9cSNobuhiro Iwamatsu }
20116f47c9cSNobuhiro Iwamatsu
spi_xfer(struct spi_slave * slave,unsigned int bitlen,const void * dout,void * din,unsigned long flags)20216f47c9cSNobuhiro Iwamatsu int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
20316f47c9cSNobuhiro Iwamatsu void *din, unsigned long flags)
20416f47c9cSNobuhiro Iwamatsu {
20516f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave *ss = to_sh_qspi(slave);
206*7f3cd1e4SMarek Vasut u32 nbyte, chunk;
207*7f3cd1e4SMarek Vasut int i, ret = 0;
2087950bf5eSMarek Vasut u8 dtdata = 0, drdata;
2097950bf5eSMarek Vasut u8 *tdata = &dtdata, *rdata = &drdata;
2107950bf5eSMarek Vasut u32 *spbmul0 = &ss->regs->spbmul0;
21116f47c9cSNobuhiro Iwamatsu
21216f47c9cSNobuhiro Iwamatsu if (dout == NULL && din == NULL) {
21316f47c9cSNobuhiro Iwamatsu if (flags & SPI_XFER_END)
21416f47c9cSNobuhiro Iwamatsu spi_cs_deactivate(slave);
21516f47c9cSNobuhiro Iwamatsu return 0;
21616f47c9cSNobuhiro Iwamatsu }
21716f47c9cSNobuhiro Iwamatsu
21816f47c9cSNobuhiro Iwamatsu if (bitlen % 8) {
21916f47c9cSNobuhiro Iwamatsu printf("%s: bitlen is not 8bit alined %d", __func__, bitlen);
22016f47c9cSNobuhiro Iwamatsu return 1;
22116f47c9cSNobuhiro Iwamatsu }
22216f47c9cSNobuhiro Iwamatsu
22316f47c9cSNobuhiro Iwamatsu nbyte = bitlen / 8;
22416f47c9cSNobuhiro Iwamatsu
22516f47c9cSNobuhiro Iwamatsu if (flags & SPI_XFER_BEGIN) {
22616f47c9cSNobuhiro Iwamatsu spi_cs_activate(slave);
22716f47c9cSNobuhiro Iwamatsu
22816f47c9cSNobuhiro Iwamatsu /* Set 1048576 byte */
22916f47c9cSNobuhiro Iwamatsu writel(0x100000, spbmul0);
23016f47c9cSNobuhiro Iwamatsu }
23116f47c9cSNobuhiro Iwamatsu
23216f47c9cSNobuhiro Iwamatsu if (flags & SPI_XFER_END)
23316f47c9cSNobuhiro Iwamatsu writel(nbyte, spbmul0);
23416f47c9cSNobuhiro Iwamatsu
23516f47c9cSNobuhiro Iwamatsu if (dout != NULL)
2367950bf5eSMarek Vasut tdata = (u8 *)dout;
23716f47c9cSNobuhiro Iwamatsu
23816f47c9cSNobuhiro Iwamatsu if (din != NULL)
23916f47c9cSNobuhiro Iwamatsu rdata = din;
24016f47c9cSNobuhiro Iwamatsu
24116f47c9cSNobuhiro Iwamatsu while (nbyte > 0) {
242*7f3cd1e4SMarek Vasut /*
243*7f3cd1e4SMarek Vasut * Check if there is 32 Byte chunk and if there is, transfer
244*7f3cd1e4SMarek Vasut * it in one burst, otherwise transfer on byte-by-byte basis.
245*7f3cd1e4SMarek Vasut */
246*7f3cd1e4SMarek Vasut chunk = (nbyte >= 32) ? 32 : 1;
247*7f3cd1e4SMarek Vasut
248*7f3cd1e4SMarek Vasut clrsetbits_8(&ss->regs->spbfcr, SPBFCR_TXTRG | SPBFCR_RXTRG,
249*7f3cd1e4SMarek Vasut chunk == 32 ? SPBFCR_TXTRG | SPBFCR_RXTRG : 0);
250*7f3cd1e4SMarek Vasut
2519d14f4efSMarek Vasut ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPTEF,
2529d14f4efSMarek Vasut true, 1000, true);
2539d14f4efSMarek Vasut if (ret)
2549d14f4efSMarek Vasut return ret;
25516f47c9cSNobuhiro Iwamatsu
256*7f3cd1e4SMarek Vasut for (i = 0; i < chunk; i++) {
257*7f3cd1e4SMarek Vasut writeb(*tdata, &ss->regs->spdr);
258*7f3cd1e4SMarek Vasut if (dout != NULL)
259*7f3cd1e4SMarek Vasut tdata++;
260*7f3cd1e4SMarek Vasut }
26116f47c9cSNobuhiro Iwamatsu
2629d14f4efSMarek Vasut ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPRFF,
2639d14f4efSMarek Vasut true, 1000, true);
2649d14f4efSMarek Vasut if (ret)
2659d14f4efSMarek Vasut return ret;
26616f47c9cSNobuhiro Iwamatsu
267*7f3cd1e4SMarek Vasut for (i = 0; i < chunk; i++) {
268*7f3cd1e4SMarek Vasut *rdata = readb(&ss->regs->spdr);
26916f47c9cSNobuhiro Iwamatsu if (din != NULL)
27016f47c9cSNobuhiro Iwamatsu rdata++;
271*7f3cd1e4SMarek Vasut }
27216f47c9cSNobuhiro Iwamatsu
273*7f3cd1e4SMarek Vasut nbyte -= chunk;
27416f47c9cSNobuhiro Iwamatsu }
27516f47c9cSNobuhiro Iwamatsu
27616f47c9cSNobuhiro Iwamatsu if (flags & SPI_XFER_END)
27716f47c9cSNobuhiro Iwamatsu spi_cs_deactivate(slave);
27816f47c9cSNobuhiro Iwamatsu
27916f47c9cSNobuhiro Iwamatsu return ret;
28016f47c9cSNobuhiro Iwamatsu }
281