Merge git://git.infradead.org/mtd-2.6

* git://git.infradead.org/mtd-2.6:
  [MTD] Cleanup of 'ioremap balanced with iounmap for drivers/mtd subsystem'
  [MTD] fix nftl_write warning
  [MTD] fix printk warning
  [MTD ONENAND] Check OneNAND lock scheme & all block unlock command support
  [MTD ONENAND] Remove unused MTD_ONENAND_SYNC_READ configuration
  [MTD ONENAND] Fix OneNAND probe
  [MTD NAND] Provide prototype for newly-exported nand_wait_ready()
  [MTD] Remove #ifndef __KERNEL__ hack in <mtd/mtd-abi.h>
  [MTD NAND] Allow override of page read and write functions.
  [MTD NAND] Allocate chip->buffers separately to allow it to be overridden
  [MTD NAND] Split nand_scan() into two parts; allow board driver to intervene
  [MTD NAND] Export nand_wait_ready() for use by board drivers
diff --git a/drivers/mtd/maps/arctic-mtd.c b/drivers/mtd/maps/arctic-mtd.c
index 642d96b..2cc9024 100644
--- a/drivers/mtd/maps/arctic-mtd.c
+++ b/drivers/mtd/maps/arctic-mtd.c
@@ -96,7 +96,7 @@
 static int __init
 init_arctic_mtd(void)
 {
-	int err = 0;
+	int err;
 
 	printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
 
@@ -112,7 +112,7 @@
 	arctic_mtd = do_map_probe("cfi_probe", &arctic_mtd_map);
 
 	if (!arctic_mtd) {
-		iounmap((void *) arctic_mtd_map.virt);
+		iounmap(arctic_mtd_map.virt);
 		return -ENXIO;
 	}
 
@@ -121,7 +121,7 @@
 	err = add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS);
 	if (err) {
 		printk("%s: add_mtd_partitions failed\n", NAME);
-		iounmap((void *) arctic_mtd_map.virt);
+		iounmap(arctic_mtd_map.virt);
 	}
 
 	return err;
diff --git a/drivers/mtd/maps/beech-mtd.c b/drivers/mtd/maps/beech-mtd.c
index a64b1a5..d76d598 100644
--- a/drivers/mtd/maps/beech-mtd.c
+++ b/drivers/mtd/maps/beech-mtd.c
@@ -72,7 +72,7 @@
 static int __init
 init_beech_mtd(void)
 {
-	int err = 0;
+	int err;
 
 	printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
 
@@ -89,7 +89,7 @@
 	beech_mtd = do_map_probe("cfi_probe", &beech_mtd_map);
 
 	if (!beech_mtd) {
-		iounmap((void *) beech_mtd_map.virt);
+		iounmap(beech_mtd_map.virt);
 		return -ENXIO;
 	}
 
@@ -98,7 +98,7 @@
 	err = add_mtd_partitions(beech_mtd, beech_partitions, 2);
 	if (err) {
 		printk("%s: add_mtd_partitions failed\n", NAME);
-		iounmap((void *) beech_mtd_map.virt);
+		iounmap(beech_mtd_map.virt);
 	}
 
 	return err;
diff --git a/drivers/mtd/maps/cstm_mips_ixx.c b/drivers/mtd/maps/cstm_mips_ixx.c
index d6bef10..df2c38e 100644
--- a/drivers/mtd/maps/cstm_mips_ixx.c
+++ b/drivers/mtd/maps/cstm_mips_ixx.c
@@ -175,8 +175,8 @@
 			printk(KERN_WARNING "Failed to ioremap\n");
 			for (j = 0; j < i; j++) {
 				if (cstm_mips_ixx_map[j].virt) {
-					iounmap((void *)cstm_mips_ixx_map[j].virt);
-					cstm_mips_ixx_map[j].virt = 0;
+					iounmap(cstm_mips_ixx_map[j].virt);
+					cstm_mips_ixx_map[j].virt = NULL;
 				}
 			}
 			return -EIO;
@@ -214,8 +214,8 @@
 		else {
 			for (i = 0; i < PHYSMAP_NUMBER; i++) {
 				if (cstm_mips_ixx_map[i].virt) {
-					iounmap((void *)cstm_mips_ixx_map[i].virt);
-					cstm_mips_ixx_map[i].virt = 0;
+					iounmap(cstm_mips_ixx_map[i].virt);
+					cstm_mips_ixx_map[i].virt = NULL;
 				}
 			}
 			return -ENXIO;
diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c
index 198e840..f9e8e5b 100644
--- a/drivers/mtd/maps/nettel.c
+++ b/drivers/mtd/maps/nettel.c
@@ -463,7 +463,7 @@
 
 #ifdef CONFIG_MTD_CFI_INTELEXT
 out_unmap1:
-	iounmap((void *) nettel_intel_map.virt);
+	iounmap(nettel_intel_map.virt);
 #endif
 
 out_unmap2:
diff --git a/drivers/mtd/maps/redwood.c b/drivers/mtd/maps/redwood.c
index 2257d2b..4d858b3 100644
--- a/drivers/mtd/maps/redwood.c
+++ b/drivers/mtd/maps/redwood.c
@@ -126,7 +126,7 @@
 
 int __init init_redwood_flash(void)
 {
-	int err = 0;
+	int err;
 
 	printk(KERN_NOTICE "redwood: flash mapping: %x at %x\n",
 			WINDOW_SIZE, WINDOW_ADDR);
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 6baf5fe..178b53b 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -69,7 +69,7 @@
 		return 1;
 
 	default:
-		printk(KERN_NOTICE "Unknown request %ld\n", rq_data_dir(req));
+		printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req));
 		return 0;
 	}
 }
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c
index 12017f3..1daf823 100644
--- a/drivers/mtd/nand/edb7312.c
+++ b/drivers/mtd/nand/edb7312.c
@@ -199,7 +199,7 @@
 	nand_release(ap7312_mtd);
 
 	/* Release io resource */
