]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/mvblue/flash.c
Merge branch 'master' of git://www.denx.de/git/u-boot-cfi-flash
[karo-tx-uboot.git] / board / mvblue / flash.c
1 /*
2  * (C) Copyright 2000
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  * (C) Copyright 2001-2003
5  *
6  * Changes for MATRIX Vision mvBLUE devices
7  * MATRIX Vision GmbH / hg,as info@matrix-vision.de
8  *
9  * SPDX-License-Identifier:     GPL-2.0+
10  */
11
12 #include <common.h>
13 #include <mpc824x.h>
14
15 #if 0
16         #define mvdebug(p) printf ##p
17 #else
18         #define mvdebug(p)
19 #endif
20
21 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
22
23 #define FLASH_BUS_WIDTH         8
24
25 #if (FLASH_BUS_WIDTH==32)
26         #define FLASH_DATA_MASK 0xffffffff
27         #define FLASH_SHIFT 1
28         #define FDT     vu_long
29 #elif (FLASH_BUS_WIDTH==16)
30         #define FLASH_DATA_MASK 0xff
31         #define FLASH_SHIFT 0
32         #define FDT     vu_short
33 #elif (FLASH_BUS_WIDTH==8)
34         #define FLASH_DATA_MASK 0xff
35         #define FLASH_SHIFT 0
36         #define FDT     vu_char
37 #else
38         #error FLASH_BUS_WIDTH undefined
39 #endif
40
41 /*-----------------------------------------------------------------------
42  * Functions
43  */
44 static ulong flash_get_size (vu_long *address, flash_info_t *info);
45 static int write_word (flash_info_t *info, ulong dest, ulong data);
46 static void flash_get_offsets (ulong base, flash_info_t *info);
47
48 /*-----------------------------------------------------------------------
49  */
50 unsigned long flash_init (void)
51 {
52         unsigned long size_b0;
53         int i;
54
55         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
56                 flash_info[i].flash_id = FLASH_UNKNOWN;
57         }
58
59         size_b0 = flash_get_size((vu_long *)0xffc00000, &flash_info[0]);
60
61         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
62                 printf ("## Unknown FLASH : Size = 0x%08lx = %ld MB\n",
63                         size_b0, size_b0<<20);
64         }
65
66         flash_get_offsets (0xffc00000, &flash_info[0]);
67         flash_info[0].size = size_b0;
68
69         /* monitor protection OFF by default */
70         flash_protect ( FLAG_PROTECT_CLEAR, 0xffc00000, 0x2000, flash_info );
71
72         return size_b0;
73 }
74
75 /*-----------------------------------------------------------------------
76  */
77 static void flash_get_offsets (ulong base, flash_info_t *info)
78 {
79         int i;
80
81         /* set up sector start address table */
82         if (info->flash_id & FLASH_BTYPE)
83         {       /* bottom boot sector types - these are the useful ones! */
84                 /* set sector offsets for bottom boot block type */
85                 if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B)
86                 {       /* AMDLV320B has 8 x 8k bottom boot sectors */
87                         for (i = 0; i < 8; i++)                                                                                         /* +8k          */
88                                 info->start[i] = base + (i * (0x00002000 << FLASH_SHIFT));
89                         for (; i < info->sector_count; i++)                                                                     /* +64k         */
90                                 info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)) - (0x00070000 << FLASH_SHIFT);
91                 }
92                 else
93                 {       /* other types have 4 bottom boot sectors (16,8,8,32) */
94                         i = 0;
95                         info->start[i++] = base +  0x00000000;                                                          /* -            */
96                         info->start[i++] = base + (0x00004000 << FLASH_SHIFT);                          /* +16k         */
97                         info->start[i++] = base + (0x00006000 << FLASH_SHIFT);                          /* +8k          */
98                         info->start[i++] = base + (0x00008000 << FLASH_SHIFT);                          /* +8k          */
99                         info->start[i++] = base + (0x00010000 << FLASH_SHIFT);                          /* +32k         */
100                         for (; i < info->sector_count; i++)                                                                     /* +64k         */
101                                 info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)) - (0x00030000 << FLASH_SHIFT);
102                 }
103         }
104         else
105         {       /* top boot sector types - not so useful */
106                 /* set sector offsets for top boot block type */
107                 if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T)
108                 {       /* AMDLV320T has 8 x 8k top boot sectors */
109                         for (i = 0; i < info->sector_count - 8; i++)                                            /* +64k         */
110                                 info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT));
111                         for (; i < info->sector_count; i++)                                                                     /* +8k          */
112                                 info->start[i] = base + (i * (0x00002000 << FLASH_SHIFT));
113                 }
114                 else
115                 {       /* other types have 4 top boot sectors (32,8,8,16) */
116                         for (i = 0; i < info->sector_count - 4; i++)                                            /* +64k         */
117                                 info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT));
118
119                         info->start[i++] = base + info->size - (0x00010000 << FLASH_SHIFT);     /* -32k         */
120                         info->start[i++] = base + info->size - (0x00008000 << FLASH_SHIFT);     /* -8k          */
121                         info->start[i++] = base + info->size - (0x00006000 << FLASH_SHIFT);     /* -8k          */
122                         info->start[i]   = base + info->size - (0x00004000 << FLASH_SHIFT);     /* -16k         */
123                 }
124         }
125 }
126
127 /*-----------------------------------------------------------------------
128  */
129 void flash_print_info  (flash_info_t *info)
130 {
131         int i;
132
133         if (info->flash_id == FLASH_UNKNOWN) {
134                 printf ("missing or unknown FLASH type\n");
135                 return;
136         }
137
138         switch (info->flash_id & FLASH_VENDMASK) {
139         case FLASH_MAN_AMD:     printf ("AMD ");                break;
140         case FLASH_MAN_FUJ:     printf ("FUJITSU ");    break;
141         case FLASH_MAN_STM:     printf ("ST ");                 break;
142         default:                printf ("Unknown Vendor ");     break;
143         }
144
145         switch (info->flash_id & FLASH_TYPEMASK) {
146         case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
147                                 break;
148         case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
149                                 break;
150         case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
151                                 break;
152         case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
153                                 break;
154         case FLASH_STMW320DB:   printf ("M29W320B (32 Mbit, bottom boot sect)\n");
155                                 break;
156         case FLASH_STMW320DT:   printf ("M29W320T (32 Mbit, top boot sector)\n");
157                                 break;
158         default:                printf ("Unknown Chip Type\n");
159                                 break;
160         }
161
162         printf ("  Size: %ld MB in %d Sectors\n", info->size >> 20, info->sector_count);
163
164         printf ("  Sector Start Addresses:");
165         for (i=0; i<info->sector_count; ++i) {
166                 if ((i % 5) == 0)
167                         printf ("\n   ");
168                 printf (" %08lX%s", info->start[i], info->protect[i] ? " (RO)" : "     ");
169         }
170         printf ("\n");
171 }
172
173 /*
174  * The following code cannot be run from FLASH!
175  */
176
177 #define AMD_ID_LV160T_MVS       (AMD_ID_LV160T & FLASH_DATA_MASK)
178 #define AMD_ID_LV160B_MVS       (AMD_ID_LV160B & FLASH_DATA_MASK)
179 #define AMD_ID_LV320T_MVS       (AMD_ID_LV320T & FLASH_DATA_MASK)
180 #define AMD_ID_LV320B_MVS       (AMD_ID_LV320B & FLASH_DATA_MASK)
181 #define STM_ID_W320DT_MVS       (STM_ID_29W320DT & FLASH_DATA_MASK)
182 #define STM_ID_W320DB_MVS       (STM_ID_29W320DB & FLASH_DATA_MASK)
183 #define AMD_MANUFACT_MVS        (AMD_MANUFACT  & FLASH_DATA_MASK)
184 #define FUJ_MANUFACT_MVS        (FUJ_MANUFACT  & FLASH_DATA_MASK)
185 #define STM_MANUFACT_MVS        (STM_MANUFACT  & FLASH_DATA_MASK)
186
187 #if (FLASH_BUS_WIDTH >= 16)
188         #define AUTOSELECT_ADDR1        0x0555
189         #define AUTOSELECT_ADDR2        0x02AA
190         #define AUTOSELECT_ADDR3        AUTOSELECT_ADDR1
191 #else
192         #define AUTOSELECT_ADDR1        0x0AAA
193         #define AUTOSELECT_ADDR2        0x0555
194         #define AUTOSELECT_ADDR3        AUTOSELECT_ADDR1
195 #endif
196
197 #define AUTOSELECT_DATA1        (0x00AA00AA & FLASH_DATA_MASK)
198 #define AUTOSELECT_DATA2        (0x00550055 & FLASH_DATA_MASK)
199 #define AUTOSELECT_DATA3        (0x00900090 & FLASH_DATA_MASK)
200
201 #define RESET_BANK_DATA         (0x00F000F0 & FLASH_DATA_MASK)
202
203
204 static ulong flash_get_size (vu_long *address, flash_info_t *info)
205 {
206         short i;
207         FDT value;
208         FDT *addr = (FDT *)address;
209
210         ulong base = (ulong)address;
211         addr[AUTOSELECT_ADDR1] = AUTOSELECT_DATA1;
212         addr[AUTOSELECT_ADDR2] = AUTOSELECT_DATA2;
213         addr[AUTOSELECT_ADDR3] = AUTOSELECT_DATA3;
214         __asm__ __volatile__("sync");
215
216         udelay(180);
217
218         value = addr[0];                        /* manufacturer ID      */
219         switch (value) {
220         case AMD_MANUFACT_MVS:
221                 info->flash_id = FLASH_MAN_AMD;
222                 break;
223         case FUJ_MANUFACT_MVS:
224                 info->flash_id = FLASH_MAN_FUJ;
225                 break;
226         case STM_MANUFACT_MVS:
227                 info->flash_id = FLASH_MAN_STM;
228                 break;
229         default:
230                 info->flash_id = FLASH_UNKNOWN;
231                 info->sector_count = 0;
232                 info->size = 0;
233                 return (0);                     /* no or unknown flash  */
234         }
235 #if (FLASH_BUS_WIDTH >= 16)
236         value = addr[1];                        /* device ID            */
237 #else
238         value = addr[2];                        /* device ID            */
239 #endif
240
241         switch (value) {
242         case AMD_ID_LV160T_MVS:
243                 info->flash_id += FLASH_AM160T;
244                 info->sector_count = 37;
245                 info->size = (0x00200000 << FLASH_SHIFT);
246                 break;                          /* => 2 or 4 MB         */
247
248         case AMD_ID_LV160B_MVS:
249                 info->flash_id += FLASH_AM160B;
250                 info->sector_count = 37;
251                 info->size = (0x00200000 << FLASH_SHIFT);
252                 break;                          /* => 2 or 4 MB         */
253
254         case AMD_ID_LV320T_MVS:
255                 info->flash_id += FLASH_AM320T;
256                 info->sector_count = 71;
257                 info->size = (0x00400000 << FLASH_SHIFT);
258                 break;                          /* => 4 or 8 MB         */
259
260         case AMD_ID_LV320B_MVS:
261                 info->flash_id += FLASH_AM320B;
262                 info->sector_count = 71;
263                 info->size = (0x00400000 << FLASH_SHIFT);
264                 break;                          /* => 4 or 8MB          */
265
266         case STM_ID_W320DT_MVS:
267                 info->flash_id += FLASH_STMW320DT;
268                 info->sector_count = 67;
269                 info->size = (0x00400000 << FLASH_SHIFT);
270                 break;                          /* => 4 or 8 MB         */
271
272         case STM_ID_W320DB_MVS:
273                 info->flash_id += FLASH_STMW320DB;
274                 info->sector_count = 67;
275                 info->size = (0x00400000 << FLASH_SHIFT);
276                 break;                          /* => 4 or 8MB          */
277
278         default:
279                 info->flash_id = FLASH_UNKNOWN;
280                 return (0);                     /* => no or unknown flash */
281
282         }
283
284         /* set up sector start address table */
285         flash_get_offsets (base, info);
286
287         /* check for protected sectors */
288         for (i = 0; i < info->sector_count; i++) {
289                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
290                 /* D0 = 1 if protected */
291                 addr = (FDT *)(info->start[i]);
292                 info->protect[i] = addr[2] & 1;
293         }
294
295         /*
296          * Prevent writes to uninitialized FLASH.
297          */
298         if (info->flash_id != FLASH_UNKNOWN) {
299                 addr = (FDT *)info->start[0];
300                 *addr = RESET_BANK_DATA;        /* reset bank */
301         }
302         return (info->size);
303 }
304
305
306 /*-----------------------------------------------------------------------
307  */
308
309 #if (FLASH_BUS_WIDTH >= 16)
310         #define ERASE_ADDR1 0x0555
311         #define ERASE_ADDR2 0x02AA
312 #else
313         #define ERASE_ADDR1 0x0AAA
314         #define ERASE_ADDR2 0x0555
315 #endif
316
317 #define ERASE_ADDR3 ERASE_ADDR1
318 #define ERASE_ADDR4 ERASE_ADDR1
319 #define ERASE_ADDR5 ERASE_ADDR2
320
321 #define ERASE_DATA1 (0x00AA00AA & FLASH_DATA_MASK)
322 #define ERASE_DATA2 (0x00550055 & FLASH_DATA_MASK)
323 #define ERASE_DATA3 (0x00800080 & FLASH_DATA_MASK)
324 #define ERASE_DATA4 ERASE_DATA1
325 #define ERASE_DATA5 ERASE_DATA2
326
327 #define ERASE_SECTOR_DATA       (0x00300030 & FLASH_DATA_MASK)
328 #define ERASE_CHIP_DATA         (0x00100010 & FLASH_DATA_MASK)
329 #define ERASE_CONFIRM_DATA      (0x00800080 & FLASH_DATA_MASK)
330
331 int     flash_erase (flash_info_t *info, int s_first, int s_last)
332 {
333         FDT *addr = (FDT *)(info->start[0]);
334
335         int prot, sect, l_sect, flag;
336         ulong start, now, last;
337
338         __asm__ __volatile__ ("sync");
339         addr[0] = 0xf0;
340         udelay(1000);
341
342         printf("\nflash_erase: first = %d @ 0x%08lx\n", s_first, info->start[s_first] );
343         printf("             last  = %d @ 0x%08lx\n", s_last , info->start[s_last ] );
344
345         if ((s_first < 0) || (s_first > s_last)) {
346                 if (info->flash_id == FLASH_UNKNOWN) {
347                         printf ("- missing\n");
348                 } else {
349                         printf ("- no sectors to erase\n");
350                 }
351                 return 1;
352         }
353
354         if ((info->flash_id == FLASH_UNKNOWN) || (info->flash_id > FLASH_AMD_COMP)) {
355                 printf ("Can't erase unknown flash type %08lx - aborted\n", info->flash_id);
356                 return 1;
357         }
358
359         prot = 0;
360         for (sect=s_first; sect<=s_last; ++sect) {
361                 if (info->protect[sect]) {
362                         prot++;
363                 }
364         }
365
366         if (prot) {
367                 printf ("- Warning: %d protected sectors will not be erased!\n",
368                         prot);
369         } else {
370                 printf ("\n");
371         }
372
373         l_sect = -1;
374
375         /* Disable interrupts which might cause a timeout here */
376         flag = disable_interrupts();
377
378         addr[ERASE_ADDR1] = ERASE_DATA1;
379         addr[ERASE_ADDR2] = ERASE_DATA2;
380         addr[ERASE_ADDR3] = ERASE_DATA3;
381         addr[ERASE_ADDR4] = ERASE_DATA4;
382         addr[ERASE_ADDR5] = ERASE_DATA5;
383
384         for (sect = s_first; sect <= s_last; sect++) {
385                 if (info->protect[sect] == 0) {
386                         addr = (FDT *)(info->start[sect]);
387                         addr[0] = ERASE_SECTOR_DATA;
388                         l_sect = sect;
389                 }
390         }
391
392         if (flag)
393                 enable_interrupts();
394
395         /*
396          * We wait for the last triggered sector
397          */
398         if (l_sect < 0)
399                 goto DONE;
400
401         start = get_timer (0);
402         last  = start;
403         addr = (FDT *)(info->start[l_sect]);
404
405         while ((addr[0] & ERASE_CONFIRM_DATA) != ERASE_CONFIRM_DATA) {
406                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
407                         printf ("Timeout\n");
408                         return 1;
409                 }
410                 /* show that we're waiting */
411                 if ((now - last) > 1000) {      /* every second */
412                         putc ('.');
413                         last = now;
414                 }
415         }
416
417 DONE:
418         printf (" done\n");
419         return 0;
420 }
421
422 /*-----------------------------------------------------------------------
423  * Copy memory to flash, returns:
424  * 0 - OK
425  * 1 - write timeout
426  * 2 - Flash not erased
427  */
428
429 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
430 {
431 #define BUFF_INC 4
432         ulong cp, wp, data;
433         int i, l, rc;
434
435         mvdebug (("+write_buff %p ==> 0x%08lx, count = 0x%08lx\n", src, addr, cnt));
436
437         wp = (addr & ~3);       /* get lower word aligned address */
438         /*
439          * handle unaligned start bytes
440          */
441         if ((l = addr - wp) != 0) {
442                 mvdebug ((" handle unaligned start bytes (cnt = 0x%08lx)\n", cnt));
443                 data = 0;
444                 for (i=0, cp=wp; i<l; ++i, ++cp) {
445                         data = (data << 8) | (*(uchar *)cp);
446                 }
447                 for (; i<BUFF_INC && cnt>0; ++i) {
448                         data = (data << 8) | *src++;
449                         --cnt;
450                         ++cp;
451                 }
452                 for (; cnt==0 && i<BUFF_INC; ++i, ++cp) {
453                         data = (data << 8) | (*(uchar *)cp);
454                 }
455
456                 if ((rc = write_word(info, wp, data)) != 0) {
457                         return (rc);
458                 }
459                 wp += BUFF_INC;
460         }
461
462         /*
463          * handle (half)word aligned part
464          */
465         mvdebug ((" handle word aligned part (cnt = 0x%08lx)\n", cnt));
466         while (cnt >= BUFF_INC) {
467                 data = 0;
468                 for (i=0; i<BUFF_INC; ++i) {
469                         data = (data << 8) | *src++;
470                 }
471                 if ((rc = write_word(info, wp, data)) != 0) {
472                         return (rc);
473                 }
474                 wp  += BUFF_INC;
475                 cnt -= BUFF_INC;
476         }
477
478         if (cnt == 0) {
479                 return (0);
480         }
481
482         /*
483          * handle unaligned tail bytes
484          */
485         mvdebug ((" handle unaligned tail bytes (cnt = 0x%08lx)\n", cnt));
486         data = 0;
487         for (i=0, cp=wp; i<BUFF_INC && cnt>0; ++i, ++cp) {
488                 data = (data << 8) | *src++;
489                 --cnt;
490         }
491         for (; i<BUFF_INC; ++i, ++cp) {
492                 data = (data << 8) | (*(uchar *)cp);
493         }
494
495         return (write_word(info, wp, data));
496 }
497
498 #if (FLASH_BUS_WIDTH >= 16)
499         #define WRITE_ADDR1 0x0555
500         #define WRITE_ADDR2 0x02AA
501 #else
502         #define WRITE_ADDR1 0x0AAA
503         #define WRITE_ADDR2 0x0555
504         #define WRITE_ADDR3 WRITE_ADDR1
505 #endif
506
507 #define WRITE_DATA1 (0x00AA00AA & FLASH_DATA_MASK)
508 #define WRITE_DATA2 (0x00550055 & FLASH_DATA_MASK)
509 #define WRITE_DATA3 (0x00A000A0 & FLASH_DATA_MASK)
510
511 #define WRITE_CONFIRM_DATA ERASE_CONFIRM_DATA
512
513 /*-----------------------------------------------------------------------
514  * Write a byte to Flash, returns:
515  * 0 - OK
516  * 1 - write timeout
517  * 2 - Flash not erased
518  */
519 static int write_char (flash_info_t *info, ulong dest, uchar data)
520 {
521         vu_char *addr = (vu_char *)(info->start[0]);
522         ulong start;
523         int flag;
524
525         /* Check if Flash is (sufficiently) erased */
526         if ((*((vu_char *)dest) & data) != data) {
527                 printf(" *** ERROR: Flash not erased !\n");
528                 return (2);
529         }
530         flag = disable_interrupts();
531
532         addr[WRITE_ADDR1] = WRITE_DATA1;
533         addr[WRITE_ADDR2] = WRITE_DATA2;
534         addr[WRITE_ADDR3] = WRITE_DATA3;
535         *((vu_char *)dest) = data;
536
537         if (flag)
538                 enable_interrupts();
539
540         /* data polling for D7 */
541         start = get_timer (0);
542         addr = (vu_char *)dest;
543         while (( (*addr) & WRITE_CONFIRM_DATA) != (data & WRITE_CONFIRM_DATA)) {
544                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
545                         printf(" *** ERROR: Flash write timeout !");
546                         return (1);
547                 }
548         }
549         mvdebug (("-write_byte\n"));
550         return (0);
551 }
552
553 /*-----------------------------------------------------------------------
554  * Write a word to Flash, returns:
555  * 0 - OK
556  * 1 - write timeout
557  * 2 - Flash not erased
558  */
559 static int write_word (flash_info_t *info, ulong dest, ulong data)
560 {
561         int i,
562                 result = 0;
563
564         mvdebug (("+write_word : 0x%08lx @ 0x%08lx\n", data, dest));
565         for ( i=0; (i < 4) && (result == 0); i++, dest+=1 )
566                 result = write_char (info, dest, (data >> (8*(3-i))) & 0xff );
567         mvdebug (("-write_word\n"));
568         return result;
569 }
570 /*---------------------------------------------------------------- */