static int exynos_change_usb_mode(struct exynos_usb_switch *usb_switch, enum usb_cable_status mode) { struct s3c_udc *udc; unsigned long cur_mode = usb_switch->connect; int ret = 0; if (test_bit(USB_DEVICE_ATTACHED, &cur_mode) || test_bit(USB_HOST_ATTACHED, &cur_mode)) { if (mode == USB_DEVICE_ATTACHED || mode == USB_HOST_ATTACHED) { printk(KERN_DEBUG "Skip request %d, current %lu\n", mode, cur_mode); return -EPERM; } } if (!test_bit(USB_DEVICE_ATTACHED, &cur_mode) && mode == USB_DEVICE_DETACHED) { printk(KERN_DEBUG "Skip request %d, current %lu\n", mode, cur_mode); return -EPERM; } else if (!test_bit(USB_HOST_ATTACHED, &cur_mode) && mode == USB_HOST_DETACHED) { printk(KERN_DEBUG "Skip request %d, current %lu\n", mode, cur_mode); return -EPERM; } switch (mode) { case USB_DEVICE_DETACHED: if (test_bit(USB_HOST_ATTACHED, &cur_mode)) { printk(KERN_ERR "Abnormal request %d, current %lu\n", mode, cur_mode); return -EPERM; } udc = dev_get_drvdata(usb_switch->s3c_udc_dev); if (udc && udc->gadget.ops && udc->gadget.ops->vbus_session) udc->gadget.ops->vbus_session(&udc->gadget, 0); clear_bit(USB_DEVICE_ATTACHED, &usb_switch->connect); break; case USB_DEVICE_ATTACHED: udc = dev_get_drvdata(usb_switch->s3c_udc_dev); if (udc && udc->gadget.ops && udc->gadget.ops->vbus_session) udc->gadget.ops->vbus_session(&udc->gadget, 1); set_bit(USB_DEVICE_ATTACHED, &usb_switch->connect); break; case USB_HOST_DETACHED: if (test_bit(USB_DEVICE_ATTACHED, &cur_mode)) { printk(KERN_ERR "Abnormal request %d, current %lu\n", mode, cur_mode); return -EPERM; } if (usb_switch->ohci_dev) pm_runtime_allow(usb_switch->ohci_dev); if (usb_switch->ehci_dev) pm_runtime_allow(usb_switch->ehci_dev); if (usb_switch->gpio_host_vbus) set_host_vbus(usb_switch, 0); wake_unlock(&usb_switch->wake_lock); clear_bit(USB_HOST_ATTACHED, &usb_switch->connect); break; case USB_HOST_ATTACHED: wake_lock(&usb_switch->wake_lock); if (usb_switch->gpio_host_vbus) set_host_vbus(usb_switch, 1); if (usb_switch->ehci_dev) pm_runtime_forbid(usb_switch->ehci_dev); if (usb_switch->ohci_dev) pm_runtime_forbid(usb_switch->ohci_dev); set_bit(USB_HOST_ATTACHED, &usb_switch->connect); break; default: printk(KERN_ERR "Does not changed\n"); } printk(KERN_ERR "usb cable = %d\n", mode); return ret; }
static int exynos_change_usb_mode(struct exynos_usb_switch *usb_switch, enum usb_cable_status mode) { struct s3c_udc *udc; struct exynos_ss_udc *ss_udc; unsigned long cur_mode = usb_switch->connect; int ret = 0; if (test_bit(USB_DEVICE_ATTACHED, &cur_mode) || test_bit(USB_HOST_ATTACHED, &cur_mode)) { if (mode == USB_DEVICE_ATTACHED || mode == USB_HOST_ATTACHED) { printk(KERN_DEBUG "Skip request %d, current %lu\n", mode, cur_mode); return -EPERM; } } else if (test_bit(USB_DRD_DEVICE_ATTACHED, &cur_mode) || test_bit(USB_DRD_HOST_ATTACHED, &cur_mode)) { if (mode == USB_DRD_DEVICE_ATTACHED || mode == USB_DRD_HOST_ATTACHED) { printk(KERN_DEBUG "Skip request %d, current %lu\n", mode, cur_mode); return -EPERM; } } if (!test_bit(USB_DEVICE_ATTACHED, &cur_mode) && mode == USB_DEVICE_DETACHED) { printk(KERN_DEBUG "Skip request %d, current %lu\n", mode, cur_mode); return -EPERM; } else if (!test_bit(USB_HOST_ATTACHED, &cur_mode) && mode == USB_HOST_DETACHED) { printk(KERN_DEBUG "Skip request %d, current %lu\n", mode, cur_mode); return -EPERM; } else if (!test_bit(USB_DRD_DEVICE_ATTACHED, &cur_mode) && mode == USB_DRD_DEVICE_DETACHED) { printk(KERN_DEBUG "Skip request %d, current %lu\n", mode, cur_mode); return -EPERM; } else if (!test_bit(USB_DRD_HOST_ATTACHED, &cur_mode) && mode == USB_DRD_HOST_DETACHED) { printk(KERN_DEBUG "Skip request %d, current %lu\n", mode, cur_mode); return -EPERM; } switch (mode) { case USB_DEVICE_DETACHED: if (test_bit(USB_HOST_ATTACHED, &cur_mode)) { printk(KERN_ERR "Abnormal request %d, current %lu\n", mode, cur_mode); return -EPERM; } udc = dev_get_drvdata(usb_switch->s3c_udc_dev); if (udc && udc->gadget.ops && udc->gadget.ops->vbus_session) udc->gadget.ops->vbus_session(&udc->gadget, 0); clear_bit(USB_DEVICE_ATTACHED, &usb_switch->connect); break; case USB_DEVICE_ATTACHED: udc = dev_get_drvdata(usb_switch->s3c_udc_dev); if (udc && udc->gadget.ops && udc->gadget.ops->vbus_session) udc->gadget.ops->vbus_session(&udc->gadget, 1); set_bit(USB_DEVICE_ATTACHED, &usb_switch->connect); break; case USB_HOST_DETACHED: if (test_bit(USB_DEVICE_ATTACHED, &cur_mode)) { printk(KERN_ERR "Abnormal request %d, current %lu\n", mode, cur_mode); return -EPERM; } if (usb_switch->ohci_dev) pm_runtime_put(usb_switch->ohci_dev); if (usb_switch->ehci_dev) pm_runtime_put(usb_switch->ehci_dev); if (usb_switch->gpio_host_vbus) set_host_vbus(usb_switch, 0); #if defined(CONFIG_BATTERY_SAMSUNG) exynos_usb_cable_disconnect(); #endif clear_bit(USB_HOST_ATTACHED, &usb_switch->connect); break; case USB_HOST_ATTACHED: #if defined(CONFIG_BATTERY_SAMSUNG) exynos_usb_cable_connect(); #endif if (usb_switch->gpio_host_vbus) set_host_vbus(usb_switch, 1); if (usb_switch->ehci_dev) pm_runtime_get_sync(usb_switch->ehci_dev); if (usb_switch->ohci_dev) pm_runtime_get_sync(usb_switch->ohci_dev); set_bit(USB_HOST_ATTACHED, &usb_switch->connect); break; case USB_DRD_DEVICE_DETACHED: if (test_bit(USB_DRD_HOST_ATTACHED, &cur_mode)) { printk(KERN_ERR "Abnormal request %d, current %lu\n", mode, cur_mode); return -EPERM; } ss_udc = dev_get_drvdata(usb_switch->exynos_udc_dev); if (ss_udc && ss_udc->gadget.ops && ss_udc->gadget.ops->vbus_session) ss_udc->gadget.ops->vbus_session(&ss_udc->gadget, 0); clear_bit(USB_DRD_DEVICE_ATTACHED, &usb_switch->connect); break; case USB_DRD_DEVICE_ATTACHED: ss_udc = dev_get_drvdata(usb_switch->exynos_udc_dev); if (ss_udc && ss_udc->gadget.ops && ss_udc->gadget.ops->vbus_session) ss_udc->gadget.ops->vbus_session(&ss_udc->gadget, 1); set_bit(USB_DRD_DEVICE_ATTACHED, &usb_switch->connect); break; case USB_DRD_HOST_DETACHED: if (test_bit(USB_DRD_DEVICE_ATTACHED, &cur_mode)) { printk(KERN_ERR "Abnormal request %d, current %lu\n", mode, cur_mode); return -EPERM; } if (usb_switch->xhci_dev) pm_runtime_put_sync(usb_switch->xhci_dev); #if defined(CONFIG_BATTERY_SAMSUNG) exynos_usb_cable_disconnect(); #endif clear_bit(USB_DRD_HOST_ATTACHED, &usb_switch->connect); break; case USB_DRD_HOST_ATTACHED: #if defined(CONFIG_BATTERY_SAMSUNG) exynos_usb_cable_connect(); #endif if (usb_switch->xhci_dev) pm_runtime_get_sync(usb_switch->xhci_dev); set_bit(USB_DRD_HOST_ATTACHED, &usb_switch->connect); break; default: printk(KERN_ERR "Does not changed\n"); } printk(KERN_INFO "usb cable = %d\n", mode); return ret; }
static int exynos_change_usb_mode(struct exynos_usb_switch *usb_switch, enum usb_cable_status mode) { struct usb_gadget *gadget; unsigned long cur_mode = usb_switch->connect; int ret = 0; if (test_bit(USB_DEVICE_ATTACHED, &cur_mode) || test_bit(USB_HOST_ATTACHED, &cur_mode)) { if (mode == USB_DEVICE_ATTACHED || mode == USB_HOST_ATTACHED) { printk(KERN_DEBUG "Skip request %d, current %lu\n", mode, cur_mode); return -EPERM; } } if (!test_bit(USB_DEVICE_ATTACHED, &cur_mode) && mode == USB_DEVICE_DETACHED) { printk(KERN_DEBUG "Skip request %d, current %lu\n", mode, cur_mode); return -EPERM; } else if (!test_bit(USB_HOST_ATTACHED, &cur_mode) && mode == USB_HOST_DETACHED) { printk(KERN_DEBUG "Skip request %d, current %lu\n", mode, cur_mode); return -EPERM; } /* * FIXME: Currently we get gadget every time usb mode is going * to change. This prevents from problems related to UDC module * removing and wrong probe order. S3C UDC driver should provide * corresponding helper function. If S3C UDC is not available weak * analog is used instead. * * Correct solution would be to implement binding similar to OTG's * set_host() and set_peripheral(). */ gadget = s3c_udc_get_gadget(usb_switch->s3c_udc_dev); switch (mode) { case USB_DEVICE_DETACHED: if (test_bit(USB_HOST_ATTACHED, &cur_mode)) { printk(KERN_ERR "Abnormal request %d, current %lu\n", mode, cur_mode); return -EPERM; } if (gadget && gadget->ops) usb_gadget_vbus_disconnect(gadget); clear_bit(USB_DEVICE_ATTACHED, &usb_switch->connect); break; case USB_DEVICE_ATTACHED: if (gadget && gadget->ops) usb_gadget_vbus_connect(gadget); set_bit(USB_DEVICE_ATTACHED, &usb_switch->connect); break; case USB_HOST_DETACHED: if (test_bit(USB_DEVICE_ATTACHED, &cur_mode)) { printk(KERN_ERR "Abnormal request %d, current %lu\n", mode, cur_mode); return -EPERM; } if (usb_switch->ohci_dev) pm_runtime_allow(usb_switch->ohci_dev); if (usb_switch->ehci_dev) pm_runtime_allow(usb_switch->ehci_dev); if (usb_switch->gpio_host_vbus) set_host_vbus(usb_switch, 0); wake_unlock(&usb_switch->wake_lock); clear_bit(USB_HOST_ATTACHED, &usb_switch->connect); break; case USB_HOST_ATTACHED: wake_lock(&usb_switch->wake_lock); if (usb_switch->gpio_host_vbus) set_host_vbus(usb_switch, 1); if (usb_switch->ehci_dev) pm_runtime_forbid(usb_switch->ehci_dev); if (usb_switch->ohci_dev) pm_runtime_forbid(usb_switch->ohci_dev); set_bit(USB_HOST_ATTACHED, &usb_switch->connect); break; default: printk(KERN_ERR "Does not changed\n"); } printk(KERN_ERR "usb cable = %d\n", mode); return ret; }