10b2182ddSShimoda, Yoshihiro /* 20b2182ddSShimoda, Yoshihiro * SH RSPI driver 30b2182ddSShimoda, Yoshihiro * 493722206SGeert Uytterhoeven * Copyright (C) 2012, 2013 Renesas Solutions Corp. 5880c6d11SGeert Uytterhoeven * Copyright (C) 2014 Glider bvba 60b2182ddSShimoda, Yoshihiro * 70b2182ddSShimoda, Yoshihiro * Based on spi-sh.c: 80b2182ddSShimoda, Yoshihiro * Copyright (C) 2011 Renesas Solutions Corp. 90b2182ddSShimoda, Yoshihiro * 100b2182ddSShimoda, Yoshihiro * This program is free software; you can redistribute it and/or modify 110b2182ddSShimoda, Yoshihiro * it under the terms of the GNU General Public License as published by 120b2182ddSShimoda, Yoshihiro * the Free Software Foundation; version 2 of the License. 130b2182ddSShimoda, Yoshihiro * 140b2182ddSShimoda, Yoshihiro * This program is distributed in the hope that it will be useful, 150b2182ddSShimoda, Yoshihiro * but WITHOUT ANY WARRANTY; without even the implied warranty of 160b2182ddSShimoda, Yoshihiro * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 170b2182ddSShimoda, Yoshihiro * GNU General Public License for more details. 180b2182ddSShimoda, Yoshihiro * 190b2182ddSShimoda, Yoshihiro * You should have received a copy of the GNU General Public License 200b2182ddSShimoda, Yoshihiro * along with this program; if not, write to the Free Software 210b2182ddSShimoda, Yoshihiro * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 220b2182ddSShimoda, Yoshihiro * 230b2182ddSShimoda, Yoshihiro */ 240b2182ddSShimoda, Yoshihiro 250b2182ddSShimoda, Yoshihiro #include <linux/module.h> 260b2182ddSShimoda, Yoshihiro #include <linux/kernel.h> 270b2182ddSShimoda, Yoshihiro #include <linux/sched.h> 280b2182ddSShimoda, Yoshihiro #include <linux/errno.h> 290b2182ddSShimoda, Yoshihiro #include <linux/interrupt.h> 300b2182ddSShimoda, Yoshihiro #include <linux/platform_device.h> 310b2182ddSShimoda, Yoshihiro #include <linux/io.h> 320b2182ddSShimoda, Yoshihiro #include <linux/clk.h> 33a3633fe7SShimoda, Yoshihiro #include <linux/dmaengine.h> 34a3633fe7SShimoda, Yoshihiro #include <linux/dma-mapping.h> 35426ef76dSGeert Uytterhoeven #include <linux/of_device.h> 36490c9774SGeert Uytterhoeven #include <linux/pm_runtime.h> 37a3633fe7SShimoda, Yoshihiro #include <linux/sh_dma.h> 380b2182ddSShimoda, Yoshihiro #include <linux/spi/spi.h> 39a3633fe7SShimoda, Yoshihiro #include <linux/spi/rspi.h> 400b2182ddSShimoda, Yoshihiro 416ab4865bSGeert Uytterhoeven #define RSPI_SPCR 0x00 /* Control Register */ 426ab4865bSGeert Uytterhoeven #define RSPI_SSLP 0x01 /* Slave Select Polarity Register */ 436ab4865bSGeert Uytterhoeven #define RSPI_SPPCR 0x02 /* Pin Control Register */ 446ab4865bSGeert Uytterhoeven #define RSPI_SPSR 0x03 /* Status Register */ 456ab4865bSGeert Uytterhoeven #define RSPI_SPDR 0x04 /* Data Register */ 466ab4865bSGeert Uytterhoeven #define RSPI_SPSCR 0x08 /* Sequence Control Register */ 476ab4865bSGeert Uytterhoeven #define RSPI_SPSSR 0x09 /* Sequence Status Register */ 486ab4865bSGeert Uytterhoeven #define RSPI_SPBR 0x0a /* Bit Rate Register */ 496ab4865bSGeert Uytterhoeven #define RSPI_SPDCR 0x0b /* Data Control Register */ 506ab4865bSGeert Uytterhoeven #define RSPI_SPCKD 0x0c /* Clock Delay Register */ 516ab4865bSGeert Uytterhoeven #define RSPI_SSLND 0x0d /* Slave Select Negation Delay Register */ 526ab4865bSGeert Uytterhoeven #define RSPI_SPND 0x0e /* Next-Access Delay Register */ 53862d357fSGeert Uytterhoeven #define RSPI_SPCR2 0x0f /* Control Register 2 (SH only) */ 546ab4865bSGeert Uytterhoeven #define RSPI_SPCMD0 0x10 /* Command Register 0 */ 556ab4865bSGeert Uytterhoeven #define RSPI_SPCMD1 0x12 /* Command Register 1 */ 566ab4865bSGeert Uytterhoeven #define RSPI_SPCMD2 0x14 /* Command Register 2 */ 576ab4865bSGeert Uytterhoeven #define RSPI_SPCMD3 0x16 /* Command Register 3 */ 586ab4865bSGeert Uytterhoeven #define RSPI_SPCMD4 0x18 /* Command Register 4 */ 596ab4865bSGeert Uytterhoeven #define RSPI_SPCMD5 0x1a /* Command Register 5 */ 606ab4865bSGeert Uytterhoeven #define RSPI_SPCMD6 0x1c /* Command Register 6 */ 616ab4865bSGeert Uytterhoeven #define RSPI_SPCMD7 0x1e /* Command Register 7 */ 62880c6d11SGeert Uytterhoeven #define RSPI_SPCMD(i) (RSPI_SPCMD0 + (i) * 2) 63880c6d11SGeert Uytterhoeven #define RSPI_NUM_SPCMD 8 64880c6d11SGeert Uytterhoeven #define RSPI_RZ_NUM_SPCMD 4 65880c6d11SGeert Uytterhoeven #define QSPI_NUM_SPCMD 4 66862d357fSGeert Uytterhoeven 67862d357fSGeert Uytterhoeven /* RSPI on RZ only */ 686ab4865bSGeert Uytterhoeven #define RSPI_SPBFCR 0x20 /* Buffer Control Register */ 696ab4865bSGeert Uytterhoeven #define RSPI_SPBFDR 0x22 /* Buffer Data Count Setting Register */ 700b2182ddSShimoda, Yoshihiro 71862d357fSGeert Uytterhoeven /* QSPI only */ 72fbe5072bSGeert Uytterhoeven #define QSPI_SPBFCR 0x18 /* Buffer Control Register */ 73fbe5072bSGeert Uytterhoeven #define QSPI_SPBDCR 0x1a /* Buffer Data Count Register */ 74fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL0 0x1c /* Transfer Data Length Multiplier Setting Register 0 */ 75fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL1 0x20 /* Transfer Data Length Multiplier Setting Register 1 */ 76fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL2 0x24 /* Transfer Data Length Multiplier Setting Register 2 */ 77fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL3 0x28 /* Transfer Data Length Multiplier Setting Register 3 */ 78880c6d11SGeert Uytterhoeven #define QSPI_SPBMUL(i) (QSPI_SPBMUL0 + (i) * 4) 795ce0ba88SHiep Cao Minh 806ab4865bSGeert Uytterhoeven /* SPCR - Control Register */ 816ab4865bSGeert Uytterhoeven #define SPCR_SPRIE 0x80 /* Receive Interrupt Enable */ 826ab4865bSGeert Uytterhoeven #define SPCR_SPE 0x40 /* Function Enable */ 836ab4865bSGeert Uytterhoeven #define SPCR_SPTIE 0x20 /* Transmit Interrupt Enable */ 846ab4865bSGeert Uytterhoeven #define SPCR_SPEIE 0x10 /* Error Interrupt Enable */ 856ab4865bSGeert Uytterhoeven #define SPCR_MSTR 0x08 /* Master/Slave Mode Select */ 866ab4865bSGeert Uytterhoeven #define SPCR_MODFEN 0x04 /* Mode Fault Error Detection Enable */ 876ab4865bSGeert Uytterhoeven /* RSPI on SH only */ 886ab4865bSGeert Uytterhoeven #define SPCR_TXMD 0x02 /* TX Only Mode (vs. Full Duplex) */ 896ab4865bSGeert Uytterhoeven #define SPCR_SPMS 0x01 /* 3-wire Mode (vs. 4-wire) */ 90fbe5072bSGeert Uytterhoeven /* QSPI on R-Car M2 only */ 91fbe5072bSGeert Uytterhoeven #define SPCR_WSWAP 0x02 /* Word Swap of read-data for DMAC */ 92fbe5072bSGeert Uytterhoeven #define SPCR_BSWAP 0x01 /* Byte Swap of read-data for DMAC */ 930b2182ddSShimoda, Yoshihiro 946ab4865bSGeert Uytterhoeven /* SSLP - Slave Select Polarity Register */ 956ab4865bSGeert Uytterhoeven #define SSLP_SSL1P 0x02 /* SSL1 Signal Polarity Setting */ 966ab4865bSGeert Uytterhoeven #define SSLP_SSL0P 0x01 /* SSL0 Signal Polarity Setting */ 970b2182ddSShimoda, Yoshihiro 986ab4865bSGeert Uytterhoeven /* SPPCR - Pin Control Register */ 996ab4865bSGeert Uytterhoeven #define SPPCR_MOIFE 0x20 /* MOSI Idle Value Fixing Enable */ 1006ab4865bSGeert Uytterhoeven #define SPPCR_MOIFV 0x10 /* MOSI Idle Fixed Value */ 1010b2182ddSShimoda, Yoshihiro #define SPPCR_SPOM 0x04 1026ab4865bSGeert Uytterhoeven #define SPPCR_SPLP2 0x02 /* Loopback Mode 2 (non-inverting) */ 1036ab4865bSGeert Uytterhoeven #define SPPCR_SPLP 0x01 /* Loopback Mode (inverting) */ 1040b2182ddSShimoda, Yoshihiro 105fbe5072bSGeert Uytterhoeven #define SPPCR_IO3FV 0x04 /* Single-/Dual-SPI Mode IO3 Output Fixed Value */ 106fbe5072bSGeert Uytterhoeven #define SPPCR_IO2FV 0x04 /* Single-/Dual-SPI Mode IO2 Output Fixed Value */ 107fbe5072bSGeert Uytterhoeven 1086ab4865bSGeert Uytterhoeven /* SPSR - Status Register */ 1096ab4865bSGeert Uytterhoeven #define SPSR_SPRF 0x80 /* Receive Buffer Full Flag */ 1106ab4865bSGeert Uytterhoeven #define SPSR_TEND 0x40 /* Transmit End */ 1116ab4865bSGeert Uytterhoeven #define SPSR_SPTEF 0x20 /* Transmit Buffer Empty Flag */ 1126ab4865bSGeert Uytterhoeven #define SPSR_PERF 0x08 /* Parity Error Flag */ 1136ab4865bSGeert Uytterhoeven #define SPSR_MODF 0x04 /* Mode Fault Error Flag */ 1146ab4865bSGeert Uytterhoeven #define SPSR_IDLNF 0x02 /* RSPI Idle Flag */ 115862d357fSGeert Uytterhoeven #define SPSR_OVRF 0x01 /* Overrun Error Flag (RSPI only) */ 1160b2182ddSShimoda, Yoshihiro 1176ab4865bSGeert Uytterhoeven /* SPSCR - Sequence Control Register */ 1186ab4865bSGeert Uytterhoeven #define SPSCR_SPSLN_MASK 0x07 /* Sequence Length Specification */ 1190b2182ddSShimoda, Yoshihiro 1206ab4865bSGeert Uytterhoeven /* SPSSR - Sequence Status Register */ 1216ab4865bSGeert Uytterhoeven #define SPSSR_SPECM_MASK 0x70 /* Command Error Mask */ 1226ab4865bSGeert Uytterhoeven #define SPSSR_SPCP_MASK 0x07 /* Command Pointer Mask */ 1230b2182ddSShimoda, Yoshihiro 1246ab4865bSGeert Uytterhoeven /* SPDCR - Data Control Register */ 1256ab4865bSGeert Uytterhoeven #define SPDCR_TXDMY 0x80 /* Dummy Data Transmission Enable */ 1266ab4865bSGeert Uytterhoeven #define SPDCR_SPLW1 0x40 /* Access Width Specification (RZ) */ 1276ab4865bSGeert Uytterhoeven #define SPDCR_SPLW0 0x20 /* Access Width Specification (RZ) */ 1286ab4865bSGeert Uytterhoeven #define SPDCR_SPLLWORD (SPDCR_SPLW1 | SPDCR_SPLW0) 1296ab4865bSGeert Uytterhoeven #define SPDCR_SPLWORD SPDCR_SPLW1 1306ab4865bSGeert Uytterhoeven #define SPDCR_SPLBYTE SPDCR_SPLW0 1316ab4865bSGeert Uytterhoeven #define SPDCR_SPLW 0x20 /* Access Width Specification (SH) */ 132862d357fSGeert Uytterhoeven #define SPDCR_SPRDTD 0x10 /* Receive Transmit Data Select (SH) */ 1330b2182ddSShimoda, Yoshihiro #define SPDCR_SLSEL1 0x08 1340b2182ddSShimoda, Yoshihiro #define SPDCR_SLSEL0 0x04 135862d357fSGeert Uytterhoeven #define SPDCR_SLSEL_MASK 0x0c /* SSL1 Output Select (SH) */ 1360b2182ddSShimoda, Yoshihiro #define SPDCR_SPFC1 0x02 1370b2182ddSShimoda, Yoshihiro #define SPDCR_SPFC0 0x01 138862d357fSGeert Uytterhoeven #define SPDCR_SPFC_MASK 0x03 /* Frame Count Setting (1-4) (SH) */ 1390b2182ddSShimoda, Yoshihiro 1406ab4865bSGeert Uytterhoeven /* SPCKD - Clock Delay Register */ 1416ab4865bSGeert Uytterhoeven #define SPCKD_SCKDL_MASK 0x07 /* Clock Delay Setting (1-8) */ 1420b2182ddSShimoda, Yoshihiro 1436ab4865bSGeert Uytterhoeven /* SSLND - Slave Select Negation Delay Register */ 1446ab4865bSGeert Uytterhoeven #define SSLND_SLNDL_MASK 0x07 /* SSL Negation Delay Setting (1-8) */ 1450b2182ddSShimoda, Yoshihiro 1466ab4865bSGeert Uytterhoeven /* SPND - Next-Access Delay Register */ 1476ab4865bSGeert Uytterhoeven #define SPND_SPNDL_MASK 0x07 /* Next-Access Delay Setting (1-8) */ 1480b2182ddSShimoda, Yoshihiro 1496ab4865bSGeert Uytterhoeven /* SPCR2 - Control Register 2 */ 1506ab4865bSGeert Uytterhoeven #define SPCR2_PTE 0x08 /* Parity Self-Test Enable */ 1516ab4865bSGeert Uytterhoeven #define SPCR2_SPIE 0x04 /* Idle Interrupt Enable */ 1526ab4865bSGeert Uytterhoeven #define SPCR2_SPOE 0x02 /* Odd Parity Enable (vs. Even) */ 1536ab4865bSGeert Uytterhoeven #define SPCR2_SPPE 0x01 /* Parity Enable */ 1540b2182ddSShimoda, Yoshihiro 1556ab4865bSGeert Uytterhoeven /* SPCMDn - Command Registers */ 1566ab4865bSGeert Uytterhoeven #define SPCMD_SCKDEN 0x8000 /* Clock Delay Setting Enable */ 1576ab4865bSGeert Uytterhoeven #define SPCMD_SLNDEN 0x4000 /* SSL Negation Delay Setting Enable */ 1586ab4865bSGeert Uytterhoeven #define SPCMD_SPNDEN 0x2000 /* Next-Access Delay Enable */ 1596ab4865bSGeert Uytterhoeven #define SPCMD_LSBF 0x1000 /* LSB First */ 1606ab4865bSGeert Uytterhoeven #define SPCMD_SPB_MASK 0x0f00 /* Data Length Setting */ 1610b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK) 162880c6d11SGeert Uytterhoeven #define SPCMD_SPB_8BIT 0x0000 /* QSPI only */ 1635ce0ba88SHiep Cao Minh #define SPCMD_SPB_16BIT 0x0100 1640b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_20BIT 0x0000 1650b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_24BIT 0x0100 1660b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_32BIT 0x0200 1676ab4865bSGeert Uytterhoeven #define SPCMD_SSLKP 0x0080 /* SSL Signal Level Keeping */ 168fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_MASK 0x0060 /* SPI Operating Mode (QSPI only) */ 169fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD1 0x0040 170fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD0 0x0020 171fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_SINGLE 0 172fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_DUAL SPCMD_SPIMOD0 173fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_QUAD SPCMD_SPIMOD1 174fbe5072bSGeert Uytterhoeven #define SPCMD_SPRW 0x0010 /* SPI Read/Write Access (Dual/Quad) */ 1756ab4865bSGeert Uytterhoeven #define SPCMD_SSLA_MASK 0x0030 /* SSL Assert Signal Setting (RSPI) */ 1766ab4865bSGeert Uytterhoeven #define SPCMD_BRDV_MASK 0x000c /* Bit Rate Division Setting */ 1776ab4865bSGeert Uytterhoeven #define SPCMD_CPOL 0x0002 /* Clock Polarity Setting */ 1786ab4865bSGeert Uytterhoeven #define SPCMD_CPHA 0x0001 /* Clock Phase Setting */ 1790b2182ddSShimoda, Yoshihiro 1806ab4865bSGeert Uytterhoeven /* SPBFCR - Buffer Control Register */ 181862d357fSGeert Uytterhoeven #define SPBFCR_TXRST 0x80 /* Transmit Buffer Data Reset */ 182862d357fSGeert Uytterhoeven #define SPBFCR_RXRST 0x40 /* Receive Buffer Data Reset */ 1836ab4865bSGeert Uytterhoeven #define SPBFCR_TXTRG_MASK 0x30 /* Transmit Buffer Data Triggering Number */ 1846ab4865bSGeert Uytterhoeven #define SPBFCR_RXTRG_MASK 0x07 /* Receive Buffer Data Triggering Number */ 1855ce0ba88SHiep Cao Minh 1860b2182ddSShimoda, Yoshihiro struct rspi_data { 1870b2182ddSShimoda, Yoshihiro void __iomem *addr; 1880b2182ddSShimoda, Yoshihiro u32 max_speed_hz; 1890b2182ddSShimoda, Yoshihiro struct spi_master *master; 1900b2182ddSShimoda, Yoshihiro wait_queue_head_t wait; 1910b2182ddSShimoda, Yoshihiro struct clk *clk; 192348e5153SGeert Uytterhoeven u16 spcmd; 19306a7a3cfSGeert Uytterhoeven u8 spsr; 19406a7a3cfSGeert Uytterhoeven u8 sppcr; 19593722206SGeert Uytterhoeven int rx_irq, tx_irq; 1965ce0ba88SHiep Cao Minh const struct spi_ops *ops; 197a3633fe7SShimoda, Yoshihiro 198a3633fe7SShimoda, Yoshihiro /* for dmaengine */ 199a3633fe7SShimoda, Yoshihiro struct dma_chan *chan_tx; 200a3633fe7SShimoda, Yoshihiro struct dma_chan *chan_rx; 201a3633fe7SShimoda, Yoshihiro 202a3633fe7SShimoda, Yoshihiro unsigned dma_callbacked:1; 20374da7686SGeert Uytterhoeven unsigned byte_access:1; 2040b2182ddSShimoda, Yoshihiro }; 2050b2182ddSShimoda, Yoshihiro 206baf588f4SGeert Uytterhoeven static void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset) 2070b2182ddSShimoda, Yoshihiro { 2080b2182ddSShimoda, Yoshihiro iowrite8(data, rspi->addr + offset); 2090b2182ddSShimoda, Yoshihiro } 2100b2182ddSShimoda, Yoshihiro 211baf588f4SGeert Uytterhoeven static void rspi_write16(const struct rspi_data *rspi, u16 data, u16 offset) 2120b2182ddSShimoda, Yoshihiro { 2130b2182ddSShimoda, Yoshihiro iowrite16(data, rspi->addr + offset); 2140b2182ddSShimoda, Yoshihiro } 2150b2182ddSShimoda, Yoshihiro 216baf588f4SGeert Uytterhoeven static void rspi_write32(const struct rspi_data *rspi, u32 data, u16 offset) 2175ce0ba88SHiep Cao Minh { 2185ce0ba88SHiep Cao Minh iowrite32(data, rspi->addr + offset); 2195ce0ba88SHiep Cao Minh } 2205ce0ba88SHiep Cao Minh 221baf588f4SGeert Uytterhoeven static u8 rspi_read8(const struct rspi_data *rspi, u16 offset) 2220b2182ddSShimoda, Yoshihiro { 2230b2182ddSShimoda, Yoshihiro return ioread8(rspi->addr + offset); 2240b2182ddSShimoda, Yoshihiro } 2250b2182ddSShimoda, Yoshihiro 226baf588f4SGeert Uytterhoeven static u16 rspi_read16(const struct rspi_data *rspi, u16 offset) 2270b2182ddSShimoda, Yoshihiro { 2280b2182ddSShimoda, Yoshihiro return ioread16(rspi->addr + offset); 2290b2182ddSShimoda, Yoshihiro } 2300b2182ddSShimoda, Yoshihiro 23174da7686SGeert Uytterhoeven static void rspi_write_data(const struct rspi_data *rspi, u16 data) 23274da7686SGeert Uytterhoeven { 23374da7686SGeert Uytterhoeven if (rspi->byte_access) 23474da7686SGeert Uytterhoeven rspi_write8(rspi, data, RSPI_SPDR); 23574da7686SGeert Uytterhoeven else /* 16 bit */ 23674da7686SGeert Uytterhoeven rspi_write16(rspi, data, RSPI_SPDR); 23774da7686SGeert Uytterhoeven } 23874da7686SGeert Uytterhoeven 23974da7686SGeert Uytterhoeven static u16 rspi_read_data(const struct rspi_data *rspi) 24074da7686SGeert Uytterhoeven { 24174da7686SGeert Uytterhoeven if (rspi->byte_access) 24274da7686SGeert Uytterhoeven return rspi_read8(rspi, RSPI_SPDR); 24374da7686SGeert Uytterhoeven else /* 16 bit */ 24474da7686SGeert Uytterhoeven return rspi_read16(rspi, RSPI_SPDR); 24574da7686SGeert Uytterhoeven } 24674da7686SGeert Uytterhoeven 2475ce0ba88SHiep Cao Minh /* optional functions */ 2485ce0ba88SHiep Cao Minh struct spi_ops { 24974da7686SGeert Uytterhoeven int (*set_config_register)(struct rspi_data *rspi, int access_size); 250eb557f75SGeert Uytterhoeven int (*transfer_one)(struct spi_master *master, struct spi_device *spi, 251eb557f75SGeert Uytterhoeven struct spi_transfer *xfer); 252880c6d11SGeert Uytterhoeven u16 mode_bits; 253b42e0359SGeert Uytterhoeven u16 flags; 2545ce0ba88SHiep Cao Minh }; 2555ce0ba88SHiep Cao Minh 2565ce0ba88SHiep Cao Minh /* 257862d357fSGeert Uytterhoeven * functions for RSPI on legacy SH 2585ce0ba88SHiep Cao Minh */ 25974da7686SGeert Uytterhoeven static int rspi_set_config_register(struct rspi_data *rspi, int access_size) 2600b2182ddSShimoda, Yoshihiro { 2615ce0ba88SHiep Cao Minh int spbr; 2620b2182ddSShimoda, Yoshihiro 26306a7a3cfSGeert Uytterhoeven /* Sets output mode, MOSI signal, and (optionally) loopback */ 26406a7a3cfSGeert Uytterhoeven rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); 2650b2182ddSShimoda, Yoshihiro 2665ce0ba88SHiep Cao Minh /* Sets transfer bit rate */ 2673beb61dbSGeert Uytterhoeven spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 2683beb61dbSGeert Uytterhoeven 2 * rspi->max_speed_hz) - 1; 2695ce0ba88SHiep Cao Minh rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); 2705ce0ba88SHiep Cao Minh 27174da7686SGeert Uytterhoeven /* Disable dummy transmission, set 16-bit word access, 1 frame */ 27274da7686SGeert Uytterhoeven rspi_write8(rspi, 0, RSPI_SPDCR); 27374da7686SGeert Uytterhoeven rspi->byte_access = 0; 2745ce0ba88SHiep Cao Minh 2755ce0ba88SHiep Cao Minh /* Sets RSPCK, SSL, next-access delay value */ 2765ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, RSPI_SPCKD); 2775ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, RSPI_SSLND); 2785ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, RSPI_SPND); 2795ce0ba88SHiep Cao Minh 2805ce0ba88SHiep Cao Minh /* Sets parity, interrupt mask */ 2815ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, RSPI_SPCR2); 2825ce0ba88SHiep Cao Minh 2835ce0ba88SHiep Cao Minh /* Sets SPCMD */ 284880c6d11SGeert Uytterhoeven rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size); 285880c6d11SGeert Uytterhoeven rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 2865ce0ba88SHiep Cao Minh 2875ce0ba88SHiep Cao Minh /* Sets RSPI mode */ 2885ce0ba88SHiep Cao Minh rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); 2895ce0ba88SHiep Cao Minh 2905ce0ba88SHiep Cao Minh return 0; 2910b2182ddSShimoda, Yoshihiro } 2920b2182ddSShimoda, Yoshihiro 2935ce0ba88SHiep Cao Minh /* 294862d357fSGeert Uytterhoeven * functions for RSPI on RZ 295862d357fSGeert Uytterhoeven */ 296862d357fSGeert Uytterhoeven static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size) 297862d357fSGeert Uytterhoeven { 298862d357fSGeert Uytterhoeven int spbr; 299862d357fSGeert Uytterhoeven 30006a7a3cfSGeert Uytterhoeven /* Sets output mode, MOSI signal, and (optionally) loopback */ 30106a7a3cfSGeert Uytterhoeven rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); 302862d357fSGeert Uytterhoeven 303862d357fSGeert Uytterhoeven /* Sets transfer bit rate */ 3043beb61dbSGeert Uytterhoeven spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 3053beb61dbSGeert Uytterhoeven 2 * rspi->max_speed_hz) - 1; 306862d357fSGeert Uytterhoeven rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); 307862d357fSGeert Uytterhoeven 308862d357fSGeert Uytterhoeven /* Disable dummy transmission, set byte access */ 309862d357fSGeert Uytterhoeven rspi_write8(rspi, SPDCR_SPLBYTE, RSPI_SPDCR); 310862d357fSGeert Uytterhoeven rspi->byte_access = 1; 311862d357fSGeert Uytterhoeven 312862d357fSGeert Uytterhoeven /* Sets RSPCK, SSL, next-access delay value */ 313862d357fSGeert Uytterhoeven rspi_write8(rspi, 0x00, RSPI_SPCKD); 314862d357fSGeert Uytterhoeven rspi_write8(rspi, 0x00, RSPI_SSLND); 315862d357fSGeert Uytterhoeven rspi_write8(rspi, 0x00, RSPI_SPND); 316862d357fSGeert Uytterhoeven 317862d357fSGeert Uytterhoeven /* Sets SPCMD */ 318862d357fSGeert Uytterhoeven rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size); 319862d357fSGeert Uytterhoeven rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 320862d357fSGeert Uytterhoeven 321862d357fSGeert Uytterhoeven /* Sets RSPI mode */ 322862d357fSGeert Uytterhoeven rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); 323862d357fSGeert Uytterhoeven 324862d357fSGeert Uytterhoeven return 0; 325862d357fSGeert Uytterhoeven } 326862d357fSGeert Uytterhoeven 327862d357fSGeert Uytterhoeven /* 3285ce0ba88SHiep Cao Minh * functions for QSPI 3295ce0ba88SHiep Cao Minh */ 33074da7686SGeert Uytterhoeven static int qspi_set_config_register(struct rspi_data *rspi, int access_size) 3315ce0ba88SHiep Cao Minh { 3325ce0ba88SHiep Cao Minh int spbr; 3335ce0ba88SHiep Cao Minh 33406a7a3cfSGeert Uytterhoeven /* Sets output mode, MOSI signal, and (optionally) loopback */ 33506a7a3cfSGeert Uytterhoeven rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); 3365ce0ba88SHiep Cao Minh 3375ce0ba88SHiep Cao Minh /* Sets transfer bit rate */ 3383beb61dbSGeert Uytterhoeven spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 2 * rspi->max_speed_hz); 3395ce0ba88SHiep Cao Minh rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); 3405ce0ba88SHiep Cao Minh 34174da7686SGeert Uytterhoeven /* Disable dummy transmission, set byte access */ 34274da7686SGeert Uytterhoeven rspi_write8(rspi, 0, RSPI_SPDCR); 34374da7686SGeert Uytterhoeven rspi->byte_access = 1; 3445ce0ba88SHiep Cao Minh 3455ce0ba88SHiep Cao Minh /* Sets RSPCK, SSL, next-access delay value */ 3465ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, RSPI_SPCKD); 3475ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, RSPI_SSLND); 3485ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, RSPI_SPND); 3495ce0ba88SHiep Cao Minh 3505ce0ba88SHiep Cao Minh /* Data Length Setting */ 3515ce0ba88SHiep Cao Minh if (access_size == 8) 352880c6d11SGeert Uytterhoeven rspi->spcmd |= SPCMD_SPB_8BIT; 3535ce0ba88SHiep Cao Minh else if (access_size == 16) 354880c6d11SGeert Uytterhoeven rspi->spcmd |= SPCMD_SPB_16BIT; 3558e1c8096SLaurent Pinchart else 356880c6d11SGeert Uytterhoeven rspi->spcmd |= SPCMD_SPB_32BIT; 3575ce0ba88SHiep Cao Minh 358880c6d11SGeert Uytterhoeven rspi->spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SPNDEN; 3595ce0ba88SHiep Cao Minh 3605ce0ba88SHiep Cao Minh /* Resets transfer data length */ 3615ce0ba88SHiep Cao Minh rspi_write32(rspi, 0, QSPI_SPBMUL0); 3625ce0ba88SHiep Cao Minh 3635ce0ba88SHiep Cao Minh /* Resets transmit and receive buffer */ 3645ce0ba88SHiep Cao Minh rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR); 3655ce0ba88SHiep Cao Minh /* Sets buffer to allow normal operation */ 3665ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, QSPI_SPBFCR); 3675ce0ba88SHiep Cao Minh 3685ce0ba88SHiep Cao Minh /* Sets SPCMD */ 369880c6d11SGeert Uytterhoeven rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 3705ce0ba88SHiep Cao Minh 371880c6d11SGeert Uytterhoeven /* Enables SPI function in master mode */ 3725ce0ba88SHiep Cao Minh rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR); 3735ce0ba88SHiep Cao Minh 3745ce0ba88SHiep Cao Minh return 0; 3755ce0ba88SHiep Cao Minh } 3765ce0ba88SHiep Cao Minh 3775ce0ba88SHiep Cao Minh #define set_config_register(spi, n) spi->ops->set_config_register(spi, n) 3785ce0ba88SHiep Cao Minh 379baf588f4SGeert Uytterhoeven static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable) 3800b2182ddSShimoda, Yoshihiro { 3810b2182ddSShimoda, Yoshihiro rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR); 3820b2182ddSShimoda, Yoshihiro } 3830b2182ddSShimoda, Yoshihiro 384baf588f4SGeert Uytterhoeven static void rspi_disable_irq(const struct rspi_data *rspi, u8 disable) 3850b2182ddSShimoda, Yoshihiro { 3860b2182ddSShimoda, Yoshihiro rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~disable, RSPI_SPCR); 3870b2182ddSShimoda, Yoshihiro } 3880b2182ddSShimoda, Yoshihiro 3890b2182ddSShimoda, Yoshihiro static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask, 3900b2182ddSShimoda, Yoshihiro u8 enable_bit) 3910b2182ddSShimoda, Yoshihiro { 3920b2182ddSShimoda, Yoshihiro int ret; 3930b2182ddSShimoda, Yoshihiro 3940b2182ddSShimoda, Yoshihiro rspi->spsr = rspi_read8(rspi, RSPI_SPSR); 3955dd1ad23SGeert Uytterhoeven if (rspi->spsr & wait_mask) 3965dd1ad23SGeert Uytterhoeven return 0; 3975dd1ad23SGeert Uytterhoeven 3980b2182ddSShimoda, Yoshihiro rspi_enable_irq(rspi, enable_bit); 3990b2182ddSShimoda, Yoshihiro ret = wait_event_timeout(rspi->wait, rspi->spsr & wait_mask, HZ); 4000b2182ddSShimoda, Yoshihiro if (ret == 0 && !(rspi->spsr & wait_mask)) 4010b2182ddSShimoda, Yoshihiro return -ETIMEDOUT; 4020b2182ddSShimoda, Yoshihiro 4030b2182ddSShimoda, Yoshihiro return 0; 4040b2182ddSShimoda, Yoshihiro } 4050b2182ddSShimoda, Yoshihiro 4065f684c34SGeert Uytterhoeven static inline int rspi_wait_for_tx_empty(struct rspi_data *rspi) 4075f684c34SGeert Uytterhoeven { 4085f684c34SGeert Uytterhoeven return rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); 4095f684c34SGeert Uytterhoeven } 4105f684c34SGeert Uytterhoeven 4115f684c34SGeert Uytterhoeven static inline int rspi_wait_for_rx_full(struct rspi_data *rspi) 4125f684c34SGeert Uytterhoeven { 4135f684c34SGeert Uytterhoeven return rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE); 4145f684c34SGeert Uytterhoeven } 4155f684c34SGeert Uytterhoeven 41635301c99SGeert Uytterhoeven static int rspi_data_out(struct rspi_data *rspi, u8 data) 41735301c99SGeert Uytterhoeven { 4185f684c34SGeert Uytterhoeven int error = rspi_wait_for_tx_empty(rspi); 4195f684c34SGeert Uytterhoeven if (error < 0) { 42035301c99SGeert Uytterhoeven dev_err(&rspi->master->dev, "transmit timeout\n"); 4215f684c34SGeert Uytterhoeven return error; 42235301c99SGeert Uytterhoeven } 42335301c99SGeert Uytterhoeven rspi_write_data(rspi, data); 42435301c99SGeert Uytterhoeven return 0; 42535301c99SGeert Uytterhoeven } 42635301c99SGeert Uytterhoeven 42735301c99SGeert Uytterhoeven static int rspi_data_in(struct rspi_data *rspi) 42835301c99SGeert Uytterhoeven { 4295f684c34SGeert Uytterhoeven int error; 43035301c99SGeert Uytterhoeven u8 data; 43135301c99SGeert Uytterhoeven 4325f684c34SGeert Uytterhoeven error = rspi_wait_for_rx_full(rspi); 4335f684c34SGeert Uytterhoeven if (error < 0) { 43435301c99SGeert Uytterhoeven dev_err(&rspi->master->dev, "receive timeout\n"); 4355f684c34SGeert Uytterhoeven return error; 43635301c99SGeert Uytterhoeven } 43735301c99SGeert Uytterhoeven data = rspi_read_data(rspi); 43835301c99SGeert Uytterhoeven return data; 43935301c99SGeert Uytterhoeven } 44035301c99SGeert Uytterhoeven 4416837b8e9SGeert Uytterhoeven static int rspi_pio_transfer(struct rspi_data *rspi, const u8 *tx, u8 *rx, 4426837b8e9SGeert Uytterhoeven unsigned int n) 44335301c99SGeert Uytterhoeven { 4446837b8e9SGeert Uytterhoeven while (n-- > 0) { 4456837b8e9SGeert Uytterhoeven if (tx) { 4466837b8e9SGeert Uytterhoeven int ret = rspi_data_out(rspi, *tx++); 44735301c99SGeert Uytterhoeven if (ret < 0) 44835301c99SGeert Uytterhoeven return ret; 4496837b8e9SGeert Uytterhoeven } 4506837b8e9SGeert Uytterhoeven if (rx) { 4516837b8e9SGeert Uytterhoeven int ret = rspi_data_in(rspi); 4526837b8e9SGeert Uytterhoeven if (ret < 0) 4536837b8e9SGeert Uytterhoeven return ret; 4546837b8e9SGeert Uytterhoeven *rx++ = ret; 4556837b8e9SGeert Uytterhoeven } 4566837b8e9SGeert Uytterhoeven } 45735301c99SGeert Uytterhoeven 4586837b8e9SGeert Uytterhoeven return 0; 45935301c99SGeert Uytterhoeven } 46035301c99SGeert Uytterhoeven 461a3633fe7SShimoda, Yoshihiro static void rspi_dma_complete(void *arg) 4620b2182ddSShimoda, Yoshihiro { 463a3633fe7SShimoda, Yoshihiro struct rspi_data *rspi = arg; 464a3633fe7SShimoda, Yoshihiro 465a3633fe7SShimoda, Yoshihiro rspi->dma_callbacked = 1; 466a3633fe7SShimoda, Yoshihiro wake_up_interruptible(&rspi->wait); 467a3633fe7SShimoda, Yoshihiro } 468a3633fe7SShimoda, Yoshihiro 469c132f094SGeert Uytterhoeven static int rspi_dma_map_sg(struct scatterlist *sg, const void *buf, 470c132f094SGeert Uytterhoeven unsigned len, struct dma_chan *chan, 471a3633fe7SShimoda, Yoshihiro enum dma_transfer_direction dir) 472a3633fe7SShimoda, Yoshihiro { 473a3633fe7SShimoda, Yoshihiro sg_init_table(sg, 1); 474a3633fe7SShimoda, Yoshihiro sg_set_buf(sg, buf, len); 475a3633fe7SShimoda, Yoshihiro sg_dma_len(sg) = len; 476a3633fe7SShimoda, Yoshihiro return dma_map_sg(chan->device->dev, sg, 1, dir); 477a3633fe7SShimoda, Yoshihiro } 478a3633fe7SShimoda, Yoshihiro 479a3633fe7SShimoda, Yoshihiro static void rspi_dma_unmap_sg(struct scatterlist *sg, struct dma_chan *chan, 480a3633fe7SShimoda, Yoshihiro enum dma_transfer_direction dir) 481a3633fe7SShimoda, Yoshihiro { 482a3633fe7SShimoda, Yoshihiro dma_unmap_sg(chan->device->dev, sg, 1, dir); 483a3633fe7SShimoda, Yoshihiro } 484a3633fe7SShimoda, Yoshihiro 485a3633fe7SShimoda, Yoshihiro static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t) 486a3633fe7SShimoda, Yoshihiro { 487a3633fe7SShimoda, Yoshihiro struct scatterlist sg; 4889c5de2c1SGeert Uytterhoeven const void *buf = t->tx_buf; 489a3633fe7SShimoda, Yoshihiro struct dma_async_tx_descriptor *desc; 4909c5de2c1SGeert Uytterhoeven unsigned int len = t->len; 491a3633fe7SShimoda, Yoshihiro int ret = 0; 492a3633fe7SShimoda, Yoshihiro 4939c5de2c1SGeert Uytterhoeven if (!rspi_dma_map_sg(&sg, buf, len, rspi->chan_tx, DMA_TO_DEVICE)) 4949c5de2c1SGeert Uytterhoeven return -EFAULT; 495a3633fe7SShimoda, Yoshihiro 496a3633fe7SShimoda, Yoshihiro desc = dmaengine_prep_slave_sg(rspi->chan_tx, &sg, 1, DMA_TO_DEVICE, 497a3633fe7SShimoda, Yoshihiro DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 498a3633fe7SShimoda, Yoshihiro if (!desc) { 499a3633fe7SShimoda, Yoshihiro ret = -EIO; 500a3633fe7SShimoda, Yoshihiro goto end; 501a3633fe7SShimoda, Yoshihiro } 502a3633fe7SShimoda, Yoshihiro 503a3633fe7SShimoda, Yoshihiro /* 504a3633fe7SShimoda, Yoshihiro * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be 505a3633fe7SShimoda, Yoshihiro * called. So, this driver disables the IRQ while DMA transfer. 506a3633fe7SShimoda, Yoshihiro */ 50793722206SGeert Uytterhoeven disable_irq(rspi->tx_irq); 508a3633fe7SShimoda, Yoshihiro 509a3633fe7SShimoda, Yoshihiro rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD, RSPI_SPCR); 510a3633fe7SShimoda, Yoshihiro rspi_enable_irq(rspi, SPCR_SPTIE); 511a3633fe7SShimoda, Yoshihiro rspi->dma_callbacked = 0; 512a3633fe7SShimoda, Yoshihiro 513a3633fe7SShimoda, Yoshihiro desc->callback = rspi_dma_complete; 514a3633fe7SShimoda, Yoshihiro desc->callback_param = rspi; 515a3633fe7SShimoda, Yoshihiro dmaengine_submit(desc); 516a3633fe7SShimoda, Yoshihiro dma_async_issue_pending(rspi->chan_tx); 517a3633fe7SShimoda, Yoshihiro 518a3633fe7SShimoda, Yoshihiro ret = wait_event_interruptible_timeout(rspi->wait, 519a3633fe7SShimoda, Yoshihiro rspi->dma_callbacked, HZ); 520a3633fe7SShimoda, Yoshihiro if (ret > 0 && rspi->dma_callbacked) 521a3633fe7SShimoda, Yoshihiro ret = 0; 522a3633fe7SShimoda, Yoshihiro else if (!ret) 523a3633fe7SShimoda, Yoshihiro ret = -ETIMEDOUT; 524a3633fe7SShimoda, Yoshihiro rspi_disable_irq(rspi, SPCR_SPTIE); 525a3633fe7SShimoda, Yoshihiro 52693722206SGeert Uytterhoeven enable_irq(rspi->tx_irq); 527a3633fe7SShimoda, Yoshihiro 528a3633fe7SShimoda, Yoshihiro end: 529a3633fe7SShimoda, Yoshihiro rspi_dma_unmap_sg(&sg, rspi->chan_tx, DMA_TO_DEVICE); 530a3633fe7SShimoda, Yoshihiro return ret; 531a3633fe7SShimoda, Yoshihiro } 532a3633fe7SShimoda, Yoshihiro 533baf588f4SGeert Uytterhoeven static void rspi_receive_init(const struct rspi_data *rspi) 534a3633fe7SShimoda, Yoshihiro { 53597b95c11SGeert Uytterhoeven u8 spsr; 5360b2182ddSShimoda, Yoshihiro 5370b2182ddSShimoda, Yoshihiro spsr = rspi_read8(rspi, RSPI_SPSR); 5380b2182ddSShimoda, Yoshihiro if (spsr & SPSR_SPRF) 53974da7686SGeert Uytterhoeven rspi_read_data(rspi); /* dummy read */ 5400b2182ddSShimoda, Yoshihiro if (spsr & SPSR_OVRF) 5410b2182ddSShimoda, Yoshihiro rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF, 542df900e67SGeert Uytterhoeven RSPI_SPSR); 543a3633fe7SShimoda, Yoshihiro } 544a3633fe7SShimoda, Yoshihiro 545862d357fSGeert Uytterhoeven static void rspi_rz_receive_init(const struct rspi_data *rspi) 546862d357fSGeert Uytterhoeven { 547862d357fSGeert Uytterhoeven rspi_receive_init(rspi); 548862d357fSGeert Uytterhoeven rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, RSPI_SPBFCR); 549862d357fSGeert Uytterhoeven rspi_write8(rspi, 0, RSPI_SPBFCR); 550862d357fSGeert Uytterhoeven } 551862d357fSGeert Uytterhoeven 552baf588f4SGeert Uytterhoeven static void qspi_receive_init(const struct rspi_data *rspi) 553cb52c673SHiep Cao Minh { 55497b95c11SGeert Uytterhoeven u8 spsr; 555cb52c673SHiep Cao Minh 556cb52c673SHiep Cao Minh spsr = rspi_read8(rspi, RSPI_SPSR); 557cb52c673SHiep Cao Minh if (spsr & SPSR_SPRF) 55874da7686SGeert Uytterhoeven rspi_read_data(rspi); /* dummy read */ 559cb52c673SHiep Cao Minh rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR); 560340a15e6SGeert Uytterhoeven rspi_write8(rspi, 0, QSPI_SPBFCR); 561cb52c673SHiep Cao Minh } 562cb52c673SHiep Cao Minh 563b42e0359SGeert Uytterhoeven static int rspi_send_receive_dma(struct rspi_data *rspi, struct spi_transfer *t) 564a3633fe7SShimoda, Yoshihiro { 565b42e0359SGeert Uytterhoeven struct scatterlist sg_rx, sg_tx; 566b42e0359SGeert Uytterhoeven const void *tx_buf = t->tx_buf; 567b42e0359SGeert Uytterhoeven void *rx_buf = t->rx_buf; 568b42e0359SGeert Uytterhoeven struct dma_async_tx_descriptor *desc_tx, *desc_rx; 5699c5de2c1SGeert Uytterhoeven unsigned int len = t->len; 570a3633fe7SShimoda, Yoshihiro int ret = 0; 571a3633fe7SShimoda, Yoshihiro 572b42e0359SGeert Uytterhoeven /* prepare transmit transfer */ 573b42e0359SGeert Uytterhoeven if (!rspi_dma_map_sg(&sg_tx, tx_buf, len, rspi->chan_tx, 574b42e0359SGeert Uytterhoeven DMA_TO_DEVICE)) 575b42e0359SGeert Uytterhoeven return -EFAULT; 576b42e0359SGeert Uytterhoeven 577b42e0359SGeert Uytterhoeven desc_tx = dmaengine_prep_slave_sg(rspi->chan_tx, &sg_tx, 1, 578a3633fe7SShimoda, Yoshihiro DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 579b42e0359SGeert Uytterhoeven if (!desc_tx) { 580a3633fe7SShimoda, Yoshihiro ret = -EIO; 581b42e0359SGeert Uytterhoeven goto end_tx_mapped; 582a3633fe7SShimoda, Yoshihiro } 583a3633fe7SShimoda, Yoshihiro 584a3633fe7SShimoda, Yoshihiro /* prepare receive transfer */ 585b42e0359SGeert Uytterhoeven if (!rspi_dma_map_sg(&sg_rx, rx_buf, len, rspi->chan_rx, 586a3633fe7SShimoda, Yoshihiro DMA_FROM_DEVICE)) { 587a3633fe7SShimoda, Yoshihiro ret = -EFAULT; 588b42e0359SGeert Uytterhoeven goto end_tx_mapped; 589a3633fe7SShimoda, Yoshihiro 590a3633fe7SShimoda, Yoshihiro } 591b42e0359SGeert Uytterhoeven desc_rx = dmaengine_prep_slave_sg(rspi->chan_rx, &sg_rx, 1, 592b42e0359SGeert Uytterhoeven DMA_FROM_DEVICE, 593a3633fe7SShimoda, Yoshihiro DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 594b42e0359SGeert Uytterhoeven if (!desc_rx) { 595a3633fe7SShimoda, Yoshihiro ret = -EIO; 596a3633fe7SShimoda, Yoshihiro goto end; 597a3633fe7SShimoda, Yoshihiro } 598a3633fe7SShimoda, Yoshihiro 599a3633fe7SShimoda, Yoshihiro rspi_receive_init(rspi); 600a3633fe7SShimoda, Yoshihiro 601a3633fe7SShimoda, Yoshihiro /* 602a3633fe7SShimoda, Yoshihiro * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be 603a3633fe7SShimoda, Yoshihiro * called. So, this driver disables the IRQ while DMA transfer. 604a3633fe7SShimoda, Yoshihiro */ 60593722206SGeert Uytterhoeven disable_irq(rspi->tx_irq); 60693722206SGeert Uytterhoeven if (rspi->rx_irq != rspi->tx_irq) 60793722206SGeert Uytterhoeven disable_irq(rspi->rx_irq); 608a3633fe7SShimoda, Yoshihiro 609a3633fe7SShimoda, Yoshihiro rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD, RSPI_SPCR); 610a3633fe7SShimoda, Yoshihiro rspi_enable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE); 611a3633fe7SShimoda, Yoshihiro rspi->dma_callbacked = 0; 612a3633fe7SShimoda, Yoshihiro 613b42e0359SGeert Uytterhoeven desc_rx->callback = rspi_dma_complete; 614b42e0359SGeert Uytterhoeven desc_rx->callback_param = rspi; 615b42e0359SGeert Uytterhoeven dmaengine_submit(desc_rx); 616a3633fe7SShimoda, Yoshihiro dma_async_issue_pending(rspi->chan_rx); 617a3633fe7SShimoda, Yoshihiro 618b42e0359SGeert Uytterhoeven desc_tx->callback = NULL; /* No callback */ 619b42e0359SGeert Uytterhoeven dmaengine_submit(desc_tx); 620a3633fe7SShimoda, Yoshihiro dma_async_issue_pending(rspi->chan_tx); 621a3633fe7SShimoda, Yoshihiro 622a3633fe7SShimoda, Yoshihiro ret = wait_event_interruptible_timeout(rspi->wait, 623a3633fe7SShimoda, Yoshihiro rspi->dma_callbacked, HZ); 624a3633fe7SShimoda, Yoshihiro if (ret > 0 && rspi->dma_callbacked) 625a3633fe7SShimoda, Yoshihiro ret = 0; 626a3633fe7SShimoda, Yoshihiro else if (!ret) 627a3633fe7SShimoda, Yoshihiro ret = -ETIMEDOUT; 628a3633fe7SShimoda, Yoshihiro rspi_disable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE); 629a3633fe7SShimoda, Yoshihiro 63093722206SGeert Uytterhoeven enable_irq(rspi->tx_irq); 63193722206SGeert Uytterhoeven if (rspi->rx_irq != rspi->tx_irq) 63293722206SGeert Uytterhoeven enable_irq(rspi->rx_irq); 633a3633fe7SShimoda, Yoshihiro 634a3633fe7SShimoda, Yoshihiro end: 635b42e0359SGeert Uytterhoeven rspi_dma_unmap_sg(&sg_rx, rspi->chan_rx, DMA_FROM_DEVICE); 636b42e0359SGeert Uytterhoeven end_tx_mapped: 637b42e0359SGeert Uytterhoeven rspi_dma_unmap_sg(&sg_tx, rspi->chan_tx, DMA_TO_DEVICE); 638a3633fe7SShimoda, Yoshihiro return ret; 639a3633fe7SShimoda, Yoshihiro } 640a3633fe7SShimoda, Yoshihiro 641baf588f4SGeert Uytterhoeven static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t) 642a3633fe7SShimoda, Yoshihiro { 643a3633fe7SShimoda, Yoshihiro /* If the module receives data by DMAC, it also needs TX DMAC */ 644b42e0359SGeert Uytterhoeven if (t->rx_buf) 645b42e0359SGeert Uytterhoeven return rspi->chan_tx && rspi->chan_rx; 646b42e0359SGeert Uytterhoeven 647b42e0359SGeert Uytterhoeven if (rspi->chan_tx) 648a3633fe7SShimoda, Yoshihiro return 1; 649a3633fe7SShimoda, Yoshihiro 650a3633fe7SShimoda, Yoshihiro return 0; 651a3633fe7SShimoda, Yoshihiro } 652a3633fe7SShimoda, Yoshihiro 6538449fd76SGeert Uytterhoeven static int rspi_transfer_out_in(struct rspi_data *rspi, 6548449fd76SGeert Uytterhoeven struct spi_transfer *xfer) 6558449fd76SGeert Uytterhoeven { 656b42e0359SGeert Uytterhoeven u8 spcr; 6576837b8e9SGeert Uytterhoeven int ret; 6588449fd76SGeert Uytterhoeven 6598449fd76SGeert Uytterhoeven spcr = rspi_read8(rspi, RSPI_SPCR); 6606837b8e9SGeert Uytterhoeven if (xfer->rx_buf) { 66132c64261SGeert Uytterhoeven rspi_receive_init(rspi); 6628449fd76SGeert Uytterhoeven spcr &= ~SPCR_TXMD; 66332c64261SGeert Uytterhoeven } else { 6648449fd76SGeert Uytterhoeven spcr |= SPCR_TXMD; 66532c64261SGeert Uytterhoeven } 6668449fd76SGeert Uytterhoeven rspi_write8(rspi, spcr, RSPI_SPCR); 6678449fd76SGeert Uytterhoeven 6686837b8e9SGeert Uytterhoeven ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len); 6698449fd76SGeert Uytterhoeven if (ret < 0) 6708449fd76SGeert Uytterhoeven return ret; 6718449fd76SGeert Uytterhoeven 6728449fd76SGeert Uytterhoeven /* Wait for the last transmission */ 6735f684c34SGeert Uytterhoeven rspi_wait_for_tx_empty(rspi); 6748449fd76SGeert Uytterhoeven 6758449fd76SGeert Uytterhoeven return 0; 6768449fd76SGeert Uytterhoeven } 6778449fd76SGeert Uytterhoeven 67879d23495SGeert Uytterhoeven static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi, 67979d23495SGeert Uytterhoeven struct spi_transfer *xfer) 6800b2182ddSShimoda, Yoshihiro { 68179d23495SGeert Uytterhoeven struct rspi_data *rspi = spi_master_get_devdata(master); 6828449fd76SGeert Uytterhoeven 6838449fd76SGeert Uytterhoeven if (!rspi_is_dma(rspi, xfer)) 6848449fd76SGeert Uytterhoeven return rspi_transfer_out_in(rspi, xfer); 6850b2182ddSShimoda, Yoshihiro 6868449fd76SGeert Uytterhoeven if (xfer->rx_buf) 687b42e0359SGeert Uytterhoeven return rspi_send_receive_dma(rspi, xfer); 688b42e0359SGeert Uytterhoeven else 689b42e0359SGeert Uytterhoeven return rspi_send_dma(rspi, xfer); 6900b2182ddSShimoda, Yoshihiro } 6910b2182ddSShimoda, Yoshihiro 692862d357fSGeert Uytterhoeven static int rspi_rz_transfer_out_in(struct rspi_data *rspi, 693862d357fSGeert Uytterhoeven struct spi_transfer *xfer) 694862d357fSGeert Uytterhoeven { 6956837b8e9SGeert Uytterhoeven int ret; 696862d357fSGeert Uytterhoeven 697862d357fSGeert Uytterhoeven rspi_rz_receive_init(rspi); 698862d357fSGeert Uytterhoeven 6996837b8e9SGeert Uytterhoeven ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len); 700862d357fSGeert Uytterhoeven if (ret < 0) 701862d357fSGeert Uytterhoeven return ret; 702862d357fSGeert Uytterhoeven 703862d357fSGeert Uytterhoeven /* Wait for the last transmission */ 7045f684c34SGeert Uytterhoeven rspi_wait_for_tx_empty(rspi); 705862d357fSGeert Uytterhoeven 706862d357fSGeert Uytterhoeven return 0; 707862d357fSGeert Uytterhoeven } 708862d357fSGeert Uytterhoeven 709862d357fSGeert Uytterhoeven static int rspi_rz_transfer_one(struct spi_master *master, 710862d357fSGeert Uytterhoeven struct spi_device *spi, 711862d357fSGeert Uytterhoeven struct spi_transfer *xfer) 712862d357fSGeert Uytterhoeven { 713862d357fSGeert Uytterhoeven struct rspi_data *rspi = spi_master_get_devdata(master); 714862d357fSGeert Uytterhoeven 715862d357fSGeert Uytterhoeven return rspi_rz_transfer_out_in(rspi, xfer); 716862d357fSGeert Uytterhoeven } 717862d357fSGeert Uytterhoeven 718340a15e6SGeert Uytterhoeven static int qspi_transfer_out_in(struct rspi_data *rspi, 719340a15e6SGeert Uytterhoeven struct spi_transfer *xfer) 720340a15e6SGeert Uytterhoeven { 7216837b8e9SGeert Uytterhoeven int ret; 722340a15e6SGeert Uytterhoeven 723340a15e6SGeert Uytterhoeven qspi_receive_init(rspi); 724340a15e6SGeert Uytterhoeven 7256837b8e9SGeert Uytterhoeven ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len); 726340a15e6SGeert Uytterhoeven if (ret < 0) 727340a15e6SGeert Uytterhoeven return ret; 728340a15e6SGeert Uytterhoeven 729340a15e6SGeert Uytterhoeven /* Wait for the last transmission */ 7305f684c34SGeert Uytterhoeven rspi_wait_for_tx_empty(rspi); 731340a15e6SGeert Uytterhoeven 732340a15e6SGeert Uytterhoeven return 0; 733340a15e6SGeert Uytterhoeven } 734340a15e6SGeert Uytterhoeven 735880c6d11SGeert Uytterhoeven static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) 736880c6d11SGeert Uytterhoeven { 737880c6d11SGeert Uytterhoeven int ret; 738880c6d11SGeert Uytterhoeven 7396837b8e9SGeert Uytterhoeven ret = rspi_pio_transfer(rspi, xfer->tx_buf, NULL, xfer->len); 740880c6d11SGeert Uytterhoeven if (ret < 0) 741880c6d11SGeert Uytterhoeven return ret; 742880c6d11SGeert Uytterhoeven 743880c6d11SGeert Uytterhoeven /* Wait for the last transmission */ 7445f684c34SGeert Uytterhoeven rspi_wait_for_tx_empty(rspi); 745880c6d11SGeert Uytterhoeven 746880c6d11SGeert Uytterhoeven return 0; 747880c6d11SGeert Uytterhoeven } 748880c6d11SGeert Uytterhoeven 749880c6d11SGeert Uytterhoeven static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) 750880c6d11SGeert Uytterhoeven { 7516837b8e9SGeert Uytterhoeven return rspi_pio_transfer(rspi, NULL, xfer->rx_buf, xfer->len); 752880c6d11SGeert Uytterhoeven } 753880c6d11SGeert Uytterhoeven 754eb557f75SGeert Uytterhoeven static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi, 755eb557f75SGeert Uytterhoeven struct spi_transfer *xfer) 756eb557f75SGeert Uytterhoeven { 757eb557f75SGeert Uytterhoeven struct rspi_data *rspi = spi_master_get_devdata(master); 758eb557f75SGeert Uytterhoeven 759ba824d49SGeert Uytterhoeven if (spi->mode & SPI_LOOP) { 760ba824d49SGeert Uytterhoeven return qspi_transfer_out_in(rspi, xfer); 761b42e0359SGeert Uytterhoeven } else if (xfer->tx_nbits > SPI_NBITS_SINGLE) { 762880c6d11SGeert Uytterhoeven /* Quad or Dual SPI Write */ 763880c6d11SGeert Uytterhoeven return qspi_transfer_out(rspi, xfer); 764b42e0359SGeert Uytterhoeven } else if (xfer->rx_nbits > SPI_NBITS_SINGLE) { 765880c6d11SGeert Uytterhoeven /* Quad or Dual SPI Read */ 766880c6d11SGeert Uytterhoeven return qspi_transfer_in(rspi, xfer); 767880c6d11SGeert Uytterhoeven } else { 768880c6d11SGeert Uytterhoeven /* Single SPI Transfer */ 769340a15e6SGeert Uytterhoeven return qspi_transfer_out_in(rspi, xfer); 770eb557f75SGeert Uytterhoeven } 771880c6d11SGeert Uytterhoeven } 772eb557f75SGeert Uytterhoeven 7730b2182ddSShimoda, Yoshihiro static int rspi_setup(struct spi_device *spi) 7740b2182ddSShimoda, Yoshihiro { 7750b2182ddSShimoda, Yoshihiro struct rspi_data *rspi = spi_master_get_devdata(spi->master); 7760b2182ddSShimoda, Yoshihiro 7770b2182ddSShimoda, Yoshihiro rspi->max_speed_hz = spi->max_speed_hz; 7780b2182ddSShimoda, Yoshihiro 779348e5153SGeert Uytterhoeven rspi->spcmd = SPCMD_SSLKP; 780348e5153SGeert Uytterhoeven if (spi->mode & SPI_CPOL) 781348e5153SGeert Uytterhoeven rspi->spcmd |= SPCMD_CPOL; 782348e5153SGeert Uytterhoeven if (spi->mode & SPI_CPHA) 783348e5153SGeert Uytterhoeven rspi->spcmd |= SPCMD_CPHA; 784348e5153SGeert Uytterhoeven 78506a7a3cfSGeert Uytterhoeven /* CMOS output mode and MOSI signal from previous transfer */ 78606a7a3cfSGeert Uytterhoeven rspi->sppcr = 0; 78706a7a3cfSGeert Uytterhoeven if (spi->mode & SPI_LOOP) 78806a7a3cfSGeert Uytterhoeven rspi->sppcr |= SPPCR_SPLP; 78906a7a3cfSGeert Uytterhoeven 7905ce0ba88SHiep Cao Minh set_config_register(rspi, 8); 7910b2182ddSShimoda, Yoshihiro 7920b2182ddSShimoda, Yoshihiro return 0; 7930b2182ddSShimoda, Yoshihiro } 7940b2182ddSShimoda, Yoshihiro 795880c6d11SGeert Uytterhoeven static u16 qspi_transfer_mode(const struct spi_transfer *xfer) 796880c6d11SGeert Uytterhoeven { 797880c6d11SGeert Uytterhoeven if (xfer->tx_buf) 798880c6d11SGeert Uytterhoeven switch (xfer->tx_nbits) { 799880c6d11SGeert Uytterhoeven case SPI_NBITS_QUAD: 800880c6d11SGeert Uytterhoeven return SPCMD_SPIMOD_QUAD; 801880c6d11SGeert Uytterhoeven case SPI_NBITS_DUAL: 802880c6d11SGeert Uytterhoeven return SPCMD_SPIMOD_DUAL; 803880c6d11SGeert Uytterhoeven default: 804880c6d11SGeert Uytterhoeven return 0; 805880c6d11SGeert Uytterhoeven } 806880c6d11SGeert Uytterhoeven if (xfer->rx_buf) 807880c6d11SGeert Uytterhoeven switch (xfer->rx_nbits) { 808880c6d11SGeert Uytterhoeven case SPI_NBITS_QUAD: 809880c6d11SGeert Uytterhoeven return SPCMD_SPIMOD_QUAD | SPCMD_SPRW; 810880c6d11SGeert Uytterhoeven case SPI_NBITS_DUAL: 811880c6d11SGeert Uytterhoeven return SPCMD_SPIMOD_DUAL | SPCMD_SPRW; 812880c6d11SGeert Uytterhoeven default: 813880c6d11SGeert Uytterhoeven return 0; 814880c6d11SGeert Uytterhoeven } 815880c6d11SGeert Uytterhoeven 816880c6d11SGeert Uytterhoeven return 0; 817880c6d11SGeert Uytterhoeven } 818880c6d11SGeert Uytterhoeven 819880c6d11SGeert Uytterhoeven static int qspi_setup_sequencer(struct rspi_data *rspi, 820880c6d11SGeert Uytterhoeven const struct spi_message *msg) 821880c6d11SGeert Uytterhoeven { 822880c6d11SGeert Uytterhoeven const struct spi_transfer *xfer; 823880c6d11SGeert Uytterhoeven unsigned int i = 0, len = 0; 824880c6d11SGeert Uytterhoeven u16 current_mode = 0xffff, mode; 825880c6d11SGeert Uytterhoeven 826880c6d11SGeert Uytterhoeven list_for_each_entry(xfer, &msg->transfers, transfer_list) { 827880c6d11SGeert Uytterhoeven mode = qspi_transfer_mode(xfer); 828880c6d11SGeert Uytterhoeven if (mode == current_mode) { 829880c6d11SGeert Uytterhoeven len += xfer->len; 830880c6d11SGeert Uytterhoeven continue; 831880c6d11SGeert Uytterhoeven } 832880c6d11SGeert Uytterhoeven 833880c6d11SGeert Uytterhoeven /* Transfer mode change */ 834880c6d11SGeert Uytterhoeven if (i) { 835880c6d11SGeert Uytterhoeven /* Set transfer data length of previous transfer */ 836880c6d11SGeert Uytterhoeven rspi_write32(rspi, len, QSPI_SPBMUL(i - 1)); 837880c6d11SGeert Uytterhoeven } 838880c6d11SGeert Uytterhoeven 839880c6d11SGeert Uytterhoeven if (i >= QSPI_NUM_SPCMD) { 840880c6d11SGeert Uytterhoeven dev_err(&msg->spi->dev, 841880c6d11SGeert Uytterhoeven "Too many different transfer modes"); 842880c6d11SGeert Uytterhoeven return -EINVAL; 843880c6d11SGeert Uytterhoeven } 844880c6d11SGeert Uytterhoeven 845880c6d11SGeert Uytterhoeven /* Program transfer mode for this transfer */ 846880c6d11SGeert Uytterhoeven rspi_write16(rspi, rspi->spcmd | mode, RSPI_SPCMD(i)); 847880c6d11SGeert Uytterhoeven current_mode = mode; 848880c6d11SGeert Uytterhoeven len = xfer->len; 849880c6d11SGeert Uytterhoeven i++; 850880c6d11SGeert Uytterhoeven } 851880c6d11SGeert Uytterhoeven if (i) { 852880c6d11SGeert Uytterhoeven /* Set final transfer data length and sequence length */ 853880c6d11SGeert Uytterhoeven rspi_write32(rspi, len, QSPI_SPBMUL(i - 1)); 854880c6d11SGeert Uytterhoeven rspi_write8(rspi, i - 1, RSPI_SPSCR); 855880c6d11SGeert Uytterhoeven } 856880c6d11SGeert Uytterhoeven 857880c6d11SGeert Uytterhoeven return 0; 858880c6d11SGeert Uytterhoeven } 859880c6d11SGeert Uytterhoeven 86079d23495SGeert Uytterhoeven static int rspi_prepare_message(struct spi_master *master, 861880c6d11SGeert Uytterhoeven struct spi_message *msg) 86279d23495SGeert Uytterhoeven { 86379d23495SGeert Uytterhoeven struct rspi_data *rspi = spi_master_get_devdata(master); 864880c6d11SGeert Uytterhoeven int ret; 8650b2182ddSShimoda, Yoshihiro 866880c6d11SGeert Uytterhoeven if (msg->spi->mode & 867880c6d11SGeert Uytterhoeven (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)) { 868880c6d11SGeert Uytterhoeven /* Setup sequencer for messages with multiple transfer modes */ 869880c6d11SGeert Uytterhoeven ret = qspi_setup_sequencer(rspi, msg); 870880c6d11SGeert Uytterhoeven if (ret < 0) 871880c6d11SGeert Uytterhoeven return ret; 872880c6d11SGeert Uytterhoeven } 873880c6d11SGeert Uytterhoeven 874880c6d11SGeert Uytterhoeven /* Enable SPI function in master mode */ 87579d23495SGeert Uytterhoeven rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR); 8760b2182ddSShimoda, Yoshihiro return 0; 8770b2182ddSShimoda, Yoshihiro } 8780b2182ddSShimoda, Yoshihiro 87979d23495SGeert Uytterhoeven static int rspi_unprepare_message(struct spi_master *master, 880880c6d11SGeert Uytterhoeven struct spi_message *msg) 8810b2182ddSShimoda, Yoshihiro { 88279d23495SGeert Uytterhoeven struct rspi_data *rspi = spi_master_get_devdata(master); 88379d23495SGeert Uytterhoeven 884880c6d11SGeert Uytterhoeven /* Disable SPI function */ 88579d23495SGeert Uytterhoeven rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR); 886880c6d11SGeert Uytterhoeven 887880c6d11SGeert Uytterhoeven /* Reset sequencer for Single SPI Transfers */ 888880c6d11SGeert Uytterhoeven rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 889880c6d11SGeert Uytterhoeven rspi_write8(rspi, 0, RSPI_SPSCR); 89079d23495SGeert Uytterhoeven return 0; 8910b2182ddSShimoda, Yoshihiro } 8920b2182ddSShimoda, Yoshihiro 89393722206SGeert Uytterhoeven static irqreturn_t rspi_irq_mux(int irq, void *_sr) 8940b2182ddSShimoda, Yoshihiro { 895c132f094SGeert Uytterhoeven struct rspi_data *rspi = _sr; 89697b95c11SGeert Uytterhoeven u8 spsr; 8970b2182ddSShimoda, Yoshihiro irqreturn_t ret = IRQ_NONE; 89897b95c11SGeert Uytterhoeven u8 disable_irq = 0; 8990b2182ddSShimoda, Yoshihiro 9000b2182ddSShimoda, Yoshihiro rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR); 9010b2182ddSShimoda, Yoshihiro if (spsr & SPSR_SPRF) 9020b2182ddSShimoda, Yoshihiro disable_irq |= SPCR_SPRIE; 9030b2182ddSShimoda, Yoshihiro if (spsr & SPSR_SPTEF) 9040b2182ddSShimoda, Yoshihiro disable_irq |= SPCR_SPTIE; 9050b2182ddSShimoda, Yoshihiro 9060b2182ddSShimoda, Yoshihiro if (disable_irq) { 9070b2182ddSShimoda, Yoshihiro ret = IRQ_HANDLED; 9080b2182ddSShimoda, Yoshihiro rspi_disable_irq(rspi, disable_irq); 9090b2182ddSShimoda, Yoshihiro wake_up(&rspi->wait); 9100b2182ddSShimoda, Yoshihiro } 9110b2182ddSShimoda, Yoshihiro 9120b2182ddSShimoda, Yoshihiro return ret; 9130b2182ddSShimoda, Yoshihiro } 9140b2182ddSShimoda, Yoshihiro 91593722206SGeert Uytterhoeven static irqreturn_t rspi_irq_rx(int irq, void *_sr) 91693722206SGeert Uytterhoeven { 91793722206SGeert Uytterhoeven struct rspi_data *rspi = _sr; 91893722206SGeert Uytterhoeven u8 spsr; 91993722206SGeert Uytterhoeven 92093722206SGeert Uytterhoeven rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR); 92193722206SGeert Uytterhoeven if (spsr & SPSR_SPRF) { 92293722206SGeert Uytterhoeven rspi_disable_irq(rspi, SPCR_SPRIE); 92393722206SGeert Uytterhoeven wake_up(&rspi->wait); 92493722206SGeert Uytterhoeven return IRQ_HANDLED; 92593722206SGeert Uytterhoeven } 92693722206SGeert Uytterhoeven 92793722206SGeert Uytterhoeven return 0; 92893722206SGeert Uytterhoeven } 92993722206SGeert Uytterhoeven 93093722206SGeert Uytterhoeven static irqreturn_t rspi_irq_tx(int irq, void *_sr) 93193722206SGeert Uytterhoeven { 93293722206SGeert Uytterhoeven struct rspi_data *rspi = _sr; 93393722206SGeert Uytterhoeven u8 spsr; 93493722206SGeert Uytterhoeven 93593722206SGeert Uytterhoeven rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR); 93693722206SGeert Uytterhoeven if (spsr & SPSR_SPTEF) { 93793722206SGeert Uytterhoeven rspi_disable_irq(rspi, SPCR_SPTIE); 93893722206SGeert Uytterhoeven wake_up(&rspi->wait); 93993722206SGeert Uytterhoeven return IRQ_HANDLED; 94093722206SGeert Uytterhoeven } 94193722206SGeert Uytterhoeven 94293722206SGeert Uytterhoeven return 0; 94393722206SGeert Uytterhoeven } 94493722206SGeert Uytterhoeven 945fd4a319bSGrant Likely static int rspi_request_dma(struct rspi_data *rspi, 946a3633fe7SShimoda, Yoshihiro struct platform_device *pdev) 947a3633fe7SShimoda, Yoshihiro { 948baf588f4SGeert Uytterhoeven const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev); 949e2b05099SGuennadi Liakhovetski struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 950a3633fe7SShimoda, Yoshihiro dma_cap_mask_t mask; 9510243c536SShimoda, Yoshihiro struct dma_slave_config cfg; 9520243c536SShimoda, Yoshihiro int ret; 953a3633fe7SShimoda, Yoshihiro 954e2b05099SGuennadi Liakhovetski if (!res || !rspi_pd) 9550243c536SShimoda, Yoshihiro return 0; /* The driver assumes no error. */ 956a3633fe7SShimoda, Yoshihiro 957a3633fe7SShimoda, Yoshihiro /* If the module receives data by DMAC, it also needs TX DMAC */ 958a3633fe7SShimoda, Yoshihiro if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) { 959a3633fe7SShimoda, Yoshihiro dma_cap_zero(mask); 960a3633fe7SShimoda, Yoshihiro dma_cap_set(DMA_SLAVE, mask); 9610243c536SShimoda, Yoshihiro rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter, 9620243c536SShimoda, Yoshihiro (void *)rspi_pd->dma_rx_id); 9630243c536SShimoda, Yoshihiro if (rspi->chan_rx) { 9640243c536SShimoda, Yoshihiro cfg.slave_id = rspi_pd->dma_rx_id; 9650243c536SShimoda, Yoshihiro cfg.direction = DMA_DEV_TO_MEM; 966e2b05099SGuennadi Liakhovetski cfg.dst_addr = 0; 967e2b05099SGuennadi Liakhovetski cfg.src_addr = res->start + RSPI_SPDR; 9680243c536SShimoda, Yoshihiro ret = dmaengine_slave_config(rspi->chan_rx, &cfg); 9690243c536SShimoda, Yoshihiro if (!ret) 970a3633fe7SShimoda, Yoshihiro dev_info(&pdev->dev, "Use DMA when rx.\n"); 9710243c536SShimoda, Yoshihiro else 9720243c536SShimoda, Yoshihiro return ret; 9730243c536SShimoda, Yoshihiro } 974a3633fe7SShimoda, Yoshihiro } 975a3633fe7SShimoda, Yoshihiro if (rspi_pd->dma_tx_id) { 976a3633fe7SShimoda, Yoshihiro dma_cap_zero(mask); 977a3633fe7SShimoda, Yoshihiro dma_cap_set(DMA_SLAVE, mask); 9780243c536SShimoda, Yoshihiro rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter, 9790243c536SShimoda, Yoshihiro (void *)rspi_pd->dma_tx_id); 9800243c536SShimoda, Yoshihiro if (rspi->chan_tx) { 9810243c536SShimoda, Yoshihiro cfg.slave_id = rspi_pd->dma_tx_id; 9820243c536SShimoda, Yoshihiro cfg.direction = DMA_MEM_TO_DEV; 983e2b05099SGuennadi Liakhovetski cfg.dst_addr = res->start + RSPI_SPDR; 984e2b05099SGuennadi Liakhovetski cfg.src_addr = 0; 9850243c536SShimoda, Yoshihiro ret = dmaengine_slave_config(rspi->chan_tx, &cfg); 9860243c536SShimoda, Yoshihiro if (!ret) 987a3633fe7SShimoda, Yoshihiro dev_info(&pdev->dev, "Use DMA when tx\n"); 9880243c536SShimoda, Yoshihiro else 9890243c536SShimoda, Yoshihiro return ret; 990a3633fe7SShimoda, Yoshihiro } 991a3633fe7SShimoda, Yoshihiro } 992a3633fe7SShimoda, Yoshihiro 9930243c536SShimoda, Yoshihiro return 0; 9940243c536SShimoda, Yoshihiro } 9950243c536SShimoda, Yoshihiro 996fd4a319bSGrant Likely static void rspi_release_dma(struct rspi_data *rspi) 997a3633fe7SShimoda, Yoshihiro { 998a3633fe7SShimoda, Yoshihiro if (rspi->chan_tx) 999a3633fe7SShimoda, Yoshihiro dma_release_channel(rspi->chan_tx); 1000a3633fe7SShimoda, Yoshihiro if (rspi->chan_rx) 1001a3633fe7SShimoda, Yoshihiro dma_release_channel(rspi->chan_rx); 1002a3633fe7SShimoda, Yoshihiro } 1003a3633fe7SShimoda, Yoshihiro 1004fd4a319bSGrant Likely static int rspi_remove(struct platform_device *pdev) 10050b2182ddSShimoda, Yoshihiro { 10065ffbe2d9SLaurent Pinchart struct rspi_data *rspi = platform_get_drvdata(pdev); 10070b2182ddSShimoda, Yoshihiro 1008a3633fe7SShimoda, Yoshihiro rspi_release_dma(rspi); 1009490c9774SGeert Uytterhoeven pm_runtime_disable(&pdev->dev); 10100b2182ddSShimoda, Yoshihiro 10110b2182ddSShimoda, Yoshihiro return 0; 10120b2182ddSShimoda, Yoshihiro } 10130b2182ddSShimoda, Yoshihiro 1014426ef76dSGeert Uytterhoeven static const struct spi_ops rspi_ops = { 1015426ef76dSGeert Uytterhoeven .set_config_register = rspi_set_config_register, 1016426ef76dSGeert Uytterhoeven .transfer_one = rspi_transfer_one, 1017880c6d11SGeert Uytterhoeven .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP, 1018b42e0359SGeert Uytterhoeven .flags = SPI_MASTER_MUST_TX, 1019426ef76dSGeert Uytterhoeven }; 1020426ef76dSGeert Uytterhoeven 1021426ef76dSGeert Uytterhoeven static const struct spi_ops rspi_rz_ops = { 1022426ef76dSGeert Uytterhoeven .set_config_register = rspi_rz_set_config_register, 1023426ef76dSGeert Uytterhoeven .transfer_one = rspi_rz_transfer_one, 1024880c6d11SGeert Uytterhoeven .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP, 1025b42e0359SGeert Uytterhoeven .flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX, 1026426ef76dSGeert Uytterhoeven }; 1027426ef76dSGeert Uytterhoeven 1028426ef76dSGeert Uytterhoeven static const struct spi_ops qspi_ops = { 1029426ef76dSGeert Uytterhoeven .set_config_register = qspi_set_config_register, 1030426ef76dSGeert Uytterhoeven .transfer_one = qspi_transfer_one, 1031880c6d11SGeert Uytterhoeven .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP | 1032880c6d11SGeert Uytterhoeven SPI_TX_DUAL | SPI_TX_QUAD | 1033880c6d11SGeert Uytterhoeven SPI_RX_DUAL | SPI_RX_QUAD, 1034b42e0359SGeert Uytterhoeven .flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX, 1035426ef76dSGeert Uytterhoeven }; 1036426ef76dSGeert Uytterhoeven 1037426ef76dSGeert Uytterhoeven #ifdef CONFIG_OF 1038426ef76dSGeert Uytterhoeven static const struct of_device_id rspi_of_match[] = { 1039426ef76dSGeert Uytterhoeven /* RSPI on legacy SH */ 1040426ef76dSGeert Uytterhoeven { .compatible = "renesas,rspi", .data = &rspi_ops }, 1041426ef76dSGeert Uytterhoeven /* RSPI on RZ/A1H */ 1042426ef76dSGeert Uytterhoeven { .compatible = "renesas,rspi-rz", .data = &rspi_rz_ops }, 1043426ef76dSGeert Uytterhoeven /* QSPI on R-Car Gen2 */ 1044426ef76dSGeert Uytterhoeven { .compatible = "renesas,qspi", .data = &qspi_ops }, 1045426ef76dSGeert Uytterhoeven { /* sentinel */ } 1046426ef76dSGeert Uytterhoeven }; 1047426ef76dSGeert Uytterhoeven 1048426ef76dSGeert Uytterhoeven MODULE_DEVICE_TABLE(of, rspi_of_match); 1049426ef76dSGeert Uytterhoeven 1050426ef76dSGeert Uytterhoeven static int rspi_parse_dt(struct device *dev, struct spi_master *master) 1051426ef76dSGeert Uytterhoeven { 1052426ef76dSGeert Uytterhoeven u32 num_cs; 1053426ef76dSGeert Uytterhoeven int error; 1054426ef76dSGeert Uytterhoeven 1055426ef76dSGeert Uytterhoeven /* Parse DT properties */ 1056426ef76dSGeert Uytterhoeven error = of_property_read_u32(dev->of_node, "num-cs", &num_cs); 1057426ef76dSGeert Uytterhoeven if (error) { 1058426ef76dSGeert Uytterhoeven dev_err(dev, "of_property_read_u32 num-cs failed %d\n", error); 1059426ef76dSGeert Uytterhoeven return error; 1060426ef76dSGeert Uytterhoeven } 1061426ef76dSGeert Uytterhoeven 1062426ef76dSGeert Uytterhoeven master->num_chipselect = num_cs; 1063426ef76dSGeert Uytterhoeven return 0; 1064426ef76dSGeert Uytterhoeven } 1065426ef76dSGeert Uytterhoeven #else 106664b67defSShimoda, Yoshihiro #define rspi_of_match NULL 1067426ef76dSGeert Uytterhoeven static inline int rspi_parse_dt(struct device *dev, struct spi_master *master) 1068426ef76dSGeert Uytterhoeven { 1069426ef76dSGeert Uytterhoeven return -EINVAL; 1070426ef76dSGeert Uytterhoeven } 1071426ef76dSGeert Uytterhoeven #endif /* CONFIG_OF */ 1072426ef76dSGeert Uytterhoeven 107393722206SGeert Uytterhoeven static int rspi_request_irq(struct device *dev, unsigned int irq, 107493722206SGeert Uytterhoeven irq_handler_t handler, const char *suffix, 107593722206SGeert Uytterhoeven void *dev_id) 107693722206SGeert Uytterhoeven { 107793722206SGeert Uytterhoeven const char *base = dev_name(dev); 107893722206SGeert Uytterhoeven size_t len = strlen(base) + strlen(suffix) + 2; 107993722206SGeert Uytterhoeven char *name = devm_kzalloc(dev, len, GFP_KERNEL); 108093722206SGeert Uytterhoeven if (!name) 108193722206SGeert Uytterhoeven return -ENOMEM; 108293722206SGeert Uytterhoeven snprintf(name, len, "%s:%s", base, suffix); 108393722206SGeert Uytterhoeven return devm_request_irq(dev, irq, handler, 0, name, dev_id); 108493722206SGeert Uytterhoeven } 108593722206SGeert Uytterhoeven 1086fd4a319bSGrant Likely static int rspi_probe(struct platform_device *pdev) 10870b2182ddSShimoda, Yoshihiro { 10880b2182ddSShimoda, Yoshihiro struct resource *res; 10890b2182ddSShimoda, Yoshihiro struct spi_master *master; 10900b2182ddSShimoda, Yoshihiro struct rspi_data *rspi; 109193722206SGeert Uytterhoeven int ret; 1092426ef76dSGeert Uytterhoeven const struct of_device_id *of_id; 1093426ef76dSGeert Uytterhoeven const struct rspi_plat_data *rspi_pd; 10945ce0ba88SHiep Cao Minh const struct spi_ops *ops; 10950b2182ddSShimoda, Yoshihiro 10960b2182ddSShimoda, Yoshihiro master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data)); 10970b2182ddSShimoda, Yoshihiro if (master == NULL) { 10980b2182ddSShimoda, Yoshihiro dev_err(&pdev->dev, "spi_alloc_master error.\n"); 10990b2182ddSShimoda, Yoshihiro return -ENOMEM; 11000b2182ddSShimoda, Yoshihiro } 11010b2182ddSShimoda, Yoshihiro 1102426ef76dSGeert Uytterhoeven of_id = of_match_device(rspi_of_match, &pdev->dev); 1103426ef76dSGeert Uytterhoeven if (of_id) { 1104426ef76dSGeert Uytterhoeven ops = of_id->data; 1105426ef76dSGeert Uytterhoeven ret = rspi_parse_dt(&pdev->dev, master); 1106426ef76dSGeert Uytterhoeven if (ret) 1107426ef76dSGeert Uytterhoeven goto error1; 1108426ef76dSGeert Uytterhoeven } else { 1109426ef76dSGeert Uytterhoeven ops = (struct spi_ops *)pdev->id_entry->driver_data; 1110426ef76dSGeert Uytterhoeven rspi_pd = dev_get_platdata(&pdev->dev); 1111426ef76dSGeert Uytterhoeven if (rspi_pd && rspi_pd->num_chipselect) 1112426ef76dSGeert Uytterhoeven master->num_chipselect = rspi_pd->num_chipselect; 1113426ef76dSGeert Uytterhoeven else 1114426ef76dSGeert Uytterhoeven master->num_chipselect = 2; /* default */ 1115426ef76dSGeert Uytterhoeven }; 1116426ef76dSGeert Uytterhoeven 1117426ef76dSGeert Uytterhoeven /* ops parameter check */ 1118426ef76dSGeert Uytterhoeven if (!ops->set_config_register) { 1119426ef76dSGeert Uytterhoeven dev_err(&pdev->dev, "there is no set_config_register\n"); 1120426ef76dSGeert Uytterhoeven ret = -ENODEV; 1121426ef76dSGeert Uytterhoeven goto error1; 1122426ef76dSGeert Uytterhoeven } 1123426ef76dSGeert Uytterhoeven 11240b2182ddSShimoda, Yoshihiro rspi = spi_master_get_devdata(master); 112524b5a82cSJingoo Han platform_set_drvdata(pdev, rspi); 11265ce0ba88SHiep Cao Minh rspi->ops = ops; 11270b2182ddSShimoda, Yoshihiro rspi->master = master; 11285d79e9acSLaurent Pinchart 11295d79e9acSLaurent Pinchart res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 11305d79e9acSLaurent Pinchart rspi->addr = devm_ioremap_resource(&pdev->dev, res); 11315d79e9acSLaurent Pinchart if (IS_ERR(rspi->addr)) { 11325d79e9acSLaurent Pinchart ret = PTR_ERR(rspi->addr); 11330b2182ddSShimoda, Yoshihiro goto error1; 11340b2182ddSShimoda, Yoshihiro } 11350b2182ddSShimoda, Yoshihiro 113629f397b7SGeert Uytterhoeven rspi->clk = devm_clk_get(&pdev->dev, NULL); 11370b2182ddSShimoda, Yoshihiro if (IS_ERR(rspi->clk)) { 11380b2182ddSShimoda, Yoshihiro dev_err(&pdev->dev, "cannot get clock\n"); 11390b2182ddSShimoda, Yoshihiro ret = PTR_ERR(rspi->clk); 11405d79e9acSLaurent Pinchart goto error1; 11410b2182ddSShimoda, Yoshihiro } 114217fe0d9aSGeert Uytterhoeven 1143490c9774SGeert Uytterhoeven pm_runtime_enable(&pdev->dev); 11440b2182ddSShimoda, Yoshihiro 11450b2182ddSShimoda, Yoshihiro init_waitqueue_head(&rspi->wait); 11460b2182ddSShimoda, Yoshihiro 11470b2182ddSShimoda, Yoshihiro master->bus_num = pdev->id; 11480b2182ddSShimoda, Yoshihiro master->setup = rspi_setup; 1149490c9774SGeert Uytterhoeven master->auto_runtime_pm = true; 1150eb557f75SGeert Uytterhoeven master->transfer_one = ops->transfer_one; 115179d23495SGeert Uytterhoeven master->prepare_message = rspi_prepare_message; 115279d23495SGeert Uytterhoeven master->unprepare_message = rspi_unprepare_message; 1153880c6d11SGeert Uytterhoeven master->mode_bits = ops->mode_bits; 1154b42e0359SGeert Uytterhoeven master->flags = ops->flags; 1155426ef76dSGeert Uytterhoeven master->dev.of_node = pdev->dev.of_node; 11560b2182ddSShimoda, Yoshihiro 115793722206SGeert Uytterhoeven ret = platform_get_irq_byname(pdev, "rx"); 115893722206SGeert Uytterhoeven if (ret < 0) { 115993722206SGeert Uytterhoeven ret = platform_get_irq_byname(pdev, "mux"); 116093722206SGeert Uytterhoeven if (ret < 0) 116193722206SGeert Uytterhoeven ret = platform_get_irq(pdev, 0); 116293722206SGeert Uytterhoeven if (ret >= 0) 116393722206SGeert Uytterhoeven rspi->rx_irq = rspi->tx_irq = ret; 116493722206SGeert Uytterhoeven } else { 116593722206SGeert Uytterhoeven rspi->rx_irq = ret; 116693722206SGeert Uytterhoeven ret = platform_get_irq_byname(pdev, "tx"); 116793722206SGeert Uytterhoeven if (ret >= 0) 116893722206SGeert Uytterhoeven rspi->tx_irq = ret; 116993722206SGeert Uytterhoeven } 117093722206SGeert Uytterhoeven if (ret < 0) { 117193722206SGeert Uytterhoeven dev_err(&pdev->dev, "platform_get_irq error\n"); 117293722206SGeert Uytterhoeven goto error2; 117393722206SGeert Uytterhoeven } 117493722206SGeert Uytterhoeven 117593722206SGeert Uytterhoeven if (rspi->rx_irq == rspi->tx_irq) { 117693722206SGeert Uytterhoeven /* Single multiplexed interrupt */ 117793722206SGeert Uytterhoeven ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_mux, 117893722206SGeert Uytterhoeven "mux", rspi); 117993722206SGeert Uytterhoeven } else { 118093722206SGeert Uytterhoeven /* Multi-interrupt mode, only SPRI and SPTI are used */ 118193722206SGeert Uytterhoeven ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_rx, 118293722206SGeert Uytterhoeven "rx", rspi); 118393722206SGeert Uytterhoeven if (!ret) 118493722206SGeert Uytterhoeven ret = rspi_request_irq(&pdev->dev, rspi->tx_irq, 118593722206SGeert Uytterhoeven rspi_irq_tx, "tx", rspi); 118693722206SGeert Uytterhoeven } 11870b2182ddSShimoda, Yoshihiro if (ret < 0) { 11880b2182ddSShimoda, Yoshihiro dev_err(&pdev->dev, "request_irq error\n"); 1189fcb4ed74SGeert Uytterhoeven goto error2; 11900b2182ddSShimoda, Yoshihiro } 11910b2182ddSShimoda, Yoshihiro 11920243c536SShimoda, Yoshihiro ret = rspi_request_dma(rspi, pdev); 119327e105a6SGeert Uytterhoeven if (ret < 0) 119427e105a6SGeert Uytterhoeven dev_warn(&pdev->dev, "DMA not available, using PIO\n"); 1195a3633fe7SShimoda, Yoshihiro 11969e03d05eSJingoo Han ret = devm_spi_register_master(&pdev->dev, master); 11970b2182ddSShimoda, Yoshihiro if (ret < 0) { 11980b2182ddSShimoda, Yoshihiro dev_err(&pdev->dev, "spi_register_master error.\n"); 1199fcb4ed74SGeert Uytterhoeven goto error3; 12000b2182ddSShimoda, Yoshihiro } 12010b2182ddSShimoda, Yoshihiro 12020b2182ddSShimoda, Yoshihiro dev_info(&pdev->dev, "probed\n"); 12030b2182ddSShimoda, Yoshihiro 12040b2182ddSShimoda, Yoshihiro return 0; 12050b2182ddSShimoda, Yoshihiro 1206fcb4ed74SGeert Uytterhoeven error3: 12075d79e9acSLaurent Pinchart rspi_release_dma(rspi); 1208fcb4ed74SGeert Uytterhoeven error2: 1209490c9774SGeert Uytterhoeven pm_runtime_disable(&pdev->dev); 12100b2182ddSShimoda, Yoshihiro error1: 12110b2182ddSShimoda, Yoshihiro spi_master_put(master); 12120b2182ddSShimoda, Yoshihiro 12130b2182ddSShimoda, Yoshihiro return ret; 12140b2182ddSShimoda, Yoshihiro } 12150b2182ddSShimoda, Yoshihiro 12165ce0ba88SHiep Cao Minh static struct platform_device_id spi_driver_ids[] = { 12175ce0ba88SHiep Cao Minh { "rspi", (kernel_ulong_t)&rspi_ops }, 1218862d357fSGeert Uytterhoeven { "rspi-rz", (kernel_ulong_t)&rspi_rz_ops }, 12195ce0ba88SHiep Cao Minh { "qspi", (kernel_ulong_t)&qspi_ops }, 12205ce0ba88SHiep Cao Minh {}, 12215ce0ba88SHiep Cao Minh }; 12225ce0ba88SHiep Cao Minh 12235ce0ba88SHiep Cao Minh MODULE_DEVICE_TABLE(platform, spi_driver_ids); 12245ce0ba88SHiep Cao Minh 12250b2182ddSShimoda, Yoshihiro static struct platform_driver rspi_driver = { 12260b2182ddSShimoda, Yoshihiro .probe = rspi_probe, 1227fd4a319bSGrant Likely .remove = rspi_remove, 12285ce0ba88SHiep Cao Minh .id_table = spi_driver_ids, 12290b2182ddSShimoda, Yoshihiro .driver = { 12305ce0ba88SHiep Cao Minh .name = "renesas_spi", 12310b2182ddSShimoda, Yoshihiro .owner = THIS_MODULE, 1232426ef76dSGeert Uytterhoeven .of_match_table = of_match_ptr(rspi_of_match), 12330b2182ddSShimoda, Yoshihiro }, 12340b2182ddSShimoda, Yoshihiro }; 12350b2182ddSShimoda, Yoshihiro module_platform_driver(rspi_driver); 12360b2182ddSShimoda, Yoshihiro 12370b2182ddSShimoda, Yoshihiro MODULE_DESCRIPTION("Renesas RSPI bus driver"); 12380b2182ddSShimoda, Yoshihiro MODULE_LICENSE("GPL v2"); 12390b2182ddSShimoda, Yoshihiro MODULE_AUTHOR("Yoshihiro Shimoda"); 12400b2182ddSShimoda, Yoshihiro MODULE_ALIAS("platform:rspi"); 1241