blob: 62700f9f9f903c82b5ed3be5888f6fe12985c006 [file] [log] [blame]
wdenkefa329c2004-03-23 20:18:25 +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
31flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
32
33/* Board support for 1 or 2 flash devices */
34#define FLASH_PORT_WIDTH32
35#undef FLASH_PORT_WIDTH16
36
37#ifdef FLASH_PORT_WIDTH16
38#define FLASH_PORT_WIDTH ushort
39#define FLASH_PORT_WIDTHV vu_short
40#define SWAP(x) (x)
41#else
42#define FLASH_PORT_WIDTH ulong
43#define FLASH_PORT_WIDTHV vu_long
44#define SWAP(x) (x)
45#endif
46
47/* Intel-compatible flash ID */
48#define INTEL_COMPAT 0x00890089
49#define INTEL_ALT 0x00B000B0
50
51/* Intel-compatible flash commands */
52#define INTEL_PROGRAM 0x00100010
53#define INTEL_ERASE 0x00200020
54#define INTEL_CLEAR 0x00500050
55#define INTEL_LOCKBIT 0x00600060
56#define INTEL_PROTECT 0x00010001
57#define INTEL_STATUS 0x00700070
58#define INTEL_READID 0x00900090
59#define INTEL_CONFIRM 0x00D000D0
60#define INTEL_RESET 0xFFFFFFFF
61
62/* Intel-compatible flash status bits */
63#define INTEL_FINISHED 0x00800080
64#define INTEL_OK 0x00800080
65
66#define FPW FLASH_PORT_WIDTH
67#define FPWV FLASH_PORT_WIDTHV
68
69#define mb() __asm__ __volatile__ ("" : : : "memory")
70
71/*-----------------------------------------------------------------------
72 * Functions
73 */
74static ulong flash_get_size (FPW *addr, flash_info_t *info);
75static int write_data (flash_info_t *info, ulong dest, FPW data);
76static void flash_get_offsets (ulong base, flash_info_t *info);
77void inline spin_wheel (void);
Wolfgang Denk010162e2005-07-30 16:39:27 +020078static void flash_sync_real_protect (flash_info_t * info);
79static unsigned char intel_sector_protected (flash_info_t *info, ushort sector);
wdenkefa329c2004-03-23 20:18:25 +000080
81/*-----------------------------------------------------------------------
82 */
83
84unsigned long flash_init (void)
85{
86 int i;
87 ulong size = 0;
wdenk49822e22004-06-19 21:19:10 +000088 extern void flash_preinit(void);
89 extern void flash_afterinit(ulong, ulong);
90 ulong flashbase = CFG_FLASH_BASE;
91
92 flash_preinit();
wdenkefa329c2004-03-23 20:18:25 +000093
94 for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
95 switch (i) {
96 case 0:
wdenk49822e22004-06-19 21:19:10 +000097 memset(&flash_info[i], 0, sizeof(flash_info_t));
98 flash_get_size ((FPW *) flashbase, &flash_info[i]);
99 flash_get_offsets (flash_info[i].start[0], &flash_info[i]);
wdenkefa329c2004-03-23 20:18:25 +0000100 break;
101 default:
102 panic ("configured to many flash banks!\n");
103 break;
104 }
105 size += flash_info[i].size;
Wolfgang Denk010162e2005-07-30 16:39:27 +0200106
107 /* get the h/w and s/w protection status in sync */
108 flash_sync_real_protect(&flash_info[i]);
wdenkefa329c2004-03-23 20:18:25 +0000109 }
110
111 /* Protect monitor and environment sectors
112 */
wdenk49822e22004-06-19 21:19:10 +0000113#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
114#ifndef CONFIG_BOOT_ROM
wdenkefa329c2004-03-23 20:18:25 +0000115 flash_protect ( FLAG_PROTECT_SET,
116 CFG_MONITOR_BASE,
117 CFG_MONITOR_BASE + monitor_flash_len - 1,
118 &flash_info[0] );
wdenk49822e22004-06-19 21:19:10 +0000119#endif
120#endif
wdenkefa329c2004-03-23 20:18:25 +0000121
wdenk49822e22004-06-19 21:19:10 +0000122#ifdef CFG_ENV_IS_IN_FLASH
wdenkefa329c2004-03-23 20:18:25 +0000123 flash_protect ( FLAG_PROTECT_SET,
124 CFG_ENV_ADDR,
125 CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0] );
wdenk49822e22004-06-19 21:19:10 +0000126#endif
127
128 flash_afterinit(flash_info[0].start[0], flash_info[0].size);
wdenkefa329c2004-03-23 20:18:25 +0000129
130 return size;
131}
132
133/*-----------------------------------------------------------------------
134 */
135static void flash_get_offsets (ulong base, flash_info_t *info)
136{
137 int i;
138
139 if (info->flash_id == FLASH_UNKNOWN) {
140 return;
141 }
142
143 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
144 for (i = 0; i < info->sector_count; i++) {
145 info->start[i] = base + (i * PHYS_FLASH_SECT_SIZE);
wdenkefa329c2004-03-23 20:18:25 +0000146 }
147 }
148}
149
150/*-----------------------------------------------------------------------
151 */
152void flash_print_info (flash_info_t *info)
153{
154 int i;
155
156 if (info->flash_id == FLASH_UNKNOWN) {
157 printf ("missing or unknown FLASH type\n");
158 return;
159 }
160
161 switch (info->flash_id & FLASH_VENDMASK) {
162 case FLASH_MAN_INTEL:
163 printf ("INTEL ");
164 break;
165 default:
166 printf ("Unknown Vendor ");
167 break;
168 }
169
170 switch (info->flash_id & FLASH_TYPEMASK) {
171 case FLASH_28F128J3A:
172 printf ("28F128J3A\n");
173 break;
174
175 case FLASH_28F640J3A:
176 printf ("28F640J3A\n");
177 break;
178
179 case FLASH_28F320J3A:
180 printf ("28F320J3A\n");
181 break;
182
183 default:
184 printf ("Unknown Chip Type\n");
185 break;
186 }
187
188 printf (" Size: %ld MB in %d Sectors\n",
189 info->size >> 20, info->sector_count);
190
191 printf (" Sector Start Addresses:");
192 for (i = 0; i < info->sector_count; ++i) {
193 if ((i % 5) == 0)
194 printf ("\n ");
195 printf (" %08lX%s",
196 info->start[i],
197 info->protect[i] ? " (RO)" : " ");
198 }
199 printf ("\n");
200 return;
201}
202
203/*
204 * The following code cannot be run from FLASH!
205 */
206static ulong flash_get_size (FPW *addr, flash_info_t *info)
207{
208 volatile FPW value;
209
210 /* Write auto select command: read Manufacturer ID */
211 addr[0x5555] = (FPW) 0x00AA00AA;
212 addr[0x2AAA] = (FPW) 0x00550055;
213 addr[0x5555] = (FPW) 0x00900090;
214
215 mb ();
wdenk49822e22004-06-19 21:19:10 +0000216 udelay(100);
217
wdenkefa329c2004-03-23 20:18:25 +0000218 value = addr[0];
219
220 switch (value) {
221
222 case (FPW) INTEL_MANUFACT:
223 info->flash_id = FLASH_MAN_INTEL;
224 break;
225
226 default:
227 info->flash_id = FLASH_UNKNOWN;
228 info->sector_count = 0;
229 info->size = 0;
230 addr[0] = (FPW) 0x00FF00FF; /* restore read mode */
231 return (0); /* no or unknown flash */
232 }
233
234 mb ();
235 value = addr[1]; /* device ID */
236
237 switch (value) {
238
239 case (FPW) INTEL_ID_28F128J3A:
240 info->flash_id += FLASH_28F128J3A;
241 info->sector_count = 128;
242 info->size = 0x02000000;
wdenk49822e22004-06-19 21:19:10 +0000243 info->start[0] = CFG_FLASH_BASE;
wdenkefa329c2004-03-23 20:18:25 +0000244 break; /* => 32 MB */
245
246 case (FPW) INTEL_ID_28F640J3A:
247 info->flash_id += FLASH_28F640J3A;
248 info->sector_count = 64;
249 info->size = 0x01000000;
wdenk49822e22004-06-19 21:19:10 +0000250 info->start[0] = CFG_FLASH_BASE + 0x01000000;
wdenkefa329c2004-03-23 20:18:25 +0000251 break; /* => 16 MB */
252
253 case (FPW) INTEL_ID_28F320J3A:
254 info->flash_id += FLASH_28F320J3A;
255 info->sector_count = 32;
wdenk49822e22004-06-19 21:19:10 +0000256 info->size = 0x800000;
257 info->start[0] = CFG_FLASH_BASE + 0x01800000;
wdenkefa329c2004-03-23 20:18:25 +0000258 break; /* => 8 MB */
259
260 default:
261 info->flash_id = FLASH_UNKNOWN;
262 break;
263 }
264
265 if (info->sector_count > CFG_MAX_FLASH_SECT) {
266 printf ("** ERROR: sector count %d > max (%d) **\n",
267 info->sector_count, CFG_MAX_FLASH_SECT);
268 info->sector_count = CFG_MAX_FLASH_SECT;
269 }
270
271 addr[0] = (FPW) 0x00FF00FF; /* restore read mode */
272
273 return (info->size);
274}
275
276
Wolfgang Denk010162e2005-07-30 16:39:27 +0200277/*
278 * This function gets the u-boot flash sector protection status
279 * (flash_info_t.protect[]) in sync with the sector protection
280 * status stored in hardware.
281 */
282static void flash_sync_real_protect (flash_info_t * info)
283{
284 int i;
285
286 switch (info->flash_id & FLASH_TYPEMASK) {
287
288 case FLASH_28F128J3A:
289 case FLASH_28F640J3A:
290 case FLASH_28F320J3A:
291 for (i = 0; i < info->sector_count; ++i) {
292 info->protect[i] = intel_sector_protected(info, i);
293 }
294 break;
295 default:
296 /* no h/w protect support */
297 break;
298 }
299}
300
301
302/*
303 * checks if "sector" in bank "info" is protected. Should work on intel
304 * strata flash chips 28FxxxJ3x in 8-bit mode.
305 * Returns 1 if sector is protected (or timed-out while trying to read
306 * protection status), 0 if it is not.
307 */
308static unsigned char intel_sector_protected (flash_info_t *info, ushort sector)
309{
310 FPWV *addr;
311 FPWV *lock_conf_addr;
312 ulong start;
313 unsigned char ret;
314
315 /*
316 * first, wait for the WSM to be finished. The rationale for
317 * waiting for the WSM to become idle for at most
318 * CFG_FLASH_ERASE_TOUT is as follows. The WSM can be busy
319 * because of: (1) erase, (2) program or (3) lock bit
320 * configuration. So we just wait for the longest timeout of
321 * the (1)-(3), i.e. the erase timeout.
322 */
323
324 /* wait at least 35ns (W12) before issuing Read Status Register */
325 udelay(1);
326 addr = (FPWV *) info->start[sector];
327 *addr = (FPW) INTEL_STATUS;
328
329 start = get_timer (0);
330 while ((*addr & (FPW) INTEL_FINISHED) != (FPW) INTEL_FINISHED) {
331 if (get_timer (start) > CFG_FLASH_ERASE_TOUT) {
332 *addr = (FPW) INTEL_RESET; /* restore read mode */
333 printf("WSM busy too long, can't get prot status\n");
334 return 1;
335 }
336 }
337
338 /* issue the Read Identifier Codes command */
339 *addr = (FPW) INTEL_READID;
340
341 /* wait at least 35ns (W12) before reading */
342 udelay(1);
343
344 /* Intel example code uses offset of 2 for 16 bit flash */
345 lock_conf_addr = (FPWV *) info->start[sector] + 2;
346 ret = (*lock_conf_addr & (FPW) INTEL_PROTECT) ? 1 : 0;
347
348 /* put flash back in read mode */
349 *addr = (FPW) INTEL_RESET;
350
351 return ret;
352}
353
354
355
wdenkefa329c2004-03-23 20:18:25 +0000356/*-----------------------------------------------------------------------
357 */
358
359int flash_erase (flash_info_t *info, int s_first, int s_last)
360{
361 int flag, prot, sect;
362 ulong type, start, last;
363 int rcode = 0;
364
365 if ((s_first < 0) || (s_first > s_last)) {
366 if (info->flash_id == FLASH_UNKNOWN) {
367 printf ("- missing\n");
368 } else {
369 printf ("- no sectors to erase\n");
370 }
371 return 1;
372 }
373
374 type = (info->flash_id & FLASH_VENDMASK);
375 if ((type != FLASH_MAN_INTEL)) {
376 printf ("Can't erase unknown flash type %08lx - aborted\n",
377 info->flash_id);
378 return 1;
379 }
380
381 prot = 0;
382 for (sect = s_first; sect <= s_last; ++sect) {
383 if (info->protect[sect]) {
384 prot++;
385 }
386 }
387
388 if (prot) {
389 printf ("- Warning: %d protected sectors will not be erased!\n",
390 prot);
391 } else {
392 printf ("\n");
393 }
394
395 start = get_timer (0);
396 last = start;
397
398 /* Disable interrupts which might cause a timeout here */
399 flag = disable_interrupts ();
400
401 /* Start erase on unprotected sectors */
402 for (sect = s_first; sect <= s_last; sect++) {
403 if (info->protect[sect] == 0) { /* not protected */
404 FPWV *addr = (FPWV *) (info->start[sect]);
405 FPW status;
406
407 printf ("Erasing sector %2d ... ", sect);
408
409 /* arm simple, non interrupt dependent timer */
410 start = get_timer(0);
411
412 *addr = (FPW) 0x00500050; /* clear status register */
413 *addr = (FPW) 0x00200020; /* erase setup */
414 *addr = (FPW) 0x00D000D0; /* erase confirm */
415
416 while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) {
417 if (get_timer(start) > CFG_FLASH_ERASE_TOUT) {
418 printf ("Timeout\n");
419 *addr = (FPW) 0x00B000B0; /* suspend erase */
420 *addr = (FPW) 0x00FF00FF; /* reset to read mode */
421 rcode = 1;
422 break;
423 }
424 }
425
426 *addr = 0x00500050; /* clear status register cmd. */
427 *addr = 0x00FF00FF; /* resest to read mode */
428
429 printf (" done\n");
430 }
431 }
432 return rcode;
433}
434
435/*-----------------------------------------------------------------------
436 * Copy memory to flash, returns:
437 * 0 - OK
438 * 1 - write timeout
439 * 2 - Flash not erased
440 * 4 - Flash not identified
441 */
442
443int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
444{
445 ulong cp, wp;
446 FPW data;
447 int count, i, l, rc, port_width;
448
449 if (info->flash_id == FLASH_UNKNOWN) {
450 return 4;
451 }
452/* get lower word aligned address */
453#ifdef FLASH_PORT_WIDTH16
454 wp = (addr & ~1);
455 port_width = 2;
456#else
457 wp = (addr & ~3);
458 port_width = 4;
459#endif
460
461 /*
462 * handle unaligned start bytes
463 */
464 if ((l = addr - wp) != 0) {
465 data = 0;
466 for (i = 0, cp = wp; i < l; ++i, ++cp) {
467 data = (data << 8) | (*(uchar *) cp);
468 }
469 for (; i < port_width && cnt > 0; ++i) {
470 data = (data << 8) | *src++;
471 --cnt;
472 ++cp;
473 }
474 for (; cnt == 0 && i < port_width; ++i, ++cp) {
475 data = (data << 8) | (*(uchar *) cp);
476 }
477
478 if ((rc = write_data (info, wp, SWAP (data))) != 0) {
479 return (rc);
480 }
481 wp += port_width;
482 }
483
484 /*
485 * handle word aligned part
486 */
487 count = 0;
488 while (cnt >= port_width) {
489 data = 0;
490 for (i = 0; i < port_width; ++i) {
491 data = (data << 8) | *src++;
492 }
493 if ((rc = write_data (info, wp, SWAP (data))) != 0) {
494 return (rc);
495 }
496 wp += port_width;
497 cnt -= port_width;
498 if (count++ > 0x800) {
499 spin_wheel ();
500 count = 0;
501 }
502 }
503
504 if (cnt == 0) {
505 return (0);
506 }
507
508 /*
509 * handle unaligned tail bytes
510 */
511 data = 0;
512 for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) {
513 data = (data << 8) | *src++;
514 --cnt;
515 }
516 for (; i < port_width; ++i, ++cp) {
517 data = (data << 8) | (*(uchar *) cp);
518 }
519
520 return (write_data (info, wp, SWAP (data)));
521}
522
523/*-----------------------------------------------------------------------
524 * Write a word or halfword to Flash, returns:
525 * 0 - OK
526 * 1 - write timeout
527 * 2 - Flash not erased
528 */
529static int write_data (flash_info_t *info, ulong dest, FPW data)
530{
531 FPWV *addr = (FPWV *) dest;
532 ulong status;
533 ulong start;
534 int flag;
535
536 /* Check if Flash is (sufficiently) erased */
537 if ((*addr & data) != data) {
538 printf ("not erased at %08lx (%lx)\n", (ulong) addr, *addr);
539 return (2);
540 }
541 /* Disable interrupts which might cause a timeout here */
542 flag = disable_interrupts ();
543
544 *addr = (FPW) 0x00400040; /* write setup */
545 *addr = data;
546
547 /* arm simple, non interrupt dependent timer */
548 start = get_timer(0);
549
550 /* wait while polling the status register */
551 while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) {
552 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
553 *addr = (FPW) 0x00FF00FF; /* restore read mode */
554 return (1);
555 }
556 }
557
558 *addr = (FPW) 0x00FF00FF; /* restore read mode */
559
560 return (0);
561}
562
563void inline spin_wheel (void)
564{
565 static int p = 0;
566 static char w[] = "\\/-";
567
568 printf ("\010%c", w[p]);
569 (++p == 3) ? (p = 0) : 0;
570}
571
572/*-----------------------------------------------------------------------
573 * Set/Clear sector's lock bit, returns:
574 * 0 - OK
575 * 1 - Error (timeout, voltage problems, etc.)
576 */
Wolfgang Denk010162e2005-07-30 16:39:27 +0200577int flash_real_protect (flash_info_t *info, long sector, int prot)
wdenkefa329c2004-03-23 20:18:25 +0000578{
579 ulong start;
580 int i;
581 int rc = 0;
582 vu_long *addr = (vu_long *)(info->start[sector]);
583 int flag = disable_interrupts();
584
585 *addr = INTEL_CLEAR; /* Clear status register */
586 if (prot) { /* Set sector lock bit */
587 *addr = INTEL_LOCKBIT; /* Sector lock bit */
588 *addr = INTEL_PROTECT; /* set */
589 }
590 else { /* Clear sector lock bit */
591 *addr = INTEL_LOCKBIT; /* All sectors lock bits */
592 *addr = INTEL_CONFIRM; /* clear */
593 }
594
595 start = get_timer(0);
596
597 while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) {
598 if (get_timer(start) > CFG_FLASH_UNLOCK_TOUT) {
599 printf("Flash lock bit operation timed out\n");
600 rc = 1;
601 break;
602 }
603 }
604
605 if (*addr != INTEL_OK) {
606 printf("Flash lock bit operation failed at %08X, CSR=%08X\n",
607 (uint)addr, (uint)*addr);
608 rc = 1;
609 }
610
611 if (!rc)
612 info->protect[sector] = prot;
613
614 /*
615 * Clear lock bit command clears all sectors lock bits, so
616 * we have to restore lock bits of protected sectors.
Wolfgang Denk010162e2005-07-30 16:39:27 +0200617 * WARNING: code below re-locks sectors only for one bank (info).
618 * This causes problems on boards where several banks share
619 * the same chip, as sectors in othere banks will be unlocked
620 * but not re-locked. It works fine on pm520 though, as there
621 * is only one chip and one bank.
wdenkefa329c2004-03-23 20:18:25 +0000622 */
623 if (!prot)
624 {
625 for (i = 0; i < info->sector_count; i++)
626 {
627 if (info->protect[i])
628 {
629 start = get_timer(0);
630 addr = (vu_long *)(info->start[i]);
631 *addr = INTEL_LOCKBIT; /* Sector lock bit */
632 *addr = INTEL_PROTECT; /* set */
633 while ((*addr & INTEL_FINISHED) != INTEL_FINISHED)
634 {
635 if (get_timer(start) > CFG_FLASH_UNLOCK_TOUT)
636 {
637 printf("Flash lock bit operation timed out\n");
638 rc = 1;
639 break;
640 }
641 }
642 }
643 }
Wolfgang Denk010162e2005-07-30 16:39:27 +0200644 /*
645 * get the s/w sector protection status in sync with the h/w,
646 * in case something went wrong during the re-locking.
647 */
648 flash_sync_real_protect(info); /* resets flash to read mode */
wdenkefa329c2004-03-23 20:18:25 +0000649 }
650
651 if (flag)
652 enable_interrupts();
653
654 *addr = INTEL_RESET; /* Reset to read array mode */
655
656 return rc;
657}