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