]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/mousse/flash.c
nand: remove CONFIG_SYS_NAND_PAGE_SIZE
[karo-tx-uboot.git] / board / mousse / flash.c
1 /*
2  * MOUSSE/MPC8240 Board definitions.
3  * Flash Routines for MOUSSE onboard AMD29LV106DB devices
4  *
5  * (C) Copyright 2000
6  * Marius Groeger <mgroeger@sysgo.de>
7  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
8  *
9  * (C) Copyright 2000
10  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
11  *
12  * (C) Copyright 1999, by Curt McDowell, 08-06-99, Broadcom Corp.
13  * (C) Copyright 2001, James Dougherty, 07/18/01, Broadcom Corp.
14  *
15  * SPDX-License-Identifier:     GPL-2.0+
16  */
17
18 #include <common.h>
19 #include <mpc8xx.h>
20 #include <malloc.h>
21 #include "mousse.h"
22 #include "flash.h"
23
24 int flashLibDebug = 0;
25 int flashLibInited = 0;
26
27 #define OK  0
28 #define ERROR -1
29 #define STATUS int
30 #define PRINTF                  if (flashLibDebug) printf
31 #if 0
32 #define PRIVATE                 static
33 #else
34 #define PRIVATE
35 #endif
36
37 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
38
39 #define SLEEP_DELAY    166
40 #define FLASH_SECTOR_SIZE   (64*1024)
41 /***********************************************************************
42  *
43  * Virtual Flash Devices on Mousse board
44  *
45  * These must be kept in sync with the definitions in flashLib.h.
46  *
47  ***********************************************************************/
48
49 PRIVATE flash_dev_t flashDev[] = {
50     /* Bank 0 sector SA0 (16 kB) */
51     {   "SA0",FLASH0_BANK, FLASH0_SEG0_START, 1, 14,
52         FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
53     },
54     /* Bank 0 sector SA1 (8 kB) */
55     {   "SA1", FLASH0_BANK, FLASH0_SEG0_START + 0x4000, 1, 13,
56         FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
57     },
58     /* Bank 0 sector SA2 (8 kB) */
59     {   "SA2", FLASH0_BANK, FLASH0_SEG0_START + 0x6000, 1, 13,
60         FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
61     },
62     /* Bank 0 sector SA3 is occluded by Mousse I/O devices */
63     /* Bank 0 sectors SA4-SA18, after Mousse devices up to PLCC (960 kB)  */
64     {   "KERNEL", FLASH0_BANK, FLASH0_SEG1_START, 15, 16,
65         FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
66     },
67     /* Bank 0 sectors SA19-SA26, jumper can occlude this by PLCC (512 kB) */
68     /* This is where the Kahlua boot vector and boot ROM code resides. */
69     {   "BOOT",FLASH0_BANK, FLASH0_SEG2_START, 8, 16,
70         FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
71     },
72     /* Bank 0 sectors SA27-SA34 (512 kB) */
73     {   "RAMDISK",FLASH0_BANK, FLASH0_SEG3_START, 8, 16,
74         FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
75     },
76 };
77
78 int flashDevCount = (sizeof (flashDev) / sizeof (flashDev[0]));
79
80 #define DEV(no)                 (&flashDev[no])
81 #define DEV_NO(dev)             ((dev) - flashDev)
82
83 /***********************************************************************
84  *
85  * Private Flash Routines
86  *
87  ***********************************************************************/
88
89 /*
90  * The convention is:
91  *
92  * "addr" is always the PROM raw address, which is the address of an
93  * 8-bit quantity for flash 0 and 16-bit quantity for flash 1.
94  *
95  * "pos" is always a logical byte position from the PROM beginning.
96  */
97
98 #define FLASH0_ADDR(dev, addr) \
99         ((unsigned char *) ((dev)->base + (addr)))
100
101 #define FLASH0_WRITE(dev, addr, value) \
102         (*FLASH0_ADDR(dev, addr) = (value))
103
104 #define FLASH0_READ(dev, addr) \
105         (*FLASH0_ADDR(dev, addr))
106
107 PRIVATE int flashCheck (flash_dev_t * dev)
108 {
109         if (!flashLibInited) {
110                 printf ("flashCheck: flashLib not initialized\n");
111                 return ERROR;
112         }
113
114         if (dev < &flashDev[0] || dev >= &flashDev[flashDevCount]) {
115                 printf ("flashCheck: Bad dev parameter\n");
116                 return ERROR;
117         }
118
119         if (!dev->found) {
120                 printf ("flashCheck: Device %d not available\n", DEV_NO (dev));
121                 return ERROR;
122         }
123
124         return OK;
125 }
126
127 PRIVATE void flashReset (flash_dev_t * dev)
128 {
129         PRINTF ("flashReset: dev=%d\n", DEV_NO (dev));
130
131         if (dev->bank == FLASH0_BANK) {
132                 FLASH0_WRITE (dev, 0x555, 0xaa);
133                 FLASH0_WRITE (dev, 0xaaa, 0x55);
134                 FLASH0_WRITE (dev, 0x555, 0xf0);
135         }
136
137         udelay (SLEEP_DELAY);
138
139         PRINTF ("flashReset: done\n");
140 }
141
142 PRIVATE int flashProbe (flash_dev_t * dev)
143 {
144         int rv, deviceID, vendorID;
145
146         PRINTF ("flashProbe: dev=%d\n", DEV_NO (dev));
147
148         if (dev->bank != FLASH0_BANK) {
149                 rv = ERROR;
150                 goto DONE;
151         }
152
153         FLASH0_WRITE (dev, 0xaaa, 0xaa);
154         FLASH0_WRITE (dev, 0x555, 0x55);
155         FLASH0_WRITE (dev, 0xaaa, 0x90);
156
157         udelay (SLEEP_DELAY);
158
159         vendorID = FLASH0_READ (dev, 0);
160         deviceID = FLASH0_READ (dev, 2);
161
162         FLASH0_WRITE (dev, 0, 0xf0);
163
164         PRINTF ("flashProbe: vendor=0x%x device=0x%x\n", vendorID, deviceID);
165
166         if (vendorID == dev->vendorID && deviceID == dev->deviceID)
167                 rv = OK;
168         else
169                 rv = ERROR;
170
171   DONE:
172         PRINTF ("flashProbe: rv=%d\n", rv);
173
174         return rv;
175 }
176
177 PRIVATE int flashWait (flash_dev_t * dev, int addr, int expect, int erase)
178 {
179         int rv = ERROR;
180         int i, data;
181         int polls;
182
183 #if 0
184         PRINTF ("flashWait: dev=%d addr=0x%x expect=0x%x erase=%d\n",
185                 DEV_NO (dev), addr, expect, erase);
186 #endif
187
188         if (dev->bank != FLASH0_BANK) {
189                 rv = ERROR;
190                 goto done;
191         }
192
193         if (erase)
194                 polls = FLASH_ERASE_SECTOR_TIMEOUT;     /* Ticks */
195         else
196                 polls = FLASH_PROGRAM_POLLS;    /* Loops */
197
198         for (i = 0; i < polls; i++) {
199                 if (erase)
200                         udelay (SLEEP_DELAY);
201
202                 data = FLASH0_READ (dev, addr);
203
204                 if (((data ^ expect) & 0x80) == 0) {
205                         rv = OK;
206                         goto done;
207                 }
208
209                 if (data & 0x20) {
210                         /*
211                          * If the 0x20 bit has come on, it could actually be because
212                          * the operation succeeded, so check the done bit again.
213                          */
214
215                         data = FLASH0_READ (dev, addr);
216
217                         if (((data ^ expect) & 0x80) == 0) {
218                                 rv = OK;
219                                 goto done;
220                         }
221
222                         printf ("flashWait: Program error (dev: %d, addr: 0x%x)\n",
223                                         DEV_NO (dev), addr);
224
225                         flashReset (dev);
226                         rv = ERROR;
227                         goto done;
228                 }
229         }
230
231         printf ("flashWait: Timeout %s (dev: %d, addr: 0x%x)\n",
232                 erase ? "erasing sector" : "programming byte",
233                 DEV_NO (dev), addr);
234
235   done:
236
237 #if 0
238         PRINTF ("flashWait: rv=%d\n", rv);
239 #endif
240
241         return rv;
242 }
243
244 /***********************************************************************
245  *
246  * Public Flash Routines
247  *
248  ***********************************************************************/
249
250 STATUS flashLibInit (void)
251 {
252         int i;
253
254         PRINTF ("flashLibInit: devices=%d\n", flashDevCount);
255
256         for (i = 0; i < flashDevCount; i++) {
257                 flash_dev_t *dev = &flashDev[i];
258
259                 /*
260                  * For bank 1, probe both without and with byte swappage,
261                  * so that this module works on both old and new Mousse boards.
262                  */
263
264                 flashReset (dev);
265
266                 if (flashProbe (dev) != ERROR)
267                         dev->found = 1;
268
269                 flashReset (dev);
270
271                 if (flashProbe (dev) != ERROR)
272                         dev->found = 1;
273
274                 dev->swap = 0;
275
276                 if (dev->found) {
277                         PRINTF ("\n  FLASH %s[%d]: iobase=0x%x - %d sectors %d KB",
278                                 flashDev[i].name, i, flashDev[i].base,
279                                 flashDev[i].sectors,
280                                 (flashDev[i].sectors * FLASH_SECTOR_SIZE) / 1024);
281
282                 }
283         }
284
285         flashLibInited = 1;
286
287         PRINTF ("flashLibInit: done\n");
288
289         return OK;
290 }
291
292 STATUS flashEraseSector (flash_dev_t * dev, int sector)
293 {
294         int pos, addr;
295
296         PRINTF ("flashErasesector: dev=%d sector=%d\n", DEV_NO (dev), sector);
297
298         if (flashCheck (dev) == ERROR)
299                 return ERROR;
300
301         if (sector < 0 || sector >= dev->sectors) {
302                 printf ("flashEraseSector: Sector out of range (dev: %d, sector: %d)\n", DEV_NO (dev), sector);
303                 return ERROR;
304         }
305
306         pos = FLASH_SECTOR_POS (dev, sector);
307
308         if (dev->bank != FLASH0_BANK) {
309                 return ERROR;
310         }
311
312         addr = pos;
313
314         FLASH0_WRITE (dev, 0xaaa, 0xaa);
315         FLASH0_WRITE (dev, 0x555, 0x55);
316         FLASH0_WRITE (dev, 0xaaa, 0x80);
317         FLASH0_WRITE (dev, 0xaaa, 0xaa);
318         FLASH0_WRITE (dev, 0x555, 0x55);
319         FLASH0_WRITE (dev, addr, 0x30);
320
321         return flashWait (dev, addr, 0xff, 1);
322 }
323
324 /*
325  * Note: it takes about as long to flash all sectors together with Chip
326  * Erase as it does to flash them one at a time (about 30 seconds for 2
327  * MB).  Also since we want to be able to treat subsets of sectors as if
328  * they were complete devices, we don't use Chip Erase.
329  */
330
331 STATUS flashErase (flash_dev_t * dev)
332 {
333         int sector;
334
335         PRINTF ("flashErase: dev=%d sectors=%d\n", DEV_NO (dev), dev->sectors);
336
337         if (flashCheck (dev) == ERROR)
338                 return ERROR;
339
340         for (sector = 0; sector < dev->sectors; sector++) {
341                 if (flashEraseSector (dev, sector) == ERROR)
342                         return ERROR;
343         }
344         return OK;
345 }
346
347 /*
348  * Read and write bytes
349  */
350
351 STATUS flashRead (flash_dev_t * dev, int pos, char *buf, int len)
352 {
353         int addr, words;
354
355         PRINTF ("flashRead: dev=%d pos=0x%x buf=0x%x len=0x%x\n",
356                 DEV_NO (dev), pos, (int) buf, len);
357
358         if (flashCheck (dev) == ERROR)
359                 return ERROR;
360
361         if (pos < 0 || len < 0 || pos + len > FLASH_MAX_POS (dev)) {
362                 printf ("flashRead: Position out of range "
363                         "(dev: %d, pos: 0x%x, len: 0x%x)\n",
364                         DEV_NO (dev), pos, len);
365                 return ERROR;
366         }
367
368         if (len == 0)
369                 return OK;
370
371         if (dev->bank == FLASH0_BANK) {
372                 addr = pos;
373                 words = len;
374
375                 PRINTF ("flashRead: memcpy(0x%x, 0x%x, 0x%x)\n",
376                         (int) buf, (int) FLASH0_ADDR (dev, pos), len);
377
378                 memcpy (buf, FLASH0_ADDR (dev, addr), words);
379
380         }
381         PRINTF ("flashRead: rv=OK\n");
382
383         return OK;
384 }
385
386 STATUS flashWrite (flash_dev_t * dev, int pos, char *buf, int len)
387 {
388         int addr, words;
389
390         PRINTF ("flashWrite: dev=%d pos=0x%x buf=0x%x len=0x%x\n",
391                 DEV_NO (dev), pos, (int) buf, len);
392
393         if (flashCheck (dev) == ERROR)
394                 return ERROR;
395
396         if (pos < 0 || len < 0 || pos + len > FLASH_MAX_POS (dev)) {
397                 printf ("flashWrite: Position out of range "
398                         "(dev: %d, pos: 0x%x, len: 0x%x)\n",
399                         DEV_NO (dev), pos, len);
400                 return ERROR;
401         }
402
403         if (len == 0)
404                 return OK;
405
406         if (dev->bank == FLASH0_BANK) {
407                 unsigned char tmp;
408
409                 addr = pos;
410                 words = len;
411
412                 while (words--) {
413                         tmp = *buf;
414                         if (~FLASH0_READ (dev, addr) & tmp) {
415                                 printf ("flashWrite: Attempt to program 0 to 1 "
416                                         "(dev: %d, addr: 0x%x, data: 0x%x)\n",
417                                         DEV_NO (dev), addr, tmp);
418                                 return ERROR;
419                         }
420                         FLASH0_WRITE (dev, 0xaaa, 0xaa);
421                         FLASH0_WRITE (dev, 0x555, 0x55);
422                         FLASH0_WRITE (dev, 0xaaa, 0xa0);
423                         FLASH0_WRITE (dev, addr, tmp);
424                         if (flashWait (dev, addr, tmp, 0) < 0)
425                                 return ERROR;
426                         buf++;
427                         addr++;
428                 }
429         }
430
431         PRINTF ("flashWrite: rv=OK\n");
432
433         return OK;
434 }
435
436 /*
437  * flashWritable returns true if a range contains all F's.
438  */
439
440 STATUS flashWritable (flash_dev_t * dev, int pos, int len)
441 {
442         int addr, words;
443         int rv = ERROR;
444
445         PRINTF ("flashWritable: dev=%d pos=0x%x len=0x%x\n",
446                         DEV_NO (dev), pos, len);
447
448         if (flashCheck (dev) == ERROR)
449                 goto done;
450
451         if (pos < 0 || len < 0 || pos + len > FLASH_MAX_POS (dev)) {
452                 printf ("flashWritable: Position out of range "
453                         "(dev: %d, pos: 0x%x, len: 0x%x)\n",
454                         DEV_NO (dev), pos, len);
455                 goto done;
456         }
457
458         if (len == 0) {
459                 rv = 1;
460                 goto done;
461         }
462
463         if (dev->bank == FLASH0_BANK) {
464                 addr = pos;
465                 words = len;
466
467                 while (words--) {
468                         if (FLASH0_READ (dev, addr) != 0xff) {
469                                 rv = 0;
470                                 goto done;
471                         }
472                         addr++;
473                 }
474         }
475
476         rv = 1;
477
478   done:
479         PRINTF ("flashWrite: rv=%d\n", rv);
480         return rv;
481 }
482
483
484 /*
485  * NOTE: the below code cannot run from FLASH!!!
486  */
487 /***********************************************************************
488  *
489  * Flash Diagnostics
490  *
491  ***********************************************************************/
492
493 STATUS flashDiag (flash_dev_t * dev)
494 {
495         unsigned int *buf = 0;
496         int i, len, sector;
497         int rv = ERROR;
498
499         if (flashCheck (dev) == ERROR)
500                 return ERROR;
501
502         printf ("flashDiag: Testing device %d, "
503                 "base: 0x%x, %d sectors @ %d kB = %d kB\n",
504                 DEV_NO (dev), dev->base,
505                 dev->sectors,
506                 1 << (dev->lgSectorSize - 10),
507                 dev->sectors << (dev->lgSectorSize - 10));
508
509         len = 1 << dev->lgSectorSize;
510
511         printf ("flashDiag: Erasing\n");
512
513         if (flashErase (dev) == ERROR) {
514                 printf ("flashDiag: Erase failed\n");
515                 goto done;
516         }
517         printf ("%d bytes requested ...\n", len);
518         buf = malloc (len);
519         printf ("allocated %d bytes ...\n", len);
520         if (buf == 0) {
521                 printf ("flashDiag: Out of memory\n");
522                 goto done;
523         }
524
525         /*
526          * Write unique counting pattern to each sector
527          */
528
529         for (sector = 0; sector < dev->sectors; sector++) {
530                 printf ("flashDiag: Write sector %d\n", sector);
531
532                 for (i = 0; i < len / 4; i++)
533                         buf[i] = sector << 24 | i;
534
535                 if (flashWrite (dev,
536                                 sector << dev->lgSectorSize,
537                                 (char *) buf, len) == ERROR) {
538                         printf ("flashDiag: Write failed (dev: %d, sector: %d)\n",
539                                 DEV_NO (dev), sector);
540                         goto done;
541                 }
542         }
543
544         /*
545          * Verify
546          */
547
548         for (sector = 0; sector < dev->sectors; sector++) {
549                 printf ("flashDiag: Verify sector %d\n", sector);
550
551                 if (flashRead (dev,
552                                    sector << dev->lgSectorSize,
553                                    (char *) buf, len) == ERROR) {
554                         printf ("flashDiag: Read failed (dev: %d, sector: %d)\n",
555                                 DEV_NO (dev), sector);
556                         goto done;
557                 }
558
559                 for (i = 0; i < len / 4; i++) {
560                         if (buf[i] != (sector << 24 | i)) {
561                                 printf ("flashDiag: Verify error "
562                                         "(dev: %d, sector: %d, offset: 0x%x)\n",
563                                         DEV_NO (dev), sector, i);
564                                 printf ("flashDiag: Expected 0x%08x, got 0x%08x\n",
565                                         sector << 24 | i, buf[i]);
566
567                                 goto done;
568                         }
569                 }
570         }
571
572         printf ("flashDiag: Erasing\n");
573
574         if (flashErase (dev) == ERROR) {
575                 printf ("flashDiag: Final erase failed\n");
576                 goto done;
577         }
578
579         rv = OK;
580
581   done:
582         if (buf)
583                 free (buf);
584
585         if (rv == OK)
586                 printf ("flashDiag: Device %d passed\n", DEV_NO (dev));
587         else
588                 printf ("flashDiag: Device %d failed\n", DEV_NO (dev));
589
590         return rv;
591 }
592
593 STATUS flashDiagAll (void)
594 {
595         int i;
596         int rv = OK;
597
598         PRINTF ("flashDiagAll: devices=%d\n", flashDevCount);
599
600         for (i = 0; i < flashDevCount; i++) {
601                 flash_dev_t *dev = &flashDev[i];
602
603                 if (dev->found && flashDiag (dev) == ERROR)
604                         rv = ERROR;
605         }
606
607         if (rv == OK)
608                 printf ("flashDiagAll: Passed\n");
609         else
610                 printf ("flashDiagAll: Failed because of earlier errors\n");
611
612         return OK;
613 }
614
615
616 /*-----------------------------------------------------------------------
617  */
618 unsigned long flash_init (void)
619 {
620         unsigned long size = 0;
621         flash_dev_t *dev = NULL;
622
623         flashLibInit ();
624
625         /*
626          * Provide info for FLASH (up to 960K) of Kernel Image data.
627          */
628         dev = FLASH_DEV_BANK0_LOW;
629         flash_info[FLASH_BANK_KERNEL].flash_id =
630                         (dev->vendorID << 16) | dev->deviceID;
631         flash_info[FLASH_BANK_KERNEL].sector_count = dev->sectors;
632         flash_info[FLASH_BANK_KERNEL].size =
633                         flash_info[FLASH_BANK_KERNEL].sector_count * FLASH_SECTOR_SIZE;
634         flash_info[FLASH_BANK_KERNEL].start[FIRST_SECTOR] = dev->base;
635         size += flash_info[FLASH_BANK_KERNEL].size;
636
637         /*
638          * Provide info for 512K PLCC FLASH ROM (U-Boot)
639          */
640         dev = FLASH_DEV_BANK0_BOOT;
641         flash_info[FLASH_BANK_BOOT].flash_id =
642                         (dev->vendorID << 16) | dev->deviceID;
643         flash_info[FLASH_BANK_BOOT].sector_count = dev->sectors;
644         flash_info[FLASH_BANK_BOOT].size =
645                         flash_info[FLASH_BANK_BOOT].sector_count * FLASH_SECTOR_SIZE;
646         flash_info[FLASH_BANK_BOOT].start[FIRST_SECTOR] = dev->base;
647         size += flash_info[FLASH_BANK_BOOT].size;
648
649
650         /*
651          * Provide info for 512K FLASH0 segment (U-Boot)
652          */
653         dev = FLASH_DEV_BANK0_HIGH;
654         flash_info[FLASH_BANK_AUX].flash_id =
655                         (dev->vendorID << 16) | dev->deviceID;
656         flash_info[FLASH_BANK_AUX].sector_count = dev->sectors;
657         flash_info[FLASH_BANK_AUX].size =
658                         flash_info[FLASH_BANK_AUX].sector_count * FLASH_SECTOR_SIZE;
659         flash_info[FLASH_BANK_AUX].start[FIRST_SECTOR] = dev->base;
660         size += flash_info[FLASH_BANK_AUX].size;
661
662
663         return size;
664 }
665
666 /*
667  * Get flash device from U-Boot flash info.
668  */
669 flash_dev_t *getFlashDevFromInfo (flash_info_t * info)
670 {
671         int i;
672
673         if (!info)
674                 return NULL;
675
676         for (i = 0; i < flashDevCount; i++) {
677                 flash_dev_t *dev = &flashDev[i];
678
679                 if (dev->found && (dev->base == info->start[0]))
680                         return dev;
681         }
682         printf ("ERROR: notice, no FLASH mapped at address 0x%x\n",
683                         (unsigned int) info->start[0]);
684         return NULL;
685 }
686
687 ulong flash_get_size (vu_long * addr, flash_info_t * info)
688 {
689         int i;
690
691         for (i = 0; i < flashDevCount; i++) {
692                 flash_dev_t *dev = &flashDev[i];
693
694                 if (dev->found) {
695                         if (dev->base == (unsigned int) addr) {
696                                 info->flash_id = (dev->vendorID << 16) | dev->deviceID;
697                                 info->sector_count = dev->sectors;
698                                 info->size = info->sector_count * FLASH_SECTOR_SIZE;
699                                 return dev->sectors * FLASH_SECTOR_SIZE;
700                         }
701                 }
702         }
703         return 0;
704 }
705
706 void flash_print_info (flash_info_t * info)
707 {
708         int i;
709         unsigned int chip;
710
711         if (info->flash_id == FLASH_UNKNOWN) {
712                 printf ("missing or unknown FLASH type\n");
713                 return;
714         }
715
716         switch ((info->flash_id >> 16) & 0xff) {
717         case 0x1:
718                 printf ("AMD ");
719                 break;
720         default:
721                 printf ("Unknown Vendor ");
722                 break;
723         }
724         chip = (unsigned int) info->flash_id & 0x000000ff;
725
726         switch (chip) {
727
728         case AMD_ID_F040B:
729                 printf ("AM29F040B (4 Mbit)\n");
730                 break;
731
732         case AMD_ID_LV160B:
733         case FLASH_AM160LV:
734         case 0x49:
735                 printf ("AM29LV160B (16 Mbit / 2M x 8bit)\n");
736                 break;
737
738         default:
739                 printf ("Unknown Chip Type:0x%x\n", chip);
740                 break;
741         }
742
743         printf ("  Size: %ld bytes in %d Sectors\n",
744                 info->size, info->sector_count);
745
746         printf ("  Sector Start Addresses:");
747         for (i = 0; i < info->sector_count; ++i) {
748                 if ((i % 5) == 0)
749                         printf ("\n   ");
750                 printf (" %08lX%s",
751                         info->start[FIRST_SECTOR] + i * FLASH_SECTOR_SIZE,
752                         info->protect[i] ? " (RO)" : "     ");
753         }
754         printf ("\n");
755 }
756
757
758 /*
759  * Erase a range of flash sectors.
760  */
761 int flash_erase (flash_info_t * info, int s_first, int s_last)
762 {
763         int prot, sect;
764         flash_dev_t *dev = NULL;
765
766         if ((s_first < 0) || (s_first > s_last)) {
767                 if (info->flash_id == FLASH_UNKNOWN) {
768                         printf ("- missing\n");
769                 } else {
770                         printf ("- no sectors to erase\n");
771                 }
772                 return 1;
773         }
774
775         prot = 0;
776         for (sect = s_first; sect <= s_last; sect++) {
777                 if (info->protect[sect]) {
778                         prot++;
779                 }
780         }
781
782         if (prot) {
783                 printf ("- Warning: %d protected sectors will not be erased!\n",
784                         prot);
785         } else {
786                 printf ("\n");
787         }
788
789         /* Start erase on unprotected sectors */
790         dev = getFlashDevFromInfo (info);
791         if (dev) {
792                 printf ("Erase FLASH[%s] -%d sectors:", dev->name, dev->sectors);
793                 for (sect = s_first; sect <= s_last; sect++) {
794                         if (info->protect[sect] == 0) { /* not protected */
795                                 printf (".");
796                                 if (ERROR == flashEraseSector (dev, sect)) {
797                                         printf ("ERROR: could not erase sector %d on FLASH[%s]\n", sect, dev->name);
798                                         return 1;
799                                 }
800                         }
801                 }
802         }
803         printf (" done\n");
804         return 0;
805 }
806
807 /*-----------------------------------------------------------------------
808  * Write a word to Flash, returns:
809  * 0 - OK
810  * 1 - write timeout
811  * 2 - Flash not erased
812  */
813 static int write_word (flash_info_t * info, ulong dest, ulong data)
814 {
815
816         flash_dev_t *dev = getFlashDevFromInfo (info);
817         int addr = dest - info->start[0];
818
819         if (!dev)
820                 return 1;
821
822         if (OK != flashWrite (dev, addr, (char *) &data, sizeof (ulong))) {
823                 printf ("ERROR: could not write to addr=0x%x, data=0x%x\n",
824                         (unsigned int) addr, (unsigned) data);
825                 return 1;
826         }
827
828         if ((addr % FLASH_SECTOR_SIZE) == 0)
829                 printf (".");
830
831
832         PRINTF ("write_word:0x%x, base=0x%x, addr=0x%x, data=0x%x\n",
833                 (unsigned) info->start[0],
834                 (unsigned) dest,
835                 (unsigned) (dest - info->start[0]), (unsigned) data);
836
837         return (0);
838 }
839
840
841 /*-----------------------------------------------------------------------
842  * Copy memory to flash, returns:
843  * 0 - OK
844  * 1 - write timeout
845  * 2 - Flash not erased
846  */
847
848 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
849 {
850         ulong cp, wp, data;
851         int i, l, rc;
852         flash_dev_t *dev = getFlashDevFromInfo (info);
853
854         if (dev) {
855                 printf ("FLASH[%s]:", dev->name);
856                 wp = (addr & ~3);       /* get lower word aligned address */
857
858                 /*
859                  * handle unaligned start bytes
860                  */
861                 if ((l = addr - wp) != 0) {
862                         data = 0;
863                         for (i = 0, cp = wp; i < l; ++i, ++cp) {
864                                 data = (data << 8) | (*(uchar *) cp);
865                         }
866                         for (; i < 4 && cnt > 0; ++i) {
867                                 data = (data << 8) | *src++;
868                                 --cnt;
869                                 ++cp;
870                         }
871                         for (; cnt == 0 && i < 4; ++i, ++cp) {
872                                 data = (data << 8) | (*(uchar *) cp);
873                         }
874                         if ((rc = write_word (info, wp, data)) != 0) {
875                                 return (rc);
876                         }
877                         wp += 4;
878                 }
879
880                 /*
881                  * handle word aligned part
882                  */
883                 while (cnt >= 4) {
884                         data = 0;
885                         for (i = 0; i < 4; ++i) {
886                                 data = (data << 8) | *src++;
887                         }
888                         if ((rc = write_word (info, wp, data)) != 0) {
889                                 return (rc);
890                         }
891                         wp += 4;
892                         cnt -= 4;
893                 }
894
895                 if (cnt == 0) {
896                         return (0);
897                 }
898
899                 /*
900                  * handle unaligned tail bytes
901                  */
902                 data = 0;
903                 for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
904                         data = (data << 8) | *src++;
905                         --cnt;
906                 }
907                 for (; i < 4; ++i, ++cp) {
908                         data = (data << 8) | (*(uchar *) cp);
909                 }
910
911                 return (write_word (info, wp, data));
912         }
913         return 1;
914 }
915
916 /*-----------------------------------------------------------------------
917  */