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