458796be306167549b6ef0ef762d399d86d35d6a
1 /*\r
2 * Copyright (c) 2011-2015, Texas Instruments Incorporated\r
3 * All rights reserved.\r
4 *\r
5 * Redistribution and use in source and binary forms, with or without\r
6 * modification, are permitted provided that the following conditions\r
7 * are met:\r
8 *\r
9 * * Redistributions of source code must retain the above copyright\r
10 * notice, this list of conditions and the following disclaimer.\r
11 *\r
12 * * Redistributions in binary form must reproduce the above copyright\r
13 * notice, this list of conditions and the following disclaimer in the\r
14 * documentation and/or other materials provided with the distribution.\r
15 *\r
16 * * Neither the name of Texas Instruments Incorporated nor the names of\r
17 * its contributors may be used to endorse or promote products derived\r
18 * from this software without specific prior written permission.\r
19 *\r
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
31 *\r
32 */\r
33 \r
34 /**************************************************************************************\r
35 * FILE PURPOSE: NAND writer utility\r
36 **************************************************************************************\r
37 * FILE NAME: nandwriter.c\r
38 *\r
39 * DESCRIPTION: A simple nand writer using platform lib APIs to program the NAND flash\r
40 * with an image that the ibl can read.\r
41 *\r
42 ***************************************************************************************/\r
43 #include <stdlib.h>\r
44 #include <stdio.h>\r
45 #include <string.h>\r
46 #include "platform.h"\r
47 #include "types.h"\r
48 \r
49 /* NAND writer utility version */\r
50 char version[] = "01.00.00.05";\r
51 \r
52 /* The input file name is hard coded */\r
53 char *input_file = "nand_writer_input.txt";\r
54 \r
55 uint32_t swap_byte = 0;\r
56 volatile uint32_t nand_erase_flag = 0;\r
57 \r
58 /* Parameters defined in the input_file */\r
59 #define FILE_NAME "file_name"\r
60 #define START_ADDR "start_addr"\r
61 #define RBL_ECC "rbl_ecc"\r
62 #define SKIP_BAD "skip_bad"\r
63 \r
64 /* Memory address to store the write data */\r
65 #define WRITE_DATA_ADDRESS 0x80000000\r
66 \r
67 /* NAND device specific definitions */\r
68 #define BAD_BLOCK_MARKER_VALUE 0xA5\r
69 \r
70 /******************************************************************************\r
71 * Structure: NAND_WRITER_INFO_T\r
72 *\r
73 * NAND writer control data. This structure should be filled in\r
74 * by the user before running\r
75 ******************************************************************************/\r
76 #define MAX_LINE_LENGTH 40\r
77 typedef struct NAND_WRITER_INFO_tag\r
78 {\r
79 char file_name[MAX_LINE_LENGTH]; /* CCS format data file name */\r
80 uint32_t blockSizeBytes; /* The size of each sector */\r
81 uint32_t deviceTotalBytes; /* Total number of bytes available in the device */\r
82 uint32_t startAddr; /* Start address to write */\r
83 uint32_t writeBytes; /* Number of bytes to be written into the device */\r
84 uint8_t flags; /* Flag used for EVMK2H for multiple ECC formats */\r
85 uint8_t skip_bad_blks; /* Flag used to skip bad blocks */\r
86 uint8_t *writeData; /* Address to store the write data */\r
87 uint8_t *readData; /* Address to store the read data */\r
88 \r
89 } NAND_WRITER_INFO_T;\r
90 \r
91 NAND_WRITER_INFO_T nandWriterInfo;\r
92 \r
93 /* OSAL functions for Platform Library */\r
94 uint8_t *Osal_platformMalloc (uint32_t num_bytes, uint32_t alignment)\r
95 {\r
96 return malloc(num_bytes);\r
97 }\r
98 \r
99 void Osal_platformFree (uint8_t *dataPtr, uint32_t num_bytes)\r
100 {\r
101 /* Free up the memory */\r
102 if (dataPtr)\r
103 {\r
104 free(dataPtr);\r
105 }\r
106 }\r
107 \r
108 void Osal_platformSpiCsEnter(void)\r
109 {\r
110 return;\r
111 }\r
112 \r
113 void Osal_platformSpiCsExit (void)\r
114 {\r
115 return;\r
116 }\r
117 \r
118 /******************************************************************************\r
119 * Function: print_platform_errno\r
120 ******************************************************************************/\r
121 void\r
122 print_platform_errno\r
123 (\r
124 void\r
125 )\r
126 {\r
127 printf ("Returned platform error number is %d\n", platform_errno);\r
128 }\r
129 \r
130 /******************************************************************************\r
131 * Function: checkBadBlockMark\r
132 *\r
133 * Checks for the bad block mark. Returns TRUE if a block is marked bad.\r
134 ******************************************************************************/\r
135 Bool\r
136 checkBadBlockMark \r
137 (\r
138 PLATFORM_DEVICE_info *p_device,\r
139 uint32_t block\r
140 )\r
141 {\r
142 if (p_device->bblist[block] != 0xff)\r
143 {\r
144 return TRUE;\r
145 }\r
146 else\r
147 {\r
148 return FALSE;\r
149 }\r
150 }\r
151 \r
152 /******************************************************************************\r
153 * Function: markBlockBad\r
154 *\r
155 * Mark a block as bad. Byte 5 of the spare area data is\r
156 * written as 0xA5.\r
157 ******************************************************************************/\r
158 void \r
159 markBlockBad \r
160 (\r
161 PLATFORM_DEVICE_info *p_device,\r
162 uint32_t block\r
163 )\r
164 {\r
165 uint8_t *spare_data;\r
166 \r
167 spare_data = malloc(p_device->spare_size);\r
168 if (spare_data == NULL)\r
169 {\r
170 printf ("Can not allocate spare_data memory!\n");\r
171 return;\r
172 }\r
173 \r
174 platform_device_read_spare_data(p_device->handle, block, 0, spare_data);\r
175 \r
176 /* Set all data bytes to 0xff, only set the user defined bad block mark value */\r
177 spare_data[p_device->bboffset] = BAD_BLOCK_MARKER_VALUE;\r
178 \r
179 /* Write the data to page */\r
180 platform_device_write_spare_data(p_device->handle, block, 0, spare_data);\r
181 \r
182 /* Save the user defined bad block mark in bblist */\r
183 p_device->bblist[block] = BAD_BLOCK_MARKER_VALUE;\r
184 \r
185 free (spare_data);\r
186 }\r
187 \r
188 /******************************************************************************\r
189 * Function: formBlock\r
190 *\r
191 * Form a block of data to write to the NAND. The block is\r
192 * created as a byte stream from the 4 byte stream in which\r
193 * the MSB is always sent first.\r
194 ******************************************************************************/\r
195 void\r
196 formBlock\r
197 (\r
198 uint32_t *data,\r
199 uint32_t blockSize,\r
200 uint8_t *scratch\r
201 )\r
202 {\r
203 uint32_t i, j;\r
204 \r
205 /* Convert the data to a byte stream */\r
206 for (i = j = 0; j < blockSize; i++, j+=4)\r
207 {\r
208 scratch[j+0] = (data[i] >> 24) & 0xff;\r
209 scratch[j+1] = (data[i] >> 16) & 0xff;\r
210 scratch[j+2] = (data[i] >> 8) & 0xff;\r
211 scratch[j+3] = (data[i] >> 0) & 0xff;\r
212 }\r
213 }\r
214 \r
215 /******************************************************************************\r
216 * Function: flash_nand\r
217 *\r
218 * Write the image to flash.\r
219 * Returns TRUE if the image is written successfully\r
220 * FALSE if the image write fails\r
221 ******************************************************************************/\r
222 Bool \r
223 flash_nand\r
224 (\r
225 PLATFORM_DEVICE_info *p_device\r
226 )\r
227 {\r
228 uint32_t wPos, wLen;\r
229 uint32_t block, start_block;\r
230 uint8_t *scrach_block;\r
231 uint32_t num_blks;\r
232 uint32_t bad_block_found;\r
233 \r
234 if (swap_byte)\r
235 {\r
236 scrach_block = malloc(nandWriterInfo.blockSizeBytes);\r
237 if (scrach_block == NULL)\r
238 {\r
239 printf ("Can not allocate scratch block memory!\n");\r
240 return (FALSE);\r
241 }\r
242 }\r
243 \r
244 start_block = nandWriterInfo.startAddr / nandWriterInfo.blockSizeBytes;\r
245 \r
246 /* skip the bad blocks if the flag is set */\r
247 if (nandWriterInfo.skip_bad_blks)\r
248 {\r
249 num_blks = nandWriterInfo.writeBytes / nandWriterInfo.blockSizeBytes;\r
250 if ((nandWriterInfo.writeBytes - nandWriterInfo.blockSizeBytes * num_blks) > 0)\r
251 num_blks++;\r
252 \r
253 while (TRUE)\r
254 {\r
255 bad_block_found = FALSE;\r
256 for (block = start_block; block < start_block + num_blks; block++)\r
257 {\r
258 if (checkBadBlockMark(p_device, block))\r
259 {\r
260 start_block = block + 1;\r
261 bad_block_found = TRUE;\r
262 break;\r
263 }\r
264 }\r
265 if (bad_block_found == FALSE)\r
266 break;\r
267 }\r
268 }\r
269 \r
270 /* Program the NAND */\r
271 for (block = start_block, wPos = 0; wPos < nandWriterInfo.writeBytes; block++, wPos += nandWriterInfo.blockSizeBytes)\r
272 {\r
273 while(checkBadBlockMark(p_device, block))\r
274 {\r
275 printf ("Bad block # %d detected, skipping block ... \n", block);\r
276 if (++block == p_device->block_count)\r
277 {\r
278 printf ("Flash failed: End of device reached\n");\r
279 if (swap_byte) free (scrach_block);\r
280 return (FALSE); \r
281 }\r
282 }\r
283 \r
284 printf ("Flashing block %d (%d bytes of %d)\n", block, wPos, nandWriterInfo.writeBytes);\r
285 \r
286 platform_device_erase_block(p_device->handle, block);\r
287 \r
288 wLen = nandWriterInfo.blockSizeBytes;\r
289 if (nandWriterInfo.writeBytes - wPos < nandWriterInfo.blockSizeBytes)\r
290 {\r
291 wLen = nandWriterInfo.writeBytes - wPos;\r
292 }\r
293 \r
294 if (swap_byte)\r
295 {\r
296 formBlock((uint32_t *)(&nandWriterInfo.writeData[wPos]), nandWriterInfo.blockSizeBytes, scrach_block);\r
297 }\r
298 else\r
299 {\r
300 scrach_block = &nandWriterInfo.writeData[wPos];\r
301 }\r
302 if (platform_device_write(p_device->handle, \r
303 block*nandWriterInfo.blockSizeBytes, \r
304 scrach_block, \r
305 wLen) != Platform_EOK)\r
306 {\r
307 printf ("platform_device_write block # %d failed!\n", block);\r
308 print_platform_errno();\r
309 if (swap_byte) free (scrach_block);\r
310 return (FALSE);\r
311 }\r
312 \r
313 }\r
314 \r
315 if (swap_byte) free (scrach_block);\r
316 return (TRUE);\r
317 } \r
318 \r
319 /******************************************************************************\r
320 * Function: flash_verify\r
321 *\r
322 * Read back the data file that was just flashed. On errors mark the block as bad.\r
323 * Returns TRUE if the image verified correctly.\r
324 * FALSE if the image verification failed\r
325 ******************************************************************************/\r
326 Bool \r
327 flash_verify\r
328 (\r
329 PLATFORM_DEVICE_info *p_device\r
330 )\r
331 {\r
332 uint32_t rPos, rLen;\r
333 uint32_t i, j;\r
334 uint32_t block, start_block;\r
335 uint8_t *scrach_block;\r
336 uint32_t *read_data_w;\r
337 \r
338 if (swap_byte) \r
339 {\r
340 scrach_block = malloc(nandWriterInfo.blockSizeBytes);\r
341 if (scrach_block == NULL)\r
342 {\r
343 printf ("Can not allocate scratch block memory!\n");\r
344 return (FALSE);\r
345 }\r
346 }\r
347 \r
348 start_block = nandWriterInfo.startAddr / nandWriterInfo.blockSizeBytes;\r
349 \r
350 for (block = start_block, rPos = 0; rPos < nandWriterInfo.writeBytes; block++, rPos += nandWriterInfo.blockSizeBytes)\r
351 {\r
352 while(checkBadBlockMark(p_device, block))\r
353 {\r
354 printf ("Bad block # %d detected, skipping block ... \n", block);\r
355 if (++block == p_device->block_count)\r
356 {\r
357 printf ("Flash failed: End of device reached\n");\r
358 if (swap_byte) free (scrach_block);\r
359 return (FALSE); \r
360 }\r
361 }\r
362 \r
363 \r
364 printf ("Reading and verifying block %d (%d bytes of %d)\n", block, rPos, nandWriterInfo.writeBytes);\r
365 \r
366 if (!swap_byte)\r
367 {\r
368 scrach_block = &nandWriterInfo.readData[rPos];\r
369 \r
370 }\r
371 \r
372 /* Read a block of data */\r
373 if(platform_device_read(p_device->handle, \r
374 block*nandWriterInfo.blockSizeBytes, \r
375 scrach_block,\r
376 nandWriterInfo.blockSizeBytes) != Platform_EOK)\r
377 {\r
378 printf ("Failure in reading block %d\n", block);\r
379 print_platform_errno();\r
380 if (platform_errno == PLATFORM_ERRNO_ECC_FAIL)\r
381 {\r
382 printf ("marking block %d as bad, re-flash attempted\n", block);\r
383 markBlockBad (p_device, block);\r
384 }\r
385 if (swap_byte) free (scrach_block);\r
386 return (FALSE);\r
387 }\r
388 \r
389 /* Convert the packed data */\r
390 if (swap_byte)\r
391 {\r
392 read_data_w = (uint32_t *)(&nandWriterInfo.readData[rPos]);\r
393 for (i = 0, j = 0; i < nandWriterInfo.blockSizeBytes; i += 4)\r
394 read_data_w[j++] = (scrach_block[i+0] << 24) | (scrach_block[i+1] << 16) | (scrach_block[i+2] << 8) | scrach_block[i+3];\r
395 }\r
396 \r
397 rLen = nandWriterInfo.blockSizeBytes;\r
398 if (nandWriterInfo.writeBytes - rPos < nandWriterInfo.blockSizeBytes)\r
399 {\r
400 rLen = nandWriterInfo.writeBytes - rPos;\r
401 }\r
402 \r
403 /* Compare the data read with data programmed */\r
404 for (i = rPos; i < rLen; i++)\r
405 {\r
406 if (nandWriterInfo.readData[i] != nandWriterInfo.writeData[i])\r
407 {\r
408 printf ("Failure in block %d, at byte %d, (at byte %d in the data file) expected 0x%08x, read 0x%08x\n", \r
409 block, i, rPos, nandWriterInfo.writeData[i], nandWriterInfo.readData[i]);\r
410 if (swap_byte) free (scrach_block);\r
411 return (FALSE);\r
412 }\r
413 }\r
414 \r
415 }\r
416 \r
417 if (swap_byte) free (scrach_block);\r
418 return (TRUE);\r
419 }\r
420 \r
421 /******************************************************************************\r
422 * Function: parse_input_file \r
423 ******************************************************************************/\r
424 static Bool\r
425 parse_input_file\r
426 (\r
427 FILE* fp\r
428 )\r
429 {\r
430 char line[MAX_LINE_LENGTH];\r
431 char tokens[] = " :=;\n\r";\r
432 char *key, *data;\r
433 \r
434 memset(line, 0, MAX_LINE_LENGTH);\r
435 \r
436 fgets(line, MAX_LINE_LENGTH, fp);\r
437 key = (char *)strtok(line, tokens);\r
438 data = (char *)strtok(NULL, tokens);\r
439 \r
440 if(strlen(data) == 0)\r
441 {\r
442 return FALSE;\r
443 }\r
444 \r
445 if(strcmp(key, FILE_NAME) != 0)\r
446 {\r
447 return FALSE;\r
448 }\r
449 \r
450 strcpy (nandWriterInfo.file_name, data);\r
451 \r
452 fgets(line, MAX_LINE_LENGTH, fp);\r
453 key = (char *)strtok(line, tokens);\r
454 data = (char *)strtok(NULL, tokens);\r
455 \r
456 if(strlen(data) == 0)\r
457 {\r
458 return FALSE;\r
459 }\r
460 \r
461 if(strcmp(key, START_ADDR) != 0)\r
462 {\r
463 return FALSE;\r
464 }\r
465 \r
466 nandWriterInfo.startAddr = (uint32_t)atoi(data);\r
467 \r
468 fgets(line, MAX_LINE_LENGTH, fp);\r
469 key = (char *)strtok(line, tokens);\r
470 data = (char *)strtok(NULL, tokens);\r
471 \r
472 if(strlen(data) != 0 && (strcmp(key, RBL_ECC) == 0))\r
473 {\r
474 nandWriterInfo.flags = (uint8_t)atoi(data);\r
475 }\r
476 else\r
477 {\r
478 nandWriterInfo.flags = 0;\r
479 }\r
480 \r
481 /* Scan skip bad block input parameter */\r
482 fgets(line, MAX_LINE_LENGTH, fp);\r
483 key = (char *)strtok(line, tokens);\r
484 data = (char *)strtok(NULL, tokens);\r
485 \r
486 if(strlen(data) != 0 && (strcmp(key, SKIP_BAD) == 0))\r
487 {\r
488 nandWriterInfo.skip_bad_blks = (uint8_t)atoi(data);\r
489 }\r
490 else\r
491 {\r
492 nandWriterInfo.skip_bad_blks = 0;\r
493 }\r
494 \r
495 return TRUE;\r
496 }\r
497 \r
498 /******************************************************************************\r
499 * Function: find_file_length\r
500 ******************************************************************************/\r
501 static Bool\r
502 find_file_length\r
503 (\r
504 FILE* fp\r
505 )\r
506 {\r
507 char line[MAX_LINE_LENGTH];\r
508 char *pEnd;\r
509 char *ext;\r
510 uint32_t data_len, write_addr;\r
511 \r
512 memset(line, 0, MAX_LINE_LENGTH);\r
513 \r
514 ext = strrchr(nandWriterInfo.file_name, '.');\r
515 if (ext && (strcmp(ext, ".dat") == 0))\r
516 {\r
517 fgets(line, MAX_LINE_LENGTH, fp);\r
518 \r
519 /* Read the write address from the CCS header */\r
520 strtoul (line,&pEnd,16);\r
521 strtoul (pEnd,&pEnd,16);\r
522 write_addr = strtoul (pEnd,&pEnd,16);\r
523 strtoul (pEnd,&pEnd,16);\r
524 \r
525 /* Read the data length */\r
526 data_len = (strtoul (pEnd,NULL,16)) * 4;\r
527 }\r
528 else\r
529 {\r
530 /* find the data length by seeking to the end and getting position */\r
531 fseek(fp, 0, SEEK_END);\r
532 data_len = ftell(fp);\r
533 fseek(fp, 0, SEEK_SET);\r
534 }\r
535 \r
536 if (data_len > (nandWriterInfo.deviceTotalBytes - nandWriterInfo.startAddr))\r
537 {\r
538 printf ("The data file is too big to fit into the device.\n");\r
539 return FALSE;\r
540 }\r
541 \r
542 nandWriterInfo.writeBytes = data_len;\r
543 if (write_addr != WRITE_DATA_ADDRESS)\r
544 write_addr = WRITE_DATA_ADDRESS;\r
545 nandWriterInfo.writeData = (uint8_t *)write_addr;\r
546 nandWriterInfo.readData = (uint8_t *)(write_addr + nandWriterInfo.deviceTotalBytes);\r
547 \r
548 return TRUE;\r
549 }\r
550 \r
551 static Bool \r
552 nand_erase_all_blks(PLATFORM_DEVICE_info *p_device)\r
553 {\r
554 uint32_t block;\r
555 uint32_t max_blks;\r
556 \r
557 max_blks = p_device->block_count;\r
558 \r
559 for (block=0; block<max_blks;block++)\r
560 {\r
561 printf (".");\r
562 if (platform_device_erase_block(p_device->handle, block) != Platform_EOK)\r
563 return FALSE;\r
564 }\r
565 \r
566 printf ("\nFormatted %d nand blocks \n", block);\r
567 return (TRUE);\r
568 }\r
569 \r
570 /******************************************************************************\r
571 * Function: main \r
572 ******************************************************************************/\r
573 void main ()\r
574 {\r
575 FILE *fp;\r
576 platform_init_flags init_flags;\r
577 platform_init_config init_config;\r
578 PLATFORM_DEVICE_info *p_device;\r
579 Bool ret;\r
580 uint32_t rCount;\r
581 printf("NAND Writer Utility Version %s\n\n", version);\r
582 \r
583 fp = fopen(input_file, "r");\r
584 if (fp == NULL)\r
585 {\r
586 printf("Error in opening %s input file\n", input_file);\r
587 return;\r
588 }\r
589 \r
590 ret = parse_input_file(fp);\r
591 fclose (fp);\r
592 \r
593 if (ret == FALSE)\r
594 {\r
595 printf("Error in parsing %s input file\n", input_file);\r
596 return;\r
597 }\r
598 \r
599 /* Initialize main Platform lib */\r
600 memset(&init_config, 0, sizeof(platform_init_config));\r
601 memset(&init_flags, 1, sizeof(platform_init_flags));\r
602 init_flags.pll = 0;\r
603 init_flags.ddr = 0;\r
604 init_flags.phy =0;\r
605 if (platform_init(&init_flags, &init_config) != Platform_EOK)\r
606 {\r
607 printf ("Platform init failed!\n");\r
608 print_platform_errno();\r
609 return;\r
610 }\r
611 #if (defined(_EVMC6657L_) || defined(DEVICE_K2H))\r
612 p_device = platform_device_open(PLATFORM_DEVID_MT29F1G08ABCHC, nandWriterInfo.flags);\r
613 #elif defined(DEVICE_K2E)\r
614 p_device = platform_device_open(PLATFORM_DEVID_MT29F4G08ABADA, nandWriterInfo.flags);\r
615 #elif defined(DEVICE_K2L)\r
616 p_device = platform_device_open(PLATFORM_DEVID_MT29F16G08ADBCAH4C, nandWriterInfo.flags);\r
617 #elif defined(DEVICE_K2G)\r
618 p_device = platform_device_open(PLATFORM_DEVID_MT29F2G16ABAFA, nandWriterInfo.flags);\r
619 #else\r
620 p_device = platform_device_open(PLATFORM_DEVID_NAND512R3A2D, 0);\r
621 #endif\r
622 if (p_device == NULL) \r
623 {\r
624 printf ("NAND device open failed!\n");\r
625 print_platform_errno();\r
626 return;\r
627 }\r
628 nandWriterInfo.deviceTotalBytes = p_device->block_count * p_device->page_count * p_device->page_size;\r
629 nandWriterInfo.blockSizeBytes = p_device->page_count * p_device->page_size;\r
630 \r
631 if ((nandWriterInfo.startAddr % nandWriterInfo.blockSizeBytes) != 0)\r
632 {\r
633 printf ("The start programming address 0x%8x set in %s is not at the beginning of a block, block size = 0x%4x\n", \r
634 nandWriterInfo.startAddr, \r
635 nandWriterInfo.file_name,\r
636 nandWriterInfo.blockSizeBytes);\r
637 return;\r
638 }\r
639 \r
640 /* Check if we need to erase the nand completely */\r
641 if (nand_erase_flag == 0x12345678)\r
642 {\r
643 if (nand_erase_all_blks(p_device) == FALSE)\r
644 {\r
645 printf ("Formatting all nand blocks - failed \n");\r
646 }\r
647 else\r
648 {\r
649 printf ("Formatting all nand blocks - Successful\n");\r
650 }\r
651 platform_device_close(p_device->handle);\r
652 /* Operation Complete */\r
653 return;\r
654 }\r
655 \r
656 /* Open and find the length of the data file */\r
657 fp = fopen (nandWriterInfo.file_name, "rb");\r
658 if (fp == NULL)\r
659 {\r
660 printf ("Failed to open file %s\n", nandWriterInfo.file_name);\r
661 platform_device_close(p_device->handle);\r
662 return;\r
663 }\r
664 \r
665 /* Parse the CCS format file */\r
666 ret = find_file_length(fp);\r
667 fclose (fp);\r
668 if (ret == FALSE)\r
669 {\r
670 printf("Error in parsing CCS file %s\n", nandWriterInfo.file_name);\r
671 platform_device_close(p_device->handle);\r
672 return;\r
673 }\r
674 \r
675 /* Write the flash, verify the results. On read back failure mark\r
676 * the block as bad and try rewriting again */\r
677 rCount = 0;\r
678 \r
679 do \r
680 {\r
681 if (flash_nand (p_device) == FALSE)\r
682 {\r
683 printf ("NAND write giving up\n");\r
684 return;\r
685 }\r
686 \r
687 rCount += 1;\r
688 \r
689 } while ((flash_verify (p_device) == FALSE) && (rCount < 5));\r
690 \r
691 \r
692 if (rCount >= 5) \r
693 {\r
694 printf ("NAND write failed (maximum retries reached)\n");\r
695 }\r
696 else\r
697 {\r
698 printf ("NAND programming completed successfully\n");\r
699 }\r
700 \r
701 platform_device_close(p_device->handle);\r
702 \r
703 return;\r
704 }\r
705 \r
706 \r
707 \r
708 \r