xref: /openbmc/linux/drivers/spi/spi-rspi.c (revision 862d357f)
10b2182ddSShimoda, Yoshihiro /*
20b2182ddSShimoda, Yoshihiro  * SH RSPI driver
30b2182ddSShimoda, Yoshihiro  *
493722206SGeert Uytterhoeven  * Copyright (C) 2012, 2013  Renesas Solutions Corp.
50b2182ddSShimoda, Yoshihiro  *
60b2182ddSShimoda, Yoshihiro  * Based on spi-sh.c:
70b2182ddSShimoda, Yoshihiro  * Copyright (C) 2011 Renesas Solutions Corp.
80b2182ddSShimoda, Yoshihiro  *
90b2182ddSShimoda, Yoshihiro  * This program is free software; you can redistribute it and/or modify
100b2182ddSShimoda, Yoshihiro  * it under the terms of the GNU General Public License as published by
110b2182ddSShimoda, Yoshihiro  * the Free Software Foundation; version 2 of the License.
120b2182ddSShimoda, Yoshihiro  *
130b2182ddSShimoda, Yoshihiro  * This program is distributed in the hope that it will be useful,
140b2182ddSShimoda, Yoshihiro  * but WITHOUT ANY WARRANTY; without even the implied warranty of
150b2182ddSShimoda, Yoshihiro  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
160b2182ddSShimoda, Yoshihiro  * GNU General Public License for more details.
170b2182ddSShimoda, Yoshihiro  *
180b2182ddSShimoda, Yoshihiro  * You should have received a copy of the GNU General Public License
190b2182ddSShimoda, Yoshihiro  * along with this program; if not, write to the Free Software
200b2182ddSShimoda, Yoshihiro  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
210b2182ddSShimoda, Yoshihiro  *
220b2182ddSShimoda, Yoshihiro  */
230b2182ddSShimoda, Yoshihiro 
240b2182ddSShimoda, Yoshihiro #include <linux/module.h>
250b2182ddSShimoda, Yoshihiro #include <linux/kernel.h>
260b2182ddSShimoda, Yoshihiro #include <linux/sched.h>
270b2182ddSShimoda, Yoshihiro #include <linux/errno.h>
280b2182ddSShimoda, Yoshihiro #include <linux/interrupt.h>
290b2182ddSShimoda, Yoshihiro #include <linux/platform_device.h>
300b2182ddSShimoda, Yoshihiro #include <linux/io.h>
310b2182ddSShimoda, Yoshihiro #include <linux/clk.h>
32a3633fe7SShimoda, Yoshihiro #include <linux/dmaengine.h>
33a3633fe7SShimoda, Yoshihiro #include <linux/dma-mapping.h>
34a3633fe7SShimoda, Yoshihiro #include <linux/sh_dma.h>
350b2182ddSShimoda, Yoshihiro #include <linux/spi/spi.h>
36a3633fe7SShimoda, Yoshihiro #include <linux/spi/rspi.h>
370b2182ddSShimoda, Yoshihiro 
386ab4865bSGeert Uytterhoeven #define RSPI_SPCR		0x00	/* Control Register */
396ab4865bSGeert Uytterhoeven #define RSPI_SSLP		0x01	/* Slave Select Polarity Register */
406ab4865bSGeert Uytterhoeven #define RSPI_SPPCR		0x02	/* Pin Control Register */
416ab4865bSGeert Uytterhoeven #define RSPI_SPSR		0x03	/* Status Register */
426ab4865bSGeert Uytterhoeven #define RSPI_SPDR		0x04	/* Data Register */
436ab4865bSGeert Uytterhoeven #define RSPI_SPSCR		0x08	/* Sequence Control Register */
446ab4865bSGeert Uytterhoeven #define RSPI_SPSSR		0x09	/* Sequence Status Register */
456ab4865bSGeert Uytterhoeven #define RSPI_SPBR		0x0a	/* Bit Rate Register */
466ab4865bSGeert Uytterhoeven #define RSPI_SPDCR		0x0b	/* Data Control Register */
476ab4865bSGeert Uytterhoeven #define RSPI_SPCKD		0x0c	/* Clock Delay Register */
486ab4865bSGeert Uytterhoeven #define RSPI_SSLND		0x0d	/* Slave Select Negation Delay Register */
496ab4865bSGeert Uytterhoeven #define RSPI_SPND		0x0e	/* Next-Access Delay Register */
50862d357fSGeert Uytterhoeven #define RSPI_SPCR2		0x0f	/* Control Register 2 (SH only) */
516ab4865bSGeert Uytterhoeven #define RSPI_SPCMD0		0x10	/* Command Register 0 */
526ab4865bSGeert Uytterhoeven #define RSPI_SPCMD1		0x12	/* Command Register 1 */
536ab4865bSGeert Uytterhoeven #define RSPI_SPCMD2		0x14	/* Command Register 2 */
546ab4865bSGeert Uytterhoeven #define RSPI_SPCMD3		0x16	/* Command Register 3 */
556ab4865bSGeert Uytterhoeven #define RSPI_SPCMD4		0x18	/* Command Register 4 */
566ab4865bSGeert Uytterhoeven #define RSPI_SPCMD5		0x1a	/* Command Register 5 */
576ab4865bSGeert Uytterhoeven #define RSPI_SPCMD6		0x1c	/* Command Register 6 */
586ab4865bSGeert Uytterhoeven #define RSPI_SPCMD7		0x1e	/* Command Register 7 */
59862d357fSGeert Uytterhoeven 
60862d357fSGeert Uytterhoeven /* RSPI on RZ only */
616ab4865bSGeert Uytterhoeven #define RSPI_SPBFCR		0x20	/* Buffer Control Register */
626ab4865bSGeert Uytterhoeven #define RSPI_SPBFDR		0x22	/* Buffer Data Count Setting Register */
630b2182ddSShimoda, Yoshihiro 
64862d357fSGeert Uytterhoeven /* QSPI only */
65fbe5072bSGeert Uytterhoeven #define QSPI_SPBFCR		0x18	/* Buffer Control Register */
66fbe5072bSGeert Uytterhoeven #define QSPI_SPBDCR		0x1a	/* Buffer Data Count Register */
67fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL0		0x1c	/* Transfer Data Length Multiplier Setting Register 0 */
68fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL1		0x20	/* Transfer Data Length Multiplier Setting Register 1 */
69fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL2		0x24	/* Transfer Data Length Multiplier Setting Register 2 */
70fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL3		0x28	/* Transfer Data Length Multiplier Setting Register 3 */
715ce0ba88SHiep Cao Minh 
726ab4865bSGeert Uytterhoeven /* SPCR - Control Register */
736ab4865bSGeert Uytterhoeven #define SPCR_SPRIE		0x80	/* Receive Interrupt Enable */
746ab4865bSGeert Uytterhoeven #define SPCR_SPE		0x40	/* Function Enable */
756ab4865bSGeert Uytterhoeven #define SPCR_SPTIE		0x20	/* Transmit Interrupt Enable */
766ab4865bSGeert Uytterhoeven #define SPCR_SPEIE		0x10	/* Error Interrupt Enable */
776ab4865bSGeert Uytterhoeven #define SPCR_MSTR		0x08	/* Master/Slave Mode Select */
786ab4865bSGeert Uytterhoeven #define SPCR_MODFEN		0x04	/* Mode Fault Error Detection Enable */
796ab4865bSGeert Uytterhoeven /* RSPI on SH only */
806ab4865bSGeert Uytterhoeven #define SPCR_TXMD		0x02	/* TX Only Mode (vs. Full Duplex) */
816ab4865bSGeert Uytterhoeven #define SPCR_SPMS		0x01	/* 3-wire Mode (vs. 4-wire) */
82fbe5072bSGeert Uytterhoeven /* QSPI on R-Car M2 only */
83fbe5072bSGeert Uytterhoeven #define SPCR_WSWAP		0x02	/* Word Swap of read-data for DMAC */
84fbe5072bSGeert Uytterhoeven #define SPCR_BSWAP		0x01	/* Byte Swap of read-data for DMAC */
850b2182ddSShimoda, Yoshihiro 
866ab4865bSGeert Uytterhoeven /* SSLP - Slave Select Polarity Register */
876ab4865bSGeert Uytterhoeven #define SSLP_SSL1P		0x02	/* SSL1 Signal Polarity Setting */
886ab4865bSGeert Uytterhoeven #define SSLP_SSL0P		0x01	/* SSL0 Signal Polarity Setting */
890b2182ddSShimoda, Yoshihiro 
906ab4865bSGeert Uytterhoeven /* SPPCR - Pin Control Register */
916ab4865bSGeert Uytterhoeven #define SPPCR_MOIFE		0x20	/* MOSI Idle Value Fixing Enable */
926ab4865bSGeert Uytterhoeven #define SPPCR_MOIFV		0x10	/* MOSI Idle Fixed Value */
930b2182ddSShimoda, Yoshihiro #define SPPCR_SPOM		0x04
946ab4865bSGeert Uytterhoeven #define SPPCR_SPLP2		0x02	/* Loopback Mode 2 (non-inverting) */
956ab4865bSGeert Uytterhoeven #define SPPCR_SPLP		0x01	/* Loopback Mode (inverting) */
960b2182ddSShimoda, Yoshihiro 
97fbe5072bSGeert Uytterhoeven #define SPPCR_IO3FV		0x04	/* Single-/Dual-SPI Mode IO3 Output Fixed Value */
98fbe5072bSGeert Uytterhoeven #define SPPCR_IO2FV		0x04	/* Single-/Dual-SPI Mode IO2 Output Fixed Value */
99fbe5072bSGeert Uytterhoeven 
1006ab4865bSGeert Uytterhoeven /* SPSR - Status Register */
1016ab4865bSGeert Uytterhoeven #define SPSR_SPRF		0x80	/* Receive Buffer Full Flag */
1026ab4865bSGeert Uytterhoeven #define SPSR_TEND		0x40	/* Transmit End */
1036ab4865bSGeert Uytterhoeven #define SPSR_SPTEF		0x20	/* Transmit Buffer Empty Flag */
1046ab4865bSGeert Uytterhoeven #define SPSR_PERF		0x08	/* Parity Error Flag */
1056ab4865bSGeert Uytterhoeven #define SPSR_MODF		0x04	/* Mode Fault Error Flag */
1066ab4865bSGeert Uytterhoeven #define SPSR_IDLNF		0x02	/* RSPI Idle Flag */
107862d357fSGeert Uytterhoeven #define SPSR_OVRF		0x01	/* Overrun Error Flag (RSPI only) */
1080b2182ddSShimoda, Yoshihiro 
1096ab4865bSGeert Uytterhoeven /* SPSCR - Sequence Control Register */
1106ab4865bSGeert Uytterhoeven #define SPSCR_SPSLN_MASK	0x07	/* Sequence Length Specification */
1110b2182ddSShimoda, Yoshihiro 
1126ab4865bSGeert Uytterhoeven /* SPSSR - Sequence Status Register */
1136ab4865bSGeert Uytterhoeven #define SPSSR_SPECM_MASK	0x70	/* Command Error Mask */
1146ab4865bSGeert Uytterhoeven #define SPSSR_SPCP_MASK		0x07	/* Command Pointer Mask */
1150b2182ddSShimoda, Yoshihiro 
1166ab4865bSGeert Uytterhoeven /* SPDCR - Data Control Register */
1176ab4865bSGeert Uytterhoeven #define SPDCR_TXDMY		0x80	/* Dummy Data Transmission Enable */
1186ab4865bSGeert Uytterhoeven #define SPDCR_SPLW1		0x40	/* Access Width Specification (RZ) */
1196ab4865bSGeert Uytterhoeven #define SPDCR_SPLW0		0x20	/* Access Width Specification (RZ) */
1206ab4865bSGeert Uytterhoeven #define SPDCR_SPLLWORD		(SPDCR_SPLW1 | SPDCR_SPLW0)
1216ab4865bSGeert Uytterhoeven #define SPDCR_SPLWORD		SPDCR_SPLW1
1226ab4865bSGeert Uytterhoeven #define SPDCR_SPLBYTE		SPDCR_SPLW0
1236ab4865bSGeert Uytterhoeven #define SPDCR_SPLW		0x20	/* Access Width Specification (SH) */
124862d357fSGeert Uytterhoeven #define SPDCR_SPRDTD		0x10	/* Receive Transmit Data Select (SH) */
1250b2182ddSShimoda, Yoshihiro #define SPDCR_SLSEL1		0x08
1260b2182ddSShimoda, Yoshihiro #define SPDCR_SLSEL0		0x04
127862d357fSGeert Uytterhoeven #define SPDCR_SLSEL_MASK	0x0c	/* SSL1 Output Select (SH) */
1280b2182ddSShimoda, Yoshihiro #define SPDCR_SPFC1		0x02
1290b2182ddSShimoda, Yoshihiro #define SPDCR_SPFC0		0x01
130862d357fSGeert Uytterhoeven #define SPDCR_SPFC_MASK		0x03	/* Frame Count Setting (1-4) (SH) */
1310b2182ddSShimoda, Yoshihiro 
1326ab4865bSGeert Uytterhoeven /* SPCKD - Clock Delay Register */
1336ab4865bSGeert Uytterhoeven #define SPCKD_SCKDL_MASK	0x07	/* Clock Delay Setting (1-8) */
1340b2182ddSShimoda, Yoshihiro 
1356ab4865bSGeert Uytterhoeven /* SSLND - Slave Select Negation Delay Register */
1366ab4865bSGeert Uytterhoeven #define SSLND_SLNDL_MASK	0x07	/* SSL Negation Delay Setting (1-8) */
1370b2182ddSShimoda, Yoshihiro 
1386ab4865bSGeert Uytterhoeven /* SPND - Next-Access Delay Register */
1396ab4865bSGeert Uytterhoeven #define SPND_SPNDL_MASK		0x07	/* Next-Access Delay Setting (1-8) */
1400b2182ddSShimoda, Yoshihiro 
1416ab4865bSGeert Uytterhoeven /* SPCR2 - Control Register 2 */
1426ab4865bSGeert Uytterhoeven #define SPCR2_PTE		0x08	/* Parity Self-Test Enable */
1436ab4865bSGeert Uytterhoeven #define SPCR2_SPIE		0x04	/* Idle Interrupt Enable */
1446ab4865bSGeert Uytterhoeven #define SPCR2_SPOE		0x02	/* Odd Parity Enable (vs. Even) */
1456ab4865bSGeert Uytterhoeven #define SPCR2_SPPE		0x01	/* Parity Enable */
1460b2182ddSShimoda, Yoshihiro 
1476ab4865bSGeert Uytterhoeven /* SPCMDn - Command Registers */
1486ab4865bSGeert Uytterhoeven #define SPCMD_SCKDEN		0x8000	/* Clock Delay Setting Enable */
1496ab4865bSGeert Uytterhoeven #define SPCMD_SLNDEN		0x4000	/* SSL Negation Delay Setting Enable */
1506ab4865bSGeert Uytterhoeven #define SPCMD_SPNDEN		0x2000	/* Next-Access Delay Enable */
1516ab4865bSGeert Uytterhoeven #define SPCMD_LSBF		0x1000	/* LSB First */
1526ab4865bSGeert Uytterhoeven #define SPCMD_SPB_MASK		0x0f00	/* Data Length Setting */
1530b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_8_TO_16(bit)	(((bit - 1) << 8) & SPCMD_SPB_MASK)
1545ce0ba88SHiep Cao Minh #define SPCMD_SPB_8BIT		0x0000	/* qspi only */
1555ce0ba88SHiep Cao Minh #define SPCMD_SPB_16BIT		0x0100
1560b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_20BIT		0x0000
1570b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_24BIT		0x0100
1580b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_32BIT		0x0200
1596ab4865bSGeert Uytterhoeven #define SPCMD_SSLKP		0x0080	/* SSL Signal Level Keeping */
160fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_MASK	0x0060	/* SPI Operating Mode (QSPI only) */
161fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD1		0x0040
162fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD0		0x0020
163fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_SINGLE	0
164fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_DUAL	SPCMD_SPIMOD0
165fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_QUAD	SPCMD_SPIMOD1
166fbe5072bSGeert Uytterhoeven #define SPCMD_SPRW		0x0010	/* SPI Read/Write Access (Dual/Quad) */
1676ab4865bSGeert Uytterhoeven #define SPCMD_SSLA_MASK		0x0030	/* SSL Assert Signal Setting (RSPI) */
1686ab4865bSGeert Uytterhoeven #define SPCMD_BRDV_MASK		0x000c	/* Bit Rate Division Setting */
1696ab4865bSGeert Uytterhoeven #define SPCMD_CPOL		0x0002	/* Clock Polarity Setting */
1706ab4865bSGeert Uytterhoeven #define SPCMD_CPHA		0x0001	/* Clock Phase Setting */
1710b2182ddSShimoda, Yoshihiro 
1726ab4865bSGeert Uytterhoeven /* SPBFCR - Buffer Control Register */
173862d357fSGeert Uytterhoeven #define SPBFCR_TXRST		0x80	/* Transmit Buffer Data Reset */
174862d357fSGeert Uytterhoeven #define SPBFCR_RXRST		0x40	/* Receive Buffer Data Reset */
1756ab4865bSGeert Uytterhoeven #define SPBFCR_TXTRG_MASK	0x30	/* Transmit Buffer Data Triggering Number */
1766ab4865bSGeert Uytterhoeven #define SPBFCR_RXTRG_MASK	0x07	/* Receive Buffer Data Triggering Number */
1775ce0ba88SHiep Cao Minh 
1782aae80b2SGeert Uytterhoeven #define DUMMY_DATA		0x00
1792aae80b2SGeert Uytterhoeven 
1800b2182ddSShimoda, Yoshihiro struct rspi_data {
1810b2182ddSShimoda, Yoshihiro 	void __iomem *addr;
1820b2182ddSShimoda, Yoshihiro 	u32 max_speed_hz;
1830b2182ddSShimoda, Yoshihiro 	struct spi_master *master;
1840b2182ddSShimoda, Yoshihiro 	wait_queue_head_t wait;
1850b2182ddSShimoda, Yoshihiro 	struct clk *clk;
18697b95c11SGeert Uytterhoeven 	u8 spsr;
187348e5153SGeert Uytterhoeven 	u16 spcmd;
18893722206SGeert Uytterhoeven 	int rx_irq, tx_irq;
1895ce0ba88SHiep Cao Minh 	const struct spi_ops *ops;
190a3633fe7SShimoda, Yoshihiro 
191a3633fe7SShimoda, Yoshihiro 	/* for dmaengine */
192a3633fe7SShimoda, Yoshihiro 	struct dma_chan *chan_tx;
193a3633fe7SShimoda, Yoshihiro 	struct dma_chan *chan_rx;
194a3633fe7SShimoda, Yoshihiro 
195a3633fe7SShimoda, Yoshihiro 	unsigned dma_width_16bit:1;
196a3633fe7SShimoda, Yoshihiro 	unsigned dma_callbacked:1;
19774da7686SGeert Uytterhoeven 	unsigned byte_access:1;
1980b2182ddSShimoda, Yoshihiro };
1990b2182ddSShimoda, Yoshihiro 
200baf588f4SGeert Uytterhoeven static void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset)
2010b2182ddSShimoda, Yoshihiro {
2020b2182ddSShimoda, Yoshihiro 	iowrite8(data, rspi->addr + offset);
2030b2182ddSShimoda, Yoshihiro }
2040b2182ddSShimoda, Yoshihiro 
205baf588f4SGeert Uytterhoeven static void rspi_write16(const struct rspi_data *rspi, u16 data, u16 offset)
2060b2182ddSShimoda, Yoshihiro {
2070b2182ddSShimoda, Yoshihiro 	iowrite16(data, rspi->addr + offset);
2080b2182ddSShimoda, Yoshihiro }
2090b2182ddSShimoda, Yoshihiro 
210baf588f4SGeert Uytterhoeven static void rspi_write32(const struct rspi_data *rspi, u32 data, u16 offset)
2115ce0ba88SHiep Cao Minh {
2125ce0ba88SHiep Cao Minh 	iowrite32(data, rspi->addr + offset);
2135ce0ba88SHiep Cao Minh }
2145ce0ba88SHiep Cao Minh 
215baf588f4SGeert Uytterhoeven static u8 rspi_read8(const struct rspi_data *rspi, u16 offset)
2160b2182ddSShimoda, Yoshihiro {
2170b2182ddSShimoda, Yoshihiro 	return ioread8(rspi->addr + offset);
2180b2182ddSShimoda, Yoshihiro }
2190b2182ddSShimoda, Yoshihiro 
220baf588f4SGeert Uytterhoeven static u16 rspi_read16(const struct rspi_data *rspi, u16 offset)
2210b2182ddSShimoda, Yoshihiro {
2220b2182ddSShimoda, Yoshihiro 	return ioread16(rspi->addr + offset);
2230b2182ddSShimoda, Yoshihiro }
2240b2182ddSShimoda, Yoshihiro 
22574da7686SGeert Uytterhoeven static void rspi_write_data(const struct rspi_data *rspi, u16 data)
22674da7686SGeert Uytterhoeven {
22774da7686SGeert Uytterhoeven 	if (rspi->byte_access)
22874da7686SGeert Uytterhoeven 		rspi_write8(rspi, data, RSPI_SPDR);
22974da7686SGeert Uytterhoeven 	else /* 16 bit */
23074da7686SGeert Uytterhoeven 		rspi_write16(rspi, data, RSPI_SPDR);
23174da7686SGeert Uytterhoeven }
23274da7686SGeert Uytterhoeven 
23374da7686SGeert Uytterhoeven static u16 rspi_read_data(const struct rspi_data *rspi)
23474da7686SGeert Uytterhoeven {
23574da7686SGeert Uytterhoeven 	if (rspi->byte_access)
23674da7686SGeert Uytterhoeven 		return rspi_read8(rspi, RSPI_SPDR);
23774da7686SGeert Uytterhoeven 	else /* 16 bit */
23874da7686SGeert Uytterhoeven 		return rspi_read16(rspi, RSPI_SPDR);
23974da7686SGeert Uytterhoeven }
24074da7686SGeert Uytterhoeven 
2415ce0ba88SHiep Cao Minh /* optional functions */
2425ce0ba88SHiep Cao Minh struct spi_ops {
24374da7686SGeert Uytterhoeven 	int (*set_config_register)(struct rspi_data *rspi, int access_size);
244eb557f75SGeert Uytterhoeven 	int (*transfer_one)(struct spi_master *master, struct spi_device *spi,
245eb557f75SGeert Uytterhoeven 			    struct spi_transfer *xfer);
2465ce0ba88SHiep Cao Minh };
2475ce0ba88SHiep Cao Minh 
2485ce0ba88SHiep Cao Minh /*
249862d357fSGeert Uytterhoeven  * functions for RSPI on legacy SH
2505ce0ba88SHiep Cao Minh  */
25174da7686SGeert Uytterhoeven static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
2520b2182ddSShimoda, Yoshihiro {
2535ce0ba88SHiep Cao Minh 	int spbr;
2540b2182ddSShimoda, Yoshihiro 
2555ce0ba88SHiep Cao Minh 	/* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
2565ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPPCR);
2570b2182ddSShimoda, Yoshihiro 
2585ce0ba88SHiep Cao Minh 	/* Sets transfer bit rate */
2595ce0ba88SHiep Cao Minh 	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
2605ce0ba88SHiep Cao Minh 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
2615ce0ba88SHiep Cao Minh 
26274da7686SGeert Uytterhoeven 	/* Disable dummy transmission, set 16-bit word access, 1 frame */
26374da7686SGeert Uytterhoeven 	rspi_write8(rspi, 0, RSPI_SPDCR);
26474da7686SGeert Uytterhoeven 	rspi->byte_access = 0;
2655ce0ba88SHiep Cao Minh 
2665ce0ba88SHiep Cao Minh 	/* Sets RSPCK, SSL, next-access delay value */
2675ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
2685ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SSLND);
2695ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPND);
2705ce0ba88SHiep Cao Minh 
2715ce0ba88SHiep Cao Minh 	/* Sets parity, interrupt mask */
2725ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCR2);
2735ce0ba88SHiep Cao Minh 
2745ce0ba88SHiep Cao Minh 	/* Sets SPCMD */
275348e5153SGeert Uytterhoeven 	rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | rspi->spcmd,
2765ce0ba88SHiep Cao Minh 		     RSPI_SPCMD0);
2775ce0ba88SHiep Cao Minh 
2785ce0ba88SHiep Cao Minh 	/* Sets RSPI mode */
2795ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
2805ce0ba88SHiep Cao Minh 
2815ce0ba88SHiep Cao Minh 	return 0;
2820b2182ddSShimoda, Yoshihiro }
2830b2182ddSShimoda, Yoshihiro 
2845ce0ba88SHiep Cao Minh /*
285862d357fSGeert Uytterhoeven  * functions for RSPI on RZ
286862d357fSGeert Uytterhoeven  */
287862d357fSGeert Uytterhoeven static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size)
288862d357fSGeert Uytterhoeven {
289862d357fSGeert Uytterhoeven 	int spbr;
290862d357fSGeert Uytterhoeven 
291862d357fSGeert Uytterhoeven 	/* Sets output mode */
292862d357fSGeert Uytterhoeven 	rspi_write8(rspi, 0x00, RSPI_SPPCR);
293862d357fSGeert Uytterhoeven 
294862d357fSGeert Uytterhoeven 	/* Sets transfer bit rate */
295862d357fSGeert Uytterhoeven 	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
296862d357fSGeert Uytterhoeven 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
297862d357fSGeert Uytterhoeven 
298862d357fSGeert Uytterhoeven 	/* Disable dummy transmission, set byte access */
299862d357fSGeert Uytterhoeven 	rspi_write8(rspi, SPDCR_SPLBYTE, RSPI_SPDCR);
300862d357fSGeert Uytterhoeven 	rspi->byte_access = 1;
301862d357fSGeert Uytterhoeven 
302862d357fSGeert Uytterhoeven 	/* Sets RSPCK, SSL, next-access delay value */
303862d357fSGeert Uytterhoeven 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
304862d357fSGeert Uytterhoeven 	rspi_write8(rspi, 0x00, RSPI_SSLND);
305862d357fSGeert Uytterhoeven 	rspi_write8(rspi, 0x00, RSPI_SPND);
306862d357fSGeert Uytterhoeven 
307862d357fSGeert Uytterhoeven 	/* Sets SPCMD */
308862d357fSGeert Uytterhoeven 	rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size);
309862d357fSGeert Uytterhoeven 	rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
310862d357fSGeert Uytterhoeven 
311862d357fSGeert Uytterhoeven 	/* Sets RSPI mode */
312862d357fSGeert Uytterhoeven 	rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
313862d357fSGeert Uytterhoeven 
314862d357fSGeert Uytterhoeven 	return 0;
315862d357fSGeert Uytterhoeven }
316862d357fSGeert Uytterhoeven 
317862d357fSGeert Uytterhoeven /*
3185ce0ba88SHiep Cao Minh  * functions for QSPI
3195ce0ba88SHiep Cao Minh  */
32074da7686SGeert Uytterhoeven static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
3215ce0ba88SHiep Cao Minh {
3225ce0ba88SHiep Cao Minh 	u16 spcmd;
3235ce0ba88SHiep Cao Minh 	int spbr;
3245ce0ba88SHiep Cao Minh 
3255ce0ba88SHiep Cao Minh 	/* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
3265ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPPCR);
3275ce0ba88SHiep Cao Minh 
3285ce0ba88SHiep Cao Minh 	/* Sets transfer bit rate */
3295ce0ba88SHiep Cao Minh 	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz);
3305ce0ba88SHiep Cao Minh 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
3315ce0ba88SHiep Cao Minh 
33274da7686SGeert Uytterhoeven 	/* Disable dummy transmission, set byte access */
33374da7686SGeert Uytterhoeven 	rspi_write8(rspi, 0, RSPI_SPDCR);
33474da7686SGeert Uytterhoeven 	rspi->byte_access = 1;
3355ce0ba88SHiep Cao Minh 
3365ce0ba88SHiep Cao Minh 	/* Sets RSPCK, SSL, next-access delay value */
3375ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
3385ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SSLND);
3395ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPND);
3405ce0ba88SHiep Cao Minh 
3415ce0ba88SHiep Cao Minh 	/* Data Length Setting */
3425ce0ba88SHiep Cao Minh 	if (access_size == 8)
3435ce0ba88SHiep Cao Minh 		spcmd = SPCMD_SPB_8BIT;
3445ce0ba88SHiep Cao Minh 	else if (access_size == 16)
3455ce0ba88SHiep Cao Minh 		spcmd = SPCMD_SPB_16BIT;
3468e1c8096SLaurent Pinchart 	else
3475ce0ba88SHiep Cao Minh 		spcmd = SPCMD_SPB_32BIT;
3485ce0ba88SHiep Cao Minh 
349348e5153SGeert Uytterhoeven 	spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | rspi->spcmd | SPCMD_SPNDEN;
3505ce0ba88SHiep Cao Minh 
3515ce0ba88SHiep Cao Minh 	/* Resets transfer data length */
3525ce0ba88SHiep Cao Minh 	rspi_write32(rspi, 0, QSPI_SPBMUL0);
3535ce0ba88SHiep Cao Minh 
3545ce0ba88SHiep Cao Minh 	/* Resets transmit and receive buffer */
3555ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
3565ce0ba88SHiep Cao Minh 	/* Sets buffer to allow normal operation */
3575ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
3585ce0ba88SHiep Cao Minh 
3595ce0ba88SHiep Cao Minh 	/* Sets SPCMD */
3605ce0ba88SHiep Cao Minh 	rspi_write16(rspi, spcmd, RSPI_SPCMD0);
3615ce0ba88SHiep Cao Minh 
3625ce0ba88SHiep Cao Minh 	/* Enables SPI function in a master mode */
3635ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR);
3645ce0ba88SHiep Cao Minh 
3655ce0ba88SHiep Cao Minh 	return 0;
3665ce0ba88SHiep Cao Minh }
3675ce0ba88SHiep Cao Minh 
3685ce0ba88SHiep Cao Minh #define set_config_register(spi, n) spi->ops->set_config_register(spi, n)
3695ce0ba88SHiep Cao Minh 
370baf588f4SGeert Uytterhoeven static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable)
3710b2182ddSShimoda, Yoshihiro {
3720b2182ddSShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR);
3730b2182ddSShimoda, Yoshihiro }
3740b2182ddSShimoda, Yoshihiro 
375baf588f4SGeert Uytterhoeven static void rspi_disable_irq(const struct rspi_data *rspi, u8 disable)
3760b2182ddSShimoda, Yoshihiro {
3770b2182ddSShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~disable, RSPI_SPCR);
3780b2182ddSShimoda, Yoshihiro }
3790b2182ddSShimoda, Yoshihiro 
3800b2182ddSShimoda, Yoshihiro static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
3810b2182ddSShimoda, Yoshihiro 				   u8 enable_bit)
3820b2182ddSShimoda, Yoshihiro {
3830b2182ddSShimoda, Yoshihiro 	int ret;
3840b2182ddSShimoda, Yoshihiro 
3850b2182ddSShimoda, Yoshihiro 	rspi->spsr = rspi_read8(rspi, RSPI_SPSR);
3860b2182ddSShimoda, Yoshihiro 	rspi_enable_irq(rspi, enable_bit);
3870b2182ddSShimoda, Yoshihiro 	ret = wait_event_timeout(rspi->wait, rspi->spsr & wait_mask, HZ);
3880b2182ddSShimoda, Yoshihiro 	if (ret == 0 && !(rspi->spsr & wait_mask))
3890b2182ddSShimoda, Yoshihiro 		return -ETIMEDOUT;
3900b2182ddSShimoda, Yoshihiro 
3910b2182ddSShimoda, Yoshihiro 	return 0;
3920b2182ddSShimoda, Yoshihiro }
3930b2182ddSShimoda, Yoshihiro 
39435301c99SGeert Uytterhoeven static int rspi_data_out(struct rspi_data *rspi, u8 data)
39535301c99SGeert Uytterhoeven {
39635301c99SGeert Uytterhoeven 	if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
39735301c99SGeert Uytterhoeven 		dev_err(&rspi->master->dev, "transmit timeout\n");
39835301c99SGeert Uytterhoeven 		return -ETIMEDOUT;
39935301c99SGeert Uytterhoeven 	}
40035301c99SGeert Uytterhoeven 	rspi_write_data(rspi, data);
40135301c99SGeert Uytterhoeven 	return 0;
40235301c99SGeert Uytterhoeven }
40335301c99SGeert Uytterhoeven 
40435301c99SGeert Uytterhoeven static int rspi_data_in(struct rspi_data *rspi)
40535301c99SGeert Uytterhoeven {
40635301c99SGeert Uytterhoeven 	u8 data;
40735301c99SGeert Uytterhoeven 
40835301c99SGeert Uytterhoeven 	if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
40935301c99SGeert Uytterhoeven 		dev_err(&rspi->master->dev, "receive timeout\n");
41035301c99SGeert Uytterhoeven 		return -ETIMEDOUT;
41135301c99SGeert Uytterhoeven 	}
41235301c99SGeert Uytterhoeven 	data = rspi_read_data(rspi);
41335301c99SGeert Uytterhoeven 	return data;
41435301c99SGeert Uytterhoeven }
41535301c99SGeert Uytterhoeven 
41635301c99SGeert Uytterhoeven static int rspi_data_out_in(struct rspi_data *rspi, u8 data)
41735301c99SGeert Uytterhoeven {
41835301c99SGeert Uytterhoeven 	int ret;
41935301c99SGeert Uytterhoeven 
42035301c99SGeert Uytterhoeven 	ret = rspi_data_out(rspi, data);
42135301c99SGeert Uytterhoeven 	if (ret < 0)
42235301c99SGeert Uytterhoeven 		return ret;
42335301c99SGeert Uytterhoeven 
42435301c99SGeert Uytterhoeven 	return rspi_data_in(rspi);
42535301c99SGeert Uytterhoeven }
42635301c99SGeert Uytterhoeven 
427a3633fe7SShimoda, Yoshihiro static void rspi_dma_complete(void *arg)
4280b2182ddSShimoda, Yoshihiro {
429a3633fe7SShimoda, Yoshihiro 	struct rspi_data *rspi = arg;
430a3633fe7SShimoda, Yoshihiro 
431a3633fe7SShimoda, Yoshihiro 	rspi->dma_callbacked = 1;
432a3633fe7SShimoda, Yoshihiro 	wake_up_interruptible(&rspi->wait);
433a3633fe7SShimoda, Yoshihiro }
434a3633fe7SShimoda, Yoshihiro 
435c132f094SGeert Uytterhoeven static int rspi_dma_map_sg(struct scatterlist *sg, const void *buf,
436c132f094SGeert Uytterhoeven 			   unsigned len, struct dma_chan *chan,
437a3633fe7SShimoda, Yoshihiro 			   enum dma_transfer_direction dir)
438a3633fe7SShimoda, Yoshihiro {
439a3633fe7SShimoda, Yoshihiro 	sg_init_table(sg, 1);
440a3633fe7SShimoda, Yoshihiro 	sg_set_buf(sg, buf, len);
441a3633fe7SShimoda, Yoshihiro 	sg_dma_len(sg) = len;
442a3633fe7SShimoda, Yoshihiro 	return dma_map_sg(chan->device->dev, sg, 1, dir);
443a3633fe7SShimoda, Yoshihiro }
444a3633fe7SShimoda, Yoshihiro 
445a3633fe7SShimoda, Yoshihiro static void rspi_dma_unmap_sg(struct scatterlist *sg, struct dma_chan *chan,
446a3633fe7SShimoda, Yoshihiro 			      enum dma_transfer_direction dir)
447a3633fe7SShimoda, Yoshihiro {
448a3633fe7SShimoda, Yoshihiro 	dma_unmap_sg(chan->device->dev, sg, 1, dir);
449a3633fe7SShimoda, Yoshihiro }
450a3633fe7SShimoda, Yoshihiro 
451a3633fe7SShimoda, Yoshihiro static void rspi_memory_to_8bit(void *buf, const void *data, unsigned len)
452a3633fe7SShimoda, Yoshihiro {
453a3633fe7SShimoda, Yoshihiro 	u16 *dst = buf;
454a3633fe7SShimoda, Yoshihiro 	const u8 *src = data;
455a3633fe7SShimoda, Yoshihiro 
456a3633fe7SShimoda, Yoshihiro 	while (len) {
457a3633fe7SShimoda, Yoshihiro 		*dst++ = (u16)(*src++);
458a3633fe7SShimoda, Yoshihiro 		len--;
459a3633fe7SShimoda, Yoshihiro 	}
460a3633fe7SShimoda, Yoshihiro }
461a3633fe7SShimoda, Yoshihiro 
462a3633fe7SShimoda, Yoshihiro static void rspi_memory_from_8bit(void *buf, const void *data, unsigned len)
463a3633fe7SShimoda, Yoshihiro {
464a3633fe7SShimoda, Yoshihiro 	u8 *dst = buf;
465a3633fe7SShimoda, Yoshihiro 	const u16 *src = data;
466a3633fe7SShimoda, Yoshihiro 
467a3633fe7SShimoda, Yoshihiro 	while (len) {
468a3633fe7SShimoda, Yoshihiro 		*dst++ = (u8)*src++;
469a3633fe7SShimoda, Yoshihiro 		len--;
470a3633fe7SShimoda, Yoshihiro 	}
471a3633fe7SShimoda, Yoshihiro }
472a3633fe7SShimoda, Yoshihiro 
473a3633fe7SShimoda, Yoshihiro static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
474a3633fe7SShimoda, Yoshihiro {
475a3633fe7SShimoda, Yoshihiro 	struct scatterlist sg;
476c132f094SGeert Uytterhoeven 	const void *buf = NULL;
477a3633fe7SShimoda, Yoshihiro 	struct dma_async_tx_descriptor *desc;
47893722206SGeert Uytterhoeven 	unsigned int len;
479a3633fe7SShimoda, Yoshihiro 	int ret = 0;
480a3633fe7SShimoda, Yoshihiro 
481a3633fe7SShimoda, Yoshihiro 	if (rspi->dma_width_16bit) {
482c132f094SGeert Uytterhoeven 		void *tmp;
483a3633fe7SShimoda, Yoshihiro 		/*
484a3633fe7SShimoda, Yoshihiro 		 * If DMAC bus width is 16-bit, the driver allocates a dummy
485a3633fe7SShimoda, Yoshihiro 		 * buffer. And, the driver converts original data into the
486a3633fe7SShimoda, Yoshihiro 		 * DMAC data as the following format:
487a3633fe7SShimoda, Yoshihiro 		 *  original data: 1st byte, 2nd byte ...
488a3633fe7SShimoda, Yoshihiro 		 *  DMAC data:     1st byte, dummy, 2nd byte, dummy ...
489a3633fe7SShimoda, Yoshihiro 		 */
490a3633fe7SShimoda, Yoshihiro 		len = t->len * 2;
491c132f094SGeert Uytterhoeven 		tmp = kmalloc(len, GFP_KERNEL);
492c132f094SGeert Uytterhoeven 		if (!tmp)
493a3633fe7SShimoda, Yoshihiro 			return -ENOMEM;
494c132f094SGeert Uytterhoeven 		rspi_memory_to_8bit(tmp, t->tx_buf, t->len);
495c132f094SGeert Uytterhoeven 		buf = tmp;
496a3633fe7SShimoda, Yoshihiro 	} else {
497a3633fe7SShimoda, Yoshihiro 		len = t->len;
498c132f094SGeert Uytterhoeven 		buf = t->tx_buf;
499a3633fe7SShimoda, Yoshihiro 	}
500a3633fe7SShimoda, Yoshihiro 
501a3633fe7SShimoda, Yoshihiro 	if (!rspi_dma_map_sg(&sg, buf, len, rspi->chan_tx, DMA_TO_DEVICE)) {
502a3633fe7SShimoda, Yoshihiro 		ret = -EFAULT;
503a3633fe7SShimoda, Yoshihiro 		goto end_nomap;
504a3633fe7SShimoda, Yoshihiro 	}
505a3633fe7SShimoda, Yoshihiro 	desc = dmaengine_prep_slave_sg(rspi->chan_tx, &sg, 1, DMA_TO_DEVICE,
506a3633fe7SShimoda, Yoshihiro 				       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
507a3633fe7SShimoda, Yoshihiro 	if (!desc) {
508a3633fe7SShimoda, Yoshihiro 		ret = -EIO;
509a3633fe7SShimoda, Yoshihiro 		goto end;
510a3633fe7SShimoda, Yoshihiro 	}
511a3633fe7SShimoda, Yoshihiro 
512a3633fe7SShimoda, Yoshihiro 	/*
513a3633fe7SShimoda, Yoshihiro 	 * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
514a3633fe7SShimoda, Yoshihiro 	 * called. So, this driver disables the IRQ while DMA transfer.
515a3633fe7SShimoda, Yoshihiro 	 */
51693722206SGeert Uytterhoeven 	disable_irq(rspi->tx_irq);
517a3633fe7SShimoda, Yoshihiro 
518a3633fe7SShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD, RSPI_SPCR);
519a3633fe7SShimoda, Yoshihiro 	rspi_enable_irq(rspi, SPCR_SPTIE);
520a3633fe7SShimoda, Yoshihiro 	rspi->dma_callbacked = 0;
521a3633fe7SShimoda, Yoshihiro 
522a3633fe7SShimoda, Yoshihiro 	desc->callback = rspi_dma_complete;
523a3633fe7SShimoda, Yoshihiro 	desc->callback_param = rspi;
524a3633fe7SShimoda, Yoshihiro 	dmaengine_submit(desc);
525a3633fe7SShimoda, Yoshihiro 	dma_async_issue_pending(rspi->chan_tx);
526a3633fe7SShimoda, Yoshihiro 
527a3633fe7SShimoda, Yoshihiro 	ret = wait_event_interruptible_timeout(rspi->wait,
528a3633fe7SShimoda, Yoshihiro 					       rspi->dma_callbacked, HZ);
529a3633fe7SShimoda, Yoshihiro 	if (ret > 0 && rspi->dma_callbacked)
530a3633fe7SShimoda, Yoshihiro 		ret = 0;
531a3633fe7SShimoda, Yoshihiro 	else if (!ret)
532a3633fe7SShimoda, Yoshihiro 		ret = -ETIMEDOUT;
533a3633fe7SShimoda, Yoshihiro 	rspi_disable_irq(rspi, SPCR_SPTIE);
534a3633fe7SShimoda, Yoshihiro 
53593722206SGeert Uytterhoeven 	enable_irq(rspi->tx_irq);
536a3633fe7SShimoda, Yoshihiro 
537a3633fe7SShimoda, Yoshihiro end:
538a3633fe7SShimoda, Yoshihiro 	rspi_dma_unmap_sg(&sg, rspi->chan_tx, DMA_TO_DEVICE);
539a3633fe7SShimoda, Yoshihiro end_nomap:
540a3633fe7SShimoda, Yoshihiro 	if (rspi->dma_width_16bit)
541a3633fe7SShimoda, Yoshihiro 		kfree(buf);
542a3633fe7SShimoda, Yoshihiro 
543a3633fe7SShimoda, Yoshihiro 	return ret;
544a3633fe7SShimoda, Yoshihiro }
545a3633fe7SShimoda, Yoshihiro 
546baf588f4SGeert Uytterhoeven static void rspi_receive_init(const struct rspi_data *rspi)
547a3633fe7SShimoda, Yoshihiro {
54897b95c11SGeert Uytterhoeven 	u8 spsr;
5490b2182ddSShimoda, Yoshihiro 
5500b2182ddSShimoda, Yoshihiro 	spsr = rspi_read8(rspi, RSPI_SPSR);
5510b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPRF)
55274da7686SGeert Uytterhoeven 		rspi_read_data(rspi);	/* dummy read */
5530b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_OVRF)
5540b2182ddSShimoda, Yoshihiro 		rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF,
555df900e67SGeert Uytterhoeven 			    RSPI_SPSR);
556a3633fe7SShimoda, Yoshihiro }
557a3633fe7SShimoda, Yoshihiro 
558862d357fSGeert Uytterhoeven static void rspi_rz_receive_init(const struct rspi_data *rspi)
559862d357fSGeert Uytterhoeven {
560862d357fSGeert Uytterhoeven 	rspi_receive_init(rspi);
561862d357fSGeert Uytterhoeven 	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, RSPI_SPBFCR);
562862d357fSGeert Uytterhoeven 	rspi_write8(rspi, 0, RSPI_SPBFCR);
563862d357fSGeert Uytterhoeven }
564862d357fSGeert Uytterhoeven 
565baf588f4SGeert Uytterhoeven static void qspi_receive_init(const struct rspi_data *rspi)
566cb52c673SHiep Cao Minh {
56797b95c11SGeert Uytterhoeven 	u8 spsr;
568cb52c673SHiep Cao Minh 
569cb52c673SHiep Cao Minh 	spsr = rspi_read8(rspi, RSPI_SPSR);
570cb52c673SHiep Cao Minh 	if (spsr & SPSR_SPRF)
57174da7686SGeert Uytterhoeven 		rspi_read_data(rspi);   /* dummy read */
572cb52c673SHiep Cao Minh 	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
573340a15e6SGeert Uytterhoeven 	rspi_write8(rspi, 0, QSPI_SPBFCR);
574cb52c673SHiep Cao Minh }
575cb52c673SHiep Cao Minh 
576a3633fe7SShimoda, Yoshihiro static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
577a3633fe7SShimoda, Yoshihiro {
578a3633fe7SShimoda, Yoshihiro 	struct scatterlist sg, sg_dummy;
579a3633fe7SShimoda, Yoshihiro 	void *dummy = NULL, *rx_buf = NULL;
580a3633fe7SShimoda, Yoshihiro 	struct dma_async_tx_descriptor *desc, *desc_dummy;
58193722206SGeert Uytterhoeven 	unsigned int len;
582a3633fe7SShimoda, Yoshihiro 	int ret = 0;
583a3633fe7SShimoda, Yoshihiro 
584a3633fe7SShimoda, Yoshihiro 	if (rspi->dma_width_16bit) {
585a3633fe7SShimoda, Yoshihiro 		/*
586a3633fe7SShimoda, Yoshihiro 		 * If DMAC bus width is 16-bit, the driver allocates a dummy
587a3633fe7SShimoda, Yoshihiro 		 * buffer. And, finally the driver converts the DMAC data into
588a3633fe7SShimoda, Yoshihiro 		 * actual data as the following format:
589a3633fe7SShimoda, Yoshihiro 		 *  DMAC data:   1st byte, dummy, 2nd byte, dummy ...
590a3633fe7SShimoda, Yoshihiro 		 *  actual data: 1st byte, 2nd byte ...
591a3633fe7SShimoda, Yoshihiro 		 */
592a3633fe7SShimoda, Yoshihiro 		len = t->len * 2;
593a3633fe7SShimoda, Yoshihiro 		rx_buf = kmalloc(len, GFP_KERNEL);
594a3633fe7SShimoda, Yoshihiro 		if (!rx_buf)
595a3633fe7SShimoda, Yoshihiro 			return -ENOMEM;
596a3633fe7SShimoda, Yoshihiro 	 } else {
597a3633fe7SShimoda, Yoshihiro 		len = t->len;
598a3633fe7SShimoda, Yoshihiro 		rx_buf = t->rx_buf;
599a3633fe7SShimoda, Yoshihiro 	}
600a3633fe7SShimoda, Yoshihiro 
601a3633fe7SShimoda, Yoshihiro 	/* prepare dummy transfer to generate SPI clocks */
602a3633fe7SShimoda, Yoshihiro 	dummy = kzalloc(len, GFP_KERNEL);
603a3633fe7SShimoda, Yoshihiro 	if (!dummy) {
604a3633fe7SShimoda, Yoshihiro 		ret = -ENOMEM;
605a3633fe7SShimoda, Yoshihiro 		goto end_nomap;
606a3633fe7SShimoda, Yoshihiro 	}
607a3633fe7SShimoda, Yoshihiro 	if (!rspi_dma_map_sg(&sg_dummy, dummy, len, rspi->chan_tx,
608a3633fe7SShimoda, Yoshihiro 			     DMA_TO_DEVICE)) {
609a3633fe7SShimoda, Yoshihiro 		ret = -EFAULT;
610a3633fe7SShimoda, Yoshihiro 		goto end_nomap;
611a3633fe7SShimoda, Yoshihiro 	}
612a3633fe7SShimoda, Yoshihiro 	desc_dummy = dmaengine_prep_slave_sg(rspi->chan_tx, &sg_dummy, 1,
613a3633fe7SShimoda, Yoshihiro 			DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
614a3633fe7SShimoda, Yoshihiro 	if (!desc_dummy) {
615a3633fe7SShimoda, Yoshihiro 		ret = -EIO;
616a3633fe7SShimoda, Yoshihiro 		goto end_dummy_mapped;
617a3633fe7SShimoda, Yoshihiro 	}
618a3633fe7SShimoda, Yoshihiro 
619a3633fe7SShimoda, Yoshihiro 	/* prepare receive transfer */
620a3633fe7SShimoda, Yoshihiro 	if (!rspi_dma_map_sg(&sg, rx_buf, len, rspi->chan_rx,
621a3633fe7SShimoda, Yoshihiro 			     DMA_FROM_DEVICE)) {
622a3633fe7SShimoda, Yoshihiro 		ret = -EFAULT;
623a3633fe7SShimoda, Yoshihiro 		goto end_dummy_mapped;
624a3633fe7SShimoda, Yoshihiro 
625a3633fe7SShimoda, Yoshihiro 	}
626a3633fe7SShimoda, Yoshihiro 	desc = dmaengine_prep_slave_sg(rspi->chan_rx, &sg, 1, DMA_FROM_DEVICE,
627a3633fe7SShimoda, Yoshihiro 				       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
628a3633fe7SShimoda, Yoshihiro 	if (!desc) {
629a3633fe7SShimoda, Yoshihiro 		ret = -EIO;
630a3633fe7SShimoda, Yoshihiro 		goto end;
631a3633fe7SShimoda, Yoshihiro 	}
632a3633fe7SShimoda, Yoshihiro 
633a3633fe7SShimoda, Yoshihiro 	rspi_receive_init(rspi);
634a3633fe7SShimoda, Yoshihiro 
635a3633fe7SShimoda, Yoshihiro 	/*
636a3633fe7SShimoda, Yoshihiro 	 * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
637a3633fe7SShimoda, Yoshihiro 	 * called. So, this driver disables the IRQ while DMA transfer.
638a3633fe7SShimoda, Yoshihiro 	 */
63993722206SGeert Uytterhoeven 	disable_irq(rspi->tx_irq);
64093722206SGeert Uytterhoeven 	if (rspi->rx_irq != rspi->tx_irq)
64193722206SGeert Uytterhoeven 		disable_irq(rspi->rx_irq);
642a3633fe7SShimoda, Yoshihiro 
643a3633fe7SShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD, RSPI_SPCR);
644a3633fe7SShimoda, Yoshihiro 	rspi_enable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
645a3633fe7SShimoda, Yoshihiro 	rspi->dma_callbacked = 0;
646a3633fe7SShimoda, Yoshihiro 
647a3633fe7SShimoda, Yoshihiro 	desc->callback = rspi_dma_complete;
648a3633fe7SShimoda, Yoshihiro 	desc->callback_param = rspi;
649a3633fe7SShimoda, Yoshihiro 	dmaengine_submit(desc);
650a3633fe7SShimoda, Yoshihiro 	dma_async_issue_pending(rspi->chan_rx);
651a3633fe7SShimoda, Yoshihiro 
652a3633fe7SShimoda, Yoshihiro 	desc_dummy->callback = NULL;	/* No callback */
653a3633fe7SShimoda, Yoshihiro 	dmaengine_submit(desc_dummy);
654a3633fe7SShimoda, Yoshihiro 	dma_async_issue_pending(rspi->chan_tx);
655a3633fe7SShimoda, Yoshihiro 
656a3633fe7SShimoda, Yoshihiro 	ret = wait_event_interruptible_timeout(rspi->wait,
657a3633fe7SShimoda, Yoshihiro 					       rspi->dma_callbacked, HZ);
658a3633fe7SShimoda, Yoshihiro 	if (ret > 0 && rspi->dma_callbacked)
659a3633fe7SShimoda, Yoshihiro 		ret = 0;
660a3633fe7SShimoda, Yoshihiro 	else if (!ret)
661a3633fe7SShimoda, Yoshihiro 		ret = -ETIMEDOUT;
662a3633fe7SShimoda, Yoshihiro 	rspi_disable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
663a3633fe7SShimoda, Yoshihiro 
66493722206SGeert Uytterhoeven 	enable_irq(rspi->tx_irq);
66593722206SGeert Uytterhoeven 	if (rspi->rx_irq != rspi->tx_irq)
66693722206SGeert Uytterhoeven 		enable_irq(rspi->rx_irq);
667a3633fe7SShimoda, Yoshihiro 
668a3633fe7SShimoda, Yoshihiro end:
669a3633fe7SShimoda, Yoshihiro 	rspi_dma_unmap_sg(&sg, rspi->chan_rx, DMA_FROM_DEVICE);
670a3633fe7SShimoda, Yoshihiro end_dummy_mapped:
671a3633fe7SShimoda, Yoshihiro 	rspi_dma_unmap_sg(&sg_dummy, rspi->chan_tx, DMA_TO_DEVICE);
672a3633fe7SShimoda, Yoshihiro end_nomap:
673a3633fe7SShimoda, Yoshihiro 	if (rspi->dma_width_16bit) {
674a3633fe7SShimoda, Yoshihiro 		if (!ret)
675a3633fe7SShimoda, Yoshihiro 			rspi_memory_from_8bit(t->rx_buf, rx_buf, t->len);
676a3633fe7SShimoda, Yoshihiro 		kfree(rx_buf);
677a3633fe7SShimoda, Yoshihiro 	}
678a3633fe7SShimoda, Yoshihiro 	kfree(dummy);
679a3633fe7SShimoda, Yoshihiro 
680a3633fe7SShimoda, Yoshihiro 	return ret;
681a3633fe7SShimoda, Yoshihiro }
682a3633fe7SShimoda, Yoshihiro 
683baf588f4SGeert Uytterhoeven static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t)
684a3633fe7SShimoda, Yoshihiro {
685a3633fe7SShimoda, Yoshihiro 	if (t->tx_buf && rspi->chan_tx)
686a3633fe7SShimoda, Yoshihiro 		return 1;
687a3633fe7SShimoda, Yoshihiro 	/* If the module receives data by DMAC, it also needs TX DMAC */
688a3633fe7SShimoda, Yoshihiro 	if (t->rx_buf && rspi->chan_tx && rspi->chan_rx)
689a3633fe7SShimoda, Yoshihiro 		return 1;
690a3633fe7SShimoda, Yoshihiro 
691a3633fe7SShimoda, Yoshihiro 	return 0;
692a3633fe7SShimoda, Yoshihiro }
693a3633fe7SShimoda, Yoshihiro 
6948449fd76SGeert Uytterhoeven static int rspi_transfer_out_in(struct rspi_data *rspi,
6958449fd76SGeert Uytterhoeven 				struct spi_transfer *xfer)
6968449fd76SGeert Uytterhoeven {
6978449fd76SGeert Uytterhoeven 	int remain = xfer->len, ret;
6988449fd76SGeert Uytterhoeven 	const u8 *tx_buf = xfer->tx_buf;
6998449fd76SGeert Uytterhoeven 	u8 *rx_buf = xfer->rx_buf;
7008449fd76SGeert Uytterhoeven 	u8 spcr, data;
7018449fd76SGeert Uytterhoeven 
7028449fd76SGeert Uytterhoeven 	rspi_receive_init(rspi);
7038449fd76SGeert Uytterhoeven 
7048449fd76SGeert Uytterhoeven 	spcr = rspi_read8(rspi, RSPI_SPCR);
7058449fd76SGeert Uytterhoeven 	if (rx_buf)
7068449fd76SGeert Uytterhoeven 		spcr &= ~SPCR_TXMD;
7078449fd76SGeert Uytterhoeven 	else
7088449fd76SGeert Uytterhoeven 		spcr |= SPCR_TXMD;
7098449fd76SGeert Uytterhoeven 	rspi_write8(rspi, spcr, RSPI_SPCR);
7108449fd76SGeert Uytterhoeven 
7118449fd76SGeert Uytterhoeven 	while (remain > 0) {
7128449fd76SGeert Uytterhoeven 		data = tx_buf ? *tx_buf++ : DUMMY_DATA;
7138449fd76SGeert Uytterhoeven 		ret = rspi_data_out(rspi, data);
7148449fd76SGeert Uytterhoeven 		if (ret < 0)
7158449fd76SGeert Uytterhoeven 			return ret;
7168449fd76SGeert Uytterhoeven 		if (rx_buf) {
7178449fd76SGeert Uytterhoeven 			ret = rspi_data_in(rspi);
7188449fd76SGeert Uytterhoeven 			if (ret < 0)
7198449fd76SGeert Uytterhoeven 				return ret;
7208449fd76SGeert Uytterhoeven 			*rx_buf++ = ret;
7218449fd76SGeert Uytterhoeven 		}
7228449fd76SGeert Uytterhoeven 		remain--;
7238449fd76SGeert Uytterhoeven 	}
7248449fd76SGeert Uytterhoeven 
7258449fd76SGeert Uytterhoeven 	/* Wait for the last transmission */
7268449fd76SGeert Uytterhoeven 	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
7278449fd76SGeert Uytterhoeven 
7288449fd76SGeert Uytterhoeven 	return 0;
7298449fd76SGeert Uytterhoeven }
7308449fd76SGeert Uytterhoeven 
73179d23495SGeert Uytterhoeven static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
73279d23495SGeert Uytterhoeven 			     struct spi_transfer *xfer)
7330b2182ddSShimoda, Yoshihiro {
73479d23495SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
7358449fd76SGeert Uytterhoeven 	int ret;
7368449fd76SGeert Uytterhoeven 
7378449fd76SGeert Uytterhoeven 	if (!rspi_is_dma(rspi, xfer))
7388449fd76SGeert Uytterhoeven 		return rspi_transfer_out_in(rspi, xfer);
7390b2182ddSShimoda, Yoshihiro 
74079d23495SGeert Uytterhoeven 	if (xfer->tx_buf) {
74179d23495SGeert Uytterhoeven 		ret = rspi_send_dma(rspi, xfer);
7420b2182ddSShimoda, Yoshihiro 		if (ret < 0)
74379d23495SGeert Uytterhoeven 			return ret;
7440b2182ddSShimoda, Yoshihiro 	}
7458449fd76SGeert Uytterhoeven 	if (xfer->rx_buf)
7468449fd76SGeert Uytterhoeven 		return rspi_receive_dma(rspi, xfer);
7478449fd76SGeert Uytterhoeven 
7488449fd76SGeert Uytterhoeven 	return 0;
7490b2182ddSShimoda, Yoshihiro }
7500b2182ddSShimoda, Yoshihiro 
751862d357fSGeert Uytterhoeven static int rspi_rz_transfer_out_in(struct rspi_data *rspi,
752862d357fSGeert Uytterhoeven 				   struct spi_transfer *xfer)
753862d357fSGeert Uytterhoeven {
754862d357fSGeert Uytterhoeven 	int remain = xfer->len, ret;
755862d357fSGeert Uytterhoeven 	const u8 *tx_buf = xfer->tx_buf;
756862d357fSGeert Uytterhoeven 	u8 *rx_buf = xfer->rx_buf;
757862d357fSGeert Uytterhoeven 	u8 data;
758862d357fSGeert Uytterhoeven 
759862d357fSGeert Uytterhoeven 	rspi_rz_receive_init(rspi);
760862d357fSGeert Uytterhoeven 
761862d357fSGeert Uytterhoeven 	while (remain > 0) {
762862d357fSGeert Uytterhoeven 		data = tx_buf ? *tx_buf++ : DUMMY_DATA;
763862d357fSGeert Uytterhoeven 		ret = rspi_data_out_in(rspi, data);
764862d357fSGeert Uytterhoeven 		if (ret < 0)
765862d357fSGeert Uytterhoeven 			return ret;
766862d357fSGeert Uytterhoeven 		if (rx_buf)
767862d357fSGeert Uytterhoeven 			*rx_buf++ = ret;
768862d357fSGeert Uytterhoeven 		remain--;
769862d357fSGeert Uytterhoeven 	}
770862d357fSGeert Uytterhoeven 
771862d357fSGeert Uytterhoeven 	/* Wait for the last transmission */
772862d357fSGeert Uytterhoeven 	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
773862d357fSGeert Uytterhoeven 
774862d357fSGeert Uytterhoeven 	return 0;
775862d357fSGeert Uytterhoeven }
776862d357fSGeert Uytterhoeven 
777862d357fSGeert Uytterhoeven static int rspi_rz_transfer_one(struct spi_master *master,
778862d357fSGeert Uytterhoeven 				struct spi_device *spi,
779862d357fSGeert Uytterhoeven 				struct spi_transfer *xfer)
780862d357fSGeert Uytterhoeven {
781862d357fSGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
782862d357fSGeert Uytterhoeven 
783862d357fSGeert Uytterhoeven 	return rspi_rz_transfer_out_in(rspi, xfer);
784862d357fSGeert Uytterhoeven }
785862d357fSGeert Uytterhoeven 
786340a15e6SGeert Uytterhoeven static int qspi_transfer_out_in(struct rspi_data *rspi,
787340a15e6SGeert Uytterhoeven 				struct spi_transfer *xfer)
788340a15e6SGeert Uytterhoeven {
789340a15e6SGeert Uytterhoeven 	int remain = xfer->len, ret;
790340a15e6SGeert Uytterhoeven 	const u8 *tx_buf = xfer->tx_buf;
791340a15e6SGeert Uytterhoeven 	u8 *rx_buf = xfer->rx_buf;
792340a15e6SGeert Uytterhoeven 	u8 data;
793340a15e6SGeert Uytterhoeven 
794340a15e6SGeert Uytterhoeven 	qspi_receive_init(rspi);
795340a15e6SGeert Uytterhoeven 
796340a15e6SGeert Uytterhoeven 	while (remain > 0) {
797340a15e6SGeert Uytterhoeven 		data = tx_buf ? *tx_buf++ : DUMMY_DATA;
798340a15e6SGeert Uytterhoeven 		ret = rspi_data_out_in(rspi, data);
799340a15e6SGeert Uytterhoeven 		if (ret < 0)
800340a15e6SGeert Uytterhoeven 			return ret;
801340a15e6SGeert Uytterhoeven 		if (rx_buf)
802340a15e6SGeert Uytterhoeven 			*rx_buf++ = ret;
803340a15e6SGeert Uytterhoeven 		remain--;
804340a15e6SGeert Uytterhoeven 	}
805340a15e6SGeert Uytterhoeven 
806340a15e6SGeert Uytterhoeven 	/* Wait for the last transmission */
807340a15e6SGeert Uytterhoeven 	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
808340a15e6SGeert Uytterhoeven 
809340a15e6SGeert Uytterhoeven 	return 0;
810340a15e6SGeert Uytterhoeven }
811340a15e6SGeert Uytterhoeven 
812eb557f75SGeert Uytterhoeven static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi,
813eb557f75SGeert Uytterhoeven 			     struct spi_transfer *xfer)
814eb557f75SGeert Uytterhoeven {
815eb557f75SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
816eb557f75SGeert Uytterhoeven 
817340a15e6SGeert Uytterhoeven 	return qspi_transfer_out_in(rspi, xfer);
818eb557f75SGeert Uytterhoeven }
819eb557f75SGeert Uytterhoeven 
8200b2182ddSShimoda, Yoshihiro static int rspi_setup(struct spi_device *spi)
8210b2182ddSShimoda, Yoshihiro {
8220b2182ddSShimoda, Yoshihiro 	struct rspi_data *rspi = spi_master_get_devdata(spi->master);
8230b2182ddSShimoda, Yoshihiro 
8240b2182ddSShimoda, Yoshihiro 	rspi->max_speed_hz = spi->max_speed_hz;
8250b2182ddSShimoda, Yoshihiro 
826348e5153SGeert Uytterhoeven 	rspi->spcmd = SPCMD_SSLKP;
827348e5153SGeert Uytterhoeven 	if (spi->mode & SPI_CPOL)
828348e5153SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_CPOL;
829348e5153SGeert Uytterhoeven 	if (spi->mode & SPI_CPHA)
830348e5153SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_CPHA;
831348e5153SGeert Uytterhoeven 
8325ce0ba88SHiep Cao Minh 	set_config_register(rspi, 8);
8330b2182ddSShimoda, Yoshihiro 
8340b2182ddSShimoda, Yoshihiro 	return 0;
8350b2182ddSShimoda, Yoshihiro }
8360b2182ddSShimoda, Yoshihiro 
83779d23495SGeert Uytterhoeven static void rspi_cleanup(struct spi_device *spi)
8380b2182ddSShimoda, Yoshihiro {
83979d23495SGeert Uytterhoeven }
8400b2182ddSShimoda, Yoshihiro 
84179d23495SGeert Uytterhoeven static int rspi_prepare_message(struct spi_master *master,
84279d23495SGeert Uytterhoeven 				struct spi_message *message)
84379d23495SGeert Uytterhoeven {
84479d23495SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
8450b2182ddSShimoda, Yoshihiro 
84679d23495SGeert Uytterhoeven 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
8470b2182ddSShimoda, Yoshihiro 	return 0;
8480b2182ddSShimoda, Yoshihiro }
8490b2182ddSShimoda, Yoshihiro 
85079d23495SGeert Uytterhoeven static int rspi_unprepare_message(struct spi_master *master,
85179d23495SGeert Uytterhoeven 				  struct spi_message *message)
8520b2182ddSShimoda, Yoshihiro {
85379d23495SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
85479d23495SGeert Uytterhoeven 
85579d23495SGeert Uytterhoeven 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
85679d23495SGeert Uytterhoeven 	return 0;
8570b2182ddSShimoda, Yoshihiro }
8580b2182ddSShimoda, Yoshihiro 
85993722206SGeert Uytterhoeven static irqreturn_t rspi_irq_mux(int irq, void *_sr)
8600b2182ddSShimoda, Yoshihiro {
861c132f094SGeert Uytterhoeven 	struct rspi_data *rspi = _sr;
86297b95c11SGeert Uytterhoeven 	u8 spsr;
8630b2182ddSShimoda, Yoshihiro 	irqreturn_t ret = IRQ_NONE;
86497b95c11SGeert Uytterhoeven 	u8 disable_irq = 0;
8650b2182ddSShimoda, Yoshihiro 
8660b2182ddSShimoda, Yoshihiro 	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
8670b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPRF)
8680b2182ddSShimoda, Yoshihiro 		disable_irq |= SPCR_SPRIE;
8690b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPTEF)
8700b2182ddSShimoda, Yoshihiro 		disable_irq |= SPCR_SPTIE;
8710b2182ddSShimoda, Yoshihiro 
8720b2182ddSShimoda, Yoshihiro 	if (disable_irq) {
8730b2182ddSShimoda, Yoshihiro 		ret = IRQ_HANDLED;
8740b2182ddSShimoda, Yoshihiro 		rspi_disable_irq(rspi, disable_irq);
8750b2182ddSShimoda, Yoshihiro 		wake_up(&rspi->wait);
8760b2182ddSShimoda, Yoshihiro 	}
8770b2182ddSShimoda, Yoshihiro 
8780b2182ddSShimoda, Yoshihiro 	return ret;
8790b2182ddSShimoda, Yoshihiro }
8800b2182ddSShimoda, Yoshihiro 
88193722206SGeert Uytterhoeven static irqreturn_t rspi_irq_rx(int irq, void *_sr)
88293722206SGeert Uytterhoeven {
88393722206SGeert Uytterhoeven 	struct rspi_data *rspi = _sr;
88493722206SGeert Uytterhoeven 	u8 spsr;
88593722206SGeert Uytterhoeven 
88693722206SGeert Uytterhoeven 	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
88793722206SGeert Uytterhoeven 	if (spsr & SPSR_SPRF) {
88893722206SGeert Uytterhoeven 		rspi_disable_irq(rspi, SPCR_SPRIE);
88993722206SGeert Uytterhoeven 		wake_up(&rspi->wait);
89093722206SGeert Uytterhoeven 		return IRQ_HANDLED;
89193722206SGeert Uytterhoeven 	}
89293722206SGeert Uytterhoeven 
89393722206SGeert Uytterhoeven 	return 0;
89493722206SGeert Uytterhoeven }
89593722206SGeert Uytterhoeven 
89693722206SGeert Uytterhoeven static irqreturn_t rspi_irq_tx(int irq, void *_sr)
89793722206SGeert Uytterhoeven {
89893722206SGeert Uytterhoeven 	struct rspi_data *rspi = _sr;
89993722206SGeert Uytterhoeven 	u8 spsr;
90093722206SGeert Uytterhoeven 
90193722206SGeert Uytterhoeven 	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
90293722206SGeert Uytterhoeven 	if (spsr & SPSR_SPTEF) {
90393722206SGeert Uytterhoeven 		rspi_disable_irq(rspi, SPCR_SPTIE);
90493722206SGeert Uytterhoeven 		wake_up(&rspi->wait);
90593722206SGeert Uytterhoeven 		return IRQ_HANDLED;
90693722206SGeert Uytterhoeven 	}
90793722206SGeert Uytterhoeven 
90893722206SGeert Uytterhoeven 	return 0;
90993722206SGeert Uytterhoeven }
91093722206SGeert Uytterhoeven 
911fd4a319bSGrant Likely static int rspi_request_dma(struct rspi_data *rspi,
912a3633fe7SShimoda, Yoshihiro 				      struct platform_device *pdev)
913a3633fe7SShimoda, Yoshihiro {
914baf588f4SGeert Uytterhoeven 	const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
915e2b05099SGuennadi Liakhovetski 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
916a3633fe7SShimoda, Yoshihiro 	dma_cap_mask_t mask;
9170243c536SShimoda, Yoshihiro 	struct dma_slave_config cfg;
9180243c536SShimoda, Yoshihiro 	int ret;
919a3633fe7SShimoda, Yoshihiro 
920e2b05099SGuennadi Liakhovetski 	if (!res || !rspi_pd)
9210243c536SShimoda, Yoshihiro 		return 0;	/* The driver assumes no error. */
922a3633fe7SShimoda, Yoshihiro 
923a3633fe7SShimoda, Yoshihiro 	rspi->dma_width_16bit = rspi_pd->dma_width_16bit;
924a3633fe7SShimoda, Yoshihiro 
925a3633fe7SShimoda, Yoshihiro 	/* If the module receives data by DMAC, it also needs TX DMAC */
926a3633fe7SShimoda, Yoshihiro 	if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) {
927a3633fe7SShimoda, Yoshihiro 		dma_cap_zero(mask);
928a3633fe7SShimoda, Yoshihiro 		dma_cap_set(DMA_SLAVE, mask);
9290243c536SShimoda, Yoshihiro 		rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter,
9300243c536SShimoda, Yoshihiro 						    (void *)rspi_pd->dma_rx_id);
9310243c536SShimoda, Yoshihiro 		if (rspi->chan_rx) {
9320243c536SShimoda, Yoshihiro 			cfg.slave_id = rspi_pd->dma_rx_id;
9330243c536SShimoda, Yoshihiro 			cfg.direction = DMA_DEV_TO_MEM;
934e2b05099SGuennadi Liakhovetski 			cfg.dst_addr = 0;
935e2b05099SGuennadi Liakhovetski 			cfg.src_addr = res->start + RSPI_SPDR;
9360243c536SShimoda, Yoshihiro 			ret = dmaengine_slave_config(rspi->chan_rx, &cfg);
9370243c536SShimoda, Yoshihiro 			if (!ret)
938a3633fe7SShimoda, Yoshihiro 				dev_info(&pdev->dev, "Use DMA when rx.\n");
9390243c536SShimoda, Yoshihiro 			else
9400243c536SShimoda, Yoshihiro 				return ret;
9410243c536SShimoda, Yoshihiro 		}
942a3633fe7SShimoda, Yoshihiro 	}
943a3633fe7SShimoda, Yoshihiro 	if (rspi_pd->dma_tx_id) {
944a3633fe7SShimoda, Yoshihiro 		dma_cap_zero(mask);
945a3633fe7SShimoda, Yoshihiro 		dma_cap_set(DMA_SLAVE, mask);
9460243c536SShimoda, Yoshihiro 		rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter,
9470243c536SShimoda, Yoshihiro 						    (void *)rspi_pd->dma_tx_id);
9480243c536SShimoda, Yoshihiro 		if (rspi->chan_tx) {
9490243c536SShimoda, Yoshihiro 			cfg.slave_id = rspi_pd->dma_tx_id;
9500243c536SShimoda, Yoshihiro 			cfg.direction = DMA_MEM_TO_DEV;
951e2b05099SGuennadi Liakhovetski 			cfg.dst_addr = res->start + RSPI_SPDR;
952e2b05099SGuennadi Liakhovetski 			cfg.src_addr = 0;
9530243c536SShimoda, Yoshihiro 			ret = dmaengine_slave_config(rspi->chan_tx, &cfg);
9540243c536SShimoda, Yoshihiro 			if (!ret)
955a3633fe7SShimoda, Yoshihiro 				dev_info(&pdev->dev, "Use DMA when tx\n");
9560243c536SShimoda, Yoshihiro 			else
9570243c536SShimoda, Yoshihiro 				return ret;
958a3633fe7SShimoda, Yoshihiro 		}
959a3633fe7SShimoda, Yoshihiro 	}
960a3633fe7SShimoda, Yoshihiro 
9610243c536SShimoda, Yoshihiro 	return 0;
9620243c536SShimoda, Yoshihiro }
9630243c536SShimoda, Yoshihiro 
964fd4a319bSGrant Likely static void rspi_release_dma(struct rspi_data *rspi)
965a3633fe7SShimoda, Yoshihiro {
966a3633fe7SShimoda, Yoshihiro 	if (rspi->chan_tx)
967a3633fe7SShimoda, Yoshihiro 		dma_release_channel(rspi->chan_tx);
968a3633fe7SShimoda, Yoshihiro 	if (rspi->chan_rx)
969a3633fe7SShimoda, Yoshihiro 		dma_release_channel(rspi->chan_rx);
970a3633fe7SShimoda, Yoshihiro }
971a3633fe7SShimoda, Yoshihiro 
972fd4a319bSGrant Likely static int rspi_remove(struct platform_device *pdev)
9730b2182ddSShimoda, Yoshihiro {
9745ffbe2d9SLaurent Pinchart 	struct rspi_data *rspi = platform_get_drvdata(pdev);
9750b2182ddSShimoda, Yoshihiro 
976a3633fe7SShimoda, Yoshihiro 	rspi_release_dma(rspi);
977fcb4ed74SGeert Uytterhoeven 	clk_disable(rspi->clk);
9780b2182ddSShimoda, Yoshihiro 
9790b2182ddSShimoda, Yoshihiro 	return 0;
9800b2182ddSShimoda, Yoshihiro }
9810b2182ddSShimoda, Yoshihiro 
98293722206SGeert Uytterhoeven static int rspi_request_irq(struct device *dev, unsigned int irq,
98393722206SGeert Uytterhoeven 			    irq_handler_t handler, const char *suffix,
98493722206SGeert Uytterhoeven 			    void *dev_id)
98593722206SGeert Uytterhoeven {
98693722206SGeert Uytterhoeven 	const char *base = dev_name(dev);
98793722206SGeert Uytterhoeven 	size_t len = strlen(base) + strlen(suffix) + 2;
98893722206SGeert Uytterhoeven 	char *name = devm_kzalloc(dev, len, GFP_KERNEL);
98993722206SGeert Uytterhoeven 	if (!name)
99093722206SGeert Uytterhoeven 		return -ENOMEM;
99193722206SGeert Uytterhoeven 	snprintf(name, len, "%s:%s", base, suffix);
99293722206SGeert Uytterhoeven 	return devm_request_irq(dev, irq, handler, 0, name, dev_id);
99393722206SGeert Uytterhoeven }
99493722206SGeert Uytterhoeven 
995fd4a319bSGrant Likely static int rspi_probe(struct platform_device *pdev)
9960b2182ddSShimoda, Yoshihiro {
9970b2182ddSShimoda, Yoshihiro 	struct resource *res;
9980b2182ddSShimoda, Yoshihiro 	struct spi_master *master;
9990b2182ddSShimoda, Yoshihiro 	struct rspi_data *rspi;
100093722206SGeert Uytterhoeven 	int ret;
10010b2182ddSShimoda, Yoshihiro 	char clk_name[16];
1002baf588f4SGeert Uytterhoeven 	const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
10035ce0ba88SHiep Cao Minh 	const struct spi_ops *ops;
10045ce0ba88SHiep Cao Minh 	const struct platform_device_id *id_entry = pdev->id_entry;
10050b2182ddSShimoda, Yoshihiro 
10065ce0ba88SHiep Cao Minh 	ops = (struct spi_ops *)id_entry->driver_data;
10075ce0ba88SHiep Cao Minh 	/* ops parameter check */
10085ce0ba88SHiep Cao Minh 	if (!ops->set_config_register) {
10095ce0ba88SHiep Cao Minh 		dev_err(&pdev->dev, "there is no set_config_register\n");
10105ce0ba88SHiep Cao Minh 		return -ENODEV;
10115ce0ba88SHiep Cao Minh 	}
10120b2182ddSShimoda, Yoshihiro 
10130b2182ddSShimoda, Yoshihiro 	master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data));
10140b2182ddSShimoda, Yoshihiro 	if (master == NULL) {
10150b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "spi_alloc_master error.\n");
10160b2182ddSShimoda, Yoshihiro 		return -ENOMEM;
10170b2182ddSShimoda, Yoshihiro 	}
10180b2182ddSShimoda, Yoshihiro 
10190b2182ddSShimoda, Yoshihiro 	rspi = spi_master_get_devdata(master);
102024b5a82cSJingoo Han 	platform_set_drvdata(pdev, rspi);
10215ce0ba88SHiep Cao Minh 	rspi->ops = ops;
10220b2182ddSShimoda, Yoshihiro 	rspi->master = master;
10235d79e9acSLaurent Pinchart 
10245d79e9acSLaurent Pinchart 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
10255d79e9acSLaurent Pinchart 	rspi->addr = devm_ioremap_resource(&pdev->dev, res);
10265d79e9acSLaurent Pinchart 	if (IS_ERR(rspi->addr)) {
10275d79e9acSLaurent Pinchart 		ret = PTR_ERR(rspi->addr);
10280b2182ddSShimoda, Yoshihiro 		goto error1;
10290b2182ddSShimoda, Yoshihiro 	}
10300b2182ddSShimoda, Yoshihiro 
10315ce0ba88SHiep Cao Minh 	snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id);
10325d79e9acSLaurent Pinchart 	rspi->clk = devm_clk_get(&pdev->dev, clk_name);
10330b2182ddSShimoda, Yoshihiro 	if (IS_ERR(rspi->clk)) {
10340b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "cannot get clock\n");
10350b2182ddSShimoda, Yoshihiro 		ret = PTR_ERR(rspi->clk);
10365d79e9acSLaurent Pinchart 		goto error1;
10370b2182ddSShimoda, Yoshihiro 	}
10380b2182ddSShimoda, Yoshihiro 	clk_enable(rspi->clk);
10390b2182ddSShimoda, Yoshihiro 
10400b2182ddSShimoda, Yoshihiro 	init_waitqueue_head(&rspi->wait);
10410b2182ddSShimoda, Yoshihiro 
1042efd85acbSGeert Uytterhoeven 	if (rspi_pd && rspi_pd->num_chipselect)
10435ce0ba88SHiep Cao Minh 		master->num_chipselect = rspi_pd->num_chipselect;
1044efd85acbSGeert Uytterhoeven 	else
10455ce0ba88SHiep Cao Minh 		master->num_chipselect = 2; /* default */
10465ce0ba88SHiep Cao Minh 
10470b2182ddSShimoda, Yoshihiro 	master->bus_num = pdev->id;
10480b2182ddSShimoda, Yoshihiro 	master->setup = rspi_setup;
1049eb557f75SGeert Uytterhoeven 	master->transfer_one = ops->transfer_one;
10500b2182ddSShimoda, Yoshihiro 	master->cleanup = rspi_cleanup;
105179d23495SGeert Uytterhoeven 	master->prepare_message = rspi_prepare_message;
105279d23495SGeert Uytterhoeven 	master->unprepare_message = rspi_unprepare_message;
1053348e5153SGeert Uytterhoeven 	master->mode_bits = SPI_CPHA | SPI_CPOL;
10540b2182ddSShimoda, Yoshihiro 
105593722206SGeert Uytterhoeven 	ret = platform_get_irq_byname(pdev, "rx");
105693722206SGeert Uytterhoeven 	if (ret < 0) {
105793722206SGeert Uytterhoeven 		ret = platform_get_irq_byname(pdev, "mux");
105893722206SGeert Uytterhoeven 		if (ret < 0)
105993722206SGeert Uytterhoeven 			ret = platform_get_irq(pdev, 0);
106093722206SGeert Uytterhoeven 		if (ret >= 0)
106193722206SGeert Uytterhoeven 			rspi->rx_irq = rspi->tx_irq = ret;
106293722206SGeert Uytterhoeven 	} else {
106393722206SGeert Uytterhoeven 		rspi->rx_irq = ret;
106493722206SGeert Uytterhoeven 		ret = platform_get_irq_byname(pdev, "tx");
106593722206SGeert Uytterhoeven 		if (ret >= 0)
106693722206SGeert Uytterhoeven 			rspi->tx_irq = ret;
106793722206SGeert Uytterhoeven 	}
106893722206SGeert Uytterhoeven 	if (ret < 0) {
106993722206SGeert Uytterhoeven 		dev_err(&pdev->dev, "platform_get_irq error\n");
107093722206SGeert Uytterhoeven 		goto error2;
107193722206SGeert Uytterhoeven 	}
107293722206SGeert Uytterhoeven 
107393722206SGeert Uytterhoeven 	if (rspi->rx_irq == rspi->tx_irq) {
107493722206SGeert Uytterhoeven 		/* Single multiplexed interrupt */
107593722206SGeert Uytterhoeven 		ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_mux,
107693722206SGeert Uytterhoeven 				       "mux", rspi);
107793722206SGeert Uytterhoeven 	} else {
107893722206SGeert Uytterhoeven 		/* Multi-interrupt mode, only SPRI and SPTI are used */
107993722206SGeert Uytterhoeven 		ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_rx,
108093722206SGeert Uytterhoeven 				       "rx", rspi);
108193722206SGeert Uytterhoeven 		if (!ret)
108293722206SGeert Uytterhoeven 			ret = rspi_request_irq(&pdev->dev, rspi->tx_irq,
108393722206SGeert Uytterhoeven 					       rspi_irq_tx, "tx", rspi);
108493722206SGeert Uytterhoeven 	}
10850b2182ddSShimoda, Yoshihiro 	if (ret < 0) {
10860b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "request_irq error\n");
1087fcb4ed74SGeert Uytterhoeven 		goto error2;
10880b2182ddSShimoda, Yoshihiro 	}
10890b2182ddSShimoda, Yoshihiro 
10900243c536SShimoda, Yoshihiro 	ret = rspi_request_dma(rspi, pdev);
10910243c536SShimoda, Yoshihiro 	if (ret < 0) {
10920243c536SShimoda, Yoshihiro 		dev_err(&pdev->dev, "rspi_request_dma failed.\n");
1093fcb4ed74SGeert Uytterhoeven 		goto error3;
10940243c536SShimoda, Yoshihiro 	}
1095a3633fe7SShimoda, Yoshihiro 
10969e03d05eSJingoo Han 	ret = devm_spi_register_master(&pdev->dev, master);
10970b2182ddSShimoda, Yoshihiro 	if (ret < 0) {
10980b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "spi_register_master error.\n");
1099fcb4ed74SGeert Uytterhoeven 		goto error3;
11000b2182ddSShimoda, Yoshihiro 	}
11010b2182ddSShimoda, Yoshihiro 
11020b2182ddSShimoda, Yoshihiro 	dev_info(&pdev->dev, "probed\n");
11030b2182ddSShimoda, Yoshihiro 
11040b2182ddSShimoda, Yoshihiro 	return 0;
11050b2182ddSShimoda, Yoshihiro 
1106fcb4ed74SGeert Uytterhoeven error3:
11075d79e9acSLaurent Pinchart 	rspi_release_dma(rspi);
1108fcb4ed74SGeert Uytterhoeven error2:
1109fcb4ed74SGeert Uytterhoeven 	clk_disable(rspi->clk);
11100b2182ddSShimoda, Yoshihiro error1:
11110b2182ddSShimoda, Yoshihiro 	spi_master_put(master);
11120b2182ddSShimoda, Yoshihiro 
11130b2182ddSShimoda, Yoshihiro 	return ret;
11140b2182ddSShimoda, Yoshihiro }
11150b2182ddSShimoda, Yoshihiro 
11165ce0ba88SHiep Cao Minh static struct spi_ops rspi_ops = {
11175ce0ba88SHiep Cao Minh 	.set_config_register =		rspi_set_config_register,
1118eb557f75SGeert Uytterhoeven 	.transfer_one =			rspi_transfer_one,
11195ce0ba88SHiep Cao Minh };
11205ce0ba88SHiep Cao Minh 
1121862d357fSGeert Uytterhoeven static struct spi_ops rspi_rz_ops = {
1122862d357fSGeert Uytterhoeven 	.set_config_register =		rspi_rz_set_config_register,
1123862d357fSGeert Uytterhoeven 	.transfer_one =			rspi_rz_transfer_one,
1124862d357fSGeert Uytterhoeven };
1125862d357fSGeert Uytterhoeven 
11265ce0ba88SHiep Cao Minh static struct spi_ops qspi_ops = {
11275ce0ba88SHiep Cao Minh 	.set_config_register =		qspi_set_config_register,
1128eb557f75SGeert Uytterhoeven 	.transfer_one =			qspi_transfer_one,
11295ce0ba88SHiep Cao Minh };
11305ce0ba88SHiep Cao Minh 
11315ce0ba88SHiep Cao Minh static struct platform_device_id spi_driver_ids[] = {
11325ce0ba88SHiep Cao Minh 	{ "rspi",	(kernel_ulong_t)&rspi_ops },
1133862d357fSGeert Uytterhoeven 	{ "rspi-rz",	(kernel_ulong_t)&rspi_rz_ops },
11345ce0ba88SHiep Cao Minh 	{ "qspi",	(kernel_ulong_t)&qspi_ops },
11355ce0ba88SHiep Cao Minh 	{},
11365ce0ba88SHiep Cao Minh };
11375ce0ba88SHiep Cao Minh 
11385ce0ba88SHiep Cao Minh MODULE_DEVICE_TABLE(platform, spi_driver_ids);
11395ce0ba88SHiep Cao Minh 
11400b2182ddSShimoda, Yoshihiro static struct platform_driver rspi_driver = {
11410b2182ddSShimoda, Yoshihiro 	.probe =	rspi_probe,
1142fd4a319bSGrant Likely 	.remove =	rspi_remove,
11435ce0ba88SHiep Cao Minh 	.id_table =	spi_driver_ids,
11440b2182ddSShimoda, Yoshihiro 	.driver		= {
11455ce0ba88SHiep Cao Minh 		.name = "renesas_spi",
11460b2182ddSShimoda, Yoshihiro 		.owner	= THIS_MODULE,
11470b2182ddSShimoda, Yoshihiro 	},
11480b2182ddSShimoda, Yoshihiro };
11490b2182ddSShimoda, Yoshihiro module_platform_driver(rspi_driver);
11500b2182ddSShimoda, Yoshihiro 
11510b2182ddSShimoda, Yoshihiro MODULE_DESCRIPTION("Renesas RSPI bus driver");
11520b2182ddSShimoda, Yoshihiro MODULE_LICENSE("GPL v2");
11530b2182ddSShimoda, Yoshihiro MODULE_AUTHOR("Yoshihiro Shimoda");
11540b2182ddSShimoda, Yoshihiro MODULE_ALIAS("platform:rspi");
1155