blob: 977822ac51e10b562d9af76f54bbf6bb66a2bea4 [file] [log] [blame]
wdenk337f5652004-10-28 00:09:35 +00001/*
2 * (C) Copyright 2001
3 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
4 *
5 * (C) Copyright 2001-2004
6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
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#include <linux/byteorder/swab.h>
29
30
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020031flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
wdenk337f5652004-10-28 00:09:35 +000032
33/* Board support for 1 or 2 flash devices */
34#define FLASH_PORT_WIDTH8
35
36typedef unsigned char FLASH_PORT_WIDTH;
37typedef volatile unsigned char FLASH_PORT_WIDTHV;
38
39#define SWAP(x) (x)
40
41/* Intel-compatible flash ID */
42#define INTEL_COMPAT 0x89
43#define INTEL_ALT 0xB0
44
45/* Intel-compatible flash commands */
46#define INTEL_PROGRAM 0x10
47#define INTEL_ERASE 0x20
48#define INTEL_CLEAR 0x50
49#define INTEL_LOCKBIT 0x60
50#define INTEL_PROTECT 0x01
51#define INTEL_STATUS 0x70
52#define INTEL_READID 0x90
53#define INTEL_CONFIRM 0xD0
54#define INTEL_RESET 0xFF
55
56/* Intel-compatible flash status bits */
57#define INTEL_FINISHED 0x80
58#define INTEL_OK 0x80
59
60#define FPW FLASH_PORT_WIDTH
61#define FPWV FLASH_PORT_WIDTHV
62
63#define FLASH_CYCLE1 0x0555
64#define FLASH_CYCLE2 0x02aa
65
66#define WR_BLOCK 0x20
wdenk337f5652004-10-28 00:09:35 +000067/*-----------------------------------------------------------------------
68 * Functions
69 */
70static ulong flash_get_size (FPW * addr, flash_info_t * info);
71static int write_data (flash_info_t * info, ulong dest, FPW data);
72static int write_data_block (flash_info_t * info, ulong src, ulong dest);
73static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data);
74static void flash_get_offsets (ulong base, flash_info_t * info);
75void inline spin_wheel (void);
Wolfgang Denk862eeeb2005-07-30 16:39:27 +020076static void flash_sync_real_protect (flash_info_t * info);
77static unsigned char intel_sector_protected (flash_info_t *info, ushort sector);
78static unsigned char same_chip_banks (int bank1, int bank2);
wdenk337f5652004-10-28 00:09:35 +000079
80/*-----------------------------------------------------------------------
81 */
82
83unsigned long flash_init (void)
84{
85 int i;
86 ulong size = 0;
87 ulong fsize = 0;
88
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020089 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
wdenk337f5652004-10-28 00:09:35 +000090 memset (&flash_info[i], 0, sizeof (flash_info_t));
91
92 switch (i) {
93 case 0:
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020094 flash_get_size ((FPW *) CONFIG_SYS_FLASH1_BASE,
wdenk337f5652004-10-28 00:09:35 +000095 &flash_info[i]);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020096 flash_get_offsets (CONFIG_SYS_FLASH1_BASE, &flash_info[i]);
wdenk337f5652004-10-28 00:09:35 +000097 break;
98 case 1:
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020099 flash_get_size ((FPW *) CONFIG_SYS_FLASH1_BASE,
wdenk337f5652004-10-28 00:09:35 +0000100 &flash_info[i]);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200101 fsize = CONFIG_SYS_FLASH1_BASE + flash_info[i - 1].size;
wdenk337f5652004-10-28 00:09:35 +0000102 flash_get_offsets (fsize, &flash_info[i]);
103 break;
104 case 2:
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200105 flash_get_size ((FPW *) CONFIG_SYS_FLASH0_BASE,
wdenk337f5652004-10-28 00:09:35 +0000106 &flash_info[i]);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200107 flash_get_offsets (CONFIG_SYS_FLASH0_BASE, &flash_info[i]);
wdenk337f5652004-10-28 00:09:35 +0000108 break;
109 case 3:
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200110 flash_get_size ((FPW *) CONFIG_SYS_FLASH0_BASE,
wdenk337f5652004-10-28 00:09:35 +0000111 &flash_info[i]);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200112 fsize = CONFIG_SYS_FLASH0_BASE + flash_info[i - 1].size;
wdenk337f5652004-10-28 00:09:35 +0000113 flash_get_offsets (fsize, &flash_info[i]);
114 break;
115 default:
116 panic ("configured to many flash banks!\n");
117 break;
118 }
119 size += flash_info[i].size;
Wolfgang Denk862eeeb2005-07-30 16:39:27 +0200120
121 /* get the h/w and s/w protection status in sync */
122 flash_sync_real_protect(&flash_info[i]);
wdenk337f5652004-10-28 00:09:35 +0000123 }
124
125 /* Protect monitor and environment sectors
126 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200127#if defined (CONFIG_SYS_AMD_BOOT)
wdenk337f5652004-10-28 00:09:35 +0000128 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200129 CONFIG_SYS_MONITOR_BASE,
130 CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
wdenk337f5652004-10-28 00:09:35 +0000131 &flash_info[2]);
132 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200133 CONFIG_SYS_INTEL_BASE,
134 CONFIG_SYS_INTEL_BASE + monitor_flash_len - 1,
wdenk337f5652004-10-28 00:09:35 +0000135 &flash_info[1]);
136#else
137 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200138 CONFIG_SYS_MONITOR_BASE,
139 CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
wdenk337f5652004-10-28 00:09:35 +0000140 &flash_info[3]);
141 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200142 CONFIG_SYS_AMD_BASE,
143 CONFIG_SYS_AMD_BASE + monitor_flash_len - 1, &flash_info[0]);
wdenk337f5652004-10-28 00:09:35 +0000144#endif
145
146 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD7e1cda62008-09-10 22:48:06 +0200147 CONFIG_ENV1_ADDR,
148 CONFIG_ENV1_ADDR + CONFIG_ENV1_SIZE - 1, &flash_info[1]);
wdenk337f5652004-10-28 00:09:35 +0000149 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD7e1cda62008-09-10 22:48:06 +0200150 CONFIG_ENV_ADDR,
151 CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[3]);
wdenk337f5652004-10-28 00:09:35 +0000152
153 return size;
154}
155
156/*-----------------------------------------------------------------------
157 */
158static void flash_get_offsets (ulong base, flash_info_t * info)
159{
160 int i;
161
162 if (info->flash_id == FLASH_UNKNOWN)
163 return;
164
165 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) {
166 for (i = 0; i < info->sector_count; i++) {
167 info->start[i] = base + (i * PHYS_AMD_SECT_SIZE);
168 info->protect[i] = 0;
169 }
170 }
171
172 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
173 for (i = 0; i < info->sector_count; i++) {
174 info->start[i] = base + (i * PHYS_INTEL_SECT_SIZE);
wdenk337f5652004-10-28 00:09:35 +0000175 }
176 }
177}
178
179/*-----------------------------------------------------------------------
180 */
181void flash_print_info (flash_info_t * info)
182{
183 int i;
184
185 if (info->flash_id == FLASH_UNKNOWN) {
186 printf ("missing or unknown FLASH type\n");
187 return;
188 }
189
190 switch (info->flash_id & FLASH_VENDMASK) {
191 case FLASH_MAN_INTEL:
192 printf ("INTEL ");
193 break;
194 case FLASH_MAN_AMD:
195 printf ("AMD ");
196 break;
197 default:
198 printf ("Unknown Vendor ");
199 break;
200 }
201
202 switch (info->flash_id & FLASH_TYPEMASK) {
203 case FLASH_28F128J3A:
204 printf ("28F128J3A\n");
205 break;
206
207 case FLASH_AM040:
208 printf ("AMD29F040B\n");
209 break;
210
211 default:
212 printf ("Unknown Chip Type\n");
213 break;
214 }
215
216 printf (" Size: %ld MB in %d Sectors\n",
217 info->size >> 20, info->sector_count);
218
219 printf (" Sector Start Addresses:");
220 for (i = 0; i < info->sector_count; ++i) {
221 if ((i % 5) == 0)
222 printf ("\n ");
223 printf (" %08lX%s",
224 info->start[i], info->protect[i] ? " (RO)" : " ");
225 }
226 printf ("\n");
227 return;
228}
229
230/*
231 * The following code cannot be run from FLASH!
232 */
233static ulong flash_get_size (FPW * addr, flash_info_t * info)
234{
235 FPWV value;
236 static int amd = 0;
237
238 /* Write auto select command: read Manufacturer ID */
239 /* Write auto select command sequence and test FLASH answer */
240 addr[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* for AMD, Intel ignores this */
241 __asm__ ("sync");
242 addr[FLASH_CYCLE2] = (FPW) 0x00550055; /* for AMD, Intel ignores this */
243 __asm__ ("sync");
244 addr[FLASH_CYCLE1] = (FPW) 0x00900090; /* selects Intel or AMD */
245 __asm__ ("sync");
246
247 udelay (100);
248
249 switch (addr[0] & 0xff) {
250
251 case (uchar) AMD_MANUFACT:
252 info->flash_id = FLASH_MAN_AMD;
253 value = addr[1];
254 break;
255
256 case (uchar) INTEL_MANUFACT:
257 info->flash_id = FLASH_MAN_INTEL;
258 value = addr[2];
259 break;
260
261 default:
262 printf ("unknown\n");
263 info->flash_id = FLASH_UNKNOWN;
264 info->sector_count = 0;
265 info->size = 0;
266 addr[0] = (FPW) 0x00FF00FF; /* restore read mode */
267 return (0); /* no or unknown flash */
268 }
269
270 switch (value) {
271
272 case (FPW) INTEL_ID_28F128J3A:
273 info->flash_id += FLASH_28F128J3A;
274 info->sector_count = 64;
275 info->size = 0x00800000; /* => 16 MB */
276 break;
277
278 case (FPW) AMD_ID_LV040B:
279 info->flash_id += FLASH_AM040;
280 if (amd == 0) {
281 info->sector_count = 7;
282 info->size = 0x00070000; /* => 448 KB */
283 amd = 1;
284 } else {
285 /* for Environment settings */
286 info->sector_count = 1;
287 info->size = PHYS_AMD_SECT_SIZE; /* => 64 KB */
288 amd = 0;
289 }
290 break;
291
292 default:
293 info->flash_id = FLASH_UNKNOWN;
294 break;
295 }
296
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200297 if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
wdenk337f5652004-10-28 00:09:35 +0000298 printf ("** ERROR: sector count %d > max (%d) **\n",
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200299 info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
300 info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
wdenk337f5652004-10-28 00:09:35 +0000301 }
302
303 if (value == (FPW) INTEL_ID_28F128J3A)
304 addr[0] = (FPW) 0x00FF00FF; /* restore read mode */
305 else
306 addr[0] = (FPW) 0x00F000F0; /* restore read mode */
307
308 return (info->size);
309}
310
311
Wolfgang Denk862eeeb2005-07-30 16:39:27 +0200312/*
313 * This function gets the u-boot flash sector protection status
314 * (flash_info_t.protect[]) in sync with the sector protection
315 * status stored in hardware.
316 */
317static void flash_sync_real_protect (flash_info_t * info)
318{
319 int i;
320
321 switch (info->flash_id & FLASH_TYPEMASK) {
322 case FLASH_28F128J3A:
323 for (i = 0; i < info->sector_count; ++i) {
324 info->protect[i] = intel_sector_protected(info, i);
325 }
326 break;
327 case FLASH_AM040:
328 default:
329 /* no h/w protect support */
330 break;
331 }
332}
333
334
335/*
336 * checks if "sector" in bank "info" is protected. Should work on intel
337 * strata flash chips 28FxxxJ3x in 8-bit mode.
338 * Returns 1 if sector is protected (or timed-out while trying to read
339 * protection status), 0 if it is not.
340 */
341static unsigned char intel_sector_protected (flash_info_t *info, ushort sector)
342{
343 FPWV *addr;
344 FPWV *lock_conf_addr;
345 ulong start;
346 unsigned char ret;
347
348 /*
349 * first, wait for the WSM to be finished. The rationale for
350 * waiting for the WSM to become idle for at most
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200351 * CONFIG_SYS_FLASH_ERASE_TOUT is as follows. The WSM can be busy
Wolfgang Denk862eeeb2005-07-30 16:39:27 +0200352 * because of: (1) erase, (2) program or (3) lock bit
353 * configuration. So we just wait for the longest timeout of
354 * the (1)-(3), i.e. the erase timeout.
355 */
356
357 /* wait at least 35ns (W12) before issuing Read Status Register */
358 udelay(1);
359 addr = (FPWV *) info->start[sector];
360 *addr = (FPW) INTEL_STATUS;
361
362 start = get_timer (0);
363 while ((*addr & (FPW) INTEL_FINISHED) != (FPW) INTEL_FINISHED) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200364 if (get_timer (start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
Wolfgang Denk862eeeb2005-07-30 16:39:27 +0200365 *addr = (FPW) INTEL_RESET; /* restore read mode */
366 printf("WSM busy too long, can't get prot status\n");
367 return 1;
368 }
369 }
370
371 /* issue the Read Identifier Codes command */
372 *addr = (FPW) INTEL_READID;
373
374 /* wait at least 35ns (W12) before reading */
375 udelay(1);
376
377 /* Intel example code uses offset of 4 for 8-bit flash */
378 lock_conf_addr = (FPWV *) info->start[sector] + 4;
379 ret = (*lock_conf_addr & (FPW) INTEL_PROTECT) ? 1 : 0;
380
381 /* put flash back in read mode */
382 *addr = (FPW) INTEL_RESET;
383
384 return ret;
385}
386
387
388/*
389 * Checks if "bank1" and "bank2" are on the same chip. Returns 1 if they
390 * are and 0 otherwise.
391 */
392static unsigned char same_chip_banks (int bank1, int bank2)
393{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200394 unsigned char same_chip[CONFIG_SYS_MAX_FLASH_BANKS][CONFIG_SYS_MAX_FLASH_BANKS] = {
Wolfgang Denk862eeeb2005-07-30 16:39:27 +0200395 {1, 1, 0, 0},
396 {1, 1, 0, 0},
397 {0, 0, 1, 1},
398 {0, 0, 1, 1}
399 };
400 return same_chip[bank1][bank2];
401}
402
403
wdenk337f5652004-10-28 00:09:35 +0000404/*-----------------------------------------------------------------------
405 */
406int flash_erase (flash_info_t * info, int s_first, int s_last)
407{
408 int flag, prot, sect;
Wolfgang Denk5664f902011-11-04 15:56:00 +0000409 ulong type, start;
wdenk337f5652004-10-28 00:09:35 +0000410 int rcode = 0, intel = 0;
411
412 if ((s_first < 0) || (s_first > s_last)) {
413 if (info->flash_id == FLASH_UNKNOWN)
414 printf ("- missing\n");
415 else
416 printf ("- no sectors to erase\n");
417 return 1;
418 }
419
420 type = (info->flash_id & FLASH_VENDMASK);
421 if ((type != FLASH_MAN_INTEL)) {
422 type = (info->flash_id & FLASH_VENDMASK);
423 if ((type != FLASH_MAN_AMD)) {
424 printf ("Can't erase unknown flash type %08lx - aborted\n",
425 info->flash_id);
426 return 1;
427 }
428 }
429
430 if (type == FLASH_MAN_INTEL)
431 intel = 1;
432
433 prot = 0;
434 for (sect = s_first; sect <= s_last; ++sect) {
435 if (info->protect[sect]) {
436 prot++;
437 }
438 }
439
440 if (prot) {
441 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
442 } else {
443 printf ("\n");
444 }
445
446 start = get_timer (0);
wdenk337f5652004-10-28 00:09:35 +0000447
448 /* Disable interrupts which might cause a timeout here */
449 flag = disable_interrupts ();
450
451 /* Start erase on unprotected sectors */
452 for (sect = s_first; sect <= s_last; sect++) {
453 if (info->protect[sect] == 0) { /* not protected */
454 FPWV *addr = (FPWV *) (info->start[sect]);
455 FPW status;
456
457 printf ("Erasing sector %2d ... ", sect);
458
459 /* arm simple, non interrupt dependent timer */
460 start = get_timer (0);
461
462 if (intel) {
463 *addr = (FPW) 0x00500050; /* clear status register */
464 *addr = (FPW) 0x00200020; /* erase setup */
465 *addr = (FPW) 0x00D000D0; /* erase confirm */
466 } else {
467 FPWV *base; /* first address in bank */
468
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200469 base = (FPWV *) (CONFIG_SYS_AMD_BASE);
wdenk337f5652004-10-28 00:09:35 +0000470 base[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* unlock */
471 base[FLASH_CYCLE2] = (FPW) 0x00550055; /* unlock */
472 base[FLASH_CYCLE1] = (FPW) 0x00800080; /* erase mode */
473 base[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* unlock */
474 base[FLASH_CYCLE2] = (FPW) 0x00550055; /* unlock */
475 *addr = (FPW) 0x00300030; /* erase sector */
476 }
477
478 while (((status =
479 *addr) & (FPW) 0x00800080) !=
480 (FPW) 0x00800080) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200481 if (get_timer (start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenk337f5652004-10-28 00:09:35 +0000482 printf ("Timeout\n");
483 if (intel) {
484 *addr = (FPW) 0x00B000B0; /* suspend erase */
485 *addr = (FPW) 0x00FF00FF; /* reset to read mode */
486 } else
487 *addr = (FPW) 0x00F000F0; /* reset to read mode */
488
489 rcode = 1;
490 break;
491 }
492 }
493
494 if (intel) {
495 *addr = (FPW) 0x00500050; /* clear status register cmd. */
496 *addr = (FPW) 0x00FF00FF; /* resest to read mode */
497 } else
498 *addr = (FPW) 0x00F000F0; /* reset to read mode */
499
500 printf (" done\n");
501 }
502 }
Wolfgang Denk5664f902011-11-04 15:56:00 +0000503 if (flag)
504 enable_interrupts();
505
wdenk337f5652004-10-28 00:09:35 +0000506 return rcode;
507}
508
509/*-----------------------------------------------------------------------
510 * Copy memory to flash, returns:
511 * 0 - OK
512 * 1 - write timeout
513 * 2 - Flash not erased
514 * 4 - Flash not identified
515 */
516
517int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
518{
519 if (info->flash_id == FLASH_UNKNOWN) {
520 return 4;
521 }
522
523 switch (info->flash_id & FLASH_VENDMASK) {
524 case FLASH_MAN_AMD:
525 {
526 FPW data = 0; /* 16 or 32 bit word, matches flash bus width */
527 int bytes; /* number of bytes to program in current word */
528 int left; /* number of bytes left to program */
529 int i, res;
530
531 for (left = cnt, res = 0;
532 left > 0 && res == 0;
533 addr += sizeof (data), left -=
534 sizeof (data) - bytes) {
535
536 bytes = addr & (sizeof (data) - 1);
537 addr &= ~(sizeof (data) - 1);
538
539 /* combine source and destination data so can program
540 * an entire word of 16 or 32 bits
541 */
542 for (i = 0; i < sizeof (data); i++) {
543 data <<= 8;
544 if (i < bytes || i - bytes >= left)
545 data += *((uchar *) addr + i);
546 else
547 data += *src++;
548 }
549
550 res = write_word_amd (info, (FPWV *) addr,
551 data);
552 }
553 return res;
554 } /* case FLASH_MAN_AMD */
555
556 case FLASH_MAN_INTEL:
557 {
558 ulong cp, wp;
559 FPW data;
560 int count, i, l, rc, port_width;
561
562 /* get lower word aligned address */
563 wp = addr;
564 port_width = 1;
565
566 /*
567 * handle unaligned start bytes
568 */
569 if ((l = addr - wp) != 0) {
570 data = 0;
571 for (i = 0, cp = wp; i < l; ++i, ++cp) {
572 data = (data << 8) | (*(uchar *) cp);
573 }
574
575 for (; i < port_width && cnt > 0; ++i) {
576 data = (data << 8) | *src++;
577 --cnt;
578 ++cp;
579 }
580
581 for (; cnt == 0 && i < port_width; ++i, ++cp)
582 data = (data << 8) | (*(uchar *) cp);
583
584 if ((rc =
585 write_data (info, wp, SWAP (data))) != 0)
586 return (rc);
587 wp += port_width;
588 }
589
590 if (cnt > WR_BLOCK) {
591 /*
592 * handle word aligned part
593 */
594 count = 0;
595 while (cnt >= WR_BLOCK) {
596
597 if ((rc =
598 write_data_block (info,
599 (ulong) src,
600 wp)) != 0)
601 return (rc);
602
603 wp += WR_BLOCK;
604 src += WR_BLOCK;
605 cnt -= WR_BLOCK;
606
607 if (count++ > 0x800) {
608 spin_wheel ();
609 count = 0;
610 }
611 }
612 }
613
614 if (cnt < WR_BLOCK) {
615 /*
616 * handle word aligned part
617 */
618 count = 0;
619 while (cnt >= port_width) {
620 data = 0;
621 for (i = 0; i < port_width; ++i)
622 data = (data << 8) | *src++;
623
624 if ((rc =
625 write_data (info, wp,
626 SWAP (data))) != 0)
627 return (rc);
628
629 wp += port_width;
630 cnt -= port_width;
631 if (count++ > 0x800) {
632 spin_wheel ();
633 count = 0;
634 }
635 }
636 }
637
638 if (cnt == 0)
639 return (0);
640
641 /*
642 * handle unaligned tail bytes
643 */
644 data = 0;
645 for (i = 0, cp = wp; i < port_width && cnt > 0;
646 ++i, ++cp) {
647 data = (data << 8) | *src++;
648 --cnt;
649 }
650
651 for (; i < port_width; ++i, ++cp)
652 data = (data << 8) | (*(uchar *) cp);
653
654 return (write_data (info, wp, SWAP (data)));
655 } /* case FLASH_MAN_INTEL */
656
657 } /* switch */
658 return (0);
659}
660
661/*-----------------------------------------------------------------------
662 * Write a word or halfword to Flash, returns:
663 * 0 - OK
664 * 1 - write timeout
665 * 2 - Flash not erased
666 */
667static int write_data (flash_info_t * info, ulong dest, FPW data)
668{
669 FPWV *addr = (FPWV *) dest;
670 ulong start;
Wolfgang Denk5664f902011-11-04 15:56:00 +0000671 int flag, rc = 0;
wdenk337f5652004-10-28 00:09:35 +0000672
673 /* Check if Flash is (sufficiently) erased */
674 if ((*addr & data) != data) {
Wolfgang Denk8d541882008-07-10 13:16:09 +0200675 printf ("not erased at %08lx (%lx)\n", (ulong)addr, (ulong)*addr);
wdenk337f5652004-10-28 00:09:35 +0000676 return (2);
677 }
678 /* Disable interrupts which might cause a timeout here */
679 flag = disable_interrupts ();
680
681 *addr = (FPW) 0x00400040; /* write setup */
682 *addr = data;
683
684 /* arm simple, non interrupt dependent timer */
685 start = get_timer (0);
686
687 /* wait while polling the status register */
688 while ((*addr & (FPW) 0x00800080) != (FPW) 0x00800080) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200689 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
Wolfgang Denk5664f902011-11-04 15:56:00 +0000690 rc = 1;
691 goto OUT;
wdenk337f5652004-10-28 00:09:35 +0000692 }
693 }
694
Wolfgang Denk5664f902011-11-04 15:56:00 +0000695OUT:
696 *addr = (FPW)0x00FF00FF; /* restore read mode */
wdenk337f5652004-10-28 00:09:35 +0000697
Wolfgang Denk5664f902011-11-04 15:56:00 +0000698 if (flag)
699 enable_interrupts();
700
701 return rc;
wdenk337f5652004-10-28 00:09:35 +0000702}
703
704/*-----------------------------------------------------------------------
705 * Write a word or halfword to Flash, returns:
706 * 0 - OK
707 * 1 - write timeout
708 * 2 - Flash not erased
709 */
710static int write_data_block (flash_info_t * info, ulong src, ulong dest)
711{
712 FPWV *srcaddr = (FPWV *) src;
713 FPWV *dstaddr = (FPWV *) dest;
714 ulong start;
Wolfgang Denk5664f902011-11-04 15:56:00 +0000715 int flag, i, rc = 0;
wdenk337f5652004-10-28 00:09:35 +0000716
717 /* Check if Flash is (sufficiently) erased */
718 for (i = 0; i < WR_BLOCK; i++)
719 if ((*dstaddr++ & 0xff) != 0xff) {
720 printf ("not erased at %08lx (%lx)\n",
Wolfgang Denk8d541882008-07-10 13:16:09 +0200721 (ulong)dstaddr, (ulong)*dstaddr);
wdenk337f5652004-10-28 00:09:35 +0000722 return (2);
723 }
724
725 dstaddr = (FPWV *) dest;
726
727 /* Disable interrupts which might cause a timeout here */
728 flag = disable_interrupts ();
729
730 *dstaddr = (FPW) 0x00e800e8; /* write block setup */
731
732 /* arm simple, non interrupt dependent timer */
733 start = get_timer (0);
734
735 /* wait while polling the status register */
Wolfgang Denk5664f902011-11-04 15:56:00 +0000736 while ((*dstaddr & (FPW)0x00800080) != (FPW)0x00800080) {
737 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
738 rc = 1;
739 goto OUT;
wdenk337f5652004-10-28 00:09:35 +0000740 }
741 }
742
743 *dstaddr = (FPW) 0x001f001f; /* write 32 to buffer */
744 for (i = 0; i < WR_BLOCK; i++)
745 *dstaddr++ = *srcaddr++;
746
747 dstaddr -= 1;
748 *dstaddr = (FPW) 0x00d000d0; /* write 32 to buffer */
749
750 /* arm simple, non interrupt dependent timer */
751 start = get_timer (0);
752
753 /* wait while polling the status register */
754 while ((*dstaddr & (FPW) 0x00800080) != (FPW) 0x00800080) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200755 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenk337f5652004-10-28 00:09:35 +0000756 *dstaddr = (FPW) 0x00FF00FF; /* restore read mode */
757 return (1);
758 }
759 }
760
Wolfgang Denk5664f902011-11-04 15:56:00 +0000761OUT:
762 *dstaddr = (FPW)0x00FF00FF; /* restore read mode */
763 if (flag)
764 enable_interrupts();
wdenk337f5652004-10-28 00:09:35 +0000765
Wolfgang Denk5664f902011-11-04 15:56:00 +0000766 return rc;
wdenk337f5652004-10-28 00:09:35 +0000767}
768
769/*-----------------------------------------------------------------------
770 * Write a word to Flash for AMD FLASH
771 * A word is 16 or 32 bits, whichever the bus width of the flash bank
772 * (not an individual chip) is.
773 *
774 * returns:
775 * 0 - OK
776 * 1 - write timeout
777 * 2 - Flash not erased
778 */
779static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data)
780{
781 ulong start;
782 int flag;
783 int res = 0; /* result, assume success */
784 FPWV *base; /* first address in flash bank */
785
786 /* Check if Flash is (sufficiently) erased */
787 if ((*dest & data) != data) {
788 return (2);
789 }
790
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200791 base = (FPWV *) (CONFIG_SYS_AMD_BASE);
wdenk337f5652004-10-28 00:09:35 +0000792
793 /* Disable interrupts which might cause a timeout here */
794 flag = disable_interrupts ();
795
796 base[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* unlock */
797 base[FLASH_CYCLE2] = (FPW) 0x00550055; /* unlock */
798 base[FLASH_CYCLE1] = (FPW) 0x00A000A0; /* selects program mode */
799
800 *dest = data; /* start programming the data */
801
802 /* re-enable interrupts if necessary */
803 if (flag)
804 enable_interrupts ();
805
806 start = get_timer (0);
807
808 /* data polling for D7 */
809 while (res == 0
810 && (*dest & (FPW) 0x00800080) != (data & (FPW) 0x00800080)) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200811 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenk337f5652004-10-28 00:09:35 +0000812 *dest = (FPW) 0x00F000F0; /* reset bank */
813 res = 1;
814 }
815 }
816
817 return (res);
818}
819
820void inline spin_wheel (void)
821{
822 static int p = 0;
823 static char w[] = "\\/-";
824
825 printf ("\010%c", w[p]);
826 (++p == 3) ? (p = 0) : 0;
827}
828
829/*-----------------------------------------------------------------------
830 * Set/Clear sector's lock bit, returns:
831 * 0 - OK
832 * 1 - Error (timeout, voltage problems, etc.)
833 */
834int flash_real_protect (flash_info_t * info, long sector, int prot)
835{
836 ulong start;
Wolfgang Denk862eeeb2005-07-30 16:39:27 +0200837 int i, j;
838 int curr_bank;
839 int bank;
wdenk337f5652004-10-28 00:09:35 +0000840 int rc = 0;
841 FPWV *addr = (FPWV *) (info->start[sector]);
842 int flag = disable_interrupts ();
843
844 /*
845 * 29F040B AMD flash does not support software protection/unprotection,
846 * the only way to protect the AMD flash is marked it as prot bit.
847 * This flash only support hardware protection, by supply or not supply
848 * 12vpp to the flash
849 */
850 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) {
851 info->protect[sector] = prot;
852
853 return 0;
854 }
855
856 *addr = INTEL_CLEAR; /* Clear status register */
857 if (prot) { /* Set sector lock bit */
858 *addr = INTEL_LOCKBIT; /* Sector lock bit */
859 *addr = INTEL_PROTECT; /* set */
860 } else { /* Clear sector lock bit */
861 *addr = INTEL_LOCKBIT; /* All sectors lock bits */
862 *addr = INTEL_CONFIRM; /* clear */
863 }
864
865 start = get_timer (0);
866
867 while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200868 if (get_timer (start) > CONFIG_SYS_FLASH_UNLOCK_TOUT) {
wdenk337f5652004-10-28 00:09:35 +0000869 printf ("Flash lock bit operation timed out\n");
870 rc = 1;
871 break;
872 }
873 }
874
875 if (*addr != INTEL_OK) {
876 printf ("Flash lock bit operation failed at %08X, CSR=%08X\n",
877 (uint) addr, (uint) * addr);
878 rc = 1;
879 }
880
881 if (!rc)
882 info->protect[sector] = prot;
883
884 /*
885 * Clear lock bit command clears all sectors lock bits, so
886 * we have to restore lock bits of protected sectors.
887 */
888 if (!prot) {
Wolfgang Denk862eeeb2005-07-30 16:39:27 +0200889 /*
890 * re-locking must be done for all banks that belong on one
891 * FLASH chip, as all the sectors on the chip were unlocked
892 * by INTEL_LOCKBIT/INTEL_CONFIRM commands. (let's hope
893 * that banks never span chips, in particular chips which
894 * support h/w protection differently).
895 */
896
897 /* find the current bank number */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200898 curr_bank = CONFIG_SYS_MAX_FLASH_BANKS + 1;
899 for (j = 0; j < CONFIG_SYS_MAX_FLASH_BANKS; ++j) {
Wolfgang Denk862eeeb2005-07-30 16:39:27 +0200900 if (&flash_info[j] == info) {
901 curr_bank = j;
902 }
903 }
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200904 if (curr_bank == CONFIG_SYS_MAX_FLASH_BANKS + 1) {
Wolfgang Denk862eeeb2005-07-30 16:39:27 +0200905 printf("Error: can't determine bank number!\n");
906 }
907
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200908 for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
Wolfgang Denk862eeeb2005-07-30 16:39:27 +0200909 if (!same_chip_banks(curr_bank, bank)) {
910 continue;
911 }
912 info = &flash_info[bank];
913 for (i = 0; i < info->sector_count; i++) {
914 if (info->protect[i]) {
915 start = get_timer (0);
916 addr = (FPWV *) (info->start[i]);
917 *addr = INTEL_LOCKBIT; /* Sector lock bit */
918 *addr = INTEL_PROTECT; /* set */
919 while ((*addr & INTEL_FINISHED) !=
920 INTEL_FINISHED) {
921 if (get_timer (start) >
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200922 CONFIG_SYS_FLASH_UNLOCK_TOUT) {
Wolfgang Denk862eeeb2005-07-30 16:39:27 +0200923 printf ("Flash lock bit operation timed out\n");
924 rc = 1;
925 break;
926 }
wdenk337f5652004-10-28 00:09:35 +0000927 }
928 }
929 }
930 }
Wolfgang Denk862eeeb2005-07-30 16:39:27 +0200931
932 /*
933 * get the s/w sector protection status in sync with the h/w,
934 * in case something went wrong during the re-locking.
935 */
936 flash_sync_real_protect(info); /* resets flash to read mode */
wdenk337f5652004-10-28 00:09:35 +0000937 }
938
939 if (flag)
940 enable_interrupts ();
941
942 *addr = INTEL_RESET; /* Reset to read array mode */
943
944 return rc;
945}