All of lore.kernel.org
 help / color / mirror / Atom feed
From: ian <spyro@f2s.com>
To: eric miao <eric.y.miao@gmail.com>
Cc: Dmitry Baryshkov <dbaryshkov@gmail.com>,
	ARM Linux <linux-arm-kernel@lists.arm.linux.org.uk>,
	linux-kernel@vger.kernel.org,
	Russell King - ARM Linux <linux@arm.linux.org.uk>
Subject: [UPDATED PATCH] Support for Toshiba TMIO multifunction devices
Date: Thu, 22 Nov 2007 00:34:09 +0000	[thread overview]
Message-ID: <1195691649.2329.105.camel@wirenth> (raw)
In-Reply-To: <f17812d70711202005m110ae880m5ba195988e57a638@mail.gmail.com>

On Wed, 2007-11-21 at 12:05 +0800, eric miao wrote:
> On Nov 21, 2007 11:54 AM, ian <spyro@f2s.com> wrote:
> > On Wed, 2007-11-21 at 10:23 +0800, eric miao wrote:
> > > Roughly went through the patch, looks good, here comes the remind, though :-)
> > >
> > > 1. is it possible to use some name other than "soc_core", maybe
> > > "tmio_core" so that other multifunction chips sharing a core base
> > > will live easier.
> >
> > It's (soc-core) not tmio MFD specific - its already used by other MFD
> > chips (although obviously not ones in mainline (yet!)

I've renamed soc-core to mfd-core in the patches attached to this
message.

> > > 2. those C++ style comments "//" are not so pleasant...
> >
> > Should I clean them up and resubmit?
> 
> Will be nice then, anyway, could you inline them so others can comment?

All done.

> Well, I briefly went through the git history, looks like Russell is the proper
> one you could sent them to (probably not) :-)

I've added RMK to the CC.

I've ommitted the platform support for e-series - I'll send that to RMK
once this is merged.

Patches follow:

>From 9c4ffb764ae2366368a0038a6fbdd9a19ce430c4 Mon Sep 17 00:00:00 2001
From: Ian Molton <spyro@f2s.com>
Date: Wed, 21 Nov 2007 23:32:37 +0000
Subject: [PATCH] Reuseable MFD core code suitable for multifunction
chips with
 built in IRQ multiplexing and local RAM.

---
 drivers/mfd/Kconfig    |   25 ++++++++++++
 drivers/mfd/Makefile   |    3 +
 drivers/mfd/mfd-core.c |  102
++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/mfd/mfd-core.h |   26 ++++++++++++
 include/linux/ioport.h |    3 +
 5 files changed, 159 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mfd/mfd-core.c
 create mode 100644 drivers/mfd/mfd-core.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 2571619..38edfdc 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -15,6 +15,31 @@ config MFD_SM501
 	  interface. The device may be connected by PCI or local bus with
 	  varying functions enabled.
 
+config MFD_T7L66XB
+	bool "Toshiba T7L66XB SoC support"
+	---help---
+	  This driver supports the T7L66XB, which incorporates SD/MMC, and
+	  USB host functionality. associated subdevices are:
+	      tmio_mmc
+	      tmio_ohci
+
+config MFD_TC6387XB
+	bool "Toshiba TC6387XB SoC support"
+	---help---
+	  This driver supports the TC6393XB, which incorporates SD/MMC, NAND,
+	  Video, and USB host functionality. associated subdevices are:
+	      tmio_mmc
+
+config MFD_TC6393XB
+	bool "Toshiba TC6393XB SoC support"
+	---help---
+	  This driver supports the TC6393XB, which incorporates SD/MMC, NAND,
+	  Video, and USB host functionality. associated subdevices are:
+	      tmio_mmc
+	      tmio_nand
+	      tmio_fb
+	      tmio_ohci
+
 endmenu
 
 menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 5143209..5ae3877 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -3,6 +3,9 @@
 #
 
 obj-$(CONFIG_MFD_SM501)		+= sm501.o
