rtc: tps80031: register as mfd sub device
[linux-2.6.git] / arch / arm / mach-tegra / tegra_usb_modem_power.c
1 /*
2  * arch/arm/mach-tegra/tegra_usb_modem_power.c
3  *
4  * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
5  *
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.
10  *
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
14  * more details.
15  *
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.
19  */
20
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_params.h>
35 #include <mach/tegra_usb_modem_power.h>
36
37 #define BOOST_CPU_FREQ_MIN      1200000
38 #define BOOST_CPU_FREQ_TIMEOUT  5000
39
40 #define WAKELOCK_TIMEOUT_FOR_USB_ENUM           (HZ * 10)
41 #define WAKELOCK_TIMEOUT_FOR_REMOTE_WAKE        (HZ)
42
43 struct tegra_usb_modem {
44         struct tegra_usb_modem_power_platform_data *pdata;
45         unsigned int wake_cnt;  /* remote wakeup counter */
46         unsigned int wake_irq;  /* remote wakeup irq */
47         unsigned int boot_irq;  /* modem boot irq */
48         struct mutex lock;
49         struct wake_lock wake_lock;     /* modem wake lock */
50         unsigned int vid;       /* modem vendor id */
51         unsigned int pid;       /* modem product id */
52         struct usb_device *udev;        /* modem usb device */
53         struct usb_device *parent;      /* parent device */
54         struct usb_interface *intf;     /* first modem usb interface */
55         struct workqueue_struct *wq;    /* modem workqueue */
56         struct delayed_work recovery_work;      /* modem recovery work */
57         struct pm_qos_request_list cpu_boost_req; /* min CPU freq request */
58         struct work_struct cpu_boost_work;      /* CPU freq boost work */
59         struct delayed_work cpu_unboost_work;   /* CPU freq unboost work */
60         const struct tegra_modem_operations *ops;       /* modem operations */
61         unsigned int capability;        /* modem capability */
62         int system_suspend;     /* system suspend flag */
63         struct notifier_block pm_notifier;      /* pm event notifier */
64         struct notifier_block usb_notifier;     /* usb event notifier */
65         int sysfs_file_created;
66         int short_autosuspend_enabled;
67 };
68
69 static struct platform_device *hc = NULL;       /* USB host controller */
70 static struct mutex hc_lock;
71 static const struct platform_device *hc_device;
72 static const struct tegra_usb_platform_data *hc_pdata;
73
74 /* supported modems */
75 static const struct usb_device_id modem_list[] = {
76         {USB_DEVICE(0x1983, 0x0310),    /* Icera 450 rev1 */
77          .driver_info = TEGRA_MODEM_AUTOSUSPEND,
78          },
79         {USB_DEVICE(0x1983, 0x0321),    /* Icera 450 rev2 */
80          .driver_info = TEGRA_MODEM_AUTOSUSPEND,
81          },
82         {USB_DEVICE(0x1983, 0x0327),    /* Icera 450 5AE */
83          .driver_info = TEGRA_MODEM_AUTOSUSPEND,
84          },
85         {}
86 };
87
88 static void cpu_freq_unboost(struct work_struct *ws)
89 {
90         struct tegra_usb_modem *modem = container_of(ws, struct tegra_usb_modem,
91                                                      cpu_unboost_work.work);
92
93         pm_qos_update_request(&modem->cpu_boost_req, PM_QOS_DEFAULT_VALUE);
94 }
95
96 static void cpu_freq_boost(struct work_struct *ws)
97 {
98         struct tegra_usb_modem *modem = container_of(ws, struct tegra_usb_modem,
99                                                      cpu_boost_work);
100
101         cancel_delayed_work_sync(&modem->cpu_unboost_work);
102         pm_qos_update_request(&modem->cpu_boost_req, BOOST_CPU_FREQ_MIN);
103         queue_delayed_work(modem->wq, &modem->cpu_unboost_work,
104                               msecs_to_jiffies(BOOST_CPU_FREQ_TIMEOUT));
105 }
106
107 static irqreturn_t tegra_usb_modem_wake_thread(int irq, void *data)
108 {
109         struct tegra_usb_modem *modem = (struct tegra_usb_modem *)data;
110
111         mutex_lock(&modem->lock);
112         if (modem->udev && modem->udev->state != USB_STATE_NOTATTACHED) {
113                 pr_info("modem wake (%u)\n", ++(modem->wake_cnt));
114
115                 if (!modem->system_suspend) {
116                         wake_lock_timeout(&modem->wake_lock,
117                                           WAKELOCK_TIMEOUT_FOR_REMOTE_WAKE);
118
119                         usb_lock_device(modem->udev);
120                         if (usb_autopm_get_interface(modem->intf) == 0)
121                                 usb_autopm_put_interface_async(modem->intf);
122                         usb_unlock_device(modem->udev);
123                 }
124 #ifdef CONFIG_PM
125                 if (modem->capability & TEGRA_MODEM_AUTOSUSPEND &&
126                     modem->short_autosuspend_enabled) {
127                         pm_runtime_set_autosuspend_delay(&modem->udev->dev,
128                                         modem->pdata->autosuspend_delay);
129                         modem->short_autosuspend_enabled = 0;
130                 }
131 #endif
132         }
133         mutex_unlock(&modem->lock);
134
135         return IRQ_HANDLED;
136 }
137
138 static irqreturn_t tegra_usb_modem_boot_thread(int irq, void *data)
139 {
140         struct tegra_usb_modem *modem = (struct tegra_usb_modem *)data;
141
142         if (gpio_get_value(modem->pdata->boot_gpio))
143                 pr_info("BB_RST_OUT high\n");
144         else
145                 pr_info("BB_RST_OUT low\n");
146
147         /* hold wait lock to complete the enumeration */
148         wake_lock_timeout(&modem->wake_lock, WAKELOCK_TIMEOUT_FOR_USB_ENUM);
149
150         /* boost CPU freq */
151         if (!work_pending(&modem->cpu_boost_work))
152                 queue_work(modem->wq, &modem->cpu_boost_work);
153
154         /* USB disconnect maybe on going... */
155         mutex_lock(&modem->lock);
156         if (modem->udev && modem->udev->state != USB_STATE_NOTATTACHED)
157                 pr_warn("Device is not disconnected!\n");
158         mutex_unlock(&modem->lock);
159
160         return IRQ_HANDLED;
161 }
162
163 static void tegra_usb_modem_recovery(struct work_struct *ws)
164 {
165         struct tegra_usb_modem *modem = container_of(ws, struct tegra_usb_modem,
166                                                      recovery_work.work);
167
168         mutex_lock(&modem->lock);
169         if (!modem->udev) {     /* assume modem crashed */
170                 if (modem->ops && modem->ops->reset)
171                         modem->ops->reset();
172         }
173         mutex_unlock(&modem->lock);
174 }
175
176 static void device_add_handler(struct tegra_usb_modem *modem,
177                                struct usb_device *udev)
178 {
179         const struct usb_device_descriptor *desc = &udev->descriptor;
180         struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
181         const struct usb_device_id *id = usb_match_id(intf, modem_list);
182
183         if (id) {
184                 /* hold wakelock to ensure ril has enough time to restart */
185                 wake_lock_timeout(&modem->wake_lock,
186                                   WAKELOCK_TIMEOUT_FOR_USB_ENUM);
187
188                 pr_info("Add device %d <%s %s>\n", udev->devnum,
189                         udev->manufacturer, udev->product);
190
191                 mutex_lock(&modem->lock);
192                 modem->udev = udev;
193                 modem->parent = udev->parent;
194                 modem->intf = intf;
195                 modem->vid = desc->idVendor;
196                 modem->pid = desc->idProduct;
197                 modem->wake_cnt = 0;
198                 modem->capability = id->driver_info;
199                 mutex_unlock(&modem->lock);
200
201                 pr_info("persist_enabled: %u\n", udev->persist_enabled);
202
203 #ifdef CONFIG_PM
204                 if (modem->capability & TEGRA_MODEM_AUTOSUSPEND) {
205                         pm_runtime_set_autosuspend_delay(&udev->dev,
206                                         modem->pdata->autosuspend_delay);
207                         modem->short_autosuspend_enabled = 0;
208                         usb_enable_autosuspend(udev);
209                         pr_info("enable autosuspend for %s %s\n",
210                                 udev->manufacturer, udev->product);
211                 }
212 #endif
213         }
214 }
215
216 static void device_remove_handler(struct tegra_usb_modem *modem,
217                                   struct usb_device *udev)
218 {
219         const struct usb_device_descriptor *desc = &udev->descriptor;
220
221         if (desc->idVendor == modem->vid && desc->idProduct == modem->pid) {
222                 pr_info("Remove device %d <%s %s>\n", udev->devnum,
223                         udev->manufacturer, udev->product);
224
225                 mutex_lock(&modem->lock);
226                 modem->udev = NULL;
227                 modem->intf = NULL;
228                 modem->vid = 0;
229                 mutex_unlock(&modem->lock);
230
231                 if (modem->capability & TEGRA_MODEM_RECOVERY)
232                         queue_delayed_work(modem->wq,
233                                            &modem->recovery_work, HZ * 10);
234         }
235 }
236
237 static int mdm_usb_notifier(struct notifier_block *notifier,
238                             unsigned long usb_event, void *udev)
239 {
240         struct tegra_usb_modem *modem =
241             container_of(notifier, struct tegra_usb_modem, usb_notifier);
242
243         switch (usb_event) {
244         case USB_DEVICE_ADD:
245                 device_add_handler(modem, udev);
246                 break;
247         case USB_DEVICE_REMOVE:
248                 device_remove_handler(modem, udev);
249                 break;
250         }
251         return NOTIFY_OK;
252 }
253
254 static int mdm_pm_notifier(struct notifier_block *notifier,
255                            unsigned long pm_event, void *unused)
256 {
257         struct tegra_usb_modem *modem =
258             container_of(notifier, struct tegra_usb_modem, pm_notifier);
259
260         mutex_lock(&modem->lock);
261         if (!modem->udev) {
262                 mutex_unlock(&modem->lock);
263                 return NOTIFY_DONE;
264         }
265
266         pr_info("%s: event %ld\n", __func__, pm_event);
267         switch (pm_event) {
268         case PM_SUSPEND_PREPARE:
269                 if (wake_lock_active(&modem->wake_lock)) {
270                         pr_warn("%s: wakelock was active, aborting suspend\n",
271                                 __func__);
272                         mutex_unlock(&modem->lock);
273                         return NOTIFY_STOP;
274                 }
275
276                 modem->system_suspend = 1;
277 #ifdef CONFIG_PM
278                 if (modem->capability & TEGRA_MODEM_AUTOSUSPEND &&
279                     modem->udev &&
280                     modem->udev->state != USB_STATE_NOTATTACHED) {
281                         pm_runtime_set_autosuspend_delay(&modem->udev->dev,
282                                         modem->pdata->short_autosuspend_delay);
283                         modem->short_autosuspend_enabled = 1;
284                 }
285 #endif
286                 mutex_unlock(&modem->lock);
287                 return NOTIFY_OK;
288         case PM_POST_SUSPEND:
289                 modem->system_suspend = 0;
290                 mutex_unlock(&modem->lock);
291                 return NOTIFY_OK;
292         }
293
294         mutex_unlock(&modem->lock);
295         return NOTIFY_DONE;
296 }
297
298 static int mdm_request_wakeable_irq(struct tegra_usb_modem *modem,
299                                     irq_handler_t thread_fn,
300                                     unsigned int irq_gpio,
301                                     unsigned long irq_flags,
302                                     const char *label, unsigned int *irq)
303 {
304         int ret;
305
306         ret = gpio_request(irq_gpio, label);
307         if (ret)
308                 return ret;
309
310         /* enable IRQ for GPIO */
311         *irq = gpio_to_irq(irq_gpio);
312
313         /* request threaded irq for GPIO */
314         ret = request_threaded_irq(*irq, NULL, thread_fn, irq_flags, label,
315                                    modem);
316         if (ret)
317                 return ret;
318
319         ret = enable_irq_wake(*irq);
320         if (ret) {
321                 free_irq(*irq, modem);
322                 return ret;
323         }
324
325         return ret;
326 }
327
328 /* load USB host controller */
329 static struct platform_device *tegra_usb_null_ulpi_host_register(void)
330 {
331         struct platform_device *pdev;
332         int val;
333
334         pdev = platform_device_alloc(hc_device->name, hc_device->id);
335         if (!pdev)
336                 return NULL;
337
338         val = platform_device_add_resources(pdev, hc_device->resource,
339                                             hc_device->num_resources);
340         if (val)
341                 goto error;
342
343         pdev->dev.dma_mask = hc_device->dev.dma_mask;
344         pdev->dev.coherent_dma_mask = hc_device->dev.coherent_dma_mask;
345
346         val = platform_device_add_data(pdev, hc_pdata,
347                                        sizeof(struct tegra_usb_platform_data));
348         if (val)
349                 goto error;
350
351         val = platform_device_add(pdev);
352         if (val)
353                 goto error;
354
355         return pdev;
356
357 error:
358         pr_err("%s: err %d\n", __func__, val);
359         platform_device_put(pdev);
360         return NULL;
361 }
362
363 /* unload USB host controller */
364 static void tegra_usb_null_ulpi_host_unregister(struct platform_device *pdev)
365 {
366         platform_device_unregister(pdev);
367 }
368
369 static ssize_t show_usb_host(struct device *dev,
370                              struct device_attribute *attr, char *buf)
371 {
372         return sprintf(buf, "%d\n", (hc) ? 1 : 0);
373 }
374
375 static ssize_t load_unload_usb_host(struct device *dev,
376                                     struct device_attribute *attr,
377                                     const char *buf, size_t count)
378 {
379         int host;
380
381         if (sscanf(buf, "%d", &host) != 1 || host < 0 || host > 1)
382                 return -EINVAL;
383
384         pr_info("%s USB host\n", (host) ? "load" : "unload");
385
386         mutex_lock(&hc_lock);
387         if (host) {
388                 if (!hc)
389                         hc = tegra_usb_null_ulpi_host_register();
390         } else {
391                 if (hc) {
392                         tegra_usb_null_ulpi_host_unregister(hc);
393                         hc = NULL;
394                 }
395         }
396         mutex_unlock(&hc_lock);
397
398         return count;
399 }
400
401 static DEVICE_ATTR(load_host, S_IRUSR | S_IWUSR, show_usb_host,
402                    load_unload_usb_host);
403
404 static int mdm_init(struct tegra_usb_modem *modem, struct platform_device *pdev)
405 {
406         struct tegra_usb_modem_power_platform_data *pdata =
407             pdev->dev.platform_data;
408         int ret = 0;
409
410         modem->pdata = pdata;
411
412         hc_device = pdata->tegra_ehci_device;
413         hc_pdata = pdata->tegra_ehci_pdata;
414         mutex_init(&hc_lock);
415
416         /* get modem operations from platform data */
417         modem->ops = (const struct tegra_modem_operations *)pdata->ops;
418
419         if (modem->ops) {
420                 /* modem init */
421                 if (modem->ops->init) {
422                         ret = modem->ops->init();
423                         if (ret)
424                                 return ret;
425                 }
426
427                 /* start modem */
428                 if (modem->ops->start)
429                         modem->ops->start();
430         }
431
432         /* create sysfs node to load/unload host controller */
433         ret = device_create_file(&pdev->dev, &dev_attr_load_host);
434         if (ret) {
435                 dev_err(&pdev->dev, "can't create sysfs file\n");
436                 goto error;
437         }
438         modem->sysfs_file_created = 1;
439
440         mutex_init(&(modem->lock));
441         wake_lock_init(&modem->wake_lock, WAKE_LOCK_SUSPEND, "mdm_lock");
442
443         /* create work queue platform_driver_registe */
444         modem->wq = create_workqueue("tegra_usb_mdm_queue");
445         INIT_DELAYED_WORK(&modem->recovery_work, tegra_usb_modem_recovery);
446
447         INIT_WORK(&modem->cpu_boost_work, cpu_freq_boost);
448         INIT_DELAYED_WORK(&modem->cpu_unboost_work, cpu_freq_unboost);
449
450         pm_qos_add_request(&modem->cpu_boost_req, PM_QOS_CPU_FREQ_MIN,
451                            PM_QOS_DEFAULT_VALUE);
452
453         /* request remote wakeup irq from platform data */
454         ret = mdm_request_wakeable_irq(modem,
455                                        tegra_usb_modem_wake_thread,
456                                        pdata->wake_gpio,
457                                        pdata->wake_irq_flags,
458                                        "mdm_wake", &modem->wake_irq);
459         if (ret) {
460                 dev_err(&pdev->dev, "request wake irq error\n");
461                 goto error;
462         }
463
464         /* request boot irq from platform data */
465         ret = mdm_request_wakeable_irq(modem,
466                                        tegra_usb_modem_boot_thread,
467                                        pdata->boot_gpio,
468                                        pdata->boot_irq_flags,
469                                        "mdm_boot", &modem->boot_irq);
470         if (ret) {
471                 dev_err(&pdev->dev, "request boot irq error\n");
472                 goto error;
473         }
474
475         modem->pm_notifier.notifier_call = mdm_pm_notifier;
476         modem->usb_notifier.notifier_call = mdm_usb_notifier;
477
478         usb_register_notify(&modem->usb_notifier);
479         register_pm_notifier(&modem->pm_notifier);
480
481         return ret;
482 error:
483         if (modem->sysfs_file_created)
484                 device_remove_file(&pdev->dev, &dev_attr_load_host);
485
486         if (modem->wake_irq) {
487                 disable_irq_wake(modem->wake_irq);
488                 free_irq(modem->wake_irq, modem);
489         }
490
491         if (modem->boot_irq) {
492                 disable_irq_wake(modem->boot_irq);
493                 free_irq(modem->boot_irq, modem);
494         }
495
496         return ret;
497 }
498
499 static int tegra_usb_modem_probe(struct platform_device *pdev)
500 {
501         struct tegra_usb_modem_power_platform_data *pdata =
502             pdev->dev.platform_data;
503         struct tegra_usb_modem *modem;
504         int ret = 0;
505
506         if (!pdata) {
507                 dev_dbg(&pdev->dev, "platform_data not available\n");
508                 return -EINVAL;
509         }
510
511         modem = kzalloc(sizeof(struct tegra_usb_modem), GFP_KERNEL);
512         if (!modem) {
513                 dev_dbg(&pdev->dev, "failed to allocate memory\n");
514                 return -ENOMEM;
515         }
516
517         ret = mdm_init(modem, pdev);
518         if (ret) {
519                 kfree(modem);
520                 return ret;
521         }
522
523         dev_set_drvdata(&pdev->dev, modem);
524
525         return ret;
526 }
527
528 static int __exit tegra_usb_modem_remove(struct platform_device *pdev)
529 {
530         struct tegra_usb_modem *modem = platform_get_drvdata(pdev);
531
532         unregister_pm_notifier(&modem->pm_notifier);
533         usb_unregister_notify(&modem->usb_notifier);
534
535         if (modem->wake_irq) {
536                 disable_irq_wake(modem->wake_irq);
537                 free_irq(modem->wake_irq, modem);
538         }
539
540         if (modem->boot_irq) {
541                 disable_irq_wake(modem->boot_irq);
542                 free_irq(modem->boot_irq, modem);
543         }
544
545         if (modem->sysfs_file_created)
546                 device_remove_file(&pdev->dev, &dev_attr_load_host);
547
548         cancel_work_sync(&modem->cpu_boost_work);
549         cancel_delayed_work_sync(&modem->cpu_unboost_work);
550         destroy_workqueue(modem->wq);
551
552         pm_qos_remove_request(&modem->cpu_boost_req);
553
554         kfree(modem);
555         return 0;
556 }
557
558 #ifdef CONFIG_PM
559 static int tegra_usb_modem_suspend(struct platform_device *pdev,
560                                    pm_message_t state)
561 {
562         struct tegra_usb_modem *modem = platform_get_drvdata(pdev);
563
564         /* send L3 hint to modem */
565         if (modem->ops && modem->ops->suspend)
566                 modem->ops->suspend();
567         return 0;
568 }
569
570 static int tegra_usb_modem_resume(struct platform_device *pdev)
571 {
572         struct tegra_usb_modem *modem = platform_get_drvdata(pdev);
573
574         /* send L3->L0 hint to modem */
575         if (modem->ops && modem->ops->resume)
576                 modem->ops->resume();
577         return 0;
578 }
579 #endif
580
581 static struct platform_driver tegra_usb_modem_power_driver = {
582         .driver = {
583                    .name = "tegra_usb_modem_power",
584                    .owner = THIS_MODULE,
585                    },
586         .probe = tegra_usb_modem_probe,
587         .remove = __exit_p(tegra_usb_modem_remove),
588 #ifdef CONFIG_PM
589         .suspend = tegra_usb_modem_suspend,
590         .resume = tegra_usb_modem_resume,
591 #endif
592 };
593
594 static int __init tegra_usb_modem_power_init(void)
595 {
596         return platform_driver_register(&tegra_usb_modem_power_driver);
597 }
598
599 subsys_initcall(tegra_usb_modem_power_init);
600
601 static void __exit tegra_usb_modem_power_exit(void)
602 {
603         platform_driver_unregister(&tegra_usb_modem_power_driver);
604 }
605
606 module_exit(tegra_usb_modem_power_exit);
607
608 MODULE_DESCRIPTION("Tegra usb modem power management driver");
609 MODULE_LICENSE("GPL");