NAND Configuration

Steve Tsai startec at ms11.hinet.net
Tue Aug 6 06:25:47 EDT 2002


I use GPIO to control NCE, ALE and CLE. RE and WE are connected to CS of
ROM bank 1 and ROM bank 2.
The test program are work fine to do read/write and it seems work fine
also when I did not use CONFIG_JFFS2_FS_NAND. Thanks.


Steve Tsai



================================================================
Change in nand.c for our board.
=================================================================

#undef readb
#undef writeb

#define readb(a)  (*(volatile unsigned char *)(a))

/* Use function call for more delay in write cycle */
void writeb(unsigned char v, unsigned int a)
{
	*(volatile unsigned char *)(a) = v;
}


================================================================
Netpower.c for our board - board-specific glue layer.
=================================================================


#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>

/*
 * MTD structure for .NETpower board
 */
static struct mtd_info *dnp_mtd = NULL;

/*
 * Values specific to the .NETpower board (used with S3C4510 processor)
 */
#define DNP_FIO_BASE	0x2000000


#define   NCE   0x100
#define   ALE   0x400
#define   CLE   0x200 


/*
 * Module stuff
 */

static int dnp_fio_base = DNP_FIO_BASE;

#if 0
MODULE_PARM(dnp_fio_base, "i");

__setup("dnp_fio_base=",dnp_fio_base);
#endif

/*
 * Define partitions for flash device
 */
const static struct mtd_partition partition_info[] = {
	{ name: "DNP flash partition 1",
	  offset: 0,
	  size: 2*1024*1024 },
	{ name: "DNP flash partition 2",
	  offset: 2*1024*1024,
	  size: 6*1024*1024 }
};
#define NUM_PARTITIONS 2

/* 
 *	hardware specific access to control-lines
*/
void dnp_hwcontrol(int cmd){
    switch(cmd){

	case NAND_CTL_SETCLE: (*(volatile unsigned int *) (IOPDATA)) |=
CLE; break;
	case NAND_CTL_CLRCLE: (*(volatile unsigned int *) (IOPDATA)) &=
~CLE; break;

	case NAND_CTL_SETALE: (*(volatile unsigned int *) (IOPDATA)) |=
ALE; break;
	case NAND_CTL_CLRALE: (*(volatile unsigned int *) (IOPDATA)) &=
~ALE; break;

	case NAND_CTL_SETNCE: (*(volatile unsigned int *) (IOPDATA)) &=
~NCE; break;
	case NAND_CTL_CLRNCE: (*(volatile unsigned int *) (IOPDATA)) |=
NCE; break;
    }
}

/*
 * Main initialization routine
 */
int __init dnp_init (void)
{
	struct nand_chip *this;

	/* Allocate memory for MTD device structure and private data */
	dnp_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct
nand_chip),
				GFP_KERNEL);
	if (!dnp_mtd) {
		printk ("Unable to allocate DNP NAND MTD device
structure.\n");
		return -ENOMEM;
	}

	/* Get pointer to private data */
	this = (struct nand_chip *) (&dnp_mtd[1]);

	/* Initialize structures */
	memset((char *) dnp_mtd, 0, sizeof(struct mtd_info));
	memset((char *) this, 0, sizeof(struct nand_chip));

	/* Link the private data with the MTD structure */
	dnp_mtd->priv = this;

	/*
	 * Set GPIO Port register so that the pins are configured
	 * to be outputs for controlling the NAND flash.
	 */
	*(volatile unsigned int *)(IOPMOD)  |= (CLE|ALE|NCE);
	*(volatile unsigned int *)(IOPDATA) |= (NCE);

	/* Set address of NAND IO lines */
	/* 0x2000000 for ROM bank 1, 0x2200000 form ROM bank 2 */
	/* Above 0x4000000 is noncachable area
*/
	this->IO_ADDR_W = (dnp_fio_base | 0x4000000);
	this->IO_ADDR_R = ((dnp_fio_base+0x200000) | 0x4000000);
	/* Set address of hardware control function */
	this->hwcontrol = dnp_hwcontrol;
	this->dev_ready = NULL;
	/* 15 us command delay time */
	this->chip_delay = 15;		
	

	/* Scan to find existance of the device */
	if (nand_scan (dnp_mtd)) {
		kfree (dnp_mtd);
		return -ENXIO;
	}

	/* Allocate memory for internal data buffer */
	this->data_buf = kmalloc (sizeof(u_char) * (dnp_mtd->oobblock +
dnp_mtd->oobsize), GFP_KERNEL);
	if (!this->data_buf) {
		printk ("Unable to allocate NAND data buffer for
DNP.\n");
		kfree (dnp_mtd);
		return -ENOMEM;
	}

	/* Register the partitions */
	add_mtd_partitions(dnp_mtd, partition_info, NUM_PARTITIONS);

	/* Return happy */
	return 0;
}
module_init(dnp_init);

/*
 * Clean up routine
 */
#ifdef MODULE
static void __exit dnp_cleanup (void)
{
	struct nand_chip *this = (struct nand_chip *) &dnp_mtd[1];

	/* Unregister the device */
	del_mtd_device (dnp_mtd);

	/* Free internal data buffer */
	kfree (this->data_buf);

	/* Free the MTD device structure */
	kfree (dnp_mtd);
}
module_exit(dnp_cleanup);
#endif

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Steve Tsai <steve at synso.com");
MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on DNP
board");








-----Original Message-----
From: linux-mtd-admin at lists.infradead.org
[mailto:linux-mtd-admin at lists.infradead.org] On Behalf Of Thomas
Gleixner
Sent: Tuesday, August 06, 2002 5:46 PM
To: Steve Tsai
Cc: Linux MTD mailing list
Subject: Re: NAND Configuration


On Tue, 2002-08-06 at 09:25, Steve Tsai wrote:
Could you send me your hardware driver ? 

-- 
Thomas 
____________________________________________________
linutronix - competence in embedded & realtime linux
http://www.linutronix.de
mail: tglx at linutronix.de

nix.de



______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/





More information about the linux-mtd mailing list