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

📄 onenand.c

📁 s3c6400 ADS下官方测试程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/**************************************************************************************
* 
*	Project Name : S3C6400 Validation
*
*	Copyright 2006 by Samsung Electronics, Inc.
*	All rights reserved.
*
*	Project Description :
*		This software is only for validating functions of the S3C6400.
*		Anybody can use this software without our permission.
*  
*--------------------------------------------------------------------------------------
* 
*	File Name : onenand.c
*  
*	File Description : This file implements the API functons for OneNand controller.
*
*	Author : Heemyung.noh
*	Dept. : AP Development Team
*	Created Date : 2006/11/10
*	Version : 0.1 
* 
*	History
*	- Created(Heemyung.noh 2006/11/10)
*  
**************************************************************************************/

#include <stdio.h>

#include "def.h"
#include "option.h"
#include "library.h"
#include "sfr6400.h"
#include "system.h"
#include "sysc.h"
#include "intc.h"
#include "onenand.h"
#include "gpio.h"
#include "dma.h"
#include "timer.h"

#define ONENAND0_MEM_BASE		(0x20000000)
#define ONENAND1_MEM_BASE		(0x28000000)

#define ONENAND1_OFFSET 	(0x80000)
#define ONENAND(__n) 		( ( volatile oONENAND_REGS * ) ( ONENAND_pBase[__n] ) )

#define BUFFER				(0<<22)
#define ARRAY_RW            		(1<<22)
#define COMMANDS            	(2<<22)
#define DIRECT_ACCESS       	(3<<22)

//For OneNand Direct Access
#define	DBS(b)		((b<<5)&0x8000)		// BufferRAM of DDP (Device BufferRAM Select)
#define	DFS(b)		((b<<5)&0x8000)		// flash core of DDP (Device Flash Core Select)
#define	FBA(b)		(b&0x03ff)			// NAND Flash Block Address	
#define	FPA(p)		((p<<2)&0xfc)		// NAND Flash Page Address
#define	FSA(s)		(s&0x3)				// NAND Flash Sector Address
#define	BSA(r)		((r<<8)&0x0f00)		// BufferRAM Sector Address
#define	BSC(n)		(n&0x3)				// BufferRAM Sector Count
#define	SBA(b)		(b&0x03ff)			// Start Block Address

#define OND_DATARAM0				(0x200*4)

//Command Register - CMD 
#define OND_LD_MS_TO_BUF	0x0000
#define OND_LD_SS_TO_BUF	0x0013
#define OND_PG_MS_FR_BUF	0x0080
#define OND_PG_SS_FR_BUF	0x001a
#define OND_CP_BACK_PRG		0x001b
#define OND_UNLOCK			0x0023
#define OND_LOCK			0x002a
#define OND_LOCK_TIGHT		0x002c
#define OND_ERASE_VERIFY	0x0071
#define OND_BLK_ERASE		0x0094
#define OND_MULTY_ERASE		0x0095
#define OND_ERASE_SUS		0x00b0
#define OND_ERASE_RESUME	0x0030
#define OND_RST_CORE		0x00f0
#define OND_RST_OND			0x00f3
#define OND_OTP_ACS			0x0065
	
