# HG changeset patch
# User Matt Mackall <mpm@selenic.com>
# Date 1249941537 18000
# Node ID ac71465c2912ec4c5a56465b8c92b9611b8031d1
# Parent  8280ecb6cbe1a37ba597abd36068364485e91922
imported patch comcerto-mtd

diff -r 8280ecb6cbe1 -r ac71465c2912 drivers/mtd/maps/Kconfig
--- a/drivers/mtd/maps/Kconfig	Mon Aug 10 16:58:56 2009 -0500
+++ b/drivers/mtd/maps/Kconfig	Mon Aug 10 16:58:57 2009 -0500
@@ -461,6 +461,11 @@
 	  These boards include the Innovator, H2, H3, OSK, Perseus2, and
 	  more.  If you have such a board, say 'Y'.
 
+config MTD_COMCERTO_NOR
+	tristate "Mindspeed Comcerto board mappings"
+	depends on MTD_CFI && ARCH_COMCERTO
+	help
+
 # This needs CFI or JEDEC, depending on the cards found.
 config MTD_PCI
 	tristate "PCI MTD driver"
diff -r 8280ecb6cbe1 -r ac71465c2912 drivers/mtd/maps/Makefile
--- a/drivers/mtd/maps/Makefile	Mon Aug 10 16:58:56 2009 -0500
+++ b/drivers/mtd/maps/Makefile	Mon Aug 10 16:58:57 2009 -0500
@@ -17,6 +17,7 @@
 obj-$(CONFIG_MTD_ESB2ROM)	+= esb2rom.o
 obj-$(CONFIG_MTD_ICHXROM)	+= ichxrom.o
 obj-$(CONFIG_MTD_CK804XROM)	+= ck804xrom.o
+obj-$(CONFIG_MTD_COMCERTO_NOR)	+= comcerto-nor.o
 obj-$(CONFIG_MTD_TSUNAMI)	+= tsunami_flash.o
 obj-$(CONFIG_MTD_PXA2XX)	+= pxa2xx-flash.o
 obj-$(CONFIG_MTD_MBX860)	+= mbx860.o
