xref: /openbmc/linux/drivers/spi/spi-rspi.c (revision ffcfae38)
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 
380880c6d11SGeert Uytterhoeven 	/* Enables SPI function in master mode */
3815ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPCR_SPE | 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,
538c52fb6d6SGeert Uytterhoeven 					rx->sgl, rx->nents, DMA_FROM_DEVICE,
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,
5583819bc87SGeert Uytterhoeven 					tx->sgl, tx->nents, DMA_TO_DEVICE,
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 {
811db300838SArnd Bergmann 			ret = rspi_pio_transfer(rspi, tx, NULL, n);
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 {
848db300838SArnd Bergmann 			ret = rspi_pio_transfer(rspi, NULL, rx, n);
849db300838SArnd Bergmann 			if (ret < 0)
850db300838SArnd Bergmann 				return ret;
851db300838SArnd Bergmann 			*rx++ = ret;
852db300838SArnd Bergmann 		}
853db300838SArnd Bergmann 		n -= len;
854db300838SArnd Bergmann 	}
855db300838SArnd Bergmann 
856db300838SArnd Bergmann 	return 0;
857880c6d11SGeert Uytterhoeven }
858880c6d11SGeert Uytterhoeven 
859eb557f75SGeert Uytterhoeven static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi,
860eb557f75SGeert Uytterhoeven 			     struct spi_transfer *xfer)
861eb557f75SGeert Uytterhoeven {
862eb557f75SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
863eb557f75SGeert Uytterhoeven 
864ba824d49SGeert Uytterhoeven 	if (spi->mode & SPI_LOOP) {
865ba824d49SGeert Uytterhoeven 		return qspi_transfer_out_in(rspi, xfer);
866b42e0359SGeert Uytterhoeven 	} else if (xfer->tx_nbits > SPI_NBITS_SINGLE) {
867880c6d11SGeert Uytterhoeven 		/* Quad or Dual SPI Write */
868880c6d11SGeert Uytterhoeven 		return qspi_transfer_out(rspi, xfer);
869b42e0359SGeert Uytterhoeven 	} else if (xfer->rx_nbits > SPI_NBITS_SINGLE) {
870880c6d11SGeert Uytterhoeven 		/* Quad or Dual SPI Read */
871880c6d11SGeert Uytterhoeven 		return qspi_transfer_in(rspi, xfer);
872880c6d11SGeert Uytterhoeven 	} else {
873880c6d11SGeert Uytterhoeven 		/* Single SPI Transfer */
874340a15e6SGeert Uytterhoeven 		return qspi_transfer_out_in(rspi, xfer);
875eb557f75SGeert Uytterhoeven 	}
876880c6d11SGeert Uytterhoeven }
877eb557f75SGeert Uytterhoeven 
8780b2182ddSShimoda, Yoshihiro static int rspi_setup(struct spi_device *spi)
8790b2182ddSShimoda, Yoshihiro {
8800b2182ddSShimoda, Yoshihiro 	struct rspi_data *rspi = spi_master_get_devdata(spi->master);
8810b2182ddSShimoda, Yoshihiro 
8820b2182ddSShimoda, Yoshihiro 	rspi->max_speed_hz = spi->max_speed_hz;
8830b2182ddSShimoda, Yoshihiro 
884348e5153SGeert Uytterhoeven 	rspi->spcmd = SPCMD_SSLKP;
885348e5153SGeert Uytterhoeven 	if (spi->mode & SPI_CPOL)
886348e5153SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_CPOL;
887348e5153SGeert Uytterhoeven 	if (spi->mode & SPI_CPHA)
888348e5153SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_CPHA;
889348e5153SGeert Uytterhoeven 
89006a7a3cfSGeert Uytterhoeven 	/* CMOS output mode and MOSI signal from previous transfer */
89106a7a3cfSGeert Uytterhoeven 	rspi->sppcr = 0;
89206a7a3cfSGeert Uytterhoeven 	if (spi->mode & SPI_LOOP)
89306a7a3cfSGeert Uytterhoeven 		rspi->sppcr |= SPPCR_SPLP;
89406a7a3cfSGeert Uytterhoeven 
8955ce0ba88SHiep Cao Minh 	set_config_register(rspi, 8);
8960b2182ddSShimoda, Yoshihiro 
8970b2182ddSShimoda, Yoshihiro 	return 0;
8980b2182ddSShimoda, Yoshihiro }
8990b2182ddSShimoda, Yoshihiro 
900880c6d11SGeert Uytterhoeven static u16 qspi_transfer_mode(const struct spi_transfer *xfer)
901880c6d11SGeert Uytterhoeven {
902880c6d11SGeert Uytterhoeven 	if (xfer->tx_buf)
903880c6d11SGeert Uytterhoeven 		switch (xfer->tx_nbits) {
904880c6d11SGeert Uytterhoeven 		case SPI_NBITS_QUAD:
905880c6d11SGeert Uytterhoeven 			return SPCMD_SPIMOD_QUAD;
906880c6d11SGeert Uytterhoeven 		case SPI_NBITS_DUAL:
907880c6d11SGeert Uytterhoeven 			return SPCMD_SPIMOD_DUAL;
908880c6d11SGeert Uytterhoeven 		default:
909880c6d11SGeert Uytterhoeven 			return 0;
910880c6d11SGeert Uytterhoeven 		}
911880c6d11SGeert Uytterhoeven 	if (xfer->rx_buf)
912880c6d11SGeert Uytterhoeven 		switch (xfer->rx_nbits) {
913880c6d11SGeert Uytterhoeven 		case SPI_NBITS_QUAD:
914880c6d11SGeert Uytterhoeven 			return SPCMD_SPIMOD_QUAD | SPCMD_SPRW;
915880c6d11SGeert Uytterhoeven 		case SPI_NBITS_DUAL:
916880c6d11SGeert Uytterhoeven 			return SPCMD_SPIMOD_DUAL | SPCMD_SPRW;
917880c6d11SGeert Uytterhoeven 		default:
918880c6d11SGeert Uytterhoeven 			return 0;
919880c6d11SGeert Uytterhoeven 		}
920880c6d11SGeert Uytterhoeven 
921880c6d11SGeert Uytterhoeven 	return 0;
922880c6d11SGeert Uytterhoeven }
923880c6d11SGeert Uytterhoeven 
924880c6d11SGeert Uytterhoeven static int qspi_setup_sequencer(struct rspi_data *rspi,
925880c6d11SGeert Uytterhoeven 				const struct spi_message *msg)
926880c6d11SGeert Uytterhoeven {
927880c6d11SGeert Uytterhoeven 	const struct spi_transfer *xfer;
928880c6d11SGeert Uytterhoeven 	unsigned int i = 0, len = 0;
929880c6d11SGeert Uytterhoeven 	u16 current_mode = 0xffff, mode;
930880c6d11SGeert Uytterhoeven 
931880c6d11SGeert Uytterhoeven 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
932880c6d11SGeert Uytterhoeven 		mode = qspi_transfer_mode(xfer);
933880c6d11SGeert Uytterhoeven 		if (mode == current_mode) {
934880c6d11SGeert Uytterhoeven 			len += xfer->len;
935880c6d11SGeert Uytterhoeven 			continue;
936880c6d11SGeert Uytterhoeven 		}
937880c6d11SGeert Uytterhoeven 
938880c6d11SGeert Uytterhoeven 		/* Transfer mode change */
939880c6d11SGeert Uytterhoeven 		if (i) {
940880c6d11SGeert Uytterhoeven 			/* Set transfer data length of previous transfer */
941880c6d11SGeert Uytterhoeven 			rspi_write32(rspi, len, QSPI_SPBMUL(i - 1));
942880c6d11SGeert Uytterhoeven 		}
943880c6d11SGeert Uytterhoeven 
944880c6d11SGeert Uytterhoeven 		if (i >= QSPI_NUM_SPCMD) {
945880c6d11SGeert Uytterhoeven 			dev_err(&msg->spi->dev,
946880c6d11SGeert Uytterhoeven 				"Too many different transfer modes");
947880c6d11SGeert Uytterhoeven 			return -EINVAL;
948880c6d11SGeert Uytterhoeven 		}
949880c6d11SGeert Uytterhoeven 
950880c6d11SGeert Uytterhoeven 		/* Program transfer mode for this transfer */
951880c6d11SGeert Uytterhoeven 		rspi_write16(rspi, rspi->spcmd | mode, RSPI_SPCMD(i));
952880c6d11SGeert Uytterhoeven 		current_mode = mode;
953880c6d11SGeert Uytterhoeven 		len = xfer->len;
954880c6d11SGeert Uytterhoeven 		i++;
955880c6d11SGeert Uytterhoeven 	}
956880c6d11SGeert Uytterhoeven 	if (i) {
957880c6d11SGeert Uytterhoeven 		/* Set final transfer data length and sequence length */
958880c6d11SGeert Uytterhoeven 		rspi_write32(rspi, len, QSPI_SPBMUL(i - 1));
959880c6d11SGeert Uytterhoeven 		rspi_write8(rspi, i - 1, RSPI_SPSCR);
960880c6d11SGeert Uytterhoeven 	}
961880c6d11SGeert Uytterhoeven 
962880c6d11SGeert Uytterhoeven 	return 0;
963880c6d11SGeert Uytterhoeven }
964880c6d11SGeert Uytterhoeven 
96579d23495SGeert Uytterhoeven static int rspi_prepare_message(struct spi_master *master,
966880c6d11SGeert Uytterhoeven 				struct spi_message *msg)
96779d23495SGeert Uytterhoeven {
96879d23495SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
969880c6d11SGeert Uytterhoeven 	int ret;
9700b2182ddSShimoda, Yoshihiro 
971880c6d11SGeert Uytterhoeven 	if (msg->spi->mode &
972880c6d11SGeert Uytterhoeven 	    (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)) {
973880c6d11SGeert Uytterhoeven 		/* Setup sequencer for messages with multiple transfer modes */
974880c6d11SGeert Uytterhoeven 		ret = qspi_setup_sequencer(rspi, msg);
975880c6d11SGeert Uytterhoeven 		if (ret < 0)
976880c6d11SGeert Uytterhoeven 			return ret;
977880c6d11SGeert Uytterhoeven 	}
978880c6d11SGeert Uytterhoeven 
979880c6d11SGeert Uytterhoeven 	/* Enable SPI function in master mode */
98079d23495SGeert Uytterhoeven 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
9810b2182ddSShimoda, Yoshihiro 	return 0;
9820b2182ddSShimoda, Yoshihiro }
9830b2182ddSShimoda, Yoshihiro 
98479d23495SGeert Uytterhoeven static int rspi_unprepare_message(struct spi_master *master,
985880c6d11SGeert Uytterhoeven 				  struct spi_message *msg)
9860b2182ddSShimoda, Yoshihiro {
98779d23495SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
98879d23495SGeert Uytterhoeven 
989880c6d11SGeert Uytterhoeven 	/* Disable SPI function */
99079d23495SGeert Uytterhoeven 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
991880c6d11SGeert Uytterhoeven 
992880c6d11SGeert Uytterhoeven 	/* Reset sequencer for Single SPI Transfers */
993880c6d11SGeert Uytterhoeven 	rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
994880c6d11SGeert Uytterhoeven 	rspi_write8(rspi, 0, RSPI_SPSCR);
99579d23495SGeert Uytterhoeven 	return 0;
9960b2182ddSShimoda, Yoshihiro }
9970b2182ddSShimoda, Yoshihiro 
99893722206SGeert Uytterhoeven static irqreturn_t rspi_irq_mux(int irq, void *_sr)
9990b2182ddSShimoda, Yoshihiro {
1000c132f094SGeert Uytterhoeven 	struct rspi_data *rspi = _sr;
100197b95c11SGeert Uytterhoeven 	u8 spsr;
10020b2182ddSShimoda, Yoshihiro 	irqreturn_t ret = IRQ_NONE;
100397b95c11SGeert Uytterhoeven 	u8 disable_irq = 0;
10040b2182ddSShimoda, Yoshihiro 
10050b2182ddSShimoda, Yoshihiro 	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
10060b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPRF)
10070b2182ddSShimoda, Yoshihiro 		disable_irq |= SPCR_SPRIE;
10080b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPTEF)
10090b2182ddSShimoda, Yoshihiro 		disable_irq |= SPCR_SPTIE;
10100b2182ddSShimoda, Yoshihiro 
10110b2182ddSShimoda, Yoshihiro 	if (disable_irq) {
10120b2182ddSShimoda, Yoshihiro 		ret = IRQ_HANDLED;
10130b2182ddSShimoda, Yoshihiro 		rspi_disable_irq(rspi, disable_irq);
10140b2182ddSShimoda, Yoshihiro 		wake_up(&rspi->wait);
10150b2182ddSShimoda, Yoshihiro 	}
10160b2182ddSShimoda, Yoshihiro 
10170b2182ddSShimoda, Yoshihiro 	return ret;
10180b2182ddSShimoda, Yoshihiro }
10190b2182ddSShimoda, Yoshihiro 
102093722206SGeert Uytterhoeven static irqreturn_t rspi_irq_rx(int irq, void *_sr)
102193722206SGeert Uytterhoeven {
102293722206SGeert Uytterhoeven 	struct rspi_data *rspi = _sr;
102393722206SGeert Uytterhoeven 	u8 spsr;
102493722206SGeert Uytterhoeven 
102593722206SGeert Uytterhoeven 	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
102693722206SGeert Uytterhoeven 	if (spsr & SPSR_SPRF) {
102793722206SGeert Uytterhoeven 		rspi_disable_irq(rspi, SPCR_SPRIE);
102893722206SGeert Uytterhoeven 		wake_up(&rspi->wait);
102993722206SGeert Uytterhoeven 		return IRQ_HANDLED;
103093722206SGeert Uytterhoeven 	}
103193722206SGeert Uytterhoeven 
103293722206SGeert Uytterhoeven 	return 0;
103393722206SGeert Uytterhoeven }
103493722206SGeert Uytterhoeven 
103593722206SGeert Uytterhoeven static irqreturn_t rspi_irq_tx(int irq, void *_sr)
103693722206SGeert Uytterhoeven {
103793722206SGeert Uytterhoeven 	struct rspi_data *rspi = _sr;
103893722206SGeert Uytterhoeven 	u8 spsr;
103993722206SGeert Uytterhoeven 
104093722206SGeert Uytterhoeven 	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
104193722206SGeert Uytterhoeven 	if (spsr & SPSR_SPTEF) {
104293722206SGeert Uytterhoeven 		rspi_disable_irq(rspi, SPCR_SPTIE);
104393722206SGeert Uytterhoeven 		wake_up(&rspi->wait);
104493722206SGeert Uytterhoeven 		return IRQ_HANDLED;
104593722206SGeert Uytterhoeven 	}
104693722206SGeert Uytterhoeven 
104793722206SGeert Uytterhoeven 	return 0;
104893722206SGeert Uytterhoeven }
104993722206SGeert Uytterhoeven 
105065bf2205SGeert Uytterhoeven static struct dma_chan *rspi_request_dma_chan(struct device *dev,
105165bf2205SGeert Uytterhoeven 					      enum dma_transfer_direction dir,
105265bf2205SGeert Uytterhoeven 					      unsigned int id,
105365bf2205SGeert Uytterhoeven 					      dma_addr_t port_addr)
105465bf2205SGeert Uytterhoeven {
105565bf2205SGeert Uytterhoeven 	dma_cap_mask_t mask;
105665bf2205SGeert Uytterhoeven 	struct dma_chan *chan;
105765bf2205SGeert Uytterhoeven 	struct dma_slave_config cfg;
105865bf2205SGeert Uytterhoeven 	int ret;
105965bf2205SGeert Uytterhoeven 
106065bf2205SGeert Uytterhoeven 	dma_cap_zero(mask);
106165bf2205SGeert Uytterhoeven 	dma_cap_set(DMA_SLAVE, mask);
106265bf2205SGeert Uytterhoeven 
1063e825b8ddSGeert Uytterhoeven 	chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
1064e825b8ddSGeert Uytterhoeven 				(void *)(unsigned long)id, dev,
1065e825b8ddSGeert Uytterhoeven 				dir == DMA_MEM_TO_DEV ? "tx" : "rx");
106665bf2205SGeert Uytterhoeven 	if (!chan) {
1067e825b8ddSGeert Uytterhoeven 		dev_warn(dev, "dma_request_slave_channel_compat failed\n");
106865bf2205SGeert Uytterhoeven 		return NULL;
106965bf2205SGeert Uytterhoeven 	}
107065bf2205SGeert Uytterhoeven 
107165bf2205SGeert Uytterhoeven 	memset(&cfg, 0, sizeof(cfg));
107265bf2205SGeert Uytterhoeven 	cfg.direction = dir;
1073a30b95a7SGeert Uytterhoeven 	if (dir == DMA_MEM_TO_DEV) {
107465bf2205SGeert Uytterhoeven 		cfg.dst_addr = port_addr;
1075a30b95a7SGeert Uytterhoeven 		cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
1076a30b95a7SGeert Uytterhoeven 	} else {
107765bf2205SGeert Uytterhoeven 		cfg.src_addr = port_addr;
1078a30b95a7SGeert Uytterhoeven 		cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
1079a30b95a7SGeert Uytterhoeven 	}
108065bf2205SGeert Uytterhoeven 
108165bf2205SGeert Uytterhoeven 	ret = dmaengine_slave_config(chan, &cfg);
108265bf2205SGeert Uytterhoeven 	if (ret) {
108365bf2205SGeert Uytterhoeven 		dev_warn(dev, "dmaengine_slave_config failed %d\n", ret);
108465bf2205SGeert Uytterhoeven 		dma_release_channel(chan);
108565bf2205SGeert Uytterhoeven 		return NULL;
108665bf2205SGeert Uytterhoeven 	}
108765bf2205SGeert Uytterhoeven 
108865bf2205SGeert Uytterhoeven 	return chan;
108965bf2205SGeert Uytterhoeven }
109065bf2205SGeert Uytterhoeven 
10912f777ec9SGeert Uytterhoeven static int rspi_request_dma(struct device *dev, struct spi_master *master,
1092fcdc49aeSGeert Uytterhoeven 			    const struct resource *res)
1093a3633fe7SShimoda, Yoshihiro {
1094fcdc49aeSGeert Uytterhoeven 	const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev);
1095e825b8ddSGeert Uytterhoeven 	unsigned int dma_tx_id, dma_rx_id;
1096a3633fe7SShimoda, Yoshihiro 
1097e825b8ddSGeert Uytterhoeven 	if (dev->of_node) {
1098e825b8ddSGeert Uytterhoeven 		/* In the OF case we will get the slave IDs from the DT */
1099e825b8ddSGeert Uytterhoeven 		dma_tx_id = 0;
1100e825b8ddSGeert Uytterhoeven 		dma_rx_id = 0;
1101e825b8ddSGeert Uytterhoeven 	} else if (rspi_pd && rspi_pd->dma_tx_id && rspi_pd->dma_rx_id) {
1102e825b8ddSGeert Uytterhoeven 		dma_tx_id = rspi_pd->dma_tx_id;
1103e825b8ddSGeert Uytterhoeven 		dma_rx_id = rspi_pd->dma_rx_id;
1104e825b8ddSGeert Uytterhoeven 	} else {
1105e825b8ddSGeert Uytterhoeven 		/* The driver assumes no error. */
1106e825b8ddSGeert Uytterhoeven 		return 0;
1107e825b8ddSGeert Uytterhoeven 	}
1108a3633fe7SShimoda, Yoshihiro 
1109e825b8ddSGeert Uytterhoeven 	master->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, dma_tx_id,
111065bf2205SGeert Uytterhoeven 					       res->start + RSPI_SPDR);
1111e825b8ddSGeert Uytterhoeven 	if (!master->dma_tx)
111265bf2205SGeert Uytterhoeven 		return -ENODEV;
111365bf2205SGeert Uytterhoeven 
1114e825b8ddSGeert Uytterhoeven 	master->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, dma_rx_id,
111565bf2205SGeert Uytterhoeven 					       res->start + RSPI_SPDR);
1116e825b8ddSGeert Uytterhoeven 	if (!master->dma_rx) {
1117e825b8ddSGeert Uytterhoeven 		dma_release_channel(master->dma_tx);
1118e825b8ddSGeert Uytterhoeven 		master->dma_tx = NULL;
111965bf2205SGeert Uytterhoeven 		return -ENODEV;
1120a3633fe7SShimoda, Yoshihiro 	}
1121a3633fe7SShimoda, Yoshihiro 
11222f777ec9SGeert Uytterhoeven 	master->can_dma = rspi_can_dma;
11235f338d0cSGeert Uytterhoeven 	dev_info(dev, "DMA available");
11240243c536SShimoda, Yoshihiro 	return 0;
11250243c536SShimoda, Yoshihiro }
11260243c536SShimoda, Yoshihiro 
1127afcc98deSGeert Uytterhoeven static void rspi_release_dma(struct spi_master *master)
1128a3633fe7SShimoda, Yoshihiro {
1129afcc98deSGeert Uytterhoeven 	if (master->dma_tx)
1130afcc98deSGeert Uytterhoeven 		dma_release_channel(master->dma_tx);
1131afcc98deSGeert Uytterhoeven 	if (master->dma_rx)
1132afcc98deSGeert Uytterhoeven 		dma_release_channel(master->dma_rx);
1133a3633fe7SShimoda, Yoshihiro }
1134a3633fe7SShimoda, Yoshihiro 
1135fd4a319bSGrant Likely static int rspi_remove(struct platform_device *pdev)
11360b2182ddSShimoda, Yoshihiro {
11375ffbe2d9SLaurent Pinchart 	struct rspi_data *rspi = platform_get_drvdata(pdev);
11380b2182ddSShimoda, Yoshihiro 
1139afcc98deSGeert Uytterhoeven 	rspi_release_dma(rspi->master);
1140490c9774SGeert Uytterhoeven 	pm_runtime_disable(&pdev->dev);
11410b2182ddSShimoda, Yoshihiro 
11420b2182ddSShimoda, Yoshihiro 	return 0;
11430b2182ddSShimoda, Yoshihiro }
11440b2182ddSShimoda, Yoshihiro 
1145426ef76dSGeert Uytterhoeven static const struct spi_ops rspi_ops = {
1146426ef76dSGeert Uytterhoeven 	.set_config_register =	rspi_set_config_register,
1147426ef76dSGeert Uytterhoeven 	.transfer_one =		rspi_transfer_one,
1148880c6d11SGeert Uytterhoeven 	.mode_bits =		SPI_CPHA | SPI_CPOL | SPI_LOOP,
1149b42e0359SGeert Uytterhoeven 	.flags =		SPI_MASTER_MUST_TX,
11502f777ec9SGeert Uytterhoeven 	.fifo_size =		8,
1151426ef76dSGeert Uytterhoeven };
1152426ef76dSGeert Uytterhoeven 
1153426ef76dSGeert Uytterhoeven static const struct spi_ops rspi_rz_ops = {
1154426ef76dSGeert Uytterhoeven 	.set_config_register =	rspi_rz_set_config_register,
1155426ef76dSGeert Uytterhoeven 	.transfer_one =		rspi_rz_transfer_one,
1156880c6d11SGeert Uytterhoeven 	.mode_bits =		SPI_CPHA | SPI_CPOL | SPI_LOOP,
1157b42e0359SGeert Uytterhoeven 	.flags =		SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX,
11582f777ec9SGeert Uytterhoeven 	.fifo_size =		8,	/* 8 for TX, 32 for RX */
1159426ef76dSGeert Uytterhoeven };
1160426ef76dSGeert Uytterhoeven 
1161426ef76dSGeert Uytterhoeven static const struct spi_ops qspi_ops = {
1162426ef76dSGeert Uytterhoeven 	.set_config_register =	qspi_set_config_register,
1163426ef76dSGeert Uytterhoeven 	.transfer_one =		qspi_transfer_one,
1164880c6d11SGeert Uytterhoeven 	.mode_bits =		SPI_CPHA | SPI_CPOL | SPI_LOOP |
1165880c6d11SGeert Uytterhoeven 				SPI_TX_DUAL | SPI_TX_QUAD |
1166880c6d11SGeert Uytterhoeven 				SPI_RX_DUAL | SPI_RX_QUAD,
1167b42e0359SGeert Uytterhoeven 	.flags =		SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX,
11682f777ec9SGeert Uytterhoeven 	.fifo_size =		32,
1169426ef76dSGeert Uytterhoeven };
1170426ef76dSGeert Uytterhoeven 
1171426ef76dSGeert Uytterhoeven #ifdef CONFIG_OF
1172426ef76dSGeert Uytterhoeven static const struct of_device_id rspi_of_match[] = {
1173426ef76dSGeert Uytterhoeven 	/* RSPI on legacy SH */
1174426ef76dSGeert Uytterhoeven 	{ .compatible = "renesas,rspi", .data = &rspi_ops },
1175426ef76dSGeert Uytterhoeven 	/* RSPI on RZ/A1H */
1176426ef76dSGeert Uytterhoeven 	{ .compatible = "renesas,rspi-rz", .data = &rspi_rz_ops },
1177426ef76dSGeert Uytterhoeven 	/* QSPI on R-Car Gen2 */
1178426ef76dSGeert Uytterhoeven 	{ .compatible = "renesas,qspi", .data = &qspi_ops },
1179426ef76dSGeert Uytterhoeven 	{ /* sentinel */ }
1180426ef76dSGeert Uytterhoeven };
1181426ef76dSGeert Uytterhoeven 
1182426ef76dSGeert Uytterhoeven MODULE_DEVICE_TABLE(of, rspi_of_match);
1183426ef76dSGeert Uytterhoeven 
1184426ef76dSGeert Uytterhoeven static int rspi_parse_dt(struct device *dev, struct spi_master *master)
1185426ef76dSGeert Uytterhoeven {
1186426ef76dSGeert Uytterhoeven 	u32 num_cs;
1187426ef76dSGeert Uytterhoeven 	int error;
1188426ef76dSGeert Uytterhoeven 
1189426ef76dSGeert Uytterhoeven 	/* Parse DT properties */
1190426ef76dSGeert Uytterhoeven 	error = of_property_read_u32(dev->of_node, "num-cs", &num_cs);
1191426ef76dSGeert Uytterhoeven 	if (error) {
1192426ef76dSGeert Uytterhoeven 		dev_err(dev, "of_property_read_u32 num-cs failed %d\n", error);
1193426ef76dSGeert Uytterhoeven 		return error;
1194426ef76dSGeert Uytterhoeven 	}
1195426ef76dSGeert Uytterhoeven 
1196426ef76dSGeert Uytterhoeven 	master->num_chipselect = num_cs;
1197426ef76dSGeert Uytterhoeven 	return 0;
1198426ef76dSGeert Uytterhoeven }
1199426ef76dSGeert Uytterhoeven #else
120064b67defSShimoda, Yoshihiro #define rspi_of_match	NULL
1201426ef76dSGeert Uytterhoeven static inline int rspi_parse_dt(struct device *dev, struct spi_master *master)
1202426ef76dSGeert Uytterhoeven {
1203426ef76dSGeert Uytterhoeven 	return -EINVAL;
1204426ef76dSGeert Uytterhoeven }
1205426ef76dSGeert Uytterhoeven #endif /* CONFIG_OF */
1206426ef76dSGeert Uytterhoeven 
120793722206SGeert Uytterhoeven static int rspi_request_irq(struct device *dev, unsigned int irq,
120893722206SGeert Uytterhoeven 			    irq_handler_t handler, const char *suffix,
120993722206SGeert Uytterhoeven 			    void *dev_id)
121093722206SGeert Uytterhoeven {
121143937455SGeert Uytterhoeven 	const char *name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s",
121243937455SGeert Uytterhoeven 					  dev_name(dev), suffix);
121393722206SGeert Uytterhoeven 	if (!name)
121493722206SGeert Uytterhoeven 		return -ENOMEM;
121543937455SGeert Uytterhoeven 
121693722206SGeert Uytterhoeven 	return devm_request_irq(dev, irq, handler, 0, name, dev_id);
121793722206SGeert Uytterhoeven }
121893722206SGeert Uytterhoeven 
1219fd4a319bSGrant Likely static int rspi_probe(struct platform_device *pdev)
12200b2182ddSShimoda, Yoshihiro {
12210b2182ddSShimoda, Yoshihiro 	struct resource *res;
12220b2182ddSShimoda, Yoshihiro 	struct spi_master *master;
12230b2182ddSShimoda, Yoshihiro 	struct rspi_data *rspi;
122493722206SGeert Uytterhoeven 	int ret;
1225426ef76dSGeert Uytterhoeven 	const struct of_device_id *of_id;
1226426ef76dSGeert Uytterhoeven 	const struct rspi_plat_data *rspi_pd;
12275ce0ba88SHiep Cao Minh 	const struct spi_ops *ops;
12280b2182ddSShimoda, Yoshihiro 
12290b2182ddSShimoda, Yoshihiro 	master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data));
1230ffcfae38SGeert Uytterhoeven 	if (master == NULL)
12310b2182ddSShimoda, Yoshihiro 		return -ENOMEM;
12320b2182ddSShimoda, Yoshihiro 
1233426ef76dSGeert Uytterhoeven 	of_id = of_match_device(rspi_of_match, &pdev->dev);
1234426ef76dSGeert Uytterhoeven 	if (of_id) {
1235426ef76dSGeert Uytterhoeven 		ops = of_id->data;
1236426ef76dSGeert Uytterhoeven 		ret = rspi_parse_dt(&pdev->dev, master);
1237426ef76dSGeert Uytterhoeven 		if (ret)
1238426ef76dSGeert Uytterhoeven 			goto error1;
1239426ef76dSGeert Uytterhoeven 	} else {
1240426ef76dSGeert Uytterhoeven 		ops = (struct spi_ops *)pdev->id_entry->driver_data;
1241426ef76dSGeert Uytterhoeven 		rspi_pd = dev_get_platdata(&pdev->dev);
1242426ef76dSGeert Uytterhoeven 		if (rspi_pd && rspi_pd->num_chipselect)
1243426ef76dSGeert Uytterhoeven 			master->num_chipselect = rspi_pd->num_chipselect;
1244426ef76dSGeert Uytterhoeven 		else
1245426ef76dSGeert Uytterhoeven 			master->num_chipselect = 2; /* default */
1246d64b4726SGeert Uytterhoeven 	}
1247426ef76dSGeert Uytterhoeven 
1248426ef76dSGeert Uytterhoeven 	/* ops parameter check */
1249426ef76dSGeert Uytterhoeven 	if (!ops->set_config_register) {
1250426ef76dSGeert Uytterhoeven 		dev_err(&pdev->dev, "there is no set_config_register\n");
1251426ef76dSGeert Uytterhoeven 		ret = -ENODEV;
1252426ef76dSGeert Uytterhoeven 		goto error1;
1253426ef76dSGeert Uytterhoeven 	}
1254426ef76dSGeert Uytterhoeven 
12550b2182ddSShimoda, Yoshihiro 	rspi = spi_master_get_devdata(master);
125624b5a82cSJingoo Han 	platform_set_drvdata(pdev, rspi);
12575ce0ba88SHiep Cao Minh 	rspi->ops = ops;
12580b2182ddSShimoda, Yoshihiro 	rspi->master = master;
12595d79e9acSLaurent Pinchart 
12605d79e9acSLaurent Pinchart 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
12615d79e9acSLaurent Pinchart 	rspi->addr = devm_ioremap_resource(&pdev->dev, res);
12625d79e9acSLaurent Pinchart 	if (IS_ERR(rspi->addr)) {
12635d79e9acSLaurent Pinchart 		ret = PTR_ERR(rspi->addr);
12640b2182ddSShimoda, Yoshihiro 		goto error1;
12650b2182ddSShimoda, Yoshihiro 	}
12660b2182ddSShimoda, Yoshihiro 
126729f397b7SGeert Uytterhoeven 	rspi->clk = devm_clk_get(&pdev->dev, NULL);
12680b2182ddSShimoda, Yoshihiro 	if (IS_ERR(rspi->clk)) {
12690b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "cannot get clock\n");
12700b2182ddSShimoda, Yoshihiro 		ret = PTR_ERR(rspi->clk);
12715d79e9acSLaurent Pinchart 		goto error1;
12720b2182ddSShimoda, Yoshihiro 	}
127317fe0d9aSGeert Uytterhoeven 
1274490c9774SGeert Uytterhoeven 	pm_runtime_enable(&pdev->dev);
12750b2182ddSShimoda, Yoshihiro 
12760b2182ddSShimoda, Yoshihiro 	init_waitqueue_head(&rspi->wait);
12770b2182ddSShimoda, Yoshihiro 
12780b2182ddSShimoda, Yoshihiro 	master->bus_num = pdev->id;
12790b2182ddSShimoda, Yoshihiro 	master->setup = rspi_setup;
1280490c9774SGeert Uytterhoeven 	master->auto_runtime_pm = true;
1281eb557f75SGeert Uytterhoeven 	master->transfer_one = ops->transfer_one;
128279d23495SGeert Uytterhoeven 	master->prepare_message = rspi_prepare_message;
128379d23495SGeert Uytterhoeven 	master->unprepare_message = rspi_unprepare_message;
1284880c6d11SGeert Uytterhoeven 	master->mode_bits = ops->mode_bits;
1285b42e0359SGeert Uytterhoeven 	master->flags = ops->flags;
1286426ef76dSGeert Uytterhoeven 	master->dev.of_node = pdev->dev.of_node;
12870b2182ddSShimoda, Yoshihiro 
128893722206SGeert Uytterhoeven 	ret = platform_get_irq_byname(pdev, "rx");
128993722206SGeert Uytterhoeven 	if (ret < 0) {
129093722206SGeert Uytterhoeven 		ret = platform_get_irq_byname(pdev, "mux");
129193722206SGeert Uytterhoeven 		if (ret < 0)
129293722206SGeert Uytterhoeven 			ret = platform_get_irq(pdev, 0);
129393722206SGeert Uytterhoeven 		if (ret >= 0)
129493722206SGeert Uytterhoeven 			rspi->rx_irq = rspi->tx_irq = ret;
129593722206SGeert Uytterhoeven 	} else {
129693722206SGeert Uytterhoeven 		rspi->rx_irq = ret;
129793722206SGeert Uytterhoeven 		ret = platform_get_irq_byname(pdev, "tx");
129893722206SGeert Uytterhoeven 		if (ret >= 0)
129993722206SGeert Uytterhoeven 			rspi->tx_irq = ret;
130093722206SGeert Uytterhoeven 	}
130193722206SGeert Uytterhoeven 	if (ret < 0) {
130293722206SGeert Uytterhoeven 		dev_err(&pdev->dev, "platform_get_irq error\n");
130393722206SGeert Uytterhoeven 		goto error2;
130493722206SGeert Uytterhoeven 	}
130593722206SGeert Uytterhoeven 
130693722206SGeert Uytterhoeven 	if (rspi->rx_irq == rspi->tx_irq) {
130793722206SGeert Uytterhoeven 		/* Single multiplexed interrupt */
130893722206SGeert Uytterhoeven 		ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_mux,
130993722206SGeert Uytterhoeven 				       "mux", rspi);
131093722206SGeert Uytterhoeven 	} else {
131193722206SGeert Uytterhoeven 		/* Multi-interrupt mode, only SPRI and SPTI are used */
131293722206SGeert Uytterhoeven 		ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_rx,
131393722206SGeert Uytterhoeven 				       "rx", rspi);
131493722206SGeert Uytterhoeven 		if (!ret)
131593722206SGeert Uytterhoeven 			ret = rspi_request_irq(&pdev->dev, rspi->tx_irq,
131693722206SGeert Uytterhoeven 					       rspi_irq_tx, "tx", rspi);
131793722206SGeert Uytterhoeven 	}
13180b2182ddSShimoda, Yoshihiro 	if (ret < 0) {
13190b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "request_irq error\n");
1320fcb4ed74SGeert Uytterhoeven 		goto error2;
13210b2182ddSShimoda, Yoshihiro 	}
13220b2182ddSShimoda, Yoshihiro 
13232f777ec9SGeert Uytterhoeven 	ret = rspi_request_dma(&pdev->dev, master, res);
132427e105a6SGeert Uytterhoeven 	if (ret < 0)
132527e105a6SGeert Uytterhoeven 		dev_warn(&pdev->dev, "DMA not available, using PIO\n");
1326a3633fe7SShimoda, Yoshihiro 
13279e03d05eSJingoo Han 	ret = devm_spi_register_master(&pdev->dev, master);
13280b2182ddSShimoda, Yoshihiro 	if (ret < 0) {
13290b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "spi_register_master error.\n");
1330fcb4ed74SGeert Uytterhoeven 		goto error3;
13310b2182ddSShimoda, Yoshihiro 	}
13320b2182ddSShimoda, Yoshihiro 
13330b2182ddSShimoda, Yoshihiro 	dev_info(&pdev->dev, "probed\n");
13340b2182ddSShimoda, Yoshihiro 
13350b2182ddSShimoda, Yoshihiro 	return 0;
13360b2182ddSShimoda, Yoshihiro 
1337fcb4ed74SGeert Uytterhoeven error3:
1338afcc98deSGeert Uytterhoeven 	rspi_release_dma(master);
1339fcb4ed74SGeert Uytterhoeven error2:
1340490c9774SGeert Uytterhoeven 	pm_runtime_disable(&pdev->dev);
13410b2182ddSShimoda, Yoshihiro error1:
13420b2182ddSShimoda, Yoshihiro 	spi_master_put(master);
13430b2182ddSShimoda, Yoshihiro 
13440b2182ddSShimoda, Yoshihiro 	return ret;
13450b2182ddSShimoda, Yoshihiro }
13460b2182ddSShimoda, Yoshihiro 
13478634dafaSKrzysztof Kozlowski static const struct platform_device_id spi_driver_ids[] = {
13485ce0ba88SHiep Cao Minh 	{ "rspi",	(kernel_ulong_t)&rspi_ops },
1349862d357fSGeert Uytterhoeven 	{ "rspi-rz",	(kernel_ulong_t)&rspi_rz_ops },
13505ce0ba88SHiep Cao Minh 	{ "qspi",	(kernel_ulong_t)&qspi_ops },
13515ce0ba88SHiep Cao Minh 	{},
13525ce0ba88SHiep Cao Minh };
13535ce0ba88SHiep Cao Minh 
13545ce0ba88SHiep Cao Minh MODULE_DEVICE_TABLE(platform, spi_driver_ids);
13555ce0ba88SHiep Cao Minh 
13560b2182ddSShimoda, Yoshihiro static struct platform_driver rspi_driver = {
13570b2182ddSShimoda, Yoshihiro 	.probe =	rspi_probe,
1358fd4a319bSGrant Likely 	.remove =	rspi_remove,
13595ce0ba88SHiep Cao Minh 	.id_table =	spi_driver_ids,
13600b2182ddSShimoda, Yoshihiro 	.driver		= {
13615ce0ba88SHiep Cao Minh 		.name = "renesas_spi",
1362426ef76dSGeert Uytterhoeven 		.of_match_table = of_match_ptr(rspi_of_match),
13630b2182ddSShimoda, Yoshihiro 	},
13640b2182ddSShimoda, Yoshihiro };
13650b2182ddSShimoda, Yoshihiro module_platform_driver(rspi_driver);
13660b2182ddSShimoda, Yoshihiro 
13670b2182ddSShimoda, Yoshihiro MODULE_DESCRIPTION("Renesas RSPI bus driver");
13680b2182ddSShimoda, Yoshihiro MODULE_LICENSE("GPL v2");
13690b2182ddSShimoda, Yoshihiro MODULE_AUTHOR("Yoshihiro Shimoda");
13700b2182ddSShimoda, Yoshihiro MODULE_ALIAS("platform:rspi");
1371