typedef struct tag_ONENAND_REGS
{
	u32 rMemCfg;
	u32 reserved1[3];
	u32 rBurstLength;
	u32 reserved2[3];
	u32 rMemReset;
	u32 reserved3[3];
	u32 rIntErrStat;
	u32 reserved4[3];
	u32 rIntErrMask;
	u32 reserved5[3];
	u32 rIntErrAck;
	u32 reserved6[3];
	u32 rEccErrStat;
	u32 reserved7[3];
	u32 rManufactID;
	u32 reserved8[3];
	u32 rDeviceID;
	u32 reserved9[3];
	u32 rDataBufSize;
	u32 reserved10[3];
	u32 rBootBufSize;
	u32 reserved11[3];
	u32 rBufAmount;
	u32 reserved12[3];
	u32 rTech;
	u32 reserved13[3];
	u32 rFbaWidth;
	u32 reserved14[3];
	u32 rFpaWidth;
	u32 reserved15[3];
	u32 rFsaWidth;
	u32 reserved16[3];
	u32 rRevision;
	u32 reserved17[3];
	u32 rDataRam0;
	u32 reserved18[3];
	u32 rDataRam1;
	u32 reserved19[3];
	u32 rSyncMode;
	u32 reserved20[3];
	u32 rTransSpare;
	u32 reserved21[3];
	u32 rLockBit;
	u32 reserved22[3];
	u32 rDbsDfsWidth;
	u32 reserved23[3];
	u32 rPageCnt;
	u32 reserved24[3];
	u32 rErrPageAddr;
	u32 reserved25[3];
	u32 rBurstRdLat;
	u32 reserved26[3];
	u32 rIntPinEnable;
	u32 reserved27[3];
	u32 rIntMonCyc;
	u32 reserved28[3];
	u32 rAccClock;
	u32 reserved29[3];
	u32 rSlowRdPath;
	u32 reserved30[3];
	u32 rErrBlkAddr;
	u32 reserved31[3];
	u32 rFlashVerID;
	u32 reserved32[3];
} 
oONENAND_REGS;

static volatile u32	OneNAND_BUFFER_BASE[ONENAND_CONNUM];
static volatile u32	OneNAND_ARRAY_BASE[ONENAND_CONNUM];
static volatile u32	OneNAND_CMD_BASE[ONENAND_CONNUM];
static volatile u32	OneNAND_DIRECT_BASE[ONENAND_CONNUM];

static void *ONENAND_pBase[ONENAND_CONNUM];
volatile ONENAND_oInform	OneNand_Inform[ONENAND_CONNUM];

static u32 FbaShift[ONENAND_CONNUM], FpaShift[ONENAND_CONNUM];//, FsaShift[ONENAND_CONNUM];//, DfsDbs[ONENAND_CONNUM];
static u32 FbaMask[ONENAND_CONNUM], FpaMask[ONENAND_CONNUM];//, FsaMask[ONENAND_CONNUM];//, DfsMask[ONENAND_CONNUM];
static OneNand_sCallBack OneNand_ISRCallBack;
OneNandT_oInterruptFlag 	OneNandT_oIntFlag; 
volatile u32 OneNand_DmaDone;
DMAC g_oONDDmac0;

#if (OND_TRANS_MODE == OND_LDM_INST)
extern void OneNandPageRead(u32 uBaseAddr, u32 uSrcAddr, u32 uDstAddr);
extern void OneNandPageWrite(u32 uBaseAddr, u32 uSrcAddr, u32 uDstAddr);
#endif

//////////
// Function Name : ONENAND_Init
// Function Description : This function initializes a certain OneNand Controller
// Input : 	Controller - OneNand Controller Port Number 
// Output : 	TRUE - Memory Device is reset
//			FALSE - Memory Device is not reset because of ERROR
// Version : v0.1
bool	ONENAND_Init(u32 Controller)
{
	u32 uBaseAddress;

	if(Controller == 0)
	{
		uBaseAddress = ONENAND0_BASE;
	}
	else if(Controller == 1)
	{
		uBaseAddress = ONENAND1_BASE;
	}
	else
	{
		return FALSE;
	}
	
	ONENAND_pBase[Controller] = (void *)uBaseAddress;

#if (ONENAND_VERSION == ONENAND_EVT0)		
	//Mem Port 0 Drive Strngth increase(OneNand Control Signal)
	GPIO_SetMem0DrvStrength(0x55000411);
	//GPIO_SetMem0DrvStrength(0xaa000822);
	//GPIO_SetMem0DrvStrength(0xffffffff);
#endif

	ONENAND_SetFlashClock(Controller, eDiv2_HCLKx2);
	ONENAND_SetAccClock(Controller);

	ONENAND_GetDevInformation(Controller);
	ONENAND_SetMemSpace(Controller);

	ONENAND_EnableAllInterrupt(Controller);
	ONENAND_DisableInterrupt(Controller,  eOND_RDYACT);

	ONENAND_EnableECCCorrection(Controller, ONENAND_WITH_CORRECT);
	ONENAND_EnableIOBE(Controller, 1);
	ONENAND_SetBurstLatency(Controller, eOND_LATENCY4);
	ONENAND_SetSyncMode(Controller, eOND_SYNC_BURST16);

	//ONENAND_EnableAllInterrupt(Controller);
	//ONENAND_DisableInterrupt(Controller,  eOND_RDYACT);

#if (OND_TRANS_MODE == OND_DMA)
	DMAC_InitCh(DMA0, DMA_ALL, &g_oONDDmac0);
	INTC_SetVectAddr(NUM_DMA0,  ONENAND_DmaISR);
	INTC_Enable(NUM_DMA0);
#endif

	return TRUE;
}


