xref: /openbmc/u-boot/drivers/spi/sh_qspi.c (revision 9573db65)
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>
14*9573db65SMarek 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)
3916f47c9cSNobuhiro Iwamatsu 
4016f47c9cSNobuhiro Iwamatsu /* SH QSPI register set */
4116f47c9cSNobuhiro Iwamatsu struct sh_qspi_regs {
420e6fa20bSMarek Vasut 	u8	spcr;
430e6fa20bSMarek Vasut 	u8	sslp;
440e6fa20bSMarek Vasut 	u8	sppcr;
450e6fa20bSMarek Vasut 	u8	spsr;
460e6fa20bSMarek Vasut 	u32	spdr;
470e6fa20bSMarek Vasut 	u8	spscr;
480e6fa20bSMarek Vasut 	u8	spssr;
490e6fa20bSMarek Vasut 	u8	spbr;
500e6fa20bSMarek Vasut 	u8	spdcr;
510e6fa20bSMarek Vasut 	u8	spckd;
520e6fa20bSMarek Vasut 	u8	sslnd;
530e6fa20bSMarek Vasut 	u8	spnd;
540e6fa20bSMarek Vasut 	u8	dummy0;
550e6fa20bSMarek Vasut 	u16	spcmd0;
560e6fa20bSMarek Vasut 	u16	spcmd1;
570e6fa20bSMarek Vasut 	u16	spcmd2;
580e6fa20bSMarek Vasut 	u16	spcmd3;
590e6fa20bSMarek Vasut 	u8	spbfcr;
600e6fa20bSMarek Vasut 	u8	dummy1;
610e6fa20bSMarek Vasut 	u16	spbdcr;
620e6fa20bSMarek Vasut 	u32	spbmul0;
630e6fa20bSMarek Vasut 	u32	spbmul1;
640e6fa20bSMarek Vasut 	u32	spbmul2;
650e6fa20bSMarek Vasut 	u32	spbmul3;
6616f47c9cSNobuhiro Iwamatsu };
6716f47c9cSNobuhiro Iwamatsu 
6816f47c9cSNobuhiro Iwamatsu struct sh_qspi_slave {
6916f47c9cSNobuhiro Iwamatsu 	struct spi_slave	slave;
7016f47c9cSNobuhiro Iwamatsu 	struct sh_qspi_regs	*regs;
7116f47c9cSNobuhiro Iwamatsu };
7216f47c9cSNobuhiro Iwamatsu 
7316f47c9cSNobuhiro Iwamatsu static inline struct sh_qspi_slave *to_sh_qspi(struct spi_slave *slave)
7416f47c9cSNobuhiro Iwamatsu {
7516f47c9cSNobuhiro Iwamatsu 	return container_of(slave, struct sh_qspi_slave, slave);
7616f47c9cSNobuhiro Iwamatsu }
7716f47c9cSNobuhiro Iwamatsu 
7816f47c9cSNobuhiro Iwamatsu static void sh_qspi_init(struct sh_qspi_slave *ss)
7916f47c9cSNobuhiro Iwamatsu {
8016f47c9cSNobuhiro Iwamatsu 	/* QSPI initialize */
8116f47c9cSNobuhiro Iwamatsu 	/* Set master mode only */
8216f47c9cSNobuhiro Iwamatsu 	writeb(SPCR_MSTR, &ss->regs->spcr);
8316f47c9cSNobuhiro Iwamatsu 
8416f47c9cSNobuhiro Iwamatsu 	/* Set SSL signal level */
8516f47c9cSNobuhiro Iwamatsu 	writeb(0x00, &ss->regs->sslp);
8616f47c9cSNobuhiro Iwamatsu 
8716f47c9cSNobuhiro Iwamatsu 	/* Set MOSI signal value when transfer is in idle state */
8816f47c9cSNobuhiro Iwamatsu 	writeb(SPPCR_IO3FV|SPPCR_IO2FV, &ss->regs->sppcr);
8916f47c9cSNobuhiro Iwamatsu 
9016f47c9cSNobuhiro Iwamatsu 	/* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */
9116f47c9cSNobuhiro Iwamatsu 	writeb(0x01, &ss->regs->spbr);
9216f47c9cSNobuhiro Iwamatsu 
9316f47c9cSNobuhiro Iwamatsu 	/* Disable Dummy Data Transmission */
9416f47c9cSNobuhiro Iwamatsu 	writeb(0x00, &ss->regs->spdcr);
9516f47c9cSNobuhiro Iwamatsu 
9616f47c9cSNobuhiro Iwamatsu 	/* Set clock delay value */
9716f47c9cSNobuhiro Iwamatsu 	writeb(0x00, &ss->regs->spckd);
9816f47c9cSNobuhiro Iwamatsu 
9916f47c9cSNobuhiro Iwamatsu 	/* Set SSL negation delay value */
10016f47c9cSNobuhiro Iwamatsu 	writeb(0x00, &ss->regs->sslnd);
10116f47c9cSNobuhiro Iwamatsu 
10216f47c9cSNobuhiro Iwamatsu 	/* Set next-access delay value */
10316f47c9cSNobuhiro Iwamatsu 	writeb(0x00, &ss->regs->spnd);
10416f47c9cSNobuhiro Iwamatsu 
10516f47c9cSNobuhiro Iwamatsu 	/* Set equence command */
10616f47c9cSNobuhiro Iwamatsu 	writew(SPCMD_INIT2, &ss->regs->spcmd0);
10716f47c9cSNobuhiro Iwamatsu 
10816f47c9cSNobuhiro Iwamatsu 	/* Reset transfer and receive Buffer */
10916f47c9cSNobuhiro Iwamatsu 	setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
11016f47c9cSNobuhiro Iwamatsu 
11116f47c9cSNobuhiro Iwamatsu 	/* Clear transfer and receive Buffer control bit */
11216f47c9cSNobuhiro Iwamatsu 	clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
11316f47c9cSNobuhiro Iwamatsu 
11416f47c9cSNobuhiro Iwamatsu 	/* Set equence control method. Use equence0 only */
11516f47c9cSNobuhiro Iwamatsu 	writeb(0x00, &ss->regs->spscr);
11616f47c9cSNobuhiro Iwamatsu 
11716f47c9cSNobuhiro Iwamatsu 	/* Enable SPI function */
11816f47c9cSNobuhiro Iwamatsu 	setbits_8(&ss->regs->spcr, SPCR_SPE);
11916f47c9cSNobuhiro Iwamatsu }
12016f47c9cSNobuhiro Iwamatsu 
12116f47c9cSNobuhiro Iwamatsu int spi_cs_is_valid(unsigned int bus, unsigned int cs)
12216f47c9cSNobuhiro Iwamatsu {
12316f47c9cSNobuhiro Iwamatsu 	return 1;
12416f47c9cSNobuhiro Iwamatsu }
12516f47c9cSNobuhiro Iwamatsu 
12616f47c9cSNobuhiro Iwamatsu void spi_cs_activate(struct spi_slave *slave)
12716f47c9cSNobuhiro Iwamatsu {
12816f47c9cSNobuhiro Iwamatsu 	struct sh_qspi_slave *ss = to_sh_qspi(slave);
12916f47c9cSNobuhiro Iwamatsu 
13016f47c9cSNobuhiro Iwamatsu 	/* Set master mode only */
13116f47c9cSNobuhiro Iwamatsu 	writeb(SPCR_MSTR, &ss->regs->spcr);
13216f47c9cSNobuhiro Iwamatsu 
13316f47c9cSNobuhiro Iwamatsu 	/* Set command */
13416f47c9cSNobuhiro Iwamatsu 	writew(SPCMD_INIT1, &ss->regs->spcmd0);
13516f47c9cSNobuhiro Iwamatsu 
13616f47c9cSNobuhiro Iwamatsu 	/* Reset transfer and receive Buffer */
13716f47c9cSNobuhiro Iwamatsu 	setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
13816f47c9cSNobuhiro Iwamatsu 
13916f47c9cSNobuhiro Iwamatsu 	/* Clear transfer and receive Buffer control bit */
14016f47c9cSNobuhiro Iwamatsu 	clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
14116f47c9cSNobuhiro Iwamatsu 
14216f47c9cSNobuhiro Iwamatsu 	/* Set equence control method. Use equence0 only */
14316f47c9cSNobuhiro Iwamatsu 	writeb(0x00, &ss->regs->spscr);
14416f47c9cSNobuhiro Iwamatsu 
14516f47c9cSNobuhiro Iwamatsu 	/* Enable SPI function */
14616f47c9cSNobuhiro Iwamatsu 	setbits_8(&ss->regs->spcr, SPCR_SPE);
14716f47c9cSNobuhiro Iwamatsu }
14816f47c9cSNobuhiro Iwamatsu 
14916f47c9cSNobuhiro Iwamatsu void spi_cs_deactivate(struct spi_slave *slave)
15016f47c9cSNobuhiro Iwamatsu {
15116f47c9cSNobuhiro Iwamatsu 	struct sh_qspi_slave *ss = to_sh_qspi(slave);
15216f47c9cSNobuhiro Iwamatsu 
15316f47c9cSNobuhiro Iwamatsu 	/* Disable SPI Function */
15416f47c9cSNobuhiro Iwamatsu 	clrbits_8(&ss->regs->spcr, SPCR_SPE);
15516f47c9cSNobuhiro Iwamatsu }
15616f47c9cSNobuhiro Iwamatsu 
15716f47c9cSNobuhiro Iwamatsu void spi_init(void)
15816f47c9cSNobuhiro Iwamatsu {
15916f47c9cSNobuhiro Iwamatsu 	/* nothing to do */
16016f47c9cSNobuhiro Iwamatsu }
16116f47c9cSNobuhiro Iwamatsu 
16216f47c9cSNobuhiro Iwamatsu struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
16316f47c9cSNobuhiro Iwamatsu 		unsigned int max_hz, unsigned int mode)
16416f47c9cSNobuhiro Iwamatsu {
16516f47c9cSNobuhiro Iwamatsu 	struct sh_qspi_slave *ss;
16616f47c9cSNobuhiro Iwamatsu 
16716f47c9cSNobuhiro Iwamatsu 	if (!spi_cs_is_valid(bus, cs))
16816f47c9cSNobuhiro Iwamatsu 		return NULL;
16916f47c9cSNobuhiro Iwamatsu 
17016f47c9cSNobuhiro Iwamatsu 	ss = spi_alloc_slave(struct sh_qspi_slave, bus, cs);
17116f47c9cSNobuhiro Iwamatsu 	if (!ss) {
17216f47c9cSNobuhiro Iwamatsu 		printf("SPI_error: Fail to allocate sh_qspi_slave\n");
17316f47c9cSNobuhiro Iwamatsu 		return NULL;
17416f47c9cSNobuhiro Iwamatsu 	}
17516f47c9cSNobuhiro Iwamatsu 
17622e75d6dSNobuhiro Iwamatsu 	ss->regs = (struct sh_qspi_regs *)SH_QSPI_BASE;
17716f47c9cSNobuhiro Iwamatsu 
17816f47c9cSNobuhiro Iwamatsu 	/* Init SH QSPI */
17916f47c9cSNobuhiro Iwamatsu 	sh_qspi_init(ss);
18016f47c9cSNobuhiro Iwamatsu 
18116f47c9cSNobuhiro Iwamatsu 	return &ss->slave;
18216f47c9cSNobuhiro Iwamatsu }
18316f47c9cSNobuhiro Iwamatsu 
18416f47c9cSNobuhiro Iwamatsu void spi_free_slave(struct spi_slave *slave)
18516f47c9cSNobuhiro Iwamatsu {
18616f47c9cSNobuhiro Iwamatsu 	struct sh_qspi_slave *spi = to_sh_qspi(slave);
18716f47c9cSNobuhiro Iwamatsu 
18816f47c9cSNobuhiro Iwamatsu 	free(spi);
18916f47c9cSNobuhiro Iwamatsu }
19016f47c9cSNobuhiro Iwamatsu 
19116f47c9cSNobuhiro Iwamatsu int spi_claim_bus(struct spi_slave *slave)
19216f47c9cSNobuhiro Iwamatsu {
19316f47c9cSNobuhiro Iwamatsu 	return 0;
19416f47c9cSNobuhiro Iwamatsu }
19516f47c9cSNobuhiro Iwamatsu 
19616f47c9cSNobuhiro Iwamatsu void spi_release_bus(struct spi_slave *slave)
19716f47c9cSNobuhiro Iwamatsu {
19816f47c9cSNobuhiro Iwamatsu }
19916f47c9cSNobuhiro Iwamatsu 
20016f47c9cSNobuhiro Iwamatsu int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
20116f47c9cSNobuhiro Iwamatsu 	     void *din, unsigned long flags)
20216f47c9cSNobuhiro Iwamatsu {
20316f47c9cSNobuhiro Iwamatsu 	struct sh_qspi_slave *ss = to_sh_qspi(slave);
2040e6fa20bSMarek Vasut 	u32 nbyte;
20516f47c9cSNobuhiro Iwamatsu 	int ret = 0;
2060e6fa20bSMarek Vasut 	u8 dtdata = 0, drdata;
2070e6fa20bSMarek Vasut 	u8 *tdata = &dtdata, *rdata = &drdata;
2080e6fa20bSMarek Vasut 	u32 *spbmul0 = &ss->regs->spbmul0;
20916f47c9cSNobuhiro Iwamatsu 
21016f47c9cSNobuhiro Iwamatsu 	if (dout == NULL && din == NULL) {
21116f47c9cSNobuhiro Iwamatsu 		if (flags & SPI_XFER_END)
21216f47c9cSNobuhiro Iwamatsu 			spi_cs_deactivate(slave);
21316f47c9cSNobuhiro Iwamatsu 		return 0;
21416f47c9cSNobuhiro Iwamatsu 	}
21516f47c9cSNobuhiro Iwamatsu 
21616f47c9cSNobuhiro Iwamatsu 	if (bitlen % 8) {
21716f47c9cSNobuhiro Iwamatsu 		printf("%s: bitlen is not 8bit alined %d", __func__, bitlen);
21816f47c9cSNobuhiro Iwamatsu 		return 1;
21916f47c9cSNobuhiro Iwamatsu 	}
22016f47c9cSNobuhiro Iwamatsu 
22116f47c9cSNobuhiro Iwamatsu 	nbyte = bitlen / 8;
22216f47c9cSNobuhiro Iwamatsu 
22316f47c9cSNobuhiro Iwamatsu 	if (flags & SPI_XFER_BEGIN) {
22416f47c9cSNobuhiro Iwamatsu 		spi_cs_activate(slave);
22516f47c9cSNobuhiro Iwamatsu 
22616f47c9cSNobuhiro Iwamatsu 		/* Set 1048576 byte */
22716f47c9cSNobuhiro Iwamatsu 		writel(0x100000, spbmul0);
22816f47c9cSNobuhiro Iwamatsu 	}
22916f47c9cSNobuhiro Iwamatsu 
23016f47c9cSNobuhiro Iwamatsu 	if (flags & SPI_XFER_END)
23116f47c9cSNobuhiro Iwamatsu 		writel(nbyte, spbmul0);
23216f47c9cSNobuhiro Iwamatsu 
23316f47c9cSNobuhiro Iwamatsu 	if (dout != NULL)
2340e6fa20bSMarek Vasut 		tdata = (u8 *)dout;
23516f47c9cSNobuhiro Iwamatsu 
23616f47c9cSNobuhiro Iwamatsu 	if (din != NULL)
23716f47c9cSNobuhiro Iwamatsu 		rdata = din;
23816f47c9cSNobuhiro Iwamatsu 
23916f47c9cSNobuhiro Iwamatsu 	while (nbyte > 0) {
240*9573db65SMarek Vasut 		ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPTEF,
241*9573db65SMarek Vasut 				     true, 1000, true);
242*9573db65SMarek Vasut 		if (ret)
243*9573db65SMarek Vasut 			return ret;
24416f47c9cSNobuhiro Iwamatsu 
2450e6fa20bSMarek Vasut 		writeb(*tdata, (u8 *)(&ss->regs->spdr));
24616f47c9cSNobuhiro Iwamatsu 
247*9573db65SMarek Vasut 		ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPRFF,
248*9573db65SMarek Vasut 				     true, 1000, true);
249*9573db65SMarek Vasut 		if (ret)
250*9573db65SMarek Vasut 			return ret;
25116f47c9cSNobuhiro Iwamatsu 
2520e6fa20bSMarek Vasut 		*rdata = readb((u8 *)(&ss->regs->spdr));
25316f47c9cSNobuhiro Iwamatsu 
25416f47c9cSNobuhiro Iwamatsu 		if (dout != NULL)
25516f47c9cSNobuhiro Iwamatsu 			tdata++;
25616f47c9cSNobuhiro Iwamatsu 		if (din != NULL)
25716f47c9cSNobuhiro Iwamatsu 			rdata++;
25816f47c9cSNobuhiro Iwamatsu 
25916f47c9cSNobuhiro Iwamatsu 		nbyte--;
26016f47c9cSNobuhiro Iwamatsu 	}
26116f47c9cSNobuhiro Iwamatsu 
26216f47c9cSNobuhiro Iwamatsu 	if (flags & SPI_XFER_END)
26316f47c9cSNobuhiro Iwamatsu 		spi_cs_deactivate(slave);
26416f47c9cSNobuhiro Iwamatsu 
26516f47c9cSNobuhiro Iwamatsu 	return ret;
26616f47c9cSNobuhiro Iwamatsu }
267