]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/sandburst/common/flash.c
c65cb9607068294ff52e841c7e58d122728ef6d8
[karo-tx-uboot.git] / board / sandburst / common / flash.c
1 /*
2  * (C) Copyright 2002-2005
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * (C) Copyright 2002 Jun Gu <jung@artesyncp.com>
6  * Add support for Am29F016D and dynamic switch setting.
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  * Ported from Ebony flash support
28  * Travis B. Sawyer
29  * Sandburst Corporation
30  */
31 #include <common.h>
32 #include <asm/ppc4xx.h>
33 #include <asm/processor.h>
34
35
36 #undef DEBUG
37 #ifdef DEBUG
38 #define DEBUGF(x...) printf(x)
39 #else
40 #define DEBUGF(x...)
41 #endif /* DEBUG */
42
43
44 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips    */
45
46 static unsigned long flash_addr_table[8][CONFIG_SYS_MAX_FLASH_BANKS] = {
47         {0xfff80000}    /* Boot Flash */
48 };
49
50 /*-----------------------------------------------------------------------
51  * Functions
52  */
53 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
54 static int write_word (flash_info_t *info, ulong dest, ulong data);
55
56
57 #define ADDR0           0x5555
58 #define ADDR1           0x2aaa
59 #define FLASH_WORD_SIZE unsigned char
60
61
62 /*-----------------------------------------------------------------------
63  */
64
65 unsigned long flash_init (void)
66 {
67         unsigned long total_b = 0;
68         unsigned long size_b[CONFIG_SYS_MAX_FLASH_BANKS];
69         unsigned short index = 0;
70         int i;
71
72
73         DEBUGF("\n");
74         DEBUGF("FLASH: Index: %d\n", index);
75
76         /* Init: no FLASHes known */
77         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
78                 flash_info[i].flash_id = FLASH_UNKNOWN;
79                 flash_info[i].sector_count = -1;
80                 flash_info[i].size = 0;
81
82                 /* check whether the address is 0 */
83                 if (flash_addr_table[index][i] == 0) {
84                         continue;
85                 }
86
87                 /* call flash_get_size() to initialize sector address */
88                 size_b[i] = flash_get_size(
89                         (vu_long *)flash_addr_table[index][i], &flash_info[i]);
90                 flash_info[i].size = size_b[i];
91                 if (flash_info[i].flash_id == FLASH_UNKNOWN) {
92                         printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
93                                 i, size_b[i], size_b[i]<<20);
94                         flash_info[i].sector_count = -1;
95                         flash_info[i].size = 0;
96                 }
97
98                 total_b += flash_info[i].size;
99         }
100
101         return total_b;
102 }
103
104
105 /*-----------------------------------------------------------------------
106  */
107 void flash_print_info  (flash_info_t *info)
108 {
109         int i;
110         int k;
111         int size;
112         int erased;
113         volatile unsigned long *flash;
114
115         if (info->flash_id == FLASH_UNKNOWN) {
116                 printf ("missing or unknown FLASH type\n");
117                 return;
118         }
119
120         switch (info->flash_id & FLASH_VENDMASK) {
121         case FLASH_MAN_AMD:     printf ("AMD ");                break;
122         default:                printf ("Unknown Vendor ");     break;
123         }
124
125         switch (info->flash_id & FLASH_TYPEMASK) {
126         case FLASH_AM040:       printf ("AM29F040 (512 Kbit, uniform sector size)\n");
127                 break;
128         default:                printf ("Unknown Chip Type\n");
129                 break;
130         }
131
132         printf ("  Size: %ld KB in %d Sectors\n",
133                 info->size >> 10, info->sector_count);
134
135         printf ("  Sector Start Addresses:");
136         for (i=0; i<info->sector_count; ++i) {
137                 /*
138                  * Check if whole sector is erased
139                  */
140                 if (i != (info->sector_count-1))
141                         size = info->start[i+1] - info->start[i];
142                 else
143                         size = info->start[0] + info->size - info->start[i];
144                 erased = 1;
145                 flash = (volatile unsigned long *)info->start[i];
146                 size = size >> 2;        /* divide by 4 for longword access */
147                 for (k=0; k<size; k++)
148                 {
149                         if (*flash++ != 0xffffffff)
150                         {
151                                 erased = 0;
152                                 break;
153                         }
154                 }
155
156                 if ((i % 5) == 0)
157                         printf ("\n   ");
158                         printf (" %08lX%s%s",
159                                 info->start[i],
160                                 erased ? " E" : "  ",
161                                 info->protect[i] ? "RO " : "   "
162                                 );
163                         }
164                 printf ("\n");
165                 return;
166         }
167
168 /*-----------------------------------------------------------------------
169  */
170
171
172 /*-----------------------------------------------------------------------
173  */
174
175 /*
176  * The following code cannot be run from FLASH!
177  */
178 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
179 {
180         short i;
181         FLASH_WORD_SIZE value;
182         ulong base = (ulong)addr;
183         volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr;
184
185         DEBUGF("FLASH ADDR: %08x\n", (unsigned)addr );
186
187         /* Write auto select command: read Manufacturer ID */
188         udelay(10000);
189         addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
190         udelay(1000);
191         addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
192         udelay(1000);
193         addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090;
194         udelay(1000);
195
196         value = addr2[0];
197
198         DEBUGF("FLASH MANUFACT: %x\n", value);
199
200         switch (value) {
201         case (FLASH_WORD_SIZE)AMD_MANUFACT:
202                 info->flash_id = FLASH_MAN_AMD;
203                 break;
204         default:
205                 info->flash_id = FLASH_UNKNOWN;
206                 info->sector_count = 0;
207                 info->size = 0;
208                 return (0);                     /* no or unknown flash  */
209         }
210
211         value = addr2[1];                       /* device ID            */
212
213         DEBUGF("\nFLASH DEVICEID: %x\n", value);
214
215         switch (value) {
216         case (FLASH_WORD_SIZE)AMD_ID_LV040B:
217                 info->flash_id += FLASH_AM040;
218                 info->sector_count = 8;
219                 info->size = 0x00080000; /* => 512 kb */
220                 break;
221
222         default:
223                 info->flash_id = FLASH_UNKNOWN;
224                 return (0);                     /* => no or unknown flash */
225
226         }
227
228         /* set up sector start address table */
229         if (info->flash_id  == FLASH_AM040) {
230                 for (i = 0; i < info->sector_count; i++)
231                         info->start[i] = base + (i * 0x00010000);
232         } else {
233                 if (info->flash_id & FLASH_BTYPE) {
234                         /* set sector offsets for bottom boot block type        */
235                         info->start[0] = base + 0x00000000;
236                         info->start[1] = base + 0x00004000;
237                         info->start[2] = base + 0x00006000;
238                         info->start[3] = base + 0x00008000;
239                         for (i = 4; i < info->sector_count; i++) {
240                                 info->start[i] = base + (i * 0x00010000) - 0x00030000;
241                         }
242                 } else {
243                         /* set sector offsets for top boot block type           */
244                         i = info->sector_count - 1;
245                         info->start[i--] = base + info->size - 0x00004000;
246                         info->start[i--] = base + info->size - 0x00006000;
247                         info->start[i--] = base + info->size - 0x00008000;
248                         for (; i >= 0; i--) {
249                                 info->start[i] = base + i * 0x00010000;
250                         }
251                 }
252         }
253
254         /* check for protected sectors */
255         for (i = 0; i < info->sector_count; i++) {
256                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
257                 /* D0 = 1 if protected */
258                 addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]);
259                 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST)
260                         info->protect[i] = 0;
261                 else
262                         info->protect[i] = addr2[2] & 1;
263         }
264
265         /* reset to return to reading data */
266         addr2[0] = (FLASH_WORD_SIZE) 0x00F000F0;        /* reset bank */
267
268         /*
269          * Prevent writes to uninitialized FLASH.
270          */
271         if (info->flash_id != FLASH_UNKNOWN) {
272                 addr2 = (FLASH_WORD_SIZE *)info->start[0];
273                 *addr2 = (FLASH_WORD_SIZE)0x00F000F0;   /* reset bank */
274         }
275
276         return (info->size);
277 }
278
279 int wait_for_DQ7(flash_info_t *info, int sect)
280 {
281         ulong start, now, last;
282         volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);
283
284         start = get_timer (0);
285         last  = start;
286         while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
287                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
288                         printf ("Timeout\n");
289                         return -1;
290                 }
291                 /* show that we're waiting */
292                 if ((now - last) > 1000) {  /* every second */
293                         putc ('.');
294                         last = now;
295                 }
296         }
297         return 0;
298 }
299
300 /*-----------------------------------------------------------------------
301  */
302
303 int flash_erase (flash_info_t *info, int s_first, int s_last)
304 {
305         volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
306         volatile FLASH_WORD_SIZE *addr2;
307         int flag, prot, sect, l_sect;
308         int i;
309
310         if ((s_first < 0) || (s_first > s_last)) {
311                 if (info->flash_id == FLASH_UNKNOWN) {
312                         printf ("- missing\n");
313                 } else {
314                         printf ("- no sectors to erase\n");
315                 }
316                 return 1;
317         }
318
319         if (info->flash_id == FLASH_UNKNOWN) {
320                 printf ("Can't erase unknown flash type - aborted\n");
321                 return 1;
322         }
323
324         prot = 0;
325         for (sect=s_first; sect<=s_last; ++sect) {
326                 if (info->protect[sect]) {
327                         prot++;
328                 }
329         }
330
331         if (prot) {
332                 printf ("- Warning: %d protected sectors will not be erased!\n",
333                         prot);
334         } else {
335                 printf ("\n");
336         }
337
338         l_sect = -1;
339
340         /* Disable interrupts which might cause a timeout here */
341         flag = disable_interrupts();
342
343         /* Start erase on unprotected sectors */
344         for (sect = s_first; sect<=s_last; sect++) {
345                 if (info->protect[sect] == 0) { /* not protected */
346                         addr2 = (FLASH_WORD_SIZE *)(info->start[sect]);
347                         DEBUGF("Erasing sector %p\n", addr2);
348
349                         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
350                                 addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
351                                 addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
352                                 addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
353                                 addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
354                                 addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
355                                 addr2[0] = (FLASH_WORD_SIZE)0x00500050;  /* block erase */
356                                 for (i=0; i<50; i++)
357                                         udelay(1000);  /* wait 1 ms */
358                         } else {
359                                 addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
360                                 addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
361                                 addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
362                                 addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
363                                 addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
364                                 addr2[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */
365                         }
366                         l_sect = sect;
367                         /*
368                          * Wait for each sector to complete, it's more
369                          * reliable.  According to AMD Spec, you must
370                          * issue all erase commands within a specified
371                          * timeout.  This has been seen to fail, especially
372                          * if printf()s are included (for debug)!!
373                          */
374                         wait_for_DQ7(info, sect);
375                 }
376         }
377
378         /* re-enable interrupts if necessary */
379         if (flag)
380                 enable_interrupts();
381
382         /* wait at least 80us - let's wait 1 ms */
383         udelay (1000);
384
385         /* reset to read mode */
386         addr = (FLASH_WORD_SIZE *)info->start[0];
387         addr[0] = (FLASH_WORD_SIZE)0x00F000F0;  /* reset bank */
388
389         printf (" done\n");
390         return 0;
391 }
392
393 /*-----------------------------------------------------------------------
394  * Copy memory to flash, returns:
395  * 0 - OK
396  * 1 - write timeout
397  * 2 - Flash not erased
398  */
399
400 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
401 {
402         ulong cp, wp, data;
403         int i, l, rc;
404
405         wp = (addr & ~3);       /* get lower word aligned address */
406
407         /*
408          * handle unaligned start bytes
409          */
410         if ((l = addr - wp) != 0) {
411                 data = 0;
412                 for (i=0, cp=wp; i<l; ++i, ++cp) {
413                         data = (data << 8) | (*(uchar *)cp);
414                 }
415                 for (; i<4 && cnt>0; ++i) {
416                         data = (data << 8) | *src++;
417                         --cnt;
418                         ++cp;
419                 }
420                 for (; cnt==0 && i<4; ++i, ++cp) {
421                         data = (data << 8) | (*(uchar *)cp);
422                 }
423
424                 if ((rc = write_word(info, wp, data)) != 0) {
425                         return (rc);
426                 }
427                 wp += 4;
428         }
429
430         /*
431          * handle word aligned part
432          */
433         while (cnt >= 4) {
434                 data = 0;
435                 for (i=0; i<4; ++i) {
436                         data = (data << 8) | *src++;
437                 }
438                 if ((rc = write_word(info, wp, data)) != 0) {
439                         return (rc);
440                 }
441                 wp  += 4;
442                 cnt -= 4;
443         }
444
445         if (cnt == 0) {
446                 return (0);
447         }
448
449         /*
450          * handle unaligned tail bytes
451          */
452         data = 0;
453         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
454                 data = (data << 8) | *src++;
455                 --cnt;
456         }
457         for (; i<4; ++i, ++cp) {
458                 data = (data << 8) | (*(uchar *)cp);
459         }
460
461         return (write_word(info, wp, data));
462 }
463
464 /*-----------------------------------------------------------------------
465  * Write a word to Flash, returns:
466  * 0 - OK
467  * 1 - write timeout
468  * 2 - Flash not erased
469  */
470 static int write_word (flash_info_t * info, ulong dest, ulong data)
471 {
472         volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) (info->start[0]);
473         volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *) dest;
474         volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data;
475         ulong start;
476         int i;
477
478         /* Check if Flash is (sufficiently) erased */
479         if ((*((volatile FLASH_WORD_SIZE *) dest) &
480              (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) {
481                 return (2);
482         }
483
484         for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++) {
485                 int flag;
486
487                 /* Disable interrupts which might cause a timeout here */
488                 flag = disable_interrupts ();
489
490                 addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
491                 addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
492                 addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00A000A0;
493
494                 dest2[i] = data2[i];
495
496                 /* re-enable interrupts if necessary */
497                 if (flag)
498                         enable_interrupts ();
499
500                 /* data polling for D7 */
501                 start = get_timer (0);
502                 while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) !=
503                        (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) {
504
505                         if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
506                                 return (1);
507                         }
508                 }
509         }
510
511         return (0);
512 }