From nico at infradead.org  Wed Feb  8 11:46:39 2006
From: nico at infradead.org (Nicolas Pitre)
Date: Mon May 15 21:53:30 2006
Subject: mtd/drivers/mtd/chips cfi_cmdset_0001.c,1.188,1.189
Message-ID: <E1F6sSl-0006bV-F0@phoenix.infradead.org>

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

Modified Files:
	cfi_cmdset_0001.c 
Log Message:
[MTD] cfi_cmdset_0001: fix range for cache invalidation

From: Alexey Korolev <alexey.korolev@intel.com>

I found issue in cfi_cmdset0001.c. It related to setting up of cache
regions for invalidating in buffered write procedure.
Code performs cache invalidation from "cmd_addr" to "cmd_adr + len" in
do_write_buffer function. In fact we modify region from "adr" to
"adr+len".
The issue affects when you try to write and read data by small chunks.

Signed-off-by: Nicolas Pitre <nico@cam.org>


Index: cfi_cmdset_0001.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_cmdset_0001.c,v
retrieving revision 1.188
retrieving revision 1.189
diff -u -r1.188 -r1.189
--- cfi_cmdset_0001.c	6 Dec 2005 17:28:16 -0000	1.188
+++ cfi_cmdset_0001.c	8 Feb 2006 16:46:35 -0000	1.189
@@ -1019,8 +1019,8 @@
 #define XIP_INVAL_CACHED_RANGE(map, from, size)  \
 	INVALIDATE_CACHED_RANGE(map, from, size)
 
-#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec)  \
-	UDELAY(map, chip, adr, usec)
+#define INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, adr, len, usec)  \
+	UDELAY(map, chip, cmd_adr, usec)
 
 /*
  * Extra notes:
@@ -1052,7 +1052,7 @@
 	spin_lock(chip->mutex);  \
 } while (0)
 
-#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec)  \
+#define INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, adr, len, usec)  \
 do {  \
 	spin_unlock(chip->mutex);  \
 	INVALIDATE_CACHED_RANGE(map, adr, len);  \
@@ -1284,7 +1284,7 @@
 	map_write(map, datum, adr);
 	chip->state = mode;
 
-	INVALIDATE_CACHE_UDELAY(map, chip,
+	INVALIDATE_CACHE_UDELAY(map, chip, adr,
 				adr, map_bankwidth(map),
 				chip->word_write_time);
 
@@ -1572,8 +1572,8 @@
 	map_write(map, CMD(0xd0), cmd_adr);
 	chip->state = FL_WRITING;
 
-	INVALIDATE_CACHE_UDELAY(map, chip,
-				cmd_adr, len,
+	INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr,
+				adr, len,
 				chip->buffer_write_time);
 
 	timeo = jiffies + (HZ/2);
@@ -1749,7 +1749,7 @@
 	chip->state = FL_ERASING;
 	chip->erase_suspended = 0;
 
-	INVALIDATE_CACHE_UDELAY(map, chip,
+	INVALIDATE_CACHE_UDELAY(map, chip, adr,
 				adr, len,
 				chip->erase_time*1000/2);
 



From dwmw2 at infradead.org  Thu Feb  9 11:12:28 2006
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon May 15 21:53:30 2006
Subject: mtd/include/linux config.h,1.7,1.8
Message-ID: <E1F7EPE-0007UQ-0P@phoenix.infradead.org>

Update of /home/cvs/mtd/include/linux
In directory phoenix.infradead.org:/tmp/cvs-serv28771/include/linux

Modified Files:
	config.h 
Log Message:
summary by default

Index: config.h
===================================================================
RCS file: /home/cvs/mtd/include/linux/config.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- config.h	9 Feb 2005 09:23:55 -0000	1.7
+++ config.h	9 Feb 2006 16:12:24 -0000	1.8
@@ -36,6 +36,7 @@
 
 #ifndef NONAND
 #define CONFIG_JFFS2_FS_WRITEBUFFER 1
+#define CONFIG_JFFS2_SUMMARY 1
 #endif
 
 #endif /* __MTD_CONFIG_H__ */



From dwmw2 at infradead.org  Thu Feb  9 11:12:42 2006
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon May 15 21:53:30 2006
Subject: mtd/include/mtd mtd-abi.h,1.13,1.14
Message-ID: <E1F7EPS-0007Uw-Fg@phoenix.infradead.org>

Update of /home/cvs/mtd/include/mtd
In directory phoenix.infradead.org:/tmp/cvs-serv28801/include/mtd

Modified Files:
	mtd-abi.h 
Log Message:
BLOCK type

Index: mtd-abi.h
===================================================================
RCS file: /home/cvs/mtd/include/mtd/mtd-abi.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- mtd-abi.h	7 Nov 2005 11:14:56 -0000	1.13
+++ mtd-abi.h	9 Feb 2006 16:12:39 -0000	1.14
@@ -30,6 +30,7 @@
 #define MTD_NANDFLASH		4
 #define MTD_PEROM		5
 #define MTD_DATAFLASH		6
+#define MTD_BLOCK		7
 #define MTD_OTHER		14
 #define MTD_UNKNOWN		15
 



From dwmw2 at infradead.org  Thu Feb  9 11:12:43 2006
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon May 15 21:53:30 2006
Subject: mtd/drivers/mtd/devices block2mtd.c,1.30,1.31
Message-ID: <E1F7EPT-0007V0-1V@phoenix.infradead.org>

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

