xref: /openbmc/linux/drivers/spi/spi-rspi.c (revision c1ca59c2)
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 
200b2182ddSShimoda, Yoshihiro #include <linux/module.h>
210b2182ddSShimoda, Yoshihiro #include <linux/kernel.h>
220b2182ddSShimoda, Yoshihiro #include <linux/sched.h>
230b2182ddSShimoda, Yoshihiro #include <linux/errno.h>
240b2182ddSShimoda, Yoshihiro #include <linux/interrupt.h>
250b2182ddSShimoda, Yoshihiro #include <linux/platform_device.h>
260b2182ddSShimoda, Yoshihiro #include <linux/io.h>
270b2182ddSShimoda, Yoshihiro #include <linux/clk.h>
28a3633fe7SShimoda, Yoshihiro #include <linux/dmaengine.h>
29a3633fe7SShimoda, Yoshihiro #include <linux/dma-mapping.h>
30426ef76dSGeert Uytterhoeven #include <linux/of_device.h>
31490c9774SGeert Uytterhoeven #include <linux/pm_runtime.h>
32a3633fe7SShimoda, Yoshihiro #include <linux/sh_dma.h>
330b2182ddSShimoda, Yoshihiro #include <linux/spi/spi.h>
34a3633fe7SShimoda, Yoshihiro #include <linux/spi/rspi.h>
350b2182ddSShimoda, Yoshihiro 
366ab4865bSGeert Uytterhoeven #define RSPI_SPCR		0x00	/* Control Register */
376ab4865bSGeert Uytterhoeven #define RSPI_SSLP		0x01	/* Slave Select Polarity Register */
386ab4865bSGeert Uytterhoeven #define RSPI_SPPCR		0x02	/* Pin Control Register */
396ab4865bSGeert Uytterhoeven #define RSPI_SPSR		0x03	/* Status Register */
406ab4865bSGeert Uytterhoeven #define RSPI_SPDR		0x04	/* Data Register */
416ab4865bSGeert Uytterhoeven #define RSPI_SPSCR		0x08	/* Sequence Control Register */
426ab4865bSGeert Uytterhoeven #define RSPI_SPSSR		0x09	/* Sequence Status Register */
436ab4865bSGeert Uytterhoeven #define RSPI_SPBR		0x0a	/* Bit Rate Register */
446ab4865bSGeert Uytterhoeven #define RSPI_SPDCR		0x0b	/* Data Control Register */
456ab4865bSGeert Uytterhoeven #define RSPI_SPCKD		0x0c	/* Clock Delay Register */
466ab4865bSGeert Uytterhoeven #define RSPI_SSLND		0x0d	/* Slave Select Negation Delay Register */
476ab4865bSGeert Uytterhoeven #define RSPI_SPND		0x0e	/* Next-Access Delay Register */
48862d357fSGeert Uytterhoeven #define RSPI_SPCR2		0x0f	/* Control Register 2 (SH only) */
496ab4865bSGeert Uytterhoeven #define RSPI_SPCMD0		0x10	/* Command Register 0 */
506ab4865bSGeert Uytterhoeven #define RSPI_SPCMD1		0x12	/* Command Register 1 */
516ab4865bSGeert Uytterhoeven #define RSPI_SPCMD2		0x14	/* Command Register 2 */
526ab4865bSGeert Uytterhoeven #define RSPI_SPCMD3		0x16	/* Command Register 3 */
536ab4865bSGeert Uytterhoeven #define RSPI_SPCMD4		0x18	/* Command Register 4 */
546ab4865bSGeert Uytterhoeven #define RSPI_SPCMD5		0x1a	/* Command Register 5 */
556ab4865bSGeert Uytterhoeven #define RSPI_SPCMD6		0x1c	/* Command Register 6 */
566ab4865bSGeert Uytterhoeven #define RSPI_SPCMD7		0x1e	/* Command Register 7 */
57880c6d11SGeert Uytterhoeven #define RSPI_SPCMD(i)		(RSPI_SPCMD0 + (i) * 2)
58880c6d11SGeert Uytterhoeven #define RSPI_NUM_SPCMD		8
59880c6d11SGeert Uytterhoeven #define RSPI_RZ_NUM_SPCMD	4
60880c6d11SGeert Uytterhoeven #define QSPI_NUM_SPCMD		4
61862d357fSGeert Uytterhoeven 
62862d357fSGeert Uytterhoeven /* RSPI on RZ only */
636ab4865bSGeert Uytterhoeven #define RSPI_SPBFCR		0x20	/* Buffer Control Register */
646ab4865bSGeert Uytterhoeven #define RSPI_SPBFDR		0x22	/* Buffer Data Count Setting Register */
650b2182ddSShimoda, Yoshihiro 
66862d357fSGeert Uytterhoeven /* QSPI only */
67fbe5072bSGeert Uytterhoeven #define QSPI_SPBFCR		0x18	/* Buffer Control Register */
68fbe5072bSGeert Uytterhoeven #define QSPI_SPBDCR		0x1a	/* Buffer Data Count Register */
69fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL0		0x1c	/* Transfer Data Length Multiplier Setting Register 0 */
70fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL1		0x20	/* Transfer Data Length Multiplier Setting Register 1 */
71fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL2		0x24	/* Transfer Data Length Multiplier Setting Register 2 */
72fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL3		0x28	/* Transfer Data Length Multiplier Setting Register 3 */
73880c6d11SGeert Uytterhoeven #define QSPI_SPBMUL(i)		(QSPI_SPBMUL0 + (i) * 4)
745ce0ba88SHiep Cao Minh 
756ab4865bSGeert Uytterhoeven /* SPCR - Control Register */
766ab4865bSGeert Uytterhoeven #define SPCR_SPRIE		0x80	/* Receive Interrupt Enable */
776ab4865bSGeert Uytterhoeven #define SPCR_SPE		0x40	/* Function Enable */
786ab4865bSGeert Uytterhoeven #define SPCR_SPTIE		0x20	/* Transmit Interrupt Enable */
796ab4865bSGeert Uytterhoeven #define SPCR_SPEIE		0x10	/* Error Interrupt Enable */
806ab4865bSGeert Uytterhoeven #define SPCR_MSTR		0x08	/* Master/Slave Mode Select */
816ab4865bSGeert Uytterhoeven #define SPCR_MODFEN		0x04	/* Mode Fault Error Detection Enable */
826ab4865bSGeert Uytterhoeven /* RSPI on SH only */
836ab4865bSGeert Uytterhoeven #define SPCR_TXMD		0x02	/* TX Only Mode (vs. Full Duplex) */
846ab4865bSGeert Uytterhoeven #define SPCR_SPMS		0x01	/* 3-wire Mode (vs. 4-wire) */
856089af77SGeert Uytterhoeven /* QSPI on R-Car Gen2 only */
86fbe5072bSGeert Uytterhoeven #define SPCR_WSWAP		0x02	/* Word Swap of read-data for DMAC */
87fbe5072bSGeert Uytterhoeven #define SPCR_BSWAP		0x01	/* Byte Swap of read-data for DMAC */
880b2182ddSShimoda, Yoshihiro 
896ab4865bSGeert Uytterhoeven /* SSLP - Slave Select Polarity Register */
906ab4865bSGeert Uytterhoeven #define SSLP_SSL1P		0x02	/* SSL1 Signal Polarity Setting */
916ab4865bSGeert Uytterhoeven #define SSLP_SSL0P		0x01	/* SSL0 Signal Polarity Setting */
920b2182ddSShimoda, Yoshihiro 
936ab4865bSGeert Uytterhoeven /* SPPCR - Pin Control Register */
946ab4865bSGeert Uytterhoeven #define SPPCR_MOIFE		0x20	/* MOSI Idle Value Fixing Enable */
956ab4865bSGeert Uytterhoeven #define SPPCR_MOIFV		0x10	/* MOSI Idle Fixed Value */
960b2182ddSShimoda, Yoshihiro #define SPPCR_SPOM		0x04
976ab4865bSGeert Uytterhoeven #define SPPCR_SPLP2		0x02	/* Loopback Mode 2 (non-inverting) */
986ab4865bSGeert Uytterhoeven #define SPPCR_SPLP		0x01	/* Loopback Mode (inverting) */
990b2182ddSShimoda, Yoshihiro 
100fbe5072bSGeert Uytterhoeven #define SPPCR_IO3FV		0x04	/* Single-/Dual-SPI Mode IO3 Output Fixed Value */
101fbe5072bSGeert Uytterhoeven #define SPPCR_IO2FV		0x04	/* Single-/Dual-SPI Mode IO2 Output Fixed Value */
102fbe5072bSGeert Uytterhoeven 
1036ab4865bSGeert Uytterhoeven /* SPSR - Status Register */
1046ab4865bSGeert Uytterhoeven #define SPSR_SPRF		0x80	/* Receive Buffer Full Flag */
1056ab4865bSGeert Uytterhoeven #define SPSR_TEND		0x40	/* Transmit End */
1066ab4865bSGeert Uytterhoeven #define SPSR_SPTEF		0x20	/* Transmit Buffer Empty Flag */
1076ab4865bSGeert Uytterhoeven #define SPSR_PERF		0x08	/* Parity Error Flag */
1086ab4865bSGeert Uytterhoeven #define SPSR_MODF		0x04	/* Mode Fault Error Flag */
1096ab4865bSGeert Uytterhoeven #define SPSR_IDLNF		0x02	/* RSPI Idle Flag */
110862d357fSGeert Uytterhoeven #define SPSR_OVRF		0x01	/* Overrun Error Flag (RSPI only) */
1110b2182ddSShimoda, Yoshihiro 
1126ab4865bSGeert Uytterhoeven /* SPSCR - Sequence Control Register */
1136ab4865bSGeert Uytterhoeven #define SPSCR_SPSLN_MASK	0x07	/* Sequence Length Specification */
1140b2182ddSShimoda, Yoshihiro 
1156ab4865bSGeert Uytterhoeven /* SPSSR - Sequence Status Register */
1166ab4865bSGeert Uytterhoeven #define SPSSR_SPECM_MASK	0x70	/* Command Error Mask */
1176ab4865bSGeert Uytterhoeven #define SPSSR_SPCP_MASK		0x07	/* Command Pointer Mask */
1180b2182ddSShimoda, Yoshihiro 
1196ab4865bSGeert Uytterhoeven /* SPDCR - Data Control Register */
1206ab4865bSGeert Uytterhoeven #define SPDCR_TXDMY		0x80	/* Dummy Data Transmission Enable */
1216ab4865bSGeert Uytterhoeven #define SPDCR_SPLW1		0x40	/* Access Width Specification (RZ) */
1226ab4865bSGeert Uytterhoeven #define SPDCR_SPLW0		0x20	/* Access Width Specification (RZ) */
1236ab4865bSGeert Uytterhoeven #define SPDCR_SPLLWORD		(SPDCR_SPLW1 | SPDCR_SPLW0)
1246ab4865bSGeert Uytterhoeven #define SPDCR_SPLWORD		SPDCR_SPLW1
1256ab4865bSGeert Uytterhoeven #define SPDCR_SPLBYTE		SPDCR_SPLW0
1266ab4865bSGeert Uytterhoeven #define SPDCR_SPLW		0x20	/* Access Width Specification (SH) */
127862d357fSGeert Uytterhoeven #define SPDCR_SPRDTD		0x10	/* Receive Transmit Data Select (SH) */
1280b2182ddSShimoda, Yoshihiro #define SPDCR_SLSEL1		0x08
1290b2182ddSShimoda, Yoshihiro #define SPDCR_SLSEL0		0x04
130862d357fSGeert Uytterhoeven #define SPDCR_SLSEL_MASK	0x0c	/* SSL1 Output Select (SH) */
1310b2182ddSShimoda, Yoshihiro #define SPDCR_SPFC1		0x02
1320b2182ddSShimoda, Yoshihiro #define SPDCR_SPFC0		0x01
133862d357fSGeert Uytterhoeven #define SPDCR_SPFC_MASK		0x03	/* Frame Count Setting (1-4) (SH) */
1340b2182ddSShimoda, Yoshihiro 
1356ab4865bSGeert Uytterhoeven /* SPCKD - Clock Delay Register */
1366ab4865bSGeert Uytterhoeven #define SPCKD_SCKDL_MASK	0x07	/* Clock Delay Setting (1-8) */
1370b2182ddSShimoda, Yoshihiro 
1386ab4865bSGeert Uytterhoeven /* SSLND - Slave Select Negation Delay Register */
1396ab4865bSGeert Uytterhoeven #define SSLND_SLNDL_MASK	0x07	/* SSL Negation Delay Setting (1-8) */
1400b2182ddSShimoda, Yoshihiro 
1416ab4865bSGeert Uytterhoeven /* SPND - Next-Access Delay Register */
1426ab4865bSGeert Uytterhoeven #define SPND_SPNDL_MASK		0x07	/* Next-Access Delay Setting (1-8) */
1430b2182ddSShimoda, Yoshihiro 
1446ab4865bSGeert Uytterhoeven /* SPCR2 - Control Register 2 */
1456ab4865bSGeert Uytterhoeven #define SPCR2_PTE		0x08	/* Parity Self-Test Enable */
1466ab4865bSGeert Uytterhoeven #define SPCR2_SPIE		0x04	/* Idle Interrupt Enable */
1476ab4865bSGeert Uytterhoeven #define SPCR2_SPOE		0x02	/* Odd Parity Enable (vs. Even) */
1486ab4865bSGeert Uytterhoeven #define SPCR2_SPPE		0x01	/* Parity Enable */
1490b2182ddSShimoda, Yoshihiro 
1506ab4865bSGeert Uytterhoeven /* SPCMDn - Command Registers */
1516ab4865bSGeert Uytterhoeven #define SPCMD_SCKDEN		0x8000	/* Clock Delay Setting Enable */
1526ab4865bSGeert Uytterhoeven #define SPCMD_SLNDEN		0x4000	/* SSL Negation Delay Setting Enable */
1536ab4865bSGeert Uytterhoeven #define SPCMD_SPNDEN		0x2000	/* Next-Access Delay Enable */
1546ab4865bSGeert Uytterhoeven #define SPCMD_LSBF		0x1000	/* LSB First */
1556ab4865bSGeert Uytterhoeven #define SPCMD_SPB_MASK		0x0f00	/* Data Length Setting */
1560b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_8_TO_16(bit)	(((bit - 1) << 8) & SPCMD_SPB_MASK)
157880c6d11SGeert Uytterhoeven #define SPCMD_SPB_8BIT		0x0000	/* QSPI only */
1585ce0ba88SHiep Cao Minh #define SPCMD_SPB_16BIT		0x0100
1590b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_20BIT		0x0000
1600b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_24BIT		0x0100
1610b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_32BIT		0x0200
1626ab4865bSGeert Uytterhoeven #define SPCMD_SSLKP		0x0080	/* SSL Signal Level Keeping */
163fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_MASK	0x0060	/* SPI Operating Mode (QSPI only) */
164fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD1		0x0040
165fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD0		0x0020
166fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_SINGLE	0
167fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_DUAL	SPCMD_SPIMOD0
168fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_QUAD	SPCMD_SPIMOD1
169fbe5072bSGeert Uytterhoeven #define SPCMD_SPRW		0x0010	/* SPI Read/Write Access (Dual/Quad) */
1706ab4865bSGeert Uytterhoeven #define SPCMD_SSLA_MASK		0x0030	/* SSL Assert Signal Setting (RSPI) */
1716ab4865bSGeert Uytterhoeven #define SPCMD_BRDV_MASK		0x000c	/* Bit Rate Division Setting */
1726ab4865bSGeert Uytterhoeven #define SPCMD_CPOL		0x0002	/* Clock Polarity Setting */
1736ab4865bSGeert Uytterhoeven #define SPCMD_CPHA		0x0001	/* Clock Phase Setting */
1740b2182ddSShimoda, Yoshihiro 
1756ab4865bSGeert Uytterhoeven /* SPBFCR - Buffer Control Register */
176862d357fSGeert Uytterhoeven #define SPBFCR_TXRST		0x80	/* Transmit Buffer Data Reset */
177862d357fSGeert Uytterhoeven #define SPBFCR_RXRST		0x40	/* Receive Buffer Data Reset */
1786ab4865bSGeert Uytterhoeven #define SPBFCR_TXTRG_MASK	0x30	/* Transmit Buffer Data Triggering Number */
1796ab4865bSGeert Uytterhoeven #define SPBFCR_RXTRG_MASK	0x07	/* Receive Buffer Data Triggering Number */
1804b6fe3edSHiep Cao Minh /* QSPI on R-Car Gen2 */
1814b6fe3edSHiep Cao Minh #define SPBFCR_TXTRG_1B		0x00	/* 31 bytes (1 byte available) */
1824b6fe3edSHiep Cao Minh #define SPBFCR_TXTRG_32B	0x30	/* 0 byte (32 bytes available) */
1834b6fe3edSHiep Cao Minh #define SPBFCR_RXTRG_1B		0x00	/* 1 byte (31 bytes available) */
1844b6fe3edSHiep Cao Minh #define SPBFCR_RXTRG_32B	0x07	/* 32 bytes (0 byte available) */
1854b6fe3edSHiep Cao Minh 
1864b6fe3edSHiep Cao Minh #define QSPI_BUFFER_SIZE        32u
1875ce0ba88SHiep Cao Minh 
1880b2182ddSShimoda, Yoshihiro struct rspi_data {
1890b2182ddSShimoda, Yoshihiro 	void __iomem *addr;
1900b2182ddSShimoda, Yoshihiro 	u32 max_speed_hz;
1910b2182ddSShimoda, Yoshihiro 	struct spi_master *master;
1920b2182ddSShimoda, Yoshihiro 	wait_queue_head_t wait;
1930b2182ddSShimoda, Yoshihiro 	struct clk *clk;
194348e5153SGeert Uytterhoeven 	u16 spcmd;
19506a7a3cfSGeert Uytterhoeven 	u8 spsr;
19606a7a3cfSGeert Uytterhoeven 	u8 sppcr;
19793722206SGeert Uytterhoeven 	int rx_irq, tx_irq;
1985ce0ba88SHiep Cao Minh 	const struct spi_ops *ops;
199a3633fe7SShimoda, Yoshihiro 
200a3633fe7SShimoda, Yoshihiro 	unsigned dma_callbacked:1;
20174da7686SGeert Uytterhoeven 	unsigned byte_access:1;
2020b2182ddSShimoda, Yoshihiro };
2030b2182ddSShimoda, Yoshihiro 
204baf588f4SGeert Uytterhoeven static void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset)
2050b2182ddSShimoda, Yoshihiro {
2060b2182ddSShimoda, Yoshihiro 	iowrite8(data, rspi->addr + offset);
2070b2182ddSShimoda, Yoshihiro }
2080b2182ddSShimoda, Yoshihiro 
209baf588f4SGeert Uytterhoeven static void rspi_write16(const struct rspi_data *rspi, u16 data, u16 offset)
2100b2182ddSShimoda, Yoshihiro {
2110b2182ddSShimoda, Yoshihiro 	iowrite16(data, rspi->addr + offset);
2120b2182ddSShimoda, Yoshihiro }
2130b2182ddSShimoda, Yoshihiro 
214baf588f4SGeert Uytterhoeven static void rspi_write32(const struct rspi_data *rspi, u32 data, u16 offset)
2155ce0ba88SHiep Cao Minh {
2165ce0ba88SHiep Cao Minh 	iowrite32(data, rspi->addr + offset);
2175ce0ba88SHiep Cao Minh }
2185ce0ba88SHiep Cao Minh 
219baf588f4SGeert Uytterhoeven static u8 rspi_read8(const struct rspi_data *rspi, u16 offset)
2200b2182ddSShimoda, Yoshihiro {
2210b2182ddSShimoda, Yoshihiro 	return ioread8(rspi->addr + offset);
2220b2182ddSShimoda, Yoshihiro }
2230b2182ddSShimoda, Yoshihiro 
224baf588f4SGeert Uytterhoeven static u16 rspi_read16(const struct rspi_data *rspi, u16 offset)
2250b2182ddSShimoda, Yoshihiro {
2260b2182ddSShimoda, Yoshihiro 	return ioread16(rspi->addr + offset);
2270b2182ddSShimoda, Yoshihiro }
2280b2182ddSShimoda, Yoshihiro 
22974da7686SGeert Uytterhoeven static void rspi_write_data(const struct rspi_data *rspi, u16 data)
23074da7686SGeert Uytterhoeven {
23174da7686SGeert Uytterhoeven 	if (rspi->byte_access)
23274da7686SGeert Uytterhoeven 		rspi_write8(rspi, data, RSPI_SPDR);
23374da7686SGeert Uytterhoeven 	else /* 16 bit */
23474da7686SGeert Uytterhoeven 		rspi_write16(rspi, data, RSPI_SPDR);
23574da7686SGeert Uytterhoeven }
23674da7686SGeert Uytterhoeven 
23774da7686SGeert Uytterhoeven static u16 rspi_read_data(const struct rspi_data *rspi)
23874da7686SGeert Uytterhoeven {
23974da7686SGeert Uytterhoeven 	if (rspi->byte_access)
24074da7686SGeert Uytterhoeven 		return rspi_read8(rspi, RSPI_SPDR);
24174da7686SGeert Uytterhoeven 	else /* 16 bit */
24274da7686SGeert Uytterhoeven 		return rspi_read16(rspi, RSPI_SPDR);
24374da7686SGeert Uytterhoeven }
24474da7686SGeert Uytterhoeven 
2455ce0ba88SHiep Cao Minh /* optional functions */
2465ce0ba88SHiep Cao Minh struct spi_ops {
24774da7686SGeert Uytterhoeven 	int (*set_config_register)(struct rspi_data *rspi, int access_size);
248eb557f75SGeert Uytterhoeven 	int (*transfer_one)(struct spi_master *master, struct spi_device *spi,
249eb557f75SGeert Uytterhoeven 			    struct spi_transfer *xfer);
250880c6d11SGeert Uytterhoeven 	u16 mode_bits;
251b42e0359SGeert Uytterhoeven 	u16 flags;
2522f777ec9SGeert Uytterhoeven 	u16 fifo_size;
2535ce0ba88SHiep Cao Minh };
2545ce0ba88SHiep Cao Minh 
2555ce0ba88SHiep Cao Minh /*
256862d357fSGeert Uytterhoeven  * functions for RSPI on legacy SH
2575ce0ba88SHiep Cao Minh  */
25874da7686SGeert Uytterhoeven static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
2590b2182ddSShimoda, Yoshihiro {
2605ce0ba88SHiep Cao Minh 	int spbr;
2610b2182ddSShimoda, Yoshihiro 
26206a7a3cfSGeert Uytterhoeven 	/* Sets output mode, MOSI signal, and (optionally) loopback */
26306a7a3cfSGeert Uytterhoeven 	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
2640b2182ddSShimoda, Yoshihiro 
2655ce0ba88SHiep Cao Minh 	/* Sets transfer bit rate */
2663beb61dbSGeert Uytterhoeven 	spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk),
2673beb61dbSGeert Uytterhoeven 			    2 * rspi->max_speed_hz) - 1;
2685ce0ba88SHiep Cao Minh 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
2695ce0ba88SHiep Cao Minh 
27074da7686SGeert Uytterhoeven 	/* Disable dummy transmission, set 16-bit word access, 1 frame */
27174da7686SGeert Uytterhoeven 	rspi_write8(rspi, 0, RSPI_SPDCR);
27274da7686SGeert Uytterhoeven 	rspi->byte_access = 0;
2735ce0ba88SHiep Cao Minh 
2745ce0ba88SHiep Cao Minh 	/* Sets RSPCK, SSL, next-access delay value */
2755ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
2765ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SSLND);
2775ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPND);
2785ce0ba88SHiep Cao Minh 
2795ce0ba88SHiep Cao Minh 	/* Sets parity, interrupt mask */
2805ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCR2);
2815ce0ba88SHiep Cao Minh 
2825ce0ba88SHiep Cao Minh 	/* Sets SPCMD */
283880c6d11SGeert Uytterhoeven 	rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size);
284880c6d11SGeert Uytterhoeven 	rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
2855ce0ba88SHiep Cao Minh 
2865ce0ba88SHiep Cao Minh 	/* Sets RSPI mode */
2875ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
2885ce0ba88SHiep Cao Minh 
2895ce0ba88SHiep Cao Minh 	return 0;
2900b2182ddSShimoda, Yoshihiro }
2910b2182ddSShimoda, Yoshihiro 
2925ce0ba88SHiep Cao Minh /*
293862d357fSGeert Uytterhoeven  * functions for RSPI on RZ
294862d357fSGeert Uytterhoeven  */
295862d357fSGeert Uytterhoeven static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size)
296862d357fSGeert Uytterhoeven {
297862d357fSGeert Uytterhoeven 	int spbr;
298aeb8f8cbSChris Brandt 	int div = 0;
299aeb8f8cbSChris Brandt 	unsigned long clksrc;
300862d357fSGeert Uytterhoeven 
30106a7a3cfSGeert Uytterhoeven 	/* Sets output mode, MOSI signal, and (optionally) loopback */
30206a7a3cfSGeert Uytterhoeven 	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
303862d357fSGeert Uytterhoeven 
304aeb8f8cbSChris Brandt 	clksrc = clk_get_rate(rspi->clk);
305aeb8f8cbSChris Brandt 	while (div < 3) {
306aeb8f8cbSChris Brandt 		if (rspi->max_speed_hz >= clksrc/4) /* 4=(CLK/2)/2 */
307aeb8f8cbSChris Brandt 			break;
308aeb8f8cbSChris Brandt 		div++;
309aeb8f8cbSChris Brandt 		clksrc /= 2;
310aeb8f8cbSChris Brandt 	}
311aeb8f8cbSChris Brandt 
312862d357fSGeert Uytterhoeven 	/* Sets transfer bit rate */
313aeb8f8cbSChris Brandt 	spbr = DIV_ROUND_UP(clksrc, 2 * rspi->max_speed_hz) - 1;
314862d357fSGeert Uytterhoeven 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
315aeb8f8cbSChris Brandt 	rspi->spcmd |= div << 2;
316862d357fSGeert Uytterhoeven 
317862d357fSGeert Uytterhoeven 	/* Disable dummy transmission, set byte access */
318862d357fSGeert Uytterhoeven 	rspi_write8(rspi, SPDCR_SPLBYTE, RSPI_SPDCR);
319862d357fSGeert Uytterhoeven 	rspi->byte_access = 1;
320862d357fSGeert Uytterhoeven 
321862d357fSGeert Uytterhoeven 	/* Sets RSPCK, SSL, next-access delay value */
322862d357fSGeert Uytterhoeven 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
323862d357fSGeert Uytterhoeven 	rspi_write8(rspi, 0x00, RSPI_SSLND);
324862d357fSGeert Uytterhoeven 	rspi_write8(rspi, 0x00, RSPI_SPND);
325862d357fSGeert Uytterhoeven 
326862d357fSGeert Uytterhoeven 	/* Sets SPCMD */
327862d357fSGeert Uytterhoeven 	rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size);
328862d357fSGeert Uytterhoeven 	rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
329862d357fSGeert Uytterhoeven 
330862d357fSGeert Uytterhoeven 	/* Sets RSPI mode */
331862d357fSGeert Uytterhoeven 	rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
332862d357fSGeert Uytterhoeven 
333862d357fSGeert Uytterhoeven 	return 0;
334862d357fSGeert Uytterhoeven }
335862d357fSGeert Uytterhoeven 
336862d357fSGeert Uytterhoeven /*
3375ce0ba88SHiep Cao Minh  * functions for QSPI
3385ce0ba88SHiep Cao Minh  */
33974da7686SGeert Uytterhoeven static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
3405ce0ba88SHiep Cao Minh {
3415ce0ba88SHiep Cao Minh 	int spbr;
3425ce0ba88SHiep Cao Minh 
34306a7a3cfSGeert Uytterhoeven 	/* Sets output mode, MOSI signal, and (optionally) loopback */
34406a7a3cfSGeert Uytterhoeven 	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
3455ce0ba88SHiep Cao Minh 
3465ce0ba88SHiep Cao Minh 	/* Sets transfer bit rate */
3473beb61dbSGeert Uytterhoeven 	spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 2 * rspi->max_speed_hz);
3485ce0ba88SHiep Cao Minh 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
3495ce0ba88SHiep Cao Minh 
35074da7686SGeert Uytterhoeven 	/* Disable dummy transmission, set byte access */
35174da7686SGeert Uytterhoeven 	rspi_write8(rspi, 0, RSPI_SPDCR);
35274da7686SGeert Uytterhoeven 	rspi->byte_access = 1;
3535ce0ba88SHiep Cao Minh 
3545ce0ba88SHiep Cao Minh 	/* Sets RSPCK, SSL, next-access delay value */
3555ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
3565ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SSLND);
3575ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPND);
3585ce0ba88SHiep Cao Minh 
3595ce0ba88SHiep Cao Minh 	/* Data Length Setting */
3605ce0ba88SHiep Cao Minh 	if (access_size == 8)
361880c6d11SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_SPB_8BIT;
3625ce0ba88SHiep Cao Minh 	else if (access_size == 16)
363880c6d11SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_SPB_16BIT;
3648e1c8096SLaurent Pinchart 	else
365880c6d11SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_SPB_32BIT;
3665ce0ba88SHiep Cao Minh 
367880c6d11SGeert Uytterhoeven 	rspi->spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SPNDEN;
3685ce0ba88SHiep Cao Minh 
3695ce0ba88SHiep Cao Minh 	/* Resets transfer data length */
3705ce0ba88SHiep Cao Minh 	rspi_write32(rspi, 0, QSPI_SPBMUL0);
3715ce0ba88SHiep Cao Minh 
3725ce0ba88SHiep Cao Minh 	/* Resets transmit and receive buffer */
3735ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
3745ce0ba88SHiep Cao Minh 	/* Sets buffer to allow normal operation */
3755ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
3765ce0ba88SHiep Cao Minh 
3775ce0ba88SHiep Cao Minh 	/* Sets SPCMD */
378880c6d11SGeert Uytterhoeven 	rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
3795ce0ba88SHiep Cao Minh 
380b458a349SGeert Uytterhoeven 	/* Sets RSPI mode */
381b458a349SGeert Uytterhoeven 	rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
3825ce0ba88SHiep Cao Minh 
3835ce0ba88SHiep Cao Minh 	return 0;
3845ce0ba88SHiep Cao Minh }
3855ce0ba88SHiep Cao Minh 
3864b6fe3edSHiep Cao Minh static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg)
3874b6fe3edSHiep Cao Minh {
3884b6fe3edSHiep Cao Minh 	u8 data;
3894b6fe3edSHiep Cao Minh 
3904b6fe3edSHiep Cao Minh 	data = rspi_read8(rspi, reg);
3914b6fe3edSHiep Cao Minh 	data &= ~mask;
3924b6fe3edSHiep Cao Minh 	data |= (val & mask);
3934b6fe3edSHiep Cao Minh 	rspi_write8(rspi, data, reg);
3944b6fe3edSHiep Cao Minh }
3954b6fe3edSHiep Cao Minh 
396cb76b1caSGeert Uytterhoeven static unsigned int qspi_set_send_trigger(struct rspi_data *rspi,
397cb76b1caSGeert Uytterhoeven 					  unsigned int len)
3984b6fe3edSHiep Cao Minh {
3994b6fe3edSHiep Cao Minh 	unsigned int n;
4004b6fe3edSHiep Cao Minh 
4014b6fe3edSHiep Cao Minh 	n = min(len, QSPI_BUFFER_SIZE);
4024b6fe3edSHiep Cao Minh 
4034b6fe3edSHiep Cao Minh 	if (len >= QSPI_BUFFER_SIZE) {
4044b6fe3edSHiep Cao Minh 		/* sets triggering number to 32 bytes */
4054b6fe3edSHiep Cao Minh 		qspi_update(rspi, SPBFCR_TXTRG_MASK,
4064b6fe3edSHiep Cao Minh 			     SPBFCR_TXTRG_32B, QSPI_SPBFCR);
4074b6fe3edSHiep Cao Minh 	} else {
4084b6fe3edSHiep Cao Minh 		/* sets triggering number to 1 byte */
4094b6fe3edSHiep Cao Minh 		qspi_update(rspi, SPBFCR_TXTRG_MASK,
4104b6fe3edSHiep Cao Minh 			     SPBFCR_TXTRG_1B, QSPI_SPBFCR);
4114b6fe3edSHiep Cao Minh 	}
4124b6fe3edSHiep Cao Minh 
4134b6fe3edSHiep Cao Minh 	return n;
4144b6fe3edSHiep Cao Minh }
4154b6fe3edSHiep Cao Minh 
4163be09becSHiep Cao Minh static int qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len)
4174b6fe3edSHiep Cao Minh {
4184b6fe3edSHiep Cao Minh 	unsigned int n;
4194b6fe3edSHiep Cao Minh 
4204b6fe3edSHiep Cao Minh 	n = min(len, QSPI_BUFFER_SIZE);
4214b6fe3edSHiep Cao Minh 
4224b6fe3edSHiep Cao Minh 	if (len >= QSPI_BUFFER_SIZE) {
4234b6fe3edSHiep Cao Minh 		/* sets triggering number to 32 bytes */
4244b6fe3edSHiep Cao Minh 		qspi_update(rspi, SPBFCR_RXTRG_MASK,
4254b6fe3edSHiep Cao Minh 			     SPBFCR_RXTRG_32B, QSPI_SPBFCR);
4264b6fe3edSHiep Cao Minh 	} else {
4274b6fe3edSHiep Cao Minh 		/* sets triggering number to 1 byte */
4284b6fe3edSHiep Cao Minh 		qspi_update(rspi, SPBFCR_RXTRG_MASK,
4294b6fe3edSHiep Cao Minh 			     SPBFCR_RXTRG_1B, QSPI_SPBFCR);
4304b6fe3edSHiep Cao Minh 	}
4313be09becSHiep Cao Minh 	return n;
4324b6fe3edSHiep Cao Minh }
4334b6fe3edSHiep Cao Minh 
4345ce0ba88SHiep Cao Minh #define set_config_register(spi, n) spi->ops->set_config_register(spi, n)
4355ce0ba88SHiep Cao Minh 
436baf588f4SGeert Uytterhoeven static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable)
4370b2182ddSShimoda, Yoshihiro {
4380b2182ddSShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR);
4390b2182ddSShimoda, Yoshihiro }
4400b2182ddSShimoda, Yoshihiro 
441baf588f4SGeert Uytterhoeven static void rspi_disable_irq(const struct rspi_data *rspi, u8 disable)
4420b2182ddSShimoda, Yoshihiro {
4430b2182ddSShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~disable, RSPI_SPCR);
4440b2182ddSShimoda, Yoshihiro }
4450b2182ddSShimoda, Yoshihiro 
4460b2182ddSShimoda, Yoshihiro static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
4470b2182ddSShimoda, Yoshihiro 				   u8 enable_bit)
4480b2182ddSShimoda, Yoshihiro {
4490b2182ddSShimoda, Yoshihiro 	int ret;
4500b2182ddSShimoda, Yoshihiro 
4510b2182ddSShimoda, Yoshihiro 	rspi->spsr = rspi_read8(rspi, RSPI_SPSR);
4525dd1ad23SGeert Uytterhoeven 	if (rspi->spsr & wait_mask)
4535dd1ad23SGeert Uytterhoeven 		return 0;
4545dd1ad23SGeert Uytterhoeven 
4550b2182ddSShimoda, Yoshihiro 	rspi_enable_irq(rspi, enable_bit);
4560b2182ddSShimoda, Yoshihiro 	ret = wait_event_timeout(rspi->wait, rspi->spsr & wait_mask, HZ);
4570b2182ddSShimoda, Yoshihiro 	if (ret == 0 && !(rspi->spsr & wait_mask))
4580b2182ddSShimoda, Yoshihiro 		return -ETIMEDOUT;
4590b2182ddSShimoda, Yoshihiro 
4600b2182ddSShimoda, Yoshihiro 	return 0;
4610b2182ddSShimoda, Yoshihiro }
4620b2182ddSShimoda, Yoshihiro 
4635f684c34SGeert Uytterhoeven static inline int rspi_wait_for_tx_empty(struct rspi_data *rspi)
4645f684c34SGeert Uytterhoeven {
4655f684c34SGeert Uytterhoeven 	return rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
4665f684c34SGeert Uytterhoeven }
4675f684c34SGeert Uytterhoeven 
4685f684c34SGeert Uytterhoeven static inline int rspi_wait_for_rx_full(struct rspi_data *rspi)
4695f684c34SGeert Uytterhoeven {
4705f684c34SGeert Uytterhoeven 	return rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE);
4715f684c34SGeert Uytterhoeven }
4725f684c34SGeert Uytterhoeven 
47335301c99SGeert Uytterhoeven static int rspi_data_out(struct rspi_data *rspi, u8 data)
47435301c99SGeert Uytterhoeven {
4755f684c34SGeert Uytterhoeven 	int error = rspi_wait_for_tx_empty(rspi);
4765f684c34SGeert Uytterhoeven 	if (error < 0) {
47735301c99SGeert Uytterhoeven 		dev_err(&rspi->master->dev, "transmit timeout\n");
4785f684c34SGeert Uytterhoeven 		return error;
47935301c99SGeert Uytterhoeven 	}
48035301c99SGeert Uytterhoeven 	rspi_write_data(rspi, data);
48135301c99SGeert Uytterhoeven 	return 0;
48235301c99SGeert Uytterhoeven }
48335301c99SGeert Uytterhoeven 
48435301c99SGeert Uytterhoeven static int rspi_data_in(struct rspi_data *rspi)
48535301c99SGeert Uytterhoeven {
4865f684c34SGeert Uytterhoeven 	int error;
48735301c99SGeert Uytterhoeven 	u8 data;
48835301c99SGeert Uytterhoeven 
4895f684c34SGeert Uytterhoeven 	error = rspi_wait_for_rx_full(rspi);
4905f684c34SGeert Uytterhoeven 	if (error < 0) {
49135301c99SGeert Uytterhoeven 		dev_err(&rspi->master->dev, "receive timeout\n");
4925f684c34SGeert Uytterhoeven 		return error;
49335301c99SGeert Uytterhoeven 	}
49435301c99SGeert Uytterhoeven 	data = rspi_read_data(rspi);
49535301c99SGeert Uytterhoeven 	return data;
49635301c99SGeert Uytterhoeven }
49735301c99SGeert Uytterhoeven 
4986837b8e9SGeert Uytterhoeven static int rspi_pio_transfer(struct rspi_data *rspi, const u8 *tx, u8 *rx,
4996837b8e9SGeert Uytterhoeven 			     unsigned int n)
50035301c99SGeert Uytterhoeven {
5016837b8e9SGeert Uytterhoeven 	while (n-- > 0) {
5026837b8e9SGeert Uytterhoeven 		if (tx) {
5036837b8e9SGeert Uytterhoeven 			int ret = rspi_data_out(rspi, *tx++);
50435301c99SGeert Uytterhoeven 			if (ret < 0)
50535301c99SGeert Uytterhoeven 				return ret;
5066837b8e9SGeert Uytterhoeven 		}
5076837b8e9SGeert Uytterhoeven 		if (rx) {
5086837b8e9SGeert Uytterhoeven 			int ret = rspi_data_in(rspi);
5096837b8e9SGeert Uytterhoeven 			if (ret < 0)
5106837b8e9SGeert Uytterhoeven 				return ret;
5116837b8e9SGeert Uytterhoeven 			*rx++ = ret;
5126837b8e9SGeert Uytterhoeven 		}
5136837b8e9SGeert Uytterhoeven 	}
51435301c99SGeert Uytterhoeven 
5156837b8e9SGeert Uytterhoeven 	return 0;
51635301c99SGeert Uytterhoeven }
51735301c99SGeert Uytterhoeven 
518a3633fe7SShimoda, Yoshihiro static void rspi_dma_complete(void *arg)
5190b2182ddSShimoda, Yoshihiro {
520a3633fe7SShimoda, Yoshihiro 	struct rspi_data *rspi = arg;
521a3633fe7SShimoda, Yoshihiro 
522a3633fe7SShimoda, Yoshihiro 	rspi->dma_callbacked = 1;
523a3633fe7SShimoda, Yoshihiro 	wake_up_interruptible(&rspi->wait);
524a3633fe7SShimoda, Yoshihiro }
525a3633fe7SShimoda, Yoshihiro 
526c52fb6d6SGeert Uytterhoeven static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
527c52fb6d6SGeert Uytterhoeven 			     struct sg_table *rx)
528a3633fe7SShimoda, Yoshihiro {
529c52fb6d6SGeert Uytterhoeven 	struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
530c52fb6d6SGeert Uytterhoeven 	u8 irq_mask = 0;
531c52fb6d6SGeert Uytterhoeven 	unsigned int other_irq = 0;
532c52fb6d6SGeert Uytterhoeven 	dma_cookie_t cookie;
5332f777ec9SGeert Uytterhoeven 	int ret;
534a3633fe7SShimoda, Yoshihiro 
5353819bc87SGeert Uytterhoeven 	/* First prepare and submit the DMA request(s), as this may fail */
536c52fb6d6SGeert Uytterhoeven 	if (rx) {
537c52fb6d6SGeert Uytterhoeven 		desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx,
538768d59f5SStefan Agner 					rx->sgl, rx->nents, DMA_DEV_TO_MEM,
539c52fb6d6SGeert Uytterhoeven 					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
5403819bc87SGeert Uytterhoeven 		if (!desc_rx) {
5413819bc87SGeert Uytterhoeven 			ret = -EAGAIN;
5423819bc87SGeert Uytterhoeven 			goto no_dma_rx;
5433819bc87SGeert Uytterhoeven 		}
5443819bc87SGeert Uytterhoeven 
5453819bc87SGeert Uytterhoeven 		desc_rx->callback = rspi_dma_complete;
5463819bc87SGeert Uytterhoeven 		desc_rx->callback_param = rspi;
5473819bc87SGeert Uytterhoeven 		cookie = dmaengine_submit(desc_rx);
5483819bc87SGeert Uytterhoeven 		if (dma_submit_error(cookie)) {
5493819bc87SGeert Uytterhoeven 			ret = cookie;
5503819bc87SGeert Uytterhoeven 			goto no_dma_rx;
5513819bc87SGeert Uytterhoeven 		}
552c52fb6d6SGeert Uytterhoeven 
553c52fb6d6SGeert Uytterhoeven 		irq_mask |= SPCR_SPRIE;
554c52fb6d6SGeert Uytterhoeven 	}
555c52fb6d6SGeert Uytterhoeven 
5563819bc87SGeert Uytterhoeven 	if (tx) {
5573819bc87SGeert Uytterhoeven 		desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx,
558768d59f5SStefan Agner 					tx->sgl, tx->nents, DMA_MEM_TO_DEV,
5593819bc87SGeert Uytterhoeven 					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
5603819bc87SGeert Uytterhoeven 		if (!desc_tx) {
5613819bc87SGeert Uytterhoeven 			ret = -EAGAIN;
5623819bc87SGeert Uytterhoeven 			goto no_dma_tx;
5633819bc87SGeert Uytterhoeven 		}
5643819bc87SGeert Uytterhoeven 
5653819bc87SGeert Uytterhoeven 		if (rx) {
5663819bc87SGeert Uytterhoeven 			/* No callback */
5673819bc87SGeert Uytterhoeven 			desc_tx->callback = NULL;
5683819bc87SGeert Uytterhoeven 		} else {
5693819bc87SGeert Uytterhoeven 			desc_tx->callback = rspi_dma_complete;
5703819bc87SGeert Uytterhoeven 			desc_tx->callback_param = rspi;
5713819bc87SGeert Uytterhoeven 		}
5723819bc87SGeert Uytterhoeven 		cookie = dmaengine_submit(desc_tx);
5733819bc87SGeert Uytterhoeven 		if (dma_submit_error(cookie)) {
5743819bc87SGeert Uytterhoeven 			ret = cookie;
5753819bc87SGeert Uytterhoeven 			goto no_dma_tx;
5763819bc87SGeert Uytterhoeven 		}
5773819bc87SGeert Uytterhoeven 
5783819bc87SGeert Uytterhoeven 		irq_mask |= SPCR_SPTIE;
5793819bc87SGeert Uytterhoeven 	}
5803819bc87SGeert Uytterhoeven 
581a3633fe7SShimoda, Yoshihiro 	/*
582c52fb6d6SGeert Uytterhoeven 	 * DMAC needs SPxIE, but if SPxIE is set, the IRQ routine will be
583a3633fe7SShimoda, Yoshihiro 	 * called. So, this driver disables the IRQ while DMA transfer.
584a3633fe7SShimoda, Yoshihiro 	 */
585c52fb6d6SGeert Uytterhoeven 	if (tx)
586c52fb6d6SGeert Uytterhoeven 		disable_irq(other_irq = rspi->tx_irq);
587c52fb6d6SGeert Uytterhoeven 	if (rx && rspi->rx_irq != other_irq)
588c52fb6d6SGeert Uytterhoeven 		disable_irq(rspi->rx_irq);
589a3633fe7SShimoda, Yoshihiro 
590c52fb6d6SGeert Uytterhoeven 	rspi_enable_irq(rspi, irq_mask);
591a3633fe7SShimoda, Yoshihiro 	rspi->dma_callbacked = 0;
592a3633fe7SShimoda, Yoshihiro 
5933819bc87SGeert Uytterhoeven 	/* Now start DMA */
5943819bc87SGeert Uytterhoeven 	if (rx)
595c52fb6d6SGeert Uytterhoeven 		dma_async_issue_pending(rspi->master->dma_rx);
5963819bc87SGeert Uytterhoeven 	if (tx)
5972f777ec9SGeert Uytterhoeven 		dma_async_issue_pending(rspi->master->dma_tx);
598a3633fe7SShimoda, Yoshihiro 
599a3633fe7SShimoda, Yoshihiro 	ret = wait_event_interruptible_timeout(rspi->wait,
600a3633fe7SShimoda, Yoshihiro 					       rspi->dma_callbacked, HZ);
601a3633fe7SShimoda, Yoshihiro 	if (ret > 0 && rspi->dma_callbacked)
602a3633fe7SShimoda, Yoshihiro 		ret = 0;
6033819bc87SGeert Uytterhoeven 	else if (!ret) {
6043819bc87SGeert Uytterhoeven 		dev_err(&rspi->master->dev, "DMA timeout\n");
605a3633fe7SShimoda, Yoshihiro 		ret = -ETIMEDOUT;
6063819bc87SGeert Uytterhoeven 		if (tx)
6073819bc87SGeert Uytterhoeven 			dmaengine_terminate_all(rspi->master->dma_tx);
6083819bc87SGeert Uytterhoeven 		if (rx)
6093819bc87SGeert Uytterhoeven 			dmaengine_terminate_all(rspi->master->dma_rx);
6103819bc87SGeert Uytterhoeven 	}
611a3633fe7SShimoda, Yoshihiro 
612c52fb6d6SGeert Uytterhoeven 	rspi_disable_irq(rspi, irq_mask);
613c52fb6d6SGeert Uytterhoeven 
614c52fb6d6SGeert Uytterhoeven 	if (tx)
61593722206SGeert Uytterhoeven 		enable_irq(rspi->tx_irq);
616c52fb6d6SGeert Uytterhoeven 	if (rx && rspi->rx_irq != other_irq)
617c52fb6d6SGeert Uytterhoeven 		enable_irq(rspi->rx_irq);
618c52fb6d6SGeert Uytterhoeven 
619a3633fe7SShimoda, Yoshihiro 	return ret;
62085912a88SGeert Uytterhoeven 
6213819bc87SGeert Uytterhoeven no_dma_tx:
6223819bc87SGeert Uytterhoeven 	if (rx)
6233819bc87SGeert Uytterhoeven 		dmaengine_terminate_all(rspi->master->dma_rx);
6243819bc87SGeert Uytterhoeven no_dma_rx:
6253819bc87SGeert Uytterhoeven 	if (ret == -EAGAIN) {
62685912a88SGeert Uytterhoeven 		pr_warn_once("%s %s: DMA not available, falling back to PIO\n",
62785912a88SGeert Uytterhoeven 			     dev_driver_string(&rspi->master->dev),
62885912a88SGeert Uytterhoeven 			     dev_name(&rspi->master->dev));
6293819bc87SGeert Uytterhoeven 	}
6303819bc87SGeert Uytterhoeven 	return ret;
631a3633fe7SShimoda, Yoshihiro }
632a3633fe7SShimoda, Yoshihiro 
633baf588f4SGeert Uytterhoeven static void rspi_receive_init(const struct rspi_data *rspi)
634a3633fe7SShimoda, Yoshihiro {
63597b95c11SGeert Uytterhoeven 	u8 spsr;
6360b2182ddSShimoda, Yoshihiro 
6370b2182ddSShimoda, Yoshihiro 	spsr = rspi_read8(rspi, RSPI_SPSR);
6380b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPRF)
63974da7686SGeert Uytterhoeven 		rspi_read_data(rspi);	/* dummy read */
6400b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_OVRF)
6410b2182ddSShimoda, Yoshihiro 		rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF,
642df900e67SGeert Uytterhoeven 			    RSPI_SPSR);
643a3633fe7SShimoda, Yoshihiro }
644a3633fe7SShimoda, Yoshihiro 
645862d357fSGeert Uytterhoeven static void rspi_rz_receive_init(const struct rspi_data *rspi)
646862d357fSGeert Uytterhoeven {
647862d357fSGeert Uytterhoeven 	rspi_receive_init(rspi);
648862d357fSGeert Uytterhoeven 	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, RSPI_SPBFCR);
649862d357fSGeert Uytterhoeven 	rspi_write8(rspi, 0, RSPI_SPBFCR);
650862d357fSGeert Uytterhoeven }
651862d357fSGeert Uytterhoeven 
652baf588f4SGeert Uytterhoeven static void qspi_receive_init(const struct rspi_data *rspi)
653cb52c673SHiep Cao Minh {
65497b95c11SGeert Uytterhoeven 	u8 spsr;
655cb52c673SHiep Cao Minh 
656cb52c673SHiep Cao Minh 	spsr = rspi_read8(rspi, RSPI_SPSR);
657cb52c673SHiep Cao Minh 	if (spsr & SPSR_SPRF)
65874da7686SGeert Uytterhoeven 		rspi_read_data(rspi);   /* dummy read */
659cb52c673SHiep Cao Minh 	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
660340a15e6SGeert Uytterhoeven 	rspi_write8(rspi, 0, QSPI_SPBFCR);
661cb52c673SHiep Cao Minh }
662cb52c673SHiep Cao Minh 
6632f777ec9SGeert Uytterhoeven static bool __rspi_can_dma(const struct rspi_data *rspi,
6642f777ec9SGeert Uytterhoeven 			   const struct spi_transfer *xfer)
665a3633fe7SShimoda, Yoshihiro {
6662f777ec9SGeert Uytterhoeven 	return xfer->len > rspi->ops->fifo_size;
6672f777ec9SGeert Uytterhoeven }
668a3633fe7SShimoda, Yoshihiro 
6692f777ec9SGeert Uytterhoeven static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi,
6702f777ec9SGeert Uytterhoeven 			 struct spi_transfer *xfer)
6712f777ec9SGeert Uytterhoeven {
6722f777ec9SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
6732f777ec9SGeert Uytterhoeven 
6742f777ec9SGeert Uytterhoeven 	return __rspi_can_dma(rspi, xfer);
675a3633fe7SShimoda, Yoshihiro }
676a3633fe7SShimoda, Yoshihiro 
6774b6fe3edSHiep Cao Minh static int rspi_dma_check_then_transfer(struct rspi_data *rspi,
6784b6fe3edSHiep Cao Minh 					 struct spi_transfer *xfer)
6794b6fe3edSHiep Cao Minh {
6806310372dSHiep Cao Minh 	if (!rspi->master->can_dma || !__rspi_can_dma(rspi, xfer))
6814b6fe3edSHiep Cao Minh 		return -EAGAIN;
6826310372dSHiep Cao Minh 
6836310372dSHiep Cao Minh 	/* rx_buf can be NULL on RSPI on SH in TX-only Mode */
6846310372dSHiep Cao Minh 	return rspi_dma_transfer(rspi, &xfer->tx_sg,
6856310372dSHiep Cao Minh 				xfer->rx_buf ? &xfer->rx_sg : NULL);
6864b6fe3edSHiep Cao Minh }
6874b6fe3edSHiep Cao Minh 
6888b983e90SGeert Uytterhoeven static int rspi_common_transfer(struct rspi_data *rspi,
6898b983e90SGeert Uytterhoeven 				struct spi_transfer *xfer)
6908b983e90SGeert Uytterhoeven {
6918b983e90SGeert Uytterhoeven 	int ret;
6928b983e90SGeert Uytterhoeven 
6934b6fe3edSHiep Cao Minh 	ret = rspi_dma_check_then_transfer(rspi, xfer);
69485912a88SGeert Uytterhoeven 	if (ret != -EAGAIN)
69585912a88SGeert Uytterhoeven 		return ret;
6968b983e90SGeert Uytterhoeven 
6978b983e90SGeert Uytterhoeven 	ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
6988b983e90SGeert Uytterhoeven 	if (ret < 0)
6998b983e90SGeert Uytterhoeven 		return ret;
7008b983e90SGeert Uytterhoeven 
7018b983e90SGeert Uytterhoeven 	/* Wait for the last transmission */
7028b983e90SGeert Uytterhoeven 	rspi_wait_for_tx_empty(rspi);
7038b983e90SGeert Uytterhoeven 
7048b983e90SGeert Uytterhoeven 	return 0;
7058b983e90SGeert Uytterhoeven }
7068b983e90SGeert Uytterhoeven 
7078393fa78SGeert Uytterhoeven static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
7088449fd76SGeert Uytterhoeven 			     struct spi_transfer *xfer)
7098449fd76SGeert Uytterhoeven {
7108393fa78SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
711b42e0359SGeert Uytterhoeven 	u8 spcr;
7128449fd76SGeert Uytterhoeven 
7138449fd76SGeert Uytterhoeven 	spcr = rspi_read8(rspi, RSPI_SPCR);
7146837b8e9SGeert Uytterhoeven 	if (xfer->rx_buf) {
71532c64261SGeert Uytterhoeven 		rspi_receive_init(rspi);
7168449fd76SGeert Uytterhoeven 		spcr &= ~SPCR_TXMD;
71732c64261SGeert Uytterhoeven 	} else {
7188449fd76SGeert Uytterhoeven 		spcr |= SPCR_TXMD;
71932c64261SGeert Uytterhoeven 	}
7208449fd76SGeert Uytterhoeven 	rspi_write8(rspi, spcr, RSPI_SPCR);
7218449fd76SGeert Uytterhoeven 
7228b983e90SGeert Uytterhoeven 	return rspi_common_transfer(rspi, xfer);
7238449fd76SGeert Uytterhoeven }
7248449fd76SGeert Uytterhoeven 
72503e627c5SGeert Uytterhoeven static int rspi_rz_transfer_one(struct spi_master *master,
72603e627c5SGeert Uytterhoeven 				struct spi_device *spi,
727862d357fSGeert Uytterhoeven 				struct spi_transfer *xfer)
728862d357fSGeert Uytterhoeven {
72903e627c5SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
730862d357fSGeert Uytterhoeven 
731862d357fSGeert Uytterhoeven 	rspi_rz_receive_init(rspi);
732862d357fSGeert Uytterhoeven 
7338b983e90SGeert Uytterhoeven 	return rspi_common_transfer(rspi, xfer);
734862d357fSGeert Uytterhoeven }
735862d357fSGeert Uytterhoeven 
736a91bbe7dSHiep Cao Minh static int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx,
7374b6fe3edSHiep Cao Minh 					u8 *rx, unsigned int len)
7384b6fe3edSHiep Cao Minh {
739cb76b1caSGeert Uytterhoeven 	unsigned int i, n;
740cb76b1caSGeert Uytterhoeven 	int ret;
7414b6fe3edSHiep Cao Minh 
7424b6fe3edSHiep Cao Minh 	while (len > 0) {
7434b6fe3edSHiep Cao Minh 		n = qspi_set_send_trigger(rspi, len);
7444b6fe3edSHiep Cao Minh 		qspi_set_receive_trigger(rspi, len);
7454b6fe3edSHiep Cao Minh 		if (n == QSPI_BUFFER_SIZE) {
7465d4db691SGeert Uytterhoeven 			ret = rspi_wait_for_tx_empty(rspi);
7475d4db691SGeert Uytterhoeven 			if (ret < 0) {
7484b6fe3edSHiep Cao Minh 				dev_err(&rspi->master->dev, "transmit timeout\n");
7495d4db691SGeert Uytterhoeven 				return ret;
7504b6fe3edSHiep Cao Minh 			}
7514b6fe3edSHiep Cao Minh 			for (i = 0; i < n; i++)
7524b6fe3edSHiep Cao Minh 				rspi_write_data(rspi, *tx++);
7534b6fe3edSHiep Cao Minh 
7545d4db691SGeert Uytterhoeven 			ret = rspi_wait_for_rx_full(rspi);
7555d4db691SGeert Uytterhoeven 			if (ret < 0) {
7564b6fe3edSHiep Cao Minh 				dev_err(&rspi->master->dev, "receive timeout\n");
7575d4db691SGeert Uytterhoeven 				return ret;
7584b6fe3edSHiep Cao Minh 			}
7594b6fe3edSHiep Cao Minh 			for (i = 0; i < n; i++)
7604b6fe3edSHiep Cao Minh 				*rx++ = rspi_read_data(rspi);
7614b6fe3edSHiep Cao Minh 		} else {
7624b6fe3edSHiep Cao Minh 			ret = rspi_pio_transfer(rspi, tx, rx, n);
7634b6fe3edSHiep Cao Minh 			if (ret < 0)
7644b6fe3edSHiep Cao Minh 				return ret;
7654b6fe3edSHiep Cao Minh 		}
7664b6fe3edSHiep Cao Minh 		len -= n;
7674b6fe3edSHiep Cao Minh 	}
7684b6fe3edSHiep Cao Minh 
7694b6fe3edSHiep Cao Minh 	return 0;
7704b6fe3edSHiep Cao Minh }
7714b6fe3edSHiep Cao Minh 
772340a15e6SGeert Uytterhoeven static int qspi_transfer_out_in(struct rspi_data *rspi,
773340a15e6SGeert Uytterhoeven 				struct spi_transfer *xfer)
774340a15e6SGeert Uytterhoeven {
7754b6fe3edSHiep Cao Minh 	int ret;
7764b6fe3edSHiep Cao Minh 
777340a15e6SGeert Uytterhoeven 	qspi_receive_init(rspi);
778340a15e6SGeert Uytterhoeven 
7794b6fe3edSHiep Cao Minh 	ret = rspi_dma_check_then_transfer(rspi, xfer);
7804b6fe3edSHiep Cao Minh 	if (ret != -EAGAIN)
7814b6fe3edSHiep Cao Minh 		return ret;
7824b6fe3edSHiep Cao Minh 
783cc2e9328SHiep Cao Minh 	return qspi_trigger_transfer_out_in(rspi, xfer->tx_buf,
7844b6fe3edSHiep Cao Minh 					    xfer->rx_buf, xfer->len);
785340a15e6SGeert Uytterhoeven }
786340a15e6SGeert Uytterhoeven 
787880c6d11SGeert Uytterhoeven static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
788880c6d11SGeert Uytterhoeven {
789db300838SArnd Bergmann 	const u8 *tx = xfer->tx_buf;
790db300838SArnd Bergmann 	unsigned int n = xfer->len;
791db300838SArnd Bergmann 	unsigned int i, len;
792880c6d11SGeert Uytterhoeven 	int ret;
793880c6d11SGeert Uytterhoeven 
79485912a88SGeert Uytterhoeven 	if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
79585912a88SGeert Uytterhoeven 		ret = rspi_dma_transfer(rspi, &xfer->tx_sg, NULL);
79685912a88SGeert Uytterhoeven 		if (ret != -EAGAIN)
79785912a88SGeert Uytterhoeven 			return ret;
79885912a88SGeert Uytterhoeven 	}
7994f12b5e5SGeert Uytterhoeven 
800db300838SArnd Bergmann 	while (n > 0) {
801db300838SArnd Bergmann 		len = qspi_set_send_trigger(rspi, n);
802db300838SArnd Bergmann 		if (len == QSPI_BUFFER_SIZE) {
803db300838SArnd Bergmann 			ret = rspi_wait_for_tx_empty(rspi);
804db300838SArnd Bergmann 			if (ret < 0) {
805db300838SArnd Bergmann 				dev_err(&rspi->master->dev, "transmit timeout\n");
806db300838SArnd Bergmann 				return ret;
807db300838SArnd Bergmann 			}
808db300838SArnd Bergmann 			for (i = 0; i < len; i++)
809db300838SArnd Bergmann 				rspi_write_data(rspi, *tx++);
810db300838SArnd Bergmann 		} else {
811ad16d4a8SDongCV 			ret = rspi_pio_transfer(rspi, tx, NULL, len);
812880c6d11SGeert Uytterhoeven 			if (ret < 0)
813880c6d11SGeert Uytterhoeven 				return ret;
814db300838SArnd Bergmann 		}
815db300838SArnd Bergmann 		n -= len;
816db300838SArnd Bergmann 	}
817880c6d11SGeert Uytterhoeven 
818880c6d11SGeert Uytterhoeven 	/* Wait for the last transmission */
8195f684c34SGeert Uytterhoeven 	rspi_wait_for_tx_empty(rspi);
820880c6d11SGeert Uytterhoeven 
821880c6d11SGeert Uytterhoeven 	return 0;
822880c6d11SGeert Uytterhoeven }
823880c6d11SGeert Uytterhoeven 
824880c6d11SGeert Uytterhoeven static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
825880c6d11SGeert Uytterhoeven {
826db300838SArnd Bergmann 	u8 *rx = xfer->rx_buf;
827db300838SArnd Bergmann 	unsigned int n = xfer->len;
828db300838SArnd Bergmann 	unsigned int i, len;
829db300838SArnd Bergmann 	int ret;
830db300838SArnd Bergmann 
83185912a88SGeert Uytterhoeven 	if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
83285912a88SGeert Uytterhoeven 		int ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg);
83385912a88SGeert Uytterhoeven 		if (ret != -EAGAIN)
83485912a88SGeert Uytterhoeven 			return ret;
83585912a88SGeert Uytterhoeven 	}
8364f12b5e5SGeert Uytterhoeven 
837db300838SArnd Bergmann 	while (n > 0) {
838db300838SArnd Bergmann 		len = qspi_set_receive_trigger(rspi, n);
839db300838SArnd Bergmann 		if (len == QSPI_BUFFER_SIZE) {
840db300838SArnd Bergmann 			ret = rspi_wait_for_rx_full(rspi);
841db300838SArnd Bergmann 			if (ret < 0) {
842db300838SArnd Bergmann 				dev_err(&rspi->master->dev, "receive timeout\n");
843db300838SArnd Bergmann 				return ret;
844db300838SArnd Bergmann 			}
845db300838SArnd Bergmann 			for (i = 0; i < len; i++)
846db300838SArnd Bergmann 				*rx++ = rspi_read_data(rspi);
847db300838SArnd Bergmann 		} else {
848ad16d4a8SDongCV 			ret = rspi_pio_transfer(rspi, NULL, rx, len);
849db300838SArnd Bergmann 			if (ret < 0)
850db300838SArnd Bergmann 				return ret;
851db300838SArnd Bergmann 		}
852db300838SArnd Bergmann 		n -= len;
853db300838SArnd Bergmann 	}
854db300838SArnd Bergmann 
855db300838SArnd Bergmann 	return 0;
856880c6d11SGeert Uytterhoeven }
857880c6d11SGeert Uytterhoeven 
858eb557f75SGeert Uytterhoeven static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi,
859eb557f75SGeert Uytterhoeven 			     struct spi_transfer *xfer)
860eb557f75SGeert Uytterhoeven {
861eb557f75SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
862eb557f75SGeert Uytterhoeven 
863ba824d49SGeert Uytterhoeven 	if (spi->mode & SPI_LOOP) {
864ba824d49SGeert Uytterhoeven 		return qspi_transfer_out_in(rspi, xfer);
865b42e0359SGeert Uytterhoeven 	} else if (xfer->tx_nbits > SPI_NBITS_SINGLE) {
866880c6d11SGeert Uytterhoeven 		/* Quad or Dual SPI Write */
867880c6d11SGeert Uytterhoeven 		return qspi_transfer_out(rspi, xfer);
868b42e0359SGeert Uytterhoeven 	} else if (xfer->rx_nbits > SPI_NBITS_SINGLE) {
869880c6d11SGeert Uytterhoeven 		/* Quad or Dual SPI Read */
870880c6d11SGeert Uytterhoeven 		return qspi_transfer_in(rspi, xfer);
871880c6d11SGeert Uytterhoeven 	} else {
872880c6d11SGeert Uytterhoeven 		/* Single SPI Transfer */
873340a15e6SGeert Uytterhoeven 		return qspi_transfer_out_in(rspi, xfer);
874eb557f75SGeert Uytterhoeven 	}
875880c6d11SGeert Uytterhoeven }
876eb557f75SGeert Uytterhoeven 
8770b2182ddSShimoda, Yoshihiro static int rspi_setup(struct spi_device *spi)
8780b2182ddSShimoda, Yoshihiro {
8790b2182ddSShimoda, Yoshihiro 	struct rspi_data *rspi = spi_master_get_devdata(spi->master);
8800b2182ddSShimoda, Yoshihiro 
8810b2182ddSShimoda, Yoshihiro 	rspi->max_speed_hz = spi->max_speed_hz;
8820b2182ddSShimoda, Yoshihiro 
883348e5153SGeert Uytterhoeven 	rspi->spcmd = SPCMD_SSLKP;
884348e5153SGeert Uytterhoeven 	if (spi->mode & SPI_CPOL)
885348e5153SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_CPOL;
886348e5153SGeert Uytterhoeven 	if (spi->mode & SPI_CPHA)
887348e5153SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_CPHA;
888348e5153SGeert Uytterhoeven 
88906a7a3cfSGeert Uytterhoeven 	/* CMOS output mode and MOSI signal from previous transfer */
89006a7a3cfSGeert Uytterhoeven 	rspi->sppcr = 0;
89106a7a3cfSGeert Uytterhoeven 	if (spi->mode & SPI_LOOP)
89206a7a3cfSGeert Uytterhoeven 		rspi->sppcr |= SPPCR_SPLP;
89306a7a3cfSGeert Uytterhoeven 
8945ce0ba88SHiep Cao Minh 	set_config_register(rspi, 8);
8950b2182ddSShimoda, Yoshihiro 
8960b2182ddSShimoda, Yoshihiro 	return 0;
8970b2182ddSShimoda, Yoshihiro }
8980b2182ddSShimoda, Yoshihiro 
899880c6d11SGeert Uytterhoeven static u16 qspi_transfer_mode(const struct spi_transfer *xfer)
900880c6d11SGeert Uytterhoeven {
901880c6d11SGeert Uytterhoeven 	if (xfer->tx_buf)
902880c6d11SGeert Uytterhoeven 		switch (xfer->tx_nbits) {
903880c6d11SGeert Uytterhoeven 		case SPI_NBITS_QUAD:
904880c6d11SGeert Uytterhoeven 			return SPCMD_SPIMOD_QUAD;
905880c6d11SGeert Uytterhoeven 		case SPI_NBITS_DUAL:
906880c6d11SGeert Uytterhoeven 			return SPCMD_SPIMOD_DUAL;
907880c6d11SGeert Uytterhoeven 		default:
908880c6d11SGeert Uytterhoeven 			return 0;
909880c6d11SGeert Uytterhoeven 		}
910880c6d11SGeert Uytterhoeven 	if (xfer->rx_buf)
911880c6d11SGeert Uytterhoeven 		switch (xfer->rx_nbits) {
912880c6d11SGeert Uytterhoeven 		case SPI_NBITS_QUAD:
913880c6d11SGeert Uytterhoeven 			return SPCMD_SPIMOD_QUAD | SPCMD_SPRW;
914880c6d11SGeert Uytterhoeven 		case SPI_NBITS_DUAL:
915880c6d11SGeert Uytterhoeven 			return SPCMD_SPIMOD_DUAL | SPCMD_SPRW;
916880c6d11SGeert Uytterhoeven 		default:
917880c6d11SGeert Uytterhoeven 			return 0;
918880c6d11SGeert Uytterhoeven 		}
919880c6d11SGeert Uytterhoeven 
920880c6d11SGeert Uytterhoeven 	return 0;
921880c6d11SGeert Uytterhoeven }
922880c6d11SGeert Uytterhoeven 
923880c6d11SGeert Uytterhoeven static int qspi_setup_sequencer(struct rspi_data *rspi,
924880c6d11SGeert Uytterhoeven 				const struct spi_message *msg)
925880c6d11SGeert Uytterhoeven {
926880c6d11SGeert Uytterhoeven 	const struct spi_transfer *xfer;
927880c6d11SGeert Uytterhoeven 	unsigned int i = 0, len = 0;
928880c6d11SGeert Uytterhoeven 	u16 current_mode = 0xffff, mode;
929880c6d11SGeert Uytterhoeven 
930880c6d11SGeert Uytterhoeven 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
931880c6d11SGeert Uytterhoeven 		mode = qspi_transfer_mode(xfer);
932880c6d11SGeert Uytterhoeven 		if (mode == current_mode) {
933880c6d11SGeert Uytterhoeven 			len += xfer->len;
934880c6d11SGeert Uytterhoeven 			continue;
935880c6d11SGeert Uytterhoeven 		}
936880c6d11SGeert Uytterhoeven 
937880c6d11SGeert Uytterhoeven 		/* Transfer mode change */
938880c6d11SGeert Uytterhoeven 		if (i) {
939880c6d11SGeert Uytterhoeven 			/* Set transfer data length of previous transfer */
940880c6d11SGeert Uytterhoeven 			rspi_write32(rspi, len, QSPI_SPBMUL(i - 1));
941880c6d11SGeert Uytterhoeven 		}
942880c6d11SGeert Uytterhoeven 
943880c6d11SGeert Uytterhoeven 		if (i >= QSPI_NUM_SPCMD) {
944880c6d11SGeert Uytterhoeven 			dev_err(&msg->spi->dev,
945880c6d11SGeert Uytterhoeven 				"Too many different transfer modes");
946880c6d11SGeert Uytterhoeven 			return -EINVAL;
947880c6d11SGeert Uytterhoeven 		}
948880c6d11SGeert Uytterhoeven 
949880c6d11SGeert Uytterhoeven 		/* Program transfer mode for this transfer */
950880c6d11SGeert Uytterhoeven 		rspi_write16(rspi, rspi->spcmd | mode, RSPI_SPCMD(i));
951880c6d11SGeert Uytterhoeven 		current_mode = mode;
952880c6d11SGeert Uytterhoeven 		len = xfer->len;
953880c6d11SGeert Uytterhoeven 		i++;
954880c6d11SGeert Uytterhoeven 	}
955880c6d11SGeert Uytterhoeven 	if (i) {
956880c6d11SGeert Uytterhoeven 		/* Set final transfer data length and sequence length */
957880c6d11SGeert Uytterhoeven 		rspi_write32(rspi, len, QSPI_SPBMUL(i - 1));
958880c6d11SGeert Uytterhoeven 		rspi_write8(rspi, i - 1, RSPI_SPSCR);
959880c6d11SGeert Uytterhoeven 	}
960880c6d11SGeert Uytterhoeven 
961880c6d11SGeert Uytterhoeven 	return 0;
962880c6d11SGeert Uytterhoeven }
963880c6d11SGeert Uytterhoeven 
96479d23495SGeert Uytterhoeven static int rspi_prepare_message(struct spi_master *master,
965880c6d11SGeert Uytterhoeven 				struct spi_message *msg)
96679d23495SGeert Uytterhoeven {
96779d23495SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
968880c6d11SGeert Uytterhoeven 	int ret;
9690b2182ddSShimoda, Yoshihiro 
970880c6d11SGeert Uytterhoeven 	if (msg->spi->mode &
971880c6d11SGeert Uytterhoeven 	    (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)) {
972880c6d11SGeert Uytterhoeven 		/* Setup sequencer for messages with multiple transfer modes */
973880c6d11SGeert Uytterhoeven 		ret = qspi_setup_sequencer(rspi, msg);
974880c6d11SGeert Uytterhoeven 		if (ret < 0)
975880c6d11SGeert Uytterhoeven 			return ret;
976880c6d11SGeert Uytterhoeven 	}
977880c6d11SGeert Uytterhoeven 
978880c6d11SGeert Uytterhoeven 	/* Enable SPI function in master mode */
97979d23495SGeert Uytterhoeven 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
9800b2182ddSShimoda, Yoshihiro 	return 0;
9810b2182ddSShimoda, Yoshihiro }
9820b2182ddSShimoda, Yoshihiro 
98379d23495SGeert Uytterhoeven static int rspi_unprepare_message(struct spi_master *master,
984880c6d11SGeert Uytterhoeven 				  struct spi_message *msg)
9850b2182ddSShimoda, Yoshihiro {
98679d23495SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
98779d23495SGeert Uytterhoeven 
988880c6d11SGeert Uytterhoeven 	/* Disable SPI function */
98979d23495SGeert Uytterhoeven 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
990880c6d11SGeert Uytterhoeven 
991880c6d11SGeert Uytterhoeven 	/* Reset sequencer for Single SPI Transfers */
992880c6d11SGeert Uytterhoeven 	rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
993880c6d11SGeert Uytterhoeven 	rspi_write8(rspi, 0, RSPI_SPSCR);
99479d23495SGeert Uytterhoeven 	return 0;
9950b2182ddSShimoda, Yoshihiro }
9960b2182ddSShimoda, Yoshihiro 
99793722206SGeert Uytterhoeven static irqreturn_t rspi_irq_mux(int irq, void *_sr)
9980b2182ddSShimoda, Yoshihiro {
999c132f094SGeert Uytterhoeven 	struct rspi_data *rspi = _sr;
100097b95c11SGeert Uytterhoeven 	u8 spsr;
10010b2182ddSShimoda, Yoshihiro 	irqreturn_t ret = IRQ_NONE;
100297b95c11SGeert Uytterhoeven 	u8 disable_irq = 0;
10030b2182ddSShimoda, Yoshihiro 
10040b2182ddSShimoda, Yoshihiro 	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
10050b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPRF)
10060b2182ddSShimoda, Yoshihiro 		disable_irq |= SPCR_SPRIE;
10070b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPTEF)
10080b2182ddSShimoda, Yoshihiro 		disable_irq |= SPCR_SPTIE;
10090b2182ddSShimoda, Yoshihiro 
10100b2182ddSShimoda, Yoshihiro 	if (disable_irq) {
10110b2182ddSShimoda, Yoshihiro 		ret = IRQ_HANDLED;
10120b2182ddSShimoda, Yoshihiro 		rspi_disable_irq(rspi, disable_irq);
10130b2182ddSShimoda, Yoshihiro 		wake_up(&rspi->wait);
10140b2182ddSShimoda, Yoshihiro 	}
10150b2182ddSShimoda, Yoshihiro 
10160b2182ddSShimoda, Yoshihiro 	return ret;
10170b2182ddSShimoda, Yoshihiro }
10180b2182ddSShimoda, Yoshihiro 
101993722206SGeert Uytterhoeven static irqreturn_t rspi_irq_rx(int irq, void *_sr)
102093722206SGeert Uytterhoeven {
102193722206SGeert Uytterhoeven 	struct rspi_data *rspi = _sr;
102293722206SGeert Uytterhoeven 	u8 spsr;
102393722206SGeert Uytterhoeven 
102493722206SGeert Uytterhoeven 	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
102593722206SGeert Uytterhoeven 	if (spsr & SPSR_SPRF) {
102693722206SGeert Uytterhoeven 		rspi_disable_irq(rspi, SPCR_SPRIE);
102793722206SGeert Uytterhoeven 		wake_up(&rspi->wait);
102893722206SGeert Uytterhoeven 		return IRQ_HANDLED;
102993722206SGeert Uytterhoeven 	}
103093722206SGeert Uytterhoeven 
103193722206SGeert Uytterhoeven 	return 0;
103293722206SGeert Uytterhoeven }
103393722206SGeert Uytterhoeven 
103493722206SGeert Uytterhoeven static irqreturn_t rspi_irq_tx(int irq, void *_sr)
103593722206SGeert Uytterhoeven {
103693722206SGeert Uytterhoeven 	struct rspi_data *rspi = _sr;
103793722206SGeert Uytterhoeven 	u8 spsr;
103893722206SGeert Uytterhoeven 
103993722206SGeert Uytterhoeven 	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
104093722206SGeert Uytterhoeven 	if (spsr & SPSR_SPTEF) {
104193722206SGeert Uytterhoeven 		rspi_disable_irq(rspi, SPCR_SPTIE);
104293722206SGeert Uytterhoeven 		wake_up(&rspi->wait);
104393722206SGeert Uytterhoeven 		return IRQ_HANDLED;
104493722206SGeert Uytterhoeven 	}
104593722206SGeert Uytterhoeven 
104693722206SGeert Uytterhoeven 	return 0;
104793722206SGeert Uytterhoeven }
104893722206SGeert Uytterhoeven 
104965bf2205SGeert Uytterhoeven static struct dma_chan *rspi_request_dma_chan(struct device *dev,
105065bf2205SGeert Uytterhoeven 					      enum dma_transfer_direction dir,
105165bf2205SGeert Uytterhoeven 					      unsigned int id,
105265bf2205SGeert Uytterhoeven 					      dma_addr_t port_addr)
105365bf2205SGeert Uytterhoeven {
105465bf2205SGeert Uytterhoeven 	dma_cap_mask_t mask;
105565bf2205SGeert Uytterhoeven 	struct dma_chan *chan;
105665bf2205SGeert Uytterhoeven 	struct dma_slave_config cfg;
105765bf2205SGeert Uytterhoeven 	int ret;
105865bf2205SGeert Uytterhoeven 
105965bf2205SGeert Uytterhoeven 	dma_cap_zero(mask);
106065bf2205SGeert Uytterhoeven 	dma_cap_set(DMA_SLAVE, mask);
106165bf2205SGeert Uytterhoeven 
1062e825b8ddSGeert Uytterhoeven 	chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
1063e825b8ddSGeert Uytterhoeven 				(void *)(unsigned long)id, dev,
1064e825b8ddSGeert Uytterhoeven 				dir == DMA_MEM_TO_DEV ? "tx" : "rx");
106565bf2205SGeert Uytterhoeven 	if (!chan) {
1066e825b8ddSGeert Uytterhoeven 		dev_warn(dev, "dma_request_slave_channel_compat failed\n");
106765bf2205SGeert Uytterhoeven 		return NULL;
106865bf2205SGeert Uytterhoeven 	}
106965bf2205SGeert Uytterhoeven 
107065bf2205SGeert Uytterhoeven 	memset(&cfg, 0, sizeof(cfg));
107165bf2205SGeert Uytterhoeven 	cfg.direction = dir;
1072a30b95a7SGeert Uytterhoeven 	if (dir == DMA_MEM_TO_DEV) {
107365bf2205SGeert Uytterhoeven 		cfg.dst_addr = port_addr;
1074a30b95a7SGeert Uytterhoeven 		cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
1075a30b95a7SGeert Uytterhoeven 	} else {
107665bf2205SGeert Uytterhoeven 		cfg.src_addr = port_addr;
1077a30b95a7SGeert Uytterhoeven 		cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
1078a30b95a7SGeert Uytterhoeven 	}
107965bf2205SGeert Uytterhoeven 
108065bf2205SGeert Uytterhoeven 	ret = dmaengine_slave_config(chan, &cfg);
108165bf2205SGeert Uytterhoeven 	if (ret) {
108265bf2205SGeert Uytterhoeven 		dev_warn(dev, "dmaengine_slave_config failed %d\n", ret);
108365bf2205SGeert Uytterhoeven 		dma_release_channel(chan);
108465bf2205SGeert Uytterhoeven 		return NULL;
108565bf2205SGeert Uytterhoeven 	}
108665bf2205SGeert Uytterhoeven 
108765bf2205SGeert Uytterhoeven 	return chan;
108865bf2205SGeert Uytterhoeven }
108965bf2205SGeert Uytterhoeven 
10902f777ec9SGeert Uytterhoeven static int rspi_request_dma(struct device *dev, struct spi_master *master,
1091fcdc49aeSGeert Uytterhoeven 			    const struct resource *res)
1092a3633fe7SShimoda, Yoshihiro {
1093fcdc49aeSGeert Uytterhoeven 	const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev);
1094e825b8ddSGeert Uytterhoeven 	unsigned int dma_tx_id, dma_rx_id;
1095a3633fe7SShimoda, Yoshihiro 
1096e825b8ddSGeert Uytterhoeven 	if (dev->of_node) {
1097e825b8ddSGeert Uytterhoeven 		/* In the OF case we will get the slave IDs from the DT */
1098e825b8ddSGeert Uytterhoeven 		dma_tx_id = 0;
1099e825b8ddSGeert Uytterhoeven 		dma_rx_id = 0;
1100e825b8ddSGeert Uytterhoeven 	} else if (rspi_pd && rspi_pd->dma_tx_id && rspi_pd->dma_rx_id) {
1101e825b8ddSGeert Uytterhoeven 		dma_tx_id = rspi_pd->dma_tx_id;
1102e825b8ddSGeert Uytterhoeven 		dma_rx_id = rspi_pd->dma_rx_id;
1103e825b8ddSGeert Uytterhoeven 	} else {
1104e825b8ddSGeert Uytterhoeven 		/* The driver assumes no error. */
1105e825b8ddSGeert Uytterhoeven 		return 0;
1106e825b8ddSGeert Uytterhoeven 	}
1107a3633fe7SShimoda, Yoshihiro 
1108e825b8ddSGeert Uytterhoeven 	master->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, dma_tx_id,
110965bf2205SGeert Uytterhoeven 					       res->start + RSPI_SPDR);
1110e825b8ddSGeert Uytterhoeven 	if (!master->dma_tx)
111165bf2205SGeert Uytterhoeven 		return -ENODEV;
111265bf2205SGeert Uytterhoeven 
1113e825b8ddSGeert Uytterhoeven 	master->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, dma_rx_id,
111465bf2205SGeert Uytterhoeven 					       res->start + RSPI_SPDR);
1115e825b8ddSGeert Uytterhoeven 	if (!master->dma_rx) {
1116e825b8ddSGeert Uytterhoeven 		dma_release_channel(master->dma_tx);
1117e825b8ddSGeert Uytterhoeven 		master->dma_tx = NULL;
111865bf2205SGeert Uytterhoeven 		return -ENODEV;
1119a3633fe7SShimoda, Yoshihiro 	}
1120a3633fe7SShimoda, Yoshihiro 
11212f777ec9SGeert Uytterhoeven 	master->can_dma = rspi_can_dma;
11225f338d0cSGeert Uytterhoeven 	dev_info(dev, "DMA available");
11230243c536SShimoda, Yoshihiro 	return 0;
11240243c536SShimoda, Yoshihiro }
11250243c536SShimoda, Yoshihiro 
1126afcc98deSGeert Uytterhoeven static void rspi_release_dma(struct spi_master *master)
1127a3633fe7SShimoda, Yoshihiro {
1128afcc98deSGeert Uytterhoeven 	if (master->dma_tx)
1129afcc98deSGeert Uytterhoeven 		dma_release_channel(master->dma_tx);
1130afcc98deSGeert Uytterhoeven 	if (master->dma_rx)
1131afcc98deSGeert Uytterhoeven 		dma_release_channel(master->dma_rx);
1132a3633fe7SShimoda, Yoshihiro }
1133a3633fe7SShimoda, Yoshihiro 
1134fd4a319bSGrant Likely static int rspi_remove(struct platform_device *pdev)
11350b2182ddSShimoda, Yoshihiro {
11365ffbe2d9SLaurent Pinchart 	struct rspi_data *rspi = platform_get_drvdata(pdev);
11370b2182ddSShimoda, Yoshihiro 
1138afcc98deSGeert Uytterhoeven 	rspi_release_dma(rspi->master);
1139490c9774SGeert Uytterhoeven 	pm_runtime_disable(&pdev->dev);
11400b2182ddSShimoda, Yoshihiro 
11410b2182ddSShimoda, Yoshihiro 	return 0;
11420b2182ddSShimoda, Yoshihiro }
11430b2182ddSShimoda, Yoshihiro 
1144426ef76dSGeert Uytterhoeven static const struct spi_ops rspi_ops = {
1145426ef76dSGeert Uytterhoeven 	.set_config_register =	rspi_set_config_register,
1146426ef76dSGeert Uytterhoeven 	.transfer_one =		rspi_transfer_one,
1147880c6d11SGeert Uytterhoeven 	.mode_bits =		SPI_CPHA | SPI_CPOL | SPI_LOOP,
1148b42e0359SGeert Uytterhoeven 	.flags =		SPI_MASTER_MUST_TX,
11492f777ec9SGeert Uytterhoeven 	.fifo_size =		8,
1150426ef76dSGeert Uytterhoeven };
1151426ef76dSGeert Uytterhoeven 
1152426ef76dSGeert Uytterhoeven static const struct spi_ops rspi_rz_ops = {
1153426ef76dSGeert Uytterhoeven 	.set_config_register =	rspi_rz_set_config_register,
1154426ef76dSGeert Uytterhoeven 	.transfer_one =		rspi_rz_transfer_one,
1155880c6d11SGeert Uytterhoeven 	.mode_bits =		SPI_CPHA | SPI_CPOL | SPI_LOOP,
1156b42e0359SGeert Uytterhoeven 	.flags =		SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX,
11572f777ec9SGeert Uytterhoeven 	.fifo_size =		8,	/* 8 for TX, 32 for RX */
1158426ef76dSGeert Uytterhoeven };
1159426ef76dSGeert Uytterhoeven 
1160426ef76dSGeert Uytterhoeven static const struct spi_ops qspi_ops = {
1161426ef76dSGeert Uytterhoeven 	.set_config_register =	qspi_set_config_register,
1162426ef76dSGeert Uytterhoeven 	.transfer_one =		qspi_transfer_one,
1163880c6d11SGeert Uytterhoeven 	.mode_bits =		SPI_CPHA | SPI_CPOL | SPI_LOOP |
1164880c6d11SGeert Uytterhoeven 				SPI_TX_DUAL | SPI_TX_QUAD |
1165880c6d11SGeert Uytterhoeven 				SPI_RX_DUAL | SPI_RX_QUAD,
1166b42e0359SGeert Uytterhoeven 	.flags =		SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX,
11672f777ec9SGeert Uytterhoeven 	.fifo_size =		32,
1168426ef76dSGeert Uytterhoeven };
1169426ef76dSGeert Uytterhoeven 
1170426ef76dSGeert Uytterhoeven #ifdef CONFIG_OF
1171426ef76dSGeert Uytterhoeven static const struct of_device_id rspi_of_match[] = {
1172426ef76dSGeert Uytterhoeven 	/* RSPI on legacy SH */
1173426ef76dSGeert Uytterhoeven 	{ .compatible = "renesas,rspi", .data = &rspi_ops },
1174426ef76dSGeert Uytterhoeven 	/* RSPI on RZ/A1H */
1175426ef76dSGeert Uytterhoeven 	{ .compatible = "renesas,rspi-rz", .data = &rspi_rz_ops },
1176426ef76dSGeert Uytterhoeven 	/* QSPI on R-Car Gen2 */
1177426ef76dSGeert Uytterhoeven 	{ .compatible = "renesas,qspi", .data = &qspi_ops },
1178426ef76dSGeert Uytterhoeven 	{ /* sentinel */ }
1179426ef76dSGeert Uytterhoeven };
1180426ef76dSGeert Uytterhoeven 
1181426ef76dSGeert Uytterhoeven MODULE_DEVICE_TABLE(of, rspi_of_match);
1182426ef76dSGeert Uytterhoeven 
1183426ef76dSGeert Uytterhoeven static int rspi_parse_dt(struct device *dev, struct spi_master *master)
1184426ef76dSGeert Uytterhoeven {
1185426ef76dSGeert Uytterhoeven 	u32 num_cs;
1186426ef76dSGeert Uytterhoeven 	int error;
1187426ef76dSGeert Uytterhoeven 
1188426ef76dSGeert Uytterhoeven 	/* Parse DT properties */
1189426ef76dSGeert Uytterhoeven 	error = of_property_read_u32(dev->of_node, "num-cs", &num_cs);
1190426ef76dSGeert Uytterhoeven 	if (error) {
1191426ef76dSGeert Uytterhoeven 		dev_err(dev, "of_property_read_u32 num-cs failed %d\n", error);
1192426ef76dSGeert Uytterhoeven 		return error;
1193426ef76dSGeert Uytterhoeven 	}
1194426ef76dSGeert Uytterhoeven 
1195426ef76dSGeert Uytterhoeven 	master->num_chipselect = num_cs;
1196426ef76dSGeert Uytterhoeven 	return 0;
1197426ef76dSGeert Uytterhoeven }
1198426ef76dSGeert Uytterhoeven #else
119964b67defSShimoda, Yoshihiro #define rspi_of_match	NULL
1200426ef76dSGeert Uytterhoeven static inline int rspi_parse_dt(struct device *dev, struct spi_master *master)
1201426ef76dSGeert Uytterhoeven {
1202426ef76dSGeert Uytterhoeven 	return -EINVAL;
1203426ef76dSGeert Uytterhoeven }
1204426ef76dSGeert Uytterhoeven #endif /* CONFIG_OF */
1205426ef76dSGeert Uytterhoeven 
120693722206SGeert Uytterhoeven static int rspi_request_irq(struct device *dev, unsigned int irq,
120793722206SGeert Uytterhoeven 			    irq_handler_t handler, const char *suffix,
120893722206SGeert Uytterhoeven 			    void *dev_id)
120993722206SGeert Uytterhoeven {
121043937455SGeert Uytterhoeven 	const char *name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s",
121143937455SGeert Uytterhoeven 					  dev_name(dev), suffix);
121293722206SGeert Uytterhoeven 	if (!name)
121393722206SGeert Uytterhoeven 		return -ENOMEM;
121443937455SGeert Uytterhoeven 
121593722206SGeert Uytterhoeven 	return devm_request_irq(dev, irq, handler, 0, name, dev_id);
121693722206SGeert Uytterhoeven }
121793722206SGeert Uytterhoeven 
1218fd4a319bSGrant Likely static int rspi_probe(struct platform_device *pdev)
12190b2182ddSShimoda, Yoshihiro {
12200b2182ddSShimoda, Yoshihiro 	struct resource *res;
12210b2182ddSShimoda, Yoshihiro 	struct spi_master *master;
12220b2182ddSShimoda, Yoshihiro 	struct rspi_data *rspi;
122393722206SGeert Uytterhoeven 	int ret;
1224426ef76dSGeert Uytterhoeven 	const struct rspi_plat_data *rspi_pd;
12255ce0ba88SHiep Cao Minh 	const struct spi_ops *ops;
12260b2182ddSShimoda, Yoshihiro 
12270b2182ddSShimoda, Yoshihiro 	master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data));
1228ffcfae38SGeert Uytterhoeven 	if (master == NULL)
12290b2182ddSShimoda, Yoshihiro 		return -ENOMEM;
12300b2182ddSShimoda, Yoshihiro 
1231219a7bc5SGeert Uytterhoeven 	ops = of_device_get_match_data(&pdev->dev);
1232219a7bc5SGeert Uytterhoeven 	if (ops) {
1233426ef76dSGeert Uytterhoeven 		ret = rspi_parse_dt(&pdev->dev, master);
1234426ef76dSGeert Uytterhoeven 		if (ret)
1235426ef76dSGeert Uytterhoeven 			goto error1;
1236426ef76dSGeert Uytterhoeven 	} else {
1237426ef76dSGeert Uytterhoeven 		ops = (struct spi_ops *)pdev->id_entry->driver_data;
1238426ef76dSGeert Uytterhoeven 		rspi_pd = dev_get_platdata(&pdev->dev);
1239426ef76dSGeert Uytterhoeven 		if (rspi_pd && rspi_pd->num_chipselect)
1240426ef76dSGeert Uytterhoeven 			master->num_chipselect = rspi_pd->num_chipselect;
1241426ef76dSGeert Uytterhoeven 		else
1242426ef76dSGeert Uytterhoeven 			master->num_chipselect = 2; /* default */
1243d64b4726SGeert Uytterhoeven 	}
1244426ef76dSGeert Uytterhoeven 
1245426ef76dSGeert Uytterhoeven 	/* ops parameter check */
1246426ef76dSGeert Uytterhoeven 	if (!ops->set_config_register) {
1247426ef76dSGeert Uytterhoeven 		dev_err(&pdev->dev, "there is no set_config_register\n");
1248426ef76dSGeert Uytterhoeven 		ret = -ENODEV;
1249426ef76dSGeert Uytterhoeven 		goto error1;
1250426ef76dSGeert Uytterhoeven 	}
1251426ef76dSGeert Uytterhoeven 
12520b2182ddSShimoda, Yoshihiro 	rspi = spi_master_get_devdata(master);
125324b5a82cSJingoo Han 	platform_set_drvdata(pdev, rspi);
12545ce0ba88SHiep Cao Minh 	rspi->ops = ops;
12550b2182ddSShimoda, Yoshihiro 	rspi->master = master;
12565d79e9acSLaurent Pinchart 
12575d79e9acSLaurent Pinchart 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
12585d79e9acSLaurent Pinchart 	rspi->addr = devm_ioremap_resource(&pdev->dev, res);
12595d79e9acSLaurent Pinchart 	if (IS_ERR(rspi->addr)) {
12605d79e9acSLaurent Pinchart 		ret = PTR_ERR(rspi->addr);
12610b2182ddSShimoda, Yoshihiro 		goto error1;
12620b2182ddSShimoda, Yoshihiro 	}
12630b2182ddSShimoda, Yoshihiro 
126429f397b7SGeert Uytterhoeven 	rspi->clk = devm_clk_get(&pdev->dev, NULL);
12650b2182ddSShimoda, Yoshihiro 	if (IS_ERR(rspi->clk)) {
12660b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "cannot get clock\n");
12670b2182ddSShimoda, Yoshihiro 		ret = PTR_ERR(rspi->clk);
12685d79e9acSLaurent Pinchart 		goto error1;
12690b2182ddSShimoda, Yoshihiro 	}
127017fe0d9aSGeert Uytterhoeven 
1271490c9774SGeert Uytterhoeven 	pm_runtime_enable(&pdev->dev);
12720b2182ddSShimoda, Yoshihiro 
12730b2182ddSShimoda, Yoshihiro 	init_waitqueue_head(&rspi->wait);
12740b2182ddSShimoda, Yoshihiro 
12750b2182ddSShimoda, Yoshihiro 	master->bus_num = pdev->id;
12760b2182ddSShimoda, Yoshihiro 	master->setup = rspi_setup;
1277490c9774SGeert Uytterhoeven 	master->auto_runtime_pm = true;
1278eb557f75SGeert Uytterhoeven 	master->transfer_one = ops->transfer_one;
127979d23495SGeert Uytterhoeven 	master->prepare_message = rspi_prepare_message;
128079d23495SGeert Uytterhoeven 	master->unprepare_message = rspi_unprepare_message;
1281880c6d11SGeert Uytterhoeven 	master->mode_bits = ops->mode_bits;
1282b42e0359SGeert Uytterhoeven 	master->flags = ops->flags;
1283426ef76dSGeert Uytterhoeven 	master->dev.of_node = pdev->dev.of_node;
12840b2182ddSShimoda, Yoshihiro 
128593722206SGeert Uytterhoeven 	ret = platform_get_irq_byname(pdev, "rx");
128693722206SGeert Uytterhoeven 	if (ret < 0) {
128793722206SGeert Uytterhoeven 		ret = platform_get_irq_byname(pdev, "mux");
128893722206SGeert Uytterhoeven 		if (ret < 0)
128993722206SGeert Uytterhoeven 			ret = platform_get_irq(pdev, 0);
129093722206SGeert Uytterhoeven 		if (ret >= 0)
129193722206SGeert Uytterhoeven 			rspi->rx_irq = rspi->tx_irq = ret;
129293722206SGeert Uytterhoeven 	} else {
129393722206SGeert Uytterhoeven 		rspi->rx_irq = ret;
129493722206SGeert Uytterhoeven 		ret = platform_get_irq_byname(pdev, "tx");
129593722206SGeert Uytterhoeven 		if (ret >= 0)
129693722206SGeert Uytterhoeven 			rspi->tx_irq = ret;
129793722206SGeert Uytterhoeven 	}
129893722206SGeert Uytterhoeven 	if (ret < 0) {
129993722206SGeert Uytterhoeven 		dev_err(&pdev->dev, "platform_get_irq error\n");
130093722206SGeert Uytterhoeven 		goto error2;
130193722206SGeert Uytterhoeven 	}
130293722206SGeert Uytterhoeven 
130393722206SGeert Uytterhoeven 	if (rspi->rx_irq == rspi->tx_irq) {
130493722206SGeert Uytterhoeven 		/* Single multiplexed interrupt */
130593722206SGeert Uytterhoeven 		ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_mux,
130693722206SGeert Uytterhoeven 				       "mux", rspi);
130793722206SGeert Uytterhoeven 	} else {
130893722206SGeert Uytterhoeven 		/* Multi-interrupt mode, only SPRI and SPTI are used */
130993722206SGeert Uytterhoeven 		ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_rx,
131093722206SGeert Uytterhoeven 				       "rx", rspi);
131193722206SGeert Uytterhoeven 		if (!ret)
131293722206SGeert Uytterhoeven 			ret = rspi_request_irq(&pdev->dev, rspi->tx_irq,
131393722206SGeert Uytterhoeven 					       rspi_irq_tx, "tx", rspi);
131493722206SGeert Uytterhoeven 	}
13150b2182ddSShimoda, Yoshihiro 	if (ret < 0) {
13160b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "request_irq error\n");
1317fcb4ed74SGeert Uytterhoeven 		goto error2;
13180b2182ddSShimoda, Yoshihiro 	}
13190b2182ddSShimoda, Yoshihiro 
13202f777ec9SGeert Uytterhoeven 	ret = rspi_request_dma(&pdev->dev, master, res);
132127e105a6SGeert Uytterhoeven 	if (ret < 0)
132227e105a6SGeert Uytterhoeven 		dev_warn(&pdev->dev, "DMA not available, using PIO\n");
1323a3633fe7SShimoda, Yoshihiro 
13249e03d05eSJingoo Han 	ret = devm_spi_register_master(&pdev->dev, master);
13250b2182ddSShimoda, Yoshihiro 	if (ret < 0) {
13260b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "spi_register_master error.\n");
1327fcb4ed74SGeert Uytterhoeven 		goto error3;
13280b2182ddSShimoda, Yoshihiro 	}
13290b2182ddSShimoda, Yoshihiro 
13300b2182ddSShimoda, Yoshihiro 	dev_info(&pdev->dev, "probed\n");
13310b2182ddSShimoda, Yoshihiro 
13320b2182ddSShimoda, Yoshihiro 	return 0;
13330b2182ddSShimoda, Yoshihiro 
1334fcb4ed74SGeert Uytterhoeven error3:
1335afcc98deSGeert Uytterhoeven 	rspi_release_dma(master);
1336fcb4ed74SGeert Uytterhoeven error2:
1337490c9774SGeert Uytterhoeven 	pm_runtime_disable(&pdev->dev);
13380b2182ddSShimoda, Yoshihiro error1:
13390b2182ddSShimoda, Yoshihiro 	spi_master_put(master);
13400b2182ddSShimoda, Yoshihiro 
13410b2182ddSShimoda, Yoshihiro 	return ret;
13420b2182ddSShimoda, Yoshihiro }
13430b2182ddSShimoda, Yoshihiro 
13448634dafaSKrzysztof Kozlowski static const struct platform_device_id spi_driver_ids[] = {
13455ce0ba88SHiep Cao Minh 	{ "rspi",	(kernel_ulong_t)&rspi_ops },
1346862d357fSGeert Uytterhoeven 	{ "rspi-rz",	(kernel_ulong_t)&rspi_rz_ops },
13475ce0ba88SHiep Cao Minh 	{ "qspi",	(kernel_ulong_t)&qspi_ops },
13485ce0ba88SHiep Cao Minh 	{},
13495ce0ba88SHiep Cao Minh };
13505ce0ba88SHiep Cao Minh 
13515ce0ba88SHiep Cao Minh MODULE_DEVICE_TABLE(platform, spi_driver_ids);
13525ce0ba88SHiep Cao Minh 
1353c1ca59c2SGeert Uytterhoeven #ifdef CONFIG_PM_SLEEP
1354c1ca59c2SGeert Uytterhoeven static int rspi_suspend(struct device *dev)
1355c1ca59c2SGeert Uytterhoeven {
1356c1ca59c2SGeert Uytterhoeven 	struct platform_device *pdev = to_platform_device(dev);
1357c1ca59c2SGeert Uytterhoeven 	struct rspi_data *rspi = platform_get_drvdata(pdev);
1358c1ca59c2SGeert Uytterhoeven 
1359c1ca59c2SGeert Uytterhoeven 	return spi_master_suspend(rspi->master);
1360c1ca59c2SGeert Uytterhoeven }
1361c1ca59c2SGeert Uytterhoeven 
1362c1ca59c2SGeert Uytterhoeven static int rspi_resume(struct device *dev)
1363c1ca59c2SGeert Uytterhoeven {
1364c1ca59c2SGeert Uytterhoeven 	struct platform_device *pdev = to_platform_device(dev);
1365c1ca59c2SGeert Uytterhoeven 	struct rspi_data *rspi = platform_get_drvdata(pdev);
1366c1ca59c2SGeert Uytterhoeven 
1367c1ca59c2SGeert Uytterhoeven 	return spi_master_resume(rspi->master);
1368c1ca59c2SGeert Uytterhoeven }
1369c1ca59c2SGeert Uytterhoeven 
1370c1ca59c2SGeert Uytterhoeven static SIMPLE_DEV_PM_OPS(rspi_pm_ops, rspi_suspend, rspi_resume);
1371c1ca59c2SGeert Uytterhoeven #define DEV_PM_OPS	&rspi_pm_ops
1372c1ca59c2SGeert Uytterhoeven #else
1373c1ca59c2SGeert Uytterhoeven #define DEV_PM_OPS	NULL
1374c1ca59c2SGeert Uytterhoeven #endif /* CONFIG_PM_SLEEP */
1375c1ca59c2SGeert Uytterhoeven 
13760b2182ddSShimoda, Yoshihiro static struct platform_driver rspi_driver = {
13770b2182ddSShimoda, Yoshihiro 	.probe =	rspi_probe,
1378fd4a319bSGrant Likely 	.remove =	rspi_remove,
13795ce0ba88SHiep Cao Minh 	.id_table =	spi_driver_ids,
13800b2182ddSShimoda, Yoshihiro 	.driver		= {
13815ce0ba88SHiep Cao Minh 		.name = "renesas_spi",
1382c1ca59c2SGeert Uytterhoeven 		.pm = DEV_PM_OPS,
1383426ef76dSGeert Uytterhoeven 		.of_match_table = of_match_ptr(rspi_of_match),
13840b2182ddSShimoda, Yoshihiro 	},
13850b2182ddSShimoda, Yoshihiro };
13860b2182ddSShimoda, Yoshihiro module_platform_driver(rspi_driver);
13870b2182ddSShimoda, Yoshihiro 
13880b2182ddSShimoda, Yoshihiro MODULE_DESCRIPTION("Renesas RSPI bus driver");
13890b2182ddSShimoda, Yoshihiro MODULE_LICENSE("GPL v2");
13900b2182ddSShimoda, Yoshihiro MODULE_AUTHOR("Yoshihiro Shimoda");
13910b2182ddSShimoda, Yoshihiro MODULE_ALIAS("platform:rspi");
1392