//////////
// Function Name : ONENAND_SetLLI
// Function Description : This function set the DMA LLI feature
// Input : 	None
// Output : 	None
// Version : v0.1
void ONENAND_SetLLI(u32 uSrcAddr, u32 uDstAddr)
{
	u32 *pLLI_Base;
	u32 i;

	pLLI_Base = (u32 *)ONENAND_LLI_BASE;

	for(i=0 ; i<127; i++)
	{
		*pLLI_Base++ = uSrcAddr;
		*pLLI_Base++ = uDstAddr + (i*0x10);
		*pLLI_Base++ = (ONENAND_LLI_BASE + ((i+1)*0x20));
		*pLLI_Base++ = 0x0C489000;
		*pLLI_Base++ = 0x4;
		pLLI_Base += 3;
	}

	*pLLI_Base++ = uSrcAddr;
	*pLLI_Base++ = uDstAddr + (i*0x10);
	*pLLI_Base++ = 0;
	*pLLI_Base++ = 0x8C489000;
	*pLLI_Base++ = 0x4;
}



void __irq ONENAND_DmaISR(void)
{
  	DMACH_ClearIntPending(&g_oONDDmac0);

//	UART_Printf ("DMA ISR %d\n", OneNand_DmaDone);
	OneNand_DmaDone = 1;
	INTC_ClearVectAddr();
}



//////////
// Function Name : ONENAND_Reset
// Function Description : Reset the OneNand Device 
// Input : 	Controller - OneNand Controller Port Number 
//			Reset - 	WARM_RESET		(0x01)
//					CORE_RESET		(0x02)
//					HOT_RESET		(0x03)
// Version : v0.1
void ONENAND_Reset(u32 Controller, u32 uReset)
{
	Outp32(&ONENAND(Controller)->rMemReset, uReset);
	
	//Wait Reset Complete
	while(Inp32(&ONENAND(Controller)->rMemReset));
}

//////////
// Function Name : ONENAND_SetISRHandler
// Function Description : Register Interrupt Handler 
// Input : 	Ond_Callback - Array with the Interrupt Handler function address
// Version : v0.1
void ONENAND_SetISRHandler(void *Ond_Callback)
{
	OneNand_ISRCallBack.ONENAND_ISR_Func = (ONENAND_ISR_Routine)Ond_Callback;
}

//////////
// Function Name : ONENAND_SetBurstLatency
// Function Description : Sets the burst read latency in cycles 
// Input : 	Controller - OneNand Controller Port Number 
//			eLatency - (OneNAND_eLATENCY)latency cycle
// Version : v0.1
void ONENAND_SetBurstLatency(u32 Controller, OneNAND_eLATENCY eLatency)
{
	u32 uBurstReadLatency;

	uBurstReadLatency = Inp32(&ONENAND(Controller)->rMemCfg);
	uBurstReadLatency &= ~(0x7<<12);

	uBurstReadLatency |= (eLatency<<12);
	
	Outp32(&ONENAND(Controller)->rMemCfg, uBurstReadLatency);

}


