rk29: pm: rk29_pwm_set_core_voltage delay 10ms
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rk29 / usb_detect.c
1 #include <linux/wakelock.h>
2 #include <linux/workqueue.h>
3 #include <linux/interrupt.h>
4 #include <linux/gpio.h>
5 #include <mach/board.h>
6
7 static irqreturn_t usb_detect_irq_handler(int irq, void *dev_id);
8 static int detect_gpio = INVALID_GPIO;
9
10 static void usb_detect_do_wakeup(struct work_struct *work)
11 {
12         int ret;
13         int irq = gpio_to_irq(detect_gpio);
14         unsigned long flags;
15
16         rk28_send_wakeup_key();
17         free_irq(irq, NULL);
18         flags = gpio_get_value(detect_gpio) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
19         ret = request_irq(irq, usb_detect_irq_handler, flags, "usb_detect", NULL);
20         if (ret < 0) {
21                 pr_err("%s: request_irq(%d) failed\n", __func__, irq);
22         }
23 }
24
25 static DECLARE_DELAYED_WORK(wakeup_work, usb_detect_do_wakeup);
26 static bool wakelock_inited;
27 static struct wake_lock usb_wakelock;
28
29 static irqreturn_t usb_detect_irq_handler(int irq, void *dev_id)
30 {
31         wake_lock_timeout(&usb_wakelock, 10 * HZ);
32         schedule_delayed_work(&wakeup_work, HZ / 10);
33         return IRQ_HANDLED;
34 }
35
36 int board_usb_detect_init(unsigned gpio)
37 {
38         int ret;
39         int irq = gpio_to_irq(gpio);
40         unsigned long flags;
41
42         if (detect_gpio != INVALID_GPIO) {
43                 pr_err("only support call %s once\n", __func__);
44                 return -EINVAL;
45         }
46
47         ret = gpio_request(gpio, "usb_detect");
48         if (ret < 0) {
49                 pr_err("%s: gpio_request(%d) failed\n", __func__, gpio);
50                 return ret;
51         }
52
53         if (!wakelock_inited) {
54                 wake_lock_init(&usb_wakelock, WAKE_LOCK_SUSPEND, "usb_detect");
55                 wakelock_inited = true;
56         }
57
58         gpio_direction_input(gpio);
59
60         detect_gpio = gpio;
61
62         flags = gpio_get_value(gpio) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
63         ret = request_irq(irq, usb_detect_irq_handler, flags, "usb_detect", NULL);
64         if (ret < 0) {
65                 pr_err("%s: request_irq(%d) failed\n", __func__, irq);
66                 gpio_free(gpio);
67                 detect_gpio = INVALID_GPIO;
68                 return ret;
69         }
70         enable_irq_wake(irq);
71
72         return 0;
73 }
74