xref: /linux/drivers/spi/spi-dw.h (revision bac70b54ecb53b3d5af862dd4fcbaaad8f34ed23)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2ca632f55SGrant Likely #ifndef DW_SPI_HEADER_H
3ca632f55SGrant Likely #define DW_SPI_HEADER_H
4ca632f55SGrant Likely 
5bdbdf0f0SSerge Semin #include <linux/completion.h>
68378449dSSerge Semin #include <linux/debugfs.h>
7e62a15d9SAndy Shevchenko #include <linux/irqreturn.h>
8ca632f55SGrant Likely #include <linux/io.h>
9ca632f55SGrant Likely #include <linux/scatterlist.h>
10ca632f55SGrant Likely 
117eb187b3SH Hartley Sweeten /* Register offsets */
12299cb65cSWan Ahmad Zainie #define DW_SPI_CTRLR0			0x00
13299cb65cSWan Ahmad Zainie #define DW_SPI_CTRLR1			0x04
147eb187b3SH Hartley Sweeten #define DW_SPI_SSIENR			0x08
157eb187b3SH Hartley Sweeten #define DW_SPI_MWCR			0x0c
167eb187b3SH Hartley Sweeten #define DW_SPI_SER			0x10
177eb187b3SH Hartley Sweeten #define DW_SPI_BAUDR			0x14
18299cb65cSWan Ahmad Zainie #define DW_SPI_TXFTLR			0x18
19299cb65cSWan Ahmad Zainie #define DW_SPI_RXFTLR			0x1c
207eb187b3SH Hartley Sweeten #define DW_SPI_TXFLR			0x20
217eb187b3SH Hartley Sweeten #define DW_SPI_RXFLR			0x24
227eb187b3SH Hartley Sweeten #define DW_SPI_SR			0x28
237eb187b3SH Hartley Sweeten #define DW_SPI_IMR			0x2c
247eb187b3SH Hartley Sweeten #define DW_SPI_ISR			0x30
257eb187b3SH Hartley Sweeten #define DW_SPI_RISR			0x34
267eb187b3SH Hartley Sweeten #define DW_SPI_TXOICR			0x38
277eb187b3SH Hartley Sweeten #define DW_SPI_RXOICR			0x3c
287eb187b3SH Hartley Sweeten #define DW_SPI_RXUICR			0x40
297eb187b3SH Hartley Sweeten #define DW_SPI_MSTICR			0x44
307eb187b3SH Hartley Sweeten #define DW_SPI_ICR			0x48
317eb187b3SH Hartley Sweeten #define DW_SPI_DMACR			0x4c
327eb187b3SH Hartley Sweeten #define DW_SPI_DMATDLR			0x50
337eb187b3SH Hartley Sweeten #define DW_SPI_DMARDLR			0x54
347eb187b3SH Hartley Sweeten #define DW_SPI_IDR			0x58
357eb187b3SH Hartley Sweeten #define DW_SPI_VERSION			0x5c
367eb187b3SH Hartley Sweeten #define DW_SPI_DR			0x60
37*bac70b54SLars Povlsen #define DW_SPI_RX_SAMPLE_DLY		0xf0
38f2d70479STalel Shenhar #define DW_SPI_CS_OVERRIDE		0xf4
397eb187b3SH Hartley Sweeten 
40ca632f55SGrant Likely /* Bit fields in CTRLR0 */
41ca632f55SGrant Likely #define SPI_DFS_OFFSET			0
42ca632f55SGrant Likely 
43ca632f55SGrant Likely #define SPI_FRF_OFFSET			4
44ca632f55SGrant Likely #define SPI_FRF_SPI			0x0
45ca632f55SGrant Likely #define SPI_FRF_SSP			0x1
46ca632f55SGrant Likely #define SPI_FRF_MICROWIRE		0x2
47ca632f55SGrant Likely #define SPI_FRF_RESV			0x3
48ca632f55SGrant Likely 
49ca632f55SGrant Likely #define SPI_MODE_OFFSET			6
50ca632f55SGrant Likely #define SPI_SCPH_OFFSET			6
51ca632f55SGrant Likely #define SPI_SCOL_OFFSET			7
52ca632f55SGrant Likely 
53ca632f55SGrant Likely #define SPI_TMOD_OFFSET			8
54ca632f55SGrant Likely #define SPI_TMOD_MASK			(0x3 << SPI_TMOD_OFFSET)
55ca632f55SGrant Likely #define	SPI_TMOD_TR			0x0		/* xmit & recv */
56ca632f55SGrant Likely #define SPI_TMOD_TO			0x1		/* xmit only */
57ca632f55SGrant Likely #define SPI_TMOD_RO			0x2		/* recv only */
58ca632f55SGrant Likely #define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
59ca632f55SGrant Likely 
60ca632f55SGrant Likely #define SPI_SLVOE_OFFSET		10
61ca632f55SGrant Likely #define SPI_SRL_OFFSET			11
62ca632f55SGrant Likely #define SPI_CFS_OFFSET			12
63ca632f55SGrant Likely 
64e539f435SWan Ahmad Zainie /* Bit fields in CTRLR0 based on DWC_ssi_databook.pdf v1.01a */
65e539f435SWan Ahmad Zainie #define DWC_SSI_CTRLR0_SRL_OFFSET	13
66e539f435SWan Ahmad Zainie #define DWC_SSI_CTRLR0_TMOD_OFFSET	10
67e539f435SWan Ahmad Zainie #define DWC_SSI_CTRLR0_TMOD_MASK	GENMASK(11, 10)
68e539f435SWan Ahmad Zainie #define DWC_SSI_CTRLR0_SCPOL_OFFSET	9
69e539f435SWan Ahmad Zainie #define DWC_SSI_CTRLR0_SCPH_OFFSET	8
70e539f435SWan Ahmad Zainie #define DWC_SSI_CTRLR0_FRF_OFFSET	6
71e539f435SWan Ahmad Zainie #define DWC_SSI_CTRLR0_DFS_OFFSET	0
72e539f435SWan Ahmad Zainie 
73ca632f55SGrant Likely /* Bit fields in SR, 7 bits */
74ca632f55SGrant Likely #define SR_MASK				0x7f		/* cover 7 bits */
75ca632f55SGrant Likely #define SR_BUSY				(1 << 0)
76ca632f55SGrant Likely #define SR_TF_NOT_FULL			(1 << 1)
77ca632f55SGrant Likely #define SR_TF_EMPT			(1 << 2)
78ca632f55SGrant Likely #define SR_RF_NOT_EMPT			(1 << 3)
79ca632f55SGrant Likely #define SR_RF_FULL			(1 << 4)
80ca632f55SGrant Likely #define SR_TX_ERR			(1 << 5)
81ca632f55SGrant Likely #define SR_DCOL				(1 << 6)
82ca632f55SGrant Likely 
83ca632f55SGrant Likely /* Bit fields in ISR, IMR, RISR, 7 bits */
84ca632f55SGrant Likely #define SPI_INT_TXEI			(1 << 0)
85ca632f55SGrant Likely #define SPI_INT_TXOI			(1 << 1)
86ca632f55SGrant Likely #define SPI_INT_RXUI			(1 << 2)
87ca632f55SGrant Likely #define SPI_INT_RXOI			(1 << 3)
88ca632f55SGrant Likely #define SPI_INT_RXFI			(1 << 4)
89ca632f55SGrant Likely #define SPI_INT_MSTI			(1 << 5)
90ca632f55SGrant Likely 
9115ee3be7SAndy Shevchenko /* Bit fields in DMACR */
9215ee3be7SAndy Shevchenko #define SPI_DMA_RDMAE			(1 << 0)
9315ee3be7SAndy Shevchenko #define SPI_DMA_TDMAE			(1 << 1)
9415ee3be7SAndy Shevchenko 
95ca632f55SGrant Likely /* TX RX interrupt level threshold, max can be 256 */
96ca632f55SGrant Likely #define SPI_INT_THRESHOLD		32
97ca632f55SGrant Likely 
98ca632f55SGrant Likely enum dw_ssi_type {
99ca632f55SGrant Likely 	SSI_MOTO_SPI = 0,
100ca632f55SGrant Likely 	SSI_TI_SSP,
101ca632f55SGrant Likely 	SSI_NS_MICROWIRE,
102ca632f55SGrant Likely };
103ca632f55SGrant Likely 
104ca632f55SGrant Likely struct dw_spi;
105ca632f55SGrant Likely struct dw_spi_dma_ops {
1066370ababSAndy Shevchenko 	int (*dma_init)(struct device *dev, struct dw_spi *dws);
107ca632f55SGrant Likely 	void (*dma_exit)(struct dw_spi *dws);
108f89a6d8fSAndy Shevchenko 	int (*dma_setup)(struct dw_spi *dws, struct spi_transfer *xfer);
109721483e2SJarkko Nikula 	bool (*can_dma)(struct spi_controller *master, struct spi_device *spi,
110f89a6d8fSAndy Shevchenko 			struct spi_transfer *xfer);
111f89a6d8fSAndy Shevchenko 	int (*dma_transfer)(struct dw_spi *dws, struct spi_transfer *xfer);
1124d5ac1edSAndy Shevchenko 	void (*dma_stop)(struct dw_spi *dws);
113ca632f55SGrant Likely };
114ca632f55SGrant Likely 
115ca632f55SGrant Likely struct dw_spi {
116721483e2SJarkko Nikula 	struct spi_controller	*master;
117ca632f55SGrant Likely 	enum dw_ssi_type	type;
118ca632f55SGrant Likely 
119ca632f55SGrant Likely 	void __iomem		*regs;
120ca632f55SGrant Likely 	unsigned long		paddr;
121ca632f55SGrant Likely 	int			irq;
122ca632f55SGrant Likely 	u32			fifo_len;	/* depth of the FIFO buffer */
123ca632f55SGrant Likely 	u32			max_freq;	/* max bus freq supported */
124ca632f55SGrant Likely 
125f2d70479STalel Shenhar 	int			cs_override;
126c4fe57f7SMichael van der Westhuizen 	u32			reg_io_width;	/* DR I/O width in bytes */
127ca632f55SGrant Likely 	u16			bus_num;
128ca632f55SGrant Likely 	u16			num_cs;		/* supported slave numbers */
12962dbbae4SAlexandre Belloni 	void (*set_cs)(struct spi_device *spi, bool enable);
130c4eadee2SWan Ahmad Zainie 	u32 (*update_cr0)(struct spi_controller *master, struct spi_device *spi,
131c4eadee2SWan Ahmad Zainie 			  struct spi_transfer *transfer);
132ca632f55SGrant Likely 
133ca632f55SGrant Likely 	/* Current message transfer state info */
134ca632f55SGrant Likely 	size_t			len;
135ca632f55SGrant Likely 	void			*tx;
136ca632f55SGrant Likely 	void			*tx_end;
13719b61392Swuxu.wu 	spinlock_t		buf_lock;
138ca632f55SGrant Likely 	void			*rx;
139ca632f55SGrant Likely 	void			*rx_end;
140ca632f55SGrant Likely 	int			dma_mapped;
141ca632f55SGrant Likely 	u8			n_bytes;	/* current is a 1/2 bytes op */
142ca632f55SGrant Likely 	irqreturn_t		(*transfer_handler)(struct dw_spi *dws);
14313b10301SMatthias Seidel 	u32			current_freq;	/* frequency in hz */
144*bac70b54SLars Povlsen 	u32			cur_rx_sample_dly;
145*bac70b54SLars Povlsen 	u32			def_rx_sample_dly_ns;
146ca632f55SGrant Likely 
147f89a6d8fSAndy Shevchenko 	/* DMA info */
148ca632f55SGrant Likely 	struct dma_chan		*txchan;
1490b2b6651SSerge Semin 	u32			txburst;
150ca632f55SGrant Likely 	struct dma_chan		*rxchan;
1510b2b6651SSerge Semin 	u32			rxburst;
15230c8eb52SAndy Shevchenko 	unsigned long		dma_chan_busy;
153ca632f55SGrant Likely 	dma_addr_t		dma_addr; /* phy address of the Data register */
1544fe338c9SJulia Lawall 	const struct dw_spi_dma_ops *dma_ops;
155bdbdf0f0SSerge Semin 	struct completion	dma_completion;
156ca632f55SGrant Likely 
157ca632f55SGrant Likely #ifdef CONFIG_DEBUG_FS
158ca632f55SGrant Likely 	struct dentry *debugfs;
1598378449dSSerge Semin 	struct debugfs_regset32 regset;
160ca632f55SGrant Likely #endif
161ca632f55SGrant Likely };
162ca632f55SGrant Likely 
1637eb187b3SH Hartley Sweeten static inline u32 dw_readl(struct dw_spi *dws, u32 offset)
1647eb187b3SH Hartley Sweeten {
1657eb187b3SH Hartley Sweeten 	return __raw_readl(dws->regs + offset);
1667eb187b3SH Hartley Sweeten }
1677eb187b3SH Hartley Sweeten 
168c4fe57f7SMichael van der Westhuizen static inline u16 dw_readw(struct dw_spi *dws, u32 offset)
169c4fe57f7SMichael van der Westhuizen {
170c4fe57f7SMichael van der Westhuizen 	return __raw_readw(dws->regs + offset);
171c4fe57f7SMichael van der Westhuizen }
172c4fe57f7SMichael van der Westhuizen 
1737eb187b3SH Hartley Sweeten static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val)
1747eb187b3SH Hartley Sweeten {
1757eb187b3SH Hartley Sweeten 	__raw_writel(val, dws->regs + offset);
1767eb187b3SH Hartley Sweeten }
1777eb187b3SH Hartley Sweeten 
178c4fe57f7SMichael van der Westhuizen static inline void dw_writew(struct dw_spi *dws, u32 offset, u16 val)
179c4fe57f7SMichael van der Westhuizen {
180c4fe57f7SMichael van der Westhuizen 	__raw_writew(val, dws->regs + offset);
181c4fe57f7SMichael van der Westhuizen }
182c4fe57f7SMichael van der Westhuizen 
183c4fe57f7SMichael van der Westhuizen static inline u32 dw_read_io_reg(struct dw_spi *dws, u32 offset)
184c4fe57f7SMichael van der Westhuizen {
185c4fe57f7SMichael van der Westhuizen 	switch (dws->reg_io_width) {
186c4fe57f7SMichael van der Westhuizen 	case 2:
187c4fe57f7SMichael van der Westhuizen 		return dw_readw(dws, offset);
188c4fe57f7SMichael van der Westhuizen 	case 4:
189c4fe57f7SMichael van der Westhuizen 	default:
190c4fe57f7SMichael van der Westhuizen 		return dw_readl(dws, offset);
191c4fe57f7SMichael van der Westhuizen 	}
192c4fe57f7SMichael van der Westhuizen }
193c4fe57f7SMichael van der Westhuizen 
194c4fe57f7SMichael van der Westhuizen static inline void dw_write_io_reg(struct dw_spi *dws, u32 offset, u32 val)
195c4fe57f7SMichael van der Westhuizen {
196c4fe57f7SMichael van der Westhuizen 	switch (dws->reg_io_width) {
197c4fe57f7SMichael van der Westhuizen 	case 2:
198c4fe57f7SMichael van der Westhuizen 		dw_writew(dws, offset, val);
199c4fe57f7SMichael van der Westhuizen 		break;
200c4fe57f7SMichael van der Westhuizen 	case 4:
201c4fe57f7SMichael van der Westhuizen 	default:
202c4fe57f7SMichael van der Westhuizen 		dw_writel(dws, offset, val);
203c4fe57f7SMichael van der Westhuizen 		break;
204c4fe57f7SMichael van der Westhuizen 	}
205c4fe57f7SMichael van der Westhuizen }
206c4fe57f7SMichael van der Westhuizen 
207ca632f55SGrant Likely static inline void spi_enable_chip(struct dw_spi *dws, int enable)
208ca632f55SGrant Likely {
2097eb187b3SH Hartley Sweeten 	dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0));
210ca632f55SGrant Likely }
211ca632f55SGrant Likely 
212ca632f55SGrant Likely static inline void spi_set_clk(struct dw_spi *dws, u16 div)
213ca632f55SGrant Likely {
2147eb187b3SH Hartley Sweeten 	dw_writel(dws, DW_SPI_BAUDR, div);
215ca632f55SGrant Likely }
216ca632f55SGrant Likely 
217ca632f55SGrant Likely /* Disable IRQ bits */
218ca632f55SGrant Likely static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
219ca632f55SGrant Likely {
220ca632f55SGrant Likely 	u32 new_mask;
221ca632f55SGrant Likely 
2227eb187b3SH Hartley Sweeten 	new_mask = dw_readl(dws, DW_SPI_IMR) & ~mask;
2237eb187b3SH Hartley Sweeten 	dw_writel(dws, DW_SPI_IMR, new_mask);
224ca632f55SGrant Likely }
225ca632f55SGrant Likely 
226ca632f55SGrant Likely /* Enable IRQ bits */
227ca632f55SGrant Likely static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
228ca632f55SGrant Likely {
229ca632f55SGrant Likely 	u32 new_mask;
230ca632f55SGrant Likely 
2317eb187b3SH Hartley Sweeten 	new_mask = dw_readl(dws, DW_SPI_IMR) | mask;
2327eb187b3SH Hartley Sweeten 	dw_writel(dws, DW_SPI_IMR, new_mask);
233ca632f55SGrant Likely }
234ca632f55SGrant Likely 
235ca632f55SGrant Likely /*
23645746e82SAndy Shevchenko  * This does disable the SPI controller, interrupts, and re-enable the
23745746e82SAndy Shevchenko  * controller back. Transmit and receive FIFO buffers are cleared when the
23845746e82SAndy Shevchenko  * device is disabled.
23945746e82SAndy Shevchenko  */
24045746e82SAndy Shevchenko static inline void spi_reset_chip(struct dw_spi *dws)
24145746e82SAndy Shevchenko {
24245746e82SAndy Shevchenko 	spi_enable_chip(dws, 0);
24345746e82SAndy Shevchenko 	spi_mask_intr(dws, 0xff);
24445746e82SAndy Shevchenko 	spi_enable_chip(dws, 1);
24545746e82SAndy Shevchenko }
24645746e82SAndy Shevchenko 
2471cc3f141SAndy Shevchenko static inline void spi_shutdown_chip(struct dw_spi *dws)
2481cc3f141SAndy Shevchenko {
2491cc3f141SAndy Shevchenko 	spi_enable_chip(dws, 0);
2501cc3f141SAndy Shevchenko 	spi_set_clk(dws, 0);
2511cc3f141SAndy Shevchenko }
2521cc3f141SAndy Shevchenko 
253c79bdbb4SAlexandre Belloni extern void dw_spi_set_cs(struct spi_device *spi, bool enable);
25404f421e7SBaruch Siach extern int dw_spi_add_host(struct device *dev, struct dw_spi *dws);
255ca632f55SGrant Likely extern void dw_spi_remove_host(struct dw_spi *dws);
256ca632f55SGrant Likely extern int dw_spi_suspend_host(struct dw_spi *dws);
257ca632f55SGrant Likely extern int dw_spi_resume_host(struct dw_spi *dws);
258c4eadee2SWan Ahmad Zainie extern u32 dw_spi_update_cr0(struct spi_controller *master,
259c4eadee2SWan Ahmad Zainie 			     struct spi_device *spi,
260c4eadee2SWan Ahmad Zainie 			     struct spi_transfer *transfer);
261e539f435SWan Ahmad Zainie extern u32 dw_spi_update_cr0_v1_01a(struct spi_controller *master,
262e539f435SWan Ahmad Zainie 				    struct spi_device *spi,
263e539f435SWan Ahmad Zainie 				    struct spi_transfer *transfer);
264ca632f55SGrant Likely 
2656c710c0cSSerge Semin #ifdef CONFIG_SPI_DW_DMA
2666c710c0cSSerge Semin 
26757784411SSerge Semin extern void dw_spi_dma_setup_mfld(struct dw_spi *dws);
26857784411SSerge Semin extern void dw_spi_dma_setup_generic(struct dw_spi *dws);
2696c710c0cSSerge Semin 
2706c710c0cSSerge Semin #else
2716c710c0cSSerge Semin 
27257784411SSerge Semin static inline void dw_spi_dma_setup_mfld(struct dw_spi *dws) {}
27357784411SSerge Semin static inline void dw_spi_dma_setup_generic(struct dw_spi *dws) {}
2746c710c0cSSerge Semin 
2756c710c0cSSerge Semin #endif /* !CONFIG_SPI_DW_DMA */
27637aa8aa6SAndy Shevchenko 
277ca632f55SGrant Likely #endif /* DW_SPI_HEADER_H */
278