summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormattis fjallstrom <mattis@acm.org>2015-07-23 16:03:17 -0700
committermattis fjallstrom <mattis@acm.org>2015-07-23 16:03:17 -0700
commitcd0f92406cc231fda66c30312f48d12fab5ac614 (patch)
tree6986a6fd27299477745728e1cb3f1fefd674cc4e
parent01210164f6867cb66d1f522bf2b358da7b23266d (diff)
downloadolio-linux-3.10-cd0f92406cc231fda66c30312f48d12fab5ac614.tar.xz
olio-linux-3.10-cd0f92406cc231fda66c30312f48d12fab5ac614.zip
Bluetooth in sleep mode fixes
Change-Id: I9d1a303ad09db22514a27184798c38b24c0b1b71
-rw-r--r--arch/arm/boot/dts/omap3_h1.dts58
-rw-r--r--arch/arm/mach-omap2/board-omap3h1-bluetooth.c129
-rw-r--r--arch/arm/mach-omap2/board-omap3h1.c1
3 files changed, 107 insertions, 81 deletions
diff --git a/arch/arm/boot/dts/omap3_h1.dts b/arch/arm/boot/dts/omap3_h1.dts
index 5673768878d..b7a50f595e7 100644
--- a/arch/arm/boot/dts/omap3_h1.dts
+++ b/arch/arm/boot/dts/omap3_h1.dts
@@ -54,32 +54,7 @@
ti,vp = <&vp_core>;
};
};
-
- /* Test code for the ACC input pin. Should be disabled when
- * we're using the accelerometer.
- */
- /*
- gpio_buttons: gpio_buttons@0 {
- compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
- */
- /*
- interrupt-parent = <&gpio1>;
- interrupts = <31>;
- wakeup-source;
- */
- /*
- power {
- label = "mattis_button";
- linux,code = <116>;
- gpios = <&gpio1 31 1>;
- gpio-key,wakeup;
- };
- };*/
-
-
pad-wkup {
/* on omap, the irqs are calculated as follows:
* for the 96 intc IRQs
@@ -100,7 +75,8 @@
/* listed below will be reported as the wakeup reason */
/* */
/* off IRQ handle */
- ti,pad_irq = <0x16e 90 0>, /* uart3 - serial rx */
+ ti,pad_irq = <0x150 88 1>, /* uart1 - BT input */
+ <0x16e 90 0>, /* uart3 - serial rx */
<0x9f6 143 1>, /* mpu6515 irq pin - is this offset correct? */
<0x9f4 123 1>, /* BT host wake */
<0x1b0 23 1>; /* sys_nirq */
@@ -204,7 +180,8 @@
/* BT_WAKE_GPIO - for waking up BT */
/* OMAP_OFF_ENABLE, OMAP_OFF_PULL_EN, OMAP_OFF_OUTENABLE for sleep modes. */
- 0x0da 0x1604 /* DSS_DATA23, (IDIS | PI | M4 ) */
+ /* Now set this to regular old output */
+ 0x0da 0x004 /* 0x1604 */ /* DSS_DATA23, (IDIS | PI | M4 ) */
/* UART3 pins */
0x16e 0x100 /* RX, input, off wake up */
@@ -213,22 +190,17 @@
/* GPIO146, aka UART2TX, aka Microphone enable */
0x148 0x161C /* (204) OUTPUT | GPIO | OFF_ENABLE | OFF_PULL_LOW */
/* (0x161C) 0001011000011100 | PULL_ENA | PULL_UP */
- /* BT_HOST_WAKE */
- /* 0x9f4 0x4104 */ /* JTAG_EMU0 , (OMAP_MUX_MODE4 | OMAP_PIN_INPUT | OMAP_WAKEUPENABLE) */
+
/* Accelerometer interrupt */
-
/* I've tried configuring this both in the wkup pinmux (below) and here,
but this location makes it not function as an interrupt... ??? */
/* 0x9f6 0x4104 */ /* JTAG_EMU1, OMAP_MUX_MODE4 | OMAP_PIN_INPUT |
OMAP_PIN_OFF_WAKEUPENABLE */
-
- /* UART 1 needs to be in safe mode for FCC tests */
- /*
- 0x14c 0x007
- 0x14e 0x007
- 0x150 0x007
- 0x152 0x007
- */
+
+ 0x14c 0x000 /* UART1, BT, TX */
+ 0x14e 0x000 /* UART1, BT, RTS */
+ 0x150 0x4100 /* UART1, BT, CTS */
+ 0x152 0x100 /* UART1, BT, RX */
>;
};
@@ -248,13 +220,7 @@
>;
};
- /*
- i2c2_pins: pinmux_i2c2_pins {
- pinctrl-single,pins = <
- 0x18e 0x118 */ /* I2C2_SCL, MODE0 | INPUT_PULLUP */
- /* 0x190 0x118 */ /* I2C2_SDA, MODE0 | INPUT_PULLUP */
- /* >; */
- /* }; */
+
};
@@ -268,7 +234,7 @@
0x018 0x000 /* SYS_OFF_MODE, MODE0 */
0x01a 0x10c /* SYS_CLKOUT1, MODE4 | INPUT_PULLDOWN */
/* Wakeup from Bluetooth */
- 0x024 0x4104 /* JTAG_EMU0, OMAP_MUX_MODE4 | OMAP_PIN_INPUT |
+ 0x024 0x410C /* JTAG_EMU0, OMAP_MUX_MODE4 | OMAP_PIN_INPUT |
OMAP_PIN_OFF_WAKEUPENABLE */
/* Accelerometer interrupt */
0x026 0x410C /* JTAG_EMU1, OMAP_MUX_MODE4 | OMAP_PIN_INPUT |
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,
diff --git a/arch/arm/mach-omap2/board-omap3h1.c b/arch/arm/mach-omap2/board-omap3h1.c
index 0d16b8967f9..145efe4da76 100644
--- a/arch/arm/mach-omap2/board-omap3h1.c
+++ b/arch/arm/mach-omap2/board-omap3h1.c
@@ -340,6 +340,7 @@ static struct omap_uart_port_info omap_uart_ports[] = {
.wakelock_timeout = 150,
.wake_peer = bcm_bt_lpm_exit_lpm_locked,
.wakeup_capable = true,
+ .rx_trig = 0x3,
},
{
.dma_enabled = false, /* To specify DMA Mode */