update to Platform Library 00.06: header file updates
[keystone-rtos/mcsdk-tools.git] / writer / nand / src / nandwriter.c
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