]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/flash/arm/mxc/v2_0/src/mxc_nfc.c
Initial revision
[karo-tx-redboot.git] / packages / devs / flash / arm / mxc / v2_0 / src / mxc_nfc.c
1 //==-*- c-basic-offset: 4; tab-width: 4; -*-================================
2 //
3 //              mxc_nfc.c
4 //
5 //              Flash programming to support NAND flash on Freescale MXC platforms
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):    Kevin Zhang <k.zhang@freescale.com>
44 // Contributors: Kevin Zhang <k.zhang@freescale.com>
45 // Date:                 2006-01-23
46 // Purpose:
47 // Description:
48 //
49 //####DESCRIPTIONEND####
50 //
51 //==========================================================================
52
53 #include <pkgconf/hal.h>
54 #include <cyg/hal/hal_arch.h>
55 #include <cyg/hal/hal_cache.h>
56 #include <redboot.h>
57 #include <stdlib.h>
58
59 #include CYGHWR_MEMORY_LAYOUT_H
60 #include <cyg/hal/hal_io.h>
61 #define  _FLASH_PRIVATE_
62 #include <cyg/io/flash.h>
63
64 #ifdef CYGPKG_HAL_ARM_MXC30031ADS
65 #include <cyg/io/mxc_nfc_v2.h>
66 #else
67 #include <cyg/io/mxc_nfc.h>
68 #endif
69
70 #ifdef MXCFLASH_FLASH_BASED_BBT
71 #include <cyg/io/nand_bbt.h>
72 #include CYGHWR_FLASH_NAND_BBT_HEADER
73 #endif
74
75 #define MXC_UNLOCK_BLK_END              0xFFFF
76
77 #define DBG(n, fmt...) nfc_printf((n) + 1, fmt)
78
79 static void print_pkt_16(u16* pkt, u32 len);
80 static void print_page (u32 addr, bool spare_only);
81 static int nfc_read_page(u32 addr);
82 static int nfc_read_page_sp(u32 addr);
83 static int nfc_program_page(u32 flash_addr, u32 mem_addr, enum nfc_page_area area);
84 static void nfc_flash_reset(void);
85 static int mxc_nfc_scan(bool verbose);
86 static void read_nflash_id(void* id);
87 static int nand_flash_index = -1;
88 static int g_ecc_enable = true;
89 static int g_spare_only_read_ok = true;
90 static int g_nfc_debug_level = NFC_DEBUG_DEF;
91 static bool g_nfc_debug_measure = false;
92 static bool g_nfc_scan_done = false;
93 static bool g_is_2k_page = false;
94 static unsigned int g_nfc_version = MXC_NFC_V1;
95 static unsigned int is_bad_blk = false;
96
97 /*
98 //#define NFC_2K_BI_SWAP
99  *
100  * The i.MX NAND flash controller overlays the 2KiB+64B page FLASH
101  * with its internal 512B+16B buffer structure. Thus the indicator bytes
102  * for factory bad blocks that are located at column address 2048
103  * in the flash end up in the fourth main area buffer at offset 464.
104  * This switch enables a routine that swaps the BI byte from the main
105  * buffer to the spare buffer so it won't get cleared when the block is
106  * programmed.
107  * Since the factory bad block indicators are only meaningful for virgin
108  * flash chips, the checking for the factory bad block indicators actually
109  * needs to be done only once during initial flash programming and bad block
110  * table creation.
111  * Lateron the factory bad blocks will be mapped out via the bbt.
112  *
113  * Furthermore, the only thing that the manufacturer guarantees for
114  * bad blocks is that the indicator byte in the first or second page
115  * of a bad block will contain at least one zero. There is no guarantee
116  * that any byte of the bad block will be changeable. Thus, moving the
117  * BI to any other byte within the bad block may be impossible.
118  *
119  * Therefore this switch is NOT defined here!
120  */
121
122 extern unsigned int hal_timer_count(void);
123
124 #define nfc_printf(level, args...)                              \
125         do {                                                                            \
126                 if (g_nfc_debug_level >= level)                 \
127                         diag_printf(args);                                      \
128         } while (0)
129
130 #ifndef MXCFLASH_SELECT_MULTI
131 void flash_query(void *data)
132 #else
133 void nandflash_query(void *data)
134 #endif
135 {
136         read_nflash_id(data);
137         nfc_printf(NFC_DEBUG_MAX, "%s(ID=0x%x: 0x%x, 0x%x, 0x%x)\n",
138                            __FUNCTION__, *(u8*)(data), *(u8*)((u32)data + 1),
139                            *(u8*)((u32)data + 2), *(u8*)((u32)data + 3));
140 }
141
142 #ifndef MXCFLASH_SELECT_MULTI
143 int flash_program_buf(void* addr, void* data, int len)
144 #else
145 int nandflash_program_buf(void* addr, void* data, int len)
146 #endif
147 {
148         nfc_printf(NFC_DEBUG_MAX, "%s(addr=%p, data=%p, len=0x%x)\n",
149                            __FUNCTION__, addr, data, len);
150         return nfc_program_region((u32)addr, (u32)data, (u32)len);
151 }
152
153 #ifndef MXCFLASH_SELECT_MULTI
154 int flash_erase_block(void* block, unsigned int size)
155 #else
156 int nandflash_erase_block(void* block, unsigned int size)
157 #endif
158 {
159         nfc_printf(NFC_DEBUG_MAX, "%s(block=%p, size=0x%x)\n",
160                            __FUNCTION__, block, size);
161         return nfc_erase_region((u32)block, size);
162 }
163
164 #ifndef MXCFLASH_SELECT_MULTI
165 bool flash_code_overlaps(void *start, void *end)
166 #else
167 bool nandflash_code_overlaps(void *start, void *end)
168 #endif
169 {
170         extern unsigned char _stext[], _etext[];
171
172         return ((((unsigned long)&_stext >= (unsigned long)start) &&
173                          ((unsigned long)&_stext < (unsigned long)end)) ||
174                         (((unsigned long)&_etext >= (unsigned long)start) &&
175                          ((unsigned long)&_etext < (unsigned long)end)));
176 }
177
178 #ifndef MXCFLASH_SELECT_MULTI
179 int flash_hwr_map_error(int e)
180 #else
181 int nandflash_hwr_map_error(int e)
182 #endif
183 {
184         return e;
185 }
186
187 #ifndef MXCFLASH_SELECT_MULTI
188 int flash_lock_block(void* block)
189 #else
190 int nandflash_lock_block(void* block)
191 #endif
192 {
193         // Not supported yet
194         return 0;
195 }
196
197 #ifndef MXCFLASH_SELECT_MULTI
198 int flash_unlock_block(void* block, int block_size, int blocks)
199 #else
200 int nandflash_unlock_block(void* block, int block_size, int blocks)
201 #endif
202 {
203         // Not supported yet
204         return 0;
205 }
206
207 //----------------------------------------------------------------------------
208 // Now that device properties are defined, include magic for defining
209 // accessor type and constants.
210 #include <cyg/io/flash_dev.h>
211
212 // Information about supported devices
213 typedef struct flash_dev_info {
214         cyg_uint16       device_id;
215         cyg_uint16       device_id2;
216         cyg_uint16       device_id3;
217         cyg_uint16       device_id4;
218         cyg_uint16       page_size;
219         cyg_uint32       spare_size;
220         cyg_uint32       pages_per_block;
221         cyg_uint32       block_size;
222         cyg_int32        block_count;
223         cyg_uint32       base_mask;
224         cyg_uint32       chipsize;
225         cyg_uint32       device_size;
226         cyg_uint32       port_size;             // x8 or x16 IO
227         cyg_uint32       type;                  //SLC vs MLC
228         const char       *vendor_info;
229 } flash_dev_info_t;
230
231 static const flash_dev_info_t* flash_dev_info;
232 static const flash_dev_info_t supported_devices[] = {
233 #include <cyg/io/mxc_nand_parts.inl>
234 };
235 #define NUM_DEVICES (sizeof(supported_devices)/sizeof(flash_dev_info_t))
236
237 #define NF_PG_SZ                                        flash_dev_info->page_size
238 #define NF_PG_PER_BLK                           flash_dev_info->pages_per_block
239 #define NF_DEV_SZ                                       flash_dev_info->device_size
240 #define NF_BLK_SZ                                       flash_dev_info->block_size
241 #define NF_BLK_CNT                                      flash_dev_info->block_count
242 #define NF_SPARE_SZ                                     flash_dev_info->spare_size
243
244 #define NAND_PG_SHIFT                           (g_is_2k_page ? 12 : 9)
245
246 // Mask off the higher bits representing linear address of the nand flash
247 #define MXC_NAND_LA_MASK                        (NF_DEV_SZ - 1)
248
249 #define NFC_DEVICE_ALIGN(a)                     ((a) & MXC_NAND_LA_MASK & (~(NF_DEV_SZ - 1)))
250 #define NFC_BLOCK_ALIGN(a)                      ((a) & MXC_NAND_LA_MASK & (~(NF_BLK_SZ - 1)))
251 #define NFC_PAGE_ALIGN(a)                       ((a) & MXC_NAND_LA_MASK & (~(NF_PG_SZ - 1)))
252
253 #define BLOCK_TO_OFFSET(blk)                    (blk * NF_PG_PER_BLK * NF_PG_SZ)
254 #define BLOCK_TO_PAGE(blk)                              (blk * NF_PG_PER_BLK)
255 #define BLOCK_PAGE_TO_OFFSET(blk, pge)  ((blk * NF_PG_PER_BLK + pge) * NF_PG_SZ)
256 #define OFFSET_TO_BLOCK(offset)                 ((offset / NF_PG_SZ) / NF_PG_PER_BLK)
257 #define OFFSET_TO_PAGE(offset)                  ((offset / NF_PG_SZ) % NF_PG_PER_BLK)
258
259 static u8 *bad_block_table;
260 static u32 *l_to_p_table;
261 static bool mxcnfc_init_ok = false;
262
263 //mxc_nand_fixup_t nand_page_sz_2k_fixup;
264 //mxc_nand_fixup_t nand_port_sz_x16_fixup;
265
266 nfc_setup_func_t *nfc_setup = NULL;
267
268 int
269 #ifndef MXCFLASH_SELECT_MULTI
270 flash_hwr_init(void)
271 #else
272 nandflash_hwr_init(void)
273 #endif
274 {
275         cyg_uint16 id[4];
276         int i, bad_block_num;
277         nfc_printf(NFC_DEBUG_MAX, "%s()\n", __FUNCTION__);
278 #ifdef CYGPKG_HAL_ARM_MXC91131
279 extern u32 system_rev;
280         // take care of the NFC spare-only read bug on MXC91131 TO 2.0
281         if (system_rev == CHIP_REV_2_0) {
282                 g_spare_only_read_ok = false;
283         }
284 #endif
285
286         // Look through table for device data
287         flash_dev_info = supported_devices;
288         flash_dev_query(id);
289         for (i = 0; i < NUM_DEVICES; i++) {
290                 if ((flash_dev_info->device_id == id[0]) &&
291                         (flash_dev_info->device_id2 == 0xFFFF || flash_dev_info->device_id2 == id[1]))
292                         break;
293                 flash_dev_info++;
294         }
295
296         nfc_printf(NFC_DEBUG_MED, "%s(): %d out of NUM_DEVICES=%d, id=0x%x\n",
297                            __FUNCTION__, i, (u32)NUM_DEVICES, flash_dev_info->device_id);
298
299         // Did we find the device? If not, return error.
300         if (NUM_DEVICES == i) {
301                 diag_printf("Unrecognized NAND part: 0x%04x, 0x%04x, 0x%04x, 0x%04x\n",
302                                         id[0], id[1], id[2], id[3]);
303                 return FLASH_ERR_DRV_WRONG_PART;
304         }
305
306         if (NF_PG_SZ == 2048) {
307                 g_is_2k_page = true;
308                 g_spare_only_read_ok = false;
309         }
310         if (nfc_setup) {
311                 g_nfc_version = nfc_setup(NF_PG_SZ, flash_dev_info->port_size,
312                                                                   flash_dev_info->type);
313         }
314
315         nand_flash_index = i;
316         nfc_flash_reset();
317         mxcnfc_init_ok = true;
318
319         bad_block_table = malloc(NF_BLK_CNT / 4);
320         if (bad_block_table == NULL) {
321                 diag_printf("** Error: could not allocate %d byte for bad block table\n",
322                                         NF_BLK_CNT / 4);
323                 return FLASH_ERR_PROTOCOL;
324         }
325         l_to_p_table = malloc(NF_BLK_CNT * 4);
326         if (l_to_p_table == NULL) {
327                 diag_printf("** Error: could not allocate %d byte for bad block relocation table\n",
328                                         NF_BLK_CNT * 4);
329                 return FLASH_ERR_PROTOCOL;
330         }
331         memset(bad_block_table, 0, NF_BLK_CNT / 4);
332         memset(l_to_p_table, 0, NF_BLK_CNT * 4);
333
334         nfc_printf(NFC_DEBUG_MAX, "%s(bad_block_table=%p)\n",
335                            __FUNCTION__, bad_block_table);
336         bad_block_num = mxc_nfc_scan(false);
337
338         nfc_printf(NFC_DEBUG_MIN, "\nFound %d bad/reserved blocks\n\n", bad_block_num);
339
340         // Hard wired for now
341         flash_info.block_size = NF_BLK_SZ;
342         flash_info.blocks = NF_BLK_CNT - bad_block_num;
343         flash_info.start = (void *)MXC_NAND_BASE_DUMMY;
344         flash_info.end = (void *)(MXC_NAND_BASE_DUMMY + (NF_DEV_SZ) -
345                                                           (bad_block_num * NF_BLK_SZ));
346
347         nfc_printf(NFC_DEBUG_MED, "%s(): block_size=0x%x, blocks=0x%x, start=%p, end=%p\n",
348                            __FUNCTION__, flash_info.block_size, flash_info.blocks,
349                            flash_info.start, flash_info.end);
350
351         return FLASH_ERR_OK;
352 }
353
354 /*!
355  * Starts the address input cycles for different operations as defined in ops.
356  *
357  * @param ops                   operations as defined in enum nfc_addr_ops
358  * @param addr                  starting address
359  * @param mask                  mask for the full address range of the nand flash
360  *                                              For 64MB flash, the mask should be 0x03FFFFFF (64MB-1)
361  */
362 static void start_nfc_addr_ops(enum nfc_addr_ops ops, u32 addr, u32 mask)
363 {
364         u32 m = mask, a = addr;
365
366         switch (ops) {
367         case ADDRESS_INPUT_READ_ID:
368                 NFC_ADDR_INPUT(0);
369                 return;
370         case ADDRESS_INPUT_READ_PAGE:
371         case ADDRESS_INPUT_PROGRAM_PAGE:
372                 if (g_is_2k_page) {
373                         NFC_ADDR_INPUT(a & 0xFF);
374                         NFC_ADDR_INPUT((a >> 8) & 0xF);
375                 } else {
376                         NFC_ADDR_INPUT(a & 0xFF);
377                 }
378                 // don't break on purpose
379         case ADDRESS_INPUT_ERASE_BLOCK:
380                 a >>= NAND_PG_SHIFT;
381                 m >>= NAND_PG_SHIFT;
382                 break;
383         default:
384                 diag_printf("!!!!!! %s(): wrong ops: %d !!!!!\n", __FUNCTION__, ops);
385                 return;
386         }
387
388         do {
389                 NFC_ADDR_INPUT(a);
390                 m >>= ADDR_INPUT_SIZE;
391                 a >>= ADDR_INPUT_SIZE;
392         } while (m != 0);
393 }
394
395 // Doesn't seem to need it as when reaching here means past the query
396 // function. So reset isn't necessary.
397 static void nfc_flash_reset(void)
398 {
399 #ifdef MXC_NFC_RESET
400         nfc_printf(NFC_DEBUG_MAX, "%s()\n", __FUNCTION__);
401         NFC_PRESET(MXC_UNLOCK_BLK_END);
402         NFC_CMD_INPUT(FLASH_Reset);
403 #endif
404 }
405
406 static u8 get_byte(cyg_uint16 *buf, int offs)
407 {
408         cyg_uint16 word = buf[offs >> 1];
409         if (offs & 1) {
410                 return word >> 8;
411         }
412         return word & 0xff;
413 }
414
415 static void store_byte(cyg_uint16 *buf, int offs, u8 val)
416 {
417         cyg_uint16 word = buf[offs >> 1];
418
419         if (offs & 1) {
420                 word = (word & 0x00ff) | ((u16)val << 8);
421         } else {
422                 word = (word & 0xff00) | val;
423         }
424         buf[offs >> 1] = word;
425 }
426
427 static void nfc_buf_mem_cpy(void *dst, void *src, u32 len)
428 {
429         u16 *d = dst, *s = src;
430
431         if (((unsigned long)dst & 1) || ((unsigned long)src & 1)) {
432                 diag_printf("%s: Source (%p) or destination address (%p) not halfword aligned\n",
433                                         __FUNCTION__, src, dst);
434                 return;
435         }
436         if (len == 0) {
437                 return;
438         }
439         do {
440                 *d++ = *s++;
441                 len -= 2;
442         } while (len > 1);
443
444         if (len != 0) {
445                 u16 tmp = *d;
446                 tmp = (tmp & ~0xff) | (*s & 0xff);
447         }
448 }
449
450 static void read_nflash_id(void *id)
451 {
452         volatile u32 *ptr = (u32*)NAND_MAIN_BUF0;
453         volatile u32 *id_32 = (u32*)id;
454
455         nfc_printf(NFC_DEBUG_MAX, "%s()\n", __FUNCTION__);
456 //        NFC_PRESET(NF_BLK_CNT -1); -- doesn't work for 2k flash, why?
457         NFC_PRESET(MXC_UNLOCK_BLK_END);
458         NFC_CMD_INPUT(FLASH_Read_ID);
459         start_nfc_addr_ops(ADDRESS_INPUT_READ_ID, 0, 0);
460         NFC_DATA_OUTPUT(RAM_BUF_0, FDO_FLASH_ID, g_ecc_enable);
461
462         *id_32++ = *ptr++;
463         *id_32++ = *ptr++;
464 }
465
466 static u8 bad_block_code(int block)
467 {
468         int offs = block >> 2;
469         int shift = (block & 0x03) << 1;
470         u8 code = (bad_block_table[offs] >> shift) & 0x03;
471
472         if (code != 0) {
473                 DBG(0, "Block %d is marked %s (%02x) in mem bbt @ %04x\n", block,
474                         (code != 2) ? "bad" : "reserved", code, offs);
475         }
476         return code;
477 }
478
479 /*!
480  * Checks to see if a block is bad by looking at the 6th byte of the spare area
481  * inside a page.
482  * @param ra            starting address in the raw address space (offset)
483  *                                      (No error checking). It doesn't have to be block-aligned.
484  * @return                      true if bad block; false otherwise
485  */
486 static u8 nfc_is_badblock(u32 ra)
487 {
488         u32 block = OFFSET_TO_BLOCK(ra), ecc_val = g_ecc_enable;
489         bool res = false;
490         u16 temp, i;
491
492         if (g_nfc_scan_done) {
493                 if (block >= NF_BLK_CNT) {
494                         diag_printf("Error %d: Block count out of range: %d\n", __LINE__, block);
495                         return true;
496                 }
497                 return bad_block_code(block);
498         }
499
500         // turn off ecc when scanning for bad blocks
501 //        g_ecc_enable = false; // TODO: we should turn OFF ecc
502         g_ecc_enable = true;
503         // check for the 1st and 2nd pages
504         for (i = 0, ra = NFC_BLOCK_ALIGN(ra); i < 2; i++, ra += NF_PG_SZ) {
505                 if (nfc_read_page(ra) != 0) {
506                         diag_printf("Warning: uncorrectable ECC at addr 0x%08x\n", ra);
507                 }
508                 if (g_is_2k_page && is_bad_blk) {
509                         DBG(3, "Bad block %d\n", block);
510                         res = true;
511                         break;
512                 } else {
513                         temp = readw(NAND_SPAR_BUF0 + 4);
514                         if ((temp >> 8) != 0xFF) {
515                                 res = true;
516                                 DBG(2, "Block %d is marked bad in OOB area\n", block);
517                                 print_pkt_16((u16*)(NAND_SPAR_BUF0), g_is_2k_page ? 64 : 16);
518                                 break;
519                         }
520                 }
521         }
522         g_ecc_enable = ecc_val;
523         return res;
524 }
525
526 static void nfc_update_blk_table(u32 faddr, u8 is_bad)
527 {
528         u32 block = OFFSET_TO_BLOCK(faddr);
529         int offs = block >> 2;
530         int shift = (block & 0x03) << 1;
531         u8 mask = 0x03 << shift;
532
533         if (block >= NF_BLK_CNT) {
534                 diag_printf("Block count out of range: %d\n", block);
535                 return;
536         }
537         if (is_bad) {
538                 nfc_printf(NFC_DEBUG_MED, "marking block %d %s\n", block,
539                                    is_bad == 2 ? "reserved" : "bad");
540                 bad_block_table[offs] = (bad_block_table[offs] & ~mask) | (is_bad << shift);
541         } else {
542                 nfc_printf(NFC_DEBUG_MAX, "Block %d is good\n", block);
543                 bad_block_table[offs] &= ~mask;
544         }
545 }
546
547 /*!
548  * Erase a block without checking the BI field. If the block is bad, mark it
549  * in the global table. Note that there is NO error checking for passed-in ra.
550  * @param ra            starting address in the raw address space (offset)
551  *                                      Must be block-aligned
552  * @return                      0 if successful; -1 otherwise
553  */
554 static int nfc_erase_blk(u32 ra)
555 {
556         u16 flash_status;
557         u32 flash_addr;
558
559         if (ra % NF_BLK_SZ) {
560                 diag_printf("** Error: block erase address must be block aligned: 0x%08x\n", ra);
561                 return -1;
562         }
563         flash_addr = (ra / NF_PG_SZ) << NAND_PG_SHIFT;
564         nfc_printf(NFC_DEBUG_MED, "%s: Erasing block %d @ %08x\n", __FUNCTION__, ra / NF_BLK_SZ, ra);
565
566         NFC_CMD_INPUT(FLASH_Block_Erase);
567
568         start_nfc_addr_ops(ADDRESS_INPUT_ERASE_BLOCK, flash_addr, MXC_NAND_LA_MASK);
569         NFC_CMD_INPUT(FLASH_Start_Erase);
570
571         flash_status = NFC_STATUS_READ();
572
573         // check I/O bit 0 to see if it is 0 for success
574         if ((flash_status & 0x1) != 0) {
575                 diag_printf("** Error: failed to erase block %d at %08x; status=0x%x\n",
576                                         OFFSET_TO_BLOCK(ra), ra, flash_status);
577                 nfc_update_blk_table(ra, true);
578                 return -1;
579         }
580         return 0;
581 }
582
583 /*!
584  * Program a block of data in the flash. This function doesn't do
585  * bad block checking. But if program fails, it returns an error code.
586  * @param ra            destination raw flash address
587  * @param maddr         source address in the RAM
588  @ @return                      0 if successful; -1 otherwise
589  */
590 static int nfc_program_blk(u32 ra, u32 maddr)
591 {
592         u32 i;
593
594         for (i = 0; i < NF_PG_PER_BLK; i++) {
595                 if (nfc_program_page(ra, maddr, NFC_MAIN_ONLY) != 0) {
596                         nfc_update_blk_table(ra, true);
597                         return -1;
598                 }
599                 ra += NF_PG_SZ;
600                 maddr += NF_PG_SZ;
601         }
602         return 0;
603 }
604
605 /*
606  * Convert a linear address to raw address. No address checking in this function.
607  * @param la            linear address used by the upper flash driver
608  * @return                      raw address for NAND flash
609  */
610 static u32 nfc_l_to_p(u32 la)
611 {
612         u32 block, offset, ra;
613
614         block = la / NF_BLK_SZ;
615         offset = la % NF_BLK_SZ;
616         ra = (l_to_p_table[block] * NF_BLK_SZ) + offset;
617
618         nfc_printf(NFC_DEBUG_MAX, "\n%s(): l_to_p_table[0x%08x]=0x%08x, offset=0x%08x\n",
619                            __FUNCTION__, block, l_to_p_table[block], offset);
620         nfc_printf(NFC_DEBUG_MAX, "%s(la=0x%08x, ra=0x%08x)\n",
621                            __FUNCTION__, la, ra);
622         return ra;
623
624 }
625 /*!
626  * Erase a range of NAND flash
627  * @param la                    linear NAND flash address. it has to be block size aligned
628  * @param len                   number of bytes
629  * @return                              FLASH_ERR_OK (0) if successful; non-zero otherwise
630  */
631 int nfc_erase_region(u32 la, int len)
632 {
633         u32 ra;
634
635         nfc_printf(NFC_DEBUG_MED, "%s(la=0x%08x, len=0x%08x)\n", __FUNCTION__, la, len);
636
637         la &= MXC_NAND_LA_MASK;
638         if ((la % NF_BLK_SZ) != 0) {
639                 diag_printf("** Error: address %08x not aligned to block boundary\n", la);
640                 return FLASH_ERR_INVALID;
641         }
642         if (len <= 0 || la + len >= NF_DEV_SZ) {
643                 diag_printf("** Error: invalid length %d\n", len);
644                 return FLASH_ERR_INVALID;
645         }
646
647         // now la has to be block aligned
648         do {
649                 ra = nfc_l_to_p(la);
650                 la += NF_BLK_SZ;
651
652                 if (ra > (NF_DEV_SZ - NF_BLK_SZ)) {
653                         diag_printf("** Error: la=0x%08x (ra=0x%08x) is out of valid range\n", la, ra);
654                         return FLASH_ERR_ERASE;
655                 }
656                 if (nfc_is_badblock(ra)) {
657                         diag_printf("** Error: bad block: %d at address %08x\n",
658                                             OFFSET_TO_BLOCK(ra), ra);
659                         return FLASH_ERR_ERASE;
660                 } else {
661                         if (nfc_erase_blk(ra) == 0) {
662                                 // erase ok
663                                 len -= NF_BLK_SZ;
664                         } else {
665                                 return FLASH_ERR_ERASE;
666                         }
667                 }
668         } while (len > 0);
669
670         return FLASH_ERR_OK;
671 }
672
673 /*!
674  * Program data from memory to flash
675  * @param la                    linear NAND flash address. it has to be block size aligned
676  * @param maddr                 memory buf address where data will be copied from
677  * @param len                   number of bytes
678  * @return                              FLASH_ERR_OK (0) if successful; non-zero otherwise
679  */
680 int nfc_program_region(u32 la, u32 maddr, int len)
681 {
682         u32 ra;
683
684         nfc_printf(NFC_DEBUG_MED, "%s(la=0x%08x, maddr=0x%08x, len=0x%x)\n",
685                            __FUNCTION__, la, maddr, len);
686
687         la &=  MXC_NAND_LA_MASK;
688
689         if ((la % NF_BLK_SZ) != 0 || len <= 0) {
690                 diag_printf("%s(): invalid or not block aligned\n", __FUNCTION__);
691                 diag_printf("la=0x%08x, len=%d\n", la, len);
692                 return FLASH_ERR_INVALID;
693         }
694
695         do {
696                 ra = nfc_l_to_p(la);
697                 la += NF_BLK_SZ;
698
699                 if (ra > (NF_DEV_SZ - NF_BLK_SZ)) {
700                         diag_printf("%s()1: la=0x%08x (ra=0x%08x) is out of valid range\n",
701                                                 __FUNCTION__, la, ra);
702                         return FLASH_ERR_PROGRAM;
703                 }
704
705                 if (nfc_is_badblock(ra)) {
706                         diag_printf("\n%s(ra=0x%08x): bad block: %d\n",
707                                                 __FUNCTION__, ra, OFFSET_TO_BLOCK(ra));
708                         return FLASH_ERR_PROGRAM;
709                 } else {
710                         if (nfc_program_blk(ra, maddr) == 0) {
711                                 len -= NF_BLK_SZ;
712                                 maddr += NF_BLK_SZ;
713                         } else {
714                                 diag_printf("\n%s2(ra=0x%08x): bad block: %d\n",
715                                                         __FUNCTION__, ra, OFFSET_TO_BLOCK(ra));
716                                 return FLASH_ERR_PROGRAM;
717                         }
718                 }
719         } while (len > 0);
720
721         return FLASH_ERR_OK;
722 }
723
724 /*!
725  * Read data from linear NAND flash address to memory. The MSB of the passed-
726  * in flash address will be masked off inside the function.
727  *
728  * @param la                    linear NAND flash address. it has to be page aligned
729  * @param mem_addr              memory buf address where data will be copied to
730  * @param len                   number of bytes
731  * @return                              FLASH_ERR_OK (0) if successful; non-zero otherwise
732  */
733 int nfc_read_region(u32 la, u32 mem_addr, int len)
734 {
735         u32 ra;
736         u32 dst = mem_addr;
737
738         // make sure 32-bit aligned
739         len = (len + 3) & (~0x3);
740
741         nfc_printf(NFC_DEBUG_MED, "\n%s(la=0x%08x, mem_addr=0x%08x, len=0x%x)\n",
742                            __FUNCTION__, la, mem_addr, len);
743
744         if (la < (u32)(flash_info.start) || (la + len) > (u32)(flash_info.end)) {
745                 diag_printf("\n%s(): Error: invalid address=0x%08x, len=%d\n",
746                                         __FUNCTION__, la, len);
747                 return FLASH_ERR_INVALID;
748         }
749         la &=  MXC_NAND_LA_MASK;
750
751         if (len <= 0) {
752                 diag_printf("** Error: invalid length %d\n", len);
753                 return FLASH_ERR_INVALID;
754         }
755         if ((la % NF_PG_SZ) != 0) {
756                 diag_printf("** Error: flash address 0x%08x not page aligned\n", la);
757                 return FLASH_ERR_INVALID;
758         }
759
760         do {
761                 ra = nfc_l_to_p(la);
762                 la += NF_PG_SZ;
763
764                 if (nfc_is_badblock(ra)) {
765                         diag_printf("\n%s(1): ra=0x%08x bad block: %d\n",
766                                            __FUNCTION__, ra, OFFSET_TO_BLOCK(ra));
767                         return FLASH_ERR_INVALID;
768                 } else {
769                         int i;
770                         if (nfc_read_page(ra) != 0) {
771                                 return FLASH_ERR_INVALID;
772                         }
773                         i = (len < NF_PG_SZ) ? len: NF_PG_SZ;
774 //                        diag_printf("\nlen=%d, i=%d\n", len, i);
775                         // now do the copying
776                         nfc_buf_mem_cpy((void*)dst, (void*)(NAND_MAIN_BUF0), i);
777                         len -= i;
778                         dst += i;
779                 }
780         } while (len > 0);
781
782         return FLASH_ERR_OK;
783 }
784
785 #ifdef NFC_2K_BI_SWAP
786 static void mxc_swap_2k_BI_main_sp(int check_bad_blk)
787 {
788         u16 tmp1, tmp2, new_tmp1;
789         tmp1 = readw(BAD_BLK_MARKER_464);
790         tmp2 = readw(BAD_BLK_MARKER_SP_5);
791
792         new_tmp1 = (tmp1 & 0xFF00) | (tmp2 >> 8);
793         tmp2 = (tmp1 << 8) | (tmp2 & 0xFF);
794         writew(new_tmp1, BAD_BLK_MARKER_464);
795         writew(tmp2, BAD_BLK_MARKER_SP_5);
796         if (check_bad_blk) {
797                 is_bad_blk = 0;
798                 if ((tmp1 & 0xFF) != 0xFF) {
799                         is_bad_blk = 1;
800                 }
801         }
802 }
803 #endif
804
805 static int nfc_program_page_raw(u32 block, u32 page)
806 {
807         u16 flash_status;
808         u32 flash_addr = (block * NF_PG_PER_BLK + page) << NAND_PG_SHIFT;
809
810         diag_printf("%s: addr=%08x block=%6d page=%6d\n", __FUNCTION__,
811                                 flash_addr, block, page);
812 #if 0
813 return 0;
814 #endif
815         NFC_CMD_INPUT(FLASH_Send_Data);
816         start_nfc_addr_ops(ADDRESS_INPUT_PROGRAM_PAGE, flash_addr,
817                                            MXC_NAND_LA_MASK);
818
819         NFC_DATA_INPUT(RAM_BUF_0, NFC_MAIN_ONLY, g_ecc_enable);
820         if (g_is_2k_page && PG_2K_DATA_OP_MULTI_CYCLES()) {
821                 NFC_DATA_INPUT_2k(RAM_BUF_1);
822                 NFC_DATA_INPUT_2k(RAM_BUF_2);
823                 NFC_DATA_INPUT_2k(RAM_BUF_3);
824         }
825         NFC_CMD_INPUT(FLASH_Program);
826
827         flash_status = NFC_STATUS_READ();
828         // check I/O bit 0 to see if it is 0 for success
829         if ((flash_status & 0x1) != 0) {
830                 diag_printf("** Error: failed to program page %d at 0x%08x status=0x%x\n",
831                                         flash_addr >> NAND_PG_SHIFT, (block * NF_PG_PER_BLK + page) * NF_PG_SZ,
832                                         flash_status);
833                 return -1;
834         }
835
836         return 0;
837 }
838
839 static int nfc_write_pg_random(u32 flash_addr, u32 mem_addr,
840                                                            enum nfc_page_area area, int swap)
841 {
842         u16 flash_status, i;
843
844         nfc_printf(NFC_DEBUG_MAX, "%s: addr=%08x block=%6d page=%6d, col=%4d\n", __FUNCTION__,
845                            flash_addr, (flash_addr >> NAND_PG_SHIFT) / NF_PG_PER_BLK,
846                            flash_addr >> NAND_PG_SHIFT, flash_addr % NF_PG_SZ);
847         switch (area) {
848         case NFC_MAIN_ONLY:
849                 // Read back the spare area first
850                 for (i = 0; i < 16; i++) {
851                         // Make all spare area as 0xFF
852                         writel(0xFFFFFFFF, NAND_SPAR_BUF0 + i * 4);
853                 }
854
855                 nfc_buf_mem_cpy((void *)NAND_MAIN_BUF0, (void *)mem_addr, 512);
856                 if (g_is_2k_page) {
857                         nfc_buf_mem_cpy((void *)NAND_MAIN_BUF1, (void *)(mem_addr + 512),
858                                                         512 * 3);
859 #ifdef MXC_NAND_BOOT_LOAD_AT_0x400
860                         // To replace the data at offset 0x400 with the address of the NFC base
861                         // This is needed for certain platforms 
862                         if ((flash_addr <= 0x400) && ((flash_addr + NF_PG_SZ - 1) > 0x400)) {
863 //                                diag_printf("\nflash_addr = 0x%08x\n", flash_addr);
864                                 diag_printf("\n[INFO] 2K page: copy data at 0x400 to spare area and set it to 0x%08x\n", NFC_BASE);
865                                 writel(readl(NFC_BASE + 0x400), NAND_SPAR_BUF2);
866                                 writel(NFC_BASE, NFC_BASE + 0x400);
867                         }
868 #endif
869 #ifdef NFC_2K_BI_SWAP
870                         if (swap)
871                                 mxc_swap_2k_BI_main_sp(0);
872 #endif
873                 } else {
874 #ifdef MXC_NAND_BOOT_LOAD_AT_0x400
875                         // To replace the data at offset 0x400 with the address of the NFC base
876                         // This is needed for certain platforms 
877                         if ((flash_addr <= 0x400) && ((flash_addr + NF_PG_SZ - 1) > 0x400)) {
878                                 diag_printf("\nflash_addr = 0x%08x\n", flash_addr);
879                                 diag_printf("\n[INFO] 512 page: copy data at 0x400 to spare area and set it to 0x%08x\n", NFC_BASE);
880                                 writel(readl(NFC_BASE), NAND_SPAR_BUF0);
881                                 writel(NFC_BASE, NFC_BASE);
882                         }
883 #endif
884                 }
885                 break;
886         case NFC_SPARE_ONLY:
887                 // This is used ONLY for testing when manually create "bad" blocks
888                 nfc_buf_mem_cpy((void *)(NAND_SPAR_BUF0), (void *)mem_addr, 16);
889                 if (!g_is_2k_page) {
890                         NFC_CMD_INPUT(FLASH_Read_Mode3);
891                 }
892                 break;
893         default:
894                 diag_printf("NOT supported yet!\n");
895                 return -1;
896         }
897
898         NFC_CMD_INPUT(FLASH_Send_Data);
899         start_nfc_addr_ops(ADDRESS_INPUT_PROGRAM_PAGE, flash_addr,
900                                            MXC_NAND_LA_MASK);
901
902         NFC_DATA_INPUT(RAM_BUF_0, area, g_ecc_enable);
903         if (g_is_2k_page && PG_2K_DATA_OP_MULTI_CYCLES()) {
904                 NFC_DATA_INPUT_2k(RAM_BUF_1);
905                 NFC_DATA_INPUT_2k(RAM_BUF_2);
906                 NFC_DATA_INPUT_2k(RAM_BUF_3);
907         }
908         NFC_CMD_INPUT(FLASH_Program);
909
910         flash_status = NFC_STATUS_READ();
911         // check I/O bit 0 to see if it is 0 for success
912         if ((flash_status & 0x1) != 0) {
913                 diag_printf("Error: failed to write page %d col=%d (address 0x%08x) status=0x%x\n",
914                                         flash_addr >> NAND_PG_SHIFT, flash_addr % NF_PG_SZ,
915                                         (flash_addr >> NAND_PG_SHIFT) * NF_PG_SZ + (flash_addr % NF_PG_SZ),
916                                         flash_status);
917                 return -1;
918         }
919
920         return 0;
921 }
922
923 /*!
924  * This function programs a page's main, spare, or both. For main area program,
925  * It copies out the spare area of that page first and then write it along
926  * with the main area back to the NAND flash (FIXME: can't just program main alone?
927  * For spare area program, it will scratch out the main area data (FIXME).
928  *
929  * @param ra                    starting address to be programmed inside the NAND flash.
930  *                                              Must be page-aligned
931  * @param mem_addr              source address in the RAM.
932  *                                              For main area:  mem_addr -> starting of data for main area
933  *                                              For spare area: mem_addr -> starting of data for spare area
934  *                                              For both area: mem_addr -> starting of data for main area along with spare area
935  * @return                              0 if no error or 1-bit error; -1 otherwise
936  */
937 // FIXME: Add programming of the spare area only
938 static int nfc_program_page(u32 ra, u32 mem_addr, enum nfc_page_area area)
939 {
940         u32 flash_addr;
941
942 //        diag_printf("%s(0x%08x, 0x%08x, %d\n", __FUNCTION__, ra, mem_addr, area);
943
944         if (ra % NF_PG_SZ) {
945                 diag_printf("** Error: Non page-aligned write not supported: 0x%08x\n", ra);
946                 return -1;
947         }
948         flash_addr = (ra / NF_PG_SZ) << NAND_PG_SHIFT;
949
950         return nfc_write_pg_random(flash_addr, mem_addr, area, 1);
951 }
952
953 /*!
954  * Low level spare-only read. Only applies to 512 byte page NAND.
955  *
956  * @param addr                  starting address to be read from the NAND flash
957  * @param buf                   one of the internal buffers
958  * @return                              0 if no error or 1-bit error; -1 otherwise
959  */
960 static int nfc_sp_only_read_ll(u32 addr, enum nfc_internal_buf buf)
961 {
962         volatile u16 temp;
963
964         NFC_CMD_INPUT(FLASH_Read_Mode3);
965         start_nfc_addr_ops(ADDRESS_INPUT_READ_PAGE, addr, MXC_NAND_LA_MASK);
966         NFC_DATA_OUTPUT(buf, FDO_SPARE_ONLY, g_ecc_enable);
967         temp = readw(ECC_STATUS_RESULT_REG);
968         NFC_CMD_INPUT(FLASH_Read_Mode1);
969
970         if (g_ecc_enable) {
971                 if ((temp & 0x2) != 0x0) {
972                         nfc_printf(NFC_DEBUG_MED, "\nError %d: %s(addr=0x%08x): ECC status result reg=0x%x\n",
973                                                 __LINE__, __FUNCTION__, addr, temp);
974                         return -1;
975                 }
976         }
977
978         return 0;
979 }
980
981 /*!
982  * Read spare area from NAND flash to the 1st internal RAM buffer. 
983  * Not supported for 2kB page NAND.
984  * 
985  * @param addr                  starting address to be read from the NAND flash
986  *
987  * @return                              0 if no error or 1-bit error; -1 otherwise
988  */
989 static int nfc_read_page_sp(u32 addr)
990 {
991         if (g_spare_only_read_ok) {
992                 if (g_is_2k_page) {
993                         diag_printf("** Error: spare-only read for 2k page is not supported\n");
994                         return -1;
995                 }
996                 return nfc_sp_only_read_ll(addr, RAM_BUF_0);
997         }
998         return -1;
999 }
1000
1001 static int nfc_read_pg_random(u32 flash_addr, int swap)
1002 {
1003         volatile u16 t1, t2 = 0, t3 = 0, t4 = 0;
1004         int res = 0;
1005                 
1006 #if 0 //TODO: kevin revisit
1007         if (!g_is_2k_page && (t1 = (flash_addr & ((1 << (1 + NAND_PG_SHIFT)) - 1))) >= 512) {
1008                         NFC_CMD_INPUT(FLASH_Read_Mode3);
1009                         flash_addr -= 512;
1010                         diag_printf("kevin: 0x%08x\n", flash_addr);
1011         } else {
1012                         NFC_CMD_INPUT(FLASH_Read_Mode1);
1013         }
1014 #endif
1015         nfc_printf(NFC_DEBUG_MAX, "%s: addr=%08x block=%6d page=%6d, col=%4d\n", __FUNCTION__,
1016                            flash_addr, (flash_addr >> NAND_PG_SHIFT) / NF_PG_PER_BLK,
1017                            flash_addr >> NAND_PG_SHIFT, flash_addr % NF_PG_SZ);
1018
1019         NFC_CMD_INPUT(FLASH_Read_Mode1);
1020
1021         start_nfc_addr_ops(ADDRESS_INPUT_READ_PAGE, flash_addr, MXC_NAND_LA_MASK);
1022         if (g_is_2k_page) {
1023                 NFC_CMD_INPUT(FLASH_Read_Mode1_2K);
1024         }
1025         
1026         if (g_nfc_version == MXC_NFC_V1) {
1027                 NFC_DATA_OUTPUT(RAM_BUF_0, FDO_PAGE_SPARE, g_ecc_enable);
1028                 t1 = readw(ECC_STATUS_RESULT_REG);
1029
1030                 if (g_is_2k_page) {
1031                         NFC_DATA_OUTPUT(RAM_BUF_1, FDO_PAGE_SPARE, g_ecc_enable);
1032                         t2 = readw(ECC_STATUS_RESULT_REG);
1033                         NFC_DATA_OUTPUT(RAM_BUF_2, FDO_PAGE_SPARE, g_ecc_enable);
1034                         t3 = readw(ECC_STATUS_RESULT_REG);
1035                         NFC_DATA_OUTPUT(RAM_BUF_3, FDO_PAGE_SPARE, g_ecc_enable);
1036                         t4 = readw(ECC_STATUS_RESULT_REG);
1037                 }
1038                 
1039                 if (g_ecc_enable && ((t1 & 0xA) != 0x0 || (t2 & 0xA) != 0x0 || (t3 & 0xA) != 0x0
1040                         || (t4 & 0xA) != 0x0)) {
1041                         diag_printf("** Error: uncorrectable ECC error in flash at addr 0x%08x page %d, col %d: ECC status=0x%x:0x%x:0x%x:0x%x\n",
1042                                                 (flash_addr >> NAND_PG_SHIFT) * NF_PG_SZ + (flash_addr % NF_PG_SZ),
1043                                                 flash_addr >> NAND_PG_SHIFT,
1044                                                 flash_addr % NF_PG_SZ, t1, t2, t3, t4);
1045                         res = -1;
1046                         goto out;
1047                 }
1048         } else if (g_nfc_version == MXC_NFC_V2) {
1049                 NFC_DATA_OUTPUT(RAM_BUF_0, FDO_PAGE_SPARE, g_ecc_enable);
1050                 if (g_is_2k_page) {
1051                         if (PG_2K_DATA_OP_MULTI_CYCLES()) {
1052                                 NFC_DATA_OUTPUT(RAM_BUF_1, FDO_PAGE_SPARE, g_ecc_enable);
1053                                 NFC_DATA_OUTPUT(RAM_BUF_2, FDO_PAGE_SPARE, g_ecc_enable);
1054                                 NFC_DATA_OUTPUT(RAM_BUF_3, FDO_PAGE_SPARE, g_ecc_enable);
1055                         }
1056                         // To replace the data at offset 0x400 with the address of the NFC base
1057                         // This is needed for certain platforms 
1058                         if ((flash_addr <= 0x400) && ((flash_addr + NF_PG_SZ - 1) > 0x400)) {
1059 //                                diag_printf("\nRead: flash_addr = 0x%08x\n", flash_addr);
1060                                 diag_printf("\n[INFO] 2K page: copy back data from spare to 0x400\n");
1061                                 writel(readl(NAND_SPAR_BUF2), NFC_BASE + 0x400);
1062                         }
1063                 } else {
1064                         // To replace the data at offset 0x400 with the address of the NFC base
1065                         // This is needed for certain platforms 
1066                         if ((flash_addr <= 0x400) && ((flash_addr + NF_PG_SZ - 1) > 0x400)) {
1067                                 diag_printf("\nflash_addr = 0x%08x\n", flash_addr);
1068                                 diag_printf("\n[INFO] 512 page: copy back data from spare to 0x400\n");
1069                                 writel(readl(NAND_SPAR_BUF0), NFC_BASE);
1070                         }
1071                 }
1072                 if (g_ecc_enable) {
1073                         t1 = readw(ECC_STATUS_RESULT_REG);
1074                         if (!g_is_2k_page) {
1075                                 if ((t1 & 0xF) > 4) {
1076                                         diag_printf("** Error: uncorrectable ECC error at address 0x%08x page %d, col %d ECC status=0x%x\n",
1077                                                                 (flash_addr >> NAND_PG_SHIFT) * NF_PG_SZ + (flash_addr % NF_PG_SZ),
1078                                                                 flash_addr >> NAND_PG_SHIFT,
1079                                                                 flash_addr % NF_PG_SZ, t1 & 0xF);
1080                                         res = -1;
1081                                         goto out;
1082                                 }
1083                         } else {
1084                                 t2 = (t1 >> 4) & 0xF;
1085                                 t3 = (t1 >> 8) & 0xF;
1086                                 t4 = (t1 >> 12) & 0xF;
1087                                 if (t2 > 4 || t3 > 4 || t4 > 4) {
1088                                         diag_printf("** Error: uncorrectable ECC error at address 0x%08x page %d, col=%d ECC status=0x%x:0x%x:0x%x\n",
1089                                                                 (flash_addr >> NAND_PG_SHIFT) * NF_PG_SZ + (flash_addr % NF_PG_SZ),
1090                                                                 flash_addr >> NAND_PG_SHIFT,
1091                                                                 flash_addr % NF_PG_SZ, t2, t3, t4);
1092                                         res = -1;
1093                                         goto out;
1094                                 }
1095                         }
1096                 }
1097         }
1098 out:
1099         if (g_is_2k_page) {
1100 #ifdef NFC_2K_BI_SWAP
1101                 if (swap)
1102                         mxc_swap_2k_BI_main_sp(1);
1103 #endif
1104         }
1105         return res;
1106 }
1107
1108 /*!
1109  * Read a page's both main and spare area from NAND flash to the internal RAM buffer.
1110  * It always reads data to the internal buffer 0.
1111  *
1112  * @param ra              starting address to be read from the NAND flash; must be page-aligned
1113  *
1114  * @return                              0 if no error or 1-bit error; -1 otherwise
1115  */
1116 static int nfc_read_page(u32 ra)
1117 {
1118         u32 flash_addr;
1119
1120         if (ra % NF_PG_SZ) {
1121                 diag_printf("Non page-aligned read not supported here: 0x%08x\n", ra);
1122                 return -1;
1123         }
1124
1125         flash_addr = (ra / NF_PG_SZ) << NAND_PG_SHIFT;
1126
1127         return nfc_read_pg_random(flash_addr, 1);
1128 }
1129
1130 // Read data into buffer
1131 int flash_read_buf(void* addr, void* data, int len)
1132 {
1133         if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
1134                 memcpy(data, addr, len);
1135                 return 0;
1136         } else {
1137                 return nfc_read_region((u32)addr, (u32)data, len);
1138         }
1139 }
1140
1141 void mxc_nfc_print_info(void)
1142 {
1143         diag_printf("[0x%08x bytes]: %d blocks of %d pages of %d bytes each.\n",
1144                                 NF_DEV_SZ, NF_BLK_CNT,
1145                                 NF_PG_PER_BLK, NF_PG_SZ);
1146 }
1147
1148 #ifdef MXCFLASH_FLASH_BASED_BBT
1149 /*
1150  * The NFC buffers cannot be accessed in byte mode.
1151  * This routine extracts one byte at a given location in the NFC buffer.
1152  */
1153
1154 /**
1155  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
1156  * @buf:        the buffer to search
1157  * @td:         search pattern descriptor
1158  *
1159  * Check for a pattern at the given place. Used to search bad block
1160  * tables and good / bad block identifiers.
1161  *
1162 */
1163 static int check_short_pattern(void *buf, struct nand_bbt_descr *td)
1164 {
1165         int i;
1166
1167         for (i = 0; i < td->len; i++) {
1168                 if (get_byte(buf, td->offs + i) != td->pattern[i]) {
1169                         return -1;
1170                 }
1171         }
1172         return 0;
1173 }
1174
1175 /**
1176  * search_bbt - [GENERIC] scan the device for a specific bad block table
1177  * @mtd:        MTD device structure
1178  * @buf:        temporary buffer
1179  * @td:         descriptor for the bad block table
1180  *
1181  * Read the bad block table by searching for a given ident pattern.
1182  * Search is preformed either from the beginning up or from the end of
1183  * the device downwards. The search starts always at the start of a
1184  * block.
1185  * If the option NAND_BBT_PERCHIP is given, each chip is searched
1186  * for a bbt, which contains the bad block information of this chip.
1187  * This is necessary to provide support for certain DOC devices.
1188  *
1189  * The bbt ident pattern resides in the oob area of the first page
1190  * in a block.
1191  */
1192 static int search_bbt(struct nand_bbt_descr *td)
1193 {
1194         int bits, startblock, block, dir;
1195         int bbtblocks;
1196         void *oob = (void *)NAND_SPAR_BUF0;
1197
1198         /* Search direction top -> down ? */
1199         if (td->options & NAND_BBT_LASTBLOCK) {
1200                 startblock = (NF_DEV_SZ / NF_BLK_SZ) - 1;
1201                 dir = -1;
1202         } else {
1203                 startblock = 0;
1204                 dir = 1;
1205         }
1206
1207         bbtblocks = NF_DEV_SZ / NF_BLK_SZ;
1208
1209         /* Number of bits for each erase block in the bbt */
1210         bits = td->options & NAND_BBT_NRBITS_MSK;
1211
1212         /* Reset version information */
1213         td->version = 0;
1214         td->pages = -1;
1215         /* Scan the maximum number of blocks */
1216         for (block = 0; block < td->maxblocks; block++) {
1217                 int actblock = startblock + dir * block;
1218                 int ret;
1219
1220                 nfc_printf(NFC_DEBUG_MAX, "%s: Reading block %d (page %d) addr %08x\n", __FUNCTION__,
1221                                    actblock, actblock * NF_PG_PER_BLK, actblock * NF_BLK_SZ);
1222
1223                 ret = nfc_read_page(actblock * NF_BLK_SZ);
1224                 if (ret != 0) {
1225                         nfc_printf(NFC_DEBUG_MED, "Failed to read bbt page %d\n",
1226                                            actblock * NF_PG_PER_BLK);
1227                         continue;
1228                 }
1229                 if (check_short_pattern(oob, td) == 0) {
1230                         nfc_printf(NFC_DEBUG_MED, "Found bbt pattern in block %d\n", actblock);
1231                         td->pages = actblock * NF_PG_PER_BLK;
1232                         if (td->options & NAND_BBT_VERSION) {
1233                                 td->version = get_byte(oob, td->veroffs);
1234                         }
1235                         break;
1236                 }
1237                 nfc_printf(NFC_DEBUG_MED, "No bbt pattern in block %d\n", actblock);
1238         }
1239         startblock += flash_dev_info->chipsize / NF_BLK_SZ;
1240
1241         /* Check, if we found a bbt */
1242         if (td->pages == -1) {
1243                 nfc_printf(NFC_DEBUG_MED, "Bad block table not found\n");
1244                 return -1;
1245         } else {
1246                 nfc_printf(NFC_DEBUG_MED, "Bad block table found at page %d, version 0x%02X\n",
1247                                    td->pages, td->version);
1248         }
1249         return 0;
1250 }
1251
1252 /**
1253  * nand_isbad_bbt - [NAND Interface] Check if a block is bad
1254  * @mtd:        MTD device structure
1255  * @offs:       offset in the device
1256  * @allowbbt:   allow access to bad block table region
1257  *
1258 */
1259 int nand_isbad_bbt(u16 *bbt, int block, int allowbbt)
1260 {
1261         cyg_uint8 res;
1262
1263         block <<= 1;
1264         res = (get_byte(bbt, block >> 3) >> (block & 0x06)) & 0x03;
1265
1266         switch (res ^ 0x03) {
1267         case 0x00:
1268                 return 0;
1269         case 0x01:
1270                 return 1;
1271         case 0x02:
1272                 return allowbbt ? 0 : 1;
1273         }
1274         return 1;
1275 }
1276
1277 static int mxc_nfc_find_bbt(struct nand_bbt_descr *td, struct nand_bbt_descr *md)
1278 {
1279         int ret;
1280         int bad = 0;
1281         int block;
1282         int good;
1283         struct nand_bbt_descr *bd = NULL;
1284
1285         search_bbt(td);
1286         bad += td->pages >= 0; /* account for reserved bbt block */
1287         if (md != NULL) {
1288                 search_bbt(md);
1289                 bad += md->pages >= 0;
1290         }
1291         if (td->pages < 0 && (md != NULL && md->pages < 0)) {
1292                 diag_printf("No FLASH based bad block table found\n");
1293                 return -1;
1294         }
1295         if (md == NULL || md->version <= td->version) {
1296                 ret = nfc_read_page(td->pages * NF_PG_SZ);
1297                 if (ret == 0) {
1298                         bd = td;
1299                         nfc_printf(NFC_DEBUG_MIN, "Using normal bbt at page %d\n", bd->pages);
1300                 }
1301         }
1302         if (bd == NULL && md != NULL) {
1303                 ret = nfc_read_page(md->pages * NF_PG_SZ);
1304                 if (ret == 0) {
1305                         bd = md;
1306                         nfc_printf(NFC_DEBUG_MIN, "Using mirror bbt at page %d\n", bd->pages);
1307                 }
1308         }
1309         if (bd == NULL) {
1310                 ret = nfc_read_page(td->pages * NF_PG_SZ);
1311                 if (ret == 0) {
1312                         bd = td;
1313                         nfc_printf(NFC_DEBUG_MIN, "Using normal bbt at page %d\n", bd->pages);
1314                         nfc_update_blk_table(td->pages * NF_PG_SZ, 2);
1315                         bad++;
1316                 } else {
1317                         diag_printf("** Error: Failed to read bbt from flash\n");
1318                         return -1;
1319                 }
1320         }
1321         for (block = 0, good = 0; block < NF_BLK_CNT; block++) {
1322                 if (nand_isbad_bbt((u16 *)NAND_MAIN_BUF0, block, true)) {
1323                         nfc_update_blk_table(block * NF_BLK_SZ, true);
1324                         nfc_printf(NFC_DEBUG_MIN, "Block %d is marked bad in flash bbt\n", block);
1325                         bad++;
1326                 } else {
1327                         l_to_p_table[good] = block;
1328                         good++;
1329                 }
1330         }
1331         g_nfc_scan_done = true;
1332         nfc_printf(NFC_DEBUG_MIN, "%s: Found %d bad/reserved blocks\n", __FUNCTION__, bad);
1333         return bad;
1334 }
1335
1336 static inline void mxc_nfc_buf_clear(unsigned long buf, u8 pattern, int size)
1337 {
1338         int i;
1339         u16 *p = (u16 *)buf;
1340         u16 fill = pattern;
1341
1342         fill = (fill << 8) | pattern;
1343         for (i = 0; i < size >> 1; i++) {
1344                 p[i] = fill;
1345         }
1346 }
1347
1348 static int mxc_nfc_write_bbt(int block, int page)
1349 {
1350         int ret;
1351
1352         DBG(1, "%s: Writing bbt block %d page %d\n", __FUNCTION__,
1353                 block, page);
1354         ret = nfc_program_page_raw(block, page);
1355         if (ret != 0) {
1356                 DBG(0, "%s: Failed to write bbt block %d page %d\n", __FUNCTION__, block, page);
1357                 return ret;
1358         }
1359         nfc_update_blk_table(block * NF_BLK_SZ, 2);
1360         return 0;
1361 }
1362
1363 static int mxc_nfc_create_bbt(struct nand_bbt_descr *td, struct nand_bbt_descr *md)
1364 {
1365         int ret = 0;
1366         int block;
1367         int pg_offs = 0;
1368         int page = 0;
1369         u16 *buf = (u16 *)NAND_MAIN_BUF0;
1370         u16 *oob = (u16 *)NAND_SPAR_BUF0;
1371
1372         if (td->pages >= 0) {
1373                 return 1;
1374         }
1375         if (md->pages < 0) {
1376                 td->version = 1;
1377         } else {
1378                 td->version = md->version;
1379         }
1380         for (block = NF_BLK_CNT - 1; block >= NF_BLK_CNT - td->maxblocks - 1; block--) {
1381                 int pg = block * NF_PG_PER_BLK;
1382
1383                 if ((bad_block_code(block) & ~2) == 0) {
1384                         if (md != NULL && md->pages == pg) {
1385                                 continue;
1386                         }
1387                         td->pages = pg;
1388                         break;
1389                 }
1390         }
1391         if (td->pages < 0) {
1392                 return -1;
1393         }
1394         mxc_nfc_buf_clear(NAND_SPAR_BUF0, 0xff, NF_SPARE_SZ);
1395         mxc_nfc_buf_clear(NAND_MAIN_BUF0, 0xff, NF_PG_SZ);
1396
1397         DBG(0, "%s: Creating bbt %c%c%c%c version %d\n", __FUNCTION__,
1398                 td->pattern[0], td->pattern[1], td->pattern[2], td->pattern[3], td->version);
1399         nfc_buf_mem_cpy(oob + (td->offs >> 1), td->pattern, td->len);
1400         store_byte(oob, td->veroffs, td->version);
1401
1402         for (block = 0, pg_offs = 0; block < NF_BLK_CNT;) {
1403                 u16 tmp = 0xffff;
1404                 int i;
1405
1406                 if (pg_offs << 1 >= NF_PG_SZ) {
1407                         ret = mxc_nfc_write_bbt(td->pages / NF_PG_PER_BLK, page);
1408                         if (ret != 0) {
1409                                 return ret;
1410                         }
1411                         page++;
1412                         mxc_nfc_buf_clear(NAND_SPAR_BUF0, 0xff, NF_SPARE_SZ);
1413                         mxc_nfc_buf_clear(NAND_MAIN_BUF0, 0xff, NF_PG_SZ);
1414                         pg_offs = 0;
1415                 }
1416                 for (i = 0; i < 16 && block < NF_BLK_CNT; i += 2, block++) {
1417                         u8 code = bad_block_code(block);
1418                         if ((code & ~2) != 0) {
1419                                 tmp &= ~(code << i);
1420                                 DBG(2, "%s: bad block %d pattern[%p] %04x mask %04x\n", __FUNCTION__,
1421                                         block, &buf[pg_offs], tmp, 0x03 << i);
1422                         }
1423                 }
1424                 buf[pg_offs] = tmp;
1425                 pg_offs++;
1426         }
1427         if (pg_offs > 0) {
1428                 DBG(0, "%s: Writing final bbt block %d page %d\n", __FUNCTION__,
1429                         td->pages / NF_PG_PER_BLK, page);
1430                 ret = mxc_nfc_write_bbt(td->pages / NF_PG_PER_BLK, page);
1431         }
1432         return ret;
1433 }
1434 #endif
1435
1436 static int mxc_nfc_scan(bool verbose)
1437 {
1438         int addr, bad = -1;
1439         int i, j;
1440         u32 count1 = hal_timer_count(), count2;
1441
1442         g_nfc_scan_done = false;
1443
1444 #ifdef MXCFLASH_FLASH_BASED_BBT
1445         bad = mxc_nfc_find_bbt(g_mxc_nfc_bbt_main_descr, g_mxc_nfc_bbt_mirror_descr);
1446 #endif
1447         if (bad < 0) {
1448                 for (i = 0, j = 0, addr = 0; addr < NF_DEV_SZ; addr += NF_BLK_SZ, i++) {
1449                         if (nfc_is_badblock(addr)) {
1450                                 bad++;
1451                                 nfc_update_blk_table(addr, true);
1452                                 if (verbose)
1453                                         nfc_printf(NFC_DEBUG_DEF, "      block %d at 0x%08x\n",
1454                                                            OFFSET_TO_BLOCK(addr), addr);
1455                         } else {
1456                                 nfc_update_blk_table(addr, false);
1457                                 l_to_p_table[j] = i;
1458                                 j++;
1459                         }
1460                 }
1461         }
1462 #ifdef MXCFLASH_FLASH_BASED_BBT
1463         if (mxc_nfc_create_bbt(g_mxc_nfc_bbt_main_descr, g_mxc_nfc_bbt_mirror_descr) == 0) {
1464                 bad++; /* account for reserved block for main bbt */
1465         }
1466         if (g_mxc_nfc_bbt_mirror_descr != NULL) {
1467                 if (mxc_nfc_create_bbt(g_mxc_nfc_bbt_mirror_descr, g_mxc_nfc_bbt_main_descr) == 0) {
1468                         bad++; /* account for reserved block for mirror bbt */
1469                 }
1470         }
1471 #endif
1472         if (g_nfc_debug_measure) {
1473                 count2 = hal_timer_count();
1474                 diag_printf("counter1=%d, counter2=%d, diff=%d\n",
1475                                         count1, count2, count2 - count1);
1476                 diag_printf("Using [diff * 1000000 / 32768] to get usec\n");
1477         }
1478         g_nfc_scan_done = true;
1479         return bad;
1480 }
1481
1482 ////////////////////////// "nand" commands support /////////////////////////
1483 // Image management functions
1484 local_cmd_entry("info",
1485                 "Show nand flash info (number of good/bad blocks)",
1486                 "[-f <raw address>] [-l <length>]",
1487                 nand_info,
1488                 NAND_cmds
1489                    );
1490
1491 local_cmd_entry("show",
1492                 "Show a page main/spare areas or spare area only (-s)",
1493                 "-f <raw page address> [-s]",
1494                 nand_show,
1495                 NAND_cmds
1496                    );
1497
1498 local_cmd_entry("read",
1499                 "Read data from nand flash into RAM",
1500                 "-f <raw address> -b <memory_load_address> -l <image_length> [-c <col_addr>]",
1501                 nand_read,
1502                 NAND_cmds
1503                    );
1504
1505 local_cmd_entry("write",
1506                 "Write data from RAM into nand flash",
1507                 "-f <raw address> -b <memory_address> -l <image_length> [-c <col_addr>]",
1508                 nand_write,
1509                 NAND_cmds
1510                    );
1511
1512 local_cmd_entry("erase",
1513                 "Erase nand flash contents",
1514                 "-f <raw address> -l <length> [-o] [-z] \n\
1515                                 -o: force erase (even for bad blocks) \n\
1516                                 -z: mark bad (testing only!)",
1517                 nand_erase,
1518                 NAND_cmds
1519                    );
1520
1521 #if 0
1522 local_cmd_entry("format",
1523                 "Check ALL blocks with ECC disabled and Erase the entire NAND flash with ECC ",
1524                 "-f <raw address> -l <length> [-o] [-z] \n\
1525                                 -o: force erase (even for bad blocks) \n\
1526                                 -z: mark bad (testing only!)",
1527                 nand_format,
1528                 NAND_cmds
1529                    );
1530 #endif
1531 local_cmd_entry("debug",
1532                 "Various NAND debug features ",
1533                 "<0> min debug messages <default> \n\
1534                          <1> med debug messages \n\
1535                          <2> max debug messages \n\
1536                          <3> enable(default)/disable h/w ECC for both r/w \n\
1537                          <4> disable(default)/enable spare-only read \n\
1538                          <9> enable/disable measurement \n\
1539                          no parameter - display current debug setup",
1540                 nand_debug_fun,
1541                 NAND_cmds
1542                    );
1543
1544 // Define table boundaries
1545 CYG_HAL_TABLE_BEGIN(__NAND_cmds_TAB__, NAND_cmds);
1546 CYG_HAL_TABLE_END(__NAND_cmds_TAB_END__, NAND_cmds);
1547
1548 extern struct cmd __NAND_cmds_TAB__[], __NAND_cmds_TAB_END__;
1549
1550 // CLI function
1551 static cmd_fun do_nand_cmds;
1552 RedBoot_nested_cmd("nand",
1553                                    "Utility function to NAND flash using raw address",
1554                                    "{cmds}",
1555                                    do_nand_cmds,
1556                                    __NAND_cmds_TAB__, &__NAND_cmds_TAB_END__
1557                                    );
1558
1559 static void nand_usage(char *why)
1560 {
1561         diag_printf("*** invalid 'nand' command: %s\n", why);
1562         cmd_usage(__NAND_cmds_TAB__, &__NAND_cmds_TAB_END__, "nand ");
1563 }
1564
1565 static u32 curr_addr;
1566 static void nand_show(int argc, char *argv[])
1567 {
1568         u32 ra;
1569         bool flash_addr_set = false;
1570         bool spar_only = false;
1571         struct option_info opts[2];
1572
1573         init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
1574                   (void *)&ra, (bool *)&flash_addr_set, "NAND FLASH memory byte address");
1575         init_opts(&opts[1], 's', false, OPTION_ARG_TYPE_FLG,
1576                   (void *)&spar_only, (bool *)0, "Spare only");
1577
1578         if (!scan_opts(argc, argv, 2, opts, 2, 0, 0, "")) {
1579                 return;
1580         }
1581         if (!flash_addr_set) {
1582                 ra = curr_addr;
1583                 curr_addr += NF_PG_SZ;
1584         } else {
1585                 curr_addr = ra;
1586         }
1587
1588         ra &= MXC_NAND_LA_MASK;
1589
1590         if (ra % NF_PG_SZ) {
1591                 diag_printf("** Error: address not page aligned\n");
1592                 return;
1593         }
1594
1595         if (nfc_is_badblock(NFC_BLOCK_ALIGN(ra))) {
1596                 diag_printf("This is a bad block\n");
1597         }
1598
1599         print_page(ra, spar_only);
1600 }
1601
1602 /*!
1603  * For low level nand read command. It doesn't check for bad block or not
1604  */
1605 static void nand_read(int argc, char *argv[])
1606 {
1607         int len;
1608         unsigned long mem_addr, ra, col;
1609         bool mem_addr_set = false;
1610         bool flash_addr_set = false;
1611         bool length_set = false;
1612         bool col_set = false;
1613         struct option_info opts[4];
1614         int j = 0;
1615         bool ecc_status = g_ecc_enable;;
1616
1617         init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
1618                           &mem_addr, &mem_addr_set, "memory base address");
1619         init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM,
1620                           &ra, &flash_addr_set, "FLASH memory base address");
1621         init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
1622                           &len, &length_set, "image length [in FLASH]");
1623         init_opts(&opts[3], 'c', true, OPTION_ARG_TYPE_NUM,
1624                           &col, &col_set, "column addr");
1625         
1626         if (!scan_opts(argc, argv, 2, opts, 4, 0, 0, 0)) {
1627                 nand_usage("invalid arguments");
1628                 return;
1629         }
1630
1631         if (!mem_addr_set || !flash_addr_set || !length_set) {
1632                 nand_usage("required parameter missing");
1633                 return;
1634         }
1635         if ((mem_addr < (CYG_ADDRESS)ram_start) ||
1636                 ((mem_addr + len) >= (CYG_ADDRESS)ram_end)) {
1637                 diag_printf("** WARNING: RAM address: %08lx may be invalid\n", mem_addr);
1638                 diag_printf("   valid range is %p-%p\n", ram_start, ram_end);
1639         }
1640
1641         // Safety check - make sure the address range is not within the code we're running
1642         if (flash_code_overlaps((void *)ra, (void *)(ra+len-1))) {
1643                 diag_printf("**Error: Can't program this region - contains code in use!\n");
1644                 return;
1645         }
1646         
1647         if (col_set) {
1648                 u32 flash_addr = ((ra / NF_PG_SZ) << NAND_PG_SHIFT) + col;
1649
1650                 diag_printf("Random read at page %ld, column %ld (addr %08x)\n",
1651                                         ra / NF_PG_SZ, col, flash_addr);
1652
1653                 if (g_is_2k_page) {
1654                         g_ecc_enable = false;
1655                 }
1656                 nfc_read_pg_random(flash_addr, 0); // don't swap BI for 2k page
1657                 if (g_is_2k_page) {
1658                         g_ecc_enable = ecc_status;
1659                 }
1660                 
1661                 nfc_buf_mem_cpy((void *)mem_addr, (void *)NAND_MAIN_BUF0, NF_PG_SZ);
1662                 return;
1663         }
1664         
1665         // ensure integer multiple of page size
1666         len = (len + NF_PG_SZ - 1) & ~(NF_PG_SZ - 1);
1667         ra &= MXC_NAND_LA_MASK;
1668
1669         do {
1670                 if (OFFSET_TO_BLOCK(ra) > (NF_BLK_CNT - 1)) {
1671                         diag_printf("Out of range: addr=0x%08lx\n", ra);
1672                         return;
1673                 }
1674                 if (nfc_read_page(ra) != 0) {
1675                         diag_printf("** Error: uncorrectable ECC at addr 0x%08lx\n", ra);
1676                         diag_printf("should invoke bad block management to replace this block\n");
1677                         diag_printf("and then mark this block \"bad\". But Redboot doesn't do it yet.\n");
1678                 }
1679                 if ((j++ % 0x20) == 0)
1680                         diag_printf("\n%s 0x%08lx: ", __FUNCTION__, ra);
1681                 diag_printf(".");
1682
1683                 nfc_buf_mem_cpy((void *)mem_addr, (void *)NAND_MAIN_BUF0, NF_PG_SZ);
1684
1685                 ra += NF_PG_SZ;
1686                 mem_addr += NF_PG_SZ;
1687                 len -= NF_PG_SZ;
1688         } while (len > 0);
1689         diag_printf("\n");
1690 }
1691
1692 static void nand_write(int argc, char *argv[])
1693 {
1694         int len, j = 0;
1695         u32 mem_addr, ra, col;
1696         bool mem_addr_set = false;
1697         bool flash_addr_set = false;
1698         bool length_set = false;
1699         bool col_set = false;
1700         struct option_info opts[4];
1701         bool ecc_status = g_ecc_enable;;
1702
1703         init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
1704                           (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");
1705         init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM,
1706                           (void *)&ra, (bool *)&flash_addr_set, "FLASH memory base address");
1707         init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
1708                           (void *)&len, (bool *)&length_set, "image length [in FLASH]");
1709         init_opts(&opts[3], 'c', true, OPTION_ARG_TYPE_NUM,
1710                           (void *)&col, (bool *)&col_set, "column addr");
1711         if (!scan_opts(argc, argv, 2, opts, 4, 0, 0, 0))
1712         {
1713                 nand_usage("invalid arguments");
1714                 return;
1715         }
1716
1717         if (!mem_addr_set || !flash_addr_set || !length_set) {
1718                 nand_usage("required parameter missing");
1719                 return;
1720         }
1721
1722         if ((mem_addr < (CYG_ADDRESS)ram_start) ||
1723                 ((mem_addr+len) >= (CYG_ADDRESS)ram_end)) {
1724                 diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr);
1725                 diag_printf("   valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
1726         }
1727
1728         if (col_set) {
1729                 u32 flash_addr = ((ra / NF_PG_SZ) << NAND_PG_SHIFT) + col;
1730
1731                 diag_printf("Random write at page %d, column %d (addr %08x)\n",
1732                                         ra / NF_PG_SZ, col, flash_addr);
1733                 
1734                 if (g_is_2k_page) {
1735                         g_ecc_enable = false;
1736                 }
1737                 nfc_write_pg_random(flash_addr, mem_addr, NFC_MAIN_ONLY, 0);
1738                 if (g_is_2k_page) {
1739                         g_ecc_enable = ecc_status;
1740                 }
1741                 return;
1742         }
1743
1744         ra &= MXC_NAND_LA_MASK;
1745
1746         if ((len % NF_PG_SZ) != 0) {
1747                 diag_printf("Not a full page write?\n\n");
1748         }
1749
1750         do {
1751                 if (OFFSET_TO_BLOCK(ra) > (NF_BLK_CNT - 1)) {
1752                         diag_printf("Out of range: addr=0x%08x\n", ra);
1753                         return;
1754                 }
1755                 if (nfc_is_badblock(ra)) {
1756                         diag_printf("\nERROR: bad block at raw addr=0x%08x(block=%d)\n",
1757                                            ra, OFFSET_TO_BLOCK(ra));
1758                         diag_printf("%s() failed\n", __FUNCTION__);
1759                         return;
1760                 }
1761
1762                 if (nfc_program_page(ra, mem_addr, NFC_MAIN_ONLY) != 0) {
1763                         if (g_nfc_debug_level >= NFC_DEBUG_DEF) {
1764                                 diag_printf("Error %d: program error at addr 0x%08x\n", __LINE__, ra);
1765                                 diag_printf("should invoke bad block management to replace this block \n");
1766                                 diag_printf("and then mark this block \"bad\". But Redboot doesn't do it yet.\n");
1767                         }
1768                         return;
1769                 }
1770                 if ((j++ % 0x20) == 0)
1771                         diag_printf("\nProgramming 0x%08x: ", ra);
1772                 diag_printf(".");
1773                 
1774                 len -= NF_PG_SZ;
1775                 ra += NF_PG_SZ;
1776                 mem_addr += NF_PG_SZ;
1777         } while (len > 0);
1778         diag_printf("\n");
1779 }
1780
1781 void nand_debug_fun(int argc, char *argv[])
1782 {
1783         int opt;
1784
1785         if (argc == 3) {
1786                 opt = argv[2][0] - '0';
1787                 switch (opt) {
1788                 case 0:
1789                         g_nfc_debug_level = NFC_DEBUG_MIN;
1790                         break;
1791                 case 1:
1792                         g_nfc_debug_level = NFC_DEBUG_MED;
1793                         break;
1794                 case 2:
1795                         g_nfc_debug_level = NFC_DEBUG_MAX;
1796                         break;
1797                 case 3:
1798                         g_ecc_enable = g_ecc_enable? false: true;
1799                         break;
1800                 case 4:
1801                         // toggle g_spare_only_read_ok
1802                         g_spare_only_read_ok = g_spare_only_read_ok? false: true;
1803                         break;
1804                 case 9:
1805                         g_nfc_debug_measure = g_nfc_debug_measure? false: true;
1806                         break;
1807
1808                 default:
1809                         diag_printf("%s(%s) not supported\n", __FUNCTION__, argv[2]);
1810                         break;
1811
1812                 }
1813         }
1814         diag_printf("Current debug options are: \n");
1815         diag_printf("    h/w ECC: %s\n", g_ecc_enable ? "on":"off");
1816         diag_printf("    sp-only read: %s\n", g_spare_only_read_ok ? "on":"off");
1817         diag_printf("    measurement: %s\n", g_nfc_debug_measure ? "on":"off");
1818         diag_printf("    message level: %s\n", (g_nfc_debug_level == NFC_DEBUG_MIN) ? "min" : \
1819                 ((g_nfc_debug_level == NFC_DEBUG_MED) ? "med" : "max"));
1820 }
1821
1822 static void nand_erase(int argc, char *argv[])
1823 {
1824         u32 i, j = 0, len, ra;
1825         bool faddr_set = false;
1826         bool force_erase_set = false;
1827         bool force_bad_block_set = false;
1828         bool length_set = false;
1829         struct option_info opts[4];
1830
1831         init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
1832                           &ra, (bool *)&faddr_set, "FLASH memory base address");
1833         init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
1834                           &len, (bool *)&length_set, "length in bytes");
1835         init_opts(&opts[2], 'o', false, OPTION_ARG_TYPE_FLG,
1836                           &force_erase_set, (bool *)&force_erase_set, "force erases block");
1837         init_opts(&opts[3], 'z', false, OPTION_ARG_TYPE_FLG,
1838                           &force_bad_block_set, (bool *)&force_bad_block_set, "erases blocks and mark bad");
1839
1840         if (!scan_opts(argc, argv, 2, opts, 4, 0, 0, 0)) {
1841                 nand_usage("invalid arguments");
1842                 return;
1843         }
1844
1845         if (!faddr_set || !length_set) {
1846                 nand_usage("missing argument");
1847                 return;
1848         }
1849         if ((ra % NF_BLK_SZ) != 0 ||
1850                 (len % NF_BLK_SZ) != 0 || len == 0) {
1851                 diag_printf("Address or length is not block aligned or length is zero!\n");
1852                 diag_printf("Block size is 0x%08x\n", NF_BLK_SZ);
1853                 return;
1854         }
1855
1856         if (!verify_action("About to erase 0x%08x bytes from nand offset 0x%08x\n", len, ra)) {
1857                 diag_printf("** Aborted\n");
1858                 return;
1859         }
1860
1861         ra &= MXC_NAND_LA_MASK;
1862
1863         // now ra is block aligned
1864         if (force_erase_set == true) {
1865                 diag_printf("Force erase ...");
1866                 for (i = ra; i < (ra + len); i += NF_BLK_SZ) {
1867                         if (nfc_erase_blk(i) != 0) { //error
1868                                 diag_printf("\n**Error: could not erase block %d at address 0x%08x\n",
1869                                                         i / NF_BLK_SZ, i);
1870                                 goto nand_erase_out;               //don't erase bad block
1871                         } else {
1872                                 if ((j++ % 0x20) == 0)
1873                                         diag_printf("\nErasing 0x%08x: ", i);
1874                                 diag_printf(".");
1875                         }
1876                 }
1877                 diag_printf("\n");
1878         } else if (force_bad_block_set == true) {
1879                 u16 temp_spare_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1880                 
1881                 for (i = ra; i < (ra + len); i += NF_BLK_SZ) {
1882                         if (i == 0) {
1883                                 continue;
1884                         }
1885                         if (nfc_is_badblock(i)) {
1886                                 diag_printf("block at 0x%08x is already bad\n", i);
1887                                 continue;                       //don't erase bad block
1888                         }
1889                         diag_printf("Erasing ... \n");
1890
1891                         if (nfc_erase_blk(i) != 0) { //error
1892                                 diag_printf("\n**Error: could not erase block %d at address 0x%08x\n",
1893                                                         i / NF_BLK_SZ, i);
1894                                 goto nand_erase_out;               //don't erase bad block
1895                         }
1896
1897                         diag_printf("\nMarking bad block at: 0x%08x\n", i);
1898
1899                         if (nfc_program_page(i, (u32)temp_spare_buf, NFC_SPARE_ONLY) != 0) {
1900                                 diag_printf("**Error: Can't program block %d at address 0x%08x\n",
1901                                                         i / NF_BLK_SZ, i);
1902                                 continue;
1903                         }
1904                 }
1905         } else {
1906                 for (i = ra; i < (ra + len); i += NF_BLK_SZ) {
1907                         if (nfc_is_badblock(i)) {
1908                                 diag_printf("\nWarning: Skipping erase of bad/reserved block %d at address 0x%08x\n",
1909                                                         i / NF_BLK_SZ, i);
1910                                 continue;                       //don't erase bad block
1911                         }
1912                         if (nfc_erase_blk(i) != 0) { //error
1913                                 diag_printf("\n**Error: could not erase block %d at address 0x%08x\n",
1914                                                         i / NF_BLK_SZ, i);
1915                                 continue;                       //don't erase bad block
1916                         }
1917                         if ((j++ % 0x20) == 0)
1918                                 diag_printf("\nErasing 0x%08x: ", i);
1919                         diag_printf(".");
1920                 }
1921         }
1922 nand_erase_out:
1923         diag_printf("\n");
1924         mxc_nfc_scan(false);
1925 }
1926
1927 static int nfc_dump_bad_blocks(unsigned long ra, u32 len)
1928 {
1929         int i, j = 0;
1930
1931         for (i = 0; i < ((len + NF_BLK_SZ - 1) / NF_BLK_SZ); i++) {
1932                 u8 code = nfc_is_badblock(NFC_BLOCK_ALIGN(ra));
1933                 if (code != 0) {
1934                         diag_printf("block %ld at offset 0x%08lx is %s\n",
1935                                                 OFFSET_TO_BLOCK(ra), ra,
1936                                                 code == 2 ? "reserved" : "bad");
1937                         j++;
1938                 }
1939                 ra += NF_BLK_SZ;
1940         }
1941         return j;
1942 }
1943
1944 static void nand_info(int argc, char *argv[])
1945 {
1946         u32 i, j = 0, len, ra;
1947         bool flash_addr_set = false;
1948         bool flash_len_set = false;
1949         struct option_info opts[2];
1950
1951         init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
1952                           &ra, &flash_addr_set, "NAND FLASH memory byte address");
1953         init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
1954                           &len, &flash_len_set, "length");
1955
1956         if (!scan_opts(argc, argv, 2, opts, 2, 0, 0, 0)) {
1957                 nand_usage("invalid arguments");
1958                 return;
1959         }
1960
1961         if (nand_flash_index == -1) {
1962                 diag_printf("Can't find valid NAND flash: %d\n", __LINE__);
1963                 return;
1964         }
1965
1966         i = mxc_nfc_scan(true);
1967         if (!flash_addr_set) {
1968                 diag_printf("\nType: %s\n", flash_dev_info->vendor_info);
1969                 diag_printf("Total size:\t 0x%08x bytes (%d MB)\n", NF_DEV_SZ, NF_DEV_SZ / 0x100000);
1970                 diag_printf("Total blocks:\t 0x%x (%d)\n", NF_BLK_CNT, NF_BLK_CNT);
1971                 diag_printf("Block size:\t 0x%x (%d)\n", NF_BLK_SZ, NF_BLK_SZ);
1972                 diag_printf("Page size:\t 0x%x (%d)\n", NF_PG_SZ, NF_PG_SZ);
1973                 diag_printf("Pages per block: 0x%x (%d)\n", NF_PG_PER_BLK, NF_PG_PER_BLK);
1974
1975                 diag_printf("Bad blocks: \n");
1976
1977                 if (i == 0) {
1978                         diag_printf("  none\n");
1979                 } else {
1980                         nfc_dump_bad_blocks(0, NF_DEV_SZ);
1981                         diag_printf("\nTotal number of bad/reserved blocks: %d\n", i);
1982                 }
1983                 return;
1984         }
1985
1986         if (!flash_len_set) {
1987                 len = NF_DEV_SZ;
1988         }
1989
1990         ra &= MXC_NAND_LA_MASK;
1991
1992         if (ra % NF_BLK_SZ) {
1993                 diag_printf("** Error: address 0x%08x not aligned to block boundary\n", ra);
1994                 return;
1995         }
1996         diag_printf("\n");
1997         j = nfc_dump_bad_blocks(0, NF_DEV_SZ);
1998         diag_printf("==================================\n");
1999         diag_printf("Found %d bad block(s) out of %d\n", j, (len + NF_BLK_SZ - 1) / NF_BLK_SZ);
2000 }
2001
2002 static void do_nand_cmds(int argc, char *argv[])
2003 {
2004         struct cmd *cmd;
2005
2006         if (!mxcnfc_init_ok) {
2007                 diag_printf("\nWarning:NAND flash hasn't been initialized. Try \"factive nand\" first\n\n");
2008                 return;
2009         }
2010
2011         if (argc < 2) {
2012                 nand_usage("too few arguments");
2013                 return;
2014         }
2015         if ((cmd = cmd_search(__NAND_cmds_TAB__, &__NAND_cmds_TAB_END__,
2016                                                   argv[1])) != (struct cmd *)0) {
2017                 (cmd->fun)(argc, argv);
2018                 return;
2019         }
2020         nand_usage("unrecognized command");
2021 }
2022
2023 /*!
2024  * Display a memory region by 16-bit words
2025  * @param pkt   pointer to the starting address of the memory
2026  * @param len   byte length of the buffer to be displayed
2027  */
2028 static void print_pkt_16(u16* pkt, u32 len)
2029 {
2030         diag_printf("******************** %d bytes********************\n", len);
2031         u32 i = 0, tempLen = (len + 1) / 2;
2032
2033         while (tempLen >= 0) {
2034                 if (tempLen >= 8) {
2035                         diag_printf("[%03x-%03x] ", i*2, ((i*2)+14));
2036                         diag_printf("%04x %04x %04x %04x %04x %04x %04x %04x\n",
2037                                                 pkt[i], pkt[i+1], pkt[i+2], pkt[i+3],
2038                                                 pkt[i+4], pkt[i+5], pkt[i+6], pkt[i+7]);
2039                 } else {
2040                         if (tempLen == 0) {
2041                                 diag_printf("*************************************************\n");
2042                                 return;
2043                         }
2044                         diag_printf("[%03x-%03x] ", i*2, ((i*2)+14));
2045                         switch(tempLen) {
2046                                 case 1:
2047                                         diag_printf("%04x\n", pkt[i]);
2048                                         break;
2049                                 case 2:
2050                                         diag_printf("%04x %04x\n", pkt[i], pkt[i+1]);
2051                                         break;
2052                                 case 3:
2053                                         diag_printf("%04x %04x %04x\n", pkt[i], pkt[i+1], pkt[i+2]);
2054                                         break;
2055                                 case 4:
2056                                         diag_printf("%04x %04x %04x %04x\n", pkt[i],pkt[i+1], pkt[i+2],pkt[i+3]);
2057                                         break;
2058                                 case 5:
2059                                         diag_printf("%04x %04x %04x %04x %04x\n", pkt[i], pkt[i+1], pkt[i+2], pkt[i+3],pkt[i+4]);
2060                                         break;
2061                                 case 6:
2062                                         diag_printf("%04x %04x %04x %04x %04x %04x\n", pkt[i], pkt[i+1], pkt[i+2], pkt[i+3],pkt[i+4],
2063                                                          pkt[i+5]);
2064                                         break;
2065                                 case 7:
2066                                         diag_printf("%04x %04x %04x %04x %04x %04x %04x\n", pkt[i], pkt[i+1], pkt[i+2], pkt[i+3],pkt[i+4],
2067                                                          pkt[i+5], pkt[i+6]);
2068                                         break;
2069                         }
2070                 }
2071                 tempLen -= 8;
2072                 i += 8;
2073         }
2074 }
2075
2076 // addr = starting byte address within NAND flash
2077 static void print_page(u32 addr, bool spare_only)
2078 {
2079         u32 blk_num = OFFSET_TO_BLOCK(addr), pg_num = OFFSET_TO_PAGE(addr);
2080
2081         if (spare_only) {
2082                 if (nfc_read_page_sp(addr) != 0) {
2083                         diag_printf("Error %d: uncorrectable. But still printing ...\n", __LINE__);
2084                 }
2085         } else {
2086                 if (nfc_read_page(addr) != 0) {
2087                         diag_printf("Error %d: uncorrectable. But still printing ...\n", __LINE__);
2088                 }
2089         }
2090
2091         diag_printf("\n============ Printing block(%d) page(%d)  ==============\n",
2092                                 blk_num, pg_num);
2093
2094         diag_printf("<<<<<<<<< spare area >>>>>>>>>\n");
2095         print_pkt_16((u16*)(NAND_SPAR_BUF0), g_is_2k_page ? 64 : 16);
2096
2097         if (!spare_only) {
2098                 diag_printf("<<<<<<<<< main area >>>>>>>>>\n");
2099                 print_pkt_16((u16*)(NAND_MAIN_BUF0), NF_PG_SZ);
2100         }
2101
2102         diag_printf("\n");
2103 }