-	iounmap((void *)this->IO_ADDR_R);
+	iounmap(this->IO_ADDR_R);
 
 	/* Free the MTD device structure */
 	kfree(ep7312_mtd);
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 975b2ef..baece61 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -415,7 +415,7 @@
  * Wait for the ready pin, after a command
  * The timeout is catched later.
  */
-static void nand_wait_ready(struct mtd_info *mtd)
+void nand_wait_ready(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
 	unsigned long timeo = jiffies + 2;
@@ -429,6 +429,7 @@
 	} while (time_before(jiffies, timeo));
 	led_trigger_event(nand_led_trigger, LED_OFF);
 }
+EXPORT_SYMBOL_GPL(nand_wait_ready);
 
 /**
  * nand_command - [DEFAULT] Send command to NAND device
@@ -766,8 +767,8 @@
 	int eccbytes = chip->ecc.bytes;
 	int eccsteps = chip->ecc.steps;
 	uint8_t *p = buf;
-	uint8_t *ecc_calc = chip->buffers.ecccalc;
-	uint8_t *ecc_code = chip->buffers.ecccode;
+	uint8_t *ecc_calc = chip->buffers->ecccalc;
+	uint8_t *ecc_code = chip->buffers->ecccode;
 	int *eccpos = chip->ecc.layout->eccpos;
 
 	nand_read_page_raw(mtd, chip, buf);
@@ -808,8 +809,8 @@
 	int eccbytes = chip->ecc.bytes;
 	int eccsteps = chip->ecc.steps;
 	uint8_t *p = buf;
-	uint8_t *ecc_calc = chip->buffers.ecccalc;
-	uint8_t *ecc_code = chip->buffers.ecccode;
+	uint8_t *ecc_calc = chip->buffers->ecccalc;
+	uint8_t *ecc_code = chip->buffers->ecccode;
 	int *eccpos = chip->ecc.layout->eccpos;
 
 	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
@@ -970,7 +971,7 @@
 	page = realpage & chip->pagemask;
 
 	col = (int)(from & (mtd->writesize - 1));
-	chip->oob_poi = chip->buffers.oobrbuf;
+	chip->oob_poi = chip->buffers->oobrbuf;
 
 	buf = ops->datbuf;
 	oob = ops->oobbuf;
@@ -981,7 +982,7 @@
 
 		/* Is the current page in the buffer ? */
 		if (realpage != chip->pagebuf || oob) {
-			bufpoi = aligned ? buf : chip->buffers.databuf;
+			bufpoi = aligned ? buf : chip->buffers->databuf;
 
 			if (likely(sndcmd)) {
 				chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
@@ -989,14 +990,17 @@
 			}
 
 			/* Now read the page into the buffer */
-			ret = chip->ecc.read_page(mtd, chip, bufpoi);
+			if (unlikely(ops->mode == MTD_OOB_RAW))
+				ret = chip->ecc.read_page_raw(mtd, chip, bufpoi);
+			else
+				ret = chip->ecc.read_page(mtd, chip, bufpoi);
 			if (ret < 0)
 				break;
 
 			/* Transfer not aligned data */
 			if (!aligned) {
 				chip->pagebuf = realpage;
-				memcpy(buf, chip->buffers.databuf + col, bytes);
+				memcpy(buf, chip->buffers->databuf + col, bytes);
 			}
 
 			buf += bytes;
@@ -1023,7 +1027,7 @@
 					nand_wait_ready(mtd);
 			}
 		} else {
-			memcpy(buf, chip->buffers.databuf + col, bytes);
+			memcpy(buf, chip->buffers->databuf + col, bytes);
 			buf += bytes;
 		}
 
