xref: /openbmc/linux/drivers/spi/spi-cadence-xspi.c (revision ee1cd5048959de496cd005c50b137212a5b62062)
1a16cc807SParshuram Thombare // SPDX-License-Identifier: GPL-2.0+
2a16cc807SParshuram Thombare // Cadence XSPI flash controller driver
3a16cc807SParshuram Thombare // Copyright (C) 2020-21 Cadence
4a16cc807SParshuram Thombare 
5a16cc807SParshuram Thombare #include <linux/completion.h>
6a16cc807SParshuram Thombare #include <linux/delay.h>
7a16cc807SParshuram Thombare #include <linux/err.h>
8a16cc807SParshuram Thombare #include <linux/errno.h>
9a16cc807SParshuram Thombare #include <linux/interrupt.h>
10a16cc807SParshuram Thombare #include <linux/io.h>
11a16cc807SParshuram Thombare #include <linux/iopoll.h>
12a16cc807SParshuram Thombare #include <linux/kernel.h>
13a16cc807SParshuram Thombare #include <linux/module.h>
14a16cc807SParshuram Thombare #include <linux/of.h>
15a16cc807SParshuram Thombare #include <linux/platform_device.h>
16a16cc807SParshuram Thombare #include <linux/pm_runtime.h>
17a16cc807SParshuram Thombare #include <linux/spi/spi.h>
18a16cc807SParshuram Thombare #include <linux/spi/spi-mem.h>
19a16cc807SParshuram Thombare #include <linux/bitfield.h>
20a16cc807SParshuram Thombare #include <linux/limits.h>
21a16cc807SParshuram Thombare #include <linux/log2.h>
22a16cc807SParshuram Thombare 
23a16cc807SParshuram Thombare #define CDNS_XSPI_MAGIC_NUM_VALUE	0x6522
24a16cc807SParshuram Thombare #define CDNS_XSPI_MAX_BANKS		8
25a16cc807SParshuram Thombare #define CDNS_XSPI_NAME			"cadence-xspi"
26a16cc807SParshuram Thombare 
27a16cc807SParshuram Thombare /*
28a16cc807SParshuram Thombare  * Note: below are additional auxiliary registers to
29a16cc807SParshuram Thombare  * configure XSPI controller pin-strap settings
30a16cc807SParshuram Thombare  */
31a16cc807SParshuram Thombare 
32a16cc807SParshuram Thombare /* PHY DQ timing register */
33a16cc807SParshuram Thombare #define CDNS_XSPI_CCP_PHY_DQ_TIMING		0x0000
34a16cc807SParshuram Thombare 
35a16cc807SParshuram Thombare /* PHY DQS timing register */
36a16cc807SParshuram Thombare #define CDNS_XSPI_CCP_PHY_DQS_TIMING		0x0004
37a16cc807SParshuram Thombare 
38a16cc807SParshuram Thombare /* PHY gate loopback control register */
39a16cc807SParshuram Thombare #define CDNS_XSPI_CCP_PHY_GATE_LPBCK_CTRL	0x0008
40a16cc807SParshuram Thombare 
41a16cc807SParshuram Thombare /* PHY DLL slave control register */
42a16cc807SParshuram Thombare #define CDNS_XSPI_CCP_PHY_DLL_SLAVE_CTRL	0x0010
43a16cc807SParshuram Thombare 
44a16cc807SParshuram Thombare /* DLL PHY control register */
45a16cc807SParshuram Thombare #define CDNS_XSPI_DLL_PHY_CTRL			0x1034
46a16cc807SParshuram Thombare 
47a16cc807SParshuram Thombare /* Command registers */
48a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_REG_0			0x0000
49a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_REG_1			0x0004
50a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_REG_2			0x0008
51a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_REG_3			0x000C
52a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_REG_4			0x0010
53a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_REG_5			0x0014
54a16cc807SParshuram Thombare 
55a16cc807SParshuram Thombare /* Command status registers */
56a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_STATUS_REG		0x0044
57a16cc807SParshuram Thombare 
58a16cc807SParshuram Thombare /* Controller status register */
59a16cc807SParshuram Thombare #define CDNS_XSPI_CTRL_STATUS_REG		0x0100
60a16cc807SParshuram Thombare #define CDNS_XSPI_INIT_COMPLETED		BIT(16)
61a16cc807SParshuram Thombare #define CDNS_XSPI_INIT_LEGACY			BIT(9)
62a16cc807SParshuram Thombare #define CDNS_XSPI_INIT_FAIL			BIT(8)
63a16cc807SParshuram Thombare #define CDNS_XSPI_CTRL_BUSY			BIT(7)
64a16cc807SParshuram Thombare 
65a16cc807SParshuram Thombare /* Controller interrupt status register */
66a16cc807SParshuram Thombare #define CDNS_XSPI_INTR_STATUS_REG		0x0110
67a16cc807SParshuram Thombare #define CDNS_XSPI_STIG_DONE			BIT(23)
68a16cc807SParshuram Thombare #define CDNS_XSPI_SDMA_ERROR			BIT(22)
69a16cc807SParshuram Thombare #define CDNS_XSPI_SDMA_TRIGGER			BIT(21)
70a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_IGNRD_EN			BIT(20)
71a16cc807SParshuram Thombare #define CDNS_XSPI_DDMA_TERR_EN			BIT(18)
72a16cc807SParshuram Thombare #define CDNS_XSPI_CDMA_TREE_EN			BIT(17)
73a16cc807SParshuram Thombare #define CDNS_XSPI_CTRL_IDLE_EN			BIT(16)
74a16cc807SParshuram Thombare 
75a16cc807SParshuram Thombare #define CDNS_XSPI_TRD_COMP_INTR_STATUS		0x0120
76a16cc807SParshuram Thombare #define CDNS_XSPI_TRD_ERR_INTR_STATUS		0x0130
77a16cc807SParshuram Thombare #define CDNS_XSPI_TRD_ERR_INTR_EN		0x0134
78a16cc807SParshuram Thombare 
79a16cc807SParshuram Thombare /* Controller interrupt enable register */
80a16cc807SParshuram Thombare #define CDNS_XSPI_INTR_ENABLE_REG		0x0114
81a16cc807SParshuram Thombare #define CDNS_XSPI_INTR_EN			BIT(31)
82a16cc807SParshuram Thombare #define CDNS_XSPI_STIG_DONE_EN			BIT(23)
83a16cc807SParshuram Thombare #define CDNS_XSPI_SDMA_ERROR_EN			BIT(22)
84a16cc807SParshuram Thombare #define CDNS_XSPI_SDMA_TRIGGER_EN		BIT(21)
85a16cc807SParshuram Thombare 
86a16cc807SParshuram Thombare #define CDNS_XSPI_INTR_MASK (CDNS_XSPI_INTR_EN | \
87a16cc807SParshuram Thombare 	CDNS_XSPI_STIG_DONE_EN  | \
88a16cc807SParshuram Thombare 	CDNS_XSPI_SDMA_ERROR_EN | \
89a16cc807SParshuram Thombare 	CDNS_XSPI_SDMA_TRIGGER_EN)
90a16cc807SParshuram Thombare 
91a16cc807SParshuram Thombare /* Controller config register */
92a16cc807SParshuram Thombare #define CDNS_XSPI_CTRL_CONFIG_REG		0x0230
93a16cc807SParshuram Thombare #define CDNS_XSPI_CTRL_WORK_MODE		GENMASK(6, 5)
94a16cc807SParshuram Thombare 
95a16cc807SParshuram Thombare #define CDNS_XSPI_WORK_MODE_DIRECT		0
96a16cc807SParshuram Thombare #define CDNS_XSPI_WORK_MODE_STIG		1
97a16cc807SParshuram Thombare #define CDNS_XSPI_WORK_MODE_ACMD		3
98a16cc807SParshuram Thombare 
99a16cc807SParshuram Thombare /* SDMA trigger transaction registers */
100a16cc807SParshuram Thombare #define CDNS_XSPI_SDMA_SIZE_REG			0x0240
101a16cc807SParshuram Thombare #define CDNS_XSPI_SDMA_TRD_INFO_REG		0x0244
102a16cc807SParshuram Thombare #define CDNS_XSPI_SDMA_DIR			BIT(8)
103a16cc807SParshuram Thombare 
104a16cc807SParshuram Thombare /* Controller features register */
105a16cc807SParshuram Thombare #define CDNS_XSPI_CTRL_FEATURES_REG		0x0F04
106a16cc807SParshuram Thombare #define CDNS_XSPI_NUM_BANKS			GENMASK(25, 24)
107a16cc807SParshuram Thombare #define CDNS_XSPI_DMA_DATA_WIDTH		BIT(21)
108a16cc807SParshuram Thombare #define CDNS_XSPI_NUM_THREADS			GENMASK(3, 0)
109a16cc807SParshuram Thombare 
110a16cc807SParshuram Thombare /* Controller version register */
111a16cc807SParshuram Thombare #define CDNS_XSPI_CTRL_VERSION_REG		0x0F00
112a16cc807SParshuram Thombare #define CDNS_XSPI_MAGIC_NUM			GENMASK(31, 16)
113a16cc807SParshuram Thombare #define CDNS_XSPI_CTRL_REV			GENMASK(7, 0)
114a16cc807SParshuram Thombare 
115a16cc807SParshuram Thombare /* STIG Profile 1.0 instruction fields (split into registers) */
116a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_INSTR_TYPE		GENMASK(6, 0)
117a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_P1_R1_ADDR0		GENMASK(31, 24)
118a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_P1_R2_ADDR1		GENMASK(7, 0)
119a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_P1_R2_ADDR2		GENMASK(15, 8)
120a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_P1_R2_ADDR3		GENMASK(23, 16)
121a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_P1_R2_ADDR4		GENMASK(31, 24)
122a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_P1_R3_ADDR5		GENMASK(7, 0)
123a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_P1_R3_CMD			GENMASK(23, 16)
124a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_P1_R3_NUM_ADDR_BYTES	GENMASK(30, 28)
125a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_P1_R4_ADDR_IOS		GENMASK(1, 0)
126a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_P1_R4_CMD_IOS		GENMASK(9, 8)
127a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_P1_R4_BANK		GENMASK(14, 12)
128a16cc807SParshuram Thombare 
129a16cc807SParshuram Thombare /* STIG data sequence instruction fields (split into registers) */
130a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_DSEQ_R2_DCNT_L		GENMASK(31, 16)
131a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_DSEQ_R3_DCNT_H		GENMASK(15, 0)
132a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_DSEQ_R3_NUM_OF_DUMMY	GENMASK(25, 20)
133a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_DSEQ_R4_BANK		GENMASK(14, 12)
134a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_DSEQ_R4_DATA_IOS		GENMASK(9, 8)
135a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_DSEQ_R4_DIR		BIT(4)
136a16cc807SParshuram Thombare 
137a16cc807SParshuram Thombare /* STIG command status fields */
138a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_STATUS_COMPLETED		BIT(15)
139a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_STATUS_FAILED		BIT(14)
140a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_STATUS_DQS_ERROR		BIT(3)
141a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_STATUS_CRC_ERROR		BIT(2)
142a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_STATUS_BUS_ERROR		BIT(1)
143a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_STATUS_INV_SEQ_ERROR	BIT(0)
144a16cc807SParshuram Thombare 
145a16cc807SParshuram Thombare #define CDNS_XSPI_STIG_DONE_FLAG		BIT(0)
146a16cc807SParshuram Thombare #define CDNS_XSPI_TRD_STATUS			0x0104
147a16cc807SParshuram Thombare 
148*d4b55b13SWitold Sadowski #define MODE_NO_OF_BYTES			GENMASK(25, 24)
149*d4b55b13SWitold Sadowski #define MODEBYTES_COUNT			1
150*d4b55b13SWitold Sadowski 
151a16cc807SParshuram Thombare /* Helper macros for filling command registers */
152a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_1(op, data_phase) ( \
153a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_INSTR_TYPE, (data_phase) ? \
154a16cc807SParshuram Thombare 		CDNS_XSPI_STIG_INSTR_TYPE_1 : CDNS_XSPI_STIG_INSTR_TYPE_0) | \
155a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_P1_R1_ADDR0, (op)->addr.val & 0xff))
156a16cc807SParshuram Thombare 
157a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_2(op) ( \
158a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_P1_R2_ADDR1, ((op)->addr.val >> 8)  & 0xFF) | \
159a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_P1_R2_ADDR2, ((op)->addr.val >> 16) & 0xFF) | \
160a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_P1_R2_ADDR3, ((op)->addr.val >> 24) & 0xFF) | \
161a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_P1_R2_ADDR4, ((op)->addr.val >> 32) & 0xFF))
162a16cc807SParshuram Thombare 
163*d4b55b13SWitold Sadowski #define CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_3(op, modebytes) ( \
164a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_P1_R3_ADDR5, ((op)->addr.val >> 40) & 0xFF) | \
165a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_P1_R3_CMD, (op)->cmd.opcode) | \
166*d4b55b13SWitold Sadowski 	FIELD_PREP(MODE_NO_OF_BYTES, modebytes) | \
167a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_P1_R3_NUM_ADDR_BYTES, (op)->addr.nbytes))
168a16cc807SParshuram Thombare 
169a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_4(op, chipsel) ( \
170a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_P1_R4_ADDR_IOS, ilog2((op)->addr.buswidth)) | \
171a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_P1_R4_CMD_IOS, ilog2((op)->cmd.buswidth)) | \
172a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_P1_R4_BANK, chipsel))
173a16cc807SParshuram Thombare 
174a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_FLD_DSEQ_CMD_1(op) \
175a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_INSTR_TYPE, CDNS_XSPI_STIG_INSTR_TYPE_DATA_SEQ)
176a16cc807SParshuram Thombare 
177a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_FLD_DSEQ_CMD_2(op) \
178a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R2_DCNT_L, (op)->data.nbytes & 0xFFFF)
179a16cc807SParshuram Thombare 
180*d4b55b13SWitold Sadowski #define CDNS_XSPI_CMD_FLD_DSEQ_CMD_3(op, dummybytes) ( \
181a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_DCNT_H, \
182a16cc807SParshuram Thombare 		((op)->data.nbytes >> 16) & 0xffff) | \
183e8bb8f19SWitold Sadowski 	FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_NUM_OF_DUMMY, \
184e8bb8f19SWitold Sadowski 		  (op)->dummy.buswidth != 0 ? \
185*d4b55b13SWitold Sadowski 		  (((dummybytes) * 8) / (op)->dummy.buswidth) : \
186e8bb8f19SWitold Sadowski 		  0))
187a16cc807SParshuram Thombare 
188a16cc807SParshuram Thombare #define CDNS_XSPI_CMD_FLD_DSEQ_CMD_4(op, chipsel) ( \
189a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R4_BANK, chipsel) | \
190a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R4_DATA_IOS, \
191a16cc807SParshuram Thombare 		ilog2((op)->data.buswidth)) | \
192a16cc807SParshuram Thombare 	FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R4_DIR, \
193a16cc807SParshuram Thombare 		((op)->data.dir == SPI_MEM_DATA_IN) ? \
194a16cc807SParshuram Thombare 		CDNS_XSPI_STIG_CMD_DIR_READ : CDNS_XSPI_STIG_CMD_DIR_WRITE))
195a16cc807SParshuram Thombare 
196a16cc807SParshuram Thombare enum cdns_xspi_stig_instr_type {
197a16cc807SParshuram Thombare 	CDNS_XSPI_STIG_INSTR_TYPE_0,
198a16cc807SParshuram Thombare 	CDNS_XSPI_STIG_INSTR_TYPE_1,
199a16cc807SParshuram Thombare 	CDNS_XSPI_STIG_INSTR_TYPE_DATA_SEQ = 127,
200a16cc807SParshuram Thombare };
201a16cc807SParshuram Thombare 
202a16cc807SParshuram Thombare enum cdns_xspi_sdma_dir {
203a16cc807SParshuram Thombare 	CDNS_XSPI_SDMA_DIR_READ,
204a16cc807SParshuram Thombare 	CDNS_XSPI_SDMA_DIR_WRITE,
205a16cc807SParshuram Thombare };
206a16cc807SParshuram Thombare 
207a16cc807SParshuram Thombare enum cdns_xspi_stig_cmd_dir {
208a16cc807SParshuram Thombare 	CDNS_XSPI_STIG_CMD_DIR_READ,
209a16cc807SParshuram Thombare 	CDNS_XSPI_STIG_CMD_DIR_WRITE,
210a16cc807SParshuram Thombare };
211a16cc807SParshuram Thombare 
212a16cc807SParshuram Thombare struct cdns_xspi_dev {
213a16cc807SParshuram Thombare 	struct platform_device *pdev;
214a16cc807SParshuram Thombare 	struct device *dev;
215a16cc807SParshuram Thombare 
216a16cc807SParshuram Thombare 	void __iomem *iobase;
217a16cc807SParshuram Thombare 	void __iomem *auxbase;
218a16cc807SParshuram Thombare 	void __iomem *sdmabase;
219a16cc807SParshuram Thombare 
220a16cc807SParshuram Thombare 	int irq;
221a16cc807SParshuram Thombare 	int cur_cs;
222a16cc807SParshuram Thombare 	unsigned int sdmasize;
223a16cc807SParshuram Thombare 
224a16cc807SParshuram Thombare 	struct completion cmd_complete;
225a16cc807SParshuram Thombare 	struct completion auto_cmd_complete;
226a16cc807SParshuram Thombare 	struct completion sdma_complete;
227a16cc807SParshuram Thombare 	bool sdma_error;
228a16cc807SParshuram Thombare 
229a16cc807SParshuram Thombare 	void *in_buffer;
230a16cc807SParshuram Thombare 	const void *out_buffer;
231a16cc807SParshuram Thombare 
232a16cc807SParshuram Thombare 	u8 hw_num_banks;
233a16cc807SParshuram Thombare };
234a16cc807SParshuram Thombare 
cdns_xspi_wait_for_controller_idle(struct cdns_xspi_dev * cdns_xspi)235a16cc807SParshuram Thombare static int cdns_xspi_wait_for_controller_idle(struct cdns_xspi_dev *cdns_xspi)
236a16cc807SParshuram Thombare {
237a16cc807SParshuram Thombare 	u32 ctrl_stat;
238a16cc807SParshuram Thombare 
239a16cc807SParshuram Thombare 	return readl_relaxed_poll_timeout(cdns_xspi->iobase +
240a16cc807SParshuram Thombare 					  CDNS_XSPI_CTRL_STATUS_REG,
241a16cc807SParshuram Thombare 					  ctrl_stat,
242a16cc807SParshuram Thombare 					  ((ctrl_stat &
243a16cc807SParshuram Thombare 					    CDNS_XSPI_CTRL_BUSY) == 0),
244a16cc807SParshuram Thombare 					  100, 1000);
245a16cc807SParshuram Thombare }
246a16cc807SParshuram Thombare 
cdns_xspi_trigger_command(struct cdns_xspi_dev * cdns_xspi,u32 cmd_regs[6])247a16cc807SParshuram Thombare static void cdns_xspi_trigger_command(struct cdns_xspi_dev *cdns_xspi,
24879bffb1eSParshuram Thombare 				      u32 cmd_regs[6])
249a16cc807SParshuram Thombare {
250a16cc807SParshuram Thombare 	writel(cmd_regs[5], cdns_xspi->iobase + CDNS_XSPI_CMD_REG_5);
251a16cc807SParshuram Thombare 	writel(cmd_regs[4], cdns_xspi->iobase + CDNS_XSPI_CMD_REG_4);
252a16cc807SParshuram Thombare 	writel(cmd_regs[3], cdns_xspi->iobase + CDNS_XSPI_CMD_REG_3);
253a16cc807SParshuram Thombare 	writel(cmd_regs[2], cdns_xspi->iobase + CDNS_XSPI_CMD_REG_2);
254a16cc807SParshuram Thombare 	writel(cmd_regs[1], cdns_xspi->iobase + CDNS_XSPI_CMD_REG_1);
255a16cc807SParshuram Thombare 	writel(cmd_regs[0], cdns_xspi->iobase + CDNS_XSPI_CMD_REG_0);
256a16cc807SParshuram Thombare }
257a16cc807SParshuram Thombare 
cdns_xspi_check_command_status(struct cdns_xspi_dev * cdns_xspi)258a16cc807SParshuram Thombare static int cdns_xspi_check_command_status(struct cdns_xspi_dev *cdns_xspi)
259a16cc807SParshuram Thombare {
260a16cc807SParshuram Thombare 	int ret = 0;
261a16cc807SParshuram Thombare 	u32 cmd_status = readl(cdns_xspi->iobase + CDNS_XSPI_CMD_STATUS_REG);
262a16cc807SParshuram Thombare 
263a16cc807SParshuram Thombare 	if (cmd_status & CDNS_XSPI_CMD_STATUS_COMPLETED) {
264a16cc807SParshuram Thombare 		if ((cmd_status & CDNS_XSPI_CMD_STATUS_FAILED) != 0) {
265a16cc807SParshuram Thombare 			if (cmd_status & CDNS_XSPI_CMD_STATUS_DQS_ERROR) {
266a16cc807SParshuram Thombare 				dev_err(cdns_xspi->dev,
267a16cc807SParshuram Thombare 					"Incorrect DQS pulses detected\n");
268a16cc807SParshuram Thombare 				ret = -EPROTO;
269a16cc807SParshuram Thombare 			}
270a16cc807SParshuram Thombare 			if (cmd_status & CDNS_XSPI_CMD_STATUS_CRC_ERROR) {
271a16cc807SParshuram Thombare 				dev_err(cdns_xspi->dev,
272a16cc807SParshuram Thombare 					"CRC error received\n");
273a16cc807SParshuram Thombare 				ret = -EPROTO;
274a16cc807SParshuram Thombare 			}
275a16cc807SParshuram Thombare 			if (cmd_status & CDNS_XSPI_CMD_STATUS_BUS_ERROR) {
276a16cc807SParshuram Thombare 				dev_err(cdns_xspi->dev,
277a16cc807SParshuram Thombare 					"Error resp on system DMA interface\n");
278a16cc807SParshuram Thombare 				ret = -EPROTO;
279a16cc807SParshuram Thombare 			}
280a16cc807SParshuram Thombare 			if (cmd_status & CDNS_XSPI_CMD_STATUS_INV_SEQ_ERROR) {
281a16cc807SParshuram Thombare 				dev_err(cdns_xspi->dev,
282a16cc807SParshuram Thombare 					"Invalid command sequence detected\n");
283a16cc807SParshuram Thombare 				ret = -EPROTO;
284a16cc807SParshuram Thombare 			}
285a16cc807SParshuram Thombare 		}
286a16cc807SParshuram Thombare 	} else {
287a16cc807SParshuram Thombare 		dev_err(cdns_xspi->dev, "Fatal err - command not completed\n");
288a16cc807SParshuram Thombare 		ret = -EPROTO;
289a16cc807SParshuram Thombare 	}
290a16cc807SParshuram Thombare 
291a16cc807SParshuram Thombare 	return ret;
292a16cc807SParshuram Thombare }
293a16cc807SParshuram Thombare 
cdns_xspi_set_interrupts(struct cdns_xspi_dev * cdns_xspi,bool enabled)294a16cc807SParshuram Thombare static void cdns_xspi_set_interrupts(struct cdns_xspi_dev *cdns_xspi,
295a16cc807SParshuram Thombare 				     bool enabled)
296a16cc807SParshuram Thombare {
297a16cc807SParshuram Thombare 	u32 intr_enable;
298a16cc807SParshuram Thombare 
299a16cc807SParshuram Thombare 	intr_enable = readl(cdns_xspi->iobase + CDNS_XSPI_INTR_ENABLE_REG);
300a16cc807SParshuram Thombare 	if (enabled)
301a16cc807SParshuram Thombare 		intr_enable |= CDNS_XSPI_INTR_MASK;
302a16cc807SParshuram Thombare 	else
303a16cc807SParshuram Thombare 		intr_enable &= ~CDNS_XSPI_INTR_MASK;
304a16cc807SParshuram Thombare 	writel(intr_enable, cdns_xspi->iobase + CDNS_XSPI_INTR_ENABLE_REG);
305a16cc807SParshuram Thombare }
306a16cc807SParshuram Thombare 
cdns_xspi_controller_init(struct cdns_xspi_dev * cdns_xspi)307a16cc807SParshuram Thombare static int cdns_xspi_controller_init(struct cdns_xspi_dev *cdns_xspi)
308a16cc807SParshuram Thombare {
309a16cc807SParshuram Thombare 	u32 ctrl_ver;
310a16cc807SParshuram Thombare 	u32 ctrl_features;
311a16cc807SParshuram Thombare 	u16 hw_magic_num;
312a16cc807SParshuram Thombare 
313a16cc807SParshuram Thombare 	ctrl_ver = readl(cdns_xspi->iobase + CDNS_XSPI_CTRL_VERSION_REG);
314a16cc807SParshuram Thombare 	hw_magic_num = FIELD_GET(CDNS_XSPI_MAGIC_NUM, ctrl_ver);
315a16cc807SParshuram Thombare 	if (hw_magic_num != CDNS_XSPI_MAGIC_NUM_VALUE) {
316a16cc807SParshuram Thombare 		dev_err(cdns_xspi->dev,
3175c258a8aSColin Ian King 			"Incorrect XSPI magic number: %x, expected: %x\n",
318a16cc807SParshuram Thombare 			hw_magic_num, CDNS_XSPI_MAGIC_NUM_VALUE);
319a16cc807SParshuram Thombare 		return -EIO;
320a16cc807SParshuram Thombare 	}
321a16cc807SParshuram Thombare 
322a16cc807SParshuram Thombare 	ctrl_features = readl(cdns_xspi->iobase + CDNS_XSPI_CTRL_FEATURES_REG);
323a16cc807SParshuram Thombare 	cdns_xspi->hw_num_banks = FIELD_GET(CDNS_XSPI_NUM_BANKS, ctrl_features);
324a16cc807SParshuram Thombare 	cdns_xspi_set_interrupts(cdns_xspi, false);
325a16cc807SParshuram Thombare 
326a16cc807SParshuram Thombare 	return 0;
327a16cc807SParshuram Thombare }
328a16cc807SParshuram Thombare 
cdns_xspi_sdma_handle(struct cdns_xspi_dev * cdns_xspi)329a16cc807SParshuram Thombare static void cdns_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi)
330a16cc807SParshuram Thombare {
331a16cc807SParshuram Thombare 	u32 sdma_size, sdma_trd_info;
332a16cc807SParshuram Thombare 	u8 sdma_dir;
333a16cc807SParshuram Thombare 
334a16cc807SParshuram Thombare 	sdma_size = readl(cdns_xspi->iobase + CDNS_XSPI_SDMA_SIZE_REG);
335a16cc807SParshuram Thombare 	sdma_trd_info = readl(cdns_xspi->iobase + CDNS_XSPI_SDMA_TRD_INFO_REG);
336a16cc807SParshuram Thombare 	sdma_dir = FIELD_GET(CDNS_XSPI_SDMA_DIR, sdma_trd_info);
337a16cc807SParshuram Thombare 
338a16cc807SParshuram Thombare 	switch (sdma_dir) {
339a16cc807SParshuram Thombare 	case CDNS_XSPI_SDMA_DIR_READ:
340a16cc807SParshuram Thombare 		ioread8_rep(cdns_xspi->sdmabase,
341a16cc807SParshuram Thombare 			    cdns_xspi->in_buffer, sdma_size);
342a16cc807SParshuram Thombare 		break;
343a16cc807SParshuram Thombare 
344a16cc807SParshuram Thombare 	case CDNS_XSPI_SDMA_DIR_WRITE:
345a16cc807SParshuram Thombare 		iowrite8_rep(cdns_xspi->sdmabase,
346a16cc807SParshuram Thombare 			     cdns_xspi->out_buffer, sdma_size);
347a16cc807SParshuram Thombare 		break;
348a16cc807SParshuram Thombare 	}
349a16cc807SParshuram Thombare }
350a16cc807SParshuram Thombare 
cdns_xspi_send_stig_command(struct cdns_xspi_dev * cdns_xspi,const struct spi_mem_op * op,bool data_phase)351a16cc807SParshuram Thombare static int cdns_xspi_send_stig_command(struct cdns_xspi_dev *cdns_xspi,
352a16cc807SParshuram Thombare 				       const struct spi_mem_op *op,
353a16cc807SParshuram Thombare 				       bool data_phase)
354a16cc807SParshuram Thombare {
35579bffb1eSParshuram Thombare 	u32 cmd_regs[6];
356a16cc807SParshuram Thombare 	u32 cmd_status;
357a16cc807SParshuram Thombare 	int ret;
358*d4b55b13SWitold Sadowski 	int dummybytes = op->dummy.nbytes;
359a16cc807SParshuram Thombare 
360a16cc807SParshuram Thombare 	ret = cdns_xspi_wait_for_controller_idle(cdns_xspi);
361a16cc807SParshuram Thombare 	if (ret < 0)
362a16cc807SParshuram Thombare 		return -EIO;
363a16cc807SParshuram Thombare 
364a16cc807SParshuram Thombare 	writel(FIELD_PREP(CDNS_XSPI_CTRL_WORK_MODE, CDNS_XSPI_WORK_MODE_STIG),
365a16cc807SParshuram Thombare 	       cdns_xspi->iobase + CDNS_XSPI_CTRL_CONFIG_REG);
366a16cc807SParshuram Thombare 
367a16cc807SParshuram Thombare 	cdns_xspi_set_interrupts(cdns_xspi, true);
368a16cc807SParshuram Thombare 	cdns_xspi->sdma_error = false;
369a16cc807SParshuram Thombare 
370a16cc807SParshuram Thombare 	memset(cmd_regs, 0, sizeof(cmd_regs));
371a16cc807SParshuram Thombare 	cmd_regs[1] = CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_1(op, data_phase);
372a16cc807SParshuram Thombare 	cmd_regs[2] = CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_2(op);
373*d4b55b13SWitold Sadowski 	if (dummybytes != 0) {
374*d4b55b13SWitold Sadowski 		cmd_regs[3] = CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_3(op, 1);
375*d4b55b13SWitold Sadowski 		dummybytes--;
376*d4b55b13SWitold Sadowski 	} else {
377*d4b55b13SWitold Sadowski 		cmd_regs[3] = CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_3(op, 0);
378*d4b55b13SWitold Sadowski 	}
379a16cc807SParshuram Thombare 	cmd_regs[4] = CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_4(op,
380a16cc807SParshuram Thombare 						       cdns_xspi->cur_cs);
381a16cc807SParshuram Thombare 
382a16cc807SParshuram Thombare 	cdns_xspi_trigger_command(cdns_xspi, cmd_regs);
383a16cc807SParshuram Thombare 
384a16cc807SParshuram Thombare 	if (data_phase) {
385a16cc807SParshuram Thombare 		cmd_regs[0] = CDNS_XSPI_STIG_DONE_FLAG;
386a16cc807SParshuram Thombare 		cmd_regs[1] = CDNS_XSPI_CMD_FLD_DSEQ_CMD_1(op);
387a16cc807SParshuram Thombare 		cmd_regs[2] = CDNS_XSPI_CMD_FLD_DSEQ_CMD_2(op);
388*d4b55b13SWitold Sadowski 		cmd_regs[3] = CDNS_XSPI_CMD_FLD_DSEQ_CMD_3(op, dummybytes);
389a16cc807SParshuram Thombare 		cmd_regs[4] = CDNS_XSPI_CMD_FLD_DSEQ_CMD_4(op,
390a16cc807SParshuram Thombare 							   cdns_xspi->cur_cs);
391a16cc807SParshuram Thombare 
392a16cc807SParshuram Thombare 		cdns_xspi->in_buffer = op->data.buf.in;
393a16cc807SParshuram Thombare 		cdns_xspi->out_buffer = op->data.buf.out;
394a16cc807SParshuram Thombare 
395a16cc807SParshuram Thombare 		cdns_xspi_trigger_command(cdns_xspi, cmd_regs);
396a16cc807SParshuram Thombare 
397a16cc807SParshuram Thombare 		wait_for_completion(&cdns_xspi->sdma_complete);
398a16cc807SParshuram Thombare 		if (cdns_xspi->sdma_error) {
399a16cc807SParshuram Thombare 			cdns_xspi_set_interrupts(cdns_xspi, false);
400a16cc807SParshuram Thombare 			return -EIO;
401a16cc807SParshuram Thombare 		}
402a16cc807SParshuram Thombare 		cdns_xspi_sdma_handle(cdns_xspi);
403a16cc807SParshuram Thombare 	}
404a16cc807SParshuram Thombare 
405a16cc807SParshuram Thombare 	wait_for_completion(&cdns_xspi->cmd_complete);
406a16cc807SParshuram Thombare 	cdns_xspi_set_interrupts(cdns_xspi, false);
407a16cc807SParshuram Thombare 
408a16cc807SParshuram Thombare 	cmd_status = cdns_xspi_check_command_status(cdns_xspi);
409a16cc807SParshuram Thombare 	if (cmd_status)
410a16cc807SParshuram Thombare 		return -EPROTO;
411a16cc807SParshuram Thombare 
412a16cc807SParshuram Thombare 	return 0;
413a16cc807SParshuram Thombare }
414a16cc807SParshuram Thombare 
cdns_xspi_mem_op(struct cdns_xspi_dev * cdns_xspi,struct spi_mem * mem,const struct spi_mem_op * op)415a16cc807SParshuram Thombare static int cdns_xspi_mem_op(struct cdns_xspi_dev *cdns_xspi,
416a16cc807SParshuram Thombare 			    struct spi_mem *mem,
417a16cc807SParshuram Thombare 			    const struct spi_mem_op *op)
418a16cc807SParshuram Thombare {
419a16cc807SParshuram Thombare 	enum spi_mem_data_dir dir = op->data.dir;
420a16cc807SParshuram Thombare 
4219e264f3fSAmit Kumar Mahapatra via Alsa-devel 	if (cdns_xspi->cur_cs != spi_get_chipselect(mem->spi, 0))
4229e264f3fSAmit Kumar Mahapatra via Alsa-devel 		cdns_xspi->cur_cs = spi_get_chipselect(mem->spi, 0);
423a16cc807SParshuram Thombare 
424a16cc807SParshuram Thombare 	return cdns_xspi_send_stig_command(cdns_xspi, op,
425a16cc807SParshuram Thombare 					   (dir != SPI_MEM_NO_DATA));
426a16cc807SParshuram Thombare }
427a16cc807SParshuram Thombare 
cdns_xspi_mem_op_execute(struct spi_mem * mem,const struct spi_mem_op * op)428a16cc807SParshuram Thombare static int cdns_xspi_mem_op_execute(struct spi_mem *mem,
429a16cc807SParshuram Thombare 				    const struct spi_mem_op *op)
430a16cc807SParshuram Thombare {
431a16cc807SParshuram Thombare 	struct cdns_xspi_dev *cdns_xspi =
432ec7cfadfSYang Yingliang 		spi_controller_get_devdata(mem->spi->controller);
433a16cc807SParshuram Thombare 	int ret = 0;
434a16cc807SParshuram Thombare 
435a16cc807SParshuram Thombare 	ret = cdns_xspi_mem_op(cdns_xspi, mem, op);
436a16cc807SParshuram Thombare 
437a16cc807SParshuram Thombare 	return ret;
438a16cc807SParshuram Thombare }
439a16cc807SParshuram Thombare 
cdns_xspi_adjust_mem_op_size(struct spi_mem * mem,struct spi_mem_op * op)440a16cc807SParshuram Thombare static int cdns_xspi_adjust_mem_op_size(struct spi_mem *mem, struct spi_mem_op *op)
441a16cc807SParshuram Thombare {
442a16cc807SParshuram Thombare 	struct cdns_xspi_dev *cdns_xspi =
443ec7cfadfSYang Yingliang 		spi_controller_get_devdata(mem->spi->controller);
444a16cc807SParshuram Thombare 
445a16cc807SParshuram Thombare 	op->data.nbytes = clamp_val(op->data.nbytes, 0, cdns_xspi->sdmasize);
446a16cc807SParshuram Thombare 
447a16cc807SParshuram Thombare 	return 0;
448a16cc807SParshuram Thombare }
449a16cc807SParshuram Thombare 
450a16cc807SParshuram Thombare static const struct spi_controller_mem_ops cadence_xspi_mem_ops = {
451a16cc807SParshuram Thombare 	.exec_op = cdns_xspi_mem_op_execute,
452a16cc807SParshuram Thombare 	.adjust_op_size = cdns_xspi_adjust_mem_op_size,
453a16cc807SParshuram Thombare };
454a16cc807SParshuram Thombare 
cdns_xspi_irq_handler(int this_irq,void * dev)455a16cc807SParshuram Thombare static irqreturn_t cdns_xspi_irq_handler(int this_irq, void *dev)
456a16cc807SParshuram Thombare {
457a16cc807SParshuram Thombare 	struct cdns_xspi_dev *cdns_xspi = dev;
458a16cc807SParshuram Thombare 	u32 irq_status;
459a16cc807SParshuram Thombare 	irqreturn_t result = IRQ_NONE;
460a16cc807SParshuram Thombare 
461a16cc807SParshuram Thombare 	irq_status = readl(cdns_xspi->iobase + CDNS_XSPI_INTR_STATUS_REG);
462a16cc807SParshuram Thombare 	writel(irq_status, cdns_xspi->iobase + CDNS_XSPI_INTR_STATUS_REG);
463a16cc807SParshuram Thombare 
464a16cc807SParshuram Thombare 	if (irq_status &
465a16cc807SParshuram Thombare 	    (CDNS_XSPI_SDMA_ERROR | CDNS_XSPI_SDMA_TRIGGER |
466a16cc807SParshuram Thombare 	     CDNS_XSPI_STIG_DONE)) {
467a16cc807SParshuram Thombare 		if (irq_status & CDNS_XSPI_SDMA_ERROR) {
468a16cc807SParshuram Thombare 			dev_err(cdns_xspi->dev,
469a16cc807SParshuram Thombare 				"Slave DMA transaction error\n");
470a16cc807SParshuram Thombare 			cdns_xspi->sdma_error = true;
471a16cc807SParshuram Thombare 			complete(&cdns_xspi->sdma_complete);
472a16cc807SParshuram Thombare 		}
473a16cc807SParshuram Thombare 
474a16cc807SParshuram Thombare 		if (irq_status & CDNS_XSPI_SDMA_TRIGGER)
475a16cc807SParshuram Thombare 			complete(&cdns_xspi->sdma_complete);
476a16cc807SParshuram Thombare 
477a16cc807SParshuram Thombare 		if (irq_status & CDNS_XSPI_STIG_DONE)
478a16cc807SParshuram Thombare 			complete(&cdns_xspi->cmd_complete);
479a16cc807SParshuram Thombare 
480a16cc807SParshuram Thombare 		result = IRQ_HANDLED;
481a16cc807SParshuram Thombare 	}
482a16cc807SParshuram Thombare 
483a16cc807SParshuram Thombare 	irq_status = readl(cdns_xspi->iobase + CDNS_XSPI_TRD_COMP_INTR_STATUS);
484a16cc807SParshuram Thombare 	if (irq_status) {
485a16cc807SParshuram Thombare 		writel(irq_status,
486a16cc807SParshuram Thombare 		       cdns_xspi->iobase + CDNS_XSPI_TRD_COMP_INTR_STATUS);
487a16cc807SParshuram Thombare 
488a16cc807SParshuram Thombare 		complete(&cdns_xspi->auto_cmd_complete);
489a16cc807SParshuram Thombare 
490a16cc807SParshuram Thombare 		result = IRQ_HANDLED;
491a16cc807SParshuram Thombare 	}
492a16cc807SParshuram Thombare 
493a16cc807SParshuram Thombare 	return result;
494a16cc807SParshuram Thombare }
495a16cc807SParshuram Thombare 
cdns_xspi_of_get_plat_data(struct platform_device * pdev)496a16cc807SParshuram Thombare static int cdns_xspi_of_get_plat_data(struct platform_device *pdev)
497a16cc807SParshuram Thombare {
498a16cc807SParshuram Thombare 	struct device_node *node_prop = pdev->dev.of_node;
499a16cc807SParshuram Thombare 	struct device_node *node_child;
500a16cc807SParshuram Thombare 	unsigned int cs;
501a16cc807SParshuram Thombare 
502a16cc807SParshuram Thombare 	for_each_child_of_node(node_prop, node_child) {
503a16cc807SParshuram Thombare 		if (!of_device_is_available(node_child))
504a16cc807SParshuram Thombare 			continue;
505a16cc807SParshuram Thombare 
506a16cc807SParshuram Thombare 		if (of_property_read_u32(node_child, "reg", &cs)) {
507a16cc807SParshuram Thombare 			dev_err(&pdev->dev, "Couldn't get memory chip select\n");
5082a4a4e89SWan Jiabing 			of_node_put(node_child);
509a16cc807SParshuram Thombare 			return -ENXIO;
510a16cc807SParshuram Thombare 		} else if (cs >= CDNS_XSPI_MAX_BANKS) {
511a16cc807SParshuram Thombare 			dev_err(&pdev->dev, "reg (cs) parameter value too large\n");
5122a4a4e89SWan Jiabing 			of_node_put(node_child);
513a16cc807SParshuram Thombare 			return -ENXIO;
514a16cc807SParshuram Thombare 		}
515a16cc807SParshuram Thombare 	}
516a16cc807SParshuram Thombare 
517a16cc807SParshuram Thombare 	return 0;
518a16cc807SParshuram Thombare }
519a16cc807SParshuram Thombare 
cdns_xspi_print_phy_config(struct cdns_xspi_dev * cdns_xspi)520a16cc807SParshuram Thombare static void cdns_xspi_print_phy_config(struct cdns_xspi_dev *cdns_xspi)
521a16cc807SParshuram Thombare {
522a16cc807SParshuram Thombare 	struct device *dev = cdns_xspi->dev;
523a16cc807SParshuram Thombare 
524a16cc807SParshuram Thombare 	dev_info(dev, "PHY configuration\n");
525a16cc807SParshuram Thombare 	dev_info(dev, "   * xspi_dll_phy_ctrl: %08x\n",
526a16cc807SParshuram Thombare 		 readl(cdns_xspi->iobase + CDNS_XSPI_DLL_PHY_CTRL));
527a16cc807SParshuram Thombare 	dev_info(dev, "   * phy_dq_timing: %08x\n",
528a16cc807SParshuram Thombare 		 readl(cdns_xspi->auxbase + CDNS_XSPI_CCP_PHY_DQ_TIMING));
529a16cc807SParshuram Thombare 	dev_info(dev, "   * phy_dqs_timing: %08x\n",
530a16cc807SParshuram Thombare 		 readl(cdns_xspi->auxbase + CDNS_XSPI_CCP_PHY_DQS_TIMING));
531a16cc807SParshuram Thombare 	dev_info(dev, "   * phy_gate_loopback_ctrl: %08x\n",
532a16cc807SParshuram Thombare 		 readl(cdns_xspi->auxbase + CDNS_XSPI_CCP_PHY_GATE_LPBCK_CTRL));
533a16cc807SParshuram Thombare 	dev_info(dev, "   * phy_dll_slave_ctrl: %08x\n",
534a16cc807SParshuram Thombare 		 readl(cdns_xspi->auxbase + CDNS_XSPI_CCP_PHY_DLL_SLAVE_CTRL));
535a16cc807SParshuram Thombare }
536a16cc807SParshuram Thombare 
cdns_xspi_probe(struct platform_device * pdev)537a16cc807SParshuram Thombare static int cdns_xspi_probe(struct platform_device *pdev)
538a16cc807SParshuram Thombare {
539a16cc807SParshuram Thombare 	struct device *dev = &pdev->dev;
540ec7cfadfSYang Yingliang 	struct spi_controller *host = NULL;
541a16cc807SParshuram Thombare 	struct cdns_xspi_dev *cdns_xspi = NULL;
542a16cc807SParshuram Thombare 	struct resource *res;
543a16cc807SParshuram Thombare 	int ret;
544a16cc807SParshuram Thombare 
545ec7cfadfSYang Yingliang 	host = devm_spi_alloc_host(dev, sizeof(*cdns_xspi));
546ec7cfadfSYang Yingliang 	if (!host)
547a16cc807SParshuram Thombare 		return -ENOMEM;
548a16cc807SParshuram Thombare 
549ec7cfadfSYang Yingliang 	host->mode_bits = SPI_3WIRE | SPI_TX_DUAL  | SPI_TX_QUAD  |
550a16cc807SParshuram Thombare 		SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_OCTAL | SPI_RX_OCTAL |
551a16cc807SParshuram Thombare 		SPI_MODE_0  | SPI_MODE_3;
552a16cc807SParshuram Thombare 
553ec7cfadfSYang Yingliang 	host->mem_ops = &cadence_xspi_mem_ops;
554ec7cfadfSYang Yingliang 	host->dev.of_node = pdev->dev.of_node;
555ec7cfadfSYang Yingliang 	host->bus_num = -1;
556a16cc807SParshuram Thombare 
557ec7cfadfSYang Yingliang 	platform_set_drvdata(pdev, host);
558a16cc807SParshuram Thombare 
559ec7cfadfSYang Yingliang 	cdns_xspi = spi_controller_get_devdata(host);
560a16cc807SParshuram Thombare 	cdns_xspi->pdev = pdev;
561a16cc807SParshuram Thombare 	cdns_xspi->dev = &pdev->dev;
562a16cc807SParshuram Thombare 	cdns_xspi->cur_cs = 0;
563a16cc807SParshuram Thombare 
564a16cc807SParshuram Thombare 	init_completion(&cdns_xspi->cmd_complete);
565a16cc807SParshuram Thombare 	init_completion(&cdns_xspi->auto_cmd_complete);
566a16cc807SParshuram Thombare 	init_completion(&cdns_xspi->sdma_complete);
567a16cc807SParshuram Thombare 
568a16cc807SParshuram Thombare 	ret = cdns_xspi_of_get_plat_data(pdev);
569a16cc807SParshuram Thombare 	if (ret)
570a16cc807SParshuram Thombare 		return -ENODEV;
571a16cc807SParshuram Thombare 
572a16cc807SParshuram Thombare 	cdns_xspi->iobase = devm_platform_ioremap_resource_byname(pdev, "io");
573a16cc807SParshuram Thombare 	if (IS_ERR(cdns_xspi->iobase)) {
574a16cc807SParshuram Thombare 		dev_err(dev, "Failed to remap controller base address\n");
575a16cc807SParshuram Thombare 		return PTR_ERR(cdns_xspi->iobase);
576a16cc807SParshuram Thombare 	}
577a16cc807SParshuram Thombare 
578a16cc807SParshuram Thombare 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sdma");
579a16cc807SParshuram Thombare 	cdns_xspi->sdmabase = devm_ioremap_resource(dev, res);
5809671847fSShang XiaoJing 	if (IS_ERR(cdns_xspi->sdmabase))
581a16cc807SParshuram Thombare 		return PTR_ERR(cdns_xspi->sdmabase);
582a16cc807SParshuram Thombare 	cdns_xspi->sdmasize = resource_size(res);
583a16cc807SParshuram Thombare 
584a16cc807SParshuram Thombare 	cdns_xspi->auxbase = devm_platform_ioremap_resource_byname(pdev, "aux");
585a16cc807SParshuram Thombare 	if (IS_ERR(cdns_xspi->auxbase)) {
586a16cc807SParshuram Thombare 		dev_err(dev, "Failed to remap AUX address\n");
587a16cc807SParshuram Thombare 		return PTR_ERR(cdns_xspi->auxbase);
588a16cc807SParshuram Thombare 	}
589a16cc807SParshuram Thombare 
590a16cc807SParshuram Thombare 	cdns_xspi->irq = platform_get_irq(pdev, 0);
591c59dbc64SYihao Han 	if (cdns_xspi->irq < 0)
592a16cc807SParshuram Thombare 		return -ENXIO;
593a16cc807SParshuram Thombare 
594a16cc807SParshuram Thombare 	ret = devm_request_irq(dev, cdns_xspi->irq, cdns_xspi_irq_handler,
595a16cc807SParshuram Thombare 			       IRQF_SHARED, pdev->name, cdns_xspi);
596a16cc807SParshuram Thombare 	if (ret) {
597a16cc807SParshuram Thombare 		dev_err(dev, "Failed to request IRQ: %d\n", cdns_xspi->irq);
598a16cc807SParshuram Thombare 		return ret;
599a16cc807SParshuram Thombare 	}
600a16cc807SParshuram Thombare 
601a16cc807SParshuram Thombare 	cdns_xspi_print_phy_config(cdns_xspi);
602a16cc807SParshuram Thombare 
603a16cc807SParshuram Thombare 	ret = cdns_xspi_controller_init(cdns_xspi);
604a16cc807SParshuram Thombare 	if (ret) {
605a16cc807SParshuram Thombare 		dev_err(dev, "Failed to initialize controller\n");
606a16cc807SParshuram Thombare 		return ret;
607a16cc807SParshuram Thombare 	}
608a16cc807SParshuram Thombare 
609ec7cfadfSYang Yingliang 	host->num_chipselect = 1 << cdns_xspi->hw_num_banks;
610a16cc807SParshuram Thombare 
611ec7cfadfSYang Yingliang 	ret = devm_spi_register_controller(dev, host);
612a16cc807SParshuram Thombare 	if (ret) {
613ec7cfadfSYang Yingliang 		dev_err(dev, "Failed to register SPI host\n");
614a16cc807SParshuram Thombare 		return ret;
615a16cc807SParshuram Thombare 	}
616a16cc807SParshuram Thombare 
617ec7cfadfSYang Yingliang 	dev_info(dev, "Successfully registered SPI host\n");
618a16cc807SParshuram Thombare 
619a16cc807SParshuram Thombare 	return 0;
620a16cc807SParshuram Thombare }
621a16cc807SParshuram Thombare 
622a16cc807SParshuram Thombare static const struct of_device_id cdns_xspi_of_match[] = {
623a16cc807SParshuram Thombare 	{
624a16cc807SParshuram Thombare 		.compatible = "cdns,xspi-nor",
625a16cc807SParshuram Thombare 	},
626a16cc807SParshuram Thombare 	{ /* end of table */}
627a16cc807SParshuram Thombare };
628a16cc807SParshuram Thombare MODULE_DEVICE_TABLE(of, cdns_xspi_of_match);
629a16cc807SParshuram Thombare 
630a16cc807SParshuram Thombare static struct platform_driver cdns_xspi_platform_driver = {
631a16cc807SParshuram Thombare 	.probe          = cdns_xspi_probe,
632a16cc807SParshuram Thombare 	.remove         = NULL,
633a16cc807SParshuram Thombare 	.driver = {
634a16cc807SParshuram Thombare 		.name = CDNS_XSPI_NAME,
635a16cc807SParshuram Thombare 		.of_match_table = cdns_xspi_of_match,
636a16cc807SParshuram Thombare 	},
637a16cc807SParshuram Thombare };
638a16cc807SParshuram Thombare 
639a16cc807SParshuram Thombare module_platform_driver(cdns_xspi_platform_driver);
640a16cc807SParshuram Thombare 
641a16cc807SParshuram Thombare MODULE_DESCRIPTION("Cadence XSPI Controller Driver");
642a16cc807SParshuram Thombare MODULE_LICENSE("GPL v2");
643a16cc807SParshuram Thombare MODULE_ALIAS("platform:" CDNS_XSPI_NAME);
644a16cc807SParshuram Thombare MODULE_AUTHOR("Konrad Kociolek <konrad@cadence.com>");
645a16cc807SParshuram Thombare MODULE_AUTHOR("Jayshri Pawar <jpawar@cadence.com>");
646a16cc807SParshuram Thombare MODULE_AUTHOR("Parshuram Thombare <pthombar@cadence.com>");
647