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