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

📄 k9k8g08u0a.c

📁 nandflash k9g808u0a在pxa270的驱动,由于pxa270没有nandflash接口
💻 C
字号:
/* *  drivers/mtd/nand/nw_nand_nd.c * *  Copyright (C) 2004 Embedded Edge, LLC * * $Id: nw_nand_nd.c,v 1.1.2.1 2007/08/27 22:25:16 quy 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>//#include <asm/au1000.h>#define NW_NAND_PHYS_ADDR 	0x20000000#define NW_MEM_STNAND_CMD 	0x10000000#define NW_MEM_STNAND_ADDR 	0x00000020//MA20 0x00100000->MA05 0x00000020#define NW_MEM_STNAND_DATA 	0x00000000/* * MTD structure for NAND controller */static struct mtd_info *nw_nand_mtd = NULL;static volatile u32 p_nand,p_nand1;static int nand_width = 1; /* default, only x8 supported for now *//* * Define partitions for flash device */const static struct mtd_partition nw_partition_info[] ={	#define NW_NUM_PARTITIONS            1	{ 		.name = "nw NAND FS 0",	  .offset = 0,	  .size = 8*1024*1024 	}};static inline void write_cmd_reg(u8 cmd){	#if 0	if (nand_width)		*((volatile u8 *)(p_nand + NW_MEM_STNAND_CMD)) = cmd;	else		*((volatile u16 *)(p_nand + NW_MEM_STNAND_CMD)) = cmd;	#else	if (nand_width)		*((volatile u8 *)(p_nand1)) = cmd;	else		*((volatile u16 *)(p_nand1)) = cmd;	#endif	//au_sync();}static inline void write_addr_reg(u8 addr){	if (nand_width)		*((volatile u8 *)(p_nand + NW_MEM_STNAND_ADDR)) = addr;	else		*((volatile u16 *)(p_nand + NW_MEM_STNAND_ADDR)) = addr;	//au_sync();}static inline void write_data_reg(u8 data){	if (nand_width)		*((volatile u8 *)(p_nand + NW_MEM_STNAND_DATA)) = data;	else		*((volatile u16 *)(p_nand + NW_MEM_STNAND_DATA)) = data;	//au_sync();}static inline u32 read_data_reg(void){	u32 data;	if (nand_width)	{		data = *((volatile u8 *)(p_nand + NW_MEM_STNAND_DATA));		//au_sync();	}	else	{		data = *((volatile u16 *)(p_nand + NW_MEM_STNAND_DATA));		//au_sync();	}	return data;}void nw_nand_hwcontrol(struct mtd_info *mtd, int cmd){	switch(cmd)	{		case NAND_CTL_SETWP: 			GPSR1 = 0x00080000;			break;		case NAND_CTL_CLRWP: 			GPCR1 = 0x00080000;			break;	}}int nw_nand_device_ready(struct mtd_info *mtd){	int ready;	ready = (GPLR2 >> 18)&0x1;	return ready;}static u_char nw_nand_read_byte(struct mtd_info *mtd){	u_char ret;	ret = read_data_reg();	return ret;}static void nw_nand_write_byte(struct mtd_info *mtd, u_char byte){	write_data_reg((u8)byte);}static void nw_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len){	int i;	for (i=0; i<len; i++)		write_data_reg(buf[i]);}static void nw_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len){	int i;	for (i=0; i<len; i++)		buf[i] = (u_char)read_data_reg();}static int nw_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len){	int i;	for (i=0; i<len; i++)		if (buf[i] != (u_char)read_data_reg())			return -EFAULT;	return 0;}static void nw_nand_select_chip(struct mtd_info *mtd, int chip){	return;}static void nw_nand_command (struct mtd_info *mtd, unsigned command, 		int column, int page_addr){		register struct nand_chip *this = mtd->priv;			printk("quy command=0x%x column=0x%x page_addr=0x%x\n",command,column,page_addr);		/**Write out the command to the device**/		if(command==NAND_CMD_READ0)		{				write_cmd_reg(command);			  /* Serially input address 0x00*/				if (column != -1)				{					write_addr_reg((unsigned char) (column & 0xff));					write_addr_reg((unsigned char) ((column>>8) & 0xff));				}				if (page_addr != -1)				{					write_addr_reg((unsigned char) (page_addr & 0xff));					write_addr_reg(((page_addr >> 8) & 0xff));					write_addr_reg((unsigned char) ((page_addr >> 16) & 0x07));				}				write_cmd_reg(NAND_CMD_READSTART);		}		else if(command==NAND_CMD_SEQIN)		{				write_cmd_reg(command);			  /* Serially input address 0x80*/				if (column != -1)				{					write_addr_reg((unsigned char) (column & 0xff));					write_addr_reg((unsigned char) ((column>>8) & 0xff));				}				if (page_addr != -1)				{					write_addr_reg((unsigned char) (page_addr & 0xff));					write_addr_reg(((page_addr >> 8) & 0xff));					write_addr_reg((unsigned char) ((page_addr >> 16) & 0x07));				}		}		else if(command==NAND_CMD_PAGEPROG)		{				/*0x10*/				write_cmd_reg(command);		}		else if((command==NAND_CMD_STATUS)||(command==NAND_CMD_STATUS_MULTI))		{				/*0x70 0x71*/				command = NAND_CMD_STATUS;				write_cmd_reg(command);		}		else if(command==NAND_CMD_ERASE1)		{				/*0x60*/				write_cmd_reg(command);				if (page_addr != -1)				{					write_addr_reg((unsigned char) (page_addr & 0xff));					write_addr_reg(((page_addr >> 8) & 0xff));					write_addr_reg((unsigned char) ((page_addr >> 16) & 0x07));				}		}		else if(command==NAND_CMD_ERASE2)		{				/*0x60*/				write_cmd_reg(command);		}		else if(command==NAND_CMD_READID)		{			  /* Serially input address 0x90*/			  write_cmd_reg(command);				if (column != -1)				{					write_addr_reg((unsigned char) (column & 0xff));				}				if (page_addr != -1)				{					write_addr_reg((unsigned char) (page_addr & 0xff));					write_addr_reg(((page_addr >> 8) & 0xff));					/* One more address cycle for higher density devices */					if (mtd->size & 0x0c000000) 						write_addr_reg((unsigned char) ((page_addr >> 16) & 0x07));				}		}		else if(command==NAND_CMD_RESET)		{				/*0xff*/				write_cmd_reg(command);			  udelay(100);		}		else if(command==NAND_CMD_READOOB)		{			printk("err cmd =0x%x\n",command);		}				while (!this->dev_ready(mtd));}void nw_nand_getid(void){	int * preg;	printk("nw_nand_getid 0 2007-9-22 15:04\n");	write_cmd_reg((u8)0x90);	write_addr_reg((u8)0x00);	printk("nand id=0x%x\n",read_data_reg());	printk("nand id=0x%x\n",read_data_reg());	printk("nand id=0x%x\n",read_data_reg());	printk("nand id=0x%x\n",read_data_reg());	printk("nand id=0x%x\n",read_data_reg());}/* * Main initialization routine */int __init nw_nand_init (void){	struct nand_chip *this;	u16 boot_swapboot = 0; /* default value */	u32 mem_time;	u8 * preg;		/* Allocate memory for MTD device structure and private data */	nw_nand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL);	if (!nw_nand_mtd)	{		printk ("Unable to allocate NAND MTD dev structure.\n");		return -ENOMEM;	}	/* Get pointer to private data */	this = (struct nand_chip *) (&nw_nand_mtd[1]);	/* Initialize structures */	memset((char *) nw_nand_mtd, 0, sizeof(struct mtd_info));	memset((char *) this, 0, sizeof(struct nand_chip));	/* Link the private data with the MTD structure */	nw_nand_mtd->priv = this;	p_nand = (volatile u8 *)ioremap(NW_NAND_PHYS_ADDR, 0x1000);	p_nand1 = (volatile u8 *)ioremap(NW_NAND_PHYS_ADDR+0x10000000, 0x1000);	/* Init GPIOs with alternate functions */	GPSR0 = 0x00008000;	GPSR2 = 0x00008000;	GPSR1 = 0x00040000;	GPSR1 = 0x00080000;	GPSR1 = 0x02000000;	GPSR1 = 0x01000000;	GPSR2 = 0x00040000;	GPSR2 = 0x00080000;		GPDR1 &= ~0x01000000;	GAFR1_U = (GAFR1_U & 0xfffcffff) | 0x00010000;//nPAWIT GPIO56->nPAWIT		//GPDR1 |= 0x00800000;	//GAFR1_U = (GAFR1_U & 0xffff3fff) | 0x00008000;//nPREG GPIO55		GPDR0 |= 0x00008000;	GAFR0_L = (GAFR0_L & 0x3fffffff) | 0x40000000;//nPCE<1> GPIO15->CE1\		GPDR2 |= 0x00008000;	GAFR2_L = (GAFR2_L & 0x3fffffff) | 0x40000000;//PSKTSEL GPIO79->CLE		GPDR1 |= 0x00040000;	GAFR1_U = (GAFR1_U & 0xffffffcf) | 0x00000020;//PIOR GPIO50->RE\		GPDR1 |= 0x00080000;	GAFR1_U = (GAFR1_U & 0xffffff3f) | 0x00000080;//PIOW GPIO51->WE\		GPDR1 &= 0xfdffffff;	GAFR1_U = (GAFR1_U & 0xfff3ffff) | 0x00400000;//nIOIS16 GPIO57		GPDR2 &= 0xfffbffff;//R/B\ GPIO82 in	GPDR2 |= 0x00080000;//WP\ GPIO83 out	GPSR2 |= 0x00080000;//WP\ high		MECR = 0x00000003;//PC Card inserted	PCFR &= 0xfffd;//indicate signals should not be floated in sleep mode		//?Software should program the PGSRx bits correctly so that during sleep mode	//nPCE1 signal is held high during sleep mode	PGSR0 |= 0x00008000;		MCIO0 = 0x00001004;//for timing	MCIO1 = 0x00001004;//for timing	/* Set address of hardware control function */	this->hwcontrol = nw_nand_hwcontrol;	this->dev_ready = nw_nand_device_ready;	/* 30 us command delay time */	this->chip_delay = 30;			this->cmdfunc = nw_nand_command;	this->select_chip = nw_nand_select_chip;	this->write_byte = nw_nand_write_byte;	this->read_byte = nw_nand_read_byte;	this->write_buf = nw_nand_write_buf;	this->read_buf = nw_nand_read_buf;	this->verify_buf = nw_nand_verify_buf;	this->eccmode = NAND_ECC_SOFT;//NAND_ECC_SOFT NAND_ECC_HW3_512	//nw_nand_getid();		/* Scan to find existence of the device */	if (nand_scan (nw_nand_mtd, 1))	{		kfree (nw_nand_mtd);		return -ENXIO;	}	/* Register the partitions */	add_mtd_partitions(nw_nand_mtd, nw_partition_info, NW_NUM_PARTITIONS);	return 0;}module_init(nw_nand_init);/* * Clean up routine */static void __exit nw_nand_cleanup (void){	struct nand_chip *this = (struct nand_chip *) &nw_nand_mtd[1];	iounmap ((void *)p_nand);	/* Unregister partitions */	del_mtd_partitions(nw_nand_mtd);	/* Unregister the device */	del_mtd_device (nw_nand_mtd);	/* Free the MTD device structure */	kfree (nw_nand_mtd);}module_exit(nw_nand_cleanup);MODULE_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 + -