blob: e6c85b6d9a56a332b2906ed20be2b905660a56e7 [file] [log] [blame]
wdenkaffae2b2002-08-17 09:36:01 +00001/*
2 * (C) Copyright 2000
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24#include <common.h>
25#include <board/cogent/flash.h>
26
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020027flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
wdenkaffae2b2002-08-17 09:36:01 +000028
Jean-Christophe PLAGNIOL-VILLARD5a1aceb2008-09-10 22:48:04 +020029#if defined(CONFIG_ENV_IS_IN_FLASH)
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +020030# ifndef CONFIG_ENV_ADDR
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020031# define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
wdenkaffae2b2002-08-17 09:36:01 +000032# endif
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +020033# ifndef CONFIG_ENV_SIZE
34# define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
wdenkaffae2b2002-08-17 09:36:01 +000035# endif
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +020036# ifndef CONFIG_ENV_SECT_SIZE
37# define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE
wdenkaffae2b2002-08-17 09:36:01 +000038# endif
39#endif
40
41/*-----------------------------------------------------------------------
42 * Functions
43 */
44static int write_word (flash_info_t *info, ulong dest, ulong data);
45
46/*-----------------------------------------------------------------------
47 */
48
49
50#if defined(CONFIG_CMA302)
51
52/*
53 * probe for the existence of flash at address "addr"
54 * 0 = yes, 1 = bad Manufacturer's Id, 2 = bad Device Id
55 */
56static int
57c302f_probe_word(c302f_addr_t addr)
58{
59 /* reset the flash */
60 *addr = C302F_BNK_CMD_RST;
61
62 /* check the manufacturer id */
63 *addr = C302F_BNK_CMD_RD_ID;
64 if (*C302F_BNK_ADDR_MAN(addr) != C302F_BNK_RD_ID_MAN)
65 return 1;
66
67 /* check the device id */
68 *addr = C302F_BNK_CMD_RD_ID;
69 if (*C302F_BNK_ADDR_DEV(addr) != C302F_BNK_RD_ID_DEV)
70 return 2;
71
72#ifdef FLASH_DEBUG
73 {
74 int i;
75
76 printf("\nMaster Lock Config = 0x%08lx\n",
77 *C302F_BNK_ADDR_CFGM(addr));
78 for (i = 0; i < C302F_BNK_NBLOCKS; i++)
79 printf("Block %2d Lock Config = 0x%08lx\n",
80 i, *C302F_BNK_ADDR_CFG(i, addr));
81 }
82#endif
83
84 /* reset the flash again */
85 *addr = C302F_BNK_CMD_RST;
86
87 return 0;
88}
89
90/*
91 * probe for Cogent CMA302 flash module at address "base" and store
92 * info for any found into flash_info entry "fip". Must find at least
93 * one bank.
94 */
95static void
96c302f_probe(flash_info_t *fip, c302f_addr_t base)
97{
98 c302f_addr_t addr, eaddr;
99 int nbanks;
100
101 fip->size = 0L;
102 fip->sector_count = 0;
103
104 addr = base;
105 eaddr = C302F_BNK_ADDR_BASE(addr, C302F_MAX_BANKS);
106 nbanks = 0;
107
108 while (addr < eaddr) {
109 c302f_addr_t addrw, eaddrw, addrb;
110 int i, osc, nsc;
111
112 addrw = addr;
113 eaddrw = C302F_BNK_ADDR_NEXT_WORD(addrw);
114
115 while (addrw < eaddrw)
116 if (c302f_probe_word(addrw++) != 0)
117 goto out;
118
119 /* bank exists - append info for this bank to *fip */
120 fip->flash_id = FLASH_MAN_INTEL|FLASH_28F008S5;
121 fip->size += C302F_BNK_SIZE;
122 osc = fip->sector_count;
123 fip->sector_count += C302F_BNK_NBLOCKS;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200124 if ((nsc = fip->sector_count) >= CONFIG_SYS_MAX_FLASH_SECT)
wdenkaffae2b2002-08-17 09:36:01 +0000125 panic("Too many sectors in flash at address 0x%08lx\n",
126 (unsigned long)base);
127
128 addrb = addr;
129 for (i = osc; i < nsc; i++) {
130 fip->start[i] = (ulong)addrb;
131 fip->protect[i] = 0;
132 addrb = C302F_BNK_ADDR_NEXT_BLK(addrb);
133 }
134
135 addr = C302F_BNK_ADDR_NEXT_BNK(addr);
136 nbanks++;
137 }
138
139out:
140 if (nbanks == 0)
141 panic("ERROR: no flash found at address 0x%08lx\n",
142 (unsigned long)base);
143}
144
145static void
146c302f_reset(flash_info_t *info, int sect)
147{
148 c302f_addr_t addrw, eaddrw;
149
150 addrw = (c302f_addr_t)info->start[sect];
151 eaddrw = C302F_BNK_ADDR_NEXT_WORD(addrw);
152
153 while (addrw < eaddrw) {
154#ifdef FLASH_DEBUG
155 printf(" writing reset cmd to addr 0x%08lx\n",
156 (unsigned long)addrw);
157#endif
158 *addrw = C302F_BNK_CMD_RST;
159 addrw++;
160 }
161}
162
163static void
164c302f_erase_init(flash_info_t *info, int sect)
165{
166 c302f_addr_t addrw, saddrw, eaddrw;
167 int flag;
168
169#ifdef FLASH_DEBUG
170 printf("0x%08lx C302F_BNK_CMD_PROG\n", C302F_BNK_CMD_PROG);
171 printf("0x%08lx C302F_BNK_CMD_ERASE1\n", C302F_BNK_CMD_ERASE1);
172 printf("0x%08lx C302F_BNK_CMD_ERASE2\n", C302F_BNK_CMD_ERASE2);
173 printf("0x%08lx C302F_BNK_CMD_CLR_STAT\n", C302F_BNK_CMD_CLR_STAT);
174 printf("0x%08lx C302F_BNK_CMD_RST\n", C302F_BNK_CMD_RST);
175 printf("0x%08lx C302F_BNK_STAT_RDY\n", C302F_BNK_STAT_RDY);
176 printf("0x%08lx C302F_BNK_STAT_ERR\n", C302F_BNK_STAT_ERR);
177#endif
178
179 saddrw = (c302f_addr_t)info->start[sect];
180 eaddrw = C302F_BNK_ADDR_NEXT_WORD(saddrw);
181
182#ifdef FLASH_DEBUG
183 printf("erasing sector %d, start addr = 0x%08lx "
184 "(bank next word addr = 0x%08lx)\n", sect,
185 (unsigned long)saddrw, (unsigned long)eaddrw);
186#endif
187
188 /* Disable intrs which might cause a timeout here */
189 flag = disable_interrupts();
190
191 for (addrw = saddrw; addrw < eaddrw; addrw++) {
192#ifdef FLASH_DEBUG
193 printf(" writing erase cmd to addr 0x%08lx\n",
194 (unsigned long)addrw);
195#endif
196 *addrw = C302F_BNK_CMD_ERASE1;
197 *addrw = C302F_BNK_CMD_ERASE2;
198 }
199
200 /* re-enable interrupts if necessary */
201 if (flag)
202 enable_interrupts();
203}
204
205static int
206c302f_erase_poll(flash_info_t *info, int sect)
207{
208 c302f_addr_t addrw, saddrw, eaddrw;
209 int sectdone, haderr;
210
211 saddrw = (c302f_addr_t)info->start[sect];
212 eaddrw = C302F_BNK_ADDR_NEXT_WORD(saddrw);
213
214 sectdone = 1;
215 haderr = 0;
216
217 for (addrw = saddrw; addrw < eaddrw; addrw++) {
218 c302f_word_t stat = *addrw;
219
220#ifdef FLASH_DEBUG
221 printf(" checking status at addr "
222 "0x%08lx [0x%08lx]\n",
223 (unsigned long)addrw, stat);
224#endif
225 if ((stat & C302F_BNK_STAT_RDY) != C302F_BNK_STAT_RDY)
226 sectdone = 0;
227 else if ((stat & C302F_BNK_STAT_ERR) != 0) {
228 printf(" failed on sector %d "
229 "(stat = 0x%08lx) at "
230 "address 0x%08lx\n",
231 sect, stat,
232 (unsigned long)addrw);
233 *addrw = C302F_BNK_CMD_CLR_STAT;
234 haderr = 1;
235 }
236 }
237
238 if (haderr)
239 return (-1);
240 else
241 return (sectdone);
242}
243
244static int
245c302f_write_word(c302f_addr_t addr, c302f_word_t value)
246{
247 c302f_word_t stat;
248 ulong start;
249 int flag, retval;
250
251 /* Disable interrupts which might cause a timeout here */
252 flag = disable_interrupts();
253
254 *addr = C302F_BNK_CMD_PROG;
255
256 *addr = value;
257
258 /* re-enable interrupts if necessary */
259 if (flag)
260 enable_interrupts();
261
262 retval = 0;
263
264 /* data polling for D7 */
265 start = get_timer (0);
266 do {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200267 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenkaffae2b2002-08-17 09:36:01 +0000268 retval = 1;
269 goto done;
270 }
271 stat = *addr;
272 } while ((stat & C302F_BNK_STAT_RDY) != C302F_BNK_STAT_RDY);
273
274 if ((stat & C302F_BNK_STAT_ERR) != 0) {
275 printf("flash program failed (stat = 0x%08lx) "
276 "at address 0x%08lx\n", (ulong)stat, (ulong)addr);
277 *addr = C302F_BNK_CMD_CLR_STAT;
278 retval = 3;
279 }
280
281done:
282 /* reset to read mode */
283 *addr = C302F_BNK_CMD_RST;
284
285 return (retval);
286}
287
288#endif /* CONFIG_CMA302 */
289
290unsigned long
291flash_init(void)
292{
293 unsigned long total;
294 int i;
295 flash_info_t *fip;
296
297 /* Init: no FLASHes known */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200298 for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
wdenkaffae2b2002-08-17 09:36:01 +0000299 flash_info[i].flash_id = FLASH_UNKNOWN;
300 }
301
302 fip = &flash_info[0];
303 total = 0L;
304
305#if defined(CONFIG_CMA302)
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200306 c302f_probe(fip, (c302f_addr_t)CONFIG_SYS_FLASH_BASE);
wdenkaffae2b2002-08-17 09:36:01 +0000307 total += fip->size;
308 fip++;
309#endif
310
311#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)
312 /* not yet ...
313 cmbf_probe(fip, (cmbf_addr_t)CMA_MB_FLASH_BASE);
314 total += fip->size;
315 fip++;
316 */
317#endif
318
319 /*
320 * protect monitor and environment sectors
321 */
322
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200323#if CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
wdenkaffae2b2002-08-17 09:36:01 +0000324 flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200325 CONFIG_SYS_MONITOR_BASE,
326 CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
wdenkaffae2b2002-08-17 09:36:01 +0000327 &flash_info[0]);
328#endif
329
Jean-Christophe PLAGNIOL-VILLARD5a1aceb2008-09-10 22:48:04 +0200330#ifdef CONFIG_ENV_IS_IN_FLASH
wdenkaffae2b2002-08-17 09:36:01 +0000331 /* ENV protection ON by default */
332 flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +0200333 CONFIG_ENV_ADDR,
334 CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
wdenkaffae2b2002-08-17 09:36:01 +0000335 &flash_info[0]);
336#endif
337 return total;
338}
339
340/*-----------------------------------------------------------------------
341 */
342void
343flash_print_info(flash_info_t *info)
344{
345 int i;
346
347 if (info->flash_id == FLASH_UNKNOWN) {
348 printf ("missing or unknown FLASH type\n");
349 return;
350 }
351
352 switch (info->flash_id & FLASH_VENDMASK) {
353 case FLASH_MAN_INTEL: printf ("INTEL "); break;
354 default: printf ("Unknown Vendor "); break;
355 }
356
357 switch (info->flash_id & FLASH_TYPEMASK) {
358 case FLASH_28F008S5: printf ("28F008S5\n");
359 break;
360 default: printf ("Unknown Chip Type\n");
361 break;
362 }
363
364 printf (" Size: %ld MB in %d Sectors\n",
365 info->size >> 20, info->sector_count);
366
367 printf (" Sector Start Addresses:");
368 for (i=0; i<info->sector_count; ++i) {
369 if ((i % 4) == 0)
370 printf ("\n ");
371 printf (" %2d - %08lX%s", i,
372 info->start[i],
373 info->protect[i] ? " (RO)" : " "
374 );
375 }
376 printf ("\n");
377 return;
378}
379
380/*-----------------------------------------------------------------------
381 */
382
383
384/*-----------------------------------------------------------------------
385 */
386
387/*
388 * The following code cannot be run from FLASH!
389 */
390
391int
392flash_erase(flash_info_t *info, int s_first, int s_last)
393{
394 int prot, sect, haderr;
395 ulong start, now, last;
396 void (*erase_init)(flash_info_t *, int);
397 int (*erase_poll)(flash_info_t *, int);
398 void (*reset)(flash_info_t *, int);
399 int rcode = 0;
400
401#ifdef FLASH_DEBUG
402 printf("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
403 " Bank # %d: ", s_last - s_first + 1, s_first, s_last,
404 (info - flash_info) + 1);
405 flash_print_info(info);
406#endif
407
408 if ((s_first < 0) || (s_first > s_last)) {
409 if (info->flash_id == FLASH_UNKNOWN) {
410 printf ("- missing\n");
411 } else {
412 printf ("- no sectors to erase\n");
413 }
414 return 1;
415 }
416
417 switch (info->flash_id) {
418
419#if defined(CONFIG_CMA302)
420 case FLASH_MAN_INTEL|FLASH_28F008S5:
421 erase_init = c302f_erase_init;
422 erase_poll = c302f_erase_poll;
423 reset = c302f_reset;
424 break;
425#endif
426
427#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)
428 case FLASH_MAN_INTEL|FLASH_28F800_B:
429 case FLASH_MAN_AMD|FLASH_AM29F800B:
430 /* not yet ...
431 erase_init = cmbf_erase_init;
432 erase_poll = cmbf_erase_poll;
433 reset = cmbf_reset;
434 break;
435 */
436#endif
437
438 default:
439 printf ("Flash type %08lx not supported - aborted\n",
440 info->flash_id);
441 return 1;
442 }
443
444 prot = 0;
445 for (sect=s_first; sect<=s_last; ++sect) {
446 if (info->protect[sect]) {
447 prot++;
448 }
449 }
450
451 if (prot) {
452 printf("- Warning: %d protected sector%s will not be erased!\n",
453 prot, (prot > 1 ? "s" : ""));
454 }
455
456 start = get_timer (0);
457 last = 0;
458 haderr = 0;
459
460 for (sect = s_first; sect <= s_last; sect++) {
461 if (info->protect[sect] == 0) { /* not protected */
462 ulong estart;
463 int sectdone;
464
465 (*erase_init)(info, sect);
466
467 /* wait at least 80us - let's wait 1 ms */
468 udelay (1000);
469
470 estart = get_timer(start);
471
472 do {
473 now = get_timer(start);
474
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200475 if (now - estart > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenkaffae2b2002-08-17 09:36:01 +0000476 printf ("Timeout (sect %d)\n", sect);
477 haderr = 1;
478 break;
479 }
480
481#ifndef FLASH_DEBUG
482 /* show that we're waiting */
483 if ((now - last) > 1000) { /* every second */
484 putc ('.');
485 last = now;
486 }
487#endif
488
489 sectdone = (*erase_poll)(info, sect);
490
491 if (sectdone < 0) {
492 haderr = 1;
493 break;
494 }
495
496 } while (!sectdone);
497
498 if (haderr)
499 break;
500 }
501 }
502
503 if (haderr > 0) {
504 printf (" failed\n");
505 rcode = 1;
506 }
507 else
508 printf (" done\n");
509
510 /* reset to read mode */
511 for (sect = s_first; sect <= s_last; sect++) {
512 if (info->protect[sect] == 0) { /* not protected */
513 (*reset)(info, sect);
514 }
515 }
516 return rcode;
517}
518
519/*-----------------------------------------------------------------------
520 * Copy memory to flash, returns:
521 * 0 - OK
522 * 1 - write timeout
523 * 2 - Flash not erased
524 * 3 - write error
525 */
526
527int
528write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
529{
530 ulong cp, wp, data;
531 int i, l, rc;
532 ulong start, now, last;
533
534 wp = (addr & ~3); /* get lower word aligned address */
535
536 /*
537 * handle unaligned start bytes
538 */
539 if ((l = addr - wp) != 0) {
540 data = 0;
541 for (i=0, cp=wp; i<l; ++i, ++cp) {
542 data = (data << 8) | (*(uchar *)cp);
543 }
544 for (; i<4 && cnt>0; ++i) {
545 data = (data << 8) | *src++;
546 --cnt;
547 ++cp;
548 }
549 for (; cnt==0 && i<4; ++i, ++cp) {
550 data = (data << 8) | (*(uchar *)cp);
551 }
552
553 if ((rc = write_word(info, wp, data)) != 0) {
554 return (rc);
555 }
556 wp += 4;
557 }
558
559 /*
560 * handle word aligned part
561 */
562 start = get_timer (0);
563 last = 0;
564 while (cnt >= 4) {
565 data = 0;
566 for (i=0; i<4; ++i) {
567 data = (data << 8) | *src++;
568 }
569 if ((rc = write_word(info, wp, data)) != 0) {
570 return (rc);
571 }
572 wp += 4;
573 cnt -= 4;
574
575 /* show that we're waiting */
576 now = get_timer(start);
577 if ((now - last) > 1000) { /* every second */
578 putc ('.');
579 last = now;
580 }
581 }
582
583 if (cnt == 0) {
584 return (0);
585 }
586
587 /*
588 * handle unaligned tail bytes
589 */
590 data = 0;
591 for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
592 data = (data << 8) | *src++;
593 --cnt;
594 }
595 for (; i<4; ++i, ++cp) {
596 data = (data << 8) | (*(uchar *)cp);
597 }
598
599 return (write_word(info, wp, data));
600}
601
602/*-----------------------------------------------------------------------
603 * Write a word to Flash, returns:
604 * 0 - OK
605 * 1 - write timeout
606 * 2 - Flash not erased
607 * 3 - write error
608 */
609static int
610write_word(flash_info_t *info, ulong dest, ulong data)
611{
612 int retval;
613
614 /* Check if Flash is (sufficiently) erased */
615 if ((*(ulong *)dest & data) != data) {
616 return (2);
617 }
618
619 switch (info->flash_id) {
620
621#if defined(CONFIG_CMA302)
622 case FLASH_MAN_INTEL|FLASH_28F008S5:
623 retval = c302f_write_word((c302f_addr_t)dest, (c302f_word_t)data);
624 break;
625#endif
626
627#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)
628 case FLASH_MAN_INTEL|FLASH_28F800_B:
629 case FLASH_MAN_AMD|FLASH_AM29F800B:
630 /* not yet ...
631 retval = cmbf_write_word((cmbf_addr_t)dest, (cmbf_word_t)data);
632 */
633 retval = 3;
634 break;
635#endif
636
637 default:
638 printf ("Flash type %08lx not supported - aborted\n",
639 info->flash_id);
640 retval = 3;
641 break;
642 }
643
644 return (retval);
645}
646
647/*-----------------------------------------------------------------------
648 */