2 * arch/arm/mach-tegra/tegra_usb_modem_power.c
4 * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include <linux/module.h>
22 #include <linux/init.h>
23 #include <linux/interrupt.h>
24 #include <linux/platform_device.h>
25 #include <linux/platform_data/tegra_usb.h>
26 #include <linux/workqueue.h>
27 #include <linux/gpio.h>
28 #include <linux/usb.h>
29 #include <linux/err.h>
30 #include <linux/pm_runtime.h>
31 #include <linux/suspend.h>
32 #include <linux/slab.h>
33 #include <linux/wakelock.h>
34 #include <linux/pm_qos.h>
35 #include <mach/gpio-tegra.h>
36 #include <mach/tegra_usb_modem_power.h>
38 #define BOOST_CPU_FREQ_MIN 1200000
39 #define BOOST_CPU_FREQ_TIMEOUT 5000
41 #define WAKELOCK_TIMEOUT_FOR_USB_ENUM (HZ * 10)
42 #define WAKELOCK_TIMEOUT_FOR_REMOTE_WAKE (HZ)
44 struct tegra_usb_modem {
45 struct tegra_usb_modem_power_platform_data *pdata;
46 unsigned int wake_cnt; /* remote wakeup counter */
47 unsigned int wake_irq; /* remote wakeup irq */
48 unsigned int boot_irq; /* modem boot irq */
50 struct wake_lock wake_lock; /* modem wake lock */
51 unsigned int vid; /* modem vendor id */
52 unsigned int pid; /* modem product id */
53 struct usb_device *udev; /* modem usb device */
54 struct usb_device *parent; /* parent device */
55 struct usb_interface *intf; /* first modem usb interface */
56 struct workqueue_struct *wq; /* modem workqueue */
57 struct delayed_work recovery_work; /* modem recovery work */
58 struct work_struct host_load_work; /* usb host load work */
59 struct work_struct host_unload_work; /* usb host unload work */
60 struct pm_qos_request cpu_boost_req; /* min CPU freq request */
61 struct work_struct cpu_boost_work; /* CPU freq boost work */
62 struct delayed_work cpu_unboost_work; /* CPU freq unboost work */
63 const struct tegra_modem_operations *ops; /* modem operations */
64 unsigned int capability; /* modem capability */
65 int system_suspend; /* system suspend flag */
66 struct notifier_block pm_notifier; /* pm event notifier */
67 struct notifier_block usb_notifier; /* usb event notifier */
68 int sysfs_file_created;
69 int short_autosuspend_enabled;
72 static struct platform_device *hc = NULL; /* USB host controller */
73 static struct mutex hc_lock;
74 static const struct platform_device *hc_device;
75 static const struct tegra_usb_platform_data *hc_pdata;
77 /* supported modems */
78 static const struct usb_device_id modem_list[] = {
79 {USB_DEVICE(0x1983, 0x0310), /* Icera 450 rev1 */
80 .driver_info = TEGRA_MODEM_AUTOSUSPEND,
82 {USB_DEVICE(0x1983, 0x0321), /* Icera 450 rev2 */
83 .driver_info = TEGRA_MODEM_AUTOSUSPEND,
85 {USB_DEVICE(0x1983, 0x0327), /* Icera 450 5AE */
86 .driver_info = TEGRA_MODEM_AUTOSUSPEND,
88 {USB_DEVICE(0x1983, 0x0427), /* Icera 500 5AN */
89 .driver_info = TEGRA_MODEM_AUTOSUSPEND,
91 {USB_DEVICE(0x1983, 0x1005), /* Icera 500 5AN (BSD) */
92 /* .driver_info = TEGRA_MODEM_AUTOSUSPEND, */
94 {USB_DEVICE(0x1983, 0x1006), /* Icera 500 Nemo */
95 .driver_info = TEGRA_USB_HOST_RELOAD,
100 static ssize_t load_unload_usb_host(struct device *dev,
101 struct device_attribute *attr,
102 const char *buf, size_t count);
104 static void cpu_freq_unboost(struct work_struct *ws)
106 struct tegra_usb_modem *modem = container_of(ws, struct tegra_usb_modem,
107 cpu_unboost_work.work);
109 pm_qos_update_request(&modem->cpu_boost_req, PM_QOS_DEFAULT_VALUE);
112 static void cpu_freq_boost(struct work_struct *ws)
114 struct tegra_usb_modem *modem = container_of(ws, struct tegra_usb_modem,
117 cancel_delayed_work_sync(&modem->cpu_unboost_work);
118 pm_qos_update_request(&modem->cpu_boost_req, BOOST_CPU_FREQ_MIN);
119 queue_delayed_work(modem->wq, &modem->cpu_unboost_work,
120 msecs_to_jiffies(BOOST_CPU_FREQ_TIMEOUT));
123 static irqreturn_t tegra_usb_modem_wake_thread(int irq, void *data)
125 struct tegra_usb_modem *modem = (struct tegra_usb_modem *)data;
127 mutex_lock(&modem->lock);
128 if (modem->udev && modem->udev->state != USB_STATE_NOTATTACHED) {
129 pr_info("modem wake (%u)\n", ++(modem->wake_cnt));
131 if (!modem->system_suspend) {
132 wake_lock_timeout(&modem->wake_lock,
133 WAKELOCK_TIMEOUT_FOR_REMOTE_WAKE);
135 usb_lock_device(modem->udev);
136 if (usb_autopm_get_interface(modem->intf) == 0)
137 usb_autopm_put_interface_async(modem->intf);
138 usb_unlock_device(modem->udev);
141 if (modem->capability & TEGRA_MODEM_AUTOSUSPEND &&
142 modem->short_autosuspend_enabled) {
143 pm_runtime_set_autosuspend_delay(&modem->udev->dev,
144 modem->pdata->autosuspend_delay);
145 modem->short_autosuspend_enabled = 0;
149 mutex_unlock(&modem->lock);
154 static irqreturn_t tegra_usb_modem_boot_thread(int irq, void *data)
156 struct tegra_usb_modem *modem = (struct tegra_usb_modem *)data;
157 int v = gpio_get_value(modem->pdata->boot_gpio);
159 pr_info("MDM_COLDBOOT %s\n", v ? "high" : "low");
161 if (modem->capability & TEGRA_USB_HOST_RELOAD)
162 if (!work_pending(&modem->host_load_work) &&
163 !work_pending(&modem->host_unload_work))
164 queue_work(modem->wq, v ? &modem->host_load_work :
165 &modem->host_unload_work);
167 /* hold wait lock to complete the enumeration */
168 wake_lock_timeout(&modem->wake_lock, WAKELOCK_TIMEOUT_FOR_USB_ENUM);
171 if (!work_pending(&modem->cpu_boost_work))
172 queue_work(modem->wq, &modem->cpu_boost_work);
174 /* USB disconnect maybe on going... */
175 mutex_lock(&modem->lock);
176 if (modem->udev && modem->udev->state != USB_STATE_NOTATTACHED)
177 pr_warn("Device is not disconnected!\n");
178 mutex_unlock(&modem->lock);
183 static void tegra_usb_modem_recovery(struct work_struct *ws)
185 struct tegra_usb_modem *modem = container_of(ws, struct tegra_usb_modem,
188 mutex_lock(&modem->lock);
189 if (!modem->udev) { /* assume modem crashed */
190 if (modem->ops && modem->ops->reset)
193 mutex_unlock(&modem->lock);
196 static void tegra_usb_host_load(struct work_struct *ws)
198 load_unload_usb_host(NULL, NULL, "1", 1);
201 static void tegra_usb_host_unload(struct work_struct *ws)
203 load_unload_usb_host(NULL, NULL, "0", 1);
206 static void device_add_handler(struct tegra_usb_modem *modem,
207 struct usb_device *udev)
209 const struct usb_device_descriptor *desc = &udev->descriptor;
210 struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
211 const struct usb_device_id *id = NULL;
214 id = usb_match_id(intf, modem_list);
217 /* hold wakelock to ensure ril has enough time to restart */
218 wake_lock_timeout(&modem->wake_lock,
219 WAKELOCK_TIMEOUT_FOR_USB_ENUM);
221 pr_info("Add device %d <%s %s>\n", udev->devnum,
222 udev->manufacturer, udev->product);
224 mutex_lock(&modem->lock);
226 modem->parent = udev->parent;
228 modem->vid = desc->idVendor;
229 modem->pid = desc->idProduct;
231 modem->capability = id->driver_info;
232 mutex_unlock(&modem->lock);
234 pr_info("persist_enabled: %u\n", udev->persist_enabled);
237 if (modem->capability & TEGRA_MODEM_AUTOSUSPEND) {
238 pm_runtime_set_autosuspend_delay(&udev->dev,
239 modem->pdata->autosuspend_delay);
240 modem->short_autosuspend_enabled = 0;
241 usb_enable_autosuspend(udev);
242 pr_info("enable autosuspend for %s %s\n",
243 udev->manufacturer, udev->product);
246 /* allow the device to wake up the system */
247 if (udev->actconfig->desc.bmAttributes &
248 USB_CONFIG_ATT_WAKEUP)
249 device_set_wakeup_enable(&udev->dev, true);
255 static void device_remove_handler(struct tegra_usb_modem *modem,
256 struct usb_device *udev)
258 const struct usb_device_descriptor *desc = &udev->descriptor;
260 if (desc->idVendor == modem->vid && desc->idProduct == modem->pid) {
261 pr_info("Remove device %d <%s %s>\n", udev->devnum,
262 udev->manufacturer, udev->product);
264 mutex_lock(&modem->lock);
268 mutex_unlock(&modem->lock);
270 if (modem->capability & TEGRA_MODEM_RECOVERY)
271 queue_delayed_work(modem->wq,
272 &modem->recovery_work, HZ * 10);
276 static int mdm_usb_notifier(struct notifier_block *notifier,
277 unsigned long usb_event, void *udev)
279 struct tegra_usb_modem *modem =
280 container_of(notifier, struct tegra_usb_modem, usb_notifier);
284 device_add_handler(modem, udev);
286 case USB_DEVICE_REMOVE:
287 device_remove_handler(modem, udev);
293 static int mdm_pm_notifier(struct notifier_block *notifier,
294 unsigned long pm_event, void *unused)
296 struct tegra_usb_modem *modem =
297 container_of(notifier, struct tegra_usb_modem, pm_notifier);
299 mutex_lock(&modem->lock);
301 mutex_unlock(&modem->lock);
305 pr_info("%s: event %ld\n", __func__, pm_event);
307 case PM_SUSPEND_PREPARE:
308 if (wake_lock_active(&modem->wake_lock)) {
309 pr_warn("%s: wakelock was active, aborting suspend\n",
311 mutex_unlock(&modem->lock);
315 modem->system_suspend = 1;
317 if (modem->capability & TEGRA_MODEM_AUTOSUSPEND &&
319 modem->udev->state != USB_STATE_NOTATTACHED) {
320 pm_runtime_set_autosuspend_delay(&modem->udev->dev,
321 modem->pdata->short_autosuspend_delay);
322 modem->short_autosuspend_enabled = 1;
325 mutex_unlock(&modem->lock);
327 case PM_POST_SUSPEND:
328 modem->system_suspend = 0;
329 mutex_unlock(&modem->lock);
333 mutex_unlock(&modem->lock);
337 static int mdm_request_wakeable_irq(struct tegra_usb_modem *modem,
338 irq_handler_t thread_fn,
339 unsigned int irq_gpio,
340 unsigned long irq_flags,
341 const char *label, unsigned int *irq)
345 ret = gpio_request(irq_gpio, label);
349 /* enable IRQ for GPIO */
350 *irq = gpio_to_irq(irq_gpio);
352 /* request threaded irq for GPIO */
353 ret = request_threaded_irq(*irq, NULL, thread_fn, irq_flags, label,
358 ret = enable_irq_wake(*irq);
360 free_irq(*irq, modem);
367 /* load USB host controller */
368 static struct platform_device *tegra_usb_host_register(void)
370 struct platform_device *pdev;
373 pdev = platform_device_alloc(hc_device->name, hc_device->id);
377 val = platform_device_add_resources(pdev, hc_device->resource,
378 hc_device->num_resources);
382 pdev->dev.dma_mask = hc_device->dev.dma_mask;
383 pdev->dev.coherent_dma_mask = hc_device->dev.coherent_dma_mask;
385 val = platform_device_add_data(pdev, hc_pdata,
386 sizeof(struct tegra_usb_platform_data));
390 val = platform_device_add(pdev);
397 pr_err("%s: err %d\n", __func__, val);
398 platform_device_put(pdev);
402 /* unload USB host controller */
403 static void tegra_usb_host_unregister(struct platform_device *pdev)
405 platform_device_unregister(pdev);
408 static ssize_t show_usb_host(struct device *dev,
409 struct device_attribute *attr, char *buf)
411 return sprintf(buf, "%d\n", (hc) ? 1 : 0);
414 static ssize_t load_unload_usb_host(struct device *dev,
415 struct device_attribute *attr,
416 const char *buf, size_t count)
420 if (sscanf(buf, "%d", &host) != 1 || host < 0 || host > 1)
423 pr_info("%s USB host\n", (host) ? "load" : "unload");
425 mutex_lock(&hc_lock);
428 hc = tegra_usb_host_register();
431 tegra_usb_host_unregister(hc);
435 mutex_unlock(&hc_lock);
440 static DEVICE_ATTR(load_host, S_IRUSR | S_IWUSR, show_usb_host,
441 load_unload_usb_host);
443 static int mdm_init(struct tegra_usb_modem *modem, struct platform_device *pdev)
445 struct tegra_usb_modem_power_platform_data *pdata =
446 pdev->dev.platform_data;
449 modem->pdata = pdata;
451 hc_device = pdata->tegra_ehci_device;
452 hc_pdata = pdata->tegra_ehci_pdata;
453 mutex_init(&hc_lock);
455 /* get modem operations from platform data */
456 modem->ops = (const struct tegra_modem_operations *)pdata->ops;
460 if (modem->ops->init) {
461 ret = modem->ops->init();
467 if (modem->ops->start)
471 /* create sysfs node to load/unload host controller */
472 ret = device_create_file(&pdev->dev, &dev_attr_load_host);
474 dev_err(&pdev->dev, "can't create sysfs file\n");
477 modem->sysfs_file_created = 1;
479 mutex_init(&(modem->lock));
480 wake_lock_init(&modem->wake_lock, WAKE_LOCK_SUSPEND, "mdm_lock");
482 /* create work queue platform_driver_registe */
483 modem->wq = create_workqueue("tegra_usb_mdm_queue");
484 INIT_DELAYED_WORK(&modem->recovery_work, tegra_usb_modem_recovery);
485 INIT_WORK(&modem->host_load_work, tegra_usb_host_load);
486 INIT_WORK(&modem->host_unload_work, tegra_usb_host_unload);
487 INIT_WORK(&modem->cpu_boost_work, cpu_freq_boost);
488 INIT_DELAYED_WORK(&modem->cpu_unboost_work, cpu_freq_unboost);
490 pm_qos_add_request(&modem->cpu_boost_req, PM_QOS_CPU_FREQ_MIN,
491 PM_QOS_DEFAULT_VALUE);
493 /* if wake gpio is not specified we rely on native usb remote wake */
494 if (gpio_is_valid(pdata->wake_gpio)) {
495 /* request remote wakeup irq from platform data */
496 ret = mdm_request_wakeable_irq(modem,
497 tegra_usb_modem_wake_thread,
499 pdata->wake_irq_flags,
500 "mdm_wake", &modem->wake_irq);
502 dev_err(&pdev->dev, "request wake irq error\n");
507 if (gpio_is_valid(pdata->boot_gpio)) {
508 /* request boot irq from platform data */
509 ret = mdm_request_wakeable_irq(modem,
510 tegra_usb_modem_boot_thread,
512 pdata->boot_irq_flags,
513 "mdm_boot", &modem->boot_irq);
515 dev_err(&pdev->dev, "request boot irq error\n");
519 dev_err(&pdev->dev, "boot irq not specified\n");
523 modem->pm_notifier.notifier_call = mdm_pm_notifier;
524 modem->usb_notifier.notifier_call = mdm_usb_notifier;
526 usb_register_notify(&modem->usb_notifier);
527 register_pm_notifier(&modem->pm_notifier);
531 if (modem->sysfs_file_created)
532 device_remove_file(&pdev->dev, &dev_attr_load_host);
534 if (modem->wake_irq) {
535 disable_irq_wake(modem->wake_irq);
536 free_irq(modem->wake_irq, modem);
539 if (modem->boot_irq) {
540 disable_irq_wake(modem->boot_irq);
541 free_irq(modem->boot_irq, modem);
547 static int tegra_usb_modem_probe(struct platform_device *pdev)
549 struct tegra_usb_modem_power_platform_data *pdata =
550 pdev->dev.platform_data;
551 struct tegra_usb_modem *modem;
555 dev_dbg(&pdev->dev, "platform_data not available\n");
559 modem = kzalloc(sizeof(struct tegra_usb_modem), GFP_KERNEL);
561 dev_dbg(&pdev->dev, "failed to allocate memory\n");
565 ret = mdm_init(modem, pdev);
571 dev_set_drvdata(&pdev->dev, modem);
576 static int __exit tegra_usb_modem_remove(struct platform_device *pdev)
578 struct tegra_usb_modem *modem = platform_get_drvdata(pdev);
580 unregister_pm_notifier(&modem->pm_notifier);
581 usb_unregister_notify(&modem->usb_notifier);
583 if (modem->wake_irq) {
584 disable_irq_wake(modem->wake_irq);
585 free_irq(modem->wake_irq, modem);
588 if (modem->boot_irq) {
589 disable_irq_wake(modem->boot_irq);
590 free_irq(modem->boot_irq, modem);
593 if (modem->sysfs_file_created)
594 device_remove_file(&pdev->dev, &dev_attr_load_host);
596 cancel_delayed_work_sync(&modem->recovery_work);
597 cancel_work_sync(&modem->host_load_work);
598 cancel_work_sync(&modem->host_unload_work);
599 cancel_work_sync(&modem->cpu_boost_work);
600 cancel_delayed_work_sync(&modem->cpu_unboost_work);
601 destroy_workqueue(modem->wq);
603 pm_qos_remove_request(&modem->cpu_boost_req);
610 static int tegra_usb_modem_suspend(struct platform_device *pdev,
613 struct tegra_usb_modem *modem = platform_get_drvdata(pdev);
615 /* send L3 hint to modem */
616 if (modem->ops && modem->ops->suspend)
617 modem->ops->suspend();
621 static int tegra_usb_modem_resume(struct platform_device *pdev)
623 struct tegra_usb_modem *modem = platform_get_drvdata(pdev);
625 /* send L3->L0 hint to modem */
626 if (modem->ops && modem->ops->resume)
627 modem->ops->resume();
632 static struct platform_driver tegra_usb_modem_power_driver = {
634 .name = "tegra_usb_modem_power",
635 .owner = THIS_MODULE,
637 .probe = tegra_usb_modem_probe,
638 .remove = __exit_p(tegra_usb_modem_remove),
640 .suspend = tegra_usb_modem_suspend,
641 .resume = tegra_usb_modem_resume,
645 static int __init tegra_usb_modem_power_init(void)
647 return platform_driver_register(&tegra_usb_modem_power_driver);
650 module_init(tegra_usb_modem_power_init);
652 static void __exit tegra_usb_modem_power_exit(void)
654 platform_driver_unregister(&tegra_usb_modem_power_driver);
657 module_exit(tegra_usb_modem_power_exit);
659 MODULE_DESCRIPTION("Tegra usb modem power management driver");
660 MODULE_LICENSE("GPL");