source: SVN/rincon/u-boot/board/RPXlite_dw/flash.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 2 years ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 12.6 KB
Line 
1/*
2 * (C) Copyright 2004
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 * Yoo. Jonghoon, IPone, yooth@ipone.co.kr
26 * U-Boot port on RPXlite board
27 *
28 * Some of flash control words are modified. (from 2x16bit device
29 * to 4x8bit device)
30 * RPXLite board I tested has only 4 AM29LV800BB devices. Other devices
31 * are not tested.
32 *
33 * (?) Does an RPXLite board which
34 *      does not use AM29LV800 flash memory exist ?
35 *      I don't know...
36 */
37
38/* Yes,Yoo.They do use other FLASH for the board.
39 *
40 * Sam Song, IEMC. SHU, samsongshu@yahoo.com.cn
41 * U-Boot port on RPXlite DW version board
42 *
43 * By now,it uses 4 AM29DL323DB90VI devices(4x8bit).
44 * The total FLASH has 16MB(4x4MB).
45 * I just made some necessary changes on the basis of Wolfgang and Yoo's job.
46 *
47 * June 8, 2004 */
48
49#include <common.h>
50#include <mpc8xx.h>
51
52flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips        */
53
54/*-----------------------------------------------------------------------
55 * Functions   vu_long : volatile unsigned long IN include/common.h
56 */
57static ulong flash_get_size (vu_long *addr, flash_info_t *info);
58static int write_word (flash_info_t *info, ulong dest, ulong data);
59static void flash_get_offsets (ulong base, flash_info_t *info);
60
61unsigned long flash_init (void)
62{
63        unsigned long size_b0 ;
64        int i;
65
66        /* Init: no FLASHes known */
67        for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
68                flash_info[i].flash_id = FLASH_UNKNOWN;
69        }
70
71        size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
72        flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
73
74#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
75        /* If Monitor is in the cope of FLASH,then
76         * protect this area by default in case for
77         * other occupation. [SAM] */
78
79        /* monitor protection ON by default */
80        flash_protect(FLAG_PROTECT_SET,
81                      CFG_MONITOR_BASE,
82                      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
83                      &flash_info[0]);
84#endif
85        flash_info[0].size = size_b0;
86        return (size_b0);
87}
88
89static void flash_get_offsets (ulong base, flash_info_t *info)
90{
91        int i;
92
93        /* set up sector start address table */
94        if (info->flash_id & FLASH_BTYPE) {
95                info->start[0] = base + 0x00000000;
96                info->start[1] = base + 0x00008000;
97                info->start[2] = base + 0x00010000;
98                info->start[3] = base + 0x00018000;
99                info->start[4] = base + 0x00020000;
100                info->start[5] = base + 0x00028000;
101                info->start[6] = base + 0x00030000;
102                info->start[7] = base + 0x00038000;
103
104                for (i = 8; i < info->sector_count; i++) {
105                        info->start[i] = base + ((i-7) * 0x00040000);
106                }
107        } else {
108                i = info->sector_count - 1;
109                info->start[i--] = base + info->size - 0x00010000;
110                info->start[i--] = base + info->size - 0x00018000;
111                info->start[i--] = base + info->size - 0x00020000;
112                for (; i >= 0; i--) {
113                        info->start[i] = base + i * 0x00040000;
114                }
115        }
116
117}
118
119void flash_print_info  (flash_info_t *info)
120{
121        int i;
122
123        if (info->flash_id == FLASH_UNKNOWN) {
124                printf ("missing or unknown FLASH type\n");
125                return;
126        }
127
128        switch (info->flash_id & FLASH_VENDMASK) {
129        case FLASH_MAN_AMD:     printf ("AMD ");                break;
130        case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
131        default:                printf ("Unknown Vendor ");     break;
132        }
133
134        switch (info->flash_id & FLASH_TYPEMASK) {
135        case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
136                                break;
137        case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
138                                break;
139        case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
140                                break;
141        case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
142                                break;
143        case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
144                                break;
145        case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
146                                break;
147        case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
148                                break;
149        case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
150                                break;
151        case FLASH_AMDL323B:    printf ("AM29DL323B (32 Mbit, bottom boot sector)\n");
152                                break;
153        /* I just add the FLASH_AMDL323B for RPXlite_DW BOARD. [SAM]  */
154        default:                printf ("Unknown Chip Type\n");
155                                break;
156        }
157        printf ("  Size: %ld MB in %d Sectors\n",info->size >> 20, info->sector_count);
158        printf ("  Sector Start Addresses:");
159        for (i=0; i<info->sector_count; ++i) {
160                if ((i % 5) == 0)
161                        printf ("\n   ");
162                printf (" %08lX%s",info->start[i],info->protect[i] ? " (RO)" : "     ");
163        }
164        printf ("\n");
165        return;
166}
167
168static ulong flash_get_size (vu_long *addr, flash_info_t *info)
169{
170        short i;
171        ulong value;
172        ulong base = (ulong)addr;
173
174        /* Write auto select command: read Manufacturer ID */
175        addr[0xAAA] = 0x00AA00AA ;
176        addr[0x555] = 0x00550055 ;
177        addr[0xAAA] = 0x00900090 ;
178
179        value = addr[0] ;
180        switch (value & 0x00FF00FF) {
181        case AMD_MANUFACT:                      /* AMD_MANUFACT =0x00010001 in flash.h */
182                info->flash_id = FLASH_MAN_AMD; /* FLASH_MAN_AMD=0x00000000 in flash.h */
183                break;
184        case FUJ_MANUFACT:
185                info->flash_id = FLASH_MAN_FUJ;
186                break;
187        default:
188                info->flash_id = FLASH_UNKNOWN;
189                info->sector_count = 0;
190                info->size = 0;
191                return (0);                     /* no or unknown flash  */
192        }
193
194        value = addr[2] ;                       /* device ID            */
195        switch (value & 0x00FF00FF) {
196        case (AMD_ID_LV400T & 0x00FF00FF):
197                info->flash_id += FLASH_AM400T;
198                info->sector_count = 11;
199                info->size = 0x00100000;
200                break;                          /* => 1 MB              */
201        case (AMD_ID_LV400B & 0x00FF00FF):
202                info->flash_id += FLASH_AM400B;
203                info->sector_count = 11;
204                info->size = 0x00100000;
205                break;                          /* => 1 MB              */
206        case (AMD_ID_LV800T & 0x00FF00FF):
207                info->flash_id += FLASH_AM800T;
208                info->sector_count = 19;
209                info->size = 0x00200000;
210                break;                          /* => 2 MB              */
211        case (AMD_ID_LV800B & 0x00FF00FF):
212                info->flash_id += FLASH_AM800B;
213                info->sector_count = 19;
214                info->size = 0x00400000;        /* Size doubled by yooth */
215                break;                          /* => 4 MB               */
216        case (AMD_ID_LV160T & 0x00FF00FF):
217                info->flash_id += FLASH_AM160T;
218                info->sector_count = 35;
219                info->size = 0x00400000;
220                break;                          /* => 4 MB              */
221        case (AMD_ID_LV160B & 0x00FF00FF):
222                info->flash_id += FLASH_AM160B;
223                info->sector_count = 35;
224                info->size = 0x00400000;
225                break;                          /* => 4 MB              */
226        case (AMD_ID_DL323B & 0x00FF00FF):
227                info->flash_id += FLASH_AMDL323B;
228                info->sector_count = 71;
229                info->size = 0x01000000;
230                break;                          /* => 16 MB(4x4MB)  */
231        /* AMD_ID_DL323B= 0x22532253  FLASH_AMDL323B= 0x0013
232         * AMD_ID_DL323B could be found in <flash.h>.[SAM]
233         * So we could get : flash_id = 0x00000013.
234         * The first four-bit represents VEDOR ID,leaving others for FLASH ID. */
235        default:
236                info->flash_id = FLASH_UNKNOWN;
237                return (0);                     /* => no or unknown flash */
238
239        }
240        /* set up sector start address table */
241        if (info->flash_id & FLASH_BTYPE) {
242        /* FLASH_BTYPE=0x0001 mask for bottom boot sector type.If the last bit equals 1,
243         * it means bottom boot flash. GOOD IDEA! [SAM]
244         */
245
246        /* set sector offsets for bottom boot block type        */
247                info->start[0] = base + 0x00000000;
248                info->start[1] = base + 0x00008000;
249                info->start[2] = base + 0x00010000;
250                info->start[3] = base + 0x00018000;
251                info->start[4] = base + 0x00020000;
252                info->start[5] = base + 0x00028000;
253                info->start[6] = base + 0x00030000;
254                info->start[7] = base + 0x00038000;
255
256                for (i = 8; i < info->sector_count; i++) {
257                        info->start[i] = base + ((i-7) * 0x00040000) ;
258                }
259        } else {
260                /* set sector offsets for top boot block type           */
261                i = info->sector_count - 1;
262                info->start[i--] = base + info->size - 0x00010000;
263                info->start[i--] = base + info->size - 0x00018000;
264                info->start[i--] = base + info->size - 0x00020000;
265                for (; i >= 0; i--) {
266                        info->start[i] = base + i * 0x00040000;
267                }
268        }
269
270        /* check for protected sectors */
271        for (i = 0; i < info->sector_count; i++) {
272                /* read sector protection at sector address, (A7 .. A0) = 0x02 */
273                /* D0 = 1 if protected */
274                addr = (volatile unsigned long *)(info->start[i]);
275                /* info->protect[i] = addr[4] & 1 ; */
276                /* Mask it for disorder FLASH protection **[Sam]** */
277        }
278
279        /*
280         * Prevent writes to uninitialized FLASH.
281         */
282        if (info->flash_id != FLASH_UNKNOWN) {
283                addr = (volatile unsigned long *)info->start[0];
284
285                *addr = 0xF0F0F0F0;     /* reset bank */
286        }
287        return (info->size);
288}
289
290int     flash_erase (flash_info_t *info, int s_first, int s_last)
291{
292        vu_long *addr = (vu_long*)(info->start[0]);
293        int flag, prot, sect, l_sect;
294        ulong start, now, last;
295
296        if ((s_first < 0) || (s_first > s_last)) {
297                if (info->flash_id == FLASH_UNKNOWN) {
298                        printf ("- missing\n");
299                } else {
300                        printf ("- no sectors to erase\n");
301                }
302                return 1;
303        }
304
305        if ((info->flash_id == FLASH_UNKNOWN) ||
306            (info->flash_id > FLASH_AMD_COMP)) {
307                printf ("Can't erase unknown flash type %08lx - aborted\n",
308                        info->flash_id);
309                return 1;
310        }
311
312        prot = 0;
313        for (sect=s_first; sect<=s_last; ++sect) {
314                if (info->protect[sect]) {
315                        prot++;
316                }
317        }
318
319        if (prot) {
320                printf ("- Warning: %d protected sectors will not be erased!\n",
321                        prot);
322        } else {
323                printf ("\n");
324        }
325
326        l_sect = -1;
327
328        /* Disable interrupts which might cause a timeout here */
329        flag = disable_interrupts();
330
331        addr[0xAAA] = 0xAAAAAAAA;
332        addr[0x555] = 0x55555555;
333        addr[0xAAA] = 0x80808080;
334        addr[0xAAA] = 0xAAAAAAAA;
335        addr[0x555] = 0x55555555;
336
337        /* Start erase on unprotected sectors */
338        for (sect = s_first; sect<=s_last; sect++) {
339                if (info->protect[sect] == 0) { /* not protected */
340                        addr = (vu_long *)(info->start[sect]) ;
341                        addr[0] = 0x30303030 ;
342                        l_sect = sect;
343                }
344        }
345
346        /* re-enable interrupts if necessary */
347        if (flag)
348                enable_interrupts();
349
350        /* wait at least 80us - let's wait 1 ms */
351        udelay (1000);
352
353        /*
354         * We wait for the last triggered sector
355         */
356        if (l_sect < 0)
357                goto DONE;
358
359        start = get_timer (0);
360        last  = start;
361        addr = (vu_long *)(info->start[l_sect]);
362        while ((addr[0] & 0x80808080) != 0x80808080) {
363                if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
364                        printf ("Timeout\n");
365                        return 1;
366                }
367                /* show that we're waiting */
368                if ((now - last) > 1000) {      /* every second */
369                        putc ('.');
370                        last = now;
371                }
372        }
373
374DONE:
375        /* reset to read mode */
376        addr = (vu_long *)info->start[0];
377        addr[0] = 0xF0F0F0F0;   /* reset bank */
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
390int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
391{
392        ulong cp, wp, data;
393        int i, l, rc;
394
395        wp = (addr & ~3);       /* get lower word aligned address */
396
397        /*
398         * handle unaligned start bytes
399         */
400        if ((l = addr - wp) != 0) {
401                data = 0;
402                for (i=0, cp=wp; i<l; ++i, ++cp) {
403                        data = (data << 8) | (*(uchar *)cp);
404                }
405                for (; i<4 && cnt>0; ++i) {
406                        data = (data << 8) | *src++;
407                        --cnt;
408                        ++cp;
409                }
410                for (; cnt==0 && i<4; ++i, ++cp) {
411                        data = (data << 8) | (*(uchar *)cp);
412                }
413
414                if ((rc = write_word(info, wp, data)) != 0) {
415                        return (rc);
416                }
417                wp += 4;
418        }
419
420        /*
421         * handle word aligned part
422         */
423        while (cnt >= 4) {
424                data = 0;
425                for (i=0; i<4; ++i) {
426                        data = (data << 8) | *src++;
427                }
428                if ((rc = write_word(info, wp, data)) != 0) {
429                        return (rc);
430                }
431                wp  += 4;
432                cnt -= 4;
433        }
434
435        if (cnt == 0) {
436                return (0);
437        }
438
439        /*
440         * handle unaligned tail bytes
441         */
442        data = 0;
443        for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
444                data = (data << 8) | *src++;
445                --cnt;
446        }
447        for (; i<4; ++i, ++cp) {
448                data = (data << 8) | (*(uchar *)cp);
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 */
459static int write_word (flash_info_t *info, ulong dest, ulong data)
460{
461        vu_long *addr = (vu_long *)(info->start[0]);
462        ulong start;
463        int flag;
464
465        /* Check if Flash is (sufficiently) erased */
466        if ((*((vu_long *)dest) & data) != data) {
467                return (2);
468        }
469        /* Disable interrupts which might cause a timeout here */
470        flag = disable_interrupts();
471
472        addr[0xAAA] = 0xAAAAAAAA;
473        addr[0x555] = 0x55555555;
474        addr[0xAAA] = 0xA0A0A0A0;
475
476        *((vu_long *)dest) = data;
477
478        /* re-enable interrupts if necessary */
479        if (flag)
480                enable_interrupts();
481
482        /* data polling for D7 */
483        start = get_timer (0);
484        while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) {
485                if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
486                        return (1);
487                }
488        }
489        return (0);
490}
Note: See TracBrowser for help on using the repository browser.