Index: linux/kernel26/arch/arm/mach-pxa/h5400/h5400.c
===================================================================
RCS file: /cvs/linux/kernel26/arch/arm/mach-pxa/h5400/h5400.c,v
retrieving revision 1.57
diff -u -r1.57 h5400.c
--- linux/kernel26/arch/arm/mach-pxa/h5400/h5400.c	17 Sep 2007 16:31:41 -0000	1.57
+++ linux/kernel26/arch/arm/mach-pxa/h5400/h5400.c	14 Feb 2008 00:27:58 -0000
@@ -19,6 +19,7 @@
  * History:
  *
  * 2002-08-23   Jamey Hicks        GPIO and IRQ support for iPAQ H5400
+ * 2008-02-14   Michal Panczyk        Merge back the BT functions
  *
  */
 
@@ -127,31 +128,89 @@
  * Bluetooth functions and data structures
  ****************************************************************************/
 
-void (*h5400_btuart_configure)(int state);
-void (*h5400_hwuart_configure)(int state);
-EXPORT_SYMBOL(h5400_btuart_configure);
-EXPORT_SYMBOL(h5400_hwuart_configure);
-
-static void h5400_btuart_configure_wrap(int state)
+static void h5400_bluetooth_power(int on)
 {
-	if (h5400_btuart_configure)
-		h5400_btuart_configure(state);
-	return;
+	if (on) {
+		/* apply reset. The chip requires that the reset pins go
+		 * high 2ms after voltage is applied to VCC and IOVCC. So it
+		 * is driven low now before we set the power pins. It
+		 * is assumed that the reset pins are tied together
+		 * on the h5[1,4,5]xx handhelds. */
+		SET_H5400_GPIO(BT_M_RESET, !on);
+		
+		/* Select the 'operating environment' pins to run/normal mode.
+		 * Setting these pins to ENV_0 = 0 and ENV_1 = 1 would put the
+		 * In-System-Programming (ISP) mode. In theory that would
+		 * allow the host computer to rewrite the firmware.
+		 */
+		SET_H5400_GPIO(BT_ENV_0, on);
+		SET_H5400_GPIO(BT_ENV_1, on);
+		/* configure power pins */
+		samcop_set_gpio_b(&h5400_samcop.dev,
+		                  SAMCOP_GPIO_GPB_BLUETOOTH_3V0_ON,
+		                  SAMCOP_GPIO_GPB_BLUETOOTH_3V0_ON);
+		SET_H5400_GPIO(BT_2V8_N, !on);
+                /* A 2ms delay between voltage application and reset driven
+                 * high is a requirement of the power-on cycle of the device.
+                 */
+		mdelay(2);
+		SET_H5400_GPIO(BT_M_RESET, on);
+		led_trigger_event_shared(h5400_radio_trig, LED_FULL);
+	} else {
+		samcop_set_gpio_b(&h5400_samcop.dev,
+		                  SAMCOP_GPIO_GPB_BLUETOOTH_3V0_ON,
+		                  ~SAMCOP_GPIO_GPB_BLUETOOTH_3V0_ON);
+		SET_H5400_GPIO(BT_2V8_N, !on);
+		led_trigger_event_shared(h5400_radio_trig, LED_OFF);
+	}
 }
 
-static struct platform_pxa_serial_funcs h5400_btuart_funcs = {
-	.configure = h5400_btuart_configure_wrap,
-};
+static void h5400_btuart_configure(int state)
+{
+	switch (state) {
+	case PXA_UART_CFG_PRE_STARTUP: /* pre UART enable */
+		pxa_gpio_mode(GPIO42_BTRXD_MD);
+		pxa_gpio_mode(GPIO43_BTTXD_MD);
+		pxa_gpio_mode(GPIO44_BTCTS_MD);
+		pxa_gpio_mode(GPIO45_BTRTS_MD);
+		h5400_bluetooth_power(1);
+		break;
+
+	case PXA_UART_CFG_PRE_SHUTDOWN: /* post UART disable */
+		h5400_bluetooth_power(0);
+		break;
+
+	default:
+		break;
+	}
+}
 
-static void h5400_hwuart_configure_wrap(int state)
+static void h5400_hwuart_configure(int state)
 {
-	if (h5400_hwuart_configure)
-		h5400_hwuart_configure(state);
-	return;
+	switch (state) {
+	case PXA_UART_CFG_PRE_STARTUP: /* pre UART enable */
+		pxa_gpio_mode(GPIO42_HWRXD_MD);
+		pxa_gpio_mode(GPIO43_HWTXD_MD);
+		pxa_gpio_mode(GPIO44_HWCTS_MD);
+		pxa_gpio_mode(GPIO45_HWRTS_MD);
+		h5400_bluetooth_power(1);
+		break;
+
+	case PXA_UART_CFG_PRE_SHUTDOWN: /* post UART disable */
+		h5400_bluetooth_power(0);
+		break;
+
+	default:
+		break;
+	}
 }
 
+static struct platform_pxa_serial_funcs h5400_btuart_funcs = {
+	.configure = h5400_btuart_configure,
+};
+
 static struct platform_pxa_serial_funcs h5400_hwuart_funcs = {
-	.configure = h5400_hwuart_configure_wrap,
+	.configure = h5400_hwuart_configure,
 };
 
 /****************************************************************************
Index: linux/kernel26/include/asm-arm/arch-pxa/h5400.h
===================================================================
RCS file: /cvs/linux/kernel26/include/asm-arm/arch-pxa/h5400.h,v
retrieving revision 1.4
diff -u -r1.4 h5400.h
--- linux/kernel26/include/asm-arm/arch-pxa/h5400.h	18 Jul 2007 10:56:04 -0000	1.4
+++ linux/kernel26/include/asm-arm/arch-pxa/h5400.h	14 Feb 2008 00:28:09 -0000
@@ -3,7 +3,4 @@
 #define H5000_SAMCOP_IRQ_BASE IRQ_BOARD_START
 #define H5000_MQ11XX_IRQ_BASE (H5000_SAMCOP_IRQ_BASE + SAMCOP_NR_IRQS)
 
-extern void (*h5400_btuart_configure)(int state);
-extern void (*h5400_hwuart_configure)(int state);
-
 EXTERN_LED_TRIGGER_SHARED(h5400_radio_trig);
