mtd/drivers/mtd/nand ppchameleonevb.c,1.1,1.2

gleixner at infradead.org gleixner at infradead.org
Wed May 5 18:09:57 EDT 2004


Update of /home/cvs/mtd/drivers/mtd/nand
In directory phoenix.infradead.org:/tmp/cvs-serv8989

Modified Files:
	ppchameleonevb.c 
Log Message:
support all NAND parts on CPU board and EVB

Index: ppchameleonevb.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nand/ppchameleonevb.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ppchameleonevb.c	18 Mar 2004 09:27:24 -0000	1.1
+++ ppchameleonevb.c	5 May 2004 22:09:54 -0000	1.2
@@ -13,9 +13,14 @@
  * published by the Free Software Foundation.
  *
  *  Overview:
- *   This is a device driver for the NAND flash device found on the
- *   PPChameleonEVB board which utilizes the Samsung K9F5608U0B part. This is
- *   a 256Mibit (32MiB x 8 bits) NAND flash device.
+ *   This is a device driver for the NAND flash devices found on the
+ *   PPChameleon/PPChameleonEVB system.
+ *   PPChameleon options (autodetected):
+ *   - BA model: no NAND
+ *   - ME model: 32MB (Samsung K9F5608U0B)
+ *   - HI model: 128MB (Samsung K9F1G08UOM)
+ *   PPChameleonEVB options:
+ *   - 32MB (Samsung K9F5608U0B)
  */
 
 #include <linux/init.h>
@@ -27,38 +32,76 @@
 #include <asm/io.h>
 #include <platforms/PPChameleonEVB.h>
 
+#undef USE_READY_BUSY_PIN
+#define USE_READY_BUSY_PIN
+/* see datasheets (tR) */
+#define NAND_BIG_DELAY_US		25
+#define NAND_SMALL_DELAY_US		10
+
 /* handy sizes */
 #define SZ_4M                           0x00400000
-
-/* GPIO pins used to drive NAND chip */
-#define NAND_nCE_GPIO_PIN (1 << 14)
-#define NAND_CLE_GPIO_PIN (1 << 15)
-#define NAND_ALE_GPIO_PIN (1 << 16)
+#define NAND_SMALL_SIZE                 0x02000000
+#define NAND_MTD_NAME		"ppchameleon-nand"
+#define NAND_EVB_MTD_NAME	"ppchameleonevb-nand"
+
+/* GPIO pins used to drive NAND chip mounted on processor module */
+#define NAND_nCE_GPIO_PIN 		(0x80000000 >> 1)
+#define NAND_CLE_GPIO_PIN 		(0x80000000 >> 2)
+#define NAND_ALE_GPIO_PIN 		(0x80000000 >> 3)
+#define NAND_RB_GPIO_PIN 		(0x80000000 >> 4)
+/* GPIO pins used to drive NAND chip mounted on EVB */
+#define NAND_EVB_nCE_GPIO_PIN 	(0x80000000 >> 14)
+#define NAND_EVB_CLE_GPIO_PIN 	(0x80000000 >> 15)
+#define NAND_EVB_ALE_GPIO_PIN 	(0x80000000 >> 16)
+#define NAND_EVB_RB_GPIO_PIN 	(0x80000000 >> 31)
 
 /*
  * MTD structure for PPChameleonEVB board
  */
+static struct mtd_info *ppchameleon_mtd 	= NULL;
 static struct mtd_info *ppchameleonevb_mtd = NULL;
 
 /*
  * Module stuff
  */
+static int ppchameleon_fio_pbase 	= CFG_NAND0_PADDR;
 static int ppchameleonevb_fio_pbase = CFG_NAND1_PADDR;
+
 #ifdef MODULE
+MODULE_PARM(ppchameleon_fio_pbase, "i");
+__setup("ppchameleon_fio_pbase=",ppchameleon_fio_pbase);
 MODULE_PARM(ppchameleonevb_fio_pbase, "i");
-
 __setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase);
 #endif
 
