User: Password:
|
|
Subscribe / Log in / New account

Support for Toshiba TMIO multifunction devices

From:  ian <spyro@f2s.com>
To:  eric miao <eric.y.miao@gmail.com>
Subject:  [UPDATED PATCH] Support for Toshiba TMIO multifunction devices
Date:  Thu, 22 Nov 2007 00:34:09 +0000
Message-ID:  <1195691649.2329.105.camel@wirenth>
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>

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



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Copyright © 2007, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds