blob: 54a910b1780121d51060669d571c002ede543d66 [file] [log] [blame]
wdenk452cfd62002-11-19 11:04:11 +00001/*
2 * (C) Copyright 2001
3 * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
4 *
5 * (C) Copyright 2002
6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7 *
Wolfgang Denkbd8ec7e2013-10-07 13:07:26 +02008 * SPDX-License-Identifier: GPL-2.0+
wdenk452cfd62002-11-19 11:04:11 +00009 */
10
11#include <common.h>
12#include <flash.h>
13#include <asm/io.h>
14#include <memio.h>
15
16/*---------------------------------------------------------------------*/
17#undef DEBUG_FLASH
wdenk452cfd62002-11-19 11:04:11 +000018
19#ifdef DEBUG_FLASH
wdenk874ac262003-07-24 23:38:38 +000020#define DEBUGF(fmt,args...) printf(fmt ,##args)
wdenk452cfd62002-11-19 11:04:11 +000021#else
22#define DEBUGF(fmt,args...)
23#endif
24/*---------------------------------------------------------------------*/
25
Marian Balakowicz513b4a12005-10-11 19:09:42 +020026flash_info_t flash_info[];
wdenk452cfd62002-11-19 11:04:11 +000027
28static ulong flash_get_size (ulong addr, flash_info_t *info);
29static int flash_get_offsets (ulong base, flash_info_t *info);
30static int write_word (flash_info_t *info, ulong dest, ulong data);
31static void flash_reset (ulong addr);
32
33int flash_xd_nest;
34
35static void flash_to_xd(void)
36{
37 unsigned char x;
38
39 flash_xd_nest ++;
40
41 if (flash_xd_nest == 1)
42 {
43 DEBUGF("Flash on XD\n");
44 x = pci_read_cfg_byte(0, 0, 0x74);
45 pci_write_cfg_byte(0, 0, 0x74, x|1);
46 }
47}
48
49static void flash_to_mem(void)
50{
51 unsigned char x;
52
53 flash_xd_nest --;
wdenk57b2d802003-06-27 21:31:46 +000054
wdenk452cfd62002-11-19 11:04:11 +000055 if (flash_xd_nest == 0)
56 {
57 DEBUGF("Flash on memory bus\n");
58 x = pci_read_cfg_byte(0, 0, 0x74);
59 pci_write_cfg_byte(0, 0, 0x74, x&0xFE);
60 }
61}
62
63unsigned long flash_init_old(void)
64{
65 int i;
66
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020067 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
wdenk452cfd62002-11-19 11:04:11 +000068 {
69 flash_info[i].flash_id = FLASH_UNKNOWN;
70 flash_info[i].sector_count = 0;
71 flash_info[i].size = 0;
72 }
73
74
75 return 1;
76}
77
78unsigned long flash_init (void)
79{
80 unsigned int i;
81 unsigned long flash_size = 0;
82
83 flash_xd_nest = 0;
84
85 flash_to_xd();
86
87 /* Init: no FLASHes known */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020088 for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
wdenk452cfd62002-11-19 11:04:11 +000089 flash_info[i].flash_id = FLASH_UNKNOWN;
90 flash_info[i].sector_count = 0;
91 flash_info[i].size = 0;
92 }
93
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020094 DEBUGF("\n## Get flash size @ 0x%08x\n", CONFIG_SYS_FLASH_BASE);
wdenk452cfd62002-11-19 11:04:11 +000095
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020096 flash_size = flash_get_size (CONFIG_SYS_FLASH_BASE, flash_info);
wdenk452cfd62002-11-19 11:04:11 +000097
98 DEBUGF("## Flash bank size: %08lx\n", flash_size);
99
100 if (flash_size) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200101#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE && \
102 CONFIG_SYS_MONITOR_BASE < CONFIG_SYS_FLASH_BASE + CONFIG_SYS_FLASH_MAX_SIZE
wdenk452cfd62002-11-19 11:04:11 +0000103 /* monitor protection ON by default */
104 flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200105 CONFIG_SYS_MONITOR_BASE,
106 CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN - 1,
wdenk452cfd62002-11-19 11:04:11 +0000107 &flash_info[0]);
108#endif
109
Jean-Christophe PLAGNIOL-VILLARD53db4cd2008-09-10 22:48:04 +0200110#ifdef CONFIG_ENV_IS_IN_FLASH
wdenk452cfd62002-11-19 11:04:11 +0000111 /* ENV protection ON by default */
112 flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD7e1cda62008-09-10 22:48:06 +0200113 CONFIG_ENV_ADDR,
114 CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
wdenk452cfd62002-11-19 11:04:11 +0000115 &flash_info[0]);
116#endif
117
118 } else {
wdenk874ac262003-07-24 23:38:38 +0000119 printf ("Warning: the BOOT Flash is not initialised !");
wdenk452cfd62002-11-19 11:04:11 +0000120 }
121
122 flash_to_mem();
123
124 return flash_size;
125}
126
127/*
128 * The following code cannot be run from FLASH!
129 */
130static ulong flash_get_size (ulong addr, flash_info_t *info)
131{
132 short i;
133 uchar value;
134 uchar *x = (uchar *)addr;
135
136 flash_to_xd();
137
138 /* Write auto select command: read Manufacturer ID */
139 x[0x0555] = 0xAA;
Peter Tyser745e27e2009-04-20 11:09:05 -0500140 __asm__ volatile ("sync\n eieio");
wdenk452cfd62002-11-19 11:04:11 +0000141 x[0x02AA] = 0x55;
Peter Tyser745e27e2009-04-20 11:09:05 -0500142 __asm__ volatile ("sync\n eieio");
wdenk452cfd62002-11-19 11:04:11 +0000143 x[0x0555] = 0x90;
Peter Tyser745e27e2009-04-20 11:09:05 -0500144 __asm__ volatile ("sync\n eieio");
wdenk452cfd62002-11-19 11:04:11 +0000145
146 value = x[0];
Peter Tyser745e27e2009-04-20 11:09:05 -0500147 __asm__ volatile ("sync\n eieio");
wdenk452cfd62002-11-19 11:04:11 +0000148
149 DEBUGF("Manuf. ID @ 0x%08lx: 0x%08x\n", (ulong)addr, value);
150
151 switch (value | (value << 16)) {
152 case AMD_MANUFACT:
153 info->flash_id = FLASH_MAN_AMD;
154 break;
155
156 case FUJ_MANUFACT:
157 info->flash_id = FLASH_MAN_FUJ;
158 break;
159
160 case STM_MANUFACT:
161 info->flash_id = FLASH_MAN_STM;
162 break;
163
164 default:
165 info->flash_id = FLASH_UNKNOWN;
166 info->sector_count = 0;
167 info->size = 0;
168 flash_reset (addr);
169 return 0;
170 }
171
172 value = x[1];
Peter Tyser745e27e2009-04-20 11:09:05 -0500173 __asm__ volatile ("sync\n eieio");
wdenk452cfd62002-11-19 11:04:11 +0000174
175 DEBUGF("Device ID @ 0x%08lx: 0x%08x\n", addr+1, value);
176
177 switch (value) {
178 case AMD_ID_F040B:
179 DEBUGF("Am29F040B\n");
180 info->flash_id += FLASH_AM040;
181 info->sector_count = 8;
182 info->size = 0x00080000;
183 break; /* => 512 kB */
184
185 case AMD_ID_LV040B:
186 DEBUGF("Am29LV040B\n");
187 info->flash_id += FLASH_AM040;
188 info->sector_count = 8;
189 info->size = 0x00080000;
190 break; /* => 512 kB */
191
192 case AMD_ID_LV400T:
193 DEBUGF("Am29LV400T\n");
194 info->flash_id += FLASH_AM400T;
195 info->sector_count = 11;
196 info->size = 0x00100000;
197 break; /* => 1 MB */
198
199 case AMD_ID_LV400B:
200 DEBUGF("Am29LV400B\n");
201 info->flash_id += FLASH_AM400B;
202 info->sector_count = 11;
203 info->size = 0x00100000;
204 break; /* => 1 MB */
205
206 case AMD_ID_LV800T:
207 DEBUGF("Am29LV800T\n");
208 info->flash_id += FLASH_AM800T;
209 info->sector_count = 19;
210 info->size = 0x00200000;
211 break; /* => 2 MB */
212
213 case AMD_ID_LV800B:
214 DEBUGF("Am29LV400B\n");
215 info->flash_id += FLASH_AM800B;
216 info->sector_count = 19;
217 info->size = 0x00200000;
218 break; /* => 2 MB */
219
220 case AMD_ID_LV160T:
221 DEBUGF("Am29LV160T\n");
222 info->flash_id += FLASH_AM160T;
223 info->sector_count = 35;
224 info->size = 0x00400000;
225 break; /* => 4 MB */
226
227 case AMD_ID_LV160B:
228 DEBUGF("Am29LV160B\n");
229 info->flash_id += FLASH_AM160B;
230 info->sector_count = 35;
231 info->size = 0x00400000;
232 break; /* => 4 MB */
233
234 case AMD_ID_LV320T:
235 DEBUGF("Am29LV320T\n");
236 info->flash_id += FLASH_AM320T;
237 info->sector_count = 67;
238 info->size = 0x00800000;
239 break; /* => 8 MB */
240
241#if 0
242 /* Has the same ID as AMD_ID_LV320T, to be fixed */
243 case AMD_ID_LV320B:
244 DEBUGF("Am29LV320B\n");
245 info->flash_id += FLASH_AM320B;
246 info->sector_count = 67;
247 info->size = 0x00800000;
248 break; /* => 8 MB */
249#endif
250
251 case AMD_ID_LV033C:
252 DEBUGF("Am29LV033C\n");
253 info->flash_id += FLASH_AM033C;
254 info->sector_count = 64;
255 info->size = 0x01000000;
256 break; /* => 16Mb */
257
258 case STM_ID_F040B:
259 DEBUGF("M29F040B\n");
260 info->flash_id += FLASH_AM040;
261 info->sector_count = 8;
262 info->size = 0x00080000;
263 break; /* => 512 kB */
264
265 default:
266 info->flash_id = FLASH_UNKNOWN;
267 flash_reset (addr);
268 flash_to_mem();
269 return (0); /* => no or unknown flash */
270
271 }
272
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200273 if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
wdenk874ac262003-07-24 23:38:38 +0000274 printf ("** ERROR: sector count %d > max (%d) **\n",
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200275 info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
276 info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
wdenk452cfd62002-11-19 11:04:11 +0000277 }
278
279 if (! flash_get_offsets (addr, info)) {
280 flash_reset (addr);
281 flash_to_mem();
282 return 0;
283 }
284
285 /* check for protected sectors */
286 for (i = 0; i < info->sector_count; i++) {
287 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
288 /* D0 = 1 if protected */
289 value = in8(info->start[i] + 2);
290 iobarrier_rw();
291 info->protect[i] = (value & 1) != 0;
292 }
293
294 /*
295 * Reset bank to read mode
296 */
297 flash_reset (addr);
298
299 flash_to_mem();
300
301 return (info->size);
302}
303
304static int flash_get_offsets (ulong base, flash_info_t *info)
305{
306 unsigned int i;
307
308 switch (info->flash_id & FLASH_TYPEMASK) {
309 case FLASH_AM040:
310 /* set sector offsets for uniform sector type */
311 for (i = 0; i < info->sector_count; i++) {
312 info->start[i] = base + i * info->size /
wdenk57b2d802003-06-27 21:31:46 +0000313 info->sector_count;
wdenk452cfd62002-11-19 11:04:11 +0000314 }
315 break;
316 default:
317 return 0;
318 }
319
320 return 1;
321}
322
323int flash_erase (flash_info_t *info, int s_first, int s_last)
324{
325 volatile ulong addr = info->start[0];
326 int flag, prot, sect, l_sect;
327 ulong start, now, last;
328
329 flash_to_xd();
330
331 if (s_first < 0 || s_first > s_last) {
332 if (info->flash_id == FLASH_UNKNOWN) {
wdenk874ac262003-07-24 23:38:38 +0000333 printf ("- missing\n");
wdenk452cfd62002-11-19 11:04:11 +0000334 } else {
wdenk874ac262003-07-24 23:38:38 +0000335 printf ("- no sectors to erase\n");
wdenk452cfd62002-11-19 11:04:11 +0000336 }
337 flash_to_mem();
338 return 1;
339 }
340
341 if (info->flash_id == FLASH_UNKNOWN) {
wdenk874ac262003-07-24 23:38:38 +0000342 printf ("Can't erase unknown flash type %08lx - aborted\n",
wdenk452cfd62002-11-19 11:04:11 +0000343 info->flash_id);
344 flash_to_mem();
345 return 1;
346 }
347
348 prot = 0;
349 for (sect=s_first; sect<=s_last; ++sect) {
350 if (info->protect[sect]) {
351 prot++;
352 }
353 }
354
355 if (prot) {
wdenk874ac262003-07-24 23:38:38 +0000356 printf ("- Warning: %d protected sectors will not be erased!\n",
wdenk452cfd62002-11-19 11:04:11 +0000357 prot);
358 } else {
wdenk874ac262003-07-24 23:38:38 +0000359 printf ("");
wdenk452cfd62002-11-19 11:04:11 +0000360 }
361
362 l_sect = -1;
363
364 /* Disable interrupts which might cause a timeout here */
365 flag = disable_interrupts();
366
367 out8(addr + 0x555, 0xAA);
368 iobarrier_rw();
369 out8(addr + 0x2AA, 0x55);
370 iobarrier_rw();
371 out8(addr + 0x555, 0x80);
372 iobarrier_rw();
373 out8(addr + 0x555, 0xAA);
374 iobarrier_rw();
375 out8(addr + 0x2AA, 0x55);
376 iobarrier_rw();
377
378 /* Start erase on unprotected sectors */
379 for (sect = s_first; sect<=s_last; sect++) {
380 if (info->protect[sect] == 0) { /* not protected */
381 addr = info->start[sect];
382 out8(addr, 0x30);
383 iobarrier_rw();
384 l_sect = sect;
385 }
386 }
387
388 /* re-enable interrupts if necessary */
389 if (flag)
390 enable_interrupts();
391
392 /* wait at least 80us - let's wait 1 ms */
wdenk874ac262003-07-24 23:38:38 +0000393 udelay (1000);
wdenk452cfd62002-11-19 11:04:11 +0000394
395 /*
396 * We wait for the last triggered sector
397 */
398 if (l_sect < 0)
399 goto DONE;
400
wdenk874ac262003-07-24 23:38:38 +0000401 start = get_timer (0);
wdenk452cfd62002-11-19 11:04:11 +0000402 last = start;
403 addr = info->start[l_sect];
404
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200405 DEBUGF ("Start erase timeout: %d\n", CONFIG_SYS_FLASH_ERASE_TOUT);
wdenk452cfd62002-11-19 11:04:11 +0000406
407 while ((in8(addr) & 0x80) != 0x80) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200408 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenk874ac262003-07-24 23:38:38 +0000409 printf ("Timeout\n");
wdenk452cfd62002-11-19 11:04:11 +0000410 flash_reset (info->start[0]);
411 flash_to_mem();
412 return 1;
413 }
414 /* show that we're waiting */
415 if ((now - last) > 1000) { /* every second */
wdenk874ac262003-07-24 23:38:38 +0000416 putc ('.');
wdenk452cfd62002-11-19 11:04:11 +0000417 last = now;
418 }
419 iobarrier_rw();
420 }
421
422DONE:
423 /* reset to read mode */
424 flash_reset (info->start[0]);
425 flash_to_mem();
426
wdenk874ac262003-07-24 23:38:38 +0000427 printf (" done\n");
wdenk452cfd62002-11-19 11:04:11 +0000428 return 0;
429}
430
431/*
432 * Copy memory to flash, returns:
433 * 0 - OK
434 * 1 - write timeout
435 * 2 - Flash not erased
436 */
437int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
438{
439 ulong cp, wp, data;
440 int i, l, rc;
441 ulong out_cnt = 0;
442
443 flash_to_xd();
444
445 wp = (addr & ~3); /* get lower word aligned address */
446
447 /*
448 * handle unaligned start bytes
449 */
450 if ((l = addr - wp) != 0) {
451 data = 0;
452 for (i=0, cp=wp; i<l; ++i, ++cp) {
453 data = (data << 8) | (*(uchar *)cp);
454 }
455 for (; i<4 && cnt>0; ++i) {
456 data = (data << 8) | *src++;
457 --cnt;
458 ++cp;
459 }
460 for (; cnt==0 && i<4; ++i, ++cp) {
461 data = (data << 8) | (*(uchar *)cp);
462 }
463
464 if ((rc = write_word(info, wp, data)) != 0) {
wdenk57b2d802003-06-27 21:31:46 +0000465 flash_to_mem();
wdenk452cfd62002-11-19 11:04:11 +0000466 return (rc);
467 }
468 wp += 4;
469 }
470
wdenk874ac262003-07-24 23:38:38 +0000471 putc(219);
wdenk452cfd62002-11-19 11:04:11 +0000472
473 /*
474 * handle word aligned part
475 */
476 while (cnt >= 4) {
wdenk57b2d802003-06-27 21:31:46 +0000477 if (out_cnt>26214)
wdenk452cfd62002-11-19 11:04:11 +0000478 {
wdenk874ac262003-07-24 23:38:38 +0000479 putc(219);
wdenk452cfd62002-11-19 11:04:11 +0000480 out_cnt = 0;
481 }
482 data = 0;
483 for (i=0; i<4; ++i) {
484 data = (data << 8) | *src++;
485 }
486 if ((rc = write_word(info, wp, data)) != 0) {
487 flash_to_mem();
488 return (rc);
489 }
490 wp += 4;
491 cnt -= 4;
492 out_cnt += 4;
493 }
494
495 if (cnt == 0) {
496 flash_to_mem();
497 return (0);
498 }
499
500 /*
501 * handle unaligned tail bytes
502 */
503 data = 0;
504 for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
505 data = (data << 8) | *src++;
506 --cnt;
507 }
508 for (; i<4; ++i, ++cp) {
509 data = (data << 8) | (*(uchar *)cp);
510 }
511
512 flash_to_mem();
513 return (write_word(info, wp, data));
514}
515
516/*
517 * Write a word to Flash, returns:
518 * 0 - OK
519 * 1 - write timeout
520 * 2 - Flash not erased
521 */
522static int write_word (flash_info_t *info, ulong dest, ulong data)
523{
524 volatile ulong addr = info->start[0];
525 ulong start;
526 int i;
527
528 flash_to_xd();
529
530 /* Check if Flash is (sufficiently) erased */
531 if ((in32(dest) & data) != data) {
532 flash_to_mem();
533 return (2);
534 }
535
536 /* write each byte out */
537 for (i = 0; i < 4; i++) {
538 char *data_ch = (char *)&data;
539 int flag = disable_interrupts();
540
541 out8(addr + 0x555, 0xAA);
542 iobarrier_rw();
543 out8(addr + 0x2AA, 0x55);
544 iobarrier_rw();
545 out8(addr + 0x555, 0xA0);
546 iobarrier_rw();
547 out8(dest+i, data_ch[i]);
548 iobarrier_rw();
549
550 /* re-enable interrupts if necessary */
551 if (flag)
552 enable_interrupts();
553
554 /* data polling for D7 */
wdenk874ac262003-07-24 23:38:38 +0000555 start = get_timer (0);
wdenk452cfd62002-11-19 11:04:11 +0000556 while ((in8(dest+i) & 0x80) != (data_ch[i] & 0x80)) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200557 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenk452cfd62002-11-19 11:04:11 +0000558 flash_reset (addr);
559 flash_to_mem();
560 return (1);
561 }
562 iobarrier_rw();
563 }
564 }
565
566 flash_reset (addr);
567 flash_to_mem();
568 return (0);
569}
570
571/*
572 * Reset bank to read mode
573 */
574static void flash_reset (ulong addr)
575{
wdenk57b2d802003-06-27 21:31:46 +0000576 flash_to_xd();
wdenk452cfd62002-11-19 11:04:11 +0000577 out8(addr, 0xF0); /* reset bank */
578 iobarrier_rw();
579 flash_to_mem();
580}
581
582void flash_print_info (flash_info_t *info)
583{
584 int i;
585
586 if (info->flash_id == FLASH_UNKNOWN) {
wdenk874ac262003-07-24 23:38:38 +0000587 printf ("missing or unknown FLASH type\n");
wdenk452cfd62002-11-19 11:04:11 +0000588 return;
589 }
590
591 switch (info->flash_id & FLASH_VENDMASK) {
wdenk874ac262003-07-24 23:38:38 +0000592 case FLASH_MAN_AMD: printf ("AMD "); break;
593 case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
594 case FLASH_MAN_BM: printf ("BRIGHT MICRO "); break;
595 case FLASH_MAN_STM: printf ("SGS THOMSON "); break;
596 default: printf ("Unknown Vendor "); break;
wdenk452cfd62002-11-19 11:04:11 +0000597 }
598
599 switch (info->flash_id & FLASH_TYPEMASK) {
wdenk874ac262003-07-24 23:38:38 +0000600 case FLASH_AM040: printf ("29F040 or 29LV040 (4 Mbit, uniform sectors)\n");
wdenk452cfd62002-11-19 11:04:11 +0000601 break;
wdenk874ac262003-07-24 23:38:38 +0000602 case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
wdenk452cfd62002-11-19 11:04:11 +0000603 break;
wdenk874ac262003-07-24 23:38:38 +0000604 case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n");
wdenk452cfd62002-11-19 11:04:11 +0000605 break;
wdenk874ac262003-07-24 23:38:38 +0000606 case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
wdenk452cfd62002-11-19 11:04:11 +0000607 break;
wdenk874ac262003-07-24 23:38:38 +0000608 case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n");
wdenk452cfd62002-11-19 11:04:11 +0000609 break;
wdenk874ac262003-07-24 23:38:38 +0000610 case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
wdenk452cfd62002-11-19 11:04:11 +0000611 break;
wdenk874ac262003-07-24 23:38:38 +0000612 case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n");
wdenk452cfd62002-11-19 11:04:11 +0000613 break;
wdenk874ac262003-07-24 23:38:38 +0000614 case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
wdenk452cfd62002-11-19 11:04:11 +0000615 break;
wdenk874ac262003-07-24 23:38:38 +0000616 case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n");
wdenk452cfd62002-11-19 11:04:11 +0000617 break;
wdenk874ac262003-07-24 23:38:38 +0000618 default: printf ("Unknown Chip Type\n");
wdenk452cfd62002-11-19 11:04:11 +0000619 break;
620 }
621
622 if (info->size % 0x100000 == 0) {
wdenk874ac262003-07-24 23:38:38 +0000623 printf (" Size: %ld MB in %d Sectors\n",
wdenk452cfd62002-11-19 11:04:11 +0000624 info->size / 0x100000, info->sector_count);
625 } else if (info->size % 0x400 == 0) {
wdenk874ac262003-07-24 23:38:38 +0000626 printf (" Size: %ld KB in %d Sectors\n",
wdenk57b2d802003-06-27 21:31:46 +0000627 info->size / 0x400, info->sector_count);
wdenk452cfd62002-11-19 11:04:11 +0000628 } else {
wdenk874ac262003-07-24 23:38:38 +0000629 printf (" Size: %ld B in %d Sectors\n",
wdenk57b2d802003-06-27 21:31:46 +0000630 info->size, info->sector_count);
wdenk452cfd62002-11-19 11:04:11 +0000631 }
632
wdenk874ac262003-07-24 23:38:38 +0000633 printf (" Sector Start Addresses:");
wdenk452cfd62002-11-19 11:04:11 +0000634 for (i=0; i<info->sector_count; ++i) {
635 if ((i % 5) == 0)
wdenk874ac262003-07-24 23:38:38 +0000636 printf ("\n ");
637 printf (" %08lX%s",
wdenk452cfd62002-11-19 11:04:11 +0000638 info->start[i],
639 info->protect[i] ? " (RO)" : " "
640 );
641 }
wdenk874ac262003-07-24 23:38:38 +0000642 printf ("\n");
wdenk452cfd62002-11-19 11:04:11 +0000643}