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

📄 cfiamd.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    if (flashWPtr[0x20] == 'Q' &&        flashWPtr[0x21] == 'Q' &&        flashWPtr[0x22] == 'R' &&        flashWPtr[0x23] == 'R' &&        flashWPtr[0x24] == 'Y' &&        flashWPtr[0x25] == 'Y')        {#ifdef DEBUG_PRINT        DEBUG_PRINT ("Debug: Detected two 16 bit devices in 16 bit mode(3)\n");#endif	thisCFI->multiplier = 4;	thisCFI->interleaveWidth = 2;	vol.interleaving = 2;	goto getCFI;	}    /* If we get here the device is probably not CFI */	#ifdef DEBUG_PRINT    DEBUG_PRINT ("Debug: Failed to identify CFI... \n Exiting \n");#endif    flashDPtr[0x55] = (ULONG) (AMD_READ_ARRAY << 24| AMD_READ_ARRAY <<16 			     | AMD_READ_ARRAY << 8 | AMD_READ_ARRAY);     return flUnknownMedia;getCFI:    if (!eightBitMode)	{	thisCFI->wordMode = TRUE; /* limitting ourselves to 8 an 16 bit devs */	thisCFI->unlockAddr1 = AMD_WW_UNLOCK_ADDR1;	thisCFI->unlockAddr2 = AMD_WW_UNLOCK_ADDR2;#ifdef DEBUG_PRINT	DEBUG_PRINT("WORD MODE !!\n");#endif	}    else	{	thisCFI->wordMode = FALSE;	thisCFI->unlockAddr1 = AMD_BW_UNLOCK_ADDR1;	thisCFI->unlockAddr2 = AMD_BW_UNLOCK_ADDR2;#ifdef DEBUG_PRINT	DEBUG_PRINT("WORD MODE !!\n");#endif	}    /* check the command set ID */    /* NOTE: Not swapped */    thisCFI->commandSetId = *(USHORT *)(&flashPtr[0x13 * thisCFI->multiplier]);#ifdef DEBUG_PRINT    DEBUG_PRINT ("Debug: Commandset ID is 0x%x\n", thisCFI->commandSetId);#endif    /* Only support the AMD/Fujitsu Command set */    if ( thisCFI->commandSetId != AMDFUJ_COMMAND_SET)         {#ifdef DEBUG_PRINT    DEBUG_PRINT("Debug: did not recognize command set.\n");#endif        return flUnknownMedia;        }    /* get address for primary algorithm extended table. */    primaryTable = CFI_WORD_READ(&flashPtr[0x15 * thisCFI->multiplier]);    /* check alternate command set ID. */    /* NOTE: not swapped */    thisCFI->altCommandSetId = *(USHORT *)				(&flashPtr[0x17 * thisCFI->multiplier]);    if (thisCFI->altCommandSetId != AMDFUJ_ALT_COMMAND_SET &&        thisCFI->altCommandSetId != ALT_NOT_SUPPORTED)        return flUnknownMedia;    /* get address for secondary algorithm extended table. */    secondaryTable = CFI_WORD_READ(&flashPtr[0x19 * thisCFI->multiplier]);    thisCFI->vpp = flashPtr[0x1d * thisCFI->multiplier];    /*Get the number of erase block descriptions for thei CFI*/    if (eightBitMode)	thisCFI->sectorDefs = (int) (*(UCHAR *) 				(&flashPtr[0x2c * thisCFI->multiplier]));    else	thisCFI->sectorDefs = (int) (*(USHORT *)				    (&flashPtr[0x2c * thisCFI->multiplier]));    /* We should bail out if this is greater than 8 */#ifdef DEBUG_PRINT    DEBUG_PRINT ("Debug: Number of erase block descriptions is 0x%x\n", 					    thisCFI->sectorDefs);#endif    vol.erasableBlockSize = 0;    thisCFI->sectorsInCFI = 0;    for ( ix = 0; ix < thisCFI->sectorDefs; ix++)	{	thisCFI->secDesc[ix].numSecs = (int) (*(USHORT *)		(&flashPtr[(0x2d + (ix * 4)) * thisCFI->multiplier]));	thisCFI->secDesc[ix].numSecs++;#ifdef DEBUG_PRINT    DEBUG_PRINT ("Debug: Num sectors in %d - %d\n", ix, thisCFI->secDesc[ix].numSecs);#endif	thisCFI->secDesc[ix].secSize = (long) ((*(USHORT *)		(&flashPtr[(0x2f + (ix * 4)) * thisCFI->multiplier])) +		(*(USHORT *)(&flashPtr[(0x30 + (ix * 4)) * 			       thisCFI->multiplier])) * 0x100L);#ifdef DEBUG_PRINT    DEBUG_PRINT ("Debug: Sector size is 0x%x\n",			(UINT32) thisCFI->secDesc[ix].secSize);#endif	/* TrueFFS does not support the flexible sector architecture so we 	 * take the largest sector size to be the erase block size.	 */ 	if (vol.erasableBlockSize < thisCFI->secDesc[ix].secSize)	    vol.erasableBlockSize = thisCFI->secDesc[ix].secSize;	/* Also track the number of sector on this device */	thisCFI->sectorsInCFI += thisCFI->secDesc[ix].numSecs;	}    if (vol.erasableBlockSize == 0x00)	vol.erasableBlockSize = 0x80L;    else	vol.erasableBlockSize *= 256;    /* Get Device Size */	    if (eightBitMode)	vol.chipSize = (1L << flashPtr[0x27 * thisCFI->multiplier]);    else	vol.chipSize = (1L << *(USHORT*)(&flashPtr[0x27 * thisCFI->multiplier]));    vol.erasableBlockSize *= vol.interleaving;    #ifdef SAVE_NVRAM_REGION    /* Top boot block devices will loose their entire boot block to NVRAM. Since      * TrueFFS cares not about the subdivisions we reserve an entire erase block     * on each of the interleaved devices.      */    vol.chipSize -= vol.erasableBlockSize;#endif#ifdef DEBUG_PRINT    DEBUG_PRINT("Debug: %d sectors on device\n", thisCFI->sectorsInCFI);    DEBUG_PRINT("Debug: Erasable block size is 0x%lx\n", vol.erasableBlockSize);    DEBUG_PRINT("Debug: Chip size is 0x%lx\n", vol.chipSize);#endif    /* Since boot blocks happen to be subdevided erase blocks and TrueFFS does     * not support the sub devision of erase blocks the MTD needs to be able     * to detect the "sectors" that are sub devisions and erase all of them     * (assuming that they are contiguous) together. Since the boot block can     * appear either at the top or the bottom, the only way to keep track of     * them is to read all sector descriptions and remember them for cross     * reference. The size of the largest erase block is registered as the     * eraseBlockSize for the volume.     */    /* Setup the commands first */    for (i = 0; i < thisCFI->multiplier; i++)	{	unlock1 	 |= AMD_UNLOCK_1   << (i * 8);	unlock2 	 |= AMD_UNLOCK_2   << (i * 8);	readID	 	 |= AMD_READ_ID    << (i * 8);	readArray 	 |= AMD_READ_ARRAY << (i * 8);	}	        /* Get JEDEC ID so we know if this is a top or bottom boot device */    *(UINT32 *)(flashPtr + (thisCFI->unlockAddr1 * thisCFI->multiplier)) = unlock1;    *(UINT32 *)(flashPtr + (thisCFI->unlockAddr2 * thisCFI->multiplier)) = unlock2;    *(UINT32 *)(flashPtr + (thisCFI->unlockAddr1 * thisCFI->multiplier)) = readID;    if (eightBitMode)        vol.type = flashPtr[0] << 8 | flashPtr[thisCFI->interleaveWidth];    else	vol.type = (*(USHORT *)(&flashPtr[0]) << 8) | 		    (*(USHORT *)(&flashPtr[thisCFI->multiplier]) & 0x00ff);    /* Determine boot block type */    if ((vol.type == Am29DS163DT_FLASH) ||	(vol.type == Am29DS323DT_FLASH) ||	(vol.type == Am29PDS322DT_FLASH)||	(vol.type == Am29SL160CT_FLASH) ||	(vol.type == Am29DL161DT_FLASH) ||	(vol.type == Am29DL162DT_FLASH) ||	(vol.type == Am29DL163DT_FLASH) ||	(vol.type == Am29DL164DT_FLASH) ||	(vol.type == Am29LV320DT_FLASH) ||	(vol.type == Am29DL322DT_FLASH) ||	(vol.type == Am29DL323DT_FLASH) ||	(vol.type == Am29DL324DT_FLASH) ||	(vol.type == Am29LV116DT_FLASH) ||	(vol.type == Am29F160DT_FLASH)  ||	(vol.type == Fuj29LV160TE_FLASH))	thisCFI->bootBlockType = BOOTBLOCK_TOP;    else if ((vol.type == Am29DS163DT_FLASH) ||	(vol.type == Am29DS323DB_FLASH) ||	(vol.type == Am29PDS322DB_FLASH) ||	(vol.type == Am29SL160CB_FLASH) ||	(vol.type == Am29DL161DB_FLASH) ||	(vol.type == Am29DL162DB_FLASH) ||	(vol.type == Am29DL163DB_FLASH) ||	(vol.type == Am29DL164DB_FLASH) ||	(vol.type == Am29LV320DB_FLASH) ||	(vol.type == Am29DL322DB_FLASH) ||	(vol.type == Am29DL323DB_FLASH) ||	(vol.type == Am29DL324DB_FLASH) ||	(vol.type == Am29LV116DB_FLASH) ||	(vol.type == Am29F160DB_FLASH)  ||	(vol.type == Fuj29LV160BE_FLASH))	thisCFI->bootBlockType = BOOTBLOCK_BOTTOM;    else if ((vol.type == Am29LV017D_FLASH) ||	(vol.type == Am29LV033C_FLASH) ||	(vol.type == Am29LV065D_FLASH) ||	(vol.type == Am29LV640D_FLASH) ||	(vol.type == Am29F016D_FLASH)  ||	(vol.type == Am29F017D_FLASH))	thisCFI->bootBlockType = BOOTBLOCK_NONE;    else	{	/* Probably an unregistered device that needs to be added here */#ifdef DEBUG_PRINT	DEBUG_PRINT ("Unknown device of type 0x%x \n", vol.type);#endif	/* set device back to read array */	*(UINT32 *) flashPtr = AMD_READ_ARRAY;	return flUnknownMedia;	}    /* We now have all of the CFI info that we need. Now lets build up      * the sector map and register the erase block sizes.      */    if (thisCFI->bootBlockType == BOOTBLOCK_NONE)	{#ifdef DEBUG_PRINT	DEBUG_PRINT("Debug: Uniform device, no boot block\n");#endif	/* Simplest case is the uniform sector device. Has only one 	 * sector desc. 	 */	for (; thisSector < thisCFI->secDesc[0].numSecs; thisSector++)	    {	    thisCFI->secInfo[thisSector].sectorSize = vol.erasableBlockSize;	    thisCFI->secInfo[thisSector].sectorBaseAdrs = sectorBaseAdrs;	    sectorBaseAdrs += (CardAddress) vol.erasableBlockSize;	    }	}    else if (thisCFI->bootBlockType == BOOTBLOCK_BOTTOM)	{#ifdef DEBUG_PRINT	DEBUG_PRINT("Debug: Bottom boot block device\n");#endif	/* This is a hack but when looking at the data sheets for all of	 * these devices what comes across is that the CFI data always 	 * describes a botom boot device. There for we read the sector 	 * info in the exact order that it is provided in.	 */    	for ( ix = 0; ix < thisCFI->sectorDefs; ix++)	    {	    int iy;            for (iy = 0; iy < thisCFI->secDesc[ix].numSecs; iy++, thisSector++)                {	    	if (thisCFI->secDesc[ix].secSize != 0x00)	            thisCFI->secInfo[thisSector].sectorSize = 				    thisCFI->secDesc[ix].secSize * 0x100L;	    	else	            thisCFI->secInfo[thisSector].sectorSize = 0x80L;				/* count boot blocks */		if (thisCFI->secInfo[thisSector].sectorSize != vol.erasableBlockSize)		    thisCFI->bootBlockSectors++;			    	thisCFI->secInfo[thisSector].sectorBaseAdrs = sectorBaseAdrs;	    	sectorBaseAdrs += (CardAddress) thisCFI->secInfo[thisSector].sectorSize;	    	}	    }	}    else	/* Top boot device */	{	int secCount;#ifdef DEBUG_PRINT	DEBUG_PRINT("Debug: Top boot block device\n");#endif	/* First load the descriptions of the uniform sectors and 	 * then add the sub divisions 	 */    	for ( ix = 0; ix < thisCFI->sectorDefs; ix++)	    {	    int iy;	    /* We assume that the unform sectors will never be of the 	     * variety 128 bytes 	     */	    if (vol.erasableBlockSize == thisCFI->secDesc[ix].secSize * 0x100L * vol.interleaving)		{            	for (iy = 0; iy < thisCFI->secDesc[ix].numSecs; 							iy++, thisSector++)                    {		    thisCFI->secInfo[thisSector].sectorSize = 							vol.erasableBlockSize;		    thisCFI->secInfo[thisSector].sectorBaseAdrs = 							sectorBaseAdrs;	    	    sectorBaseAdrs += (CardAddress) 		    		thisCFI->secInfo[thisSector].sectorSize;		    }		break;	    	}	    }	for ( ix = 0, secCount = 0; 		thisCFI->secDesc[ix].secSize * 0x100L * vol.interleaving			 != vol.erasableBlockSize; 		ix++)	    {	    int iy;	    for (iy = 0; iy < thisCFI->secDesc[ix].numSecs; iy++, secCount++)		{	    	thisCFI->secInfo[(thisCFI->sectorsInCFI - 1) - secCount].sectorSize = 						thisCFI->secDesc[ix].secSize * 0x100L * vol.interleaving;		}	    }	for (; thisSector <= (thisCFI->sectorsInCFI -1); thisSector++)	    {	    thisCFI->secInfo[thisSector].sectorBaseAdrs = sectorBaseAdrs;    	    sectorBaseAdrs += (CardAddress) thisCFI->secInfo[thisSector].sectorSize;	    thisCFI->bootBlockSectors++;	    }	}#ifdef DEBUG_PRINT    DEBUG_PRINT("Debug: Number of boot block sectors is %d\n", thisCFI->bootBlockSectors);#endif    /* Make sure this comes at the end since the device is set to READ_ARRAY     * mode prior to the return     */    if (cfiAmdChipCountGet(&vol) != flOK)	return flUnknownMedia;#ifdef DEBUG_PRINT    DEBUG_PRINT ("Debug: No of chips detected is %d\n", vol.noOfChips);#if 0    for (ix = 0; ix < thisCFI->sectorsInCFI; ix++)	DEBUG_PRINT ("%2d:0x%x	---  0x%lx\n", ix,			thisCFI->secInfo[ix].sectorBaseAdrs, 			thisCFI->secInfo[ix].sectorSize);#endif#endif    vol.erase = cfiAmdErase;    vol.write = cfiAmdWrite;    /* Might have to do this on a bus width basis but for now it seems to     * work with Intel devices.     */    flashPtr[0] = AMD_READ_ARRAY;    flashPtr[1] = AMD_READ_ARRAY;    flashPtr[2] = AMD_READ_ARRAY;    flashPtr[3] = AMD_READ_ARRAY;    return flOK;    }

⌨️ 快捷键说明

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