18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * SH RSPI driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2012, 2013 Renesas Solutions Corp. 68c2ecf20Sopenharmony_ci * Copyright (C) 2014 Glider bvba 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Based on spi-sh.c: 98c2ecf20Sopenharmony_ci * Copyright (C) 2011 Renesas Solutions Corp. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/kernel.h> 148c2ecf20Sopenharmony_ci#include <linux/sched.h> 158c2ecf20Sopenharmony_ci#include <linux/errno.h> 168c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 178c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 188c2ecf20Sopenharmony_ci#include <linux/io.h> 198c2ecf20Sopenharmony_ci#include <linux/clk.h> 208c2ecf20Sopenharmony_ci#include <linux/dmaengine.h> 218c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 228c2ecf20Sopenharmony_ci#include <linux/of_device.h> 238c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 248c2ecf20Sopenharmony_ci#include <linux/sh_dma.h> 258c2ecf20Sopenharmony_ci#include <linux/spi/spi.h> 268c2ecf20Sopenharmony_ci#include <linux/spi/rspi.h> 278c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define RSPI_SPCR 0x00 /* Control Register */ 308c2ecf20Sopenharmony_ci#define RSPI_SSLP 0x01 /* Slave Select Polarity Register */ 318c2ecf20Sopenharmony_ci#define RSPI_SPPCR 0x02 /* Pin Control Register */ 328c2ecf20Sopenharmony_ci#define RSPI_SPSR 0x03 /* Status Register */ 338c2ecf20Sopenharmony_ci#define RSPI_SPDR 0x04 /* Data Register */ 348c2ecf20Sopenharmony_ci#define RSPI_SPSCR 0x08 /* Sequence Control Register */ 358c2ecf20Sopenharmony_ci#define RSPI_SPSSR 0x09 /* Sequence Status Register */ 368c2ecf20Sopenharmony_ci#define RSPI_SPBR 0x0a /* Bit Rate Register */ 378c2ecf20Sopenharmony_ci#define RSPI_SPDCR 0x0b /* Data Control Register */ 388c2ecf20Sopenharmony_ci#define RSPI_SPCKD 0x0c /* Clock Delay Register */ 398c2ecf20Sopenharmony_ci#define RSPI_SSLND 0x0d /* Slave Select Negation Delay Register */ 408c2ecf20Sopenharmony_ci#define RSPI_SPND 0x0e /* Next-Access Delay Register */ 418c2ecf20Sopenharmony_ci#define RSPI_SPCR2 0x0f /* Control Register 2 (SH only) */ 428c2ecf20Sopenharmony_ci#define RSPI_SPCMD0 0x10 /* Command Register 0 */ 438c2ecf20Sopenharmony_ci#define RSPI_SPCMD1 0x12 /* Command Register 1 */ 448c2ecf20Sopenharmony_ci#define RSPI_SPCMD2 0x14 /* Command Register 2 */ 458c2ecf20Sopenharmony_ci#define RSPI_SPCMD3 0x16 /* Command Register 3 */ 468c2ecf20Sopenharmony_ci#define RSPI_SPCMD4 0x18 /* Command Register 4 */ 478c2ecf20Sopenharmony_ci#define RSPI_SPCMD5 0x1a /* Command Register 5 */ 488c2ecf20Sopenharmony_ci#define RSPI_SPCMD6 0x1c /* Command Register 6 */ 498c2ecf20Sopenharmony_ci#define RSPI_SPCMD7 0x1e /* Command Register 7 */ 508c2ecf20Sopenharmony_ci#define RSPI_SPCMD(i) (RSPI_SPCMD0 + (i) * 2) 518c2ecf20Sopenharmony_ci#define RSPI_NUM_SPCMD 8 528c2ecf20Sopenharmony_ci#define RSPI_RZ_NUM_SPCMD 4 538c2ecf20Sopenharmony_ci#define QSPI_NUM_SPCMD 4 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/* RSPI on RZ only */ 568c2ecf20Sopenharmony_ci#define RSPI_SPBFCR 0x20 /* Buffer Control Register */ 578c2ecf20Sopenharmony_ci#define RSPI_SPBFDR 0x22 /* Buffer Data Count Setting Register */ 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* QSPI only */ 608c2ecf20Sopenharmony_ci#define QSPI_SPBFCR 0x18 /* Buffer Control Register */ 618c2ecf20Sopenharmony_ci#define QSPI_SPBDCR 0x1a /* Buffer Data Count Register */ 628c2ecf20Sopenharmony_ci#define QSPI_SPBMUL0 0x1c /* Transfer Data Length Multiplier Setting Register 0 */ 638c2ecf20Sopenharmony_ci#define QSPI_SPBMUL1 0x20 /* Transfer Data Length Multiplier Setting Register 1 */ 648c2ecf20Sopenharmony_ci#define QSPI_SPBMUL2 0x24 /* Transfer Data Length Multiplier Setting Register 2 */ 658c2ecf20Sopenharmony_ci#define QSPI_SPBMUL3 0x28 /* Transfer Data Length Multiplier Setting Register 3 */ 668c2ecf20Sopenharmony_ci#define QSPI_SPBMUL(i) (QSPI_SPBMUL0 + (i) * 4) 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* SPCR - Control Register */ 698c2ecf20Sopenharmony_ci#define SPCR_SPRIE 0x80 /* Receive Interrupt Enable */ 708c2ecf20Sopenharmony_ci#define SPCR_SPE 0x40 /* Function Enable */ 718c2ecf20Sopenharmony_ci#define SPCR_SPTIE 0x20 /* Transmit Interrupt Enable */ 728c2ecf20Sopenharmony_ci#define SPCR_SPEIE 0x10 /* Error Interrupt Enable */ 738c2ecf20Sopenharmony_ci#define SPCR_MSTR 0x08 /* Master/Slave Mode Select */ 748c2ecf20Sopenharmony_ci#define SPCR_MODFEN 0x04 /* Mode Fault Error Detection Enable */ 758c2ecf20Sopenharmony_ci/* RSPI on SH only */ 768c2ecf20Sopenharmony_ci#define SPCR_TXMD 0x02 /* TX Only Mode (vs. Full Duplex) */ 778c2ecf20Sopenharmony_ci#define SPCR_SPMS 0x01 /* 3-wire Mode (vs. 4-wire) */ 788c2ecf20Sopenharmony_ci/* QSPI on R-Car Gen2 only */ 798c2ecf20Sopenharmony_ci#define SPCR_WSWAP 0x02 /* Word Swap of read-data for DMAC */ 808c2ecf20Sopenharmony_ci#define SPCR_BSWAP 0x01 /* Byte Swap of read-data for DMAC */ 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/* SSLP - Slave Select Polarity Register */ 838c2ecf20Sopenharmony_ci#define SSLP_SSLP(i) BIT(i) /* SSLi Signal Polarity Setting */ 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci/* SPPCR - Pin Control Register */ 868c2ecf20Sopenharmony_ci#define SPPCR_MOIFE 0x20 /* MOSI Idle Value Fixing Enable */ 878c2ecf20Sopenharmony_ci#define SPPCR_MOIFV 0x10 /* MOSI Idle Fixed Value */ 888c2ecf20Sopenharmony_ci#define SPPCR_SPOM 0x04 898c2ecf20Sopenharmony_ci#define SPPCR_SPLP2 0x02 /* Loopback Mode 2 (non-inverting) */ 908c2ecf20Sopenharmony_ci#define SPPCR_SPLP 0x01 /* Loopback Mode (inverting) */ 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci#define SPPCR_IO3FV 0x04 /* Single-/Dual-SPI Mode IO3 Output Fixed Value */ 938c2ecf20Sopenharmony_ci#define SPPCR_IO2FV 0x04 /* Single-/Dual-SPI Mode IO2 Output Fixed Value */ 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* SPSR - Status Register */ 968c2ecf20Sopenharmony_ci#define SPSR_SPRF 0x80 /* Receive Buffer Full Flag */ 978c2ecf20Sopenharmony_ci#define SPSR_TEND 0x40 /* Transmit End */ 988c2ecf20Sopenharmony_ci#define SPSR_SPTEF 0x20 /* Transmit Buffer Empty Flag */ 998c2ecf20Sopenharmony_ci#define SPSR_PERF 0x08 /* Parity Error Flag */ 1008c2ecf20Sopenharmony_ci#define SPSR_MODF 0x04 /* Mode Fault Error Flag */ 1018c2ecf20Sopenharmony_ci#define SPSR_IDLNF 0x02 /* RSPI Idle Flag */ 1028c2ecf20Sopenharmony_ci#define SPSR_OVRF 0x01 /* Overrun Error Flag (RSPI only) */ 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci/* SPSCR - Sequence Control Register */ 1058c2ecf20Sopenharmony_ci#define SPSCR_SPSLN_MASK 0x07 /* Sequence Length Specification */ 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci/* SPSSR - Sequence Status Register */ 1088c2ecf20Sopenharmony_ci#define SPSSR_SPECM_MASK 0x70 /* Command Error Mask */ 1098c2ecf20Sopenharmony_ci#define SPSSR_SPCP_MASK 0x07 /* Command Pointer Mask */ 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci/* SPDCR - Data Control Register */ 1128c2ecf20Sopenharmony_ci#define SPDCR_TXDMY 0x80 /* Dummy Data Transmission Enable */ 1138c2ecf20Sopenharmony_ci#define SPDCR_SPLW1 0x40 /* Access Width Specification (RZ) */ 1148c2ecf20Sopenharmony_ci#define SPDCR_SPLW0 0x20 /* Access Width Specification (RZ) */ 1158c2ecf20Sopenharmony_ci#define SPDCR_SPLLWORD (SPDCR_SPLW1 | SPDCR_SPLW0) 1168c2ecf20Sopenharmony_ci#define SPDCR_SPLWORD SPDCR_SPLW1 1178c2ecf20Sopenharmony_ci#define SPDCR_SPLBYTE SPDCR_SPLW0 1188c2ecf20Sopenharmony_ci#define SPDCR_SPLW 0x20 /* Access Width Specification (SH) */ 1198c2ecf20Sopenharmony_ci#define SPDCR_SPRDTD 0x10 /* Receive Transmit Data Select (SH) */ 1208c2ecf20Sopenharmony_ci#define SPDCR_SLSEL1 0x08 1218c2ecf20Sopenharmony_ci#define SPDCR_SLSEL0 0x04 1228c2ecf20Sopenharmony_ci#define SPDCR_SLSEL_MASK 0x0c /* SSL1 Output Select (SH) */ 1238c2ecf20Sopenharmony_ci#define SPDCR_SPFC1 0x02 1248c2ecf20Sopenharmony_ci#define SPDCR_SPFC0 0x01 1258c2ecf20Sopenharmony_ci#define SPDCR_SPFC_MASK 0x03 /* Frame Count Setting (1-4) (SH) */ 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci/* SPCKD - Clock Delay Register */ 1288c2ecf20Sopenharmony_ci#define SPCKD_SCKDL_MASK 0x07 /* Clock Delay Setting (1-8) */ 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* SSLND - Slave Select Negation Delay Register */ 1318c2ecf20Sopenharmony_ci#define SSLND_SLNDL_MASK 0x07 /* SSL Negation Delay Setting (1-8) */ 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci/* SPND - Next-Access Delay Register */ 1348c2ecf20Sopenharmony_ci#define SPND_SPNDL_MASK 0x07 /* Next-Access Delay Setting (1-8) */ 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci/* SPCR2 - Control Register 2 */ 1378c2ecf20Sopenharmony_ci#define SPCR2_PTE 0x08 /* Parity Self-Test Enable */ 1388c2ecf20Sopenharmony_ci#define SPCR2_SPIE 0x04 /* Idle Interrupt Enable */ 1398c2ecf20Sopenharmony_ci#define SPCR2_SPOE 0x02 /* Odd Parity Enable (vs. Even) */ 1408c2ecf20Sopenharmony_ci#define SPCR2_SPPE 0x01 /* Parity Enable */ 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci/* SPCMDn - Command Registers */ 1438c2ecf20Sopenharmony_ci#define SPCMD_SCKDEN 0x8000 /* Clock Delay Setting Enable */ 1448c2ecf20Sopenharmony_ci#define SPCMD_SLNDEN 0x4000 /* SSL Negation Delay Setting Enable */ 1458c2ecf20Sopenharmony_ci#define SPCMD_SPNDEN 0x2000 /* Next-Access Delay Enable */ 1468c2ecf20Sopenharmony_ci#define SPCMD_LSBF 0x1000 /* LSB First */ 1478c2ecf20Sopenharmony_ci#define SPCMD_SPB_MASK 0x0f00 /* Data Length Setting */ 1488c2ecf20Sopenharmony_ci#define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK) 1498c2ecf20Sopenharmony_ci#define SPCMD_SPB_8BIT 0x0000 /* QSPI only */ 1508c2ecf20Sopenharmony_ci#define SPCMD_SPB_16BIT 0x0100 1518c2ecf20Sopenharmony_ci#define SPCMD_SPB_20BIT 0x0000 1528c2ecf20Sopenharmony_ci#define SPCMD_SPB_24BIT 0x0100 1538c2ecf20Sopenharmony_ci#define SPCMD_SPB_32BIT 0x0200 1548c2ecf20Sopenharmony_ci#define SPCMD_SSLKP 0x0080 /* SSL Signal Level Keeping */ 1558c2ecf20Sopenharmony_ci#define SPCMD_SPIMOD_MASK 0x0060 /* SPI Operating Mode (QSPI only) */ 1568c2ecf20Sopenharmony_ci#define SPCMD_SPIMOD1 0x0040 1578c2ecf20Sopenharmony_ci#define SPCMD_SPIMOD0 0x0020 1588c2ecf20Sopenharmony_ci#define SPCMD_SPIMOD_SINGLE 0 1598c2ecf20Sopenharmony_ci#define SPCMD_SPIMOD_DUAL SPCMD_SPIMOD0 1608c2ecf20Sopenharmony_ci#define SPCMD_SPIMOD_QUAD SPCMD_SPIMOD1 1618c2ecf20Sopenharmony_ci#define SPCMD_SPRW 0x0010 /* SPI Read/Write Access (Dual/Quad) */ 1628c2ecf20Sopenharmony_ci#define SPCMD_SSLA(i) ((i) << 4) /* SSL Assert Signal Setting */ 1638c2ecf20Sopenharmony_ci#define SPCMD_BRDV_MASK 0x000c /* Bit Rate Division Setting */ 1648c2ecf20Sopenharmony_ci#define SPCMD_BRDV(brdv) ((brdv) << 2) 1658c2ecf20Sopenharmony_ci#define SPCMD_CPOL 0x0002 /* Clock Polarity Setting */ 1668c2ecf20Sopenharmony_ci#define SPCMD_CPHA 0x0001 /* Clock Phase Setting */ 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci/* SPBFCR - Buffer Control Register */ 1698c2ecf20Sopenharmony_ci#define SPBFCR_TXRST 0x80 /* Transmit Buffer Data Reset */ 1708c2ecf20Sopenharmony_ci#define SPBFCR_RXRST 0x40 /* Receive Buffer Data Reset */ 1718c2ecf20Sopenharmony_ci#define SPBFCR_TXTRG_MASK 0x30 /* Transmit Buffer Data Triggering Number */ 1728c2ecf20Sopenharmony_ci#define SPBFCR_RXTRG_MASK 0x07 /* Receive Buffer Data Triggering Number */ 1738c2ecf20Sopenharmony_ci/* QSPI on R-Car Gen2 */ 1748c2ecf20Sopenharmony_ci#define SPBFCR_TXTRG_1B 0x00 /* 31 bytes (1 byte available) */ 1758c2ecf20Sopenharmony_ci#define SPBFCR_TXTRG_32B 0x30 /* 0 byte (32 bytes available) */ 1768c2ecf20Sopenharmony_ci#define SPBFCR_RXTRG_1B 0x00 /* 1 byte (31 bytes available) */ 1778c2ecf20Sopenharmony_ci#define SPBFCR_RXTRG_32B 0x07 /* 32 bytes (0 byte available) */ 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci#define QSPI_BUFFER_SIZE 32u 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistruct rspi_data { 1828c2ecf20Sopenharmony_ci void __iomem *addr; 1838c2ecf20Sopenharmony_ci u32 speed_hz; 1848c2ecf20Sopenharmony_ci struct spi_controller *ctlr; 1858c2ecf20Sopenharmony_ci struct platform_device *pdev; 1868c2ecf20Sopenharmony_ci wait_queue_head_t wait; 1878c2ecf20Sopenharmony_ci spinlock_t lock; /* Protects RMW-access to RSPI_SSLP */ 1888c2ecf20Sopenharmony_ci struct clk *clk; 1898c2ecf20Sopenharmony_ci u16 spcmd; 1908c2ecf20Sopenharmony_ci u8 spsr; 1918c2ecf20Sopenharmony_ci u8 sppcr; 1928c2ecf20Sopenharmony_ci int rx_irq, tx_irq; 1938c2ecf20Sopenharmony_ci const struct spi_ops *ops; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci unsigned dma_callbacked:1; 1968c2ecf20Sopenharmony_ci unsigned byte_access:1; 1978c2ecf20Sopenharmony_ci}; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_cistatic void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci iowrite8(data, rspi->addr + offset); 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistatic void rspi_write16(const struct rspi_data *rspi, u16 data, u16 offset) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci iowrite16(data, rspi->addr + offset); 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic void rspi_write32(const struct rspi_data *rspi, u32 data, u16 offset) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci iowrite32(data, rspi->addr + offset); 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic u8 rspi_read8(const struct rspi_data *rspi, u16 offset) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci return ioread8(rspi->addr + offset); 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic u16 rspi_read16(const struct rspi_data *rspi, u16 offset) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci return ioread16(rspi->addr + offset); 2228c2ecf20Sopenharmony_ci} 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_cistatic void rspi_write_data(const struct rspi_data *rspi, u16 data) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci if (rspi->byte_access) 2278c2ecf20Sopenharmony_ci rspi_write8(rspi, data, RSPI_SPDR); 2288c2ecf20Sopenharmony_ci else /* 16 bit */ 2298c2ecf20Sopenharmony_ci rspi_write16(rspi, data, RSPI_SPDR); 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic u16 rspi_read_data(const struct rspi_data *rspi) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci if (rspi->byte_access) 2358c2ecf20Sopenharmony_ci return rspi_read8(rspi, RSPI_SPDR); 2368c2ecf20Sopenharmony_ci else /* 16 bit */ 2378c2ecf20Sopenharmony_ci return rspi_read16(rspi, RSPI_SPDR); 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci/* optional functions */ 2418c2ecf20Sopenharmony_cistruct spi_ops { 2428c2ecf20Sopenharmony_ci int (*set_config_register)(struct rspi_data *rspi, int access_size); 2438c2ecf20Sopenharmony_ci int (*transfer_one)(struct spi_controller *ctlr, 2448c2ecf20Sopenharmony_ci struct spi_device *spi, struct spi_transfer *xfer); 2458c2ecf20Sopenharmony_ci u16 extra_mode_bits; 2468c2ecf20Sopenharmony_ci u16 min_div; 2478c2ecf20Sopenharmony_ci u16 max_div; 2488c2ecf20Sopenharmony_ci u16 flags; 2498c2ecf20Sopenharmony_ci u16 fifo_size; 2508c2ecf20Sopenharmony_ci u8 num_hw_ss; 2518c2ecf20Sopenharmony_ci}; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic void rspi_set_rate(struct rspi_data *rspi) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci unsigned long clksrc; 2568c2ecf20Sopenharmony_ci int brdv = 0, spbr; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci clksrc = clk_get_rate(rspi->clk); 2598c2ecf20Sopenharmony_ci spbr = DIV_ROUND_UP(clksrc, 2 * rspi->speed_hz) - 1; 2608c2ecf20Sopenharmony_ci while (spbr > 255 && brdv < 3) { 2618c2ecf20Sopenharmony_ci brdv++; 2628c2ecf20Sopenharmony_ci spbr = DIV_ROUND_UP(spbr + 1, 2) - 1; 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); 2668c2ecf20Sopenharmony_ci rspi->spcmd |= SPCMD_BRDV(brdv); 2678c2ecf20Sopenharmony_ci rspi->speed_hz = DIV_ROUND_UP(clksrc, (2U << brdv) * (spbr + 1)); 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci/* 2718c2ecf20Sopenharmony_ci * functions for RSPI on legacy SH 2728c2ecf20Sopenharmony_ci */ 2738c2ecf20Sopenharmony_cistatic int rspi_set_config_register(struct rspi_data *rspi, int access_size) 2748c2ecf20Sopenharmony_ci{ 2758c2ecf20Sopenharmony_ci /* Sets output mode, MOSI signal, and (optionally) loopback */ 2768c2ecf20Sopenharmony_ci rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci /* Sets transfer bit rate */ 2798c2ecf20Sopenharmony_ci rspi_set_rate(rspi); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci /* Disable dummy transmission, set 16-bit word access, 1 frame */ 2828c2ecf20Sopenharmony_ci rspi_write8(rspi, 0, RSPI_SPDCR); 2838c2ecf20Sopenharmony_ci rspi->byte_access = 0; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci /* Sets RSPCK, SSL, next-access delay value */ 2868c2ecf20Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SPCKD); 2878c2ecf20Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SSLND); 2888c2ecf20Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SPND); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* Sets parity, interrupt mask */ 2918c2ecf20Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SPCR2); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* Resets sequencer */ 2948c2ecf20Sopenharmony_ci rspi_write8(rspi, 0, RSPI_SPSCR); 2958c2ecf20Sopenharmony_ci rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size); 2968c2ecf20Sopenharmony_ci rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci /* Sets RSPI mode */ 2998c2ecf20Sopenharmony_ci rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci return 0; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci/* 3058c2ecf20Sopenharmony_ci * functions for RSPI on RZ 3068c2ecf20Sopenharmony_ci */ 3078c2ecf20Sopenharmony_cistatic int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci /* Sets output mode, MOSI signal, and (optionally) loopback */ 3108c2ecf20Sopenharmony_ci rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci /* Sets transfer bit rate */ 3138c2ecf20Sopenharmony_ci rspi_set_rate(rspi); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci /* Disable dummy transmission, set byte access */ 3168c2ecf20Sopenharmony_ci rspi_write8(rspi, SPDCR_SPLBYTE, RSPI_SPDCR); 3178c2ecf20Sopenharmony_ci rspi->byte_access = 1; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci /* Sets RSPCK, SSL, next-access delay value */ 3208c2ecf20Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SPCKD); 3218c2ecf20Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SSLND); 3228c2ecf20Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SPND); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci /* Resets sequencer */ 3258c2ecf20Sopenharmony_ci rspi_write8(rspi, 0, RSPI_SPSCR); 3268c2ecf20Sopenharmony_ci rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size); 3278c2ecf20Sopenharmony_ci rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci /* Sets RSPI mode */ 3308c2ecf20Sopenharmony_ci rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci return 0; 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci/* 3368c2ecf20Sopenharmony_ci * functions for QSPI 3378c2ecf20Sopenharmony_ci */ 3388c2ecf20Sopenharmony_cistatic int qspi_set_config_register(struct rspi_data *rspi, int access_size) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci unsigned long clksrc; 3418c2ecf20Sopenharmony_ci int brdv = 0, spbr; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci /* Sets output mode, MOSI signal, and (optionally) loopback */ 3448c2ecf20Sopenharmony_ci rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci /* Sets transfer bit rate */ 3478c2ecf20Sopenharmony_ci clksrc = clk_get_rate(rspi->clk); 3488c2ecf20Sopenharmony_ci if (rspi->speed_hz >= clksrc) { 3498c2ecf20Sopenharmony_ci spbr = 0; 3508c2ecf20Sopenharmony_ci rspi->speed_hz = clksrc; 3518c2ecf20Sopenharmony_ci } else { 3528c2ecf20Sopenharmony_ci spbr = DIV_ROUND_UP(clksrc, 2 * rspi->speed_hz); 3538c2ecf20Sopenharmony_ci while (spbr > 255 && brdv < 3) { 3548c2ecf20Sopenharmony_ci brdv++; 3558c2ecf20Sopenharmony_ci spbr = DIV_ROUND_UP(spbr, 2); 3568c2ecf20Sopenharmony_ci } 3578c2ecf20Sopenharmony_ci spbr = clamp(spbr, 0, 255); 3588c2ecf20Sopenharmony_ci rspi->speed_hz = DIV_ROUND_UP(clksrc, (2U << brdv) * spbr); 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci rspi_write8(rspi, spbr, RSPI_SPBR); 3618c2ecf20Sopenharmony_ci rspi->spcmd |= SPCMD_BRDV(brdv); 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci /* Disable dummy transmission, set byte access */ 3648c2ecf20Sopenharmony_ci rspi_write8(rspi, 0, RSPI_SPDCR); 3658c2ecf20Sopenharmony_ci rspi->byte_access = 1; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci /* Sets RSPCK, SSL, next-access delay value */ 3688c2ecf20Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SPCKD); 3698c2ecf20Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SSLND); 3708c2ecf20Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SPND); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci /* Data Length Setting */ 3738c2ecf20Sopenharmony_ci if (access_size == 8) 3748c2ecf20Sopenharmony_ci rspi->spcmd |= SPCMD_SPB_8BIT; 3758c2ecf20Sopenharmony_ci else if (access_size == 16) 3768c2ecf20Sopenharmony_ci rspi->spcmd |= SPCMD_SPB_16BIT; 3778c2ecf20Sopenharmony_ci else 3788c2ecf20Sopenharmony_ci rspi->spcmd |= SPCMD_SPB_32BIT; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci rspi->spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SPNDEN; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci /* Resets transfer data length */ 3838c2ecf20Sopenharmony_ci rspi_write32(rspi, 0, QSPI_SPBMUL0); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci /* Resets transmit and receive buffer */ 3868c2ecf20Sopenharmony_ci rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR); 3878c2ecf20Sopenharmony_ci /* Sets buffer to allow normal operation */ 3888c2ecf20Sopenharmony_ci rspi_write8(rspi, 0x00, QSPI_SPBFCR); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci /* Resets sequencer */ 3918c2ecf20Sopenharmony_ci rspi_write8(rspi, 0, RSPI_SPSCR); 3928c2ecf20Sopenharmony_ci rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /* Sets RSPI mode */ 3958c2ecf20Sopenharmony_ci rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci return 0; 3988c2ecf20Sopenharmony_ci} 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_cistatic void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg) 4018c2ecf20Sopenharmony_ci{ 4028c2ecf20Sopenharmony_ci u8 data; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci data = rspi_read8(rspi, reg); 4058c2ecf20Sopenharmony_ci data &= ~mask; 4068c2ecf20Sopenharmony_ci data |= (val & mask); 4078c2ecf20Sopenharmony_ci rspi_write8(rspi, data, reg); 4088c2ecf20Sopenharmony_ci} 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cistatic unsigned int qspi_set_send_trigger(struct rspi_data *rspi, 4118c2ecf20Sopenharmony_ci unsigned int len) 4128c2ecf20Sopenharmony_ci{ 4138c2ecf20Sopenharmony_ci unsigned int n; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci n = min(len, QSPI_BUFFER_SIZE); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci if (len >= QSPI_BUFFER_SIZE) { 4188c2ecf20Sopenharmony_ci /* sets triggering number to 32 bytes */ 4198c2ecf20Sopenharmony_ci qspi_update(rspi, SPBFCR_TXTRG_MASK, 4208c2ecf20Sopenharmony_ci SPBFCR_TXTRG_32B, QSPI_SPBFCR); 4218c2ecf20Sopenharmony_ci } else { 4228c2ecf20Sopenharmony_ci /* sets triggering number to 1 byte */ 4238c2ecf20Sopenharmony_ci qspi_update(rspi, SPBFCR_TXTRG_MASK, 4248c2ecf20Sopenharmony_ci SPBFCR_TXTRG_1B, QSPI_SPBFCR); 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci return n; 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_cistatic int qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci unsigned int n; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci n = min(len, QSPI_BUFFER_SIZE); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci if (len >= QSPI_BUFFER_SIZE) { 4378c2ecf20Sopenharmony_ci /* sets triggering number to 32 bytes */ 4388c2ecf20Sopenharmony_ci qspi_update(rspi, SPBFCR_RXTRG_MASK, 4398c2ecf20Sopenharmony_ci SPBFCR_RXTRG_32B, QSPI_SPBFCR); 4408c2ecf20Sopenharmony_ci } else { 4418c2ecf20Sopenharmony_ci /* sets triggering number to 1 byte */ 4428c2ecf20Sopenharmony_ci qspi_update(rspi, SPBFCR_RXTRG_MASK, 4438c2ecf20Sopenharmony_ci SPBFCR_RXTRG_1B, QSPI_SPBFCR); 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci return n; 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_cistatic void rspi_enable_irq(const struct rspi_data *rspi, u8 enable) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR); 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_cistatic void rspi_disable_irq(const struct rspi_data *rspi, u8 disable) 4548c2ecf20Sopenharmony_ci{ 4558c2ecf20Sopenharmony_ci rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~disable, RSPI_SPCR); 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_cistatic int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask, 4598c2ecf20Sopenharmony_ci u8 enable_bit) 4608c2ecf20Sopenharmony_ci{ 4618c2ecf20Sopenharmony_ci int ret; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci rspi->spsr = rspi_read8(rspi, RSPI_SPSR); 4648c2ecf20Sopenharmony_ci if (rspi->spsr & wait_mask) 4658c2ecf20Sopenharmony_ci return 0; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci rspi_enable_irq(rspi, enable_bit); 4688c2ecf20Sopenharmony_ci ret = wait_event_timeout(rspi->wait, rspi->spsr & wait_mask, HZ); 4698c2ecf20Sopenharmony_ci if (ret == 0 && !(rspi->spsr & wait_mask)) 4708c2ecf20Sopenharmony_ci return -ETIMEDOUT; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci return 0; 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic inline int rspi_wait_for_tx_empty(struct rspi_data *rspi) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci return rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); 4788c2ecf20Sopenharmony_ci} 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_cistatic inline int rspi_wait_for_rx_full(struct rspi_data *rspi) 4818c2ecf20Sopenharmony_ci{ 4828c2ecf20Sopenharmony_ci return rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE); 4838c2ecf20Sopenharmony_ci} 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistatic int rspi_data_out(struct rspi_data *rspi, u8 data) 4868c2ecf20Sopenharmony_ci{ 4878c2ecf20Sopenharmony_ci int error = rspi_wait_for_tx_empty(rspi); 4888c2ecf20Sopenharmony_ci if (error < 0) { 4898c2ecf20Sopenharmony_ci dev_err(&rspi->ctlr->dev, "transmit timeout\n"); 4908c2ecf20Sopenharmony_ci return error; 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci rspi_write_data(rspi, data); 4938c2ecf20Sopenharmony_ci return 0; 4948c2ecf20Sopenharmony_ci} 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_cistatic int rspi_data_in(struct rspi_data *rspi) 4978c2ecf20Sopenharmony_ci{ 4988c2ecf20Sopenharmony_ci int error; 4998c2ecf20Sopenharmony_ci u8 data; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci error = rspi_wait_for_rx_full(rspi); 5028c2ecf20Sopenharmony_ci if (error < 0) { 5038c2ecf20Sopenharmony_ci dev_err(&rspi->ctlr->dev, "receive timeout\n"); 5048c2ecf20Sopenharmony_ci return error; 5058c2ecf20Sopenharmony_ci } 5068c2ecf20Sopenharmony_ci data = rspi_read_data(rspi); 5078c2ecf20Sopenharmony_ci return data; 5088c2ecf20Sopenharmony_ci} 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_cistatic int rspi_pio_transfer(struct rspi_data *rspi, const u8 *tx, u8 *rx, 5118c2ecf20Sopenharmony_ci unsigned int n) 5128c2ecf20Sopenharmony_ci{ 5138c2ecf20Sopenharmony_ci while (n-- > 0) { 5148c2ecf20Sopenharmony_ci if (tx) { 5158c2ecf20Sopenharmony_ci int ret = rspi_data_out(rspi, *tx++); 5168c2ecf20Sopenharmony_ci if (ret < 0) 5178c2ecf20Sopenharmony_ci return ret; 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci if (rx) { 5208c2ecf20Sopenharmony_ci int ret = rspi_data_in(rspi); 5218c2ecf20Sopenharmony_ci if (ret < 0) 5228c2ecf20Sopenharmony_ci return ret; 5238c2ecf20Sopenharmony_ci *rx++ = ret; 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci return 0; 5288c2ecf20Sopenharmony_ci} 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_cistatic void rspi_dma_complete(void *arg) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci struct rspi_data *rspi = arg; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci rspi->dma_callbacked = 1; 5358c2ecf20Sopenharmony_ci wake_up_interruptible(&rspi->wait); 5368c2ecf20Sopenharmony_ci} 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_cistatic int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, 5398c2ecf20Sopenharmony_ci struct sg_table *rx) 5408c2ecf20Sopenharmony_ci{ 5418c2ecf20Sopenharmony_ci struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL; 5428c2ecf20Sopenharmony_ci u8 irq_mask = 0; 5438c2ecf20Sopenharmony_ci unsigned int other_irq = 0; 5448c2ecf20Sopenharmony_ci dma_cookie_t cookie; 5458c2ecf20Sopenharmony_ci int ret; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci /* First prepare and submit the DMA request(s), as this may fail */ 5488c2ecf20Sopenharmony_ci if (rx) { 5498c2ecf20Sopenharmony_ci desc_rx = dmaengine_prep_slave_sg(rspi->ctlr->dma_rx, rx->sgl, 5508c2ecf20Sopenharmony_ci rx->nents, DMA_DEV_TO_MEM, 5518c2ecf20Sopenharmony_ci DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 5528c2ecf20Sopenharmony_ci if (!desc_rx) { 5538c2ecf20Sopenharmony_ci ret = -EAGAIN; 5548c2ecf20Sopenharmony_ci goto no_dma_rx; 5558c2ecf20Sopenharmony_ci } 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci desc_rx->callback = rspi_dma_complete; 5588c2ecf20Sopenharmony_ci desc_rx->callback_param = rspi; 5598c2ecf20Sopenharmony_ci cookie = dmaengine_submit(desc_rx); 5608c2ecf20Sopenharmony_ci if (dma_submit_error(cookie)) { 5618c2ecf20Sopenharmony_ci ret = cookie; 5628c2ecf20Sopenharmony_ci goto no_dma_rx; 5638c2ecf20Sopenharmony_ci } 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci irq_mask |= SPCR_SPRIE; 5668c2ecf20Sopenharmony_ci } 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci if (tx) { 5698c2ecf20Sopenharmony_ci desc_tx = dmaengine_prep_slave_sg(rspi->ctlr->dma_tx, tx->sgl, 5708c2ecf20Sopenharmony_ci tx->nents, DMA_MEM_TO_DEV, 5718c2ecf20Sopenharmony_ci DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 5728c2ecf20Sopenharmony_ci if (!desc_tx) { 5738c2ecf20Sopenharmony_ci ret = -EAGAIN; 5748c2ecf20Sopenharmony_ci goto no_dma_tx; 5758c2ecf20Sopenharmony_ci } 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci if (rx) { 5788c2ecf20Sopenharmony_ci /* No callback */ 5798c2ecf20Sopenharmony_ci desc_tx->callback = NULL; 5808c2ecf20Sopenharmony_ci } else { 5818c2ecf20Sopenharmony_ci desc_tx->callback = rspi_dma_complete; 5828c2ecf20Sopenharmony_ci desc_tx->callback_param = rspi; 5838c2ecf20Sopenharmony_ci } 5848c2ecf20Sopenharmony_ci cookie = dmaengine_submit(desc_tx); 5858c2ecf20Sopenharmony_ci if (dma_submit_error(cookie)) { 5868c2ecf20Sopenharmony_ci ret = cookie; 5878c2ecf20Sopenharmony_ci goto no_dma_tx; 5888c2ecf20Sopenharmony_ci } 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci irq_mask |= SPCR_SPTIE; 5918c2ecf20Sopenharmony_ci } 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci /* 5948c2ecf20Sopenharmony_ci * DMAC needs SPxIE, but if SPxIE is set, the IRQ routine will be 5958c2ecf20Sopenharmony_ci * called. So, this driver disables the IRQ while DMA transfer. 5968c2ecf20Sopenharmony_ci */ 5978c2ecf20Sopenharmony_ci if (tx) 5988c2ecf20Sopenharmony_ci disable_irq(other_irq = rspi->tx_irq); 5998c2ecf20Sopenharmony_ci if (rx && rspi->rx_irq != other_irq) 6008c2ecf20Sopenharmony_ci disable_irq(rspi->rx_irq); 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci rspi_enable_irq(rspi, irq_mask); 6038c2ecf20Sopenharmony_ci rspi->dma_callbacked = 0; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci /* Now start DMA */ 6068c2ecf20Sopenharmony_ci if (rx) 6078c2ecf20Sopenharmony_ci dma_async_issue_pending(rspi->ctlr->dma_rx); 6088c2ecf20Sopenharmony_ci if (tx) 6098c2ecf20Sopenharmony_ci dma_async_issue_pending(rspi->ctlr->dma_tx); 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci ret = wait_event_interruptible_timeout(rspi->wait, 6128c2ecf20Sopenharmony_ci rspi->dma_callbacked, HZ); 6138c2ecf20Sopenharmony_ci if (ret > 0 && rspi->dma_callbacked) { 6148c2ecf20Sopenharmony_ci ret = 0; 6158c2ecf20Sopenharmony_ci if (tx) 6168c2ecf20Sopenharmony_ci dmaengine_synchronize(rspi->ctlr->dma_tx); 6178c2ecf20Sopenharmony_ci if (rx) 6188c2ecf20Sopenharmony_ci dmaengine_synchronize(rspi->ctlr->dma_rx); 6198c2ecf20Sopenharmony_ci } else { 6208c2ecf20Sopenharmony_ci if (!ret) { 6218c2ecf20Sopenharmony_ci dev_err(&rspi->ctlr->dev, "DMA timeout\n"); 6228c2ecf20Sopenharmony_ci ret = -ETIMEDOUT; 6238c2ecf20Sopenharmony_ci } 6248c2ecf20Sopenharmony_ci if (tx) 6258c2ecf20Sopenharmony_ci dmaengine_terminate_all(rspi->ctlr->dma_tx); 6268c2ecf20Sopenharmony_ci if (rx) 6278c2ecf20Sopenharmony_ci dmaengine_terminate_all(rspi->ctlr->dma_rx); 6288c2ecf20Sopenharmony_ci } 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci rspi_disable_irq(rspi, irq_mask); 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci if (tx) 6338c2ecf20Sopenharmony_ci enable_irq(rspi->tx_irq); 6348c2ecf20Sopenharmony_ci if (rx && rspi->rx_irq != other_irq) 6358c2ecf20Sopenharmony_ci enable_irq(rspi->rx_irq); 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci return ret; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_cino_dma_tx: 6408c2ecf20Sopenharmony_ci if (rx) 6418c2ecf20Sopenharmony_ci dmaengine_terminate_all(rspi->ctlr->dma_rx); 6428c2ecf20Sopenharmony_cino_dma_rx: 6438c2ecf20Sopenharmony_ci if (ret == -EAGAIN) { 6448c2ecf20Sopenharmony_ci dev_warn_once(&rspi->ctlr->dev, 6458c2ecf20Sopenharmony_ci "DMA not available, falling back to PIO\n"); 6468c2ecf20Sopenharmony_ci } 6478c2ecf20Sopenharmony_ci return ret; 6488c2ecf20Sopenharmony_ci} 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_cistatic void rspi_receive_init(const struct rspi_data *rspi) 6518c2ecf20Sopenharmony_ci{ 6528c2ecf20Sopenharmony_ci u8 spsr; 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci spsr = rspi_read8(rspi, RSPI_SPSR); 6558c2ecf20Sopenharmony_ci if (spsr & SPSR_SPRF) 6568c2ecf20Sopenharmony_ci rspi_read_data(rspi); /* dummy read */ 6578c2ecf20Sopenharmony_ci if (spsr & SPSR_OVRF) 6588c2ecf20Sopenharmony_ci rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF, 6598c2ecf20Sopenharmony_ci RSPI_SPSR); 6608c2ecf20Sopenharmony_ci} 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_cistatic void rspi_rz_receive_init(const struct rspi_data *rspi) 6638c2ecf20Sopenharmony_ci{ 6648c2ecf20Sopenharmony_ci rspi_receive_init(rspi); 6658c2ecf20Sopenharmony_ci rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, RSPI_SPBFCR); 6668c2ecf20Sopenharmony_ci rspi_write8(rspi, 0, RSPI_SPBFCR); 6678c2ecf20Sopenharmony_ci} 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_cistatic void qspi_receive_init(const struct rspi_data *rspi) 6708c2ecf20Sopenharmony_ci{ 6718c2ecf20Sopenharmony_ci u8 spsr; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci spsr = rspi_read8(rspi, RSPI_SPSR); 6748c2ecf20Sopenharmony_ci if (spsr & SPSR_SPRF) 6758c2ecf20Sopenharmony_ci rspi_read_data(rspi); /* dummy read */ 6768c2ecf20Sopenharmony_ci rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR); 6778c2ecf20Sopenharmony_ci rspi_write8(rspi, 0, QSPI_SPBFCR); 6788c2ecf20Sopenharmony_ci} 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_cistatic bool __rspi_can_dma(const struct rspi_data *rspi, 6818c2ecf20Sopenharmony_ci const struct spi_transfer *xfer) 6828c2ecf20Sopenharmony_ci{ 6838c2ecf20Sopenharmony_ci return xfer->len > rspi->ops->fifo_size; 6848c2ecf20Sopenharmony_ci} 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_cistatic bool rspi_can_dma(struct spi_controller *ctlr, struct spi_device *spi, 6878c2ecf20Sopenharmony_ci struct spi_transfer *xfer) 6888c2ecf20Sopenharmony_ci{ 6898c2ecf20Sopenharmony_ci struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci return __rspi_can_dma(rspi, xfer); 6928c2ecf20Sopenharmony_ci} 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_cistatic int rspi_dma_check_then_transfer(struct rspi_data *rspi, 6958c2ecf20Sopenharmony_ci struct spi_transfer *xfer) 6968c2ecf20Sopenharmony_ci{ 6978c2ecf20Sopenharmony_ci if (!rspi->ctlr->can_dma || !__rspi_can_dma(rspi, xfer)) 6988c2ecf20Sopenharmony_ci return -EAGAIN; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci /* rx_buf can be NULL on RSPI on SH in TX-only Mode */ 7018c2ecf20Sopenharmony_ci return rspi_dma_transfer(rspi, &xfer->tx_sg, 7028c2ecf20Sopenharmony_ci xfer->rx_buf ? &xfer->rx_sg : NULL); 7038c2ecf20Sopenharmony_ci} 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_cistatic int rspi_common_transfer(struct rspi_data *rspi, 7068c2ecf20Sopenharmony_ci struct spi_transfer *xfer) 7078c2ecf20Sopenharmony_ci{ 7088c2ecf20Sopenharmony_ci int ret; 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci xfer->effective_speed_hz = rspi->speed_hz; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci ret = rspi_dma_check_then_transfer(rspi, xfer); 7138c2ecf20Sopenharmony_ci if (ret != -EAGAIN) 7148c2ecf20Sopenharmony_ci return ret; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len); 7178c2ecf20Sopenharmony_ci if (ret < 0) 7188c2ecf20Sopenharmony_ci return ret; 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci /* Wait for the last transmission */ 7218c2ecf20Sopenharmony_ci rspi_wait_for_tx_empty(rspi); 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci return 0; 7248c2ecf20Sopenharmony_ci} 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_cistatic int rspi_transfer_one(struct spi_controller *ctlr, 7278c2ecf20Sopenharmony_ci struct spi_device *spi, struct spi_transfer *xfer) 7288c2ecf20Sopenharmony_ci{ 7298c2ecf20Sopenharmony_ci struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 7308c2ecf20Sopenharmony_ci u8 spcr; 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci spcr = rspi_read8(rspi, RSPI_SPCR); 7338c2ecf20Sopenharmony_ci if (xfer->rx_buf) { 7348c2ecf20Sopenharmony_ci rspi_receive_init(rspi); 7358c2ecf20Sopenharmony_ci spcr &= ~SPCR_TXMD; 7368c2ecf20Sopenharmony_ci } else { 7378c2ecf20Sopenharmony_ci spcr |= SPCR_TXMD; 7388c2ecf20Sopenharmony_ci } 7398c2ecf20Sopenharmony_ci rspi_write8(rspi, spcr, RSPI_SPCR); 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci return rspi_common_transfer(rspi, xfer); 7428c2ecf20Sopenharmony_ci} 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_cistatic int rspi_rz_transfer_one(struct spi_controller *ctlr, 7458c2ecf20Sopenharmony_ci struct spi_device *spi, 7468c2ecf20Sopenharmony_ci struct spi_transfer *xfer) 7478c2ecf20Sopenharmony_ci{ 7488c2ecf20Sopenharmony_ci struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci rspi_rz_receive_init(rspi); 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci return rspi_common_transfer(rspi, xfer); 7538c2ecf20Sopenharmony_ci} 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_cistatic int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx, 7568c2ecf20Sopenharmony_ci u8 *rx, unsigned int len) 7578c2ecf20Sopenharmony_ci{ 7588c2ecf20Sopenharmony_ci unsigned int i, n; 7598c2ecf20Sopenharmony_ci int ret; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci while (len > 0) { 7628c2ecf20Sopenharmony_ci n = qspi_set_send_trigger(rspi, len); 7638c2ecf20Sopenharmony_ci qspi_set_receive_trigger(rspi, len); 7648c2ecf20Sopenharmony_ci ret = rspi_wait_for_tx_empty(rspi); 7658c2ecf20Sopenharmony_ci if (ret < 0) { 7668c2ecf20Sopenharmony_ci dev_err(&rspi->ctlr->dev, "transmit timeout\n"); 7678c2ecf20Sopenharmony_ci return ret; 7688c2ecf20Sopenharmony_ci } 7698c2ecf20Sopenharmony_ci for (i = 0; i < n; i++) 7708c2ecf20Sopenharmony_ci rspi_write_data(rspi, *tx++); 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci ret = rspi_wait_for_rx_full(rspi); 7738c2ecf20Sopenharmony_ci if (ret < 0) { 7748c2ecf20Sopenharmony_ci dev_err(&rspi->ctlr->dev, "receive timeout\n"); 7758c2ecf20Sopenharmony_ci return ret; 7768c2ecf20Sopenharmony_ci } 7778c2ecf20Sopenharmony_ci for (i = 0; i < n; i++) 7788c2ecf20Sopenharmony_ci *rx++ = rspi_read_data(rspi); 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci len -= n; 7818c2ecf20Sopenharmony_ci } 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci return 0; 7848c2ecf20Sopenharmony_ci} 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_cistatic int qspi_transfer_out_in(struct rspi_data *rspi, 7878c2ecf20Sopenharmony_ci struct spi_transfer *xfer) 7888c2ecf20Sopenharmony_ci{ 7898c2ecf20Sopenharmony_ci int ret; 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci qspi_receive_init(rspi); 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci ret = rspi_dma_check_then_transfer(rspi, xfer); 7948c2ecf20Sopenharmony_ci if (ret != -EAGAIN) 7958c2ecf20Sopenharmony_ci return ret; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci return qspi_trigger_transfer_out_in(rspi, xfer->tx_buf, 7988c2ecf20Sopenharmony_ci xfer->rx_buf, xfer->len); 7998c2ecf20Sopenharmony_ci} 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_cistatic int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) 8028c2ecf20Sopenharmony_ci{ 8038c2ecf20Sopenharmony_ci const u8 *tx = xfer->tx_buf; 8048c2ecf20Sopenharmony_ci unsigned int n = xfer->len; 8058c2ecf20Sopenharmony_ci unsigned int i, len; 8068c2ecf20Sopenharmony_ci int ret; 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci if (rspi->ctlr->can_dma && __rspi_can_dma(rspi, xfer)) { 8098c2ecf20Sopenharmony_ci ret = rspi_dma_transfer(rspi, &xfer->tx_sg, NULL); 8108c2ecf20Sopenharmony_ci if (ret != -EAGAIN) 8118c2ecf20Sopenharmony_ci return ret; 8128c2ecf20Sopenharmony_ci } 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci while (n > 0) { 8158c2ecf20Sopenharmony_ci len = qspi_set_send_trigger(rspi, n); 8168c2ecf20Sopenharmony_ci ret = rspi_wait_for_tx_empty(rspi); 8178c2ecf20Sopenharmony_ci if (ret < 0) { 8188c2ecf20Sopenharmony_ci dev_err(&rspi->ctlr->dev, "transmit timeout\n"); 8198c2ecf20Sopenharmony_ci return ret; 8208c2ecf20Sopenharmony_ci } 8218c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) 8228c2ecf20Sopenharmony_ci rspi_write_data(rspi, *tx++); 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci n -= len; 8258c2ecf20Sopenharmony_ci } 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci /* Wait for the last transmission */ 8288c2ecf20Sopenharmony_ci rspi_wait_for_tx_empty(rspi); 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci return 0; 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_cistatic int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) 8348c2ecf20Sopenharmony_ci{ 8358c2ecf20Sopenharmony_ci u8 *rx = xfer->rx_buf; 8368c2ecf20Sopenharmony_ci unsigned int n = xfer->len; 8378c2ecf20Sopenharmony_ci unsigned int i, len; 8388c2ecf20Sopenharmony_ci int ret; 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci if (rspi->ctlr->can_dma && __rspi_can_dma(rspi, xfer)) { 8418c2ecf20Sopenharmony_ci int ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg); 8428c2ecf20Sopenharmony_ci if (ret != -EAGAIN) 8438c2ecf20Sopenharmony_ci return ret; 8448c2ecf20Sopenharmony_ci } 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci while (n > 0) { 8478c2ecf20Sopenharmony_ci len = qspi_set_receive_trigger(rspi, n); 8488c2ecf20Sopenharmony_ci ret = rspi_wait_for_rx_full(rspi); 8498c2ecf20Sopenharmony_ci if (ret < 0) { 8508c2ecf20Sopenharmony_ci dev_err(&rspi->ctlr->dev, "receive timeout\n"); 8518c2ecf20Sopenharmony_ci return ret; 8528c2ecf20Sopenharmony_ci } 8538c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) 8548c2ecf20Sopenharmony_ci *rx++ = rspi_read_data(rspi); 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci n -= len; 8578c2ecf20Sopenharmony_ci } 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci return 0; 8608c2ecf20Sopenharmony_ci} 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_cistatic int qspi_transfer_one(struct spi_controller *ctlr, 8638c2ecf20Sopenharmony_ci struct spi_device *spi, struct spi_transfer *xfer) 8648c2ecf20Sopenharmony_ci{ 8658c2ecf20Sopenharmony_ci struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci xfer->effective_speed_hz = rspi->speed_hz; 8688c2ecf20Sopenharmony_ci if (spi->mode & SPI_LOOP) { 8698c2ecf20Sopenharmony_ci return qspi_transfer_out_in(rspi, xfer); 8708c2ecf20Sopenharmony_ci } else if (xfer->tx_nbits > SPI_NBITS_SINGLE) { 8718c2ecf20Sopenharmony_ci /* Quad or Dual SPI Write */ 8728c2ecf20Sopenharmony_ci return qspi_transfer_out(rspi, xfer); 8738c2ecf20Sopenharmony_ci } else if (xfer->rx_nbits > SPI_NBITS_SINGLE) { 8748c2ecf20Sopenharmony_ci /* Quad or Dual SPI Read */ 8758c2ecf20Sopenharmony_ci return qspi_transfer_in(rspi, xfer); 8768c2ecf20Sopenharmony_ci } else { 8778c2ecf20Sopenharmony_ci /* Single SPI Transfer */ 8788c2ecf20Sopenharmony_ci return qspi_transfer_out_in(rspi, xfer); 8798c2ecf20Sopenharmony_ci } 8808c2ecf20Sopenharmony_ci} 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_cistatic u16 qspi_transfer_mode(const struct spi_transfer *xfer) 8838c2ecf20Sopenharmony_ci{ 8848c2ecf20Sopenharmony_ci if (xfer->tx_buf) 8858c2ecf20Sopenharmony_ci switch (xfer->tx_nbits) { 8868c2ecf20Sopenharmony_ci case SPI_NBITS_QUAD: 8878c2ecf20Sopenharmony_ci return SPCMD_SPIMOD_QUAD; 8888c2ecf20Sopenharmony_ci case SPI_NBITS_DUAL: 8898c2ecf20Sopenharmony_ci return SPCMD_SPIMOD_DUAL; 8908c2ecf20Sopenharmony_ci default: 8918c2ecf20Sopenharmony_ci return 0; 8928c2ecf20Sopenharmony_ci } 8938c2ecf20Sopenharmony_ci if (xfer->rx_buf) 8948c2ecf20Sopenharmony_ci switch (xfer->rx_nbits) { 8958c2ecf20Sopenharmony_ci case SPI_NBITS_QUAD: 8968c2ecf20Sopenharmony_ci return SPCMD_SPIMOD_QUAD | SPCMD_SPRW; 8978c2ecf20Sopenharmony_ci case SPI_NBITS_DUAL: 8988c2ecf20Sopenharmony_ci return SPCMD_SPIMOD_DUAL | SPCMD_SPRW; 8998c2ecf20Sopenharmony_ci default: 9008c2ecf20Sopenharmony_ci return 0; 9018c2ecf20Sopenharmony_ci } 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci return 0; 9048c2ecf20Sopenharmony_ci} 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_cistatic int qspi_setup_sequencer(struct rspi_data *rspi, 9078c2ecf20Sopenharmony_ci const struct spi_message *msg) 9088c2ecf20Sopenharmony_ci{ 9098c2ecf20Sopenharmony_ci const struct spi_transfer *xfer; 9108c2ecf20Sopenharmony_ci unsigned int i = 0, len = 0; 9118c2ecf20Sopenharmony_ci u16 current_mode = 0xffff, mode; 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci list_for_each_entry(xfer, &msg->transfers, transfer_list) { 9148c2ecf20Sopenharmony_ci mode = qspi_transfer_mode(xfer); 9158c2ecf20Sopenharmony_ci if (mode == current_mode) { 9168c2ecf20Sopenharmony_ci len += xfer->len; 9178c2ecf20Sopenharmony_ci continue; 9188c2ecf20Sopenharmony_ci } 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci /* Transfer mode change */ 9218c2ecf20Sopenharmony_ci if (i) { 9228c2ecf20Sopenharmony_ci /* Set transfer data length of previous transfer */ 9238c2ecf20Sopenharmony_ci rspi_write32(rspi, len, QSPI_SPBMUL(i - 1)); 9248c2ecf20Sopenharmony_ci } 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci if (i >= QSPI_NUM_SPCMD) { 9278c2ecf20Sopenharmony_ci dev_err(&msg->spi->dev, 9288c2ecf20Sopenharmony_ci "Too many different transfer modes"); 9298c2ecf20Sopenharmony_ci return -EINVAL; 9308c2ecf20Sopenharmony_ci } 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci /* Program transfer mode for this transfer */ 9338c2ecf20Sopenharmony_ci rspi_write16(rspi, rspi->spcmd | mode, RSPI_SPCMD(i)); 9348c2ecf20Sopenharmony_ci current_mode = mode; 9358c2ecf20Sopenharmony_ci len = xfer->len; 9368c2ecf20Sopenharmony_ci i++; 9378c2ecf20Sopenharmony_ci } 9388c2ecf20Sopenharmony_ci if (i) { 9398c2ecf20Sopenharmony_ci /* Set final transfer data length and sequence length */ 9408c2ecf20Sopenharmony_ci rspi_write32(rspi, len, QSPI_SPBMUL(i - 1)); 9418c2ecf20Sopenharmony_ci rspi_write8(rspi, i - 1, RSPI_SPSCR); 9428c2ecf20Sopenharmony_ci } 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci return 0; 9458c2ecf20Sopenharmony_ci} 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_cistatic int rspi_setup(struct spi_device *spi) 9488c2ecf20Sopenharmony_ci{ 9498c2ecf20Sopenharmony_ci struct rspi_data *rspi = spi_controller_get_devdata(spi->controller); 9508c2ecf20Sopenharmony_ci u8 sslp; 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci if (spi->cs_gpiod) 9538c2ecf20Sopenharmony_ci return 0; 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci pm_runtime_get_sync(&rspi->pdev->dev); 9568c2ecf20Sopenharmony_ci spin_lock_irq(&rspi->lock); 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci sslp = rspi_read8(rspi, RSPI_SSLP); 9598c2ecf20Sopenharmony_ci if (spi->mode & SPI_CS_HIGH) 9608c2ecf20Sopenharmony_ci sslp |= SSLP_SSLP(spi->chip_select); 9618c2ecf20Sopenharmony_ci else 9628c2ecf20Sopenharmony_ci sslp &= ~SSLP_SSLP(spi->chip_select); 9638c2ecf20Sopenharmony_ci rspi_write8(rspi, sslp, RSPI_SSLP); 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci spin_unlock_irq(&rspi->lock); 9668c2ecf20Sopenharmony_ci pm_runtime_put(&rspi->pdev->dev); 9678c2ecf20Sopenharmony_ci return 0; 9688c2ecf20Sopenharmony_ci} 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_cistatic int rspi_prepare_message(struct spi_controller *ctlr, 9718c2ecf20Sopenharmony_ci struct spi_message *msg) 9728c2ecf20Sopenharmony_ci{ 9738c2ecf20Sopenharmony_ci struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 9748c2ecf20Sopenharmony_ci struct spi_device *spi = msg->spi; 9758c2ecf20Sopenharmony_ci const struct spi_transfer *xfer; 9768c2ecf20Sopenharmony_ci int ret; 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci /* 9798c2ecf20Sopenharmony_ci * As the Bit Rate Register must not be changed while the device is 9808c2ecf20Sopenharmony_ci * active, all transfers in a message must use the same bit rate. 9818c2ecf20Sopenharmony_ci * In theory, the sequencer could be enabled, and each Command Register 9828c2ecf20Sopenharmony_ci * could divide the base bit rate by a different value. 9838c2ecf20Sopenharmony_ci * However, most RSPI variants do not have Transfer Data Length 9848c2ecf20Sopenharmony_ci * Multiplier Setting Registers, so each sequence step would be limited 9858c2ecf20Sopenharmony_ci * to a single word, making this feature unsuitable for large 9868c2ecf20Sopenharmony_ci * transfers, which would gain most from it. 9878c2ecf20Sopenharmony_ci */ 9888c2ecf20Sopenharmony_ci rspi->speed_hz = spi->max_speed_hz; 9898c2ecf20Sopenharmony_ci list_for_each_entry(xfer, &msg->transfers, transfer_list) { 9908c2ecf20Sopenharmony_ci if (xfer->speed_hz < rspi->speed_hz) 9918c2ecf20Sopenharmony_ci rspi->speed_hz = xfer->speed_hz; 9928c2ecf20Sopenharmony_ci } 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci rspi->spcmd = SPCMD_SSLKP; 9958c2ecf20Sopenharmony_ci if (spi->mode & SPI_CPOL) 9968c2ecf20Sopenharmony_ci rspi->spcmd |= SPCMD_CPOL; 9978c2ecf20Sopenharmony_ci if (spi->mode & SPI_CPHA) 9988c2ecf20Sopenharmony_ci rspi->spcmd |= SPCMD_CPHA; 9998c2ecf20Sopenharmony_ci if (spi->mode & SPI_LSB_FIRST) 10008c2ecf20Sopenharmony_ci rspi->spcmd |= SPCMD_LSBF; 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci /* Configure slave signal to assert */ 10038c2ecf20Sopenharmony_ci rspi->spcmd |= SPCMD_SSLA(spi->cs_gpiod ? rspi->ctlr->unused_native_cs 10048c2ecf20Sopenharmony_ci : spi->chip_select); 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci /* CMOS output mode and MOSI signal from previous transfer */ 10078c2ecf20Sopenharmony_ci rspi->sppcr = 0; 10088c2ecf20Sopenharmony_ci if (spi->mode & SPI_LOOP) 10098c2ecf20Sopenharmony_ci rspi->sppcr |= SPPCR_SPLP; 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci rspi->ops->set_config_register(rspi, 8); 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci if (msg->spi->mode & 10148c2ecf20Sopenharmony_ci (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)) { 10158c2ecf20Sopenharmony_ci /* Setup sequencer for messages with multiple transfer modes */ 10168c2ecf20Sopenharmony_ci ret = qspi_setup_sequencer(rspi, msg); 10178c2ecf20Sopenharmony_ci if (ret < 0) 10188c2ecf20Sopenharmony_ci return ret; 10198c2ecf20Sopenharmony_ci } 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci /* Enable SPI function in master mode */ 10228c2ecf20Sopenharmony_ci rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR); 10238c2ecf20Sopenharmony_ci return 0; 10248c2ecf20Sopenharmony_ci} 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_cistatic int rspi_unprepare_message(struct spi_controller *ctlr, 10278c2ecf20Sopenharmony_ci struct spi_message *msg) 10288c2ecf20Sopenharmony_ci{ 10298c2ecf20Sopenharmony_ci struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci /* Disable SPI function */ 10328c2ecf20Sopenharmony_ci rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR); 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci /* Reset sequencer for Single SPI Transfers */ 10358c2ecf20Sopenharmony_ci rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 10368c2ecf20Sopenharmony_ci rspi_write8(rspi, 0, RSPI_SPSCR); 10378c2ecf20Sopenharmony_ci return 0; 10388c2ecf20Sopenharmony_ci} 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_cistatic irqreturn_t rspi_irq_mux(int irq, void *_sr) 10418c2ecf20Sopenharmony_ci{ 10428c2ecf20Sopenharmony_ci struct rspi_data *rspi = _sr; 10438c2ecf20Sopenharmony_ci u8 spsr; 10448c2ecf20Sopenharmony_ci irqreturn_t ret = IRQ_NONE; 10458c2ecf20Sopenharmony_ci u8 disable_irq = 0; 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR); 10488c2ecf20Sopenharmony_ci if (spsr & SPSR_SPRF) 10498c2ecf20Sopenharmony_ci disable_irq |= SPCR_SPRIE; 10508c2ecf20Sopenharmony_ci if (spsr & SPSR_SPTEF) 10518c2ecf20Sopenharmony_ci disable_irq |= SPCR_SPTIE; 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci if (disable_irq) { 10548c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 10558c2ecf20Sopenharmony_ci rspi_disable_irq(rspi, disable_irq); 10568c2ecf20Sopenharmony_ci wake_up(&rspi->wait); 10578c2ecf20Sopenharmony_ci } 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci return ret; 10608c2ecf20Sopenharmony_ci} 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_cistatic irqreturn_t rspi_irq_rx(int irq, void *_sr) 10638c2ecf20Sopenharmony_ci{ 10648c2ecf20Sopenharmony_ci struct rspi_data *rspi = _sr; 10658c2ecf20Sopenharmony_ci u8 spsr; 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR); 10688c2ecf20Sopenharmony_ci if (spsr & SPSR_SPRF) { 10698c2ecf20Sopenharmony_ci rspi_disable_irq(rspi, SPCR_SPRIE); 10708c2ecf20Sopenharmony_ci wake_up(&rspi->wait); 10718c2ecf20Sopenharmony_ci return IRQ_HANDLED; 10728c2ecf20Sopenharmony_ci } 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci return 0; 10758c2ecf20Sopenharmony_ci} 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_cistatic irqreturn_t rspi_irq_tx(int irq, void *_sr) 10788c2ecf20Sopenharmony_ci{ 10798c2ecf20Sopenharmony_ci struct rspi_data *rspi = _sr; 10808c2ecf20Sopenharmony_ci u8 spsr; 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR); 10838c2ecf20Sopenharmony_ci if (spsr & SPSR_SPTEF) { 10848c2ecf20Sopenharmony_ci rspi_disable_irq(rspi, SPCR_SPTIE); 10858c2ecf20Sopenharmony_ci wake_up(&rspi->wait); 10868c2ecf20Sopenharmony_ci return IRQ_HANDLED; 10878c2ecf20Sopenharmony_ci } 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci return 0; 10908c2ecf20Sopenharmony_ci} 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_cistatic struct dma_chan *rspi_request_dma_chan(struct device *dev, 10938c2ecf20Sopenharmony_ci enum dma_transfer_direction dir, 10948c2ecf20Sopenharmony_ci unsigned int id, 10958c2ecf20Sopenharmony_ci dma_addr_t port_addr) 10968c2ecf20Sopenharmony_ci{ 10978c2ecf20Sopenharmony_ci dma_cap_mask_t mask; 10988c2ecf20Sopenharmony_ci struct dma_chan *chan; 10998c2ecf20Sopenharmony_ci struct dma_slave_config cfg; 11008c2ecf20Sopenharmony_ci int ret; 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci dma_cap_zero(mask); 11038c2ecf20Sopenharmony_ci dma_cap_set(DMA_SLAVE, mask); 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, 11068c2ecf20Sopenharmony_ci (void *)(unsigned long)id, dev, 11078c2ecf20Sopenharmony_ci dir == DMA_MEM_TO_DEV ? "tx" : "rx"); 11088c2ecf20Sopenharmony_ci if (!chan) { 11098c2ecf20Sopenharmony_ci dev_warn(dev, "dma_request_slave_channel_compat failed\n"); 11108c2ecf20Sopenharmony_ci return NULL; 11118c2ecf20Sopenharmony_ci } 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ci memset(&cfg, 0, sizeof(cfg)); 11148c2ecf20Sopenharmony_ci cfg.dst_addr = port_addr + RSPI_SPDR; 11158c2ecf20Sopenharmony_ci cfg.src_addr = port_addr + RSPI_SPDR; 11168c2ecf20Sopenharmony_ci cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; 11178c2ecf20Sopenharmony_ci cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; 11188c2ecf20Sopenharmony_ci cfg.direction = dir; 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci ret = dmaengine_slave_config(chan, &cfg); 11218c2ecf20Sopenharmony_ci if (ret) { 11228c2ecf20Sopenharmony_ci dev_warn(dev, "dmaengine_slave_config failed %d\n", ret); 11238c2ecf20Sopenharmony_ci dma_release_channel(chan); 11248c2ecf20Sopenharmony_ci return NULL; 11258c2ecf20Sopenharmony_ci } 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci return chan; 11288c2ecf20Sopenharmony_ci} 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_cistatic int rspi_request_dma(struct device *dev, struct spi_controller *ctlr, 11318c2ecf20Sopenharmony_ci const struct resource *res) 11328c2ecf20Sopenharmony_ci{ 11338c2ecf20Sopenharmony_ci const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev); 11348c2ecf20Sopenharmony_ci unsigned int dma_tx_id, dma_rx_id; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci if (dev->of_node) { 11378c2ecf20Sopenharmony_ci /* In the OF case we will get the slave IDs from the DT */ 11388c2ecf20Sopenharmony_ci dma_tx_id = 0; 11398c2ecf20Sopenharmony_ci dma_rx_id = 0; 11408c2ecf20Sopenharmony_ci } else if (rspi_pd && rspi_pd->dma_tx_id && rspi_pd->dma_rx_id) { 11418c2ecf20Sopenharmony_ci dma_tx_id = rspi_pd->dma_tx_id; 11428c2ecf20Sopenharmony_ci dma_rx_id = rspi_pd->dma_rx_id; 11438c2ecf20Sopenharmony_ci } else { 11448c2ecf20Sopenharmony_ci /* The driver assumes no error. */ 11458c2ecf20Sopenharmony_ci return 0; 11468c2ecf20Sopenharmony_ci } 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci ctlr->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, dma_tx_id, 11498c2ecf20Sopenharmony_ci res->start); 11508c2ecf20Sopenharmony_ci if (!ctlr->dma_tx) 11518c2ecf20Sopenharmony_ci return -ENODEV; 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci ctlr->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, dma_rx_id, 11548c2ecf20Sopenharmony_ci res->start); 11558c2ecf20Sopenharmony_ci if (!ctlr->dma_rx) { 11568c2ecf20Sopenharmony_ci dma_release_channel(ctlr->dma_tx); 11578c2ecf20Sopenharmony_ci ctlr->dma_tx = NULL; 11588c2ecf20Sopenharmony_ci return -ENODEV; 11598c2ecf20Sopenharmony_ci } 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci ctlr->can_dma = rspi_can_dma; 11628c2ecf20Sopenharmony_ci dev_info(dev, "DMA available"); 11638c2ecf20Sopenharmony_ci return 0; 11648c2ecf20Sopenharmony_ci} 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_cistatic void rspi_release_dma(struct spi_controller *ctlr) 11678c2ecf20Sopenharmony_ci{ 11688c2ecf20Sopenharmony_ci if (ctlr->dma_tx) 11698c2ecf20Sopenharmony_ci dma_release_channel(ctlr->dma_tx); 11708c2ecf20Sopenharmony_ci if (ctlr->dma_rx) 11718c2ecf20Sopenharmony_ci dma_release_channel(ctlr->dma_rx); 11728c2ecf20Sopenharmony_ci} 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_cistatic int rspi_remove(struct platform_device *pdev) 11758c2ecf20Sopenharmony_ci{ 11768c2ecf20Sopenharmony_ci struct rspi_data *rspi = platform_get_drvdata(pdev); 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci rspi_release_dma(rspi->ctlr); 11798c2ecf20Sopenharmony_ci pm_runtime_disable(&pdev->dev); 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci return 0; 11828c2ecf20Sopenharmony_ci} 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_cistatic const struct spi_ops rspi_ops = { 11858c2ecf20Sopenharmony_ci .set_config_register = rspi_set_config_register, 11868c2ecf20Sopenharmony_ci .transfer_one = rspi_transfer_one, 11878c2ecf20Sopenharmony_ci .min_div = 2, 11888c2ecf20Sopenharmony_ci .max_div = 4096, 11898c2ecf20Sopenharmony_ci .flags = SPI_CONTROLLER_MUST_TX, 11908c2ecf20Sopenharmony_ci .fifo_size = 8, 11918c2ecf20Sopenharmony_ci .num_hw_ss = 2, 11928c2ecf20Sopenharmony_ci}; 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_cistatic const struct spi_ops rspi_rz_ops = { 11958c2ecf20Sopenharmony_ci .set_config_register = rspi_rz_set_config_register, 11968c2ecf20Sopenharmony_ci .transfer_one = rspi_rz_transfer_one, 11978c2ecf20Sopenharmony_ci .min_div = 2, 11988c2ecf20Sopenharmony_ci .max_div = 4096, 11998c2ecf20Sopenharmony_ci .flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX, 12008c2ecf20Sopenharmony_ci .fifo_size = 8, /* 8 for TX, 32 for RX */ 12018c2ecf20Sopenharmony_ci .num_hw_ss = 1, 12028c2ecf20Sopenharmony_ci}; 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_cistatic const struct spi_ops qspi_ops = { 12058c2ecf20Sopenharmony_ci .set_config_register = qspi_set_config_register, 12068c2ecf20Sopenharmony_ci .transfer_one = qspi_transfer_one, 12078c2ecf20Sopenharmony_ci .extra_mode_bits = SPI_TX_DUAL | SPI_TX_QUAD | 12088c2ecf20Sopenharmony_ci SPI_RX_DUAL | SPI_RX_QUAD, 12098c2ecf20Sopenharmony_ci .min_div = 1, 12108c2ecf20Sopenharmony_ci .max_div = 4080, 12118c2ecf20Sopenharmony_ci .flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX, 12128c2ecf20Sopenharmony_ci .fifo_size = 32, 12138c2ecf20Sopenharmony_ci .num_hw_ss = 1, 12148c2ecf20Sopenharmony_ci}; 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 12178c2ecf20Sopenharmony_cistatic const struct of_device_id rspi_of_match[] = { 12188c2ecf20Sopenharmony_ci /* RSPI on legacy SH */ 12198c2ecf20Sopenharmony_ci { .compatible = "renesas,rspi", .data = &rspi_ops }, 12208c2ecf20Sopenharmony_ci /* RSPI on RZ/A1H */ 12218c2ecf20Sopenharmony_ci { .compatible = "renesas,rspi-rz", .data = &rspi_rz_ops }, 12228c2ecf20Sopenharmony_ci /* QSPI on R-Car Gen2 */ 12238c2ecf20Sopenharmony_ci { .compatible = "renesas,qspi", .data = &qspi_ops }, 12248c2ecf20Sopenharmony_ci { /* sentinel */ } 12258c2ecf20Sopenharmony_ci}; 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, rspi_of_match); 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_cistatic int rspi_parse_dt(struct device *dev, struct spi_controller *ctlr) 12308c2ecf20Sopenharmony_ci{ 12318c2ecf20Sopenharmony_ci u32 num_cs; 12328c2ecf20Sopenharmony_ci int error; 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci /* Parse DT properties */ 12358c2ecf20Sopenharmony_ci error = of_property_read_u32(dev->of_node, "num-cs", &num_cs); 12368c2ecf20Sopenharmony_ci if (error) { 12378c2ecf20Sopenharmony_ci dev_err(dev, "of_property_read_u32 num-cs failed %d\n", error); 12388c2ecf20Sopenharmony_ci return error; 12398c2ecf20Sopenharmony_ci } 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci ctlr->num_chipselect = num_cs; 12428c2ecf20Sopenharmony_ci return 0; 12438c2ecf20Sopenharmony_ci} 12448c2ecf20Sopenharmony_ci#else 12458c2ecf20Sopenharmony_ci#define rspi_of_match NULL 12468c2ecf20Sopenharmony_cistatic inline int rspi_parse_dt(struct device *dev, struct spi_controller *ctlr) 12478c2ecf20Sopenharmony_ci{ 12488c2ecf20Sopenharmony_ci return -EINVAL; 12498c2ecf20Sopenharmony_ci} 12508c2ecf20Sopenharmony_ci#endif /* CONFIG_OF */ 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_cistatic int rspi_request_irq(struct device *dev, unsigned int irq, 12538c2ecf20Sopenharmony_ci irq_handler_t handler, const char *suffix, 12548c2ecf20Sopenharmony_ci void *dev_id) 12558c2ecf20Sopenharmony_ci{ 12568c2ecf20Sopenharmony_ci const char *name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", 12578c2ecf20Sopenharmony_ci dev_name(dev), suffix); 12588c2ecf20Sopenharmony_ci if (!name) 12598c2ecf20Sopenharmony_ci return -ENOMEM; 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci return devm_request_irq(dev, irq, handler, 0, name, dev_id); 12628c2ecf20Sopenharmony_ci} 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_cistatic int rspi_probe(struct platform_device *pdev) 12658c2ecf20Sopenharmony_ci{ 12668c2ecf20Sopenharmony_ci struct resource *res; 12678c2ecf20Sopenharmony_ci struct spi_controller *ctlr; 12688c2ecf20Sopenharmony_ci struct rspi_data *rspi; 12698c2ecf20Sopenharmony_ci int ret; 12708c2ecf20Sopenharmony_ci const struct rspi_plat_data *rspi_pd; 12718c2ecf20Sopenharmony_ci const struct spi_ops *ops; 12728c2ecf20Sopenharmony_ci unsigned long clksrc; 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci ctlr = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data)); 12758c2ecf20Sopenharmony_ci if (ctlr == NULL) 12768c2ecf20Sopenharmony_ci return -ENOMEM; 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci ops = of_device_get_match_data(&pdev->dev); 12798c2ecf20Sopenharmony_ci if (ops) { 12808c2ecf20Sopenharmony_ci ret = rspi_parse_dt(&pdev->dev, ctlr); 12818c2ecf20Sopenharmony_ci if (ret) 12828c2ecf20Sopenharmony_ci goto error1; 12838c2ecf20Sopenharmony_ci } else { 12848c2ecf20Sopenharmony_ci ops = (struct spi_ops *)pdev->id_entry->driver_data; 12858c2ecf20Sopenharmony_ci rspi_pd = dev_get_platdata(&pdev->dev); 12868c2ecf20Sopenharmony_ci if (rspi_pd && rspi_pd->num_chipselect) 12878c2ecf20Sopenharmony_ci ctlr->num_chipselect = rspi_pd->num_chipselect; 12888c2ecf20Sopenharmony_ci else 12898c2ecf20Sopenharmony_ci ctlr->num_chipselect = 2; /* default */ 12908c2ecf20Sopenharmony_ci } 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci rspi = spi_controller_get_devdata(ctlr); 12938c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, rspi); 12948c2ecf20Sopenharmony_ci rspi->ops = ops; 12958c2ecf20Sopenharmony_ci rspi->ctlr = ctlr; 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 12988c2ecf20Sopenharmony_ci rspi->addr = devm_ioremap_resource(&pdev->dev, res); 12998c2ecf20Sopenharmony_ci if (IS_ERR(rspi->addr)) { 13008c2ecf20Sopenharmony_ci ret = PTR_ERR(rspi->addr); 13018c2ecf20Sopenharmony_ci goto error1; 13028c2ecf20Sopenharmony_ci } 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_ci rspi->clk = devm_clk_get(&pdev->dev, NULL); 13058c2ecf20Sopenharmony_ci if (IS_ERR(rspi->clk)) { 13068c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "cannot get clock\n"); 13078c2ecf20Sopenharmony_ci ret = PTR_ERR(rspi->clk); 13088c2ecf20Sopenharmony_ci goto error1; 13098c2ecf20Sopenharmony_ci } 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci rspi->pdev = pdev; 13128c2ecf20Sopenharmony_ci pm_runtime_enable(&pdev->dev); 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci init_waitqueue_head(&rspi->wait); 13158c2ecf20Sopenharmony_ci spin_lock_init(&rspi->lock); 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci ctlr->bus_num = pdev->id; 13188c2ecf20Sopenharmony_ci ctlr->setup = rspi_setup; 13198c2ecf20Sopenharmony_ci ctlr->auto_runtime_pm = true; 13208c2ecf20Sopenharmony_ci ctlr->transfer_one = ops->transfer_one; 13218c2ecf20Sopenharmony_ci ctlr->prepare_message = rspi_prepare_message; 13228c2ecf20Sopenharmony_ci ctlr->unprepare_message = rspi_unprepare_message; 13238c2ecf20Sopenharmony_ci ctlr->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | 13248c2ecf20Sopenharmony_ci SPI_LOOP | ops->extra_mode_bits; 13258c2ecf20Sopenharmony_ci clksrc = clk_get_rate(rspi->clk); 13268c2ecf20Sopenharmony_ci ctlr->min_speed_hz = DIV_ROUND_UP(clksrc, ops->max_div); 13278c2ecf20Sopenharmony_ci ctlr->max_speed_hz = DIV_ROUND_UP(clksrc, ops->min_div); 13288c2ecf20Sopenharmony_ci ctlr->flags = ops->flags; 13298c2ecf20Sopenharmony_ci ctlr->dev.of_node = pdev->dev.of_node; 13308c2ecf20Sopenharmony_ci ctlr->use_gpio_descriptors = true; 13318c2ecf20Sopenharmony_ci ctlr->max_native_cs = rspi->ops->num_hw_ss; 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci ret = platform_get_irq_byname_optional(pdev, "rx"); 13348c2ecf20Sopenharmony_ci if (ret < 0) { 13358c2ecf20Sopenharmony_ci ret = platform_get_irq_byname_optional(pdev, "mux"); 13368c2ecf20Sopenharmony_ci if (ret < 0) 13378c2ecf20Sopenharmony_ci ret = platform_get_irq(pdev, 0); 13388c2ecf20Sopenharmony_ci if (ret >= 0) 13398c2ecf20Sopenharmony_ci rspi->rx_irq = rspi->tx_irq = ret; 13408c2ecf20Sopenharmony_ci } else { 13418c2ecf20Sopenharmony_ci rspi->rx_irq = ret; 13428c2ecf20Sopenharmony_ci ret = platform_get_irq_byname(pdev, "tx"); 13438c2ecf20Sopenharmony_ci if (ret >= 0) 13448c2ecf20Sopenharmony_ci rspi->tx_irq = ret; 13458c2ecf20Sopenharmony_ci } 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci if (rspi->rx_irq == rspi->tx_irq) { 13488c2ecf20Sopenharmony_ci /* Single multiplexed interrupt */ 13498c2ecf20Sopenharmony_ci ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_mux, 13508c2ecf20Sopenharmony_ci "mux", rspi); 13518c2ecf20Sopenharmony_ci } else { 13528c2ecf20Sopenharmony_ci /* Multi-interrupt mode, only SPRI and SPTI are used */ 13538c2ecf20Sopenharmony_ci ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_rx, 13548c2ecf20Sopenharmony_ci "rx", rspi); 13558c2ecf20Sopenharmony_ci if (!ret) 13568c2ecf20Sopenharmony_ci ret = rspi_request_irq(&pdev->dev, rspi->tx_irq, 13578c2ecf20Sopenharmony_ci rspi_irq_tx, "tx", rspi); 13588c2ecf20Sopenharmony_ci } 13598c2ecf20Sopenharmony_ci if (ret < 0) { 13608c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "request_irq error\n"); 13618c2ecf20Sopenharmony_ci goto error2; 13628c2ecf20Sopenharmony_ci } 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci ret = rspi_request_dma(&pdev->dev, ctlr, res); 13658c2ecf20Sopenharmony_ci if (ret < 0) 13668c2ecf20Sopenharmony_ci dev_warn(&pdev->dev, "DMA not available, using PIO\n"); 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci ret = devm_spi_register_controller(&pdev->dev, ctlr); 13698c2ecf20Sopenharmony_ci if (ret < 0) { 13708c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); 13718c2ecf20Sopenharmony_ci goto error3; 13728c2ecf20Sopenharmony_ci } 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "probed\n"); 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci return 0; 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_cierror3: 13798c2ecf20Sopenharmony_ci rspi_release_dma(ctlr); 13808c2ecf20Sopenharmony_cierror2: 13818c2ecf20Sopenharmony_ci pm_runtime_disable(&pdev->dev); 13828c2ecf20Sopenharmony_cierror1: 13838c2ecf20Sopenharmony_ci spi_controller_put(ctlr); 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci return ret; 13868c2ecf20Sopenharmony_ci} 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_cistatic const struct platform_device_id spi_driver_ids[] = { 13898c2ecf20Sopenharmony_ci { "rspi", (kernel_ulong_t)&rspi_ops }, 13908c2ecf20Sopenharmony_ci {}, 13918c2ecf20Sopenharmony_ci}; 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(platform, spi_driver_ids); 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 13968c2ecf20Sopenharmony_cistatic int rspi_suspend(struct device *dev) 13978c2ecf20Sopenharmony_ci{ 13988c2ecf20Sopenharmony_ci struct rspi_data *rspi = dev_get_drvdata(dev); 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci return spi_controller_suspend(rspi->ctlr); 14018c2ecf20Sopenharmony_ci} 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_cistatic int rspi_resume(struct device *dev) 14048c2ecf20Sopenharmony_ci{ 14058c2ecf20Sopenharmony_ci struct rspi_data *rspi = dev_get_drvdata(dev); 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci return spi_controller_resume(rspi->ctlr); 14088c2ecf20Sopenharmony_ci} 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(rspi_pm_ops, rspi_suspend, rspi_resume); 14118c2ecf20Sopenharmony_ci#define DEV_PM_OPS &rspi_pm_ops 14128c2ecf20Sopenharmony_ci#else 14138c2ecf20Sopenharmony_ci#define DEV_PM_OPS NULL 14148c2ecf20Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */ 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_cistatic struct platform_driver rspi_driver = { 14178c2ecf20Sopenharmony_ci .probe = rspi_probe, 14188c2ecf20Sopenharmony_ci .remove = rspi_remove, 14198c2ecf20Sopenharmony_ci .id_table = spi_driver_ids, 14208c2ecf20Sopenharmony_ci .driver = { 14218c2ecf20Sopenharmony_ci .name = "renesas_spi", 14228c2ecf20Sopenharmony_ci .pm = DEV_PM_OPS, 14238c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(rspi_of_match), 14248c2ecf20Sopenharmony_ci }, 14258c2ecf20Sopenharmony_ci}; 14268c2ecf20Sopenharmony_cimodule_platform_driver(rspi_driver); 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Renesas RSPI bus driver"); 14298c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 14308c2ecf20Sopenharmony_ciMODULE_AUTHOR("Yoshihiro Shimoda"); 14318c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:rspi"); 1432