From 1b9449e9a441eebd81364775c1831eeccc5a2afb Mon Sep 17 00:00:00 2001 From: tytung Date: Fri, 25 Mar 2011 23:15:05 +0800 Subject: [PATCH] Fixed Bluetooth 60mA battery drain Based on Trilu's patch http://forum.xda-developers.com/showthread.php?t=1007774 Removed some debug and unnecessary code, and added some missing code by tytung. Thanks to Trilu for finally fixing the BT problem. Thanks to Charansingh for the work he has done on the BT problem. --- arch/arm/mach-msm/board-htcleo-rfkill.c | 290 +++--------------------- arch/arm/mach-msm/board-htcleo.c | 90 ++++++-- drivers/serial/Makefile | 2 +- drivers/serial/msm_serial_hs.c | 3 +- 4 files changed, 109 insertions(+), 276 deletions(-) diff --git a/arch/arm/mach-msm/board-htcleo-rfkill.c b/arch/arm/mach-msm/board-htcleo-rfkill.c index 6081b8ce..2fb4f40a 100644 --- a/arch/arm/mach-msm/board-htcleo-rfkill.c +++ b/arch/arm/mach-msm/board-htcleo-rfkill.c @@ -13,27 +13,20 @@ * */ -/* Control bluetooth power for htcleo platform */ - -#include -#include -#include -#include #include -#include +#include +#include +#include +#include +#include #include -#include "gpio_chip.h" -#include "proc_comm.h" #include "board-htcleo.h" -#define HTC_RFKILL_DBG #define MAX_BT_SIZE 0x6U static struct rfkill *bt_rfk; static const char bt_name[] = "bcm4329"; -static int pre_state; - /* Fix BT address for Leo */ static unsigned char bt_bd_ram[MAX_BT_SIZE] = {0x50,0xC3,0x00,0x00,0x00,0x00}; @@ -42,249 +35,15 @@ unsigned char *get_bt_bd_ram(void) return (bt_bd_ram); } - -/* bt initial configuration */ -static uint32_t htcleo_bt_init_table[] = { - - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_RTS, /* BT_RTS */ - 2, - GPIO_OUTPUT, - GPIO_NO_PULL, - GPIO_8MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_CTS, /* BT_CTS */ - 0, - GPIO_INPUT, - GPIO_PULL_UP, - GPIO_8MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_RX, /* BT_RX */ - 0, - GPIO_INPUT, - GPIO_PULL_UP, - GPIO_8MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_TX, /* BT_TX */ - 2, - GPIO_OUTPUT, - GPIO_NO_PULL, - GPIO_8MA), - - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_RESET_N, /* BT_RESET_N */ - 0, - GPIO_OUTPUT, - GPIO_NO_PULL, - GPIO_4MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_SHUTDOWN_N, /* BT_SHUTDOWN_N */ - 0, - GPIO_OUTPUT, - GPIO_NO_PULL, - GPIO_4MA), - - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_HOST_WAKE, /* BT_HOST_WAKE */ - 0, - GPIO_INPUT, - GPIO_PULL_UP, - GPIO_4MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_CHIP_WAKE, /* BT_CHIP_WAKE */ - 0, - GPIO_OUTPUT, - GPIO_NO_PULL, - GPIO_4MA), -}; - -/* bt on configuration */ -static uint32_t htcleo_bt_on_table[] = { - - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_RTS, /* BT_RTS */ - 2, - GPIO_OUTPUT, - GPIO_NO_PULL, - GPIO_8MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_CTS, /* BT_CTS */ - 2, - GPIO_INPUT, - GPIO_PULL_UP, - GPIO_8MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_RX, /* BT_RX */ - 2, - GPIO_INPUT, - GPIO_PULL_UP, - GPIO_8MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_TX, /* BT_TX */ - 2, - GPIO_OUTPUT, - GPIO_NO_PULL, - GPIO_8MA), - - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_HOST_WAKE, /* BT_HOST_WAKE */ - 0, - GPIO_INPUT, - GPIO_PULL_DOWN, - GPIO_4MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_CHIP_WAKE, /* BT_CHIP_WAKE */ - 0, - GPIO_OUTPUT, - GPIO_PULL_UP, - GPIO_4MA), - - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_RESET_N, /* BT_RESET_N */ - 0, - GPIO_OUTPUT, - GPIO_NO_PULL, - GPIO_4MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_SHUTDOWN_N, /* BT_SHUTDOWN_N */ - 0, - GPIO_OUTPUT, - GPIO_NO_PULL, - GPIO_4MA), -}; - -/* bt off configuration */ -static uint32_t htcleo_bt_off_table[] = { - - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_RTS, /* BT_RTS */ - 0, - GPIO_OUTPUT, - GPIO_NO_PULL, - GPIO_8MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_CTS, /* BT_CTS */ - 0, - GPIO_INPUT, - GPIO_PULL_UP, - GPIO_8MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_RX, /* BT_RX */ - 0, - GPIO_INPUT, - GPIO_PULL_UP, - GPIO_8MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_TX, /* BT_TX */ - 0, - GPIO_OUTPUT, - GPIO_NO_PULL, - GPIO_8MA), - - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_RESET_N, /* BT_RESET_N */ - 0, - GPIO_OUTPUT, - GPIO_NO_PULL, - GPIO_4MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_SHUTDOWN_N, /* BT_SHUTDOWN_N */ - 0, - GPIO_OUTPUT, - GPIO_NO_PULL, - GPIO_4MA), - - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_HOST_WAKE, /* BT_HOST_WAKE */ - 0, - GPIO_INPUT, - GPIO_PULL_UP, - GPIO_4MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_BT_CHIP_WAKE, /* BT_CHIP_WAKE */ - 0, - GPIO_OUTPUT, - GPIO_NO_PULL, - GPIO_4MA), -}; - -static void config_bt_table(uint32_t *table, int len) -{ - int n; - unsigned id; - for (n = 0; n < len; n++) { - id = table[n]; - msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &id, 0); - } -} - -static void htcleo_config_bt_init(void) -{ - /* set bt initial configuration*/ - config_bt_table(htcleo_bt_init_table, - ARRAY_SIZE(htcleo_bt_init_table)); - mdelay(5); - - /* BT_RESET_N */ - gpio_configure(HTCLEO_GPIO_BT_RESET_N, - GPIOF_DRIVE_OUTPUT | GPIOF_OUTPUT_LOW); - mdelay(2); - /* BT_SHUTDOWN_N */ - gpio_configure(HTCLEO_GPIO_BT_SHUTDOWN_N, - GPIOF_DRIVE_OUTPUT | GPIOF_OUTPUT_LOW); - mdelay(2); - - /* BT_CHIP_WAKE */ - gpio_configure(HTCLEO_GPIO_BT_CHIP_WAKE, - GPIOF_DRIVE_OUTPUT | GPIOF_OUTPUT_HIGH); - -} - -static void htcleo_config_bt_on(void) -{ - - #ifdef HTC_RFKILL_DBG - printk(KERN_INFO "-- RK ON --\n"); - #endif - - /* set bt on configuration*/ - config_bt_table(htcleo_bt_on_table, - ARRAY_SIZE(htcleo_bt_on_table)); - mdelay(5); - - /* BT_RESET_N */ - gpio_configure(HTCLEO_GPIO_BT_RESET_N, - GPIOF_DRIVE_OUTPUT | GPIOF_OUTPUT_HIGH); - mdelay(2); - /* BT_SHUTDOWN_N */ - gpio_configure(HTCLEO_GPIO_BT_SHUTDOWN_N, - GPIOF_DRIVE_OUTPUT | GPIOF_OUTPUT_HIGH); - mdelay(2); -} - -static void htcleo_config_bt_off(void) -{ - #ifdef HTC_RFKILL_DBG - printk(KERN_INFO "-- RK OFF --\n"); - #endif - - /* BT_SHUTDOWN_N */ - gpio_configure(HTCLEO_GPIO_BT_SHUTDOWN_N, - GPIOF_DRIVE_OUTPUT | GPIOF_OUTPUT_LOW); - mdelay(2); - /* BT_RESET_N */ - gpio_configure(HTCLEO_GPIO_BT_RESET_N, - GPIOF_DRIVE_OUTPUT | GPIOF_OUTPUT_LOW); - mdelay(2); - - /* set bt off configuration*/ - config_bt_table(htcleo_bt_off_table, - ARRAY_SIZE(htcleo_bt_off_table)); - mdelay(5); - - /* BT_RTS */ - gpio_configure(HTCLEO_GPIO_BT_UART1_RTS, - GPIOF_DRIVE_OUTPUT | GPIOF_OUTPUT_LOW); - /* BT_TX */ - gpio_configure(HTCLEO_GPIO_BT_UART1_TX, - GPIOF_DRIVE_OUTPUT | GPIOF_OUTPUT_LOW); - - /* BT_CHIP_WAKE */ - gpio_configure(HTCLEO_GPIO_BT_CHIP_WAKE, - GPIOF_DRIVE_OUTPUT | GPIOF_OUTPUT_LOW); -} - static int bluetooth_set_power(void *data, bool blocked) { - if (pre_state == blocked) { - #ifdef HTC_RFKILL_DBG - printk(KERN_INFO "-- SAME ST --\n"); - #endif - return 0; - } else - pre_state = blocked; - - if (!blocked) - htcleo_config_bt_on(); - else - htcleo_config_bt_off(); - + if (!blocked) { + gpio_direction_output(HTCLEO_GPIO_BT_RESET_N, 1); + gpio_direction_output(HTCLEO_GPIO_BT_SHUTDOWN_N, 1); + } else { + gpio_direction_output(HTCLEO_GPIO_BT_SHUTDOWN_N, 0); + gpio_direction_output(HTCLEO_GPIO_BT_RESET_N, 0); + } return 0; } @@ -295,22 +54,28 @@ static struct rfkill_ops htcleo_rfkill_ops = { static int htcleo_rfkill_probe(struct platform_device *pdev) { int rc = 0; - bool default_state = true; /* off */ + bool default_state = true; /* off */ - htcleo_config_bt_init(); /* bt gpio initial config */ + rc = gpio_request(HTCLEO_GPIO_BT_RESET_N, "bt_reset"); + if (rc) + goto err_gpio_reset; + rc = gpio_request(HTCLEO_GPIO_BT_SHUTDOWN_N, "bt_shutdown"); + if (rc) + goto err_gpio_shutdown; bluetooth_set_power(NULL, default_state); bt_rfk = rfkill_alloc(bt_name, &pdev->dev, RFKILL_TYPE_BLUETOOTH, - &htcleo_rfkill_ops, NULL); + &htcleo_rfkill_ops, NULL); if (!bt_rfk) { rc = -ENOMEM; - goto err_rfkill_reset; + goto err_rfkill_alloc; } rfkill_set_states(bt_rfk, default_state, false); /* userspace cannot take exclusive control */ + rc = rfkill_register(bt_rfk); if (rc) goto err_rfkill_reg; @@ -319,7 +84,11 @@ static int htcleo_rfkill_probe(struct platform_device *pdev) err_rfkill_reg: rfkill_destroy(bt_rfk); -err_rfkill_reset: +err_rfkill_alloc: + gpio_free(HTCLEO_GPIO_BT_SHUTDOWN_N); +err_gpio_shutdown: + gpio_free(HTCLEO_GPIO_BT_RESET_N); +err_gpio_reset: return rc; } @@ -327,6 +96,8 @@ static int htcleo_rfkill_remove(struct platform_device *dev) { rfkill_unregister(bt_rfk); rfkill_destroy(bt_rfk); + gpio_free(HTCLEO_GPIO_BT_SHUTDOWN_N); + gpio_free(HTCLEO_GPIO_BT_RESET_N); return 0; } @@ -342,7 +113,6 @@ static struct platform_driver htcleo_rfkill_driver = { static int __init htcleo_rfkill_init(void) { - pre_state = -1; if (!machine_is_htcleo()) return 0; @@ -357,5 +127,5 @@ static void __exit htcleo_rfkill_exit(void) module_init(htcleo_rfkill_init); module_exit(htcleo_rfkill_exit); MODULE_DESCRIPTION("htcleo rfkill"); -MODULE_AUTHOR("Markinus"); +MODULE_AUTHOR("Nick Pelly "); MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-msm/board-htcleo.c b/arch/arm/mach-msm/board-htcleo.c index a462b580..13a295c6 100644 --- a/arch/arm/mach-msm/board-htcleo.c +++ b/arch/arm/mach-msm/board-htcleo.c @@ -50,6 +50,10 @@ #include #include #include +#include +#ifdef CONFIG_SERIAL_BCM_BT_LPM +#include +#endif #include #include #include @@ -555,20 +559,69 @@ __setup("bt.mac=", htcleo_bt_macaddress_setup); //----------------------------------------------------- #ifdef CONFIG_SERIAL_MSM_HS -static struct msm_serial_hs_platform_data msm_uart_dm1_pdata = -{ - /* Chip to Device */ - .rx_wakeup_irq = MSM_GPIO_TO_INT(HTCLEO_GPIO_BT_HOST_WAKE), +static struct msm_serial_hs_platform_data msm_uart_dm1_pdata = { + .rx_wakeup_irq = -1, .inject_rx_on_wakeup = 0, - .cpu_lock_supported = 0, +#ifdef CONFIG_SERIAL_BCM_BT_LPM + .exit_lpm_cb = bcm_bt_lpm_exit_lpm_locked, +#endif +}; - /* for bcm */ - .bt_wakeup_pin_supported = 1, - .bt_wakeup_pin = HTCLEO_GPIO_BT_CHIP_WAKE, - .host_wakeup_pin = HTCLEO_GPIO_BT_HOST_WAKE, +#ifdef CONFIG_SERIAL_BCM_BT_LPM +static struct bcm_bt_lpm_platform_data bcm_bt_lpm_pdata = { + .gpio_wake = HTCLEO_GPIO_BT_CHIP_WAKE, + .gpio_host_wake = HTCLEO_GPIO_BT_HOST_WAKE, + .request_clock_off_locked = msm_hs_request_clock_off_locked, + .request_clock_on_locked = msm_hs_request_clock_on_locked, +}; +struct platform_device bcm_bt_lpm_device = { + .name = "bcm_bt_lpm", + .id = 0, + .dev = { + .platform_data = &bcm_bt_lpm_pdata, + }, }; #endif +#endif + +static uint32_t bt_gpio_table[] = { + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_RTS, 2, GPIO_OUTPUT, + GPIO_PULL_UP, GPIO_8MA), + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_CTS, 2, GPIO_INPUT, + GPIO_PULL_UP, GPIO_8MA), + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_RX, 2, GPIO_INPUT, + GPIO_PULL_UP, GPIO_8MA), + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_TX, 2, GPIO_OUTPUT, + GPIO_PULL_UP, GPIO_8MA), + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_RESET_N, 0, GPIO_OUTPUT, + GPIO_PULL_DOWN, GPIO_4MA), + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_SHUTDOWN_N, 0, GPIO_OUTPUT, + GPIO_PULL_DOWN, GPIO_4MA), + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_CHIP_WAKE, 0, GPIO_OUTPUT, + GPIO_PULL_DOWN, GPIO_4MA), + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_HOST_WAKE, 0, GPIO_INPUT, + GPIO_PULL_DOWN, GPIO_4MA), +}; + +static uint32_t bt_gpio_table_rev_CX[] = { + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_RTS, 2, GPIO_OUTPUT, + GPIO_PULL_UP, GPIO_8MA), + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_CTS, 2, GPIO_INPUT, + GPIO_PULL_UP, GPIO_8MA), + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_RX, 2, GPIO_INPUT, + GPIO_PULL_UP, GPIO_8MA), + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_UART1_TX, 2, GPIO_OUTPUT, + GPIO_PULL_UP, GPIO_8MA), + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_RESET_N, 0, GPIO_OUTPUT, + GPIO_PULL_DOWN, GPIO_4MA), + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_SHUTDOWN_N, 0, GPIO_OUTPUT, + GPIO_PULL_DOWN, GPIO_4MA), + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_CHIP_WAKE, 0, GPIO_OUTPUT, + GPIO_PULL_DOWN, GPIO_4MA), + PCOM_GPIO_CFG(HTCLEO_GPIO_BT_HOST_WAKE, 0, GPIO_INPUT, + GPIO_PULL_DOWN, GPIO_4MA), +}; static struct platform_device htcleo_rfkill = { @@ -847,9 +900,10 @@ static struct platform_device *devices[] __initdata = #if !defined(CONFIG_MSM_SERIAL_DEBUGGER) &msm_device_uart1, #endif -#ifdef CONFIG_SERIAL_MSM_HS - &msm_device_uart_dm1, +#ifdef CONFIG_SERIAL_BCM_BT_LPM + &bcm_bt_lpm_device, #endif + &msm_device_uart_dm1, &msm_device_nand, &msm_device_smd, &htcleo_rfkill, @@ -980,15 +1034,23 @@ static void __init htcleo_init(void) perflock_init(&htcleo_perflock_data); +#if defined(CONFIG_MSM_SERIAL_DEBUGGER) + msm_serial_debug_init(MSM_UART1_PHYS, INT_UART1, + &msm_device_uart1.dev, 1, MSM_GPIO_TO_INT(139)); +#endif + init_dex_comm(); #ifdef CONFIG_SERIAL_MSM_HS - msm_device_uart_dm1.dev.platform_data = &msm_uart_dm1_pdata; - msm_device_uart_dm1.name = "msm_serial_hs_bcm"; /* for bcm */ - msm_device_uart_dm1.resource[3].end = 6; + msm_device_uart_dm1.dev.platform_data = &msm_uart_dm1_pdata; + msm_device_uart_dm1.name = "msm_serial_hs"; /* for bcm */ + msm_device_uart_dm1.resource[3].end = 6; #endif + config_gpio_table(bt_gpio_table, ARRAY_SIZE(bt_gpio_table)); + bt_export_bd_address(); + htcleo_audio_init(); msm_device_i2c_init(); diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 9b1ce892..35dfc674 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -75,7 +75,7 @@ obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o obj-$(CONFIG_SERIAL_MSM) += msm_serial.o obj-$(CONFIG_MSM_SERIAL_DEBUGGER) += msm_serial_debugger.o -obj-$(CONFIG_SERIAL_MSM_HS) += msm_serial_hs_bcm.o +obj-$(CONFIG_SERIAL_MSM_HS) += msm_serial_hs.o obj-$(CONFIG_SERIAL_NETX) += netx-serial.o obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o diff --git a/drivers/serial/msm_serial_hs.c b/drivers/serial/msm_serial_hs.c index 27ada6a3..305b8b88 100644 --- a/drivers/serial/msm_serial_hs.c +++ b/drivers/serial/msm_serial_hs.c @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -1338,7 +1339,7 @@ static int uartdm_init_port(struct uart_port *uport) return 0; } -static int __init msm_hs_probe(struct platform_device *pdev) +static int msm_hs_probe(struct platform_device *pdev) { int ret; struct uart_port *uport;