//////////
// Function Name : ONENAND_SetFlashClock
// Function Description : Sets the OneNand Internal Flash Clock
// Input : 	Controller - OneNand Controller Port Number 
// Version : v0.1
void ONENAND_SetFlashClock(u32 Controller, OneNAND_eFlashClock eFlashClock)
{
	u32 uClkDivider;
	
	uClkDivider = SYSC_GetDIV0();
	uClkDivider = (uClkDivider & ~(3<<16)) | (eFlashClock<<16);

	SYSC_SetDIV0_all(uClkDivider);
}




//////////
// Function Name : ONENAND_SetAccClock
// Function Description : Sets the number of cycles required to cover the access time of the Flash memory device
//					 ACCESS_CLK = 35ns/Clock period + 1
// Input : 	Controller - OneNand Controller Port Number 
// Version : v0.1
void ONENAND_SetAccClock(u32 Controller)
{
	u32 uClkDivider, uAccClock;

	uClkDivider = SYSC_GetDIV0();
	uClkDivider = (uClkDivider & (3<<16))>>16;
	
	OneNand_Inform[Controller].uFlashClock = g_HCLKx2/(uClkDivider+1);

	uAccClock = (35*(OneNand_Inform[Controller].uFlashClock/1000))/1000000 + 1;
	Outp32(&ONENAND(Controller)->rAccClock, uAccClock&0x7);
}



//////////
// Function Name : ONENAND_SyncMode
// Function Description : Set the OneNand Transfer Mode include burst length 
// Input : 	Controller - OneNand Controller Port Number 
//			uMode - 	Read&Write Transfer Mode
// Version : v0.1
void ONENAND_SetSyncMode(u32 Controller, OneNAND_eMODE eMode)
{
	u32 uSyncMode;
	//u32 uConfig;

	uSyncMode = Inp32(&ONENAND(Controller)->rMemCfg);
	uSyncMode &= ~((1<<15)|(0x7<<9)|(1<<1));
	
	switch (eMode)
	{
		case eOND_SYNC_CONT:
			uSyncMode|= (0x1<<15)|(0x0<<9)|(0x1<<1);
			Outp32(&ONENAND(Controller)->rBurstLength, 16);
			//Outp32(&ONENAND(Controller)->rBurstLength, 0);
			Outp32(&ONENAND(Controller)->rMemCfg, uSyncMode);		//sync, burst:incr
			break;

		case eOND_SYNC_BURST4:
			uSyncMode|= (0x1<<15)|(0x1<<9)|(0x1<<1);
			Outp32(&ONENAND(Controller)->rBurstLength, 4);
			Outp32(&ONENAND(Controller)->rMemCfg, uSyncMode);		//sync, burst:4
			break;

		case eOND_SYNC_BURST8:
			uSyncMode|= (0x1<<15)|(0x2<<9)|(0x1<<1);
			Outp32(&ONENAND(Controller)->rBurstLength, 8);
			Outp32(&ONENAND(Controller)->rMemCfg, uSyncMode);		//sync, burst:8
			break;

		case eOND_SYNC_BURST16:
			uSyncMode|= (0x1<<15)|(0x3<<9)|(0x1<<1); //|(1<<4);
			Outp32(&ONENAND(Controller)->rBurstLength, 16);
			Outp32(&ONENAND(Controller)->rMemCfg, uSyncMode);		//sync, burst:16
			break;

		case eOND_SYNC_BURST32:
			uSyncMode|= (0x1<<15)|(0x4<<9)|(0x1<<1);
			Outp32(&ONENAND(Controller)->rBurstLength, 16);
			Outp32(&ONENAND(Controller)->rMemCfg, uSyncMode);		//sync, burst:16
			break;

		case eOND_ASYNC:
		default:
			uSyncMode|= (0x0<<15)|(0x0<<9)|(0x0<<1);
			Outp32(&ONENAND(Controller)->rBurstLength, 0);
			Outp32(&ONENAND(Controller)->rMemCfg, uSyncMode);		//rm async, burst:4
			break;
	}

	//DelayfrTimer(milli, 100);
	//ONENAND_DirectRead(Controller, OND_SYSCONFIG, &uConfig);
	//UART_Printf("OND_SYSCONFIG : 0x%04x\n", uConfig);
}


