📄 nordriver.c
字号:
/* amd29LvMtd.c - TrueFFS MTD for AMD AM29LV devices */ /* Copyright 2000 Wind River, Inc. *//*modification history--------------------01h,27oct01,mil Removed inline eieio and replaced with CACHE_PIPE_FLUSH().01g,11oct01,mil Merged from post T2.1 release into T2.2.01f,22aug01,mil Decoupled this MTD from BSP by using tffsFlashBaseAdrs from sysTffs.c.01e,21aug01,mil Created in mcpn765 for TFFS until merged back to target/src/drv/tffs/amdmtd.c.01d,06aug00,srr Modified amd29lv323CT support for 16 MB.01c,31jul00,cak Renamed from mv2400mtd to amd29lvmtd. Added support for the amd29lv323. 01b,09may00,add Fixed erase bug (last 4 sectors are odd sizes)01a,21apr00,add Created.*//*DESCRIPTIONThis module implements an TrueFFS MTD for the AMD AM29LV160D andAM29LV323 flash devices. *//* includes */#include "config.h"#ifdef INCLUDE_TFFS #include <vxWorks.h>#include <taskLib.h>#include <logLib.h>#include <stdio.h>#include <cacheLib.h>#include "tffs/flflash.h"#include "tffs/backgrnd.h"IMPORT int sysClkRateGet();#define AT91C_A24_NC/* defines */#define S29GL_N_256_MTD_SECTOR_SIZE NOR_FLASH_SECTOR_SIZE_IN_BYTES#define S29GL_N_256_CHIP_SIZE NOR_FLASH_TFFS_SIZE_IN_BYTES#define S29GL_N_256_LAST_SECTOR_NUM (S29GL_N_256_CHIP_SIZE / S29GL_N_256_MTD_SECTOR_SIZE - 1)#define AMD29LV_MTD_SECTOR_SIZE (0x40000)#define AMD29LV_160_CHIP_SIZE (0x80000) /* 8MB */#define AMD29LV_160_LAST_SECTOR_NUM (AMD29LV_160_CHIP_SIZE / AMD29LV_MTD_SECTOR_SIZE - 1)/* specific 160 chip defines */#define AMD29LV_160_D_MTD_SECTOR_SIZE (NOR_FLASH_SECTOR_SIZE_IN_BYTES)#define AMD29LV_160_D_CHIP_SIZE (NOR_FLASH_TFFS_SIZE_IN_BYTES) #define AMD29LV_160_D_LAST_SECTOR_NUM (AMD29LV_160_D_CHIP_SIZE / AMD29LV_160_D_MTD_SECTOR_SIZE - 1)#define AMD29LV_323_CHIP_SIZE (0x1000000) /* 16MB */#define AMD29LV_323_LAST_SECTOR_SIZE (0x8000)#define AMD29LV_323_LAST_SECTOR_NUM (AMD29LV_323_CHIP_SIZE / AMD29LV_MTD_SECTOR_SIZE - 1)#define AMD29LV_MTD_CHIP_CNT (1)#define AMD29LV_MTD_INTERLEAVE (1)#define DEBUG_READ 0x00000001#define DEBUG_WRITE 0x00000002#define DEBUG_PROGRAM 0x00000004#define DEBUG_ERASE 0x00000008#define DEBUG_ID 0x00000010#define DEBUG_MAP 0x00000020#define DEBUG_PROG32 0x00000040#define DEBUG_ALWAYS 0xffffffff#undef TFFS_NOR_DEBUG#ifdef TFFS_NOR_DEBUG LOCAL UINT32 tffs_nor_debug_switch = DEBUG_ALWAYS; #define TFFS_NOR_DEBUG_PRINT(mask, string) \ if ((tffs_nor_debug_switch & mask) || (mask == DEBUG_ALWAYS)) \ printf string#else #define TFFS_NOR_DEBUG_PRINT(mask, string)#endif/* local routines */LOCAL FLStatus amd29lvSectorRangeErase(FLFlash* pVol, int, int);LOCAL FLStatus amd29lvProgram(FLFlash*, CardAddress, const void FAR1*, int, FLBoolean);LOCAL void FAR0* amd29lvMap(FLFlash*, CardAddress, int);LOCAL void flashReset(FLFlash*, BOOL);LOCAL void flashIdGet(FLFlash*, UINT16*, UINT16*);LOCAL void flashUnlock(FLFlash*, BOOL);LOCAL STATUS flashProgram16Bits(FLFlash*, volatile UINT16*, UINT16, BOOL);LOCAL void flashRegWrite16Bits(FLFlash*, UINT32, UINT32, BOOL);LOCAL UINT16 flashRegRead16Bits(FLFlash*, UINT32, BOOL);LOCAL STATUS flashSectorErase(FLFlash*, int , BOOL);/******************************************************************************** amd29lvMTDIdentify - MTD identify routine (see TrueFFS Programmer's Guide)** RETURNS: FLStatus**/FLStatus amd29lvMTDIdentify ( FLFlash* pVol ){ UINT16 manCode; UINT16 devCode; if (pVol->socket->window.baseAddress != (NOR_FLASH_TFFS_BASE >> 12)) { TFFS_NOR_DEBUG_PRINT(DEBUG_ID, ("%s: base address (0x%x) mismatch. \n", __FUNCTION__, (vol.socket->window.baseAddress <<12))); printf("window.baseAddress = 0x%x\n", (pVol->socket->window.baseAddress <<12)); return flUnknownMedia; } #if 1 flashIdGet(pVol, &manCode, &devCode);#else *((volatile UINT16 *)NOR_FLASH_TFFS_BASE + 0x555) = 0xAA; *((volatile UINT16 *)NOR_FLASH_TFFS_BASE + 0x2AA) = 0x55; *((volatile UINT16 *)NOR_FLASH_TFFS_BASE + 0x555) = 0x90; *manCode = *((volatile UINT16 *)NOR_FLASH_TFFS_BASE + 0x000); *((volatile UINT16 *)NOR_FLASH_TFFS_BASE + 0x555) = 0xAA; *((volatile UINT16 *)NOR_FLASH_TFFS_BASE + 0x2AA) = 0x55; *((volatile UINT16 *)NOR_FLASH_TFFS_BASE + 0x555) = 0x90; *devCode = *((volatile UINT16 *)NOR_FLASH_TFFS_BASE + 0x001); /* Issue reset command to exit autoselect mode */ *((volatile UINT16 *)ROM_BASE_ADRS + 0x000) = 0xF0;#endif if (manCode != 0x0001) { TFFS_NOR_DEBUG_PRINT(DEBUG_ALWAYS, ("amd29lvMTDIdentify Manufacturer unknown: 0x%02x\n", manCode)); return(flUnknownMedia); } if (devCode == 0x227e) /* amd29LV160BT */ { pVol->type = 0x017e; pVol->erasableBlockSize = S29GL_N_256_MTD_SECTOR_SIZE; pVol->chipSize = S29GL_N_256_CHIP_SIZE; pVol->noOfChips = AMD29LV_MTD_CHIP_CNT; pVol->interleaving = AMD29LV_MTD_INTERLEAVE; pVol->write = amd29lvProgram; pVol->erase = amd29lvSectorRangeErase; pVol->map = amd29lvMap; } else if (devCode == 0x22C4) /* amd29LV160BT */ { pVol->type = 0x01C4; pVol->erasableBlockSize = AMD29LV_MTD_SECTOR_SIZE; pVol->chipSize = AMD29LV_160_CHIP_SIZE; pVol->noOfChips = AMD29LV_MTD_CHIP_CNT; pVol->interleaving = AMD29LV_MTD_INTERLEAVE; pVol->write = amd29lvProgram; pVol->erase = amd29lvSectorRangeErase; pVol->map = amd29lvMap; } else if (devCode == 0x2249) { pVol->type = 0x0149; pVol->erasableBlockSize = AMD29LV_160_D_MTD_SECTOR_SIZE; pVol->chipSize = AMD29LV_160_D_CHIP_SIZE; pVol->noOfChips = AMD29LV_MTD_CHIP_CNT; pVol->interleaving = AMD29LV_MTD_INTERLEAVE; pVol->write = amd29lvProgram; pVol->erase = amd29lvSectorRangeErase; pVol->map = amd29lvMap; } else if (devCode == 0x2250) /* amd29LV323CT */ { pVol->type = 0x0150; pVol->erasableBlockSize = AMD29LV_MTD_SECTOR_SIZE; pVol->chipSize = AMD29LV_323_CHIP_SIZE; pVol->noOfChips = AMD29LV_MTD_CHIP_CNT; pVol->interleaving = AMD29LV_MTD_INTERLEAVE; pVol->write = amd29lvProgram; pVol->erase = amd29lvSectorRangeErase; pVol->map = amd29lvMap; } else { TFFS_NOR_DEBUG_PRINT(DEBUG_ALWAYS, ("amd29lvMTDIdentify Device unknown: 0x%02x\n", devCode)); return(flUnknownMedia); } TFFS_NOR_DEBUG_PRINT(DEBUG_ID, ("amd29lvMTDIdentify succeeds!\n")); return(flOK); }/******************************************************************************** amd29lvProgram - MTD write routine (see TrueFFS Programmer's Guide)** RETURNS: FLStatus**/LOCAL FLStatus amd29lvProgram ( FLFlash* pVol, CardAddress address, const void FAR1* buffer, int length, FLBoolean overwrite ){ volatile UINT16* pFlash = NULL; UINT16* pBuffer = NULL; STATUS rc = OK; int i; BOOL doFree = FALSE; TFFS_NOR_DEBUG_PRINT(DEBUG_PROGRAM, ("Program: 0x%08x, 0x%08x, %d\n", (unsigned int) address, length, overwrite)); if (flWriteProtected(vol.socket)) { return(flWriteProtect); } /* Check alignment */ if (((address & 0x01) != 0) || (((UINT32) buffer) & 0x01)) { TFFS_NOR_DEBUG_PRINT(DEBUG_ALWAYS, ("amd29lvProgram: Alignment error\n")); return(flBadParameter); } if (overwrite && length == 2) { int sector = 0; int offset = 0; pFlash = (volatile UINT16*) pVol->map(pVol, address, length); pBuffer = (UINT16*) malloc(S29GL_N_256_MTD_SECTOR_SIZE); if (pBuffer == 0) { TFFS_NOR_DEBUG_PRINT(DEBUG_ALWAYS, ("amd29lvProgram: No memory\n")); return(flBadParameter); } /* Determine sector and offset */ sector = address / S29GL_N_256_MTD_SECTOR_SIZE; offset = address % S29GL_N_256_MTD_SECTOR_SIZE; TFFS_NOR_DEBUG_PRINT(DEBUG_PROGRAM,("Overwrite sector: 0x%08x, offset: 0x%08x\n", sector,offset)); /* Get a pointer to the flash sector */ pFlash = (volatile UINT16*) pVol->map(pVol, sector * S29GL_N_256_MTD_SECTOR_SIZE, S29GL_N_256_MTD_SECTOR_SIZE); /* Copy the sector from flash to memory */ memcpy(pBuffer, (void*) pFlash, S29GL_N_256_MTD_SECTOR_SIZE); /* Overwrite the sector in memory */ memcpy(((UINT8*) pBuffer) + offset, buffer, length); /* Erase sector */ rc = amd29lvSectorRangeErase(pVol, sector, 1); if (rc != flOK) { printf("Erase sector failed.\r\n"); free(pBuffer); return(rc); } length = S29GL_N_256_MTD_SECTOR_SIZE; doFree = TRUE; } else { if ((length & 0x01) != 0) { TFFS_NOR_DEBUG_PRINT(DEBUG_ALWAYS, ("amd29lvProgram: length: %d\n", length)); return(flBadParameter); } pBuffer = (UINT16*) buffer; pFlash = (volatile UINT16*) pVol->map(pVol, address, length); } /* Program 'length' bytes (4 bytes each iterations) */ for (i = 0; i < (length / 2); i++, pFlash++) { /* Don't bother programming if buffer data == format value */ if (pBuffer[i] == (UINT16)0xffff) continue; /* Program 16 bits */ rc = flashProgram16Bits(pVol, pFlash, pBuffer[i], FALSE); if (rc != OK) break; } if (doFree) { free(pBuffer); } if (rc != OK) { TFFS_NOR_DEBUG_PRINT(DEBUG_ALWAYS, ("amd29lvProgram: TimedOut.\r\n")); return (flTimedOut); } return(flOK); }/******************************************************************************** amd29lvSectorRangeErase - MTD erase routine (see TrueFFS Programmer's Guide)** RETURNS: FLStatus**/LOCAL FLStatus amd29lvSectorRangeErase ( FLFlash* pVol, int sectorNum, int sectorCount ){ int i; STATUS rc; /* Check for valid range */ if (pVol->type == 0x017e) /* amd29LV160BT */ { if (sectorNum + sectorCount > S29GL_N_256_LAST_SECTOR_NUM + 1) { TFFS_NOR_DEBUG_PRINT(DEBUG_ALWAYS, ("Invalid sector range: %d - %d\n", sectorNum, sectorCount)); } } else if (pVol->type == 0x1C4) /* amd29LV160BT */ { if (sectorNum + sectorCount > AMD29LV_160_LAST_SECTOR_NUM + 1) { TFFS_NOR_DEBUG_PRINT(DEBUG_ALWAYS, ("Invalid sector range: %d - %d\n", sectorNum, sectorCount)); } /* Last sector is really 4 seperately erasable sectors */ if (sectorNum + sectorCount == AMD29LV_160_LAST_SECTOR_NUM + 1) { sectorCount += 3; } } else if (pVol->type == 0x149) /* amd29LV160D */ { if (sectorNum + sectorCount > AMD29LV_160_D_LAST_SECTOR_NUM + 1) { TFFS_NOR_DEBUG_PRINT(DEBUG_ALWAYS, ("Invalid sector range: %d - %d\n", sectorNum, sectorCount)); } } else /* amd29LV323CT */ { if (sectorNum + sectorCount > AMD29LV_323_LAST_SECTOR_NUM + 1) { TFFS_NOR_DEBUG_PRINT(DEBUG_ALWAYS, ("Invalid sector range: %d - %d\n", sectorNum, sectorCount)); } /* Last sector is really 8 seperately erasable sectors */ if (sectorNum + sectorCount == AMD29LV_323_LAST_SECTOR_NUM + 1) { sectorCount += 7; } } for (i = 0; i < sectorCount; i++) {#if 0 /* Erase lower half */ rc = flashHalfSectorErase(pVol, sectorNum + i, FALSE); if (rc != OK) return(flTimedOut); /* Erase upper half */ rc = flashHalfSectorErase(pVol, sectorNum + i, TRUE); if (rc != OK) return(flTimedOut);#else rc = flashSectorErase(pVol, sectorNum + i, FALSE); if (rc != OK) { return(flTimedOut); } #endif } return(flOK); }/******************************************************************************** amd29lvMap - MTD map routine (see TrueFFS Programmer's Guide)** RETURNS: FLStatus**/LOCAL void FAR0* amd29lvMap ( FLFlash* pVol, CardAddress address, int length ) {#if 0 #if 0 UINT32 flashBaseAddr = (pVol->socket->window.baseAddress << 12); void FAR0* pFlash = (void FAR0*) (flashBaseAddr + address); TFFS_NOR_DEBUG_PRINT(DEBUG_MAP, ("Mapping 0x%08x bytes at 0x%08x to %p\n", length, (unsigned int) address, pFlash)); return(pFlash); #else #ifdef AT91_NOR_FLASH_16M_TO_32M printf("\namd29lvMap() address:0x%x\n",address);/*add by wurj*/ if (address >= 0xf00000) { printf("\namd29lvMap() address:0x%x > 0xf00000\n",address);/*add by wurj*/ address += 0x1100000; } #endif /* AT91_NOR_FLASH_16M_TO_32M */ return ((void FAR0*)((pVol->socket->window.baseAddress << 12) + address)); #endif#endif/* base = 10100000; size = 1f00000 tempaddress : 10100000 -- 12000000
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -