PageRenderTime 89ms CodeModel.GetById 32ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 0ms

/board/evb64260/flash.c

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