From: Russ D. <ru...@us...> - 2002-06-19 04:41:52
|
Update of /cvsroot/blob/blob/src/blob In directory usw-pr-cvs1:/tmp/cvs-serv27030 Modified Files: amd32.c Log Message: amd32 flash rewrite Index: amd32.c =================================================================== RCS file: /cvsroot/blob/blob/src/blob/amd32.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- amd32.c 29 Apr 2002 21:32:43 -0000 1.5 +++ amd32.c 19 Jun 2002 04:41:49 -0000 1.6 @@ -18,6 +18,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/21358.pdf + * */ #ident "$Id$" @@ -36,6 +38,9 @@ #define READ_ARRAY 0x00F000F0 #define UNLOCK1 0x00AA00AA #define UNLOCK2 0x00550055 +#define CONFIG_QUERY 0x00900090 +#define EXIT_UNLOCK1 0x00900090 +#define EXIT_UNLOCK2 0x00000000 #define ERASE_SETUP 0x00800080 #define ERASE_CONFIRM 0x00300030 #define PGM_SETUP 0x00A000A0 @@ -43,21 +48,70 @@ #define FLASH_ADDR1 (0x00000555 << 2) #define FLASH_ADDR2 (0x000002AA << 2) #define ERASE_DONE 0x00800080 +#define TOGGLE_BIT 0x00400040 #define RDY_MASK 0x00800080 #define STATUS_PGM_ERR 0x00200020 #define STATUS_ERASE_ERR 0x00000001 -#define READY 1 -#define ERR 2 +#define READY 1 +#define LAST_CHANCE 2 +#define LAST_CHANCE2 3 +#define ERR 4 +static void flash_read_array_amd32(void) +{ + *(u32 *)FLASH_ADDR1 = data_to_flash(READ_ARRAY); + barrier(); +} +/* NOT! for amd16.c, this examines one chip of the two chip interleave */ +static int get_status_amd16(u32 result, u32 last, int chip) +{ + if (chip == LAST_CHANCE) + chip = LAST_CHANCE2; + else if (!(result ^ last)) /* didn't toggle */ + chip = READY; + else if (chip == LAST_CHANCE2) + chip = ERR; + else if (result & STATUS_PGM_ERR) + chip = LAST_CHANCE; + return chip; +} -static int flash_erase_amd32(u32 *addr) +static int get_status_amd32(u32 *addr) { - u32 result; + u32 result, last; int chip1, chip2; + chip1 = chip2 = 0; + + last = data_from_flash(*addr); + barrier(); + + do { + result = data_from_flash(*addr); + barrier(); + + if ((chip1 != ERR && chip1 != READY)) + chip1 = get_status_amd16(result & 0xFFFF, last & 0xFFFF, chip1); + + if ((chip2 != ERR && chip2 != READY)) + chip2 = get_status_amd16(result >> 16, last >> 16, chip2); + + last = result; + + } while ((chip1 != ERR && chip1 != READY) || (chip2 != ERR && chip2 != READY)); + + if (chip1 == ERR || chip2 == ERR) return -1; + + return 0; + +} + + +static int flash_erase_amd32(u32 *addr) +{ /* prepare for erase */ *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1); barrier(); @@ -81,32 +135,18 @@ /* Russ, why don't you do this like the LART does? Just check * the status of chips with a single compare. -- Erik */ - chip1 = chip2 = 0; - - do { - result = data_from_flash(*addr); - barrier(); - - if (!chip1 && (result & 0xFFFF) & ERASE_DONE) - chip1 = READY; - if (!chip1 && (result & 0xFFFF) & STATUS_PGM_ERR) - chip1 = ERR; - - if (!chip2 && (result >> 16) & ERASE_DONE) - chip2 = READY; + /* Maybe this restructuring will amke it more clear, when the flash + * is done erasing, it will return 0xFFFF on read, which contains the + * status pgm err bit. So an error condition occurs if the status pgm + * bit is set, but the erase done bit is not. OK, switch this over + * to detecting bit toggles. --Russ */ - if (!chip2 && (result >> 16) & STATUS_PGM_ERR) - chip2 = ERR; - - } while(!chip1 || !chip2); - - /* put flash back into Read Array mode */ - *(u32 *)FLASH_ADDR1 = data_to_flash(READ_ARRAY); - barrier(); - - if (chip1 == ERR || chip2 == ERR) + if (get_status_amd32(addr) < 0) { + /* put flash back into Read Array mode */ + flash_read_array_amd32(); return -EFLASHERASE; + } return 0; } @@ -116,66 +156,22 @@ static int flash_write_amd32(u32 *dst, const u32* src) { - u32 result; - int chip1, chip2; *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1); barrier(); *(u32 *)FLASH_ADDR2 = data_to_flash(UNLOCK2); barrier(); - *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK_BYPASS); + *(u32 *)FLASH_ADDR1 = data_to_flash(PGM_SETUP); barrier(); - *dst = data_to_flash(PGM_SETUP); - barrier(); *dst = *src; barrier(); - /* This is a pretty similar situation to the erasing status below - * Bit 7 is ~(data bit 7) until the flash is complete. If bit 5 - * gets set before this happens, there is an error, but this could - * happen near the clock edge, and bit 5 could be the actual data - * before bit 7 changes, so we have to read again. -- Russ - */ - - chip1 = chip2 = 0; - do { - result = data_from_flash(*dst); + if (get_status_amd32(dst) < 0 || *dst != *src) { barrier(); - - if (!chip1 && ((result & 0x80) == (*src & 0x80))) - chip1 = READY; - - if (!chip1 && ((result & 0xFFFF) & STATUS_PGM_ERR)) { - result = data_from_flash(*dst); - barrier(); - - if ((result & 0x80) == (*src & 0x80)) - chip1 = READY; - else - chip1 = ERR; - } - - if (!chip2 && ((result & (0x80 << 16)) == (*src & (0x80 << 16)))) - chip2 = READY; - - if (!chip2 && ((result >> 16) & STATUS_PGM_ERR)) { - result = data_from_flash(*dst); - barrier(); - - if ((result & (0x80 << 16)) == (*src & (0x80 << 16))) - chip2 = READY; - else - chip2 = ERR; - } - - } while (!chip1 || !chip2); - - *(u32 *)FLASH_ADDR1 = data_to_flash(READ_ARRAY); - barrier(); - - if (chip1 == ERR || chip2 == ERR || *dst != *src) + flash_read_array_amd32(); return -EFLASHPGM; + } return 0; } @@ -203,8 +199,18 @@ static int flash_query_block_lock_amd32(u32 *blockStart) { - /* FIXME: this function should be fleshed out -- Erik */ - return 0; + int result; + *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1); + barrier(); + *(u32 *)FLASH_ADDR2 = data_to_flash(UNLOCK2); + barrier(); + *(u32 *)FLASH_ADDR1 = data_to_flash(CONFIG_QUERY); + barrier(); + + result = *(u32 *)(blockStart + 2); + flash_read_array_amd32(); + return !!result; + } |