📄 k9s1208.c
字号:
/**************************************************************************************
*
* Project Name : S3C6410 Validation
*
* Copyright 2006 by Samsung Electronics, Inc.
* All rights reserved.
*
* Project Description :
* This software is only for validating functions of the S3C6410.
* Anybody can use this software without our permission.
*
*--------------------------------------------------------------------------------------
*
* File Name : K9s1208.c
*
* File Description : This file implements the functons for Nand Device Access.
*
* Author : Heemyung.noh
* Dept. : AP Development Team
* Created Date : 2007/02/02
* Version : 0.1
*
* History
* - Created(Heemyung.noh 2007/02/02)
*
**************************************************************************************/
#include "def.h"
#include "option.h"
#include "sfr6410.h"
#include "System.h"
#include "Nand.h"
u32 srcAddress;
u32 targetBlock; // Block number (0 ~ 4095)
u32 targetSize; // Total byte size
u32 downloadAddress;
u32 downloadProgramSize=0x0;
//*************************************************
//*************************************************
//** H/W dependent functions **
//*************************************************
//*************************************************
//The code is made for bi-endian mode
// block0: reserved for boot strap
// block1~4095: used for OS image
// badblock SE: xx xx xx xx xx 00 ....
// good block SE: ECC0 ECC1 ECC2 FF FF FF ....
#define NF_MECC_UnLock() {rNFCONT&=~(1<<7);}
#define NF_MECC_Lock() {rNFCONT|=(1<<7);}
#define NF_CMD(cmd) {rNFCMD=cmd;}
#define NF_ADDR(addr) {rNFADDR=addr;}
#define NF_nFCE_L() {rNFCONT&=~(1<<1);}
#define NF_nFCE_H() {rNFCONT|=(1<<1);}
//for debugging
//#define NF_nFCE_L() {rNFCONT&=~(1<<2);}
//#define NF_nFCE_H() {rNFCONT|=(1<<2);}
#define NF_RSTECC() {rNFCONT|=(1<<5|1<<4);}
#define NF_RDDATA() (rNFDATA)
#define NF_RDDATA8() ((*(volatile unsigned char*)0x70200010) )
#define NF_WRDATA(data) {rNFDATA=data;}
#define NF_WAITRB() {while(!(rNFSTAT&(1<<4)));}
//wait tWB and check F_RNB pin.
// RnB Signal
#define NF_CLEAR_RB() {rNFSTAT |= (1<<4);} // Have write '1' to clear this bit.
#define NF_DETECT_RB() {while(!(rNFSTAT&(1<<4)));}
#define ID_K9S1208V0M 0xec76
#define ID_K9K2G16U0M 0xecca
#define NF16_BAD_OFFSET (12)
// HCLK=100Mhz
//#define TACLS 0 // 1-clk(0ns)
//#define TWRPH0 6 // 3-clk(25ns)
//#define TWRPH1 0 // 1-clk(10ns) //TACLS+TWRPH0+TWRPH1>=50ns
// k9F1208U0B (HCLK 100MHz)
//#define TACLS 3 // 1-clk(0ns)
//#define TWRPH0 2 // 3-clk(25ns)
//#define TWRPH1 1 // 1-clk(10ns) //TACLS+TWRPH0+TWRPH1>=50ns
#define TACLS 7 // 1-clk(0ns)
#define TWRPH0 7 // 3-clk(25ns)
#define TWRPH1 7 // 1-clk(10ns) //TACLS+TWRPH0+TWRPH1>=50ns
#if (NAND_TYPE == MLC_8BIT)
int NF8_ReadPage(u32 block,u32 page,u8 *buffer)
{
int i;
unsigned int blockPage;
// u32 Mecc;
u8 *bufPt=buffer;
u32 uPageSize;
// u8 temp;
page=page&0x7f;
blockPage=(block<<7)+page;
uPageSize = 512; //512byte * 4 times
NF_RSTECC(); // Initialize ECC
// NF_MECC_UnLock();
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(0x00);
NF_ADDR(0);
NF_ADDR(0);
NF_ADDR(blockPage&0xff); //
NF_ADDR((blockPage>>8)&0xff); // Block & Page num.
NF_ADDR((blockPage>>16)&0xff); //
NF_CMD(0x30);
NF_DETECT_RB();
for(i=0;i<uPageSize;i++)
{
*bufPt++=NF_RDDATA8(); // Read one page
}
NF_CMD(0x05);
NF_ADDR((512)&0xFF);
NF_ADDR((512>>8)&0xFF);
NF_CMD(0xE0);
for(i=0;i<uPageSize;i++)
{
*bufPt++=NF_RDDATA8(); // Read one page
}
NF_CMD(0x05);
NF_ADDR((512*2)&0xFF);
NF_ADDR(((512*2)>>8)&0xFF);
NF_CMD(0xE0);
for(i=0;i<uPageSize;i++)
{
*bufPt++=NF_RDDATA8(); // Read one page
}
NF_CMD(0x05);
NF_ADDR((512*3)&0xFF);
NF_ADDR(((512*3)>>8)&0xFF);
NF_CMD(0xE0);
for(i=0;i<uPageSize;i++)
{
*bufPt++=NF_RDDATA8(); // Read one page
}
/*
Mecc = NF_RDDATA8();
Mecc |= NF_RDDATA8()<<8;
Mecc |= NF_RDDATA8()<<16;
Mecc |= NF_RDDATA8()<<24;
rNFMECCD0=((Mecc&0xff00)<<8)|(Mecc&0xff);
rNFMECCD1=((Mecc&0xff000000)>>8)|((Mecc&0xff0000)>>16);
*/
NF_nFCE_H();
/*
if ((rNFECCERR0&0x3) == 0x0)
{
return 1;
}
else
{
return 0;
}
*/
return 1;
}
#else
int NF8_ReadPage(u32 block,u32 page,u8 *buffer)
{
int i;
unsigned int blockPage;
u32 Mecc;
u8 *bufPt=buffer;
u32 uPageSize;
u8 temp;
#if (NAND_TYPE == NORMAL_8BIT)
page=page&0x1f;
blockPage=(block<<5)+page;
uPageSize = 512;
#elif (NAND_TYPE == ADVANCED_8BIT)
page=page&0x3f;
blockPage=(block<<6)+page;
uPageSize = 2048;
#endif
NF_RSTECC(); // Initialize ECC
NF_MECC_UnLock();
NF_nFCE_L();
NF_CLEAR_RB();
#if (NAND_TYPE == NORMAL_8BIT)
NF_CMD(0x00); // Read command
NF_ADDR(0); // Column = 0
#elif (NAND_TYPE == ADVANCED_8BIT)
NF_CMD(0x00);
NF_ADDR(0);
NF_ADDR(0);
#endif
NF_ADDR(blockPage&0xff); //
NF_ADDR((blockPage>>8)&0xff); // Block & Page num.
NF_ADDR((blockPage>>16)&0xff); //
#if (NAND_TYPE == ADVANCED_8BIT)
NF_CMD(0x30);
#endif
NF_DETECT_RB();
for(i=0;i<uPageSize;i++)
{
*bufPt++=NF_RDDATA8(); // Read one page
}
NF_MECC_Lock();
#if (NAND_TYPE == ADVANCED_8BIT)
temp = NF_RDDATA8();
#endif
Mecc = NF_RDDATA8();
Mecc |= NF_RDDATA8()<<8;
Mecc |= NF_RDDATA8()<<16;
Mecc |= NF_RDDATA8()<<24;
rNFMECCD0=((Mecc&0xff00)<<8)|(Mecc&0xff);
rNFMECCD1=((Mecc&0xff000000)>>8)|((Mecc&0xff0000)>>16);
NF_nFCE_H();
if ((rNFECCERR0&0x3) == 0x0)
{
return 1;
}
else
{
return 0;
}
}
#endif
void Nand_Reset(void)
{
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(0xFF); //reset command
NF_DETECT_RB();
NF_nFCE_H();
}
void NF8_Init(void)
{
#if (NAND_TYPE == NORMAL_8BIT)
rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(1<<2)|(0<<0);
rNFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
#elif (NAND_TYPE == ADVANCED_8BIT)
rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(1<<3)|(1<<2)|(1<<0);
rNFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
#elif (NAND_TYPE == MLC_8BIT)
rNFCONF = (1<<24)|(TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(1<<3)|(1<<2)|(0<<0);
rNFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
#endif
Nand_Reset();
}
int NF8_IsBadBlock(u32 block)
{
unsigned int blockPage;
u8 data;
#if (NAND_TYPE == NORMAL_8BIT)
blockPage=(block<<5);
#elif (NAND_TYPE == ADVANCED_8BIT)
blockPage=(block<<6);
#elif (NAND_TYPE == MLC_8BIT)
blockPage=(block<<7);
#endif
NF_nFCE_L();
NF_CLEAR_RB();
#if (NAND_TYPE == NORMAL_8BIT)
NF_CMD(0x50); // Spare array read command
NF_ADDR((512+5)&0xf); // Read the mark of bad block in spare array(M addr=5), A4-A7:Don't care
#elif (NAND_TYPE == ADVANCED_8BIT)
NF_CMD(0x00);
NF_ADDR((2048)&0xff);
NF_ADDR(((2048)>>8)&0xf);
#elif (NAND_TYPE == MLC_8BIT)
NF_CMD(0x00);
NF_ADDR((2048)&0xff);
NF_ADDR(((2048)>>8)&0xf);
#endif
NF_ADDR(blockPage&0xff); // The mark of bad block is in 0 page
NF_ADDR((blockPage>>8)&0xff); // For block number A[24:17]
NF_ADDR((blockPage>>16)&0xff); // For block number A[25]
#if (NAND_TYPE != NORMAL_8BIT)
NF_CMD(0x30);
#endif
NF_DETECT_RB(); // Wait tR(max 12us)
data=NF_RDDATA();
NF_CMD(0x00); // Define the starting address of the 1st half of the register
NF_nFCE_H();
if(data!=0xff)
return 0;
else
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -