162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * SH RSPI driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2012, 2013 Renesas Solutions Corp. 662306a36Sopenharmony_ci * Copyright (C) 2014 Glider bvba 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Based on spi-sh.c: 962306a36Sopenharmony_ci * Copyright (C) 2011 Renesas Solutions Corp. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/sched.h> 1562306a36Sopenharmony_ci#include <linux/errno.h> 1662306a36Sopenharmony_ci#include <linux/interrupt.h> 1762306a36Sopenharmony_ci#include <linux/platform_device.h> 1862306a36Sopenharmony_ci#include <linux/io.h> 1962306a36Sopenharmony_ci#include <linux/clk.h> 2062306a36Sopenharmony_ci#include <linux/dmaengine.h> 2162306a36Sopenharmony_ci#include <linux/dma-mapping.h> 2262306a36Sopenharmony_ci#include <linux/of.h> 2362306a36Sopenharmony_ci#include <linux/pm_runtime.h> 2462306a36Sopenharmony_ci#include <linux/reset.h> 2562306a36Sopenharmony_ci#include <linux/sh_dma.h> 2662306a36Sopenharmony_ci#include <linux/spi/spi.h> 2762306a36Sopenharmony_ci#include <linux/spi/rspi.h> 2862306a36Sopenharmony_ci#include <linux/spinlock.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define RSPI_SPCR 0x00 /* Control Register */ 3162306a36Sopenharmony_ci#define RSPI_SSLP 0x01 /* Slave Select Polarity Register */ 3262306a36Sopenharmony_ci#define RSPI_SPPCR 0x02 /* Pin Control Register */ 3362306a36Sopenharmony_ci#define RSPI_SPSR 0x03 /* Status Register */ 3462306a36Sopenharmony_ci#define RSPI_SPDR 0x04 /* Data Register */ 3562306a36Sopenharmony_ci#define RSPI_SPSCR 0x08 /* Sequence Control Register */ 3662306a36Sopenharmony_ci#define RSPI_SPSSR 0x09 /* Sequence Status Register */ 3762306a36Sopenharmony_ci#define RSPI_SPBR 0x0a /* Bit Rate Register */ 3862306a36Sopenharmony_ci#define RSPI_SPDCR 0x0b /* Data Control Register */ 3962306a36Sopenharmony_ci#define RSPI_SPCKD 0x0c /* Clock Delay Register */ 4062306a36Sopenharmony_ci#define RSPI_SSLND 0x0d /* Slave Select Negation Delay Register */ 4162306a36Sopenharmony_ci#define RSPI_SPND 0x0e /* Next-Access Delay Register */ 4262306a36Sopenharmony_ci#define RSPI_SPCR2 0x0f /* Control Register 2 (SH only) */ 4362306a36Sopenharmony_ci#define RSPI_SPCMD0 0x10 /* Command Register 0 */ 4462306a36Sopenharmony_ci#define RSPI_SPCMD1 0x12 /* Command Register 1 */ 4562306a36Sopenharmony_ci#define RSPI_SPCMD2 0x14 /* Command Register 2 */ 4662306a36Sopenharmony_ci#define RSPI_SPCMD3 0x16 /* Command Register 3 */ 4762306a36Sopenharmony_ci#define RSPI_SPCMD4 0x18 /* Command Register 4 */ 4862306a36Sopenharmony_ci#define RSPI_SPCMD5 0x1a /* Command Register 5 */ 4962306a36Sopenharmony_ci#define RSPI_SPCMD6 0x1c /* Command Register 6 */ 5062306a36Sopenharmony_ci#define RSPI_SPCMD7 0x1e /* Command Register 7 */ 5162306a36Sopenharmony_ci#define RSPI_SPCMD(i) (RSPI_SPCMD0 + (i) * 2) 5262306a36Sopenharmony_ci#define RSPI_NUM_SPCMD 8 5362306a36Sopenharmony_ci#define RSPI_RZ_NUM_SPCMD 4 5462306a36Sopenharmony_ci#define QSPI_NUM_SPCMD 4 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* RSPI on RZ only */ 5762306a36Sopenharmony_ci#define RSPI_SPBFCR 0x20 /* Buffer Control Register */ 5862306a36Sopenharmony_ci#define RSPI_SPBFDR 0x22 /* Buffer Data Count Setting Register */ 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* QSPI only */ 6162306a36Sopenharmony_ci#define QSPI_SPBFCR 0x18 /* Buffer Control Register */ 6262306a36Sopenharmony_ci#define QSPI_SPBDCR 0x1a /* Buffer Data Count Register */ 6362306a36Sopenharmony_ci#define QSPI_SPBMUL0 0x1c /* Transfer Data Length Multiplier Setting Register 0 */ 6462306a36Sopenharmony_ci#define QSPI_SPBMUL1 0x20 /* Transfer Data Length Multiplier Setting Register 1 */ 6562306a36Sopenharmony_ci#define QSPI_SPBMUL2 0x24 /* Transfer Data Length Multiplier Setting Register 2 */ 6662306a36Sopenharmony_ci#define QSPI_SPBMUL3 0x28 /* Transfer Data Length Multiplier Setting Register 3 */ 6762306a36Sopenharmony_ci#define QSPI_SPBMUL(i) (QSPI_SPBMUL0 + (i) * 4) 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/* SPCR - Control Register */ 7062306a36Sopenharmony_ci#define SPCR_SPRIE 0x80 /* Receive Interrupt Enable */ 7162306a36Sopenharmony_ci#define SPCR_SPE 0x40 /* Function Enable */ 7262306a36Sopenharmony_ci#define SPCR_SPTIE 0x20 /* Transmit Interrupt Enable */ 7362306a36Sopenharmony_ci#define SPCR_SPEIE 0x10 /* Error Interrupt Enable */ 7462306a36Sopenharmony_ci#define SPCR_MSTR 0x08 /* Master/Slave Mode Select */ 7562306a36Sopenharmony_ci#define SPCR_MODFEN 0x04 /* Mode Fault Error Detection Enable */ 7662306a36Sopenharmony_ci/* RSPI on SH only */ 7762306a36Sopenharmony_ci#define SPCR_TXMD 0x02 /* TX Only Mode (vs. Full Duplex) */ 7862306a36Sopenharmony_ci#define SPCR_SPMS 0x01 /* 3-wire Mode (vs. 4-wire) */ 7962306a36Sopenharmony_ci/* QSPI on R-Car Gen2 only */ 8062306a36Sopenharmony_ci#define SPCR_WSWAP 0x02 /* Word Swap of read-data for DMAC */ 8162306a36Sopenharmony_ci#define SPCR_BSWAP 0x01 /* Byte Swap of read-data for DMAC */ 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci/* SSLP - Slave Select Polarity Register */ 8462306a36Sopenharmony_ci#define SSLP_SSLP(i) BIT(i) /* SSLi Signal Polarity Setting */ 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/* SPPCR - Pin Control Register */ 8762306a36Sopenharmony_ci#define SPPCR_MOIFE 0x20 /* MOSI Idle Value Fixing Enable */ 8862306a36Sopenharmony_ci#define SPPCR_MOIFV 0x10 /* MOSI Idle Fixed Value */ 8962306a36Sopenharmony_ci#define SPPCR_SPOM 0x04 9062306a36Sopenharmony_ci#define SPPCR_SPLP2 0x02 /* Loopback Mode 2 (non-inverting) */ 9162306a36Sopenharmony_ci#define SPPCR_SPLP 0x01 /* Loopback Mode (inverting) */ 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci#define SPPCR_IO3FV 0x04 /* Single-/Dual-SPI Mode IO3 Output Fixed Value */ 9462306a36Sopenharmony_ci#define SPPCR_IO2FV 0x04 /* Single-/Dual-SPI Mode IO2 Output Fixed Value */ 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/* SPSR - Status Register */ 9762306a36Sopenharmony_ci#define SPSR_SPRF 0x80 /* Receive Buffer Full Flag */ 9862306a36Sopenharmony_ci#define SPSR_TEND 0x40 /* Transmit End */ 9962306a36Sopenharmony_ci#define SPSR_SPTEF 0x20 /* Transmit Buffer Empty Flag */ 10062306a36Sopenharmony_ci#define SPSR_PERF 0x08 /* Parity Error Flag */ 10162306a36Sopenharmony_ci#define SPSR_MODF 0x04 /* Mode Fault Error Flag */ 10262306a36Sopenharmony_ci#define SPSR_IDLNF 0x02 /* RSPI Idle Flag */ 10362306a36Sopenharmony_ci#define SPSR_OVRF 0x01 /* Overrun Error Flag (RSPI only) */ 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/* SPSCR - Sequence Control Register */ 10662306a36Sopenharmony_ci#define SPSCR_SPSLN_MASK 0x07 /* Sequence Length Specification */ 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/* SPSSR - Sequence Status Register */ 10962306a36Sopenharmony_ci#define SPSSR_SPECM_MASK 0x70 /* Command Error Mask */ 11062306a36Sopenharmony_ci#define SPSSR_SPCP_MASK 0x07 /* Command Pointer Mask */ 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci/* SPDCR - Data Control Register */ 11362306a36Sopenharmony_ci#define SPDCR_TXDMY 0x80 /* Dummy Data Transmission Enable */ 11462306a36Sopenharmony_ci#define SPDCR_SPLW1 0x40 /* Access Width Specification (RZ) */ 11562306a36Sopenharmony_ci#define SPDCR_SPLW0 0x20 /* Access Width Specification (RZ) */ 11662306a36Sopenharmony_ci#define SPDCR_SPLLWORD (SPDCR_SPLW1 | SPDCR_SPLW0) 11762306a36Sopenharmony_ci#define SPDCR_SPLWORD SPDCR_SPLW1 11862306a36Sopenharmony_ci#define SPDCR_SPLBYTE SPDCR_SPLW0 11962306a36Sopenharmony_ci#define SPDCR_SPLW 0x20 /* Access Width Specification (SH) */ 12062306a36Sopenharmony_ci#define SPDCR_SPRDTD 0x10 /* Receive Transmit Data Select (SH) */ 12162306a36Sopenharmony_ci#define SPDCR_SLSEL1 0x08 12262306a36Sopenharmony_ci#define SPDCR_SLSEL0 0x04 12362306a36Sopenharmony_ci#define SPDCR_SLSEL_MASK 0x0c /* SSL1 Output Select (SH) */ 12462306a36Sopenharmony_ci#define SPDCR_SPFC1 0x02 12562306a36Sopenharmony_ci#define SPDCR_SPFC0 0x01 12662306a36Sopenharmony_ci#define SPDCR_SPFC_MASK 0x03 /* Frame Count Setting (1-4) (SH) */ 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci/* SPCKD - Clock Delay Register */ 12962306a36Sopenharmony_ci#define SPCKD_SCKDL_MASK 0x07 /* Clock Delay Setting (1-8) */ 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci/* SSLND - Slave Select Negation Delay Register */ 13262306a36Sopenharmony_ci#define SSLND_SLNDL_MASK 0x07 /* SSL Negation Delay Setting (1-8) */ 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci/* SPND - Next-Access Delay Register */ 13562306a36Sopenharmony_ci#define SPND_SPNDL_MASK 0x07 /* Next-Access Delay Setting (1-8) */ 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/* SPCR2 - Control Register 2 */ 13862306a36Sopenharmony_ci#define SPCR2_PTE 0x08 /* Parity Self-Test Enable */ 13962306a36Sopenharmony_ci#define SPCR2_SPIE 0x04 /* Idle Interrupt Enable */ 14062306a36Sopenharmony_ci#define SPCR2_SPOE 0x02 /* Odd Parity Enable (vs. Even) */ 14162306a36Sopenharmony_ci#define SPCR2_SPPE 0x01 /* Parity Enable */ 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/* SPCMDn - Command Registers */ 14462306a36Sopenharmony_ci#define SPCMD_SCKDEN 0x8000 /* Clock Delay Setting Enable */ 14562306a36Sopenharmony_ci#define SPCMD_SLNDEN 0x4000 /* SSL Negation Delay Setting Enable */ 14662306a36Sopenharmony_ci#define SPCMD_SPNDEN 0x2000 /* Next-Access Delay Enable */ 14762306a36Sopenharmony_ci#define SPCMD_LSBF 0x1000 /* LSB First */ 14862306a36Sopenharmony_ci#define SPCMD_SPB_MASK 0x0f00 /* Data Length Setting */ 14962306a36Sopenharmony_ci#define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK) 15062306a36Sopenharmony_ci#define SPCMD_SPB_8BIT 0x0000 /* QSPI only */ 15162306a36Sopenharmony_ci#define SPCMD_SPB_16BIT 0x0100 15262306a36Sopenharmony_ci#define SPCMD_SPB_20BIT 0x0000 15362306a36Sopenharmony_ci#define SPCMD_SPB_24BIT 0x0100 15462306a36Sopenharmony_ci#define SPCMD_SPB_32BIT 0x0200 15562306a36Sopenharmony_ci#define SPCMD_SSLKP 0x0080 /* SSL Signal Level Keeping */ 15662306a36Sopenharmony_ci#define SPCMD_SPIMOD_MASK 0x0060 /* SPI Operating Mode (QSPI only) */ 15762306a36Sopenharmony_ci#define SPCMD_SPIMOD1 0x0040 15862306a36Sopenharmony_ci#define SPCMD_SPIMOD0 0x0020 15962306a36Sopenharmony_ci#define SPCMD_SPIMOD_SINGLE 0 16062306a36Sopenharmony_ci#define SPCMD_SPIMOD_DUAL SPCMD_SPIMOD0 16162306a36Sopenharmony_ci#define SPCMD_SPIMOD_QUAD SPCMD_SPIMOD1 16262306a36Sopenharmony_ci#define SPCMD_SPRW 0x0010 /* SPI Read/Write Access (Dual/Quad) */ 16362306a36Sopenharmony_ci#define SPCMD_SSLA(i) ((i) << 4) /* SSL Assert Signal Setting */ 16462306a36Sopenharmony_ci#define SPCMD_BRDV_MASK 0x000c /* Bit Rate Division Setting */ 16562306a36Sopenharmony_ci#define SPCMD_BRDV(brdv) ((brdv) << 2) 16662306a36Sopenharmony_ci#define SPCMD_CPOL 0x0002 /* Clock Polarity Setting */ 16762306a36Sopenharmony_ci#define SPCMD_CPHA 0x0001 /* Clock Phase Setting */ 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci/* SPBFCR - Buffer Control Register */ 17062306a36Sopenharmony_ci#define SPBFCR_TXRST 0x80 /* Transmit Buffer Data Reset */ 17162306a36Sopenharmony_ci#define SPBFCR_RXRST 0x40 /* Receive Buffer Data Reset */ 17262306a36Sopenharmony_ci#define SPBFCR_TXTRG_MASK 0x30 /* Transmit Buffer Data Triggering Number */ 17362306a36Sopenharmony_ci#define SPBFCR_RXTRG_MASK 0x07 /* Receive Buffer Data Triggering Number */ 17462306a36Sopenharmony_ci/* QSPI on R-Car Gen2 */ 17562306a36Sopenharmony_ci#define SPBFCR_TXTRG_1B 0x00 /* 31 bytes (1 byte available) */ 17662306a36Sopenharmony_ci#define SPBFCR_TXTRG_32B 0x30 /* 0 byte (32 bytes available) */ 17762306a36Sopenharmony_ci#define SPBFCR_RXTRG_1B 0x00 /* 1 byte (31 bytes available) */ 17862306a36Sopenharmony_ci#define SPBFCR_RXTRG_32B 0x07 /* 32 bytes (0 byte available) */ 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci#define QSPI_BUFFER_SIZE 32u 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistruct rspi_data { 18362306a36Sopenharmony_ci void __iomem *addr; 18462306a36Sopenharmony_ci u32 speed_hz; 18562306a36Sopenharmony_ci struct spi_controller *ctlr; 18662306a36Sopenharmony_ci struct platform_device *pdev; 18762306a36Sopenharmony_ci wait_queue_head_t wait; 18862306a36Sopenharmony_ci spinlock_t lock; /* Protects RMW-access to RSPI_SSLP */ 18962306a36Sopenharmony_ci struct clk *clk; 19062306a36Sopenharmony_ci u16 spcmd; 19162306a36Sopenharmony_ci u8 spsr; 19262306a36Sopenharmony_ci u8 sppcr; 19362306a36Sopenharmony_ci int rx_irq, tx_irq; 19462306a36Sopenharmony_ci const struct spi_ops *ops; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci unsigned dma_callbacked:1; 19762306a36Sopenharmony_ci unsigned byte_access:1; 19862306a36Sopenharmony_ci}; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci iowrite8(data, rspi->addr + offset); 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic void rspi_write16(const struct rspi_data *rspi, u16 data, u16 offset) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci iowrite16(data, rspi->addr + offset); 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistatic void rspi_write32(const struct rspi_data *rspi, u32 data, u16 offset) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci iowrite32(data, rspi->addr + offset); 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic u8 rspi_read8(const struct rspi_data *rspi, u16 offset) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci return ioread8(rspi->addr + offset); 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic u16 rspi_read16(const struct rspi_data *rspi, u16 offset) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci return ioread16(rspi->addr + offset); 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic void rspi_write_data(const struct rspi_data *rspi, u16 data) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci if (rspi->byte_access) 22862306a36Sopenharmony_ci rspi_write8(rspi, data, RSPI_SPDR); 22962306a36Sopenharmony_ci else /* 16 bit */ 23062306a36Sopenharmony_ci rspi_write16(rspi, data, RSPI_SPDR); 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_cistatic u16 rspi_read_data(const struct rspi_data *rspi) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci if (rspi->byte_access) 23662306a36Sopenharmony_ci return rspi_read8(rspi, RSPI_SPDR); 23762306a36Sopenharmony_ci else /* 16 bit */ 23862306a36Sopenharmony_ci return rspi_read16(rspi, RSPI_SPDR); 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci/* optional functions */ 24262306a36Sopenharmony_cistruct spi_ops { 24362306a36Sopenharmony_ci int (*set_config_register)(struct rspi_data *rspi, int access_size); 24462306a36Sopenharmony_ci int (*transfer_one)(struct spi_controller *ctlr, 24562306a36Sopenharmony_ci struct spi_device *spi, struct spi_transfer *xfer); 24662306a36Sopenharmony_ci u16 extra_mode_bits; 24762306a36Sopenharmony_ci u16 min_div; 24862306a36Sopenharmony_ci u16 max_div; 24962306a36Sopenharmony_ci u16 flags; 25062306a36Sopenharmony_ci u16 fifo_size; 25162306a36Sopenharmony_ci u8 num_hw_ss; 25262306a36Sopenharmony_ci}; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic void rspi_set_rate(struct rspi_data *rspi) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci unsigned long clksrc; 25762306a36Sopenharmony_ci int brdv = 0, spbr; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci clksrc = clk_get_rate(rspi->clk); 26062306a36Sopenharmony_ci spbr = DIV_ROUND_UP(clksrc, 2 * rspi->speed_hz) - 1; 26162306a36Sopenharmony_ci while (spbr > 255 && brdv < 3) { 26262306a36Sopenharmony_ci brdv++; 26362306a36Sopenharmony_ci spbr = DIV_ROUND_UP(spbr + 1, 2) - 1; 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); 26762306a36Sopenharmony_ci rspi->spcmd |= SPCMD_BRDV(brdv); 26862306a36Sopenharmony_ci rspi->speed_hz = DIV_ROUND_UP(clksrc, (2U << brdv) * (spbr + 1)); 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci/* 27262306a36Sopenharmony_ci * functions for RSPI on legacy SH 27362306a36Sopenharmony_ci */ 27462306a36Sopenharmony_cistatic int rspi_set_config_register(struct rspi_data *rspi, int access_size) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci /* Sets output mode, MOSI signal, and (optionally) loopback */ 27762306a36Sopenharmony_ci rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci /* Sets transfer bit rate */ 28062306a36Sopenharmony_ci rspi_set_rate(rspi); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci /* Disable dummy transmission, set 16-bit word access, 1 frame */ 28362306a36Sopenharmony_ci rspi_write8(rspi, 0, RSPI_SPDCR); 28462306a36Sopenharmony_ci rspi->byte_access = 0; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci /* Sets RSPCK, SSL, next-access delay value */ 28762306a36Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SPCKD); 28862306a36Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SSLND); 28962306a36Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SPND); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci /* Sets parity, interrupt mask */ 29262306a36Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SPCR2); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci /* Resets sequencer */ 29562306a36Sopenharmony_ci rspi_write8(rspi, 0, RSPI_SPSCR); 29662306a36Sopenharmony_ci rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size); 29762306a36Sopenharmony_ci rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci /* Sets RSPI mode */ 30062306a36Sopenharmony_ci rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci return 0; 30362306a36Sopenharmony_ci} 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci/* 30662306a36Sopenharmony_ci * functions for RSPI on RZ 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_cistatic int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci /* Sets output mode, MOSI signal, and (optionally) loopback */ 31162306a36Sopenharmony_ci rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci /* Sets transfer bit rate */ 31462306a36Sopenharmony_ci rspi_set_rate(rspi); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* Disable dummy transmission, set byte access */ 31762306a36Sopenharmony_ci rspi_write8(rspi, SPDCR_SPLBYTE, RSPI_SPDCR); 31862306a36Sopenharmony_ci rspi->byte_access = 1; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci /* Sets RSPCK, SSL, next-access delay value */ 32162306a36Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SPCKD); 32262306a36Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SSLND); 32362306a36Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SPND); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci /* Resets sequencer */ 32662306a36Sopenharmony_ci rspi_write8(rspi, 0, RSPI_SPSCR); 32762306a36Sopenharmony_ci rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size); 32862306a36Sopenharmony_ci rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci /* Sets RSPI mode */ 33162306a36Sopenharmony_ci rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci return 0; 33462306a36Sopenharmony_ci} 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci/* 33762306a36Sopenharmony_ci * functions for QSPI 33862306a36Sopenharmony_ci */ 33962306a36Sopenharmony_cistatic int qspi_set_config_register(struct rspi_data *rspi, int access_size) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci unsigned long clksrc; 34262306a36Sopenharmony_ci int brdv = 0, spbr; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* Sets output mode, MOSI signal, and (optionally) loopback */ 34562306a36Sopenharmony_ci rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci /* Sets transfer bit rate */ 34862306a36Sopenharmony_ci clksrc = clk_get_rate(rspi->clk); 34962306a36Sopenharmony_ci if (rspi->speed_hz >= clksrc) { 35062306a36Sopenharmony_ci spbr = 0; 35162306a36Sopenharmony_ci rspi->speed_hz = clksrc; 35262306a36Sopenharmony_ci } else { 35362306a36Sopenharmony_ci spbr = DIV_ROUND_UP(clksrc, 2 * rspi->speed_hz); 35462306a36Sopenharmony_ci while (spbr > 255 && brdv < 3) { 35562306a36Sopenharmony_ci brdv++; 35662306a36Sopenharmony_ci spbr = DIV_ROUND_UP(spbr, 2); 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci spbr = clamp(spbr, 0, 255); 35962306a36Sopenharmony_ci rspi->speed_hz = DIV_ROUND_UP(clksrc, (2U << brdv) * spbr); 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci rspi_write8(rspi, spbr, RSPI_SPBR); 36262306a36Sopenharmony_ci rspi->spcmd |= SPCMD_BRDV(brdv); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci /* Disable dummy transmission, set byte access */ 36562306a36Sopenharmony_ci rspi_write8(rspi, 0, RSPI_SPDCR); 36662306a36Sopenharmony_ci rspi->byte_access = 1; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci /* Sets RSPCK, SSL, next-access delay value */ 36962306a36Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SPCKD); 37062306a36Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SSLND); 37162306a36Sopenharmony_ci rspi_write8(rspi, 0x00, RSPI_SPND); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci /* Data Length Setting */ 37462306a36Sopenharmony_ci if (access_size == 8) 37562306a36Sopenharmony_ci rspi->spcmd |= SPCMD_SPB_8BIT; 37662306a36Sopenharmony_ci else if (access_size == 16) 37762306a36Sopenharmony_ci rspi->spcmd |= SPCMD_SPB_16BIT; 37862306a36Sopenharmony_ci else 37962306a36Sopenharmony_ci rspi->spcmd |= SPCMD_SPB_32BIT; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci rspi->spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SPNDEN; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* Resets transfer data length */ 38462306a36Sopenharmony_ci rspi_write32(rspi, 0, QSPI_SPBMUL0); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci /* Resets transmit and receive buffer */ 38762306a36Sopenharmony_ci rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR); 38862306a36Sopenharmony_ci /* Sets buffer to allow normal operation */ 38962306a36Sopenharmony_ci rspi_write8(rspi, 0x00, QSPI_SPBFCR); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci /* Resets sequencer */ 39262306a36Sopenharmony_ci rspi_write8(rspi, 0, RSPI_SPSCR); 39362306a36Sopenharmony_ci rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci /* Sets RSPI mode */ 39662306a36Sopenharmony_ci rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci return 0; 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cistatic void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci u8 data; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci data = rspi_read8(rspi, reg); 40662306a36Sopenharmony_ci data &= ~mask; 40762306a36Sopenharmony_ci data |= (val & mask); 40862306a36Sopenharmony_ci rspi_write8(rspi, data, reg); 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cistatic unsigned int qspi_set_send_trigger(struct rspi_data *rspi, 41262306a36Sopenharmony_ci unsigned int len) 41362306a36Sopenharmony_ci{ 41462306a36Sopenharmony_ci unsigned int n; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci n = min(len, QSPI_BUFFER_SIZE); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci if (len >= QSPI_BUFFER_SIZE) { 41962306a36Sopenharmony_ci /* sets triggering number to 32 bytes */ 42062306a36Sopenharmony_ci qspi_update(rspi, SPBFCR_TXTRG_MASK, 42162306a36Sopenharmony_ci SPBFCR_TXTRG_32B, QSPI_SPBFCR); 42262306a36Sopenharmony_ci } else { 42362306a36Sopenharmony_ci /* sets triggering number to 1 byte */ 42462306a36Sopenharmony_ci qspi_update(rspi, SPBFCR_TXTRG_MASK, 42562306a36Sopenharmony_ci SPBFCR_TXTRG_1B, QSPI_SPBFCR); 42662306a36Sopenharmony_ci } 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci return n; 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_cistatic int qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len) 43262306a36Sopenharmony_ci{ 43362306a36Sopenharmony_ci unsigned int n; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci n = min(len, QSPI_BUFFER_SIZE); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci if (len >= QSPI_BUFFER_SIZE) { 43862306a36Sopenharmony_ci /* sets triggering number to 32 bytes */ 43962306a36Sopenharmony_ci qspi_update(rspi, SPBFCR_RXTRG_MASK, 44062306a36Sopenharmony_ci SPBFCR_RXTRG_32B, QSPI_SPBFCR); 44162306a36Sopenharmony_ci } else { 44262306a36Sopenharmony_ci /* sets triggering number to 1 byte */ 44362306a36Sopenharmony_ci qspi_update(rspi, SPBFCR_RXTRG_MASK, 44462306a36Sopenharmony_ci SPBFCR_RXTRG_1B, QSPI_SPBFCR); 44562306a36Sopenharmony_ci } 44662306a36Sopenharmony_ci return n; 44762306a36Sopenharmony_ci} 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic void rspi_enable_irq(const struct rspi_data *rspi, u8 enable) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR); 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cistatic void rspi_disable_irq(const struct rspi_data *rspi, u8 disable) 45562306a36Sopenharmony_ci{ 45662306a36Sopenharmony_ci rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~disable, RSPI_SPCR); 45762306a36Sopenharmony_ci} 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_cistatic int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask, 46062306a36Sopenharmony_ci u8 enable_bit) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci int ret; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci rspi->spsr = rspi_read8(rspi, RSPI_SPSR); 46562306a36Sopenharmony_ci if (rspi->spsr & wait_mask) 46662306a36Sopenharmony_ci return 0; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci rspi_enable_irq(rspi, enable_bit); 46962306a36Sopenharmony_ci ret = wait_event_timeout(rspi->wait, rspi->spsr & wait_mask, HZ); 47062306a36Sopenharmony_ci if (ret == 0 && !(rspi->spsr & wait_mask)) 47162306a36Sopenharmony_ci return -ETIMEDOUT; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci return 0; 47462306a36Sopenharmony_ci} 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_cistatic inline int rspi_wait_for_tx_empty(struct rspi_data *rspi) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci return rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); 47962306a36Sopenharmony_ci} 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_cistatic inline int rspi_wait_for_rx_full(struct rspi_data *rspi) 48262306a36Sopenharmony_ci{ 48362306a36Sopenharmony_ci return rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE); 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_cistatic int rspi_data_out(struct rspi_data *rspi, u8 data) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci int error = rspi_wait_for_tx_empty(rspi); 48962306a36Sopenharmony_ci if (error < 0) { 49062306a36Sopenharmony_ci dev_err(&rspi->ctlr->dev, "transmit timeout\n"); 49162306a36Sopenharmony_ci return error; 49262306a36Sopenharmony_ci } 49362306a36Sopenharmony_ci rspi_write_data(rspi, data); 49462306a36Sopenharmony_ci return 0; 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_cistatic int rspi_data_in(struct rspi_data *rspi) 49862306a36Sopenharmony_ci{ 49962306a36Sopenharmony_ci int error; 50062306a36Sopenharmony_ci u8 data; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci error = rspi_wait_for_rx_full(rspi); 50362306a36Sopenharmony_ci if (error < 0) { 50462306a36Sopenharmony_ci dev_err(&rspi->ctlr->dev, "receive timeout\n"); 50562306a36Sopenharmony_ci return error; 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci data = rspi_read_data(rspi); 50862306a36Sopenharmony_ci return data; 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cistatic int rspi_pio_transfer(struct rspi_data *rspi, const u8 *tx, u8 *rx, 51262306a36Sopenharmony_ci unsigned int n) 51362306a36Sopenharmony_ci{ 51462306a36Sopenharmony_ci while (n-- > 0) { 51562306a36Sopenharmony_ci if (tx) { 51662306a36Sopenharmony_ci int ret = rspi_data_out(rspi, *tx++); 51762306a36Sopenharmony_ci if (ret < 0) 51862306a36Sopenharmony_ci return ret; 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci if (rx) { 52162306a36Sopenharmony_ci int ret = rspi_data_in(rspi); 52262306a36Sopenharmony_ci if (ret < 0) 52362306a36Sopenharmony_ci return ret; 52462306a36Sopenharmony_ci *rx++ = ret; 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci return 0; 52962306a36Sopenharmony_ci} 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_cistatic void rspi_dma_complete(void *arg) 53262306a36Sopenharmony_ci{ 53362306a36Sopenharmony_ci struct rspi_data *rspi = arg; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci rspi->dma_callbacked = 1; 53662306a36Sopenharmony_ci wake_up_interruptible(&rspi->wait); 53762306a36Sopenharmony_ci} 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_cistatic int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, 54062306a36Sopenharmony_ci struct sg_table *rx) 54162306a36Sopenharmony_ci{ 54262306a36Sopenharmony_ci struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL; 54362306a36Sopenharmony_ci u8 irq_mask = 0; 54462306a36Sopenharmony_ci unsigned int other_irq = 0; 54562306a36Sopenharmony_ci dma_cookie_t cookie; 54662306a36Sopenharmony_ci int ret; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci /* First prepare and submit the DMA request(s), as this may fail */ 54962306a36Sopenharmony_ci if (rx) { 55062306a36Sopenharmony_ci desc_rx = dmaengine_prep_slave_sg(rspi->ctlr->dma_rx, rx->sgl, 55162306a36Sopenharmony_ci rx->nents, DMA_DEV_TO_MEM, 55262306a36Sopenharmony_ci DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 55362306a36Sopenharmony_ci if (!desc_rx) { 55462306a36Sopenharmony_ci ret = -EAGAIN; 55562306a36Sopenharmony_ci goto no_dma_rx; 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci desc_rx->callback = rspi_dma_complete; 55962306a36Sopenharmony_ci desc_rx->callback_param = rspi; 56062306a36Sopenharmony_ci cookie = dmaengine_submit(desc_rx); 56162306a36Sopenharmony_ci if (dma_submit_error(cookie)) { 56262306a36Sopenharmony_ci ret = cookie; 56362306a36Sopenharmony_ci goto no_dma_rx; 56462306a36Sopenharmony_ci } 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci irq_mask |= SPCR_SPRIE; 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci if (tx) { 57062306a36Sopenharmony_ci desc_tx = dmaengine_prep_slave_sg(rspi->ctlr->dma_tx, tx->sgl, 57162306a36Sopenharmony_ci tx->nents, DMA_MEM_TO_DEV, 57262306a36Sopenharmony_ci DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 57362306a36Sopenharmony_ci if (!desc_tx) { 57462306a36Sopenharmony_ci ret = -EAGAIN; 57562306a36Sopenharmony_ci goto no_dma_tx; 57662306a36Sopenharmony_ci } 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci if (rx) { 57962306a36Sopenharmony_ci /* No callback */ 58062306a36Sopenharmony_ci desc_tx->callback = NULL; 58162306a36Sopenharmony_ci } else { 58262306a36Sopenharmony_ci desc_tx->callback = rspi_dma_complete; 58362306a36Sopenharmony_ci desc_tx->callback_param = rspi; 58462306a36Sopenharmony_ci } 58562306a36Sopenharmony_ci cookie = dmaengine_submit(desc_tx); 58662306a36Sopenharmony_ci if (dma_submit_error(cookie)) { 58762306a36Sopenharmony_ci ret = cookie; 58862306a36Sopenharmony_ci goto no_dma_tx; 58962306a36Sopenharmony_ci } 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci irq_mask |= SPCR_SPTIE; 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci /* 59562306a36Sopenharmony_ci * DMAC needs SPxIE, but if SPxIE is set, the IRQ routine will be 59662306a36Sopenharmony_ci * called. So, this driver disables the IRQ while DMA transfer. 59762306a36Sopenharmony_ci */ 59862306a36Sopenharmony_ci if (tx) 59962306a36Sopenharmony_ci disable_irq(other_irq = rspi->tx_irq); 60062306a36Sopenharmony_ci if (rx && rspi->rx_irq != other_irq) 60162306a36Sopenharmony_ci disable_irq(rspi->rx_irq); 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci rspi_enable_irq(rspi, irq_mask); 60462306a36Sopenharmony_ci rspi->dma_callbacked = 0; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci /* Now start DMA */ 60762306a36Sopenharmony_ci if (rx) 60862306a36Sopenharmony_ci dma_async_issue_pending(rspi->ctlr->dma_rx); 60962306a36Sopenharmony_ci if (tx) 61062306a36Sopenharmony_ci dma_async_issue_pending(rspi->ctlr->dma_tx); 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci ret = wait_event_interruptible_timeout(rspi->wait, 61362306a36Sopenharmony_ci rspi->dma_callbacked, HZ); 61462306a36Sopenharmony_ci if (ret > 0 && rspi->dma_callbacked) { 61562306a36Sopenharmony_ci ret = 0; 61662306a36Sopenharmony_ci if (tx) 61762306a36Sopenharmony_ci dmaengine_synchronize(rspi->ctlr->dma_tx); 61862306a36Sopenharmony_ci if (rx) 61962306a36Sopenharmony_ci dmaengine_synchronize(rspi->ctlr->dma_rx); 62062306a36Sopenharmony_ci } else { 62162306a36Sopenharmony_ci if (!ret) { 62262306a36Sopenharmony_ci dev_err(&rspi->ctlr->dev, "DMA timeout\n"); 62362306a36Sopenharmony_ci ret = -ETIMEDOUT; 62462306a36Sopenharmony_ci } 62562306a36Sopenharmony_ci if (tx) 62662306a36Sopenharmony_ci dmaengine_terminate_sync(rspi->ctlr->dma_tx); 62762306a36Sopenharmony_ci if (rx) 62862306a36Sopenharmony_ci dmaengine_terminate_sync(rspi->ctlr->dma_rx); 62962306a36Sopenharmony_ci } 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci rspi_disable_irq(rspi, irq_mask); 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci if (tx) 63462306a36Sopenharmony_ci enable_irq(rspi->tx_irq); 63562306a36Sopenharmony_ci if (rx && rspi->rx_irq != other_irq) 63662306a36Sopenharmony_ci enable_irq(rspi->rx_irq); 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci return ret; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_cino_dma_tx: 64162306a36Sopenharmony_ci if (rx) 64262306a36Sopenharmony_ci dmaengine_terminate_sync(rspi->ctlr->dma_rx); 64362306a36Sopenharmony_cino_dma_rx: 64462306a36Sopenharmony_ci if (ret == -EAGAIN) { 64562306a36Sopenharmony_ci dev_warn_once(&rspi->ctlr->dev, 64662306a36Sopenharmony_ci "DMA not available, falling back to PIO\n"); 64762306a36Sopenharmony_ci } 64862306a36Sopenharmony_ci return ret; 64962306a36Sopenharmony_ci} 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_cistatic void rspi_receive_init(const struct rspi_data *rspi) 65262306a36Sopenharmony_ci{ 65362306a36Sopenharmony_ci u8 spsr; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci spsr = rspi_read8(rspi, RSPI_SPSR); 65662306a36Sopenharmony_ci if (spsr & SPSR_SPRF) 65762306a36Sopenharmony_ci rspi_read_data(rspi); /* dummy read */ 65862306a36Sopenharmony_ci if (spsr & SPSR_OVRF) 65962306a36Sopenharmony_ci rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF, 66062306a36Sopenharmony_ci RSPI_SPSR); 66162306a36Sopenharmony_ci} 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_cistatic void rspi_rz_receive_init(const struct rspi_data *rspi) 66462306a36Sopenharmony_ci{ 66562306a36Sopenharmony_ci rspi_receive_init(rspi); 66662306a36Sopenharmony_ci rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, RSPI_SPBFCR); 66762306a36Sopenharmony_ci rspi_write8(rspi, 0, RSPI_SPBFCR); 66862306a36Sopenharmony_ci} 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_cistatic void qspi_receive_init(const struct rspi_data *rspi) 67162306a36Sopenharmony_ci{ 67262306a36Sopenharmony_ci u8 spsr; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci spsr = rspi_read8(rspi, RSPI_SPSR); 67562306a36Sopenharmony_ci if (spsr & SPSR_SPRF) 67662306a36Sopenharmony_ci rspi_read_data(rspi); /* dummy read */ 67762306a36Sopenharmony_ci rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR); 67862306a36Sopenharmony_ci rspi_write8(rspi, 0, QSPI_SPBFCR); 67962306a36Sopenharmony_ci} 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_cistatic bool __rspi_can_dma(const struct rspi_data *rspi, 68262306a36Sopenharmony_ci const struct spi_transfer *xfer) 68362306a36Sopenharmony_ci{ 68462306a36Sopenharmony_ci return xfer->len > rspi->ops->fifo_size; 68562306a36Sopenharmony_ci} 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_cistatic bool rspi_can_dma(struct spi_controller *ctlr, struct spi_device *spi, 68862306a36Sopenharmony_ci struct spi_transfer *xfer) 68962306a36Sopenharmony_ci{ 69062306a36Sopenharmony_ci struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci return __rspi_can_dma(rspi, xfer); 69362306a36Sopenharmony_ci} 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_cistatic int rspi_dma_check_then_transfer(struct rspi_data *rspi, 69662306a36Sopenharmony_ci struct spi_transfer *xfer) 69762306a36Sopenharmony_ci{ 69862306a36Sopenharmony_ci if (!rspi->ctlr->can_dma || !__rspi_can_dma(rspi, xfer)) 69962306a36Sopenharmony_ci return -EAGAIN; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci /* rx_buf can be NULL on RSPI on SH in TX-only Mode */ 70262306a36Sopenharmony_ci return rspi_dma_transfer(rspi, &xfer->tx_sg, 70362306a36Sopenharmony_ci xfer->rx_buf ? &xfer->rx_sg : NULL); 70462306a36Sopenharmony_ci} 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_cistatic int rspi_common_transfer(struct rspi_data *rspi, 70762306a36Sopenharmony_ci struct spi_transfer *xfer) 70862306a36Sopenharmony_ci{ 70962306a36Sopenharmony_ci int ret; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci xfer->effective_speed_hz = rspi->speed_hz; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci ret = rspi_dma_check_then_transfer(rspi, xfer); 71462306a36Sopenharmony_ci if (ret != -EAGAIN) 71562306a36Sopenharmony_ci return ret; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len); 71862306a36Sopenharmony_ci if (ret < 0) 71962306a36Sopenharmony_ci return ret; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci /* Wait for the last transmission */ 72262306a36Sopenharmony_ci rspi_wait_for_tx_empty(rspi); 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci return 0; 72562306a36Sopenharmony_ci} 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_cistatic int rspi_transfer_one(struct spi_controller *ctlr, 72862306a36Sopenharmony_ci struct spi_device *spi, struct spi_transfer *xfer) 72962306a36Sopenharmony_ci{ 73062306a36Sopenharmony_ci struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 73162306a36Sopenharmony_ci u8 spcr; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci spcr = rspi_read8(rspi, RSPI_SPCR); 73462306a36Sopenharmony_ci if (xfer->rx_buf) { 73562306a36Sopenharmony_ci rspi_receive_init(rspi); 73662306a36Sopenharmony_ci spcr &= ~SPCR_TXMD; 73762306a36Sopenharmony_ci } else { 73862306a36Sopenharmony_ci spcr |= SPCR_TXMD; 73962306a36Sopenharmony_ci } 74062306a36Sopenharmony_ci rspi_write8(rspi, spcr, RSPI_SPCR); 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci return rspi_common_transfer(rspi, xfer); 74362306a36Sopenharmony_ci} 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_cistatic int rspi_rz_transfer_one(struct spi_controller *ctlr, 74662306a36Sopenharmony_ci struct spi_device *spi, 74762306a36Sopenharmony_ci struct spi_transfer *xfer) 74862306a36Sopenharmony_ci{ 74962306a36Sopenharmony_ci struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci rspi_rz_receive_init(rspi); 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci return rspi_common_transfer(rspi, xfer); 75462306a36Sopenharmony_ci} 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_cistatic int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx, 75762306a36Sopenharmony_ci u8 *rx, unsigned int len) 75862306a36Sopenharmony_ci{ 75962306a36Sopenharmony_ci unsigned int i, n; 76062306a36Sopenharmony_ci int ret; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci while (len > 0) { 76362306a36Sopenharmony_ci n = qspi_set_send_trigger(rspi, len); 76462306a36Sopenharmony_ci qspi_set_receive_trigger(rspi, len); 76562306a36Sopenharmony_ci ret = rspi_wait_for_tx_empty(rspi); 76662306a36Sopenharmony_ci if (ret < 0) { 76762306a36Sopenharmony_ci dev_err(&rspi->ctlr->dev, "transmit timeout\n"); 76862306a36Sopenharmony_ci return ret; 76962306a36Sopenharmony_ci } 77062306a36Sopenharmony_ci for (i = 0; i < n; i++) 77162306a36Sopenharmony_ci rspi_write_data(rspi, *tx++); 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci ret = rspi_wait_for_rx_full(rspi); 77462306a36Sopenharmony_ci if (ret < 0) { 77562306a36Sopenharmony_ci dev_err(&rspi->ctlr->dev, "receive timeout\n"); 77662306a36Sopenharmony_ci return ret; 77762306a36Sopenharmony_ci } 77862306a36Sopenharmony_ci for (i = 0; i < n; i++) 77962306a36Sopenharmony_ci *rx++ = rspi_read_data(rspi); 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci len -= n; 78262306a36Sopenharmony_ci } 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci return 0; 78562306a36Sopenharmony_ci} 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_cistatic int qspi_transfer_out_in(struct rspi_data *rspi, 78862306a36Sopenharmony_ci struct spi_transfer *xfer) 78962306a36Sopenharmony_ci{ 79062306a36Sopenharmony_ci int ret; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci qspi_receive_init(rspi); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci ret = rspi_dma_check_then_transfer(rspi, xfer); 79562306a36Sopenharmony_ci if (ret != -EAGAIN) 79662306a36Sopenharmony_ci return ret; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci return qspi_trigger_transfer_out_in(rspi, xfer->tx_buf, 79962306a36Sopenharmony_ci xfer->rx_buf, xfer->len); 80062306a36Sopenharmony_ci} 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_cistatic int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) 80362306a36Sopenharmony_ci{ 80462306a36Sopenharmony_ci const u8 *tx = xfer->tx_buf; 80562306a36Sopenharmony_ci unsigned int n = xfer->len; 80662306a36Sopenharmony_ci unsigned int i, len; 80762306a36Sopenharmony_ci int ret; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci if (rspi->ctlr->can_dma && __rspi_can_dma(rspi, xfer)) { 81062306a36Sopenharmony_ci ret = rspi_dma_transfer(rspi, &xfer->tx_sg, NULL); 81162306a36Sopenharmony_ci if (ret != -EAGAIN) 81262306a36Sopenharmony_ci return ret; 81362306a36Sopenharmony_ci } 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci while (n > 0) { 81662306a36Sopenharmony_ci len = qspi_set_send_trigger(rspi, n); 81762306a36Sopenharmony_ci ret = rspi_wait_for_tx_empty(rspi); 81862306a36Sopenharmony_ci if (ret < 0) { 81962306a36Sopenharmony_ci dev_err(&rspi->ctlr->dev, "transmit timeout\n"); 82062306a36Sopenharmony_ci return ret; 82162306a36Sopenharmony_ci } 82262306a36Sopenharmony_ci for (i = 0; i < len; i++) 82362306a36Sopenharmony_ci rspi_write_data(rspi, *tx++); 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci n -= len; 82662306a36Sopenharmony_ci } 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci /* Wait for the last transmission */ 82962306a36Sopenharmony_ci rspi_wait_for_tx_empty(rspi); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci return 0; 83262306a36Sopenharmony_ci} 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_cistatic int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) 83562306a36Sopenharmony_ci{ 83662306a36Sopenharmony_ci u8 *rx = xfer->rx_buf; 83762306a36Sopenharmony_ci unsigned int n = xfer->len; 83862306a36Sopenharmony_ci unsigned int i, len; 83962306a36Sopenharmony_ci int ret; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci if (rspi->ctlr->can_dma && __rspi_can_dma(rspi, xfer)) { 84262306a36Sopenharmony_ci ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg); 84362306a36Sopenharmony_ci if (ret != -EAGAIN) 84462306a36Sopenharmony_ci return ret; 84562306a36Sopenharmony_ci } 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci while (n > 0) { 84862306a36Sopenharmony_ci len = qspi_set_receive_trigger(rspi, n); 84962306a36Sopenharmony_ci ret = rspi_wait_for_rx_full(rspi); 85062306a36Sopenharmony_ci if (ret < 0) { 85162306a36Sopenharmony_ci dev_err(&rspi->ctlr->dev, "receive timeout\n"); 85262306a36Sopenharmony_ci return ret; 85362306a36Sopenharmony_ci } 85462306a36Sopenharmony_ci for (i = 0; i < len; i++) 85562306a36Sopenharmony_ci *rx++ = rspi_read_data(rspi); 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci n -= len; 85862306a36Sopenharmony_ci } 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci return 0; 86162306a36Sopenharmony_ci} 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_cistatic int qspi_transfer_one(struct spi_controller *ctlr, 86462306a36Sopenharmony_ci struct spi_device *spi, struct spi_transfer *xfer) 86562306a36Sopenharmony_ci{ 86662306a36Sopenharmony_ci struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci xfer->effective_speed_hz = rspi->speed_hz; 86962306a36Sopenharmony_ci if (spi->mode & SPI_LOOP) { 87062306a36Sopenharmony_ci return qspi_transfer_out_in(rspi, xfer); 87162306a36Sopenharmony_ci } else if (xfer->tx_nbits > SPI_NBITS_SINGLE) { 87262306a36Sopenharmony_ci /* Quad or Dual SPI Write */ 87362306a36Sopenharmony_ci return qspi_transfer_out(rspi, xfer); 87462306a36Sopenharmony_ci } else if (xfer->rx_nbits > SPI_NBITS_SINGLE) { 87562306a36Sopenharmony_ci /* Quad or Dual SPI Read */ 87662306a36Sopenharmony_ci return qspi_transfer_in(rspi, xfer); 87762306a36Sopenharmony_ci } else { 87862306a36Sopenharmony_ci /* Single SPI Transfer */ 87962306a36Sopenharmony_ci return qspi_transfer_out_in(rspi, xfer); 88062306a36Sopenharmony_ci } 88162306a36Sopenharmony_ci} 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_cistatic u16 qspi_transfer_mode(const struct spi_transfer *xfer) 88462306a36Sopenharmony_ci{ 88562306a36Sopenharmony_ci if (xfer->tx_buf) 88662306a36Sopenharmony_ci switch (xfer->tx_nbits) { 88762306a36Sopenharmony_ci case SPI_NBITS_QUAD: 88862306a36Sopenharmony_ci return SPCMD_SPIMOD_QUAD; 88962306a36Sopenharmony_ci case SPI_NBITS_DUAL: 89062306a36Sopenharmony_ci return SPCMD_SPIMOD_DUAL; 89162306a36Sopenharmony_ci default: 89262306a36Sopenharmony_ci return 0; 89362306a36Sopenharmony_ci } 89462306a36Sopenharmony_ci if (xfer->rx_buf) 89562306a36Sopenharmony_ci switch (xfer->rx_nbits) { 89662306a36Sopenharmony_ci case SPI_NBITS_QUAD: 89762306a36Sopenharmony_ci return SPCMD_SPIMOD_QUAD | SPCMD_SPRW; 89862306a36Sopenharmony_ci case SPI_NBITS_DUAL: 89962306a36Sopenharmony_ci return SPCMD_SPIMOD_DUAL | SPCMD_SPRW; 90062306a36Sopenharmony_ci default: 90162306a36Sopenharmony_ci return 0; 90262306a36Sopenharmony_ci } 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci return 0; 90562306a36Sopenharmony_ci} 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_cistatic int qspi_setup_sequencer(struct rspi_data *rspi, 90862306a36Sopenharmony_ci const struct spi_message *msg) 90962306a36Sopenharmony_ci{ 91062306a36Sopenharmony_ci const struct spi_transfer *xfer; 91162306a36Sopenharmony_ci unsigned int i = 0, len = 0; 91262306a36Sopenharmony_ci u16 current_mode = 0xffff, mode; 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci list_for_each_entry(xfer, &msg->transfers, transfer_list) { 91562306a36Sopenharmony_ci mode = qspi_transfer_mode(xfer); 91662306a36Sopenharmony_ci if (mode == current_mode) { 91762306a36Sopenharmony_ci len += xfer->len; 91862306a36Sopenharmony_ci continue; 91962306a36Sopenharmony_ci } 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci /* Transfer mode change */ 92262306a36Sopenharmony_ci if (i) { 92362306a36Sopenharmony_ci /* Set transfer data length of previous transfer */ 92462306a36Sopenharmony_ci rspi_write32(rspi, len, QSPI_SPBMUL(i - 1)); 92562306a36Sopenharmony_ci } 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci if (i >= QSPI_NUM_SPCMD) { 92862306a36Sopenharmony_ci dev_err(&msg->spi->dev, 92962306a36Sopenharmony_ci "Too many different transfer modes"); 93062306a36Sopenharmony_ci return -EINVAL; 93162306a36Sopenharmony_ci } 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci /* Program transfer mode for this transfer */ 93462306a36Sopenharmony_ci rspi_write16(rspi, rspi->spcmd | mode, RSPI_SPCMD(i)); 93562306a36Sopenharmony_ci current_mode = mode; 93662306a36Sopenharmony_ci len = xfer->len; 93762306a36Sopenharmony_ci i++; 93862306a36Sopenharmony_ci } 93962306a36Sopenharmony_ci if (i) { 94062306a36Sopenharmony_ci /* Set final transfer data length and sequence length */ 94162306a36Sopenharmony_ci rspi_write32(rspi, len, QSPI_SPBMUL(i - 1)); 94262306a36Sopenharmony_ci rspi_write8(rspi, i - 1, RSPI_SPSCR); 94362306a36Sopenharmony_ci } 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci return 0; 94662306a36Sopenharmony_ci} 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_cistatic int rspi_setup(struct spi_device *spi) 94962306a36Sopenharmony_ci{ 95062306a36Sopenharmony_ci struct rspi_data *rspi = spi_controller_get_devdata(spi->controller); 95162306a36Sopenharmony_ci u8 sslp; 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci if (spi_get_csgpiod(spi, 0)) 95462306a36Sopenharmony_ci return 0; 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci pm_runtime_get_sync(&rspi->pdev->dev); 95762306a36Sopenharmony_ci spin_lock_irq(&rspi->lock); 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci sslp = rspi_read8(rspi, RSPI_SSLP); 96062306a36Sopenharmony_ci if (spi->mode & SPI_CS_HIGH) 96162306a36Sopenharmony_ci sslp |= SSLP_SSLP(spi_get_chipselect(spi, 0)); 96262306a36Sopenharmony_ci else 96362306a36Sopenharmony_ci sslp &= ~SSLP_SSLP(spi_get_chipselect(spi, 0)); 96462306a36Sopenharmony_ci rspi_write8(rspi, sslp, RSPI_SSLP); 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci spin_unlock_irq(&rspi->lock); 96762306a36Sopenharmony_ci pm_runtime_put(&rspi->pdev->dev); 96862306a36Sopenharmony_ci return 0; 96962306a36Sopenharmony_ci} 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_cistatic int rspi_prepare_message(struct spi_controller *ctlr, 97262306a36Sopenharmony_ci struct spi_message *msg) 97362306a36Sopenharmony_ci{ 97462306a36Sopenharmony_ci struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 97562306a36Sopenharmony_ci struct spi_device *spi = msg->spi; 97662306a36Sopenharmony_ci const struct spi_transfer *xfer; 97762306a36Sopenharmony_ci int ret; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci /* 98062306a36Sopenharmony_ci * As the Bit Rate Register must not be changed while the device is 98162306a36Sopenharmony_ci * active, all transfers in a message must use the same bit rate. 98262306a36Sopenharmony_ci * In theory, the sequencer could be enabled, and each Command Register 98362306a36Sopenharmony_ci * could divide the base bit rate by a different value. 98462306a36Sopenharmony_ci * However, most RSPI variants do not have Transfer Data Length 98562306a36Sopenharmony_ci * Multiplier Setting Registers, so each sequence step would be limited 98662306a36Sopenharmony_ci * to a single word, making this feature unsuitable for large 98762306a36Sopenharmony_ci * transfers, which would gain most from it. 98862306a36Sopenharmony_ci */ 98962306a36Sopenharmony_ci rspi->speed_hz = spi->max_speed_hz; 99062306a36Sopenharmony_ci list_for_each_entry(xfer, &msg->transfers, transfer_list) { 99162306a36Sopenharmony_ci if (xfer->speed_hz < rspi->speed_hz) 99262306a36Sopenharmony_ci rspi->speed_hz = xfer->speed_hz; 99362306a36Sopenharmony_ci } 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci rspi->spcmd = SPCMD_SSLKP; 99662306a36Sopenharmony_ci if (spi->mode & SPI_CPOL) 99762306a36Sopenharmony_ci rspi->spcmd |= SPCMD_CPOL; 99862306a36Sopenharmony_ci if (spi->mode & SPI_CPHA) 99962306a36Sopenharmony_ci rspi->spcmd |= SPCMD_CPHA; 100062306a36Sopenharmony_ci if (spi->mode & SPI_LSB_FIRST) 100162306a36Sopenharmony_ci rspi->spcmd |= SPCMD_LSBF; 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci /* Configure slave signal to assert */ 100462306a36Sopenharmony_ci rspi->spcmd |= SPCMD_SSLA(spi_get_csgpiod(spi, 0) ? rspi->ctlr->unused_native_cs 100562306a36Sopenharmony_ci : spi_get_chipselect(spi, 0)); 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci /* CMOS output mode and MOSI signal from previous transfer */ 100862306a36Sopenharmony_ci rspi->sppcr = 0; 100962306a36Sopenharmony_ci if (spi->mode & SPI_LOOP) 101062306a36Sopenharmony_ci rspi->sppcr |= SPPCR_SPLP; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci rspi->ops->set_config_register(rspi, 8); 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci if (msg->spi->mode & 101562306a36Sopenharmony_ci (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)) { 101662306a36Sopenharmony_ci /* Setup sequencer for messages with multiple transfer modes */ 101762306a36Sopenharmony_ci ret = qspi_setup_sequencer(rspi, msg); 101862306a36Sopenharmony_ci if (ret < 0) 101962306a36Sopenharmony_ci return ret; 102062306a36Sopenharmony_ci } 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci /* Enable SPI function in master mode */ 102362306a36Sopenharmony_ci rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR); 102462306a36Sopenharmony_ci return 0; 102562306a36Sopenharmony_ci} 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_cistatic int rspi_unprepare_message(struct spi_controller *ctlr, 102862306a36Sopenharmony_ci struct spi_message *msg) 102962306a36Sopenharmony_ci{ 103062306a36Sopenharmony_ci struct rspi_data *rspi = spi_controller_get_devdata(ctlr); 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci /* Disable SPI function */ 103362306a36Sopenharmony_ci rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR); 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci /* Reset sequencer for Single SPI Transfers */ 103662306a36Sopenharmony_ci rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); 103762306a36Sopenharmony_ci rspi_write8(rspi, 0, RSPI_SPSCR); 103862306a36Sopenharmony_ci return 0; 103962306a36Sopenharmony_ci} 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_cistatic irqreturn_t rspi_irq_mux(int irq, void *_sr) 104262306a36Sopenharmony_ci{ 104362306a36Sopenharmony_ci struct rspi_data *rspi = _sr; 104462306a36Sopenharmony_ci u8 spsr; 104562306a36Sopenharmony_ci irqreturn_t ret = IRQ_NONE; 104662306a36Sopenharmony_ci u8 disable_irq = 0; 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR); 104962306a36Sopenharmony_ci if (spsr & SPSR_SPRF) 105062306a36Sopenharmony_ci disable_irq |= SPCR_SPRIE; 105162306a36Sopenharmony_ci if (spsr & SPSR_SPTEF) 105262306a36Sopenharmony_ci disable_irq |= SPCR_SPTIE; 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci if (disable_irq) { 105562306a36Sopenharmony_ci ret = IRQ_HANDLED; 105662306a36Sopenharmony_ci rspi_disable_irq(rspi, disable_irq); 105762306a36Sopenharmony_ci wake_up(&rspi->wait); 105862306a36Sopenharmony_ci } 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci return ret; 106162306a36Sopenharmony_ci} 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_cistatic irqreturn_t rspi_irq_rx(int irq, void *_sr) 106462306a36Sopenharmony_ci{ 106562306a36Sopenharmony_ci struct rspi_data *rspi = _sr; 106662306a36Sopenharmony_ci u8 spsr; 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR); 106962306a36Sopenharmony_ci if (spsr & SPSR_SPRF) { 107062306a36Sopenharmony_ci rspi_disable_irq(rspi, SPCR_SPRIE); 107162306a36Sopenharmony_ci wake_up(&rspi->wait); 107262306a36Sopenharmony_ci return IRQ_HANDLED; 107362306a36Sopenharmony_ci } 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci return 0; 107662306a36Sopenharmony_ci} 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_cistatic irqreturn_t rspi_irq_tx(int irq, void *_sr) 107962306a36Sopenharmony_ci{ 108062306a36Sopenharmony_ci struct rspi_data *rspi = _sr; 108162306a36Sopenharmony_ci u8 spsr; 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR); 108462306a36Sopenharmony_ci if (spsr & SPSR_SPTEF) { 108562306a36Sopenharmony_ci rspi_disable_irq(rspi, SPCR_SPTIE); 108662306a36Sopenharmony_ci wake_up(&rspi->wait); 108762306a36Sopenharmony_ci return IRQ_HANDLED; 108862306a36Sopenharmony_ci } 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci return 0; 109162306a36Sopenharmony_ci} 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_cistatic struct dma_chan *rspi_request_dma_chan(struct device *dev, 109462306a36Sopenharmony_ci enum dma_transfer_direction dir, 109562306a36Sopenharmony_ci unsigned int id, 109662306a36Sopenharmony_ci dma_addr_t port_addr) 109762306a36Sopenharmony_ci{ 109862306a36Sopenharmony_ci dma_cap_mask_t mask; 109962306a36Sopenharmony_ci struct dma_chan *chan; 110062306a36Sopenharmony_ci struct dma_slave_config cfg; 110162306a36Sopenharmony_ci int ret; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci dma_cap_zero(mask); 110462306a36Sopenharmony_ci dma_cap_set(DMA_SLAVE, mask); 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, 110762306a36Sopenharmony_ci (void *)(unsigned long)id, dev, 110862306a36Sopenharmony_ci dir == DMA_MEM_TO_DEV ? "tx" : "rx"); 110962306a36Sopenharmony_ci if (!chan) { 111062306a36Sopenharmony_ci dev_warn(dev, "dma_request_slave_channel_compat failed\n"); 111162306a36Sopenharmony_ci return NULL; 111262306a36Sopenharmony_ci } 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci memset(&cfg, 0, sizeof(cfg)); 111562306a36Sopenharmony_ci cfg.dst_addr = port_addr + RSPI_SPDR; 111662306a36Sopenharmony_ci cfg.src_addr = port_addr + RSPI_SPDR; 111762306a36Sopenharmony_ci cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; 111862306a36Sopenharmony_ci cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; 111962306a36Sopenharmony_ci cfg.direction = dir; 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci ret = dmaengine_slave_config(chan, &cfg); 112262306a36Sopenharmony_ci if (ret) { 112362306a36Sopenharmony_ci dev_warn(dev, "dmaengine_slave_config failed %d\n", ret); 112462306a36Sopenharmony_ci dma_release_channel(chan); 112562306a36Sopenharmony_ci return NULL; 112662306a36Sopenharmony_ci } 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci return chan; 112962306a36Sopenharmony_ci} 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_cistatic int rspi_request_dma(struct device *dev, struct spi_controller *ctlr, 113262306a36Sopenharmony_ci const struct resource *res) 113362306a36Sopenharmony_ci{ 113462306a36Sopenharmony_ci const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev); 113562306a36Sopenharmony_ci unsigned int dma_tx_id, dma_rx_id; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci if (dev->of_node) { 113862306a36Sopenharmony_ci /* In the OF case we will get the slave IDs from the DT */ 113962306a36Sopenharmony_ci dma_tx_id = 0; 114062306a36Sopenharmony_ci dma_rx_id = 0; 114162306a36Sopenharmony_ci } else if (rspi_pd && rspi_pd->dma_tx_id && rspi_pd->dma_rx_id) { 114262306a36Sopenharmony_ci dma_tx_id = rspi_pd->dma_tx_id; 114362306a36Sopenharmony_ci dma_rx_id = rspi_pd->dma_rx_id; 114462306a36Sopenharmony_ci } else { 114562306a36Sopenharmony_ci /* The driver assumes no error. */ 114662306a36Sopenharmony_ci return 0; 114762306a36Sopenharmony_ci } 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci ctlr->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, dma_tx_id, 115062306a36Sopenharmony_ci res->start); 115162306a36Sopenharmony_ci if (!ctlr->dma_tx) 115262306a36Sopenharmony_ci return -ENODEV; 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci ctlr->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, dma_rx_id, 115562306a36Sopenharmony_ci res->start); 115662306a36Sopenharmony_ci if (!ctlr->dma_rx) { 115762306a36Sopenharmony_ci dma_release_channel(ctlr->dma_tx); 115862306a36Sopenharmony_ci ctlr->dma_tx = NULL; 115962306a36Sopenharmony_ci return -ENODEV; 116062306a36Sopenharmony_ci } 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci ctlr->can_dma = rspi_can_dma; 116362306a36Sopenharmony_ci dev_info(dev, "DMA available"); 116462306a36Sopenharmony_ci return 0; 116562306a36Sopenharmony_ci} 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_cistatic void rspi_release_dma(struct spi_controller *ctlr) 116862306a36Sopenharmony_ci{ 116962306a36Sopenharmony_ci if (ctlr->dma_tx) 117062306a36Sopenharmony_ci dma_release_channel(ctlr->dma_tx); 117162306a36Sopenharmony_ci if (ctlr->dma_rx) 117262306a36Sopenharmony_ci dma_release_channel(ctlr->dma_rx); 117362306a36Sopenharmony_ci} 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_cistatic void rspi_remove(struct platform_device *pdev) 117662306a36Sopenharmony_ci{ 117762306a36Sopenharmony_ci struct rspi_data *rspi = platform_get_drvdata(pdev); 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci rspi_release_dma(rspi->ctlr); 118062306a36Sopenharmony_ci pm_runtime_disable(&pdev->dev); 118162306a36Sopenharmony_ci} 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_cistatic const struct spi_ops rspi_ops = { 118462306a36Sopenharmony_ci .set_config_register = rspi_set_config_register, 118562306a36Sopenharmony_ci .transfer_one = rspi_transfer_one, 118662306a36Sopenharmony_ci .min_div = 2, 118762306a36Sopenharmony_ci .max_div = 4096, 118862306a36Sopenharmony_ci .flags = SPI_CONTROLLER_MUST_TX, 118962306a36Sopenharmony_ci .fifo_size = 8, 119062306a36Sopenharmony_ci .num_hw_ss = 2, 119162306a36Sopenharmony_ci}; 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_cistatic const struct spi_ops rspi_rz_ops __maybe_unused = { 119462306a36Sopenharmony_ci .set_config_register = rspi_rz_set_config_register, 119562306a36Sopenharmony_ci .transfer_one = rspi_rz_transfer_one, 119662306a36Sopenharmony_ci .min_div = 2, 119762306a36Sopenharmony_ci .max_div = 4096, 119862306a36Sopenharmony_ci .flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX, 119962306a36Sopenharmony_ci .fifo_size = 8, /* 8 for TX, 32 for RX */ 120062306a36Sopenharmony_ci .num_hw_ss = 1, 120162306a36Sopenharmony_ci}; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_cistatic const struct spi_ops qspi_ops __maybe_unused = { 120462306a36Sopenharmony_ci .set_config_register = qspi_set_config_register, 120562306a36Sopenharmony_ci .transfer_one = qspi_transfer_one, 120662306a36Sopenharmony_ci .extra_mode_bits = SPI_TX_DUAL | SPI_TX_QUAD | 120762306a36Sopenharmony_ci SPI_RX_DUAL | SPI_RX_QUAD, 120862306a36Sopenharmony_ci .min_div = 1, 120962306a36Sopenharmony_ci .max_div = 4080, 121062306a36Sopenharmony_ci .flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX, 121162306a36Sopenharmony_ci .fifo_size = 32, 121262306a36Sopenharmony_ci .num_hw_ss = 1, 121362306a36Sopenharmony_ci}; 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_cistatic const struct of_device_id rspi_of_match[] __maybe_unused = { 121662306a36Sopenharmony_ci /* RSPI on legacy SH */ 121762306a36Sopenharmony_ci { .compatible = "renesas,rspi", .data = &rspi_ops }, 121862306a36Sopenharmony_ci /* RSPI on RZ/A1H */ 121962306a36Sopenharmony_ci { .compatible = "renesas,rspi-rz", .data = &rspi_rz_ops }, 122062306a36Sopenharmony_ci /* QSPI on R-Car Gen2 */ 122162306a36Sopenharmony_ci { .compatible = "renesas,qspi", .data = &qspi_ops }, 122262306a36Sopenharmony_ci { /* sentinel */ } 122362306a36Sopenharmony_ci}; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, rspi_of_match); 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci#ifdef CONFIG_OF 122862306a36Sopenharmony_cistatic void rspi_reset_control_assert(void *data) 122962306a36Sopenharmony_ci{ 123062306a36Sopenharmony_ci reset_control_assert(data); 123162306a36Sopenharmony_ci} 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_cistatic int rspi_parse_dt(struct device *dev, struct spi_controller *ctlr) 123462306a36Sopenharmony_ci{ 123562306a36Sopenharmony_ci struct reset_control *rstc; 123662306a36Sopenharmony_ci u32 num_cs; 123762306a36Sopenharmony_ci int error; 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci /* Parse DT properties */ 124062306a36Sopenharmony_ci error = of_property_read_u32(dev->of_node, "num-cs", &num_cs); 124162306a36Sopenharmony_ci if (error) { 124262306a36Sopenharmony_ci dev_err(dev, "of_property_read_u32 num-cs failed %d\n", error); 124362306a36Sopenharmony_ci return error; 124462306a36Sopenharmony_ci } 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci ctlr->num_chipselect = num_cs; 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci rstc = devm_reset_control_get_optional_exclusive(dev, NULL); 124962306a36Sopenharmony_ci if (IS_ERR(rstc)) 125062306a36Sopenharmony_ci return dev_err_probe(dev, PTR_ERR(rstc), 125162306a36Sopenharmony_ci "failed to get reset ctrl\n"); 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci error = reset_control_deassert(rstc); 125462306a36Sopenharmony_ci if (error) { 125562306a36Sopenharmony_ci dev_err(dev, "failed to deassert reset %d\n", error); 125662306a36Sopenharmony_ci return error; 125762306a36Sopenharmony_ci } 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci error = devm_add_action_or_reset(dev, rspi_reset_control_assert, rstc); 126062306a36Sopenharmony_ci if (error) { 126162306a36Sopenharmony_ci dev_err(dev, "failed to register assert devm action, %d\n", error); 126262306a36Sopenharmony_ci return error; 126362306a36Sopenharmony_ci } 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci return 0; 126662306a36Sopenharmony_ci} 126762306a36Sopenharmony_ci#else 126862306a36Sopenharmony_ci#define rspi_of_match NULL 126962306a36Sopenharmony_cistatic inline int rspi_parse_dt(struct device *dev, struct spi_controller *ctlr) 127062306a36Sopenharmony_ci{ 127162306a36Sopenharmony_ci return -EINVAL; 127262306a36Sopenharmony_ci} 127362306a36Sopenharmony_ci#endif /* CONFIG_OF */ 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_cistatic int rspi_request_irq(struct device *dev, unsigned int irq, 127662306a36Sopenharmony_ci irq_handler_t handler, const char *suffix, 127762306a36Sopenharmony_ci void *dev_id) 127862306a36Sopenharmony_ci{ 127962306a36Sopenharmony_ci const char *name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", 128062306a36Sopenharmony_ci dev_name(dev), suffix); 128162306a36Sopenharmony_ci if (!name) 128262306a36Sopenharmony_ci return -ENOMEM; 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci return devm_request_irq(dev, irq, handler, 0, name, dev_id); 128562306a36Sopenharmony_ci} 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_cistatic int rspi_probe(struct platform_device *pdev) 128862306a36Sopenharmony_ci{ 128962306a36Sopenharmony_ci struct resource *res; 129062306a36Sopenharmony_ci struct spi_controller *ctlr; 129162306a36Sopenharmony_ci struct rspi_data *rspi; 129262306a36Sopenharmony_ci int ret; 129362306a36Sopenharmony_ci const struct rspi_plat_data *rspi_pd; 129462306a36Sopenharmony_ci const struct spi_ops *ops; 129562306a36Sopenharmony_ci unsigned long clksrc; 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci ctlr = spi_alloc_host(&pdev->dev, sizeof(struct rspi_data)); 129862306a36Sopenharmony_ci if (ctlr == NULL) 129962306a36Sopenharmony_ci return -ENOMEM; 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci ops = of_device_get_match_data(&pdev->dev); 130262306a36Sopenharmony_ci if (ops) { 130362306a36Sopenharmony_ci ret = rspi_parse_dt(&pdev->dev, ctlr); 130462306a36Sopenharmony_ci if (ret) 130562306a36Sopenharmony_ci goto error1; 130662306a36Sopenharmony_ci } else { 130762306a36Sopenharmony_ci ops = (struct spi_ops *)pdev->id_entry->driver_data; 130862306a36Sopenharmony_ci rspi_pd = dev_get_platdata(&pdev->dev); 130962306a36Sopenharmony_ci if (rspi_pd && rspi_pd->num_chipselect) 131062306a36Sopenharmony_ci ctlr->num_chipselect = rspi_pd->num_chipselect; 131162306a36Sopenharmony_ci else 131262306a36Sopenharmony_ci ctlr->num_chipselect = 2; /* default */ 131362306a36Sopenharmony_ci } 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci rspi = spi_controller_get_devdata(ctlr); 131662306a36Sopenharmony_ci platform_set_drvdata(pdev, rspi); 131762306a36Sopenharmony_ci rspi->ops = ops; 131862306a36Sopenharmony_ci rspi->ctlr = ctlr; 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci rspi->addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 132162306a36Sopenharmony_ci if (IS_ERR(rspi->addr)) { 132262306a36Sopenharmony_ci ret = PTR_ERR(rspi->addr); 132362306a36Sopenharmony_ci goto error1; 132462306a36Sopenharmony_ci } 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci rspi->clk = devm_clk_get(&pdev->dev, NULL); 132762306a36Sopenharmony_ci if (IS_ERR(rspi->clk)) { 132862306a36Sopenharmony_ci dev_err(&pdev->dev, "cannot get clock\n"); 132962306a36Sopenharmony_ci ret = PTR_ERR(rspi->clk); 133062306a36Sopenharmony_ci goto error1; 133162306a36Sopenharmony_ci } 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci rspi->pdev = pdev; 133462306a36Sopenharmony_ci pm_runtime_enable(&pdev->dev); 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci init_waitqueue_head(&rspi->wait); 133762306a36Sopenharmony_ci spin_lock_init(&rspi->lock); 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_ci ctlr->bus_num = pdev->id; 134062306a36Sopenharmony_ci ctlr->setup = rspi_setup; 134162306a36Sopenharmony_ci ctlr->auto_runtime_pm = true; 134262306a36Sopenharmony_ci ctlr->transfer_one = ops->transfer_one; 134362306a36Sopenharmony_ci ctlr->prepare_message = rspi_prepare_message; 134462306a36Sopenharmony_ci ctlr->unprepare_message = rspi_unprepare_message; 134562306a36Sopenharmony_ci ctlr->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | 134662306a36Sopenharmony_ci SPI_LOOP | ops->extra_mode_bits; 134762306a36Sopenharmony_ci clksrc = clk_get_rate(rspi->clk); 134862306a36Sopenharmony_ci ctlr->min_speed_hz = DIV_ROUND_UP(clksrc, ops->max_div); 134962306a36Sopenharmony_ci ctlr->max_speed_hz = DIV_ROUND_UP(clksrc, ops->min_div); 135062306a36Sopenharmony_ci ctlr->flags = ops->flags; 135162306a36Sopenharmony_ci ctlr->dev.of_node = pdev->dev.of_node; 135262306a36Sopenharmony_ci ctlr->use_gpio_descriptors = true; 135362306a36Sopenharmony_ci ctlr->max_native_cs = rspi->ops->num_hw_ss; 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci ret = platform_get_irq_byname_optional(pdev, "rx"); 135662306a36Sopenharmony_ci if (ret < 0) { 135762306a36Sopenharmony_ci ret = platform_get_irq_byname_optional(pdev, "mux"); 135862306a36Sopenharmony_ci if (ret < 0) 135962306a36Sopenharmony_ci ret = platform_get_irq(pdev, 0); 136062306a36Sopenharmony_ci if (ret >= 0) 136162306a36Sopenharmony_ci rspi->rx_irq = rspi->tx_irq = ret; 136262306a36Sopenharmony_ci } else { 136362306a36Sopenharmony_ci rspi->rx_irq = ret; 136462306a36Sopenharmony_ci ret = platform_get_irq_byname(pdev, "tx"); 136562306a36Sopenharmony_ci if (ret >= 0) 136662306a36Sopenharmony_ci rspi->tx_irq = ret; 136762306a36Sopenharmony_ci } 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci if (rspi->rx_irq == rspi->tx_irq) { 137062306a36Sopenharmony_ci /* Single multiplexed interrupt */ 137162306a36Sopenharmony_ci ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_mux, 137262306a36Sopenharmony_ci "mux", rspi); 137362306a36Sopenharmony_ci } else { 137462306a36Sopenharmony_ci /* Multi-interrupt mode, only SPRI and SPTI are used */ 137562306a36Sopenharmony_ci ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_rx, 137662306a36Sopenharmony_ci "rx", rspi); 137762306a36Sopenharmony_ci if (!ret) 137862306a36Sopenharmony_ci ret = rspi_request_irq(&pdev->dev, rspi->tx_irq, 137962306a36Sopenharmony_ci rspi_irq_tx, "tx", rspi); 138062306a36Sopenharmony_ci } 138162306a36Sopenharmony_ci if (ret < 0) { 138262306a36Sopenharmony_ci dev_err(&pdev->dev, "request_irq error\n"); 138362306a36Sopenharmony_ci goto error2; 138462306a36Sopenharmony_ci } 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci ret = rspi_request_dma(&pdev->dev, ctlr, res); 138762306a36Sopenharmony_ci if (ret < 0) 138862306a36Sopenharmony_ci dev_warn(&pdev->dev, "DMA not available, using PIO\n"); 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci ret = devm_spi_register_controller(&pdev->dev, ctlr); 139162306a36Sopenharmony_ci if (ret < 0) { 139262306a36Sopenharmony_ci dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); 139362306a36Sopenharmony_ci goto error3; 139462306a36Sopenharmony_ci } 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci dev_info(&pdev->dev, "probed\n"); 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci return 0; 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_cierror3: 140162306a36Sopenharmony_ci rspi_release_dma(ctlr); 140262306a36Sopenharmony_cierror2: 140362306a36Sopenharmony_ci pm_runtime_disable(&pdev->dev); 140462306a36Sopenharmony_cierror1: 140562306a36Sopenharmony_ci spi_controller_put(ctlr); 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci return ret; 140862306a36Sopenharmony_ci} 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_cistatic const struct platform_device_id spi_driver_ids[] = { 141162306a36Sopenharmony_ci { "rspi", (kernel_ulong_t)&rspi_ops }, 141262306a36Sopenharmony_ci {}, 141362306a36Sopenharmony_ci}; 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(platform, spi_driver_ids); 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 141862306a36Sopenharmony_cistatic int rspi_suspend(struct device *dev) 141962306a36Sopenharmony_ci{ 142062306a36Sopenharmony_ci struct rspi_data *rspi = dev_get_drvdata(dev); 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci return spi_controller_suspend(rspi->ctlr); 142362306a36Sopenharmony_ci} 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_cistatic int rspi_resume(struct device *dev) 142662306a36Sopenharmony_ci{ 142762306a36Sopenharmony_ci struct rspi_data *rspi = dev_get_drvdata(dev); 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci return spi_controller_resume(rspi->ctlr); 143062306a36Sopenharmony_ci} 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(rspi_pm_ops, rspi_suspend, rspi_resume); 143362306a36Sopenharmony_ci#define DEV_PM_OPS &rspi_pm_ops 143462306a36Sopenharmony_ci#else 143562306a36Sopenharmony_ci#define DEV_PM_OPS NULL 143662306a36Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */ 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_cistatic struct platform_driver rspi_driver = { 143962306a36Sopenharmony_ci .probe = rspi_probe, 144062306a36Sopenharmony_ci .remove_new = rspi_remove, 144162306a36Sopenharmony_ci .id_table = spi_driver_ids, 144262306a36Sopenharmony_ci .driver = { 144362306a36Sopenharmony_ci .name = "renesas_spi", 144462306a36Sopenharmony_ci .pm = DEV_PM_OPS, 144562306a36Sopenharmony_ci .of_match_table = of_match_ptr(rspi_of_match), 144662306a36Sopenharmony_ci }, 144762306a36Sopenharmony_ci}; 144862306a36Sopenharmony_cimodule_platform_driver(rspi_driver); 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ciMODULE_DESCRIPTION("Renesas RSPI bus driver"); 145162306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 145262306a36Sopenharmony_ciMODULE_AUTHOR("Yoshihiro Shimoda"); 1453