19135bac3SWolfram Sang // SPDX-License-Identifier: GPL-2.0 20b2182ddSShimoda, Yoshihiro /* 30b2182ddSShimoda, Yoshihiro * SH RSPI driver 40b2182ddSShimoda, Yoshihiro * 593722206SGeert Uytterhoeven * Copyright (C) 2012, 2013 Renesas Solutions Corp. 6880c6d11SGeert Uytterhoeven * Copyright (C) 2014 Glider bvba 70b2182ddSShimoda, Yoshihiro * 80b2182ddSShimoda, Yoshihiro * Based on spi-sh.c: 90b2182ddSShimoda, Yoshihiro * Copyright (C) 2011 Renesas Solutions Corp. 100b2182ddSShimoda, Yoshihiro */ 110b2182ddSShimoda, Yoshihiro 120b2182ddSShimoda, Yoshihiro #include <linux/module.h> 130b2182ddSShimoda, Yoshihiro #include <linux/kernel.h> 140b2182ddSShimoda, Yoshihiro #include <linux/sched.h> 150b2182ddSShimoda, Yoshihiro #include <linux/errno.h> 160b2182ddSShimoda, Yoshihiro #include <linux/interrupt.h> 170b2182ddSShimoda, Yoshihiro #include <linux/platform_device.h> 180b2182ddSShimoda, Yoshihiro #include <linux/io.h> 190b2182ddSShimoda, Yoshihiro #include <linux/clk.h> 20a3633fe7SShimoda, Yoshihiro #include <linux/dmaengine.h> 21a3633fe7SShimoda, Yoshihiro #include <linux/dma-mapping.h> 22426ef76dSGeert Uytterhoeven #include <linux/of_device.h> 23490c9774SGeert Uytterhoeven #include <linux/pm_runtime.h> 24aadbff4aSLad Prabhakar #include <linux/reset.h> 25a3633fe7SShimoda, Yoshihiro #include <linux/sh_dma.h> 260b2182ddSShimoda, Yoshihiro #include <linux/spi/spi.h> 27a3633fe7SShimoda, Yoshihiro #include <linux/spi/rspi.h> 28f3a14a3aSGeert Uytterhoeven #include <linux/spinlock.h> 290b2182ddSShimoda, Yoshihiro 306ab4865bSGeert Uytterhoeven #define RSPI_SPCR 0x00 /* Control Register */ 316ab4865bSGeert Uytterhoeven #define RSPI_SSLP 0x01 /* Slave Select Polarity Register */ 326ab4865bSGeert Uytterhoeven #define RSPI_SPPCR 0x02 /* Pin Control Register */ 336ab4865bSGeert Uytterhoeven #define RSPI_SPSR 0x03 /* Status Register */ 346ab4865bSGeert Uytterhoeven #define RSPI_SPDR 0x04 /* Data Register */ 356ab4865bSGeert Uytterhoeven #define RSPI_SPSCR 0x08 /* Sequence Control Register */ 366ab4865bSGeert Uytterhoeven #define RSPI_SPSSR 0x09 /* Sequence Status Register */ 376ab4865bSGeert Uytterhoeven #define RSPI_SPBR 0x0a /* Bit Rate Register */ 386ab4865bSGeert Uytterhoeven #define RSPI_SPDCR 0x0b /* Data Control Register */ 396ab4865bSGeert Uytterhoeven #define RSPI_SPCKD 0x0c /* Clock Delay Register */ 406ab4865bSGeert Uytterhoeven #define RSPI_SSLND 0x0d /* Slave Select Negation Delay Register */ 416ab4865bSGeert Uytterhoeven #define RSPI_SPND 0x0e /* Next-Access Delay Register */ 42862d357fSGeert Uytterhoeven #define RSPI_SPCR2 0x0f /* Control Register 2 (SH only) */ 436ab4865bSGeert Uytterhoeven #define RSPI_SPCMD0 0x10 /* Command Register 0 */ 446ab4865bSGeert Uytterhoeven #define RSPI_SPCMD1 0x12 /* Command Register 1 */ 456ab4865bSGeert Uytterhoeven #define RSPI_SPCMD2 0x14 /* Command Register 2 */ 466ab4865bSGeert Uytterhoeven #define RSPI_SPCMD3 0x16 /* Command Register 3 */ 476ab4865bSGeert Uytterhoeven #define RSPI_SPCMD4 0x18 /* Command Register 4 */ 486ab4865bSGeert Uytterhoeven #define RSPI_SPCMD5 0x1a /* Command Register 5 */ 496ab4865bSGeert Uytterhoeven #define RSPI_SPCMD6 0x1c /* Command Register 6 */ 506ab4865bSGeert Uytterhoeven #define RSPI_SPCMD7 0x1e /* Command Register 7 */ 51880c6d11SGeert Uytterhoeven #define RSPI_SPCMD(i) (RSPI_SPCMD0 + (i) * 2) 52880c6d11SGeert Uytterhoeven #define RSPI_NUM_SPCMD 8 53880c6d11SGeert Uytterhoeven #define RSPI_RZ_NUM_SPCMD 4 54880c6d11SGeert Uytterhoeven #define QSPI_NUM_SPCMD 4 55862d357fSGeert Uytterhoeven 56862d357fSGeert Uytterhoeven /* RSPI on RZ only */ 576ab4865bSGeert Uytterhoeven #define RSPI_SPBFCR 0x20 /* Buffer Control Register */ 586ab4865bSGeert Uytterhoeven #define RSPI_SPBFDR 0x22 /* Buffer Data Count Setting Register */ 590b2182ddSShimoda, Yoshihiro 60862d357fSGeert Uytterhoeven /* QSPI only */ 61fbe5072bSGeert Uytterhoeven #define QSPI_SPBFCR 0x18 /* Buffer Control Register */ 62fbe5072bSGeert Uytterhoeven #define QSPI_SPBDCR 0x1a /* Buffer Data Count Register */ 63fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL0 0x1c /* Transfer Data Length Multiplier Setting Register 0 */ 64fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL1 0x20 /* Transfer Data Length Multiplier Setting Register 1 */ 65fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL2 0x24 /* Transfer Data Length Multiplier Setting Register 2 */ 66fbe5072bSGeert Uytterhoeven #define QSPI_SPBMUL3 0x28 /* Transfer Data Length Multiplier Setting Register 3 */ 67880c6d11SGeert Uytterhoeven #define QSPI_SPBMUL(i) (QSPI_SPBMUL0 + (i) * 4) 685ce0ba88SHiep Cao Minh 696ab4865bSGeert Uytterhoeven /* SPCR - Control Register */ 706ab4865bSGeert Uytterhoeven #define SPCR_SPRIE 0x80 /* Receive Interrupt Enable */ 716ab4865bSGeert Uytterhoeven #define SPCR_SPE 0x40 /* Function Enable */ 726ab4865bSGeert Uytterhoeven #define SPCR_SPTIE 0x20 /* Transmit Interrupt Enable */ 736ab4865bSGeert Uytterhoeven #define SPCR_SPEIE 0x10 /* Error Interrupt Enable */ 746ab4865bSGeert Uytterhoeven #define SPCR_MSTR 0x08 /* Master/Slave Mode Select */ 756ab4865bSGeert Uytterhoeven #define SPCR_MODFEN 0x04 /* Mode Fault Error Detection Enable */ 766ab4865bSGeert Uytterhoeven /* RSPI on SH only */ 776ab4865bSGeert Uytterhoeven #define SPCR_TXMD 0x02 /* TX Only Mode (vs. Full Duplex) */ 786ab4865bSGeert Uytterhoeven #define SPCR_SPMS 0x01 /* 3-wire Mode (vs. 4-wire) */ 796089af77SGeert Uytterhoeven /* QSPI on R-Car Gen2 only */ 80fbe5072bSGeert Uytterhoeven #define SPCR_WSWAP 0x02 /* Word Swap of read-data for DMAC */ 81fbe5072bSGeert Uytterhoeven #define SPCR_BSWAP 0x01 /* Byte Swap of read-data for DMAC */ 820b2182ddSShimoda, Yoshihiro 836ab4865bSGeert Uytterhoeven /* SSLP - Slave Select Polarity Register */ 84f3a14a3aSGeert Uytterhoeven #define SSLP_SSLP(i) BIT(i) /* SSLi Signal Polarity Setting */ 850b2182ddSShimoda, Yoshihiro 866ab4865bSGeert Uytterhoeven /* SPPCR - Pin Control Register */ 876ab4865bSGeert Uytterhoeven #define SPPCR_MOIFE 0x20 /* MOSI Idle Value Fixing Enable */ 886ab4865bSGeert Uytterhoeven #define SPPCR_MOIFV 0x10 /* MOSI Idle Fixed Value */ 890b2182ddSShimoda, Yoshihiro #define SPPCR_SPOM 0x04 906ab4865bSGeert Uytterhoeven #define SPPCR_SPLP2 0x02 /* Loopback Mode 2 (non-inverting) */ 916ab4865bSGeert Uytterhoeven #define SPPCR_SPLP 0x01 /* Loopback Mode (inverting) */ 920b2182ddSShimoda, Yoshihiro 93fbe5072bSGeert Uytterhoeven #define SPPCR_IO3FV 0x04 /* Single-/Dual-SPI Mode IO3 Output Fixed Value */ 94fbe5072bSGeert Uytterhoeven #define SPPCR_IO2FV 0x04 /* Single-/Dual-SPI Mode IO2 Output Fixed Value */ 95fbe5072bSGeert Uytterhoeven 966ab4865bSGeert Uytterhoeven /* SPSR - Status Register */ 976ab4865bSGeert Uytterhoeven #define SPSR_SPRF 0x80 /* Receive Buffer Full Flag */ 986ab4865bSGeert Uytterhoeven #define SPSR_TEND 0x40 /* Transmit End */ 996ab4865bSGeert Uytterhoeven #define SPSR_SPTEF 0x20 /* Transmit Buffer Empty Flag */ 1006ab4865bSGeert Uytterhoeven #define SPSR_PERF 0x08 /* Parity Error Flag */ 1016ab4865bSGeert Uytterhoeven #define SPSR_MODF 0x04 /* Mode Fault Error Flag */ 1026ab4865bSGeert Uytterhoeven #define SPSR_IDLNF 0x02 /* RSPI Idle Flag */ 103862d357fSGeert Uytterhoeven #define SPSR_OVRF 0x01 /* Overrun Error Flag (RSPI only) */ 1040b2182ddSShimoda, Yoshihiro 1056ab4865bSGeert Uytterhoeven /* SPSCR - Sequence Control Register */ 1066ab4865bSGeert Uytterhoeven #define SPSCR_SPSLN_MASK 0x07 /* Sequence Length Specification */ 1070b2182ddSShimoda, Yoshihiro 1086ab4865bSGeert Uytterhoeven /* SPSSR - Sequence Status Register */ 1096ab4865bSGeert Uytterhoeven #define SPSSR_SPECM_MASK 0x70 /* Command Error Mask */ 1106ab4865bSGeert Uytterhoeven #define SPSSR_SPCP_MASK 0x07 /* Command Pointer Mask */ 1110b2182ddSShimoda, Yoshihiro 1126ab4865bSGeert Uytterhoeven /* SPDCR - Data Control Register */ 1136ab4865bSGeert Uytterhoeven #define SPDCR_TXDMY 0x80 /* Dummy Data Transmission Enable */ 1146ab4865bSGeert Uytterhoeven #define SPDCR_SPLW1 0x40 /* Access Width Specification (RZ) */ 1156ab4865bSGeert Uytterhoeven #define SPDCR_SPLW0 0x20 /* Access Width Specification (RZ) */ 1166ab4865bSGeert Uytterhoeven #define SPDCR_SPLLWORD (SPDCR_SPLW1 | SPDCR_SPLW0) 1176ab4865bSGeert Uytterhoeven #define SPDCR_SPLWORD SPDCR_SPLW1 1186ab4865bSGeert Uytterhoeven #define SPDCR_SPLBYTE SPDCR_SPLW0 1196ab4865bSGeert Uytterhoeven #define SPDCR_SPLW 0x20 /* Access Width Specification (SH) */ 120862d357fSGeert Uytterhoeven #define SPDCR_SPRDTD 0x10 /* Receive Transmit Data Select (SH) */ 1210b2182ddSShimoda, Yoshihiro #define SPDCR_SLSEL1 0x08 1220b2182ddSShimoda, Yoshihiro #define SPDCR_SLSEL0 0x04 123862d357fSGeert Uytterhoeven #define SPDCR_SLSEL_MASK 0x0c /* SSL1 Output Select (SH) */ 1240b2182ddSShimoda, Yoshihiro #define SPDCR_SPFC1 0x02 1250b2182ddSShimoda, Yoshihiro #define SPDCR_SPFC0 0x01 126862d357fSGeert Uytterhoeven #define SPDCR_SPFC_MASK 0x03 /* Frame Count Setting (1-4) (SH) */ 1270b2182ddSShimoda, Yoshihiro 1286ab4865bSGeert Uytterhoeven /* SPCKD - Clock Delay Register */ 1296ab4865bSGeert Uytterhoeven #define SPCKD_SCKDL_MASK 0x07 /* Clock Delay Setting (1-8) */ 1300b2182ddSShimoda, Yoshihiro 1316ab4865bSGeert Uytterhoeven /* SSLND - Slave Select Negation Delay Register */ 1326ab4865bSGeert Uytterhoeven #define SSLND_SLNDL_MASK 0x07 /* SSL Negation Delay Setting (1-8) */ 1330b2182ddSShimoda, Yoshihiro 1346ab4865bSGeert Uytterhoeven /* SPND - Next-Access Delay Register */ 1356ab4865bSGeert Uytterhoeven #define SPND_SPNDL_MASK 0x07 /* Next-Access Delay Setting (1-8) */ 1360b2182ddSShimoda, Yoshihiro 1376ab4865bSGeert Uytterhoeven /* SPCR2 - Control Register 2 */ 1386ab4865bSGeert Uytterhoeven #define SPCR2_PTE 0x08 /* Parity Self-Test Enable */ 1396ab4865bSGeert Uytterhoeven #define SPCR2_SPIE 0x04 /* Idle Interrupt Enable */ 1406ab4865bSGeert Uytterhoeven #define SPCR2_SPOE 0x02 /* Odd Parity Enable (vs. Even) */ 1416ab4865bSGeert Uytterhoeven #define SPCR2_SPPE 0x01 /* Parity Enable */ 1420b2182ddSShimoda, Yoshihiro 1436ab4865bSGeert Uytterhoeven /* SPCMDn - Command Registers */ 1446ab4865bSGeert Uytterhoeven #define SPCMD_SCKDEN 0x8000 /* Clock Delay Setting Enable */ 1456ab4865bSGeert Uytterhoeven #define SPCMD_SLNDEN 0x4000 /* SSL Negation Delay Setting Enable */ 1466ab4865bSGeert Uytterhoeven #define SPCMD_SPNDEN 0x2000 /* Next-Access Delay Enable */ 1476ab4865bSGeert Uytterhoeven #define SPCMD_LSBF 0x1000 /* LSB First */ 1486ab4865bSGeert Uytterhoeven #define SPCMD_SPB_MASK 0x0f00 /* Data Length Setting */ 1490b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK) 150880c6d11SGeert Uytterhoeven #define SPCMD_SPB_8BIT 0x0000 /* QSPI only */ 1515ce0ba88SHiep Cao Minh #define SPCMD_SPB_16BIT 0x0100 1520b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_20BIT 0x0000 1530b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_24BIT 0x0100 1540b2182ddSShimoda, Yoshihiro #define SPCMD_SPB_32BIT 0x0200 1556ab4865bSGeert Uytterhoeven #define SPCMD_SSLKP 0x0080 /* SSL Signal Level Keeping */ 156fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_MASK 0x0060 /* SPI Operating Mode (QSPI only) */ 157fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD1 0x0040 158fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD0 0x0020 159fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_SINGLE 0 160fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_DUAL SPCMD_SPIMOD0 161fbe5072bSGeert Uytterhoeven #define SPCMD_SPIMOD_QUAD SPCMD_SPIMOD1 162fbe5072bSGeert Uytterhoeven #define SPCMD_SPRW 0x0010 /* SPI Read/Write Access (Dual/Quad) */ 1639815ed87SGeert Uytterhoeven #define SPCMD_SSLA(i) ((i) << 4) /* SSL Assert Signal Setting */ 1646ab4865bSGeert Uytterhoeven #define SPCMD_BRDV_MASK 0x000c /* Bit Rate Division Setting */ 1658dd71698SGeert Uytterhoeven #define SPCMD_BRDV(brdv) ((brdv) << 2) 1666ab4865bSGeert Uytterhoeven #define SPCMD_CPOL 0x0002 /* Clock Polarity Setting */ 1676ab4865bSGeert Uytterhoeven #define SPCMD_CPHA 0x0001 /* Clock Phase Setting */ 1680b2182ddSShimoda, Yoshihiro 1696ab4865bSGeert Uytterhoeven /* SPBFCR - Buffer Control Register */ 170862d357fSGeert Uytterhoeven #define SPBFCR_TXRST 0x80 /* Transmit Buffer Data Reset */ 171862d357fSGeert Uytterhoeven #define SPBFCR_RXRST 0x40 /* Receive Buffer Data Reset */ 1726ab4865bSGeert Uytterhoeven #define SPBFCR_TXTRG_MASK 0x30 /* Transmit Buffer Data Triggering Number */ 1736ab4865bSGeert Uytterhoeven #define SPBFCR_RXTRG_MASK 0x07 /* Receive Buffer Data Triggering Number */ 1744b6fe3edSHiep Cao Minh /* QSPI on R-Car Gen2 */ 1754b6fe3edSHiep Cao Minh #define SPBFCR_TXTRG_1B 0x00 /* 31 bytes (1 byte available) */ 1764b6fe3edSHiep Cao Minh #define SPBFCR_TXTRG_32B 0x30 /* 0 byte (32 bytes available) */ 1774b6fe3edSHiep Cao Minh #define SPBFCR_RXTRG_1B 0x00 /* 1 byte (31 bytes available) */ 1784b6fe3edSHiep Cao Minh #define SPBFCR_RXTRG_32B 0x07 /* 32 bytes (0 byte available) */ 1794b6fe3edSHiep Cao Minh 1804b6fe3edSHiep Cao Minh #define QSPI_BUFFER_SIZE 32u 1815ce0ba88SHiep Cao Minh 1820b2182ddSShimoda, Yoshihiro struct rspi_data { 1830b2182ddSShimoda, Yoshihiro void __iomem *addr; 184e0fe7005SGeert Uytterhoeven u32 speed_hz; 1859428a073SGeert Uytterhoeven struct spi_controller *ctlr; 186f3a14a3aSGeert Uytterhoeven struct platform_device *pdev; 1870b2182ddSShimoda, Yoshihiro wait_queue_head_t wait; 188f3a14a3aSGeert Uytterhoeven spinlock_t lock; /* Protects RMW-access to RSPI_SSLP */ 1890b2182ddSShimoda, Yoshihiro struct clk *clk; 190348e5153SGeert Uytterhoeven u16 spcmd; 19106a7a3cfSGeert Uytterhoeven u8 spsr; 19206a7a3cfSGeert Uytterhoeven u8 sppcr; 19393722206SGeert Uytterhoeven int rx_irq, tx_irq; 1945ce0ba88SHiep Cao Minh const struct spi_ops *ops; 195a3633fe7SShimoda, Yoshihiro 196a3633fe7SShimoda, Yoshihiro unsigned dma_callbacked:1; 19774da7686SGeert Uytterhoeven unsigned byte_access:1; 1980b2182ddSShimoda, Yoshihiro }; 1990b2182ddSShimoda, Yoshihiro 200baf588f4SGeert Uytterhoeven static void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset) 2010b2182ddSShimoda, Yoshihiro { 2020b2182ddSShimoda, Yoshihiro iowrite8(data, rspi->addr + offset); 2030b2182ddSShimoda, Yoshihiro } 2040b2182ddSShimoda, Yoshihiro 205baf588f4SGeert Uytterhoeven static void rspi_write16(const struct rspi_data *rspi, u16 data, u16 offset) 2060b2182ddSShimoda, Yoshihiro { 2070b2182ddSShimoda, Yoshihiro iowrite16(data, rspi->addr + offset); 2080b2182ddSShimoda, Yoshihiro } 2090b2182ddSShimoda, Yoshihiro 210baf588f4SGeert Uytterhoeven static void rspi_write32(const struct rspi_data *rspi, u32 data, u16 offset) 2115ce0ba88SHiep Cao Minh { 2125ce0ba88SHiep Cao Minh iowrite32(data, rspi->addr + offset); 2135ce0ba88SHiep Cao Minh } 2145ce0ba88SHiep Cao Minh 215baf588f4SGeert Uytterhoeven static u8 rspi_read8(const struct rspi_data *rspi, u16 offset) 2160b2182ddSShimoda, Yoshihiro { 2170b2182ddSShimoda, Yoshihiro return ioread8(rspi->addr + offset); 2180b2182ddSShimoda, Yoshihiro } 2190b2182ddSShimoda, Yoshihiro 220baf588f4SGeert Uytterhoeven static u16 rspi_read16(const struct rspi_data *rspi, u16 offset) 2210b2182ddSShimoda, Yoshihiro { 2220b2182ddSShimoda, Yoshihiro return ioread16(rspi->addr + offset); 2230b2182ddSShimoda, Yoshihiro } 2240b2182ddSShimoda, Yoshihiro 22574da7686SGeert Uytterhoeven static void rspi_write_data(const struct rspi_data *rspi, u16 data) 22674da7686SGeert Uytterhoeven { 22774da7686SGeert Uytterhoeven if (rspi->byte_access) 22874da7686SGeert Uytterhoeven rspi_write8(rspi, data, RSPI_SPDR); 22974da7686SGeert Uytterhoeven else /* 16 bit */ 23074da7686SGeert Uytterhoeven rspi_write16(rspi, data, RSPI_SPDR); 23174da7686SGeert Uytterhoeven } 23274da7686SGeert Uytterhoeven 23374da7686SGeert Uytterhoeven static u16 rspi_read_data(const struct rspi_data *rspi) 23474da7686SGeert Uytterhoeven { 23574da7686SGeert Uytterhoeven if (rspi->byte_access) 23674da7686SGeert Uytterhoeven return rspi_read8(rspi, RSPI_SPDR); 23774da7686SGeert Uytterhoeven else /* 16 bit */ 23874da7686SGeert Uytterhoeven return rspi_read16(rspi, RSPI_SPDR); 23974da7686SGeert Uytterhoeven } 24074da7686SGeert Uytterhoeven 2415ce0ba88SHiep Cao Minh /* optional functions */ 2425ce0ba88SHiep Cao Minh struct spi_ops { 24374da7686SGeert Uytterhoeven int (*set_config_register)(struct rspi_data *rspi, int access_size); 2449428a073SGeert Uytterhoeven int (*transfer_one)(struct spi_controller *ctlr, 2459428a073SGeert Uytterhoeven struct spi_device *spi, struct spi_transfer *xfer); 246cd982e6cSGeert Uytterhoeven u16 extra_mode_bits; 247c3197974SGeert Uytterhoeven u16 min_div; 248c3197974SGeert Uytterhoeven u16 max_div; 249b42e0359SGeert Uytterhoeven u16 flags; 2502f777ec9SGeert Uytterhoeven u16 fifo_size; 251144d8f97SGeert Uytterhoeven u8 num_hw_ss; 2525ce0ba88SHiep Cao Minh }; 2535ce0ba88SHiep Cao Minh 2544e71d926SGeert Uytterhoeven static void rspi_set_rate(struct rspi_data *rspi) 2554e71d926SGeert Uytterhoeven { 2564e71d926SGeert Uytterhoeven unsigned long clksrc; 2574e71d926SGeert Uytterhoeven int brdv = 0, spbr; 2584e71d926SGeert Uytterhoeven 2594e71d926SGeert Uytterhoeven clksrc = clk_get_rate(rspi->clk); 2604e71d926SGeert Uytterhoeven spbr = DIV_ROUND_UP(clksrc, 2 * rspi->speed_hz) - 1; 2614e71d926SGeert Uytterhoeven while (spbr > 255 && brdv < 3) { 2624e71d926SGeert Uytterhoeven brdv++; 2634e71d926SGeert Uytterhoeven spbr = DIV_ROUND_UP(spbr + 1, 2) - 1; 2644e71d926SGeert Uytterhoeven } 2654e71d926SGeert Uytterhoeven 2664e71d926SGeert Uytterhoeven rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); 2674e71d926SGeert Uytterhoeven rspi->spcmd |= SPCMD_BRDV(brdv); 268cb588254SGeert Uytterhoeven rspi->speed_hz = DIV_ROUND_UP(clksrc, (2U << brdv) * (spbr + 1)); 2694e71d926SGeert Uytterhoeven } 2704e71d926SGeert Uytterhoeven 2715ce0ba88SHiep Cao Minh /* 272862d357fSGeert Uytterhoeven * functions for RSPI on legacy SH 2735ce0ba88SHiep Cao Minh */ 27474da7686SGeert Uytterhoeven static int rspi_set_config_register(struct rspi_data *rspi, int access_size) 2750b2182ddSShimoda, Yoshihiro { 27606a7a3cfSGeert Uytterhoeven /* Sets output mode, MOSI signal, and (optionally) loopback */ 27706a7a3cfSGeert Uytterhoeven rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); 2780b2182ddSShimoda, Yoshihiro 2795ce0ba88SHiep Cao Minh /* Sets transfer bit rate */ 2804e71d926SGeert Uytterhoeven rspi_set_rate(rspi); 2815ce0ba88SHiep Cao Minh 28274da7686SGeert Uytterhoeven /* Disable dummy transmission, set 16-bit word access, 1 frame */ 28374da7686SGeert Uytterhoeven rspi_write8(rspi, 0, RSPI_SPDCR); 28474da7686SGeert Uytterhoeven rspi->byte_access = 0; 2855ce0ba88SHiep Cao Minh 2865ce0ba88SHiep Cao Minh /* Sets RSPCK, SSL, next-access delay value */ 2875ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, RSPI_SPCKD); 2885ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, RSPI_SSLND); 2895ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, RSPI_SPND); 2905ce0ba88SHiep Cao Minh 2915ce0ba88SHiep Cao Minh /* Sets parity, interrupt mask */ 2925ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, RSPI_SPCR2); 2935ce0ba88SHiep Cao Minh 29426843bb1SGeert Uytterhoeven /* Resets sequencer */ 29526843bb1SGeert Uytterhoeven rspi_write8(rspi, 0, RSPI_SPSCR); 296880c6d11SGeert Uytterhoeven rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size); 297880c6d11SGeert Uytterhoeven rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 2985ce0ba88SHiep Cao Minh 2995ce0ba88SHiep Cao Minh /* Sets RSPI mode */ 3005ce0ba88SHiep Cao Minh rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); 3015ce0ba88SHiep Cao Minh 3025ce0ba88SHiep Cao Minh return 0; 3030b2182ddSShimoda, Yoshihiro } 3040b2182ddSShimoda, Yoshihiro 3055ce0ba88SHiep Cao Minh /* 306862d357fSGeert Uytterhoeven * functions for RSPI on RZ 307862d357fSGeert Uytterhoeven */ 308862d357fSGeert Uytterhoeven static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size) 309862d357fSGeert Uytterhoeven { 31006a7a3cfSGeert Uytterhoeven /* Sets output mode, MOSI signal, and (optionally) loopback */ 31106a7a3cfSGeert Uytterhoeven rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); 312862d357fSGeert Uytterhoeven 313862d357fSGeert Uytterhoeven /* Sets transfer bit rate */ 3144e71d926SGeert Uytterhoeven rspi_set_rate(rspi); 315862d357fSGeert Uytterhoeven 316862d357fSGeert Uytterhoeven /* Disable dummy transmission, set byte access */ 317862d357fSGeert Uytterhoeven rspi_write8(rspi, SPDCR_SPLBYTE, RSPI_SPDCR); 318862d357fSGeert Uytterhoeven rspi->byte_access = 1; 319862d357fSGeert Uytterhoeven 320862d357fSGeert Uytterhoeven /* Sets RSPCK, SSL, next-access delay value */ 321862d357fSGeert Uytterhoeven rspi_write8(rspi, 0x00, RSPI_SPCKD); 322862d357fSGeert Uytterhoeven rspi_write8(rspi, 0x00, RSPI_SSLND); 323862d357fSGeert Uytterhoeven rspi_write8(rspi, 0x00, RSPI_SPND); 324862d357fSGeert Uytterhoeven 32526843bb1SGeert Uytterhoeven /* Resets sequencer */ 32626843bb1SGeert Uytterhoeven rspi_write8(rspi, 0, RSPI_SPSCR); 327862d357fSGeert Uytterhoeven rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size); 328862d357fSGeert Uytterhoeven rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 329862d357fSGeert Uytterhoeven 330862d357fSGeert Uytterhoeven /* Sets RSPI mode */ 331862d357fSGeert Uytterhoeven rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); 332862d357fSGeert Uytterhoeven 333862d357fSGeert Uytterhoeven return 0; 334862d357fSGeert Uytterhoeven } 335862d357fSGeert Uytterhoeven 336862d357fSGeert Uytterhoeven /* 3375ce0ba88SHiep Cao Minh * functions for QSPI 3385ce0ba88SHiep Cao Minh */ 33974da7686SGeert Uytterhoeven static int qspi_set_config_register(struct rspi_data *rspi, int access_size) 3405ce0ba88SHiep Cao Minh { 3416a195f24SGeert Uytterhoeven unsigned long clksrc; 3426a195f24SGeert Uytterhoeven int brdv = 0, spbr; 3435ce0ba88SHiep Cao Minh 34406a7a3cfSGeert Uytterhoeven /* Sets output mode, MOSI signal, and (optionally) loopback */ 34506a7a3cfSGeert Uytterhoeven rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); 3465ce0ba88SHiep Cao Minh 3475ce0ba88SHiep Cao Minh /* Sets transfer bit rate */ 3486a195f24SGeert Uytterhoeven clksrc = clk_get_rate(rspi->clk); 3496a195f24SGeert Uytterhoeven if (rspi->speed_hz >= clksrc) { 3506a195f24SGeert Uytterhoeven spbr = 0; 351cb588254SGeert Uytterhoeven rspi->speed_hz = clksrc; 3526a195f24SGeert Uytterhoeven } else { 3536a195f24SGeert Uytterhoeven spbr = DIV_ROUND_UP(clksrc, 2 * rspi->speed_hz); 3546a195f24SGeert Uytterhoeven while (spbr > 255 && brdv < 3) { 3556a195f24SGeert Uytterhoeven brdv++; 3566a195f24SGeert Uytterhoeven spbr = DIV_ROUND_UP(spbr, 2); 3576a195f24SGeert Uytterhoeven } 3586a195f24SGeert Uytterhoeven spbr = clamp(spbr, 0, 255); 359cb588254SGeert Uytterhoeven rspi->speed_hz = DIV_ROUND_UP(clksrc, (2U << brdv) * spbr); 3606a195f24SGeert Uytterhoeven } 3616a195f24SGeert Uytterhoeven rspi_write8(rspi, spbr, RSPI_SPBR); 3626a195f24SGeert Uytterhoeven rspi->spcmd |= SPCMD_BRDV(brdv); 3635ce0ba88SHiep Cao Minh 36474da7686SGeert Uytterhoeven /* Disable dummy transmission, set byte access */ 36574da7686SGeert Uytterhoeven rspi_write8(rspi, 0, RSPI_SPDCR); 36674da7686SGeert Uytterhoeven rspi->byte_access = 1; 3675ce0ba88SHiep Cao Minh 3685ce0ba88SHiep Cao Minh /* Sets RSPCK, SSL, next-access delay value */ 3695ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, RSPI_SPCKD); 3705ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, RSPI_SSLND); 3715ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, RSPI_SPND); 3725ce0ba88SHiep Cao Minh 3735ce0ba88SHiep Cao Minh /* Data Length Setting */ 3745ce0ba88SHiep Cao Minh if (access_size == 8) 375880c6d11SGeert Uytterhoeven rspi->spcmd |= SPCMD_SPB_8BIT; 3765ce0ba88SHiep Cao Minh else if (access_size == 16) 377880c6d11SGeert Uytterhoeven rspi->spcmd |= SPCMD_SPB_16BIT; 3788e1c8096SLaurent Pinchart else 379880c6d11SGeert Uytterhoeven rspi->spcmd |= SPCMD_SPB_32BIT; 3805ce0ba88SHiep Cao Minh 381880c6d11SGeert Uytterhoeven rspi->spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SPNDEN; 3825ce0ba88SHiep Cao Minh 3835ce0ba88SHiep Cao Minh /* Resets transfer data length */ 3845ce0ba88SHiep Cao Minh rspi_write32(rspi, 0, QSPI_SPBMUL0); 3855ce0ba88SHiep Cao Minh 3865ce0ba88SHiep Cao Minh /* Resets transmit and receive buffer */ 3875ce0ba88SHiep Cao Minh rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR); 3885ce0ba88SHiep Cao Minh /* Sets buffer to allow normal operation */ 3895ce0ba88SHiep Cao Minh rspi_write8(rspi, 0x00, QSPI_SPBFCR); 3905ce0ba88SHiep Cao Minh 39126843bb1SGeert Uytterhoeven /* Resets sequencer */ 39226843bb1SGeert Uytterhoeven rspi_write8(rspi, 0, RSPI_SPSCR); 393880c6d11SGeert Uytterhoeven rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 3945ce0ba88SHiep Cao Minh 395b458a349SGeert Uytterhoeven /* Sets RSPI mode */ 396b458a349SGeert Uytterhoeven rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); 3975ce0ba88SHiep Cao Minh 3985ce0ba88SHiep Cao Minh return 0; 3995ce0ba88SHiep Cao Minh } 4005ce0ba88SHiep Cao Minh 4014b6fe3edSHiep Cao Minh static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg) 4024b6fe3edSHiep Cao Minh { 4034b6fe3edSHiep Cao Minh u8 data; 4044b6fe3edSHiep Cao Minh 4054b6fe3edSHiep Cao Minh data = rspi_read8(rspi, reg); 4064b6fe3edSHiep Cao Minh data &= ~mask; 4074b6fe3edSHiep Cao Minh data |= (val & mask); 4084b6fe3edSHiep Cao Minh rspi_write8(rspi, data, reg); 4094b6fe3edSHiep Cao Minh } 4104b6fe3edSHiep Cao Minh 411cb76b1caSGeert Uytterhoeven static unsigned int qspi_set_send_trigger(struct rspi_data *rspi, 412cb76b1caSGeert Uytterhoeven unsigned int len) 4134b6fe3edSHiep Cao Minh { 4144b6fe3edSHiep Cao Minh unsigned int n; 4154b6fe3edSHiep Cao Minh 4164b6fe3edSHiep Cao Minh n = min(len, QSPI_BUFFER_SIZE); 4174b6fe3edSHiep Cao Minh 4184b6fe3edSHiep Cao Minh if (len >= QSPI_BUFFER_SIZE) { 4194b6fe3edSHiep Cao Minh /* sets triggering number to 32 bytes */ 4204b6fe3edSHiep Cao Minh qspi_update(rspi, SPBFCR_TXTRG_MASK, 4214b6fe3edSHiep Cao Minh SPBFCR_TXTRG_32B, QSPI_SPBFCR); 4224b6fe3edSHiep Cao Minh } else { 4234b6fe3edSHiep Cao Minh /* sets triggering number to 1 byte */ 4244b6fe3edSHiep Cao Minh qspi_update(rspi, SPBFCR_TXTRG_MASK, 4254b6fe3edSHiep Cao Minh SPBFCR_TXTRG_1B, QSPI_SPBFCR); 4264b6fe3edSHiep Cao Minh } 4274b6fe3edSHiep Cao Minh 4284b6fe3edSHiep Cao Minh return n; 4294b6fe3edSHiep Cao Minh } 4304b6fe3edSHiep Cao Minh 4313be09becSHiep Cao Minh static int qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len) 4324b6fe3edSHiep Cao Minh { 4334b6fe3edSHiep Cao Minh unsigned int n; 4344b6fe3edSHiep Cao Minh 4354b6fe3edSHiep Cao Minh n = min(len, QSPI_BUFFER_SIZE); 4364b6fe3edSHiep Cao Minh 4374b6fe3edSHiep Cao Minh if (len >= QSPI_BUFFER_SIZE) { 4384b6fe3edSHiep Cao Minh /* sets triggering number to 32 bytes */ 4394b6fe3edSHiep Cao Minh qspi_update(rspi, SPBFCR_RXTRG_MASK, 4404b6fe3edSHiep Cao Minh SPBFCR_RXTRG_32B, QSPI_SPBFCR); 4414b6fe3edSHiep Cao Minh } else { 4424b6fe3edSHiep Cao Minh /* sets triggering number to 1 byte */ 4434b6fe3edSHiep Cao Minh qspi_update(rspi, SPBFCR_RXTRG_MASK, 4444b6fe3edSHiep Cao Minh SPBFCR_RXTRG_1B, QSPI_SPBFCR); 4454b6fe3edSHiep Cao Minh } 4463be09becSHiep Cao Minh return n; 4474b6fe3edSHiep Cao Minh } 4484b6fe3edSHiep Cao Minh 449baf588f4SGeert Uytterhoeven static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable) 4500b2182ddSShimoda, Yoshihiro { 4510b2182ddSShimoda, Yoshihiro rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR); 4520b2182ddSShimoda, Yoshihiro } 4530b2182ddSShimoda, Yoshihiro 454baf588f4SGeert Uytterhoeven static void rspi_disable_irq(const struct rspi_data *rspi, u8 disable) 4550b2182ddSShimoda, Yoshihiro { 4560b2182ddSShimoda, Yoshihiro rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~disable, RSPI_SPCR); 4570b2182ddSShimoda, Yoshihiro } 4580b2182ddSShimoda, Yoshihiro 4590b2182ddSShimoda, Yoshihiro static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask, 4600b2182ddSShimoda, Yoshihiro u8 enable_bit) 4610b2182ddSShimoda, Yoshihiro { 4620b2182ddSShimoda, Yoshihiro int ret; 4630b2182ddSShimoda, Yoshihiro 4640b2182ddSShimoda, Yoshihiro rspi->spsr = rspi_read8(rspi, RSPI_SPSR); 4655dd1ad23SGeert Uytterhoeven if (rspi->spsr & wait_mask) 4665dd1ad23SGeert Uytterhoeven return 0; 4675dd1ad23SGeert Uytterhoeven 4680b2182ddSShimoda, Yoshihiro rspi_enable_irq(rspi, enable_bit); 4690b2182ddSShimoda, Yoshihiro ret = wait_event_timeout(rspi->wait, rspi->spsr & wait_mask, HZ); 4700b2182ddSShimoda, Yoshihiro if (ret == 0 && !(rspi->spsr & wait_mask)) 4710b2182ddSShimoda, Yoshihiro return -ETIMEDOUT; 4720b2182ddSShimoda, Yoshihiro 4730b2182ddSShimoda, Yoshihiro return 0; 4740b2182ddSShimoda, Yoshihiro } 4750b2182ddSShimoda, Yoshihiro 4765f684c34SGeert Uytterhoeven static inline int rspi_wait_for_tx_empty(struct rspi_data *rspi) 4775f684c34SGeert Uytterhoeven { 4785f684c34SGeert Uytterhoeven return rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); 4795f684c34SGeert Uytterhoeven } 4805f684c34SGeert Uytterhoeven 4815f684c34SGeert Uytterhoeven static inline int rspi_wait_for_rx_full(struct rspi_data *rspi) 4825f684c34SGeert Uytterhoeven { 4835f684c34SGeert Uytterhoeven return rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE); 4845f684c34SGeert Uytterhoeven } 4855f684c34SGeert Uytterhoeven 48635301c99SGeert Uytterhoeven static int rspi_data_out(struct rspi_data *rspi, u8 data) 48735301c99SGeert Uytterhoeven { 4885f684c34SGeert Uytterhoeven int error = rspi_wait_for_tx_empty(rspi); 4895f684c34SGeert Uytterhoeven if (error < 0) { 4909428a073SGeert Uytterhoeven dev_err(&rspi->ctlr->dev, "transmit timeout\n"); 4915f684c34SGeert Uytterhoeven return error; 49235301c99SGeert Uytterhoeven } 49335301c99SGeert Uytterhoeven rspi_write_data(rspi, data); 49435301c99SGeert Uytterhoeven return 0; 49535301c99SGeert Uytterhoeven } 49635301c99SGeert Uytterhoeven 49735301c99SGeert Uytterhoeven static int rspi_data_in(struct rspi_data *rspi) 49835301c99SGeert Uytterhoeven { 4995f684c34SGeert Uytterhoeven int error; 50035301c99SGeert Uytterhoeven u8 data; 50135301c99SGeert Uytterhoeven 5025f684c34SGeert Uytterhoeven error = rspi_wait_for_rx_full(rspi); 5035f684c34SGeert Uytterhoeven if (error < 0) { 5049428a073SGeert Uytterhoeven dev_err(&rspi->ctlr->dev, "receive timeout\n"); 5055f684c34SGeert Uytterhoeven return error; 50635301c99SGeert Uytterhoeven } 50735301c99SGeert Uytterhoeven data = rspi_read_data(rspi); 50835301c99SGeert Uytterhoeven return data; 50935301c99SGeert Uytterhoeven } 51035301c99SGeert Uytterhoeven 5116837b8e9SGeert Uytterhoeven static int rspi_pio_transfer(struct rspi_data *rspi, const u8 *tx, u8 *rx, 5126837b8e9SGeert Uytterhoeven unsigned int n) 51335301c99SGeert Uytterhoeven { 5146837b8e9SGeert Uytterhoeven while (n-- > 0) { 5156837b8e9SGeert Uytterhoeven if (tx) { 5166837b8e9SGeert Uytterhoeven int ret = rspi_data_out(rspi, *tx++); 51735301c99SGeert Uytterhoeven if (ret < 0) 51835301c99SGeert Uytterhoeven return ret; 5196837b8e9SGeert Uytterhoeven } 5206837b8e9SGeert Uytterhoeven if (rx) { 5216837b8e9SGeert Uytterhoeven int ret = rspi_data_in(rspi); 5226837b8e9SGeert Uytterhoeven if (ret < 0) 5236837b8e9SGeert Uytterhoeven return ret; 5246837b8e9SGeert Uytterhoeven *rx++ = ret; 5256837b8e9SGeert Uytterhoeven } 5266837b8e9SGeert Uytterhoeven } 52735301c99SGeert Uytterhoeven 5286837b8e9SGeert Uytterhoeven return 0; 52935301c99SGeert Uytterhoeven } 53035301c99SGeert Uytterhoeven 531a3633fe7SShimoda, Yoshihiro static void rspi_dma_complete(void *arg) 5320b2182ddSShimoda, Yoshihiro { 533a3633fe7SShimoda, Yoshihiro struct rspi_data *rspi = arg; 534a3633fe7SShimoda, Yoshihiro 535a3633fe7SShimoda, Yoshihiro rspi->dma_callbacked = 1; 536a3633fe7SShimoda, Yoshihiro wake_up_interruptible(&rspi->wait); 537a3633fe7SShimoda, Yoshihiro } 538a3633fe7SShimoda, Yoshihiro 539c52fb6d6SGeert Uytterhoeven static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, 540c52fb6d6SGeert Uytterhoeven struct sg_table *rx) 541a3633fe7SShimoda, Yoshihiro { 542c52fb6d6SGeert Uytterhoeven struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL; 543c52fb6d6SGeert Uytterhoeven u8 irq_mask = 0; 544c52fb6d6SGeert Uytterhoeven unsigned int other_irq = 0; 545c52fb6d6SGeert Uytterhoeven dma_cookie_t cookie; 5462f777ec9SGeert Uytterhoeven int ret; 547a3633fe7SShimoda, Yoshihiro 5483819bc87SGeert Uytterhoeven /* First prepare and submit the DMA request(s), as this may fail */ 549c52fb6d6SGeert Uytterhoeven if (rx) { 5509428a073SGeert Uytterhoeven desc_rx = dmaengine_prep_slave_sg(rspi->ctlr->dma_rx, rx->sgl, 5519428a073SGeert Uytterhoeven rx->nents, DMA_DEV_TO_MEM, 552c52fb6d6SGeert Uytterhoeven DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 5533819bc87SGeert Uytterhoeven if (!desc_rx) { 5543819bc87SGeert Uytterhoeven ret = -EAGAIN; 5553819bc87SGeert Uytterhoeven goto no_dma_rx; 5563819bc87SGeert Uytterhoeven } 5573819bc87SGeert Uytterhoeven 5583819bc87SGeert Uytterhoeven desc_rx->callback = rspi_dma_complete; 5593819bc87SGeert Uytterhoeven desc_rx->callback_param = rspi; 5603819bc87SGeert Uytterhoeven cookie = dmaengine_submit(desc_rx); 5613819bc87SGeert Uytterhoeven if (dma_submit_error(cookie)) { 5623819bc87SGeert Uytterhoeven ret = cookie; 5633819bc87SGeert Uytterhoeven goto no_dma_rx; 5643819bc87SGeert Uytterhoeven } 565c52fb6d6SGeert Uytterhoeven 566c52fb6d6SGeert Uytterhoeven irq_mask |= SPCR_SPRIE; 567c52fb6d6SGeert Uytterhoeven } 568c52fb6d6SGeert Uytterhoeven 5693819bc87SGeert Uytterhoeven if (tx) { 5709428a073SGeert Uytterhoeven desc_tx = dmaengine_prep_slave_sg(rspi->ctlr->dma_tx, tx->sgl, 5719428a073SGeert Uytterhoeven tx->nents, DMA_MEM_TO_DEV, 5723819bc87SGeert Uytterhoeven DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 5733819bc87SGeert Uytterhoeven if (!desc_tx) { 5743819bc87SGeert Uytterhoeven ret = -EAGAIN; 5753819bc87SGeert Uytterhoeven goto no_dma_tx; 5763819bc87SGeert Uytterhoeven } 5773819bc87SGeert Uytterhoeven 5783819bc87SGeert Uytterhoeven if (rx) { 5793819bc87SGeert Uytterhoeven /* No callback */ 5803819bc87SGeert Uytterhoeven desc_tx->callback = NULL; 5813819bc87SGeert Uytterhoeven } else { 5823819bc87SGeert Uytterhoeven desc_tx->callback = rspi_dma_complete; 5833819bc87SGeert Uytterhoeven desc_tx->callback_param = rspi; 5843819bc87SGeert Uytterhoeven } 5853819bc87SGeert Uytterhoeven cookie = dmaengine_submit(desc_tx); 5863819bc87SGeert Uytterhoeven if (dma_submit_error(cookie)) { 5873819bc87SGeert Uytterhoeven ret = cookie; 5883819bc87SGeert Uytterhoeven goto no_dma_tx; 5893819bc87SGeert Uytterhoeven } 5903819bc87SGeert Uytterhoeven 5913819bc87SGeert Uytterhoeven irq_mask |= SPCR_SPTIE; 5923819bc87SGeert Uytterhoeven } 5933819bc87SGeert Uytterhoeven 594a3633fe7SShimoda, Yoshihiro /* 595c52fb6d6SGeert Uytterhoeven * DMAC needs SPxIE, but if SPxIE is set, the IRQ routine will be 596a3633fe7SShimoda, Yoshihiro * called. So, this driver disables the IRQ while DMA transfer. 597a3633fe7SShimoda, Yoshihiro */ 598c52fb6d6SGeert Uytterhoeven if (tx) 599c52fb6d6SGeert Uytterhoeven disable_irq(other_irq = rspi->tx_irq); 600c52fb6d6SGeert Uytterhoeven if (rx && rspi->rx_irq != other_irq) 601c52fb6d6SGeert Uytterhoeven disable_irq(rspi->rx_irq); 602a3633fe7SShimoda, Yoshihiro 603c52fb6d6SGeert Uytterhoeven rspi_enable_irq(rspi, irq_mask); 604a3633fe7SShimoda, Yoshihiro rspi->dma_callbacked = 0; 605a3633fe7SShimoda, Yoshihiro 6063819bc87SGeert Uytterhoeven /* Now start DMA */ 6073819bc87SGeert Uytterhoeven if (rx) 6089428a073SGeert Uytterhoeven dma_async_issue_pending(rspi->ctlr->dma_rx); 6093819bc87SGeert Uytterhoeven if (tx) 6109428a073SGeert Uytterhoeven dma_async_issue_pending(rspi->ctlr->dma_tx); 611a3633fe7SShimoda, Yoshihiro 612a3633fe7SShimoda, Yoshihiro ret = wait_event_interruptible_timeout(rspi->wait, 613a3633fe7SShimoda, Yoshihiro rspi->dma_callbacked, HZ); 6148dbbaa47SGeert Uytterhoeven if (ret > 0 && rspi->dma_callbacked) { 615a3633fe7SShimoda, Yoshihiro ret = 0; 6168dbbaa47SGeert Uytterhoeven } else { 6178dbbaa47SGeert Uytterhoeven if (!ret) { 6189428a073SGeert Uytterhoeven dev_err(&rspi->ctlr->dev, "DMA timeout\n"); 619a3633fe7SShimoda, Yoshihiro ret = -ETIMEDOUT; 6208dbbaa47SGeert Uytterhoeven } 6213819bc87SGeert Uytterhoeven if (tx) 62229176eddSWolfram Sang dmaengine_terminate_sync(rspi->ctlr->dma_tx); 6233819bc87SGeert Uytterhoeven if (rx) 62429176eddSWolfram Sang dmaengine_terminate_sync(rspi->ctlr->dma_rx); 6253819bc87SGeert Uytterhoeven } 626a3633fe7SShimoda, Yoshihiro 627c52fb6d6SGeert Uytterhoeven rspi_disable_irq(rspi, irq_mask); 628c52fb6d6SGeert Uytterhoeven 629c52fb6d6SGeert Uytterhoeven if (tx) 63093722206SGeert Uytterhoeven enable_irq(rspi->tx_irq); 631c52fb6d6SGeert Uytterhoeven if (rx && rspi->rx_irq != other_irq) 632c52fb6d6SGeert Uytterhoeven enable_irq(rspi->rx_irq); 633c52fb6d6SGeert Uytterhoeven 634a3633fe7SShimoda, Yoshihiro return ret; 63585912a88SGeert Uytterhoeven 6363819bc87SGeert Uytterhoeven no_dma_tx: 6373819bc87SGeert Uytterhoeven if (rx) 63829176eddSWolfram Sang dmaengine_terminate_sync(rspi->ctlr->dma_rx); 6393819bc87SGeert Uytterhoeven no_dma_rx: 6403819bc87SGeert Uytterhoeven if (ret == -EAGAIN) { 6411bec84ddSGeert Uytterhoeven dev_warn_once(&rspi->ctlr->dev, 6421bec84ddSGeert Uytterhoeven "DMA not available, falling back to PIO\n"); 6433819bc87SGeert Uytterhoeven } 6443819bc87SGeert Uytterhoeven return ret; 645a3633fe7SShimoda, Yoshihiro } 646a3633fe7SShimoda, Yoshihiro 647baf588f4SGeert Uytterhoeven static void rspi_receive_init(const struct rspi_data *rspi) 648a3633fe7SShimoda, Yoshihiro { 64997b95c11SGeert Uytterhoeven u8 spsr; 6500b2182ddSShimoda, Yoshihiro 6510b2182ddSShimoda, Yoshihiro spsr = rspi_read8(rspi, RSPI_SPSR); 6520b2182ddSShimoda, Yoshihiro if (spsr & SPSR_SPRF) 65374da7686SGeert Uytterhoeven rspi_read_data(rspi); /* dummy read */ 6540b2182ddSShimoda, Yoshihiro if (spsr & SPSR_OVRF) 6550b2182ddSShimoda, Yoshihiro rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF, 656df900e67SGeert Uytterhoeven RSPI_SPSR); 657a3633fe7SShimoda, Yoshihiro } 658a3633fe7SShimoda, Yoshihiro 659862d357fSGeert Uytterhoeven static void rspi_rz_receive_init(const struct rspi_data *rspi) 660862d357fSGeert Uytterhoeven { 661862d357fSGeert Uytterhoeven rspi_receive_init(rspi); 662862d357fSGeert Uytterhoeven rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, RSPI_SPBFCR); 663862d357fSGeert Uytterhoeven rspi_write8(rspi, 0, RSPI_SPBFCR); 664862d357fSGeert Uytterhoeven } 665862d357fSGeert Uytterhoeven 666baf588f4SGeert Uytterhoeven static void qspi_receive_init(const struct rspi_data *rspi) 667cb52c673SHiep Cao Minh { 66897b95c11SGeert Uytterhoeven u8 spsr; 669cb52c673SHiep Cao Minh 670cb52c673SHiep Cao Minh spsr = rspi_read8(rspi, RSPI_SPSR); 671cb52c673SHiep Cao Minh if (spsr & SPSR_SPRF) 67274da7686SGeert Uytterhoeven rspi_read_data(rspi); /* dummy read */ 673cb52c673SHiep Cao Minh rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR); 674340a15e6SGeert Uytterhoeven rspi_write8(rspi, 0, QSPI_SPBFCR); 675cb52c673SHiep Cao Minh } 676cb52c673SHiep Cao Minh 6772f777ec9SGeert Uytterhoeven static bool __rspi_can_dma(const struct rspi_data *rspi, 6782f777ec9SGeert Uytterhoeven const struct spi_transfer *xfer) 679a3633fe7SShimoda, Yoshihiro { 6802f777ec9SGeert Uytterhoeven return xfer->len > rspi->ops->fifo_size; 6812f777ec9SGeert Uytterhoeven } 682a3633fe7SShimoda, Yoshihiro 6839428a073SGeert Uytterhoeven static bool rspi_can_dma(struct spi_controller *ctlr, struct spi_device *spi, 6842f777ec9SGeert Uytterhoeven struct spi_transfer *xfer) 6852f777ec9SGeert Uytterhoeven { 6869428a073SGeert Uytterhoeven struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 6872f777ec9SGeert Uytterhoeven 6882f777ec9SGeert Uytterhoeven return __rspi_can_dma(rspi, xfer); 689a3633fe7SShimoda, Yoshihiro } 690a3633fe7SShimoda, Yoshihiro 6914b6fe3edSHiep Cao Minh static int rspi_dma_check_then_transfer(struct rspi_data *rspi, 6924b6fe3edSHiep Cao Minh struct spi_transfer *xfer) 6934b6fe3edSHiep Cao Minh { 6949428a073SGeert Uytterhoeven if (!rspi->ctlr->can_dma || !__rspi_can_dma(rspi, xfer)) 6954b6fe3edSHiep Cao Minh return -EAGAIN; 6966310372dSHiep Cao Minh 6976310372dSHiep Cao Minh /* rx_buf can be NULL on RSPI on SH in TX-only Mode */ 6986310372dSHiep Cao Minh return rspi_dma_transfer(rspi, &xfer->tx_sg, 6996310372dSHiep Cao Minh xfer->rx_buf ? &xfer->rx_sg : NULL); 7004b6fe3edSHiep Cao Minh } 7014b6fe3edSHiep Cao Minh 7028b983e90SGeert Uytterhoeven static int rspi_common_transfer(struct rspi_data *rspi, 7038b983e90SGeert Uytterhoeven struct spi_transfer *xfer) 7048b983e90SGeert Uytterhoeven { 7058b983e90SGeert Uytterhoeven int ret; 7068b983e90SGeert Uytterhoeven 707cb588254SGeert Uytterhoeven xfer->effective_speed_hz = rspi->speed_hz; 708cb588254SGeert Uytterhoeven 7094b6fe3edSHiep Cao Minh ret = rspi_dma_check_then_transfer(rspi, xfer); 71085912a88SGeert Uytterhoeven if (ret != -EAGAIN) 71185912a88SGeert Uytterhoeven return ret; 7128b983e90SGeert Uytterhoeven 7138b983e90SGeert Uytterhoeven ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len); 7148b983e90SGeert Uytterhoeven if (ret < 0) 7158b983e90SGeert Uytterhoeven return ret; 7168b983e90SGeert Uytterhoeven 7178b983e90SGeert Uytterhoeven /* Wait for the last transmission */ 7188b983e90SGeert Uytterhoeven rspi_wait_for_tx_empty(rspi); 7198b983e90SGeert Uytterhoeven 7208b983e90SGeert Uytterhoeven return 0; 7218b983e90SGeert Uytterhoeven } 7228b983e90SGeert Uytterhoeven 7239428a073SGeert Uytterhoeven static int rspi_transfer_one(struct spi_controller *ctlr, 7249428a073SGeert Uytterhoeven struct spi_device *spi, struct spi_transfer *xfer) 7258449fd76SGeert Uytterhoeven { 7269428a073SGeert Uytterhoeven struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 727b42e0359SGeert Uytterhoeven u8 spcr; 7288449fd76SGeert Uytterhoeven 7298449fd76SGeert Uytterhoeven spcr = rspi_read8(rspi, RSPI_SPCR); 7306837b8e9SGeert Uytterhoeven if (xfer->rx_buf) { 73132c64261SGeert Uytterhoeven rspi_receive_init(rspi); 7328449fd76SGeert Uytterhoeven spcr &= ~SPCR_TXMD; 73332c64261SGeert Uytterhoeven } else { 7348449fd76SGeert Uytterhoeven spcr |= SPCR_TXMD; 73532c64261SGeert Uytterhoeven } 7368449fd76SGeert Uytterhoeven rspi_write8(rspi, spcr, RSPI_SPCR); 7378449fd76SGeert Uytterhoeven 7388b983e90SGeert Uytterhoeven return rspi_common_transfer(rspi, xfer); 7398449fd76SGeert Uytterhoeven } 7408449fd76SGeert Uytterhoeven 7419428a073SGeert Uytterhoeven static int rspi_rz_transfer_one(struct spi_controller *ctlr, 74203e627c5SGeert Uytterhoeven struct spi_device *spi, 743862d357fSGeert Uytterhoeven struct spi_transfer *xfer) 744862d357fSGeert Uytterhoeven { 7459428a073SGeert Uytterhoeven struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 746862d357fSGeert Uytterhoeven 747862d357fSGeert Uytterhoeven rspi_rz_receive_init(rspi); 748862d357fSGeert Uytterhoeven 7498b983e90SGeert Uytterhoeven return rspi_common_transfer(rspi, xfer); 750862d357fSGeert Uytterhoeven } 751862d357fSGeert Uytterhoeven 752a91bbe7dSHiep Cao Minh static int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx, 7534b6fe3edSHiep Cao Minh u8 *rx, unsigned int len) 7544b6fe3edSHiep Cao Minh { 755cb76b1caSGeert Uytterhoeven unsigned int i, n; 756cb76b1caSGeert Uytterhoeven int ret; 7574b6fe3edSHiep Cao Minh 7584b6fe3edSHiep Cao Minh while (len > 0) { 7594b6fe3edSHiep Cao Minh n = qspi_set_send_trigger(rspi, len); 7604b6fe3edSHiep Cao Minh qspi_set_receive_trigger(rspi, len); 7615d4db691SGeert Uytterhoeven ret = rspi_wait_for_tx_empty(rspi); 7625d4db691SGeert Uytterhoeven if (ret < 0) { 7639428a073SGeert Uytterhoeven dev_err(&rspi->ctlr->dev, "transmit timeout\n"); 7645d4db691SGeert Uytterhoeven return ret; 7654b6fe3edSHiep Cao Minh } 7664b6fe3edSHiep Cao Minh for (i = 0; i < n; i++) 7674b6fe3edSHiep Cao Minh rspi_write_data(rspi, *tx++); 7684b6fe3edSHiep Cao Minh 7695d4db691SGeert Uytterhoeven ret = rspi_wait_for_rx_full(rspi); 7705d4db691SGeert Uytterhoeven if (ret < 0) { 7719428a073SGeert Uytterhoeven dev_err(&rspi->ctlr->dev, "receive timeout\n"); 7725d4db691SGeert Uytterhoeven return ret; 7734b6fe3edSHiep Cao Minh } 7744b6fe3edSHiep Cao Minh for (i = 0; i < n; i++) 7754b6fe3edSHiep Cao Minh *rx++ = rspi_read_data(rspi); 7767e95b166SHoan Nguyen An 7774b6fe3edSHiep Cao Minh len -= n; 7784b6fe3edSHiep Cao Minh } 7794b6fe3edSHiep Cao Minh 7804b6fe3edSHiep Cao Minh return 0; 7814b6fe3edSHiep Cao Minh } 7824b6fe3edSHiep Cao Minh 783340a15e6SGeert Uytterhoeven static int qspi_transfer_out_in(struct rspi_data *rspi, 784340a15e6SGeert Uytterhoeven struct spi_transfer *xfer) 785340a15e6SGeert Uytterhoeven { 7864b6fe3edSHiep Cao Minh int ret; 7874b6fe3edSHiep Cao Minh 788340a15e6SGeert Uytterhoeven qspi_receive_init(rspi); 789340a15e6SGeert Uytterhoeven 7904b6fe3edSHiep Cao Minh ret = rspi_dma_check_then_transfer(rspi, xfer); 7914b6fe3edSHiep Cao Minh if (ret != -EAGAIN) 7924b6fe3edSHiep Cao Minh return ret; 7934b6fe3edSHiep Cao Minh 794cc2e9328SHiep Cao Minh return qspi_trigger_transfer_out_in(rspi, xfer->tx_buf, 7954b6fe3edSHiep Cao Minh xfer->rx_buf, xfer->len); 796340a15e6SGeert Uytterhoeven } 797340a15e6SGeert Uytterhoeven 798880c6d11SGeert Uytterhoeven static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) 799880c6d11SGeert Uytterhoeven { 800db300838SArnd Bergmann const u8 *tx = xfer->tx_buf; 801db300838SArnd Bergmann unsigned int n = xfer->len; 802db300838SArnd Bergmann unsigned int i, len; 803880c6d11SGeert Uytterhoeven int ret; 804880c6d11SGeert Uytterhoeven 8059428a073SGeert Uytterhoeven if (rspi->ctlr->can_dma && __rspi_can_dma(rspi, xfer)) { 80685912a88SGeert Uytterhoeven ret = rspi_dma_transfer(rspi, &xfer->tx_sg, NULL); 80785912a88SGeert Uytterhoeven if (ret != -EAGAIN) 80885912a88SGeert Uytterhoeven return ret; 80985912a88SGeert Uytterhoeven } 8104f12b5e5SGeert Uytterhoeven 811db300838SArnd Bergmann while (n > 0) { 812db300838SArnd Bergmann len = qspi_set_send_trigger(rspi, n); 813db300838SArnd Bergmann ret = rspi_wait_for_tx_empty(rspi); 814db300838SArnd Bergmann if (ret < 0) { 8159428a073SGeert Uytterhoeven dev_err(&rspi->ctlr->dev, "transmit timeout\n"); 816db300838SArnd Bergmann return ret; 817db300838SArnd Bergmann } 818db300838SArnd Bergmann for (i = 0; i < len; i++) 819db300838SArnd Bergmann rspi_write_data(rspi, *tx++); 8207e95b166SHoan Nguyen An 821db300838SArnd Bergmann n -= len; 822db300838SArnd Bergmann } 823880c6d11SGeert Uytterhoeven 824880c6d11SGeert Uytterhoeven /* Wait for the last transmission */ 8255f684c34SGeert Uytterhoeven rspi_wait_for_tx_empty(rspi); 826880c6d11SGeert Uytterhoeven 827880c6d11SGeert Uytterhoeven return 0; 828880c6d11SGeert Uytterhoeven } 829880c6d11SGeert Uytterhoeven 830880c6d11SGeert Uytterhoeven static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) 831880c6d11SGeert Uytterhoeven { 832db300838SArnd Bergmann u8 *rx = xfer->rx_buf; 833db300838SArnd Bergmann unsigned int n = xfer->len; 834db300838SArnd Bergmann unsigned int i, len; 835db300838SArnd Bergmann int ret; 836db300838SArnd Bergmann 8379428a073SGeert Uytterhoeven if (rspi->ctlr->can_dma && __rspi_can_dma(rspi, xfer)) { 8381d734f59SLad Prabhakar ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg); 83985912a88SGeert Uytterhoeven if (ret != -EAGAIN) 84085912a88SGeert Uytterhoeven return ret; 84185912a88SGeert Uytterhoeven } 8424f12b5e5SGeert Uytterhoeven 843db300838SArnd Bergmann while (n > 0) { 844db300838SArnd Bergmann len = qspi_set_receive_trigger(rspi, n); 845db300838SArnd Bergmann ret = rspi_wait_for_rx_full(rspi); 846db300838SArnd Bergmann if (ret < 0) { 8479428a073SGeert Uytterhoeven dev_err(&rspi->ctlr->dev, "receive timeout\n"); 848db300838SArnd Bergmann return ret; 849db300838SArnd Bergmann } 850db300838SArnd Bergmann for (i = 0; i < len; i++) 851db300838SArnd Bergmann *rx++ = rspi_read_data(rspi); 8527e95b166SHoan Nguyen An 853db300838SArnd Bergmann n -= len; 854db300838SArnd Bergmann } 855db300838SArnd Bergmann 856db300838SArnd Bergmann return 0; 857880c6d11SGeert Uytterhoeven } 858880c6d11SGeert Uytterhoeven 8599428a073SGeert Uytterhoeven static int qspi_transfer_one(struct spi_controller *ctlr, 8609428a073SGeert Uytterhoeven struct spi_device *spi, struct spi_transfer *xfer) 861eb557f75SGeert Uytterhoeven { 8629428a073SGeert Uytterhoeven struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 863eb557f75SGeert Uytterhoeven 864cb588254SGeert Uytterhoeven xfer->effective_speed_hz = rspi->speed_hz; 865ba824d49SGeert Uytterhoeven if (spi->mode & SPI_LOOP) { 866ba824d49SGeert Uytterhoeven return qspi_transfer_out_in(rspi, xfer); 867b42e0359SGeert Uytterhoeven } else if (xfer->tx_nbits > SPI_NBITS_SINGLE) { 868880c6d11SGeert Uytterhoeven /* Quad or Dual SPI Write */ 869880c6d11SGeert Uytterhoeven return qspi_transfer_out(rspi, xfer); 870b42e0359SGeert Uytterhoeven } else if (xfer->rx_nbits > SPI_NBITS_SINGLE) { 871880c6d11SGeert Uytterhoeven /* Quad or Dual SPI Read */ 872880c6d11SGeert Uytterhoeven return qspi_transfer_in(rspi, xfer); 873880c6d11SGeert Uytterhoeven } else { 874880c6d11SGeert Uytterhoeven /* Single SPI Transfer */ 875340a15e6SGeert Uytterhoeven return qspi_transfer_out_in(rspi, xfer); 876eb557f75SGeert Uytterhoeven } 877880c6d11SGeert Uytterhoeven } 878eb557f75SGeert Uytterhoeven 879880c6d11SGeert Uytterhoeven static u16 qspi_transfer_mode(const struct spi_transfer *xfer) 880880c6d11SGeert Uytterhoeven { 881880c6d11SGeert Uytterhoeven if (xfer->tx_buf) 882880c6d11SGeert Uytterhoeven switch (xfer->tx_nbits) { 883880c6d11SGeert Uytterhoeven case SPI_NBITS_QUAD: 884880c6d11SGeert Uytterhoeven return SPCMD_SPIMOD_QUAD; 885880c6d11SGeert Uytterhoeven case SPI_NBITS_DUAL: 886880c6d11SGeert Uytterhoeven return SPCMD_SPIMOD_DUAL; 887880c6d11SGeert Uytterhoeven default: 888880c6d11SGeert Uytterhoeven return 0; 889880c6d11SGeert Uytterhoeven } 890880c6d11SGeert Uytterhoeven if (xfer->rx_buf) 891880c6d11SGeert Uytterhoeven switch (xfer->rx_nbits) { 892880c6d11SGeert Uytterhoeven case SPI_NBITS_QUAD: 893880c6d11SGeert Uytterhoeven return SPCMD_SPIMOD_QUAD | SPCMD_SPRW; 894880c6d11SGeert Uytterhoeven case SPI_NBITS_DUAL: 895880c6d11SGeert Uytterhoeven return SPCMD_SPIMOD_DUAL | SPCMD_SPRW; 896880c6d11SGeert Uytterhoeven default: 897880c6d11SGeert Uytterhoeven return 0; 898880c6d11SGeert Uytterhoeven } 899880c6d11SGeert Uytterhoeven 900880c6d11SGeert Uytterhoeven return 0; 901880c6d11SGeert Uytterhoeven } 902880c6d11SGeert Uytterhoeven 903880c6d11SGeert Uytterhoeven static int qspi_setup_sequencer(struct rspi_data *rspi, 904880c6d11SGeert Uytterhoeven const struct spi_message *msg) 905880c6d11SGeert Uytterhoeven { 906880c6d11SGeert Uytterhoeven const struct spi_transfer *xfer; 907880c6d11SGeert Uytterhoeven unsigned int i = 0, len = 0; 908880c6d11SGeert Uytterhoeven u16 current_mode = 0xffff, mode; 909880c6d11SGeert Uytterhoeven 910880c6d11SGeert Uytterhoeven list_for_each_entry(xfer, &msg->transfers, transfer_list) { 911880c6d11SGeert Uytterhoeven mode = qspi_transfer_mode(xfer); 912880c6d11SGeert Uytterhoeven if (mode == current_mode) { 913880c6d11SGeert Uytterhoeven len += xfer->len; 914880c6d11SGeert Uytterhoeven continue; 915880c6d11SGeert Uytterhoeven } 916880c6d11SGeert Uytterhoeven 917880c6d11SGeert Uytterhoeven /* Transfer mode change */ 918880c6d11SGeert Uytterhoeven if (i) { 919880c6d11SGeert Uytterhoeven /* Set transfer data length of previous transfer */ 920880c6d11SGeert Uytterhoeven rspi_write32(rspi, len, QSPI_SPBMUL(i - 1)); 921880c6d11SGeert Uytterhoeven } 922880c6d11SGeert Uytterhoeven 923880c6d11SGeert Uytterhoeven if (i >= QSPI_NUM_SPCMD) { 924880c6d11SGeert Uytterhoeven dev_err(&msg->spi->dev, 925880c6d11SGeert Uytterhoeven "Too many different transfer modes"); 926880c6d11SGeert Uytterhoeven return -EINVAL; 927880c6d11SGeert Uytterhoeven } 928880c6d11SGeert Uytterhoeven 929880c6d11SGeert Uytterhoeven /* Program transfer mode for this transfer */ 930880c6d11SGeert Uytterhoeven rspi_write16(rspi, rspi->spcmd | mode, RSPI_SPCMD(i)); 931880c6d11SGeert Uytterhoeven current_mode = mode; 932880c6d11SGeert Uytterhoeven len = xfer->len; 933880c6d11SGeert Uytterhoeven i++; 934880c6d11SGeert Uytterhoeven } 935880c6d11SGeert Uytterhoeven if (i) { 936880c6d11SGeert Uytterhoeven /* Set final transfer data length and sequence length */ 937880c6d11SGeert Uytterhoeven rspi_write32(rspi, len, QSPI_SPBMUL(i - 1)); 938880c6d11SGeert Uytterhoeven rspi_write8(rspi, i - 1, RSPI_SPSCR); 939880c6d11SGeert Uytterhoeven } 940880c6d11SGeert Uytterhoeven 941880c6d11SGeert Uytterhoeven return 0; 942880c6d11SGeert Uytterhoeven } 943880c6d11SGeert Uytterhoeven 944f3a14a3aSGeert Uytterhoeven static int rspi_setup(struct spi_device *spi) 945f3a14a3aSGeert Uytterhoeven { 946f3a14a3aSGeert Uytterhoeven struct rspi_data *rspi = spi_controller_get_devdata(spi->controller); 947f3a14a3aSGeert Uytterhoeven u8 sslp; 948f3a14a3aSGeert Uytterhoeven 949f3a14a3aSGeert Uytterhoeven if (spi->cs_gpiod) 950f3a14a3aSGeert Uytterhoeven return 0; 951f3a14a3aSGeert Uytterhoeven 952f3a14a3aSGeert Uytterhoeven pm_runtime_get_sync(&rspi->pdev->dev); 953f3a14a3aSGeert Uytterhoeven spin_lock_irq(&rspi->lock); 954f3a14a3aSGeert Uytterhoeven 955f3a14a3aSGeert Uytterhoeven sslp = rspi_read8(rspi, RSPI_SSLP); 956f3a14a3aSGeert Uytterhoeven if (spi->mode & SPI_CS_HIGH) 957f3a14a3aSGeert Uytterhoeven sslp |= SSLP_SSLP(spi->chip_select); 958f3a14a3aSGeert Uytterhoeven else 959f3a14a3aSGeert Uytterhoeven sslp &= ~SSLP_SSLP(spi->chip_select); 960f3a14a3aSGeert Uytterhoeven rspi_write8(rspi, sslp, RSPI_SSLP); 961f3a14a3aSGeert Uytterhoeven 962f3a14a3aSGeert Uytterhoeven spin_unlock_irq(&rspi->lock); 963f3a14a3aSGeert Uytterhoeven pm_runtime_put(&rspi->pdev->dev); 964f3a14a3aSGeert Uytterhoeven return 0; 965f3a14a3aSGeert Uytterhoeven } 966f3a14a3aSGeert Uytterhoeven 9679428a073SGeert Uytterhoeven static int rspi_prepare_message(struct spi_controller *ctlr, 968880c6d11SGeert Uytterhoeven struct spi_message *msg) 96979d23495SGeert Uytterhoeven { 9709428a073SGeert Uytterhoeven struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 97142bdaaecSGeert Uytterhoeven struct spi_device *spi = msg->spi; 972e0fe7005SGeert Uytterhoeven const struct spi_transfer *xfer; 973880c6d11SGeert Uytterhoeven int ret; 9740b2182ddSShimoda, Yoshihiro 975e0fe7005SGeert Uytterhoeven /* 976e0fe7005SGeert Uytterhoeven * As the Bit Rate Register must not be changed while the device is 977e0fe7005SGeert Uytterhoeven * active, all transfers in a message must use the same bit rate. 978e0fe7005SGeert Uytterhoeven * In theory, the sequencer could be enabled, and each Command Register 979e0fe7005SGeert Uytterhoeven * could divide the base bit rate by a different value. 980e0fe7005SGeert Uytterhoeven * However, most RSPI variants do not have Transfer Data Length 981e0fe7005SGeert Uytterhoeven * Multiplier Setting Registers, so each sequence step would be limited 982e0fe7005SGeert Uytterhoeven * to a single word, making this feature unsuitable for large 983e0fe7005SGeert Uytterhoeven * transfers, which would gain most from it. 984e0fe7005SGeert Uytterhoeven */ 985e0fe7005SGeert Uytterhoeven rspi->speed_hz = spi->max_speed_hz; 986e0fe7005SGeert Uytterhoeven list_for_each_entry(xfer, &msg->transfers, transfer_list) { 987e0fe7005SGeert Uytterhoeven if (xfer->speed_hz < rspi->speed_hz) 988e0fe7005SGeert Uytterhoeven rspi->speed_hz = xfer->speed_hz; 989e0fe7005SGeert Uytterhoeven } 99042bdaaecSGeert Uytterhoeven 99142bdaaecSGeert Uytterhoeven rspi->spcmd = SPCMD_SSLKP; 99242bdaaecSGeert Uytterhoeven if (spi->mode & SPI_CPOL) 99342bdaaecSGeert Uytterhoeven rspi->spcmd |= SPCMD_CPOL; 99442bdaaecSGeert Uytterhoeven if (spi->mode & SPI_CPHA) 99542bdaaecSGeert Uytterhoeven rspi->spcmd |= SPCMD_CPHA; 996c046f8fdSGeert Uytterhoeven if (spi->mode & SPI_LSB_FIRST) 997c046f8fdSGeert Uytterhoeven rspi->spcmd |= SPCMD_LSBF; 99842bdaaecSGeert Uytterhoeven 9999815ed87SGeert Uytterhoeven /* Configure slave signal to assert */ 1000144d8f97SGeert Uytterhoeven rspi->spcmd |= SPCMD_SSLA(spi->cs_gpiod ? rspi->ctlr->unused_native_cs 1001144d8f97SGeert Uytterhoeven : spi->chip_select); 10029815ed87SGeert Uytterhoeven 100342bdaaecSGeert Uytterhoeven /* CMOS output mode and MOSI signal from previous transfer */ 100442bdaaecSGeert Uytterhoeven rspi->sppcr = 0; 100542bdaaecSGeert Uytterhoeven if (spi->mode & SPI_LOOP) 100642bdaaecSGeert Uytterhoeven rspi->sppcr |= SPPCR_SPLP; 100742bdaaecSGeert Uytterhoeven 10088f2344faSGeert Uytterhoeven rspi->ops->set_config_register(rspi, 8); 100942bdaaecSGeert Uytterhoeven 1010880c6d11SGeert Uytterhoeven if (msg->spi->mode & 1011880c6d11SGeert Uytterhoeven (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)) { 1012880c6d11SGeert Uytterhoeven /* Setup sequencer for messages with multiple transfer modes */ 1013880c6d11SGeert Uytterhoeven ret = qspi_setup_sequencer(rspi, msg); 1014880c6d11SGeert Uytterhoeven if (ret < 0) 1015880c6d11SGeert Uytterhoeven return ret; 1016880c6d11SGeert Uytterhoeven } 1017880c6d11SGeert Uytterhoeven 1018880c6d11SGeert Uytterhoeven /* Enable SPI function in master mode */ 101979d23495SGeert Uytterhoeven rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR); 10200b2182ddSShimoda, Yoshihiro return 0; 10210b2182ddSShimoda, Yoshihiro } 10220b2182ddSShimoda, Yoshihiro 10239428a073SGeert Uytterhoeven static int rspi_unprepare_message(struct spi_controller *ctlr, 1024880c6d11SGeert Uytterhoeven struct spi_message *msg) 10250b2182ddSShimoda, Yoshihiro { 10269428a073SGeert Uytterhoeven struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 102779d23495SGeert Uytterhoeven 1028880c6d11SGeert Uytterhoeven /* Disable SPI function */ 102979d23495SGeert Uytterhoeven rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR); 1030880c6d11SGeert Uytterhoeven 1031880c6d11SGeert Uytterhoeven /* Reset sequencer for Single SPI Transfers */ 1032880c6d11SGeert Uytterhoeven rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 1033880c6d11SGeert Uytterhoeven rspi_write8(rspi, 0, RSPI_SPSCR); 103479d23495SGeert Uytterhoeven return 0; 10350b2182ddSShimoda, Yoshihiro } 10360b2182ddSShimoda, Yoshihiro 103793722206SGeert Uytterhoeven static irqreturn_t rspi_irq_mux(int irq, void *_sr) 10380b2182ddSShimoda, Yoshihiro { 1039c132f094SGeert Uytterhoeven struct rspi_data *rspi = _sr; 104097b95c11SGeert Uytterhoeven u8 spsr; 10410b2182ddSShimoda, Yoshihiro irqreturn_t ret = IRQ_NONE; 104297b95c11SGeert Uytterhoeven u8 disable_irq = 0; 10430b2182ddSShimoda, Yoshihiro 10440b2182ddSShimoda, Yoshihiro rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR); 10450b2182ddSShimoda, Yoshihiro if (spsr & SPSR_SPRF) 10460b2182ddSShimoda, Yoshihiro disable_irq |= SPCR_SPRIE; 10470b2182ddSShimoda, Yoshihiro if (spsr & SPSR_SPTEF) 10480b2182ddSShimoda, Yoshihiro disable_irq |= SPCR_SPTIE; 10490b2182ddSShimoda, Yoshihiro 10500b2182ddSShimoda, Yoshihiro if (disable_irq) { 10510b2182ddSShimoda, Yoshihiro ret = IRQ_HANDLED; 10520b2182ddSShimoda, Yoshihiro rspi_disable_irq(rspi, disable_irq); 10530b2182ddSShimoda, Yoshihiro wake_up(&rspi->wait); 10540b2182ddSShimoda, Yoshihiro } 10550b2182ddSShimoda, Yoshihiro 10560b2182ddSShimoda, Yoshihiro return ret; 10570b2182ddSShimoda, Yoshihiro } 10580b2182ddSShimoda, Yoshihiro 105993722206SGeert Uytterhoeven static irqreturn_t rspi_irq_rx(int irq, void *_sr) 106093722206SGeert Uytterhoeven { 106193722206SGeert Uytterhoeven struct rspi_data *rspi = _sr; 106293722206SGeert Uytterhoeven u8 spsr; 106393722206SGeert Uytterhoeven 106493722206SGeert Uytterhoeven rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR); 106593722206SGeert Uytterhoeven if (spsr & SPSR_SPRF) { 106693722206SGeert Uytterhoeven rspi_disable_irq(rspi, SPCR_SPRIE); 106793722206SGeert Uytterhoeven wake_up(&rspi->wait); 106893722206SGeert Uytterhoeven return IRQ_HANDLED; 106993722206SGeert Uytterhoeven } 107093722206SGeert Uytterhoeven 107193722206SGeert Uytterhoeven return 0; 107293722206SGeert Uytterhoeven } 107393722206SGeert Uytterhoeven 107493722206SGeert Uytterhoeven static irqreturn_t rspi_irq_tx(int irq, void *_sr) 107593722206SGeert Uytterhoeven { 107693722206SGeert Uytterhoeven struct rspi_data *rspi = _sr; 107793722206SGeert Uytterhoeven u8 spsr; 107893722206SGeert Uytterhoeven 107993722206SGeert Uytterhoeven rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR); 108093722206SGeert Uytterhoeven if (spsr & SPSR_SPTEF) { 108193722206SGeert Uytterhoeven rspi_disable_irq(rspi, SPCR_SPTIE); 108293722206SGeert Uytterhoeven wake_up(&rspi->wait); 108393722206SGeert Uytterhoeven return IRQ_HANDLED; 108493722206SGeert Uytterhoeven } 108593722206SGeert Uytterhoeven 108693722206SGeert Uytterhoeven return 0; 108793722206SGeert Uytterhoeven } 108893722206SGeert Uytterhoeven 108965bf2205SGeert Uytterhoeven static struct dma_chan *rspi_request_dma_chan(struct device *dev, 109065bf2205SGeert Uytterhoeven enum dma_transfer_direction dir, 109165bf2205SGeert Uytterhoeven unsigned int id, 109265bf2205SGeert Uytterhoeven dma_addr_t port_addr) 109365bf2205SGeert Uytterhoeven { 109465bf2205SGeert Uytterhoeven dma_cap_mask_t mask; 109565bf2205SGeert Uytterhoeven struct dma_chan *chan; 109665bf2205SGeert Uytterhoeven struct dma_slave_config cfg; 109765bf2205SGeert Uytterhoeven int ret; 109865bf2205SGeert Uytterhoeven 109965bf2205SGeert Uytterhoeven dma_cap_zero(mask); 110065bf2205SGeert Uytterhoeven dma_cap_set(DMA_SLAVE, mask); 110165bf2205SGeert Uytterhoeven 1102e825b8ddSGeert Uytterhoeven chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, 1103e825b8ddSGeert Uytterhoeven (void *)(unsigned long)id, dev, 1104e825b8ddSGeert Uytterhoeven dir == DMA_MEM_TO_DEV ? "tx" : "rx"); 110565bf2205SGeert Uytterhoeven if (!chan) { 1106e825b8ddSGeert Uytterhoeven dev_warn(dev, "dma_request_slave_channel_compat failed\n"); 110765bf2205SGeert Uytterhoeven return NULL; 110865bf2205SGeert Uytterhoeven } 110965bf2205SGeert Uytterhoeven 111065bf2205SGeert Uytterhoeven memset(&cfg, 0, sizeof(cfg)); 1111*6f381481SBiju Das cfg.dst_addr = port_addr + RSPI_SPDR; 1112*6f381481SBiju Das cfg.src_addr = port_addr + RSPI_SPDR; 1113a30b95a7SGeert Uytterhoeven cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; 1114a30b95a7SGeert Uytterhoeven cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; 1115*6f381481SBiju Das cfg.direction = dir; 111665bf2205SGeert Uytterhoeven 111765bf2205SGeert Uytterhoeven ret = dmaengine_slave_config(chan, &cfg); 111865bf2205SGeert Uytterhoeven if (ret) { 111965bf2205SGeert Uytterhoeven dev_warn(dev, "dmaengine_slave_config failed %d\n", ret); 112065bf2205SGeert Uytterhoeven dma_release_channel(chan); 112165bf2205SGeert Uytterhoeven return NULL; 112265bf2205SGeert Uytterhoeven } 112365bf2205SGeert Uytterhoeven 112465bf2205SGeert Uytterhoeven return chan; 112565bf2205SGeert Uytterhoeven } 112665bf2205SGeert Uytterhoeven 11279428a073SGeert Uytterhoeven static int rspi_request_dma(struct device *dev, struct spi_controller *ctlr, 1128fcdc49aeSGeert Uytterhoeven const struct resource *res) 1129a3633fe7SShimoda, Yoshihiro { 1130fcdc49aeSGeert Uytterhoeven const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev); 1131e825b8ddSGeert Uytterhoeven unsigned int dma_tx_id, dma_rx_id; 1132a3633fe7SShimoda, Yoshihiro 1133e825b8ddSGeert Uytterhoeven if (dev->of_node) { 1134e825b8ddSGeert Uytterhoeven /* In the OF case we will get the slave IDs from the DT */ 1135e825b8ddSGeert Uytterhoeven dma_tx_id = 0; 1136e825b8ddSGeert Uytterhoeven dma_rx_id = 0; 1137e825b8ddSGeert Uytterhoeven } else if (rspi_pd && rspi_pd->dma_tx_id && rspi_pd->dma_rx_id) { 1138e825b8ddSGeert Uytterhoeven dma_tx_id = rspi_pd->dma_tx_id; 1139e825b8ddSGeert Uytterhoeven dma_rx_id = rspi_pd->dma_rx_id; 1140e825b8ddSGeert Uytterhoeven } else { 1141e825b8ddSGeert Uytterhoeven /* The driver assumes no error. */ 1142e825b8ddSGeert Uytterhoeven return 0; 1143e825b8ddSGeert Uytterhoeven } 1144a3633fe7SShimoda, Yoshihiro 11459428a073SGeert Uytterhoeven ctlr->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, dma_tx_id, 1146*6f381481SBiju Das res->start); 11479428a073SGeert Uytterhoeven if (!ctlr->dma_tx) 114865bf2205SGeert Uytterhoeven return -ENODEV; 114965bf2205SGeert Uytterhoeven 11509428a073SGeert Uytterhoeven ctlr->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, dma_rx_id, 1151*6f381481SBiju Das res->start); 11529428a073SGeert Uytterhoeven if (!ctlr->dma_rx) { 11539428a073SGeert Uytterhoeven dma_release_channel(ctlr->dma_tx); 11549428a073SGeert Uytterhoeven ctlr->dma_tx = NULL; 115565bf2205SGeert Uytterhoeven return -ENODEV; 1156a3633fe7SShimoda, Yoshihiro } 1157a3633fe7SShimoda, Yoshihiro 11589428a073SGeert Uytterhoeven ctlr->can_dma = rspi_can_dma; 11595f338d0cSGeert Uytterhoeven dev_info(dev, "DMA available"); 11600243c536SShimoda, Yoshihiro return 0; 11610243c536SShimoda, Yoshihiro } 11620243c536SShimoda, Yoshihiro 11639428a073SGeert Uytterhoeven static void rspi_release_dma(struct spi_controller *ctlr) 1164a3633fe7SShimoda, Yoshihiro { 11659428a073SGeert Uytterhoeven if (ctlr->dma_tx) 11669428a073SGeert Uytterhoeven dma_release_channel(ctlr->dma_tx); 11679428a073SGeert Uytterhoeven if (ctlr->dma_rx) 11689428a073SGeert Uytterhoeven dma_release_channel(ctlr->dma_rx); 1169a3633fe7SShimoda, Yoshihiro } 1170a3633fe7SShimoda, Yoshihiro 1171fd4a319bSGrant Likely static int rspi_remove(struct platform_device *pdev) 11720b2182ddSShimoda, Yoshihiro { 11735ffbe2d9SLaurent Pinchart struct rspi_data *rspi = platform_get_drvdata(pdev); 11740b2182ddSShimoda, Yoshihiro 11759428a073SGeert Uytterhoeven rspi_release_dma(rspi->ctlr); 1176490c9774SGeert Uytterhoeven pm_runtime_disable(&pdev->dev); 11770b2182ddSShimoda, Yoshihiro 11780b2182ddSShimoda, Yoshihiro return 0; 11790b2182ddSShimoda, Yoshihiro } 11800b2182ddSShimoda, Yoshihiro 1181426ef76dSGeert Uytterhoeven static const struct spi_ops rspi_ops = { 1182426ef76dSGeert Uytterhoeven .set_config_register = rspi_set_config_register, 1183426ef76dSGeert Uytterhoeven .transfer_one = rspi_transfer_one, 1184c3197974SGeert Uytterhoeven .min_div = 2, 1185c3197974SGeert Uytterhoeven .max_div = 4096, 11869428a073SGeert Uytterhoeven .flags = SPI_CONTROLLER_MUST_TX, 11872f777ec9SGeert Uytterhoeven .fifo_size = 8, 1188144d8f97SGeert Uytterhoeven .num_hw_ss = 2, 1189426ef76dSGeert Uytterhoeven }; 1190426ef76dSGeert Uytterhoeven 1191426ef76dSGeert Uytterhoeven static const struct spi_ops rspi_rz_ops = { 1192426ef76dSGeert Uytterhoeven .set_config_register = rspi_rz_set_config_register, 1193426ef76dSGeert Uytterhoeven .transfer_one = rspi_rz_transfer_one, 1194c3197974SGeert Uytterhoeven .min_div = 2, 1195c3197974SGeert Uytterhoeven .max_div = 4096, 11969428a073SGeert Uytterhoeven .flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX, 11972f777ec9SGeert Uytterhoeven .fifo_size = 8, /* 8 for TX, 32 for RX */ 1198144d8f97SGeert Uytterhoeven .num_hw_ss = 1, 1199426ef76dSGeert Uytterhoeven }; 1200426ef76dSGeert Uytterhoeven 1201426ef76dSGeert Uytterhoeven static const struct spi_ops qspi_ops = { 1202426ef76dSGeert Uytterhoeven .set_config_register = qspi_set_config_register, 1203426ef76dSGeert Uytterhoeven .transfer_one = qspi_transfer_one, 1204cd982e6cSGeert Uytterhoeven .extra_mode_bits = SPI_TX_DUAL | SPI_TX_QUAD | 1205880c6d11SGeert Uytterhoeven SPI_RX_DUAL | SPI_RX_QUAD, 1206c3197974SGeert Uytterhoeven .min_div = 1, 1207c3197974SGeert Uytterhoeven .max_div = 4080, 12089428a073SGeert Uytterhoeven .flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX, 12092f777ec9SGeert Uytterhoeven .fifo_size = 32, 1210144d8f97SGeert Uytterhoeven .num_hw_ss = 1, 1211426ef76dSGeert Uytterhoeven }; 1212426ef76dSGeert Uytterhoeven 1213426ef76dSGeert Uytterhoeven #ifdef CONFIG_OF 1214426ef76dSGeert Uytterhoeven static const struct of_device_id rspi_of_match[] = { 1215426ef76dSGeert Uytterhoeven /* RSPI on legacy SH */ 1216426ef76dSGeert Uytterhoeven { .compatible = "renesas,rspi", .data = &rspi_ops }, 1217426ef76dSGeert Uytterhoeven /* RSPI on RZ/A1H */ 1218426ef76dSGeert Uytterhoeven { .compatible = "renesas,rspi-rz", .data = &rspi_rz_ops }, 1219426ef76dSGeert Uytterhoeven /* QSPI on R-Car Gen2 */ 1220426ef76dSGeert Uytterhoeven { .compatible = "renesas,qspi", .data = &qspi_ops }, 1221426ef76dSGeert Uytterhoeven { /* sentinel */ } 1222426ef76dSGeert Uytterhoeven }; 1223426ef76dSGeert Uytterhoeven 1224426ef76dSGeert Uytterhoeven MODULE_DEVICE_TABLE(of, rspi_of_match); 1225426ef76dSGeert Uytterhoeven 1226aadbff4aSLad Prabhakar static void rspi_reset_control_assert(void *data) 1227aadbff4aSLad Prabhakar { 1228aadbff4aSLad Prabhakar reset_control_assert(data); 1229aadbff4aSLad Prabhakar } 1230aadbff4aSLad Prabhakar 12319428a073SGeert Uytterhoeven static int rspi_parse_dt(struct device *dev, struct spi_controller *ctlr) 1232426ef76dSGeert Uytterhoeven { 1233aadbff4aSLad Prabhakar struct reset_control *rstc; 1234426ef76dSGeert Uytterhoeven u32 num_cs; 1235426ef76dSGeert Uytterhoeven int error; 1236426ef76dSGeert Uytterhoeven 1237426ef76dSGeert Uytterhoeven /* Parse DT properties */ 1238426ef76dSGeert Uytterhoeven error = of_property_read_u32(dev->of_node, "num-cs", &num_cs); 1239426ef76dSGeert Uytterhoeven if (error) { 1240426ef76dSGeert Uytterhoeven dev_err(dev, "of_property_read_u32 num-cs failed %d\n", error); 1241426ef76dSGeert Uytterhoeven return error; 1242426ef76dSGeert Uytterhoeven } 1243426ef76dSGeert Uytterhoeven 12449428a073SGeert Uytterhoeven ctlr->num_chipselect = num_cs; 1245aadbff4aSLad Prabhakar 1246aadbff4aSLad Prabhakar rstc = devm_reset_control_get_optional_exclusive(dev, NULL); 1247aadbff4aSLad Prabhakar if (IS_ERR(rstc)) 1248aadbff4aSLad Prabhakar return dev_err_probe(dev, PTR_ERR(rstc), 1249aadbff4aSLad Prabhakar "failed to get reset ctrl\n"); 1250aadbff4aSLad Prabhakar 1251aadbff4aSLad Prabhakar error = reset_control_deassert(rstc); 1252aadbff4aSLad Prabhakar if (error) { 1253aadbff4aSLad Prabhakar dev_err(dev, "failed to deassert reset %d\n", error); 1254aadbff4aSLad Prabhakar return error; 1255aadbff4aSLad Prabhakar } 1256aadbff4aSLad Prabhakar 1257aadbff4aSLad Prabhakar error = devm_add_action_or_reset(dev, rspi_reset_control_assert, rstc); 1258aadbff4aSLad Prabhakar if (error) { 1259aadbff4aSLad Prabhakar dev_err(dev, "failed to register assert devm action, %d\n", error); 1260aadbff4aSLad Prabhakar return error; 1261aadbff4aSLad Prabhakar } 1262aadbff4aSLad Prabhakar 1263426ef76dSGeert Uytterhoeven return 0; 1264426ef76dSGeert Uytterhoeven } 1265426ef76dSGeert Uytterhoeven #else 126664b67defSShimoda, Yoshihiro #define rspi_of_match NULL 12679428a073SGeert Uytterhoeven static inline int rspi_parse_dt(struct device *dev, struct spi_controller *ctlr) 1268426ef76dSGeert Uytterhoeven { 1269426ef76dSGeert Uytterhoeven return -EINVAL; 1270426ef76dSGeert Uytterhoeven } 1271426ef76dSGeert Uytterhoeven #endif /* CONFIG_OF */ 1272426ef76dSGeert Uytterhoeven 127393722206SGeert Uytterhoeven static int rspi_request_irq(struct device *dev, unsigned int irq, 127493722206SGeert Uytterhoeven irq_handler_t handler, const char *suffix, 127593722206SGeert Uytterhoeven void *dev_id) 127693722206SGeert Uytterhoeven { 127743937455SGeert Uytterhoeven const char *name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", 127843937455SGeert Uytterhoeven dev_name(dev), suffix); 127993722206SGeert Uytterhoeven if (!name) 128093722206SGeert Uytterhoeven return -ENOMEM; 128143937455SGeert Uytterhoeven 128293722206SGeert Uytterhoeven return devm_request_irq(dev, irq, handler, 0, name, dev_id); 128393722206SGeert Uytterhoeven } 128493722206SGeert Uytterhoeven 1285fd4a319bSGrant Likely static int rspi_probe(struct platform_device *pdev) 12860b2182ddSShimoda, Yoshihiro { 12870b2182ddSShimoda, Yoshihiro struct resource *res; 12889428a073SGeert Uytterhoeven struct spi_controller *ctlr; 12890b2182ddSShimoda, Yoshihiro struct rspi_data *rspi; 129093722206SGeert Uytterhoeven int ret; 1291426ef76dSGeert Uytterhoeven const struct rspi_plat_data *rspi_pd; 12925ce0ba88SHiep Cao Minh const struct spi_ops *ops; 1293c3197974SGeert Uytterhoeven unsigned long clksrc; 12940b2182ddSShimoda, Yoshihiro 12959428a073SGeert Uytterhoeven ctlr = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data)); 12969428a073SGeert Uytterhoeven if (ctlr == NULL) 12970b2182ddSShimoda, Yoshihiro return -ENOMEM; 12980b2182ddSShimoda, Yoshihiro 1299219a7bc5SGeert Uytterhoeven ops = of_device_get_match_data(&pdev->dev); 1300219a7bc5SGeert Uytterhoeven if (ops) { 13019428a073SGeert Uytterhoeven ret = rspi_parse_dt(&pdev->dev, ctlr); 1302426ef76dSGeert Uytterhoeven if (ret) 1303426ef76dSGeert Uytterhoeven goto error1; 1304426ef76dSGeert Uytterhoeven } else { 1305426ef76dSGeert Uytterhoeven ops = (struct spi_ops *)pdev->id_entry->driver_data; 1306426ef76dSGeert Uytterhoeven rspi_pd = dev_get_platdata(&pdev->dev); 1307426ef76dSGeert Uytterhoeven if (rspi_pd && rspi_pd->num_chipselect) 13089428a073SGeert Uytterhoeven ctlr->num_chipselect = rspi_pd->num_chipselect; 1309426ef76dSGeert Uytterhoeven else 13109428a073SGeert Uytterhoeven ctlr->num_chipselect = 2; /* default */ 1311d64b4726SGeert Uytterhoeven } 1312426ef76dSGeert Uytterhoeven 13139428a073SGeert Uytterhoeven rspi = spi_controller_get_devdata(ctlr); 131424b5a82cSJingoo Han platform_set_drvdata(pdev, rspi); 13155ce0ba88SHiep Cao Minh rspi->ops = ops; 13169428a073SGeert Uytterhoeven rspi->ctlr = ctlr; 13175d79e9acSLaurent Pinchart 13185d79e9acSLaurent Pinchart res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 13195d79e9acSLaurent Pinchart rspi->addr = devm_ioremap_resource(&pdev->dev, res); 13205d79e9acSLaurent Pinchart if (IS_ERR(rspi->addr)) { 13215d79e9acSLaurent Pinchart ret = PTR_ERR(rspi->addr); 13220b2182ddSShimoda, Yoshihiro goto error1; 13230b2182ddSShimoda, Yoshihiro } 13240b2182ddSShimoda, Yoshihiro 132529f397b7SGeert Uytterhoeven rspi->clk = devm_clk_get(&pdev->dev, NULL); 13260b2182ddSShimoda, Yoshihiro if (IS_ERR(rspi->clk)) { 13270b2182ddSShimoda, Yoshihiro dev_err(&pdev->dev, "cannot get clock\n"); 13280b2182ddSShimoda, Yoshihiro ret = PTR_ERR(rspi->clk); 13295d79e9acSLaurent Pinchart goto error1; 13300b2182ddSShimoda, Yoshihiro } 133117fe0d9aSGeert Uytterhoeven 1332f3a14a3aSGeert Uytterhoeven rspi->pdev = pdev; 1333490c9774SGeert Uytterhoeven pm_runtime_enable(&pdev->dev); 13340b2182ddSShimoda, Yoshihiro 13350b2182ddSShimoda, Yoshihiro init_waitqueue_head(&rspi->wait); 1336f3a14a3aSGeert Uytterhoeven spin_lock_init(&rspi->lock); 13370b2182ddSShimoda, Yoshihiro 13389428a073SGeert Uytterhoeven ctlr->bus_num = pdev->id; 1339f3a14a3aSGeert Uytterhoeven ctlr->setup = rspi_setup; 13409428a073SGeert Uytterhoeven ctlr->auto_runtime_pm = true; 13419428a073SGeert Uytterhoeven ctlr->transfer_one = ops->transfer_one; 13429428a073SGeert Uytterhoeven ctlr->prepare_message = rspi_prepare_message; 13439428a073SGeert Uytterhoeven ctlr->unprepare_message = rspi_unprepare_message; 1344f3a14a3aSGeert Uytterhoeven ctlr->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | 1345f3a14a3aSGeert Uytterhoeven SPI_LOOP | ops->extra_mode_bits; 1346c3197974SGeert Uytterhoeven clksrc = clk_get_rate(rspi->clk); 1347c3197974SGeert Uytterhoeven ctlr->min_speed_hz = DIV_ROUND_UP(clksrc, ops->max_div); 1348c3197974SGeert Uytterhoeven ctlr->max_speed_hz = DIV_ROUND_UP(clksrc, ops->min_div); 13499428a073SGeert Uytterhoeven ctlr->flags = ops->flags; 13509428a073SGeert Uytterhoeven ctlr->dev.of_node = pdev->dev.of_node; 1351144d8f97SGeert Uytterhoeven ctlr->use_gpio_descriptors = true; 1352144d8f97SGeert Uytterhoeven ctlr->max_native_cs = rspi->ops->num_hw_ss; 13530b2182ddSShimoda, Yoshihiro 13542de860b4SGeert Uytterhoeven ret = platform_get_irq_byname_optional(pdev, "rx"); 135593722206SGeert Uytterhoeven if (ret < 0) { 13562de860b4SGeert Uytterhoeven ret = platform_get_irq_byname_optional(pdev, "mux"); 135793722206SGeert Uytterhoeven if (ret < 0) 135893722206SGeert Uytterhoeven ret = platform_get_irq(pdev, 0); 135993722206SGeert Uytterhoeven if (ret >= 0) 136093722206SGeert Uytterhoeven rspi->rx_irq = rspi->tx_irq = ret; 136193722206SGeert Uytterhoeven } else { 136293722206SGeert Uytterhoeven rspi->rx_irq = ret; 136393722206SGeert Uytterhoeven ret = platform_get_irq_byname(pdev, "tx"); 136493722206SGeert Uytterhoeven if (ret >= 0) 136593722206SGeert Uytterhoeven rspi->tx_irq = ret; 136693722206SGeert Uytterhoeven } 136793722206SGeert Uytterhoeven 136893722206SGeert Uytterhoeven if (rspi->rx_irq == rspi->tx_irq) { 136993722206SGeert Uytterhoeven /* Single multiplexed interrupt */ 137093722206SGeert Uytterhoeven ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_mux, 137193722206SGeert Uytterhoeven "mux", rspi); 137293722206SGeert Uytterhoeven } else { 137393722206SGeert Uytterhoeven /* Multi-interrupt mode, only SPRI and SPTI are used */ 137493722206SGeert Uytterhoeven ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_rx, 137593722206SGeert Uytterhoeven "rx", rspi); 137693722206SGeert Uytterhoeven if (!ret) 137793722206SGeert Uytterhoeven ret = rspi_request_irq(&pdev->dev, rspi->tx_irq, 137893722206SGeert Uytterhoeven rspi_irq_tx, "tx", rspi); 137993722206SGeert Uytterhoeven } 13800b2182ddSShimoda, Yoshihiro if (ret < 0) { 13810b2182ddSShimoda, Yoshihiro dev_err(&pdev->dev, "request_irq error\n"); 1382fcb4ed74SGeert Uytterhoeven goto error2; 13830b2182ddSShimoda, Yoshihiro } 13840b2182ddSShimoda, Yoshihiro 13859428a073SGeert Uytterhoeven ret = rspi_request_dma(&pdev->dev, ctlr, res); 138627e105a6SGeert Uytterhoeven if (ret < 0) 138727e105a6SGeert Uytterhoeven dev_warn(&pdev->dev, "DMA not available, using PIO\n"); 1388a3633fe7SShimoda, Yoshihiro 13899428a073SGeert Uytterhoeven ret = devm_spi_register_controller(&pdev->dev, ctlr); 13900b2182ddSShimoda, Yoshihiro if (ret < 0) { 13919428a073SGeert Uytterhoeven dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); 1392fcb4ed74SGeert Uytterhoeven goto error3; 13930b2182ddSShimoda, Yoshihiro } 13940b2182ddSShimoda, Yoshihiro 13950b2182ddSShimoda, Yoshihiro dev_info(&pdev->dev, "probed\n"); 13960b2182ddSShimoda, Yoshihiro 13970b2182ddSShimoda, Yoshihiro return 0; 13980b2182ddSShimoda, Yoshihiro 1399fcb4ed74SGeert Uytterhoeven error3: 14009428a073SGeert Uytterhoeven rspi_release_dma(ctlr); 1401fcb4ed74SGeert Uytterhoeven error2: 1402490c9774SGeert Uytterhoeven pm_runtime_disable(&pdev->dev); 14030b2182ddSShimoda, Yoshihiro error1: 14049428a073SGeert Uytterhoeven spi_controller_put(ctlr); 14050b2182ddSShimoda, Yoshihiro 14060b2182ddSShimoda, Yoshihiro return ret; 14070b2182ddSShimoda, Yoshihiro } 14080b2182ddSShimoda, Yoshihiro 14098634dafaSKrzysztof Kozlowski static const struct platform_device_id spi_driver_ids[] = { 14105ce0ba88SHiep Cao Minh { "rspi", (kernel_ulong_t)&rspi_ops }, 14115ce0ba88SHiep Cao Minh {}, 14125ce0ba88SHiep Cao Minh }; 14135ce0ba88SHiep Cao Minh 14145ce0ba88SHiep Cao Minh MODULE_DEVICE_TABLE(platform, spi_driver_ids); 14155ce0ba88SHiep Cao Minh 1416c1ca59c2SGeert Uytterhoeven #ifdef CONFIG_PM_SLEEP 1417c1ca59c2SGeert Uytterhoeven static int rspi_suspend(struct device *dev) 1418c1ca59c2SGeert Uytterhoeven { 1419be0bf62eSWolfram Sang struct rspi_data *rspi = dev_get_drvdata(dev); 1420c1ca59c2SGeert Uytterhoeven 14219428a073SGeert Uytterhoeven return spi_controller_suspend(rspi->ctlr); 1422c1ca59c2SGeert Uytterhoeven } 1423c1ca59c2SGeert Uytterhoeven 1424c1ca59c2SGeert Uytterhoeven static int rspi_resume(struct device *dev) 1425c1ca59c2SGeert Uytterhoeven { 1426be0bf62eSWolfram Sang struct rspi_data *rspi = dev_get_drvdata(dev); 1427c1ca59c2SGeert Uytterhoeven 14289428a073SGeert Uytterhoeven return spi_controller_resume(rspi->ctlr); 1429c1ca59c2SGeert Uytterhoeven } 1430c1ca59c2SGeert Uytterhoeven 1431c1ca59c2SGeert Uytterhoeven static SIMPLE_DEV_PM_OPS(rspi_pm_ops, rspi_suspend, rspi_resume); 1432c1ca59c2SGeert Uytterhoeven #define DEV_PM_OPS &rspi_pm_ops 1433c1ca59c2SGeert Uytterhoeven #else 1434c1ca59c2SGeert Uytterhoeven #define DEV_PM_OPS NULL 1435c1ca59c2SGeert Uytterhoeven #endif /* CONFIG_PM_SLEEP */ 1436c1ca59c2SGeert Uytterhoeven 14370b2182ddSShimoda, Yoshihiro static struct platform_driver rspi_driver = { 14380b2182ddSShimoda, Yoshihiro .probe = rspi_probe, 1439fd4a319bSGrant Likely .remove = rspi_remove, 14405ce0ba88SHiep Cao Minh .id_table = spi_driver_ids, 14410b2182ddSShimoda, Yoshihiro .driver = { 14425ce0ba88SHiep Cao Minh .name = "renesas_spi", 1443c1ca59c2SGeert Uytterhoeven .pm = DEV_PM_OPS, 1444426ef76dSGeert Uytterhoeven .of_match_table = of_match_ptr(rspi_of_match), 14450b2182ddSShimoda, Yoshihiro }, 14460b2182ddSShimoda, Yoshihiro }; 14470b2182ddSShimoda, Yoshihiro module_platform_driver(rspi_driver); 14480b2182ddSShimoda, Yoshihiro 14490b2182ddSShimoda, Yoshihiro MODULE_DESCRIPTION("Renesas RSPI bus driver"); 14500b2182ddSShimoda, Yoshihiro MODULE_LICENSE("GPL v2"); 14510b2182ddSShimoda, Yoshihiro MODULE_AUTHOR("Yoshihiro Shimoda"); 1452