⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cfiamd.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* cfiamd.c - MTD for AMD parts that comply with CFI */ /* Copyright 1984-2002 Wind River Systems, Inc. */#include "copyright_wrs.h"/* FAT-FTL Lite Software Development Kit * Copyright (C) M-Systems Ltd. 1995-2001       *//*modification history--------------------01l,24jun02,nrv  fixing the condition where flashPtr[0x24] is checked twice01k,30apr02,nrv  cleaned up the code by removing local var gif01j,09apr02,yp   fixed SPR 75069. reworked write routines so status chek would work.01i,28mar02,nrv  vol.mtdVars is dereferenced before the pointer is set in                 cfiAmdIdentify01h,12feb02,yp   Written based on cfiscs.c*//*DESCRIPTIONThis library provides an MTD for devices that conform to the Common Flash Interface (CFI) and the AMD/Fujitsu command set. The library provides identification, erase and write routines for 8 and 16 bit devices in native or byte mode. Support is also added for word width devices interleaved word wide where bytes 0 and 1 would be on device one and bytes 2 and 3 would be on device two, and so on. Support is also present for configurations that only permit double word width writes.The identification process supports byte, word, and double word width devices as specified by the CFI query process. Vendr specific extentions are made available from an instance specific data structure, referred to in this file as thisCFI. In addition to supporting a boot code region through the format process thisdriver is also able to reserve the last erase block of each device in the arrayso the vxWorks may use this region as NVRAM if the macro SAVE_NVRAM_REGION is defined.The low voltage devices that support boot blocks get no special treatment in this driver. The asymmetric regions are regocgnized from the erase block regioninformation retreaved during CFI identification. They can, therefore be used by the the file system just like any other sector, if they are not used for boot purposes. Since TrueFFS does not support uneven sector distribution, the size of the largest sector is taken as the erase block size. When an erase request corresponds to the boot block region, all sectors in the boot block are erased.As such, the NVRAM area saved on a top boot device is the entire boot block and not just the last sector as one might expect.Based on the observation that CFI data on the sector distribution on AMD devicesalways describes bottom boot devices, this driver does an "autoselect" to determine the boot block type for proper interpretation of the device geometry data. The erase process assumes that bottom boot devices have the boot block located in sector zero. The first erase block encountered in an erase request that has a sector size other than vol.erasableBlockSize on top boot devices is assumed to be the boot block anchor on top boot devices.NOMANUAL*/#include <stdio.h>#include "tffs/flflash.h"#include "tffs/backgrnd.h"#define 	MAXSECTORS	128	/* should work with any value */typedef enum    {    BOOTBLOCK_NONE,    BOOTBLOCK_TOP,    BOOTBLOCK_BOTTOM    }BOOTBLOCK;typedef union    {    UCHAR uchar[4];    UINT32 uint32;    } CFI_DWORD;typedef union    {    UCHAR uchar[2];    USHORT ushort;    } CFI_WORD;    /* Instance specific CFI data so that a system may have more than one CFI * device. */typedef struct {  unsigned         commandSetId;            /* id of a specific command set. */  unsigned         altCommandSetId;         /* id of alternate command set.  */  FLBoolean        wordMode;                /* TRUE - word mode.             */					    /* FALSE - byte mode.            */  int              multiplier;              /* the number of bytes between   */					    /* 1st Q and 1st R in query	     */  int		   interleaveWidth;	    /* 1 - byte 2 - word interleaved */	  unsigned         maxBytesWrite;           /* maximum number of bytes       */					    /* in multi-byte write.          */  FLBoolean        vpp;                     /* if = TRUE, need vpp.          */  long             optionalCommands;        /* optional commands supported   */					    /* (1 = yes, 0 = no):            */					    /* bit 0 - chip erase.           */					    /* bit 1 - suspend erase.        */					    /* bit 2 - suspend write         */					    /* bit 3 - lock/unlock.          */					    /* bit 4 - queued erase.         */  unsigned         afterSuspend;            /* functions supported after     */					    /* suspend (1 = yes, 0 = no):    */					    /* bit 0 - write after erase     */					    /*         suspend.              */  int 		   sectorDefs;		    /* Number of sector definitions  */  struct {				    /* sector descriptions as found  */      long 	   secSize;		    /* in CFI query. 		     */      int 	   numSecs;		    /*				     */  }secDesc[8];				    /* assume 8 is enough	     */  struct {				    /*				     */      long	   sectorSize;		    /* sector size 		     */      UINT32	   sectorBaseAdrs;	    /* base address of sector	     */  } secInfo[MAXSECTORS];		    /* per sector info		     */  UINT32 unlockAddr1;			    /* offset for first unlock	     */  UINT32 unlockAddr2;			    /* offset for 2nd unlock	     */  int sectorsInCFI;			    /* sector count for device	     */  int bootBlockSectors;			    /* sectors that makeup boot block*/  BOOTBLOCK bootBlockType;		    /* Top, Bottom or None	     */      } CFI;LOCAL CFI mtdVars[DRIVES];/* defines *//* Save the last erase block on each device discovered in the array  * for NVRAM */#define SAVE_NVRAM_REGION/* disable debugging */#undef CFI_DEBUG#ifdef CFI_DEBUG#define DEBUG_PRINT    printf#else#undef DEBUG_PRINT#endif#ifndef _BYTE_ORDER#error "Error: _BYTE_ORDER needs to be #define'd.  Try #include \"vxWorks.h\" "#endif#if (_BYTE_ORDER == _BIG_ENDIAN)#define CFI_LONGSWAP(x)	LONGSWAP(x)	/* swap everything in a long word */#define CFI_WORDSWAP(x) WORDSWAP(x)	/* swap the shorts in a long */#define CFI_BYTESWAP(x) ( ( (x & 0xff) << 8) | ( (x >> 8) & 0xff) )  /* Swap bytes in a short */#else#define CFI_LONGSWAP(x)	(x)		/* pass it as is */#define CFI_WORDSWAP(x) (x)		/* pass it as is */#define CFI_BYTESWAP(x) (x)		/* pass it as is */#endif /* _BYTE_ORDER == _BIG_ENDIAN */#define CFI_LONG_WRITE(addr, data)  (*(ULONG *)addr = (ULONG)(CFI_WORDSWAP(data)))#define CFI_WORD_WRITE(addr, data)  (*(USHORT *)addr = (USHORT)(CFI_BYTESWAP(data)))#define CFI_WORD_READ(addr)         (CFI_BYTESWAP(*(USHORT *)addr))#define CFI_LONG_READ(addr)         (CFI_WORDSWAP(*(ULONG *)addr))/* command set IDs */#define INTEL_COMMAND_SET      0x0001#define AMDFUJ_COMMAND_SET     0x0002#define INTEL_ALT_COMMAND_SET  0x0001#define AMDFUJ_ALT_COMMAND_SET 0x0004#define ALT_NOT_SUPPORTED      0x0000/* CFI identification strings */#define ID_STR_LENGTH      3#define QUERY_ID_STR       "QRY"#define PRIMARY_ID_STR     "PRI"#define ALTERNATE_ID_STR   "ALT"/* commands */#define AMD_SETUP_ERASE		0x80#define AMD_SETUP_WRITE		0xa0#define AMD_READ_ID 		0x90#define AMD_SUSPEND_ERASE	0xb0#define AMD_SECTOR_ERASE	0x30#define AMD_RESUME_ERASE	0x30#define AMD_READ_ARRAY		0xf0#define AMD_NO_UNLOCK_ADDR 0xffffffffL#define AMD_UNLOCK_1		0xaa#define	AMD_UNLOCK_2		0x55#define AMD_WW_UNLOCK_ADDR1	0x555u	/* Word wide devices */#define	AMD_WW_UNLOCK_ADDR2	0x2aau  /* Word wide devices */#define AMD_BW_UNLOCK_ADDR1	0xaaau  /* Byte wide devices */#define	AMD_BW_UNLOCK_ADDR2	0x555u  /* Byte wide devices */#define	AMD_D2		4	/* Toggles when erase suspended */#define AMD_D5		0x20	/* Set when programming timeout */#define	AMD_D6		0x40	/* Toggles when programming *//* optional commands support */#define CHIP_ERASE_SUPPORT           0x0001#define SUSPEND_ERASE_SUPPORT        0x0002#define SUSPEND_WRITE_SUPPORT        0x0004#define LOCK_SUPPORT                 0x0008#define QUEUED_ERASE_SUPPORT         0x0010#define QUERY	0x98/* supported functions after suspend */#define WRITE_AFTER_SUSPEND_SUPPORT  0x0001#define thisCFI   ((CFI *)vol.mtdVars)/* JEDEC IDs *//* 1.8 volt devices */#if 0/* Leaving out this one since it will complicate driver  */#define Am39BDS643G_FLASH	0x017e /* top boot only 95 64KB, 4 16KB,					  31 64KB, and 4 16KB sectors*/#endif #define Am29DS163DT_FLASH	0x0195 /* 8 8KB, and 31 64KB sectors */#define Am29DS163DB_FLASH	0x0196 /* 8 8KB, and 31 64KB sectors */#define Am29DS323DT_FLASH	0x01b7 /* 8 8KB, and 63 64KB sectors */#define Am29DS323DB_FLASH	0x01b8 /* 8 8KB, and 63 64KB sectors */#define Am29PDS322DT_FLASH	0x0101 /* 8 8KB, and 63 64KB sectors */#define Am29PDS322DB_FLASH	0x0100 /* 8 8KB, and 63 64KB sectors */#define Am29SL160CT_FLASH	0x01e4 /* 8 8KB, and 31 64KB sectors */#define Am29SL160CB_FLASH	0x01e7 /* 8 8KB, and 31 64KB sectors *//* 3.0 volt devices */#define Am29LV160BT_FLASH	0x01c4 /* 31 64KB, 1 32KB, 2 8KB, and 1 16KB sectors */#define Am29LV160BB_FLASH       0x0149 /* 1 16KB, 2 8KB, 1 32KB, and 31 64KB sectors */#define Am29DL161DT_FLASH	0x0136 /* 8 8KB, and 31 64KB sectors */#define Am29DL161DB_FLASH	0x0139 /* 8 8KB, and 31 64KB sectors */#define Am29DL162DT_FLASH	0x012d /* 8 8KB, and 31 64KB sectors */#define Am29DL162DB_FLASH	0x012e /* 8 8KB, and 31 64KB sectors */#define Am29DL163DT_FLASH	0x0128 /* 8 8KB, and 31 64KB sectors */#define Am29DL163DB_FLASH	0x012b /* 8 8KB, and 31 64KB sectors */#define Am29DL164DT_FLASH	0x0133 /* 8 8KB, and 31 64KB sectors */#define Am29DL164DB_FLASH	0x0135 /* 8 8KB, and 31 64KB sectors *//* The DL32xG series has the same JEDEC IDs and sector architecture */#define Am29LV320DT_FLASH	0x01f6 /* 8 8KB, and 63 64KB sectors */#define Am29LV320DB_FLASH	0x01f9 /* 8 8KB, and 63 64KB sectors */#define Am29DL322DT_FLASH	0x0155 /* 8 8KB, and 63 64KB sectors */#define Am29DL322DB_FLASH	0x0156 /* 8 8KB, and 63 64KB sectors */#define Am29DL323DT_FLASH	0x0150 /* 8 8KB, and 63 64KB sectors */#define Am29DL323DB_FLASH	0x0153 /* 8 8KB, and 63 64KB sectors */#define Am29DL324DT_FLASH	0x015c /* 8 8KB, and 63 64KB sectors */#define Am29DL324DB_FLASH	0x015f /* 8 8KB, and 63 64KB sectors */#define Am29LV017D_FLASH        0x01c8 /* 32  64KB sectors */#define Am29LV033C_FLASH        0x01a3 /* 64  64KB sectors */#define Am29LV065D_FLASH        0x0193 /* 128 64KB sectors */#define Am29LV116DT_FLASH	0x01c7 /* 31 64KB, 1 32KB, 2 8KB, and 1 16KB 					  sectors */#define Am29LV116DB_FLASH       0x014c /* 1 16KB, 2 8KB, 1 32KB, and 31 64KB 					  sectors */#define Am29LV640D_FLASH	0x01d7 /* 128 64KB sectors *//* left out PDL series because of the double CE# lines and left out PDL  * series since they are quite impractical WRT TrueFFS. Should add support * for mirror bit devices as soon as data sheets become available. *//* 5.0 volt devices */#define Am29F016D_FLASH		0x01ad	/* 32 64KB uniform sectors */#define Am29F017D_FLASH		0x013d	/* 32 64KB uniform sectors */#define Am29F160DT_FLASH	0x01d2 /* 31 64KB, 1 32KB, 2 8KB, and 1 16KB sectors */#define Am29F160DB_FLASH	0x01d8 /* 1 16KB, 2 8KB, 1 32KB, and 31 64KB sectors */#define Fuj29LV160TE_FLASH      0x04c4 /* 31 64KB, 1 32KB, 2 8KB, and 1 16KB sectors */#define Fuj29LV160BE_FLASH      0x0449 /* 1 16KB, 2 8KB, 1 32KB, and 31 64KB sectors *//****************************************************************************** * cfiAmdChipCountGet - return the number of chips in this array * * Leave the first chip (or set of interleaved chips) in READ_ARRAY * mode and move forward by chip size (or interleaved chip size) until * address wrap around is detected. The chip count is updated in  * vol.noOfChips. * * NOMANUAL * */LOCAL FLStatus cfiAmdChipCountGet    (    FLFlash vol    )    {    UINT32 cmdBuffer;    int ix;    char queryIdStr[ID_STR_LENGTH + 1] = QUERY_ID_STR;    FlashPTR flashPtr = (FlashPTR) flMap(vol.socket, 0);    /* Switch first (interleaved) chip set to QUERY mode */    cmdBuffer = 0x0;    for (ix = 0; ix < thisCFI->multiplier; ix++)	cmdBuffer |= QUERY << (8 * ix);    flashPtr[0x55 * thisCFI->multiplier] = cmdBuffer;    /* NOTE: The address wrap around technique used here works only if the flash     * size was declared correctly in the socket driver. At some point the MTD     * should be discovering flash size and exporting it to the socket driver.      */    for (vol.noOfChips = 1 * vol.interleaving;       /* Scan the chips */         vol.noOfChips < 2000;  /* Big enough ? */         vol.noOfChips += vol.interleaving)         {#ifdef SAVE_NVRAM_REGION	/* Reinstate the NVRAM region */	flashPtr = (FlashPTR) flMap(vol.socket, vol.noOfChips * 		(vol.chipSize + (vol.erasableBlockSize / vol.interleaving)));#else	flashPtr = (FlashPTR) flMap(vol.socket, vol.noOfChips * vol.chipSize);#endif#ifdef DEBUG_PRINT	DEBUG_PRINT("Debug: Looking for Flash device at base 0x%x\n", (UINT32) flashPtr);#endif	if ((flashPtr[0x10 * thisCFI->multiplier]) 		    == (unsigned char)queryIdStr[0] &&	    (flashPtr[0x11 * thisCFI->multiplier]) 		    == (unsigned char)queryIdStr[1] &&	    (flashPtr[0x12 * thisCFI->multiplier]) 		    == (unsigned char)queryIdStr[2])	    {	    goto noMoreChips;      /* Wrapped around */	    }	/* Confirm this is also a CFI part */	*(UCHAR *)(flashPtr + (0x55 * thisCFI->multiplier))	   = (UCHAR)(QUERY);	if (flashPtr[0x10 * thisCFI->multiplier]		!= (unsigned char)queryIdStr[0] ||	    flashPtr[0x11 * thisCFI->multiplier]		!= (unsigned char)queryIdStr[1] ||	    flashPtr[0x12 * thisCFI->multiplier]		!= (unsigned char)queryIdStr[2])	    {	    /* Should not happen !! */	    goto noMoreChips;	/* Not a CFI Flash part */	    }	flashPtr[0x55 * thisCFI->multiplier] 		= (UCHAR)(AMD_READ_ARRAY);	}    /* We should never get here. */#ifdef DEBUG_PRINT    DEBUG_PRINT("Debug: Device count overflow\n");#endif  /* DEBUG_PRINT */    return flGeneralFailure;    noMoreChips:    flashPtr = (FlashPTR) flMap(vol.socket, 0);    /* Switch to READ_ARRAY mode */    cmdBuffer = 0x0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -