www.pudn.com > S3c2410bsp.rar > sst39vf160.c


/* sst39vf160.c - SST39VF160 MTD driver */

/*
modification history
--------------------
*/

#include "intLib.h"
#include "stdio.h"
#include "tffs/flflash.h"
#include "config.h"

#define	FLASH_BASE_ADRS		ROM_SIZE
#define	FLASH_SIZE		(0x00400000-ROM_SIZE)

typedef struct {
	FlashWPTR	unlockAddr1;
	FlashWPTR  	unlockAddr2;
} Vars;

static Vars mtdVars[DRIVES];

#define thisVars   ((Vars *) vol.mtdVars)

#undef DEBUG_PRINT	

static void FAR0* sst39vf160Map(FLFlash* pVol,	CardAddress address, int length);
static FLStatus sst39vf160Erase	(FLFlash vol, int firstErasableBlock, int numOfErasableBlocks);
static FLStatus sst39vf160Write	(FLFlash vol, CardAddress address, const void FAR1 *buffer, int length, int modes);
static STATUS  doneDetect(void * ptr,  int timeCounter);

FLStatus sst39vf160Identify(FLFlash vol)
{
	FlashWPTR  baseFlashPtr;
#ifdef DEBUG_PRINT
#endif
	flSetWindowBusWidth(vol.socket, 16);	/* use 16-bits */
	flSetWindowSpeed(vol.socket, 90);  		/* 90 nsec */
	flSetWindowSize(vol.socket, FLASH_SIZE>>12);
	vol.interleaving = 1; 
	vol.chipSize = FLASH_SIZE;
	vol.noOfChips = 0x1;	                /* one chip */
	vol.erasableBlockSize = 0x1000;      	/* 4k bytes */
  
	vol.flags |= SUSPEND_FOR_WRITE;

	vol.map   = sst39vf160Map;	
	vol.erase = sst39vf160Erase;
	vol.write = sst39vf160Write;

	vol.mtdVars = &mtdVars[flSocketNoOf(vol.socket)];
	baseFlashPtr = (FlashWPTR)vol.map (&vol, (CardAddress)0, vol.interleaving);
	thisVars->unlockAddr1 = (FlashWPTR)((long)baseFlashPtr) + 0x5555;
	thisVars->unlockAddr2 = (FlashWPTR)((long)baseFlashPtr) + 0x2aaa;
	return flOK;
}
static void FAR0* sst39vf160Map(FLFlash* pVol,	CardAddress address, int length)
{
	void FAR0* pFlash = (void FAR0*) (FLASH_BASE_ADRS + address);
	return(pFlash);
}
static FLStatus sst39vf160Erase	(FLFlash vol, int firstErasableBlock, int numOfErasableBlocks)
{
	int iBlock, i; 			FlashWPTR flashPtr;
	unsigned int offset;	int level;

	if(numOfErasableBlocks <= 0) return ERROR;

	for (iBlock = 0; iBlock < numOfErasableBlocks; iBlock++) 
	{
		offset = (firstErasableBlock + iBlock) * vol.erasableBlockSize;
		flashPtr = (FlashWPTR) vol.map(&vol, offset, vol.interleaving);
		#ifdef DEBUG_PRINT
		#endif
		*thisVars->unlockAddr1 = 0xaa;
	    *thisVars->unlockAddr2 = 0x55;
	    *thisVars->unlockAddr1 = 0x80;
		*thisVars->unlockAddr1 = 0xaa;
	    *thisVars->unlockAddr2 = 0x55;
		level = intLock();
		*flashPtr = 0x30;
		doneDetect((void *)flashPtr, 0x2000000);				  
		for(i=0; i= 1) {
		*thisVars->unlockAddr1 = 0x0aa;
    	*thisVars->unlockAddr2 = 0x55;
		level = intLock();	
	    *thisVars->unlockAddr1 = 0x0a0;
		*flashPtr = *gBuffer;
		doneDetect((void *)flashPtr, 0x1000000);
		if(*flashPtr != *gBuffer) {
			*flashPtr = 0xf0;
			return flWriteFault;
		}
		intUnlock(level);
		cLength--;
		flashPtr++;
		gBuffer++;
	}
	if (tffscmp((void FAR0 *)flashTmp, buffer,length))
	{
		return flWriteFault;
	}

	return flOK;
}

static STATUS  doneDetect(void * ptr,  int timeCounter)
{
	FlashWPTR pFlash = ptr;
	INT16 buf1,buf2;
	
	buf1 = *pFlash & 0x40;
	while(1){
		buf2  = *pFlash & 0x40;
		if(buf1 == buf2) break; 
		else buf1 = buf2;
		if(timeCounter-- <= 0) return ERROR;
	}
	return OK;
}