4 * Copyright (C) 2011 Google, Inc.
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <linux/kernel.h>
18 #include <linux/device.h>
19 #include <linux/err.h>
20 #include <linux/module.h>
21 #include <linux/notifier.h>
22 #include <linux/wakelock.h>
23 #include <linux/spinlock.h>
24 #include <linux/usb/otg.h>
26 #define TEMPORARY_HOLD_TIME 2000
28 static bool enabled
= true;
29 static struct usb_phy
*otgwl_xceiv
;
30 static struct notifier_block otgwl_nb
;
33 * otgwl_spinlock is held while the VBUS lock is grabbed or dropped and the
34 * held field is updated to match.
37 static DEFINE_SPINLOCK(otgwl_spinlock
);
40 * Only one lock, but since these 3 fields are associated with each other...
45 struct wake_lock wakelock
;
50 * VBUS present lock. Also used as a timed lock on charger
51 * connect/disconnect and USB host disconnect, to allow the system
52 * to react to the change in power.
55 static struct otgwl_lock vbus_lock
;
57 static void otgwl_hold(struct otgwl_lock
*lock
)
60 wake_lock(&lock
->wakelock
);
65 static void otgwl_temporary_hold(struct otgwl_lock
*lock
)
67 wake_lock_timeout(&lock
->wakelock
,
68 msecs_to_jiffies(TEMPORARY_HOLD_TIME
));
72 static void otgwl_drop(struct otgwl_lock
*lock
)
75 wake_unlock(&lock
->wakelock
);
80 static void otgwl_handle_event(unsigned long event
)
82 unsigned long irqflags
;
84 spin_lock_irqsave(&otgwl_spinlock
, irqflags
);
87 otgwl_drop(&vbus_lock
);
88 spin_unlock_irqrestore(&otgwl_spinlock
, irqflags
);
94 case USB_EVENT_ENUMERATED
:
95 otgwl_hold(&vbus_lock
);
100 case USB_EVENT_CHARGER
:
101 otgwl_temporary_hold(&vbus_lock
);
108 spin_unlock_irqrestore(&otgwl_spinlock
, irqflags
);
111 static int otgwl_otg_notifications(struct notifier_block
*nb
,
112 unsigned long event
, void *unused
)
114 otgwl_handle_event(event
);
118 static int set_enabled(const char *val
, const struct kernel_param
*kp
)
120 int rv
= param_set_bool(val
, kp
);
126 otgwl_handle_event(otgwl_xceiv
->last_event
);
131 static struct kernel_param_ops enabled_param_ops
= {
133 .get
= param_get_bool
,
136 module_param_cb(enabled
, &enabled_param_ops
, &enabled
, 0644);
137 MODULE_PARM_DESC(enabled
, "enable wakelock when VBUS present");
139 static int __init
otg_wakelock_init(void)
144 phy
= usb_get_phy(USB_PHY_TYPE_USB2
);
147 pr_err("%s: No USB transceiver found\n", __func__
);
152 snprintf(vbus_lock
.name
, sizeof(vbus_lock
.name
), "vbus-%s",
153 dev_name(otgwl_xceiv
->dev
));
154 wake_lock_init(&vbus_lock
.wakelock
, WAKE_LOCK_SUSPEND
,
157 otgwl_nb
.notifier_call
= otgwl_otg_notifications
;
158 ret
= usb_register_notifier(otgwl_xceiv
, &otgwl_nb
);
161 pr_err("%s: usb_register_notifier on transceiver %s"
162 " failed\n", __func__
,
163 dev_name(otgwl_xceiv
->dev
));
165 wake_lock_destroy(&vbus_lock
.wakelock
);
169 otgwl_handle_event(otgwl_xceiv
->last_event
);
173 late_initcall(otg_wakelock_init
);