source: SVN/rincon/u-boot/board/lpd7a40x/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: 10.6 KB
Line 
1/*
2 * (C) Copyright 2002
3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4 * Marius Groeger <mgroeger@sysgo.de>
5 *
6 * (C) Copyright 2002
7 * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
8 *
9 * See file CREDITS for list of people who contributed to this
10 * project.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
26 */
27
28/* #define DEBUG */
29
30#include <common.h>
31#include <environment.h>
32
33#define FLASH_BANK_SIZE 0x1000000       /* 16MB (2 x 8 MB) */
34#define MAIN_SECT_SIZE  0x40000         /* 256KB (2 x 128kB) */
35
36flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
37
38
39#define CMD_READ_ARRAY          0x00FF00FF
40#define CMD_IDENTIFY            0x00900090
41#define CMD_ERASE_SETUP         0x00200020
42#define CMD_ERASE_CONFIRM       0x00D000D0
43#define CMD_PROGRAM             0x00400040
44#define CMD_RESUME              0x00D000D0
45#define CMD_SUSPEND             0x00B000B0
46#define CMD_STATUS_READ         0x00700070
47#define CMD_STATUS_RESET        0x00500050
48
49#define BIT_BUSY                0x00800080
50#define BIT_ERASE_SUSPEND       0x00400040
51#define BIT_ERASE_ERROR         0x00200020
52#define BIT_PROGRAM_ERROR       0x00100010
53#define BIT_VPP_RANGE_ERROR     0x00080008
54#define BIT_PROGRAM_SUSPEND     0x00040004
55#define BIT_PROTECT_ERROR       0x00020002
56#define BIT_UNDEFINED           0x00010001
57
58#define BIT_SEQUENCE_ERROR      0x00300030
59#define BIT_TIMEOUT             0x80000000
60
61/*-----------------------------------------------------------------------
62 */
63
64ulong flash_init (void)
65{
66        int i, j;
67        ulong size = 0;
68
69        for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
70                ulong flashbase = 0;
71
72                flash_info[i].flash_id =
73                        (INTEL_MANUFACT     & FLASH_VENDMASK) |
74                        (INTEL_ID_28F640J3A & FLASH_TYPEMASK);
75                flash_info[i].size = FLASH_BANK_SIZE;
76                flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
77                memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
78                if (i == 0)
79                        flashbase = CFG_FLASH_BASE;
80                else
81                        panic ("configured too many flash banks!\n");
82                for (j = 0; j < flash_info[i].sector_count; j++) {
83                        flash_info[i].start[j] = flashbase;
84
85                        /* uniform sector size */
86                        flashbase += MAIN_SECT_SIZE;
87                }
88                size += flash_info[i].size;
89        }
90
91        /*
92         * Protect monitor and environment sectors
93         */
94        flash_protect ( FLAG_PROTECT_SET,
95                        CFG_FLASH_BASE,
96                        CFG_FLASH_BASE + monitor_flash_len - 1,
97                        &flash_info[0]);
98
99        flash_protect ( FLAG_PROTECT_SET,
100                        CONFIG_ENV_ADDR,
101                        CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
102
103#ifdef CONFIG_ENV_ADDR_REDUND
104        flash_protect ( FLAG_PROTECT_SET,
105                        CONFIG_ENV_ADDR_REDUND,
106                        CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SIZE_REDUND - 1,
107                        &flash_info[0]);
108#endif
109
110        return size;
111}
112
113/*-----------------------------------------------------------------------
114 */
115void flash_print_info (flash_info_t * info)
116{
117        int i;
118
119        switch (info->flash_id & FLASH_VENDMASK) {
120        case (INTEL_MANUFACT & FLASH_VENDMASK):
121                printf ("Intel: ");
122                break;
123        default:
124                printf ("Unknown Vendor ");
125                break;
126        }
127
128        switch (info->flash_id & FLASH_TYPEMASK) {
129        case (INTEL_ID_28F640J3A & FLASH_TYPEMASK):
130                printf ("2x 28F640J3A (64Mbit)\n");
131                break;
132        default:
133                printf ("Unknown Chip Type\n");
134                return;
135                break;
136        }
137
138        printf ("  Size: %ld MB in %d Sectors\n",
139                        info->size >> 20, info->sector_count);
140
141        printf ("  Sector Start Addresses:");
142        for (i = 0; i < info->sector_count; i++) {
143                if ((i % 5) == 0) {
144                        printf ("\n   ");
145                }
146                printf (" %08lX%s",
147                        info->start[i],
148                        info->protect[i] ? " (RO)" : "     ");
149        }
150        printf ("\n");
151}
152
153/*-----------------------------------------------------------------------
154 */
155
156int flash_error (ulong code)
157{
158        /* Check bit patterns */
159        /* SR.7=0 is busy, SR.7=1 is ready */
160        /* all other flags indicate error on 1 */
161        /* SR.0 is undefined */
162        /* Timeout is our faked flag */
163
164        /* sequence is described in Intel 290644-005 document */
165
166        /* check Timeout */
167        if (code & BIT_TIMEOUT) {
168                puts ("Timeout\n");
169                return ERR_TIMOUT;
170        }
171
172        /* check Busy, SR.7 */
173        if (~code & BIT_BUSY) {
174                puts ("Busy\n");
175                return ERR_PROG_ERROR;
176        }
177
178        /* check Vpp low, SR.3 */
179        if (code & BIT_VPP_RANGE_ERROR) {
180                puts ("Vpp range error\n");
181                return ERR_PROG_ERROR;
182        }
183
184        /* check Device Protect Error, SR.1 */
185        if (code & BIT_PROTECT_ERROR) {
186                puts ("Device protect error\n");
187                return ERR_PROG_ERROR;
188        }
189
190        /* check Command Seq Error, SR.4 & SR.5 */
191        if (code & BIT_SEQUENCE_ERROR) {
192                puts ("Command seqence error\n");
193                return ERR_PROG_ERROR;
194        }
195
196        /* check Block Erase Error, SR.5 */
197        if (code & BIT_ERASE_ERROR) {
198                puts ("Block erase error\n");
199                return ERR_PROG_ERROR;
200        }
201
202        /* check Program Error, SR.4 */
203        if (code & BIT_PROGRAM_ERROR) {
204                puts ("Program error\n");
205                return ERR_PROG_ERROR;
206        }
207
208        /* check Block Erase Suspended, SR.6 */
209        if (code & BIT_ERASE_SUSPEND) {
210                puts ("Block erase suspended\n");
211                return ERR_PROG_ERROR;
212        }
213
214        /* check Program Suspended, SR.2 */
215        if (code & BIT_PROGRAM_SUSPEND) {
216                puts ("Program suspended\n");
217                return ERR_PROG_ERROR;
218        }
219
220        /* OK, no error */
221        return ERR_OK;
222}
223
224/*-----------------------------------------------------------------------
225 */
226
227int flash_erase (flash_info_t * info, int s_first, int s_last)
228{
229        ulong result, result1;
230        int iflag, prot, sect;
231        int rc = ERR_OK;
232
233#ifdef USE_920T_MMU
234        int cflag;
235#endif
236
237        debug ("flash_erase: s_first %d  s_last %d\n", s_first, s_last);
238
239        /* first look for protection bits */
240
241        if (info->flash_id == FLASH_UNKNOWN)
242                return ERR_UNKNOWN_FLASH_TYPE;
243
244        if ((s_first < 0) || (s_first > s_last)) {
245                return ERR_INVAL;
246        }
247
248        if ((info->flash_id & FLASH_VENDMASK) !=
249                (INTEL_MANUFACT & FLASH_VENDMASK)) {
250                return ERR_UNKNOWN_FLASH_VENDOR;
251        }
252
253        prot = 0;
254        for (sect = s_first; sect <= s_last; ++sect) {
255                if (info->protect[sect]) {
256                        prot++;
257                }
258        }
259
260        if (prot) {
261                printf ("- Warning: %d protected sectors will not be erased!\n",
262                        prot);
263        } else {
264                printf ("\n");
265        }
266
267        /*
268         * Disable interrupts which might cause a timeout
269         * here. Remember that our exception vectors are
270         * at address 0 in the flash, and we don't want a
271         * (ticker) exception to happen while the flash
272         * chip is in programming mode.
273         */
274#ifdef USE_920T_MMU
275        cflag = dcache_status ();
276        dcache_disable ();
277#endif
278        iflag = disable_interrupts ();
279
280        /* Start erase on unprotected sectors */
281        for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
282
283                debug ("Erasing sector %2d @ %08lX... ",
284                        sect, info->start[sect]);
285
286                /* arm simple, non interrupt dependent timer */
287                reset_timer_masked();
288
289                if (info->protect[sect] == 0) { /* not protected */
290                        vu_long *addr = (vu_long *) (info->start[sect]);
291                        ulong bsR7, bsR7_2, bsR5, bsR5_2;
292
293                        /* *addr = CMD_STATUS_RESET; */
294                        *addr = CMD_ERASE_SETUP;
295                        *addr = CMD_ERASE_CONFIRM;
296
297                        /* wait until flash is ready */
298                        do {
299                                /* check timeout */
300                                if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
301                                        *addr = CMD_STATUS_RESET;
302                                        result = BIT_TIMEOUT;
303                                        break;
304                                }
305
306                                *addr = CMD_STATUS_READ;
307                                result = *addr;
308                                bsR7 = result & (1 << 7);
309                                bsR7_2 = result & (1 << 23);
310                        } while (!bsR7 | !bsR7_2);
311
312                        *addr = CMD_STATUS_READ;
313                        result1 = *addr;
314                        bsR5 = result1 & (1 << 5);
315                        bsR5_2 = result1 & (1 << 21);
316#ifdef SAMSUNG_FLASH_DEBUG
317                        printf ("bsR5 %lx bsR5_2 %lx\n", bsR5, bsR5_2);
318                        if (bsR5 != 0 && bsR5_2 != 0)
319                                printf ("bsR5 %lx bsR5_2 %lx\n", bsR5, bsR5_2);
320#endif
321
322                        *addr = CMD_READ_ARRAY;
323                        *addr = CMD_RESUME;
324
325                        if ((rc = flash_error (result)) != ERR_OK)
326                                goto outahere;
327#if 0
328                        printf ("ok.\n");
329                } else {                /* it was protected */
330
331                        printf ("protected!\n");
332#endif
333                }
334        }
335
336outahere:
337        /* allow flash to settle - wait 10 ms */
338        udelay_masked (10000);
339
340        if (iflag)
341                enable_interrupts ();
342
343#ifdef USE_920T_MMU
344        if (cflag)
345                dcache_enable ();
346#endif
347        return rc;
348}
349
350/*-----------------------------------------------------------------------
351 * Copy memory to flash
352 */
353
354static int write_word (flash_info_t * info, ulong dest, ulong data)
355{
356        vu_long *addr = (vu_long *) dest;
357        ulong result;
358        int rc = ERR_OK;
359        int iflag;
360
361#ifdef USE_920T_MMU
362        int cflag;
363#endif
364
365        /*
366         * Check if Flash is (sufficiently) erased
367         */
368        result = *addr;
369        if ((result & data) != data)
370                return ERR_NOT_ERASED;
371
372        /*
373         * Disable interrupts which might cause a timeout
374         * here. Remember that our exception vectors are
375         * at address 0 in the flash, and we don't want a
376         * (ticker) exception to happen while the flash
377         * chip is in programming mode.
378         */
379#ifdef USE_920T_MMU
380        cflag = dcache_status ();
381        dcache_disable ();
382#endif
383        iflag = disable_interrupts ();
384
385        /* *addr = CMD_STATUS_RESET; */
386        *addr = CMD_PROGRAM;
387        *addr = data;
388
389        /* arm simple, non interrupt dependent timer */
390        reset_timer_masked ();
391
392        /* wait until flash is ready */
393        do {
394                /* check timeout */
395                if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
396                        *addr = CMD_SUSPEND;
397                        result = BIT_TIMEOUT;
398                        break;
399                }
400
401                *addr = CMD_STATUS_READ;
402                result = *addr;
403        } while (~result & BIT_BUSY);
404
405        /* *addr = CMD_READ_ARRAY; */
406        *addr = CMD_STATUS_READ;
407        result = *addr;
408
409        rc = flash_error (result);
410
411        if (iflag)
412                enable_interrupts ();
413
414#ifdef USE_920T_MMU
415        if (cflag)
416                dcache_enable ();
417#endif
418        *addr = CMD_READ_ARRAY;
419        *addr = CMD_RESUME;
420        return rc;
421}
422
423/*-----------------------------------------------------------------------
424 * Copy memory to flash.
425 */
426
427int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
428{
429        ulong cp, wp, data;
430        int l;
431        int i, rc;
432
433        wp = (addr & ~3);                       /* get lower word aligned address */
434
435        /*
436         * handle unaligned start bytes
437         */
438        if ((l = addr - wp) != 0) {
439                data = 0;
440                for (i = 0, cp = wp; i < l; ++i, ++cp) {
441                        data = (data >> 8) | (*(uchar *) cp << 24);
442                }
443                for (; i < 4 && cnt > 0; ++i) {
444                        data = (data >> 8) | (*src++ << 24);
445                        --cnt;
446                        ++cp;
447                }
448                for (; cnt == 0 && i < 4; ++i, ++cp) {
449                        data = (data >> 8) | (*(uchar *) cp << 24);
450                }
451
452                if ((rc = write_word (info, wp, data)) != 0) {
453                        return (rc);
454                }
455                wp += 4;
456        }
457
458        /*
459         * handle word aligned part
460         */
461        while (cnt >= 4) {
462                data = *((vu_long *) src);
463                if ((rc = write_word (info, wp, data)) != 0) {
464                        return (rc);
465                }
466                src += 4;
467                wp += 4;
468                cnt -= 4;
469        }
470
471        if (cnt == 0) {
472                return ERR_OK;
473        }
474
475        /*
476         * handle unaligned tail bytes
477         */
478        data = 0;
479        for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
480                data = (data >> 8) | (*src++ << 24);
481                --cnt;
482        }
483        for (; i < 4; ++i, ++cp) {
484                data = (data >> 8) | (*(uchar *) cp << 24);
485        }
486
487        return write_word (info, wp, data);
488}
Note: See TracBrowser for help on using the repository browser.