]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/MAI/AmigaOneG3SE/flash_new.c
imported Freescale specific U-Boot additions for i.MX28,... release L2.6.31_10.08.01
[karo-tx-uboot.git] / board / MAI / AmigaOneG3SE / flash_new.c
1 /*
2  * (C) Copyright 2001
3  * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
4  *
5  * (C) Copyright 2002
6  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26
27 #include <common.h>
28 #include <flash.h>
29 #include <asm/io.h>
30 #include "memio.h"
31
32 /*---------------------------------------------------------------------*/
33 #undef DEBUG_FLASH
34
35 #ifdef DEBUG_FLASH
36 #define DEBUGF(fmt,args...) printf(fmt ,##args)
37 #else
38 #define DEBUGF(fmt,args...)
39 #endif
40 /*---------------------------------------------------------------------*/
41
42 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
43
44 static ulong flash_get_size (ulong addr, flash_info_t *info);
45 static int flash_get_offsets (ulong base, flash_info_t *info);
46 static int write_word (flash_info_t *info, ulong dest, ulong data);
47 static void flash_reset (ulong addr);
48
49 int flash_xd_nest;
50
51 static void flash_to_xd(void)
52 {
53     unsigned char x;
54
55     flash_xd_nest ++;
56
57     if (flash_xd_nest == 1)
58     {
59         DEBUGF("Flash on XD\n");
60         x = pci_read_cfg_byte(0, 0, 0x74);
61         pci_write_cfg_byte(0, 0, 0x74, x|1);
62     }
63 }
64
65 static void flash_to_mem(void)
66 {
67     unsigned char x;
68
69     flash_xd_nest --;
70
71     if (flash_xd_nest == 0)
72     {
73         DEBUGF("Flash on memory bus\n");
74         x = pci_read_cfg_byte(0, 0, 0x74);
75         pci_write_cfg_byte(0, 0, 0x74, x&0xFE);
76     }
77 }
78
79 unsigned long flash_init_old(void)
80 {
81     int i;
82
83     for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
84     {
85         flash_info[i].flash_id = FLASH_UNKNOWN;
86         flash_info[i].sector_count = 0;
87         flash_info[i].size = 0;
88     }
89
90
91     return 1;
92 }
93
94 unsigned long flash_init (void)
95 {
96         unsigned int i;
97         unsigned long flash_size = 0;
98
99         flash_xd_nest = 0;
100
101         flash_to_xd();
102
103         /* Init: no FLASHes known */
104         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
105                 flash_info[i].flash_id = FLASH_UNKNOWN;
106                 flash_info[i].sector_count = 0;
107                 flash_info[i].size = 0;
108         }
109
110         DEBUGF("\n## Get flash size @ 0x%08x\n", CONFIG_SYS_FLASH_BASE);
111
112         flash_size = flash_get_size (CONFIG_SYS_FLASH_BASE, flash_info);
113
114         DEBUGF("## Flash bank size: %08lx\n", flash_size);
115
116         if (flash_size) {
117 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE && \
118     CONFIG_SYS_MONITOR_BASE < CONFIG_SYS_FLASH_BASE + CONFIG_SYS_FLASH_MAX_SIZE
119                 /* monitor protection ON by default */
120                 flash_protect(FLAG_PROTECT_SET,
121                               CONFIG_SYS_MONITOR_BASE,
122                               CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
123                               &flash_info[0]);
124 #endif
125
126 #ifdef CONFIG_ENV_IS_IN_FLASH
127                 /* ENV protection ON by default */
128                 flash_protect(FLAG_PROTECT_SET,
129                               CONFIG_ENV_ADDR,
130                               CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
131                               &flash_info[0]);
132 #endif
133
134         } else {
135                 puts ("Warning: the BOOT Flash is not initialised !");
136         }
137
138         flash_to_mem();
139
140         return flash_size;
141 }
142
143 /*
144  * The following code cannot be run from FLASH!
145  */
146 static ulong flash_get_size (ulong addr, flash_info_t *info)
147 {
148         short i;
149         uchar value;
150         uchar *x = (uchar *)addr;
151
152         flash_to_xd();
153
154         /* Write auto select command: read Manufacturer ID */
155         x[0x0555] =  0xAA;
156         __asm__ volatile ("sync\n eieio");
157         x[0x02AA] =  0x55;
158         __asm__ volatile ("sync\n eieio");
159         x[0x0555] =  0x90;
160         __asm__ volatile ("sync\n eieio");
161
162         value = x[0];
163         __asm__ volatile ("sync\n eieio");
164
165         DEBUGF("Manuf. ID @ 0x%08lx: 0x%08x\n", (ulong)addr, value);
166
167         switch (value | (value << 16)) {
168                 case AMD_MANUFACT:
169                         info->flash_id = FLASH_MAN_AMD;
170                         break;
171
172                 case FUJ_MANUFACT:
173                         info->flash_id = FLASH_MAN_FUJ;
174                         break;
175
176                 case STM_MANUFACT:
177                         info->flash_id = FLASH_MAN_STM;
178                         break;
179
180                 default:
181                         info->flash_id = FLASH_UNKNOWN;
182                         info->sector_count = 0;
183                         info->size = 0;
184                         flash_reset (addr);
185                         return 0;
186         }
187
188         value = x[1];
189         __asm__ volatile ("sync\n eieio");
190
191         DEBUGF("Device ID @ 0x%08lx: 0x%08x\n", addr+1, value);
192
193         switch (value) {
194                 case AMD_ID_F040B:
195                         DEBUGF("Am29F040B\n");
196                         info->flash_id += FLASH_AM040;
197                         info->sector_count = 8;
198                         info->size = 0x00080000;
199                         break;                  /* => 512 kB            */
200
201                 case AMD_ID_LV040B:
202                         DEBUGF("Am29LV040B\n");
203                         info->flash_id += FLASH_AM040;
204                         info->sector_count = 8;
205                         info->size = 0x00080000;
206                         break;                  /* => 512 kB            */
207
208                 case AMD_ID_LV400T:
209                         DEBUGF("Am29LV400T\n");
210                         info->flash_id += FLASH_AM400T;
211                         info->sector_count = 11;
212                         info->size = 0x00100000;
213                         break;                  /* => 1 MB              */
214
215                 case AMD_ID_LV400B:
216                         DEBUGF("Am29LV400B\n");
217                         info->flash_id += FLASH_AM400B;
218                         info->sector_count = 11;
219                         info->size = 0x00100000;
220                         break;                  /* => 1 MB              */
221
222                 case AMD_ID_LV800T:
223                         DEBUGF("Am29LV800T\n");
224                         info->flash_id += FLASH_AM800T;
225                         info->sector_count = 19;
226                         info->size = 0x00200000;
227                         break;                  /* => 2 MB              */
228
229                 case AMD_ID_LV800B:
230                         DEBUGF("Am29LV400B\n");
231                         info->flash_id += FLASH_AM800B;
232                         info->sector_count = 19;
233                         info->size = 0x00200000;
234                         break;                  /* => 2 MB              */
235
236                 case AMD_ID_LV160T:
237                         DEBUGF("Am29LV160T\n");
238                         info->flash_id += FLASH_AM160T;
239                         info->sector_count = 35;
240                         info->size = 0x00400000;
241                         break;                  /* => 4 MB              */
242
243                 case AMD_ID_LV160B:
244                         DEBUGF("Am29LV160B\n");
245                         info->flash_id += FLASH_AM160B;
246                         info->sector_count = 35;
247                         info->size = 0x00400000;
248                         break;                  /* => 4 MB              */
249
250                 case AMD_ID_LV320T:
251                         DEBUGF("Am29LV320T\n");
252                         info->flash_id += FLASH_AM320T;
253                         info->sector_count = 67;
254                         info->size = 0x00800000;
255                         break;                  /* => 8 MB              */
256
257 #if 0
258                 /* Has the same ID as AMD_ID_LV320T, to be fixed */
259                 case AMD_ID_LV320B:
260                         DEBUGF("Am29LV320B\n");
261                         info->flash_id += FLASH_AM320B;
262                         info->sector_count = 67;
263                         info->size = 0x00800000;
264                         break;                  /* => 8 MB              */
265 #endif
266
267                 case AMD_ID_LV033C:
268                         DEBUGF("Am29LV033C\n");
269                         info->flash_id += FLASH_AM033C;
270                         info->sector_count = 64;
271                         info->size = 0x01000000;
272                         break;                  /* => 16Mb              */
273
274                 case STM_ID_F040B:
275                         DEBUGF("M29F040B\n");
276                         info->flash_id += FLASH_AM040;
277                         info->sector_count = 8;
278                         info->size = 0x00080000;
279                         break;                  /* => 512 kB            */
280
281                 default:
282                         info->flash_id = FLASH_UNKNOWN;
283                         flash_reset (addr);
284                         flash_to_mem();
285                         return (0);             /* => no or unknown flash */
286
287         }
288
289         if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
290                 printf ("** ERROR: sector count %d > max (%d) **\n",
291                         info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
292                 info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
293         }
294
295         if (! flash_get_offsets (addr, info)) {
296                 flash_reset (addr);
297                 flash_to_mem();
298                 return 0;
299         }
300
301         /* check for protected sectors */
302         for (i = 0; i < info->sector_count; i++) {
303                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
304                 /* D0 = 1 if protected */
305                 value = in8(info->start[i] + 2);
306                 iobarrier_rw();
307                 info->protect[i] = (value & 1) != 0;
308         }
309
310         /*
311          * Reset bank to read mode
312          */
313         flash_reset (addr);
314
315         flash_to_mem();
316
317         return (info->size);
318 }
319
320 static int flash_get_offsets (ulong base, flash_info_t *info)
321 {
322         unsigned int i;
323
324         switch (info->flash_id & FLASH_TYPEMASK) {
325                 case FLASH_AM040:
326                         /* set sector offsets for uniform sector type   */
327                         for (i = 0; i < info->sector_count; i++) {
328                                 info->start[i] = base + i * info->size /
329                                                             info->sector_count;
330                         }
331                         break;
332                 default:
333                         return 0;
334         }
335
336         return 1;
337 }
338
339 int flash_erase (flash_info_t *info, int s_first, int s_last)
340 {
341         volatile ulong addr = info->start[0];
342         int flag, prot, sect, l_sect;
343         ulong start, now, last;
344
345         flash_to_xd();
346
347         if (s_first < 0 || s_first > s_last) {
348                 if (info->flash_id == FLASH_UNKNOWN) {
349                         printf ("- missing\n");
350                 } else {
351                         printf ("- no sectors to erase\n");
352                 }
353                 flash_to_mem();
354                 return 1;
355         }
356
357         if (info->flash_id == FLASH_UNKNOWN) {
358                 printf ("Can't erase unknown flash type %08lx - aborted\n",
359                         info->flash_id);
360                 flash_to_mem();
361                 return 1;
362         }
363
364         prot = 0;
365         for (sect=s_first; sect<=s_last; ++sect) {
366                 if (info->protect[sect]) {
367                         prot++;
368                 }
369         }
370
371         if (prot) {
372                 printf ("- Warning: %d protected sectors will not be erased!\n",
373                         prot);
374         } else {
375                 printf ("\n");
376         }
377
378         l_sect = -1;
379
380         /* Disable interrupts which might cause a timeout here */
381         flag = disable_interrupts();
382
383         out8(addr + 0x555, 0xAA);
384         iobarrier_rw();
385         out8(addr + 0x2AA, 0x55);
386         iobarrier_rw();
387         out8(addr + 0x555, 0x80);
388         iobarrier_rw();
389         out8(addr + 0x555, 0xAA);
390         iobarrier_rw();
391         out8(addr + 0x2AA, 0x55);
392         iobarrier_rw();
393
394         /* Start erase on unprotected sectors */
395         for (sect = s_first; sect<=s_last; sect++) {
396                 if (info->protect[sect] == 0) { /* not protected */
397                         addr = info->start[sect];
398                         out8(addr, 0x30);
399                         iobarrier_rw();
400                         l_sect = sect;
401                 }
402         }
403
404         /* re-enable interrupts if necessary */
405         if (flag)
406                 enable_interrupts();
407
408         /* wait at least 80us - let's wait 1 ms */
409         udelay (1000);
410
411         /*
412          * We wait for the last triggered sector
413          */
414         if (l_sect < 0)
415                 goto DONE;
416
417         start = get_timer (0);
418         last  = start;
419         addr = info->start[l_sect];
420
421         DEBUGF ("Start erase timeout: %d\n", CONFIG_SYS_FLASH_ERASE_TOUT);
422
423         while ((in8(addr) & 0x80) != 0x80) {
424                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
425                         printf ("Timeout\n");
426                         flash_reset (info->start[0]);
427                         flash_to_mem();
428                         return 1;
429                 }
430                 /* show that we're waiting */
431                 if ((now - last) > 1000) {      /* every second */
432                         putc ('.');
433                         last = now;
434                 }
435                 iobarrier_rw();
436         }
437
438 DONE:
439         /* reset to read mode */
440         flash_reset (info->start[0]);
441         flash_to_mem();
442
443         printf (" done\n");
444         return 0;
445 }
446
447 /*
448  * Copy memory to flash, returns:
449  * 0 - OK
450  * 1 - write timeout
451  * 2 - Flash not erased
452  */
453 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
454 {
455         ulong cp, wp, data;
456         int i, l, rc;
457
458         flash_to_xd();
459
460         wp = (addr & ~3);       /* get lower word aligned address */
461
462         /*
463          * handle unaligned start bytes
464          */
465         if ((l = addr - wp) != 0) {
466                 data = 0;
467                 for (i=0, cp=wp; i<l; ++i, ++cp) {
468                         data = (data << 8) | (*(uchar *)cp);
469                 }
470                 for (; i<4 && cnt>0; ++i) {
471                         data = (data << 8) | *src++;
472                         --cnt;
473                         ++cp;
474                 }
475                 for (; cnt==0 && i<4; ++i, ++cp) {
476                         data = (data << 8) | (*(uchar *)cp);
477                 }
478
479                 if ((rc = write_word(info, wp, data)) != 0) {
480                         flash_to_mem();
481                         return (rc);
482                 }
483                 wp += 4;
484         }
485
486         /*
487          * handle word aligned part
488          */
489         while (cnt >= 4) {
490                 data = 0;
491                 for (i=0; i<4; ++i) {
492                         data = (data << 8) | *src++;
493                 }
494                 if ((rc = write_word(info, wp, data)) != 0) {
495                         flash_to_mem();
496                         return (rc);
497                 }
498                 wp  += 4;
499                 cnt -= 4;
500         }
501
502         if (cnt == 0) {
503                 flash_to_mem();
504                 return (0);
505         }
506
507         /*
508          * handle unaligned tail bytes
509          */
510         data = 0;
511         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
512                 data = (data << 8) | *src++;
513                 --cnt;
514         }
515         for (; i<4; ++i, ++cp) {
516                 data = (data << 8) | (*(uchar *)cp);
517         }
518
519
520         flash_to_mem();
521         return (write_word(info, wp, data));
522 }
523
524 /*
525  * Write a word to Flash, returns:
526  * 0 - OK
527  * 1 - write timeout
528  * 2 - Flash not erased
529  */
530 static int write_word (flash_info_t *info, ulong dest, ulong data)
531 {
532         volatile ulong addr = info->start[0];
533         ulong start;
534         int i;
535
536         flash_to_xd();
537
538         /* Check if Flash is (sufficiently) erased */
539         if ((in32(dest) & data) != data) {
540                 flash_to_mem();
541                 return (2);
542         }
543
544         /* write each byte out */
545         for (i = 0; i < 4; i++) {
546                 char *data_ch = (char *)&data;
547                 int flag = disable_interrupts();
548
549                 out8(addr + 0x555, 0xAA);
550                 iobarrier_rw();
551                 out8(addr + 0x2AA, 0x55);
552                 iobarrier_rw();
553                 out8(addr + 0x555, 0xA0);
554                 iobarrier_rw();
555                 out8(dest+i, data_ch[i]);
556                 iobarrier_rw();
557
558                 /* re-enable interrupts if necessary */
559                 if (flag)
560                         enable_interrupts();
561
562                 /* data polling for D7 */
563                 start = get_timer (0);
564                 while ((in8(dest+i) & 0x80) != (data_ch[i] & 0x80)) {
565                         if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
566                                 flash_reset (addr);
567                                 flash_to_mem();
568                                 return (1);
569                         }
570                         iobarrier_rw();
571                 }
572         }
573
574         flash_reset (addr);
575         flash_to_mem();
576         return (0);
577 }
578
579 /*
580  * Reset bank to read mode
581  */
582 static void flash_reset (ulong addr)
583 {
584         flash_to_xd();
585         out8(addr, 0xF0);       /* reset bank */
586         iobarrier_rw();
587         flash_to_mem();
588 }
589
590 void flash_print_info (flash_info_t *info)
591 {
592         int i;
593
594         if (info->flash_id == FLASH_UNKNOWN) {
595                 printf ("missing or unknown FLASH type\n");
596                 return;
597         }
598
599         switch (info->flash_id & FLASH_VENDMASK) {
600         case FLASH_MAN_AMD:     printf ("AMD ");                break;
601         case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
602         case FLASH_MAN_BM:      printf ("BRIGHT MICRO ");       break;
603         case FLASH_MAN_STM:     printf ("SGS THOMSON ");        break;
604         default:                printf ("Unknown Vendor ");     break;
605         }
606
607         switch (info->flash_id & FLASH_TYPEMASK) {
608         case FLASH_AM040:       printf ("29F040 or 29LV040 (4 Mbit, uniform sectors)\n");
609                                 break;
610         case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
611                                 break;
612         case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
613                                 break;
614         case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
615                                 break;
616         case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
617                                 break;
618         case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
619                                 break;
620         case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
621                                 break;
622         case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
623                                 break;
624         case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
625                                 break;
626         default:                printf ("Unknown Chip Type\n");
627                                 break;
628         }
629
630         if (info->size % 0x100000 == 0) {
631                 printf ("  Size: %ld MB in %d Sectors\n",
632                         info->size / 0x100000, info->sector_count);
633         } else if (info->size % 0x400 == 0) {
634                 printf ("  Size: %ld KB in %d Sectors\n",
635                         info->size / 0x400, info->sector_count);
636         } else {
637                 printf ("  Size: %ld B in %d Sectors\n",
638                         info->size, info->sector_count);
639         }
640
641         printf ("  Sector Start Addresses:");
642         for (i=0; i<info->sector_count; ++i) {
643                 if ((i % 5) == 0)
644                         printf ("\n   ");
645                 printf (" %08lX%s",
646                         info->start[i],
647                         info->protect[i] ? " (RO)" : "     "
648                 );
649         }
650         printf ("\n");
651 }