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

📄 onenand_base.c

📁 u-boot 源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
}/** * onenand_update_bufferram - [GENERIC] Update BufferRAM information * @param mtd		MTD data structure * @param addr		address to update * @param valid		valid flag * * Update BufferRAM information */static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr,				    int valid){	struct onenand_chip *this = mtd->priv;	int block, page;	int i;	block = (int)(addr >> this->erase_shift);	page = (int)(addr >> this->page_shift);	page &= this->page_mask;	/* Invalidate BufferRAM */	for (i = 0; i < MAX_BUFFERRAM; i++) {		if (this->bufferram[i].block == block &&		    this->bufferram[i].page == page)			this->bufferram[i].valid = 0;	}	/* Update BufferRAM */	i = ONENAND_CURRENT_BUFFERRAM(this);	this->bufferram[i].block = block;	this->bufferram[i].page = page;	this->bufferram[i].valid = valid;	return 0;}/** * onenand_get_device - [GENERIC] Get chip for selected access * @param mtd		MTD device structure * @param new_state	the state which is requested * * Get the device and lock it for exclusive access */static void onenand_get_device(struct mtd_info *mtd, int new_state){	/* Do nothing */}/** * onenand_release_device - [GENERIC] release chip * @param mtd		MTD device structure * * Deselect, release chip lock and wake up anyone waiting on the device */static void onenand_release_device(struct mtd_info *mtd){	/* Do nothing */}/** * onenand_read_ecc - [MTD Interface] Read data with ECC * @param mtd		MTD device structure * @param from		offset to read from * @param len		number of bytes to read * @param retlen	pointer to variable to store the number of read bytes * @param buf		the databuffer to put data * @param oob_buf	filesystem supplied oob data buffer * @param oobsel	oob selection structure * * OneNAND read with ECC */static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,			    size_t * retlen, u_char * buf,			    u_char * oob_buf, struct nand_oobinfo *oobsel){	struct onenand_chip *this = mtd->priv;	int read = 0, column;	int thislen;	int ret = 0;	DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ecc: from = 0x%08x, 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,		      "onenand_read_ecc: Attempt read beyond end of device\n");		*retlen = 0;		return -EINVAL;	}	/* Grab the lock and see if the device is available */	onenand_get_device(mtd, FL_READING);	while (read < len) {		thislen = min_t(int, mtd->oobblock, len - read);		column = from & (mtd->oobblock - 1);		if (column + thislen > mtd->oobblock)			thislen = mtd->oobblock - column;		if (!onenand_check_bufferram(mtd, from)) {			this->command(mtd, ONENAND_CMD_READ, from,				      mtd->oobblock);			ret = this->wait(mtd, FL_READING);			/* First copy data and check return value for ECC handling */			onenand_update_bufferram(mtd, from, 1);		}		this->read_bufferram(mtd, ONENAND_DATARAM, buf, column,				     thislen);		read += thislen;		if (read == len)			break;		if (ret) {			DEBUG(MTD_DEBUG_LEVEL0,			      "onenand_read_ecc: read failed = %d\n", ret);			break;		}		from += thislen;		buf += thislen;	}	/* Deselect and wake up anyone waiting on the device */	onenand_release_device(mtd);	/*	 * Return success, if no ECC failures, else -EBADMSG	 * fs driver will take care of that, because	 * retlen == desired len and result == -EBADMSG	 */	*retlen = read;	return ret;}/** * onenand_read - [MTD Interface] MTD compability function for onenand_read_ecc * @param mtd		MTD device structure * @param from		offset to read from * @param len		number of bytes to read * @param retlen	pointer to variable to store the number of read bytes * @param buf		the databuffer to put data * * This function simply calls onenand_read_ecc with oob buffer and oobsel = NULL*/int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,		 size_t * retlen, u_char * buf){	return onenand_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);}/** * onenand_read_oob - [MTD Interface] OneNAND read out-of-band * @param mtd		MTD device structure * @param from		offset to read from * @param len		number of bytes to read * @param retlen	pointer to variable to store the number of read bytes * @param buf		the databuffer to put data * * OneNAND read out-of-band data from the spare area */int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,		     size_t * retlen, u_char * buf){	struct onenand_chip *this = mtd->priv;	int read = 0, thislen, column;	int ret = 0;	DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob: from = 0x%08x, len = %i\n",	      (unsigned int)from, (int)len);	/* Initialize return length value */	*retlen = 0;	/* Do not allow reads past end of device */	if (unlikely((from + len) > mtd->size)) {		DEBUG(MTD_DEBUG_LEVEL0,		      "onenand_read_oob: Attempt read beyond end of device\n");		return -EINVAL;	}	/* Grab the lock and see if the device is available */	onenand_get_device(mtd, FL_READING);	column = from & (mtd->oobsize - 1);	while (read < len) {		thislen = mtd->oobsize - column;		thislen = min_t(int, thislen, len);		this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);		onenand_update_bufferram(mtd, from, 0);		ret = this->wait(mtd, FL_READING);		/* First copy data and check return value for ECC handling */		this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column,				     thislen);		read += thislen;		if (read == len)			break;		if (ret) {			DEBUG(MTD_DEBUG_LEVEL0,			      "onenand_read_oob: read failed = %d\n", ret);			break;		}		buf += thislen;		/* Read more? */		if (read < len) {			/* Page size */			from += mtd->oobblock;			column = 0;		}	}	/* Deselect and wake up anyone waiting on the device */	onenand_release_device(mtd);	*retlen = read;	return ret;}#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE/** * onenand_verify_page - [GENERIC] verify the chip contents after a write * @param mtd		MTD device structure * @param buf		the databuffer to verify * @param block		block address * @param page		page address * * Check DataRAM area directly */static int onenand_verify_page(struct mtd_info *mtd, u_char * buf,			       loff_t addr, int block, int page){	struct onenand_chip *this = mtd->priv;	void __iomem *dataram0, *dataram1;	int ret = 0;	this->command(mtd, ONENAND_CMD_READ, addr, mtd->oobblock);	ret = this->wait(mtd, FL_READING);	if (ret)		return ret;	onenand_update_bufferram(mtd, addr, 1);	/* Check, if the two dataram areas are same */	dataram0 = this->base + ONENAND_DATARAM;	dataram1 = dataram0 + mtd->oobblock;	if (memcmp(dataram0, dataram1, mtd->oobblock))		return -EBADMSG;	return 0;}#else#define onenand_verify_page(...)	(0)#endif#define NOTALIGNED(x)	((x & (mtd->oobblock - 1)) != 0)/** * onenand_write_ecc - [MTD Interface] OneNAND write with ECC * @param mtd		MTD device structure * @param to		offset to write to * @param len		number of bytes to write * @param retlen	pointer to variable to store the number of written bytes * @param buf		the data to write * @param eccbuf	filesystem supplied oob data buffer * @param oobsel	oob selection structure * * OneNAND write with ECC */static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,			     size_t * retlen, const u_char * buf,			     u_char * eccbuf, struct nand_oobinfo *oobsel){	struct onenand_chip *this = mtd->priv;	int written = 0;	int ret = 0;	DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ecc: to = 0x%08x, len = %i\n",	      (unsigned int)to, (int)len);	/* Initialize retlen, in case of early exit */	*retlen = 0;	/* Do not allow writes past end of device */	if (unlikely((to + len) > mtd->size)) {		DEBUG(MTD_DEBUG_LEVEL0,		      "onenand_write_ecc: Attempt write to past end of device\n");		return -EINVAL;	}	/* Reject writes, which are not page aligned */	if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {		DEBUG(MTD_DEBUG_LEVEL0,		      "onenand_write_ecc: Attempt to write not page aligned data\n");		return -EINVAL;	}	/* Grab the lock and see if the device is available */	onenand_get_device(mtd, FL_WRITING);	/* Loop until all data write */	while (written < len) {		int thislen = min_t(int, mtd->oobblock, len - written);		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock);		this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen);		this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0,				      mtd->oobsize);		this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock);		onenand_update_bufferram(mtd, to, 1);		ret = this->wait(mtd, FL_WRITING);		if (ret) {			DEBUG(MTD_DEBUG_LEVEL0,			      "onenand_write_ecc: write filaed %d\n", ret);			break;		}		written += thislen;		/* Only check verify write turn on */		ret = onenand_verify_page(mtd, (u_char *) buf, to, block, page);		if (ret) {			DEBUG(MTD_DEBUG_LEVEL0,			      "onenand_write_ecc: verify failed %d\n", ret);			break;		}		if (written == len)			break;		to += thislen;		buf += thislen;	}	/* Deselect and wake up anyone waiting on the device */	onenand_release_device(mtd);	*retlen = written;	return ret;}/** * onenand_write - [MTD Interface] compability function for onenand_write_ecc * @param mtd		MTD device structure * @param to		offset to write to * @param len		number of bytes to write * @param retlen	pointer to variable to store the number of written bytes * @param buf		the data to write * * This function simply calls onenand_write_ecc * with oob buffer and oobsel = NULL */int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,		  size_t * retlen, const u_char * buf){	return onenand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL);}/** * onenand_write_oob - [MTD Interface] OneNAND write out-of-band * @param mtd		MTD device structure * @param to		offset to write to * @param len		number of bytes to write * @param retlen	pointer to variable to store the number of written bytes * @param buf		the data to write * * OneNAND write out-of-band */int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,		      size_t * retlen, const u_char * buf){	struct onenand_chip *this = mtd->priv;	int column, status;	int written = 0;	DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n",	      (unsigned int)to, (int)len);	/* Initialize retlen, in case of early exit */	*retlen = 0;	/* Do not allow writes past end of device */	if (unlikely((to + len) > mtd->size)) {		DEBUG(MTD_DEBUG_LEVEL0,		      "onenand_write_oob: Attempt write to past end of device\n");		return -EINVAL;	}	/* Grab the lock and see if the device is available */	onenand_get_device(mtd, FL_WRITING);	/* Loop until all data write */	while (written < len) {		int thislen = min_t(int, mtd->oobsize, len - written);		column = to & (mtd->oobsize - 1);		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize);		this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0,				      mtd->oobsize);		this->write_bufferram(mtd, ONENAND_SPARERAM, buf, column,				      thislen);		this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);		onenand_update_bufferram(mtd, to, 0);		status = this->wait(mtd, FL_WRITING);		if (status)			break;		written += thislen;		if (written == len)

⌨️ 快捷键说明

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