summaryrefslogtreecommitdiff
path: root/arch/arm/mach-omap2/board-omap3h1-bluetooth.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/board-omap3h1-bluetooth.c')
-rw-r--r--arch/arm/mach-omap2/board-omap3h1-bluetooth.c129
1 files changed, 94 insertions, 35 deletions
diff --git a/arch/arm/mach-omap2/board-omap3h1-bluetooth.c b/arch/arm/mach-omap2/board-omap3h1-bluetooth.c
index 84108a79258..4ce3b2ae00f 100644
--- a/arch/arm/mach-omap2/board-omap3h1-bluetooth.c
+++ b/arch/arm/mach-omap2/board-omap3h1-bluetooth.c
@@ -41,24 +41,25 @@
#include "board-omap3h1.h"
#include <linux/regulator/driver.h>
-static void update_host_wake_locked(int);
+static void set_host_wake_locked(int);
#define BT_RESET_GPIO 179
#define BT_REG_GPIO 180
-#define BT_RESET_GPIO 179
#define BT_WAKE_GPIO 93
#define BT_HOST_WAKE_GPIO 11
#define UART_PORT 1
+#define olio_debug(format, ...) printk ("OLIO %s: ", __FUNCTION__); printk (format, ##__VA_ARGS__)
+
static struct rfkill *bt_rfkill;
static struct regulator *clk32ksys_reg;
static bool bt_enabled;
-static bool host_wake_uart_enabled;
-static bool wake_uart_enabled;
+static bool host_wake_uart_enabled = 0;
+static bool wake_uart_enabled = 0;
static struct dentry *btdebugdent;
-struct bcm_bt_lpm {
- int wake;
+static struct bcm_bt_lpm {
+ int bcm_wake;
int host_wake;
struct hrtimer enter_lpm_timer;
@@ -66,8 +67,16 @@ struct bcm_bt_lpm {
struct uart_port *uport;
- struct wake_lock wake_lock;
- char wake_lock_name[100];
+ /* Lock for use when host is communicating with chip */
+
+ struct wake_lock bcm_wake_lock;
+
+ /* Lock used when chip wakes up the host */
+
+ struct wake_lock host_wake_lock;
+
+ char host_wake_lock_name[100];
+ char bcm_wake_lock_name[100];
} bt_lpm;
static int bcm20702_bt_rfkill_set_power(void *data, bool blocked)
@@ -84,7 +93,8 @@ static int bcm20702_bt_rfkill_set_power(void *data, bool blocked)
} else {
// Chip won't toggle host_wake after reset. Make sure
// we don't hold the wake_lock until chip wakes up again.
- update_host_wake_locked(0);
+ // set_host_wake_locked(0);
+ // OLIO removed, we'll let go of the wake lock when HOST_WAKE drops.
gpio_set_value(BT_RESET_GPIO, 0);
gpio_set_value(BT_REG_GPIO, 0);
@@ -103,20 +113,32 @@ static const struct rfkill_ops bcm20702_bt_rfkill_ops = {
static void set_wake_locked(int wake)
{
- bt_lpm.wake = wake;
+ if (bt_lpm.bcm_wake == wake) {
+ return;
+ }
- if (!wake)
- wake_unlock(&bt_lpm.wake_lock);
+ bt_lpm.bcm_wake = wake;
- if (!wake_uart_enabled && wake)
- omap_serial_ext_uart_enable(UART_PORT);
+ if (wake) {
+ olio_debug ("Now locking wake lock\n");
+ wake_lock (&bt_lpm.bcm_wake_lock);
+ if (!wake_uart_enabled)
+ omap_serial_ext_uart_enable(UART_PORT);
+ }
gpio_set_value(BT_WAKE_GPIO, wake);
+ /* Let UART know we're done with it */
+
if (wake_uart_enabled && !wake)
omap_serial_ext_uart_disable(UART_PORT);
wake_uart_enabled = wake;
+
+ if (!wake) {
+ olio_debug ("Now unlocking wake lock\n");
+ wake_unlock(&bt_lpm.bcm_wake_lock);
+ }
}
static enum hrtimer_restart enter_lpm(struct hrtimer *timer) {
@@ -129,26 +151,41 @@ static enum hrtimer_restart enter_lpm(struct hrtimer *timer) {
}
void bcm_bt_lpm_exit_lpm_locked(struct uart_port *uport) {
+ int ret;
+
bt_lpm.uport = uport;
- hrtimer_try_to_cancel(&bt_lpm.enter_lpm_timer);
+ ret = hrtimer_try_to_cancel(&bt_lpm.enter_lpm_timer);
+ if (ret == -1) {
+ olio_debug ("timer executing, unable to cancel\n");
+ }
+
set_wake_locked(1);
hrtimer_start(&bt_lpm.enter_lpm_timer, bt_lpm.enter_lpm_delay,
- HRTIMER_MODE_REL);
+ HRTIMER_MODE_REL);
}
EXPORT_SYMBOL(bcm_bt_lpm_exit_lpm_locked);
-static void update_host_wake_locked(int host_wake)
+static void set_host_wake_locked(int host_wake)
{
- if (host_wake == bt_lpm.host_wake)
+ olio_debug ("Entered, requested host_wake is %d\n", host_wake);
+
+ if (host_wake == bt_lpm.host_wake) {
+ olio_debug ("Host wake lock is already in requested state\n");
return;
+ }
+
+ olio_debug ("host_wake (%d) is different from bt_lpm.host_wake (%d)\n",
+ host_wake, bt_lpm.host_wake);
bt_lpm.host_wake = host_wake;
if (host_wake) {
- wake_lock(&bt_lpm.wake_lock);
+ olio_debug ("host_wake is set, taking wake lock\n");
+ wake_lock(&bt_lpm.host_wake_lock);
+
if (!host_wake_uart_enabled) {
omap_serial_ext_uart_enable(UART_PORT);
}
@@ -156,14 +193,22 @@ static void update_host_wake_locked(int host_wake)
if (host_wake_uart_enabled) {
omap_serial_ext_uart_disable(UART_PORT);
}
- // Take a timed wakelock, so that upper layers can take it.
- // The chipset deasserts the hostwake lock, when there is no
- // more data to send.
- wake_lock_timeout(&bt_lpm.wake_lock, HZ/2);
+
}
+
+ /* Set wake lock to time out, so that upper layers can take it.
+ * The chipset deasserts the host wake lock when there is no
+ * more data to send.
+ */
+
+ if (!host_wake) {
+ olio_debug ("host_wake isn't set, adding timeout to wake lock\n");
+ wake_lock_timeout(&bt_lpm.host_wake_lock, HZ/2);
+ }
host_wake_uart_enabled = host_wake;
+ olio_debug ("Exiting\n");
}
static irqreturn_t host_wake_isr(int irq, void *dev)
@@ -172,7 +217,11 @@ static irqreturn_t host_wake_isr(int irq, void *dev)
unsigned long flags;
host_wake = gpio_get_value(BT_HOST_WAKE_GPIO);
- irq_set_irq_type(irq, host_wake ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH);
+
+ /* Invert the interrupt type to catch the next transition */
+
+ irq_set_irq_type(irq, host_wake ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING);
+ olio_debug ("Set next trigger to be %s\n", host_wake ? "falling" : "rising");
if (!bt_lpm.uport) {
bt_lpm.host_wake = host_wake;
@@ -180,7 +229,7 @@ static irqreturn_t host_wake_isr(int irq, void *dev)
}
spin_lock_irqsave(&bt_lpm.uport->lock, flags);
- update_host_wake_locked(host_wake);
+ set_host_wake_locked(host_wake);
spin_unlock_irqrestore(&bt_lpm.uport->lock, flags);
return IRQ_HANDLED;
@@ -210,8 +259,8 @@ static int bcm_bt_lpm_init(struct platform_device *pdev)
bt_lpm.host_wake = 0;
irq = gpio_to_irq(BT_HOST_WAKE_GPIO);
- ret = request_irq(irq, host_wake_isr, IRQF_TRIGGER_HIGH,
- "bt host_wake", NULL);
+ ret = request_irq(irq, host_wake_isr, IRQF_TRIGGER_RISING,
+ "bt host_wake", NULL);
if (ret) {
gpio_free(BT_WAKE_GPIO);
gpio_free(BT_HOST_WAKE_GPIO);
@@ -228,10 +277,16 @@ static int bcm_bt_lpm_init(struct platform_device *pdev)
gpio_direction_output(BT_WAKE_GPIO, 0);
gpio_direction_input(BT_HOST_WAKE_GPIO);
- snprintf(bt_lpm.wake_lock_name, sizeof(bt_lpm.wake_lock_name),
- "BTLowPower");
- wake_lock_init(&bt_lpm.wake_lock, WAKE_LOCK_SUSPEND,
- bt_lpm.wake_lock_name);
+ snprintf(bt_lpm.bcm_wake_lock_name, sizeof(bt_lpm.bcm_wake_lock_name),
+ "BCM BTLowPower");
+ snprintf(bt_lpm.host_wake_lock_name, sizeof(bt_lpm.host_wake_lock_name),
+ "HOST BTLowPower");
+
+ wake_lock_init(&bt_lpm.bcm_wake_lock, WAKE_LOCK_SUSPEND,
+ bt_lpm.bcm_wake_lock_name);
+ wake_lock_init(&bt_lpm.host_wake_lock, WAKE_LOCK_SUSPEND,
+ bt_lpm.host_wake_lock_name);
+
return 0;
}
@@ -239,7 +294,7 @@ static int btdebug_dump(struct seq_file *sf, void *private)
{
seq_printf(sf, "en=%d bt_wake=%d lpm.w=%d w_uart_en=%d\n",
bt_enabled, gpio_get_value(BT_WAKE_GPIO),
- bt_lpm.wake, wake_uart_enabled);
+ bt_lpm.bcm_wake, wake_uart_enabled);
seq_printf(sf, "bt_host_wake=%d lpm.hw=%d hw_uart_en=%d\n",
gpio_get_value(BT_HOST_WAKE_GPIO), bt_lpm.host_wake,
host_wake_uart_enabled);
@@ -335,7 +390,8 @@ static int bcm20702_bluetooth_remove(struct platform_device *pdev)
gpio_free(BT_HOST_WAKE_GPIO);
regulator_put(clk32ksys_reg);
- wake_lock_destroy(&bt_lpm.wake_lock);
+ wake_lock_destroy(&bt_lpm.bcm_wake_lock);
+ wake_lock_destroy(&bt_lpm.host_wake_lock);
return 0;
}
@@ -362,11 +418,14 @@ int bcm4430_bluetooth_resume(struct platform_device *pdev)
return 0;
}
+/*
+ .suspend = bcm4430_bluetooth_suspend,
+ .resume = bcm4430_bluetooth_resume,
+*/
+
static struct platform_driver bcm20702_bluetooth_platform_driver = {
.probe = bcm20702_bluetooth_probe,
.remove = bcm20702_bluetooth_remove,
- .suspend = bcm4430_bluetooth_suspend,
- .resume = bcm4430_bluetooth_resume,
.driver = {
.name = "bcm20702_bluetooth",
.owner = THIS_MODULE,