USB: support RK3188 usb bypass uart function
[firefly-linux-kernel-4.4.55.git] / arch / arm / plat-rk / usb_detect.c
1 #include <linux/wakelock.h>
2 #include <linux/workqueue.h>
3 #include <linux/interrupt.h>
4 #include <linux/irq.h>
5 #include <linux/gpio.h>
6 #include <mach/board.h>
7
8 #define WAKE_LOCK_TIMEOUT       (10 * HZ)
9
10 static irqreturn_t usb_detect_irq_handler(int irq, void *dev_id);
11 static int detect_gpio = INVALID_GPIO;
12
13 static void usb_detect_do_wakeup(struct work_struct *work)
14 {
15         int ret;
16         int irq = gpio_to_irq(detect_gpio);
17         unsigned int type;
18
19         rk28_send_wakeup_key();
20         type = gpio_get_value(detect_gpio) ? IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
21         ret = irq_set_irq_type(irq, type);
22         if (ret < 0) {
23                 pr_err("%s: irq_set_irq_type(%d, %d) failed\n", __func__, irq, type);
24         }
25         enable_irq(irq);
26 }
27
28 static DECLARE_DELAYED_WORK(wakeup_work, usb_detect_do_wakeup);
29 static bool wakelock_inited;
30 static struct wake_lock usb_wakelock;
31
32 static irqreturn_t usb_detect_irq_handler(int irq, void *dev_id)
33 {
34         disable_irq_nosync(irq); // for irq debounce
35         wake_lock_timeout(&usb_wakelock, WAKE_LOCK_TIMEOUT);
36         schedule_delayed_work(&wakeup_work, HZ / 10);
37         return IRQ_HANDLED;
38 }
39
40 int __init board_usb_detect_init(unsigned gpio)
41 {
42         int ret;
43         int irq = gpio_to_irq(gpio);
44         unsigned long flags;
45
46         if (detect_gpio != INVALID_GPIO) {
47                 pr_err("only support call %s once\n", __func__);
48                 return -EINVAL;
49         }
50
51         ret = gpio_request(gpio, "usb_detect");
52         if (ret < 0) {
53                 pr_err("%s: gpio_request(%d) failed\n", __func__, gpio);
54                 return ret;
55         }
56
57         if (!wakelock_inited) {
58                 wake_lock_init(&usb_wakelock, WAKE_LOCK_SUSPEND, "usb_detect");
59                 wakelock_inited = true;
60         }
61
62         gpio_direction_input(gpio);
63
64         detect_gpio = gpio;
65
66         flags = gpio_get_value(gpio) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
67         ret = request_irq(irq, usb_detect_irq_handler, flags, "usb_detect", NULL);
68         if (ret < 0) {
69                 pr_err("%s: request_irq(%d) failed\n", __func__, irq);
70                 gpio_free(gpio);
71                 detect_gpio = INVALID_GPIO;
72                 return ret;
73         }
74         enable_irq_wake(irq);
75
76         return 0;
77 }
78
79 #ifdef IRQ_OTG_BVALID
80 #include <linux/io.h>
81 #include <mach/iomux.h>
82
83 static irqreturn_t bvalid_irq_handler(int irq, void *dev_id)
84 {
85         /* clear irq */
86 #ifdef CONFIG_ARCH_RK2928
87         writel_relaxed((1 << 31) | (1 << 15), RK2928_GRF_BASE + GRF_UOC0_CON5);
88 #ifdef CONFIG_RK_USB_UART
89         /* usb otg dp/dm switch to usb phy */
90         writel_relaxed((3 << (12 + 16)),RK2928_GRF_BASE + GRF_UOC1_CON4);
91 #endif
92 #elif defined(CONFIG_ARCH_RK3188)
93         writel_relaxed((1 << 31) | (1 << 15), RK30_GRF_BASE + GRF_UOC0_CON3);
94 #ifdef CONFIG_RK_USB_UART
95         /* usb otg dp/dm switch to usb phy */
96         writel_relaxed((0x0300 << 16), RK30_GRF_BASE + GRF_UOC0_CON0);
97 #endif
98 #endif
99
100 #ifdef CONFIG_RK_USB_DETECT_BY_OTG_BVALID
101         wake_lock_timeout(&usb_wakelock, WAKE_LOCK_TIMEOUT);
102         rk28_send_wakeup_key();
103 #endif
104
105         return IRQ_HANDLED;
106 }
107
108 static int __init bvalid_init(void)
109 {
110         int ret;
111         int irq = IRQ_OTG_BVALID;
112
113 #ifndef CONFIG_RK_USB_UART
114         if (detect_gpio != INVALID_GPIO) {
115                 printk("usb detect inited by board_usb_detect_init, disable detect by bvalid irq\n");
116                 return 0;
117         }
118 #endif
119
120 #ifdef CONFIG_RK_USB_DETECT_BY_OTG_BVALID
121         if (!wakelock_inited) {
122                 wake_lock_init(&usb_wakelock, WAKE_LOCK_SUSPEND, "usb_detect");
123                 wakelock_inited = true;
124         }
125 #endif
126
127         ret = request_irq(irq, bvalid_irq_handler, 0, "bvalid", NULL);
128         if (ret < 0) {
129                 pr_err("%s: request_irq(%d) failed\n", __func__, irq);
130                 return ret;
131         }
132
133         /* clear & enable bvalid irq */
134 #ifdef CONFIG_ARCH_RK2928
135         writel_relaxed((3 << 30) | (3 << 14), RK2928_GRF_BASE + GRF_UOC0_CON5);
136 #elif defined(CONFIG_ARCH_RK3188)
137         writel_relaxed((3 << 30) | (3 << 14), RK30_GRF_BASE + GRF_UOC0_CON3);
138 #endif
139
140 #ifdef CONFIG_RK_USB_DETECT_BY_OTG_BVALID
141         enable_irq_wake(irq);
142 #endif
143
144         return 0;
145 }
146 late_initcall(bvalid_init);
147 #endif