blob: d2f169b88efcacd89f19dca290b43a3c0f1f5b6b [file] [log] [blame]
wdenk174e0e52003-12-07 22:27:15 +00001/*
2 * (C) Copyright 2003
3 * MuLogic B.V.
4 *
5 * (C) Copyright 2001
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 <ppc4xx.h>
29#include <asm/u-boot.h>
30#include <asm/processor.h>
31
32flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
33
34
35#define FLASH_WORD_SIZE unsigned long
36#define FLASH_ID_MASK 0xFFFFFFFF
37
38/*-----------------------------------------------------------------------
39 * Functions
40 */
41/* stolen from esteem192e/flash.c */
42ulong flash_get_size (volatile FLASH_WORD_SIZE *addr, flash_info_t *info);
43
44static int write_word (flash_info_t *info, ulong dest, ulong data);
45static void flash_get_offsets (ulong base, flash_info_t *info);
46
47
48/*-----------------------------------------------------------------------
49 */
50
51unsigned long flash_init (void)
52{
53 unsigned long size_b0, size_b1;
54 int i;
55 uint pbcr;
56 unsigned long base_b0, base_b1;
57 volatile FLASH_WORD_SIZE* flash_base;
58
59 /* Init: no FLASHes known */
60 for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
61 flash_info[i].flash_id = FLASH_UNKNOWN;
62 }
63
64 /* Static FLASH Bank configuration here */
65 /* Test for 8M Flash first */
66 debug ("\n## Get flash bank 1 size @ 0x%08x\n",FLASH_BASE0_8M_PRELIM);
67 flash_base = (volatile FLASH_WORD_SIZE*)(FLASH_BASE0_8M_PRELIM);
68 size_b0 = flash_get_size(flash_base, &flash_info[0]);
69
70 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
71 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
72 size_b0, size_b0<<20);
73 return 0;
74 }
75
76 if (size_b0 < 8*1024*1024) {
77 /* Not quite 8M, try 4M Flash base address */
78 debug ("\n## Get flash bank 1 size @ 0x%08x\n",FLASH_BASE0_4M_PRELIM);
79 flash_base = (volatile FLASH_WORD_SIZE*)(FLASH_BASE0_4M_PRELIM);
80 size_b0 = flash_get_size(flash_base, &flash_info[0]);
81 }
82
83 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
84 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
85 size_b0, size_b0<<20);
86 return 0;
87 }
88
89 /* Only one bank */
90 if (CFG_MAX_FLASH_BANKS == 1) {
91 /* Setup offsets */
92 flash_get_offsets ((ulong)flash_base, &flash_info[0]);
93
94 /* Monitor protection ON by default */
95 (void)flash_protect(FLAG_PROTECT_SET, CFG_MONITOR_BASE,
96 CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, &flash_info[0]);
97 size_b1 = 0 ;
98 flash_info[0].size = size_b0;
99 return(size_b0);
100 }
101
102 /* We have 2 banks */
103 size_b1 = flash_get_size(flash_base, &flash_info[1]);
104
105 /* Re-do sizing to get full correct info */
106 if (size_b1) {
107 mtdcr(ebccfga, pb0cr);
108 pbcr = mfdcr(ebccfgd);
109 mtdcr(ebccfga, pb0cr);
110 base_b1 = -size_b1;
111 pbcr = (pbcr & 0x0001ffff) | base_b1 | (((size_b1/1024/1024)-1)<<17);
112 mtdcr(ebccfgd, pbcr);
113 }
114
115 if (size_b0) {
116 mtdcr(ebccfga, pb1cr);
117 pbcr = mfdcr(ebccfgd);
118 mtdcr(ebccfga, pb1cr);
119 base_b0 = base_b1 - size_b0;
120 pbcr = (pbcr & 0x0001ffff) | base_b0 | (((size_b0/1024/1024)-1)<<17);
121 mtdcr(ebccfgd, pbcr);
122 }
123
124 size_b0 = flash_get_size((volatile FLASH_WORD_SIZE *)base_b0, &flash_info[0]);
125 flash_get_offsets (base_b0, &flash_info[0]);
126
127 /* monitor protection ON by default */
128 (void)flash_protect(FLAG_PROTECT_SET, CFG_MONITOR_BASE,
129 CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, &flash_info[0]);
130
131 if (size_b1) {
132 /* Re-do sizing to get full correct info */
133 size_b1 = flash_get_size((volatile FLASH_WORD_SIZE *)base_b1, &flash_info[1]);
134 flash_get_offsets (base_b1, &flash_info[1]);
135
136 /* monitor protection ON by default */
137 (void)flash_protect(FLAG_PROTECT_SET, base_b1+size_b1-CFG_MONITOR_LEN,
138 base_b1+size_b1-1, &flash_info[1]);
139
140 /* monitor protection OFF by default (one is enough) */
141 (void)flash_protect(FLAG_PROTECT_CLEAR, base_b0+size_b0-CFG_MONITOR_LEN,
142 base_b0+size_b0-1, &flash_info[0]);
143 } else {
144 flash_info[1].flash_id = FLASH_UNKNOWN;
145 flash_info[1].sector_count = -1;
146 }
147
148 flash_info[0].size = size_b0;
149 flash_info[1].size = size_b1;
150 return (size_b0 + size_b1);
151}
152
153
wdenk174e0e52003-12-07 22:27:15 +0000154/*-----------------------------------------------------------------------
155 This code is specific to the AM29DL163/AM29DL232 for the QS850/QS823.
156 */
157
158static void flash_get_offsets (ulong base, flash_info_t *info)
159{
160 int i;
161 long large_sect_size;
162 long small_sect_size;
163
164 /* set up sector start adress table */
165 large_sect_size = info->size / (info->sector_count - 8 + 1);
166 small_sect_size = large_sect_size / 8;
167
168 if (info->flash_id & FLASH_BTYPE) {
169
170 /* set sector offsets for bottom boot block type */
171 for (i = 0; i < 7; i++) {
172 info->start[i] = base;
173 base += small_sect_size;
174 }
175
176 for (; i < info->sector_count; i++) {
177 info->start[i] = base;
178 base += large_sect_size;
179 }
180 }
181 else
182 {
183 /* set sector offsets for top boot block type */
184 for (i = 0; i < (info->sector_count - 8); i++) {
185 info->start[i] = base;
186 base += large_sect_size;
187 }
188
189 for (; i < info->sector_count; i++) {
190 info->start[i] = base;
191 base += small_sect_size;
192 }
193 }
194}
195
196/*-----------------------------------------------------------------------
197 */
198
199void flash_print_info (flash_info_t *info)
200{
201 int i;
202 uchar *boottype;
203 uchar botboot[]=", bottom boot sect)\n";
204 uchar topboot[]=", top boot sector)\n";
205
206 if (info->flash_id == FLASH_UNKNOWN) {
207 printf ("missing or unknown FLASH type\n");
208 return;
209 }
210
211 switch (info->flash_id & FLASH_VENDMASK) {
212 case FLASH_MAN_AMD:
213 printf ("AMD ");
214 break;
215 case FLASH_MAN_FUJ:
216 printf ("FUJITSU ");
217 break;
218 case FLASH_MAN_SST:
219 printf ("SST ");
220 break;
221 case FLASH_MAN_STM:
222 printf ("STM ");
223 break;
224 case FLASH_MAN_INTEL:
225 printf ("INTEL ");
226 break;
227 default:
228 printf ("Unknown Vendor ");
229 break;
230 }
231
232 if (info->flash_id & 0x0001 ) {
233 boottype = botboot;
234 } else {
235 boottype = topboot;
236 }
237
238 switch (info->flash_id & FLASH_TYPEMASK) {
239 case FLASH_AM160B:
240 printf ("AM29LV160B (16 Mbit%s",boottype);
241 break;
242 case FLASH_AM160T:
243 printf ("AM29LV160T (16 Mbit%s",boottype);
244 break;
245 case FLASH_AMDL163T:
246 printf ("AM29DL163T (16 Mbit%s",boottype);
247 break;
248 case FLASH_AMDL163B:
249 printf ("AM29DL163B (16 Mbit%s",boottype);
250 break;
251 case FLASH_AM320B:
252 printf ("AM29LV320B (32 Mbit%s",boottype);
253 break;
254 case FLASH_AM320T:
255 printf ("AM29LV320T (32 Mbit%s",boottype);
256 break;
257 case FLASH_AMDL323T:
258 printf ("AM29DL323T (32 Mbit%s",boottype);
259 break;
260 case FLASH_AMDL323B:
261 printf ("AM29DL323B (32 Mbit%s",boottype);
262 break;
263 case FLASH_AMDL322T:
264 printf ("AM29DL322T (32 Mbit%s",boottype);
265 break;
266 default:
267 printf ("Unknown Chip Type\n");
268 break;
269 }
270
271 printf (" Size: %ld MB in %d Sectors\n",
272 info->size >> 20, info->sector_count);
273
274 printf (" Sector Start Addresses:");
275 for (i=0; i<info->sector_count; ++i) {
276 if ((i % 5) == 0)
277 printf ("\n ");
278 printf (" %08lX%s", info->start[i],
279 info->protect[i] ? " (RO)" : " ");
280 }
281 printf ("\n");
282 return;
283}
284
285
286/*-----------------------------------------------------------------------
287 * The following code cannot be run from FLASH!
288 */
289ulong flash_get_size (volatile FLASH_WORD_SIZE *addr, flash_info_t *info)
290{
291 short i;
292 ulong base = (ulong)addr;
293 FLASH_WORD_SIZE value;
294
295 /* Write auto select command: read Manufacturer ID */
296
297 /*
298 * Note: if it is an AMD flash and the word at addr[0000]
299 * is 0x00890089 this routine will think it is an Intel
300 * flash device and may(most likely) cause trouble.
301 */
302
303 addr[0x0000] = 0x00900090;
304 if(addr[0x0000] != 0x00890089){
305 addr[0x0555] = 0x00AA00AA;
306 addr[0x02AA] = 0x00550055;
307 addr[0x0555] = 0x00900090;
308 }
309 value = addr[0];
310
311 switch (value) {
312 case (AMD_MANUFACT & FLASH_ID_MASK):
313 info->flash_id = FLASH_MAN_AMD;
314 break;
315 case (FUJ_MANUFACT & FLASH_ID_MASK):
316 info->flash_id = FLASH_MAN_FUJ;
317 break;
318 case (STM_MANUFACT & FLASH_ID_MASK):
319 info->flash_id = FLASH_MAN_STM;
320 break;
321 case (SST_MANUFACT & FLASH_ID_MASK):
322 info->flash_id = FLASH_MAN_SST;
323 break;
324 case (INTEL_MANUFACT & FLASH_ID_MASK):
325 info->flash_id = FLASH_MAN_INTEL;
326 break;
327 default:
328 info->flash_id = FLASH_UNKNOWN;
329 info->sector_count = 0;
330 info->size = 0;
331 return (0); /* no or unknown flash */
332 }
333
334 value = addr[1]; /* device ID */
335
336 switch (value) {
337 case (AMD_ID_LV160T & FLASH_ID_MASK):
338 info->flash_id += FLASH_AM160T;
339 info->sector_count = 35;
340 info->size = 0x00400000;
341 break; /* => 4 MB */
342
343 case (AMD_ID_LV160B & FLASH_ID_MASK):
344 info->flash_id += FLASH_AM160B;
345 info->sector_count = 35;
346 info->size = 0x00400000;
347 break; /* => 4 MB */
348
349 case (AMD_ID_DL163T & FLASH_ID_MASK):
350 info->flash_id += FLASH_AMDL163T;
351 info->sector_count = 39;
352 info->size = 0x00400000;
353 break; /* => 4 MB */
354
355 case (AMD_ID_DL163B & FLASH_ID_MASK):
356 info->flash_id += FLASH_AMDL163B;
357 info->sector_count = 39;
358 info->size = 0x00400000;
359 break; /* => 4 MB */
360
361 case (AMD_ID_DL323T & FLASH_ID_MASK):
362 info->flash_id += FLASH_AMDL323T;
363 info->sector_count = 71;
364 info->size = 0x00800000;
365 break; /* => 8 MB */
366
367 case (AMD_ID_DL323B & FLASH_ID_MASK):
368 info->flash_id += FLASH_AMDL323B;
369 info->sector_count = 71;
370 info->size = 0x00800000;
371 break; /* => 8 MB */
372
373 case (AMD_ID_DL322T & FLASH_ID_MASK):
374 info->flash_id += FLASH_AMDL322T;
375 info->sector_count = 71;
376 info->size = 0x00800000;
377 break; /* => 8 MB */
378
379 default:
380 /* FIXME*/
381 info->flash_id = FLASH_UNKNOWN;
382 return (0); /* => no or unknown flash */
383 }
384
385 flash_get_offsets(base, info);
386
387 /* check for protected sectors */
388 for (i = 0; i < info->sector_count; i++) {
389 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
390 /* D0 = 1 if protected */
391 addr = (volatile FLASH_WORD_SIZE *)(info->start[i]);
392 info->protect[i] = addr[2] & 1;
393 }
394
395 /*
396 * Prevent writes to uninitialized FLASH.
397 */
398 if (info->flash_id != FLASH_UNKNOWN) {
399 addr = (volatile FLASH_WORD_SIZE *)info->start[0];
400 *addr = (0x00FF00FF & FLASH_ID_MASK); /* reset bank */
401 }
402
403 return (info->size);
404}
405
406
407/*-----------------------------------------------------------------------
408 */
409
410int flash_erase (flash_info_t *info, int s_first, int s_last)
411{
412 volatile FLASH_WORD_SIZE *addr=(volatile FLASH_WORD_SIZE*)(info->start[0]);
413 int flag, prot, sect, l_sect;
414 ulong start, now, last;
415 int rcode = 0;
416
417 if ((s_first < 0) || (s_first > s_last)) {
418 if (info->flash_id == FLASH_UNKNOWN) {
419 printf ("- missing\n");
420 } else {
421 printf ("- no sectors to erase\n");
422 }
423 return 1;
424 }
425
426 if ((info->flash_id == FLASH_UNKNOWN) ||
427 (info->flash_id > FLASH_AMD_COMP) ) {
428 printf ("Can't erase unknown flash type - aborted\n");
429 return 1;
430 }
431
432 prot = 0;
433 for (sect=s_first; sect<=s_last; ++sect) {
434 if (info->protect[sect]) {
435 prot++;
436 }
437 }
438
439 if (prot) {
440 printf ("- Warning: %d protected sectors will not be erased!\n",
441 prot);
442 } else {
443 printf ("\n");
444 }
445
446 l_sect = -1;
447
448 /* Disable interrupts which might cause a timeout here */
449 flag = disable_interrupts();
450 addr[0x0555] = 0x00AA00AA;
451 addr[0x02AA] = 0x00550055;
452 addr[0x0555] = 0x00800080;
453 addr[0x0555] = 0x00AA00AA;
454 addr[0x02AA] = 0x00550055;
455 /* Start erase on unprotected sectors */
456 for (sect = s_first; sect<=s_last; sect++) {
457 if (info->protect[sect] == 0) { /* not protected */
458 addr = (volatile FLASH_WORD_SIZE *)(info->start[sect]);
459 addr[0] = (0x00300030 & FLASH_ID_MASK);
460 l_sect = sect;
461 }
462 }
463
464 /* re-enable interrupts if necessary */
465 if (flag)
466 enable_interrupts();
467
468 /* wait at least 80us - let's wait 1 ms */
469 udelay (1000);
470
471 /*
472 * We wait for the last triggered sector
473 */
474 if (l_sect < 0)
475 goto DONE;
476
477 start = get_timer (0);
478 last = start;
479 addr = (volatile FLASH_WORD_SIZE*)(info->start[l_sect]);
480 while ((addr[0] & (0x00800080&FLASH_ID_MASK)) !=
481 (0x00800080&FLASH_ID_MASK) )
482 {
483 if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
484 printf ("Timeout\n");
485 return 1;
486 }
487 /* show that we're waiting */
488 if ((now - last) > 1000) { /* every second */
489 serial_putc ('.');
490 last = now;
491 }
492 }
493
494DONE:
495 /* reset to read mode */
496 addr = (volatile FLASH_WORD_SIZE *)info->start[0];
497 addr[0] = (0x00F000F0 & FLASH_ID_MASK); /* reset bank */
498
499 printf (" done\n");
500 return rcode;
501}
502
503/*-----------------------------------------------------------------------
504 * Copy memory to flash, returns:
505 * 0 - OK
506 * 1 - write timeout
507 * 2 - Flash not erased
508 */
509
510int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
511{
512 ulong cp, wp, data;
513 int l;
514 int i, rc;
515
516 wp = (addr & ~3); /* get lower word aligned address */
517
518 /*
519 * handle unaligned start bytes
520 */
521 if ((l = addr - wp) != 0) {
522 data = 0;
523 for (i=0, cp=wp; i<l; ++i, ++cp) {
524 data = (data << 8) | (*(uchar *)cp);
525 }
526 for (; i<4 && cnt>0; ++i) {
527 data = (data << 8) | *src++;
528 --cnt;
529 ++cp;
530 }
531 for (; cnt==0 && i<4; ++i, ++cp) {
532 data = (data << 8) | (*(uchar *)cp);
533 }
534
535 if ((rc = write_word(info, wp, data)) != 0) {
536 return (rc);
537 }
538 wp += 4;
539 }
540
541 /*
542 * handle word aligned part
543 */
544 while (cnt >= 4) {
545 data = 0;
546 for (i=0; i<4; ++i) {
547 data = (data << 8) | *src++;
548 }
549 if ((rc = write_word(info, wp, data)) != 0) {
550 return (rc);
551 }
552 wp += 4;
553 cnt -= 4;
554 }
555
556 if (cnt == 0) {
557 return (0);
558 }
559
560 /*
561 * handle unaligned tail bytes
562 */
563 data = 0;
564 for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
565 data = (data << 8) | *src++;
566 --cnt;
567 }
568 for (; i<4; ++i, ++cp) {
569 data = (data << 8) | (*(uchar *)cp);
570 }
571
572 return (write_word(info, wp, data));
573}
574
575/*-----------------------------------------------------------------------
576 * Write a word to Flash, returns:
577 * 0 - OK
578 * 1 - write timeout
579 * 2 - Flash not erased
580 */
581static int write_word (flash_info_t *info, ulong dest, ulong data)
582{
583 vu_long *addr = (vu_long*)(info->start[0]);
584 ulong start;
585 int flag;
586
587 /* Check if Flash is (sufficiently) erased */
588 if ((*((vu_long *)dest) & data) != data) {
589 return (2);
590 }
591
592 /* Disable interrupts which might cause a timeout here */
593 flag = disable_interrupts();
594
595 /* AMD stuff */
596 addr[0x0555] = 0x00AA00AA;
597 addr[0x02AA] = 0x00550055;
598 addr[0x0555] = 0x00A000A0;
599
600 *((vu_long *)dest) = data;
601
602 /* re-enable interrupts if necessary */
603 if (flag)
604 enable_interrupts();
605
606 /* data polling for D7 */
607 start = get_timer(0);
608
609 while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
610 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
611 return (1);
612 }
613 }
614
615 return (0);
616}