Modified Files:
	block2mtd.c 
Log Message:
BLOCK type

Index: block2mtd.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/devices/block2mtd.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- block2mtd.c	29 Nov 2005 14:48:32 -0000	1.30
+++ block2mtd.c	9 Feb 2006 16:12:40 -0000	1.31
@@ -323,7 +323,7 @@
 
 	dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
 	dev->mtd.erasesize = erase_size;
-	dev->mtd.type = MTD_RAM;
+	dev->mtd.type = MTD_BLOCK;
 	dev->mtd.flags = MTD_CAP_RAM;
 	dev->mtd.erase = block2mtd_erase;
 	dev->mtd.write = block2mtd_write;



From dwmw2 at infradead.org  Thu Feb  9 11:13:01 2006
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon May 15 21:53:30 2006
Subject: mtd/fs/jffs2 scan.c,1.134,1.135
Message-ID: <E1F7EPl-0007Vk-PT@phoenix.infradead.org>

Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv28853

Modified Files:
	scan.c 
Log Message:
Avoid divide-by-zero

Index: scan.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/scan.c,v
retrieving revision 1.134
retrieving revision 1.135
diff -u -r1.134 -r1.135
--- scan.c	13 Jan 2006 10:25:29 -0000	1.134
+++ scan.c	9 Feb 2006 16:12:59 -0000	1.135
@@ -239,7 +239,7 @@
 		c->nextblock->dirty_size = 0;
 	}
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
-	if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size % c->wbuf_pagesize)) {
+	if (!jffs2_can_mark_obsolete(c) && c->wbuf_pagesize && c->nextblock && (c->nextblock->free_size % c->wbuf_pagesize)) {
 		/* If we're going to start writing into a block which already
 		   contains data, and the end of the data isn't page-aligned,
 		   skip a little and align it. */



From dwmw2 at infradead.org  Thu Feb  9 11:13:38 2006
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon May 15 21:53:30 2006
Subject: mtd/fs/jffs2 fs.c, 1.71, 1.72 os-linux.h, 1.67, 1.68 wbuf.c, 1.109,
	1.110
Message-ID: <E1F7EQM-0007Wo-BO@phoenix.infradead.org>

Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv28919

Modified Files:
	fs.c os-linux.h wbuf.c 
Log Message:
wbuf on block2mtd

Index: fs.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/fs.c,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -r1.71 -r1.72
--- fs.c	11 Dec 2005 14:07:39 -0000	1.71
+++ fs.c	9 Feb 2006 16:13:35 -0000	1.72
@@ -657,6 +657,13 @@
 			return ret;
 	}
 
+	/* and MTD-on-blockdevice */
+	if (jffs2_block_mtd(c)) {
+		ret = jffs2_block_mtd_setup(c);
+		if (ret)
+			return ret;
+	}
+
 	return ret;
 }
 
@@ -680,4 +687,9 @@
 	if (jffs2_nor_wbuf_flash(c)) {
 		jffs2_nor_wbuf_flash_cleanup(c);
 	}
+
+	/* and MTD-on-blockdevice */
+	if (jffs2_block_mtd(c)) {
+		jffs2_block_mtd_cleanup(c);
+	}
 }

Index: os-linux.h
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/os-linux.h,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -r1.67 -r1.68
--- os-linux.h	11 Nov 2005 14:29:12 -0000	1.67
+++ os-linux.h	9 Feb 2006 16:13:35 -0000	1.68
@@ -93,12 +93,15 @@
 #define jffs2_nor_ecc(c) (0)
 #define jffs2_dataflash(c) (0)
 #define jffs2_nor_wbuf_flash(c) (0)
+#define jffs2_block_mtd(c) (0)
 #define jffs2_nor_ecc_flash_setup(c) (0)
 #define jffs2_nor_ecc_flash_cleanup(c) do {} while (0)
 #define jffs2_dataflash_setup(c) (0)
 #define jffs2_dataflash_cleanup(c) do {} while (0)
 #define jffs2_nor_wbuf_flash_setup(c) (0)
 #define jffs2_nor_wbuf_flash_cleanup(c) do {} while (0)
+#define jffs2_block_mtd_setup(c) (0)
+#define jffs2_block_mtd_cleanup(c) do {} while (0)
 
 #else /* NAND and/or ECC'd NOR support present */
 
@@ -146,6 +149,9 @@
 int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c);
 void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c);
 
+#define jffs2_block_mtd(c) (c->mtd->type == MTD_BLOCK)
+int jffs2_block_mtd_setup(struct jffs2_sb_info *c);
+void jffs2_block_mtd_cleanup(struct jffs2_sb_info *c);
 #endif /* WRITEBUFFER */
 
 /* erase.c */

Index: wbuf.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/wbuf.c,v
retrieving revision 1.109
retrieving revision 1.110
diff -u -r1.109 -r1.110
--- wbuf.c	21 Jan 2006 21:50:44 -0000	1.109
+++ wbuf.c	9 Feb 2006 16:13:35 -0000	1.110
@@ -1348,3 +1348,25 @@
 void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c) {
 	kfree(c->wbuf);
 }
