aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorFrederic Danis <frederic.danis@linux.intel.com>2015-09-23 12:18:09 -0400
committerMarcel Holtmann <marcel@holtmann.org>2015-09-24 10:25:44 -0400
commitb7a622a249736b36c0bf4c3f986ed431281d5e98 (patch)
treeb53ecfd0bb4942abc7ecfaddb338390acb38f1e2 /drivers/bluetooth
parent5cebdfea32b89911d4540440c1c2854a1a3d591e (diff)
Bluetooth: hci_bcm: Prepare PM runtime support
Change some CONFIG_PM_SLEEP to CONFIG_PM as hu and is_suspended parameters will be used during PM runtime callbacks. Add bcm_suspend_device() and bcm_resume_device() which performs link management for PM callbacks. These functions will be used for runtime management. Signed-off-by: Frederic Danis <frederic.danis@linux.intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/hci_bcm.c88
1 files changed, 60 insertions, 28 deletions
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index 2cb50898d667..fc5ca950d37a 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -56,7 +56,7 @@ struct bcm_device {
56 int irq; 56 int irq;
57 u8 irq_polarity; 57 u8 irq_polarity;
58 58
59#ifdef CONFIG_PM_SLEEP 59#ifdef CONFIG_PM
60 struct hci_uart *hu; 60 struct hci_uart *hu;
61 bool is_suspended; /* suspend/resume flag */ 61 bool is_suspended; /* suspend/resume flag */
62#endif 62#endif
@@ -153,7 +153,7 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
153 return 0; 153 return 0;
154} 154}
155 155
156#ifdef CONFIG_PM_SLEEP 156#ifdef CONFIG_PM
157static irqreturn_t bcm_host_wake(int irq, void *data) 157static irqreturn_t bcm_host_wake(int irq, void *data)
158{ 158{
159 struct bcm_device *bdev = data; 159 struct bcm_device *bdev = data;
@@ -259,7 +259,7 @@ static int bcm_open(struct hci_uart *hu)
259 if (hu->tty->dev->parent == dev->pdev->dev.parent) { 259 if (hu->tty->dev->parent == dev->pdev->dev.parent) {
260 bcm->dev = dev; 260 bcm->dev = dev;
261 hu->init_speed = dev->init_speed; 261 hu->init_speed = dev->init_speed;
262#ifdef CONFIG_PM_SLEEP 262#ifdef CONFIG_PM
263 dev->hu = hu; 263 dev->hu = hu;
264#endif 264#endif
265 bcm_gpio_set_power(bcm->dev, true); 265 bcm_gpio_set_power(bcm->dev, true);
@@ -283,7 +283,7 @@ static int bcm_close(struct hci_uart *hu)
283 mutex_lock(&bcm_device_lock); 283 mutex_lock(&bcm_device_lock);
284 if (bcm_device_exists(bdev)) { 284 if (bcm_device_exists(bdev)) {
285 bcm_gpio_set_power(bdev, false); 285 bcm_gpio_set_power(bdev, false);
286#ifdef CONFIG_PM_SLEEP 286#ifdef CONFIG_PM
287 if (device_can_wakeup(&bdev->pdev->dev)) { 287 if (device_can_wakeup(&bdev->pdev->dev)) {
288 devm_free_irq(&bdev->pdev->dev, bdev->irq, bdev); 288 devm_free_irq(&bdev->pdev->dev, bdev->irq, bdev);
289 device_init_wakeup(&bdev->pdev->dev, false); 289 device_init_wakeup(&bdev->pdev->dev, false);
@@ -425,24 +425,17 @@ static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
425 return skb_dequeue(&bcm->txq); 425 return skb_dequeue(&bcm->txq);
426} 426}
427 427
428#ifdef CONFIG_PM_SLEEP 428#ifdef CONFIG_PM
429/* Platform suspend callback */ 429static int bcm_suspend_device(struct device *dev)
430static int bcm_suspend(struct device *dev)
431{ 430{
432 struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev)); 431 struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
433 int error;
434 432
435 bt_dev_dbg(bdev, "suspend: is_suspended %d", bdev->is_suspended); 433 bt_dev_dbg(bdev, "");
436
437 mutex_lock(&bcm_device_lock);
438
439 if (!bdev->hu)
440 goto unlock;
441 434
442 if (!bdev->is_suspended) { 435 if (!bdev->is_suspended && bdev->hu) {
443 hci_uart_set_flow_control(bdev->hu, true); 436 hci_uart_set_flow_control(bdev->hu, true);
444 437
445 /* Once this callback returns, driver suspends BT via GPIO */ 438 /* Once this returns, driver suspends BT via GPIO */
446 bdev->is_suspended = true; 439 bdev->is_suspended = true;
447 } 440 }
448 441
@@ -453,6 +446,52 @@ static int bcm_suspend(struct device *dev)
453 mdelay(15); 446 mdelay(15);
454 } 447 }
455 448
449 return 0;
450}
451
452static int bcm_resume_device(struct device *dev)
453{
454 struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
455
456 bt_dev_dbg(bdev, "");
457
458 if (bdev->device_wakeup) {
459 gpiod_set_value(bdev->device_wakeup, true);
460 bt_dev_dbg(bdev, "resume, delaying 15 ms");
461 mdelay(15);
462 }
463
464 /* When this executes, the device has woken up already */
465 if (bdev->is_suspended && bdev->hu) {
466 bdev->is_suspended = false;
467
468 hci_uart_set_flow_control(bdev->hu, false);
469 }
470
471 return 0;
472}
473#endif
474
475#ifdef CONFIG_PM_SLEEP
476/* Platform suspend callback */
477static int bcm_suspend(struct device *dev)
478{
479 struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
480 int error;
481
482 bt_dev_dbg(bdev, "suspend: is_suspended %d", bdev->is_suspended);
483
484 /* bcm_suspend can be called at any time as long as platform device is
485 * bound, so it should use bcm_device_lock to protect access to hci_uart
486 * and device_wake-up GPIO.
487 */
488 mutex_lock(&bcm_device_lock);
489
490 if (!bdev->hu)
491 goto unlock;
492
493 bcm_suspend_device(dev);
494
456 if (device_may_wakeup(&bdev->pdev->dev)) { 495 if (device_may_wakeup(&bdev->pdev->dev)) {
457 error = enable_irq_wake(bdev->irq); 496 error = enable_irq_wake(bdev->irq);
458 if (!error) 497 if (!error)
@@ -472,6 +511,10 @@ static int bcm_resume(struct device *dev)
472 511
473 bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended); 512 bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended);
474 513
514 /* bcm_resume can be called at any time as long as platform device is
515 * bound, so it should use bcm_device_lock to protect access to hci_uart
516 * and device_wake-up GPIO.
517 */
475 mutex_lock(&bcm_device_lock); 518 mutex_lock(&bcm_device_lock);
476 519
477 if (!bdev->hu) 520 if (!bdev->hu)
@@ -482,18 +525,7 @@ static int bcm_resume(struct device *dev)
482 bt_dev_dbg(bdev, "BCM irq: disabled"); 525 bt_dev_dbg(bdev, "BCM irq: disabled");
483 } 526 }
484 527
485 if (bdev->device_wakeup) { 528 bcm_resume_device(dev);
486 gpiod_set_value(bdev->device_wakeup, true);
487 bt_dev_dbg(bdev, "resume, delaying 15 ms");
488 mdelay(15);
489 }
490
491 /* When this callback executes, the device has woken up already */
492 if (bdev->is_suspended) {
493 bdev->is_suspended = false;
494
495 hci_uart_set_flow_control(bdev->hu, false);
496 }
497 529
498unlock: 530unlock:
499 mutex_unlock(&bcm_device_lock); 531 mutex_unlock(&bcm_device_lock);