Index: openezx/drivers/i2c/chips/ezx-eoc.c
===================================================================
--- openezx.orig/drivers/i2c/chips/ezx-eoc.c	2008-12-01 01:20:21.000000000 +0800
+++ openezx/drivers/i2c/chips/ezx-eoc.c	2008-12-01 01:27:19.000000000 +0800
@@ -16,46 +16,12 @@
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/workqueue.h>
+#include <linux/mfd/ezx-pcap.h>
+#include <linux/mfd/ezx-eoc.h>
+
+static LIST_HEAD(event_list);
+static DEFINE_MUTEX(event_lock);
 
-#define EOC_REG_ADDR_SIZE		1
-#define EOC_REG_DATA_SIZE		3
-#define EOC_REG_INT_STATUS		32
-#define EOC_REG_INT_MASK		33
-#define EOC_REG_INT_SENSE		34
-#define EOC_REG_POWER_CONTROL_0		35
-#define EOC_REG_POWER_CONTROL_1		36
-#define EOC_REG_CONN_CONTROL		37
-
-#define EOC_INT_VBUS_3V4		(1 << 0)
-#define EOC_INT_VBUS			(1 << 1)
-#define EOC_INT_VBUS_OV			(1 << 2)
-#define EOC_INT_RVRS_CHRG		(1 << 3)
-#define EOC_INT_ID			(1 << 4)
-#define EOC_INT_ID_GROUND		(1 << 5)
-#define EOC_INT_SE1			(1 << 6)
-#define EOC_INT_CC_CV			(1 << 7)
-#define EOC_INT_CHRG_CURR		(1 << 8)
-#define EOC_INT_RVRS_CURR		(1 << 9)
-#define EOC_INT_CK			(1 << 10)
-#define EOC_INT_BATTPON			(1 << 11)
-
-/* 21044  2, 6(70K_PD), 12(XCVR), 17(MODE(3)) */
-#define EOC_CONN_USB_SUSPEND		(1 << 1)
-#define EOC_CONN_DPLUS_150K_PU		(1 << 5)
-#define EOC_CONN_VBUS_70K_PD		(1 << 6)
-#define EOC_CONN_XCVR			(1 << 12)
-#define EOC_CONN_MODE(x)		((x & 7) << 14)
-#define EOC_CONN_ID_PD			(1 << 20)
-#define EOC_CONN_ID_PU			(1 << 22)
-
-/* c 2, 3 */
-#define EOC_POWER1_INPUT_SOURCE(x)	((x & 3) << 0)
-#define EOC_POWER1_OUTPUT_VOLTAGE	(1 << 2)
-#define EOC_POWER1_VUSB			(1 << 3)
-
-/* c00 10, 11 */
-#define EOC_POWER0_VBUS_5K_PD		(1 << 19)
-#define EOC_POWER0_REVERSE_MODE		(1 << 13)
 
 static struct i2c_client *eoc_i2c_client;
 static const struct i2c_device_id eoc_id[] = {
@@ -79,9 +45,9 @@
 	*val |= (value[1] << 8);
 	*val |= (value[0] << 16);
 
-	printk(KERN_INFO "EOC: read %d: %08x\n", reg, *val);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(eoc_reg_read);
 
 int eoc_reg_write(char reg, unsigned int val)
 {
@@ -91,20 +57,107 @@
 	value[1] = (char)(val >> 16);
 	value[2] = (char)(val >> 8);
 	value[3] = (char)val;
-	printk(KERN_INFO "EOC: write %d: %08x\n", reg, val);
 	if(i2c_master_send(eoc_i2c_client, value, EOC_REG_ADDR_SIZE +
 		EOC_REG_DATA_SIZE) != (EOC_REG_ADDR_SIZE + EOC_REG_DATA_SIZE))
 		return -EIO;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(eoc_reg_write);
+
+int eoc_set_reg_mask(char reg, int mask, int value)
+{
+
+	unsigned int old_value;
+
+	eoc_reg_read(reg, &old_value);
+
+	old_value &= ~mask;
+
+	old_value |= value & mask;
+
+	eoc_reg_write(reg, old_value);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(eoc_set_reg_mask);
 
 static void eoc_work(struct work_struct *_eoc)
 {
-	unsigned int isr, msr, i, x;
-	eoc_reg_read(EOC_REG_INT_STATUS, &isr);
-	eoc_reg_read(EOC_REG_INT_MASK, &msr);
-	printk(KERN_INFO "EOC INTS: ");
-	for (i = (isr & ~msr), x = 0; i; x++) {
+	unsigned int isr, msr, service, events;
+	struct pcap_event *cb;
+
+	service = 0;
+	while (gpio_get_value(10)) {
+		eoc_reg_read(EOC_REG_INT_STATUS, &isr);
+		eoc_reg_read(EOC_REG_INT_MASK, &msr);
+
+		service |= isr & (~msr);
+
+		eoc_reg_write(EOC_REG_INT_STATUS, isr);
+		eoc_reg_write(EOC_REG_INT_MASK, msr);
+	}
+
+	mutex_lock(&event_lock);
+	list_for_each_entry(cb, &event_list, node) {
+		events = service & cb->events;
+		if (events)
+			cb->callback(events, cb->data);
+	}
+	mutex_unlock(&event_lock);
+
+	return;
+
+}
+
+static irqreturn_t eoc_irq(int irq, void *arg)
+{
+	schedule_work(&work);
+	return IRQ_HANDLED;
+}
+
+int ezx_eoc_register_event(u32 events, void *callback, char *label)
+{
+	struct pcap_event *cb;
+
+	cb = kzalloc(sizeof(struct pcap_event), GFP_KERNEL);
+	if (!cb)
+		return -ENOMEM;
+
+	cb->label = label;
+	cb->events = events;
+	cb->callback = callback;
+
+	mutex_lock(&event_lock);
+	list_add_tail(&cb->node, &event_list);
+	mutex_unlock(&event_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ezx_eoc_register_event);
+
+int ezx_eoc_unregister_event(u32 events)
+{
+	int ret = -EINVAL;
+	struct pcap_event *cb;
+	struct pcap_event *store;
+
+	mutex_lock(&event_lock);
+	list_for_each_entry_safe(cb, store, &event_list, node) {
+		if (cb->events & events) {
+			list_del(&cb->node);
+			kfree(cb);
+			ret = 0;
+		}
+	}
+	mutex_unlock(&event_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ezx_eoc_unregister_event);
+
+void eoc_event_debug(u32 events, void *data)
+{
+	int x, i;
+	for (i = events, x = 0; i; x++) {
 		if (!(i & (1 << x)))
 			continue;
 		i &= ~(1 << x);
@@ -147,16 +200,9 @@
 			break;
 		}
 	}
-
 	printk("\n");
-	eoc_reg_write(EOC_REG_INT_STATUS, isr);
 }
 
-static irqreturn_t eoc_irq(int irq, void *arg)
-{
-	schedule_work(&work);
-	return IRQ_HANDLED;
-}
 
 static int __devinit eoc_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
@@ -178,11 +224,13 @@
 	eoc_reg_write(EOC_REG_CONN_CONTROL, 0x21044);
 	if (ret)
 		goto ret;
+
 	for (x = EOC_REG_INT_MASK; x <= EOC_REG_CONN_CONTROL; x++) {
 		ret = eoc_reg_read(x, &tmp);
 		if (ret)
 			goto ret;
 	}
+
 	ret = gpio_request(10, "EOC");
 	if (ret)
 		goto ret;
@@ -190,12 +238,24 @@
 	ret = request_irq(gpio_to_irq(10), eoc_irq, IRQF_TRIGGER_RISING,
 								"EOC", NULL);
 	eoc_reg_write(EOC_REG_INT_STATUS, 0xffffff);
+
+	ezx_eoc_register_event(EOC_INT_VBUS_3V4 |
+	    EOC_INT_VBUS | EOC_INT_VBUS_OV | EOC_INT_RVRS_CHRG |
+	    EOC_INT_ID | EOC_INT_ID_GROUND | EOC_INT_SE1 |
+	    EOC_INT_CC_CV | EOC_INT_CHRG_CURR | EOC_INT_RVRS_CURR |
+	    EOC_INT_CK | EOC_INT_BATTPON,
+	    eoc_event_debug, "eoc test");
 ret:
 	return ret;
 }
 
 static int __devexit eoc_remove(struct i2c_client *client)
 {
+	ezx_eoc_unregister_event(EOC_INT_VBUS_3V4 |
+	    EOC_INT_VBUS | EOC_INT_VBUS_OV | EOC_INT_RVRS_CHRG |
+	    EOC_INT_ID | EOC_INT_ID_GROUND | EOC_INT_SE1 |
+	    EOC_INT_CC_CV | EOC_INT_CHRG_CURR | EOC_INT_RVRS_CURR |
+	    EOC_INT_CK | EOC_INT_BATTPON);
 	free_irq(gpio_to_irq(10), NULL);
 	flush_scheduled_work();
 	kfree(i2c_get_clientdata(client));
@@ -212,9 +272,12 @@
 	.id_table = eoc_id,
 };
 
+
 static int __init eoc_init(void)
 {
-	return i2c_add_driver(&eoc_driver);
+
+	int ret = i2c_add_driver(&eoc_driver);
+	return ret;
 }
 
 static void __exit eoc_exit(void)
Index: openezx/arch/arm/mach-pxa/ezx.c
===================================================================
--- openezx.orig/arch/arm/mach-pxa/ezx.c	2008-12-01 01:20:21.000000000 +0800
+++ openezx/arch/arm/mach-pxa/ezx.c	2008-12-01 01:22:21.000000000 +0800
@@ -1323,6 +1323,7 @@
 #ifdef CONFIG_MACH_EZX_E6
 static struct i2c_board_info __initdata e6_i2c_board_info[] = {
 	{ I2C_BOARD_INFO("tea5767", 0x81) },
+	{ I2C_BOARD_INFO("ezx-eoc", 0x17) },
 };
 
 static void __init e6_init(void)
Index: openezx/include/linux/mfd/ezx-eoc.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ openezx/include/linux/mfd/ezx-eoc.h	2008-12-01 01:22:21.000000000 +0800
@@ -0,0 +1,49 @@
+#ifndef EZX_EOC_H
+#define EZX_EOC_H
+
+
+#define EOC_REG_ADDR_SIZE               1
+#define EOC_REG_DATA_SIZE               3
+#define EOC_REG_INT_STATUS              32
+#define EOC_REG_INT_MASK                33
+#define EOC_REG_INT_SENSE               34
+#define EOC_REG_POWER_CONTROL_0         35
+#define EOC_REG_POWER_CONTROL_1         36
+#define EOC_REG_CONN_CONTROL            37
+
+#define EOC_INT_VBUS_3V4                (1 << 0)
+#define EOC_INT_VBUS                    (1 << 1)
+#define EOC_INT_VBUS_OV                 (1 << 2)
+#define EOC_INT_RVRS_CHRG               (1 << 3)
+#define EOC_INT_ID                      (1 << 4)
+#define EOC_INT_ID_GROUND               (1 << 5)
+#define EOC_INT_SE1                     (1 << 6)
+#define EOC_INT_CC_CV                   (1 << 7)
+#define EOC_INT_CHRG_CURR               (1 << 8)
+#define EOC_INT_RVRS_CURR               (1 << 9)
+#define EOC_INT_CK                      (1 << 10)
+#define EOC_INT_BATTPON                 (1 << 11)
+
+/* 21044  2, 6(70K_PD), 12(XCVR), 17(MODE(3)) */
+#define EOC_CONN_USB_SUSPEND            (1 << 1)
+#define EOC_CONN_DPLUS_150K_PU          (1 << 5)
+#define EOC_CONN_VBUS_70K_PD            (1 << 6)
+#define EOC_CONN_XCVR                   (1 << 12)
+#define EOC_CONN_MODE(x)                ((x & 7) << 14)
+#define EOC_CONN_ID_PD                  (1 << 20)
+#define EOC_CONN_ID_PU                  (1 << 22)
+
+/* c 2, 3 */
+#define EOC_POWER1_INPUT_SOURCE(x)      ((x & 3) << 0)
+#define EOC_POWER1_OUTPUT_VOLTAGE       (1 << 2)
+#define EOC_POWER1_VUSB                 (1 << 3)
+
+/* c00 10, 11 */
+#define EOC_POWER0_VBUS_5K_PD           (1 << 19)
+#define EOC_POWER0_REVERSE_MODE         (1 << 13)
+
+int eoc_reg_read(char reg, unsigned int *val);
+int eoc_reg_write(char reg, unsigned int val);
+int eoc_set_reg_mask(char reg, int mask, int value);
+
+#endif

