xref: /rk3399_rockchip-uboot/drivers/spi/sh_qspi.c (revision 7f3cd1e4f8010ae7bed52343c6fc5a6b4ea16e05)
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