Added uboot tools
[keystone-rtos/mcsdk-tools.git] / boot_loader / uboot / nandwriter / nandwrite.c
1 /* A very simple NAND writer */
2 #include <stdio.h>\r
3 \r
4 // This code will work ONLY for Micron MT29F2G08ABDHC devices!
6 /* These values are setup at run time */
7 unsigned int busWidth             = 8;
8 unsigned int pageSizeBytes        = 2048;
9 unsigned int pagesPerBlock        = 64;
10 unsigned int spareBytesPerSegment = 16;
11 unsigned int spareBytesPerPage    = 0;
13 unsigned int readIdCmd          = 0x90;
14 unsigned int readPageCmd        = 0x00;
15 unsigned int readPageDoneCmd    = 0x30;        /* Not used for small page devices */
16 unsigned int readPageRandomCmd  = 0x05;        /* Not used for small page devices */
17 unsigned int readPageRndDoneCmd = 0xE0;        /* Not used for small page devices */
19 unsigned int smallPageReadEccCmd = 0x50;       /* Used only on small page devices */
21 unsigned int blockEraseACmd = 0x60;
22 unsigned int blockEraseBCmd = 0xD0;
24 unsigned int resetCmd = 0xFF;
26 unsigned int programACmd = 0x80;
27 unsigned int programBCmd = 0x10;
29 unsigned int readStatusRegCmd = 0x70;
31 /* Which pages have manufacturer bad block mark? */\r
32 unsigned int manufactureBadBlockPages[] = { 0 };   /* indexed from 0 */
33 \r
34 /* Which spare bytes of of page have manufacturer bad block mark? */\r
35 unsigned int manufactureBadBlockBytes[] = { 0 };   /* array of bad word mark locations indexed from 0 */
37 volatile unsigned int statusReg;
39 unsigned int csRegion = 0;
40 unsigned int memBase  = 0;
42 /* data, address, command latch addresses assuming the EMIF16 is configured with emif11a as
43  * the address latch, and emif12a as the command latch */
44 unsigned int dataOffset = 0x0000;
45 unsigned int addrOffset = 0x2000;
46 unsigned int cmdOffset  = 0x4000;
48 int smallPage = 0;  //1;
50 /* The following values are defined in the linker command file */
51 //extern unsigned int writeBlock;
52 //extern unsigned int readBlock;
53 //extern unsigned int spareBlock;
54 //extern unsigned int scratchBlock;
55 extern unsigned char writeBlock;
56 extern unsigned char readBlock;
57 extern unsigned char spareBlock;
58 extern unsigned char scratchBlock;
60 unsigned char *writeData        = &writeBlock;        /* Defined in the linker command file */
61 unsigned char *readData         = &readBlock;
62 unsigned char *spareData        = &spareBlock;        /* the spare data area is placed here after writes */
63 unsigned char *scratch          = &scratchBlock;      /* used for temporary storage */
65 volatile unsigned int dataSizeUint32    = 0x20000;  // THIS MUST BE SET TO THE NUMBER OF WORDS TO PROGRAM!
67 unsigned int firstBlock = 0;    /* The first block to program */
69 int doWrite   = 1;   /* Set to 1 to program the nand */
70 //int doCompare = 0;   /* Set to 1 to compare writeData and readData */
73 void eraseBlock (int n);
74 void programSegment(unsigned int firstBlock, int blockIdx, unsigned int page, int segment, unsigned int memOffset, unsigned int eccOffset);
75 void readAndCorrectSegment(unsigned int firstBlock, int blockCount, unsigned int pageCount, int segmentCount, unsigned int memOffset);
76 void readDeviceId();\r
78 volatile unsigned int dummy;
81 #define EMIF_CTL_BASE               0x20c00000
83 #define EMIF_CTL_RCSR               0x0000\r
84 \r
85 #define EMIF_CTL_A1CR               0x0010
87 #define EMIF_CTL_NANDFCR            0x0060
88 #define EMIF_CTL_NANDFSR            0x0064
90 #define EMIF_CTL_NANDF4BECCLR       0x00bc
92 #define EMIF_CTL_NANDF4BECC1R       0x00c0
93 #define EMIF_CTL_NANDF4BECC2R       0x00c4
94 #define EMIF_CTL_NANDF4BECC3R       0x00c8
95 #define EMIF_CTL_NANDF4BECC4R       0x00cc
97 #define EMIF_CTL_NANDFEA1R          0x00d0
98 #define EMIF_CTL_NANDFEA2R          0x00d4
100 #define EMIF_CTL_NANDFEV1R          0x00d8
101 #define EMIF_CTL_NANDFEV2R          0x00dc
103 #define BITMASK(x,y)      (   (   (  ((unsigned int)1 << (((unsigned int)x)-((unsigned int)y)+(unsigned int)1) ) - (unsigned int)1 )   )   <<  ((unsigned int)y)   )
104 #define READ_BITFIELD(z,x,y)   (((unsigned int)z) & BITMASK(x,y)) >> (y)
105 #define SET_BITFIELD(z,f,x,y)  (((unsigned int)z) & ~BITMASK(x,y)) | ( (((UINT32)f) << (y)) & BITMASK(x,y) )
106 \r
108 /***************/\r
109 /* Stop the ECC hardware block */\r
110 /***************/\r
111 void stopEcc(void)
113   dummy = *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_RCSR));
114   dummy = *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDF4BECC1R));
118 /***************/\r
119 /* Enable EMIF access for NAND at this chip select  */
120 /***************/\r
121 void nandEnableRegion(int region)
122 {\r
123   unsigned int a1cr;\r
124 \r
125   a1cr = *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_A1CR));
126   a1cr = a1cr & ~0x03;\r
128   *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDFCR)) = (1 << region);
129 \r
130   if (busWidth == 16)\r
131   {\r
132     a1cr = a1cr | 0x01;\r
133   }\r
134 \r
135   *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_A1CR)) = a1cr;
139 /***************/\r
140 /* Enable (start) the ECC calculation by the EMIF hardware block */
141 /***************/\r
142 void eccEnable(int region)
144   *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDFCR)) = (1 << region) | (region << 4) | (1 << 12);
146 \r
147 \r
148 /***************/\r
149 /*   */
150 /***************/\r
151 void correctDisable (void)
153   dummy = *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDFEA1R));
157 /***************/\r
158 /*   */
159 /***************/\r
160 void eccCorrectLoad (unsigned int v)
162   *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDF4BECCLR)) = v;
164 \r
166 /***************/\r
167 /*   */
168 /***************/\r
169 void eccWaitCalc (void)
171   dummy = *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_RCSR));
174 \r
175 /***************/\r
176 /* Read the ECC data from the hardware */
177 /***************/\r
178 void readEccReg (unsigned int *ev)
179 {\r
180   ev[0] = (*((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDF4BECC1R))) & 0x03ff03ff;
181   ev[1] = (*((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDF4BECC2R))) & 0x03ff03ff;
182   ev[2] = (*((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDF4BECC3R))) & 0x03ff03ff;
183   ev[3] = (*((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDF4BECC4R))) & 0x03ff03ff;
187 /***************/\r
188 /*   */
189 /***************/\r
190 /* returns:
191     -1 : errors cannot be corrected
192      0 : error are not in the data fields
193      1 : there are errors to be corrected
194 */
195 int errAddressRun(void)
197   unsigned int v;
199   *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDFCR)) = (1 << 13);
201   do\r
202   {
203     v = *((volatile unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDFSR));
204     v = (v >> 8) & 0xff;
205   } while ( (v != 1) && (v != 2) && (v != 3) );
207   return (v);
211 /***************/\r
212 /*   */
213 /***************/\r
214 int errNumErrors (void)
216     unsigned int v;
218     v = *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDFSR));
220     v = ((v >> 16) & 0x3) + 1;
222     return (v);
228 /***************/\r
229 /*   */
230 /***************/\r
231 void correct8BitData (unsigned char *p, int n)
233     unsigned int  idx;
234     unsigned char xor;
236     if ((n == 3) || (n == 4))  {
238         idx = 519 - *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDFEA1R));
239         xor = *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDFEV1R));
241     }  else  {
243         idx = 519 - *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDFEA2R));
244         xor = *((unsigned int *)(EMIF_CTL_BASE + EMIF_CTL_NANDFEV2R));
245     }
247     /* Shift if necessary, mask */
248     if ((n == 2) || (n == 4))  {
249         idx = (idx >> 16);
250         xor = (xor >> 16);
251     }
253     idx = idx & 0x3ff;
254     xor = xor & 0x0ff;
256     if (idx < 512)
257         p[idx] ^= xor;
262 volatile unsigned int deld;  // Delay variable
263 \r
265 /***************/\r
266 /* Big delay  */
267 /***************/\r
268 void bigDelay (void)
270   for (deld = 0; deld < 10000; deld++);
272 \r
274 /***************/\r
275 /* Small delay  */
276 /***************/\r
277 void smallDelay(void)
279   for (deld = 0; deld < 1000; deld++);
281 \r
282 \r
283 /***************/\r
284 /* Write byte to command latch, CLE, of NAND */
285 /***************/\r
286 void command(unsigned int cmd)
288   *((unsigned char *)(memBase + cmdOffset)) = cmd;
292 /***************/\r
293 /* Write byte to address latch, ALE, of NAND */
294 /***************/\r
295 void address(unsigned char addr)
297   *((unsigned char *)(memBase + addrOffset)) = addr;
301 /***************/\r
302 /* Read a byte from the data latch of the NAND */
303 /***************/\r
304 unsigned char readData8Bit (void)
306   unsigned char c;
308   c = *((unsigned char *)(memBase + dataOffset));
310   return (c);
312 \r
314 /***************/\r
315 /* Write a byte of data to the data latch of the NAND */
316 /***************/\r
317 void writeData8Bit (unsigned char c)
319     *((unsigned char *)(memBase + dataOffset)) = c;
323 /***************/\r
324 /* Read the status register */
325 /***************/\r
326 void readStatusReg(void)
328   // Write command to read the status register, delay\r
329   command (readStatusRegCmd);
330   smallDelay ();
332   // Read the status data, delay\r
333   statusReg = readData8Bit();
334   smallDelay ();
335 \r
336   if (statusReg & 0x01)\r
337   {\r
338     for (;;)\r
339     {\r
340     }\r
341   }\r
342 \r
343   // Reset the device
344   command (resetCmd);
345   bigDelay ();
347 \r
349 /***************/\r
350 /* Read the spare bytes for the specified block/page/segment */
351 /***************/\r
352 void readSpareBytes(unsigned int block, unsigned int page, unsigned char *iscratch, int segment)
354   unsigned int  columnAddr;
355   unsigned int  rowAddr;
356   unsigned char addr[5];
357   int i;
359   unsigned char *scratch = (unsigned char *)iscratch;
362   // Reset NAND device and delay
363   command (resetCmd);\r
364   bigDelay();
365 \r
366   // Calculate the column and row addresses for the desired spared bytes\r
367   columnAddr = pageSizeBytes + (segment * spareBytesPerSegment);\r
368   rowAddr = (block << 6) + page;\r
369   if (busWidth == 16)\r
370   {\r
371     for (;;)\r
372     {\r
373     }\r
374   }
375 \r
376   addr[0] = columnAddr & 0xFF;\r
377   addr[1] = (columnAddr >> 8) & 0xFF;\r
378   addr[2] = rowAddr & 0xFF;\r
379   addr[3] = (rowAddr >> 8) & 0xFF;\r
380   addr[4] = (rowAddr >> 16) & 0xFF;\r
381 \r
382   // Send the read command to the device\r
383   command(readPageCmd);
384   smallDelay();
385 \r
386   // Send the address bytes to the device
387   address(addr[0]);
388   smallDelay();
390   address(addr[1]);
391   smallDelay();
393   address(addr[2]);
394   smallDelay();
396   address(addr[3]);
397   smallDelay();
399   address(addr[4]);
400   smallDelay();
401 \r
402   // Send the end of the read command to the device\r
403   command(readPageDoneCmd);
404   bigDelay();
406   if (busWidth == 8)\r
407   {
408     for (i = 0; i < spareBytesPerSegment; i++)\r
409     {
410       scratch[i] = readData8Bit();
411       smallDelay ();
412     }
413   }\r
414   else\r
415   {\r
416     for (;;)\r
417     {\r
418     }\r
419   }\r
423 /***************/\r
424 /* Check erased block to see if it is good or bad. */
425 /***************/\r
426 int blockIsBad(unsigned int n)
428   int i;
429   unsigned char *cscratch = (unsigned char *)scratch;
431   /* read spare bytes: block n, page 0, segment 0 */
432   readSpareBytes(n, 0, scratch, 0);
433 \r
434   if (busWidth == 8)\r
435   {
436     for (i = 0; i < 6; i++)\r
437     {\r
438       if (cscratch[i] != 0xff)\r
439       {\r
440         printf ("Block %d should have been erase, but it has bad block mark, page %d! (%02X02X02X02X02X02X)\n",\r
441                 n, 0, cscratch[0], cscratch[1], cscratch[2], cscratch[3], cscratch[4], cscratch[5]);
442         return (1);\r
443       }
444     }\r
445   }
446   else\r
447   {\r
448     for (;;)\r
449     {\r
450     }\r
451   }\r
453   /* read spare bytes: block n, page 0, segment 0 */
454   readSpareBytes(n, 1, scratch, 0);
456   if (busWidth == 8)\r
457   {
458     for (i = 0; i < 6; i++)\r
459     {\r
460       if (cscratch[i] != 0xff)\r
461       {\r
462         printf ("Block %d should have been erase, but it has bad block mark, page %d! (%02X02X02X02X02X02X)\n",\r
463                 n, 1, cscratch[0], cscratch[1], cscratch[2], cscratch[3], cscratch[4], cscratch[5]);
464         return (1);\r
465       }\r
466     }
467   }
468   else\r
469   {\r
470     for (;;)\r
471     {\r
472     }\r
473   }\r
475   /* read spare bytes: block n, page 0, segment 0 */
476   readSpareBytes(n, pagesPerBlock - 1, scratch, 0);
478   if (busWidth == 8)\r
479   {
480     for (i = 0; i < 6; i++)\r
481     {\r
482       if (cscratch[i] != 0xff)\r
483       {\r
484         printf ("Block %d should have been erase, but it has bad block mark, page %d! (%02X02X02X02X02X02X)\n",\r
485                 n, (pagesPerBlock - 1), cscratch[0], cscratch[1], cscratch[2], cscratch[3], cscratch[4], cscratch[5]);
486         return (1);\r
487       }
488     }\r
489   }
490   else\r
491   {\r
492     for (;;)\r
493     {\r
494     }\r
495   }\r
497   // No bad block marks found, return false.\r
498   return (0);
500 \r
502 /***************/\r
503 /* Check a block for the manufacturer bad block mark. */
504 /* Must use this before erasing a block!              */
505 /***************/\r
506 int blockIsBadManufacture(unsigned int n)
508   int i;
509   int j;
510   unsigned char *cscratch = (unsigned char *)scratch;
512   // "manufactureBadBlockPages" tells us which pages of the block to check
513   for (j = 0; j < sizeof(manufactureBadBlockPages) / sizeof(unsigned int); j++)\r
514   {
515     /* read spare bytes: block n, page defined above, segment 0 */
516     readSpareBytes(n, manufactureBadBlockPages[j], scratch, 0);
518     if (busWidth == 8)\r
519     {
520       for (i = 0; i < sizeof(manufactureBadBlockBytes) / sizeof (unsigned int); i++)\r
521       {
522         if (cscratch[manufactureBadBlockBytes[i]] != 0xff)\r
523         {\r
524           printf ("Block %d should have been erase, but it has bad block mark, page %d! (%02X02X02X02X02X02X)\n",\r
525                   n, manufactureBadBlockPages[j], cscratch[0], cscratch[1], cscratch[2], cscratch[3], cscratch[4], cscratch[5]);
526           return (1);\r
527         }
528       }
529     }
530     else\r
531     {\r
532       for (;;)\r
533       {\r
534       }\r
535     }\r
536   }
538   return (0);
540 \r
542 /***************/\r
543 /* Erase block n  */
544 /***************/\r
545 void eraseBlock(int n)
546 {\r
547   unsigned int  rowAddr;
548   unsigned char addr[3];
549 \r
550 \r
551   // Calculate the row address\r
552   rowAddr = n << 6;\r
553 \r
554   addr[0] = rowAddr & 0xFF;\r
555   addr[1] = (rowAddr >> 8) & 0xFF;\r
556   addr[2] = (rowAddr >> 16) & 0xFF;\r
558   // Send the command and address bytes (with delay) to the device\r
559   command (resetCmd);
560   bigDelay();
562   command (blockEraseACmd);
563   smallDelay ();
564 \r
565   address (addr[0]);
566   smallDelay();
567 \r
568   address (addr[1]);
569   smallDelay();
570 \r
571   address (addr[2]);
572   smallDelay();
574   command (blockEraseBCmd);
575   bigDelay ();
576   bigDelay ();
578   readStatusReg();\r
579   printf ("Erased block %d, status = 0x%02X\n", n, statusReg);
583 /***************/\r
584 /* Read and correct (ECC) a 512-byte segment.  */
585 /***************/\r
586 void readDeviceId(void)
588   unsigned char deviceId[5];\r
589   unsigned char onfiId[4];\r
590   unsigned char *p8;
591   unsigned char idAddr;\r
592   int           tempIndex;\r
593 \r
595   // p8 points to storage for device ID bytes
596   p8 = (unsigned char *)deviceId;
597 \r
598   /* Reset the device, delay. */
599   command (resetCmd);
600   bigDelay();
602   /* Send 'read ID' command to device, delay */
603   command (readIdCmd);
604   smallDelay();
605 \r
606   // Send the address bytes to the device (0x00 is regular ID)
607   idAddr = 0x00;\r
608   address(idAddr);
609   smallDelay();
611   bigDelay();
612 \r
613   // Read the 5 bytes of the regular ID\r
614   for (tempIndex = 0; tempIndex < 5; tempIndex++)\r
615   {\r
616     p8[tempIndex] = readData8Bit();\r
617     smallDelay();
618   }\r
619 \r
620   printf ("\nDevice ID for MT29F2G08ABDHC is: 0x2CAA901506\n\n");
621 \r
622   printf ("ID read from device:\n");
623   printf ("Device ID[0]: 0x%02X\n", deviceId[0]);
624   printf ("Device ID[1]: 0x%02X\n", deviceId[1]);
625   printf ("Device ID[2]: 0x%02X\n", deviceId[2]);
626   printf ("Device ID[3]: 0x%02X\n", deviceId[3]);
627   printf ("Device ID[4]: 0x%02X\n\n", deviceId[4]);
628 \r
629   // p8 points to storage for onfi ID bytes
630   p8 = (unsigned char *)onfiId;
631 \r
632   /* Reset the device, delay. */
633   command (resetCmd);
634   bigDelay();
636   /* Send 'read ID' command to device, delay */
637   command (readIdCmd);
638   smallDelay();
639 \r
640   // Send the address bytes to the device (0x20 is onfi ID)
641   idAddr = 0x20;\r
642   address(idAddr);
643   smallDelay();
645   bigDelay();
646 \r
647   // Read the 4 bytes of the regular ID\r
648   for (tempIndex = 0; tempIndex < 4; tempIndex++)\r
649   {\r
650     p8[tempIndex] = readData8Bit();
651     smallDelay();
652   }\r
653 \r
654   printf ("onfi ID[0]: %c (should be \"O\")\n", onfiId[0]);
655   printf ("onfi ID[1]: %c (should be \"N\")\n", onfiId[1]);
656   printf ("onfi ID[2]: %c (should be \"F\")\n", onfiId[2]);
657   printf ("onfi ID[3]: %c (should be \"I\")\n\n", onfiId[3]);
658 }\r
661 /***************/\r
662 /* Read and correct (ECC) a 512-byte segment.  */
663 /***************/\r
664 void readAndCorrectSegment(unsigned int firstBlock, int blockCount, unsigned int pageCount, int segmentCount, unsigned int memOffset)
666   unsigned int  columnAddr;
667   unsigned int  rowAddr;
668   unsigned char addr[5];
669   unsigned char *p8;
670   unsigned char *pecc;
671   unsigned int  ecc10[8];
672   unsigned int  eccReg[4];
673   unsigned char a;
674   unsigned char b;
675   int           tempIndex;\r
676   int           tempReturn;\r
677   int           numErrors;\r
678 \r
680   /* Read the spare area for this page */
681   readSpareBytes(firstBlock + blockCount, pageCount, scratch, segmentCount);
683   // p8 points to storage are for bytes to be read from NAND
684   p8 = (unsigned char *) (((unsigned int)readData) + memOffset);
685 \r
686   // Calculate the column and row addresses for of what data should be read from the NAND\r
687   columnAddr = segmentCount * 512;\r
688   rowAddr = ((firstBlock + blockCount) << 6) + pageCount;\r
689   if (busWidth == 16)\r
690   {\r
691     for (;;)\r
692     {\r
693     }\r
694   }
695 \r
696   addr[0] = columnAddr & 0xFF;\r
697   addr[1] = (columnAddr >> 8) & 0xFF;\r
698   addr[2] = rowAddr & 0xFF;\r
699   addr[3] = (rowAddr >> 8) & 0xFF;\r
700   addr[4] = (rowAddr >> 16) & 0xFF;\r
702   /* Reset the device, delay. */
703   command (resetCmd);
704   bigDelay();
706   /* Send 'read' command to device, delay */
707   command (readPageCmd);
708   smallDelay();
709 \r
710   // Send the address bytes to the device
711   address(addr[0]);
712   smallDelay();
714   address(addr[1]);
715   smallDelay();
717   address(addr[2]);
718   smallDelay();
720   address(addr[3]);
721   smallDelay();
723   address(addr[4]);
724   smallDelay();
725 \r
726   // Send the end of the read command to the device\r
727   command(readPageDoneCmd);
729   bigDelay();
731   /* Clear the ECC to start fresh */
732   stopEcc();
734   smallDelay();
736   /* Enable the 4 bit ECC through the nand flash control register */
737   eccEnable(csRegion);
739   if (busWidth == 8)\r
740   {
741     /* Read the 512-byte data segment from the device */
742     for (tempIndex = 0; tempIndex < 512; tempIndex++)\r
743     {\r
744       p8[tempIndex] = readData8Bit();
745     }\r
746   }\r
747   else\r
748   {
749     for (;;);
750   }
751 \r
752   /* Halt ECC hardware so we can read it. */
753   stopEcc ();
754 \r
755   //Read Status Register\r
756   readStatusReg();\r
758   /* Convert the ECC bytes from 10-bit format to 8-bit values. The 1st 6 bytes are not used for ECC. */
759   pecc = (unsigned char *) (((unsigned int)scratch) + 6);
761   /* Convert the 80 bits of ecc into eight 10 bit values. The byte order here is little endian */
762   a =  pecc[0] ;
763   b =  READ_BITFIELD(pecc[1], 1, 0);
764   ecc10[0] = a | (b << 8);
766   a  =  READ_BITFIELD(pecc[1], 7, 2);
767   a |= (READ_BITFIELD(pecc[2], 1, 0)) << 6;
768   b  =  READ_BITFIELD(pecc[2], 3, 2);
769   ecc10[1] = a | (b << 8);
770 \r
771   a  =  READ_BITFIELD(pecc[2], 7, 4);
772   a |= (READ_BITFIELD(pecc[3], 3, 0)) << 4;
773   b  =  READ_BITFIELD(pecc[3], 5, 4);
774   ecc10[2] = a | (b << 8);
776   a  =  READ_BITFIELD(pecc[3], 7, 6);
777   a |= (READ_BITFIELD(pecc[4], 5, 0)) << 2;
778   b  =  READ_BITFIELD(pecc[4], 7, 6);
779   ecc10[3] = a | (b << 8);
781   a = pecc[5];
782   b = READ_BITFIELD(pecc[6], 1, 0);
783   ecc10[4] = a | (b << 8);
785   a   =  READ_BITFIELD(pecc[6], 7, 2);
786   a  |= (READ_BITFIELD(pecc[7], 1, 0)) << 6;
787   b   =  READ_BITFIELD(pecc[7], 3, 2);
788   ecc10[5] = a | (b << 8);
790   a  =  READ_BITFIELD(pecc[7], 7, 4);
791   a |= (READ_BITFIELD(pecc[8], 3, 0)) << 4;
792   b  =  READ_BITFIELD(pecc[8], 5, 4);
793   ecc10[6] = a | (b << 8);
795   a  =  READ_BITFIELD(pecc[8], 7, 6);
796   a |= (READ_BITFIELD(pecc[9], 5, 0)) << 2;
797   b  =  READ_BITFIELD(pecc[9], 7, 6);
798   ecc10[7] = a | (b << 8);
800   /* Disable any left over error correction */
801   correctDisable ();
803   for (tempIndex = 7; tempIndex >= 0; tempIndex--)\r
804   {\r
805     eccCorrectLoad(ecc10[tempIndex]);
806   }\r
808   eccWaitCalc();
810   readEccReg(eccReg);
812   /* 0 values indicates there are no bit errors */
813   if ((eccReg[0] == 0) && (eccReg[1] == 0) && (eccReg[2] == 0) && (eccReg[3] == 0))\r
814   {\r
815     return;\r
816   }
818   /* If there are bit errors perform the data correction */
819   tempReturn = errAddressRun();
820 \r
821   if (tempReturn == -1)\r
822   {
823     printf ("There are errors in block %d page %d segment %d that cannot be corrected\n",
824             firstBlock + blockCount, pageCount, segmentCount);
825     return;
826   }
828   if (tempReturn == 0)\r
829   {\r
830     return;   /* Errors are not present in the data bits */
831   }
833   /* Correct the errors */
834   numErrors = errNumErrors();
836   for (tempIndex = numErrors; tempIndex >= 1; tempIndex--)\r
837   {
838     if (busWidth == 8)\r
839     {
840       correct8BitData (p8, tempIndex);\r
841     }
842   }
846 /***************/\r
847 /* Program a 512-byte segment. */
848 /***************/\r
849 void programSegment(unsigned int firstBlock, int blockIdx, unsigned int page, int segmentCount, unsigned int memOffset, unsigned int eccOffset)
851   unsigned int  columnAddr;
852   unsigned int  rowAddr;
853   unsigned char addr[5];
854   unsigned char *p8;
855   unsigned int  eccReg[4];
856   unsigned int  ecc8[10];
857   unsigned char a;
858   unsigned char b;
859   int           tempIndex;\r
860 \r
861 \r
862   // p8 points to group of bytes to be written to NAND
863   p8 = (unsigned char *) (((unsigned int)writeData) + memOffset);
864 \r
865   // Calculate the column and row addresses for where the data should be written on the NAND\r
866   columnAddr = segmentCount * 512;\r
867   rowAddr = ((firstBlock + blockIdx) << 6) + page;\r
868   if (busWidth == 16)\r
869   {\r
870     for (;;)\r
871     {\r
872     }\r
873   }
874 \r
875   addr[0] = columnAddr & 0xFF;\r
876   addr[1] = (columnAddr >> 8) & 0xFF;\r
877   addr[2] = rowAddr & 0xFF;\r
878   addr[3] = (rowAddr >> 8) & 0xFF;\r
879   addr[4] = (rowAddr >> 16) & 0xFF;\r
881   /* Reset the device and delay */
882   command(resetCmd);
883   bigDelay();
885   /* Send 'write' command to device, delay. */
886   command(programACmd);
887   smallDelay();
888 \r
889   // Send the address bytes to the device
890   address(addr[0]);
891   smallDelay();
893   address(addr[1]);
894   smallDelay();
896   address(addr[2]);
897   smallDelay();
899   address(addr[3]);
900   smallDelay();
902   address(addr[4]);
903   smallDelay();
905   bigDelay();
907   /* Clear the ECC to start fresh */
908   stopEcc();
910   smallDelay();
912   /* Enable the 4 bit ECC through the nand flash control register */
913   eccEnable(csRegion);
915   if (busWidth == 8)\r
916   {
917     /* Write the 512-byte data segment to the device */
918     for (tempIndex = 0; tempIndex < 512; tempIndex++)\r
919     {\r
920       writeData8Bit (p8[tempIndex]);\r
921     }
922   }\r
923   else\r
924   {
925     for (;;);
926   }
927 \r
928   /* Halt ECC hardware so we can read it. */
929   //  stopEcc ();
931   /* Read the compuated ECC values and convert them to 10 bytes */
932   readEccReg(eccReg);
933 \r
934   /* Send the end of  write command to the device */
935   command(programBCmd);
936   bigDelay();
937   readStatusReg();
938   //printf ("Wrote block %d, segment %d, status = 0x%02X\n", blockIdx, segmentCount, statusReg);
940   ecc8[0] = READ_BITFIELD(eccReg[0], 7, 0);
942   a = READ_BITFIELD(eccReg[0],  9,  8);
943   b = READ_BITFIELD(eccReg[0], 21, 16);
944   ecc8[1] = a | (b << 2);
946   a = READ_BITFIELD(eccReg[0], 25, 22);
947   b = READ_BITFIELD(eccReg[1],  3,  0);
948   ecc8[2] = a | (b << 4);
950   a = READ_BITFIELD(eccReg[1],  9,  4);
951   b = READ_BITFIELD(eccReg[1], 17, 16);
952   ecc8[3] = a | (b << 6);
954   ecc8[4] = READ_BITFIELD(eccReg[1], 25, 18);
956   ecc8[5] = READ_BITFIELD(eccReg[2], 7, 0);
958   a = READ_BITFIELD(eccReg[2],  9,  8);
959   b = READ_BITFIELD(eccReg[2], 21, 16);
960   ecc8[6] = a | (b << 2);
962   a = READ_BITFIELD(eccReg[2], 25, 22);
963   b = READ_BITFIELD(eccReg[3],  3,  0);
964   ecc8[7] = a | (b << 4);
966   a = READ_BITFIELD(eccReg[3],  9,  4);
967   b = READ_BITFIELD(eccReg[3], 17, 16);
968   ecc8[8] = a | (b << 6);
970   ecc8[9] = READ_BITFIELD(eccReg[3], 25, 18);
971 \r
972   // Generate the spare bytes for this segment\r
973   // 6 bytes of 0xff (no bad block marks) followed by ECC data\r
974   for (tempIndex = 0; tempIndex < 6; tempIndex++)\r
975   {\r
976     spareData[eccOffset + tempIndex] = 0xFF;\r
977   }\r
978   for (tempIndex = 6; tempIndex < 16; tempIndex++)\r
979   {\r
980     spareData[eccOffset + tempIndex] = ecc8[tempIndex - 6];\r
981   }\r
982 \r
983   // Re-calculate the column addresses for writing these spare bytes\r
984   // (row address is the same since the block and page are the same)s\r
985   columnAddr = pageSizeBytes + (segmentCount * spareBytesPerSegment);\r
986   if (busWidth == 16)\r
987   {\r
988     for (;;)\r
989     {\r
990     }\r
991   }
992 \r
993   addr[0] = columnAddr & 0xFF;\r
994   addr[1] = (columnAddr >> 8) & 0xFF;\r
995 \r
996   /* Reset the device and delay */
997   command (resetCmd);
998   bigDelay();
1000   /* Send 'write' command to device, delay. */
1001   command (programACmd);
1002   smallDelay();
1003 \r
1004   // Send the address bytes to the device
1005   address(addr[0]);
1006   smallDelay();
1008   address(addr[1]);
1009   smallDelay();
1011   address(addr[2]);
1012   smallDelay();
1014   address(addr[3]);
1015   smallDelay();
1017   address(addr[4]);
1018   smallDelay();
1020   bigDelay();
1022   if (busWidth == 8)\r
1023   {
1024     /* Write the spare bytes for this 512-byte data segment to the device */
1025     for (tempIndex = 0; tempIndex < 16; tempIndex++)\r
1026     {\r
1027       writeData8Bit(spareData[eccOffset + tempIndex]);\r
1028     }
1029   }\r
1030   else\r
1031   {
1032     for (;;);
1033   }
1034 \r
1035   /* Send the end of  write command to the device */
1036   command (programBCmd);
1037   bigDelay ();
1038   readStatusReg ();
1039   //printf ("Wrote spare bytes for block %d, segment %d, status = 0x%02X\n", blockIdx, segmentCount, statusReg);
1041 \r
1042 /***************/\r
1043 /* main  */\r
1044 /***************/\r
1045 int main ()\r
1046 {\r
1047 \r
1048   unsigned int nblocks;          /* Number of blocks that will be programmed */\r
1049   unsigned int bytesPerBlock;\r
1050   unsigned int memOffset = 0;\r
1051   unsigned int eccOffset = 0;\r
1052   unsigned int dataSizeUint8;\r
1053 \r
1054   int wordCount;\r
1055   int blockCount;\r
1056   int errorCount;\r
1057   int pageCount;\r
1058   int tempIndex;\r
1059   int memOffset_Offset;\r
1060   int segmentCount;\r
1061 \r
1062   printf ("Appleton EVM NAND writer for Micron MT29F2G08xxx devices.\n\n");\r
1063 \r
1064 \r
1065   if (dataSizeUint32 == 0x00)\r
1066   {\r
1067     printf ("Variable \'dataSizeUint32\' is zero.\n");\r
1068     printf ("It must be set the the number of words in image!\n");\r
1069     printf ("Execution will stall until the variable is updated.\n");\r
1070 \r
1071     while (dataSizeUint32 == 0x00)\r
1072     {\r
1073       // Wait until user tells us how much data to program\r
1074     }\r
1075   }\r
1076 \r
1077   dataSizeUint8 = dataSizeUint32 * 4;\r
1078 \r
1079   // Calculate the number of spare bytes per page based on number of spare per segment and number of segments\r
1080   spareBytesPerPage = spareBytesPerSegment * (pageSizeBytes / 512);\r
1081 \r
1082   // Calculate the number of bytes per block based on NAND geometry\r
1083   bytesPerBlock = pageSizeBytes * pagesPerBlock;\r
1084 \r
1085   // Calculate the number of blocks to program based on size of image to write to NAND\r
1086   nblocks = (dataSizeUint8 + bytesPerBlock - 1) / bytesPerBlock;\r
1087 \r
1088   // Calculate the base address of the device in EMIF\r
1089   memBase  = 0x70000000 + (csRegion * 0x04000000);\r
1090 \r
1091   /* Configure the nand flash control register */\r
1092   nandEnableRegion(csRegion);\r
1093 \r
1094   // Read and display the device ID information\r
1095   readDeviceId();\r
1096 \r
1097   if (doWrite != 0)\r
1098   {\r
1099     printf ("Erasing %d blocks starting at block %d\n", nblocks, firstBlock);\r
1100 \r
1101     /* Strange for loop here, i is the check, j is incremented */\r
1102     for (blockCount = 0; blockCount < nblocks; blockCount++)\r
1103     {\r
1104       if (blockIsBadManufacture (firstBlock + blockCount) != 0)\r
1105       {\r
1106         printf ("Block %d has been marked bad. Skipping the block (not erased)\n", firstBlock+blockCount);\r
1107         continue;\r
1108       }\r
1109 \r
1110       eraseBlock (firstBlock + blockCount);\r
1111       printf ("Block %d erased.\n", firstBlock + blockCount);\r
1112     }\r
1113 \r
1114     printf ("Programming %d blocks starting at block %d\n", nblocks, firstBlock);\r
1115 \r
1116     for (blockCount = 0; blockCount < nblocks; blockCount++)\r
1117     {\r
1118       printf ("Attempting to program block %d\n", firstBlock + blockCount);\r
1119 \r
1120       if (blockIsBad(firstBlock + blockCount) != 0)\r
1121       {\r
1122         printf ("Block %d has been marked bad. Skipping the block\n");\r
1123         continue;\r
1124       }\r
1125 \r
1126       for (pageCount = 0; pageCount < pagesPerBlock; pageCount++)\r
1127       {\r
1128         // File the spare area for this page with 0x55 pattern\r
1129         for (tempIndex = 0; tempIndex < spareBytesPerPage; tempIndex++)\r
1130         {\r
1131          spareData[eccOffset + tempIndex] = 0x55;\r
1132         }\r
1133 \r
1134         //programPage(firstBlock, j, k, memOffset, eccOffset);\r
1135 \r
1136         // Program the page, one 512-byte segment at a time\r
1137         for (memOffset_Offset = segmentCount = 0; memOffset_Offset < pageSizeBytes; memOffset_Offset += 512, segmentCount++)\r
1138         {\r
1139           programSegment(firstBlock, blockCount, pageCount, segmentCount, (memOffset + memOffset_Offset), eccOffset);\r
1140           eccOffset += spareBytesPerSegment;\r
1141         }\r
1142 \r
1143         memOffset += pageSizeBytes;\r
1144         if (memOffset >= dataSizeUint8)\r
1145         {\r
1146           break;\r
1147         }\r
1148       }\r
1149     }\r
1150   }\r
1151 \r
1152   /* Read back the data just written. */\r
1153   memOffset = 0;\r
1154 \r
1155   for (blockCount = 0; blockCount < nblocks; blockCount++)\r
1156   {\r
1157     printf ("Attempting to read block %d\n", firstBlock + blockCount);\r
1158 \r
1159     if (blockIsBad(firstBlock + blockCount) != 0)\r
1160     {\r
1161       printf ("Block %d has been marked bad. Skipping the block\n");\r
1162       continue;\r
1163     }\r
1164 \r
1165     for (pageCount = 0; pageCount < pagesPerBlock; pageCount++)\r
1166     {\r
1167       //readPage(firstBlock, blockCount, pageCount, memOffset);\r
1168 \r
1169       // Read the page, one 512-byte segment at a time\r
1170       for (memOffset_Offset = segmentCount = 0; memOffset_Offset < pageSizeBytes; memOffset_Offset += 512, segmentCount++)\r
1171       {\r
1172         readAndCorrectSegment(firstBlock, blockCount, pageCount, segmentCount, (memOffset + memOffset_Offset));\r
1173       }\r
1174 \r
1175       memOffset += pageSizeBytes;\r
1176       if (memOffset >= dataSizeUint8)\r
1177       {\r
1178         break;\r
1179       }\r
1180     }\r
1181   }\r
1182 \r
1183   /* Compare the read and write data. */\r
1184   for (wordCount = errorCount = 0; wordCount < dataSizeUint32; wordCount++)\r
1185   {\r
1186     if (writeData[wordCount] != readData[wordCount])\r
1187     {\r
1188       printf ("Data comparison failure at offset %d (0x%08x). Wrote 0x%08x, read 0x%08x\n", wordCount, wordCount, writeData[wordCount], readData[wordCount]);\r
1189 \r
1190       if (++errorCount >= 10)\r
1191       {\r
1192         printf ("Too many comparison errors, quiting\n");\r
1193         break;\r
1194       }\r
1195     }\r
1196 \r
1197   }\r
1198 \r
1199   if (errorCount == 0)\r
1200   {\r
1201     printf ("Data compare complete, no errors\n");\r
1202   }\r
1203 }\r
1204 \r