+obj-$(CONFIG_MFD_T7L66XB)       += t7l66xb.o  mfd-core.o
+obj-$(CONFIG_MFD_TC6387XB)      += tc6387xb.o mfd-core.o
+obj-$(CONFIG_MFD_TC6393XB)      += tc6393xb.o mfd-core.o
 
 obj-$(CONFIG_MCP)		+= mcp-core.o
 obj-$(CONFIG_MCP_SA11X0)	+= mcp-sa11x0.o
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
new file mode 100644
index 0000000..e668c92
--- /dev/null
+++ b/drivers/mfd/mfd-core.c
@@ -0,0 +1,102 @@
+/*
+ * drivers/mfd/mfd-core.c
+ *
+ * core MFD support
+ * Copyright (c) 2006 Ian Molton
+ *
+ * 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/ioport.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include "mfd-core.h"
+
+void mfd_free_devices(struct platform_device *devices, int nr_devs)
+{
+	struct platform_device *dev = devices;
+	int i;
+
+	for (i = 0; i < nr_devs; i++) {
+		struct resource *res = dev->resource;
+		platform_device_unregister(dev++);
+		kfree(res);
+	}
+	kfree(devices);
+}
+EXPORT_SYMBOL_GPL(mfd_free_devices);
+
+#define SIGNED_SHIFT(val, shift) ((shift) >= 0 ? ((val) << (shift)) :
((val) >> -(shift)))
+
+struct platform_device *mfd_add_devices(struct platform_device *dev,
+					struct mfd_device_data *mfd, int nr_devs,
+					struct resource *mem,
+					int relative_addr_shift, int irq_base)
+{
+	struct platform_device *devices;
+	int i, r, base;
+
+	devices = kzalloc(nr_devs * sizeof(struct platform_device),
GFP_KERNEL);
+	if (!devices)
+		return NULL;
+
+	for (i = 0; i < nr_devs; i++) {
+		struct platform_device *sdev = &devices[i];
+		struct mfd_device_data *blk = &mfd[i];
+		struct resource *res;
+
+		sdev->id = -1;
+		sdev->name = blk->name;
+
+		sdev->dev.parent = &dev->dev;
+		sdev->dev.platform_data = (void *)blk->hwconfig;
+		sdev->num_resources = blk->num_resources;
+
+		/* Allocate space for the subdevice resources */
+		res = kzalloc(blk->num_resources * sizeof (struct resource),
GFP_KERNEL);
+		if (!res)
+			goto fail;
+
+		for (r = 0; r < blk->num_resources; r++) {
+			res[r].name = blk->res[r].name; // Fixme - should copy
+
+			/* Find out base to use */
+			base = 0;
+			if (blk->res[r].flags & IORESOURCE_MEM) {
+				base = mem->start;
+			} else if ((blk->res[r].flags & IORESOURCE_IRQ) &&
+				(blk->res[r].flags & IORESOURCE_IRQ_MFD_SUBDEVICE)) {
+				base = irq_base;
+			}
+
+			/* Adjust resource */
+			if (blk->res[r].flags & IORESOURCE_MEM) {
+				res[r].parent = mem;
+				res[r].start = base + SIGNED_SHIFT(blk->res[r].start,
relative_addr_shift);
+				res[r].end   = base + SIGNED_SHIFT(blk->res[r].end,
relative_addr_shift);
+			} else {
+				res[r].start = base + blk->res[r].start;
+				res[r].end   = base + blk->res[r].end;
+			}
+			res[r].flags = blk->res[r].flags;
+		}
+
+		sdev->resource = res;
+		if (platform_device_register(sdev)) {
+			kfree(res);
+			goto fail;
+		}
+
+		printk(KERN_INFO "MFD: registering %s\n", blk->name);
+	}
+	return devices;
+
+fail:
+	mfd_free_devices(devices, i + 1);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(mfd_add_devices);
diff --git a/drivers/mfd/mfd-core.h b/drivers/mfd/mfd-core.h
new file mode 100644
index 0000000..b65803d
--- /dev/null
+++ b/drivers/mfd/mfd-core.h
@@ -0,0 +1,26 @@
+/*
+ * drivers/mfd/mfd-core.h
+ *
+ * core MFD support
+ * Copyright (c) 2006 Ian Molton
+ *
+ * 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.
+ *
+ */
+
+struct mfd_device_data {
+	char *name;
+	struct resource *res;
+	int num_resources;
+	void *hwconfig; /* platform_data to pass to the subdevice */
+};
+
+struct platform_device *mfd_add_devices(struct platform_device *dev,
+					struct mfd_device_data *mfd, int n_devs,
+					struct resource *mem,
+					int relative_addr_shift, int irq_base);
+
+void mfd_free_devices(struct platform_device *devices, int nr_devs);
+
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 6187a85..5e8360a 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -57,6 +57,9 @@ struct resource_list {
 #define IORESOURCE_IRQ_LOWLEVEL		(1<<3)
 #define IORESOURCE_IRQ_SHAREABLE	(1<<4)
 
+/* MFD device IRQ specific bits (IORESOURCE_BITS) */
+#define IORESOURCE_IRQ_MFD_SUBDEVICE    (1<<5)
+
 /* ISA PnP DMA specific bits (IORESOURCE_BITS) */
 #define IORESOURCE_DMA_TYPE_MASK	(3<<0)
 #define IORESOURCE_DMA_8BIT		(0<<0)
-- 
1.5.3.5.737.gdee1b

>From 53de37ad4c365b801ed2a5248272bed82958b908 Mon Sep 17 00:00:00 2001
From: Ian Molton <spyro@f2s.com>
Date: Thu, 22 Nov 2007 00:17:41 +0000
Subject: [PATCH] Preliminary support for Toshibas TMIO based
multifunction chips.

        Includes support for:
         * t7l66xb
         * tc6387xb
         * tc6393xb
---
 drivers/mfd/t7l66xb.c     |  291 +++++++++++++++++++++++++++++++++++
 drivers/mfd/tc6387xb.c    |  143 +++++++++++++++++
 drivers/mfd/tc6393xb.c    |  374
+++++++++++++++++++++++++++++++++++++++++++++
 include/linux/t7l66xb.h   |   56 +++++++
 include/linux/tc6387xb.h  |   34 ++++
 include/linux/tc6393.h    |  136 ++++++++++++++++
 include/linux/tmio_mmc.h  |   26 +++
 include/linux/tmio_nand.h |   15 ++
 include/linux/tmio_ohci.h |   15 ++
 9 files changed, 1090 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mfd/t7l66xb.c
 create mode 100644 drivers/mfd/tc6387xb.c
 create mode 100644 drivers/mfd/tc6393xb.c
 create mode 100644 include/linux/t7l66xb.h
 create mode 100644 include/linux/tc6387xb.h
 create mode 100644 include/linux/tc6393.h
 create mode 100644 include/linux/tmio_mmc.h
 create mode 100644 include/linux/tmio_nand.h
 create mode 100644 include/linux/tmio_ohci.h

diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
new file mode 100644
index 0000000..3b74542
--- /dev/null
+++ b/drivers/mfd/t7l66xb.c
@@ -0,0 +1,291 @@
+/*
+ * drivers/mfd/t7l66xb.c
+ *
+ * Toshiba T7L66XB support
+ * Copyright (c) 2005 Ian Molton
+ *
+ * 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.
+ *
+ * This is based on my and Dirk Opfers work on the tc6393xb SoC.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/io.h>
+#include <asm/arch/pxa-regs.h>
+
+#include <linux/t7l66xb.h>
+#include <linux/tmio_mmc.h>
+#include "mfd-core.h"
+
+#define platform_get_platdata(_dev)      ((_dev)->dev.platform_data)
+
+struct t7l66xb_data
+{
+	int irq_base, irq_nr;
+	void *mapbase;
+	struct platform_device *devices;
+	int ndevices;
+};
+
+struct tmio_ohci_hwconfig t7l66xb_ohci_hwconfig = {
+	.start = NULL,
+};
+
+static struct resource t7l66xb_mmc_resources[] = {
+	{
+		.name = "control",
+		.start = T7L66XB_MMC_CTL_BASE,
+		.end   = T7L66XB_MMC_CTL_BASE + 0x1ff,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "config",
+		.start = T7L66XB_MMC_CNF_BASE,
+		.end   = T7L66XB_MMC_CNF_BASE + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = T7L66XB_MMC_IRQ,
+		.end = T7L66XB_MMC_IRQ,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_MFD_SUBDEVICE,
+	},
+};
+
+static struct mfd_device_data t7l66xb_devices[] = {
+	{
+		.name = "tmio_mmc",
+		.res = t7l66xb_mmc_resources,
+		.num_resources = ARRAY_SIZE(t7l66xb_mmc_resources),
+	},
+};
+
+/* Handle the T7L66XB interrupt mux */
+static void t7l66xb_irq_handler(unsigned int irq, struct irq_desc
*desc)
+{
+	int req, i;
+	struct t7l66xb_data *data = get_irq_data(irq);
+
+	/* Acknowledge the parent IRQ */
+	desc->chip->ack(irq);
+  
+	while ( (req = (readb(data->mapbase + T7L66XB_SYS_ISR)
+			& ~(readb(data->mapbase + T7L66XB_SYS_IMR)))) ) {
+		for (i = 0; i <= 7; i++) {
+			int dev_irq = data->irq_base + i;
+			struct irq_desc *d = NULL;
+			if ((req & (1<<i))) {
+				d = irq_desc + dev_irq;
+				d->handle_irq(dev_irq, d);
+			}
+		}
+	}
+}
+
+
+static void t7l66xb_mask_irq(unsigned int irq)
+{
+	struct t7l66xb_data *data = get_irq_chip_data(irq);
+
+	writeb(readb(data->mapbase + T7L66XB_SYS_IMR) | 1 << (irq -
data->irq_base), data->mapbase + T7L66XB_SYS_IMR);
+}
+
+static void t7l66xb_unmask_irq(unsigned int irq)
+{
+	struct t7l66xb_data *data = get_irq_chip_data(irq);
+
+	writeb(readb(data->mapbase + T7L66XB_SYS_IMR) & ~( 1 << (irq -
data->irq_base)),data->mapbase + T7L66XB_SYS_IMR);
+}
+
+static struct irq_chip t7l66xb_chip = {
+	.name   = "t7l66xb",
+	.ack	= t7l66xb_mask_irq,
+	.mask	= t7l66xb_mask_irq,
+	.unmask	= t7l66xb_unmask_irq,
+};
+
+/* Install the IRQ handler */
+static void t7l66xb_setup_irq(struct t7l66xb_data *tchip)
+{
+	int i;
+
+	for (i = 0; i < T7L66XB_NR_IRQS; i++) {
+		int irq = tchip->irq_base + i;
+		set_irq_chip (irq, &t7l66xb_chip);
+		set_irq_chip_data (irq, tchip);
+		set_irq_handler(irq, handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	set_irq_data (tchip->irq_nr, tchip);
+        set_irq_chained_handler (tchip->irq_nr, t7l66xb_irq_handler);
+	set_irq_type (tchip->irq_nr, IRQT_FALLING);
+}
+
+static void t7l66xb_hwinit(struct platform_device *dev)
+{
+	struct t7l66xb_platform_data *pdata = platform_get_platdata(dev);
+
+	if (pdata && pdata->hw_init)
+		pdata->hw_init();
+}
+
+
+#ifdef CONFIG_PM
+
+static int t7l66xb_suspend(struct platform_device *dev, pm_message_t
state)
+{
+	struct t7l66xb_platform_data *pdata = platform_get_platdata(dev);
+
+
+	if (pdata && pdata->suspend)
+		pdata->suspend();
+
+	return 0;
+}
+
+static int t7l66xb_resume(struct platform_device *dev)
+{
+	struct t7l66xb_platform_data *pdata = platform_get_platdata(dev);
+
+	if (pdata && pdata->resume)
+		pdata->resume();
+
+	t7l66xb_hwinit(dev);
+
+	return 0;
+}
+#endif
+
+static int t7l66xb_probe(struct platform_device *dev)
+{
+	struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
+	unsigned long pbase = (unsigned long)dev->resource[0].start;
+	unsigned long plen = dev->resource[0].end - dev->resource[0].start;
+	int err = -ENOMEM;
+	struct t7l66xb_data *data;
+
+	data = kmalloc (sizeof (struct t7l66xb_data), GFP_KERNEL);
+	if (!data)
+		goto out;
+
+	data->irq_base = pdata->irq_base;
+	data->irq_nr   = dev->resource[1].start;
+
+	if (!data->irq_base) {
+		printk("t7166xb: uninitialized irq_base!\n");
+		goto out_free_data;
+	}
+
+	data->mapbase = ioremap(pbase, plen);
+	if(!data->mapbase)
+		goto out_free_irqs;
+
+	platform_set_drvdata(dev, data);
+	t7l66xb_setup_irq(data);
+	t7l66xb_hwinit(dev);
+
+	/* Mask IRQs  -- should we mask/unmask on suspend/resume? */
+	writew(0xbf, data->mapbase + T7L66XB_SYS_IMR);
+
+	printk(KERN_INFO "%s rev %d @ 0x%08lx using irq %d-%d on irq %d\n",
+	       dev->name,  readw(data->mapbase + T7L66XB_SYS_RIDR),
+	       (unsigned long)data->mapbase, data->irq_base,
+	       data->irq_base + T7L66XB_NR_IRQS - 1, data->irq_nr);
+
+	data->devices = mfd_add_devices(dev, t7l66xb_devices,
+	                                ARRAY_SIZE(t7l66xb_devices),
+	                                &dev->resource[0], 0, data->irq_base);
+
+	if(!data->devices){
+		printk(KERN_INFO "%s: Failed to allocate devices!\n",
+		       dev->name);
+		goto out_free_devices;
+	}
+
+	return 0;
+
+out_free_devices:
+	mfd_free_devices(data->devices, ARRAY_SIZE(t7l66xb_devices));
+out_free_irqs:
+out_free_data:
+	kfree(data);
+out:
+	return err;
+}
+
+static int t7l66xb_remove(struct platform_device *dev)
+{
+	struct t7l66xb_data *tchip = platform_get_drvdata(dev);
+	int i;
+
+	/* Free the subdevice resources */
+	for (i = 0; i < tchip->ndevices; i++) {
+		platform_device_unregister (&tchip->devices[i]);
+		kfree (tchip->devices[i].resource);
+	}
+
+	/* Take down IRQ handling */
+        for (i = 0; i < T7L66XB_NR_IRQS; i++) {
+                int irq = i + tchip->irq_base;
+                set_irq_handler (irq, NULL);
+                set_irq_chip (irq, NULL);
+                set_irq_chip_data (irq, NULL);
+        }
+	set_irq_chained_handler (tchip->irq_nr, NULL);
+	
+	/* Free core resources */
+	iounmap (tchip->mapbase);
+	mfd_free_devices(tchip->devices, ARRAY_SIZE(t7l66xb_devices));
+	kfree (tchip);
+
+	return 0;
+}
+
+
+static struct platform_driver t7l66xb_platform_driver = {
+	.driver = {
+		.name		= "t7l66xb",
+	},
+	.probe		= t7l66xb_probe,
+	.remove		= t7l66xb_remove,
+#ifdef CONFIG_PM
+	.suspend	= t7l66xb_suspend,
+	.resume		= t7l66xb_resume,
+#endif
+};
+
+
+static int __init t7l66xb_init(void)
+{
+	int retval = 0;
+		
+	retval = platform_driver_register (&t7l66xb_platform_driver);
+	return retval;
+}
+
+static void __exit t7l66xb_exit(void)
+{
+	platform_driver_unregister(&t7l66xb_platform_driver);
+}
+
+module_init(t7l66xb_init);
+module_exit(t7l66xb_exit);
+
+MODULE_DESCRIPTION("Toshiba T7L66XB core driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ian Molton and Dirk Opfer");
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
new file mode 100644
index 0000000..d309b9f
--- /dev/null
+++ b/drivers/mfd/tc6387xb.c
@@ -0,0 +1,143 @@
+/*
+ * drivers/mfd/tc6387xb.c
+ *
+ * Toshiba TC6387XB support
+ * Copyright (c) 2005 Ian Molton
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <linux/tmio_mmc.h>
+#include <linux/tc6387xb.h>
+#include "mfd-core.h"
+
+struct tc6387xb_data {
+	int irq;
+	struct tc6387xb_platform_data *platform;
+};
+
+static void tc6387xb_hwinit(struct platform_device *dev)
+{
+	struct tc6387xb_data *data = platform_get_drvdata(dev);
+
+	if (data && data->platform && data->platform->hw_init)
+		data->platform->hw_init();
+
+}
+
+#ifdef CONFIG_PM
+
+static int tc6387xb_suspend(struct platform_device *dev, pm_message_t
state)
+{
+	struct tc6387xb_data *data = platform_get_drvdata(dev);
+
+	if (data && data->platform && data->platform->suspend)
+		data->platform->suspend();
+
+	return 0;
+}
+
+static int tc6387xb_resume(struct platform_device *dev)
+{
+	struct tc6387xb_data *data = platform_get_drvdata(dev);
+
+	if (data && data->platform && data->platform->resume)
+		data->platform->resume();
+
+	return 0;
+}
+#endif
+
+static struct resource tc6387xb_mmc_resources[] = {
+        {
+                .name = "control",
+                .start = TC6387XB_MMC_CTL_BASE,
+                .end   = TC6387XB_MMC_CTL_BASE + 0x1ff,
+                .flags = IORESOURCE_MEM,
+        },
+        {
+                .name = "config",
+                .start = TC6387XB_MMC_CNF_BASE,
+                .end   = TC6387XB_MMC_CNF_BASE + 0xff,
+                .flags = IORESOURCE_MEM,
+        },
+        {
+                .start = TC6387XB_MMC_IRQ,
+                .end   = TC6387XB_MMC_IRQ,
+                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_MFD_SUBDEVICE,
+        },
+};
+
+static struct mfd_device_data tc6387xb_devices[] = {
+        {
+                .name = "tmio_mmc",
+                .res = tc6387xb_mmc_resources,
+                .num_resources = ARRAY_SIZE(tc6387xb_mmc_resources),
+        },
+};
+
+
+static int tc6387xb_probe(struct platform_device *pdev)
+{
+	struct tc6387xb_data *data;
+
+	data = kmalloc(sizeof(struct tc6387xb_data), GFP_KERNEL);
+	if(!data)
+		return -ENOMEM;
+
+	data->irq = pdev->resource[1].start;
+	data->platform = pdev->dev.platform_data;
+	platform_set_drvdata(pdev, data);
+
+	tc6387xb_hwinit(pdev);
+	
+	mfd_add_devices(pdev, tc6387xb_devices, ARRAY_SIZE(tc6387xb_devices),
&pdev->resource[0], 0, data->irq);
+
+	/* Init finished. */
+	return 0;
+}
+
+static struct platform_driver tc6387xb_platform_driver = {
+	.driver = {
+		.name		= "tc6387xb",
+	},
+	.probe		= tc6387xb_probe,
+#ifdef CONFIG_PM
+	.suspend	= tc6387xb_suspend,
+	.resume		= tc6387xb_resume,
+#endif
+};
+
+
+static int __init tc6387xb_init(void)
+{
+	return platform_driver_register (&tc6387xb_platform_driver);
+}
+
+static void __exit tc6387xb_exit(void)
+{
+	platform_driver_unregister(&tc6387xb_platform_driver);
+}
+
+module_init(tc6387xb_init);
+module_exit(tc6387xb_exit);
+
+MODULE_DESCRIPTION("Toshiba TC6387XB core driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ian Molton");
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
new file mode 100644
index 0000000..860d67b
--- /dev/null
+++ b/drivers/mfd/tc6393xb.c
@@ -0,0 +1,374 @@
+/*
+ * drivers/mfd/tc6393xb.c
+ *
+ * Toshiba TC6393 support
+ * Copyright (c) 2005 Dirk Opfer
+ * Copyright (c) 2005 Ian Molton <spyro@f2s.com>
+ *
+ *	Based on code written by Sharp/Lineo for 2.4 kernels
+ *	Based on locomo.c
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/io.h>
+#include <asm/arch/pxa-regs.h>
+
+#include <linux/tmio_mmc.h>
+#include <linux/tmio_nand.h>
+#include <linux/tmio_ohci.h>
+#include <linux/tc6393.h>
+#include "mfd-core.h"
+
+#define platform_get_platdata(_dev)      ((_dev)->dev.platform_data)
+
+struct tc6393xb_data
+{
+	int irq_base, irq_nr;
+	void *mapbase;
+	struct platform_device *devices;
+	int ndevices;
+};
+
+/* Setup the TC6393XB NAND flash controllers configuration registers */
+static void tc6393xb_nand_hwinit(struct platform_device *sdev) {
+	
+	struct tc6393xb_data *chip = platform_get_drvdata(sdev);
+	
+	/* Sequence: 
+	 * SMD Buffer ON (gpio related)
+	 * Enable the clock (SCRUNEN)
+	 * Set the ctl reg base address
+	 * Enable the ctl reg
+	 * Configure power control (control bt PCNT[1,0] 4ms startup delay)
+	 */
+	/* (89h) SMD Buffer ON By TC6393XB SystemConfig gpibfc1*/
+	writew(0xff, chip->mapbase + TC6393_SYS_GPIBCR1);
+
+}
+
+static struct tmio_nand_hwconfig tc6393xb_nand_hwconfig = {
+	.hwinit  = tc6393xb_nand_hwinit,
+};
+
+static void tc6393xb_mmc_set_clock(struct platform_device *sdev, int
state) {
+	struct tc6393xb_data *chip = platform_get_drvdata(sdev);
+	unsigned char tmp;
+
+	if(state == MMC_CLOCK_ENABLED){
+		tmp = readw(chip->mapbase + TC6393_SYS_GPIBCR1);
+		writew(tmp | CK32KEN, chip->mapbase + TC6393_SYS_GPIBCR1);
+	}
+}
+
+static struct tmio_mmc_hwconfig tc6393xb_mmc_hwconfig = {
+        .set_mmc_clock  = tc6393xb_mmc_set_clock,
+};
+
+static struct resource tc6393xb_mmc_resources[] = {
+	{
+		.name = "control",
+		.start = TC6393XB_MMC_CTL_BASE,
+		.end   = TC6393XB_MMC_CTL_BASE + 0x1ff,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "config",
+		.start = TC6393XB_MMC_CNF_BASE,
+		.end   = TC6393XB_MMC_CNF_BASE + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = TC6393XB_MMC_IRQ,
+		.end   = TC6393XB_MMC_IRQ,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_MFD_SUBDEVICE,
+	},
+};
+
+static struct resource tc6393xb_nand_resources[] = {
+	{
+		.name = "control",
+		.start = TC6393XB_NAND_CTL_BASE,
+		.end   = TC6393XB_NAND_CTL_BASE + 0x1ff,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "config",
+		.start = TC6393XB_NAND_CNF_BASE,
+		.end   = TC6393XB_NAND_CNF_BASE + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static struct mfd_device_data tc6393xb_devices[] = {
+	{
+		.name = "tmio_mmc",
+		.res = tc6393xb_mmc_resources,
+		.num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
+		.hwconfig = &tc6393xb_mmc_hwconfig,
+	},
+	{
+		.name = "tmio-nand",
+		.res = tc6393xb_nand_resources,
+		.num_resources = ARRAY_SIZE(tc6393xb_nand_resources),
+		.hwconfig = &tc6393xb_nand_hwconfig,
+	},
+};
+
+/** TC6393 interrupt handling stuff.
+ * NOTE: TC6393 has a 1 to many mapping on all of its IRQs.
+ * that is, there is only one real hardware interrupt
+ * we determine which interrupt it is by reading some IO memory.
+ * We have two levels of expansion, first in the handler for the
+ * hardware interrupt we generate an interrupt
+ * IRQ_TC6393_*_BASE and those handlers generate more interrupts
+ *
+ */
+static void tc6393xb_irq_handler(unsigned int irq, struct irq_desc
*desc)
+{
+	int req, i;
+	struct tc6393xb_data *data = get_irq_data(irq);
+	
+	/* Acknowledge the parent IRQ */
+	desc->chip->ack(irq);
+  
+	while ( (req = (readb(data->mapbase + TC6393_SYS_ISR)
+			& ~(readb(data->mapbase + TC6393_SYS_IMR)))) ) {
+		for (i = 0; i <= 7; i++) {
+			int dev_irq = data->irq_base + i;
+			struct irq_desc *d = NULL;
+			if ((req & (1<<i))) {
+				if(i != 1)  printk("IRQ! from %d\n", i);
+				d = irq_desc + dev_irq;
+				d->handle_irq(dev_irq, d);
+			}
+		}
+	}
+}
+
+static void tc6393xb_mask_irq(unsigned int irq)
+{
+	struct tc6393xb_data *tc6393 = get_irq_chip_data(irq);
+
+	writeb(readb(tc6393->mapbase + TC6393_SYS_IMR) | 1 << (irq -
tc6393->irq_base),tc6393->mapbase + TC6393_SYS_IMR);
+}
+
+static void tc6393xb_unmask_irq(unsigned int irq)
+{
+	struct tc6393xb_data *tc6393 = get_irq_chip_data(irq);
+
+	writeb(readb(tc6393->mapbase + TC6393_SYS_IMR) & ~( 1 << (irq -
tc6393->irq_base)),tc6393->mapbase + TC6393_SYS_IMR);
+}
+
+static struct irq_chip tc6393xb_chip = {
+	.ack	= tc6393xb_mask_irq,
+	.mask	= tc6393xb_mask_irq,
+	.unmask	= tc6393xb_unmask_irq,
+};
+
+
+static void tc6393xb_setup_irq(struct tc6393xb_data *tchip)
+{
+	int i;
+	
+	for (i = 0; i < TC6393XB_NR_IRQS; i++) {
+		int irq = tchip->irq_base + i;
+		set_irq_chip (irq, &tc6393xb_chip);
+		set_irq_chip_data (irq, tchip);
+		set_irq_handler(irq, handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	set_irq_data (tchip->irq_nr, tchip);
+	set_irq_chained_handler (tchip->irq_nr, tc6393xb_irq_handler);
+	set_irq_type (tchip->irq_nr, IRQT_FALLING);
+}
+
+void tc6393xb_hwinit(struct platform_device *dev)
+{
+	struct tc6393xb_platform_data *pdata = platform_get_platdata(dev);
+	struct tc6393xb_data *tchip =  platform_get_drvdata(dev);
+
+	if(!pdata || !tchip){
+		BUG_ON("no driver data!\n");
+		return;
+	}
+
+	if (pdata->hw_init)
+		pdata->hw_init();
+		
+	writew(0, tchip->mapbase + TC6393_SYS_FER);
+
+	/* Clock setting */
+	writew(pdata->sys_pll2cr,   tchip->mapbase + TC6393_SYS_PLL2CR);
+	writew(pdata->sys_ccr,      tchip->mapbase + TC6393_SYS_CCR);
+	writew(pdata->sys_mcr,      tchip->mapbase + TC6393_SYS_MCR);
+
+  	/* GPIO */
+	writew(pdata->sys_gper,     tchip->mapbase + TC6393_SYS_GPER);
+	writew(pdata->sys_gpodsr1,  tchip->mapbase + TC6393_SYS_GPODSR1);
+	writew(pdata->sys_gpooecr1, tchip->mapbase + TC6393_SYS_GPOOECR1);
+}
+
+
+#ifdef CONFIG_PM
+
+static int tc6393xb_suspend(struct platform_device *dev, pm_message_t
state)
+{
+	struct tc6393xb_platform_data *pdata = platform_get_platdata(dev);
+
+	if (pdata && pdata->suspend)
+		pdata->suspend();
+
+	return 0;
+}
+
+static int tc6393xb_resume(struct platform_device *dev)
+{
+	struct tc6393xb_platform_data *pdata = platform_get_platdata(dev);
+
+	if (pdata && pdata->resume)
+		pdata->resume();
+
+	tc6393xb_hwinit(dev);
+
+	return 0;
+}
+
+#endif
+
+static int tc6393xb_probe(struct platform_device *dev)
+{
+	struct tc6393xb_platform_data *pdata = dev->dev.platform_data;
+	unsigned long pbase = (unsigned long)dev->resource[0].start;
+	unsigned long plen = dev->resource[0].end - dev->resource[0].start;
+	int err = -ENOMEM;
+	struct tc6393xb_data *data;
+
+	data = kmalloc (sizeof (struct tc6393xb_data), GFP_KERNEL);
+	if (!data)
+		goto out;
+
+	data->irq_base = pdata->irq_base;
+	data->irq_nr = dev->resource[1].start;
+
+	if (!data->irq_base) {
+		printk("tc6393xb: uninitialized irq_base!\n");
+		goto out_free_data;
+	}
+
+	data->mapbase = ioremap(pbase, plen);
+	if(!data->mapbase)
+		goto out_free_irqs;
+
+	platform_set_drvdata(dev, data);
+	tc6393xb_setup_irq (data);
+	tc6393xb_hwinit(dev);
+
+	/* Enable (but mask!) our IRQs */
+	writew(0,    data->mapbase + TC6393_SYS_IRR);
+	writew(0xbf, data->mapbase + TC6393_SYS_IMR);
+
+	printk(KERN_INFO "%s rev %d @ 0x%08lx using irq %d-%d on irq %d\n",
+	       dev->name,  readw(data->mapbase + TC6393_SYS_RIDR),
+	       (unsigned long)data->mapbase, data->irq_base,
+	       data->irq_base + TC6393XB_NR_IRQS - 1, data->irq_nr);
+
+	data->devices =  mfd_add_devices(dev, tc6393xb_devices,
+	                                ARRAY_SIZE(tc6393xb_devices),
+	                                &dev->resource[0], 0, data->irq_base);
+
+	if(!data->devices) {
+		printk(KERN_INFO "%s: Failed to allocate devices!\n",
+		       dev->name);
+		goto out_free_devices;
+	}
+
+	return 0;
+
+out_free_devices:
+	mfd_free_devices(data->devices, ARRAY_SIZE(tc6393xb_devices));
+out_free_irqs:
+out_free_data:
+	kfree(data);
+out:
+	return err;
+}
+
+static int tc6393xb_remove(struct platform_device *dev)
+{
+	struct tc6393xb_data *tchip = platform_get_drvdata(dev);
+	int i;
+
+	/* Free the subdevice resources */
+        for (i = 0; i < tchip->ndevices; i++) {
+                platform_device_unregister (&tchip->devices[i]);
+                kfree (tchip->devices[i].resource);
+        }
+
+	/* Take down IRQ handling */
+	for (i = 0; i < TC6393XB_NR_IRQS; i++) {
+		int irq = i + tchip->irq_base;
+		set_irq_handler (irq, NULL);
+		set_irq_chip (irq, NULL);
+		set_irq_chip_data (irq, NULL);
+	}
+	
+	set_irq_chained_handler (tchip->irq_nr, NULL);
+
+	/* Free core resources */
+        iounmap (tchip->mapbase);
+        mfd_free_devices(tchip->devices, ARRAY_SIZE(tc6393xb_devices));
+        kfree (tchip);
+
+	return 0;
+}
+
+
+static struct platform_driver tc6393xb_device_driver = {
+	.driver = {
+		.name		= "tc6393xb",
+	},
+	.probe		= tc6393xb_probe,
+	.remove		= tc6393xb_remove,
+#ifdef CONFIG_PM
+	.suspend	= tc6393xb_suspend,
+	.resume		= tc6393xb_resume,
+#endif
+};
+
+
+static int __init tc6393xb_init(void)
+{
+	int retval = 0;
+	retval = platform_driver_register (&tc6393xb_device_driver);
+	return retval;
+}
+
+static void __exit tc6393xb_exit(void)
+{
+	platform_driver_unregister(&tc6393xb_device_driver);
+}
+
+module_init(tc6393xb_init);
+module_exit(tc6393xb_exit);
+
+MODULE_DESCRIPTION("Toshiba TC6393 core driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dirk Opfer and Ian Molton");
diff --git a/include/linux/t7l66xb.h b/include/linux/t7l66xb.h
new file mode 100644
index 0000000..f2d013a
--- /dev/null
+++ b/include/linux/t7l66xb.h
@@ -0,0 +1,56 @@
+/*
+ *
+ * This file contains the definitions for the T7L66XB
+ *
+ * (C) Copyright 2005 Ian Molton <spyro@f2s.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ */
+
+#include <linux/platform_device.h>
+
+
+/* FIXME - this needs to be a common struct to all TMIO based MFDs. */
+struct tmio_hwconfig {
+	void (*hwinit)(struct platform_device *sdev);
+	void (*suspend)(struct platform_device *sdev);
+	void (*resume)(struct platform_device *sdev);
+};
+
+struct tmio_ohci_hwconfig {
+	void (*start)(struct platform_device *dev);
+};
+
+struct t7l66xb_platform_data
+{
+	/* Standard MFD properties */
+	int irq_base;
+	struct platform_device **child_devs;
+	int num_child_devs;
+
+	void (* hw_init) (void);
+	void (* suspend) (void);
+	void (* resume)  (void);
+};
+
+
+#define T7L66XB_NAND_CNF_BASE  (0x000100)
+#define T7L66XB_NAND_CTL_BASE  (0x001000)
+
+#define T7L66XB_MMC_CNF_BASE   (0x000200)
+#define T7L66XB_MMC_CTL_BASE   (0x000800)
+#define T7L66XB_MMC_IRQ        (1)
+
+#define T7L66XB_USB_CNF_BASE   (0x000300)
+#define T7L66XB_USB_CTL_BASE   (0x002000)
+#define T7L66XB_OHCI_IRQ       (0)
+
+/* System Configuration register */
+#define T7L66XB_SYS_RIDR    0x008        // Revision ID
+#define T7L66XB_SYS_ISR     0x0e1        // Interrupt Status
+#define T7L66XB_SYS_IMR     0x042        // Interrupt Mask
+
+#define T7L66XB_NR_IRQS	8
+
diff --git a/include/linux/tc6387xb.h b/include/linux/tc6387xb.h
new file mode 100644
index 0000000..99c01a3
--- /dev/null
+++ b/include/linux/tc6387xb.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * (C) Copyright 2005 Ian Molton <spyro@f2s.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ */
+
+#include <linux/platform_device.h>
+
+/* FIXME - this needs to be a common struct to all TMIO based MFDs. */
+struct tmio_hwconfig {
+	void (*hwinit)(struct platform_device *sdev);
+	void (*suspend)(struct platform_device *sdev);
+	void (*resume)(struct platform_device *sdev);
+};
+
+struct tc6387xb_platform_data
+{
+	/* Standard MFD properties */
+	int irq_base;
+	struct platform_device **child_devs;
+	int num_child_devs;
+
+	void (* hw_init) (void);
+	void (* suspend) (void);
+	void (* resume)  (void);
+};
+
+#define TC6387XB_MMC_CNF_BASE    (0x000200)
+#define TC6387XB_MMC_CTL_BASE    (0x000800)
+#define TC6387XB_MMC_IRQ         (0)
+
diff --git a/include/linux/tc6393.h b/include/linux/tc6393.h
new file mode 100644
index 0000000..99ecd42
--- /dev/null
+++ b/include/linux/tc6393.h
@@ -0,0 +1,136 @@
+/*
+ *
+ * (C) Copyright 2005 Dirk Opfer
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ */
+
+struct tc6393xb_platform_data
+{
+	/* Standard MFD properties */
+	int irq_base;
+	struct platform_device **child_devs;
+	int num_child_devs;
+
+	u16 sys_gper;
+	u16 sys_gpodsr1;
+	u16 sys_gpooecr1;
+	u16 sys_pll2cr;
+	u16 sys_ccr;
+	u16 sys_mcr;
+	void (* hw_init) (void);
+	void (* suspend) (void);
+	void (* resume)  (void);
+};
+
+#define CK32KEN 0x1
+#define USBCLK  0x2
+
+/*
+ TC6393XB Resource Area Map (Offset)
+  System Configration Register Area         0x00000000 - 0x000000FF 
+  NAND Flash Host Controller Register Area  0x00000100 - 0x000001FF 
+  USB Host Controller Register Area         0x00000300 - 0x000003FF
+  LCD Host Controller Register Area         0x00000500 - 0x000005FF
+  NAND Flash Control Register               0x00001000 - 0x00001007
+  USB Control Register                      0x00003000 - 0x000031FF
+  LCD Control Register                      0x00005000 - 0x000051FF
+  Local Memory 0 (32KB)                     0x00010000 - 0x00017FFF
+  Local Memory 0 (32KB) alias               0x00018000 - 0x0001FFFF
+  Local Memory 1 (1MB)                      0x00100000 - 0x001FFFFF
+*/
+
+#define TC6393_SYS_BASE		0
+
+#define TC6393XB_NAND_CNF_BASE	(TC6393_SYS_BASE + 0x000100)
+#define TC6393XB_NAND_CTL_BASE  (TC6393_SYS_BASE + 0x001000)
+
+#define TC6393XB_MMC_CNF_BASE	(TC6393_SYS_BASE + 0x000200)
+#define TC6393XB_MMC_CTL_BASE	(TC6393_SYS_BASE + 0x000800)
+#define TC6393XB_MMC_IRQ          (1)
+
+#define TC6393XB_USB_CNF_BASE   (TC6393_SYS_BASE + 0x000300)
+#define TC6393XB_USB_CTL_BASE   (TC6393_SYS_BASE + 0x000a00)
+#define TC6393XB_USB_IRQ        (0)
+
+#define TC6393_SERIAL_CONF_BASE	(TC6393_SYS_BASE + 0x000400)
+#define TC6393_GC_CONF_BASE	(TC6393_SYS_BASE + 0x000500)
+#define TC6393_RAM0_BASE	(TC6393_SYS_BASE + 0x010000)
+#define TC6393_RAM0_SIZE	(32*1024)
+#define TC6393_RAM1_BASE	(TC6393_SYS_BASE + 0x100000)
+#define TC6393_RAM1_SIZE	(64 * 1024 * 16)
+
+
+/* 
+ * Internal Local Memory use purpose
+ *   RAM0 is used for USB
+ *   RAM1 is used for GC
+ */
+/* Internal register mapping */
+#define TC6393_GC_INTERNAL_REG_BASE	0x000600	/* Length 0x200 */
+
+	
+/* System Configuration register */
+#define TC6393_SYS_RIDR		0x008			// Revision ID
+#define TC6393_SYS_ISR		0x050			// Interrupt Status
+#define TC6393_SYS_IMR		0x052			// Interrupt Mask
+#define TC6393_SYS_IRR		0x054			// Interrupt Routing
+#define TC6393_SYS_GPER		0x060			// GP Enable
+#define TC6393_SYS_GPAIOEN	0x061			// GP Alternative Enable
+#define TC6393_SYS_GPISR1	0x064			// GPI Status 1
+#define TC6393_SYS_GPISR2	0x066			// GPI Status 2
+#define TC6393_SYS_GPIIMR1	0x068			// GPI INT Mask 1
+#define TC6393_SYS_GPIIMR2	0x06A			// GPI INT Mask 2
+#define TC6393_SYS_GPIEDER1	0x06C			// GPI Edge Detect Enable 1
+#define TC6393_SYS_GPIEDER2	0x06E			// GPI Edge Detect Enable 2
+#define TC6393_SYS_GPILIR1	0x070			// GPI Level Invert 1
+#define TC6393_SYS_GPILIR2	0x072			// GPI Level Invert 2
+#define TC6393_SYS_GPODSR1	0x078			// GPO Data set 1
+#define TC6393_SYS_GPODSR2      0x07A			// GPO Data set 2
+#define TC6393_SYS_GPOOECR1     0x07C			// GPO Data OE Contorol 1
+#define TC6393_SYS_GPOOECR2     0x07E			// GPO Data OE Contorol 2
+#define TC6393_SYS_GPIARCR1     0x080			// GP Internal Active Register
Contorol 1
+#define TC6393_SYS_GPIARCR2     0x082			// GP Internal Active Register
Contorol 2
+#define TC6393_SYS_GPIARLCR1    0x084			// GP Internal Active Register
Level Contorol 1
+#define TC6393_SYS_GPIARLCR2    0x086			// GP Internal Active Register
Level Contorol 2
+
+#define TC6393_SYS_GPIBCR1      0x089			// GPa Internal Activ Register
Contorol 1
+
+#define TC6393_SYS_GPIBCR2      0x08A			// GPa Internal Activ Register
Contorol 2
+#define TC6393_SYS_GPaIARCR     0x08C			
+#define TC6393_SYS_GPaIARLCR    0x090
+#define TC6393_SYS_GPaIBCR      0x094
+#define TC6393_SYS_CCR          0x098			/* Clock Control Register */
+#define TC6393_SYS_PLL2CR       0x09A			// PLL2 Control
+#define TC6393_SYS_PLL1CR1      0x09C			// PLL1 Control 1
+#define TC6393_SYS_PLL1CR2      0x09E			// PLL1 Control 2
+#define TC6393_SYS_DCR          0x0A0
+#define TC6393_SYS_FER          0x0E0			/* Function Enable Register */
+#define TC6393_SYS_MCR          0x0E4
+#define TC6393_SYS_ConfigCR     0x0FC
+
+/* GPIO bit */
+#define TC6393_GPIO19  ( 1 << 19 )
+#define TC6393_GPIO18  ( 1 << 18 )
+#define TC6393_GPIO17  ( 1 << 17 )
+#define TC6393_GPIO16  ( 1 << 16 )
+#define TC6393_GPIO15  ( 1 << 15 )
+#define TC6393_GPIO14  ( 1 << 14 )
+#define TC6393_GPIO13  ( 1 << 13 )
+#define TC6393_GPIO12  ( 1 << 12 )
+#define TC6393_GPIO11  ( 1 << 11 )
+#define TC6393_GPIO10  ( 1 << 10 )
+#define TC6393_GPIO9   ( 1 << 9 )
+#define TC6393_GPIO8   ( 1 << 8 )
+#define TC6393_GPIO7   ( 1 << 7 )
+#define TC6393_GPIO6   ( 1 << 6 )
+#define TC6393_GPIO5   ( 1 << 5 )
+#define TC6393_GPIO4   ( 1 << 4 )
+#define TC6393_GPIO3   ( 1 << 3 )
+#define TC6393_GPIO2   ( 1 << 2 )
+#define TC6393_GPIO1   ( 1 << 1 )
+#define TC6393_GPIO0   ( 1 << 0 )
+
+#define TC6393XB_NR_IRQS	8
diff --git a/include/linux/tmio_mmc.h b/include/linux/tmio_mmc.h
new file mode 100644
index 0000000..00358bf
--- /dev/null
+++ b/include/linux/tmio_mmc.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2005 Ian Molton
+ *
+ * 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/platform_device.h>
+
+#define MMC_CLOCK_DISABLED 0
+#define MMC_CLOCK_ENABLED  1
+
+#define TMIO_WP_ALWAYS_RW ((void*)-1)
+
+struct tmio_mmc_hwconfig {
+	void (*hwinit)(struct platform_device *sdev);
+	void (*set_mmc_clock)(struct platform_device *sdev, int state);
+
+	/* NULL - use ASIC3 signal, 
+	   TMIO_WP_ALWAYS_RW - assume always R/W (e.g. miniSD) 
+	   otherwise - machine-specific handler */
+	int (*mmc_get_ro)(struct platform_device *pdev);
+	short address_shift;
+};
diff --git a/include/linux/tmio_nand.h b/include/linux/tmio_nand.h
new file mode 100644
index 0000000..e1b38eb
--- /dev/null
+++ b/include/linux/tmio_nand.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2005 Ian Molton
+ *
+ * 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.
+ *
+ */
+
+struct tmio_nand_hwconfig {
+        void (*hwinit)(struct platform_device *sdev);
+        void (*suspend)(struct platform_device *sdev);
+        void (*resume)(struct platform_device *sdev);
+};
+
diff --git a/include/linux/tmio_ohci.h b/include/linux/tmio_ohci.h
new file mode 100644
index 0000000..5d07083
--- /dev/null
+++ b/include/linux/tmio_ohci.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2005 Ian Molton
+ *
+ * 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.
+ *
+ */
+
+struct tmio_ohci_hwconfig {
+        void (*hwinit)(struct platform_device *sdev);
+        void (*suspend)(struct platform_device *sdev);
+        void (*resume)(struct platform_device *sdev);
+};
+
-- 
1.5.3.5.737.gdee1b




  reply	other threads:[~2007-11-22  0:37 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-11-20 20:40 [patch] 0/4 Support for Toshiba TMIO multifunction devices ian
2007-11-20 22:04 ` Dmitry Baryshkov
2007-11-20 22:20   ` ian
2007-11-21  2:23     ` eric miao
2007-11-21  3:54       ` ian
2007-11-21  4:05         ` eric miao
2007-11-22  0:34           ` ian [this message]
2007-11-22  0:52             ` [UPDATED PATCH] " Russell King - ARM Linux
2007-11-22 10:52               ` ian
2007-11-26 12:23                 ` Russell King - ARM Linux
2007-11-22  0:49         ` [patch] 0/4 " Anton Vorontsov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1195691649.2329.105.camel@wirenth \
    --to=spyro@f2s.com \
    --cc=dbaryshkov@gmail.com \
    --cc=eric.y.miao@gmail.com \
    --cc=linux-arm-kernel@lists.arm.linux.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@arm.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.