diff -r 8280ecb6cbe1 -r ac71465c2912 drivers/mtd/maps/comcerto-nor.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/mtd/maps/comcerto-nor.c	Mon Aug 10 16:58:57 2009 -0500
@@ -0,0 +1,254 @@
+/*
+ *  linux/drivers/mtd/maps/comcerto-nor.c
+ *
+ *  Copyright (C) 2004,2006 Mindspeed Technologies, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/comcerto-nor.h>
+
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <asm/mach/flash.h>
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probes[] = { "cmdlinepart", NULL };
+#endif
+
+struct comcertoflash_info {
+	struct mtd_partition *parts;
+	struct mtd_info *mtd;
+	struct map_info map;
+};
+
+#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
+static map_word comcertoflash_map_read(struct map_info *map, unsigned long ofs);
+static void comcertoflash_map_write(struct map_info *map, const map_word datum,
+				    unsigned long ofs);
+static void comcertoflash_map_copy_from(struct map_info *map, void *to,
+					unsigned long from, ssize_t len);
+static void comcertoflash_map_copy_to(struct map_info *map, unsigned long to,
+				      const void *from, ssize_t len);
+
+static map_word comcertoflash_map_read(struct map_info *map, unsigned long ofs)
+{
+	/*
+	 * On baord with NOR of 16MB
+	 * The bit 23 of the address bus is driven by GPIO 5
+	 * So for access greater than 8MB, we should set GPIO to 0 (It is at one by default)
+	 */
+	if (ofs >= SZ_8M)
+		comcerto_gpio_set_0(GPIO_5);
+	else
+		comcerto_gpio_set_1(GPIO_5);
+
+	/*We then call the generic function */
+	return inline_map_read(map, ofs);
+}
+
+static void comcertoflash_map_write(struct map_info *map, const map_word datum,
+				    unsigned long ofs)
+{
+	/*
+	 * On baord with NOR of 16MB
+	 * The bit 23 of the address bus is driven by GPIO 5
+	 * So for access greater than 8MB, we should set GPIO to 0 (It is at one by default)
+	 */
+	if (ofs >= SZ_8M)
+		comcerto_gpio_set_0(GPIO_5);
+	else
+		comcerto_gpio_set_1(GPIO_5);
+
+	/*We then call the generic function */
+	inline_map_write(map, datum, ofs);
+}
+
+static void comcertoflash_map_copy_from(struct map_info *map, void *to,
+					unsigned long from, ssize_t len)
+{
+	/*
+	 * On baord with NOR of 16MB
+	 * The bit 23 of the address bus is driven by GPIO 5
+	 * So for access greater than 8MB, we should set GPIO to 0 (It is at one by default)
+	 */
+	if (from >= SZ_8M)
+		comcerto_gpio_set_0(GPIO_5);
+	else
+		comcerto_gpio_set_1(GPIO_5);
+
+	/* We then call the generic function */
+	inline_map_copy_from(map, to, from, len);
+}
+
+static void comcertoflash_map_copy_to(struct map_info *map, unsigned long to,
+				      const void *from, ssize_t len)
+{
+	/*
+	 * On baord with NOR of 16MB
+	 * The bit 23 of the address bus is driven by GPIO 5
+	 * So for access greater than 8MB, we should set GPIO to 0 (It is at one by default)
+	 */
+	if (to >= SZ_8M)
+		comcerto_gpio_set_0(GPIO_5);
+	else
+		comcerto_gpio_set_1(GPIO_5);
+
+	/*We then call the generic function */
+	inline_map_copy_to(map, to, from, len);
+}
+#endif
+
+static int __devinit comcertoflash_probe(struct platform_device *pdev)
+{
+	int err;
+	struct comcertoflash_info *info;
+	struct flash_platform_data *pdata = pdev->dev.platform_data;
+        struct comcertoflash_board_data *board_data = pdev->dev.driver_data;
+	struct resource *res = pdev->resource;
+	unsigned long size = res->end - res->start + 1;
+
+	info = kmalloc(sizeof(struct comcertoflash_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	memset(info, 0, sizeof(struct comcertoflash_info));
+
+	if (!request_mem_region(res->start, size, "flash")) {
+		err = -EBUSY;
+		goto out_free_info;
+	}
+
+	info->map.virt = ioremap(res->start, size);
+	if (!info->map.virt) {
+		err = -ENOMEM;
+		goto out_release_mem_region;
+	}
+
+	info->map.name = dev_name(&pdev->dev);
+	info->map.phys = res->start;
+	info->map.size = size;
+	info->map.bankwidth = pdata->width;
+	// info->map.set_vpp  = comcerto_set_vpp;
+
+#ifndef CONFIG_MTD_COMPLEX_MAPPINGS
+	simple_map_init(&info->map);
+#else
+	/*Set our own wrapper to read/write NOR */
+        if (board_data) {
+            /*New board-specific override */
+            info->map.read = board_data->read;
+            info->map.write = board_data->write;
+            info->map.copy_from = board_data->copy_from;
+            info->map.copy_to = board_data->copy_to;
+        } else {
+            /*Old code*/
+            /*Set our own wrapper to read/write NOR */
+            info->map.read = comcertoflash_map_read;
+            info->map.write = comcertoflash_map_write;
+            info->map.copy_from = comcertoflash_map_copy_from;
+            info->map.copy_to = comcertoflash_map_copy_to;
+        }
+#endif
+
+	info->mtd = do_map_probe(pdata->map_name, &info->map);
+	if (!info->mtd) {
+		err = -EIO;
+		goto out_iounmap;
+	}
+	info->mtd->owner = THIS_MODULE;
+
+#ifdef CONFIG_MTD_PARTITIONS
+	err = parse_mtd_partitions(info->mtd, part_probes, &info->parts, 0);
+	if (err > 0)
+		add_mtd_partitions(info->mtd, info->parts, err);
+	else if (err < 0 && pdata->parts)
+		add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
+	else
+#endif
+		add_mtd_device(info->mtd);
+
+	platform_set_drvdata(pdev, info);
+
+	return 0;
+
+      out_iounmap:
+	iounmap(info->map.virt);
+      out_release_mem_region:
+	release_mem_region(res->start, size);
+      out_free_info:
+	kfree(info);
+
+	return err;
+}
+
+static int __devexit comcertoflash_remove(struct platform_device *pdev)
+{
+	struct comcertoflash_info *info = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (info) {
+#ifdef CONFIG_MTD_PARTITIONS
+		if (info->parts) {
+			del_mtd_partitions(info->mtd);
+			kfree(info->parts);
+		} else
+#endif
+			del_mtd_device(info->mtd);
+
+		map_destroy(info->mtd);
+		release_mem_region(info->map.phys, info->map.size);
+		iounmap((void __iomem *)info->map.virt);
+		kfree(info);
+	}
+
+	return 0;
+}
+
+static struct platform_driver comcertoflash_driver = {
+	.probe = comcertoflash_probe,
+	.remove = __devexit_p(comcertoflash_remove),
+	.driver = {
+		   .name = "comcertoflash",
+		   },
+};
+
+static int __init comcertoflash_init(void)
+{
+	return platform_driver_register(&comcertoflash_driver);
+}
+
+static void __exit comcertoflash_exit(void)
+{
+	platform_driver_unregister(&comcertoflash_driver);
+}
+
+module_init(comcertoflash_init);
+module_exit(comcertoflash_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MTD NOR map driver for Mindspeed Comcerto boards");
diff -r 8280ecb6cbe1 -r ac71465c2912 drivers/mtd/nand/Kconfig
--- a/drivers/mtd/nand/Kconfig	Mon Aug 10 16:58:56 2009 -0500
+++ b/drivers/mtd/nand/Kconfig	Mon Aug 10 16:58:57 2009 -0500
@@ -83,6 +83,10 @@
 config MTD_NAND_IDS
 	tristate
 
+config MTD_NAND_COMCERTO
+	tristate "SmartMedia Card on Comcerto boards"
+	depends on MTD_NAND && ARCH_COMCERTO
+
 config MTD_NAND_AU1550
 	tristate "Au1550/1200 NAND support"
 	depends on SOC_AU1200 || SOC_AU1550
diff -r 8280ecb6cbe1 -r ac71465c2912 drivers/mtd/nand/Makefile
--- a/drivers/mtd/nand/Makefile	Mon Aug 10 16:58:56 2009 -0500
+++ b/drivers/mtd/nand/Makefile	Mon Aug 10 16:58:57 2009 -0500
@@ -19,6 +19,7 @@
 obj-$(CONFIG_MTD_NAND_H1900)		+= h1910.o
 obj-$(CONFIG_MTD_NAND_RTC_FROM4)	+= rtc_from4.o
 obj-$(CONFIG_MTD_NAND_SHARPSL)		+= sharpsl.o
+obj-$(CONFIG_MTD_NAND_COMCERTO)		+= comcerto-nand.o
 obj-$(CONFIG_MTD_NAND_TS7250)		+= ts7250.o
 obj-$(CONFIG_MTD_NAND_NANDSIM)		+= nandsim.o
 obj-$(CONFIG_MTD_NAND_CS553X)		+= cs553x_nand.o
diff -r 8280ecb6cbe1 -r ac71465c2912 drivers/mtd/nand/comcerto-nand.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/mtd/nand/comcerto-nand.c	Mon Aug 10 16:58:57 2009 -0500
@@ -0,0 +1,249 @@
+/*
+ *  linux/drivers/mtd/nand/comcerto-nand.c
+ *
+ *  Copyright (C) Mindspeed Technologies, Inc.
+ *
+ * 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.
+ *
+ *  Overview:
+ *   This is a device driver for the NAND flash device found on the
+ *   Comcerto board which utilizes the Toshiba TC58V64AFT part. This is
+ *   a 128Mibit (8MiB x 8 bits) NAND flash device.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <linux/platform_device.h>
+
+/*
+ * MTD structure for Comcerto board
+ */
+struct comcerto_nand_info {
+	struct mtd_partition *parts;
+	struct mtd_info *mtd;
+};
+
+/*
+ * Define partitions for flash device
+ */
+
+/* Partitions cominf from command line*/
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probes[] = { "cmdlinepart", NULL };
+#endif
+
+/*********************************************************************
+ * NAND Hardware functions
+ *
+ *********************************************************************/
+
+/* 
+ *	hardware specific access to control-lines
+*/
+void comcerto_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+	struct nand_chip *chip = mtd->priv;
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		if (ctrl & NAND_NCE)
+			comcerto_gpio_set_0(COMCERTO_NAND_CE);
+		else
+			comcerto_gpio_set_1(COMCERTO_NAND_CE);
+
+		if (ctrl & NAND_CLE)
+			comcerto_gpio_set_1(COMCERTO_NAND_CLE);
+		else
+			comcerto_gpio_set_0(COMCERTO_NAND_CLE);
+
+		if (ctrl & NAND_ALE)
+			comcerto_gpio_set_1(COMCERTO_NAND_ALE);
+		else
+			comcerto_gpio_set_0(COMCERTO_NAND_ALE);
+	}
+
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, chip->IO_ADDR_W);
+}
+
+int comcerto_nand_ready(struct mtd_info *mtd)
+{
+	return comcerto_gpio_read(COMCERTO_NAND_BR) ? 1 : 0;
+}
+
+/*********************************************************************
+ * NAND Probe
+ *
+ *********************************************************************/
+static int comcerto_nand_probe(struct platform_device *pdev)
+{
+	struct comcerto_nand_info *info;
+	struct mtd_info *mtd;
+	struct nand_chip *nand_device;
+	int err = 0;
+
+	/* Allocate memory for info structure */
+	info = kmalloc(sizeof(struct comcerto_nand_info), GFP_KERNEL);
+	if (!info) {
+		printk(KERN_ERR
+		       "comcerto nand: unable to allocate info structure\n");
+		err = -ENOMEM;
+		goto out;
+	}
+	memset(info, 0, sizeof(struct comcerto_nand_info));
+
+	/* Allocate memory for MTD device structure */
+	mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
+	if (!mtd) {
+		printk(KERN_ERR
+		       "comcerto nand: unable to allocate mtd info structure\n");
+		err = -ENOMEM;
+		goto out_info;
+	}
+	memset(mtd, 0, sizeof(struct mtd_info));
+
+	/* Link the private data with the MTD structure */
+	info->mtd = mtd;
+	mtd->owner = THIS_MODULE;
+
+	/* Allocate pointer to nand_device data */
+	nand_device = kmalloc(sizeof(struct nand_chip), GFP_KERNEL);	//(struct nand_chip *) (&comcerto_nand_mtd[1]);
+	if (!nand_device) {
+		printk(KERN_ERR
+		       "comcerto nand: unable to allocate nand chip structure\n");
+		err = -ENOMEM;
+		goto out_mtd;
+	}
+	memset(nand_device, 0, sizeof(struct nand_chip));
+
+	/* Link the private data with the MTD structure */
+	mtd->priv = nand_device;
+
+	/*Map physical address of nand into virtual space */
+	nand_device->IO_ADDR_R =
+	    ioremap_nocache(pdev->resource->start,
+			    pdev->resource->end - pdev->resource->start + 1);
+	if (nand_device->IO_ADDR_R == NULL) {
+		printk(KERN_ERR "comcerto nand: cannot map nand memory\n");
+		err = -EIO;
+		goto out_nand;
+	}
+	/* This is the same address to read and write */
+	nand_device->IO_ADDR_W = nand_device->IO_ADDR_R;
+
+	/* Set address of hardware control function */
+	nand_device->cmd_ctrl = comcerto_nand_hwcontrol;
+	nand_device->dev_ready = comcerto_nand_ready;
+
+	/* 20 us command delay time */
+	nand_device->chip_delay = 20;
+	nand_device->ecc.mode = NAND_ECC_SOFT;
+
+	/* Scan to find existence of the device */
+	if (nand_scan(mtd, 1)) {
+		err = -ENXIO;
+		goto out_ior;
+	}
+
+	/*Name of the mtd device */
+	mtd->name = dev_name(&pdev->dev);
+
+	/* Register the partitions */
+#ifdef CONFIG_MTD_PARTITIONS
+	err = parse_mtd_partitions(mtd, part_probes, &info->parts, 0);
+	if (err > 0) {
+		add_mtd_partitions(mtd, info->parts, err);
+	} else
+#endif
+		add_mtd_device(mtd);
+
+	err = 0;
+
+	/* Link the info stucture with platform_device */
+	platform_set_drvdata(pdev, info);
+
+	goto out;
+
+      out_ior:
+	iounmap(nand_device->IO_ADDR_R);
+      out_nand:
+	kfree(nand_device);
+      out_mtd:
+	kfree(mtd);
+      out_info:
+	kfree(info);
+      out:
+	return err;
+}
+
+/*********************************************************************
+ * NAND Remove
+ *
+ *********************************************************************/
+static int comcerto_nand_remove(struct platform_device *pdev)
+{
+	struct comcerto_nand_info *info =
+	    (struct comcerto_nand_info *)platform_get_drvdata(pdev);
+	struct mtd_info *mtd = info->mtd;
+	struct nand_chip *nand_device = (struct nand_chip *)mtd->priv;
+
+	platform_set_drvdata(pdev, NULL);
+
+	/* Unregister the device */
+#ifdef CONFIG_MTD_PARTITIONS
+	if (info->parts) {
+		del_mtd_partitions(info->mtd);
+		kfree(info->parts);
+	} else
+#endif
+		del_mtd_device(mtd);
+
+	/*Deregister virtual address */
+	iounmap(nand_device->IO_ADDR_R);
+
+	kfree(nand_device);
+
+	/* Free the MTD device structure */
+	kfree(mtd);
+
+	kfree(info);
+
+	return 0;
+}
+
+/*********************************************************************
+ * Driver Registration
+ *
+ *********************************************************************/
+
+static struct platform_driver comcerto_nand_driver = {
+	.probe = comcerto_nand_probe,
+	.remove = __devexit_p(comcerto_nand_remove),
+	.driver = {
+		   .name = "comcertonand",
+		   },
+};
+
+int __init comcerto_nand_init(void)
+{
+	return platform_driver_register(&comcerto_nand_driver);
+}
+
+static void __exit comcerto_nand_exit(void)
+{
+	platform_driver_unregister(&comcerto_nand_driver);
+}
+
+module_init(comcerto_nand_init);
+module_exit(comcerto_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on Comcerto board");
diff -r 8280ecb6cbe1 -r ac71465c2912 include/linux/mtd/comcerto-nor.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/linux/mtd/comcerto-nor.h	Mon Aug 10 16:58:57 2009 -0500
@@ -0,0 +1,30 @@
+/*
+ *  linux/include/linux/mtd/comcerto-nor.h
+ *
+ *  Copyright (C) 2004,2006,2007 Mindspeed Technologies, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+struct comcertoflash_board_data {
+#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
+    /* provide custom flash mapping functions if necessary for board */
+    map_word (*read)(struct map_info *, unsigned long);
+    void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t);
+    
+    void (*write)(struct map_info *, const map_word, unsigned long);
+    void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);
+#endif
+};
