blob: ad046bed69b9098b2a72a6bfa05cbf9b42fceaa9 [file] [log] [blame]
Stefan Roeseb79316f2005-08-15 12:31:23 +02001/*
2 * (C) Copyright 2002-2005
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 Denk3765b3e2013-10-07 13:07:26 +02008 * SPDX-License-Identifier: GPL-2.0+
Stefan Roeseb79316f2005-08-15 12:31:23 +02009 */
10/*
11 * Ported from Ebony flash support
12 * Travis B. Sawyer
13 * Sandburst Corporation
14 */
15#include <common.h>
Stefan Roeseb36df562010-09-09 19:18:00 +020016#include <asm/ppc4xx.h>
Stefan Roeseb79316f2005-08-15 12:31:23 +020017#include <asm/processor.h>
18
19
20#undef DEBUG
21#ifdef DEBUG
22#define DEBUGF(x...) printf(x)
23#else
24#define DEBUGF(x...)
25#endif /* DEBUG */
26
27
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020028flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
Stefan Roeseb79316f2005-08-15 12:31:23 +020029
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020030static unsigned long flash_addr_table[8][CONFIG_SYS_MAX_FLASH_BANKS] = {
Stefan Roeseb79316f2005-08-15 12:31:23 +020031 {0xfff80000} /* Boot Flash */
32};
33
34/*-----------------------------------------------------------------------
35 * Functions
36 */
37static ulong flash_get_size (vu_long *addr, flash_info_t *info);
38static int write_word (flash_info_t *info, ulong dest, ulong data);
39
40
41#define ADDR0 0x5555
42#define ADDR1 0x2aaa
43#define FLASH_WORD_SIZE unsigned char
44
45
46/*-----------------------------------------------------------------------
47 */
48
49unsigned long flash_init (void)
50{
51 unsigned long total_b = 0;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020052 unsigned long size_b[CONFIG_SYS_MAX_FLASH_BANKS];
Stefan Roeseb79316f2005-08-15 12:31:23 +020053 unsigned short index = 0;
54 int i;
55
56
57 DEBUGF("\n");
58 DEBUGF("FLASH: Index: %d\n", index);
59
60 /* Init: no FLASHes known */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020061 for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
Stefan Roeseb79316f2005-08-15 12:31:23 +020062 flash_info[i].flash_id = FLASH_UNKNOWN;
63 flash_info[i].sector_count = -1;
64 flash_info[i].size = 0;
65
66 /* check whether the address is 0 */
67 if (flash_addr_table[index][i] == 0) {
68 continue;
69 }
70
71 /* call flash_get_size() to initialize sector address */
72 size_b[i] = flash_get_size(
73 (vu_long *)flash_addr_table[index][i], &flash_info[i]);
74 flash_info[i].size = size_b[i];
75 if (flash_info[i].flash_id == FLASH_UNKNOWN) {
76 printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
77 i, size_b[i], size_b[i]<<20);
78 flash_info[i].sector_count = -1;
79 flash_info[i].size = 0;
80 }
81
82 total_b += flash_info[i].size;
83 }
84
85 return total_b;
86}
87
88
89/*-----------------------------------------------------------------------
90 */
91void flash_print_info (flash_info_t *info)
92{
93 int i;
94 int k;
95 int size;
96 int erased;
97 volatile unsigned long *flash;
98
99 if (info->flash_id == FLASH_UNKNOWN) {
100 printf ("missing or unknown FLASH type\n");
101 return;
102 }
103
104 switch (info->flash_id & FLASH_VENDMASK) {
105 case FLASH_MAN_AMD: printf ("AMD "); break;
106 default: printf ("Unknown Vendor "); break;
107 }
108
109 switch (info->flash_id & FLASH_TYPEMASK) {
110 case FLASH_AM040: printf ("AM29F040 (512 Kbit, uniform sector size)\n");
111 break;
112 default: printf ("Unknown Chip Type\n");
113 break;
114 }
115
116 printf (" Size: %ld KB in %d Sectors\n",
117 info->size >> 10, info->sector_count);
118
119 printf (" Sector Start Addresses:");
120 for (i=0; i<info->sector_count; ++i) {
121 /*
122 * Check if whole sector is erased
123 */
124 if (i != (info->sector_count-1))
125 size = info->start[i+1] - info->start[i];
126 else
127 size = info->start[0] + info->size - info->start[i];
128 erased = 1;
129 flash = (volatile unsigned long *)info->start[i];
130 size = size >> 2; /* divide by 4 for longword access */
131 for (k=0; k<size; k++)
132 {
133 if (*flash++ != 0xffffffff)
134 {
135 erased = 0;
136 break;
137 }
138 }
139
140 if ((i % 5) == 0)
141 printf ("\n ");
142 printf (" %08lX%s%s",
143 info->start[i],
144 erased ? " E" : " ",
145 info->protect[i] ? "RO " : " "
146 );
147 }
148 printf ("\n");
149 return;
150 }
151
152/*-----------------------------------------------------------------------
153 */
154
155
156/*-----------------------------------------------------------------------
157 */
158
159/*
160 * The following code cannot be run from FLASH!
161 */
162static ulong flash_get_size (vu_long *addr, flash_info_t *info)
163{
164 short i;
165 FLASH_WORD_SIZE value;
166 ulong base = (ulong)addr;
167 volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr;
168
169 DEBUGF("FLASH ADDR: %08x\n", (unsigned)addr );
170
171 /* Write auto select command: read Manufacturer ID */
172 udelay(10000);
173 addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
174 udelay(1000);
175 addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
176 udelay(1000);
177 addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090;
178 udelay(1000);
179
180 value = addr2[0];
181
182 DEBUGF("FLASH MANUFACT: %x\n", value);
183
184 switch (value) {
185 case (FLASH_WORD_SIZE)AMD_MANUFACT:
186 info->flash_id = FLASH_MAN_AMD;
187 break;
188 default:
189 info->flash_id = FLASH_UNKNOWN;
190 info->sector_count = 0;
191 info->size = 0;
192 return (0); /* no or unknown flash */
193 }
194
195 value = addr2[1]; /* device ID */
196
197 DEBUGF("\nFLASH DEVICEID: %x\n", value);
198
199 switch (value) {
200 case (FLASH_WORD_SIZE)AMD_ID_LV040B:
201 info->flash_id += FLASH_AM040;
202 info->sector_count = 8;
203 info->size = 0x00080000; /* => 512 kb */
204 break;
205
206 default:
207 info->flash_id = FLASH_UNKNOWN;
208 return (0); /* => no or unknown flash */
209
210 }
211
212 /* set up sector start address table */
213 if (info->flash_id == FLASH_AM040) {
214 for (i = 0; i < info->sector_count; i++)
215 info->start[i] = base + (i * 0x00010000);
216 } else {
217 if (info->flash_id & FLASH_BTYPE) {
218 /* set sector offsets for bottom boot block type */
219 info->start[0] = base + 0x00000000;
220 info->start[1] = base + 0x00004000;
221 info->start[2] = base + 0x00006000;
222 info->start[3] = base + 0x00008000;
223 for (i = 4; i < info->sector_count; i++) {
224 info->start[i] = base + (i * 0x00010000) - 0x00030000;
225 }
226 } else {
227 /* set sector offsets for top boot block type */
228 i = info->sector_count - 1;
229 info->start[i--] = base + info->size - 0x00004000;
230 info->start[i--] = base + info->size - 0x00006000;
231 info->start[i--] = base + info->size - 0x00008000;
232 for (; i >= 0; i--) {
233 info->start[i] = base + i * 0x00010000;
234 }
235 }
236 }
237
238 /* check for protected sectors */
239 for (i = 0; i < info->sector_count; i++) {
240 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
241 /* D0 = 1 if protected */
242 addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]);
243 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST)
244 info->protect[i] = 0;
245 else
246 info->protect[i] = addr2[2] & 1;
247 }
248
249 /* reset to return to reading data */
250 addr2[0] = (FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */
251
252 /*
253 * Prevent writes to uninitialized FLASH.
254 */
255 if (info->flash_id != FLASH_UNKNOWN) {
256 addr2 = (FLASH_WORD_SIZE *)info->start[0];
257 *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
258 }
259
260 return (info->size);
261}
262
263int wait_for_DQ7(flash_info_t *info, int sect)
264{
265 ulong start, now, last;
266 volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);
267
268 start = get_timer (0);
269 last = start;
270 while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200271 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
Stefan Roeseb79316f2005-08-15 12:31:23 +0200272 printf ("Timeout\n");
273 return -1;
274 }
275 /* show that we're waiting */
276 if ((now - last) > 1000) { /* every second */
277 putc ('.');
278 last = now;
279 }
280 }
281 return 0;
282}
283
284/*-----------------------------------------------------------------------
285 */
286
287int flash_erase (flash_info_t *info, int s_first, int s_last)
288{
289 volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
290 volatile FLASH_WORD_SIZE *addr2;
Wolfgang Denkeffa4e32011-11-29 22:17:50 +0000291 int flag, prot, sect;
Stefan Roeseb79316f2005-08-15 12:31:23 +0200292 int i;
293
294 if ((s_first < 0) || (s_first > s_last)) {
295 if (info->flash_id == FLASH_UNKNOWN) {
296 printf ("- missing\n");
297 } else {
298 printf ("- no sectors to erase\n");
299 }
300 return 1;
301 }
302
303 if (info->flash_id == FLASH_UNKNOWN) {
304 printf ("Can't erase unknown flash type - aborted\n");
305 return 1;
306 }
307
308 prot = 0;
309 for (sect=s_first; sect<=s_last; ++sect) {
310 if (info->protect[sect]) {
311 prot++;
312 }
313 }
314
315 if (prot) {
316 printf ("- Warning: %d protected sectors will not be erased!\n",
317 prot);
318 } else {
319 printf ("\n");
320 }
321
Stefan Roeseb79316f2005-08-15 12:31:23 +0200322 /* Disable interrupts which might cause a timeout here */
323 flag = disable_interrupts();
324
325 /* Start erase on unprotected sectors */
326 for (sect = s_first; sect<=s_last; sect++) {
327 if (info->protect[sect] == 0) { /* not protected */
328 addr2 = (FLASH_WORD_SIZE *)(info->start[sect]);
329 DEBUGF("Erasing sector %p\n", addr2);
330
331 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
332 addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
333 addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
334 addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
335 addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
336 addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
337 addr2[0] = (FLASH_WORD_SIZE)0x00500050; /* block erase */
338 for (i=0; i<50; i++)
339 udelay(1000); /* wait 1 ms */
340 } else {
341 addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
342 addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
343 addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
344 addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
345 addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
346 addr2[0] = (FLASH_WORD_SIZE)0x00300030; /* sector erase */
347 }
Stefan Roeseb79316f2005-08-15 12:31:23 +0200348 /*
349 * Wait for each sector to complete, it's more
350 * reliable. According to AMD Spec, you must
351 * issue all erase commands within a specified
352 * timeout. This has been seen to fail, especially
353 * if printf()s are included (for debug)!!
354 */
355 wait_for_DQ7(info, sect);
356 }
357 }
358
359 /* re-enable interrupts if necessary */
360 if (flag)
361 enable_interrupts();
362
363 /* wait at least 80us - let's wait 1 ms */
364 udelay (1000);
365
366 /* reset to read mode */
367 addr = (FLASH_WORD_SIZE *)info->start[0];
368 addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
369
370 printf (" done\n");
371 return 0;
372}
373
374/*-----------------------------------------------------------------------
375 * Copy memory to flash, returns:
376 * 0 - OK
377 * 1 - write timeout
378 * 2 - Flash not erased
379 */
380
381int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
382{
383 ulong cp, wp, data;
384 int i, l, rc;
385
386 wp = (addr & ~3); /* get lower word aligned address */
387
388 /*
389 * handle unaligned start bytes
390 */
391 if ((l = addr - wp) != 0) {
392 data = 0;
393 for (i=0, cp=wp; i<l; ++i, ++cp) {
394 data = (data << 8) | (*(uchar *)cp);
395 }
396 for (; i<4 && cnt>0; ++i) {
397 data = (data << 8) | *src++;
398 --cnt;
399 ++cp;
400 }
401 for (; cnt==0 && i<4; ++i, ++cp) {
402 data = (data << 8) | (*(uchar *)cp);
403 }
404
405 if ((rc = write_word(info, wp, data)) != 0) {
406 return (rc);
407 }
408 wp += 4;
409 }
410
411 /*
412 * handle word aligned part
413 */
414 while (cnt >= 4) {
415 data = 0;
416 for (i=0; i<4; ++i) {
417 data = (data << 8) | *src++;
418 }
419 if ((rc = write_word(info, wp, data)) != 0) {
420 return (rc);
421 }
422 wp += 4;
423 cnt -= 4;
424 }
425
426 if (cnt == 0) {
427 return (0);
428 }
429
430 /*
431 * handle unaligned tail bytes
432 */
433 data = 0;
434 for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
435 data = (data << 8) | *src++;
436 --cnt;
437 }
438 for (; i<4; ++i, ++cp) {
439 data = (data << 8) | (*(uchar *)cp);
440 }
441
442 return (write_word(info, wp, data));
443}
444
445/*-----------------------------------------------------------------------
446 * Write a word to Flash, returns:
447 * 0 - OK
448 * 1 - write timeout
449 * 2 - Flash not erased
450 */
451static int write_word (flash_info_t * info, ulong dest, ulong data)
452{
453 volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) (info->start[0]);
454 volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *) dest;
455 volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data;
456 ulong start;
457 int i;
458
459 /* Check if Flash is (sufficiently) erased */
460 if ((*((volatile FLASH_WORD_SIZE *) dest) &
461 (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) {
462 return (2);
463 }
464
465 for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++) {
466 int flag;
467
468 /* Disable interrupts which might cause a timeout here */
469 flag = disable_interrupts ();
470
471 addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
472 addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
473 addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00A000A0;
474
475 dest2[i] = data2[i];
476
477 /* re-enable interrupts if necessary */
478 if (flag)
479 enable_interrupts ();
480
481 /* data polling for D7 */
482 start = get_timer (0);
483 while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) !=
484 (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) {
485
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200486 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
Stefan Roeseb79316f2005-08-15 12:31:23 +0200487 return (1);
488 }
489 }
490 }
491
492 return (0);
493}