source: SVN/rincon/u-boot/board/esd/cpci5200/strataflash.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: 21.5 KB
Line 
1/*
2 * (C) Copyright 2002
3 * Brad Kemp, Seranoa Networks, Brad.Kemp@seranoa.com
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#include <common.h>
25#include <asm/processor.h>
26#include <asm/cache.h>
27
28#undef  DEBUG_FLASH
29/*
30 * This file implements a Common Flash Interface (CFI) driver for U-Boot.
31 * The width of the port and the width of the chips are determined at initialization.
32 * These widths are used to calculate the address for access CFI data structures.
33 * It has been tested on an Intel Strataflash implementation.
34 *
35 * References
36 * JEDEC Standard JESD68 - Common Flash Interface (CFI)
37 * JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes
38 * Intel Application Note 646 Common Flash Interface (CFI) and Command Sets
39 * Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet
40 *
41 * TODO
42 * Use Primary Extended Query table (PRI) and Alternate Algorithm Query Table (ALT) to determine if protection is available
43 * Add support for other command sets Use the PRI and ALT to determine command set
44 * Verify erase and program timeouts.
45 */
46
47#define FLASH_CMD_CFI                   0x98
48#define FLASH_CMD_READ_ID               0x90
49#define FLASH_CMD_RESET                 0xff
50#define FLASH_CMD_BLOCK_ERASE           0x20
51#define FLASH_CMD_ERASE_CONFIRM         0xD0
52#define FLASH_CMD_WRITE                 0x40
53#define FLASH_CMD_PROTECT               0x60
54#define FLASH_CMD_PROTECT_SET           0x01
55#define FLASH_CMD_PROTECT_CLEAR         0xD0
56#define FLASH_CMD_CLEAR_STATUS          0x50
57#define FLASH_CMD_WRITE_TO_BUFFER       0xE8
58#define FLASH_CMD_WRITE_BUFFER_CONFIRM  0xD0
59
60#define FLASH_STATUS_DONE               0x80
61#define FLASH_STATUS_ESS                0x40
62#define FLASH_STATUS_ECLBS              0x20
63#define FLASH_STATUS_PSLBS              0x10
64#define FLASH_STATUS_VPENS              0x08
65#define FLASH_STATUS_PSS                0x04
66#define FLASH_STATUS_DPS                0x02
67#define FLASH_STATUS_R                  0x01
68#define FLASH_STATUS_PROTECT            0x01
69
70#define FLASH_OFFSET_CFI                0x55
71#define FLASH_OFFSET_CFI_RESP           0x10
72#define FLASH_OFFSET_WTOUT              0x1F
73#define FLASH_OFFSET_WBTOUT             0x20
74#define FLASH_OFFSET_ETOUT              0x21
75#define FLASH_OFFSET_CETOUT             0x22
76#define FLASH_OFFSET_WMAX_TOUT          0x23
77#define FLASH_OFFSET_WBMAX_TOUT         0x24
78#define FLASH_OFFSET_EMAX_TOUT          0x25
79#define FLASH_OFFSET_CEMAX_TOUT         0x26
80#define FLASH_OFFSET_SIZE               0x27
81#define FLASH_OFFSET_INTERFACE          0x28
82#define FLASH_OFFSET_BUFFER_SIZE        0x2A
83#define FLASH_OFFSET_NUM_ERASE_REGIONS  0x2C
84#define FLASH_OFFSET_ERASE_REGIONS      0x2D
85#define FLASH_OFFSET_PROTECT            0x02
86#define FLASH_OFFSET_USER_PROTECTION    0x85
87#define FLASH_OFFSET_INTEL_PROTECTION   0x81
88
89#define FLASH_MAN_CFI                   0x01000000
90
91typedef union {
92        unsigned char c;
93        unsigned short w;
94        unsigned long l;
95} cfiword_t;
96
97typedef union {
98        unsigned char *cp;
99        unsigned short *wp;
100        unsigned long *lp;
101} cfiptr_t;
102
103#define NUM_ERASE_REGIONS 4
104
105flash_info_t flash_info[CFG_MAX_FLASH_BANKS];   /* info for FLASH chips        */
106
107/*-----------------------------------------------------------------------
108 * Functions
109 */
110
111static void flash_add_byte(flash_info_t * info, cfiword_t * cword, uchar c);
112static void flash_make_cmd(flash_info_t * info, uchar cmd, void *cmdbuf);
113static void flash_write_cmd(flash_info_t * info, int sect, uchar offset,
114                            uchar cmd);
115static int flash_isequal(flash_info_t * info, int sect, uchar offset,
116                         uchar cmd);
117static int flash_isset(flash_info_t * info, int sect, uchar offset, uchar cmd);
118static int flash_detect_cfi(flash_info_t * info);
119static ulong flash_get_size(ulong base, int banknum);
120static int flash_write_cfiword(flash_info_t * info, ulong dest,
121                               cfiword_t cword);
122static int flash_full_status_check(flash_info_t * info, ulong sector,
123                                   ulong tout, char *prompt);
124#ifdef CFG_FLASH_USE_BUFFER_WRITE
125static int flash_write_cfibuffer(flash_info_t * info, ulong dest, uchar * cp,
126                                 int len);
127#endif
128/*-----------------------------------------------------------------------
129 * create an address based on the offset and the port width
130 */
131inline uchar *flash_make_addr(flash_info_t * info, int sect, int offset)
132{
133        return ((uchar *) (info->start[sect] + (offset * info->portwidth)));
134}
135
136/*-----------------------------------------------------------------------
137 * read a character at a port width address
138 */
139inline uchar flash_read_uchar(flash_info_t * info, uchar offset)
140{
141        uchar *cp;
142        cp = flash_make_addr(info, 0, offset);
143        return (cp[info->portwidth - 1]);
144}
145
146/*-----------------------------------------------------------------------
147 * read a short word by swapping for ppc format.
148 */
149ushort flash_read_ushort(flash_info_t * info, int sect, uchar offset)
150{
151        uchar *addr;
152
153        addr = flash_make_addr(info, sect, offset);
154        return ((addr[(2 * info->portwidth) - 1] << 8) |
155                addr[info->portwidth - 1]);
156
157}
158
159/*-----------------------------------------------------------------------
160 * read a long word by picking the least significant byte of each maiximum
161 * port size word. Swap for ppc format.
162 */
163ulong flash_read_long(flash_info_t * info, int sect, uchar offset)
164{
165        uchar *addr;
166
167        addr = flash_make_addr(info, sect, offset);
168        return ((addr[(2 * info->portwidth) - 1] << 24) |
169                (addr[(info->portwidth) - 1] << 16) |
170                (addr[(4 * info->portwidth) - 1] << 8) |
171                addr[(3 * info->portwidth) - 1]);
172
173}
174
175/*-----------------------------------------------------------------------
176 */
177unsigned long flash_init(void)
178{
179        unsigned long size;
180        int i;
181        unsigned long address;
182
183        /* The flash is positioned back to back, with the demultiplexing of the chip
184         * based on the A24 address line.
185         *
186         */
187
188        address = CFG_FLASH_BASE;
189        size = 0;
190
191        /* Init: no FLASHes known */
192        for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
193                flash_info[i].flash_id = FLASH_UNKNOWN;
194                size += flash_info[i].size = flash_get_size(address, i);
195                address += CFG_FLASH_INCREMENT;
196                if (flash_info[i].flash_id == FLASH_UNKNOWN) {
197                        printf
198                            ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
199                             i, flash_info[0].size, flash_info[i].size << 20);
200                }
201        }
202
203#if 0                           /* test-only */
204        /* Monitor protection ON by default */
205#if (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
206        for (i = 0;
207             flash_info[0].start[i] < CFG_MONITOR_BASE + monitor_flash_len - 1;
208             i++)
209                (void)flash_real_protect(&flash_info[0], i, 1);
210#endif
211#endif
212
213        return (size);
214}
215
216/*-----------------------------------------------------------------------
217 */
218int flash_erase(flash_info_t * info, int s_first, int s_last)
219{
220        int rcode = 0;
221        int prot;
222        int sect;
223
224        if (info->flash_id != FLASH_MAN_CFI) {
225                printf("Can't erase unknown flash type - aborted\n");
226                return 1;
227        }
228        if ((s_first < 0) || (s_first > s_last)) {
229                printf("- no sectors to erase\n");
230                return 1;
231        }
232
233        prot = 0;
234        for (sect = s_first; sect <= s_last; ++sect) {
235                if (info->protect[sect]) {
236                        prot++;
237                }
238        }
239        if (prot) {
240                printf("- Warning: %d protected sectors will not be erased!\n",
241                       prot);
242        } else {
243                printf("\n");
244        }
245
246        for (sect = s_first; sect <= s_last; sect++) {
247                if (info->protect[sect] == 0) { /* not protected */
248                        flash_write_cmd(info, sect, 0, FLASH_CMD_CLEAR_STATUS);
249                        flash_write_cmd(info, sect, 0, FLASH_CMD_BLOCK_ERASE);
250                        flash_write_cmd(info, sect, 0, FLASH_CMD_ERASE_CONFIRM);
251
252                        if (flash_full_status_check
253                            (info, sect, info->erase_blk_tout, "erase")) {
254                                rcode = 1;
255                        } else
256                                printf(".");
257                }
258        }
259        printf(" done\n");
260        return rcode;
261}
262
263/*-----------------------------------------------------------------------
264 */
265void flash_print_info(flash_info_t * info)
266{
267        int i;
268
269        if (info->flash_id != FLASH_MAN_CFI) {
270                printf("missing or unknown FLASH type\n");
271                return;
272        }
273
274        printf("CFI conformant FLASH (%d x %d)",
275               (info->portwidth << 3), (info->chipwidth << 3));
276        printf("  Size: %ld MB in %d Sectors\n",
277               info->size >> 20, info->sector_count);
278        printf
279            (" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n",
280             info->erase_blk_tout, info->write_tout, info->buffer_write_tout,
281             info->buffer_size);
282
283        printf("  Sector Start Addresses:");
284        for (i = 0; i < info->sector_count; ++i) {
285                if ((i % 5) == 0)
286                        printf("\n");
287                printf(" %08lX%5s",
288                       info->start[i], info->protect[i] ? " (RO)" : " ");
289        }
290        printf("\n");
291        return;
292}
293
294/*-----------------------------------------------------------------------
295 * Copy memory to flash, returns:
296 * 0 - OK
297 * 1 - write timeout
298 * 2 - Flash not erased
299 */
300int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
301{
302        ulong wp;
303        ulong cp;
304        int aln;
305        cfiword_t cword;
306        int i, rc;
307
308        /* get lower aligned address */
309        wp = (addr & ~(info->portwidth - 1));
310
311        /* handle unaligned start */
312        if ((aln = addr - wp) != 0) {
313                cword.l = 0;
314                cp = wp;
315                for (i = 0; i < aln; ++i, ++cp)
316                        flash_add_byte(info, &cword, (*(uchar *) cp));
317
318                for (; (i < info->portwidth) && (cnt > 0); i++) {
319                        flash_add_byte(info, &cword, *src++);
320                        cnt--;
321                        cp++;
322                }
323                for (; (cnt == 0) && (i < info->portwidth); ++i, ++cp)
324                        flash_add_byte(info, &cword, (*(uchar *) cp));
325                if ((rc = flash_write_cfiword(info, wp, cword)) != 0)
326                        return rc;
327                wp = cp;
328        }
329#ifdef CFG_FLASH_USE_BUFFER_WRITE
330        while (cnt >= info->portwidth) {
331                i = info->buffer_size > cnt ? cnt : info->buffer_size;
332                if ((rc = flash_write_cfibuffer(info, wp, src, i)) != ERR_OK)
333                        return rc;
334                wp += i;
335                src += i;
336                cnt -= i;
337        }
338#else
339        /* handle the aligned part */
340        while (cnt >= info->portwidth) {
341                cword.l = 0;
342                for (i = 0; i < info->portwidth; i++) {
343                        flash_add_byte(info, &cword, *src++);
344                }
345                if ((rc = flash_write_cfiword(info, wp, cword)) != 0)
346                        return rc;
347                wp += info->portwidth;
348                cnt -= info->portwidth;
349        }
350#endif                          /* CFG_FLASH_USE_BUFFER_WRITE */
351        if (cnt == 0) {
352                return (0);
353        }
354
355        /*
356         * handle unaligned tail bytes
357         */
358        cword.l = 0;
359        for (i = 0, cp = wp; (i < info->portwidth) && (cnt > 0); ++i, ++cp) {
360                flash_add_byte(info, &cword, *src++);
361                --cnt;
362        }
363        for (; i < info->portwidth; ++i, ++cp) {
364                flash_add_byte(info, &cword, (*(uchar *) cp));
365        }
366
367        return flash_write_cfiword(info, wp, cword);
368}
369
370/*-----------------------------------------------------------------------
371 */
372int flash_real_protect(flash_info_t * info, long sector, int prot)
373{
374        int retcode = 0;
375
376        flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS);
377        flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT);
378        if (prot)
379                flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_SET);
380        else
381                flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
382
383        if ((retcode =
384             flash_full_status_check(info, sector, info->erase_blk_tout,
385                                     prot ? "protect" : "unprotect")) == 0) {
386
387                info->protect[sector] = prot;
388                /* Intel's unprotect unprotects all locking */
389                if (prot == 0) {
390                        int i;
391                        for (i = 0; i < info->sector_count; i++) {
392                                if (info->protect[i])
393                                        flash_real_protect(info, i, 1);
394                        }
395                }
396        }
397
398        return retcode;
399}
400
401/*-----------------------------------------------------------------------
402 *  wait for XSR.7 to be set. Time out with an error if it does not.
403 *  This routine does not set the flash to read-array mode.
404 */
405static int flash_status_check(flash_info_t * info, ulong sector, ulong tout,
406                              char *prompt)
407{
408        ulong start;
409
410        /* Wait for command completion */
411        start = get_timer(0);
412        while (!flash_isset(info, sector, 0, FLASH_STATUS_DONE)) {
413                if (get_timer(start) > info->erase_blk_tout) {
414                        printf("Flash %s timeout at address %lx\n", prompt,
415                               info->start[sector]);
416                        flash_write_cmd(info, sector, 0, FLASH_CMD_RESET);
417                        return ERR_TIMOUT;
418                }
419        }
420        return ERR_OK;
421}
422
423/*-----------------------------------------------------------------------
424 * Wait for XSR.7 to be set, if it times out print an error, otherwise do a full status check.
425 * This routine sets the flash to read-array mode.
426 */
427static int flash_full_status_check(flash_info_t * info, ulong sector,
428                                   ulong tout, char *prompt)
429{
430        int retcode;
431        retcode = flash_status_check(info, sector, tout, prompt);
432        if ((retcode == ERR_OK)
433            && !flash_isequal(info, sector, 0, FLASH_STATUS_DONE)) {
434                retcode = ERR_INVAL;
435                printf("Flash %s error at address %lx\n", prompt,
436                       info->start[sector]);
437                if (flash_isset
438                    (info, sector, 0,
439                     FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {
440                        printf("Command Sequence Error.\n");
441                } else if (flash_isset(info, sector, 0, FLASH_STATUS_ECLBS)) {
442                        printf("Block Erase Error.\n");
443                        retcode = ERR_NOT_ERASED;
444                } else if (flash_isset(info, sector, 0, FLASH_STATUS_PSLBS)) {
445                        printf("Locking Error\n");
446                }
447                if (flash_isset(info, sector, 0, FLASH_STATUS_DPS)) {
448                        printf("Block locked.\n");
449                        retcode = ERR_PROTECTED;
450                }
451                if (flash_isset(info, sector, 0, FLASH_STATUS_VPENS))
452                        printf("Vpp Low Error.\n");
453        }
454        flash_write_cmd(info, sector, 0, FLASH_CMD_RESET);
455        return retcode;
456}
457
458/*-----------------------------------------------------------------------
459 */
460static void flash_add_byte(flash_info_t * info, cfiword_t * cword, uchar c)
461{
462        switch (info->portwidth) {
463        case FLASH_CFI_8BIT:
464                cword->c = c;
465                break;
466        case FLASH_CFI_16BIT:
467                cword->w = (cword->w << 8) | c;
468                break;
469        case FLASH_CFI_32BIT:
470                cword->l = (cword->l << 8) | c;
471        }
472}
473
474/*-----------------------------------------------------------------------
475 * make a proper sized command based on the port and chip widths
476 */
477static void flash_make_cmd(flash_info_t * info, uchar cmd, void *cmdbuf)
478{
479        int i;
480        uchar *cp = (uchar *) cmdbuf;
481        for (i = 0; i < info->portwidth; i++)
482                *cp++ = ((i + 1) % info->chipwidth) ? '\0' : cmd;
483}
484
485/*
486 * Write a proper sized command to the correct address
487 */
488static void flash_write_cmd(flash_info_t * info, int sect, uchar offset,
489                            uchar cmd)
490{
491
492        volatile cfiptr_t addr;
493        cfiword_t cword;
494        addr.cp = flash_make_addr(info, sect, offset);
495        flash_make_cmd(info, cmd, &cword);
496        switch (info->portwidth) {
497        case FLASH_CFI_8BIT:
498                *addr.cp = cword.c;
499                break;
500        case FLASH_CFI_16BIT:
501                *addr.wp = cword.w;
502                break;
503        case FLASH_CFI_32BIT:
504                *addr.lp = cword.l;
505                break;
506        }
507}
508
509/*-----------------------------------------------------------------------
510 */
511static int flash_isequal(flash_info_t * info, int sect, uchar offset, uchar cmd)
512{
513        cfiptr_t cptr;
514        cfiword_t cword;
515        int retval;
516        cptr.cp = flash_make_addr(info, sect, offset);
517        flash_make_cmd(info, cmd, &cword);
518        switch (info->portwidth) {
519        case FLASH_CFI_8BIT:
520                retval = (cptr.cp[0] == cword.c);
521                break;
522        case FLASH_CFI_16BIT:
523                retval = (cptr.wp[0] == cword.w);
524                break;
525        case FLASH_CFI_32BIT:
526                retval = (cptr.lp[0] == cword.l);
527                break;
528        default:
529                retval = 0;
530                break;
531        }
532        return retval;
533}
534
535/*-----------------------------------------------------------------------
536 */
537static int flash_isset(flash_info_t * info, int sect, uchar offset, uchar cmd)
538{
539        cfiptr_t cptr;
540        cfiword_t cword;
541        int retval;
542        cptr.cp = flash_make_addr(info, sect, offset);
543        flash_make_cmd(info, cmd, &cword);
544        switch (info->portwidth) {
545        case FLASH_CFI_8BIT:
546                retval = ((cptr.cp[0] & cword.c) == cword.c);
547                break;
548        case FLASH_CFI_16BIT:
549                retval = ((cptr.wp[0] & cword.w) == cword.w);
550                break;
551        case FLASH_CFI_32BIT:
552                retval = ((cptr.lp[0] & cword.l) == cword.l);
553                break;
554        default:
555                retval = 0;
556                break;
557        }
558        return retval;
559}
560
561/*-----------------------------------------------------------------------
562 * detect if flash is compatible with the Common Flash Interface (CFI)
563 * http://www.jedec.org/download/search/jesd68.pdf
564 *
565 */
566static int flash_detect_cfi(flash_info_t * info)
567{
568
569        for (info->portwidth = FLASH_CFI_8BIT;
570             info->portwidth <= FLASH_CFI_32BIT; info->portwidth <<= 1) {
571                for (info->chipwidth = FLASH_CFI_BY8;
572                     info->chipwidth <= info->portwidth;
573                     info->chipwidth <<= 1) {
574                        flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
575                        flash_write_cmd(info, 0, FLASH_OFFSET_CFI,
576                                        FLASH_CMD_CFI);
577                        if (flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
578                            && flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 1,
579                                             'R')
580                            && flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 2,
581                                             'Y'))
582                                return 1;
583                }
584        }
585        return 0;
586}
587
588/*
589 * The following code cannot be run from FLASH!
590 *
591 */
592static ulong flash_get_size(ulong base, int banknum)
593{
594        flash_info_t *info = &flash_info[banknum];
595        int i, j;
596        int sect_cnt;
597        unsigned long sector;
598        unsigned long tmp;
599        int size_ratio = 0;
600        uchar num_erase_regions;
601        int erase_region_size;
602        int erase_region_count;
603
604        info->start[0] = base;
605#if 0
606        invalidate_dcache_range(base, base + 0x400);
607#endif
608        if (flash_detect_cfi(info)) {
609
610                size_ratio = info->portwidth / info->chipwidth;
611                num_erase_regions =
612                    flash_read_uchar(info, FLASH_OFFSET_NUM_ERASE_REGIONS);
613
614                sect_cnt = 0;
615                sector = base;
616                for (i = 0; i < num_erase_regions; i++) {
617                        if (i > NUM_ERASE_REGIONS) {
618                                printf("%d erase regions found, only %d used\n",
619                                       num_erase_regions, NUM_ERASE_REGIONS);
620                                break;
621                        }
622                        tmp =
623                            flash_read_long(info, 0,
624                                            FLASH_OFFSET_ERASE_REGIONS);
625                        erase_region_size =
626                            (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
627                        tmp >>= 16;
628                        erase_region_count = (tmp & 0xffff) + 1;
629                        for (j = 0; j < erase_region_count; j++) {
630                                info->start[sect_cnt] = sector;
631                                sector += (erase_region_size * size_ratio);
632                                info->protect[sect_cnt] =
633                                    flash_isset(info, sect_cnt,
634                                                FLASH_OFFSET_PROTECT,
635                                                FLASH_STATUS_PROTECT);
636                                sect_cnt++;
637                        }
638                }
639
640                info->sector_count = sect_cnt;
641                /* multiply the size by the number of chips */
642                info->size =
643                    (1 << flash_read_uchar(info, FLASH_OFFSET_SIZE)) *
644                    size_ratio;
645                info->buffer_size =
646                    (1 << flash_read_ushort(info, 0, FLASH_OFFSET_BUFFER_SIZE));
647                tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_ETOUT);
648                info->erase_blk_tout =
649                    (tmp *
650                     (1 << flash_read_uchar(info, FLASH_OFFSET_EMAX_TOUT)));
651                tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_WBTOUT);
652                info->buffer_write_tout =
653                    (tmp *
654                     (1 << flash_read_uchar(info, FLASH_OFFSET_WBMAX_TOUT)));
655                tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_WTOUT);
656                info->write_tout =
657                    (tmp *
658                     (1 << flash_read_uchar(info, FLASH_OFFSET_WMAX_TOUT))) /
659                    1000;
660                info->flash_id = FLASH_MAN_CFI;
661        }
662
663        flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
664#ifdef DEBUG_FLASH
665        printf("portwidth=%d chipwidth=%d\n", info->portwidth, info->chipwidth);        /* test-only */
666#endif
667#ifdef DEBUG_FLASH
668        printf("found %d erase regions\n", num_erase_regions);
669#endif
670#ifdef DEBUG_FLASH
671        printf("size=%08x sectors=%08x \n", info->size, info->sector_count);
672#endif
673        return (info->size);
674}
675
676/*-----------------------------------------------------------------------
677 */
678static int flash_write_cfiword(flash_info_t * info, ulong dest, cfiword_t cword)
679{
680
681        cfiptr_t ctladdr;
682        cfiptr_t cptr;
683        int flag;
684
685        ctladdr.cp = flash_make_addr(info, 0, 0);
686        cptr.cp = (uchar *) dest;
687
688        /* Check if Flash is (sufficiently) erased */
689        switch (info->portwidth) {
690        case FLASH_CFI_8BIT:
691                flag = ((cptr.cp[0] & cword.c) == cword.c);
692                break;
693        case FLASH_CFI_16BIT:
694                flag = ((cptr.wp[0] & cword.w) == cword.w);
695                break;
696        case FLASH_CFI_32BIT:
697                flag = ((cptr.lp[0] & cword.l) == cword.l);
698                break;
699        default:
700                return 2;
701        }
702        if (!flag)
703                return 2;
704
705        /* Disable interrupts which might cause a timeout here */
706        flag = disable_interrupts();
707
708        flash_write_cmd(info, 0, 0, FLASH_CMD_CLEAR_STATUS);
709        flash_write_cmd(info, 0, 0, FLASH_CMD_WRITE);
710
711        switch (info->portwidth) {
712        case FLASH_CFI_8BIT:
713                cptr.cp[0] = cword.c;
714                break;
715        case FLASH_CFI_16BIT:
716                cptr.wp[0] = cword.w;
717                break;
718        case FLASH_CFI_32BIT:
719                cptr.lp[0] = cword.l;
720                break;
721        }
722
723        /* re-enable interrupts if necessary */
724        if (flag)
725                enable_interrupts();
726
727        return flash_full_status_check(info, 0, info->write_tout, "write");
728}
729
730#ifdef CFG_FLASH_USE_BUFFER_WRITE
731
732/* loop through the sectors from the highest address
733 * when the passed address is greater or equal to the sector address
734 * we have a match
735 */
736static int find_sector(flash_info_t * info, ulong addr)
737{
738        int sector;
739        for (sector = info->sector_count - 1; sector >= 0; sector--) {
740                if (addr >= info->start[sector])
741                        break;
742        }
743        return sector;
744}
745
746static int flash_write_cfibuffer(flash_info_t * info, ulong dest, uchar * cp,
747                                 int len)
748{
749
750        int sector;
751        int cnt;
752        int retcode;
753        volatile cfiptr_t src;
754        volatile cfiptr_t dst;
755
756        src.cp = cp;
757        dst.cp = (uchar *) dest;
758        sector = find_sector(info, dest);
759        flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS);
760        flash_write_cmd(info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
761        if ((retcode = flash_status_check(info, sector, info->buffer_write_tout,
762                                          "write to buffer")) == ERR_OK) {
763                switch (info->portwidth) {
764                case FLASH_CFI_8BIT:
765                        cnt = len;
766                        break;
767                case FLASH_CFI_16BIT:
768                        cnt = len >> 1;
769                        break;
770                case FLASH_CFI_32BIT:
771                        cnt = len >> 2;
772                        break;
773                default:
774                        return ERR_INVAL;
775                        break;
776                }
777                flash_write_cmd(info, sector, 0, (uchar) cnt - 1);
778                while (cnt-- > 0) {
779                        switch (info->portwidth) {
780                        case FLASH_CFI_8BIT:
781                                *dst.cp++ = *src.cp++;
782                                break;
783                        case FLASH_CFI_16BIT:
784                                *dst.wp++ = *src.wp++;
785                                break;
786                        case FLASH_CFI_32BIT:
787                                *dst.lp++ = *src.lp++;
788                                break;
789                        default:
790                                return ERR_INVAL;
791                                break;
792                        }
793                }
794                flash_write_cmd(info, sector, 0,
795                                FLASH_CMD_WRITE_BUFFER_CONFIRM);
796                retcode =
797                    flash_full_status_check(info, sector,
798                                            info->buffer_write_tout,
799                                            "buffer write");
800        }
801        flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS);
802        return retcode;
803}
804#endif                          /* CFG_USE_FLASH_BUFFER_WRITE */
Note: See TracBrowser for help on using the repository browser.