Index: linux-2.6.30.9/drivers/i2c/busses/Kconfig
===================================================================
--- linux-2.6.30.9.orig/drivers/i2c/busses/Kconfig	2009-11-24 21:00:21.000000000 +0100
+++ linux-2.6.30.9/drivers/i2c/busses/Kconfig	2009-11-24 21:00:23.000000000 +0100
@@ -326,6 +326,10 @@
 	  devices such as DaVinci NIC.
 	  For details please see http://www.ti.com/davinci
 
+config I2C_EP93XX
+	tristate "EP93XX I2C"
+	depends on I2C && ARCH_EP93XX
+
 config I2C_GPIO
 	tristate "GPIO-based bitbanging I2C"
 	depends on GENERIC_GPIO
Index: linux-2.6.30.9/drivers/i2c/busses/Makefile
===================================================================
--- linux-2.6.30.9.orig/drivers/i2c/busses/Makefile	2009-11-24 21:00:21.000000000 +0100
+++ linux-2.6.30.9/drivers/i2c/busses/Makefile	2009-11-24 21:00:23.000000000 +0100
@@ -30,6 +30,7 @@
 obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
 obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o
+obj-$(CONFIG_I2C_EP93XX)	+= i2c-ep93xx.o
 obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
 obj-$(CONFIG_I2C_HIGHLANDER)	+= i2c-highlander.o
 obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