@@ -1266,7 +1270,7 @@
 	realpage = (int)(from >> chip->page_shift);
 	page = realpage & chip->pagemask;
 
-	chip->oob_poi = chip->buffers.oobrbuf;
+	chip->oob_poi = chip->buffers->oobrbuf;
 
 	while(1) {
 		sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
@@ -1322,8 +1326,6 @@
 static int nand_read_oob(struct mtd_info *mtd, loff_t from,
 			 struct mtd_oob_ops *ops)
 {
-	int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
-			 uint8_t *buf) = NULL;
 	struct nand_chip *chip = mtd->priv;
 	int ret = -ENOTSUPP;
 
@@ -1341,12 +1343,7 @@
 	switch(ops->mode) {
 	case MTD_OOB_PLACE:
 	case MTD_OOB_AUTO:
-		break;
-
 	case MTD_OOB_RAW:
-		/* Replace the read_page algorithm temporary */
-		read_page = chip->ecc.read_page;
-		chip->ecc.read_page = nand_read_page_raw;
 		break;
 
 	default:
@@ -1358,8 +1355,6 @@
 	else
 		ret = nand_do_read_ops(mtd, from, ops);
 
-	if (unlikely(ops->mode == MTD_OOB_RAW))
-		chip->ecc.read_page = read_page;
  out:
 	nand_release_device(mtd);
 	return ret;
@@ -1391,7 +1386,7 @@
 	int i, eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
 	int eccsteps = chip->ecc.steps;
-	uint8_t *ecc_calc = chip->buffers.ecccalc;
+	uint8_t *ecc_calc = chip->buffers->ecccalc;
 	const uint8_t *p = buf;
 	int *eccpos = chip->ecc.layout->eccpos;
 
@@ -1417,7 +1412,7 @@
 	int i, eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
 	int eccsteps = chip->ecc.steps;
-	uint8_t *ecc_calc = chip->buffers.ecccalc;
+	uint8_t *ecc_calc = chip->buffers->ecccalc;
 	const uint8_t *p = buf;
 	int *eccpos = chip->ecc.layout->eccpos;
 
@@ -1478,7 +1473,7 @@
 }
 
 /**
- * nand_write_page - [INTERNAL] write one page
+ * nand_write_page - [REPLACEABLE] write one page
  * @mtd:	MTD device structure
  * @chip:	NAND chip descriptor
  * @buf:	the data to write
@@ -1486,13 +1481,16 @@
  * @cached:	cached programming
  */
 static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
-			   const uint8_t *buf, int page, int cached)
+			   const uint8_t *buf, int page, int cached, int raw)
 {
 	int status;
 
 	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
 
-	chip->ecc.write_page(mtd, chip, buf);
+	if (unlikely(raw))
+		chip->ecc.write_page_raw(mtd, chip, buf);
+	else
+		chip->ecc.write_page(mtd, chip, buf);
 
 	/*
 	 * Cached progamming disabled for now, Not sure if its worth the
@@ -1627,7 +1625,7 @@
 	    (chip->pagebuf << chip->page_shift) < (to + ops->len))
 		chip->pagebuf = -1;
 
-	chip->oob_poi = chip->buffers.oobwbuf;
+	chip->oob_poi = chip->buffers->oobwbuf;
 
 	while(1) {
 		int cached = writelen > bytes && page != blockmask;
@@ -1635,7 +1633,8 @@
 		if (unlikely(oob))
 			oob = nand_fill_oob(chip, oob, ops);
 
-		ret = nand_write_page(mtd, chip, buf, page, cached);
+		ret = chip->write_page(mtd, chip, buf, page, cached,
+				       (ops->mode == MTD_OOB_RAW));
 		if (ret)
 			break;
 
@@ -1745,7 +1744,7 @@
 	if (page == chip->pagebuf)
 		chip->pagebuf = -1;
 
-	chip->oob_poi = chip->buffers.oobwbuf;
+	chip->oob_poi = chip->buffers->oobwbuf;
 	memset(chip->oob_poi, 0xff, mtd->oobsize);
 	nand_fill_oob(chip, ops->oobbuf, ops);
 	status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
@@ -1768,8 +1767,6 @@
 static int nand_write_oob(struct mtd_info *mtd, loff_t to,
 			  struct mtd_oob_ops *ops)
 {
-	void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
-			  const uint8_t *buf) = NULL;
 	struct nand_chip *chip = mtd->priv;
 	int ret = -ENOTSUPP;
 
@@ -1787,12 +1784,7 @@
 	switch(ops->mode) {
 	case MTD_OOB_PLACE:
 	case MTD_OOB_AUTO:
-		break;
-
 	case MTD_OOB_RAW:
-		/* Replace the write_page algorithm temporary */
-		write_page = chip->ecc.write_page;
-		chip->ecc.write_page = nand_write_page_raw;
 		break;
 
 	default:
@@ -1804,8 +1796,6 @@
 	else
 		ret = nand_do_write_ops(mtd, to, ops);
 
-	if (unlikely(ops->mode == MTD_OOB_RAW))
-		chip->ecc.write_page = write_page;
  out:
 	nand_release_device(mtd);
 	return ret;
@@ -2288,40 +2278,22 @@
 	return type;
 }
 
