]>
Commit | Line | Data |
---|---|---|
36fab997 | 1 | /* |
cfcbf8c4 | 2 | * Copyright 2004-2007 Freescale Semiconductor, Inc. |
36fab997 IY |
3 | * Copyright 2008 Sascha Hauer, kernel@pengutronix.de |
4 | * Copyright 2009 Ilya Yanok, <yanok@emcraft.com> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License | |
8 | * as published by the Free Software Foundation; either version 2 | |
9 | * of the License, or (at your option) any later version. | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program; if not, write to the Free Software | |
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |
18 | * MA 02110-1301, USA. | |
19 | */ | |
20 | ||
21 | #include <common.h> | |
22 | #include <nand.h> | |
23 | #include <linux/err.h> | |
24 | #include <asm/io.h> | |
58c758fe | 25 | #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35) |
36fab997 IY |
26 | #include <asm/arch/imx-regs.h> |
27 | #endif | |
28 | ||
29 | #define DRIVER_NAME "mxc_nand" | |
30 | ||
b081c2e9 JR |
31 | /* |
32 | * TODO: Use same register defs here as nand_spl mxc nand driver. | |
33 | */ | |
34 | /* | |
35 | * Register map and bit definitions for the Freescale NAND Flash Controller | |
36 | * present in various i.MX devices. | |
37 | * | |
38 | * MX31 and MX27 have version 1 which has | |
39 | * 4 512 byte main buffers and | |
40 | * 4 16 byte spare buffers | |
41 | * to support up to 2K byte pagesize nand. | |
42 | * Reading or writing a 2K page requires 4 FDI/FDO cycles. | |
43 | * | |
44 | * MX25 has version 1.1 which has | |
45 | * 8 512 byte main buffers and | |
46 | * 8 64 byte spare buffers | |
47 | * to support up to 4K byte pagesize nand. | |
48 | * Reading or writing a 2K or 4K page requires only 1 FDI/FDO cycle. | |
49 | * Also some of registers are moved and/or changed meaning as seen below. | |
50 | */ | |
51 | #if defined(CONFIG_MX31) || defined(CONFIG_MX27) | |
52 | #define MXC_NFC_V1 | |
58c758fe | 53 | #elif defined(CONFIG_MX25) || defined(CONFIG_MX35) |
b081c2e9 JR |
54 | #define MXC_NFC_V1_1 |
55 | #else | |
56 | #warning "MXC NFC version not defined" | |
57 | #endif | |
58 | ||
59 | #if defined(MXC_NFC_V1) | |
60 | #define NAND_MXC_NR_BUFS 4 | |
61 | #define NAND_MXC_SPARE_BUF_SIZE 16 | |
62 | #define NAND_MXC_REG_OFFSET 0xe00 | |
63 | #define is_mxc_nfc_11() 0 | |
64 | #elif defined(MXC_NFC_V1_1) | |
65 | #define NAND_MXC_NR_BUFS 8 | |
66 | #define NAND_MXC_SPARE_BUF_SIZE 64 | |
67 | #define NAND_MXC_REG_OFFSET 0x1e00 | |
68 | #define is_mxc_nfc_11() 1 | |
69 | #else | |
70 | #error "define CONFIG_NAND_MXC_VXXX to use mtd mxc nand driver" | |
71 | #endif | |
36fab997 | 72 | struct nfc_regs { |
b081c2e9 JR |
73 | uint8_t main_area[NAND_MXC_NR_BUFS][0x200]; |
74 | uint8_t spare_area[NAND_MXC_NR_BUFS][NAND_MXC_SPARE_BUF_SIZE]; | |
75 | /* | |
76 | * reserved size is offset of nfc registers | |
77 | * minus total main and spare sizes | |
78 | */ | |
79 | uint8_t reserved1[NAND_MXC_REG_OFFSET | |
80 | - NAND_MXC_NR_BUFS * (512 + NAND_MXC_SPARE_BUF_SIZE)]; | |
81 | #if defined(MXC_NFC_V1) | |
36fab997 | 82 | uint16_t nfc_buf_size; |
b081c2e9 | 83 | uint16_t reserved2; |
36fab997 IY |
84 | uint16_t nfc_buf_addr; |
85 | uint16_t nfc_flash_addr; | |
86 | uint16_t nfc_flash_cmd; | |
87 | uint16_t nfc_config; | |
88 | uint16_t nfc_ecc_status_result; | |
89 | uint16_t nfc_rsltmain_area; | |
90 | uint16_t nfc_rsltspare_area; | |
91 | uint16_t nfc_wrprot; | |
92 | uint16_t nfc_unlockstart_blkaddr; | |
93 | uint16_t nfc_unlockend_blkaddr; | |
94 | uint16_t nfc_nf_wrprst; | |
95 | uint16_t nfc_config1; | |
96 | uint16_t nfc_config2; | |
b081c2e9 JR |
97 | #elif defined(MXC_NFC_V1_1) |
98 | uint16_t reserved2[2]; | |
99 | uint16_t nfc_buf_addr; | |
100 | uint16_t nfc_flash_addr; | |
101 | uint16_t nfc_flash_cmd; | |
102 | uint16_t nfc_config; | |
103 | uint16_t nfc_ecc_status_result; | |
104 | uint16_t nfc_ecc_status_result2; | |
105 | uint16_t nfc_spare_area_size; | |
106 | uint16_t nfc_wrprot; | |
107 | uint16_t reserved3[2]; | |
108 | uint16_t nfc_nf_wrprst; | |
109 | uint16_t nfc_config1; | |
110 | uint16_t nfc_config2; | |
111 | uint16_t reserved4; | |
112 | uint16_t nfc_unlockstart_blkaddr; | |
113 | uint16_t nfc_unlockend_blkaddr; | |
114 | uint16_t nfc_unlockstart_blkaddr1; | |
115 | uint16_t nfc_unlockend_blkaddr1; | |
116 | uint16_t nfc_unlockstart_blkaddr2; | |
117 | uint16_t nfc_unlockend_blkaddr2; | |
118 | uint16_t nfc_unlockstart_blkaddr3; | |
119 | uint16_t nfc_unlockend_blkaddr3; | |
120 | #endif | |
36fab997 IY |
121 | }; |
122 | ||
123 | /* | |
124 | * Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register | |
125 | * for Command operation | |
126 | */ | |
127 | #define NFC_CMD 0x1 | |
128 | ||
129 | /* | |
130 | * Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register | |
131 | * for Address operation | |
132 | */ | |
133 | #define NFC_ADDR 0x2 | |
134 | ||
135 | /* | |
136 | * Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register | |
137 | * for Input operation | |
138 | */ | |
139 | #define NFC_INPUT 0x4 | |
140 | ||
141 | /* | |
142 | * Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register | |
143 | * for Data Output operation | |
144 | */ | |
145 | #define NFC_OUTPUT 0x8 | |
146 | ||
147 | /* | |
148 | * Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register | |
149 | * for Read ID operation | |
150 | */ | |
151 | #define NFC_ID 0x10 | |
152 | ||
153 | /* | |
154 | * Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register | |
155 | * for Read Status operation | |
156 | */ | |
157 | #define NFC_STATUS 0x20 | |
158 | ||
159 | /* | |
160 | * Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read | |
161 | * Status operation | |
162 | */ | |
163 | #define NFC_INT 0x8000 | |
164 | ||
b081c2e9 JR |
165 | #ifdef MXC_NFC_V1_1 |
166 | #define NFC_4_8N_ECC (1 << 0) | |
167 | #else | |
168 | #define NFC_4_8N_ECC 0 | |
169 | #endif | |
36fab997 IY |
170 | #define NFC_SP_EN (1 << 2) |
171 | #define NFC_ECC_EN (1 << 3) | |
172 | #define NFC_BIG (1 << 5) | |
173 | #define NFC_RST (1 << 6) | |
174 | #define NFC_CE (1 << 7) | |
175 | #define NFC_ONE_CYCLE (1 << 8) | |
176 | ||
177 | typedef enum {false, true} bool; | |
178 | ||
179 | struct mxc_nand_host { | |
180 | struct mtd_info mtd; | |
181 | struct nand_chip *nand; | |
182 | ||
183 | struct nfc_regs __iomem *regs; | |
184 | int spare_only; | |
185 | int status_request; | |
186 | int pagesize_2k; | |
187 | int clk_act; | |
188 | uint16_t col_addr; | |
b081c2e9 | 189 | unsigned int page_addr; |
36fab997 IY |
190 | }; |
191 | ||
192 | static struct mxc_nand_host mxc_host; | |
193 | static struct mxc_nand_host *host = &mxc_host; | |
194 | ||
195 | /* Define delays in microsec for NAND device operations */ | |
196 | #define TROP_US_DELAY 2000 | |
197 | /* Macros to get byte and bit positions of ECC */ | |
198 | #define COLPOS(x) ((x) >> 3) | |
199 | #define BITPOS(x) ((x) & 0xf) | |
200 | ||
201 | /* Define single bit Error positions in Main & Spare area */ | |
202 | #define MAIN_SINGLEBIT_ERROR 0x4 | |
203 | #define SPARE_SINGLEBIT_ERROR 0x1 | |
204 | ||
205 | /* OOB placement block for use with hardware ecc generation */ | |
b081c2e9 JR |
206 | #if defined(MXC_NFC_V1) |
207 | #ifndef CONFIG_SYS_NAND_LARGEPAGE | |
36fab997 IY |
208 | static struct nand_ecclayout nand_hw_eccoob = { |
209 | .eccbytes = 5, | |
210 | .eccpos = {6, 7, 8, 9, 10}, | |
b081c2e9 | 211 | .oobfree = { {0, 5}, {11, 5}, } |
36fab997 IY |
212 | }; |
213 | #else | |
b081c2e9 JR |
214 | static struct nand_ecclayout nand_hw_eccoob2k = { |
215 | .eccbytes = 20, | |
216 | .eccpos = { | |
217 | 6, 7, 8, 9, 10, | |
218 | 22, 23, 24, 25, 26, | |
219 | 38, 39, 40, 41, 42, | |
220 | 54, 55, 56, 57, 58, | |
221 | }, | |
222 | .oobfree = { {2, 4}, {11, 11}, {27, 11}, {43, 11}, {59, 5} }, | |
36fab997 IY |
223 | }; |
224 | #endif | |
b081c2e9 JR |
225 | #elif defined(MXC_NFC_V1_1) |
226 | #ifndef CONFIG_SYS_NAND_LARGEPAGE | |
227 | static struct nand_ecclayout nand_hw_eccoob = { | |
228 | .eccbytes = 9, | |
229 | .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, | |
230 | .oobfree = { {2, 5} } | |
c4832dff | 231 | }; |
b081c2e9 JR |
232 | #else |
233 | static struct nand_ecclayout nand_hw_eccoob2k = { | |
234 | .eccbytes = 36, | |
235 | .eccpos = { | |
236 | 7, 8, 9, 10, 11, 12, 13, 14, 15, | |
237 | 23, 24, 25, 26, 27, 28, 29, 30, 31, | |
238 | 39, 40, 41, 42, 43, 44, 45, 46, 47, | |
239 | 55, 56, 57, 58, 59, 60, 61, 62, 63, | |
240 | }, | |
241 | .oobfree = { {2, 5}, {16, 7}, {32, 7}, {48, 7} }, | |
242 | }; | |
243 | #endif | |
244 | #endif | |
c4832dff | 245 | |
f6a9748e ML |
246 | #ifdef CONFIG_MX27 |
247 | static int is_16bit_nand(void) | |
248 | { | |
249 | struct system_control_regs *sc_regs = | |
250 | (struct system_control_regs *)IMX_SYSTEM_CTL_BASE; | |
251 | ||
252 | if (readl(&sc_regs->fmcr) & NF_16BIT_SEL) | |
253 | return 1; | |
254 | else | |
255 | return 0; | |
256 | } | |
257 | #elif defined(CONFIG_MX31) | |
258 | static int is_16bit_nand(void) | |
259 | { | |
260 | struct clock_control_regs *sc_regs = | |
261 | (struct clock_control_regs *)CCM_BASE; | |
262 | ||
263 | if (readl(&sc_regs->rcsr) & CCM_RCSR_NF16B) | |
264 | return 1; | |
265 | else | |
266 | return 0; | |
267 | } | |
58c758fe | 268 | #elif defined(CONFIG_MX25) || defined(CONFIG_MX35) |
b081c2e9 JR |
269 | static int is_16bit_nand(void) |
270 | { | |
271 | struct ccm_regs *ccm = | |
272 | (struct ccm_regs *)IMX_CCM_BASE; | |
273 | ||
274 | if (readl(&ccm->rcsr) & CCM_RCSR_NF_16BIT_SEL) | |
275 | return 1; | |
276 | else | |
277 | return 0; | |
278 | } | |
f6a9748e ML |
279 | #else |
280 | #warning "8/16 bit NAND autodetection not supported" | |
281 | static int is_16bit_nand(void) | |
282 | { | |
283 | return 0; | |
284 | } | |
285 | #endif | |
286 | ||
36fab997 IY |
287 | static uint32_t *mxc_nand_memcpy32(uint32_t *dest, uint32_t *source, size_t size) |
288 | { | |
289 | uint32_t *d = dest; | |
290 | ||
291 | size >>= 2; | |
292 | while (size--) | |
293 | __raw_writel(__raw_readl(source++), d++); | |
294 | return dest; | |
295 | } | |
296 | ||
297 | /* | |
298 | * This function polls the NANDFC to wait for the basic operation to | |
299 | * complete by checking the INT bit of config2 register. | |
300 | */ | |
301 | static void wait_op_done(struct mxc_nand_host *host, int max_retries, | |
302 | uint16_t param) | |
303 | { | |
304 | uint32_t tmp; | |
305 | ||
306 | while (max_retries-- > 0) { | |
307 | if (readw(&host->regs->nfc_config2) & NFC_INT) { | |
308 | tmp = readw(&host->regs->nfc_config2); | |
309 | tmp &= ~NFC_INT; | |
310 | writew(tmp, &host->regs->nfc_config2); | |
311 | break; | |
312 | } | |
313 | udelay(1); | |
314 | } | |
315 | if (max_retries < 0) { | |
316 | MTDDEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n", | |
317 | __func__, param); | |
318 | } | |
319 | } | |
320 | ||
321 | /* | |
322 | * This function issues the specified command to the NAND device and | |
323 | * waits for completion. | |
324 | */ | |
325 | static void send_cmd(struct mxc_nand_host *host, uint16_t cmd) | |
326 | { | |
327 | MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd); | |
328 | ||
329 | writew(cmd, &host->regs->nfc_flash_cmd); | |
330 | writew(NFC_CMD, &host->regs->nfc_config2); | |
331 | ||
332 | /* Wait for operation to complete */ | |
333 | wait_op_done(host, TROP_US_DELAY, cmd); | |
334 | } | |
335 | ||
336 | /* | |
337 | * This function sends an address (or partial address) to the | |
338 | * NAND device. The address is used to select the source/destination for | |
339 | * a NAND command. | |
340 | */ | |
341 | static void send_addr(struct mxc_nand_host *host, uint16_t addr) | |
342 | { | |
343 | MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x)\n", addr); | |
344 | ||
345 | writew(addr, &host->regs->nfc_flash_addr); | |
346 | writew(NFC_ADDR, &host->regs->nfc_config2); | |
347 | ||
348 | /* Wait for operation to complete */ | |
349 | wait_op_done(host, TROP_US_DELAY, addr); | |
350 | } | |
351 | ||
352 | /* | |
353 | * This function requests the NANDFC to initate the transfer | |
354 | * of data currently in the NANDFC RAM buffer to the NAND device. | |
355 | */ | |
356 | static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, | |
357 | int spare_only) | |
358 | { | |
b081c2e9 JR |
359 | if (spare_only) |
360 | MTDDEBUG(MTD_DEBUG_LEVEL1, "send_prog_page (%d)\n", spare_only); | |
361 | ||
362 | if (is_mxc_nfc_11()) { | |
363 | int i; | |
364 | /* | |
365 | * The controller copies the 64 bytes of spare data from | |
366 | * the first 16 bytes of each of the 4 64 byte spare buffers. | |
367 | * Copy the contiguous data starting in spare_area[0] to | |
368 | * the four spare area buffers. | |
369 | */ | |
370 | for (i = 1; i < 4; i++) { | |
371 | void __iomem *src = &host->regs->spare_area[0][i * 16]; | |
372 | void __iomem *dst = &host->regs->spare_area[i][0]; | |
373 | ||
374 | mxc_nand_memcpy32(dst, src, 16); | |
375 | } | |
376 | } | |
36fab997 IY |
377 | |
378 | writew(buf_id, &host->regs->nfc_buf_addr); | |
379 | ||
380 | /* Configure spare or page+spare access */ | |
381 | if (!host->pagesize_2k) { | |
382 | uint16_t config1 = readw(&host->regs->nfc_config1); | |
383 | if (spare_only) | |
384 | config1 |= NFC_SP_EN; | |
385 | else | |
386 | config1 &= ~(NFC_SP_EN); | |
387 | writew(config1, &host->regs->nfc_config1); | |
388 | } | |
389 | ||
390 | writew(NFC_INPUT, &host->regs->nfc_config2); | |
391 | ||
392 | /* Wait for operation to complete */ | |
393 | wait_op_done(host, TROP_US_DELAY, spare_only); | |
394 | } | |
395 | ||
396 | /* | |
397 | * Requests NANDFC to initated the transfer of data from the | |
398 | * NAND device into in the NANDFC ram buffer. | |
399 | */ | |
400 | static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id, | |
401 | int spare_only) | |
402 | { | |
403 | MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only); | |
404 | ||
405 | writew(buf_id, &host->regs->nfc_buf_addr); | |
406 | ||
407 | /* Configure spare or page+spare access */ | |
408 | if (!host->pagesize_2k) { | |
409 | uint32_t config1 = readw(&host->regs->nfc_config1); | |
410 | if (spare_only) | |
411 | config1 |= NFC_SP_EN; | |
412 | else | |
413 | config1 &= ~NFC_SP_EN; | |
414 | writew(config1, &host->regs->nfc_config1); | |
415 | } | |
416 | ||
417 | writew(NFC_OUTPUT, &host->regs->nfc_config2); | |
418 | ||
419 | /* Wait for operation to complete */ | |
420 | wait_op_done(host, TROP_US_DELAY, spare_only); | |
b081c2e9 JR |
421 | |
422 | if (is_mxc_nfc_11()) { | |
423 | int i; | |
424 | ||
425 | /* | |
426 | * The controller copies the 64 bytes of spare data to | |
427 | * the first 16 bytes of each of the 4 spare buffers. | |
428 | * Make the data contiguous starting in spare_area[0]. | |
429 | */ | |
430 | for (i = 1; i < 4; i++) { | |
431 | void __iomem *src = &host->regs->spare_area[i][0]; | |
432 | void __iomem *dst = &host->regs->spare_area[0][i * 16]; | |
433 | ||
434 | mxc_nand_memcpy32(dst, src, 16); | |
435 | } | |
436 | } | |
36fab997 IY |
437 | } |
438 | ||
439 | /* Request the NANDFC to perform a read of the NAND device ID. */ | |
440 | static void send_read_id(struct mxc_nand_host *host) | |
441 | { | |
442 | uint16_t tmp; | |
443 | ||
444 | /* NANDFC buffer 0 is used for device ID output */ | |
445 | writew(0x0, &host->regs->nfc_buf_addr); | |
446 | ||
447 | /* Read ID into main buffer */ | |
448 | tmp = readw(&host->regs->nfc_config1); | |
449 | tmp &= ~NFC_SP_EN; | |
450 | writew(tmp, &host->regs->nfc_config1); | |
451 | ||
452 | writew(NFC_ID, &host->regs->nfc_config2); | |
453 | ||
454 | /* Wait for operation to complete */ | |
455 | wait_op_done(host, TROP_US_DELAY, 0); | |
456 | } | |
457 | ||
458 | /* | |
459 | * This function requests the NANDFC to perform a read of the | |
460 | * NAND device status and returns the current status. | |
461 | */ | |
462 | static uint16_t get_dev_status(struct mxc_nand_host *host) | |
463 | { | |
b081c2e9 | 464 | void __iomem *main_buf = host->regs->main_area[1]; |
36fab997 IY |
465 | uint32_t store; |
466 | uint16_t ret, tmp; | |
467 | /* Issue status request to NAND device */ | |
468 | ||
469 | /* store the main area1 first word, later do recovery */ | |
470 | store = readl(main_buf); | |
471 | /* NANDFC buffer 1 is used for device status */ | |
472 | writew(1, &host->regs->nfc_buf_addr); | |
473 | ||
474 | /* Read status into main buffer */ | |
475 | tmp = readw(&host->regs->nfc_config1); | |
476 | tmp &= ~NFC_SP_EN; | |
477 | writew(tmp, &host->regs->nfc_config1); | |
478 | ||
479 | writew(NFC_STATUS, &host->regs->nfc_config2); | |
480 | ||
481 | /* Wait for operation to complete */ | |
482 | wait_op_done(host, TROP_US_DELAY, 0); | |
483 | ||
484 | /* | |
485 | * Status is placed in first word of main buffer | |
486 | * get status, then recovery area 1 data | |
487 | */ | |
488 | ret = readw(main_buf); | |
489 | writel(store, main_buf); | |
490 | ||
491 | return ret; | |
492 | } | |
493 | ||
494 | /* This function is used by upper layer to checks if device is ready */ | |
495 | static int mxc_nand_dev_ready(struct mtd_info *mtd) | |
496 | { | |
497 | /* | |
498 | * NFC handles R/B internally. Therefore, this function | |
499 | * always returns status as ready. | |
500 | */ | |
501 | return 1; | |
502 | } | |
503 | ||
504 | #ifdef CONFIG_MXC_NAND_HWECC | |
505 | static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) | |
506 | { | |
507 | /* | |
508 | * If HW ECC is enabled, we turn it on during init. There is | |
509 | * no need to enable again here. | |
510 | */ | |
511 | } | |
512 | ||
b081c2e9 JR |
513 | #ifdef MXC_NFC_V1_1 |
514 | static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on) | |
515 | { | |
516 | struct nand_chip *nand_chip = mtd->priv; | |
517 | struct mxc_nand_host *host = nand_chip->priv; | |
518 | uint16_t tmp = readw(&host->regs->nfc_config1); | |
519 | ||
520 | if (on) | |
521 | tmp |= NFC_ECC_EN; | |
522 | else | |
523 | tmp &= ~NFC_ECC_EN; | |
524 | writew(tmp, &host->regs->nfc_config1); | |
525 | } | |
526 | ||
527 | static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, | |
528 | struct nand_chip *chip, | |
529 | int page, int sndcmd) | |
530 | { | |
531 | struct mxc_nand_host *host = chip->priv; | |
532 | uint8_t *buf = chip->oob_poi; | |
533 | int length = mtd->oobsize; | |
534 | int eccpitch = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; | |
535 | uint8_t *bufpoi = buf; | |
536 | int i, toread; | |
537 | ||
538 | MTDDEBUG(MTD_DEBUG_LEVEL0, | |
539 | "%s: Reading OOB area of page %u to oob %p\n", | |
540 | __FUNCTION__, host->page_addr, buf); | |
541 | ||
542 | chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize, page); | |
543 | for (i = 0; i < chip->ecc.steps; i++) { | |
544 | toread = min_t(int, length, chip->ecc.prepad); | |
545 | if (toread) { | |
546 | chip->read_buf(mtd, bufpoi, toread); | |
547 | bufpoi += toread; | |
548 | length -= toread; | |
549 | } | |
550 | bufpoi += chip->ecc.bytes; | |
551 | host->col_addr += chip->ecc.bytes; | |
552 | length -= chip->ecc.bytes; | |
553 | ||
554 | toread = min_t(int, length, chip->ecc.postpad); | |
555 | if (toread) { | |
556 | chip->read_buf(mtd, bufpoi, toread); | |
557 | bufpoi += toread; | |
558 | length -= toread; | |
559 | } | |
560 | } | |
561 | if (length > 0) | |
562 | chip->read_buf(mtd, bufpoi, length); | |
563 | ||
564 | _mxc_nand_enable_hwecc(mtd, 0); | |
565 | chip->cmdfunc(mtd, NAND_CMD_READOOB, | |
566 | mtd->writesize + chip->ecc.prepad, page); | |
567 | bufpoi = buf + chip->ecc.prepad; | |
568 | length = mtd->oobsize - chip->ecc.prepad; | |
569 | for (i = 0; i < chip->ecc.steps; i++) { | |
570 | toread = min_t(int, length, chip->ecc.bytes); | |
571 | chip->read_buf(mtd, bufpoi, toread); | |
572 | bufpoi += eccpitch; | |
573 | length -= eccpitch; | |
574 | host->col_addr += chip->ecc.postpad + chip->ecc.prepad; | |
575 | } | |
576 | _mxc_nand_enable_hwecc(mtd, 1); | |
577 | return 1; | |
578 | } | |
579 | ||
580 | static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd, | |
581 | struct nand_chip *chip, | |
582 | uint8_t *buf, | |
583 | int page) | |
584 | { | |
585 | struct mxc_nand_host *host = chip->priv; | |
586 | int eccsize = chip->ecc.size; | |
587 | int eccbytes = chip->ecc.bytes; | |
588 | int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad; | |
589 | uint8_t *oob = chip->oob_poi; | |
590 | int steps, size; | |
591 | int n; | |
592 | ||
593 | _mxc_nand_enable_hwecc(mtd, 0); | |
594 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, host->page_addr); | |
595 | ||
596 | for (n = 0, steps = chip->ecc.steps; steps > 0; n++, steps--) { | |
597 | host->col_addr = n * eccsize; | |
598 | chip->read_buf(mtd, buf, eccsize); | |
599 | buf += eccsize; | |
600 | ||
601 | host->col_addr = mtd->writesize + n * eccpitch; | |
602 | if (chip->ecc.prepad) { | |
603 | chip->read_buf(mtd, oob, chip->ecc.prepad); | |
604 | oob += chip->ecc.prepad; | |
605 | } | |
606 | ||
607 | chip->read_buf(mtd, oob, eccbytes); | |
608 | oob += eccbytes; | |
609 | ||
610 | if (chip->ecc.postpad) { | |
611 | chip->read_buf(mtd, oob, chip->ecc.postpad); | |
612 | oob += chip->ecc.postpad; | |
613 | } | |
614 | } | |
615 | ||
616 | size = mtd->oobsize - (oob - chip->oob_poi); | |
617 | if (size) | |
618 | chip->read_buf(mtd, oob, size); | |
619 | _mxc_nand_enable_hwecc(mtd, 0); | |
620 | ||
621 | return 0; | |
622 | } | |
623 | ||
624 | static int mxc_nand_read_page_syndrome(struct mtd_info *mtd, | |
625 | struct nand_chip *chip, | |
626 | uint8_t *buf, | |
627 | int page) | |
628 | { | |
629 | struct mxc_nand_host *host = chip->priv; | |
630 | int n, eccsize = chip->ecc.size; | |
631 | int eccbytes = chip->ecc.bytes; | |
632 | int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad; | |
633 | int eccsteps = chip->ecc.steps; | |
634 | uint8_t *p = buf; | |
635 | uint8_t *oob = chip->oob_poi; | |
636 | ||
637 | MTDDEBUG(MTD_DEBUG_LEVEL1, "Reading page %u to buf %p oob %p\n", | |
638 | host->page_addr, buf, oob); | |
639 | ||
640 | /* first read out the data area and the available portion of OOB */ | |
641 | for (n = 0; eccsteps; n++, eccsteps--, p += eccsize) { | |
642 | int stat; | |
643 | ||
644 | host->col_addr = n * eccsize; | |
645 | ||
646 | chip->read_buf(mtd, p, eccsize); | |
647 | ||
648 | host->col_addr = mtd->writesize + n * eccpitch; | |
649 | ||
650 | if (chip->ecc.prepad) { | |
651 | chip->read_buf(mtd, oob, chip->ecc.prepad); | |
652 | oob += chip->ecc.prepad; | |
653 | } | |
654 | ||
655 | stat = chip->ecc.correct(mtd, p, oob, NULL); | |
656 | ||
657 | if (stat < 0) | |
658 | mtd->ecc_stats.failed++; | |
659 | else | |
660 | mtd->ecc_stats.corrected += stat; | |
661 | oob += eccbytes; | |
662 | ||
663 | if (chip->ecc.postpad) { | |
664 | chip->read_buf(mtd, oob, chip->ecc.postpad); | |
665 | oob += chip->ecc.postpad; | |
666 | } | |
667 | } | |
668 | ||
669 | /* Calculate remaining oob bytes */ | |
670 | n = mtd->oobsize - (oob - chip->oob_poi); | |
671 | if (n) | |
672 | chip->read_buf(mtd, oob, n); | |
673 | ||
674 | /* Then switch ECC off and read the OOB area to get the ECC code */ | |
675 | _mxc_nand_enable_hwecc(mtd, 0); | |
676 | chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize, host->page_addr); | |
677 | eccsteps = chip->ecc.steps; | |
678 | oob = chip->oob_poi + chip->ecc.prepad; | |
679 | for (n = 0; eccsteps; n++, eccsteps--, p += eccsize) { | |
680 | host->col_addr = mtd->writesize + | |
681 | n * eccpitch + | |
682 | chip->ecc.prepad; | |
683 | chip->read_buf(mtd, oob, eccbytes); | |
684 | oob += eccbytes + chip->ecc.postpad; | |
685 | } | |
686 | _mxc_nand_enable_hwecc(mtd, 1); | |
687 | return 0; | |
688 | } | |
689 | ||
690 | static int mxc_nand_write_oob_syndrome(struct mtd_info *mtd, | |
691 | struct nand_chip *chip, int page) | |
692 | { | |
693 | struct mxc_nand_host *host = chip->priv; | |
694 | int eccpitch = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; | |
695 | int length = mtd->oobsize; | |
696 | int i, len, status, steps = chip->ecc.steps; | |
697 | const uint8_t *bufpoi = chip->oob_poi; | |
698 | ||
699 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page); | |
700 | for (i = 0; i < steps; i++) { | |
701 | len = min_t(int, length, eccpitch); | |
702 | ||
703 | chip->write_buf(mtd, bufpoi, len); | |
704 | bufpoi += len; | |
705 | length -= len; | |
706 | host->col_addr += chip->ecc.prepad + chip->ecc.postpad; | |
707 | } | |
708 | if (length > 0) | |
709 | chip->write_buf(mtd, bufpoi, length); | |
710 | ||
711 | chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); | |
712 | status = chip->waitfunc(mtd, chip); | |
713 | return status & NAND_STATUS_FAIL ? -EIO : 0; | |
714 | } | |
715 | ||
716 | static void mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd, | |
717 | struct nand_chip *chip, | |
718 | const uint8_t *buf) | |
719 | { | |
720 | struct mxc_nand_host *host = chip->priv; | |
721 | int eccsize = chip->ecc.size; | |
722 | int eccbytes = chip->ecc.bytes; | |
723 | int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad; | |
724 | uint8_t *oob = chip->oob_poi; | |
725 | int steps, size; | |
726 | int n; | |
727 | ||
728 | for (n = 0, steps = chip->ecc.steps; steps > 0; n++, steps--) { | |
729 | host->col_addr = n * eccsize; | |
730 | chip->write_buf(mtd, buf, eccsize); | |
731 | buf += eccsize; | |
732 | ||
733 | host->col_addr = mtd->writesize + n * eccpitch; | |
734 | ||
735 | if (chip->ecc.prepad) { | |
736 | chip->write_buf(mtd, oob, chip->ecc.prepad); | |
737 | oob += chip->ecc.prepad; | |
738 | } | |
739 | ||
740 | host->col_addr += eccbytes; | |
741 | oob += eccbytes; | |
742 | ||
743 | if (chip->ecc.postpad) { | |
744 | chip->write_buf(mtd, oob, chip->ecc.postpad); | |
745 | oob += chip->ecc.postpad; | |
746 | } | |
747 | } | |
748 | ||
749 | size = mtd->oobsize - (oob - chip->oob_poi); | |
750 | if (size) | |
751 | chip->write_buf(mtd, oob, size); | |
752 | } | |
753 | ||
754 | static void mxc_nand_write_page_syndrome(struct mtd_info *mtd, | |
755 | struct nand_chip *chip, | |
756 | const uint8_t *buf) | |
757 | { | |
758 | struct mxc_nand_host *host = chip->priv; | |
759 | int i, n, eccsize = chip->ecc.size; | |
760 | int eccbytes = chip->ecc.bytes; | |
761 | int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad; | |
762 | int eccsteps = chip->ecc.steps; | |
763 | const uint8_t *p = buf; | |
764 | uint8_t *oob = chip->oob_poi; | |
765 | ||
766 | chip->ecc.hwctl(mtd, NAND_ECC_WRITE); | |
767 | ||
768 | for (i = n = 0; | |
769 | eccsteps; | |
770 | n++, eccsteps--, i += eccbytes, p += eccsize) { | |
771 | host->col_addr = n * eccsize; | |
772 | ||
773 | chip->write_buf(mtd, p, eccsize); | |
774 | ||
775 | host->col_addr = mtd->writesize + n * eccpitch; | |
776 | ||
777 | if (chip->ecc.prepad) { | |
778 | chip->write_buf(mtd, oob, chip->ecc.prepad); | |
779 | oob += chip->ecc.prepad; | |
780 | } | |
781 | ||
782 | chip->write_buf(mtd, oob, eccbytes); | |
783 | oob += eccbytes; | |
784 | ||
785 | if (chip->ecc.postpad) { | |
786 | chip->write_buf(mtd, oob, chip->ecc.postpad); | |
787 | oob += chip->ecc.postpad; | |
788 | } | |
789 | } | |
790 | ||
791 | /* Calculate remaining oob bytes */ | |
792 | i = mtd->oobsize - (oob - chip->oob_poi); | |
793 | if (i) | |
794 | chip->write_buf(mtd, oob, i); | |
795 | } | |
796 | ||
797 | static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, | |
798 | u_char *read_ecc, u_char *calc_ecc) | |
799 | { | |
800 | struct nand_chip *nand_chip = mtd->priv; | |
801 | struct mxc_nand_host *host = nand_chip->priv; | |
802 | uint16_t ecc_status = readw(&host->regs->nfc_ecc_status_result); | |
803 | int subpages = mtd->writesize / nand_chip->subpagesize; | |
804 | int pg2blk_shift = nand_chip->phys_erase_shift - | |
805 | nand_chip->page_shift; | |
806 | ||
807 | do { | |
808 | if ((ecc_status & 0xf) > 4) { | |
809 | static int last_bad = -1; | |
810 | ||
811 | if (last_bad != host->page_addr >> pg2blk_shift) { | |
812 | last_bad = host->page_addr >> pg2blk_shift; | |
813 | printk(KERN_DEBUG | |
814 | "MXC_NAND: HWECC uncorrectable ECC error" | |
815 | " in block %u page %u subpage %d\n", | |
816 | last_bad, host->page_addr, | |
817 | mtd->writesize / nand_chip->subpagesize | |
818 | - subpages); | |
819 | } | |
820 | return -1; | |
821 | } | |
822 | ecc_status >>= 4; | |
823 | subpages--; | |
824 | } while (subpages > 0); | |
825 | ||
826 | return 0; | |
827 | } | |
828 | #else | |
829 | #define mxc_nand_read_page_syndrome NULL | |
830 | #define mxc_nand_read_page_raw_syndrome NULL | |
831 | #define mxc_nand_read_oob_syndrome NULL | |
832 | #define mxc_nand_write_page_syndrome NULL | |
833 | #define mxc_nand_write_page_raw_syndrome NULL | |
834 | #define mxc_nand_write_oob_syndrome NULL | |
835 | #define mxc_nfc_11_nand_correct_data NULL | |
836 | ||
36fab997 IY |
837 | static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, |
838 | u_char *read_ecc, u_char *calc_ecc) | |
839 | { | |
840 | struct nand_chip *nand_chip = mtd->priv; | |
841 | struct mxc_nand_host *host = nand_chip->priv; | |
842 | ||
843 | /* | |
844 | * 1-Bit errors are automatically corrected in HW. No need for | |
845 | * additional correction. 2-Bit errors cannot be corrected by | |
846 | * HW ECC, so we need to return failure | |
847 | */ | |
848 | uint16_t ecc_status = readw(&host->regs->nfc_ecc_status_result); | |
849 | ||
850 | if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { | |
851 | MTDDEBUG(MTD_DEBUG_LEVEL0, | |
852 | "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); | |
853 | return -1; | |
854 | } | |
855 | ||
856 | return 0; | |
857 | } | |
b081c2e9 JR |
858 | #endif |
859 | ||
36fab997 IY |
860 | static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, |
861 | u_char *ecc_code) | |
862 | { | |
863 | return 0; | |
864 | } | |
865 | #endif | |
866 | ||
867 | static u_char mxc_nand_read_byte(struct mtd_info *mtd) | |
868 | { | |
869 | struct nand_chip *nand_chip = mtd->priv; | |
870 | struct mxc_nand_host *host = nand_chip->priv; | |
871 | uint8_t ret = 0; | |
872 | uint16_t col; | |
873 | uint16_t __iomem *main_buf = | |
b081c2e9 | 874 | (uint16_t __iomem *)host->regs->main_area[0]; |
36fab997 | 875 | uint16_t __iomem *spare_buf = |
b081c2e9 | 876 | (uint16_t __iomem *)host->regs->spare_area[0]; |
36fab997 IY |
877 | union { |
878 | uint16_t word; | |
879 | uint8_t bytes[2]; | |
880 | } nfc_word; | |
881 | ||
882 | /* Check for status request */ | |
883 | if (host->status_request) | |
884 | return get_dev_status(host) & 0xFF; | |
885 | ||
886 | /* Get column for 16-bit access */ | |
887 | col = host->col_addr >> 1; | |
888 | ||
889 | /* If we are accessing the spare region */ | |
890 | if (host->spare_only) | |
891 | nfc_word.word = readw(&spare_buf[col]); | |
892 | else | |
893 | nfc_word.word = readw(&main_buf[col]); | |
894 | ||
895 | /* Pick upper/lower byte of word from RAM buffer */ | |
896 | ret = nfc_word.bytes[host->col_addr & 0x1]; | |
897 | ||
898 | /* Update saved column address */ | |
899 | if (nand_chip->options & NAND_BUSWIDTH_16) | |
900 | host->col_addr += 2; | |
901 | else | |
902 | host->col_addr++; | |
903 | ||
904 | return ret; | |
905 | } | |
906 | ||
907 | static uint16_t mxc_nand_read_word(struct mtd_info *mtd) | |
908 | { | |
909 | struct nand_chip *nand_chip = mtd->priv; | |
910 | struct mxc_nand_host *host = nand_chip->priv; | |
911 | uint16_t col, ret; | |
912 | uint16_t __iomem *p; | |
913 | ||
914 | MTDDEBUG(MTD_DEBUG_LEVEL3, | |
915 | "mxc_nand_read_word(col = %d)\n", host->col_addr); | |
916 | ||
917 | col = host->col_addr; | |
918 | /* Adjust saved column address */ | |
919 | if (col < mtd->writesize && host->spare_only) | |
920 | col += mtd->writesize; | |
921 | ||
922 | if (col < mtd->writesize) { | |
b081c2e9 JR |
923 | p = (uint16_t __iomem *)(host->regs->main_area[0] + |
924 | (col >> 1)); | |
36fab997 | 925 | } else { |
b081c2e9 | 926 | p = (uint16_t __iomem *)(host->regs->spare_area[0] + |
36fab997 IY |
927 | ((col - mtd->writesize) >> 1)); |
928 | } | |
929 | ||
930 | if (col & 1) { | |
931 | union { | |
932 | uint16_t word; | |
933 | uint8_t bytes[2]; | |
934 | } nfc_word[3]; | |
935 | ||
936 | nfc_word[0].word = readw(p); | |
937 | nfc_word[1].word = readw(p + 1); | |
938 | ||
939 | nfc_word[2].bytes[0] = nfc_word[0].bytes[1]; | |
940 | nfc_word[2].bytes[1] = nfc_word[1].bytes[0]; | |
941 | ||
942 | ret = nfc_word[2].word; | |
943 | } else { | |
944 | ret = readw(p); | |
945 | } | |
946 | ||
947 | /* Update saved column address */ | |
948 | host->col_addr = col + 2; | |
949 | ||
950 | return ret; | |
951 | } | |
952 | ||
953 | /* | |
954 | * Write data of length len to buffer buf. The data to be | |
955 | * written on NAND Flash is first copied to RAMbuffer. After the Data Input | |
956 | * Operation by the NFC, the data is written to NAND Flash | |
957 | */ | |
958 | static void mxc_nand_write_buf(struct mtd_info *mtd, | |
959 | const u_char *buf, int len) | |
960 | { | |
961 | struct nand_chip *nand_chip = mtd->priv; | |
962 | struct mxc_nand_host *host = nand_chip->priv; | |
963 | int n, col, i = 0; | |
964 | ||
965 | MTDDEBUG(MTD_DEBUG_LEVEL3, | |
966 | "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr, | |
967 | len); | |
968 | ||
969 | col = host->col_addr; | |
970 | ||
971 | /* Adjust saved column address */ | |
972 | if (col < mtd->writesize && host->spare_only) | |
973 | col += mtd->writesize; | |
974 | ||
975 | n = mtd->writesize + mtd->oobsize - col; | |
976 | n = min(len, n); | |
977 | ||
978 | MTDDEBUG(MTD_DEBUG_LEVEL3, | |
979 | "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n); | |
980 | ||
981 | while (n > 0) { | |
982 | void __iomem *p; | |
983 | ||
984 | if (col < mtd->writesize) { | |
b081c2e9 | 985 | p = host->regs->main_area[0] + (col & ~3); |
36fab997 | 986 | } else { |
b081c2e9 | 987 | p = host->regs->spare_area[0] - |
36fab997 IY |
988 | mtd->writesize + (col & ~3); |
989 | } | |
990 | ||
991 | MTDDEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__, | |
992 | __LINE__, p); | |
993 | ||
994 | if (((col | (unsigned long)&buf[i]) & 3) || n < 4) { | |
995 | union { | |
996 | uint32_t word; | |
997 | uint8_t bytes[4]; | |
998 | } nfc_word; | |
999 | ||
1000 | nfc_word.word = readl(p); | |
1001 | nfc_word.bytes[col & 3] = buf[i++]; | |
1002 | n--; | |
1003 | col++; | |
1004 | ||
1005 | writel(nfc_word.word, p); | |
1006 | } else { | |
1007 | int m = mtd->writesize - col; | |
1008 | ||
1009 | if (col >= mtd->writesize) | |
1010 | m += mtd->oobsize; | |
1011 | ||
1012 | m = min(n, m) & ~3; | |
1013 | ||
1014 | MTDDEBUG(MTD_DEBUG_LEVEL3, | |
1015 | "%s:%d: n = %d, m = %d, i = %d, col = %d\n", | |
1016 | __func__, __LINE__, n, m, i, col); | |
1017 | ||
1018 | mxc_nand_memcpy32(p, (uint32_t *)&buf[i], m); | |
1019 | col += m; | |
1020 | i += m; | |
1021 | n -= m; | |
1022 | } | |
1023 | } | |
1024 | /* Update saved column address */ | |
1025 | host->col_addr = col; | |
1026 | } | |
1027 | ||
1028 | /* | |
1029 | * Read the data buffer from the NAND Flash. To read the data from NAND | |
1030 | * Flash first the data output cycle is initiated by the NFC, which copies | |
1031 | * the data to RAMbuffer. This data of length len is then copied to buffer buf. | |
1032 | */ | |
1033 | static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | |
1034 | { | |
1035 | struct nand_chip *nand_chip = mtd->priv; | |
1036 | struct mxc_nand_host *host = nand_chip->priv; | |
1037 | int n, col, i = 0; | |
1038 | ||
1039 | MTDDEBUG(MTD_DEBUG_LEVEL3, | |
1040 | "mxc_nand_read_buf(col = %d, len = %d)\n", host->col_addr, len); | |
1041 | ||
1042 | col = host->col_addr; | |
1043 | ||
1044 | /* Adjust saved column address */ | |
1045 | if (col < mtd->writesize && host->spare_only) | |
1046 | col += mtd->writesize; | |
1047 | ||
1048 | n = mtd->writesize + mtd->oobsize - col; | |
1049 | n = min(len, n); | |
1050 | ||
1051 | while (n > 0) { | |
1052 | void __iomem *p; | |
1053 | ||
1054 | if (col < mtd->writesize) { | |
b081c2e9 | 1055 | p = host->regs->main_area[0] + (col & ~3); |
36fab997 | 1056 | } else { |
b081c2e9 | 1057 | p = host->regs->spare_area[0] - |
36fab997 IY |
1058 | mtd->writesize + (col & ~3); |
1059 | } | |
1060 | ||
1061 | if (((col | (int)&buf[i]) & 3) || n < 4) { | |
1062 | union { | |
1063 | uint32_t word; | |
1064 | uint8_t bytes[4]; | |
1065 | } nfc_word; | |
1066 | ||
1067 | nfc_word.word = readl(p); | |
1068 | buf[i++] = nfc_word.bytes[col & 3]; | |
1069 | n--; | |
1070 | col++; | |
1071 | } else { | |
1072 | int m = mtd->writesize - col; | |
1073 | ||
1074 | if (col >= mtd->writesize) | |
1075 | m += mtd->oobsize; | |
1076 | ||
1077 | m = min(n, m) & ~3; | |
1078 | mxc_nand_memcpy32((uint32_t *)&buf[i], p, m); | |
1079 | ||
1080 | col += m; | |
1081 | i += m; | |
1082 | n -= m; | |
1083 | } | |
1084 | } | |
1085 | /* Update saved column address */ | |
1086 | host->col_addr = col; | |
1087 | } | |
1088 | ||
1089 | /* | |
1090 | * Used by the upper layer to verify the data in NAND Flash | |
1091 | * with the data in the buf. | |
1092 | */ | |
1093 | static int mxc_nand_verify_buf(struct mtd_info *mtd, | |
1094 | const u_char *buf, int len) | |
1095 | { | |
1096 | u_char tmp[256]; | |
1097 | uint bsize; | |
1098 | ||
1099 | while (len) { | |
1100 | bsize = min(len, 256); | |
1101 | mxc_nand_read_buf(mtd, tmp, bsize); | |
1102 | ||
1103 | if (memcmp(buf, tmp, bsize)) | |
1104 | return 1; | |
1105 | ||
1106 | buf += bsize; | |
1107 | len -= bsize; | |
1108 | } | |
1109 | ||
1110 | return 0; | |
1111 | } | |
1112 | ||
1113 | /* | |
1114 | * This function is used by upper layer for select and | |
1115 | * deselect of the NAND chip | |
1116 | */ | |
1117 | static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) | |
1118 | { | |
1119 | struct nand_chip *nand_chip = mtd->priv; | |
1120 | struct mxc_nand_host *host = nand_chip->priv; | |
1121 | ||
1122 | switch (chip) { | |
1123 | case -1: | |
1124 | /* TODO: Disable the NFC clock */ | |
1125 | if (host->clk_act) | |
1126 | host->clk_act = 0; | |
1127 | break; | |
1128 | case 0: | |
1129 | /* TODO: Enable the NFC clock */ | |
1130 | if (!host->clk_act) | |
1131 | host->clk_act = 1; | |
1132 | break; | |
1133 | ||
1134 | default: | |
1135 | break; | |
1136 | } | |
1137 | } | |
1138 | ||
1139 | /* | |
1140 | * Used by the upper layer to write command to NAND Flash for | |
1141 | * different operations to be carried out on NAND Flash | |
1142 | */ | |
b081c2e9 | 1143 | void mxc_nand_command(struct mtd_info *mtd, unsigned command, |
36fab997 IY |
1144 | int column, int page_addr) |
1145 | { | |
1146 | struct nand_chip *nand_chip = mtd->priv; | |
1147 | struct mxc_nand_host *host = nand_chip->priv; | |
1148 | ||
1149 | MTDDEBUG(MTD_DEBUG_LEVEL3, | |
1150 | "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", | |
1151 | command, column, page_addr); | |
1152 | ||
1153 | /* Reset command state information */ | |
1154 | host->status_request = false; | |
1155 | ||
1156 | /* Command pre-processing step */ | |
1157 | switch (command) { | |
1158 | ||
1159 | case NAND_CMD_STATUS: | |
1160 | host->col_addr = 0; | |
1161 | host->status_request = true; | |
1162 | break; | |
1163 | ||
1164 | case NAND_CMD_READ0: | |
b081c2e9 | 1165 | host->page_addr = page_addr; |
36fab997 IY |
1166 | host->col_addr = column; |
1167 | host->spare_only = false; | |
1168 | break; | |
1169 | ||
1170 | case NAND_CMD_READOOB: | |
1171 | host->col_addr = column; | |
1172 | host->spare_only = true; | |
1173 | if (host->pagesize_2k) | |
1174 | command = NAND_CMD_READ0; /* only READ0 is valid */ | |
1175 | break; | |
1176 | ||
1177 | case NAND_CMD_SEQIN: | |
1178 | if (column >= mtd->writesize) { | |
1179 | /* | |
1180 | * before sending SEQIN command for partial write, | |
1181 | * we need read one page out. FSL NFC does not support | |
1182 | * partial write. It alway send out 512+ecc+512+ecc ... | |
1183 | * for large page nand flash. But for small page nand | |
1184 | * flash, it does support SPARE ONLY operation. | |
1185 | */ | |
1186 | if (host->pagesize_2k) { | |
1187 | /* call ourself to read a page */ | |
1188 | mxc_nand_command(mtd, NAND_CMD_READ0, 0, | |
1189 | page_addr); | |
1190 | } | |
1191 | ||
1192 | host->col_addr = column - mtd->writesize; | |
1193 | host->spare_only = true; | |
1194 | ||
1195 | /* Set program pointer to spare region */ | |
1196 | if (!host->pagesize_2k) | |
1197 | send_cmd(host, NAND_CMD_READOOB); | |
1198 | } else { | |
1199 | host->spare_only = false; | |
1200 | host->col_addr = column; | |
1201 | ||
1202 | /* Set program pointer to page start */ | |
1203 | if (!host->pagesize_2k) | |
1204 | send_cmd(host, NAND_CMD_READ0); | |
1205 | } | |
1206 | break; | |
1207 | ||
1208 | case NAND_CMD_PAGEPROG: | |
1209 | send_prog_page(host, 0, host->spare_only); | |
1210 | ||
b081c2e9 | 1211 | if (host->pagesize_2k && !is_mxc_nfc_11()) { |
36fab997 IY |
1212 | /* data in 4 areas datas */ |
1213 | send_prog_page(host, 1, host->spare_only); | |
1214 | send_prog_page(host, 2, host->spare_only); | |
1215 | send_prog_page(host, 3, host->spare_only); | |
1216 | } | |
1217 | ||
1218 | break; | |
1219 | } | |
1220 | ||
1221 | /* Write out the command to the device. */ | |
1222 | send_cmd(host, command); | |
1223 | ||
1224 | /* Write out column address, if necessary */ | |
1225 | if (column != -1) { | |
1226 | /* | |
1227 | * MXC NANDFC can only perform full page+spare or | |
1228 | * spare-only read/write. When the upper layers | |
1229 | * layers perform a read/write buf operation, | |
1230 | * we will used the saved column adress to index into | |
1231 | * the full page. | |
1232 | */ | |
1233 | send_addr(host, 0); | |
1234 | if (host->pagesize_2k) | |
1235 | /* another col addr cycle for 2k page */ | |
1236 | send_addr(host, 0); | |
1237 | } | |
1238 | ||
1239 | /* Write out page address, if necessary */ | |
1240 | if (page_addr != -1) { | |
b081c2e9 JR |
1241 | u32 page_mask = nand_chip->pagemask; |
1242 | do { | |
1243 | send_addr(host, page_addr & 0xFF); | |
1244 | page_addr >>= 8; | |
1245 | page_mask >>= 8; | |
1246 | } while (page_mask); | |
36fab997 IY |
1247 | } |
1248 | ||
1249 | /* Command post-processing step */ | |
1250 | switch (command) { | |
1251 | ||
1252 | case NAND_CMD_RESET: | |
1253 | break; | |
1254 | ||
1255 | case NAND_CMD_READOOB: | |
1256 | case NAND_CMD_READ0: | |
1257 | if (host->pagesize_2k) { | |
1258 | /* send read confirm command */ | |
1259 | send_cmd(host, NAND_CMD_READSTART); | |
1260 | /* read for each AREA */ | |
1261 | send_read_page(host, 0, host->spare_only); | |
b081c2e9 JR |
1262 | if (!is_mxc_nfc_11()) { |
1263 | send_read_page(host, 1, host->spare_only); | |
1264 | send_read_page(host, 2, host->spare_only); | |
1265 | send_read_page(host, 3, host->spare_only); | |
1266 | } | |
36fab997 IY |
1267 | } else { |
1268 | send_read_page(host, 0, host->spare_only); | |
1269 | } | |
1270 | break; | |
1271 | ||
1272 | case NAND_CMD_READID: | |
1273 | host->col_addr = 0; | |
1274 | send_read_id(host); | |
1275 | break; | |
1276 | ||
1277 | case NAND_CMD_PAGEPROG: | |
1278 | break; | |
1279 | ||
1280 | case NAND_CMD_STATUS: | |
1281 | break; | |
1282 | ||
1283 | case NAND_CMD_ERASE2: | |
1284 | break; | |
1285 | } | |
1286 | } | |
1287 | ||
b081c2e9 JR |
1288 | #ifdef MXC_NFC_V1_1 |
1289 | static void mxc_setup_config1(void) | |
1290 | { | |
1291 | uint16_t tmp; | |
1292 | ||
1293 | tmp = readw(&host->regs->nfc_config1); | |
1294 | tmp |= NFC_ONE_CYCLE; | |
1295 | tmp |= NFC_4_8N_ECC; | |
1296 | writew(tmp, &host->regs->nfc_config1); | |
1297 | if (host->pagesize_2k) | |
1298 | writew(64/2, &host->regs->nfc_spare_area_size); | |
1299 | else | |
1300 | writew(16/2, &host->regs->nfc_spare_area_size); | |
1301 | } | |
1302 | #else | |
1303 | #define mxc_setup_config1() | |
1304 | #endif | |
1305 | ||
36fab997 IY |
1306 | int board_nand_init(struct nand_chip *this) |
1307 | { | |
36fab997 IY |
1308 | struct mtd_info *mtd; |
1309 | uint16_t tmp; | |
1310 | int err = 0; | |
1311 | ||
1312 | /* structures must be linked */ | |
1313 | mtd = &host->mtd; | |
1314 | mtd->priv = this; | |
1315 | host->nand = this; | |
1316 | ||
1317 | /* 5 us command delay time */ | |
1318 | this->chip_delay = 5; | |
1319 | ||
1320 | this->priv = host; | |
1321 | this->dev_ready = mxc_nand_dev_ready; | |
1322 | this->cmdfunc = mxc_nand_command; | |
1323 | this->select_chip = mxc_nand_select_chip; | |
1324 | this->read_byte = mxc_nand_read_byte; | |
1325 | this->read_word = mxc_nand_read_word; | |
1326 | this->write_buf = mxc_nand_write_buf; | |
1327 | this->read_buf = mxc_nand_read_buf; | |
1328 | this->verify_buf = mxc_nand_verify_buf; | |
1329 | ||
1330 | host->regs = (struct nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE; | |
1331 | host->clk_act = 1; | |
1332 | ||
1333 | #ifdef CONFIG_MXC_NAND_HWECC | |
1334 | this->ecc.calculate = mxc_nand_calculate_ecc; | |
1335 | this->ecc.hwctl = mxc_nand_enable_hwecc; | |
1336 | this->ecc.correct = mxc_nand_correct_data; | |
b081c2e9 JR |
1337 | if (is_mxc_nfc_11()) { |
1338 | this->ecc.mode = NAND_ECC_HW_SYNDROME; | |
1339 | this->ecc.read_page = mxc_nand_read_page_syndrome; | |
1340 | this->ecc.read_page_raw = mxc_nand_read_page_raw_syndrome; | |
1341 | this->ecc.read_oob = mxc_nand_read_oob_syndrome; | |
1342 | this->ecc.write_page = mxc_nand_write_page_syndrome; | |
1343 | this->ecc.write_page_raw = mxc_nand_write_page_raw_syndrome; | |
1344 | this->ecc.write_oob = mxc_nand_write_oob_syndrome; | |
1345 | this->ecc.bytes = 9; | |
1346 | this->ecc.prepad = 7; | |
1347 | } else { | |
1348 | this->ecc.mode = NAND_ECC_HW; | |
1349 | } | |
1350 | ||
1351 | host->pagesize_2k = 0; | |
1352 | ||
36fab997 | 1353 | this->ecc.size = 512; |
36fab997 IY |
1354 | tmp = readw(&host->regs->nfc_config1); |
1355 | tmp |= NFC_ECC_EN; | |
1356 | writew(tmp, &host->regs->nfc_config1); | |
1357 | #else | |
1358 | this->ecc.layout = &nand_soft_eccoob; | |
1359 | this->ecc.mode = NAND_ECC_SOFT; | |
1360 | tmp = readw(&host->regs->nfc_config1); | |
1361 | tmp &= ~NFC_ECC_EN; | |
1362 | writew(tmp, &host->regs->nfc_config1); | |
1363 | #endif | |
36fab997 IY |
1364 | /* Reset NAND */ |
1365 | this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); | |
1366 | ||
1367 | /* | |
1368 | * preset operation | |
1369 | * Unlock the internal RAM Buffer | |
1370 | */ | |
1371 | writew(0x2, &host->regs->nfc_config); | |
1372 | ||
1373 | /* Blocks to be unlocked */ | |
1374 | writew(0x0, &host->regs->nfc_unlockstart_blkaddr); | |
1375 | writew(0x4000, &host->regs->nfc_unlockend_blkaddr); | |
1376 | ||
1377 | /* Unlock Block Command for given address range */ | |
1378 | writew(0x4, &host->regs->nfc_wrprot); | |
1379 | ||
1380 | /* NAND bus width determines access funtions used by upper layer */ | |
f6a9748e | 1381 | if (is_16bit_nand()) |
36fab997 IY |
1382 | this->options |= NAND_BUSWIDTH_16; |
1383 | ||
c4832dff ML |
1384 | #ifdef CONFIG_SYS_NAND_LARGEPAGE |
1385 | host->pagesize_2k = 1; | |
b081c2e9 | 1386 | this->ecc.layout = &nand_hw_eccoob2k; |
c4832dff | 1387 | #else |
36fab997 | 1388 | host->pagesize_2k = 0; |
b081c2e9 | 1389 | this->ecc.layout = &nand_hw_eccoob; |
c4832dff | 1390 | #endif |
b081c2e9 | 1391 | mxc_setup_config1(); |
36fab997 IY |
1392 | return err; |
1393 | } |