blob: e6cf8eb6b365e281bd260749b1425a45742f6a7d [file] [log] [blame]
wdenk7ebf7442002-11-02 23:17:16 +00001/*
2 * (C) Copyright 2001
3 * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
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/*
25 * flash.c - flash support for the 512k, 8bit boot flash on the GEVB
26 * most of this file was based on the existing U-Boot
27 * flash drivers.
28 */
29
30#include <common.h>
31#include <mpc8xx.h>
32#include <galileo/gt64260R.h>
33#include <galileo/memory.h>
34#include "intel_flash.h"
35
36#define FLASH_ROM 0xFFFD /* unknown flash type */
37#define FLASH_RAM 0xFFFE /* unknown flash type */
38#define FLASH_MAN_UNKNOWN 0xFFFF0000
39
40/* #define DEBUG */
41/* #define FLASH_ID_OVERRIDE */ /* Hack to set type to 040B if ROM emulator is installed.
42 * Can be used to program a ROM in circuit if a programmer
43 * is not available by swapping the rom out. */
44
45/* Intel flash commands */
46int flash_erase_intel(flash_info_t *info, int s_first, int s_last);
47int write_word_intel(bank_addr_t addr, bank_word_t value);
48
49flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
50
51/*-----------------------------------------------------------------------
52 * Functions
53 */
54static ulong flash_get_size (int portwidth, vu_long *addr, flash_info_t *info);
55static int write_word (flash_info_t *info, ulong dest, ulong data);
56static void flash_get_offsets (ulong base, flash_info_t *info);
wdenk232fe0b2003-09-02 22:48:03 +000057static flash_info_t *flash_get_info(ulong base);
wdenk7ebf7442002-11-02 23:17:16 +000058
59/*-----------------------------------------------------------------------
60 */
61
62unsigned long
63flash_init (void)
64{
65 unsigned int i;
66 unsigned long size_b0 = 0, size_b1 = 0;
67 unsigned long base, flash_size;
68
69 /* Init: no FLASHes known */
70 for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
71 flash_info[i].flash_id = FLASH_UNKNOWN;
72 }
73
74 /* the boot flash */
75 base = CFG_FLASH_BASE;
wdenk232fe0b2003-09-02 22:48:03 +000076#ifndef CFG_BOOT_FLASH_WIDTH
77#define CFG_BOOT_FLASH_WIDTH 1
78#endif
79 size_b0 = flash_get_size(CFG_BOOT_FLASH_WIDTH, (vu_long *)base,
80 &flash_info[0]);
wdenk7ebf7442002-11-02 23:17:16 +000081
82 printf("[%ldkB@%lx] ", size_b0/1024, base);
83
84 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
85 printf ("## Unknown FLASH at %08lx: Size = 0x%08lx = %ld MB\n",
86 base, size_b0, size_b0<<20);
87 }
88
89 base = memoryGetDeviceBaseAddress(CFG_EXTRA_FLASH_DEVICE);
90 for(i=1;i<CFG_MAX_FLASH_BANKS;i++) {
91 unsigned long size = flash_get_size(CFG_EXTRA_FLASH_WIDTH, (vu_long *)base, &flash_info[i]);
92
93 printf("[%ldMB@%lx] ", size>>20, base);
94
95 if (flash_info[i].flash_id == FLASH_UNKNOWN) {
96 if(i==1) {
97 printf ("## Unknown FLASH at %08lx: Size = 0x%08lx = %ld MB\n",
98 base, size_b1, size_b1<<20);
99 }
100 break;
101 }
102 size_b1+=size;
103 base+=size;
104 }
105
wdenk232fe0b2003-09-02 22:48:03 +0000106#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
107 /* monitor protection ON by default */
108 flash_protect(FLAG_PROTECT_SET,
109 CFG_MONITOR_BASE,
110 CFG_MONITOR_BASE + monitor_flash_len - 1,
111 flash_get_info(CFG_MONITOR_BASE));
112#endif
113
114#ifdef CFG_ENV_IS_IN_FLASH
115 /* ENV protection ON by default */
116 flash_protect(FLAG_PROTECT_SET,
117 CFG_ENV_ADDR,
118 CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
119 flash_get_info(CFG_ENV_ADDR));
120#endif
121
wdenk7ebf7442002-11-02 23:17:16 +0000122 flash_size = size_b0 + size_b1;
123 return flash_size;
124}
125
126/*-----------------------------------------------------------------------
127 */
128static void
129flash_get_offsets (ulong base, flash_info_t *info)
130{
131 int i;
132 int sector_size;
133
134 if(!info->sector_count) return;
135
136 /* set up sector start address table */
137 switch(info->flash_id & FLASH_TYPEMASK) {
138 case FLASH_AM040:
139 case FLASH_28F128J3A:
140 case FLASH_28F640J3A:
141 case FLASH_RAM:
142 /* this chip has uniformly spaced sectors */
143 sector_size=info->size/info->sector_count;
144 for (i = 0; i < info->sector_count; i++)
145 info->start[i] = base + (i * sector_size);
146 break;
147 default:
148 if (info->flash_id & FLASH_BTYPE) {
149 /* set sector offsets for bottom boot block type */
150 info->start[0] = base + 0x00000000;
151 info->start[1] = base + 0x00008000;
152 info->start[2] = base + 0x0000C000;
153 info->start[3] = base + 0x00010000;
154 for (i = 4; i < info->sector_count; i++) {
155 info->start[i] = base + (i * 0x00020000) - 0x00060000;
156 }
157 } else {
158 /* set sector offsets for top boot block type */
159 i = info->sector_count - 1;
160 info->start[i--] = base + info->size - 0x00008000;
161 info->start[i--] = base + info->size - 0x0000C000;
162 info->start[i--] = base + info->size - 0x00010000;
163 for (; i >= 0; i--) {
164 info->start[i] = base + i * 0x00020000;
165 }
166 }
167 }
wdenk232fe0b2003-09-02 22:48:03 +0000168}
169
170/*-----------------------------------------------------------------------
171 */
172
173static flash_info_t *flash_get_info(ulong base)
174{
175 int i;
176 flash_info_t * info;
177
178 for (i = 0; i < CFG_MAX_FLASH_BANKS; i ++) {
179 info = & flash_info[i];
180 if (info->start[0] <= base && base <= info->start[0] + info->size - 1)
181 break;
182 }
183
184 return i == CFG_MAX_FLASH_BANKS ? 0 : info;
wdenk7ebf7442002-11-02 23:17:16 +0000185}
186
187/*-----------------------------------------------------------------------
188 */
189void
190flash_print_info (flash_info_t *info)
191{
192 int i;
193
194 if (info->flash_id == FLASH_UNKNOWN) {
195 printf ("missing or unknown FLASH type\n");
196 return;
197 }
198
199 switch (info->flash_id & FLASH_VENDMASK) {
200 case FLASH_MAN_AMD: printf ("AMD "); break;
201 case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
202 case FLASH_MAN_INTEL: printf ("INTEL "); break;
203 default: printf ("Unknown Vendor "); break;
204 }
205
206 switch (info->flash_id & FLASH_TYPEMASK) {
207 case FLASH_AM040:
208 printf ("AM29LV040B (4 Mbit, bottom boot sect)\n");
209 break;
210 case FLASH_AM400B:
211 printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
212 break;
213 case FLASH_AM400T:
214 printf ("AM29LV400T (4 Mbit, top boot sector)\n");
215 break;
216 case FLASH_AM800B:
217 printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
218 break;
219 case FLASH_AM800T:
220 printf ("AM29LV800T (8 Mbit, top boot sector)\n");
221 break;
222 case FLASH_AM160B:
223 printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
224 break;
225 case FLASH_AM160T:
226 printf ("AM29LV160T (16 Mbit, top boot sector)\n");
227 break;
228 case FLASH_AM320B:
229 printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
230 break;
231 case FLASH_AM320T:
232 printf ("AM29LV320T (32 Mbit, top boot sector)\n");
233 break;
234 case FLASH_28F640J3A:
235 printf ("28F640J3A (64 Mbit)\n");
236 break;
237 case FLASH_28F128J3A:
238 printf ("28F128J3A (128 Mbit)\n");
239 break;
240 case FLASH_ROM:
241 printf ("ROM\n");
242 break;
243 case FLASH_RAM:
244 printf ("RAM\n");
245 break;
246 default:
247 printf ("Unknown Chip Type\n");
248 break;
249 }
250
251 puts (" Size: ");
252 print_size (info->size, "");
253 printf (" in %d Sectors\n", info->sector_count);
254
255 printf (" Sector Start Addresses:");
256 for (i=0; i<info->sector_count; ++i) {
257 if ((i % 5) == 0)
258 printf ("\n ");
259 printf (" %08lX%s",
260 info->start[i],
261 info->protect[i] ? " (RO)" : " "
262 );
263 }
264 printf ("\n");
265 return;
266}
267
268/*-----------------------------------------------------------------------
269 */
270
271
272/*-----------------------------------------------------------------------
273 */
274
275/*
276 * The following code cannot be run from FLASH!
277 */
278
279static inline void flash_cmd(int width, volatile unsigned char *addr, int offset, unsigned char cmd)
280{
wdenk57b2d802003-06-27 21:31:46 +0000281 /* supports 1x8, 1x16, and 2x16 */
282 /* 2x8 and 4x8 are not supported */
wdenk7ebf7442002-11-02 23:17:16 +0000283 if(width==4) {
284 /* assuming chips are in 16 bit mode */
285 /* 2x16 */
286 unsigned long cmd32=(cmd<<16)|cmd;
287 *(volatile unsigned long *)(addr+offset*2)=cmd32;
wdenk232fe0b2003-09-02 22:48:03 +0000288 } else if (width == 2) {
289 /* 1x16 */
290 *(volatile unsigned short *)((unsigned short*)addr+offset)=cmd;
wdenk7ebf7442002-11-02 23:17:16 +0000291 } else {
wdenk232fe0b2003-09-02 22:48:03 +0000292 /* 1x8 */
wdenk7ebf7442002-11-02 23:17:16 +0000293 *(volatile unsigned char *)(addr+offset)=cmd;
294 }
295}
296
297static ulong
298flash_get_size (int portwidth, vu_long *addr, flash_info_t *info)
299{
300 short i;
301 volatile unsigned char *caddr = (unsigned char *)addr;
302 volatile unsigned short *saddr = (unsigned short *)addr;
303 volatile unsigned long *laddr = (unsigned long *)addr;
304 char old[2], save;
305 ulong id, manu, base = (ulong)addr;
306
307 info->portwidth=portwidth;
308
309 save = *caddr;
310
311 flash_cmd(portwidth,caddr,0,0xf0);
312 flash_cmd(portwidth,caddr,0,0xf0);
313
314 udelay(10);
315
316 old[0] = caddr[0];
317 old[1] = caddr[1];
318
319
320 if(old[0]!=0xf0) {
321 flash_cmd(portwidth,caddr,0,0xf0);
322 flash_cmd(portwidth,caddr,0,0xf0);
323
324 udelay(10);
325
326 if(*caddr==0xf0) {
327 /* this area is ROM */
328 *caddr=save;
329#ifndef FLASH_ID_OVERRIDE
330 info->flash_id = FLASH_ROM + FLASH_MAN_UNKNOWN;
331 info->sector_count = 8;
332 info->size = 0x80000;
333#else
334 info->flash_id = FLASH_MAN_AMD + FLASH_AM040;
335 info->sector_count = 8;
336 info->size = 0x80000;
337 info->chipwidth=1;
338#endif
339 flash_get_offsets(base, info);
340 return info->size;
341 }
342 } else {
343 *caddr=0;
344
345 udelay(10);
346
347 if(*caddr==0) {
348 /* this area is RAM */
349 *caddr=save;
350 info->flash_id = FLASH_RAM + FLASH_MAN_UNKNOWN;
351 info->sector_count = 8;
352 info->size = 0x80000;
353 flash_get_offsets(base, info);
354 return info->size;
355 }
356 flash_cmd(portwidth,caddr,0,0xf0);
357
358 udelay(10);
359 }
360
361 /* Write auto select command: read Manufacturer ID */
362 flash_cmd(portwidth,caddr,0x555,0xAA);
363 flash_cmd(portwidth,caddr,0x2AA,0x55);
364 flash_cmd(portwidth,caddr,0x555,0x90);
365
366 udelay(10);
367
368 if ((caddr[0] == old[0]) &&
369 (caddr[1] == old[1])) {
370
371 /* this area is ROM */
372#ifndef FLASH_ID_OVERRIDE
373 info->flash_id = FLASH_ROM + FLASH_MAN_UNKNOWN;
374 info->sector_count = 8;
375 info->size = 0x80000;
376#else
377 info->flash_id = FLASH_MAN_AMD + FLASH_AM040;
378 info->sector_count = 8;
379 info->size = 0x80000;
380 info->chipwidth=1;
381#endif
382 flash_get_offsets(base, info);
383 return info->size;
384#ifdef DEBUG
385 } else {
386 printf("%px%d: %02x:%02x -> %02x:%02x\n",
387 caddr, portwidth, old[0], old[1],
388 caddr[0], caddr[1]);
389#endif
390 }
391
392 switch(portwidth) {
393 case 1:
394 manu = caddr[0];
395 manu |= manu<<16;
396 id = caddr[1];
397 break;
398 case 2:
399 manu = saddr[0];
400 manu |= manu<<16;
401 id = saddr[1];
402 id |= id<<16;
403 break;
404 case 4:
405 manu = laddr[0];
406 id = laddr[1];
407 break;
408 default:
409 id = manu = -1;
410 break;
411 }
412
413#ifdef DEBUG
414 printf("\n%08lx:%08lx:%08lx\n", base, manu, id);
415 printf("%08lx %08lx %08lx %08lx\n",
416 laddr[0],laddr[1],laddr[2],laddr[3]);
417#endif
418
419 switch (manu) {
420 case AMD_MANUFACT:
421 info->flash_id = FLASH_MAN_AMD;
422 break;
423 case FUJ_MANUFACT:
424 info->flash_id = FLASH_MAN_FUJ;
425 break;
426 case INTEL_MANUFACT:
427 info->flash_id = FLASH_MAN_INTEL;
428 break;
429 default:
430 printf("Unknown Mfr [%08lx]:%08lx\n", manu, id);
431 info->flash_id = FLASH_UNKNOWN;
432 info->sector_count = 0;
433 info->size = 0;
434 return (0); /* no or unknown flash */
435 }
436
437 switch (id) {
438 case AMD_ID_LV400T:
439 info->flash_id += FLASH_AM400T;
440 info->sector_count = 11;
441 info->size = 0x00100000;
442 info->chipwidth=1;
443 break; /* => 1 MB */
444
445 case AMD_ID_LV400B:
446 info->flash_id += FLASH_AM400B;
447 info->sector_count = 11;
448 info->size = 0x00100000;
449 info->chipwidth=1;
450 break; /* => 1 MB */
451
452 case AMD_ID_LV800T:
453 info->flash_id += FLASH_AM800T;
454 info->sector_count = 19;
455 info->size = 0x00200000;
456 info->chipwidth=1;
457 break; /* => 2 MB */
458
459 case AMD_ID_LV800B:
460 info->flash_id += FLASH_AM800B;
461 info->sector_count = 19;
462 info->size = 0x00200000;
463 info->chipwidth=1;
464 break; /* => 2 MB */
465
466 case AMD_ID_LV160T:
467 info->flash_id += FLASH_AM160T;
468 info->sector_count = 35;
469 info->size = 0x00400000;
470 info->chipwidth=1;
471 break; /* => 4 MB */
472
473 case AMD_ID_LV160B:
474 info->flash_id += FLASH_AM160B;
475 info->sector_count = 35;
476 info->size = 0x00400000;
477 info->chipwidth=1;
478 break; /* => 4 MB */
479#if 0 /* enable when device IDs are available */
480 case AMD_ID_LV320T:
481 info->flash_id += FLASH_AM320T;
482 info->sector_count = 67;
483 info->size = 0x00800000;
484 break; /* => 8 MB */
485
486 case AMD_ID_LV320B:
487 info->flash_id += FLASH_AM320B;
488 info->sector_count = 67;
489 info->size = 0x00800000;
490 break; /* => 8 MB */
491#endif
492 case AMD_ID_LV040B:
493 info->flash_id += FLASH_AM040;
494 info->sector_count = 8;
495 info->size = 0x80000;
496 info->chipwidth=1;
497 break;
498
499 case INTEL_ID_28F640J3A:
500 info->flash_id += FLASH_28F640J3A;
501 info->sector_count = 64;
502 info->size = 128*1024 * 64; /* 128kbytes x 64 blocks */
503 info->chipwidth=2;
504 if(portwidth==4) info->size*=2; /* 2x16 */
505 break;
506
507 case INTEL_ID_28F128J3A:
508 info->flash_id += FLASH_28F128J3A;
509 info->sector_count = 128;
510 info->size = 128*1024 * 128; /* 128kbytes x 128 blocks */
511 info->chipwidth=2;
512 if(portwidth==4) info->size*=2; /* 2x16 */
513 break;
514
515 default:
516 printf("Unknown id %lx:[%lx]\n", manu, id);
517 info->flash_id = FLASH_UNKNOWN;
518 info->chipwidth=1;
519 return (0); /* => no or unknown flash */
520
521 }
522
523 flash_get_offsets(base, info);
524
525#if 0
526 /* set up sector start address table */
527 if (info->flash_id & FLASH_AM040) {
528 /* this chip has uniformly spaced sectors */
529 for (i = 0; i < info->sector_count; i++)
530 info->start[i] = base + (i * 0x00010000);
531
532 } else if (info->flash_id & FLASH_BTYPE) {
533 /* set sector offsets for bottom boot block type */
534 info->start[0] = base + 0x00000000;
535 info->start[1] = base + 0x00008000;
536 info->start[2] = base + 0x0000C000;
537 info->start[3] = base + 0x00010000;
538 for (i = 4; i < info->sector_count; i++) {
539 info->start[i] = base + (i * 0x00020000) - 0x00060000;
540 }
541 } else {
542 /* set sector offsets for top boot block type */
543 i = info->sector_count - 1;
544 info->start[i--] = base + info->size - 0x00008000;
545 info->start[i--] = base + info->size - 0x0000C000;
546 info->start[i--] = base + info->size - 0x00010000;
547 for (; i >= 0; i--) {
548 info->start[i] = base + i * 0x00020000;
549 }
550 }
551#endif
552
553 /* check for protected sectors */
554 for (i = 0; i < info->sector_count; i++) {
555 /* read sector protection at sector address, (A7 .. A0)=0x02 */
556 /* D0 = 1 if protected */
557 caddr = (volatile unsigned char *)(info->start[i]);
558 saddr = (volatile unsigned short *)(info->start[i]);
559 laddr = (volatile unsigned long *)(info->start[i]);
560 if(portwidth==1)
561 info->protect[i] = caddr[2] & 1;
562 else if(portwidth==2)
563 info->protect[i] = saddr[2] & 1;
564 else
565 info->protect[i] = laddr[2] & 1;
566 }
567
568 /*
569 * Prevent writes to uninitialized FLASH.
570 */
571 if (info->flash_id != FLASH_UNKNOWN) {
572 caddr = (volatile unsigned char *)info->start[0];
573
574 flash_cmd(portwidth,caddr,0,0xF0); /* reset bank */
575 }
576
577 return (info->size);
578}
579
580/* TODO: 2x16 unsupported */
581int
582flash_erase (flash_info_t *info, int s_first, int s_last)
583{
584 volatile unsigned char *addr = (char *)(info->start[0]);
585 int flag, prot, sect, l_sect;
586 ulong start, now, last;
587
588 /* TODO: 2x16 unsupported */
589 if(info->portwidth==4) return 1;
590
591 if((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) return 1;
592 if((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) {
593 for (sect = s_first; sect<=s_last; sect++) {
594 int sector_size=info->size/info->sector_count;
595 addr = (char *)(info->start[sect]);
596 memset((void *)addr, 0, sector_size);
597 }
598 return 0;
599 }
600
601 if ((s_first < 0) || (s_first > s_last)) {
602 if (info->flash_id == FLASH_UNKNOWN) {
603 printf ("- missing\n");
604 } else {
605 printf ("- no sectors to erase\n");
606 }
607 return 1;
608 }
609
610 if ((info->flash_id&FLASH_VENDMASK) == FLASH_MAN_INTEL) {
611 return flash_erase_intel(info,
612 (unsigned short)s_first,
613 (unsigned short)s_last);
614 }
615
616#if 0
617 if ((info->flash_id == FLASH_UNKNOWN) ||
618 (info->flash_id > FLASH_AMD_COMP)) {
619 printf ("Can't erase unknown flash type %08lx - aborted\n",
620 info->flash_id);
621 return 1;
622 }
623#endif
624
625 prot = 0;
626 for (sect=s_first; sect<=s_last; ++sect) {
627 if (info->protect[sect]) {
628 prot++;
629 }
630 }
631
632 if (prot) {
633 printf ("- Warning: %d protected sectors will not be erased!\n",
634 prot);
635 } else {
636 printf ("\n");
637 }
638
639 l_sect = -1;
640
641 /* Disable interrupts which might cause a timeout here */
642 flag = disable_interrupts();
643
644 flash_cmd(info->portwidth,addr,0x555,0xAA);
645 flash_cmd(info->portwidth,addr,0x2AA,0x55);
646 flash_cmd(info->portwidth,addr,0x555,0x80);
647 flash_cmd(info->portwidth,addr,0x555,0xAA);
648 flash_cmd(info->portwidth,addr,0x2AA,0x55);
649
650 /* Start erase on unprotected sectors */
651 for (sect = s_first; sect<=s_last; sect++) {
652 if (info->protect[sect] == 0) { /* not protected */
653 addr = (char *)(info->start[sect]);
654 flash_cmd(info->portwidth,addr,0,0x30);
655 l_sect = sect;
656 }
657 }
658
659 /* re-enable interrupts if necessary */
660 if (flag)
661 enable_interrupts();
662
663 /* wait at least 80us - let's wait 1 ms */
664 udelay (1000);
665
666 /*
667 * We wait for the last triggered sector
668 */
669 if (l_sect < 0)
670 goto DONE;
671
672 start = get_timer (0);
673 last = start;
674 addr = (volatile unsigned char *)(info->start[l_sect]);
675 /* broken for 2x16: TODO */
676 while ((addr[0] & 0x80) != 0x80) {
677 if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
678 printf ("Timeout\n");
679 return 1;
680 }
681 /* show that we're waiting */
682 if ((now - last) > 1000) { /* every second */
683 putc ('.');
684 last = now;
685 }
686 }
687
688DONE:
689 /* reset to read mode */
690 addr = (volatile unsigned char *)info->start[0];
691 flash_cmd(info->portwidth,addr,0,0xf0);
692 flash_cmd(info->portwidth,addr,0,0xf0);
693
694 printf (" done\n");
695 return 0;
696}
697
698/*-----------------------------------------------------------------------
699 * Copy memory to flash, returns:
700 * 0 - OK
701 * 1 - write timeout
702 * 2 - Flash not erased
703 */
704
705/* broken for 2x16: TODO */
706int
707write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
708{
709 ulong cp, wp, data;
710 int i, l, rc;
711
712 if(info->portwidth==4) return 1;
713
714 if((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) return 0;
715 if((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) {
716 memcpy((void *)addr, src, cnt);
717 return 0;
718 }
719
720 wp = (addr & ~3); /* get lower word aligned address */
721
722 /*
723 * handle unaligned start bytes
724 */
725 if ((l = addr - wp) != 0) {
726 data = 0;
727 for (i=0, cp=wp; i<l; ++i, ++cp) {
728 data = (data << 8) | (*(uchar *)cp);
729 }
730 for (; i<4 && cnt>0; ++i) {
731 data = (data << 8) | *src++;
732 --cnt;
733 ++cp;
734 }
735 for (; cnt==0 && i<4; ++i, ++cp) {
736 data = (data << 8) | (*(uchar *)cp);
737 }
738
739 if ((rc = write_word(info, wp, data)) != 0) {
740 return (rc);
741 }
742 wp += 4;
743 }
744
745 /*
746 * handle word aligned part
747 */
748 while (cnt >= 4) {
749 data = 0;
750 for (i=0; i<4; ++i) {
751 data = (data << 8) | *src++;
752 }
753 if ((rc = write_word(info, wp, data)) != 0) {
754 return (rc);
755 }
756 wp += 4;
757 cnt -= 4;
758 }
759
760 if (cnt == 0) {
761 return (0);
762 }
763
764 /*
765 * handle unaligned tail bytes
766 */
767 data = 0;
768 for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
769 data = (data << 8) | *src++;
770 --cnt;
771 }
772 for (; i<4; ++i, ++cp) {
773 data = (data << 8) | (*(uchar *)cp);
774 }
775
776 return (write_word(info, wp, data));
777}
778
779/*-----------------------------------------------------------------------
780 * Write a word to Flash, returns:
781 * 0 - OK
782 * 1 - write timeout
783 * 2 - Flash not erased
784 */
785/* broken for 2x16: TODO */
786static int
787write_word (flash_info_t *info, ulong dest, ulong data)
788{
789 volatile unsigned char *addr = (char *)(info->start[0]);
790 ulong start;
791 int flag, i;
792
793 if(info->portwidth==4) return 1;
794
795 if((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) return 1;
796 if((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) {
797 *(unsigned long *)dest=data;
798 return 0;
799 }
800 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
801 unsigned short low = data & 0xffff;
802 unsigned short hi = (data >> 16) & 0xffff;
803 int ret = write_word_intel((bank_addr_t)dest, hi);
804
805 if (!ret) ret = write_word_intel((bank_addr_t)(dest+2), low);
806
807 return ret;
808 }
809
810 /* Check if Flash is (sufficiently) erased */
811 if ((*((vu_long *)dest) & data) != data) {
812 return (2);
813 }
814 /* Disable interrupts which might cause a timeout here */
815 flag = disable_interrupts();
816
817 /* first, perform an unlock bypass command to speed up flash writes */
818 addr[0x555] = 0xAA;
819 addr[0x2AA] = 0x55;
820 addr[0x555] = 0x20;
821
822 /* write each byte out */
823 for (i = 0; i < 4; i++) {
824 char *data_ch = (char *)&data;
825 addr[0] = 0xA0;
826 *(((char *)dest)+i) = data_ch[i];
827 udelay(10); /* XXX */
828 }
829
830 /* we're done, now do an unlock bypass reset */
831 addr[0] = 0x90;
832 addr[0] = 0x00;
833
834 /* re-enable interrupts if necessary */
835 if (flag)
836 enable_interrupts();
837
838 /* data polling for D7 */
839 start = get_timer (0);
840 while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
841 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
842 return (1);
843 }
844 }
845 return (0);
846}