xref: /openbmc/linux/drivers/spi/spi-zynqmp-gqspi.c (revision ecc23d0a422a3118fcf6e4f0a46e17a6c2047b02)
159899843SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2dfe11a11SRanjit Waghmode /*
3dfe11a11SRanjit Waghmode  * Xilinx Zynq UltraScale+ MPSoC Quad-SPI (QSPI) controller driver
4dfe11a11SRanjit Waghmode  * (master mode only)
5dfe11a11SRanjit Waghmode  *
6dfe11a11SRanjit Waghmode  * Copyright (C) 2009 - 2015 Xilinx, Inc.
7dfe11a11SRanjit Waghmode  */
8dfe11a11SRanjit Waghmode 
9dfe11a11SRanjit Waghmode #include <linux/clk.h>
10dfe11a11SRanjit Waghmode #include <linux/delay.h>
11dfe11a11SRanjit Waghmode #include <linux/dma-mapping.h>
12dfe11a11SRanjit Waghmode #include <linux/dmaengine.h>
13ab7b7c71SOlof Johansson #include <linux/firmware/xlnx-zynqmp.h>
14dfe11a11SRanjit Waghmode #include <linux/interrupt.h>
15dfe11a11SRanjit Waghmode #include <linux/io.h>
16dfe11a11SRanjit Waghmode #include <linux/module.h>
17749396cbSRob Herring #include <linux/of.h>
18dfe11a11SRanjit Waghmode #include <linux/platform_device.h>
199e3a0003SNaga Sureshkumar Relli #include <linux/pm_runtime.h>
20dfe11a11SRanjit Waghmode #include <linux/spi/spi.h>
21dfe11a11SRanjit Waghmode #include <linux/spinlock.h>
22dfe11a11SRanjit Waghmode #include <linux/workqueue.h>
231c26372eSAmit Kumar Mahapatra #include <linux/spi/spi-mem.h>
24dfe11a11SRanjit Waghmode 
25dfe11a11SRanjit Waghmode /* Generic QSPI register offsets */
26dfe11a11SRanjit Waghmode #define GQSPI_CONFIG_OFST		0x00000100
27dfe11a11SRanjit Waghmode #define GQSPI_ISR_OFST			0x00000104
28dfe11a11SRanjit Waghmode #define GQSPI_IDR_OFST			0x0000010C
29dfe11a11SRanjit Waghmode #define GQSPI_IER_OFST			0x00000108
30dfe11a11SRanjit Waghmode #define GQSPI_IMASK_OFST		0x00000110
31dfe11a11SRanjit Waghmode #define GQSPI_EN_OFST			0x00000114
32dfe11a11SRanjit Waghmode #define GQSPI_TXD_OFST			0x0000011C
33dfe11a11SRanjit Waghmode #define GQSPI_RXD_OFST			0x00000120
34dfe11a11SRanjit Waghmode #define GQSPI_TX_THRESHOLD_OFST		0x00000128
35dfe11a11SRanjit Waghmode #define GQSPI_RX_THRESHOLD_OFST		0x0000012C
3629f4d95bSAmit Kumar Mahapatra #define IOU_TAPDLY_BYPASS_OFST		0x0000003C
37dfe11a11SRanjit Waghmode #define GQSPI_LPBK_DLY_ADJ_OFST		0x00000138
38dfe11a11SRanjit Waghmode #define GQSPI_GEN_FIFO_OFST		0x00000140
39dfe11a11SRanjit Waghmode #define GQSPI_SEL_OFST			0x00000144
40dfe11a11SRanjit Waghmode #define GQSPI_GF_THRESHOLD_OFST		0x00000150
41dfe11a11SRanjit Waghmode #define GQSPI_FIFO_CTRL_OFST		0x0000014C
42dfe11a11SRanjit Waghmode #define GQSPI_QSPIDMA_DST_CTRL_OFST	0x0000080C
43dfe11a11SRanjit Waghmode #define GQSPI_QSPIDMA_DST_SIZE_OFST	0x00000804
44dfe11a11SRanjit Waghmode #define GQSPI_QSPIDMA_DST_STS_OFST	0x00000808
45dfe11a11SRanjit Waghmode #define GQSPI_QSPIDMA_DST_I_STS_OFST	0x00000814
46dfe11a11SRanjit Waghmode #define GQSPI_QSPIDMA_DST_I_EN_OFST	0x00000818
47dfe11a11SRanjit Waghmode #define GQSPI_QSPIDMA_DST_I_DIS_OFST	0x0000081C
48dfe11a11SRanjit Waghmode #define GQSPI_QSPIDMA_DST_I_MASK_OFST	0x00000820
49dfe11a11SRanjit Waghmode #define GQSPI_QSPIDMA_DST_ADDR_OFST	0x00000800
50dfe11a11SRanjit Waghmode #define GQSPI_QSPIDMA_DST_ADDR_MSB_OFST 0x00000828
51fae7b3c3SNaga Sureshkumar Relli #define GQSPI_DATA_DLY_ADJ_OFST         0x000001F8
52dfe11a11SRanjit Waghmode 
53dfe11a11SRanjit Waghmode /* GQSPI register bit masks */
54dfe11a11SRanjit Waghmode #define GQSPI_SEL_MASK				0x00000001
55dfe11a11SRanjit Waghmode #define GQSPI_EN_MASK				0x00000001
56dfe11a11SRanjit Waghmode #define GQSPI_LPBK_DLY_ADJ_USE_LPBK_MASK	0x00000020
57dfe11a11SRanjit Waghmode #define GQSPI_ISR_WR_TO_CLR_MASK		0x00000002
58dfe11a11SRanjit Waghmode #define GQSPI_IDR_ALL_MASK			0x00000FBE
59dfe11a11SRanjit Waghmode #define GQSPI_CFG_MODE_EN_MASK			0xC0000000
60dfe11a11SRanjit Waghmode #define GQSPI_CFG_GEN_FIFO_START_MODE_MASK	0x20000000
61dfe11a11SRanjit Waghmode #define GQSPI_CFG_ENDIAN_MASK			0x04000000
62dfe11a11SRanjit Waghmode #define GQSPI_CFG_EN_POLL_TO_MASK		0x00100000
63dfe11a11SRanjit Waghmode #define GQSPI_CFG_WP_HOLD_MASK			0x00080000
64dfe11a11SRanjit Waghmode #define GQSPI_CFG_BAUD_RATE_DIV_MASK		0x00000038
65dfe11a11SRanjit Waghmode #define GQSPI_CFG_CLK_PHA_MASK			0x00000004
66dfe11a11SRanjit Waghmode #define GQSPI_CFG_CLK_POL_MASK			0x00000002
67dfe11a11SRanjit Waghmode #define GQSPI_CFG_START_GEN_FIFO_MASK		0x10000000
68dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_IMM_DATA_MASK		0x000000FF
69dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_DATA_XFER			0x00000100
70dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_EXP			0x00000200
71dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_MODE_SPI			0x00000400
72dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_MODE_DUALSPI		0x00000800
73dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_MODE_QUADSPI		0x00000C00
74dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_MODE_MASK			0x00000C00
75dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_CS_LOWER			0x00001000
76dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_CS_UPPER			0x00002000
77dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_BUS_LOWER			0x00004000
78dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_BUS_UPPER			0x00008000
79dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_BUS_BOTH			0x0000C000
80dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_BUS_MASK			0x0000C000
81dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_TX			0x00010000
82dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_RX			0x00020000
83dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_STRIPE			0x00040000
84dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_POLL			0x00080000
85dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_EXP_START			0x00000100
86dfe11a11SRanjit Waghmode #define GQSPI_FIFO_CTRL_RST_RX_FIFO_MASK	0x00000004
87dfe11a11SRanjit Waghmode #define GQSPI_FIFO_CTRL_RST_TX_FIFO_MASK	0x00000002
88dfe11a11SRanjit Waghmode #define GQSPI_FIFO_CTRL_RST_GEN_FIFO_MASK	0x00000001
89dfe11a11SRanjit Waghmode #define GQSPI_ISR_RXEMPTY_MASK			0x00000800
90dfe11a11SRanjit Waghmode #define GQSPI_ISR_GENFIFOFULL_MASK		0x00000400
91dfe11a11SRanjit Waghmode #define GQSPI_ISR_GENFIFONOT_FULL_MASK		0x00000200
92dfe11a11SRanjit Waghmode #define GQSPI_ISR_TXEMPTY_MASK			0x00000100
93dfe11a11SRanjit Waghmode #define GQSPI_ISR_GENFIFOEMPTY_MASK		0x00000080
94dfe11a11SRanjit Waghmode #define GQSPI_ISR_RXFULL_MASK			0x00000020
95dfe11a11SRanjit Waghmode #define GQSPI_ISR_RXNEMPTY_MASK			0x00000010
96dfe11a11SRanjit Waghmode #define GQSPI_ISR_TXFULL_MASK			0x00000008
97dfe11a11SRanjit Waghmode #define GQSPI_ISR_TXNOT_FULL_MASK		0x00000004
98dfe11a11SRanjit Waghmode #define GQSPI_ISR_POLL_TIME_EXPIRE_MASK		0x00000002
99dfe11a11SRanjit Waghmode #define GQSPI_IER_TXNOT_FULL_MASK		0x00000004
100dfe11a11SRanjit Waghmode #define GQSPI_IER_RXEMPTY_MASK			0x00000800
101dfe11a11SRanjit Waghmode #define GQSPI_IER_POLL_TIME_EXPIRE_MASK		0x00000002
102dfe11a11SRanjit Waghmode #define GQSPI_IER_RXNEMPTY_MASK			0x00000010
103dfe11a11SRanjit Waghmode #define GQSPI_IER_GENFIFOEMPTY_MASK		0x00000080
104dfe11a11SRanjit Waghmode #define GQSPI_IER_TXEMPTY_MASK			0x00000100
105dfe11a11SRanjit Waghmode #define GQSPI_QSPIDMA_DST_INTR_ALL_MASK		0x000000FE
106dfe11a11SRanjit Waghmode #define GQSPI_QSPIDMA_DST_STS_WTC		0x0000E000
107dfe11a11SRanjit Waghmode #define GQSPI_CFG_MODE_EN_DMA_MASK		0x80000000
108dfe11a11SRanjit Waghmode #define GQSPI_ISR_IDR_MASK			0x00000994
109dfe11a11SRanjit Waghmode #define GQSPI_QSPIDMA_DST_I_EN_DONE_MASK	0x00000002
110dfe11a11SRanjit Waghmode #define GQSPI_QSPIDMA_DST_I_STS_DONE_MASK	0x00000002
111dfe11a11SRanjit Waghmode #define GQSPI_IRQ_MASK				0x00000980
112dfe11a11SRanjit Waghmode 
113dfe11a11SRanjit Waghmode #define GQSPI_CFG_BAUD_RATE_DIV_SHIFT		3
114dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_CS_SETUP			0x4
115dfe11a11SRanjit Waghmode #define GQSPI_GENFIFO_CS_HOLD			0x3
116dfe11a11SRanjit Waghmode #define GQSPI_TXD_DEPTH				64
117dfe11a11SRanjit Waghmode #define GQSPI_RX_FIFO_THRESHOLD			32
118dfe11a11SRanjit Waghmode #define GQSPI_RX_FIFO_FILL	(GQSPI_RX_FIFO_THRESHOLD * 4)
119dfe11a11SRanjit Waghmode #define GQSPI_TX_FIFO_THRESHOLD_RESET_VAL	32
120dfe11a11SRanjit Waghmode #define GQSPI_TX_FIFO_FILL	(GQSPI_TXD_DEPTH -\
121dfe11a11SRanjit Waghmode 				GQSPI_TX_FIFO_THRESHOLD_RESET_VAL)
122dfe11a11SRanjit Waghmode #define GQSPI_GEN_FIFO_THRESHOLD_RESET_VAL	0X10
123dfe11a11SRanjit Waghmode #define GQSPI_QSPIDMA_DST_CTRL_RESET_VAL	0x803FFA00
124dfe11a11SRanjit Waghmode #define GQSPI_SELECT_FLASH_CS_LOWER		0x1
125dfe11a11SRanjit Waghmode #define GQSPI_SELECT_FLASH_CS_UPPER		0x2
126dfe11a11SRanjit Waghmode #define GQSPI_SELECT_FLASH_CS_BOTH		0x3
127dfe11a11SRanjit Waghmode #define GQSPI_SELECT_FLASH_BUS_LOWER		0x1
128dfe11a11SRanjit Waghmode #define GQSPI_SELECT_FLASH_BUS_UPPER		0x2
129dfe11a11SRanjit Waghmode #define GQSPI_SELECT_FLASH_BUS_BOTH		0x3
130dfe11a11SRanjit Waghmode #define GQSPI_BAUD_DIV_MAX	7	/* Baud rate divisor maximum */
131dfe11a11SRanjit Waghmode #define GQSPI_BAUD_DIV_SHIFT	2	/* Baud rate divisor shift */
132dfe11a11SRanjit Waghmode #define GQSPI_SELECT_MODE_SPI		0x1
133dfe11a11SRanjit Waghmode #define GQSPI_SELECT_MODE_DUALSPI	0x2
134dfe11a11SRanjit Waghmode #define GQSPI_SELECT_MODE_QUADSPI	0x4
135dfe11a11SRanjit Waghmode #define GQSPI_DMA_UNALIGN		0x3
136dfe11a11SRanjit Waghmode #define GQSPI_DEFAULT_NUM_CS	1	/* Default number of chip selects */
137dfe11a11SRanjit Waghmode 
138dd9c232dSAmit Kumar Mahapatra #define GQSPI_MAX_NUM_CS	2	/* Maximum number of chip selects */
139dd9c232dSAmit Kumar Mahapatra 
140fae7b3c3SNaga Sureshkumar Relli #define GQSPI_USE_DATA_DLY		0x1
141fae7b3c3SNaga Sureshkumar Relli #define GQSPI_USE_DATA_DLY_SHIFT	31
142fae7b3c3SNaga Sureshkumar Relli #define GQSPI_DATA_DLY_ADJ_VALUE	0x2
143fae7b3c3SNaga Sureshkumar Relli #define GQSPI_DATA_DLY_ADJ_SHIFT	28
14429f4d95bSAmit Kumar Mahapatra #define GQSPI_LPBK_DLY_ADJ_DLY_1	0x1
14529f4d95bSAmit Kumar Mahapatra #define GQSPI_LPBK_DLY_ADJ_DLY_1_SHIFT	0x3
14629f4d95bSAmit Kumar Mahapatra #define TAP_DLY_BYPASS_LQSPI_RX_VALUE	0x1
14729f4d95bSAmit Kumar Mahapatra #define TAP_DLY_BYPASS_LQSPI_RX_SHIFT	0x2
14829f4d95bSAmit Kumar Mahapatra 
14929f4d95bSAmit Kumar Mahapatra /* set to differentiate versal from zynqmp, 1=versal, 0=zynqmp */
15029f4d95bSAmit Kumar Mahapatra #define QSPI_QUIRK_HAS_TAPDELAY		BIT(0)
151fae7b3c3SNaga Sureshkumar Relli 
152fae7b3c3SNaga Sureshkumar Relli #define GQSPI_FREQ_37_5MHZ	37500000
153fae7b3c3SNaga Sureshkumar Relli #define GQSPI_FREQ_40MHZ	40000000
154fae7b3c3SNaga Sureshkumar Relli #define GQSPI_FREQ_100MHZ	100000000
155fae7b3c3SNaga Sureshkumar Relli #define GQSPI_FREQ_150MHZ	150000000
156fae7b3c3SNaga Sureshkumar Relli 
1579e3a0003SNaga Sureshkumar Relli #define SPI_AUTOSUSPEND_TIMEOUT		3000
158dfe11a11SRanjit Waghmode enum mode_type {GQSPI_MODE_IO, GQSPI_MODE_DMA};
159dfe11a11SRanjit Waghmode 
160dfe11a11SRanjit Waghmode /**
16129f4d95bSAmit Kumar Mahapatra  * struct qspi_platform_data - zynqmp qspi platform data structure
16229f4d95bSAmit Kumar Mahapatra  * @quirks:    Flags is used to identify the platform
16329f4d95bSAmit Kumar Mahapatra  */
16429f4d95bSAmit Kumar Mahapatra struct qspi_platform_data {
16529f4d95bSAmit Kumar Mahapatra 	u32 quirks;
16629f4d95bSAmit Kumar Mahapatra };
16729f4d95bSAmit Kumar Mahapatra 
16829f4d95bSAmit Kumar Mahapatra /**
169dfe11a11SRanjit Waghmode  * struct zynqmp_qspi - Defines qspi driver instance
170b3b95308SAmit Kumar Mahapatra  * @ctlr:		Pointer to the spi controller information
171dfe11a11SRanjit Waghmode  * @regs:		Virtual address of the QSPI controller registers
172dfe11a11SRanjit Waghmode  * @refclk:		Pointer to the peripheral clock
173dfe11a11SRanjit Waghmode  * @pclk:		Pointer to the APB clock
174dfe11a11SRanjit Waghmode  * @irq:		IRQ number
175dfe11a11SRanjit Waghmode  * @dev:		Pointer to struct device
176dfe11a11SRanjit Waghmode  * @txbuf:		Pointer to the TX buffer
177dfe11a11SRanjit Waghmode  * @rxbuf:		Pointer to the RX buffer
178dfe11a11SRanjit Waghmode  * @bytes_to_transfer:	Number of bytes left to transfer
179dfe11a11SRanjit Waghmode  * @bytes_to_receive:	Number of bytes left to receive
180dfe11a11SRanjit Waghmode  * @genfifocs:		Used for chip select
181dfe11a11SRanjit Waghmode  * @genfifobus:		Used to select the upper or lower bus
182dfe11a11SRanjit Waghmode  * @dma_rx_bytes:	Remaining bytes to receive by DMA mode
183dfe11a11SRanjit Waghmode  * @dma_addr:		DMA address after mapping the kernel buffer
184dfe11a11SRanjit Waghmode  * @genfifoentry:	Used for storing the genfifoentry instruction.
185dfe11a11SRanjit Waghmode  * @mode:		Defines the mode in which QSPI is operating
1861c26372eSAmit Kumar Mahapatra  * @data_completion:	completion structure
187b3b95308SAmit Kumar Mahapatra  * @op_lock:		Operational lock
18821764a49SAmit Kumar Mahapatra  * @speed_hz:          Current SPI bus clock speed in hz
18929f4d95bSAmit Kumar Mahapatra  * @has_tapdelay:	Used for tapdelay register available in qspi
190dfe11a11SRanjit Waghmode  */
191dfe11a11SRanjit Waghmode struct zynqmp_qspi {
192799f923fSQuanyang Wang 	struct spi_controller *ctlr;
193dfe11a11SRanjit Waghmode 	void __iomem *regs;
194dfe11a11SRanjit Waghmode 	struct clk *refclk;
195dfe11a11SRanjit Waghmode 	struct clk *pclk;
196dfe11a11SRanjit Waghmode 	int irq;
197dfe11a11SRanjit Waghmode 	struct device *dev;
198dfe11a11SRanjit Waghmode 	const void *txbuf;
199dfe11a11SRanjit Waghmode 	void *rxbuf;
200dfe11a11SRanjit Waghmode 	int bytes_to_transfer;
201dfe11a11SRanjit Waghmode 	int bytes_to_receive;
202dfe11a11SRanjit Waghmode 	u32 genfifocs;
203dfe11a11SRanjit Waghmode 	u32 genfifobus;
204dfe11a11SRanjit Waghmode 	u32 dma_rx_bytes;
205dfe11a11SRanjit Waghmode 	dma_addr_t dma_addr;
206dfe11a11SRanjit Waghmode 	u32 genfifoentry;
207dfe11a11SRanjit Waghmode 	enum mode_type mode;
2081c26372eSAmit Kumar Mahapatra 	struct completion data_completion;
209a0f65be6SQuanyang Wang 	struct mutex op_lock;
21021764a49SAmit Kumar Mahapatra 	u32 speed_hz;
21129f4d95bSAmit Kumar Mahapatra 	bool has_tapdelay;
212dfe11a11SRanjit Waghmode };
213dfe11a11SRanjit Waghmode 
214dfe11a11SRanjit Waghmode /**
21591af6eb0SAmit Kumar Mahapatra  * zynqmp_gqspi_read - For GQSPI controller read operation
216dfe11a11SRanjit Waghmode  * @xqspi:	Pointer to the zynqmp_qspi structure
217dfe11a11SRanjit Waghmode  * @offset:	Offset from where to read
21891af6eb0SAmit Kumar Mahapatra  * Return:      Value at the offset
219dfe11a11SRanjit Waghmode  */
zynqmp_gqspi_read(struct zynqmp_qspi * xqspi,u32 offset)220dfe11a11SRanjit Waghmode static u32 zynqmp_gqspi_read(struct zynqmp_qspi *xqspi, u32 offset)
221dfe11a11SRanjit Waghmode {
222dfe11a11SRanjit Waghmode 	return readl_relaxed(xqspi->regs + offset);
223dfe11a11SRanjit Waghmode }
224dfe11a11SRanjit Waghmode 
225dfe11a11SRanjit Waghmode /**
22691af6eb0SAmit Kumar Mahapatra  * zynqmp_gqspi_write - For GQSPI controller write operation
227dfe11a11SRanjit Waghmode  * @xqspi:	Pointer to the zynqmp_qspi structure
228dfe11a11SRanjit Waghmode  * @offset:	Offset where to write
229dfe11a11SRanjit Waghmode  * @val:	Value to be written
230dfe11a11SRanjit Waghmode  */
zynqmp_gqspi_write(struct zynqmp_qspi * xqspi,u32 offset,u32 val)231dfe11a11SRanjit Waghmode static inline void zynqmp_gqspi_write(struct zynqmp_qspi *xqspi, u32 offset,
232dfe11a11SRanjit Waghmode 				      u32 val)
233dfe11a11SRanjit Waghmode {
234dfe11a11SRanjit Waghmode 	writel_relaxed(val, (xqspi->regs + offset));
235dfe11a11SRanjit Waghmode }
236dfe11a11SRanjit Waghmode 
237dfe11a11SRanjit Waghmode /**
23891af6eb0SAmit Kumar Mahapatra  * zynqmp_gqspi_selectslave - For selection of slave device
239dfe11a11SRanjit Waghmode  * @instanceptr:	Pointer to the zynqmp_qspi structure
2404b42b0b4SLee Jones  * @slavecs:	For chip select
2414b42b0b4SLee Jones  * @slavebus:	To check which bus is selected- upper or lower
242dfe11a11SRanjit Waghmode  */
zynqmp_gqspi_selectslave(struct zynqmp_qspi * instanceptr,u8 slavecs,u8 slavebus)243dfe11a11SRanjit Waghmode static void zynqmp_gqspi_selectslave(struct zynqmp_qspi *instanceptr,
244dfe11a11SRanjit Waghmode 				     u8 slavecs, u8 slavebus)
245dfe11a11SRanjit Waghmode {
246dfe11a11SRanjit Waghmode 	/*
247dfe11a11SRanjit Waghmode 	 * Bus and CS lines selected here will be updated in the instance and
248dfe11a11SRanjit Waghmode 	 * used for subsequent GENFIFO entries during transfer.
249dfe11a11SRanjit Waghmode 	 */
250dfe11a11SRanjit Waghmode 
251dfe11a11SRanjit Waghmode 	/* Choose slave select line */
252dfe11a11SRanjit Waghmode 	switch (slavecs) {
253dfe11a11SRanjit Waghmode 	case GQSPI_SELECT_FLASH_CS_BOTH:
254dfe11a11SRanjit Waghmode 		instanceptr->genfifocs = GQSPI_GENFIFO_CS_LOWER |
255dfe11a11SRanjit Waghmode 			GQSPI_GENFIFO_CS_UPPER;
256861a481cSDan Carpenter 		break;
257dfe11a11SRanjit Waghmode 	case GQSPI_SELECT_FLASH_CS_UPPER:
258dfe11a11SRanjit Waghmode 		instanceptr->genfifocs = GQSPI_GENFIFO_CS_UPPER;
259dfe11a11SRanjit Waghmode 		break;
260dfe11a11SRanjit Waghmode 	case GQSPI_SELECT_FLASH_CS_LOWER:
261dfe11a11SRanjit Waghmode 		instanceptr->genfifocs = GQSPI_GENFIFO_CS_LOWER;
262dfe11a11SRanjit Waghmode 		break;
263dfe11a11SRanjit Waghmode 	default:
264dfe11a11SRanjit Waghmode 		dev_warn(instanceptr->dev, "Invalid slave select\n");
265dfe11a11SRanjit Waghmode 	}
266dfe11a11SRanjit Waghmode 
267dfe11a11SRanjit Waghmode 	/* Choose the bus */
268dfe11a11SRanjit Waghmode 	switch (slavebus) {
269dfe11a11SRanjit Waghmode 	case GQSPI_SELECT_FLASH_BUS_BOTH:
270dfe11a11SRanjit Waghmode 		instanceptr->genfifobus = GQSPI_GENFIFO_BUS_LOWER |
271dfe11a11SRanjit Waghmode 			GQSPI_GENFIFO_BUS_UPPER;
272dfe11a11SRanjit Waghmode 		break;
273dfe11a11SRanjit Waghmode 	case GQSPI_SELECT_FLASH_BUS_UPPER:
274dfe11a11SRanjit Waghmode 		instanceptr->genfifobus = GQSPI_GENFIFO_BUS_UPPER;
275dfe11a11SRanjit Waghmode 		break;
276dfe11a11SRanjit Waghmode 	case GQSPI_SELECT_FLASH_BUS_LOWER:
277dfe11a11SRanjit Waghmode 		instanceptr->genfifobus = GQSPI_GENFIFO_BUS_LOWER;
278dfe11a11SRanjit Waghmode 		break;
279dfe11a11SRanjit Waghmode 	default:
280dfe11a11SRanjit Waghmode 		dev_warn(instanceptr->dev, "Invalid slave bus\n");
281dfe11a11SRanjit Waghmode 	}
282dfe11a11SRanjit Waghmode }
283dfe11a11SRanjit Waghmode 
284dfe11a11SRanjit Waghmode /**
285fae7b3c3SNaga Sureshkumar Relli  * zynqmp_qspi_set_tapdelay:   To configure qspi tap delays
286fae7b3c3SNaga Sureshkumar Relli  * @xqspi:             Pointer to the zynqmp_qspi structure
287fae7b3c3SNaga Sureshkumar Relli  * @baudrateval:       Buadrate to configure
288fae7b3c3SNaga Sureshkumar Relli  */
zynqmp_qspi_set_tapdelay(struct zynqmp_qspi * xqspi,u32 baudrateval)289fae7b3c3SNaga Sureshkumar Relli static void zynqmp_qspi_set_tapdelay(struct zynqmp_qspi *xqspi, u32 baudrateval)
290fae7b3c3SNaga Sureshkumar Relli {
29129f4d95bSAmit Kumar Mahapatra 	u32 tapdlybypass = 0, lpbkdlyadj = 0, datadlyadj = 0, clk_rate;
292fae7b3c3SNaga Sureshkumar Relli 	u32 reqhz = 0;
293fae7b3c3SNaga Sureshkumar Relli 
294fae7b3c3SNaga Sureshkumar Relli 	clk_rate = clk_get_rate(xqspi->refclk);
295fae7b3c3SNaga Sureshkumar Relli 	reqhz = (clk_rate / (GQSPI_BAUD_DIV_SHIFT << baudrateval));
296fae7b3c3SNaga Sureshkumar Relli 
29729f4d95bSAmit Kumar Mahapatra 	if (!xqspi->has_tapdelay) {
298fae7b3c3SNaga Sureshkumar Relli 		if (reqhz <= GQSPI_FREQ_40MHZ) {
299fae7b3c3SNaga Sureshkumar Relli 			zynqmp_pm_set_tapdelay_bypass(PM_TAPDELAY_QSPI,
300fae7b3c3SNaga Sureshkumar Relli 						      PM_TAPDELAY_BYPASS_ENABLE);
301fae7b3c3SNaga Sureshkumar Relli 		} else if (reqhz <= GQSPI_FREQ_100MHZ) {
302fae7b3c3SNaga Sureshkumar Relli 			zynqmp_pm_set_tapdelay_bypass(PM_TAPDELAY_QSPI,
303fae7b3c3SNaga Sureshkumar Relli 						      PM_TAPDELAY_BYPASS_ENABLE);
304fae7b3c3SNaga Sureshkumar Relli 			lpbkdlyadj |= (GQSPI_LPBK_DLY_ADJ_USE_LPBK_MASK);
305fae7b3c3SNaga Sureshkumar Relli 			datadlyadj |= ((GQSPI_USE_DATA_DLY <<
30629f4d95bSAmit Kumar Mahapatra 					GQSPI_USE_DATA_DLY_SHIFT)
30729f4d95bSAmit Kumar Mahapatra 					| (GQSPI_DATA_DLY_ADJ_VALUE <<
308fae7b3c3SNaga Sureshkumar Relli 						GQSPI_DATA_DLY_ADJ_SHIFT));
309fae7b3c3SNaga Sureshkumar Relli 		} else if (reqhz <= GQSPI_FREQ_150MHZ) {
310fae7b3c3SNaga Sureshkumar Relli 			lpbkdlyadj |= GQSPI_LPBK_DLY_ADJ_USE_LPBK_MASK;
311fae7b3c3SNaga Sureshkumar Relli 		}
31229f4d95bSAmit Kumar Mahapatra 	} else {
31329f4d95bSAmit Kumar Mahapatra 		if (reqhz <= GQSPI_FREQ_37_5MHZ) {
31429f4d95bSAmit Kumar Mahapatra 			tapdlybypass |= (TAP_DLY_BYPASS_LQSPI_RX_VALUE <<
31529f4d95bSAmit Kumar Mahapatra 					TAP_DLY_BYPASS_LQSPI_RX_SHIFT);
31629f4d95bSAmit Kumar Mahapatra 		} else if (reqhz <= GQSPI_FREQ_100MHZ) {
31729f4d95bSAmit Kumar Mahapatra 			tapdlybypass |= (TAP_DLY_BYPASS_LQSPI_RX_VALUE <<
31829f4d95bSAmit Kumar Mahapatra 					TAP_DLY_BYPASS_LQSPI_RX_SHIFT);
31929f4d95bSAmit Kumar Mahapatra 			lpbkdlyadj |= (GQSPI_LPBK_DLY_ADJ_USE_LPBK_MASK);
32029f4d95bSAmit Kumar Mahapatra 			datadlyadj |= (GQSPI_USE_DATA_DLY <<
32129f4d95bSAmit Kumar Mahapatra 					GQSPI_USE_DATA_DLY_SHIFT);
32229f4d95bSAmit Kumar Mahapatra 		} else if (reqhz <= GQSPI_FREQ_150MHZ) {
32329f4d95bSAmit Kumar Mahapatra 			lpbkdlyadj |= (GQSPI_LPBK_DLY_ADJ_USE_LPBK_MASK
32429f4d95bSAmit Kumar Mahapatra 				       | (GQSPI_LPBK_DLY_ADJ_DLY_1 <<
32529f4d95bSAmit Kumar Mahapatra 					       GQSPI_LPBK_DLY_ADJ_DLY_1_SHIFT));
32629f4d95bSAmit Kumar Mahapatra 		}
32729f4d95bSAmit Kumar Mahapatra 		zynqmp_gqspi_write(xqspi,
32829f4d95bSAmit Kumar Mahapatra 				   IOU_TAPDLY_BYPASS_OFST, tapdlybypass);
32929f4d95bSAmit Kumar Mahapatra 	}
330fae7b3c3SNaga Sureshkumar Relli 	zynqmp_gqspi_write(xqspi, GQSPI_LPBK_DLY_ADJ_OFST, lpbkdlyadj);
331fae7b3c3SNaga Sureshkumar Relli 	zynqmp_gqspi_write(xqspi, GQSPI_DATA_DLY_ADJ_OFST, datadlyadj);
332fae7b3c3SNaga Sureshkumar Relli }
333fae7b3c3SNaga Sureshkumar Relli 
334fae7b3c3SNaga Sureshkumar Relli /**
33591af6eb0SAmit Kumar Mahapatra  * zynqmp_qspi_init_hw - Initialize the hardware
336dfe11a11SRanjit Waghmode  * @xqspi:	Pointer to the zynqmp_qspi structure
337dfe11a11SRanjit Waghmode  *
338dfe11a11SRanjit Waghmode  * The default settings of the QSPI controller's configurable parameters on
339dfe11a11SRanjit Waghmode  * reset are
340dfe11a11SRanjit Waghmode  *	- Master mode
341dfe11a11SRanjit Waghmode  *	- TX threshold set to 1
342dfe11a11SRanjit Waghmode  *	- RX threshold set to 1
343dfe11a11SRanjit Waghmode  *	- Flash memory interface mode enabled
344dfe11a11SRanjit Waghmode  * This function performs the following actions
345dfe11a11SRanjit Waghmode  *	- Disable and clear all the interrupts
346dfe11a11SRanjit Waghmode  *	- Enable manual slave select
347dfe11a11SRanjit Waghmode  *	- Enable manual start
348dfe11a11SRanjit Waghmode  *	- Deselect all the chip select lines
34922742b8bSAmit Kumar Mahapatra  *	- Set the little endian mode of TX FIFO
35022742b8bSAmit Kumar Mahapatra  *	- Set clock phase
35122742b8bSAmit Kumar Mahapatra  *	- Set clock polarity and
352dfe11a11SRanjit Waghmode  *	- Enable the QSPI controller
353dfe11a11SRanjit Waghmode  */
zynqmp_qspi_init_hw(struct zynqmp_qspi * xqspi)354dfe11a11SRanjit Waghmode static void zynqmp_qspi_init_hw(struct zynqmp_qspi *xqspi)
355dfe11a11SRanjit Waghmode {
35621764a49SAmit Kumar Mahapatra 	u32 config_reg, baud_rate_val = 0;
35721764a49SAmit Kumar Mahapatra 	ulong clk_rate;
358dfe11a11SRanjit Waghmode 
359dfe11a11SRanjit Waghmode 	/* Select the GQSPI mode */
360dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_SEL_OFST, GQSPI_SEL_MASK);
361dfe11a11SRanjit Waghmode 	/* Clear and disable interrupts */
362dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_ISR_OFST,
363dfe11a11SRanjit Waghmode 			   zynqmp_gqspi_read(xqspi, GQSPI_ISR_OFST) |
364dfe11a11SRanjit Waghmode 			   GQSPI_ISR_WR_TO_CLR_MASK);
365dfe11a11SRanjit Waghmode 	/* Clear the DMA STS */
366dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_I_STS_OFST,
367dfe11a11SRanjit Waghmode 			   zynqmp_gqspi_read(xqspi,
368dfe11a11SRanjit Waghmode 					     GQSPI_QSPIDMA_DST_I_STS_OFST));
369dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_STS_OFST,
370dfe11a11SRanjit Waghmode 			   zynqmp_gqspi_read(xqspi,
371dfe11a11SRanjit Waghmode 					     GQSPI_QSPIDMA_DST_STS_OFST) |
372dfe11a11SRanjit Waghmode 					     GQSPI_QSPIDMA_DST_STS_WTC);
373dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_IDR_OFST, GQSPI_IDR_ALL_MASK);
374dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi,
375dfe11a11SRanjit Waghmode 			   GQSPI_QSPIDMA_DST_I_DIS_OFST,
376dfe11a11SRanjit Waghmode 			   GQSPI_QSPIDMA_DST_INTR_ALL_MASK);
377dfe11a11SRanjit Waghmode 	/* Disable the GQSPI */
378dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, 0x0);
379dfe11a11SRanjit Waghmode 	config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST);
380dfe11a11SRanjit Waghmode 	config_reg &= ~GQSPI_CFG_MODE_EN_MASK;
381dfe11a11SRanjit Waghmode 	/* Manual start */
382dfe11a11SRanjit Waghmode 	config_reg |= GQSPI_CFG_GEN_FIFO_START_MODE_MASK;
383dfe11a11SRanjit Waghmode 	/* Little endian by default */
384dfe11a11SRanjit Waghmode 	config_reg &= ~GQSPI_CFG_ENDIAN_MASK;
385dfe11a11SRanjit Waghmode 	/* Disable poll time out */
386dfe11a11SRanjit Waghmode 	config_reg &= ~GQSPI_CFG_EN_POLL_TO_MASK;
387dfe11a11SRanjit Waghmode 	/* Set hold bit */
388dfe11a11SRanjit Waghmode 	config_reg |= GQSPI_CFG_WP_HOLD_MASK;
389dfe11a11SRanjit Waghmode 	/* Clear pre-scalar by default */
390dfe11a11SRanjit Waghmode 	config_reg &= ~GQSPI_CFG_BAUD_RATE_DIV_MASK;
39122742b8bSAmit Kumar Mahapatra 	/* Set CPHA */
39222742b8bSAmit Kumar Mahapatra 	if (xqspi->ctlr->mode_bits & SPI_CPHA)
39322742b8bSAmit Kumar Mahapatra 		config_reg |= GQSPI_CFG_CLK_PHA_MASK;
39422742b8bSAmit Kumar Mahapatra 	else
395dfe11a11SRanjit Waghmode 		config_reg &= ~GQSPI_CFG_CLK_PHA_MASK;
39622742b8bSAmit Kumar Mahapatra 	/* Set CPOL */
39722742b8bSAmit Kumar Mahapatra 	if (xqspi->ctlr->mode_bits & SPI_CPOL)
39822742b8bSAmit Kumar Mahapatra 		config_reg |= GQSPI_CFG_CLK_POL_MASK;
39922742b8bSAmit Kumar Mahapatra 	else
400dfe11a11SRanjit Waghmode 		config_reg &= ~GQSPI_CFG_CLK_POL_MASK;
40122742b8bSAmit Kumar Mahapatra 
40221764a49SAmit Kumar Mahapatra 	/* Set the clock frequency */
40321764a49SAmit Kumar Mahapatra 	clk_rate = clk_get_rate(xqspi->refclk);
40421764a49SAmit Kumar Mahapatra 	while ((baud_rate_val < GQSPI_BAUD_DIV_MAX) &&
40521764a49SAmit Kumar Mahapatra 	       (clk_rate /
40621764a49SAmit Kumar Mahapatra 		(GQSPI_BAUD_DIV_SHIFT << baud_rate_val)) > xqspi->speed_hz)
40721764a49SAmit Kumar Mahapatra 		baud_rate_val++;
40821764a49SAmit Kumar Mahapatra 
40921764a49SAmit Kumar Mahapatra 	config_reg &= ~GQSPI_CFG_BAUD_RATE_DIV_MASK;
41021764a49SAmit Kumar Mahapatra 	config_reg |= (baud_rate_val << GQSPI_CFG_BAUD_RATE_DIV_SHIFT);
41121764a49SAmit Kumar Mahapatra 
412dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg);
413dfe11a11SRanjit Waghmode 
414fae7b3c3SNaga Sureshkumar Relli 	/* Set the tapdelay for clock frequency */
415fae7b3c3SNaga Sureshkumar Relli 	zynqmp_qspi_set_tapdelay(xqspi, baud_rate_val);
416fae7b3c3SNaga Sureshkumar Relli 
417dfe11a11SRanjit Waghmode 	/* Clear the TX and RX FIFO */
418dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_FIFO_CTRL_OFST,
419dfe11a11SRanjit Waghmode 			   GQSPI_FIFO_CTRL_RST_RX_FIFO_MASK |
420dfe11a11SRanjit Waghmode 			   GQSPI_FIFO_CTRL_RST_TX_FIFO_MASK |
421dfe11a11SRanjit Waghmode 			   GQSPI_FIFO_CTRL_RST_GEN_FIFO_MASK);
422dfe11a11SRanjit Waghmode 	/* Reset thresholds */
423dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_TX_THRESHOLD_OFST,
424dfe11a11SRanjit Waghmode 			   GQSPI_TX_FIFO_THRESHOLD_RESET_VAL);
425dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_RX_THRESHOLD_OFST,
426dfe11a11SRanjit Waghmode 			   GQSPI_RX_FIFO_THRESHOLD);
427dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_GF_THRESHOLD_OFST,
428dfe11a11SRanjit Waghmode 			   GQSPI_GEN_FIFO_THRESHOLD_RESET_VAL);
429dfe11a11SRanjit Waghmode 	zynqmp_gqspi_selectslave(xqspi,
430dfe11a11SRanjit Waghmode 				 GQSPI_SELECT_FLASH_CS_LOWER,
431dfe11a11SRanjit Waghmode 				 GQSPI_SELECT_FLASH_BUS_LOWER);
432dfe11a11SRanjit Waghmode 	/* Initialize DMA */
433dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi,
434dfe11a11SRanjit Waghmode 			   GQSPI_QSPIDMA_DST_CTRL_OFST,
435dfe11a11SRanjit Waghmode 			   GQSPI_QSPIDMA_DST_CTRL_RESET_VAL);
436dfe11a11SRanjit Waghmode 
437dfe11a11SRanjit Waghmode 	/* Enable the GQSPI */
438dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, GQSPI_EN_MASK);
439dfe11a11SRanjit Waghmode }
440dfe11a11SRanjit Waghmode 
441dfe11a11SRanjit Waghmode /**
44291af6eb0SAmit Kumar Mahapatra  * zynqmp_qspi_copy_read_data - Copy data to RX buffer
443dfe11a11SRanjit Waghmode  * @xqspi:	Pointer to the zynqmp_qspi structure
444dfe11a11SRanjit Waghmode  * @data:	The variable where data is stored
445dfe11a11SRanjit Waghmode  * @size:	Number of bytes to be copied from data to RX buffer
446dfe11a11SRanjit Waghmode  */
zynqmp_qspi_copy_read_data(struct zynqmp_qspi * xqspi,ulong data,u8 size)447dfe11a11SRanjit Waghmode static void zynqmp_qspi_copy_read_data(struct zynqmp_qspi *xqspi,
448dfe11a11SRanjit Waghmode 				       ulong data, u8 size)
449dfe11a11SRanjit Waghmode {
450dfe11a11SRanjit Waghmode 	memcpy(xqspi->rxbuf, &data, size);
451dfe11a11SRanjit Waghmode 	xqspi->rxbuf += size;
452dfe11a11SRanjit Waghmode 	xqspi->bytes_to_receive -= size;
453dfe11a11SRanjit Waghmode }
454dfe11a11SRanjit Waghmode 
455dfe11a11SRanjit Waghmode /**
45691af6eb0SAmit Kumar Mahapatra  * zynqmp_qspi_chipselect - Select or deselect the chip select line
457dfe11a11SRanjit Waghmode  * @qspi:	Pointer to the spi_device structure
458dfe11a11SRanjit Waghmode  * @is_high:	Select(0) or deselect (1) the chip select line
459dfe11a11SRanjit Waghmode  */
zynqmp_qspi_chipselect(struct spi_device * qspi,bool is_high)460dfe11a11SRanjit Waghmode static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high)
461dfe11a11SRanjit Waghmode {
462dfe11a11SRanjit Waghmode 	struct zynqmp_qspi *xqspi = spi_master_get_devdata(qspi->master);
463dfe11a11SRanjit Waghmode 	ulong timeout;
4641c26372eSAmit Kumar Mahapatra 	u32 genfifoentry = 0, statusreg;
465dfe11a11SRanjit Waghmode 
466dfe11a11SRanjit Waghmode 	genfifoentry |= GQSPI_GENFIFO_MODE_SPI;
467dfe11a11SRanjit Waghmode 
468dfe11a11SRanjit Waghmode 	if (!is_high) {
4699e264f3fSAmit Kumar Mahapatra via Alsa-devel 		if (!spi_get_chipselect(qspi, 0)) {
4701c26372eSAmit Kumar Mahapatra 			xqspi->genfifobus = GQSPI_GENFIFO_BUS_LOWER;
4711c26372eSAmit Kumar Mahapatra 			xqspi->genfifocs = GQSPI_GENFIFO_CS_LOWER;
472dd9c232dSAmit Kumar Mahapatra 		} else {
473dd9c232dSAmit Kumar Mahapatra 			xqspi->genfifobus = GQSPI_GENFIFO_BUS_UPPER;
474dd9c232dSAmit Kumar Mahapatra 			xqspi->genfifocs = GQSPI_GENFIFO_CS_UPPER;
475dd9c232dSAmit Kumar Mahapatra 		}
4761c26372eSAmit Kumar Mahapatra 		genfifoentry |= xqspi->genfifobus;
477dfe11a11SRanjit Waghmode 		genfifoentry |= xqspi->genfifocs;
478dfe11a11SRanjit Waghmode 		genfifoentry |= GQSPI_GENFIFO_CS_SETUP;
479dfe11a11SRanjit Waghmode 	} else {
480dfe11a11SRanjit Waghmode 		genfifoentry |= GQSPI_GENFIFO_CS_HOLD;
481dfe11a11SRanjit Waghmode 	}
482dfe11a11SRanjit Waghmode 
483dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, genfifoentry);
484dfe11a11SRanjit Waghmode 
485dfe11a11SRanjit Waghmode 	/* Manually start the generic FIFO command */
486dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
487dfe11a11SRanjit Waghmode 			   zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) |
488dfe11a11SRanjit Waghmode 			   GQSPI_CFG_START_GEN_FIFO_MASK);
489dfe11a11SRanjit Waghmode 
490dfe11a11SRanjit Waghmode 	timeout = jiffies + msecs_to_jiffies(1000);
491dfe11a11SRanjit Waghmode 
492dfe11a11SRanjit Waghmode 	/* Wait until the generic FIFO command is empty */
493dfe11a11SRanjit Waghmode 	do {
494dfe11a11SRanjit Waghmode 		statusreg = zynqmp_gqspi_read(xqspi, GQSPI_ISR_OFST);
495dfe11a11SRanjit Waghmode 
496dfe11a11SRanjit Waghmode 		if ((statusreg & GQSPI_ISR_GENFIFOEMPTY_MASK) &&
497dfe11a11SRanjit Waghmode 		    (statusreg & GQSPI_ISR_TXEMPTY_MASK))
498dfe11a11SRanjit Waghmode 			break;
499dfe11a11SRanjit Waghmode 		cpu_relax();
500dfe11a11SRanjit Waghmode 	} while (!time_after_eq(jiffies, timeout));
501dfe11a11SRanjit Waghmode 
502dfe11a11SRanjit Waghmode 	if (time_after_eq(jiffies, timeout))
503dfe11a11SRanjit Waghmode 		dev_err(xqspi->dev, "Chip select timed out\n");
504dfe11a11SRanjit Waghmode }
505dfe11a11SRanjit Waghmode 
506dfe11a11SRanjit Waghmode /**
5071c26372eSAmit Kumar Mahapatra  * zynqmp_qspi_selectspimode - Selects SPI mode - x1 or x2 or x4.
5081c26372eSAmit Kumar Mahapatra  * @xqspi:	xqspi is a pointer to the GQSPI instance
5091c26372eSAmit Kumar Mahapatra  * @spimode:	spimode - SPI or DUAL or QUAD.
5101c26372eSAmit Kumar Mahapatra  * Return:	Mask to set desired SPI mode in GENFIFO entry.
5111c26372eSAmit Kumar Mahapatra  */
zynqmp_qspi_selectspimode(struct zynqmp_qspi * xqspi,u8 spimode)5121c26372eSAmit Kumar Mahapatra static inline u32 zynqmp_qspi_selectspimode(struct zynqmp_qspi *xqspi,
5131c26372eSAmit Kumar Mahapatra 					    u8 spimode)
5141c26372eSAmit Kumar Mahapatra {
5151c26372eSAmit Kumar Mahapatra 	u32 mask = 0;
5161c26372eSAmit Kumar Mahapatra 
5171c26372eSAmit Kumar Mahapatra 	switch (spimode) {
5181c26372eSAmit Kumar Mahapatra 	case GQSPI_SELECT_MODE_DUALSPI:
5191c26372eSAmit Kumar Mahapatra 		mask = GQSPI_GENFIFO_MODE_DUALSPI;
5201c26372eSAmit Kumar Mahapatra 		break;
5211c26372eSAmit Kumar Mahapatra 	case GQSPI_SELECT_MODE_QUADSPI:
5221c26372eSAmit Kumar Mahapatra 		mask = GQSPI_GENFIFO_MODE_QUADSPI;
5231c26372eSAmit Kumar Mahapatra 		break;
5241c26372eSAmit Kumar Mahapatra 	case GQSPI_SELECT_MODE_SPI:
5251c26372eSAmit Kumar Mahapatra 		mask = GQSPI_GENFIFO_MODE_SPI;
5261c26372eSAmit Kumar Mahapatra 		break;
5271c26372eSAmit Kumar Mahapatra 	default:
5281c26372eSAmit Kumar Mahapatra 		dev_warn(xqspi->dev, "Invalid SPI mode\n");
5291c26372eSAmit Kumar Mahapatra 	}
5301c26372eSAmit Kumar Mahapatra 
5311c26372eSAmit Kumar Mahapatra 	return mask;
5321c26372eSAmit Kumar Mahapatra }
5331c26372eSAmit Kumar Mahapatra 
5341c26372eSAmit Kumar Mahapatra /**
5351c26372eSAmit Kumar Mahapatra  * zynqmp_qspi_config_op - Configure QSPI controller for specified
536dfe11a11SRanjit Waghmode  *				transfer
5371c26372eSAmit Kumar Mahapatra  * @xqspi:	Pointer to the zynqmp_qspi structure
538dfe11a11SRanjit Waghmode  * @qspi:	Pointer to the spi_device structure
539dfe11a11SRanjit Waghmode  *
540dfe11a11SRanjit Waghmode  * Sets the operational mode of QSPI controller for the next QSPI transfer and
541dfe11a11SRanjit Waghmode  * sets the requested clock frequency.
542dfe11a11SRanjit Waghmode  *
543dfe11a11SRanjit Waghmode  * Return:	Always 0
544dfe11a11SRanjit Waghmode  *
545dfe11a11SRanjit Waghmode  * Note:
546dfe11a11SRanjit Waghmode  *	If the requested frequency is not an exact match with what can be
547dfe11a11SRanjit Waghmode  *	obtained using the pre-scalar value, the driver sets the clock
548dfe11a11SRanjit Waghmode  *	frequency which is lower than the requested frequency (maximum lower)
549dfe11a11SRanjit Waghmode  *	for the transfer.
550dfe11a11SRanjit Waghmode  *
551dfe11a11SRanjit Waghmode  *	If the requested frequency is higher or lower than that is supported
552dfe11a11SRanjit Waghmode  *	by the QSPI controller the driver will set the highest or lowest
553dfe11a11SRanjit Waghmode  *	frequency supported by controller.
554dfe11a11SRanjit Waghmode  */
zynqmp_qspi_config_op(struct zynqmp_qspi * xqspi,struct spi_device * qspi)5551c26372eSAmit Kumar Mahapatra static int zynqmp_qspi_config_op(struct zynqmp_qspi *xqspi,
5561c26372eSAmit Kumar Mahapatra 				 struct spi_device *qspi)
557dfe11a11SRanjit Waghmode {
558dfe11a11SRanjit Waghmode 	ulong clk_rate;
55921764a49SAmit Kumar Mahapatra 	u32 config_reg, req_speed_hz, baud_rate_val = 0;
56021764a49SAmit Kumar Mahapatra 
56121764a49SAmit Kumar Mahapatra 	req_speed_hz = qspi->max_speed_hz;
56221764a49SAmit Kumar Mahapatra 
56321764a49SAmit Kumar Mahapatra 	if (xqspi->speed_hz != req_speed_hz) {
56421764a49SAmit Kumar Mahapatra 		xqspi->speed_hz = req_speed_hz;
565dfe11a11SRanjit Waghmode 
566dfe11a11SRanjit Waghmode 		/* Set the clock frequency */
56721764a49SAmit Kumar Mahapatra 		/* If req_speed_hz == 0, default to lowest speed */
568dfe11a11SRanjit Waghmode 		clk_rate = clk_get_rate(xqspi->refclk);
569dfe11a11SRanjit Waghmode 
570dfe11a11SRanjit Waghmode 		while ((baud_rate_val < GQSPI_BAUD_DIV_MAX) &&
571dfe11a11SRanjit Waghmode 		       (clk_rate /
57221764a49SAmit Kumar Mahapatra 			(GQSPI_BAUD_DIV_SHIFT << baud_rate_val)) >
57321764a49SAmit Kumar Mahapatra 		       req_speed_hz)
574dfe11a11SRanjit Waghmode 			baud_rate_val++;
575dfe11a11SRanjit Waghmode 
576dfe11a11SRanjit Waghmode 		config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST);
577dfe11a11SRanjit Waghmode 
578dfe11a11SRanjit Waghmode 		config_reg &= ~GQSPI_CFG_BAUD_RATE_DIV_MASK;
579dfe11a11SRanjit Waghmode 		config_reg |= (baud_rate_val << GQSPI_CFG_BAUD_RATE_DIV_SHIFT);
580dfe11a11SRanjit Waghmode 		zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg);
581fae7b3c3SNaga Sureshkumar Relli 		zynqmp_qspi_set_tapdelay(xqspi, baud_rate_val);
58221764a49SAmit Kumar Mahapatra 	}
583dfe11a11SRanjit Waghmode 	return 0;
584dfe11a11SRanjit Waghmode }
585dfe11a11SRanjit Waghmode 
586dfe11a11SRanjit Waghmode /**
5871c26372eSAmit Kumar Mahapatra  * zynqmp_qspi_setup_op - Configure the QSPI controller
588dfe11a11SRanjit Waghmode  * @qspi:	Pointer to the spi_device structure
589dfe11a11SRanjit Waghmode  *
590dfe11a11SRanjit Waghmode  * Sets the operational mode of QSPI controller for the next QSPI transfer,
591dfe11a11SRanjit Waghmode  * baud rate and divisor value to setup the requested qspi clock.
592dfe11a11SRanjit Waghmode  *
593dfe11a11SRanjit Waghmode  * Return:	0 on success; error value otherwise.
594dfe11a11SRanjit Waghmode  */
zynqmp_qspi_setup_op(struct spi_device * qspi)5951c26372eSAmit Kumar Mahapatra static int zynqmp_qspi_setup_op(struct spi_device *qspi)
596dfe11a11SRanjit Waghmode {
5971c26372eSAmit Kumar Mahapatra 	struct spi_controller *ctlr = qspi->master;
5981c26372eSAmit Kumar Mahapatra 	struct zynqmp_qspi *xqspi = spi_controller_get_devdata(ctlr);
5991c26372eSAmit Kumar Mahapatra 
6001c26372eSAmit Kumar Mahapatra 	if (ctlr->busy)
601dfe11a11SRanjit Waghmode 		return -EBUSY;
6021c26372eSAmit Kumar Mahapatra 
6031c26372eSAmit Kumar Mahapatra 	zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, GQSPI_EN_MASK);
6041c26372eSAmit Kumar Mahapatra 
605dfe11a11SRanjit Waghmode 	return 0;
606dfe11a11SRanjit Waghmode }
607dfe11a11SRanjit Waghmode 
608dfe11a11SRanjit Waghmode /**
60991af6eb0SAmit Kumar Mahapatra  * zynqmp_qspi_filltxfifo - Fills the TX FIFO as long as there is room in
610dfe11a11SRanjit Waghmode  *				the FIFO or the bytes required to be
611dfe11a11SRanjit Waghmode  *				transmitted.
612dfe11a11SRanjit Waghmode  * @xqspi:	Pointer to the zynqmp_qspi structure
613dfe11a11SRanjit Waghmode  * @size:	Number of bytes to be copied from TX buffer to TX FIFO
614dfe11a11SRanjit Waghmode  */
zynqmp_qspi_filltxfifo(struct zynqmp_qspi * xqspi,int size)615dfe11a11SRanjit Waghmode static void zynqmp_qspi_filltxfifo(struct zynqmp_qspi *xqspi, int size)
616dfe11a11SRanjit Waghmode {
617dfe11a11SRanjit Waghmode 	u32 count = 0, intermediate;
618dfe11a11SRanjit Waghmode 
6198ad07d79SQuanyang Wang 	while ((xqspi->bytes_to_transfer > 0) && (count < size) && (xqspi->txbuf)) {
620dfe11a11SRanjit Waghmode 		if (xqspi->bytes_to_transfer >= 4) {
6212530b3dfSAmit Kumar Mahapatra 			memcpy(&intermediate, xqspi->txbuf, 4);
622dfe11a11SRanjit Waghmode 			xqspi->txbuf += 4;
623dfe11a11SRanjit Waghmode 			xqspi->bytes_to_transfer -= 4;
6242530b3dfSAmit Kumar Mahapatra 			count += 4;
625dfe11a11SRanjit Waghmode 		} else {
6262530b3dfSAmit Kumar Mahapatra 			memcpy(&intermediate, xqspi->txbuf,
6272530b3dfSAmit Kumar Mahapatra 			       xqspi->bytes_to_transfer);
628dfe11a11SRanjit Waghmode 			xqspi->txbuf += xqspi->bytes_to_transfer;
629dfe11a11SRanjit Waghmode 			xqspi->bytes_to_transfer = 0;
6302530b3dfSAmit Kumar Mahapatra 			count += xqspi->bytes_to_transfer;
631dfe11a11SRanjit Waghmode 		}
6322530b3dfSAmit Kumar Mahapatra 		zynqmp_gqspi_write(xqspi, GQSPI_TXD_OFST, intermediate);
633dfe11a11SRanjit Waghmode 	}
634dfe11a11SRanjit Waghmode }
635dfe11a11SRanjit Waghmode 
636dfe11a11SRanjit Waghmode /**
63791af6eb0SAmit Kumar Mahapatra  * zynqmp_qspi_readrxfifo - Fills the RX FIFO as long as there is room in
638dfe11a11SRanjit Waghmode  *				the FIFO.
639dfe11a11SRanjit Waghmode  * @xqspi:	Pointer to the zynqmp_qspi structure
640dfe11a11SRanjit Waghmode  * @size:	Number of bytes to be copied from RX buffer to RX FIFO
641dfe11a11SRanjit Waghmode  */
zynqmp_qspi_readrxfifo(struct zynqmp_qspi * xqspi,u32 size)642dfe11a11SRanjit Waghmode static void zynqmp_qspi_readrxfifo(struct zynqmp_qspi *xqspi, u32 size)
643dfe11a11SRanjit Waghmode {
644dfe11a11SRanjit Waghmode 	ulong data;
645dfe11a11SRanjit Waghmode 	int count = 0;
646dfe11a11SRanjit Waghmode 
647dfe11a11SRanjit Waghmode 	while ((count < size) && (xqspi->bytes_to_receive > 0)) {
648dfe11a11SRanjit Waghmode 		if (xqspi->bytes_to_receive >= 4) {
649dfe11a11SRanjit Waghmode 			(*(u32 *)xqspi->rxbuf) =
650dfe11a11SRanjit Waghmode 			zynqmp_gqspi_read(xqspi, GQSPI_RXD_OFST);
651dfe11a11SRanjit Waghmode 			xqspi->rxbuf += 4;
652dfe11a11SRanjit Waghmode 			xqspi->bytes_to_receive -= 4;
653dfe11a11SRanjit Waghmode 			count += 4;
654dfe11a11SRanjit Waghmode 		} else {
655dfe11a11SRanjit Waghmode 			data = zynqmp_gqspi_read(xqspi, GQSPI_RXD_OFST);
656dfe11a11SRanjit Waghmode 			count += xqspi->bytes_to_receive;
657dfe11a11SRanjit Waghmode 			zynqmp_qspi_copy_read_data(xqspi, data,
658dfe11a11SRanjit Waghmode 						   xqspi->bytes_to_receive);
659dfe11a11SRanjit Waghmode 			xqspi->bytes_to_receive = 0;
660dfe11a11SRanjit Waghmode 		}
661dfe11a11SRanjit Waghmode 	}
662dfe11a11SRanjit Waghmode }
663dfe11a11SRanjit Waghmode 
664dfe11a11SRanjit Waghmode /**
6651c26372eSAmit Kumar Mahapatra  * zynqmp_qspi_fillgenfifo - Fills the GENFIFO.
6661c26372eSAmit Kumar Mahapatra  * @xqspi:	Pointer to the zynqmp_qspi structure
6671c26372eSAmit Kumar Mahapatra  * @nbits:	Transfer/Receive buswidth.
6681c26372eSAmit Kumar Mahapatra  * @genfifoentry:       Variable in which GENFIFO mask is saved
6691c26372eSAmit Kumar Mahapatra  */
zynqmp_qspi_fillgenfifo(struct zynqmp_qspi * xqspi,u8 nbits,u32 genfifoentry)6701c26372eSAmit Kumar Mahapatra static void zynqmp_qspi_fillgenfifo(struct zynqmp_qspi *xqspi, u8 nbits,
6711c26372eSAmit Kumar Mahapatra 				    u32 genfifoentry)
6721c26372eSAmit Kumar Mahapatra {
6731c26372eSAmit Kumar Mahapatra 	u32 transfer_len = 0;
6741c26372eSAmit Kumar Mahapatra 
6751c26372eSAmit Kumar Mahapatra 	if (xqspi->txbuf) {
6761c26372eSAmit Kumar Mahapatra 		genfifoentry &= ~GQSPI_GENFIFO_RX;
6771c26372eSAmit Kumar Mahapatra 		genfifoentry |= GQSPI_GENFIFO_DATA_XFER;
6781c26372eSAmit Kumar Mahapatra 		genfifoentry |= GQSPI_GENFIFO_TX;
6791c26372eSAmit Kumar Mahapatra 		transfer_len = xqspi->bytes_to_transfer;
6808ad07d79SQuanyang Wang 	} else if (xqspi->rxbuf) {
6811c26372eSAmit Kumar Mahapatra 		genfifoentry &= ~GQSPI_GENFIFO_TX;
6821c26372eSAmit Kumar Mahapatra 		genfifoentry |= GQSPI_GENFIFO_DATA_XFER;
6831c26372eSAmit Kumar Mahapatra 		genfifoentry |= GQSPI_GENFIFO_RX;
6841c26372eSAmit Kumar Mahapatra 		if (xqspi->mode == GQSPI_MODE_DMA)
6851c26372eSAmit Kumar Mahapatra 			transfer_len = xqspi->dma_rx_bytes;
6861c26372eSAmit Kumar Mahapatra 		else
6871c26372eSAmit Kumar Mahapatra 			transfer_len = xqspi->bytes_to_receive;
6888ad07d79SQuanyang Wang 	} else {
6898ad07d79SQuanyang Wang 		/* Sending dummy circles here */
6908ad07d79SQuanyang Wang 		genfifoentry &= ~(GQSPI_GENFIFO_TX | GQSPI_GENFIFO_RX);
6918ad07d79SQuanyang Wang 		genfifoentry |= GQSPI_GENFIFO_DATA_XFER;
6928ad07d79SQuanyang Wang 		transfer_len = xqspi->bytes_to_transfer;
6931c26372eSAmit Kumar Mahapatra 	}
6941c26372eSAmit Kumar Mahapatra 	genfifoentry |= zynqmp_qspi_selectspimode(xqspi, nbits);
6951c26372eSAmit Kumar Mahapatra 	xqspi->genfifoentry = genfifoentry;
6961c26372eSAmit Kumar Mahapatra 
6971c26372eSAmit Kumar Mahapatra 	if ((transfer_len) < GQSPI_GENFIFO_IMM_DATA_MASK) {
6981c26372eSAmit Kumar Mahapatra 		genfifoentry &= ~GQSPI_GENFIFO_IMM_DATA_MASK;
6991c26372eSAmit Kumar Mahapatra 		genfifoentry |= transfer_len;
7001c26372eSAmit Kumar Mahapatra 		zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, genfifoentry);
7011c26372eSAmit Kumar Mahapatra 	} else {
7021c26372eSAmit Kumar Mahapatra 		int tempcount = transfer_len;
7031c26372eSAmit Kumar Mahapatra 		u32 exponent = 8;	/* 2^8 = 256 */
7041c26372eSAmit Kumar Mahapatra 		u8 imm_data = tempcount & 0xFF;
7051c26372eSAmit Kumar Mahapatra 
7061c26372eSAmit Kumar Mahapatra 		tempcount &= ~(tempcount & 0xFF);
7071c26372eSAmit Kumar Mahapatra 		/* Immediate entry */
7081c26372eSAmit Kumar Mahapatra 		if (tempcount != 0) {
7091c26372eSAmit Kumar Mahapatra 			/* Exponent entries */
7101c26372eSAmit Kumar Mahapatra 			genfifoentry |= GQSPI_GENFIFO_EXP;
7111c26372eSAmit Kumar Mahapatra 			while (tempcount != 0) {
7121c26372eSAmit Kumar Mahapatra 				if (tempcount & GQSPI_GENFIFO_EXP_START) {
7131c26372eSAmit Kumar Mahapatra 					genfifoentry &=
7141c26372eSAmit Kumar Mahapatra 						~GQSPI_GENFIFO_IMM_DATA_MASK;
7151c26372eSAmit Kumar Mahapatra 					genfifoentry |= exponent;
7161c26372eSAmit Kumar Mahapatra 					zynqmp_gqspi_write(xqspi,
7171c26372eSAmit Kumar Mahapatra 							   GQSPI_GEN_FIFO_OFST,
7181c26372eSAmit Kumar Mahapatra 							   genfifoentry);
7191c26372eSAmit Kumar Mahapatra 				}
7201c26372eSAmit Kumar Mahapatra 				tempcount = tempcount >> 1;
7211c26372eSAmit Kumar Mahapatra 				exponent++;
7221c26372eSAmit Kumar Mahapatra 			}
7231c26372eSAmit Kumar Mahapatra 		}
7241c26372eSAmit Kumar Mahapatra 		if (imm_data != 0) {
7251c26372eSAmit Kumar Mahapatra 			genfifoentry &= ~GQSPI_GENFIFO_EXP;
7261c26372eSAmit Kumar Mahapatra 			genfifoentry &= ~GQSPI_GENFIFO_IMM_DATA_MASK;
7271c26372eSAmit Kumar Mahapatra 			genfifoentry |= (u8)(imm_data & 0xFF);
7281c26372eSAmit Kumar Mahapatra 			zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST,
7291c26372eSAmit Kumar Mahapatra 					   genfifoentry);
7301c26372eSAmit Kumar Mahapatra 		}
7311c26372eSAmit Kumar Mahapatra 	}
7321c26372eSAmit Kumar Mahapatra 	if (xqspi->mode == GQSPI_MODE_IO && xqspi->rxbuf) {
7331c26372eSAmit Kumar Mahapatra 		/* Dummy generic FIFO entry */
7341c26372eSAmit Kumar Mahapatra 		zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, 0x0);
7351c26372eSAmit Kumar Mahapatra 	}
7361c26372eSAmit Kumar Mahapatra }
7371c26372eSAmit Kumar Mahapatra 
7381c26372eSAmit Kumar Mahapatra /**
73991af6eb0SAmit Kumar Mahapatra  * zynqmp_process_dma_irq - Handler for DMA done interrupt of QSPI
740dfe11a11SRanjit Waghmode  *				controller
741dfe11a11SRanjit Waghmode  * @xqspi:	zynqmp_qspi instance pointer
742dfe11a11SRanjit Waghmode  *
743dfe11a11SRanjit Waghmode  * This function handles DMA interrupt only.
744dfe11a11SRanjit Waghmode  */
zynqmp_process_dma_irq(struct zynqmp_qspi * xqspi)745dfe11a11SRanjit Waghmode static void zynqmp_process_dma_irq(struct zynqmp_qspi *xqspi)
746dfe11a11SRanjit Waghmode {
747dfe11a11SRanjit Waghmode 	u32 config_reg, genfifoentry;
748dfe11a11SRanjit Waghmode 
749dfe11a11SRanjit Waghmode 	dma_unmap_single(xqspi->dev, xqspi->dma_addr,
750dfe11a11SRanjit Waghmode 			 xqspi->dma_rx_bytes, DMA_FROM_DEVICE);
751dfe11a11SRanjit Waghmode 	xqspi->rxbuf += xqspi->dma_rx_bytes;
752dfe11a11SRanjit Waghmode 	xqspi->bytes_to_receive -= xqspi->dma_rx_bytes;
753dfe11a11SRanjit Waghmode 	xqspi->dma_rx_bytes = 0;
754dfe11a11SRanjit Waghmode 
755dfe11a11SRanjit Waghmode 	/* Disabling the DMA interrupts */
756dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_I_DIS_OFST,
757dfe11a11SRanjit Waghmode 			   GQSPI_QSPIDMA_DST_I_EN_DONE_MASK);
758dfe11a11SRanjit Waghmode 
759dfe11a11SRanjit Waghmode 	if (xqspi->bytes_to_receive > 0) {
760dfe11a11SRanjit Waghmode 		/* Switch to IO mode,for remaining bytes to receive */
761dfe11a11SRanjit Waghmode 		config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST);
762dfe11a11SRanjit Waghmode 		config_reg &= ~GQSPI_CFG_MODE_EN_MASK;
763dfe11a11SRanjit Waghmode 		zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg);
764dfe11a11SRanjit Waghmode 
765dfe11a11SRanjit Waghmode 		/* Initiate the transfer of remaining bytes */
766dfe11a11SRanjit Waghmode 		genfifoentry = xqspi->genfifoentry;
767dfe11a11SRanjit Waghmode 		genfifoentry |= xqspi->bytes_to_receive;
768dfe11a11SRanjit Waghmode 		zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, genfifoentry);
769dfe11a11SRanjit Waghmode 
770dfe11a11SRanjit Waghmode 		/* Dummy generic FIFO entry */
771dfe11a11SRanjit Waghmode 		zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, 0x0);
772dfe11a11SRanjit Waghmode 
773dfe11a11SRanjit Waghmode 		/* Manual start */
774dfe11a11SRanjit Waghmode 		zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
775f09a433bSAmit Kumar Mahapatra 				   (zynqmp_gqspi_read(xqspi,
776f09a433bSAmit Kumar Mahapatra 						      GQSPI_CONFIG_OFST) |
777dfe11a11SRanjit Waghmode 				   GQSPI_CFG_START_GEN_FIFO_MASK));
778dfe11a11SRanjit Waghmode 
779dfe11a11SRanjit Waghmode 		/* Enable the RX interrupts for IO mode */
780dfe11a11SRanjit Waghmode 		zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
781dfe11a11SRanjit Waghmode 				   GQSPI_IER_GENFIFOEMPTY_MASK |
782dfe11a11SRanjit Waghmode 				   GQSPI_IER_RXNEMPTY_MASK |
783dfe11a11SRanjit Waghmode 				   GQSPI_IER_RXEMPTY_MASK);
784dfe11a11SRanjit Waghmode 	}
785dfe11a11SRanjit Waghmode }
786dfe11a11SRanjit Waghmode 
787dfe11a11SRanjit Waghmode /**
78891af6eb0SAmit Kumar Mahapatra  * zynqmp_qspi_irq - Interrupt service routine of the QSPI controller
789dfe11a11SRanjit Waghmode  * @irq:	IRQ number
790dfe11a11SRanjit Waghmode  * @dev_id:	Pointer to the xqspi structure
791dfe11a11SRanjit Waghmode  *
792dfe11a11SRanjit Waghmode  * This function handles TX empty only.
793dfe11a11SRanjit Waghmode  * On TX empty interrupt this function reads the received data from RX FIFO
794dfe11a11SRanjit Waghmode  * and fills the TX FIFO if there is any data remaining to be transferred.
795dfe11a11SRanjit Waghmode  *
796dfe11a11SRanjit Waghmode  * Return:	IRQ_HANDLED when interrupt is handled
797dfe11a11SRanjit Waghmode  *		IRQ_NONE otherwise.
798dfe11a11SRanjit Waghmode  */
zynqmp_qspi_irq(int irq,void * dev_id)799dfe11a11SRanjit Waghmode static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id)
800dfe11a11SRanjit Waghmode {
8011c26372eSAmit Kumar Mahapatra 	struct zynqmp_qspi *xqspi = (struct zynqmp_qspi *)dev_id;
8021c26372eSAmit Kumar Mahapatra 	irqreturn_t ret = IRQ_NONE;
803dfe11a11SRanjit Waghmode 	u32 status, mask, dma_status = 0;
804dfe11a11SRanjit Waghmode 
805dfe11a11SRanjit Waghmode 	status = zynqmp_gqspi_read(xqspi, GQSPI_ISR_OFST);
806dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_ISR_OFST, status);
807dfe11a11SRanjit Waghmode 	mask = (status & ~(zynqmp_gqspi_read(xqspi, GQSPI_IMASK_OFST)));
808dfe11a11SRanjit Waghmode 
809dfe11a11SRanjit Waghmode 	/* Read and clear DMA status */
810dfe11a11SRanjit Waghmode 	if (xqspi->mode == GQSPI_MODE_DMA) {
811dfe11a11SRanjit Waghmode 		dma_status =
812dfe11a11SRanjit Waghmode 			zynqmp_gqspi_read(xqspi, GQSPI_QSPIDMA_DST_I_STS_OFST);
813dfe11a11SRanjit Waghmode 		zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_I_STS_OFST,
814dfe11a11SRanjit Waghmode 				   dma_status);
815dfe11a11SRanjit Waghmode 	}
816dfe11a11SRanjit Waghmode 
817dfe11a11SRanjit Waghmode 	if (mask & GQSPI_ISR_TXNOT_FULL_MASK) {
818dfe11a11SRanjit Waghmode 		zynqmp_qspi_filltxfifo(xqspi, GQSPI_TX_FIFO_FILL);
819dfe11a11SRanjit Waghmode 		ret = IRQ_HANDLED;
820dfe11a11SRanjit Waghmode 	}
821dfe11a11SRanjit Waghmode 
822dfe11a11SRanjit Waghmode 	if (dma_status & GQSPI_QSPIDMA_DST_I_STS_DONE_MASK) {
823dfe11a11SRanjit Waghmode 		zynqmp_process_dma_irq(xqspi);
824dfe11a11SRanjit Waghmode 		ret = IRQ_HANDLED;
825dfe11a11SRanjit Waghmode 	} else if (!(mask & GQSPI_IER_RXEMPTY_MASK) &&
826dfe11a11SRanjit Waghmode 			(mask & GQSPI_IER_GENFIFOEMPTY_MASK)) {
827dfe11a11SRanjit Waghmode 		zynqmp_qspi_readrxfifo(xqspi, GQSPI_RX_FIFO_FILL);
828dfe11a11SRanjit Waghmode 		ret = IRQ_HANDLED;
829dfe11a11SRanjit Waghmode 	}
830dfe11a11SRanjit Waghmode 
831f09a433bSAmit Kumar Mahapatra 	if (xqspi->bytes_to_receive == 0 && xqspi->bytes_to_transfer == 0 &&
832f09a433bSAmit Kumar Mahapatra 	    ((status & GQSPI_IRQ_MASK) == GQSPI_IRQ_MASK)) {
833dfe11a11SRanjit Waghmode 		zynqmp_gqspi_write(xqspi, GQSPI_IDR_OFST, GQSPI_ISR_IDR_MASK);
8341c26372eSAmit Kumar Mahapatra 		complete(&xqspi->data_completion);
835dfe11a11SRanjit Waghmode 		ret = IRQ_HANDLED;
836dfe11a11SRanjit Waghmode 	}
837dfe11a11SRanjit Waghmode 	return ret;
838dfe11a11SRanjit Waghmode }
839dfe11a11SRanjit Waghmode 
840dfe11a11SRanjit Waghmode /**
8411c26372eSAmit Kumar Mahapatra  * zynqmp_qspi_setuprxdma - This function sets up the RX DMA operation
842dfe11a11SRanjit Waghmode  * @xqspi:	xqspi is a pointer to the GQSPI instance.
843b3b95308SAmit Kumar Mahapatra  *
844b3b95308SAmit Kumar Mahapatra  * Return:	0 on success; error value otherwise.
845dfe11a11SRanjit Waghmode  */
zynqmp_qspi_setuprxdma(struct zynqmp_qspi * xqspi)846126bdb60SQuanyang Wang static int zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi)
847dfe11a11SRanjit Waghmode {
848dfe11a11SRanjit Waghmode 	u32 rx_bytes, rx_rem, config_reg;
849dfe11a11SRanjit Waghmode 	dma_addr_t addr;
850dfe11a11SRanjit Waghmode 	u64 dma_align =  (u64)(uintptr_t)xqspi->rxbuf;
851dfe11a11SRanjit Waghmode 
852f09a433bSAmit Kumar Mahapatra 	if (xqspi->bytes_to_receive < 8 ||
853dfe11a11SRanjit Waghmode 	    ((dma_align & GQSPI_DMA_UNALIGN) != 0x0)) {
854dfe11a11SRanjit Waghmode 		/* Setting to IO mode */
855dfe11a11SRanjit Waghmode 		config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST);
856dfe11a11SRanjit Waghmode 		config_reg &= ~GQSPI_CFG_MODE_EN_MASK;
857dfe11a11SRanjit Waghmode 		zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg);
858dfe11a11SRanjit Waghmode 		xqspi->mode = GQSPI_MODE_IO;
859dfe11a11SRanjit Waghmode 		xqspi->dma_rx_bytes = 0;
860126bdb60SQuanyang Wang 		return 0;
861dfe11a11SRanjit Waghmode 	}
862dfe11a11SRanjit Waghmode 
863dfe11a11SRanjit Waghmode 	rx_rem = xqspi->bytes_to_receive % 4;
864dfe11a11SRanjit Waghmode 	rx_bytes = (xqspi->bytes_to_receive - rx_rem);
865dfe11a11SRanjit Waghmode 
866dfe11a11SRanjit Waghmode 	addr = dma_map_single(xqspi->dev, (void *)xqspi->rxbuf,
867dfe11a11SRanjit Waghmode 			      rx_bytes, DMA_FROM_DEVICE);
868126bdb60SQuanyang Wang 	if (dma_mapping_error(xqspi->dev, addr)) {
869dfe11a11SRanjit Waghmode 		dev_err(xqspi->dev, "ERR:rxdma:memory not mapped\n");
870126bdb60SQuanyang Wang 		return -ENOMEM;
871126bdb60SQuanyang Wang 	}
872dfe11a11SRanjit Waghmode 
873dfe11a11SRanjit Waghmode 	xqspi->dma_rx_bytes = rx_bytes;
874dfe11a11SRanjit Waghmode 	xqspi->dma_addr = addr;
875dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_ADDR_OFST,
876dfe11a11SRanjit Waghmode 			   (u32)(addr & 0xffffffff));
877dfe11a11SRanjit Waghmode 	addr = ((addr >> 16) >> 16);
878dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_ADDR_MSB_OFST,
879dfe11a11SRanjit Waghmode 			   ((u32)addr) & 0xfff);
880dfe11a11SRanjit Waghmode 
881dfe11a11SRanjit Waghmode 	/* Enabling the DMA mode */
882dfe11a11SRanjit Waghmode 	config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST);
883dfe11a11SRanjit Waghmode 	config_reg &= ~GQSPI_CFG_MODE_EN_MASK;
884dfe11a11SRanjit Waghmode 	config_reg |= GQSPI_CFG_MODE_EN_DMA_MASK;
885dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg);
886dfe11a11SRanjit Waghmode 
887dfe11a11SRanjit Waghmode 	/* Switch to DMA mode */
888dfe11a11SRanjit Waghmode 	xqspi->mode = GQSPI_MODE_DMA;
889dfe11a11SRanjit Waghmode 
890dfe11a11SRanjit Waghmode 	/* Write the number of bytes to transfer */
891dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_SIZE_OFST, rx_bytes);
892126bdb60SQuanyang Wang 
893126bdb60SQuanyang Wang 	return 0;
894dfe11a11SRanjit Waghmode }
895dfe11a11SRanjit Waghmode 
896dfe11a11SRanjit Waghmode /**
8971c26372eSAmit Kumar Mahapatra  * zynqmp_qspi_write_op - This function sets up the GENFIFO entries,
8981c26372eSAmit Kumar Mahapatra  *			TX FIFO, and fills the TX FIFO with as many
8991c26372eSAmit Kumar Mahapatra  *			bytes as possible.
9001c26372eSAmit Kumar Mahapatra  * @xqspi:	Pointer to the GQSPI instance.
9011c26372eSAmit Kumar Mahapatra  * @tx_nbits:	Transfer buswidth.
9021c26372eSAmit Kumar Mahapatra  * @genfifoentry:	Variable in which GENFIFO mask is returned
9031c26372eSAmit Kumar Mahapatra  *			to calling function
904dfe11a11SRanjit Waghmode  */
zynqmp_qspi_write_op(struct zynqmp_qspi * xqspi,u8 tx_nbits,u32 genfifoentry)9051c26372eSAmit Kumar Mahapatra static void zynqmp_qspi_write_op(struct zynqmp_qspi *xqspi, u8 tx_nbits,
9061c26372eSAmit Kumar Mahapatra 				 u32 genfifoentry)
907dfe11a11SRanjit Waghmode {
908dfe11a11SRanjit Waghmode 	u32 config_reg;
909dfe11a11SRanjit Waghmode 
9101c26372eSAmit Kumar Mahapatra 	zynqmp_qspi_fillgenfifo(xqspi, tx_nbits, genfifoentry);
9111c26372eSAmit Kumar Mahapatra 	zynqmp_qspi_filltxfifo(xqspi, GQSPI_TXD_DEPTH);
912dfe11a11SRanjit Waghmode 	if (xqspi->mode == GQSPI_MODE_DMA) {
913dfe11a11SRanjit Waghmode 		config_reg = zynqmp_gqspi_read(xqspi,
914dfe11a11SRanjit Waghmode 					       GQSPI_CONFIG_OFST);
915dfe11a11SRanjit Waghmode 		config_reg &= ~GQSPI_CFG_MODE_EN_MASK;
916dfe11a11SRanjit Waghmode 		zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
917dfe11a11SRanjit Waghmode 				   config_reg);
918dfe11a11SRanjit Waghmode 		xqspi->mode = GQSPI_MODE_IO;
919dfe11a11SRanjit Waghmode 	}
920dfe11a11SRanjit Waghmode }
921dfe11a11SRanjit Waghmode 
922dfe11a11SRanjit Waghmode /**
9231c26372eSAmit Kumar Mahapatra  * zynqmp_qspi_read_op - This function sets up the GENFIFO entries and
9241c26372eSAmit Kumar Mahapatra  *				RX DMA operation.
9251c26372eSAmit Kumar Mahapatra  * @xqspi:	xqspi is a pointer to the GQSPI instance.
9261c26372eSAmit Kumar Mahapatra  * @rx_nbits:	Receive buswidth.
9271c26372eSAmit Kumar Mahapatra  * @genfifoentry:	genfifoentry is pointer to the variable in which
9281c26372eSAmit Kumar Mahapatra  *			GENFIFO	mask is returned to calling function
929b3b95308SAmit Kumar Mahapatra  *
930b3b95308SAmit Kumar Mahapatra  * Return:	0 on success; error value otherwise.
931dfe11a11SRanjit Waghmode  */
zynqmp_qspi_read_op(struct zynqmp_qspi * xqspi,u8 rx_nbits,u32 genfifoentry)932126bdb60SQuanyang Wang static int zynqmp_qspi_read_op(struct zynqmp_qspi *xqspi, u8 rx_nbits,
9331c26372eSAmit Kumar Mahapatra 				u32 genfifoentry)
934dfe11a11SRanjit Waghmode {
935126bdb60SQuanyang Wang 	int ret;
936126bdb60SQuanyang Wang 
937126bdb60SQuanyang Wang 	ret = zynqmp_qspi_setuprxdma(xqspi);
938126bdb60SQuanyang Wang 	if (ret)
939126bdb60SQuanyang Wang 		return ret;
94041d31093SQuanyang Wang 	zynqmp_qspi_fillgenfifo(xqspi, rx_nbits, genfifoentry);
941126bdb60SQuanyang Wang 
942126bdb60SQuanyang Wang 	return 0;
943dfe11a11SRanjit Waghmode }
944dfe11a11SRanjit Waghmode 
945dfe11a11SRanjit Waghmode /**
94691af6eb0SAmit Kumar Mahapatra  * zynqmp_qspi_suspend - Suspend method for the QSPI driver
9474b42b0b4SLee Jones  * @dev:	Address of the platform_device structure
948dfe11a11SRanjit Waghmode  *
949dfe11a11SRanjit Waghmode  * This function stops the QSPI driver queue and disables the QSPI controller
950dfe11a11SRanjit Waghmode  *
951dfe11a11SRanjit Waghmode  * Return:	Always 0
952dfe11a11SRanjit Waghmode  */
zynqmp_qspi_suspend(struct device * dev)953dfe11a11SRanjit Waghmode static int __maybe_unused zynqmp_qspi_suspend(struct device *dev)
954dfe11a11SRanjit Waghmode {
955799f923fSQuanyang Wang 	struct zynqmp_qspi *xqspi = dev_get_drvdata(dev);
956799f923fSQuanyang Wang 	struct spi_controller *ctlr = xqspi->ctlr;
957799f923fSQuanyang Wang 	int ret;
958dfe11a11SRanjit Waghmode 
959799f923fSQuanyang Wang 	ret = spi_controller_suspend(ctlr);
960799f923fSQuanyang Wang 	if (ret)
961799f923fSQuanyang Wang 		return ret;
962dfe11a11SRanjit Waghmode 
9631c26372eSAmit Kumar Mahapatra 	zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, 0x0);
964dfe11a11SRanjit Waghmode 
965dfe11a11SRanjit Waghmode 	return 0;
966dfe11a11SRanjit Waghmode }
967dfe11a11SRanjit Waghmode 
968dfe11a11SRanjit Waghmode /**
96991af6eb0SAmit Kumar Mahapatra  * zynqmp_qspi_resume - Resume method for the QSPI driver
970dfe11a11SRanjit Waghmode  * @dev:	Address of the platform_device structure
971dfe11a11SRanjit Waghmode  *
972dfe11a11SRanjit Waghmode  * The function starts the QSPI driver queue and initializes the QSPI
973dfe11a11SRanjit Waghmode  * controller
974dfe11a11SRanjit Waghmode  *
975dfe11a11SRanjit Waghmode  * Return:	0 on success; error value otherwise
976dfe11a11SRanjit Waghmode  */
zynqmp_qspi_resume(struct device * dev)977dfe11a11SRanjit Waghmode static int __maybe_unused zynqmp_qspi_resume(struct device *dev)
978dfe11a11SRanjit Waghmode {
979799f923fSQuanyang Wang 	struct zynqmp_qspi *xqspi = dev_get_drvdata(dev);
980799f923fSQuanyang Wang 	struct spi_controller *ctlr = xqspi->ctlr;
981799f923fSQuanyang Wang 
982799f923fSQuanyang Wang 	zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, GQSPI_EN_MASK);
983dfe11a11SRanjit Waghmode 
9841c26372eSAmit Kumar Mahapatra 	spi_controller_resume(ctlr);
985dfe11a11SRanjit Waghmode 
986dfe11a11SRanjit Waghmode 	return 0;
987dfe11a11SRanjit Waghmode }
988dfe11a11SRanjit Waghmode 
9899e3a0003SNaga Sureshkumar Relli /**
9909e3a0003SNaga Sureshkumar Relli  * zynqmp_runtime_suspend - Runtime suspend method for the SPI driver
9919e3a0003SNaga Sureshkumar Relli  * @dev:	Address of the platform_device structure
9929e3a0003SNaga Sureshkumar Relli  *
9939e3a0003SNaga Sureshkumar Relli  * This function disables the clocks
9949e3a0003SNaga Sureshkumar Relli  *
9959e3a0003SNaga Sureshkumar Relli  * Return:	Always 0
9969e3a0003SNaga Sureshkumar Relli  */
zynqmp_runtime_suspend(struct device * dev)9979e3a0003SNaga Sureshkumar Relli static int __maybe_unused zynqmp_runtime_suspend(struct device *dev)
9989e3a0003SNaga Sureshkumar Relli {
999799f923fSQuanyang Wang 	struct zynqmp_qspi *xqspi = dev_get_drvdata(dev);
10009e3a0003SNaga Sureshkumar Relli 
1001c6bdae08SQuanyang Wang 	clk_disable_unprepare(xqspi->refclk);
1002c6bdae08SQuanyang Wang 	clk_disable_unprepare(xqspi->pclk);
10039e3a0003SNaga Sureshkumar Relli 
10049e3a0003SNaga Sureshkumar Relli 	return 0;
10059e3a0003SNaga Sureshkumar Relli }
10069e3a0003SNaga Sureshkumar Relli 
10079e3a0003SNaga Sureshkumar Relli /**
10089e3a0003SNaga Sureshkumar Relli  * zynqmp_runtime_resume - Runtime resume method for the SPI driver
10099e3a0003SNaga Sureshkumar Relli  * @dev:	Address of the platform_device structure
10109e3a0003SNaga Sureshkumar Relli  *
10119e3a0003SNaga Sureshkumar Relli  * This function enables the clocks
10129e3a0003SNaga Sureshkumar Relli  *
10139e3a0003SNaga Sureshkumar Relli  * Return:	0 on success and error value on error
10149e3a0003SNaga Sureshkumar Relli  */
zynqmp_runtime_resume(struct device * dev)10159e3a0003SNaga Sureshkumar Relli static int __maybe_unused zynqmp_runtime_resume(struct device *dev)
10169e3a0003SNaga Sureshkumar Relli {
1017799f923fSQuanyang Wang 	struct zynqmp_qspi *xqspi = dev_get_drvdata(dev);
10189e3a0003SNaga Sureshkumar Relli 	int ret;
10199e3a0003SNaga Sureshkumar Relli 
1020c6bdae08SQuanyang Wang 	ret = clk_prepare_enable(xqspi->pclk);
10219e3a0003SNaga Sureshkumar Relli 	if (ret) {
10229e3a0003SNaga Sureshkumar Relli 		dev_err(dev, "Cannot enable APB clock.\n");
10239e3a0003SNaga Sureshkumar Relli 		return ret;
10249e3a0003SNaga Sureshkumar Relli 	}
10259e3a0003SNaga Sureshkumar Relli 
1026c6bdae08SQuanyang Wang 	ret = clk_prepare_enable(xqspi->refclk);
10279e3a0003SNaga Sureshkumar Relli 	if (ret) {
10289e3a0003SNaga Sureshkumar Relli 		dev_err(dev, "Cannot enable device clock.\n");
1029c6bdae08SQuanyang Wang 		clk_disable_unprepare(xqspi->pclk);
10309e3a0003SNaga Sureshkumar Relli 		return ret;
10319e3a0003SNaga Sureshkumar Relli 	}
10329e3a0003SNaga Sureshkumar Relli 
10339e3a0003SNaga Sureshkumar Relli 	return 0;
10349e3a0003SNaga Sureshkumar Relli }
10359e3a0003SNaga Sureshkumar Relli 
10361c26372eSAmit Kumar Mahapatra /**
10371c26372eSAmit Kumar Mahapatra  * zynqmp_qspi_exec_op() - Initiates the QSPI transfer
10381c26372eSAmit Kumar Mahapatra  * @mem: The SPI memory
10391c26372eSAmit Kumar Mahapatra  * @op: The memory operation to execute
10401c26372eSAmit Kumar Mahapatra  *
10411c26372eSAmit Kumar Mahapatra  * Executes a memory operation.
10421c26372eSAmit Kumar Mahapatra  *
10431c26372eSAmit Kumar Mahapatra  * This function first selects the chip and starts the memory operation.
10441c26372eSAmit Kumar Mahapatra  *
10451c26372eSAmit Kumar Mahapatra  * Return: 0 in case of success, a negative error code otherwise.
10461c26372eSAmit Kumar Mahapatra  */
zynqmp_qspi_exec_op(struct spi_mem * mem,const struct spi_mem_op * op)10471c26372eSAmit Kumar Mahapatra static int zynqmp_qspi_exec_op(struct spi_mem *mem,
10481c26372eSAmit Kumar Mahapatra 			       const struct spi_mem_op *op)
10491c26372eSAmit Kumar Mahapatra {
10501c26372eSAmit Kumar Mahapatra 	struct zynqmp_qspi *xqspi = spi_controller_get_devdata
10511c26372eSAmit Kumar Mahapatra 				    (mem->spi->master);
10521c26372eSAmit Kumar Mahapatra 	int err = 0, i;
10531c26372eSAmit Kumar Mahapatra 	u32 genfifoentry = 0;
1054a2c5bedbSQuanyang Wang 	u16 opcode = op->cmd.opcode;
1055a2c5bedbSQuanyang Wang 	u64 opaddr;
10561c26372eSAmit Kumar Mahapatra 
10571c26372eSAmit Kumar Mahapatra 	dev_dbg(xqspi->dev, "cmd:%#x mode:%d.%d.%d.%d\n",
10581c26372eSAmit Kumar Mahapatra 		op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
10591c26372eSAmit Kumar Mahapatra 		op->dummy.buswidth, op->data.buswidth);
10601c26372eSAmit Kumar Mahapatra 
1061a0f65be6SQuanyang Wang 	mutex_lock(&xqspi->op_lock);
10621c26372eSAmit Kumar Mahapatra 	zynqmp_qspi_config_op(xqspi, mem->spi);
10631c26372eSAmit Kumar Mahapatra 	zynqmp_qspi_chipselect(mem->spi, false);
10641c26372eSAmit Kumar Mahapatra 	genfifoentry |= xqspi->genfifocs;
10651c26372eSAmit Kumar Mahapatra 	genfifoentry |= xqspi->genfifobus;
10661c26372eSAmit Kumar Mahapatra 
10671c26372eSAmit Kumar Mahapatra 	if (op->cmd.opcode) {
10681c26372eSAmit Kumar Mahapatra 		reinit_completion(&xqspi->data_completion);
1069a2c5bedbSQuanyang Wang 		xqspi->txbuf = &opcode;
10701c26372eSAmit Kumar Mahapatra 		xqspi->rxbuf = NULL;
10711c26372eSAmit Kumar Mahapatra 		xqspi->bytes_to_transfer = op->cmd.nbytes;
10721c26372eSAmit Kumar Mahapatra 		xqspi->bytes_to_receive = 0;
10731c26372eSAmit Kumar Mahapatra 		zynqmp_qspi_write_op(xqspi, op->cmd.buswidth, genfifoentry);
10741c26372eSAmit Kumar Mahapatra 		zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
10751c26372eSAmit Kumar Mahapatra 				   zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) |
10761c26372eSAmit Kumar Mahapatra 				   GQSPI_CFG_START_GEN_FIFO_MASK);
10771c26372eSAmit Kumar Mahapatra 		zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
10781c26372eSAmit Kumar Mahapatra 				   GQSPI_IER_GENFIFOEMPTY_MASK |
10791c26372eSAmit Kumar Mahapatra 				   GQSPI_IER_TXNOT_FULL_MASK);
1080a16bff68SQuanyang Wang 		if (!wait_for_completion_timeout
10811c26372eSAmit Kumar Mahapatra 		    (&xqspi->data_completion, msecs_to_jiffies(1000))) {
10821c26372eSAmit Kumar Mahapatra 			err = -ETIMEDOUT;
10831c26372eSAmit Kumar Mahapatra 			goto return_err;
10841c26372eSAmit Kumar Mahapatra 		}
10851c26372eSAmit Kumar Mahapatra 	}
10861c26372eSAmit Kumar Mahapatra 
10871c26372eSAmit Kumar Mahapatra 	if (op->addr.nbytes) {
1088a2c5bedbSQuanyang Wang 		xqspi->txbuf = &opaddr;
10891c26372eSAmit Kumar Mahapatra 		for (i = 0; i < op->addr.nbytes; i++) {
10901c26372eSAmit Kumar Mahapatra 			*(((u8 *)xqspi->txbuf) + i) = op->addr.val >>
10911c26372eSAmit Kumar Mahapatra 					(8 * (op->addr.nbytes - i - 1));
10921c26372eSAmit Kumar Mahapatra 		}
10931c26372eSAmit Kumar Mahapatra 
10941c26372eSAmit Kumar Mahapatra 		reinit_completion(&xqspi->data_completion);
10951c26372eSAmit Kumar Mahapatra 		xqspi->rxbuf = NULL;
10961c26372eSAmit Kumar Mahapatra 		xqspi->bytes_to_transfer = op->addr.nbytes;
10971c26372eSAmit Kumar Mahapatra 		xqspi->bytes_to_receive = 0;
10981c26372eSAmit Kumar Mahapatra 		zynqmp_qspi_write_op(xqspi, op->addr.buswidth, genfifoentry);
10991c26372eSAmit Kumar Mahapatra 		zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
11001c26372eSAmit Kumar Mahapatra 				   zynqmp_gqspi_read(xqspi,
11011c26372eSAmit Kumar Mahapatra 						     GQSPI_CONFIG_OFST) |
11021c26372eSAmit Kumar Mahapatra 				   GQSPI_CFG_START_GEN_FIFO_MASK);
11031c26372eSAmit Kumar Mahapatra 		zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
11041c26372eSAmit Kumar Mahapatra 				   GQSPI_IER_TXEMPTY_MASK |
11051c26372eSAmit Kumar Mahapatra 				   GQSPI_IER_GENFIFOEMPTY_MASK |
11061c26372eSAmit Kumar Mahapatra 				   GQSPI_IER_TXNOT_FULL_MASK);
1107a16bff68SQuanyang Wang 		if (!wait_for_completion_timeout
11081c26372eSAmit Kumar Mahapatra 		    (&xqspi->data_completion, msecs_to_jiffies(1000))) {
11091c26372eSAmit Kumar Mahapatra 			err = -ETIMEDOUT;
11101c26372eSAmit Kumar Mahapatra 			goto return_err;
11111c26372eSAmit Kumar Mahapatra 		}
11121c26372eSAmit Kumar Mahapatra 	}
11131c26372eSAmit Kumar Mahapatra 
11141c26372eSAmit Kumar Mahapatra 	if (op->dummy.nbytes) {
11158ad07d79SQuanyang Wang 		xqspi->txbuf = NULL;
11161c26372eSAmit Kumar Mahapatra 		xqspi->rxbuf = NULL;
11178ad07d79SQuanyang Wang 		/*
11188ad07d79SQuanyang Wang 		 * xqspi->bytes_to_transfer here represents the dummy circles
11198ad07d79SQuanyang Wang 		 * which need to be sent.
11208ad07d79SQuanyang Wang 		 */
11218ad07d79SQuanyang Wang 		xqspi->bytes_to_transfer = op->dummy.nbytes * 8 / op->dummy.buswidth;
11221c26372eSAmit Kumar Mahapatra 		xqspi->bytes_to_receive = 0;
11238ad07d79SQuanyang Wang 		/*
11248ad07d79SQuanyang Wang 		 * Using op->data.buswidth instead of op->dummy.buswidth here because
11258ad07d79SQuanyang Wang 		 * we need to use it to configure the correct SPI mode.
11268ad07d79SQuanyang Wang 		 */
11278ad07d79SQuanyang Wang 		zynqmp_qspi_write_op(xqspi, op->data.buswidth,
11281c26372eSAmit Kumar Mahapatra 				     genfifoentry);
11291c26372eSAmit Kumar Mahapatra 		zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
11301c26372eSAmit Kumar Mahapatra 				   zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) |
11311c26372eSAmit Kumar Mahapatra 				   GQSPI_CFG_START_GEN_FIFO_MASK);
11321c26372eSAmit Kumar Mahapatra 	}
11331c26372eSAmit Kumar Mahapatra 
11341c26372eSAmit Kumar Mahapatra 	if (op->data.nbytes) {
11351c26372eSAmit Kumar Mahapatra 		reinit_completion(&xqspi->data_completion);
11361c26372eSAmit Kumar Mahapatra 		if (op->data.dir == SPI_MEM_DATA_OUT) {
11371c26372eSAmit Kumar Mahapatra 			xqspi->txbuf = (u8 *)op->data.buf.out;
11381c26372eSAmit Kumar Mahapatra 			xqspi->rxbuf = NULL;
11391c26372eSAmit Kumar Mahapatra 			xqspi->bytes_to_transfer = op->data.nbytes;
11401c26372eSAmit Kumar Mahapatra 			xqspi->bytes_to_receive = 0;
11411c26372eSAmit Kumar Mahapatra 			zynqmp_qspi_write_op(xqspi, op->data.buswidth,
11421c26372eSAmit Kumar Mahapatra 					     genfifoentry);
11431c26372eSAmit Kumar Mahapatra 			zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
11441c26372eSAmit Kumar Mahapatra 					   zynqmp_gqspi_read
11451c26372eSAmit Kumar Mahapatra 					   (xqspi, GQSPI_CONFIG_OFST) |
11461c26372eSAmit Kumar Mahapatra 					   GQSPI_CFG_START_GEN_FIFO_MASK);
11471c26372eSAmit Kumar Mahapatra 			zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
11481c26372eSAmit Kumar Mahapatra 					   GQSPI_IER_TXEMPTY_MASK |
11491c26372eSAmit Kumar Mahapatra 					   GQSPI_IER_GENFIFOEMPTY_MASK |
11501c26372eSAmit Kumar Mahapatra 					   GQSPI_IER_TXNOT_FULL_MASK);
11511c26372eSAmit Kumar Mahapatra 		} else {
11521c26372eSAmit Kumar Mahapatra 			xqspi->txbuf = NULL;
11531c26372eSAmit Kumar Mahapatra 			xqspi->rxbuf = (u8 *)op->data.buf.in;
11541c26372eSAmit Kumar Mahapatra 			xqspi->bytes_to_receive = op->data.nbytes;
11551c26372eSAmit Kumar Mahapatra 			xqspi->bytes_to_transfer = 0;
1156126bdb60SQuanyang Wang 			err = zynqmp_qspi_read_op(xqspi, op->data.buswidth,
11571c26372eSAmit Kumar Mahapatra 					    genfifoentry);
1158126bdb60SQuanyang Wang 			if (err)
1159126bdb60SQuanyang Wang 				goto return_err;
1160126bdb60SQuanyang Wang 
11611c26372eSAmit Kumar Mahapatra 			zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
11621c26372eSAmit Kumar Mahapatra 					   zynqmp_gqspi_read
11631c26372eSAmit Kumar Mahapatra 					   (xqspi, GQSPI_CONFIG_OFST) |
11641c26372eSAmit Kumar Mahapatra 					   GQSPI_CFG_START_GEN_FIFO_MASK);
11651c26372eSAmit Kumar Mahapatra 			if (xqspi->mode == GQSPI_MODE_DMA) {
11661c26372eSAmit Kumar Mahapatra 				zynqmp_gqspi_write
11671c26372eSAmit Kumar Mahapatra 					(xqspi, GQSPI_QSPIDMA_DST_I_EN_OFST,
11681c26372eSAmit Kumar Mahapatra 					 GQSPI_QSPIDMA_DST_I_EN_DONE_MASK);
11691c26372eSAmit Kumar Mahapatra 			} else {
11701c26372eSAmit Kumar Mahapatra 				zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
11711c26372eSAmit Kumar Mahapatra 						   GQSPI_IER_GENFIFOEMPTY_MASK |
11721c26372eSAmit Kumar Mahapatra 						   GQSPI_IER_RXNEMPTY_MASK |
11731c26372eSAmit Kumar Mahapatra 						   GQSPI_IER_RXEMPTY_MASK);
11741c26372eSAmit Kumar Mahapatra 			}
11751c26372eSAmit Kumar Mahapatra 		}
1176a16bff68SQuanyang Wang 		if (!wait_for_completion_timeout
11771c26372eSAmit Kumar Mahapatra 		    (&xqspi->data_completion, msecs_to_jiffies(1000)))
11781c26372eSAmit Kumar Mahapatra 			err = -ETIMEDOUT;
11791c26372eSAmit Kumar Mahapatra 	}
11801c26372eSAmit Kumar Mahapatra 
11811c26372eSAmit Kumar Mahapatra return_err:
11821c26372eSAmit Kumar Mahapatra 
11831c26372eSAmit Kumar Mahapatra 	zynqmp_qspi_chipselect(mem->spi, true);
1184a0f65be6SQuanyang Wang 	mutex_unlock(&xqspi->op_lock);
11851c26372eSAmit Kumar Mahapatra 
11861c26372eSAmit Kumar Mahapatra 	return err;
11871c26372eSAmit Kumar Mahapatra }
11881c26372eSAmit Kumar Mahapatra 
11899e3a0003SNaga Sureshkumar Relli static const struct dev_pm_ops zynqmp_qspi_dev_pm_ops = {
11909e3a0003SNaga Sureshkumar Relli 	SET_RUNTIME_PM_OPS(zynqmp_runtime_suspend,
11919e3a0003SNaga Sureshkumar Relli 			   zynqmp_runtime_resume, NULL)
11929e3a0003SNaga Sureshkumar Relli 	SET_SYSTEM_SLEEP_PM_OPS(zynqmp_qspi_suspend, zynqmp_qspi_resume)
11939e3a0003SNaga Sureshkumar Relli };
1194dfe11a11SRanjit Waghmode 
119529f4d95bSAmit Kumar Mahapatra static const struct qspi_platform_data versal_qspi_def = {
119629f4d95bSAmit Kumar Mahapatra 	.quirks = QSPI_QUIRK_HAS_TAPDELAY,
119729f4d95bSAmit Kumar Mahapatra };
119829f4d95bSAmit Kumar Mahapatra 
119929f4d95bSAmit Kumar Mahapatra static const struct of_device_id zynqmp_qspi_of_match[] = {
120029f4d95bSAmit Kumar Mahapatra 	{ .compatible = "xlnx,zynqmp-qspi-1.0"},
120129f4d95bSAmit Kumar Mahapatra 	{ .compatible = "xlnx,versal-qspi-1.0", .data = &versal_qspi_def },
120229f4d95bSAmit Kumar Mahapatra 	{ /* End of table */ }
120329f4d95bSAmit Kumar Mahapatra };
120429f4d95bSAmit Kumar Mahapatra 
12051c26372eSAmit Kumar Mahapatra static const struct spi_controller_mem_ops zynqmp_qspi_mem_ops = {
12061c26372eSAmit Kumar Mahapatra 	.exec_op = zynqmp_qspi_exec_op,
12071c26372eSAmit Kumar Mahapatra };
12081c26372eSAmit Kumar Mahapatra 
1209dfe11a11SRanjit Waghmode /**
121091af6eb0SAmit Kumar Mahapatra  * zynqmp_qspi_probe - Probe method for the QSPI driver
1211dfe11a11SRanjit Waghmode  * @pdev:	Pointer to the platform_device structure
1212dfe11a11SRanjit Waghmode  *
1213dfe11a11SRanjit Waghmode  * This function initializes the driver data structures and the hardware.
1214dfe11a11SRanjit Waghmode  *
1215dfe11a11SRanjit Waghmode  * Return:	0 on success; error value otherwise
1216dfe11a11SRanjit Waghmode  */
zynqmp_qspi_probe(struct platform_device * pdev)1217dfe11a11SRanjit Waghmode static int zynqmp_qspi_probe(struct platform_device *pdev)
1218dfe11a11SRanjit Waghmode {
1219dfe11a11SRanjit Waghmode 	int ret = 0;
12201c26372eSAmit Kumar Mahapatra 	struct spi_controller *ctlr;
1221dfe11a11SRanjit Waghmode 	struct zynqmp_qspi *xqspi;
1222dfe11a11SRanjit Waghmode 	struct device *dev = &pdev->dev;
12231c26372eSAmit Kumar Mahapatra 	struct device_node *np = dev->of_node;
1224dd9c232dSAmit Kumar Mahapatra 	u32 num_cs;
122529f4d95bSAmit Kumar Mahapatra 	const struct qspi_platform_data *p_data;
1226dfe11a11SRanjit Waghmode 
12271c26372eSAmit Kumar Mahapatra 	ctlr = spi_alloc_master(&pdev->dev, sizeof(*xqspi));
12281c26372eSAmit Kumar Mahapatra 	if (!ctlr)
1229dfe11a11SRanjit Waghmode 		return -ENOMEM;
1230dfe11a11SRanjit Waghmode 
12311c26372eSAmit Kumar Mahapatra 	xqspi = spi_controller_get_devdata(ctlr);
12321c26372eSAmit Kumar Mahapatra 	xqspi->dev = dev;
1233799f923fSQuanyang Wang 	xqspi->ctlr = ctlr;
12341c26372eSAmit Kumar Mahapatra 	platform_set_drvdata(pdev, xqspi);
1235dfe11a11SRanjit Waghmode 
123629f4d95bSAmit Kumar Mahapatra 	p_data = of_device_get_match_data(&pdev->dev);
123729f4d95bSAmit Kumar Mahapatra 	if (p_data && (p_data->quirks & QSPI_QUIRK_HAS_TAPDELAY))
123829f4d95bSAmit Kumar Mahapatra 		xqspi->has_tapdelay = true;
123929f4d95bSAmit Kumar Mahapatra 
1240214d1edbSYueHaibing 	xqspi->regs = devm_platform_ioremap_resource(pdev, 0);
1241dfe11a11SRanjit Waghmode 	if (IS_ERR(xqspi->regs)) {
1242dfe11a11SRanjit Waghmode 		ret = PTR_ERR(xqspi->regs);
1243dfe11a11SRanjit Waghmode 		goto remove_master;
1244dfe11a11SRanjit Waghmode 	}
1245dfe11a11SRanjit Waghmode 
1246dfe11a11SRanjit Waghmode 	xqspi->pclk = devm_clk_get(&pdev->dev, "pclk");
1247dfe11a11SRanjit Waghmode 	if (IS_ERR(xqspi->pclk)) {
1248dfe11a11SRanjit Waghmode 		dev_err(dev, "pclk clock not found.\n");
1249dfe11a11SRanjit Waghmode 		ret = PTR_ERR(xqspi->pclk);
1250dfe11a11SRanjit Waghmode 		goto remove_master;
1251dfe11a11SRanjit Waghmode 	}
1252dfe11a11SRanjit Waghmode 
1253dfe11a11SRanjit Waghmode 	xqspi->refclk = devm_clk_get(&pdev->dev, "ref_clk");
1254dfe11a11SRanjit Waghmode 	if (IS_ERR(xqspi->refclk)) {
1255dfe11a11SRanjit Waghmode 		dev_err(dev, "ref_clk clock not found.\n");
1256dfe11a11SRanjit Waghmode 		ret = PTR_ERR(xqspi->refclk);
1257c6bdae08SQuanyang Wang 		goto remove_master;
1258dfe11a11SRanjit Waghmode 	}
1259dfe11a11SRanjit Waghmode 
12601c26372eSAmit Kumar Mahapatra 	ret = clk_prepare_enable(xqspi->pclk);
12611c26372eSAmit Kumar Mahapatra 	if (ret) {
12621c26372eSAmit Kumar Mahapatra 		dev_err(dev, "Unable to enable APB clock.\n");
12631c26372eSAmit Kumar Mahapatra 		goto remove_master;
12641c26372eSAmit Kumar Mahapatra 	}
12651c26372eSAmit Kumar Mahapatra 
1266dfe11a11SRanjit Waghmode 	ret = clk_prepare_enable(xqspi->refclk);
1267dfe11a11SRanjit Waghmode 	if (ret) {
1268dfe11a11SRanjit Waghmode 		dev_err(dev, "Unable to enable device clock.\n");
1269dfe11a11SRanjit Waghmode 		goto clk_dis_pclk;
1270dfe11a11SRanjit Waghmode 	}
1271dfe11a11SRanjit Waghmode 
1272c6bdae08SQuanyang Wang 	init_completion(&xqspi->data_completion);
1273c6bdae08SQuanyang Wang 
1274a0f65be6SQuanyang Wang 	mutex_init(&xqspi->op_lock);
1275a0f65be6SQuanyang Wang 
12769e3a0003SNaga Sureshkumar Relli 	pm_runtime_use_autosuspend(&pdev->dev);
12779e3a0003SNaga Sureshkumar Relli 	pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
12789e3a0003SNaga Sureshkumar Relli 	pm_runtime_set_active(&pdev->dev);
12799e3a0003SNaga Sureshkumar Relli 	pm_runtime_enable(&pdev->dev);
128058eaa7b2SDinghao Liu 
128158eaa7b2SDinghao Liu 	ret = pm_runtime_get_sync(&pdev->dev);
128258eaa7b2SDinghao Liu 	if (ret < 0) {
128358eaa7b2SDinghao Liu 		dev_err(&pdev->dev, "Failed to pm_runtime_get_sync: %d\n", ret);
128458eaa7b2SDinghao Liu 		goto clk_dis_all;
128558eaa7b2SDinghao Liu 	}
128658eaa7b2SDinghao Liu 
128722742b8bSAmit Kumar Mahapatra 	ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD |
128822742b8bSAmit Kumar Mahapatra 		SPI_TX_DUAL | SPI_TX_QUAD;
128921764a49SAmit Kumar Mahapatra 	ctlr->max_speed_hz = clk_get_rate(xqspi->refclk) / 2;
129021764a49SAmit Kumar Mahapatra 	xqspi->speed_hz = ctlr->max_speed_hz;
129122742b8bSAmit Kumar Mahapatra 
1292dfe11a11SRanjit Waghmode 	/* QSPI controller initializations */
1293dfe11a11SRanjit Waghmode 	zynqmp_qspi_init_hw(xqspi);
1294dfe11a11SRanjit Waghmode 
1295dfe11a11SRanjit Waghmode 	xqspi->irq = platform_get_irq(pdev, 0);
12963182d49aSRuan Jinjie 	if (xqspi->irq < 0) {
12973182d49aSRuan Jinjie 		ret = xqspi->irq;
1298dfe11a11SRanjit Waghmode 		goto clk_dis_all;
1299dfe11a11SRanjit Waghmode 	}
1300dfe11a11SRanjit Waghmode 	ret = devm_request_irq(&pdev->dev, xqspi->irq, zynqmp_qspi_irq,
13011c26372eSAmit Kumar Mahapatra 			       0, pdev->name, xqspi);
1302dfe11a11SRanjit Waghmode 	if (ret != 0) {
1303dfe11a11SRanjit Waghmode 		ret = -ENXIO;
1304dfe11a11SRanjit Waghmode 		dev_err(dev, "request_irq failed\n");
1305dfe11a11SRanjit Waghmode 		goto clk_dis_all;
1306dfe11a11SRanjit Waghmode 	}
1307dfe11a11SRanjit Waghmode 
130813262fc2SJiasheng Jiang 	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
130913262fc2SJiasheng Jiang 	if (ret)
131013262fc2SJiasheng Jiang 		goto clk_dis_all;
131113262fc2SJiasheng Jiang 
1312dd9c232dSAmit Kumar Mahapatra 	ret = of_property_read_u32(np, "num-cs", &num_cs);
1313dd9c232dSAmit Kumar Mahapatra 	if (ret < 0) {
13141c26372eSAmit Kumar Mahapatra 		ctlr->num_chipselect = GQSPI_DEFAULT_NUM_CS;
1315dd9c232dSAmit Kumar Mahapatra 	} else if (num_cs > GQSPI_MAX_NUM_CS) {
1316dd9c232dSAmit Kumar Mahapatra 		ret = -EINVAL;
1317dd9c232dSAmit Kumar Mahapatra 		dev_err(&pdev->dev, "only %d chip selects are available\n",
1318dd9c232dSAmit Kumar Mahapatra 			GQSPI_MAX_NUM_CS);
1319dd9c232dSAmit Kumar Mahapatra 		goto clk_dis_all;
1320dd9c232dSAmit Kumar Mahapatra 	} else {
1321dd9c232dSAmit Kumar Mahapatra 		ctlr->num_chipselect = num_cs;
1322dd9c232dSAmit Kumar Mahapatra 	}
1323dd9c232dSAmit Kumar Mahapatra 
1324dd9c232dSAmit Kumar Mahapatra 	ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
13251c26372eSAmit Kumar Mahapatra 	ctlr->mem_ops = &zynqmp_qspi_mem_ops;
13261c26372eSAmit Kumar Mahapatra 	ctlr->setup = zynqmp_qspi_setup_op;
13271c26372eSAmit Kumar Mahapatra 	ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
13281c26372eSAmit Kumar Mahapatra 	ctlr->dev.of_node = np;
132958eaa7b2SDinghao Liu 	ctlr->auto_runtime_pm = true;
1330dfe11a11SRanjit Waghmode 
13311c26372eSAmit Kumar Mahapatra 	ret = devm_spi_register_controller(&pdev->dev, ctlr);
13321c26372eSAmit Kumar Mahapatra 	if (ret) {
13331c26372eSAmit Kumar Mahapatra 		dev_err(&pdev->dev, "spi_register_controller failed\n");
1334dfe11a11SRanjit Waghmode 		goto clk_dis_all;
13351c26372eSAmit Kumar Mahapatra 	}
1336dfe11a11SRanjit Waghmode 
133758eaa7b2SDinghao Liu 	pm_runtime_mark_last_busy(&pdev->dev);
133858eaa7b2SDinghao Liu 	pm_runtime_put_autosuspend(&pdev->dev);
133958eaa7b2SDinghao Liu 
1340dfe11a11SRanjit Waghmode 	return 0;
1341dfe11a11SRanjit Waghmode 
1342dfe11a11SRanjit Waghmode clk_dis_all:
13439e3a0003SNaga Sureshkumar Relli 	pm_runtime_disable(&pdev->dev);
1344*2c8cfd16SJinjie Ruan 	pm_runtime_dont_use_autosuspend(&pdev->dev);
13451527b076SJohan Hovold 	pm_runtime_put_noidle(&pdev->dev);
13461527b076SJohan Hovold 	pm_runtime_set_suspended(&pdev->dev);
1347dfe11a11SRanjit Waghmode 	clk_disable_unprepare(xqspi->refclk);
1348dfe11a11SRanjit Waghmode clk_dis_pclk:
1349dfe11a11SRanjit Waghmode 	clk_disable_unprepare(xqspi->pclk);
1350dfe11a11SRanjit Waghmode remove_master:
13511c26372eSAmit Kumar Mahapatra 	spi_controller_put(ctlr);
1352dfe11a11SRanjit Waghmode 
1353dfe11a11SRanjit Waghmode 	return ret;
1354dfe11a11SRanjit Waghmode }
1355dfe11a11SRanjit Waghmode 
1356dfe11a11SRanjit Waghmode /**
135791af6eb0SAmit Kumar Mahapatra  * zynqmp_qspi_remove - Remove method for the QSPI driver
1358dfe11a11SRanjit Waghmode  * @pdev:	Pointer to the platform_device structure
1359dfe11a11SRanjit Waghmode  *
1360dfe11a11SRanjit Waghmode  * This function is called if a device is physically removed from the system or
1361dfe11a11SRanjit Waghmode  * if the driver module is being unloaded. It frees all resources allocated to
1362dfe11a11SRanjit Waghmode  * the device.
1363dfe11a11SRanjit Waghmode  *
1364dfe11a11SRanjit Waghmode  * Return:	0 Always
1365dfe11a11SRanjit Waghmode  */
zynqmp_qspi_remove(struct platform_device * pdev)13663ffefa1dSUwe Kleine-König static void zynqmp_qspi_remove(struct platform_device *pdev)
1367dfe11a11SRanjit Waghmode {
13681c26372eSAmit Kumar Mahapatra 	struct zynqmp_qspi *xqspi = platform_get_drvdata(pdev);
1369dfe11a11SRanjit Waghmode 
13701527b076SJohan Hovold 	pm_runtime_get_sync(&pdev->dev);
13711527b076SJohan Hovold 
1372dfe11a11SRanjit Waghmode 	zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, 0x0);
13731527b076SJohan Hovold 
13741527b076SJohan Hovold 	pm_runtime_disable(&pdev->dev);
1375*2c8cfd16SJinjie Ruan 	pm_runtime_dont_use_autosuspend(&pdev->dev);
13761527b076SJohan Hovold 	pm_runtime_put_noidle(&pdev->dev);
13771527b076SJohan Hovold 	pm_runtime_set_suspended(&pdev->dev);
1378dfe11a11SRanjit Waghmode 	clk_disable_unprepare(xqspi->refclk);
1379dfe11a11SRanjit Waghmode 	clk_disable_unprepare(xqspi->pclk);
1380dfe11a11SRanjit Waghmode }
1381dfe11a11SRanjit Waghmode 
1382dfe11a11SRanjit Waghmode MODULE_DEVICE_TABLE(of, zynqmp_qspi_of_match);
1383dfe11a11SRanjit Waghmode 
1384dfe11a11SRanjit Waghmode static struct platform_driver zynqmp_qspi_driver = {
1385dfe11a11SRanjit Waghmode 	.probe = zynqmp_qspi_probe,
13863ffefa1dSUwe Kleine-König 	.remove_new = zynqmp_qspi_remove,
1387dfe11a11SRanjit Waghmode 	.driver = {
1388dfe11a11SRanjit Waghmode 		.name = "zynqmp-qspi",
1389dfe11a11SRanjit Waghmode 		.of_match_table = zynqmp_qspi_of_match,
1390dfe11a11SRanjit Waghmode 		.pm = &zynqmp_qspi_dev_pm_ops,
1391dfe11a11SRanjit Waghmode 	},
1392dfe11a11SRanjit Waghmode };
1393dfe11a11SRanjit Waghmode 
1394dfe11a11SRanjit Waghmode module_platform_driver(zynqmp_qspi_driver);
1395dfe11a11SRanjit Waghmode 
1396dfe11a11SRanjit Waghmode MODULE_AUTHOR("Xilinx, Inc.");
1397dfe11a11SRanjit Waghmode MODULE_DESCRIPTION("Xilinx Zynqmp QSPI driver");
1398dfe11a11SRanjit Waghmode MODULE_LICENSE("GPL");
1399