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