//////////
// Function Name : ONENAND_SyncMode
// Function Description : Set the OneNand Transfer Mode include burst length 
// Input : 	Controller - OneNand Controller Port Number 
//			uMode - 	Read&Write Transfer Mode
// Version : v0.1
void ONENAND_SetSyncMode_1(u32 Controller, u32 uReadMode, u32 uWriteMode, u32 uBurst)
{
	u32 uSyncMode;

	uSyncMode = Inp32(&ONENAND(Controller)->rMemCfg);
	uSyncMode &= ~((1<<15)|(0x7<<9)|(1<<1));
	uSyncMode |= ((uReadMode<<15)|(uBurst<<9)|(uWriteMode<<1));

	if(uBurst == BURST4)
		Outp32(&ONENAND(Controller)->rBurstLength, 4);
	else if(uBurst == BURST8)
		Outp32(&ONENAND(Controller)->rBurstLength, 8);
	else		
		Outp32(&ONENAND(Controller)->rBurstLength, 16);
	
	Outp32(&ONENAND(Controller)->rMemCfg, uSyncMode);
}



//////////
// Function Name : ONENAND_EnableIOBE
// Function Description : Set the I/O Buffer enable for INT and RDY signals
// Input : 	Controller - OneNand Controller Port Number 
//			uEnable - IOBE Enable/Disable
// Version : v0.1
void ONENAND_EnableIOBE(u32 Controller, u32 uEnable)
{
	u32 uEnableIOBE;

	uEnableIOBE = Inp32(&ONENAND(Controller)->rMemCfg);

#if 0	
	uEnableIOBE &= ~(0x7<<5);
	uEnableIOBE |= (1<<7)|(1<<6)|(uEnable<<5);
	
	Outp32(&ONENAND(Controller)->rMemCfg, uEnableIOBE);
#else
	//rb1004 OneNand Sync write ......070425...EVT0
	if(!(uEnableIOBE & (1<<5)))
	{
		uEnableIOBE &= ~(0x7<<5);
		uEnableIOBE |= (1<<7)|(1<<6)|(uEnable<<5);
		
		Outp32(&ONENAND(Controller)->rMemCfg, uEnableIOBE);
	}
#endif	
}


//////////
// Function Name : ONENAND_EnableECCCorrection
// Function Description : Set the ECC Error Correction Operation
// Input : 	Controller - OneNand Controller Port Number 
//			uEnable -ONENAND_WITH_CORRECT :  ECC Error Correction enable
//					ONENAND_WITHOUT_CORRECT : ECC Error Correction disable
// Version : v0.1
void ONENAND_EnableECCCorrection(u32 Controller, u32 uEnable)
{
	u32 uEnableECC;

	uEnableECC = Inp32(&ONENAND(Controller)->rMemCfg);

#if 0
	if(uEnable == ONENAND_WITH_CORRECT)
		uEnableECC &= ~(0x1<<8);
	else if(uEnable == ONENAND_WITHOUT_CORRECT)
		uEnableECC |= (0x1<<8);
	
	Outp32(&ONENAND(Controller)->rMemCfg, uEnableECC);
#else
	//rb1004 OneNand Sync write ......070425...EVT0
	if(uEnable == ONENAND_WITH_CORRECT)
	{
		if((uEnableECC&(1<<8)))
		{

⌨️ 快捷键说明

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