diff options
Diffstat (limited to 'uClinux-2.4.20-uc1/drivers/block/wbflash')
-rw-r--r-- | uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.c | 558 | ||||
-rw-r--r-- | uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.h | 78 | ||||
-rw-r--r-- | uClinux-2.4.20-uc1/drivers/block/wbflash/flash.c | 2112 | ||||
-rw-r--r-- | uClinux-2.4.20-uc1/drivers/block/wbflash/flash_u.c | 492 | ||||
-rw-r--r-- | uClinux-2.4.20-uc1/drivers/block/wbflash/image.c | 356 |
5 files changed, 1798 insertions, 1798 deletions
diff --git a/uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.c b/uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.c index ba4f0a3..9398461 100644 --- a/uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.c +++ b/uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.c @@ -1,279 +1,279 @@ -/******************************************************************************
- *
- * Copyright (c) 2007 Windond Electronics Corp.
- * All rights reserved.
- *
- * $Workfile: cfi.c $
- *
- *
- ******************************************************************************/
-
-//#include <stdio.h>
-//#include <string.h>
-//#include <stdlib.h>
-//#include "wblib.h"
-#include <asm/arch/flash.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-
-#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);
-
-}
+/****************************************************************************** + * + * Copyright (c) 2007 Windond Electronics Corp. + * All rights reserved. + * + * $Workfile: cfi.c $ + * + * + ******************************************************************************/ + +//#include <stdio.h> +//#include <string.h> +//#include <stdlib.h> +//#include "wblib.h" +#include <asm/arch/flash.h> +#include <linux/types.h> +#include <linux/slab.h> + +#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 index 19f2a65..88c0514 100644 --- a/uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.h +++ b/uClinux-2.4.20-uc1/drivers/block/wbflash/cfi.h @@ -1,39 +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__
+/****************************************************************************** + * + * 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 index d13d4a8..e4eaf2f 100644 --- a/uClinux-2.4.20-uc1/drivers/block/wbflash/flash.c +++ b/uClinux-2.4.20-uc1/drivers/block/wbflash/flash.c @@ -1,1056 +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 <asm/arch/flash.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-// 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<delay*DELAY_1US;i++);
-}
-
-static __inline void FlushDCache()
-{
- /* Flush Entire DCache */
- if( CAHCNF_R & 0x6 ) /* If write buffer or data cache is enabled */
- {
- CAHCON_R=0x86;
- while( CAHCON_R );
- }
-
-}
-
-
-
-INT BlockLock_W28J800TT(UINT32 address, UINT32 op)
-{
- address|=0x80000000;
-
- if( op==BLOCK_LOCK )
- {
- outph(address,0x70);
- while( !(inph(address)&0x80) );
- outph(address,0x60);
- outph(address,0x01);
- while( !(inph(address)&0x80) );
- outph(address,0xFFFF);
- }
- else if( op==BLOCK_UNLOCK )
- {
- outph(address,0x70);
- while( !(inph(address)&0x80) );
- outph(address,0x60);
- outph(address,0xD0);
- while( !(inph(address)&0x80) );
- outph(address,0xFFFF);
- }
- return 0;
-}
-
-INT BlockSize_W28J800TT(UINT32 address)
-{
- address-=FLASH_BASE;
- address&=0x7FFFFFFF;
- if( address >= 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<address+size;i+=2)
- {
- outph(i,0x40);
- outph(i,*((UINT16 *)data));
- //while( !(inph(i)&0x80) );
- status=normal_polling( i, 0x80 );
- if( status < 0 )return -1; // polling time-out
- data+=2;
- }
- outph(address,0xFFFF);
- FlushDCache();
-
- return 0;
-}
-
-INT ReadPID_Winbond(UINT32 address, UCHAR *pid0, UCHAR *pid1)
-{
- if( !CheckDataWidth(16) )return -1;
-
- address|=0x80000000;
- outph(address,0x70);
- FlashDelay(50000); // delay 50ms
- outph(address,0x90);
- *pid0=inph(address);
- *pid1=inph(address+1);
- outph(address,0xFFFF);
-
- return 0;
-}
-
-INT ReadPID_W28J800TT(UINT32 address, UCHAR *pid0, UCHAR *pid1)
-{
- int status;
- status=ReadPID_Winbond(address,pid0,pid1);
- if( status < 0 )return -1; // not x16 flash
- _flash_size=0x100000;
- return 0;
-}
-
-INT ReadPID_W28J800BT(UINT32 address, UCHAR *pid0, UCHAR *pid1)
-{
- int status;
- status=ReadPID_Winbond(address,pid0,pid1);
- if( status < 0 )return -1; // not x16 flash
- _flash_size=0x100000;
- return 0;
-}
-
-INT ReadPID_W28J160TT(UINT32 address, UCHAR *pid0, UCHAR *pid1)
-{
- int status;
- status=ReadPID_Winbond(address,pid0,pid1);
- if( status < 0 )return -1; // not x16 flash
- _flash_size=0x200000;
- return 0;
-}
-
-INT ReadPID_W28J320TT(UINT32 address, UCHAR *pid0, UCHAR *pid1)
-{
- int status;
- status=ReadPID_Winbond(address,pid0,pid1);
- if( status < 0 )return -1; // not x16 flash
- _flash_size=0x400000;
- return 0;
-}
-
-
-
-
-INT BlockSize_W28J320TT(UINT32 address)
-{
- address-=FLASH_BASE;
- address&=0x7FFFFFFF;
- if( address >= 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<address+size;i++)
- {
- outpb(addr1,0xAA);
- outpb(addr2,0x55);
- outpb(addr1,0xA0);
- outpb(i,*data);
- while( !((inpb(i)&0x80)==(*data&0x80)) );
- data++;
- }
- FlushDCache();
-
- return 0;
-}
-
-INT ReadPID_W39L010(UINT32 address, UCHAR *pid0, UCHAR *pid1)
-{
- UINT32 addr1, addr2;
-
- if( !CheckDataWidth(8) )return -1;
-
-
-
- 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,0x60);
- *pid0=inpb(address);
- *pid1=inpb(address+1);
- outpb(addr1,0xAA);
- outpb(addr2,0x55);
- outpb(addr1,0xF0);
- outpb(address,0xFF);
-
- _flash_size=0x20000;
-
- return 0;
-}
-
-
-
-INT BlockLock_W29EE011(UINT32 address, UINT32 op)
-{
- return -1;
-}
-
-
-INT BlockSize_W29EE011(UINT32 address)
-{
- address-=FLASH_BASE;
- address&=0x7FFFFFFF;
- if( address < _flash_size )
- return 0x80;
- else
- return 0;
-}
-
-INT BlockErase_W29EE011(UINT32 address,UINT32 size)
-{
- UINT32 addr1,addr2;
- static INT flag=0;
-
- if( flag )return 0;
-
- flag=1;
-
- 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);
- FlashDelay(50000); // delay 50ms
-
- FlushDCache();
-
- return 0;
-}
-
-INT BlockWrite_W29EE011(UINT32 address, UCHAR * data, UINT32 size)
-{
- UINT32 i;
- UINT32 addr1, addr2;
-
- address|=0x80000000;
- addr1=(address&0xFFF00000)+(0x5555);
- addr2=(address&0xFFF00000)+(0x2AAA);
- outpb(addr1,0xAA);
- outpb(addr2,0x55);
- outpb(addr1,0xA0);
- for(i=0;i<size;i++)
- outpb(address+i,*(data+i));
- while( inpb(address+i-1)!=*(data+i-1) );
- FlushDCache();
-
- return 0;
-}
-
-INT ReadPID_W29EE011(UINT32 address, UCHAR *pid0, UCHAR *pid1)
-{
- UINT32 addr1, addr2;
-
- if( !CheckDataWidth(8) )return -1;
-
-
- 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,0x60);
- FlashDelay(10);//delay 10 us
- *pid0=inpb(address);
- *pid1=inpb(address+1);
- outpb(addr1,0xAA);
- outpb(addr2,0x55);
- outpb(addr1,0xF0);
- FlashDelay(10);//delay 10 us
- outpb(address,0xFF);
-
- _flash_size=0x20000;
-
- return 0;
-}
-
-
-
-INT BlockLock_AM29LV800BB(UINT32 address, UINT32 op)
-{
- return -1;
-}
-
-
-INT BlockSize_AM29LV800BB(UINT32 address)
-{
- address-=FLASH_BASE;
- address&=0x7FFFFFFF;
- if( address < 0x4000 )
- return 0x4000;
- else if( address < 0x6000 )
- return 0x2000;
- else if( address < 0x8000 )
- return 0x2000;
- else if( address < 0x10000 )
- return 0x8000;
- else
- {
- if( address < _flash_size )
- return 0x10000;
- else
- return 0;
- }
-}
-
-INT BlockSize_AM29LV800BT(UINT32 address)
-{
- address-=FLASH_BASE;
- address&=0x7FFFFFFF;
- if( address < 0x0F0000 )
- return 0x10000;
- else if( address < 0xF8000 )
- return 0x8000;
- else if( address < 0xFA000 )
- return 0x2000;
- else if( address < 0xFC000 )
- return 0x2000;
- else
- {
- if( address < _flash_size )
- return 0x4000;
- else
- return 0;
- }
-}
-INT BlockErase_AM29LV800BB(UINT32 address,UINT32 size)
-{
- UINT32 addr1,addr2;
- INT status;
-
- if( (address&(size-1))!=0x0 )return -1;// not in the start of a block
-
- address|=0x80000000;
- addr1=(address&0xFFF00000)+(0x5555<<1);
- addr2=(address&0xFFF00000)+(0x2AAA<<1);
-
- outph(addr1,0xAA);
- outph(addr2,0x55);
- outph(addr1,0x80);
- outph(addr1,0xAA);
- outph(addr2,0x55);
- outph(address,0x30);
- //while( (inph(address))!=0xFFFF );
- status=polling16(address, 0xFFFF);
-
- FlushDCache();
-
- return status;
-}
-
-INT BlockWrite_AM29LV800BB(UINT32 address, UCHAR * data, UINT32 size)
-{
- UINT32 i;
- UINT32 addr1, addr2;
- INT status;
-
- address|=0x80000000;
- addr1=(address&0xFFF00000)+(0x5555<<1);
- addr2=(address&0xFFF00000)+(0x2AAA<<1);
-
- for(i=address;i<address+size;i+=2)
- {
- outph(addr1,0xAA);
- outph(addr2,0x55);
- outph(addr1,0xA0);
- outph(i,*((UINT16*)data));
- status=polling16( i, (*(UINT16 *)data));
- if( status < 0 )return status; // time-out
- data+=2;
- }
-
- outph(address,0xFFFF);
- FlushDCache();
-
- return status;
-}
-
-
-INT ReadPID_AM29LV(UINT32 address, UCHAR *pid0, UCHAR *pid1)
-{
- UINT32 addr1, addr2;
-
- if( !CheckDataWidth(16) )return -1;
-
-
- address|=0x80000000;
- addr1=(address&0xFFF00000)+(0x5555<<1);
- addr2=(address&0xFFF00000)+(0x2AAA<<1);
-
- outph(addr1,0xAA);
- outph(addr2,0x55);
- outph(addr1,0x90);
- *pid0=(char)inph(address);
- *pid1=(char)inph((address+2));
- outph(address,0xFFFF);
-
- return 0;
-}
-
-
-INT ReadPID_AM29LV800BB(UINT32 address, UCHAR *pid0, UCHAR *pid1)
-{
-
- ReadPID_AM29LV(address, pid0, pid1);
- _flash_size=0x100000;
-
- return 0;
-}
-
-INT ReadPID_AM29LV160DB(UINT32 address, UCHAR *pid0, UCHAR *pid1)
-{
-
- ReadPID_AM29LV(address, pid0, pid1);
- _flash_size=0x200000;
-
- return 0;
-}
-
-INT ReadPID_AM29LV320DB(UINT32 address, UCHAR *pid0, UCHAR *pid1)
-{
-
- ReadPID_AM29LV(address, pid0, pid1);
- _flash_size=0x400000;
-
- return 0;
-}
-
-
-
-INT BlockSize_AM29LV160DB(UINT32 address)
-{
- address-=FLASH_BASE;
- address&=0x7FFFFFFF;
- if( address < 0x4000 )
- return 0x4000;
- else if( address < 0x6000 )
- return 0x2000;
- else if( address < 0x8000 )
- return 0x2000;
- else if( address < 0x10000 )
- return 0x8000;
- else
- {
- if( address < _flash_size )
- return 0x10000;
- else
- return 0;
- }
-}
-
-INT BlockSize_AM29LV160DT(UINT32 address)
-{
- address-=FLASH_BASE;
- address&=0x7FFFFFFF;
- if( address < 0x1F0000 )
- return 0x10000;
- else if( address < 0x1F8000 )
- return 0x8000;
- else if( address < 0x1FA000 )
- return 0x2000;
- else if( address < 0x1FC000 )
- return 0x2000;
- else
- {
- if( address < _flash_size )
- return 0x4000;
- else
- return 0;
- }
-}
-INT BlockSize_AM29LV320DB(UINT32 address)
-{
- address-=FLASH_BASE;
- address&=0x7FFFFFFF;
- if( address < 0x10000 )
- return 0x2000;
- else
- {
- if( address < _flash_size )
- return 0x10000;
- else
- return 0;
- }
-}
-
-INT BlockSize_AM29LV320DT(UINT32 address)
-{
- address-=FLASH_BASE;
- address&=0x7FFFFFFF;
- if( address < 0x3F0000 )
- return 0x10000;
- else
- {
- if( address < _flash_size )
- return 0x2000;
- else
- return 0;
- }
-}
-
-INT BlockLock_E28F640(UINT32 address, UINT32 op)
-{
-
- address|=0x80000000;
-
- if( op==BLOCK_LOCK )
- {
- outph(address,0x60);
- outph(address,0x01);
- while( !(inph(address)&0x80) );
- outph(address,0xFFFF);
- }
- else if( op==BLOCK_UNLOCK )
- {
- outph(address,0x60);
- outph(address,0xD0);
- while( !(inph(address)&0x80) );
- outph(address,0xFFFF);
- }
-
- return 0;
-}
-
-INT BlockSize_E28F640(UINT32 address)
-{
- address-=FLASH_BASE;
- address&=0x7FFFFFFF;
- if( address < _flash_size )
- return 0x10000;
- else
- return 0;
-}
-
-INT BlockErase_E28F640(UINT32 address,UINT32 size)
-{
- UINT32 i,j,tmp;
- CHAR * buffer;
-
- address|=0x80000000;
- buffer = kmalloc(128*1024,GFP_KERNEL);
- if(!buffer)
- return 1;
- // backup the data
- j=0xFFFF;
- if( (address & FLASH_BLOCK_SIZE) )
- {
-
- for(i=0;i<FLASH_BLOCK_SIZE/2;i++)
- {
- tmp=*((volatile unsigned short *)(address-FLASH_BLOCK_SIZE)+i);
- *((volatile unsigned short *)buffer+i)=tmp;
- j&=tmp;
- }
- }
- else
- {
- for(i=0;i<FLASH_BLOCK_SIZE/2;i++)
- {
- tmp=*((volatile unsigned short *)(address+FLASH_BLOCK_SIZE)+i);
- *((volatile unsigned short *)buffer+i)=tmp;
- j&=tmp;
- }
- }
-
-
- outph(address,0x20);
- outph(address,0xD0);
- while( !(inph(address)&0x80) );
- outph(address,0xFFFF);
-
-
- // write back the data
- if( (j&0xFFFF)!=0xFFFF )
- {
- if( (address & FLASH_BLOCK_SIZE) )
- BlockWrite_E28F640(address-FLASH_BLOCK_SIZE, (UCHAR *)buffer, FLASH_BLOCK_SIZE);
- else
- BlockWrite_E28F640(address+FLASH_BLOCK_SIZE, (UCHAR *)buffer, FLASH_BLOCK_SIZE);
- }
- FlushDCache();
- kfree(buffer);
- return 0;
-}
-
-INT BlockWrite_E28F640(UINT32 address, UCHAR * data, UINT32 size)
-{
- UINT32 i;
-#if 0
- UINT32 pdata,j;
-
- address|=0x80000000;
-
- do{
- outph(address, 0xE8);
- }while( !(inph(address)&0x80) );
-
- i=size;
- while(i)
- {
- if( i < 32 )
- {
- outph(address, i);
- for(j=0;j<i/2;j++)
- outph(address+j, *((unsigned short *)pdata+j));
- pdata+=i;
- i=0;
- }
- else
- {
- outph(address, 32);
- for(j=0;j<16;j++)
- outph(address+j, *((unsigned short *)pdata+j));
- pdata+=32;
- i-=32;
- }
- outph(address, 0xD0);
- while( !(inph(address)&0x80) );
- }
-
-#else
- address|=0x80000000;
-
- for(i=address;i<address+size;i+=2)
- {
- outph(i,0x40);
- outph(i,*((UINT16 *)data));
- while( !(inph(i)&0x80) );
- data+=2;
- }
-
- outph(address,0xFFFF);
-#endif
-
- FlushDCache();
- return 0;
-}
-
-INT ReadPID_E28F640(UINT32 address, UCHAR *pid0, UCHAR *pid1)
-{
- if( !CheckDataWidth(16) )return -1;
-
- outph(address,0x90);
- *pid0=inph(address);
- *pid1=inph(address+1);
- outph(address,0xFFFF);
-
- _flash_size=0x800000;
-
- return 0;
-}
-
-
-INT BlockSize_SST39VF160(UINT32 address)
-{
- address-=FLASH_BASE;
- address&=0x7FFFFFFF;
- if( address < _flash_size )
- return 0x10000;
- else
- return 0;
-
-}
-
-
-INT ReadPID_SST39VF160(UINT32 address, UCHAR *pid0, UCHAR *pid1)
-{
-
- ReadPID_AM29LV(address, pid0, pid1);
- outph(address, 0x00F0 ); /* Exit Software ID mode */
- _flash_size=0x200000;
-
- return 0;
-}
-
-INT BlockErase_SST39VF160(UINT32 address,UINT32 size)
-{
- UINT32 addr1,addr2;
- INT status;
-
- if( (address&(size-1))!=0x0 )return -1;// not in the start of a block
-
- address|=0x80000000;
- addr1=(address&0xFFF00000)+(0x5555<<1);
- addr2=(address&0xFFF00000)+(0x2AAA<<1);
-
- outph(addr1,0xAA);
- outph(addr2,0x55);
- outph(addr1,0x80);
- outph(addr1,0xAA);
- outph(addr2,0x55);
- outph(address,0x50);
- status=polling16(address, 0xFFFF);
-
- FlushDCache();
-
- return status;
-}
-
-INT BlockErase_MX28F160C3B(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 MX28F160C3 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_MX28F160C3B(UINT32 address, UCHAR * data, UINT32 size)
-{
- UINT32 i;
- int status;
-
- BlockLock_W28J800TT(address,BLOCK_UNLOCK); // The MX28F160C3 sector is default to be locked
-
- address|=0x80000000;
- for(i=address;i<address+size;i+=2)
- {
- outph(i,0x40);
- outph(i,*((UINT16 *)data));
- //while( !(inph(i)&0x80) );
- status=normal_polling( i, 0x80 );
- if( status < 0 )return -1; // polling time-out
- data+=2;
- }
- outph(address,0xFFFF);
- FlushDCache();
-
- return 0;
-}
-
-UINT32 FlashSize()
-{
- return _flash_size;
-}
-
-
-
-
+/****************************************************************************** + * + * 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 <asm/arch/flash.h> +#include <linux/types.h> +#include <linux/slab.h> +// 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<delay*DELAY_1US;i++); +} + +static __inline void FlushDCache() +{ + /* Flush Entire DCache */ + if( CAHCNF_R & 0x6 ) /* If write buffer or data cache is enabled */ + { + CAHCON_R=0x86; + while( CAHCON_R ); + } + +} + + + +INT BlockLock_W28J800TT(UINT32 address, UINT32 op) +{ + address|=0x80000000; + + if( op==BLOCK_LOCK ) + { + outph(address,0x70); + while( !(inph(address)&0x80) ); + outph(address,0x60); + outph(address,0x01); + while( !(inph(address)&0x80) ); + outph(address,0xFFFF); + } + else if( op==BLOCK_UNLOCK ) + { + outph(address,0x70); + while( !(inph(address)&0x80) ); + outph(address,0x60); + outph(address,0xD0); + while( !(inph(address)&0x80) ); + outph(address,0xFFFF); + } + return 0; +} + +INT BlockSize_W28J800TT(UINT32 address) +{ + address-=FLASH_BASE; + address&=0x7FFFFFFF; + if( address >= 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<address+size;i+=2) + { + outph(i,0x40); + outph(i,*((UINT16 *)data)); + //while( !(inph(i)&0x80) ); + status=normal_polling( i, 0x80 ); + if( status < 0 )return -1; // polling time-out + data+=2; + } + outph(address,0xFFFF); + FlushDCache(); + + return 0; +} + +INT ReadPID_Winbond(UINT32 address, UCHAR *pid0, UCHAR *pid1) +{ + if( !CheckDataWidth(16) )return -1; + + address|=0x80000000; + outph(address,0x70); + FlashDelay(50000); // delay 50ms + outph(address,0x90); + *pid0=inph(address); + *pid1=inph(address+1); + outph(address,0xFFFF); + + return 0; +} + +INT ReadPID_W28J800TT(UINT32 address, UCHAR *pid0, UCHAR *pid1) +{ + int status; + status=ReadPID_Winbond(address,pid0,pid1); + if( status < 0 )return -1; // not x16 flash + _flash_size=0x100000; + return 0; +} + +INT ReadPID_W28J800BT(UINT32 address, UCHAR *pid0, UCHAR *pid1) +{ + int status; + status=ReadPID_Winbond(address,pid0,pid1); + if( status < 0 )return -1; // not x16 flash + _flash_size=0x100000; + return 0; +} + +INT ReadPID_W28J160TT(UINT32 address, UCHAR *pid0, UCHAR *pid1) +{ + int status; + status=ReadPID_Winbond(address,pid0,pid1); + if( status < 0 )return -1; // not x16 flash + _flash_size=0x200000; + return 0; +} + +INT ReadPID_W28J320TT(UINT32 address, UCHAR *pid0, UCHAR *pid1) +{ + int status; + status=ReadPID_Winbond(address,pid0,pid1); + if( status < 0 )return -1; // not x16 flash + _flash_size=0x400000; + return 0; +} + + + + +INT BlockSize_W28J320TT(UINT32 address) +{ + address-=FLASH_BASE; + address&=0x7FFFFFFF; + if( address >= 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<address+size;i++) + { + outpb(addr1,0xAA); + outpb(addr2,0x55); + outpb(addr1,0xA0); + outpb(i,*data); + while( !((inpb(i)&0x80)==(*data&0x80)) ); + data++; + } + FlushDCache(); + + return 0; +} + +INT ReadPID_W39L010(UINT32 address, UCHAR *pid0, UCHAR *pid1) +{ + UINT32 addr1, addr2; + + if( !CheckDataWidth(8) )return -1; + + + + 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,0x60); + *pid0=inpb(address); + *pid1=inpb(address+1); + outpb(addr1,0xAA); + outpb(addr2,0x55); + outpb(addr1,0xF0); + outpb(address,0xFF); + + _flash_size=0x20000; + + return 0; +} + + + +INT BlockLock_W29EE011(UINT32 address, UINT32 op) +{ + return -1; +} + + +INT BlockSize_W29EE011(UINT32 address) +{ + address-=FLASH_BASE; + address&=0x7FFFFFFF; + if( address < _flash_size ) + return 0x80; + else + return 0; +} + +INT BlockErase_W29EE011(UINT32 address,UINT32 size) +{ + UINT32 addr1,addr2; + static INT flag=0; + + if( flag )return 0; + + flag=1; + + 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); + FlashDelay(50000); // delay 50ms + + FlushDCache(); + + return 0; +} + +INT BlockWrite_W29EE011(UINT32 address, UCHAR * data, UINT32 size) +{ + UINT32 i; + UINT32 addr1, addr2; + + address|=0x80000000; + addr1=(address&0xFFF00000)+(0x5555); + addr2=(address&0xFFF00000)+(0x2AAA); + outpb(addr1,0xAA); + outpb(addr2,0x55); + outpb(addr1,0xA0); + for(i=0;i<size;i++) + outpb(address+i,*(data+i)); + while( inpb(address+i-1)!=*(data+i-1) ); + FlushDCache(); + + return 0; +} + +INT ReadPID_W29EE011(UINT32 address, UCHAR *pid0, UCHAR *pid1) +{ + UINT32 addr1, addr2; + + if( !CheckDataWidth(8) )return -1; + + + 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,0x60); + FlashDelay(10);//delay 10 us + *pid0=inpb(address); + *pid1=inpb(address+1); + outpb(addr1,0xAA); + outpb(addr2,0x55); + outpb(addr1,0xF0); + FlashDelay(10);//delay 10 us + outpb(address,0xFF); + + _flash_size=0x20000; + + return 0; +} + + + +INT BlockLock_AM29LV800BB(UINT32 address, UINT32 op) +{ + return -1; +} + + +INT BlockSize_AM29LV800BB(UINT32 address) +{ + address-=FLASH_BASE; + address&=0x7FFFFFFF; + if( address < 0x4000 ) + return 0x4000; + else if( address < 0x6000 ) + return 0x2000; + else if( address < 0x8000 ) + return 0x2000; + else if( address < 0x10000 ) + return 0x8000; + else + { + if( address < _flash_size ) + return 0x10000; + else + return 0; + } +} + +INT BlockSize_AM29LV800BT(UINT32 address) +{ + address-=FLASH_BASE; + address&=0x7FFFFFFF; + if( address < 0x0F0000 ) + return 0x10000; + else if( address < 0xF8000 ) + return 0x8000; + else if( address < 0xFA000 ) + return 0x2000; + else if( address < 0xFC000 ) + return 0x2000; + else + { + if( address < _flash_size ) + return 0x4000; + else + return 0; + } +} +INT BlockErase_AM29LV800BB(UINT32 address,UINT32 size) +{ + UINT32 addr1,addr2; + INT status; + + if( (address&(size-1))!=0x0 )return -1;// not in the start of a block + + address|=0x80000000; + addr1=(address&0xFFF00000)+(0x5555<<1); + addr2=(address&0xFFF00000)+(0x2AAA<<1); + + outph(addr1,0xAA); + outph(addr2,0x55); + outph(addr1,0x80); + outph(addr1,0xAA); + outph(addr2,0x55); + outph(address,0x30); + //while( (inph(address))!=0xFFFF ); + status=polling16(address, 0xFFFF); + + FlushDCache(); + + return status; +} + +INT BlockWrite_AM29LV800BB(UINT32 address, UCHAR * data, UINT32 size) +{ + UINT32 i; + UINT32 addr1, addr2; + INT status; + + address|=0x80000000; + addr1=(address&0xFFF00000)+(0x5555<<1); + addr2=(address&0xFFF00000)+(0x2AAA<<1); + + for(i=address;i<address+size;i+=2) + { + outph(addr1,0xAA); + outph(addr2,0x55); + outph(addr1,0xA0); + outph(i,*((UINT16*)data)); + status=polling16( i, (*(UINT16 *)data)); + if( status < 0 )return status; // time-out + data+=2; + } + + outph(address,0xFFFF); + FlushDCache(); + + return status; +} + + +INT ReadPID_AM29LV(UINT32 address, UCHAR *pid0, UCHAR *pid1) +{ + UINT32 addr1, addr2; + + if( !CheckDataWidth(16) )return -1; + + + address|=0x80000000; + addr1=(address&0xFFF00000)+(0x5555<<1); + addr2=(address&0xFFF00000)+(0x2AAA<<1); + + outph(addr1,0xAA); + outph(addr2,0x55); + outph(addr1,0x90); + *pid0=(char)inph(address); + *pid1=(char)inph((address+2)); + outph(address,0xFFFF); + + return 0; +} + + +INT ReadPID_AM29LV800BB(UINT32 address, UCHAR *pid0, UCHAR *pid1) +{ + + ReadPID_AM29LV(address, pid0, pid1); + _flash_size=0x100000; + + return 0; +} + +INT ReadPID_AM29LV160DB(UINT32 address, UCHAR *pid0, UCHAR *pid1) +{ + + ReadPID_AM29LV(address, pid0, pid1); + _flash_size=0x200000; + + return 0; +} + +INT ReadPID_AM29LV320DB(UINT32 address, UCHAR *pid0, UCHAR *pid1) +{ + + ReadPID_AM29LV(address, pid0, pid1); + _flash_size=0x400000; + + return 0; +} + + + +INT BlockSize_AM29LV160DB(UINT32 address) +{ + address-=FLASH_BASE; + address&=0x7FFFFFFF; + if( address < 0x4000 ) + return 0x4000; + else if( address < 0x6000 ) + return 0x2000; + else if( address < 0x8000 ) + return 0x2000; + else if( address < 0x10000 ) + return 0x8000; + else + { + if( address < _flash_size ) + return 0x10000; + else + return 0; + } +} + +INT BlockSize_AM29LV160DT(UINT32 address) +{ + address-=FLASH_BASE; + address&=0x7FFFFFFF; + if( address < 0x1F0000 ) + return 0x10000; + else if( address < 0x1F8000 ) + return 0x8000; + else if( address < 0x1FA000 ) + return 0x2000; + else if( address < 0x1FC000 ) + return 0x2000; + else + { + if( address < _flash_size ) + return 0x4000; + else + return 0; + } +} +INT BlockSize_AM29LV320DB(UINT32 address) +{ + address-=FLASH_BASE; + address&=0x7FFFFFFF; + if( address < 0x10000 ) + return 0x2000; + else + { + if( address < _flash_size ) + return 0x10000; + else + return 0; + } +} + +INT BlockSize_AM29LV320DT(UINT32 address) +{ + address-=FLASH_BASE; + address&=0x7FFFFFFF; + if( address < 0x3F0000 ) + return 0x10000; + else + { + if( address < _flash_size ) + return 0x2000; + else + return 0; + } +} + +INT BlockLock_E28F640(UINT32 address, UINT32 op) +{ + + address|=0x80000000; + + if( op==BLOCK_LOCK ) + { + outph(address,0x60); + outph(address,0x01); + while( !(inph(address)&0x80) ); + outph(address,0xFFFF); + } + else if( op==BLOCK_UNLOCK ) + { + outph(address,0x60); + outph(address,0xD0); + while( !(inph(address)&0x80) ); + outph(address,0xFFFF); + } + + return 0; +} + +INT BlockSize_E28F640(UINT32 address) +{ + address-=FLASH_BASE; + address&=0x7FFFFFFF; + if( address < _flash_size ) + return 0x10000; + else + return 0; +} + +INT BlockErase_E28F640(UINT32 address,UINT32 size) +{ + UINT32 i,j,tmp; + CHAR * buffer; + + address|=0x80000000; + buffer = kmalloc(128*1024,GFP_KERNEL); + if(!buffer) + return 1; + // backup the data + j=0xFFFF; + if( (address & FLASH_BLOCK_SIZE) ) + { + + for(i=0;i<FLASH_BLOCK_SIZE/2;i++) + { + tmp=*((volatile unsigned short *)(address-FLASH_BLOCK_SIZE)+i); + *((volatile unsigned short *)buffer+i)=tmp; + j&=tmp; + } + } + else + { + for(i=0;i<FLASH_BLOCK_SIZE/2;i++) + { + tmp=*((volatile unsigned short *)(address+FLASH_BLOCK_SIZE)+i); + *((volatile unsigned short *)buffer+i)=tmp; + j&=tmp; + } + } + + + outph(address,0x20); + outph(address,0xD0); + while( !(inph(address)&0x80) ); + outph(address,0xFFFF); + + + // write back the data + if( (j&0xFFFF)!=0xFFFF ) + { + if( (address & FLASH_BLOCK_SIZE) ) + BlockWrite_E28F640(address-FLASH_BLOCK_SIZE, (UCHAR *)buffer, FLASH_BLOCK_SIZE); + else + BlockWrite_E28F640(address+FLASH_BLOCK_SIZE, (UCHAR *)buffer, FLASH_BLOCK_SIZE); + } + FlushDCache(); + kfree(buffer); + return 0; +} + +INT BlockWrite_E28F640(UINT32 address, UCHAR * data, UINT32 size) +{ + UINT32 i; +#if 0 + UINT32 pdata,j; + + address|=0x80000000; + + do{ + outph(address, 0xE8); + }while( !(inph(address)&0x80) ); + + i=size; + while(i) + { + if( i < 32 ) + { + outph(address, i); + for(j=0;j<i/2;j++) + outph(address+j, *((unsigned short *)pdata+j)); + pdata+=i; + i=0; + } + else + { + outph(address, 32); + for(j=0;j<16;j++) + outph(address+j, *((unsigned short *)pdata+j)); + pdata+=32; + i-=32; + } + outph(address, 0xD0); + while( !(inph(address)&0x80) ); + } + +#else + address|=0x80000000; + + for(i=address;i<address+size;i+=2) + { + outph(i,0x40); + outph(i,*((UINT16 *)data)); + while( !(inph(i)&0x80) ); + data+=2; + } + + outph(address,0xFFFF); +#endif + + FlushDCache(); + return 0; +} + +INT ReadPID_E28F640(UINT32 address, UCHAR *pid0, UCHAR *pid1) +{ + if( !CheckDataWidth(16) )return -1; + + outph(address,0x90); + *pid0=inph(address); + *pid1=inph(address+1); + outph(address,0xFFFF); + + _flash_size=0x800000; + + return 0; +} + + +INT BlockSize_SST39VF160(UINT32 address) +{ + address-=FLASH_BASE; + address&=0x7FFFFFFF; + if( address < _flash_size ) + return 0x10000; + else + return 0; + +} + + +INT ReadPID_SST39VF160(UINT32 address, UCHAR *pid0, UCHAR *pid1) +{ + + ReadPID_AM29LV(address, pid0, pid1); + outph(address, 0x00F0 ); /* Exit Software ID mode */ + _flash_size=0x200000; + + return 0; +} + +INT BlockErase_SST39VF160(UINT32 address,UINT32 size) +{ + UINT32 addr1,addr2; + INT status; + + if( (address&(size-1))!=0x0 )return -1;// not in the start of a block + + address|=0x80000000; + addr1=(address&0xFFF00000)+(0x5555<<1); + addr2=(address&0xFFF00000)+(0x2AAA<<1); + + outph(addr1,0xAA); + outph(addr2,0x55); + outph(addr1,0x80); + outph(addr1,0xAA); + outph(addr2,0x55); + outph(address,0x50); + status=polling16(address, 0xFFFF); + + FlushDCache(); + + return status; +} + +INT BlockErase_MX28F160C3B(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 MX28F160C3 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_MX28F160C3B(UINT32 address, UCHAR * data, UINT32 size) +{ + UINT32 i; + int status; + + BlockLock_W28J800TT(address,BLOCK_UNLOCK); // The MX28F160C3 sector is default to be locked + + address|=0x80000000; + for(i=address;i<address+size;i+=2) + { + outph(i,0x40); + outph(i,*((UINT16 *)data)); + //while( !(inph(i)&0x80) ); + status=normal_polling( i, 0x80 ); + if( status < 0 )return -1; // polling time-out + data+=2; + } + outph(address,0xFFFF); + FlushDCache(); + + return 0; +} + +UINT32 FlashSize() +{ + return _flash_size; +} + + + + diff --git a/uClinux-2.4.20-uc1/drivers/block/wbflash/flash_u.c b/uClinux-2.4.20-uc1/drivers/block/wbflash/flash_u.c index 55e6f52..51cb3fd 100644 --- a/uClinux-2.4.20-uc1/drivers/block/wbflash/flash_u.c +++ b/uClinux-2.4.20-uc1/drivers/block/wbflash/flash_u.c @@ -1,246 +1,246 @@ -#include <asm/semaphore.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/config.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <asm/fcntl.h>
-#include <asm/unistd.h>
-#include <asm/uaccess.h>
-#include <asm/arch/flash.h>
-#include <asm/arch/bib.h>
-
-#include <linux/init.h>
-#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)<blockSize;len+=2)
- if(inph((dest+len))!=0xFFFF)
- {
-#ifdef _DEBUG
- printk("01 inph(%x):%x\n",dest+len,inph(dest+len));
-#endif
- if((dest&(blockSize-1))||(dest+i-addr)<=blockSize)
- {
- buf=(UINT32)MALLOC(blockSize);
- if(buf != 0)
- {
-#ifdef _DEBUG
- printk("\n_FlashWrite:dest:%x,addr:%x,buf:%x\n",dest,addr,buf);
-#endif
- //memset((UCHAR *)buf,0xFF,blockSize);
- MEMCPY((UCHAR *)buf,(UCHAR *)addr,blockSize);
-
- //MEMCPY((UCHAR *)buf,(UCHAR *)addr,dest-addr);
- if(i<blockSize-(dest-addr))
- count=i;
- else
- count=blockSize-(dest-addr);
-
-#ifdef _DEBUG
- printk("\n_FlashWrite:i:%d,count:%d,dest:%x,addr:%x,len:%d\n",i,count,dest,addr,len);
-#endif
-
- MEMCPY((void *)(buf+(dest-addr)),(void *)src,count);
-
- down(&spare_lock);
- //save_flags(flags); cli();//prevent closing watch dog interrupt
-#ifdef _DEBUG
- printk("%s:%d BlockErase,%x\n",__FILE__,__LINE__,inph(dest+len));
-#endif
- cfiCmd.erase(addr, blockSize);
-#ifdef _DEBUG
- printk("02 inph(%x):%x\n",dest+len,inph(dest+len));
- printk("%s:%d BlockWrite\n",__FILE__,__LINE__);
-#endif
- cfiCmd.write(addr, (UCHAR *)buf, blockSize);
-#ifdef _DEBUG
- printk("03 inph(%x):%x\n",dest+len,inph(dest+len));
-#endif
- //restore_flags(flags);
- up(&spare_lock);
-
- FREE((void *)buf);
- blockSize = count;
- }
- else
- {
- return (iBufLen - i);
- }
- }
- else
- {
- down(&spare_lock);
- //save_flags(flags); cli();
-#ifdef _DEBUG
- printk("\nb_FlashWrite:i:%d,count:%d,dest:%x,addr:%x,%x\n",i,count,dest,addr,inph(dest+len));
-#endif
- cfiCmd.erase(dest, blockSize);
- cfiCmd.write(dest, (UCHAR *)src, blockSize);
-
- //restore_flags(flags);
- up(&spare_lock);
- }
- break;
- }
- if((len>=i)||((len+dest-addr)>=cfiGetBlockSize(dest)))
- {
- if((dest&(blockSize-1))||(dest+i-addr)<=blockSize)
- {
-#ifdef _DEBUG
-printk("Write direct\n");
-#endif
- if(i<blockSize-(dest-addr))
- count=i;
- else
- count=blockSize-(dest-addr);
- down(&spare_lock);
- //save_flags(flags); cli();
- cfiCmd.write(dest, (UCHAR *)src, count);
- //restore_flags(flags);
- up(&spare_lock);
- blockSize=count;
- }
- else
- {
-#ifdef _DEBUG
-printk("Write direct one block\n");
-#endif
- down(&spare_lock);
- //save_flags(flags); cli();
- cfiCmd.write(dest, (UCHAR *)src, blockSize);
- //restore_flags(flags);
- up(&spare_lock);
- }
- }
- src+=blockSize;
- dest+=blockSize;
- i-=blockSize;
- }
-
- return (iBufLen);
-}
-
-module_init(Init_WinbondFlash);
+#include <asm/semaphore.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/config.h> +#include <linux/major.h> +#include <linux/slab.h> +#include <asm/fcntl.h> +#include <asm/unistd.h> +#include <asm/uaccess.h> +#include <asm/arch/flash.h> +#include <asm/arch/bib.h> + +#include <linux/init.h> +#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)<blockSize;len+=2) + if(inph((dest+len))!=0xFFFF) + { +#ifdef _DEBUG + printk("01 inph(%x):%x\n",dest+len,inph(dest+len)); +#endif + if((dest&(blockSize-1))||(dest+i-addr)<=blockSize) + { + buf=(UINT32)MALLOC(blockSize); + if(buf != 0) + { +#ifdef _DEBUG + printk("\n_FlashWrite:dest:%x,addr:%x,buf:%x\n",dest,addr,buf); +#endif + //memset((UCHAR *)buf,0xFF,blockSize); + MEMCPY((UCHAR *)buf,(UCHAR *)addr,blockSize); + + //MEMCPY((UCHAR *)buf,(UCHAR *)addr,dest-addr); + if(i<blockSize-(dest-addr)) + count=i; + else + count=blockSize-(dest-addr); + +#ifdef _DEBUG + printk("\n_FlashWrite:i:%d,count:%d,dest:%x,addr:%x,len:%d\n",i,count,dest,addr,len); +#endif + + MEMCPY((void *)(buf+(dest-addr)),(void *)src,count); + + down(&spare_lock); + //save_flags(flags); cli();//prevent closing watch dog interrupt +#ifdef _DEBUG + printk("%s:%d BlockErase,%x\n",__FILE__,__LINE__,inph(dest+len)); +#endif + cfiCmd.erase(addr, blockSize); +#ifdef _DEBUG + printk("02 inph(%x):%x\n",dest+len,inph(dest+len)); + printk("%s:%d BlockWrite\n",__FILE__,__LINE__); +#endif + cfiCmd.write(addr, (UCHAR *)buf, blockSize); +#ifdef _DEBUG + printk("03 inph(%x):%x\n",dest+len,inph(dest+len)); +#endif + //restore_flags(flags); + up(&spare_lock); + + FREE((void *)buf); + blockSize = count; + } + else + { + return (iBufLen - i); + } + } + else + { + down(&spare_lock); + //save_flags(flags); cli(); +#ifdef _DEBUG + printk("\nb_FlashWrite:i:%d,count:%d,dest:%x,addr:%x,%x\n",i,count,dest,addr,inph(dest+len)); +#endif + cfiCmd.erase(dest, blockSize); + cfiCmd.write(dest, (UCHAR *)src, blockSize); + + //restore_flags(flags); + up(&spare_lock); + } + break; + } + if((len>=i)||((len+dest-addr)>=cfiGetBlockSize(dest))) + { + if((dest&(blockSize-1))||(dest+i-addr)<=blockSize) + { +#ifdef _DEBUG +printk("Write direct\n"); +#endif + if(i<blockSize-(dest-addr)) + count=i; + else + count=blockSize-(dest-addr); + down(&spare_lock); + //save_flags(flags); cli(); + cfiCmd.write(dest, (UCHAR *)src, count); + //restore_flags(flags); + up(&spare_lock); + blockSize=count; + } + else + { +#ifdef _DEBUG +printk("Write direct one block\n"); +#endif + down(&spare_lock); + //save_flags(flags); cli(); + cfiCmd.write(dest, (UCHAR *)src, blockSize); + //restore_flags(flags); + up(&spare_lock); + } + } + src+=blockSize; + dest+=blockSize; + i-=blockSize; + } + + return (iBufLen); +} + +module_init(Init_WinbondFlash); diff --git a/uClinux-2.4.20-uc1/drivers/block/wbflash/image.c b/uClinux-2.4.20-uc1/drivers/block/wbflash/image.c index ea79b7d..800fc2f 100644 --- a/uClinux-2.4.20-uc1/drivers/block/wbflash/image.c +++ b/uClinux-2.4.20-uc1/drivers/block/wbflash/image.c @@ -1,178 +1,178 @@ -#include <asm/arch/flash.h>
-#include <asm/semaphore.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/config.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <asm/fcntl.h>
-#include <asm/unistd.h>
-#include <asm/uaccess.h>
-#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<sizeof(tfooter)/4-1;i++)// Not include the checksum
- {
- sum+=*(p+i);
- }
- sum = ~((sum&(-1LU))+(sum>>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;i<footer_num;i++)
- {
- if( footer[i]->num == 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;i<footer_num;i++)
- {
- if( image_footer->num == 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;i<footer_num;i++)
- {
- a0=footer[i]->base;
- 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;
-}
-
-
-
+#include <asm/arch/flash.h> +#include <asm/semaphore.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/config.h> +#include <linux/major.h> +#include <linux/slab.h> +#include <asm/fcntl.h> +#include <asm/unistd.h> +#include <asm/uaccess.h> +#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<sizeof(tfooter)/4-1;i++)// Not include the checksum + { + sum+=*(p+i); + } + sum = ~((sum&(-1LU))+(sum>>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;i<footer_num;i++) + { + if( footer[i]->num == 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;i<footer_num;i++) + { + if( image_footer->num == 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;i<footer_num;i++) + { + a0=footer[i]->base; + 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; +} + + + |