unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / devs / flash / arm / mxc / v2_0 / src / mxc_nfc.c
1 //==========================================================================
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 Initial version
46 // Date:                 2007-12-20 Update to support 4K page and bbt management.
47 // Purpose:
48 // Description:
49 //       -- Add bad block management according to Linux NAND MTD implementation.
50 //              Reference linux/drivers/mtd/nand/nand_bbt.c by Thomas Gleixner
51 //              Summary:
52 //                 1. Last 4 blocks are reserved for one main BBT and one
53 //                        mirror BBT (2 spare ones just in case a block turns bad.)
54 //                 2. The main BBT block's spare area starts with "Bbt0" followed
55 //                        by a version number starting from 1.
56 //                 3. The mirror BBT block's spare area starts with "1tbB" followed
57 //                        by a version number also starting from 1.
58 //                 4. The actual main area, starting from first page in the BBT block,
59 //                        is used to indicate if a block is bad or not through 2bit/block:
60 //                              * The table uses 2 bits per block
61 //                              * 11b:  block is good
62 //                              * 00b:  block is factory marked bad
63 //                              * 01b:  block is marked bad due to wear
64 //                              * 10b:  block is marked reserved (for BBT)
65 //              Redboot operations: During boot, it searches for the marker for
66 //                                                      either main BBT or mirror BBT based on the marker:
67 //                 case 1: Neither table is found:
68 //                                 Do the bad block scan of the whole flash with ECC off. Use
69 //                                 manufactor marked BI field to decide if a block is bad and
70 //                                 then build the BBT in RAM. Then write this table to both
71 //                                 main BBT block and mirror BBT block.
72 //                 case 2: Only one table is found:
73 //                                 Load the BBT from the flash and stored in the RAM.
74 //                                 Then build the 2nd BBT in the flash.
75 //                 case 3: If both tables found, load the one with higher version in the
76 //                                 RAM and then update the block with older BBT info with the
77 //                                 newer one. If same version, just then read out the table in
78 //                                 RAM.
79 //
80 //####DESCRIPTIONEND####
81 //
82 //==========================================================================
83
84 #include <pkgconf/hal.h>
85 #include <cyg/hal/hal_arch.h>
86 #include <cyg/hal/hal_cache.h>
87 #include <cyg/io/nand_bbt.h>
88 #include <redboot.h>
89 #include <stdlib.h>
90 #if 0
91 static int nfc_debug = 1;
92 #endif
93
94 #include CYGHWR_MEMORY_LAYOUT_H
95
96 #include <cyg/hal/hal_io.h>
97 #define  _FLASH_PRIVATE_
98 #include <cyg/io/flash.h>
99
100 #include CYGHWR_FLASH_NAND_BBT_HEADER
101
102 #include <cyg/io/imx_nfc.h>
103
104 #define ECC_FORCE_ON    1
105 #define ECC_FORCE_OFF   2
106
107 typedef u64 flash_addr_t;
108
109 enum blk_bad_type
110 {
111         BLK_GOOD = 0,
112         BLK_BAD_RUNTIME = 1,
113         BLK_RESERVED = 2,
114         BLK_BAD_FACTORY = 3,
115 };
116
117 #define diag_printf1(fmt...) CYG_MACRO_START                                            \
118                 if (g_nfc_debug_level >= NFC_DEBUG_MIN) diag_printf(fmt);       \
119 CYG_MACRO_END
120
121 #define MXC_UNLOCK_BLK_END              0xFFFF
122
123 extern unsigned int hal_timer_count(void);
124 int nfc_program_region(flash_addr_t addr, u8 *buf, u32 len);
125 int nfc_erase_region(flash_addr_t addr, u32 len, bool skip_bad, bool verbose);
126
127 static int nfc_write_pg_random(u32 pg_no, u32 pg_off, u8 *buf, u32 ecc_force);
128 static int nfc_read_pg_random(u32 pg_no, u32 pg_off, u32 ecc_force, u32 cs_line,
129                                                           u32 num_of_nand_chips);
130 static int nfc_erase_blk(u32 ra);
131 static void print_page(u32 addr, bool spare_only);
132 static int nfc_read_page(u32 cs_line, u32 pg_no, u32 pg_off);
133 static int mxc_nfc_scan(bool lowlevel);
134 static void read_nflash_id(u32 *id, u32 cs_line);
135 static int nfc_program_blk(u32 ra, u8 *buf, u32 len);
136
137 static void print_pkt_16(u16 *pkt, u32 len);
138
139 // globals
140 static int nand_flash_index = -1;
141 static int g_ecc_enable = true;
142 static int g_spare_only_read_ok = true;
143 static int g_nfc_debug_level = NFC_DEBUG_NONE;
144 static bool g_nfc_debug_measure = false;
145 static bool g_is_2k_page = false;
146 static unsigned long g_block_offset;
147 static bool g_is_4k_page = false;
148 static unsigned int g_nfc_version = MXC_NFC_V1; // default to version 1.0
149 static int      num_of_nand_chips = 1;
150 static int num_of_nand_chips_for_nandsize = 1;
151 static int scale_block_cnt = 1;
152
153 #define nfc_printf(level, args...) CYG_MACRO_START      \
154                 if (g_nfc_debug_level >= level)                         \
155                         diag_printf(args);                                              \
156 CYG_MACRO_END
157
158 #if defined(NFC_V2_0) || defined(NFC_V2_1)
159 #include <cyg/io/mxc_nfc_v2.h>
160 #elif defined(NFC_V3_0)
161 #include <cyg/io/mxc_nfc_v3.h>
162 #else
163 #include <cyg/io/mxc_nfc.h>
164 #endif
165
166 #ifndef NAND_LAUNCH_REG
167 #define NAND_LAUNCH_REG                         0xDEADEEEE
168 #define NAND_CONFIGURATION1_REG         0xDEADEEEE
169 #define NFC_FLASH_CONFIG2_REG           0xDEADEEEE
170 #define NFC_FLASH_CONFIG2_ECC_EN        0xDEADEEEE
171 #define write_nfc_ip_reg(a, b)
172 #endif
173
174 #ifndef MXCFLASH_SELECT_MULTI
175 void flash_query(void *data)
176 #else
177 void nandflash_query(void *data)
178 #endif
179 {
180         u32 id[2];
181         read_nflash_id(&id[0], 0);
182         nfc_printf(NFC_DEBUG_MAX, "%s(ID=0x%02x: 0x%02x, 0x%02x, 0x%02x)\n", __FUNCTION__,
183                            id[0] & 0xff, (id[0] >> 8) & 0xff, (id[0] >> 16) & 0xff, id[0] >> 24);
184         memcpy(data, id, sizeof(id));
185 }
186
187 #ifndef MXCFLASH_SELECT_MULTI
188 int flash_program_buf(void *addr, void *data, int len)
189 #else
190 int nandflash_program_buf(void *addr, void *data, int len)
191 #endif
192 {
193         nfc_printf(NFC_DEBUG_MAX, "%s(addr=%p, data=%p, len=0x%08x)\n",
194                            __FUNCTION__, addr, data, len);
195         return nfc_program_region((u32)addr, data, len);
196 }
197
198 #ifndef MXCFLASH_SELECT_MULTI
199 int flash_erase_block(void *block, unsigned int size)
200 #else
201 int nandflash_erase_block(void *block, unsigned int size)
202 #endif
203 {
204         nfc_printf(NFC_DEBUG_MAX, "%s(block=%p, size=0x%08x)\n",
205                            __FUNCTION__, block, size);
206         return nfc_erase_region((u32)block, size, 1, 0);
207 }
208
209 #ifndef MXCFLASH_SELECT_MULTI
210 bool flash_code_overlaps(void *start, void *end)
211 #else
212 bool nandflash_code_overlaps(void *start, void *end)
213 #endif
214 {
215         extern unsigned char _stext[], _etext[];
216
217         return ((((unsigned long)&_stext >= (unsigned long)start) &&
218                          ((unsigned long)&_stext < (unsigned long)end)) ||
219                         (((unsigned long)&_etext >= (unsigned long)start) &&
220                          ((unsigned long)&_etext < (unsigned long)end)));
221 }
222
223 #ifndef MXCFLASH_SELECT_MULTI
224 int flash_hwr_map_error(int e)
225 #else
226 int nandflash_hwr_map_error(int e)
227 #endif
228 {
229         return e;
230 }
231
232 #ifndef MXCFLASH_SELECT_MULTI
233 int flash_lock_block(void *block)
234 #else
235 int nandflash_lock_block(void *block)
236 #endif
237 {
238         // Not supported yet
239         return 0;
240 }
241
242 #ifndef MXCFLASH_SELECT_MULTI
243 int flash_unlock_block(void *block, int block_size, int blocks)
244 #else
245 int nandflash_unlock_block(void *block, int block_size, int blocks)
246 #endif
247 {
248         // Not supported yet
249         return 0;
250 }
251
252 //----------------------------------------------------------------------------
253 // Now that device properties are defined, include magic for defining
254 // accessor type and constants.
255 #include <cyg/io/flash_dev.h>
256
257 // Information about supported devices
258 typedef struct flash_dev_info {
259         cyg_uint16       device_id;
260         cyg_uint16       device_id2;
261         cyg_uint16       device_id3;
262         cyg_uint16       device_id4;
263         cyg_uint16       page_size;
264         cyg_uint16       spare_size;
265         cyg_uint32       pages_per_block;
266         cyg_uint32       block_size;
267         cyg_int32        block_count;
268         cyg_uint32       device_size;
269         cyg_uint32       port_size;             // x8 or x16 IO
270         cyg_uint32       type;                  // SLC vs MLC
271         cyg_uint32       options;
272         cyg_uint32       fis_start_addr;
273         cyg_uint32       bi_off;
274         cyg_uint32       bbt_blk_max_nr;
275         cyg_uint8        vendor_info[96];
276         cyg_uint32       col_cycle;                // number of column address cycles
277         cyg_uint32       row_cycle;                // number of row address cycles
278         cyg_uint32       max_bad_blk;
279 } flash_dev_info_t;
280
281 static const flash_dev_info_t *flash_dev_info;
282 static const flash_dev_info_t supported_devices[] = {
283 #include <cyg/io/mxc_nand_parts.inl>
284 };
285 #define NUM_DEVICES NUM_ELEMS(supported_devices)
286
287 #define COL_CYCLE                                       flash_dev_info->col_cycle
288 #define ROW_CYCLE                                       flash_dev_info->row_cycle
289 #define NF_PG_SZ                                        ((flash_dev_info->page_size) * num_of_nand_chips)
290 #define NF_SPARE_SZ                                     ((flash_dev_info->spare_size) * num_of_nand_chips)
291 #define NF_PG_PER_BLK                           flash_dev_info->pages_per_block
292 #define NF_DEV_SZ                                       ((flash_dev_info->device_size) * num_of_nand_chips_for_nandsize)
293 #define NF_BLK_SZ                                       ((flash_dev_info->block_size) * num_of_nand_chips)
294 #define NF_BLK_CNT                                      ((flash_dev_info->block_count) / scale_block_cnt)
295 #define NF_VEND_INFO                            flash_dev_info->vendor_info
296 #define NF_OPTIONS                                      flash_dev_info->options
297 #define NF_BBT_MAX_NR                           flash_dev_info->bbt_blk_max_nr
298 #define NF_OPTIONS                                      flash_dev_info->options
299 #define NF_BI_OFF                                       flash_dev_info->bi_off
300
301 #define MXC_NAND_ADDR_MASK                              (NF_DEV_SZ - 1)
302 #define BLOCK_TO_OFFSET(blk)                    ((blk) * NF_PG_PER_BLK * NF_PG_SZ)
303 #define BLOCK_TO_PAGE(blk)                              ((blk) * NF_PG_PER_BLK)
304 #define BLOCK_PAGE_TO_OFFSET(blk, pge)  (((blk) * NF_PG_PER_BLK + (pge)) * NF_PG_SZ)
305 #define OFFSET_TO_BLOCK(offset)                 (((offset) / NF_PG_SZ) / NF_PG_PER_BLK)
306 #define OFFSET_TO_PAGE(offset)                  (((offset) / NF_PG_SZ) % NF_PG_PER_BLK)
307
308 static u8 *g_bbt, *g_page_buf;
309 static u32 g_bbt_sz;
310 static bool mxcnfc_init_ok = false;
311 static bool mxc_nfc_scan_done;
312
313 // this callback allows the platform specific function to be called right
314 // after flash_dev_query()
315 nfc_setup_func_t *nfc_setup = NULL;
316
317 // this callback allows the platform specific iomux setup
318 nfc_iomuxsetup_func_t *nfc_iomux_setup = NULL;
319
320 int
321 #ifndef MXCFLASH_SELECT_MULTI
322 flash_hwr_init(void)
323 #else
324 nandflash_hwr_init(void)
325 #endif
326 {
327         u32 id[2];
328         int i;
329
330         nfc_printf(NFC_DEBUG_MAX, "%s()\n", __FUNCTION__);
331
332         if (nfc_iomux_setup)
333                 nfc_iomux_setup();
334
335         NFC_SET_NFC_ACTIVE_CS(0);
336         NFC_CMD_INPUT(FLASH_Reset);
337
338         // Look through table for device data
339         flash_dev_query(&id[0]);
340         flash_dev_info = supported_devices;
341         for (i = 0; i < NUM_DEVICES; i++) {
342                 if ((flash_dev_info->device_id == (id[0] & 0xffff)) &&
343                         (flash_dev_info->device_id2 == 0xFFFF ||
344                          flash_dev_info->device_id2 == (id[0] >> 16)))
345                         break;
346                 flash_dev_info++;
347         }
348
349         // Did we find the device? If not, return error.
350         if (NUM_DEVICES == i) {
351                 diag_printf("Unrecognized NAND part: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
352                                         id[0] & 0xff, (id[0] >> 8) & 0xff, (id[0] >> 16) & 0xff, id[0] >> 24);
353                 return FLASH_ERR_DRV_WRONG_PART;
354         }
355
356         nand_flash_index = i;
357         mxcnfc_init_ok = true;
358
359         if (NF_PG_SZ == 2048) {
360                 g_is_2k_page = true;
361                 g_spare_only_read_ok = false;
362         }
363         if (NF_PG_SZ == 4096) {
364                 g_is_4k_page = true;
365                 g_spare_only_read_ok = false;
366         }
367
368         nfc_printf(NFC_DEBUG_MED, "%s(): %d out of NUM_DEVICES=%d, id=0x%02x\n",
369                            __FUNCTION__, i, NUM_DEVICES, flash_dev_info->device_id);
370
371         if (nfc_setup) {
372                 g_nfc_version = nfc_setup(NF_PG_SZ / num_of_nand_chips, flash_dev_info->port_size,
373                                                                   flash_dev_info->type, num_of_nand_chips);
374         }
375         diag_printf1("NFC version: %02x\n", g_nfc_version);
376         if (g_nfc_version == MXC_NFC_V3) {
377                 for (i = 2; i <= NUM_OF_CS_LINES; i++) {
378                         u32 id_tmp[2];
379                         read_nflash_id(&id_tmp[0], i - 1);
380                         if (id[0] != id_tmp[0]) {
381                                 break;
382                         }
383                         /* Support interleave with 1, 2, 4, 8 chips */
384                         if (i == (num_of_nand_chips * 2)) {
385                                 num_of_nand_chips = i;
386                         }
387                         NFC_CMD_INPUT(FLASH_Reset);
388                 }
389
390                 if (nfc_setup && (num_of_nand_chips > 1)) {
391                         nfc_setup(NF_PG_SZ / num_of_nand_chips, flash_dev_info->port_size,
392                                                    flash_dev_info->type, num_of_nand_chips);
393                 }
394         }
395
396         NFC_ARCH_INIT();
397
398         g_bbt_sz = NF_BLK_CNT / 4;
399         g_bbt = malloc(g_bbt_sz); // two bit for each block
400         if (g_bbt == NULL) {
401                 diag_printf("%s(): failed to allocate %d byte for bbt\n", __FUNCTION__, g_bbt_sz);
402                 return FLASH_ERR_PROTOCOL;
403         }
404
405         g_page_buf = malloc(NF_PG_SZ); // for programming less than one page size buffer
406         if (g_page_buf == NULL) {
407                 diag_printf("%s(): failed to allocate %d byte page buffer\n", __FUNCTION__,
408                                         NF_PG_SZ);
409                 return FLASH_ERR_PROTOCOL;
410         }
411         memset(g_bbt, 0, g_bbt_sz);
412
413         /* For now cap off the Device size to 2GB */
414         i = 1;
415         while ((i <= num_of_nand_chips) && ((NF_DEV_SZ * i) < 0x80000000)) {
416                 num_of_nand_chips_for_nandsize = i;
417                 i *= 2;
418         }
419
420         scale_block_cnt = num_of_nand_chips / num_of_nand_chips_for_nandsize;
421         // Hard wired for now
422         flash_info.block_size = NF_BLK_SZ;
423         flash_info.blocks = NF_BLK_CNT - CYGNUM_FLASH_NAND_BBT_BLOCKS;
424         flash_info.start = (void *)MXC_NAND_BASE_DUMMY;
425         flash_info.end = (void *)(MXC_NAND_BASE_DUMMY + NF_DEV_SZ -
426                                                           CYGNUM_FLASH_NAND_BBT_BLOCKS * NF_BLK_SZ);
427
428         mxc_nfc_scan(false); // look for table
429
430         diag_printf1("%s(): block_size=0x%08x, blocks=0x%08x, start=%p, end=%p\n",
431                                  __FUNCTION__, flash_info.block_size, flash_info.blocks,
432                                  flash_info.start, flash_info.end);
433
434         return FLASH_ERR_OK;
435 }
436
437 // used by redboot/current/src/flash.c
438 int mxc_nand_fis_start(void)
439 {
440         return flash_dev_info->fis_start_addr * num_of_nand_chips;
441 }
442
443 static inline u8 get_byte(cyg_uint16 *buf, int offs)
444 {
445         cyg_uint16 word = buf[offs >> 1];
446         if (offs & 1) {
447                 return word >> 8;
448         }
449         return word & 0xff;
450 }
451
452 static inline void store_byte(cyg_uint16 *buf, int offs, u8 val)
453 {
454         cyg_uint16 word = buf[offs >> 1];
455
456         if (offs & 1) {
457                 word = (word & 0x00ff) | ((u16)val << 8);
458         } else {
459                 word = (word & 0xff00) | val;
460         }
461         buf[offs >> 1] = word;
462 }
463
464 static inline bool nfc_verify_addr(unsigned long dst, unsigned long len)
465 {
466         if (dst < NAND_MAIN_BUF0 || dst + len >= NAND_SPAR_BUF3 + NFC_SPARE_BUF_SZ) {
467                 diag_printf("%s: Bad NFC Buffer address 0x%08lx\n", __FUNCTION__, dst);
468                 return false;
469         }
470         return true;
471 }
472
473 static void nfc_buf_read(void *dst, unsigned long src, u32 len)
474 {
475         u16 *s = (u16 *)(src & ~1);
476         u8 *bp = dst;
477
478         if (len == 0) {
479                 return;
480         }
481         if (src + len < src) {
482                 diag_printf("%s: Bad address range 0x%08lx .. 0x%08lx\n", __FUNCTION__,
483                                         src, src + len);
484         }
485         if ((unsigned long)dst + len < (unsigned long)dst) {
486                 diag_printf("%s: Bad address range 0x%08lx .. 0x%08lx\n", __FUNCTION__,
487                                         (unsigned long)dst, (unsigned long)dst + len);
488         }
489         if (src < NAND_MAIN_BUF0 || src + len >= NAND_SPAR_BUF3 + NF_PG_SZ) {
490                 diag_printf("%s: Bad NFC Buffer address 0x%08lx\n", __FUNCTION__, src);
491                 return;
492         }
493         if ((unsigned long)dst >= NAND_MAIN_BUF0 &&
494                 (unsigned long)dst < NAND_SPAR_BUF3 + NF_PG_SZ) {
495                 diag_printf("%s: Bad memory address 0x%08lx\n", __FUNCTION__,
496                                         (unsigned long)dst);
497                 return;
498         }
499         if (src & 1) {
500                 *bp++ = get_byte(s, 1);
501                 s++;
502                 len--;
503         }
504         if ((unsigned long)bp & 1) {
505                 while (len > 1) {
506                         u16 word = *s++;
507                         *bp++ = word & 0xff;
508                         *bp++ = word >> 8;
509                         len -= 2;
510                 }
511         } else {
512                 u16 *wp = (u16 *)bp;
513
514                 while (len > 1) {
515                         *wp++ = *s++;
516                         len -= 2;
517                 }
518                 bp = (u8*)wp;
519         }
520         if (len != 0) {
521                 u16 word = *s;
522                 *bp = word & 0xff;
523         }
524 }
525
526 static void nfc_buf_write(unsigned long dst, void *src, u32 len)
527 {
528         u8 *bp = src;
529         u16 *d = (u16 *)(dst & ~1);
530
531         if (len == 0) {
532                 return;
533         }
534         if (!nfc_verify_addr(dst, len)) {
535                 return;
536         }
537         if (dst & 1) {
538                 store_byte(d, 1, *bp);
539                 d++;
540                 bp++;
541                 len--;
542         }
543         if ((unsigned long)bp & 1) {
544                 while (len > 1) {
545                         u16 word;
546                         word = *bp++;
547                         word |= (u16)(*bp++) << 8;
548                         *d++ = word;
549                         len -= 2;
550                 }
551         } else {
552                 u16 *wp = (u16 *)bp;
553                 while (len > 1) {
554                         *d++ = *wp++;
555                         len -= 2;
556                 }
557                 bp = (u8 *)wp;
558         }
559         if (len != 0) {
560                 store_byte(d, 1, *bp);
561         }
562 }
563
564 #ifndef NFC_V3_0
565 /*!
566  * Starts the address input cycles for different operations as defined in ops.
567  *
568  * @param ops                   operations as defined in enum nfc_addr_ops
569  * @param pg_no                 page number offset from 0
570  * @param pg_off                byte offset within the page
571  * @param is_erase              don't care for earlier NFC
572  * @param cs_line                don't care for earlier NFC
573  */
574 static void start_nfc_addr_ops(u32 ops, u32 pg_no, u32 pg_off, u32 is_erase,
575                                    u32 cs_line, u32 num_of_chips)
576 {
577         int i;
578
579         switch (ops) {
580         case FLASH_Read_ID:
581                 /* Only supports one NAND chip (CS0) */
582                 if (cs_line != 0)
583                         return;
584                 NFC_ADDR_INPUT(0);
585                 return;
586         case FLASH_Read_Mode1:
587         case FLASH_Program:
588                 for (i = 0; i < COL_CYCLE; i++, pg_off >>= 8) {
589                         NFC_ADDR_INPUT(pg_off & 0xFF);
590                 }
591                 // don't break on purpose
592         case FLASH_Block_Erase:
593                 for (i = 0; i < ROW_CYCLE; i++, pg_no >>= 8) {
594                         NFC_ADDR_INPUT(pg_no & 0xFF);
595                 }
596                 break;
597         default:
598                 diag_printf("!!!!!! %s(): wrong ops: %d !!!!!\n", __FUNCTION__, ops);
599                 return;
600         }
601 }
602 #endif                                  // #ifndef NFC_V3_0
603
604 static void read_nflash_id(u32 *id, u32 cs_line)
605 {
606         volatile u32 *ptr = (volatile u32*)NAND_MAIN_BUF0;
607
608     nfc_printf(NFC_DEBUG_MIN, "%s: read flash id from chip %d @ %p\n",
609                            __FUNCTION__, cs_line, ptr);
610
611         NFC_PRESET(MXC_UNLOCK_BLK_END);
612         NFC_SET_NFC_ACTIVE_CS(cs_line);
613         NFC_CMD_INPUT(FLASH_Read_ID);
614
615         start_nfc_addr_ops(FLASH_Read_ID, 0, 0, 0, cs_line, num_of_nand_chips);
616         NFC_DATA_OUTPUT(RAM_BUF_0, FDO_FLASH_ID, g_ecc_enable);
617
618     *id++ = *ptr++;
619     *id++ = *ptr++;
620 }
621
622 static void mark_blk_bad(unsigned int block, unsigned char *buf,
623                                                  enum blk_bad_type bad_type)
624 {
625         unsigned int off = block >> 2;           // byte offset - each byte can hold status for 4 blocks
626         unsigned int sft = (block & 3) << 1;  // bit shift 0, 2, 4, 6
627         unsigned char val = buf[off];
628
629         if (block > NF_BLK_CNT) {
630                 diag_printf("%s: Block number %u out of range: 0..%u\n", __FUNCTION__,
631                                         block, NF_BLK_CNT - 1);
632                 return;
633         }
634         val = (val & ~(3 << sft)) | (bad_type << sft);
635         buf[off] = val;
636 }
637
638 /*!
639  * Checks to see if a block is bad. If buf is not NULL, it indicates a valid
640  * BBT in the RAM. In this case, it assumes to have 2-bit to represent each
641  * block for good or bad
642  *                              * 11b:  block is good
643  *                              * 00b:  block is factory marked bad
644  *                              * 01b:  block is marked bad due to wear
645  *                              * 10b:  block is marked reserved (for BBT)
646  * If buf is NULL, then it indicates a low level scan based on the certain
647  * offset value in certain pages and certain offset to be non-0xFF. In this
648  * case, the HW ECC will be turned off.
649  *
650  * @param block         0-based block number
651  * @param buf           BBT buffer. Could be NULL (see above explanation)
652  *
653  * @return                      1 if bad block; 0 otherwise
654  */
655 static int nfc_is_badblock(u32 block, u8 *buf)
656 {
657         u32 off;           // byte offset
658         u32 sft;           // bit shift 0, 2, 4, 6
659         flash_addr_t addr;
660         u16 temp, i;
661         int res;
662         u32 pg_no;
663
664         if (buf) {
665                 // use BBT
666                 off = block >> 2;               // byte offset
667                 sft = (block & 3) << 1;  // bit shift 0, 2, 4, 6
668                 res = (buf[off] >> sft) & 0x3;
669                 if (res) {
670                         addr = BLOCK_TO_OFFSET(block);
671                         diag_printf1("Block %u at %08llx is marked %s (%d) in BBT@%p[%02x] mask %02x\n",
672                                                  block, (u64)addr, res == BLK_RESERVED ? "reserved" :
673                                                  res == BLK_BAD_FACTORY ? "factory bad" : "runtime bad",
674                                                  res, buf, off, 3 << sft);
675                 }
676                 return res;
677         }
678
679         // need to do low level scan with ECC off
680         if (NF_OPTIONS & NAND_BBT_SCANLSTPAGE) {
681                 if (g_is_4k_page || g_is_2k_page) {
682                         addr = (block + 1) * NF_BLK_SZ - NF_PG_SZ;
683                         pg_no = addr / NF_PG_SZ;
684                         for (i = 0; i < num_of_nand_chips; i++) {
685                                 // we don't do partial page read here. No ecc either
686                                 nfc_read_pg_random(pg_no, 0, ECC_FORCE_OFF, i, num_of_nand_chips);
687                                 temp = readw((u32)NAND_MAIN_BUF0 + NF_BI_OFF);
688                                 if ((temp & 0xFF) != 0xFF) {
689                                         return BLK_BAD_FACTORY;
690                                 }
691                         }
692                 } else {
693                         diag_printf("only 2K/4K page is supported\n");
694                         // die here -- need to fix the SW
695                         while (1);
696                 }
697                 return 0;
698         }
699         addr = block * NF_BLK_SZ;
700         pg_no = addr / NF_PG_SZ;
701         for (i = 0; i < num_of_nand_chips; i++) {
702                 nfc_read_pg_random(pg_no, 0, ECC_FORCE_OFF, i, num_of_nand_chips); // no ecc
703                 if (g_is_2k_page || g_is_4k_page) {
704                         temp = readw(NAND_MAIN_BUF0 + NF_BI_OFF);
705                 } else {
706                         temp = readw(NAND_SPAR_BUF0 + 4) >> 8; // BI is at 5th byte in spare area
707                 }
708                 if ((temp & 0xFF) != 0xFF) {
709                         return BLK_BAD_FACTORY;
710                 }
711         }
712         if (NF_OPTIONS & NAND_BBT_SCAN2NDPAGE) {
713                 addr += NF_PG_SZ;
714                 pg_no++;
715                 for (i = 0; i < num_of_nand_chips; i++) {
716                         nfc_read_pg_random(pg_no, 0, ECC_FORCE_OFF, i, num_of_nand_chips); // no ecc
717                         if (g_is_2k_page || g_is_4k_page) {
718                                 temp = readw(NAND_MAIN_BUF0 + NF_BI_OFF);
719                         } else {
720                                 temp = readw(NAND_SPAR_BUF0 + 4) >> 8; // BI is at 5th byte in spare area
721                         }
722                         if ((temp & 0xFF) != 0xFF) {
723                                 return BLK_BAD_FACTORY;
724                         }
725                 }
726         }
727         return 0;
728 }
729
730 /*
731  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
732  * @buf:        the buffer to search
733  * @td:         search pattern descriptor
734  *
735  * Check for a pattern at the given place. Used to search bad block
736  * tables and good / bad block identifiers.
737 */
738 static int check_short_pattern(void *buf, struct nand_bbt_descr *td)
739 {
740         int i;
741
742         for (i = 0; i < td->len; i++) {
743                 if (get_byte(buf, td->offs + i) != td->pattern[i]) {
744                         return -1;
745                 }
746         }
747         return 0;
748 }
749
750 static int nfc_write_page(u32 pg_no, u32 pg_off, u32 ecc_force);
751 /*
752  * Program g_bbt into the NAND block with offset at g_main_bbt_addr.
753  * This assumes that the g_bbt has been built already.
754  *
755  * If g_main_bbt_addr is 0, search for a free block from the bottom 4 blocks (but make
756  * sure not re-using the mirror block). If g_mirror_bbt_page is 0, do the same thing.
757  * Otherwise, just use g_main_bbt_addr, g_mirror_bbt_page numbers to prgram the
758  * g_bbt into those two blocks.
759  * todo: need to do the version to see which one is newer.
760  *
761  * @return      0 if successful; -1 otherwise.
762  */
763 static int mxc_nfc_write_bbt_page(struct nand_bbt_descr *td)
764 {
765         int ret;
766         u32 block = td->pages / NF_PG_PER_BLK;
767         flash_addr_t addr = td->pages * NF_PG_SZ;
768
769         ret = nfc_erase_blk(addr);
770         if (ret != 0) {
771                 diag_printf("Failed to erase bbt block %u\n", block);
772                 return ret;
773         }
774         ret = nfc_write_page(td->pages, 0, 0);
775         if (ret != 0) {
776                 diag_printf("Failed to write bbt block %u\n", block);
777                 return ret;
778         }
779         mark_blk_bad(block, g_bbt, BLK_RESERVED);
780         return 0;
781 }
782
783 static inline void mxc_nfc_buf_clear(unsigned long buf, u8 pattern, int size)
784 {
785         int i;
786         u16 *p = (u16 *)buf;
787         u16 fill = pattern;
788
789         fill = (fill << 8) | pattern;
790         for (i = 0; i < size >> 1; i++) {
791                 p[i] = fill;
792         }
793 }
794
795 static int mxc_nfc_write_bbt(struct nand_bbt_descr *td, struct nand_bbt_descr *md)
796 {
797         int ret = -1;
798         int block;
799         int pg_offs = 0;
800         int page = 0;
801         u16 *buf = (u16 *)NAND_MAIN_BUF0;
802
803         for (block = NF_BLK_CNT - 1; block >= NF_BLK_CNT - td->maxblocks - 1; block--) {
804                 int pg = block * NF_PG_PER_BLK;
805
806                 if ((nfc_is_badblock(block, g_bbt) & 1) == 0) {
807                         if (md != NULL && md->pages == pg) {
808                                 continue;
809                         }
810                         td->pages = pg;
811                         break;
812                 }
813         }
814         if (td->pages < 0) {
815                 return -1;
816         }
817         mxc_nfc_buf_clear(NAND_SPAR_BUF0, 0xff, NF_SPARE_SZ);
818         mxc_nfc_buf_clear(NAND_MAIN_BUF0, 0xff, NF_PG_SZ);
819         diag_printf1("%s: Updating bbt %c%c%c%c version %d\n", __FUNCTION__,
820                                  td->pattern[0], td->pattern[1], td->pattern[2], td->pattern[3], td->version);
821         nfc_buf_write(NAND_SPAR_BUF0 + td->offs, td->pattern, td->len);
822         store_byte((u16 *)NAND_SPAR_BUF0, td->veroffs, td->version);
823
824         for (block = 0, pg_offs = 0; block < NF_BLK_CNT; pg_offs++) {
825                 u16 tmp = 0xffff;
826                 int i;
827
828                 if (pg_offs << 1 >= NF_PG_SZ) {
829                         ret = mxc_nfc_write_bbt_page(td);
830                         if (ret != 0) {
831                                 return ret;
832                         }
833                         page++;
834                         mxc_nfc_buf_clear(NAND_SPAR_BUF0, 0xff, NF_SPARE_SZ);
835                         mxc_nfc_buf_clear(NAND_MAIN_BUF0, 0xff, NF_PG_SZ);
836                         pg_offs = 0;
837                 }
838                 for (i = 0; i < 16 && block < NF_BLK_CNT; i += 2, block++) {
839                         u8 code = nfc_is_badblock(block, g_bbt);
840                         if ((code & 1) != 0) {
841                                 tmp &= ~(code << i);
842                                 diag_printf1("%s: bad block %u pattern[%p] 0x%04x mask 0x%04x\n", __FUNCTION__,
843                                                          block, &buf[pg_offs], tmp, 0x03 << i);
844                         }
845                 }
846                 buf[pg_offs] = tmp;
847         }
848         if (pg_offs > 0) {
849                 diag_printf1("%s: Writing final bbt block %d page %d\n", __FUNCTION__,
850                                          td->pages / NF_PG_PER_BLK, page);
851                 ret = mxc_nfc_write_bbt_page(td);
852         }
853         return ret;
854 }
855
856 static int mxc_nfc_update_bbt(struct nand_bbt_descr *td, struct nand_bbt_descr *md)
857 {
858         int ret;
859
860         if (td == NULL) {
861                 return -1;
862         }
863         if (td->pages < 0 && (md == NULL || md->pages == -1)) {
864                 td->version = 1;
865         } else {
866                 if (md != NULL && md->pages >= 0) {
867                         if (md->version >= td->version) {
868                                 td->version = ++md->version;
869                         } else {
870                                 md->version = ++td->version;
871                         }
872                 } else {
873                         td->version++;
874                 }
875         }
876         ret = mxc_nfc_write_bbt(td, md);
877         if (ret) {
878                 diag_printf("** Error: Failed to update main BBT\n");
879         }
880         if (md) {
881                 ret = mxc_nfc_write_bbt(md, td);
882                 if (ret) {
883                         diag_printf("** Error: Failed to update mirror BBT\n");
884                 }
885         }
886         return ret;
887 }
888
889 static int program_bbt_to_flash(void)
890 {
891         return mxc_nfc_update_bbt(g_mxc_nfc_bbt_main_descr, g_mxc_nfc_bbt_mirror_descr);
892 }
893
894 /*!
895  * Unconditionally erase a block without checking the BI field.
896  * Note that there is NO error checking for passed-in ra.
897  *
898  * @param ra            starting address in the raw address space (offset)
899  *                                      Must be block-aligned
900  * @return                      0 if successful; -1 otherwise
901  */
902 static int nfc_erase_blk(u32 ra)
903 {
904         u16 flash_status, i;
905         u32 pg_no, pg_off;
906
907         if (g_nfc_version == MXC_NFC_V3) {
908                 // combine the two commands for erase
909                 writel((FLASH_Start_Erase << 8) | FLASH_Block_Erase, NAND_CMD_REG);
910                 pg_no = ra / NF_PG_SZ;
911                 pg_off = ra % NF_PG_SZ;
912                 for (i = 0; i < num_of_nand_chips; i++) {
913                         start_nfc_addr_ops(FLASH_Block_Erase, pg_no, pg_off, 1, i, num_of_nand_chips);
914                         // start auto-erase
915                         writel(NAND_LAUNCH_AUTO_ERASE, NAND_LAUNCH_REG);
916                         wait_op_done();
917                         pg_off = 0;
918                 }
919                 flash_status = NFC_STATUS_READ();
920                 // check I/O bit 0 to see if it is 0 for success
921                 if ((flash_status & ((0x1 << num_of_nand_chips) - 1)) != 0) {
922                         return -1;
923                 }
924         } else {
925                 NFC_CMD_INPUT(FLASH_Block_Erase);
926                 start_nfc_addr_ops(FLASH_Block_Erase, ra / NF_PG_SZ, ra % NF_PG_SZ,
927                                                    1, 0, num_of_nand_chips);
928                 NFC_CMD_INPUT(FLASH_Start_Erase);
929
930                 flash_status = NFC_STATUS_READ();
931
932                 // check I/O bit 0 to see if it is 0 for success
933                 if ((flash_status & 0x1) != 0) {
934                         return -1;
935                 }
936         }
937         return 0;
938 }
939
940 /*!
941  * Program a block of data in the flash. This function doesn't do
942  * bad block checking. But if program fails, it return error.
943  * Note: If "len" is less than a block it will program up to a page's
944  *               boundary. If not within a page boundary, then it fills the
945  *               rest of the page with 0xFF.
946  *
947  * @param ra            destination raw flash address
948  * @param buf           source address in the RAM
949  * @param len           len to be programmed
950  *
951  * @return                      0 if successful; -1 otherwise
952  */
953 static int nfc_program_blk(u32 ra, u8 *buf, u32 len)
954 {
955         u32 temp = num_of_nand_chips;
956
957         /* Needed when romupdate is called */
958         if (ra == 0)
959                 num_of_nand_chips = 1;
960
961         for (; len >= NF_PG_SZ; len -= NF_PG_SZ) {
962                 if (nfc_write_pg_random(ra / NF_PG_SZ, ra % NF_PG_SZ, buf, 0) != 0) {
963                         return -1;
964                 }
965                 ra += NF_PG_SZ;
966                 buf += NF_PG_SZ;
967         }
968         if (len != 0) {
969                 memset(g_page_buf + len, 0xFF, NF_PG_SZ - len);
970                 memcpy(g_page_buf, buf, len);
971                 if (nfc_write_pg_random(ra / NF_PG_SZ, ra % NF_PG_SZ, g_page_buf, 0) != 0) {
972                         num_of_nand_chips = temp;
973                         return -1;
974                 }
975         }
976         num_of_nand_chips = temp;
977         return 0;
978 }
979
980 /*!
981  * Erase a range of NAND flash good blocks only.
982  * It skips bad blocks and update the BBT once it sees new bad block due to erase.
983  * @param addr                  raw NAND flash address. it has to be block size aligned
984  * @param len                   number of bytes
985  * @param skip_bad              if 1, don't erase bad block; otherwise, always erase
986  * @param verbose               use true to print more messages
987  *
988  * @return                              FLASH_ERR_OK (0) if successful; non-zero otherwise
989  */
990 int nfc_erase_region(flash_addr_t addr, u32 len, bool skip_bad, bool verbose)
991 {
992         u32 sz, blk, update = 0, skip = 0, j = 0;
993
994         nfc_printf(NFC_DEBUG_MED, "%s: addr=0x%08llx len=0x%08x\n",
995                            __FUNCTION__, (u64)addr, len);
996
997         if ((addr % NF_BLK_SZ) != 0) {
998                 diag_printf("Error: flash address 0x%08llx not block aligned\n", addr);
999                 return FLASH_ERR_INVALID;
1000         }
1001         if ((len % NF_BLK_SZ) != 0 || len == 0) {
1002                 diag_printf("Error: invalid length %u (must be > 0 and block aligned)\n", len);
1003                 return FLASH_ERR_INVALID;
1004         }
1005         addr &= MXC_NAND_ADDR_MASK;
1006         // now addr has to be block aligned
1007         for (sz = 0; sz < len; addr += NF_BLK_SZ, j++, sz += NF_BLK_SZ) {
1008                 blk = OFFSET_TO_BLOCK(addr);
1009                 if (skip_bad && nfc_is_badblock(blk, g_bbt)) {
1010                         if (skip++ >= flash_dev_info->max_bad_blk) {
1011                                 diag_printf("\nToo many bad blocks encountered\n");
1012                                 return FLASH_ERR_PROTOCOL;
1013                         }
1014                         diag_printf("\nSkipping bad block %u at addr 0x%08llx\n",
1015                                                 blk, (u64)addr);
1016                         continue;
1017                 }
1018                 if (nfc_erase_blk(addr) != 0) {
1019                         diag_printf("\nError: Failed to erase block %u at addr 0x%08llx\n",
1020                                             blk, (u64)addr);
1021                         mark_blk_bad(blk, g_bbt, BLK_BAD_RUNTIME);
1022                         // we don't need to update the table immediately here since even
1023                         // with power loss now, we should see the same erase error again.
1024                         update++;
1025                         continue;
1026                 }
1027                 if (verbose) {
1028                         if ((j % 0x20) == 0)
1029                                 diag_printf("\n%s 0x%08llx: ", skip_bad ? "Erase" : "FORCE erase", (u64)addr);
1030                         diag_printf(".");
1031                 }
1032         }
1033         if (update) {
1034                 if (program_bbt_to_flash() != 0) {
1035                         diag_printf("\nError: Failed to update bad block table\n");
1036                         return -1;
1037                 }
1038                 diag_printf("\nnew bad blocks=%d\n", update);
1039         }
1040         return FLASH_ERR_OK;
1041 }
1042
1043 /*!
1044  * Program a range of NAND flash in blocks only.
1045  * It skips bad blocks and update the BBT once it sees new bad block due to program.
1046  * @param addr                  raw NAND flash address. it has to be block size aligned
1047  * @param len                   number of bytes
1048  * @return                              FLASH_ERR_OK (0) if successful; non-zero otherwise
1049  */
1050 int nfc_program_region(flash_addr_t addr, u8 *buf, u32 len)
1051 {
1052         u32 sz, blk, update = 0, skip = 0, partial_block_size;
1053
1054         diag_printf1("%s: addr=0x%08llx, len=0x%08x\n", __FUNCTION__, (u64)addr, len);
1055
1056         if ((addr % (NF_PG_SZ / num_of_nand_chips)) != 0) {
1057                 diag_printf("Error: flash address 0x%08llx not page aligned\n", (u64)addr);
1058                 return FLASH_ERR_INVALID;
1059         }
1060         if (len == 0) {
1061                 diag_printf("Error: invalid length\n");
1062                 return FLASH_ERR_INVALID;
1063         }
1064
1065         partial_block_size = addr % NF_BLK_SZ;
1066
1067         addr &= MXC_NAND_ADDR_MASK;
1068         // now addr has to be block aligned
1069         while (1) {
1070                 blk = OFFSET_TO_BLOCK(addr);
1071                 if (nfc_is_badblock(blk, g_bbt)) {
1072                         if (skip++ >= flash_dev_info->max_bad_blk) {
1073                                 diag_printf("\nToo many bad blocks encountered\n");
1074                                 return FLASH_ERR_PROTOCOL;
1075                         }
1076                         diag_printf("\nSkipping bad block %u at addr 0x%08llx\n", blk, addr);
1077                         goto incr_address;
1078                 }
1079
1080                 sz = (len >= partial_block_size) ? partial_block_size : len;
1081
1082                 if (nfc_program_blk(addr, buf, sz) != 0) {
1083                         update++;
1084                         diag_printf("\nError: Failed to program flash block %u at addr 0x%08llx\n",
1085                                                 blk, (u64)addr);
1086                         mark_blk_bad(blk, g_bbt, BLK_BAD_RUNTIME);
1087                         if (skip + update > flash_dev_info->max_bad_blk) {
1088                                 diag_printf("\nToo many bad blocks encountered\n");
1089                                 return FLASH_ERR_PROTOCOL;
1090                         }
1091                         // we don't need to update the table immediately here since even
1092                         // with power loss now, we should see the same program error again.
1093                         goto incr_address;
1094                 }
1095                 diag_printf(".");
1096
1097                 len -= sz;
1098                 buf += sz;
1099                 if (len == 0)
1100                         break;
1101
1102 incr_address:
1103                 addr += partial_block_size;
1104                 partial_block_size = NF_BLK_SZ;
1105         }
1106         if (update) {
1107                 if (program_bbt_to_flash() != 0) {
1108                         diag_printf("\nError: Failed to update bad block table\n");
1109                         return -1;
1110                 }
1111                 diag_printf("\nnew bad blocks: %d\n", update);
1112         }
1113         if (skip)
1114                 diag_printf("\nbad blocks skipped: %d\n", skip);
1115
1116         return FLASH_ERR_OK;
1117 }
1118
1119 /*!
1120  * Read data from raw NAND flash address to memory. The MSB of the passed-
1121  * in flash address will be masked off inside the function.
1122  * It skips bad blocks and read good blocks of data for "len" bytes.
1123  *
1124  * @param addr                  NAND flash address. it has to be page aligned
1125  * @param buf                   memory buf where data will be copied to
1126  * @param len                   number of bytes
1127  * @return                              FLASH_ERR_OK (0) if successful; non-zero otherwise
1128  */
1129 int nfc_read_region(flash_addr_t addr, u8 *buf, u32 len)
1130 {
1131         u32 blk, bad = 0, start_point = 0, pg_no;
1132         unsigned long offset = addr % NF_PG_SZ;
1133
1134         diag_printf1("%s: addr=0x%08llx, buf=0x%p, len=0x%08x\n",
1135                                  __FUNCTION__, addr, buf, len);
1136
1137         if (addr < (u32)flash_info.start || (addr + len) > (u32)flash_info.end || len == 0) {
1138                 diag_printf("Error: flash address 0x%08llx..0x%08llx outside valid range %p..%p\n",
1139                                         (u64)addr, (u64)addr + len - 1, flash_info.start, flash_info.end);
1140                 return FLASH_ERR_INVALID;
1141         }
1142
1143         addr = (addr & MXC_NAND_ADDR_MASK) - offset;
1144         blk = OFFSET_TO_BLOCK(addr);
1145         while (len > 0) {
1146                 int i;
1147
1148                 if ((addr % NF_BLK_SZ) == 0) {
1149                         // only need to test block aligned page address
1150                         blk = OFFSET_TO_BLOCK(addr);
1151                         if (nfc_is_badblock(blk, g_bbt)) {
1152                                 if (bad++ >= flash_dev_info->max_bad_blk) {
1153                                         diag_printf("\nToo many bad blocks encountered\n");
1154                                         return FLASH_ERR_PROTOCOL;
1155                                 }
1156                                 diag_printf("\nSkipping bad block %u at addr 0x%08llx\n", blk, (u64)addr);
1157                                 addr += NF_BLK_SZ;
1158                                 continue;
1159                         }
1160                 }
1161
1162                 pg_no = addr / NF_PG_SZ;
1163                 if ((addr % NF_PG_SZ) != 0) {
1164                         /* Find which interleaved NAND device */
1165                         start_point = (addr - (pg_no * NF_PG_SZ)) / (NF_PG_SZ / num_of_nand_chips);
1166                 } else {
1167                         start_point = 0;
1168                 }
1169                 for (i = start_point; i < num_of_nand_chips; i++) {
1170                         int chunk_size = len > NF_PG_SZ / num_of_nand_chips ?
1171                                 NF_PG_SZ / num_of_nand_chips : len;
1172
1173                         if (nfc_read_page(i, pg_no, 0) != 0) {
1174                                 diag_printf("\nError: Failed to read flash block %u at addr 0x%08llx\n",
1175                                                         blk, (u64)addr);
1176                                 return FLASH_ERR_INVALID;
1177                         }
1178                         // now do the copying
1179                         nfc_buf_read(buf, NAND_MAIN_BUF0, chunk_size);
1180
1181                         buf += chunk_size;
1182                         len -= chunk_size;
1183                         addr += NF_PG_SZ / num_of_nand_chips - offset;
1184                         offset = 0;
1185                 }
1186         }
1187
1188         return FLASH_ERR_OK;
1189 }
1190
1191 /*
1192  * Support only either program for main area only. Or spare-area only for 512B.
1193  * If one wants to write to the spare-area, then before calling this function,
1194  * the spare area NFC RAM buffer has to be setup already. This function doesn't touch
1195  * the spare area NFC RAM buffer.
1196  *
1197  * @param pg_no                 page number offset from 0
1198  * @param pg_off                byte offset within the page
1199  * @param buf                   data buffer in the RAM to be written to NAND flash
1200  * @param ecc_force             can force ecc to be off. Otherwise, by default it is on
1201  *                                              unless the page offset is non-zero
1202  *
1203  * @return      0 if successful; non-zero otherwise
1204  */
1205 // SP-only opearation is not supported anymore !!!
1206 static int nfc_write_pg_random(u32 pg_no, u32 pg_off, u8 *buf, u32 ecc_force)
1207 {
1208         u16 flash_status;
1209         u32 ecc = NFC_FLASH_CONFIG2_ECC_EN, v, i;
1210         u32 write_count = NF_PG_SZ, start_point = 0, rba, rba_count = 0;
1211
1212         // the 2nd condition is to test for unaligned page address -- ecc has to be off.
1213         if (ecc_force == ECC_FORCE_OFF || pg_off != 0) {
1214                 ecc = 0;
1215         }
1216
1217         diag_printf1("%s(0x%x, 0x%x, %d)\n", __FUNCTION__, pg_no, pg_off, ecc_force);
1218
1219         switch (g_nfc_version & 0xf0) {
1220         case MXC_NFC_V3:
1221                 /* Check if Page size is greater than NFC buffer */
1222                 do {
1223                         if (write_count <= NFC_BUFSIZE) {
1224                                 // No need to worry about the spare area
1225                                 nfc_buf_write(NAND_MAIN_BUF0, buf, write_count);
1226                                 write_count = 0;
1227                         } else {
1228                                 // No need to worry about the spare area
1229                                 nfc_buf_write(NAND_MAIN_BUF0, buf, NFC_BUFSIZE);
1230                                 write_count -= NFC_BUFSIZE;
1231                                 buf += NFC_BUFSIZE;
1232                         }
1233                         // combine the two commands for program
1234                         writel((FLASH_Program << 8) | FLASH_Send_Data, NAND_CMD_REG);
1235
1236                         for (i = start_point; i < num_of_nand_chips; i++) {
1237                                 rba = rba_count * ((NF_PG_SZ / num_of_nand_chips) / 512);
1238                                 /* Completely wrote out the NFC buffer, break and copy more to the NFC buffer */
1239                                 if (rba > 7) {
1240                                         rba_count = 0;
1241                                         break;
1242                                 }
1243
1244                                 // For ECC
1245                                 v = readl(NFC_FLASH_CONFIG2_REG) & ~NFC_FLASH_CONFIG2_ECC_EN;
1246                                 // setup config2 register for ECC enable or not
1247                                 write_nfc_ip_reg(v | ecc, NFC_FLASH_CONFIG2_REG);
1248
1249                                 start_nfc_addr_ops(FLASH_Program, pg_no, pg_off, 0, i, num_of_nand_chips);
1250
1251                                 // start auto-program
1252                                 writel(NAND_LAUNCH_AUTO_PROG, NAND_LAUNCH_REG);
1253                                 if (i < (num_of_nand_chips - i))
1254                                         wait_for_auto_prog_done();
1255                                 else
1256                                         wait_op_done();
1257                                 pg_off = 0;
1258                                 rba_count++;
1259                         }
1260                         start_point = i;
1261                 } while (write_count > 0);
1262                 flash_status = NFC_STATUS_READ();
1263                 // check I/O bit 0 to see if it is 0 for success
1264                 if ((flash_status & ((0x1 << num_of_nand_chips) - 1)) != 0) {
1265                         return -1;
1266                 }
1267                 break;
1268         default:
1269                 if (g_nfc_version != MXC_NFC_V1) {
1270                         int i;
1271
1272                         for (i = 1; i < NFC_SPARE_BUF_SZ / 16; i++) {
1273                                 memcpy((void *)(NAND_SPAR_BUF0 + i * NFC_SPARE_BUF_SZ),
1274                                            (void *)(NAND_SPAR_BUF0 + i * 16), 16);
1275                         }
1276                 }
1277                 nfc_buf_write(NAND_MAIN_BUF0, buf, NF_PG_SZ);
1278 #ifdef BARKER_CODE_SWAP_LOC
1279                 // To replace the data at offset MXC_NAND_BOOT_LOAD_BARKER with
1280                 // the address of the NFC base. This is needed for certain platforms.
1281                 if (pg_no == 0) {
1282                         diag_printf("\n[INFO]: copy data at 0x%x to spare area and set it to 0x%x\n",
1283                                                 BARKER_CODE_SWAP_LOC, BARKER_CODE_VAL);
1284                         writel(readl(NFC_BASE + BARKER_CODE_SWAP_LOC), NAND_SPAR_BUF0);
1285                         // todo: set BARKER_CODE_VAL and BARKER_CODE_SWAP_LOC for skye, etc.
1286                         writel(BARKER_CODE_VAL, NFC_BASE + BARKER_CODE_SWAP_LOC);
1287                 }
1288 #endif
1289                 NFC_CMD_INPUT(FLASH_Send_Data);
1290                 start_nfc_addr_ops(FLASH_Program, pg_no, pg_off, 0, 0, num_of_nand_chips);
1291
1292                 NFC_DATA_INPUT(RAM_BUF_0, NFC_MAIN_ONLY, ecc);
1293                 if (g_is_4k_page && PG_2K_DATA_OP_MULTI_CYCLES()) {
1294                         diag_printf("4K page with multi cycle write is not supported\n");
1295                         return -1;
1296                 }
1297                 if (g_is_2k_page && PG_2K_DATA_OP_MULTI_CYCLES()) {
1298                         NFC_DATA_INPUT_2k(RAM_BUF_1);
1299                         NFC_DATA_INPUT_2k(RAM_BUF_2);
1300                         NFC_DATA_INPUT_2k(RAM_BUF_3);
1301                 }
1302                 NFC_CMD_INPUT(FLASH_Program);
1303
1304                 flash_status = NFC_STATUS_READ();
1305                 // check I/O bit 0 to see if it is 0 for success
1306                 if ((flash_status & 0x1) != 0) {
1307                         diag_printf("** Error: failed to program page %u at 0x%08x status=0x%02x\n",
1308                                                 pg_no, pg_no * NF_PG_SZ + pg_off, flash_status);
1309                         return -1;
1310                 }
1311         }
1312         return 0;
1313 }
1314
1315 #ifndef NFC_V3_0
1316 // for version V1 and V2 of NFC
1317 static int nfc_read_pg_random(u32 pg_no, u32 pg_off, u32 ecc_force, u32 cs_line,
1318                                                           u32 num_of_nand_chips)
1319 {
1320         u32 t1, ecc = 1;
1321         u8 t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, t8 = 0;
1322         int res = 0;
1323
1324         if (ecc_force == ECC_FORCE_OFF || pg_off != 0 )
1325                 ecc = 0;
1326
1327         NFC_CMD_INPUT(FLASH_Read_Mode1);
1328         start_nfc_addr_ops(FLASH_Read_Mode1, pg_no, pg_off, 0, 0, num_of_nand_chips);
1329
1330         if (g_is_2k_page || g_is_4k_page) {
1331                 NFC_CMD_INPUT(FLASH_Read_Mode1_LG);
1332         }
1333
1334         NFC_DATA_OUTPUT(RAM_BUF_0, FDO_PAGE_SPARE, ecc);
1335         switch (g_nfc_version & 0xf0) {
1336         case MXC_NFC_V1:
1337                 t1 = readw(ECC_STATUS_RESULT_REG);
1338                 if (g_is_2k_page && PG_2K_DATA_OP_MULTI_CYCLES()) {
1339                         NFC_DATA_OUTPUT(RAM_BUF_1, FDO_PAGE_SPARE, ecc);
1340                         t2 = readw(ECC_STATUS_RESULT_REG);
1341                         NFC_DATA_OUTPUT(RAM_BUF_2, FDO_PAGE_SPARE, ecc);
1342                         t3 = readw(ECC_STATUS_RESULT_REG);
1343                         NFC_DATA_OUTPUT(RAM_BUF_3, FDO_PAGE_SPARE, ecc);
1344                         t4 = readw(ECC_STATUS_RESULT_REG);
1345                 }
1346
1347                 if (ecc && ((t1 & 0xA) != 0x0 || (t2 & 0xA) != 0x0 ||
1348                                         (t3 & 0xA) != 0x0 || (t4 & 0xA) != 0x0)) {
1349                         diag_printf("\n** Error: %s(page=%d, col=%d): ECC status=0x%x:0x%x:0x%x:0x%x\n",
1350                                                 __FUNCTION__, pg_no, pg_off, t1, t2, t3, t4);
1351                         res = -1;
1352                         goto out;
1353                 }
1354                 break;
1355         case MXC_NFC_V2:
1356                 if (g_is_2k_page && PG_2K_DATA_OP_MULTI_CYCLES()) {
1357                         NFC_DATA_OUTPUT(RAM_BUF_1, FDO_PAGE_SPARE, ecc);
1358                         NFC_DATA_OUTPUT(RAM_BUF_2, FDO_PAGE_SPARE, ecc);
1359                         NFC_DATA_OUTPUT(RAM_BUF_3, FDO_PAGE_SPARE, ecc);
1360                 }
1361                 if (ecc) {
1362                         t1 = readl(ECC_STATUS_RESULT_REG);
1363                         if (g_is_2k_page || g_is_4k_page) {
1364                                 t2 = (t1 >> 4) & 0xF;
1365                                 t3 = (t1 >> 8) & 0xF;
1366                                 t4 = (t1 >> 12) & 0xF;
1367                                 if (g_is_4k_page) {
1368                                         t5 = (t1 >> 16) & 0xF;
1369                                         t6 = (t1 >> 20) & 0xF;
1370                                         t7 = (t1 >> 24) & 0xF;
1371                                         t8 = (t1 >> 28) & 0xF;
1372                                 }
1373                         }
1374                         if ((t1 = (t1 & 0xF)) > 4 || t2 > 4 || t3 > 4 || t4 > 4 ||
1375                                 t5 > 4 || t6 > 4 || t7 > 4 || t8 > 4) {
1376                                 diag_printf("\n** Error: ECC error reading block %u page %u\n",
1377                                                         pg_no / NF_PG_PER_BLK, pg_no % NF_PG_PER_BLK);
1378                                 diag_printf("   ECC status=%x:%x:%x:%x:%x:%x:%x:%x\n",
1379                                                         t1, t2, t3, t4, t5, t6, t7, t8);
1380                                 res = -1;
1381                                 goto out;
1382                         }
1383                 }
1384                 break;
1385         default:
1386                 diag_printf("Unknown NFC version: %d\n", g_nfc_version);
1387                 return -1;
1388         }
1389         if (g_nfc_version != MXC_NFC_V1) {
1390                 int i;
1391
1392                 for (i = 1; i < NFC_SPARE_BUF_SZ / 16; i++) {
1393                         memcpy((void *)(NAND_SPAR_BUF0 + i * 16),
1394                                    (void *)(NAND_SPAR_BUF0 + i * NFC_SPARE_BUF_SZ), 16);
1395                 }
1396         }
1397 #ifdef BARKER_CODE_SWAP_LOC
1398         // To replace the data at offset BARKER_CODE_SWAP_LOC with the address of the NFC base
1399         // This is needed for certain platforms
1400         if (pg_no == 0) {
1401                 diag_printf("\n[INFO]: copy back data from spare to 0x%x\n", BARKER_CODE_SWAP_LOC);
1402                 writel(readl(NAND_SPAR_BUF0), NFC_BASE + BARKER_CODE_SWAP_LOC);
1403         }
1404 #endif
1405
1406 out:
1407         return res;
1408 }
1409 #endif                  // ifndef NFC_V3_0
1410
1411 /*!
1412  * Read a page's both main and spare area from NAND flash to the internal RAM buffer.
1413  * It always reads data to the internal buffer 0.
1414  *
1415  * @param cs_line       which NAND device is used
1416  * @param pg_no    page number of the device
1417  * @param pg_off        offset within a page
1418  *
1419  * @return                              0 if no error or 1-bit error; -1 otherwise
1420  */
1421 static int nfc_read_page(u32 cs_line, u32 pg_no, u32 pg_off)
1422 {
1423         return nfc_read_pg_random(pg_no, pg_off, ECC_FORCE_ON, cs_line, num_of_nand_chips);
1424 }
1425
1426 static int nfc_write_page(u32 pg_no, u32 pg_off, u32 ecc_force)
1427 {
1428         u16 flash_status;
1429         u32 ecc = NFC_FLASH_CONFIG2_ECC_EN;
1430
1431         diag_printf1("Writing page %u addr 0x%08llx\n",
1432                                  pg_no, (u64)pg_no * NF_PG_SZ + pg_off);
1433         if (ecc_force == ECC_FORCE_OFF || pg_off != 0) {
1434                 ecc = 0;
1435         }
1436
1437         if (g_nfc_version == MXC_NFC_V3) {
1438                 int i;
1439                 u32 v;
1440                 u32 start_point = 0, rba, rba_count = 0;
1441
1442                 // combine the two commands for program
1443                 writel((FLASH_Program << 8) | FLASH_Send_Data, NAND_CMD_REG);
1444
1445                 for (i = start_point; i < num_of_nand_chips; i++) {
1446                         rba = rba_count * ((NF_PG_SZ / num_of_nand_chips) / 512);
1447                         /* Completely wrote out the NFC buffer, break and copy more to the NFC buffer */
1448                         if (rba > 7) {
1449                                 rba_count = 0;
1450                                 break;
1451                         }
1452
1453                         // For ECC
1454                         v = readl(NFC_FLASH_CONFIG2_REG) & ~NFC_FLASH_CONFIG2_ECC_EN;
1455                         // setup config2 register for ECC enable or not
1456                         write_nfc_ip_reg(v | ecc, NFC_FLASH_CONFIG2_REG);
1457
1458                         start_nfc_addr_ops(FLASH_Program, pg_no, pg_off, 0, i, num_of_nand_chips);
1459
1460                         // start auto-program
1461                         writel(NAND_LAUNCH_AUTO_PROG, NAND_LAUNCH_REG);
1462                         if (i < (num_of_nand_chips - i))
1463                                 wait_for_auto_prog_done();
1464                         else
1465                                 wait_op_done();
1466                         pg_off = 0;
1467                         rba_count++;
1468                 }
1469                 start_point = i;
1470                 flash_status = NFC_STATUS_READ();
1471         } else {
1472                 if (g_nfc_version != MXC_NFC_V1) {
1473                         int i;
1474
1475                         for (i = NFC_SPARE_BUF_SZ / 16 - 1; i >= 0; i--) {
1476                                 memcpy((void *)(NAND_SPAR_BUF0 + i * NFC_SPARE_BUF_SZ),
1477                                            (void *)(NAND_SPAR_BUF0 + i * 16), 16);
1478                         }
1479                 }
1480                 NFC_CMD_INPUT(FLASH_Send_Data);
1481                 start_nfc_addr_ops(FLASH_Program, pg_no, pg_off, 0, 0, num_of_nand_chips);
1482
1483                 NFC_DATA_INPUT(RAM_BUF_0, NFC_MAIN_ONLY, ecc);
1484                 if (g_is_4k_page && PG_2K_DATA_OP_MULTI_CYCLES()) {
1485                         diag_printf("4K page with multi cycle write is not supported\n");
1486                         return -1;
1487                 }
1488                 if (g_is_2k_page && PG_2K_DATA_OP_MULTI_CYCLES()) {
1489                         NFC_DATA_INPUT_2k(RAM_BUF_1);
1490                         NFC_DATA_INPUT_2k(RAM_BUF_2);
1491                         NFC_DATA_INPUT_2k(RAM_BUF_3);
1492                 }
1493                 NFC_CMD_INPUT(FLASH_Program);
1494
1495                 flash_status = NFC_STATUS_READ();
1496         }
1497         if ((flash_status & 0x1) != 0) {
1498                 diag_printf("** Error: failed to program page %u at addr 0x%08llx\n",
1499                                         pg_no, (u64)pg_no * NF_PG_SZ + pg_off);
1500                 return -1;
1501         }
1502         return 0;
1503 }
1504
1505 // Read data into buffer
1506 #ifndef MXCFLASH_SELECT_MULTI
1507 int flash_read_buf(void *addr, void *data, int len)
1508 #else
1509 int nandflash_read_buf(void *addr, void *data, int len)
1510 #endif
1511 {
1512         flash_addr_t flash_addr = (unsigned long)addr;
1513         return nfc_read_region(flash_addr, data, len);
1514 }
1515
1516 void mxc_nfc_print_info(void)
1517 {
1518         diag_printf("[0x%08x bytes]: %u blocks of %u pages of %u bytes each.\n",
1519                                 NF_DEV_SZ, NF_BLK_CNT,
1520                                 NF_PG_PER_BLK, NF_PG_SZ);
1521 }
1522
1523 static inline void mxc_clr_block_offset(void *start, void *end)
1524 {
1525         nfc_printf(NFC_DEBUG_MIN, "Clearing block offset %lu for %p..%p\n",
1526                            g_block_offset, start, end);
1527         g_block_offset = 0;
1528 }
1529
1530 static void *flash_region_start;
1531 static void *flash_region_end;
1532 static int flash_enable;
1533
1534 void mxc_flash_enable(void *start, void *end)
1535 {
1536         if (flash_enable++ == 0) {
1537                 flash_region_start = start;
1538                 flash_region_end = end;
1539                 mxc_clr_block_offset(start, end);
1540         } else {
1541                 if (start < flash_region_start || end > flash_region_end) {
1542                         diag_printf("** WARNING: Enable %p..%p outside enabled flash region %p..%p\n",
1543                                                 start, end, flash_region_start, flash_region_end);
1544                 }
1545         }
1546 }
1547
1548 void mxc_flash_disable(void *start, void *end)
1549 {
1550         if (flash_enable) {
1551                 if (--flash_enable == 0) {
1552                         if (start != flash_region_start || end != flash_region_end) {
1553                                 diag_printf("** Error: Disable %p..%p not equal to enabled flash region %p..%p\n",
1554                                                         start, end, flash_region_start, flash_region_end);
1555                         }
1556                 }
1557         } else {
1558                 diag_printf("** Error: unbalanced call to flash_disable()\n");
1559         }
1560 }
1561
1562 static int mxc_nfc_isbad_bbt(u16 *bbt, int block)
1563 {
1564         cyg_uint8 res;
1565
1566         block <<= 1;
1567         res = (get_byte(bbt, block >> 3) >> (block & 0x06)) & 0x03;
1568         res ^= 0x03;
1569         return res;
1570 }
1571
1572 static int mxc_nfc_search_bbt(struct nand_bbt_descr *td)
1573 {
1574         int i;
1575
1576         td->pages = -1;
1577         for (i = 0; i < NF_BBT_MAX_NR; i++) {
1578                 u32 blk = NF_BLK_CNT - i - 1;
1579                 flash_addr_t addr = blk * NF_BLK_SZ;
1580
1581                 if (nfc_read_pg_random(addr / NF_PG_SZ, addr % NF_PG_SZ,
1582                                                            ECC_FORCE_ON, 0, num_of_nand_chips) != 0) {
1583                         diag_printf("Failed to read bbt page %u at 0x%08llx\n",
1584                                                 (u32)(addr / NF_PG_SZ), addr);
1585                         continue;
1586                 }
1587                 if (check_short_pattern((void *)NAND_SPAR_BUF0, td) == 0) {
1588                         diag_printf1("found BBT at block %u addr %08llx\n", blk, (u64)addr);
1589                         td->pages = blk * NF_PG_PER_BLK;
1590                         td->version = get_byte((void *)NAND_SPAR_BUF0, td->veroffs);
1591                         mark_blk_bad(blk, g_bbt, BLK_RESERVED);
1592                         diag_printf1("Found version %d BBT at block %d (0x%08llx)\n",
1593                                                  td->version, td->pages / NF_PG_PER_BLK,
1594                                                  (u64)td->pages * NF_PG_SZ);
1595                         return 0;
1596                 }
1597         }
1598         return 1;
1599 }
1600
1601 /*
1602  * Look for the BBT depending on the passed-in lowlevel value.
1603  * @param       lowlevel        If true, then it does a low level scan based on factory
1604  *                                              marked BI(block info) field with ECC off to decide if a
1605  *                                              block is bad.
1606  *                                              If false, then it checks to see if an existing BBT in the
1607  *                                              flash or not. If not, then it returns -1. If yes, it will
1608  *                                              prints out the number of bad blocks.
1609  *
1610  * @return      number of bad blocks for the whole nand flash
1611  *
1612  * Note: For a brand new flash, this function has to be called with
1613  *               lowlevel=true.
1614  *
1615  *
1616  */
1617 static int mxc_nfc_scan(bool lowlevel)
1618 {
1619         u32 bad = 0, i;
1620         u32 count1 = 0, count2 = 0;
1621         u8 *buf = NULL;
1622         struct nand_bbt_descr *td = g_mxc_nfc_bbt_main_descr;
1623         struct nand_bbt_descr *md = g_mxc_nfc_bbt_mirror_descr;
1624
1625         nfc_printf(NFC_DEBUG_MAX, "%s()\n", __FUNCTION__);
1626         mxc_nfc_scan_done = 0;
1627
1628         if (g_nfc_debug_measure) {
1629                 count1 = hal_timer_count();
1630         }
1631         // read out the last 4 blocks for marker
1632         // need to keep where is the td and md block number
1633         if (!lowlevel) {
1634                 struct nand_bbt_descr *bd;
1635
1636                 diag_printf1("Searching for BBT in the flash ...\n");
1637                 if (mxc_nfc_search_bbt(td) != 0) {
1638                         diag_printf("No main BBT found in flash\n");
1639                 }
1640                 if (md && mxc_nfc_search_bbt(md) != 0) {
1641                         diag_printf("No mirror BBT found in flash\n");
1642                 }
1643                 if (td->pages == -1 && (!md || md->pages == -1)) {
1644                         diag_printf("No BBT found. Need to do \"nand scan\" first\n");
1645                         return -1;
1646                 }
1647                 if (td->pages >= 0 && (md == NULL || md->version <= td->version)) {
1648                         bd = td;
1649                         nfc_printf(NFC_DEBUG_MIN, "Using normal bbt at page %d\n", bd->pages);
1650                 } else if (md != NULL && md->pages >= 0) {
1651                         bd = md;
1652                         nfc_printf(NFC_DEBUG_MIN, "Using mirror bbt at page %d\n", bd->pages);
1653                 } else {
1654                         diag_printf("** Error: Failed to read bbt from flash\n");
1655                         return -1;
1656                 }
1657                 nfc_read_page(0, bd->pages, 0);
1658                 for (i = 0; i < NF_BLK_CNT; i++) {
1659                         int res = mxc_nfc_isbad_bbt((u16 *)NAND_MAIN_BUF0, i);
1660                         if (res) {
1661                                 // construct the bad block table
1662                                 mark_blk_bad(i, g_bbt, res);
1663                                 bad++;
1664                         }
1665                 }
1666                 buf = g_bbt;
1667         } else {
1668                 diag_printf("Doing low level scan to construct BBT\n");
1669                 for (i = 0; i < NF_BLK_CNT; i++) {
1670                         int res = nfc_is_badblock(i, buf);
1671                         if (res) {
1672                                 // construct the bad block table
1673                                 if (!buf)
1674                                         mark_blk_bad(i, g_bbt, res);
1675                                 bad++;
1676                         }
1677                 }
1678         }
1679         diag_printf1("Total bad blocks: %d\n", bad);
1680         if (g_nfc_debug_measure) {
1681                 count2 = hal_timer_count();
1682                 diag_printf("counter1=0x%x, counter2=0x%x, diff=0x%x (%u usec)\n",
1683                                         count1, count2, count2 - count1,
1684                                         (count2 - count1) * 1000000 / 32768);
1685         }
1686         mxc_nfc_scan_done = 1;
1687         return bad;
1688 }
1689
1690 ////////////////////////// "nand" commands support /////////////////////////
1691 // Image management functions
1692 local_cmd_entry("info",
1693                                 "Show nand flash info (number of good/bad blocks)",
1694                                 "",
1695                                 nand_info,
1696                                 NAND_cmds
1697                    );
1698
1699 local_cmd_entry("show",
1700                                 "Show a page main/spare areas or spare area only (-s)",
1701                                 "-f <raw page address> [-s]",
1702                                 nand_show,
1703                                 NAND_cmds
1704                    );
1705
1706 local_cmd_entry("read",
1707                                 "Read data from nand flash into RAM",
1708                                 "-f <raw addr> -b <mem_load_addr> -l <byte len> [-c <col>]\n"
1709                                 "      Note -c is only for 2K-page for value <0, 2048+64-1>",
1710                                 nand_read,
1711                                 NAND_cmds
1712                    );
1713
1714 local_cmd_entry("write",
1715                                 "Write data from RAM into nand flash",
1716                                 "-f <raw address> -b <memory_address> -l <image_length> [-c <col_addr>]",
1717                                 nand_write,
1718                                 NAND_cmds
1719                    );
1720
1721 local_cmd_entry("erase",
1722                                 "Erase nand flash contents",
1723                                 "-f <raw address> -l <length> [-o]\n"
1724                                 "             -o: force erase (even for bad blocks)",
1725                                 nand_erase,
1726                                 NAND_cmds
1727                    );
1728
1729 local_cmd_entry("scan",
1730                                 "Scan bad blocks and may also save bad block table into the NAND flash.",
1731                                 "[-o] [-r]\n"
1732                                 "No argument: save existing bad block table (BBT)\n"
1733                                 "            -r: re-scan with ECC off and save BBT -- for brand NEW flash\n"
1734                                 "            -o: force erase all, reconstruct BBT (no ECC) and save BBT -- for development.",
1735                                 nand_scan,
1736                                 NAND_cmds
1737                    );
1738
1739 local_cmd_entry("debug",
1740                                 "Various NAND debug features ",
1741                                 "<0> no debug messages <default>\n"
1742                                 "             <1> min debug messages\n"
1743                                 "             <2> med debug messages\n"
1744                                 "             <3> max debug messages\n"
1745                                 "             <4> enable(default)/disable h/w ECC for both r/w\n"
1746                                 "             <5> disable(default)/enalbe spare-only read\n"
1747                                 "             <9> enable/disable measurement\n"
1748                                 "             no parameter - display current debug setup",
1749                                 nand_debug_fun,
1750                                 NAND_cmds
1751                                 );
1752
1753 local_cmd_entry("bad",
1754                                 "Mark bad block in BBT",
1755                                 "[-f <raw address>] [-b <block number>] [-c]\n"
1756                                 "           -c: clear bad block mark\n"
1757                                 "           -f and -b are mutually exclusive",
1758                                 nand_bad,
1759                                 NAND_cmds
1760                                 );
1761
1762 // Define table boundaries
1763 CYG_HAL_TABLE_BEGIN( __NAND_cmds_TAB__, NAND_cmds);
1764 CYG_HAL_TABLE_END( __NAND_cmds_TAB_END__, NAND_cmds);
1765
1766 extern struct cmd __NAND_cmds_TAB__[], __NAND_cmds_TAB_END__;
1767
1768 // CLI function
1769 static cmd_fun do_nand_cmds;
1770 RedBoot_nested_cmd("nand",
1771                    "Utility function to NAND flash using raw address",
1772                    "{cmds}",
1773                    do_nand_cmds,
1774                    __NAND_cmds_TAB__, &__NAND_cmds_TAB_END__
1775                   );
1776
1777 static void nand_usage(char *why)
1778 {
1779         diag_printf("*** invalid 'nand' command: %s\n", why);
1780         cmd_usage(__NAND_cmds_TAB__, &__NAND_cmds_TAB_END__, "nand ");
1781 }
1782
1783 static u32 curr_addr;
1784 static void nand_show(int argc, char *argv[])
1785 {
1786         u32 ra;
1787         bool flash_addr_set = false;
1788         bool spar_only = false;
1789         struct option_info opts[2];
1790
1791         init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
1792                           &ra, &flash_addr_set, "NAND FLASH memory byte address");
1793         init_opts(&opts[1], 's', false, OPTION_ARG_TYPE_FLG,
1794                           &spar_only, NULL, "Spare only");
1795
1796         if (!scan_opts(argc, argv, 2, opts, 2, 0, 0, 0)) {
1797                 return;
1798         }
1799         if (!flash_addr_set) {
1800                 ra = curr_addr;
1801                 curr_addr += NF_PG_SZ;
1802         } else {
1803                 curr_addr = ra;
1804         }
1805
1806         if (ra % NF_PG_SZ) {
1807                 diag_printf("** Error: flash address must be page aligned\n");
1808                 return;
1809         }
1810
1811         ra &= MXC_NAND_ADDR_MASK;
1812         if (nfc_is_badblock(OFFSET_TO_BLOCK(ra), g_bbt)) {
1813                 diag_printf("This is a bad block\n");
1814         }
1815
1816         print_page(ra, spar_only);
1817 }
1818
1819 /*!
1820  * For low level nand read command. It doesn't check for bad block or not
1821  */
1822 static void nand_read(int argc, char *argv[])
1823 {
1824         int len;
1825         u32 mem_addr, ra, col, i, pg_no, pg_off;
1826         bool mem_addr_set = false;
1827         bool flash_addr_set = false;
1828         bool length_set = false;
1829         bool col_set = false;
1830         struct option_info opts[4];
1831         int j = 0;
1832         bool ecc_status = g_ecc_enable;
1833
1834         init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
1835                           &mem_addr, &mem_addr_set, "memory base address");
1836         init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM,
1837                           &ra, &flash_addr_set, "FLASH memory base address");
1838         init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
1839                           &len, &length_set, "image length [in FLASH]");
1840         init_opts(&opts[3], 'c', true, OPTION_ARG_TYPE_NUM,
1841                           &col, &col_set, "column addr");
1842
1843         if (!scan_opts(argc, argv, 2, opts, 4, 0, 0, 0)) {
1844                 nand_usage("invalid arguments");
1845                 return;
1846         }
1847
1848         if (ra % NF_PG_SZ) {
1849                 diag_printf("** Error: flash address must be page aligned\n");
1850                 return;
1851         }
1852
1853         if (!mem_addr_set || !flash_addr_set || !length_set) {
1854                 nand_usage("** Error: required parameter missing");
1855                 return;
1856         }
1857         if ((mem_addr < (CYG_ADDRESS)ram_start) ||
1858                 ((mem_addr+len) >= (CYG_ADDRESS)ram_end)) {
1859                 diag_printf("** WARNING: RAM address: 0x%08x may be invalid\n", mem_addr);
1860                 diag_printf("   valid range is 0x%p-0x%p\n", ram_start, ram_end);
1861         }
1862
1863         if (col_set) {
1864                 diag_printf("Random read at page %u, column 0x%04x\n",
1865                                         ra / NF_PG_SZ, col);
1866
1867                 if (g_is_2k_page || g_is_4k_page) {
1868                         g_ecc_enable = false;
1869                 }
1870                 nfc_read_pg_random(ra / NF_PG_SZ, col, ECC_FORCE_OFF, 0, num_of_nand_chips);
1871                 if (g_is_2k_page || g_is_4k_page) {
1872                         g_ecc_enable = ecc_status;
1873                 }
1874                 nfc_buf_read((void *)mem_addr, NAND_MAIN_BUF0, NF_PG_SZ);
1875                 return;
1876         }
1877
1878         // ensure integer multiple of page size
1879         len = (len + NF_PG_SZ - 1) & ~(NF_PG_SZ - 1);
1880         ra &= MXC_NAND_ADDR_MASK;
1881         do {
1882                 if (OFFSET_TO_BLOCK(ra) > (NF_BLK_CNT - 1)) {
1883                         diag_printf("\n** Error: flash address: 0x%08x out of range\n", ra);
1884                         return;
1885                 }
1886                 pg_no = ra / NF_PG_SZ;
1887                 pg_off = ra % NF_PG_SZ;
1888                 for (i = 0; i < num_of_nand_chips; i++) {
1889                         if (nfc_read_page(i, pg_no, pg_off) != 0) {
1890                                 diag_printf("\n** Error: uncorrectable ECC at addr 0x%08x\n", ra);
1891                                 diag_printf("use 'nand bad -b %u' to mark this block in BBT\n",
1892                                                         pg_no / NF_PG_PER_BLK);
1893                         }
1894                         if ((j++ % 0x20) == 0)
1895                                 diag_printf("\n%s 0x%08x: ", __FUNCTION__, ra);
1896                         diag_printf(".");
1897
1898                         nfc_buf_read((void *)mem_addr, NAND_MAIN_BUF0, NF_PG_SZ / num_of_nand_chips);
1899
1900                         ra += NF_PG_SZ / num_of_nand_chips;
1901                         mem_addr += NF_PG_SZ / num_of_nand_chips;
1902                         len -= NF_PG_SZ / num_of_nand_chips;
1903                         pg_off = 0;
1904                 }
1905         } while (len > 0);
1906         diag_printf("\n");
1907 }
1908
1909 static void nand_write(int argc, char *argv[])
1910 {
1911         int len, len_st, j = 0;
1912         u32 mem_addr, mem_addr_st, ra, col;
1913         bool mem_addr_set = false;
1914         bool flash_addr_set = false;
1915         bool length_set = false;
1916         bool col_set = false;
1917         struct option_info opts[4];
1918         bool ecc_status = g_ecc_enable;
1919         int skip = 0;
1920
1921         init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
1922                           &mem_addr, &mem_addr_set, "memory base address");
1923         init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM,
1924                           &ra, &flash_addr_set, "FLASH memory base address");
1925         init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
1926                           &len, &length_set, "image length [in FLASH]");
1927         init_opts(&opts[3], 'c', true, OPTION_ARG_TYPE_NUM,
1928                           &col, &col_set, "column addr");
1929         if (!scan_opts(argc, argv, 2, opts, 4, 0, 0, 0)) {
1930                 nand_usage("invalid arguments");
1931                 return;
1932         }
1933
1934         if (!mem_addr_set || !flash_addr_set || !length_set) {
1935                 nand_usage("required parameter missing");
1936                 return;
1937         }
1938
1939         if ((mem_addr < (CYG_ADDRESS)ram_start) ||
1940                 ((mem_addr+len) >= (CYG_ADDRESS)ram_end)) {
1941                 diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr);
1942                 diag_printf("   valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
1943         }
1944
1945         if (col_set) {
1946                 diag_printf("Random write at page %u, column %u\n", ra / NF_PG_SZ, col);
1947
1948                 if (g_is_2k_page || g_is_4k_page) {
1949                         g_ecc_enable = false;
1950                 }
1951                 nfc_write_pg_random(ra / NF_PG_SZ, col, (u8 *)mem_addr, 0);
1952                 if (g_is_2k_page || g_is_4k_page) {
1953                         g_ecc_enable = ecc_status;
1954                 }
1955                 return;
1956         }
1957
1958         if ((ra % NF_PG_SZ) != 0) {
1959                 diag_printf("** Error: flash address must be page aligned\n");
1960                 return;
1961         }
1962
1963         mem_addr_st = mem_addr;
1964         len_st = len;
1965         ra &= MXC_NAND_ADDR_MASK;
1966         do {
1967                 if (OFFSET_TO_BLOCK(ra) > (NF_BLK_CNT - 1)) {
1968                         diag_printf("Out of range: addr=0x%x\n", ra);
1969                         return;
1970                 }
1971                 if (nfc_is_badblock(OFFSET_TO_BLOCK(ra), g_bbt)) {
1972                         if (skip++ >= flash_dev_info->max_bad_blk) {
1973                                 diag_printf("\nToo many bad blocks encountered\n");
1974                                 return;
1975                         }
1976                         diag_printf("\nSkipping bad block %u at addr=0x%08llx\n",
1977                                                 OFFSET_TO_BLOCK(ra), (u64)ra);
1978                         ra = (OFFSET_TO_BLOCK(ra) + 1) *  NF_BLK_SZ;
1979                         continue;
1980                 }
1981
1982                 if ((ra % NF_BLK_SZ) == 0) {
1983                          mem_addr_st = mem_addr;
1984                          len_st = len;
1985                 }
1986                 if (nfc_write_pg_random(ra / NF_PG_SZ, ra % NF_PG_SZ, (u8 *)mem_addr, 0) != 0) {
1987                         if (g_nfc_debug_level >= NFC_DEBUG_DEF) {
1988                                 diag_printf("Warning %d: program error at addr 0x%x\n", __LINE__, ra);
1989                         }
1990                         mark_blk_bad(OFFSET_TO_BLOCK(ra), g_bbt, BLK_BAD_RUNTIME);
1991                         ra = (OFFSET_TO_BLOCK(ra) + 1) *  NF_BLK_SZ; //make sure block size aligned
1992                         mem_addr = mem_addr_st; // rewind to blocl boundary
1993                         len = len_st;
1994                         continue;
1995                 }
1996                 if ((j++ % 0x20) == 0)
1997                         diag_printf("\nProgramming 0x%08x: ", ra);
1998                 diag_printf(".");
1999
2000                 len -= NF_PG_SZ;
2001                 ra += NF_PG_SZ;
2002                 mem_addr += NF_PG_SZ;
2003         } while (len > 0);
2004         if (skip) {
2005                 diag_printf("\n%s(skip bad blocks=%d\n\n", __FUNCTION__, skip);
2006         }
2007         diag_printf("\n");
2008 }
2009
2010 void nand_debug_fun(int argc, char *argv[])
2011 {
2012         int opt;
2013         const char *dbg_lvl_str;
2014
2015         if (argc == 3) {
2016                 opt = argv[2][0] - '0';
2017                 switch (opt) {
2018                 case 0:
2019                         g_nfc_debug_level = NFC_DEBUG_NONE;
2020                         break;
2021                 case 1:
2022                         g_nfc_debug_level = NFC_DEBUG_MIN;
2023                         break;
2024                 case 2:
2025                         g_nfc_debug_level = NFC_DEBUG_MED;
2026                         break;
2027                 case 3:
2028                         g_nfc_debug_level = NFC_DEBUG_MAX;
2029                         break;
2030                 case 4:
2031                         g_ecc_enable = g_ecc_enable? false: true;
2032                         break;
2033                 case 5:
2034                         // toggle g_spare_only_read_ok
2035                         g_spare_only_read_ok = g_spare_only_read_ok? false: true;
2036                         break;
2037                 case 9:
2038                         g_nfc_debug_measure = g_nfc_debug_measure? false: true;
2039                         break;
2040
2041                 default:
2042                         diag_printf("%s(%s) not supported\n", __FUNCTION__, argv[2]);
2043                 }
2044         }
2045         switch (g_nfc_debug_level) {
2046         case NFC_DEBUG_NONE:
2047                 dbg_lvl_str = "none";
2048                 break;
2049         case NFC_DEBUG_MIN:
2050                 dbg_lvl_str = "min";
2051                 break;
2052         case NFC_DEBUG_MED:
2053                 dbg_lvl_str = "med";
2054                 break;
2055         case NFC_DEBUG_MAX:
2056                 dbg_lvl_str = "max";
2057                 break;
2058         default:
2059                 dbg_lvl_str = "invalid";
2060         }
2061         diag_printf("Current debug options are:\n");
2062         diag_printf("    h/w ECC: %s\n", g_ecc_enable ? "on" : "off");
2063         diag_printf("    sp-only read: %s\n", g_spare_only_read_ok ? "on" : "off");
2064         diag_printf("    measurement: %s\n", g_nfc_debug_measure ? "on" : "off");
2065         diag_printf("    message level: %s\n", dbg_lvl_str);
2066 }
2067
2068 static void nand_erase(int argc, char *argv[])
2069 {
2070         u32 len, ra;
2071         bool faddr_set = false;
2072         bool force_erase_set = false;
2073         bool length_set = false;
2074         struct option_info opts[4];
2075
2076         init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
2077                   &ra, &faddr_set, "FLASH memory base address");
2078         init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
2079                   &len, &length_set, "length in bytes");
2080         init_opts(&opts[2], 'o', false, OPTION_ARG_TYPE_FLG,
2081                   &force_erase_set, &force_erase_set, "force erases block");
2082
2083         if (!scan_opts(argc, argv, 2, opts, 4, 0, 0, 0)) {
2084                 nand_usage("invalid arguments");
2085                 return;
2086         }
2087
2088         if (!faddr_set || !length_set) {
2089                 nand_usage("missing argument");
2090                 return;
2091         }
2092         if ((ra % NF_BLK_SZ) != 0 ||
2093                 (len % NF_BLK_SZ) != 0 || len == 0) {
2094                 diag_printf("Address or length is not block aligned or length is zero!\n");
2095                 diag_printf("Block size is 0x%x\n", NF_BLK_SZ);
2096                 return;
2097         }
2098
2099         if (!verify_action("About to erase 0x%x bytes from nand offset 0x%x\n", len, ra)) {
2100                 diag_printf("** Aborted\n");
2101                 return;
2102         }
2103
2104         // now ra is block aligned
2105         if (force_erase_set == true) {
2106                 diag_printf("Force erase ...");
2107                 nfc_erase_region(ra, len, 0, 1);
2108                 diag_printf("\n");
2109         } else {
2110                 nfc_erase_region(ra, len, 1, 1);
2111         }
2112         diag_printf("\n");
2113 }
2114
2115 extern void romupdate(int argc, char *argv[]);
2116 static void nand_scan(int argc, char *argv[])
2117 {
2118         bool force_erase = false;
2119         bool force_rescan = false;
2120         struct option_info opts[2];
2121
2122         init_opts(&opts[0], 'o', false, OPTION_ARG_TYPE_FLG,
2123                   &force_erase, NULL, "force erases block first");
2124
2125         init_opts(&opts[1], 'r', false, OPTION_ARG_TYPE_FLG,
2126                   &force_rescan, NULL, "force low level re-scan");
2127
2128         if (!scan_opts(argc, argv, 2, opts, 2, 0, 0, 0)) {
2129                 nand_usage("invalid arguments");
2130                 return;
2131         }
2132
2133         if (!force_erase && !force_rescan && !mxc_nfc_scan_done) {
2134                 diag_printf("Need to build BBT first with \"nand scan [-o|-r]\"\n");
2135                 return;
2136         }
2137         if (force_erase) {
2138                 void *bbt = g_bbt;
2139
2140                 diag_printf("Force erase first ...\n");
2141                 g_bbt = NULL;
2142                 // do force erase, skipping bad blocks. After this call, g_bbt should be re-built
2143                 // for the whole NAND flash.
2144                 if (nfc_erase_region(0, NF_DEV_SZ, true, false) != 0) {
2145                         g_bbt = bbt;
2146                         return;
2147                 }
2148                 g_bbt = bbt;
2149                 mxc_nfc_scan_done = 0;
2150                 diag_printf("\n");
2151         }
2152         if (force_rescan) {
2153                 diag_printf("Force re-scan ...\n");
2154                 memset(g_bbt, 0, g_bbt_sz);
2155                 mxc_nfc_scan(true);
2156         }
2157         // program g_bbt into the flash
2158         diag_printf("Writing BBT to flash\n");
2159         if (program_bbt_to_flash() != 0) {
2160                 diag_printf("Error: Failed to write BBT to flash\n");
2161         }
2162         if (force_erase) {
2163                 romupdate(0, NULL);
2164         }
2165 }
2166
2167 static void nand_info(int argc, char *argv[])
2168 {
2169         u32 i, j = 0;
2170
2171         if (nand_flash_index == -1) {
2172                 diag_printf("Can't find valid NAND flash: %d\n", __LINE__);
2173                 return;
2174         }
2175
2176         diag_printf("\nType:\t\t %s\n", NF_VEND_INFO);
2177         diag_printf("Total size:\t 0x%08x bytes (%d MiB)\n", NF_DEV_SZ, NF_DEV_SZ / SZ_1M);
2178         diag_printf("Total blocks:\t 0x%x (%d)\n", NF_BLK_CNT, NF_BLK_CNT);
2179         diag_printf("Block size:\t 0x%x (%d)\n", NF_BLK_SZ, NF_BLK_SZ);
2180         diag_printf("Page size:\t 0x%x (%d)\n", NF_PG_SZ, NF_PG_SZ);
2181         diag_printf("Spare size:\t 0x%x (%d)\n", NF_SPARE_SZ, NF_SPARE_SZ);
2182         diag_printf("Pages per block: 0x%x (%d)\n", NF_PG_PER_BLK, NF_PG_PER_BLK);
2183
2184         if (mxc_nfc_scan(false) == -1) {
2185                 return;
2186         }
2187         diag_printf("\n");
2188         for (i = 0; i < NF_BLK_CNT; i++) {
2189                 int res = nfc_is_badblock(i, g_bbt);
2190                 if (res & ~BLK_RESERVED) {
2191                         diag_printf("block %d at offset 0x%x is a %s bad block\n",
2192                                                 i, i * NF_BLK_SZ, res == BLK_BAD_FACTORY ? "factory" : "runtime");
2193                         j++;
2194                 }
2195         }
2196         diag_printf("==================================\n");
2197         diag_printf("Found %d bad block(s) out of %d\n", j, i);
2198 }
2199
2200 static void nand_bad(int argc, char *argv[])
2201 {
2202         u32 ra;
2203         u32 block;
2204         bool ra_set = false;
2205         bool block_set = false;
2206         bool clear = false;
2207         struct option_info opts[3];
2208         int bad;
2209
2210         init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
2211                           &ra, &ra_set, "FLASH memory base address");
2212         init_opts(&opts[1], 'b', true, OPTION_ARG_TYPE_NUM,
2213                           &block, &block_set, "block number");
2214         init_opts(&opts[2], 'c', false, OPTION_ARG_TYPE_FLG,
2215                           &clear, NULL, "clear bad block marker");
2216
2217         if (!scan_opts(argc, argv, 2, opts, NUM_ELEMS(opts), NULL, 0, NULL)) {
2218                 nand_usage("invalid arguments");
2219                 return;
2220         }
2221
2222         if (!ra_set && !block_set) {
2223                 nand_usage("missing argument");
2224                 return;
2225         }
2226         if (ra_set && block_set) {
2227                 nand_usage("options -f and -b are mutually exclusive");
2228                 return;
2229         } else if (ra_set) {
2230                 block = OFFSET_TO_BLOCK(ra & MXC_NAND_ADDR_MASK);
2231         } else {
2232                 ra = BLOCK_TO_OFFSET(block) + (unsigned long)flash_info.start;
2233         }
2234         if ((ra % NF_BLK_SZ) != 0) {
2235                 diag_printf("Address is not block aligned!\n");
2236                 diag_printf("Block size is 0x%08x\n", NF_BLK_SZ);
2237                 return;
2238         }
2239
2240         bad = nfc_is_badblock(block, g_bbt);
2241         if ((bad && !clear) || (!bad && clear)) {
2242                 diag_printf("block %5u at address 0x%08x is already %s\n",
2243                                         block, ra, bad ? "bad" : "good");
2244                 return;
2245         }
2246         if (clear && bad != BLK_BAD_RUNTIME) {
2247                 diag_printf("Refusing to mark a factory bad block as good!\n");
2248                 return;
2249         }
2250         if (!verify_action("Mark block %u at address 0x%08x %s in BBT",
2251                                            block, ra, clear ? "good" : "bad")) {
2252                 diag_printf("** Aborted\n");
2253                 return;
2254         }
2255
2256         nfc_printf(NFC_DEBUG_MIN, "Marking block %5u at 0x%08x %s\n",
2257                            block, ra, clear ? "good" : "bad");
2258         mark_blk_bad(block, g_bbt, clear ? 0 : BLK_BAD_RUNTIME);
2259         mxc_nfc_update_bbt(g_mxc_nfc_bbt_main_descr,
2260                                            g_mxc_nfc_bbt_mirror_descr);
2261 }
2262
2263 static void do_nand_cmds(int argc, char *argv[])
2264 {
2265         struct cmd *cmd;
2266
2267         if (!mxcnfc_init_ok) {
2268 #ifdef CYGHWR_DEVS_FLASH_MXC_MULTI
2269                 diag_printf("Warning: NAND flash hasn't been initialized. Try \"factive nand\" first\n\n");
2270 #else
2271                 diag_printf("Error: NAND flash hasn't been initialized\n");
2272 #endif
2273                 return;
2274         }
2275
2276         if (argc < 2) {
2277                 nand_usage("too few arguments");
2278                 return;
2279         }
2280
2281         if ((cmd = cmd_search(__NAND_cmds_TAB__, &__NAND_cmds_TAB_END__,
2282                                                   argv[1])) != NULL) {
2283                 cmd->fun(argc, argv);
2284                 return;
2285         }
2286         nand_usage("unrecognized command");
2287 }
2288
2289 /*!
2290  * Display a memory region by 16-bit words
2291  * @param pkt   pointer to the starting address of the memory
2292  * @param len   byte length of the buffer to be displayed
2293  */
2294 static void print_pkt_16(u16 *pkt, u32 len)
2295 {
2296         diag_printf("******************** %d bytes********************\n", len);
2297         u32 i = 0, tempLen = (len + 1) / 2;
2298
2299         while (tempLen != 0) {
2300                 if (tempLen >= 8) {
2301                         diag_printf("[%03x-%03x] ", i * 2, (i * 2) + 14);
2302                         diag_printf("%04x %04x %04x %04x %04x %04x %04x %04x\n",
2303                                                 pkt[i], pkt[i + 1], pkt[i + 2], pkt[i + 3],
2304                                                 pkt[i + 4], pkt[i + 5], pkt[i + 6], pkt[i + 7]);
2305                         tempLen -= 8;
2306                         i += 8;
2307                 } else {
2308                         if (tempLen != 0) {
2309                                 diag_printf("[%03x-%03x]", i * 2, (i + tempLen) * 2);
2310                                 while (tempLen-- != 0) {
2311                                         diag_printf(" %04x", pkt[i++]);
2312                                 }
2313                                 diag_printf("\n");
2314                         }
2315                         diag_printf("*************************************************\n");
2316                         return;
2317                 }
2318         }
2319 }
2320
2321 // addr = starting byte address within NAND flash
2322 static void print_page(u32 addr, bool spare_only)
2323 {
2324         u32 i, pg_no, pg_off;
2325         u32 blk_num = OFFSET_TO_BLOCK(addr), pg_num = OFFSET_TO_PAGE(addr);
2326
2327         if (addr % NF_PG_SZ) {
2328                 diag_printf("Non page-aligned read not supported here: 0x%x\n", addr);
2329                 return;
2330         }
2331         if (spare_only) {
2332                 diag_printf("Error %d: Not supported\n", __LINE__);
2333                 return;
2334         } else {
2335                 pg_no = addr / NF_PG_SZ;
2336                 pg_off = addr % NF_PG_SZ;
2337                 for (i = 0; i < num_of_nand_chips; i++) {
2338                         if (nfc_read_page(i, pg_no, pg_off) != 0) {
2339                                 diag_printf("Error %d: uncorrectable. But still printing ...\n", __LINE__);
2340                         }
2341                         pg_off = 0;
2342                         diag_printf("\n============ Printing block(%d) page(%d)  ==============\n",
2343                                                                   blk_num, pg_num);
2344
2345                         diag_printf("<<<<<<<<< spare area >>>>>>>>>\n");
2346                         print_pkt_16((u16*)NAND_SPAR_BUF0, NF_SPARE_SZ);
2347
2348                         if (!spare_only) {
2349                                 diag_printf("<<<<<<<<< main area >>>>>>>>>\n");
2350                                 print_pkt_16((u16*)NAND_MAIN_BUF0, NF_PG_SZ / num_of_nand_chips);
2351                         }
2352
2353                         diag_printf("\n");
2354                 }
2355         }
2356 }