]> git.sur5r.net Git - u-boot/blob - board/pcippc2/flash.c
Merge branch 'fixes' into cleanups
[u-boot] / board / pcippc2 / flash.c
1 /*
2  * (C) Copyright 2001
3  * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
4  *
5  * (C) Copyright 2002
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 <config.h>
28 #include <common.h>
29 #include <flash.h>
30 #include <asm/io.h>
31
32 /*---------------------------------------------------------------------*/
33 #undef DEBUG_FLASH
34
35 #ifdef DEBUG_FLASH
36 #define DEBUGF(fmt,args...) printf(fmt ,##args)
37 #else
38 #define DEBUGF(fmt,args...)
39 #endif
40 /*---------------------------------------------------------------------*/
41
42 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
43
44 static ulong flash_get_size (ulong addr, flash_info_t *info);
45 static int flash_get_offsets (ulong base, flash_info_t *info);
46 static int write_word (flash_info_t *info, ulong dest, ulong data);
47 static void flash_reset (ulong addr);
48
49 unsigned long flash_init (void)
50 {
51         unsigned int i;
52         unsigned long flash_size = 0;
53
54         /* Init: no FLASHes known */
55         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
56                 flash_info[i].flash_id = FLASH_UNKNOWN;
57                 flash_info[i].sector_count = 0;
58                 flash_info[i].size = 0;
59         }
60
61         DEBUGF("\n## Get flash size @ 0x%08x\n", CONFIG_SYS_FLASH_BASE);
62
63         flash_size = flash_get_size (CONFIG_SYS_FLASH_BASE, flash_info);
64
65         DEBUGF("## Flash bank size: %08lx\n", flash_size);
66
67         if (flash_size) {
68 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE && \
69     CONFIG_SYS_MONITOR_BASE < CONFIG_SYS_FLASH_BASE + CONFIG_SYS_FLASH_MAX_SIZE
70                 /* monitor protection ON by default */
71                 flash_protect(FLAG_PROTECT_SET,
72                               CONFIG_SYS_MONITOR_BASE,
73                               CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
74                               &flash_info[0]);
75 #endif
76
77 #ifdef CONFIG_ENV_IS_IN_FLASH
78                 /* ENV protection ON by default */
79                 flash_protect(FLAG_PROTECT_SET,
80                               CONFIG_ENV_ADDR,
81                               CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
82                               &flash_info[0]);
83 #endif
84
85         } else {
86                 puts ("Warning: the BOOT Flash is not initialised !");
87         }
88
89         return flash_size;
90 }
91
92 /*
93  * The following code cannot be run from FLASH!
94  */
95 static ulong flash_get_size (ulong addr, flash_info_t *info)
96 {
97         short i;
98         uchar value;
99
100         /* Write auto select command: read Manufacturer ID */
101         out8(addr + 0x0555, 0xAA);
102         iobarrier_rw();
103         out8(addr + 0x02AA, 0x55);
104         iobarrier_rw();
105         out8(addr + 0x0555, 0x90);
106         iobarrier_rw();
107
108         value = in8(addr);
109         iobarrier_rw();
110
111         DEBUGF("Manuf. ID @ 0x%08lx: 0x%08x\n", (ulong)addr, value);
112
113         switch (value | (value << 16)) {
114                 case AMD_MANUFACT:
115                         info->flash_id = FLASH_MAN_AMD;
116                         break;
117
118                 case FUJ_MANUFACT:
119                         info->flash_id = FLASH_MAN_FUJ;
120                         break;
121
122                 case STM_MANUFACT:
123                         info->flash_id = FLASH_MAN_STM;
124                         break;
125
126                 default:
127                         info->flash_id = FLASH_UNKNOWN;
128                         info->sector_count = 0;
129                         info->size = 0;
130                         flash_reset (addr);
131                         return 0;
132         }
133
134         value = in8(addr + 1);                  /* device ID            */
135         iobarrier_rw();
136
137         DEBUGF("Device ID @ 0x%08lx: 0x%08x\n", addr+1, value);
138
139         switch ((ulong)value) {
140                 case AMD_ID_F040B:
141                         DEBUGF("Am29F040B\n");
142                         info->flash_id += FLASH_AM040;
143                         info->sector_count = 8;
144                         info->size = 0x00080000;
145                         break;                  /* => 512 kB            */
146
147                 case AMD_ID_LV040B:
148                         DEBUGF("Am29LV040B\n");
149                         info->flash_id += FLASH_AM040;
150                         info->sector_count = 8;
151                         info->size = 0x00080000;
152                         break;                  /* => 512 kB            */
153
154                 case AMD_ID_LV400T:
155                         DEBUGF("Am29LV400T\n");
156                         info->flash_id += FLASH_AM400T;
157                         info->sector_count = 11;
158                         info->size = 0x00100000;
159                         break;                  /* => 1 MB              */
160
161                 case AMD_ID_LV400B:
162                         DEBUGF("Am29LV400B\n");
163                         info->flash_id += FLASH_AM400B;
164                         info->sector_count = 11;
165                         info->size = 0x00100000;
166                         break;                  /* => 1 MB              */
167
168                 case AMD_ID_LV800T:
169                         DEBUGF("Am29LV800T\n");
170                         info->flash_id += FLASH_AM800T;
171                         info->sector_count = 19;
172                         info->size = 0x00200000;
173                         break;                  /* => 2 MB              */
174
175                 case AMD_ID_LV800B:
176                         DEBUGF("Am29LV400B\n");
177                         info->flash_id += FLASH_AM800B;
178                         info->sector_count = 19;
179                         info->size = 0x00200000;
180                         break;                  /* => 2 MB              */
181
182                 case AMD_ID_LV160T:
183                         DEBUGF("Am29LV160T\n");
184                         info->flash_id += FLASH_AM160T;
185                         info->sector_count = 35;
186                         info->size = 0x00400000;
187                         break;                  /* => 4 MB              */
188
189                 case AMD_ID_LV160B:
190                         DEBUGF("Am29LV160B\n");
191                         info->flash_id += FLASH_AM160B;
192                         info->sector_count = 35;
193                         info->size = 0x00400000;
194                         break;                  /* => 4 MB              */
195
196                 case AMD_ID_LV320T:
197                         DEBUGF("Am29LV320T\n");
198                         info->flash_id += FLASH_AM320T;
199                         info->sector_count = 67;
200                         info->size = 0x00800000;
201                         break;                  /* => 8 MB              */
202
203 #if 0
204                 /* Has the same ID as AMD_ID_LV320T, to be fixed */
205                 case AMD_ID_LV320B:
206                         DEBUGF("Am29LV320B\n");
207                         info->flash_id += FLASH_AM320B;
208                         info->sector_count = 67;
209                         info->size = 0x00800000;
210                         break;                  /* => 8 MB              */
211 #endif
212
213                 case AMD_ID_LV033C:
214                         DEBUGF("Am29LV033C\n");
215                         info->flash_id += FLASH_AM033C;
216                         info->sector_count = 64;
217                         info->size = 0x01000000;
218                         break;                  /* => 16Mb              */
219
220                 case STM_ID_F040B:
221                         DEBUGF("M29F040B\n");
222                         info->flash_id += FLASH_AM040;
223                         info->sector_count = 8;
224                         info->size = 0x00080000;
225                         break;                  /* => 512 kB            */
226
227                 default:
228                         info->flash_id = FLASH_UNKNOWN;
229                         flash_reset (addr);
230                         return (0);             /* => no or unknown flash */
231
232         }
233
234         if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
235                 printf ("** ERROR: sector count %d > max (%d) **\n",
236                         info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
237                 info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
238         }
239
240         if (! flash_get_offsets (addr, info)) {
241                 flash_reset (addr);
242                 return 0;
243         }
244
245         /* check for protected sectors */
246         for (i = 0; i < info->sector_count; i++) {
247                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
248                 /* D0 = 1 if protected */
249                 value = in8(info->start[i] + 2);
250                 iobarrier_rw();
251                 info->protect[i] = (value & 1) != 0;
252         }
253
254         /*
255          * Reset bank to read mode
256          */
257         flash_reset (addr);
258
259         return (info->size);
260 }
261
262 static int flash_get_offsets (ulong base, flash_info_t *info)
263 {
264         unsigned int i;
265
266         switch (info->flash_id & FLASH_TYPEMASK) {
267                 case FLASH_AM040:
268                         /* set sector offsets for uniform sector type   */
269                         for (i = 0; i < info->sector_count; i++) {
270                                 info->start[i] = base + i * info->size /
271                                                             info->sector_count;
272                         }
273                         break;
274                 default:
275                         return 0;
276         }
277
278         return 1;
279 }
280
281 int flash_erase (flash_info_t *info, int s_first, int s_last)
282 {
283         volatile ulong addr = info->start[0];
284         int flag, prot, sect, l_sect;
285         ulong start, now, last;
286
287         if (s_first < 0 || s_first > s_last) {
288                 if (info->flash_id == FLASH_UNKNOWN) {
289                         printf ("- missing\n");
290                 } else {
291                         printf ("- no sectors to erase\n");
292                 }
293                 return 1;
294         }
295
296         if (info->flash_id == FLASH_UNKNOWN) {
297                 printf ("Can't erase unknown flash type %08lx - aborted\n",
298                         info->flash_id);
299                 return 1;
300         }
301
302         prot = 0;
303         for (sect=s_first; sect<=s_last; ++sect) {
304                 if (info->protect[sect]) {
305                         prot++;
306                 }
307         }
308
309         if (prot) {
310                 printf ("- Warning: %d protected sectors will not be erased!\n",
311                         prot);
312         } else {
313                 printf ("\n");
314         }
315
316         l_sect = -1;
317
318         /* Disable interrupts which might cause a timeout here */
319         flag = disable_interrupts();
320
321         out8(addr + 0x555, 0xAA);
322         iobarrier_rw();
323         out8(addr + 0x2AA, 0x55);
324         iobarrier_rw();
325         out8(addr + 0x555, 0x80);
326         iobarrier_rw();
327         out8(addr + 0x555, 0xAA);
328         iobarrier_rw();
329         out8(addr + 0x2AA, 0x55);
330         iobarrier_rw();
331
332         /* Start erase on unprotected sectors */
333         for (sect = s_first; sect<=s_last; sect++) {
334                 if (info->protect[sect] == 0) { /* not protected */
335                         addr = info->start[sect];
336                         out8(addr, 0x30);
337                         iobarrier_rw();
338                         l_sect = sect;
339                 }
340         }
341
342         /* re-enable interrupts if necessary */
343         if (flag)
344                 enable_interrupts();
345
346         /* wait at least 80us - let's wait 1 ms */
347         udelay (1000);
348
349         /*
350          * We wait for the last triggered sector
351          */
352         if (l_sect < 0)
353                 goto DONE;
354
355         start = get_timer (0);
356         last  = start;
357         addr = info->start[l_sect];
358
359         DEBUGF ("Start erase timeout: %d\n", CONFIG_SYS_FLASH_ERASE_TOUT);
360
361         while ((in8(addr) & 0x80) != 0x80) {
362                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
363                         printf ("Timeout\n");
364                         flash_reset (info->start[0]);
365                         return 1;
366                 }
367                 /* show that we're waiting */
368                 if ((now - last) > 1000) {      /* every second */
369                         putc ('.');
370                         last = now;
371                 }
372                 iobarrier_rw();
373         }
374
375 DONE:
376         /* reset to read mode */
377         flash_reset (info->start[0]);
378
379         printf (" done\n");
380         return 0;
381 }
382
383 /*
384  * Copy memory to flash, returns:
385  * 0 - OK
386  * 1 - write timeout
387  * 2 - Flash not erased
388  */
389 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
390 {
391         ulong cp, wp, data;
392         int i, l, rc;
393
394         wp = (addr & ~3);       /* get lower word aligned address */
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  * Write a word to Flash, returns:
455  * 0 - OK
456  * 1 - write timeout
457  * 2 - Flash not erased
458  */
459 static int write_word (flash_info_t *info, ulong dest, ulong data)
460 {
461         volatile ulong addr = info->start[0];
462         ulong start;
463         int i;
464
465         /* Check if Flash is (sufficiently) erased */
466         if ((in32(dest) & data) != data) {
467                 return (2);
468         }
469
470         /* write each byte out */
471         for (i = 0; i < 4; i++) {
472                 char *data_ch = (char *)&data;
473                 int flag = disable_interrupts();
474
475                 out8(addr + 0x555, 0xAA);
476                 iobarrier_rw();
477                 out8(addr + 0x2AA, 0x55);
478                 iobarrier_rw();
479                 out8(addr + 0x555, 0xA0);
480                 iobarrier_rw();
481                 out8(dest+i, data_ch[i]);
482                 iobarrier_rw();
483
484                 /* re-enable interrupts if necessary */
485                 if (flag)
486                         enable_interrupts();
487
488                 /* data polling for D7 */
489                 start = get_timer (0);
490                 while ((in8(dest+i) & 0x80) != (data_ch[i] & 0x80)) {
491                         if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
492                                 flash_reset (addr);
493                                 return (1);
494                         }
495                         iobarrier_rw();
496                 }
497         }
498
499         flash_reset (addr);
500         return (0);
501 }
502
503 /*
504  * Reset bank to read mode
505  */
506 static void flash_reset (ulong addr)
507 {
508         out8(addr, 0xF0);       /* reset bank */
509         iobarrier_rw();
510 }
511
512 void flash_print_info (flash_info_t *info)
513 {
514         int i;
515
516         if (info->flash_id == FLASH_UNKNOWN) {
517                 printf ("missing or unknown FLASH type\n");
518                 return;
519         }
520
521         switch (info->flash_id & FLASH_VENDMASK) {
522         case FLASH_MAN_AMD:     printf ("AMD ");                break;
523         case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
524         case FLASH_MAN_BM:      printf ("BRIGHT MICRO ");       break;
525         case FLASH_MAN_STM:     printf ("SGS THOMSON ");        break;
526         default:                printf ("Unknown Vendor ");     break;
527         }
528
529         switch (info->flash_id & FLASH_TYPEMASK) {
530         case FLASH_AM040:       printf ("29F040 or 29LV040 (4 Mbit, uniform sectors)\n");
531                                 break;
532         case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
533                                 break;
534         case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
535                                 break;
536         case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
537                                 break;
538         case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
539                                 break;
540         case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
541                                 break;
542         case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
543                                 break;
544         case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
545                                 break;
546         case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
547                                 break;
548         default:                printf ("Unknown Chip Type\n");
549                                 break;
550         }
551
552         if (info->size % 0x100000 == 0) {
553                 printf ("  Size: %ld MB in %d Sectors\n",
554                         info->size / 0x100000, info->sector_count);
555         } else if (info->size % 0x400 == 0) {
556                 printf ("  Size: %ld KB in %d Sectors\n",
557                         info->size / 0x400, info->sector_count);
558         } else {
559                 printf ("  Size: %ld B in %d Sectors\n",
560                         info->size, info->sector_count);
561         }
562
563         printf ("  Sector Start Addresses:");
564         for (i=0; i<info->sector_count; ++i) {
565                 if ((i % 5) == 0)
566                         printf ("\n   ");
567                 printf (" %08lX%s",
568                         info->start[i],
569                         info->protect[i] ? " (RO)" : "     "
570                 );
571         }
572         printf ("\n");
573 }