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.
This commit is contained in:
tytung 2011-03-25 23:15:05 +08:00
parent ea113caeb1
commit 1b9449e9a4
4 changed files with 109 additions and 276 deletions

View File

@ -13,27 +13,20 @@
*
*/
/* Control bluetooth power for htcleo platform */
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/rfkill.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/rfkill.h>
#include <asm/gpio.h>
#include <asm/mach-types.h>
#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 <npelly@google.com>");
MODULE_LICENSE("GPL");

View File

@ -50,6 +50,10 @@
#include <mach/htc_usb.h>
#include <mach/msm_flashlight.h>
#include <mach/msm_serial_hs.h>
#include <mach/msm_serial_debugger.h>
#ifdef CONFIG_SERIAL_BCM_BT_LPM
#include <mach/bcm_bt_lpm.h>
#endif
#include <mach/perflock.h>
#include <mach/htc_headset_mgr.h>
#include <mach/htc_headset_gpio.h>
@ -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();

View File

@ -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

View File

@ -42,6 +42,7 @@
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
@ -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;