]> git.sur5r.net Git - u-boot/blob - board/adderII/flash.c
Patches by Pantelis Antoniou, 16 Apr 2004:
[u-boot] / board / adderII / flash.c
1 /*
2  * (C) Copyright 2000-2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23 /******************************************************************************
24 ** Notes: AM29LV320DB - 90EI ( 32 Mbit device )
25 ** Sectors - Eight 8 Kb sector
26 **         - Sixty three 64 Kb sector
27 ** Bottom boot sector
28 ******************************************************************************/
29 #include <common.h>
30 #include <mpc8xx.h>
31
32
33 /******************************************************************************
34 **      Defines
35 ******************************************************************************/
36 #ifdef CONFIG_ADDERII
37
38 #define ADDR0   0x0555
39 #define ADDR1   0x02AA
40 #define FLASH_WORD_SIZE unsigned short
41
42 #endif
43
44 #if defined( CFG_ENV_IS_IN_FLASH )
45 # ifndef  CFG_ENV_ADDR
46 #  define CFG_ENV_ADDR  ( CFG_FLASH_BASE + CFG_ENV_OFFSET )
47 # endif
48 # ifndef  CFG_ENV_SIZE
49 #  define CFG_ENV_SIZE  CFG_ENV_SECT_SIZE
50 # endif
51 # ifndef  CFG_ENV_SECT_SIZE
52 #  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
53 # endif
54 #endif
55
56 /******************************************************************************
57 **      Global Parameters
58 ******************************************************************************/
59 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
60
61 /******************************************************************************
62 **      Function Prototypes
63 ******************************************************************************/
64 static ulong flash_get_size( vu_long *addr, flash_info_t *info );
65
66 static int write_word( flash_info_t *info, ulong dest, ulong data );
67
68 static void flash_get_offsets( ulong base, flash_info_t *info );
69
70 int wait_for_DQ7( flash_info_t *info, int sect );
71
72 /******************************************************************************
73 ** Function :   flash_init
74 ** Param    :   void
75 ** Notes    :   Initializes the Flash Chip
76 ******************************************************************************/
77 ulong flash_init (void)
78 {
79         ulong size_b0 = -1;
80         int i;
81         volatile immap_t *immap = (immap_t *) CFG_IMMR;
82         volatile memctl8xx_t *memctl = &immap->im_memctl;
83
84         /* Set Flash to unknown */
85         for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
86                 flash_info[i].flash_id = FLASH_UNKNOWN;
87         }
88
89         /* Get the Flash Bank Size */
90
91         size_b0 = flash_get_size ((vu_long *) (CFG_FLASH_BASE),
92                                   &flash_info[0]);
93
94         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
95                 printf ("## UNKNOWN Flash on Bank 0 - Size = 0x%08lx = %ldMB\n",
96                         size_b0, size_b0 >> 20);
97         }
98
99         /* Remap Flash according to size detected  */
100         memctl->memc_or0 = 0xFF800774;
101         memctl->memc_br0 = CFG_BR0_PRELIM;
102
103         /* Setup Flash Sector Offsets */
104
105         flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
106
107         /* Monitor Protection ON - default */
108
109 #if ( CFG_MONITOR_BASE >= CFG_FLASH_BASE  )
110         flash_protect (FLAG_PROTECT_SET, CFG_MONITOR_BASE,
111                        (CFG_MONITOR_BASE + monitor_flash_len - 1),
112                        &flash_info[0]);
113 #endif
114
115         /* Protect Environment Variables */
116 #ifdef CFG_ENV_IS_IN_FLASH
117         flash_protect (FLAG_PROTECT_SET, CFG_ENV_ADDR,
118                        (CFG_ENV_ADDR + CFG_ENV_SIZE - 1), &flash_info[0]);
119 #endif
120
121         return size_b0;
122 }
123
124 /******************************************************************************
125 ** Function : flash_get_offsets
126 ** Param    : ulong base, flash_into_t *info
127 ** Notes    :
128 ******************************************************************************/
129 static void flash_get_offsets (ulong base, flash_info_t * info)
130 {
131         return;
132 }
133
134
135 /******************************************************************************
136 ** Function : flash_print_info
137 ** Param    : flash_info_t
138 ** Notes    :
139 ******************************************************************************/
140 void flash_print_info (flash_info_t * info)
141 {
142         int i;
143
144         if (info->flash_id == FLASH_UNKNOWN) {
145                 printf ("Missing or unknown flash type\n");
146                 return;
147         }
148
149         switch (info->flash_id & FLASH_VENDMASK) {
150         case FLASH_MAN_AMD:
151                 printf ("AMD ");
152                 break;
153         case FLASH_MAN_FUJ:
154                 printf ("FUJITSU ");
155                 break;
156         case FLASH_MAN_BM:
157                 printf ("BRIGHT MICRO ");
158                 break;
159         default:
160                 printf ("Unknown Vendor ");
161                 break;
162         }
163
164         switch (info->flash_id & FLASH_TYPEMASK) {
165         case FLASH_AM320B:
166                 printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
167                 break;
168         case FLASH_AM320T:
169                 printf ("AM29LV320T (32 Mbit, top boot sector)\n");
170                 break;
171         default:
172                 printf ("Unknown Chip Type\n");
173                 break;
174
175         }
176
177         printf ("  Size: %ld MB in %d Sectors\n", info->size >> 20,
178                 info->sector_count);
179         printf ("  Sector Start Addresses:");
180
181         for (i = 0; i < info->sector_count; ++i) {
182                 if ((i % 5) == 0) {
183                         printf ("\n   ");
184                 }
185                 printf (" %08lX%s",
186                         info->start[i],
187                         info->protect[i] ? " (RO)" : "     ");
188         }
189         printf ("\n");
190         return;
191 }
192
193 /******************************************************************************
194 ** Function : flash_get_size
195 ** Param    : vu_long *addr, flash_info_t *info
196 ** Notes    :
197 ******************************************************************************/
198 static ulong flash_get_size (vu_long * addr, flash_info_t * info)
199 {
200         short i;
201         FLASH_WORD_SIZE manu_id, dev_id;
202         ulong base = (ulong) addr;
203         volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) addr;
204
205         /* Write Auto Select Command and read Manufacturer's ID and Dev ID */
206
207         addr2[ADDR0] = (FLASH_WORD_SIZE) 0xAAAAAAAA;
208         addr2[ADDR1] = (FLASH_WORD_SIZE) 0x55555555;
209         addr2[ADDR0] = (FLASH_WORD_SIZE) 0x90909090;
210
211         manu_id = addr2[0];
212
213         switch (manu_id) {
214         case (FLASH_WORD_SIZE) AMD_MANUFACT:
215                 info->flash_id = FLASH_MAN_AMD;
216                 break;
217
218         default:
219                 info->flash_id = FLASH_UNKNOWN;
220                 info->sector_count = 0;
221                 info->size = 0;
222                 break;
223         }
224
225         /* Read Device Id */
226         dev_id = addr2[1];
227
228         switch (dev_id) {
229         case (FLASH_WORD_SIZE) AMD_ID_LV320B:
230                 info->flash_id += FLASH_AM320B;
231                 info->sector_count = 71;        /* 8 - boot sec + 63 normal */
232                 info->size = 0x400000;  /* 4MByte */
233                 break;
234
235         default:
236                 info->flash_id = FLASH_UNKNOWN;
237                 break;
238         }
239
240         /* Set up sector start Addresses */
241
242         if (info->flash_id & FLASH_BTYPE) {
243                 /* set sector offsets for bottom boot block
244                  ** Eight 8 Kb Boot sectors
245                  ** Sixty Three 64Kb sectors
246                  */
247                 for (i = 0; i < 8; i++) {
248                         info->start[i] = base + (i * 0x00002000);
249                 }
250                 for (i = 8; i < info->sector_count; i++) {
251                         info->start[i] = base + (i * 0x00010000) - 0x00070000;
252                 }
253         }
254
255         /* Reset To read mode */
256
257         if (info->flash_id != FLASH_UNKNOWN) {
258                 addr = (ulong *) info->start[0];
259                 *addr = 0xF0F0F0F0;
260         }
261         return (info->size);
262 }
263
264 /*******************************************************************************
265 ** Function : flash_erase
266 ** Param    : flash_info_t *info, int s_first, int s_last
267 ** Notes    :
268 ******************************************************************************/
269 int flash_erase (flash_info_t * info, int s_first, int s_last)
270 {
271         volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *) (info->start[0]);
272         volatile FLASH_WORD_SIZE *addr2;
273         int flag, prot, sect, l_sect;
274         int i;
275
276         if ((s_first < 0) || (s_first > s_last)) {
277                 if (info->flash_id == FLASH_UNKNOWN) {
278                         printf ("- missing\n");
279                 } else {
280                         printf ("- no sectors to erase\n");
281                 }
282                 return 1;
283         }
284
285         if (info->flash_id == FLASH_UNKNOWN) {
286                 printf ("Can't erase unknown flash type - aborted\n");
287                 return 1;
288         }
289
290         prot = 0;
291         for (sect = s_first; sect <= s_last; ++sect) {
292                 if (info->protect[sect]) {
293                         prot++;
294                 }
295         }
296
297         if (prot) {
298                 printf ("Warning: %d protected sectors will not be erased!\n",
299                         prot);
300         } else {
301                 printf ("\n");
302         }
303
304         l_sect = -1;
305
306         /* Disable interrupts which might cause a timeout here */
307         flag = disable_interrupts ();
308
309         /* Start erase on unprotected sectors */
310         for (sect = s_first; sect <= s_last; sect++) {
311
312                 if (info->protect[sect] == 0) { /* not protected */
313                         addr2 = (FLASH_WORD_SIZE *) (info->start[sect]);
314
315                         if ((info->flash_id & FLASH_VENDMASK) ==
316                             FLASH_MAN_SST) {
317                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
318                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
319                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00800080;
320                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
321                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
322                                 addr2[0] = (FLASH_WORD_SIZE) 0x00500050;        /* block erase */
323                                 for (i = 0; i < 50; i++)
324                                         udelay (1000);  /* wait 1 ms */
325                         } else {
326                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
327                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
328                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00800080;
329                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
330                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
331                                 addr2[0] = (FLASH_WORD_SIZE) 0x00300030;        /* sector erase */
332                         }
333                         l_sect = sect;
334                         /*
335                          * Wait for each sector to complete, it's more
336                          * reliable.  According to AMD Spec, you must
337                          * issue all erase commands within a specified
338                          * timeout.  This has been seen to fail, especially
339                          * if printf()s are included (for debug)!!
340                          */
341                         wait_for_DQ7 (info, sect);
342                 }
343         }
344         /* re-enable interrupts if necessary */
345         if (flag)
346                 enable_interrupts ();
347
348         /* wait at least 80us - let's wait 1 ms */
349         udelay (1000);
350
351         /* reset to read mode */
352         addr = (FLASH_WORD_SIZE *) info->start[0];
353         addr[0] = (FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */
354
355         printf (" done\n");
356         return 0;
357 }
358
359 int wait_for_DQ7 (flash_info_t * info, int sect)
360 {
361         ulong start, now, last;
362         volatile FLASH_WORD_SIZE *addr =
363                 (FLASH_WORD_SIZE *) (info->start[sect]);
364
365         start = get_timer (0);
366         last = start;
367         while ((addr[0] & (FLASH_WORD_SIZE) 0x00800080) !=
368                (FLASH_WORD_SIZE) 0x00800080) {
369                 if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {
370                         printf ("Timeout\n");
371                         return -1;
372                 }
373                 /* show that we're waiting */
374                 if ((now - last) > 1000) {
375                         putc ('.');
376                         last = now;
377                 }
378         }
379         return 0;
380 }
381
382
383 /******************************************************************************
384 ** Function : write_buff
385 ** Param    : flash_info_t *info, uchar *src, ulong addr, ulong cnt
386 ** Notes    :
387 ******************************************************************************/
388 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
389 {
390         ulong cp, wp, data;
391         int i, l, rc;
392
393         /* get lower word aligned address */
394         wp = (addr & ~3);
395
396         /*
397          * handle unaligned start bytes
398          */
399         if ((l = addr - wp) != 0) {
400                 data = 0;
401                 for (i = 0, cp = wp; i < l; ++i, ++cp) {
402                         data = (data << 8) | (*(uchar *) cp);
403                 }
404                 for (; i < 4 && cnt > 0; ++i) {
405                         data = (data << 8) | *src++;
406                         --cnt;
407                         ++cp;
408                 }
409                 for (; cnt == 0 && i < 4; ++i, ++cp) {
410                         data = (data << 8) | (*(uchar *) cp);
411                 }
412
413                 if ((rc = write_word (info, wp, data)) != 0) {
414                         return (rc);
415                 }
416                 wp += 4;
417         }
418
419         /*
420          * handle word aligned part
421          */
422         while (cnt >= 4) {
423                 data = 0;
424                 for (i = 0; i < 4; ++i) {
425                         data = (data << 8) | *src++;
426                 }
427                 if ((rc = write_word (info, wp, data)) != 0) {
428                         return (rc);
429                 }
430                 wp += 4;
431                 cnt -= 4;
432         }
433
434         if (cnt == 0) {
435                 return (0);
436         }
437
438         /*
439          * handle unaligned tail bytes
440          */
441         data = 0;
442         for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
443                 data = (data << 8) | *src++;
444                 --cnt;
445         }
446         for (; i < 4; ++i, ++cp) {
447                 data = (data << 8) | (*(uchar *) cp);
448         }
449
450         return (write_word (info, wp, data));
451 }
452
453
454 /******************************************************************************
455 ** Function : write_word
456 ** Param    : flash_info_t *info, ulong dest, ulong data
457 ** Notes    :
458 ******************************************************************************/
459 static int write_word (flash_info_t * info, ulong dest, ulong data)
460 {
461         volatile FLASH_WORD_SIZE *addr2 =
462                 (FLASH_WORD_SIZE *) (info->start[0]);
463         volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *) dest;
464         volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data;
465         ulong start;
466         int i;
467
468         /* Check if Flash is (sufficiently) erased */
469         if ((*((volatile FLASH_WORD_SIZE *) dest) &
470              (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) {
471                 return (2);
472         }
473
474         for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++) {
475                 int flag;
476
477                 /* Disable interrupts which might cause a timeout here */
478                 flag = disable_interrupts ();
479
480                 addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
481                 addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
482                 addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00A000A0;
483
484                 dest2[i] = data2[i];
485
486                 /* re-enable interrupts if necessary */
487                 if (flag)
488                         enable_interrupts ();
489
490                 /* data polling for D7 */
491                 start = get_timer (0);
492                 while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) !=
493                        (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) {
494                         if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
495                                 return (1);
496                         }
497                 }
498         }
499
500         return (0);
501 }