-/* module_text_address() isn't exported, and it's mostly a pointless
-   test if this is a module _anyway_ -- they'd have to try _really_ hard
-   to call us from in-kernel code if the core NAND support is modular. */
-#ifdef MODULE
-#define caller_is_module() (1)
-#else
-#define caller_is_module() \
-	module_text_address((unsigned long)__builtin_return_address(0))
-#endif
-
 /**
- * nand_scan - [NAND Interface] Scan for the NAND device
- * @mtd:	MTD device structure
- * @maxchips:	Number of chips to scan for
+ * nand_scan_ident - [NAND Interface] Scan for the NAND device
+ * @mtd:	     MTD device structure
+ * @maxchips:	     Number of chips to scan for
  *
- * This fills out all the uninitialized function pointers
- * with the defaults.
- * The flash ID is read and the mtd/chip structures are
- * filled with the appropriate values.
- * The mtd->owner field must be set to the module of the caller
+ * This is the first phase of the normal nand_scan() function. It
+ * reads the flash ID and sets up MTD fields accordingly.
  *
+ * The mtd->owner field must be set to the module of the caller.
  */
-int nand_scan(struct mtd_info *mtd, int maxchips)
+int nand_scan_ident(struct mtd_info *mtd, int maxchips)
 {
 	int i, busw, nand_maf_id;
 	struct nand_chip *chip = mtd->priv;
 	struct nand_flash_dev *type;
 
-	/* Many callers got this wrong, so check for it for a while... */
-	if (!mtd->owner && caller_is_module()) {
-		printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
-		BUG();
-	}
-
 	/* Get buswidth to select the correct functions */
 	busw = chip->options & NAND_BUSWIDTH_16;
 	/* Set the default functions */
@@ -2353,8 +2325,31 @@
 	chip->numchips = i;
 	mtd->size = i * chip->chipsize;
 
+	return 0;
+}
+
+
+/**
+ * nand_scan_tail - [NAND Interface] Scan for the NAND device
+ * @mtd:	    MTD device structure
+ * @maxchips:	    Number of chips to scan for
+ *
+ * This is the second phase of the normal nand_scan() function. It
+ * fills out all the uninitialized function pointers with the defaults
+ * and scans for a bad block table if appropriate.
+ */
+int nand_scan_tail(struct mtd_info *mtd)
+{
+	int i;
+	struct nand_chip *chip = mtd->priv;
+
+	if (!(chip->options & NAND_OWN_BUFFERS))
+		chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL);
+	if (!chip->buffers)
+		return -ENOMEM;
+
 	/* Preset the internal oob write buffer */
-	memset(chip->buffers.oobwbuf, 0xff, mtd->oobsize);
+	memset(chip->buffers->oobwbuf, 0xff, mtd->oobsize);
 
 	/*
 	 * If no default placement scheme is given, select an appropriate one
@@ -2377,10 +2372,18 @@
 		}
 	}
 
+	if (!chip->write_page)
+		chip->write_page = nand_write_page;
+
 	/*
 	 * check ECC mode, default to software if 3byte/512byte hardware ECC is
 	 * selected and we have 256 byte pagesize fallback to software ECC
 	 */
