diff options
| author | wdenk <wdenk> | 2003-05-31 18:35:21 +0000 | 
|---|---|---|
| committer | wdenk <wdenk> | 2003-05-31 18:35:21 +0000 | 
| commit | 7a8e9bed17d7924a9c5c4699b1f6a3a0359524ed (patch) | |
| tree | 5c273df9c5efa7b1b6a4ca88904e48039ef591e8 /board/sc520_cdp/flash.c | |
| parent | 3b57fe0a70b903f4db66c558bb9828bc58acf06b (diff) | |
| download | olio-uboot-2014.01-7a8e9bed17d7924a9c5c4699b1f6a3a0359524ed.tar.xz olio-uboot-2014.01-7a8e9bed17d7924a9c5c4699b1f6a3a0359524ed.zip | |
* Patch by Marc Singer, 29 May 2003:LABEL_2003_05_31_2115
  Fixed rarp boot method for IA32 and other little-endian CPUs.
* Patch by Marc Singer, 28 May 2003:
  Added port I/O commands.
* Patch by Matthew McClintock, 28 May 2003
  - cpu/mpc824x/start.S: fix relocation code when booting from RAM
  - minor patches for utx8245
* Patch by Daniel Engström, 28 May 2003:
  x86 update
* Patch by Dave Ellis, 9 May 2003 + 27 May 2003:
  add nand flash support to SXNI855T configuration
  fix/extend nand flash support:
  - fix 'nand erase' command so does not erase bad blocks
  - fix 'nand write' command so does not write to bad blocks
  - fix nand_probe() so handles no flash detected properly
  - add doc/README.nand
  - add .jffs2 and .oob options to nand read/write
  - add 'nand bad' command to list bad blocks
  - add 'clean' option to 'nand erase' to write JFFS2 clean markers
  - make NAND read/write faster
* Patch by Rune Torgersen, 23 May 2003:
  Update for MPC8266ADS board
