]> git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/mtd/cfi_flash.c
Merge branch 'master' of git://www.denx.de/git/u-boot-mpc83xx
[people/ms/u-boot.git] / drivers / mtd / cfi_flash.c
1 /*
2 * (C) Copyright 2002-2004
3 * Brad Kemp, Seranoa Networks, Brad.Kemp@seranoa.com
4 *
5 * Copyright (C) 2003 Arabella Software Ltd.
6 * Yuli Barcohen <yuli@arabellasw.com>
7 *
8 * Copyright (C) 2004
9 * Ed Okerson
10 *
11 * Copyright (C) 2006
12 * Tolunay Orkun <listmember@orkun.us>
13 *
14 * See file CREDITS for list of people who contributed to this
15 * project.
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License as
19 * published by the Free Software Foundation; either version 2 of
20 * the License, or (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
30 * MA 02111-1307 USA
31 *
32 */
33
34 /* The DEBUG define must be before common to enable debugging */
35 /* #define DEBUG */
36
37 #include <common.h>
38 #include <asm/processor.h>
39 #include <asm/io.h>
40 #include <asm/byteorder.h>
41 #include <environment.h>
42 #ifdef CFG_FLASH_CFI_DRIVER
43
44 /*
45 * This file implements a Common Flash Interface (CFI) driver for
46 * U-Boot.
47 *
48 * The width of the port and the width of the chips are determined at
49 * initialization. These widths are used to calculate the address for
50 * access CFI data structures.
51 *
52 * References
53 * JEDEC Standard JESD68 - Common Flash Interface (CFI)
54 * JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes
55 * Intel Application Note 646 Common Flash Interface (CFI) and Command Sets
56 * Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet
57 * AMD CFI Specification, Release 2.0 December 1, 2001
58 * AMD/Spansion Application Note: Migration from Single-byte to Three-byte
59 * Device IDs, Publication Number 25538 Revision A, November 8, 2001
60 *
61 * Define CFG_WRITE_SWAPPED_DATA, if you have to swap the Bytes between
62 * reading and writing ... (yes there is such a Hardware).
63 */
64
65 #ifndef CFG_FLASH_BANKS_LIST
66 #define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
67 #endif
68
69 #define FLASH_CMD_CFI 0x98
70 #define FLASH_CMD_READ_ID 0x90
71 #define FLASH_CMD_RESET 0xff
72 #define FLASH_CMD_BLOCK_ERASE 0x20
73 #define FLASH_CMD_ERASE_CONFIRM 0xD0
74 #define FLASH_CMD_WRITE 0x40
75 #define FLASH_CMD_PROTECT 0x60
76 #define FLASH_CMD_PROTECT_SET 0x01
77 #define FLASH_CMD_PROTECT_CLEAR 0xD0
78 #define FLASH_CMD_CLEAR_STATUS 0x50
79 #define FLASH_CMD_WRITE_TO_BUFFER 0xE8
80 #define FLASH_CMD_WRITE_BUFFER_CONFIRM 0xD0
81
82 #define FLASH_STATUS_DONE 0x80
83 #define FLASH_STATUS_ESS 0x40
84 #define FLASH_STATUS_ECLBS 0x20
85 #define FLASH_STATUS_PSLBS 0x10
86 #define FLASH_STATUS_VPENS 0x08
87 #define FLASH_STATUS_PSS 0x04
88 #define FLASH_STATUS_DPS 0x02
89 #define FLASH_STATUS_R 0x01
90 #define FLASH_STATUS_PROTECT 0x01
91
92 #define AMD_CMD_RESET 0xF0
93 #define AMD_CMD_WRITE 0xA0
94 #define AMD_CMD_ERASE_START 0x80
95 #define AMD_CMD_ERASE_SECTOR 0x30
96 #define AMD_CMD_UNLOCK_START 0xAA
97 #define AMD_CMD_UNLOCK_ACK 0x55
98 #define AMD_CMD_WRITE_TO_BUFFER 0x25
99 #define AMD_CMD_WRITE_BUFFER_CONFIRM 0x29
100
101 #define AMD_STATUS_TOGGLE 0x40
102 #define AMD_STATUS_ERROR 0x20
103
104 #define FLASH_OFFSET_MANUFACTURER_ID 0x00
105 #define FLASH_OFFSET_DEVICE_ID 0x01
106 #define FLASH_OFFSET_DEVICE_ID2 0x0E
107 #define FLASH_OFFSET_DEVICE_ID3 0x0F
108 #define FLASH_OFFSET_CFI 0x55
109 #define FLASH_OFFSET_CFI_ALT 0x555
110 #define FLASH_OFFSET_CFI_RESP 0x10
111 #define FLASH_OFFSET_PRIMARY_VENDOR 0x13
112 /* extended query table primary address */
113 #define FLASH_OFFSET_EXT_QUERY_T_P_ADDR 0x15
114 #define FLASH_OFFSET_WTOUT 0x1F
115 #define FLASH_OFFSET_WBTOUT 0x20
116 #define FLASH_OFFSET_ETOUT 0x21
117 #define FLASH_OFFSET_CETOUT 0x22
118 #define FLASH_OFFSET_WMAX_TOUT 0x23
119 #define FLASH_OFFSET_WBMAX_TOUT 0x24
120 #define FLASH_OFFSET_EMAX_TOUT 0x25
121 #define FLASH_OFFSET_CEMAX_TOUT 0x26
122 #define FLASH_OFFSET_SIZE 0x27
123 #define FLASH_OFFSET_INTERFACE 0x28
124 #define FLASH_OFFSET_BUFFER_SIZE 0x2A
125 #define FLASH_OFFSET_NUM_ERASE_REGIONS 0x2C
126 #define FLASH_OFFSET_ERASE_REGIONS 0x2D
127 #define FLASH_OFFSET_PROTECT 0x02
128 #define FLASH_OFFSET_USER_PROTECTION 0x85
129 #define FLASH_OFFSET_INTEL_PROTECTION 0x81
130
131 #define CFI_CMDSET_NONE 0
132 #define CFI_CMDSET_INTEL_EXTENDED 1
133 #define CFI_CMDSET_AMD_STANDARD 2
134 #define CFI_CMDSET_INTEL_STANDARD 3
135 #define CFI_CMDSET_AMD_EXTENDED 4
136 #define CFI_CMDSET_MITSU_STANDARD 256
137 #define CFI_CMDSET_MITSU_EXTENDED 257
138 #define CFI_CMDSET_SST 258
139
140 #ifdef CFG_FLASH_CFI_AMD_RESET /* needed for STM_ID_29W320DB on UC100 */
141 # undef FLASH_CMD_RESET
142 # define FLASH_CMD_RESET AMD_CMD_RESET /* use AMD-Reset instead */
143 #endif
144
145 typedef union {
146 unsigned char c;
147 unsigned short w;
148 unsigned long l;
149 unsigned long long ll;
150 } cfiword_t;
151
152 #define NUM_ERASE_REGIONS 4 /* max. number of erase regions */
153
154 static uint flash_offset_cfi[2] = { FLASH_OFFSET_CFI, FLASH_OFFSET_CFI_ALT };
155
156 /* use CFG_MAX_FLASH_BANKS_DETECT if defined */
157 #ifdef CFG_MAX_FLASH_BANKS_DETECT
158 static ulong bank_base[CFG_MAX_FLASH_BANKS_DETECT] = CFG_FLASH_BANKS_LIST;
159 flash_info_t flash_info[CFG_MAX_FLASH_BANKS_DETECT]; /* FLASH chips info */
160 #else
161 static ulong bank_base[CFG_MAX_FLASH_BANKS] = CFG_FLASH_BANKS_LIST;
162 flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* FLASH chips info */
163 #endif
164
165 /*
166 * Check if chip width is defined. If not, start detecting with 8bit.
167 */
168 #ifndef CFG_FLASH_CFI_WIDTH
169 #define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
170 #endif
171
172 typedef unsigned long flash_sect_t;
173
174 /* CFI standard query structure */
175 struct cfi_qry {
176 u8 qry[3];
177 u16 p_id;
178 u16 p_adr;
179 u16 a_id;
180 u16 a_adr;
181 u8 vcc_min;
182 u8 vcc_max;
183 u8 vpp_min;
184 u8 vpp_max;
185 u8 word_write_timeout_typ;
186 u8 buf_write_timeout_typ;
187 u8 block_erase_timeout_typ;
188 u8 chip_erase_timeout_typ;
189 u8 word_write_timeout_max;
190 u8 buf_write_timeout_max;
191 u8 block_erase_timeout_max;
192 u8 chip_erase_timeout_max;
193 u8 dev_size;
194 u16 interface_desc;
195 u16 max_buf_write_size;
196 u8 num_erase_regions;
197 u32 erase_region_info[NUM_ERASE_REGIONS];
198 } __attribute__((packed));
199
200 struct cfi_pri_hdr {
201 u8 pri[3];
202 u8 major_version;
203 u8 minor_version;
204 } __attribute__((packed));
205
206 static void flash_write8(u8 value, void *addr)
207 {
208 __raw_writeb(value, addr);
209 }
210
211 static void flash_write16(u16 value, void *addr)
212 {
213 __raw_writew(value, addr);
214 }
215
216 static void flash_write32(u32 value, void *addr)
217 {
218 __raw_writel(value, addr);
219 }
220
221 static void flash_write64(u64 value, void *addr)
222 {
223 /* No architectures currently implement __raw_writeq() */
224 *(volatile u64 *)addr = value;
225 }
226
227 static u8 flash_read8(void *addr)
228 {
229 return __raw_readb(addr);
230 }
231
232 static u16 flash_read16(void *addr)
233 {
234 return __raw_readw(addr);
235 }
236
237 static u32 flash_read32(void *addr)
238 {
239 return __raw_readl(addr);
240 }
241
242 static u64 __flash_read64(void *addr)
243 {
244 /* No architectures currently implement __raw_readq() */
245 return *(volatile u64 *)addr;
246 }
247
248 u64 flash_read64(void *addr)__attribute__((weak, alias("__flash_read64")));
249
250 /*-----------------------------------------------------------------------
251 */
252 #if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
253 static flash_info_t *flash_get_info(ulong base)
254 {
255 int i;
256 flash_info_t * info = 0;
257
258 for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
259 info = & flash_info[i];
260 if (info->size && info->start[0] <= base &&
261 base <= info->start[0] + info->size - 1)
262 break;
263 }
264
265 return i == CFG_MAX_FLASH_BANKS ? 0 : info;
266 }
267 #endif
268
269 unsigned long flash_sector_size(flash_info_t *info, flash_sect_t sect)
270 {
271 if (sect != (info->sector_count - 1))
272 return info->start[sect + 1] - info->start[sect];
273 else
274 return info->start[0] + info->size - info->start[sect];
275 }
276
277 /*-----------------------------------------------------------------------
278 * create an address based on the offset and the port width
279 */
280 static inline void *
281 flash_map (flash_info_t * info, flash_sect_t sect, uint offset)
282 {
283 unsigned int byte_offset = offset * info->portwidth;
284
285 return map_physmem(info->start[sect] + byte_offset,
286 flash_sector_size(info, sect) - byte_offset,
287 MAP_NOCACHE);
288 }
289
290 static inline void flash_unmap(flash_info_t *info, flash_sect_t sect,
291 unsigned int offset, void *addr)
292 {
293 unsigned int byte_offset = offset * info->portwidth;
294
295 unmap_physmem(addr, flash_sector_size(info, sect) - byte_offset);
296 }
297
298 /*-----------------------------------------------------------------------
299 * make a proper sized command based on the port and chip widths
300 */
301 static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)
302 {
303 int i;
304 uchar *cp = (uchar *) cmdbuf;
305
306 #if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
307 for (i = info->portwidth; i > 0; i--)
308 #else
309 for (i = 1; i <= info->portwidth; i++)
310 #endif
311 *cp++ = (i & (info->chipwidth - 1)) ? '\0' : cmd;
312 }
313
314 #ifdef DEBUG
315 /*-----------------------------------------------------------------------
316 * Debug support
317 */
318 static void print_longlong (char *str, unsigned long long data)
319 {
320 int i;
321 char *cp;
322
323 cp = (unsigned char *) &data;
324 for (i = 0; i < 8; i++)
325 sprintf (&str[i * 2], "%2.2x", *cp++);
326 }
327
328 static void flash_printqry (struct cfi_qry *qry)
329 {
330 u8 *p = (u8 *)qry;
331 int x, y;
332
333 for (x = 0; x < sizeof(struct cfi_qry); x += 16) {
334 debug("%02x : ", x);
335 for (y = 0; y < 16; y++)
336 debug("%2.2x ", p[x + y]);
337 debug(" ");
338 for (y = 0; y < 16; y++) {
339 unsigned char c = p[x + y];
340 if (c >= 0x20 && c <= 0x7e)
341 debug("%c", c);
342 else
343 debug(".");
344 }
345 debug("\n");
346 }
347 }
348 #endif
349
350
351 /*-----------------------------------------------------------------------
352 * read a character at a port width address
353 */
354 static inline uchar flash_read_uchar (flash_info_t * info, uint offset)
355 {
356 uchar *cp;
357 uchar retval;
358
359 cp = flash_map (info, 0, offset);
360 #if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
361 retval = flash_read8(cp);
362 #else
363 retval = flash_read8(cp + info->portwidth - 1);
364 #endif
365 flash_unmap (info, 0, offset, cp);
366 return retval;
367 }
368
369 /*-----------------------------------------------------------------------
370 * read a word at a port width address, assume 16bit bus
371 */
372 static inline ushort flash_read_word (flash_info_t * info, uint offset)
373 {
374 ushort *addr, retval;
375
376 addr = flash_map (info, 0, offset);
377 retval = flash_read16 (addr);
378 flash_unmap (info, 0, offset, addr);
379 return retval;
380 }
381
382
383 /*-----------------------------------------------------------------------
384 * read a long word by picking the least significant byte of each maximum
385 * port size word. Swap for ppc format.
386 */
387 static ulong flash_read_long (flash_info_t * info, flash_sect_t sect,
388 uint offset)
389 {
390 uchar *addr;
391 ulong retval;
392
393 #ifdef DEBUG
394 int x;
395 #endif
396 addr = flash_map (info, sect, offset);
397
398 #ifdef DEBUG
399 debug ("long addr is at %p info->portwidth = %d\n", addr,
400 info->portwidth);
401 for (x = 0; x < 4 * info->portwidth; x++) {
402 debug ("addr[%x] = 0x%x\n", x, flash_read8(addr + x));
403 }
404 #endif
405 #if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
406 retval = ((flash_read8(addr) << 16) |
407 (flash_read8(addr + info->portwidth) << 24) |
408 (flash_read8(addr + 2 * info->portwidth)) |
409 (flash_read8(addr + 3 * info->portwidth) << 8));
410 #else
411 retval = ((flash_read8(addr + 2 * info->portwidth - 1) << 24) |
412 (flash_read8(addr + info->portwidth - 1) << 16) |
413 (flash_read8(addr + 4 * info->portwidth - 1) << 8) |
414 (flash_read8(addr + 3 * info->portwidth - 1)));
415 #endif
416 flash_unmap(info, sect, offset, addr);
417
418 return retval;
419 }
420
421 /*
422 * Write a proper sized command to the correct address
423 */
424 static void flash_write_cmd (flash_info_t * info, flash_sect_t sect,
425 uint offset, uchar cmd)
426 {
427
428 void *addr;
429 cfiword_t cword;
430
431 addr = flash_map (info, sect, offset);
432 flash_make_cmd (info, cmd, &cword);
433 switch (info->portwidth) {
434 case FLASH_CFI_8BIT:
435 debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr, cmd,
436 cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
437 flash_write8(cword.c, addr);
438 break;
439 case FLASH_CFI_16BIT:
440 debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr,
441 cmd, cword.w,
442 info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
443 flash_write16(cword.w, addr);
444 break;
445 case FLASH_CFI_32BIT:
446 debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr,
447 cmd, cword.l,
448 info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
449 flash_write32(cword.l, addr);
450 break;
451 case FLASH_CFI_64BIT:
452 #ifdef DEBUG
453 {
454 char str[20];
455
456 print_longlong (str, cword.ll);
457
458 debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n",
459 addr, cmd, str,
460 info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
461 }
462 #endif
463 flash_write64(cword.ll, addr);
464 break;
465 }
466
467 /* Ensure all the instructions are fully finished */
468 sync();
469
470 flash_unmap(info, sect, offset, addr);
471 }
472
473 static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect)
474 {
475 flash_write_cmd (info, sect, info->addr_unlock1, AMD_CMD_UNLOCK_START);
476 flash_write_cmd (info, sect, info->addr_unlock2, AMD_CMD_UNLOCK_ACK);
477 }
478
479 /*-----------------------------------------------------------------------
480 */
481 static int flash_isequal (flash_info_t * info, flash_sect_t sect,
482 uint offset, uchar cmd)
483 {
484 void *addr;
485 cfiword_t cword;
486 int retval;
487
488 addr = flash_map (info, sect, offset);
489 flash_make_cmd (info, cmd, &cword);
490
491 debug ("is= cmd %x(%c) addr %p ", cmd, cmd, addr);
492 switch (info->portwidth) {
493 case FLASH_CFI_8BIT:
494 debug ("is= %x %x\n", flash_read8(addr), cword.c);
495 retval = (flash_read8(addr) == cword.c);
496 break;
497 case FLASH_CFI_16BIT:
498 debug ("is= %4.4x %4.4x\n", flash_read16(addr), cword.w);
499 retval = (flash_read16(addr) == cword.w);
500 break;
501 case FLASH_CFI_32BIT:
502 debug ("is= %8.8lx %8.8lx\n", flash_read32(addr), cword.l);
503 retval = (flash_read32(addr) == cword.l);
504 break;
505 case FLASH_CFI_64BIT:
506 #ifdef DEBUG
507 {
508 char str1[20];
509 char str2[20];
510
511 print_longlong (str1, flash_read64(addr));
512 print_longlong (str2, cword.ll);
513 debug ("is= %s %s\n", str1, str2);
514 }
515 #endif
516 retval = (flash_read64(addr) == cword.ll);
517 break;
518 default:
519 retval = 0;
520 break;
521 }
522 flash_unmap(info, sect, offset, addr);
523
524 return retval;
525 }
526
527 /*-----------------------------------------------------------------------
528 */
529 static int flash_isset (flash_info_t * info, flash_sect_t sect,
530 uint offset, uchar cmd)
531 {
532 void *addr;
533 cfiword_t cword;
534 int retval;
535
536 addr = flash_map (info, sect, offset);
537 flash_make_cmd (info, cmd, &cword);
538 switch (info->portwidth) {
539 case FLASH_CFI_8BIT:
540 retval = ((flash_read8(addr) & cword.c) == cword.c);
541 break;
542 case FLASH_CFI_16BIT:
543 retval = ((flash_read16(addr) & cword.w) == cword.w);
544 break;
545 case FLASH_CFI_32BIT:
546 retval = ((flash_read32(addr) & cword.l) == cword.l);
547 break;
548 case FLASH_CFI_64BIT:
549 retval = ((flash_read64(addr) & cword.ll) == cword.ll);
550 break;
551 default:
552 retval = 0;
553 break;
554 }
555 flash_unmap(info, sect, offset, addr);
556
557 return retval;
558 }
559
560 /*-----------------------------------------------------------------------
561 */
562 static int flash_toggle (flash_info_t * info, flash_sect_t sect,
563 uint offset, uchar cmd)
564 {
565 void *addr;
566 cfiword_t cword;
567 int retval;
568
569 addr = flash_map (info, sect, offset);
570 flash_make_cmd (info, cmd, &cword);
571 switch (info->portwidth) {
572 case FLASH_CFI_8BIT:
573 retval = ((flash_read8(addr) & cword.c) !=
574 (flash_read8(addr) & cword.c));
575 break;
576 case FLASH_CFI_16BIT:
577 retval = ((flash_read16(addr) & cword.w) !=
578 (flash_read16(addr) & cword.w));
579 break;
580 case FLASH_CFI_32BIT:
581 retval = ((flash_read32(addr) & cword.l) !=
582 (flash_read32(addr) & cword.l));
583 break;
584 case FLASH_CFI_64BIT:
585 retval = ((flash_read64(addr) & cword.ll) !=
586 (flash_read64(addr) & cword.ll));
587 break;
588 default:
589 retval = 0;
590 break;
591 }
592 flash_unmap(info, sect, offset, addr);
593
594 return retval;
595 }
596
597 /*
598 * flash_is_busy - check to see if the flash is busy
599 *
600 * This routine checks the status of the chip and returns true if the
601 * chip is busy.
602 */
603 static int flash_is_busy (flash_info_t * info, flash_sect_t sect)
604 {
605 int retval;
606
607 switch (info->vendor) {
608 case CFI_CMDSET_INTEL_STANDARD:
609 case CFI_CMDSET_INTEL_EXTENDED:
610 retval = !flash_isset (info, sect, 0, FLASH_STATUS_DONE);
611 break;
612 case CFI_CMDSET_AMD_STANDARD:
613 case CFI_CMDSET_AMD_EXTENDED:
614 #ifdef CONFIG_FLASH_CFI_LEGACY
615 case CFI_CMDSET_AMD_LEGACY:
616 #endif
617 retval = flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE);
618 break;
619 default:
620 retval = 0;
621 }
622 debug ("flash_is_busy: %d\n", retval);
623 return retval;
624 }
625
626 /*-----------------------------------------------------------------------
627 * wait for XSR.7 to be set. Time out with an error if it does not.
628 * This routine does not set the flash to read-array mode.
629 */
630 static int flash_status_check (flash_info_t * info, flash_sect_t sector,
631 ulong tout, char *prompt)
632 {
633 ulong start;
634
635 #if CFG_HZ != 1000
636 tout *= CFG_HZ/1000;
637 #endif
638
639 /* Wait for command completion */
640 start = get_timer (0);
641 while (flash_is_busy (info, sector)) {
642 if (get_timer (start) > tout) {
643 printf ("Flash %s timeout at address %lx data %lx\n",
644 prompt, info->start[sector],
645 flash_read_long (info, sector, 0));
646 flash_write_cmd (info, sector, 0, info->cmd_reset);
647 return ERR_TIMOUT;
648 }
649 udelay (1); /* also triggers watchdog */
650 }
651 return ERR_OK;
652 }
653
654 /*-----------------------------------------------------------------------
655 * Wait for XSR.7 to be set, if it times out print an error, otherwise
656 * do a full status check.
657 *
658 * This routine sets the flash to read-array mode.
659 */
660 static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
661 ulong tout, char *prompt)
662 {
663 int retcode;
664
665 retcode = flash_status_check (info, sector, tout, prompt);
666 switch (info->vendor) {
667 case CFI_CMDSET_INTEL_EXTENDED:
668 case CFI_CMDSET_INTEL_STANDARD:
669 if ((retcode == ERR_OK)
670 && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {
671 retcode = ERR_INVAL;
672 printf ("Flash %s error at address %lx\n", prompt,
673 info->start[sector]);
674 if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS |
675 FLASH_STATUS_PSLBS)) {
676 puts ("Command Sequence Error.\n");
677 } else if (flash_isset (info, sector, 0,
678 FLASH_STATUS_ECLBS)) {
679 puts ("Block Erase Error.\n");
680 retcode = ERR_NOT_ERASED;
681 } else if (flash_isset (info, sector, 0,
682 FLASH_STATUS_PSLBS)) {
683 puts ("Locking Error\n");
684 }
685 if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) {
686 puts ("Block locked.\n");
687 retcode = ERR_PROTECTED;
688 }
689 if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS))
690 puts ("Vpp Low Error.\n");
691 }
692 flash_write_cmd (info, sector, 0, info->cmd_reset);
693 break;
694 default:
695 break;
696 }
697 return retcode;
698 }
699
700 /*-----------------------------------------------------------------------
701 */
702 static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c)
703 {
704 #if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
705 unsigned short w;
706 unsigned int l;
707 unsigned long long ll;
708 #endif
709
710 switch (info->portwidth) {
711 case FLASH_CFI_8BIT:
712 cword->c = c;
713 break;
714 case FLASH_CFI_16BIT:
715 #if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
716 w = c;
717 w <<= 8;
718 cword->w = (cword->w >> 8) | w;
719 #else
720 cword->w = (cword->w << 8) | c;
721 #endif
722 break;
723 case FLASH_CFI_32BIT:
724 #if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
725 l = c;
726 l <<= 24;
727 cword->l = (cword->l >> 8) | l;
728 #else
729 cword->l = (cword->l << 8) | c;
730 #endif
731 break;
732 case FLASH_CFI_64BIT:
733 #if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
734 ll = c;
735 ll <<= 56;
736 cword->ll = (cword->ll >> 8) | ll;
737 #else
738 cword->ll = (cword->ll << 8) | c;
739 #endif
740 break;
741 }
742 }
743
744 /* loop through the sectors from the highest address when the passed
745 * address is greater or equal to the sector address we have a match
746 */
747 static flash_sect_t find_sector (flash_info_t * info, ulong addr)
748 {
749 flash_sect_t sector;
750
751 for (sector = info->sector_count - 1; sector >= 0; sector--) {
752 if (addr >= info->start[sector])
753 break;
754 }
755 return sector;
756 }
757
758 /*-----------------------------------------------------------------------
759 */
760 static int flash_write_cfiword (flash_info_t * info, ulong dest,
761 cfiword_t cword)
762 {
763 void *dstaddr;
764 int flag;
765
766 dstaddr = map_physmem(dest, info->portwidth, MAP_NOCACHE);
767
768 /* Check if Flash is (sufficiently) erased */
769 switch (info->portwidth) {
770 case FLASH_CFI_8BIT:
771 flag = ((flash_read8(dstaddr) & cword.c) == cword.c);
772 break;
773 case FLASH_CFI_16BIT:
774 flag = ((flash_read16(dstaddr) & cword.w) == cword.w);
775 break;
776 case FLASH_CFI_32BIT:
777 flag = ((flash_read32(dstaddr) & cword.l) == cword.l);
778 break;
779 case FLASH_CFI_64BIT:
780 flag = ((flash_read64(dstaddr) & cword.ll) == cword.ll);
781 break;
782 default:
783 flag = 0;
784 break;
785 }
786 if (!flag) {
787 unmap_physmem(dstaddr, info->portwidth);
788 return ERR_NOT_ERASED;
789 }
790
791 /* Disable interrupts which might cause a timeout here */
792 flag = disable_interrupts ();
793
794 switch (info->vendor) {
795 case CFI_CMDSET_INTEL_EXTENDED:
796 case CFI_CMDSET_INTEL_STANDARD:
797 flash_write_cmd (info, 0, 0, FLASH_CMD_CLEAR_STATUS);
798 flash_write_cmd (info, 0, 0, FLASH_CMD_WRITE);
799 break;
800 case CFI_CMDSET_AMD_EXTENDED:
801 case CFI_CMDSET_AMD_STANDARD:
802 #ifdef CONFIG_FLASH_CFI_LEGACY
803 case CFI_CMDSET_AMD_LEGACY:
804 #endif
805 flash_unlock_seq (info, 0);
806 flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_WRITE);
807 break;
808 }
809
810 switch (info->portwidth) {
811 case FLASH_CFI_8BIT:
812 flash_write8(cword.c, dstaddr);
813 break;
814 case FLASH_CFI_16BIT:
815 flash_write16(cword.w, dstaddr);
816 break;
817 case FLASH_CFI_32BIT:
818 flash_write32(cword.l, dstaddr);
819 break;
820 case FLASH_CFI_64BIT:
821 flash_write64(cword.ll, dstaddr);
822 break;
823 }
824
825 /* re-enable interrupts if necessary */
826 if (flag)
827 enable_interrupts ();
828
829 unmap_physmem(dstaddr, info->portwidth);
830
831 return flash_full_status_check (info, find_sector (info, dest),
832 info->write_tout, "write");
833 }
834
835 #ifdef CFG_FLASH_USE_BUFFER_WRITE
836
837 static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
838 int len)
839 {
840 flash_sect_t sector;
841 int cnt;
842 int retcode;
843 void *src = cp;
844 void *dst = map_physmem(dest, len, MAP_NOCACHE);
845 void *dst2 = dst;
846 int flag = 0;
847 uint offset = 0;
848 unsigned int shift;
849
850 switch (info->portwidth) {
851 case FLASH_CFI_8BIT:
852 shift = 0;
853 break;
854 case FLASH_CFI_16BIT:
855 shift = 1;
856 break;
857 case FLASH_CFI_32BIT:
858 shift = 2;
859 break;
860 case FLASH_CFI_64BIT:
861 shift = 3;
862 break;
863 default:
864 retcode = ERR_INVAL;
865 goto out_unmap;
866 }
867
868 cnt = len >> shift;
869
870 while ((cnt-- > 0) && (flag == 0)) {
871 switch (info->portwidth) {
872 case FLASH_CFI_8BIT:
873 flag = ((flash_read8(dst2) & flash_read8(src)) ==
874 flash_read8(src));
875 src += 1, dst2 += 1;
876 break;
877 case FLASH_CFI_16BIT:
878 flag = ((flash_read16(dst2) & flash_read16(src)) ==
879 flash_read16(src));
880 src += 2, dst2 += 2;
881 break;
882 case FLASH_CFI_32BIT:
883 flag = ((flash_read32(dst2) & flash_read32(src)) ==
884 flash_read32(src));
885 src += 4, dst2 += 4;
886 break;
887 case FLASH_CFI_64BIT:
888 flag = ((flash_read64(dst2) & flash_read64(src)) ==
889 flash_read64(src));
890 src += 8, dst2 += 8;
891 break;
892 }
893 }
894 if (!flag) {
895 retcode = ERR_NOT_ERASED;
896 goto out_unmap;
897 }
898
899 src = cp;
900 sector = find_sector (info, dest);
901
902 switch (info->vendor) {
903 case CFI_CMDSET_INTEL_STANDARD:
904 case CFI_CMDSET_INTEL_EXTENDED:
905 flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
906 flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
907 retcode = flash_status_check (info, sector,
908 info->buffer_write_tout,
909 "write to buffer");
910 if (retcode == ERR_OK) {
911 /* reduce the number of loops by the width of
912 * the port */
913 cnt = len >> shift;
914 flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
915 while (cnt-- > 0) {
916 switch (info->portwidth) {
917 case FLASH_CFI_8BIT:
918 flash_write8(flash_read8(src), dst);
919 src += 1, dst += 1;
920 break;
921 case FLASH_CFI_16BIT:
922 flash_write16(flash_read16(src), dst);
923 src += 2, dst += 2;
924 break;
925 case FLASH_CFI_32BIT:
926 flash_write32(flash_read32(src), dst);
927 src += 4, dst += 4;
928 break;
929 case FLASH_CFI_64BIT:
930 flash_write64(flash_read64(src), dst);
931 src += 8, dst += 8;
932 break;
933 default:
934 retcode = ERR_INVAL;
935 goto out_unmap;
936 }
937 }
938 flash_write_cmd (info, sector, 0,
939 FLASH_CMD_WRITE_BUFFER_CONFIRM);
940 retcode = flash_full_status_check (
941 info, sector, info->buffer_write_tout,
942 "buffer write");
943 }
944
945 break;
946
947 case CFI_CMDSET_AMD_STANDARD:
948 case CFI_CMDSET_AMD_EXTENDED:
949 flash_unlock_seq(info,0);
950
951 #ifdef CONFIG_FLASH_SPANSION_S29WS_N
952 offset = ((unsigned long)dst - info->start[sector]) >> shift;
953 #endif
954 flash_write_cmd(info, sector, offset, AMD_CMD_WRITE_TO_BUFFER);
955 cnt = len >> shift;
956 flash_write_cmd(info, sector, offset, (uchar)cnt - 1);
957
958 switch (info->portwidth) {
959 case FLASH_CFI_8BIT:
960 while (cnt-- > 0) {
961 flash_write8(flash_read8(src), dst);
962 src += 1, dst += 1;
963 }
964 break;
965 case FLASH_CFI_16BIT:
966 while (cnt-- > 0) {
967 flash_write16(flash_read16(src), dst);
968 src += 2, dst += 2;
969 }
970 break;
971 case FLASH_CFI_32BIT:
972 while (cnt-- > 0) {
973 flash_write32(flash_read32(src), dst);
974 src += 4, dst += 4;
975 }
976 break;
977 case FLASH_CFI_64BIT:
978 while (cnt-- > 0) {
979 flash_write64(flash_read64(src), dst);
980 src += 8, dst += 8;
981 }
982 break;
983 default:
984 retcode = ERR_INVAL;
985 goto out_unmap;
986 }
987
988 flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
989 retcode = flash_full_status_check (info, sector,
990 info->buffer_write_tout,
991 "buffer write");
992 break;
993
994 default:
995 debug ("Unknown Command Set\n");
996 retcode = ERR_INVAL;
997 break;
998 }
999
1000 out_unmap:
1001 unmap_physmem(dst, len);
1002 return retcode;
1003 }
1004 #endif /* CFG_FLASH_USE_BUFFER_WRITE */
1005
1006
1007 /*-----------------------------------------------------------------------
1008 */
1009 int flash_erase (flash_info_t * info, int s_first, int s_last)
1010 {
1011 int rcode = 0;
1012 int prot;
1013 flash_sect_t sect;
1014
1015 if (info->flash_id != FLASH_MAN_CFI) {
1016 puts ("Can't erase unknown flash type - aborted\n");
1017 return 1;
1018 }
1019 if ((s_first < 0) || (s_first > s_last)) {
1020 puts ("- no sectors to erase\n");
1021 return 1;
1022 }
1023
1024 prot = 0;
1025 for (sect = s_first; sect <= s_last; ++sect) {
1026 if (info->protect[sect]) {
1027 prot++;
1028 }
1029 }
1030 if (prot) {
1031 printf ("- Warning: %d protected sectors will not be erased!\n",
1032 prot);
1033 } else {
1034 putc ('\n');
1035 }
1036
1037
1038 for (sect = s_first; sect <= s_last; sect++) {
1039 if (info->protect[sect] == 0) { /* not protected */
1040 switch (info->vendor) {
1041 case CFI_CMDSET_INTEL_STANDARD:
1042 case CFI_CMDSET_INTEL_EXTENDED:
1043 flash_write_cmd (info, sect, 0,
1044 FLASH_CMD_CLEAR_STATUS);
1045 flash_write_cmd (info, sect, 0,
1046 FLASH_CMD_BLOCK_ERASE);
1047 flash_write_cmd (info, sect, 0,
1048 FLASH_CMD_ERASE_CONFIRM);
1049 break;
1050 case CFI_CMDSET_AMD_STANDARD:
1051 case CFI_CMDSET_AMD_EXTENDED:
1052 flash_unlock_seq (info, sect);
1053 flash_write_cmd (info, sect,
1054 info->addr_unlock1,
1055 AMD_CMD_ERASE_START);
1056 flash_unlock_seq (info, sect);
1057 flash_write_cmd (info, sect, 0,
1058 AMD_CMD_ERASE_SECTOR);
1059 break;
1060 #ifdef CONFIG_FLASH_CFI_LEGACY
1061 case CFI_CMDSET_AMD_LEGACY:
1062 flash_unlock_seq (info, 0);
1063 flash_write_cmd (info, 0, info->addr_unlock1,
1064 AMD_CMD_ERASE_START);
1065 flash_unlock_seq (info, 0);
1066 flash_write_cmd (info, sect, 0,
1067 AMD_CMD_ERASE_SECTOR);
1068 break;
1069 #endif
1070 default:
1071 debug ("Unkown flash vendor %d\n",
1072 info->vendor);
1073 break;
1074 }
1075
1076 if (flash_full_status_check
1077 (info, sect, info->erase_blk_tout, "erase")) {
1078 rcode = 1;
1079 } else
1080 putc ('.');
1081 }
1082 }
1083 puts (" done\n");
1084 return rcode;
1085 }
1086
1087 /*-----------------------------------------------------------------------
1088 */
1089 void flash_print_info (flash_info_t * info)
1090 {
1091 int i;
1092
1093 if (info->flash_id != FLASH_MAN_CFI) {
1094 puts ("missing or unknown FLASH type\n");
1095 return;
1096 }
1097
1098 printf ("%s FLASH (%d x %d)",
1099 info->name,
1100 (info->portwidth << 3), (info->chipwidth << 3));
1101 if (info->size < 1024*1024)
1102 printf (" Size: %ld kB in %d Sectors\n",
1103 info->size >> 10, info->sector_count);
1104 else
1105 printf (" Size: %ld MB in %d Sectors\n",
1106 info->size >> 20, info->sector_count);
1107 printf (" ");
1108 switch (info->vendor) {
1109 case CFI_CMDSET_INTEL_STANDARD:
1110 printf ("Intel Standard");
1111 break;
1112 case CFI_CMDSET_INTEL_EXTENDED:
1113 printf ("Intel Extended");
1114 break;
1115 case CFI_CMDSET_AMD_STANDARD:
1116 printf ("AMD Standard");
1117 break;
1118 case CFI_CMDSET_AMD_EXTENDED:
1119 printf ("AMD Extended");
1120 break;
1121 #ifdef CONFIG_FLASH_CFI_LEGACY
1122 case CFI_CMDSET_AMD_LEGACY:
1123 printf ("AMD Legacy");
1124 break;
1125 #endif
1126 default:
1127 printf ("Unknown (%d)", info->vendor);
1128 break;
1129 }
1130 printf (" command set, Manufacturer ID: 0x%02X, Device ID: 0x%02X",
1131 info->manufacturer_id, info->device_id);
1132 if (info->device_id == 0x7E) {
1133 printf("%04X", info->device_id2);
1134 }
1135 printf ("\n Erase timeout: %ld ms, write timeout: %ld ms\n",
1136 info->erase_blk_tout,
1137 info->write_tout);
1138 if (info->buffer_size > 1) {
1139 printf (" Buffer write timeout: %ld ms, "
1140 "buffer size: %d bytes\n",
1141 info->buffer_write_tout,
1142 info->buffer_size);
1143 }
1144
1145 puts ("\n Sector Start Addresses:");
1146 for (i = 0; i < info->sector_count; ++i) {
1147 if ((i % 5) == 0)
1148 printf ("\n");
1149 #ifdef CFG_FLASH_EMPTY_INFO
1150 int k;
1151 int size;
1152 int erased;
1153 volatile unsigned long *flash;
1154
1155 /*
1156 * Check if whole sector is erased
1157 */
1158 size = flash_sector_size(info, i);
1159 erased = 1;
1160 flash = (volatile unsigned long *) info->start[i];
1161 size = size >> 2; /* divide by 4 for longword access */
1162 for (k = 0; k < size; k++) {
1163 if (*flash++ != 0xffffffff) {
1164 erased = 0;
1165 break;
1166 }
1167 }
1168
1169 /* print empty and read-only info */
1170 printf (" %08lX %c %s ",
1171 info->start[i],
1172 erased ? 'E' : ' ',
1173 info->protect[i] ? "RO" : " ");
1174 #else /* ! CFG_FLASH_EMPTY_INFO */
1175 printf (" %08lX %s ",
1176 info->start[i],
1177 info->protect[i] ? "RO" : " ");
1178 #endif
1179 }
1180 putc ('\n');
1181 return;
1182 }
1183
1184 /*-----------------------------------------------------------------------
1185 * This is used in a few places in write_buf() to show programming
1186 * progress. Making it a function is nasty because it needs to do side
1187 * effect updates to digit and dots. Repeated code is nasty too, so
1188 * we define it once here.
1189 */
1190 #ifdef CONFIG_FLASH_SHOW_PROGRESS
1191 #define FLASH_SHOW_PROGRESS(scale, dots, digit, dots_sub) \
1192 dots -= dots_sub; \
1193 if ((scale > 0) && (dots <= 0)) { \
1194 if ((digit % 5) == 0) \
1195 printf ("%d", digit / 5); \
1196 else \
1197 putc ('.'); \
1198 digit--; \
1199 dots += scale; \
1200 }
1201 #else
1202 #define FLASH_SHOW_PROGRESS(scale, dots, digit, dots_sub)
1203 #endif
1204
1205 /*-----------------------------------------------------------------------
1206 * Copy memory to flash, returns:
1207 * 0 - OK
1208 * 1 - write timeout
1209 * 2 - Flash not erased
1210 */
1211 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
1212 {
1213 ulong wp;
1214 uchar *p;
1215 int aln;
1216 cfiword_t cword;
1217 int i, rc;
1218 #ifdef CFG_FLASH_USE_BUFFER_WRITE
1219 int buffered_size;
1220 #endif
1221 #ifdef CONFIG_FLASH_SHOW_PROGRESS
1222 int digit = CONFIG_FLASH_SHOW_PROGRESS;
1223 int scale = 0;
1224 int dots = 0;
1225
1226 /*
1227 * Suppress if there are fewer than CONFIG_FLASH_SHOW_PROGRESS writes.
1228 */
1229 if (cnt >= CONFIG_FLASH_SHOW_PROGRESS) {
1230 scale = (int)((cnt + CONFIG_FLASH_SHOW_PROGRESS - 1) /
1231 CONFIG_FLASH_SHOW_PROGRESS);
1232 }
1233 #endif
1234
1235 /* get lower aligned address */
1236 wp = (addr & ~(info->portwidth - 1));
1237
1238 /* handle unaligned start */
1239 if ((aln = addr - wp) != 0) {
1240 cword.l = 0;
1241 p = map_physmem(wp, info->portwidth, MAP_NOCACHE);
1242 for (i = 0; i < aln; ++i)
1243 flash_add_byte (info, &cword, flash_read8(p + i));
1244
1245 for (; (i < info->portwidth) && (cnt > 0); i++) {
1246 flash_add_byte (info, &cword, *src++);
1247 cnt--;
1248 }
1249 for (; (cnt == 0) && (i < info->portwidth); ++i)
1250 flash_add_byte (info, &cword, flash_read8(p + i));
1251
1252 rc = flash_write_cfiword (info, wp, cword);
1253 unmap_physmem(p, info->portwidth);
1254 if (rc != 0)
1255 return rc;
1256
1257 wp += i;
1258 FLASH_SHOW_PROGRESS(scale, dots, digit, i);
1259 }
1260
1261 /* handle the aligned part */
1262 #ifdef CFG_FLASH_USE_BUFFER_WRITE
1263 buffered_size = (info->portwidth / info->chipwidth);
1264 buffered_size *= info->buffer_size;
1265 while (cnt >= info->portwidth) {
1266 /* prohibit buffer write when buffer_size is 1 */
1267 if (info->buffer_size == 1) {
1268 cword.l = 0;
1269 for (i = 0; i < info->portwidth; i++)
1270 flash_add_byte (info, &cword, *src++);
1271 if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
1272 return rc;
1273 wp += info->portwidth;
1274 cnt -= info->portwidth;
1275 continue;
1276 }
1277
1278 /* write buffer until next buffered_size aligned boundary */
1279 i = buffered_size - (wp % buffered_size);
1280 if (i > cnt)
1281 i = cnt;
1282 if ((rc = flash_write_cfibuffer (info, wp, src, i)) != ERR_OK)
1283 return rc;
1284 i -= i & (info->portwidth - 1);
1285 wp += i;
1286 src += i;
1287 cnt -= i;
1288 FLASH_SHOW_PROGRESS(scale, dots, digit, i);
1289 }
1290 #else
1291 while (cnt >= info->portwidth) {
1292 cword.l = 0;
1293 for (i = 0; i < info->portwidth; i++) {
1294 flash_add_byte (info, &cword, *src++);
1295 }
1296 if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
1297 return rc;
1298 wp += info->portwidth;
1299 cnt -= info->portwidth;
1300 FLASH_SHOW_PROGRESS(scale, dots, digit, info->portwidth);
1301 }
1302 #endif /* CFG_FLASH_USE_BUFFER_WRITE */
1303
1304 if (cnt == 0) {
1305 return (0);
1306 }
1307
1308 /*
1309 * handle unaligned tail bytes
1310 */
1311 cword.l = 0;
1312 p = map_physmem(wp, info->portwidth, MAP_NOCACHE);
1313 for (i = 0; (i < info->portwidth) && (cnt > 0); ++i) {
1314 flash_add_byte (info, &cword, *src++);
1315 --cnt;
1316 }
1317 for (; i < info->portwidth; ++i)
1318 flash_add_byte (info, &cword, flash_read8(p + i));
1319 unmap_physmem(p, info->portwidth);
1320
1321 return flash_write_cfiword (info, wp, cword);
1322 }
1323
1324 /*-----------------------------------------------------------------------
1325 */
1326 #ifdef CFG_FLASH_PROTECTION
1327
1328 int flash_real_protect (flash_info_t * info, long sector, int prot)
1329 {
1330 int retcode = 0;
1331
1332 flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
1333 flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);
1334 if (prot)
1335 flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET);
1336 else
1337 flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
1338
1339 if ((retcode =
1340 flash_full_status_check (info, sector, info->erase_blk_tout,
1341 prot ? "protect" : "unprotect")) == 0) {
1342
1343 info->protect[sector] = prot;
1344
1345 /*
1346 * On some of Intel's flash chips (marked via legacy_unlock)
1347 * unprotect unprotects all locking.
1348 */
1349 if ((prot == 0) && (info->legacy_unlock)) {
1350 flash_sect_t i;
1351
1352 for (i = 0; i < info->sector_count; i++) {
1353 if (info->protect[i])
1354 flash_real_protect (info, i, 1);
1355 }
1356 }
1357 }
1358 return retcode;
1359 }
1360
1361 /*-----------------------------------------------------------------------
1362 * flash_read_user_serial - read the OneTimeProgramming cells
1363 */
1364 void flash_read_user_serial (flash_info_t * info, void *buffer, int offset,
1365 int len)
1366 {
1367 uchar *src;
1368 uchar *dst;
1369
1370 dst = buffer;
1371 src = flash_map (info, 0, FLASH_OFFSET_USER_PROTECTION);
1372 flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
1373 memcpy (dst, src + offset, len);
1374 flash_write_cmd (info, 0, 0, info->cmd_reset);
1375 flash_unmap(info, 0, FLASH_OFFSET_USER_PROTECTION, src);
1376 }
1377
1378 /*
1379 * flash_read_factory_serial - read the device Id from the protection area
1380 */
1381 void flash_read_factory_serial (flash_info_t * info, void *buffer, int offset,
1382 int len)
1383 {
1384 uchar *src;
1385
1386 src = flash_map (info, 0, FLASH_OFFSET_INTEL_PROTECTION);
1387 flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
1388 memcpy (buffer, src + offset, len);
1389 flash_write_cmd (info, 0, 0, info->cmd_reset);
1390 flash_unmap(info, 0, FLASH_OFFSET_INTEL_PROTECTION, src);
1391 }
1392
1393 #endif /* CFG_FLASH_PROTECTION */
1394
1395 /*-----------------------------------------------------------------------
1396 * Reverse the order of the erase regions in the CFI QRY structure.
1397 * This is needed for chips that are either a) correctly detected as
1398 * top-boot, or b) buggy.
1399 */
1400 static void cfi_reverse_geometry(struct cfi_qry *qry)
1401 {
1402 unsigned int i, j;
1403 u32 tmp;
1404
1405 for (i = 0, j = qry->num_erase_regions - 1; i < j; i++, j--) {
1406 tmp = qry->erase_region_info[i];
1407 qry->erase_region_info[i] = qry->erase_region_info[j];
1408 qry->erase_region_info[j] = tmp;
1409 }
1410 }
1411
1412 /*-----------------------------------------------------------------------
1413 * read jedec ids from device and set corresponding fields in info struct
1414 *
1415 * Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct
1416 *
1417 */
1418 static void cmdset_intel_read_jedec_ids(flash_info_t *info)
1419 {
1420 flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
1421 flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID);
1422 udelay(1000); /* some flash are slow to respond */
1423 info->manufacturer_id = flash_read_uchar (info,
1424 FLASH_OFFSET_MANUFACTURER_ID);
1425 info->device_id = flash_read_uchar (info,
1426 FLASH_OFFSET_DEVICE_ID);
1427 flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
1428 }
1429
1430 static int cmdset_intel_init(flash_info_t *info, struct cfi_qry *qry)
1431 {
1432 info->cmd_reset = FLASH_CMD_RESET;
1433
1434 cmdset_intel_read_jedec_ids(info);
1435 flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);
1436
1437 #ifdef CFG_FLASH_PROTECTION
1438 /* read legacy lock/unlock bit from intel flash */
1439 if (info->ext_addr) {
1440 info->legacy_unlock = flash_read_uchar (info,
1441 info->ext_addr + 5) & 0x08;
1442 }
1443 #endif
1444
1445 return 0;
1446 }
1447
1448 static void cmdset_amd_read_jedec_ids(flash_info_t *info)
1449 {
1450 flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
1451 flash_unlock_seq(info, 0);
1452 flash_write_cmd(info, 0, info->addr_unlock1, FLASH_CMD_READ_ID);
1453 udelay(1000); /* some flash are slow to respond */
1454
1455 info->manufacturer_id = flash_read_uchar (info,
1456 FLASH_OFFSET_MANUFACTURER_ID);
1457
1458 switch (info->chipwidth){
1459 case FLASH_CFI_8BIT:
1460 info->device_id = flash_read_uchar (info,
1461 FLASH_OFFSET_DEVICE_ID);
1462 if (info->device_id == 0x7E) {
1463 /* AMD 3-byte (expanded) device ids */
1464 info->device_id2 = flash_read_uchar (info,
1465 FLASH_OFFSET_DEVICE_ID2);
1466 info->device_id2 <<= 8;
1467 info->device_id2 |= flash_read_uchar (info,
1468 FLASH_OFFSET_DEVICE_ID3);
1469 }
1470 break;
1471 case FLASH_CFI_16BIT:
1472 info->device_id = flash_read_word (info,
1473 FLASH_OFFSET_DEVICE_ID);
1474 break;
1475 default:
1476 break;
1477 }
1478 flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
1479 }
1480
1481 static int cmdset_amd_init(flash_info_t *info, struct cfi_qry *qry)
1482 {
1483 info->cmd_reset = AMD_CMD_RESET;
1484
1485 cmdset_amd_read_jedec_ids(info);
1486 flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);
1487
1488 return 0;
1489 }
1490
1491 #ifdef CONFIG_FLASH_CFI_LEGACY
1492 static void flash_read_jedec_ids (flash_info_t * info)
1493 {
1494 info->manufacturer_id = 0;
1495 info->device_id = 0;
1496 info->device_id2 = 0;
1497
1498 switch (info->vendor) {
1499 case CFI_CMDSET_INTEL_STANDARD:
1500 case CFI_CMDSET_INTEL_EXTENDED:
1501 cmdset_intel_read_jedec_ids(info);
1502 break;
1503 case CFI_CMDSET_AMD_STANDARD:
1504 case CFI_CMDSET_AMD_EXTENDED:
1505 cmdset_amd_read_jedec_ids(info);
1506 break;
1507 default:
1508 break;
1509 }
1510 }
1511
1512 /*-----------------------------------------------------------------------
1513 * Call board code to request info about non-CFI flash.
1514 * board_flash_get_legacy needs to fill in at least:
1515 * info->portwidth, info->chipwidth and info->interface for Jedec probing.
1516 */
1517 static int flash_detect_legacy(ulong base, int banknum)
1518 {
1519 flash_info_t *info = &flash_info[banknum];
1520
1521 if (board_flash_get_legacy(base, banknum, info)) {
1522 /* board code may have filled info completely. If not, we
1523 use JEDEC ID probing. */
1524 if (!info->vendor) {
1525 int modes[] = {
1526 CFI_CMDSET_AMD_STANDARD,
1527 CFI_CMDSET_INTEL_STANDARD
1528 };
1529 int i;
1530
1531 for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) {
1532 info->vendor = modes[i];
1533 info->start[0] = base;
1534 if (info->portwidth == FLASH_CFI_8BIT
1535 && info->interface == FLASH_CFI_X8X16) {
1536 info->addr_unlock1 = 0x2AAA;
1537 info->addr_unlock2 = 0x5555;
1538 } else {
1539 info->addr_unlock1 = 0x5555;
1540 info->addr_unlock2 = 0x2AAA;
1541 }
1542 flash_read_jedec_ids(info);
1543 debug("JEDEC PROBE: ID %x %x %x\n",
1544 info->manufacturer_id,
1545 info->device_id,
1546 info->device_id2);
1547 if (jedec_flash_match(info, base))
1548 break;
1549 }
1550 }
1551
1552 switch(info->vendor) {
1553 case CFI_CMDSET_INTEL_STANDARD:
1554 case CFI_CMDSET_INTEL_EXTENDED:
1555 info->cmd_reset = FLASH_CMD_RESET;
1556 break;
1557 case CFI_CMDSET_AMD_STANDARD:
1558 case CFI_CMDSET_AMD_EXTENDED:
1559 case CFI_CMDSET_AMD_LEGACY:
1560 info->cmd_reset = AMD_CMD_RESET;
1561 break;
1562 }
1563 info->flash_id = FLASH_MAN_CFI;
1564 return 1;
1565 }
1566 return 0; /* use CFI */
1567 }
1568 #else
1569 static inline int flash_detect_legacy(ulong base, int banknum)
1570 {
1571 return 0; /* use CFI */
1572 }
1573 #endif
1574
1575 /*-----------------------------------------------------------------------
1576 * detect if flash is compatible with the Common Flash Interface (CFI)
1577 * http://www.jedec.org/download/search/jesd68.pdf
1578 */
1579 static void flash_read_cfi (flash_info_t *info, void *buf,
1580 unsigned int start, size_t len)
1581 {
1582 u8 *p = buf;
1583 unsigned int i;
1584
1585 for (i = 0; i < len; i++)
1586 p[i] = flash_read_uchar(info, start + i);
1587 }
1588
1589 static int __flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry)
1590 {
1591 int cfi_offset;
1592
1593 /* We do not yet know what kind of commandset to use, so we issue
1594 the reset command in both Intel and AMD variants, in the hope
1595 that AMD flash roms ignore the Intel command. */
1596 flash_write_cmd (info, 0, 0, AMD_CMD_RESET);
1597 flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
1598
1599 for (cfi_offset=0;
1600 cfi_offset < sizeof(flash_offset_cfi) / sizeof(uint);
1601 cfi_offset++) {
1602 flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset],
1603 FLASH_CMD_CFI);
1604 if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
1605 && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')
1606 && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) {
1607 flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP,
1608 sizeof(struct cfi_qry));
1609 info->interface = le16_to_cpu(qry->interface_desc);
1610
1611 info->cfi_offset = flash_offset_cfi[cfi_offset];
1612 debug ("device interface is %d\n",
1613 info->interface);
1614 debug ("found port %d chip %d ",
1615 info->portwidth, info->chipwidth);
1616 debug ("port %d bits chip %d bits\n",
1617 info->portwidth << CFI_FLASH_SHIFT_WIDTH,
1618 info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
1619
1620 /* calculate command offsets as in the Linux driver */
1621 info->addr_unlock1 = 0x555;
1622 info->addr_unlock2 = 0x2aa;
1623
1624 /*
1625 * modify the unlock address if we are
1626 * in compatibility mode
1627 */
1628 if ( /* x8/x16 in x8 mode */
1629 ((info->chipwidth == FLASH_CFI_BY8) &&
1630 (info->interface == FLASH_CFI_X8X16)) ||
1631 /* x16/x32 in x16 mode */
1632 ((info->chipwidth == FLASH_CFI_BY16) &&
1633 (info->interface == FLASH_CFI_X16X32)))
1634 {
1635 info->addr_unlock1 = 0xaaa;
1636 info->addr_unlock2 = 0x555;
1637 }
1638
1639 info->name = "CFI conformant";
1640 return 1;
1641 }
1642 }
1643
1644 return 0;
1645 }
1646
1647 static int flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry)
1648 {
1649 debug ("flash detect cfi\n");
1650
1651 for (info->portwidth = CFG_FLASH_CFI_WIDTH;
1652 info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) {
1653 for (info->chipwidth = FLASH_CFI_BY8;
1654 info->chipwidth <= info->portwidth;
1655 info->chipwidth <<= 1)
1656 if (__flash_detect_cfi(info, qry))
1657 return 1;
1658 }
1659 debug ("not found\n");
1660 return 0;
1661 }
1662
1663 /*
1664 * Manufacturer-specific quirks. Add workarounds for geometry
1665 * reversal, etc. here.
1666 */
1667 static void flash_fixup_amd(flash_info_t *info, struct cfi_qry *qry)
1668 {
1669 /* check if flash geometry needs reversal */
1670 if (qry->num_erase_regions > 1) {
1671 /* reverse geometry if top boot part */
1672 if (info->cfi_version < 0x3131) {
1673 /* CFI < 1.1, try to guess from device id */
1674 if ((info->device_id & 0x80) != 0)
1675 cfi_reverse_geometry(qry);
1676 } else if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) {
1677 /* CFI >= 1.1, deduct from top/bottom flag */
1678 /* note: ext_addr is valid since cfi_version > 0 */
1679 cfi_reverse_geometry(qry);
1680 }
1681 }
1682 }
1683
1684 static void flash_fixup_atmel(flash_info_t *info, struct cfi_qry *qry)
1685 {
1686 int reverse_geometry = 0;
1687
1688 /* Check the "top boot" bit in the PRI */
1689 if (info->ext_addr && !(flash_read_uchar(info, info->ext_addr + 6) & 1))
1690 reverse_geometry = 1;
1691
1692 /* AT49BV6416(T) list the erase regions in the wrong order.
1693 * However, the device ID is identical with the non-broken
1694 * AT49BV642D since u-boot only reads the low byte (they
1695 * differ in the high byte.) So leave out this fixup for now.
1696 */
1697 #if 0
1698 if (info->device_id == 0xd6 || info->device_id == 0xd2)
1699 reverse_geometry = !reverse_geometry;
1700 #endif
1701
1702 if (reverse_geometry)
1703 cfi_reverse_geometry(qry);
1704 }
1705
1706 /*
1707 * The following code cannot be run from FLASH!
1708 *
1709 */
1710 ulong flash_get_size (ulong base, int banknum)
1711 {
1712 flash_info_t *info = &flash_info[banknum];
1713 int i, j;
1714 flash_sect_t sect_cnt;
1715 unsigned long sector;
1716 unsigned long tmp;
1717 int size_ratio;
1718 uchar num_erase_regions;
1719 int erase_region_size;
1720 int erase_region_count;
1721 struct cfi_qry qry;
1722
1723 info->ext_addr = 0;
1724 info->cfi_version = 0;
1725 #ifdef CFG_FLASH_PROTECTION
1726 info->legacy_unlock = 0;
1727 #endif
1728
1729 info->start[0] = base;
1730
1731 if (flash_detect_cfi (info, &qry)) {
1732 info->vendor = le16_to_cpu(qry.p_id);
1733 info->ext_addr = le16_to_cpu(qry.p_adr);
1734 num_erase_regions = qry.num_erase_regions;
1735
1736 if (info->ext_addr) {
1737 info->cfi_version = (ushort) flash_read_uchar (info,
1738 info->ext_addr + 3) << 8;
1739 info->cfi_version |= (ushort) flash_read_uchar (info,
1740 info->ext_addr + 4);
1741 }
1742
1743 #ifdef DEBUG
1744 flash_printqry (&qry);
1745 #endif
1746
1747 switch (info->vendor) {
1748 case CFI_CMDSET_INTEL_STANDARD:
1749 case CFI_CMDSET_INTEL_EXTENDED:
1750 cmdset_intel_init(info, &qry);
1751 break;
1752 case CFI_CMDSET_AMD_STANDARD:
1753 case CFI_CMDSET_AMD_EXTENDED:
1754 cmdset_amd_init(info, &qry);
1755 break;
1756 default:
1757 printf("CFI: Unknown command set 0x%x\n",
1758 info->vendor);
1759 /*
1760 * Unfortunately, this means we don't know how
1761 * to get the chip back to Read mode. Might
1762 * as well try an Intel-style reset...
1763 */
1764 flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
1765 return 0;
1766 }
1767
1768 /* Do manufacturer-specific fixups */
1769 switch (info->manufacturer_id) {
1770 case 0x0001:
1771 flash_fixup_amd(info, &qry);
1772 break;
1773 case 0x001f:
1774 flash_fixup_atmel(info, &qry);
1775 break;
1776 }
1777
1778 debug ("manufacturer is %d\n", info->vendor);
1779 debug ("manufacturer id is 0x%x\n", info->manufacturer_id);
1780 debug ("device id is 0x%x\n", info->device_id);
1781 debug ("device id2 is 0x%x\n", info->device_id2);
1782 debug ("cfi version is 0x%04x\n", info->cfi_version);
1783
1784 size_ratio = info->portwidth / info->chipwidth;
1785 /* if the chip is x8/x16 reduce the ratio by half */
1786 if ((info->interface == FLASH_CFI_X8X16)
1787 && (info->chipwidth == FLASH_CFI_BY8)) {
1788 size_ratio >>= 1;
1789 }
1790 debug ("size_ratio %d port %d bits chip %d bits\n",
1791 size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH,
1792 info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
1793 debug ("found %d erase regions\n", num_erase_regions);
1794 sect_cnt = 0;
1795 sector = base;
1796 for (i = 0; i < num_erase_regions; i++) {
1797 if (i > NUM_ERASE_REGIONS) {
1798 printf ("%d erase regions found, only %d used\n",
1799 num_erase_regions, NUM_ERASE_REGIONS);
1800 break;
1801 }
1802
1803 tmp = le32_to_cpu(qry.erase_region_info[i]);
1804 debug("erase region %u: 0x%08lx\n", i, tmp);
1805
1806 erase_region_count = (tmp & 0xffff) + 1;
1807 tmp >>= 16;
1808 erase_region_size =
1809 (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
1810 debug ("erase_region_count = %d erase_region_size = %d\n",
1811 erase_region_count, erase_region_size);
1812 for (j = 0; j < erase_region_count; j++) {
1813 if (sect_cnt >= CFG_MAX_FLASH_SECT) {
1814 printf("ERROR: too many flash sectors\n");
1815 break;
1816 }
1817 info->start[sect_cnt] = sector;
1818 sector += (erase_region_size * size_ratio);
1819
1820 /*
1821 * Only read protection status from
1822 * supported devices (intel...)
1823 */
1824 switch (info->vendor) {
1825 case CFI_CMDSET_INTEL_EXTENDED:
1826 case CFI_CMDSET_INTEL_STANDARD:
1827 info->protect[sect_cnt] =
1828 flash_isset (info, sect_cnt,
1829 FLASH_OFFSET_PROTECT,
1830 FLASH_STATUS_PROTECT);
1831 break;
1832 default:
1833 /* default: not protected */
1834 info->protect[sect_cnt] = 0;
1835 }
1836
1837 sect_cnt++;
1838 }
1839 }
1840
1841 info->sector_count = sect_cnt;
1842 info->size = 1 << qry.dev_size;
1843 /* multiply the size by the number of chips */
1844 info->size *= size_ratio;
1845 info->buffer_size = 1 << le16_to_cpu(qry.max_buf_write_size);
1846 tmp = 1 << qry.block_erase_timeout_typ;
1847 info->erase_blk_tout = tmp *
1848 (1 << qry.block_erase_timeout_max);
1849 tmp = (1 << qry.buf_write_timeout_typ) *
1850 (1 << qry.buf_write_timeout_max);
1851
1852 /* round up when converting to ms */
1853 info->buffer_write_tout = (tmp + 999) / 1000;
1854 tmp = (1 << qry.word_write_timeout_typ) *
1855 (1 << qry.word_write_timeout_max);
1856 /* round up when converting to ms */
1857 info->write_tout = (tmp + 999) / 1000;
1858 info->flash_id = FLASH_MAN_CFI;
1859 if ((info->interface == FLASH_CFI_X8X16) &&
1860 (info->chipwidth == FLASH_CFI_BY8)) {
1861 /* XXX - Need to test on x8/x16 in parallel. */
1862 info->portwidth >>= 1;
1863 }
1864 }
1865
1866 flash_write_cmd (info, 0, 0, info->cmd_reset);
1867 return (info->size);
1868 }
1869
1870 /*-----------------------------------------------------------------------
1871 */
1872 unsigned long flash_init (void)
1873 {
1874 unsigned long size = 0;
1875 int i;
1876 #if defined(CFG_FLASH_AUTOPROTECT_LIST)
1877 struct apl_s {
1878 ulong start;
1879 ulong size;
1880 } apl[] = CFG_FLASH_AUTOPROTECT_LIST;
1881 #endif
1882
1883 #ifdef CFG_FLASH_PROTECTION
1884 char *s = getenv("unlock");
1885 #endif
1886
1887 /* Init: no FLASHes known */
1888 for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
1889 flash_info[i].flash_id = FLASH_UNKNOWN;
1890
1891 if (!flash_detect_legacy (bank_base[i], i))
1892 flash_get_size (bank_base[i], i);
1893 size += flash_info[i].size;
1894 if (flash_info[i].flash_id == FLASH_UNKNOWN) {
1895 #ifndef CFG_FLASH_QUIET_TEST
1896 printf ("## Unknown FLASH on Bank %d "
1897 "- Size = 0x%08lx = %ld MB\n",
1898 i+1, flash_info[i].size,
1899 flash_info[i].size << 20);
1900 #endif /* CFG_FLASH_QUIET_TEST */
1901 }
1902 #ifdef CFG_FLASH_PROTECTION
1903 else if ((s != NULL) && (strcmp(s, "yes") == 0)) {
1904 /*
1905 * Only the U-Boot image and it's environment
1906 * is protected, all other sectors are
1907 * unprotected (unlocked) if flash hardware
1908 * protection is used (CFG_FLASH_PROTECTION)
1909 * and the environment variable "unlock" is
1910 * set to "yes".
1911 */
1912 if (flash_info[i].legacy_unlock) {
1913 int k;
1914
1915 /*
1916 * Disable legacy_unlock temporarily,
1917 * since flash_real_protect would
1918 * relock all other sectors again
1919 * otherwise.
1920 */
1921 flash_info[i].legacy_unlock = 0;
1922
1923 /*
1924 * Legacy unlocking (e.g. Intel J3) ->
1925 * unlock only one sector. This will
1926 * unlock all sectors.
1927 */
1928 flash_real_protect (&flash_info[i], 0, 0);
1929
1930 flash_info[i].legacy_unlock = 1;
1931
1932 /*
1933 * Manually mark other sectors as
1934 * unlocked (unprotected)
1935 */
1936 for (k = 1; k < flash_info[i].sector_count; k++)
1937 flash_info[i].protect[k] = 0;
1938 } else {
1939 /*
1940 * No legancy unlocking -> unlock all sectors
1941 */
1942 flash_protect (FLAG_PROTECT_CLEAR,
1943 flash_info[i].start[0],
1944 flash_info[i].start[0]
1945 + flash_info[i].size - 1,
1946 &flash_info[i]);
1947 }
1948 }
1949 #endif /* CFG_FLASH_PROTECTION */
1950 }
1951
1952 /* Monitor protection ON by default */
1953 #if (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
1954 flash_protect (FLAG_PROTECT_SET,
1955 CFG_MONITOR_BASE,
1956 CFG_MONITOR_BASE + monitor_flash_len - 1,
1957 flash_get_info(CFG_MONITOR_BASE));
1958 #endif
1959
1960 /* Environment protection ON by default */
1961 #ifdef CFG_ENV_IS_IN_FLASH
1962 flash_protect (FLAG_PROTECT_SET,
1963 CFG_ENV_ADDR,
1964 CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
1965 flash_get_info(CFG_ENV_ADDR));
1966 #endif
1967
1968 /* Redundant environment protection ON by default */
1969 #ifdef CFG_ENV_ADDR_REDUND
1970 flash_protect (FLAG_PROTECT_SET,
1971 CFG_ENV_ADDR_REDUND,
1972 CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1,
1973 flash_get_info(CFG_ENV_ADDR_REDUND));
1974 #endif
1975
1976 #if defined(CFG_FLASH_AUTOPROTECT_LIST)
1977 for (i = 0; i < (sizeof(apl) / sizeof(struct apl_s)); i++) {
1978 debug("autoprotecting from %08x to %08x\n",
1979 apl[i].start, apl[i].start + apl[i].size - 1);
1980 flash_protect (FLAG_PROTECT_SET,
1981 apl[i].start,
1982 apl[i].start + apl[i].size - 1,
1983 flash_get_info(apl[i].start));
1984 }
1985 #endif
1986 return (size);
1987 }
1988
1989 #endif /* CFG_FLASH_CFI */