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

📄 jz4730_nand.c

📁 jz4730 北京群正出品
💻 C
📖 第 1 页 / 共 5 页
字号:
 * * The function expects, that the device is already selected  */static int nand_check_wp (struct mtd_info *mtd){	struct nand_chip *this = mtd->priv;	/* Check the WP bit */	this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1);	return (this->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1; }/** * nand_block_checkbad - [GENERIC] Check if a block is marked bad * @mtd:	MTD device structure * @ofs:	offset from device start * @getchip:	0, if the chip is already selected * @allowbbt:	1, if its allowed to access the bbt area * * Check, if the block is bad. Either by reading the bad block table or * calling of the scan function. */static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt){	struct nand_chip *this = mtd->priv;		if (!this->bbt)		return this->block_bad(mtd, ofs, getchip);		/* Return info from the table */	return nand_isbad_bbt (mtd, ofs, allowbbt);}/*  * Wait for the ready pin, after a command * The timeout is catched later. */static void nand_wait_ready(struct mtd_info *mtd){	struct nand_chip *this = mtd->priv;	unsigned long	timeo = jiffies + 2;	/* wait until command is processed or timeout occures */	do {		if (this->dev_ready(mtd))			return;	} while (time_before(jiffies, timeo));	}/** * nand_command - [DEFAULT] Send command to NAND device * @mtd:	MTD device structure * @command:	the command to be sent * @column:	the column address for this command, -1 if none * @page_addr:	the page address for this command, -1 if none * * Send command to NAND device. This function is used for small page * devices (256/512 Bytes per page) */static void nand_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(mtd, NAND_CTL_SETCLE);	/*	 * 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;		}		this->write_byte(mtd, readcmd);	}	this->write_byte(mtd, command);	/* Set ALE and clear CLE to start address cycle */	this->hwcontrol(mtd, NAND_CTL_CLRCLE);	if (column != -1 || page_addr != -1) {		this->hwcontrol(mtd, 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_byte(mtd, column);		}		if (page_addr != -1) {			this->write_byte(mtd, (unsigned char) (page_addr & 0xff));			this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));			/* One more address cycle for devices > 32MiB */			if (this->chipsize > (32 << 20))				this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f));		}		/* Latch in address */		this->hwcontrol(mtd, NAND_CTL_CLRALE);	}		/* 	 * 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;	case NAND_CMD_RESET:		if (this->dev_ready)				break;		udelay(this->chip_delay);		this->hwcontrol(mtd, NAND_CTL_SETCLE);		this->write_byte(mtd, NAND_CMD_STATUS);		this->hwcontrol(mtd, NAND_CTL_CLRCLE);		while ( !(this->read_byte(mtd) & NAND_STATUS_READY));		return;	/* 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. */	ndelay (100);	nand_wait_ready(mtd);}/** * nand_command_lp - [DEFAULT] Send command to NAND large page device * @mtd:	MTD device structure * @command:	the command to be sent * @column:	the column address for this command, -1 if none * @page_addr:	the page address for this command, -1 if none * * Send command to NAND device. This is the version for the new large page devices * We dont have the seperate regions as we have in the small page devices. * We must emulate NAND_CMD_READOOB to keep the code compatible. * */static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, int page_addr){	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(mtd, NAND_CTL_SETCLE);	/* Write out the command to the device. */	this->write_byte(mtd, (command & 0xff));	/* End command latch cycle */	this->hwcontrol(mtd, NAND_CTL_CLRCLE);	if (column != -1 || page_addr != -1) {		this->hwcontrol(mtd, 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_byte(mtd, column & 0xff);			this->write_byte(mtd, column >> 8);		}			if (page_addr != -1) {			this->write_byte(mtd, (unsigned char) (page_addr & 0xff));			this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));			/* One more address cycle for devices > 128MiB */			if (this->chipsize > (128 << 20))				this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0xff));		}		/* Latch in address */		this->hwcontrol(mtd, 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(mtd, NAND_CTL_SETCLE);		this->write_byte(mtd, NAND_CMD_STATUS);		this->hwcontrol(mtd, NAND_CTL_CLRCLE);		while ( !(this->read_byte(mtd) & NAND_STATUS_READY));		return;	case NAND_CMD_READ0:		/* Begin command latch cycle */		this->hwcontrol(mtd, NAND_CTL_SETCLE);		/* Write out the start read command */		this->write_byte(mtd, NAND_CMD_READSTART);		/* End command latch cycle */		this->hwcontrol(mtd, 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. */	ndelay (100);	nand_wait_ready(mtd);}/** * nand_wait - [DEFAULT]  wait until the command is done * @mtd:	MTD device structure * @this:	NAND chip structure * @state:	state to select the max. timeout value * * Wait for command done. This applies to erase and program only * Erase can take up to 400ms and program up to 20ms according to  * general NAND and SmartMedia specs **/static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state){	unsigned long	timeo = jiffies;	int	status;		if (state == FL_ERASING)		 timeo += (HZ * 400) / 1000;	else		 timeo += (HZ * 20) / 1000;	/* Apply this short delay always to ensure that we do wait tWB in	 * any case on any machine. */	ndelay (100);	if ((state == FL_ERASING) && (this->options & NAND_IS_AND))		this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1);	else			this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1);	while (time_before(jiffies, timeo)) {				/* Check, if we were interrupted */		if (this->state != state)			return 0;		if (this->dev_ready) {			if (this->dev_ready(mtd))				break;			} else {			if (this->read_byte(mtd) & NAND_STATUS_READY)				break;		}		OSTimeDly(1);	}	status = (int) this->read_byte(mtd);	return status;}/** * nand_write_page - [GENERIC] write one page * @mtd:	MTD device structure * @this:	NAND chip structure * @page: 	startpage inside the chip, must be called with (page & this->pagemask) * @oob_buf:	out of band data buffer * @oobsel:	out of band selecttion structre * @cached:	1 = enable cached programming if supported by chip * * Nand_page_program function is used for write and writev ! * This function will always program a full page of data * If you call it with a non page aligned buffer, you're lost :) * * Cached programming is not supported yet. */static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, 	u_char *oob_buf,  struct nand_oobinfo *oobsel, int cached){	int 	i, status;	u_char	ecc_code[32];	int	eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;	int  	*oob_config = oobsel->eccpos;	int	datidx = 0, eccidx = 0, eccsteps = this->eccsteps;	int	eccbytes = 0;		/* FIXME: Enable cached programming */	cached = 0;		/* Send command to begin auto page programming */	this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page);	/* Write out complete page of data, take care of eccmode */	switch (eccmode) {	/* No ecc, write all */	case NAND_ECC_NONE:		TRACE (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");		this->write_buf(mtd, this->data_poi, mtd->oobblock);		break;			/* Software ecc 3/256, write all */	case NAND_ECC_SOFT:		for (; eccsteps; eccsteps--) {			this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code);			for (i = 0; i < 3; i++, eccidx++)				oob_buf[oob_config[eccidx]] = ecc_code[i];			datidx += this->eccsize;		}		this->write_buf(mtd, this->data_poi, mtd->oobblock);		break;	default:		eccbytes = this->eccbytes;		for (; eccsteps; eccsteps--) {			/* enable hardware ecc logic for write */			this->enable_hwecc(mtd, NAND_ECC_WRITE);			this->write_buf(mtd, &this->data_poi[datidx], this->eccsize);			this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code);			for (i = 0; i < eccbytes; i++, eccidx++)				oob_buf[oob_config[eccidx]] = ecc_code[i];			/* If the hardware ecc provides syndromes then			 * the ecc code must be written immidiately after			 * the data bytes (words) */			if (this->options & NAND_HWECC_SYNDROME)				this->write_buf(mtd, ecc_code, eccbytes);			datidx += this->eccsize;		}		break;	}											/* Write out OOB data */	if (this->options & NAND_HWECC_SYNDROME)		this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes);	else 		this->write_buf(mtd, oob_buf, mtd->oobsize);	/* Send command to actually program the data */	this->cmdfunc (mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1);	if (!cached) {		/* call wait ready function */		status = this->waitfunc (mtd, this, FL_WRITING);		/* See if operation failed and additional status checks are available */		if ((status & NAND_STATUS_FAIL) && (this->errstat)) {			status = this->errstat(mtd, this, FL_WRITING, status, page);		}		/* See if device thinks it succeeded */		if (status & NAND_STATUS_FAIL) {			DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);			return -EIO;		}	} else {		/* FIXME: Implement cached programming ! */		/* wait until cache is ready*/		// status = this->waitfunc (mtd, this, FL_CACHEDRPG);	}	return 0;	}#ifdef CONFIG_MTD_NAND_VERIFY_WRITE/** * nand_verify_pages - [GENERIC] verify the chip contents after a write * @mtd:	MTD device structure * @this:	NAND chip structure * @page: 	startpage inside the chip, must be called with (page & this->pagemask) * @numpages:	number of pages to verify * @oob_buf:	out of band data buffer * @oobsel:	out of band selecttion structre * @chipnr:	number of the current chip * @oobmode:	1 = full buffer verify, 0 = ecc only * * The NAND device assumes that it is always writing to a cleanly erased page. * Hence, it performs its internal write verification only on bits that  * transitioned from 1 to 0. The device does NOT verify the whole page on a * byte by byte basis. It is possible that the page was not completely erased  * or the page is becoming unusable due to wear. The read with ECC would catch  * the error later when the ECC page check fails, but we would rather catch  * it early in the page write stage. Better to write no data than invalid data. */static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, 	u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode){	int 	i, j, datidx = 0, oobofs = 0, res = -EIO;	int	eccsteps = this->eccsteps;	int	hweccbytes; 	u_char 	oobdata[64];	hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0;	/* Send command to read back the first page */	this->cmdfunc (mtd, NAND_CMD_READ0, 0, page);	for(;;) {		for (j = 0; j < eccsteps; j++) {			/* Loop through and verify the data */

⌨️ 快捷键说明

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