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

📄 s3c24a0_nand.c

📁 SMDK2440 boot code, base on vivi
💻 C
字号:
/* * NAND controller on SAMSUNG S3C24A0 * *  bushi@mizi.com * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive * for more details. */#include <config.h>#include <machine.h>#include <types.h>#include <mtd/mtd.h>#include <mtd/nand.h>#include <time.h>#include <vmalloc.h>#include <vstring.h>#include <errno.h>extern int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);static struct mtd_info *s3c24a0_nand_mtd = NULL;static void s3c24a0_nand_select_chip(struct mtd_info *mtd, int chip){	if (chip == 0)		NANDCONT &= ~(1 << 7);	else		NANDCONT |= (1 << 7);}static int s3c24a0_nand_device_ready(struct mtd_info *mtd){	return (NFSTAT & NFSTAT_RnB) ? 1:0;}/* small and normal page size */static void s3c24a0_nand_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr){	register struct nand_chip *this = mtd->priv;	/* Adjust columns for 16 bit buswidth */	if (this->options & NAND_BUSWIDTH_16)		column >>= 1;	/*	 * 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;		}		NFCMD = readcmd;	}	NFCMD = (command & 0xFF);	if (column != -1 || page_addr != -1) {		/* Serially input address */		if (column != -1)			NFADDR = (column & 0xFF);		if (page_addr != -1) {			NFADDR = (unsigned char)(page_addr & 0xff);			NFADDR = (unsigned char)((page_addr >> 8) & 0xff);			/* One more address cycle for higher density devices */			if (mtd->size & 0x0c000000) 				NFADDR = (unsigned char)((page_addr >> 16) & 0x0f);		}		/* Latch in address */	}		/* 	 * 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;		NFCMD = NAND_CMD_STATUS;		while ( !(NFDATA & 0x40));		return;	/* This applies to read commands */		default:		if (!this->dev_ready) {			udelay (this->chip_delay);			return;		}		}		/* wait until command is processed */	while (!this->dev_ready(mtd));}/*  * large page size  *   (not used, but ...) */static void s3c24a0_nand_cmdfunc_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;	}	/* Adjust columns for 16 bit buswidth */	if (this->options & NAND_BUSWIDTH_16)		column >>= 1;	NFCMD = command;	if (column != -1 || page_addr != -1) {		/* Serially input address */		if (column != -1) {			NFADDR = (column & 0xff);			NFADDR = (column >> 8);		}			if (page_addr != -1) {			NFADDR = (unsigned char) ((page_addr & 0xff));			NFADDR = (unsigned char) ((page_addr >> 8) & 0xff);			/* One more address cycle for devices > 128MiB */			if (this->chipsize > (128 << 20))				NFADDR = (unsigned char) ((page_addr >> 16) & 0xff);		}	}		/* 	 * program and erase have their own busy handlers 	 * status and sequential in needs 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:		return;	case NAND_CMD_RESET:		if (this->dev_ready)				break;		udelay(this->chip_delay);		NFCMD = NAND_CMD_STATUS;		while ( !(NFDATA & 0x40));		return;	case NAND_CMD_READ0:		NFCMD = NAND_CMD_READSTART;			/* 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;		}		}		/* wait until command is processed */	while (!this->dev_ready(mtd));}/* Internal buffers. Page buffer and oob buffer for one block */static u_char data_buf[2048 + 64]; /* maximum */static u_char oob_buf[64 * 32];    /* FIXME */int s3c24a0_nand_init (void){	struct nand_chip *this;	int err = 0;	/* Allocate memory for MTD device structure and private data */	s3c24a0_nand_mtd = vmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip));	if (!s3c24a0_nand_mtd) {		printk ("Unable to allocate NAND MTD device structure.\n");		err = -ENOMEM;		goto out;	}	/* Get pointer to private data */	this = (struct nand_chip *) (&s3c24a0_nand_mtd[1]);	/* Initialize structures */	memset((char *) s3c24a0_nand_mtd, 0, sizeof(struct mtd_info));	memset((char *) this, 0, sizeof(struct nand_chip));	/* Link the private data with the MTD structure */	s3c24a0_nand_mtd->priv = this;	/* Disable write protect */	GPCON_M &= ~(0x3 << 8);	GPCON_M |= (0x1 << 8);	/* to set as output */	GPDAT |= (0x1 << 15);	/* disable write protect */	/* Set address of NAND IO lines */	this->IO_ADDR_R = 0x40c00010;	this->IO_ADDR_W = 0x40c00010;	this->select_chip = s3c24a0_nand_select_chip;	this->dev_ready = s3c24a0_nand_device_ready;	this->cmdfunc = s3c24a0_nand_cmdfunc;	this->eccmode = NAND_ECC_SOFT;	printk(__FILE__": Using NAND S/W ECC\n");	/* Set internal data buffer */	this->data_buf = data_buf;	this->oob_buf = oob_buf;	/* 20 us command delay time */	this->chip_delay = 20;			/* Scan to find existance of the device */	if (nand_scan (s3c24a0_nand_mtd, 1)) {		err = -ENXIO;		goto out_mtd;	}	s3c24a0_nand_mtd->eccsize = this->eccsize;	add_mtd_device(s3c24a0_nand_mtd);	goto out;out_mtd:	free (s3c24a0_nand_mtd);out:	return err;}

⌨️ 快捷键说明

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