From b10d9039a678f38ed48f4cf032c6b3bc82848594 Mon Sep 17 00:00:00 2001 From: Oliver Schinagl Date: Fri, 18 Mar 2011 19:56:30 +0000 Subject: Winbond flash support. --- uClinux-2.4.20-uc1/drivers/block/Config.in | 5 + uClinux-2.4.20-uc1/drivers/block/Makefile | 3 + uClinux-2.4.20-uc1/drivers/block/blkmem.c | 18 + uClinux-2.4.20-uc1/drivers/block/export.c | 38 + uClinux-2.4.20-uc1/drivers/block/wbflash/Config.in | 2 + uClinux-2.4.20-uc1/drivers/block/wbflash/Makefile | 7 + uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.c | 279 ++++++ uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.h | 39 + uClinux-2.4.20-uc1/drivers/block/wbflash/flash.c | 1056 ++++++++++++++++++++ uClinux-2.4.20-uc1/drivers/block/wbflash/flash_u.c | 246 +++++ uClinux-2.4.20-uc1/drivers/block/wbflash/image.c | 178 ++++ .../include/asm-armnommu/arch-W90N745/flash.h | 103 ++ 12 files changed, 1974 insertions(+) create mode 100755 uClinux-2.4.20-uc1/drivers/block/export.c create mode 100644 uClinux-2.4.20-uc1/drivers/block/wbflash/Config.in create mode 100644 uClinux-2.4.20-uc1/drivers/block/wbflash/Makefile create mode 100644 uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.c create mode 100644 uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.h create mode 100644 uClinux-2.4.20-uc1/drivers/block/wbflash/flash.c create mode 100644 uClinux-2.4.20-uc1/drivers/block/wbflash/flash_u.c create mode 100644 uClinux-2.4.20-uc1/drivers/block/wbflash/image.c create mode 100644 uClinux-2.4.20-uc1/include/asm-armnommu/arch-W90N745/flash.h diff --git a/uClinux-2.4.20-uc1/drivers/block/Config.in b/uClinux-2.4.20-uc1/drivers/block/Config.in index e349779..52d0c96 100644 --- a/uClinux-2.4.20-uc1/drivers/block/Config.in +++ b/uClinux-2.4.20-uc1/drivers/block/Config.in @@ -33,6 +33,10 @@ dep_tristate 'Parallel port IDE device support' CONFIG_PARIDE $CONFIG_PARPORT if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then source drivers/block/paride/Config.in fi +dep_tristate 'Winbond W90N745 flash support' CONFIG_WBFLASH +if [ "$CONFIG_WBFLASH" = "y" -o "$CONFIG_WBFLASH" = "m" ]; then + source drivers/block/wbflash/Config.in +fi dep_tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA $CONFIG_PCI dep_tristate 'Compaq Smart Array 5xxx support' CONFIG_BLK_CPQ_CISS_DA $CONFIG_PCI dep_mbool ' SCSI tape drive support for Smart Array 5xxx' CONFIG_CISS_SCSI_TAPE $CONFIG_BLK_CPQ_CISS_DA $CONFIG_SCSI @@ -54,6 +58,7 @@ if [ "$CONFIG_BLK_DEV_BLKMEM" = "y" -o "$CONFIG_BLK_DEV_BLKMEM" = "m" ]; then choice ' FLASH type' \ "NONE CONFIG_NOFLASH \ AMD CONFIG_AMDFLASH \ + W90N745 CONFIG_WBFLASH \ INTEL CONFIG_INTELFLASH" NONE if [ "$CONFIG_AMDFLASH" = "y" -o "$CONFIG_INTELFLASH" = "y" ]; then choice ' FLASH size' \ diff --git a/uClinux-2.4.20-uc1/drivers/block/Makefile b/uClinux-2.4.20-uc1/drivers/block/Makefile index 55106f0..e4186d2 100644 --- a/uClinux-2.4.20-uc1/drivers/block/Makefile +++ b/uClinux-2.4.20-uc1/drivers/block/Makefile @@ -32,8 +32,11 @@ obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o obj-$(CONFIG_BLK_DEV_UMEM) += umem.o obj-$(CONFIG_BLK_DEV_NBD) += nbd.o +obj-$(CONFIG_WBFLASH) += wbflash/wbflash.o +obj-y+= export.o subdir-$(CONFIG_PARIDE) += paride +subdir-$(CONFIG_WBFLASH) += wbflash ifeq ($(CONFIG_ARCH_ACORN),y) mod-subdirs += ../acorn/block diff --git a/uClinux-2.4.20-uc1/drivers/block/blkmem.c b/uClinux-2.4.20-uc1/drivers/block/blkmem.c index 27c506f..a71c55f 100644 --- a/uClinux-2.4.20-uc1/drivers/block/blkmem.c +++ b/uClinux-2.4.20-uc1/drivers/block/blkmem.c @@ -220,6 +220,14 @@ extern char __romfs_start[]; #define FIXED_ROMARRAY __romfs_start #endif +#ifdef CONFIG_ARCH_WINBOND +#ifndef ROMFS_BASE +#define FIXED_ROMARRAY (char *)0x700000 +#else +#define FIXED_ROMARRAY (char *)ROMFS_BASE +#endif +#endif + /******* END OF BOARD-SPECIFIC CONFIGURATION ************/ /* Simple romfs, at internal, cat on the end of kernel, or seperate fixed adderess romfs. */ @@ -2799,6 +2807,16 @@ int __init blkmem_init( void ) #endif for(i=0;i +#include + +#ifndef CONFIG_WBFLASH//CONFIG_W90N745FLASH + +asmlinkage int sys_FindImage(UINT32 image_num, tfooter ** image_footer) +{ + return -ENOSYS; +} +asmlinkage int sys_DelImage(UINT32 image_num) +{ + return -ENOSYS; +} +asmlinkage int sys_CorruptCheck(tfooter * image_footer) +{ + return -ENOSYS; +} +asmlinkage int sys_ReadWinbondFlash(unsigned long pos, unsigned long length, char * buffer) +{ + return -ENOSYS; +} +asmlinkage int sys_WriteWinbondFlash(unsigned long pos, unsigned long length, char * buffer) +{ + return -ENOSYS; +} +asmlinkage int sys_WinbondFlashBlockSize(unsigned long pos) +{ + return -ENOSYS; +} +asmlinkage int sys_WinbondFlashTotalSize() +{ + return -ENOSYS; +} +asmlinkage int sys_WinbondFlashBase() +{ + return -ENOSYS; +} +#endif diff --git a/uClinux-2.4.20-uc1/drivers/block/wbflash/Config.in b/uClinux-2.4.20-uc1/drivers/block/wbflash/Config.in new file mode 100644 index 0000000..37cfeda --- /dev/null +++ b/uClinux-2.4.20-uc1/drivers/block/wbflash/Config.in @@ -0,0 +1,2 @@ +comment 'Winbond low level flash drivers' +dep_tristate ' Winbond low level flash driver support' CONFIG_WBFLASHDRV $CONFIG_WBFLASH diff --git a/uClinux-2.4.20-uc1/drivers/block/wbflash/Makefile b/uClinux-2.4.20-uc1/drivers/block/wbflash/Makefile new file mode 100644 index 0000000..426559f --- /dev/null +++ b/uClinux-2.4.20-uc1/drivers/block/wbflash/Makefile @@ -0,0 +1,7 @@ +O_TARGET := wbflash.o + +obj-$(CONFIG_WBFLASHDRV) += cfi.o flash_u.o image.o + +#export-objs := wbflash.o + +include $(TOPDIR)/Rules.make diff --git a/uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.c b/uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.c new file mode 100644 index 0000000..ba4f0a3 --- /dev/null +++ b/uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.c @@ -0,0 +1,279 @@ +/****************************************************************************** + * + * Copyright (c) 2007 Windond Electronics Corp. + * All rights reserved. + * + * $Workfile: cfi.c $ + * + * + ******************************************************************************/ + +//#include +//#include +//#include +//#include "wblib.h" +#include +#include +#include + +#include "cfi.h" +//#include "platform.h" + +//#define FLASH_BASE 0xFF000000 +#define MAX_REGION_NUM 10 + +static unsigned short cfiCmdSet = 0; +static unsigned short cfiExtTab = 0; +static unsigned int cfiDevSize = 0; +static unsigned short cfiNumEraseBlkRegion = 0; + +static struct cfi_erase_block_region_info cfiEraseBlkRegionInfo[MAX_REGION_NUM]; +static int dummyErase(unsigned int address, unsigned int size); +static int dummyWrite(unsigned int address, unsigned char *data, unsigned int size); + +struct cfi_command cfiCmd = { + write: dummyWrite, + erase: dummyErase, +}; + + +/* Retrun 0: OK, otherwise: CFI not found */ +static int cfiCheckIdent(void) +{ + unsigned short i[3]; + + CFI_READ(FLASH_BASE, 0x10, i[0]); + CFI_READ(FLASH_BASE, 0x11, i[1]); + CFI_READ(FLASH_BASE, 0x12, i[2]); + + if(i[0] == 'Q' && i[1] == 'R' && i[2] == 'Y') + return(0); + else + return(-1); + +} + +unsigned int cfiGetFlashSize(void) +{ + return(cfiDevSize); +} + +unsigned int cfiGetBlockSize(unsigned int address) +{ + int i, offset = 0; + + address = (address | 0x80000000) - (FLASH_BASE | 0x80000000); + //printk("addr %x %x\n", address, FLASH_BASE); + + for(i = 0; i < cfiNumEraseBlkRegion; i++) { + if(address < (offset += (cfiEraseBlkRegionInfo[i].num * cfiEraseBlkRegionInfo[i].size))) + return(cfiEraseBlkRegionInfo[i].size); + } + //uprintf("get size error\n"); + + return(0); + +} + +static void flushDCache(void) +{ + + if( *(unsigned int volatile *)(0xFFF02000) & 0x6 ) /* If write buffer or data cache is enabled */ + { + *(unsigned int volatile *)(0xFFF02004) = 0x86; + while( *(unsigned int volatile *)(0xFFF02004)); + } + +} + + +static int polling16(unsigned int addr, unsigned short data) +{ + unsigned short rdata; + int timeout = 0x600000; + + rdata = *(unsigned short volatile *)(addr); + while( rdata != data ) + { + rdata = *(unsigned short volatile *)(addr); + if( !(timeout--) ) + { + rdata = *(unsigned short volatile *)(addr); + if( rdata != data ) + { + //printf("timeout\n"); + return -1; + } + } + } + + return 0; +} + +static int intelWrite(unsigned int address, unsigned char *data, unsigned int size) +{ + unsigned int i; + int status = 0; + + address |= 0x80000000; + for(i = address; i < address + size; i += 2) + { + CFI_WRITE(i, 0, 0x40); + CFI_WRITE(i, 0, *(unsigned short *)data); + CFI_WRITE(address, 0, 0x70); + while(!( *(unsigned short *)(address) & 0x80)); + if(*(unsigned short *)(address) & 0x19) { + status = -1; + goto exit; + } + data+=2; + } + +exit: + CFI_WRITE(address,0,0xFF); + flushDCache(); + return(status); +} + +static int dummyWrite(unsigned int address, unsigned char *data, unsigned int size) +{ + printk("Dummy Write\n"); + return(-1); +} +static int amdWrite(unsigned int address, unsigned char *data, unsigned int size) +{ + int status; + unsigned int i; + + address |= 0x80000000; + for(i = address; i < address+size; i += 2) + { + CFI_WRITE(FLASH_BASE, 0x555, 0xAA); + CFI_WRITE(FLASH_BASE, 0x2AA, 0x55); + CFI_WRITE(FLASH_BASE, 0x555, 0xA0); + CFI_WRITE(i, 0, *(unsigned short *)data); + status = polling16( i, *(unsigned short *)data); + if(status < 0) { + printk("write failed, time out!\n"); + return(status); // time-out + } + data+=2; + } + + flushDCache(); + return(0); + +} + +static int intelErase(unsigned int address, unsigned int size) +{ + int status = 0; + + address|=0x80000000; + + CFI_WRITE(address, 0, 0x50); // Clear sttaus register + CFI_WRITE(address, 0, 0x20); + CFI_WRITE(address, 0, 0xD0); + + CFI_WRITE(address, 0, 0x70); + while(!( *(unsigned short *)(address) & 0x80)); + if(*(unsigned short *)(address) & 0x39) + status = -1; + + CFI_WRITE(address, 0, 0xFF); + flushDCache(); + return(status); +} + +static int dummyErase(unsigned int address, unsigned int size) +{ + printk("Dummy Erase\n"); + return(-1); +} +static int amdErase(unsigned int address, unsigned int size) +{ + int status; + + //printk("erase addr: %x\n", address); + + if((address & (size - 1)) != 0x0) + return -1;// not in the start of a block + address |= 0x80000000; + //printf("erase addr: %08x\n", address); + CFI_WRITE(FLASH_BASE, 0x555, 0xAA); + CFI_WRITE(FLASH_BASE, 0x2AA, 0x55); + CFI_WRITE(FLASH_BASE, 0x555, 0x80); + CFI_WRITE(FLASH_BASE, 0x555, 0xAA); + CFI_WRITE(FLASH_BASE, 0x2AA, 0x55); + CFI_WRITE(address, 0, 0x30); + status = polling16(address, 0xFFFF); + CFI_WRITE(FLASH_BASE, 0, 0xFF); + flushDCache(); + if(status < 0) + printk("erase failed, time out!\n"); + return(status); + +} + +int cfiGetFlashInfo(void) +{ + + unsigned int i; + + // goes into query mode + DESELECT_QUERY_MODE(FLASH_BASE); + SELECT_QUERY_MODE(FLASH_BASE); + + if(cfiCheckIdent() != 0) { + printk("No CFI information found\n"); + goto exit; + } + + CFI_READ(FLASH_BASE, 0x13, cfiCmdSet); + CFI_READ(FLASH_BASE, 0x15, cfiExtTab); + CFI_READ(FLASH_BASE, 0x27, cfiDevSize); + cfiDevSize = 1 << cfiDevSize; + + CFI_READ(FLASH_BASE, 0x2C, cfiNumEraseBlkRegion); + //cfiEraseBlkRegionInfo = (struct cfi_erase_block_region_info *)malloc(sizeof(struct cfi_erase_block_region_info) * cfiNumEraseBlkRegion); + + if(cfiNumEraseBlkRegion > MAX_REGION_NUM) { + //sysprintf("Out of memory\n"); + goto exit; + } + + for(i = 0; i < cfiNumEraseBlkRegion * 4; i += 4) { + unsigned short s1, s2; + CFI_READ(FLASH_BASE, 0x2D + i, s1); + CFI_READ(FLASH_BASE, 0x2E + i, s2); + + cfiEraseBlkRegionInfo[i/4].num = s1 + (s2 << 8) + 1; + //printk("num %d ", (cfiEraseBlkRegionInfo + i/4)->num); + + CFI_READ(FLASH_BASE, 0x2F + i, s1); + CFI_READ(FLASH_BASE, 0x30 + i, s2); + + cfiEraseBlkRegionInfo[i/4].size = (s1 + (s2 << 8)) * 256; + //printk("size %x \n", (cfiEraseBlkRegionInfo + i/4)->size); + + } + + DESELECT_QUERY_MODE(FLASH_BASE); + if(cfiCmdSet == AMD_CMD_SET) { + cfiCmd.write = amdWrite; + cfiCmd.erase = amdErase; + + }else if(cfiCmdSet == INTEL_CMD_SET) { + cfiCmd.write = intelWrite; + cfiCmd.erase = intelErase; + + } else { + printk("CFI command set %04x not support!\n", cfiCmdSet); + return(-1); + } + printk("CFI command set %04x will be used\n", cfiCmdSet); + +exit: + return(0); + +} diff --git a/uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.h b/uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.h new file mode 100644 index 0000000..19f2a65 --- /dev/null +++ b/uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * + * Copyright (c) 2007 Windond Electronics Corp. + * All rights reserved. + * + * $Workfile: cfi.h $ + * + * + ******************************************************************************/ +#ifndef __CFI_H__ +#define __CFI_H__ + +#define SELECT_QUERY_MODE(_base_) do{*(unsigned short volatile *)(((_base_) & 0xFFF00000) + (0x55 << 1)) = 0x98;}while(0) +#define DESELECT_QUERY_MODE(_base_) do{*(unsigned short volatile *)((_base_) & 0xFFF00000) = 0xF0;\ + *(unsigned short volatile *)((_base_) & 0xFFF00000) = 0xFF;}while(0) + +#define CFI_READ(_base_, _offset_, _var_) do{_var_ = *(unsigned short volatile *)(((_base_) & 0xFFF00000) + ((_offset_) << 1));}while(0) +#define CFI_WRITE(_base_, _offset_, _var_) do{*(unsigned short volatile *)(((_base_) /*& 0xFFF00000*/) + ((_offset_) << 1)) = (_var_);}while(0) + +#define AMD_CMD_SET 0x0002 +#define INTEL_CMD_SET 0x0003 + +struct cfi_erase_block_region_info { + unsigned int size; + unsigned int num; +}; + + +struct cfi_command{ + int (*write) (unsigned int address, unsigned char *data, unsigned int size); + int (*erase) (unsigned int address, unsigned int size); +}; + +extern unsigned int cfiGetBlockSize(unsigned int address); +extern unsigned int cfiGetFlashSize(void); +extern int cfiGetFlashInfo(void); +extern struct cfi_command cfiCmd; + +#endif // #ifdef __CFI_H__ diff --git a/uClinux-2.4.20-uc1/drivers/block/wbflash/flash.c b/uClinux-2.4.20-uc1/drivers/block/wbflash/flash.c new file mode 100644 index 0000000..d13d4a8 --- /dev/null +++ b/uClinux-2.4.20-uc1/drivers/block/wbflash/flash.c @@ -0,0 +1,1056 @@ +/****************************************************************************** + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "cfi.h" + +static int Init_WinbondFlash(void); + +#define BL_PHY 0 +#define BL_IC_PLUS 1 +#define BL_MARVELL6052 2 + +tbl_info info; +DECLARE_MUTEX(spare_lock); + +#define _DEBUG +#undef _DEBUG + +#define MALLOC(x) kmalloc((x), GFP_KERNEL) +#define FREE kfree +#define MEMCPY memcpy //or use "copy_to_user" + +//yyang1 030605 ??? +int __init Init_WinbondFlash(void) +{ + + if (cfiGetFlashInfo() == -1) { + printk("No supported flash detected!\n"); + return -EINVAL; + } + + return 0; +} + +asmlinkage int sys_ReadWinbondFlash(unsigned long pos, unsigned long length, char * buffer) +{ + // if(!pCurFlash) + // return -EINVAL; + if(cfiGetFlashSize() <= 0) + return(-EINVAL); + +#ifdef _DEBUG + printk("\nWinbondFlash Read: pos = %x, length = %d, buffer = 0x%x.\n", pos, length, buffer); +#endif + if(length%2) + length++; + down(&spare_lock); + if(copy_to_user(buffer, (void*)(FLASH_BASE | pos), length)) + { + up(&spare_lock); + return -EFAULT; + } + up(&spare_lock); + return length; +} + +static int _FlashWrite(char *pcBuf, int iBufLen, int iOffset); +asmlinkage int sys_WriteWinbondFlash(unsigned long pos, unsigned long length, char * buffer) +{ + // if(!pCurFlash) + // return -EINVAL;; + + if(cfiGetFlashSize() <= 0) + return(-EINVAL); + +#ifdef _DEBUG + printk("\nWinbondFlash Write: pos = %x, length = %d, buffer = 0x%x.\n", pos, length, buffer); +#endif + + return _FlashWrite(buffer, length, pos); +} + +asmlinkage int sys_WinbondFlashBlockSize(unsigned long pos) +{ + if(cfiGetFlashSize() == 0) + return -EINVAL;; + +#ifdef _DEBUG + printk("\nWinbondFlash BlockSize: pos = %d.\n", pos); +#endif + + pos |= FLASH_BASE; + return cfiGetBlockSize(pos); +} +asmlinkage int sys_WinbondFlashTotalSize(void) +{ + printk("sys_WinbondFlashTotalSize\n"); + return cfiGetFlashSize(); +} +asmlinkage int sys_WinbondFlashBase(void) +{ + return FLASH_BASE; +} + +static int _FlashWrite(char *pcBuf, int iBufLen, int iOffset) +{ + // unsigned long flags; + UINT32 blockSize,src,dest; + INT i; + + if (cfiGetFlashSize() == 0) return -EINVAL; + +#ifdef _DEBUG + printk("\nWinbondFlash _FlashWrite: pos = %x, length = %d, buffer = 0x%x.\n", iOffset, iBufLen, pcBuf); +#endif + + //i = iBufLen; + i=(iBufLen%2)?(iBufLen+1):iBufLen; + + src = (UINT32)pcBuf; + dest = (iOffset%2)?(iOffset+1):iOffset | FLASH_BASE; + + //CSR_WRITE(WTCR, (CSR_READ(WTCR)&0xF7)|0x01);//clyu reset watch dog + + while (i>0) + { + volatile UINT32 buf; + volatile UINT32 addr; + UINT32 count; + int len; + blockSize = cfiGetBlockSize(dest); + if(blockSize<=0) + return 0; + +#ifdef _DEBUG +//#if 1 + printk("\n_FlashWrite:dest:%x,cur blockSize:%x\n",dest,blockSize); +#endif + addr=dest&~(blockSize-1); + for(len=0;len=i)||((len+dest-addr)>=cfiGetBlockSize(dest))) + { + if((dest&(blockSize-1))||(dest+i-addr)<=blockSize) + { +#ifdef _DEBUG +printk("Write direct\n"); +#endif + if(i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cfi.h" + +extern struct semaphore spare_lock; + + + +int FindFooter(tfooter *** image_footer) +{ + static tfooter * image_footers[MAX_FOOTER_NUM]; + unsigned int footer_num=0; + //int flash_type; + unsigned int blocksize,addr,i; + tfooter * footer; + unsigned int * p; + unsigned long long sum; + + *image_footer=image_footers; + + if(cfiGetFlashSize() == 0 ) + return -1; + + addr=FLASH_BASE+BOOTER_BLOCK_LENGTH; // the 64kb of flash was preservied to boot loader + blocksize=cfiGetBlockSize(addr); + while( blocksize!= 0 ) + { + addr+=blocksize; + footer=(tfooter *)(addr-sizeof(tfooter)); + if(footer->signature==SIGNATURE_WORD) + { + p=(unsigned int *)footer; + sum=0; + for(i=0;i>32)); + if( (unsigned int)sum == footer->checksum ) + image_footers[footer_num++]=footer; + } + + blocksize=cfiGetBlockSize(addr); + } + + return footer_num; +} + +/*1 success 0 failure*/ +asmlinkage int sys_FindImage(unsigned int image_num, tfooter ** image_footer) +{ + int footer_num; + tfooter ** footer; + int i; + + + footer_num=FindFooter(&footer); + if(footer_num<=0) + { + return 0; + } + + for(i=0;inum == image_num ) + { + *image_footer=footer[i]; + return 1; + } + } + + + return 0; +} + + + +/*0 success*/ +asmlinkage int sys_DelImage(unsigned int image_num) +{ + unsigned int flash_type; + tfooter * footer; + unsigned int addr; + unsigned int blocksize; + unsigned int end; + unsigned long flags; + + if( sys_FindImage( image_num, &footer) ) + { + if(cfiGetFlashSize() == 0) { + printk("delete failed\n"); + return -EINVAL; + } + addr=footer->base; + blocksize = cfiGetBlockSize(addr); + end=footer->base+footer->length; + + end+=sizeof(tfooter); + + //printk("end at:%x", end); + + if((end & (blocksize-1)) == 0 ) + end -= blocksize; + else + end = end&(~(blocksize-1)); + + //printk("end at:%x", end); + + + { + down(&spare_lock); + save_flags(flags); cli(); + + cfiGetBlockSize(end); + cfiCmd.erase(end,blocksize); + restore_flags(flags); + up(&spare_lock); + } + + return 0; + } + printk("delete image failed\n"); + return -EINVAL; +} + +/*0 success 1 Corrupt*/ +asmlinkage int sys_CorruptCheck(tfooter * image_footer) +{ + int footer_num; + tfooter ** footer; + int i; + unsigned int a0,a1,b0,b1; + + if( image_footer->base < (FLASH_BASE+BOOTER_BLOCK_LENGTH) )return 1; + if( image_footer->base+image_footer->length > (FLASH_BASE+cfiGetFlashSize()) )return 1; + footer_num=FindFooter(&footer); + + if(footer_num<=0) + return 0; + for(i=0;inum == footer[i]->num ) { + printk("iamge exists"); + return 1; + } + } + + + b0=image_footer->base; + if( FLASH_BLOCK_SIZE-(image_footer->length%FLASH_BLOCK_SIZE) < sizeof(tfooter) ) + b1=image_footer->base+image_footer->length+FLASH_BLOCK_SIZE; + else + b1=image_footer->base+image_footer->length; + for(i=0;ibase; + if( (FLASH_BLOCK_SIZE-(footer[i]->length%FLASH_BLOCK_SIZE) < sizeof(tfooter)) || !(footer[i]->length&(FLASH_BLOCK_SIZE-1)) ) + a1=footer[i]->base+footer[i]->length+FLASH_BLOCK_SIZE; + else + a1=footer[i]->base+footer[i]->length; + if( (b0 >= a0) && (b0 < a1) )return 1; + if( (b1 >= a0) && (b1 < a1) )return 1; + if( (a0 > b0) && (a1 < b1) )return 1; + } + + return 0; +} + + + diff --git a/uClinux-2.4.20-uc1/include/asm-armnommu/arch-W90N745/flash.h b/uClinux-2.4.20-uc1/include/asm-armnommu/arch-W90N745/flash.h new file mode 100644 index 0000000..49451df --- /dev/null +++ b/uClinux-2.4.20-uc1/include/asm-armnommu/arch-W90N745/flash.h @@ -0,0 +1,103 @@ +#ifndef FLASH_H +#define FLASH_H +//--------------------------------------------------------------------------- +#include +#include + + +// if no platform.h +#ifndef FLASH_BASE +#define FLASH_BASE (0x7F000000) +#define FLASH_BLOCK_SIZE (0x10000) +#endif + +#ifndef ROMCON +#define ROMCON (0xFFF01004) +#endif + +#define EXT3CON (0xFFF01024) + +#define FLASH_NAME_SIZE 16 + +#define VP_int(x) (*((volatile unsigned int*)(x))) +#define VP_short(x) (*((volatile unsigned short*)(x))) +#define VP_char(x) (*((volatile unsigned char*)(x))) +#define CAHCNF_R VP_int(0xFFF02000) +#define CAHCON_R VP_int(0xFFF02004) + +#if 0 +#define inph(x) VP_short(x) +#define outph(x,y) VP_short(x)=(y) +#define inpb(x) VP_char(x) +#define outpb(x,y) VP_char(x)=(y) +#endif + + +#define inpw(port) *((volatile unsigned int *)port) +#define outpw(port,x) *((volatile unsigned int *)port)=x +#define inph(port) *((volatile unsigned short *)port) +#define outph(port,x) *((volatile unsigned short *)port)=x +#define inpb(port) *((volatile unsigned char *)port) +#define outpb(port,x) *((volatile unsigned char *)port)=x + + +#define BLOCK_LOCK 0 +#define BLOCK_UNLOCK 1 + + +typedef struct +{ + char PID0; + char PID1; + char name[FLASH_NAME_SIZE]; + int (*BlockSize)(UINT32 address); + int (*BlockErase)(UINT32 address,UINT32 size); + int (*BlockWrite)(UINT32 address, UCHAR * data, UINT32 size); + int (*ReadPID)(UINT32 address, UCHAR *PID0, UCHAR *PID1 ); + int (*BlockLock)(UINT32 address, UINT32 op); +} flash_t; + + + +#define IMAGE_ACTIVE 0x1 // Only the active image will be processed by bootloader +#define IMAGE_COPY2RAM 0x2 // copy this image to ram +#define IMAGE_EXEC 0x4 // execute this image +#define IMAGE_FILE 0x8 // file image +#define IMAGE_COMPRESSED 0x10 // compressed image, bootloader will unzip it +#define SIGNATURE_WORD 0xA0FFFF9F + +typedef struct t_footer +{ + UINT32 num; + UINT32 base; + UINT32 length; + UINT32 load_address; + UINT32 exec_address; + CHAR name[16]; + UINT32 image_checksum; + UINT32 signature; + UINT32 type; + UINT32 checksum; +} tfooter; + + +#define MAX_FOOTER_NUM 8 + + +#define BOOTER_BLOCK_LENGTH FLASH_BLOCK_SIZE +extern flash_t flash[];// The supported flash types +extern int flash_type; +extern UINT32 _flash_size; +extern char * _flash_buffer; + +extern int FindFlash(void); // function to identify the flash type +extern int FindFooter(tfooter *** image_footer); //function to find the image footers +int sys_DelImage(UINT32 image_num); +int sys_FindImage(UINT32 image_num, tfooter ** image_footer); +extern int sys_CorruptCheck(tfooter * image_footer);//function to check if data corrupt +extern tbl_info info; +extern int GetImgAddr(unsigned int default_addr); +extern int GetLoadImage(); +extern int get_flash_type_num(void); +//--------------------------------------------------------------------------- +#endif -- cgit v0.12