xref: /openbmc/linux/drivers/spi/spi-rspi.c (revision 348e5153)
10b2182ddSShimoda, Yoshihiro /*
20b2182ddSShimoda, Yoshihiro  * SH RSPI driver
30b2182ddSShimoda, Yoshihiro  *
40b2182ddSShimoda, Yoshihiro  * Copyright (C) 2012  Renesas Solutions Corp.
50b2182ddSShimoda, Yoshihiro  *
60b2182ddSShimoda, Yoshihiro  * Based on spi-sh.c:
70b2182ddSShimoda, Yoshihiro  * Copyright (C) 2011 Renesas Solutions Corp.
80b2182ddSShimoda, Yoshihiro  *
90b2182ddSShimoda, Yoshihiro  * This program is free software; you can redistribute it and/or modify
100b2182ddSShimoda, Yoshihiro  * it under the terms of the GNU General Public License as published by
110b2182ddSShimoda, Yoshihiro  * the Free Software Foundation; version 2 of the License.
120b2182ddSShimoda, Yoshihiro  *
130b2182ddSShimoda, Yoshihiro  * This program is distributed in the hope that it will be useful,
140b2182ddSShimoda, Yoshihiro  * but WITHOUT ANY WARRANTY; without even the implied warranty of
150b2182ddSShimoda, Yoshihiro  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
160b2182ddSShimoda, Yoshihiro  * GNU General Public License for more details.
170b2182ddSShimoda, Yoshihiro  *
180b2182ddSShimoda, Yoshihiro  * You should have received a copy of the GNU General Public License
190b2182ddSShimoda, Yoshihiro  * along with this program; if not, write to the Free Software
200b2182ddSShimoda, Yoshihiro  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
210b2182ddSShimoda, Yoshihiro  *
220b2182ddSShimoda, Yoshihiro  */
230b2182ddSShimoda, Yoshihiro 
240b2182ddSShimoda, Yoshihiro #include <linux/module.h>
250b2182ddSShimoda, Yoshihiro #include <linux/kernel.h>
260b2182ddSShimoda, Yoshihiro #include <linux/sched.h>
270b2182ddSShimoda, Yoshihiro #include <linux/errno.h>
280b2182ddSShimoda, Yoshihiro #include <linux/list.h>
290b2182ddSShimoda, Yoshihiro #include <linux/workqueue.h>
300b2182ddSShimoda, Yoshihiro #include <linux/interrupt.h>
310b2182ddSShimoda, Yoshihiro #include <linux/platform_device.h>
320b2182ddSShimoda, Yoshihiro #include <linux/io.h>
330b2182ddSShimoda, Yoshihiro #include <linux/clk.h>
34a3633fe7SShimoda, Yoshihiro #include <linux/dmaengine.h>
35a3633fe7SShimoda, Yoshihiro #include <linux/dma-mapping.h>
36a3633fe7SShimoda, Yoshihiro #include <linux/sh_dma.h>
370b2182ddSShimoda, Yoshihiro #include <linux/spi/spi.h>
38a3633fe7SShimoda, Yoshihiro #include <linux/spi/rspi.h>
390b2182ddSShimoda, Yoshihiro 
406ab4865bSGeert Uytterhoeven #define RSPI_SPCR		0x00	/* Control Register */
416ab4865bSGeert Uytterhoeven #define RSPI_SSLP		0x01	/* Slave Select Polarity Register */
426ab4865bSGeert Uytterhoeven #define RSPI_SPPCR		0x02	/* Pin Control Register */
436ab4865bSGeert Uytterhoeven #define RSPI_SPSR		0x03	/* Status Register */
446ab4865bSGeert Uytterhoeven #define RSPI_SPDR		0x04	/* Data Register */
456ab4865bSGeert Uytterhoeven #define RSPI_SPSCR		0x08	/* Sequence Control Register */
466ab4865bSGeert Uytterhoeven #define RSPI_SPSSR		0x09	/* Sequence Status Register */
476ab4865bSGeert Uytterhoeven #define RSPI_SPBR		0x0a	/* Bit Rate Register */
486ab4865bSGeert Uytterhoeven #define RSPI_SPDCR		0x0b	/* Data Control Register */
496ab4865bSGeert Uytterhoeven #define RSPI_SPCKD		0x0c	/* Clock Delay Register */
506ab4865bSGeert Uytterhoeven #define RSPI_SSLND		0x0d	/* Slave Select Negation Delay Register */
516ab4865bSGeert Uytterhoeven #define RSPI_SPND		0x0e	/* Next-Access Delay Register */
526ab4865bSGeert Uytterhoeven #define RSPI_SPCR2		0x0f	/* Control Register 2 */
536ab4865bSGeert Uytterhoeven #define RSPI_SPCMD0		0x10	/* Command Register 0 */
546ab4865bSGeert Uytterhoeven #define RSPI_SPCMD1		0x12	/* Command Register 1 */
556ab4865bSGeert Uytterhoeven #define RSPI_SPCMD2		0x14	/* Command Register 2 */
566ab4865bSGeert Uytterhoeven #define RSPI_SPCMD3		0x16	/* Command Register 3 */
576ab4865bSGeert Uytterhoeven #define RSPI_SPCMD4		0x18	/* Command Register 4 */
586ab4865bSGeert Uytterhoeven #define RSPI_SPCMD5		0x1a	/* Command Register 5 */
596ab4865bSGeert Uytterhoeven #define RSPI_SPCMD6		0x1c	/* Command Register 6 */
606ab4865bSGeert Uytterhoeven #define RSPI_SPCMD7		0x1e	/* Command Register 7 */
616ab4865bSGeert Uytterhoeven #define RSPI_SPBFCR		0x20	/* Buffer Control Register */
626ab4865bSGeert Uytterhoeven #define RSPI_SPBFDR		0x22	/* Buffer Data Count Setting Register */
630b2182ddSShimoda, Yoshihiro 
645ce0ba88SHiep Cao Minh /*qspi only */
65fbe5072bSGeert Uytterhoeven #define QSPI_SPBFCR		0x18	/* Buffer Control Register */
66fbe5072bSGeert Uytterhoeven #define QSPI_SPBDCR		0x1a	/* Buffer Data Count Register */
67fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL0		0x1c	/* Transfer Data Length Multiplier Setting Register 0 */
68fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL1		0x20	/* Transfer Data Length Multiplier Setting Register 1 */
69fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL2		0x24	/* Transfer Data Length Multiplier Setting Register 2 */
70fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL3		0x28	/* Transfer Data Length Multiplier Setting Register 3 */
715ce0ba88SHiep Cao Minh 
726ab4865bSGeert Uytterhoeven /* SPCR - Control Register */
736ab4865bSGeert Uytterhoeven #define SPCR_SPRIE		0x80	/* Receive Interrupt Enable */
746ab4865bSGeert Uytterhoeven #define SPCR_SPE		0x40	/* Function Enable */
756ab4865bSGeert Uytterhoeven #define SPCR_SPTIE		0x20	/* Transmit Interrupt Enable */
766ab4865bSGeert Uytterhoeven #define SPCR_SPEIE		0x10	/* Error Interrupt Enable */
776ab4865bSGeert Uytterhoeven #define SPCR_MSTR		0x08	/* Master/Slave Mode Select */
786ab4865bSGeert Uytterhoeven #define SPCR_MODFEN		0x04	/* Mode Fault Error Detection Enable */
796ab4865bSGeert Uytterhoeven /* RSPI on SH only */
806ab4865bSGeert Uytterhoeven #define SPCR_TXMD		0x02	/* TX Only Mode (vs. Full Duplex) */
816ab4865bSGeert Uytterhoeven #define SPCR_SPMS		0x01	/* 3-wire Mode (vs. 4-wire) */
82fbe5072bSGeert Uytterhoeven /* QSPI on R-Car M2 only */
83fbe5072bSGeert Uytterhoeven #define SPCR_WSWAP		0x02	/* Word Swap of read-data for DMAC */
84fbe5072bSGeert Uytterhoeven #define SPCR_BSWAP		0x01	/* Byte Swap of read-data for DMAC */
850b2182ddSShimoda, Yoshihiro 
866ab4865bSGeert Uytterhoeven /* SSLP - Slave Select Polarity Register */
876ab4865bSGeert Uytterhoeven #define SSLP_SSL1P		0x02	/* SSL1 Signal Polarity Setting */
886ab4865bSGeert Uytterhoeven #define SSLP_SSL0P		0x01	/* SSL0 Signal Polarity Setting */
890b2182ddSShimoda, Yoshihiro 
906ab4865bSGeert Uytterhoeven /* SPPCR - Pin Control Register */
916ab4865bSGeert Uytterhoeven #define SPPCR_MOIFE		0x20	/* MOSI Idle Value Fixing Enable */
926ab4865bSGeert Uytterhoeven #define SPPCR_MOIFV		0x10	/* MOSI Idle Fixed Value */
930b2182ddSShimoda, Yoshihiro #define SPPCR_SPOM		0x04
946ab4865bSGeert Uytterhoeven #define SPPCR_SPLP2		0x02	/* Loopback Mode 2 (non-inverting) */
956ab4865bSGeert Uytterhoeven #define SPPCR_SPLP		0x01	/* Loopback Mode (inverting) */
960b2182ddSShimoda, Yoshihiro 
97fbe5072bSGeert Uytterhoeven #define SPPCR_IO3FV		0x04	/* Single-/Dual-SPI Mode IO3 Output Fixed Value */
98fbe5072bSGeert Uytterhoeven #define SPPCR_IO2FV		0x04	/* Single-/Dual-SPI Mode IO2 Output Fixed Value */
99fbe5072bSGeert Uytterhoeven 
1006ab4865bSGeert Uytterhoeven /* SPSR - Status Register */
1016ab4865bSGeert Uytterhoeven #define SPSR_SPRF		0x80	/* Receive Buffer Full Flag */
1026ab4865bSGeert Uytterhoeven #define SPSR_TEND		0x40	/* Transmit End */
1036ab4865bSGeert Uytterhoeven #define SPSR_SPTEF		0x20	/* Transmit Buffer Empty Flag */
1046ab4865bSGeert Uytterhoeven #define SPSR_PERF		0x08	/* Parity Error Flag */
1056ab4865bSGeert Uytterhoeven #define SPSR_MODF		0x04	/* Mode Fault Error Flag */
1066ab4865bSGeert Uytterhoeven #define SPSR_IDLNF		0x02	/* RSPI Idle Flag */
1076ab4865bSGeert Uytterhoeven #define SPSR_OVRF		0x01	/* Overrun Error Flag */
1080b2182ddSShimoda, Yoshihiro 
1096ab4865bSGeert Uytterhoeven /* SPSCR - Sequence Control Register */
1106ab4865bSGeert Uytterhoeven #define SPSCR_SPSLN_MASK	0x07	/* Sequence Length Specification */
1110b2182ddSShimoda, Yoshihiro 
1126ab4865bSGeert Uytterhoeven /* SPSSR - Sequence Status Register */
1136ab4865bSGeert Uytterhoeven #define SPSSR_SPECM_MASK	0x70	/* Command Error Mask */
1146ab4865bSGeert Uytterhoeven #define SPSSR_SPCP_MASK		0x07	/* Command Pointer Mask */
1150b2182ddSShimoda, Yoshihiro 
1166ab4865bSGeert Uytterhoeven /* SPDCR - Data Control Register */
1176ab4865bSGeert Uytterhoeven #define SPDCR_TXDMY		0x80	/* Dummy Data Transmission Enable */
1186ab4865bSGeert Uytterhoeven #define SPDCR_SPLW1		0x40	/* Access Width Specification (RZ) */
1196ab4865bSGeert Uytterhoeven #define SPDCR_SPLW0		0x20	/* Access Width Specification (RZ) */
1206ab4865bSGeert Uytterhoeven #define SPDCR_SPLLWORD		(SPDCR_SPLW1 | SPDCR_SPLW0)
1216ab4865bSGeert Uytterhoeven #define SPDCR_SPLWORD		SPDCR_SPLW1
1226ab4865bSGeert Uytterhoeven #define SPDCR_SPLBYTE		SPDCR_SPLW0
1236ab4865bSGeert Uytterhoeven #define SPDCR_SPLW		0x20	/* Access Width Specification (SH) */
1246ab4865bSGeert Uytterhoeven #define SPDCR_SPRDTD		0x10	/* Receive Transmit Data Select */
1250b2182ddSShimoda, Yoshihiro #define SPDCR_SLSEL1		0x08
1260b2182ddSShimoda, Yoshihiro #define SPDCR_SLSEL0		0x04
1276ab4865bSGeert Uytterhoeven #define SPDCR_SLSEL_MASK	0x0c	/* SSL1 Output Select */
1280b2182ddSShimoda, Yoshihiro #define SPDCR_SPFC1		0x02
1290b2182ddSShimoda, Yoshihiro #define SPDCR_SPFC0		0x01
1306ab4865bSGeert Uytterhoeven #define SPDCR_SPFC_MASK		0x03	/* Frame Count Setting (1-4) */
1310b2182ddSShimoda, Yoshihiro 
1326ab4865bSGeert Uytterhoeven /* SPCKD - Clock Delay Register */
1336ab4865bSGeert Uytterhoeven #define SPCKD_SCKDL_MASK	0x07	/* Clock Delay Setting (1-8) */
1340b2182ddSShimoda, Yoshihiro 
1356ab4865bSGeert Uytterhoeven /* SSLND - Slave Select Negation Delay Register */
1366ab4865bSGeert Uytterhoeven #define SSLND_SLNDL_MASK	0x07	/* SSL Negation Delay Setting (1-8) */
1370b2182ddSShimoda, Yoshihiro 
1386ab4865bSGeert Uytterhoeven /* SPND - Next-Access Delay Register */
1396ab4865bSGeert Uytterhoeven #define SPND_SPNDL_MASK		0x07	/* Next-Access Delay Setting (1-8) */
1400b2182ddSShimoda, Yoshihiro 
1416ab4865bSGeert Uytterhoeven /* SPCR2 - Control Register 2 */
1426ab4865bSGeert Uytterhoeven #define SPCR2_PTE		0x08	/* Parity Self-Test Enable */
1436ab4865bSGeert Uytterhoeven #define SPCR2_SPIE		0x04	/* Idle Interrupt Enable */
1446ab4865bSGeert Uytterhoeven #define SPCR2_SPOE		0x02	/* Odd Parity Enable (vs. Even) */
1456ab4865bSGeert Uytterhoeven #define SPCR2_SPPE		0x01	/* Parity Enable */
1460b2182ddSShimoda, Yoshihiro 
1476ab4865bSGeert Uytterhoeven /* SPCMDn - Command Registers */
1486ab4865bSGeert Uytterhoeven #define SPCMD_SCKDEN		0x8000	/* Clock Delay Setting Enable */
1496ab4865bSGeert Uytterhoeven #define SPCMD_SLNDEN		0x4000	/* SSL Negation Delay Setting Enable */
1506ab4865bSGeert Uytterhoeven #define SPCMD_SPNDEN		0x2000	/* Next-Access Delay Enable */
1516ab4865bSGeert Uytterhoeven #define SPCMD_LSBF		0x1000	/* LSB First */
1526ab4865bSGeert Uytterhoeven #define SPCMD_SPB_MASK		0x0f00	/* Data Length Setting */
1530b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_8_TO_16(bit)	(((bit - 1) << 8) & SPCMD_SPB_MASK)
1545ce0ba88SHiep Cao Minh #define SPCMD_SPB_8BIT		0x0000	/* qspi only */
1555ce0ba88SHiep Cao Minh #define SPCMD_SPB_16BIT		0x0100
1560b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_20BIT		0x0000
1570b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_24BIT		0x0100
1580b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_32BIT		0x0200
1596ab4865bSGeert Uytterhoeven #define SPCMD_SSLKP		0x0080	/* SSL Signal Level Keeping */
160fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_MASK	0x0060	/* SPI Operating Mode (QSPI only) */
161fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD1		0x0040
162fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD0		0x0020
163fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_SINGLE	0
164fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_DUAL	SPCMD_SPIMOD0
165fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_QUAD	SPCMD_SPIMOD1
166fbe5072bSGeert Uytterhoeven #define SPCMD_SPRW		0x0010	/* SPI Read/Write Access (Dual/Quad) */
1676ab4865bSGeert Uytterhoeven #define SPCMD_SSLA_MASK		0x0030	/* SSL Assert Signal Setting (RSPI) */
1686ab4865bSGeert Uytterhoeven #define SPCMD_BRDV_MASK		0x000c	/* Bit Rate Division Setting */
1696ab4865bSGeert Uytterhoeven #define SPCMD_CPOL		0x0002	/* Clock Polarity Setting */
1706ab4865bSGeert Uytterhoeven #define SPCMD_CPHA		0x0001	/* Clock Phase Setting */
1710b2182ddSShimoda, Yoshihiro 
1726ab4865bSGeert Uytterhoeven /* SPBFCR - Buffer Control Register */
1736ab4865bSGeert Uytterhoeven #define SPBFCR_TXRST		0x80	/* Transmit Buffer Data Reset (qspi only) */
1746ab4865bSGeert Uytterhoeven #define SPBFCR_RXRST		0x40	/* Receive Buffer Data Reset (qspi only) */
1756ab4865bSGeert Uytterhoeven #define SPBFCR_TXTRG_MASK	0x30	/* Transmit Buffer Data Triggering Number */
1766ab4865bSGeert Uytterhoeven #define SPBFCR_RXTRG_MASK	0x07	/* Receive Buffer Data Triggering Number */
1775ce0ba88SHiep Cao Minh 
1782aae80b2SGeert Uytterhoeven #define DUMMY_DATA		0x00
1792aae80b2SGeert Uytterhoeven 
1800b2182ddSShimoda, Yoshihiro struct rspi_data {
1810b2182ddSShimoda, Yoshihiro 	void __iomem *addr;
1820b2182ddSShimoda, Yoshihiro 	u32 max_speed_hz;
1830b2182ddSShimoda, Yoshihiro 	struct spi_master *master;
1840b2182ddSShimoda, Yoshihiro 	struct list_head queue;
1850b2182ddSShimoda, Yoshihiro 	struct work_struct ws;
1860b2182ddSShimoda, Yoshihiro 	wait_queue_head_t wait;
1870b2182ddSShimoda, Yoshihiro 	spinlock_t lock;
1880b2182ddSShimoda, Yoshihiro 	struct clk *clk;
18997b95c11SGeert Uytterhoeven 	u8 spsr;
190348e5153SGeert Uytterhoeven 	u16 spcmd;
1915ce0ba88SHiep Cao Minh 	const struct spi_ops *ops;
192a3633fe7SShimoda, Yoshihiro 
193a3633fe7SShimoda, Yoshihiro 	/* for dmaengine */
194a3633fe7SShimoda, Yoshihiro 	struct dma_chan *chan_tx;
195a3633fe7SShimoda, Yoshihiro 	struct dma_chan *chan_rx;
196a3633fe7SShimoda, Yoshihiro 	int irq;
197a3633fe7SShimoda, Yoshihiro 
198a3633fe7SShimoda, Yoshihiro 	unsigned dma_width_16bit:1;
199a3633fe7SShimoda, Yoshihiro 	unsigned dma_callbacked:1;
2000b2182ddSShimoda, Yoshihiro };
2010b2182ddSShimoda, Yoshihiro 
202baf588f4SGeert Uytterhoeven static void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset)
2030b2182ddSShimoda, Yoshihiro {
2040b2182ddSShimoda, Yoshihiro 	iowrite8(data, rspi->addr + offset);
2050b2182ddSShimoda, Yoshihiro }
2060b2182ddSShimoda, Yoshihiro 
207baf588f4SGeert Uytterhoeven static void rspi_write16(const struct rspi_data *rspi, u16 data, u16 offset)
2080b2182ddSShimoda, Yoshihiro {
2090b2182ddSShimoda, Yoshihiro 	iowrite16(data, rspi->addr + offset);
2100b2182ddSShimoda, Yoshihiro }
2110b2182ddSShimoda, Yoshihiro 
212baf588f4SGeert Uytterhoeven static void rspi_write32(const struct rspi_data *rspi, u32 data, u16 offset)
2135ce0ba88SHiep Cao Minh {
2145ce0ba88SHiep Cao Minh 	iowrite32(data, rspi->addr + offset);
2155ce0ba88SHiep Cao Minh }
2165ce0ba88SHiep Cao Minh 
217baf588f4SGeert Uytterhoeven static u8 rspi_read8(const struct rspi_data *rspi, u16 offset)
2180b2182ddSShimoda, Yoshihiro {
2190b2182ddSShimoda, Yoshihiro 	return ioread8(rspi->addr + offset);
2200b2182ddSShimoda, Yoshihiro }
2210b2182ddSShimoda, Yoshihiro 
222baf588f4SGeert Uytterhoeven static u16 rspi_read16(const struct rspi_data *rspi, u16 offset)
2230b2182ddSShimoda, Yoshihiro {
2240b2182ddSShimoda, Yoshihiro 	return ioread16(rspi->addr + offset);
2250b2182ddSShimoda, Yoshihiro }
2260b2182ddSShimoda, Yoshihiro 
2275ce0ba88SHiep Cao Minh /* optional functions */
2285ce0ba88SHiep Cao Minh struct spi_ops {
229baf588f4SGeert Uytterhoeven 	int (*set_config_register)(const struct rspi_data *rspi,
230baf588f4SGeert Uytterhoeven 				   int access_size);
231cb52c673SHiep Cao Minh 	int (*send_pio)(struct rspi_data *rspi, struct spi_message *mesg,
232cb52c673SHiep Cao Minh 			struct spi_transfer *t);
233cb52c673SHiep Cao Minh 	int (*receive_pio)(struct rspi_data *rspi, struct spi_message *mesg,
234cb52c673SHiep Cao Minh 			   struct spi_transfer *t);
235cb52c673SHiep Cao Minh 
2365ce0ba88SHiep Cao Minh };
2375ce0ba88SHiep Cao Minh 
2385ce0ba88SHiep Cao Minh /*
2395ce0ba88SHiep Cao Minh  * functions for RSPI
2405ce0ba88SHiep Cao Minh  */
241baf588f4SGeert Uytterhoeven static int rspi_set_config_register(const struct rspi_data *rspi,
242baf588f4SGeert Uytterhoeven 				    int access_size)
2430b2182ddSShimoda, Yoshihiro {
2445ce0ba88SHiep Cao Minh 	int spbr;
2450b2182ddSShimoda, Yoshihiro 
2465ce0ba88SHiep Cao Minh 	/* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
2475ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPPCR);
2480b2182ddSShimoda, Yoshihiro 
2495ce0ba88SHiep Cao Minh 	/* Sets transfer bit rate */
2505ce0ba88SHiep Cao Minh 	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
2515ce0ba88SHiep Cao Minh 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
2525ce0ba88SHiep Cao Minh 
2535ce0ba88SHiep Cao Minh 	/* Sets number of frames to be used: 1 frame */
2545ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPDCR);
2555ce0ba88SHiep Cao Minh 
2565ce0ba88SHiep Cao Minh 	/* Sets RSPCK, SSL, next-access delay value */
2575ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
2585ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SSLND);
2595ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPND);
2605ce0ba88SHiep Cao Minh 
2615ce0ba88SHiep Cao Minh 	/* Sets parity, interrupt mask */
2625ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCR2);
2635ce0ba88SHiep Cao Minh 
2645ce0ba88SHiep Cao Minh 	/* Sets SPCMD */
265348e5153SGeert Uytterhoeven 	rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | rspi->spcmd,
2665ce0ba88SHiep Cao Minh 		     RSPI_SPCMD0);
2675ce0ba88SHiep Cao Minh 
2685ce0ba88SHiep Cao Minh 	/* Sets RSPI mode */
2695ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
2705ce0ba88SHiep Cao Minh 
2715ce0ba88SHiep Cao Minh 	return 0;
2720b2182ddSShimoda, Yoshihiro }
2730b2182ddSShimoda, Yoshihiro 
2745ce0ba88SHiep Cao Minh /*
2755ce0ba88SHiep Cao Minh  * functions for QSPI
2765ce0ba88SHiep Cao Minh  */
277baf588f4SGeert Uytterhoeven static int qspi_set_config_register(const struct rspi_data *rspi,
278baf588f4SGeert Uytterhoeven 				    int access_size)
2795ce0ba88SHiep Cao Minh {
2805ce0ba88SHiep Cao Minh 	u16 spcmd;
2815ce0ba88SHiep Cao Minh 	int spbr;
2825ce0ba88SHiep Cao Minh 
2835ce0ba88SHiep Cao Minh 	/* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
2845ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPPCR);
2855ce0ba88SHiep Cao Minh 
2865ce0ba88SHiep Cao Minh 	/* Sets transfer bit rate */
2875ce0ba88SHiep Cao Minh 	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz);
2885ce0ba88SHiep Cao Minh 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
2895ce0ba88SHiep Cao Minh 
2905ce0ba88SHiep Cao Minh 	/* Sets number of frames to be used: 1 frame */
2915ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPDCR);
2925ce0ba88SHiep Cao Minh 
2935ce0ba88SHiep Cao Minh 	/* Sets RSPCK, SSL, next-access delay value */
2945ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
2955ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SSLND);
2965ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPND);
2975ce0ba88SHiep Cao Minh 
2985ce0ba88SHiep Cao Minh 	/* Data Length Setting */
2995ce0ba88SHiep Cao Minh 	if (access_size == 8)
3005ce0ba88SHiep Cao Minh 		spcmd = SPCMD_SPB_8BIT;
3015ce0ba88SHiep Cao Minh 	else if (access_size == 16)
3025ce0ba88SHiep Cao Minh 		spcmd = SPCMD_SPB_16BIT;
3035ce0ba88SHiep Cao Minh 	else if (access_size == 32)
3045ce0ba88SHiep Cao Minh 		spcmd = SPCMD_SPB_32BIT;
3055ce0ba88SHiep Cao Minh 
306348e5153SGeert Uytterhoeven 	spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | rspi->spcmd | SPCMD_SPNDEN;
3075ce0ba88SHiep Cao Minh 
3085ce0ba88SHiep Cao Minh 	/* Resets transfer data length */
3095ce0ba88SHiep Cao Minh 	rspi_write32(rspi, 0, QSPI_SPBMUL0);
3105ce0ba88SHiep Cao Minh 
3115ce0ba88SHiep Cao Minh 	/* Resets transmit and receive buffer */
3125ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
3135ce0ba88SHiep Cao Minh 	/* Sets buffer to allow normal operation */
3145ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
3155ce0ba88SHiep Cao Minh 
3165ce0ba88SHiep Cao Minh 	/* Sets SPCMD */
3175ce0ba88SHiep Cao Minh 	rspi_write16(rspi, spcmd, RSPI_SPCMD0);
3185ce0ba88SHiep Cao Minh 
3195ce0ba88SHiep Cao Minh 	/* Enables SPI function in a master mode */
3205ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR);
3215ce0ba88SHiep Cao Minh 
3225ce0ba88SHiep Cao Minh 	return 0;
3235ce0ba88SHiep Cao Minh }
3245ce0ba88SHiep Cao Minh 
3255ce0ba88SHiep Cao Minh #define set_config_register(spi, n) spi->ops->set_config_register(spi, n)
3265ce0ba88SHiep Cao Minh 
327baf588f4SGeert Uytterhoeven static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable)
3280b2182ddSShimoda, Yoshihiro {
3290b2182ddSShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR);
3300b2182ddSShimoda, Yoshihiro }
3310b2182ddSShimoda, Yoshihiro 
332baf588f4SGeert Uytterhoeven static void rspi_disable_irq(const struct rspi_data *rspi, u8 disable)
3330b2182ddSShimoda, Yoshihiro {
3340b2182ddSShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~disable, RSPI_SPCR);
3350b2182ddSShimoda, Yoshihiro }
3360b2182ddSShimoda, Yoshihiro 
3370b2182ddSShimoda, Yoshihiro static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
3380b2182ddSShimoda, Yoshihiro 				   u8 enable_bit)
3390b2182ddSShimoda, Yoshihiro {
3400b2182ddSShimoda, Yoshihiro 	int ret;
3410b2182ddSShimoda, Yoshihiro 
3420b2182ddSShimoda, Yoshihiro 	rspi->spsr = rspi_read8(rspi, RSPI_SPSR);
3430b2182ddSShimoda, Yoshihiro 	rspi_enable_irq(rspi, enable_bit);
3440b2182ddSShimoda, Yoshihiro 	ret = wait_event_timeout(rspi->wait, rspi->spsr & wait_mask, HZ);
3450b2182ddSShimoda, Yoshihiro 	if (ret == 0 && !(rspi->spsr & wait_mask))
3460b2182ddSShimoda, Yoshihiro 		return -ETIMEDOUT;
3470b2182ddSShimoda, Yoshihiro 
3480b2182ddSShimoda, Yoshihiro 	return 0;
3490b2182ddSShimoda, Yoshihiro }
3500b2182ddSShimoda, Yoshihiro 
351baf588f4SGeert Uytterhoeven static void rspi_assert_ssl(const struct rspi_data *rspi)
3520b2182ddSShimoda, Yoshihiro {
3530b2182ddSShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
3540b2182ddSShimoda, Yoshihiro }
3550b2182ddSShimoda, Yoshihiro 
356baf588f4SGeert Uytterhoeven static void rspi_negate_ssl(const struct rspi_data *rspi)
3570b2182ddSShimoda, Yoshihiro {
3580b2182ddSShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
3590b2182ddSShimoda, Yoshihiro }
3600b2182ddSShimoda, Yoshihiro 
3610b2182ddSShimoda, Yoshihiro static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
3620b2182ddSShimoda, Yoshihiro 			 struct spi_transfer *t)
3630b2182ddSShimoda, Yoshihiro {
3640b2182ddSShimoda, Yoshihiro 	int remain = t->len;
365c132f094SGeert Uytterhoeven 	const u8 *data = t->tx_buf;
3660b2182ddSShimoda, Yoshihiro 	while (remain > 0) {
3670b2182ddSShimoda, Yoshihiro 		rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD,
3680b2182ddSShimoda, Yoshihiro 			    RSPI_SPCR);
3690b2182ddSShimoda, Yoshihiro 
3700b2182ddSShimoda, Yoshihiro 		if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
3710b2182ddSShimoda, Yoshihiro 			dev_err(&rspi->master->dev,
3720b2182ddSShimoda, Yoshihiro 				"%s: tx empty timeout\n", __func__);
3730b2182ddSShimoda, Yoshihiro 			return -ETIMEDOUT;
3740b2182ddSShimoda, Yoshihiro 		}
3750b2182ddSShimoda, Yoshihiro 
3760b2182ddSShimoda, Yoshihiro 		rspi_write16(rspi, *data, RSPI_SPDR);
3770b2182ddSShimoda, Yoshihiro 		data++;
3780b2182ddSShimoda, Yoshihiro 		remain--;
3790b2182ddSShimoda, Yoshihiro 	}
3800b2182ddSShimoda, Yoshihiro 
3810b2182ddSShimoda, Yoshihiro 	/* Waiting for the last transmition */
3820b2182ddSShimoda, Yoshihiro 	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
3830b2182ddSShimoda, Yoshihiro 
3840b2182ddSShimoda, Yoshihiro 	return 0;
3850b2182ddSShimoda, Yoshihiro }
3860b2182ddSShimoda, Yoshihiro 
387cb52c673SHiep Cao Minh static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
388cb52c673SHiep Cao Minh 			 struct spi_transfer *t)
389cb52c673SHiep Cao Minh {
390cb52c673SHiep Cao Minh 	int remain = t->len;
391c132f094SGeert Uytterhoeven 	const u8 *data = t->tx_buf;
392cb52c673SHiep Cao Minh 
393cb52c673SHiep Cao Minh 	rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR);
394cb52c673SHiep Cao Minh 	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
395cb52c673SHiep Cao Minh 
396cb52c673SHiep Cao Minh 	while (remain > 0) {
397cb52c673SHiep Cao Minh 
398cb52c673SHiep Cao Minh 		if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
399cb52c673SHiep Cao Minh 			dev_err(&rspi->master->dev,
400cb52c673SHiep Cao Minh 				"%s: tx empty timeout\n", __func__);
401cb52c673SHiep Cao Minh 			return -ETIMEDOUT;
402cb52c673SHiep Cao Minh 		}
403cb52c673SHiep Cao Minh 		rspi_write8(rspi, *data++, RSPI_SPDR);
404cb52c673SHiep Cao Minh 
405cb52c673SHiep Cao Minh 		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
406cb52c673SHiep Cao Minh 			dev_err(&rspi->master->dev,
407cb52c673SHiep Cao Minh 				"%s: receive timeout\n", __func__);
408cb52c673SHiep Cao Minh 			return -ETIMEDOUT;
409cb52c673SHiep Cao Minh 		}
410cb52c673SHiep Cao Minh 		rspi_read8(rspi, RSPI_SPDR);
411cb52c673SHiep Cao Minh 
412cb52c673SHiep Cao Minh 		remain--;
413cb52c673SHiep Cao Minh 	}
414cb52c673SHiep Cao Minh 
415cb52c673SHiep Cao Minh 	/* Waiting for the last transmition */
416cb52c673SHiep Cao Minh 	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
417cb52c673SHiep Cao Minh 
418cb52c673SHiep Cao Minh 	return 0;
419cb52c673SHiep Cao Minh }
420cb52c673SHiep Cao Minh 
421cb52c673SHiep Cao Minh #define send_pio(spi, mesg, t) spi->ops->send_pio(spi, mesg, t)
422cb52c673SHiep Cao Minh 
423a3633fe7SShimoda, Yoshihiro static void rspi_dma_complete(void *arg)
4240b2182ddSShimoda, Yoshihiro {
425a3633fe7SShimoda, Yoshihiro 	struct rspi_data *rspi = arg;
426a3633fe7SShimoda, Yoshihiro 
427a3633fe7SShimoda, Yoshihiro 	rspi->dma_callbacked = 1;
428a3633fe7SShimoda, Yoshihiro 	wake_up_interruptible(&rspi->wait);
429a3633fe7SShimoda, Yoshihiro }
430a3633fe7SShimoda, Yoshihiro 
431c132f094SGeert Uytterhoeven static int rspi_dma_map_sg(struct scatterlist *sg, const void *buf,
432c132f094SGeert Uytterhoeven 			   unsigned len, struct dma_chan *chan,
433a3633fe7SShimoda, Yoshihiro 			   enum dma_transfer_direction dir)
434a3633fe7SShimoda, Yoshihiro {
435a3633fe7SShimoda, Yoshihiro 	sg_init_table(sg, 1);
436a3633fe7SShimoda, Yoshihiro 	sg_set_buf(sg, buf, len);
437a3633fe7SShimoda, Yoshihiro 	sg_dma_len(sg) = len;
438a3633fe7SShimoda, Yoshihiro 	return dma_map_sg(chan->device->dev, sg, 1, dir);
439a3633fe7SShimoda, Yoshihiro }
440a3633fe7SShimoda, Yoshihiro 
441a3633fe7SShimoda, Yoshihiro static void rspi_dma_unmap_sg(struct scatterlist *sg, struct dma_chan *chan,
442a3633fe7SShimoda, Yoshihiro 			      enum dma_transfer_direction dir)
443a3633fe7SShimoda, Yoshihiro {
444a3633fe7SShimoda, Yoshihiro 	dma_unmap_sg(chan->device->dev, sg, 1, dir);
445a3633fe7SShimoda, Yoshihiro }
446a3633fe7SShimoda, Yoshihiro 
447a3633fe7SShimoda, Yoshihiro static void rspi_memory_to_8bit(void *buf, const void *data, unsigned len)
448a3633fe7SShimoda, Yoshihiro {
449a3633fe7SShimoda, Yoshihiro 	u16 *dst = buf;
450a3633fe7SShimoda, Yoshihiro 	const u8 *src = data;
451a3633fe7SShimoda, Yoshihiro 
452a3633fe7SShimoda, Yoshihiro 	while (len) {
453a3633fe7SShimoda, Yoshihiro 		*dst++ = (u16)(*src++);
454a3633fe7SShimoda, Yoshihiro 		len--;
455a3633fe7SShimoda, Yoshihiro 	}
456a3633fe7SShimoda, Yoshihiro }
457a3633fe7SShimoda, Yoshihiro 
458a3633fe7SShimoda, Yoshihiro static void rspi_memory_from_8bit(void *buf, const void *data, unsigned len)
459a3633fe7SShimoda, Yoshihiro {
460a3633fe7SShimoda, Yoshihiro 	u8 *dst = buf;
461a3633fe7SShimoda, Yoshihiro 	const u16 *src = data;
462a3633fe7SShimoda, Yoshihiro 
463a3633fe7SShimoda, Yoshihiro 	while (len) {
464a3633fe7SShimoda, Yoshihiro 		*dst++ = (u8)*src++;
465a3633fe7SShimoda, Yoshihiro 		len--;
466a3633fe7SShimoda, Yoshihiro 	}
467a3633fe7SShimoda, Yoshihiro }
468a3633fe7SShimoda, Yoshihiro 
469a3633fe7SShimoda, Yoshihiro static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
470a3633fe7SShimoda, Yoshihiro {
471a3633fe7SShimoda, Yoshihiro 	struct scatterlist sg;
472c132f094SGeert Uytterhoeven 	const void *buf = NULL;
473a3633fe7SShimoda, Yoshihiro 	struct dma_async_tx_descriptor *desc;
474a3633fe7SShimoda, Yoshihiro 	unsigned len;
475a3633fe7SShimoda, Yoshihiro 	int ret = 0;
476a3633fe7SShimoda, Yoshihiro 
477a3633fe7SShimoda, Yoshihiro 	if (rspi->dma_width_16bit) {
478c132f094SGeert Uytterhoeven 		void *tmp;
479a3633fe7SShimoda, Yoshihiro 		/*
480a3633fe7SShimoda, Yoshihiro 		 * If DMAC bus width is 16-bit, the driver allocates a dummy
481a3633fe7SShimoda, Yoshihiro 		 * buffer. And, the driver converts original data into the
482a3633fe7SShimoda, Yoshihiro 		 * DMAC data as the following format:
483a3633fe7SShimoda, Yoshihiro 		 *  original data: 1st byte, 2nd byte ...
484a3633fe7SShimoda, Yoshihiro 		 *  DMAC data:     1st byte, dummy, 2nd byte, dummy ...
485a3633fe7SShimoda, Yoshihiro 		 */
486a3633fe7SShimoda, Yoshihiro 		len = t->len * 2;
487c132f094SGeert Uytterhoeven 		tmp = kmalloc(len, GFP_KERNEL);
488c132f094SGeert Uytterhoeven 		if (!tmp)
489a3633fe7SShimoda, Yoshihiro 			return -ENOMEM;
490c132f094SGeert Uytterhoeven 		rspi_memory_to_8bit(tmp, t->tx_buf, t->len);
491c132f094SGeert Uytterhoeven 		buf = tmp;
492a3633fe7SShimoda, Yoshihiro 	} else {
493a3633fe7SShimoda, Yoshihiro 		len = t->len;
494c132f094SGeert Uytterhoeven 		buf = t->tx_buf;
495a3633fe7SShimoda, Yoshihiro 	}
496a3633fe7SShimoda, Yoshihiro 
497a3633fe7SShimoda, Yoshihiro 	if (!rspi_dma_map_sg(&sg, buf, len, rspi->chan_tx, DMA_TO_DEVICE)) {
498a3633fe7SShimoda, Yoshihiro 		ret = -EFAULT;
499a3633fe7SShimoda, Yoshihiro 		goto end_nomap;
500a3633fe7SShimoda, Yoshihiro 	}
501a3633fe7SShimoda, Yoshihiro 	desc = dmaengine_prep_slave_sg(rspi->chan_tx, &sg, 1, DMA_TO_DEVICE,
502a3633fe7SShimoda, Yoshihiro 				       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
503a3633fe7SShimoda, Yoshihiro 	if (!desc) {
504a3633fe7SShimoda, Yoshihiro 		ret = -EIO;
505a3633fe7SShimoda, Yoshihiro 		goto end;
506a3633fe7SShimoda, Yoshihiro 	}
507a3633fe7SShimoda, Yoshihiro 
508a3633fe7SShimoda, Yoshihiro 	/*
509a3633fe7SShimoda, Yoshihiro 	 * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
510a3633fe7SShimoda, Yoshihiro 	 * called. So, this driver disables the IRQ while DMA transfer.
511a3633fe7SShimoda, Yoshihiro 	 */
512a3633fe7SShimoda, Yoshihiro 	disable_irq(rspi->irq);
513a3633fe7SShimoda, Yoshihiro 
514a3633fe7SShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD, RSPI_SPCR);
515a3633fe7SShimoda, Yoshihiro 	rspi_enable_irq(rspi, SPCR_SPTIE);
516a3633fe7SShimoda, Yoshihiro 	rspi->dma_callbacked = 0;
517a3633fe7SShimoda, Yoshihiro 
518a3633fe7SShimoda, Yoshihiro 	desc->callback = rspi_dma_complete;
519a3633fe7SShimoda, Yoshihiro 	desc->callback_param = rspi;
520a3633fe7SShimoda, Yoshihiro 	dmaengine_submit(desc);
521a3633fe7SShimoda, Yoshihiro 	dma_async_issue_pending(rspi->chan_tx);
522a3633fe7SShimoda, Yoshihiro 
523a3633fe7SShimoda, Yoshihiro 	ret = wait_event_interruptible_timeout(rspi->wait,
524a3633fe7SShimoda, Yoshihiro 					       rspi->dma_callbacked, HZ);
525a3633fe7SShimoda, Yoshihiro 	if (ret > 0 && rspi->dma_callbacked)
526a3633fe7SShimoda, Yoshihiro 		ret = 0;
527a3633fe7SShimoda, Yoshihiro 	else if (!ret)
528a3633fe7SShimoda, Yoshihiro 		ret = -ETIMEDOUT;
529a3633fe7SShimoda, Yoshihiro 	rspi_disable_irq(rspi, SPCR_SPTIE);
530a3633fe7SShimoda, Yoshihiro 
531a3633fe7SShimoda, Yoshihiro 	enable_irq(rspi->irq);
532a3633fe7SShimoda, Yoshihiro 
533a3633fe7SShimoda, Yoshihiro end:
534a3633fe7SShimoda, Yoshihiro 	rspi_dma_unmap_sg(&sg, rspi->chan_tx, DMA_TO_DEVICE);
535a3633fe7SShimoda, Yoshihiro end_nomap:
536a3633fe7SShimoda, Yoshihiro 	if (rspi->dma_width_16bit)
537a3633fe7SShimoda, Yoshihiro 		kfree(buf);
538a3633fe7SShimoda, Yoshihiro 
539a3633fe7SShimoda, Yoshihiro 	return ret;
540a3633fe7SShimoda, Yoshihiro }
541a3633fe7SShimoda, Yoshihiro 
542baf588f4SGeert Uytterhoeven static void rspi_receive_init(const struct rspi_data *rspi)
543a3633fe7SShimoda, Yoshihiro {
54497b95c11SGeert Uytterhoeven 	u8 spsr;
5450b2182ddSShimoda, Yoshihiro 
5460b2182ddSShimoda, Yoshihiro 	spsr = rspi_read8(rspi, RSPI_SPSR);
5470b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPRF)
5480b2182ddSShimoda, Yoshihiro 		rspi_read16(rspi, RSPI_SPDR);	/* dummy read */
5490b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_OVRF)
5500b2182ddSShimoda, Yoshihiro 		rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF,
5510b2182ddSShimoda, Yoshihiro 			    RSPI_SPCR);
552a3633fe7SShimoda, Yoshihiro }
553a3633fe7SShimoda, Yoshihiro 
554a3633fe7SShimoda, Yoshihiro static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
555a3633fe7SShimoda, Yoshihiro 			    struct spi_transfer *t)
556a3633fe7SShimoda, Yoshihiro {
557a3633fe7SShimoda, Yoshihiro 	int remain = t->len;
558a3633fe7SShimoda, Yoshihiro 	u8 *data;
559a3633fe7SShimoda, Yoshihiro 
560a3633fe7SShimoda, Yoshihiro 	rspi_receive_init(rspi);
5610b2182ddSShimoda, Yoshihiro 
562c132f094SGeert Uytterhoeven 	data = t->rx_buf;
5630b2182ddSShimoda, Yoshihiro 	while (remain > 0) {
5640b2182ddSShimoda, Yoshihiro 		rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD,
5650b2182ddSShimoda, Yoshihiro 			    RSPI_SPCR);
5660b2182ddSShimoda, Yoshihiro 
5670b2182ddSShimoda, Yoshihiro 		if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
5680b2182ddSShimoda, Yoshihiro 			dev_err(&rspi->master->dev,
5690b2182ddSShimoda, Yoshihiro 				"%s: tx empty timeout\n", __func__);
5700b2182ddSShimoda, Yoshihiro 			return -ETIMEDOUT;
5710b2182ddSShimoda, Yoshihiro 		}
5720b2182ddSShimoda, Yoshihiro 		/* dummy write for generate clock */
5732aae80b2SGeert Uytterhoeven 		rspi_write16(rspi, DUMMY_DATA, RSPI_SPDR);
5740b2182ddSShimoda, Yoshihiro 
5750b2182ddSShimoda, Yoshihiro 		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
5760b2182ddSShimoda, Yoshihiro 			dev_err(&rspi->master->dev,
5770b2182ddSShimoda, Yoshihiro 				"%s: receive timeout\n", __func__);
5780b2182ddSShimoda, Yoshihiro 			return -ETIMEDOUT;
5790b2182ddSShimoda, Yoshihiro 		}
5800b2182ddSShimoda, Yoshihiro 		/* SPDR allows 16 or 32-bit access only */
5810b2182ddSShimoda, Yoshihiro 		*data = (u8)rspi_read16(rspi, RSPI_SPDR);
5820b2182ddSShimoda, Yoshihiro 
5830b2182ddSShimoda, Yoshihiro 		data++;
5840b2182ddSShimoda, Yoshihiro 		remain--;
5850b2182ddSShimoda, Yoshihiro 	}
5860b2182ddSShimoda, Yoshihiro 
5870b2182ddSShimoda, Yoshihiro 	return 0;
5880b2182ddSShimoda, Yoshihiro }
5890b2182ddSShimoda, Yoshihiro 
590baf588f4SGeert Uytterhoeven static void qspi_receive_init(const struct rspi_data *rspi)
591cb52c673SHiep Cao Minh {
59297b95c11SGeert Uytterhoeven 	u8 spsr;
593cb52c673SHiep Cao Minh 
594cb52c673SHiep Cao Minh 	spsr = rspi_read8(rspi, RSPI_SPSR);
595cb52c673SHiep Cao Minh 	if (spsr & SPSR_SPRF)
596cb52c673SHiep Cao Minh 		rspi_read8(rspi, RSPI_SPDR);   /* dummy read */
597cb52c673SHiep Cao Minh 	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
598cb52c673SHiep Cao Minh 	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
599cb52c673SHiep Cao Minh }
600cb52c673SHiep Cao Minh 
601cb52c673SHiep Cao Minh static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
602cb52c673SHiep Cao Minh 			    struct spi_transfer *t)
603cb52c673SHiep Cao Minh {
604cb52c673SHiep Cao Minh 	int remain = t->len;
605cb52c673SHiep Cao Minh 	u8 *data;
606cb52c673SHiep Cao Minh 
607cb52c673SHiep Cao Minh 	qspi_receive_init(rspi);
608cb52c673SHiep Cao Minh 
609c132f094SGeert Uytterhoeven 	data = t->rx_buf;
610cb52c673SHiep Cao Minh 	while (remain > 0) {
611cb52c673SHiep Cao Minh 
612cb52c673SHiep Cao Minh 		if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
613cb52c673SHiep Cao Minh 			dev_err(&rspi->master->dev,
614cb52c673SHiep Cao Minh 				"%s: tx empty timeout\n", __func__);
615cb52c673SHiep Cao Minh 			return -ETIMEDOUT;
616cb52c673SHiep Cao Minh 		}
617cb52c673SHiep Cao Minh 		/* dummy write for generate clock */
6182aae80b2SGeert Uytterhoeven 		rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR);
619cb52c673SHiep Cao Minh 
620cb52c673SHiep Cao Minh 		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
621cb52c673SHiep Cao Minh 			dev_err(&rspi->master->dev,
622cb52c673SHiep Cao Minh 				"%s: receive timeout\n", __func__);
623cb52c673SHiep Cao Minh 			return -ETIMEDOUT;
624cb52c673SHiep Cao Minh 		}
625cb52c673SHiep Cao Minh 		/* SPDR allows 8, 16 or 32-bit access */
626cb52c673SHiep Cao Minh 		*data++ = rspi_read8(rspi, RSPI_SPDR);
627cb52c673SHiep Cao Minh 		remain--;
628cb52c673SHiep Cao Minh 	}
629cb52c673SHiep Cao Minh 
630cb52c673SHiep Cao Minh 	return 0;
631cb52c673SHiep Cao Minh }
632cb52c673SHiep Cao Minh 
633cb52c673SHiep Cao Minh #define receive_pio(spi, mesg, t) spi->ops->receive_pio(spi, mesg, t)
634cb52c673SHiep Cao Minh 
635a3633fe7SShimoda, Yoshihiro static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
636a3633fe7SShimoda, Yoshihiro {
637a3633fe7SShimoda, Yoshihiro 	struct scatterlist sg, sg_dummy;
638a3633fe7SShimoda, Yoshihiro 	void *dummy = NULL, *rx_buf = NULL;
639a3633fe7SShimoda, Yoshihiro 	struct dma_async_tx_descriptor *desc, *desc_dummy;
640a3633fe7SShimoda, Yoshihiro 	unsigned len;
641a3633fe7SShimoda, Yoshihiro 	int ret = 0;
642a3633fe7SShimoda, Yoshihiro 
643a3633fe7SShimoda, Yoshihiro 	if (rspi->dma_width_16bit) {
644a3633fe7SShimoda, Yoshihiro 		/*
645a3633fe7SShimoda, Yoshihiro 		 * If DMAC bus width is 16-bit, the driver allocates a dummy
646a3633fe7SShimoda, Yoshihiro 		 * buffer. And, finally the driver converts the DMAC data into
647a3633fe7SShimoda, Yoshihiro 		 * actual data as the following format:
648a3633fe7SShimoda, Yoshihiro 		 *  DMAC data:   1st byte, dummy, 2nd byte, dummy ...
649a3633fe7SShimoda, Yoshihiro 		 *  actual data: 1st byte, 2nd byte ...
650a3633fe7SShimoda, Yoshihiro 		 */
651a3633fe7SShimoda, Yoshihiro 		len = t->len * 2;
652a3633fe7SShimoda, Yoshihiro 		rx_buf = kmalloc(len, GFP_KERNEL);
653a3633fe7SShimoda, Yoshihiro 		if (!rx_buf)
654a3633fe7SShimoda, Yoshihiro 			return -ENOMEM;
655a3633fe7SShimoda, Yoshihiro 	 } else {
656a3633fe7SShimoda, Yoshihiro 		len = t->len;
657a3633fe7SShimoda, Yoshihiro 		rx_buf = t->rx_buf;
658a3633fe7SShimoda, Yoshihiro 	}
659a3633fe7SShimoda, Yoshihiro 
660a3633fe7SShimoda, Yoshihiro 	/* prepare dummy transfer to generate SPI clocks */
661a3633fe7SShimoda, Yoshihiro 	dummy = kzalloc(len, GFP_KERNEL);
662a3633fe7SShimoda, Yoshihiro 	if (!dummy) {
663a3633fe7SShimoda, Yoshihiro 		ret = -ENOMEM;
664a3633fe7SShimoda, Yoshihiro 		goto end_nomap;
665a3633fe7SShimoda, Yoshihiro 	}
666a3633fe7SShimoda, Yoshihiro 	if (!rspi_dma_map_sg(&sg_dummy, dummy, len, rspi->chan_tx,
667a3633fe7SShimoda, Yoshihiro 			     DMA_TO_DEVICE)) {
668a3633fe7SShimoda, Yoshihiro 		ret = -EFAULT;
669a3633fe7SShimoda, Yoshihiro 		goto end_nomap;
670a3633fe7SShimoda, Yoshihiro 	}
671a3633fe7SShimoda, Yoshihiro 	desc_dummy = dmaengine_prep_slave_sg(rspi->chan_tx, &sg_dummy, 1,
672a3633fe7SShimoda, Yoshihiro 			DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
673a3633fe7SShimoda, Yoshihiro 	if (!desc_dummy) {
674a3633fe7SShimoda, Yoshihiro 		ret = -EIO;
675a3633fe7SShimoda, Yoshihiro 		goto end_dummy_mapped;
676a3633fe7SShimoda, Yoshihiro 	}
677a3633fe7SShimoda, Yoshihiro 
678a3633fe7SShimoda, Yoshihiro 	/* prepare receive transfer */
679a3633fe7SShimoda, Yoshihiro 	if (!rspi_dma_map_sg(&sg, rx_buf, len, rspi->chan_rx,
680a3633fe7SShimoda, Yoshihiro 			     DMA_FROM_DEVICE)) {
681a3633fe7SShimoda, Yoshihiro 		ret = -EFAULT;
682a3633fe7SShimoda, Yoshihiro 		goto end_dummy_mapped;
683a3633fe7SShimoda, Yoshihiro 
684a3633fe7SShimoda, Yoshihiro 	}
685a3633fe7SShimoda, Yoshihiro 	desc = dmaengine_prep_slave_sg(rspi->chan_rx, &sg, 1, DMA_FROM_DEVICE,
686a3633fe7SShimoda, Yoshihiro 				       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
687a3633fe7SShimoda, Yoshihiro 	if (!desc) {
688a3633fe7SShimoda, Yoshihiro 		ret = -EIO;
689a3633fe7SShimoda, Yoshihiro 		goto end;
690a3633fe7SShimoda, Yoshihiro 	}
691a3633fe7SShimoda, Yoshihiro 
692a3633fe7SShimoda, Yoshihiro 	rspi_receive_init(rspi);
693a3633fe7SShimoda, Yoshihiro 
694a3633fe7SShimoda, Yoshihiro 	/*
695a3633fe7SShimoda, Yoshihiro 	 * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
696a3633fe7SShimoda, Yoshihiro 	 * called. So, this driver disables the IRQ while DMA transfer.
697a3633fe7SShimoda, Yoshihiro 	 */
698a3633fe7SShimoda, Yoshihiro 	disable_irq(rspi->irq);
699a3633fe7SShimoda, Yoshihiro 
700a3633fe7SShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD, RSPI_SPCR);
701a3633fe7SShimoda, Yoshihiro 	rspi_enable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
702a3633fe7SShimoda, Yoshihiro 	rspi->dma_callbacked = 0;
703a3633fe7SShimoda, Yoshihiro 
704a3633fe7SShimoda, Yoshihiro 	desc->callback = rspi_dma_complete;
705a3633fe7SShimoda, Yoshihiro 	desc->callback_param = rspi;
706a3633fe7SShimoda, Yoshihiro 	dmaengine_submit(desc);
707a3633fe7SShimoda, Yoshihiro 	dma_async_issue_pending(rspi->chan_rx);
708a3633fe7SShimoda, Yoshihiro 
709a3633fe7SShimoda, Yoshihiro 	desc_dummy->callback = NULL;	/* No callback */
710a3633fe7SShimoda, Yoshihiro 	dmaengine_submit(desc_dummy);
711a3633fe7SShimoda, Yoshihiro 	dma_async_issue_pending(rspi->chan_tx);
712a3633fe7SShimoda, Yoshihiro 
713a3633fe7SShimoda, Yoshihiro 	ret = wait_event_interruptible_timeout(rspi->wait,
714a3633fe7SShimoda, Yoshihiro 					       rspi->dma_callbacked, HZ);
715a3633fe7SShimoda, Yoshihiro 	if (ret > 0 && rspi->dma_callbacked)
716a3633fe7SShimoda, Yoshihiro 		ret = 0;
717a3633fe7SShimoda, Yoshihiro 	else if (!ret)
718a3633fe7SShimoda, Yoshihiro 		ret = -ETIMEDOUT;
719a3633fe7SShimoda, Yoshihiro 	rspi_disable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
720a3633fe7SShimoda, Yoshihiro 
721a3633fe7SShimoda, Yoshihiro 	enable_irq(rspi->irq);
722a3633fe7SShimoda, Yoshihiro 
723a3633fe7SShimoda, Yoshihiro end:
724a3633fe7SShimoda, Yoshihiro 	rspi_dma_unmap_sg(&sg, rspi->chan_rx, DMA_FROM_DEVICE);
725a3633fe7SShimoda, Yoshihiro end_dummy_mapped:
726a3633fe7SShimoda, Yoshihiro 	rspi_dma_unmap_sg(&sg_dummy, rspi->chan_tx, DMA_TO_DEVICE);
727a3633fe7SShimoda, Yoshihiro end_nomap:
728a3633fe7SShimoda, Yoshihiro 	if (rspi->dma_width_16bit) {
729a3633fe7SShimoda, Yoshihiro 		if (!ret)
730a3633fe7SShimoda, Yoshihiro 			rspi_memory_from_8bit(t->rx_buf, rx_buf, t->len);
731a3633fe7SShimoda, Yoshihiro 		kfree(rx_buf);
732a3633fe7SShimoda, Yoshihiro 	}
733a3633fe7SShimoda, Yoshihiro 	kfree(dummy);
734a3633fe7SShimoda, Yoshihiro 
735a3633fe7SShimoda, Yoshihiro 	return ret;
736a3633fe7SShimoda, Yoshihiro }
737a3633fe7SShimoda, Yoshihiro 
738baf588f4SGeert Uytterhoeven static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t)
739a3633fe7SShimoda, Yoshihiro {
740a3633fe7SShimoda, Yoshihiro 	if (t->tx_buf && rspi->chan_tx)
741a3633fe7SShimoda, Yoshihiro 		return 1;
742a3633fe7SShimoda, Yoshihiro 	/* If the module receives data by DMAC, it also needs TX DMAC */
743a3633fe7SShimoda, Yoshihiro 	if (t->rx_buf && rspi->chan_tx && rspi->chan_rx)
744a3633fe7SShimoda, Yoshihiro 		return 1;
745a3633fe7SShimoda, Yoshihiro 
746a3633fe7SShimoda, Yoshihiro 	return 0;
747a3633fe7SShimoda, Yoshihiro }
748a3633fe7SShimoda, Yoshihiro 
7490b2182ddSShimoda, Yoshihiro static void rspi_work(struct work_struct *work)
7500b2182ddSShimoda, Yoshihiro {
7510b2182ddSShimoda, Yoshihiro 	struct rspi_data *rspi = container_of(work, struct rspi_data, ws);
7520b2182ddSShimoda, Yoshihiro 	struct spi_message *mesg;
7530b2182ddSShimoda, Yoshihiro 	struct spi_transfer *t;
7540b2182ddSShimoda, Yoshihiro 	unsigned long flags;
7550b2182ddSShimoda, Yoshihiro 	int ret;
7560b2182ddSShimoda, Yoshihiro 
7578d4d08ceSShimoda, Yoshihiro 	while (1) {
7580b2182ddSShimoda, Yoshihiro 		spin_lock_irqsave(&rspi->lock, flags);
7598d4d08ceSShimoda, Yoshihiro 		if (list_empty(&rspi->queue)) {
7608d4d08ceSShimoda, Yoshihiro 			spin_unlock_irqrestore(&rspi->lock, flags);
7618d4d08ceSShimoda, Yoshihiro 			break;
7628d4d08ceSShimoda, Yoshihiro 		}
7630b2182ddSShimoda, Yoshihiro 		mesg = list_entry(rspi->queue.next, struct spi_message, queue);
7640b2182ddSShimoda, Yoshihiro 		list_del_init(&mesg->queue);
7650b2182ddSShimoda, Yoshihiro 		spin_unlock_irqrestore(&rspi->lock, flags);
7660b2182ddSShimoda, Yoshihiro 
7670b2182ddSShimoda, Yoshihiro 		rspi_assert_ssl(rspi);
7680b2182ddSShimoda, Yoshihiro 
7690b2182ddSShimoda, Yoshihiro 		list_for_each_entry(t, &mesg->transfers, transfer_list) {
7700b2182ddSShimoda, Yoshihiro 			if (t->tx_buf) {
771a3633fe7SShimoda, Yoshihiro 				if (rspi_is_dma(rspi, t))
772a3633fe7SShimoda, Yoshihiro 					ret = rspi_send_dma(rspi, t);
773a3633fe7SShimoda, Yoshihiro 				else
774cb52c673SHiep Cao Minh 					ret = send_pio(rspi, mesg, t);
7750b2182ddSShimoda, Yoshihiro 				if (ret < 0)
7760b2182ddSShimoda, Yoshihiro 					goto error;
7770b2182ddSShimoda, Yoshihiro 			}
7780b2182ddSShimoda, Yoshihiro 			if (t->rx_buf) {
779a3633fe7SShimoda, Yoshihiro 				if (rspi_is_dma(rspi, t))
780a3633fe7SShimoda, Yoshihiro 					ret = rspi_receive_dma(rspi, t);
781a3633fe7SShimoda, Yoshihiro 				else
782cb52c673SHiep Cao Minh 					ret = receive_pio(rspi, mesg, t);
7830b2182ddSShimoda, Yoshihiro 				if (ret < 0)
7840b2182ddSShimoda, Yoshihiro 					goto error;
7850b2182ddSShimoda, Yoshihiro 			}
7860b2182ddSShimoda, Yoshihiro 			mesg->actual_length += t->len;
7870b2182ddSShimoda, Yoshihiro 		}
7880b2182ddSShimoda, Yoshihiro 		rspi_negate_ssl(rspi);
7890b2182ddSShimoda, Yoshihiro 
7900b2182ddSShimoda, Yoshihiro 		mesg->status = 0;
7910b2182ddSShimoda, Yoshihiro 		mesg->complete(mesg->context);
7920b2182ddSShimoda, Yoshihiro 	}
7930b2182ddSShimoda, Yoshihiro 
7940b2182ddSShimoda, Yoshihiro 	return;
7950b2182ddSShimoda, Yoshihiro 
7960b2182ddSShimoda, Yoshihiro error:
7970b2182ddSShimoda, Yoshihiro 	mesg->status = ret;
7980b2182ddSShimoda, Yoshihiro 	mesg->complete(mesg->context);
7990b2182ddSShimoda, Yoshihiro }
8000b2182ddSShimoda, Yoshihiro 
8010b2182ddSShimoda, Yoshihiro static int rspi_setup(struct spi_device *spi)
8020b2182ddSShimoda, Yoshihiro {
8030b2182ddSShimoda, Yoshihiro 	struct rspi_data *rspi = spi_master_get_devdata(spi->master);
8040b2182ddSShimoda, Yoshihiro 
8050b2182ddSShimoda, Yoshihiro 	if (!spi->bits_per_word)
8060b2182ddSShimoda, Yoshihiro 		spi->bits_per_word = 8;
8070b2182ddSShimoda, Yoshihiro 	rspi->max_speed_hz = spi->max_speed_hz;
8080b2182ddSShimoda, Yoshihiro 
809348e5153SGeert Uytterhoeven 	rspi->spcmd = SPCMD_SSLKP;
810348e5153SGeert Uytterhoeven 	if (spi->mode & SPI_CPOL)
811348e5153SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_CPOL;
812348e5153SGeert Uytterhoeven 	if (spi->mode & SPI_CPHA)
813348e5153SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_CPHA;
814348e5153SGeert Uytterhoeven 
8155ce0ba88SHiep Cao Minh 	set_config_register(rspi, 8);
8160b2182ddSShimoda, Yoshihiro 
8170b2182ddSShimoda, Yoshihiro 	return 0;
8180b2182ddSShimoda, Yoshihiro }
8190b2182ddSShimoda, Yoshihiro 
8200b2182ddSShimoda, Yoshihiro static int rspi_transfer(struct spi_device *spi, struct spi_message *mesg)
8210b2182ddSShimoda, Yoshihiro {
8220b2182ddSShimoda, Yoshihiro 	struct rspi_data *rspi = spi_master_get_devdata(spi->master);
8230b2182ddSShimoda, Yoshihiro 	unsigned long flags;
8240b2182ddSShimoda, Yoshihiro 
8250b2182ddSShimoda, Yoshihiro 	mesg->actual_length = 0;
8260b2182ddSShimoda, Yoshihiro 	mesg->status = -EINPROGRESS;
8270b2182ddSShimoda, Yoshihiro 
8280b2182ddSShimoda, Yoshihiro 	spin_lock_irqsave(&rspi->lock, flags);
8290b2182ddSShimoda, Yoshihiro 	list_add_tail(&mesg->queue, &rspi->queue);
8300b2182ddSShimoda, Yoshihiro 	schedule_work(&rspi->ws);
8310b2182ddSShimoda, Yoshihiro 	spin_unlock_irqrestore(&rspi->lock, flags);
8320b2182ddSShimoda, Yoshihiro 
8330b2182ddSShimoda, Yoshihiro 	return 0;
8340b2182ddSShimoda, Yoshihiro }
8350b2182ddSShimoda, Yoshihiro 
8360b2182ddSShimoda, Yoshihiro static void rspi_cleanup(struct spi_device *spi)
8370b2182ddSShimoda, Yoshihiro {
8380b2182ddSShimoda, Yoshihiro }
8390b2182ddSShimoda, Yoshihiro 
8400b2182ddSShimoda, Yoshihiro static irqreturn_t rspi_irq(int irq, void *_sr)
8410b2182ddSShimoda, Yoshihiro {
842c132f094SGeert Uytterhoeven 	struct rspi_data *rspi = _sr;
84397b95c11SGeert Uytterhoeven 	u8 spsr;
8440b2182ddSShimoda, Yoshihiro 	irqreturn_t ret = IRQ_NONE;
84597b95c11SGeert Uytterhoeven 	u8 disable_irq = 0;
8460b2182ddSShimoda, Yoshihiro 
8470b2182ddSShimoda, Yoshihiro 	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
8480b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPRF)
8490b2182ddSShimoda, Yoshihiro 		disable_irq |= SPCR_SPRIE;
8500b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPTEF)
8510b2182ddSShimoda, Yoshihiro 		disable_irq |= SPCR_SPTIE;
8520b2182ddSShimoda, Yoshihiro 
8530b2182ddSShimoda, Yoshihiro 	if (disable_irq) {
8540b2182ddSShimoda, Yoshihiro 		ret = IRQ_HANDLED;
8550b2182ddSShimoda, Yoshihiro 		rspi_disable_irq(rspi, disable_irq);
8560b2182ddSShimoda, Yoshihiro 		wake_up(&rspi->wait);
8570b2182ddSShimoda, Yoshihiro 	}
8580b2182ddSShimoda, Yoshihiro 
8590b2182ddSShimoda, Yoshihiro 	return ret;
8600b2182ddSShimoda, Yoshihiro }
8610b2182ddSShimoda, Yoshihiro 
862fd4a319bSGrant Likely static int rspi_request_dma(struct rspi_data *rspi,
863a3633fe7SShimoda, Yoshihiro 				      struct platform_device *pdev)
864a3633fe7SShimoda, Yoshihiro {
865baf588f4SGeert Uytterhoeven 	const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
866e2b05099SGuennadi Liakhovetski 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
867a3633fe7SShimoda, Yoshihiro 	dma_cap_mask_t mask;
8680243c536SShimoda, Yoshihiro 	struct dma_slave_config cfg;
8690243c536SShimoda, Yoshihiro 	int ret;
870a3633fe7SShimoda, Yoshihiro 
871e2b05099SGuennadi Liakhovetski 	if (!res || !rspi_pd)
8720243c536SShimoda, Yoshihiro 		return 0;	/* The driver assumes no error. */
873a3633fe7SShimoda, Yoshihiro 
874a3633fe7SShimoda, Yoshihiro 	rspi->dma_width_16bit = rspi_pd->dma_width_16bit;
875a3633fe7SShimoda, Yoshihiro 
876a3633fe7SShimoda, Yoshihiro 	/* If the module receives data by DMAC, it also needs TX DMAC */
877a3633fe7SShimoda, Yoshihiro 	if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) {
878a3633fe7SShimoda, Yoshihiro 		dma_cap_zero(mask);
879a3633fe7SShimoda, Yoshihiro 		dma_cap_set(DMA_SLAVE, mask);
8800243c536SShimoda, Yoshihiro 		rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter,
8810243c536SShimoda, Yoshihiro 						    (void *)rspi_pd->dma_rx_id);
8820243c536SShimoda, Yoshihiro 		if (rspi->chan_rx) {
8830243c536SShimoda, Yoshihiro 			cfg.slave_id = rspi_pd->dma_rx_id;
8840243c536SShimoda, Yoshihiro 			cfg.direction = DMA_DEV_TO_MEM;
885e2b05099SGuennadi Liakhovetski 			cfg.dst_addr = 0;
886e2b05099SGuennadi Liakhovetski 			cfg.src_addr = res->start + RSPI_SPDR;
8870243c536SShimoda, Yoshihiro 			ret = dmaengine_slave_config(rspi->chan_rx, &cfg);
8880243c536SShimoda, Yoshihiro 			if (!ret)
889a3633fe7SShimoda, Yoshihiro 				dev_info(&pdev->dev, "Use DMA when rx.\n");
8900243c536SShimoda, Yoshihiro 			else
8910243c536SShimoda, Yoshihiro 				return ret;
8920243c536SShimoda, Yoshihiro 		}
893a3633fe7SShimoda, Yoshihiro 	}
894a3633fe7SShimoda, Yoshihiro 	if (rspi_pd->dma_tx_id) {
895a3633fe7SShimoda, Yoshihiro 		dma_cap_zero(mask);
896a3633fe7SShimoda, Yoshihiro 		dma_cap_set(DMA_SLAVE, mask);
8970243c536SShimoda, Yoshihiro 		rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter,
8980243c536SShimoda, Yoshihiro 						    (void *)rspi_pd->dma_tx_id);
8990243c536SShimoda, Yoshihiro 		if (rspi->chan_tx) {
9000243c536SShimoda, Yoshihiro 			cfg.slave_id = rspi_pd->dma_tx_id;
9010243c536SShimoda, Yoshihiro 			cfg.direction = DMA_MEM_TO_DEV;
902e2b05099SGuennadi Liakhovetski 			cfg.dst_addr = res->start + RSPI_SPDR;
903e2b05099SGuennadi Liakhovetski 			cfg.src_addr = 0;
9040243c536SShimoda, Yoshihiro 			ret = dmaengine_slave_config(rspi->chan_tx, &cfg);
9050243c536SShimoda, Yoshihiro 			if (!ret)
906a3633fe7SShimoda, Yoshihiro 				dev_info(&pdev->dev, "Use DMA when tx\n");
9070243c536SShimoda, Yoshihiro 			else
9080243c536SShimoda, Yoshihiro 				return ret;
909a3633fe7SShimoda, Yoshihiro 		}
910a3633fe7SShimoda, Yoshihiro 	}
911a3633fe7SShimoda, Yoshihiro 
9120243c536SShimoda, Yoshihiro 	return 0;
9130243c536SShimoda, Yoshihiro }
9140243c536SShimoda, Yoshihiro 
915fd4a319bSGrant Likely static void rspi_release_dma(struct rspi_data *rspi)
916a3633fe7SShimoda, Yoshihiro {
917a3633fe7SShimoda, Yoshihiro 	if (rspi->chan_tx)
918a3633fe7SShimoda, Yoshihiro 		dma_release_channel(rspi->chan_tx);
919a3633fe7SShimoda, Yoshihiro 	if (rspi->chan_rx)
920a3633fe7SShimoda, Yoshihiro 		dma_release_channel(rspi->chan_rx);
921a3633fe7SShimoda, Yoshihiro }
922a3633fe7SShimoda, Yoshihiro 
923fd4a319bSGrant Likely static int rspi_remove(struct platform_device *pdev)
9240b2182ddSShimoda, Yoshihiro {
9259d3405dbSAxel Lin 	struct rspi_data *rspi = spi_master_get(platform_get_drvdata(pdev));
9260b2182ddSShimoda, Yoshihiro 
9270b2182ddSShimoda, Yoshihiro 	spi_unregister_master(rspi->master);
928a3633fe7SShimoda, Yoshihiro 	rspi_release_dma(rspi);
9290b2182ddSShimoda, Yoshihiro 	free_irq(platform_get_irq(pdev, 0), rspi);
9300b2182ddSShimoda, Yoshihiro 	clk_put(rspi->clk);
9310b2182ddSShimoda, Yoshihiro 	iounmap(rspi->addr);
9320b2182ddSShimoda, Yoshihiro 	spi_master_put(rspi->master);
9330b2182ddSShimoda, Yoshihiro 
9340b2182ddSShimoda, Yoshihiro 	return 0;
9350b2182ddSShimoda, Yoshihiro }
9360b2182ddSShimoda, Yoshihiro 
937fd4a319bSGrant Likely static int rspi_probe(struct platform_device *pdev)
9380b2182ddSShimoda, Yoshihiro {
9390b2182ddSShimoda, Yoshihiro 	struct resource *res;
9400b2182ddSShimoda, Yoshihiro 	struct spi_master *master;
9410b2182ddSShimoda, Yoshihiro 	struct rspi_data *rspi;
9420b2182ddSShimoda, Yoshihiro 	int ret, irq;
9430b2182ddSShimoda, Yoshihiro 	char clk_name[16];
944baf588f4SGeert Uytterhoeven 	const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
9455ce0ba88SHiep Cao Minh 	const struct spi_ops *ops;
9465ce0ba88SHiep Cao Minh 	const struct platform_device_id *id_entry = pdev->id_entry;
9470b2182ddSShimoda, Yoshihiro 
9485ce0ba88SHiep Cao Minh 	ops = (struct spi_ops *)id_entry->driver_data;
9495ce0ba88SHiep Cao Minh 	/* ops parameter check */
9505ce0ba88SHiep Cao Minh 	if (!ops->set_config_register) {
9515ce0ba88SHiep Cao Minh 		dev_err(&pdev->dev, "there is no set_config_register\n");
9525ce0ba88SHiep Cao Minh 		return -ENODEV;
9535ce0ba88SHiep Cao Minh 	}
9540b2182ddSShimoda, Yoshihiro 	/* get base addr */
9550b2182ddSShimoda, Yoshihiro 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
9560b2182ddSShimoda, Yoshihiro 	if (unlikely(res == NULL)) {
9570b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "invalid resource\n");
9580b2182ddSShimoda, Yoshihiro 		return -EINVAL;
9590b2182ddSShimoda, Yoshihiro 	}
9600b2182ddSShimoda, Yoshihiro 
9610b2182ddSShimoda, Yoshihiro 	irq = platform_get_irq(pdev, 0);
9620b2182ddSShimoda, Yoshihiro 	if (irq < 0) {
9630b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "platform_get_irq error\n");
9640b2182ddSShimoda, Yoshihiro 		return -ENODEV;
9650b2182ddSShimoda, Yoshihiro 	}
9660b2182ddSShimoda, Yoshihiro 
9670b2182ddSShimoda, Yoshihiro 	master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data));
9680b2182ddSShimoda, Yoshihiro 	if (master == NULL) {
9690b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "spi_alloc_master error.\n");
9700b2182ddSShimoda, Yoshihiro 		return -ENOMEM;
9710b2182ddSShimoda, Yoshihiro 	}
9720b2182ddSShimoda, Yoshihiro 
9730b2182ddSShimoda, Yoshihiro 	rspi = spi_master_get_devdata(master);
97424b5a82cSJingoo Han 	platform_set_drvdata(pdev, rspi);
9755ce0ba88SHiep Cao Minh 	rspi->ops = ops;
9760b2182ddSShimoda, Yoshihiro 	rspi->master = master;
9770b2182ddSShimoda, Yoshihiro 	rspi->addr = ioremap(res->start, resource_size(res));
9780b2182ddSShimoda, Yoshihiro 	if (rspi->addr == NULL) {
9790b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "ioremap error.\n");
9800b2182ddSShimoda, Yoshihiro 		ret = -ENOMEM;
9810b2182ddSShimoda, Yoshihiro 		goto error1;
9820b2182ddSShimoda, Yoshihiro 	}
9830b2182ddSShimoda, Yoshihiro 
9845ce0ba88SHiep Cao Minh 	snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id);
9850b2182ddSShimoda, Yoshihiro 	rspi->clk = clk_get(&pdev->dev, clk_name);
9860b2182ddSShimoda, Yoshihiro 	if (IS_ERR(rspi->clk)) {
9870b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "cannot get clock\n");
9880b2182ddSShimoda, Yoshihiro 		ret = PTR_ERR(rspi->clk);
9890b2182ddSShimoda, Yoshihiro 		goto error2;
9900b2182ddSShimoda, Yoshihiro 	}
9910b2182ddSShimoda, Yoshihiro 	clk_enable(rspi->clk);
9920b2182ddSShimoda, Yoshihiro 
9930b2182ddSShimoda, Yoshihiro 	INIT_LIST_HEAD(&rspi->queue);
9940b2182ddSShimoda, Yoshihiro 	spin_lock_init(&rspi->lock);
9950b2182ddSShimoda, Yoshihiro 	INIT_WORK(&rspi->ws, rspi_work);
9960b2182ddSShimoda, Yoshihiro 	init_waitqueue_head(&rspi->wait);
9970b2182ddSShimoda, Yoshihiro 
9985ce0ba88SHiep Cao Minh 	master->num_chipselect = rspi_pd->num_chipselect;
9995ce0ba88SHiep Cao Minh 	if (!master->num_chipselect)
10005ce0ba88SHiep Cao Minh 		master->num_chipselect = 2; /* default */
10015ce0ba88SHiep Cao Minh 
10020b2182ddSShimoda, Yoshihiro 	master->bus_num = pdev->id;
10030b2182ddSShimoda, Yoshihiro 	master->setup = rspi_setup;
10040b2182ddSShimoda, Yoshihiro 	master->transfer = rspi_transfer;
10050b2182ddSShimoda, Yoshihiro 	master->cleanup = rspi_cleanup;
1006348e5153SGeert Uytterhoeven 	master->mode_bits = SPI_CPHA | SPI_CPOL;
10070b2182ddSShimoda, Yoshihiro 
10080b2182ddSShimoda, Yoshihiro 	ret = request_irq(irq, rspi_irq, 0, dev_name(&pdev->dev), rspi);
10090b2182ddSShimoda, Yoshihiro 	if (ret < 0) {
10100b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "request_irq error\n");
10110b2182ddSShimoda, Yoshihiro 		goto error3;
10120b2182ddSShimoda, Yoshihiro 	}
10130b2182ddSShimoda, Yoshihiro 
1014a3633fe7SShimoda, Yoshihiro 	rspi->irq = irq;
10150243c536SShimoda, Yoshihiro 	ret = rspi_request_dma(rspi, pdev);
10160243c536SShimoda, Yoshihiro 	if (ret < 0) {
10170243c536SShimoda, Yoshihiro 		dev_err(&pdev->dev, "rspi_request_dma failed.\n");
10180243c536SShimoda, Yoshihiro 		goto error4;
10190243c536SShimoda, Yoshihiro 	}
1020a3633fe7SShimoda, Yoshihiro 
10210b2182ddSShimoda, Yoshihiro 	ret = spi_register_master(master);
10220b2182ddSShimoda, Yoshihiro 	if (ret < 0) {
10230b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "spi_register_master error.\n");
10240b2182ddSShimoda, Yoshihiro 		goto error4;
10250b2182ddSShimoda, Yoshihiro 	}
10260b2182ddSShimoda, Yoshihiro 
10270b2182ddSShimoda, Yoshihiro 	dev_info(&pdev->dev, "probed\n");
10280b2182ddSShimoda, Yoshihiro 
10290b2182ddSShimoda, Yoshihiro 	return 0;
10300b2182ddSShimoda, Yoshihiro 
10310b2182ddSShimoda, Yoshihiro error4:
1032a3633fe7SShimoda, Yoshihiro 	rspi_release_dma(rspi);
10330b2182ddSShimoda, Yoshihiro 	free_irq(irq, rspi);
10340b2182ddSShimoda, Yoshihiro error3:
10350b2182ddSShimoda, Yoshihiro 	clk_put(rspi->clk);
10360b2182ddSShimoda, Yoshihiro error2:
10370b2182ddSShimoda, Yoshihiro 	iounmap(rspi->addr);
10380b2182ddSShimoda, Yoshihiro error1:
10390b2182ddSShimoda, Yoshihiro 	spi_master_put(master);
10400b2182ddSShimoda, Yoshihiro 
10410b2182ddSShimoda, Yoshihiro 	return ret;
10420b2182ddSShimoda, Yoshihiro }
10430b2182ddSShimoda, Yoshihiro 
10445ce0ba88SHiep Cao Minh static struct spi_ops rspi_ops = {
10455ce0ba88SHiep Cao Minh 	.set_config_register =		rspi_set_config_register,
1046cb52c673SHiep Cao Minh 	.send_pio =			rspi_send_pio,
1047cb52c673SHiep Cao Minh 	.receive_pio =			rspi_receive_pio,
10485ce0ba88SHiep Cao Minh };
10495ce0ba88SHiep Cao Minh 
10505ce0ba88SHiep Cao Minh static struct spi_ops qspi_ops = {
10515ce0ba88SHiep Cao Minh 	.set_config_register =		qspi_set_config_register,
1052cb52c673SHiep Cao Minh 	.send_pio =			qspi_send_pio,
1053cb52c673SHiep Cao Minh 	.receive_pio =			qspi_receive_pio,
10545ce0ba88SHiep Cao Minh };
10555ce0ba88SHiep Cao Minh 
10565ce0ba88SHiep Cao Minh static struct platform_device_id spi_driver_ids[] = {
10575ce0ba88SHiep Cao Minh 	{ "rspi",	(kernel_ulong_t)&rspi_ops },
10585ce0ba88SHiep Cao Minh 	{ "qspi",	(kernel_ulong_t)&qspi_ops },
10595ce0ba88SHiep Cao Minh 	{},
10605ce0ba88SHiep Cao Minh };
10615ce0ba88SHiep Cao Minh 
10625ce0ba88SHiep Cao Minh MODULE_DEVICE_TABLE(platform, spi_driver_ids);
10635ce0ba88SHiep Cao Minh 
10640b2182ddSShimoda, Yoshihiro static struct platform_driver rspi_driver = {
10650b2182ddSShimoda, Yoshihiro 	.probe =	rspi_probe,
1066fd4a319bSGrant Likely 	.remove =	rspi_remove,
10675ce0ba88SHiep Cao Minh 	.id_table =	spi_driver_ids,
10680b2182ddSShimoda, Yoshihiro 	.driver		= {
10695ce0ba88SHiep Cao Minh 		.name = "renesas_spi",
10700b2182ddSShimoda, Yoshihiro 		.owner	= THIS_MODULE,
10710b2182ddSShimoda, Yoshihiro 	},
10720b2182ddSShimoda, Yoshihiro };
10730b2182ddSShimoda, Yoshihiro module_platform_driver(rspi_driver);
10740b2182ddSShimoda, Yoshihiro 
10750b2182ddSShimoda, Yoshihiro MODULE_DESCRIPTION("Renesas RSPI bus driver");
10760b2182ddSShimoda, Yoshihiro MODULE_LICENSE("GPL v2");
10770b2182ddSShimoda, Yoshihiro MODULE_AUTHOR("Yoshihiro Shimoda");
10780b2182ddSShimoda, Yoshihiro MODULE_ALIAS("platform:rspi");
1079