+/* Internal buffers. Page buffer and oob buffer for one block */
+static u_char data_buf[2048 + 64];
+static u_char oob_buf[64 * 64];
+static u_char data_buf_evb[512 + 16];
+static u_char oob_buf_evb[16 * 32];
+
 #ifdef CONFIG_MTD_PARTITIONS
 /*
- * Define static partitions for flash device
+ * Define static partitions for flash devices
  */
-static struct mtd_partition partition_info[] = {
+static struct mtd_partition partition_info_hi[] = {
+	{ name: "PPChameleon HI Nand Flash",
+		  offset: 0,
+		  size: 128*1024*1024 }
+};
+
+static struct mtd_partition partition_info_me[] = {
+	{ name: "PPChameleon ME Nand Flash",
+		  offset: 0,
+		  size: 32*1024*1024 }
+};
+
+static struct mtd_partition partition_info_evb[] = {
 	{ name: "PPChameleonEVB Nand Flash",
 		  offset: 0,
 		  size: 32*1024*1024 }
 };
+
 #define NUM_PARTITIONS 1
 
 extern int parse_cmdline_partitions(struct mtd_info *master,
@@ -70,42 +113,77 @@
 /*
  *	hardware specific access to control-lines
  */
+static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+{
+	switch(cmd) {
+
+	case NAND_CTL_SETCLE:
+        	MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
+		break;
+	case NAND_CTL_CLRCLE:
+        	MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
+		break;
+	case NAND_CTL_SETALE:
+        	MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
+		break;
+	case NAND_CTL_CLRALE:
+        	MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
+		break;
+	case NAND_CTL_SETNCE:
+			MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
+		break;
+	case NAND_CTL_CLRNCE:
+			MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
+		break;
+	}
+}
+
 static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
 {
 	switch(cmd) {
 
 	case NAND_CTL_SETCLE:
-        	MACRO_NAND_CTL_SETCLE(CFG_NAND1_PADDR);
+        	MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
 		break;
 	case NAND_CTL_CLRCLE:
-        	MACRO_NAND_CTL_CLRCLE(CFG_NAND1_PADDR);
+        	MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
 		break;
 	case NAND_CTL_SETALE:
-        	MACRO_NAND_CTL_SETALE(CFG_NAND1_PADDR);
+        	MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
 		break;
 	case NAND_CTL_CLRALE:
-        	MACRO_NAND_CTL_CLRALE(CFG_NAND1_PADDR);
+        	MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
 		break;
 	case NAND_CTL_SETNCE:
-        	MACRO_NAND_ENABLE_CE(CFG_NAND1_PADDR);
+        	MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
 		break;
 	case NAND_CTL_CLRNCE:
-        	MACRO_NAND_DISABLE_CE(CFG_NAND1_PADDR);
+        	MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
 		break;
 	}
 }
 
-#if 0
+#ifdef USE_READY_BUSY_PIN
 /*
  *	read device ready pin
  */
+static int ppchameleon_device_ready(struct mtd_info *minfo)
+{
+	if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_RB_GPIO_PIN)
+		return 1;
+	return 0;
+}
+
 static int ppchameleonevb_device_ready(struct mtd_info *minfo)
 {
+	if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN)
 	return 1;
+	return 0;
 }
 #endif
 
 #ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes[] = { "cmdlinepart", NULL };
 const char *part_probes_evb[] = { "cmdlinepart", NULL };
 #endif
 
@@ -118,9 +196,117 @@
 	const char *part_type = 0;
 	int mtd_parts_nb = 0;
 	struct mtd_partition *mtd_parts = 0;
+	int ppchameleon_fio_base;
 	int ppchameleonevb_fio_base;
 
 