+
+int jffs2_block_mtd_setup(struct jffs2_sb_info *c) {
+	/* Use a 512-byte sector as wbuf region, for performance */
+	/* Cleanmarker currently occupies a whole programming region */
+	c->cleanmarker_size = 512;
+	c->ebh_size = 512;
+
+	/* Initialize write buffer */
+	init_rwsem(&c->wbuf_sem);
+	c->wbuf_pagesize = 512;
+	c->wbuf_ofs = 0xFFFFFFFF;
+
+	c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
+	if (!c->wbuf)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void jffs2_block_mtd_cleanup(struct jffs2_sb_info *c) {
+	kfree(c->wbuf);
+}



From havasi at infradead.org  Wed Feb 15 04:42:05 2006
From: havasi at infradead.org (havasi@infradead.org)
Date: Mon May 15 21:53:30 2006
Subject: mtd/fs/jffs2 summary.h,1.3,1.4
Message-ID: <E1F9JAj-0002hq-H4@phoenix.infradead.org>

Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv10387

Modified Files:
	summary.h 
Log Message:
[JFFS2] Alligment fix. (noticed on Intel XScale big endian)

Thanks for Robert Liu.



Index: summary.h
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/summary.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- summary.h	4 Nov 2005 08:06:25 -0000	1.3
+++ summary.h	15 Feb 2006 09:42:02 -0000	1.4
@@ -52,7 +52,7 @@
 struct jffs2_sum_unknown_flash
 {
 	jint16_t nodetype;	/* node type */
-};
+} __attribute__((packed));
 
 struct jffs2_sum_inode_flash
 {
@@ -104,7 +104,7 @@
 {
 	union jffs2_sum_mem *next;
 	jint16_t nodetype;	/* node type */
-};
+} __attribute__((packed));
 
 struct jffs2_sum_inode_mem
 {



From havasi at infradead.org  Wed Feb 15 04:42:36 2006
From: havasi at infradead.org (havasi@infradead.org)
Date: Mon May 15 21:53:31 2006
Subject: mtd/util summary.h,1.6,1.7
Message-ID: <E1F9JBE-0002iU-UJ@phoenix.infradead.org>

Update of /home/cvs/mtd/util
In directory phoenix.infradead.org:/tmp/cvs-serv10429

Modified Files:
	summary.h 
Log Message:
[JFFS2] Alligment fix. (noticed on Intel XScale big endian)

Thanks for Robert Liu.



Index: summary.h
===================================================================
RCS file: /home/cvs/mtd/util/summary.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- summary.h	7 Nov 2005 11:15:14 -0000	1.6
+++ summary.h	15 Feb 2006 09:42:34 -0000	1.7
@@ -51,7 +51,7 @@
 struct jffs2_sum_unknown_flash
 {
 	jint16_t nodetype;	/* node type */
-};
+} __attribute__((packed));
 
 struct jffs2_sum_inode_flash
 {
@@ -88,7 +88,7 @@
 {
 	union jffs2_sum_mem *next;
 	jint16_t nodetype;	/* node type */
-};
+} __attribute__((packed));
 
 struct jffs2_sum_inode_mem
 {



From pavlov at infradead.org  Tue Feb 21 04:29:27 2006
From: pavlov at infradead.org (Andrew Victor)
Date: Mon May 15 21:53:31 2006
Subject: mtd/drivers/mtd/nand at91_nand.c, NONE, 1.1 Makefile.common, 1.16,
	1.17 Kconfig, 1.35, 1.36
Message-ID: <E1FBTpn-0000Qb-Ew@phoenix.infradead.org>

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

Modified Files:
	Makefile.common Kconfig 
Added Files:
	at91_nand.c 
Log Message:
Add support for the NAND (SmartMedia) controller on the Atmel AT91RM9200
processor.

Signed-off-by: Andrew Victor <andrew@sanpeople.com>



--- NEW FILE at91_nand.c ---
/*
 * drivers/mtd/nand/at91_nand.c
 *
 *  Copyright (C) 2003 Rick Bronson
 *
 *  Derived from drivers/mtd/nand/autcpu12.c
 *	 Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
 *
 *  Derived from drivers/mtd/spia.c
 *	 Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
 *
 * 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/module.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>

#include <asm/io.h>
#include <asm/sizes.h>

#include <asm/arch/hardware.h>
#include <asm/arch/board.h>
#include <asm/arch/gpio.h>

struct at91_nand_host {
	struct nand_chip	nand_chip;
	struct mtd_info		mtd;
	void __iomem		*io_base;
	struct at91_nand_data	*board;
};

/*
 * Hardware specific access to control-lines
 */
static void at91_nand_hwcontrol(struct mtd_info *mtd, int cmd)
{
	struct nand_chip *nand_chip = mtd->priv;
	struct at91_nand_host *host = nand_chip->priv;

	switch(cmd) {
		case NAND_CTL_SETCLE:
			nand_chip->IO_ADDR_W = host->io_base + (1 << host->board->cle);
			break;
		case NAND_CTL_CLRCLE:
			nand_chip->IO_ADDR_W = host->io_base;
			break;
		case NAND_CTL_SETALE:
			nand_chip->IO_ADDR_W = host->io_base + (1 << host->board->ale);
			break;
		case NAND_CTL_CLRALE:
			nand_chip->IO_ADDR_W = host->io_base;
			break;
		case NAND_CTL_SETNCE:
			break;
		case NAND_CTL_CLRNCE:
			break;
	}
}


/*
 * Read the Device Ready pin.
 */
static int at91_nand_device_ready(struct mtd_info *mtd)
{
	struct nand_chip *nand_chip = mtd->priv;
	struct at91_nand_host *host = nand_chip->priv;

	return at91_get_gpio_value(host->board->rdy_pin);
}


/*
 * Enable NAND and detect card.
 */
static void at91_nand_enable(struct at91_nand_host *host)
{
	unsigned int csa;

	/* Setup Smart Media, first enable the address range of CS3 */
	csa = at91_sys_read(AT91_EBI_CSA);
	at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS3A_SMC_SMARTMEDIA);

	/* set the bus interface characteristics */
	at91_sys_write(AT91_SMC_CSR(3), AT91_SMC_ACSS_STD | AT91_SMC_DBW_8 | AT91_SMC_WSEN
				| AT91_SMC_NWS_(5)
				| AT91_SMC_TDF_(1)
				| AT91_SMC_RWSETUP_(0)	/* tDS Data Set up Time 30 - ns */
				| AT91_SMC_RWHOLD_(1)	/* tDH Data Hold Time 20 - ns */
	);

	if (host->board->enable_pin)
		at91_set_gpio_value(host->board->enable_pin, 0);
}

