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

📄 au1550nd.c

📁 老版本的mtd-snap
💻 C
字号:
/* *  drivers/mtd/nand/au1550nd.c * *  Copyright (C) 2004 Embedded Edge, LLC * * $Id: au1550nd.c,v 1.11 2004/11/04 12:53:10 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */#include <linux/slab.h>#include <linux/init.h>#include <linux/module.h>#include <linux/mtd/mtd.h>#include <linux/mtd/nand.h>#include <linux/mtd/partitions.h>#include <asm/io.h>/* fixme: this is ugly */#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0)#include <asm/mach-au1x00/au1000.h>#ifdef CONFIG_MIPS_PB1550#include <asm/mach-pb1x00/pb1550.h> #endif#ifdef CONFIG_MIPS_DB1550#include <asm/mach-db1x00/db1x00.h> #endif#else#include <asm/au1000.h>#ifdef CONFIG_MIPS_PB1550#include <asm/pb1550.h> #endif#ifdef CONFIG_MIPS_DB1550#include <asm/db1x00.h> #endif#endif/* * MTD structure for NAND controller */static struct mtd_info *au1550_mtd = NULL;static void __iomem *p_nand;static int nand_width = 1; /* default x8*/#define NAND_CS 1/* * Define partitions for flash device */const static struct mtd_partition partition_info[] = {#ifdef CONFIG_MIPS_PB1550#define NUM_PARTITIONS            2	{ 		.name = "Pb1550 NAND FS 0",	  	.offset = 0,	  	.size = 8*1024*1024 	},	{ 		.name = "Pb1550 NAND FS 1",		.offset =  MTDPART_OFS_APPEND, 		.size =    MTDPART_SIZ_FULL	}#endif#ifdef CONFIG_MIPS_DB1550#define NUM_PARTITIONS            2	{ 		.name = "Db1550 NAND FS 0",	  	.offset = 0,	  	.size = 8*1024*1024 	},	{ 		.name = "Db1550 NAND FS 1",		.offset =  MTDPART_OFS_APPEND, 		.size =    MTDPART_SIZ_FULL	}#endif};/** * au_read_byte -  read one byte from the chip * @mtd:	MTD device structure * *  read function for 8bit buswith */static u_char au_read_byte(struct mtd_info *mtd){	struct nand_chip *this = mtd->priv;	u_char ret = readb(this->IO_ADDR_R);	au_sync();	return ret;}/** * au_write_byte -  write one byte to the chip * @mtd:	MTD device structure * @byte:	pointer to data byte to write * *  write function for 8it buswith */static void au_write_byte(struct mtd_info *mtd, u_char byte){	struct nand_chip *this = mtd->priv;	writeb(byte, this->IO_ADDR_W);	au_sync();}/** * au_read_byte16 -  read one byte endianess aware from the chip * @mtd:	MTD device structure * *  read function for 16bit buswith with  * endianess conversion */static u_char au_read_byte16(struct mtd_info *mtd){	struct nand_chip *this = mtd->priv;	u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));	au_sync();	return ret;}/** * au_write_byte16 -  write one byte endianess aware to the chip * @mtd:	MTD device structure * @byte:	pointer to data byte to write * *  write function for 16bit buswith with * endianess conversion */static void au_write_byte16(struct mtd_info *mtd, u_char byte){	struct nand_chip *this = mtd->priv;	writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);	au_sync();}/** * au_read_word -  read one word from the chip * @mtd:	MTD device structure * *  read function for 16bit buswith without  * endianess conversion */static u16 au_read_word(struct mtd_info *mtd){	struct nand_chip *this = mtd->priv;	u16 ret = readw(this->IO_ADDR_R);	au_sync();	return ret;}/** * au_write_word -  write one word to the chip * @mtd:	MTD device structure * @word:	data word to write * *  write function for 16bit buswith without  * endianess conversion */static void au_write_word(struct mtd_info *mtd, u16 word){	struct nand_chip *this = mtd->priv;	writew(word, this->IO_ADDR_W);	au_sync();}/** * au_write_buf -  write buffer to chip * @mtd:	MTD device structure * @buf:	data buffer * @len:	number of bytes to write * *  write function for 8bit buswith */static void au_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);		au_sync();	}}/** * au_read_buf -  read chip data into buffer  * @mtd:	MTD device structure * @buf:	buffer to store date * @len:	number of bytes to read * *  read function for 8bit buswith */static void au_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);		au_sync();		}}/** * au_verify_buf -  Verify chip data against buffer  * @mtd:	MTD device structure * @buf:	buffer containing the data to compare * @len:	number of bytes to compare * *  verify function for 8bit buswith */static int au_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;		au_sync();	}	return 0;}/** * au_write_buf16 -  write buffer to chip * @mtd:	MTD device structure * @buf:	data buffer * @len:	number of bytes to write * *  write function for 16bit buswith */static void au_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);		au_sync();	}		}/** * au_read_buf16 -  read chip data into buffer  * @mtd:	MTD device structure * @buf:	buffer to store date * @len:	number of bytes to read * *  read function for 16bit buswith */static void au_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);		au_sync();	}}/** * au_verify_buf16 -  Verify chip data against buffer  * @mtd:	MTD device structure * @buf:	buffer containing the data to compare * @len:	number of bytes to compare * *  verify function for 16bit buswith */static int au_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;		au_sync();	}	return 0;}static void au1550_hwcontrol(struct mtd_info *mtd, int cmd){	register struct nand_chip *this = mtd->priv;	switch(cmd){	case NAND_CTL_SETCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_CMD; break;	case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break;	case NAND_CTL_SETALE: this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; break;	case NAND_CTL_CLRALE: 		this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; 		/* FIXME: Nobody knows why this is neccecary, 		 * but it works only that way */		udelay(1); 		break;	case NAND_CTL_SETNCE: 		/* assert (force assert) chip enable */		au_writel((1<<(4+NAND_CS)) , MEM_STNDCTL); break;		break;	case NAND_CTL_CLRNCE:  		/* deassert chip enable */		au_writel(0, MEM_STNDCTL); break;		break;	}	this->IO_ADDR_R = this->IO_ADDR_W;		/* Drain the writebuffer */	au_sync();}int au1550_device_ready(struct mtd_info *mtd){	int ret = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0;	au_sync();	return ret;}/* * Main initialization routine */int __init au1550_init (void){	struct nand_chip *this;	u16 boot_swapboot = 0; /* default value */	int retval;	/* Allocate memory for MTD device structure and private data */	au1550_mtd = kmalloc (sizeof(struct mtd_info) + 			sizeof (struct nand_chip), GFP_KERNEL);	if (!au1550_mtd) {		printk ("Unable to allocate NAND MTD dev structure.\n");		return -ENOMEM;	}	/* Get pointer to private data */	this = (struct nand_chip *) (&au1550_mtd[1]);	/* Initialize structures */	memset((char *) au1550_mtd, 0, sizeof(struct mtd_info));	memset((char *) this, 0, sizeof(struct nand_chip));	/* Link the private data with the MTD structure */	au1550_mtd->priv = this;	/* MEM_STNDCTL: disable ints, disable nand boot */	au_writel(0, MEM_STNDCTL);#ifdef CONFIG_MIPS_PB1550	/* set gpio206 high */	au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR);	boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) | 		((bcsr->status >> 6)  & 0x1);	switch (boot_swapboot) {		case 0:		case 2:		case 8:		case 0xC:		case 0xD:			/* x16 NAND Flash */			nand_width = 0;			break;		case 1:		case 9:		case 3:		case 0xE:		case 0xF:			/* x8 NAND Flash */			nand_width = 1;			break;		default:			printk("Pb1550 NAND: bad boot:swap\n");			retval = -EINVAL;			goto outmem;	}#endif	/* Configure RCE1 - should be done by YAMON */	au_writel(0x5 | (nand_width << 22), 0xB4001010); /* MEM_STCFG1 */	au_writel(NAND_TIMING, 0xB4001014); /* MEM_STTIME1 */	au_sync();	/* setup and enable chip select, MEM_STADDR1 */	/* we really need to decode offsets only up till 0x20 */	au_writel((1<<28) | (NAND_PHYS_ADDR>>4) | 			(((NAND_PHYS_ADDR + 0x1000)-1) & (0x3fff<<18)>>18), 			MEM_STADDR1);	au_sync();	p_nand = ioremap(NAND_PHYS_ADDR, 0x1000);	/* Set address of hardware control function */	this->hwcontrol = au1550_hwcontrol;	this->dev_ready = au1550_device_ready;	/* 30 us command delay time */	this->chip_delay = 30;			this->eccmode = NAND_ECC_SOFT;	this->options = NAND_NO_AUTOINCR;	if (!nand_width)		this->options |= NAND_BUSWIDTH_16;	this->read_byte = (!nand_width) ? au_read_byte16 : au_read_byte;	this->write_byte = (!nand_width) ? au_write_byte16 : au_write_byte;	this->write_word = au_write_word;	this->read_word = au_read_word;	this->write_buf = (!nand_width) ? au_write_buf16 : au_write_buf;	this->read_buf = (!nand_width) ? au_read_buf16 : au_read_buf;	this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf;	/* Scan to find existence of the device */	if (nand_scan (au1550_mtd, 1)) {		retval = -ENXIO;		goto outio;	}	/* Register the partitions */	add_mtd_partitions(au1550_mtd, partition_info, NUM_PARTITIONS);	return 0; outio:	iounmap ((void *)p_nand);	 outmem:	kfree (au1550_mtd);	return retval;}module_init(au1550_init);/* * Clean up routine */#ifdef MODULEstatic void __exit au1550_cleanup (void){	struct nand_chip *this = (struct nand_chip *) &au1550_mtd[1];	/* Release resources, unregister device */	nand_release (au1550_mtd);	/* Free the MTD device structure */	kfree (au1550_mtd);	/* Unmap */	iounmap ((void *)p_nand);}module_exit(au1550_cleanup);#endifMODULE_LICENSE("GPL");MODULE_AUTHOR("Embedded Edge, LLC");MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on Pb1550 board");

⌨️ 快捷键说明

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