+	if (!chip->ecc.read_page_raw)
+		chip->ecc.read_page_raw = nand_read_page_raw;
+	if (!chip->ecc.write_page_raw)
+		chip->ecc.write_page_raw = nand_write_page_raw;
+
 	switch (chip->ecc.mode) {
 	case NAND_ECC_HW:
 		/* Use standard hwecc read page function ? */
@@ -2438,6 +2441,7 @@
 		chip->ecc.size = mtd->writesize;
 		chip->ecc.bytes = 0;
 		break;
+
 	default:
 		printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
 		       chip->ecc.mode);
@@ -2503,6 +2507,44 @@
 	return chip->scan_bbt(mtd);
 }
 
+/* module_text_address() isn't exported, and it's mostly a pointless
+   test if this is a module _anyway_ -- they'd have to try _really_ hard
+   to call us from in-kernel code if the core NAND support is modular. */
+#ifdef MODULE
+#define caller_is_module() (1)
+#else
+#define caller_is_module() \
+	module_text_address((unsigned long)__builtin_return_address(0))
+#endif
+
+/**
+ * nand_scan - [NAND Interface] Scan for the NAND device
+ * @mtd:	MTD device structure
+ * @maxchips:	Number of chips to scan for
+ *
+ * This fills out all the uninitialized function pointers
+ * with the defaults.
+ * The flash ID is read and the mtd/chip structures are
+ * filled with the appropriate values.
+ * The mtd->owner field must be set to the module of the caller
+ *
+ */
+int nand_scan(struct mtd_info *mtd, int maxchips)
+{
+	int ret;
+
+	/* Many callers got this wrong, so check for it for a while... */
+	if (!mtd->owner && caller_is_module()) {
+		printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
+		BUG();
+	}
+
+	ret = nand_scan_ident(mtd, maxchips);
+	if (!ret)
+		ret = nand_scan_tail(mtd);
+	return ret;
+}
+
 /**
  * nand_release - [NAND Interface] Free resources held by the NAND device
  * @mtd:	MTD device structure
@@ -2520,9 +2562,13 @@
 
 	/* Free bad block table memory */
 	kfree(chip->bbt);
+	if (!(chip->options & NAND_OWN_BUFFERS))
+		kfree(chip->buffers);
 }
 
 EXPORT_SYMBOL_GPL(nand_scan);
+EXPORT_SYMBOL_GPL(nand_scan_ident);
+EXPORT_SYMBOL_GPL(nand_scan_tail);
 EXPORT_SYMBOL_GPL(nand_release);
 
 static int __init nand_base_init(void)
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index a612c4e..9402653 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -759,7 +759,7 @@
 	struct nand_chip *this = mtd->priv;
 
 	bd->options &= ~NAND_BBT_SCANEMPTY;
-	return create_bbt(mtd, this->buffers.databuf, bd, -1);
+	return create_bbt(mtd, this->buffers->databuf, bd, -1);
 }
 
 /**
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index dd5cea8..b5a5f8d 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -175,6 +175,8 @@
 	return res;
 }
 
+#ifdef CONFIG_NFTL_RW
+
 /*
  * Write data and oob to flash
  */
@@ -196,8 +198,6 @@
 	return res;
 }
 
-#ifdef CONFIG_NFTL_RW
-
 /* Actual NFTL access routines */
 /* NFTL_findfreeblock: Find a free Erase Unit on the NFTL partition. This function is used
  *	when the give Virtual Unit Chain
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
index 5930a03..465961b 100644
--- a/drivers/mtd/onenand/Kconfig
+++ b/drivers/mtd/onenand/Kconfig
@@ -43,10 +43,4 @@
 
 	  OTP block is fully-guaranteed to be a valid block.
 
-config MTD_ONENAND_SYNC_READ
-	bool "OneNAND Sync. Burst Read Support"
-	depends on ARCH_OMAP
-	help
-	  This enables support for Sync. Burst Read.
-
 endmenu
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 84ec40d..8ed68b2 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mtd/onenand/onenand_base.c
  *
- *  Copyright (C) 2005 Samsung Electronics
+ *  Copyright (C) 2005-2006 Samsung Electronics
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -199,6 +199,7 @@
 	case ONENAND_CMD_UNLOCK:
 	case ONENAND_CMD_LOCK:
 	case ONENAND_CMD_LOCK_TIGHT:
+	case ONENAND_CMD_UNLOCK_ALL:
 		block = -1;
 		page = -1;
 		break;
@@ -1211,11 +1212,11 @@
 	end = len >> this->erase_shift;
 
 	/* Continuous lock scheme */