Index: linux-2.6.30.9/drivers/i2c/busses/i2c-ep93xx.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.30.9/drivers/i2c/busses/i2c-ep93xx.c	2009-11-24 21:00:38.000000000 +0100
@@ -0,0 +1,193 @@
+/* ------------------------------------------------------------------------ *
+ * i2c-ep933xx.c I2C bus glue for Cirrus EP93xx                             *
+ * ------------------------------------------------------------------------ *
+
+   Copyright (C) 2004 Michael Burian
+
+   Based on i2c-parport-light.c
+   Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
+
+   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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ------------------------------------------------------------------------ */
+
+
+//#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+
+//1/(2*clockfrequency)
+#define EE_DELAY_USEC       50
+#define GPIOG_EECLK 1
+#define GPIOG_EEDAT 2
+
+/* ----- I2C algorithm call-back functions and structures ----------------- */
+
+// TODO: optimize
+static void ep93xx_setscl(void *data, int state)
+{
+	unsigned int uiPGDR, uiPGDDR;
+
+	uiPGDR = inl(GPIO_PGDR);
+	uiPGDDR = inl(GPIO_PGDDR);
+
+	/* Configure the clock line as output. */
+	uiPGDDR |= GPIOG_EECLK;
+	outl(uiPGDDR, GPIO_PGDDR);
+
+	/* Set clock line to state */
+	if(state)
+		uiPGDR |= GPIOG_EECLK;
+	else
+		uiPGDR &= ~GPIOG_EECLK;
+
+	outl(uiPGDR, GPIO_PGDR);
+}
+
+static void ep93xx_setsda(void *data, int state)
+{
+	unsigned int uiPGDR, uiPGDDR;
+
+	uiPGDR = inl(GPIO_PGDR);
+	uiPGDDR = inl(GPIO_PGDDR);
+
+	/* Configure the data line as output. */
+	uiPGDDR |= GPIOG_EEDAT;
+	outl(uiPGDDR, GPIO_PGDDR);
+
+	/* Set data line to state */
+	if(state)
+		uiPGDR |= GPIOG_EEDAT;
+	else
+		uiPGDR &= ~GPIOG_EEDAT;
+
+	outl(uiPGDR, GPIO_PGDR);
+}
+
+static int ep93xx_getscl(void *data)
+{
+	unsigned int uiPGDR, uiPGDDR;
+
+	uiPGDR = inl(GPIO_PGDR);
+	uiPGDDR = inl(GPIO_PGDDR);
+
+	/* Configure the clock line as input */
+	uiPGDDR &= ~GPIOG_EECLK;
+	outl(uiPGDDR, GPIO_PGDDR);
+
+	/* Return state of the clock line */
+	return (inl(GPIO_PGDR) & GPIOG_EECLK) ? 1 : 0;
+}
+
+static int ep93xx_getsda(void *data)
+{
+	unsigned int uiPGDR, uiPGDDR;
+	uiPGDR = inl(GPIO_PGDR);
+	uiPGDDR = inl(GPIO_PGDDR);
+
+	/* Configure the data line as input */
+	uiPGDDR &= ~GPIOG_EEDAT;
+	outl(uiPGDDR, GPIO_PGDDR);
+
+	/* Return state of the data line */
+	return (inl(GPIO_PGDR) & GPIOG_EEDAT) ? 1 : 0;
+}
+
+/* ------------------------------------------------------------------------
+ * Encapsulate the above functions in the correct operations structure.
+ * This is only done when more than one hardware adapter is supported.
+ */
+
+/* last line (us, ms, timeout)
+ * us dominates the bit rate: 10us  means: 100Kbit/sec(25 means 40kbps)
+ *                            10ms  not known
+ *                            100ms timeout
+ */
+static struct i2c_algo_bit_data ep93xx_data = {
+	.setsda		= ep93xx_setsda,
+	.setscl		= ep93xx_setscl,
+	.getsda		= ep93xx_getsda,
+	.getscl		= ep93xx_getscl,
+	.udelay		= 10,
+	//.mdelay		= 10,
+	.timeout	= HZ,
+};
+
+/* ----- I2c structure ---------------------------------------------------- */
+static struct i2c_adapter ep93xx_adapter = {
+	.owner		= THIS_MODULE,
+	.class		= I2C_CLASS_HWMON,
+	.algo_data	= &ep93xx_data,
+	.name		= "EP93XX I2C bit-bang interface",
+};
+
+/* ----- Module loading, unloading and information ------------------------ */
+
+static int __init i2c_ep93xx_init(void)
+{
+	unsigned long uiPGDR, uiPGDDR;
+
+	/* Read the current value of the GPIO data and data direction registers. */
+	uiPGDR = inl(GPIO_PGDR);
+	uiPGDDR = inl(GPIO_PGDDR);
+
+	/* If the GPIO pins have not been configured since reset, the data
+	 * and clock lines will be set as inputs and with data value of 0.
+	 * External pullup resisters are pulling them high.
+	 * Set them both high before configuring them as outputs. */
+	uiPGDR |= (GPIOG_EEDAT | GPIOG_EECLK);
+	outl(uiPGDR, GPIO_PGDR);
+
+	/* Delay to meet the EE Interface timing specification. */
+	udelay(EE_DELAY_USEC);
+
+
+	/* Configure the EE data and clock lines as outputs. */
+	uiPGDDR |= (GPIOG_EEDAT | GPIOG_EECLK);
+	outl(uiPGDDR, GPIO_PGDDR);
+
+	/* Delay to meet the EE Interface timing specification. */
+	udelay(EE_DELAY_USEC);
+
+	/* Reset hardware to a sane state (SCL and SDA high) */
+	ep93xx_setsda(NULL, 1);
+	ep93xx_setscl(NULL, 1);
+
+	if (i2c_bit_add_bus(&ep93xx_adapter) > 0) {
+		printk(KERN_ERR "i2c-ep93xx: Unable to register with I2C\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit i2c_ep93xx_exit(void)
+{
+	//i2c_bit_del_bus(&ep93xx_adapter);
+	i2c_del_adapter(&ep93xx_adapter);
+}
+
+MODULE_AUTHOR("Michael Burian");
+MODULE_DESCRIPTION("I2C bus glue for Cirrus EP93xx processors");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_ep93xx_init);
+module_exit(i2c_ep93xx_exit);
