blob: d12f4201d6cf05905e32d80cc2836d82c8b77578 [file] [log] [blame]
Alison Wang6b57ff62014-05-06 09:13:01 +08001/*
2 * Copyright 2013-2014 Freescale Semiconductor, Inc.
3 *
4 * Freescale Quad Serial Peripheral Interface (QSPI) driver
5 *
6 * SPDX-License-Identifier: GPL-2.0+
7 */
8
9#include <common.h>
10#include <malloc.h>
11#include <spi.h>
12#include <asm/io.h>
13#include <linux/sizes.h>
14#include "fsl_qspi.h"
15
16#define RX_BUFFER_SIZE 0x80
Peng Fanb93ab2e2014-12-31 11:01:38 +080017#ifdef CONFIG_MX6SX
18#define TX_BUFFER_SIZE 0x200
19#else
Alison Wang6b57ff62014-05-06 09:13:01 +080020#define TX_BUFFER_SIZE 0x40
Peng Fanb93ab2e2014-12-31 11:01:38 +080021#endif
Alison Wang6b57ff62014-05-06 09:13:01 +080022
23#define OFFSET_BITS_MASK 0x00ffffff
24
25#define FLASH_STATUS_WEL 0x02
26
27/* SEQID */
28#define SEQID_WREN 1
29#define SEQID_FAST_READ 2
30#define SEQID_RDSR 3
31#define SEQID_SE 4
32#define SEQID_CHIP_ERASE 5
33#define SEQID_PP 6
34#define SEQID_RDID 7
Peng Fanba4dc8a2014-12-31 11:01:39 +080035#define SEQID_BE_4K 8
Alison Wang6b57ff62014-05-06 09:13:01 +080036
Peng Fan53e3db72014-12-31 11:01:36 +080037/* QSPI CMD */
38#define QSPI_CMD_PP 0x02 /* Page program (up to 256 bytes) */
39#define QSPI_CMD_RDSR 0x05 /* Read status register */
40#define QSPI_CMD_WREN 0x06 /* Write enable */
41#define QSPI_CMD_FAST_READ 0x0b /* Read data bytes (high frequency) */
Peng Fanba4dc8a2014-12-31 11:01:39 +080042#define QSPI_CMD_BE_4K 0x20 /* 4K erase */
Peng Fan53e3db72014-12-31 11:01:36 +080043#define QSPI_CMD_CHIP_ERASE 0xc7 /* Erase whole flash chip */
44#define QSPI_CMD_SE 0xd8 /* Sector erase (usually 64KiB) */
45#define QSPI_CMD_RDID 0x9f /* Read JEDEC ID */
Alison Wang6b57ff62014-05-06 09:13:01 +080046
Peng Fan53e3db72014-12-31 11:01:36 +080047/* 4-byte address QSPI CMD - used on Spansion and some Macronix flashes */
48#define QSPI_CMD_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */
49#define QSPI_CMD_PP_4B 0x12 /* Page program (up to 256 bytes) */
50#define QSPI_CMD_SE_4B 0xdc /* Sector erase (usually 64KiB) */
Alison Wang6b57ff62014-05-06 09:13:01 +080051
52#ifdef CONFIG_SYS_FSL_QSPI_LE
53#define qspi_read32 in_le32
54#define qspi_write32 out_le32
55#elif defined(CONFIG_SYS_FSL_QSPI_BE)
56#define qspi_read32 in_be32
57#define qspi_write32 out_be32
58#endif
59
60static unsigned long spi_bases[] = {
61 QSPI0_BASE_ADDR,
Peng Fanb93ab2e2014-12-31 11:01:38 +080062#ifdef CONFIG_MX6SX
63 QSPI1_BASE_ADDR,
64#endif
Alison Wang6b57ff62014-05-06 09:13:01 +080065};
66
67static unsigned long amba_bases[] = {
68 QSPI0_AMBA_BASE,
Peng Fanb93ab2e2014-12-31 11:01:38 +080069#ifdef CONFIG_MX6SX
70 QSPI1_AMBA_BASE,
71#endif
Alison Wang6b57ff62014-05-06 09:13:01 +080072};
73
74struct fsl_qspi {
75 struct spi_slave slave;
76 unsigned long reg_base;
77 unsigned long amba_base;
78 u32 sf_addr;
79 u8 cur_seqid;
80};
81
82/* QSPI support swapping the flash read/write data
83 * in hardware for LS102xA, but not for VF610 */
84static inline u32 qspi_endian_xchg(u32 data)
85{
86#ifdef CONFIG_VF610
87 return swab32(data);
88#else
89 return data;
90#endif
91}
92
93static inline struct fsl_qspi *to_qspi_spi(struct spi_slave *slave)
94{
95 return container_of(slave, struct fsl_qspi, slave);
96}
97
98static void qspi_set_lut(struct fsl_qspi *qspi)
99{
100 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
101 u32 lut_base;
102
103 /* Unlock the LUT */
104 qspi_write32(&regs->lutkey, LUT_KEY_VALUE);
105 qspi_write32(&regs->lckcr, QSPI_LCKCR_UNLOCK);
106
107 /* Write Enable */
108 lut_base = SEQID_WREN * 4;
Peng Fan53e3db72014-12-31 11:01:36 +0800109 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_WREN) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800110 PAD0(LUT_PAD1) | INSTR0(LUT_CMD));
111 qspi_write32(&regs->lut[lut_base + 1], 0);
112 qspi_write32(&regs->lut[lut_base + 2], 0);
113 qspi_write32(&regs->lut[lut_base + 3], 0);
114
115 /* Fast Read */
116 lut_base = SEQID_FAST_READ * 4;
117 if (FSL_QSPI_FLASH_SIZE <= SZ_16M)
Peng Fan53e3db72014-12-31 11:01:36 +0800118 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_FAST_READ) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800119 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
120 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
121 else
Peng Fan53e3db72014-12-31 11:01:36 +0800122 qspi_write32(&regs->lut[lut_base],
123 OPRND0(QSPI_CMD_FAST_READ_4B) |
124 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) |
125 OPRND1(ADDR32BIT) | PAD1(LUT_PAD1) |
126 INSTR1(LUT_ADDR));
Alison Wang6b57ff62014-05-06 09:13:01 +0800127 qspi_write32(&regs->lut[lut_base + 1], OPRND0(8) | PAD0(LUT_PAD1) |
128 INSTR0(LUT_DUMMY) | OPRND1(RX_BUFFER_SIZE) | PAD1(LUT_PAD1) |
129 INSTR1(LUT_READ));
130 qspi_write32(&regs->lut[lut_base + 2], 0);
131 qspi_write32(&regs->lut[lut_base + 3], 0);
132
133 /* Read Status */
134 lut_base = SEQID_RDSR * 4;
Peng Fan53e3db72014-12-31 11:01:36 +0800135 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_RDSR) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800136 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) |
137 PAD1(LUT_PAD1) | INSTR1(LUT_READ));
138 qspi_write32(&regs->lut[lut_base + 1], 0);
139 qspi_write32(&regs->lut[lut_base + 2], 0);
140 qspi_write32(&regs->lut[lut_base + 3], 0);
141
142 /* Erase a sector */
143 lut_base = SEQID_SE * 4;
144 if (FSL_QSPI_FLASH_SIZE <= SZ_16M)
Peng Fan53e3db72014-12-31 11:01:36 +0800145 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_SE) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800146 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
147 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
148 else
Peng Fan53e3db72014-12-31 11:01:36 +0800149 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_SE_4B) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800150 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
151 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
152 qspi_write32(&regs->lut[lut_base + 1], 0);
153 qspi_write32(&regs->lut[lut_base + 2], 0);
154 qspi_write32(&regs->lut[lut_base + 3], 0);
155
156 /* Erase the whole chip */
157 lut_base = SEQID_CHIP_ERASE * 4;
Peng Fan53e3db72014-12-31 11:01:36 +0800158 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_CHIP_ERASE) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800159 PAD0(LUT_PAD1) | INSTR0(LUT_CMD));
160 qspi_write32(&regs->lut[lut_base + 1], 0);
161 qspi_write32(&regs->lut[lut_base + 2], 0);
162 qspi_write32(&regs->lut[lut_base + 3], 0);
163
164 /* Page Program */
165 lut_base = SEQID_PP * 4;
166 if (FSL_QSPI_FLASH_SIZE <= SZ_16M)
Peng Fan53e3db72014-12-31 11:01:36 +0800167 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_PP) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800168 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
169 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
170 else
Peng Fan53e3db72014-12-31 11:01:36 +0800171 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_PP_4B) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800172 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
173 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
Peng Fanb93ab2e2014-12-31 11:01:38 +0800174#ifdef CONFIG_MX6SX
175 /*
176 * To MX6SX, OPRND0(TX_BUFFER_SIZE) can not work correctly.
177 * So, Use IDATSZ in IPCR to determine the size and here set 0.
178 */
179 qspi_write32(&regs->lut[lut_base + 1], OPRND0(0) |
180 PAD0(LUT_PAD1) | INSTR0(LUT_WRITE));
181#else
Alison Wang6b57ff62014-05-06 09:13:01 +0800182 qspi_write32(&regs->lut[lut_base + 1], OPRND0(TX_BUFFER_SIZE) |
183 PAD0(LUT_PAD1) | INSTR0(LUT_WRITE));
Peng Fanb93ab2e2014-12-31 11:01:38 +0800184#endif
Alison Wang6b57ff62014-05-06 09:13:01 +0800185 qspi_write32(&regs->lut[lut_base + 2], 0);
186 qspi_write32(&regs->lut[lut_base + 3], 0);
187
188 /* READ ID */
189 lut_base = SEQID_RDID * 4;
Peng Fan53e3db72014-12-31 11:01:36 +0800190 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_RDID) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800191 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(8) |
192 PAD1(LUT_PAD1) | INSTR1(LUT_READ));
193 qspi_write32(&regs->lut[lut_base + 1], 0);
194 qspi_write32(&regs->lut[lut_base + 2], 0);
195 qspi_write32(&regs->lut[lut_base + 3], 0);
196
Peng Fanba4dc8a2014-12-31 11:01:39 +0800197 /* SUB SECTOR 4K ERASE */
198 lut_base = SEQID_BE_4K * 4;
199 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_BE_4K) |
200 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
201 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
202
Alison Wang6b57ff62014-05-06 09:13:01 +0800203 /* Lock the LUT */
204 qspi_write32(&regs->lutkey, LUT_KEY_VALUE);
205 qspi_write32(&regs->lckcr, QSPI_LCKCR_LOCK);
206}
207
208void spi_init()
209{
210 /* do nothing */
211}
212
213struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
214 unsigned int max_hz, unsigned int mode)
215{
216 struct fsl_qspi *qspi;
217 struct fsl_qspi_regs *regs;
218 u32 reg_val, smpr_val;
219 u32 total_size, seq_id;
220
221 if (bus >= ARRAY_SIZE(spi_bases))
222 return NULL;
223
Peng Faned0c81c2014-12-31 11:01:37 +0800224 if (cs >= FSL_QSPI_FLASH_NUM)
225 return NULL;
226
Alison Wang6b57ff62014-05-06 09:13:01 +0800227 qspi = spi_alloc_slave(struct fsl_qspi, bus, cs);
228 if (!qspi)
229 return NULL;
230
231 qspi->reg_base = spi_bases[bus];
Peng Faned0c81c2014-12-31 11:01:37 +0800232 /*
233 * According cs, use different amba_base to choose the
234 * corresponding flash devices.
235 *
236 * If not, only one flash device is used even if passing
237 * different cs using `sf probe`
238 */
239 qspi->amba_base = amba_bases[bus] + cs * FSL_QSPI_FLASH_SIZE;
Alison Wang6b57ff62014-05-06 09:13:01 +0800240
241 qspi->slave.max_write_size = TX_BUFFER_SIZE;
242
243 regs = (struct fsl_qspi_regs *)qspi->reg_base;
244 qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK);
245
246 smpr_val = qspi_read32(&regs->smpr);
247 qspi_write32(&regs->smpr, smpr_val & ~(QSPI_SMPR_FSDLY_MASK |
248 QSPI_SMPR_FSPHS_MASK | QSPI_SMPR_HSENA_MASK));
249 qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK);
250
251 total_size = FSL_QSPI_FLASH_SIZE * FSL_QSPI_FLASH_NUM;
Peng Faned0c81c2014-12-31 11:01:37 +0800252 /*
253 * Any read access to non-implemented addresses will provide
254 * undefined results.
255 *
256 * In case single die flash devices, TOP_ADDR_MEMA2 and
257 * TOP_ADDR_MEMB2 should be initialized/programmed to
258 * TOP_ADDR_MEMA1 and TOP_ADDR_MEMB1 respectively - in effect,
259 * setting the size of these devices to 0. This would ensure
260 * that the complete memory map is assigned to only one flash device.
261 */
262 qspi_write32(&regs->sfa1ad, FSL_QSPI_FLASH_SIZE | amba_bases[bus]);
263 qspi_write32(&regs->sfa2ad, FSL_QSPI_FLASH_SIZE | amba_bases[bus]);
264 qspi_write32(&regs->sfb1ad, total_size | amba_bases[bus]);
265 qspi_write32(&regs->sfb2ad, total_size | amba_bases[bus]);
Alison Wang6b57ff62014-05-06 09:13:01 +0800266
267 qspi_set_lut(qspi);
268
269 smpr_val = qspi_read32(&regs->smpr);
270 smpr_val &= ~QSPI_SMPR_DDRSMP_MASK;
271 qspi_write32(&regs->smpr, smpr_val);
272 qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK);
273
274 seq_id = 0;
275 reg_val = qspi_read32(&regs->bfgencr);
276 reg_val &= ~QSPI_BFGENCR_SEQID_MASK;
277 reg_val |= (seq_id << QSPI_BFGENCR_SEQID_SHIFT);
278 reg_val &= ~QSPI_BFGENCR_PAR_EN_MASK;
279 qspi_write32(&regs->bfgencr, reg_val);
280
281 return &qspi->slave;
282}
283
284void spi_free_slave(struct spi_slave *slave)
285{
286 struct fsl_qspi *qspi = to_qspi_spi(slave);
287
288 free(qspi);
289}
290
291int spi_claim_bus(struct spi_slave *slave)
292{
293 return 0;
294}
295
296static void qspi_op_rdid(struct fsl_qspi *qspi, u32 *rxbuf, u32 len)
297{
298 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
299 u32 mcr_reg, rbsr_reg, data;
300 int i, size;
301
302 mcr_reg = qspi_read32(&regs->mcr);
303 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
304 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
305 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
306
307 qspi_write32(&regs->sfar, qspi->amba_base);
308
309 qspi_write32(&regs->ipcr, (SEQID_RDID << QSPI_IPCR_SEQID_SHIFT) | 0);
310 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
311 ;
312
313 i = 0;
314 size = len;
315 while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
316 rbsr_reg = qspi_read32(&regs->rbsr);
317 if (rbsr_reg & QSPI_RBSR_RDBFL_MASK) {
318 data = qspi_read32(&regs->rbdr[i]);
319 data = qspi_endian_xchg(data);
320 memcpy(rxbuf, &data, 4);
321 rxbuf++;
322 size -= 4;
323 i++;
324 }
325 }
326
327 qspi_write32(&regs->mcr, mcr_reg);
328}
329
330static void qspi_op_read(struct fsl_qspi *qspi, u32 *rxbuf, u32 len)
331{
332 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
333 u32 mcr_reg, data;
334 int i, size;
335 u32 to_or_from;
336
337 mcr_reg = qspi_read32(&regs->mcr);
338 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
339 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
340 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
341
342 to_or_from = qspi->sf_addr + qspi->amba_base;
343
344 while (len > 0) {
345 qspi_write32(&regs->sfar, to_or_from);
346
347 size = (len > RX_BUFFER_SIZE) ?
348 RX_BUFFER_SIZE : len;
349
350 qspi_write32(&regs->ipcr,
351 (SEQID_FAST_READ << QSPI_IPCR_SEQID_SHIFT) | size);
352 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
353 ;
354
355 to_or_from += size;
356 len -= size;
357
358 i = 0;
359 while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
360 data = qspi_read32(&regs->rbdr[i]);
361 data = qspi_endian_xchg(data);
362 memcpy(rxbuf, &data, 4);
363 rxbuf++;
364 size -= 4;
365 i++;
366 }
367 qspi_write32(&regs->mcr, qspi_read32(&regs->mcr) |
368 QSPI_MCR_CLR_RXF_MASK);
369 }
370
371 qspi_write32(&regs->mcr, mcr_reg);
372}
373
374static void qspi_op_pp(struct fsl_qspi *qspi, u32 *txbuf, u32 len)
375{
376 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
377 u32 mcr_reg, data, reg, status_reg;
378 int i, size, tx_size;
379 u32 to_or_from = 0;
380
381 mcr_reg = qspi_read32(&regs->mcr);
382 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
383 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
384 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
385
386 status_reg = 0;
387 while ((status_reg & FLASH_STATUS_WEL) != FLASH_STATUS_WEL) {
388 qspi_write32(&regs->ipcr,
389 (SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0);
390 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
391 ;
392
393 qspi_write32(&regs->ipcr,
394 (SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 1);
395 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
396 ;
397
398 reg = qspi_read32(&regs->rbsr);
399 if (reg & QSPI_RBSR_RDBFL_MASK) {
400 status_reg = qspi_read32(&regs->rbdr[0]);
401 status_reg = qspi_endian_xchg(status_reg);
402 }
403 qspi_write32(&regs->mcr,
404 qspi_read32(&regs->mcr) | QSPI_MCR_CLR_RXF_MASK);
405 }
406
407 to_or_from = qspi->sf_addr + qspi->amba_base;
408 qspi_write32(&regs->sfar, to_or_from);
409
410 tx_size = (len > TX_BUFFER_SIZE) ?
411 TX_BUFFER_SIZE : len;
412
413 size = (tx_size + 3) / 4;
414
415 for (i = 0; i < size; i++) {
416 data = qspi_endian_xchg(*txbuf);
417 qspi_write32(&regs->tbdr, data);
418 txbuf++;
419 }
420
421 qspi_write32(&regs->ipcr,
422 (SEQID_PP << QSPI_IPCR_SEQID_SHIFT) | tx_size);
423 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
424 ;
425
426 qspi_write32(&regs->mcr, mcr_reg);
427}
428
429static void qspi_op_rdsr(struct fsl_qspi *qspi, u32 *rxbuf)
430{
431 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
432 u32 mcr_reg, reg, data;
433
434 mcr_reg = qspi_read32(&regs->mcr);
435 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
436 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
437 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
438
439 qspi_write32(&regs->sfar, qspi->amba_base);
440
441 qspi_write32(&regs->ipcr,
442 (SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 0);
443 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
444 ;
445
446 while (1) {
447 reg = qspi_read32(&regs->rbsr);
448 if (reg & QSPI_RBSR_RDBFL_MASK) {
449 data = qspi_read32(&regs->rbdr[0]);
450 data = qspi_endian_xchg(data);
451 memcpy(rxbuf, &data, 4);
452 qspi_write32(&regs->mcr, qspi_read32(&regs->mcr) |
453 QSPI_MCR_CLR_RXF_MASK);
454 break;
455 }
456 }
457
458 qspi_write32(&regs->mcr, mcr_reg);
459}
460
Peng Fanba4dc8a2014-12-31 11:01:39 +0800461static void qspi_op_erase(struct fsl_qspi *qspi)
Alison Wang6b57ff62014-05-06 09:13:01 +0800462{
463 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
464 u32 mcr_reg;
465 u32 to_or_from = 0;
466
467 mcr_reg = qspi_read32(&regs->mcr);
468 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
469 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
470 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
471
472 to_or_from = qspi->sf_addr + qspi->amba_base;
473 qspi_write32(&regs->sfar, to_or_from);
474
475 qspi_write32(&regs->ipcr,
476 (SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0);
477 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
478 ;
479
Peng Fanba4dc8a2014-12-31 11:01:39 +0800480 if (qspi->cur_seqid == QSPI_CMD_SE) {
481 qspi_write32(&regs->ipcr,
482 (SEQID_SE << QSPI_IPCR_SEQID_SHIFT) | 0);
483 } else if (qspi->cur_seqid == QSPI_CMD_BE_4K) {
484 qspi_write32(&regs->ipcr,
485 (SEQID_BE_4K << QSPI_IPCR_SEQID_SHIFT) | 0);
486 }
Alison Wang6b57ff62014-05-06 09:13:01 +0800487 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
488 ;
489
490 qspi_write32(&regs->mcr, mcr_reg);
491}
492
493int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
494 const void *dout, void *din, unsigned long flags)
495{
496 struct fsl_qspi *qspi = to_qspi_spi(slave);
497 u32 bytes = DIV_ROUND_UP(bitlen, 8);
498 static u32 pp_sfaddr;
499 u32 txbuf;
500
501 if (dout) {
502 memcpy(&txbuf, dout, 4);
503 qspi->cur_seqid = *(u8 *)dout;
504
505 if (flags == SPI_XFER_END) {
506 qspi->sf_addr = pp_sfaddr;
507 qspi_op_pp(qspi, (u32 *)dout, bytes);
508 return 0;
509 }
510
Peng Fan53e3db72014-12-31 11:01:36 +0800511 if (qspi->cur_seqid == QSPI_CMD_FAST_READ) {
Alison Wang6b57ff62014-05-06 09:13:01 +0800512 qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
Peng Fanba4dc8a2014-12-31 11:01:39 +0800513 } else if ((qspi->cur_seqid == QSPI_CMD_SE) ||
514 (qspi->cur_seqid == QSPI_CMD_BE_4K)) {
Alison Wang6b57ff62014-05-06 09:13:01 +0800515 qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
Peng Fanba4dc8a2014-12-31 11:01:39 +0800516 qspi_op_erase(qspi);
Peng Fan53e3db72014-12-31 11:01:36 +0800517 } else if (qspi->cur_seqid == QSPI_CMD_PP) {
Alison Wang6b57ff62014-05-06 09:13:01 +0800518 pp_sfaddr = swab32(txbuf) & OFFSET_BITS_MASK;
519 }
520 }
521
522 if (din) {
Peng Fan53e3db72014-12-31 11:01:36 +0800523 if (qspi->cur_seqid == QSPI_CMD_FAST_READ)
Alison Wang6b57ff62014-05-06 09:13:01 +0800524 qspi_op_read(qspi, din, bytes);
Peng Fan53e3db72014-12-31 11:01:36 +0800525 else if (qspi->cur_seqid == QSPI_CMD_RDID)
Alison Wang6b57ff62014-05-06 09:13:01 +0800526 qspi_op_rdid(qspi, din, bytes);
Peng Fan53e3db72014-12-31 11:01:36 +0800527 else if (qspi->cur_seqid == QSPI_CMD_RDSR)
Alison Wang6b57ff62014-05-06 09:13:01 +0800528 qspi_op_rdsr(qspi, din);
529 }
530
531 return 0;
532}
533
534void spi_release_bus(struct spi_slave *slave)
535{
536 /* Nothing to do */
537}