aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/bluetooth
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/bluesleep.c864
-rw-r--r--drivers/bluetooth/ti_bluesleep.c371
2 files changed, 1235 insertions, 0 deletions
diff --git a/drivers/bluetooth/bluesleep.c b/drivers/bluetooth/bluesleep.c
new file mode 100644
index 00000000000..0e2ec0befbe
--- /dev/null
+++ b/drivers/bluetooth/bluesleep.c
@@ -0,0 +1,864 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 *
6 * You should have received a copy of the GNU General Public License
7 * along with this program; if not, write to the Free Software
8 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * Copyright (C) 2006-2007 - Motorola
16 * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
17 *
18 * Date Author Comment
19 * ----------- -------------- --------------------------------
20 * 2006-Apr-28 Motorola The kernel module for running the Bluetooth(R)
21 * Sleep-Mode Protocol from the Host side
22 * 2006-Sep-08 Motorola Added workqueue for handling sleep work.
23 * 2007-Jan-24 Motorola Added mbm_handle_ioi() call to ISR.
24 * 2009-Aug-10 Motorola Changed "add_timer" to "mod_timer" to solve
25 * race when flurry of queued work comes in.
26*/
27
28#include <linux/module.h> /* kernel module definitions */
29#include <linux/errno.h>
30#include <linux/init.h>
31#include <linux/interrupt.h>
32#include <linux/kernel.h>
33#include <linux/notifier.h>
34#include <linux/proc_fs.h>
35#include <linux/spinlock.h>
36#include <linux/timer.h>
37#include <linux/uaccess.h>
38#include <linux/version.h>
39#include <linux/workqueue.h>
40#include <linux/platform_device.h>
41
42#include <linux/irq.h>
43#include <linux/ioport.h>
44#include <linux/param.h>
45#include <linux/bitops.h>
46#include <linux/termios.h>
47#include <linux/wakelock.h>
48#include <mach/gpio.h>
49#include <linux/serial_core.h>
50#include <linux/tegra_uart.h>
51
52#include <net/bluetooth/bluetooth.h>
53#include <net/bluetooth/hci_core.h> /* event notifications */
54#include "hci_uart.h"
55
56#define BT_SLEEP_DBG
57#ifndef BT_SLEEP_DBG
58#define BT_DBG(fmt, arg...)
59#endif
60/*
61 * Defines
62 */
63
64#define VERSION "1.1"
65#define PROC_DIR "bluetooth/sleep"
66
67#define POLARITY_LOW 0
68#define POLARITY_HIGH 1
69
70/* enable/disable wake-on-bluetooth */
71#define BT_ENABLE_IRQ_WAKE 1
72
73struct bluesleep_info {
74 unsigned host_wake;
75 unsigned ext_wake;
76 unsigned host_wake_irq;
77 struct uart_port *uport;
78 struct wake_lock wake_lock;
79 int irq_polarity;
80 int has_ext_wake;
81};
82
83/* work function */
84static void bluesleep_sleep_work(struct work_struct *work);
85
86/* work queue */
87DECLARE_DELAYED_WORK(sleep_workqueue, bluesleep_sleep_work);
88
89/* Macros for handling sleep work */
90#define bluesleep_rx_busy() schedule_delayed_work(&sleep_workqueue, 0)
91#define bluesleep_tx_busy() schedule_delayed_work(&sleep_workqueue, 0)
92#define bluesleep_rx_idle() schedule_delayed_work(&sleep_workqueue, 0)
93#define bluesleep_tx_idle() schedule_delayed_work(&sleep_workqueue, 0)
94
95/* 10 second timeout */
96#define TX_TIMER_INTERVAL 10
97
98/* state variable names and bit positions */
99#define BT_PROTO 0x01
100#define BT_TXDATA 0x02
101#define BT_ASLEEP 0x04
102#define BT_EXT_WAKE 0x08
103#define BT_SUSPEND 0x10
104
105/* global pointer to a single hci device. */
106static struct hci_dev *bluesleep_hdev;
107
108static struct bluesleep_info *bsi;
109
110/* module usage */
111static atomic_t open_count = ATOMIC_INIT(1);
112
113/*
114 * Local function prototypes
115 */
116static int bluesleep_hci_event(struct notifier_block *this,
117 unsigned long event, void *data);
118static int bluesleep_start(void);
119static void bluesleep_stop(void);
120
121/*
122 * Global variables
123 */
124/** Global state flags */
125static unsigned long flags;
126
127/** Tasklet to respond to change in hostwake line */
128static struct tasklet_struct hostwake_task;
129
130/** Transmission timer */
131static void bluesleep_tx_timer_expire(unsigned long data);
132static DEFINE_TIMER(tx_timer, bluesleep_tx_timer_expire, 0, 0);
133
134/** Lock for state transitions */
135static spinlock_t rw_lock;
136
137/** Notifier block for HCI events */
138struct notifier_block hci_event_nblock = {
139 .notifier_call = bluesleep_hci_event,
140};
141
142struct proc_dir_entry *bluetooth_dir, *sleep_dir;
143
144/*
145 * Local functions
146 */
147static void hsuart_power(int on)
148{
149 if (test_bit(BT_SUSPEND, &flags))
150 return;
151 if (on) {
152 tegra_uart_request_clock_on(bsi->uport);
153 tegra_uart_set_mctrl(bsi->uport, TIOCM_RTS);
154 } else {
155 tegra_uart_set_mctrl(bsi->uport, 0);
156 tegra_uart_request_clock_off(bsi->uport);
157 }
158}
159
160/**
161 * @return 1 if the Host can go to sleep, 0 otherwise.
162 */
163int bluesleep_can_sleep(void)
164{
165 /* check if WAKE_BT_GPIO and BT_WAKE_GPIO are both deasserted */
166 return ((gpio_get_value(bsi->host_wake) != bsi->irq_polarity) &&
167 (!test_bit(BT_EXT_WAKE, &flags)) &&
168 (bsi->uport != NULL));
169}
170
171void bluesleep_sleep_wakeup(void)
172{
173 if (test_bit(BT_ASLEEP, &flags)) {
174 BT_DBG("waking up...");
175 wake_lock(&bsi->wake_lock);
176 /* Start the timer */
177 mod_timer(&tx_timer, jiffies + (TX_TIMER_INTERVAL * HZ));
178 if (bsi->has_ext_wake == 1)
179 gpio_set_value(bsi->ext_wake, 1);
180 set_bit(BT_EXT_WAKE, &flags);
181 clear_bit(BT_ASLEEP, &flags);
182 /*Activating UART */
183 }
184}
185
186/**
187 * @brief@ main sleep work handling function which update the flags
188 * and activate and deactivate UART ,check FIFO.
189 */
190static void bluesleep_sleep_work(struct work_struct *work)
191{
192 if (bluesleep_can_sleep()) {
193 /* already asleep, this is an error case */
194 if (test_bit(BT_ASLEEP, &flags)) {
195 BT_DBG("already asleep");
196 return;
197 }
198
199 if (tegra_uart_is_tx_empty(bsi->uport)) {
200 BT_DBG("going to sleep...");
201 set_bit(BT_ASLEEP, &flags);
202 /*Deactivating UART */
203 /* UART clk is not turned off immediately. Release
204 * wakelock after 500 ms.
205 */
206 wake_lock_timeout(&bsi->wake_lock, HZ / 2);
207 } else {
208 mod_timer(&tx_timer, jiffies + TX_TIMER_INTERVAL * HZ);
209 return;
210 }
211 } else if (!test_bit(BT_EXT_WAKE, &flags)
212 && !test_bit(BT_ASLEEP, &flags)) {
213 mod_timer(&tx_timer, jiffies + (TX_TIMER_INTERVAL * HZ));
214 if (bsi->has_ext_wake == 1)
215 gpio_set_value(bsi->ext_wake, 1);
216 set_bit(BT_EXT_WAKE, &flags);
217 } else {
218 bluesleep_sleep_wakeup();
219 }
220}
221
222/**
223 * A tasklet function that runs in tasklet context and reads the value
224 * of the HOST_WAKE GPIO pin and further defer the work.
225 * @param data Not used.
226 */
227static void bluesleep_hostwake_task(unsigned long data)
228{
229 BT_DBG("hostwake line change");
230
231 spin_lock(&rw_lock);
232 if ((gpio_get_value(bsi->host_wake) == bsi->irq_polarity))
233 bluesleep_rx_busy();
234 else
235 bluesleep_rx_idle();
236 spin_unlock(&rw_lock);
237
238}
239
240/**
241 * Handles proper timer action when outgoing data is delivered to the
242 * HCI line discipline. Sets BT_TXDATA.
243 */
244static void bluesleep_outgoing_data(void)
245{
246 unsigned long irq_flags;
247
248 spin_lock_irqsave(&rw_lock, irq_flags);
249 /* log data passing by */
250 set_bit(BT_TXDATA, &flags);
251 /* if the tx side is sleeping... */
252 if (!test_bit(BT_EXT_WAKE, &flags)) {
253 BT_DBG("tx was sleeping");
254 bluesleep_sleep_wakeup();
255 }
256 spin_unlock_irqrestore(&rw_lock, irq_flags);
257}
258
259/**
260 * Handles HCI device events.
261 * @param this Not used.
262 * @param event The event that occurred.
263 * @param data The HCI device associated with the event.
264 * @return <code>NOTIFY_DONE</code>.
265 */
266static int bluesleep_hci_event(struct notifier_block *this,
267 unsigned long event, void *data)
268{
269 struct hci_dev *hdev = (struct hci_dev *) data;
270 struct hci_uart *hu;
271 struct uart_state *state;
272
273 if (!hdev)
274 return NOTIFY_DONE;
275
276 switch (event) {
277 case HCI_DEV_REG:
278 if (!bluesleep_hdev) {
279 bluesleep_hdev = hdev;
280 hu = (struct hci_uart *) hdev->driver_data;
281 state = (struct uart_state *) hu->tty->driver_data;
282 bsi->uport = state->uart_port;
283 /* if bluetooth started, start bluesleep*/
284 bluesleep_start();
285 }
286 break;
287 case HCI_DEV_UNREG:
288 bluesleep_stop();
289 bluesleep_hdev = NULL;
290 bsi->uport = NULL;
291 /* if bluetooth stopped, stop bluesleep also */
292 break;
293 case HCI_DEV_WRITE:
294 bluesleep_outgoing_data();
295 break;
296 }
297
298 return NOTIFY_DONE;
299}
300
301/**
302 * Handles transmission timer expiration.
303 * @param data Not used.
304 */
305static void bluesleep_tx_timer_expire(unsigned long data)
306{
307 unsigned long irq_flags;
308
309 BT_DBG("Tx timer expired");
310
311 spin_lock_irqsave(&rw_lock, irq_flags);
312
313 /* were we silent during the last timeout? */
314 if (!test_bit(BT_TXDATA, &flags)) {
315 BT_DBG("Tx has been idle");
316 if (bsi->has_ext_wake == 1)
317 gpio_set_value(bsi->ext_wake, 0);
318 clear_bit(BT_EXT_WAKE, &flags);
319 bluesleep_tx_idle();
320 } else {
321 BT_DBG("Tx data during last period");
322 mod_timer(&tx_timer, jiffies + (TX_TIMER_INTERVAL*HZ));
323 }
324
325 /* clear the incoming data flag */
326 clear_bit(BT_TXDATA, &flags);
327
328 spin_unlock_irqrestore(&rw_lock, irq_flags);
329}
330
331/**
332 * Schedules a tasklet to run when receiving an interrupt on the
333 * <code>HOST_WAKE</code> GPIO pin.
334 * @param irq Not used.
335 * @param dev_id Not used.
336 */
337static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id)
338{
339 /* schedule a tasklet to handle the change in the host wake line */
340 tasklet_schedule(&hostwake_task);
341 return IRQ_HANDLED;
342}
343
344/**
345 * Starts the Sleep-Mode Protocol on the Host.
346 * @return On success, 0. On error, -1, and <code>errno</code> is set
347 * appropriately.
348 */
349static int bluesleep_start(void)
350{
351 int retval;
352 unsigned long irq_flags;
353
354 spin_lock_irqsave(&rw_lock, irq_flags);
355 if (test_bit(BT_PROTO, &flags)) {
356 spin_unlock_irqrestore(&rw_lock, irq_flags);
357 return 0;
358 }
359 spin_unlock_irqrestore(&rw_lock, irq_flags);
360
361 if (!atomic_dec_and_test(&open_count)) {
362 atomic_inc(&open_count);
363 return -EBUSY;
364 }
365
366 /* start the timer */
367 mod_timer(&tx_timer, jiffies + (TX_TIMER_INTERVAL * HZ));
368
369 /* assert BT_WAKE */
370 if (bsi->has_ext_wake == 1)
371 gpio_set_value(bsi->ext_wake, 1);
372 set_bit(BT_EXT_WAKE, &flags);
373#if BT_ENABLE_IRQ_WAKE
374 retval = enable_irq_wake(bsi->host_wake_irq);
375 if (retval < 0) {
376 BT_ERR("Couldn't enable BT_HOST_WAKE as wakeup interrupt");
377 goto fail;
378 }
379#endif
380 set_bit(BT_PROTO, &flags);
381 wake_lock(&bsi->wake_lock);
382 return 0;
383fail:
384 del_timer(&tx_timer);
385 atomic_inc(&open_count);
386
387 return retval;
388}
389
390/**
391 * Stops the Sleep-Mode Protocol on the Host.
392 */
393static void bluesleep_stop(void)
394{
395 unsigned long irq_flags;
396
397 spin_lock_irqsave(&rw_lock, irq_flags);
398 if (!test_bit(BT_PROTO, &flags)) {
399 spin_unlock_irqrestore(&rw_lock, irq_flags);
400 return;
401 }
402 /* assert BT_WAKE */
403 if (bsi->has_ext_wake == 1)
404 gpio_set_value(bsi->ext_wake, 1);
405 set_bit(BT_EXT_WAKE, &flags);
406 del_timer(&tx_timer);
407 clear_bit(BT_PROTO, &flags);
408
409 if (test_bit(BT_ASLEEP, &flags)) {
410 clear_bit(BT_ASLEEP, &flags);
411 hsuart_power(1);
412 }
413
414 atomic_inc(&open_count);
415 spin_unlock_irqrestore(&rw_lock, irq_flags);
416
417#if BT_ENABLE_IRQ_WAKE
418 if (disable_irq_wake(bsi->host_wake_irq))
419 BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n");
420#endif
421 wake_lock_timeout(&bsi->wake_lock, HZ / 2);
422}
423/**
424 * Read the <code>BT_WAKE</code> GPIO pin value via the proc interface.
425 * When this function returns, <code>page</code> will contain a 1 if the
426 * pin is high, 0 otherwise.
427 * @param page Buffer for writing data.
428 * @param start Not used.
429 * @param offset Not used.
430 * @param count Not used.
431 * @param eof Whether or not there is more data to be read.
432 * @param data Not used.
433 * @return The number of bytes written.
434 */
435static int bluepower_read_proc_btwake(char *page, char **start, off_t offset,
436 int count, int *eof, void *data)
437{
438 *eof = 1;
439 return sprintf(page, "btwake:%u\n",test_bit(BT_EXT_WAKE, &flags));
440}
441
442/**
443 * Write the <code>BT_WAKE</code> GPIO pin value via the proc interface.
444 * @param file Not used.
445 * @param buffer The buffer to read from.
446 * @param count The number of bytes to be written.
447 * @param data Not used.
448 * @return On success, the number of bytes written. On error, -1, and
449 * <code>errno</code> is set appropriately.
450 */
451static int bluepower_write_proc_btwake(struct file *file, const char *buffer,
452 unsigned long count, void *data)
453{
454 char *buf;
455
456 if (count < 1)
457 return -EINVAL;
458
459 buf = kmalloc(count, GFP_KERNEL);
460 if (!buf)
461 return -ENOMEM;
462
463 if (copy_from_user(buf, buffer, count)) {
464 kfree(buf);
465 return -EFAULT;
466 }
467 if (buf[0] == '0') {
468 if (bsi->has_ext_wake == 1)
469 gpio_set_value(bsi->ext_wake, 0);
470 clear_bit(BT_EXT_WAKE, &flags);
471 } else if (buf[0] == '1') {
472 if (bsi->has_ext_wake == 1)
473 gpio_set_value(bsi->ext_wake, 1);
474 set_bit(BT_EXT_WAKE, &flags);
475 } else {
476 kfree(buf);
477 return -EINVAL;
478 }
479
480 kfree(buf);
481 return count;
482}
483
484/**
485 * Read the <code>BT_HOST_WAKE</code> GPIO pin value via the proc interface.
486 * When this function returns, <code>page</code> will contain a 1 if the pin
487 * is high, 0 otherwise.
488 * @param page Buffer for writing data.
489 * @param start Not used.
490 * @param offset Not used.
491 * @param count Not used.
492 * @param eof Whether or not there is more data to be read.
493 * @param data Not used.
494 * @return The number of bytes written.
495 */
496static int bluepower_read_proc_hostwake(char *page, char **start, off_t offset,
497 int count, int *eof, void *data)
498{
499 *eof = 1;
500 return sprintf(page, "hostwake: %u\n", gpio_get_value(bsi->host_wake));
501}
502
503
504/**
505 * Read the low-power status of the Host via the proc interface.
506 * When this function returns, <code>page</code> contains a 1 if the Host
507 * is asleep, 0 otherwise.
508 * @param page Buffer for writing data.
509 * @param start Not used.
510 * @param offset Not used.
511 * @param count Not used.
512 * @param eof Whether or not there is more data to be read.
513 * @param data Not used.
514 * @return The number of bytes written.
515 */
516static int bluesleep_read_proc_asleep(char *page, char **start, off_t offset,
517 int count, int *eof, void *data)
518{
519 unsigned int asleep;
520
521 asleep = test_bit(BT_ASLEEP, &flags) ? 1 : 0;
522 *eof = 1;
523 return sprintf(page, "asleep: %u\n", asleep);
524}
525
526/**
527 * Read the low-power protocol being used by the Host via the proc interface.
528 * When this function returns, <code>page</code> will contain a 1 if the Host
529 * is using the Sleep Mode Protocol, 0 otherwise.
530 * @param page Buffer for writing data.
531 * @param start Not used.
532 * @param offset Not used.
533 * @param count Not used.
534 * @param eof Whether or not there is more data to be read.
535 * @param data Not used.
536 * @return The number of bytes written.
537 */
538static int bluesleep_read_proc_proto(char *page, char **start, off_t offset,
539 int count, int *eof, void *data)
540{
541 unsigned int proto;
542
543 proto = test_bit(BT_PROTO, &flags) ? 1 : 0;
544 *eof = 1;
545 return sprintf(page, "proto: %u\n", proto);
546}
547
548/**
549 * Modify the low-power protocol used by the Host via the proc interface.
550 * @param file Not used.
551 * @param buffer The buffer to read from.
552 * @param count The number of bytes to be written.
553 * @param data Not used.
554 * @return On success, the number of bytes written. On error, -1, and
555 * <code>errno</code> is set appropriately.
556 */
557static int bluesleep_write_proc_proto(struct file *file, const char *buffer,
558 unsigned long count, void *data)
559{
560 char proto;
561
562 if (count < 1)
563 return -EINVAL;
564
565 if (copy_from_user(&proto, buffer, 1))
566 return -EFAULT;
567
568 if (proto == '0')
569 bluesleep_stop();
570 else
571 bluesleep_start();
572
573 /* claim that we wrote everything */
574 return count;
575}
576
577
578static int bluesleep_probe(struct platform_device *pdev)
579{
580 int ret;
581 struct resource *res;
582
583 bsi = kzalloc(sizeof(struct bluesleep_info), GFP_KERNEL);
584 if (!bsi)
585 return -ENOMEM;
586
587 res = platform_get_resource_byname(pdev, IORESOURCE_IO,
588 "gpio_host_wake");
589 if (!res) {
590 BT_ERR("couldn't find host_wake gpio\n");
591 ret = -ENODEV;
592 goto free_bsi;
593 }
594 bsi->host_wake = res->start;
595
596 ret = gpio_request(bsi->host_wake, "bt_host_wake");
597 if (ret)
598 goto free_bsi;
599
600 /* configure host_wake as input */
601 ret = gpio_direction_input(bsi->host_wake);
602 if (ret < 0) {
603 pr_err("gpio-keys: failed to configure input"
604 " direction for GPIO %d, error %d\n",
605 bsi->host_wake, ret);
606 gpio_free(bsi->host_wake);
607 goto free_bsi;
608 }
609
610 res = platform_get_resource_byname(pdev, IORESOURCE_IO,
611 "gpio_ext_wake");
612
613 if (!res)
614 bsi->has_ext_wake = 0;
615 else
616 bsi->has_ext_wake = 1;
617
618 if (bsi->has_ext_wake) {
619 bsi->ext_wake = res->start;
620 ret = gpio_request(bsi->ext_wake, "bt_ext_wake");
621 if (ret)
622 goto free_bt_host_wake;
623
624 /* configure ext_wake as output mode*/
625 ret = gpio_direction_output(bsi->ext_wake, 1);
626 if (ret < 0) {
627 pr_err("gpio-keys: failed to configure output"
628 " direction for GPIO %d, error %d\n",
629 bsi->ext_wake, ret);
630 gpio_free(bsi->ext_wake);
631 goto free_bt_host_wake;
632 }
633 } else
634 set_bit(BT_EXT_WAKE, &flags);
635
636 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
637 "host_wake");
638 if (!res) {
639 BT_ERR("couldn't find host_wake irq\n");
640 ret = -ENODEV;
641 goto free_bt_host_wake;
642 }
643 bsi->host_wake_irq = res->start;
644 if (bsi->host_wake_irq < 0) {
645 BT_ERR("couldn't find host_wake irq\n");
646 ret = -ENODEV;
647 goto free_bt_ext_wake;
648 }
649 if (res->flags & IORESOURCE_IRQ_LOWEDGE)
650 bsi->irq_polarity = POLARITY_LOW;/*low edge (falling edge)*/
651 else
652 bsi->irq_polarity = POLARITY_HIGH;/*anything else*/
653
654 wake_lock_init(&bsi->wake_lock, WAKE_LOCK_SUSPEND, "bluesleep");
655 clear_bit(BT_SUSPEND, &flags);
656
657 if (bsi->irq_polarity == POLARITY_LOW) {
658 ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
659 IRQF_DISABLED | IRQF_TRIGGER_FALLING,
660 "bluetooth hostwake", NULL);
661 } else {
662 ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
663 IRQF_DISABLED | IRQF_TRIGGER_RISING,
664 "bluetooth hostwake", NULL);
665 }
666 if (ret < 0) {
667 BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ");
668 goto free_bt_ext_wake;
669 }
670
671 return 0;
672
673free_bt_ext_wake:
674 gpio_free(bsi->ext_wake);
675free_bt_host_wake:
676 gpio_free(bsi->host_wake);
677free_bsi:
678 kfree(bsi);
679 return ret;
680}
681
682static int bluesleep_remove(struct platform_device *pdev)
683{
684 free_irq(bsi->host_wake_irq, NULL);
685 gpio_free(bsi->host_wake);
686 gpio_free(bsi->ext_wake);
687 wake_lock_destroy(&bsi->wake_lock);
688 kfree(bsi);
689 return 0;
690}
691
692
693static int bluesleep_resume(struct platform_device *pdev)
694{
695 if (test_bit(BT_SUSPEND, &flags)) {
696 BT_DBG("bluesleep resuming...\n");
697 if ((bsi->uport != NULL) &&
698 (gpio_get_value(bsi->host_wake) == bsi->irq_polarity)) {
699 BT_DBG("bluesleep resume form BT event...\n");
700 tegra_uart_request_clock_on(bsi->uport);
701 tegra_uart_set_mctrl(bsi->uport, TIOCM_RTS);
702 }
703 clear_bit(BT_SUSPEND, &flags);
704 }
705 return 0;
706}
707
708static int bluesleep_suspend(struct platform_device *pdev, pm_message_t state)
709{
710 BT_DBG("bluesleep suspending...\n");
711 set_bit(BT_SUSPEND, &flags);
712 return 0;
713}
714
715static struct platform_driver bluesleep_driver = {
716 .probe = bluesleep_probe,
717 .remove = bluesleep_remove,
718 .suspend = bluesleep_suspend,
719 .resume = bluesleep_resume,
720 .driver = {
721 .name = "bluesleep",
722 .owner = THIS_MODULE,
723 },
724};
725/**
726 * Initializes the module.
727 * @return On success, 0. On error, -1, and <code>errno</code> is set
728 * appropriately.
729 */
730static int __init bluesleep_init(void)
731{
732 int retval;
733 struct proc_dir_entry *ent;
734
735 BT_INFO("BlueSleep Mode Driver Ver %s", VERSION);
736
737 retval = platform_driver_register(&bluesleep_driver);
738 if (retval)
739 return retval;
740
741 if (bsi == NULL)
742 return 0;
743
744 bluesleep_hdev = NULL;
745
746 bluetooth_dir = proc_mkdir("bluetooth", NULL);
747 if (bluetooth_dir == NULL) {
748 BT_ERR("Unable to create /proc/bluetooth directory");
749 return -ENOMEM;
750 }
751
752 sleep_dir = proc_mkdir("sleep", bluetooth_dir);
753 if (sleep_dir == NULL) {
754 BT_ERR("Unable to create /proc/%s directory", PROC_DIR);
755 return -ENOMEM;
756 }
757
758 /* Creating read/write "btwake" entry */
759 ent = create_proc_entry("btwake", 0, sleep_dir);
760 if (ent == NULL) {
761 BT_ERR("Unable to create /proc/%s/btwake entry", PROC_DIR);
762 retval = -ENOMEM;
763 goto fail;
764 }
765 ent->read_proc = bluepower_read_proc_btwake;
766 ent->write_proc = bluepower_write_proc_btwake;
767
768 /* read only proc entries */
769 if (create_proc_read_entry("hostwake", 0, sleep_dir,
770 bluepower_read_proc_hostwake, NULL) == NULL) {
771 BT_ERR("Unable to create /proc/%s/hostwake entry", PROC_DIR);
772 retval = -ENOMEM;
773 goto fail;
774 }
775
776 /* read/write proc entries */
777 ent = create_proc_entry("proto", 0, sleep_dir);
778 if (ent == NULL) {
779 BT_ERR("Unable to create /proc/%s/proto entry", PROC_DIR);
780 retval = -ENOMEM;
781 goto fail;
782 }
783 ent->read_proc = bluesleep_read_proc_proto;
784 ent->write_proc = bluesleep_write_proc_proto;
785
786 /* read only proc entries */
787 if (create_proc_read_entry("asleep", 0,
788 sleep_dir, bluesleep_read_proc_asleep, NULL) == NULL) {
789 BT_ERR("Unable to create /proc/%s/asleep entry", PROC_DIR);
790 retval = -ENOMEM;
791 goto fail;
792 }
793
794 flags = 0; /* clear all status bits */
795
796 /* Initialize spinlock. */
797 spin_lock_init(&rw_lock);
798
799 /* Initialize timer */
800 init_timer(&tx_timer);
801 tx_timer.function = bluesleep_tx_timer_expire;
802 tx_timer.data = 0;
803
804 /* initialize host wake tasklet */
805 tasklet_init(&hostwake_task, bluesleep_hostwake_task, 0);
806
807 /* assert bt wake */
808 if (bsi->has_ext_wake == 1)
809 gpio_set_value(bsi->ext_wake, 1);
810 set_bit(BT_EXT_WAKE, &flags);
811 hci_register_notifier(&hci_event_nblock);
812
813 return 0;
814
815fail:
816 remove_proc_entry("asleep", sleep_dir);
817 remove_proc_entry("proto", sleep_dir);
818 remove_proc_entry("hostwake", sleep_dir);
819 remove_proc_entry("btwake", sleep_dir);
820 remove_proc_entry("sleep", bluetooth_dir);
821 remove_proc_entry("bluetooth", 0);
822 return retval;
823}
824
825/**
826 * Cleans up the module.
827 */
828static void __exit bluesleep_exit(void)
829{
830 if (bsi == NULL)
831 return;
832
833 /* assert bt wake */
834 if (bsi->has_ext_wake == 1)
835 gpio_set_value(bsi->ext_wake, 1);
836 set_bit(BT_EXT_WAKE, &flags);
837 if (test_bit(BT_PROTO, &flags)) {
838 if (disable_irq_wake(bsi->host_wake_irq))
839 BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n");
840 free_irq(bsi->host_wake_irq, NULL);
841 del_timer(&tx_timer);
842 if (test_bit(BT_ASLEEP, &flags))
843 hsuart_power(1);
844 }
845
846 hci_unregister_notifier(&hci_event_nblock);
847 platform_driver_unregister(&bluesleep_driver);
848
849 remove_proc_entry("asleep", sleep_dir);
850 remove_proc_entry("proto", sleep_dir);
851 remove_proc_entry("hostwake", sleep_dir);
852 remove_proc_entry("btwake", sleep_dir);
853 remove_proc_entry("sleep", bluetooth_dir);
854 remove_proc_entry("bluetooth", 0);
855}
856
857module_init(bluesleep_init);
858module_exit(bluesleep_exit);
859
860MODULE_DESCRIPTION("Bluetooth Sleep Mode Driver ver %s " VERSION);
861#ifdef MODULE_LICENSE
862MODULE_LICENSE("GPL");
863#endif
864
diff --git a/drivers/bluetooth/ti_bluesleep.c b/drivers/bluetooth/ti_bluesleep.c
new file mode 100644
index 00000000000..d86fd261e67
--- /dev/null
+++ b/drivers/bluetooth/ti_bluesleep.c
@@ -0,0 +1,371 @@
1/*
2 * TI Bluesleep driver
3 * Kernel module responsible for Wake up of Host
4 * Copyright (C) 2009-2010 Texas Instruments
5
6
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * for more details.
19 *
20 * Copyright (C) 2006-2007 - Motorola
21 * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
22 *
23 * Date Author Comment
24 * ----------- -------------- --------------------------------
25 * 2006-Apr-28 Motorola The kernel module for running the Bluetooth(R)
26 * Sleep-Mode Protocol from the Host side
27 * 2006-Sep-08 Motorola Added workqueue for handling sleep work.
28 * 2007-Jan-24 Motorola Added mbm_handle_ioi() call to ISR.
29 * 2009-Aug-10 Motorola Changed "add_timer" to "mod_timer" to solve
30 * race when flurry of queued work comes in.
31*/
32
33#include <linux/module.h> /* kernel module definitions */
34#include <linux/errno.h>
35#include <linux/init.h>
36#include <linux/interrupt.h>
37#include <linux/kernel.h>
38#include <linux/notifier.h>
39#include <linux/proc_fs.h>
40#include <linux/spinlock.h>
41#include <linux/timer.h>
42#include <linux/uaccess.h>
43#include <linux/version.h>
44#include <linux/workqueue.h>
45#include <linux/platform_device.h>
46
47#include <linux/irq.h>
48#include <linux/ioport.h>
49#include <linux/param.h>
50#include <linux/bitops.h>
51#include <linux/termios.h>
52#include <linux/wakelock.h>
53#include <mach/gpio.h>
54#include <linux/serial_core.h>
55#include <linux/tegra_uart.h>
56
57#include <net/bluetooth/bluetooth.h>
58#include <net/bluetooth/hci_core.h> /* event notifications */
59#include "hci_uart.h"
60
61/*
62 * Defines
63 */
64
65#define VERSION "1.1"
66
67#define POLARITY_LOW 0
68#define POLARITY_HIGH 1
69
70struct bluesleep_info {
71 unsigned host_wake_irq;
72 struct uart_port *uport;
73 struct wake_lock wake_lock;
74 int irq_polarity;
75 int has_ext_wake;
76};
77
78
79/* state variable names and bit positions */
80#define FLAG_RESET 0x00
81#define BT_ACTIVE 0x02
82#define BT_SUSPEND 0x04
83
84
85/* work function */
86static void hostwake_sleep_work(struct work_struct *work);
87
88/* work queue */
89DECLARE_DELAYED_WORK(ti_sleep_workqueue, hostwake_sleep_work);
90
91/* Macros for handling sleep work */
92#define hostwake_workqueue() schedule_delayed_work(&ti_sleep_workqueue, 0)
93
94static struct bluesleep_info *bsi;
95
96/* module usage */
97static atomic_t open_count = ATOMIC_INIT(1);
98
99/*
100 * Global variables
101 */
102/** Global state flags */
103static unsigned long flags;
104
105/** Tasklet to respond to change in hostwake line */
106static struct tasklet_struct hostwake_task;
107
108/** Lock for state transitions */
109static spinlock_t rw_lock;
110
111/*
112 * Local functions
113 */
114static void hsuart_power(int on)
115{
116 pr_debug("%s", __func__);
117
118 if (on) {
119 tegra_uart_request_clock_on(bsi->uport);
120 tegra_uart_set_mctrl(bsi->uport, TIOCM_RTS);
121 } else {
122 tegra_uart_set_mctrl(bsi->uport, 0);
123 tegra_uart_request_clock_off(bsi->uport);
124 }
125}
126
127
128
129/**
130 * @brief@ main sleep work handling function which update the flags
131 * and activate and deactivate UART .
132 */
133
134static void hostwake_sleep_work(struct work_struct *work)
135{
136 pr_debug("%s", __func__);
137 free_irq(bsi->host_wake_irq, "tibluesleep");
138 /*Activating UART */
139 if (test_bit(BT_SUSPEND, &flags)) {
140 BT_DBG("Activate UART");
141 hsuart_power(1);
142
143 }
144 bsi->has_ext_wake = 0;
145 clear_bit(BT_SUSPEND, &flags);
146 set_bit(BT_ACTIVE, &flags);
147
148}
149
150
151/**
152 * A tasklet function that runs in tasklet context
153 * @param data Not used.
154 */
155static void bluesleep_hostwake_task(unsigned long data)
156{
157 pr_debug("%s", __func__);
158 disable_irq(bsi->host_wake_irq);
159 spin_lock(&rw_lock);
160 hostwake_workqueue();
161 spin_unlock(&rw_lock);
162}
163
164
165/**
166 * Schedules a tasklet to run when receiving an interrupt on the
167 * <code>HOST_WAKE</code> GPIO pin.
168 * @param irq Not used.
169 * @param dev_id Not used.
170 */
171static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id)
172{
173
174 pr_debug("%s", __func__);
175 /* schedule a tasklet to handle the change in the host wake line */
176 bsi->has_ext_wake = 1;
177 tasklet_schedule(&hostwake_task);
178 return IRQ_HANDLED;
179}
180
181/**
182 * Starts the Sleep-Mode Protocol on the Host.
183 * @return On success, 0. On error, -1, and <code>errno</code> is set
184 * appropriately.
185 */
186
187 int bluesleep_start(struct uart_port *uport)
188{
189 int retval;
190 bsi->uport = uport;
191 pr_debug("%s", __func__);
192
193 if (test_bit(BT_SUSPEND, &flags)) {
194 BT_DBG("bluesleep_acquire irq");
195 if (bsi->irq_polarity == POLARITY_LOW) {
196 retval = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
197 IRQF_DISABLED | IRQF_TRIGGER_FALLING,
198 "bluetooth hostwake", "tibluesleep");
199 } else {
200 retval = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
201 IRQF_DISABLED | IRQF_TRIGGER_RISING,
202 "bluetooth hostwake", "tibluesleep");
203 }
204 if (retval < 0) {
205 BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ");
206 goto fail;
207 }
208
209 retval = enable_irq_wake(bsi->host_wake_irq);
210 if (retval < 0) {
211 BT_ERR("Couldn't enable BT_HOST_WAKE as wakeup"
212 "interrupt retval %d\n", retval);
213 free_irq(bsi->host_wake_irq, NULL);
214 goto fail;
215 }
216 }
217
218 return 0;
219fail:
220 atomic_inc(&open_count);
221 return retval;
222}
223
224/**
225 * Stops the Sleep-Mode Protocol on the Host.
226 */
227 void bluesleep_stop(void)
228{
229
230 pr_debug("%s", __func__);
231
232 if (disable_irq_wake(bsi->host_wake_irq))
233 BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n");
234
235 free_irq(bsi->host_wake_irq, NULL);
236}
237
238static int bluesleep_probe(struct platform_device *pdev)
239{
240 int ret;
241 struct resource *res;
242
243 bsi = kzalloc(sizeof(struct bluesleep_info), GFP_KERNEL);
244 if (!bsi)
245 return -ENOMEM;
246
247 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
248 "host_wake");
249 if (!res) {
250 BT_ERR("couldn't find host_wake irq\n");
251 ret = -ENODEV;
252 goto free_bsi;
253 }
254
255 bsi->host_wake_irq = res->start;
256
257 if (bsi->host_wake_irq < 0) {
258 BT_ERR("couldn't find host_wake irq");
259 ret = -ENODEV;
260 goto free_bsi;
261 }
262 if (res->flags & IORESOURCE_IRQ_LOWEDGE)
263 bsi->irq_polarity = POLARITY_LOW;/*low edge (falling edge)*/
264 else
265 bsi->irq_polarity = POLARITY_HIGH;/*anything else*/
266
267 wake_lock_init(&bsi->wake_lock, WAKE_LOCK_SUSPEND, "bluesleep");
268 clear_bit(BT_SUSPEND, &flags);
269 set_bit(BT_ACTIVE, &flags);
270
271 return 0;
272
273free_bsi:
274 kfree(bsi);
275 return ret;
276}
277
278static int bluesleep_remove(struct platform_device *pdev)
279{
280 pr_debug("%s", __func__);
281 kfree(bsi);
282 return 0;
283}
284
285
286static int bluesleep_resume(struct platform_device *pdev)
287{
288
289 pr_debug("%s", __func__);
290 if (test_bit(BT_SUSPEND, &flags)) {
291
292 if ((bsi->uport != NULL) && (bsi->has_ext_wake)) {
293 tegra_uart_request_clock_on(bsi->uport);
294 tegra_uart_set_mctrl(bsi->uport, TIOCM_RTS);
295 }
296 clear_bit(BT_SUSPEND, &flags);
297 set_bit(BT_ACTIVE, &flags);
298 }
299
300 return 0;
301}
302
303static int bluesleep_suspend(struct platform_device *pdev, pm_message_t state)
304{
305 pr_debug("%s", __func__);
306 set_bit(BT_SUSPEND, &flags);
307 return 0;
308}
309
310static struct platform_driver bluesleep_driver = {
311 .probe = bluesleep_probe,
312 .remove = bluesleep_remove,
313 .suspend = bluesleep_suspend,
314 .resume = bluesleep_resume,
315 .driver = {
316 .name = "tibluesleep",
317 .owner = THIS_MODULE,
318 },
319};
320/**
321 * Initializes the module.
322 * @return On success, 0. On error, -1, and <code>errno</code> is set
323 * appropriately.
324 */
325static int __init bluesleep_init(void)
326{
327 int retval;
328
329 BT_INFO("BlueSleep Mode Driver Ver %s", VERSION);
330
331 retval = platform_driver_register(&bluesleep_driver);
332 if (retval)
333 goto fail;
334
335 if (bsi == NULL)
336 return 0;
337
338 flags = FLAG_RESET; /* clear all status bits */
339
340 /* Initialize spinlock. */
341 spin_lock_init(&rw_lock);
342
343 /* initialize host wake tasklet */
344 tasklet_init(&hostwake_task, bluesleep_hostwake_task, 0);
345
346 return 0;
347fail:
348 return retval;
349}
350
351/**
352 * Cleans up the module.
353 */
354
355static void __exit bluesleep_exit(void)
356{
357 if (bsi == NULL)
358 return;
359 /* assert bt wake */
360 free_irq(bsi->host_wake_irq, NULL);
361 platform_driver_unregister(&bluesleep_driver);
362
363}
364
365module_init(bluesleep_init);
366module_exit(bluesleep_exit);
367
368MODULE_DESCRIPTION("TI Bluetooth Sleep Mode Driver ver %s " VERSION);
369#ifdef MODULE_LICENSE
370MODULE_LICENSE("GPL");
371#endif