|
|
|
@ -37,11 +37,11 @@ flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ |
|
|
|
|
typedef unsigned short FLASH_PORT_WIDTH; |
|
|
|
|
typedef volatile unsigned short FLASH_PORT_WIDTHV; |
|
|
|
|
|
|
|
|
|
#define FPW FLASH_PORT_WIDTH |
|
|
|
|
#define FPWV FLASH_PORT_WIDTHV |
|
|
|
|
#define FPW FLASH_PORT_WIDTH |
|
|
|
|
#define FPWV FLASH_PORT_WIDTHV |
|
|
|
|
|
|
|
|
|
#define FLASH_CYCLE1 0x0555 |
|
|
|
|
#define FLASH_CYCLE2 0x02aa |
|
|
|
|
#define FLASH_CYCLE2 0x02AA |
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
|
* Functions |
|
|
|
@ -96,9 +96,9 @@ static void flash_reset(flash_info_t *info) |
|
|
|
|
|
|
|
|
|
/* Put FLASH back in read mode */ |
|
|
|
|
if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) |
|
|
|
|
*base = (FPW)0x00FF00FF; /* Intel Read Mode */ |
|
|
|
|
*base = (FPW)0x00FF; /* Intel Read Mode */ |
|
|
|
|
else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) |
|
|
|
|
*base = (FPW)0x00F000F0; /* AMD Read Mode */ |
|
|
|
|
*base = (FPW)0x00F0; /* AMD Read Mode */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
@ -183,9 +183,9 @@ ulong flash_get_size (FPWV *addr, flash_info_t *info) |
|
|
|
|
|
|
|
|
|
/* Write auto select command: read Manufacturer ID */ |
|
|
|
|
/* Write auto select command sequence and test FLASH answer */ |
|
|
|
|
addr[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* for AMD, Intel ignores this */ |
|
|
|
|
addr[FLASH_CYCLE2] = (FPW)0x00550055; /* for AMD, Intel ignores this */ |
|
|
|
|
addr[FLASH_CYCLE1] = (FPW)0x00900090; /* selects Intel or AMD */ |
|
|
|
|
addr[FLASH_CYCLE1] = (FPW)0x00AA; /* for AMD, Intel ignores this */ |
|
|
|
|
addr[FLASH_CYCLE2] = (FPW)0x0055; /* for AMD, Intel ignores this */ |
|
|
|
|
addr[FLASH_CYCLE1] = (FPW)0x0090; /* selects Intel or AMD */ |
|
|
|
|
|
|
|
|
|
/* The manufacturer codes are only 1 byte, so just use 1 byte.
|
|
|
|
|
* This works for any bus width and any FLASH device width. |
|
|
|
@ -262,7 +262,7 @@ ulong flash_get_size (FPWV *addr, flash_info_t *info) |
|
|
|
|
int flash_erase (flash_info_t *info, int s_first, int s_last) |
|
|
|
|
{ |
|
|
|
|
FPWV *addr = (FPWV *)(info->start[0]); |
|
|
|
|
int flag, prot, sect, l_sect; |
|
|
|
|
int flag, prot, sect, ssect, l_sect; |
|
|
|
|
ulong start, now, last; |
|
|
|
|
|
|
|
|
|
printf ("flash_erase: first: %d last: %d\n", s_first, s_last); |
|
|
|
@ -297,58 +297,70 @@ int flash_erase (flash_info_t *info, int s_first, int s_last) |
|
|
|
|
printf ("\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
l_sect = -1; |
|
|
|
|
|
|
|
|
|
/* Disable interrupts which might cause a timeout here */ |
|
|
|
|
flag = disable_interrupts(); |
|
|
|
|
|
|
|
|
|
addr[0x0555] = 0x00AA; |
|
|
|
|
addr[0x02AA] = 0x0055; |
|
|
|
|
addr[0x0555] = 0x0080; |
|
|
|
|
addr[0x0555] = 0x00AA; |
|
|
|
|
addr[0x02AA] = 0x0055; |
|
|
|
|
|
|
|
|
|
/* Start erase on unprotected sectors */ |
|
|
|
|
for (sect = s_first; sect<=s_last; sect++) { |
|
|
|
|
if (info->protect[sect] == 0) { /* not protected */ |
|
|
|
|
addr = (FPWV *)(info->start[sect]); |
|
|
|
|
addr[0] = 0x0030; |
|
|
|
|
l_sect = sect; |
|
|
|
|
/*
|
|
|
|
|
* Start erase on unprotected sectors. |
|
|
|
|
* Since the flash can erase multiple sectors with one command |
|
|
|
|
* we take advantage of that by doing the erase in chunks of |
|
|
|
|
* 3 sectors. |
|
|
|
|
*/ |
|
|
|
|
for (sect = s_first; sect <= s_last; ) { |
|
|
|
|
l_sect = -1; |
|
|
|
|
|
|
|
|
|
addr[FLASH_CYCLE1] = 0x00AA; |
|
|
|
|
addr[FLASH_CYCLE2] = 0x0055; |
|
|
|
|
addr[FLASH_CYCLE1] = 0x0080; |
|
|
|
|
addr[FLASH_CYCLE1] = 0x00AA; |
|
|
|
|
addr[FLASH_CYCLE2] = 0x0055; |
|
|
|
|
|
|
|
|
|
/* do the erase in chunks of at most 3 sectors */ |
|
|
|
|
for (ssect = 0; ssect < 3; ssect++) { |
|
|
|
|
if ((sect + ssect) > s_last) |
|
|
|
|
break; |
|
|
|
|
if (info->protect[sect + ssect] == 0) { /* not protected */ |
|
|
|
|
addr = (FPWV *)(info->start[sect + ssect]); |
|
|
|
|
addr[0] = 0x0030; |
|
|
|
|
l_sect = sect + ssect; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
/* wait at least 80us - let's wait 1 ms */ |
|
|
|
|
udelay (1000); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We wait for the last triggered sector |
|
|
|
|
*/ |
|
|
|
|
if (l_sect < 0) |
|
|
|
|
goto DONE; |
|
|
|
|
|
|
|
|
|
start = get_timer (0); |
|
|
|
|
last = start; |
|
|
|
|
addr = (FPWV *)(info->start[l_sect]); |
|
|
|
|
while ((addr[0] & 0x0080) != 0x0080) { |
|
|
|
|
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { |
|
|
|
|
printf ("Timeout\n"); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
/* show that we're waiting */ |
|
|
|
|
if ((now - last) > 1000) { /* every second */ |
|
|
|
|
putc ('.'); |
|
|
|
|
last = now; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
addr = (FPWV *)info->start[0]; |
|
|
|
|
addr[0] = 0x00F0; /* reset bank */ |
|
|
|
|
sect += ssect; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* re-enable interrupts if necessary */ |
|
|
|
|
if (flag) |
|
|
|
|
enable_interrupts(); |
|
|
|
|
|
|
|
|
|
/* wait at least 80us - let's wait 1 ms */ |
|
|
|
|
udelay (1000); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We wait for the last triggered sector |
|
|
|
|
*/ |
|
|
|
|
if (l_sect < 0) |
|
|
|
|
goto DONE; |
|
|
|
|
|
|
|
|
|
start = get_timer (0); |
|
|
|
|
last = start; |
|
|
|
|
addr = (FPWV *)(info->start[l_sect]); |
|
|
|
|
while ((addr[0] & 0x00000080) != 0x00000080) { |
|
|
|
|
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { |
|
|
|
|
printf ("Timeout\n"); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
/* show that we're waiting */ |
|
|
|
|
if ((now - last) > 1000) { /* every second */ |
|
|
|
|
putc ('.'); |
|
|
|
|
last = now; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
DONE: |
|
|
|
|
/* reset to read mode */ |
|
|
|
|
addr = (FPWV *)info->start[0]; |
|
|
|
|
addr[0] = 0x000000F0; /* reset bank */ |
|
|
|
|
addr[0] = 0x00F0; /* reset bank */ |
|
|
|
|
|
|
|
|
|
printf (" done\n"); |
|
|
|
|
return 0; |
|
|
|
@ -432,9 +444,9 @@ static int write_word_amd (flash_info_t *info, FPWV *dest, FPW data) |
|
|
|
|
/* Disable interrupts which might cause a timeout here */ |
|
|
|
|
flag = disable_interrupts(); |
|
|
|
|
|
|
|
|
|
base[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* unlock */ |
|
|
|
|
base[FLASH_CYCLE2] = (FPW)0x00550055; /* unlock */ |
|
|
|
|
base[FLASH_CYCLE1] = (FPW)0x00A000A0; /* selects program mode */ |
|
|
|
|
base[FLASH_CYCLE1] = (FPW)0x00AA; /* unlock */ |
|
|
|
|
base[FLASH_CYCLE2] = (FPW)0x0055; /* unlock */ |
|
|
|
|
base[FLASH_CYCLE1] = (FPW)0x00A0; /* selects program mode */ |
|
|
|
|
|
|
|
|
|
*dest = data; /* start programming the data */ |
|
|
|
|
|
|
|
|
@ -445,9 +457,9 @@ static int write_word_amd (flash_info_t *info, FPWV *dest, FPW data) |
|
|
|
|
start = get_timer (0); |
|
|
|
|
|
|
|
|
|
/* data polling for D7 */ |
|
|
|
|
while ((*dest & (FPW)0x00000080) != (data & (FPW)0x00000080)) { |
|
|
|
|
while ((*dest & (FPW)0x0080) != (data & (FPW)0x0080)) { |
|
|
|
|
if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { |
|
|
|
|
*dest = (FPW)0x000000F0; /* reset bank */ |
|
|
|
|
*dest = (FPW)0x00F0; /* reset bank */ |
|
|
|
|
return (1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|