blob: ad4f4ced17b56a2709284c414ac6292a5eb99abd [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
Peng Fana2358782015-01-04 17:07:14 +080036#ifdef CONFIG_SPI_FLASH_BAR
37#define SEQID_BRRD 9
38#define SEQID_BRWR 10
39#define SEQID_RDEAR 11
40#define SEQID_WREAR 12
41#endif
Alison Wang6b57ff62014-05-06 09:13:01 +080042
Peng Fan53e3db72014-12-31 11:01:36 +080043/* QSPI CMD */
44#define QSPI_CMD_PP 0x02 /* Page program (up to 256 bytes) */
45#define QSPI_CMD_RDSR 0x05 /* Read status register */
46#define QSPI_CMD_WREN 0x06 /* Write enable */
47#define QSPI_CMD_FAST_READ 0x0b /* Read data bytes (high frequency) */
Peng Fanba4dc8a2014-12-31 11:01:39 +080048#define QSPI_CMD_BE_4K 0x20 /* 4K erase */
Peng Fan53e3db72014-12-31 11:01:36 +080049#define QSPI_CMD_CHIP_ERASE 0xc7 /* Erase whole flash chip */
50#define QSPI_CMD_SE 0xd8 /* Sector erase (usually 64KiB) */
51#define QSPI_CMD_RDID 0x9f /* Read JEDEC ID */
Alison Wang6b57ff62014-05-06 09:13:01 +080052
Peng Fana2358782015-01-04 17:07:14 +080053/* Used for Micron, winbond and Macronix flashes */
54#define QSPI_CMD_WREAR 0xc5 /* EAR register write */
55#define QSPI_CMD_RDEAR 0xc8 /* EAR reigster read */
56
57/* Used for Spansion flashes only. */
58#define QSPI_CMD_BRRD 0x16 /* Bank register read */
59#define QSPI_CMD_BRWR 0x17 /* Bank register write */
60
Peng Fan53e3db72014-12-31 11:01:36 +080061/* 4-byte address QSPI CMD - used on Spansion and some Macronix flashes */
62#define QSPI_CMD_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */
63#define QSPI_CMD_PP_4B 0x12 /* Page program (up to 256 bytes) */
64#define QSPI_CMD_SE_4B 0xdc /* Sector erase (usually 64KiB) */
Alison Wang6b57ff62014-05-06 09:13:01 +080065
66#ifdef CONFIG_SYS_FSL_QSPI_LE
67#define qspi_read32 in_le32
68#define qspi_write32 out_le32
69#elif defined(CONFIG_SYS_FSL_QSPI_BE)
70#define qspi_read32 in_be32
71#define qspi_write32 out_be32
72#endif
73
74static unsigned long spi_bases[] = {
75 QSPI0_BASE_ADDR,
Peng Fanb93ab2e2014-12-31 11:01:38 +080076#ifdef CONFIG_MX6SX
77 QSPI1_BASE_ADDR,
78#endif
Alison Wang6b57ff62014-05-06 09:13:01 +080079};
80
81static unsigned long amba_bases[] = {
82 QSPI0_AMBA_BASE,
Peng Fanb93ab2e2014-12-31 11:01:38 +080083#ifdef CONFIG_MX6SX
84 QSPI1_AMBA_BASE,
85#endif
Alison Wang6b57ff62014-05-06 09:13:01 +080086};
87
88struct fsl_qspi {
89 struct spi_slave slave;
90 unsigned long reg_base;
91 unsigned long amba_base;
92 u32 sf_addr;
93 u8 cur_seqid;
94};
95
96/* QSPI support swapping the flash read/write data
97 * in hardware for LS102xA, but not for VF610 */
98static inline u32 qspi_endian_xchg(u32 data)
99{
100#ifdef CONFIG_VF610
101 return swab32(data);
102#else
103 return data;
104#endif
105}
106
107static inline struct fsl_qspi *to_qspi_spi(struct spi_slave *slave)
108{
109 return container_of(slave, struct fsl_qspi, slave);
110}
111
112static void qspi_set_lut(struct fsl_qspi *qspi)
113{
114 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
115 u32 lut_base;
116
117 /* Unlock the LUT */
118 qspi_write32(&regs->lutkey, LUT_KEY_VALUE);
119 qspi_write32(&regs->lckcr, QSPI_LCKCR_UNLOCK);
120
121 /* Write Enable */
122 lut_base = SEQID_WREN * 4;
Peng Fan53e3db72014-12-31 11:01:36 +0800123 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_WREN) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800124 PAD0(LUT_PAD1) | INSTR0(LUT_CMD));
125 qspi_write32(&regs->lut[lut_base + 1], 0);
126 qspi_write32(&regs->lut[lut_base + 2], 0);
127 qspi_write32(&regs->lut[lut_base + 3], 0);
128
129 /* Fast Read */
130 lut_base = SEQID_FAST_READ * 4;
Peng Fana2358782015-01-04 17:07:14 +0800131#ifdef CONFIG_SPI_FLASH_BAR
132 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_FAST_READ) |
133 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
134 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
135#else
Alison Wang6b57ff62014-05-06 09:13:01 +0800136 if (FSL_QSPI_FLASH_SIZE <= SZ_16M)
Peng Fan53e3db72014-12-31 11:01:36 +0800137 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_FAST_READ) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800138 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
139 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
140 else
Peng Fan53e3db72014-12-31 11:01:36 +0800141 qspi_write32(&regs->lut[lut_base],
142 OPRND0(QSPI_CMD_FAST_READ_4B) |
143 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) |
144 OPRND1(ADDR32BIT) | PAD1(LUT_PAD1) |
145 INSTR1(LUT_ADDR));
Peng Fana2358782015-01-04 17:07:14 +0800146#endif
Alison Wang6b57ff62014-05-06 09:13:01 +0800147 qspi_write32(&regs->lut[lut_base + 1], OPRND0(8) | PAD0(LUT_PAD1) |
148 INSTR0(LUT_DUMMY) | OPRND1(RX_BUFFER_SIZE) | PAD1(LUT_PAD1) |
149 INSTR1(LUT_READ));
150 qspi_write32(&regs->lut[lut_base + 2], 0);
151 qspi_write32(&regs->lut[lut_base + 3], 0);
152
153 /* Read Status */
154 lut_base = SEQID_RDSR * 4;
Peng Fan53e3db72014-12-31 11:01:36 +0800155 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_RDSR) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800156 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) |
157 PAD1(LUT_PAD1) | INSTR1(LUT_READ));
158 qspi_write32(&regs->lut[lut_base + 1], 0);
159 qspi_write32(&regs->lut[lut_base + 2], 0);
160 qspi_write32(&regs->lut[lut_base + 3], 0);
161
162 /* Erase a sector */
163 lut_base = SEQID_SE * 4;
Peng Fana2358782015-01-04 17:07:14 +0800164#ifdef CONFIG_SPI_FLASH_BAR
165 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_SE) |
166 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
167 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
168#else
Alison Wang6b57ff62014-05-06 09:13:01 +0800169 if (FSL_QSPI_FLASH_SIZE <= SZ_16M)
Peng Fan53e3db72014-12-31 11:01:36 +0800170 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_SE) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800171 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
172 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
173 else
Peng Fan53e3db72014-12-31 11:01:36 +0800174 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_SE_4B) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800175 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
176 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
Peng Fana2358782015-01-04 17:07:14 +0800177#endif
Alison Wang6b57ff62014-05-06 09:13:01 +0800178 qspi_write32(&regs->lut[lut_base + 1], 0);
179 qspi_write32(&regs->lut[lut_base + 2], 0);
180 qspi_write32(&regs->lut[lut_base + 3], 0);
181
182 /* Erase the whole chip */
183 lut_base = SEQID_CHIP_ERASE * 4;
Peng Fan53e3db72014-12-31 11:01:36 +0800184 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_CHIP_ERASE) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800185 PAD0(LUT_PAD1) | INSTR0(LUT_CMD));
186 qspi_write32(&regs->lut[lut_base + 1], 0);
187 qspi_write32(&regs->lut[lut_base + 2], 0);
188 qspi_write32(&regs->lut[lut_base + 3], 0);
189
190 /* Page Program */
191 lut_base = SEQID_PP * 4;
Peng Fana2358782015-01-04 17:07:14 +0800192#ifdef CONFIG_SPI_FLASH_BAR
193 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_PP) |
194 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
195 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
196#else
Alison Wang6b57ff62014-05-06 09:13:01 +0800197 if (FSL_QSPI_FLASH_SIZE <= SZ_16M)
Peng Fan53e3db72014-12-31 11:01:36 +0800198 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_PP) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800199 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
200 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
201 else
Peng Fan53e3db72014-12-31 11:01:36 +0800202 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_PP_4B) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800203 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
204 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
Peng Fana2358782015-01-04 17:07:14 +0800205#endif
Peng Fanb93ab2e2014-12-31 11:01:38 +0800206#ifdef CONFIG_MX6SX
207 /*
208 * To MX6SX, OPRND0(TX_BUFFER_SIZE) can not work correctly.
209 * So, Use IDATSZ in IPCR to determine the size and here set 0.
210 */
211 qspi_write32(&regs->lut[lut_base + 1], OPRND0(0) |
212 PAD0(LUT_PAD1) | INSTR0(LUT_WRITE));
213#else
Alison Wang6b57ff62014-05-06 09:13:01 +0800214 qspi_write32(&regs->lut[lut_base + 1], OPRND0(TX_BUFFER_SIZE) |
215 PAD0(LUT_PAD1) | INSTR0(LUT_WRITE));
Peng Fanb93ab2e2014-12-31 11:01:38 +0800216#endif
Alison Wang6b57ff62014-05-06 09:13:01 +0800217 qspi_write32(&regs->lut[lut_base + 2], 0);
218 qspi_write32(&regs->lut[lut_base + 3], 0);
219
220 /* READ ID */
221 lut_base = SEQID_RDID * 4;
Peng Fan53e3db72014-12-31 11:01:36 +0800222 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_RDID) |
Alison Wang6b57ff62014-05-06 09:13:01 +0800223 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(8) |
224 PAD1(LUT_PAD1) | INSTR1(LUT_READ));
225 qspi_write32(&regs->lut[lut_base + 1], 0);
226 qspi_write32(&regs->lut[lut_base + 2], 0);
227 qspi_write32(&regs->lut[lut_base + 3], 0);
228
Peng Fanba4dc8a2014-12-31 11:01:39 +0800229 /* SUB SECTOR 4K ERASE */
230 lut_base = SEQID_BE_4K * 4;
231 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_BE_4K) |
232 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
233 PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
234
Peng Fana2358782015-01-04 17:07:14 +0800235#ifdef CONFIG_SPI_FLASH_BAR
236 /*
237 * BRRD BRWR RDEAR WREAR are all supported, because it is hard to
238 * dynamically check whether to set BRRD BRWR or RDEAR WREAR during
239 * initialization.
240 */
241 lut_base = SEQID_BRRD * 4;
242 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_BRRD) |
243 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) |
244 PAD1(LUT_PAD1) | INSTR1(LUT_READ));
245
246 lut_base = SEQID_BRWR * 4;
247 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_BRWR) |
248 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) |
249 PAD1(LUT_PAD1) | INSTR1(LUT_WRITE));
250
251 lut_base = SEQID_RDEAR * 4;
252 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_RDEAR) |
253 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) |
254 PAD1(LUT_PAD1) | INSTR1(LUT_READ));
255
256 lut_base = SEQID_WREAR * 4;
257 qspi_write32(&regs->lut[lut_base], OPRND0(QSPI_CMD_WREAR) |
258 PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) |
259 PAD1(LUT_PAD1) | INSTR1(LUT_WRITE));
260#endif
Alison Wang6b57ff62014-05-06 09:13:01 +0800261 /* Lock the LUT */
262 qspi_write32(&regs->lutkey, LUT_KEY_VALUE);
263 qspi_write32(&regs->lckcr, QSPI_LCKCR_LOCK);
264}
265
266void spi_init()
267{
268 /* do nothing */
269}
270
271struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
272 unsigned int max_hz, unsigned int mode)
273{
274 struct fsl_qspi *qspi;
275 struct fsl_qspi_regs *regs;
276 u32 reg_val, smpr_val;
277 u32 total_size, seq_id;
278
279 if (bus >= ARRAY_SIZE(spi_bases))
280 return NULL;
281
Peng Faned0c81c2014-12-31 11:01:37 +0800282 if (cs >= FSL_QSPI_FLASH_NUM)
283 return NULL;
284
Alison Wang6b57ff62014-05-06 09:13:01 +0800285 qspi = spi_alloc_slave(struct fsl_qspi, bus, cs);
286 if (!qspi)
287 return NULL;
288
289 qspi->reg_base = spi_bases[bus];
Peng Faned0c81c2014-12-31 11:01:37 +0800290 /*
291 * According cs, use different amba_base to choose the
292 * corresponding flash devices.
293 *
294 * If not, only one flash device is used even if passing
295 * different cs using `sf probe`
296 */
297 qspi->amba_base = amba_bases[bus] + cs * FSL_QSPI_FLASH_SIZE;
Alison Wang6b57ff62014-05-06 09:13:01 +0800298
299 qspi->slave.max_write_size = TX_BUFFER_SIZE;
300
301 regs = (struct fsl_qspi_regs *)qspi->reg_base;
302 qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK);
303
304 smpr_val = qspi_read32(&regs->smpr);
305 qspi_write32(&regs->smpr, smpr_val & ~(QSPI_SMPR_FSDLY_MASK |
306 QSPI_SMPR_FSPHS_MASK | QSPI_SMPR_HSENA_MASK));
307 qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK);
308
309 total_size = FSL_QSPI_FLASH_SIZE * FSL_QSPI_FLASH_NUM;
Peng Faned0c81c2014-12-31 11:01:37 +0800310 /*
311 * Any read access to non-implemented addresses will provide
312 * undefined results.
313 *
314 * In case single die flash devices, TOP_ADDR_MEMA2 and
315 * TOP_ADDR_MEMB2 should be initialized/programmed to
316 * TOP_ADDR_MEMA1 and TOP_ADDR_MEMB1 respectively - in effect,
317 * setting the size of these devices to 0. This would ensure
318 * that the complete memory map is assigned to only one flash device.
319 */
320 qspi_write32(&regs->sfa1ad, FSL_QSPI_FLASH_SIZE | amba_bases[bus]);
321 qspi_write32(&regs->sfa2ad, FSL_QSPI_FLASH_SIZE | amba_bases[bus]);
322 qspi_write32(&regs->sfb1ad, total_size | amba_bases[bus]);
323 qspi_write32(&regs->sfb2ad, total_size | amba_bases[bus]);
Alison Wang6b57ff62014-05-06 09:13:01 +0800324
325 qspi_set_lut(qspi);
326
327 smpr_val = qspi_read32(&regs->smpr);
328 smpr_val &= ~QSPI_SMPR_DDRSMP_MASK;
329 qspi_write32(&regs->smpr, smpr_val);
330 qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK);
331
332 seq_id = 0;
333 reg_val = qspi_read32(&regs->bfgencr);
334 reg_val &= ~QSPI_BFGENCR_SEQID_MASK;
335 reg_val |= (seq_id << QSPI_BFGENCR_SEQID_SHIFT);
336 reg_val &= ~QSPI_BFGENCR_PAR_EN_MASK;
337 qspi_write32(&regs->bfgencr, reg_val);
338
339 return &qspi->slave;
340}
341
342void spi_free_slave(struct spi_slave *slave)
343{
344 struct fsl_qspi *qspi = to_qspi_spi(slave);
345
346 free(qspi);
347}
348
349int spi_claim_bus(struct spi_slave *slave)
350{
351 return 0;
352}
353
Peng Fana2358782015-01-04 17:07:14 +0800354#ifdef CONFIG_SPI_FLASH_BAR
355/* Bank register read/write, EAR register read/write */
356static void qspi_op_rdbank(struct fsl_qspi *qspi, u8 *rxbuf, u32 len)
357{
358 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
359 u32 reg, mcr_reg, data, seqid;
360
361 mcr_reg = qspi_read32(&regs->mcr);
362 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
363 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
364 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
365
366 qspi_write32(&regs->sfar, qspi->amba_base);
367
368 if (qspi->cur_seqid == QSPI_CMD_BRRD)
369 seqid = SEQID_BRRD;
370 else
371 seqid = SEQID_RDEAR;
372
373 qspi_write32(&regs->ipcr, (seqid << QSPI_IPCR_SEQID_SHIFT) | len);
374
375 /* Wait previous command complete */
376 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
377 ;
378
379 while (1) {
380 reg = qspi_read32(&regs->rbsr);
381 if (reg & QSPI_RBSR_RDBFL_MASK) {
382 data = qspi_read32(&regs->rbdr[0]);
383 data = qspi_endian_xchg(data);
384 memcpy(rxbuf, &data, len);
385 qspi_write32(&regs->mcr, qspi_read32(&regs->mcr) |
386 QSPI_MCR_CLR_RXF_MASK);
387 break;
388 }
389 }
390
391 qspi_write32(&regs->mcr, mcr_reg);
392}
393#endif
394
Alison Wang6b57ff62014-05-06 09:13:01 +0800395static void qspi_op_rdid(struct fsl_qspi *qspi, u32 *rxbuf, u32 len)
396{
397 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
398 u32 mcr_reg, rbsr_reg, data;
399 int i, size;
400
401 mcr_reg = qspi_read32(&regs->mcr);
402 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
403 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
404 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
405
406 qspi_write32(&regs->sfar, qspi->amba_base);
407
408 qspi_write32(&regs->ipcr, (SEQID_RDID << QSPI_IPCR_SEQID_SHIFT) | 0);
409 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
410 ;
411
412 i = 0;
413 size = len;
414 while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
415 rbsr_reg = qspi_read32(&regs->rbsr);
416 if (rbsr_reg & QSPI_RBSR_RDBFL_MASK) {
417 data = qspi_read32(&regs->rbdr[i]);
418 data = qspi_endian_xchg(data);
419 memcpy(rxbuf, &data, 4);
420 rxbuf++;
421 size -= 4;
422 i++;
423 }
424 }
425
426 qspi_write32(&regs->mcr, mcr_reg);
427}
428
429static void qspi_op_read(struct fsl_qspi *qspi, u32 *rxbuf, u32 len)
430{
431 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
432 u32 mcr_reg, data;
433 int i, size;
434 u32 to_or_from;
435
436 mcr_reg = qspi_read32(&regs->mcr);
437 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
438 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
439 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
440
441 to_or_from = qspi->sf_addr + qspi->amba_base;
442
443 while (len > 0) {
444 qspi_write32(&regs->sfar, to_or_from);
445
446 size = (len > RX_BUFFER_SIZE) ?
447 RX_BUFFER_SIZE : len;
448
449 qspi_write32(&regs->ipcr,
450 (SEQID_FAST_READ << QSPI_IPCR_SEQID_SHIFT) | size);
451 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
452 ;
453
454 to_or_from += size;
455 len -= size;
456
457 i = 0;
458 while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
459 data = qspi_read32(&regs->rbdr[i]);
460 data = qspi_endian_xchg(data);
461 memcpy(rxbuf, &data, 4);
462 rxbuf++;
463 size -= 4;
464 i++;
465 }
466 qspi_write32(&regs->mcr, qspi_read32(&regs->mcr) |
467 QSPI_MCR_CLR_RXF_MASK);
468 }
469
470 qspi_write32(&regs->mcr, mcr_reg);
471}
472
Peng Fana2358782015-01-04 17:07:14 +0800473static void qspi_op_write(struct fsl_qspi *qspi, u8 *txbuf, u32 len)
Alison Wang6b57ff62014-05-06 09:13:01 +0800474{
475 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
Peng Fana2358782015-01-04 17:07:14 +0800476 u32 mcr_reg, data, reg, status_reg, seqid;
Alison Wang6b57ff62014-05-06 09:13:01 +0800477 int i, size, tx_size;
478 u32 to_or_from = 0;
479
480 mcr_reg = qspi_read32(&regs->mcr);
481 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
482 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
483 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
484
485 status_reg = 0;
486 while ((status_reg & FLASH_STATUS_WEL) != FLASH_STATUS_WEL) {
487 qspi_write32(&regs->ipcr,
488 (SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0);
489 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
490 ;
491
492 qspi_write32(&regs->ipcr,
493 (SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 1);
494 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
495 ;
496
497 reg = qspi_read32(&regs->rbsr);
498 if (reg & QSPI_RBSR_RDBFL_MASK) {
499 status_reg = qspi_read32(&regs->rbdr[0]);
500 status_reg = qspi_endian_xchg(status_reg);
501 }
502 qspi_write32(&regs->mcr,
503 qspi_read32(&regs->mcr) | QSPI_MCR_CLR_RXF_MASK);
504 }
505
Peng Fana2358782015-01-04 17:07:14 +0800506 /* Default is page programming */
507 seqid = SEQID_PP;
508#ifdef CONFIG_SPI_FLASH_BAR
509 if (qspi->cur_seqid == QSPI_CMD_BRWR)
510 seqid = SEQID_BRWR;
511 else if (qspi->cur_seqid == QSPI_CMD_WREAR)
512 seqid = SEQID_WREAR;
513#endif
514
Alison Wang6b57ff62014-05-06 09:13:01 +0800515 to_or_from = qspi->sf_addr + qspi->amba_base;
Peng Fana2358782015-01-04 17:07:14 +0800516
Alison Wang6b57ff62014-05-06 09:13:01 +0800517 qspi_write32(&regs->sfar, to_or_from);
518
519 tx_size = (len > TX_BUFFER_SIZE) ?
520 TX_BUFFER_SIZE : len;
521
Peng Fana2358782015-01-04 17:07:14 +0800522 size = tx_size / 4;
Alison Wang6b57ff62014-05-06 09:13:01 +0800523 for (i = 0; i < size; i++) {
Peng Fana2358782015-01-04 17:07:14 +0800524 memcpy(&data, txbuf, 4);
525 data = qspi_endian_xchg(data);
Alison Wang6b57ff62014-05-06 09:13:01 +0800526 qspi_write32(&regs->tbdr, data);
Peng Fana2358782015-01-04 17:07:14 +0800527 txbuf += 4;
Alison Wang6b57ff62014-05-06 09:13:01 +0800528 }
529
Peng Fana2358782015-01-04 17:07:14 +0800530 size = tx_size % 4;
531 if (size) {
532 data = 0;
533 memcpy(&data, txbuf, size);
534 data = qspi_endian_xchg(data);
535 qspi_write32(&regs->tbdr, data);
536 }
537
538 qspi_write32(&regs->ipcr, (seqid << QSPI_IPCR_SEQID_SHIFT) | tx_size);
Alison Wang6b57ff62014-05-06 09:13:01 +0800539 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
540 ;
541
542 qspi_write32(&regs->mcr, mcr_reg);
543}
544
545static void qspi_op_rdsr(struct fsl_qspi *qspi, u32 *rxbuf)
546{
547 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
548 u32 mcr_reg, reg, data;
549
550 mcr_reg = qspi_read32(&regs->mcr);
551 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
552 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
553 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
554
555 qspi_write32(&regs->sfar, qspi->amba_base);
556
557 qspi_write32(&regs->ipcr,
558 (SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 0);
559 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
560 ;
561
562 while (1) {
563 reg = qspi_read32(&regs->rbsr);
564 if (reg & QSPI_RBSR_RDBFL_MASK) {
565 data = qspi_read32(&regs->rbdr[0]);
566 data = qspi_endian_xchg(data);
567 memcpy(rxbuf, &data, 4);
568 qspi_write32(&regs->mcr, qspi_read32(&regs->mcr) |
569 QSPI_MCR_CLR_RXF_MASK);
570 break;
571 }
572 }
573
574 qspi_write32(&regs->mcr, mcr_reg);
575}
576
Peng Fanba4dc8a2014-12-31 11:01:39 +0800577static void qspi_op_erase(struct fsl_qspi *qspi)
Alison Wang6b57ff62014-05-06 09:13:01 +0800578{
579 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
580 u32 mcr_reg;
581 u32 to_or_from = 0;
582
583 mcr_reg = qspi_read32(&regs->mcr);
584 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
585 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
586 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
587
588 to_or_from = qspi->sf_addr + qspi->amba_base;
589 qspi_write32(&regs->sfar, to_or_from);
590
591 qspi_write32(&regs->ipcr,
592 (SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0);
593 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
594 ;
595
Peng Fanba4dc8a2014-12-31 11:01:39 +0800596 if (qspi->cur_seqid == QSPI_CMD_SE) {
597 qspi_write32(&regs->ipcr,
598 (SEQID_SE << QSPI_IPCR_SEQID_SHIFT) | 0);
599 } else if (qspi->cur_seqid == QSPI_CMD_BE_4K) {
600 qspi_write32(&regs->ipcr,
601 (SEQID_BE_4K << QSPI_IPCR_SEQID_SHIFT) | 0);
602 }
Alison Wang6b57ff62014-05-06 09:13:01 +0800603 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
604 ;
605
606 qspi_write32(&regs->mcr, mcr_reg);
607}
608
609int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
610 const void *dout, void *din, unsigned long flags)
611{
612 struct fsl_qspi *qspi = to_qspi_spi(slave);
613 u32 bytes = DIV_ROUND_UP(bitlen, 8);
Peng Fana2358782015-01-04 17:07:14 +0800614 static u32 wr_sfaddr;
Alison Wang6b57ff62014-05-06 09:13:01 +0800615 u32 txbuf;
616
617 if (dout) {
Peng Fana2358782015-01-04 17:07:14 +0800618 if (flags & SPI_XFER_BEGIN) {
619 qspi->cur_seqid = *(u8 *)dout;
620 memcpy(&txbuf, dout, 4);
621 }
Alison Wang6b57ff62014-05-06 09:13:01 +0800622
623 if (flags == SPI_XFER_END) {
Peng Fana2358782015-01-04 17:07:14 +0800624 qspi->sf_addr = wr_sfaddr;
625 qspi_op_write(qspi, (u8 *)dout, bytes);
Alison Wang6b57ff62014-05-06 09:13:01 +0800626 return 0;
627 }
628
Peng Fan53e3db72014-12-31 11:01:36 +0800629 if (qspi->cur_seqid == QSPI_CMD_FAST_READ) {
Alison Wang6b57ff62014-05-06 09:13:01 +0800630 qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
Peng Fanba4dc8a2014-12-31 11:01:39 +0800631 } else if ((qspi->cur_seqid == QSPI_CMD_SE) ||
632 (qspi->cur_seqid == QSPI_CMD_BE_4K)) {
Alison Wang6b57ff62014-05-06 09:13:01 +0800633 qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
Peng Fanba4dc8a2014-12-31 11:01:39 +0800634 qspi_op_erase(qspi);
Peng Fana2358782015-01-04 17:07:14 +0800635 } else if (qspi->cur_seqid == QSPI_CMD_PP)
636 wr_sfaddr = swab32(txbuf) & OFFSET_BITS_MASK;
637#ifdef CONFIG_SPI_FLASH_BAR
638 else if ((qspi->cur_seqid == QSPI_CMD_BRWR) ||
639 (qspi->cur_seqid == QSPI_CMD_WREAR)) {
640 wr_sfaddr = 0;
Alison Wang6b57ff62014-05-06 09:13:01 +0800641 }
Peng Fana2358782015-01-04 17:07:14 +0800642#endif
Alison Wang6b57ff62014-05-06 09:13:01 +0800643 }
644
645 if (din) {
Peng Fan53e3db72014-12-31 11:01:36 +0800646 if (qspi->cur_seqid == QSPI_CMD_FAST_READ)
Alison Wang6b57ff62014-05-06 09:13:01 +0800647 qspi_op_read(qspi, din, bytes);
Peng Fan53e3db72014-12-31 11:01:36 +0800648 else if (qspi->cur_seqid == QSPI_CMD_RDID)
Alison Wang6b57ff62014-05-06 09:13:01 +0800649 qspi_op_rdid(qspi, din, bytes);
Peng Fan53e3db72014-12-31 11:01:36 +0800650 else if (qspi->cur_seqid == QSPI_CMD_RDSR)
Alison Wang6b57ff62014-05-06 09:13:01 +0800651 qspi_op_rdsr(qspi, din);
Peng Fana2358782015-01-04 17:07:14 +0800652#ifdef CONFIG_SPI_FLASH_BAR
653 else if ((qspi->cur_seqid == QSPI_CMD_BRRD) ||
654 (qspi->cur_seqid == QSPI_CMD_RDEAR)) {
655 qspi->sf_addr = 0;
656 qspi_op_rdbank(qspi, din, bytes);
657 }
658#endif
Alison Wang6b57ff62014-05-06 09:13:01 +0800659 }
660
661 return 0;
662}
663
664void spi_release_bus(struct spi_slave *slave)
665{
666 /* Nothing to do */
667}