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

📄 smc_core.c

📁 阳初s3c2410开发板的启动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * vivi/drivers/mtd/nand/smc_core.c:  * * Based on linux/drivers/mtd/nand/smc.c * * $Id: smc_core.c,v 1.3 2002/08/10 07:47:08 nandy Exp $ * * * 棱淬: *   恐 this->oobblock捞扼绊 沁阑鳖? thsi->oobblcok_ofs捞扼绊 窍搁 *   粱歹 疙犬窍瘤 臼阑鳖? */#include "config.h"#include "mtd/mtd.h"#include "mtd/nand.h"#include "mtd/nand_ids.h"#include "mtd/nand_ecc.h"#include "time.h"#include "printk.h"#include <types.h>#include <errno.h>#define CONFIG_MTD_NAND_VERIFY_WRITE/* * Macros for low-level register control */#if defined(CONFIG_ARCH_S3C2410)#define nand_select()	this->hwcontrol(NAND_CTL_SETNCE); \			this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); \			udelay(10);#elif defined(CONFIG_ARCH_S3C2440)#define NF_CLEAR_RB()	{NFSTAT |= NFSTAT_RnB;}#define NF_DETECT_RB()	{while(!(NFSTAT & NFSTAT_RnB));}#if 0#define nand_select()	\		do \		{\			this->hwcontrol(NAND_CTL_SETNCE); \			nand_command(mtd, NAND_CMD_RESET, -1, -1); \			NF_DETECT_RB();\			NF_CLEAR_RB();\		}\		while (0)#endif#define nand_select()	\		do \		{\			this->hwcontrol(NAND_CTL_SETNCE); \			nand_command(mtd, NAND_CMD_RESET, -1, -1); \		}\		while (0)#else#error must defined CONFIG_ARCH_S3C2410 or CONFIG_ARCH_S3C2440#endif#define nand_deselect()	this->hwcontrol(NAND_CTL_CLRNCE);static inline void sm_swap(u_char *x, u_char *y) {	u_char tmp;	tmp = *x;	*x = *y;	*y = tmp;}/* define if you'll be using < 2M SMC device */#undef USE_256BYTE_NAND_FLASH/* * Send command to NAND device */static voidnand_command(struct mtd_info *mtd, unsigned command, int column, int page_addr){	register struct nand_chip *this = mtd->priv;	/* Begin command latch cycle */	this->hwcontrol(NAND_CTL_SETCLE);	this->hwcontrol(NAND_CTL_DAT_OUT);	/*	 * Write out the command to the device.	 */	if (command != NAND_CMD_SEQIN)		this->write_cmd(command);	else {		if (mtd->oobblock == 256 && column >= 256) {			column -= 256;			this->write_cmd(NAND_CMD_RESET);			this->write_cmd(NAND_CMD_READOOB);			this->write_cmd(NAND_CMD_SEQIN);		} else if (mtd->oobblock == 512 && column >= 256) {			if (column < 512) {				column -= 256;				this->write_cmd(NAND_CMD_READ1);				this->write_cmd(NAND_CMD_SEQIN);			} else {				column -= 512;				this->write_cmd(NAND_CMD_READOOB);				this->write_cmd(NAND_CMD_SEQIN);			}		} else {			this->write_cmd(NAND_CMD_READ0);			this->write_cmd(NAND_CMD_SEQIN);		}	}	/* Set ALE and clear CLE to start address cycle */	this->hwcontrol(NAND_CTL_CLRCLE);	this->hwcontrol(NAND_CTL_SETALE);	/* Serially input address */	if (column != -1)		this->write_addr(column);	if (page_addr != -1) {		this->write_addr((u_char)(page_addr & 0xff));		this->write_addr((u_char)((page_addr >> 8) & 0xff));		/* One more address cycle for higher density devices */		if (mtd->size & 0x0c000000) {			this->write_addr((u_char)((page_addr >> 16) & 0xff));		}	}	/* Latch in address */	this->hwcontrol(NAND_CTL_CLRALE);		this->hwcontrol(NAND_CTL_DAT_IN);	/* Pause for 15us */	udelay(15); }/* * Send command to large page NAND device */static voidnand_command_lp(struct mtd_info *mtd, unsigned command, int column, int page_addr){#ifdef __OLD__    register struct nand_chip *this = mtd->priv;	/* Emulate NAND_CMD_READOOB */	if (command == NAND_CMD_READOOB) {		column += mtd->oobblock;		command = NAND_CMD_READ0;	}	/* Begin command latch cycle */	//this->hwcontrol(NAND_CTL_SETCLE);	/* Write out the command to the device. */	this->write_cmd(command & 0xff);	/* End command latch cycle */	//this->hwcontrol(NAND_CTL_CLRCLE);	//this->hwcontrol(NAND_CTL_DAT_OUT);	/*	 * Write out the command to the device.	 */	if (command != NAND_CMD_SEQIN)		this->write_cmd(command);	else {		if (mtd->oobblock == 256 && column >= 256) {			column -= 256;			this->write_cmd(NAND_CMD_RESET);			this->write_cmd(NAND_CMD_READOOB);			this->write_cmd(NAND_CMD_SEQIN);		} else if (mtd->oobblock == 512 && column >= 256) {			if (column < 512) {				column -= 256;				this->write_cmd(NAND_CMD_READ1);				this->write_cmd(NAND_CMD_SEQIN);			} else {				column -= 512;				this->write_cmd(NAND_CMD_READOOB);				this->write_cmd(NAND_CMD_SEQIN);			}		} else {			this->write_cmd(NAND_CMD_READ0);			this->write_cmd(NAND_CMD_SEQIN);		}	}	/* Set ALE and clear CLE to start address cycle */	this->hwcontrol(NAND_CTL_CLRCLE);	this->hwcontrol(NAND_CTL_SETALE);	/* Serially input address */	if (column != -1) {		this->write_addr((u_char)(column & 0xff));		/* NAND_CMD_READID need only one byte column addr */		if (command != NAND_CMD_READID)			this->write_addr((u_char)((column >> 8) & 0xff));	}	if (page_addr != -1) {		this->write_addr((u_char)(page_addr & 0xff));		this->write_addr((u_char)((page_addr >> 8) & 0xff));		/* One more address cycle for higher density devices */		if (mtd->size & 0x30000000) {			this->write_addr((u_char)((page_addr >> 16) & 0xff));		}	}	/* Latch in address */	this->hwcontrol(NAND_CTL_CLRALE);		this->hwcontrol(NAND_CTL_DAT_IN);	/* Pause for 15us */	udelay(15);#endif					register struct nand_chip *this = mtd->priv;	/* Emulate NAND_CMD_READOOB */	if (command == NAND_CMD_READOOB) {		column += mtd->oobblock;		command = NAND_CMD_READ0;	}				/* Begin command latch cycle */	this->hwcontrol(NAND_CTL_SETCLE);	/* Write out the command to the device. */	this->write_cmd(command & 0xff);	/* End command latch cycle */	this->hwcontrol(NAND_CTL_CLRCLE);	if (column != -1 || page_addr != -1) {		this->hwcontrol(NAND_CTL_SETALE);		/* Serially input address */		if (column != -1) {			/* Adjust columns for 16 bit buswidth */			//if (this->options & NAND_BUSWIDTH_16)			//	column >>= 1;			this->write_addr(column & 0xff);			this->write_addr(column >> 8);		}			if (page_addr != -1) {			this->write_addr((unsigned char) (page_addr & 0xff));			this->write_addr((unsigned char) ((page_addr >> 8) & 0xff));			/* One more address cycle for devices > 128MiB */			//if (this->chipsize > (128 << 20))			if (mtd->size > (128 << 20))				this->write_addr((unsigned char) ((page_addr >> 16) & 0xff));		}		/* Latch in address */		this->hwcontrol(NAND_CTL_CLRALE);	}		/* 	 * program and erase have their own busy handlers 	 * status, sequential in, and deplete1 need no delay	 */	switch (command) {				case NAND_CMD_CACHEDPROG:	case NAND_CMD_PAGEPROG:	case NAND_CMD_ERASE1:	case NAND_CMD_ERASE2:	case NAND_CMD_SEQIN:	case NAND_CMD_STATUS:	//case NAND_CMD_DEPLETE1:		return;	/* 	 * read error status commands require only a short delay	 */	//case NAND_CMD_STATUS_ERROR:	//case NAND_CMD_STATUS_ERROR0:	//case NAND_CMD_STATUS_ERROR1:	//case NAND_CMD_STATUS_ERROR2:	//case NAND_CMD_STATUS_ERROR3:	//	udelay(this->chip_delay);	//	return;	case NAND_CMD_RESET:		//if (this->dev_ready)			//	break;		//udelay(this->chip_delay);		this->hwcontrol(NAND_CTL_SETCLE);		this->write_cmd(NAND_CMD_STATUS);		this->hwcontrol(NAND_CTL_CLRCLE);		while ( !(this->read_data() & NAND_STATUS_READY));		return;	case NAND_CMD_READ0:		/* Begin command latch cycle */		this->hwcontrol(NAND_CTL_SETCLE);		/* Write out the start read command */		this->write_cmd(NAND_CMD_READSTART);		/* End command latch cycle */		this->hwcontrol(NAND_CTL_CLRCLE);		/* Fall through into ready check */			/* This applies to read commands */		default:		/* 		 * If we don't have access to the busy pin, we apply the given		 * command delay		*/		//if (!this->dev_ready) {		//	udelay (this->chip_delay);		//	return;		//}		}	/* Apply this short delay always to ensure that we do wait tWB in	 * any case on any machine. */	udelay(15);}/* * NAND read */static intnand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf){	int j, col, page, state;	struct nand_chip *this = mtd->priv;	DEBUG(MTD_DEBUG_LEVEL3,		__FUNCTION__"(): from = 0x%08lx, len = %i\n",		(unsigned int)from, (int)len);	/* Do not allow reads past end of device */	if ((from + len) > mtd->size) {		DEBUG(MTD_DEBUG_LEVEL0,			__FUNCTION__"(): Attempt read beyond end of device\n");		*retlen = 0;		return -EINVAL;	}	/* First we calculate the starting page */	page = from >> this->page_shift;	/* Get raw starting column */	col = from & (mtd->oobblock - 1);#if 0	/* State machine for devices having pages larger than 256 bytes */	state = (col < mtd->eccsize) ? 0 : 1;	/* Calculate column address within ECC block context */	col = (col >= mtd->eccsize) ? (col - mtd->eccsize) : col;	/* Initialize return value */	*retlen = 0;	/* Select the NAND device */	nand_select();	/* Loop until all data read */	while (*retlen < len) {		/* Send the read command */		if (!state)			this->cmdfunc(mtd, NAND_CMD_READ0, col, page);		else			this->cmdfunc(mtd, NAND_CMD_READ1, col, page);		this->wait_for_ready();		/* Read the data directly into the return buffer */		if ((*retlen + (mtd->eccsize - col)) >= len) {			while (*retlen < len)				buf[(*retlen)++] = this->read_data();			/* We're done */			continue;		} else {			for (j = col; j < mtd->eccsize; j++)				buf[(*retlen)++] = this->read_data();		}		/*		 * If the amount of data to be read is greater than		 * (256 - col), then all subsequent reads will take		 * place on page or half-page (in the case of 512 byte		 * page devices) aligned boundaries and the column		 * address will be zero. Setting the column address to		 * zero after the first read allows us to simplify		 * the reading of data and the if/else statements above.		 */		if (col)			col = 0x00;		/* Increment page address */		if ((mtd->oobblock == 256) || state)			page++;		/* Toggle state machine */		if (mtd->oobblock == 512)			state = state ? 0 : 1;	}#else	/* State machine for devices having pages larger than 256 bytes */	state = (col < mtd->eccsize) ? 0 : 1;	/* Calculate column address within ECC block context */	col = (col >= mtd->eccsize) ? (col - mtd->eccsize) : col;	/* Initialize return value */	*retlen = 0;	/* Select the NAND device */	nand_select();	/* Loop until all data read */	while (*retlen < len) {		/* Send the read command */		//if (!state)			this->cmdfunc(mtd, NAND_CMD_READ0, col, page);		//else			//this->cmdfunc(mtd, NAND_CMD_READ1, col, page);		this->wait_for_ready();		/* Read the data directly into the return buffer */		if ((*retlen + (mtd->oobblock - col)) >= len) {			while (*retlen < len)				buf[(*retlen)++] = this->read_data();			/* We're done */			continue;		} else {			for (j = col; j < mtd->oobblock; j++)				buf[(*retlen)++] = this->read_data();		}		/*		 * If the amount of data to be read is greater than		 * (256 - col), then all subsequent reads will take		 * place on page or half-page (in the case of 512 byte		 * page devices) aligned boundaries and the column		 * address will be zero. Setting the column address to		 * zero after the first read allows us to simplify		 * the reading of data and the if/else statements above.		 */		if (col)			col = 0x00;		/* Increment page address */		//if ((mtd->oobblock == 256) || state)			page++;		/* Toggle state machine */		//if (mtd->oobblock == 512)		//	state = state ? 0 : 1;	}#endif	/* De-select the NAND device */	nand_deselect();	/* Return happy */	return 0;	}/* * if mtd->oobblock == 512 */inline intsmc_read_ecc_512(struct mtd_info *mtd, u_char *ecc_code){	struct nand_chip *this = mtd->priv;	u_char ecc_calc[3];	int j, ret;

⌨️ 快捷键说明

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