xref: /openbmc/linux/drivers/spi/spi-rspi.c (revision 74da7686)
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/interrupt.h>
290b2182ddSShimoda, Yoshihiro #include <linux/platform_device.h>
300b2182ddSShimoda, Yoshihiro #include <linux/io.h>
310b2182ddSShimoda, Yoshihiro #include <linux/clk.h>
32a3633fe7SShimoda, Yoshihiro #include <linux/dmaengine.h>
33a3633fe7SShimoda, Yoshihiro #include <linux/dma-mapping.h>
34a3633fe7SShimoda, Yoshihiro #include <linux/sh_dma.h>
350b2182ddSShimoda, Yoshihiro #include <linux/spi/spi.h>
36a3633fe7SShimoda, Yoshihiro #include <linux/spi/rspi.h>
370b2182ddSShimoda, Yoshihiro 
386ab4865bSGeert Uytterhoeven #define RSPI_SPCR		0x00	/* Control Register */
396ab4865bSGeert Uytterhoeven #define RSPI_SSLP		0x01	/* Slave Select Polarity Register */
406ab4865bSGeert Uytterhoeven #define RSPI_SPPCR		0x02	/* Pin Control Register */
416ab4865bSGeert Uytterhoeven #define RSPI_SPSR		0x03	/* Status Register */
426ab4865bSGeert Uytterhoeven #define RSPI_SPDR		0x04	/* Data Register */
436ab4865bSGeert Uytterhoeven #define RSPI_SPSCR		0x08	/* Sequence Control Register */
446ab4865bSGeert Uytterhoeven #define RSPI_SPSSR		0x09	/* Sequence Status Register */
456ab4865bSGeert Uytterhoeven #define RSPI_SPBR		0x0a	/* Bit Rate Register */
466ab4865bSGeert Uytterhoeven #define RSPI_SPDCR		0x0b	/* Data Control Register */
476ab4865bSGeert Uytterhoeven #define RSPI_SPCKD		0x0c	/* Clock Delay Register */
486ab4865bSGeert Uytterhoeven #define RSPI_SSLND		0x0d	/* Slave Select Negation Delay Register */
496ab4865bSGeert Uytterhoeven #define RSPI_SPND		0x0e	/* Next-Access Delay Register */
506ab4865bSGeert Uytterhoeven #define RSPI_SPCR2		0x0f	/* Control Register 2 */
516ab4865bSGeert Uytterhoeven #define RSPI_SPCMD0		0x10	/* Command Register 0 */
526ab4865bSGeert Uytterhoeven #define RSPI_SPCMD1		0x12	/* Command Register 1 */
536ab4865bSGeert Uytterhoeven #define RSPI_SPCMD2		0x14	/* Command Register 2 */
546ab4865bSGeert Uytterhoeven #define RSPI_SPCMD3		0x16	/* Command Register 3 */
556ab4865bSGeert Uytterhoeven #define RSPI_SPCMD4		0x18	/* Command Register 4 */
566ab4865bSGeert Uytterhoeven #define RSPI_SPCMD5		0x1a	/* Command Register 5 */
576ab4865bSGeert Uytterhoeven #define RSPI_SPCMD6		0x1c	/* Command Register 6 */
586ab4865bSGeert Uytterhoeven #define RSPI_SPCMD7		0x1e	/* Command Register 7 */
596ab4865bSGeert Uytterhoeven #define RSPI_SPBFCR		0x20	/* Buffer Control Register */
606ab4865bSGeert Uytterhoeven #define RSPI_SPBFDR		0x22	/* Buffer Data Count Setting Register */
610b2182ddSShimoda, Yoshihiro 
625ce0ba88SHiep Cao Minh /*qspi only */
63fbe5072bSGeert Uytterhoeven #define QSPI_SPBFCR		0x18	/* Buffer Control Register */
64fbe5072bSGeert Uytterhoeven #define QSPI_SPBDCR		0x1a	/* Buffer Data Count Register */
65fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL0		0x1c	/* Transfer Data Length Multiplier Setting Register 0 */
66fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL1		0x20	/* Transfer Data Length Multiplier Setting Register 1 */
67fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL2		0x24	/* Transfer Data Length Multiplier Setting Register 2 */
68fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL3		0x28	/* Transfer Data Length Multiplier Setting Register 3 */
695ce0ba88SHiep Cao Minh 
706ab4865bSGeert Uytterhoeven /* SPCR - Control Register */
716ab4865bSGeert Uytterhoeven #define SPCR_SPRIE		0x80	/* Receive Interrupt Enable */
726ab4865bSGeert Uytterhoeven #define SPCR_SPE		0x40	/* Function Enable */
736ab4865bSGeert Uytterhoeven #define SPCR_SPTIE		0x20	/* Transmit Interrupt Enable */
746ab4865bSGeert Uytterhoeven #define SPCR_SPEIE		0x10	/* Error Interrupt Enable */
756ab4865bSGeert Uytterhoeven #define SPCR_MSTR		0x08	/* Master/Slave Mode Select */
766ab4865bSGeert Uytterhoeven #define SPCR_MODFEN		0x04	/* Mode Fault Error Detection Enable */
776ab4865bSGeert Uytterhoeven /* RSPI on SH only */
786ab4865bSGeert Uytterhoeven #define SPCR_TXMD		0x02	/* TX Only Mode (vs. Full Duplex) */
796ab4865bSGeert Uytterhoeven #define SPCR_SPMS		0x01	/* 3-wire Mode (vs. 4-wire) */
80fbe5072bSGeert Uytterhoeven /* QSPI on R-Car M2 only */
81fbe5072bSGeert Uytterhoeven #define SPCR_WSWAP		0x02	/* Word Swap of read-data for DMAC */
82fbe5072bSGeert Uytterhoeven #define SPCR_BSWAP		0x01	/* Byte Swap of read-data for DMAC */
830b2182ddSShimoda, Yoshihiro 
846ab4865bSGeert Uytterhoeven /* SSLP - Slave Select Polarity Register */
856ab4865bSGeert Uytterhoeven #define SSLP_SSL1P		0x02	/* SSL1 Signal Polarity Setting */
866ab4865bSGeert Uytterhoeven #define SSLP_SSL0P		0x01	/* SSL0 Signal Polarity Setting */
870b2182ddSShimoda, Yoshihiro 
886ab4865bSGeert Uytterhoeven /* SPPCR - Pin Control Register */
896ab4865bSGeert Uytterhoeven #define SPPCR_MOIFE		0x20	/* MOSI Idle Value Fixing Enable */
906ab4865bSGeert Uytterhoeven #define SPPCR_MOIFV		0x10	/* MOSI Idle Fixed Value */
910b2182ddSShimoda, Yoshihiro #define SPPCR_SPOM		0x04
926ab4865bSGeert Uytterhoeven #define SPPCR_SPLP2		0x02	/* Loopback Mode 2 (non-inverting) */
936ab4865bSGeert Uytterhoeven #define SPPCR_SPLP		0x01	/* Loopback Mode (inverting) */
940b2182ddSShimoda, Yoshihiro 
95fbe5072bSGeert Uytterhoeven #define SPPCR_IO3FV		0x04	/* Single-/Dual-SPI Mode IO3 Output Fixed Value */
96fbe5072bSGeert Uytterhoeven #define SPPCR_IO2FV		0x04	/* Single-/Dual-SPI Mode IO2 Output Fixed Value */
97fbe5072bSGeert Uytterhoeven 
986ab4865bSGeert Uytterhoeven /* SPSR - Status Register */
996ab4865bSGeert Uytterhoeven #define SPSR_SPRF		0x80	/* Receive Buffer Full Flag */
1006ab4865bSGeert Uytterhoeven #define SPSR_TEND		0x40	/* Transmit End */
1016ab4865bSGeert Uytterhoeven #define SPSR_SPTEF		0x20	/* Transmit Buffer Empty Flag */
1026ab4865bSGeert Uytterhoeven #define SPSR_PERF		0x08	/* Parity Error Flag */
1036ab4865bSGeert Uytterhoeven #define SPSR_MODF		0x04	/* Mode Fault Error Flag */
1046ab4865bSGeert Uytterhoeven #define SPSR_IDLNF		0x02	/* RSPI Idle Flag */
1056ab4865bSGeert Uytterhoeven #define SPSR_OVRF		0x01	/* Overrun Error Flag */
1060b2182ddSShimoda, Yoshihiro 
1076ab4865bSGeert Uytterhoeven /* SPSCR - Sequence Control Register */
1086ab4865bSGeert Uytterhoeven #define SPSCR_SPSLN_MASK	0x07	/* Sequence Length Specification */
1090b2182ddSShimoda, Yoshihiro 
1106ab4865bSGeert Uytterhoeven /* SPSSR - Sequence Status Register */
1116ab4865bSGeert Uytterhoeven #define SPSSR_SPECM_MASK	0x70	/* Command Error Mask */
1126ab4865bSGeert Uytterhoeven #define SPSSR_SPCP_MASK		0x07	/* Command Pointer Mask */
1130b2182ddSShimoda, Yoshihiro 
1146ab4865bSGeert Uytterhoeven /* SPDCR - Data Control Register */
1156ab4865bSGeert Uytterhoeven #define SPDCR_TXDMY		0x80	/* Dummy Data Transmission Enable */
1166ab4865bSGeert Uytterhoeven #define SPDCR_SPLW1		0x40	/* Access Width Specification (RZ) */
1176ab4865bSGeert Uytterhoeven #define SPDCR_SPLW0		0x20	/* Access Width Specification (RZ) */
1186ab4865bSGeert Uytterhoeven #define SPDCR_SPLLWORD		(SPDCR_SPLW1 | SPDCR_SPLW0)
1196ab4865bSGeert Uytterhoeven #define SPDCR_SPLWORD		SPDCR_SPLW1
1206ab4865bSGeert Uytterhoeven #define SPDCR_SPLBYTE		SPDCR_SPLW0
1216ab4865bSGeert Uytterhoeven #define SPDCR_SPLW		0x20	/* Access Width Specification (SH) */
1226ab4865bSGeert Uytterhoeven #define SPDCR_SPRDTD		0x10	/* Receive Transmit Data Select */
1230b2182ddSShimoda, Yoshihiro #define SPDCR_SLSEL1		0x08
1240b2182ddSShimoda, Yoshihiro #define SPDCR_SLSEL0		0x04
1256ab4865bSGeert Uytterhoeven #define SPDCR_SLSEL_MASK	0x0c	/* SSL1 Output Select */
1260b2182ddSShimoda, Yoshihiro #define SPDCR_SPFC1		0x02
1270b2182ddSShimoda, Yoshihiro #define SPDCR_SPFC0		0x01
1286ab4865bSGeert Uytterhoeven #define SPDCR_SPFC_MASK		0x03	/* Frame Count Setting (1-4) */
1290b2182ddSShimoda, Yoshihiro 
1306ab4865bSGeert Uytterhoeven /* SPCKD - Clock Delay Register */
1316ab4865bSGeert Uytterhoeven #define SPCKD_SCKDL_MASK	0x07	/* Clock Delay Setting (1-8) */
1320b2182ddSShimoda, Yoshihiro 
1336ab4865bSGeert Uytterhoeven /* SSLND - Slave Select Negation Delay Register */
1346ab4865bSGeert Uytterhoeven #define SSLND_SLNDL_MASK	0x07	/* SSL Negation Delay Setting (1-8) */
1350b2182ddSShimoda, Yoshihiro 
1366ab4865bSGeert Uytterhoeven /* SPND - Next-Access Delay Register */
1376ab4865bSGeert Uytterhoeven #define SPND_SPNDL_MASK		0x07	/* Next-Access Delay Setting (1-8) */
1380b2182ddSShimoda, Yoshihiro 
1396ab4865bSGeert Uytterhoeven /* SPCR2 - Control Register 2 */
1406ab4865bSGeert Uytterhoeven #define SPCR2_PTE		0x08	/* Parity Self-Test Enable */
1416ab4865bSGeert Uytterhoeven #define SPCR2_SPIE		0x04	/* Idle Interrupt Enable */
1426ab4865bSGeert Uytterhoeven #define SPCR2_SPOE		0x02	/* Odd Parity Enable (vs. Even) */
1436ab4865bSGeert Uytterhoeven #define SPCR2_SPPE		0x01	/* Parity Enable */
1440b2182ddSShimoda, Yoshihiro 
1456ab4865bSGeert Uytterhoeven /* SPCMDn - Command Registers */
1466ab4865bSGeert Uytterhoeven #define SPCMD_SCKDEN		0x8000	/* Clock Delay Setting Enable */
1476ab4865bSGeert Uytterhoeven #define SPCMD_SLNDEN		0x4000	/* SSL Negation Delay Setting Enable */
1486ab4865bSGeert Uytterhoeven #define SPCMD_SPNDEN		0x2000	/* Next-Access Delay Enable */
1496ab4865bSGeert Uytterhoeven #define SPCMD_LSBF		0x1000	/* LSB First */
1506ab4865bSGeert Uytterhoeven #define SPCMD_SPB_MASK		0x0f00	/* Data Length Setting */
1510b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_8_TO_16(bit)	(((bit - 1) << 8) & SPCMD_SPB_MASK)
1525ce0ba88SHiep Cao Minh #define SPCMD_SPB_8BIT		0x0000	/* qspi only */
1535ce0ba88SHiep Cao Minh #define SPCMD_SPB_16BIT		0x0100
1540b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_20BIT		0x0000
1550b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_24BIT		0x0100
1560b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_32BIT		0x0200
1576ab4865bSGeert Uytterhoeven #define SPCMD_SSLKP		0x0080	/* SSL Signal Level Keeping */
158fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_MASK	0x0060	/* SPI Operating Mode (QSPI only) */
159fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD1		0x0040
160fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD0		0x0020
161fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_SINGLE	0
162fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_DUAL	SPCMD_SPIMOD0
163fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_QUAD	SPCMD_SPIMOD1
164fbe5072bSGeert Uytterhoeven #define SPCMD_SPRW		0x0010	/* SPI Read/Write Access (Dual/Quad) */
1656ab4865bSGeert Uytterhoeven #define SPCMD_SSLA_MASK		0x0030	/* SSL Assert Signal Setting (RSPI) */
1666ab4865bSGeert Uytterhoeven #define SPCMD_BRDV_MASK		0x000c	/* Bit Rate Division Setting */
1676ab4865bSGeert Uytterhoeven #define SPCMD_CPOL		0x0002	/* Clock Polarity Setting */
1686ab4865bSGeert Uytterhoeven #define SPCMD_CPHA		0x0001	/* Clock Phase Setting */
1690b2182ddSShimoda, Yoshihiro 
1706ab4865bSGeert Uytterhoeven /* SPBFCR - Buffer Control Register */
1716ab4865bSGeert Uytterhoeven #define SPBFCR_TXRST		0x80	/* Transmit Buffer Data Reset (qspi only) */
1726ab4865bSGeert Uytterhoeven #define SPBFCR_RXRST		0x40	/* Receive Buffer Data Reset (qspi only) */
1736ab4865bSGeert Uytterhoeven #define SPBFCR_TXTRG_MASK	0x30	/* Transmit Buffer Data Triggering Number */
1746ab4865bSGeert Uytterhoeven #define SPBFCR_RXTRG_MASK	0x07	/* Receive Buffer Data Triggering Number */
1755ce0ba88SHiep Cao Minh 
1762aae80b2SGeert Uytterhoeven #define DUMMY_DATA		0x00
1772aae80b2SGeert Uytterhoeven 
1780b2182ddSShimoda, Yoshihiro struct rspi_data {
1790b2182ddSShimoda, Yoshihiro 	void __iomem *addr;
1800b2182ddSShimoda, Yoshihiro 	u32 max_speed_hz;
1810b2182ddSShimoda, Yoshihiro 	struct spi_master *master;
1820b2182ddSShimoda, Yoshihiro 	wait_queue_head_t wait;
1830b2182ddSShimoda, Yoshihiro 	struct clk *clk;
18497b95c11SGeert Uytterhoeven 	u8 spsr;
185348e5153SGeert Uytterhoeven 	u16 spcmd;
1865ce0ba88SHiep Cao Minh 	const struct spi_ops *ops;
187a3633fe7SShimoda, Yoshihiro 
188a3633fe7SShimoda, Yoshihiro 	/* for dmaengine */
189a3633fe7SShimoda, Yoshihiro 	struct dma_chan *chan_tx;
190a3633fe7SShimoda, Yoshihiro 	struct dma_chan *chan_rx;
191a3633fe7SShimoda, Yoshihiro 	int irq;
192a3633fe7SShimoda, Yoshihiro 
193a3633fe7SShimoda, Yoshihiro 	unsigned dma_width_16bit:1;
194a3633fe7SShimoda, Yoshihiro 	unsigned dma_callbacked:1;
19574da7686SGeert Uytterhoeven 	unsigned byte_access:1;
1960b2182ddSShimoda, Yoshihiro };
1970b2182ddSShimoda, Yoshihiro 
198baf588f4SGeert Uytterhoeven static void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset)
1990b2182ddSShimoda, Yoshihiro {
2000b2182ddSShimoda, Yoshihiro 	iowrite8(data, rspi->addr + offset);
2010b2182ddSShimoda, Yoshihiro }
2020b2182ddSShimoda, Yoshihiro 
203baf588f4SGeert Uytterhoeven static void rspi_write16(const struct rspi_data *rspi, u16 data, u16 offset)
2040b2182ddSShimoda, Yoshihiro {
2050b2182ddSShimoda, Yoshihiro 	iowrite16(data, rspi->addr + offset);
2060b2182ddSShimoda, Yoshihiro }
2070b2182ddSShimoda, Yoshihiro 
208baf588f4SGeert Uytterhoeven static void rspi_write32(const struct rspi_data *rspi, u32 data, u16 offset)
2095ce0ba88SHiep Cao Minh {
2105ce0ba88SHiep Cao Minh 	iowrite32(data, rspi->addr + offset);
2115ce0ba88SHiep Cao Minh }
2125ce0ba88SHiep Cao Minh 
213baf588f4SGeert Uytterhoeven static u8 rspi_read8(const struct rspi_data *rspi, u16 offset)
2140b2182ddSShimoda, Yoshihiro {
2150b2182ddSShimoda, Yoshihiro 	return ioread8(rspi->addr + offset);
2160b2182ddSShimoda, Yoshihiro }
2170b2182ddSShimoda, Yoshihiro 
218baf588f4SGeert Uytterhoeven static u16 rspi_read16(const struct rspi_data *rspi, u16 offset)
2190b2182ddSShimoda, Yoshihiro {
2200b2182ddSShimoda, Yoshihiro 	return ioread16(rspi->addr + offset);
2210b2182ddSShimoda, Yoshihiro }
2220b2182ddSShimoda, Yoshihiro 
22374da7686SGeert Uytterhoeven static void rspi_write_data(const struct rspi_data *rspi, u16 data)
22474da7686SGeert Uytterhoeven {
22574da7686SGeert Uytterhoeven 	if (rspi->byte_access)
22674da7686SGeert Uytterhoeven 		rspi_write8(rspi, data, RSPI_SPDR);
22774da7686SGeert Uytterhoeven 	else /* 16 bit */
22874da7686SGeert Uytterhoeven 		rspi_write16(rspi, data, RSPI_SPDR);
22974da7686SGeert Uytterhoeven }
23074da7686SGeert Uytterhoeven 
23174da7686SGeert Uytterhoeven static u16 rspi_read_data(const struct rspi_data *rspi)
23274da7686SGeert Uytterhoeven {
23374da7686SGeert Uytterhoeven 	if (rspi->byte_access)
23474da7686SGeert Uytterhoeven 		return rspi_read8(rspi, RSPI_SPDR);
23574da7686SGeert Uytterhoeven 	else /* 16 bit */
23674da7686SGeert Uytterhoeven 		return rspi_read16(rspi, RSPI_SPDR);
23774da7686SGeert Uytterhoeven }
23874da7686SGeert Uytterhoeven 
2395ce0ba88SHiep Cao Minh /* optional functions */
2405ce0ba88SHiep Cao Minh struct spi_ops {
24174da7686SGeert Uytterhoeven 	int (*set_config_register)(struct rspi_data *rspi, int access_size);
24291949a2dSGeert Uytterhoeven 	int (*send_pio)(struct rspi_data *rspi, struct spi_transfer *t);
24391949a2dSGeert Uytterhoeven 	int (*receive_pio)(struct rspi_data *rspi, struct spi_transfer *t);
2445ce0ba88SHiep Cao Minh };
2455ce0ba88SHiep Cao Minh 
2465ce0ba88SHiep Cao Minh /*
2475ce0ba88SHiep Cao Minh  * functions for RSPI
2485ce0ba88SHiep Cao Minh  */
24974da7686SGeert Uytterhoeven static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
2500b2182ddSShimoda, Yoshihiro {
2515ce0ba88SHiep Cao Minh 	int spbr;
2520b2182ddSShimoda, Yoshihiro 
2535ce0ba88SHiep Cao Minh 	/* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
2545ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPPCR);
2550b2182ddSShimoda, Yoshihiro 
2565ce0ba88SHiep Cao Minh 	/* Sets transfer bit rate */
2575ce0ba88SHiep Cao Minh 	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
2585ce0ba88SHiep Cao Minh 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
2595ce0ba88SHiep Cao Minh 
26074da7686SGeert Uytterhoeven 	/* Disable dummy transmission, set 16-bit word access, 1 frame */
26174da7686SGeert Uytterhoeven 	rspi_write8(rspi, 0, RSPI_SPDCR);
26274da7686SGeert Uytterhoeven 	rspi->byte_access = 0;
2635ce0ba88SHiep Cao Minh 
2645ce0ba88SHiep Cao Minh 	/* Sets RSPCK, SSL, next-access delay value */
2655ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
2665ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SSLND);
2675ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPND);
2685ce0ba88SHiep Cao Minh 
2695ce0ba88SHiep Cao Minh 	/* Sets parity, interrupt mask */
2705ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCR2);
2715ce0ba88SHiep Cao Minh 
2725ce0ba88SHiep Cao Minh 	/* Sets SPCMD */
273348e5153SGeert Uytterhoeven 	rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | rspi->spcmd,
2745ce0ba88SHiep Cao Minh 		     RSPI_SPCMD0);
2755ce0ba88SHiep Cao Minh 
2765ce0ba88SHiep Cao Minh 	/* Sets RSPI mode */
2775ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
2785ce0ba88SHiep Cao Minh 
2795ce0ba88SHiep Cao Minh 	return 0;
2800b2182ddSShimoda, Yoshihiro }
2810b2182ddSShimoda, Yoshihiro 
2825ce0ba88SHiep Cao Minh /*
2835ce0ba88SHiep Cao Minh  * functions for QSPI
2845ce0ba88SHiep Cao Minh  */
28574da7686SGeert Uytterhoeven static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
2865ce0ba88SHiep Cao Minh {
2875ce0ba88SHiep Cao Minh 	u16 spcmd;
2885ce0ba88SHiep Cao Minh 	int spbr;
2895ce0ba88SHiep Cao Minh 
2905ce0ba88SHiep Cao Minh 	/* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
2915ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPPCR);
2925ce0ba88SHiep Cao Minh 
2935ce0ba88SHiep Cao Minh 	/* Sets transfer bit rate */
2945ce0ba88SHiep Cao Minh 	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz);
2955ce0ba88SHiep Cao Minh 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
2965ce0ba88SHiep Cao Minh 
29774da7686SGeert Uytterhoeven 	/* Disable dummy transmission, set byte access */
29874da7686SGeert Uytterhoeven 	rspi_write8(rspi, 0, RSPI_SPDCR);
29974da7686SGeert Uytterhoeven 	rspi->byte_access = 1;
3005ce0ba88SHiep Cao Minh 
3015ce0ba88SHiep Cao Minh 	/* Sets RSPCK, SSL, next-access delay value */
3025ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
3035ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SSLND);
3045ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, RSPI_SPND);
3055ce0ba88SHiep Cao Minh 
3065ce0ba88SHiep Cao Minh 	/* Data Length Setting */
3075ce0ba88SHiep Cao Minh 	if (access_size == 8)
3085ce0ba88SHiep Cao Minh 		spcmd = SPCMD_SPB_8BIT;
3095ce0ba88SHiep Cao Minh 	else if (access_size == 16)
3105ce0ba88SHiep Cao Minh 		spcmd = SPCMD_SPB_16BIT;
3118e1c8096SLaurent Pinchart 	else
3125ce0ba88SHiep Cao Minh 		spcmd = SPCMD_SPB_32BIT;
3135ce0ba88SHiep Cao Minh 
314348e5153SGeert Uytterhoeven 	spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | rspi->spcmd | SPCMD_SPNDEN;
3155ce0ba88SHiep Cao Minh 
3165ce0ba88SHiep Cao Minh 	/* Resets transfer data length */
3175ce0ba88SHiep Cao Minh 	rspi_write32(rspi, 0, QSPI_SPBMUL0);
3185ce0ba88SHiep Cao Minh 
3195ce0ba88SHiep Cao Minh 	/* Resets transmit and receive buffer */
3205ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
3215ce0ba88SHiep Cao Minh 	/* Sets buffer to allow normal operation */
3225ce0ba88SHiep Cao Minh 	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
3235ce0ba88SHiep Cao Minh 
3245ce0ba88SHiep Cao Minh 	/* Sets SPCMD */
3255ce0ba88SHiep Cao Minh 	rspi_write16(rspi, spcmd, RSPI_SPCMD0);
3265ce0ba88SHiep Cao Minh 
3275ce0ba88SHiep Cao Minh 	/* Enables SPI function in a master mode */
3285ce0ba88SHiep Cao Minh 	rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR);
3295ce0ba88SHiep Cao Minh 
3305ce0ba88SHiep Cao Minh 	return 0;
3315ce0ba88SHiep Cao Minh }
3325ce0ba88SHiep Cao Minh 
3335ce0ba88SHiep Cao Minh #define set_config_register(spi, n) spi->ops->set_config_register(spi, n)
3345ce0ba88SHiep Cao Minh 
335baf588f4SGeert Uytterhoeven static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable)
3360b2182ddSShimoda, Yoshihiro {
3370b2182ddSShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR);
3380b2182ddSShimoda, Yoshihiro }
3390b2182ddSShimoda, Yoshihiro 
340baf588f4SGeert Uytterhoeven static void rspi_disable_irq(const struct rspi_data *rspi, u8 disable)
3410b2182ddSShimoda, Yoshihiro {
3420b2182ddSShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~disable, RSPI_SPCR);
3430b2182ddSShimoda, Yoshihiro }
3440b2182ddSShimoda, Yoshihiro 
3450b2182ddSShimoda, Yoshihiro static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
3460b2182ddSShimoda, Yoshihiro 				   u8 enable_bit)
3470b2182ddSShimoda, Yoshihiro {
3480b2182ddSShimoda, Yoshihiro 	int ret;
3490b2182ddSShimoda, Yoshihiro 
3500b2182ddSShimoda, Yoshihiro 	rspi->spsr = rspi_read8(rspi, RSPI_SPSR);
3510b2182ddSShimoda, Yoshihiro 	rspi_enable_irq(rspi, enable_bit);
3520b2182ddSShimoda, Yoshihiro 	ret = wait_event_timeout(rspi->wait, rspi->spsr & wait_mask, HZ);
3530b2182ddSShimoda, Yoshihiro 	if (ret == 0 && !(rspi->spsr & wait_mask))
3540b2182ddSShimoda, Yoshihiro 		return -ETIMEDOUT;
3550b2182ddSShimoda, Yoshihiro 
3560b2182ddSShimoda, Yoshihiro 	return 0;
3570b2182ddSShimoda, Yoshihiro }
3580b2182ddSShimoda, Yoshihiro 
35991949a2dSGeert Uytterhoeven static int rspi_send_pio(struct rspi_data *rspi, struct spi_transfer *t)
3600b2182ddSShimoda, Yoshihiro {
3610b2182ddSShimoda, Yoshihiro 	int remain = t->len;
362c132f094SGeert Uytterhoeven 	const u8 *data = t->tx_buf;
3630b2182ddSShimoda, Yoshihiro 	while (remain > 0) {
3640b2182ddSShimoda, Yoshihiro 		rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD,
3650b2182ddSShimoda, Yoshihiro 			    RSPI_SPCR);
3660b2182ddSShimoda, Yoshihiro 
3670b2182ddSShimoda, Yoshihiro 		if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
3680b2182ddSShimoda, Yoshihiro 			dev_err(&rspi->master->dev,
3690b2182ddSShimoda, Yoshihiro 				"%s: tx empty timeout\n", __func__);
3700b2182ddSShimoda, Yoshihiro 			return -ETIMEDOUT;
3710b2182ddSShimoda, Yoshihiro 		}
3720b2182ddSShimoda, Yoshihiro 
37374da7686SGeert Uytterhoeven 		rspi_write_data(rspi, *data);
3740b2182ddSShimoda, Yoshihiro 		data++;
3750b2182ddSShimoda, Yoshihiro 		remain--;
3760b2182ddSShimoda, Yoshihiro 	}
3770b2182ddSShimoda, Yoshihiro 
378b7ed6b88SGeert Uytterhoeven 	/* Waiting for the last transmission */
3790b2182ddSShimoda, Yoshihiro 	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
3800b2182ddSShimoda, Yoshihiro 
3810b2182ddSShimoda, Yoshihiro 	return 0;
3820b2182ddSShimoda, Yoshihiro }
3830b2182ddSShimoda, Yoshihiro 
38491949a2dSGeert Uytterhoeven static int qspi_send_pio(struct rspi_data *rspi, struct spi_transfer *t)
385cb52c673SHiep Cao Minh {
386cb52c673SHiep Cao Minh 	int remain = t->len;
387c132f094SGeert Uytterhoeven 	const u8 *data = t->tx_buf;
388cb52c673SHiep Cao Minh 
389cb52c673SHiep Cao Minh 	rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR);
390cb52c673SHiep Cao Minh 	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
391cb52c673SHiep Cao Minh 
392cb52c673SHiep Cao Minh 	while (remain > 0) {
393cb52c673SHiep Cao Minh 
394cb52c673SHiep Cao Minh 		if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
395cb52c673SHiep Cao Minh 			dev_err(&rspi->master->dev,
396cb52c673SHiep Cao Minh 				"%s: tx empty timeout\n", __func__);
397cb52c673SHiep Cao Minh 			return -ETIMEDOUT;
398cb52c673SHiep Cao Minh 		}
39974da7686SGeert Uytterhoeven 		rspi_write_data(rspi, *data++);
400cb52c673SHiep Cao Minh 
401cb52c673SHiep Cao Minh 		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
402cb52c673SHiep Cao Minh 			dev_err(&rspi->master->dev,
403cb52c673SHiep Cao Minh 				"%s: receive timeout\n", __func__);
404cb52c673SHiep Cao Minh 			return -ETIMEDOUT;
405cb52c673SHiep Cao Minh 		}
40674da7686SGeert Uytterhoeven 		rspi_read_data(rspi);
407cb52c673SHiep Cao Minh 
408cb52c673SHiep Cao Minh 		remain--;
409cb52c673SHiep Cao Minh 	}
410cb52c673SHiep Cao Minh 
411b7ed6b88SGeert Uytterhoeven 	/* Waiting for the last transmission */
412cb52c673SHiep Cao Minh 	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
413cb52c673SHiep Cao Minh 
414cb52c673SHiep Cao Minh 	return 0;
415cb52c673SHiep Cao Minh }
416cb52c673SHiep Cao Minh 
41791949a2dSGeert Uytterhoeven #define send_pio(spi, t) spi->ops->send_pio(spi, t)
418cb52c673SHiep Cao Minh 
419a3633fe7SShimoda, Yoshihiro static void rspi_dma_complete(void *arg)
4200b2182ddSShimoda, Yoshihiro {
421a3633fe7SShimoda, Yoshihiro 	struct rspi_data *rspi = arg;
422a3633fe7SShimoda, Yoshihiro 
423a3633fe7SShimoda, Yoshihiro 	rspi->dma_callbacked = 1;
424a3633fe7SShimoda, Yoshihiro 	wake_up_interruptible(&rspi->wait);
425a3633fe7SShimoda, Yoshihiro }
426a3633fe7SShimoda, Yoshihiro 
427c132f094SGeert Uytterhoeven static int rspi_dma_map_sg(struct scatterlist *sg, const void *buf,
428c132f094SGeert Uytterhoeven 			   unsigned len, struct dma_chan *chan,
429a3633fe7SShimoda, Yoshihiro 			   enum dma_transfer_direction dir)
430a3633fe7SShimoda, Yoshihiro {
431a3633fe7SShimoda, Yoshihiro 	sg_init_table(sg, 1);
432a3633fe7SShimoda, Yoshihiro 	sg_set_buf(sg, buf, len);
433a3633fe7SShimoda, Yoshihiro 	sg_dma_len(sg) = len;
434a3633fe7SShimoda, Yoshihiro 	return dma_map_sg(chan->device->dev, sg, 1, dir);
435a3633fe7SShimoda, Yoshihiro }
436a3633fe7SShimoda, Yoshihiro 
437a3633fe7SShimoda, Yoshihiro static void rspi_dma_unmap_sg(struct scatterlist *sg, struct dma_chan *chan,
438a3633fe7SShimoda, Yoshihiro 			      enum dma_transfer_direction dir)
439a3633fe7SShimoda, Yoshihiro {
440a3633fe7SShimoda, Yoshihiro 	dma_unmap_sg(chan->device->dev, sg, 1, dir);
441a3633fe7SShimoda, Yoshihiro }
442a3633fe7SShimoda, Yoshihiro 
443a3633fe7SShimoda, Yoshihiro static void rspi_memory_to_8bit(void *buf, const void *data, unsigned len)
444a3633fe7SShimoda, Yoshihiro {
445a3633fe7SShimoda, Yoshihiro 	u16 *dst = buf;
446a3633fe7SShimoda, Yoshihiro 	const u8 *src = data;
447a3633fe7SShimoda, Yoshihiro 
448a3633fe7SShimoda, Yoshihiro 	while (len) {
449a3633fe7SShimoda, Yoshihiro 		*dst++ = (u16)(*src++);
450a3633fe7SShimoda, Yoshihiro 		len--;
451a3633fe7SShimoda, Yoshihiro 	}
452a3633fe7SShimoda, Yoshihiro }
453a3633fe7SShimoda, Yoshihiro 
454a3633fe7SShimoda, Yoshihiro static void rspi_memory_from_8bit(void *buf, const void *data, unsigned len)
455a3633fe7SShimoda, Yoshihiro {
456a3633fe7SShimoda, Yoshihiro 	u8 *dst = buf;
457a3633fe7SShimoda, Yoshihiro 	const u16 *src = data;
458a3633fe7SShimoda, Yoshihiro 
459a3633fe7SShimoda, Yoshihiro 	while (len) {
460a3633fe7SShimoda, Yoshihiro 		*dst++ = (u8)*src++;
461a3633fe7SShimoda, Yoshihiro 		len--;
462a3633fe7SShimoda, Yoshihiro 	}
463a3633fe7SShimoda, Yoshihiro }
464a3633fe7SShimoda, Yoshihiro 
465a3633fe7SShimoda, Yoshihiro static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
466a3633fe7SShimoda, Yoshihiro {
467a3633fe7SShimoda, Yoshihiro 	struct scatterlist sg;
468c132f094SGeert Uytterhoeven 	const void *buf = NULL;
469a3633fe7SShimoda, Yoshihiro 	struct dma_async_tx_descriptor *desc;
470a3633fe7SShimoda, Yoshihiro 	unsigned len;
471a3633fe7SShimoda, Yoshihiro 	int ret = 0;
472a3633fe7SShimoda, Yoshihiro 
473a3633fe7SShimoda, Yoshihiro 	if (rspi->dma_width_16bit) {
474c132f094SGeert Uytterhoeven 		void *tmp;
475a3633fe7SShimoda, Yoshihiro 		/*
476a3633fe7SShimoda, Yoshihiro 		 * If DMAC bus width is 16-bit, the driver allocates a dummy
477a3633fe7SShimoda, Yoshihiro 		 * buffer. And, the driver converts original data into the
478a3633fe7SShimoda, Yoshihiro 		 * DMAC data as the following format:
479a3633fe7SShimoda, Yoshihiro 		 *  original data: 1st byte, 2nd byte ...
480a3633fe7SShimoda, Yoshihiro 		 *  DMAC data:     1st byte, dummy, 2nd byte, dummy ...
481a3633fe7SShimoda, Yoshihiro 		 */
482a3633fe7SShimoda, Yoshihiro 		len = t->len * 2;
483c132f094SGeert Uytterhoeven 		tmp = kmalloc(len, GFP_KERNEL);
484c132f094SGeert Uytterhoeven 		if (!tmp)
485a3633fe7SShimoda, Yoshihiro 			return -ENOMEM;
486c132f094SGeert Uytterhoeven 		rspi_memory_to_8bit(tmp, t->tx_buf, t->len);
487c132f094SGeert Uytterhoeven 		buf = tmp;
488a3633fe7SShimoda, Yoshihiro 	} else {
489a3633fe7SShimoda, Yoshihiro 		len = t->len;
490c132f094SGeert Uytterhoeven 		buf = t->tx_buf;
491a3633fe7SShimoda, Yoshihiro 	}
492a3633fe7SShimoda, Yoshihiro 
493a3633fe7SShimoda, Yoshihiro 	if (!rspi_dma_map_sg(&sg, buf, len, rspi->chan_tx, DMA_TO_DEVICE)) {
494a3633fe7SShimoda, Yoshihiro 		ret = -EFAULT;
495a3633fe7SShimoda, Yoshihiro 		goto end_nomap;
496a3633fe7SShimoda, Yoshihiro 	}
497a3633fe7SShimoda, Yoshihiro 	desc = dmaengine_prep_slave_sg(rspi->chan_tx, &sg, 1, DMA_TO_DEVICE,
498a3633fe7SShimoda, Yoshihiro 				       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
499a3633fe7SShimoda, Yoshihiro 	if (!desc) {
500a3633fe7SShimoda, Yoshihiro 		ret = -EIO;
501a3633fe7SShimoda, Yoshihiro 		goto end;
502a3633fe7SShimoda, Yoshihiro 	}
503a3633fe7SShimoda, Yoshihiro 
504a3633fe7SShimoda, Yoshihiro 	/*
505a3633fe7SShimoda, Yoshihiro 	 * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
506a3633fe7SShimoda, Yoshihiro 	 * called. So, this driver disables the IRQ while DMA transfer.
507a3633fe7SShimoda, Yoshihiro 	 */
508a3633fe7SShimoda, Yoshihiro 	disable_irq(rspi->irq);
509a3633fe7SShimoda, Yoshihiro 
510a3633fe7SShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD, RSPI_SPCR);
511a3633fe7SShimoda, Yoshihiro 	rspi_enable_irq(rspi, SPCR_SPTIE);
512a3633fe7SShimoda, Yoshihiro 	rspi->dma_callbacked = 0;
513a3633fe7SShimoda, Yoshihiro 
514a3633fe7SShimoda, Yoshihiro 	desc->callback = rspi_dma_complete;
515a3633fe7SShimoda, Yoshihiro 	desc->callback_param = rspi;
516a3633fe7SShimoda, Yoshihiro 	dmaengine_submit(desc);
517a3633fe7SShimoda, Yoshihiro 	dma_async_issue_pending(rspi->chan_tx);
518a3633fe7SShimoda, Yoshihiro 
519a3633fe7SShimoda, Yoshihiro 	ret = wait_event_interruptible_timeout(rspi->wait,
520a3633fe7SShimoda, Yoshihiro 					       rspi->dma_callbacked, HZ);
521a3633fe7SShimoda, Yoshihiro 	if (ret > 0 && rspi->dma_callbacked)
522a3633fe7SShimoda, Yoshihiro 		ret = 0;
523a3633fe7SShimoda, Yoshihiro 	else if (!ret)
524a3633fe7SShimoda, Yoshihiro 		ret = -ETIMEDOUT;
525a3633fe7SShimoda, Yoshihiro 	rspi_disable_irq(rspi, SPCR_SPTIE);
526a3633fe7SShimoda, Yoshihiro 
527a3633fe7SShimoda, Yoshihiro 	enable_irq(rspi->irq);
528a3633fe7SShimoda, Yoshihiro 
529a3633fe7SShimoda, Yoshihiro end:
530a3633fe7SShimoda, Yoshihiro 	rspi_dma_unmap_sg(&sg, rspi->chan_tx, DMA_TO_DEVICE);
531a3633fe7SShimoda, Yoshihiro end_nomap:
532a3633fe7SShimoda, Yoshihiro 	if (rspi->dma_width_16bit)
533a3633fe7SShimoda, Yoshihiro 		kfree(buf);
534a3633fe7SShimoda, Yoshihiro 
535a3633fe7SShimoda, Yoshihiro 	return ret;
536a3633fe7SShimoda, Yoshihiro }
537a3633fe7SShimoda, Yoshihiro 
538baf588f4SGeert Uytterhoeven static void rspi_receive_init(const struct rspi_data *rspi)
539a3633fe7SShimoda, Yoshihiro {
54097b95c11SGeert Uytterhoeven 	u8 spsr;
5410b2182ddSShimoda, Yoshihiro 
5420b2182ddSShimoda, Yoshihiro 	spsr = rspi_read8(rspi, RSPI_SPSR);
5430b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPRF)
54474da7686SGeert Uytterhoeven 		rspi_read_data(rspi);	/* dummy read */
5450b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_OVRF)
5460b2182ddSShimoda, Yoshihiro 		rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF,
547df900e67SGeert Uytterhoeven 			    RSPI_SPSR);
548a3633fe7SShimoda, Yoshihiro }
549a3633fe7SShimoda, Yoshihiro 
55091949a2dSGeert Uytterhoeven static int rspi_receive_pio(struct rspi_data *rspi, struct spi_transfer *t)
551a3633fe7SShimoda, Yoshihiro {
552a3633fe7SShimoda, Yoshihiro 	int remain = t->len;
553a3633fe7SShimoda, Yoshihiro 	u8 *data;
554a3633fe7SShimoda, Yoshihiro 
555a3633fe7SShimoda, Yoshihiro 	rspi_receive_init(rspi);
5560b2182ddSShimoda, Yoshihiro 
557c132f094SGeert Uytterhoeven 	data = t->rx_buf;
5580b2182ddSShimoda, Yoshihiro 	while (remain > 0) {
5590b2182ddSShimoda, Yoshihiro 		rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD,
5600b2182ddSShimoda, Yoshihiro 			    RSPI_SPCR);
5610b2182ddSShimoda, Yoshihiro 
5620b2182ddSShimoda, Yoshihiro 		if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
5630b2182ddSShimoda, Yoshihiro 			dev_err(&rspi->master->dev,
5640b2182ddSShimoda, Yoshihiro 				"%s: tx empty timeout\n", __func__);
5650b2182ddSShimoda, Yoshihiro 			return -ETIMEDOUT;
5660b2182ddSShimoda, Yoshihiro 		}
5670b2182ddSShimoda, Yoshihiro 		/* dummy write for generate clock */
56874da7686SGeert Uytterhoeven 		rspi_write_data(rspi, DUMMY_DATA);
5690b2182ddSShimoda, Yoshihiro 
5700b2182ddSShimoda, Yoshihiro 		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
5710b2182ddSShimoda, Yoshihiro 			dev_err(&rspi->master->dev,
5720b2182ddSShimoda, Yoshihiro 				"%s: receive timeout\n", __func__);
5730b2182ddSShimoda, Yoshihiro 			return -ETIMEDOUT;
5740b2182ddSShimoda, Yoshihiro 		}
57574da7686SGeert Uytterhoeven 		*data = rspi_read_data(rspi);
5760b2182ddSShimoda, Yoshihiro 
5770b2182ddSShimoda, Yoshihiro 		data++;
5780b2182ddSShimoda, Yoshihiro 		remain--;
5790b2182ddSShimoda, Yoshihiro 	}
5800b2182ddSShimoda, Yoshihiro 
5810b2182ddSShimoda, Yoshihiro 	return 0;
5820b2182ddSShimoda, Yoshihiro }
5830b2182ddSShimoda, Yoshihiro 
584baf588f4SGeert Uytterhoeven static void qspi_receive_init(const struct rspi_data *rspi)
585cb52c673SHiep Cao Minh {
58697b95c11SGeert Uytterhoeven 	u8 spsr;
587cb52c673SHiep Cao Minh 
588cb52c673SHiep Cao Minh 	spsr = rspi_read8(rspi, RSPI_SPSR);
589cb52c673SHiep Cao Minh 	if (spsr & SPSR_SPRF)
59074da7686SGeert Uytterhoeven 		rspi_read_data(rspi);   /* dummy read */
591cb52c673SHiep Cao Minh 	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
592cb52c673SHiep Cao Minh 	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
593cb52c673SHiep Cao Minh }
594cb52c673SHiep Cao Minh 
59591949a2dSGeert Uytterhoeven static int qspi_receive_pio(struct rspi_data *rspi, struct spi_transfer *t)
596cb52c673SHiep Cao Minh {
597cb52c673SHiep Cao Minh 	int remain = t->len;
598cb52c673SHiep Cao Minh 	u8 *data;
599cb52c673SHiep Cao Minh 
600cb52c673SHiep Cao Minh 	qspi_receive_init(rspi);
601cb52c673SHiep Cao Minh 
602c132f094SGeert Uytterhoeven 	data = t->rx_buf;
603cb52c673SHiep Cao Minh 	while (remain > 0) {
604cb52c673SHiep Cao Minh 
605cb52c673SHiep Cao Minh 		if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
606cb52c673SHiep Cao Minh 			dev_err(&rspi->master->dev,
607cb52c673SHiep Cao Minh 				"%s: tx empty timeout\n", __func__);
608cb52c673SHiep Cao Minh 			return -ETIMEDOUT;
609cb52c673SHiep Cao Minh 		}
610cb52c673SHiep Cao Minh 		/* dummy write for generate clock */
61174da7686SGeert Uytterhoeven 		rspi_write_data(rspi, DUMMY_DATA);
612cb52c673SHiep Cao Minh 
613cb52c673SHiep Cao Minh 		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
614cb52c673SHiep Cao Minh 			dev_err(&rspi->master->dev,
615cb52c673SHiep Cao Minh 				"%s: receive timeout\n", __func__);
616cb52c673SHiep Cao Minh 			return -ETIMEDOUT;
617cb52c673SHiep Cao Minh 		}
61874da7686SGeert Uytterhoeven 		*data++ = rspi_read_data(rspi);
619cb52c673SHiep Cao Minh 		remain--;
620cb52c673SHiep Cao Minh 	}
621cb52c673SHiep Cao Minh 
622cb52c673SHiep Cao Minh 	return 0;
623cb52c673SHiep Cao Minh }
624cb52c673SHiep Cao Minh 
62591949a2dSGeert Uytterhoeven #define receive_pio(spi, t) spi->ops->receive_pio(spi, t)
626cb52c673SHiep Cao Minh 
627a3633fe7SShimoda, Yoshihiro static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
628a3633fe7SShimoda, Yoshihiro {
629a3633fe7SShimoda, Yoshihiro 	struct scatterlist sg, sg_dummy;
630a3633fe7SShimoda, Yoshihiro 	void *dummy = NULL, *rx_buf = NULL;
631a3633fe7SShimoda, Yoshihiro 	struct dma_async_tx_descriptor *desc, *desc_dummy;
632a3633fe7SShimoda, Yoshihiro 	unsigned len;
633a3633fe7SShimoda, Yoshihiro 	int ret = 0;
634a3633fe7SShimoda, Yoshihiro 
635a3633fe7SShimoda, Yoshihiro 	if (rspi->dma_width_16bit) {
636a3633fe7SShimoda, Yoshihiro 		/*
637a3633fe7SShimoda, Yoshihiro 		 * If DMAC bus width is 16-bit, the driver allocates a dummy
638a3633fe7SShimoda, Yoshihiro 		 * buffer. And, finally the driver converts the DMAC data into
639a3633fe7SShimoda, Yoshihiro 		 * actual data as the following format:
640a3633fe7SShimoda, Yoshihiro 		 *  DMAC data:   1st byte, dummy, 2nd byte, dummy ...
641a3633fe7SShimoda, Yoshihiro 		 *  actual data: 1st byte, 2nd byte ...
642a3633fe7SShimoda, Yoshihiro 		 */
643a3633fe7SShimoda, Yoshihiro 		len = t->len * 2;
644a3633fe7SShimoda, Yoshihiro 		rx_buf = kmalloc(len, GFP_KERNEL);
645a3633fe7SShimoda, Yoshihiro 		if (!rx_buf)
646a3633fe7SShimoda, Yoshihiro 			return -ENOMEM;
647a3633fe7SShimoda, Yoshihiro 	 } else {
648a3633fe7SShimoda, Yoshihiro 		len = t->len;
649a3633fe7SShimoda, Yoshihiro 		rx_buf = t->rx_buf;
650a3633fe7SShimoda, Yoshihiro 	}
651a3633fe7SShimoda, Yoshihiro 
652a3633fe7SShimoda, Yoshihiro 	/* prepare dummy transfer to generate SPI clocks */
653a3633fe7SShimoda, Yoshihiro 	dummy = kzalloc(len, GFP_KERNEL);
654a3633fe7SShimoda, Yoshihiro 	if (!dummy) {
655a3633fe7SShimoda, Yoshihiro 		ret = -ENOMEM;
656a3633fe7SShimoda, Yoshihiro 		goto end_nomap;
657a3633fe7SShimoda, Yoshihiro 	}
658a3633fe7SShimoda, Yoshihiro 	if (!rspi_dma_map_sg(&sg_dummy, dummy, len, rspi->chan_tx,
659a3633fe7SShimoda, Yoshihiro 			     DMA_TO_DEVICE)) {
660a3633fe7SShimoda, Yoshihiro 		ret = -EFAULT;
661a3633fe7SShimoda, Yoshihiro 		goto end_nomap;
662a3633fe7SShimoda, Yoshihiro 	}
663a3633fe7SShimoda, Yoshihiro 	desc_dummy = dmaengine_prep_slave_sg(rspi->chan_tx, &sg_dummy, 1,
664a3633fe7SShimoda, Yoshihiro 			DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
665a3633fe7SShimoda, Yoshihiro 	if (!desc_dummy) {
666a3633fe7SShimoda, Yoshihiro 		ret = -EIO;
667a3633fe7SShimoda, Yoshihiro 		goto end_dummy_mapped;
668a3633fe7SShimoda, Yoshihiro 	}
669a3633fe7SShimoda, Yoshihiro 
670a3633fe7SShimoda, Yoshihiro 	/* prepare receive transfer */
671a3633fe7SShimoda, Yoshihiro 	if (!rspi_dma_map_sg(&sg, rx_buf, len, rspi->chan_rx,
672a3633fe7SShimoda, Yoshihiro 			     DMA_FROM_DEVICE)) {
673a3633fe7SShimoda, Yoshihiro 		ret = -EFAULT;
674a3633fe7SShimoda, Yoshihiro 		goto end_dummy_mapped;
675a3633fe7SShimoda, Yoshihiro 
676a3633fe7SShimoda, Yoshihiro 	}
677a3633fe7SShimoda, Yoshihiro 	desc = dmaengine_prep_slave_sg(rspi->chan_rx, &sg, 1, DMA_FROM_DEVICE,
678a3633fe7SShimoda, Yoshihiro 				       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
679a3633fe7SShimoda, Yoshihiro 	if (!desc) {
680a3633fe7SShimoda, Yoshihiro 		ret = -EIO;
681a3633fe7SShimoda, Yoshihiro 		goto end;
682a3633fe7SShimoda, Yoshihiro 	}
683a3633fe7SShimoda, Yoshihiro 
684a3633fe7SShimoda, Yoshihiro 	rspi_receive_init(rspi);
685a3633fe7SShimoda, Yoshihiro 
686a3633fe7SShimoda, Yoshihiro 	/*
687a3633fe7SShimoda, Yoshihiro 	 * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
688a3633fe7SShimoda, Yoshihiro 	 * called. So, this driver disables the IRQ while DMA transfer.
689a3633fe7SShimoda, Yoshihiro 	 */
690a3633fe7SShimoda, Yoshihiro 	disable_irq(rspi->irq);
691a3633fe7SShimoda, Yoshihiro 
692a3633fe7SShimoda, Yoshihiro 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD, RSPI_SPCR);
693a3633fe7SShimoda, Yoshihiro 	rspi_enable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
694a3633fe7SShimoda, Yoshihiro 	rspi->dma_callbacked = 0;
695a3633fe7SShimoda, Yoshihiro 
696a3633fe7SShimoda, Yoshihiro 	desc->callback = rspi_dma_complete;
697a3633fe7SShimoda, Yoshihiro 	desc->callback_param = rspi;
698a3633fe7SShimoda, Yoshihiro 	dmaengine_submit(desc);
699a3633fe7SShimoda, Yoshihiro 	dma_async_issue_pending(rspi->chan_rx);
700a3633fe7SShimoda, Yoshihiro 
701a3633fe7SShimoda, Yoshihiro 	desc_dummy->callback = NULL;	/* No callback */
702a3633fe7SShimoda, Yoshihiro 	dmaengine_submit(desc_dummy);
703a3633fe7SShimoda, Yoshihiro 	dma_async_issue_pending(rspi->chan_tx);
704a3633fe7SShimoda, Yoshihiro 
705a3633fe7SShimoda, Yoshihiro 	ret = wait_event_interruptible_timeout(rspi->wait,
706a3633fe7SShimoda, Yoshihiro 					       rspi->dma_callbacked, HZ);
707a3633fe7SShimoda, Yoshihiro 	if (ret > 0 && rspi->dma_callbacked)
708a3633fe7SShimoda, Yoshihiro 		ret = 0;
709a3633fe7SShimoda, Yoshihiro 	else if (!ret)
710a3633fe7SShimoda, Yoshihiro 		ret = -ETIMEDOUT;
711a3633fe7SShimoda, Yoshihiro 	rspi_disable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
712a3633fe7SShimoda, Yoshihiro 
713a3633fe7SShimoda, Yoshihiro 	enable_irq(rspi->irq);
714a3633fe7SShimoda, Yoshihiro 
715a3633fe7SShimoda, Yoshihiro end:
716a3633fe7SShimoda, Yoshihiro 	rspi_dma_unmap_sg(&sg, rspi->chan_rx, DMA_FROM_DEVICE);
717a3633fe7SShimoda, Yoshihiro end_dummy_mapped:
718a3633fe7SShimoda, Yoshihiro 	rspi_dma_unmap_sg(&sg_dummy, rspi->chan_tx, DMA_TO_DEVICE);
719a3633fe7SShimoda, Yoshihiro end_nomap:
720a3633fe7SShimoda, Yoshihiro 	if (rspi->dma_width_16bit) {
721a3633fe7SShimoda, Yoshihiro 		if (!ret)
722a3633fe7SShimoda, Yoshihiro 			rspi_memory_from_8bit(t->rx_buf, rx_buf, t->len);
723a3633fe7SShimoda, Yoshihiro 		kfree(rx_buf);
724a3633fe7SShimoda, Yoshihiro 	}
725a3633fe7SShimoda, Yoshihiro 	kfree(dummy);
726a3633fe7SShimoda, Yoshihiro 
727a3633fe7SShimoda, Yoshihiro 	return ret;
728a3633fe7SShimoda, Yoshihiro }
729a3633fe7SShimoda, Yoshihiro 
730baf588f4SGeert Uytterhoeven static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t)
731a3633fe7SShimoda, Yoshihiro {
732a3633fe7SShimoda, Yoshihiro 	if (t->tx_buf && rspi->chan_tx)
733a3633fe7SShimoda, Yoshihiro 		return 1;
734a3633fe7SShimoda, Yoshihiro 	/* If the module receives data by DMAC, it also needs TX DMAC */
735a3633fe7SShimoda, Yoshihiro 	if (t->rx_buf && rspi->chan_tx && rspi->chan_rx)
736a3633fe7SShimoda, Yoshihiro 		return 1;
737a3633fe7SShimoda, Yoshihiro 
738a3633fe7SShimoda, Yoshihiro 	return 0;
739a3633fe7SShimoda, Yoshihiro }
740a3633fe7SShimoda, Yoshihiro 
74179d23495SGeert Uytterhoeven static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
74279d23495SGeert Uytterhoeven 			     struct spi_transfer *xfer)
7430b2182ddSShimoda, Yoshihiro {
74479d23495SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
74579d23495SGeert Uytterhoeven 	int ret = 0;
7460b2182ddSShimoda, Yoshihiro 
74779d23495SGeert Uytterhoeven 	if (xfer->tx_buf) {
74879d23495SGeert Uytterhoeven 		if (rspi_is_dma(rspi, xfer))
74979d23495SGeert Uytterhoeven 			ret = rspi_send_dma(rspi, xfer);
750a3633fe7SShimoda, Yoshihiro 		else
75179d23495SGeert Uytterhoeven 			ret = send_pio(rspi, xfer);
7520b2182ddSShimoda, Yoshihiro 		if (ret < 0)
75379d23495SGeert Uytterhoeven 			return ret;
7540b2182ddSShimoda, Yoshihiro 	}
75579d23495SGeert Uytterhoeven 	if (xfer->rx_buf) {
75679d23495SGeert Uytterhoeven 		if (rspi_is_dma(rspi, xfer))
75779d23495SGeert Uytterhoeven 			ret = rspi_receive_dma(rspi, xfer);
758a3633fe7SShimoda, Yoshihiro 		else
75979d23495SGeert Uytterhoeven 			ret = receive_pio(rspi, xfer);
7600b2182ddSShimoda, Yoshihiro 	}
76179d23495SGeert Uytterhoeven 	return ret;
7620b2182ddSShimoda, Yoshihiro }
7630b2182ddSShimoda, Yoshihiro 
7640b2182ddSShimoda, Yoshihiro static int rspi_setup(struct spi_device *spi)
7650b2182ddSShimoda, Yoshihiro {
7660b2182ddSShimoda, Yoshihiro 	struct rspi_data *rspi = spi_master_get_devdata(spi->master);
7670b2182ddSShimoda, Yoshihiro 
7680b2182ddSShimoda, Yoshihiro 	rspi->max_speed_hz = spi->max_speed_hz;
7690b2182ddSShimoda, Yoshihiro 
770348e5153SGeert Uytterhoeven 	rspi->spcmd = SPCMD_SSLKP;
771348e5153SGeert Uytterhoeven 	if (spi->mode & SPI_CPOL)
772348e5153SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_CPOL;
773348e5153SGeert Uytterhoeven 	if (spi->mode & SPI_CPHA)
774348e5153SGeert Uytterhoeven 		rspi->spcmd |= SPCMD_CPHA;
775348e5153SGeert Uytterhoeven 
7765ce0ba88SHiep Cao Minh 	set_config_register(rspi, 8);
7770b2182ddSShimoda, Yoshihiro 
7780b2182ddSShimoda, Yoshihiro 	return 0;
7790b2182ddSShimoda, Yoshihiro }
7800b2182ddSShimoda, Yoshihiro 
78179d23495SGeert Uytterhoeven static void rspi_cleanup(struct spi_device *spi)
7820b2182ddSShimoda, Yoshihiro {
78379d23495SGeert Uytterhoeven }
7840b2182ddSShimoda, Yoshihiro 
78579d23495SGeert Uytterhoeven static int rspi_prepare_message(struct spi_master *master,
78679d23495SGeert Uytterhoeven 				struct spi_message *message)
78779d23495SGeert Uytterhoeven {
78879d23495SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
7890b2182ddSShimoda, Yoshihiro 
79079d23495SGeert Uytterhoeven 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
7910b2182ddSShimoda, Yoshihiro 	return 0;
7920b2182ddSShimoda, Yoshihiro }
7930b2182ddSShimoda, Yoshihiro 
79479d23495SGeert Uytterhoeven static int rspi_unprepare_message(struct spi_master *master,
79579d23495SGeert Uytterhoeven 				  struct spi_message *message)
7960b2182ddSShimoda, Yoshihiro {
79779d23495SGeert Uytterhoeven 	struct rspi_data *rspi = spi_master_get_devdata(master);
79879d23495SGeert Uytterhoeven 
79979d23495SGeert Uytterhoeven 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
80079d23495SGeert Uytterhoeven 	return 0;
8010b2182ddSShimoda, Yoshihiro }
8020b2182ddSShimoda, Yoshihiro 
8030b2182ddSShimoda, Yoshihiro static irqreturn_t rspi_irq(int irq, void *_sr)
8040b2182ddSShimoda, Yoshihiro {
805c132f094SGeert Uytterhoeven 	struct rspi_data *rspi = _sr;
80697b95c11SGeert Uytterhoeven 	u8 spsr;
8070b2182ddSShimoda, Yoshihiro 	irqreturn_t ret = IRQ_NONE;
80897b95c11SGeert Uytterhoeven 	u8 disable_irq = 0;
8090b2182ddSShimoda, Yoshihiro 
8100b2182ddSShimoda, Yoshihiro 	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
8110b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPRF)
8120b2182ddSShimoda, Yoshihiro 		disable_irq |= SPCR_SPRIE;
8130b2182ddSShimoda, Yoshihiro 	if (spsr & SPSR_SPTEF)
8140b2182ddSShimoda, Yoshihiro 		disable_irq |= SPCR_SPTIE;
8150b2182ddSShimoda, Yoshihiro 
8160b2182ddSShimoda, Yoshihiro 	if (disable_irq) {
8170b2182ddSShimoda, Yoshihiro 		ret = IRQ_HANDLED;
8180b2182ddSShimoda, Yoshihiro 		rspi_disable_irq(rspi, disable_irq);
8190b2182ddSShimoda, Yoshihiro 		wake_up(&rspi->wait);
8200b2182ddSShimoda, Yoshihiro 	}
8210b2182ddSShimoda, Yoshihiro 
8220b2182ddSShimoda, Yoshihiro 	return ret;
8230b2182ddSShimoda, Yoshihiro }
8240b2182ddSShimoda, Yoshihiro 
825fd4a319bSGrant Likely static int rspi_request_dma(struct rspi_data *rspi,
826a3633fe7SShimoda, Yoshihiro 				      struct platform_device *pdev)
827a3633fe7SShimoda, Yoshihiro {
828baf588f4SGeert Uytterhoeven 	const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
829e2b05099SGuennadi Liakhovetski 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
830a3633fe7SShimoda, Yoshihiro 	dma_cap_mask_t mask;
8310243c536SShimoda, Yoshihiro 	struct dma_slave_config cfg;
8320243c536SShimoda, Yoshihiro 	int ret;
833a3633fe7SShimoda, Yoshihiro 
834e2b05099SGuennadi Liakhovetski 	if (!res || !rspi_pd)
8350243c536SShimoda, Yoshihiro 		return 0;	/* The driver assumes no error. */
836a3633fe7SShimoda, Yoshihiro 
837a3633fe7SShimoda, Yoshihiro 	rspi->dma_width_16bit = rspi_pd->dma_width_16bit;
838a3633fe7SShimoda, Yoshihiro 
839a3633fe7SShimoda, Yoshihiro 	/* If the module receives data by DMAC, it also needs TX DMAC */
840a3633fe7SShimoda, Yoshihiro 	if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) {
841a3633fe7SShimoda, Yoshihiro 		dma_cap_zero(mask);
842a3633fe7SShimoda, Yoshihiro 		dma_cap_set(DMA_SLAVE, mask);
8430243c536SShimoda, Yoshihiro 		rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter,
8440243c536SShimoda, Yoshihiro 						    (void *)rspi_pd->dma_rx_id);
8450243c536SShimoda, Yoshihiro 		if (rspi->chan_rx) {
8460243c536SShimoda, Yoshihiro 			cfg.slave_id = rspi_pd->dma_rx_id;
8470243c536SShimoda, Yoshihiro 			cfg.direction = DMA_DEV_TO_MEM;
848e2b05099SGuennadi Liakhovetski 			cfg.dst_addr = 0;
849e2b05099SGuennadi Liakhovetski 			cfg.src_addr = res->start + RSPI_SPDR;
8500243c536SShimoda, Yoshihiro 			ret = dmaengine_slave_config(rspi->chan_rx, &cfg);
8510243c536SShimoda, Yoshihiro 			if (!ret)
852a3633fe7SShimoda, Yoshihiro 				dev_info(&pdev->dev, "Use DMA when rx.\n");
8530243c536SShimoda, Yoshihiro 			else
8540243c536SShimoda, Yoshihiro 				return ret;
8550243c536SShimoda, Yoshihiro 		}
856a3633fe7SShimoda, Yoshihiro 	}
857a3633fe7SShimoda, Yoshihiro 	if (rspi_pd->dma_tx_id) {
858a3633fe7SShimoda, Yoshihiro 		dma_cap_zero(mask);
859a3633fe7SShimoda, Yoshihiro 		dma_cap_set(DMA_SLAVE, mask);
8600243c536SShimoda, Yoshihiro 		rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter,
8610243c536SShimoda, Yoshihiro 						    (void *)rspi_pd->dma_tx_id);
8620243c536SShimoda, Yoshihiro 		if (rspi->chan_tx) {
8630243c536SShimoda, Yoshihiro 			cfg.slave_id = rspi_pd->dma_tx_id;
8640243c536SShimoda, Yoshihiro 			cfg.direction = DMA_MEM_TO_DEV;
865e2b05099SGuennadi Liakhovetski 			cfg.dst_addr = res->start + RSPI_SPDR;
866e2b05099SGuennadi Liakhovetski 			cfg.src_addr = 0;
8670243c536SShimoda, Yoshihiro 			ret = dmaengine_slave_config(rspi->chan_tx, &cfg);
8680243c536SShimoda, Yoshihiro 			if (!ret)
869a3633fe7SShimoda, Yoshihiro 				dev_info(&pdev->dev, "Use DMA when tx\n");
8700243c536SShimoda, Yoshihiro 			else
8710243c536SShimoda, Yoshihiro 				return ret;
872a3633fe7SShimoda, Yoshihiro 		}
873a3633fe7SShimoda, Yoshihiro 	}
874a3633fe7SShimoda, Yoshihiro 
8750243c536SShimoda, Yoshihiro 	return 0;
8760243c536SShimoda, Yoshihiro }
8770243c536SShimoda, Yoshihiro 
878fd4a319bSGrant Likely static void rspi_release_dma(struct rspi_data *rspi)
879a3633fe7SShimoda, Yoshihiro {
880a3633fe7SShimoda, Yoshihiro 	if (rspi->chan_tx)
881a3633fe7SShimoda, Yoshihiro 		dma_release_channel(rspi->chan_tx);
882a3633fe7SShimoda, Yoshihiro 	if (rspi->chan_rx)
883a3633fe7SShimoda, Yoshihiro 		dma_release_channel(rspi->chan_rx);
884a3633fe7SShimoda, Yoshihiro }
885a3633fe7SShimoda, Yoshihiro 
886fd4a319bSGrant Likely static int rspi_remove(struct platform_device *pdev)
8870b2182ddSShimoda, Yoshihiro {
8885ffbe2d9SLaurent Pinchart 	struct rspi_data *rspi = platform_get_drvdata(pdev);
8890b2182ddSShimoda, Yoshihiro 
890a3633fe7SShimoda, Yoshihiro 	rspi_release_dma(rspi);
891fcb4ed74SGeert Uytterhoeven 	clk_disable(rspi->clk);
8920b2182ddSShimoda, Yoshihiro 
8930b2182ddSShimoda, Yoshihiro 	return 0;
8940b2182ddSShimoda, Yoshihiro }
8950b2182ddSShimoda, Yoshihiro 
896fd4a319bSGrant Likely static int rspi_probe(struct platform_device *pdev)
8970b2182ddSShimoda, Yoshihiro {
8980b2182ddSShimoda, Yoshihiro 	struct resource *res;
8990b2182ddSShimoda, Yoshihiro 	struct spi_master *master;
9000b2182ddSShimoda, Yoshihiro 	struct rspi_data *rspi;
9010b2182ddSShimoda, Yoshihiro 	int ret, irq;
9020b2182ddSShimoda, Yoshihiro 	char clk_name[16];
903baf588f4SGeert Uytterhoeven 	const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
9045ce0ba88SHiep Cao Minh 	const struct spi_ops *ops;
9055ce0ba88SHiep Cao Minh 	const struct platform_device_id *id_entry = pdev->id_entry;
9060b2182ddSShimoda, Yoshihiro 
9075ce0ba88SHiep Cao Minh 	ops = (struct spi_ops *)id_entry->driver_data;
9085ce0ba88SHiep Cao Minh 	/* ops parameter check */
9095ce0ba88SHiep Cao Minh 	if (!ops->set_config_register) {
9105ce0ba88SHiep Cao Minh 		dev_err(&pdev->dev, "there is no set_config_register\n");
9115ce0ba88SHiep Cao Minh 		return -ENODEV;
9125ce0ba88SHiep Cao Minh 	}
9130b2182ddSShimoda, Yoshihiro 
9140b2182ddSShimoda, Yoshihiro 	irq = platform_get_irq(pdev, 0);
9150b2182ddSShimoda, Yoshihiro 	if (irq < 0) {
9160b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "platform_get_irq error\n");
9170b2182ddSShimoda, Yoshihiro 		return -ENODEV;
9180b2182ddSShimoda, Yoshihiro 	}
9190b2182ddSShimoda, Yoshihiro 
9200b2182ddSShimoda, Yoshihiro 	master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data));
9210b2182ddSShimoda, Yoshihiro 	if (master == NULL) {
9220b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "spi_alloc_master error.\n");
9230b2182ddSShimoda, Yoshihiro 		return -ENOMEM;
9240b2182ddSShimoda, Yoshihiro 	}
9250b2182ddSShimoda, Yoshihiro 
9260b2182ddSShimoda, Yoshihiro 	rspi = spi_master_get_devdata(master);
92724b5a82cSJingoo Han 	platform_set_drvdata(pdev, rspi);
9285ce0ba88SHiep Cao Minh 	rspi->ops = ops;
9290b2182ddSShimoda, Yoshihiro 	rspi->master = master;
9305d79e9acSLaurent Pinchart 
9315d79e9acSLaurent Pinchart 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
9325d79e9acSLaurent Pinchart 	rspi->addr = devm_ioremap_resource(&pdev->dev, res);
9335d79e9acSLaurent Pinchart 	if (IS_ERR(rspi->addr)) {
9345d79e9acSLaurent Pinchart 		ret = PTR_ERR(rspi->addr);
9350b2182ddSShimoda, Yoshihiro 		goto error1;
9360b2182ddSShimoda, Yoshihiro 	}
9370b2182ddSShimoda, Yoshihiro 
9385ce0ba88SHiep Cao Minh 	snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id);
9395d79e9acSLaurent Pinchart 	rspi->clk = devm_clk_get(&pdev->dev, clk_name);
9400b2182ddSShimoda, Yoshihiro 	if (IS_ERR(rspi->clk)) {
9410b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "cannot get clock\n");
9420b2182ddSShimoda, Yoshihiro 		ret = PTR_ERR(rspi->clk);
9435d79e9acSLaurent Pinchart 		goto error1;
9440b2182ddSShimoda, Yoshihiro 	}
9450b2182ddSShimoda, Yoshihiro 	clk_enable(rspi->clk);
9460b2182ddSShimoda, Yoshihiro 
9470b2182ddSShimoda, Yoshihiro 	init_waitqueue_head(&rspi->wait);
9480b2182ddSShimoda, Yoshihiro 
949efd85acbSGeert Uytterhoeven 	if (rspi_pd && rspi_pd->num_chipselect)
9505ce0ba88SHiep Cao Minh 		master->num_chipselect = rspi_pd->num_chipselect;
951efd85acbSGeert Uytterhoeven 	else
9525ce0ba88SHiep Cao Minh 		master->num_chipselect = 2; /* default */
9535ce0ba88SHiep Cao Minh 
9540b2182ddSShimoda, Yoshihiro 	master->bus_num = pdev->id;
9550b2182ddSShimoda, Yoshihiro 	master->setup = rspi_setup;
95679d23495SGeert Uytterhoeven 	master->transfer_one = rspi_transfer_one;
9570b2182ddSShimoda, Yoshihiro 	master->cleanup = rspi_cleanup;
95879d23495SGeert Uytterhoeven 	master->prepare_message = rspi_prepare_message;
95979d23495SGeert Uytterhoeven 	master->unprepare_message = rspi_unprepare_message;
960348e5153SGeert Uytterhoeven 	master->mode_bits = SPI_CPHA | SPI_CPOL;
9610b2182ddSShimoda, Yoshihiro 
9625d79e9acSLaurent Pinchart 	ret = devm_request_irq(&pdev->dev, irq, rspi_irq, 0,
9635d79e9acSLaurent Pinchart 			       dev_name(&pdev->dev), rspi);
9640b2182ddSShimoda, Yoshihiro 	if (ret < 0) {
9650b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "request_irq error\n");
966fcb4ed74SGeert Uytterhoeven 		goto error2;
9670b2182ddSShimoda, Yoshihiro 	}
9680b2182ddSShimoda, Yoshihiro 
969a3633fe7SShimoda, Yoshihiro 	rspi->irq = irq;
9700243c536SShimoda, Yoshihiro 	ret = rspi_request_dma(rspi, pdev);
9710243c536SShimoda, Yoshihiro 	if (ret < 0) {
9720243c536SShimoda, Yoshihiro 		dev_err(&pdev->dev, "rspi_request_dma failed.\n");
973fcb4ed74SGeert Uytterhoeven 		goto error3;
9740243c536SShimoda, Yoshihiro 	}
975a3633fe7SShimoda, Yoshihiro 
9769e03d05eSJingoo Han 	ret = devm_spi_register_master(&pdev->dev, master);
9770b2182ddSShimoda, Yoshihiro 	if (ret < 0) {
9780b2182ddSShimoda, Yoshihiro 		dev_err(&pdev->dev, "spi_register_master error.\n");
979fcb4ed74SGeert Uytterhoeven 		goto error3;
9800b2182ddSShimoda, Yoshihiro 	}
9810b2182ddSShimoda, Yoshihiro 
9820b2182ddSShimoda, Yoshihiro 	dev_info(&pdev->dev, "probed\n");
9830b2182ddSShimoda, Yoshihiro 
9840b2182ddSShimoda, Yoshihiro 	return 0;
9850b2182ddSShimoda, Yoshihiro 
986fcb4ed74SGeert Uytterhoeven error3:
9875d79e9acSLaurent Pinchart 	rspi_release_dma(rspi);
988fcb4ed74SGeert Uytterhoeven error2:
989fcb4ed74SGeert Uytterhoeven 	clk_disable(rspi->clk);
9900b2182ddSShimoda, Yoshihiro error1:
9910b2182ddSShimoda, Yoshihiro 	spi_master_put(master);
9920b2182ddSShimoda, Yoshihiro 
9930b2182ddSShimoda, Yoshihiro 	return ret;
9940b2182ddSShimoda, Yoshihiro }
9950b2182ddSShimoda, Yoshihiro 
9965ce0ba88SHiep Cao Minh static struct spi_ops rspi_ops = {
9975ce0ba88SHiep Cao Minh 	.set_config_register =		rspi_set_config_register,
998cb52c673SHiep Cao Minh 	.send_pio =			rspi_send_pio,
999cb52c673SHiep Cao Minh 	.receive_pio =			rspi_receive_pio,
10005ce0ba88SHiep Cao Minh };
10015ce0ba88SHiep Cao Minh 
10025ce0ba88SHiep Cao Minh static struct spi_ops qspi_ops = {
10035ce0ba88SHiep Cao Minh 	.set_config_register =		qspi_set_config_register,
1004cb52c673SHiep Cao Minh 	.send_pio =			qspi_send_pio,
1005cb52c673SHiep Cao Minh 	.receive_pio =			qspi_receive_pio,
10065ce0ba88SHiep Cao Minh };
10075ce0ba88SHiep Cao Minh 
10085ce0ba88SHiep Cao Minh static struct platform_device_id spi_driver_ids[] = {
10095ce0ba88SHiep Cao Minh 	{ "rspi",	(kernel_ulong_t)&rspi_ops },
10105ce0ba88SHiep Cao Minh 	{ "qspi",	(kernel_ulong_t)&qspi_ops },
10115ce0ba88SHiep Cao Minh 	{},
10125ce0ba88SHiep Cao Minh };
10135ce0ba88SHiep Cao Minh 
10145ce0ba88SHiep Cao Minh MODULE_DEVICE_TABLE(platform, spi_driver_ids);
10155ce0ba88SHiep Cao Minh 
10160b2182ddSShimoda, Yoshihiro static struct platform_driver rspi_driver = {
10170b2182ddSShimoda, Yoshihiro 	.probe =	rspi_probe,
1018fd4a319bSGrant Likely 	.remove =	rspi_remove,
10195ce0ba88SHiep Cao Minh 	.id_table =	spi_driver_ids,
10200b2182ddSShimoda, Yoshihiro 	.driver		= {
10215ce0ba88SHiep Cao Minh 		.name = "renesas_spi",
10220b2182ddSShimoda, Yoshihiro 		.owner	= THIS_MODULE,
10230b2182ddSShimoda, Yoshihiro 	},
10240b2182ddSShimoda, Yoshihiro };
10250b2182ddSShimoda, Yoshihiro module_platform_driver(rspi_driver);
10260b2182ddSShimoda, Yoshihiro 
10270b2182ddSShimoda, Yoshihiro MODULE_DESCRIPTION("Renesas RSPI bus driver");
10280b2182ddSShimoda, Yoshihiro MODULE_LICENSE("GPL v2");
10290b2182ddSShimoda, Yoshihiro MODULE_AUTHOR("Yoshihiro Shimoda");
10300b2182ddSShimoda, Yoshihiro MODULE_ALIAS("platform:rspi");
1031