blob: 75d7769b60a30754b33252991a8321bc4832807d [file] [log] [blame]
wdenkf4863a72004-02-07 01:27:10 +00001/*
2 * (C) Masami Komiya <mkomiya@sonare.it> 2004
3 *
4 * (C) Copyright 2001-2004
5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25
26#include <common.h>
Stefan Roeseb36df562010-09-09 19:18:00 +020027#include <asm/ppc4xx.h>
wdenkf4863a72004-02-07 01:27:10 +000028#include <asm/processor.h>
29
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020030flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
wdenkf4863a72004-02-07 01:27:10 +000031
32
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020033#ifdef CONFIG_SYS_FLASH_16BIT
wdenkf4863a72004-02-07 01:27:10 +000034#define FLASH_WORD_SIZE unsigned short
35#define FLASH_ID_MASK 0xFFFF
36#else
37#define FLASH_WORD_SIZE unsigned long
38#define FLASH_ID_MASK 0xFFFFFFFF
39#endif
40
41/*-----------------------------------------------------------------------
42 * Functions
43 */
44/* stolen from esteem192e/flash.c */
45ulong flash_get_size (volatile FLASH_WORD_SIZE * addr, flash_info_t * info);
46
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020047#ifndef CONFIG_SYS_FLASH_16BIT
wdenkf4863a72004-02-07 01:27:10 +000048static int write_word (flash_info_t * info, ulong dest, ulong data);
49#else
50static int write_short (flash_info_t * info, ulong dest, ushort data);
51#endif
52static void flash_get_offsets (ulong base, flash_info_t * info);
53
54
55/*-----------------------------------------------------------------------
56 */
57
58unsigned long flash_init (void)
59{
60 unsigned long size_b0, size_b1;
61 int i;
62 uint pbcr;
63 unsigned long base_b0, base_b1;
64
65 /* Init: no FLASHes known */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020066 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
wdenkf4863a72004-02-07 01:27:10 +000067 flash_info[i].flash_id = FLASH_UNKNOWN;
68 }
69
70 /* Static FLASH Bank configuration here - FIXME XXX */
71
72 size_b0 =
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020073 flash_get_size ((volatile FLASH_WORD_SIZE *) CONFIG_SYS_FLASH_BASE,
wdenkf4863a72004-02-07 01:27:10 +000074 &flash_info[0]);
75
76 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
77 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", size_b0, size_b0 << 20);
78 }
79
80 /* Only one bank */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020081 if (CONFIG_SYS_MAX_FLASH_BANKS == 1) {
wdenkf4863a72004-02-07 01:27:10 +000082 /* Setup offsets */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020083 flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
wdenkf4863a72004-02-07 01:27:10 +000084
85 /* Monitor protection ON by default */
86#if 0 /* sand: */
87 (void) flash_protect (FLAG_PROTECT_SET,
88 FLASH_BASE0_PRELIM - monitor_flash_len +
89 size_b0,
90 FLASH_BASE0_PRELIM - 1 + size_b0,
91 &flash_info[0]);
92#else
93 (void) flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020094 CONFIG_SYS_MONITOR_BASE,
95 CONFIG_SYS_MONITOR_BASE + monitor_flash_len -
wdenkf4863a72004-02-07 01:27:10 +000096 1, &flash_info[0]);
97#endif
98 size_b1 = 0;
99 flash_info[0].size = size_b0;
100 }
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200101#ifdef CONFIG_SYS_FLASH_BASE_2
wdenkf4863a72004-02-07 01:27:10 +0000102 /* 2 banks */
103 else {
104 size_b1 =
105 flash_get_size ((volatile FLASH_WORD_SIZE *)
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200106 CONFIG_SYS_FLASH_BASE_2, &flash_info[1]);
wdenkf4863a72004-02-07 01:27:10 +0000107
108 /* Re-do sizing to get full correct info */
109
110 if (size_b1) {
Stefan Roesed1c3b272009-09-09 16:25:29 +0200111 mtdcr (EBC0_CFGADDR, PB0CR);
112 pbcr = mfdcr (EBC0_CFGDATA);
113 mtdcr (EBC0_CFGADDR, PB0CR);
wdenkf4863a72004-02-07 01:27:10 +0000114 base_b1 = -size_b1;
115 pbcr = (pbcr & 0x0001ffff) | base_b1 |
116 (((size_b1 / 1024 / 1024) - 1) << 17);
Stefan Roesed1c3b272009-09-09 16:25:29 +0200117 mtdcr (EBC0_CFGDATA, pbcr);
118 /* printf("PB1CR = %x\n", pbcr); */
wdenkf4863a72004-02-07 01:27:10 +0000119 }
120
121 if (size_b0) {
Stefan Roesed1c3b272009-09-09 16:25:29 +0200122 mtdcr (EBC0_CFGADDR, PB1CR);
123 pbcr = mfdcr (EBC0_CFGDATA);
124 mtdcr (EBC0_CFGADDR, PB1CR);
wdenkf4863a72004-02-07 01:27:10 +0000125 base_b0 = base_b1 - size_b0;
126 pbcr = (pbcr & 0x0001ffff) | base_b0 |
127 (((size_b0 / 1024 / 1024) - 1) << 17);
Stefan Roesed1c3b272009-09-09 16:25:29 +0200128 mtdcr (EBC0_CFGDATA, pbcr);
129 /* printf("PB0CR = %x\n", pbcr); */
wdenkf4863a72004-02-07 01:27:10 +0000130 }
131
132 size_b0 =
133 flash_get_size ((volatile FLASH_WORD_SIZE *) base_b0,
134 &flash_info[0]);
135
136 flash_get_offsets (base_b0, &flash_info[0]);
137
138 /* monitor protection ON by default */
139#if 0 /* sand: */
140 (void) flash_protect (FLAG_PROTECT_SET,
141 FLASH_BASE0_PRELIM - monitor_flash_len +
142 size_b0,
143 FLASH_BASE0_PRELIM - 1 + size_b0,
144 &flash_info[0]);
145#else
146 (void) flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200147 CONFIG_SYS_MONITOR_BASE,
148 CONFIG_SYS_MONITOR_BASE + monitor_flash_len -
wdenkf4863a72004-02-07 01:27:10 +0000149 1, &flash_info[0]);
150#endif
151
152 if (size_b1) {
153 /* Re-do sizing to get full correct info */
154 size_b1 =
155 flash_get_size ((volatile FLASH_WORD_SIZE *)
156 base_b1, &flash_info[1]);
157
158 flash_get_offsets (base_b1, &flash_info[1]);
159
160 /* monitor protection ON by default */
161 (void) flash_protect (FLAG_PROTECT_SET,
162 base_b1 + size_b1 -
163 monitor_flash_len,
164 base_b1 + size_b1 - 1,
165 &flash_info[1]);
166 /* monitor protection OFF by default (one is enough) */
167 (void) flash_protect (FLAG_PROTECT_CLEAR,
168 base_b0 + size_b0 -
169 monitor_flash_len,
170 base_b0 + size_b0 - 1,
171 &flash_info[0]);
172 } else {
173 flash_info[1].flash_id = FLASH_UNKNOWN;
174 flash_info[1].sector_count = -1;
175 }
176
177 flash_info[0].size = size_b0;
178 flash_info[1].size = size_b1;
179 } /* else 2 banks */
180#endif
181 return (size_b0 + size_b1);
182}
183
184
185/*-----------------------------------------------------------------------
186 */
187
188static void flash_get_offsets (ulong base, flash_info_t * info)
189{
190 int i;
191
192 /* set up sector start adress table */
193 if ((info->flash_id & FLASH_TYPEMASK) == FLASH_28F320J3A ||
194 (info->flash_id & FLASH_TYPEMASK) == FLASH_28F640J3A ||
195 (info->flash_id & FLASH_TYPEMASK) == FLASH_28F128J3A) {
196 for (i = 0; i < info->sector_count; i++) {
197 info->start[i] =
198 base + (i * info->size / info->sector_count);
199 }
200 } else if (info->flash_id & FLASH_BTYPE) {
201 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
202
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200203#ifndef CONFIG_SYS_FLASH_16BIT
wdenkf4863a72004-02-07 01:27:10 +0000204 /* set sector offsets for bottom boot block type */
205 info->start[0] = base + 0x00000000;
206 info->start[1] = base + 0x00004000;
207 info->start[2] = base + 0x00008000;
208 info->start[3] = base + 0x0000C000;
209 info->start[4] = base + 0x00010000;
210 info->start[5] = base + 0x00014000;
211 info->start[6] = base + 0x00018000;
212 info->start[7] = base + 0x0001C000;
213 for (i = 8; i < info->sector_count; i++) {
214 info->start[i] =
215 base + (i * 0x00020000) - 0x000E0000;
216 }
217 } else {
218 /* set sector offsets for bottom boot block type */
219 info->start[0] = base + 0x00000000;
220 info->start[1] = base + 0x00008000;
221 info->start[2] = base + 0x0000C000;
222 info->start[3] = base + 0x00010000;
223 for (i = 4; i < info->sector_count; i++) {
224 info->start[i] =
225 base + (i * 0x00020000) - 0x00060000;
226 }
227 }
228#else
229 /* set sector offsets for bottom boot block type */
230 info->start[0] = base + 0x00000000;
231 info->start[1] = base + 0x00002000;
232 info->start[2] = base + 0x00004000;
233 info->start[3] = base + 0x00006000;
234 info->start[4] = base + 0x00008000;
235 info->start[5] = base + 0x0000A000;
236 info->start[6] = base + 0x0000C000;
237 info->start[7] = base + 0x0000E000;
238 for (i = 8; i < info->sector_count; i++) {
239 info->start[i] =
240 base + (i * 0x00010000) - 0x00070000;
241 }
242 } else {
243 /* set sector offsets for bottom boot block type */
244 info->start[0] = base + 0x00000000;
245 info->start[1] = base + 0x00004000;
246 info->start[2] = base + 0x00006000;
247 info->start[3] = base + 0x00008000;
248 for (i = 4; i < info->sector_count; i++) {
249 info->start[i] =
250 base + (i * 0x00010000) - 0x00030000;
251 }
252 }
253#endif
254 } else {
255 /* set sector offsets for top boot block type */
256 i = info->sector_count - 1;
257 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
258
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200259#ifndef CONFIG_SYS_FLASH_16BIT
wdenkf4863a72004-02-07 01:27:10 +0000260 info->start[i--] = base + info->size - 0x00004000;
261 info->start[i--] = base + info->size - 0x00008000;
262 info->start[i--] = base + info->size - 0x0000C000;
263 info->start[i--] = base + info->size - 0x00010000;
264 info->start[i--] = base + info->size - 0x00014000;
265 info->start[i--] = base + info->size - 0x00018000;
266 info->start[i--] = base + info->size - 0x0001C000;
267 for (; i >= 0; i--) {
268 info->start[i] = base + i * 0x00020000;
269 }
270
271 } else {
272
273 info->start[i--] = base + info->size - 0x00008000;
274 info->start[i--] = base + info->size - 0x0000C000;
275 info->start[i--] = base + info->size - 0x00010000;
276 for (; i >= 0; i--) {
277 info->start[i] = base + i * 0x00020000;
278 }
279 }
280#else
281 info->start[i--] = base + info->size - 0x00002000;
282 info->start[i--] = base + info->size - 0x00004000;
283 info->start[i--] = base + info->size - 0x00006000;
284 info->start[i--] = base + info->size - 0x00008000;
285 info->start[i--] = base + info->size - 0x0000A000;
286 info->start[i--] = base + info->size - 0x0000C000;
287 info->start[i--] = base + info->size - 0x0000E000;
288 for (; i >= 0; i--) {
289 info->start[i] = base + i * 0x00010000;
290 }
291
292 } else {
293
294 info->start[i--] = base + info->size - 0x00004000;
295 info->start[i--] = base + info->size - 0x00006000;
296 info->start[i--] = base + info->size - 0x00008000;
297 for (; i >= 0; i--) {
298 info->start[i] = base + i * 0x00010000;
299 }
300 }
301#endif
302 }
303
304
305}
306
307/*-----------------------------------------------------------------------
308 */
309
310void flash_print_info (flash_info_t * info)
311{
312 int i;
313 uchar *boottype;
314 uchar botboot[] = ", bottom boot sect)\n";
315 uchar topboot[] = ", top boot sector)\n";
316
317 if (info->flash_id == FLASH_UNKNOWN) {
318 printf ("missing or unknown FLASH type\n");
319 return;
320 }
321
322 switch (info->flash_id & FLASH_VENDMASK) {
323 case FLASH_MAN_AMD:
324 printf ("AMD ");
325 break;
326 case FLASH_MAN_FUJ:
327 printf ("FUJITSU ");
328 break;
329 case FLASH_MAN_SST:
330 printf ("SST ");
331 break;
332 case FLASH_MAN_STM:
333 printf ("STM ");
334 break;
335 case FLASH_MAN_INTEL:
336 printf ("INTEL ");
337 break;
338 default:
339 printf ("Unknown Vendor ");
340 break;
341 }
342
343 if (info->flash_id & 0x0001) {
344 boottype = botboot;
345 } else {
346 boottype = topboot;
347 }
348
349 switch (info->flash_id & FLASH_TYPEMASK) {
350 case FLASH_AM400B:
351 printf ("AM29LV400B (4 Mbit%s", boottype);
352 break;
353 case FLASH_AM400T:
354 printf ("AM29LV400T (4 Mbit%s", boottype);
355 break;
356 case FLASH_AM800B:
357 printf ("AM29LV800B (8 Mbit%s", boottype);
358 break;
359 case FLASH_AM800T:
360 printf ("AM29LV800T (8 Mbit%s", boottype);
361 break;
362 case FLASH_AM160B:
363 printf ("AM29LV160B (16 Mbit%s", boottype);
364 break;
365 case FLASH_AM160T:
366 printf ("AM29LV160T (16 Mbit%s", boottype);
367 break;
368 case FLASH_AM320B:
369 printf ("AM29LV320B (32 Mbit%s", boottype);
370 break;
371 case FLASH_AM320T:
372 printf ("AM29LV320T (32 Mbit%s", boottype);
373 break;
374 case FLASH_INTEL800B:
375 printf ("INTEL28F800B (8 Mbit%s", boottype);
376 break;
377 case FLASH_INTEL800T:
378 printf ("INTEL28F800T (8 Mbit%s", boottype);
379 break;
380 case FLASH_INTEL160B:
381 printf ("INTEL28F160B (16 Mbit%s", boottype);
382 break;
383 case FLASH_INTEL160T:
384 printf ("INTEL28F160T (16 Mbit%s", boottype);
385 break;
386 case FLASH_INTEL320B:
387 printf ("INTEL28F320B (32 Mbit%s", boottype);
388 break;
389 case FLASH_INTEL320T:
390 printf ("INTEL28F320T (32 Mbit%s", boottype);
391 break;
392
393#if 0 /* enable when devices are available */
394
395 case FLASH_INTEL640B:
396 printf ("INTEL28F640B (64 Mbit%s", boottype);
397 break;
398 case FLASH_INTEL640T:
399 printf ("INTEL28F640T (64 Mbit%s", boottype);
400 break;
401#endif
402 case FLASH_28F320J3A:
403 printf ("INTEL28F320J3A (32 Mbit%s", boottype);
404 break;
405 case FLASH_28F640J3A:
406 printf ("INTEL28F640J3A (64 Mbit%s", boottype);
407 break;
408 case FLASH_28F128J3A:
409 printf ("INTEL28F128J3A (128 Mbit%s", boottype);
410 break;
411
412 default:
413 printf ("Unknown Chip Type\n");
414 break;
415 }
416
417 printf (" Size: %ld MB in %d Sectors\n",
418 info->size >> 20, info->sector_count);
419
420 printf (" Sector Start Addresses:");
421 for (i = 0; i < info->sector_count; ++i) {
422 if ((i % 5) == 0)
423 printf ("\n ");
424 printf (" %08lX%s",
425 info->start[i], info->protect[i] ? " (RO)" : " ");
426 }
427 printf ("\n");
428 return;
429}
430
431
432/*-----------------------------------------------------------------------
433 */
434
435
436/*-----------------------------------------------------------------------
437 */
438
439/*
440 * The following code cannot be run from FLASH!
441 */
442ulong flash_get_size (volatile FLASH_WORD_SIZE * addr, flash_info_t * info)
443{
444 short i;
445 ulong base = (ulong) addr;
446 FLASH_WORD_SIZE value;
447
448 /* Write auto select command: read Manufacturer ID */
449
450
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200451#ifndef CONFIG_SYS_FLASH_16BIT
wdenkf4863a72004-02-07 01:27:10 +0000452
453 /*
454 * Note: if it is an AMD flash and the word at addr[0000]
455 * is 0x00890089 this routine will think it is an Intel
456 * flash device and may(most likely) cause trouble.
457 */
458
459 addr[0x0000] = 0x00900090;
460 if (addr[0x0000] != 0x00890089) {
461 addr[0x0555] = 0x00AA00AA;
462 addr[0x02AA] = 0x00550055;
463 addr[0x0555] = 0x00900090;
464#else
465
466 /*
467 * Note: if it is an AMD flash and the word at addr[0000]
468 * is 0x0089 this routine will think it is an Intel
469 * flash device and may(most likely) cause trouble.
470 */
471
472 addr[0x0000] = 0x0090;
473
474 if (addr[0x0000] != 0x0089) {
475 addr[0x0555] = 0x00AA;
476 addr[0x02AA] = 0x0055;
477 addr[0x0555] = 0x0090;
478#endif
479 }
480 value = addr[0];
481
482 switch (value) {
483 case (AMD_MANUFACT & FLASH_ID_MASK):
484 info->flash_id = FLASH_MAN_AMD;
485 break;
486 case (FUJ_MANUFACT & FLASH_ID_MASK):
487 info->flash_id = FLASH_MAN_FUJ;
488 break;
489 case (STM_MANUFACT & FLASH_ID_MASK):
490 info->flash_id = FLASH_MAN_STM;
491 break;
492 case (SST_MANUFACT & FLASH_ID_MASK):
493 info->flash_id = FLASH_MAN_SST;
494 break;
495 case (INTEL_MANUFACT & FLASH_ID_MASK):
496 info->flash_id = FLASH_MAN_INTEL;
497 break;
498 default:
499 info->flash_id = FLASH_UNKNOWN;
500 info->sector_count = 0;
501 info->size = 0;
502 return (0); /* no or unknown flash */
503
504 }
505
506 value = addr[1]; /* device ID */
507
508 switch (value) {
509
510 case (AMD_ID_LV400T & FLASH_ID_MASK):
511 info->flash_id += FLASH_AM400T;
512 info->sector_count = 11;
513 info->size = 0x00100000;
514 break; /* => 1 MB */
515
516 case (AMD_ID_LV400B & FLASH_ID_MASK):
517 info->flash_id += FLASH_AM400B;
518 info->sector_count = 11;
519 info->size = 0x00100000;
520 break; /* => 1 MB */
521
522 case (AMD_ID_LV800T & FLASH_ID_MASK):
523 info->flash_id += FLASH_AM800T;
524 info->sector_count = 19;
525 info->size = 0x00200000;
526 break; /* => 2 MB */
527
528 case (AMD_ID_LV800B & FLASH_ID_MASK):
529 info->flash_id += FLASH_AM800B;
530 info->sector_count = 19;
531 info->size = 0x00200000;
532 break; /* => 2 MB */
533
534 case (AMD_ID_LV160T & FLASH_ID_MASK):
535 info->flash_id += FLASH_AM160T;
536 info->sector_count = 35;
537 info->size = 0x00400000;
538 break; /* => 4 MB */
539
540 case (AMD_ID_LV160B & FLASH_ID_MASK):
541 info->flash_id += FLASH_AM160B;
542 info->sector_count = 35;
543 info->size = 0x00400000;
544 break; /* => 4 MB */
545#if 0 /* enable when device IDs are available */
546 case (AMD_ID_LV320T & FLASH_ID_MASK):
547 info->flash_id += FLASH_AM320T;
548 info->sector_count = 67;
549 info->size = 0x00800000;
550 break; /* => 8 MB */
551
552 case (AMD_ID_LV320B & FLASH_ID_MASK):
553 info->flash_id += FLASH_AM320B;
554 info->sector_count = 67;
555 info->size = 0x00800000;
556 break; /* => 8 MB */
557#endif
558
559 case (INTEL_ID_28F800B3T & FLASH_ID_MASK):
560 info->flash_id += FLASH_INTEL800T;
561 info->sector_count = 23;
562 info->size = 0x00200000;
563 break; /* => 2 MB */
564
565 case (INTEL_ID_28F800B3B & FLASH_ID_MASK):
566 info->flash_id += FLASH_INTEL800B;
567 info->sector_count = 23;
568 info->size = 0x00200000;
569 break; /* => 2 MB */
570
571 case (INTEL_ID_28F160B3T & FLASH_ID_MASK):
572 info->flash_id += FLASH_INTEL160T;
573 info->sector_count = 39;
574 info->size = 0x00400000;
575 break; /* => 4 MB */
576
577 case (INTEL_ID_28F160B3B & FLASH_ID_MASK):
578 info->flash_id += FLASH_INTEL160B;
579 info->sector_count = 39;
580 info->size = 0x00400000;
581 break; /* => 4 MB */
582
583 case (INTEL_ID_28F320B3T & FLASH_ID_MASK):
584 info->flash_id += FLASH_INTEL320T;
585 info->sector_count = 71;
586 info->size = 0x00800000;
587 break; /* => 8 MB */
588
589 case (INTEL_ID_28F320B3B & FLASH_ID_MASK):
590 info->flash_id += FLASH_AM320B;
591 info->sector_count = 71;
592 info->size = 0x00800000;
593 break; /* => 8 MB */
594
595#if 0 /* enable when devices are available */
596 case (INTEL_ID_28F320B3T & FLASH_ID_MASK):
597 info->flash_id += FLASH_INTEL320T;
598 info->sector_count = 135;
599 info->size = 0x01000000;
600 break; /* => 16 MB */
601
602 case (INTEL_ID_28F320B3B & FLASH_ID_MASK):
603 info->flash_id += FLASH_AM320B;
604 info->sector_count = 135;
605 info->size = 0x01000000;
606 break; /* => 16 MB */
607#endif
608 case (INTEL_ID_28F320J3A & FLASH_ID_MASK):
609 info->flash_id += FLASH_28F320J3A;
610 info->sector_count = 32;
611 info->size = 0x00400000;
612 break; /* => 32 MBit */
613 case (INTEL_ID_28F640J3A & FLASH_ID_MASK):
614 info->flash_id += FLASH_28F640J3A;
615 info->sector_count = 64;
616 info->size = 0x00800000;
617 break; /* => 64 MBit */
618 case (INTEL_ID_28F128J3A & FLASH_ID_MASK):
619 info->flash_id += FLASH_28F128J3A;
620 info->sector_count = 128;
621 info->size = 0x01000000;
622 break; /* => 128 MBit */
623
624 default:
625 /* FIXME */
626 info->flash_id = FLASH_UNKNOWN;
627 return (0); /* => no or unknown flash */
628 }
629
630 flash_get_offsets (base, info);
631
632 /* check for protected sectors */
633 for (i = 0; i < info->sector_count; i++) {
634 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
635 /* D0 = 1 if protected */
636 addr = (volatile FLASH_WORD_SIZE *) (info->start[i]);
637 info->protect[i] = addr[2] & 1;
638 }
639
640 /*
641 * Prevent writes to uninitialized FLASH.
642 */
643 if (info->flash_id != FLASH_UNKNOWN) {
644 addr = (volatile FLASH_WORD_SIZE *) info->start[0];
645 if ((info->flash_id & 0xFF00) == FLASH_MAN_INTEL) {
646 *addr = (0x00F000F0 & FLASH_ID_MASK); /* reset bank */
647 } else {
648 *addr = (0x00FF00FF & FLASH_ID_MASK); /* reset bank */
649 }
650 }
651
652 return (info->size);
653}
654
655
656/*-----------------------------------------------------------------------
657 */
658
659int flash_erase (flash_info_t * info, int s_first, int s_last)
660{
661
662 volatile FLASH_WORD_SIZE *addr =
663 (volatile FLASH_WORD_SIZE *) (info->start[0]);
664 int flag, prot, sect, l_sect, barf;
665 ulong start, now, last;
666 int rcode = 0;
667
668 if ((s_first < 0) || (s_first > s_last)) {
669 if (info->flash_id == FLASH_UNKNOWN) {
670 printf ("- missing\n");
671 } else {
672 printf ("- no sectors to erase\n");
673 }
674 return 1;
675 }
676
677 if ((info->flash_id == FLASH_UNKNOWN) ||
678 ((info->flash_id > FLASH_AMD_COMP) &&
679 ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL))) {
680 printf ("Can't erase unknown flash type - aborted\n");
681 return 1;
682 }
683
684 prot = 0;
685 for (sect = s_first; sect <= s_last; ++sect) {
686 if (info->protect[sect]) {
687 prot++;
688 }
689 }
690
691 if (prot) {
692 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
693 } else {
694 printf ("\n");
695 }
696
697 l_sect = -1;
698
699 /* Disable interrupts which might cause a timeout here */
700 flag = disable_interrupts ();
701 if (info->flash_id < FLASH_AMD_COMP) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200702#ifndef CONFIG_SYS_FLASH_16BIT
wdenkf4863a72004-02-07 01:27:10 +0000703 addr[0x0555] = 0x00AA00AA;
704 addr[0x02AA] = 0x00550055;
705 addr[0x0555] = 0x00800080;
706 addr[0x0555] = 0x00AA00AA;
707 addr[0x02AA] = 0x00550055;
708#else
709 addr[0x0555] = 0x00AA;
710 addr[0x02AA] = 0x0055;
711 addr[0x0555] = 0x0080;
712 addr[0x0555] = 0x00AA;
713 addr[0x02AA] = 0x0055;
714#endif
715 /* Start erase on unprotected sectors */
716 for (sect = s_first; sect <= s_last; sect++) {
717 if (info->protect[sect] == 0) { /* not protected */
718 addr = (volatile FLASH_WORD_SIZE *) (info->
719 start
720 [sect]);
721 addr[0] = (0x00300030 & FLASH_ID_MASK);
722 l_sect = sect;
723 }
724 }
725
726 /* re-enable interrupts if necessary */
727 if (flag)
728 enable_interrupts ();
729
730 /* wait at least 80us - let's wait 1 ms */
731 udelay (1000);
732
733 /*
734 * We wait for the last triggered sector
735 */
736 if (l_sect < 0)
737 goto DONE;
738
739 start = get_timer (0);
740 last = start;
741 addr = (volatile FLASH_WORD_SIZE *) (info->start[l_sect]);
742 while ((addr[0] & (0x00800080 & FLASH_ID_MASK)) !=
743 (0x00800080 & FLASH_ID_MASK)) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200744 if ((now = get_timer (start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenkf4863a72004-02-07 01:27:10 +0000745 printf ("Timeout\n");
746 return 1;
747 }
748 /* show that we're waiting */
749 if ((now - last) > 1000000) { /* every second */
750 serial_putc ('.');
751 last = now;
752 }
753 }
754
755 DONE:
756 /* reset to read mode */
757 addr = (volatile FLASH_WORD_SIZE *) info->start[0];
758 addr[0] = (0x00F000F0 & FLASH_ID_MASK); /* reset bank */
759 } else {
760
761
762 for (sect = s_first; sect <= s_last; sect++) {
763 if (info->protect[sect] == 0) { /* not protected */
764 barf = 0;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200765#ifndef CONFIG_SYS_FLASH_16BIT
wdenkf4863a72004-02-07 01:27:10 +0000766 addr = (vu_long *) (info->start[sect]);
767 addr[0] = 0x00500050;
768 addr[0] = 0x00200020;
769 addr[0] = 0x00D000D0;
770 while (!(addr[0] & 0x00800080)); /* wait for error or finish */
771 if (addr[0] & 0x003A003A) { /* check for error */
772 barf = addr[0] & 0x003A0000;
773 if (barf) {
774 barf >>= 16;
775 } else {
776 barf = addr[0] & 0x0000003A;
777 }
778 }
779#else
780 addr = (vu_short *) (info->start[sect]);
781 addr[0] = 0x0050; /* clear status register */
782 addr[0] = 0x0020;
783 addr[0] = 0x00D0;
784 while (!(addr[0] & 0x0080)); /* wait for error or finish */
785 if (addr[0] & 0x003A) /* check for error */
786 barf = addr[0] & 0x003A;
787#endif
788 if (barf) {
789 printf ("\nFlash error in sector at %lx\n", (unsigned long) addr);
790 if (barf & 0x0002)
791 printf ("Block locked, not erased.\n");
792 if ((barf & 0x0030) == 0x0030)
793 printf ("Command Sequence error.\n");
794 if ((barf & 0x0030) == 0x0020)
795 printf ("Block Erase error.\n");
796 if (barf & 0x0008)
797 printf ("Vpp Low error.\n");
798 rcode = 1;
799 } else
800 printf (".");
801 l_sect = sect;
802 }
803 addr = (volatile FLASH_WORD_SIZE *) info->start[0];
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200804#ifndef CONFIG_SYS_FLASH_16BIT
wdenkf4863a72004-02-07 01:27:10 +0000805 addr[0] = (0x00FF00FF & FLASH_ID_MASK); /* reset bank */
806#else
807 addr[0] = (0x00FF & FLASH_ID_MASK); /* reset bank */
808#endif
809 }
810
811 }
812 printf (" done\n");
813 return rcode;
814}
815
816/*-----------------------------------------------------------------------
817 */
818
819/*flash_info_t *addr2info (ulong addr)
820{
821 flash_info_t *info;
822 int i;
823
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200824 for (i=0, info=&flash_info[0]; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
wdenkf4863a72004-02-07 01:27:10 +0000825 if ((addr >= info->start[0]) &&
826 (addr < (info->start[0] + info->size)) ) {
827 return (info);
828 }
829 }
830
831 return (NULL);
832}
833*/
834/*-----------------------------------------------------------------------
835 * Copy memory to flash.
836 * Make sure all target addresses are within Flash bounds,
837 * and no protected sectors are hit.
838 * Returns:
839 * 0 - OK
840 * 1 - write timeout
841 * 2 - Flash not erased
842 * 4 - target range includes protected sectors
843 * 8 - target address not in Flash memory
844 */
845
846/*int flash_write (uchar *src, ulong addr, ulong cnt)
847{
848 int i;
849 ulong end = addr + cnt - 1;
850 flash_info_t *info_first = addr2info (addr);
851 flash_info_t *info_last = addr2info (end );
852 flash_info_t *info;
853
854 if (cnt == 0) {
855 return (0);
856 }
857
858 if (!info_first || !info_last) {
859 return (8);
860 }
861
862 for (info = info_first; info <= info_last; ++info) {
wdenkcd37d9e2004-02-10 00:03:41 +0000863 ulong b_end = info->start[0] + info->size;*/ /* bank end addr */
wdenkf4863a72004-02-07 01:27:10 +0000864/* short s_end = info->sector_count - 1;
865 for (i=0; i<info->sector_count; ++i) {
866 ulong e_addr = (i == s_end) ? b_end : info->start[i + 1];
867
868 if ((end >= info->start[i]) && (addr < e_addr) &&
869 (info->protect[i] != 0) ) {
870 return (4);
871 }
872 }
873 }
874
wdenkcd37d9e2004-02-10 00:03:41 +0000875*/ /* finally write data to flash */
wdenkf4863a72004-02-07 01:27:10 +0000876/* for (info = info_first; info <= info_last && cnt>0; ++info) {
877 ulong len;
878
879 len = info->start[0] + info->size - addr;
880 if (len > cnt)
881 len = cnt;
882 if ((i = write_buff(info, src, addr, len)) != 0) {
883 return (i);
884 }
885 cnt -= len;
886 addr += len;
887 src += len;
888 }
889 return (0);
890}
891*/
892/*-----------------------------------------------------------------------
893 * Copy memory to flash, returns:
894 * 0 - OK
895 * 1 - write timeout
896 * 2 - Flash not erased
897 */
898
899int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
900{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200901#ifndef CONFIG_SYS_FLASH_16BIT
wdenkf4863a72004-02-07 01:27:10 +0000902 ulong cp, wp, data;
903 int l;
904#else
905 ulong cp, wp;
906 ushort data;
907#endif
908 int i, rc;
909
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200910#ifndef CONFIG_SYS_FLASH_16BIT
wdenkf4863a72004-02-07 01:27:10 +0000911
912
913 wp = (addr & ~3); /* get lower word aligned address */
914
915 /*
916 * handle unaligned start bytes
917 */
918 if ((l = addr - wp) != 0) {
919 data = 0;
920 for (i = 0, cp = wp; i < l; ++i, ++cp) {
921 data = (data << 8) | (*(uchar *) cp);
922 }
923 for (; i < 4 && cnt > 0; ++i) {
924 data = (data << 8) | *src++;
925 --cnt;
926 ++cp;
927 }
928 for (; cnt == 0 && i < 4; ++i, ++cp) {
929 data = (data << 8) | (*(uchar *) cp);
930 }
931
932 if ((rc = write_word (info, wp, data)) != 0) {
933 return (rc);
934 }
935 wp += 4;
936 }
937
938 /*
939 * handle word aligned part
940 */
941 while (cnt >= 4) {
942 data = 0;
943 for (i = 0; i < 4; ++i) {
944 data = (data << 8) | *src++;
945 }
946 if ((rc = write_word (info, wp, data)) != 0) {
947 return (rc);
948 }
949 wp += 4;
950 cnt -= 4;
951 }
952
953 if (cnt == 0) {
954 return (0);
955 }
956
957 /*
958 * handle unaligned tail bytes
959 */
960 data = 0;
961 for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
962 data = (data << 8) | *src++;
963 --cnt;
964 }
965 for (; i < 4; ++i, ++cp) {
966 data = (data << 8) | (*(uchar *) cp);
967 }
968
969 return (write_word (info, wp, data));
970
971#else
972 wp = (addr & ~1); /* get lower word aligned address */
973
974 /*
975 * handle unaligned start byte
976 */
977 if (addr - wp) {
978 data = 0;
979 data = (data << 8) | *src++;
980 --cnt;
981 if ((rc = write_short (info, wp, data)) != 0) {
982 return (rc);
983 }
984 wp += 2;
985 }
986
987 /*
988 * handle word aligned part
989 */
990/* l = 0; used for debuging */
991 while (cnt >= 2) {
992 data = 0;
993 for (i = 0; i < 2; ++i) {
994 data = (data << 8) | *src++;
995 }
996
997/* if(!l){
998 printf("%x",data);
999 l = 1;
1000 } used for debuging */
1001
1002 if ((rc = write_short (info, wp, data)) != 0) {
1003 return (rc);
1004 }
1005 wp += 2;
1006 cnt -= 2;
1007 }
1008
1009 if (cnt == 0) {
1010 return (0);
1011 }
1012
1013 /*
1014 * handle unaligned tail bytes
1015 */
1016 data = 0;
1017 for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
1018 data = (data << 8) | *src++;
1019 --cnt;
1020 }
1021 for (; i < 2; ++i, ++cp) {
1022 data = (data << 8) | (*(uchar *) cp);
1023 }
1024
1025 return (write_short (info, wp, data));
1026
1027
1028#endif
1029}
1030
1031/*-----------------------------------------------------------------------
1032 * Write a word to Flash, returns:
1033 * 0 - OK
1034 * 1 - write timeout
1035 * 2 - Flash not erased
1036 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +02001037#ifndef CONFIG_SYS_FLASH_16BIT
wdenkf4863a72004-02-07 01:27:10 +00001038static int write_word (flash_info_t * info, ulong dest, ulong data)
1039{
1040 vu_long *addr = (vu_long *) (info->start[0]);
1041 ulong start, barf;
1042 int flag;
1043
1044#if defined (__MIPSEL__)
1045 data = cpu_to_be32 (data);
1046#endif
1047
1048 /* Check if Flash is (sufficiently) erased */
1049 if ((*((vu_long *) dest) & data) != data) {
1050 return (2);
1051 }
1052
1053 /* Disable interrupts which might cause a timeout here */
1054 flag = disable_interrupts ();
1055
1056 if (info->flash_id < FLASH_AMD_COMP) {
1057 /* AMD stuff */
1058 addr[0x0555] = 0x00AA00AA;
1059 addr[0x02AA] = 0x00550055;
1060 addr[0x0555] = 0x00A000A0;
1061 } else {
1062 /* intel stuff */
1063 *addr = 0x00400040;
1064 }
1065
1066 *((vu_long *) dest) = data;
1067
1068 /* re-enable interrupts if necessary */
1069 if (flag)
1070 enable_interrupts ();
1071
1072 /* data polling for D7 */
1073 start = get_timer (0);
1074
1075 if (info->flash_id < FLASH_AMD_COMP) {
1076
1077 while ((*((vu_long *) dest) & 0x00800080) !=
1078 (data & 0x00800080)) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +02001079 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenkf4863a72004-02-07 01:27:10 +00001080 printf ("timeout\n");
1081 return (1);
1082 }
1083 }
1084
1085 } else {
1086
1087 while (!(addr[0] & 0x00800080)) { /* wait for error or finish */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +02001088 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenkf4863a72004-02-07 01:27:10 +00001089 printf ("timeout\n");
1090 return (1);
1091 }
1092 }
1093
1094 if (addr[0] & 0x003A003A) { /* check for error */
1095 barf = addr[0] & 0x003A0000;
1096 if (barf) {
1097 barf >>= 16;
1098 } else {
1099 barf = addr[0] & 0x0000003A;
1100 }
1101 printf ("\nFlash write error at address %lx\n",
1102 (unsigned long) dest);
1103 if (barf & 0x0002)
1104 printf ("Block locked, not erased.\n");
1105 if (barf & 0x0010)
1106 printf ("Programming error.\n");
1107 if (barf & 0x0008)
1108 printf ("Vpp Low error.\n");
1109 return (2);
1110 }
1111
1112
1113 }
1114
1115 return (0);
1116}
1117
1118#else
1119
1120static int write_short (flash_info_t * info, ulong dest, ushort data)
1121{
1122 vu_short *addr = (vu_short *) (info->start[0]);
1123 ulong start, barf;
1124 int flag;
1125
1126#if defined (__MIPSEL__)
1127 data = cpu_to_be16 (data);
1128#endif
1129
1130 /* Check if Flash is (sufficiently) erased */
1131 if ((*((vu_short *) dest) & data) != data) {
1132 return (2);
1133 }
1134
1135 /* Disable interrupts which might cause a timeout here */
1136 flag = disable_interrupts ();
1137
1138 if (info->flash_id < FLASH_AMD_COMP) {
1139 /* AMD stuff */
1140 addr[0x0555] = 0x00AA;
1141 addr[0x02AA] = 0x0055;
1142 addr[0x0555] = 0x00A0;
1143 } else {
1144 /* intel stuff */
1145 *addr = 0x00D0;
1146 *addr = 0x0040;
1147 }
1148 *((vu_short *) dest) = data;
1149
1150 /* re-enable interrupts if necessary */
1151 if (flag)
1152 enable_interrupts ();
1153
1154 /* data polling for D7 */
1155 start = get_timer (0);
1156
1157 if (info->flash_id < FLASH_AMD_COMP) {
1158 /* AMD stuff */
1159 while ((*((vu_short *) dest) & 0x0080) != (data & 0x0080)) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +02001160 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenkf4863a72004-02-07 01:27:10 +00001161 return (1);
1162 }
1163 }
1164
1165 } else {
1166 /* intel stuff */
1167 while (!(addr[0] & 0x0080)) { /* wait for error or finish */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +02001168 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT)
wdenkf4863a72004-02-07 01:27:10 +00001169 return (1);
1170 }
1171
1172 if (addr[0] & 0x003A) { /* check for error */
1173 barf = addr[0] & 0x003A;
1174 printf ("\nFlash write error at address %lx\n",
1175 (unsigned long) dest);
1176 if (barf & 0x0002)
1177 printf ("Block locked, not erased.\n");
1178 if (barf & 0x0010)
1179 printf ("Programming error.\n");
1180 if (barf & 0x0008)
1181 printf ("Vpp Low error.\n");
1182 return (2);
1183 }
1184 *addr = 0x00B0;
1185 *addr = 0x0070;
1186 while (!(addr[0] & 0x0080)) { /* wait for error or finish */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +02001187 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT)
wdenkf4863a72004-02-07 01:27:10 +00001188 return (1);
1189 }
1190
1191 *addr = 0x00FF;
1192
1193 }
1194
1195 return (0);
1196
1197}
1198#endif