blob: aed3b6f59c9711b40287050c4b9864c02e5f94da [file] [log] [blame]
wdenk983fda82004-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-VILLARD6d0f6bc2008-10-16 15:01:15 +020031flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
wdenk983fda82004-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
wdenk983fda82004-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 Denk010162e2005-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);
wdenk983fda82004-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-VILLARD6d0f6bc2008-10-16 15:01:15 +020089 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
wdenk983fda82004-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-VILLARD6d0f6bc2008-10-16 15:01:15 +020094 flash_get_size ((FPW *) CONFIG_SYS_FLASH1_BASE,
wdenk983fda82004-10-28 00:09:35 +000095 &flash_info[i]);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020096 flash_get_offsets (CONFIG_SYS_FLASH1_BASE, &flash_info[i]);
wdenk983fda82004-10-28 00:09:35 +000097 break;
98 case 1:
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020099 flash_get_size ((FPW *) CONFIG_SYS_FLASH1_BASE,
wdenk983fda82004-10-28 00:09:35 +0000100 &flash_info[i]);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200101 fsize = CONFIG_SYS_FLASH1_BASE + flash_info[i - 1].size;
wdenk983fda82004-10-28 00:09:35 +0000102 flash_get_offsets (fsize, &flash_info[i]);
103 break;
104 case 2:
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200105 flash_get_size ((FPW *) CONFIG_SYS_FLASH0_BASE,
wdenk983fda82004-10-28 00:09:35 +0000106 &flash_info[i]);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200107 flash_get_offsets (CONFIG_SYS_FLASH0_BASE, &flash_info[i]);
wdenk983fda82004-10-28 00:09:35 +0000108 break;
109 case 3:
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200110 flash_get_size ((FPW *) CONFIG_SYS_FLASH0_BASE,
wdenk983fda82004-10-28 00:09:35 +0000111 &flash_info[i]);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200112 fsize = CONFIG_SYS_FLASH0_BASE + flash_info[i - 1].size;
wdenk983fda82004-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 Denk010162e2005-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]);
wdenk983fda82004-10-28 00:09:35 +0000123 }
124
125 /* Protect monitor and environment sectors
126 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200127#if defined (CONFIG_SYS_AMD_BOOT)
wdenk983fda82004-10-28 00:09:35 +0000128 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200129 CONFIG_SYS_MONITOR_BASE,
130 CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
wdenk983fda82004-10-28 00:09:35 +0000131 &flash_info[2]);
132 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200133 CONFIG_SYS_INTEL_BASE,
134 CONFIG_SYS_INTEL_BASE + monitor_flash_len - 1,
wdenk983fda82004-10-28 00:09:35 +0000135 &flash_info[1]);
136#else
137 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200138 CONFIG_SYS_MONITOR_BASE,
139 CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
wdenk983fda82004-10-28 00:09:35 +0000140 &flash_info[3]);
141 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200142 CONFIG_SYS_AMD_BASE,
143 CONFIG_SYS_AMD_BASE + monitor_flash_len - 1, &flash_info[0]);
wdenk983fda82004-10-28 00:09:35 +0000144#endif
145
146 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +0200147 CONFIG_ENV1_ADDR,
148 CONFIG_ENV1_ADDR + CONFIG_ENV1_SIZE - 1, &flash_info[1]);
wdenk983fda82004-10-28 00:09:35 +0000149 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +0200150 CONFIG_ENV_ADDR,
151 CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[3]);
wdenk983fda82004-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);
wdenk983fda82004-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-VILLARD6d0f6bc2008-10-16 15:01:15 +0200297 if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
wdenk983fda82004-10-28 00:09:35 +0000298 printf ("** ERROR: sector count %d > max (%d) **\n",
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200299 info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
300 info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
wdenk983fda82004-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 Denk010162e2005-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-VILLARD6d0f6bc2008-10-16 15:01:15 +0200351 * CONFIG_SYS_FLASH_ERASE_TOUT is as follows. The WSM can be busy
Wolfgang Denk010162e2005-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-VILLARD6d0f6bc2008-10-16 15:01:15 +0200364 if (get_timer (start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
Wolfgang Denk010162e2005-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-VILLARD6d0f6bc2008-10-16 15:01:15 +0200394 unsigned char same_chip[CONFIG_SYS_MAX_FLASH_BANKS][CONFIG_SYS_MAX_FLASH_BANKS] = {
Wolfgang Denk010162e2005-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
wdenk983fda82004-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;
409 ulong type, start, last;
410 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);
447 last = start;
448
449 /* Disable interrupts which might cause a timeout here */
450 flag = disable_interrupts ();
451
452 /* Start erase on unprotected sectors */
453 for (sect = s_first; sect <= s_last; sect++) {
454 if (info->protect[sect] == 0) { /* not protected */
455 FPWV *addr = (FPWV *) (info->start[sect]);
456 FPW status;
457
458 printf ("Erasing sector %2d ... ", sect);
459
460 /* arm simple, non interrupt dependent timer */
461 start = get_timer (0);
462
463 if (intel) {
464 *addr = (FPW) 0x00500050; /* clear status register */
465 *addr = (FPW) 0x00200020; /* erase setup */
466 *addr = (FPW) 0x00D000D0; /* erase confirm */
467 } else {
468 FPWV *base; /* first address in bank */
469
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200470 base = (FPWV *) (CONFIG_SYS_AMD_BASE);
wdenk983fda82004-10-28 00:09:35 +0000471 base[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* unlock */
472 base[FLASH_CYCLE2] = (FPW) 0x00550055; /* unlock */
473 base[FLASH_CYCLE1] = (FPW) 0x00800080; /* erase mode */
474 base[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* unlock */
475 base[FLASH_CYCLE2] = (FPW) 0x00550055; /* unlock */
476 *addr = (FPW) 0x00300030; /* erase sector */
477 }
478
479 while (((status =
480 *addr) & (FPW) 0x00800080) !=
481 (FPW) 0x00800080) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200482 if (get_timer (start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenk983fda82004-10-28 00:09:35 +0000483 printf ("Timeout\n");
484 if (intel) {
485 *addr = (FPW) 0x00B000B0; /* suspend erase */
486 *addr = (FPW) 0x00FF00FF; /* reset to read mode */
487 } else
488 *addr = (FPW) 0x00F000F0; /* reset to read mode */
489
490 rcode = 1;
491 break;
492 }
493 }
494
495 if (intel) {
496 *addr = (FPW) 0x00500050; /* clear status register cmd. */
497 *addr = (FPW) 0x00FF00FF; /* resest to read mode */
498 } else
499 *addr = (FPW) 0x00F000F0; /* reset to read mode */
500
501 printf (" done\n");
502 }
503 }
504 return rcode;
505}
506
507/*-----------------------------------------------------------------------
508 * Copy memory to flash, returns:
509 * 0 - OK
510 * 1 - write timeout
511 * 2 - Flash not erased
512 * 4 - Flash not identified
513 */
514
515int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
516{
517 if (info->flash_id == FLASH_UNKNOWN) {
518 return 4;
519 }
520
521 switch (info->flash_id & FLASH_VENDMASK) {
522 case FLASH_MAN_AMD:
523 {
524 FPW data = 0; /* 16 or 32 bit word, matches flash bus width */
525 int bytes; /* number of bytes to program in current word */
526 int left; /* number of bytes left to program */
527 int i, res;
528
529 for (left = cnt, res = 0;
530 left > 0 && res == 0;
531 addr += sizeof (data), left -=
532 sizeof (data) - bytes) {
533
534 bytes = addr & (sizeof (data) - 1);
535 addr &= ~(sizeof (data) - 1);
536
537 /* combine source and destination data so can program
538 * an entire word of 16 or 32 bits
539 */
540 for (i = 0; i < sizeof (data); i++) {
541 data <<= 8;
542 if (i < bytes || i - bytes >= left)
543 data += *((uchar *) addr + i);
544 else
545 data += *src++;
546 }
547
548 res = write_word_amd (info, (FPWV *) addr,
549 data);
550 }
551 return res;
552 } /* case FLASH_MAN_AMD */
553
554 case FLASH_MAN_INTEL:
555 {
556 ulong cp, wp;
557 FPW data;
558 int count, i, l, rc, port_width;
559
560 /* get lower word aligned address */
561 wp = addr;
562 port_width = 1;
563
564 /*
565 * handle unaligned start bytes
566 */
567 if ((l = addr - wp) != 0) {
568 data = 0;
569 for (i = 0, cp = wp; i < l; ++i, ++cp) {
570 data = (data << 8) | (*(uchar *) cp);
571 }
572
573 for (; i < port_width && cnt > 0; ++i) {
574 data = (data << 8) | *src++;
575 --cnt;
576 ++cp;
577 }
578
579 for (; cnt == 0 && i < port_width; ++i, ++cp)
580 data = (data << 8) | (*(uchar *) cp);
581
582 if ((rc =
583 write_data (info, wp, SWAP (data))) != 0)
584 return (rc);
585 wp += port_width;
586 }
587
588 if (cnt > WR_BLOCK) {
589 /*
590 * handle word aligned part
591 */
592 count = 0;
593 while (cnt >= WR_BLOCK) {
594
595 if ((rc =
596 write_data_block (info,
597 (ulong) src,
598 wp)) != 0)
599 return (rc);
600
601 wp += WR_BLOCK;
602 src += WR_BLOCK;
603 cnt -= WR_BLOCK;
604
605 if (count++ > 0x800) {
606 spin_wheel ();
607 count = 0;
608 }
609 }
610 }
611
612 if (cnt < WR_BLOCK) {
613 /*
614 * handle word aligned part
615 */
616 count = 0;
617 while (cnt >= port_width) {
618 data = 0;
619 for (i = 0; i < port_width; ++i)
620 data = (data << 8) | *src++;
621
622 if ((rc =
623 write_data (info, wp,
624 SWAP (data))) != 0)
625 return (rc);
626
627 wp += port_width;
628 cnt -= port_width;
629 if (count++ > 0x800) {
630 spin_wheel ();
631 count = 0;
632 }
633 }
634 }
635
636 if (cnt == 0)
637 return (0);
638
639 /*
640 * handle unaligned tail bytes
641 */
642 data = 0;
643 for (i = 0, cp = wp; i < port_width && cnt > 0;
644 ++i, ++cp) {
645 data = (data << 8) | *src++;
646 --cnt;
647 }
648
649 for (; i < port_width; ++i, ++cp)
650 data = (data << 8) | (*(uchar *) cp);
651
652 return (write_data (info, wp, SWAP (data)));
653 } /* case FLASH_MAN_INTEL */
654
655 } /* switch */
656 return (0);
657}
658
659/*-----------------------------------------------------------------------
660 * Write a word or halfword to Flash, returns:
661 * 0 - OK
662 * 1 - write timeout
663 * 2 - Flash not erased
664 */
665static int write_data (flash_info_t * info, ulong dest, FPW data)
666{
667 FPWV *addr = (FPWV *) dest;
668 ulong start;
669 int flag;
670
671 /* Check if Flash is (sufficiently) erased */
672 if ((*addr & data) != data) {
Wolfgang Denk06c53be2008-07-10 13:16:09 +0200673 printf ("not erased at %08lx (%lx)\n", (ulong)addr, (ulong)*addr);
wdenk983fda82004-10-28 00:09:35 +0000674 return (2);
675 }
676 /* Disable interrupts which might cause a timeout here */
677 flag = disable_interrupts ();
678
679 *addr = (FPW) 0x00400040; /* write setup */
680 *addr = data;
681
682 /* arm simple, non interrupt dependent timer */
683 start = get_timer (0);
684
685 /* wait while polling the status register */
686 while ((*addr & (FPW) 0x00800080) != (FPW) 0x00800080) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200687 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenk983fda82004-10-28 00:09:35 +0000688 *addr = (FPW) 0x00FF00FF; /* restore read mode */
689 return (1);
690 }
691 }
692
693 *addr = (FPW) 0x00FF00FF; /* restore read mode */
694
695 return (0);
696}
697
698/*-----------------------------------------------------------------------
699 * Write a word or halfword to Flash, returns:
700 * 0 - OK
701 * 1 - write timeout
702 * 2 - Flash not erased
703 */
704static int write_data_block (flash_info_t * info, ulong src, ulong dest)
705{
706 FPWV *srcaddr = (FPWV *) src;
707 FPWV *dstaddr = (FPWV *) dest;
708 ulong start;
709 int flag, i;
710
711 /* Check if Flash is (sufficiently) erased */
712 for (i = 0; i < WR_BLOCK; i++)
713 if ((*dstaddr++ & 0xff) != 0xff) {
714 printf ("not erased at %08lx (%lx)\n",
Wolfgang Denk06c53be2008-07-10 13:16:09 +0200715 (ulong)dstaddr, (ulong)*dstaddr);
wdenk983fda82004-10-28 00:09:35 +0000716 return (2);
717 }
718
719 dstaddr = (FPWV *) dest;
720
721 /* Disable interrupts which might cause a timeout here */
722 flag = disable_interrupts ();
723
724 *dstaddr = (FPW) 0x00e800e8; /* write block setup */
725
726 /* arm simple, non interrupt dependent timer */
727 start = get_timer (0);
728
729 /* wait while polling the status register */
730 while ((*dstaddr & (FPW) 0x00800080) != (FPW) 0x00800080) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200731 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenk983fda82004-10-28 00:09:35 +0000732 *dstaddr = (FPW) 0x00FF00FF; /* restore read mode */
733 return (1);
734 }
735 }
736
737 *dstaddr = (FPW) 0x001f001f; /* write 32 to buffer */
738 for (i = 0; i < WR_BLOCK; i++)
739 *dstaddr++ = *srcaddr++;
740
741 dstaddr -= 1;
742 *dstaddr = (FPW) 0x00d000d0; /* write 32 to buffer */
743
744 /* arm simple, non interrupt dependent timer */
745 start = get_timer (0);
746
747 /* wait while polling the status register */
748 while ((*dstaddr & (FPW) 0x00800080) != (FPW) 0x00800080) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200749 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenk983fda82004-10-28 00:09:35 +0000750 *dstaddr = (FPW) 0x00FF00FF; /* restore read mode */
751 return (1);
752 }
753 }
754
755 *dstaddr = (FPW) 0x00FF00FF; /* restore read mode */
756
757 return (0);
758}
759
760/*-----------------------------------------------------------------------
761 * Write a word to Flash for AMD FLASH
762 * A word is 16 or 32 bits, whichever the bus width of the flash bank
763 * (not an individual chip) is.
764 *
765 * returns:
766 * 0 - OK
767 * 1 - write timeout
768 * 2 - Flash not erased
769 */
770static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data)
771{
772 ulong start;
773 int flag;
774 int res = 0; /* result, assume success */
775 FPWV *base; /* first address in flash bank */
776
777 /* Check if Flash is (sufficiently) erased */
778 if ((*dest & data) != data) {
779 return (2);
780 }
781
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200782 base = (FPWV *) (CONFIG_SYS_AMD_BASE);
wdenk983fda82004-10-28 00:09:35 +0000783
784 /* Disable interrupts which might cause a timeout here */
785 flag = disable_interrupts ();
786
787 base[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* unlock */
788 base[FLASH_CYCLE2] = (FPW) 0x00550055; /* unlock */
789 base[FLASH_CYCLE1] = (FPW) 0x00A000A0; /* selects program mode */
790
791 *dest = data; /* start programming the data */
792
793 /* re-enable interrupts if necessary */
794 if (flag)
795 enable_interrupts ();
796
797 start = get_timer (0);
798
799 /* data polling for D7 */
800 while (res == 0
801 && (*dest & (FPW) 0x00800080) != (data & (FPW) 0x00800080)) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200802 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenk983fda82004-10-28 00:09:35 +0000803 *dest = (FPW) 0x00F000F0; /* reset bank */
804 res = 1;
805 }
806 }
807
808 return (res);
809}
810
811void inline spin_wheel (void)
812{
813 static int p = 0;
814 static char w[] = "\\/-";
815
816 printf ("\010%c", w[p]);
817 (++p == 3) ? (p = 0) : 0;
818}
819
820/*-----------------------------------------------------------------------
821 * Set/Clear sector's lock bit, returns:
822 * 0 - OK
823 * 1 - Error (timeout, voltage problems, etc.)
824 */
825int flash_real_protect (flash_info_t * info, long sector, int prot)
826{
827 ulong start;
Wolfgang Denk010162e2005-07-30 16:39:27 +0200828 int i, j;
829 int curr_bank;
830 int bank;
wdenk983fda82004-10-28 00:09:35 +0000831 int rc = 0;
832 FPWV *addr = (FPWV *) (info->start[sector]);
833 int flag = disable_interrupts ();
834
835 /*
836 * 29F040B AMD flash does not support software protection/unprotection,
837 * the only way to protect the AMD flash is marked it as prot bit.
838 * This flash only support hardware protection, by supply or not supply
839 * 12vpp to the flash
840 */
841 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) {
842 info->protect[sector] = prot;
843
844 return 0;
845 }
846
847 *addr = INTEL_CLEAR; /* Clear status register */
848 if (prot) { /* Set sector lock bit */
849 *addr = INTEL_LOCKBIT; /* Sector lock bit */
850 *addr = INTEL_PROTECT; /* set */
851 } else { /* Clear sector lock bit */
852 *addr = INTEL_LOCKBIT; /* All sectors lock bits */
853 *addr = INTEL_CONFIRM; /* clear */
854 }
855
856 start = get_timer (0);
857
858 while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200859 if (get_timer (start) > CONFIG_SYS_FLASH_UNLOCK_TOUT) {
wdenk983fda82004-10-28 00:09:35 +0000860 printf ("Flash lock bit operation timed out\n");
861 rc = 1;
862 break;
863 }
864 }
865
866 if (*addr != INTEL_OK) {
867 printf ("Flash lock bit operation failed at %08X, CSR=%08X\n",
868 (uint) addr, (uint) * addr);
869 rc = 1;
870 }
871
872 if (!rc)
873 info->protect[sector] = prot;
874
875 /*
876 * Clear lock bit command clears all sectors lock bits, so
877 * we have to restore lock bits of protected sectors.
878 */
879 if (!prot) {
Wolfgang Denk010162e2005-07-30 16:39:27 +0200880 /*
881 * re-locking must be done for all banks that belong on one
882 * FLASH chip, as all the sectors on the chip were unlocked
883 * by INTEL_LOCKBIT/INTEL_CONFIRM commands. (let's hope
884 * that banks never span chips, in particular chips which
885 * support h/w protection differently).
886 */
887
888 /* find the current bank number */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200889 curr_bank = CONFIG_SYS_MAX_FLASH_BANKS + 1;
890 for (j = 0; j < CONFIG_SYS_MAX_FLASH_BANKS; ++j) {
Wolfgang Denk010162e2005-07-30 16:39:27 +0200891 if (&flash_info[j] == info) {
892 curr_bank = j;
893 }
894 }
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200895 if (curr_bank == CONFIG_SYS_MAX_FLASH_BANKS + 1) {
Wolfgang Denk010162e2005-07-30 16:39:27 +0200896 printf("Error: can't determine bank number!\n");
897 }
898
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200899 for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
Wolfgang Denk010162e2005-07-30 16:39:27 +0200900 if (!same_chip_banks(curr_bank, bank)) {
901 continue;
902 }
903 info = &flash_info[bank];
904 for (i = 0; i < info->sector_count; i++) {
905 if (info->protect[i]) {
906 start = get_timer (0);
907 addr = (FPWV *) (info->start[i]);
908 *addr = INTEL_LOCKBIT; /* Sector lock bit */
909 *addr = INTEL_PROTECT; /* set */
910 while ((*addr & INTEL_FINISHED) !=
911 INTEL_FINISHED) {
912 if (get_timer (start) >
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200913 CONFIG_SYS_FLASH_UNLOCK_TOUT) {
Wolfgang Denk010162e2005-07-30 16:39:27 +0200914 printf ("Flash lock bit operation timed out\n");
915 rc = 1;
916 break;
917 }
wdenk983fda82004-10-28 00:09:35 +0000918 }
919 }
920 }
921 }
Wolfgang Denk010162e2005-07-30 16:39:27 +0200922
923 /*
924 * get the s/w sector protection status in sync with the h/w,
925 * in case something went wrong during the re-locking.
926 */
927 flash_sync_real_protect(info); /* resets flash to read mode */
wdenk983fda82004-10-28 00:09:35 +0000928 }
929
930 if (flag)
931 enable_interrupts ();
932
933 *addr = INTEL_RESET; /* Reset to read array mode */
934
935 return rc;
936}