blob: 5e0b0692747cb7791c38e33783c515629f8ba6ff [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
Peng Fan5f7f70c2015-01-08 10:40:20 +0800266#if defined(CONFIG_SYS_FSL_QSPI_AHB)
267/*
268 * If we have changed the content of the flash by writing or erasing,
269 * we need to invalidate the AHB buffer. If we do not do so, we may read out
270 * the wrong data. The spec tells us reset the AHB domain and Serial Flash
271 * domain at the same time.
272 */
273static inline void qspi_ahb_invalid(struct fsl_qspi *q)
274{
275 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)q->reg_base;
276 u32 reg;
277
278 reg = qspi_read32(&regs->mcr);
279 reg |= QSPI_MCR_SWRSTHD_MASK | QSPI_MCR_SWRSTSD_MASK;
280 qspi_write32(&regs->mcr, reg);
281
282 /*
283 * The minimum delay : 1 AHB + 2 SFCK clocks.
284 * Delay 1 us is enough.
285 */
286 udelay(1);
287
288 reg &= ~(QSPI_MCR_SWRSTHD_MASK | QSPI_MCR_SWRSTSD_MASK);
289 qspi_write32(&regs->mcr, reg);
290}
291
292/* Read out the data from the AHB buffer. */
293static inline void qspi_ahb_read(struct fsl_qspi *q, u8 *rxbuf, int len)
294{
295 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)q->reg_base;
296 u32 mcr_reg;
297
298 mcr_reg = qspi_read32(&regs->mcr);
299
300 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
301 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
302
303 /* Read out the data directly from the AHB buffer. */
304 memcpy(rxbuf, (u8 *)(q->amba_base + q->sf_addr), len);
305
306 qspi_write32(&regs->mcr, mcr_reg);
307}
308
309static void qspi_enable_ddr_mode(struct fsl_qspi_regs *regs)
310{
311 u32 reg, reg2;
312
313 reg = qspi_read32(&regs->mcr);
314 /* Disable the module */
315 qspi_write32(&regs->mcr, reg | QSPI_MCR_MDIS_MASK);
316
317 /* Set the Sampling Register for DDR */
318 reg2 = qspi_read32(&regs->smpr);
319 reg2 &= ~QSPI_SMPR_DDRSMP_MASK;
320 reg2 |= (2 << QSPI_SMPR_DDRSMP_SHIFT);
321 qspi_write32(&regs->smpr, reg2);
322
323 /* Enable the module again (enable the DDR too) */
324 reg |= QSPI_MCR_DDR_EN_MASK;
325 /* Enable bit 29 for imx6sx */
326 reg |= (1 << 29);
327
328 qspi_write32(&regs->mcr, reg);
329}
330
331/*
332 * There are two different ways to read out the data from the flash:
333 * the "IP Command Read" and the "AHB Command Read".
334 *
335 * The IC guy suggests we use the "AHB Command Read" which is faster
336 * then the "IP Command Read". (What's more is that there is a bug in
337 * the "IP Command Read" in the Vybrid.)
338 *
339 * After we set up the registers for the "AHB Command Read", we can use
340 * the memcpy to read the data directly. A "missed" access to the buffer
341 * causes the controller to clear the buffer, and use the sequence pointed
342 * by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash.
343 */
344static void qspi_init_ahb_read(struct fsl_qspi_regs *regs)
345{
346 /* AHB configuration for access buffer 0/1/2 .*/
347 qspi_write32(&regs->buf0cr, QSPI_BUFXCR_INVALID_MSTRID);
348 qspi_write32(&regs->buf1cr, QSPI_BUFXCR_INVALID_MSTRID);
349 qspi_write32(&regs->buf2cr, QSPI_BUFXCR_INVALID_MSTRID);
350 qspi_write32(&regs->buf3cr, QSPI_BUF3CR_ALLMST_MASK |
351 (0x80 << QSPI_BUF3CR_ADATSZ_SHIFT));
352
353 /* We only use the buffer3 */
354 qspi_write32(&regs->buf0ind, 0);
355 qspi_write32(&regs->buf1ind, 0);
356 qspi_write32(&regs->buf2ind, 0);
357
358 /*
359 * Set the default lut sequence for AHB Read.
360 * Parallel mode is disabled.
361 */
362 qspi_write32(&regs->bfgencr,
363 SEQID_FAST_READ << QSPI_BFGENCR_SEQID_SHIFT);
364
365 /*Enable DDR Mode*/
366 qspi_enable_ddr_mode(regs);
367}
368#endif
369
Alison Wang6b57ff62014-05-06 09:13:01 +0800370void spi_init()
371{
372 /* do nothing */
373}
374
375struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
376 unsigned int max_hz, unsigned int mode)
377{
378 struct fsl_qspi *qspi;
379 struct fsl_qspi_regs *regs;
Peng Fan5f7f70c2015-01-08 10:40:20 +0800380 u32 smpr_val;
381 u32 total_size;
Alison Wang6b57ff62014-05-06 09:13:01 +0800382
383 if (bus >= ARRAY_SIZE(spi_bases))
384 return NULL;
385
Peng Faned0c81c2014-12-31 11:01:37 +0800386 if (cs >= FSL_QSPI_FLASH_NUM)
387 return NULL;
388
Alison Wang6b57ff62014-05-06 09:13:01 +0800389 qspi = spi_alloc_slave(struct fsl_qspi, bus, cs);
390 if (!qspi)
391 return NULL;
392
393 qspi->reg_base = spi_bases[bus];
Peng Faned0c81c2014-12-31 11:01:37 +0800394 /*
395 * According cs, use different amba_base to choose the
396 * corresponding flash devices.
397 *
398 * If not, only one flash device is used even if passing
399 * different cs using `sf probe`
400 */
401 qspi->amba_base = amba_bases[bus] + cs * FSL_QSPI_FLASH_SIZE;
Alison Wang6b57ff62014-05-06 09:13:01 +0800402
403 qspi->slave.max_write_size = TX_BUFFER_SIZE;
404
405 regs = (struct fsl_qspi_regs *)qspi->reg_base;
406 qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK);
407
408 smpr_val = qspi_read32(&regs->smpr);
409 qspi_write32(&regs->smpr, smpr_val & ~(QSPI_SMPR_FSDLY_MASK |
410 QSPI_SMPR_FSPHS_MASK | QSPI_SMPR_HSENA_MASK));
411 qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK);
412
413 total_size = FSL_QSPI_FLASH_SIZE * FSL_QSPI_FLASH_NUM;
Peng Faned0c81c2014-12-31 11:01:37 +0800414 /*
415 * Any read access to non-implemented addresses will provide
416 * undefined results.
417 *
418 * In case single die flash devices, TOP_ADDR_MEMA2 and
419 * TOP_ADDR_MEMB2 should be initialized/programmed to
420 * TOP_ADDR_MEMA1 and TOP_ADDR_MEMB1 respectively - in effect,
421 * setting the size of these devices to 0. This would ensure
422 * that the complete memory map is assigned to only one flash device.
423 */
424 qspi_write32(&regs->sfa1ad, FSL_QSPI_FLASH_SIZE | amba_bases[bus]);
425 qspi_write32(&regs->sfa2ad, FSL_QSPI_FLASH_SIZE | amba_bases[bus]);
426 qspi_write32(&regs->sfb1ad, total_size | amba_bases[bus]);
427 qspi_write32(&regs->sfb2ad, total_size | amba_bases[bus]);
Alison Wang6b57ff62014-05-06 09:13:01 +0800428
429 qspi_set_lut(qspi);
430
431 smpr_val = qspi_read32(&regs->smpr);
432 smpr_val &= ~QSPI_SMPR_DDRSMP_MASK;
433 qspi_write32(&regs->smpr, smpr_val);
434 qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK);
435
Peng Fan5f7f70c2015-01-08 10:40:20 +0800436#ifdef CONFIG_SYS_FSL_QSPI_AHB
437 qspi_init_ahb_read(regs);
438#endif
Alison Wang6b57ff62014-05-06 09:13:01 +0800439 return &qspi->slave;
440}
441
442void spi_free_slave(struct spi_slave *slave)
443{
444 struct fsl_qspi *qspi = to_qspi_spi(slave);
445
446 free(qspi);
447}
448
449int spi_claim_bus(struct spi_slave *slave)
450{
451 return 0;
452}
453
Peng Fana2358782015-01-04 17:07:14 +0800454#ifdef CONFIG_SPI_FLASH_BAR
455/* Bank register read/write, EAR register read/write */
456static void qspi_op_rdbank(struct fsl_qspi *qspi, u8 *rxbuf, u32 len)
457{
458 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
459 u32 reg, mcr_reg, data, seqid;
460
461 mcr_reg = qspi_read32(&regs->mcr);
462 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
463 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
464 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
465
466 qspi_write32(&regs->sfar, qspi->amba_base);
467
468 if (qspi->cur_seqid == QSPI_CMD_BRRD)
469 seqid = SEQID_BRRD;
470 else
471 seqid = SEQID_RDEAR;
472
473 qspi_write32(&regs->ipcr, (seqid << QSPI_IPCR_SEQID_SHIFT) | len);
474
475 /* Wait previous command complete */
476 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
477 ;
478
479 while (1) {
480 reg = qspi_read32(&regs->rbsr);
481 if (reg & QSPI_RBSR_RDBFL_MASK) {
482 data = qspi_read32(&regs->rbdr[0]);
483 data = qspi_endian_xchg(data);
484 memcpy(rxbuf, &data, len);
485 qspi_write32(&regs->mcr, qspi_read32(&regs->mcr) |
486 QSPI_MCR_CLR_RXF_MASK);
487 break;
488 }
489 }
490
491 qspi_write32(&regs->mcr, mcr_reg);
492}
493#endif
494
Alison Wang6b57ff62014-05-06 09:13:01 +0800495static void qspi_op_rdid(struct fsl_qspi *qspi, u32 *rxbuf, u32 len)
496{
497 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
498 u32 mcr_reg, rbsr_reg, data;
499 int i, size;
500
501 mcr_reg = qspi_read32(&regs->mcr);
502 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
503 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
504 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
505
506 qspi_write32(&regs->sfar, qspi->amba_base);
507
508 qspi_write32(&regs->ipcr, (SEQID_RDID << QSPI_IPCR_SEQID_SHIFT) | 0);
509 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
510 ;
511
512 i = 0;
513 size = len;
514 while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
515 rbsr_reg = qspi_read32(&regs->rbsr);
516 if (rbsr_reg & QSPI_RBSR_RDBFL_MASK) {
517 data = qspi_read32(&regs->rbdr[i]);
518 data = qspi_endian_xchg(data);
519 memcpy(rxbuf, &data, 4);
520 rxbuf++;
521 size -= 4;
522 i++;
523 }
524 }
525
526 qspi_write32(&regs->mcr, mcr_reg);
527}
528
Peng Fan5f7f70c2015-01-08 10:40:20 +0800529#ifndef CONFIG_SYS_FSL_QSPI_AHB
530/* If not use AHB read, read data from ip interface */
Alison Wang6b57ff62014-05-06 09:13:01 +0800531static void qspi_op_read(struct fsl_qspi *qspi, u32 *rxbuf, u32 len)
532{
533 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
534 u32 mcr_reg, data;
535 int i, size;
536 u32 to_or_from;
537
538 mcr_reg = qspi_read32(&regs->mcr);
539 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
540 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
541 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
542
543 to_or_from = qspi->sf_addr + qspi->amba_base;
544
545 while (len > 0) {
546 qspi_write32(&regs->sfar, to_or_from);
547
548 size = (len > RX_BUFFER_SIZE) ?
549 RX_BUFFER_SIZE : len;
550
551 qspi_write32(&regs->ipcr,
552 (SEQID_FAST_READ << QSPI_IPCR_SEQID_SHIFT) | size);
553 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
554 ;
555
556 to_or_from += size;
557 len -= size;
558
559 i = 0;
560 while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
561 data = qspi_read32(&regs->rbdr[i]);
562 data = qspi_endian_xchg(data);
563 memcpy(rxbuf, &data, 4);
564 rxbuf++;
565 size -= 4;
566 i++;
567 }
568 qspi_write32(&regs->mcr, qspi_read32(&regs->mcr) |
569 QSPI_MCR_CLR_RXF_MASK);
570 }
571
572 qspi_write32(&regs->mcr, mcr_reg);
573}
Peng Fan5f7f70c2015-01-08 10:40:20 +0800574#endif
Alison Wang6b57ff62014-05-06 09:13:01 +0800575
Peng Fana2358782015-01-04 17:07:14 +0800576static void qspi_op_write(struct fsl_qspi *qspi, u8 *txbuf, u32 len)
Alison Wang6b57ff62014-05-06 09:13:01 +0800577{
578 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
Peng Fana2358782015-01-04 17:07:14 +0800579 u32 mcr_reg, data, reg, status_reg, seqid;
Alison Wang6b57ff62014-05-06 09:13:01 +0800580 int i, size, tx_size;
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 status_reg = 0;
589 while ((status_reg & FLASH_STATUS_WEL) != FLASH_STATUS_WEL) {
590 qspi_write32(&regs->ipcr,
591 (SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0);
592 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
593 ;
594
595 qspi_write32(&regs->ipcr,
596 (SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 1);
597 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
598 ;
599
600 reg = qspi_read32(&regs->rbsr);
601 if (reg & QSPI_RBSR_RDBFL_MASK) {
602 status_reg = qspi_read32(&regs->rbdr[0]);
603 status_reg = qspi_endian_xchg(status_reg);
604 }
605 qspi_write32(&regs->mcr,
606 qspi_read32(&regs->mcr) | QSPI_MCR_CLR_RXF_MASK);
607 }
608
Peng Fana2358782015-01-04 17:07:14 +0800609 /* Default is page programming */
610 seqid = SEQID_PP;
611#ifdef CONFIG_SPI_FLASH_BAR
612 if (qspi->cur_seqid == QSPI_CMD_BRWR)
613 seqid = SEQID_BRWR;
614 else if (qspi->cur_seqid == QSPI_CMD_WREAR)
615 seqid = SEQID_WREAR;
616#endif
617
Alison Wang6b57ff62014-05-06 09:13:01 +0800618 to_or_from = qspi->sf_addr + qspi->amba_base;
Peng Fana2358782015-01-04 17:07:14 +0800619
Alison Wang6b57ff62014-05-06 09:13:01 +0800620 qspi_write32(&regs->sfar, to_or_from);
621
622 tx_size = (len > TX_BUFFER_SIZE) ?
623 TX_BUFFER_SIZE : len;
624
Peng Fana2358782015-01-04 17:07:14 +0800625 size = tx_size / 4;
Alison Wang6b57ff62014-05-06 09:13:01 +0800626 for (i = 0; i < size; i++) {
Peng Fana2358782015-01-04 17:07:14 +0800627 memcpy(&data, txbuf, 4);
628 data = qspi_endian_xchg(data);
Alison Wang6b57ff62014-05-06 09:13:01 +0800629 qspi_write32(&regs->tbdr, data);
Peng Fana2358782015-01-04 17:07:14 +0800630 txbuf += 4;
Alison Wang6b57ff62014-05-06 09:13:01 +0800631 }
632
Peng Fana2358782015-01-04 17:07:14 +0800633 size = tx_size % 4;
634 if (size) {
635 data = 0;
636 memcpy(&data, txbuf, size);
637 data = qspi_endian_xchg(data);
638 qspi_write32(&regs->tbdr, data);
639 }
640
641 qspi_write32(&regs->ipcr, (seqid << QSPI_IPCR_SEQID_SHIFT) | tx_size);
Alison Wang6b57ff62014-05-06 09:13:01 +0800642 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
643 ;
644
645 qspi_write32(&regs->mcr, mcr_reg);
646}
647
648static void qspi_op_rdsr(struct fsl_qspi *qspi, u32 *rxbuf)
649{
650 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
651 u32 mcr_reg, reg, data;
652
653 mcr_reg = qspi_read32(&regs->mcr);
654 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
655 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
656 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
657
658 qspi_write32(&regs->sfar, qspi->amba_base);
659
660 qspi_write32(&regs->ipcr,
661 (SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 0);
662 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
663 ;
664
665 while (1) {
666 reg = qspi_read32(&regs->rbsr);
667 if (reg & QSPI_RBSR_RDBFL_MASK) {
668 data = qspi_read32(&regs->rbdr[0]);
669 data = qspi_endian_xchg(data);
670 memcpy(rxbuf, &data, 4);
671 qspi_write32(&regs->mcr, qspi_read32(&regs->mcr) |
672 QSPI_MCR_CLR_RXF_MASK);
673 break;
674 }
675 }
676
677 qspi_write32(&regs->mcr, mcr_reg);
678}
679
Peng Fanba4dc8a2014-12-31 11:01:39 +0800680static void qspi_op_erase(struct fsl_qspi *qspi)
Alison Wang6b57ff62014-05-06 09:13:01 +0800681{
682 struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
683 u32 mcr_reg;
684 u32 to_or_from = 0;
685
686 mcr_reg = qspi_read32(&regs->mcr);
687 qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
688 QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
689 qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
690
691 to_or_from = qspi->sf_addr + qspi->amba_base;
692 qspi_write32(&regs->sfar, to_or_from);
693
694 qspi_write32(&regs->ipcr,
695 (SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0);
696 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
697 ;
698
Peng Fanba4dc8a2014-12-31 11:01:39 +0800699 if (qspi->cur_seqid == QSPI_CMD_SE) {
700 qspi_write32(&regs->ipcr,
701 (SEQID_SE << QSPI_IPCR_SEQID_SHIFT) | 0);
702 } else if (qspi->cur_seqid == QSPI_CMD_BE_4K) {
703 qspi_write32(&regs->ipcr,
704 (SEQID_BE_4K << QSPI_IPCR_SEQID_SHIFT) | 0);
705 }
Alison Wang6b57ff62014-05-06 09:13:01 +0800706 while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
707 ;
708
709 qspi_write32(&regs->mcr, mcr_reg);
710}
711
712int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
713 const void *dout, void *din, unsigned long flags)
714{
715 struct fsl_qspi *qspi = to_qspi_spi(slave);
716 u32 bytes = DIV_ROUND_UP(bitlen, 8);
Peng Fana2358782015-01-04 17:07:14 +0800717 static u32 wr_sfaddr;
Alison Wang6b57ff62014-05-06 09:13:01 +0800718 u32 txbuf;
719
720 if (dout) {
Peng Fana2358782015-01-04 17:07:14 +0800721 if (flags & SPI_XFER_BEGIN) {
722 qspi->cur_seqid = *(u8 *)dout;
723 memcpy(&txbuf, dout, 4);
724 }
Alison Wang6b57ff62014-05-06 09:13:01 +0800725
726 if (flags == SPI_XFER_END) {
Peng Fana2358782015-01-04 17:07:14 +0800727 qspi->sf_addr = wr_sfaddr;
728 qspi_op_write(qspi, (u8 *)dout, bytes);
Alison Wang6b57ff62014-05-06 09:13:01 +0800729 return 0;
730 }
731
Peng Fan53e3db72014-12-31 11:01:36 +0800732 if (qspi->cur_seqid == QSPI_CMD_FAST_READ) {
Alison Wang6b57ff62014-05-06 09:13:01 +0800733 qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
Peng Fanba4dc8a2014-12-31 11:01:39 +0800734 } else if ((qspi->cur_seqid == QSPI_CMD_SE) ||
735 (qspi->cur_seqid == QSPI_CMD_BE_4K)) {
Alison Wang6b57ff62014-05-06 09:13:01 +0800736 qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
Peng Fanba4dc8a2014-12-31 11:01:39 +0800737 qspi_op_erase(qspi);
Peng Fana2358782015-01-04 17:07:14 +0800738 } else if (qspi->cur_seqid == QSPI_CMD_PP)
739 wr_sfaddr = swab32(txbuf) & OFFSET_BITS_MASK;
740#ifdef CONFIG_SPI_FLASH_BAR
741 else if ((qspi->cur_seqid == QSPI_CMD_BRWR) ||
742 (qspi->cur_seqid == QSPI_CMD_WREAR)) {
743 wr_sfaddr = 0;
Alison Wang6b57ff62014-05-06 09:13:01 +0800744 }
Peng Fana2358782015-01-04 17:07:14 +0800745#endif
Alison Wang6b57ff62014-05-06 09:13:01 +0800746 }
747
748 if (din) {
Peng Fan5f7f70c2015-01-08 10:40:20 +0800749 if (qspi->cur_seqid == QSPI_CMD_FAST_READ) {
750#ifdef CONFIG_SYS_FSL_QSPI_AHB
751 qspi_ahb_read(qspi, din, bytes);
752#else
Alison Wang6b57ff62014-05-06 09:13:01 +0800753 qspi_op_read(qspi, din, bytes);
Peng Fan5f7f70c2015-01-08 10:40:20 +0800754#endif
755 }
Peng Fan53e3db72014-12-31 11:01:36 +0800756 else if (qspi->cur_seqid == QSPI_CMD_RDID)
Alison Wang6b57ff62014-05-06 09:13:01 +0800757 qspi_op_rdid(qspi, din, bytes);
Peng Fan53e3db72014-12-31 11:01:36 +0800758 else if (qspi->cur_seqid == QSPI_CMD_RDSR)
Alison Wang6b57ff62014-05-06 09:13:01 +0800759 qspi_op_rdsr(qspi, din);
Peng Fana2358782015-01-04 17:07:14 +0800760#ifdef CONFIG_SPI_FLASH_BAR
761 else if ((qspi->cur_seqid == QSPI_CMD_BRRD) ||
762 (qspi->cur_seqid == QSPI_CMD_RDEAR)) {
763 qspi->sf_addr = 0;
764 qspi_op_rdbank(qspi, din, bytes);
765 }
766#endif
Alison Wang6b57ff62014-05-06 09:13:01 +0800767 }
768
Peng Fan5f7f70c2015-01-08 10:40:20 +0800769#ifdef CONFIG_SYS_FSL_QSPI_AHB
770 if ((qspi->cur_seqid == QSPI_CMD_SE) ||
771 (qspi->cur_seqid == QSPI_CMD_PP) ||
772 (qspi->cur_seqid == QSPI_CMD_BE_4K) ||
773 (qspi->cur_seqid == QSPI_CMD_WREAR) ||
774 (qspi->cur_seqid == QSPI_CMD_BRWR))
775 qspi_ahb_invalid(qspi);
776#endif
777
Alison Wang6b57ff62014-05-06 09:13:01 +0800778 return 0;
779}
780
781void spi_release_bus(struct spi_slave *slave)
782{
783 /* Nothing to do */
784}