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

📄 jz4730_nand.c

📁 jz4730 北京群正出品
💻 C
📖 第 1 页 / 共 5 页
字号:
/*************************************************************************** ** NAND Flash Driver for Jz4730. ** ** This file was derived from CELinux. The header files should also be ** referred to CELinux. ** ***************************************************************************/#include "cdefs.h"#include "types.h"#include "nand.h"#include "bitops.h"#include "debug.h"#include <stdlib.h>#include <string.h>#include "jiffies.h"#include "byteorder.h"#include "delay.h"#include "errno.h"#include "ucos_ii.h"#include "task_prio.h"#ifdef CONFIG_MTD_PARTITIONS#	include "mtd_partition.h"#endif#include "memzero.h"#include "regs.h"//-------------------------------------------------------------------////-------------------- nand_base.c routines ------------------------////-------------------------------------------------------------------///* Define default oob placement schemes for large and small page devices */static struct nand_oobinfo nand_oob_8 = {	.useecc = MTD_NANDECC_AUTOPLACE,	.eccbytes = 3,	.eccpos = {0, 1, 2},	.oobfree = { {3, 2}, {6, 2} }};static struct nand_oobinfo nand_oob_16 = {	.useecc = MTD_NANDECC_AUTOPLACE,	.eccbytes = 6,	.eccpos = {0, 1, 2, 3, 6, 7},	.oobfree = { {8, 8} }};static struct nand_oobinfo nand_oob_64 = {	.useecc = MTD_NANDECC_AUTOPLACE,	.eccbytes = 24,	.eccpos = {		40, 41, 42, 43, 44, 45, 46, 47, 		48, 49, 50, 51, 52, 53, 54, 55, 		56, 57, 58, 59, 60, 61, 62, 63},	.oobfree = { {2, 38} }};/* This is used for padding purposes in nand_write_oob */static u_char ffchars[] = {	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,};/* * NAND low-level MTD interface functions */static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len);static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,			  size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf);static int nand_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);static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char *buf);static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs,			unsigned long count, loff_t to, size_t * retlen);static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs,			unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);static int nand_erase (struct mtd_info *mtd, struct erase_info *instr);static void nand_sync (struct mtd_info *mtd);/* Some internal functions */static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf,		struct nand_oobinfo *oobsel, int mode);#ifdef CONFIG_MTD_NAND_VERIFY_WRITEstatic 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);#else#define nand_verify_pages(...) (0)#endif/** * nand_get_device - [GENERIC] Get chip for selected access * @this:	the nand chip descriptor * @mtd:	MTD device structure * @new_state:	the state which is requested  * * Get the device and lock it for exclusive access */static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state){	u8 err;	for (;;)	{		if (this->state == FL_READY)		{			this->state = new_state;			return 0;		}		if (new_state == FL_PM_SUSPENDED)		{			return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;		}		OSMutexPend(this->mutex, 0, &err);	}}/** * nand_release_device - [GENERIC] release chip * @mtd:	MTD device structure *  * Deselect, release chip lock and wake up anyone waiting on the device  */static void nand_release_device (struct mtd_info *mtd){	struct nand_chip* this = mtd->priv;	u32 psr;	bool flag;	/* De-select the NAND device */	nand_select_chip(mtd, -1);	local_irq_save(psr);	flag = (this->mutex->OSEventCnt & 0xffU) != 0xffU &&	       (this->mutex->OSEventCnt & 0xffU) == OSPrioCur;	local_irq_restore(psr);	/* Release the chip */	this->state = FL_READY;	if (flag)		OSMutexPost(this->mutex);}/** * nand_read_byte - [DEFAULT] read one byte from the chip * @mtd:	MTD device structure * * Default read function for 8bit buswith */static u_char nand_read_byte(struct mtd_info *mtd){	struct nand_chip *this = mtd->priv;	return readb(this->IO_ADDR_R);}/** * nand_write_byte - [DEFAULT] write one byte to the chip * @mtd:	MTD device structure * @byte:	pointer to data byte to write * * Default write function for 8it buswith */static void nand_write_byte(struct mtd_info *mtd, u_char byte){	struct nand_chip *this = mtd->priv;	writeb(byte, this->IO_ADDR_W);}/** * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip * @mtd:	MTD device structure * * Default read function for 16bit buswith with  * endianess conversion */static u_char nand_read_byte16(struct mtd_info *mtd){	struct nand_chip *this = mtd->priv;	return (u_char) readw(this->IO_ADDR_R);}/** * nand_write_byte16 - [DEFAULT] write one byte endianess aware to the chip * @mtd:	MTD device structure * @byte:	pointer to data byte to write * * Default write function for 16bit buswith with * endianess conversion */static void nand_write_byte16(struct mtd_info *mtd, u_char byte){	struct nand_chip *this = mtd->priv;	writew((u16) byte, this->IO_ADDR_W);}/** * nand_read_word - [DEFAULT] read one word from the chip * @mtd:	MTD device structure * * Default read function for 16bit buswith without  * endianess conversion */static u16 nand_read_word(struct mtd_info *mtd){	struct nand_chip *this = mtd->priv;	return readw(this->IO_ADDR_R);}/** * nand_write_word - [DEFAULT] write one word to the chip * @mtd:	MTD device structure * @word:	data word to write * * Default write function for 16bit buswith without  * endianess conversion */static void nand_write_word(struct mtd_info *mtd, u16 word){	struct nand_chip *this = mtd->priv;	writew(word, this->IO_ADDR_W);}/** * nand_select_chip - [DEFAULT] control CE line * @mtd:	MTD device structure * @chip:	chipnumber to select, -1 for deselect * * Default select function for 1 chip devices. */static void nand_select_chip(struct mtd_info *mtd, int chip){	struct nand_chip *this = mtd->priv;	switch(chip) {	case -1:		this->hwcontrol(mtd, NAND_CTL_CLRNCE);			break;	case 0:		this->hwcontrol(mtd, NAND_CTL_SETNCE);		break;	default:		BUG();	}}/** * nand_write_buf - [DEFAULT] write buffer to chip * @mtd:	MTD device structure * @buf:	data buffer * @len:	number of bytes to write * * Default write function for 8bit buswith */static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len){	int i;	struct nand_chip *this = mtd->priv;	for (i=0; i<len; i++)		writeb(buf[i], this->IO_ADDR_W);}/** * nand_read_buf - [DEFAULT] read chip data into buffer  * @mtd:	MTD device structure * @buf:	buffer to store date * @len:	number of bytes to read * * Default read function for 8bit buswith */static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len){	int i;	struct nand_chip *this = mtd->priv;	for (i=0; i<len; i++)		buf[i] = readb(this->IO_ADDR_R);}/** * nand_verify_buf - [DEFAULT] Verify chip data against buffer  * @mtd:	MTD device structure * @buf:	buffer containing the data to compare * @len:	number of bytes to compare * * Default verify function for 8bit buswith */static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len){	int i;	struct nand_chip *this = mtd->priv;	for (i=0; i<len; i++)		if (buf[i] != readb(this->IO_ADDR_R))			return -EFAULT;	return 0;}/** * nand_write_buf16 - [DEFAULT] write buffer to chip * @mtd:	MTD device structure * @buf:	data buffer * @len:	number of bytes to write * * Default write function for 16bit buswith */static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len){	int i;	struct nand_chip *this = mtd->priv;	u16 *p = (u16 *) buf;	len >>= 1;		for (i=0; i<len; i++)		writew(p[i], this->IO_ADDR_W);		}/** * nand_read_buf16 - [DEFAULT] read chip data into buffer  * @mtd:	MTD device structure * @buf:	buffer to store date * @len:	number of bytes to read * * Default read function for 16bit buswith */static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len){	int i;	struct nand_chip *this = mtd->priv;	u16 *p = (u16 *) buf;	len >>= 1;	for (i=0; i<len; i++)		p[i] = readw(this->IO_ADDR_R);}/** * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer  * @mtd:	MTD device structure * @buf:	buffer containing the data to compare * @len:	number of bytes to compare * * Default verify function for 16bit buswith */static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len){	int i;	struct nand_chip *this = mtd->priv;	u16 *p = (u16 *) buf;	len >>= 1;	for (i=0; i<len; i++)		if (p[i] != readw(this->IO_ADDR_R))			return -EFAULT;	return 0;}/** * nand_block_bad - [DEFAULT] Read bad block marker from the chip * @mtd:	MTD device structure * @ofs:	offset from device start * @getchip:	0, if the chip is already selected * * Check, if the block is bad.  */static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip){	int page, chipnr, res = 0;	struct nand_chip *this = mtd->priv;	u16 bad;	if (getchip) {		page = (int)(ofs >> this->page_shift);		chipnr = (int)(ofs >> this->chip_shift);		/* Grab the lock and see if the device is available */		nand_get_device (this, mtd, FL_READING);		/* Select the NAND device */		this->select_chip(mtd, chipnr);	} else 		page = (int) ofs;		if (this->options & NAND_BUSWIDTH_16) {		this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask);		bad = cpu_to_le16(this->read_word(mtd));		if (this->badblockpos & 0x1)			bad >>= 1;		if ((bad & 0xFF) != 0xff)			res = 1;	} else {		this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page & this->pagemask);		if (this->read_byte(mtd) != 0xff)			res = 1;	}			if (getchip) {		/* Deselect and wake up anyone waiting on the device */		nand_release_device(mtd);	}			return res;}/** * nand_default_block_markbad - [DEFAULT] mark a block bad * @mtd:	MTD device structure * @ofs:	offset from device start * * This is the default implementation, which can be overridden by * a hardware specific driver.*/static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs){	struct nand_chip *this = mtd->priv;	u_char buf[2] = {0, 0};	size_t	retlen;	int block;		/* Get block number */	block = ((int) ofs) >> this->bbt_erase_shift;	if (this->bbt)		this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);	/* Do we have a flash based bad block table ? */	if (this->options & NAND_USE_FLASH_BBT)		return nand_update_bbt (mtd, ofs);			/* We write two bytes, so we dont have to mess with 16 bit access */	ofs += mtd->oobsize + (this->badblockpos & ~0x01);	return nand_write_oob (mtd, ofs , 2, &retlen, buf);}/**  * nand_check_wp - [GENERIC] check if the chip is write protected * @mtd:	MTD device structure * Check, if the device is write protected 

⌨️ 快捷键说明

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