source: SVN/rincon/u-boot/board/cmi/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: 11.3 KB
Line 
1/*
2 * (C) Copyright 2003
3 * Martin Winistoerfer, martinwinistoerfer@gmx.ch.
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 * File:                flash.c
26 *
27 * Discription:         This Driver is for 28F320J3A, 28F640J3A and
28 *                      28F128J3A Intel flashs working in 16 Bit mode.
29 *                      They are single bank flashs.
30 *
31 *                      Most of this code is taken from existing u-boot
32 *                      source code.
33 */
34
35
36#include <common.h>
37#include <mpc5xx.h>
38
39#if defined(CONFIG_ENV_IS_IN_FLASH)
40# ifndef  CONFIG_ENV_ADDR
41#  define CONFIG_ENV_ADDR       (CFG_FLASH_BASE + CONFIG_ENV_OFFSET)
42# endif
43# ifndef  CONFIG_ENV_SIZE
44#  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
45# endif
46# ifndef  CONFIG_ENV_SECT_SIZE
47#  define CONFIG_ENV_SECT_SIZE  CONFIG_ENV_SIZE
48# endif
49#endif
50
51#define FLASH_ID_MASK                   0xFFFF
52#define FLASH_BLOCK_SIZE                0x00010000
53#define FLASH_CMD_READ_ID               0x0090
54#define FLASH_CMD_RESET                 0x00ff
55#define FLASH_CMD_BLOCK_ERASE           0x0020
56#define FLASH_CMD_ERASE_CONFIRM         0x00D0
57#define FLASH_CMD_CLEAR_STATUS          0x0050
58#define FLASH_CMD_SUSPEND_ERASE         0x00B0
59#define FLASH_CMD_WRITE                 0x0040
60#define FLASH_CMD_PROTECT               0x0060
61#define FLASH_CMD_PROTECT_SET           0x0001
62#define FLASH_CMD_PROTECT_CLEAR         0x00D0
63#define FLASH_STATUS_DONE               0x0080
64
65flash_info_t    flash_info[CFG_MAX_FLASH_BANKS];
66
67/*
68 * Local function prototypes
69 */
70static ulong    flash_get_size          (vu_short *addr, flash_info_t *info);
71static int      write_short             (flash_info_t *info, ulong dest, ushort data);
72static void     flash_get_offsets       (ulong base, flash_info_t *info);
73
74/*
75 * Initialize flash
76 */
77
78unsigned long flash_init (void)
79{
80        unsigned long size_b0;
81        int i;
82
83        /* Init: no FLASHes known */
84        for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
85                flash_info[i].flash_id = FLASH_UNKNOWN;
86        }
87
88        /* Static FLASH Bank configuration here - FIXME XXX */
89#if 1
90        debug ("\n## Get flash bank 1 size @ 0x%08x\n",FLASH_BASE0_PRELIM);
91#endif
92        size_b0 = flash_get_size((vu_short *)FLASH_BASE0_PRELIM, &flash_info[0]);
93
94        if (flash_info[0].flash_id == FLASH_UNKNOWN) {
95                printf ("## Unknown FLASH on Bank 0: "
96                        "ID 0x%lx, Size = 0x%08lx = %ld MB\n",
97                        flash_info[0].flash_id,
98                        size_b0, size_b0<<20);
99        }
100
101        flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]);
102
103        flash_info[0].size = size_b0;
104
105#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
106        /* monitor protection ON by default */
107        flash_protect(FLAG_PROTECT_SET,
108                      CFG_MONITOR_BASE,
109                      CFG_MONITOR_BASE+monitor_flash_len-1,
110                      &flash_info[0]);
111#endif
112
113#ifdef  CONFIG_ENV_IS_IN_FLASH
114        /* ENV protection ON by default */
115        flash_protect(FLAG_PROTECT_SET,
116                      CONFIG_ENV_ADDR,
117                      CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
118                      &flash_info[0]);
119#endif
120
121        return size_b0;
122}
123
124/*
125 * Compute start adress of each sector (block)
126 */
127
128static void flash_get_offsets (ulong base, flash_info_t *info)
129{
130        int i;
131
132        if (info->flash_id == FLASH_UNKNOWN) {
133                return;
134        }
135
136        switch (info->flash_id & FLASH_VENDMASK) {
137        case FLASH_MAN_INTEL:
138            for (i = 0; i < info->sector_count; i++) {
139                info->start[i] = base + i * FLASH_BLOCK_SIZE;
140            }
141            return;
142
143        default:
144            printf ("Don't know sector offsets for flash type 0x%lx\n",
145                info->flash_id);
146            return;
147        }
148}
149
150/*
151 * Print flash information
152 */
153void flash_print_info  (flash_info_t *info)
154{
155        int i;
156
157        if (info->flash_id == FLASH_UNKNOWN) {
158                printf ("missing or unknown FLASH type\n");
159                return;
160        }
161
162        switch (info->flash_id & FLASH_VENDMASK) {
163        case FLASH_MAN_AMD:     printf ("AMD ");                break;
164        case FLASH_MAN_FUJ:     printf ("Fujitsu ");            break;
165        case FLASH_MAN_SST:     printf ("SST ");                break;
166        case FLASH_MAN_STM:     printf ("STM ");                break;
167        case FLASH_MAN_INTEL:   printf ("Intel ");              break;
168        case FLASH_MAN_MT:      printf ("MT ");                 break;
169        default:                printf ("Unknown Vendor ");     break;
170        }
171
172        switch (info->flash_id & FLASH_TYPEMASK) {
173        case FLASH_28F320J3A:   printf ("28F320J3A (32Mbit) 16-Bit\n");
174                                break;
175        case FLASH_28F640J3A:   printf ("28F640J3A (64Mbit) 16-Bit\n");
176                                break;
177        case FLASH_28F128J3A:   printf ("28F128J3A (128Mbit) 16-Bit\n");
178                                break;
179        default:                printf ("Unknown Chip Type\n");
180                                break;
181        }
182
183        if (info->size >= (1 << 20)) {
184                i = 20;
185        } else {
186                i = 10;
187        }
188        printf ("  Size: %ld %cB in %d Sectors\n",
189                info->size >> i,
190                (i == 20) ? 'M' : 'k',
191                info->sector_count);
192
193        printf ("  Sector Start Addresses:");
194        for (i=0; i<info->sector_count; ++i) {
195                if ((i % 5) == 0)
196                        printf ("\n   ");
197                printf (" %08lX%s",
198                        info->start[i],
199                        info->protect[i] ? " (RO)" : "     "
200                );
201        }
202        printf ("\n");
203        return;
204}
205
206/*
207 * Get size of flash in bytes.
208 * The following code cannot be run from FLASH!
209 */
210
211static ulong flash_get_size (vu_short *addr, flash_info_t *info)
212{
213        vu_short value;
214
215        /* Read Manufacturer ID */
216        addr[0] = FLASH_CMD_READ_ID;
217        value = addr[0];
218
219        switch (value) {
220        case (AMD_MANUFACT & FLASH_ID_MASK):
221                info->flash_id = FLASH_MAN_AMD;
222                break;
223        case (FUJ_MANUFACT & FLASH_ID_MASK):
224                info->flash_id = FLASH_MAN_FUJ;
225                break;
226        case (SST_MANUFACT & FLASH_ID_MASK):
227                info->flash_id = FLASH_MAN_SST;
228                break;
229        case (STM_MANUFACT & FLASH_ID_MASK):
230                info->flash_id = FLASH_MAN_STM;
231                break;
232        case (INTEL_MANUFACT & FLASH_ID_MASK):
233                info->flash_id = FLASH_MAN_INTEL;
234                break;
235        default:
236                info->flash_id = FLASH_UNKNOWN;
237                info->sector_count = 0;
238                info->size = 0;
239                addr[0] = FLASH_CMD_RESET;      /* restore read mode */
240                return (0);                     /* no or unknown flash  */
241        }
242
243        value = addr[1];                        /* device ID            */
244
245        switch (value) {
246        case (INTEL_ID_28F320J3A  & FLASH_ID_MASK):
247                info->flash_id += FLASH_28F320J3A;
248                info->sector_count = 32;
249                info->size = 0x00400000;
250                break;                          /* =>  32 MBit          */
251
252        case (INTEL_ID_28F640J3A & FLASH_ID_MASK):
253                info->flash_id += FLASH_28F640J3A;
254                info->sector_count = 64;
255                info->size = 0x00800000;
256                break;                          /* => 64 MBit           */
257
258        case (INTEL_ID_28F128J3A & FLASH_ID_MASK):
259                info->flash_id += FLASH_28F128J3A;
260                info->sector_count = 128;
261                info->size = 0x01000000;
262                break;                          /* => 128 MBit          */
263
264        default:
265                info->flash_id = FLASH_UNKNOWN;
266                addr[0] = FLASH_CMD_RESET;      /* restore read mode */
267                return (0);                     /* => no or unknown flash */
268
269        }
270
271        if (info->sector_count > CFG_MAX_FLASH_SECT) {
272                printf ("** ERROR: sector count %d > max (%d) **\n",
273                        info->sector_count, CFG_MAX_FLASH_SECT);
274                info->sector_count = CFG_MAX_FLASH_SECT;
275        }
276
277        addr[0] = FLASH_CMD_RESET;              /* restore read mode */
278
279        return (info->size);
280}
281
282
283/*
284 * Erase unprotected sectors
285 */
286
287int flash_erase (flash_info_t *info, int s_first, int s_last)
288{
289        int flag, prot, sect;
290        ulong start, now, last;
291
292        if ((s_first < 0) || (s_first > s_last)) {
293                if (info->flash_id == FLASH_UNKNOWN) {
294                        printf ("- missing\n");
295                } else {
296                        printf ("- no sectors to erase\n");
297                }
298                return 1;
299        }
300
301        if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) {
302                printf ("Can erase only Intel flash types - aborted\n");
303                return 1;
304        }
305
306        prot = 0;
307        for (sect=s_first; sect<=s_last; ++sect) {
308                if (info->protect[sect]) {
309                        prot++;
310                }
311        }
312
313        if (prot) {
314                printf ("- Warning: %d protected sectors will not be erased!\n",
315                        prot);
316        } else {
317                printf ("\n");
318        }
319
320        start = get_timer (0);
321        last  = start;
322
323        /* Start erase on unprotected sectors */
324        for (sect = s_first; sect<=s_last; sect++) {
325                if (info->protect[sect] == 0) { /* not protected */
326                        vu_short *addr = (vu_short *)(info->start[sect]);
327                        unsigned long status;
328
329                        /* Disable interrupts which might cause a timeout here */
330                        flag = disable_interrupts();
331
332#ifdef DEBUG
333                        printf("Erase sector %d at start addr 0x%08X", sect, (unsigned int)info->start[sect]);
334#endif
335
336                        *addr = FLASH_CMD_CLEAR_STATUS;
337                        *addr = FLASH_CMD_BLOCK_ERASE;
338                        *addr = FLASH_CMD_ERASE_CONFIRM;
339
340                        /* re-enable interrupts if necessary */
341                        if (flag)
342                                enable_interrupts();
343
344                        /* wait at least 80us - let's wait 1 ms */
345                        udelay (1000);
346
347                        while (((status = *addr) & FLASH_STATUS_DONE) != FLASH_STATUS_DONE) {
348                                if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
349                                        printf("Flash erase timeout at address %lx\n", info->start[sect]);
350                                        *addr = FLASH_CMD_SUSPEND_ERASE;
351                                        *addr = FLASH_CMD_RESET;
352                                        return 1;
353                                }
354
355                                /* show that we're waiting */
356                                if ((now - last) > 1000) {      /* every second */
357                                        putc ('.');
358                                        last = now;
359                                }
360                        }
361                        *addr = FLASH_CMD_RESET;
362                }
363        }
364        printf (" done\n");
365        return 0;
366}
367
368/*
369 * Copy memory to flash, returns:
370 * 0 - OK
371 * 1 - write timeout
372 * 2 - Flash not erased
373 * 4 - Flash not identified
374 */
375
376int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
377{
378        ulong cp, wp;
379        ushort data;
380        int i, rc;
381
382        if (info->flash_id == FLASH_UNKNOWN) {
383                return 4;
384        }
385
386        wp = (addr & ~1);       /* get lower word aligned address */
387
388        /*
389         * handle unaligned start byte
390         */
391
392        if (addr - wp) {
393                data = 0;
394                data = (data << 8) | *src++;
395                --cnt;
396                if ((rc = write_short(info, wp, data)) != 0) {
397                        return (rc);
398                }
399                wp += 2;
400        }
401
402        /*
403         * handle word aligned part
404         */
405
406        while (cnt >= 2) {
407                data = 0;
408                for (i=0; i<2; ++i) {
409                        data = (data << 8) | *src++;
410                }
411
412                if ((rc = write_short(info, wp, data)) != 0) {
413                        return (rc);
414                }
415                wp  += 2;
416                cnt -= 2;
417        }
418
419        if (cnt == 0) {
420                return (0);
421        }
422
423        /*
424         * handle unaligned tail bytes
425         */
426
427        data = 0;
428        for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
429                data = (data << 8) | *src++;
430                --cnt;
431        }
432        for (; i<2; ++i, ++cp) {
433                data = (data << 8) | (*(uchar *)cp);
434        }
435
436        return (write_short(info, wp, data));
437
438}
439
440/*
441 * Write 16 bit (short) to flash
442 */
443
444static int write_short (flash_info_t *info, ulong dest, ushort data)
445{
446        vu_short *addr = (vu_short*)(info->start[0]);
447        ulong start;
448        int flag;
449
450        /* Check if Flash is (sufficiently) erased */
451        if ((*((vu_short *)dest) & data) != data) {
452                return (2);
453        }
454
455        /* Disable interrupts which might cause a timeout here */
456        flag = disable_interrupts();
457
458        if (!(info->flash_id & FLASH_VENDMASK)) {
459                return 4;
460        }
461        *addr = FLASH_CMD_ERASE_CONFIRM;
462        *addr = FLASH_CMD_WRITE;
463
464        *((vu_short *)dest) = data;
465
466        /* re-enable interrupts if necessary */
467        if (flag) {
468                enable_interrupts();
469        }
470
471        /* data polling for D7 */
472        start = get_timer (0);
473
474        /* wait for error or finish */
475        while(!(addr[0] & FLASH_STATUS_DONE)){
476                if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
477                        addr[0] = FLASH_CMD_RESET;
478                        return (1);
479                }
480        }
481
482        *addr = FLASH_CMD_RESET;
483        return (0);
484}
485
486/*
487 * Protects a flash sector
488 */
489
490int flash_real_protect(flash_info_t *info, long sector, int prot)
491{
492        vu_short *addr = (vu_short*)(info->start[sector]);
493        ulong start;
494
495        *addr = FLASH_CMD_CLEAR_STATUS;
496        *addr = FLASH_CMD_PROTECT;
497
498        if(prot) {
499                *addr = FLASH_CMD_PROTECT_SET;
500        } else {
501                *addr = FLASH_CMD_PROTECT_CLEAR;
502        }
503
504        /* wait for error or finish */
505        start = get_timer (0);
506        while(!(addr[0] & FLASH_STATUS_DONE)){
507                if (get_timer(start) > CFG_FLASH_ERASE_TOUT) {
508                        printf("Flash protect timeout at address %lx\n",  info->start[sector]);
509                        addr[0] = FLASH_CMD_RESET;
510                        return (1);
511                }
512        }
513        /* Set software protect flag */
514        info->protect[sector] = prot;
515        *addr = FLASH_CMD_RESET;
516        return (0);
517}
Note: See TracBrowser for help on using the repository browser.