-	if (this->options & ONENAND_CONT_LOCK) {
+	if (this->options & ONENAND_HAS_CONT_LOCK) {
 		/* Set start block address */
 		this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
 		/* Set end block address */
-		this->write_word(end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS);
+		this->write_word(start + end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS);
 		/* Write unlock command */
 		this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0);
 
@@ -1236,7 +1237,7 @@
 	}
 
 	/* Block lock scheme */
-	for (block = start; block < end; block++) {
+	for (block = start; block < start + end; block++) {
 		/* Set block address */
 		value = onenand_block_address(this, block);
 		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
@@ -1265,6 +1266,79 @@
 	return 0;
 }
 
+/**
+ * onenand_check_lock_status - [OneNAND Interface] Check lock status
+ * @param this		onenand chip data structure
+ *
+ * Check lock status
+ */
+static void onenand_check_lock_status(struct onenand_chip *this)
+{
+	unsigned int value, block, status;
+	unsigned int end;
+
+	end = this->chipsize >> this->erase_shift;
+	for (block = 0; block < end; block++) {
+		/* Set block address */
+		value = onenand_block_address(this, block);
+		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
+		/* Select DataRAM for DDP */
+		value = onenand_bufferram_address(this, block);
+		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
+		/* Set start block address */
+		this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
+
+		/* Check lock status */
+		status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
+		if (!(status & ONENAND_WP_US))
+			printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
+	}
+}
+
+/**
+ * onenand_unlock_all - [OneNAND Interface] unlock all blocks
+ * @param mtd		MTD device structure
+ *
+ * Unlock all blocks
+ */
+static int onenand_unlock_all(struct mtd_info *mtd)
+{
+	struct onenand_chip *this = mtd->priv;
+
+	if (this->options & ONENAND_HAS_UNLOCK_ALL) {
+		/* Write unlock command */
+		this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);
+
+		/* There's no return value */
+		this->wait(mtd, FL_UNLOCKING);
+
+		/* Sanity check */
+		while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
+		    & ONENAND_CTRL_ONGO)
+			continue;
+
+		/* Workaround for all block unlock in DDP */
+		if (this->device_id & ONENAND_DEVICE_IS_DDP) {
+			loff_t ofs;
+			size_t len;
+
+			/* 1st block on another chip */
+			ofs = this->chipsize >> 1;
+			len = 1 << this->erase_shift;
+
+			onenand_unlock(mtd, ofs, len);
+		}
+
+		onenand_check_lock_status(this);
+
+		return 0;
+	}
+
+	mtd->unlock(mtd, 0x0, this->chipsize);
+
+	return 0;
+}
+
 #ifdef CONFIG_MTD_ONENAND_OTP
 
 /* Interal OTP operation */
@@ -1564,12 +1638,43 @@
 #endif	/* CONFIG_MTD_ONENAND_OTP */
 
 /**
+ * onenand_lock_scheme - Check and set OneNAND lock scheme
+ * @param mtd		MTD data structure
+ *
+ * Check and set OneNAND lock scheme
+ */
+static void onenand_lock_scheme(struct mtd_info *mtd)
+{
+	struct onenand_chip *this = mtd->priv;
+	unsigned int density, process;
+
+	/* Lock scheme depends on density and process */
+	density = this->device_id >> ONENAND_DEVICE_DENSITY_SHIFT;
+	process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT;
+
+	/* Lock scheme */
+	if (density >= ONENAND_DEVICE_DENSITY_1Gb) {
+		/* A-Die has all block unlock */
+		if (process) {
+			printk(KERN_DEBUG "Chip support all block unlock\n");
+			this->options |= ONENAND_HAS_UNLOCK_ALL;
+		}
+	} else {
+		/* Some OneNAND has continues lock scheme */
+		if (!process) {
+			printk(KERN_DEBUG "Lock scheme is Continues Lock\n");
+			this->options |= ONENAND_HAS_CONT_LOCK;
+		}
+	}
+}
+
+/**
  * onenand_print_device_info - Print device ID
  * @param device        device ID
  *
  * Print device ID
  */
-static void onenand_print_device_info(int device)
+static void onenand_print_device_info(int device, int version)
 {
         int vcc, demuxed, ddp, density;
 
@@ -1583,6 +1688,7 @@
                 (16 << density),
                 vcc ? "2.65/3.3" : "1.8",
                 device);
