/****************************************************************************** * * Copyright (c) 2003 Windond Electronics Corp. * All rights reserved. * * $Workfile: flash.c $ * * $Author: andy $ ******************************************************************************/ /* * $History: flash.c $ * * ***************** Version 10 ***************** * User: Wschang0 Date: 04/01/07 Time: 11:34a * Updated in $/W90N740/FIRMWARE/WBLv1_1/Src * Increase the timeout count in polling16 function to avoid early timeout * in W29LV800BT * * ***************** Version 9 ***************** * User: Wschang0 Date: 03/12/25 Time: 4:06p * Updated in $/W90N740/FIRMWARE/WBLv1_1/Src * Add W29LV800BT, W29LV160DT, W29LV320DT * Remove the FLASH_NUM * * ***************** Version 8 ***************** * User: Wschang0 Date: 03/12/03 Time: 5:16p * Updated in $/W90N740/FIRMWARE/WBLv1_1/Src * Add MX29LV160BT/TT * Fixed MX28F160C3BT/TT. * The MX28F160C3 sectors are default to be locked, thus it needs unlock * it before write/erase it. * * ***************** Version 7 ***************** * User: Wschang0 Date: 03/11/05 Time: 11:03a * Updated in $/W90N740/FIRMWARE/WBLv1_1/Src * Add MX28F160C3T & MX28F160C3B * * ***************** Version 6 ***************** * User: Wschang0 Date: 03/09/26 Time: 2:30p * Updated in $/W90N740/FIRMWARE/WBLv1_1/Src * Correct the flash name of SST39VF160 in the flash[] table * * ***************** Version 5 ***************** * User: Wschang0 Date: 03/08/27 Time: 1:41p * Updated in $/W90N740/FIRMWARE/WBLv1_1/Src * Add FlushDCache to Write/Erase functions to avoid data cache * incohereance after Write/Erase flash. * * ***************** Version 4 ***************** * User: Wschang0 Date: 03/08/27 Time: 11:28a * Updated in $/W90N740/FIRMWARE/WBLv1_1/Src * Add SST 39VF160 flash type * * ***************** Version 3 ***************** * User: Wschang0 Date: 03/08/20 Time: 1:39p * Updated in $/W90N740/FIRMWARE/WBLv1_1/Src * * ***************** Version 2 ***************** * User: Wschang0 Date: 03/08/20 Time: 11:53a * Updated in $/W90N740/FIRMWARE/WBLv1_1/Src * Add VSS header */ #include #include #include // Update Note: // 8/19, 2003: Add Flash Tyep W28J800BT, W28J320TT, Fix the PID of W28J320BT // 8/07, 2003: W39L010 was protected when the erase address not in offset 0 // 7/24, 2003: Remove the redundant code. Time-out check, for reliability UINT32 _flash_size = 0; #define DELAY_1US 20 #define TIMEOUT 8000000UL static int normal_polling(unsigned int addr, unsigned short mask) { unsigned short rdata; unsigned int cnt; rdata=inph(addr)&mask; cnt=0; while( rdata != mask ) { rdata=inph(addr)&mask; if( cnt++ > TIMEOUT ) return -1; // time-out } return 0; } static int polling16(unsigned int addr, unsigned short data) { unsigned short rdata; int timeout=0x600000; rdata=inph(addr); while( rdata != data ) { rdata=inph(addr); if( (rdata&0x20) || !(timeout--) ) { rdata=inph(addr); if( rdata != data ) { //printf("polling time-out: %x\n",rdata); return -1; //polling time-out } } } return 0; } static INT CheckDataWidth(INT w) { INT extio_flag=0; // check if the platform (the Flash ROM is not in 0x7F000000) if( (ROMCON&0xFF000000)==0xFC000000 )extio_flag=1; switch(w) { case 8: if(extio_flag) { if( (EXT3CON&0x3)== 0x1 )return 1; else return 0; } else { if( (ROMCON&0xC)== 0x0 )return 1; else return 0; } case 16: if(extio_flag) { if( (EXT3CON&0x3)== 0x2 )return 1; else return 0; } else { if( (ROMCON&0xC)== 0x4 )return 1; else return 0; } case 32: if(extio_flag) { if( (EXT3CON&0x3)== 0x3 )return 1; else return 0; } else { if( (ROMCON&0xC)== 0x8 )return 1; else return 0; } default: return 0; } } void FlashDelay(UINT32 delay) { volatile UINT32 i; for(i=0;i= 0xF0000 ) { if( address < _flash_size ) return 0x2000; else return 0; } else return 0x10000; } INT BlockSize_W28J800BT(UINT32 address) { address-=FLASH_BASE; address&=0x7FFFFFFF; if( address < 0x10000 ) return 0x2000; else { if( address < _flash_size ) return 0x10000; else return 0; } } INT BlockErase_W28J800TT(UINT32 address,UINT32 size) { int status; if( (address&(size-1))!=0x0 )return -1;// not in the start of a block BlockLock_W28J800TT(address,BLOCK_UNLOCK); // The intel flash sector is default to be locked address|=0x80000000; outph(address,0x70); status=normal_polling( address, 0x80 ); if( status < 0 )return -1; // polling time-out outph(address,0x20); outph(address,0xD0); status=normal_polling( address, 0x80 ); if( status < 0 )return -1; // polling time-out outph(address,0xFFFF); FlushDCache(); return 0; } INT BlockWrite_W28J800TT(UINT32 address, UCHAR * data, UINT32 size) { UINT32 i; int status; address|=0x80000000; BlockLock_W28J800TT(address,BLOCK_UNLOCK); // The MX28F160C3 sector is default to be locked for(i=address;i= 0x3F0000 ) { if( address < _flash_size ) return 0x2000; else return 0; } else return 0x10000; } INT BlockSize_W28J320BT(UINT32 address) { address-=FLASH_BASE; address&=0x7FFFFFFF; if( address < 0x10000 ) return 0x2000; else { if( address < _flash_size ) return 0x10000; else return 0; } } INT BlockSize_W28J160BT(UINT32 address) { address-=FLASH_BASE; address&=0x7FFFFFFF; if( address < 0x10000 ) return 0x2000; else { if( address < _flash_size ) return 0x10000; else return 0; } } INT BlockSize_W28J160TT(UINT32 address) { address-=FLASH_BASE; address&=0x7FFFFFFF; if( address >= 0x1F0000 ) { if( address < 0x200000 ) return 0x2000; else return 0; } else return 0x10000; } INT BlockLock_W39L010(UINT32 address, UINT32 op) { return -1; } INT BlockSize_W39L010(UINT32 address) { address-=FLASH_BASE; address&=0x7FFFFFFF; if( address < _flash_size ) return 0x20000; else return 0; } INT BlockErase_W39L010(UINT32 address,UINT32 size) { UINT32 addr1,addr2; if( (address&(0x20000-1))!=0x0 )return -1;// not in the start of flash address|=0x80000000; addr1=(address&0xFFF00000)+(0x5555); addr2=(address&0xFFF00000)+(0x2AAA); outpb(addr1,0xAA); outpb(addr2,0x55); outpb(addr1,0x80); outpb(addr1,0xAA); outpb(addr2,0x55); outpb(addr1,0x10); while( (inpb(address)&0x80)!=0x80 ); FlushDCache(); return 0; } INT BlockWrite_W39L010(UINT32 address, UCHAR * data, UINT32 size) { UINT32 i; UINT32 addr1, addr2; address|=0x80000000; addr1=(address&0xFFF00000)+(0x5555); addr2=(address&0xFFF00000)+(0x2AAA); for(i=address;i