blob: b1fd6576f1ca727bef429c944f1d590f28ecbd28 [file] [log] [blame]
Marian Balakowicz6c5879f2006-06-30 16:30:46 +02001/*
2 * (C) Copyright 2006
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * (C) Copyright 2002 Jun Gu <jung@artesyncp.com>
6 * Add support for Am29F016D and dynamic switch setting.
7 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02008 * SPDX-License-Identifier: GPL-2.0+
Marian Balakowicz6c5879f2006-06-30 16:30:46 +02009 */
10
11/*
12 * Modified 4/5/2001
13 * Wait for completion of each sector erase command issued
14 * 4/5/2001
15 * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
16 */
17
18#include <common.h>
Stefan Roeseb36df562010-09-09 19:18:00 +020019#include <asm/ppc4xx.h>
Marian Balakowicz6c5879f2006-06-30 16:30:46 +020020#include <asm/processor.h>
Stefan Roeseb36df562010-09-09 19:18:00 +020021#include <asm/ppc440.h>
Marian Balakowicz6c5879f2006-06-30 16:30:46 +020022#include "yucca.h"
23
24#ifdef DEBUG
25#define DEBUGF(x...) printf(x)
26#else
27#define DEBUGF(x...)
28#endif /* DEBUG */
29
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020030flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
Marian Balakowicz6c5879f2006-06-30 16:30:46 +020031
32/*
33 * Mark big flash bank (16 bit instead of 8 bit access) in address with bit 0
34 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020035static unsigned long flash_addr_table[][CONFIG_SYS_MAX_FLASH_BANKS] = {
Marian Balakowicz6c5879f2006-06-30 16:30:46 +020036 {0xfff00000, 0xfff80000, 0xe7c00001}, /* 0:boot from small flash */
37 {0x00000000, 0x00000000, 0x00000000}, /* 1:boot from pci 66 */
38 {0x00000000, 0x00000000, 0x00000000}, /* 2:boot from nand flash */
39 {0xe7F00000, 0xe7F80000, 0xFFC00001}, /* 3:boot from big flash 33*/
40 {0xe7F00000, 0xe7F80000, 0xFFC00001}, /* 4:boot from big flash 66*/
41 {0x00000000, 0x00000000, 0x00000000}, /* 5:boot from */
42 {0x00000000, 0x00000000, 0x00000000}, /* 6:boot from pci 66 */
43 {0x00000000, 0x00000000, 0x00000000}, /* 7:boot from */
44 {0xfff00000, 0xfff80000, 0xe7c00001}, /* 8:boot from small flash */
45};
46
47/*
48 * include common flash code (for amcc boards)
49 */
50/*-----------------------------------------------------------------------
51 * Functions
52 */
53static int write_word(flash_info_t * info, ulong dest, ulong data);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020054#ifdef CONFIG_SYS_FLASH_2ND_16BIT_DEV
Marian Balakowicz6c5879f2006-06-30 16:30:46 +020055static int write_word_1(flash_info_t * info, ulong dest, ulong data);
56static int write_word_2(flash_info_t * info, ulong dest, ulong data);
57static int flash_erase_1(flash_info_t * info, int s_first, int s_last);
58static int flash_erase_2(flash_info_t * info, int s_first, int s_last);
59static ulong flash_get_size_1(vu_long * addr, flash_info_t * info);
60static ulong flash_get_size_2(vu_long * addr, flash_info_t * info);
61#endif
62
63void flash_print_info(flash_info_t * info)
64{
65 int i;
66 int k;
67 int size;
68 int erased;
69 volatile unsigned long *flash;
70
71 if (info->flash_id == FLASH_UNKNOWN) {
72 printf("missing or unknown FLASH type\n");
73 return;
74 }
75
76 switch (info->flash_id & FLASH_VENDMASK) {
77 case FLASH_MAN_AMD:
78 printf("AMD ");
79 break;
80 case FLASH_MAN_STM:
81 printf("STM ");
82 break;
83 case FLASH_MAN_FUJ:
84 printf("FUJITSU ");
85 break;
86 case FLASH_MAN_SST:
87 printf("SST ");
88 break;
89 case FLASH_MAN_MX:
90 printf("MIXC ");
91 break;
92 default:
93 printf("Unknown Vendor ");
94 break;
95 }
96
97 switch (info->flash_id & FLASH_TYPEMASK) {
98 case FLASH_AM040:
99 printf("AM29F040 (512 Kbit, uniform sector size)\n");
100 break;
101 case FLASH_AM400B:
102 printf("AM29LV400B (4 Mbit, bottom boot sect)\n");
103 break;
104 case FLASH_AM400T:
105 printf("AM29LV400T (4 Mbit, top boot sector)\n");
106 break;
107 case FLASH_AM800B:
108 printf("AM29LV800B (8 Mbit, bottom boot sect)\n");
109 break;
110 case FLASH_AM800T:
111 printf("AM29LV800T (8 Mbit, top boot sector)\n");
112 break;
113 case FLASH_AMD016:
114 printf("AM29F016D (16 Mbit, uniform sector size)\n");
115 break;
116 case FLASH_AM160B:
117 printf("AM29LV160B (16 Mbit, bottom boot sect)\n");
118 break;
119 case FLASH_AM160T:
120 printf("AM29LV160T (16 Mbit, top boot sector)\n");
121 break;
122 case FLASH_AM320B:
123 printf("AM29LV320B (32 Mbit, bottom boot sect)\n");
124 break;
125 case FLASH_AM320T:
126 printf("AM29LV320T (32 Mbit, top boot sector)\n");
127 break;
128 case FLASH_AM033C:
129 printf("AM29LV033C (32 Mbit, top boot sector)\n");
130 break;
131 case FLASH_SST800A:
132 printf("SST39LF/VF800 (8 Mbit, uniform sector size)\n");
133 break;
134 case FLASH_SST160A:
135 printf("SST39LF/VF160 (16 Mbit, uniform sector size)\n");
136 break;
137 case FLASH_STMW320DT:
138 printf ("M29W320DT (32 M, top sector)\n");
139 break;
140 case FLASH_MXLV320T:
141 printf ("MXLV320T (32 Mbit, top sector)\n");
142 break;
143 default:
144 printf("Unknown Chip Type\n");
145 break;
146 }
147
148 printf(" Size: %ld KB in %d Sectors\n",
149 info->size >> 10, info->sector_count);
150
151 printf(" Sector Start Addresses:");
152 for (i = 0; i < info->sector_count; ++i) {
153 /*
154 * Check if whole sector is erased
155 */
156 if (i != (info->sector_count - 1))
157 size = info->start[i + 1] - info->start[i];
158 else
159 size = info->start[0] + info->size - info->start[i];
160 erased = 1;
161 flash = (volatile unsigned long *)info->start[i];
162 size = size >> 2; /* divide by 4 for longword access */
163 for (k = 0; k < size; k++) {
164 if (*flash++ != 0xffffffff) {
165 erased = 0;
166 break;
167 }
168 }
169
170 if ((i % 5) == 0)
171 printf("\n ");
172 printf(" %08lX%s%s",
173 info->start[i],
174 erased ? " E" : " ",
175 info->protect[i] ? "RO " : " ");
176 }
177 printf("\n");
178 return;
179}
180
181
182/*
183 * The following code cannot be run from FLASH!
184 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200185#ifdef CONFIG_SYS_FLASH_2ND_16BIT_DEV
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200186static ulong flash_get_size(vu_long * addr, flash_info_t * info)
187{
188 /* bit 0 used for big flash marking */
189 if ((ulong)addr & 0x1)
190 return flash_get_size_2((vu_long *)((ulong)addr & 0xfffffffe), info);
191 else
192 return flash_get_size_1(addr, info);
193}
194
195static ulong flash_get_size_1(vu_long * addr, flash_info_t * info)
196#else
197static ulong flash_get_size(vu_long * addr, flash_info_t * info)
198#endif
199{
200 short i;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200201 CONFIG_SYS_FLASH_WORD_SIZE value;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200202 ulong base = (ulong) addr;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200203 volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) addr;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200204
205 DEBUGF("FLASH ADDR: %08x\n", (unsigned)addr);
206
207 /* Write auto select command: read Manufacturer ID */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200208 addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
209 addr2[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
210 addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00900090;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200211 udelay(1000);
212
213 value = addr2[0];
214 DEBUGF("FLASH MANUFACT: %x\n", value);
215
216 switch (value) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200217 case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_MANUFACT:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200218 info->flash_id = FLASH_MAN_AMD;
219 break;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200220 case (CONFIG_SYS_FLASH_WORD_SIZE) FUJ_MANUFACT:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200221 info->flash_id = FLASH_MAN_FUJ;
222 break;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200223 case (CONFIG_SYS_FLASH_WORD_SIZE) SST_MANUFACT:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200224 info->flash_id = FLASH_MAN_SST;
225 break;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200226 case (CONFIG_SYS_FLASH_WORD_SIZE) STM_MANUFACT:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200227 info->flash_id = FLASH_MAN_STM;
228 break;
229 default:
230 info->flash_id = FLASH_UNKNOWN;
231 info->sector_count = 0;
232 info->size = 0;
233 return (0); /* no or unknown flash */
234 }
235
236 value = addr2[1]; /* device ID */
237 DEBUGF("\nFLASH DEVICEID: %x\n", value);
238
239 switch (value) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200240 case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV040B:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200241 info->flash_id += FLASH_AM040;
242 info->sector_count = 8;
243 info->size = 0x0080000; /* => 512 ko */
244 break;
245
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200246 case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_F040B:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200247 info->flash_id += FLASH_AM040;
248 info->sector_count = 8;
249 info->size = 0x0080000; /* => 512 ko */
250 break;
251
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200252 case (CONFIG_SYS_FLASH_WORD_SIZE) STM_ID_M29W040B:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200253 info->flash_id += FLASH_AM040;
254 info->sector_count = 8;
255 info->size = 0x0080000; /* => 512 ko */
256 break;
257
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200258 case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_F016D:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200259 info->flash_id += FLASH_AMD016;
260 info->sector_count = 32;
261 info->size = 0x00200000;
262 break; /* => 2 MB */
263
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200264 case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV033C:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200265 info->flash_id += FLASH_AMDLV033C;
266 info->sector_count = 64;
267 info->size = 0x00400000;
268 break; /* => 4 MB */
269
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200270 case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV400T:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200271 info->flash_id += FLASH_AM400T;
272 info->sector_count = 11;
273 info->size = 0x00080000;
274 break; /* => 0.5 MB */
275
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200276 case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV400B:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200277 info->flash_id += FLASH_AM400B;
278 info->sector_count = 11;
279 info->size = 0x00080000;
280 break; /* => 0.5 MB */
281
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200282 case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV800T:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200283 info->flash_id += FLASH_AM800T;
284 info->sector_count = 19;
285 info->size = 0x00100000;
286 break; /* => 1 MB */
287
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200288 case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV800B:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200289 info->flash_id += FLASH_AM800B;
290 info->sector_count = 19;
291 info->size = 0x00100000;
292 break; /* => 1 MB */
293
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200294 case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV160T:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200295 info->flash_id += FLASH_AM160T;
296 info->sector_count = 35;
297 info->size = 0x00200000;
298 break; /* => 2 MB */
299
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200300 case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV160B:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200301 info->flash_id += FLASH_AM160B;
302 info->sector_count = 35;
303 info->size = 0x00200000;
304 break; /* => 2 MB */
305
306 default:
307 info->flash_id = FLASH_UNKNOWN;
308 return (0); /* => no or unknown flash */
309 }
310
311 /* set up sector start address table */
312 if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
313 ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) ||
314 ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMD016)) {
315 for (i = 0; i < info->sector_count; i++)
316 info->start[i] = base + (i * 0x00010000);
317 } else {
318 if (info->flash_id & FLASH_BTYPE) {
319 /* set sector offsets for bottom boot block type */
320 info->start[0] = base + 0x00000000;
321 info->start[1] = base + 0x00004000;
322 info->start[2] = base + 0x00006000;
323 info->start[3] = base + 0x00008000;
324 for (i = 4; i < info->sector_count; i++) {
325 info->start[i] =
326 base + (i * 0x00010000) - 0x00030000;
327 }
328 } else {
329 /* set sector offsets for top boot block type */
330 i = info->sector_count - 1;
331 info->start[i--] = base + info->size - 0x00004000;
332 info->start[i--] = base + info->size - 0x00006000;
333 info->start[i--] = base + info->size - 0x00008000;
334 for (; i >= 0; i--) {
335 info->start[i] = base + i * 0x00010000;
336 }
337 }
338 }
339
340 /* check for protected sectors */
341 for (i = 0; i < info->sector_count; i++) {
342 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
343 /* D0 = 1 if protected */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200344 addr2 = (volatile CONFIG_SYS_FLASH_WORD_SIZE *)(info->start[i]);
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200345
346 /* For AMD29033C flash we need to resend the command of *
347 * reading flash protection for upper 8 Mb of flash */
348 if (i == 32) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200349 addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xAAAAAAAA;
350 addr2[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x55555555;
351 addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x90909090;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200352 }
353
354 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST)
355 info->protect[i] = 0;
356 else
357 info->protect[i] = addr2[2] & 1;
358 }
359
360 /* issue bank reset to return to read mode */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200361 addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00F000F0;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200362
363 return (info->size);
364}
365
366static int wait_for_DQ7_1(flash_info_t * info, int sect)
367{
368 ulong start, now, last;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200369 volatile CONFIG_SYS_FLASH_WORD_SIZE *addr =
370 (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[sect]);
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200371
372 start = get_timer(0);
373 last = start;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200374 while ((addr[0] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080) !=
375 (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080) {
376 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200377 printf("Timeout\n");
378 return -1;
379 }
380 /* show that we're waiting */
381 if ((now - last) > 1000) { /* every second */
382 putc('.');
383 last = now;
384 }
385 }
386 return 0;
387}
388
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200389#ifdef CONFIG_SYS_FLASH_2ND_16BIT_DEV
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200390int flash_erase(flash_info_t * info, int s_first, int s_last)
391{
392 if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) ||
393 ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) ||
394 ((info->flash_id & FLASH_TYPEMASK) == FLASH_STMW320DT) ||
395 ((info->flash_id & FLASH_TYPEMASK) == FLASH_MXLV320T)) {
396 return flash_erase_2(info, s_first, s_last);
397 } else {
398 return flash_erase_1(info, s_first, s_last);
399 }
400}
401
402static int flash_erase_1(flash_info_t * info, int s_first, int s_last)
403#else
404int flash_erase(flash_info_t * info, int s_first, int s_last)
405#endif
406{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200407 volatile CONFIG_SYS_FLASH_WORD_SIZE *addr = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[0]);
408 volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2;
Wolfgang Denk2975fe12011-11-17 09:50:00 +0000409 int flag, prot, sect;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200410 int i;
411
412 if ((s_first < 0) || (s_first > s_last)) {
413 if (info->flash_id == FLASH_UNKNOWN)
414 printf("- missing\n");
415 else
416 printf("- no sectors to erase\n");
417 return 1;
418 }
419
420 if (info->flash_id == FLASH_UNKNOWN) {
421 printf("Can't erase unknown flash type - aborted\n");
422 return 1;
423 }
424
425 prot = 0;
426 for (sect = s_first; sect <= s_last; ++sect) {
427 if (info->protect[sect])
428 prot++;
429 }
430
431 if (prot)
432 printf("- Warning: %d protected sectors will not be erased!", prot);
433
434 printf("\n");
435
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200436 /* Disable interrupts which might cause a timeout here */
437 flag = disable_interrupts();
438
439 /* Start erase on unprotected sectors */
440 for (sect = s_first; sect <= s_last; sect++) {
441 if (info->protect[sect] == 0) { /* not protected */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200442 addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[sect]);
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200443
444 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200445 addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
446 addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
447 addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080;
448 addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
449 addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
450 addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00500050; /* block erase */
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200451 for (i = 0; i < 50; i++)
452 udelay(1000); /* wait 1 ms */
453 } else {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200454 addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
455 addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
456 addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080;
457 addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
458 addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
459 addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00300030; /* sector erase */
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200460 }
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200461 /*
462 * Wait for each sector to complete, it's more
463 * reliable. According to AMD Spec, you must
464 * issue all erase commands within a specified
465 * timeout. This has been seen to fail, especially
466 * if printf()s are included (for debug)!!
467 */
468 wait_for_DQ7_1(info, sect);
469 }
470 }
471
472 /* re-enable interrupts if necessary */
473 if (flag)
474 enable_interrupts();
475
476 /* wait at least 80us - let's wait 1 ms */
477 udelay(1000);
478
479 /* reset to read mode */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200480 addr = (CONFIG_SYS_FLASH_WORD_SIZE *) info->start[0];
481 addr[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200482
483 printf(" done\n");
484 return 0;
485}
486
487/*-----------------------------------------------------------------------
488 * Copy memory to flash, returns:
489 * 0 - OK
490 * 1 - write timeout
491 * 2 - Flash not erased
492 */
493int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
494{
495 ulong cp, wp, data;
496 int i, l, rc;
497
498 wp = (addr & ~3); /* get lower word aligned address */
499
500 /*
501 * handle unaligned start bytes
502 */
503 if ((l = addr - wp) != 0) {
504 data = 0;
505 for (i = 0, cp = wp; i < l; ++i, ++cp)
506 data = (data << 8) | (*(uchar *) cp);
507
508 for (; i < 4 && cnt > 0; ++i) {
509 data = (data << 8) | *src++;
510 --cnt;
511 ++cp;
512 }
513
514 for (; cnt == 0 && i < 4; ++i, ++cp)
515 data = (data << 8) | (*(uchar *) cp);
516
517 if ((rc = write_word(info, wp, data)) != 0)
518 return (rc);
519
520 wp += 4;
521 }
522
523 /*
524 * handle word aligned part
525 */
526 while (cnt >= 4) {
527 data = 0;
528 for (i = 0; i < 4; ++i)
529 data = (data << 8) | *src++;
530
531 if ((rc = write_word(info, wp, data)) != 0)
532 return (rc);
533
534 wp += 4;
535 cnt -= 4;
536 }
537
538 if (cnt == 0)
539 return (0);
540
541 /*
542 * handle unaligned tail bytes
543 */
544 data = 0;
545 for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
546 data = (data << 8) | *src++;
547 --cnt;
548 }
549 for (; i < 4; ++i, ++cp)
550 data = (data << 8) | (*(uchar *) cp);
551
552 return (write_word(info, wp, data));
553}
554
555/*-----------------------------------------------------------------------
556 * Copy memory to flash, returns:
557 * 0 - OK
558 * 1 - write timeout
559 * 2 - Flash not erased
560 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200561#ifdef CONFIG_SYS_FLASH_2ND_16BIT_DEV
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200562static int write_word(flash_info_t * info, ulong dest, ulong data)
563{
564 if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) ||
565 ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) ||
566 ((info->flash_id & FLASH_TYPEMASK) == FLASH_STMW320DT) ||
567 ((info->flash_id & FLASH_TYPEMASK) == FLASH_MXLV320T)) {
568 return write_word_2(info, dest, data);
569 } else {
570 return write_word_1(info, dest, data);
571 }
572}
573
574static int write_word_1(flash_info_t * info, ulong dest, ulong data)
575#else
576static int write_word(flash_info_t * info, ulong dest, ulong data)
577#endif
578{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200579 volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[0]);
580 volatile CONFIG_SYS_FLASH_WORD_SIZE *dest2 = (CONFIG_SYS_FLASH_WORD_SIZE *) dest;
581 volatile CONFIG_SYS_FLASH_WORD_SIZE *data2 = (CONFIG_SYS_FLASH_WORD_SIZE *) & data;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200582 ulong start;
583 int i, flag;
584
585 /* Check if Flash is (sufficiently) erased */
586 if ((*((vu_long *)dest) & data) != data)
587 return (2);
588
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200589 for (i = 0; i < 4 / sizeof(CONFIG_SYS_FLASH_WORD_SIZE); i++) {
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200590 /* Disable interrupts which might cause a timeout here */
591 flag = disable_interrupts();
592
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200593 addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
594 addr2[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
595 addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00A000A0;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200596
597 dest2[i] = data2[i];
598
599 /* re-enable interrupts if necessary */
600 if (flag)
601 enable_interrupts();
602
603 /* data polling for D7 */
604 start = get_timer(0);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200605 while ((dest2[i] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080) !=
606 (data2[i] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080)) {
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200607
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200608 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT)
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200609 return (1);
610 }
611 }
612
613 return (0);
614}
615
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200616#ifdef CONFIG_SYS_FLASH_2ND_16BIT_DEV
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200617
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200618#undef CONFIG_SYS_FLASH_WORD_SIZE
619#define CONFIG_SYS_FLASH_WORD_SIZE unsigned short
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200620
621/*
622 * The following code cannot be run from FLASH!
623 */
624static ulong flash_get_size_2(vu_long * addr, flash_info_t * info)
625{
626 short i;
627 int n;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200628 CONFIG_SYS_FLASH_WORD_SIZE value;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200629 ulong base = (ulong) addr;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200630 volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) addr;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200631
632 DEBUGF("FLASH ADDR: %08x\n", (unsigned)addr);
633
634 /* issue bank reset to return to read mode */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200635 addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00F000F0;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200636 /* Write auto select command: read Manufacturer ID */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200637 addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
638 addr2[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
639 addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00900090;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200640 udelay(1000);
641
642 value = addr2[0];
643 DEBUGF("FLASH MANUFACT: %x\n", value);
644
645 switch (value) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200646 case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_MANUFACT:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200647 info->flash_id = FLASH_MAN_AMD;
648 break;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200649 case (CONFIG_SYS_FLASH_WORD_SIZE) FUJ_MANUFACT:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200650 info->flash_id = FLASH_MAN_FUJ;
651 break;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200652 case (CONFIG_SYS_FLASH_WORD_SIZE) SST_MANUFACT:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200653 info->flash_id = FLASH_MAN_SST;
654 break;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200655 case (CONFIG_SYS_FLASH_WORD_SIZE) STM_MANUFACT:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200656 info->flash_id = FLASH_MAN_STM;
657 break;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200658 case (CONFIG_SYS_FLASH_WORD_SIZE) MX_MANUFACT:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200659 info->flash_id = FLASH_MAN_MX;
660 break;
661 default:
662 info->flash_id = FLASH_UNKNOWN;
663 info->sector_count = 0;
664 info->size = 0;
665 return (0); /* no or unknown flash */
666 }
667
668 value = addr2[1]; /* device ID */
669 DEBUGF("\nFLASH DEVICEID: %x\n", value);
670
671 switch (value) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200672 case (CONFIG_SYS_FLASH_WORD_SIZE)AMD_ID_LV320T:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200673 info->flash_id += FLASH_AM320T;
674 info->sector_count = 71;
675 info->size = 0x00400000;
676 break; /* => 4 MB */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200677 case (CONFIG_SYS_FLASH_WORD_SIZE)AMD_ID_LV320B:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200678 info->flash_id += FLASH_AM320B;
679 info->sector_count = 71;
680 info->size = 0x00400000;
681 break; /* => 4 MB */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200682 case (CONFIG_SYS_FLASH_WORD_SIZE)STM_ID_29W320DT:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200683 info->flash_id += FLASH_STMW320DT;
684 info->sector_count = 67;
685 info->size = 0x00400000;
686 break; /* => 4 MB */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200687 case (CONFIG_SYS_FLASH_WORD_SIZE)MX_ID_LV320T:
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200688 info->flash_id += FLASH_MXLV320T;
689 info->sector_count = 71;
690 info->size = 0x00400000;
691 break; /* => 4 MB */
692 default:
693 info->flash_id = FLASH_UNKNOWN;
694 return (0); /* => no or unknown flash */
695 }
696
697 /* set up sector start address table */
698 if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
699 ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) ||
700 ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMD016)) {
701 for (i = 0; i < info->sector_count; i++)
702 info->start[i] = base + (i * 0x00010000);
703 } else if ((info->flash_id & FLASH_TYPEMASK) == FLASH_STMW320DT) {
704 /* set sector offsets for top boot block type */
705 base += info->size;
706 i = info->sector_count;
707 /* 1 x 16k boot sector */
708 base -= 16 << 10;
709 --i;
710 info->start[i] = base;
711 /* 2 x 8k boot sectors */
712 for (n = 0; n < 2; ++n) {
713 base -= 8 << 10;
714 --i;
715 info->start[i] = base;
716 }
717 /* 1 x 32k boot sector */
718 base -= 32 << 10;
719 --i;
720 info->start[i] = base;
721
722 while (i > 0) { /* 64k regular sectors */
723 base -= 64 << 10;
724 --i;
725 info->start[i] = base;
726 }
727 } else if ((info->flash_id & FLASH_TYPEMASK) == FLASH_MXLV320T) {
728 i = info->sector_count - 1;
729 info->start[i--] = base + info->size - 0x00002000;
730 info->start[i--] = base + info->size - 0x00004000;
731 info->start[i--] = base + info->size - 0x00006000;
732 info->start[i--] = base + info->size - 0x00008000;
733 info->start[i--] = base + info->size - 0x0000a000;
734 info->start[i--] = base + info->size - 0x0000c000;
735 info->start[i--] = base + info->size - 0x0000e000;
736 info->start[i--] = base + info->size - 0x00010000;
737
738 for (; i >= 0; i--)
739 info->start[i] = base + i * 0x00010000;
740 } else {
741 if (info->flash_id & FLASH_BTYPE) {
742 /* set sector offsets for bottom boot block type */
743 info->start[0] = base + 0x00000000;
744 info->start[1] = base + 0x00004000;
745 info->start[2] = base + 0x00006000;
746 info->start[3] = base + 0x00008000;
747
748 for (i = 4; i < info->sector_count; i++)
749 info->start[i] = base + (i * 0x00010000) - 0x00030000;
750 } else {
751 /* set sector offsets for top boot block type */
752 i = info->sector_count - 1;
753 info->start[i--] = base + info->size - 0x00004000;
754 info->start[i--] = base + info->size - 0x00006000;
755 info->start[i--] = base + info->size - 0x00008000;
756
757 for (; i >= 0; i--)
758 info->start[i] = base + i * 0x00010000;
759 }
760 }
761
762 /* check for protected sectors */
763 for (i = 0; i < info->sector_count; i++) {
764 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
765 /* D0 = 1 if protected */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200766 addr2 = (volatile CONFIG_SYS_FLASH_WORD_SIZE *)(info->start[i]);
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200767
768 /* For AMD29033C flash we need to resend the command of *
769 * reading flash protection for upper 8 Mb of flash */
770 if (i == 32) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200771 addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xAAAAAAAA;
772 addr2[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x55555555;
773 addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x90909090;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200774 }
775
776 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST)
777 info->protect[i] = 0;
778 else
779 info->protect[i] = addr2[2] & 1;
780 }
781
782 /* issue bank reset to return to read mode */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200783 addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00F000F0;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200784
785 return (info->size);
786}
787
788static int wait_for_DQ7_2(flash_info_t * info, int sect)
789{
790 ulong start, now, last;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200791 volatile CONFIG_SYS_FLASH_WORD_SIZE *addr =
792 (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[sect]);
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200793
794 start = get_timer(0);
795 last = start;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200796 while ((addr[0] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080) !=
797 (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080) {
798 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200799 printf("Timeout\n");
800 return -1;
801 }
802 /* show that we're waiting */
803 if ((now - last) > 1000) { /* every second */
804 putc('.');
805 last = now;
806 }
807 }
808 return 0;
809}
810
811static int flash_erase_2(flash_info_t * info, int s_first, int s_last)
812{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200813 volatile CONFIG_SYS_FLASH_WORD_SIZE *addr = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[0]);
814 volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2;
Wolfgang Denk2975fe12011-11-17 09:50:00 +0000815 int flag, prot, sect;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200816 int i;
817
818 if ((s_first < 0) || (s_first > s_last)) {
819 if (info->flash_id == FLASH_UNKNOWN)
820 printf("- missing\n");
821 else
822 printf("- no sectors to erase\n");
823 return 1;
824 }
825
826 if (info->flash_id == FLASH_UNKNOWN) {
827 printf("Can't erase unknown flash type - aborted\n");
828 return 1;
829 }
830
831 prot = 0;
832 for (sect = s_first; sect <= s_last; ++sect) {
833 if (info->protect[sect])
834 prot++;
835 }
836
837 if (prot)
838 printf("- Warning: %d protected sectors will not be erased!", prot);
839
840 printf("\n");
841
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200842 /* Disable interrupts which might cause a timeout here */
843 flag = disable_interrupts();
844
845 /* Start erase on unprotected sectors */
846 for (sect = s_first; sect <= s_last; sect++) {
847 if (info->protect[sect] == 0) { /* not protected */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200848 addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[sect]);
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200849
850 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200851 addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
852 addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
853 addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080;
854 addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
855 addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
856 addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00500050; /* block erase */
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200857 for (i = 0; i < 50; i++)
858 udelay(1000); /* wait 1 ms */
859 } else {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200860 addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
861 addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
862 addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080;
863 addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
864 addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
865 addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00300030; /* sector erase */
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200866 }
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200867 /*
868 * Wait for each sector to complete, it's more
869 * reliable. According to AMD Spec, you must
870 * issue all erase commands within a specified
871 * timeout. This has been seen to fail, especially
872 * if printf()s are included (for debug)!!
873 */
874 wait_for_DQ7_2(info, sect);
875 }
876 }
877
878 /* re-enable interrupts if necessary */
879 if (flag)
880 enable_interrupts();
881
882 /* wait at least 80us - let's wait 1 ms */
883 udelay(1000);
884
885 /* reset to read mode */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200886 addr = (CONFIG_SYS_FLASH_WORD_SIZE *) info->start[0];
887 addr[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200888
889 printf(" done\n");
890 return 0;
891}
892
893static int write_word_2(flash_info_t * info, ulong dest, ulong data)
894{
Wolfgang Denk70fb8092009-09-11 11:47:07 +0200895 ulong *data_ptr = &data;
896 volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *)(info->start[0]);
897 volatile CONFIG_SYS_FLASH_WORD_SIZE *dest2 = (CONFIG_SYS_FLASH_WORD_SIZE *)dest;
898 volatile CONFIG_SYS_FLASH_WORD_SIZE *data2 = (CONFIG_SYS_FLASH_WORD_SIZE *)data_ptr;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200899 ulong start;
900 int i;
901
902 /* Check if Flash is (sufficiently) erased */
903 if ((*((vu_long *)dest) & data) != data)
904 return (2);
905
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200906 for (i = 0; i < 4 / sizeof(CONFIG_SYS_FLASH_WORD_SIZE); i++) {
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200907 int flag;
908
909 /* Disable interrupts which might cause a timeout here */
910 flag = disable_interrupts();
911
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200912 addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
913 addr2[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
914 addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00A000A0;
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200915
916 dest2[i] = data2[i];
917
918 /* re-enable interrupts if necessary */
919 if (flag)
920 enable_interrupts();
921
922 /* data polling for D7 */
923 start = get_timer(0);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200924 while ((dest2[i] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080) !=
925 (data2[i] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080)) {
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200926
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200927 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT)
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200928 return (1);
929 }
930 }
931
932 return (0);
933}
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200934#endif /* CONFIG_SYS_FLASH_2ND_16BIT_DEV */
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200935
936/*-----------------------------------------------------------------------
937 * Functions
938 */
939static ulong flash_get_size(vu_long * addr, flash_info_t * info);
940static int write_word(flash_info_t * info, ulong dest, ulong data);
941
942/*-----------------------------------------------------------------------
943 */
944
945unsigned long flash_init(void)
946{
947 unsigned long total_b = 0;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200948 unsigned long size_b[CONFIG_SYS_MAX_FLASH_BANKS];
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200949 unsigned short index = 0;
950 int i;
951 unsigned long val;
952 unsigned long ebc_boot_size;
953 unsigned long boot_selection;
954
955 mfsdr(sdr_pstrp0, val);
956 index = (val & SDR0_PSTRP0_BOOTSTRAP_MASK) >> 28;
957
958 if ((index == 0xc) || (index == 8)) {
959 /*
960 * Boot Settings in IIC EEprom address 0xA8 or 0xA0
961 * Read Serial Device Strap Register1 in PPC440SPe
962 */
Stefan Roesed1c3b272009-09-09 16:25:29 +0200963 mfsdr(SDR0_SDSTP1, val);
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200964 boot_selection = val & SDR0_SDSTP1_BOOT_SEL_MASK;
965 ebc_boot_size = val & SDR0_SDSTP1_EBC_ROM_BS_MASK;
966
967 switch(boot_selection) {
968 case SDR0_SDSTP1_BOOT_SEL_EBC:
969 switch(ebc_boot_size) {
970 case SDR0_SDSTP1_EBC_ROM_BS_16BIT:
971 index = 3;
972 break;
973 case SDR0_SDSTP1_EBC_ROM_BS_8BIT:
974 index = 0;
975 break;
976 }
977 break;
978
979 case SDR0_SDSTP1_BOOT_SEL_PCI:
980 index = 1;
981 break;
982
983 }
984 } /*else if (index == 0) {*/
985/* if (in8(FPGA_SETTING_REG) & FPGA_SET_REG_OP_CODE_FLASH_ABOVE)*/
Wolfgang Denkb87dfd22006-07-19 13:50:38 +0200986/* index = 8;*/ /* sram below op code flash -> new index 8*/
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200987/* }*/
988
989 DEBUGF("\n");
990 DEBUGF("FLASH: Index: %d\n", index);
991
992 /* Init: no FLASHes known */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200993 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
Marian Balakowicz6c5879f2006-06-30 16:30:46 +0200994 flash_info[i].flash_id = FLASH_UNKNOWN;
995 flash_info[i].sector_count = -1;
996 flash_info[i].size = 0;
997
998 /* check whether the address is 0 */
999 if (flash_addr_table[index][i] == 0)
1000 continue;
1001
1002 /* call flash_get_size() to initialize sector address */
1003 size_b[i] = flash_get_size((vu_long *) flash_addr_table[index][i],
1004 &flash_info[i]);
1005
1006 flash_info[i].size = size_b[i];
1007
1008 if (flash_info[i].flash_id == FLASH_UNKNOWN) {
1009 printf("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
1010 i, size_b[i], size_b[i] << 20);
1011 flash_info[i].sector_count = -1;
1012 flash_info[i].size = 0;
1013 }
1014
1015 /* Monitor protection ON by default */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +02001016 (void)flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_MONITOR_BASE,
1017 CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN - 1,
Marian Balakowicz6c5879f2006-06-30 16:30:46 +02001018 &flash_info[i]);
Jean-Christophe PLAGNIOL-VILLARD5a1aceb2008-09-10 22:48:04 +02001019#if defined(CONFIG_ENV_IS_IN_FLASH)
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +02001020 (void)flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR,
1021 CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
Marian Balakowicz6c5879f2006-06-30 16:30:46 +02001022 &flash_info[i]);
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +02001023#if defined(CONFIG_ENV_ADDR_REDUND)
1024 (void)flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR_REDUND,
1025 CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1,
Marian Balakowicz6c5879f2006-06-30 16:30:46 +02001026 &flash_info[i]);
1027#endif
1028#endif
1029 total_b += flash_info[i].size;
1030 }
1031
1032 return total_b;
1033}