+	printk(KERN_DEBUG "OneNAND version = 0x%04x\n", version);
 }
 
 static const struct onenand_manufacturers onenand_manuf_ids[] = {
@@ -1625,9 +1731,14 @@
 static int onenand_probe(struct mtd_info *mtd)
 {
 	struct onenand_chip *this = mtd->priv;
-	int bram_maf_id, bram_dev_id, maf_id, dev_id;
-	int version_id;
+	int bram_maf_id, bram_dev_id, maf_id, dev_id, ver_id;
 	int density;
+	int syscfg;
+
+	/* Save system configuration 1 */
+	syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
+	/* Clear Sync. Burst Read mode to read BootRAM */
+	this->write_word((syscfg & ~ONENAND_SYS_CFG1_SYNC_READ), this->base + ONENAND_REG_SYS_CFG1);
 
 	/* Send the command for reading device ID from BootRAM */
 	this->write_word(ONENAND_CMD_READID, this->base + ONENAND_BOOTRAM);
@@ -1636,24 +1747,31 @@
 	bram_maf_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x0);
 	bram_dev_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x2);
 
+	/* Reset OneNAND to read default register values */
+	this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
+	/* Wait reset */
+	this->wait(mtd, FL_RESETING);
+
+	/* Restore system configuration 1 */
+	this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
+
 	/* Check manufacturer ID */
 	if (onenand_check_maf(bram_maf_id))
 		return -ENXIO;
 
-	/* Reset OneNAND to read default register values */
-	this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
-
 	/* Read manufacturer and device IDs from Register */
 	maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
 	dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
+	ver_id= this->read_word(this->base + ONENAND_REG_VERSION_ID);
 
 	/* Check OneNAND device */
 	if (maf_id != bram_maf_id || dev_id != bram_dev_id)
 		return -ENXIO;
 
 	/* Flash device information */
-	onenand_print_device_info(dev_id);
+	onenand_print_device_info(dev_id, ver_id);
 	this->device_id = dev_id;
+	this->version_id = ver_id;
 
 	density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
 	this->chipsize = (16 << density) << 20;
@@ -1676,16 +1794,8 @@
 
 	mtd->size = this->chipsize;
 
-	/* Version ID */
-	version_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
-	printk(KERN_DEBUG "OneNAND version = 0x%04x\n", version_id);
-
-	/* Lock scheme */
-	if (density <= ONENAND_DEVICE_DENSITY_512Mb &&
-	    !(version_id >> ONENAND_VERSION_PROCESS_SHIFT)) {
-		printk(KERN_INFO "Lock scheme is Continues Lock\n");
-		this->options |= ONENAND_CONT_LOCK;
-	}
+	/* Check OneNAND lock scheme */
+	onenand_lock_scheme(mtd);
 
 	return 0;
 }
@@ -1821,7 +1931,7 @@
 	mtd->owner = THIS_MODULE;
 
 	/* Unlock whole block */
-	mtd->unlock(mtd, 0x0, this->chipsize);
+	onenand_unlock_all(mtd);
 
 	return this->scan_bbt(mtd);
 }
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 0b4cd2f..70420bb 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -27,9 +27,17 @@
 struct mtd_info;
 /* Scan and identify a NAND device */
 extern int nand_scan (struct mtd_info *mtd, int max_chips);
+/* Separate phases of nand_scan(), allowing board driver to intervene
+ * and override command or ECC setup according to flash type */
+extern int nand_scan_ident(struct mtd_info *mtd, int max_chips);
+extern int nand_scan_tail(struct mtd_info *mtd);
+
 /* Free resources held by the NAND device */
 extern void nand_release (struct mtd_info *mtd);
 
+/* Internal helper for board drivers which need to override command function */
+extern void nand_wait_ready(struct mtd_info *mtd);
+
 /* The maximum number of NAND chips in an array */
 #define NAND_MAX_CHIPS		8
 
@@ -178,7 +186,9 @@
 #define NAND_USE_FLASH_BBT	0x00010000
 /* This option skips the bbt scan during initialization. */
 #define NAND_SKIP_BBTSCAN	0x00020000
-
+/* This option is defined if the board driver allocates its own buffers
+   (e.g. because it needs them DMA-coherent */
+#define NAND_OWN_BUFFERS	0x00040000
 /* Options set by nand scan */
 /* Nand scan has allocated controller struct */
 #define NAND_CONTROLLER_ALLOC	0x80000000
@@ -228,6 +238,8 @@
  *		be provided if an hardware ECC is available
  * @calculate:	function for ecc calculation or readback from ecc hardware
  * @correct:	function for ecc correction, matching to ecc generator (sw/hw)
+ * @read_page_raw:	function to read a raw page without ECC
+ * @write_page_raw:	function to write a raw page without ECC
  * @read_page:	function to read a page according to the ecc generator requirements
  * @write_page:	function to write a page according to the ecc generator requirements
  * @read_oob:	function to read chip OOB data
