]> git.ipfire.org Git - people/ms/u-boot.git/blame - board/kup4k/flash.c
* Get (mostly) rid of CFG_MONITOR_LEN definition; compute real length
[people/ms/u-boot.git] / board / kup4k / flash.c
CommitLineData
56f94be3
WD
1/*
2 * (C) Copyright 2000-2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24#include <common.h>
25#include <mpc8xx.h>
26
27#ifndef CFG_ENV_ADDR
28#define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET)
29#endif
30
31#define CONFIG_FLASH_16BIT
32
33flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
34
35/*-----------------------------------------------------------------------
36 * Functions
37 */
38static ulong flash_get_size (vu_long *addr, flash_info_t *info);
39static int write_word (flash_info_t *info, ulong dest, ulong data);
40
41/*-----------------------------------------------------------------------
42 */
43
44unsigned long flash_init (void)
45{
46 volatile immap_t *immap = (immap_t *)CFG_IMMR;
47 volatile memctl8xx_t *memctl = &immap->im_memctl;
48 unsigned long size_b0;
49 int i;
50
51 /* Init: no FLASHes known */
52 for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
53 flash_info[i].flash_id = FLASH_UNKNOWN;
54 }
55
56 /* Static FLASH Bank configuration here - FIXME XXX */
57
58 size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
59
60 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
61 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
62 size_b0, size_b0<<20);
63 }
64
65
66 /* Remap FLASH according to real size */
67 memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & OR_AM_MSK);
68 memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V | BR_PS_16;
69
70 /* Re-do sizing to get full correct info */
71 size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
72
73#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
74 /* monitor protection ON by default */
75 flash_protect(FLAG_PROTECT_SET,
76 CFG_MONITOR_BASE,
3b57fe0a 77 CFG_MONITOR_BASE+monitor_flash_len-1,
56f94be3
WD
78 &flash_info[0]);
79#endif
80
81#ifdef CFG_ENV_IS_IN_FLASH
82 /* ENV protection ON by default */
83 flash_protect(FLAG_PROTECT_SET,
84 CFG_ENV_ADDR,
85 CFG_ENV_ADDR+CFG_ENV_SIZE-1,
86 &flash_info[0]);
87#endif
88
89 flash_info[0].size = size_b0;
90
91 return (size_b0);
92}
93
94/*-----------------------------------------------------------------------
95 */
96void flash_print_info (flash_info_t *info)
97{
98 int i;
99
100 if (info->flash_id == FLASH_UNKNOWN) {
101 printf ("missing or unknown FLASH type\n");
102 return;
103 }
104
105 switch (info->flash_id & FLASH_VENDMASK) {
106 case FLASH_MAN_AMD: printf ("AMD "); break;
107 case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
108 default: printf ("Unknown Vendor "); break;
109 }
110
111 switch (info->flash_id & FLASH_TYPEMASK) {
112 case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
113 break;
114 case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n");
115 break;
116 case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
117 break;
118 case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n");
119 break;
120 case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
121 break;
122 case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n");
123 break;
124 case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
125 break;
126 case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n");
127 break;
128 default: printf ("Unknown Chip Type\n");
129 break;
130 }
131
132 printf (" Size: %ld MB in %d Sectors\n",
133 info->size >> 20, info->sector_count);
134
135 printf (" Sector Start Addresses:");
136 for (i=0; i<info->sector_count; ++i) {
137 if ((i % 5) == 0)
138 printf ("\n ");
139 printf (" %08lX%s",
140 info->start[i],
141 info->protect[i] ? " (RO)" : " "
142 );
143 }
144 printf ("\n");
145 return;
146}
147
148/*-----------------------------------------------------------------------
149 */
150
151
152/*-----------------------------------------------------------------------
153 */
154
155/*
156 * The following code cannot be run from FLASH!
157 */
158
159static ulong flash_get_size (vu_long *addr, flash_info_t *info)
160{
161 short i;
162 ulong value;
163 ulong base = (ulong)addr;
164
165 /* Write auto select command: read Manufacturer ID */
166 vu_short *s_addr=(vu_short*)addr;
167 s_addr[0x5555] = 0x00AA;
168 s_addr[0x2AAA] = 0x0055;
169 s_addr[0x5555] = 0x0090;
170
171 value = s_addr[0];
172 value = value|(value<<16);
173
174 switch (value) {
175 case FUJ_MANUFACT:
176 info->flash_id = FLASH_MAN_FUJ;
177 break;
178 default:
179 info->flash_id = FLASH_UNKNOWN;
180 info->sector_count = 0;
181 info->size = 0;
182 return (0); /* no or unknown flash */
183 }
184
185 value = s_addr[1];
186 value = value|(value<<16);
187
188 switch (value) {
189 case FUJI_ID_29F800BA:
190 info->flash_id += FLASH_AM400T;
191 info->sector_count = 19;
192 info->size = 0x00100000;
193 break; /* => 1 MB */
194 default:
195 info->flash_id = FLASH_UNKNOWN;
196 return (0); /* => no or unknown flash */
197 }
198
199 /* set up sector start address table */
200 /* set sector offsets for bottom boot block type */
201 info->start[0] = base + 0x00000000;
202 info->start[1] = base + 0x00004000;
203 info->start[2] = base + 0x00006000;
204 info->start[3] = base + 0x00008000;
205 for (i = 4; i < info->sector_count; i++) {
206 info->start[i] = base + (i * 0x00010000) - 0x00030000;
207 }
208
209
210 /* check for protected sectors */
211 for (i = 0; i < info->sector_count; i++) {
212 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
213 /* D0 = 1 if protected */
214 s_addr = (volatile unsigned short *)(info->start[i]);
215 info->protect[i] = s_addr[2] & 1;
216 }
217
218 /*
219 * Prevent writes to uninitialized FLASH.
220 */
221 if (info->flash_id != FLASH_UNKNOWN) {
222 s_addr = (volatile unsigned short *)info->start[0];
223 *s_addr = 0x00F0; /* reset bank */
224 }
225 return (info->size);
226}
227
228
229/*-----------------------------------------------------------------------
230 */
231
232
233int flash_erase (flash_info_t *info, int s_first, int s_last)
234{
235 vu_long *addr = (vu_long*)(info->start[0]);
236 int flag, prot, sect;
237 ulong start, now, last;
238#ifdef CONFIG_FLASH_16BIT
239 vu_short *s_addr = (vu_short*)addr;
240#endif
241
242 if ((s_first < 0) || (s_first > s_last)) {
243 if (info->flash_id == FLASH_UNKNOWN) {
244 printf ("- missing\n");
245 } else {
246 printf ("- no sectors to erase\n");
247 }
248 return 1;
249 }
250/*#ifndef CONFIG_FLASH_16BIT
251 ulong type;
252 type = (info->flash_id & FLASH_VENDMASK);
253 if ((type != FLASH_MAN_SST) && (type != FLASH_MAN_STM)) {
254 printf ("Can't erase unknown flash type %08lx - aborted\n",
255 info->flash_id);
256 return;
257 }
258#endif*/
259 prot = 0;
260 for (sect=s_first; sect<=s_last; ++sect) {
261 if (info->protect[sect]) {
262 prot++;
263 }
264 }
265
266 if (prot) {
267 printf ("- Warning: %d protected sectors will not be erased!\n",
268 prot);
269 } else {
270 printf ("\n");
271 }
272
273 start = get_timer (0);
274 last = start;
275 /* Start erase on unprotected sectors */
276 for (sect = s_first; sect<=s_last; sect++) {
277 if (info->protect[sect] == 0) { /* not protected */
278#ifdef CONFIG_FLASH_16BIT
279 vu_short *s_sect_addr = (vu_short*)(info->start[sect]);
280#else
281 vu_long *sect_addr = (vu_long*)(info->start[sect]);
282#endif
283 /* Disable interrupts which might cause a timeout here */
284 flag = disable_interrupts();
285
286#ifdef CONFIG_FLASH_16BIT
287
288 /*printf("\ns_sect_addr=%x",s_sect_addr);*/
289 s_addr[0x5555] = 0x00AA;
290 s_addr[0x2AAA] = 0x0055;
291 s_addr[0x5555] = 0x0080;
292 s_addr[0x5555] = 0x00AA;
293 s_addr[0x2AAA] = 0x0055;
294 s_sect_addr[0] = 0x0030;
295#else
296 addr[0x5555] = 0x00AA00AA;
297 addr[0x2AAA] = 0x00550055;
298 addr[0x5555] = 0x00800080;
299 addr[0x5555] = 0x00AA00AA;
300 addr[0x2AAA] = 0x00550055;
301 sect_addr[0] = 0x00300030;
302#endif
303 /* re-enable interrupts if necessary */
304 if (flag)
305 enable_interrupts();
306
307 /* wait at least 80us - let's wait 1 ms */
308 udelay (1000);
309
310#ifdef CONFIG_FLASH_16BIT
311 while ((s_sect_addr[0] & 0x0080) != 0x0080) {
312#else
313 while ((sect_addr[0] & 0x00800080) != 0x00800080) {
314#endif
315 if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
316 printf ("Timeout\n");
317 return 1;
318 }
319 /* show that we're waiting */
320 if ((now - last) > 1000) { /* every second */
321 putc ('.');
322 last = now;
323 }
324 }
325 }
326 }
327
328 /* reset to read mode */
329 addr = (volatile unsigned long *)info->start[0];
330#ifdef CONFIG_FLASH_16BIT
331 s_addr[0] = 0x00F0; /* reset bank */
332#else
333 addr[0] = 0x00F000F0; /* reset bank */
334#endif
335
336 printf (" done\n");
337 return 0;
338}
339
340
341/*-----------------------------------------------------------------------
342 * Copy memory to flash, returns:
343 * 0 - OK
344 * 1 - write timeout
345 * 2 - Flash not erased
346 */
347
348int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
349{
350 ulong cp, wp, data;
351 int i, l, rc;
352
353 wp = (addr & ~3); /* get lower word aligned address */
354
355 /*
356 * handle unaligned start bytes
357 */
358 if ((l = addr - wp) != 0) {
359 data = 0;
360 for (i=0, cp=wp; i<l; ++i, ++cp) {
361 data = (data << 8) | (*(uchar *)cp);
362 }
363 for (; i<4 && cnt>0; ++i) {
364 data = (data << 8) | *src++;
365 --cnt;
366 ++cp;
367 }
368 for (; cnt==0 && i<4; ++i, ++cp) {
369 data = (data << 8) | (*(uchar *)cp);
370 }
371
372 if ((rc = write_word(info, wp, data)) != 0) {
373 return (rc);
374 }
375 wp += 4;
376 }
377
378 /*
379 * handle word aligned part
380 */
381 while (cnt >= 4) {
382 data = 0;
383 for (i=0; i<4; ++i) {
384 data = (data << 8) | *src++;
385 }
386 if ((rc = write_word(info, wp, data)) != 0) {
387 return (rc);
388 }
389 wp += 4;
390 cnt -= 4;
391 }
392
393 if (cnt == 0) {
394 return (0);
395 }
396
397 /*
398 * handle unaligned tail bytes
399 */
400 data = 0;
401 for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
402 data = (data << 8) | *src++;
403 --cnt;
404 }
405 for (; i<4; ++i, ++cp) {
406 data = (data << 8) | (*(uchar *)cp);
407 }
408
409 return (write_word(info, wp, data));
410}
411
412
413/*-----------------------------------------------------------------------
414 * Write a word to Flash, returns:
415 * 0 - OK
416 * 1 - write timeout
417 * 2 - Flash not erased
418 */
419static int write_word (flash_info_t *info, ulong dest, ulong data)
420{
421 vu_long *addr = (vu_long*)(info->start[0]);
422
423#ifdef CONFIG_FLASH_16BIT
424 vu_short high_data;
425 vu_short low_data;
426 vu_short *s_addr = (vu_short*)addr;
427#endif
428 ulong start;
429 int flag;
430
431 /* Check if Flash is (sufficiently) erased */
432 if ((*((vu_long *)dest) & data) != data) {
433 return (2);
434 }
435
436#ifdef CONFIG_FLASH_16BIT
437 /* Write the 16 higher-bits */
438 /* Disable interrupts which might cause a timeout here */
439 flag = disable_interrupts();
440
441 high_data = ((data>>16) & 0x0000ffff);
442
443 s_addr[0x5555] = 0x00AA;
444 s_addr[0x2AAA] = 0x0055;
445 s_addr[0x5555] = 0x00A0;
446
447 *((vu_short *)dest) = high_data;
448
449
450 /* re-enable interrupts if necessary */
451 if (flag)
452 enable_interrupts();
453
454 /* data polling for D7 */
455 start = get_timer (0);
456 while ((*((vu_short *)dest) & 0x0080) != (high_data & 0x0080)) {
457 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
458 return (1);
459 }
460 }
461
462
463 /* Write the 16 lower-bits */
464#endif
465
466 /* Disable interrupts which might cause a timeout here */
467 flag = disable_interrupts();
468#ifdef CONFIG_FLASH_16BIT
469 dest += 0x2;
470 low_data = (data & 0x0000ffff);
471
472 s_addr[0x5555] = 0x00AA;
473 s_addr[0x2AAA] = 0x0055;
474 s_addr[0x5555] = 0x00A0;
475 *((vu_short *)dest) = low_data;
476
477#else
478 addr[0x5555] = 0x00AA00AA;
479 addr[0x2AAA] = 0x00550055;
480 addr[0x5555] = 0x00A000A0;
481 *((vu_long *)dest) = data;
482#endif
483
484 /* re-enable interrupts if necessary */
485 if (flag)
486 enable_interrupts();
487
488 /* data polling for D7 */
489 start = get_timer (0);
490
491#ifdef CONFIG_FLASH_16BIT
492 while ((*((vu_short *)dest) & 0x0080) != (low_data & 0x0080)) {
493#else
494 while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
495#endif
496
497 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
498 return (1);
499 }
500 }
501 return (0);
502}