+	/*********************************
+	* Processor module NAND (if any) *
+	*********************************/
+	/* Allocate memory for MTD device structure and private data */
+	ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) +
+			     sizeof(struct nand_chip),
+			     GFP_KERNEL);
+	if (!ppchameleon_mtd) {
+		printk("Unable to allocate PPChameleon NAND MTD device structure.\n");
+		return -ENOMEM;
+	}
+
+	/* map physical address */
+	ppchameleon_fio_base = (unsigned long)ioremap(ppchameleon_fio_pbase, SZ_4M);
+	if(!ppchameleon_fio_base) {
+		printk("ioremap PPChameleon NAND flash failed\n");
+		kfree(ppchameleon_mtd);
+		return -EIO;
+	}
+
+	/* Get pointer to private data */
+	this = (struct nand_chip *) (&ppchameleon_mtd[1]);
+
+	/* Initialize structures */
+	memset((char *) ppchameleon_mtd, 0, sizeof(struct mtd_info));
+	memset((char *) this, 0, sizeof(struct nand_chip));
+
+	/* Link the private data with the MTD structure */
+	ppchameleon_mtd->priv = this;
+
+        /* Initialize GPIOs */
+	/* Pin mapping for NAND chip */
+	/*
+		CE	GPIO_01
+		CLE	GPIO_02
+		ALE	GPIO_03
+		R/B	GPIO_04
+	*/
+	/* output select */
+	out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xC0FFFFFF);
+	/* three-state select */
+	out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xC0FFFFFF);
+	/* enable output driver */
+	out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN);
+#ifdef USE_READY_BUSY_PIN
+	/* three-state select */
+	out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFF3FFFFF);
+	/* high-impedecence */
+	out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) & (~NAND_RB_GPIO_PIN));
+	/* input select */
+	out_be32((volatile unsigned*)GPIO0_ISR1H, (in_be32((volatile unsigned*)GPIO0_ISR1H) & 0xFF3FFFFF) | 0x00400000);
+#endif
+
+	/* insert callbacks */
+	this->IO_ADDR_R = ppchameleon_fio_base;
+	this->IO_ADDR_W = ppchameleon_fio_base;
+	this->hwcontrol = ppchameleon_hwcontrol;
+#ifdef USE_READY_BUSY_PIN
+	this->dev_ready = ppchameleon_device_ready;
+#endif
+	this->chip_delay = NAND_BIG_DELAY_US;
+	/* ECC mode */
+	this->eccmode = NAND_ECC_SOFT;
+
+	/* Set internal data buffer */
+	this->data_buf = data_buf;
+	this->oob_buf = oob_buf;
+
+	/* Scan to find existence of the device (it could not be mounted) */
+	if (nand_scan (ppchameleon_mtd, 1)) {
+		iounmap((void *)ppchameleon_fio_base);
+		kfree (ppchameleon_mtd);
+		goto nand_evb_init;
+	}
+
+#ifndef USE_READY_BUSY_PIN
+	/* Adjust delay if necessary */
+	if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
+		this->chip_delay = NAND_SMALL_DELAY_US;
+#endif
+
+#ifdef CONFIG_MTD_PARTITIONS
+	ppchameleon_mtd->name = "ppchameleon-nand";
+	mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0);
+	if (mtd_parts_nb > 0)
+	  part_type = "command line";
+	else
+	  mtd_parts_nb = 0;
+#endif
+	if (mtd_parts_nb == 0)
+	{
+		if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
+			mtd_parts = partition_info_me;
+		else
+			mtd_parts = partition_info_hi;
+		mtd_parts_nb = NUM_PARTITIONS;
+		part_type = "static";
+	}
+
+	/* Register the partitions */
+	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
+	add_mtd_partitions(ppchameleon_mtd, mtd_parts, mtd_parts_nb);
+
+nand_evb_init:
+	/****************************
+	* EVB NAND (always present) *
+	****************************/
 	/* Allocate memory for MTD device structure and private data */
 	ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) +
 			     sizeof(struct nand_chip),
@@ -154,28 +340,41 @@
 		CE	GPIO_14
 		CLE	GPIO_15
 		ALE	GPIO_16
-		R/B	GPIO_31 (still not used)
+		R/B	GPIO_31
 	*/
 	/* output select */
