]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
91afd36f | 2 | |
6b57ff6f | 3 | /* |
91afd36f KS |
4 | * Freescale QuadSPI driver. |
5 | * | |
6 | * Copyright (C) 2013 Freescale Semiconductor, Inc. | |
7 | * Copyright (C) 2018 Bootlin | |
8 | * Copyright (C) 2018 exceet electronics GmbH | |
9 | * Copyright (C) 2018 Kontron Electronics GmbH | |
10 | * Copyright 2019-2020 NXP | |
11 | * | |
12 | * This driver is a ported version of Linux Freescale QSPI driver taken from | |
13 | * v5.5-rc1 tag having following information. | |
6b57ff6f | 14 | * |
91afd36f KS |
15 | * Transition to SPI MEM interface: |
16 | * Authors: | |
17 | * Boris Brezillon <[email protected]> | |
18 | * Frieder Schrempf <[email protected]> | |
19 | * Yogesh Gaur <[email protected]> | |
20 | * Suresh Gupta <[email protected]> | |
21 | * | |
22 | * Based on the original fsl-quadspi.c spi-nor driver. | |
23 | * Transition to spi-mem in spi-fsl-qspi.c | |
6b57ff6f AW |
24 | */ |
25 | ||
26 | #include <common.h> | |
f7ae49fc | 27 | #include <log.h> |
6b57ff6f | 28 | #include <asm/io.h> |
c05ed00a | 29 | #include <linux/delay.h> |
4d72caa5 SG |
30 | #include <linux/libfdt.h> |
31 | #include <linux/sizes.h> | |
32 | #include <linux/iopoll.h> | |
5bc48308 | 33 | #include <dm.h> |
91afd36f KS |
34 | #include <linux/iopoll.h> |
35 | #include <linux/sizes.h> | |
36 | #include <linux/err.h> | |
37 | #include <spi.h> | |
38 | #include <spi-mem.h> | |
6b57ff6f | 39 | |
5bc48308 HW |
40 | DECLARE_GLOBAL_DATA_PTR; |
41 | ||
91afd36f KS |
42 | /* |
43 | * The driver only uses one single LUT entry, that is updated on | |
44 | * each call of exec_op(). Index 0 is preset at boot with a basic | |
45 | * read operation, so let's use the last entry (15). | |
46 | */ | |
47 | #define SEQID_LUT 15 | |
48 | ||
49 | /* Registers used by the driver */ | |
50 | #define QUADSPI_MCR 0x00 | |
51 | #define QUADSPI_MCR_RESERVED_MASK GENMASK(19, 16) | |
52 | #define QUADSPI_MCR_MDIS_MASK BIT(14) | |
53 | #define QUADSPI_MCR_CLR_TXF_MASK BIT(11) | |
54 | #define QUADSPI_MCR_CLR_RXF_MASK BIT(10) | |
55 | #define QUADSPI_MCR_DDR_EN_MASK BIT(7) | |
56 | #define QUADSPI_MCR_END_CFG_MASK GENMASK(3, 2) | |
57 | #define QUADSPI_MCR_SWRSTHD_MASK BIT(1) | |
58 | #define QUADSPI_MCR_SWRSTSD_MASK BIT(0) | |
59 | ||
60 | #define QUADSPI_IPCR 0x08 | |
61 | #define QUADSPI_IPCR_SEQID(x) ((x) << 24) | |
62 | #define QUADSPI_FLSHCR 0x0c | |
63 | #define QUADSPI_FLSHCR_TCSS_MASK GENMASK(3, 0) | |
64 | #define QUADSPI_FLSHCR_TCSH_MASK GENMASK(11, 8) | |
65 | #define QUADSPI_FLSHCR_TDH_MASK GENMASK(17, 16) | |
66 | ||
67 | #define QUADSPI_BUF3CR 0x1c | |
68 | #define QUADSPI_BUF3CR_ALLMST_MASK BIT(31) | |
69 | #define QUADSPI_BUF3CR_ADATSZ(x) ((x) << 8) | |
70 | #define QUADSPI_BUF3CR_ADATSZ_MASK GENMASK(15, 8) | |
71 | ||
72 | #define QUADSPI_BFGENCR 0x20 | |
73 | #define QUADSPI_BFGENCR_SEQID(x) ((x) << 12) | |
74 | ||
75 | #define QUADSPI_BUF0IND 0x30 | |
76 | #define QUADSPI_BUF1IND 0x34 | |
77 | #define QUADSPI_BUF2IND 0x38 | |
78 | #define QUADSPI_SFAR 0x100 | |
79 | ||
80 | #define QUADSPI_SMPR 0x108 | |
81 | #define QUADSPI_SMPR_DDRSMP_MASK GENMASK(18, 16) | |
82 | #define QUADSPI_SMPR_FSDLY_MASK BIT(6) | |
83 | #define QUADSPI_SMPR_FSPHS_MASK BIT(5) | |
84 | #define QUADSPI_SMPR_HSENA_MASK BIT(0) | |
85 | ||
86 | #define QUADSPI_RBCT 0x110 | |
87 | #define QUADSPI_RBCT_WMRK_MASK GENMASK(4, 0) | |
88 | #define QUADSPI_RBCT_RXBRD_USEIPS BIT(8) | |
89 | ||
90 | #define QUADSPI_TBDR 0x154 | |
91 | ||
92 | #define QUADSPI_SR 0x15c | |
93 | #define QUADSPI_SR_IP_ACC_MASK BIT(1) | |
94 | #define QUADSPI_SR_AHB_ACC_MASK BIT(2) | |
95 | ||
96 | #define QUADSPI_FR 0x160 | |
97 | #define QUADSPI_FR_TFF_MASK BIT(0) | |
98 | ||
99 | #define QUADSPI_RSER 0x164 | |
100 | #define QUADSPI_RSER_TFIE BIT(0) | |
101 | ||
102 | #define QUADSPI_SPTRCLR 0x16c | |
103 | #define QUADSPI_SPTRCLR_IPPTRC BIT(8) | |
104 | #define QUADSPI_SPTRCLR_BFPTRC BIT(0) | |
105 | ||
106 | #define QUADSPI_SFA1AD 0x180 | |
107 | #define QUADSPI_SFA2AD 0x184 | |
108 | #define QUADSPI_SFB1AD 0x188 | |
109 | #define QUADSPI_SFB2AD 0x18c | |
110 | #define QUADSPI_RBDR(x) (0x200 + ((x) * 4)) | |
111 | ||
112 | #define QUADSPI_LUTKEY 0x300 | |
113 | #define QUADSPI_LUTKEY_VALUE 0x5AF05AF0 | |
114 | ||
115 | #define QUADSPI_LCKCR 0x304 | |
116 | #define QUADSPI_LCKER_LOCK BIT(0) | |
117 | #define QUADSPI_LCKER_UNLOCK BIT(1) | |
118 | ||
119 | #define QUADSPI_LUT_BASE 0x310 | |
120 | #define QUADSPI_LUT_OFFSET (SEQID_LUT * 4 * 4) | |
121 | #define QUADSPI_LUT_REG(idx) \ | |
122 | (QUADSPI_LUT_BASE + QUADSPI_LUT_OFFSET + (idx) * 4) | |
123 | ||
124 | /* Instruction set for the LUT register */ | |
125 | #define LUT_STOP 0 | |
126 | #define LUT_CMD 1 | |
127 | #define LUT_ADDR 2 | |
128 | #define LUT_DUMMY 3 | |
129 | #define LUT_MODE 4 | |
130 | #define LUT_MODE2 5 | |
131 | #define LUT_MODE4 6 | |
132 | #define LUT_FSL_READ 7 | |
133 | #define LUT_FSL_WRITE 8 | |
134 | #define LUT_JMP_ON_CS 9 | |
135 | #define LUT_ADDR_DDR 10 | |
136 | #define LUT_MODE_DDR 11 | |
137 | #define LUT_MODE2_DDR 12 | |
138 | #define LUT_MODE4_DDR 13 | |
139 | #define LUT_FSL_READ_DDR 14 | |
140 | #define LUT_FSL_WRITE_DDR 15 | |
141 | #define LUT_DATA_LEARN 16 | |
142 | ||
143 | /* | |
144 | * The PAD definitions for LUT register. | |
145 | * | |
146 | * The pad stands for the number of IO lines [0:3]. | |
147 | * For example, the quad read needs four IO lines, | |
148 | * so you should use LUT_PAD(4). | |
149 | */ | |
150 | #define LUT_PAD(x) (fls(x) - 1) | |
151 | ||
152 | /* | |
153 | * Macro for constructing the LUT entries with the following | |
154 | * register layout: | |
155 | * | |
156 | * --------------------------------------------------- | |
157 | * | INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 | | |
158 | * --------------------------------------------------- | |
159 | */ | |
160 | #define LUT_DEF(idx, ins, pad, opr) \ | |
161 | ((((ins) << 10) | ((pad) << 8) | (opr)) << (((idx) % 2) * 16)) | |
162 | ||
163 | /* Controller needs driver to swap endianness */ | |
ce7575a8 YL |
164 | #define QUADSPI_QUIRK_SWAP_ENDIAN BIT(0) |
165 | ||
91afd36f KS |
166 | /* Controller needs 4x internal clock */ |
167 | #define QUADSPI_QUIRK_4X_INT_CLK BIT(1) | |
ce7575a8 | 168 | |
91afd36f KS |
169 | /* |
170 | * TKT253890, the controller needs the driver to fill the txfifo with | |
171 | * 16 bytes at least to trigger a data transfer, even though the extra | |
172 | * data won't be transferred. | |
173 | */ | |
174 | #define QUADSPI_QUIRK_TKT253890 BIT(2) | |
ce7575a8 | 175 | |
91afd36f KS |
176 | /* TKT245618, the controller cannot wake up from wait mode */ |
177 | #define QUADSPI_QUIRK_TKT245618 BIT(3) | |
178 | ||
179 | /* | |
180 | * Controller adds QSPI_AMBA_BASE (base address of the mapped memory) | |
181 | * internally. No need to add it when setting SFXXAD and SFAR registers | |
5bc48308 | 182 | */ |
91afd36f | 183 | #define QUADSPI_QUIRK_BASE_INTERNAL BIT(4) |
5bc48308 | 184 | |
91afd36f KS |
185 | /* |
186 | * Controller uses TDH bits in register QUADSPI_FLSHCR. | |
187 | * They need to be set in accordance with the DDR/SDR mode. | |
5bc48308 | 188 | */ |
91afd36f KS |
189 | #define QUADSPI_QUIRK_USE_TDH_SETTING BIT(5) |
190 | ||
191 | struct fsl_qspi_devtype_data { | |
192 | unsigned int rxfifo; | |
193 | unsigned int txfifo; | |
194 | unsigned int ahb_buf_size; | |
195 | unsigned int quirks; | |
196 | bool little_endian; | |
6b57ff6f AW |
197 | }; |
198 | ||
ce7575a8 | 199 | static const struct fsl_qspi_devtype_data vybrid_data = { |
91afd36f KS |
200 | .rxfifo = SZ_128, |
201 | .txfifo = SZ_64, | |
202 | .ahb_buf_size = SZ_1K, | |
203 | .quirks = QUADSPI_QUIRK_SWAP_ENDIAN, | |
204 | .little_endian = true, | |
ce7575a8 YL |
205 | }; |
206 | ||
207 | static const struct fsl_qspi_devtype_data imx6sx_data = { | |
91afd36f KS |
208 | .rxfifo = SZ_128, |
209 | .txfifo = SZ_512, | |
210 | .ahb_buf_size = SZ_1K, | |
211 | .quirks = QUADSPI_QUIRK_4X_INT_CLK | QUADSPI_QUIRK_TKT245618, | |
212 | .little_endian = true, | |
213 | }; | |
214 | ||
215 | static const struct fsl_qspi_devtype_data imx7d_data = { | |
216 | .rxfifo = SZ_128, | |
217 | .txfifo = SZ_512, | |
218 | .ahb_buf_size = SZ_1K, | |
219 | .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK | | |
220 | QUADSPI_QUIRK_USE_TDH_SETTING, | |
221 | .little_endian = true, | |
ce7575a8 YL |
222 | }; |
223 | ||
91afd36f KS |
224 | static const struct fsl_qspi_devtype_data imx6ul_data = { |
225 | .rxfifo = SZ_128, | |
226 | .txfifo = SZ_512, | |
227 | .ahb_buf_size = SZ_1K, | |
228 | .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK | | |
229 | QUADSPI_QUIRK_USE_TDH_SETTING, | |
230 | .little_endian = true, | |
ce7575a8 | 231 | }; |
5bc48308 | 232 | |
91afd36f KS |
233 | static const struct fsl_qspi_devtype_data ls1021a_data = { |
234 | .rxfifo = SZ_128, | |
235 | .txfifo = SZ_64, | |
236 | .ahb_buf_size = SZ_1K, | |
237 | .quirks = 0, | |
238 | .little_endian = false, | |
9699fb4d YL |
239 | }; |
240 | ||
91afd36f KS |
241 | static const struct fsl_qspi_devtype_data ls1088a_data = { |
242 | .rxfifo = SZ_128, | |
243 | .txfifo = SZ_128, | |
244 | .ahb_buf_size = SZ_1K, | |
245 | .quirks = QUADSPI_QUIRK_TKT253890, | |
246 | .little_endian = true, | |
247 | }; | |
248 | ||
249 | static const struct fsl_qspi_devtype_data ls2080a_data = { | |
250 | .rxfifo = SZ_128, | |
251 | .txfifo = SZ_64, | |
252 | .ahb_buf_size = SZ_1K, | |
253 | .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_BASE_INTERNAL, | |
254 | .little_endian = true, | |
255 | }; | |
256 | ||
257 | struct fsl_qspi { | |
258 | struct udevice *dev; | |
259 | void __iomem *iobase; | |
260 | void __iomem *ahb_addr; | |
261 | u32 memmap_phy; | |
262 | const struct fsl_qspi_devtype_data *devtype_data; | |
263 | int selected; | |
264 | }; | |
265 | ||
266 | static inline int needs_swap_endian(struct fsl_qspi *q) | |
5bc48308 | 267 | { |
91afd36f | 268 | return q->devtype_data->quirks & QUADSPI_QUIRK_SWAP_ENDIAN; |
5bc48308 HW |
269 | } |
270 | ||
91afd36f | 271 | static inline int needs_4x_clock(struct fsl_qspi *q) |
5bc48308 | 272 | { |
91afd36f | 273 | return q->devtype_data->quirks & QUADSPI_QUIRK_4X_INT_CLK; |
5bc48308 | 274 | } |
6b57ff6f | 275 | |
91afd36f | 276 | static inline int needs_fill_txfifo(struct fsl_qspi *q) |
1f553564 | 277 | { |
91afd36f | 278 | return q->devtype_data->quirks & QUADSPI_QUIRK_TKT253890; |
1f553564 RS |
279 | } |
280 | ||
91afd36f | 281 | static inline int needs_wakeup_wait_mode(struct fsl_qspi *q) |
6b57ff6f | 282 | { |
91afd36f | 283 | return q->devtype_data->quirks & QUADSPI_QUIRK_TKT245618; |
6b57ff6f AW |
284 | } |
285 | ||
91afd36f | 286 | static inline int needs_amba_base_offset(struct fsl_qspi *q) |
6b57ff6f | 287 | { |
91afd36f KS |
288 | return !(q->devtype_data->quirks & QUADSPI_QUIRK_BASE_INTERNAL); |
289 | } | |
febffe8d | 290 | |
91afd36f KS |
291 | static inline int needs_tdh_setting(struct fsl_qspi *q) |
292 | { | |
293 | return q->devtype_data->quirks & QUADSPI_QUIRK_USE_TDH_SETTING; | |
6b57ff6f AW |
294 | } |
295 | ||
5f7f70c1 | 296 | /* |
91afd36f KS |
297 | * An IC bug makes it necessary to rearrange the 32-bit data. |
298 | * Later chips, such as IMX6SLX, have fixed this bug. | |
5f7f70c1 | 299 | */ |
91afd36f | 300 | static inline u32 fsl_qspi_endian_xchg(struct fsl_qspi *q, u32 a) |
5f7f70c1 | 301 | { |
91afd36f | 302 | return needs_swap_endian(q) ? __swab32(a) : a; |
5f7f70c1 PF |
303 | } |
304 | ||
91afd36f KS |
305 | /* |
306 | * R/W functions for big- or little-endian registers: | |
307 | * The QSPI controller's endianness is independent of | |
308 | * the CPU core's endianness. So far, although the CPU | |
309 | * core is little-endian the QSPI controller can use | |
310 | * big-endian or little-endian. | |
311 | */ | |
312 | static void qspi_writel(struct fsl_qspi *q, u32 val, void __iomem *addr) | |
5f7f70c1 | 313 | { |
91afd36f KS |
314 | if (q->devtype_data->little_endian) |
315 | out_le32(addr, val); | |
316 | else | |
317 | out_be32(addr, val); | |
318 | } | |
5f7f70c1 | 319 | |
91afd36f KS |
320 | static u32 qspi_readl(struct fsl_qspi *q, void __iomem *addr) |
321 | { | |
322 | if (q->devtype_data->little_endian) | |
323 | return in_le32(addr); | |
5f7f70c1 | 324 | |
91afd36f | 325 | return in_be32(addr); |
5f7f70c1 PF |
326 | } |
327 | ||
91afd36f | 328 | static int fsl_qspi_check_buswidth(struct fsl_qspi *q, u8 width) |
5f7f70c1 | 329 | { |
91afd36f KS |
330 | switch (width) { |
331 | case 1: | |
332 | case 2: | |
333 | case 4: | |
334 | return 0; | |
335 | } | |
5f7f70c1 | 336 | |
91afd36f | 337 | return -ENOTSUPP; |
5f7f70c1 PF |
338 | } |
339 | ||
91afd36f KS |
340 | static bool fsl_qspi_supports_op(struct spi_slave *slave, |
341 | const struct spi_mem_op *op) | |
5f7f70c1 | 342 | { |
91afd36f KS |
343 | struct fsl_qspi *q = dev_get_priv(slave->dev->parent); |
344 | int ret; | |
345 | ||
346 | ret = fsl_qspi_check_buswidth(q, op->cmd.buswidth); | |
347 | ||
348 | if (op->addr.nbytes) | |
349 | ret |= fsl_qspi_check_buswidth(q, op->addr.buswidth); | |
350 | ||
351 | if (op->dummy.nbytes) | |
352 | ret |= fsl_qspi_check_buswidth(q, op->dummy.buswidth); | |
5bc48308 | 353 | |
91afd36f KS |
354 | if (op->data.nbytes) |
355 | ret |= fsl_qspi_check_buswidth(q, op->data.buswidth); | |
5f7f70c1 | 356 | |
91afd36f KS |
357 | if (ret) |
358 | return false; | |
5f7f70c1 PF |
359 | |
360 | /* | |
91afd36f KS |
361 | * The number of instructions needed for the op, needs |
362 | * to fit into a single LUT entry. | |
5f7f70c1 | 363 | */ |
91afd36f KS |
364 | if (op->addr.nbytes + |
365 | (op->dummy.nbytes ? 1 : 0) + | |
366 | (op->data.nbytes ? 1 : 0) > 6) | |
367 | return false; | |
368 | ||
369 | /* Max 64 dummy clock cycles supported */ | |
370 | if (op->dummy.nbytes && | |
371 | (op->dummy.nbytes * 8 / op->dummy.buswidth > 64)) | |
372 | return false; | |
373 | ||
374 | /* Max data length, check controller limits and alignment */ | |
375 | if (op->data.dir == SPI_MEM_DATA_IN && | |
376 | (op->data.nbytes > q->devtype_data->ahb_buf_size || | |
377 | (op->data.nbytes > q->devtype_data->rxfifo - 4 && | |
378 | !IS_ALIGNED(op->data.nbytes, 8)))) | |
379 | return false; | |
380 | ||
381 | if (op->data.dir == SPI_MEM_DATA_OUT && | |
382 | op->data.nbytes > q->devtype_data->txfifo) | |
383 | return false; | |
384 | ||
385 | return true; | |
5f7f70c1 | 386 | } |
5f7f70c1 | 387 | |
91afd36f KS |
388 | static void fsl_qspi_prepare_lut(struct fsl_qspi *q, |
389 | const struct spi_mem_op *op) | |
a2358783 | 390 | { |
91afd36f KS |
391 | void __iomem *base = q->iobase; |
392 | u32 lutval[4] = {}; | |
393 | int lutidx = 1, i; | |
a2358783 | 394 | |
91afd36f KS |
395 | lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth), |
396 | op->cmd.opcode); | |
a2358783 | 397 | |
91afd36f KS |
398 | /* |
399 | * For some unknown reason, using LUT_ADDR doesn't work in some | |
400 | * cases (at least with only one byte long addresses), so | |
401 | * let's use LUT_MODE to write the address bytes one by one | |
402 | */ | |
403 | for (i = 0; i < op->addr.nbytes; i++) { | |
404 | u8 addrbyte = op->addr.val >> (8 * (op->addr.nbytes - i - 1)); | |
a2358783 | 405 | |
91afd36f KS |
406 | lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_MODE, |
407 | LUT_PAD(op->addr.buswidth), | |
408 | addrbyte); | |
409 | lutidx++; | |
a2358783 PF |
410 | } |
411 | ||
91afd36f KS |
412 | if (op->dummy.nbytes) { |
413 | lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_DUMMY, | |
414 | LUT_PAD(op->dummy.buswidth), | |
415 | op->dummy.nbytes * 8 / | |
416 | op->dummy.buswidth); | |
417 | lutidx++; | |
6b57ff6f AW |
418 | } |
419 | ||
91afd36f KS |
420 | if (op->data.nbytes) { |
421 | lutval[lutidx / 2] |= LUT_DEF(lutidx, | |
422 | op->data.dir == SPI_MEM_DATA_IN ? | |
423 | LUT_FSL_READ : LUT_FSL_WRITE, | |
424 | LUT_PAD(op->data.buswidth), | |
425 | 0); | |
426 | lutidx++; | |
6b57ff6f AW |
427 | } |
428 | ||
91afd36f | 429 | lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_STOP, 0, 0); |
6b57ff6f | 430 | |
91afd36f KS |
431 | /* unlock LUT */ |
432 | qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); | |
433 | qspi_writel(q, QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR); | |
434 | ||
435 | dev_dbg(q->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x]\n", | |
436 | op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3]); | |
6b57ff6f | 437 | |
91afd36f KS |
438 | /* fill LUT */ |
439 | for (i = 0; i < ARRAY_SIZE(lutval); i++) | |
440 | qspi_writel(q, lutval[i], base + QUADSPI_LUT_REG(i)); | |
a2358783 | 441 | |
91afd36f KS |
442 | /* lock LUT */ |
443 | qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); | |
444 | qspi_writel(q, QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR); | |
445 | } | |
a2358783 | 446 | |
91afd36f KS |
447 | /* |
448 | * If we have changed the content of the flash by writing or erasing, or if we | |
449 | * read from flash with a different offset into the page buffer, we need to | |
450 | * invalidate the AHB buffer. If we do not do so, we may read out the wrong | |
451 | * data. The spec tells us reset the AHB domain and Serial Flash domain at | |
452 | * the same time. | |
453 | */ | |
454 | static void fsl_qspi_invalidate(struct fsl_qspi *q) | |
455 | { | |
456 | u32 reg; | |
6b57ff6f | 457 | |
91afd36f KS |
458 | reg = qspi_readl(q, q->iobase + QUADSPI_MCR); |
459 | reg |= QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK; | |
460 | qspi_writel(q, reg, q->iobase + QUADSPI_MCR); | |
6b57ff6f | 461 | |
10509987 | 462 | /* |
91afd36f KS |
463 | * The minimum delay : 1 AHB + 2 SFCK clocks. |
464 | * Delay 1 us is enough. | |
10509987 | 465 | */ |
91afd36f | 466 | udelay(1); |
6b57ff6f | 467 | |
91afd36f KS |
468 | reg &= ~(QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK); |
469 | qspi_writel(q, reg, q->iobase + QUADSPI_MCR); | |
6b57ff6f AW |
470 | } |
471 | ||
91afd36f | 472 | static void fsl_qspi_select_mem(struct fsl_qspi *q, struct spi_slave *slave) |
6b57ff6f | 473 | { |
91afd36f KS |
474 | struct dm_spi_slave_platdata *plat = |
475 | dev_get_parent_platdata(slave->dev); | |
476 | ||
477 | if (q->selected == plat->cs) | |
478 | return; | |
6b57ff6f | 479 | |
91afd36f KS |
480 | q->selected = plat->cs; |
481 | fsl_qspi_invalidate(q); | |
6b57ff6f AW |
482 | } |
483 | ||
91afd36f | 484 | static void fsl_qspi_read_ahb(struct fsl_qspi *q, const struct spi_mem_op *op) |
6b57ff6f | 485 | { |
91afd36f KS |
486 | memcpy_fromio(op->data.buf.in, |
487 | q->ahb_addr + q->selected * q->devtype_data->ahb_buf_size, | |
488 | op->data.nbytes); | |
6b57ff6f AW |
489 | } |
490 | ||
91afd36f KS |
491 | static void fsl_qspi_fill_txfifo(struct fsl_qspi *q, |
492 | const struct spi_mem_op *op) | |
6b57ff6f | 493 | { |
91afd36f KS |
494 | void __iomem *base = q->iobase; |
495 | int i; | |
496 | u32 val; | |
6b57ff6f | 497 | |
91afd36f KS |
498 | for (i = 0; i < ALIGN_DOWN(op->data.nbytes, 4); i += 4) { |
499 | memcpy(&val, op->data.buf.out + i, 4); | |
500 | val = fsl_qspi_endian_xchg(q, val); | |
501 | qspi_writel(q, val, base + QUADSPI_TBDR); | |
6b57ff6f AW |
502 | } |
503 | ||
91afd36f KS |
504 | if (i < op->data.nbytes) { |
505 | memcpy(&val, op->data.buf.out + i, op->data.nbytes - i); | |
506 | val = fsl_qspi_endian_xchg(q, val); | |
507 | qspi_writel(q, val, base + QUADSPI_TBDR); | |
508 | } | |
5bc48308 | 509 | |
91afd36f KS |
510 | if (needs_fill_txfifo(q)) { |
511 | for (i = op->data.nbytes; i < 16; i += 4) | |
512 | qspi_writel(q, 0, base + QUADSPI_TBDR); | |
513 | } | |
5bc48308 HW |
514 | } |
515 | ||
91afd36f KS |
516 | static void fsl_qspi_read_rxfifo(struct fsl_qspi *q, |
517 | const struct spi_mem_op *op) | |
5bc48308 | 518 | { |
91afd36f KS |
519 | void __iomem *base = q->iobase; |
520 | int i; | |
521 | u8 *buf = op->data.buf.in; | |
522 | u32 val; | |
5bc48308 | 523 | |
91afd36f KS |
524 | for (i = 0; i < ALIGN_DOWN(op->data.nbytes, 4); i += 4) { |
525 | val = qspi_readl(q, base + QUADSPI_RBDR(i / 4)); | |
526 | val = fsl_qspi_endian_xchg(q, val); | |
527 | memcpy(buf + i, &val, 4); | |
528 | } | |
529 | ||
530 | if (i < op->data.nbytes) { | |
531 | val = qspi_readl(q, base + QUADSPI_RBDR(i / 4)); | |
532 | val = fsl_qspi_endian_xchg(q, val); | |
533 | memcpy(buf + i, &val, op->data.nbytes - i); | |
534 | } | |
5bc48308 HW |
535 | } |
536 | ||
91afd36f KS |
537 | static int fsl_qspi_readl_poll_tout(struct fsl_qspi *q, void __iomem *base, |
538 | u32 mask, u32 delay_us, u32 timeout_us) | |
5bc48308 | 539 | { |
91afd36f | 540 | u32 reg; |
5bc48308 | 541 | |
91afd36f KS |
542 | if (!q->devtype_data->little_endian) |
543 | mask = (u32)cpu_to_be32(mask); | |
544 | ||
545 | return readl_poll_timeout(base, reg, !(reg & mask), timeout_us); | |
5bc48308 | 546 | } |
5bc48308 | 547 | |
91afd36f | 548 | static int fsl_qspi_do_op(struct fsl_qspi *q, const struct spi_mem_op *op) |
5bc48308 | 549 | { |
91afd36f KS |
550 | void __iomem *base = q->iobase; |
551 | int err = 0; | |
5bc48308 | 552 | |
91afd36f KS |
553 | /* |
554 | * Always start the sequence at the same index since we update | |
555 | * the LUT at each exec_op() call. And also specify the DATA | |
556 | * length, since it's has not been specified in the LUT. | |
557 | */ | |
558 | qspi_writel(q, op->data.nbytes | QUADSPI_IPCR_SEQID(SEQID_LUT), | |
559 | base + QUADSPI_IPCR); | |
5bc48308 | 560 | |
91afd36f KS |
561 | /* wait for the controller being ready */ |
562 | err = fsl_qspi_readl_poll_tout(q, base + QUADSPI_SR, | |
563 | (QUADSPI_SR_IP_ACC_MASK | | |
564 | QUADSPI_SR_AHB_ACC_MASK), | |
565 | 10, 1000); | |
566 | ||
567 | if (!err && op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN) | |
568 | fsl_qspi_read_rxfifo(q, op); | |
569 | ||
570 | return err; | |
5bc48308 HW |
571 | } |
572 | ||
91afd36f KS |
573 | static int fsl_qspi_exec_op(struct spi_slave *slave, |
574 | const struct spi_mem_op *op) | |
5bc48308 | 575 | { |
91afd36f KS |
576 | struct fsl_qspi *q = dev_get_priv(slave->dev->parent); |
577 | void __iomem *base = q->iobase; | |
578 | u32 addr_offset = 0; | |
579 | int err = 0; | |
5bc48308 | 580 | |
91afd36f KS |
581 | /* wait for the controller being ready */ |
582 | fsl_qspi_readl_poll_tout(q, base + QUADSPI_SR, (QUADSPI_SR_IP_ACC_MASK | | |
583 | QUADSPI_SR_AHB_ACC_MASK), 10, 1000); | |
5bc48308 | 584 | |
91afd36f | 585 | fsl_qspi_select_mem(q, slave); |
5bc48308 | 586 | |
91afd36f KS |
587 | if (needs_amba_base_offset(q)) |
588 | addr_offset = q->memmap_phy; | |
589 | ||
590 | qspi_writel(q, | |
591 | q->selected * q->devtype_data->ahb_buf_size + addr_offset, | |
592 | base + QUADSPI_SFAR); | |
593 | ||
594 | qspi_writel(q, qspi_readl(q, base + QUADSPI_MCR) | | |
595 | QUADSPI_MCR_CLR_RXF_MASK | QUADSPI_MCR_CLR_TXF_MASK, | |
596 | base + QUADSPI_MCR); | |
597 | ||
598 | qspi_writel(q, QUADSPI_SPTRCLR_BFPTRC | QUADSPI_SPTRCLR_IPPTRC, | |
599 | base + QUADSPI_SPTRCLR); | |
600 | ||
601 | fsl_qspi_prepare_lut(q, op); | |
5bc48308 | 602 | |
bf9bffa9 | 603 | /* |
91afd36f KS |
604 | * If we have large chunks of data, we read them through the AHB bus |
605 | * by accessing the mapped memory. In all other cases we use | |
606 | * IP commands to access the flash. | |
bf9bffa9 | 607 | */ |
91afd36f KS |
608 | if (op->data.nbytes > (q->devtype_data->rxfifo - 4) && |
609 | op->data.dir == SPI_MEM_DATA_IN) { | |
610 | fsl_qspi_read_ahb(q, op); | |
611 | } else { | |
612 | qspi_writel(q, QUADSPI_RBCT_WMRK_MASK | | |
613 | QUADSPI_RBCT_RXBRD_USEIPS, base + QUADSPI_RBCT); | |
614 | ||
615 | if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) | |
616 | fsl_qspi_fill_txfifo(q, op); | |
617 | ||
618 | err = fsl_qspi_do_op(q, op); | |
ce7575a8 YL |
619 | } |
620 | ||
91afd36f KS |
621 | /* Invalidate the data in the AHB buffer. */ |
622 | fsl_qspi_invalidate(q); | |
ce7575a8 | 623 | |
91afd36f KS |
624 | return err; |
625 | } | |
1c631da4 | 626 | |
91afd36f KS |
627 | static int fsl_qspi_adjust_op_size(struct spi_slave *slave, |
628 | struct spi_mem_op *op) | |
629 | { | |
630 | struct fsl_qspi *q = dev_get_priv(slave->dev->parent); | |
631 | ||
632 | if (op->data.dir == SPI_MEM_DATA_OUT) { | |
633 | if (op->data.nbytes > q->devtype_data->txfifo) | |
634 | op->data.nbytes = q->devtype_data->txfifo; | |
635 | } else { | |
636 | if (op->data.nbytes > q->devtype_data->ahb_buf_size) | |
637 | op->data.nbytes = q->devtype_data->ahb_buf_size; | |
638 | else if (op->data.nbytes > (q->devtype_data->rxfifo - 4)) | |
639 | op->data.nbytes = ALIGN_DOWN(op->data.nbytes, 8); | |
1c631da4 SG |
640 | } |
641 | ||
91afd36f KS |
642 | return 0; |
643 | } | |
644 | ||
645 | static int fsl_qspi_default_setup(struct fsl_qspi *q) | |
646 | { | |
647 | void __iomem *base = q->iobase; | |
648 | u32 reg, addr_offset = 0; | |
649 | ||
650 | /* Reset the module */ | |
651 | qspi_writel(q, QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK, | |
652 | base + QUADSPI_MCR); | |
653 | udelay(1); | |
5bc48308 | 654 | |
91afd36f KS |
655 | /* Disable the module */ |
656 | qspi_writel(q, QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK, | |
657 | base + QUADSPI_MCR); | |
5bc48308 | 658 | |
4e147418 | 659 | /* |
91afd36f KS |
660 | * Previous boot stages (BootROM, bootloader) might have used DDR |
661 | * mode and did not clear the TDH bits. As we currently use SDR mode | |
662 | * only, clear the TDH bits if necessary. | |
4e147418 | 663 | */ |
91afd36f KS |
664 | if (needs_tdh_setting(q)) |
665 | qspi_writel(q, qspi_readl(q, base + QUADSPI_FLSHCR) & | |
666 | ~QUADSPI_FLSHCR_TDH_MASK, | |
667 | base + QUADSPI_FLSHCR); | |
668 | ||
669 | reg = qspi_readl(q, base + QUADSPI_SMPR); | |
670 | qspi_writel(q, reg & ~(QUADSPI_SMPR_FSDLY_MASK | |
671 | | QUADSPI_SMPR_FSPHS_MASK | |
672 | | QUADSPI_SMPR_HSENA_MASK | |
673 | | QUADSPI_SMPR_DDRSMP_MASK), base + QUADSPI_SMPR); | |
674 | ||
675 | /* We only use the buffer3 for AHB read */ | |
676 | qspi_writel(q, 0, base + QUADSPI_BUF0IND); | |
677 | qspi_writel(q, 0, base + QUADSPI_BUF1IND); | |
678 | qspi_writel(q, 0, base + QUADSPI_BUF2IND); | |
679 | ||
680 | qspi_writel(q, QUADSPI_BFGENCR_SEQID(SEQID_LUT), | |
681 | q->iobase + QUADSPI_BFGENCR); | |
682 | qspi_writel(q, QUADSPI_RBCT_WMRK_MASK, base + QUADSPI_RBCT); | |
683 | qspi_writel(q, QUADSPI_BUF3CR_ALLMST_MASK | | |
684 | QUADSPI_BUF3CR_ADATSZ(q->devtype_data->ahb_buf_size / 8), | |
685 | base + QUADSPI_BUF3CR); | |
686 | ||
687 | if (needs_amba_base_offset(q)) | |
688 | addr_offset = q->memmap_phy; | |
4e147418 | 689 | |
5bc48308 | 690 | /* |
91afd36f KS |
691 | * In HW there can be a maximum of four chips on two buses with |
692 | * two chip selects on each bus. We use four chip selects in SW | |
693 | * to differentiate between the four chips. | |
694 | * We use ahb_buf_size for each chip and set SFA1AD, SFA2AD, SFB1AD, | |
695 | * SFB2AD accordingly. | |
5bc48308 | 696 | */ |
91afd36f KS |
697 | qspi_writel(q, q->devtype_data->ahb_buf_size + addr_offset, |
698 | base + QUADSPI_SFA1AD); | |
699 | qspi_writel(q, q->devtype_data->ahb_buf_size * 2 + addr_offset, | |
700 | base + QUADSPI_SFA2AD); | |
701 | qspi_writel(q, q->devtype_data->ahb_buf_size * 3 + addr_offset, | |
702 | base + QUADSPI_SFB1AD); | |
703 | qspi_writel(q, q->devtype_data->ahb_buf_size * 4 + addr_offset, | |
704 | base + QUADSPI_SFB2AD); | |
705 | ||
706 | q->selected = -1; | |
707 | ||
708 | /* Enable the module */ | |
709 | qspi_writel(q, QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK, | |
710 | base + QUADSPI_MCR); | |
5bc48308 HW |
711 | return 0; |
712 | } | |
713 | ||
91afd36f KS |
714 | static const struct spi_controller_mem_ops fsl_qspi_mem_ops = { |
715 | .adjust_op_size = fsl_qspi_adjust_op_size, | |
716 | .supports_op = fsl_qspi_supports_op, | |
717 | .exec_op = fsl_qspi_exec_op, | |
718 | }; | |
719 | ||
720 | static int fsl_qspi_probe(struct udevice *bus) | |
5bc48308 | 721 | { |
91afd36f KS |
722 | struct dm_spi_bus *dm_bus = bus->uclass_priv; |
723 | struct fsl_qspi *q = dev_get_priv(bus); | |
5bc48308 | 724 | const void *blob = gd->fdt_blob; |
e160f7d4 | 725 | int node = dev_of_offset(bus); |
91afd36f KS |
726 | struct fdt_resource res; |
727 | int ret; | |
5bc48308 | 728 | |
91afd36f KS |
729 | q->dev = bus; |
730 | q->devtype_data = (struct fsl_qspi_devtype_data *) | |
731 | dev_get_driver_data(bus); | |
5bc48308 | 732 | |
91afd36f KS |
733 | /* find the resources */ |
734 | ret = fdt_get_named_resource(blob, node, "reg", "reg-names", "QuadSPI", | |
735 | &res); | |
bf9bffa9 | 736 | if (ret) { |
91afd36f | 737 | dev_err(bus, "Can't get regs base addresses(ret = %d)!\n", ret); |
bf9bffa9 YY |
738 | return -ENOMEM; |
739 | } | |
91afd36f KS |
740 | |
741 | q->iobase = map_physmem(res.start, res.end - res.start, MAP_NOCACHE); | |
742 | ||
bf9bffa9 | 743 | ret = fdt_get_named_resource(blob, node, "reg", "reg-names", |
91afd36f | 744 | "QuadSPI-memory", &res); |
5bc48308 | 745 | if (ret) { |
91afd36f | 746 | dev_err(bus, "Can't get AMBA base addresses(ret = %d)!\n", ret); |
5bc48308 HW |
747 | return -ENOMEM; |
748 | } | |
749 | ||
91afd36f KS |
750 | q->ahb_addr = map_physmem(res.start, res.end - res.start, MAP_NOCACHE); |
751 | q->memmap_phy = res.start; | |
5bc48308 | 752 | |
91afd36f KS |
753 | dm_bus->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", |
754 | 66000000); | |
5bc48308 | 755 | |
91afd36f | 756 | fsl_qspi_default_setup(q); |
5bc48308 HW |
757 | |
758 | return 0; | |
759 | } | |
760 | ||
761 | static int fsl_qspi_xfer(struct udevice *dev, unsigned int bitlen, | |
91afd36f | 762 | const void *dout, void *din, unsigned long flags) |
5bc48308 | 763 | { |
91afd36f | 764 | return 0; |
5bc48308 HW |
765 | } |
766 | ||
767 | static int fsl_qspi_claim_bus(struct udevice *dev) | |
768 | { | |
5bc48308 HW |
769 | return 0; |
770 | } | |
771 | ||
772 | static int fsl_qspi_release_bus(struct udevice *dev) | |
773 | { | |
5bc48308 HW |
774 | return 0; |
775 | } | |
776 | ||
777 | static int fsl_qspi_set_speed(struct udevice *bus, uint speed) | |
778 | { | |
5bc48308 HW |
779 | return 0; |
780 | } | |
781 | ||
782 | static int fsl_qspi_set_mode(struct udevice *bus, uint mode) | |
783 | { | |
5bc48308 HW |
784 | return 0; |
785 | } | |
786 | ||
787 | static const struct dm_spi_ops fsl_qspi_ops = { | |
788 | .claim_bus = fsl_qspi_claim_bus, | |
789 | .release_bus = fsl_qspi_release_bus, | |
790 | .xfer = fsl_qspi_xfer, | |
791 | .set_speed = fsl_qspi_set_speed, | |
792 | .set_mode = fsl_qspi_set_mode, | |
91afd36f | 793 | .mem_ops = &fsl_qspi_mem_ops, |
5bc48308 HW |
794 | }; |
795 | ||
796 | static const struct udevice_id fsl_qspi_ids[] = { | |
91afd36f KS |
797 | { .compatible = "fsl,vf610-qspi", .data = (ulong)&vybrid_data, }, |
798 | { .compatible = "fsl,imx6sx-qspi", .data = (ulong)&imx6sx_data, }, | |
799 | { .compatible = "fsl,imx6ul-qspi", .data = (ulong)&imx6ul_data, }, | |
800 | { .compatible = "fsl,imx7d-qspi", .data = (ulong)&imx7d_data, }, | |
801 | { .compatible = "fsl,ls1021a-qspi", .data = (ulong)&ls1021a_data, }, | |
802 | { .compatible = "fsl,ls1088a-qspi", .data = (ulong)&ls1088a_data, }, | |
803 | { .compatible = "fsl,ls2080a-qspi", .data = (ulong)&ls2080a_data, }, | |
5bc48308 HW |
804 | { } |
805 | }; | |
806 | ||
807 | U_BOOT_DRIVER(fsl_qspi) = { | |
808 | .name = "fsl_qspi", | |
809 | .id = UCLASS_SPI, | |
810 | .of_match = fsl_qspi_ids, | |
811 | .ops = &fsl_qspi_ops, | |
91afd36f | 812 | .priv_auto_alloc_size = sizeof(struct fsl_qspi), |
5bc48308 | 813 | .probe = fsl_qspi_probe, |
5bc48308 | 814 | }; |