/*
 * Disable NAND.
 */
static void at91_nand_disable(struct at91_nand_host *host)
{
	if (host->board->enable_pin)
		at91_set_gpio_value(host->board->enable_pin, 1);
}

/*
 * Probe for the NAND device.
 */
static int __init at91_nand_probe(struct platform_device *pdev)
{
	struct at91_nand_host *host;
	struct mtd_info *mtd;
	struct nand_chip *nand_chip;
	int res;

#ifdef CONFIG_MTD_PARTITIONS
	struct mtd_partition *partitions = NULL;
	int num_partitions = 0;
#endif

	/* Allocate memory for the device structure (and zero it) */
	host = kzalloc(sizeof(struct at91_nand_host), GFP_KERNEL);
	if (!host) {
		printk(KERN_ERR "at91_nand: failed to allocate device structure.\n");
		return -ENOMEM;
	}

	host->io_base = ioremap(pdev->resource[0].start,
				pdev->resource[0].end - pdev->resource[0].start + 1);
	if (host->io_base == NULL) {
		printk(KERN_ERR "at91_nand: ioremap failed\n");
		kfree(host);
		return -EIO;
	}

	mtd = &host->mtd;
	nand_chip = &host->nand_chip;
	host->board = pdev->dev.platform_data;

	nand_chip->priv = host;		/* link the private data structures */
	mtd->priv = nand_chip;

	/* Set address of NAND IO lines */
	nand_chip->IO_ADDR_R = host->io_base;
	nand_chip->IO_ADDR_W = host->io_base;
	nand_chip->hwcontrol = at91_nand_hwcontrol;
	nand_chip->dev_ready = at91_nand_device_ready;
	nand_chip->eccmode = NAND_ECC_SOFT;	/* enable ECC */
	nand_chip->chip_delay = 20;		/* 20us command delay time */

	platform_set_drvdata(pdev, host);
	at91_nand_enable(host);

	if (host->board->det_pin) {
		if (at91_get_gpio_value(host->board->det_pin)) {
			printk ("No SmartMedia card inserted.\n");
			res = ENXIO;
			goto out;
		}
	}

	/* Scan to find existance of the device */
	if (nand_scan(mtd, 1)) {
		res = -ENXIO;
		goto out;
	}

#ifdef CONFIG_MTD_PARTITIONS
	if (host->board->partition_info)
		partitions = host->board->partition_info(mtd->size, &num_partitions);

	if ((!partitions) || (num_partitions == 0)) {
		printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n");
		res = ENXIO;
		goto out;
	}

	res = add_mtd_partitions(mtd, partitions, num_partitions);
#else
	res = add_mtd_device(mtd);
#endif

out:
	if (res) {
		at91_nand_disable(host);
		platform_set_drvdata(pdev, NULL);
	
		iounmap(host->io_base);
		kfree(host);
	}

	return res;
}

/*
 * Remove a NAND device.
 */
static int __devexit at91_nand_remove(struct platform_device *pdev)
{
	struct at91_nand_host *host = platform_get_drvdata(pdev);
	struct mtd_info *mtd = &host->mtd;

	del_mtd_partitions(mtd);
	del_mtd_device(mtd);

	at91_nand_disable(host);

	iounmap(host->io_base);
	kfree(host);

	return 0;
}

static struct platform_driver at91_nand_driver = {
	.probe		= at91_nand_probe,
	.remove		= at91_nand_remove,
	.driver		= {
		.name	= "at91_nand",
		.owner	= THIS_MODULE,
	},
};

static int __init at91_nand_init(void)
{
	return platform_driver_register(&at91_nand_driver);
}


static void __exit at91_nand_exit(void)
{
	platform_driver_unregister(&at91_nand_driver);
}


