Index: linux-2.6.21/arch/arm/mach-pxa/ezx.c
===================================================================
--- linux-2.6.21.orig/arch/arm/mach-pxa/ezx.c	2007-06-29 01:07:18.000000000 -0300
+++ linux-2.6.21/arch/arm/mach-pxa/ezx.c	2007-08-16 15:52:21.000000000 -0300
@@ -86,8 +86,40 @@
 	.init		= ezx_ohci_init,
 };
 
+/* BP */
+static struct resource ezxbp_resources[] = {
+	[0] = {
+		.start		= IRQ_GPIO(GPIO_BP_RDY),
+		.end		= IRQ_GPIO(GPIO_BP_RDY),
+		.flags		= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start		= IRQ_GPIO(GPIO_BB_WDI2),
+		.end		= IRQ_GPIO(GPIO_BB_WDI2),
+		.flags		= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start		= IRQ_GPIO(GPIO_BB_WDI),
+		.end		= IRQ_GPIO(GPIO_BB_WDI),
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ezxbp_device = {
+	.name		= "ezx-bp",
+	.dev		= {
+		//.parent		=
+		//.platform_data	=
+	},
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ezxbp_resources),
+	.resource	= ezxbp_resources,
+};
+
+
 
 static struct platform_device *devices[] __initdata = {
+	&ezxbp_device,
 };
 
 static int __init ezx_init(void)
Index: linux-2.6.21/arch/arm/mach-pxa/Kconfig
===================================================================
--- linux-2.6.21.orig/arch/arm/mach-pxa/Kconfig	2007-06-29 01:07:18.000000000 -0300
+++ linux-2.6.21/arch/arm/mach-pxa/Kconfig	2007-08-16 15:52:20.000000000 -0300
@@ -102,6 +102,9 @@
 
 endchoice
 
+config EZX_BP
+	bool "BP Control code for EZX Platform"
+
 endif
 
 endmenu
Index: linux-2.6.21/arch/arm/mach-pxa/ezx-bp.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.21/arch/arm/mach-pxa/ezx-bp.c	2007-08-16 15:52:43.000000000 -0300
@@ -0,0 +1,262 @@
+/*
+ *  BP handshake code for Motorola EZX phones
+ *
+ *  Copyright (c) 2007 Daniel Ribeiro <drwyrm@gmail.com>
+ *
+ *  Based on Motorola's a780.c Copyright (c) 2003-2005 Motorola
+ *
+ *  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/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/irq.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+
+#include <asm/arch/ezx.h>
+
+/* BP Handshake */
+#define FIRST_STEP              2
+#define LAST_STEP               3
+#define BP_RDY_TIMEOUT          0x000c0000
+
+#if 1
+#define DEBUGP(x, args ...)	printk(x, ##args)
+#else
+#define DEBUGP(x, args ...)
+#endif
+
+struct bp {
+	int irq_wdi;
+	int irq_wdi2;
+	int irq_rdy;
+};
+
+/* check power down condition */
+static inline void check_power_off(void)
+{
+	if (pxa_gpio_get_value(GPIO_BB_WDI2) == 0) {
+		DEBUGP("BP request poweroff!\n");
+		/*
+		 * It is correct to power off here, the following line is
+		 * commented out because e680 lowers WDI2 when BP is in
+		 * flash mode, otherwise WDI2 is used to detect low
+		 * battery. You can safely uncomment this line if you are
+		 * using this kernel with BP in normal mode.
+		 */
+#ifndef CONFIG_PXA_EZX_E680
+		pm_power_off();
+#endif
+	}
+}
+
+static int step = FIRST_STEP;
+
+inline int bp_handshake_passed(void)
+{
+	return (step > LAST_STEP);
+}
+EXPORT_SYMBOL(bp_handshake_passed);
+
+void handshake(void)
+{
+        /* step 1: check MCU_INT_SW or BP_RDY is low (now it is checked in apboot) */
+	DEBUGP("bp handshake entered!\n");
+        if (step == 1) {
+                int timeout = BP_RDY_TIMEOUT;
+
+                /* config MCU_INT_SW, BP_RDY as input */
+		pxa_gpio_mode(GPIO_MCU_INT_SW | GPIO_IN);
+		pxa_gpio_mode(GPIO_BP_RDY | GPIO_IN);
+
+                while (timeout--) {
+                        if (pxa_gpio_get_value(GPIO_MCU_INT_SW) == 0
+                                || pxa_gpio_get_value(GPIO_BP_RDY) == 0) {
+                                step ++;
+                                break;
+                        }
+
+                        check_power_off();
+                }
+		DEBUGP("ezx-bp: handshake step 1\n");
+        }
+
+        /* step 2: wait BP_RDY is low */
+        if (step == 2) {
+                if (pxa_gpio_get_value(GPIO_BP_RDY) == 0) {
+                        /* config MCU_INT_SW as output */
+                        pxa_gpio_mode(GPIO_MCU_INT_SW | GPIO_OUT);
+                        pxa_gpio_set_value(GPIO_MCU_INT_SW, 0);
+
+                        step ++;
+			DEBUGP("ezx-bp: handshake step 2\n");
+                }
+        }
+
+        /* step 3: wait BP_RDY is high */
+        else if (step == 3) {
+                if (pxa_gpio_get_value(GPIO_BP_RDY)) {
+                        step ++;
+                        //FIXME delay_bklight();
+                        pxa_gpio_set_value(GPIO_MCU_INT_SW, 1);
+			printk(KERN_NOTICE "ezx-bp: handshake passed\n");
+                }
+        }
+}
+
+irqreturn_t bp_wdi_handler(int irq, void *dev_id)
+{
+	DEBUGP("BP Lowered WDI line. This is not good :(\n");
+	/*
+	 * this means that BP is not responsive.
+	 * we could try to reset BP and then handshake again
+	 * but i doubt its possible to bring it up again.
+	 */
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t bp_rdy_handler(int irq, void *dev_id)
+{
+	struct bp *bp = dev_id;
+	DEBUGP("BP rdy irq\n");
+	if (!bp_handshake_passed()) {
+		handshake();
+		if (bp_handshake_passed()) {
+		/* FIXME: (test) try to not disable irq_wdi2 and drain battery */
+			disable_irq(bp->irq_wdi2);
+
+			/* set bp_rdy handle for usb ipc */
+			set_irq_type(bp->irq_rdy, IRQT_FALLING);
+	       	}
+	}
+#ifdef CONFIG_TS0710_MUX_USB
+	else usb_send_readurb();
+#endif
+	return IRQ_HANDLED;
+}
+
+/* BP request for poweroff */
+static irqreturn_t bp_wdi2_handler(int irq, void *dev_id)
+{
+	DEBUGP("BP request poweroff!\n");
+	/* same case as check_power_off() */
+#ifndef CONFIG_PXA_EZX_E680
+	pm_power_off();
+#endif
+	return IRQ_HANDLED;
+}
+
+static int __init ezxbp_probe(struct platform_device *dev)
+{
+	int ret;
+	struct bp *bp;
+
+	bp = kzalloc(sizeof(*bp), GFP_KERNEL);
+	if (!bp)
+		return -ENOMEM;
+
+	bp->irq_rdy = platform_get_irq(dev, 0);
+	if(bp->irq_rdy < 0) {
+		ret = bp->irq_rdy;
+		goto fail;
+	}
+
+	bp->irq_wdi2 = platform_get_irq(dev, 1);
+	if(bp->irq_wdi2 < 0) {
+		ret = bp->irq_wdi2;
+		goto fail;
+	}
+
+	bp->irq_wdi = platform_get_irq(dev, 2);
+	if(bp->irq_wdi < 0) {
+		ret = bp->irq_wdi;
+		goto fail;
+	}
+
+        set_irq_type(bp->irq_wdi, IRQT_FALLING);
+        request_irq(bp->irq_wdi, bp_wdi_handler, SA_INTERRUPT,
+			"bp wdi", bp);
+
+        set_irq_type(bp->irq_rdy, IRQT_BOTHEDGE);
+        request_irq(bp->irq_rdy, bp_rdy_handler, SA_INTERRUPT,
+			"bp rdy", bp);
+
+        set_irq_type(bp->irq_wdi2, IRQT_FALLING);
+        request_irq(bp->irq_wdi2, bp_wdi2_handler, SA_INTERRUPT,
+			"bp wdi2", bp);
+
+        /* turn on BP */
+        pxa_gpio_mode(GPIO_BB_RESET|GPIO_OUT);
+        pxa_gpio_set_value(GPIO_BB_RESET, 1);
+
+        check_power_off();
+        handshake();
+
+	return 0;
+fail:
+	kfree(bp);
+	return ret;
+}
+
+static int ezxbp_remove(struct platform_device *dev)
+{
+	struct bp *bp = platform_get_drvdata(dev);
+
+	free_irq(bp->irq_wdi, bp);
+	free_irq(bp->irq_wdi2, bp);
+	free_irq(bp->irq_rdy, bp);
+	kfree(bp);
+
+	return 0;
+}
+
+static int ezxbp_suspend(struct platform_device *dev, pm_message_t state)
+{
+	DEBUGP("bp suspend!\n");
+//	pxa_gpio_set_value(GPIO_MCU_INT_SW, 0);
+        return 0;
+}
+
+static int ezxbp_resume(struct platform_device *dev)
+{
+	DEBUGP("bp resume!\n");
+//	pxa_gpio_set_value(GPIO_MCU_INT_SW, 1);
+        return 0;
+}
+static struct platform_driver ezxbp_driver = {
+	.probe		= ezxbp_probe,
+	.remove		= ezxbp_remove,
+#warning FIXME: missing suspend/resume support
+	.suspend	= ezxbp_suspend,
+	.resume		= ezxbp_resume,
+	.driver		= {
+		.name	= "ezx-bp",
+		.owner	= THIS_MODULE,
+	},
+};
+
+int __init ezxbp_init(void)
+{
+	return platform_driver_register(&ezxbp_driver);
+}
+
+void ezxbp_fini(void)
+{
+	return platform_driver_unregister(&ezxbp_driver);
+}
+
+module_init(ezxbp_init);
+module_exit(ezxbp_fini);
+
+MODULE_DESCRIPTION("Motorola BP Control driver");
+MODULE_AUTHOR("Daniel Ribeiro <drwyrm@gmail.com>");
+MODULE_LICENSE("GPL");
+
Index: linux-2.6.21/arch/arm/mach-pxa/Makefile
===================================================================
--- linux-2.6.21.orig/arch/arm/mach-pxa/Makefile	2007-06-29 01:07:18.000000000 -0300
+++ linux-2.6.21/arch/arm/mach-pxa/Makefile	2007-08-16 15:52:20.000000000 -0300
@@ -24,6 +24,7 @@
 obj-$(CONFIG_PXA_EZX_E2)	+= ezx-e2.o
 obj-$(CONFIG_PXA_EZX_A1200)	+= ezx-a1200.o
 obj-$(CONFIG_PXA_EZX_E6)	+= ezx-e6.o
+obj-$(CONFIG_EZX_BP)		+= ezx-bp.o
 
 # Support for blinky lights
 led-y := leds.o