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

Last change on this file since 55 was 55, checked in by Tim Harvey, 22 months ago

rincon: added latest u-boot source

restored form server backup

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

File size: 10.4 KB
Line 
1/*
2 * (C)  Copyright 2001
3 * Stäubli Faverges - <www.staubli.com>
4 * Pierre AUBERT  p.aubert@staubli.com
5 * U-Boot port on RPXClassic LF (CLLF_BW31) board
6 *
7 * RPXClassic uses Am29DL323B flash memory with 2 banks
8 *
9 *
10 * (C) Copyright 2000
11 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
12 *
13 * See file CREDITS for list of people who contributed to this
14 * project.
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License as
18 * published by the Free Software Foundation; either version 2 of
19 * the License, or (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29 * MA 02111-1307 USA
30 */
31
32
33#include <common.h>
34#include <mpc8xx.h>
35
36flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips        */
37
38/*-----------------------------------------------------------------------
39 * Functions
40 */
41static ulong flash_get_size (vu_long *addr, flash_info_t *info);
42static int write_word (flash_info_t *info, ulong dest, ulong data);
43static void flash_get_offsets (ulong base, flash_info_t *info);
44
45/*-----------------------------------------------------------------------
46 */
47
48unsigned long flash_init (void)
49{
50        unsigned long size_b0 ;
51        int i;
52
53        /* Init: no FLASHes known */
54        for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
55                flash_info[i].flash_id = FLASH_UNKNOWN;
56        }
57
58        size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
59
60
61        flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
62
63#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
64        /* monitor protection ON by default */
65        flash_protect(FLAG_PROTECT_SET,
66                      CFG_MONITOR_BASE,
67                      CFG_MONITOR_BASE+monitor_flash_len-1,
68                      &flash_info[0]);
69#endif
70
71        flash_info[0].size = size_b0;
72
73        return (size_b0);
74}
75
76/*-----------------------------------------------------------------------
77 */
78static void flash_get_offsets (ulong base, flash_info_t *info)
79{
80        int i;
81
82        if (info->flash_id & FLASH_BTYPE) {
83                /* set sector offsets for bottom boot block type        */
84                info->start[0] = base + 0x00000000;
85                info->start[1] = base + 0x00008000;
86                info->start[2] = base + 0x00010000;
87                info->start[3] = base + 0x00018000;
88                info->start[4] = base + 0x00020000;
89                info->start[5] = base + 0x00028000;
90                info->start[6] = base + 0x00030000;
91                info->start[7] = base + 0x00038000;
92                for (i = 8; i < info->sector_count; i++) {
93                        info->start[i] = base + ((i-7) * 0x00040000) ;
94                }
95        }
96}
97
98/*-----------------------------------------------------------------------
99 */
100void flash_print_info  (flash_info_t *info)
101{
102        int i;
103
104        if (info->flash_id == FLASH_UNKNOWN) {
105                printf ("missing or unknown FLASH type\n");
106                return;
107        }
108
109        switch (info->flash_id & FLASH_VENDMASK) {
110        case FLASH_MAN_AMD:     printf ("AMD ");                break;
111        default:                printf ("Unknown Vendor ");     break;
112        }
113
114        switch (info->flash_id & FLASH_TYPEMASK) {
115        case FLASH_AMDL323B:
116            printf ("AMDL323DB (16 Mbytes, bottom boot sect)\n");
117            break;
118        default:
119            printf ("Unknown Chip Type\n");
120            break;
121        }
122
123        printf ("  Size: %ld MB in %d Sectors\n",
124                info->size >> 20, info->sector_count);
125
126        printf ("  Sector Start Addresses:");
127        for (i=0; i<info->sector_count; ++i) {
128                if ((i % 5) == 0)
129                        printf ("\n   ");
130                printf (" %08lX%s",
131                        info->start[i],
132                        info->protect[i] ? " (RO)" : "     "
133                );
134        }
135        printf ("\n");
136}
137
138/*-----------------------------------------------------------------------
139 */
140
141
142/*-----------------------------------------------------------------------
143 */
144
145/*
146 * The following code cannot be run from FLASH!
147 */
148
149static ulong flash_get_size (vu_long *addr, flash_info_t *info)
150{
151        short i;
152        ulong value;
153        ulong base = (ulong)addr;
154
155        /* Reset flash componeny                                             */
156        addr [0] = 0xf0f0f0f0;
157
158        /* Write auto select command: read Manufacturer ID */
159        addr[0xAAA] = 0xAAAAAAAA ;
160        addr[0x555] = 0x55555555 ;
161        addr[0xAAA] = 0x90909090 ;
162
163        value = addr[0] ;
164
165        switch (value & 0x00FF00FF) {
166        case AMD_MANUFACT:
167                info->flash_id = FLASH_MAN_AMD;
168                break;
169        default:
170                info->flash_id = FLASH_UNKNOWN;
171                info->sector_count = 0;
172                info->size = 0;
173                return (0);                     /* no or unknown flash  */
174        }
175
176        value = addr[2] ;               /* device ID            */
177
178        switch (value & 0x00FF00FF) {
179        case (AMD_ID_DL323B & 0x00FF00FF):
180            info->flash_id += FLASH_AMDL323B;
181            info->sector_count = 71;
182            info->size = 0x01000000;            /* 16 Mb                     */
183
184            break;
185        default:
186                info->flash_id = FLASH_UNKNOWN;
187                return (0);                     /* => no or unknown flash */
188
189        }
190        /* set up sector start address table */
191        /* set sector offsets for bottom boot block type        */
192        info->start[0] = base + 0x00000000;
193        info->start[1] = base + 0x00008000;
194        info->start[2] = base + 0x00010000;
195        info->start[3] = base + 0x00018000;
196        info->start[4] = base + 0x00020000;
197        info->start[5] = base + 0x00028000;
198        info->start[6] = base + 0x00030000;
199        info->start[7] = base + 0x00038000;
200        for (i = 8; i < info->sector_count; i++) {
201            info->start[i] = base + ((i-7) * 0x00040000) ;
202        }
203
204        /* check for protected sectors */
205        for (i = 0; i < 23; i++) {
206            /* read sector protection at sector address, (A7 .. A0) = 0x02 */
207            /* D0 = 1 if protected */
208            addr = (volatile unsigned long *)(info->start[i]);
209            info->protect[i] = addr[4] & 1 ;
210        }
211        /* Check for protected sectors in the 2nd bank                       */
212        addr[0x100AAA] = 0xAAAAAAAA ;
213        addr[0x100555] = 0x55555555 ;
214        addr[0x100AAA] = 0x90909090 ;
215
216        for (i = 23; i < info->sector_count; i++) {
217            /* read sector protection at sector address, (A7 .. A0) = 0x02 */
218            /* D0 = 1 if protected */
219            addr = (volatile unsigned long *)(info->start[i]);
220            info->protect[i] = addr[4] & 1 ;
221        }
222
223        /*
224         * Prevent writes to uninitialized FLASH.
225         */
226        if (info->flash_id != FLASH_UNKNOWN) {
227                addr = (volatile unsigned long *)info->start[0];
228
229                *addr = 0xF0F0F0F0;     /* reset bank 1                      */
230                addr = (volatile unsigned long *)info->start[23];
231
232                *addr = 0xF0F0F0F0;     /* reset bank 2                      */
233
234        }
235
236        return (info->size);
237}
238
239
240/*-----------------------------------------------------------------------
241 */
242
243int     flash_erase (flash_info_t *info, int s_first, int s_last)
244{
245        vu_long *addr = (vu_long*)(info->start[0]);
246        int flag, prot, sect, l_sect;
247        ulong start, now, last;
248
249        if ((s_first < 0) || (s_first > s_last)) {
250                if (info->flash_id == FLASH_UNKNOWN) {
251                        printf ("- missing\n");
252                } else {
253                        printf ("- no sectors to erase\n");
254                }
255                return 1;
256        }
257
258        if ((info->flash_id == FLASH_UNKNOWN) ||
259            (info->flash_id > FLASH_AMD_COMP)) {
260                printf ("Can't erase unknown flash type %08lx - aborted\n",
261                        info->flash_id);
262                return 1;
263        }
264
265        prot = 0;
266        for (sect=s_first; sect<=s_last; ++sect) {
267                if (info->protect[sect]) {
268                        prot++;
269                }
270        }
271
272        if (prot) {
273                printf ("- Warning: %d protected sectors will not be erased!\n",
274                        prot);
275        } else {
276                printf ("\n");
277        }
278
279        l_sect = -1;
280
281        /* Disable interrupts which might cause a timeout here */
282        flag = disable_interrupts();
283
284        addr[0xAAA] = 0xAAAAAAAA;
285        addr[0x555] = 0x55555555;
286        addr[0xAAA] = 0x80808080;
287        addr[0xAAA] = 0xAAAAAAAA;
288        addr[0x555] = 0x55555555;
289
290        /* Start erase on unprotected sectors */
291        for (sect = s_first; sect<=s_last; sect++) {
292                if (info->protect[sect] == 0) { /* not protected */
293                        addr = (vu_long *)(info->start[sect]) ;
294                        addr[0] = 0x30303030 ;
295                        l_sect = sect;
296                }
297        }
298
299        /* re-enable interrupts if necessary */
300        if (flag)
301                enable_interrupts();
302
303        /* wait at least 80us - let's wait 1 ms */
304        udelay (1000);
305
306        /*
307         * We wait for the last triggered sector
308         */
309        if (l_sect < 0)
310                goto DONE;
311
312        start = get_timer (0);
313        last  = start;
314        addr = (vu_long *)(info->start[l_sect]);
315        while ((addr[0] & 0x80808080) != 0x80808080) {
316                if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
317                        printf ("Timeout\n");
318                        return 1;
319                }
320                /* show that we're waiting */
321                if ((now - last) > 1000) {      /* every second */
322                        putc ('.');
323                        last = now;
324                }
325        }
326
327DONE:
328        /* reset to read mode */
329        addr = (vu_long *)info->start[0];
330        addr[0] = 0xF0F0F0F0;   /* reset bank */
331
332        printf (" done\n");
333        return 0;
334}
335
336/*-----------------------------------------------------------------------
337 * Copy memory to flash, returns:
338 * 0 - OK
339 * 1 - write timeout
340 * 2 - Flash not erased
341 */
342
343int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
344{
345        ulong cp, wp, data;
346        int i, l, rc;
347
348        wp = (addr & ~3);       /* get lower word aligned address */
349
350        /*
351         * handle unaligned start bytes
352         */
353        if ((l = addr - wp) != 0) {
354                data = 0;
355                for (i=0, cp=wp; i<l; ++i, ++cp) {
356                        data = (data << 8) | (*(uchar *)cp);
357                }
358                for (; i<4 && cnt>0; ++i) {
359                        data = (data << 8) | *src++;
360                        --cnt;
361                        ++cp;
362                }
363                for (; cnt==0 && i<4; ++i, ++cp) {
364                        data = (data << 8) | (*(uchar *)cp);
365                }
366
367                if ((rc = write_word(info, wp, data)) != 0) {
368                        return (rc);
369                }
370                wp += 4;
371        }
372
373        /*
374         * handle word aligned part
375         */
376        while (cnt >= 4) {
377                data = 0;
378                for (i=0; i<4; ++i) {
379                        data = (data << 8) | *src++;
380                }
381                if ((rc = write_word(info, wp, data)) != 0) {
382                        return (rc);
383                }
384                wp  += 4;
385                cnt -= 4;
386        }
387
388        if (cnt == 0) {
389                return (0);
390        }
391
392        /*
393         * handle unaligned tail bytes
394         */
395        data = 0;
396        for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
397                data = (data << 8) | *src++;
398                --cnt;
399        }
400        for (; i<4; ++i, ++cp) {
401                data = (data << 8) | (*(uchar *)cp);
402        }
403
404        return (write_word(info, wp, data));
405}
406
407/*-----------------------------------------------------------------------
408 * Write a word to Flash, returns:
409 * 0 - OK
410 * 1 - write timeout
411 * 2 - Flash not erased
412 */
413static int write_word (flash_info_t *info, ulong dest, ulong data)
414{
415        vu_long *addr = (vu_long *)(info->start[0]);
416        ulong start;
417        int flag;
418
419        /* Check if Flash is (sufficiently) erased */
420        if ((*((vu_long *)dest) & data) != data) {
421                return (2);
422        }
423        /* Disable interrupts which might cause a timeout here */
424        flag = disable_interrupts();
425
426        addr[0xAAA] = 0xAAAAAAAA;
427        addr[0x555] = 0x55555555;
428        addr[0xAAA] = 0xA0A0A0A0;
429
430        *((vu_long *)dest) = data;
431
432        /* re-enable interrupts if necessary */
433        if (flag)
434                enable_interrupts();
435
436        /* data polling for D7 */
437        start = get_timer (0);
438        while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) {
439                if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
440                        return (1);
441                }
442        }
443        return (0);
444}
445
446/*-----------------------------------------------------------------------
447 */
Note: See TracBrowser for help on using the repository browser.