module_init(at91_nand_init);
module_exit(at91_nand_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rick Bronson");
MODULE_DESCRIPTION("Glue layer for SmartMediaCard on ATMEL AT91RM9200");

Index: Makefile.common
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nand/Makefile.common,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- Makefile.common	6 Jul 2005 09:33:28 -0000	1.16
+++ Makefile.common	21 Feb 2006 09:29:24 -0000	1.17
@@ -18,5 +18,6 @@
 obj-$(CONFIG_MTD_NAND_RTC_FROM4)	+= rtc_from4.o
 obj-$(CONFIG_MTD_NAND_SHARPSL)		+= sharpsl.o
 obj-$(CONFIG_MTD_NAND_NANDSIM)		+= nandsim.o
+obj-$(CONFIG_MTD_NAND_AT91)		+= at91_nand.o
 
 nand-objs = nand_base.o nand_bbt.o

Index: Kconfig
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nand/Kconfig,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- Kconfig	7 Nov 2005 11:14:30 -0000	1.35
+++ Kconfig	21 Feb 2006 09:29:24 -0000	1.36
@@ -183,6 +183,12 @@
  	bool "Support for NAND Flash on Sharp SL Series (C7xx + others)"
  	depends on MTD_NAND	&& ARCH_PXA
 
+config MTD_NAND_AT91
+	bool "AT91 NAND (Smart Media) support"
+	depends on MTD_NAND && ARCH_AT91RM9200
+	help
+	  Enables access to the Smart Media card interface on the AT91RM9200.
+
 config MTD_NAND_NANDSIM
 	tristate "Support for NAND Flash Simulator"
 	depends on m && MTD_NAND && MTD_PARTITIONS



From kyungmin.park at samsung.com  Tue Feb 21 19:26:40 2006
From: kyungmin.park at samsung.com (kyungmin.park@samsung.com)
Date: Mon May 15 21:53:31 2006
Subject: mtd/drivers/mtd mtdchar.c,1.79,1.80
Message-ID: <E1FBhq4-0000qF-5y@phoenix.infradead.org>

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

Modified Files:
	mtdchar.c 
Log Message:
[MTD] OneNAND: One-Time Programmable (OTP) support

One Block of the NAND Flash Array memory is reserved as
a One-Time Programmable Block memory area.
Also, 1st Block of NAND Flash Array can be used as OTP.

The OTP block can be read, programmed and locked using the same
operations as any other NAND Flash Array memory block.
OTP block cannot be erased.

OTP block is fully-guaranteed to be a valid block.


Index: mtdchar.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/mtdchar.c,v
retrieving revision 1.79
retrieving revision 1.80
diff -u -r1.79 -r1.80
--- mtdchar.c	6 Jan 2006 13:35:31 -0000	1.79
+++ mtdchar.c	22 Feb 2006 00:26:36 -0000	1.80
@@ -557,7 +557,7 @@
 		break;
 	}
 
