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

📄 s3c2410nd.c

📁 一个韩国朋友写的用于S3C2410板子上的2410 nand flash的驱动文件
💻 C
字号:
/* * MTD NAND device driver for S3C2410 Development Board * based on smc.c * * This file is subject to the terms and conditions of the GNU General Public * License.  See the file COPYING in the main directory of this archive * for more details. *//* (林) eZEX俊辑 固瘤SDK俊辑 力傍登绰 smc_s3c2410.c甫 官帕栏肺 荐沥沁嚼聪促. *   www.ezex.co.kr <lsh3974@ezex.co.kr> *    * 函版等 何盒篮 酒贰客 鞍嚼聪促. * - MTD 2003-6-13老磊俊 嘎眠绢 窃荐 牢磐其捞胶 函版 * - 颇萍记 困摹 炼沥 * - 窃荐 捞抚 函版 * - H/W ECC detect, S/W 沥沥 扁瓷 瘤盔 (512/3) * - nand.c  *   nand_read_ecc()俊辑 ECC 八荤搬苞甫 倒妨林绰 何盒捞 512/6老锭父 贸府登绊 乐扁 锭巩俊 *   yaffs啊 沥惑利栏肺 牢侥登扁 困秦辑 oob_buf甫 512/3阑 贸府窍绰 何盒捞 眠啊 登菌嚼聪促. */#include <linux/slab.h>#include <linux/module.h>#include <linux/mtd/mtd.h>#include <linux/mtd/nand.h>#include <linux/mtd/compatmac.h>#include <linux/irq.h>#include <asm/io.h>#include <asm/hardware.h>#include <asm/sizes.h>#include <linux/compiler.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/sched.h>/* * MTD structure for S3C2410 Development Board */static struct mtd_info *s3c2410_mtd = NULL;#include <linux/mtd/partitions.h>/* nand 场何盒篮 bon 颇萍记 抛捞喉阑 困秦辑 巢败敌促. * 俺惯捞 场唱搁 场鳖瘤 犬厘矫懦巴. */static struct mtd_partition s3c2410_partitions[] = {	{		name:		"root", // 1M ~ 28M : 0x800page ~ 0xe000page		size:		6* SZ_1M, // 13M 0xd100page		offset:		 1*SZ_1M, // 1M 		//mask_flags:	MTD_WRITEABLE,  /* force read-only */	},	{		name: "user",		size: 10*SZ_1M,		offset : MTDPART_OFS_APPEND,	}};static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd) {    switch (cmd) {    case NAND_CTL_SETNCE:	NFCONF &= ~NFCONF_nFCE_HIGH; break;    case NAND_CTL_CLRNCE:	NFCONF |= NFCONF_nFCE_HIGH; break;    case NAND_CTL_SETCLE:	break;    case NAND_CTL_CLRCLE:	break;    case NAND_CTL_SETALE:	break;    case NAND_CTL_CLRALE:	break;    }}static u_char s3c2410_read_byte(struct mtd_info *mtd) {    return (u_char) NFDATA;}static void s3c2410_write_byte(struct mtd_info *mtd, u_char val) {    NFDATA = (u_char) val;}static void s3c2410_write_buf(struct mtd_info *mtd, const u_char *buf, int len){	int i;	for(i =0; i< len; i++) NFDATA = buf[i];}static void s3c2410_read_buf(struct mtd_info *mtd, u_char *buf, int len){	int i;	for(i=0; i< len; i++) buf[i] = NFDATA;}static int s3c2410_verify_buf(struct mtd_info *mtd, const u_char *buf, int len){	int i;	for(i=0; i<len; i++)		if(buf[i] != NFDATA) return -1;	return 0;	}static int s3c2410_dev_ready(struct mtd_info *mtd){	return (NFSTAT & 0x1);}static void s3c2410_command (struct mtd_info *mtd, unsigned command, int column, int page_addr){//	register struct nand_chip *this = mtd->priv;	/* Begin command latch cycle */	/*	 * Write out the command to the device.	 */	if (command == NAND_CMD_SEQIN) {		int readcmd;		if (column >= mtd->oobblock) {			/* OOB area */			column -= mtd->oobblock;			readcmd = NAND_CMD_READOOB;		} else if (column < 256) {			/* First 256 bytes --> READ0 */			readcmd = NAND_CMD_READ0;		} else {			column -= 256;			readcmd = NAND_CMD_READ1;		}		NFCMD = (__u8)readcmd;	//	this->write_byte(mtd, readcmd);	}	NFCMD = (__u8)command;	/* Set ALE and clear CLE to start address cycle */	if (column != -1 || page_addr != -1) {		/* Serially input address */		if (column != -1)			NFADDR = (__u8)column;		if (page_addr != -1) {			NFADDR = (__u8)(page_addr & 0xff);			NFADDR = (__u8)((page_addr >> 8) & 0xff);			/* One more address cycle for higher density devices */			if (mtd->size & 0x0c000000) 				NFADDR = (__u8)((page_addr >> 16) & 0x0f);		}		/* Latch in address */	}		/* 	 * program and erase have their own busy handlers 	 * status and sequential in needs no delay	*/	switch (command) {				case NAND_CMD_PAGEPROG:	case NAND_CMD_ERASE1:	case NAND_CMD_ERASE2:	case NAND_CMD_SEQIN:	case NAND_CMD_STATUS:		return;	default :		break;	}	/* wait until command is processed */	while (!(NFSTAT&0x1));}// 3/512 H/W// nand_correct_data(..)甫 荐沥窃.// static int s3c2410_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc){	__u8 a,b,c, d1, d2, d3, bit, i; 	// s3c2410篮 18bit Line Parity甫 荤侩窍扁 锭巩俊 醚 林家啊 9厚飘 鞘夸窃.	__u32 add; 		d1 = calc_ecc[0] ^ read_ecc[0];	d2 = calc_ecc[1] ^ read_ecc[1];	d3 = calc_ecc[2] ^ read_ecc[2];	if((d1 | d2 | d3) == 0) {		return 0;	} else {		a = (d1 ^ (d1 >> 1)) & 0x55;		b = (d2 ^ (d2 >> 1)) & 0x55;		c = (d3 ^ (d3 >> 1)) & 0x55;		// 菩府萍 俊矾 俺荐 犬牢.. 菩府萍啊 12俺 葛滴 促弗 版快父		// 坷幅甫 荐沥且 荐 乐促.		if( (a ==0x55) && (b ==0x55) && (c == 0x55)) {			// line parity [8]			add = (((__u32)d3 & 0x2) !=0) << 9;			a = 0x80;			c = 0x80;			// line parity [7:4]			for(i=0; i<4; i++) {				if(d2 & c) add |= a;				a >>= 1;				c >>= 2;			}			// line parity [3:0]			c = 0x80;			for(i=0; i<4; i++) {				if(d1 &	c) add |= a;				a >>= 1;				c >>= 2;			}			// column parity [2:0]			bit = 0;			b = 0x04;			c = 0x80;			for(i=0; i<3; i++) {				if(d3 & c) bit |= b;				c >>= 2;				b >>= 1;			}			b = 0x1;			a = dat[add];			a ^= ( b << bit);			dat[add] = a;						return 1;		}else {		// 菩府萍啊 茄 厚飘父 1老锭 ECC 俊矾捞促.			i = 0;			while(d1) {				if(d1 & 0x1) i++;				d1 >>= 1;			}			while(d2) {				if(d2 & 0x1) i++;				d2 >>=1;			}			while(d3) {				if(d3 & 0x1) i++;				d3 >>=1;			}			// ECC 俊矾捞骨肺 促矫 拌魂等 蔼栏肺 函版			if(i == 1) {				read_ecc[0] = calc_ecc[0];				read_ecc[1] = calc_ecc[1];				read_ecc[2] = calc_ecc[2];				return 2;			}			// 2bit 捞惑 俊矾啊 八免登绢 汗备且 荐 绝绰 版快 			return -1;		}	}	return -1;}static void s3c2410_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code){	__u32 ecc, i;	ecc = NFECC;	*(ecc_code) = ecc &0xff;	*(ecc_code+1) = (ecc & 0xff00) >> 8;	*(ecc_code+2) = (ecc & 0xff0000) >> 16;// 荤侩窍瘤 臼绰 ecc绰 0xff肺 盲况狄.. s3c2410_correct_ecc俊辑 荤侩窍瘤 臼扁 锭巩俊// 狼固绝阑 荐档 乐瘤父.. 趣矫唱 窍绰 付澜俊 持绢 涤聪促. 哗档 等促绰 犬脚捞 乐栏搁// 历俊霸档 埃窜茄 汲疙阑 焊郴林矫搁 皑荤窍摆嚼聪促.	// <lsh3974@ezex.co.kr>	for(i=3; i<6;i++) {		ecc_code[i] = 0xff;	}	return;}static void s3c2410_enable_hwecc(struct mtd_info *mtd, int mode){ 	NFCONF |= NFCONF_ECC_INIT; 	return;}/* * Main initialization routine */int __init s3c2410_nand_init (void){    struct nand_chip *this;    u_int16_t nfconf;    unsigned int  result=0;    /* Allocate memory for MTD device structure and private data */    s3c2410_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),			GFP_KERNEL);    if (!s3c2410_mtd) {      printk ("Unable to allocate S3C2410 NAND MTD device structure.\n");      return -ENOMEM;    }    /* Get pointer to private data */    this = (struct nand_chip *) (&s3c2410_mtd[1]);    /* Initialize structures */    memset((char *) s3c2410_mtd, 0, sizeof(struct mtd_info));    memset((char *) this, 0, sizeof(struct nand_chip));    /* Link the private data with the MTD structure */    s3c2410_mtd->priv = this;    /* set NAND Flash controller */    {      nfconf = NFCONF;      /* NAND Flash controller enable */      nfconf |= NFCONF_FCTRL_EN;      /* Set flash memory timing */      nfconf &= ~NFCONF_TWRPH1;   /* 0x0 */      nfconf |= NFCONF_TWRPH0_3;  /* 0x3 */      nfconf &= ~NFCONF_TACLS;    /* 0x0 */      NFCONF = nfconf;    }    /* Set address of NAND IO lines */	this->IO_ADDR_R = (unsigned long)ioremap(0x4e00000c, SZ_1K);	this->IO_ADDR_W = (unsigned long)ioremap(0x4e00000c, SZ_1K);	this->read_byte = s3c2410_read_byte;	this->write_byte = s3c2410_write_byte;	this->write_buf = s3c2410_write_buf;		this->read_buf = s3c2410_read_buf;	this->verify_buf = s3c2410_verify_buf;    this->hwcontrol = s3c2410_hwcontrol;	this->dev_ready = s3c2410_dev_ready;	this->cmdfunc = s3c2410_command;	this->calculate_ecc = s3c2410_calculate_ecc;	this->eccmode = NAND_ECC_HW3_512;	this->enable_hwecc = s3c2410_enable_hwecc;	this->correct_data = s3c2410_correct_data;	if(nand_scan(s3c2410_mtd, 1)) {		kfree( (void*)s3c2410_mtd);		return -ENXIO;	}  /* Allocate memory for internal data buffer */    this->data_buf = kmalloc(sizeof(u_char) * 			     (s3c2410_mtd->oobblock + s3c2410_mtd->oobsize), 			     GFP_KERNEL);    if (!this->data_buf) {      printk ("Unable to allocate NAND data buffer for S3C2410.\n");      this->data_buf = NULL;      return -ENOMEM;    }   result= add_mtd_partitions(s3c2410_mtd,s3c2410_partitions, 		       sizeof(s3c2410_partitions)/sizeof(s3c2410_partitions[0]));    printk("this is the result of add_mtd_partitions %d \n",result);    return 0;}module_init(s3c2410_nand_init);/* * Clean up routine */#ifdef MODULEstatic void __exit s3c2410_cleanup (void){    struct nand_chip *this = (struct nand_chip *) &s3c2410_mtd[1];	iounmap(this->IO_ADDR_W);	iounmap(this->IO_ADDR_R);	del_mtd_partitions(s3c2410_mtd);    s3c2410_mtd->size = 0;    if (this->data_buf != NULL) {      /* Free internal data buffer */      kfree (this->data_buf);      this->data_buf = NULL;    }    /* Free the MTD device structure */    kfree (s3c2410_mtd);}module_exit(s3c2410_cleanup);#endifMODULE_LICENSE("GPL");MODULE_AUTHOR("LSH <www.ezex.co.kr>");MODULE_DESCRIPTION("S3C2410 NAND Flash driver");

⌨️ 快捷键说明

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