source: SVN/rincon/u-boot/board/freescale/m5253demo/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: 9.9 KB
Line 
1/*
2 * (C) Copyright 2000-2003
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
6 * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
7 *
8 * See file CREDITS for list of people who contributed to this
9 * project.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 * MA 02111-1307 USA
25 */
26
27#include <common.h>
28
29#include <asm/immap.h>
30
31#ifndef CFG_FLASH_CFI
32typedef unsigned short FLASH_PORT_WIDTH;
33typedef volatile unsigned short FLASH_PORT_WIDTHV;
34
35#define FPW             FLASH_PORT_WIDTH
36#define FPWV            FLASH_PORT_WIDTHV
37
38#define FLASH_CYCLE1    0x5555
39#define FLASH_CYCLE2    0x2aaa
40
41#define SYNC                    __asm__("nop")
42
43/*-----------------------------------------------------------------------
44 * Functions
45 */
46
47ulong flash_get_size(FPWV * addr, flash_info_t * info);
48int flash_get_offsets(ulong base, flash_info_t * info);
49int write_word(flash_info_t * info, FPWV * dest, u16 data);
50void inline spin_wheel(void);
51
52flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
53
54ulong flash_init(void)
55{
56        ulong size = 0;
57        ulong fbase = 0;
58
59        fbase = (ulong) CFG_FLASH_BASE;
60        flash_get_size((FPWV *) fbase, &flash_info[0]);
61        flash_get_offsets((ulong) fbase, &flash_info[0]);
62        fbase += flash_info[0].size;
63        size += flash_info[0].size;
64
65        /* Protect monitor and environment sectors */
66        flash_protect(FLAG_PROTECT_SET,
67                      CFG_MONITOR_BASE,
68                      CFG_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]);
69
70        return size;
71}
72
73int flash_get_offsets(ulong base, flash_info_t * info)
74{
75        int j, k;
76
77        if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
78
79                info->start[0] = base;
80                for (k = 0, j = 0; j < CFG_SST_SECT; j++, k++) {
81                        info->start[k + 1] = info->start[k] + CFG_SST_SECTSZ;
82                        info->protect[k] = 0;
83                }
84        }
85
86        return ERR_OK;
87}
88
89void flash_print_info(flash_info_t * info)
90{
91        int i;
92
93        switch (info->flash_id & FLASH_VENDMASK) {
94        case FLASH_MAN_SST:
95                printf("SST ");
96                break;
97        default:
98                printf("Unknown Vendor ");
99                break;
100        }
101
102        switch (info->flash_id & FLASH_TYPEMASK) {
103        case FLASH_SST6401B:
104                printf("SST39VF6401B\n");
105                break;
106        default:
107                printf("Unknown Chip Type\n");
108                return;
109        }
110
111        if (info->size > 0x100000) {
112                int remainder;
113
114                printf("  Size: %ld", info->size >> 20);
115
116                remainder = (info->size % 0x100000);
117                if (remainder) {
118                        remainder >>= 10;
119                        remainder = (int)((float)
120                                          (((float)remainder / (float)1024) *
121                                           10000));
122                        printf(".%d ", remainder);
123                }
124
125                printf("MB in %d Sectors\n", info->sector_count);
126        } else
127                printf("  Size: %ld KB in %d Sectors\n",
128                       info->size >> 10, info->sector_count);
129
130        printf("  Sector Start Addresses:");
131        for (i = 0; i < info->sector_count; ++i) {
132                if ((i % 5) == 0)
133                        printf("\n   ");
134                printf(" %08lX%s",
135                       info->start[i], info->protect[i] ? " (RO)" : "     ");
136        }
137        printf("\n");
138}
139
140/*
141 * The following code cannot be run from FLASH!
142 */
143ulong flash_get_size(FPWV * addr, flash_info_t * info)
144{
145        u16 value;
146
147        addr[FLASH_CYCLE1] = (FPWV) 0x00AA00AA; /* for Atmel, Intel ignores this */
148        addr[FLASH_CYCLE2] = (FPWV) 0x00550055; /* for Atmel, Intel ignores this */
149        addr[FLASH_CYCLE1] = (FPWV) 0x00900090; /* selects Intel or Atmel */
150
151        switch (addr[0] & 0xffff) {
152        case (u8) SST_MANUFACT:
153                info->flash_id = FLASH_MAN_SST;
154                value = addr[1];
155                break;
156        default:
157                printf("Unknown Flash\n");
158                info->flash_id = FLASH_UNKNOWN;
159                info->sector_count = 0;
160                info->size = 0;
161
162                *addr = (FPW) 0x00F000F0;
163                return (0);     /* no or unknown flash  */
164        }
165
166        switch (value) {
167        case (u16) SST_ID_xF6401B:
168                info->flash_id += FLASH_SST6401B;
169                break;
170        default:
171                info->flash_id = FLASH_UNKNOWN;
172                break;
173        }
174
175        info->sector_count = 0;
176        info->size = 0;
177        info->sector_count = CFG_SST_SECT;
178        info->size = CFG_SST_SECT * CFG_SST_SECTSZ;
179
180        /* reset ID mode */
181        *addr = (FPWV) 0x00F000F0;
182
183        if (info->sector_count > CFG_MAX_FLASH_SECT) {
184                printf("** ERROR: sector count %d > max (%d) **\n",
185                       info->sector_count, CFG_MAX_FLASH_SECT);
186                info->sector_count = CFG_MAX_FLASH_SECT;
187        }
188
189        return (info->size);
190}
191
192int flash_erase(flash_info_t * info, int s_first, int s_last)
193{
194        FPWV *addr;
195        int flag, prot, sect, count;
196        ulong type, start, last;
197        int rcode = 0, flashtype = 0;
198
199        if ((s_first < 0) || (s_first > s_last)) {
200                if (info->flash_id == FLASH_UNKNOWN)
201                        printf("- missing\n");
202                else
203                        printf("- no sectors to erase\n");
204                return 1;
205        }
206
207        type = (info->flash_id & FLASH_VENDMASK);
208
209        switch (type) {
210        case FLASH_MAN_SST:
211                flashtype = 1;
212                break;
213        default:
214                type = (info->flash_id & FLASH_VENDMASK);
215                printf("Can't erase unknown flash type %08lx - aborted\n",
216                       info->flash_id);
217                return 1;
218        }
219
220        prot = 0;
221        for (sect = s_first; sect <= s_last; ++sect) {
222                if (info->protect[sect]) {
223                        prot++;
224                }
225        }
226
227        if (prot)
228                printf("- Warning: %d protected sectors will not be erased!\n",
229                       prot);
230        else
231                printf("\n");
232
233        flag = disable_interrupts();
234
235        start = get_timer(0);
236        last = start;
237
238        if ((s_last - s_first) == (CFG_SST_SECT - 1)) {
239                if (prot == 0) {
240                        addr = (FPWV *) info->start[0];
241
242                        addr[FLASH_CYCLE1] = 0x00AA;    /* unlock */
243                        addr[FLASH_CYCLE2] = 0x0055;    /* unlock */
244                        addr[FLASH_CYCLE1] = 0x0080;    /* erase mode */
245                        addr[FLASH_CYCLE1] = 0x00AA;    /* unlock */
246                        addr[FLASH_CYCLE2] = 0x0055;    /* unlock */
247                        *addr = 0x0030; /* erase chip */
248
249                        count = 0;
250                        start = get_timer(0);
251
252                        while ((*addr & 0x0080) != 0x0080) {
253                                if (count++ > 0x10000) {
254                                        spin_wheel();
255                                        count = 0;
256                                }
257
258                                if (get_timer(start) > CFG_FLASH_ERASE_TOUT) {
259                                        printf("Timeout\n");
260                                        *addr = 0x00F0; /* reset to read mode */
261
262                                        return 1;
263                                }
264                        }
265
266                        *addr = 0x00F0; /* reset to read mode */
267
268                        printf("\b. done\n");
269
270                        if (flag)
271                                enable_interrupts();
272
273                        return 0;
274                } else if (prot == CFG_SST_SECT) {
275                        return 1;
276                }
277        }
278
279        /* Start erase on unprotected sectors */
280        for (sect = s_first; sect <= s_last; sect++) {
281                if (info->protect[sect] == 0) { /* not protected */
282
283                        addr = (FPWV *) (info->start[sect]);
284
285                        printf(".");
286
287                        /* arm simple, non interrupt dependent timer */
288                        start = get_timer(0);
289
290                        switch (flashtype) {
291                        case 1:
292                                {
293                                        FPWV *base;     /* first address in bank */
294
295                                        flag = disable_interrupts();
296
297                                        base = (FPWV *) (CFG_FLASH_BASE);       /* First sector */
298
299                                        base[FLASH_CYCLE1] = 0x00AA;    /* unlock */
300                                        base[FLASH_CYCLE2] = 0x0055;    /* unlock */
301                                        base[FLASH_CYCLE1] = 0x0080;    /* erase mode */
302                                        base[FLASH_CYCLE1] = 0x00AA;    /* unlock */
303                                        base[FLASH_CYCLE2] = 0x0055;    /* unlock */
304                                        *addr = 0x0050; /* erase sector */
305
306                                        if (flag)
307                                                enable_interrupts();
308
309                                        while ((*addr & 0x0080) != 0x0080) {
310                                                if (get_timer(start) >
311                                                    CFG_FLASH_ERASE_TOUT) {
312                                                        printf("Timeout\n");
313                                                        *addr = 0x00F0; /* reset to read mode */
314
315                                                        rcode = 1;
316                                                        break;
317                                                }
318                                        }
319
320                                        *addr = 0x00F0; /* reset to read mode */
321                                        break;
322                                }
323                        }       /* switch (flashtype) */
324                }
325        }
326        printf(" done\n");
327
328        if (flag)
329                enable_interrupts();
330
331        return rcode;
332}
333
334int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
335{
336        ulong wp, count;
337        u16 data;
338        int rc, port_width;
339
340        if (info->flash_id == FLASH_UNKNOWN)
341                return 4;
342
343        /* get lower word aligned address */
344        wp = addr;
345        port_width = sizeof(FPW);
346
347        /* handle unaligned start bytes */
348        if (wp & 1) {
349                data = *((FPWV *) wp);
350                data = (data << 8) | *src;
351
352                if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
353                        return (rc);
354
355                wp++;
356                cnt -= 1;
357                src++;
358        }
359
360        while (cnt >= 2) {
361                /*
362                 * handle word aligned part
363                 */
364                count = 0;
365                data = *((FPWV *) src);
366
367                if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
368                        return (rc);
369
370                wp += 2;
371                src += 2;
372                cnt -= 2;
373
374                if (count++ > 0x800) {
375                        spin_wheel();
376                        count = 0;
377                }
378        }
379        /* handle word aligned part */
380        if (cnt) {
381                /* handle word aligned part */
382                count = 0;
383                data = *((FPWV *) wp);
384
385                data = (data & 0x00FF) | (*src << 8);
386
387                if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
388                        return (rc);
389
390                wp++;
391                src++;
392                cnt -= 1;
393                if (count++ > 0x800) {
394                        spin_wheel();
395                        count = 0;
396                }
397        }
398
399        if (cnt == 0)
400                return ERR_OK;
401
402        return ERR_OK;
403}
404
405/*-----------------------------------------------------------------------
406 * Write a word to Flash
407 * A word is 16 bits, whichever the bus width of the flash bank
408 * (not an individual chip) is.
409 *
410 * returns:
411 * 0 - OK
412 * 1 - write timeout
413 * 2 - Flash not erased
414 */
415int write_word(flash_info_t * info, FPWV * dest, u16 data)
416{
417        ulong start;
418        int flag;
419        int res = 0;            /* result, assume success */
420        FPWV *base;             /* first address in flash bank */
421
422        /* Check if Flash is (sufficiently) erased */
423        if ((*dest & (u8) data) != (u8) data) {
424                return (2);
425        }
426
427        base = (FPWV *) (CFG_FLASH_BASE);
428
429        /* Disable interrupts which might cause a timeout here */
430        flag = disable_interrupts();
431
432        base[FLASH_CYCLE1] = (u8) 0x00AA00AA;   /* unlock */
433        base[FLASH_CYCLE2] = (u8) 0x00550055;   /* unlock */
434        base[FLASH_CYCLE1] = (u8) 0x00A000A0;   /* selects program mode */
435
436        *dest = data;           /* start programming the data */
437
438        /* re-enable interrupts if necessary */
439        if (flag)
440                enable_interrupts();
441
442        start = get_timer(0);
443
444        /* data polling for D7 */
445        while (res == 0
446               && (*dest & (u8) 0x00800080) != (data & (u8) 0x00800080)) {
447                if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
448                        *dest = (u8) 0x00F000F0;        /* reset bank */
449                        res = 1;
450                }
451        }
452
453        *dest++ = (u8) 0x00F000F0;      /* reset bank */
454
455        return (res);
456}
457
458void inline spin_wheel(void)
459{
460        static int p = 0;
461        static char w[] = "\\/-";
462
463        printf("\010%c", w[p]);
464        (++p == 3) ? (p = 0) : 0;
465}
466
467#endif
Note: See TracBrowser for help on using the repository browser.