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

📄 diskonchip.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*  * drivers/mtd/nand/diskonchip.c * * (C) 2003 Red Hat, Inc. * (C) 2004 Dan Brown <dan_brown@ieee.org> * (C) 2004 Kalev Lember <kalev@smartlink.ee> * * Author: David Woodhouse <dwmw2@infradead.org> * Additional Diskonchip 2000 and Millennium support by Dan Brown <dan_brown@ieee.org> * Diskonchip Millennium Plus support by Kalev Lember <kalev@smartlink.ee> * * Interface to generic NAND code for M-Systems DiskOnChip devices * * $Id: diskonchip.c,v 1.34 2004/08/09 19:41:12 dbrown Exp $ */#include <linux/kernel.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/delay.h>#include <asm/io.h>#include <linux/mtd/mtd.h>#include <linux/mtd/nand.h>#include <linux/mtd/doc2000.h>#include <linux/mtd/compatmac.h>#include <linux/mtd/partitions.h>#include <linux/mtd/inftl.h>/* Where to look for the devices? */#ifndef CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS#define CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS 0#endifstatic unsigned long __initdata doc_locations[] = {#if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)#ifdef CONFIG_MTD_DISKONCHIP_PROBE_HIGH	0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, 	0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,	0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, 	0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, 	0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,#else /*  CONFIG_MTD_DOCPROBE_HIGH */	0xc8000, 0xca000, 0xcc000, 0xce000, 	0xd0000, 0xd2000, 0xd4000, 0xd6000,	0xd8000, 0xda000, 0xdc000, 0xde000, 	0xe0000, 0xe2000, 0xe4000, 0xe6000, 	0xe8000, 0xea000, 0xec000, 0xee000,#endif /*  CONFIG_MTD_DOCPROBE_HIGH */#elif defined(__PPC__)	0xe4000000,#elif defined(CONFIG_MOMENCO_OCELOT)	0x2f000000,        0xff000000,#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)        0xff000000,##else#warning Unknown architecture for DiskOnChip. No default probe locations defined#endif	0xffffffff };static struct mtd_info *doclist = NULL;struct doc_priv {	unsigned long virtadr;	unsigned long physadr;	u_char ChipID;	u_char CDSNControl;	int chips_per_floor; /* The number of chips detected on each floor */	int curfloor;	int curchip;	int mh0_page;	int mh1_page;	struct mtd_info *nextdoc;};/* Max number of eraseblocks to scan (from start of device) for the (I)NFTL   MediaHeader.  The spec says to just keep going, I think, but that's just   silly. */#define MAX_MEDIAHEADER_SCAN 8/* This is the syndrome computed by the HW ecc generator upon reading an empty   page, one with all 0xff for data and stored ecc code. */static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a };/* This is the ecc value computed by the HW ecc generator upon writing an empty   page, one with all 0xff for data. */static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 };#define INFTL_BBT_RESERVED_BLOCKS 4#define DoC_is_MillenniumPlus(doc) ((doc)->ChipID == DOC_ChipID_DocMilPlus16 || (doc)->ChipID == DOC_ChipID_DocMilPlus32)#define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)#define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd);static void doc200x_select_chip(struct mtd_info *mtd, int chip);static int debug=0;MODULE_PARM(debug, "i");static int try_dword=1;MODULE_PARM(try_dword, "i");static int no_ecc_failures=0;MODULE_PARM(no_ecc_failures, "i");static int no_autopart=0;MODULE_PARM(no_autopart, "i");#ifdef MTD_NAND_DISKONCHIP_BBTWRITEstatic int inftl_bbt_write=1;#elsestatic int inftl_bbt_write=0;#endifMODULE_PARM(inftl_bbt_write, "i");static unsigned long doc_config_location = CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS;MODULE_PARM(doc_config_location, "l");MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip");static void DoC_Delay(struct doc_priv *doc, unsigned short cycles){	volatile char dummy;	int i;		for (i = 0; i < cycles; i++) {		if (DoC_is_Millennium(doc))			dummy = ReadDOC(doc->virtadr, NOP);		else if (DoC_is_MillenniumPlus(doc))			dummy = ReadDOC(doc->virtadr, Mplus_NOP);		else			dummy = ReadDOC(doc->virtadr, DOCStatus);	}	}#define CDSN_CTRL_FR_B_MASK	(CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1)/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */static int _DoC_WaitReady(struct doc_priv *doc){	unsigned long docptr = doc->virtadr;	unsigned long timeo = jiffies + (HZ * 10);	if(debug) printk("_DoC_WaitReady...\n");	/* Out-of-line routine to wait for chip response */	if (DoC_is_MillenniumPlus(doc)) {		while ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) {			if (time_after(jiffies, timeo)) {				printk("_DoC_WaitReady timed out.\n");				return -EIO;			}			udelay(1);			cond_resched();		}	} else {		while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {			if (time_after(jiffies, timeo)) {				printk("_DoC_WaitReady timed out.\n");				return -EIO;			}			udelay(1);			cond_resched();		}	}	return 0;}static inline int DoC_WaitReady(struct doc_priv *doc){	unsigned long docptr = doc->virtadr;	int ret = 0;	if (DoC_is_MillenniumPlus(doc)) {		DoC_Delay(doc, 4);		if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK)			/* Call the out-of-line routine to wait */			ret = _DoC_WaitReady(doc);	} else {		DoC_Delay(doc, 4);		if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))			/* Call the out-of-line routine to wait */			ret = _DoC_WaitReady(doc);		DoC_Delay(doc, 2);	}	if(debug) printk("DoC_WaitReady OK\n");	return ret;}static void doc2000_write_byte(struct mtd_info *mtd, u_char datum){	struct nand_chip *this = mtd->priv;	struct doc_priv *doc = (void *)this->priv;	unsigned long docptr = doc->virtadr;	if(debug)printk("write_byte %02x\n", datum);	WriteDOC(datum, docptr, CDSNSlowIO);	WriteDOC(datum, docptr, 2k_CDSN_IO);}static u_char doc2000_read_byte(struct mtd_info *mtd){	struct nand_chip *this = mtd->priv;	struct doc_priv *doc = (void *)this->priv;	unsigned long docptr = doc->virtadr;	u_char ret;	ReadDOC(docptr, CDSNSlowIO);	DoC_Delay(doc, 2);	ret = ReadDOC(docptr, 2k_CDSN_IO);	if (debug) printk("read_byte returns %02x\n", ret);	return ret;}static void doc2000_writebuf(struct mtd_info *mtd, 			     const u_char *buf, int len){	struct nand_chip *this = mtd->priv;	struct doc_priv *doc = (void *)this->priv;	unsigned long docptr = doc->virtadr;	int i;	if (debug)printk("writebuf of %d bytes: ", len);	for (i=0; i < len; i++) {		WriteDOC_(buf[i], docptr, DoC_2k_CDSN_IO + i);		if (debug && i < 16)			printk("%02x ", buf[i]);	}	if (debug) printk("\n");}static void doc2000_readbuf(struct mtd_info *mtd, 			    u_char *buf, int len){	struct nand_chip *this = mtd->priv;	struct doc_priv *doc = (void *)this->priv;	unsigned long docptr = doc->virtadr; 	int i;	if (debug)printk("readbuf of %d bytes: ", len);	for (i=0; i < len; i++) {		buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i);	}}static void doc2000_readbuf_dword(struct mtd_info *mtd, 			    u_char *buf, int len){	struct nand_chip *this = mtd->priv;	struct doc_priv *doc = (void *)this->priv;	unsigned long docptr = doc->virtadr; 	int i;	if (debug) printk("readbuf_dword of %d bytes: ", len);	if (unlikely((((unsigned long)buf)|len) & 3)) {		for (i=0; i < len; i++) {			*(uint8_t *)(&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i);		}	} else {		for (i=0; i < len; i+=4) {			*(uint32_t*)(&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i);		}	}}static int doc2000_verifybuf(struct mtd_info *mtd, 			      const u_char *buf, int len){	struct nand_chip *this = mtd->priv;	struct doc_priv *doc = (void *)this->priv;	unsigned long docptr = doc->virtadr;	int i;	for (i=0; i < len; i++)		if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO))			return -EFAULT;	return 0;}static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr){	struct nand_chip *this = mtd->priv;	struct doc_priv *doc = (void *)this->priv;	uint16_t ret;	doc200x_select_chip(mtd, nr);	doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);	this->write_byte(mtd, NAND_CMD_READID);	doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE);	doc200x_hwcontrol(mtd, NAND_CTL_SETALE);	this->write_byte(mtd, 0);	doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);	ret = this->read_byte(mtd) << 8;	ret |= this->read_byte(mtd);	if (doc->ChipID == DOC_ChipID_Doc2k && try_dword && !nr) {		/* First chip probe. See if we get same results by 32-bit access */		union {			uint32_t dword;			uint8_t byte[4];		} ident;		unsigned long docptr = doc->virtadr;		doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);		doc2000_write_byte(mtd, NAND_CMD_READID);		doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE);		doc200x_hwcontrol(mtd, NAND_CTL_SETALE);		doc2000_write_byte(mtd, 0);		doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);		ident.dword = readl(docptr + DoC_2k_CDSN_IO);		if (((ident.byte[0] << 8) | ident.byte[1]) == ret) {			printk(KERN_INFO "DiskOnChip 2000 responds to DWORD access\n");			this->read_buf = &doc2000_readbuf_dword;		}	}			return ret;}static void __init doc2000_count_chips(struct mtd_info *mtd){	struct nand_chip *this = mtd->priv;	struct doc_priv *doc = (void *)this->priv;	uint16_t mfrid;	int i;	/* Max 4 chips per floor on DiskOnChip 2000 */	doc->chips_per_floor = 4;	/* Find out what the first chip is */	mfrid = doc200x_ident_chip(mtd, 0);	/* Find how many chips in each floor. */	for (i = 1; i < 4; i++) {		if (doc200x_ident_chip(mtd, i) != mfrid)			break;	}	doc->chips_per_floor = i;	printk(KERN_DEBUG "Detected %d chips per floor.\n", i);}static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state){	struct doc_priv *doc = (void *)this->priv;	int status;		DoC_WaitReady(doc);	this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);	DoC_WaitReady(doc);	status = (int)this->read_byte(mtd);	return status;}static void doc2001_write_byte(struct mtd_info *mtd, u_char datum){	struct nand_chip *this = mtd->priv;	struct doc_priv *doc = (void *)this->priv;	unsigned long docptr = doc->virtadr;	WriteDOC(datum, docptr, CDSNSlowIO);	WriteDOC(datum, docptr, Mil_CDSN_IO);	WriteDOC(datum, docptr, WritePipeTerm);}static u_char doc2001_read_byte(struct mtd_info *mtd){	struct nand_chip *this = mtd->priv;	struct doc_priv *doc = (void *)this->priv;	unsigned long docptr = doc->virtadr;	//ReadDOC(docptr, CDSNSlowIO);	/* 11.4.5 -- delay twice to allow extended length cycle */	DoC_Delay(doc, 2);	ReadDOC(docptr, ReadPipeInit);	//return ReadDOC(docptr, Mil_CDSN_IO);	return ReadDOC(docptr, LastDataRead);}static void doc2001_writebuf(struct mtd_info *mtd, 			     const u_char *buf, int len){	struct nand_chip *this = mtd->priv;	struct doc_priv *doc = (void *)this->priv;	unsigned long docptr = doc->virtadr;	int i;	for (i=0; i < len; i++)		WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i);	/* Terminate write pipeline */	WriteDOC(0x00, docptr, WritePipeTerm);}static void doc2001_readbuf(struct mtd_info *mtd, 			    u_char *buf, int len){	struct nand_chip *this = mtd->priv;	struct doc_priv *doc = (void *)this->priv;	unsigned long docptr = doc->virtadr;	int i;

⌨️ 快捷键说明

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