blob: 146a923e115e91b96dc6d73ff0ebeecf33e412c6 [file] [log] [blame]
wdenkf9087a32002-11-03 00:30:25 +00001/*
2 * (C) Copyright 2000-2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenkf9087a32002-11-03 00:30:25 +00006 */
7
8#define DEBUG
9
10#include <common.h>
11#include <mpc8xx.h>
12
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +020013#ifndef CONFIG_ENV_ADDR
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020014#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
wdenkf9087a32002-11-03 00:30:25 +000015#endif
16
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020017flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
wdenkf9087a32002-11-03 00:30:25 +000018
19/*-----------------------------------------------------------------------
20 * Functions
21 */
22static ulong flash_get_size (vu_long *addr, flash_info_t *info);
23static int write_word (flash_info_t *info, ulong dest, ulong data);
24
25/*-----------------------------------------------------------------------
26 */
27
28unsigned long flash_init (void)
29{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020030 volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
wdenkf9087a32002-11-03 00:30:25 +000031 volatile memctl8xx_t *memctl = &immap->im_memctl;
32 unsigned long size;
33 int i;
34
35 /* Init: no FLASHes known */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020036 for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
wdenkf9087a32002-11-03 00:30:25 +000037 flash_info[i].flash_id = FLASH_UNKNOWN;
38 }
39
40 /* Static FLASH Bank configuration here - FIXME XXX */
41
42 size = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
43
44 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
45 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
46 size, size<<20);
47 }
48
49 /* Remap FLASH according to real size */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020050 memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH | (-size & OR_AM_MSK);
51 memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
wdenkf9087a32002-11-03 00:30:25 +000052
53 /* Re-do sizing to get full correct info */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020054 size = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
wdenkf9087a32002-11-03 00:30:25 +000055
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020056#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
wdenkf9087a32002-11-03 00:30:25 +000057 /* monitor protection ON by default */
58 flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020059 CONFIG_SYS_MONITOR_BASE,
60 CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
wdenkf9087a32002-11-03 00:30:25 +000061 &flash_info[0]);
62#endif
63
Jean-Christophe PLAGNIOL-VILLARD5a1aceb2008-09-10 22:48:04 +020064#ifdef CONFIG_ENV_IS_IN_FLASH
wdenkf9087a32002-11-03 00:30:25 +000065 /* ENV protection ON by default */
66 flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +020067 CONFIG_ENV_ADDR,
68 CONFIG_ENV_ADDR+CONFIG_ENV_SIZE-1,
wdenkf9087a32002-11-03 00:30:25 +000069 &flash_info[0]);
70#endif
71
72 flash_info[0].size = size;
73
74 return (size);
75}
76
77/*-----------------------------------------------------------------------
78 */
79void flash_print_info (flash_info_t *info)
80{
81 int i;
82
83 if (info->flash_id == FLASH_UNKNOWN) {
84 puts ("missing or unknown FLASH type\n");
85 return;
86 }
87
88 switch (info->flash_id & FLASH_VENDMASK) {
89 case FLASH_MAN_AMD: puts ("AMD "); break;
90 case FLASH_MAN_FUJ: puts ("FUJITSU "); break;
91 default: puts ("Unknown Vendor "); break;
92 }
93
94 switch (info->flash_id & FLASH_TYPEMASK) {
95 case FLASH_AM400B: puts ("AM29LV400B (4 Mbit, bottom boot sect)\n");
96 break;
97 case FLASH_AM400T: puts ("AM29LV400T (4 Mbit, top boot sector)\n");
98 break;
99 case FLASH_AM800B: puts ("AM29LV800B (8 Mbit, bottom boot sect)\n");
100 break;
101 case FLASH_AM800T: puts ("AM29LV800T (8 Mbit, top boot sector)\n");
102 break;
103 case FLASH_AM160B: puts ("AM29LV160B (16 Mbit, bottom boot sect)\n");
104 break;
105 case FLASH_AM160T: puts ("AM29LV160T (16 Mbit, top boot sector)\n");
106 break;
107 case FLASH_AM320B: puts ("AM29LV320B (32 Mbit, bottom boot sect)\n");
108 break;
109 case FLASH_AM320T: puts ("AM29LV320T (32 Mbit, top boot sector)\n");
110 break;
111 default: puts ("Unknown Chip Type\n");
112 break;
113 }
114
115 printf (" Size: %ld MB in %d Sectors\n",
116 info->size >> 20, info->sector_count);
117
118 puts (" Sector Start Addresses:");
119 for (i=0; i<info->sector_count; ++i) {
120 if ((i % 5) == 0)
121 puts ("\n ");
122 printf (" %08lX%s",
123 info->start[i],
124 info->protect[i] ? " (RO)" : " "
125 );
126 }
127 puts ("\n");
128 return;
129}
130
131/*-----------------------------------------------------------------------
132 */
133
134
135/*-----------------------------------------------------------------------
136 */
137
138/*
139 * The following code cannot be run from FLASH!
140 */
141
142static ulong flash_get_size (vu_long *addr, flash_info_t *info)
143{
144 short i;
145 ulong value;
146 ulong base = (ulong)addr;
147
148 /* Write auto select command: read Manufacturer ID */
149 addr[0x0555] = 0x00AA00AA;
150 addr[0x02AA] = 0x00550055;
151 addr[0x0555] = 0x00900090;
152
153 value = addr[0];
154
155 switch (value) {
156 case AMD_MANUFACT:
157 info->flash_id = FLASH_MAN_AMD;
158 break;
159 case FUJ_MANUFACT:
160 info->flash_id = FLASH_MAN_FUJ;
161 break;
162 default:
163 info->flash_id = FLASH_UNKNOWN;
164 info->sector_count = 0;
165 info->size = 0;
166 return (0); /* no or unknown flash */
167 }
168
169 value = addr[1]; /* device ID */
170
171 switch (value) {
172 case AMD_ID_LV400T:
173 info->flash_id += FLASH_AM400T;
174 info->sector_count = 11;
175 info->size = 0x00100000;
176 break; /* => 1 MB */
177
178 case AMD_ID_LV400B:
179 info->flash_id += FLASH_AM400B;
180 info->sector_count = 11;
181 info->size = 0x00100000;
182 break; /* => 1 MB */
183
184 case AMD_ID_LV800T:
185 info->flash_id += FLASH_AM800T;
186 info->sector_count = 19;
187 info->size = 0x00200000;
188 break; /* => 2 MB */
189
190 case AMD_ID_LV800B:
191 info->flash_id += FLASH_AM800B;
192 info->sector_count = 19;
193 info->size = 0x00200000;
194 break; /* => 2 MB */
195
196 case AMD_ID_LV160T:
197 info->flash_id += FLASH_AM160T;
198 info->sector_count = 35;
199 info->size = 0x00400000;
200 break; /* => 4 MB */
201
202 case AMD_ID_LV160B:
203 info->flash_id += FLASH_AM160B;
204 info->sector_count = 35;
205 info->size = 0x00400000;
206 break; /* => 4 MB */
207 case AMD_ID_LV320T:
208 info->flash_id += FLASH_AM320T;
209 info->sector_count = 71;
210 info->size = 0x00800000;
211 break; /* => 8 MB */
212
213 case AMD_ID_LV320B:
214 info->flash_id += FLASH_AM320B;
215 info->sector_count = 71;
216 info->size = 0x00800000;
217 break; /* => 8 MB */
218 default:
219 info->flash_id = FLASH_UNKNOWN;
220 return (0); /* => no or unknown flash */
221 }
222
223 /* set up sector start address table */
224 switch (value) {
225 case AMD_ID_LV400B:
226 case AMD_ID_LV800B:
227 case AMD_ID_LV160B:
228 /* set sector offsets for bottom boot block type */
229 info->start[0] = base + 0x00000000;
230 info->start[1] = base + 0x00008000;
231 info->start[2] = base + 0x0000C000;
232 info->start[3] = base + 0x00010000;
233 for (i = 4; i < info->sector_count; i++) {
234 info->start[i] = base + (i * 0x00020000) - 0x00060000;
235 }
236 break;
237 case AMD_ID_LV400T:
238 case AMD_ID_LV800T:
239 case AMD_ID_LV160T:
240 /* set sector offsets for top boot block type */
241 i = info->sector_count - 1;
242 info->start[i--] = base + info->size - 0x00008000;
243 info->start[i--] = base + info->size - 0x0000C000;
244 info->start[i--] = base + info->size - 0x00010000;
245 for (; i >= 0; i--) {
246 info->start[i] = base + i * 0x00020000;
247 }
248 break;
249 case AMD_ID_LV320B:
250 for (i = 0; i < info->sector_count; i++) {
251 info->start[i] = base;
252 /*
253 * The first 8 sectors are 8 kB,
254 * all the other ones are 64 kB
255 */
256 base += (i < 8)
257 ? 2 * ( 8 << 10)
258 : 2 * (64 << 10);
259 }
260 break;
261 case AMD_ID_LV320T:
262 for (i = 0; i < info->sector_count; i++) {
263 info->start[i] = base;
264 /*
265 * The last 8 sectors are 8 kB,
266 * all the other ones are 64 kB
267 */
268 base += (i < (info->sector_count - 8))
269 ? 2 * (64 << 10)
270 : 2 * ( 8 << 10);
271 }
272 break;
273 default:
274 return (0);
275 break;
276 }
277
278 /* check for protected sectors */
279 for (i = 0; i < info->sector_count; i++) {
280 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
281 /* D0 = 1 if protected */
282 addr = (volatile unsigned long *)(info->start[i]);
283 info->protect[i] = addr[2] & 1;
284 }
285
286 /*
287 * Prevent writes to uninitialized FLASH.
288 */
289 if (info->flash_id != FLASH_UNKNOWN) {
290 addr = (volatile unsigned long *)info->start[0];
291
292 *addr = 0x00F000F0; /* reset bank */
293 }
294
295 return (info->size);
296}
297
298
299/*-----------------------------------------------------------------------
300 */
301
302int flash_erase (flash_info_t *info, int s_first, int s_last)
303{
304 vu_long *addr = (vu_long*)(info->start[0]);
305 int flag, prot, sect, l_sect;
306 ulong start, now, last;
307
308 if ((s_first < 0) || (s_first > s_last)) {
309 if (info->flash_id == FLASH_UNKNOWN) {
310 puts ("- missing\n");
311 } else {
312 puts ("- no sectors to erase\n");
313 }
314 return 1;
315 }
316
317 if ((info->flash_id == FLASH_UNKNOWN) ||
318 (info->flash_id > FLASH_AMD_COMP)) {
319 printf ("Can't erase unknown flash type %08lx - aborted\n",
320 info->flash_id);
321 return 1;
322 }
323
324 prot = 0;
325 for (sect=s_first; sect<=s_last; ++sect) {
326 if (info->protect[sect]) {
327 prot++;
328 }
329 }
330
331 if (prot) {
332 printf ("- Warning: %d protected sectors will not be erased!\n",
333 prot);
334 } else {
335 puts ("\n");
336 }
337
338 l_sect = -1;
339
340 /* Disable interrupts which might cause a timeout here */
341 flag = disable_interrupts();
342
343 addr[0x0555] = 0x00AA00AA;
344 addr[0x02AA] = 0x00550055;
345 addr[0x0555] = 0x00800080;
346 addr[0x0555] = 0x00AA00AA;
347 addr[0x02AA] = 0x00550055;
348
349 /* Start erase on unprotected sectors */
350 for (sect = s_first; sect<=s_last; sect++) {
351 if (info->protect[sect] == 0) { /* not protected */
352 addr = (vu_long*)(info->start[sect]);
353 addr[0] = 0x00300030;
354 l_sect = sect;
355 }
356 }
357
358 /* re-enable interrupts if necessary */
359 if (flag)
360 enable_interrupts();
361
362 /* wait at least 80us - let's wait 1 ms */
363 udelay (1000);
364
365 /*
366 * We wait for the last triggered sector
367 */
368 if (l_sect < 0)
369 goto DONE;
370
371 start = get_timer (0);
372 last = start;
373 addr = (vu_long*)(info->start[l_sect]);
374 while ((addr[0] & 0x00800080) != 0x00800080) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200375 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenkf9087a32002-11-03 00:30:25 +0000376 puts ("Timeout\n");
377 return 1;
378 }
379 /* show that we're waiting */
380 if ((now - last) > 1000) { /* every second */
381 putc ('.');
382 last = now;
383 }
384 }
385
386DONE:
387 /* reset to read mode */
388 addr = (volatile unsigned long *)info->start[0];
389 addr[0] = 0x00F000F0; /* reset bank */
390
391 puts (" done\n");
392 return 0;
393}
394
395/*-----------------------------------------------------------------------
396 * Copy memory to flash, returns:
397 * 0 - OK
398 * 1 - write timeout
399 * 2 - Flash not erased
400 */
401
402int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
403{
404 ulong cp, wp, data;
405 int i, l, rc;
406
407 wp = (addr & ~3); /* get lower word aligned address */
408
409 /*
410 * handle unaligned start bytes
411 */
412 if ((l = addr - wp) != 0) {
413 data = 0;
414 for (i=0, cp=wp; i<l; ++i, ++cp) {
415 data = (data << 8) | (*(uchar *)cp);
416 }
417 for (; i<4 && cnt>0; ++i) {
418 data = (data << 8) | *src++;
419 --cnt;
420 ++cp;
421 }
422 for (; cnt==0 && i<4; ++i, ++cp) {
423 data = (data << 8) | (*(uchar *)cp);
424 }
425
426 if ((rc = write_word(info, wp, data)) != 0) {
427 return (rc);
428 }
429 wp += 4;
430 }
431
432 /*
433 * handle word aligned part
434 */
435 while (cnt >= 4) {
436 data = 0;
437 for (i=0; i<4; ++i) {
438 data = (data << 8) | *src++;
439 }
440 if ((rc = write_word(info, wp, data)) != 0) {
441 return (rc);
442 }
443 wp += 4;
444 cnt -= 4;
445 }
446
447 if (cnt == 0) {
448 return (0);
449 }
450
451 /*
452 * handle unaligned tail bytes
453 */
454 data = 0;
455 for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
456 data = (data << 8) | *src++;
457 --cnt;
458 }
459 for (; i<4; ++i, ++cp) {
460 data = (data << 8) | (*(uchar *)cp);
461 }
462
463 return (write_word(info, wp, data));
464}
465
466/*-----------------------------------------------------------------------
467 * Write a word to Flash, returns:
468 * 0 - OK
469 * 1 - write timeout
470 * 2 - Flash not erased
471 */
472static int write_word (flash_info_t *info, ulong dest, ulong data)
473{
474 vu_long *addr = (vu_long*)(info->start[0]);
475 ulong start;
476 int flag;
477
478 /* Check if Flash is (sufficiently) erased */
479 if ((*((vu_long *)dest) & data) != data) {
480 return (2);
481 }
482 /* Disable interrupts which might cause a timeout here */
483 flag = disable_interrupts();
484
485 addr[0x0555] = 0x00AA00AA;
486 addr[0x02AA] = 0x00550055;
487 addr[0x0555] = 0x00A000A0;
488
489 *((vu_long *)dest) = data;
490
491 /* re-enable interrupts if necessary */
492 if (flag)
493 enable_interrupts();
494
495 /* data polling for D7 */
496 start = get_timer (0);
497 while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200498 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenkf9087a32002-11-03 00:30:25 +0000499 return (1);
500 }
501 }
502 return (0);
503}
504
505/*-----------------------------------------------------------------------
506 */