-#ifdef CONFIG_MTD_OTP
+#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP)
 	case OTPSELECT:
 	{
 		int mode;



From kyungmin.park at samsung.com  Tue Feb 21 19:26:41 2006
From: kyungmin.park at samsung.com (kyungmin.park@samsung.com)
Date: Mon May 15 21:53:31 2006
Subject: mtd/util flash_otp_write.c,1.2,1.3
Message-ID: <E1FBhq5-0000qT-KE@phoenix.infradead.org>

Update of /home/cvs/mtd/util
In directory phoenix.infradead.org:/tmp/cvs-serv3220/util

Modified Files:
	flash_otp_write.c 
Log Message:
[MTD] OneNAND: One-Time Programmable (OTP) support

One Block of the NAND Flash Array memory is reserved as
a One-Time Programmable Block memory area.
Also, 1st Block of NAND Flash Array can be used as OTP.

The OTP block can be read, programmed and locked using the same
operations as any other NAND Flash Array memory block.
OTP block cannot be erased.

OTP block is fully-guaranteed to be a valid block.


Index: flash_otp_write.c
===================================================================
RCS file: /home/cvs/mtd/util/flash_otp_write.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- flash_otp_write.c	7 Nov 2005 11:15:10 -0000	1.2
+++ flash_otp_write.c	22 Feb 2006 00:26:38 -0000	1.3
@@ -15,9 +15,10 @@
 
 int main(int argc,char *argv[])
 {
-	int fd, val, ret, size, wrote;
+	int fd, val, ret, size, wrote, len;
+	mtd_info_t mtdInfo;
 	off_t offset;
-	char *p, buf[256];
+	char *p, buf[2048];
 
 	if (argc != 4 || strcmp(argv[1], "-u")) {
 		fprintf(stderr, "Usage: %s -u <device> <offset>\n", argv[0]);
@@ -39,6 +40,11 @@
 		return errno;
 	}
 
+	if (ioctl(fd, MEMGETINFO, &mtdInfo)) {
+		perror("MEMGETINFO");
+		return errno;
+	}
+
 	offset = strtoul(argv[3], &p, 0);
 	if (argv[3][0] == 0 || *p != 0) {
 		fprintf(stderr, "%s: bad offset value\n", argv[0]);
@@ -52,14 +58,24 @@
 
 	printf("Writing OTP user data on %s at offset 0x%lx\n", argv[2], offset);
 
+	if (mtdInfo.type == MTD_NANDFLASH)
+		len = mtdInfo.oobblock;
+	else
+		len = 256;
+
 	wrote = 0;
-	while ((size = read(0, buf, sizeof(buf)))) {
+	while ((size = read(0, buf, len))) {
 		if (size < 0) {
 			perror("read()");
 			return errno;
 		}
 		p = buf;
 		while (size > 0) {
+			if (mtdInfo.type == MTD_NANDFLASH) {
+				/* Fill remain buffers with 0xff */
+				memset(buf + size, 0xff, mtdInfo.oobblock - size);
+				size = mtdInfo.oobblock;
+			}
 			ret = write(fd, p, size);
 			if (ret < 0) {
 				perror("write()");



From kyungmin.park at samsung.com  Tue Feb 21 19:26:41 2006
From: kyungmin.park at samsung.com (kyungmin.park@samsung.com)
Date: Mon May 15 21:53:31 2006
Subject: mtd/include/linux/mtd onenand.h,1.12,1.13 onenand_regs.h,1.3,1.4
Message-ID: <E1FBhq5-0000qO-Cp@phoenix.infradead.org>

Update of /home/cvs/mtd/include/linux/mtd
In directory phoenix.infradead.org:/tmp/cvs-serv3220/include/linux/mtd

Modified Files:
	onenand.h onenand_regs.h 
Log Message:
[MTD] OneNAND: One-Time Programmable (OTP) support

One Block of the NAND Flash Array memory is reserved as
a One-Time Programmable Block memory area.
Also, 1st Block of NAND Flash Array can be used as OTP.

The OTP block can be read, programmed and locked using the same
operations as any other NAND Flash Array memory block.
OTP block cannot be erased.

OTP block is fully-guaranteed to be a valid block.


Index: onenand.h
===================================================================
RCS file: /home/cvs/mtd/include/linux/mtd/onenand.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- onenand.h	18 Jan 2006 15:16:40 -0000	1.12
+++ onenand.h	22 Feb 2006 00:26:38 -0000	1.13
@@ -37,6 +37,8 @@
 	FL_SYNCING,
 	FL_UNLOCKING,
 	FL_LOCKING,
+	FL_RESETING,
+	FL_OTPING,
 	FL_PM_SUSPENDED,
 } onenand_state_t;
 

Index: onenand_regs.h
===================================================================
RCS file: /home/cvs/mtd/include/linux/mtd/onenand_regs.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- onenand_regs.h	18 Jan 2006 15:16:40 -0000	1.3
+++ onenand_regs.h	22 Feb 2006 00:26:38 -0000	1.4
@@ -114,6 +114,7 @@
 #define ONENAND_CMD_LOCK_TIGHT		(0x2C)
 #define ONENAND_CMD_ERASE		(0x94)
 #define ONENAND_CMD_RESET		(0xF0)
+#define ONENAND_CMD_OTP_ACCESS		(0x65)
 #define ONENAND_CMD_READID		(0x90)
 
 /* NOTE: Those are not *REAL* commands */
@@ -154,6 +155,8 @@
 #define ONENAND_CTRL_ERASE		(1 << 11)
 #define ONENAND_CTRL_ERROR		(1 << 10)
 #define ONENAND_CTRL_RSTB		(1 << 7)
+#define ONENAND_CTRL_OTP_L		(1 << 6)
+#define ONENAND_CTRL_OTP_BL		(1 << 5)
 
 /*
  * Interrupt Status Register F241h (R)
@@ -179,4 +182,9 @@
 #define ONENAND_ECC_2BIT		(1 << 1)
 #define ONENAND_ECC_2BIT_ALL		(0xAAAA)
 
+/*
+ * One-Time Programmable (OTP)
+ */
+#define ONENAND_OTP_LOCK_OFFSET		(14)
+
 #endif	/* __ONENAND_REG_H */



From kyungmin.park at samsung.com  Tue Feb 21 19:26:40 2006
From: kyungmin.park at samsung.com (kyungmin.park@samsung.com)
Date: Mon May 15 21:53:31 2006
Subject: mtd/drivers/mtd/onenand Kconfig,1.7,1.8 onenand_base.c,1.18,1.19
Message-ID: <E1FBhq4-0000qJ-Or@phoenix.infradead.org>

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

Modified Files:
	Kconfig onenand_base.c 
Log Message:
[MTD] OneNAND: One-Time Programmable (OTP) support

One Block of the NAND Flash Array memory is reserved as
a One-Time Programmable Block memory area.
Also, 1st Block of NAND Flash Array can be used as OTP.

The OTP block can be read, programmed and locked using the same
operations as any other NAND Flash Array memory block.
OTP block cannot be erased.

OTP block is fully-guaranteed to be a valid block.


Index: Kconfig
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/onenand/Kconfig,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- Kconfig	7 Nov 2005 00:00:21 -0000	1.7
+++ Kconfig	22 Feb 2006 00:26:37 -0000	1.8
@@ -29,6 +29,20 @@
 	help
 	  Support for OneNAND flash via platform device driver.
 
+config MTD_ONENAND_OTP
+	bool "OneNAND OTP Support"
+	depends on MTD_ONENAND
+	help
+	  One Block of the NAND Flash Array memory is reserved as
+	  a One-Time Programmable Block memory area.
+	  Also, 1st Block of NAND Flash Array can be used as OTP.
+
+	  The OTP block can be read, programmed and locked using the same
+	  operations as any other NAND Flash Array memory block.
+	  OTP block cannot be erased.
+
+	  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

Index: onenand_base.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/onenand/onenand_base.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- onenand_base.c	27 Jan 2006 00:26:34 -0000	1.18
+++ onenand_base.c	22 Feb 2006 00:26:37 -0000	1.19
@@ -193,7 +193,7 @@
 static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t len)
 {
 	struct onenand_chip *this = mtd->priv;
-	int value, readcmd = 0;
+	int value, readcmd = 0, block_cmd = 0;
 	int block, page;
 	/* Now we use page size operation */
 	int sectors = 4, count = 4;
@@ -209,6 +209,8 @@
 
 	case ONENAND_CMD_ERASE:
 	case ONENAND_CMD_BUFFERRAM:
+	case ONENAND_CMD_OTP_ACCESS:
+		block_cmd = 1;
 		block = (int) (addr >> this->erase_shift);
 		page = -1;
 		break;
@@ -237,7 +239,7 @@
 		value = onenand_block_address(this, block);
 		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
 
-		if (cmd == ONENAND_CMD_ERASE) {
+		if (cmd == block_cmd) {
 			/* Select DataRAM for DDP */
 			value = onenand_bufferram_address(this, block);
 			this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
@@ -1414,6 +1416,304 @@
 	return 0;
 }
 
+#ifdef CONFIG_MTD_ONENAND_OTP
+
+/* Interal OTP operation */
+typedef int (*otp_op_t)(struct mtd_info *mtd, loff_t form, size_t len,
+		size_t *retlen, u_char *buf);
+
+/**
+ * do_otp_read - [DEFAULT] Read OTP block area
+ * @param mtd		MTD device structure
+ * @param from		The offset to read
+ * @param len		number of bytes to read
+ * @param retlen	pointer to variable to store the number of readbytes
+ * @param buf		the databuffer to put/get data
+ *
+ * Read OTP block area.
+ */
+static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *buf)
+{
+	struct onenand_chip *this = mtd->priv;
+	int ret;
+
+	/* Enter OTP access mode */
+	this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
+	this->wait(mtd, FL_OTPING);
+
+	ret = mtd->read(mtd, from, len, retlen, buf);
+
+	/* Exit OTP access mode */
+	this->command(mtd, ONENAND_CMD_RESET, 0, 0);
+	this->wait(mtd, FL_RESETING);
+
+	return ret;
+}
+
+/**
+ * do_otp_write - [DEFAULT] Write OTP block area
+ * @param mtd		MTD device structure
+ * @param from		The offset to write
+ * @param len		number of bytes to write
+ * @param retlen	pointer to variable to store the number of write bytes
+ * @param buf		the databuffer to put/get data
+ *
+ * Write OTP block area.
+ */
+static int do_otp_write(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *buf)
+{
+	struct onenand_chip *this = mtd->priv;
+	unsigned char *pbuf = buf;
+	int ret;
+
+	/* Force buffer page aligned */
+	if (len < mtd->oobblock) {
+		memcpy(this->page_buf, buf, len);
+		memset(this->page_buf + len, 0xff, mtd->oobblock - len);
+		pbuf = this->page_buf;
+		len = mtd->oobblock;
+	}
+
+	/* Enter OTP access mode */
+	this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
+	this->wait(mtd, FL_OTPING);
+
+	ret = mtd->write(mtd, from, len, retlen, pbuf);
+
+	/* Exit OTP access mode */
+	this->command(mtd, ONENAND_CMD_RESET, 0, 0);
+	this->wait(mtd, FL_RESETING);
+
+	return ret;
+}
+
+/**
+ * do_otp_lock - [DEFAULT] Lock OTP block area
+ * @param mtd		MTD device structure
+ * @param from		The offset to lock
+ * @param len		number of bytes to lock
+ * @param retlen	pointer to variable to store the number of lock bytes
+ * @param buf		the databuffer to put/get data
+ *
+ * Lock OTP block area.
+ */
+static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *buf)
+{
+	struct onenand_chip *this = mtd->priv;
+	int ret;
+
+	/* Enter OTP access mode */
+	this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
+	this->wait(mtd, FL_OTPING);
+
+	ret = mtd->write_oob(mtd, from, len, retlen, buf);
+
+	/* Exit OTP access mode */
+	this->command(mtd, ONENAND_CMD_RESET, 0, 0);
+	this->wait(mtd, FL_RESETING);
+
+	return ret;
+}
+
+/**
+ * onenand_otp_walk - [DEFAULT] Handle OTP operation
+ * @param mtd		MTD device structure
+ * @param from		The offset to read/write
+ * @param len		number of bytes to read/write
+ * @param retlen	pointer to variable to store the number of read bytes
+ * @param buf		the databuffer to put/get data
+ * @param action	do given action
+ * @param mode		specify user and factory
+ *
+ * Handle OTP operation.
+ */
+static int onenand_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
+			size_t *retlen, u_char *buf,
+			otp_op_t action, int mode)
+{
+	struct onenand_chip *this = mtd->priv;
+	int otp_pages;
+	int density;
+	int ret = 0;
+
+	*retlen = 0;
+
+	density = this->device_id >> ONENAND_DEVICE_DENSITY_SHIFT;
+	if (density < ONENAND_DEVICE_DENSITY_512Mb)
+		otp_pages = 20;
+	else
+		otp_pages = 10;
+
+	if (mode == MTD_OTP_FACTORY) {
+		from += mtd->oobblock * otp_pages;
+		otp_pages = 64 - otp_pages;
+	}
+
+	/* Check User/Factory boundary */
+	if (((mtd->oobblock * otp_pages) - (from + len)) < 0)
+		return 0;
+
+	while (len > 0 && otp_pages > 0) {
+		if (!action) {	/* OTP Info functions */
+			struct otp_info *otpinfo;
+
+			len -= sizeof(struct otp_info);
+			if (len <= 0)
+				return -ENOSPC;
+
+			otpinfo = (struct otp_info *) buf;
+			otpinfo->start = from;
+			otpinfo->length = mtd->oobblock;
+			otpinfo->locked = 0;
+
+			from += mtd->oobblock;
+			buf += sizeof(struct otp_info);
+			*retlen += sizeof(struct otp_info);
+		} else {
+			size_t tmp_retlen;
+			int size = len;
+
+			ret = action(mtd, from, len, &tmp_retlen, buf);
+
+			buf += size;
+			len -= size;
+			*retlen += size;
+
+			if (ret < 0)
+				return ret;
+		}
+		otp_pages--;
+	}
+
+	return 0;
+}
+
+/**
+ * onenand_get_fact_prot_info - [MTD Interface] Read factory OTP info
+ * @param mtd		MTD device structure
+ * @param buf		the databuffer to put/get data
+ * @param len		number of bytes to read
+ *
+ * Read factory OTP info.
+ */
+static int onenand_get_fact_prot_info(struct mtd_info *mtd,
+			struct otp_info *buf, size_t len)
+{
+	size_t retlen;
+	int ret;
+
+	ret = onenand_otp_walk(mtd, 0, len, &retlen, (u_char *) buf, NULL, MTD_OTP_FACTORY);
+
+	return ret ? : retlen;
+}
+
+/**
+ * onenand_read_fact_prot_reg - [MTD Interface] Read factory OTP area
+ * @param mtd		MTD device structure
+ * @param from		The offset to read
+ * @param len		number of bytes to read
+ * @param retlen	pointer to variable to store the number of read bytes
+ * @param buf		the databuffer to put/get data
+ *
+ * Read factory OTP area.
+ */
+static int onenand_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
+			size_t len, size_t *retlen, u_char *buf)
+{
+	return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_read, MTD_OTP_FACTORY);
+}
+
+/**
+ * onenand_get_user_prot_info - [MTD Interface] Read user OTP info
+ * @param mtd		MTD device structure
+ * @param buf		the databuffer to put/get data
+ * @param len		number of bytes to read
+ *
+ * Read user OTP info.
+ */
+static int onenand_get_user_prot_info(struct mtd_info *mtd,
+			struct otp_info *buf, size_t len)
+{
+	size_t retlen;
+	int ret;
+
+	ret = onenand_otp_walk(mtd, 0, len, &retlen, (u_char *) buf, NULL, MTD_OTP_USER);
+
+	return ret ? : retlen;
+}
+
+/**
+ * onenand_read_user_prot_reg - [MTD Interface] Read user OTP area
+ * @param mtd		MTD device structure
+ * @param from		The offset to read
+ * @param len		number of bytes to read
+ * @param retlen	pointer to variable to store the number of read bytes
+ * @param buf		the databuffer to put/get data
+ *
+ * Read user OTP area.
+ */
+static int onenand_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
+			size_t len, size_t *retlen, u_char *buf)
+{
+	return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_read, MTD_OTP_USER);
+}
+
+/**
+ * onenand_write_user_prot_reg - [MTD Interface] Write user OTP area
+ * @param mtd		MTD device structure
+ * @param from		The offset to write
+ * @param len		number of bytes to write
+ * @param retlen	pointer to variable to store the number of write bytes
+ * @param buf		the databuffer to put/get data
+ *
+ * Write user OTP area.
+ */
+static int onenand_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
+			size_t len, size_t *retlen, u_char *buf)
+{
+	return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_write, MTD_OTP_USER);
+}
+
+/**
+ * onenand_lock_user_prot_reg - [MTD Interface] Lock user OTP area
+ * @param mtd		MTD device structure
+ * @param from		The offset to lock
+ * @param len		number of bytes to unlock
+ *
+ * Write lock mark on spare area in page 0 in OTP block 
+ */
+static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
+			size_t len)
+{
+	unsigned char oob_buf[64];
+	size_t retlen;
+	int ret;
+
+	memset(oob_buf, 0xff, mtd->oobsize);
+	/*
+	 * Note: OTP lock operation
+	 *       OTP block : 0xXXFC
+	 *       1st block : 0xXXF3 (If chip support)
+	 *       Both      : 0xXXF0 (If chip support)
+	 */
+	oob_buf[ONENAND_OTP_LOCK_OFFSET] = 0xFC;
+
+	/*
+	 * Write lock mark to 8th word of sector0 of page0 of the spare0.
+	 * We write 16 bytes spare area instead of 2 bytes.
+	 */
+	from = 0;
+	len = 16;
+
+	ret = onenand_otp_walk(mtd, from, len, &retlen, oob_buf, do_otp_lock, MTD_OTP_USER);
+
+	return ret ? : retlen;
+}
+#endif	/* CONFIG_MTD_ONENAND_OTP */
+
 /**
  * onenand_print_device_info - Print device ID
  * @param device        device ID
@@ -1565,7 +1865,6 @@
 				"in suspended state\n");
 }
 
-
 /**
  * onenand_scan - [OneNAND Interface] Scan for the OneNAND device
  * @param mtd		MTD device structure
@@ -1657,6 +1956,14 @@
 	mtd->write_ecc = onenand_write_ecc;
 	mtd->read_oob = onenand_read_oob;
 	mtd->write_oob = onenand_write_oob;
+#ifdef CONFIG_MTD_ONENAND_OTP
+	mtd->get_fact_prot_info = onenand_get_fact_prot_info;
+	mtd->read_fact_prot_reg = onenand_read_fact_prot_reg;
+	mtd->get_user_prot_info = onenand_get_user_prot_info;
+	mtd->read_user_prot_reg = onenand_read_user_prot_reg;
+	mtd->write_user_prot_reg = onenand_write_user_prot_reg;
+	mtd->lock_user_prot_reg = onenand_lock_user_prot_reg;
+#endif
 	mtd->readv = NULL;
 	mtd->readv_ecc = NULL;
 	mtd->writev = onenand_writev;



