]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/barco/flash.c
rename CFG_ macros to CONFIG_SYS
[karo-tx-uboot.git] / board / barco / flash.c
1 /********************************************************************
2  *
3  * Unless otherwise specified, Copyright (C) 2004-2005 Barco Control Rooms
4  *
5  * $Source: /home/services/cvs/firmware/ppc/u-boot-1.1.2/board/barco/flash.c,v $
6  * $Revision: 1.3 $
7  * $Author: mleeman $
8  * $Date: 2005/02/21 12:48:58 $
9  *
10  * Last ChangeLog Entry
11  * $Log: flash.c,v $
12  * Revision 1.3  2005/02/21 12:48:58  mleeman
13  * update of copyright years (feedback wd)
14  *
15  * Revision 1.2  2005/02/21 11:04:04  mleeman
16  * remove dead code and Coding style (feedback wd)
17  *
18  * Revision 1.1  2005/02/14 09:23:46  mleeman
19  * - moved 'barcohydra' directory to a more generic barco; since we will be
20  *   supporting and adding multiple boards
21  *
22  * Revision 1.2  2005/02/09 12:56:23  mleeman
23  * add generic header to track changes in sources
24  *
25  *
26  *******************************************************************/
27
28 /*
29  * (C) Copyright 2000
30  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
31  *
32  * See file CREDITS for list of people who contributed to this
33  * project.
34  *
35  * This program is free software; you can redistribute it and/or
36  * modify it under the terms of the GNU General Public License as
37  * published by the Free Software Foundation; either version 2 of
38  * the License, or (at your option) any later version.
39  *
40  * This program is distributed in the hope that it will be useful,
41  * but WITHOUT ANY WARRANTY; without even the implied warranty of
42  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
43  * GNU General Public License for more details.
44  *
45  * You should have received a copy of the GNU General Public License
46  * along with this program; if not, write to the Free Software
47  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
48  * MA 02111-1307 USA
49  */
50
51 #include <common.h>
52 #include <mpc824x.h>
53 #include <asm/processor.h>
54 #include <flash.h>
55
56 #define ROM_CS0_START   0xFF800000
57 #define ROM_CS1_START   0xFF000000
58
59 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips    */
60
61 #if defined(CONFIG_ENV_IS_IN_FLASH)
62 # ifndef  CONFIG_ENV_ADDR
63 #  define CONFIG_ENV_ADDR  (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
64 # endif
65 # ifndef  CONFIG_ENV_SIZE
66 #  define CONFIG_ENV_SIZE  CONFIG_ENV_SECT_SIZE
67 # endif
68 # ifndef  CONFIG_ENV_SECT_SIZE
69 #  define CONFIG_ENV_SECT_SIZE  CONFIG_ENV_SIZE
70 # endif
71 #endif
72
73 /*-----------------------------------------------------------------------
74  * Functions
75  */
76 static int write_word (flash_info_t *info, ulong dest, ulong data);
77
78 /*flash command address offsets*/
79
80 #define ADDR0           (0xAAA)
81 #define ADDR1           (0x555)
82 #define ADDR3           (0x001)
83
84 #define FLASH_WORD_SIZE unsigned char
85
86 /*-----------------------------------------------------------------------
87  */
88
89 static unsigned long flash_id(unsigned char mfct, unsigned char chip) __attribute__ ((const));
90
91 typedef struct{
92   FLASH_WORD_SIZE extval;
93   unsigned short intval;
94 } map_entry;
95
96 static unsigned long flash_id(unsigned char mfct, unsigned char chip)
97 {
98         static const map_entry mfct_map[] = {
99                 {(FLASH_WORD_SIZE) AMD_MANUFACT,        (unsigned short) ((unsigned long) FLASH_MAN_AMD >> 16)},
100                 {(FLASH_WORD_SIZE) FUJ_MANUFACT,        (unsigned short) ((unsigned long) FLASH_MAN_FUJ >> 16)},
101                 {(FLASH_WORD_SIZE) STM_MANUFACT,        (unsigned short) ((unsigned long) FLASH_MAN_STM >> 16)},
102                 {(FLASH_WORD_SIZE) MT_MANUFACT, (unsigned short) ((unsigned long) FLASH_MAN_MT >> 16)},
103                 {(FLASH_WORD_SIZE) INTEL_MANUFACT,(unsigned short) ((unsigned long) FLASH_MAN_INTEL >> 16)},
104                 {(FLASH_WORD_SIZE) INTEL_ALT_MANU,(unsigned short) ((unsigned long) FLASH_MAN_INTEL >> 16)}
105         };
106
107         static const map_entry chip_map[] = {
108                 {AMD_ID_F040B,  FLASH_AM040},
109                 {AMD_ID_F033C,  FLASH_AM033},
110                 {AMD_ID_F065D,  FLASH_AM065},
111                 {ATM_ID_LV040,  FLASH_AT040},
112                 {(FLASH_WORD_SIZE) STM_ID_x800AB,       FLASH_STM800AB}
113         };
114
115         const map_entry *p;
116         unsigned long result = FLASH_UNKNOWN;
117
118         /* find chip id */
119         for(p = &chip_map[0]; p < &chip_map[sizeof chip_map / sizeof chip_map[0]]; p++){
120                 if(p->extval == chip){
121                         result = FLASH_VENDMASK | p->intval;
122                         break;
123                 }
124         }
125
126         /* find vendor id */
127         for(p = &mfct_map[0]; p < &mfct_map[sizeof mfct_map / sizeof mfct_map[0]]; p++){
128                 if(p->extval == mfct){
129                         result &= ~FLASH_VENDMASK;
130                         result |= (unsigned long) p->intval << 16;
131                         break;
132                 }
133         }
134
135         return result;
136 }
137
138
139 unsigned long flash_init(void)
140 {
141         unsigned long i;
142         unsigned char j;
143         static const ulong flash_banks[] = CONFIG_SYS_FLASH_BANKS;
144
145         /* Init: no FLASHes known */
146         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++){
147                 flash_info_t * const pflinfo = &flash_info[i];
148                 pflinfo->flash_id = FLASH_UNKNOWN;
149                 pflinfo->size = 0;
150                 pflinfo->sector_count = 0;
151         }
152
153         /* Enable writes to Hydra/Argus flash */
154         {
155                 register unsigned int temp;
156                 CONFIG_READ_WORD(PICR1,temp);
157                 temp |= PICR1_FLASH_WR_EN;
158                 CONFIG_WRITE_WORD(PICR1,temp);
159         }
160
161         for(i = 0; i < sizeof flash_banks / sizeof flash_banks[0]; i++){
162                 flash_info_t * const pflinfo = &flash_info[i];
163                 const unsigned long base_address = flash_banks[i];
164                 volatile FLASH_WORD_SIZE * const flash = (FLASH_WORD_SIZE *) base_address;
165
166                 /* write autoselect sequence */
167                 flash[0x5555] = 0xaa;
168                 flash[0x2aaa] = 0x55;
169                 flash[0x5555] = 0x90;
170                 __asm__ __volatile__("sync");
171
172                 pflinfo->flash_id = flash_id(flash[0x0], flash[0x1]);
173
174                 switch(pflinfo->flash_id & FLASH_TYPEMASK){
175                         case FLASH_AM033:
176                                 pflinfo->size = 0x00200000;
177                                 pflinfo->sector_count = 64;
178                                 for(j = 0; j < 64; j++){
179                                         pflinfo->start[j] = base_address + 0x00010000 * j;
180                                         pflinfo->protect[j] = flash[(j << 16) | 0x2];
181                                 }
182                                 break;
183                         case FLASH_AM065:
184                                 pflinfo->size = 0x00800000;
185                                 pflinfo->sector_count =128;
186                                 for(j = 0; j < 128; j++){
187                                         pflinfo->start[j] = base_address + 0x00010000 * j;
188                                         pflinfo->protect[j] = flash[(j << 16) | 0x2];
189                                 }
190                                 break;
191                         case FLASH_AT040:
192                                 pflinfo->size = 0x00080000;
193                                 pflinfo->sector_count = 2;
194                                 pflinfo->start[0] = base_address ;
195                                 pflinfo->start[1] = base_address + 0x00004000;
196                                 pflinfo->protect[0] = ((flash[0x02] & 0X01)==0) ? 0X02 : 0X01;
197                                 pflinfo->protect[1] = 0X02;
198                                 break;
199                         case FLASH_AM040:
200                                 pflinfo->size = 0x00080000;
201                                 pflinfo->sector_count = 8;
202                                 for(j = 0; j < 8; j++){
203                                         pflinfo->start[j] = base_address + 0x00010000 * j;
204                                         pflinfo->protect[j] = flash[(j << 16) | 0x2];
205                                 }
206                                 break;
207                         case FLASH_STM800AB:
208                                 pflinfo->size = 0x00100000;
209                                 pflinfo->sector_count = 19;
210                                 pflinfo->start[0] = base_address;
211                                 pflinfo->start[1] = base_address + 0x4000;
212                                 pflinfo->start[2] = base_address + 0x6000;
213                                 pflinfo->start[3] = base_address + 0x8000;
214                                 for(j = 1; j < 16; j++){
215                                         pflinfo->start[j+3] = base_address + 0x00010000 * j;
216                                 }
217                                 break;
218                 }
219                 /* Protect monitor and environment sectors */
220 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
221                 flash_protect(FLAG_PROTECT_SET,
222                                 CONFIG_SYS_MONITOR_BASE,
223                                 CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
224                                 &flash_info[0]);
225 #endif
226
227 #if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
228                 flash_protect(FLAG_PROTECT_SET,
229                                 CONFIG_ENV_ADDR,
230                                 CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
231                                 &flash_info[0]);
232 #endif
233
234                 /* reset device to read mode */
235                 flash[0x0000] = 0xf0;
236                 __asm__ __volatile__("sync");
237         }
238
239         return flash_info[0].size + flash_info[1].size;
240 }
241
242 /*-----------------------------------------------------------------------
243  */
244 void flash_print_info(flash_info_t *info)
245 {
246         static const char unk[] = "Unknown";
247         const char *mfct = unk, *type = unk;
248         unsigned int i;
249
250         if(info->flash_id != FLASH_UNKNOWN){
251                 switch(info->flash_id & FLASH_VENDMASK){
252                         case FLASH_MAN_ATM:
253                                 mfct = "Atmel";
254                                 break;
255                         case FLASH_MAN_AMD:
256                                 mfct = "AMD";
257                                 break;
258                         case FLASH_MAN_FUJ:
259                                 mfct = "FUJITSU";
260                                 break;
261                         case FLASH_MAN_STM:
262                                 mfct = "STM";
263                                 break;
264                         case FLASH_MAN_SST:
265                                 mfct = "SST";
266                                 break;
267                         case FLASH_MAN_BM:
268                                 mfct = "Bright Microelectonics";
269                                 break;
270                         case FLASH_MAN_INTEL:
271                                 mfct = "Intel";
272                                 break;
273                 }
274
275                 switch(info->flash_id & FLASH_TYPEMASK){
276                         case FLASH_AT040:
277                                 type = "AT49LV040 (512K * 8, uniform sector size)";
278                                 break;
279                         case FLASH_AM033:
280                                 type = "AM29F033C (4 Mbit * 8, uniform sector size)";
281                                 break;
282                         case FLASH_AM040:
283                                 type = "AM29F040B (512K * 8, uniform sector size)";
284                                 break;
285                         case FLASH_AM065:
286                                 type = "AM29F0465D ( 8 MBit * 8, uniform sector size) or part of AM29F652D( 16 MB)";
287                                 break;
288                         case FLASH_AM400B:
289                                 type = "AM29LV400B (4 Mbit, bottom boot sect)";
290                                 break;
291                         case FLASH_AM400T:
292                                 type = "AM29LV400T (4 Mbit, top boot sector)";
293                                 break;
294                         case FLASH_AM800B:
295                                 type = "AM29LV800B (8 Mbit, bottom boot sect)";
296                                 break;
297                         case FLASH_AM800T:
298                                 type = "AM29LV800T (8 Mbit, top boot sector)";
299                                 break;
300                         case FLASH_AM160T:
301                                 type = "AM29LV160T (16 Mbit, top boot sector)";
302                                 break;
303                         case FLASH_AM320B:
304                                 type = "AM29LV320B (32 Mbit, bottom boot sect)";
305                                 break;
306                         case FLASH_AM320T:
307                                 type = "AM29LV320T (32 Mbit, top boot sector)";
308                                 break;
309                         case FLASH_STM800AB:
310                                 type = "M29W800AB (8 Mbit, bottom boot sect)";
311                                 break;
312                         case FLASH_SST800A:
313                                 type = "SST39LF/VF800 (8 Mbit, uniform sector size)";
314                                 break;
315                         case FLASH_SST160A:
316                                 type = "SST39LF/VF160 (16 Mbit, uniform sector size)";
317                                 break;
318                 }
319         }
320
321         printf(
322                         "\n  Brand: %s Type: %s\n"
323                         "  Size: %lu KB in %d Sectors\n",
324                         mfct,
325                         type,
326                         info->size >> 10,
327                         info->sector_count
328               );
329
330         printf ("  Sector Start Addresses:");
331
332         for (i = 0; i < info->sector_count; i++){
333                 unsigned long size;
334                 unsigned int erased;
335                 unsigned long * flash = (unsigned long *) info->start[i];
336
337                 /*
338                  * Check if whole sector is erased
339                  */
340                 size =
341                         (i != (info->sector_count - 1)) ?
342                         (info->start[i + 1] - info->start[i]) >> 2 :
343                         (info->start[0] + info->size - info->start[i]) >> 2;
344
345                 for(
346                                 flash = (unsigned long *) info->start[i], erased = 1;
347                                 (flash != (unsigned long *) info->start[i] + size) && erased;
348                                 flash++
349                    ){
350                         erased = *flash == ~0x0UL;
351                 }
352
353                 printf(
354                                 "%s %08lX %s %s",
355                                 (i % 5) ? "" : "\n   ",
356                                 info->start[i],
357                                 erased ? "E" : " ",
358                                 info->protect[i] ? "RO" : "  "
359                       );
360         }
361
362         puts("\n");
363         return;
364 }
365
366 int flash_erase(flash_info_t *info, int s_first, int s_last)
367 {
368         volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
369         int flag, prot, sect, l_sect;
370         ulong start, now, last;
371         unsigned char sh8b;
372
373         if ((s_first < 0) || (s_first > s_last)) {
374                 if (info->flash_id == FLASH_UNKNOWN) {
375                         printf ("- missing\n");
376                 } else {
377                         printf ("- no sectors to erase\n");
378                 }
379                 return 1;
380         }
381
382         if ((info->flash_id == FLASH_UNKNOWN) ||
383                         (info->flash_id > (FLASH_MAN_STM | FLASH_AMD_COMP))) {
384                 printf ("Can't erase unknown flash type - aborted\n");
385                 return 1;
386         }
387
388         prot = 0;
389         for (sect=s_first; sect<=s_last; ++sect) {
390                 if (info->protect[sect]) {
391                         prot++;
392                 }
393         }
394
395         if (prot) {
396                 printf ("- Warning: %d protected sectors will not be erased!\n",
397                                 prot);
398         } else {
399                 printf ("\n");
400         }
401
402         l_sect = -1;
403
404         /* Check the ROM CS */
405         if ((info->start[0] >= ROM_CS1_START) && (info->start[0] < ROM_CS0_START)){
406                 sh8b = 3;
407         }
408         else{
409                 sh8b = 0;
410         }
411
412         /* Disable interrupts which might cause a timeout here */
413         flag = disable_interrupts();
414
415         addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
416         addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
417         addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00800080;
418         addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
419         addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
420
421         /* Start erase on unprotected sectors */
422         for (sect = s_first; sect<=s_last; sect++) {
423                 if (info->protect[sect] == 0) { /* not protected */
424                         addr = (FLASH_WORD_SIZE *)(info->start[0] + (
425                                                 (info->start[sect] - info->start[0]) << sh8b));
426                         if (info->flash_id & FLASH_MAN_SST){
427                                 addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
428                                 addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
429                                 addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00800080;
430                                 addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
431                                 addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
432                                 addr[0] = (FLASH_WORD_SIZE)0x00500050;  /* block erase */
433                                 udelay(30000);  /* wait 30 ms */
434                         }
435                         else
436                                 addr[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */
437                         l_sect = sect;
438                 }
439         }
440
441         /* re-enable interrupts if necessary */
442         if (flag){
443                 enable_interrupts();
444         }
445
446         /* wait at least 80us - let's wait 1 ms */
447         udelay (1000);
448
449         /*
450          * We wait for the last triggered sector
451          */
452         if (l_sect < 0){
453                 goto DONE;
454         }
455
456         start = get_timer (0);
457         last  = start;
458         addr = (FLASH_WORD_SIZE *)(info->start[0] + (
459                                 (info->start[l_sect] - info->start[0]) << sh8b));
460         while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
461                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
462                         printf ("Timeout\n");
463                         return 1;
464                 }
465                 /* show that we're waiting */
466                 if ((now - last) > 1000) {  /* every second */
467                         serial_putc ('.');
468                         last = now;
469                 }
470         }
471
472 DONE:
473         /* reset to read mode */
474         addr = (FLASH_WORD_SIZE *)info->start[0];
475         addr[0] = (FLASH_WORD_SIZE)0x00F000F0;  /* reset bank */
476
477         printf (" done\n");
478         return 0;
479 }
480
481 /*-----------------------------------------------------------------------
482  * Copy memory to flash, returns:
483  * 0 - OK
484  * 1 - write timeout
485  * 2 - Flash not erased
486  */
487
488 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
489 {
490         ulong cp, wp, data;
491         int i, l, rc;
492
493         wp = (addr & ~3);   /* get lower word aligned address */
494
495         /*
496          * handle unaligned start bytes
497          */
498         if ((l = addr - wp) != 0) {
499                 data = 0;
500                 for (i=0, cp=wp; i<l; ++i, ++cp) {
501                         data = (data << 8) | (*(uchar *)cp);
502                 }
503                 for (; i<4 && cnt>0; ++i) {
504                         data = (data << 8) | *src++;
505                         --cnt;
506                         ++cp;
507                 }
508                 for (; cnt==0 && i<4; ++i, ++cp) {
509                         data = (data << 8) | (*(uchar *)cp);
510                 }
511
512                 if ((rc = write_word(info, wp, data)) != 0) {
513                         return (rc);
514                 }
515                 wp += 4;
516         }
517
518         /*
519          * handle word aligned part
520          */
521         while (cnt >= 4) {
522                 data = 0;
523                 for (i=0; i<4; ++i) {
524                         data = (data << 8) | *src++;
525                 }
526                 if ((rc = write_word(info, wp, data)) != 0) {
527                         return (rc);
528                 }
529                 wp  += 4;
530                 cnt -= 4;
531         }
532
533         if (cnt == 0) {
534                 return (0);
535         }
536
537         /*
538          * handle unaligned tail bytes
539          */
540         data = 0;
541         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
542                 data = (data << 8) | *src++;
543                 --cnt;
544         }
545         for (; i<4; ++i, ++cp) {
546                 data = (data << 8) | (*(uchar *)cp);
547         }
548
549         return (write_word(info, wp, data));
550 }
551
552 /*-----------------------------------------------------------------------
553  * Write a word to Flash, returns:
554  * 0 - OK
555  * 1 - write timeout
556  * 2 - Flash not erased
557  */
558 static int write_word (flash_info_t *info, ulong dest, ulong data)
559 {
560         volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)info->start[0];
561         volatile FLASH_WORD_SIZE *dest2;
562         volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data;
563         ulong start;
564         int flag;
565         int i;
566         unsigned char sh8b;
567
568         /* Check the ROM CS */
569         if ((info->start[0] >= ROM_CS1_START) && (info->start[0] < ROM_CS0_START)){
570                 sh8b = 3;
571         }
572         else{
573                 sh8b = 0;
574         }
575
576         dest2 = (FLASH_WORD_SIZE *)(((dest - info->start[0]) << sh8b) +
577                         info->start[0]);
578
579         /* Check if Flash is (sufficiently) erased */
580         if ((*dest2 & (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) {
581                 return (2);
582         }
583         /* Disable interrupts which might cause a timeout here */
584         flag = disable_interrupts();
585
586         for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++){
587                 addr2[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
588                 addr2[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
589                 addr2[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00A000A0;
590
591                 dest2[i << sh8b] = data2[i];
592
593                 /* re-enable interrupts if necessary */
594                 if (flag){
595                         enable_interrupts();
596                 }
597
598                 /* data polling for D7 */
599                 start = get_timer (0);
600                 while ((dest2[i << sh8b] & (FLASH_WORD_SIZE)0x00800080) !=
601                                 (data2[i] & (FLASH_WORD_SIZE)0x00800080)) {
602                         if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
603                                 return (1);
604                         }
605                 }
606         }
607
608         return (0);
609 }
610
611 /*----------------------------------------------------------------------- */