@@ -249,6 +261,12 @@
 	int			(*correct)(struct mtd_info *mtd, uint8_t *dat,
 					   uint8_t *read_ecc,
 					   uint8_t *calc_ecc);
+	int			(*read_page_raw)(struct mtd_info *mtd,
+						 struct nand_chip *chip,
+						 uint8_t *buf);
+	void			(*write_page_raw)(struct mtd_info *mtd,
+						  struct nand_chip *chip,
+						  const uint8_t *buf);
 	int			(*read_page)(struct mtd_info *mtd,
 					     struct nand_chip *chip,
 					     uint8_t *buf);
@@ -337,6 +355,7 @@
  * @priv:		[OPTIONAL] pointer to private chip date
  * @errstat:		[OPTIONAL] hardware specific function to perform additional error status checks
  *			(determine if errors are correctable)
+ * @write_page		[REPLACEABLE] High-level page write function
  */
 
 struct nand_chip {
@@ -359,6 +378,8 @@
 	void		(*erase_cmd)(struct mtd_info *mtd, int page);
 	int		(*scan_bbt)(struct mtd_info *mtd);
 	int		(*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
+	int		(*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
+				      const uint8_t *buf, int page, int cached, int raw);
 
 	int		chip_delay;
 	unsigned int	options;
@@ -380,7 +401,7 @@
 	struct nand_ecclayout	*ecclayout;
 
 	struct nand_ecc_ctrl ecc;
-	struct nand_buffers buffers;
+	struct nand_buffers *buffers;
 	struct nand_hw_control hwcontrol;
 
 	struct mtd_oob_ops ops;
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 1f49721..6f045b5 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -1,7 +1,7 @@
 /*
  *  linux/include/linux/mtd/onenand.h
  *
- *  Copyright (C) 2005 Samsung Electronics
+ *  Copyright (C) 2005-2006 Samsung Electronics
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -96,6 +96,7 @@
 	void __iomem		*base;
 	unsigned int		chipsize;
 	unsigned int		device_id;
+	unsigned int		version_id;
 	unsigned int		density_mask;
 	unsigned int		options;
 
@@ -149,7 +150,8 @@
 /*
  * Options bits
  */
-#define ONENAND_CONT_LOCK		(0x0001)
+#define ONENAND_HAS_CONT_LOCK		(0x0001)
+#define ONENAND_HAS_UNLOCK_ALL		(0x0002)
 #define ONENAND_PAGEBUF_ALLOC		(0x1000)
 
 /*
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
index 4a72818..9e409fe 100644
--- a/include/linux/mtd/onenand_regs.h
+++ b/include/linux/mtd/onenand_regs.h
@@ -3,7 +3,7 @@
  *
  *  OneNAND Register header file
  *
- *  Copyright (C) 2005 Samsung Electronics
+ *  Copyright (C) 2005-2006 Samsung Electronics
  *
  * 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
@@ -72,6 +72,7 @@
 #define ONENAND_DEVICE_VCC_MASK		(0x3)
 
 #define ONENAND_DEVICE_DENSITY_512Mb	(0x002)
+#define ONENAND_DEVICE_DENSITY_1Gb	(0x003)
 
 /*
  * Version ID Register F002h (R)
@@ -110,6 +111,7 @@
 #define ONENAND_CMD_UNLOCK		(0x23)
 #define ONENAND_CMD_LOCK		(0x2A)
 #define ONENAND_CMD_LOCK_TIGHT		(0x2C)
+#define ONENAND_CMD_UNLOCK_ALL		(0x27)
 #define ONENAND_CMD_ERASE		(0x94)
 #define ONENAND_CMD_RESET		(0xF0)
 #define ONENAND_CMD_OTP_ACCESS		(0x65)
diff --git a/include/mtd/Kbuild b/include/mtd/Kbuild
index 13e7a3c..e0fe92b 100644
--- a/include/mtd/Kbuild
+++ b/include/mtd/Kbuild
@@ -1,6 +1,5 @@
 header-y += inftl-user.h
 header-y += jffs2-user.h
+header-y += mtd-abi.h
 header-y += mtd-user.h
 header-y += nftl-user.h
-
-unifdef-y += mtd-abi.h
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index b0a67b7..f913c30 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -7,12 +7,6 @@
 #ifndef __MTD_ABI_H__
 #define __MTD_ABI_H__
 
-#ifndef __KERNEL__ 
-/* Urgh. The whole point of splitting this out into
-   separate files was to avoid #ifdef __KERNEL__ */
-#define __user
-#endif
-
 struct erase_info_user {
 	uint32_t start;
 	uint32_t length;