xref: /openbmc/linux/drivers/spi/spi-rspi.c (revision a30b95a7)
10b2182ddSShimoda, Yoshihiro /*
20b2182ddSShimoda, Yoshihiro  * SH RSPI driver
30b2182ddSShimoda, Yoshihiro  *
493722206SGeert Uytterhoeven  * Copyright (C) 2012, 2013  Renesas Solutions Corp.
5880c6d11SGeert Uytterhoeven  * Copyright (C) 2014 Glider bvba
60b2182ddSShimoda, Yoshihiro  *
70b2182ddSShimoda, Yoshihiro  * Based on spi-sh.c:
80b2182ddSShimoda, Yoshihiro  * Copyright (C) 2011 Renesas Solutions Corp.
90b2182ddSShimoda, Yoshihiro  *
100b2182ddSShimoda, Yoshihiro  * This program is free software; you can redistribute it and/or modify
110b2182ddSShimoda, Yoshihiro  * it under the terms of the GNU General Public License as published by
120b2182ddSShimoda, Yoshihiro  * the Free Software Foundation; version 2 of the License.
130b2182ddSShimoda, Yoshihiro  *
140b2182ddSShimoda, Yoshihiro  * This program is distributed in the hope that it will be useful,
150b2182ddSShimoda, Yoshihiro  * but WITHOUT ANY WARRANTY; without even the implied warranty of
160b2182ddSShimoda, Yoshihiro  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
170b2182ddSShimoda, Yoshihiro  * GNU General Public License for more details.
180b2182ddSShimoda, Yoshihiro  *
190b2182ddSShimoda, Yoshihiro  * You should have received a copy of the GNU General Public License
200b2182ddSShimoda, Yoshihiro  * along with this program; if not, write to the Free Software
210b2182ddSShimoda, Yoshihiro  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
220b2182ddSShimoda, Yoshihiro  *
230b2182ddSShimoda, Yoshihiro  */
240b2182ddSShimoda, Yoshihiro 
250b2182ddSShimoda, Yoshihiro #include <linux/module.h>
260b2182ddSShimoda, Yoshihiro #include <linux/kernel.h>
270b2182ddSShimoda, Yoshihiro #include <linux/sched.h>
280b2182ddSShimoda, Yoshihiro #include <linux/errno.h>
290b2182ddSShimoda, Yoshihiro #include <linux/interrupt.h>
300b2182ddSShimoda, Yoshihiro #include <linux/platform_device.h>
310b2182ddSShimoda, Yoshihiro #include <linux/io.h>
320b2182ddSShimoda, Yoshihiro #include <linux/clk.h>
33a3633fe7SShimoda, Yoshihiro #include <linux/dmaengine.h>
34a3633fe7SShimoda, Yoshihiro #include <linux/dma-mapping.h>
35426ef76dSGeert Uytterhoeven #include <linux/of_device.h>
36490c9774SGeert Uytterhoeven #include <linux/pm_runtime.h>
37a3633fe7SShimoda, Yoshihiro #include <linux/sh_dma.h>
380b2182ddSShimoda, Yoshihiro #include <linux/spi/spi.h>
39a3633fe7SShimoda, Yoshihiro #include <linux/spi/rspi.h>
400b2182ddSShimoda, Yoshihiro 
416ab4865bSGeert Uytterhoeven #define RSPI_SPCR		0x00	/* Control Register */
426ab4865bSGeert Uytterhoeven #define RSPI_SSLP		0x01	/* Slave Select Polarity Register */
436ab4865bSGeert Uytterhoeven #define RSPI_SPPCR		0x02	/* Pin Control Register */
446ab4865bSGeert Uytterhoeven #define RSPI_SPSR		0x03	/* Status Register */
456ab4865bSGeert Uytterhoeven #define RSPI_SPDR		0x04	/* Data Register */
466ab4865bSGeert Uytterhoeven #define RSPI_SPSCR		0x08	/* Sequence Control Register */
476ab4865bSGeert Uytterhoeven #define RSPI_SPSSR		0x09	/* Sequence Status Register */
486ab4865bSGeert Uytterhoeven #define RSPI_SPBR		0x0a	/* Bit Rate Register */
496ab4865bSGeert Uytterhoeven #define RSPI_SPDCR		0x0b	/* Data Control Register */
506ab4865bSGeert Uytterhoeven #define RSPI_SPCKD		0x0c	/* Clock Delay Register */
516ab4865bSGeert Uytterhoeven #define RSPI_SSLND		0x0d	/* Slave Select Negation Delay Register */
526ab4865bSGeert Uytterhoeven #define RSPI_SPND		0x0e	/* Next-Access Delay Register */
53862d357fSGeert Uytterhoeven #define RSPI_SPCR2		0x0f	/* Control Register 2 (SH only) */
546ab4865bSGeert Uytterhoeven #define RSPI_SPCMD0		0x10	/* Command Register 0 */
556ab4865bSGeert Uytterhoeven #define RSPI_SPCMD1		0x12	/* Command Register 1 */
566ab4865bSGeert Uytterhoeven #define RSPI_SPCMD2		0x14	/* Command Register 2 */
576ab4865bSGeert Uytterhoeven #define RSPI_SPCMD3		0x16	/* Command Register 3 */
586ab4865bSGeert Uytterhoeven #define RSPI_SPCMD4		0x18	/* Command Register 4 */
596ab4865bSGeert Uytterhoeven #define RSPI_SPCMD5		0x1a	/* Command Register 5 */
606ab4865bSGeert Uytterhoeven #define RSPI_SPCMD6		0x1c	/* Command Register 6 */
616ab4865bSGeert Uytterhoeven #define RSPI_SPCMD7		0x1e	/* Command Register 7 */
62880c6d11SGeert Uytterhoeven #define RSPI_SPCMD(i)		(RSPI_SPCMD0 + (i) * 2)
63880c6d11SGeert Uytterhoeven #define RSPI_NUM_SPCMD		8
64880c6d11SGeert Uytterhoeven #define RSPI_RZ_NUM_SPCMD	4
65880c6d11SGeert Uytterhoeven #define QSPI_NUM_SPCMD		4
66862d357fSGeert Uytterhoeven 
67862d357fSGeert Uytterhoeven /* RSPI on RZ only */
686ab4865bSGeert Uytterhoeven #define RSPI_SPBFCR		0x20	/* Buffer Control Register */
696ab4865bSGeert Uytterhoeven #define RSPI_SPBFDR		0x22	/* Buffer Data Count Setting Register */
700b2182ddSShimoda, Yoshihiro 
71862d357fSGeert Uytterhoeven /* QSPI only */
72fbe5072bSGeert Uytterhoeven #define QSPI_SPBFCR		0x18	/* Buffer Control Register */
73fbe5072bSGeert Uytterhoeven #define QSPI_SPBDCR		0x1a	/* Buffer Data Count Register */
74fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL0		0x1c	/* Transfer Data Length Multiplier Setting Register 0 */
75fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL1		0x20	/* Transfer Data Length Multiplier Setting Register 1 */
76fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL2		0x24	/* Transfer Data Length Multiplier Setting Register 2 */
77fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL3		0x28	/* Transfer Data Length Multiplier Setting Register 3 */
78880c6d11SGeert Uytterhoeven #define QSPI_SPBMUL(i)		(QSPI_SPBMUL0 + (i) * 4)
795ce0ba88SHiep Cao Minh 
806ab4865bSGeert Uytterhoeven /* SPCR - Control Register */
816ab4865bSGeert Uytterhoeven #define SPCR_SPRIE		0x80	/* Receive Interrupt Enable */
826ab4865bSGeert Uytterhoeven #define SPCR_SPE		0x40	/* Function Enable */
836ab4865bSGeert Uytterhoeven #define SPCR_SPTIE		0x20	/* Transmit Interrupt Enable */
846ab4865bSGeert Uytterhoeven #define SPCR_SPEIE		0x10	/* Error Interrupt Enable */
856ab4865bSGeert Uytterhoeven #define SPCR_MSTR		0x08	/* Master/Slave Mode Select */
866ab4865bSGeert Uytterhoeven #define SPCR_MODFEN		0x04	/* Mode Fault Error Detection Enable */
876ab4865bSGeert Uytterhoeven /* RSPI on SH only */
886ab4865bSGeert Uytterhoeven #define SPCR_TXMD		0x02	/* TX Only Mode (vs. Full Duplex) */
896ab4865bSGeert Uytterhoeven #define SPCR_SPMS		0x01	/* 3-wire Mode (vs. 4-wire) */
90fbe5072bSGeert Uytterhoeven /* QSPI on R-Car M2 only */
91fbe5072bSGeert Uytterhoeven #define SPCR_WSWAP		0x02	/* Word Swap of read-data for DMAC */
92fbe5072bSGeert Uytterhoeven #define SPCR_BSWAP		0x01	/* Byte Swap of read-data for DMAC */
930b2182ddSShimoda, Yoshihiro 
946ab4865bSGeert Uytterhoeven /* SSLP - Slave Select Polarity Register */
956ab4865bSGeert Uytterhoeven #define SSLP_SSL1P		0x02	/* SSL1 Signal Polarity Setting */
966ab4865bSGeert Uytterhoeven #define SSLP_SSL0P		0x01	/* SSL0 Signal Polarity Setting */
970b2182ddSShimoda, Yoshihiro 
986ab4865bSGeert Uytterhoeven /* SPPCR - Pin Control Register */
996ab4865bSGeert Uytterhoeven #define SPPCR_MOIFE		0x20	/* MOSI Idle Value Fixing Enable */
1006ab4865bSGeert Uytterhoeven #define SPPCR_MOIFV		0x10	/* MOSI Idle Fixed Value */
1010b2182ddSShimoda, Yoshihiro #define SPPCR_SPOM		0x04
1026ab4865bSGeert Uytterhoeven #define SPPCR_SPLP2		0x02	/* Loopback Mode 2 (non-inverting) */
1036ab4865bSGeert Uytterhoeven #define SPPCR_SPLP		0x01	/* Loopback Mode (inverting) */
1040b2182ddSShimoda, Yoshihiro 
105fbe5072bSGeert Uytterhoeven #define SPPCR_IO3FV		0x04	/* Single-/Dual-SPI Mode IO3 Output Fixed Value */
106fbe5072bSGeert Uytterhoeven #define SPPCR_IO2FV		0x04	/* Single-/Dual-SPI Mode IO2 Output Fixed Value */
107fbe5072bSGeert Uytterhoeven 
1086ab4865bSGeert Uytterhoeven /* SPSR - Status Register */
1096ab4865bSGeert Uytterhoeven #define SPSR_SPRF		0x80	/* Receive Buffer Full Flag */
1106ab4865bSGeert Uytterhoeven #define SPSR_TEND		0x40	/* Transmit End */
1116ab4865bSGeert Uytterhoeven #define SPSR_SPTEF		0x20	/* Transmit Buffer Empty Flag */
1126ab4865bSGeert Uytterhoeven #define SPSR_PERF		0x08	/* Parity Error Flag */
1136ab4865bSGeert Uytterhoeven #define SPSR_MODF		0x04	/* Mode Fault Error Flag */
1146ab4865bSGeert Uytterhoeven #define SPSR_IDLNF		0x02	/* RSPI Idle Flag */
115862d357fSGeert Uytterhoeven #define SPSR_OVRF		0x01	/* Overrun Error Flag (RSPI only) */
1160b2182ddSShimoda, Yoshihiro 
1176ab4865bSGeert Uytterhoeven /* SPSCR - Sequence Control Register */
1186ab4865bSGeert Uytterhoeven #define SPSCR_SPSLN_MASK	0x07	/* Sequence Length Specification */
1190b2182ddSShimoda, Yoshihiro 
1206ab4865bSGeert Uytterhoeven /* SPSSR - Sequence Status Register */
1216ab4865bSGeert Uytterhoeven #define SPSSR_SPECM_MASK	0x70	/* Command Error Mask */
1226ab4865bSGeert Uytterhoeven #define SPSSR_SPCP_MASK		0x07	/* Command Pointer Mask */
1230b2182ddSShimoda, Yoshihiro 
1246ab4865bSGeert Uytterhoeven /* SPDCR - Data Control Register */
1256ab4865bSGeert Uytterhoeven #define SPDCR_TXDMY		0x80	/* Dummy Data Transmission Enable */
1266ab4865bSGeert Uytterhoeven #define SPDCR_SPLW1		0x40	/* Access Width Specification (RZ) */
1276ab4865bSGeert Uytterhoeven #define SPDCR_SPLW0		0x20	/* Access Width Specification (RZ) */
1286ab4865bSGeert Uytterhoeven #define SPDCR_SPLLWORD		(SPDCR_SPLW1 | SPDCR_SPLW0)
1296ab4865bSGeert Uytterhoeven #define SPDCR_SPLWORD		SPDCR_SPLW1
1306ab4865bSGeert Uytterhoeven #define SPDCR_SPLBYTE		SPDCR_SPLW0
1316ab4865bSGeert Uytterhoeven #define SPDCR_SPLW		0x20	/* Access Width Specification (SH) */
132862d357fSGeert Uytterhoeven #define SPDCR_SPRDTD		0x10	/* Receive Transmit Data Select (SH) */
1330b2182ddSShimoda, Yoshihiro #define SPDCR_SLSEL1		0x08
1340b2182ddSShimoda, Yoshihiro #define SPDCR_SLSEL0		0x04
135862d357fSGeert Uytterhoeven #define SPDCR_SLSEL_MASK	0x0c	/* SSL1 Output Select (SH) */
1360b2182ddSShimoda, Yoshihiro #define SPDCR_SPFC1		0x02
1370b2182ddSShimoda, Yoshihiro #define SPDCR_SPFC0		0x01
138862d357fSGeert Uytterhoeven #define SPDCR_SPFC_MASK		0x03	/* Frame Count Setting (1-4) (SH) */
1390b2182ddSShimoda, Yoshihiro 
1406ab4865bSGeert Uytterhoeven /* SPCKD - Clock Delay Register */
1416ab4865bSGeert Uytterhoeven #define SPCKD_SCKDL_MASK	0x07	/* Clock Delay Setting (1-8) */
1420b2182ddSShimoda, Yoshihiro 
1436ab4865bSGeert Uytterhoeven /* SSLND - Slave Select Negation Delay Register */
1446ab4865bSGeert Uytterhoeven #define SSLND_SLNDL_MASK	0x07	/* SSL Negation Delay Setting (1-8) */
1450b2182ddSShimoda, Yoshihiro 
1466ab4865bSGeert Uytterhoeven /* SPND - Next-Access Delay Register */
1476ab4865bSGeert Uytterhoeven #define SPND_SPNDL_MASK		0x07	/* Next-Access Delay Setting (1-8) */
1480b2182ddSShimoda, Yoshihiro 
1496ab4865bSGeert Uytterhoeven /* SPCR2 - Control Register 2 */
1506ab4865bSGeert Uytterhoeven #define SPCR2_PTE		0x08	/* Parity Self-Test Enable */
1516ab4865bSGeert Uytterhoeven #define SPCR2_SPIE		0x04	/* Idle Interrupt Enable */
1526ab4865bSGeert Uytterhoeven #define SPCR2_SPOE		0x02	/* Odd Parity Enable (vs. Even) */
1536ab4865bSGeert Uytterhoeven #define SPCR2_SPPE		0x01	/* Parity Enable */
1540b2182ddSShimoda, Yoshihiro 
1556ab4865bSGeert Uytterhoeven /* SPCMDn - Command Registers */
1566ab4865bSGeert Uytterhoeven #define SPCMD_SCKDEN		0x8000	/* Clock Delay Setting Enable */
1576ab4865bSGeert Uytterhoeven #define SPCMD_SLNDEN		0x4000	/* SSL Negation Delay Setting Enable */
1586ab4865bSGeert Uytterhoeven #define SPCMD_SPNDEN		0x2000	/* Next-Access Delay Enable */
1596ab4865bSGeert Uytterhoeven #define SPCMD_LSBF		0x1000	/* LSB First */
1606ab4865bSGeert Uytterhoeven #define SPCMD_SPB_MASK		0x0f00	/* Data Length Setting */
1610b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_8_TO_16(bit)	(((bit - 1) << 8) & SPCMD_SPB_MASK)
162880c6d11SGeert Uytterhoeven #define SPCMD_SPB_8BIT		0x0000	/* QSPI only */
1635ce0ba88SHiep Cao Minh #define SPCMD_SPB_16BIT		0x0100
1640b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_20BIT		0x0000
1650b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_24BIT		0x0100
1660b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_32BIT		0x0200
1676ab4865bSGeert Uytterhoeven #define SPCMD_SSLKP		0x0080	/* SSL Signal Level Keeping */
168fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_MASK	0x0060	/* SPI Operating Mode (QSPI only) */
169fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD1		0x0040
170fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD0		0x0020
171fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_SINGLE	0
172fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_DUAL	SPCMD_SPIMOD0
173fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_QUAD	SPCMD_SPIMOD1
174fbe5072bSGeert Uytterhoeven #define SPCMD_SPRW		0x0010	/* SPI Read/Write Access (Dual/Quad) */
1756ab4865bSGeert Uytterhoeven #define SPCMD_SSLA_MASK		0x0030	/* SSL Assert Signal Setting (RSPI) */
1766ab4865bSGeert Uytterhoeven #define SPCMD_BRDV_MASK		0x000c	/* Bit Rate Division Setting */
1776ab4865bSGeert Uytterhoeven #define SPCMD_CPOL		0x0002	/* Clock Polarity Setting */
1786ab4865bSGeert Uytterhoeven #define SPCMD_CPHA		0x0001	/* Clock Phase Setting */
1790b2182ddSShimoda, Yoshihiro 
1806ab4865bSGeert Uytterhoeven /* SPBFCR - Buffer Control Register */
181862d357fSGeert Uytterhoeven #define SPBFCR_TXRST		0x80	/* Transmit Buffer Data Reset */
182862d357fSGeert Uytterhoeven #define SPBFCR_RXRST		0x40	/* Receive Buffer Data Reset */
1836ab4865bSGeert Uytterhoeven #define SPBFCR_TXTRG_MASK	0x30	/* Transmit Buffer Data Triggering Number */
1846ab4865bSGeert Uytterhoeven #define SPBFCR_RXTRG_MASK	0x07	/* Receive Buffer Data Triggering Number */
1855ce0ba88SHiep Cao Minh 
1860b2182ddSShimoda, Yoshihiro struct rspi_data {
1870b2182ddSShimoda, Yoshihiro 	void __iomem *addr;
1880b2182ddSShimoda, Yoshihiro 	u32 max_speed_hz;
1890b2182ddSShimoda, Yoshihiro 	struct spi_master *master;
1900b2182ddSShimoda, Yoshihiro 	wait_queue_head_t wait;
1910b2182ddSShimoda, Yoshihiro 	struct clk *clk;
192348e5153SGeert Uytterhoeven 	u16 spcmd;
19306a7a3cfSGeert Uytterhoeven 	u8 spsr;
19406a7a3cfSGeert Uytterhoeven 	u8 sppcr;
19593722206SGeert Uytterhoeven 	int rx_irq, tx_irq;
1965ce0ba88SHiep Cao Minh 	const struct spi_ops *ops;
197a3633fe7SShimoda, Yoshihiro 
198a3633fe7SShimoda, Yoshihiro 	unsigned dma_callbacked:1;
19974da7686SGeert Uytterhoeven 	unsigned byte_access:1;
2000b2182ddSShimoda, Yoshihiro };
2010b2182ddSShimoda, Yoshihiro 
202baf588f4SGeert Uytterhoeven static void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset)
2030b2182ddSShimoda, Yoshihiro {
2040b2182ddSShimoda, Yoshihiro 	iowrite8(data, rspi->addr + offset);
2050b2182ddSShimoda, Yoshihiro }
2060b2182ddSShimoda, Yoshihiro 
207baf588f4SGeert Uytterhoeven static void rspi_write16(const struct rspi_data *rspi, u16 data, u16 offset)
2080b2182ddSShimoda, Yoshihiro {
2090b2182ddSShimoda, Yoshihiro 	iowrite16(data, rspi->addr + offset);
2100b2182ddSShimoda, Yoshihiro }
2110b2182ddSShimoda, Yoshihiro 
212baf588f4SGeert Uytterhoeven static void rspi_write32(const struct rspi_data *rspi, u32 data, u16 offset)
2135ce0ba88SHiep Cao Minh {
2145ce0ba88SHiep Cao Minh 	iowrite32(data, rspi->addr + offset);
2155ce0ba88SHiep Cao Minh }
2165ce0ba88SHiep Cao Minh 
217baf588f4SGeert Uytterhoeven static u8 rspi_read8(const struct rspi_data *rspi, u16 offset)
2180b2182ddSShimoda, Yoshihiro {
2190b2182ddSShimoda, Yoshihiro 	return ioread8(rspi->addr + offset);
2200b2182ddSShimoda, Yoshihiro }
2210b2182ddSShimoda, Yoshihiro 
222baf588f4SGeert Uytterhoeven static u16 rspi_read16(const struct rspi_data *rspi, u16 offset)
2230b2182ddSShimoda, Yoshihiro {
2240b2182ddSShimoda, Yoshihiro 	return ioread16(rspi->addr + offset);
2250b2182ddSShimoda, Yoshihiro }
2260b2182ddSShimoda, Yoshihiro 
22774da7686SGeert Uytterhoeven static void rspi_write_data(const struct rspi_data *rspi, u16 data)
22874da7686SGeert Uytterhoeven {
22974da7686SGeert Uytterhoeven 	if (rspi->byte_access)
23074da7686SGeert Uytterhoeven 		rspi_write8(rspi, data, RSPI_SPDR);
23174da7686SGeert Uytterhoeven 	else /* 16 bit */
23274da7686SGeert Uytterhoeven 		rspi_write16(rspi, data, RSPI_SPDR);
23374da7686SGeert Uytterhoeven }
23474da7686SGeert Uytterhoeven 
23574da7686SGeert Uytterhoeven static u16 rspi_read_data(const struct rspi_data *rspi)
23674da7686SGeert Uytterhoeven {
23774da7686SGeert Uytterhoeven 	if (rspi->byte_access)
23874da7686SGeert Uytterhoeven 		return rspi_read8(rspi, RSPI_SPDR);
23974da7686SGeert Uytterhoeven 	else /* 16 bit */
24074da7686SGeert Uytterhoeven 		return rspi_read16(rspi, RSPI_SPDR);
24174da7686SGeert Uytterhoeven }
24274da7686SGeert Uytterhoeven 
2435ce0ba88SHiep Cao Minh /* optional functions */
2445ce0ba88SHiep Cao Minh struct spi_ops {
24574da7686SGeert Uytterhoeven 	int (*set_config_register)(struct rspi_data *rspi, int access_size);
246eb557f75SGeert Uytterhoeven 	int (*transfer_one)(struct spi_master *master, struct spi_device *spi,
247eb557f75SGeert Uytterhoeven 			    struct spi_transfer *xfer);
248880c6d11SGeert Uytterhoeven 	u16 mode_bits;
249b42e0359SGeert Uytterhoeven 	u16 flags;
2502f777ec9SGeert Uytterhoeven 	u16 fifo_size;
2515ce0ba88SHiep Cao Minh };
2525ce0ba88SHiep Cao Minh 
2535ce0ba88SHiep Cao Minh /*
254862d357fSGeert Uytterhoeven  * functions for RSPI on legacy SH
2555ce0ba88SHiep Cao Minh  */
25674da7686SGeert Uytterhoeven static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
2570b2182ddSShimoda, Yoshihiro {
2585ce0ba88SHiep Cao Minh 	int spbr;
2590b2182ddSShimoda, Yoshihiro 
26006a7a3cfSGeert Uytterhoeven 	/* Sets output mode, MOSI signal, and (optionally) loopback */
26106a7a3cfSGeert Uytterhoeven 	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
2620b2182ddSShimoda, Yoshihiro 
2635ce0ba88SHiep Cao Minh 	/* Sets transfer bit rate */
2643beb61dbSGeert Uytterhoeven 	spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk),
2653beb61dbSGeert Uytterhoeven 			    2 * rspi->max_speed_hz) - 1;
2665ce0ba88SHiep Cao Minh 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
2675ce0ba88SHiep Cao Minh 
26874da7686SGeert Uytterhoeven 	/* Disable dummy transmission, set 16-bit word access, 1 frame */
26974da7686SGeert Uytterhoeven 	rspi_write8(rspi, 0, RSPI_SPDCR);
27074da7686SGeert Uytterhoeven 	rspi->byte_access = 0;
2715ce0ba88SHiep Cao Minh 
2725ce0ba88SHiep Cao Minh 	/* Sets RSPCK, SSL, next-access delay value */
2735ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
2745ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SSLND);
2755ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPND);
2765ce0ba88SHiep Cao Minh 
2775ce0ba88SHiep Cao Minh 	/* Sets parity, interrupt mask */
2785ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCR2);
2795ce0ba88SHiep Cao Minh 
2805ce0ba88SHiep Cao Minh 	/* Sets SPCMD */
281880c6d11SGeert Uytterhoeven 	rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size);
282880c6d11SGeert Uytterhoeven 	rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
2835ce0ba88SHiep Cao Minh 
2845ce0ba88SHiep Cao Minh 	/* Sets RSPI mode */
2855ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
2865ce0ba88SHiep Cao Minh 
2875ce0ba88SHiep Cao Minh 	return 0;
2880b2182ddSShimoda, Yoshihiro }
2890b2182ddSShimoda, Yoshihiro 
2905ce0ba88SHiep Cao Minh /*
291862d357fSGeert Uytterhoeven  * functions for RSPI on RZ
292862d357fSGeert Uytterhoeven  */
293862d357fSGeert Uytterhoeven static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size)
294862d357fSGeert Uytterhoeven {
295862d357fSGeert Uytterhoeven 	int spbr;
296862d357fSGeert Uytterhoeven 
29706a7a3cfSGeert Uytterhoeven 	/* Sets output mode, MOSI signal, and (optionally) loopback */
29806a7a3cfSGeert Uytterhoeven 	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
299862d357fSGeert Uytterhoeven 
300862d357fSGeert Uytterhoeven 	/* Sets transfer bit rate */
3013beb61dbSGeert Uytterhoeven 	spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk),
3023beb61dbSGeert Uytterhoeven 			    2 * rspi->max_speed_hz) - 1;
303862d357fSGeert Uytterhoeven 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
304862d357fSGeert Uytterhoeven 
305862d357fSGeert Uytterhoeven 	/* Disable dummy transmission, set byte access */
306862d357fSGeert Uytterhoeven 	rspi_write8(rspi, SPDCR_SPLBYTE, RSPI_SPDCR);
307862d357fSGeert Uytterhoeven 	rspi->byte_access = 1;
308862d357fSGeert Uytterhoeven 
309862d357fSGeert Uytterhoeven 	/* Sets RSPCK, SSL, next-access delay value */
310862d357fSGeert Uytterhoeven 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
311862d357fSGeert Uytterhoeven 	rspi_write8(rspi, 0x00, RSPI_SSLND);
312862d357fSGeert Uytterhoeven 	rspi_write8(rspi, 0x00, RSPI_SPND);
313862d357fSGeert Uytterhoeven 
314862d357fSGeert Uytterhoeven 	/* Sets SPCMD */
315862d357fSGeert Uytterhoeven 	rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size);
316862d357fSGeert Uytterhoeven 	rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
317862d357fSGeert Uytterhoeven 
318862d357fSGeert Uytterhoeven 	/* Sets RSPI mode */
319862d357fSGeert Uytterhoeven 	rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
320862d357fSGeert Uytterhoeven 
321862d357fSGeert Uytterhoeven 	return 0;
322862d357fSGeert Uytterhoeven }
323862d357fSGeert Uytterhoeven 
324862d357fSGeert Uytterhoeven /*
3255ce0ba88SHiep Cao Minh  * functions for QSPI
3265ce0ba88SHiep Cao Minh  */
32774da7686SGeert Uytterhoeven static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
3285ce0ba88SHiep Cao Minh {
3295ce0ba88SHiep Cao Minh 	int spbr;
3305ce0ba88SHiep Cao Minh 
33106a7a3cfSGeert Uytterhoeven 	/* Sets output mode, MOSI signal, and (optionally) loopback */
33206a7a3cfSGeert Uytterhoeven 	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
3335ce0ba88SHiep Cao Minh 
3345ce0ba88SHiep Cao Minh 	/* Sets transfer bit rate */
3353beb61dbSGeert Uytterhoeven 	spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 2 * rspi->max_speed_hz);
3365ce0ba88SHiep Cao Minh 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
3375ce0ba88SHiep Cao Minh 
33874da7686SGeert Uytterhoeven 	/* Disable dummy transmission, set byte access */
33974da7686SGeert Uytterhoeven 	rspi_write8(rspi, 0, RSPI_SPDCR);
34074da7686SGeert Uytterhoeven 	rspi->byte_access = 1;
3415ce0ba88SHiep Cao Minh 
3425ce0ba88SHiep Cao Minh 	/* Sets RSPCK, SSL, next-access delay value */
3435ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
3445ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SSLND);
3455ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPND);
3465ce0ba88SHiep Cao Minh 
3475ce0ba88SHiep Cao Minh 	/* Data Length Setting */
3485ce0ba88SHiep Cao Minh 	if (access_size == 8)
349880c6d11SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_SPB_8BIT;
3505ce0ba88SHiep Cao Minh 	else if (access_size == 16)
351880c6d11SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_SPB_16BIT;
3528e1c8096SLaurent Pinchart 	else
353880c6d11SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_SPB_32BIT;
3545ce0ba88SHiep Cao Minh 
355880c6d11SGeert Uytterhoeven 	rspi->spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SPNDEN;
3565ce0ba88SHiep Cao Minh 
3575ce0ba88SHiep Cao Minh 	/* Resets transfer data length */
3585ce0ba88SHiep Cao Minh 	rspi_write32(rspi, 0, QSPI_SPBMUL0);
3595ce0ba88SHiep Cao Minh 
3605ce0ba88SHiep Cao Minh 	/* Resets transmit and receive buffer */
3615ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
3625ce0ba88SHiep Cao Minh 	/* Sets buffer to allow normal operation */
3635ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
3645ce0ba88SHiep Cao Minh 
3655ce0ba88SHiep Cao Minh 	/* Sets SPCMD */
366880c6d11SGeert Uytterhoeven 	rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
3675ce0ba88SHiep Cao Minh 
368880c6d11SGeert Uytterhoeven 	/* Enables SPI function in master mode */
3695ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR);
3705ce0ba88SHiep Cao Minh 
3715ce0ba88SHiep Cao Minh 	return 0;
3725ce0ba88SHiep Cao Minh }
3735ce0ba88SHiep Cao Minh 
3745ce0ba88SHiep Cao Minh #define set_config_register(spi, n) spi->ops->set_config_register(spi, n)
3755ce0ba88SHiep Cao Minh 
376baf588f4SGeert Uytterhoeven static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable)
3770b2182ddSShimoda, Yoshihiro {
3780b2182ddSShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR);
3790b2182ddSShimoda, Yoshihiro }
3800b2182ddSShimoda, Yoshihiro 
381baf588f4SGeert Uytterhoeven static void rspi_disable_irq(const struct rspi_data *rspi, u8 disable)
3820b2182ddSShimoda, Yoshihiro {
3830b2182ddSShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~disable, RSPI_SPCR);
3840b2182ddSShimoda, Yoshihiro }
3850b2182ddSShimoda, Yoshihiro 
3860b2182ddSShimoda, Yoshihiro static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
3870b2182ddSShimoda, Yoshihiro 				   u8 enable_bit)
3880b2182ddSShimoda, Yoshihiro {
3890b2182ddSShimoda, Yoshihiro 	int ret;
3900b2182ddSShimoda, Yoshihiro 
3910b2182ddSShimoda, Yoshihiro 	rspi->spsr = rspi_read8(rspi, RSPI_SPSR);
3925dd1ad23SGeert Uytterhoeven 	if (rspi->spsr & wait_mask)
3935dd1ad23SGeert Uytterhoeven 		return 0;
3945dd1ad23SGeert Uytterhoeven 
3950b2182ddSShimoda, Yoshihiro 	rspi_enable_irq(rspi, enable_bit);
3960b2182ddSShimoda, Yoshihiro 	ret = wait_event_timeout(rspi->wait, rspi->spsr & wait_mask, HZ);
3970b2182ddSShimoda, Yoshihiro 	if (ret == 0 && !(rspi->spsr & wait_mask))
3980b2182ddSShimoda, Yoshihiro 		return -ETIMEDOUT;
3990b2182ddSShimoda, Yoshihiro 
4000b2182ddSShimoda, Yoshihiro 	return 0;
4010b2182ddSShimoda, Yoshihiro }
4020b2182ddSShimoda, Yoshihiro 
4035f684c34SGeert Uytterhoeven static inline int rspi_wait_for_tx_empty(struct rspi_data *rspi)
4045f684c34SGeert Uytterhoeven {
4055f684c34SGeert Uytterhoeven 	return rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
4065f684c34SGeert Uytterhoeven }
4075f684c34SGeert Uytterhoeven 
4085f684c34SGeert Uytterhoeven static inline int rspi_wait_for_rx_full(struct rspi_data *rspi)
4095f684c34SGeert Uytterhoeven {
4105f684c34SGeert Uytterhoeven 	return rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE);
4115f684c34SGeert Uytterhoeven }
4125f684c34SGeert Uytterhoeven 
41335301c99SGeert Uytterhoeven static int rspi_data_out(struct rspi_data *rspi, u8 data)
41435301c99SGeert Uytterhoeven {
4155f684c34SGeert Uytterhoeven 	int error = rspi_wait_for_tx_empty(rspi);
4165f684c34SGeert Uytterhoeven 	if (error < 0) {
41735301c99SGeert Uytterhoeven 		dev_err(&rspi->master->dev, "transmit timeout\n");
4185f684c34SGeert Uytterhoeven 		return error;
41935301c99SGeert Uytterhoeven 	}
42035301c99SGeert Uytterhoeven 	rspi_write_data(rspi, data);
42135301c99SGeert Uytterhoeven 	return 0;
42235301c99SGeert Uytterhoeven }
42335301c99SGeert Uytterhoeven 
42435301c99SGeert Uytterhoeven static int rspi_data_in(struct rspi_data *rspi)
42535301c99SGeert Uytterhoeven {
4265f684c34SGeert Uytterhoeven 	int error;
42735301c99SGeert Uytterhoeven 	u8 data;
42835301c99SGeert Uytterhoeven 
4295f684c34SGeert Uytterhoeven 	error = rspi_wait_for_rx_full(rspi);
4305f684c34SGeert Uytterhoeven 	if (error < 0) {
43135301c99SGeert Uytterhoeven 		dev_err(&rspi->master->dev, "receive timeout\n");
4325f684c34SGeert Uytterhoeven 		return error;
43335301c99SGeert Uytterhoeven 	}
43435301c99SGeert Uytterhoeven 	data = rspi_read_data(rspi);
43535301c99SGeert Uytterhoeven 	return data;
43635301c99SGeert Uytterhoeven }
43735301c99SGeert Uytterhoeven 
4386837b8e9SGeert Uytterhoeven static int rspi_pio_transfer(struct rspi_data *rspi, const u8 *tx, u8 *rx,
4396837b8e9SGeert Uytterhoeven 			     unsigned int n)
44035301c99SGeert Uytterhoeven {
4416837b8e9SGeert Uytterhoeven 	while (n-- > 0) {
4426837b8e9SGeert Uytterhoeven 		if (tx) {
4436837b8e9SGeert Uytterhoeven 			int ret = rspi_data_out(rspi, *tx++);
44435301c99SGeert Uytterhoeven 			if (ret < 0)
44535301c99SGeert Uytterhoeven 				return ret;
4466837b8e9SGeert Uytterhoeven 		}
4476837b8e9SGeert Uytterhoeven 		if (rx) {
4486837b8e9SGeert Uytterhoeven 			int ret = rspi_data_in(rspi);
4496837b8e9SGeert Uytterhoeven 			if (ret < 0)
4506837b8e9SGeert Uytterhoeven 				return ret;
4516837b8e9SGeert Uytterhoeven 			*rx++ = ret;
4526837b8e9SGeert Uytterhoeven 		}
4536837b8e9SGeert Uytterhoeven 	}
45435301c99SGeert Uytterhoeven 
4556837b8e9SGeert Uytterhoeven 	return 0;
45635301c99SGeert Uytterhoeven }
45735301c99SGeert Uytterhoeven 
458a3633fe7SShimoda, Yoshihiro static void rspi_dma_complete(void *arg)
4590b2182ddSShimoda, Yoshihiro {
460a3633fe7SShimoda, Yoshihiro 	struct rspi_data *rspi = arg;
461a3633fe7SShimoda, Yoshihiro 
462a3633fe7SShimoda, Yoshihiro 	rspi->dma_callbacked = 1;
463a3633fe7SShimoda, Yoshihiro 	wake_up_interruptible(&rspi->wait);
464a3633fe7SShimoda, Yoshihiro }
465a3633fe7SShimoda, Yoshihiro 
466c52fb6d6SGeert Uytterhoeven static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
467c52fb6d6SGeert Uytterhoeven 			     struct sg_table *rx)
468a3633fe7SShimoda, Yoshihiro {
469c52fb6d6SGeert Uytterhoeven 	struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
470c52fb6d6SGeert Uytterhoeven 	u8 irq_mask = 0;
471c52fb6d6SGeert Uytterhoeven 	unsigned int other_irq = 0;
472c52fb6d6SGeert Uytterhoeven 	dma_cookie_t cookie;
4732f777ec9SGeert Uytterhoeven 	int ret;
474a3633fe7SShimoda, Yoshihiro 
4753819bc87SGeert Uytterhoeven 	/* First prepare and submit the DMA request(s), as this may fail */
476c52fb6d6SGeert Uytterhoeven 	if (rx) {
477c52fb6d6SGeert Uytterhoeven 		desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx,
478c52fb6d6SGeert Uytterhoeven 					rx->sgl, rx->nents, DMA_FROM_DEVICE,
479c52fb6d6SGeert Uytterhoeven 					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
4803819bc87SGeert Uytterhoeven 		if (!desc_rx) {
4813819bc87SGeert Uytterhoeven 			ret = -EAGAIN;
4823819bc87SGeert Uytterhoeven 			goto no_dma_rx;
4833819bc87SGeert Uytterhoeven 		}
4843819bc87SGeert Uytterhoeven 
4853819bc87SGeert Uytterhoeven 		desc_rx->callback = rspi_dma_complete;
4863819bc87SGeert Uytterhoeven 		desc_rx->callback_param = rspi;
4873819bc87SGeert Uytterhoeven 		cookie = dmaengine_submit(desc_rx);
4883819bc87SGeert Uytterhoeven 		if (dma_submit_error(cookie)) {
4893819bc87SGeert Uytterhoeven 			ret = cookie;
4903819bc87SGeert Uytterhoeven 			goto no_dma_rx;
4913819bc87SGeert Uytterhoeven 		}
492c52fb6d6SGeert Uytterhoeven 
493c52fb6d6SGeert Uytterhoeven 		irq_mask |= SPCR_SPRIE;
494c52fb6d6SGeert Uytterhoeven 	}
495c52fb6d6SGeert Uytterhoeven 
4963819bc87SGeert Uytterhoeven 	if (tx) {
4973819bc87SGeert Uytterhoeven 		desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx,
4983819bc87SGeert Uytterhoeven 					tx->sgl, tx->nents, DMA_TO_DEVICE,
4993819bc87SGeert Uytterhoeven 					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
5003819bc87SGeert Uytterhoeven 		if (!desc_tx) {
5013819bc87SGeert Uytterhoeven 			ret = -EAGAIN;
5023819bc87SGeert Uytterhoeven 			goto no_dma_tx;
5033819bc87SGeert Uytterhoeven 		}
5043819bc87SGeert Uytterhoeven 
5053819bc87SGeert Uytterhoeven 		if (rx) {
5063819bc87SGeert Uytterhoeven 			/* No callback */
5073819bc87SGeert Uytterhoeven 			desc_tx->callback = NULL;
5083819bc87SGeert Uytterhoeven 		} else {
5093819bc87SGeert Uytterhoeven 			desc_tx->callback = rspi_dma_complete;
5103819bc87SGeert Uytterhoeven 			desc_tx->callback_param = rspi;
5113819bc87SGeert Uytterhoeven 		}
5123819bc87SGeert Uytterhoeven 		cookie = dmaengine_submit(desc_tx);
5133819bc87SGeert Uytterhoeven 		if (dma_submit_error(cookie)) {
5143819bc87SGeert Uytterhoeven 			ret = cookie;
5153819bc87SGeert Uytterhoeven 			goto no_dma_tx;
5163819bc87SGeert Uytterhoeven 		}
5173819bc87SGeert Uytterhoeven 
5183819bc87SGeert Uytterhoeven 		irq_mask |= SPCR_SPTIE;
5193819bc87SGeert Uytterhoeven 	}
5203819bc87SGeert Uytterhoeven 
521a3633fe7SShimoda, Yoshihiro 	/*
522c52fb6d6SGeert Uytterhoeven 	 * DMAC needs SPxIE, but if SPxIE is set, the IRQ routine will be
523a3633fe7SShimoda, Yoshihiro 	 * called. So, this driver disables the IRQ while DMA transfer.
524a3633fe7SShimoda, Yoshihiro 	 */
525c52fb6d6SGeert Uytterhoeven 	if (tx)
526c52fb6d6SGeert Uytterhoeven 		disable_irq(other_irq = rspi->tx_irq);
527c52fb6d6SGeert Uytterhoeven 	if (rx && rspi->rx_irq != other_irq)
528c52fb6d6SGeert Uytterhoeven 		disable_irq(rspi->rx_irq);
529a3633fe7SShimoda, Yoshihiro 
530c52fb6d6SGeert Uytterhoeven 	rspi_enable_irq(rspi, irq_mask);
531a3633fe7SShimoda, Yoshihiro 	rspi->dma_callbacked = 0;
532a3633fe7SShimoda, Yoshihiro 
5333819bc87SGeert Uytterhoeven 	/* Now start DMA */
5343819bc87SGeert Uytterhoeven 	if (rx)
535c52fb6d6SGeert Uytterhoeven 		dma_async_issue_pending(rspi->master->dma_rx);
5363819bc87SGeert Uytterhoeven 	if (tx)
5372f777ec9SGeert Uytterhoeven 		dma_async_issue_pending(rspi->master->dma_tx);
538a3633fe7SShimoda, Yoshihiro 
539a3633fe7SShimoda, Yoshihiro 	ret = wait_event_interruptible_timeout(rspi->wait,
540a3633fe7SShimoda, Yoshihiro 					       rspi->dma_callbacked, HZ);
541a3633fe7SShimoda, Yoshihiro 	if (ret > 0 && rspi->dma_callbacked)
542a3633fe7SShimoda, Yoshihiro 		ret = 0;
5433819bc87SGeert Uytterhoeven 	else if (!ret) {
5443819bc87SGeert Uytterhoeven 		dev_err(&rspi->master->dev, "DMA timeout\n");
545a3633fe7SShimoda, Yoshihiro 		ret = -ETIMEDOUT;
5463819bc87SGeert Uytterhoeven 		if (tx)
5473819bc87SGeert Uytterhoeven 			dmaengine_terminate_all(rspi->master->dma_tx);
5483819bc87SGeert Uytterhoeven 		if (rx)
5493819bc87SGeert Uytterhoeven 			dmaengine_terminate_all(rspi->master->dma_rx);
5503819bc87SGeert Uytterhoeven 	}
551a3633fe7SShimoda, Yoshihiro 
552c52fb6d6SGeert Uytterhoeven 	rspi_disable_irq(rspi, irq_mask);
553c52fb6d6SGeert Uytterhoeven 
554c52fb6d6SGeert Uytterhoeven 	if (tx)
55593722206SGeert Uytterhoeven 		enable_irq(rspi->tx_irq);
556c52fb6d6SGeert Uytterhoeven 	if (rx && rspi->rx_irq != other_irq)
557c52fb6d6SGeert Uytterhoeven 		enable_irq(rspi->rx_irq);
558c52fb6d6SGeert Uytterhoeven 
559a3633fe7SShimoda, Yoshihiro 	return ret;
56085912a88SGeert Uytterhoeven 
5613819bc87SGeert Uytterhoeven no_dma_tx:
5623819bc87SGeert Uytterhoeven 	if (rx)
5633819bc87SGeert Uytterhoeven 		dmaengine_terminate_all(rspi->master->dma_rx);
5643819bc87SGeert Uytterhoeven no_dma_rx:
5653819bc87SGeert Uytterhoeven 	if (ret == -EAGAIN) {
56685912a88SGeert Uytterhoeven 		pr_warn_once("%s %s: DMA not available, falling back to PIO\n",
56785912a88SGeert Uytterhoeven 			     dev_driver_string(&rspi->master->dev),
56885912a88SGeert Uytterhoeven 			     dev_name(&rspi->master->dev));
5693819bc87SGeert Uytterhoeven 	}
5703819bc87SGeert Uytterhoeven 	return ret;
571a3633fe7SShimoda, Yoshihiro }
572a3633fe7SShimoda, Yoshihiro 
573baf588f4SGeert Uytterhoeven static void rspi_receive_init(const struct rspi_data *rspi)
574a3633fe7SShimoda, Yoshihiro {
57597b95c11SGeert Uytterhoeven 	u8 spsr;
5760b2182ddSShimoda, Yoshihiro 
5770b2182ddSShimoda, Yoshihiro 	spsr = rspi_read8(rspi, RSPI_SPSR);
5780b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPRF)
57974da7686SGeert Uytterhoeven 		rspi_read_data(rspi);	/* dummy read */
5800b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_OVRF)
5810b2182ddSShimoda, Yoshihiro 		rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF,
582df900e67SGeert Uytterhoeven 			    RSPI_SPSR);
583a3633fe7SShimoda, Yoshihiro }
584a3633fe7SShimoda, Yoshihiro 
585862d357fSGeert Uytterhoeven static void rspi_rz_receive_init(const struct rspi_data *rspi)
586862d357fSGeert Uytterhoeven {
587862d357fSGeert Uytterhoeven 	rspi_receive_init(rspi);
588862d357fSGeert Uytterhoeven 	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, RSPI_SPBFCR);
589862d357fSGeert Uytterhoeven 	rspi_write8(rspi, 0, RSPI_SPBFCR);
590862d357fSGeert Uytterhoeven }
591862d357fSGeert Uytterhoeven 
592baf588f4SGeert Uytterhoeven static void qspi_receive_init(const struct rspi_data *rspi)
593cb52c673SHiep Cao Minh {
59497b95c11SGeert Uytterhoeven 	u8 spsr;
595cb52c673SHiep Cao Minh 
596cb52c673SHiep Cao Minh 	spsr = rspi_read8(rspi, RSPI_SPSR);
597cb52c673SHiep Cao Minh 	if (spsr & SPSR_SPRF)
59874da7686SGeert Uytterhoeven 		rspi_read_data(rspi);   /* dummy read */
599cb52c673SHiep Cao Minh 	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
600340a15e6SGeert Uytterhoeven 	rspi_write8(rspi, 0, QSPI_SPBFCR);
601cb52c673SHiep Cao Minh }
602cb52c673SHiep Cao Minh 
6032f777ec9SGeert Uytterhoeven static bool __rspi_can_dma(const struct rspi_data *rspi,
6042f777ec9SGeert Uytterhoeven 			   const struct spi_transfer *xfer)
605a3633fe7SShimoda, Yoshihiro {
6062f777ec9SGeert Uytterhoeven 	return xfer->len > rspi->ops->fifo_size;
6072f777ec9SGeert Uytterhoeven }
608a3633fe7SShimoda, Yoshihiro 
6092f777ec9SGeert Uytterhoeven static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi,
6102f777ec9SGeert Uytterhoeven 			 struct spi_transfer *xfer)
6112f777ec9SGeert Uytterhoeven {
6122f777ec9SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
6132f777ec9SGeert Uytterhoeven 
6142f777ec9SGeert Uytterhoeven 	return __rspi_can_dma(rspi, xfer);
615a3633fe7SShimoda, Yoshihiro }
616a3633fe7SShimoda, Yoshihiro 
6178b983e90SGeert Uytterhoeven static int rspi_common_transfer(struct rspi_data *rspi,
6188b983e90SGeert Uytterhoeven 				struct spi_transfer *xfer)
6198b983e90SGeert Uytterhoeven {
6208b983e90SGeert Uytterhoeven 	int ret;
6218b983e90SGeert Uytterhoeven 
6228b983e90SGeert Uytterhoeven 	if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
6238b983e90SGeert Uytterhoeven 		/* rx_buf can be NULL on RSPI on SH in TX-only Mode */
62485912a88SGeert Uytterhoeven 		ret = rspi_dma_transfer(rspi, &xfer->tx_sg,
6258b983e90SGeert Uytterhoeven 					xfer->rx_buf ? &xfer->rx_sg : NULL);
62685912a88SGeert Uytterhoeven 		if (ret != -EAGAIN)
62785912a88SGeert Uytterhoeven 			return ret;
6288b983e90SGeert Uytterhoeven 	}
6298b983e90SGeert Uytterhoeven 
6308b983e90SGeert Uytterhoeven 	ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
6318b983e90SGeert Uytterhoeven 	if (ret < 0)
6328b983e90SGeert Uytterhoeven 		return ret;
6338b983e90SGeert Uytterhoeven 
6348b983e90SGeert Uytterhoeven 	/* Wait for the last transmission */
6358b983e90SGeert Uytterhoeven 	rspi_wait_for_tx_empty(rspi);
6368b983e90SGeert Uytterhoeven 
6378b983e90SGeert Uytterhoeven 	return 0;
6388b983e90SGeert Uytterhoeven }
6398b983e90SGeert Uytterhoeven 
6408393fa78SGeert Uytterhoeven static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
6418449fd76SGeert Uytterhoeven 			     struct spi_transfer *xfer)
6428449fd76SGeert Uytterhoeven {
6438393fa78SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
644b42e0359SGeert Uytterhoeven 	u8 spcr;
6458449fd76SGeert Uytterhoeven 
6468449fd76SGeert Uytterhoeven 	spcr = rspi_read8(rspi, RSPI_SPCR);
6476837b8e9SGeert Uytterhoeven 	if (xfer->rx_buf) {
64832c64261SGeert Uytterhoeven 		rspi_receive_init(rspi);
6498449fd76SGeert Uytterhoeven 		spcr &= ~SPCR_TXMD;
65032c64261SGeert Uytterhoeven 	} else {
6518449fd76SGeert Uytterhoeven 		spcr |= SPCR_TXMD;
65232c64261SGeert Uytterhoeven 	}
6538449fd76SGeert Uytterhoeven 	rspi_write8(rspi, spcr, RSPI_SPCR);
6548449fd76SGeert Uytterhoeven 
6558b983e90SGeert Uytterhoeven 	return rspi_common_transfer(rspi, xfer);
6568449fd76SGeert Uytterhoeven }
6578449fd76SGeert Uytterhoeven 
65803e627c5SGeert Uytterhoeven static int rspi_rz_transfer_one(struct spi_master *master,
65903e627c5SGeert Uytterhoeven 				struct spi_device *spi,
660862d357fSGeert Uytterhoeven 				struct spi_transfer *xfer)
661862d357fSGeert Uytterhoeven {
66203e627c5SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
663862d357fSGeert Uytterhoeven 
664862d357fSGeert Uytterhoeven 	rspi_rz_receive_init(rspi);
665862d357fSGeert Uytterhoeven 
6668b983e90SGeert Uytterhoeven 	return rspi_common_transfer(rspi, xfer);
667862d357fSGeert Uytterhoeven }
668862d357fSGeert Uytterhoeven 
669340a15e6SGeert Uytterhoeven static int qspi_transfer_out_in(struct rspi_data *rspi,
670340a15e6SGeert Uytterhoeven 				struct spi_transfer *xfer)
671340a15e6SGeert Uytterhoeven {
672340a15e6SGeert Uytterhoeven 	qspi_receive_init(rspi);
673340a15e6SGeert Uytterhoeven 
6748b983e90SGeert Uytterhoeven 	return rspi_common_transfer(rspi, xfer);
675340a15e6SGeert Uytterhoeven }
676340a15e6SGeert Uytterhoeven 
677880c6d11SGeert Uytterhoeven static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
678880c6d11SGeert Uytterhoeven {
679880c6d11SGeert Uytterhoeven 	int ret;
680880c6d11SGeert Uytterhoeven 
68185912a88SGeert Uytterhoeven 	if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
68285912a88SGeert Uytterhoeven 		ret = rspi_dma_transfer(rspi, &xfer->tx_sg, NULL);
68385912a88SGeert Uytterhoeven 		if (ret != -EAGAIN)
68485912a88SGeert Uytterhoeven 			return ret;
68585912a88SGeert Uytterhoeven 	}
6864f12b5e5SGeert Uytterhoeven 
6876837b8e9SGeert Uytterhoeven 	ret = rspi_pio_transfer(rspi, xfer->tx_buf, NULL, xfer->len);
688880c6d11SGeert Uytterhoeven 	if (ret < 0)
689880c6d11SGeert Uytterhoeven 		return ret;
690880c6d11SGeert Uytterhoeven 
691880c6d11SGeert Uytterhoeven 	/* Wait for the last transmission */
6925f684c34SGeert Uytterhoeven 	rspi_wait_for_tx_empty(rspi);
693880c6d11SGeert Uytterhoeven 
694880c6d11SGeert Uytterhoeven 	return 0;
695880c6d11SGeert Uytterhoeven }
696880c6d11SGeert Uytterhoeven 
697880c6d11SGeert Uytterhoeven static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
698880c6d11SGeert Uytterhoeven {
69985912a88SGeert Uytterhoeven 	if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
70085912a88SGeert Uytterhoeven 		int ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg);
70185912a88SGeert Uytterhoeven 		if (ret != -EAGAIN)
70285912a88SGeert Uytterhoeven 			return ret;
70385912a88SGeert Uytterhoeven 	}
7044f12b5e5SGeert Uytterhoeven 
7056837b8e9SGeert Uytterhoeven 	return rspi_pio_transfer(rspi, NULL, xfer->rx_buf, xfer->len);
706880c6d11SGeert Uytterhoeven }
707880c6d11SGeert Uytterhoeven 
708eb557f75SGeert Uytterhoeven static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi,
709eb557f75SGeert Uytterhoeven 			     struct spi_transfer *xfer)
710eb557f75SGeert Uytterhoeven {
711eb557f75SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
712eb557f75SGeert Uytterhoeven 
713ba824d49SGeert Uytterhoeven 	if (spi->mode & SPI_LOOP) {
714ba824d49SGeert Uytterhoeven 		return qspi_transfer_out_in(rspi, xfer);
715b42e0359SGeert Uytterhoeven 	} else if (xfer->tx_nbits > SPI_NBITS_SINGLE) {
716880c6d11SGeert Uytterhoeven 		/* Quad or Dual SPI Write */
717880c6d11SGeert Uytterhoeven 		return qspi_transfer_out(rspi, xfer);
718b42e0359SGeert Uytterhoeven 	} else if (xfer->rx_nbits > SPI_NBITS_SINGLE) {
719880c6d11SGeert Uytterhoeven 		/* Quad or Dual SPI Read */
720880c6d11SGeert Uytterhoeven 		return qspi_transfer_in(rspi, xfer);
721880c6d11SGeert Uytterhoeven 	} else {
722880c6d11SGeert Uytterhoeven 		/* Single SPI Transfer */
723340a15e6SGeert Uytterhoeven 		return qspi_transfer_out_in(rspi, xfer);
724eb557f75SGeert Uytterhoeven 	}
725880c6d11SGeert Uytterhoeven }
726eb557f75SGeert Uytterhoeven 
7270b2182ddSShimoda, Yoshihiro static int rspi_setup(struct spi_device *spi)
7280b2182ddSShimoda, Yoshihiro {
7290b2182ddSShimoda, Yoshihiro 	struct rspi_data *rspi = spi_master_get_devdata(spi->master);
7300b2182ddSShimoda, Yoshihiro 
7310b2182ddSShimoda, Yoshihiro 	rspi->max_speed_hz = spi->max_speed_hz;
7320b2182ddSShimoda, Yoshihiro 
733348e5153SGeert Uytterhoeven 	rspi->spcmd = SPCMD_SSLKP;
734348e5153SGeert Uytterhoeven 	if (spi->mode & SPI_CPOL)
735348e5153SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_CPOL;
736348e5153SGeert Uytterhoeven 	if (spi->mode & SPI_CPHA)
737348e5153SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_CPHA;
738348e5153SGeert Uytterhoeven 
73906a7a3cfSGeert Uytterhoeven 	/* CMOS output mode and MOSI signal from previous transfer */
74006a7a3cfSGeert Uytterhoeven 	rspi->sppcr = 0;
74106a7a3cfSGeert Uytterhoeven 	if (spi->mode & SPI_LOOP)
74206a7a3cfSGeert Uytterhoeven 		rspi->sppcr |= SPPCR_SPLP;
74306a7a3cfSGeert Uytterhoeven 
7445ce0ba88SHiep Cao Minh 	set_config_register(rspi, 8);
7450b2182ddSShimoda, Yoshihiro 
7460b2182ddSShimoda, Yoshihiro 	return 0;
7470b2182ddSShimoda, Yoshihiro }
7480b2182ddSShimoda, Yoshihiro 
749880c6d11SGeert Uytterhoeven static u16 qspi_transfer_mode(const struct spi_transfer *xfer)
750880c6d11SGeert Uytterhoeven {
751880c6d11SGeert Uytterhoeven 	if (xfer->tx_buf)
752880c6d11SGeert Uytterhoeven 		switch (xfer->tx_nbits) {
753880c6d11SGeert Uytterhoeven 		case SPI_NBITS_QUAD:
754880c6d11SGeert Uytterhoeven 			return SPCMD_SPIMOD_QUAD;
755880c6d11SGeert Uytterhoeven 		case SPI_NBITS_DUAL:
756880c6d11SGeert Uytterhoeven 			return SPCMD_SPIMOD_DUAL;
757880c6d11SGeert Uytterhoeven 		default:
758880c6d11SGeert Uytterhoeven 			return 0;
759880c6d11SGeert Uytterhoeven 		}
760880c6d11SGeert Uytterhoeven 	if (xfer->rx_buf)
761880c6d11SGeert Uytterhoeven 		switch (xfer->rx_nbits) {
762880c6d11SGeert Uytterhoeven 		case SPI_NBITS_QUAD:
763880c6d11SGeert Uytterhoeven 			return SPCMD_SPIMOD_QUAD | SPCMD_SPRW;
764880c6d11SGeert Uytterhoeven 		case SPI_NBITS_DUAL:
765880c6d11SGeert Uytterhoeven 			return SPCMD_SPIMOD_DUAL | SPCMD_SPRW;
766880c6d11SGeert Uytterhoeven 		default:
767880c6d11SGeert Uytterhoeven 			return 0;
768880c6d11SGeert Uytterhoeven 		}
769880c6d11SGeert Uytterhoeven 
770880c6d11SGeert Uytterhoeven 	return 0;
771880c6d11SGeert Uytterhoeven }
772880c6d11SGeert Uytterhoeven 
773880c6d11SGeert Uytterhoeven static int qspi_setup_sequencer(struct rspi_data *rspi,
774880c6d11SGeert Uytterhoeven 				const struct spi_message *msg)
775880c6d11SGeert Uytterhoeven {
776880c6d11SGeert Uytterhoeven 	const struct spi_transfer *xfer;
777880c6d11SGeert Uytterhoeven 	unsigned int i = 0, len = 0;
778880c6d11SGeert Uytterhoeven 	u16 current_mode = 0xffff, mode;
779880c6d11SGeert Uytterhoeven 
780880c6d11SGeert Uytterhoeven 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
781880c6d11SGeert Uytterhoeven 		mode = qspi_transfer_mode(xfer);
782880c6d11SGeert Uytterhoeven 		if (mode == current_mode) {
783880c6d11SGeert Uytterhoeven 			len += xfer->len;
784880c6d11SGeert Uytterhoeven 			continue;
785880c6d11SGeert Uytterhoeven 		}
786880c6d11SGeert Uytterhoeven 
787880c6d11SGeert Uytterhoeven 		/* Transfer mode change */
788880c6d11SGeert Uytterhoeven 		if (i) {
789880c6d11SGeert Uytterhoeven 			/* Set transfer data length of previous transfer */
790880c6d11SGeert Uytterhoeven 			rspi_write32(rspi, len, QSPI_SPBMUL(i - 1));
791880c6d11SGeert Uytterhoeven 		}
792880c6d11SGeert Uytterhoeven 
793880c6d11SGeert Uytterhoeven 		if (i >= QSPI_NUM_SPCMD) {
794880c6d11SGeert Uytterhoeven 			dev_err(&msg->spi->dev,
795880c6d11SGeert Uytterhoeven 				"Too many different transfer modes");
796880c6d11SGeert Uytterhoeven 			return -EINVAL;
797880c6d11SGeert Uytterhoeven 		}
798880c6d11SGeert Uytterhoeven 
799880c6d11SGeert Uytterhoeven 		/* Program transfer mode for this transfer */
800880c6d11SGeert Uytterhoeven 		rspi_write16(rspi, rspi->spcmd | mode, RSPI_SPCMD(i));
801880c6d11SGeert Uytterhoeven 		current_mode = mode;
802880c6d11SGeert Uytterhoeven 		len = xfer->len;
803880c6d11SGeert Uytterhoeven 		i++;
804880c6d11SGeert Uytterhoeven 	}
805880c6d11SGeert Uytterhoeven 	if (i) {
806880c6d11SGeert Uytterhoeven 		/* Set final transfer data length and sequence length */
807880c6d11SGeert Uytterhoeven 		rspi_write32(rspi, len, QSPI_SPBMUL(i - 1));
808880c6d11SGeert Uytterhoeven 		rspi_write8(rspi, i - 1, RSPI_SPSCR);
809880c6d11SGeert Uytterhoeven 	}
810880c6d11SGeert Uytterhoeven 
811880c6d11SGeert Uytterhoeven 	return 0;
812880c6d11SGeert Uytterhoeven }
813880c6d11SGeert Uytterhoeven 
81479d23495SGeert Uytterhoeven static int rspi_prepare_message(struct spi_master *master,
815880c6d11SGeert Uytterhoeven 				struct spi_message *msg)
81679d23495SGeert Uytterhoeven {
81779d23495SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
818880c6d11SGeert Uytterhoeven 	int ret;
8190b2182ddSShimoda, Yoshihiro 
820880c6d11SGeert Uytterhoeven 	if (msg->spi->mode &
821880c6d11SGeert Uytterhoeven 	    (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)) {
822880c6d11SGeert Uytterhoeven 		/* Setup sequencer for messages with multiple transfer modes */
823880c6d11SGeert Uytterhoeven 		ret = qspi_setup_sequencer(rspi, msg);
824880c6d11SGeert Uytterhoeven 		if (ret < 0)
825880c6d11SGeert Uytterhoeven 			return ret;
826880c6d11SGeert Uytterhoeven 	}
827880c6d11SGeert Uytterhoeven 
828880c6d11SGeert Uytterhoeven 	/* Enable SPI function in master mode */
82979d23495SGeert Uytterhoeven 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
8300b2182ddSShimoda, Yoshihiro 	return 0;
8310b2182ddSShimoda, Yoshihiro }
8320b2182ddSShimoda, Yoshihiro 
83379d23495SGeert Uytterhoeven static int rspi_unprepare_message(struct spi_master *master,
834880c6d11SGeert Uytterhoeven 				  struct spi_message *msg)
8350b2182ddSShimoda, Yoshihiro {
83679d23495SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
83779d23495SGeert Uytterhoeven 
838880c6d11SGeert Uytterhoeven 	/* Disable SPI function */
83979d23495SGeert Uytterhoeven 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
840880c6d11SGeert Uytterhoeven 
841880c6d11SGeert Uytterhoeven 	/* Reset sequencer for Single SPI Transfers */
842880c6d11SGeert Uytterhoeven 	rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
843880c6d11SGeert Uytterhoeven 	rspi_write8(rspi, 0, RSPI_SPSCR);
84479d23495SGeert Uytterhoeven 	return 0;
8450b2182ddSShimoda, Yoshihiro }
8460b2182ddSShimoda, Yoshihiro 
84793722206SGeert Uytterhoeven static irqreturn_t rspi_irq_mux(int irq, void *_sr)
8480b2182ddSShimoda, Yoshihiro {
849c132f094SGeert Uytterhoeven 	struct rspi_data *rspi = _sr;
85097b95c11SGeert Uytterhoeven 	u8 spsr;
8510b2182ddSShimoda, Yoshihiro 	irqreturn_t ret = IRQ_NONE;
85297b95c11SGeert Uytterhoeven 	u8 disable_irq = 0;
8530b2182ddSShimoda, Yoshihiro 
8540b2182ddSShimoda, Yoshihiro 	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
8550b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPRF)
8560b2182ddSShimoda, Yoshihiro 		disable_irq |= SPCR_SPRIE;
8570b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPTEF)
8580b2182ddSShimoda, Yoshihiro 		disable_irq |= SPCR_SPTIE;
8590b2182ddSShimoda, Yoshihiro 
8600b2182ddSShimoda, Yoshihiro 	if (disable_irq) {
8610b2182ddSShimoda, Yoshihiro 		ret = IRQ_HANDLED;
8620b2182ddSShimoda, Yoshihiro 		rspi_disable_irq(rspi, disable_irq);
8630b2182ddSShimoda, Yoshihiro 		wake_up(&rspi->wait);
8640b2182ddSShimoda, Yoshihiro 	}
8650b2182ddSShimoda, Yoshihiro 
8660b2182ddSShimoda, Yoshihiro 	return ret;
8670b2182ddSShimoda, Yoshihiro }
8680b2182ddSShimoda, Yoshihiro 
86993722206SGeert Uytterhoeven static irqreturn_t rspi_irq_rx(int irq, void *_sr)
87093722206SGeert Uytterhoeven {
87193722206SGeert Uytterhoeven 	struct rspi_data *rspi = _sr;
87293722206SGeert Uytterhoeven 	u8 spsr;
87393722206SGeert Uytterhoeven 
87493722206SGeert Uytterhoeven 	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
87593722206SGeert Uytterhoeven 	if (spsr & SPSR_SPRF) {
87693722206SGeert Uytterhoeven 		rspi_disable_irq(rspi, SPCR_SPRIE);
87793722206SGeert Uytterhoeven 		wake_up(&rspi->wait);
87893722206SGeert Uytterhoeven 		return IRQ_HANDLED;
87993722206SGeert Uytterhoeven 	}
88093722206SGeert Uytterhoeven 
88193722206SGeert Uytterhoeven 	return 0;
88293722206SGeert Uytterhoeven }
88393722206SGeert Uytterhoeven 
88493722206SGeert Uytterhoeven static irqreturn_t rspi_irq_tx(int irq, void *_sr)
88593722206SGeert Uytterhoeven {
88693722206SGeert Uytterhoeven 	struct rspi_data *rspi = _sr;
88793722206SGeert Uytterhoeven 	u8 spsr;
88893722206SGeert Uytterhoeven 
88993722206SGeert Uytterhoeven 	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
89093722206SGeert Uytterhoeven 	if (spsr & SPSR_SPTEF) {
89193722206SGeert Uytterhoeven 		rspi_disable_irq(rspi, SPCR_SPTIE);
89293722206SGeert Uytterhoeven 		wake_up(&rspi->wait);
89393722206SGeert Uytterhoeven 		return IRQ_HANDLED;
89493722206SGeert Uytterhoeven 	}
89593722206SGeert Uytterhoeven 
89693722206SGeert Uytterhoeven 	return 0;
89793722206SGeert Uytterhoeven }
89893722206SGeert Uytterhoeven 
89965bf2205SGeert Uytterhoeven static struct dma_chan *rspi_request_dma_chan(struct device *dev,
90065bf2205SGeert Uytterhoeven 					      enum dma_transfer_direction dir,
90165bf2205SGeert Uytterhoeven 					      unsigned int id,
90265bf2205SGeert Uytterhoeven 					      dma_addr_t port_addr)
90365bf2205SGeert Uytterhoeven {
90465bf2205SGeert Uytterhoeven 	dma_cap_mask_t mask;
90565bf2205SGeert Uytterhoeven 	struct dma_chan *chan;
90665bf2205SGeert Uytterhoeven 	struct dma_slave_config cfg;
90765bf2205SGeert Uytterhoeven 	int ret;
90865bf2205SGeert Uytterhoeven 
90965bf2205SGeert Uytterhoeven 	dma_cap_zero(mask);
91065bf2205SGeert Uytterhoeven 	dma_cap_set(DMA_SLAVE, mask);
91165bf2205SGeert Uytterhoeven 
91265bf2205SGeert Uytterhoeven 	chan = dma_request_channel(mask, shdma_chan_filter,
91365bf2205SGeert Uytterhoeven 				   (void *)(unsigned long)id);
91465bf2205SGeert Uytterhoeven 	if (!chan) {
91565bf2205SGeert Uytterhoeven 		dev_warn(dev, "dma_request_channel failed\n");
91665bf2205SGeert Uytterhoeven 		return NULL;
91765bf2205SGeert Uytterhoeven 	}
91865bf2205SGeert Uytterhoeven 
91965bf2205SGeert Uytterhoeven 	memset(&cfg, 0, sizeof(cfg));
92065bf2205SGeert Uytterhoeven 	cfg.slave_id = id;
92165bf2205SGeert Uytterhoeven 	cfg.direction = dir;
922a30b95a7SGeert Uytterhoeven 	if (dir == DMA_MEM_TO_DEV) {
92365bf2205SGeert Uytterhoeven 		cfg.dst_addr = port_addr;
924a30b95a7SGeert Uytterhoeven 		cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
925a30b95a7SGeert Uytterhoeven 	} else {
92665bf2205SGeert Uytterhoeven 		cfg.src_addr = port_addr;
927a30b95a7SGeert Uytterhoeven 		cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
928a30b95a7SGeert Uytterhoeven 	}
92965bf2205SGeert Uytterhoeven 
93065bf2205SGeert Uytterhoeven 	ret = dmaengine_slave_config(chan, &cfg);
93165bf2205SGeert Uytterhoeven 	if (ret) {
93265bf2205SGeert Uytterhoeven 		dev_warn(dev, "dmaengine_slave_config failed %d\n", ret);
93365bf2205SGeert Uytterhoeven 		dma_release_channel(chan);
93465bf2205SGeert Uytterhoeven 		return NULL;
93565bf2205SGeert Uytterhoeven 	}
93665bf2205SGeert Uytterhoeven 
93765bf2205SGeert Uytterhoeven 	return chan;
93865bf2205SGeert Uytterhoeven }
93965bf2205SGeert Uytterhoeven 
9402f777ec9SGeert Uytterhoeven static int rspi_request_dma(struct device *dev, struct spi_master *master,
941fcdc49aeSGeert Uytterhoeven 			    const struct resource *res)
942a3633fe7SShimoda, Yoshihiro {
943fcdc49aeSGeert Uytterhoeven 	const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev);
944a3633fe7SShimoda, Yoshihiro 
9455f338d0cSGeert Uytterhoeven 	if (!rspi_pd || !rspi_pd->dma_rx_id || !rspi_pd->dma_tx_id)
9460243c536SShimoda, Yoshihiro 		return 0;	/* The driver assumes no error. */
947a3633fe7SShimoda, Yoshihiro 
9482f777ec9SGeert Uytterhoeven 	master->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM,
94965bf2205SGeert Uytterhoeven 					       rspi_pd->dma_rx_id,
95065bf2205SGeert Uytterhoeven 					       res->start + RSPI_SPDR);
9512f777ec9SGeert Uytterhoeven 	if (!master->dma_rx)
95265bf2205SGeert Uytterhoeven 		return -ENODEV;
95365bf2205SGeert Uytterhoeven 
9542f777ec9SGeert Uytterhoeven 	master->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV,
95565bf2205SGeert Uytterhoeven 					       rspi_pd->dma_tx_id,
95665bf2205SGeert Uytterhoeven 					       res->start + RSPI_SPDR);
9572f777ec9SGeert Uytterhoeven 	if (!master->dma_tx) {
9582f777ec9SGeert Uytterhoeven 		dma_release_channel(master->dma_rx);
9592f777ec9SGeert Uytterhoeven 		master->dma_rx = NULL;
96065bf2205SGeert Uytterhoeven 		return -ENODEV;
961a3633fe7SShimoda, Yoshihiro 	}
962a3633fe7SShimoda, Yoshihiro 
9632f777ec9SGeert Uytterhoeven 	master->can_dma = rspi_can_dma;
9645f338d0cSGeert Uytterhoeven 	dev_info(dev, "DMA available");
9650243c536SShimoda, Yoshihiro 	return 0;
9660243c536SShimoda, Yoshihiro }
9670243c536SShimoda, Yoshihiro 
968afcc98deSGeert Uytterhoeven static void rspi_release_dma(struct spi_master *master)
969a3633fe7SShimoda, Yoshihiro {
970afcc98deSGeert Uytterhoeven 	if (master->dma_tx)
971afcc98deSGeert Uytterhoeven 		dma_release_channel(master->dma_tx);
972afcc98deSGeert Uytterhoeven 	if (master->dma_rx)
973afcc98deSGeert Uytterhoeven 		dma_release_channel(master->dma_rx);
974a3633fe7SShimoda, Yoshihiro }
975a3633fe7SShimoda, Yoshihiro 
976fd4a319bSGrant Likely static int rspi_remove(struct platform_device *pdev)
9770b2182ddSShimoda, Yoshihiro {
9785ffbe2d9SLaurent Pinchart 	struct rspi_data *rspi = platform_get_drvdata(pdev);
9790b2182ddSShimoda, Yoshihiro 
980afcc98deSGeert Uytterhoeven 	rspi_release_dma(rspi->master);
981490c9774SGeert Uytterhoeven 	pm_runtime_disable(&pdev->dev);
9820b2182ddSShimoda, Yoshihiro 
9830b2182ddSShimoda, Yoshihiro 	return 0;
9840b2182ddSShimoda, Yoshihiro }
9850b2182ddSShimoda, Yoshihiro 
986426ef76dSGeert Uytterhoeven static const struct spi_ops rspi_ops = {
987426ef76dSGeert Uytterhoeven 	.set_config_register =	rspi_set_config_register,
988426ef76dSGeert Uytterhoeven 	.transfer_one =		rspi_transfer_one,
989880c6d11SGeert Uytterhoeven 	.mode_bits =		SPI_CPHA | SPI_CPOL | SPI_LOOP,
990b42e0359SGeert Uytterhoeven 	.flags =		SPI_MASTER_MUST_TX,
9912f777ec9SGeert Uytterhoeven 	.fifo_size =		8,
992426ef76dSGeert Uytterhoeven };
993426ef76dSGeert Uytterhoeven 
994426ef76dSGeert Uytterhoeven static const struct spi_ops rspi_rz_ops = {
995426ef76dSGeert Uytterhoeven 	.set_config_register =	rspi_rz_set_config_register,
996426ef76dSGeert Uytterhoeven 	.transfer_one =		rspi_rz_transfer_one,
997880c6d11SGeert Uytterhoeven 	.mode_bits =		SPI_CPHA | SPI_CPOL | SPI_LOOP,
998b42e0359SGeert Uytterhoeven 	.flags =		SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX,
9992f777ec9SGeert Uytterhoeven 	.fifo_size =		8,	/* 8 for TX, 32 for RX */
1000426ef76dSGeert Uytterhoeven };
1001426ef76dSGeert Uytterhoeven 
1002426ef76dSGeert Uytterhoeven static const struct spi_ops qspi_ops = {
1003426ef76dSGeert Uytterhoeven 	.set_config_register =	qspi_set_config_register,
1004426ef76dSGeert Uytterhoeven 	.transfer_one =		qspi_transfer_one,
1005880c6d11SGeert Uytterhoeven 	.mode_bits =		SPI_CPHA | SPI_CPOL | SPI_LOOP |
1006880c6d11SGeert Uytterhoeven 				SPI_TX_DUAL | SPI_TX_QUAD |
1007880c6d11SGeert Uytterhoeven 				SPI_RX_DUAL | SPI_RX_QUAD,
1008b42e0359SGeert Uytterhoeven 	.flags =		SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX,
10092f777ec9SGeert Uytterhoeven 	.fifo_size =		32,
1010426ef76dSGeert Uytterhoeven };
1011426ef76dSGeert Uytterhoeven 
1012426ef76dSGeert Uytterhoeven #ifdef CONFIG_OF
1013426ef76dSGeert Uytterhoeven static const struct of_device_id rspi_of_match[] = {
1014426ef76dSGeert Uytterhoeven 	/* RSPI on legacy SH */
1015426ef76dSGeert Uytterhoeven 	{ .compatible = "renesas,rspi", .data = &rspi_ops },
1016426ef76dSGeert Uytterhoeven 	/* RSPI on RZ/A1H */
1017426ef76dSGeert Uytterhoeven 	{ .compatible = "renesas,rspi-rz", .data = &rspi_rz_ops },
1018426ef76dSGeert Uytterhoeven 	/* QSPI on R-Car Gen2 */
1019426ef76dSGeert Uytterhoeven 	{ .compatible = "renesas,qspi", .data = &qspi_ops },
1020426ef76dSGeert Uytterhoeven 	{ /* sentinel */ }
1021426ef76dSGeert Uytterhoeven };
1022426ef76dSGeert Uytterhoeven 
1023426ef76dSGeert Uytterhoeven MODULE_DEVICE_TABLE(of, rspi_of_match);
1024426ef76dSGeert Uytterhoeven 
1025426ef76dSGeert Uytterhoeven static int rspi_parse_dt(struct device *dev, struct spi_master *master)
1026426ef76dSGeert Uytterhoeven {
1027426ef76dSGeert Uytterhoeven 	u32 num_cs;
1028426ef76dSGeert Uytterhoeven 	int error;
1029426ef76dSGeert Uytterhoeven 
1030426ef76dSGeert Uytterhoeven 	/* Parse DT properties */
1031426ef76dSGeert Uytterhoeven 	error = of_property_read_u32(dev->of_node, "num-cs", &num_cs);
1032426ef76dSGeert Uytterhoeven 	if (error) {
1033426ef76dSGeert Uytterhoeven 		dev_err(dev, "of_property_read_u32 num-cs failed %d\n", error);
1034426ef76dSGeert Uytterhoeven 		return error;
1035426ef76dSGeert Uytterhoeven 	}
1036426ef76dSGeert Uytterhoeven 
1037426ef76dSGeert Uytterhoeven 	master->num_chipselect = num_cs;
1038426ef76dSGeert Uytterhoeven 	return 0;
1039426ef76dSGeert Uytterhoeven }
1040426ef76dSGeert Uytterhoeven #else
104164b67defSShimoda, Yoshihiro #define rspi_of_match	NULL
1042426ef76dSGeert Uytterhoeven static inline int rspi_parse_dt(struct device *dev, struct spi_master *master)
1043426ef76dSGeert Uytterhoeven {
1044426ef76dSGeert Uytterhoeven 	return -EINVAL;
1045426ef76dSGeert Uytterhoeven }
1046426ef76dSGeert Uytterhoeven #endif /* CONFIG_OF */
1047426ef76dSGeert Uytterhoeven 
104893722206SGeert Uytterhoeven static int rspi_request_irq(struct device *dev, unsigned int irq,
104993722206SGeert Uytterhoeven 			    irq_handler_t handler, const char *suffix,
105093722206SGeert Uytterhoeven 			    void *dev_id)
105193722206SGeert Uytterhoeven {
105243937455SGeert Uytterhoeven 	const char *name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s",
105343937455SGeert Uytterhoeven 					  dev_name(dev), suffix);
105493722206SGeert Uytterhoeven 	if (!name)
105593722206SGeert Uytterhoeven 		return -ENOMEM;
105643937455SGeert Uytterhoeven 
105793722206SGeert Uytterhoeven 	return devm_request_irq(dev, irq, handler, 0, name, dev_id);
105893722206SGeert Uytterhoeven }
105993722206SGeert Uytterhoeven 
1060fd4a319bSGrant Likely static int rspi_probe(struct platform_device *pdev)
10610b2182ddSShimoda, Yoshihiro {
10620b2182ddSShimoda, Yoshihiro 	struct resource *res;
10630b2182ddSShimoda, Yoshihiro 	struct spi_master *master;
10640b2182ddSShimoda, Yoshihiro 	struct rspi_data *rspi;
106593722206SGeert Uytterhoeven 	int ret;
1066426ef76dSGeert Uytterhoeven 	const struct of_device_id *of_id;
1067426ef76dSGeert Uytterhoeven 	const struct rspi_plat_data *rspi_pd;
10685ce0ba88SHiep Cao Minh 	const struct spi_ops *ops;
10690b2182ddSShimoda, Yoshihiro 
10700b2182ddSShimoda, Yoshihiro 	master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data));
10710b2182ddSShimoda, Yoshihiro 	if (master == NULL) {
10720b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "spi_alloc_master error.\n");
10730b2182ddSShimoda, Yoshihiro 		return -ENOMEM;
10740b2182ddSShimoda, Yoshihiro 	}
10750b2182ddSShimoda, Yoshihiro 
1076426ef76dSGeert Uytterhoeven 	of_id = of_match_device(rspi_of_match, &pdev->dev);
1077426ef76dSGeert Uytterhoeven 	if (of_id) {
1078426ef76dSGeert Uytterhoeven 		ops = of_id->data;
1079426ef76dSGeert Uytterhoeven 		ret = rspi_parse_dt(&pdev->dev, master);
1080426ef76dSGeert Uytterhoeven 		if (ret)
1081426ef76dSGeert Uytterhoeven 			goto error1;
1082426ef76dSGeert Uytterhoeven 	} else {
1083426ef76dSGeert Uytterhoeven 		ops = (struct spi_ops *)pdev->id_entry->driver_data;
1084426ef76dSGeert Uytterhoeven 		rspi_pd = dev_get_platdata(&pdev->dev);
1085426ef76dSGeert Uytterhoeven 		if (rspi_pd && rspi_pd->num_chipselect)
1086426ef76dSGeert Uytterhoeven 			master->num_chipselect = rspi_pd->num_chipselect;
1087426ef76dSGeert Uytterhoeven 		else
1088426ef76dSGeert Uytterhoeven 			master->num_chipselect = 2; /* default */
1089d64b4726SGeert Uytterhoeven 	}
1090426ef76dSGeert Uytterhoeven 
1091426ef76dSGeert Uytterhoeven 	/* ops parameter check */
1092426ef76dSGeert Uytterhoeven 	if (!ops->set_config_register) {
1093426ef76dSGeert Uytterhoeven 		dev_err(&pdev->dev, "there is no set_config_register\n");
1094426ef76dSGeert Uytterhoeven 		ret = -ENODEV;
1095426ef76dSGeert Uytterhoeven 		goto error1;
1096426ef76dSGeert Uytterhoeven 	}
1097426ef76dSGeert Uytterhoeven 
10980b2182ddSShimoda, Yoshihiro 	rspi = spi_master_get_devdata(master);
109924b5a82cSJingoo Han 	platform_set_drvdata(pdev, rspi);
11005ce0ba88SHiep Cao Minh 	rspi->ops = ops;
11010b2182ddSShimoda, Yoshihiro 	rspi->master = master;
11025d79e9acSLaurent Pinchart 
11035d79e9acSLaurent Pinchart 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
11045d79e9acSLaurent Pinchart 	rspi->addr = devm_ioremap_resource(&pdev->dev, res);
11055d79e9acSLaurent Pinchart 	if (IS_ERR(rspi->addr)) {
11065d79e9acSLaurent Pinchart 		ret = PTR_ERR(rspi->addr);
11070b2182ddSShimoda, Yoshihiro 		goto error1;
11080b2182ddSShimoda, Yoshihiro 	}
11090b2182ddSShimoda, Yoshihiro 
111029f397b7SGeert Uytterhoeven 	rspi->clk = devm_clk_get(&pdev->dev, NULL);
11110b2182ddSShimoda, Yoshihiro 	if (IS_ERR(rspi->clk)) {
11120b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "cannot get clock\n");
11130b2182ddSShimoda, Yoshihiro 		ret = PTR_ERR(rspi->clk);
11145d79e9acSLaurent Pinchart 		goto error1;
11150b2182ddSShimoda, Yoshihiro 	}
111617fe0d9aSGeert Uytterhoeven 
1117490c9774SGeert Uytterhoeven 	pm_runtime_enable(&pdev->dev);
11180b2182ddSShimoda, Yoshihiro 
11190b2182ddSShimoda, Yoshihiro 	init_waitqueue_head(&rspi->wait);
11200b2182ddSShimoda, Yoshihiro 
11210b2182ddSShimoda, Yoshihiro 	master->bus_num = pdev->id;
11220b2182ddSShimoda, Yoshihiro 	master->setup = rspi_setup;
1123490c9774SGeert Uytterhoeven 	master->auto_runtime_pm = true;
1124eb557f75SGeert Uytterhoeven 	master->transfer_one = ops->transfer_one;
112579d23495SGeert Uytterhoeven 	master->prepare_message = rspi_prepare_message;
112679d23495SGeert Uytterhoeven 	master->unprepare_message = rspi_unprepare_message;
1127880c6d11SGeert Uytterhoeven 	master->mode_bits = ops->mode_bits;
1128b42e0359SGeert Uytterhoeven 	master->flags = ops->flags;
1129426ef76dSGeert Uytterhoeven 	master->dev.of_node = pdev->dev.of_node;
11300b2182ddSShimoda, Yoshihiro 
113193722206SGeert Uytterhoeven 	ret = platform_get_irq_byname(pdev, "rx");
113293722206SGeert Uytterhoeven 	if (ret < 0) {
113393722206SGeert Uytterhoeven 		ret = platform_get_irq_byname(pdev, "mux");
113493722206SGeert Uytterhoeven 		if (ret < 0)
113593722206SGeert Uytterhoeven 			ret = platform_get_irq(pdev, 0);
113693722206SGeert Uytterhoeven 		if (ret >= 0)
113793722206SGeert Uytterhoeven 			rspi->rx_irq = rspi->tx_irq = ret;
113893722206SGeert Uytterhoeven 	} else {
113993722206SGeert Uytterhoeven 		rspi->rx_irq = ret;
114093722206SGeert Uytterhoeven 		ret = platform_get_irq_byname(pdev, "tx");
114193722206SGeert Uytterhoeven 		if (ret >= 0)
114293722206SGeert Uytterhoeven 			rspi->tx_irq = ret;
114393722206SGeert Uytterhoeven 	}
114493722206SGeert Uytterhoeven 	if (ret < 0) {
114593722206SGeert Uytterhoeven 		dev_err(&pdev->dev, "platform_get_irq error\n");
114693722206SGeert Uytterhoeven 		goto error2;
114793722206SGeert Uytterhoeven 	}
114893722206SGeert Uytterhoeven 
114993722206SGeert Uytterhoeven 	if (rspi->rx_irq == rspi->tx_irq) {
115093722206SGeert Uytterhoeven 		/* Single multiplexed interrupt */
115193722206SGeert Uytterhoeven 		ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_mux,
115293722206SGeert Uytterhoeven 				       "mux", rspi);
115393722206SGeert Uytterhoeven 	} else {
115493722206SGeert Uytterhoeven 		/* Multi-interrupt mode, only SPRI and SPTI are used */
115593722206SGeert Uytterhoeven 		ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_rx,
115693722206SGeert Uytterhoeven 				       "rx", rspi);
115793722206SGeert Uytterhoeven 		if (!ret)
115893722206SGeert Uytterhoeven 			ret = rspi_request_irq(&pdev->dev, rspi->tx_irq,
115993722206SGeert Uytterhoeven 					       rspi_irq_tx, "tx", rspi);
116093722206SGeert Uytterhoeven 	}
11610b2182ddSShimoda, Yoshihiro 	if (ret < 0) {
11620b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "request_irq error\n");
1163fcb4ed74SGeert Uytterhoeven 		goto error2;
11640b2182ddSShimoda, Yoshihiro 	}
11650b2182ddSShimoda, Yoshihiro 
11662f777ec9SGeert Uytterhoeven 	ret = rspi_request_dma(&pdev->dev, master, res);
116727e105a6SGeert Uytterhoeven 	if (ret < 0)
116827e105a6SGeert Uytterhoeven 		dev_warn(&pdev->dev, "DMA not available, using PIO\n");
1169a3633fe7SShimoda, Yoshihiro 
11709e03d05eSJingoo Han 	ret = devm_spi_register_master(&pdev->dev, master);
11710b2182ddSShimoda, Yoshihiro 	if (ret < 0) {
11720b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "spi_register_master error.\n");
1173fcb4ed74SGeert Uytterhoeven 		goto error3;
11740b2182ddSShimoda, Yoshihiro 	}
11750b2182ddSShimoda, Yoshihiro 
11760b2182ddSShimoda, Yoshihiro 	dev_info(&pdev->dev, "probed\n");
11770b2182ddSShimoda, Yoshihiro 
11780b2182ddSShimoda, Yoshihiro 	return 0;
11790b2182ddSShimoda, Yoshihiro 
1180fcb4ed74SGeert Uytterhoeven error3:
1181afcc98deSGeert Uytterhoeven 	rspi_release_dma(master);
1182fcb4ed74SGeert Uytterhoeven error2:
1183490c9774SGeert Uytterhoeven 	pm_runtime_disable(&pdev->dev);
11840b2182ddSShimoda, Yoshihiro error1:
11850b2182ddSShimoda, Yoshihiro 	spi_master_put(master);
11860b2182ddSShimoda, Yoshihiro 
11870b2182ddSShimoda, Yoshihiro 	return ret;
11880b2182ddSShimoda, Yoshihiro }
11890b2182ddSShimoda, Yoshihiro 
11905ce0ba88SHiep Cao Minh static struct platform_device_id spi_driver_ids[] = {
11915ce0ba88SHiep Cao Minh 	{ "rspi",	(kernel_ulong_t)&rspi_ops },
1192862d357fSGeert Uytterhoeven 	{ "rspi-rz",	(kernel_ulong_t)&rspi_rz_ops },
11935ce0ba88SHiep Cao Minh 	{ "qspi",	(kernel_ulong_t)&qspi_ops },
11945ce0ba88SHiep Cao Minh 	{},
11955ce0ba88SHiep Cao Minh };
11965ce0ba88SHiep Cao Minh 
11975ce0ba88SHiep Cao Minh MODULE_DEVICE_TABLE(platform, spi_driver_ids);
11985ce0ba88SHiep Cao Minh 
11990b2182ddSShimoda, Yoshihiro static struct platform_driver rspi_driver = {
12000b2182ddSShimoda, Yoshihiro 	.probe =	rspi_probe,
1201fd4a319bSGrant Likely 	.remove =	rspi_remove,
12025ce0ba88SHiep Cao Minh 	.id_table =	spi_driver_ids,
12030b2182ddSShimoda, Yoshihiro 	.driver		= {
12045ce0ba88SHiep Cao Minh 		.name = "renesas_spi",
12050b2182ddSShimoda, Yoshihiro 		.owner	= THIS_MODULE,
1206426ef76dSGeert Uytterhoeven 		.of_match_table = of_match_ptr(rspi_of_match),
12070b2182ddSShimoda, Yoshihiro 	},
12080b2182ddSShimoda, Yoshihiro };
12090b2182ddSShimoda, Yoshihiro module_platform_driver(rspi_driver);
12100b2182ddSShimoda, Yoshihiro 
12110b2182ddSShimoda, Yoshihiro MODULE_DESCRIPTION("Renesas RSPI bus driver");
12120b2182ddSShimoda, Yoshihiro MODULE_LICENSE("GPL v2");
12130b2182ddSShimoda, Yoshihiro MODULE_AUTHOR("Yoshihiro Shimoda");
12140b2182ddSShimoda, Yoshihiro MODULE_ALIAS("platform:rspi");
1215