Patch by Kurt Stremerch, 28 May 2004:
[platform/kernel/u-boot.git] / board / xsengine / flash.c
1 /*
2  * (C) Copyright 2002
3  * Robert Schwebel, Pengutronix, <r.schwebel@pengutronix.de>
4  *
5  * (C) Copyright 2000-2004
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 <linux/byteorder/swab.h>
29
30 #if defined CFG_JFFS_CUSTOM_PART
31 #include <jffs2/jffs2.h>
32 #endif
33
34 #define SWAP(x)               __swab32(x)
35
36 flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
37
38 /* Functions */
39 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
40 static int write_word (flash_info_t *info, ulong dest, ulong data);
41 static void flash_get_offsets (ulong base, flash_info_t *info);
42
43 #if defined CFG_JFFS_CUSTOM_PART
44
45 /*
46  * jffs2_part_info - get information about a JFFS2 partition
47  *
48  * @part_num: number of the partition you want to get info about
49  * @return:   struct part_info* in case of success, 0 if failure
50  */
51
52 static struct part_info part;
53 static int current_part = -1;
54
55 struct part_info* jffs2_part_info(int part_num) {
56         void *jffs2_priv_saved = part.jffs2_priv;
57
58         printf("jffs2_part_info: part_num=%i\n",part_num);
59
60         if (current_part == part_num)
61                 return &part;
62
63         /* u-boot partition                                                 */
64         if(part_num==0){
65                 memset(&part, 0, sizeof(part));
66
67                 part.offset=(char*)0x00000000;
68                 part.size=256*1024;
69
70                 /* Mark the struct as ready */
71                 current_part = part_num;
72
73                 printf("part.offset = 0x%08x\n",(unsigned int)part.offset);
74                 printf("part.size   = 0x%08x\n",(unsigned int)part.size);
75         }
76
77         /* primary OS+firmware partition                                    */
78         if(part_num==1){
79                 memset(&part, 0, sizeof(part));
80
81                 part.offset=(char*)0x00040000;
82                 part.size=1024*1024;
83
84                 /* Mark the struct as ready */
85                 current_part = part_num;
86
87                 printf("part.offset = 0x%08x\n",(unsigned int)part.offset);
88                 printf("part.size   = 0x%08x\n",(unsigned int)part.size);
89         }
90
91         /* secondary OS+firmware partition                                  */
92         if(part_num==2){
93                 memset(&part, 0, sizeof(part));
94
95                 part.offset=(char*)0x00140000;
96                 part.size=8*1024*1024;
97
98                 /* Mark the struct as ready */
99                 current_part = part_num;
100
101                 printf("part.offset = 0x%08x\n",(unsigned int)part.offset);
102                 printf("part.size   = 0x%08x\n",(unsigned int)part.size);
103         }
104
105         if (current_part == part_num) {
106                 part.usr_priv = &current_part;
107                 part.jffs2_priv = jffs2_priv_saved;
108                 return &part;
109         }
110
111         printf("jffs2_part_info: end of partition table\n");
112         return 0;
113 }
114 #endif
115
116
117 /*-----------------------------------------------------------------------
118  */
119 unsigned long flash_init (void)
120 {
121         int i;
122         ulong size = 0;
123
124         for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
125                 switch (i) {
126                 case 0:
127                         flash_get_size ((long *) PHYS_FLASH_1, &flash_info[i]);
128                         flash_get_offsets (PHYS_FLASH_1, &flash_info[i]);
129                         break;
130                 case 1:
131                         flash_get_size ((long *) PHYS_FLASH_2, &flash_info[i]);
132                         flash_get_offsets (PHYS_FLASH_2, &flash_info[i]);
133                         break;
134                 default:
135                         panic ("configured too many flash banks!\n");
136                         break;
137                 }
138                 size += flash_info[i].size;
139         }
140
141         /* Protect monitor and environment sectors */
142         flash_protect ( FLAG_PROTECT_SET,CFG_FLASH_BASE,CFG_FLASH_BASE + monitor_flash_len - 1,&flash_info[0] );
143         flash_protect ( FLAG_PROTECT_SET,CFG_ENV_ADDR,CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0] );
144
145         return size;
146 }
147
148 /*-----------------------------------------------------------------------
149  */
150 static void flash_get_offsets (ulong base, flash_info_t *info)
151 {
152         int i;
153
154         if (info->flash_id == FLASH_UNKNOWN) return;
155
156         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) {
157                 for (i = 0; i < info->sector_count; i++) {
158                         info->start[i] = base + (i * PHYS_FLASH_SECT_SIZE);
159                         info->protect[i] = 0;
160                 }
161         }
162 }
163
164 /*-----------------------------------------------------------------------
165  */
166 void flash_print_info  (flash_info_t *info)
167 {
168         int i;
169
170         if (info->flash_id == FLASH_UNKNOWN) {
171                 printf ("missing or unknown FLASH type\n");
172                 return;
173         }
174
175         switch (info->flash_id & FLASH_VENDMASK) {
176         case FLASH_MAN_AMD:     printf ("AMD ");                break;
177         case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
178         default:                printf ("Unknown Vendor ");     break;
179         }
180
181         switch (info->flash_id & FLASH_TYPEMASK) {
182         case FLASH_AMLV128U:    printf ("AM29LV128ML (128Mbit, uniform sector size)\n");
183                                 break;
184         case FLASH_AMLV320U:    printf ("AM29LV320ML (32Mbit, uniform sector size)\n");
185                                 break;
186         case FLASH_AMLV640U:    printf ("AM29LV640ML (64Mbit, uniform sector size)\n");
187                                 break;
188         case FLASH_AMLV320B:    printf ("AM29LV320MB (32Mbit, bottom boot sect)\n");
189                                 break;
190         default:                printf ("Unknown Chip Type\n");
191                                 break;
192         }
193
194         printf ("  Size: %ld MB in %d Sectors\n",
195                 info->size >> 20, info->sector_count);
196
197         printf ("  Sector Start Addresses:");
198         for (i=0; i<info->sector_count; ++i) {
199                 if ((i % 5) == 0)
200                         printf ("\n   ");
201                 printf (" %08lX%s",
202                         info->start[i],
203                         info->protect[i] ? " (RO)" : "     "
204                 );
205         }
206         printf ("\n");
207         return;
208 }
209
210 /*
211  * The following code cannot be run from FLASH!
212  */
213 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
214 {
215         short i;
216         ulong value;
217         ulong base = (ulong)addr;
218
219         /* Write auto select command: read Manufacturer ID */
220         addr[0x0555] = 0x00AA00AA;
221         addr[0x02AA] = 0x00550055;
222         addr[0x0555] = 0x00900090;
223
224         value = addr[0];
225
226         debug ("Manuf. ID @ 0x%08lx: 0x%08lx\n", (ulong)addr, value);
227
228         switch (value) {
229         case AMD_MANUFACT:
230                 debug ("Manufacturer: AMD\n");
231                 info->flash_id = FLASH_MAN_AMD;
232                 break;
233         case FUJ_MANUFACT:
234                 debug ("Manufacturer: FUJITSU\n");
235                 info->flash_id = FLASH_MAN_FUJ;
236                 break;
237         default:
238                 debug ("Manufacturer: *** unknown ***\n");
239                 info->flash_id = FLASH_UNKNOWN;
240                 info->sector_count = 0;
241                 info->size = 0;
242                 return (0);                     /* no or unknown flash  */
243         }
244
245         value = addr[1];                        /* device ID            */
246
247         debug ("Device ID @ 0x%08lx: 0x%08lx\n", (ulong)(&addr[1]), value);
248
249         switch (value) {
250
251         case AMD_ID_MIRROR:
252                 debug ("Mirror Bit flash: addr[14] = %08lX  addr[15] = %08lX\n",
253                         addr[14], addr[15]);
254                 switch(addr[14]) {
255                 case AMD_ID_LV128U_2:
256                         if (addr[15] != AMD_ID_LV128U_3) {
257                                 debug ("Chip: AMLV128U -> unknown\n");
258                                 info->flash_id = FLASH_UNKNOWN;
259                         } else {
260                                 debug ("Chip: AMLV128U\n");
261                                 info->flash_id += FLASH_AMLV128U;
262                                 info->sector_count = 256;
263                                 info->size = 0x02000000;
264                         }
265                         break;                          /* => 32 MB     */
266                 case AMD_ID_LV640U_2:
267                         if (addr[15] != AMD_ID_LV640U_3) {
268                                 debug ("Chip: AMLV640U -> unknown\n");
269                                 info->flash_id = FLASH_UNKNOWN;
270                         } else {
271                                 debug ("Chip: AMLV640U\n");
272                                 info->flash_id += FLASH_AMLV640U;
273                                 info->sector_count = 128;
274                                 info->size = 0x01000000;
275                         }
276                         break;                          /* => 16 MB     */
277                 case AMD_ID_LV320B_2:
278                         if (addr[15] != AMD_ID_LV320B_3) {
279                                 debug ("Chip: AMLV320B -> unknown\n");
280                                 info->flash_id = FLASH_UNKNOWN;
281                         } else {
282                                 debug ("Chip: AMLV320B\n");
283                                 info->flash_id += FLASH_AMLV320B;
284                                 info->sector_count = 71;
285                                 info->size = 0x00800000;
286                         }
287                         break;                          /* =>  8 MB     */
288                 default:
289                         debug ("Chip: *** unknown ***\n");
290                         info->flash_id = FLASH_UNKNOWN;
291                         break;
292                 }
293                 break;
294
295         default:
296                 info->flash_id = FLASH_UNKNOWN;
297                 return (0);                     /* => no or unknown flash */
298         }
299
300         /* set up sector start address table */
301         switch (value) {
302         case AMD_ID_MIRROR:
303                 switch (info->flash_id & FLASH_TYPEMASK) {
304                 /* only known types here - no default */
305                 case FLASH_AMLV128U:
306                 case FLASH_AMLV640U:
307                 case FLASH_AMLV320U:
308                         for (i = 0; i < info->sector_count; i++) {
309                                 info->start[i] = base;
310                                 base += 0x20000;
311                         }
312                         break;
313                 case FLASH_AMLV320B:
314                         for (i = 0; i < info->sector_count; i++) {
315                                 info->start[i] = base;
316                                 /*
317                                  * The first 8 sectors are 8 kB,
318                                  * all the other ones  are 64 kB
319                                  */
320                                 base += (i < 8)
321                                         ?  2 * ( 8 << 10)
322                                         :  2 * (64 << 10);
323                         }
324                         break;
325                 }
326                 break;
327
328         default:
329                 return (0);
330                 break;
331         }
332
333 #if 0
334         /* check for protected sectors */
335         for (i = 0; i < info->sector_count; i++) {
336                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
337                 /* D0 = 1 if protected */
338                 addr = (volatile unsigned long *)(info->start[i]);
339                 info->protect[i] = addr[2] & 1;
340         }
341 #endif
342
343         /*
344          * Prevent writes to uninitialized FLASH.
345          */
346         if (info->flash_id != FLASH_UNKNOWN) {
347                 addr = (volatile unsigned long *)info->start[0];
348
349                 *addr = 0x00F000F0;     /* reset bank */
350         }
351
352         return (info->size);
353 }
354
355
356 /*-----------------------------------------------------------------------
357  */
358
359 int     flash_erase (flash_info_t *info, int s_first, int s_last)
360 {
361         vu_long *addr = (vu_long*)(info->start[0]);
362         int flag, prot, sect, l_sect;
363         ulong start, now, last;
364
365         debug ("flash_erase: first: %d last: %d\n", s_first, s_last);
366
367         if ((s_first < 0) || (s_first > s_last)) {
368                 if (info->flash_id == FLASH_UNKNOWN) {
369                         printf ("- missing\n");
370                 } else {
371                         printf ("- no sectors to erase\n");
372                 }
373                 return 1;
374         }
375
376         if ((info->flash_id == FLASH_UNKNOWN) ||
377             (info->flash_id > FLASH_AMD_COMP)) {
378                 printf ("Can't erase unknown flash type %08lx - aborted\n",
379                         info->flash_id);
380                 return 1;
381         }
382
383         prot = 0;
384         for (sect=s_first; sect<=s_last; ++sect) {
385                 if (info->protect[sect]) {
386                         prot++;
387                 }
388         }
389
390         if (prot) {
391                 printf ("- Warning: %d protected sectors will not be erased!\n",
392                         prot);
393         } else {
394                 printf ("\n");
395         }
396
397         l_sect = -1;
398
399         /* Disable interrupts which might cause a timeout here */
400         flag = disable_interrupts();
401
402         addr[0x0555] = 0x00AA00AA;
403         addr[0x02AA] = 0x00550055;
404         addr[0x0555] = 0x00800080;
405         addr[0x0555] = 0x00AA00AA;
406         addr[0x02AA] = 0x00550055;
407
408         /* Start erase on unprotected sectors */
409         for (sect = s_first; sect<=s_last; sect++) {
410                 if (info->protect[sect] == 0) { /* not protected */
411                         addr = (vu_long*)(info->start[sect]);
412                         addr[0] = 0x00300030;
413                         l_sect = sect;
414                 }
415         }
416
417         /* re-enable interrupts if necessary */
418         if (flag)
419                 enable_interrupts();
420
421         /* wait at least 80us - let's wait 1 ms */
422         udelay (1000);
423
424         /*
425          * We wait for the last triggered sector
426          */
427         if (l_sect < 0)
428                 goto DONE;
429
430         start = get_timer (0);
431         last  = start;
432         addr = (vu_long*)(info->start[l_sect]);
433         while ((addr[0] & 0x00800080) != 0x00800080) {
434                 if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
435                         printf ("Timeout\n");
436                         return 1;
437                 }
438                 /* show that we're waiting */
439                 if ((now - last) > 100000) {    /* every second */
440                         putc ('.');
441                         last = now;
442                 }
443         }
444
445 DONE:
446         /* reset to read mode */
447         addr = (volatile unsigned long *)info->start[0];
448         addr[0] = 0x00F000F0;   /* reset bank */
449
450         printf (" done\n");
451         return 0;
452 }
453
454 /*-----------------------------------------------------------------------
455  * Copy memory to flash, returns:
456  * 0 - OK
457  * 1 - write timeout
458  * 2 - Flash not erased
459  */
460
461 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
462 {
463         ulong cp, wp, data;
464         int i, l, rc;
465
466         wp = (addr & ~3);       /* get lower word aligned address */
467
468         /*
469          * handle unaligned start bytes
470          */
471         if ((l = addr - wp) != 0) {
472                 data = 0;
473                 for (i=0, cp=wp; i<l; ++i, ++cp) {
474                         data = (data << 8) | (*(uchar *)cp);
475                 }
476                 for (; i<4 && cnt>0; ++i) {
477                         data = (data << 8) | *src++;
478                         --cnt;
479                         ++cp;
480                 }
481                 for (; cnt==0 && i<4; ++i, ++cp) {
482                         data = (data << 8) | (*(uchar *)cp);
483                 }
484
485                 if ((rc = write_word(info, wp, SWAP(data))) != 0) {
486                         return (rc);
487                 }
488                 wp += 4;
489         }
490
491         /*
492          * handle word aligned part
493          */
494         while (cnt >= 4) {
495                 data = 0;
496                 for (i=0; i<4; ++i) {
497                         data = (data << 8) | *src++;
498                 }
499                 if ((rc = write_word(info, wp, SWAP(data))) != 0) {
500                         return (rc);
501                 }
502                 wp  += 4;
503                 cnt -= 4;
504         }
505
506         if (cnt == 0) {
507                 return (0);
508         }
509
510         /*
511          * handle unaligned tail bytes
512          */
513         data = 0;
514         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
515                 data = (data << 8) | *src++;
516                 --cnt;
517         }
518         for (; i<4; ++i, ++cp) {
519                 data = (data << 8) | (*(uchar *)cp);
520         }
521
522         return (write_word(info, wp, SWAP(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         vu_long *addr = (vu_long*)(info->start[0]);
534         ulong start;
535         ulong rev;
536         int flag;
537         int i;
538
539         /* Check if Flash is (sufficiently) erased */
540         if ((*((vu_long *)dest) & data) != data) {
541                 return (2);
542         }
543
544         /* Disable interrupts which might cause a timeout here */
545         flag = disable_interrupts();
546
547         addr[0x0555] = 0x00AA00AA;
548         addr[0x02AA] = 0x00550055;
549         addr[0x0555] = 0x00A000A0;
550
551         *((vu_long *)dest) = data;
552
553         /* re-enable interrupts if necessary */
554         if (flag)
555                 enable_interrupts();
556
557         /* data polling for D7 */
558         start = get_timer (0);
559         while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
560                 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
561                         return (1);
562                 }
563         }
564         return (0);
565 }