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

📄 nand_module.c

📁 为了满足每个项目终端的需求
💻 C
字号:
/* * nand_module.c * * Nand flash driver module for SAMSUNG S3C2410 * * Author: Wang Lihui * Date  : $Date: 2006/06/05 09:00:00 $ * * $Revision: 1.1.1.0 $ * * Based on s3c2410-ts.c * * Copyright: * (C) HeBei Far East Harris Communications Company Limited. * * History: * * 2006-6-5 Wang Lihui 	- Initial version * */#include <linux/module.h>#include <asm/arch/S3C2410.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/hardware.h>#include <asm/arch/hardware.h>#include <asm/arch/irqs.h>#include <asm/io.h>//#include "2410addr.h"#include "k9f2808u0c.h"#include "nand_module.h"//#define DEBUG_NAND_FLASH#define DEVICE_NAME			"nandflashdrv"#define NANDFLASH_MAJOR		230#define MAX_BUF_LEN		0x6 /* 6KB */int nandflashdevMajor = 0;#define NF_CMD(cmd)		{NFCMD=cmd;}#define NF_ADDR(addr)	{NFADDR=addr;}#define NF_nFCE_L()		{NFCONF&=~(1<<11);}#define NF_nFCE_H()		{NFCONF|=(1<<11);}#define NF_RSTECC()		{NFCONF|=(1<<12);}#define NF_RDDATA() 	(NFDATA)#define NF_WRDATA(data) {NFDATA=data;}#define NF_WAITRB()    {while(!(NFSTAT&(1<<0)));}//wait tWB and check F_RNB pin.#define ID_K9S1208V0M	0xec76#define ID_K9F2808U0C	0xec73#define NF_BLOCK_SIZE	0x4000#define NF_BLOCK_NUMBER 1024#if 1// HCLK=100Mhz#define TACLS		0//0  //1clk(0ns)#define TWRPH0		3//2  //3clk(25ns)#define TWRPH1		0//0  //1clk(10ns)  //TACLS+TWRPH0+TWRPH1>=50ns#else// HCLK=50Mhz#define TACLS		0  //1clk(0ns)#define TWRPH0		1  //2clk(25ns)#define TWRPH1		0  //1clk(10ns)#endif#ifdef BAD_CHECK#undef BAD_CHECK#endifstatic U8 seBuf[16]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};int NF_ReadPage(U32 block,U32 page,U8 *buffer){    int i;    register U8 * bufPt=buffer;    unsigned int blockPage;    U8 ecc0,ecc1,ecc2;    U8 se[16];    U8 ReadTmp;    //page=page&0x1f;    blockPage=(block<<5)+page;    NF_RSTECC();    // Initialize ECC    NF_nFCE_L();    NF_CMD(0x00);   // Read command    NF_ADDR(0);	    // Column = 0    NF_ADDR(blockPage&0xff);	    //    NF_ADDR((blockPage>>8)&0xff);   // Block & Page num.    NF_ADDR((blockPage>>16)&0xff);  //    for(i=0;i<10;i++); //wait tWB(100ns)    NF_WAITRB();    // Wait tR(max 12us)#if 1 //0    i=NF_PAGE_SIZE;    while(i--!=0)    {    	*bufPt++=NF_RDDATA();	// Read one page    }#elif 0    //DMA doens't work.    rSRCPND=BIT_DMA0;    rDISRC0=0x4e00000c; //NF_RDDATA()    rDISRCC0=(1<<0); //arc=AHB,src_addr=fix    rDIDST0=(unsigned)bufPt;    rDIDSTC0=(0<<0); //dst=AHB,dst_addr=inc;    rDCON0=(1<<31)|(1<<30)|(1<<29)|(1<<28)|(1<<27)|(0<<23)|(1<<22)|(0<<20)|(512/4);	   //Handshake,AHB,interrupt,(4-burst),whole,S/W,no_autoreload,byte,count=512;    rDMASKTRIG0=(1<<1)|(1<<0);    while(!(rSRCPND & BIT_DMA0));    rSRCPND=BIT_DMA0;#elif 0    __RdPage512(bufPt);#endif    ecc0=rNFECC0;    ecc1=rNFECC1;    ecc2=rNFECC2;    se[0]=NF_RDDATA();    se[1]=NF_RDDATA();    se[2]=NF_RDDATA();    ReadTmp = NF_RDDATA();    ReadTmp = NF_RDDATA();    se[5]=NF_RDDATA();    NF_nFCE_H();    if(ecc0==se[0] && ecc1==se[1] && ecc2==se[2] && se[5]==0xff)    {    	return 1;    }    else    {    	return 0;    }}void NF_WritePage(U32 block,U32 page,U8 *buffer){    int i;    U32 blockPage=(block<<5)+page;    U8 *bufPt=buffer;    NF_nFCE_L();    NF_CMD(0x0);    NF_CMD(0x80);		    // Write 1st command    NF_ADDR(0);			    // Column 0    NF_ADDR(blockPage&0xff);	    //    NF_ADDR((blockPage>>8)&0xff);   // Block & page num.    NF_ADDR((blockPage>>16)&0xff);  //    for(i=0;i<NF_PAGE_SIZE;i++)    {	  NF_WRDATA(*bufPt++);	// Write one page to NFM from buffer    }    NF_CMD(0x10);   // Write 2nd command    //Delay(1);	    //tWB = 100ns.    for(i=0;i<10;i++);    NF_WAITRB();    //wait tPROG 200~500us;    NF_CMD(0x70);   // Read status command	//Delay(1);	    //twhr=60ns    if (NF_RDDATA()&0x1) // Page write error    {    	NF_nFCE_H();	//return 0;    }    else    {    	NF_nFCE_H();		//return 1;    }}int NF_EraseBlock(U32 block){    int i;    U32 blockPage=(block<<5);#if 0/*BAD_CHECK*/    if(NF_IsBadBlock(block) && block!=0) //block #0 can't be bad block for NAND boot	return 0;#endif    NF_nFCE_L();    NF_CMD(0x60);   // Erase one block 1st command    NF_ADDR(blockPage&0xff);	    // Page number=0    NF_ADDR((blockPage>>8)&0xff);    NF_ADDR((blockPage>>16)&0xff);    NF_CMD(0xd0);   // Erase one blcok 2nd command    //wait tWB(100ns) cacel by FHC-JISX    for(i=0;i<10;i++);    NF_WAITRB();    // Wait tBERS max 3ms.    NF_CMD(0x70);   // Read status command    if (NF_RDDATA()&0x1) // Erase error    {    	NF_nFCE_H();	//NF_MarkBadBlock(block);//???cacel the option by FHC-JISX	return 0;    }    else    {    	NF_nFCE_H();        return 1;    }}int NF_IsBadBlock(U32 block){    int i;    unsigned int blockPage;    U8 data;    blockPage=(block<<5);	// For 2'nd cycle I/O[7:5]    NF_nFCE_L();    NF_CMD(0x50);		// Spare array read command    NF_ADDR(517&0xf);		// Read the mark of bad block in spare array(M addr=5)    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]   for(i=0;i<10;i++);	// wait tWB(100ns) //?????    NF_WAITRB();	// Wait tR(max 12us)    data=NF_RDDATA();    NF_nFCE_H();    if(data!=0xff)    {    	return 1;    }    else    {    	return 0;    }}void NF_Reset(void){    int i;    NF_nFCE_L();    NF_CMD(0xFF);	//reset command    for(i=0;i<10;i++);  //tWB = 100ns.    NF_WAITRB();      //wait 200~500us;shit    NF_nFCE_H();}void NF_Init(void){    NFCONF=0xf830;    //(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);    // 1  1    1     1,   1      xxx,  r xxx,   r xxx    // En 512B 4step ECCR nFCE=H tACLS   tWRPH0   tWRPH1    NF_Reset();}/*by FHC-JISX for NAND FLASH TEST*/int NF_ReadId(void){    int i, mfr,id;    /* Chip Enable */    NF_nFCE_L();    for(i=0; i<10; i++);    /* read nand flash ID CMD */    NF_CMD(0x90);   // Read ID command    /* Write Address */    NF_ADDR(0 & 0xff);    NF_ADDR((0 >> 9) & 0xff);    NF_ADDR((0 >> 17) & 0xff);    NF_ADDR((0 >> 25) & 0xff);    /* wait the idle state */    for(i=0; i<10; i++);    NF_WAITRB();	/* read the id data */	mfr = NF_RDDATA();	id = NF_RDDATA();    /* chip Disable */    NF_nFCE_H();    return 0;}int nandflash_read(struct file *filp, char *buffer, size_t count, loff_t *ppos){	/*	char local_buffer[MAX_BUF_LEN];	*/	char* local_buffer;	int nRead;	int block_index,page_index;#ifdef DEBUG_NAND_FLASH	printk("\nnandflash_read,count:0x%x,blockindex:0x%x", count, (int)*ppos);#endif	//bug...	copy_from_user(&block_index, (int *)&buffer[0],4);	copy_from_user(&page_index,  (int *)&buffer[4],4);	local_buffer = kmalloc(count,GFP_KERNEL);	if(local_buffer == NULL)	{		return 0;	}	for(page_index = 0, nRead = 0; page_index < NF_PAGE_NUMBER; page_index++)	{		NF_ReadPage(block_index, page_index, local_buffer + nRead);		nRead += NF_PAGE_SIZE;	}	copy_to_user(buffer+8, local_buffer, nRead);	return nRead;}int nandflash_write(struct file *filp, char *buffer, size_t count, loff_t *ppos){        char*  local_buffer;        int nWrite;		int i;        int block_index,page_index;#ifdef DEBUG_NAND_FLASH        //bug...        printk("nandflash_write,count:0x%x,blockindex:0x%x\n", count,*(int*)buffer);#endif        local_buffer = kmalloc(count+4,GFP_KERNEL);        if(local_buffer == NULL)        {                printk("\nnandflash_write,kmalloc err");                return 0;        }        copy_from_user(local_buffer, buffer, count+sizeof(long));        //bug...        //block_index = (int)buffer[0];        block_index = *(int*)buffer;      //  if( block_index < 0 || block_index > MAX_BLOCKS)      //  {      //          printk("nandflash_write,block index err:%x",block_index);      //          return 0;      //  }#ifdef DEBUG_NAND_FLASH        printk("\nDRIVER:\n");        for (i=sizeof(long);i<count;i++)        printk(" %x",local_buffer[i]);        printk("\n");        printk("Index : %d\n",block_index);#endif        nWrite = 0;        for(page_index = 0, nWrite = 0; page_index < NF_PAGE_NUMBER; page_index++)        {                NF_WritePage(block_index, page_index,local_buffer+nWrite+sizeof(long));                nWrite += NF_PAGE_SIZE;        }        kfree(local_buffer);        return nWrite;}/****************************** nandflash_eraseblock*******************************/static int nandflash_eraseblock(int blocknum){#ifdef DEBUG_NAND_FLASH	printk("\nnandflash_eraseblock,blockindex:0x%x", blocknum);#endif	return NF_EraseBlock(blocknum);}static int nandflash_poll(struct file *filp, struct poll_table_struct *wait){	return 0 ;}static int nandflash_open(struct inode *inode, struct file *filp){#ifdef DEBUG_NAND_FLASH	printk("\nnandflash_open");#endif	NFCONF=0xf830;	NF_Reset();	//GPFCON = 0x5555;	//GPFDAT = 0x00;	MOD_INC_USE_COUNT;	return 0;}static int nandflash_release(struct inode *inode, struct file *filp){	MOD_DEC_USE_COUNT;	return 0;}static int nandflash_ioctl( struct inode *inode, struct file *filp, unsigned int nCmd, long argument ){	int retval = 0;	int block_index;#ifdef DEBUG_NAND_FLASH	printk("\nnandflash_ioctl,cmd:0x%x,blockindex:0x%x", nCmd, (int)argument);#endif	block_index = argument;	switch( nCmd )	{		case CMD_NF_ERASE_BLOCK:			retval = nandflash_eraseblock(block_index);			break;		default:			retval = 1;			break;	}	return retval;}static struct file_operations nandflash_fops = {	owner:	 THIS_MODULE,	open:	 nandflash_open,	read:	 nandflash_read,	write:	 nandflash_write,	release: nandflash_release,	ioctl:   nandflash_ioctl,	poll:	 nandflash_poll,};static int __init nandflash_init(void){	int ret;	ret = register_chrdev(NANDFLASH_MAJOR, DEVICE_NAME, &nandflash_fops); //FHC-JISX	if (ret < 0)	{	  	printk(DEVICE_NAME ":can't get major number\n");	  	return ret;	}	nandflashdevMajor = ret;#ifdef DEBUG_FLASH	printk("\nnandflash_init,major:%x",ret);#endif	return 0;}static void __exit nandflash_exit(void){	unregister_chrdev(nandflashdevMajor, DEVICE_NAME);}module_init(nandflash_init);module_exit(nandflash_exit);

⌨️ 快捷键说明

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