Merge branch 'master' of /home/wd/git/u-boot/custodians
[platform/kernel/u-boot.git] / board / lantec / flash.c
1 /*
2  * (C) Copyright 2000, 2001
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 /*
25  * Derived from ../tqm8xx/flash.c
26  * [Torsten Stevens, FHG IMS; Bruno Achauer, Exet AG]
27  */
28
29 #include <common.h>
30 #include <mpc8xx.h>
31
32 #if defined(CFG_ENV_IS_IN_FLASH)
33 # ifndef  CFG_ENV_ADDR
34 #  define CFG_ENV_ADDR  (CFG_FLASH_BASE + CFG_ENV_OFFSET)
35 # endif
36 # ifndef  CFG_ENV_SIZE
37 #  define CFG_ENV_SIZE  CFG_ENV_SECT_SIZE
38 # endif
39 # ifndef  CFG_ENV_SECT_SIZE
40 #  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
41 # endif
42 #endif
43
44 /*---------------------------------------------------------------------*/
45 #undef DEBUG_FLASH
46
47 #ifdef DEBUG_FLASH
48 #define DEBUGF(fmt,args...) printf(fmt ,##args)
49 #else
50 #define DEBUGF(fmt,args...)
51 #endif
52 /*---------------------------------------------------------------------*/
53
54 flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips        */
55
56 /*-----------------------------------------------------------------------
57  * Functions
58  */
59 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
60 static int write_word (flash_info_t *info, ulong dest, ulong data);
61 static void flash_get_offsets (ulong base, flash_info_t *info);
62
63 /*-----------------------------------------------------------------------
64  */
65
66 unsigned long flash_init (void)
67 {
68         volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
69         volatile memctl8xx_t *memctl = &immap->im_memctl;
70         unsigned long size_b0, size_b1;
71         int i;
72
73         /* Init: no FLASHes known */
74         for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
75                 flash_info[i].flash_id = FLASH_UNKNOWN;
76         }
77
78         /* Static FLASH Bank configuration here - FIXME XXX */
79
80         DEBUGF("\n## Get flash bank 1 size @ 0x%08x\n",FLASH_BASE0_PRELIM);
81
82         size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
83
84         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
85                 printf ("## Unknown FLASH on Bank 0: "
86                         "ID 0x%lx, Size = 0x%08lx = %ld MB\n",
87                         flash_info[0].flash_id,
88                         size_b0, size_b0<<20);
89         }
90
91         DEBUGF("## Get flash bank 2 size @ 0x%08x\n",FLASH_BASE5_PRELIM);
92
93         size_b1 = flash_get_size((vu_long *)FLASH_BASE5_PRELIM, &flash_info[1]);
94
95         DEBUGF("## Prelim. Flash bank sizes: %08lx + 0x%08lx\n",size_b0,size_b1);
96
97         if (size_b1 > size_b0) {
98                 printf ("## ERROR: "
99                         "Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
100                         size_b1, size_b1<<20,
101                         size_b0, size_b0<<20
102                 );
103                 flash_info[0].flash_id  = FLASH_UNKNOWN;
104                 flash_info[1].flash_id  = FLASH_UNKNOWN;
105                 flash_info[0].sector_count      = -1;
106                 flash_info[1].sector_count      = -1;
107                 flash_info[0].size              = 0;
108                 flash_info[1].size              = 0;
109                 return (0);
110         }
111
112         DEBUGF ("## Before remap: "
113                 "BR0: 0x%08x    OR0: 0x%08x    "
114                 "BR1: 0x%08x    OR1: 0x%08x\n",
115                 memctl->memc_br0, memctl->memc_or0,
116                 memctl->memc_br1, memctl->memc_or1);
117
118         /* Remap FLASH according to real size */
119         memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
120         memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | \
121                                 BR_MS_GPCM | BR_PS_32 | BR_V;
122
123         DEBUGF("## BR0: 0x%08x    OR0: 0x%08x\n",
124                 memctl->memc_br0, memctl->memc_or0);
125
126         /* Re-do sizing to get full correct info */
127         size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
128
129         flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
130
131         flash_info[0].size = size_b0;
132
133 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
134         /* monitor protection ON by default */
135         flash_protect(FLAG_PROTECT_SET,
136                       CFG_MONITOR_BASE,
137                       CFG_MONITOR_BASE+monitor_flash_len-1,
138                       &flash_info[0]);
139 #endif
140
141 #ifdef  CFG_ENV_IS_IN_FLASH
142         /* ENV protection ON by default */
143         flash_protect(FLAG_PROTECT_SET,
144                       CFG_ENV_ADDR,
145                       CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
146                       &flash_info[0]);
147 #endif
148
149         if (size_b1) {
150                 memctl->memc_or5 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000);
151                 memctl->memc_br5 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) |
152                                     BR_MS_GPCM | BR_PS_32 | BR_V;
153
154                 DEBUGF("## BR5: 0x%08x    OR5: 0x%08x\n",
155                         memctl->memc_br5, memctl->memc_or5);
156
157                 /* Re-do sizing to get full correct info */
158                 size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + size_b0),
159                                           &flash_info[1]);
160
161                 flash_info[1].size = size_b1;
162
163                 flash_get_offsets (CFG_FLASH_BASE + size_b0, &flash_info[1]);
164
165 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
166                 /* monitor protection ON by default */
167                 flash_protect(FLAG_PROTECT_SET,
168                               CFG_MONITOR_BASE,
169                               CFG_MONITOR_BASE+monitor_flash_len-1,
170                               &flash_info[1]);
171 #endif
172
173 #ifdef  CFG_ENV_IS_IN_FLASH
174                 /* ENV protection ON by default */
175                 flash_protect(FLAG_PROTECT_SET,
176                               CFG_ENV_ADDR,
177                               CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
178                               &flash_info[1]);
179 #endif
180         } else {
181                 memctl->memc_br5 = 0;           /* invalidate bank */
182                 memctl->memc_or5 = 0;           /* invalidate bank */
183
184                 DEBUGF("## DISABLE BR5: 0x%08x    OR5: 0x%08x\n",
185                         memctl->memc_br5, memctl->memc_or5);
186
187                 flash_info[1].flash_id = FLASH_UNKNOWN;
188                 flash_info[1].sector_count = -1;
189                 flash_info[1].size = 0;
190         }
191
192         DEBUGF("## Final Flash bank sizes: %08lx + 0x%08lx\n",size_b0,size_b1);
193
194         return (size_b0 + size_b1);
195 }
196
197 /*-----------------------------------------------------------------------
198  */
199 static void flash_get_offsets (ulong base, flash_info_t *info)
200 {
201         int i;
202
203         /* set up sector start address table */
204         if (info->flash_id & FLASH_BTYPE) {
205                 /* set sector offsets for bottom boot block type        */
206                 info->start[0] = base + 0x00000000;
207                 info->start[1] = base + 0x00008000;
208                 info->start[2] = base + 0x0000C000;
209                 info->start[3] = base + 0x00010000;
210                 for (i = 4; i < info->sector_count; i++) {
211                         info->start[i] = base + (i * 0x00020000) - 0x00060000;
212                 }
213         } else {
214                 /* set sector offsets for top boot block type           */
215                 i = info->sector_count - 1;
216                 info->start[i--] = base + info->size - 0x00008000;
217                 info->start[i--] = base + info->size - 0x0000C000;
218                 info->start[i--] = base + info->size - 0x00010000;
219                 for (; i >= 0; i--) {
220                         info->start[i] = base + i * 0x00020000;
221                 }
222         }
223
224 }
225
226 /*-----------------------------------------------------------------------
227  */
228 void flash_print_info  (flash_info_t *info)
229 {
230         int i;
231
232         if (info->flash_id == FLASH_UNKNOWN) {
233                 printf ("missing or unknown FLASH type\n");
234                 return;
235         }
236
237         switch (info->flash_id & FLASH_VENDMASK) {
238         case FLASH_MAN_AMD:     printf ("AMD ");                break;
239         case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
240         default:                printf ("Unknown Vendor ");     break;
241         }
242
243         switch (info->flash_id & FLASH_TYPEMASK) {
244         case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
245                                 break;
246         case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
247                                 break;
248         case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
249                                 break;
250         case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
251                                 break;
252         case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
253                                 break;
254         case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
255                                 break;
256         case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
257                                 break;
258         case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
259                                 break;
260         default:                printf ("Unknown Chip Type\n");
261                                 break;
262         }
263
264         printf ("  Size: %ld MB in %d Sectors\n",
265                 info->size >> 20, info->sector_count);
266
267         printf ("  Sector Start Addresses:");
268         for (i=0; i<info->sector_count; ++i) {
269                 if ((i % 5) == 0)
270                         printf ("\n   ");
271                 printf (" %08lX%s",
272                         info->start[i],
273                         info->protect[i] ? " (RO)" : "     "
274                 );
275         }
276         printf ("\n");
277         return;
278 }
279
280 /*-----------------------------------------------------------------------
281  */
282
283
284 /*-----------------------------------------------------------------------
285  */
286
287 /*
288  * The following code cannot be run from FLASH!
289  */
290
291 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
292 {
293         short i;
294         ulong value;
295         ulong base = (ulong)addr;
296
297
298         /* Write auto select command: read Manufacturer ID */
299         addr[0x0555] = 0x00AA00AA;
300         addr[0x02AA] = 0x00550055;
301         addr[0x0555] = 0x00900090;
302
303         value = addr[0];
304
305         switch (value) {
306         case AMD_MANUFACT:
307                 info->flash_id = FLASH_MAN_AMD;
308                 break;
309         case FUJ_MANUFACT:
310                 info->flash_id = FLASH_MAN_FUJ;
311                 break;
312         default:
313                 info->flash_id = FLASH_UNKNOWN;
314                 info->sector_count = 0;
315                 info->size = 0;
316                 return (0);                     /* no or unknown flash  */
317         }
318
319         value = addr[1];                        /* device ID            */
320
321         switch (value) {
322         case AMD_ID_LV400T:
323                 info->flash_id += FLASH_AM400T;
324                 info->sector_count = 11;
325                 info->size = 0x00100000;
326                 break;                          /* => 1 MB              */
327
328         case AMD_ID_LV400B:
329                 info->flash_id += FLASH_AM400B;
330                 info->sector_count = 11;
331                 info->size = 0x00100000;
332                 break;                          /* => 1 MB              */
333
334         case AMD_ID_LV800T:
335                 info->flash_id += FLASH_AM800T;
336                 info->sector_count = 19;
337                 info->size = 0x00200000;
338                 break;                          /* => 2 MB              */
339
340         case AMD_ID_LV800B:
341                 info->flash_id += FLASH_AM800B;
342                 info->sector_count = 19;
343                 info->size = 0x00200000;
344                 break;                          /* => 2 MB              */
345
346         case AMD_ID_LV160T:
347                 info->flash_id += FLASH_AM160T;
348                 info->sector_count = 35;
349                 info->size = 0x00400000;
350                 break;                          /* => 4 MB              */
351
352         case AMD_ID_LV160B:
353                 info->flash_id += FLASH_AM160B;
354                 info->sector_count = 35;
355                 info->size = 0x00400000;
356                 break;                          /* => 4 MB              */
357 #if 0   /* enable when device IDs are available */
358         case AMD_ID_LV320T:
359                 info->flash_id += FLASH_AM320T;
360                 info->sector_count = 67;
361                 info->size = 0x00800000;
362                 break;                          /* => 8 MB              */
363
364         case AMD_ID_LV320B:
365                 info->flash_id += FLASH_AM320B;
366                 info->sector_count = 67;
367                 info->size = 0x00800000;
368                 break;                          /* => 8 MB              */
369 #endif
370         default:
371                 info->flash_id = FLASH_UNKNOWN;
372                 return (0);                     /* => no or unknown flash */
373
374         }
375
376         /* set up sector start address table */
377         if (info->flash_id & FLASH_BTYPE) {
378                 /* set sector offsets for bottom boot block type        */
379                 info->start[0] = base + 0x00000000;
380                 info->start[1] = base + 0x00008000;
381                 info->start[2] = base + 0x0000C000;
382                 info->start[3] = base + 0x00010000;
383                 for (i = 4; i < info->sector_count; i++) {
384                         info->start[i] = base + (i * 0x00020000) - 0x00060000;
385                 }
386         } else {
387                 /* set sector offsets for top boot block type           */
388                 i = info->sector_count - 1;
389                 info->start[i--] = base + info->size - 0x00008000;
390                 info->start[i--] = base + info->size - 0x0000C000;
391                 info->start[i--] = base + info->size - 0x00010000;
392                 for (; i >= 0; i--) {
393                         info->start[i] = base + i * 0x00020000;
394                 }
395         }
396
397         /* check for protected sectors */
398         for (i = 0; i < info->sector_count; i++) {
399                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
400                 /* D0 = 1 if protected */
401                 addr = (volatile unsigned long *)(info->start[i]);
402                 info->protect[i] = addr[2] & 1;
403         }
404
405         /*
406          * Prevent writes to uninitialized FLASH.
407          */
408         if (info->flash_id != FLASH_UNKNOWN) {
409                 addr = (volatile unsigned long *)info->start[0];
410
411                 *addr = 0x00F000F0;     /* reset bank */
412         }
413
414         return (info->size);
415 }
416
417
418 /*-----------------------------------------------------------------------
419  */
420
421 int     flash_erase (flash_info_t *info, int s_first, int s_last)
422 {
423         vu_long *addr = (vu_long*)(info->start[0]);
424         int flag, prot, sect, l_sect;
425         ulong start, now, last;
426
427         if ((s_first < 0) || (s_first > s_last)) {
428                 if (info->flash_id == FLASH_UNKNOWN) {
429                         printf ("- missing\n");
430                 } else {
431                         printf ("- no sectors to erase\n");
432                 }
433                 return 1;
434         }
435
436         if ((info->flash_id == FLASH_UNKNOWN) ||
437             (info->flash_id > FLASH_AMD_COMP)) {
438                 printf ("Can't erase unknown flash type %08lx - aborted\n",
439                         info->flash_id);
440                 return 1;
441         }
442
443         prot = 0;
444         for (sect=s_first; sect<=s_last; ++sect) {
445                 if (info->protect[sect]) {
446                         prot++;
447                 }
448         }
449
450         if (prot) {
451                 printf ("- Warning: %d protected sectors will not be erased!\n",
452                         prot);
453         } else {
454                 printf ("\n");
455         }
456
457         l_sect = -1;
458
459         /* Disable interrupts which might cause a timeout here */
460         flag = disable_interrupts();
461
462         addr[0x0555] = 0x00AA00AA;
463         addr[0x02AA] = 0x00550055;
464         addr[0x0555] = 0x00800080;
465         addr[0x0555] = 0x00AA00AA;
466         addr[0x02AA] = 0x00550055;
467
468         /* Start erase on unprotected sectors */
469         for (sect = s_first; sect<=s_last; sect++) {
470                 if (info->protect[sect] == 0) { /* not protected */
471                         addr = (vu_long*)(info->start[sect]);
472                         addr[0] = 0x00300030;
473                         l_sect = sect;
474                 }
475         }
476
477         /* re-enable interrupts if necessary */
478         if (flag)
479                 enable_interrupts();
480
481         /* wait at least 80us - let's wait 1 ms */
482         udelay (1000);
483
484         /*
485          * We wait for the last triggered sector
486          */
487         if (l_sect < 0)
488                 goto DONE;
489
490         start = get_timer (0);
491         last  = start;
492         addr = (vu_long*)(info->start[l_sect]);
493         while ((addr[0] & 0x00800080) != 0x00800080) {
494                 if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
495                         printf ("Timeout\n");
496                         return 1;
497                 }
498                 /* show that we're waiting */
499                 if ((now - last) > 1000) {      /* every second */
500                         putc ('.');
501                         last = now;
502                 }
503         }
504
505 DONE:
506         /* reset to read mode */
507         addr = (volatile unsigned long *)info->start[0];
508         addr[0] = 0x00F000F0;   /* reset bank */
509
510         printf (" done\n");
511         return 0;
512 }
513
514 /*-----------------------------------------------------------------------
515  * Copy memory to flash, returns:
516  * 0 - OK
517  * 1 - write timeout
518  * 2 - Flash not erased
519  */
520
521 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
522 {
523         ulong cp, wp, data;
524         int i, l, rc;
525
526         wp = (addr & ~3);       /* get lower word aligned address */
527
528         /*
529          * handle unaligned start bytes
530          */
531         if ((l = addr - wp) != 0) {
532                 data = 0;
533                 for (i=0, cp=wp; i<l; ++i, ++cp) {
534                         data = (data << 8) | (*(uchar *)cp);
535                 }
536                 for (; i<4 && cnt>0; ++i) {
537                         data = (data << 8) | *src++;
538                         --cnt;
539                         ++cp;
540                 }
541                 for (; cnt==0 && i<4; ++i, ++cp) {
542                         data = (data << 8) | (*(uchar *)cp);
543                 }
544
545                 if ((rc = write_word(info, wp, data)) != 0) {
546                         return (rc);
547                 }
548                 wp += 4;
549         }
550
551         /*
552          * handle word aligned part
553          */
554         while (cnt >= 4) {
555                 data = 0;
556                 for (i=0; i<4; ++i) {
557                         data = (data << 8) | *src++;
558                 }
559                 if ((rc = write_word(info, wp, data)) != 0) {
560                         return (rc);
561                 }
562                 wp  += 4;
563                 cnt -= 4;
564         }
565
566         if (cnt == 0) {
567                 return (0);
568         }
569
570         /*
571          * handle unaligned tail bytes
572          */
573         data = 0;
574         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
575                 data = (data << 8) | *src++;
576                 --cnt;
577         }
578         for (; i<4; ++i, ++cp) {
579                 data = (data << 8) | (*(uchar *)cp);
580         }
581
582         return (write_word(info, wp, data));
583 }
584
585 /*-----------------------------------------------------------------------
586  * Write a word to Flash, returns:
587  * 0 - OK
588  * 1 - write timeout
589  * 2 - Flash not erased
590  */
591 static int write_word (flash_info_t *info, ulong dest, ulong data)
592 {
593         vu_long *addr = (vu_long*)(info->start[0]);
594         ulong start;
595         int flag;
596
597         /* Check if Flash is (sufficiently) erased */
598         if ((*((vu_long *)dest) & data) != data) {
599                 return (2);
600         }
601         /* Disable interrupts which might cause a timeout here */
602         flag = disable_interrupts();
603
604         addr[0x0555] = 0x00AA00AA;
605         addr[0x02AA] = 0x00550055;
606         addr[0x0555] = 0x00A000A0;
607
608         *((vu_long *)dest) = data;
609
610         /* re-enable interrupts if necessary */
611         if (flag)
612                 enable_interrupts();
613
614         /* data polling for D7 */
615         start = get_timer (0);
616         while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
617                 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
618                         return (1);
619                 }
620         }
621         return (0);
622 }
623
624 /*-----------------------------------------------------------------------
625  */