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

📄 hycnc_nand.c

📁 在PXA255下用做扩展NAND Flash芯片的程序源代码
💻 C
字号:
/* *  drivers/mtd/nand/hycnc_nand0.c * */#include <linux/module.h>#include <linux/mtd/mtd.h>#include <linux/mtd/nand.h>#include <linux/slab.h>#include <linux/mtd/partitions.h>#include <asm/io.h>#include <asm/arch/hardware.h>#include <asm/sizes.h>#include <linux/delay.h>#include <linux/init.h>#include <asm/errno.h>#define NAND0_DATA_CS           (0xEA000000)#define NAND1_DATA_CS           (0xEA200000)#define _NAND_CMD_CS0           (0xEA400000)#define NAND_CMD_CS0            (*(volatile unsigned char *)(_NAND_CMD_CS0))#define NAND0_NCE               (1<<0)#define NAND0_CLE               (1<<1)#define NAND0_ALE               (1<<2)#define NAND0_NWP               (1<<3)#define NAND1_NCE               (1<<4)#define NAND1_CLE               (1<<5)#define NAND1_ALE               (1<<6)#define NAND1_NWP               (1<<7)/* * MTD structure for hycnc board */static struct mtd_info *hycnc_mtd0 = NULL;static struct mtd_info *hycnc_mtd1 = NULL;/* * Define partitions for flash devices */static struct mtd_partition partition_info16k0[] = {	{ name: "hycnc_Nand_Flash_A_16K",	offset:  0,	size:    16 * SZ_1M },	{ name: "hycnc_Nand_Flash A_2_16K",	offset:  0 * SZ_1M,	size:    0 * SZ_1M },};static struct mtd_partition partition_info32k0[] = {	{ name: "hycnc_Nand_Flash_A_32K",	offset:  0,	size:   32 * SZ_1M },	{ name: "hycnc_Nand_Flash_A_2_32K",	offset: 0 * SZ_1M,	size:   0 * SZ_1M },};static struct mtd_partition partition_info64k0[] = {	{ name: "hycnc_Nand_Flash_A_64K",	offset: 0,	size:   64 * SZ_1M },	{ name: "hycnc_Nand_Flash_A_2_64K",	offset: 0 * SZ_1M,	size:   0 * SZ_1M },};static struct mtd_partition partition_info128k0[] = {	{ name: "hycnc_Nand_Flash_A_128K",	offset: 0,	size:   128 * SZ_1M },	{ name: "hycnc_Nand_Flash_A_2_128K",	offset: 0 * SZ_1M,	size:   0 * SZ_1M },};#define NUM_PARTITIONS16K0 1#define NUM_PARTITIONS32K0 1#define NUM_PARTITIONS64K0 1#define NUM_PARTITIONS128K0 1static struct mtd_partition partition_info16k1[] = {	{ name: "hycnc_Nand_Flash_B_16K",	offset:  0,	size:    16 * SZ_1M },	{ name: "hycnc_Nand_Flash_B_2_16K",	offset:  0 * SZ_1M,	size:    0 * SZ_1M },};static struct mtd_partition partition_info32k1[] = {	{ name: "hycnc_Nand_Flash_B_32K",	offset:  0,	size:   32 * SZ_1M },	{ name: "hycnc_Nand_Flash_B_2_32K",	offset: 0 * SZ_1M,	size:   0 * SZ_1M },};static struct mtd_partition partition_info64k1[] = {	{ name: "hycnc_Nand_Flash_B_64K",	offset: 0,	size:   64 * SZ_1M },	{ name: "hycnc_Nand_Flash_B_2_64K",	offset: 0 * SZ_1M,	size:   0 * SZ_1M },};static struct mtd_partition partition_info128k1[] = {	{ name: "hycnc_Nand_Flash_B_128K",	offset: 0,	size:   128 * SZ_1M },	{ name: "hycnc_Nand_Flash_B_2_128K",	offset: 0 * SZ_1M,	size:   0 * SZ_1M },};#define NUM_PARTITIONS16K1 1#define NUM_PARTITIONS32K1 1#define NUM_PARTITIONS64K1 1#define NUM_PARTITIONS128K1 1/* *  hardware specific access to control-lines*/static unsigned char nand_ctrl0 = ( NAND0_NCE | NAND0_NWP | NAND1_NCE | NAND1_NWP );static void hycnc_hwcontrol0(struct mtd_info *mtd, int cmd){    	switch(cmd)	{    		case NAND_CTL_SETCLE:				nand_ctrl0 |=  NAND0_CLE;				NAND_CMD_CS0 = nand_ctrl0;				break;    		case NAND_CTL_CLRCLE:				nand_ctrl0 &= ~NAND0_CLE;				NAND_CMD_CS0 = nand_ctrl0;				break;    		case NAND_CTL_SETALE:				nand_ctrl0 |=  NAND0_ALE;				NAND_CMD_CS0 = nand_ctrl0;				break;    		case NAND_CTL_CLRALE:				nand_ctrl0 &= ~NAND0_ALE;				NAND_CMD_CS0 = nand_ctrl0;				break;    		case NAND_CTL_SETNCE:				nand_ctrl0 &= ~NAND0_NCE;				NAND_CMD_CS0 = nand_ctrl0;				break;    		case NAND_CTL_CLRNCE:				nand_ctrl0 |=  NAND0_NCE;				NAND_CMD_CS0 = nand_ctrl0;				break;	}}static void hycnc_hwcontrol1(struct mtd_info *mtd, int cmd){    	switch(cmd)	{    		case NAND_CTL_SETCLE:				nand_ctrl0 |=  NAND1_CLE;				NAND_CMD_CS0 = nand_ctrl0;				break;    		case NAND_CTL_CLRCLE:				nand_ctrl0 &= ~NAND1_CLE;				NAND_CMD_CS0 = nand_ctrl0;				break;    		case NAND_CTL_SETALE:				nand_ctrl0 |=  NAND1_ALE;				NAND_CMD_CS0 = nand_ctrl0;				break;    		case NAND_CTL_CLRALE:				nand_ctrl0 &= ~NAND1_ALE;				NAND_CMD_CS0 = nand_ctrl0;				break;    		case NAND_CTL_SETNCE:				nand_ctrl0 &= ~NAND1_NCE;				NAND_CMD_CS0 = nand_ctrl0;				break;    		case NAND_CTL_CLRNCE:				nand_ctrl0 |=  NAND1_NCE;				NAND_CMD_CS0 = nand_ctrl0;				break;	}}/**   read device ready pin*/int hycnc_device_ready0(void){	return ( RNB_CS & NAND0_RNB ) ? 1 : 0;}int hycnc_device_ready1(void){	return ( RNB_CS & NAND1_RNB ) ? 1 : 0;}int hycnc_nand_delay = 20;/* * Main initialization routine */int __init hycnc_nand_init (void){    	struct nand_chip *this;    	int err = 0;	printk ("Initialising HYCNC NAND MTD devices.\n");	/* Allocate memory for MTD device structure and private data */    	hycnc_mtd0 = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),			GFP_KERNEL);    	if (!hycnc_mtd0) {		printk ("Unable to allocate hycnc NAND MTD device structure.\n");		err = -ENOMEM;		goto out;    	}    	/* Get pointer to private data */    	this = (struct nand_chip *) (&hycnc_mtd0[1]);    	/* Initialize structures */    	memset((char *) hycnc_mtd0, 0, sizeof(struct mtd_info));    	memset((char *) this, 0, sizeof(struct nand_chip));	/* Link the private data with the MTD structure */    	hycnc_mtd0->priv = this;    	/* Set address of NAND IO lines */    	this->IO_ADDR_R = NAND0_DATA_CS;//弊成 例措林家蔼父 霖促.    	this->IO_ADDR_W = NAND0_DATA_CS;//弊成 例措林家蔼父 霖促.    	this->hwcontrol = hycnc_hwcontrol0;    	//this->dev_ready = hycnc_device_ready0; //nand on board	this->dev_ready = NULL;	    	/* 20 us command delay time */    	this->chip_delay = hycnc_nand_delay;	this->eccmode = NAND_ECC_SOFT;	/* Scan to find existance of the device */    	if (nand_scan (hycnc_mtd0, 1)) {		printk ("Unable to find First HYCNC NAND device.\n");		err = -ENXIO;		kfree (hycnc_mtd0);	 	goto out;    	}    	/* Allocate memory for internal data buffer */    	this->data_buf = kmalloc (sizeof(u_char) * (hycnc_mtd0->oobblock + hycnc_mtd0->oobsize), GFP_KERNEL);    	if (!this->data_buf) {		printk ("Unable to allocate First NAND data buffer for hycnc.\n");		err = -ENOMEM;		kfree (hycnc_mtd0);		goto out;    	}    	/* Register the partitions */    	switch(hycnc_mtd0->size)	{		case SZ_16M:			add_mtd_partitions(hycnc_mtd0, partition_info16k0, NUM_PARTITIONS16K0);			break;		case SZ_32M:			add_mtd_partitions(hycnc_mtd0, partition_info32k0, NUM_PARTITIONS32K0);			break;		case SZ_64M:			add_mtd_partitions(hycnc_mtd0, partition_info64k0, NUM_PARTITIONS64K0);			break;		case SZ_128M:			add_mtd_partitions(hycnc_mtd0, partition_info128k0, NUM_PARTITIONS128K0);			break;		default: 			{				printk ("Unsupported First Nand Size\n");				err = -ENXIO;				goto out;			}    	}	//printk ("Initialising of First HYCNC NAND MTD was successful.\n");	/* Allocate memory for MTD device structure and private data */    	hycnc_mtd1 = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),			GFP_KERNEL);    	if (!hycnc_mtd1) {		printk ("Unable to allocate Second HYCNC NAND MTD device structure.\n");		err = -ENOMEM;		goto out;    	}    	/* Get pointer to private data */    	this = (struct nand_chip *) (&hycnc_mtd1[1]);    	/* Initialize structures */    	memset((char *) hycnc_mtd1, 0, sizeof(struct mtd_info));    	memset((char *) this, 0, sizeof(struct nand_chip));	/* Link the private data with the MTD structure */    	hycnc_mtd1->priv = this;    	/* Set address of NAND IO lines */    	this->IO_ADDR_R = NAND1_DATA_CS;//弊成 例措林家蔼父 霖促.    	this->IO_ADDR_W = NAND1_DATA_CS;//弊成 例措林家蔼父 霖促.    	this->hwcontrol = hycnc_hwcontrol1;    	//this->dev_ready = hycnc_device_ready1; //nand on board	this->dev_ready = NULL;    	/* 20 us command delay time */    	this->chip_delay = hycnc_nand_delay;	this->eccmode = NAND_ECC_SOFT;	/* Scan to find existance of the device */    	if (nand_scan (hycnc_mtd1, 1)) {		printk ("Unable to Second HYCNC NAND device.\n");		err = -ENXIO;		kfree (hycnc_mtd1);	 	goto out;    	}    	/* Allocate memory for internal data buffer */    	this->data_buf = kmalloc (sizeof(u_char) * (hycnc_mtd1->oobblock + hycnc_mtd1->oobsize), GFP_KERNEL);    	if (!this->data_buf) {		printk ("Unable to allocate Second NAND data buffer for hycnc.\n");		err = -ENOMEM;		kfree (hycnc_mtd1);		goto out;    	}    	/* Register the partitions */    	switch(hycnc_mtd1->size)	{		case SZ_16M:			add_mtd_partitions(hycnc_mtd1, partition_info16k1, NUM_PARTITIONS16K1);			break;		case SZ_32M:			add_mtd_partitions(hycnc_mtd1, partition_info32k1, NUM_PARTITIONS32K1);			break;		case SZ_64M:			add_mtd_partitions(hycnc_mtd1, partition_info64k1, NUM_PARTITIONS64K1);			break;		case SZ_128M:			add_mtd_partitions(hycnc_mtd1, partition_info128k1, NUM_PARTITIONS128K1);			break;		default: 			{				printk ("Unsupported Second Nand Size\n");				err = -ENXIO;				goto out;			}    	}	//printk ("Initialising of Second HYCNC NAND MTD was successful.\n");	return 0;out:	kfree (this->data_buf);    	return err;}module_init(hycnc_nand_init);/* * Clean up routine */#ifdef MODULEstatic void __exit hycnc_cleanup (void){    	struct nand_chip *this;    	this = (struct nand_chip *) &hycnc_mtd0[1];    	/* Unregister partitions */    	del_mtd_partitions(hycnc_mtd0);    	/* Unregister the device */    	del_mtd_device (hycnc_mtd0);    	/* Free internal data buffers */    	kfree (this->data_buf);    	/* Free the MTD device structure */    	kfree (hycnc_mtd0);    	this = (struct nand_chip *) &hycnc_mtd1[1];    	/* Unregister partitions */    	del_mtd_partitions(hycnc_mtd1);    	/* Unregister the device */    	del_mtd_device (hycnc_mtd1);    	/* Free internal data buffers */    	kfree (this->data_buf);    	/* Free the MTD device structure */    	kfree (hycnc_mtd1);}module_exit(hycnc_cleanup);#endifMODULE_LICENSE("GPL");MODULE_AUTHOR("newboder <newboder@hybus.net>");MODULE_DESCRIPTION("Glue layer for Nand");

⌨️ 快捷键说明

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