diff options
Diffstat (limited to 'drivers/misc/modem_if_na/modem_link_pm_usb.c')
-rw-r--r-- | drivers/misc/modem_if_na/modem_link_pm_usb.c | 370 |
1 files changed, 0 insertions, 370 deletions
diff --git a/drivers/misc/modem_if_na/modem_link_pm_usb.c b/drivers/misc/modem_if_na/modem_link_pm_usb.c deleted file mode 100644 index 4907de7..0000000 --- a/drivers/misc/modem_if_na/modem_link_pm_usb.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -/* - * TODO (last updated Apr 13, 2012): - * - move usb hub feature to board file - * currently, some code was commented out by CONFIG_USBHUB_USB3503 - * - Both usb_ld and link_pm_data have same gpio member. - * we have to remove it from one of them and - * make helper function for gpio handling. - */ - -#define DEBUG - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/sched.h> -#include <linux/irq.h> -#include <linux/poll.h> -#include <linux/gpio.h> -#include <linux/if_arp.h> -#include <linux/platform_device.h> -#include <linux/suspend.h> - -#include "modem_link_pm_usb.h" - -bool link_pm_is_connected(struct usb_link_device *usb_ld) -{ -#ifdef CONFIG_USBHUB_USB3503 - if (has_hub(usb_ld)) { - if (usb_ld->link_pm_data->hub_status == HUB_STATE_RESUMMING - || usb_ld->link_pm_data->hub_init_lock) - return false; - - if (usb_ld->link_pm_data->hub_status == HUB_STATE_OFF) { - schedule_delayed_work( - &usb_ld->link_pm_data->link_pm_hub, 0); - return false; - } - } -#endif - if (!usb_ld->if_usb_connected) { - mif_err("if not connected\n"); - return false; - } - - return true; -} - -#ifdef CONFIG_USBHUB_USB3503 -static void link_pm_hub_work(struct work_struct *work) -{ - int err; - struct link_pm_data *pm_data = - container_of(work, struct link_pm_data, link_pm_hub.work); - - if (pm_data->hub_status == HUB_STATE_ACTIVE) - return; - - if (!pm_data->port_enable) { - mif_err("mif: hub power func not assinged\n"); - return; - } - wake_lock(&pm_data->hub_lock); - - /* If kernel if suspend, wait the ehci resume */ - if (pm_data->dpm_suspending) { - mif_info("dpm_suspending\n"); - schedule_delayed_work(&pm_data->link_pm_hub, - msecs_to_jiffies(500)); - goto exit; - } - - switch (pm_data->hub_status) { - case HUB_STATE_OFF: - pm_data->hub_status = HUB_STATE_RESUMMING; - mif_trace("hub off->on\n"); - - /* skip 1st time before first probe */ - if (pm_data->root_hub) - pm_runtime_get_sync(pm_data->root_hub); - err = pm_data->port_enable(2, 1); - if (err < 0) { - mif_err("hub on fail err=%d\n", err); - err = pm_data->port_enable(2, 0); - if (err < 0) - mif_err("hub off fail err=%d\n", err); - pm_data->hub_status = HUB_STATE_OFF; - if (pm_data->root_hub) - pm_runtime_put_sync(pm_data->root_hub); - goto exit; - } - /* resume root hub */ - schedule_delayed_work(&pm_data->link_pm_hub, - msecs_to_jiffies(100)); - break; - case HUB_STATE_RESUMMING: - if (pm_data->hub_on_retry_cnt++ > 50) { - pm_data->hub_on_retry_cnt = 0; - pm_data->hub_status = HUB_STATE_OFF; - if (pm_data->root_hub) - pm_runtime_put_sync(pm_data->root_hub); - } - mif_trace("hub resumming\n"); - schedule_delayed_work(&pm_data->link_pm_hub, - msecs_to_jiffies(200)); - break; - case HUB_STATE_PREACTIVE: - mif_trace("hub active\n"); - pm_data->hub_on_retry_cnt = 0; - wake_unlock(&pm_data->hub_lock); - pm_data->hub_status = HUB_STATE_ACTIVE; - complete(&pm_data->hub_active); - if (pm_data->root_hub) - pm_runtime_put_sync(pm_data->root_hub); - break; - } -exit: - return; -} -#endif - -static int link_pm_hub_standby(struct link_pm_data *pm_data) -{ - int err = 0; - -#ifdef CONFIG_USBHUB_USB3503 - mif_info("wait hub standby\n"); - - if (!pm_data->port_enable) { - mif_err("hub power func not assinged\n"); - return -ENODEV; - } - - err = pm_data->port_enable(2, 0); - if (err < 0) - mif_err("hub off fail err=%d\n", err); - - pm_data->hub_status = HUB_STATE_OFF; -#endif - return err; -} - -bool link_pm_set_active(struct usb_link_device *usb_ld) -{ - int ret; - struct link_pm_data *pm_data = usb_ld->link_pm_data; - - if (has_hub(usb_ld)) { - if (pm_data->hub_status != HUB_STATE_ACTIVE) { - INIT_COMPLETION(pm_data->hub_active); - SET_SLAVE_WAKEUP(usb_ld->pdata, 1); - ret = wait_for_completion_timeout(&pm_data->hub_active, - msecs_to_jiffies(2000)); - if (!ret) { /*timeout*/ - mif_err("hub on timeout - retry\n"); - SET_SLAVE_WAKEUP(usb_ld->pdata, 0); - queue_delayed_work(usb_ld->ld.tx_wq, - &usb_ld->ld.tx_delayed_work, 0); - return false; - } - } - } else { - /* TODO do something */ - } - return true; -} - -static long link_pm_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - int value, err = 0; - struct task_struct *task = get_current(); - struct link_pm_data *pm_data = file->private_data; - struct usb_link_device *usb_ld = pm_data->usb_ld; - char taskname[TASK_COMM_LEN]; - - mif_info("cmd: 0x%08x\n", cmd); - - switch (cmd) { - case IOCTL_LINK_CONTROL_ACTIVE: - if (copy_from_user(&value, (const void __user *)arg, - sizeof(int))) - return -EFAULT; - gpio_set_value(pm_data->gpio_link_active, value); - break; - case IOCTL_LINK_GET_HOSTWAKE: - return !gpio_get_value(pm_data->gpio_link_hostwake); - case IOCTL_LINK_CONNECTED: - return pm_data->usb_ld->if_usb_connected; - case IOCTL_LINK_PORT_ON: /* hub only */ - /* ignore cp host wakeup irq, set the hub_init_lock when AP try - CP off and release hub_init_lock when CP boot done */ - pm_data->hub_init_lock = 0; - if (pm_data->root_hub) { - pm_runtime_resume(pm_data->root_hub); - pm_runtime_forbid(pm_data->root_hub->parent); - } - if (pm_data->port_enable) { - err = pm_data->port_enable(2, 1); - if (err < 0) { - mif_err("hub on fail err=%d\n", err); - goto exit; - } - pm_data->hub_status = HUB_STATE_RESUMMING; - } - break; - case IOCTL_LINK_PORT_OFF: /* hub only */ - err = link_pm_hub_standby(pm_data); - if (err < 0) { - mif_err("usb3503 active fail\n"); - goto exit; - } - pm_data->hub_init_lock = 1; - pm_data->hub_handshake_done = 0; - - break; - case IOCTL_LINK_BLOCK_AUTOSUSPEND: /* block autosuspend forever */ - mif_info("blocked autosuspend by `%s(%d)'\n", - get_task_comm(taskname, task), task->pid); - pm_data->block_autosuspend = true; - if (usb_ld->usbdev) - pm_runtime_forbid(&usb_ld->usbdev->dev); - break; - case IOCTL_LINK_ENABLE_AUTOSUSPEND: /* Enable autosuspend */ - mif_info("autosuspend enabled by `%s(%d)'\n", - get_task_comm(taskname, task), task->pid); - pm_data->block_autosuspend = false; - if (usb_ld->usbdev) - pm_runtime_allow(&usb_ld->usbdev->dev); - else { - mif_err("Enable autosuspend failed\n"); - err = -ENODEV; - } - break; - default: - break; - } -exit: - return err; -} - -static int link_pm_open(struct inode *inode, struct file *file) -{ - struct link_pm_data *pm_data = - (struct link_pm_data *)file->private_data; - file->private_data = (void *)pm_data; - return 0; -} - -static int link_pm_release(struct inode *inode, struct file *file) -{ - file->private_data = NULL; - return 0; -} - -static const struct file_operations link_pm_fops = { - .owner = THIS_MODULE, - .open = link_pm_open, - .release = link_pm_release, - .unlocked_ioctl = link_pm_ioctl, -}; - -static int link_pm_notifier_event(struct notifier_block *this, - unsigned long event, void *ptr) -{ - struct link_pm_data *pm_data = - container_of(this, struct link_pm_data, pm_notifier); - - switch (event) { - case PM_SUSPEND_PREPARE: - pm_data->dpm_suspending = true; - link_pm_hub_standby(pm_data); - return NOTIFY_OK; - case PM_POST_SUSPEND: - pm_data->dpm_suspending = false; - return NOTIFY_OK; - } - return NOTIFY_DONE; -} - -int link_pm_init(struct usb_link_device *usb_ld, void *data) -{ - int err; - int irq; - struct platform_device *pdev = (struct platform_device *)data; - struct modem_data *pdata = - (struct modem_data *)pdev->dev.platform_data; - struct modemlink_pm_data *pm_pdata = pdata->link_pm_data; - struct link_pm_data *pm_data = - kzalloc(sizeof(struct link_pm_data), GFP_KERNEL); - if (!pm_data) { - mif_err("link_pm_data is NULL\n"); - return -ENOMEM; - } - /* get link pm data from modemcontrol's platform data */ - pm_data->gpio_link_active = pm_pdata->gpio_link_active; - pm_data->gpio_link_hostwake = pm_pdata->gpio_link_hostwake; - pm_data->gpio_link_slavewake = pm_pdata->gpio_link_slavewake; - pm_data->link_reconnect = pm_pdata->link_reconnect; - pm_data->port_enable = pm_pdata->port_enable; - pm_data->cpufreq_lock = pm_pdata->cpufreq_lock; - pm_data->cpufreq_unlock = pm_pdata->cpufreq_unlock; - pm_data->autosuspend_delay_ms = pm_pdata->autosuspend_delay_ms; - pm_data->block_autosuspend = false; - - pm_data->usb_ld = usb_ld; - pm_data->link_pm_active = false; - usb_ld->link_pm_data = pm_data; - - pm_data->miscdev.minor = MISC_DYNAMIC_MINOR; - pm_data->miscdev.name = "link_pm"; - pm_data->miscdev.fops = &link_pm_fops; - - err = misc_register(&pm_data->miscdev); - if (err < 0) { - mif_err("fail to register pm device(%d)\n", err); - goto err_misc_register; - } - - pm_data->hub_init_lock = 1; - irq = gpio_to_irq(usb_ld->pdata->gpio_host_wakeup); - err = request_threaded_irq(irq, NULL, usb_resume_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "modem_usb_wake", usb_ld); - if (err) { - mif_err("Failed to allocate an interrupt(%d)\n", irq); - goto err_request_irq; - } - enable_irq_wake(irq); - - pm_data->has_usbhub = pm_pdata->has_usbhub; - -#ifdef CONFIG_USBHUB_USB3503 - if (has_hub(usb_ld)) { - init_completion(&pm_data->hub_active); - pm_data->hub_status = HUB_STATE_OFF; - pm_pdata->p_hub_status = &pm_data->hub_status; - pm_data->hub_handshake_done = 0; - pm_data->root_hub = NULL; - wake_lock_init(&pm_data->hub_lock, WAKE_LOCK_SUSPEND, - "modem_hub_enum_lock"); - INIT_DELAYED_WORK(&pm_data->link_pm_hub, link_pm_hub_work); - } -#endif - - wake_lock_init(&pm_data->boot_wake, WAKE_LOCK_SUSPEND, "boot_usb"); - - pm_data->pm_notifier.notifier_call = link_pm_notifier_event; - register_pm_notifier(&pm_data->pm_notifier); - - return 0; - -err_request_irq: - misc_deregister(&pm_data->miscdev); -err_misc_register: - kfree(pm_data); - return err; -} |