-	out_be32(GPIO0_OSRH, in_be32(GPIO0_OSRH) & 0xFFFFFFF0);
-	out_be32(GPIO0_OSRL, in_be32(GPIO0_OSRL) & 0x3FFFFFFF);
+	out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xFFFFFFF0);
+	out_be32((volatile unsigned*)GPIO0_OSRL, in_be32((volatile unsigned*)GPIO0_OSRL) & 0x3FFFFFFF);
 	/* three-state select */
-	out_be32(GPIO0_TSRH, in_be32(GPIO0_TSRH) & 0xFFFFFFF0);
-	out_be32(GPIO0_TSRL, in_be32(GPIO0_TSRL) & 0x3FFFFFFF);
+	out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0);
+	out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0x3FFFFFFF);
 	/* enable output driver */
-	out_be32(GPIO0_TCR, in_be32(GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN);
+	out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN | NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN);
+#ifdef USE_READY_BUSY_PIN
+	/* three-state select */
+	out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0xFFFFFFFC);
+	/* high-impedecence */
+	out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) & (~NAND_EVB_RB_GPIO_PIN));
+	/* input select */
+	out_be32((volatile unsigned*)GPIO0_ISR1L, (in_be32((volatile unsigned*)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001);
+#endif
+
 
 	/* insert callbacks */
 	this->IO_ADDR_R = ppchameleonevb_fio_base;
 	this->IO_ADDR_W = ppchameleonevb_fio_base;
 	this->hwcontrol = ppchameleonevb_hwcontrol;
-	/*this->dev_ready = ppchameleonevb_device_ready;*/
-        this->dev_ready = NULL;
-	/* 12 us command delay time */
-	this->chip_delay = 12;
+#ifdef USE_READY_BUSY_PIN
+	this->dev_ready = ppchameleonevb_device_ready;
+#endif
+	this->chip_delay = NAND_SMALL_DELAY_US;
+
 	/* ECC mode */
 	this->eccmode = NAND_ECC_SOFT;
 
+	/* Set internal data buffer */
+	this->data_buf = data_buf_evb;
+	this->oob_buf = oob_buf_evb;
 
 	/* Scan to find existence of the device */
 	if (nand_scan (ppchameleonevb_mtd, 1)) {
@@ -184,21 +383,8 @@
 		return -ENXIO;
 	}
 
-
-
-	/* Allocate memory for internal data buffer */
-	this->data_buf = kmalloc (sizeof(u_char) * (ppchameleonevb_mtd->oobblock + ppchameleonevb_mtd->oobsize), GFP_KERNEL);
-	if (!this->data_buf) {
-		printk("Unable to allocate NAND data buffer for PPChameleonEVB.\n");
-		iounmap((void *)ppchameleonevb_fio_base);
-		kfree (ppchameleonevb_mtd);
-		return -ENOMEM;
-
-	}
-
-
 #ifdef CONFIG_MTD_PARTITIONS
-	ppchameleonevb_mtd->name = "ppchameleonevb-nand";
+	ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;
 	mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0);
 	if (mtd_parts_nb > 0)
 	  part_type = "command line";
@@ -207,13 +393,11 @@
 #endif
 	if (mtd_parts_nb == 0)
 	{
-		mtd_parts = partition_info;
+		mtd_parts = partition_info_evb;
 		mtd_parts_nb = NUM_PARTITIONS;
 		part_type = "static";
 	}
 
-
-
 	/* Register the partitions */
 	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
 	add_mtd_partitions(ppchameleonevb_mtd, mtd_parts, mtd_parts_nb);
@@ -242,5 +426,5 @@
 module_exit(ppchameleonevb_cleanup);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("llandre <llandre at wawnet.biz>");
+MODULE_AUTHOR("DAVE Srl <support-ppchameleon at dave-tech.it>");
 MODULE_DESCRIPTION("MTD map driver for DAVE Srl PPChameleonEVB board");




More information about the linux-mtd-cvs mailing list