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