From b3337813e973ca676681d22051a907162d4d51dd Mon Sep 17 00:00:00 2001 From: Nagarjuna Kristam Date: Mon, 25 Jun 2012 16:46:14 +0530 Subject: bluetooth: enable sleep only if chip supports Some bt chips e.g TI wl12xx, do not support external wake using GPIO. If bluesleep platform data does not contain external wake GPIO information, bluesleep driver assumes, bt chip does not support external wake and disables bluetooth chip power management. Bluesleep driver is also modified to start and stop on HCI_DEV_UP and HCI_DEV_DOWN events respectively. bug 1006864 Signed-off-by: Nagarjuna Kristam Change-Id: I64c34f5816bd824da1c720175f9e93c16847299b Reviewed-on: http://git-master/r/108498 Reviewed-by: Bharat Nihalani Reviewed-by: Automatic_Commit_Validation_User --- drivers/bluetooth/bluesleep.c | 83 ++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 37 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/bluesleep.c b/drivers/bluetooth/bluesleep.c index 0e2ec0befbe3..fae677189fa9 100644 --- a/drivers/bluetooth/bluesleep.c +++ b/drivers/bluetooth/bluesleep.c @@ -274,24 +274,28 @@ static int bluesleep_hci_event(struct notifier_block *this, return NOTIFY_DONE; switch (event) { - case HCI_DEV_REG: + case HCI_DEV_UP: if (!bluesleep_hdev) { bluesleep_hdev = hdev; - hu = (struct hci_uart *) hdev->driver_data; - state = (struct uart_state *) hu->tty->driver_data; - bsi->uport = state->uart_port; + if (bsi->has_ext_wake == 1) { + hu = (struct hci_uart *) hdev->driver_data; + state = (struct uart_state *) \ + hu->tty->driver_data; + bsi->uport = state->uart_port; + } /* if bluetooth started, start bluesleep*/ bluesleep_start(); } break; - case HCI_DEV_UNREG: + case HCI_DEV_DOWN: bluesleep_stop(); bluesleep_hdev = NULL; bsi->uport = NULL; /* if bluetooth stopped, stop bluesleep also */ break; case HCI_DEV_WRITE: - bluesleep_outgoing_data(); + if (bsi->has_ext_wake == 1) + bluesleep_outgoing_data(); break; } @@ -337,7 +341,8 @@ static void bluesleep_tx_timer_expire(unsigned long data) static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id) { /* schedule a tasklet to handle the change in the host wake line */ - tasklet_schedule(&hostwake_task); + if (bsi->has_ext_wake == 1) + tasklet_schedule(&hostwake_task); return IRQ_HANDLED; } @@ -363,13 +368,15 @@ static int bluesleep_start(void) return -EBUSY; } - /* start the timer */ - mod_timer(&tx_timer, jiffies + (TX_TIMER_INTERVAL * HZ)); - /* assert BT_WAKE */ - if (bsi->has_ext_wake == 1) + if (bsi->has_ext_wake == 1) { + /* start the timer */ + mod_timer(&tx_timer, jiffies + (TX_TIMER_INTERVAL * HZ)); gpio_set_value(bsi->ext_wake, 1); - set_bit(BT_EXT_WAKE, &flags); + wake_lock(&bsi->wake_lock); + set_bit(BT_EXT_WAKE, &flags); + } + #if BT_ENABLE_IRQ_WAKE retval = enable_irq_wake(bsi->host_wake_irq); if (retval < 0) { @@ -378,10 +385,10 @@ static int bluesleep_start(void) } #endif set_bit(BT_PROTO, &flags); - wake_lock(&bsi->wake_lock); return 0; fail: - del_timer(&tx_timer); + if (bsi->has_ext_wake == 1) + del_timer(&tx_timer); atomic_inc(&open_count); return retval; @@ -400,16 +407,17 @@ static void bluesleep_stop(void) return; } /* assert BT_WAKE */ - if (bsi->has_ext_wake == 1) + if (bsi->has_ext_wake == 1) { gpio_set_value(bsi->ext_wake, 1); - set_bit(BT_EXT_WAKE, &flags); - del_timer(&tx_timer); - clear_bit(BT_PROTO, &flags); - - if (test_bit(BT_ASLEEP, &flags)) { - clear_bit(BT_ASLEEP, &flags); - hsuart_power(1); + set_bit(BT_EXT_WAKE, &flags); + del_timer(&tx_timer); + wake_lock_timeout(&bsi->wake_lock, HZ / 2); + if (test_bit(BT_ASLEEP, &flags)) { + clear_bit(BT_ASLEEP, &flags); + hsuart_power(1); + } } + clear_bit(BT_PROTO, &flags); atomic_inc(&open_count); spin_unlock_irqrestore(&rw_lock, irq_flags); @@ -418,7 +426,6 @@ static void bluesleep_stop(void) if (disable_irq_wake(bsi->host_wake_irq)) BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n"); #endif - wake_lock_timeout(&bsi->wake_lock, HZ / 2); } /** * Read the BT_WAKE GPIO pin value via the proc interface. @@ -796,18 +803,19 @@ static int __init bluesleep_init(void) /* Initialize spinlock. */ spin_lock_init(&rw_lock); - /* Initialize timer */ - init_timer(&tx_timer); - tx_timer.function = bluesleep_tx_timer_expire; - tx_timer.data = 0; + /* assert bt wake */ + if (bsi->has_ext_wake == 1) { + /* Initialize timer */ + init_timer(&tx_timer); + tx_timer.function = bluesleep_tx_timer_expire; + tx_timer.data = 0; - /* initialize host wake tasklet */ - tasklet_init(&hostwake_task, bluesleep_hostwake_task, 0); + /* initialize host wake tasklet */ + tasklet_init(&hostwake_task, bluesleep_hostwake_task, 0); - /* assert bt wake */ - if (bsi->has_ext_wake == 1) gpio_set_value(bsi->ext_wake, 1); - set_bit(BT_EXT_WAKE, &flags); + set_bit(BT_EXT_WAKE, &flags); + } hci_register_notifier(&hci_event_nblock); return 0; @@ -831,16 +839,17 @@ static void __exit bluesleep_exit(void) return; /* assert bt wake */ - if (bsi->has_ext_wake == 1) + if (bsi->has_ext_wake == 1) { gpio_set_value(bsi->ext_wake, 1); - set_bit(BT_EXT_WAKE, &flags); + del_timer(&tx_timer); + if (test_bit(BT_ASLEEP, &flags)) + hsuart_power(1); + set_bit(BT_EXT_WAKE, &flags); + } if (test_bit(BT_PROTO, &flags)) { if (disable_irq_wake(bsi->host_wake_irq)) BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n"); free_irq(bsi->host_wake_irq, NULL); - del_timer(&tx_timer); - if (test_bit(BT_ASLEEP, &flags)) - hsuart_power(1); } hci_unregister_notifier(&hci_event_nblock); -- cgit v1.2.3