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