Diffstat (limited to 'board/sc520_cdp/flash.c')
| -rw-r--r-- | board/sc520_cdp/flash.c | 911 | 
1 files changed, 552 insertions, 359 deletions
| diff --git a/board/sc520_cdp/flash.c b/board/sc520_cdp/flash.c index 973cde8b9..1ebb32e2e 100644 --- a/board/sc520_cdp/flash.c +++ b/board/sc520_cdp/flash.c @@ -1,4 +1,7 @@  /* + * (C) Copyright 2002, 2003 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + *    * (C) Copyright 2002   * Sysgo Real-Time Solutions, GmbH <www.elinos.com>   * Alex Zuepke <azu@sysgo.de> @@ -23,31 +26,23 @@   */  #include <common.h> +#include <asm/io.h> +#include <pci.h> +#include <asm/ic/sc520.h> -ulong myflush(void); +#define PROBE_BUFFER_SIZE 1024 +static unsigned char buffer[PROBE_BUFFER_SIZE]; +#define SC520_MAX_FLASH_BANKS  3 +#define SC520_FLASH_BANK0_BASE 0x38000000  /* BOOTCS */ +#define SC520_FLASH_BANK1_BASE 0x30000000  /* ROMCS0 */ +#define SC520_FLASH_BANK2_BASE 0x28000000  /* ROMCS1 */ +#define SC520_FLASH_BANKSIZE   0x8000000 -#define FLASH_BANK_SIZE 0x400000	/* 4 MB */ -#define MAIN_SECT_SIZE  0x20000		/* 128 KB */ +#define AMD29LV016B_SIZE        0x200000 +#define AMD29LV016B_SECTORS     32 -flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; - - -#define CMD_READ_ARRAY		0x00F000F0 -#define CMD_UNLOCK1		0x00AA00AA -#define CMD_UNLOCK2		0x00550055 -#define CMD_ERASE_SETUP		0x00800080 -#define CMD_ERASE_CONFIRM	0x00300030 -#define CMD_PROGRAM		0x00A000A0 -#define CMD_UNLOCK_BYPASS	0x00200020 - -#define MEM_FLASH_ADDR1		(*(volatile u32 *)(CFG_FLASH_BASE + (0x00000555 << 2))) -#define MEM_FLASH_ADDR2		(*(volatile u32 *)(CFG_FLASH_BASE + (0x000002AA << 2))) - -#define BIT_ERASE_DONE		0x00800080 -#define BIT_RDY_MASK		0x00800080 -#define BIT_PROGRAM_ERROR	0x00200020 -#define BIT_TIMEOUT		0x80000000 /* our flag */ +flash_info_t    flash_info[SC520_MAX_FLASH_BANKS];  #define READY 1  #define ERR   2 @@ -56,394 +51,592 @@ flash_info_t    flash_info[CFG_MAX_FLASH_BANKS];  /*-----------------------------------------------------------------------   */ -ulong flash_init(void) + +static u32 _probe_flash(u32 addr, u32 bw, int il)  { -    int i, j; -    ulong size = 0; +	u32 result=0; +	 +	/* First do an unlock cycle for the benefit of +	 * devices that need it */ +	 +	switch (bw) { +		 +	case 1: +		*(volatile u8*)(addr+0x5555) = 0xaa; +		*(volatile u8*)(addr+0x2aaa) = 0x55; +		*(volatile u8*)(addr+0x5555) = 0x90; +		 +		/* Read vendor */ +		result = *(volatile u8*)addr; +		result <<= 16; +		 +		/* Read device */ +		result |= *(volatile u8*)(addr+2); +		 +		/* Return device to data mode */ +		*(volatile u8*)addr = 0xff; +		*(volatile u8*)(addr+0x5555), 0xf0;   +		break; +		 +	case 2: +		*(volatile u16*)(addr+0xaaaa) = 0xaaaa; +		*(volatile u16*)(addr+0x5554) = 0x5555; +		 +		/* Issue identification command */ +		if (il == 2) { +			*(volatile u16*)(addr+0xaaaa) = 0x9090; +			 +			/* Read vendor */ +			result = *(volatile u8*)addr; +			result <<= 16; +			 +			/* Read device */ +			result |= *(volatile u8*)(addr+2); +			 +			/* Return device to data mode */ +			*(volatile u16*)addr =  0xffff; +			*(volatile u16*)(addr+0xaaaa), 0xf0f0;   +			 +		} else { +			*(volatile u8*)(addr+0xaaaa) = 0x90; +			/* Read vendor */ +			result = *(volatile u16*)addr; +			result <<= 16; +			 +			/* Read device */ +			result |= *(volatile u16*)(addr+2); +			 +			/* Return device to data mode */ +			*(volatile u8*)addr = 0xff; +			*(volatile u8*)(addr+0xaaaa), 0xf0;  			 +		} +		 +		break; +		 +	 case 4: +		*(volatile u32*)(addr+0x5554) = 0xaaaaaaaa; +		*(volatile u32*)(addr+0xaaa8) = 0x55555555; +		 +		switch (il) { +		case 1: +			/* Issue identification command */ +			*(volatile u8*)(addr+0x5554) = 0x90; +			 +			/* Read vendor */ +			result = *(volatile u16*)addr; +			result <<= 16; +		 +			/* Read device */ +			result |= *(volatile u16*)(addr+4); +			 +			/* Return device to data mode */ +			*(volatile u8*)addr =  0xff; +			*(volatile u8*)(addr+0x5554), 0xf0;   +			break; +			 +		case 2: +			/* Issue identification command */ +			*(volatile u32*)(addr + 0x5554) = 0x00900090; +			 +			/* Read vendor */ +			result = *(volatile u16*)addr; +			result <<= 16; +			 +			/* Read device */ +			result |= *(volatile u16*)(addr+4); +			 +			/* Return device to data mode */ +			*(volatile u32*)addr =  0x00ff00ff; +			*(volatile u32*)(addr+0x5554), 0x00f000f0;   +			break; +			 +		case 4: +			/* Issue identification command */ +			*(volatile u32*)(addr+0x5554) = 0x90909090; +			 +			/* Read vendor */ +			result = *(volatile u8*)addr; +			result <<= 16; +			 +			/* Read device */ +			result |= *(volatile u8*)(addr+4); +			 +			/* Return device to data mode */ +			*(volatile u32*)addr =  0xffffffff; +			*(volatile u32*)(addr+0x5554), 0xf0f0f0f0;  +			break; +		} +		break; +	} +	 +	 +	 +	return result; +} -    for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) -    { -	ulong flashbase = 0; -	flash_info[i].flash_id = -	  (AMD_MANUFACT & FLASH_VENDMASK) | -	  (AMD_ID_LV160B & FLASH_TYPEMASK); -	flash_info[i].size = FLASH_BANK_SIZE; -	flash_info[i].sector_count = CFG_MAX_FLASH_SECT; -	memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); -	if (i == 0) -	  flashbase = PHYS_FLASH_1; -	else -	  panic("configured to many flash banks!\n"); -	for (j = 0; j < flash_info[i].sector_count; j++) -	{ +extern int _probe_flash_end; +asm ("_probe_flash_end:\n" +     ".long 0\n"); -	    if (j <= 3) -	    { -		/* 1st one is 32 KB */ -		if (j == 0) -		{ -			flash_info[i].start[j] = flashbase + 0; -		} +static int identify_flash(unsigned address, int width) +{ +	int is;	 +	int device; +	int vendor;	 +	int size; +	unsigned res; +	 +	u32 (*_probe_flash_ptr)(u32 a, u32 bw, int il); +	 +	size = (unsigned)&_probe_flash_end - (unsigned)_probe_flash;  +	 +	if (size > PROBE_BUFFER_SIZE) { +		printf("_probe_flash() routine too large (%d) %p - %p\n", +		       size, &_probe_flash_end, _probe_flash); +		return 0; +	} +	 +	memcpy(buffer, _probe_flash, size); +	_probe_flash_ptr = (void*)buffer; +	 +	is = disable_interrupts(); +	res = _probe_flash_ptr(address, width, 1); +	if (is) { +		enable_interrupts(); +	} +	 +	 +        vendor = res >> 16; +	device = res & 0xffff; +	 +		 +	return res; +} -		/* 2nd and 3rd are both 16 KB */ -		if ((j == 1) || (j == 2)) -		{ -			flash_info[i].start[j] = flashbase + 0x8000 + (j-1)*0x4000; +ulong flash_init(void) +{ +	int i, j; +	ulong size = 0; +	 +	for (i = 0; i < SC520_MAX_FLASH_BANKS; i++) { +		unsigned id; +		ulong flashbase = 0; +		int sectsize = 0;  +		 +		memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); +		switch (i) { +		case 0: +			flashbase = SC520_FLASH_BANK0_BASE; +			break; +		case 1: +			flashbase = SC520_FLASH_BANK1_BASE; +			break; +		case 2: +			flashbase = SC520_FLASH_BANK2_BASE; +			break; +		default: +			panic("configured to many flash banks!\n");  		} - -		/* 4th 64 KB */ -		if (j == 3) -		{ -			flash_info[i].start[j] = flashbase + 0x10000; +		 +		id = identify_flash(flashbase, 4); +		switch (id & 0x00ff00ff) { +		case 0x000100c8: +			/* 29LV016B/29LV017B */ +			flash_info[i].flash_id = +				(AMD_MANUFACT & FLASH_VENDMASK) | +				(AMD_ID_LV016B & FLASH_TYPEMASK); +			 +			flash_info[i].size = AMD29LV016B_SIZE*4; +			flash_info[i].sector_count = AMD29LV016B_SECTORS; +			sectsize = (AMD29LV016B_SIZE*4)/AMD29LV016B_SECTORS; +			printf("Bank %d: 4 x AMD 29LV017B\n", i); +			break; +			 +			 +		default: +			printf("Bank %d have unknown flash %08x\n", i, id); +			flash_info[i].flash_id = FLASH_UNKNOWN; +			continue; +		} +		 +		for (j = 0; j < flash_info[i].sector_count; j++) { +			flash_info[i].start[j] = flashbase + j * sectsize;  		} -	    } -	    else -	    { -		flash_info[i].start[j] = flashbase + (j - 3)*MAIN_SECT_SIZE; -	    } +		size += flash_info[i].size; +		 +		flash_protect(FLAG_PROTECT_CLEAR, +			      flash_info[i].start[0], +			       flash_info[i].start[0] + flash_info[i].size - 1, +			      &flash_info[i]);  	} -	size += flash_info[i].size; -    } - -    /* -     * Protect monitor and environment sectors -     */ -    flash_protect(FLAG_PROTECT_SET, -		  i386boot_start-CFG_FLASH_BASE, -		  i386boot_end-CFG_FLASH_BASE, -		  &flash_info[0]); - -    flash_protect(FLAG_PROTECT_SET, -		  CFG_ENV_ADDR, -		  CFG_ENV_ADDR + CFG_ENV_SIZE - 1, -		  &flash_info[0]); -    return size; +	 +	/* +	 * Protect monitor and environment sectors +	 */ +	flash_protect(FLAG_PROTECT_SET, +		      i386boot_start, +		      i386boot_end, +		      &flash_info[0]); +#ifdef CFG_ENV_ADDR +	flash_protect(FLAG_PROTECT_SET, +		      CFG_ENV_ADDR, +		      CFG_ENV_ADDR + CFG_ENV_SIZE - 1, +		      &flash_info[0]); +#endif	 +	return size;  }  /*-----------------------------------------------------------------------   */ -void flash_print_info  (flash_info_t *info) +void flash_print_info(flash_info_t *info)  { -    int i; - -    switch (info->flash_id & FLASH_VENDMASK) -    { -    case (AMD_MANUFACT & FLASH_VENDMASK): -	printf("AMD: "); -	break; -    default: -	printf("Unknown Vendor "); -	break; -    } - -    switch (info->flash_id & FLASH_TYPEMASK) -    { -    case (AMD_ID_LV160B & FLASH_TYPEMASK): -	printf("2x Amd29F160BB (16Mbit)\n"); -	break; -    default: -	printf("Unknown Chip Type\n"); -	goto Done; -	break; -    } - -    printf("  Size: %ld MB in %d Sectors\n", -	   info->size >> 20, info->sector_count); - -    printf("  Sector Start Addresses:"); -    for (i = 0; i < info->sector_count; i++) -    { -	if ((i % 5) == 0) -	{ -	    printf ("\n   "); +	int i; +	 +	switch (info->flash_id & FLASH_VENDMASK) { +		 +	case (AMD_MANUFACT & FLASH_VENDMASK): +		printf("AMD:   "); +		switch (info->flash_id & FLASH_TYPEMASK) { +		case (AMD_ID_LV016B & FLASH_TYPEMASK): +			printf("4x AMD29LV017B (4x16Mbit)\n"); +			break; +		default: +			printf("Unknown Chip Type\n"); +			goto done; +			break; +		} +		 +		break; +	default: +		printf("Unknown Vendor "); +		break;  	} -	printf (" %08lX%s", info->start[i], -		info->protect[i] ? " (RO)" : "     "); -    } -    printf ("\n"); - -Done: +	 +	 +	printf("  Size: %ld MB in %d Sectors\n", +	       info->size >> 20, info->sector_count); +	 +	printf("  Sector Start Addresses:"); +	for (i = 0; i < info->sector_count; i++) { +		if ((i % 5) == 0) { +			printf ("\n   "); +		} +		printf (" %08lX%s", info->start[i], +			info->protect[i] ? " (RO)" : "     "); +	} +	printf ("\n"); +	 +	done:  }  /*-----------------------------------------------------------------------   */ -int	flash_erase (flash_info_t *info, int s_first, int s_last) -{ -    ulong result; -    int iflag, prot, sect; -    int rc = ERR_OK; -    int chip1, chip2; - -    /* first look for protection bits */ - -    if (info->flash_id == FLASH_UNKNOWN) -	return ERR_UNKNOWN_FLASH_TYPE; +/* this needs to be inlined, the SWTMRMMILLI register is reset by each read */ +#define __udelay(delay) \ +{	\ +	unsigned micro; \ +	unsigned milli=0; \ +	\ +	micro = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); \ +         \ +	for (;;) { \ +		\ +		milli += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); \ +		micro = *(volatile u16*)(0xfffef000+SC520_SWTMRMICRO); \ +		\ +		if ((delay) <= (micro + (milli * 1000))) { \ +			break; \ +		} \ +	} \ +} while (0)  -    if ((s_first < 0) || (s_first > s_last)) { -	return ERR_INVAL; -    } - -    if ((info->flash_id & FLASH_VENDMASK) != -	(AMD_MANUFACT & FLASH_VENDMASK)) { -	return ERR_UNKNOWN_FLASH_VENDOR; -    } - -    prot = 0; -    for (sect=s_first; sect<=s_last; ++sect) { -	if (info->protect[sect]) { -	    prot++; +static u32 _amd_erase_flash(u32 addr, u32 sector) +{ +	unsigned elapsed; +	 +	/* Issue erase */ +	*(volatile u32*)(addr + 0x5554) = 0xAAAAAAAA; +	*(volatile u32*)(addr + 0xaaa8) = 0x55555555; +	*(volatile u32*)(addr + 0x5554) = 0x80808080; +	/* And one unlock */ +	*(volatile u32*)(addr + 0x5554) = 0xAAAAAAAA; +	*(volatile u32*)(addr + 0xaaa8) = 0x55555555; +	/* Sector erase command comes last */ +	*(volatile u32*)(addr + sector) = 0x30303030; +	 +	elapsed = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); /* dummy read */ +	elapsed = 0; +	__udelay(50); +	while (((*(volatile u32*)(addr + sector)) & 0x80808080) != 0x80808080) { +		 +		elapsed += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); +		if (elapsed > ((CFG_FLASH_ERASE_TOUT/CFG_HZ) * 1000)) { +			*(volatile u32*)(addr) = 0xf0f0f0f0; +			return 1;			 +		}  	} -    } -    if (prot) -	return ERR_PROTECTED; - -    /* -     * Disable interrupts which might cause a timeout -     * here. Remember that our exception vectors are -     * at address 0 in the flash, and we don't want a -     * (ticker) exception to happen while the flash -     * chip is in programming mode. -     */ -    iflag = disable_interrupts(); - -    /* Start erase on unprotected sectors */ -    for (sect = s_first; sect<=s_last && !ctrlc(); sect++) -    { -	printf("Erasing sector %2d ... ", sect); - -	/* arm simple, non interrupt dependent timer */ -	reset_timer(); - -	if (info->protect[sect] == 0) -	{	/* not protected */ -	    vu_long *addr = (vu_long *)(info->start[sect]); - -	    MEM_FLASH_ADDR1 = CMD_UNLOCK1; -	    MEM_FLASH_ADDR2 = CMD_UNLOCK2; -	    MEM_FLASH_ADDR1 = CMD_ERASE_SETUP; - -	    MEM_FLASH_ADDR1 = CMD_UNLOCK1; -	    MEM_FLASH_ADDR2 = CMD_UNLOCK2; -	    *addr = CMD_ERASE_CONFIRM; - -	    /* wait until flash is ready */ -	    chip1 = chip2 = 0; +	 +	*(volatile u32*)(addr) = 0xf0f0f0f0; +	 +	return 0; +} -	    do -	    { -		result = *addr; +extern int _amd_erase_flash_end; +asm ("_amd_erase_flash_end:\n" +     ".long 0\n"); -		/* check timeout */ -		if (get_timer(0) > CFG_FLASH_ERASE_TOUT) -		{ -		    MEM_FLASH_ADDR1 = CMD_READ_ARRAY; -		    chip1 = TMO; -		    break; +int flash_erase(flash_info_t *info, int s_first, int s_last) +{ +	u32 (*_erase_flash_ptr)(u32 a, u32 so); +	int prot; +	int sect; +	unsigned size; +	 +	if ((s_first < 0) || (s_first > s_last)) { +		if (info->flash_id == FLASH_UNKNOWN) { +			printf("- missing\n"); +		} else { +			printf("- no sectors to erase\n");  		} - -		if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE) -			chip1 = READY; - -		if (!chip1 && (result & 0xFFFF) & BIT_PROGRAM_ERROR) -			chip1 = ERR; - -		if (!chip2 && (result >> 16) & BIT_ERASE_DONE) -			chip2 = READY; - -		if (!chip2 && (result >> 16) & BIT_PROGRAM_ERROR) -			chip2 = ERR; - -	    }  while (!chip1 || !chip2); - -	    MEM_FLASH_ADDR1 = CMD_READ_ARRAY; - -	    if (chip1 == ERR || chip2 == ERR) -	    { -		rc = ERR_PROG_ERROR; -		goto outahere; -	    } -	    if (chip1 == TMO) -	    { -		rc = ERR_TIMOUT; -		goto outahere; -	    } - -	    printf("ok.\n"); +		return 1;  	} -	else /* it was protected */ -	{ -	    printf("protected!\n"); +	 +	if ((info->flash_id & FLASH_VENDMASK) == (AMD_MANUFACT & FLASH_VENDMASK)) { +		size = (unsigned)&_amd_erase_flash_end - (unsigned)_amd_erase_flash;  +		 +		if (size > PROBE_BUFFER_SIZE) { +			printf("_amd_erase_flash() routine too large (%d) %p - %p\n", +			       size, &_amd_erase_flash_end, _amd_erase_flash); +			return 0; +		} +		 +		memcpy(buffer, _amd_erase_flash, size); +		_erase_flash_ptr = (void*)buffer; +	 +	}  else { +		printf ("Can't erase unknown flash type - aborted\n"); +		return 1; +	} +	 +	prot = 0; +	for (sect=s_first; sect<=s_last; ++sect) { +		if (info->protect[sect]) { +			prot++; +		} +	} +	 +	if (prot) { +		printf ("- Warning: %d protected sectors will not be erased!\n", prot); +	} else { +		printf ("\n"); +	} +		 +	 +	/* Start erase on unprotected sectors */ +	for (sect = s_first; sect<=s_last; sect++) { +		 +		if (info->protect[sect] == 0) { /* not protected */ +			int res; +			int flag; +			 +			/* Disable interrupts which might cause a timeout here */ +			flag = disable_interrupts(); +			 +			res = _erase_flash_ptr(info->start[0], info->start[sect]-info->start[0]); +			 +			/* re-enable interrupts if necessary */ +			if (flag) { +				enable_interrupts(); +			} +			 +			 +			if (res) { +				printf("Erase timed out, sector %d\n", sect); +				return res; +			} +			 +			putc('.');			 +		}		  	} -    } - -    if (ctrlc()) -      printf("User Interrupt!\n"); - -outahere: -    /* allow flash to settle - wait 10 ms */ -    udelay(10000); - -    if (iflag) -      enable_interrupts(); - -    return rc; +	 +	return 0;  }  /*----------------------------------------------------------------------- - * Copy memory to flash + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased   */ - -volatile static int write_word (flash_info_t *info, ulong dest, ulong data) +static int _amd_write_word(unsigned start, unsigned dest, unsigned data)  { -    vu_long *addr = (vu_long *)dest; -    ulong result; -    int rc = ERR_OK; -    int iflag; -    int chip1, chip2; - -    /* -     * Check if Flash is (sufficiently) erased -     */ -    result = *addr; -    if ((result & data) != data) -        return ERR_NOT_ERASED; - - -    /* -     * Disable interrupts which might cause a timeout -     * here. Remember that our exception vectors are -     * at address 0 in the flash, and we don't want a -     * (ticker) exception to happen while the flash -     * chip is in programming mode. -     */ -    iflag = disable_interrupts(); - -    MEM_FLASH_ADDR1 = CMD_UNLOCK1; -    MEM_FLASH_ADDR2 = CMD_UNLOCK2; -    MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS; -    *addr = CMD_PROGRAM; -    *addr = data; - -    /* arm simple, non interrupt dependent timer */ -    reset_timer(); - -    /* wait until flash is ready */ -    chip1 = chip2 = 0; -    do -    { -	result = *addr; - -	/* check timeout */ -	if (get_timer(0) > CFG_FLASH_ERASE_TOUT) -	{ -	    chip1 = ERR | TMO; -	    break; -	} -	if (!chip1 && ((result & 0x80) == (data & 0x80))) -		chip1 = READY; - -	if (!chip1 && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) -	{ -		result = *addr; - -		if ((result & 0x80) == (data & 0x80)) -			chip1 = READY; -		else -			chip1 = ERR; +	volatile u32 *addr2 = (u32*)start; +	volatile u32 *dest2 = (u32*)dest; +	volatile u32 *data2 = (u32*)&data; +	unsigned elapsed; +	 +	/* Check if Flash is (sufficiently) erased */ +	if ((*((volatile u32*)dest) & (u32)data) != (u32)data) { +		return 2;  	} - -	if (!chip2 && ((result & (0x80 << 16)) == (data & (0x80 << 16)))) -		chip2 = READY; - -	if (!chip2 && ((result >> 16) & BIT_PROGRAM_ERROR)) -	{ -		result = *addr; - -		if ((result & (0x80 << 16)) == (data & (0x80 << 16))) -			chip2 = READY; -		else -			chip2 = ERR; +		 +	addr2[0x5554] = 0xAAAAAAAA; +	addr2[0xaaa8] = 0x55555555; +	addr2[0x5554] = 0xA0A0A0A0; +	 +	dest2[0] = data; +	 +	elapsed = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); /* dummy read */ +	elapsed = 0; +	 +	/* data polling for D7 */ +	while ((dest2[0] & 0x80808080) != (data2[0] & 0x80808080)) { +		elapsed += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); +		if (elapsed > ((CFG_FLASH_WRITE_TOUT/CFG_HZ) * 1000)) { +			addr2[0] = 0xf0f0f0f0; +			return 1;			 +		}  	} -    }  while (!chip1 || !chip2); +	 +	addr2[0] = 0xf0f0f0f0; +	 +	return 0; +} -    *addr = CMD_READ_ARRAY; +extern int _amd_write_word_end; +asm ("_amd_write_word_end:\n" +     ".long 0\n"); -    if (chip1 == ERR || chip2 == ERR || *addr != data) -        rc = ERR_PROG_ERROR; -    if (iflag) -      enable_interrupts(); -    return rc; -} -  /*----------------------------------------------------------------------- - * Copy memory to flash. + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + * 3 - Unsupported flash type   */ -int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)  { -    ulong cp, wp, data; -    int l; -    int i, rc; +	ulong cp, wp, data; +	int i, l, rc; +	int flag; +	u32 (*_write_word_ptr)(unsigned start, unsigned dest, unsigned data); +	unsigned size; +	 +	if ((info->flash_id & FLASH_VENDMASK) == (AMD_MANUFACT & FLASH_VENDMASK)) { +		size = (unsigned)&_amd_write_word_end - (unsigned)_amd_write_word;  +		 +		if (size > PROBE_BUFFER_SIZE) { +			printf("_amd_write_word() routine too large (%d) %p - %p\n", +			       size, &_amd_write_word_end, _amd_write_word); +			return 0; +		} +		 +		memcpy(buffer, _amd_write_word, size); +		_write_word_ptr = (void*)buffer; +	 +	} else { +		printf ("Can't program unknown flash type - aborted\n"); +		return 3; +	} -    wp = (addr & ~3);	/* get lower word aligned address */ -    /* -     * handle unaligned start bytes -     */ -    if ((l = addr - wp) != 0) { -	data = 0; -	for (i=0, cp=wp; i<l; ++i, ++cp) { -	    data = (data >> 8) | (*(uchar *)cp << 24); +	wp = (addr & ~3);	/* get lower word aligned address */ +	 + +	/* +	 * handle unaligned start bytes +	 */ +	if ((l = addr - wp) != 0) { +		data = 0; +		for (i=0, cp=wp; i<l; ++i, ++cp) { +			data |= (*(uchar *)cp) << (8*i); +		} +		for (; i<4 && cnt>0; ++i) { +			data |= *src++ << (8*i); +			--cnt; +			++cp; +		} +		for (; cnt==0 && i<4; ++i, ++cp) { +			data |= (*(uchar *)cp)  << (8*i); +		} +		 +		/* Disable interrupts which might cause a timeout here */ +		flag = disable_interrupts(); +		 +		rc = _write_word_ptr(info->start[0], wp, data); +		 +		/* re-enable interrupts if necessary */ +		if (flag) { +			enable_interrupts(); +		} +		if (rc != 0) { +			return rc; +		} +		wp += 4;  	} -	for (; i<4 && cnt>0; ++i) { -	    data = (data >> 8) | (*src++ << 24); -	    --cnt; -	    ++cp; +	 +	/* +	 * handle word aligned part +	 */ +	while (cnt >= 4) { +		data = 0; +			        +		for (i=0; i<4; ++i) { +			data |= *src++ << (8*i); +		} +		 +		/* Disable interrupts which might cause a timeout here */ +		flag = disable_interrupts(); + +		rc = _write_word_ptr(info->start[0], wp, data); +		 +		/* re-enable interrupts if necessary */ +		if (flag) { +			enable_interrupts(); +		} +		if (rc != 0) { +			return rc; +		} +		wp  += 4; +		cnt -= 4;  	} -	for (; cnt==0 && i<4; ++i, ++cp) { -	    data = (data >> 8) | (*(uchar *)cp << 24); +	 +	if (cnt == 0) { +		return 0;  	} - -	if ((rc = write_word(info, wp, data)) != 0) { -	    return (rc); +	 +	/* +	 * handle unaligned tail bytes +	 */ +	data = 0; +	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { +		data |= *src++ << (8*i); +		--cnt;  	} -	wp += 4; -    } - -    /* -     * handle word aligned part -     */ -    while (cnt >= 4) { -	data = *((vu_long*)src); -	if ((rc = write_word(info, wp, data)) != 0) { -	    return (rc); +	 +	for (; i<4; ++i, ++cp) { +		data |= (*(uchar *)cp) << (8*i);  	} -	src += 4; -	wp  += 4; -	cnt -= 4; -    } - -    if (cnt == 0) { -	return ERR_OK; -    } -    /* -     * handle unaligned tail bytes -     */ -    data = 0; -    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { -	data = (data >> 8) | (*src++ << 24); -	--cnt; -    } -    for (; i<4; ++i, ++cp) { -	data = (data >> 8) | (*(uchar *)cp << 24); -    } +	/* Disable interrupts which might cause a timeout here */ +	flag = disable_interrupts(); -    return write_word(info, wp, data); +	rc = _write_word_ptr(info->start[0], wp, data); +	 +	/* re-enable interrupts if necessary */ +	if (flag) { +		enable_interrupts(); +	} +	 +	return rc; +	  } + + |