📄 onenand.c
字号:
/**************************************************************************************
*
* 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 + -