diff options
Diffstat (limited to 'drivers/usb')
178 files changed, 3404 insertions, 5989 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 75823a1..0b0afc8 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -76,6 +76,7 @@ config USB_ARCH_HAS_EHCI default y if MICROBLAZE default y if SPARC_LEON default y if ARCH_MMP + default y if MACH_LOONGSON1 default PCI # some non-PCI HCDs implement xHCI diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 9543b19..6dcc3a3 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -39,6 +39,7 @@ #include <linux/serial.h> #include <linux/tty_driver.h> #include <linux/tty_flip.h> +#include <linux/serial.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/uaccess.h> @@ -773,10 +774,37 @@ static int acm_tty_tiocmset(struct tty_struct *tty, return acm_set_control(acm, acm->ctrlout = newctrl); } +static int get_serial_info(struct acm *acm, struct serial_struct __user *info) +{ + struct serial_struct tmp; + + if (!info) + return -EINVAL; + + memset(&tmp, 0, sizeof(tmp)); + tmp.flags = ASYNC_LOW_LATENCY; + tmp.xmit_fifo_size = acm->writesize; + tmp.baud_base = le32_to_cpu(acm->line.dwDTERate); + + if (copy_to_user(info, &tmp, sizeof(tmp))) + return -EFAULT; + else + return 0; +} + static int acm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { - return -ENOIOCTLCMD; + struct acm *acm = tty->driver_data; + int rv = -ENOIOCTLCMD; + + switch (cmd) { + case TIOCGSERIAL: /* gets serial port data */ + rv = get_serial_info(acm, (struct serial_struct __user *) arg); + break; + } + + return rv; } static const __u32 acm_tty_speed[] = { diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 1c50baf..6037b50 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -31,6 +31,8 @@ #define DRIVER_AUTHOR "Oliver Neukum" #define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management" +#define HUAWEI_VENDOR_ID 0x12D1 + static const struct usb_device_id wdm_ids[] = { { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | @@ -38,6 +40,20 @@ static const struct usb_device_id wdm_ids[] = { .bInterfaceClass = USB_CLASS_COMM, .bInterfaceSubClass = USB_CDC_SUBCLASS_DMM }, + { + /* + * Huawei E392, E398 and possibly other Qualcomm based modems + * embed the Qualcomm QMI protocol inside CDC on CDC ECM like + * control interfaces. Userspace access to this is required + * to configure the accompanying data interface + */ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | + USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = HUAWEI_VENDOR_ID, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 9, /* NOTE: CDC ECM control interface! */ + }, { } }; @@ -54,9 +70,12 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); #define WDM_POLL_RUNNING 6 #define WDM_RESPONDING 7 #define WDM_SUSPENDING 8 +#define WDM_RESETTING 9 #define WDM_MAX 16 +/* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */ +#define WDM_DEFAULT_BUFSIZE 256 static DEFINE_MUTEX(wdm_mutex); @@ -80,7 +99,6 @@ struct wdm_device { u16 bufsize; u16 wMaxCommand; u16 wMaxPacketSize; - u16 bMaxPacketSize0; __le16 inum; int reslength; int length; @@ -88,7 +106,8 @@ struct wdm_device { int count; dma_addr_t shandle; dma_addr_t ihandle; - struct mutex lock; + struct mutex wlock; + struct mutex rlock; wait_queue_head_t wait; struct work_struct rxwork; int werr; @@ -159,11 +178,9 @@ static void wdm_int_callback(struct urb *urb) int rv = 0; int status = urb->status; struct wdm_device *desc; - struct usb_ctrlrequest *req; struct usb_cdc_notification *dr; desc = urb->context; - req = desc->irq; dr = (struct usb_cdc_notification *)desc->sbuf; if (status) { @@ -210,24 +227,6 @@ static void wdm_int_callback(struct urb *urb) goto exit; } - req->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE); - req->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE; - req->wValue = 0; - req->wIndex = desc->inum; - req->wLength = cpu_to_le16(desc->wMaxCommand); - - usb_fill_control_urb( - desc->response, - interface_to_usbdev(desc->intf), - /* using common endpoint 0 */ - usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0), - (unsigned char *)req, - desc->inbuf, - desc->wMaxCommand, - wdm_in_callback, - desc - ); - desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; spin_lock(&desc->iuspin); clear_bit(WDM_READ, &desc->flags); set_bit(WDM_RESPONDING, &desc->flags); @@ -276,14 +275,8 @@ static void free_urbs(struct wdm_device *desc) static void cleanup(struct wdm_device *desc) { - usb_free_coherent(interface_to_usbdev(desc->intf), - desc->wMaxPacketSize, - desc->sbuf, - desc->validity->transfer_dma); - usb_free_coherent(interface_to_usbdev(desc->intf), - desc->bMaxPacketSize0, - desc->inbuf, - desc->response->transfer_dma); + kfree(desc->sbuf); + kfree(desc->inbuf); kfree(desc->orq); kfree(desc->irq); kfree(desc->ubuf); @@ -323,7 +316,7 @@ static ssize_t wdm_write } /* concurrent writes and disconnect */ - r = mutex_lock_interruptible(&desc->lock); + r = mutex_lock_interruptible(&desc->wlock); rv = -ERESTARTSYS; if (r) { kfree(buf); @@ -348,6 +341,10 @@ static ssize_t wdm_write else if (test_bit(WDM_IN_USE, &desc->flags)) r = -EAGAIN; + + if (test_bit(WDM_RESETTING, &desc->flags)) + r = -EIO; + if (r < 0) { kfree(buf); goto out; @@ -386,7 +383,7 @@ static ssize_t wdm_write out: usb_autopm_put_interface(desc->intf); outnp: - mutex_unlock(&desc->lock); + mutex_unlock(&desc->wlock); outnl: return rv < 0 ? rv : count; } @@ -394,16 +391,17 @@ outnl: static ssize_t wdm_read (struct file *file, char __user *buffer, size_t count, loff_t *ppos) { - int rv, cntr = 0; + int rv, cntr; int i = 0; struct wdm_device *desc = file->private_data; - rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */ + rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */ if (rv < 0) return -ERESTARTSYS; - if (desc->length == 0) { + cntr = ACCESS_ONCE(desc->length); + if (cntr == 0) { desc->read = 0; retry: if (test_bit(WDM_DISCONNECTING, &desc->flags)) { @@ -427,6 +425,10 @@ retry: rv = -ENODEV; goto err; } + if (test_bit(WDM_RESETTING, &desc->flags)) { + rv = -EIO; + goto err; + } usb_mark_last_busy(interface_to_usbdev(desc->intf)); if (rv < 0) { rv = -ERESTARTSYS; @@ -453,17 +455,20 @@ retry: spin_unlock_irq(&desc->iuspin); goto retry; } - clear_bit(WDM_READ, &desc->flags); + cntr = desc->length; spin_unlock_irq(&desc->iuspin); } - cntr = count > desc->length ? desc->length : count; + if (cntr > count) + cntr = count; rv = copy_to_user(buffer, desc->ubuf, cntr); if (rv > 0) { rv = -EFAULT; goto err; } + spin_lock_irq(&desc->iuspin); + for (i = 0; i < desc->length - cntr; i++) desc->ubuf[i] = desc->ubuf[i + cntr]; @@ -471,10 +476,13 @@ retry: /* in case we had outstanding data */ if (!desc->length) clear_bit(WDM_READ, &desc->flags); + + spin_unlock_irq(&desc->iuspin); + rv = cntr; err: - mutex_unlock(&desc->lock); + mutex_unlock(&desc->rlock); return rv; } @@ -540,7 +548,8 @@ static int wdm_open(struct inode *inode, struct file *file) } intf->needs_remote_wakeup = 1; - mutex_lock(&desc->lock); + /* using write lock to protect desc->count */ + mutex_lock(&desc->wlock); if (!desc->count++) { desc->werr = 0; desc->rerr = 0; @@ -553,7 +562,7 @@ static int wdm_open(struct inode *inode, struct file *file) } else { rv = 0; } - mutex_unlock(&desc->lock); + mutex_unlock(&desc->wlock); usb_autopm_put_interface(desc->intf); out: mutex_unlock(&wdm_mutex); @@ -565,9 +574,11 @@ static int wdm_release(struct inode *inode, struct file *file) struct wdm_device *desc = file->private_data; mutex_lock(&wdm_mutex); - mutex_lock(&desc->lock); + + /* using write lock to protect desc->count */ + mutex_lock(&desc->wlock); desc->count--; - mutex_unlock(&desc->lock); + mutex_unlock(&desc->wlock); if (!desc->count) { dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); @@ -623,14 +634,13 @@ static void wdm_rxwork(struct work_struct *work) static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) { int rv = -EINVAL; - struct usb_device *udev = interface_to_usbdev(intf); struct wdm_device *desc; struct usb_host_interface *iface; struct usb_endpoint_descriptor *ep; struct usb_cdc_dmm_desc *dmhd; u8 *buffer = intf->altsetting->extra; int buflen = intf->altsetting->extralen; - u16 maxcom = 0; + u16 maxcom = WDM_DEFAULT_BUFSIZE; if (!buffer) goto out; @@ -665,7 +675,8 @@ next_desc: desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); if (!desc) goto out; - mutex_init(&desc->lock); + mutex_init(&desc->rlock); + mutex_init(&desc->wlock); spin_lock_init(&desc->iuspin); init_waitqueue_head(&desc->wait); desc->wMaxCommand = maxcom; @@ -683,7 +694,6 @@ next_desc: goto err; desc->wMaxPacketSize = usb_endpoint_maxp(ep); - desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0; desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); if (!desc->orq) @@ -708,19 +718,13 @@ next_desc: if (!desc->ubuf) goto err; - desc->sbuf = usb_alloc_coherent(interface_to_usbdev(intf), - desc->wMaxPacketSize, - GFP_KERNEL, - &desc->validity->transfer_dma); + desc->sbuf = kmalloc(desc->wMaxPacketSize, GFP_KERNEL); if (!desc->sbuf) goto err; - desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf), - desc->bMaxPacketSize0, - GFP_KERNEL, - &desc->response->transfer_dma); + desc->inbuf = kmalloc(desc->wMaxCommand, GFP_KERNEL); if (!desc->inbuf) - goto err2; + goto err; usb_fill_int_urb( desc->validity, @@ -732,30 +736,39 @@ next_desc: desc, ep->bInterval ); - desc->validity->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + desc->irq->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE); + desc->irq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE; + desc->irq->wValue = 0; + desc->irq->wIndex = desc->inum; + desc->irq->wLength = cpu_to_le16(desc->wMaxCommand); + + usb_fill_control_urb( + desc->response, + interface_to_usbdev(intf), + /* using common endpoint 0 */ + usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0), + (unsigned char *)desc->irq, + desc->inbuf, + desc->wMaxCommand, + wdm_in_callback, + desc + ); usb_set_intfdata(intf, desc); rv = usb_register_dev(intf, &wdm_class); if (rv < 0) - goto err3; + goto err2; else - dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n", - intf->minor - WDM_MINOR_BASE); + dev_info(&intf->dev, "%s: USB WDM device\n", dev_name(intf->usb_dev)); out: return rv; -err3: - usb_set_intfdata(intf, NULL); - usb_free_coherent(interface_to_usbdev(desc->intf), - desc->bMaxPacketSize0, - desc->inbuf, - desc->response->transfer_dma); err2: - usb_free_coherent(interface_to_usbdev(desc->intf), - desc->wMaxPacketSize, - desc->sbuf, - desc->validity->transfer_dma); + usb_set_intfdata(intf, NULL); err: free_urbs(desc); + kfree(desc->inbuf); + kfree(desc->sbuf); kfree(desc->ubuf); kfree(desc->orq); kfree(desc->irq); @@ -779,11 +792,13 @@ static void wdm_disconnect(struct usb_interface *intf) /* to terminate pending flushes */ clear_bit(WDM_IN_USE, &desc->flags); spin_unlock_irqrestore(&desc->iuspin, flags); - mutex_lock(&desc->lock); + wake_up_all(&desc->wait); + mutex_lock(&desc->rlock); + mutex_lock(&desc->wlock); kill_urbs(desc); cancel_work_sync(&desc->rxwork); - mutex_unlock(&desc->lock); - wake_up_all(&desc->wait); + mutex_unlock(&desc->wlock); + mutex_unlock(&desc->rlock); if (!desc->count) cleanup(desc); mutex_unlock(&wdm_mutex); @@ -798,8 +813,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); /* if this is an autosuspend the caller does the locking */ - if (!PMSG_IS_AUTO(message)) - mutex_lock(&desc->lock); + if (!PMSG_IS_AUTO(message)) { + mutex_lock(&desc->rlock); + mutex_lock(&desc->wlock); + } spin_lock_irq(&desc->iuspin); if (PMSG_IS_AUTO(message) && @@ -815,8 +832,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) kill_urbs(desc); cancel_work_sync(&desc->rxwork); } - if (!PMSG_IS_AUTO(message)) - mutex_unlock(&desc->lock); + if (!PMSG_IS_AUTO(message)) { + mutex_unlock(&desc->wlock); + mutex_unlock(&desc->rlock); + } return rv; } @@ -854,9 +873,6 @@ static int wdm_pre_reset(struct usb_interface *intf) { struct wdm_device *desc = usb_get_intfdata(intf); - mutex_lock(&desc->lock); - kill_urbs(desc); - /* * we notify everybody using poll of * an exceptional situation @@ -864,9 +880,16 @@ static int wdm_pre_reset(struct usb_interface *intf) * message from the device is lost */ spin_lock_irq(&desc->iuspin); + set_bit(WDM_RESETTING, &desc->flags); /* inform read/write */ + set_bit(WDM_READ, &desc->flags); /* unblock read */ + clear_bit(WDM_IN_USE, &desc->flags); /* unblock write */ desc->rerr = -EINTR; spin_unlock_irq(&desc->iuspin); wake_up_all(&desc->wait); + mutex_lock(&desc->rlock); + mutex_lock(&desc->wlock); + kill_urbs(desc); + cancel_work_sync(&desc->rxwork); return 0; } @@ -875,8 +898,10 @@ static int wdm_post_reset(struct usb_interface *intf) struct wdm_device *desc = usb_get_intfdata(intf); int rv; + clear_bit(WDM_RESETTING, &desc->flags); rv = recover_from_urb_loss(desc); - mutex_unlock(&desc->lock); + mutex_unlock(&desc->wlock); + mutex_unlock(&desc->rlock); return 0; } diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index d40ff95..d77daf3 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -958,13 +958,8 @@ void usb_rebind_intf(struct usb_interface *intf) int rc; /* Delayed unbind of an existing driver */ - if (intf->dev.driver) { - struct usb_driver *driver = - to_usb_driver(intf->dev.driver); - - dev_dbg(&intf->dev, "forced unbind\n"); - usb_driver_release_interface(driver, intf); - } + if (intf->dev.driver) + usb_forced_unbind_intf(intf); /* Try to rebind the interface */ if (!intf->dev.power.is_prepared) { @@ -977,15 +972,13 @@ void usb_rebind_intf(struct usb_interface *intf) #ifdef CONFIG_PM -#define DO_UNBIND 0 -#define DO_REBIND 1 - -/* Unbind drivers for @udev's interfaces that don't support suspend/resume, - * or rebind interfaces that have been unbound, according to @action. +/* Unbind drivers for @udev's interfaces that don't support suspend/resume + * There is no check for reset_resume here because it can be determined + * only during resume whether reset_resume is needed. * * The caller must hold @udev's device lock. */ -static void do_unbind_rebind(struct usb_device *udev, int action) +static void unbind_no_pm_drivers_interfaces(struct usb_device *udev) { struct usb_host_config *config; int i; @@ -996,23 +989,53 @@ static void do_unbind_rebind(struct usb_device *udev, int action) if (config) { for (i = 0; i < config->desc.bNumInterfaces; ++i) { intf = config->interface[i]; - switch (action) { - case DO_UNBIND: - if (intf->dev.driver) { - drv = to_usb_driver(intf->dev.driver); - if (!drv->suspend || !drv->resume) - usb_forced_unbind_intf(intf); - } - break; - case DO_REBIND: - if (intf->needs_binding) - usb_rebind_intf(intf); - break; + + if (intf->dev.driver) { + drv = to_usb_driver(intf->dev.driver); + if (!drv->suspend || !drv->resume) + usb_forced_unbind_intf(intf); } } } } +/* Unbind drivers for @udev's interfaces that failed to support reset-resume. + * These interfaces have the needs_binding flag set by usb_resume_interface(). + * + * The caller must hold @udev's device lock. + */ +static void unbind_no_reset_resume_drivers_interfaces(struct usb_device *udev) +{ + struct usb_host_config *config; + int i; + struct usb_interface *intf; + + config = udev->actconfig; + if (config) { + for (i = 0; i < config->desc.bNumInterfaces; ++i) { + intf = config->interface[i]; + if (intf->dev.driver && intf->needs_binding) + usb_forced_unbind_intf(intf); + } + } +} + +static void do_rebind_interfaces(struct usb_device *udev) +{ + struct usb_host_config *config; + int i; + struct usb_interface *intf; + + config = udev->actconfig; + if (config) { + for (i = 0; i < config->desc.bNumInterfaces; ++i) { + intf = config->interface[i]; + if (intf->needs_binding) + usb_rebind_intf(intf); + } + } +} + static int usb_suspend_device(struct usb_device *udev, pm_message_t msg) { struct usb_device_driver *udriver; @@ -1302,35 +1325,48 @@ int usb_suspend(struct device *dev, pm_message_t msg) { struct usb_device *udev = to_usb_device(dev); - do_unbind_rebind(udev, DO_UNBIND); + unbind_no_pm_drivers_interfaces(udev); + + /* From now on we are sure all drivers support suspend/resume + * but not necessarily reset_resume() + * so we may still need to unbind and rebind upon resume + */ choose_wakeup(udev, msg); return usb_suspend_both(udev, msg); } /* The device lock is held by the PM core */ +int usb_resume_complete(struct device *dev) +{ + struct usb_device *udev = to_usb_device(dev); + + /* For PM complete calls, all we do is rebind interfaces + * whose needs_binding flag is set + */ + if (udev->state != USB_STATE_NOTATTACHED) + do_rebind_interfaces(udev); + return 0; +} + +/* The device lock is held by the PM core */ int usb_resume(struct device *dev, pm_message_t msg) { struct usb_device *udev = to_usb_device(dev); int status; - /* For PM complete calls, all we do is rebind interfaces */ - if (msg.event == PM_EVENT_ON) { - if (udev->state != USB_STATE_NOTATTACHED) - do_unbind_rebind(udev, DO_REBIND); - status = 0; - - /* For all other calls, take the device back to full power and + /* For all calls, take the device back to full power and * tell the PM core in case it was autosuspended previously. - * Unbind the interfaces that will need rebinding later. + * Unbind the interfaces that will need rebinding later, + * because they fail to support reset_resume. + * (This can't be done in usb_resume_interface() + * above because it doesn't own the right set of locks.) */ - } else { - status = usb_resume_both(udev, msg); - if (status == 0) { - pm_runtime_disable(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - do_unbind_rebind(udev, DO_REBIND); - } + status = usb_resume_both(udev, msg); + if (status == 0) { + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + unbind_no_reset_resume_drivers_interfaces(udev); } /* Avoid PM error messages for devices disconnected while suspended diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index d136b8f..622b4a4 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -187,7 +187,10 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) return -ENODEV; dev->current_state = PCI_D0; - if (!dev->irq) { + /* The xHCI driver supports MSI and MSI-X, + * so don't fail if the BIOS doesn't provide a legacy IRQ. + */ + if (!dev->irq && (driver->flags & HCD_MASK) != HCD_USB3) { dev_err(&dev->dev, "Found HC with no IRQ. Check BIOS/PCI %s setup!\n", pci_name(dev)); @@ -377,6 +380,7 @@ static int check_root_hub_suspended(struct device *dev) return 0; } +#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME) static int suspend_common(struct device *dev, bool do_wakeup) { struct pci_dev *pci_dev = to_pci_dev(dev); @@ -468,6 +472,7 @@ static int resume_common(struct device *dev, int event) } return retval; } +#endif /* SLEEP || RUNTIME */ #ifdef CONFIG_PM_SLEEP diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index eb19cba..e128232 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2447,8 +2447,10 @@ int usb_add_hcd(struct usb_hcd *hcd, && device_can_wakeup(&hcd->self.root_hub->dev)) dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); - /* enable irqs just before we start the controller */ - if (usb_hcd_is_primary_hcd(hcd)) { + /* enable irqs just before we start the controller, + * if the BIOS provides legacy PCI irqs. + */ + if (usb_hcd_is_primary_hcd(hcd) && irqnum) { retval = usb_hcd_request_irqs(hcd, irqnum, irqflags); if (retval) goto err_request_irq; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a0613d8..72c51cd 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -62,6 +62,8 @@ struct usb_hub { resumed */ unsigned long removed_bits[1]; /* ports with a "removed" device present */ + unsigned long wakeup_bits[1]; /* ports that have signaled + remote wakeup */ #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ #error event_bits[] is too short! #endif @@ -411,6 +413,29 @@ void usb_kick_khubd(struct usb_device *hdev) kick_khubd(hub); } +/* + * Let the USB core know that a USB 3.0 device has sent a Function Wake Device + * Notification, which indicates it had initiated remote wakeup. + * + * USB 3.0 hubs do not report the port link state change from U3 to U0 when the + * device initiates resume, so the USB core will not receive notice of the + * resume through the normal hub interrupt URB. + */ +void usb_wakeup_notification(struct usb_device *hdev, + unsigned int portnum) +{ + struct usb_hub *hub; + + if (!hdev) + return; + + hub = hdev_to_hub(hdev); + if (hub) { + set_bit(portnum, hub->wakeup_bits); + kick_khubd(hub); + } +} +EXPORT_SYMBOL_GPL(usb_wakeup_notification); /* completion function, fires on port status changes and various faults */ static void hub_irq(struct urb *urb) @@ -705,10 +730,26 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) if (type == HUB_INIT3) goto init3; - /* After a resume, port power should still be on. + /* The superspeed hub except for root hub has to use Hub Depth + * value as an offset into the route string to locate the bits + * it uses to determine the downstream port number. So hub driver + * should send a set hub depth request to superspeed hub after + * the superspeed hub is set configuration in initialization or + * reset procedure. + * + * After a resume, port power should still be on. * For any other type of activation, turn it on. */ if (type != HUB_RESUME) { + if (hdev->parent && hub_is_superspeed(hdev)) { + ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), + HUB_SET_DEPTH, USB_RT_HUB, + hdev->level - 1, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); + if (ret < 0) + dev_err(hub->intfdev, + "set hub depth failed\n"); + } /* Speed up system boot by using a delayed_work for the * hub's initial power-up delays. This is pretty awkward @@ -807,12 +848,6 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_ENABLE); } - if (portchange & USB_PORT_STAT_C_LINK_STATE) { - need_debounce_delay = true; - clear_port_feature(hub->hdev, port1, - USB_PORT_FEAT_C_PORT_LINK_STATE); - } - if ((portchange & USB_PORT_STAT_C_BH_RESET) && hub_is_superspeed(hub->hdev)) { need_debounce_delay = true; @@ -834,12 +869,19 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) set_bit(port1, hub->change_bits); } else if (portstatus & USB_PORT_STAT_ENABLE) { + bool port_resumed = (portstatus & + USB_PORT_STAT_LINK_STATE) == + USB_SS_PORT_LS_U0; /* The power session apparently survived the resume. * If there was an overcurrent or suspend change * (i.e., remote wakeup request), have khubd - * take care of it. + * take care of it. Look at the port link state + * for USB 3.0 hubs, since they don't have a suspend + * change bit, and they don't set the port link change + * bit on device-initiated resume. */ - if (portchange) + if (portchange || (hub_is_superspeed(hub->hdev) && + port_resumed)) set_bit(port1, hub->change_bits); } else if (udev->persist_enabled) { @@ -987,18 +1029,6 @@ static int hub_configure(struct usb_hub *hub, goto fail; } - if (hub_is_superspeed(hdev) && (hdev->parent != NULL)) { - ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), - HUB_SET_DEPTH, USB_RT_HUB, - hdev->level - 1, 0, NULL, 0, - USB_CTRL_SET_TIMEOUT); - - if (ret < 0) { - message = "can't set hub depth"; - goto fail; - } - } - /* Request the entire hub descriptor. * hub->descriptor can handle USB_MAXCHILDREN ports, * but the hub can/will return fewer bytes here. @@ -1289,14 +1319,8 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) desc = intf->cur_altsetting; hdev = interface_to_usbdev(intf); - /* Hubs have proper suspend/resume support. USB 3.0 device suspend is - * different from USB 2.0/1.1 device suspend, and unfortunately we - * don't support it yet. So leave autosuspend disabled for USB 3.0 - * external hubs for now. Enable autosuspend for USB 3.0 roothubs, - * since that isn't a "real" hub. - */ - if (!hub_is_superspeed(hdev) || !hdev->parent) - usb_enable_autosuspend(hdev); + /* Hubs have proper suspend/resume support. */ + usb_enable_autosuspend(hdev); if (hdev->level == MAX_TOPO_LEVEL) { dev_err(&intf->dev, @@ -1838,6 +1862,37 @@ fail: return err; } +static void set_usb_port_removable(struct usb_device *udev) +{ + struct usb_device *hdev = udev->parent; + struct usb_hub *hub; + u8 port = udev->portnum; + u16 wHubCharacteristics; + bool removable = true; + + if (!hdev) + return; + + hub = hdev_to_hub(udev->parent); + + wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); + + if (!(wHubCharacteristics & HUB_CHAR_COMPOUND)) + return; + + if (hub_is_superspeed(hdev)) { + if (hub->descriptor->u.ss.DeviceRemovable & (1 << port)) + removable = false; + } else { + if (hub->descriptor->u.hs.DeviceRemovable[port / 8] & (1 << (port % 8))) + removable = false; + } + + if (removable) + udev->removable = USB_DEVICE_REMOVABLE; + else + udev->removable = USB_DEVICE_FIXED; +} /** * usb_new_device - perform initial device setup (usbcore-internal) @@ -1896,6 +1951,15 @@ int usb_new_device(struct usb_device *udev) announce_device(udev); device_enable_async_suspend(&udev->dev); + + /* + * check whether the hub marks this port as non-removable. Do it + * now so that platform-specific data can override it in + * device_add() + */ + if (udev->parent) + set_usb_port_removable(udev); + /* Register the device. The device driver is responsible * for configuring the device and invoking the add-device * notifier chain (used by usbfs and possibly others). @@ -2381,11 +2445,27 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) * we don't explicitly enable it here. */ if (udev->do_remote_wakeup) { - status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); + if (!hub_is_superspeed(hub->hdev)) { + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + /* Assume there's only one function on the USB 3.0 + * device and enable remote wake for the first + * interface. FIXME if the interface association + * descriptor shows there's more than one function. + */ + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, + USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, + USB_INTRF_FUNC_SUSPEND_RW | + USB_INTRF_FUNC_SUSPEND_LP, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } if (status) { dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", status); @@ -2675,6 +2755,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) struct usb_hub *hub = usb_get_intfdata (intf); struct usb_device *hdev = hub->hdev; unsigned port1; + int status; /* Warn if children aren't already suspended */ for (port1 = 1; port1 <= hdev->maxchild; port1++) { @@ -2687,6 +2768,17 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) return -EBUSY; } } + if (hub_is_superspeed(hdev) && hdev->do_remote_wakeup) { + /* Enable hub to send remote wakeup for all ports. */ + for (port1 = 1; port1 <= hdev->maxchild; port1++) { + status = set_port_feature(hdev, + port1 | + USB_PORT_FEAT_REMOTE_WAKE_CONNECT | + USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT | + USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT, + USB_PORT_FEAT_REMOTE_WAKE_MASK); + } + } dev_dbg(&intf->dev, "%s\n", __func__); @@ -3420,6 +3512,46 @@ done: hcd->driver->relinquish_port(hcd, port1); } +/* Returns 1 if there was a remote wakeup and a connect status change. */ +static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, + u16 portstatus, u16 portchange) +{ + struct usb_device *hdev; + struct usb_device *udev; + int connect_change = 0; + int ret; + + hdev = hub->hdev; + udev = hdev->children[port-1]; + if (!hub_is_superspeed(hdev)) { + if (!(portchange & USB_PORT_STAT_C_SUSPEND)) + return 0; + clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND); + } else { + if (!udev || udev->state != USB_STATE_SUSPENDED || + (portstatus & USB_PORT_STAT_LINK_STATE) != + USB_SS_PORT_LS_U0) + return 0; + } + + if (udev) { + /* TRSMRCY = 10 msec */ + msleep(10); + + usb_lock_device(udev); + ret = usb_remote_wakeup(udev); + usb_unlock_device(udev); + if (ret < 0) + connect_change = 1; + } else { + ret = -ENODEV; + hub_port_disable(hub, port, 1); + } + dev_dbg(hub->intfdev, "resume on port %d, status %d\n", + port, ret); + return connect_change; +} + static void hub_events(void) { struct list_head *tmp; @@ -3432,7 +3564,7 @@ static void hub_events(void) u16 portstatus; u16 portchange; int i, ret; - int connect_change; + int connect_change, wakeup_change; /* * We restart the list every time to avoid a deadlock with @@ -3511,8 +3643,9 @@ static void hub_events(void) if (test_bit(i, hub->busy_bits)) continue; connect_change = test_bit(i, hub->change_bits); + wakeup_change = test_and_clear_bit(i, hub->wakeup_bits); if (!test_and_clear_bit(i, hub->event_bits) && - !connect_change) + !connect_change && !wakeup_change) continue; ret = hub_port_status(hub, i, @@ -3553,31 +3686,10 @@ static void hub_events(void) } } - if (portchange & USB_PORT_STAT_C_SUSPEND) { - struct usb_device *udev; + if (hub_handle_remote_wakeup(hub, i, + portstatus, portchange)) + connect_change = 1; - clear_port_feature(hdev, i, - USB_PORT_FEAT_C_SUSPEND); - udev = hdev->children[i-1]; - if (udev) { - /* TRSMRCY = 10 msec */ - msleep(10); - - usb_lock_device(udev); - ret = usb_remote_wakeup(hdev-> - children[i-1]); - usb_unlock_device(udev); - if (ret < 0) - connect_change = 1; - } else { - ret = -ENODEV; - hub_port_disable(hub, i, 1); - } - dev_dbg (hub_dev, - "resume on port %d, status %d\n", - i, ret); - } - if (portchange & USB_PORT_STAT_C_OVERCURRENT) { u16 status = 0; u16 unused; diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 9e491ca..566d9f9 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -230,6 +230,28 @@ show_urbnum(struct device *dev, struct device_attribute *attr, char *buf) } static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL); +static ssize_t +show_removable(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct usb_device *udev; + char *state; + + udev = to_usb_device(dev); + + switch (udev->removable) { + case USB_DEVICE_REMOVABLE: + state = "removable"; + break; + case USB_DEVICE_FIXED: + state = "fixed"; + break; + default: + state = "unknown"; + } + + return sprintf(buf, "%s\n", state); +} +static DEVICE_ATTR(removable, S_IRUGO, show_removable, NULL); #ifdef CONFIG_PM @@ -626,6 +648,7 @@ static struct attribute *dev_attrs[] = { &dev_attr_avoid_reset_quirk.attr, &dev_attr_authorized.attr, &dev_attr_remove.attr, + &dev_attr_removable.attr, NULL, }; static struct attribute_group dev_attr_grp = { diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 909625b..f4f20c7 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -403,20 +403,17 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) * cause problems in HCDs if they get it wrong. */ { - unsigned int orig_flags = urb->transfer_flags; unsigned int allowed; static int pipetypes[4] = { PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT }; /* Check that the pipe's type matches the endpoint's type */ - if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) { - dev_err(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", + if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) + dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", usb_pipetype(urb->pipe), pipetypes[xfertype]); - return -EPIPE; /* The most suitable error code :-) */ - } - /* enforce simple/standard policy */ + /* Check against a simple/standard policy */ allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK | URB_FREE_BUFFER); switch (xfertype) { @@ -435,14 +432,12 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) allowed |= URB_ISO_ASAP; break; } - urb->transfer_flags &= allowed; + allowed &= urb->transfer_flags; - /* fail if submitter gave bogus flags */ - if (urb->transfer_flags != orig_flags) { - dev_err(&dev->dev, "BOGUS urb flags, %x --> %x\n", - orig_flags, urb->transfer_flags); - return -EINVAL; - } + /* warn if submitter gave bogus flags */ + if (allowed != urb->transfer_flags) + dev_WARN(&dev->dev, "BOGUS urb flags, %x --> %x\n", + urb->transfer_flags, allowed); } #endif /* diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 8ca9f99..c74ba7b 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -274,7 +274,7 @@ static int usb_dev_prepare(struct device *dev) static void usb_dev_complete(struct device *dev) { /* Currently used only for rebinding interfaces */ - usb_resume(dev, PMSG_ON); /* FIXME: change to PMSG_COMPLETE */ + usb_resume_complete(dev); } static int usb_dev_suspend(struct device *dev) diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 45e8479..71648dc 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -56,6 +56,7 @@ extern void usb_major_cleanup(void); extern int usb_suspend(struct device *dev, pm_message_t msg); extern int usb_resume(struct device *dev, pm_message_t msg); +extern int usb_resume_complete(struct device *dev); extern int usb_port_suspend(struct usb_device *dev, pm_message_t msg); extern int usb_port_resume(struct usb_device *dev, pm_message_t msg); diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 24137d8..d5c568e 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -126,7 +126,6 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, struct dwc3_request *req) { struct dwc3 *dwc = dep->dwc; - u32 type; int ret = 0; req->request.actual = 0; @@ -149,20 +148,14 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, direction = !!(dep->flags & DWC3_EP0_DIR_IN); - if (dwc->ep0state == EP0_STATUS_PHASE) { - type = dwc->three_stage_setup - ? DWC3_TRBCTL_CONTROL_STATUS3 - : DWC3_TRBCTL_CONTROL_STATUS2; - } else if (dwc->ep0state == EP0_DATA_PHASE) { - type = DWC3_TRBCTL_CONTROL_DATA; - } else { - /* should never happen */ - WARN_ON(1); + if (dwc->ep0state != EP0_DATA_PHASE) { + dev_WARN(dwc->dev, "Unexpected pending request\n"); return 0; } ret = dwc3_ep0_start_trans(dwc, direction, - req->request.dma, req->request.length, type); + req->request.dma, req->request.length, + DWC3_TRBCTL_CONTROL_DATA); dep->flags &= ~(DWC3_EP_PENDING_REQUEST | DWC3_EP0_DIR_IN); } else if (dwc->delayed_status) { diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c index 1fc6129..d07e44c 100644 --- a/drivers/usb/gadget/ci13xxx_msm.c +++ b/drivers/usb/gadget/ci13xxx_msm.c @@ -37,10 +37,10 @@ static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event) * Put the transceiver in non-driving mode. Otherwise host * may not detect soft-disconnection. */ - val = otg_io_read(udc->transceiver, ULPI_FUNC_CTRL); + val = usb_phy_io_read(udc->transceiver, ULPI_FUNC_CTRL); val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; - otg_io_write(udc->transceiver, val, ULPI_FUNC_CTRL); + usb_phy_io_write(udc->transceiver, val, ULPI_FUNC_CTRL); break; default: dev_dbg(dev, "unknown ci13xxx_udc event\n"); diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 9e89289..243ef1a 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -2538,7 +2538,7 @@ static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA) struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget); if (udc->transceiver) - return otg_set_power(udc->transceiver, mA); + return usb_phy_set_power(udc->transceiver, mA); return -ENOTSUPP; } @@ -2901,7 +2901,7 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev, if (retval < 0) goto free_udc; - udc->transceiver = otg_get_transceiver(); + udc->transceiver = usb_get_transceiver(); if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) { if (udc->transceiver == NULL) { @@ -2929,7 +2929,8 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev, goto unreg_device; if (udc->transceiver) { - retval = otg_set_peripheral(udc->transceiver, &udc->gadget); + retval = otg_set_peripheral(udc->transceiver->otg, + &udc->gadget); if (retval) goto remove_dbg; } @@ -2946,8 +2947,8 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev, remove_trans: if (udc->transceiver) { - otg_set_peripheral(udc->transceiver, &udc->gadget); - otg_put_transceiver(udc->transceiver); + otg_set_peripheral(udc->transceiver->otg, &udc->gadget); + usb_put_transceiver(udc->transceiver); } err("error = %i", retval); @@ -2959,7 +2960,7 @@ unreg_device: device_unregister(&udc->gadget.dev); put_transceiver: if (udc->transceiver) - otg_put_transceiver(udc->transceiver); + usb_put_transceiver(udc->transceiver); free_udc: kfree(udc); _udc = NULL; @@ -2982,8 +2983,8 @@ static void udc_remove(void) usb_del_gadget_udc(&udc->gadget); if (udc->transceiver) { - otg_set_peripheral(udc->transceiver, &udc->gadget); - otg_put_transceiver(udc->transceiver); + otg_set_peripheral(udc->transceiver->otg, &udc->gadget); + usb_put_transceiver(udc->transceiver); } #ifdef CONFIG_USB_GADGET_DEBUG_FILES dbg_remove_files(&udc->gadget.dev); diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h index f4871e1..0d31af5 100644 --- a/drivers/usb/gadget/ci13xxx_udc.h +++ b/drivers/usb/gadget/ci13xxx_udc.h @@ -136,7 +136,7 @@ struct ci13xxx { struct usb_gadget_driver *driver; /* 3rd party gadget driver */ struct ci13xxx_udc_driver *udc_driver; /* device controller driver */ int vbus_active; /* is VBUS active */ - struct otg_transceiver *transceiver; /* Transceiver struct */ + struct usb_phy *transceiver; /* Transceiver struct */ }; /****************************************************************************** diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index a95de6a..baaebf2 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -175,13 +175,12 @@ ep_found: _ep->comp_desc = comp_desc; if (g->speed == USB_SPEED_SUPER) { switch (usb_endpoint_type(_ep->desc)) { - case USB_ENDPOINT_XFER_BULK: - case USB_ENDPOINT_XFER_INT: - _ep->maxburst = comp_desc->bMaxBurst; - break; case USB_ENDPOINT_XFER_ISOC: /* mult: bits 1:0 of bmAttributes */ _ep->mult = comp_desc->bmAttributes & 0x3; + case USB_ENDPOINT_XFER_BULK: + case USB_ENDPOINT_XFER_INT: + _ep->maxburst = comp_desc->bMaxBurst; break; default: /* Do nothing for control endpoints */ diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index f59f7e3..51f3d42 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -126,7 +126,7 @@ ep_matches ( * descriptor and see if the EP matches it */ if (usb_endpoint_xfer_bulk(desc)) { - if (ep_comp) { + if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) { num_req_streams = ep_comp->bmAttributes & 0x1f; if (num_req_streams > ep->max_streams) return 0; diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 6d87f28..2c0cd82 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -418,7 +418,7 @@ int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume) /* support autoresume for remote wakeup testing */ if (autoresume) - sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; /* support OTG systems */ if (gadget_is_otg(cdev->gadget)) { diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 8246271..a371e96 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -619,7 +619,7 @@ static int fsg_setup(struct usb_function *f, switch (ctrl->bRequest) { - case USB_BULK_RESET_REQUEST: + case US_BULK_RESET_REQUEST: if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) break; @@ -635,7 +635,7 @@ static int fsg_setup(struct usb_function *f, raise_exception(fsg->common, FSG_STATE_RESET); return DELAYED_STATUS; - case USB_BULK_GET_MAX_LUN_REQUEST: + case US_BULK_GET_MAX_LUN: if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) break; @@ -1741,7 +1741,7 @@ static int send_status(struct fsg_common *common) struct fsg_buffhd *bh; struct bulk_cs_wrap *csw; int rc; - u8 status = USB_STATUS_PASS; + u8 status = US_BULK_STAT_OK; u32 sd, sdinfo = 0; /* Wait for the next buffer to become available */ @@ -1762,11 +1762,11 @@ static int send_status(struct fsg_common *common) if (common->phase_error) { DBG(common, "sending phase-error status\n"); - status = USB_STATUS_PHASE_ERROR; + status = US_BULK_STAT_PHASE; sd = SS_INVALID_COMMAND; } else if (sd != SS_NO_SENSE) { DBG(common, "sending command-failure status\n"); - status = USB_STATUS_FAIL; + status = US_BULK_STAT_FAIL; VDBG(common, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" " info x%x\n", SK(sd), ASC(sd), ASCQ(sd), sdinfo); @@ -1775,12 +1775,12 @@ static int send_status(struct fsg_common *common) /* Store and send the Bulk-only CSW */ csw = (void *)bh->buf; - csw->Signature = cpu_to_le32(USB_BULK_CS_SIG); + csw->Signature = cpu_to_le32(US_BULK_CS_SIGN); csw->Tag = common->tag; csw->Residue = cpu_to_le32(common->residue); csw->Status = status; - bh->inreq->length = USB_BULK_CS_WRAP_LEN; + bh->inreq->length = US_BULK_CS_WRAP_LEN; bh->inreq->zero = 0; if (!start_in_transfer(common, bh)) /* Don't know what to do if common->fsg is NULL */ @@ -2220,7 +2220,7 @@ unknown_cmnd: static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) { struct usb_request *req = bh->outreq; - struct fsg_bulk_cb_wrap *cbw = req->buf; + struct bulk_cb_wrap *cbw = req->buf; struct fsg_common *common = fsg->common; /* Was this a real packet? Should it be ignored? */ @@ -2228,9 +2228,9 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) return -EINVAL; /* Is the CBW valid? */ - if (req->actual != USB_BULK_CB_WRAP_LEN || + if (req->actual != US_BULK_CB_WRAP_LEN || cbw->Signature != cpu_to_le32( - USB_BULK_CB_SIG)) { + US_BULK_CB_SIGN)) { DBG(fsg, "invalid CBW: len %u sig 0x%x\n", req->actual, le32_to_cpu(cbw->Signature)); @@ -2252,7 +2252,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) } /* Is the CBW meaningful? */ - if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || + if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN || cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " "cmdlen %u\n", @@ -2272,7 +2272,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) /* Save the command for later */ common->cmnd_size = cbw->Length; memcpy(common->cmnd, cbw->CDB, common->cmnd_size); - if (cbw->Flags & USB_BULK_IN_FLAG) + if (cbw->Flags & US_BULK_FLAG_IN) common->data_dir = DATA_DIR_TO_HOST; else common->data_dir = DATA_DIR_FROM_HOST; @@ -2302,7 +2302,7 @@ static int get_next_command(struct fsg_common *common) } /* Queue a request to read a Bulk-only CBW */ - set_bulk_out_req_length(common, bh, USB_BULK_CB_WRAP_LEN); + set_bulk_out_req_length(common, bh, US_BULK_CB_WRAP_LEN); if (!start_out_transfer(common, bh)) /* Don't know what to do if common->fsg is NULL */ return -EIO; @@ -3122,15 +3122,15 @@ fsg_add(struct usb_composite_dev *cdev, struct usb_configuration *c, struct fsg_module_parameters { char *file[FSG_MAX_LUNS]; - int ro[FSG_MAX_LUNS]; - int removable[FSG_MAX_LUNS]; - int cdrom[FSG_MAX_LUNS]; - int nofua[FSG_MAX_LUNS]; + bool ro[FSG_MAX_LUNS]; + bool removable[FSG_MAX_LUNS]; + bool cdrom[FSG_MAX_LUNS]; + bool nofua[FSG_MAX_LUNS]; unsigned int file_count, ro_count, removable_count, cdrom_count; unsigned int nofua_count; unsigned int luns; /* nluns */ - int stall; /* can_stall */ + bool stall; /* can_stall */ }; #define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc) \ diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 47766f0..4fac569 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -855,7 +855,7 @@ static int class_setup_req(struct fsg_dev *fsg, if (transport_is_bbb()) { switch (ctrl->bRequest) { - case USB_BULK_RESET_REQUEST: + case US_BULK_RESET_REQUEST: if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) break; @@ -871,7 +871,7 @@ static int class_setup_req(struct fsg_dev *fsg, value = DELAYED_STATUS; break; - case USB_BULK_GET_MAX_LUN_REQUEST: + case US_BULK_GET_MAX_LUN: if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) break; @@ -2125,7 +2125,7 @@ static int send_status(struct fsg_dev *fsg) struct fsg_lun *curlun = fsg->curlun; struct fsg_buffhd *bh; int rc; - u8 status = USB_STATUS_PASS; + u8 status = US_BULK_STAT_OK; u32 sd, sdinfo = 0; /* Wait for the next buffer to become available */ @@ -2146,11 +2146,11 @@ static int send_status(struct fsg_dev *fsg) if (fsg->phase_error) { DBG(fsg, "sending phase-error status\n"); - status = USB_STATUS_PHASE_ERROR; + status = US_BULK_STAT_PHASE; sd = SS_INVALID_COMMAND; } else if (sd != SS_NO_SENSE) { DBG(fsg, "sending command-failure status\n"); - status = USB_STATUS_FAIL; + status = US_BULK_STAT_FAIL; VDBG(fsg, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" " info x%x\n", SK(sd), ASC(sd), ASCQ(sd), sdinfo); @@ -2160,12 +2160,12 @@ static int send_status(struct fsg_dev *fsg) struct bulk_cs_wrap *csw = bh->buf; /* Store and send the Bulk-only CSW */ - csw->Signature = cpu_to_le32(USB_BULK_CS_SIG); + csw->Signature = cpu_to_le32(US_BULK_CS_SIGN); csw->Tag = fsg->tag; csw->Residue = cpu_to_le32(fsg->residue); csw->Status = status; - bh->inreq->length = USB_BULK_CS_WRAP_LEN; + bh->inreq->length = US_BULK_CS_WRAP_LEN; bh->inreq->zero = 0; start_transfer(fsg, fsg->bulk_in, bh->inreq, &bh->inreq_busy, &bh->state); @@ -2609,16 +2609,16 @@ static int do_scsi_command(struct fsg_dev *fsg) static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) { struct usb_request *req = bh->outreq; - struct fsg_bulk_cb_wrap *cbw = req->buf; + struct bulk_cb_wrap *cbw = req->buf; /* Was this a real packet? Should it be ignored? */ if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) return -EINVAL; /* Is the CBW valid? */ - if (req->actual != USB_BULK_CB_WRAP_LEN || + if (req->actual != US_BULK_CB_WRAP_LEN || cbw->Signature != cpu_to_le32( - USB_BULK_CB_SIG)) { + US_BULK_CB_SIGN)) { DBG(fsg, "invalid CBW: len %u sig 0x%x\n", req->actual, le32_to_cpu(cbw->Signature)); @@ -2638,7 +2638,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) } /* Is the CBW meaningful? */ - if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || + if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN || cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " "cmdlen %u\n", @@ -2656,7 +2656,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) /* Save the command for later */ fsg->cmnd_size = cbw->Length; memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size); - if (cbw->Flags & USB_BULK_IN_FLAG) + if (cbw->Flags & US_BULK_FLAG_IN) fsg->data_dir = DATA_DIR_TO_HOST; else fsg->data_dir = DATA_DIR_FROM_HOST; @@ -2685,7 +2685,7 @@ static int get_next_command(struct fsg_dev *fsg) } /* Queue a request to read a Bulk-only CBW */ - set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN); + set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN); start_transfer(fsg, fsg->bulk_out, bh->outreq, &bh->outreq_busy, &bh->state); diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 8db5a66..b30e21f 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1216,7 +1216,7 @@ static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA) udc = container_of(gadget, struct fsl_udc, gadget); if (udc->transceiver) - return otg_set_power(udc->transceiver, mA); + return usb_phy_set_power(udc->transceiver, mA); return -ENOTSUPP; } @@ -1429,7 +1429,7 @@ static void setup_received_irq(struct fsl_udc *udc, int pipe = get_pipe_by_windex(wIndex); struct fsl_ep *ep; - if (wValue != 0 || wLength != 0 || pipe > udc->max_ep) + if (wValue != 0 || wLength != 0 || pipe >= udc->max_ep) break; ep = get_ep_by_pipe(udc, pipe); @@ -1672,7 +1672,7 @@ static void dtd_complete_irq(struct fsl_udc *udc) if (!bit_pos) return; - for (i = 0; i < udc->max_ep * 2; i++) { + for (i = 0; i < udc->max_ep; i++) { ep_num = i >> 1; direction = i % 2; @@ -1965,7 +1965,8 @@ static int fsl_start(struct usb_gadget_driver *driver, /* connect to bus through transceiver */ if (udc_controller->transceiver) { - retval = otg_set_peripheral(udc_controller->transceiver, + retval = otg_set_peripheral( + udc_controller->transceiver->otg, &udc_controller->gadget); if (retval < 0) { ERR("can't bind to transceiver\n"); @@ -2005,7 +2006,7 @@ static int fsl_stop(struct usb_gadget_driver *driver) return -EINVAL; if (udc_controller->transceiver) - otg_set_peripheral(udc_controller->transceiver, NULL); + otg_set_peripheral(udc_controller->transceiver->otg, NULL); /* stop DR, disable intr */ dr_controller_stop(udc_controller); @@ -2429,7 +2430,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) #ifdef CONFIG_USB_OTG if (pdata->operating_mode == FSL_USB2_DR_OTG) { - udc_controller->transceiver = otg_get_transceiver(); + udc_controller->transceiver = usb_get_transceiver(); if (!udc_controller->transceiver) { ERR("Can't find OTG driver!\n"); ret = -ENODEV; diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index f781f5d..e651469 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -471,7 +471,7 @@ struct fsl_udc { struct usb_ctrlrequest local_setup_buff; spinlock_t lock; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; unsigned softconnect:1; unsigned vbus_active:1; unsigned stopped:1; diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index e91f11a..edd52d9 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -11,11 +11,6 @@ /* #undef DEBUG */ /* #undef VERBOSE_DEBUG */ -#if defined(CONFIG_USB_LANGWELL_OTG) -#define OTG_TRANSCEIVER -#endif - - #include <linux/module.h> #include <linux/pci.h> #include <linux/dma-mapping.h> @@ -1236,9 +1231,9 @@ static int langwell_vbus_draw(struct usb_gadget *_gadget, unsigned mA) dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if (dev->transceiver) { - dev_vdbg(&dev->pdev->dev, "otg_set_power\n"); + dev_vdbg(&dev->pdev->dev, "usb_phy_set_power\n"); dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); - return otg_set_power(dev->transceiver, mA); + return usb_phy_set_power(dev->transceiver, mA); } dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); @@ -1492,8 +1487,7 @@ static void langwell_udc_stop(struct langwell_udc *dev) /* stop all USB activities */ -static void stop_activity(struct langwell_udc *dev, - struct usb_gadget_driver *driver) +static void stop_activity(struct langwell_udc *dev) { struct langwell_ep *ep; dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); @@ -1505,9 +1499,9 @@ static void stop_activity(struct langwell_udc *dev, } /* report disconnect; the driver is already quiesced */ - if (driver) { + if (dev->driver) { spin_unlock(&dev->lock); - driver->disconnect(&dev->gadget); + dev->driver->disconnect(&dev->gadget); spin_lock(&dev->lock); } @@ -1882,7 +1876,7 @@ static int langwell_stop(struct usb_gadget *g, /* unbind OTG transceiver */ if (dev->transceiver) - (void)otg_set_peripheral(dev->transceiver, 0); + (void)otg_set_peripheral(dev->transceiver->otg, 0); /* disable interrupt and set controller to stop state */ langwell_udc_stop(dev); @@ -1895,11 +1889,10 @@ static int langwell_stop(struct usb_gadget *g, /* stop all usb activities */ dev->gadget.speed = USB_SPEED_UNKNOWN; - stop_activity(dev, driver); - spin_unlock_irqrestore(&dev->lock, flags); - dev->gadget.dev.driver = NULL; dev->driver = NULL; + stop_activity(dev); + spin_unlock_irqrestore(&dev->lock, flags); device_remove_file(&dev->pdev->dev, &dev_attr_function); @@ -2285,13 +2278,9 @@ static void handle_setup_packet(struct langwell_udc *dev, if (!gadget_is_otg(&dev->gadget)) break; - else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) { + else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) dev->gadget.b_hnp_enable = 1; -#ifdef OTG_TRANSCEIVER - if (!dev->lotg->otg.default_a) - dev->lotg->hsm.b_hnp_enable = 1; -#endif - } else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT) + else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT) dev->gadget.a_hnp_support = 1; else if (setup->bRequest == USB_DEVICE_A_ALT_HNP_SUPPORT) @@ -2703,7 +2692,7 @@ static void handle_usb_reset(struct langwell_udc *dev) dev->bus_reset = 1; /* reset all the queues, stop all USB activities */ - stop_activity(dev, dev->driver); + stop_activity(dev); dev->usb_state = USB_STATE_DEFAULT; } else { dev_vdbg(&dev->pdev->dev, "device controller reset\n"); @@ -2711,7 +2700,7 @@ static void handle_usb_reset(struct langwell_udc *dev) langwell_udc_reset(dev); /* reset all the queues, stop all USB activities */ - stop_activity(dev, dev->driver); + stop_activity(dev); /* reset ep0 dQH and endptctrl */ ep0_reset(dev); @@ -2722,12 +2711,6 @@ static void handle_usb_reset(struct langwell_udc *dev) dev->usb_state = USB_STATE_ATTACHED; } -#ifdef OTG_TRANSCEIVER - /* refer to USB OTG 6.6.2.3 b_hnp_en is cleared */ - if (!dev->lotg->otg.default_a) - dev->lotg->hsm.b_hnp_enable = 0; -#endif - dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -2740,29 +2723,6 @@ static void handle_bus_suspend(struct langwell_udc *dev) dev->resume_state = dev->usb_state; dev->usb_state = USB_STATE_SUSPENDED; -#ifdef OTG_TRANSCEIVER - if (dev->lotg->otg.default_a) { - if (dev->lotg->hsm.b_bus_suspend_vld == 1) { - dev->lotg->hsm.b_bus_suspend = 1; - /* notify transceiver the state changes */ - if (spin_trylock(&dev->lotg->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&dev->lotg->wq_lock); - } - } - dev->lotg->hsm.b_bus_suspend_vld++; - } else { - if (!dev->lotg->hsm.a_bus_suspend) { - dev->lotg->hsm.a_bus_suspend = 1; - /* notify transceiver the state changes */ - if (spin_trylock(&dev->lotg->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&dev->lotg->wq_lock); - } - } - } -#endif - /* report suspend to the driver */ if (dev->driver) { if (dev->driver->suspend) { @@ -2793,11 +2753,6 @@ static void handle_bus_resume(struct langwell_udc *dev) if (dev->pdev->device != 0x0829) langwell_phy_low_power(dev, 0); -#ifdef OTG_TRANSCEIVER - if (dev->lotg->otg.default_a == 0) - dev->lotg->hsm.a_bus_suspend = 0; -#endif - /* report resume to the driver */ if (dev->driver) { if (dev->driver->resume) { @@ -2990,7 +2945,6 @@ static void langwell_udc_remove(struct pci_dev *pdev) dev->done = &done; -#ifndef OTG_TRANSCEIVER /* free dTD dma_pool and dQH */ if (dev->dtd_pool) dma_pool_destroy(dev->dtd_pool); @@ -3002,7 +2956,6 @@ static void langwell_udc_remove(struct pci_dev *pdev) /* release SRAM caching */ if (dev->has_sram && dev->got_sram) sram_deinit(dev); -#endif if (dev->status_req) { kfree(dev->status_req->req.buf); @@ -3015,7 +2968,6 @@ static void langwell_udc_remove(struct pci_dev *pdev) if (dev->got_irq) free_irq(pdev->irq, dev); -#ifndef OTG_TRANSCEIVER if (dev->cap_regs) iounmap(dev->cap_regs); @@ -3025,13 +2977,6 @@ static void langwell_udc_remove(struct pci_dev *pdev) if (dev->enabled) pci_disable_device(pdev); -#else - if (dev->transceiver) { - otg_put_transceiver(dev->transceiver); - dev->transceiver = NULL; - dev->lotg = NULL; - } -#endif dev->cap_regs = NULL; @@ -3042,9 +2987,7 @@ static void langwell_udc_remove(struct pci_dev *pdev) device_remove_file(&pdev->dev, &dev_attr_langwell_udc); device_remove_file(&pdev->dev, &dev_attr_remote_wakeup); -#ifndef OTG_TRANSCEIVER pci_set_drvdata(pdev, NULL); -#endif /* free dev, wait for the release() finished */ wait_for_completion(&done); @@ -3059,9 +3002,7 @@ static int langwell_udc_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct langwell_udc *dev; -#ifndef OTG_TRANSCEIVER unsigned long resource, len; -#endif void __iomem *base = NULL; size_t size; int retval; @@ -3079,16 +3020,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->pdev = pdev; dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); -#ifdef OTG_TRANSCEIVER - /* PCI device is already enabled by otg_transceiver driver */ - dev->enabled = 1; - - /* mem region and register base */ - dev->region = 1; - dev->transceiver = otg_get_transceiver(); - dev->lotg = otg_to_langwell(dev->transceiver); - base = dev->lotg->regs; -#else pci_set_drvdata(pdev, dev); /* now all the pci goodies ... */ @@ -3109,7 +3040,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->region = 1; base = ioremap_nocache(resource, len); -#endif if (base == NULL) { dev_err(&dev->pdev->dev, "can't map memory\n"); retval = -EFAULT; @@ -3133,7 +3063,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->got_sram = 0; dev_vdbg(&dev->pdev->dev, "dev->has_sram: %d\n", dev->has_sram); -#ifndef OTG_TRANSCEIVER /* enable SRAM caching if detected */ if (dev->has_sram && !dev->got_sram) sram_init(dev); @@ -3152,7 +3081,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, goto error; } dev->got_irq = 1; -#endif /* set stopped bit */ dev->stopped = 1; @@ -3227,10 +3155,8 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->remote_wakeup = 0; dev->dev_status = 1 << USB_DEVICE_SELF_POWERED; -#ifndef OTG_TRANSCEIVER /* reset device controller */ langwell_udc_reset(dev); -#endif /* initialize gadget structure */ dev->gadget.ops = &langwell_ops; /* usb_gadget_ops */ @@ -3238,9 +3164,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, INIT_LIST_HEAD(&dev->gadget.ep_list); /* ep_list */ dev->gadget.speed = USB_SPEED_UNKNOWN; /* speed */ dev->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */ -#ifdef OTG_TRANSCEIVER - dev->gadget.is_otg = 1; /* support otg mode */ -#endif /* the "gadget" abstracts/virtualizes the controller */ dev_set_name(&dev->gadget.dev, "gadget"); @@ -3252,10 +3175,8 @@ static int langwell_udc_probe(struct pci_dev *pdev, /* controller endpoints reinit */ eps_reinit(dev); -#ifndef OTG_TRANSCEIVER /* reset ep0 dQH and endptctrl */ ep0_reset(dev); -#endif /* create dTD dma_pool resource */ dev->dtd_pool = dma_pool_create("langwell_dtd", @@ -3337,7 +3258,7 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) spin_lock_irq(&dev->lock); /* stop all usb activities */ - stop_activity(dev, dev->driver); + stop_activity(dev); spin_unlock_irq(&dev->lock); /* free dTD dma_pool and dQH */ @@ -3495,22 +3416,14 @@ static struct pci_driver langwell_pci_driver = { static int __init init(void) { -#ifdef OTG_TRANSCEIVER - return langwell_register_peripheral(&langwell_pci_driver); -#else return pci_register_driver(&langwell_pci_driver); -#endif } module_init(init); static void __exit cleanup(void) { -#ifdef OTG_TRANSCEIVER - return langwell_unregister_peripheral(&langwell_pci_driver); -#else pci_unregister_driver(&langwell_pci_driver); -#endif } module_exit(cleanup); diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h index ef79e24..8c8087a 100644 --- a/drivers/usb/gadget/langwell_udc.h +++ b/drivers/usb/gadget/langwell_udc.h @@ -8,7 +8,6 @@ */ #include <linux/usb/langwell_udc.h> -#include <linux/usb/langwell_otg.h> /*-------------------------------------------------------------------------*/ @@ -163,7 +162,7 @@ struct langwell_udc { spinlock_t lock; /* device lock */ struct langwell_ep *ep; struct usb_gadget_driver *driver; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; u8 dev_addr; u32 usb_state; u32 resume_state; diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h index 34aadfa..e2be951 100644 --- a/drivers/usb/gadget/mv_udc.h +++ b/drivers/usb/gadget/mv_udc.h @@ -217,7 +217,7 @@ struct mv_udc { struct work_struct vbus_work; struct workqueue_struct *qwork; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; struct mv_usb_platform_data *pdata; diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index ec6009f..19bbe80 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -1384,7 +1384,8 @@ static int mv_udc_start(struct usb_gadget_driver *driver, } if (udc->transceiver) { - retval = otg_set_peripheral(udc->transceiver, &udc->gadget); + retval = otg_set_peripheral(udc->transceiver->otg, + &udc->gadget); if (retval) { dev_err(&udc->dev->dev, "unable to register peripheral to otg\n"); @@ -2181,7 +2182,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev) #ifdef CONFIG_USB_OTG_UTILS if (pdata->mode == MV_USB_MODE_OTG) - udc->transceiver = otg_get_transceiver(); + udc->transceiver = usb_get_transceiver(); #endif udc->clknum = pdata->clknum; diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 7d0835e..b44830d 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -1214,7 +1214,7 @@ static int omap_wakeup(struct usb_gadget *gadget) /* NOTE: non-OTG systems may use SRP TOO... */ } else if (!(udc->devstat & UDC_ATT)) { if (udc->transceiver) - retval = otg_start_srp(udc->transceiver); + retval = otg_start_srp(udc->transceiver->otg); } spin_unlock_irqrestore(&udc->lock, flags); @@ -1346,7 +1346,7 @@ static int omap_vbus_draw(struct usb_gadget *gadget, unsigned mA) udc = container_of(gadget, struct omap_udc, gadget); if (udc->transceiver) - return otg_set_power(udc->transceiver, mA); + return usb_phy_set_power(udc->transceiver, mA); return -EOPNOTSUPP; } @@ -1840,11 +1840,13 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src) spin_lock(&udc->lock); } if (udc->transceiver) - otg_set_suspend(udc->transceiver, 1); + usb_phy_set_suspend( + udc->transceiver, 1); } else { VDBG("resume\n"); if (udc->transceiver) - otg_set_suspend(udc->transceiver, 0); + usb_phy_set_suspend( + udc->transceiver, 0); if (udc->gadget.speed == USB_SPEED_FULL && udc->driver->resume) { spin_unlock(&udc->lock); @@ -2155,7 +2157,8 @@ static int omap_udc_start(struct usb_gadget_driver *driver, /* connect to bus through transceiver */ if (udc->transceiver) { - status = otg_set_peripheral(udc->transceiver, &udc->gadget); + status = otg_set_peripheral(udc->transceiver->otg, + &udc->gadget); if (status < 0) { ERR("can't bind to transceiver\n"); if (driver->unbind) { @@ -2201,7 +2204,7 @@ static int omap_udc_stop(struct usb_gadget_driver *driver) omap_vbus_session(&udc->gadget, 0); if (udc->transceiver) - (void) otg_set_peripheral(udc->transceiver, NULL); + (void) otg_set_peripheral(udc->transceiver->otg, NULL); else pullup_disable(udc); @@ -2651,7 +2654,7 @@ static void omap_udc_release(struct device *dev) } static int __init -omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv) +omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) { unsigned tmp, buf; @@ -2791,7 +2794,7 @@ static int __init omap_udc_probe(struct platform_device *pdev) { int status = -ENODEV; int hmc; - struct otg_transceiver *xceiv = NULL; + struct usb_phy *xceiv = NULL; const char *type = NULL; struct omap_usb_config *config = pdev->dev.platform_data; struct clk *dc_clk; @@ -2864,7 +2867,7 @@ static int __init omap_udc_probe(struct platform_device *pdev) * use it. Except for OTG, we don't _need_ to talk to one; * but not having one probably means no VBUS detection. */ - xceiv = otg_get_transceiver(); + xceiv = usb_get_transceiver(); if (xceiv) type = xceiv->label; else if (config->otg) { @@ -3010,7 +3013,7 @@ cleanup1: cleanup0: if (xceiv) - otg_put_transceiver(xceiv); + usb_put_transceiver(xceiv); if (cpu_is_omap16xx() || cpu_is_omap24xx() || cpu_is_omap7xx()) { clk_disable(hhc_clk); @@ -3040,7 +3043,7 @@ static int __exit omap_udc_remove(struct platform_device *pdev) pullup_disable(udc); if (udc->transceiver) { - otg_put_transceiver(udc->transceiver); + usb_put_transceiver(udc->transceiver); udc->transceiver = NULL; } omap_writew(0, UDC_SYSCON1); diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h index 29edc51..59d3b22 100644 --- a/drivers/usb/gadget/omap_udc.h +++ b/drivers/usb/gadget/omap_udc.h @@ -164,7 +164,7 @@ struct omap_udc { struct omap_ep ep[32]; u16 devstat; u16 clr_halt; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; struct list_head iso; unsigned softconnect:1; unsigned vbus_active:1; diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 33adf38..1b33634 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -996,7 +996,7 @@ static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) udc = container_of(_gadget, struct pxa25x_udc, gadget); if (udc->transceiver) - return otg_set_power(udc->transceiver, mA); + return usb_phy_set_power(udc->transceiver, mA); return -EOPNOTSUPP; } @@ -1303,7 +1303,8 @@ fail: /* connect to bus through transceiver */ if (dev->transceiver) { - retval = otg_set_peripheral(dev->transceiver, &dev->gadget); + retval = otg_set_peripheral(dev->transceiver->otg, + &dev->gadget); if (retval) { DMSG("can't bind to transceiver\n"); if (driver->unbind) @@ -1362,7 +1363,7 @@ static int pxa25x_stop(struct usb_gadget_driver *driver) local_irq_enable(); if (dev->transceiver) - (void) otg_set_peripheral(dev->transceiver, NULL); + (void) otg_set_peripheral(dev->transceiver->otg, NULL); driver->unbind(&dev->gadget); dev->gadget.dev.driver = NULL; @@ -2161,7 +2162,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) dev->dev = &pdev->dev; dev->mach = pdev->dev.platform_data; - dev->transceiver = otg_get_transceiver(); + dev->transceiver = usb_get_transceiver(); if (gpio_is_valid(dev->mach->gpio_pullup)) { if ((retval = gpio_request(dev->mach->gpio_pullup, @@ -2240,7 +2241,7 @@ lubbock_fail0: gpio_free(dev->mach->gpio_pullup); err_gpio_pullup: if (dev->transceiver) { - otg_put_transceiver(dev->transceiver); + usb_put_transceiver(dev->transceiver); dev->transceiver = NULL; } clk_put(dev->clk); @@ -2282,7 +2283,7 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev) clk_put(dev->clk); if (dev->transceiver) { - otg_put_transceiver(dev->transceiver); + usb_put_transceiver(dev->transceiver); dev->transceiver = NULL; } diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h index 8eaf4e4..893e917 100644 --- a/drivers/usb/gadget/pxa25x_udc.h +++ b/drivers/usb/gadget/pxa25x_udc.h @@ -119,7 +119,7 @@ struct pxa25x_udc { struct device *dev; struct clk *clk; struct pxa2xx_udc_mach_info *mach; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; u64 dma_mask; struct pxa25x_ep ep [PXA_UDC_NUM_ENDPOINTS]; diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index f4c44eb..98acb3a 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1666,7 +1666,7 @@ static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) udc = to_gadget_udc(_gadget); if (udc->transceiver) - return otg_set_power(udc->transceiver, mA); + return usb_phy_set_power(udc->transceiver, mA); return -EOPNOTSUPP; } @@ -1835,7 +1835,8 @@ static int pxa27x_udc_start(struct usb_gadget_driver *driver, driver->driver.name); if (udc->transceiver) { - retval = otg_set_peripheral(udc->transceiver, &udc->gadget); + retval = otg_set_peripheral(udc->transceiver->otg, + &udc->gadget); if (retval) { dev_err(udc->dev, "can't bind to transceiver\n"); goto transceiver_fail; @@ -1908,7 +1909,7 @@ static int pxa27x_udc_stop(struct usb_gadget_driver *driver) driver->driver.name); if (udc->transceiver) - return otg_set_peripheral(udc->transceiver, NULL); + return otg_set_peripheral(udc->transceiver->otg, NULL); return 0; } @@ -2463,7 +2464,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) udc->dev = &pdev->dev; udc->mach = pdev->dev.platform_data; - udc->transceiver = otg_get_transceiver(); + udc->transceiver = usb_get_transceiver(); gpio = udc->mach->gpio_pullup; if (gpio_is_valid(gpio)) { @@ -2542,7 +2543,7 @@ static int __exit pxa_udc_remove(struct platform_device *_dev) if (gpio_is_valid(gpio)) gpio_free(gpio); - otg_put_transceiver(udc->transceiver); + usb_put_transceiver(udc->transceiver); udc->transceiver = NULL; platform_set_drvdata(_dev, NULL); diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index 7f4e8f4..a1d268c 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -447,7 +447,7 @@ struct pxa_udc { struct usb_gadget_driver *driver; struct device *dev; struct pxa2xx_udc_mach_info *mach; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; enum ep0_state ep0state; struct udc_stats stats; diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index ace95f9..cef9b82 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -146,7 +146,7 @@ struct s3c_hsudc { struct usb_gadget_driver *driver; struct device *dev; struct s3c24xx_hsudc_platdata *pd; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsudc_supply_names)]; spinlock_t lock; void __iomem *regs; @@ -1169,7 +1169,8 @@ static int s3c_hsudc_start(struct usb_gadget *gadget, /* connect to bus through transceiver */ if (hsudc->transceiver) { - ret = otg_set_peripheral(hsudc->transceiver, &hsudc->gadget); + ret = otg_set_peripheral(hsudc->transceiver->otg, + &hsudc->gadget); if (ret) { dev_err(hsudc->dev, "%s: can't bind to transceiver\n", hsudc->gadget.name); @@ -1223,7 +1224,7 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget, spin_unlock_irqrestore(&hsudc->lock, flags); if (hsudc->transceiver) - (void) otg_set_peripheral(hsudc->transceiver, NULL); + (void) otg_set_peripheral(hsudc->transceiver->otg, NULL); disable_irq(hsudc->irq); @@ -1252,7 +1253,7 @@ static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA) return -ENODEV; if (hsudc->transceiver) - return otg_set_power(hsudc->transceiver, mA); + return usb_phy_set_power(hsudc->transceiver, mA); return -EOPNOTSUPP; } @@ -1284,7 +1285,7 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev) hsudc->dev = dev; hsudc->pd = pdev->dev.platform_data; - hsudc->transceiver = otg_get_transceiver(); + hsudc->transceiver = usb_get_transceiver(); for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++) hsudc->supplies[i].supply = s3c_hsudc_supply_names[i]; @@ -1388,7 +1389,7 @@ err_remap: release_mem_region(res->start, resource_size(res)); err_res: if (hsudc->transceiver) - otg_put_transceiver(hsudc->transceiver); + usb_put_transceiver(hsudc->transceiver); regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies); err_supplies: diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index 9d450fe..8081ca3 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -145,48 +145,8 @@ #endif /* DUMP_MSGS */ - - - - /*-------------------------------------------------------------------------*/ -/* Bulk-only data structures */ - -/* Command Block Wrapper */ -struct fsg_bulk_cb_wrap { - __le32 Signature; /* Contains 'USBC' */ - u32 Tag; /* Unique per command id */ - __le32 DataTransferLength; /* Size of the data */ - u8 Flags; /* Direction in bit 7 */ - u8 Lun; /* LUN (normally 0) */ - u8 Length; /* Of the CDB, <= MAX_COMMAND_SIZE */ - u8 CDB[16]; /* Command Data Block */ -}; - -#define USB_BULK_CB_WRAP_LEN 31 -#define USB_BULK_CB_SIG 0x43425355 /* Spells out USBC */ -#define USB_BULK_IN_FLAG 0x80 - -/* Command Status Wrapper */ -struct bulk_cs_wrap { - __le32 Signature; /* Should = 'USBS' */ - u32 Tag; /* Same as original command */ - __le32 Residue; /* Amount not transferred */ - u8 Status; /* See below */ -}; - -#define USB_BULK_CS_WRAP_LEN 13 -#define USB_BULK_CS_SIG 0x53425355 /* Spells out 'USBS' */ -#define USB_STATUS_PASS 0 -#define USB_STATUS_FAIL 1 -#define USB_STATUS_PHASE_ERROR 2 - -/* Bulk-only class specific requests */ -#define USB_BULK_RESET_REQUEST 0xff -#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe - - /* CBI Interrupt data structure */ struct interrupt_data { u8 bType; @@ -598,16 +558,16 @@ static __maybe_unused struct usb_ss_cap_descriptor fsg_ss_cap_desc = { | USB_5GBPS_OPERATION), .bFunctionalitySupport = USB_LOW_SPEED_OPERATION, .bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT, - .bU2DevExitLat = USB_DEFAULT_U2_DEV_EXIT_LAT, + .bU2DevExitLat = cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT), }; static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = { .bLength = USB_DT_BOS_SIZE, .bDescriptorType = USB_DT_BOS, - .wTotalLength = USB_DT_BOS_SIZE + .wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE + USB_DT_USB_EXT_CAP_SIZE - + USB_DT_USB_SS_CAP_SIZE, + + USB_DT_USB_SS_CAP_SIZE), .bNumDeviceCaps = 2, }; diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 91413ca..dd04517 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -130,7 +130,7 @@ config USB_FSL_MPH_DR_OF tristate config USB_EHCI_FSL - bool "Support for Freescale on-chip EHCI USB controller" + bool "Support for Freescale PPC on-chip EHCI USB controller" depends on USB_EHCI_HCD && FSL_SOC select USB_EHCI_ROOT_HUB_TT select USB_FSL_MPH_DR_OF if OF @@ -138,7 +138,7 @@ config USB_EHCI_FSL Variation of ARC USB block used in some Freescale chips. config USB_EHCI_MXC - bool "Support for Freescale on-chip EHCI USB controller" + bool "Support for Freescale i.MX on-chip EHCI USB controller" depends on USB_EHCI_HCD && ARCH_MXC select USB_EHCI_ROOT_HUB_TT ---help--- @@ -196,7 +196,7 @@ config USB_EHCI_S5P config USB_EHCI_MV bool "EHCI support for Marvell on-chip controller" - depends on USB_EHCI_HCD + depends on USB_EHCI_HCD && (ARCH_PXA || ARCH_MMP) select USB_EHCI_ROOT_HUB_TT ---help--- Enables support for Marvell (including PXA and MMP series) on-chip @@ -546,7 +546,7 @@ config USB_RENESAS_USBHS_HCD config USB_WHCI_HCD tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)" depends on EXPERIMENTAL - depends on PCI && USB + depends on PCI && USB && UWB select USB_WUSB select UWB_WHCI help @@ -559,7 +559,7 @@ config USB_WHCI_HCD config USB_HWA_HCD tristate "Host Wire Adapter (HWA) driver (EXPERIMENTAL)" depends on EXPERIMENTAL - depends on USB + depends on USB && UWB select USB_WUSB select UWB_HWA help @@ -606,10 +606,3 @@ config USB_OCTEON_OHCI config USB_OCTEON2_COMMON bool default y if USB_OCTEON_EHCI || USB_OCTEON_OHCI - -config USB_PXA168_EHCI - bool "Marvell PXA168 on-chip EHCI HCD support" - depends on USB_EHCI_HCD && ARCH_MMP - help - Enable support for Marvell PXA168 SoC's on-chip EHCI - host controller diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index d6d74d2..fd9109d 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -107,7 +107,7 @@ static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) HCC_PER_PORT_CHANGE_EVENT(params) ? " ppce" : "", HCC_HW_PREFETCH(params) ? " hw prefetch" : "", HCC_32FRAME_PERIODIC_LIST(params) ? - " 32 peridic list" : ""); + " 32 periodic list" : ""); } } #else diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index e90344a..cf56667 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -125,7 +125,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, */ if (pdata->init && pdata->init(pdev)) { retval = -ENODEV; - goto err3; + goto err4; } /* Enable USB controller, 83xx or 8536 */ @@ -142,12 +142,12 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, if (pdata->operating_mode == FSL_USB2_DR_OTG) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - ehci->transceiver = otg_get_transceiver(); + ehci->transceiver = usb_get_transceiver(); dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, transceiver=0x%p\n", hcd, ehci, ehci->transceiver); if (ehci->transceiver) { - retval = otg_set_host(ehci->transceiver, + retval = otg_set_host(ehci->transceiver->otg, &ehci_to_hcd(ehci)->self); if (retval) { if (ehci->transceiver) @@ -194,7 +194,7 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd, struct ehci_hcd *ehci = hcd_to_ehci(hcd); if (ehci->transceiver) { - otg_set_host(ehci->transceiver, NULL); + otg_set_host(ehci->transceiver->otg, NULL); put_device(ehci->transceiver->dev); } @@ -216,6 +216,8 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, unsigned int port_offset) { u32 portsc; + struct usb_hcd *hcd = ehci_to_hcd(ehci); + void __iomem *non_ehci = hcd->regs; portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]); portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW); @@ -231,6 +233,8 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, portsc |= PORT_PTS_PTW; /* fall through */ case FSL_USB2_PHY_UTMI: + /* enable UTMI PHY */ + setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN); portsc |= PORT_PTS_UTMI; break; case FSL_USB2_PHY_NONE: @@ -239,7 +243,7 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); } -static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) +static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) { struct usb_hcd *hcd = ehci_to_hcd(ehci); struct fsl_usb2_platform_data *pdata; @@ -252,21 +256,18 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) if (pdata->have_sysif_regs) { temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004); - out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b); - } -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - /* - * Turn on cache snooping hardware, since some PowerPC platforms - * wholly rely on hardware to deal with cache coherent - */ + /* + * Turn on cache snooping hardware, since some PowerPC platforms + * wholly rely on hardware to deal with cache coherent + */ - /* Setup Snooping for all the 4GB space */ - /* SNOOP1 starts from 0x0, size 2G */ - out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB); - /* SNOOP2 starts from 0x80000000, size 2G */ - out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB); -#endif + /* Setup Snooping for all the 4GB space */ + /* SNOOP1 starts from 0x0, size 2G */ + out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB); + /* SNOOP2 starts from 0x80000000, size 2G */ + out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB); + } if ((pdata->operating_mode == FSL_USB2_DR_HOST) || (pdata->operating_mode == FSL_USB2_DR_OTG)) @@ -299,12 +300,19 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) #endif out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); } + + if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & CTRL_PHY_CLK_VALID)) { + printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n"); + return -ENODEV; + } + return 0; } /* called after powerup, by probe or system-pm "wakeup" */ static int ehci_fsl_reinit(struct ehci_hcd *ehci) { - ehci_fsl_usb_setup(ehci); + if (ehci_fsl_usb_setup(ehci)) + return -ENODEV; ehci_port_power(ehci, 0); return 0; @@ -316,7 +324,9 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; struct fsl_usb2_platform_data *pdata; + struct device *dev; + dev = hcd->self.controller; pdata = hcd->self.controller->platform_data; ehci->big_endian_desc = pdata->big_endian_desc; ehci->big_endian_mmio = pdata->big_endian_mmio; @@ -346,6 +356,16 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) ehci_reset(ehci); + if (of_device_is_compatible(dev->parent->of_node, + "fsl,mpc5121-usb2-dr")) { + /* + * set SBUSCFG:AHBBRST so that control msgs don't + * fail when doing heavy PATA writes. + */ + ehci_writel(ehci, SBUSCFG_INCR8, + hcd->regs + FSL_SOC_USB_SBUSCFG); + } + retval = ehci_fsl_reinit(ehci); return retval; } @@ -469,6 +489,8 @@ static int ehci_fsl_mpc512x_drv_resume(struct device *dev) ehci_writel(ehci, ISIPHYCTRL_PXE | ISIPHYCTRL_PHYE, hcd->regs + FSL_SOC_USB_ISIPHYCTRL); + ehci_writel(ehci, SBUSCFG_INCR8, hcd->regs + FSL_SOC_USB_SBUSCFG); + /* restore EHCI registers */ ehci_writel(ehci, pdata->pm_command, &ehci->regs->command); ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable); diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index 4918062..863fb0c 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -19,6 +19,8 @@ #define _EHCI_FSL_H /* offsets for the non-ehci registers in the FSL SOC USB controller */ +#define FSL_SOC_USB_SBUSCFG 0x90 +#define SBUSCFG_INCR8 0x02 /* INCR8, specified */ #define FSL_SOC_USB_ULPIVP 0x170 #define FSL_SOC_USB_PORTSC1 0x184 #define PORT_PTS_MSK (3<<30) @@ -45,5 +47,7 @@ #define FSL_SOC_USB_PRICTRL 0x40c /* NOTE: big-endian */ #define FSL_SOC_USB_SICTRL 0x410 /* NOTE: big-endian */ #define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */ +#define CTRL_UTMI_PHY_EN (1<<9) +#define CTRL_PHY_CLK_VALID (1 << 17) #define SNOOP_SIZE_2GB 0x1e #endif /* _EHCI_FSL_H */ diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a007a9f..06e2548 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1361,11 +1361,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_grlib_driver #endif -#ifdef CONFIG_USB_PXA168_EHCI -#include "ehci-pxa168.c" -#define PLATFORM_DRIVER ehci_pxa168_driver -#endif - #ifdef CONFIG_CPU_XLR #include "ehci-xls.c" #define PLATFORM_DRIVER ehci_xls_driver @@ -1376,6 +1371,11 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_mv_driver #endif +#ifdef CONFIG_MACH_LOONGSON1 +#include "ehci-ls1x.c" +#define PLATFORM_DRIVER ehci_ls1x_driver +#endif + #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ !defined(XILINX_OF_PLATFORM_DRIVER) diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 77bbb23..256fbd4 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -107,7 +107,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) ehci->owned_ports = 0; } -static int ehci_port_change(struct ehci_hcd *ehci) +static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci) { int i = HCS_N_PORTS(ehci->hcs_params); @@ -727,7 +727,7 @@ static int ehci_hub_control ( #ifdef CONFIG_USB_OTG if ((hcd->self.otg_port == (wIndex + 1)) && hcd->self.b_hnp_enable) { - otg_start_hnp(ehci->transceiver); + otg_start_hnp(ehci->transceiver->otg); break; } #endif @@ -1076,7 +1076,8 @@ error_exit: return retval; } -static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) +static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd, + int portnum) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -1085,7 +1086,8 @@ static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) set_owner(ehci, --portnum, PORT_OWNER); } -static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum) +static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd, + int portnum) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); u32 __iomem *reg; diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c new file mode 100644 index 0000000..a283e59 --- /dev/null +++ b/drivers/usb/host/ehci-ls1x.c @@ -0,0 +1,159 @@ +/* + * Bus Glue for Loongson LS1X built-in EHCI controller. + * + * Copyright (c) 2012 Zhang, Keguang <keguang.zhang@gmail.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + + +#include <linux/platform_device.h> + +static int ehci_ls1x_reset(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int ret; + + ehci->caps = hcd->regs; + + ret = ehci_setup(hcd); + if (ret) + return ret; + + ehci_port_power(ehci, 0); + + return 0; +} + +static const struct hc_driver ehci_ls1x_hc_driver = { + .description = hcd_name, + .product_desc = "LOONGSON1 EHCI", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + */ + .reset = ehci_ls1x_reset, + .start = ehci_run, + .stop = ehci_stop, + .shutdown = ehci_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, + .endpoint_reset = ehci_endpoint_reset, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, + .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, + + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, +}; + +static int ehci_hcd_ls1x_probe(struct platform_device *pdev) +{ + struct usb_hcd *hcd; + struct resource *res; + int irq; + int ret; + + pr_debug("initializing loongson1 ehci USB Controller\n"); + + if (usb_disabled()) + return -ENODEV; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, + "Found HC with no IRQ. Check %s setup!\n", + dev_name(&pdev->dev)); + return -ENODEV; + } + irq = res->start; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, + "Found HC with no register addr. Check %s setup!\n", + dev_name(&pdev->dev)); + return -ENODEV; + } + + hcd = usb_create_hcd(&ehci_ls1x_hc_driver, &pdev->dev, + dev_name(&pdev->dev)); + if (!hcd) + return -ENOMEM; + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + dev_dbg(&pdev->dev, "controller already in use\n"); + ret = -EBUSY; + goto err_put_hcd; + } + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (hcd->regs == NULL) { + dev_dbg(&pdev->dev, "error mapping memory\n"); + ret = -EFAULT; + goto err_release_region; + } + + ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); + if (ret) + goto err_iounmap; + + return ret; + +err_iounmap: + iounmap(hcd->regs); +err_release_region: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +err_put_hcd: + usb_put_hcd(hcd); + return ret; +} + +static int ehci_hcd_ls1x_remove(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + + usb_remove_hcd(hcd); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); + + return 0; +} + +static struct platform_driver ehci_ls1x_driver = { + .probe = ehci_hcd_ls1x_probe, + .remove = ehci_hcd_ls1x_remove, + .shutdown = usb_hcd_platform_shutdown, + .driver = { + .name = "ls1x-ehci", + .owner = THIS_MODULE, + }, +}; + +MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ls1x-ehci"); diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 592d5f7..9803a55 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -32,7 +32,7 @@ #define MSM_USB_BASE (hcd->regs) -static struct otg_transceiver *otg; +static struct usb_phy *phy; static int ehci_msm_reset(struct usb_hcd *hcd) { @@ -145,14 +145,14 @@ static int ehci_msm_probe(struct platform_device *pdev) * powering up VBUS, mapping of registers address space and power * management. */ - otg = otg_get_transceiver(); - if (!otg) { + phy = usb_get_transceiver(); + if (!phy) { dev_err(&pdev->dev, "unable to find transceiver\n"); ret = -ENODEV; goto unmap; } - ret = otg_set_host(otg, &hcd->self); + ret = otg_set_host(phy->otg, &hcd->self); if (ret < 0) { dev_err(&pdev->dev, "unable to register with transceiver\n"); goto put_transceiver; @@ -169,7 +169,7 @@ static int ehci_msm_probe(struct platform_device *pdev) return 0; put_transceiver: - otg_put_transceiver(otg); + usb_put_transceiver(phy); unmap: iounmap(hcd->regs); put_hcd: @@ -186,8 +186,8 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); - otg_set_host(otg, NULL); - otg_put_transceiver(otg); + otg_set_host(phy->otg, NULL); + usb_put_transceiver(phy); usb_put_hcd(hcd); diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 52a604f..a936bbc 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -28,7 +28,7 @@ struct ehci_hcd_mv { void __iomem *cap_regs; void __iomem *op_regs; - struct otg_transceiver *otg; + struct usb_phy *otg; struct mv_usb_platform_data *pdata; @@ -253,7 +253,7 @@ static int mv_ehci_probe(struct platform_device *pdev) ehci_mv->mode = pdata->mode; if (ehci_mv->mode == MV_USB_MODE_OTG) { #ifdef CONFIG_USB_OTG_UTILS - ehci_mv->otg = otg_get_transceiver(); + ehci_mv->otg = usb_get_transceiver(); if (!ehci_mv->otg) { dev_err(&pdev->dev, "unable to find transceiver\n"); @@ -261,7 +261,7 @@ static int mv_ehci_probe(struct platform_device *pdev) goto err_disable_clk; } - retval = otg_set_host(ehci_mv->otg, &hcd->self); + retval = otg_set_host(ehci_mv->otg->otg, &hcd->self); if (retval < 0) { dev_err(&pdev->dev, "unable to register with transceiver\n"); @@ -303,7 +303,7 @@ err_set_vbus: #ifdef CONFIG_USB_OTG_UTILS err_put_transceiver: if (ehci_mv->otg) - otg_put_transceiver(ehci_mv->otg); + usb_put_transceiver(ehci_mv->otg); #endif err_disable_clk: mv_ehci_disable(ehci_mv); @@ -332,8 +332,8 @@ static int mv_ehci_remove(struct platform_device *pdev) usb_remove_hcd(hcd); if (ehci_mv->otg) { - otg_set_host(ehci_mv->otg, NULL); - otg_put_transceiver(ehci_mv->otg); + otg_set_host(ehci_mv->otg->otg, NULL); + usb_put_transceiver(ehci_mv->otg); } if (ehci_mv->mode == MV_USB_MODE_HOST) { diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index 55978fc..a797d51 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -220,13 +220,13 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) /* Initialize the transceiver */ if (pdata->otg) { pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET; - ret = otg_init(pdata->otg); + ret = usb_phy_init(pdata->otg); if (ret) { dev_err(dev, "unable to init transceiver, probably missing\n"); ret = -ENODEV; goto err_add; } - ret = otg_set_vbus(pdata->otg, 1); + ret = otg_set_vbus(pdata->otg->otg, 1); if (ret) { dev_err(dev, "unable to enable vbus on transceiver\n"); goto err_add; @@ -247,9 +247,11 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) * It's in violation of USB specs */ if (machine_is_mx51_efikamx() || machine_is_mx51_efikasb()) { - flags = otg_io_read(pdata->otg, ULPI_OTG_CTRL); + flags = usb_phy_io_read(pdata->otg, + ULPI_OTG_CTRL); flags |= ULPI_OTG_CTRL_CHRGVBUS; - ret = otg_io_write(pdata->otg, flags, ULPI_OTG_CTRL); + ret = usb_phy_io_write(pdata->otg, flags, + ULPI_OTG_CTRL); if (ret) { dev_err(dev, "unable to set CHRVBUS\n"); goto err_add; @@ -297,7 +299,7 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) pdata->exit(pdev); if (pdata->otg) - otg_shutdown(pdata->otg); + usb_phy_shutdown(pdata->otg); usb_remove_hcd(hcd); iounmap(hcd->regs); diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index f4b627d..01bb7241d 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -276,6 +276,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* Serial Bus Release Number is at PCI 0x60 offset */ pci_read_config_byte(pdev, 0x60, &ehci->sbrn); + if (pdev->vendor == PCI_VENDOR_ID_STMICRO + && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST) + ehci->sbrn = 0x20; /* ConneXT has no sbrn register */ /* Keep this around for a while just in case some EHCI * implementation uses legacy PCI PM support. This test @@ -526,6 +529,9 @@ static const struct pci_device_id pci_ids [] = { { /* handle any USB 2.0 EHCI controller */ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0), .driver_data = (unsigned long) &ehci_pci_hc_driver, + }, { + PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_HOST), + .driver_data = (unsigned long) &ehci_pci_hc_driver, }, { /* end: all zeroes */ } }; diff --git a/drivers/usb/host/ehci-pxa168.c b/drivers/usb/host/ehci-pxa168.c deleted file mode 100644 index 8d0e7a2..0000000 --- a/drivers/usb/host/ehci-pxa168.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * drivers/usb/host/ehci-pxa168.c - * - * Tanmay Upadhyay <tanmay.upadhyay@einfochips.com> - * - * Based on drivers/usb/host/ehci-orion.c - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/clk.h> -#include <mach/pxa168.h> - -#define USB_PHY_CTRL_REG 0x4 -#define USB_PHY_PLL_REG 0x8 -#define USB_PHY_TX_REG 0xc - -#define FBDIV_SHIFT 4 - -#define ICP_SHIFT 12 -#define ICP_15 2 -#define ICP_20 3 -#define ICP_25 4 - -#define KVCO_SHIFT 15 - -#define PLLCALI12_SHIFT 25 -#define CALI12_VDD 0 -#define CALI12_09 1 -#define CALI12_10 2 -#define CALI12_11 3 - -#define PLLVDD12_SHIFT 27 -#define VDD12_VDD 0 -#define VDD12_10 1 -#define VDD12_11 2 -#define VDD12_12 3 - -#define PLLVDD18_SHIFT 29 -#define VDD18_19 0 -#define VDD18_20 1 -#define VDD18_21 2 -#define VDD18_22 3 - - -#define PLL_READY (1 << 23) -#define VCOCAL_START (1 << 21) -#define REG_RCAL_START (1 << 12) - -struct pxa168_usb_drv_data { - struct ehci_hcd ehci; - struct clk *pxa168_usb_clk; - struct resource *usb_phy_res; - void __iomem *usb_phy_reg_base; -}; - -static int ehci_pxa168_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; - - ehci_reset(ehci); - retval = ehci_halt(ehci); - if (retval) - return retval; - - /* - * data structure init - */ - retval = ehci_init(hcd); - if (retval) - return retval; - - hcd->has_tt = 1; - - ehci_port_power(ehci, 0); - - return retval; -} - -static const struct hc_driver ehci_pxa168_hc_driver = { - .description = hcd_name, - .product_desc = "Marvell PXA168 EHCI", - .hcd_priv_size = sizeof(struct pxa168_usb_drv_data), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - - /* - * basic lifecycle operations - */ - .reset = ehci_pxa168_setup, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; - -static int pxa168_usb_phy_init(struct platform_device *pdev) -{ - struct resource *res; - void __iomem *usb_phy_reg_base; - struct pxa168_usb_pdata *pdata; - struct pxa168_usb_drv_data *drv_data; - struct usb_hcd *hcd = platform_get_drvdata(pdev); - unsigned long reg_val; - int pll_retry_cont = 10000, err = 0; - - drv_data = (struct pxa168_usb_drv_data *)hcd->hcd_priv; - pdata = (struct pxa168_usb_pdata *)pdev->dev.platform_data; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res) { - dev_err(&pdev->dev, - "Found HC with no PHY register addr. Check %s setup!\n", - dev_name(&pdev->dev)); - return -ENODEV; - } - - if (!request_mem_region(res->start, resource_size(res), - ehci_pxa168_hc_driver.description)) { - dev_dbg(&pdev->dev, "controller already in use\n"); - return -EBUSY; - } - - usb_phy_reg_base = ioremap(res->start, resource_size(res)); - if (usb_phy_reg_base == NULL) { - dev_dbg(&pdev->dev, "error mapping memory\n"); - err = -EFAULT; - goto err1; - } - drv_data->usb_phy_reg_base = usb_phy_reg_base; - drv_data->usb_phy_res = res; - - /* If someone wants to init USB phy in board specific way */ - if (pdata && pdata->phy_init) - return pdata->phy_init(usb_phy_reg_base); - - /* Power up the PHY and PLL */ - writel(readl(usb_phy_reg_base + USB_PHY_CTRL_REG) | 0x3, - usb_phy_reg_base + USB_PHY_CTRL_REG); - - /* Configure PHY PLL */ - reg_val = readl(usb_phy_reg_base + USB_PHY_PLL_REG) & ~(0x7e03ffff); - reg_val |= (VDD18_22 << PLLVDD18_SHIFT | VDD12_12 << PLLVDD12_SHIFT | - CALI12_11 << PLLCALI12_SHIFT | 3 << KVCO_SHIFT | - ICP_15 << ICP_SHIFT | 0xee << FBDIV_SHIFT | 0xb); - writel(reg_val, usb_phy_reg_base + USB_PHY_PLL_REG); - - /* Make sure PHY PLL is ready */ - while (!(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & PLL_READY)) { - if (!(pll_retry_cont--)) { - dev_dbg(&pdev->dev, "USB PHY PLL not ready\n"); - err = -EIO; - goto err2; - } - } - - /* Toggle VCOCAL_START bit of U2PLL for PLL calibration */ - udelay(200); - writel(readl(usb_phy_reg_base + USB_PHY_PLL_REG) | VCOCAL_START, - usb_phy_reg_base + USB_PHY_PLL_REG); - udelay(40); - writel(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & ~VCOCAL_START, - usb_phy_reg_base + USB_PHY_PLL_REG); - - /* Toggle REG_RCAL_START bit of U2PTX for impedance calibration */ - udelay(400); - writel(readl(usb_phy_reg_base + USB_PHY_TX_REG) | REG_RCAL_START, - usb_phy_reg_base + USB_PHY_TX_REG); - udelay(40); - writel(readl(usb_phy_reg_base + USB_PHY_TX_REG) & ~REG_RCAL_START, - usb_phy_reg_base + USB_PHY_TX_REG); - - /* Make sure PHY PLL is ready again */ - pll_retry_cont = 0; - while (!(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & PLL_READY)) { - if (!(pll_retry_cont--)) { - dev_dbg(&pdev->dev, "USB PHY PLL not ready\n"); - err = -EIO; - goto err2; - } - } - - return 0; -err2: - iounmap(usb_phy_reg_base); -err1: - release_mem_region(res->start, resource_size(res)); - return err; -} - -static int __devinit ehci_pxa168_drv_probe(struct platform_device *pdev) -{ - struct resource *res; - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - struct pxa168_usb_drv_data *drv_data; - void __iomem *regs; - int irq, err = 0; - - if (usb_disabled()) - return -ENODEV; - - pr_debug("Initializing pxa168-SoC USB Host Controller\n"); - - irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(&pdev->dev, - "Found HC with no IRQ. Check %s setup!\n", - dev_name(&pdev->dev)); - err = -ENODEV; - goto err1; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, - "Found HC with no register addr. Check %s setup!\n", - dev_name(&pdev->dev)); - err = -ENODEV; - goto err1; - } - - if (!request_mem_region(res->start, resource_size(res), - ehci_pxa168_hc_driver.description)) { - dev_dbg(&pdev->dev, "controller already in use\n"); - err = -EBUSY; - goto err1; - } - - regs = ioremap(res->start, resource_size(res)); - if (regs == NULL) { - dev_dbg(&pdev->dev, "error mapping memory\n"); - err = -EFAULT; - goto err2; - } - - hcd = usb_create_hcd(&ehci_pxa168_hc_driver, - &pdev->dev, dev_name(&pdev->dev)); - if (!hcd) { - err = -ENOMEM; - goto err3; - } - - drv_data = (struct pxa168_usb_drv_data *)hcd->hcd_priv; - - /* Enable USB clock */ - drv_data->pxa168_usb_clk = clk_get(&pdev->dev, "PXA168-USBCLK"); - if (IS_ERR(drv_data->pxa168_usb_clk)) { - dev_err(&pdev->dev, "Couldn't get USB clock\n"); - err = PTR_ERR(drv_data->pxa168_usb_clk); - goto err4; - } - clk_enable(drv_data->pxa168_usb_clk); - - err = pxa168_usb_phy_init(pdev); - if (err) { - dev_err(&pdev->dev, "USB PHY initialization failed\n"); - goto err5; - } - - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - hcd->regs = regs; - - ehci = hcd_to_ehci(hcd); - ehci->caps = hcd->regs + 0x100; - ehci->regs = hcd->regs + 0x100 + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - hcd->has_tt = 1; - ehci->sbrn = 0x20; - - err = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED); - if (err) - goto err5; - - return 0; - -err5: - clk_disable(drv_data->pxa168_usb_clk); - clk_put(drv_data->pxa168_usb_clk); -err4: - usb_put_hcd(hcd); -err3: - iounmap(regs); -err2: - release_mem_region(res->start, resource_size(res)); -err1: - dev_err(&pdev->dev, "init %s fail, %d\n", - dev_name(&pdev->dev), err); - - return err; -} - -static int __exit ehci_pxa168_drv_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct pxa168_usb_drv_data *drv_data = - (struct pxa168_usb_drv_data *)hcd->hcd_priv; - - usb_remove_hcd(hcd); - - /* Power down PHY & PLL */ - writel(readl(drv_data->usb_phy_reg_base + USB_PHY_CTRL_REG) & (~0x3), - drv_data->usb_phy_reg_base + USB_PHY_CTRL_REG); - - clk_disable(drv_data->pxa168_usb_clk); - clk_put(drv_data->pxa168_usb_clk); - - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - - iounmap(drv_data->usb_phy_reg_base); - release_mem_region(drv_data->usb_phy_res->start, - resource_size(drv_data->usb_phy_res)); - - usb_put_hcd(hcd); - - return 0; -} - -MODULE_ALIAS("platform:pxa168-ehci"); - -static struct platform_driver ehci_pxa168_driver = { - .probe = ehci_pxa168_drv_probe, - .remove = __exit_p(ehci_pxa168_drv_remove), - .shutdown = usb_hcd_platform_shutdown, - .driver.name = "pxa168-ehci", -}; diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c index b115b0b..6e92855 100644 --- a/drivers/usb/host/ehci-spear.c +++ b/drivers/usb/host/ehci-spear.c @@ -11,8 +11,10 @@ * more details. */ -#include <linux/platform_device.h> #include <linux/clk.h> +#include <linux/jiffies.h> +#include <linux/platform_device.h> +#include <linux/pm.h> struct spear_ehci { struct ehci_hcd ehci; @@ -90,6 +92,82 @@ static const struct hc_driver ehci_spear_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; +#ifdef CONFIG_PM +static int ehci_spear_drv_suspend(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + unsigned long flags; + int rc = 0; + + if (time_before(jiffies, ehci->next_statechange)) + msleep(10); + + /* + * Root hub was already suspended. Disable irq emission and mark HW + * unaccessible. The PM and USB cores make sure that the root hub is + * either suspended or stopped. + */ + spin_lock_irqsave(&ehci->lock, flags); + ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); + ehci_writel(ehci, 0, &ehci->regs->intr_enable); + ehci_readl(ehci, &ehci->regs->intr_enable); + spin_unlock_irqrestore(&ehci->lock, flags); + + return rc; +} + +static int ehci_spear_drv_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + + if (time_before(jiffies, ehci->next_statechange)) + msleep(100); + + if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { + int mask = INTR_MASK; + + ehci_prepare_ports_for_controller_resume(ehci); + + if (!hcd->self.root_hub->do_remote_wakeup) + mask &= ~STS_PCD; + + ehci_writel(ehci, mask, &ehci->regs->intr_enable); + ehci_readl(ehci, &ehci->regs->intr_enable); + return 0; + } + + usb_root_hub_lost_power(hcd->self.root_hub); + + /* + * Else reset, to cope with power loss or flush-to-storage style + * "resume" having let BIOS kick in during reboot. + */ + ehci_halt(ehci); + ehci_reset(ehci); + + /* emptying the schedule aborts any urbs */ + spin_lock_irq(&ehci->lock); + if (ehci->reclaim) + end_unlink_async(ehci); + + ehci_work(ehci); + spin_unlock_irq(&ehci->lock); + + ehci_writel(ehci, ehci->command, &ehci->regs->command); + ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); + ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ + + /* here we "know" root ports should always stay powered */ + ehci_port_power(ehci, 1); + return 0; +} +#endif /* CONFIG_PM */ + +static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend, + ehci_spear_drv_resume); + static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd ; @@ -205,7 +283,8 @@ static struct platform_driver spear_ehci_hcd_driver = { .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "spear-ehci", - .bus = &platform_bus_type + .bus = &platform_bus_type, + .pm = &ehci_spear_pm_ops, } }; diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index dbc7fe8..3de48a2 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -35,7 +35,7 @@ struct tegra_ehci_hcd { struct tegra_usb_phy *phy; struct clk *clk; struct clk *emc_clk; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; int host_resumed; int bus_suspended; int port_resuming; @@ -733,9 +733,9 @@ static int tegra_ehci_probe(struct platform_device *pdev) #ifdef CONFIG_USB_OTG_UTILS if (pdata->operating_mode == TEGRA_USB_OTG) { - tegra->transceiver = otg_get_transceiver(); + tegra->transceiver = usb_get_transceiver(); if (tegra->transceiver) - otg_set_host(tegra->transceiver, &hcd->self); + otg_set_host(tegra->transceiver->otg, &hcd->self); } #endif @@ -750,8 +750,8 @@ static int tegra_ehci_probe(struct platform_device *pdev) fail: #ifdef CONFIG_USB_OTG_UTILS if (tegra->transceiver) { - otg_set_host(tegra->transceiver, NULL); - otg_put_transceiver(tegra->transceiver); + otg_set_host(tegra->transceiver->otg, NULL); + usb_put_transceiver(tegra->transceiver); } #endif tegra_usb_phy_close(tegra->phy); @@ -808,8 +808,8 @@ static int tegra_ehci_remove(struct platform_device *pdev) #ifdef CONFIG_USB_OTG_UTILS if (tegra->transceiver) { - otg_set_host(tegra->transceiver, NULL); - otg_put_transceiver(tegra->transceiver); + otg_set_host(tegra->transceiver->otg, NULL); + usb_put_transceiver(tegra->transceiver); } #endif diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 0a5fda7..8f9acbc 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -176,7 +176,7 @@ struct ehci_hcd { /* one per controller */ /* * OTG controllers and transceivers need software interaction */ - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 7916e56..ab333ac 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -94,7 +94,6 @@ struct platform_device * __devinit fsl_usb2_device_register( pdev->dev.parent = &ofdev->dev; pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask; - pdev->dev.dma_mask = &pdev->archdata.dma_mask; *pdev->dev.dma_mask = *ofdev->dev.dma_mask; retval = platform_device_add_data(pdev, pdata, sizeof(*pdata)); diff --git a/drivers/usb/host/imx21-dbg.c b/drivers/usb/host/imx21-dbg.c index 6d75334..ec98ece 100644 --- a/drivers/usb/host/imx21-dbg.c +++ b/drivers/usb/host/imx21-dbg.c @@ -239,7 +239,7 @@ static int debug_status_show(struct seq_file *s, void *v) "ETDs allocated: %d/%d (max=%d)\n" "ETDs in use sw: %d\n" "ETDs in use hw: %d\n" - "DMEM alocated: %d/%d (max=%d)\n" + "DMEM allocated: %d/%d (max=%d)\n" "DMEM blocks: %d\n" "Queued waiting for ETD: %d\n" "Queued waiting for DMEM: %d\n", diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index e5fd8aa..9e63cdf 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2693,6 +2693,9 @@ static int __devinit isp1362_probe(struct platform_device *pdev) struct resource *irq_res; unsigned int irq_flags = 0; + if (usb_disabled()) + return -ENODEV; + /* basic sanity checks first. board-specific init logic should * have initialized this the three resources and probably board * specific platform_data. we don't probe for IRQs, and do only @@ -2864,19 +2867,4 @@ static struct platform_driver isp1362_driver = { }, }; -/*-------------------------------------------------------------------------*/ - -static int __init isp1362_init(void) -{ - if (usb_disabled()) - return -ENODEV; - pr_info("driver %s, %s\n", hcd_name, DRIVER_VERSION); - return platform_driver_register(&isp1362_driver); -} -module_init(isp1362_init); - -static void __exit isp1362_cleanup(void) -{ - platform_driver_unregister(&isp1362_driver); -} -module_exit(isp1362_cleanup); +module_platform_driver(isp1362_driver); diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 5df0b0e..77afabc 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -139,8 +139,23 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, } iclk = clk_get(&pdev->dev, "ohci_clk"); + if (IS_ERR(iclk)) { + dev_err(&pdev->dev, "failed to get ohci_clk\n"); + retval = PTR_ERR(iclk); + goto err3; + } fclk = clk_get(&pdev->dev, "uhpck"); + if (IS_ERR(fclk)) { + dev_err(&pdev->dev, "failed to get uhpck\n"); + retval = PTR_ERR(fclk); + goto err4; + } hclk = clk_get(&pdev->dev, "hclk"); + if (IS_ERR(hclk)) { + dev_err(&pdev->dev, "failed to get hclk\n"); + retval = PTR_ERR(hclk); + goto err5; + } at91_start_hc(pdev); ohci_hcd_init(hcd_to_ohci(hcd)); @@ -153,9 +168,12 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, at91_stop_hc(pdev); clk_put(hclk); + err5: clk_put(fclk); + err4: clk_put(iclk); + err3: iounmap(hcd->regs); err2: @@ -226,7 +244,8 @@ static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int if (!gpio_is_valid(pdata->vbus_pin[port])) return; - gpio_set_value(pdata->vbus_pin[port], !pdata->vbus_pin_inverted ^ enable); + gpio_set_value(pdata->vbus_pin[port], + !pdata->vbus_pin_active_low[port] ^ enable); } static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) @@ -237,7 +256,8 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) if (!gpio_is_valid(pdata->vbus_pin[port])) return -EINVAL; - return gpio_get_value(pdata->vbus_pin[port]) ^ !pdata->vbus_pin_inverted; + return gpio_get_value(pdata->vbus_pin[port]) ^ + !pdata->vbus_pin_active_low[port]; } /* diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 5179fcd..e4bcb62 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -82,6 +82,14 @@ urb_print(struct urb * urb, char * str, int small, int status) ohci_dbg(ohci,format, ## arg ); \ } while (0); +/* Version for use where "next" is the address of a local variable */ +#define ohci_dbg_nosw(ohci, next, size, format, arg...) \ + do { \ + unsigned s_len; \ + s_len = scnprintf(*next, *size, format, ## arg); \ + *size -= s_len; *next += s_len; \ + } while (0); + static void ohci_dump_intr_mask ( struct ohci_hcd *ohci, @@ -653,7 +661,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) /* dump driver info, then registers in spec order */ - ohci_dbg_sw (ohci, &next, &size, + ohci_dbg_nosw(ohci, &next, &size, "bus %s, device %s\n" "%s\n" "%s\n", @@ -672,7 +680,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) /* hcca */ if (ohci->hcca) - ohci_dbg_sw (ohci, &next, &size, + ohci_dbg_nosw(ohci, &next, &size, "hcca frame 0x%04x\n", ohci_frame_no(ohci)); /* other registers mostly affect frame timings */ diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index 55aa35a..37bb20e 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -212,12 +212,10 @@ static int exynos_ohci_suspend(struct device *dev) * mark HW unaccessible, bail out if RH has been resumed. Use * the spinlock to properly synchronize with possible pending * RH suspend or resume activity. - * - * This is still racy as hcd->state is manipulated outside of - * any locks =P But that will be a different fix. */ spin_lock_irqsave(&ohci->lock, flags); - if (hcd->state != HC_STATE_SUSPENDED && hcd->state != HC_STATE_HALT) { + if (ohci->rh_state != OHCI_RH_SUSPENDED && + ohci->rh_state != OHCI_RH_HALTED) { rc = -EINVAL; goto fail; } diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index db39686..96451e4 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -171,7 +171,7 @@ static void start_hnp(struct ohci_hcd *ohci) unsigned long flags; u32 l; - otg_start_hnp(ohci->transceiver); + otg_start_hnp(ohci->transceiver->otg); local_irq_save(flags); ohci->transceiver->state = OTG_STATE_A_SUSPEND; @@ -210,9 +210,9 @@ static int ohci_omap_init(struct usb_hcd *hcd) #ifdef CONFIG_USB_OTG if (need_transceiver) { - ohci->transceiver = otg_get_transceiver(); + ohci->transceiver = usb_get_transceiver(); if (ohci->transceiver) { - int status = otg_set_host(ohci->transceiver, + int status = otg_set_host(ohci->transceiver->otg, &ohci_to_hcd(ohci)->self); dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n", ohci->transceiver->label, status); @@ -404,7 +404,7 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) usb_remove_hcd(hcd); if (ohci->transceiver) { - (void) otg_set_host(ohci->transceiver, 0); + (void) otg_set_host(ohci->transceiver->otg, 0); put_device(ohci->transceiver->dev); } if (machine_is_omap_osk()) diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 6109810..1843bb6 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -397,6 +397,10 @@ static const struct pci_device_id pci_ids [] = { { /* handle any USB OHCI controller */ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0), .driver_data = (unsigned long) &ohci_pci_hc_driver, + }, { + /* The device in the ConneXT I/O hub has no class reg */ + PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_OHCI), + .driver_data = (unsigned long) &ohci_pci_hc_driver, }, { /* end: all zeroes */ } }; MODULE_DEVICE_TABLE (pci, pci_ids); diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 8ff6f7e..1b19aea 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -376,7 +376,7 @@ struct ohci_hcd { * OTG controllers and transceivers need software interaction; * other external transceivers should be software-transparent */ - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; void (*start_hnp)(struct ohci_hcd *ohci); /* diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index caf8742..7732d69 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -867,6 +867,22 @@ hc_init: static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) { + /* Skip Netlogic mips SoC's internal PCI USB controller. + * This device does not need/support EHCI/OHCI handoff + */ + if (pdev->vendor == 0x184e) /* vendor Netlogic */ + return; + if (pdev->class != PCI_CLASS_SERIAL_USB_UHCI && + pdev->class != PCI_CLASS_SERIAL_USB_OHCI && + pdev->class != PCI_CLASS_SERIAL_USB_EHCI && + pdev->class != PCI_CLASS_SERIAL_USB_XHCI) + return; + + if (pci_enable_device(pdev) < 0) { + dev_warn(&pdev->dev, "Can't enable PCI device, " + "BIOS handoff failed.\n"); + return; + } if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI) quirk_usb_handoff_uhci(pdev); else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI) @@ -875,5 +891,6 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) quirk_usb_disable_ehci(pdev); else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI) quirk_usb_handoff_xhci(pdev); + pci_disable_device(pdev); } DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 6b5eb10..e37dea8 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -565,6 +565,9 @@ static int uhci_start(struct usb_hcd *hcd) struct dentry __maybe_unused *dentry; hcd->uses_new_polling = 1; + /* Accept arbitrarily long scatter-gather lists */ + if (!(hcd->driver->flags & HCD_LOCAL_MEM)) + hcd->self.sg_tablesize = ~0; spin_lock_init(&uhci->lock); setup_timer(&uhci->fsbr_timer, uhci_fsbr_timeout, diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 35e257f..673ad12 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -93,7 +93,7 @@ static void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, */ memset(port_removable, 0, sizeof(port_removable)); for (i = 0; i < ports; i++) { - portsc = xhci_readl(xhci, xhci->usb3_ports[i]); + portsc = xhci_readl(xhci, xhci->usb2_ports[i]); /* If a device is removable, PORTSC reports a 0, same as in the * hub descriptor DeviceRemovable bits. */ @@ -422,6 +422,32 @@ void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, xhci_writel(xhci, temp, port_array[port_id]); } +void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, + __le32 __iomem **port_array, int port_id, u16 wake_mask) +{ + u32 temp; + + temp = xhci_readl(xhci, port_array[port_id]); + temp = xhci_port_state_to_neutral(temp); + + if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_CONNECT) + temp |= PORT_WKCONN_E; + else + temp &= ~PORT_WKCONN_E; + + if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT) + temp |= PORT_WKDISC_E; + else + temp &= ~PORT_WKDISC_E; + + if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT) + temp |= PORT_WKOC_E; + else + temp &= ~PORT_WKOC_E; + + xhci_writel(xhci, temp, port_array[port_id]); +} + /* Test and clear port RWC bit */ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, int port_id, u32 port_bit) @@ -448,6 +474,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, int slot_id; struct xhci_bus_state *bus_state; u16 link_state = 0; + u16 wake_mask = 0; max_ports = xhci_get_ports(hcd, &port_array); bus_state = &xhci->bus_state[hcd_index(hcd)]; @@ -593,6 +620,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, case SetPortFeature: if (wValue == USB_PORT_FEAT_LINK_STATE) link_state = (wIndex & 0xff00) >> 3; + if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK) + wake_mask = wIndex & 0xff00; wIndex &= 0xff; if (!wIndex || wIndex > max_ports) goto error; @@ -703,6 +732,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = xhci_readl(xhci, port_array[wIndex]); xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp); break; + case USB_PORT_FEAT_REMOTE_WAKE_MASK: + xhci_set_remote_wake_mask(xhci, port_array, + wIndex, wake_mask); + temp = xhci_readl(xhci, port_array[wIndex]); + xhci_dbg(xhci, "set port remote wake mask, " + "actual port %d status = 0x%x\n", + wIndex, temp); + break; case USB_PORT_FEAT_BH_PORT_RESET: temp |= PORT_WR; xhci_writel(xhci, temp, port_array[wIndex]); @@ -883,6 +920,10 @@ int xhci_bus_suspend(struct usb_hcd *hcd) t2 |= PORT_LINK_STROBE | XDEV_U3; set_bit(port_index, &bus_state->bus_suspended); } + /* USB core sets remote wake mask for USB 3.0 hubs, + * including the USB 3.0 roothub, but only if CONFIG_USB_SUSPEND + * is enabled, so also enable remote wake here. + */ if (hcd->self.root_hub->do_remote_wakeup) { if (t1 & PORT_CONNECT) { t2 |= PORT_WKOC_E | PORT_WKDISC_E; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 36cbe22..8339d82 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1126,26 +1126,42 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev, } /* - * Convert bInterval expressed in frames (in 1-255 range) to exponent of + * Convert bInterval expressed in microframes (in 1-255 range) to exponent of * microframes, rounded down to nearest power of 2. */ -static unsigned int xhci_parse_frame_interval(struct usb_device *udev, - struct usb_host_endpoint *ep) +static unsigned int xhci_microframes_to_exponent(struct usb_device *udev, + struct usb_host_endpoint *ep, unsigned int desc_interval, + unsigned int min_exponent, unsigned int max_exponent) { unsigned int interval; - interval = fls(8 * ep->desc.bInterval) - 1; - interval = clamp_val(interval, 3, 10); - if ((1 << interval) != 8 * ep->desc.bInterval) + interval = fls(desc_interval) - 1; + interval = clamp_val(interval, min_exponent, max_exponent); + if ((1 << interval) != desc_interval) dev_warn(&udev->dev, "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n", ep->desc.bEndpointAddress, 1 << interval, - 8 * ep->desc.bInterval); + desc_interval); return interval; } +static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, + struct usb_host_endpoint *ep) +{ + return xhci_microframes_to_exponent(udev, ep, + ep->desc.bInterval, 0, 15); +} + + +static unsigned int xhci_parse_frame_interval(struct usb_device *udev, + struct usb_host_endpoint *ep) +{ + return xhci_microframes_to_exponent(udev, ep, + ep->desc.bInterval * 8, 3, 10); +} + /* Return the polling or NAK interval. * * The polling interval is expressed in "microframes". If xHCI's Interval field @@ -1164,7 +1180,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev, /* Max NAK rate */ if (usb_endpoint_xfer_control(&ep->desc) || usb_endpoint_xfer_bulk(&ep->desc)) { - interval = ep->desc.bInterval; + interval = xhci_parse_microframe_interval(udev, ep); break; } /* Fall through - SS and HS isoc/int have same decoding */ @@ -2141,7 +2157,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) unsigned int val, val2; u64 val_64; struct xhci_segment *seg; - u32 page_size; + u32 page_size, temp; int i; page_size = xhci_readl(xhci, &xhci->op_regs->page_size); @@ -2324,6 +2340,15 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) INIT_LIST_HEAD(&xhci->lpm_failed_devs); + /* Enable USB 3.0 device notifications for function remote wake, which + * is necessary for allowing USB 3.0 devices to do remote wakeup from + * U3 (device suspend). + */ + temp = xhci_readl(xhci, &xhci->op_regs->dev_notification); + temp &= ~DEV_NOTE_MASK; + temp |= DEV_NOTE_FWAKE; + xhci_writel(xhci, temp, &xhci->op_regs->dev_notification); + return 0; fail: diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b90e138..3a03324 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1204,6 +1204,7 @@ static void handle_vendor_event(struct xhci_hcd *xhci, * * Returns a zero-based port number, which is suitable for indexing into each of * the split roothubs' port arrays and bus state arrays. + * Add one to it in order to call xhci_find_slot_id_by_port. */ static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd, struct xhci_hcd *xhci, u32 port_id) @@ -1236,6 +1237,26 @@ static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd, return num_similar_speed_ports; } +static void handle_device_notification(struct xhci_hcd *xhci, + union xhci_trb *event) +{ + u32 slot_id; + struct usb_device *udev; + + slot_id = TRB_TO_SLOT_ID(event->generic.field[3]); + if (!xhci->devs[slot_id]) { + xhci_warn(xhci, "Device Notification event for " + "unused slot %u\n", slot_id); + return; + } + + xhci_dbg(xhci, "Device Wake Notification event for slot ID %u\n", + slot_id); + udev = xhci->devs[slot_id]->udev; + if (udev && udev->parent) + usb_wakeup_notification(udev->parent, udev->portnum); +} + static void handle_port_status(struct xhci_hcd *xhci, union xhci_trb *event) { @@ -1320,20 +1341,21 @@ static void handle_port_status(struct xhci_hcd *xhci, } if (DEV_SUPERSPEED(temp)) { - xhci_dbg(xhci, "resume SS port %d\n", port_id); + xhci_dbg(xhci, "remote wake SS port %d\n", port_id); + /* Set a flag to say the port signaled remote wakeup, + * so we can tell the difference between the end of + * device and host initiated resume. + */ + bus_state->port_remote_wakeup |= 1 << faked_port_index; + xhci_test_and_clear_bit(xhci, port_array, + faked_port_index, PORT_PLC); xhci_set_link_state(xhci, port_array, faked_port_index, XDEV_U0); - slot_id = xhci_find_slot_id_by_port(hcd, xhci, - faked_port_index); - if (!slot_id) { - xhci_dbg(xhci, "slot_id is zero\n"); - goto cleanup; - } - xhci_ring_device(xhci, slot_id); - xhci_dbg(xhci, "resume SS port %d finished\n", port_id); - /* Clear PORT_PLC */ - xhci_test_and_clear_bit(xhci, port_array, - faked_port_index, PORT_PLC); + /* Need to wait until the next link state change + * indicates the device is actually in U0. + */ + bogus_port_status = true; + goto cleanup; } else { xhci_dbg(xhci, "resume HS port %d\n", port_id); bus_state->resume_done[faked_port_index] = jiffies + @@ -1344,6 +1366,32 @@ static void handle_port_status(struct xhci_hcd *xhci, } } + if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_U0 && + DEV_SUPERSPEED(temp)) { + xhci_dbg(xhci, "resume SS port %d finished\n", port_id); + /* We've just brought the device into U0 through either the + * Resume state after a device remote wakeup, or through the + * U3Exit state after a host-initiated resume. If it's a device + * initiated remote wake, don't pass up the link state change, + * so the roothub behavior is consistent with external + * USB 3.0 hub behavior. + */ + slot_id = xhci_find_slot_id_by_port(hcd, xhci, + faked_port_index + 1); + if (slot_id && xhci->devs[slot_id]) + xhci_ring_device(xhci, slot_id); + if (bus_state->port_remote_wakeup && (1 << faked_port_index)) { + bus_state->port_remote_wakeup &= + ~(1 << faked_port_index); + xhci_test_and_clear_bit(xhci, port_array, + faked_port_index, PORT_PLC); + usb_wakeup_notification(hcd->self.root_hub, + faked_port_index + 1); + bogus_port_status = true; + goto cleanup; + } + } + if (hcd->speed != HCD_USB3) xhci_test_and_clear_bit(xhci, port_array, faked_port_index, PORT_PLC); @@ -2276,6 +2324,9 @@ static int xhci_handle_event(struct xhci_hcd *xhci) else update_ptrs = 0; break; + case TRB_TYPE(TRB_DEV_NOTE): + handle_device_notification(xhci, event); + break; default: if ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK) >= TRB_TYPE(48)) @@ -3323,7 +3374,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* Check TD length */ if (running_total != td_len) { xhci_err(xhci, "ISOC TD length unmatch\n"); - return -EINVAL; + ret = -EINVAL; + goto cleanup; } } diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 6bbe3c3..c939f5f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -352,6 +352,11 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd) /* hcd->irq is -1, we have MSI */ return 0; + if (!pdev->irq) { + xhci_err(xhci, "No msi-x/msi found and no IRQ in BIOS\n"); + return -EINVAL; + } + /* fall back to legacy interrupt*/ ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, hcd->irq_descr, hcd); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index fb99c83..0f49369 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1344,6 +1344,7 @@ struct xhci_bus_state { /* ports suspend status arrays - max 31 ports for USB2, 15 for USB3 */ u32 port_c_suspend; u32 suspended_ports; + u32 port_remote_wakeup; unsigned long resume_done[USB_MAXCHILDREN]; }; diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c index d9b6a03..da97dce 100644 --- a/drivers/usb/misc/emi26.c +++ b/drivers/usb/misc/emi26.c @@ -37,9 +37,6 @@ static int emi26_set_reset(struct usb_device *dev, unsigned char reset_bit); static int emi26_load_firmware (struct usb_device *dev); static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id); static void emi26_disconnect(struct usb_interface *intf); -static int __init emi26_init (void); -static void __exit emi26_exit (void); - /* thanks to drivers/usb/serial/keyspan_pda.c code */ static int emi26_writememory (struct usb_device *dev, int address, diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 9f39062..4e0f167 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -46,9 +46,6 @@ static int emi62_set_reset(struct usb_device *dev, unsigned char reset_bit); static int emi62_load_firmware (struct usb_device *dev); static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id); static void emi62_disconnect(struct usb_interface *intf); -static int __init emi62_init (void); -static void __exit emi62_exit (void); - /* thanks to drivers/usb/serial/keyspan_pda.c code */ static int emi62_writememory(struct usb_device *dev, int address, diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c index 107bf13..b2d82b9 100644 --- a/drivers/usb/misc/usbsevseg.c +++ b/drivers/usb/misc/usbsevseg.c @@ -24,7 +24,7 @@ #define VENDOR_ID 0x0fc5 #define PRODUCT_ID 0x1227 -#define MAXLEN 6 +#define MAXLEN 8 /* table of devices that work with this driver */ static const struct usb_device_id id_table[] = { diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index e233d2b..9f3eda9 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -226,6 +226,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) struct device *dev = musb->controller; struct musb_hdrc_platform_data *plat = dev->platform_data; struct omap_musb_board_data *data = plat->board_data; + struct usb_otg *otg = musb->xceiv->otg; unsigned long flags; irqreturn_t ret = IRQ_NONE; u32 epintr, usbintr; @@ -289,14 +290,14 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) WARNING("VBUS error workaround (delay coming)\n"); } else if (is_host_enabled(musb) && drvvbus) { MUSB_HST_MODE(musb); - musb->xceiv->default_a = 1; + otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; portstate(musb->port1_status |= USB_PORT_STAT_POWER); del_timer(&otg_workaround); } else { musb->is_active = 0; MUSB_DEV_MODE(musb); - musb->xceiv->default_a = 0; + otg->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); } @@ -363,7 +364,7 @@ static int am35x_musb_init(struct musb *musb) return -ENODEV; usb_nop_xceiv_register(); - musb->xceiv = otg_get_transceiver(); + musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) return -ENODEV; @@ -405,7 +406,7 @@ static int am35x_musb_exit(struct musb *musb) if (data->set_phy_power) data->set_phy_power(0); - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; @@ -456,7 +457,7 @@ static const struct musb_platform_ops am35x_ops = { static u64 am35x_dmamask = DMA_BIT_MASK(32); -static int __init am35x_probe(struct platform_device *pdev) +static int __devinit am35x_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; @@ -561,7 +562,7 @@ err0: return ret; } -static int __exit am35x_remove(struct platform_device *pdev) +static int __devexit am35x_remove(struct platform_device *pdev) { struct am35x_glue *glue = platform_get_drvdata(pdev); @@ -630,7 +631,8 @@ static struct dev_pm_ops am35x_pm_ops = { #endif static struct platform_driver am35x_driver = { - .remove = __exit_p(am35x_remove), + .probe = am35x_probe, + .remove = __devexit_p(am35x_remove), .driver = { .name = "musb-am35x", .pm = DEV_PM_OPS, @@ -643,9 +645,9 @@ MODULE_LICENSE("GPL v2"); static int __init am35x_init(void) { - return platform_driver_probe(&am35x_driver, am35x_probe); + return platform_driver_register(&am35x_driver); } -subsys_initcall(am35x_init); +module_init(am35x_init); static void __exit am35x_exit(void) { diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index 5e7cfba..a087ed6 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -317,7 +317,7 @@ static void bfin_musb_set_vbus(struct musb *musb, int is_on) musb_readb(musb->mregs, MUSB_DEVCTL)); } -static int bfin_musb_set_power(struct otg_transceiver *x, unsigned mA) +static int bfin_musb_set_power(struct usb_phy *x, unsigned mA) { return 0; } @@ -415,7 +415,7 @@ static int bfin_musb_init(struct musb *musb) gpio_direction_output(musb->config->gpio_vrsel, 0); usb_nop_xceiv_register(); - musb->xceiv = otg_get_transceiver(); + musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) { gpio_free(musb->config->gpio_vrsel); return -ENODEV; @@ -440,7 +440,7 @@ static int bfin_musb_exit(struct musb *musb) { gpio_free(musb->config->gpio_vrsel); - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; } @@ -463,7 +463,7 @@ static const struct musb_platform_ops bfin_ops = { static u64 bfin_dmamask = DMA_BIT_MASK(32); -static int __init bfin_probe(struct platform_device *pdev) +static int __devinit bfin_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; @@ -525,7 +525,7 @@ err0: return ret; } -static int __exit bfin_remove(struct platform_device *pdev) +static int __devexit bfin_remove(struct platform_device *pdev) { struct bfin_glue *glue = platform_get_drvdata(pdev); @@ -575,6 +575,7 @@ static struct dev_pm_ops bfin_pm_ops = { #endif static struct platform_driver bfin_driver = { + .probe = bfin_probe, .remove = __exit_p(bfin_remove), .driver = { .name = "musb-blackfin", @@ -588,9 +589,9 @@ MODULE_LICENSE("GPL v2"); static int __init bfin_init(void) { - return platform_driver_probe(&bfin_driver, bfin_probe); + return platform_driver_register(&bfin_driver); } -subsys_initcall(bfin_init); +module_init(bfin_init); static void __exit bfin_exit(void) { diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 2613bfd..8bd9566 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -294,6 +294,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) { struct musb *musb = hci; void __iomem *reg_base = musb->ctrl_base; + struct usb_otg *otg = musb->xceiv->otg; unsigned long flags; irqreturn_t ret = IRQ_NONE; u32 status; @@ -351,14 +352,14 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) WARNING("VBUS error workaround (delay coming)\n"); } else if (is_host_enabled(musb) && drvvbus) { MUSB_HST_MODE(musb); - musb->xceiv->default_a = 1; + otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; portstate(musb->port1_status |= USB_PORT_STAT_POWER); del_timer(&otg_workaround); } else { musb->is_active = 0; MUSB_DEV_MODE(musb); - musb->xceiv->default_a = 0; + otg->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); } @@ -424,7 +425,7 @@ static int da8xx_musb_init(struct musb *musb) goto fail; usb_nop_xceiv_register(); - musb->xceiv = otg_get_transceiver(); + musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) goto fail; @@ -457,7 +458,7 @@ static int da8xx_musb_exit(struct musb *musb) phy_off(); - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; @@ -478,7 +479,7 @@ static const struct musb_platform_ops da8xx_ops = { static u64 da8xx_dmamask = DMA_BIT_MASK(32); -static int __init da8xx_probe(struct platform_device *pdev) +static int __devinit da8xx_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; @@ -562,7 +563,7 @@ err0: return ret; } -static int __exit da8xx_remove(struct platform_device *pdev) +static int __devexit da8xx_remove(struct platform_device *pdev) { struct da8xx_glue *glue = platform_get_drvdata(pdev); @@ -576,7 +577,8 @@ static int __exit da8xx_remove(struct platform_device *pdev) } static struct platform_driver da8xx_driver = { - .remove = __exit_p(da8xx_remove), + .probe = da8xx_probe, + .remove = __devexit_p(da8xx_remove), .driver = { .name = "musb-da8xx", }, @@ -588,9 +590,9 @@ MODULE_LICENSE("GPL v2"); static int __init da8xx_init(void) { - return platform_driver_probe(&da8xx_driver, da8xx_probe); + return platform_driver_register(&da8xx_driver); } -subsys_initcall(da8xx_init); +module_init(da8xx_init); static void __exit da8xx_exit(void) { diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index f9a3f62..97ab975 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -33,9 +33,6 @@ #include <linux/platform_device.h> #include <linux/dma-mapping.h> -#include <mach/hardware.h> -#include <mach/memory.h> -#include <asm/gpio.h> #include <mach/cputype.h> #include <asm/mach-types.h> @@ -268,6 +265,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) unsigned long flags; irqreturn_t retval = IRQ_NONE; struct musb *musb = __hci; + struct usb_otg *otg = musb->xceiv->otg; void __iomem *tibase = musb->ctrl_base; struct cppi *cppi; u32 tmp; @@ -334,14 +332,14 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) WARNING("VBUS error workaround (delay coming)\n"); } else if (is_host_enabled(musb) && drvvbus) { MUSB_HST_MODE(musb); - musb->xceiv->default_a = 1; + otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; portstate(musb->port1_status |= USB_PORT_STAT_POWER); del_timer(&otg_workaround); } else { musb->is_active = 0; MUSB_DEV_MODE(musb); - musb->xceiv->default_a = 0; + otg->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); } @@ -386,7 +384,7 @@ static int davinci_musb_init(struct musb *musb) u32 revision; usb_nop_xceiv_register(); - musb->xceiv = otg_get_transceiver(); + musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) return -ENODEV; @@ -445,7 +443,7 @@ static int davinci_musb_init(struct musb *musb) return 0; fail: - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return -ENODEV; } @@ -467,7 +465,7 @@ static int davinci_musb_exit(struct musb *musb) davinci_musb_source_power(musb, 0 /*off*/, 1); /* delay, to avoid problems with module reload */ - if (is_host_enabled(musb) && musb->xceiv->default_a) { + if (is_host_enabled(musb) && musb->xceiv->otg->default_a) { int maxdelay = 30; u8 devctl, warn = 0; @@ -494,7 +492,7 @@ static int davinci_musb_exit(struct musb *musb) phy_off(); - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; @@ -514,7 +512,7 @@ static const struct musb_platform_ops davinci_ops = { static u64 davinci_dmamask = DMA_BIT_MASK(32); -static int __init davinci_probe(struct platform_device *pdev) +static int __devinit davinci_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; @@ -597,7 +595,7 @@ err0: return ret; } -static int __exit davinci_remove(struct platform_device *pdev) +static int __devexit davinci_remove(struct platform_device *pdev) { struct davinci_glue *glue = platform_get_drvdata(pdev); @@ -611,7 +609,8 @@ static int __exit davinci_remove(struct platform_device *pdev) } static struct platform_driver davinci_driver = { - .remove = __exit_p(davinci_remove), + .probe = davinci_probe, + .remove = __devexit_p(davinci_remove), .driver = { .name = "musb-davinci", }, @@ -623,9 +622,9 @@ MODULE_LICENSE("GPL v2"); static int __init davinci_init(void) { - return platform_driver_probe(&davinci_driver, davinci_probe); + return platform_driver_register(&davinci_driver); } -subsys_initcall(davinci_init); +module_init(davinci_init); static void __exit davinci_exit(void) { diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 56cf024..b527e9e 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -131,9 +131,9 @@ static inline struct musb *dev_to_musb(struct device *dev) /*-------------------------------------------------------------------------*/ #ifndef CONFIG_BLACKFIN -static int musb_ulpi_read(struct otg_transceiver *otg, u32 offset) +static int musb_ulpi_read(struct usb_phy *phy, u32 offset) { - void __iomem *addr = otg->io_priv; + void __iomem *addr = phy->io_priv; int i = 0; u8 r; u8 power; @@ -165,10 +165,9 @@ static int musb_ulpi_read(struct otg_transceiver *otg, u32 offset) return musb_readb(addr, MUSB_ULPI_REG_DATA); } -static int musb_ulpi_write(struct otg_transceiver *otg, - u32 offset, u32 data) +static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) { - void __iomem *addr = otg->io_priv; + void __iomem *addr = phy->io_priv; int i = 0; u8 r = 0; u8 power; @@ -200,7 +199,7 @@ static int musb_ulpi_write(struct otg_transceiver *otg, #define musb_ulpi_write NULL #endif -static struct otg_io_access_ops musb_ulpi_access = { +static struct usb_phy_io_ops musb_ulpi_access = { .read = musb_ulpi_read, .write = musb_ulpi_write, }; @@ -414,6 +413,7 @@ void musb_hnp_stop(struct musb *musb) static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, u8 devctl, u8 power) { + struct usb_otg *otg = musb->xceiv->otg; irqreturn_t handled = IRQ_NONE; dev_dbg(musb->controller, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl, @@ -626,7 +626,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, case OTG_STATE_B_PERIPHERAL: musb_g_suspend(musb); musb->is_active = is_otg_enabled(musb) - && musb->xceiv->gadget->b_hnp_enable; + && otg->gadget->b_hnp_enable; if (musb->is_active) { musb->xceiv->state = OTG_STATE_B_WAIT_ACON; dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n"); @@ -643,7 +643,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, case OTG_STATE_A_HOST: musb->xceiv->state = OTG_STATE_A_SUSPEND; musb->is_active = is_otg_enabled(musb) - && musb->xceiv->host->b_hnp_enable; + && otg->host->b_hnp_enable; break; case OTG_STATE_B_HOST: /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ @@ -981,6 +981,9 @@ static void musb_shutdown(struct platform_device *pdev) unsigned long flags; pm_runtime_get_sync(musb->controller); + + musb_gadget_cleanup(musb); + spin_lock_irqsave(&musb->lock, flags); musb_platform_disable(musb); musb_generic_disable(musb); @@ -1014,12 +1017,12 @@ static void musb_shutdown(struct platform_device *pdev) || defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE) \ || defined(CONFIG_USB_MUSB_AM35X) \ || defined(CONFIG_USB_MUSB_AM35X_MODULE) -static ushort __initdata fifo_mode = 4; +static ushort __devinitdata fifo_mode = 4; #elif defined(CONFIG_USB_MUSB_UX500) \ || defined(CONFIG_USB_MUSB_UX500_MODULE) -static ushort __initdata fifo_mode = 5; +static ushort __devinitdata fifo_mode = 5; #else -static ushort __initdata fifo_mode = 2; +static ushort __devinitdata fifo_mode = 2; #endif /* "modprobe ... fifo_mode=1" etc */ @@ -1032,7 +1035,7 @@ MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration"); */ /* mode 0 - fits in 2KB */ -static struct musb_fifo_cfg __initdata mode_0_cfg[] = { +static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, }, @@ -1041,7 +1044,7 @@ static struct musb_fifo_cfg __initdata mode_0_cfg[] = { }; /* mode 1 - fits in 4KB */ -static struct musb_fifo_cfg __initdata mode_1_cfg[] = { +static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, }, { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, }, @@ -1050,7 +1053,7 @@ static struct musb_fifo_cfg __initdata mode_1_cfg[] = { }; /* mode 2 - fits in 4KB */ -static struct musb_fifo_cfg __initdata mode_2_cfg[] = { +static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, @@ -1060,7 +1063,7 @@ static struct musb_fifo_cfg __initdata mode_2_cfg[] = { }; /* mode 3 - fits in 4KB */ -static struct musb_fifo_cfg __initdata mode_3_cfg[] = { +static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, @@ -1070,7 +1073,7 @@ static struct musb_fifo_cfg __initdata mode_3_cfg[] = { }; /* mode 4 - fits in 16KB */ -static struct musb_fifo_cfg __initdata mode_4_cfg[] = { +static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, @@ -1101,7 +1104,7 @@ static struct musb_fifo_cfg __initdata mode_4_cfg[] = { }; /* mode 5 - fits in 8KB */ -static struct musb_fifo_cfg __initdata mode_5_cfg[] = { +static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, @@ -1137,7 +1140,7 @@ static struct musb_fifo_cfg __initdata mode_5_cfg[] = { * * returns negative errno or offset for next fifo. */ -static int __init +static int __devinit fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep, const struct musb_fifo_cfg *cfg, u16 offset) { @@ -1208,11 +1211,11 @@ fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep, return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0)); } -static struct musb_fifo_cfg __initdata ep0_cfg = { +static struct musb_fifo_cfg __devinitdata ep0_cfg = { .style = FIFO_RXTX, .maxpacket = 64, }; -static int __init ep_config_from_table(struct musb *musb) +static int __devinit ep_config_from_table(struct musb *musb) { const struct musb_fifo_cfg *cfg; unsigned i, n; @@ -1303,7 +1306,7 @@ done: * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false * @param musb the controller */ -static int __init ep_config_from_hw(struct musb *musb) +static int __devinit ep_config_from_hw(struct musb *musb) { u8 epnum = 0; struct musb_hw_ep *hw_ep; @@ -1350,7 +1353,7 @@ enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, }; /* Initialize MUSB (M)HDRC part of the USB hardware subsystem; * configure endpoints, or take their config from silicon */ -static int __init musb_core_init(u16 musb_type, struct musb *musb) +static int __devinit musb_core_init(u16 musb_type, struct musb *musb) { u8 reg; char *type; @@ -1586,7 +1589,7 @@ irqreturn_t musb_interrupt(struct musb *musb) EXPORT_SYMBOL_GPL(musb_interrupt); #ifndef CONFIG_MUSB_PIO_ONLY -static bool __initdata use_dma = 1; +static bool __devinitdata use_dma = 1; /* "modprobe ... use_dma=0" etc */ module_param(use_dma, bool, 0); @@ -1774,7 +1777,7 @@ static void musb_irq_work(struct work_struct *data) * Init support */ -static struct musb *__init +static struct musb *__devinit allocate_instance(struct device *dev, struct musb_hdrc_config *config, void __iomem *mbase) { @@ -1827,8 +1830,6 @@ static void musb_free(struct musb *musb) sysfs_remove_group(&musb->controller->kobj, &musb_attr_group); #endif - musb_gadget_cleanup(musb); - if (musb->nIrq >= 0) { if (musb->irq_wake) disable_irq_wake(musb->nIrq); @@ -1852,7 +1853,7 @@ static void musb_free(struct musb *musb) * @mregs: virtual address of controller registers, * not yet corrected for platform-specific offsets */ -static int __init +static int __devinit musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) { int status; @@ -1960,11 +1961,11 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) if (is_host_enabled(musb)) { struct usb_hcd *hcd = musb_to_hcd(musb); - otg_set_host(musb->xceiv, &hcd->self); + otg_set_host(musb->xceiv->otg, &hcd->self); if (is_otg_enabled(musb)) hcd->self.otg_port = 1; - musb->xceiv->host = &hcd->self; + musb->xceiv->otg->host = &hcd->self; hcd->power_budget = 2 * (plat->power ? : 250); /* program PHY to use external vBus if required */ @@ -1983,7 +1984,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) struct usb_hcd *hcd = musb_to_hcd(musb); MUSB_HST_MODE(musb); - musb->xceiv->default_a = 1; + musb->xceiv->otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_IDLE; status = usb_add_hcd(musb_to_hcd(musb), -1, 0); @@ -1998,7 +1999,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) } else /* peripheral is enabled */ { MUSB_DEV_MODE(musb); - musb->xceiv->default_a = 0; + musb->xceiv->otg->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; status = musb_gadget_setup(musb); @@ -2072,7 +2073,7 @@ fail0: static u64 *orig_dma_mask; #endif -static int __init musb_probe(struct platform_device *pdev) +static int __devinit musb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; int irq = platform_get_irq_byname(pdev, "mc"); @@ -2101,7 +2102,7 @@ static int __init musb_probe(struct platform_device *pdev) return status; } -static int __exit musb_remove(struct platform_device *pdev) +static int __devexit musb_remove(struct platform_device *pdev) { struct musb *musb = dev_to_musb(&pdev->dev); void __iomem *ctrl_base = musb->ctrl_base; @@ -2111,11 +2112,9 @@ static int __exit musb_remove(struct platform_device *pdev) * - Peripheral mode: peripheral is deactivated (or never-activated) * - OTG mode: both roles are deactivated (or never-activated) */ - pm_runtime_get_sync(musb->controller); musb_exit_debugfs(musb); musb_shutdown(pdev); - pm_runtime_put(musb->controller); musb_free(musb); iounmap(ctrl_base); device_init_wakeup(&pdev->dev, 0); @@ -2363,7 +2362,8 @@ static struct platform_driver musb_driver = { .owner = THIS_MODULE, .pm = MUSB_DEV_PM_OPS, }, - .remove = __exit_p(musb_remove), + .probe = musb_probe, + .remove = __devexit_p(musb_remove), .shutdown = musb_shutdown, }; @@ -2379,13 +2379,9 @@ static int __init musb_init(void) ", " "otg (peripheral+host)", musb_driver_name); - return platform_driver_probe(&musb_driver, musb_probe); + return platform_driver_register(&musb_driver); } - -/* make us init after usbcore and i2c (transceivers, regulators, etc) - * and before usb gadget and host-side drivers start to register - */ -fs_initcall(musb_init); +module_init(musb_init); static void __exit musb_cleanup(void) { diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 3d28fb8..93de517 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -372,7 +372,7 @@ struct musb { u16 int_rx; u16 int_tx; - struct otg_transceiver *xceiv; + struct usb_phy *xceiv; u8 xceiv_event; int nIrq; diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index 13d9af9..40a37c9 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c @@ -235,29 +235,29 @@ static const struct file_operations musb_test_mode_fops = { .release = single_release, }; -int __init musb_init_debugfs(struct musb *musb) +int __devinit musb_init_debugfs(struct musb *musb) { struct dentry *root; struct dentry *file; int ret; root = debugfs_create_dir("musb", NULL); - if (IS_ERR(root)) { - ret = PTR_ERR(root); + if (!root) { + ret = -ENOMEM; goto err0; } file = debugfs_create_file("regdump", S_IRUGO, root, musb, &musb_regdump_fops); - if (IS_ERR(file)) { - ret = PTR_ERR(file); + if (!file) { + ret = -ENOMEM; goto err1; } file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, musb, &musb_test_mode_fops); - if (IS_ERR(file)) { - ret = PTR_ERR(file); + if (!file) { + ret = -ENOMEM; goto err1; } diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index ac3d2ee..a495a30 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -574,6 +574,15 @@ void musb_g_tx(struct musb *musb, u8 epnum) if (request->actual == request->length) { musb_g_giveback(musb_ep, request, 0); + /* + * In the giveback function the MUSB lock is + * released and acquired after sometime. During + * this time period the INDEX register could get + * changed by the gadget_queue function especially + * on SMP systems. Reselect the INDEX to be sure + * we are reading/modifying the right registers + */ + musb_ep_select(mbase, epnum); req = musb_ep->desc ? next_request(musb_ep) : NULL; if (!req) { dev_dbg(musb->controller, "%s idle now\n", @@ -983,6 +992,15 @@ void musb_g_rx(struct musb *musb, u8 epnum) } #endif musb_g_giveback(musb_ep, request, 0); + /* + * In the giveback function the MUSB lock is + * released and acquired after sometime. During + * this time period the INDEX register could get + * changed by the gadget_queue function especially + * on SMP systems. Reselect the INDEX to be sure + * we are reading/modifying the right registers + */ + musb_ep_select(mbase, epnum); req = next_request(musb_ep); if (!req) @@ -1624,7 +1642,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget) } spin_unlock_irqrestore(&musb->lock, flags); - otg_start_srp(musb->xceiv); + otg_start_srp(musb->xceiv->otg); spin_lock_irqsave(&musb->lock, flags); /* Block idling for at least 1s */ @@ -1703,7 +1721,7 @@ static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA) if (!musb->xceiv->set_power) return -EOPNOTSUPP; - return otg_set_power(musb->xceiv, mA); + return usb_phy_set_power(musb->xceiv, mA); } static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on) @@ -1762,7 +1780,7 @@ static void musb_gadget_release(struct device *dev) } -static void __init +static void __devinit init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in) { struct musb_hw_ep *hw_ep = musb->endpoints + epnum; @@ -1799,7 +1817,7 @@ init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in) * Initialize the endpoints exposed to peripheral drivers, with backlinks * to the rest of the driver state. */ -static inline void __init musb_g_init_endpoints(struct musb *musb) +static inline void __devinit musb_g_init_endpoints(struct musb *musb) { u8 epnum; struct musb_hw_ep *hw_ep; @@ -1832,7 +1850,7 @@ static inline void __init musb_g_init_endpoints(struct musb *musb) /* called once during driver setup to initialize and link into * the driver model; memory is zeroed. */ -int __init musb_gadget_setup(struct musb *musb) +int __devinit musb_gadget_setup(struct musb *musb) { int status; @@ -1898,6 +1916,7 @@ static int musb_gadget_start(struct usb_gadget *g, struct usb_gadget_driver *driver) { struct musb *musb = gadget_to_musb(g); + struct usb_otg *otg = musb->xceiv->otg; unsigned long flags; int retval = -EINVAL; @@ -1914,7 +1933,7 @@ static int musb_gadget_start(struct usb_gadget *g, spin_lock_irqsave(&musb->lock, flags); musb->is_active = 1; - otg_set_peripheral(musb->xceiv, &musb->g); + otg_set_peripheral(otg, &musb->g); musb->xceiv->state = OTG_STATE_B_IDLE; /* @@ -1945,8 +1964,8 @@ static int musb_gadget_start(struct usb_gadget *g, } if ((musb->xceiv->last_event == USB_EVENT_ID) - && musb->xceiv->set_vbus) - otg_set_vbus(musb->xceiv, 1); + && otg->set_vbus) + otg_set_vbus(otg, 1); hcd->self.uses_pio_for_control = 1; } @@ -2028,7 +2047,7 @@ static int musb_gadget_stop(struct usb_gadget *g, musb->xceiv->state = OTG_STATE_UNDEFINED; stop_activity(musb, driver); - otg_set_peripheral(musb->xceiv, NULL); + otg_set_peripheral(musb->xceiv->otg, NULL); dev_dbg(musb->controller, "unregistering driver %s\n", driver->function); diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h index e61aa95..1d5eda2 100644 --- a/drivers/usb/musb/musb_io.h +++ b/drivers/usb/musb/musb_io.h @@ -39,7 +39,8 @@ #if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \ && !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \ - && !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN) + && !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN) \ + && !defined(CONFIG_MIPS) static inline void readsl(const void __iomem *addr, void *buf, int len) { insl((unsigned long)addr, buf, len); } static inline void readsw(const void __iomem *addr, void *buf, int len) diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index e9f80adc..22ec3e3 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -47,6 +47,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) { + struct usb_otg *otg = musb->xceiv->otg; u8 power; void __iomem *mbase = musb->mregs; @@ -81,7 +82,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) case OTG_STATE_A_HOST: musb->xceiv->state = OTG_STATE_A_SUSPEND; musb->is_active = is_otg_enabled(musb) - && musb->xceiv->host->b_hnp_enable; + && otg->host->b_hnp_enable; if (musb->is_active) mod_timer(&musb->otg_timer, jiffies + msecs_to_jiffies( @@ -91,7 +92,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) case OTG_STATE_B_HOST: musb->xceiv->state = OTG_STATE_B_WAIT_ACON; musb->is_active = is_otg_enabled(musb) - && musb->xceiv->host->b_hnp_enable; + && otg->host->b_hnp_enable; musb_platform_try_idle(musb, 0); break; default: @@ -179,6 +180,8 @@ static void musb_port_reset(struct musb *musb, bool do_reset) void musb_root_disconnect(struct musb *musb) { + struct usb_otg *otg = musb->xceiv->otg; + musb->port1_status = USB_PORT_STAT_POWER | (USB_PORT_STAT_C_CONNECTION << 16); @@ -188,7 +191,7 @@ void musb_root_disconnect(struct musb *musb) switch (musb->xceiv->state) { case OTG_STATE_A_SUSPEND: if (is_otg_enabled(musb) - && musb->xceiv->host->b_hnp_enable) { + && otg->host->b_hnp_enable) { musb->xceiv->state = OTG_STATE_A_PERIPHERAL; musb->g.is_a_peripheral = 1; break; diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index c27bbbf..2ae0bb3 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -132,6 +132,7 @@ static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout) static void omap2430_musb_set_vbus(struct musb *musb, int is_on) { + struct usb_otg *otg = musb->xceiv->otg; u8 devctl; unsigned long timeout = jiffies + msecs_to_jiffies(1000); int ret = 1; @@ -163,11 +164,11 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) } } - if (ret && musb->xceiv->set_vbus) - otg_set_vbus(musb->xceiv, 1); + if (ret && otg->set_vbus) + otg_set_vbus(otg, 1); } else { musb->is_active = 1; - musb->xceiv->default_a = 1; + otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; devctl |= MUSB_DEVCTL_SESSION; MUSB_HST_MODE(musb); @@ -179,7 +180,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) * jumping right to B_IDLE... */ - musb->xceiv->default_a = 0; + otg->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; devctl &= ~MUSB_DEVCTL_SESSION; @@ -222,7 +223,6 @@ static inline void omap2430_low_level_init(struct musb *musb) musb_writel(musb->mregs, OTG_FORCESTDBY, l); } -/* blocking notifier support */ static int musb_otg_notifications(struct notifier_block *nb, unsigned long event, void *unused) { @@ -231,7 +231,7 @@ static int musb_otg_notifications(struct notifier_block *nb, musb->xceiv_event = event; schedule_work(&musb->otg_notifier_work); - return 0; + return NOTIFY_OK; } static void musb_otg_notifier_work(struct work_struct *data_notifier_work) @@ -247,7 +247,7 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work) if (!is_otg_enabled(musb) || musb->gadget_driver) { pm_runtime_get_sync(musb->controller); - otg_init(musb->xceiv); + usb_phy_init(musb->xceiv); omap2430_musb_set_vbus(musb, 1); } break; @@ -257,7 +257,7 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work) if (musb->gadget_driver) pm_runtime_get_sync(musb->controller); - otg_init(musb->xceiv); + usb_phy_init(musb->xceiv); break; case USB_EVENT_NONE: @@ -270,10 +270,10 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work) } if (data->interface_type == MUSB_INTERFACE_UTMI) { - if (musb->xceiv->set_vbus) - otg_set_vbus(musb->xceiv, 0); + if (musb->xceiv->otg->set_vbus) + otg_set_vbus(musb->xceiv->otg, 0); } - otg_shutdown(musb->xceiv); + usb_phy_shutdown(musb->xceiv); break; default: dev_dbg(musb->controller, "ID float\n"); @@ -291,7 +291,7 @@ static int omap2430_musb_init(struct musb *musb) * up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. */ - musb->xceiv = otg_get_transceiver(); + musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) { pr_err("HS USB OTG: no transceiver configured\n"); return -ENODEV; @@ -326,7 +326,7 @@ static int omap2430_musb_init(struct musb *musb) musb_readl(musb->mregs, OTG_SIMENABLE)); musb->nb.notifier_call = musb_otg_notifications; - status = otg_register_notifier(musb->xceiv, &musb->nb); + status = usb_register_notifier(musb->xceiv, &musb->nb); if (status) dev_dbg(musb->controller, "notification register failed\n"); @@ -350,7 +350,7 @@ static void omap2430_musb_enable(struct musb *musb) switch (musb->xceiv->last_event) { case USB_EVENT_ID: - otg_init(musb->xceiv); + usb_phy_init(musb->xceiv); if (data->interface_type != MUSB_INTERFACE_UTMI) break; devctl = musb_readb(musb->mregs, MUSB_DEVCTL); @@ -369,7 +369,7 @@ static void omap2430_musb_enable(struct musb *musb) break; case USB_EVENT_VBUS: - otg_init(musb->xceiv); + usb_phy_init(musb->xceiv); break; default: @@ -380,15 +380,16 @@ static void omap2430_musb_enable(struct musb *musb) static void omap2430_musb_disable(struct musb *musb) { if (musb->xceiv->last_event) - otg_shutdown(musb->xceiv); + usb_phy_shutdown(musb->xceiv); } static int omap2430_musb_exit(struct musb *musb) { del_timer_sync(&musb_idle_timer); + cancel_work_sync(&musb->otg_notifier_work); omap2430_low_level_exit(musb); - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); return 0; } @@ -408,7 +409,7 @@ static const struct musb_platform_ops omap2430_ops = { static u64 omap2430_dmamask = DMA_BIT_MASK(32); -static int __init omap2430_probe(struct platform_device *pdev) +static int __devinit omap2430_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; @@ -471,7 +472,7 @@ err0: return ret; } -static int __exit omap2430_remove(struct platform_device *pdev) +static int __devexit omap2430_remove(struct platform_device *pdev) { struct omap2430_glue *glue = platform_get_drvdata(pdev); @@ -494,7 +495,7 @@ static int omap2430_runtime_suspend(struct device *dev) OTG_INTERFSEL); omap2430_low_level_exit(musb); - otg_set_suspend(musb->xceiv, 1); + usb_phy_set_suspend(musb->xceiv, 1); return 0; } @@ -508,7 +509,7 @@ static int omap2430_runtime_resume(struct device *dev) musb_writel(musb->mregs, OTG_INTERFSEL, musb->context.otg_interfsel); - otg_set_suspend(musb->xceiv, 0); + usb_phy_set_suspend(musb->xceiv, 0); return 0; } @@ -524,7 +525,8 @@ static struct dev_pm_ops omap2430_pm_ops = { #endif static struct platform_driver omap2430_driver = { - .remove = __exit_p(omap2430_remove), + .probe = omap2430_probe, + .remove = __devexit_p(omap2430_remove), .driver = { .name = "musb-omap2430", .pm = DEV_PM_OPS, @@ -537,9 +539,9 @@ MODULE_LICENSE("GPL v2"); static int __init omap2430_init(void) { - return platform_driver_probe(&omap2430_driver, omap2430_probe); + return platform_driver_register(&omap2430_driver); } -subsys_initcall(omap2430_init); +module_init(omap2430_init); static void __exit omap2430_exit(void) { diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 1f40561..de13559 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -277,7 +277,7 @@ static struct musb *the_musb; * mode), or low power Default-B sessions, something else supplies power. * Caller must take care of locking. */ -static int tusb_draw_power(struct otg_transceiver *x, unsigned mA) +static int tusb_draw_power(struct usb_phy *x, unsigned mA) { struct musb *musb = the_musb; void __iomem *tbase = musb->ctrl_base; @@ -293,7 +293,7 @@ static int tusb_draw_power(struct otg_transceiver *x, unsigned mA) * The actual current usage would be very board-specific. For now, * it's simpler to just use an aggregate (also board-specific). */ - if (x->default_a || mA < (musb->min_power << 1)) + if (x->otg->default_a || mA < (musb->min_power << 1)) mA = 0; reg = musb_readl(tbase, TUSB_PRCM_MNGMT); @@ -510,6 +510,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on) void __iomem *tbase = musb->ctrl_base; u32 conf, prcm, timer; u8 devctl; + struct usb_otg *otg = musb->xceiv->otg; /* HDRC controls CPEN, but beware current surges during device * connect. They can trigger transient overcurrent conditions @@ -522,7 +523,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on) if (is_on) { timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE); - musb->xceiv->default_a = 1; + otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; devctl |= MUSB_DEVCTL_SESSION; @@ -548,11 +549,11 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on) musb->xceiv->state = OTG_STATE_A_IDLE; } musb->is_active = 0; - musb->xceiv->default_a = 1; + otg->default_a = 1; MUSB_HST_MODE(musb); } else { musb->is_active = 0; - musb->xceiv->default_a = 0; + otg->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; MUSB_DEV_MODE(musb); } @@ -644,6 +645,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) { u32 otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); unsigned long idle_timeout = 0; + struct usb_otg *otg = musb->xceiv->otg; /* ID pin */ if ((int_src & TUSB_INT_SRC_ID_STATUS_CHNG)) { @@ -654,7 +656,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) else default_a = is_host_enabled(musb); dev_dbg(musb->controller, "Default-%c\n", default_a ? 'A' : 'B'); - musb->xceiv->default_a = default_a; + otg->default_a = default_a; tusb_musb_set_vbus(musb, default_a); /* Don't allow idling immediately */ @@ -666,7 +668,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) { /* B-dev state machine: no vbus ~= disconnect */ - if ((is_otg_enabled(musb) && !musb->xceiv->default_a) + if ((is_otg_enabled(musb) && !otg->default_a) || !is_host_enabled(musb)) { /* ? musb_root_disconnect(musb); */ musb->port1_status &= @@ -1076,7 +1078,7 @@ static int tusb_musb_init(struct musb *musb) int ret; usb_nop_xceiv_register(); - musb->xceiv = otg_get_transceiver(); + musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) return -ENODEV; @@ -1128,7 +1130,7 @@ done: if (sync) iounmap(sync); - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); } return ret; @@ -1144,7 +1146,7 @@ static int tusb_musb_exit(struct musb *musb) iounmap(musb->sync_va); - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; } @@ -1165,7 +1167,7 @@ static const struct musb_platform_ops tusb_ops = { static u64 tusb_dmamask = DMA_BIT_MASK(32); -static int __init tusb_probe(struct platform_device *pdev) +static int __devinit tusb_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; @@ -1227,7 +1229,7 @@ err0: return ret; } -static int __exit tusb_remove(struct platform_device *pdev) +static int __devexit tusb_remove(struct platform_device *pdev) { struct tusb6010_glue *glue = platform_get_drvdata(pdev); @@ -1239,7 +1241,8 @@ static int __exit tusb_remove(struct platform_device *pdev) } static struct platform_driver tusb_driver = { - .remove = __exit_p(tusb_remove), + .probe = tusb_probe, + .remove = __devexit_p(tusb_remove), .driver = { .name = "musb-tusb", }, @@ -1251,9 +1254,9 @@ MODULE_LICENSE("GPL v2"); static int __init tusb_init(void) { - return platform_driver_probe(&tusb_driver, tusb_probe); + return platform_driver_register(&tusb_driver); } -subsys_initcall(tusb_init); +module_init(tusb_init); static void __exit tusb_exit(void) { diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index f7e04bf..aa09dd4 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -37,7 +37,7 @@ struct ux500_glue { static int ux500_musb_init(struct musb *musb) { - musb->xceiv = otg_get_transceiver(); + musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) { pr_err("HS USB OTG: no transceiver configured\n"); return -ENODEV; @@ -48,7 +48,7 @@ static int ux500_musb_init(struct musb *musb) static int ux500_musb_exit(struct musb *musb) { - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); return 0; } @@ -58,7 +58,7 @@ static const struct musb_platform_ops ux500_ops = { .exit = ux500_musb_exit, }; -static int __init ux500_probe(struct platform_device *pdev) +static int __devinit ux500_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; @@ -141,7 +141,7 @@ err0: return ret; } -static int __exit ux500_remove(struct platform_device *pdev) +static int __devexit ux500_remove(struct platform_device *pdev) { struct ux500_glue *glue = platform_get_drvdata(pdev); @@ -160,7 +160,7 @@ static int ux500_suspend(struct device *dev) struct ux500_glue *glue = dev_get_drvdata(dev); struct musb *musb = glue_to_musb(glue); - otg_set_suspend(musb->xceiv, 1); + usb_phy_set_suspend(musb->xceiv, 1); clk_disable(glue->clk); return 0; @@ -178,7 +178,7 @@ static int ux500_resume(struct device *dev) return ret; } - otg_set_suspend(musb->xceiv, 0); + usb_phy_set_suspend(musb->xceiv, 0); return 0; } @@ -194,7 +194,8 @@ static const struct dev_pm_ops ux500_pm_ops = { #endif static struct platform_driver ux500_driver = { - .remove = __exit_p(ux500_remove), + .probe = ux500_probe, + .remove = __devexit_p(ux500_remove), .driver = { .name = "musb-ux500", .pm = DEV_PM_OPS, @@ -207,9 +208,9 @@ MODULE_LICENSE("GPL v2"); static int __init ux500_init(void) { - return platform_driver_probe(&ux500_driver, ux500_probe); + return platform_driver_register(&ux500_driver); } -subsys_initcall(ux500_init); +module_init(ux500_init); static void __exit ux500_exit(void) { diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 2a25955..5c87db0 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -23,7 +23,7 @@ config USB_GPIO_VBUS select USB_OTG_UTILS help Provides simple GPIO VBUS sensing for controllers with an - internal transceiver via the otg_transceiver interface, and + internal transceiver via the usb_phy interface, and optionally control of a D+ pullup GPIO as well as a VBUS current limit regulator. @@ -86,20 +86,6 @@ config NOP_USB_XCEIV built-in with usb ip or which are autonomous and doesn't require any phy programming such as ISP1x04 etc. -config USB_LANGWELL_OTG - tristate "Intel Langwell USB OTG dual-role support" - depends on USB && PCI && INTEL_SCU_IPC - select USB_OTG - select USB_OTG_UTILS - help - Say Y here if you want to build Intel Langwell USB OTG - transciever driver in kernel. This driver implements role - switch between EHCI host driver and Langwell USB OTG - client driver. - - To compile this driver as a module, choose M here: the - module will be called langwell_otg. - config USB_MSM_OTG tristate "OTG support for Qualcomm on-chip USB controller" depends on (USB || USB_GADGET) && ARCH_MSM @@ -124,7 +110,7 @@ config AB8500_USB config FSL_USB2_OTG bool "Freescale USB OTG Transceiver Driver" - depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 + depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 && USB_SUSPEND select USB_OTG select USB_OTG_UTILS help @@ -132,7 +118,7 @@ config FSL_USB2_OTG config USB_MV_OTG tristate "Marvell USB OTG support" - depends on USB_MV_UDC + depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND select USB_OTG select USB_OTG_UTILS help diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index b2c5a95..41aa509 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o obj-$(CONFIG_TWL6030_USB) += twl6030-usb.o -obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o obj-$(CONFIG_USB_ULPI) += ulpi.o obj-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi_viewport.o diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c index 74fe6e6..e6371ff 100644 --- a/drivers/usb/otg/ab8500-usb.c +++ b/drivers/usb/otg/ab8500-usb.c @@ -68,7 +68,7 @@ enum ab8500_usb_link_status { }; struct ab8500_usb { - struct otg_transceiver otg; + struct usb_phy phy; struct device *dev; int irq_num_id_rise; int irq_num_id_fall; @@ -82,9 +82,9 @@ struct ab8500_usb { int rev; }; -static inline struct ab8500_usb *xceiv_to_ab(struct otg_transceiver *x) +static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x) { - return container_of(x, struct ab8500_usb, otg); + return container_of(x, struct ab8500_usb, phy); } static void ab8500_usb_wd_workaround(struct ab8500_usb *ab) @@ -153,7 +153,7 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab) u8 reg; enum ab8500_usb_link_status lsts; void *v = NULL; - enum usb_xceiv_events event; + enum usb_phy_events event; abx500_get_register_interruptible(ab->dev, AB8500_USB, @@ -169,8 +169,8 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab) /* TODO: Disable regulators. */ ab8500_usb_host_phy_dis(ab); ab8500_usb_peri_phy_dis(ab); - ab->otg.state = OTG_STATE_B_IDLE; - ab->otg.default_a = false; + ab->phy.state = OTG_STATE_B_IDLE; + ab->phy.otg->default_a = false; ab->vbus_draw = 0; event = USB_EVENT_NONE; break; @@ -181,22 +181,22 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab) case USB_LINK_HOST_CHG_NM: case USB_LINK_HOST_CHG_HS: case USB_LINK_HOST_CHG_HS_CHIRP: - if (ab->otg.gadget) { + if (ab->phy.otg->gadget) { /* TODO: Enable regulators. */ ab8500_usb_peri_phy_en(ab); - v = ab->otg.gadget; + v = ab->phy.otg->gadget; } event = USB_EVENT_VBUS; break; case USB_LINK_HM_IDGND: - if (ab->otg.host) { + if (ab->phy.otg->host) { /* TODO: Enable regulators. */ ab8500_usb_host_phy_en(ab); - v = ab->otg.host; + v = ab->phy.otg->host; } - ab->otg.state = OTG_STATE_A_IDLE; - ab->otg.default_a = true; + ab->phy.state = OTG_STATE_A_IDLE; + ab->phy.otg->default_a = true; event = USB_EVENT_ID; break; @@ -212,7 +212,7 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab) break; } - atomic_notifier_call_chain(&ab->otg.notifier, event, v); + atomic_notifier_call_chain(&ab->phy.notifier, event, v); return 0; } @@ -262,27 +262,27 @@ static void ab8500_usb_phy_disable_work(struct work_struct *work) struct ab8500_usb *ab = container_of(work, struct ab8500_usb, phy_dis_work); - if (!ab->otg.host) + if (!ab->phy.otg->host) ab8500_usb_host_phy_dis(ab); - if (!ab->otg.gadget) + if (!ab->phy.otg->gadget) ab8500_usb_peri_phy_dis(ab); } -static int ab8500_usb_set_power(struct otg_transceiver *otg, unsigned mA) +static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA) { struct ab8500_usb *ab; - if (!otg) + if (!phy) return -ENODEV; - ab = xceiv_to_ab(otg); + ab = phy_to_ab(phy); ab->vbus_draw = mA; if (mA) - atomic_notifier_call_chain(&ab->otg.notifier, - USB_EVENT_ENUMERATED, ab->otg.gadget); + atomic_notifier_call_chain(&ab->phy.notifier, + USB_EVENT_ENUMERATED, ab->phy.otg->gadget); return 0; } @@ -290,21 +290,21 @@ static int ab8500_usb_set_power(struct otg_transceiver *otg, unsigned mA) * ab->vbus_draw. */ -static int ab8500_usb_set_suspend(struct otg_transceiver *x, int suspend) +static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend) { /* TODO */ return 0; } -static int ab8500_usb_set_peripheral(struct otg_transceiver *otg, - struct usb_gadget *gadget) +static int ab8500_usb_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) { struct ab8500_usb *ab; if (!otg) return -ENODEV; - ab = xceiv_to_ab(otg); + ab = phy_to_ab(otg->phy); /* Some drivers call this function in atomic context. * Do not update ab8500 registers directly till this @@ -313,11 +313,11 @@ static int ab8500_usb_set_peripheral(struct otg_transceiver *otg, if (!gadget) { /* TODO: Disable regulators. */ - ab->otg.gadget = NULL; + otg->gadget = NULL; schedule_work(&ab->phy_dis_work); } else { - ab->otg.gadget = gadget; - ab->otg.state = OTG_STATE_B_IDLE; + otg->gadget = gadget; + otg->phy->state = OTG_STATE_B_IDLE; /* Phy will not be enabled if cable is already * plugged-in. Schedule to enable phy. @@ -329,15 +329,14 @@ static int ab8500_usb_set_peripheral(struct otg_transceiver *otg, return 0; } -static int ab8500_usb_set_host(struct otg_transceiver *otg, - struct usb_bus *host) +static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host) { struct ab8500_usb *ab; if (!otg) return -ENODEV; - ab = xceiv_to_ab(otg); + ab = phy_to_ab(otg->phy); /* Some drivers call this function in atomic context. * Do not update ab8500 registers directly till this @@ -346,10 +345,10 @@ static int ab8500_usb_set_host(struct otg_transceiver *otg, if (!host) { /* TODO: Disable regulators. */ - ab->otg.host = NULL; + otg->host = NULL; schedule_work(&ab->phy_dis_work); } else { - ab->otg.host = host; + otg->host = host; /* Phy will not be enabled if cable is already * plugged-in. Schedule to enable phy. * Use same delay to avoid any race condition. @@ -472,6 +471,7 @@ static int ab8500_usb_v2_res_setup(struct platform_device *pdev, static int __devinit ab8500_usb_probe(struct platform_device *pdev) { struct ab8500_usb *ab; + struct usb_otg *otg; int err; int rev; @@ -488,19 +488,28 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) if (!ab) return -ENOMEM; + otg = kzalloc(sizeof *otg, GFP_KERNEL); + if (!ab->phy.otg) { + kfree(ab); + return -ENOMEM; + } + ab->dev = &pdev->dev; ab->rev = rev; - ab->otg.dev = ab->dev; - ab->otg.label = "ab8500"; - ab->otg.state = OTG_STATE_UNDEFINED; - ab->otg.set_host = ab8500_usb_set_host; - ab->otg.set_peripheral = ab8500_usb_set_peripheral; - ab->otg.set_suspend = ab8500_usb_set_suspend; - ab->otg.set_power = ab8500_usb_set_power; + ab->phy.dev = ab->dev; + ab->phy.otg = otg; + ab->phy.label = "ab8500"; + ab->phy.set_suspend = ab8500_usb_set_suspend; + ab->phy.set_power = ab8500_usb_set_power; + ab->phy.state = OTG_STATE_UNDEFINED; + + otg->phy = &ab->phy; + otg->set_host = ab8500_usb_set_host; + otg->set_peripheral = ab8500_usb_set_peripheral; platform_set_drvdata(pdev, ab); - ATOMIC_INIT_NOTIFIER_HEAD(&ab->otg.notifier); + ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier); /* v1: Wait for link status to become stable. * all: Updates form set_host and set_peripheral as they are atomic. @@ -520,7 +529,7 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) if (err < 0) goto fail0; - err = otg_set_transceiver(&ab->otg); + err = usb_set_transceiver(&ab->phy); if (err) { dev_err(&pdev->dev, "Can't register transceiver\n"); goto fail1; @@ -532,6 +541,7 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) fail1: ab8500_usb_irq_free(ab); fail0: + kfree(otg); kfree(ab); return err; } @@ -546,13 +556,14 @@ static int __devexit ab8500_usb_remove(struct platform_device *pdev) cancel_work_sync(&ab->phy_dis_work); - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); ab8500_usb_host_phy_dis(ab); ab8500_usb_peri_phy_dis(ab); platform_set_drvdata(pdev, NULL); + kfree(ab->phy.otg); kfree(ab); return 0; diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c index a190850..be4a63e 100644 --- a/drivers/usb/otg/fsl_otg.c +++ b/drivers/usb/otg/fsl_otg.c @@ -275,7 +275,7 @@ void b_srp_end(unsigned long foo) fsl_otg_dischrg_vbus(0); srp_wait_done = 1; - if ((fsl_otg_dev->otg.state == OTG_STATE_B_SRP_INIT) && + if ((fsl_otg_dev->phy.state == OTG_STATE_B_SRP_INIT) && fsl_otg_dev->fsm.b_sess_vld) fsl_otg_dev->fsm.b_srp_done = 1; } @@ -288,7 +288,7 @@ void b_srp_end(unsigned long foo) void a_wait_enum(unsigned long foo) { VDBG("a_wait_enum timeout\n"); - if (!fsl_otg_dev->otg.host->b_hnp_enable) + if (!fsl_otg_dev->phy.otg->host->b_hnp_enable) fsl_otg_add_timer(a_wait_enum_tmr); else otg_statemachine(&fsl_otg_dev->fsm); @@ -452,14 +452,14 @@ void otg_reset_controller(void) /* Call suspend/resume routines in host driver */ int fsl_otg_start_host(struct otg_fsm *fsm, int on) { - struct otg_transceiver *xceiv = fsm->transceiver; + struct usb_otg *otg = fsm->otg; struct device *dev; - struct fsl_otg *otg_dev = container_of(xceiv, struct fsl_otg, otg); + struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy); u32 retval = 0; - if (!xceiv->host) + if (!otg->host) return -ENODEV; - dev = xceiv->host->controller; + dev = otg->host->controller; /* * Update a_vbus_vld state as a_vbus_vld int is disabled @@ -518,14 +518,14 @@ end: */ int fsl_otg_start_gadget(struct otg_fsm *fsm, int on) { - struct otg_transceiver *xceiv = fsm->transceiver; + struct usb_otg *otg = fsm->otg; struct device *dev; - if (!xceiv->gadget || !xceiv->gadget->dev.parent) + if (!otg->gadget || !otg->gadget->dev.parent) return -ENODEV; VDBG("gadget %s\n", on ? "on" : "off"); - dev = xceiv->gadget->dev.parent; + dev = otg->gadget->dev.parent; if (on) { if (dev->driver->resume) @@ -542,14 +542,14 @@ int fsl_otg_start_gadget(struct otg_fsm *fsm, int on) * Called by initialization code of host driver. Register host controller * to the OTG. Suspend host for OTG role detection. */ -static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host) +static int fsl_otg_set_host(struct usb_otg *otg, struct usb_bus *host) { - struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); + struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy); - if (!otg_p || otg_dev != fsl_otg_dev) + if (!otg || otg_dev != fsl_otg_dev) return -ENODEV; - otg_p->host = host; + otg->host = host; otg_dev->fsm.a_bus_drop = 0; otg_dev->fsm.a_bus_req = 1; @@ -557,8 +557,8 @@ static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host) if (host) { VDBG("host off......\n"); - otg_p->host->otg_port = fsl_otg_initdata.otg_port; - otg_p->host->is_b_host = otg_dev->fsm.id; + otg->host->otg_port = fsl_otg_initdata.otg_port; + otg->host->is_b_host = otg_dev->fsm.id; /* * must leave time for khubd to finish its thing * before yanking the host driver out from under it, @@ -574,7 +574,7 @@ static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host) /* Mini-A cable connected */ struct otg_fsm *fsm = &otg_dev->fsm; - otg_p->state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; fsm->protocol = PROTO_UNDEF; } } @@ -587,29 +587,29 @@ static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host) } /* Called by initialization code of udc. Register udc to OTG. */ -static int fsl_otg_set_peripheral(struct otg_transceiver *otg_p, - struct usb_gadget *gadget) +static int fsl_otg_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) { - struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); + struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy); VDBG("otg_dev 0x%x\n", (int)otg_dev); VDBG("fsl_otg_dev 0x%x\n", (int)fsl_otg_dev); - if (!otg_p || otg_dev != fsl_otg_dev) + if (!otg || otg_dev != fsl_otg_dev) return -ENODEV; if (!gadget) { - if (!otg_dev->otg.default_a) - otg_p->gadget->ops->vbus_draw(otg_p->gadget, 0); - usb_gadget_vbus_disconnect(otg_dev->otg.gadget); - otg_dev->otg.gadget = 0; + if (!otg->default_a) + otg->gadget->ops->vbus_draw(otg->gadget, 0); + usb_gadget_vbus_disconnect(otg->gadget); + otg->gadget = 0; otg_dev->fsm.b_bus_req = 0; otg_statemachine(&otg_dev->fsm); return 0; } - otg_p->gadget = gadget; - otg_p->gadget->is_a_peripheral = !otg_dev->fsm.id; + otg->gadget = gadget; + otg->gadget->is_a_peripheral = !otg_dev->fsm.id; otg_dev->fsm.b_bus_req = 1; @@ -625,11 +625,11 @@ static int fsl_otg_set_peripheral(struct otg_transceiver *otg_p, } /* Set OTG port power, only for B-device */ -static int fsl_otg_set_power(struct otg_transceiver *otg_p, unsigned mA) +static int fsl_otg_set_power(struct usb_phy *phy, unsigned mA) { if (!fsl_otg_dev) return -ENODEV; - if (otg_p->state == OTG_STATE_B_PERIPHERAL) + if (phy->state == OTG_STATE_B_PERIPHERAL) pr_info("FSL OTG: Draw %d mA\n", mA); return 0; @@ -658,12 +658,12 @@ static void fsl_otg_event(struct work_struct *work) } /* B-device start SRP */ -static int fsl_otg_start_srp(struct otg_transceiver *otg_p) +static int fsl_otg_start_srp(struct usb_otg *otg) { - struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); + struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy); - if (!otg_p || otg_dev != fsl_otg_dev - || otg_p->state != OTG_STATE_B_IDLE) + if (!otg || otg_dev != fsl_otg_dev + || otg->phy->state != OTG_STATE_B_IDLE) return -ENODEV; otg_dev->fsm.b_bus_req = 1; @@ -673,11 +673,11 @@ static int fsl_otg_start_srp(struct otg_transceiver *otg_p) } /* A_host suspend will call this function to start hnp */ -static int fsl_otg_start_hnp(struct otg_transceiver *otg_p) +static int fsl_otg_start_hnp(struct usb_otg *otg) { - struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); + struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy); - if (!otg_p || otg_dev != fsl_otg_dev) + if (!otg || otg_dev != fsl_otg_dev) return -ENODEV; DBG("start_hnp...n"); @@ -698,7 +698,7 @@ static int fsl_otg_start_hnp(struct otg_transceiver *otg_p) irqreturn_t fsl_otg_isr(int irq, void *dev_id) { struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm; - struct otg_transceiver *otg = &((struct fsl_otg *)dev_id)->otg; + struct usb_otg *otg = ((struct fsl_otg *)dev_id)->phy.otg; u32 otg_int_src, otg_sc; otg_sc = fsl_readl(&usb_dr_regs->otgsc); @@ -774,6 +774,12 @@ static int fsl_otg_conf(struct platform_device *pdev) if (!fsl_otg_tc) return -ENOMEM; + fsl_otg_tc->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL); + if (!fsl_otg_tc->phy.otg) { + kfree(fsl_otg_tc); + return -ENOMEM; + } + INIT_DELAYED_WORK(&fsl_otg_tc->otg_event, fsl_otg_event); INIT_LIST_HEAD(&active_timers); @@ -788,17 +794,19 @@ static int fsl_otg_conf(struct platform_device *pdev) fsl_otg_tc->fsm.ops = &fsl_otg_ops; /* initialize the otg structure */ - fsl_otg_tc->otg.label = DRIVER_DESC; - fsl_otg_tc->otg.set_host = fsl_otg_set_host; - fsl_otg_tc->otg.set_peripheral = fsl_otg_set_peripheral; - fsl_otg_tc->otg.set_power = fsl_otg_set_power; - fsl_otg_tc->otg.start_hnp = fsl_otg_start_hnp; - fsl_otg_tc->otg.start_srp = fsl_otg_start_srp; + fsl_otg_tc->phy.label = DRIVER_DESC; + fsl_otg_tc->phy.set_power = fsl_otg_set_power; + + fsl_otg_tc->phy.otg->phy = &fsl_otg_tc->phy; + fsl_otg_tc->phy.otg->set_host = fsl_otg_set_host; + fsl_otg_tc->phy.otg->set_peripheral = fsl_otg_set_peripheral; + fsl_otg_tc->phy.otg->start_hnp = fsl_otg_start_hnp; + fsl_otg_tc->phy.otg->start_srp = fsl_otg_start_srp; fsl_otg_dev = fsl_otg_tc; /* Store the otg transceiver */ - status = otg_set_transceiver(&fsl_otg_tc->otg); + status = usb_set_transceiver(&fsl_otg_tc->phy); if (status) { pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n"); goto err; @@ -807,6 +815,7 @@ static int fsl_otg_conf(struct platform_device *pdev) return 0; err: fsl_otg_uninit_timers(); + kfree(fsl_otg_tc->phy.otg); kfree(fsl_otg_tc); return status; } @@ -815,19 +824,19 @@ err: int usb_otg_start(struct platform_device *pdev) { struct fsl_otg *p_otg; - struct otg_transceiver *otg_trans = otg_get_transceiver(); + struct usb_phy *otg_trans = usb_get_transceiver(); struct otg_fsm *fsm; int status; struct resource *res; u32 temp; struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; - p_otg = container_of(otg_trans, struct fsl_otg, otg); + p_otg = container_of(otg_trans, struct fsl_otg, phy); fsm = &p_otg->fsm; /* Initialize the state machine structure with default values */ SET_OTG_STATE(otg_trans, OTG_STATE_UNDEFINED); - fsm->transceiver = &p_otg->otg; + fsm->otg = p_otg->phy.otg; /* We don't require predefined MEM/IRQ resource index */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -857,9 +866,10 @@ int usb_otg_start(struct platform_device *pdev) status = request_irq(p_otg->irq, fsl_otg_isr, IRQF_SHARED, driver_name, p_otg); if (status) { - dev_dbg(p_otg->otg.dev, "can't get IRQ %d, error %d\n", + dev_dbg(p_otg->phy.dev, "can't get IRQ %d, error %d\n", p_otg->irq, status); iounmap(p_otg->dr_mem_map); + kfree(p_otg->phy.otg); kfree(p_otg); return status; } @@ -919,10 +929,10 @@ int usb_otg_start(struct platform_device *pdev) * Also: record initial state of ID pin */ if (fsl_readl(&p_otg->dr_mem_map->otgsc) & OTGSC_STS_USB_ID) { - p_otg->otg.state = OTG_STATE_UNDEFINED; + p_otg->phy.state = OTG_STATE_UNDEFINED; p_otg->fsm.id = 1; } else { - p_otg->otg.state = OTG_STATE_A_IDLE; + p_otg->phy.state = OTG_STATE_A_IDLE; p_otg->fsm.id = 0; } @@ -978,7 +988,7 @@ static int show_fsl_usb2_otg_state(struct device *dev, /* State */ t = scnprintf(next, size, "OTG state: %s\n\n", - otg_state_string(fsl_otg_dev->otg.state)); + otg_state_string(fsl_otg_dev->phy.state)); size -= t; next += t; @@ -1124,12 +1134,13 @@ static int __devexit fsl_otg_remove(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); free_irq(fsl_otg_dev->irq, fsl_otg_dev); iounmap((void *)usb_dr_regs); fsl_otg_uninit_timers(); + kfree(fsl_otg_dev->phy.otg); kfree(fsl_otg_dev); device_remove_file(&pdev->dev, &dev_attr_fsl_usb2_otg_state); diff --git a/drivers/usb/otg/fsl_otg.h b/drivers/usb/otg/fsl_otg.h index 3f8ef73..ca26628 100644 --- a/drivers/usb/otg/fsl_otg.h +++ b/drivers/usb/otg/fsl_otg.h @@ -369,7 +369,7 @@ inline struct fsl_otg_timer *otg_timer_initializer } struct fsl_otg { - struct otg_transceiver otg; + struct usb_phy phy; struct otg_fsm fsm; struct usb_dr_mmap *dr_mem_map; struct delayed_work otg_event; diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c index fb644c1..3ece43a 100644 --- a/drivers/usb/otg/gpio_vbus.c +++ b/drivers/usb/otg/gpio_vbus.c @@ -32,7 +32,7 @@ * Needs to be loaded before the UDC driver that will use it. */ struct gpio_vbus_data { - struct otg_transceiver otg; + struct usb_phy phy; struct device *dev; struct regulator *vbus_draw; int vbus_draw_enabled; @@ -98,7 +98,7 @@ static void gpio_vbus_work(struct work_struct *work) struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data; int gpio; - if (!gpio_vbus->otg.gadget) + if (!gpio_vbus->phy.otg->gadget) return; /* Peripheral controllers which manage the pullup themselves won't have @@ -108,8 +108,8 @@ static void gpio_vbus_work(struct work_struct *work) */ gpio = pdata->gpio_pullup; if (is_vbus_powered(pdata)) { - gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL; - usb_gadget_vbus_connect(gpio_vbus->otg.gadget); + gpio_vbus->phy.state = OTG_STATE_B_PERIPHERAL; + usb_gadget_vbus_connect(gpio_vbus->phy.otg->gadget); /* drawing a "unit load" is *always* OK, except for OTG */ set_vbus_draw(gpio_vbus, 100); @@ -124,8 +124,8 @@ static void gpio_vbus_work(struct work_struct *work) set_vbus_draw(gpio_vbus, 0); - usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget); - gpio_vbus->otg.state = OTG_STATE_B_IDLE; + usb_gadget_vbus_disconnect(gpio_vbus->phy.otg->gadget); + gpio_vbus->phy.state = OTG_STATE_B_IDLE; } } @@ -135,12 +135,13 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data) struct platform_device *pdev = data; struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data; struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev); + struct usb_otg *otg = gpio_vbus->phy.otg; dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n", is_vbus_powered(pdata) ? "supplied" : "inactive", - gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none"); + otg->gadget ? otg->gadget->name : "none"); - if (gpio_vbus->otg.gadget) + if (otg->gadget) schedule_work(&gpio_vbus->work); return IRQ_HANDLED; @@ -149,15 +150,15 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data) /* OTG transceiver interface */ /* bind/unbind the peripheral controller */ -static int gpio_vbus_set_peripheral(struct otg_transceiver *otg, - struct usb_gadget *gadget) +static int gpio_vbus_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) { struct gpio_vbus_data *gpio_vbus; struct gpio_vbus_mach_info *pdata; struct platform_device *pdev; int gpio, irq; - gpio_vbus = container_of(otg, struct gpio_vbus_data, otg); + gpio_vbus = container_of(otg->phy, struct gpio_vbus_data, phy); pdev = to_platform_device(gpio_vbus->dev); pdata = gpio_vbus->dev->platform_data; irq = gpio_to_irq(pdata->gpio_vbus); @@ -174,7 +175,7 @@ static int gpio_vbus_set_peripheral(struct otg_transceiver *otg, set_vbus_draw(gpio_vbus, 0); usb_gadget_vbus_disconnect(otg->gadget); - otg->state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; otg->gadget = NULL; return 0; @@ -189,23 +190,23 @@ static int gpio_vbus_set_peripheral(struct otg_transceiver *otg, } /* effective for B devices, ignored for A-peripheral */ -static int gpio_vbus_set_power(struct otg_transceiver *otg, unsigned mA) +static int gpio_vbus_set_power(struct usb_phy *phy, unsigned mA) { struct gpio_vbus_data *gpio_vbus; - gpio_vbus = container_of(otg, struct gpio_vbus_data, otg); + gpio_vbus = container_of(phy, struct gpio_vbus_data, phy); - if (otg->state == OTG_STATE_B_PERIPHERAL) + if (phy->state == OTG_STATE_B_PERIPHERAL) set_vbus_draw(gpio_vbus, mA); return 0; } /* for non-OTG B devices: set/clear transceiver suspend mode */ -static int gpio_vbus_set_suspend(struct otg_transceiver *otg, int suspend) +static int gpio_vbus_set_suspend(struct usb_phy *phy, int suspend) { struct gpio_vbus_data *gpio_vbus; - gpio_vbus = container_of(otg, struct gpio_vbus_data, otg); + gpio_vbus = container_of(phy, struct gpio_vbus_data, phy); /* draw max 0 mA from vbus in suspend mode; or the previously * recorded amount of current if not suspended @@ -213,7 +214,7 @@ static int gpio_vbus_set_suspend(struct otg_transceiver *otg, int suspend) * NOTE: high powered configs (mA > 100) may draw up to 2.5 mA * if they're wake-enabled ... we don't handle that yet. */ - return gpio_vbus_set_power(otg, suspend ? 0 : gpio_vbus->mA); + return gpio_vbus_set_power(phy, suspend ? 0 : gpio_vbus->mA); } /* platform driver interface */ @@ -233,13 +234,21 @@ static int __init gpio_vbus_probe(struct platform_device *pdev) if (!gpio_vbus) return -ENOMEM; + gpio_vbus->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL); + if (!gpio_vbus->phy.otg) { + kfree(gpio_vbus); + return -ENOMEM; + } + platform_set_drvdata(pdev, gpio_vbus); gpio_vbus->dev = &pdev->dev; - gpio_vbus->otg.label = "gpio-vbus"; - gpio_vbus->otg.state = OTG_STATE_UNDEFINED; - gpio_vbus->otg.set_peripheral = gpio_vbus_set_peripheral; - gpio_vbus->otg.set_power = gpio_vbus_set_power; - gpio_vbus->otg.set_suspend = gpio_vbus_set_suspend; + gpio_vbus->phy.label = "gpio-vbus"; + gpio_vbus->phy.set_power = gpio_vbus_set_power; + gpio_vbus->phy.set_suspend = gpio_vbus_set_suspend; + gpio_vbus->phy.state = OTG_STATE_UNDEFINED; + + gpio_vbus->phy.otg->phy = &gpio_vbus->phy; + gpio_vbus->phy.otg->set_peripheral = gpio_vbus_set_peripheral; err = gpio_request(gpio, "vbus_detect"); if (err) { @@ -288,7 +297,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev) } /* only active when a gadget is registered */ - err = otg_set_transceiver(&gpio_vbus->otg); + err = usb_set_transceiver(&gpio_vbus->phy); if (err) { dev_err(&pdev->dev, "can't register transceiver, err: %d\n", err); @@ -304,6 +313,7 @@ err_irq: gpio_free(pdata->gpio_vbus); err_gpio: platform_set_drvdata(pdev, NULL); + kfree(gpio_vbus->phy.otg); kfree(gpio_vbus); return err; } @@ -316,13 +326,14 @@ static int __exit gpio_vbus_remove(struct platform_device *pdev) regulator_put(gpio_vbus->vbus_draw); - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); free_irq(gpio_to_irq(gpio), &pdev->dev); if (gpio_is_valid(pdata->gpio_pullup)) gpio_free(pdata->gpio_pullup); gpio_free(gpio); platform_set_drvdata(pdev, NULL); + kfree(gpio_vbus->phy.otg); kfree(gpio_vbus); return 0; diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c index 8c86787..70cf5d7 100644 --- a/drivers/usb/otg/isp1301_omap.c +++ b/drivers/usb/otg/isp1301_omap.c @@ -52,7 +52,7 @@ MODULE_DESCRIPTION("ISP1301 USB OTG Transceiver Driver"); MODULE_LICENSE("GPL"); struct isp1301 { - struct otg_transceiver otg; + struct usb_phy phy; struct i2c_client *client; void (*i2c_release)(struct device *dev); @@ -236,7 +236,7 @@ isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits) static inline const char *state_name(struct isp1301 *isp) { - return otg_state_string(isp->otg.state); + return otg_state_string(isp->phy.state); } /*-------------------------------------------------------------------------*/ @@ -251,7 +251,7 @@ static inline const char *state_name(struct isp1301 *isp) static void power_down(struct isp1301 *isp) { - isp->otg.state = OTG_STATE_UNDEFINED; + isp->phy.state = OTG_STATE_UNDEFINED; // isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN); isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND); @@ -280,13 +280,13 @@ static int host_suspend(struct isp1301 *isp) #else struct device *dev; - if (!isp->otg.host) + if (!isp->phy.otg->host) return -ENODEV; /* Currently ASSUMES only the OTG port matters; * other ports could be active... */ - dev = isp->otg.host->controller; + dev = isp->phy.otg->host->controller; return dev->driver->suspend(dev, 3, 0); #endif } @@ -298,20 +298,20 @@ static int host_resume(struct isp1301 *isp) #else struct device *dev; - if (!isp->otg.host) + if (!isp->phy.otg->host) return -ENODEV; - dev = isp->otg.host->controller; + dev = isp->phy.otg->host->controller; return dev->driver->resume(dev, 0); #endif } static int gadget_suspend(struct isp1301 *isp) { - isp->otg.gadget->b_hnp_enable = 0; - isp->otg.gadget->a_hnp_support = 0; - isp->otg.gadget->a_alt_hnp_support = 0; - return usb_gadget_vbus_disconnect(isp->otg.gadget); + isp->phy.otg->gadget->b_hnp_enable = 0; + isp->phy.otg->gadget->a_hnp_support = 0; + isp->phy.otg->gadget->a_alt_hnp_support = 0; + return usb_gadget_vbus_disconnect(isp->phy.otg->gadget); } /*-------------------------------------------------------------------------*/ @@ -341,19 +341,19 @@ static void a_idle(struct isp1301 *isp, const char *tag) { u32 l; - if (isp->otg.state == OTG_STATE_A_IDLE) + if (isp->phy.state == OTG_STATE_A_IDLE) return; - isp->otg.default_a = 1; - if (isp->otg.host) { - isp->otg.host->is_b_host = 0; + isp->phy.otg->default_a = 1; + if (isp->phy.otg->host) { + isp->phy.otg->host->is_b_host = 0; host_suspend(isp); } - if (isp->otg.gadget) { - isp->otg.gadget->is_a_peripheral = 1; + if (isp->phy.otg->gadget) { + isp->phy.otg->gadget->is_a_peripheral = 1; gadget_suspend(isp); } - isp->otg.state = OTG_STATE_A_IDLE; + isp->phy.state = OTG_STATE_A_IDLE; l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS; omap_writel(l, OTG_CTRL); isp->last_otg_ctrl = l; @@ -365,19 +365,19 @@ static void b_idle(struct isp1301 *isp, const char *tag) { u32 l; - if (isp->otg.state == OTG_STATE_B_IDLE) + if (isp->phy.state == OTG_STATE_B_IDLE) return; - isp->otg.default_a = 0; - if (isp->otg.host) { - isp->otg.host->is_b_host = 1; + isp->phy.otg->default_a = 0; + if (isp->phy.otg->host) { + isp->phy.otg->host->is_b_host = 1; host_suspend(isp); } - if (isp->otg.gadget) { - isp->otg.gadget->is_a_peripheral = 0; + if (isp->phy.otg->gadget) { + isp->phy.otg->gadget->is_a_peripheral = 0; gadget_suspend(isp); } - isp->otg.state = OTG_STATE_B_IDLE; + isp->phy.state = OTG_STATE_B_IDLE; l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS; omap_writel(l, OTG_CTRL); isp->last_otg_ctrl = l; @@ -478,7 +478,7 @@ static void check_state(struct isp1301 *isp, const char *tag) default: break; } - if (isp->otg.state == state && !extra) + if (isp->phy.state == state && !extra) return; pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag, otg_state_string(state), fsm, state_name(isp), @@ -502,22 +502,23 @@ static void update_otg1(struct isp1301 *isp, u8 int_src) if (int_src & INTR_SESS_VLD) otg_ctrl |= OTG_ASESSVLD; - else if (isp->otg.state == OTG_STATE_A_WAIT_VFALL) { + else if (isp->phy.state == OTG_STATE_A_WAIT_VFALL) { a_idle(isp, "vfall"); otg_ctrl &= ~OTG_CTRL_BITS; } if (int_src & INTR_VBUS_VLD) otg_ctrl |= OTG_VBUSVLD; if (int_src & INTR_ID_GND) { /* default-A */ - if (isp->otg.state == OTG_STATE_B_IDLE - || isp->otg.state == OTG_STATE_UNDEFINED) { + if (isp->phy.state == OTG_STATE_B_IDLE + || isp->phy.state + == OTG_STATE_UNDEFINED) { a_idle(isp, "init"); return; } } else { /* default-B */ otg_ctrl |= OTG_ID; - if (isp->otg.state == OTG_STATE_A_IDLE - || isp->otg.state == OTG_STATE_UNDEFINED) { + if (isp->phy.state == OTG_STATE_A_IDLE + || isp->phy.state == OTG_STATE_UNDEFINED) { b_idle(isp, "init"); return; } @@ -551,14 +552,14 @@ static void otg_update_isp(struct isp1301 *isp) isp->last_otg_ctrl = otg_ctrl; otg_ctrl = otg_ctrl & OTG_XCEIV_INPUTS; - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_B_IDLE: case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_SRP_INIT: if (!(otg_ctrl & OTG_PULLUP)) { // if (otg_ctrl & OTG_B_HNPEN) { - if (isp->otg.gadget->b_hnp_enable) { - isp->otg.state = OTG_STATE_B_WAIT_ACON; + if (isp->phy.otg->gadget->b_hnp_enable) { + isp->phy.state = OTG_STATE_B_WAIT_ACON; pr_debug(" --> b_wait_acon\n"); } goto pulldown; @@ -585,10 +586,10 @@ pulldown: else clr |= ISP; \ } while (0) - if (!(isp->otg.host)) + if (!(isp->phy.otg->host)) otg_ctrl &= ~OTG_DRV_VBUS; - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_A_SUSPEND: if (otg_ctrl & OTG_DRV_VBUS) { set |= OTG1_VBUS_DRV; @@ -599,7 +600,7 @@ pulldown: /* FALLTHROUGH */ case OTG_STATE_A_VBUS_ERR: - isp->otg.state = OTG_STATE_A_WAIT_VFALL; + isp->phy.state = OTG_STATE_A_WAIT_VFALL; pr_debug(" --> a_wait_vfall\n"); /* FALLTHROUGH */ case OTG_STATE_A_WAIT_VFALL: @@ -608,7 +609,7 @@ pulldown: break; case OTG_STATE_A_IDLE: if (otg_ctrl & OTG_DRV_VBUS) { - isp->otg.state = OTG_STATE_A_WAIT_VRISE; + isp->phy.state = OTG_STATE_A_WAIT_VRISE; pr_debug(" --> a_wait_vrise\n"); } /* FALLTHROUGH */ @@ -628,17 +629,17 @@ pulldown: if (otg_change & OTG_PULLUP) { u32 l; - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_B_IDLE: if (clr & OTG1_DP_PULLUP) break; - isp->otg.state = OTG_STATE_B_PERIPHERAL; + isp->phy.state = OTG_STATE_B_PERIPHERAL; pr_debug(" --> b_peripheral\n"); break; case OTG_STATE_A_SUSPEND: if (clr & OTG1_DP_PULLUP) break; - isp->otg.state = OTG_STATE_A_PERIPHERAL; + isp->phy.state = OTG_STATE_A_PERIPHERAL; pr_debug(" --> a_peripheral\n"); break; default: @@ -659,6 +660,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) u32 otg_ctrl; int ret = IRQ_NONE; struct isp1301 *isp = _isp; + struct usb_otg *otg = isp->phy.otg; /* update ISP1301 transceiver from OTG controller */ if (otg_irq & OPRT_CHG) { @@ -675,7 +677,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) * remote wakeup (SRP, normal) using their own timer * to give "check cable and A-device" messages. */ - if (isp->otg.state == OTG_STATE_B_SRP_INIT) + if (isp->phy.state == OTG_STATE_B_SRP_INIT) b_idle(isp, "srp_timeout"); omap_writew(B_SRP_TMROUT, OTG_IRQ_SRC); @@ -693,7 +695,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) omap_writel(otg_ctrl, OTG_CTRL); /* subset of b_peripheral()... */ - isp->otg.state = OTG_STATE_B_PERIPHERAL; + isp->phy.state = OTG_STATE_B_PERIPHERAL; pr_debug(" --> b_peripheral\n"); omap_writew(B_HNP_FAIL, OTG_IRQ_SRC); @@ -705,9 +707,9 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) state_name(isp), omap_readl(OTG_CTRL)); isp1301_defer_work(isp, WORK_UPDATE_OTG); - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_A_IDLE: - if (!isp->otg.host) + if (!otg->host) break; isp1301_defer_work(isp, WORK_HOST_RESUME); otg_ctrl = omap_readl(OTG_CTRL); @@ -736,7 +738,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) otg_ctrl |= OTG_BUSDROP; otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS; omap_writel(otg_ctrl, OTG_CTRL); - isp->otg.state = OTG_STATE_A_WAIT_VFALL; + isp->phy.state = OTG_STATE_A_WAIT_VFALL; omap_writew(A_REQ_TMROUT, OTG_IRQ_SRC); ret = IRQ_HANDLED; @@ -750,7 +752,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) otg_ctrl |= OTG_BUSDROP; otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS; omap_writel(otg_ctrl, OTG_CTRL); - isp->otg.state = OTG_STATE_A_VBUS_ERR; + isp->phy.state = OTG_STATE_A_VBUS_ERR; omap_writew(A_VBUS_ERR, OTG_IRQ_SRC); ret = IRQ_HANDLED; @@ -771,7 +773,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) /* role is peripheral */ if (otg_ctrl & OTG_DRIVER_SEL) { - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_A_IDLE: b_idle(isp, __func__); break; @@ -787,19 +789,19 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) omap_writel(otg_ctrl | OTG_A_BUSREQ, OTG_CTRL); } - if (isp->otg.host) { - switch (isp->otg.state) { + if (otg->host) { + switch (isp->phy.state) { case OTG_STATE_B_WAIT_ACON: - isp->otg.state = OTG_STATE_B_HOST; + isp->phy.state = OTG_STATE_B_HOST; pr_debug(" --> b_host\n"); kick = 1; break; case OTG_STATE_A_WAIT_BCON: - isp->otg.state = OTG_STATE_A_HOST; + isp->phy.state = OTG_STATE_A_HOST; pr_debug(" --> a_host\n"); break; case OTG_STATE_A_PERIPHERAL: - isp->otg.state = OTG_STATE_A_WAIT_BCON; + isp->phy.state = OTG_STATE_A_WAIT_BCON; pr_debug(" --> a_wait_bcon\n"); break; default: @@ -813,8 +815,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) ret = IRQ_HANDLED; if (kick) - usb_bus_start_enum(isp->otg.host, - isp->otg.host->otg_port); + usb_bus_start_enum(otg->host, otg->host->otg_port); } check_state(isp, __func__); @@ -930,7 +931,7 @@ static void b_peripheral(struct isp1301 *isp) l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS; omap_writel(l, OTG_CTRL); - usb_gadget_vbus_connect(isp->otg.gadget); + usb_gadget_vbus_connect(isp->phy.otg->gadget); #ifdef CONFIG_USB_OTG enable_vbus_draw(isp, 8); @@ -940,7 +941,7 @@ static void b_peripheral(struct isp1301 *isp) /* UDC driver just set OTG_BSESSVLD */ isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP); isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN); - isp->otg.state = OTG_STATE_B_PERIPHERAL; + isp->phy.state = OTG_STATE_B_PERIPHERAL; pr_debug(" --> b_peripheral\n"); dump_regs(isp, "2periph"); #endif @@ -948,8 +949,9 @@ static void b_peripheral(struct isp1301 *isp) static void isp_update_otg(struct isp1301 *isp, u8 stat) { + struct usb_otg *otg = isp->phy.otg; u8 isp_stat, isp_bstat; - enum usb_otg_state state = isp->otg.state; + enum usb_otg_state state = isp->phy.state; if (stat & INTR_BDIS_ACON) pr_debug("OTG: BDIS_ACON, %s\n", state_name(isp)); @@ -957,7 +959,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) /* start certain state transitions right away */ isp_stat = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE); if (isp_stat & INTR_ID_GND) { - if (isp->otg.default_a) { + if (otg->default_a) { switch (state) { case OTG_STATE_B_IDLE: a_idle(isp, "idle"); @@ -972,7 +974,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) * when HNP is used. */ if (isp_stat & INTR_VBUS_VLD) - isp->otg.state = OTG_STATE_A_HOST; + isp->phy.state = OTG_STATE_A_HOST; break; case OTG_STATE_A_WAIT_VFALL: if (!(isp_stat & INTR_SESS_VLD)) @@ -980,7 +982,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) break; default: if (!(isp_stat & INTR_VBUS_VLD)) - isp->otg.state = OTG_STATE_A_VBUS_ERR; + isp->phy.state = OTG_STATE_A_VBUS_ERR; break; } isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS); @@ -989,14 +991,14 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_HOST: case OTG_STATE_B_WAIT_ACON: - usb_gadget_vbus_disconnect(isp->otg.gadget); + usb_gadget_vbus_disconnect(otg->gadget); break; default: break; } if (state != OTG_STATE_A_IDLE) a_idle(isp, "id"); - if (isp->otg.host && state == OTG_STATE_A_IDLE) + if (otg->host && state == OTG_STATE_A_IDLE) isp1301_defer_work(isp, WORK_HOST_RESUME); isp_bstat = 0; } @@ -1006,10 +1008,10 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) /* if user unplugged mini-A end of cable, * don't bypass A_WAIT_VFALL. */ - if (isp->otg.default_a) { + if (otg->default_a) { switch (state) { default: - isp->otg.state = OTG_STATE_A_WAIT_VFALL; + isp->phy.state = OTG_STATE_A_WAIT_VFALL; break; case OTG_STATE_A_WAIT_VFALL: state = OTG_STATE_A_IDLE; @@ -1022,7 +1024,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) host_suspend(isp); isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_BDIS_ACON_EN); - isp->otg.state = OTG_STATE_B_IDLE; + isp->phy.state = OTG_STATE_B_IDLE; l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; l &= ~OTG_CTRL_BITS; omap_writel(l, OTG_CTRL); @@ -1033,7 +1035,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) } isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS); - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_WAIT_ACON: case OTG_STATE_B_HOST: @@ -1055,7 +1057,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) omap_writel(l, OTG_CTRL); /* FALLTHROUGH */ case OTG_STATE_B_IDLE: - if (isp->otg.gadget && (isp_bstat & OTG_B_SESS_VLD)) { + if (otg->gadget && (isp_bstat & OTG_B_SESS_VLD)) { #ifdef CONFIG_USB_OTG update_otg1(isp, isp_stat); update_otg2(isp, isp_bstat); @@ -1073,7 +1075,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) } } - if (state != isp->otg.state) + if (state != isp->phy.state) pr_debug(" isp, %s -> %s\n", otg_state_string(state), state_name(isp)); @@ -1131,10 +1133,10 @@ isp1301_work(struct work_struct *work) * skip A_WAIT_VRISE; hc transitions invisibly * skip A_WAIT_BCON; same. */ - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_A_WAIT_BCON: case OTG_STATE_A_WAIT_VRISE: - isp->otg.state = OTG_STATE_A_HOST; + isp->phy.state = OTG_STATE_A_HOST; pr_debug(" --> a_host\n"); otg_ctrl = omap_readl(OTG_CTRL); otg_ctrl |= OTG_A_BUSREQ; @@ -1143,7 +1145,7 @@ isp1301_work(struct work_struct *work) omap_writel(otg_ctrl, OTG_CTRL); break; case OTG_STATE_B_WAIT_ACON: - isp->otg.state = OTG_STATE_B_HOST; + isp->phy.state = OTG_STATE_B_HOST; pr_debug(" --> b_host (acon)\n"); break; case OTG_STATE_B_HOST: @@ -1204,6 +1206,7 @@ static void isp1301_release(struct device *dev) /* ugly -- i2c hijacks our memory hook to wait_for_completion() */ if (isp->i2c_release) isp->i2c_release(dev); + kfree(isp->phy.otg); kfree (isp); } @@ -1274,9 +1277,9 @@ static int isp1301_otg_enable(struct isp1301 *isp) /* add or disable the host device+driver */ static int -isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) +isp1301_set_host(struct usb_otg *otg, struct usb_bus *host) { - struct isp1301 *isp = container_of(otg, struct isp1301, otg); + struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy); if (!otg || isp != the_transceiver) return -ENODEV; @@ -1284,21 +1287,21 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) if (!host) { omap_writew(0, OTG_IRQ_EN); power_down(isp); - isp->otg.host = NULL; + otg->host = NULL; return 0; } #ifdef CONFIG_USB_OTG - isp->otg.host = host; + otg->host = host; dev_dbg(&isp->client->dev, "registered host\n"); host_suspend(isp); - if (isp->otg.gadget) + if (otg->gadget) return isp1301_otg_enable(isp); return 0; #elif !defined(CONFIG_USB_GADGET_OMAP) // FIXME update its refcount - isp->otg.host = host; + otg->host = host; power_up(isp); @@ -1330,9 +1333,9 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) } static int -isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) +isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) { - struct isp1301 *isp = container_of(otg, struct isp1301, otg); + struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy); #ifndef CONFIG_USB_OTG u32 l; #endif @@ -1342,24 +1345,24 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) if (!gadget) { omap_writew(0, OTG_IRQ_EN); - if (!isp->otg.default_a) + if (!otg->default_a) enable_vbus_draw(isp, 0); - usb_gadget_vbus_disconnect(isp->otg.gadget); - isp->otg.gadget = NULL; + usb_gadget_vbus_disconnect(otg->gadget); + otg->gadget = NULL; power_down(isp); return 0; } #ifdef CONFIG_USB_OTG - isp->otg.gadget = gadget; + otg->gadget = gadget; dev_dbg(&isp->client->dev, "registered gadget\n"); /* gadget driver may be suspended until vbus_connect () */ - if (isp->otg.host) + if (otg->host) return isp1301_otg_enable(isp); return 0; #elif !defined(CONFIG_USB_OHCI_HCD) && !defined(CONFIG_USB_OHCI_HCD_MODULE) - isp->otg.gadget = gadget; + otg->gadget = gadget; // FIXME update its refcount l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; @@ -1368,7 +1371,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) omap_writel(l, OTG_CTRL); power_up(isp); - isp->otg.state = OTG_STATE_B_IDLE; + isp->phy.state = OTG_STATE_B_IDLE; if (machine_is_omap_h2() || machine_is_omap_h3()) isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); @@ -1399,7 +1402,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) /*-------------------------------------------------------------------------*/ static int -isp1301_set_power(struct otg_transceiver *dev, unsigned mA) +isp1301_set_power(struct usb_phy *dev, unsigned mA) { if (!the_transceiver) return -ENODEV; @@ -1409,13 +1412,13 @@ isp1301_set_power(struct otg_transceiver *dev, unsigned mA) } static int -isp1301_start_srp(struct otg_transceiver *dev) +isp1301_start_srp(struct usb_otg *otg) { - struct isp1301 *isp = container_of(dev, struct isp1301, otg); + struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy); u32 otg_ctrl; - if (!dev || isp != the_transceiver - || isp->otg.state != OTG_STATE_B_IDLE) + if (!otg || isp != the_transceiver + || isp->phy.state != OTG_STATE_B_IDLE) return -ENODEV; otg_ctrl = omap_readl(OTG_CTRL); @@ -1425,7 +1428,7 @@ isp1301_start_srp(struct otg_transceiver *dev) otg_ctrl |= OTG_B_BUSREQ; otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK; omap_writel(otg_ctrl, OTG_CTRL); - isp->otg.state = OTG_STATE_B_SRP_INIT; + isp->phy.state = OTG_STATE_B_SRP_INIT; pr_debug("otg: SRP, %s ... %06x\n", state_name(isp), omap_readl(OTG_CTRL)); @@ -1436,27 +1439,26 @@ isp1301_start_srp(struct otg_transceiver *dev) } static int -isp1301_start_hnp(struct otg_transceiver *dev) +isp1301_start_hnp(struct usb_otg *otg) { #ifdef CONFIG_USB_OTG - struct isp1301 *isp = container_of(dev, struct isp1301, otg); + struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy); u32 l; - if (!dev || isp != the_transceiver) + if (!otg || isp != the_transceiver) return -ENODEV; - if (isp->otg.default_a && (isp->otg.host == NULL - || !isp->otg.host->b_hnp_enable)) + if (otg->default_a && (otg->host == NULL || !otg->host->b_hnp_enable)) return -ENOTCONN; - if (!isp->otg.default_a && (isp->otg.gadget == NULL - || !isp->otg.gadget->b_hnp_enable)) + if (!otg->default_a && (otg->gadget == NULL + || !otg->gadget->b_hnp_enable)) return -ENOTCONN; /* We want hardware to manage most HNP protocol timings. * So do this part as early as possible... */ - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_B_HOST: - isp->otg.state = OTG_STATE_B_PERIPHERAL; + isp->phy.state = OTG_STATE_B_PERIPHERAL; /* caller will suspend next */ break; case OTG_STATE_A_HOST: @@ -1466,7 +1468,7 @@ isp1301_start_hnp(struct otg_transceiver *dev) MC1_BDIS_ACON_EN); #endif /* caller must suspend then clear A_BUSREQ */ - usb_gadget_vbus_connect(isp->otg.gadget); + usb_gadget_vbus_connect(otg->gadget); l = omap_readl(OTG_CTRL); l |= OTG_A_SETB_HNPEN; omap_writel(l, OTG_CTRL); @@ -1503,6 +1505,12 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) if (!isp) return 0; + isp->phy.otg = kzalloc(sizeof *isp->phy.otg, GFP_KERNEL); + if (!isp->phy.otg) { + kfree(isp); + return 0; + } + INIT_WORK(&isp->work, isp1301_work); init_timer(&isp->timer); isp->timer.function = isp1301_timer; @@ -1576,14 +1584,15 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) goto fail; } - isp->otg.dev = &i2c->dev; - isp->otg.label = DRIVER_NAME; + isp->phy.dev = &i2c->dev; + isp->phy.label = DRIVER_NAME; + isp->phy.set_power = isp1301_set_power, - isp->otg.set_host = isp1301_set_host, - isp->otg.set_peripheral = isp1301_set_peripheral, - isp->otg.set_power = isp1301_set_power, - isp->otg.start_srp = isp1301_start_srp, - isp->otg.start_hnp = isp1301_start_hnp, + isp->phy.otg->phy = &isp->phy; + isp->phy.otg->set_host = isp1301_set_host, + isp->phy.otg->set_peripheral = isp1301_set_peripheral, + isp->phy.otg->start_srp = isp1301_start_srp, + isp->phy.otg->start_hnp = isp1301_start_hnp, enable_vbus_draw(isp, 0); power_down(isp); @@ -1601,7 +1610,7 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES); #endif - status = otg_set_transceiver(&isp->otg); + status = usb_set_transceiver(&isp->phy); if (status < 0) dev_err(&i2c->dev, "can't register transceiver, %d\n", status); @@ -1609,6 +1618,7 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) return 0; fail: + kfree(isp->phy.otg); kfree(isp); return -ENODEV; } @@ -1639,7 +1649,7 @@ subsys_initcall(isp_init); static void __exit isp_exit(void) { if (the_transceiver) - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); i2c_del_driver(&isp1301_driver); } module_exit(isp_exit); diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c deleted file mode 100644 index f08f784..0000000 --- a/drivers/usb/otg/langwell_otg.c +++ /dev/null @@ -1,2347 +0,0 @@ -/* - * Intel Langwell USB OTG transceiver driver - * Copyright (C) 2008 - 2010, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -/* This driver helps to switch Langwell OTG controller function between host - * and peripheral. It works with EHCI driver and Langwell client controller - * driver together. - */ -#include <linux/module.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/moduleparam.h> -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> -#include <linux/usb.h> -#include <linux/usb/otg.h> -#include <linux/usb/hcd.h> -#include <linux/notifier.h> -#include <linux/delay.h> -#include <asm/intel_scu_ipc.h> - -#include <linux/usb/langwell_otg.h> - -#define DRIVER_DESC "Intel Langwell USB OTG transceiver driver" -#define DRIVER_VERSION "July 10, 2010" - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>"); -MODULE_VERSION(DRIVER_VERSION); -MODULE_LICENSE("GPL"); - -static const char driver_name[] = "langwell_otg"; - -static int langwell_otg_probe(struct pci_dev *pdev, - const struct pci_device_id *id); -static void langwell_otg_remove(struct pci_dev *pdev); -static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message); -static int langwell_otg_resume(struct pci_dev *pdev); - -static int langwell_otg_set_host(struct otg_transceiver *otg, - struct usb_bus *host); -static int langwell_otg_set_peripheral(struct otg_transceiver *otg, - struct usb_gadget *gadget); -static int langwell_otg_start_srp(struct otg_transceiver *otg); - -static const struct pci_device_id pci_ids[] = {{ - .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), - .class_mask = ~0, - .vendor = 0x8086, - .device = 0x0811, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, -}, { /* end: all zeroes */ } -}; - -static struct pci_driver otg_pci_driver = { - .name = (char *) driver_name, - .id_table = pci_ids, - - .probe = langwell_otg_probe, - .remove = langwell_otg_remove, - - .suspend = langwell_otg_suspend, - .resume = langwell_otg_resume, -}; - -/* HSM timers */ -static inline struct langwell_otg_timer *otg_timer_initializer -(void (*function)(unsigned long), unsigned long expires, unsigned long data) -{ - struct langwell_otg_timer *timer; - timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL); - if (timer == NULL) - return timer; - - timer->function = function; - timer->expires = expires; - timer->data = data; - return timer; -} - -static struct langwell_otg_timer *a_wait_vrise_tmr, *a_aidl_bdis_tmr, - *b_se0_srp_tmr, *b_srp_init_tmr; - -static struct list_head active_timers; - -static struct langwell_otg *the_transceiver; - -/* host/client notify transceiver when event affects HNP state */ -void langwell_update_transceiver(void) -{ - struct langwell_otg *lnw = the_transceiver; - - dev_dbg(lnw->dev, "transceiver is updated\n"); - - if (!lnw->qwork) - return ; - - queue_work(lnw->qwork, &lnw->work); -} -EXPORT_SYMBOL(langwell_update_transceiver); - -static int langwell_otg_set_host(struct otg_transceiver *otg, - struct usb_bus *host) -{ - otg->host = host; - - return 0; -} - -static int langwell_otg_set_peripheral(struct otg_transceiver *otg, - struct usb_gadget *gadget) -{ - otg->gadget = gadget; - - return 0; -} - -static int langwell_otg_set_power(struct otg_transceiver *otg, - unsigned mA) -{ - return 0; -} - -/* A-device drives vbus, controlled through IPC commands */ -static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled) -{ - struct langwell_otg *lnw = the_transceiver; - u8 sub_id; - - dev_dbg(lnw->dev, "%s <--- %s\n", __func__, enabled ? "on" : "off"); - - if (enabled) - sub_id = 0x8; /* Turn on the VBus */ - else - sub_id = 0x9; /* Turn off the VBus */ - - if (intel_scu_ipc_simple_command(0xef, sub_id)) { - dev_dbg(lnw->dev, "Failed to set Vbus via IPC commands\n"); - return -EBUSY; - } - - dev_dbg(lnw->dev, "%s --->\n", __func__); - - return 0; -} - -/* charge vbus or discharge vbus through a resistor to ground */ -static void langwell_otg_chrg_vbus(int on) -{ - struct langwell_otg *lnw = the_transceiver; - u32 val; - - val = readl(lnw->iotg.base + CI_OTGSC); - - if (on) - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC, - lnw->iotg.base + CI_OTGSC); - else - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD, - lnw->iotg.base + CI_OTGSC); -} - -/* Start SRP */ -static int langwell_otg_start_srp(struct otg_transceiver *otg) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val; - - dev_dbg(lnw->dev, "%s --->\n", __func__); - - val = readl(iotg->base + CI_OTGSC); - - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP, - iotg->base + CI_OTGSC); - - /* Check if the data plus is finished or not */ - msleep(8); - val = readl(iotg->base + CI_OTGSC); - if (val & (OTGSC_HADP | OTGSC_DP)) - dev_dbg(lnw->dev, "DataLine SRP Error\n"); - - /* Disable interrupt - b_sess_vld */ - val = readl(iotg->base + CI_OTGSC); - val &= (~(OTGSC_BSVIE | OTGSC_BSEIE)); - writel(val, iotg->base + CI_OTGSC); - - /* Start VBus SRP, drive vbus to generate VBus pulse */ - iotg->otg.set_vbus(&iotg->otg, true); - msleep(15); - iotg->otg.set_vbus(&iotg->otg, false); - - /* Enable interrupt - b_sess_vld*/ - val = readl(iotg->base + CI_OTGSC); - dev_dbg(lnw->dev, "after VBUS pulse otgsc = %x\n", val); - - val |= (OTGSC_BSVIE | OTGSC_BSEIE); - writel(val, iotg->base + CI_OTGSC); - - /* If Vbus is valid, then update the hsm */ - if (val & OTGSC_BSV) { - dev_dbg(lnw->dev, "no b_sess_vld interrupt\n"); - - lnw->iotg.hsm.b_sess_vld = 1; - langwell_update_transceiver(); - } - - dev_dbg(lnw->dev, "%s <---\n", __func__); - return 0; -} - -/* stop SOF via bus_suspend */ -static void langwell_otg_loc_sof(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct usb_hcd *hcd; - int err; - - dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "suspend" : "resume"); - - hcd = bus_to_hcd(lnw->iotg.otg.host); - if (on) - err = hcd->driver->bus_resume(hcd); - else - err = hcd->driver->bus_suspend(hcd); - - if (err) - dev_dbg(lnw->dev, "Fail to resume/suspend USB bus - %d\n", err); - - dev_dbg(lnw->dev, "%s <---\n", __func__); -} - -static int langwell_otg_check_otgsc(void) -{ - struct langwell_otg *lnw = the_transceiver; - u32 otgsc, usbcfg; - - dev_dbg(lnw->dev, "check sync OTGSC and USBCFG registers\n"); - - otgsc = readl(lnw->iotg.base + CI_OTGSC); - usbcfg = readl(lnw->usbcfg); - - dev_dbg(lnw->dev, "OTGSC = %08x, USBCFG = %08x\n", - otgsc, usbcfg); - dev_dbg(lnw->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV)); - dev_dbg(lnw->dev, "USBCFG.VBUSVAL = %d\n", - !!(usbcfg & USBCFG_VBUSVAL)); - dev_dbg(lnw->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV)); - dev_dbg(lnw->dev, "USBCFG.AVALID = %d\n", - !!(usbcfg & USBCFG_AVALID)); - dev_dbg(lnw->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV)); - dev_dbg(lnw->dev, "USBCFG.BVALID = %d\n", - !!(usbcfg & USBCFG_BVALID)); - dev_dbg(lnw->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE)); - dev_dbg(lnw->dev, "USBCFG.SESEND = %d\n", - !!(usbcfg & USBCFG_SESEND)); - - /* Check USBCFG VBusValid/AValid/BValid/SessEnd */ - if (!!(otgsc & OTGSC_AVV) ^ !!(usbcfg & USBCFG_VBUSVAL)) { - dev_dbg(lnw->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n"); - goto err; - } - if (!!(otgsc & OTGSC_ASV) ^ !!(usbcfg & USBCFG_AVALID)) { - dev_dbg(lnw->dev, "OTGSC.ASV != USBCFG.AVALID\n"); - goto err; - } - if (!!(otgsc & OTGSC_BSV) ^ !!(usbcfg & USBCFG_BVALID)) { - dev_dbg(lnw->dev, "OTGSC.BSV != USBCFG.BVALID\n"); - goto err; - } - if (!!(otgsc & OTGSC_BSE) ^ !!(usbcfg & USBCFG_SESEND)) { - dev_dbg(lnw->dev, "OTGSC.BSE != USBCFG.SESSEN\n"); - goto err; - } - - dev_dbg(lnw->dev, "OTGSC and USBCFG are synced\n"); - - return 0; - -err: - dev_warn(lnw->dev, "OTGSC isn't equal to USBCFG\n"); - return -EPIPE; -} - - -static void langwell_otg_phy_low_power(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u8 val, phcd; - int retval; - - dev_dbg(lnw->dev, "%s ---> %s mode\n", - __func__, on ? "Low power" : "Normal"); - - phcd = 0x40; - - val = readb(iotg->base + CI_HOSTPC1 + 2); - - if (on) { - /* Due to hardware issue, after set PHCD, sync will failed - * between USBCFG and OTGSC, so before set PHCD, check if - * sync is in process now. If the answer is "yes", then do - * not touch PHCD bit */ - retval = langwell_otg_check_otgsc(); - if (retval) { - dev_dbg(lnw->dev, "Skip PHCD programming..\n"); - return ; - } - - writeb(val | phcd, iotg->base + CI_HOSTPC1 + 2); - } else - writeb(val & ~phcd, iotg->base + CI_HOSTPC1 + 2); - - dev_dbg(lnw->dev, "%s <--- done\n", __func__); -} - -/* After drv vbus, add 5 ms delay to set PHCD */ -static void langwell_otg_phy_low_power_wait(int on) -{ - struct langwell_otg *lnw = the_transceiver; - - dev_dbg(lnw->dev, "add 5ms delay before programing PHCD\n"); - - mdelay(5); - langwell_otg_phy_low_power(on); -} - -/* Enable/Disable OTG interrupt */ -static void langwell_otg_intr(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val; - - dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); - - val = readl(iotg->base + CI_OTGSC); - - /* OTGSC_INT_MASK doesn't contains 1msInt */ - if (on) { - val = val | (OTGSC_INT_MASK); - writel(val, iotg->base + CI_OTGSC); - } else { - val = val & ~(OTGSC_INT_MASK); - writel(val, iotg->base + CI_OTGSC); - } - - dev_dbg(lnw->dev, "%s <---\n", __func__); -} - -/* set HAAR: Hardware Assist Auto-Reset */ -static void langwell_otg_HAAR(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val; - - dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); - - val = readl(iotg->base + CI_OTGSC); - if (on) - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR, - iotg->base + CI_OTGSC); - else - writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR, - iotg->base + CI_OTGSC); - - dev_dbg(lnw->dev, "%s <---\n", __func__); -} - -/* set HABA: Hardware Assist B-Disconnect to A-Connect */ -static void langwell_otg_HABA(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val; - - dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); - - val = readl(iotg->base + CI_OTGSC); - if (on) - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA, - iotg->base + CI_OTGSC); - else - writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA, - iotg->base + CI_OTGSC); - - dev_dbg(lnw->dev, "%s <---\n", __func__); -} - -static int langwell_otg_check_se0_srp(int on) -{ - struct langwell_otg *lnw = the_transceiver; - int delay_time = TB_SE0_SRP * 10; - u32 val; - - dev_dbg(lnw->dev, "%s --->\n", __func__); - - do { - udelay(100); - if (!delay_time--) - break; - val = readl(lnw->iotg.base + CI_PORTSC1); - val &= PORTSC_LS; - } while (!val); - - dev_dbg(lnw->dev, "%s <---\n", __func__); - return val; -} - -/* The timeout callback function to set time out bit */ -static void set_tmout(unsigned long indicator) -{ - *(int *)indicator = 1; -} - -void langwell_otg_nsf_msg(unsigned long indicator) -{ - struct langwell_otg *lnw = the_transceiver; - - switch (indicator) { - case 2: - case 4: - case 6: - case 7: - dev_warn(lnw->dev, - "OTG:NSF-%lu - deivce not responding\n", indicator); - break; - case 3: - dev_warn(lnw->dev, - "OTG:NSF-%lu - deivce not supported\n", indicator); - break; - default: - dev_warn(lnw->dev, "Do not have this kind of NSF\n"); - break; - } -} - -/* Initialize timers */ -static int langwell_otg_init_timers(struct otg_hsm *hsm) -{ - /* HSM used timers */ - a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE, - (unsigned long)&hsm->a_wait_vrise_tmout); - if (a_wait_vrise_tmr == NULL) - return -ENOMEM; - a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS, - (unsigned long)&hsm->a_aidl_bdis_tmout); - if (a_aidl_bdis_tmr == NULL) - return -ENOMEM; - b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP, - (unsigned long)&hsm->b_se0_srp); - if (b_se0_srp_tmr == NULL) - return -ENOMEM; - b_srp_init_tmr = otg_timer_initializer(&set_tmout, TB_SRP_INIT, - (unsigned long)&hsm->b_srp_init_tmout); - if (b_srp_init_tmr == NULL) - return -ENOMEM; - - return 0; -} - -/* Free timers */ -static void langwell_otg_free_timers(void) -{ - kfree(a_wait_vrise_tmr); - kfree(a_aidl_bdis_tmr); - kfree(b_se0_srp_tmr); - kfree(b_srp_init_tmr); -} - -/* The timeout callback function to set time out bit */ -static void langwell_otg_timer_fn(unsigned long indicator) -{ - struct langwell_otg *lnw = the_transceiver; - - *(int *)indicator = 1; - - dev_dbg(lnw->dev, "kernel timer - timeout\n"); - - langwell_update_transceiver(); -} - -/* kernel timer used instead of HW based interrupt */ -static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - unsigned long j = jiffies; - unsigned long data, time; - - switch (timers) { - case TA_WAIT_VRISE_TMR: - iotg->hsm.a_wait_vrise_tmout = 0; - data = (unsigned long)&iotg->hsm.a_wait_vrise_tmout; - time = TA_WAIT_VRISE; - break; - case TA_WAIT_BCON_TMR: - iotg->hsm.a_wait_bcon_tmout = 0; - data = (unsigned long)&iotg->hsm.a_wait_bcon_tmout; - time = TA_WAIT_BCON; - break; - case TA_AIDL_BDIS_TMR: - iotg->hsm.a_aidl_bdis_tmout = 0; - data = (unsigned long)&iotg->hsm.a_aidl_bdis_tmout; - time = TA_AIDL_BDIS; - break; - case TB_ASE0_BRST_TMR: - iotg->hsm.b_ase0_brst_tmout = 0; - data = (unsigned long)&iotg->hsm.b_ase0_brst_tmout; - time = TB_ASE0_BRST; - break; - case TB_SRP_INIT_TMR: - iotg->hsm.b_srp_init_tmout = 0; - data = (unsigned long)&iotg->hsm.b_srp_init_tmout; - time = TB_SRP_INIT; - break; - case TB_SRP_FAIL_TMR: - iotg->hsm.b_srp_fail_tmout = 0; - data = (unsigned long)&iotg->hsm.b_srp_fail_tmout; - time = TB_SRP_FAIL; - break; - case TB_BUS_SUSPEND_TMR: - iotg->hsm.b_bus_suspend_tmout = 0; - data = (unsigned long)&iotg->hsm.b_bus_suspend_tmout; - time = TB_BUS_SUSPEND; - break; - default: - dev_dbg(lnw->dev, "unknown timer, cannot enable it\n"); - return; - } - - lnw->hsm_timer.data = data; - lnw->hsm_timer.function = langwell_otg_timer_fn; - lnw->hsm_timer.expires = j + time * HZ / 1000; /* milliseconds */ - - add_timer(&lnw->hsm_timer); - - dev_dbg(lnw->dev, "add timer successfully\n"); -} - -/* Add timer to timer list */ -static void langwell_otg_add_timer(void *gtimer) -{ - struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; - struct langwell_otg_timer *tmp_timer; - struct intel_mid_otg_xceiv *iotg = &the_transceiver->iotg; - u32 val32; - - /* Check if the timer is already in the active list, - * if so update timer count - */ - list_for_each_entry(tmp_timer, &active_timers, list) - if (tmp_timer == timer) { - timer->count = timer->expires; - return; - } - timer->count = timer->expires; - - if (list_empty(&active_timers)) { - val32 = readl(iotg->base + CI_OTGSC); - writel(val32 | OTGSC_1MSE, iotg->base + CI_OTGSC); - } - - list_add_tail(&timer->list, &active_timers); -} - -/* Remove timer from the timer list; clear timeout status */ -static void langwell_otg_del_timer(void *gtimer) -{ - struct langwell_otg *lnw = the_transceiver; - struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; - struct langwell_otg_timer *tmp_timer, *del_tmp; - u32 val32; - - list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) - if (tmp_timer == timer) - list_del(&timer->list); - - if (list_empty(&active_timers)) { - val32 = readl(lnw->iotg.base + CI_OTGSC); - writel(val32 & ~OTGSC_1MSE, lnw->iotg.base + CI_OTGSC); - } -} - -/* Reduce timer count by 1, and find timeout conditions.*/ -static int langwell_otg_tick_timer(u32 *int_sts) -{ - struct langwell_otg *lnw = the_transceiver; - struct langwell_otg_timer *tmp_timer, *del_tmp; - int expired = 0; - - list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) { - tmp_timer->count--; - /* check if timer expires */ - if (!tmp_timer->count) { - list_del(&tmp_timer->list); - tmp_timer->function(tmp_timer->data); - expired = 1; - } - } - - if (list_empty(&active_timers)) { - dev_dbg(lnw->dev, "tick timer: disable 1ms int\n"); - *int_sts = *int_sts & ~OTGSC_1MSE; - } - return expired; -} - -static void reset_otg(void) -{ - struct langwell_otg *lnw = the_transceiver; - int delay_time = 1000; - u32 val; - - dev_dbg(lnw->dev, "reseting OTG controller ...\n"); - val = readl(lnw->iotg.base + CI_USBCMD); - writel(val | USBCMD_RST, lnw->iotg.base + CI_USBCMD); - do { - udelay(100); - if (!delay_time--) - dev_dbg(lnw->dev, "reset timeout\n"); - val = readl(lnw->iotg.base + CI_USBCMD); - val &= USBCMD_RST; - } while (val != 0); - dev_dbg(lnw->dev, "reset done.\n"); -} - -static void set_host_mode(void) -{ - struct langwell_otg *lnw = the_transceiver; - u32 val; - - reset_otg(); - val = readl(lnw->iotg.base + CI_USBMODE); - val = (val & (~USBMODE_CM)) | USBMODE_HOST; - writel(val, lnw->iotg.base + CI_USBMODE); -} - -static void set_client_mode(void) -{ - struct langwell_otg *lnw = the_transceiver; - u32 val; - - reset_otg(); - val = readl(lnw->iotg.base + CI_USBMODE); - val = (val & (~USBMODE_CM)) | USBMODE_DEVICE; - writel(val, lnw->iotg.base + CI_USBMODE); -} - -static void init_hsm(void) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val32; - - /* read OTGSC after reset */ - val32 = readl(lnw->iotg.base + CI_OTGSC); - dev_dbg(lnw->dev, "%s: OTGSC init value = 0x%x\n", __func__, val32); - - /* set init state */ - if (val32 & OTGSC_ID) { - iotg->hsm.id = 1; - iotg->otg.default_a = 0; - set_client_mode(); - iotg->otg.state = OTG_STATE_B_IDLE; - } else { - iotg->hsm.id = 0; - iotg->otg.default_a = 1; - set_host_mode(); - iotg->otg.state = OTG_STATE_A_IDLE; - } - - /* set session indicator */ - if (val32 & OTGSC_BSE) - iotg->hsm.b_sess_end = 1; - if (val32 & OTGSC_BSV) - iotg->hsm.b_sess_vld = 1; - if (val32 & OTGSC_ASV) - iotg->hsm.a_sess_vld = 1; - if (val32 & OTGSC_AVV) - iotg->hsm.a_vbus_vld = 1; - - /* defautly power the bus */ - iotg->hsm.a_bus_req = 1; - iotg->hsm.a_bus_drop = 0; - /* defautly don't request bus as B device */ - iotg->hsm.b_bus_req = 0; - /* no system error */ - iotg->hsm.a_clr_err = 0; - - langwell_otg_phy_low_power_wait(1); -} - -static void update_hsm(void) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val32; - - /* read OTGSC */ - val32 = readl(lnw->iotg.base + CI_OTGSC); - dev_dbg(lnw->dev, "%s: OTGSC value = 0x%x\n", __func__, val32); - - iotg->hsm.id = !!(val32 & OTGSC_ID); - iotg->hsm.b_sess_end = !!(val32 & OTGSC_BSE); - iotg->hsm.b_sess_vld = !!(val32 & OTGSC_BSV); - iotg->hsm.a_sess_vld = !!(val32 & OTGSC_ASV); - iotg->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV); -} - -static irqreturn_t otg_dummy_irq(int irq, void *_dev) -{ - struct langwell_otg *lnw = the_transceiver; - void __iomem *reg_base = _dev; - u32 val; - u32 int_mask = 0; - - val = readl(reg_base + CI_USBMODE); - if ((val & USBMODE_CM) != USBMODE_DEVICE) - return IRQ_NONE; - - val = readl(reg_base + CI_USBSTS); - int_mask = val & INTR_DUMMY_MASK; - - if (int_mask == 0) - return IRQ_NONE; - - /* clear hsm.b_conn here since host driver can't detect it - * otg_dummy_irq called means B-disconnect happened. - */ - if (lnw->iotg.hsm.b_conn) { - lnw->iotg.hsm.b_conn = 0; - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - } - - /* Clear interrupts */ - writel(int_mask, reg_base + CI_USBSTS); - return IRQ_HANDLED; -} - -static irqreturn_t otg_irq(int irq, void *_dev) -{ - struct langwell_otg *lnw = _dev; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 int_sts, int_en; - u32 int_mask = 0; - int flag = 0; - - int_sts = readl(lnw->iotg.base + CI_OTGSC); - int_en = (int_sts & OTGSC_INTEN_MASK) >> 8; - int_mask = int_sts & int_en; - if (int_mask == 0) - return IRQ_NONE; - - if (int_mask & OTGSC_IDIS) { - dev_dbg(lnw->dev, "%s: id change int\n", __func__); - iotg->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0; - dev_dbg(lnw->dev, "id = %d\n", iotg->hsm.id); - flag = 1; - } - if (int_mask & OTGSC_DPIS) { - dev_dbg(lnw->dev, "%s: data pulse int\n", __func__); - iotg->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0; - dev_dbg(lnw->dev, "data pulse = %d\n", iotg->hsm.a_srp_det); - flag = 1; - } - if (int_mask & OTGSC_BSEIS) { - dev_dbg(lnw->dev, "%s: b session end int\n", __func__); - iotg->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0; - dev_dbg(lnw->dev, "b_sess_end = %d\n", iotg->hsm.b_sess_end); - flag = 1; - } - if (int_mask & OTGSC_BSVIS) { - dev_dbg(lnw->dev, "%s: b session valid int\n", __func__); - iotg->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0; - dev_dbg(lnw->dev, "b_sess_vld = %d\n", iotg->hsm.b_sess_end); - flag = 1; - } - if (int_mask & OTGSC_ASVIS) { - dev_dbg(lnw->dev, "%s: a session valid int\n", __func__); - iotg->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0; - dev_dbg(lnw->dev, "a_sess_vld = %d\n", iotg->hsm.a_sess_vld); - flag = 1; - } - if (int_mask & OTGSC_AVVIS) { - dev_dbg(lnw->dev, "%s: a vbus valid int\n", __func__); - iotg->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0; - dev_dbg(lnw->dev, "a_vbus_vld = %d\n", iotg->hsm.a_vbus_vld); - flag = 1; - } - - if (int_mask & OTGSC_1MSS) { - /* need to schedule otg_work if any timer is expired */ - if (langwell_otg_tick_timer(&int_sts)) - flag = 1; - } - - writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask, - lnw->iotg.base + CI_OTGSC); - if (flag) - langwell_update_transceiver(); - - return IRQ_HANDLED; -} - -static int langwell_otg_iotg_notify(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = data; - int flag = 0; - - if (iotg == NULL) - return NOTIFY_BAD; - - if (lnw == NULL) - return NOTIFY_BAD; - - switch (action) { - case MID_OTG_NOTIFY_CONNECT: - dev_dbg(lnw->dev, "Lnw OTG Notify Connect Event\n"); - if (iotg->otg.default_a == 1) - iotg->hsm.b_conn = 1; - else - iotg->hsm.a_conn = 1; - flag = 1; - break; - case MID_OTG_NOTIFY_DISCONN: - dev_dbg(lnw->dev, "Lnw OTG Notify Disconnect Event\n"); - if (iotg->otg.default_a == 1) - iotg->hsm.b_conn = 0; - else - iotg->hsm.a_conn = 0; - flag = 1; - break; - case MID_OTG_NOTIFY_HSUSPEND: - dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus suspend Event\n"); - if (iotg->otg.default_a == 1) - iotg->hsm.a_suspend_req = 1; - else - iotg->hsm.b_bus_req = 0; - flag = 1; - break; - case MID_OTG_NOTIFY_HRESUME: - dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus resume Event\n"); - if (iotg->otg.default_a == 1) - iotg->hsm.b_bus_resume = 1; - flag = 1; - break; - case MID_OTG_NOTIFY_CSUSPEND: - dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus suspend Event\n"); - if (iotg->otg.default_a == 1) { - if (iotg->hsm.b_bus_suspend_vld == 2) { - iotg->hsm.b_bus_suspend = 1; - iotg->hsm.b_bus_suspend_vld = 0; - flag = 1; - } else { - iotg->hsm.b_bus_suspend_vld++; - flag = 0; - } - } else { - if (iotg->hsm.a_bus_suspend == 0) { - iotg->hsm.a_bus_suspend = 1; - flag = 1; - } - } - break; - case MID_OTG_NOTIFY_CRESUME: - dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus resume Event\n"); - if (iotg->otg.default_a == 0) - iotg->hsm.a_bus_suspend = 0; - flag = 0; - break; - case MID_OTG_NOTIFY_HOSTADD: - dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver Add\n"); - flag = 1; - break; - case MID_OTG_NOTIFY_HOSTREMOVE: - dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver remove\n"); - flag = 1; - break; - case MID_OTG_NOTIFY_CLIENTADD: - dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver Add\n"); - flag = 1; - break; - case MID_OTG_NOTIFY_CLIENTREMOVE: - dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver remove\n"); - flag = 1; - break; - default: - dev_dbg(lnw->dev, "Lnw OTG Nofity unknown notify message\n"); - return NOTIFY_DONE; - } - - if (flag) - langwell_update_transceiver(); - - return NOTIFY_OK; -} - -static void langwell_otg_work(struct work_struct *work) -{ - struct langwell_otg *lnw; - struct intel_mid_otg_xceiv *iotg; - int retval; - struct pci_dev *pdev; - - lnw = container_of(work, struct langwell_otg, work); - iotg = &lnw->iotg; - pdev = to_pci_dev(lnw->dev); - - dev_dbg(lnw->dev, "%s: old state = %s\n", __func__, - otg_state_string(iotg->otg.state)); - - switch (iotg->otg.state) { - case OTG_STATE_UNDEFINED: - case OTG_STATE_B_IDLE: - if (!iotg->hsm.id) { - langwell_otg_del_timer(b_srp_init_tmr); - del_timer_sync(&lnw->hsm_timer); - - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - langwell_otg_chrg_vbus(0); - set_host_mode(); - langwell_otg_phy_low_power(1); - - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.b_sess_vld) { - langwell_otg_del_timer(b_srp_init_tmr); - del_timer_sync(&lnw->hsm_timer); - iotg->hsm.b_sess_end = 0; - iotg->hsm.a_bus_suspend = 0; - langwell_otg_chrg_vbus(0); - - if (lnw->iotg.start_peripheral) { - lnw->iotg.start_peripheral(&lnw->iotg); - iotg->otg.state = OTG_STATE_B_PERIPHERAL; - } else - dev_dbg(lnw->dev, "client driver not loaded\n"); - - } else if (iotg->hsm.b_srp_init_tmout) { - iotg->hsm.b_srp_init_tmout = 0; - dev_warn(lnw->dev, "SRP init timeout\n"); - } else if (iotg->hsm.b_srp_fail_tmout) { - iotg->hsm.b_srp_fail_tmout = 0; - iotg->hsm.b_bus_req = 0; - - /* No silence failure */ - langwell_otg_nsf_msg(6); - } else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) { - del_timer_sync(&lnw->hsm_timer); - /* workaround for b_se0_srp detection */ - retval = langwell_otg_check_se0_srp(0); - if (retval) { - iotg->hsm.b_bus_req = 0; - dev_dbg(lnw->dev, "LS isn't SE0, try later\n"); - } else { - /* clear the PHCD before start srp */ - langwell_otg_phy_low_power(0); - - /* Start SRP */ - langwell_otg_add_timer(b_srp_init_tmr); - iotg->otg.start_srp(&iotg->otg); - langwell_otg_del_timer(b_srp_init_tmr); - langwell_otg_add_ktimer(TB_SRP_FAIL_TMR); - - /* reset PHY low power mode here */ - langwell_otg_phy_low_power_wait(1); - } - } - break; - case OTG_STATE_B_SRP_INIT: - if (!iotg->hsm.id) { - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_chrg_vbus(0); - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.b_sess_vld) { - langwell_otg_chrg_vbus(0); - if (lnw->iotg.start_peripheral) { - lnw->iotg.start_peripheral(&lnw->iotg); - iotg->otg.state = OTG_STATE_B_PERIPHERAL; - } else - dev_dbg(lnw->dev, "client driver not loaded\n"); - } - break; - case OTG_STATE_B_PERIPHERAL: - if (!iotg->hsm.id) { - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - langwell_otg_chrg_vbus(0); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.b_sess_vld) { - iotg->hsm.b_hnp_enable = 0; - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - iotg->otg.state = OTG_STATE_B_IDLE; - } else if (iotg->hsm.b_bus_req && iotg->otg.gadget && - iotg->otg.gadget->b_hnp_enable && - iotg->hsm.a_bus_suspend) { - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - langwell_otg_HAAR(1); - iotg->hsm.a_conn = 0; - - if (lnw->iotg.start_host) { - lnw->iotg.start_host(&lnw->iotg); - iotg->otg.state = OTG_STATE_B_WAIT_ACON; - } else - dev_dbg(lnw->dev, - "host driver not loaded.\n"); - - iotg->hsm.a_bus_resume = 0; - langwell_otg_add_ktimer(TB_ASE0_BRST_TMR); - } - break; - - case OTG_STATE_B_WAIT_ACON: - if (!iotg->hsm.id) { - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - langwell_otg_chrg_vbus(0); - - langwell_otg_HAAR(0); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.b_sess_vld) { - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - iotg->hsm.b_hnp_enable = 0; - iotg->hsm.b_bus_req = 0; - - langwell_otg_chrg_vbus(0); - langwell_otg_HAAR(0); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - } else if (iotg->hsm.a_conn) { - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - langwell_otg_HAAR(0); - iotg->otg.state = OTG_STATE_B_HOST; - langwell_update_transceiver(); - } else if (iotg->hsm.a_bus_resume || - iotg->hsm.b_ase0_brst_tmout) { - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - langwell_otg_HAAR(0); - langwell_otg_nsf_msg(7); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - iotg->hsm.a_bus_suspend = 0; - iotg->hsm.b_bus_req = 0; - - if (lnw->iotg.start_peripheral) - lnw->iotg.start_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver not loaded.\n"); - - iotg->otg.state = OTG_STATE_B_PERIPHERAL; - } - break; - - case OTG_STATE_B_HOST: - if (!iotg->hsm.id) { - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - langwell_otg_chrg_vbus(0); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.b_sess_vld) { - iotg->hsm.b_hnp_enable = 0; - iotg->hsm.b_bus_req = 0; - - langwell_otg_chrg_vbus(0); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - } else if ((!iotg->hsm.b_bus_req) || - (!iotg->hsm.a_conn)) { - iotg->hsm.b_bus_req = 0; - langwell_otg_loc_sof(0); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - iotg->hsm.a_bus_suspend = 0; - - if (lnw->iotg.start_peripheral) - lnw->iotg.start_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver not loaded.\n"); - - iotg->otg.state = OTG_STATE_B_PERIPHERAL; - } - break; - - case OTG_STATE_A_IDLE: - iotg->otg.default_a = 1; - if (iotg->hsm.id) { - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - iotg->hsm.vbus_srp_up = 0; - - langwell_otg_chrg_vbus(0); - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_bus_drop && - (iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) { - langwell_otg_phy_low_power(0); - - /* Turn on VBus */ - iotg->otg.set_vbus(&iotg->otg, true); - - iotg->hsm.vbus_srp_up = 0; - iotg->hsm.a_wait_vrise_tmout = 0; - langwell_otg_add_timer(a_wait_vrise_tmr); - iotg->otg.state = OTG_STATE_A_WAIT_VRISE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) { - iotg->hsm.vbus_srp_up = 1; - } else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) { - msleep(10); - langwell_otg_phy_low_power(0); - - /* Turn on VBus */ - iotg->otg.set_vbus(&iotg->otg, true); - iotg->hsm.a_srp_det = 1; - iotg->hsm.vbus_srp_up = 0; - iotg->hsm.a_wait_vrise_tmout = 0; - langwell_otg_add_timer(a_wait_vrise_tmr); - iotg->otg.state = OTG_STATE_A_WAIT_VRISE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_sess_vld && - !iotg->hsm.vbus_srp_up) { - langwell_otg_phy_low_power(1); - } - break; - case OTG_STATE_A_WAIT_VRISE: - if (iotg->hsm.id) { - langwell_otg_del_timer(a_wait_vrise_tmr); - iotg->hsm.b_bus_req = 0; - iotg->otg.default_a = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_B_IDLE; - } else if (iotg->hsm.a_vbus_vld) { - langwell_otg_del_timer(a_wait_vrise_tmr); - iotg->hsm.b_conn = 0; - if (lnw->iotg.start_host) - lnw->iotg.start_host(&lnw->iotg); - else { - dev_dbg(lnw->dev, "host driver not loaded.\n"); - break; - } - - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } else if (iotg->hsm.a_wait_vrise_tmout) { - iotg->hsm.b_conn = 0; - if (iotg->hsm.a_vbus_vld) { - if (lnw->iotg.start_host) - lnw->iotg.start_host(&lnw->iotg); - else { - dev_dbg(lnw->dev, - "host driver not loaded.\n"); - break; - } - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } else { - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } - } - break; - case OTG_STATE_A_WAIT_BCON: - if (iotg->hsm.id) { - /* delete hsm timer for a_wait_bcon_tmr */ - del_timer_sync(&lnw->hsm_timer); - - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_vbus_vld) { - /* delete hsm timer for a_wait_bcon_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } else if (iotg->hsm.a_bus_drop || - (iotg->hsm.a_wait_bcon_tmout && - !iotg->hsm.a_bus_req)) { - /* delete hsm timer for a_wait_bcon_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (iotg->hsm.b_conn) { - /* delete hsm timer for a_wait_bcon_tmr */ - del_timer_sync(&lnw->hsm_timer); - - iotg->hsm.a_suspend_req = 0; - iotg->otg.state = OTG_STATE_A_HOST; - if (iotg->hsm.a_srp_det && iotg->otg.host && - !iotg->otg.host->b_hnp_enable) { - /* SRP capable peripheral-only device */ - iotg->hsm.a_bus_req = 1; - iotg->hsm.a_srp_det = 0; - } else if (!iotg->hsm.a_bus_req && iotg->otg.host && - iotg->otg.host->b_hnp_enable) { - /* It is not safe enough to do a fast - * transition from A_WAIT_BCON to - * A_SUSPEND */ - msleep(10000); - if (iotg->hsm.a_bus_req) - break; - - if (request_irq(pdev->irq, - otg_dummy_irq, IRQF_SHARED, - driver_name, iotg->base) != 0) { - dev_dbg(lnw->dev, - "request interrupt %d fail\n", - pdev->irq); - } - - langwell_otg_HABA(1); - iotg->hsm.b_bus_resume = 0; - iotg->hsm.a_aidl_bdis_tmout = 0; - - langwell_otg_loc_sof(0); - /* clear PHCD to enable HW timer */ - langwell_otg_phy_low_power(0); - langwell_otg_add_timer(a_aidl_bdis_tmr); - iotg->otg.state = OTG_STATE_A_SUSPEND; - } else if (!iotg->hsm.a_bus_req && iotg->otg.host && - !iotg->otg.host->b_hnp_enable) { - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } - } - break; - case OTG_STATE_A_HOST: - if (iotg->hsm.id) { - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.a_bus_drop || - (iotg->otg.host && - !iotg->otg.host->b_hnp_enable && - !iotg->hsm.a_bus_req)) { - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (!iotg->hsm.a_vbus_vld) { - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } else if (iotg->otg.host && - iotg->otg.host->b_hnp_enable && - !iotg->hsm.a_bus_req) { - /* Set HABA to enable hardware assistance to signal - * A-connect after receiver B-disconnect. Hardware - * will then set client mode and enable URE, SLE and - * PCE after the assistance. otg_dummy_irq is used to - * clean these ints when client driver is not resumed. - */ - if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED, - driver_name, iotg->base) != 0) { - dev_dbg(lnw->dev, - "request interrupt %d failed\n", - pdev->irq); - } - - /* set HABA */ - langwell_otg_HABA(1); - iotg->hsm.b_bus_resume = 0; - iotg->hsm.a_aidl_bdis_tmout = 0; - langwell_otg_loc_sof(0); - /* clear PHCD to enable HW timer */ - langwell_otg_phy_low_power(0); - langwell_otg_add_timer(a_aidl_bdis_tmr); - iotg->otg.state = OTG_STATE_A_SUSPEND; - } else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) { - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } - break; - case OTG_STATE_A_SUSPEND: - if (iotg->hsm.id) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.a_bus_req || - iotg->hsm.b_bus_resume) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - iotg->hsm.a_suspend_req = 0; - langwell_otg_loc_sof(1); - iotg->otg.state = OTG_STATE_A_HOST; - } else if (iotg->hsm.a_aidl_bdis_tmout || - iotg->hsm.a_bus_drop) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (!iotg->hsm.b_conn && iotg->otg.host && - iotg->otg.host->b_hnp_enable) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - iotg->hsm.b_bus_suspend = 0; - iotg->hsm.b_bus_suspend_vld = 0; - - /* msleep(200); */ - if (lnw->iotg.start_peripheral) - lnw->iotg.start_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver not loaded.\n"); - - langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR); - iotg->otg.state = OTG_STATE_A_PERIPHERAL; - break; - } else if (!iotg->hsm.a_vbus_vld) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } - break; - case OTG_STATE_A_PERIPHERAL: - if (iotg->hsm.id) { - /* delete hsm timer for b_bus_suspend_tmr */ - del_timer_sync(&lnw->hsm_timer); - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_vbus_vld) { - /* delete hsm timer for b_bus_suspend_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } else if (iotg->hsm.a_bus_drop) { - /* delete hsm timer for b_bus_suspend_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (iotg->hsm.b_bus_suspend) { - /* delete hsm timer for b_bus_suspend_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - if (lnw->iotg.start_host) - lnw->iotg.start_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver not loaded.\n"); - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } else if (iotg->hsm.b_bus_suspend_tmout) { - u32 val; - val = readl(lnw->iotg.base + CI_PORTSC1); - if (!(val & PORTSC_SUSP)) - break; - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - if (lnw->iotg.start_host) - lnw->iotg.start_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver not loaded.\n"); - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } - break; - case OTG_STATE_A_VBUS_ERR: - if (iotg->hsm.id) { - iotg->otg.default_a = 0; - iotg->hsm.a_clr_err = 0; - iotg->hsm.a_srp_det = 0; - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.a_clr_err) { - iotg->hsm.a_clr_err = 0; - iotg->hsm.a_srp_det = 0; - reset_otg(); - init_hsm(); - if (iotg->otg.state == OTG_STATE_A_IDLE) - langwell_update_transceiver(); - } else { - /* FW will clear PHCD bit when any VBus - * event detected. Reset PHCD to 1 again */ - langwell_otg_phy_low_power(1); - } - break; - case OTG_STATE_A_WAIT_VFALL: - if (iotg->hsm.id) { - iotg->otg.default_a = 0; - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.a_bus_req) { - - /* Turn on VBus */ - iotg->otg.set_vbus(&iotg->otg, true); - iotg->hsm.a_wait_vrise_tmout = 0; - langwell_otg_add_timer(a_wait_vrise_tmr); - iotg->otg.state = OTG_STATE_A_WAIT_VRISE; - } else if (!iotg->hsm.a_sess_vld) { - iotg->hsm.a_srp_det = 0; - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - } - break; - default: - ; - } - - dev_dbg(lnw->dev, "%s: new state = %s\n", __func__, - otg_state_string(iotg->otg.state)); -} - -static ssize_t -show_registers(struct device *_dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - t = scnprintf(next, size, - "\n" - "USBCMD = 0x%08x\n" - "USBSTS = 0x%08x\n" - "USBINTR = 0x%08x\n" - "ASYNCLISTADDR = 0x%08x\n" - "PORTSC1 = 0x%08x\n" - "HOSTPC1 = 0x%08x\n" - "OTGSC = 0x%08x\n" - "USBMODE = 0x%08x\n", - readl(lnw->iotg.base + 0x30), - readl(lnw->iotg.base + 0x34), - readl(lnw->iotg.base + 0x38), - readl(lnw->iotg.base + 0x48), - readl(lnw->iotg.base + 0x74), - readl(lnw->iotg.base + 0xb4), - readl(lnw->iotg.base + 0xf4), - readl(lnw->iotg.base + 0xf8) - ); - size -= t; - next += t; - - return PAGE_SIZE - size; -} -static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); - -static ssize_t -show_hsm(struct device *_dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - if (iotg->otg.host) - iotg->hsm.a_set_b_hnp_en = iotg->otg.host->b_hnp_enable; - - if (iotg->otg.gadget) - iotg->hsm.b_hnp_enable = iotg->otg.gadget->b_hnp_enable; - - t = scnprintf(next, size, - "\n" - "current state = %s\n" - "a_bus_resume = \t%d\n" - "a_bus_suspend = \t%d\n" - "a_conn = \t%d\n" - "a_sess_vld = \t%d\n" - "a_srp_det = \t%d\n" - "a_vbus_vld = \t%d\n" - "b_bus_resume = \t%d\n" - "b_bus_suspend = \t%d\n" - "b_conn = \t%d\n" - "b_se0_srp = \t%d\n" - "b_sess_end = \t%d\n" - "b_sess_vld = \t%d\n" - "id = \t%d\n" - "a_set_b_hnp_en = \t%d\n" - "b_srp_done = \t%d\n" - "b_hnp_enable = \t%d\n" - "a_wait_vrise_tmout = \t%d\n" - "a_wait_bcon_tmout = \t%d\n" - "a_aidl_bdis_tmout = \t%d\n" - "b_ase0_brst_tmout = \t%d\n" - "a_bus_drop = \t%d\n" - "a_bus_req = \t%d\n" - "a_clr_err = \t%d\n" - "a_suspend_req = \t%d\n" - "b_bus_req = \t%d\n" - "b_bus_suspend_tmout = \t%d\n" - "b_bus_suspend_vld = \t%d\n", - otg_state_string(iotg->otg.state), - iotg->hsm.a_bus_resume, - iotg->hsm.a_bus_suspend, - iotg->hsm.a_conn, - iotg->hsm.a_sess_vld, - iotg->hsm.a_srp_det, - iotg->hsm.a_vbus_vld, - iotg->hsm.b_bus_resume, - iotg->hsm.b_bus_suspend, - iotg->hsm.b_conn, - iotg->hsm.b_se0_srp, - iotg->hsm.b_sess_end, - iotg->hsm.b_sess_vld, - iotg->hsm.id, - iotg->hsm.a_set_b_hnp_en, - iotg->hsm.b_srp_done, - iotg->hsm.b_hnp_enable, - iotg->hsm.a_wait_vrise_tmout, - iotg->hsm.a_wait_bcon_tmout, - iotg->hsm.a_aidl_bdis_tmout, - iotg->hsm.b_ase0_brst_tmout, - iotg->hsm.a_bus_drop, - iotg->hsm.a_bus_req, - iotg->hsm.a_clr_err, - iotg->hsm.a_suspend_req, - iotg->hsm.b_bus_req, - iotg->hsm.b_bus_suspend_tmout, - iotg->hsm.b_bus_suspend_vld - ); - size -= t; - next += t; - - return PAGE_SIZE - size; -} -static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL); - -static ssize_t -get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_req); - size -= t; - next += t; - - return PAGE_SIZE - size; -} - -static ssize_t -set_a_bus_req(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - - if (!iotg->otg.default_a) - return -1; - if (count > 2) - return -1; - - if (buf[0] == '0') { - iotg->hsm.a_bus_req = 0; - dev_dbg(lnw->dev, "User request: a_bus_req = 0\n"); - } else if (buf[0] == '1') { - /* If a_bus_drop is TRUE, a_bus_req can't be set */ - if (iotg->hsm.a_bus_drop) - return -1; - iotg->hsm.a_bus_req = 1; - dev_dbg(lnw->dev, "User request: a_bus_req = 1\n"); - } - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - return count; -} -static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, set_a_bus_req); - -static ssize_t -get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_drop); - size -= t; - next += t; - - return PAGE_SIZE - size; -} - -static ssize_t -set_a_bus_drop(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - - if (!iotg->otg.default_a) - return -1; - if (count > 2) - return -1; - - if (buf[0] == '0') { - iotg->hsm.a_bus_drop = 0; - dev_dbg(lnw->dev, "User request: a_bus_drop = 0\n"); - } else if (buf[0] == '1') { - iotg->hsm.a_bus_drop = 1; - iotg->hsm.a_bus_req = 0; - dev_dbg(lnw->dev, "User request: a_bus_drop = 1\n"); - dev_dbg(lnw->dev, "User request: and a_bus_req = 0\n"); - } - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - return count; -} -static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, get_a_bus_drop, set_a_bus_drop); - -static ssize_t -get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - t = scnprintf(next, size, "%d", lnw->iotg.hsm.b_bus_req); - size -= t; - next += t; - - return PAGE_SIZE - size; -} - -static ssize_t -set_b_bus_req(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - - if (iotg->otg.default_a) - return -1; - - if (count > 2) - return -1; - - if (buf[0] == '0') { - iotg->hsm.b_bus_req = 0; - dev_dbg(lnw->dev, "User request: b_bus_req = 0\n"); - } else if (buf[0] == '1') { - iotg->hsm.b_bus_req = 1; - dev_dbg(lnw->dev, "User request: b_bus_req = 1\n"); - } - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - return count; -} -static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR, get_b_bus_req, set_b_bus_req); - -static ssize_t -set_a_clr_err(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - - if (!iotg->otg.default_a) - return -1; - if (count > 2) - return -1; - - if (buf[0] == '1') { - iotg->hsm.a_clr_err = 1; - dev_dbg(lnw->dev, "User request: a_clr_err = 1\n"); - } - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - return count; -} -static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err); - -static struct attribute *inputs_attrs[] = { - &dev_attr_a_bus_req.attr, - &dev_attr_a_bus_drop.attr, - &dev_attr_b_bus_req.attr, - &dev_attr_a_clr_err.attr, - NULL, -}; - -static struct attribute_group debug_dev_attr_group = { - .name = "inputs", - .attrs = inputs_attrs, -}; - -static int langwell_otg_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - unsigned long resource, len; - void __iomem *base = NULL; - int retval; - u32 val32; - struct langwell_otg *lnw; - char qname[] = "langwell_otg_queue"; - - retval = 0; - dev_dbg(&pdev->dev, "\notg controller is detected.\n"); - if (pci_enable_device(pdev) < 0) { - retval = -ENODEV; - goto done; - } - - lnw = kzalloc(sizeof *lnw, GFP_KERNEL); - if (lnw == NULL) { - retval = -ENOMEM; - goto done; - } - the_transceiver = lnw; - - /* control register: BAR 0 */ - resource = pci_resource_start(pdev, 0); - len = pci_resource_len(pdev, 0); - if (!request_mem_region(resource, len, driver_name)) { - retval = -EBUSY; - goto err; - } - lnw->region = 1; - - base = ioremap_nocache(resource, len); - if (base == NULL) { - retval = -EFAULT; - goto err; - } - lnw->iotg.base = base; - - if (!request_mem_region(USBCFG_ADDR, USBCFG_LEN, driver_name)) { - retval = -EBUSY; - goto err; - } - lnw->cfg_region = 1; - - /* For the SCCB.USBCFG register */ - base = ioremap_nocache(USBCFG_ADDR, USBCFG_LEN); - if (base == NULL) { - retval = -EFAULT; - goto err; - } - lnw->usbcfg = base; - - if (!pdev->irq) { - dev_dbg(&pdev->dev, "No IRQ.\n"); - retval = -ENODEV; - goto err; - } - - lnw->qwork = create_singlethread_workqueue(qname); - if (!lnw->qwork) { - dev_dbg(&pdev->dev, "cannot create workqueue %s\n", qname); - retval = -ENOMEM; - goto err; - } - INIT_WORK(&lnw->work, langwell_otg_work); - - /* OTG common part */ - lnw->dev = &pdev->dev; - lnw->iotg.otg.dev = lnw->dev; - lnw->iotg.otg.label = driver_name; - lnw->iotg.otg.set_host = langwell_otg_set_host; - lnw->iotg.otg.set_peripheral = langwell_otg_set_peripheral; - lnw->iotg.otg.set_power = langwell_otg_set_power; - lnw->iotg.otg.set_vbus = langwell_otg_set_vbus; - lnw->iotg.otg.start_srp = langwell_otg_start_srp; - lnw->iotg.otg.state = OTG_STATE_UNDEFINED; - - if (otg_set_transceiver(&lnw->iotg.otg)) { - dev_dbg(lnw->dev, "can't set transceiver\n"); - retval = -EBUSY; - goto err; - } - - reset_otg(); - init_hsm(); - - spin_lock_init(&lnw->lock); - spin_lock_init(&lnw->wq_lock); - INIT_LIST_HEAD(&active_timers); - retval = langwell_otg_init_timers(&lnw->iotg.hsm); - if (retval) { - dev_dbg(&pdev->dev, "Failed to init timers\n"); - goto err; - } - - init_timer(&lnw->hsm_timer); - ATOMIC_INIT_NOTIFIER_HEAD(&lnw->iotg.iotg_notifier); - - lnw->iotg_notifier.notifier_call = langwell_otg_iotg_notify; - - retval = intel_mid_otg_register_notifier(&lnw->iotg, - &lnw->iotg_notifier); - if (retval) { - dev_dbg(lnw->dev, "Failed to register notifier\n"); - goto err; - } - - if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, - driver_name, lnw) != 0) { - dev_dbg(lnw->dev, "request interrupt %d failed\n", pdev->irq); - retval = -EBUSY; - goto err; - } - - /* enable OTGSC int */ - val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE | - OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU; - writel(val32, lnw->iotg.base + CI_OTGSC); - - retval = device_create_file(&pdev->dev, &dev_attr_registers); - if (retval < 0) { - dev_dbg(lnw->dev, - "Can't register sysfs attribute: %d\n", retval); - goto err; - } - - retval = device_create_file(&pdev->dev, &dev_attr_hsm); - if (retval < 0) { - dev_dbg(lnw->dev, "Can't hsm sysfs attribute: %d\n", retval); - goto err; - } - - retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group); - if (retval < 0) { - dev_dbg(lnw->dev, - "Can't register sysfs attr group: %d\n", retval); - goto err; - } - - if (lnw->iotg.otg.state == OTG_STATE_A_IDLE) - langwell_update_transceiver(); - - return 0; - -err: - if (the_transceiver) - langwell_otg_remove(pdev); -done: - return retval; -} - -static void langwell_otg_remove(struct pci_dev *pdev) -{ - struct langwell_otg *lnw = the_transceiver; - - if (lnw->qwork) { - flush_workqueue(lnw->qwork); - destroy_workqueue(lnw->qwork); - } - intel_mid_otg_unregister_notifier(&lnw->iotg, &lnw->iotg_notifier); - langwell_otg_free_timers(); - - /* disable OTGSC interrupt as OTGSC doesn't change in reset */ - writel(0, lnw->iotg.base + CI_OTGSC); - - if (pdev->irq) - free_irq(pdev->irq, lnw); - if (lnw->usbcfg) - iounmap(lnw->usbcfg); - if (lnw->cfg_region) - release_mem_region(USBCFG_ADDR, USBCFG_LEN); - if (lnw->iotg.base) - iounmap(lnw->iotg.base); - if (lnw->region) - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - - otg_set_transceiver(NULL); - pci_disable_device(pdev); - sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group); - device_remove_file(&pdev->dev, &dev_attr_hsm); - device_remove_file(&pdev->dev, &dev_attr_registers); - kfree(lnw); - lnw = NULL; -} - -static void transceiver_suspend(struct pci_dev *pdev) -{ - pci_save_state(pdev); - pci_set_power_state(pdev, PCI_D3hot); - langwell_otg_phy_low_power(1); -} - -static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - int ret = 0; - - /* Disbale OTG interrupts */ - langwell_otg_intr(0); - - if (pdev->irq) - free_irq(pdev->irq, lnw); - - /* Prevent more otg_work */ - flush_workqueue(lnw->qwork); - destroy_workqueue(lnw->qwork); - lnw->qwork = NULL; - - /* start actions */ - switch (iotg->otg.state) { - case OTG_STATE_A_WAIT_VFALL: - iotg->otg.state = OTG_STATE_A_IDLE; - case OTG_STATE_A_IDLE: - case OTG_STATE_B_IDLE: - case OTG_STATE_A_VBUS_ERR: - transceiver_suspend(pdev); - break; - case OTG_STATE_A_WAIT_VRISE: - langwell_otg_del_timer(a_wait_vrise_tmr); - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_A_WAIT_BCON: - del_timer_sync(&lnw->hsm_timer); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(&pdev->dev, "host driver has been removed.\n"); - - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_A_HOST: - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(&pdev->dev, "host driver has been removed.\n"); - - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_A_SUSPEND: - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, "host driver has been removed.\n"); - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_A_PERIPHERAL: - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(&pdev->dev, - "client driver has been removed.\n"); - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_B_HOST: - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(&pdev->dev, "host driver has been removed.\n"); - iotg->hsm.b_bus_req = 0; - iotg->otg.state = OTG_STATE_B_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_B_PERIPHERAL: - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(&pdev->dev, - "client driver has been removed.\n"); - iotg->otg.state = OTG_STATE_B_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_B_WAIT_ACON: - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - langwell_otg_HAAR(0); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(&pdev->dev, "host driver has been removed.\n"); - iotg->hsm.b_bus_req = 0; - iotg->otg.state = OTG_STATE_B_IDLE; - transceiver_suspend(pdev); - break; - default: - dev_dbg(lnw->dev, "error state before suspend\n"); - break; - } - - return ret; -} - -static void transceiver_resume(struct pci_dev *pdev) -{ - pci_restore_state(pdev); - pci_set_power_state(pdev, PCI_D0); -} - -static int langwell_otg_resume(struct pci_dev *pdev) -{ - struct langwell_otg *lnw = the_transceiver; - int ret = 0; - - transceiver_resume(pdev); - - lnw->qwork = create_singlethread_workqueue("langwell_otg_queue"); - if (!lnw->qwork) { - dev_dbg(&pdev->dev, "cannot create langwell otg workqueuen"); - ret = -ENOMEM; - goto error; - } - - if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, - driver_name, lnw) != 0) { - dev_dbg(&pdev->dev, "request interrupt %d failed\n", pdev->irq); - ret = -EBUSY; - goto error; - } - - /* enable OTG interrupts */ - langwell_otg_intr(1); - - update_hsm(); - - langwell_update_transceiver(); - - return ret; -error: - langwell_otg_intr(0); - transceiver_suspend(pdev); - return ret; -} - -static int __init langwell_otg_init(void) -{ - return pci_register_driver(&otg_pci_driver); -} -module_init(langwell_otg_init); - -static void __exit langwell_otg_cleanup(void) -{ - pci_unregister_driver(&otg_pci_driver); -} -module_exit(langwell_otg_cleanup); diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c index b276f8f..1d0347c2 100644 --- a/drivers/usb/otg/msm_otg.c +++ b/drivers/usb/otg/msm_otg.c @@ -69,9 +69,9 @@ static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) int ret = 0; if (init) { - hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX"); + hsusb_vddcx = regulator_get(motg->phy.dev, "HSUSB_VDDCX"); if (IS_ERR(hsusb_vddcx)) { - dev_err(motg->otg.dev, "unable to get hsusb vddcx\n"); + dev_err(motg->phy.dev, "unable to get hsusb vddcx\n"); return PTR_ERR(hsusb_vddcx); } @@ -79,7 +79,7 @@ static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) USB_PHY_VDD_DIG_VOL_MIN, USB_PHY_VDD_DIG_VOL_MAX); if (ret) { - dev_err(motg->otg.dev, "unable to set the voltage " + dev_err(motg->phy.dev, "unable to set the voltage " "for hsusb vddcx\n"); regulator_put(hsusb_vddcx); return ret; @@ -87,18 +87,18 @@ static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) ret = regulator_enable(hsusb_vddcx); if (ret) { - dev_err(motg->otg.dev, "unable to enable hsusb vddcx\n"); + dev_err(motg->phy.dev, "unable to enable hsusb vddcx\n"); regulator_put(hsusb_vddcx); } } else { ret = regulator_set_voltage(hsusb_vddcx, 0, USB_PHY_VDD_DIG_VOL_MAX); if (ret) - dev_err(motg->otg.dev, "unable to set the voltage " + dev_err(motg->phy.dev, "unable to set the voltage " "for hsusb vddcx\n"); ret = regulator_disable(hsusb_vddcx); if (ret) - dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n"); + dev_err(motg->phy.dev, "unable to disable hsusb vddcx\n"); regulator_put(hsusb_vddcx); } @@ -111,40 +111,40 @@ static int msm_hsusb_ldo_init(struct msm_otg *motg, int init) int rc = 0; if (init) { - hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3"); + hsusb_3p3 = regulator_get(motg->phy.dev, "HSUSB_3p3"); if (IS_ERR(hsusb_3p3)) { - dev_err(motg->otg.dev, "unable to get hsusb 3p3\n"); + dev_err(motg->phy.dev, "unable to get hsusb 3p3\n"); return PTR_ERR(hsusb_3p3); } rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN, USB_PHY_3P3_VOL_MAX); if (rc) { - dev_err(motg->otg.dev, "unable to set voltage level " + dev_err(motg->phy.dev, "unable to set voltage level " "for hsusb 3p3\n"); goto put_3p3; } rc = regulator_enable(hsusb_3p3); if (rc) { - dev_err(motg->otg.dev, "unable to enable the hsusb 3p3\n"); + dev_err(motg->phy.dev, "unable to enable the hsusb 3p3\n"); goto put_3p3; } - hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8"); + hsusb_1p8 = regulator_get(motg->phy.dev, "HSUSB_1p8"); if (IS_ERR(hsusb_1p8)) { - dev_err(motg->otg.dev, "unable to get hsusb 1p8\n"); + dev_err(motg->phy.dev, "unable to get hsusb 1p8\n"); rc = PTR_ERR(hsusb_1p8); goto disable_3p3; } rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN, USB_PHY_1P8_VOL_MAX); if (rc) { - dev_err(motg->otg.dev, "unable to set voltage level " + dev_err(motg->phy.dev, "unable to set voltage level " "for hsusb 1p8\n"); goto put_1p8; } rc = regulator_enable(hsusb_1p8); if (rc) { - dev_err(motg->otg.dev, "unable to enable the hsusb 1p8\n"); + dev_err(motg->phy.dev, "unable to enable the hsusb 1p8\n"); goto put_1p8; } @@ -235,9 +235,9 @@ static int msm_hsusb_ldo_set_mode(int on) return ret < 0 ? ret : 0; } -static int ulpi_read(struct otg_transceiver *otg, u32 reg) +static int ulpi_read(struct usb_phy *phy, u32 reg) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(phy, struct msm_otg, phy); int cnt = 0; /* initiate read operation */ @@ -253,16 +253,16 @@ static int ulpi_read(struct otg_transceiver *otg, u32 reg) } if (cnt >= ULPI_IO_TIMEOUT_USEC) { - dev_err(otg->dev, "ulpi_read: timeout %08x\n", + dev_err(phy->dev, "ulpi_read: timeout %08x\n", readl(USB_ULPI_VIEWPORT)); return -ETIMEDOUT; } return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT)); } -static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg) +static int ulpi_write(struct usb_phy *phy, u32 val, u32 reg) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(phy, struct msm_otg, phy); int cnt = 0; /* initiate write operation */ @@ -279,13 +279,13 @@ static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg) } if (cnt >= ULPI_IO_TIMEOUT_USEC) { - dev_err(otg->dev, "ulpi_write: timeout\n"); + dev_err(phy->dev, "ulpi_write: timeout\n"); return -ETIMEDOUT; } return 0; } -static struct otg_io_access_ops msm_otg_io_ops = { +static struct usb_phy_io_ops msm_otg_io_ops = { .read = ulpi_read, .write = ulpi_write, }; @@ -299,9 +299,9 @@ static void ulpi_init(struct msm_otg *motg) return; while (seq[0] >= 0) { - dev_vdbg(motg->otg.dev, "ulpi: write 0x%02x to 0x%02x\n", + dev_vdbg(motg->phy.dev, "ulpi: write 0x%02x to 0x%02x\n", seq[0], seq[1]); - ulpi_write(&motg->otg, seq[0], seq[1]); + ulpi_write(&motg->phy, seq[0], seq[1]); seq += 2; } } @@ -313,11 +313,11 @@ static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert) if (assert) { ret = clk_reset(motg->clk, CLK_RESET_ASSERT); if (ret) - dev_err(motg->otg.dev, "usb hs_clk assert failed\n"); + dev_err(motg->phy.dev, "usb hs_clk assert failed\n"); } else { ret = clk_reset(motg->clk, CLK_RESET_DEASSERT); if (ret) - dev_err(motg->otg.dev, "usb hs_clk deassert failed\n"); + dev_err(motg->phy.dev, "usb hs_clk deassert failed\n"); } return ret; } @@ -328,13 +328,13 @@ static int msm_otg_phy_clk_reset(struct msm_otg *motg) ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT); if (ret) { - dev_err(motg->otg.dev, "usb phy clk assert failed\n"); + dev_err(motg->phy.dev, "usb phy clk assert failed\n"); return ret; } usleep_range(10000, 12000); ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT); if (ret) - dev_err(motg->otg.dev, "usb phy clk deassert failed\n"); + dev_err(motg->phy.dev, "usb phy clk deassert failed\n"); return ret; } @@ -358,7 +358,7 @@ static int msm_otg_phy_reset(struct msm_otg *motg) writel(val | PORTSC_PTS_ULPI, USB_PORTSC); for (retries = 3; retries > 0; retries--) { - ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM, + ret = ulpi_write(&motg->phy, ULPI_FUNC_CTRL_SUSPENDM, ULPI_CLR(ULPI_FUNC_CTRL)); if (!ret) break; @@ -375,7 +375,7 @@ static int msm_otg_phy_reset(struct msm_otg *motg) return ret; for (retries = 3; retries > 0; retries--) { - ret = ulpi_read(&motg->otg, ULPI_DEBUG); + ret = ulpi_read(&motg->phy, ULPI_DEBUG); if (ret != -ETIMEDOUT) break; ret = msm_otg_phy_clk_reset(motg); @@ -385,14 +385,14 @@ static int msm_otg_phy_reset(struct msm_otg *motg) if (!retries) return -ETIMEDOUT; - dev_info(motg->otg.dev, "phy_reset: success\n"); + dev_info(motg->phy.dev, "phy_reset: success\n"); return 0; } #define LINK_RESET_TIMEOUT_USEC (250 * 1000) -static int msm_otg_reset(struct otg_transceiver *otg) +static int msm_otg_reset(struct usb_phy *phy) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(phy, struct msm_otg, phy); struct msm_otg_platform_data *pdata = motg->pdata; int cnt = 0; int ret; @@ -401,7 +401,7 @@ static int msm_otg_reset(struct otg_transceiver *otg) ret = msm_otg_phy_reset(motg); if (ret) { - dev_err(otg->dev, "phy_reset failed\n"); + dev_err(phy->dev, "phy_reset failed\n"); return ret; } @@ -435,8 +435,8 @@ static int msm_otg_reset(struct otg_transceiver *otg) val |= OTGSC_BSVIE; } writel(val, USB_OTGSC); - ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE); - ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL); + ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_RISE); + ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_FALL); } return 0; @@ -448,8 +448,8 @@ static int msm_otg_reset(struct otg_transceiver *otg) #ifdef CONFIG_PM_SLEEP static int msm_otg_suspend(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; - struct usb_bus *bus = otg->host; + struct usb_phy *phy = &motg->phy; + struct usb_bus *bus = phy->otg->host; struct msm_otg_platform_data *pdata = motg->pdata; int cnt = 0; @@ -475,10 +475,10 @@ static int msm_otg_suspend(struct msm_otg *motg) */ if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) { - ulpi_read(otg, 0x14); + ulpi_read(phy, 0x14); if (pdata->otg_control == OTG_PHY_CONTROL) - ulpi_write(otg, 0x01, 0x30); - ulpi_write(otg, 0x08, 0x09); + ulpi_write(phy, 0x01, 0x30); + ulpi_write(phy, 0x08, 0x09); } /* @@ -495,8 +495,8 @@ static int msm_otg_suspend(struct msm_otg *motg) } if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) { - dev_err(otg->dev, "Unable to suspend PHY\n"); - msm_otg_reset(otg); + dev_err(phy->dev, "Unable to suspend PHY\n"); + msm_otg_reset(phy); enable_irq(motg->irq); return -ETIMEDOUT; } @@ -528,7 +528,7 @@ static int msm_otg_suspend(struct msm_otg *motg) msm_hsusb_config_vddcx(0); } - if (device_may_wakeup(otg->dev)) + if (device_may_wakeup(phy->dev)) enable_irq_wake(motg->irq); if (bus) clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags); @@ -536,15 +536,15 @@ static int msm_otg_suspend(struct msm_otg *motg) atomic_set(&motg->in_lpm, 1); enable_irq(motg->irq); - dev_info(otg->dev, "USB in low power mode\n"); + dev_info(phy->dev, "USB in low power mode\n"); return 0; } static int msm_otg_resume(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; - struct usb_bus *bus = otg->host; + struct usb_phy *phy = &motg->phy; + struct usb_bus *bus = phy->otg->host; int cnt = 0; unsigned temp; @@ -592,13 +592,13 @@ static int msm_otg_resume(struct msm_otg *motg) * PHY. USB state can not be restored. Re-insertion * of USB cable is the only way to get USB working. */ - dev_err(otg->dev, "Unable to resume USB." + dev_err(phy->dev, "Unable to resume USB." "Re-plugin the cable\n"); - msm_otg_reset(otg); + msm_otg_reset(phy); } skip_phy_resume: - if (device_may_wakeup(otg->dev)) + if (device_may_wakeup(phy->dev)) disable_irq_wake(motg->irq); if (bus) set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags); @@ -607,11 +607,11 @@ skip_phy_resume: if (motg->async_int) { motg->async_int = 0; - pm_runtime_put(otg->dev); + pm_runtime_put(phy->dev); enable_irq(motg->irq); } - dev_info(otg->dev, "USB exited from low power mode\n"); + dev_info(phy->dev, "USB exited from low power mode\n"); return 0; } @@ -623,13 +623,13 @@ static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA) return; /* TODO: Notify PMIC about available current */ - dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA); + dev_info(motg->phy.dev, "Avail curr from USB = %u\n", mA); motg->cur_power = mA; } -static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA) +static int msm_otg_set_power(struct usb_phy *phy, unsigned mA) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(phy, struct msm_otg, phy); /* * Gadget driver uses set_power method to notify about the @@ -644,19 +644,19 @@ static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA) return 0; } -static void msm_otg_start_host(struct otg_transceiver *otg, int on) +static void msm_otg_start_host(struct usb_phy *phy, int on) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(phy, struct msm_otg, phy); struct msm_otg_platform_data *pdata = motg->pdata; struct usb_hcd *hcd; - if (!otg->host) + if (!phy->otg->host) return; - hcd = bus_to_hcd(otg->host); + hcd = bus_to_hcd(phy->otg->host); if (on) { - dev_dbg(otg->dev, "host on\n"); + dev_dbg(phy->dev, "host on\n"); if (pdata->vbus_power) pdata->vbus_power(1); @@ -671,7 +671,7 @@ static void msm_otg_start_host(struct otg_transceiver *otg, int on) usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); #endif } else { - dev_dbg(otg->dev, "host off\n"); + dev_dbg(phy->dev, "host off\n"); #ifdef CONFIG_USB usb_remove_hcd(hcd); @@ -683,9 +683,9 @@ static void msm_otg_start_host(struct otg_transceiver *otg, int on) } } -static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host) +static int msm_otg_set_host(struct usb_otg *otg, struct usb_bus *host) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy); struct usb_hcd *hcd; /* @@ -693,16 +693,16 @@ static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host) * only peripheral configuration. */ if (motg->pdata->mode == USB_PERIPHERAL) { - dev_info(otg->dev, "Host mode is not supported\n"); + dev_info(otg->phy->dev, "Host mode is not supported\n"); return -ENODEV; } if (!host) { - if (otg->state == OTG_STATE_A_HOST) { - pm_runtime_get_sync(otg->dev); - msm_otg_start_host(otg, 0); + if (otg->phy->state == OTG_STATE_A_HOST) { + pm_runtime_get_sync(otg->phy->dev); + msm_otg_start_host(otg->phy, 0); otg->host = NULL; - otg->state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; schedule_work(&motg->sm_work); } else { otg->host = NULL; @@ -715,30 +715,30 @@ static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host) hcd->power_budget = motg->pdata->power_budget; otg->host = host; - dev_dbg(otg->dev, "host driver registered w/ tranceiver\n"); + dev_dbg(otg->phy->dev, "host driver registered w/ tranceiver\n"); /* * Kick the state machine work, if peripheral is not supported * or peripheral is already registered with us. */ if (motg->pdata->mode == USB_HOST || otg->gadget) { - pm_runtime_get_sync(otg->dev); + pm_runtime_get_sync(otg->phy->dev); schedule_work(&motg->sm_work); } return 0; } -static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on) +static void msm_otg_start_peripheral(struct usb_phy *phy, int on) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(phy, struct msm_otg, phy); struct msm_otg_platform_data *pdata = motg->pdata; - if (!otg->gadget) + if (!phy->otg->gadget) return; if (on) { - dev_dbg(otg->dev, "gadget on\n"); + dev_dbg(phy->dev, "gadget on\n"); /* * Some boards have a switch cotrolled by gpio * to enable/disable internal HUB. Disable internal @@ -746,36 +746,36 @@ static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on) */ if (pdata->setup_gpio) pdata->setup_gpio(OTG_STATE_B_PERIPHERAL); - usb_gadget_vbus_connect(otg->gadget); + usb_gadget_vbus_connect(phy->otg->gadget); } else { - dev_dbg(otg->dev, "gadget off\n"); - usb_gadget_vbus_disconnect(otg->gadget); + dev_dbg(phy->dev, "gadget off\n"); + usb_gadget_vbus_disconnect(phy->otg->gadget); if (pdata->setup_gpio) pdata->setup_gpio(OTG_STATE_UNDEFINED); } } -static int msm_otg_set_peripheral(struct otg_transceiver *otg, - struct usb_gadget *gadget) +static int msm_otg_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy); /* * Fail peripheral registration if this board can support * only host configuration. */ if (motg->pdata->mode == USB_HOST) { - dev_info(otg->dev, "Peripheral mode is not supported\n"); + dev_info(otg->phy->dev, "Peripheral mode is not supported\n"); return -ENODEV; } if (!gadget) { - if (otg->state == OTG_STATE_B_PERIPHERAL) { - pm_runtime_get_sync(otg->dev); - msm_otg_start_peripheral(otg, 0); + if (otg->phy->state == OTG_STATE_B_PERIPHERAL) { + pm_runtime_get_sync(otg->phy->dev); + msm_otg_start_peripheral(otg->phy, 0); otg->gadget = NULL; - otg->state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; schedule_work(&motg->sm_work); } else { otg->gadget = NULL; @@ -784,14 +784,14 @@ static int msm_otg_set_peripheral(struct otg_transceiver *otg, return 0; } otg->gadget = gadget; - dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n"); + dev_dbg(otg->phy->dev, "peripheral driver registered w/ tranceiver\n"); /* * Kick the state machine work, if host is not supported * or host is already registered with us. */ if (motg->pdata->mode == USB_PERIPHERAL || otg->host) { - pm_runtime_get_sync(otg->dev); + pm_runtime_get_sync(otg->phy->dev); schedule_work(&motg->sm_work); } @@ -800,17 +800,17 @@ static int msm_otg_set_peripheral(struct otg_transceiver *otg, static bool msm_chg_check_secondary_det(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 chg_det; bool ret = false; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); ret = chg_det & (1 << 4); break; case SNPS_28NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x87); + chg_det = ulpi_read(phy, 0x87); ret = chg_det & 1; break; default: @@ -821,38 +821,38 @@ static bool msm_chg_check_secondary_det(struct msm_otg *motg) static void msm_chg_enable_secondary_det(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 chg_det; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); /* Turn off charger block */ chg_det |= ~(1 << 1); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); udelay(20); /* control chg block via ULPI */ chg_det &= ~(1 << 3); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); /* put it in host mode for enabling D- source */ chg_det &= ~(1 << 2); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); /* Turn on chg detect block */ chg_det &= ~(1 << 1); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); udelay(20); /* enable chg detection */ chg_det &= ~(1 << 0); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); break; case SNPS_28NM_INTEGRATED_PHY: /* * Configure DM as current source, DP as current sink * and enable battery charging comparators. */ - ulpi_write(otg, 0x8, 0x85); - ulpi_write(otg, 0x2, 0x85); - ulpi_write(otg, 0x1, 0x85); + ulpi_write(phy, 0x8, 0x85); + ulpi_write(phy, 0x2, 0x85); + ulpi_write(phy, 0x1, 0x85); break; default: break; @@ -861,17 +861,17 @@ static void msm_chg_enable_secondary_det(struct msm_otg *motg) static bool msm_chg_check_primary_det(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 chg_det; bool ret = false; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); ret = chg_det & (1 << 4); break; case SNPS_28NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x87); + chg_det = ulpi_read(phy, 0x87); ret = chg_det & 1; break; default: @@ -882,23 +882,23 @@ static bool msm_chg_check_primary_det(struct msm_otg *motg) static void msm_chg_enable_primary_det(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 chg_det; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); /* enable chg detection */ chg_det &= ~(1 << 0); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); break; case SNPS_28NM_INTEGRATED_PHY: /* * Configure DP as current source, DM as current sink * and enable battery charging comparators. */ - ulpi_write(otg, 0x2, 0x85); - ulpi_write(otg, 0x1, 0x85); + ulpi_write(phy, 0x2, 0x85); + ulpi_write(phy, 0x1, 0x85); break; default: break; @@ -907,17 +907,17 @@ static void msm_chg_enable_primary_det(struct msm_otg *motg) static bool msm_chg_check_dcd(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 line_state; bool ret = false; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - line_state = ulpi_read(otg, 0x15); + line_state = ulpi_read(phy, 0x15); ret = !(line_state & 1); break; case SNPS_28NM_INTEGRATED_PHY: - line_state = ulpi_read(otg, 0x87); + line_state = ulpi_read(phy, 0x87); ret = line_state & 2; break; default: @@ -928,17 +928,17 @@ static bool msm_chg_check_dcd(struct msm_otg *motg) static void msm_chg_disable_dcd(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 chg_det; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); chg_det &= ~(1 << 5); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); break; case SNPS_28NM_INTEGRATED_PHY: - ulpi_write(otg, 0x10, 0x86); + ulpi_write(phy, 0x10, 0x86); break; default: break; @@ -947,19 +947,19 @@ static void msm_chg_disable_dcd(struct msm_otg *motg) static void msm_chg_enable_dcd(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 chg_det; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); /* Turn on D+ current source */ chg_det |= (1 << 5); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); break; case SNPS_28NM_INTEGRATED_PHY: /* Data contact detection enable */ - ulpi_write(otg, 0x10, 0x85); + ulpi_write(phy, 0x10, 0x85); break; default: break; @@ -968,32 +968,32 @@ static void msm_chg_enable_dcd(struct msm_otg *motg) static void msm_chg_block_on(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 func_ctrl, chg_det; /* put the controller in non-driving mode */ - func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL); + func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL); func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK; func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; - ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL); + ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL); switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); /* control chg block via ULPI */ chg_det &= ~(1 << 3); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); /* Turn on chg detect block */ chg_det &= ~(1 << 1); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); udelay(20); break; case SNPS_28NM_INTEGRATED_PHY: /* Clear charger detecting control bits */ - ulpi_write(otg, 0x3F, 0x86); + ulpi_write(phy, 0x3F, 0x86); /* Clear alt interrupt latch and enable bits */ - ulpi_write(otg, 0x1F, 0x92); - ulpi_write(otg, 0x1F, 0x95); + ulpi_write(phy, 0x1F, 0x92); + ulpi_write(phy, 0x1F, 0x95); udelay(100); break; default: @@ -1003,32 +1003,32 @@ static void msm_chg_block_on(struct msm_otg *motg) static void msm_chg_block_off(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 func_ctrl, chg_det; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); /* Turn off charger block */ chg_det |= ~(1 << 1); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); break; case SNPS_28NM_INTEGRATED_PHY: /* Clear charger detecting control bits */ - ulpi_write(otg, 0x3F, 0x86); + ulpi_write(phy, 0x3F, 0x86); /* Clear alt interrupt latch and enable bits */ - ulpi_write(otg, 0x1F, 0x92); - ulpi_write(otg, 0x1F, 0x95); + ulpi_write(phy, 0x1F, 0x92); + ulpi_write(phy, 0x1F, 0x95); break; default: break; } /* put the controller in normal mode */ - func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL); + func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL); func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK; func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL; - ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL); + ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL); } #define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */ @@ -1038,14 +1038,14 @@ static void msm_chg_block_off(struct msm_otg *motg) static void msm_chg_detect_work(struct work_struct *w) { struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work); - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; bool is_dcd, tmout, vout; unsigned long delay; - dev_dbg(otg->dev, "chg detection work\n"); + dev_dbg(phy->dev, "chg detection work\n"); switch (motg->chg_state) { case USB_CHG_STATE_UNDEFINED: - pm_runtime_get_sync(otg->dev); + pm_runtime_get_sync(phy->dev); msm_chg_block_on(motg); msm_chg_enable_dcd(motg); motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; @@ -1088,7 +1088,7 @@ static void msm_chg_detect_work(struct work_struct *w) motg->chg_state = USB_CHG_STATE_DETECTED; case USB_CHG_STATE_DETECTED: msm_chg_block_off(motg); - dev_dbg(otg->dev, "charger = %d\n", motg->chg_type); + dev_dbg(phy->dev, "charger = %d\n", motg->chg_type); schedule_work(&motg->sm_work); return; default: @@ -1152,22 +1152,22 @@ static void msm_otg_init_sm(struct msm_otg *motg) static void msm_otg_sm_work(struct work_struct *w) { struct msm_otg *motg = container_of(w, struct msm_otg, sm_work); - struct otg_transceiver *otg = &motg->otg; + struct usb_otg *otg = motg->phy.otg; - switch (otg->state) { + switch (otg->phy->state) { case OTG_STATE_UNDEFINED: - dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n"); - msm_otg_reset(otg); + dev_dbg(otg->phy->dev, "OTG_STATE_UNDEFINED state\n"); + msm_otg_reset(otg->phy); msm_otg_init_sm(motg); - otg->state = OTG_STATE_B_IDLE; + otg->phy->state = OTG_STATE_B_IDLE; /* FALL THROUGH */ case OTG_STATE_B_IDLE: - dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n"); + dev_dbg(otg->phy->dev, "OTG_STATE_B_IDLE state\n"); if (!test_bit(ID, &motg->inputs) && otg->host) { /* disable BSV bit */ writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC); - msm_otg_start_host(otg, 1); - otg->state = OTG_STATE_A_HOST; + msm_otg_start_host(otg->phy, 1); + otg->phy->state = OTG_STATE_A_HOST; } else if (test_bit(B_SESS_VLD, &motg->inputs)) { switch (motg->chg_state) { case USB_CHG_STATE_UNDEFINED: @@ -1182,13 +1182,15 @@ static void msm_otg_sm_work(struct work_struct *w) case USB_CDP_CHARGER: msm_otg_notify_charger(motg, IDEV_CHG_MAX); - msm_otg_start_peripheral(otg, 1); - otg->state = OTG_STATE_B_PERIPHERAL; + msm_otg_start_peripheral(otg->phy, 1); + otg->phy->state + = OTG_STATE_B_PERIPHERAL; break; case USB_SDP_CHARGER: msm_otg_notify_charger(motg, IUNIT); - msm_otg_start_peripheral(otg, 1); - otg->state = OTG_STATE_B_PERIPHERAL; + msm_otg_start_peripheral(otg->phy, 1); + otg->phy->state + = OTG_STATE_B_PERIPHERAL; break; default: break; @@ -1204,34 +1206,34 @@ static void msm_otg_sm_work(struct work_struct *w) * is incremented in charger detection work. */ if (cancel_delayed_work_sync(&motg->chg_work)) { - pm_runtime_put_sync(otg->dev); - msm_otg_reset(otg); + pm_runtime_put_sync(otg->phy->dev); + msm_otg_reset(otg->phy); } msm_otg_notify_charger(motg, 0); motg->chg_state = USB_CHG_STATE_UNDEFINED; motg->chg_type = USB_INVALID_CHARGER; } - pm_runtime_put_sync(otg->dev); + pm_runtime_put_sync(otg->phy->dev); break; case OTG_STATE_B_PERIPHERAL: - dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n"); + dev_dbg(otg->phy->dev, "OTG_STATE_B_PERIPHERAL state\n"); if (!test_bit(B_SESS_VLD, &motg->inputs) || !test_bit(ID, &motg->inputs)) { msm_otg_notify_charger(motg, 0); - msm_otg_start_peripheral(otg, 0); + msm_otg_start_peripheral(otg->phy, 0); motg->chg_state = USB_CHG_STATE_UNDEFINED; motg->chg_type = USB_INVALID_CHARGER; - otg->state = OTG_STATE_B_IDLE; - msm_otg_reset(otg); + otg->phy->state = OTG_STATE_B_IDLE; + msm_otg_reset(otg->phy); schedule_work(w); } break; case OTG_STATE_A_HOST: - dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n"); + dev_dbg(otg->phy->dev, "OTG_STATE_A_HOST state\n"); if (test_bit(ID, &motg->inputs)) { - msm_otg_start_host(otg, 0); - otg->state = OTG_STATE_B_IDLE; - msm_otg_reset(otg); + msm_otg_start_host(otg->phy, 0); + otg->phy->state = OTG_STATE_B_IDLE; + msm_otg_reset(otg->phy); schedule_work(w); } break; @@ -1243,13 +1245,13 @@ static void msm_otg_sm_work(struct work_struct *w) static irqreturn_t msm_otg_irq(int irq, void *data) { struct msm_otg *motg = data; - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 otgsc = 0; if (atomic_read(&motg->in_lpm)) { disable_irq_nosync(irq); motg->async_int = 1; - pm_runtime_get(otg->dev); + pm_runtime_get(phy->dev); return IRQ_HANDLED; } @@ -1262,15 +1264,15 @@ static irqreturn_t msm_otg_irq(int irq, void *data) set_bit(ID, &motg->inputs); else clear_bit(ID, &motg->inputs); - dev_dbg(otg->dev, "ID set/clear\n"); - pm_runtime_get_noresume(otg->dev); + dev_dbg(phy->dev, "ID set/clear\n"); + pm_runtime_get_noresume(phy->dev); } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) { if (otgsc & OTGSC_BSV) set_bit(B_SESS_VLD, &motg->inputs); else clear_bit(B_SESS_VLD, &motg->inputs); - dev_dbg(otg->dev, "BSV set/clear\n"); - pm_runtime_get_noresume(otg->dev); + dev_dbg(phy->dev, "BSV set/clear\n"); + pm_runtime_get_noresume(phy->dev); } writel(otgsc, USB_OTGSC); @@ -1281,9 +1283,9 @@ static irqreturn_t msm_otg_irq(int irq, void *data) static int msm_otg_mode_show(struct seq_file *s, void *unused) { struct msm_otg *motg = s->private; - struct otg_transceiver *otg = &motg->otg; + struct usb_otg *otg = motg->phy.otg; - switch (otg->state) { + switch (otg->phy->state) { case OTG_STATE_A_HOST: seq_printf(s, "host\n"); break; @@ -1309,7 +1311,7 @@ static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, struct seq_file *s = file->private_data; struct msm_otg *motg = s->private; char buf[16]; - struct otg_transceiver *otg = &motg->otg; + struct usb_otg *otg = motg->phy.otg; int status = count; enum usb_mode_type req_mode; @@ -1333,7 +1335,7 @@ static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, switch (req_mode) { case USB_NONE: - switch (otg->state) { + switch (otg->phy->state) { case OTG_STATE_A_HOST: case OTG_STATE_B_PERIPHERAL: set_bit(ID, &motg->inputs); @@ -1344,7 +1346,7 @@ static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, } break; case USB_PERIPHERAL: - switch (otg->state) { + switch (otg->phy->state) { case OTG_STATE_B_IDLE: case OTG_STATE_A_HOST: set_bit(ID, &motg->inputs); @@ -1355,7 +1357,7 @@ static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, } break; case USB_HOST: - switch (otg->state) { + switch (otg->phy->state) { case OTG_STATE_B_IDLE: case OTG_STATE_B_PERIPHERAL: clear_bit(ID, &motg->inputs); @@ -1368,7 +1370,7 @@ static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, goto out; } - pm_runtime_get_sync(otg->dev); + pm_runtime_get_sync(otg->phy->dev); schedule_work(&motg->sm_work); out: return status; @@ -1414,7 +1416,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) int ret = 0; struct resource *res; struct msm_otg *motg; - struct otg_transceiver *otg; + struct usb_phy *phy; dev_info(&pdev->dev, "msm_otg probe\n"); if (!pdev->dev.platform_data) { @@ -1428,9 +1430,15 @@ static int __init msm_otg_probe(struct platform_device *pdev) return -ENOMEM; } + motg->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL); + if (!motg->phy.otg) { + dev_err(&pdev->dev, "unable to allocate msm_otg\n"); + return -ENOMEM; + } + motg->pdata = pdev->dev.platform_data; - otg = &motg->otg; - otg->dev = &pdev->dev; + phy = &motg->phy; + phy->dev = &pdev->dev; motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk"); if (IS_ERR(motg->phy_reset_clk)) { @@ -1538,16 +1546,18 @@ static int __init msm_otg_probe(struct platform_device *pdev) goto disable_clks; } - otg->init = msm_otg_reset; - otg->set_host = msm_otg_set_host; - otg->set_peripheral = msm_otg_set_peripheral; - otg->set_power = msm_otg_set_power; + phy->init = msm_otg_reset; + phy->set_power = msm_otg_set_power; + + phy->io_ops = &msm_otg_io_ops; - otg->io_ops = &msm_otg_io_ops; + phy->otg->phy = &motg->phy; + phy->otg->set_host = msm_otg_set_host; + phy->otg->set_peripheral = msm_otg_set_peripheral; - ret = otg_set_transceiver(&motg->otg); + ret = usb_set_transceiver(&motg->phy); if (ret) { - dev_err(&pdev->dev, "otg_set_transceiver failed\n"); + dev_err(&pdev->dev, "usb_set_transceiver failed\n"); goto free_irq; } @@ -1591,6 +1601,7 @@ put_clk: put_phy_reset_clk: clk_put(motg->phy_reset_clk); free_motg: + kfree(motg->phy.otg); kfree(motg); return ret; } @@ -1598,10 +1609,10 @@ free_motg: static int __devexit msm_otg_remove(struct platform_device *pdev) { struct msm_otg *motg = platform_get_drvdata(pdev); - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; int cnt = 0; - if (otg->host || otg->gadget) + if (phy->otg->host || phy->otg->gadget) return -EBUSY; msm_otg_debugfs_cleanup(); @@ -1613,14 +1624,14 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); pm_runtime_disable(&pdev->dev); - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); free_irq(motg->irq, motg); /* * Put PHY in low power mode. */ - ulpi_read(otg, 0x14); - ulpi_write(otg, 0x08, 0x09); + ulpi_read(phy, 0x14); + ulpi_write(phy, 0x08, 0x09); writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC); while (cnt < PHY_SUSPEND_TIMEOUT_USEC) { @@ -1630,7 +1641,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) cnt++; } if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) - dev_err(otg->dev, "Unable to suspend PHY\n"); + dev_err(phy->dev, "Unable to suspend PHY\n"); clk_disable(motg->pclk); clk_disable(motg->clk); @@ -1651,6 +1662,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) if (motg->core_clk) clk_put(motg->core_clk); + kfree(motg->phy.otg); kfree(motg); return 0; @@ -1660,7 +1672,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) static int msm_otg_runtime_idle(struct device *dev) { struct msm_otg *motg = dev_get_drvdata(dev); - struct otg_transceiver *otg = &motg->otg; + struct usb_otg *otg = motg->phy.otg; dev_dbg(dev, "OTG runtime idle\n"); @@ -1670,7 +1682,7 @@ static int msm_otg_runtime_idle(struct device *dev) * This 1 sec delay also prevents entering into LPM immediately * after asynchronous interrupt. */ - if (otg->state != OTG_STATE_UNDEFINED) + if (otg->phy->state != OTG_STATE_UNDEFINED) pm_schedule_suspend(dev, 1000); return -EAGAIN; diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c index db0d4fc..6cc6c3f 100644 --- a/drivers/usb/otg/mv_otg.c +++ b/drivers/usb/otg/mv_otg.c @@ -55,16 +55,16 @@ static char *state_string[] = { "a_vbus_err" }; -static int mv_otg_set_vbus(struct otg_transceiver *otg, bool on) +static int mv_otg_set_vbus(struct usb_otg *otg, bool on) { - struct mv_otg *mvotg = container_of(otg, struct mv_otg, otg); + struct mv_otg *mvotg = container_of(otg->phy, struct mv_otg, phy); if (mvotg->pdata->set_vbus == NULL) return -ENODEV; return mvotg->pdata->set_vbus(on); } -static int mv_otg_set_host(struct otg_transceiver *otg, +static int mv_otg_set_host(struct usb_otg *otg, struct usb_bus *host) { otg->host = host; @@ -72,7 +72,7 @@ static int mv_otg_set_host(struct otg_transceiver *otg, return 0; } -static int mv_otg_set_peripheral(struct otg_transceiver *otg, +static int mv_otg_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) { otg->gadget = gadget; @@ -202,7 +202,8 @@ static void mv_otg_init_irq(struct mv_otg *mvotg) static void mv_otg_start_host(struct mv_otg *mvotg, int on) { - struct otg_transceiver *otg = &mvotg->otg; +#ifdef CONFIG_USB + struct usb_otg *otg = mvotg->phy.otg; struct usb_hcd *hcd; if (!otg->host) @@ -216,16 +217,17 @@ static void mv_otg_start_host(struct mv_otg *mvotg, int on) usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); else usb_remove_hcd(hcd); +#endif /* CONFIG_USB */ } static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on) { - struct otg_transceiver *otg = &mvotg->otg; + struct usb_otg *otg = mvotg->phy.otg; if (!otg->gadget) return; - dev_info(otg->dev, "gadget %s\n", on ? "on" : "off"); + dev_info(mvotg->phy.dev, "gadget %s\n", on ? "on" : "off"); if (on) usb_gadget_vbus_connect(otg->gadget); @@ -341,69 +343,69 @@ static void mv_otg_update_inputs(struct mv_otg *mvotg) static void mv_otg_update_state(struct mv_otg *mvotg) { struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl; - struct otg_transceiver *otg = &mvotg->otg; - int old_state = otg->state; + struct usb_phy *phy = &mvotg->phy; + int old_state = phy->state; switch (old_state) { case OTG_STATE_UNDEFINED: - otg->state = OTG_STATE_B_IDLE; + phy->state = OTG_STATE_B_IDLE; /* FALL THROUGH */ case OTG_STATE_B_IDLE: if (otg_ctrl->id == 0) - otg->state = OTG_STATE_A_IDLE; + phy->state = OTG_STATE_A_IDLE; else if (otg_ctrl->b_sess_vld) - otg->state = OTG_STATE_B_PERIPHERAL; + phy->state = OTG_STATE_B_PERIPHERAL; break; case OTG_STATE_B_PERIPHERAL: if (!otg_ctrl->b_sess_vld || otg_ctrl->id == 0) - otg->state = OTG_STATE_B_IDLE; + phy->state = OTG_STATE_B_IDLE; break; case OTG_STATE_A_IDLE: if (otg_ctrl->id) - otg->state = OTG_STATE_B_IDLE; + phy->state = OTG_STATE_B_IDLE; else if (!(otg_ctrl->a_bus_drop) && (otg_ctrl->a_bus_req || otg_ctrl->a_srp_det)) - otg->state = OTG_STATE_A_WAIT_VRISE; + phy->state = OTG_STATE_A_WAIT_VRISE; break; case OTG_STATE_A_WAIT_VRISE: if (otg_ctrl->a_vbus_vld) - otg->state = OTG_STATE_A_WAIT_BCON; + phy->state = OTG_STATE_A_WAIT_BCON; break; case OTG_STATE_A_WAIT_BCON: if (otg_ctrl->id || otg_ctrl->a_bus_drop || otg_ctrl->a_wait_bcon_timeout) { mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER); mvotg->otg_ctrl.a_wait_bcon_timeout = 0; - otg->state = OTG_STATE_A_WAIT_VFALL; + phy->state = OTG_STATE_A_WAIT_VFALL; otg_ctrl->a_bus_req = 0; } else if (!otg_ctrl->a_vbus_vld) { mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER); mvotg->otg_ctrl.a_wait_bcon_timeout = 0; - otg->state = OTG_STATE_A_VBUS_ERR; + phy->state = OTG_STATE_A_VBUS_ERR; } else if (otg_ctrl->b_conn) { mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER); mvotg->otg_ctrl.a_wait_bcon_timeout = 0; - otg->state = OTG_STATE_A_HOST; + phy->state = OTG_STATE_A_HOST; } break; case OTG_STATE_A_HOST: if (otg_ctrl->id || !otg_ctrl->b_conn || otg_ctrl->a_bus_drop) - otg->state = OTG_STATE_A_WAIT_BCON; + phy->state = OTG_STATE_A_WAIT_BCON; else if (!otg_ctrl->a_vbus_vld) - otg->state = OTG_STATE_A_VBUS_ERR; + phy->state = OTG_STATE_A_VBUS_ERR; break; case OTG_STATE_A_WAIT_VFALL: if (otg_ctrl->id || (!otg_ctrl->b_conn && otg_ctrl->a_sess_vld) || otg_ctrl->a_bus_req) - otg->state = OTG_STATE_A_IDLE; + phy->state = OTG_STATE_A_IDLE; break; case OTG_STATE_A_VBUS_ERR: if (otg_ctrl->id || otg_ctrl->a_clr_err || otg_ctrl->a_bus_drop) { otg_ctrl->a_clr_err = 0; - otg->state = OTG_STATE_A_WAIT_VFALL; + phy->state = OTG_STATE_A_WAIT_VFALL; } break; default: @@ -414,15 +416,17 @@ static void mv_otg_update_state(struct mv_otg *mvotg) static void mv_otg_work(struct work_struct *work) { struct mv_otg *mvotg; - struct otg_transceiver *otg; + struct usb_phy *phy; + struct usb_otg *otg; int old_state; mvotg = container_of((struct delayed_work *)work, struct mv_otg, work); run: /* work queue is single thread, or we need spin_lock to protect */ - otg = &mvotg->otg; - old_state = otg->state; + phy = &mvotg->phy; + otg = phy->otg; + old_state = phy->state; if (!mvotg->active) return; @@ -430,14 +434,14 @@ run: mv_otg_update_inputs(mvotg); mv_otg_update_state(mvotg); - if (old_state != otg->state) { + if (old_state != phy->state) { dev_info(&mvotg->pdev->dev, "change from state %s to %s\n", state_string[old_state], - state_string[otg->state]); + state_string[phy->state]); - switch (otg->state) { + switch (phy->state) { case OTG_STATE_B_IDLE: - mvotg->otg.default_a = 0; + otg->default_a = 0; if (old_state == OTG_STATE_B_PERIPHERAL) mv_otg_start_periphrals(mvotg, 0); mv_otg_reset(mvotg); @@ -448,14 +452,14 @@ run: mv_otg_start_periphrals(mvotg, 1); break; case OTG_STATE_A_IDLE: - mvotg->otg.default_a = 1; + otg->default_a = 1; mv_otg_enable(mvotg); if (old_state == OTG_STATE_A_WAIT_VFALL) mv_otg_start_host(mvotg, 0); mv_otg_reset(mvotg); break; case OTG_STATE_A_WAIT_VRISE: - mv_otg_set_vbus(&mvotg->otg, 1); + mv_otg_set_vbus(otg, 1); break; case OTG_STATE_A_WAIT_BCON: if (old_state != OTG_STATE_A_HOST) @@ -477,7 +481,7 @@ run: * here. In fact, it need host driver to notify us. */ mvotg->otg_ctrl.b_conn = 0; - mv_otg_set_vbus(&mvotg->otg, 0); + mv_otg_set_vbus(otg, 0); break; case OTG_STATE_A_VBUS_ERR: break; @@ -546,8 +550,8 @@ set_a_bus_req(struct device *dev, struct device_attribute *attr, return -1; /* We will use this interface to change to A device */ - if (mvotg->otg.state != OTG_STATE_B_IDLE - && mvotg->otg.state != OTG_STATE_A_IDLE) + if (mvotg->phy.state != OTG_STATE_B_IDLE + && mvotg->phy.state != OTG_STATE_A_IDLE) return -1; /* The clock may disabled and we need to set irq for ID detected */ @@ -577,7 +581,7 @@ set_a_clr_err(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct mv_otg *mvotg = dev_get_drvdata(dev); - if (!mvotg->otg.default_a) + if (!mvotg->phy.otg->default_a) return -1; if (count > 2) @@ -613,7 +617,7 @@ set_a_bus_drop(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct mv_otg *mvotg = dev_get_drvdata(dev); - if (!mvotg->otg.default_a) + if (!mvotg->phy.otg->default_a) return -1; if (count > 2) @@ -686,9 +690,10 @@ int mv_otg_remove(struct platform_device *pdev) for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++) clk_put(mvotg->clk[clk_i]); - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); platform_set_drvdata(pdev, NULL); + kfree(mvotg->phy.otg); kfree(mvotg); return 0; @@ -698,6 +703,7 @@ static int mv_otg_probe(struct platform_device *pdev) { struct mv_usb_platform_data *pdata = pdev->dev.platform_data; struct mv_otg *mvotg; + struct usb_otg *otg; struct resource *r; int retval = 0, clk_i, i; size_t size; @@ -714,6 +720,12 @@ static int mv_otg_probe(struct platform_device *pdev) return -ENOMEM; } + otg = kzalloc(sizeof *otg, GFP_KERNEL); + if (!otg) { + kfree(mvotg); + return -ENOMEM; + } + platform_set_drvdata(pdev, mvotg); mvotg->pdev = pdev; @@ -739,12 +751,15 @@ static int mv_otg_probe(struct platform_device *pdev) /* OTG common part */ mvotg->pdev = pdev; - mvotg->otg.dev = &pdev->dev; - mvotg->otg.label = driver_name; - mvotg->otg.set_host = mv_otg_set_host; - mvotg->otg.set_peripheral = mv_otg_set_peripheral; - mvotg->otg.set_vbus = mv_otg_set_vbus; - mvotg->otg.state = OTG_STATE_UNDEFINED; + mvotg->phy.dev = &pdev->dev; + mvotg->phy.otg = otg; + mvotg->phy.label = driver_name; + mvotg->phy.state = OTG_STATE_UNDEFINED; + + otg->phy = &mvotg->phy; + otg->set_host = mv_otg_set_host; + otg->set_peripheral = mv_otg_set_peripheral; + otg->set_vbus = mv_otg_set_vbus; for (i = 0; i < OTG_TIMER_NUM; i++) init_timer(&mvotg->otg_ctrl.timer[i]); @@ -838,7 +853,7 @@ static int mv_otg_probe(struct platform_device *pdev) goto err_disable_clk; } - retval = otg_set_transceiver(&mvotg->otg); + retval = usb_set_transceiver(&mvotg->phy); if (retval < 0) { dev_err(&pdev->dev, "can't register transceiver, %d\n", retval); @@ -865,7 +880,7 @@ static int mv_otg_probe(struct platform_device *pdev) return 0; err_set_transceiver: - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); err_free_irq: free_irq(mvotg->irq, mvotg); err_disable_clk: @@ -886,6 +901,7 @@ err_put_clk: clk_put(mvotg->clk[clk_i]); platform_set_drvdata(pdev, NULL); + kfree(otg); kfree(mvotg); return retval; @@ -896,10 +912,10 @@ static int mv_otg_suspend(struct platform_device *pdev, pm_message_t state) { struct mv_otg *mvotg = platform_get_drvdata(pdev); - if (mvotg->otg.state != OTG_STATE_B_IDLE) { + if (mvotg->phy.state != OTG_STATE_B_IDLE) { dev_info(&pdev->dev, "OTG state is not B_IDLE, it is %d!\n", - mvotg->otg.state); + mvotg->phy.state); return -EAGAIN; } diff --git a/drivers/usb/otg/mv_otg.h b/drivers/usb/otg/mv_otg.h index be6ca14..8a9e351 100644 --- a/drivers/usb/otg/mv_otg.h +++ b/drivers/usb/otg/mv_otg.h @@ -136,7 +136,7 @@ struct mv_otg_regs { }; struct mv_otg { - struct otg_transceiver otg; + struct usb_phy phy; struct mv_otg_ctrl otg_ctrl; /* base address */ diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index c1e3600..58b26df 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -33,7 +33,7 @@ #include <linux/slab.h> struct nop_usb_xceiv { - struct otg_transceiver otg; + struct usb_phy phy; struct device *dev; }; @@ -58,51 +58,37 @@ void usb_nop_xceiv_unregister(void) } EXPORT_SYMBOL(usb_nop_xceiv_unregister); -static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x) -{ - return container_of(x, struct nop_usb_xceiv, otg); -} - -static int nop_set_suspend(struct otg_transceiver *x, int suspend) +static int nop_set_suspend(struct usb_phy *x, int suspend) { return 0; } -static int nop_set_peripheral(struct otg_transceiver *x, - struct usb_gadget *gadget) +static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) { - struct nop_usb_xceiv *nop; - - if (!x) + if (!otg) return -ENODEV; - nop = xceiv_to_nop(x); - if (!gadget) { - nop->otg.gadget = NULL; + otg->gadget = NULL; return -ENODEV; } - nop->otg.gadget = gadget; - nop->otg.state = OTG_STATE_B_IDLE; + otg->gadget = gadget; + otg->phy->state = OTG_STATE_B_IDLE; return 0; } -static int nop_set_host(struct otg_transceiver *x, struct usb_bus *host) +static int nop_set_host(struct usb_otg *otg, struct usb_bus *host) { - struct nop_usb_xceiv *nop; - - if (!x) + if (!otg) return -ENODEV; - nop = xceiv_to_nop(x); - if (!host) { - nop->otg.host = NULL; + otg->host = NULL; return -ENODEV; } - nop->otg.host = host; + otg->host = host; return 0; } @@ -115,15 +101,23 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) if (!nop) return -ENOMEM; + nop->phy.otg = kzalloc(sizeof *nop->phy.otg, GFP_KERNEL); + if (!nop->phy.otg) { + kfree(nop); + return -ENOMEM; + } + nop->dev = &pdev->dev; - nop->otg.dev = nop->dev; - nop->otg.label = "nop-xceiv"; - nop->otg.state = OTG_STATE_UNDEFINED; - nop->otg.set_host = nop_set_host; - nop->otg.set_peripheral = nop_set_peripheral; - nop->otg.set_suspend = nop_set_suspend; - - err = otg_set_transceiver(&nop->otg); + nop->phy.dev = nop->dev; + nop->phy.label = "nop-xceiv"; + nop->phy.set_suspend = nop_set_suspend; + nop->phy.state = OTG_STATE_UNDEFINED; + + nop->phy.otg->phy = &nop->phy; + nop->phy.otg->set_host = nop_set_host; + nop->phy.otg->set_peripheral = nop_set_peripheral; + + err = usb_set_transceiver(&nop->phy); if (err) { dev_err(&pdev->dev, "can't register transceiver, err: %d\n", err); @@ -132,10 +126,11 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, nop); - ATOMIC_INIT_NOTIFIER_HEAD(&nop->otg.notifier); + ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier); return 0; exit: + kfree(nop->phy.otg); kfree(nop); return err; } @@ -144,9 +139,10 @@ static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev) { struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); platform_set_drvdata(pdev, NULL); + kfree(nop->phy.otg); kfree(nop); return 0; diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c index 307c27b..801e597 100644 --- a/drivers/usb/otg/otg.c +++ b/drivers/usb/otg/otg.c @@ -15,56 +15,56 @@ #include <linux/usb/otg.h> -static struct otg_transceiver *xceiv; +static struct usb_phy *phy; /** - * otg_get_transceiver - find the (single) OTG transceiver + * usb_get_transceiver - find the (single) USB transceiver * * Returns the transceiver driver, after getting a refcount to it; or * null if there is no such transceiver. The caller is responsible for - * calling otg_put_transceiver() to release that count. + * calling usb_put_transceiver() to release that count. * * For use by USB host and peripheral drivers. */ -struct otg_transceiver *otg_get_transceiver(void) +struct usb_phy *usb_get_transceiver(void) { - if (xceiv) - get_device(xceiv->dev); - return xceiv; + if (phy) + get_device(phy->dev); + return phy; } -EXPORT_SYMBOL(otg_get_transceiver); +EXPORT_SYMBOL(usb_get_transceiver); /** - * otg_put_transceiver - release the (single) OTG transceiver - * @x: the transceiver returned by otg_get_transceiver() + * usb_put_transceiver - release the (single) USB transceiver + * @x: the transceiver returned by usb_get_transceiver() * - * Releases a refcount the caller received from otg_get_transceiver(). + * Releases a refcount the caller received from usb_get_transceiver(). * * For use by USB host and peripheral drivers. */ -void otg_put_transceiver(struct otg_transceiver *x) +void usb_put_transceiver(struct usb_phy *x) { if (x) put_device(x->dev); } -EXPORT_SYMBOL(otg_put_transceiver); +EXPORT_SYMBOL(usb_put_transceiver); /** - * otg_set_transceiver - declare the (single) OTG transceiver - * @x: the USB OTG transceiver to be used; or NULL + * usb_set_transceiver - declare the (single) USB transceiver + * @x: the USB transceiver to be used; or NULL * * This call is exclusively for use by transceiver drivers, which * coordinate the activities of drivers for host and peripheral * controllers, and in some cases for VBUS current regulation. */ -int otg_set_transceiver(struct otg_transceiver *x) +int usb_set_transceiver(struct usb_phy *x) { - if (xceiv && x) + if (phy && x) return -EBUSY; - xceiv = x; + phy = x; return 0; } -EXPORT_SYMBOL(otg_set_transceiver); +EXPORT_SYMBOL(usb_set_transceiver); const char *otg_state_string(enum usb_otg_state state) { diff --git a/drivers/usb/otg/otg_fsm.c b/drivers/usb/otg/otg_fsm.c index 0911738..ade131a 100644 --- a/drivers/usb/otg/otg_fsm.c +++ b/drivers/usb/otg/otg_fsm.c @@ -117,10 +117,10 @@ void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state) int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state) { state_changed = 1; - if (fsm->transceiver->state == new_state) + if (fsm->otg->phy->state == new_state) return 0; VDBG("Set state: %s\n", otg_state_string(new_state)); - otg_leave_state(fsm, fsm->transceiver->state); + otg_leave_state(fsm, fsm->otg->phy->state); switch (new_state) { case OTG_STATE_B_IDLE: otg_drv_vbus(fsm, 0); @@ -155,8 +155,8 @@ int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state) otg_loc_conn(fsm, 0); otg_loc_sof(fsm, 1); otg_set_protocol(fsm, PROTO_HOST); - usb_bus_start_enum(fsm->transceiver->host, - fsm->transceiver->host->otg_port); + usb_bus_start_enum(fsm->otg->host, + fsm->otg->host->otg_port); break; case OTG_STATE_A_IDLE: otg_drv_vbus(fsm, 0); @@ -221,7 +221,7 @@ int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state) break; } - fsm->transceiver->state = new_state; + fsm->otg->phy->state = new_state; return 0; } @@ -233,7 +233,7 @@ int otg_statemachine(struct otg_fsm *fsm) spin_lock_irqsave(&fsm->lock, flags); - state = fsm->transceiver->state; + state = fsm->otg->phy->state; state_changed = 0; /* State machine state change judgement */ @@ -248,7 +248,7 @@ int otg_statemachine(struct otg_fsm *fsm) case OTG_STATE_B_IDLE: if (!fsm->id) otg_set_state(fsm, OTG_STATE_A_IDLE); - else if (fsm->b_sess_vld && fsm->transceiver->gadget) + else if (fsm->b_sess_vld && fsm->otg->gadget) otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); else if (fsm->b_bus_req && fsm->b_sess_end && fsm->b_se0_srp) otg_set_state(fsm, OTG_STATE_B_SRP_INIT); @@ -260,7 +260,7 @@ int otg_statemachine(struct otg_fsm *fsm) case OTG_STATE_B_PERIPHERAL: if (!fsm->id || !fsm->b_sess_vld) otg_set_state(fsm, OTG_STATE_B_IDLE); - else if (fsm->b_bus_req && fsm->transceiver-> + else if (fsm->b_bus_req && fsm->otg-> gadget->b_hnp_enable && fsm->a_bus_suspend) otg_set_state(fsm, OTG_STATE_B_WAIT_ACON); break; @@ -302,7 +302,7 @@ int otg_statemachine(struct otg_fsm *fsm) break; case OTG_STATE_A_HOST: if ((!fsm->a_bus_req || fsm->a_suspend_req) && - fsm->transceiver->host->b_hnp_enable) + fsm->otg->host->b_hnp_enable) otg_set_state(fsm, OTG_STATE_A_SUSPEND); else if (fsm->id || !fsm->b_conn || fsm->a_bus_drop) otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); @@ -310,9 +310,9 @@ int otg_statemachine(struct otg_fsm *fsm) otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); break; case OTG_STATE_A_SUSPEND: - if (!fsm->b_conn && fsm->transceiver->host->b_hnp_enable) + if (!fsm->b_conn && fsm->otg->host->b_hnp_enable) otg_set_state(fsm, OTG_STATE_A_PERIPHERAL); - else if (!fsm->b_conn && !fsm->transceiver->host->b_hnp_enable) + else if (!fsm->b_conn && !fsm->otg->host->b_hnp_enable) otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); else if (fsm->a_bus_req || fsm->b_bus_resume) otg_set_state(fsm, OTG_STATE_A_HOST); diff --git a/drivers/usb/otg/otg_fsm.h b/drivers/usb/otg/otg_fsm.h index 0cecf1d..c30a2e1 100644 --- a/drivers/usb/otg/otg_fsm.h +++ b/drivers/usb/otg/otg_fsm.h @@ -82,7 +82,7 @@ struct otg_fsm { int loc_sof; struct otg_fsm_ops *ops; - struct otg_transceiver *transceiver; + struct usb_otg *otg; /* Current usb protocol used: 0:undefine; 1:host; 2:client */ int protocol; diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 14f66c3..c4a86da 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -144,7 +144,7 @@ #define GPIO_USB_4PIN_ULPI_2430C (3 << 0) struct twl4030_usb { - struct otg_transceiver otg; + struct usb_phy phy; struct device *dev; /* TWL4030 internal USB regulator supplies */ @@ -166,7 +166,7 @@ struct twl4030_usb { }; /* internal define on top of container_of */ -#define xceiv_to_twl(x) container_of((x), struct twl4030_usb, otg) +#define phy_to_twl(x) container_of((x), struct twl4030_usb, phy) /*-------------------------------------------------------------------------*/ @@ -246,10 +246,11 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits) /*-------------------------------------------------------------------------*/ -static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl) +static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl) { int status; int linkstat = USB_EVENT_NONE; + struct usb_otg *otg = twl->phy.otg; twl->vbus_supplied = false; @@ -281,7 +282,7 @@ static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl) dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", status, status, linkstat); - twl->otg.last_event = linkstat; + twl->phy.last_event = linkstat; /* REVISIT this assumes host and peripheral controllers * are registered, and that both are active... @@ -290,11 +291,11 @@ static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl) spin_lock_irq(&twl->lock); twl->linkstat = linkstat; if (linkstat == USB_EVENT_ID) { - twl->otg.default_a = true; - twl->otg.state = OTG_STATE_A_IDLE; + otg->default_a = true; + twl->phy.state = OTG_STATE_A_IDLE; } else { - twl->otg.default_a = false; - twl->otg.state = OTG_STATE_B_IDLE; + otg->default_a = false; + twl->phy.state = OTG_STATE_B_IDLE; } spin_unlock_irq(&twl->lock); @@ -520,8 +521,8 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) else twl4030_phy_resume(twl); - atomic_notifier_call_chain(&twl->otg.notifier, status, - twl->otg.gadget); + atomic_notifier_call_chain(&twl->phy.notifier, status, + twl->phy.otg->gadget); } sysfs_notify(&twl->dev->kobj, NULL, "vbus"); @@ -542,15 +543,15 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl) twl->asleep = 0; } - atomic_notifier_call_chain(&twl->otg.notifier, status, - twl->otg.gadget); + atomic_notifier_call_chain(&twl->phy.notifier, status, + twl->phy.otg->gadget); } sysfs_notify(&twl->dev->kobj, NULL, "vbus"); } -static int twl4030_set_suspend(struct otg_transceiver *x, int suspend) +static int twl4030_set_suspend(struct usb_phy *x, int suspend) { - struct twl4030_usb *twl = xceiv_to_twl(x); + struct twl4030_usb *twl = phy_to_twl(x); if (suspend) twl4030_phy_suspend(twl, 1); @@ -560,33 +561,27 @@ static int twl4030_set_suspend(struct otg_transceiver *x, int suspend) return 0; } -static int twl4030_set_peripheral(struct otg_transceiver *x, - struct usb_gadget *gadget) +static int twl4030_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) { - struct twl4030_usb *twl; - - if (!x) + if (!otg) return -ENODEV; - twl = xceiv_to_twl(x); - twl->otg.gadget = gadget; + otg->gadget = gadget; if (!gadget) - twl->otg.state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; return 0; } -static int twl4030_set_host(struct otg_transceiver *x, struct usb_bus *host) +static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host) { - struct twl4030_usb *twl; - - if (!x) + if (!otg) return -ENODEV; - twl = xceiv_to_twl(x); - twl->otg.host = host; + otg->host = host; if (!host) - twl->otg.state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; return 0; } @@ -596,6 +591,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) struct twl4030_usb_data *pdata = pdev->dev.platform_data; struct twl4030_usb *twl; int status, err; + struct usb_otg *otg; if (!pdata) { dev_dbg(&pdev->dev, "platform_data not available\n"); @@ -606,16 +602,26 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) if (!twl) return -ENOMEM; + otg = kzalloc(sizeof *otg, GFP_KERNEL); + if (!otg) { + kfree(twl); + return -ENOMEM; + } + twl->dev = &pdev->dev; twl->irq = platform_get_irq(pdev, 0); - twl->otg.dev = twl->dev; - twl->otg.label = "twl4030"; - twl->otg.set_host = twl4030_set_host; - twl->otg.set_peripheral = twl4030_set_peripheral; - twl->otg.set_suspend = twl4030_set_suspend; twl->usb_mode = pdata->usb_mode; twl->vbus_supplied = false; - twl->asleep = 1; + twl->asleep = 1; + + twl->phy.dev = twl->dev; + twl->phy.label = "twl4030"; + twl->phy.otg = otg; + twl->phy.set_suspend = twl4030_set_suspend; + + otg->phy = &twl->phy; + otg->set_host = twl4030_set_host; + otg->set_peripheral = twl4030_set_peripheral; /* init spinlock for workqueue */ spin_lock_init(&twl->lock); @@ -623,16 +629,17 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) err = twl4030_usb_ldo_init(twl); if (err) { dev_err(&pdev->dev, "ldo init failed\n"); + kfree(otg); kfree(twl); return err; } - otg_set_transceiver(&twl->otg); + usb_set_transceiver(&twl->phy); platform_set_drvdata(pdev, twl); if (device_create_file(&pdev->dev, &dev_attr_vbus)) dev_warn(&pdev->dev, "could not create sysfs file\n"); - ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier); + ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); /* Our job is to use irqs and status from the power module * to keep the transceiver disabled when nothing's connected. @@ -649,6 +656,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) if (status < 0) { dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n", twl->irq, status); + kfree(otg); kfree(twl); return status; } @@ -693,6 +701,7 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) regulator_put(twl->usb1v8); regulator_put(twl->usb3v1); + kfree(twl->phy.otg); kfree(twl); return 0; diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index ed2b26c..e3fa387 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c @@ -87,7 +87,7 @@ #define VBUS_DET BIT(2) struct twl6030_usb { - struct otg_transceiver otg; + struct usb_phy phy; struct device *dev; /* for vbus reporting with irqs disabled */ @@ -107,7 +107,7 @@ struct twl6030_usb { unsigned long features; }; -#define xceiv_to_twl(x) container_of((x), struct twl6030_usb, otg) +#define phy_to_twl(x) container_of((x), struct twl6030_usb, phy) /*-------------------------------------------------------------------------*/ @@ -137,13 +137,13 @@ static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address) return ret; } -static int twl6030_phy_init(struct otg_transceiver *x) +static int twl6030_phy_init(struct usb_phy *x) { struct twl6030_usb *twl; struct device *dev; struct twl4030_usb_data *pdata; - twl = xceiv_to_twl(x); + twl = phy_to_twl(x); dev = twl->dev; pdata = dev->platform_data; @@ -155,21 +155,21 @@ static int twl6030_phy_init(struct otg_transceiver *x) return 0; } -static void twl6030_phy_shutdown(struct otg_transceiver *x) +static void twl6030_phy_shutdown(struct usb_phy *x) { struct twl6030_usb *twl; struct device *dev; struct twl4030_usb_data *pdata; - twl = xceiv_to_twl(x); + twl = phy_to_twl(x); dev = twl->dev; pdata = dev->platform_data; pdata->phy_power(twl->dev, 0, 0); } -static int twl6030_phy_suspend(struct otg_transceiver *x, int suspend) +static int twl6030_phy_suspend(struct usb_phy *x, int suspend) { - struct twl6030_usb *twl = xceiv_to_twl(x); + struct twl6030_usb *twl = phy_to_twl(x); struct device *dev = twl->dev; struct twl4030_usb_data *pdata = dev->platform_data; @@ -178,9 +178,9 @@ static int twl6030_phy_suspend(struct otg_transceiver *x, int suspend) return 0; } -static int twl6030_start_srp(struct otg_transceiver *x) +static int twl6030_start_srp(struct usb_otg *otg) { - struct twl6030_usb *twl = xceiv_to_twl(x); + struct twl6030_usb *twl = phy_to_twl(otg->phy); twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET); twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET); @@ -256,6 +256,7 @@ static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL); static irqreturn_t twl6030_usb_irq(int irq, void *_twl) { struct twl6030_usb *twl = _twl; + struct usb_otg *otg = twl->phy.otg; int status; u8 vbus_state, hw_state; @@ -268,18 +269,18 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) regulator_enable(twl->usb3v3); twl->asleep = 1; status = USB_EVENT_VBUS; - twl->otg.default_a = false; - twl->otg.state = OTG_STATE_B_IDLE; + otg->default_a = false; + twl->phy.state = OTG_STATE_B_IDLE; twl->linkstat = status; - twl->otg.last_event = status; - atomic_notifier_call_chain(&twl->otg.notifier, - status, twl->otg.gadget); + twl->phy.last_event = status; + atomic_notifier_call_chain(&twl->phy.notifier, + status, otg->gadget); } else { status = USB_EVENT_NONE; twl->linkstat = status; - twl->otg.last_event = status; - atomic_notifier_call_chain(&twl->otg.notifier, - status, twl->otg.gadget); + twl->phy.last_event = status; + atomic_notifier_call_chain(&twl->phy.notifier, + status, otg->gadget); if (twl->asleep) { regulator_disable(twl->usb3v3); twl->asleep = 0; @@ -294,6 +295,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) { struct twl6030_usb *twl = _twl; + struct usb_otg *otg = twl->phy.otg; int status = USB_EVENT_NONE; u8 hw_state; @@ -307,12 +309,12 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x10); status = USB_EVENT_ID; - twl->otg.default_a = true; - twl->otg.state = OTG_STATE_A_IDLE; + otg->default_a = true; + twl->phy.state = OTG_STATE_A_IDLE; twl->linkstat = status; - twl->otg.last_event = status; - atomic_notifier_call_chain(&twl->otg.notifier, status, - twl->otg.gadget); + twl->phy.last_event = status; + atomic_notifier_call_chain(&twl->phy.notifier, status, + otg->gadget); } else { twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x10); @@ -324,25 +326,22 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) return IRQ_HANDLED; } -static int twl6030_set_peripheral(struct otg_transceiver *x, +static int twl6030_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) { - struct twl6030_usb *twl; - - if (!x) + if (!otg) return -ENODEV; - twl = xceiv_to_twl(x); - twl->otg.gadget = gadget; + otg->gadget = gadget; if (!gadget) - twl->otg.state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; return 0; } -static int twl6030_enable_irq(struct otg_transceiver *x) +static int twl6030_enable_irq(struct usb_phy *x) { - struct twl6030_usb *twl = xceiv_to_twl(x); + struct twl6030_usb *twl = phy_to_twl(x); twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1); twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C); @@ -376,9 +375,9 @@ static void otg_set_vbus_work(struct work_struct *data) CHARGERUSB_CTRL1); } -static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled) +static int twl6030_set_vbus(struct usb_otg *otg, bool enabled) { - struct twl6030_usb *twl = xceiv_to_twl(x); + struct twl6030_usb *twl = phy_to_twl(otg->phy); twl->vbus_enable = enabled; schedule_work(&twl->set_vbus_work); @@ -386,17 +385,14 @@ static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled) return 0; } -static int twl6030_set_host(struct otg_transceiver *x, struct usb_bus *host) +static int twl6030_set_host(struct usb_otg *otg, struct usb_bus *host) { - struct twl6030_usb *twl; - - if (!x) + if (!otg) return -ENODEV; - twl = xceiv_to_twl(x); - twl->otg.host = host; + otg->host = host; if (!host) - twl->otg.state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; return 0; } @@ -405,6 +401,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) struct twl6030_usb *twl; int status, err; struct twl4030_usb_data *pdata; + struct usb_otg *otg; struct device *dev = &pdev->dev; pdata = dev->platform_data; @@ -412,19 +409,29 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) if (!twl) return -ENOMEM; + otg = kzalloc(sizeof *otg, GFP_KERNEL); + if (!otg) { + kfree(twl); + return -ENOMEM; + } + twl->dev = &pdev->dev; twl->irq1 = platform_get_irq(pdev, 0); twl->irq2 = platform_get_irq(pdev, 1); twl->features = pdata->features; - twl->otg.dev = twl->dev; - twl->otg.label = "twl6030"; - twl->otg.set_host = twl6030_set_host; - twl->otg.set_peripheral = twl6030_set_peripheral; - twl->otg.set_vbus = twl6030_set_vbus; - twl->otg.init = twl6030_phy_init; - twl->otg.shutdown = twl6030_phy_shutdown; - twl->otg.set_suspend = twl6030_phy_suspend; - twl->otg.start_srp = twl6030_start_srp; + + twl->phy.dev = twl->dev; + twl->phy.label = "twl6030"; + twl->phy.otg = otg; + twl->phy.init = twl6030_phy_init; + twl->phy.shutdown = twl6030_phy_shutdown; + twl->phy.set_suspend = twl6030_phy_suspend; + + otg->phy = &twl->phy; + otg->set_host = twl6030_set_host; + otg->set_peripheral = twl6030_set_peripheral; + otg->set_vbus = twl6030_set_vbus; + otg->start_srp = twl6030_start_srp; /* init spinlock for workqueue */ spin_lock_init(&twl->lock); @@ -432,16 +439,17 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) err = twl6030_usb_ldo_init(twl); if (err) { dev_err(&pdev->dev, "ldo init failed\n"); + kfree(otg); kfree(twl); return err; } - otg_set_transceiver(&twl->otg); + usb_set_transceiver(&twl->phy); platform_set_drvdata(pdev, twl); if (device_create_file(&pdev->dev, &dev_attr_vbus)) dev_warn(&pdev->dev, "could not create sysfs file\n"); - ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier); + ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); @@ -453,6 +461,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", twl->irq1, status); device_remove_file(twl->dev, &dev_attr_vbus); + kfree(otg); kfree(twl); return status; } @@ -465,14 +474,15 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) twl->irq2, status); free_irq(twl->irq1, twl); device_remove_file(twl->dev, &dev_attr_vbus); + kfree(otg); kfree(twl); return status; } twl->asleep = 0; pdata->phy_init(dev); - twl6030_phy_suspend(&twl->otg, 0); - twl6030_enable_irq(&twl->otg); + twl6030_phy_suspend(&twl->phy, 0); + twl6030_enable_irq(&twl->phy); dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); return 0; @@ -496,6 +506,7 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) pdata->phy_exit(twl->dev); device_remove_file(twl->dev, &dev_attr_vbus); cancel_work_sync(&twl->set_vbus_work); + kfree(twl->phy.otg); kfree(twl); return 0; diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index 0b04667..217339d 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/otg/ulpi.c @@ -49,31 +49,31 @@ static struct ulpi_info ulpi_ids[] = { ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"), }; -static int ulpi_set_otg_flags(struct otg_transceiver *otg) +static int ulpi_set_otg_flags(struct usb_phy *phy) { unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN | ULPI_OTG_CTRL_DM_PULLDOWN; - if (otg->flags & ULPI_OTG_ID_PULLUP) + if (phy->flags & ULPI_OTG_ID_PULLUP) flags |= ULPI_OTG_CTRL_ID_PULLUP; /* * ULPI Specification rev.1.1 default * for Dp/DmPulldown is enabled. */ - if (otg->flags & ULPI_OTG_DP_PULLDOWN_DIS) + if (phy->flags & ULPI_OTG_DP_PULLDOWN_DIS) flags &= ~ULPI_OTG_CTRL_DP_PULLDOWN; - if (otg->flags & ULPI_OTG_DM_PULLDOWN_DIS) + if (phy->flags & ULPI_OTG_DM_PULLDOWN_DIS) flags &= ~ULPI_OTG_CTRL_DM_PULLDOWN; - if (otg->flags & ULPI_OTG_EXTVBUSIND) + if (phy->flags & ULPI_OTG_EXTVBUSIND) flags |= ULPI_OTG_CTRL_EXTVBUSIND; - return otg_io_write(otg, flags, ULPI_OTG_CTRL); + return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL); } -static int ulpi_set_fc_flags(struct otg_transceiver *otg) +static int ulpi_set_fc_flags(struct usb_phy *phy) { unsigned int flags = 0; @@ -81,27 +81,27 @@ static int ulpi_set_fc_flags(struct otg_transceiver *otg) * ULPI Specification rev.1.1 default * for XcvrSelect is Full Speed. */ - if (otg->flags & ULPI_FC_HS) + if (phy->flags & ULPI_FC_HS) flags |= ULPI_FUNC_CTRL_HIGH_SPEED; - else if (otg->flags & ULPI_FC_LS) + else if (phy->flags & ULPI_FC_LS) flags |= ULPI_FUNC_CTRL_LOW_SPEED; - else if (otg->flags & ULPI_FC_FS4LS) + else if (phy->flags & ULPI_FC_FS4LS) flags |= ULPI_FUNC_CTRL_FS4LS; else flags |= ULPI_FUNC_CTRL_FULL_SPEED; - if (otg->flags & ULPI_FC_TERMSEL) + if (phy->flags & ULPI_FC_TERMSEL) flags |= ULPI_FUNC_CTRL_TERMSELECT; /* * ULPI Specification rev.1.1 default * for OpMode is Normal Operation. */ - if (otg->flags & ULPI_FC_OP_NODRV) + if (phy->flags & ULPI_FC_OP_NODRV) flags |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; - else if (otg->flags & ULPI_FC_OP_DIS_NRZI) + else if (phy->flags & ULPI_FC_OP_DIS_NRZI) flags |= ULPI_FUNC_CTRL_OPMODE_DISABLE_NRZI; - else if (otg->flags & ULPI_FC_OP_NSYNC_NEOP) + else if (phy->flags & ULPI_FC_OP_NSYNC_NEOP) flags |= ULPI_FUNC_CTRL_OPMODE_NOSYNC_NOEOP; else flags |= ULPI_FUNC_CTRL_OPMODE_NORMAL; @@ -112,54 +112,54 @@ static int ulpi_set_fc_flags(struct otg_transceiver *otg) */ flags |= ULPI_FUNC_CTRL_SUSPENDM; - return otg_io_write(otg, flags, ULPI_FUNC_CTRL); + return usb_phy_io_write(phy, flags, ULPI_FUNC_CTRL); } -static int ulpi_set_ic_flags(struct otg_transceiver *otg) +static int ulpi_set_ic_flags(struct usb_phy *phy) { unsigned int flags = 0; - if (otg->flags & ULPI_IC_AUTORESUME) + if (phy->flags & ULPI_IC_AUTORESUME) flags |= ULPI_IFC_CTRL_AUTORESUME; - if (otg->flags & ULPI_IC_EXTVBUS_INDINV) + if (phy->flags & ULPI_IC_EXTVBUS_INDINV) flags |= ULPI_IFC_CTRL_EXTERNAL_VBUS; - if (otg->flags & ULPI_IC_IND_PASSTHRU) + if (phy->flags & ULPI_IC_IND_PASSTHRU) flags |= ULPI_IFC_CTRL_PASSTHRU; - if (otg->flags & ULPI_IC_PROTECT_DIS) + if (phy->flags & ULPI_IC_PROTECT_DIS) flags |= ULPI_IFC_CTRL_PROTECT_IFC_DISABLE; - return otg_io_write(otg, flags, ULPI_IFC_CTRL); + return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL); } -static int ulpi_set_flags(struct otg_transceiver *otg) +static int ulpi_set_flags(struct usb_phy *phy) { int ret; - ret = ulpi_set_otg_flags(otg); + ret = ulpi_set_otg_flags(phy); if (ret) return ret; - ret = ulpi_set_ic_flags(otg); + ret = ulpi_set_ic_flags(phy); if (ret) return ret; - return ulpi_set_fc_flags(otg); + return ulpi_set_fc_flags(phy); } -static int ulpi_check_integrity(struct otg_transceiver *otg) +static int ulpi_check_integrity(struct usb_phy *phy) { int ret, i; unsigned int val = 0x55; for (i = 0; i < 2; i++) { - ret = otg_io_write(otg, val, ULPI_SCRATCH); + ret = usb_phy_io_write(phy, val, ULPI_SCRATCH); if (ret < 0) return ret; - ret = otg_io_read(otg, ULPI_SCRATCH); + ret = usb_phy_io_read(phy, ULPI_SCRATCH); if (ret < 0) return ret; @@ -175,13 +175,13 @@ static int ulpi_check_integrity(struct otg_transceiver *otg) return 0; } -static int ulpi_init(struct otg_transceiver *otg) +static int ulpi_init(struct usb_phy *phy) { int i, vid, pid, ret; u32 ulpi_id = 0; for (i = 0; i < 4; i++) { - ret = otg_io_read(otg, ULPI_PRODUCT_ID_HIGH - i); + ret = usb_phy_io_read(phy, ULPI_PRODUCT_ID_HIGH - i); if (ret < 0) return ret; ulpi_id = (ulpi_id << 8) | ret; @@ -199,16 +199,17 @@ static int ulpi_init(struct otg_transceiver *otg) } } - ret = ulpi_check_integrity(otg); + ret = ulpi_check_integrity(phy); if (ret) return ret; - return ulpi_set_flags(otg); + return ulpi_set_flags(phy); } -static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host) +static int ulpi_set_host(struct usb_otg *otg, struct usb_bus *host) { - unsigned int flags = otg_io_read(otg, ULPI_IFC_CTRL); + struct usb_phy *phy = otg->phy; + unsigned int flags = usb_phy_io_read(phy, ULPI_IFC_CTRL); if (!host) { otg->host = NULL; @@ -221,51 +222,62 @@ static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host) ULPI_IFC_CTRL_3_PIN_SERIAL_MODE | ULPI_IFC_CTRL_CARKITMODE); - if (otg->flags & ULPI_IC_6PIN_SERIAL) + if (phy->flags & ULPI_IC_6PIN_SERIAL) flags |= ULPI_IFC_CTRL_6_PIN_SERIAL_MODE; - else if (otg->flags & ULPI_IC_3PIN_SERIAL) + else if (phy->flags & ULPI_IC_3PIN_SERIAL) flags |= ULPI_IFC_CTRL_3_PIN_SERIAL_MODE; - else if (otg->flags & ULPI_IC_CARKIT) + else if (phy->flags & ULPI_IC_CARKIT) flags |= ULPI_IFC_CTRL_CARKITMODE; - return otg_io_write(otg, flags, ULPI_IFC_CTRL); + return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL); } -static int ulpi_set_vbus(struct otg_transceiver *otg, bool on) +static int ulpi_set_vbus(struct usb_otg *otg, bool on) { - unsigned int flags = otg_io_read(otg, ULPI_OTG_CTRL); + struct usb_phy *phy = otg->phy; + unsigned int flags = usb_phy_io_read(phy, ULPI_OTG_CTRL); flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT); if (on) { - if (otg->flags & ULPI_OTG_DRVVBUS) + if (phy->flags & ULPI_OTG_DRVVBUS) flags |= ULPI_OTG_CTRL_DRVVBUS; - if (otg->flags & ULPI_OTG_DRVVBUS_EXT) + if (phy->flags & ULPI_OTG_DRVVBUS_EXT) flags |= ULPI_OTG_CTRL_DRVVBUS_EXT; } - return otg_io_write(otg, flags, ULPI_OTG_CTRL); + return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL); } -struct otg_transceiver * -otg_ulpi_create(struct otg_io_access_ops *ops, +struct usb_phy * +otg_ulpi_create(struct usb_phy_io_ops *ops, unsigned int flags) { - struct otg_transceiver *otg; + struct usb_phy *phy; + struct usb_otg *otg; + + phy = kzalloc(sizeof(*phy), GFP_KERNEL); + if (!phy) + return NULL; otg = kzalloc(sizeof(*otg), GFP_KERNEL); - if (!otg) + if (!otg) { + kfree(phy); return NULL; + } + + phy->label = "ULPI"; + phy->flags = flags; + phy->io_ops = ops; + phy->otg = otg; + phy->init = ulpi_init; - otg->label = "ULPI"; - otg->flags = flags; - otg->io_ops = ops; - otg->init = ulpi_init; + otg->phy = phy; otg->set_host = ulpi_set_host; otg->set_vbus = ulpi_set_vbus; - return otg; + return phy; } EXPORT_SYMBOL_GPL(otg_ulpi_create); diff --git a/drivers/usb/otg/ulpi_viewport.c b/drivers/usb/otg/ulpi_viewport.c index e9a37f9..c5ba7e5 100644 --- a/drivers/usb/otg/ulpi_viewport.c +++ b/drivers/usb/otg/ulpi_viewport.c @@ -40,7 +40,7 @@ static int ulpi_viewport_wait(void __iomem *view, u32 mask) return -ETIMEDOUT; } -static int ulpi_viewport_read(struct otg_transceiver *otg, u32 reg) +static int ulpi_viewport_read(struct usb_phy *otg, u32 reg) { int ret; void __iomem *view = otg->io_priv; @@ -58,7 +58,7 @@ static int ulpi_viewport_read(struct otg_transceiver *otg, u32 reg) return ULPI_VIEW_DATA_READ(readl(view)); } -static int ulpi_viewport_write(struct otg_transceiver *otg, u32 val, u32 reg) +static int ulpi_viewport_write(struct usb_phy *otg, u32 val, u32 reg) { int ret; void __iomem *view = otg->io_priv; @@ -74,7 +74,7 @@ static int ulpi_viewport_write(struct otg_transceiver *otg, u32 val, u32 reg) return ulpi_viewport_wait(view, ULPI_VIEW_RUN); } -struct otg_io_access_ops ulpi_viewport_access_ops = { +struct usb_phy_io_ops ulpi_viewport_access_ops = { .read = ulpi_viewport_read, .write = ulpi_viewport_write, }; diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 937f2d4..00bd2a5 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -388,7 +388,7 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv, struct usbhs_pipe *pipe; int recip = ctrl->bRequestType & USB_RECIP_MASK; int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK; - int ret; + int ret = 0; int (*func)(struct usbhs_priv *priv, struct usbhsg_uep *uep, struct usb_ctrlrequest *ctrl); char *msg; diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 677f577..434df7f 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -238,6 +238,15 @@ config USB_SERIAL_EDGEPORT_TI To compile this driver as a module, choose M here: the module will be called io_ti. +config USB_SERIAL_F81232 + tristate "USB Fintek F81232 Single Port Serial Driver" + help + Say Y here if you want to use the Fintek F81232 single + port usb to serial adapter. + + To compile this driver as a module, choose M here: the + module will be called f81232. + config USB_SERIAL_GARMIN tristate "USB Garmin GPS driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 9e536ee..5ac438b 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o +obj-$(CONFIG_USB_SERIAL_F81232) += f81232.o obj-$(CONFIG_USB_SERIAL_FTDI_SIO) += ftdi_sio.o obj-$(CONFIG_USB_SERIAL_FUNSOFT) += funsoft.o obj-$(CONFIG_USB_SERIAL_GARMIN) += garmin_gps.o diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index 123bf91..eec4fb9 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -175,7 +175,6 @@ static struct usb_driver aircable_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver aircable_device = { @@ -183,7 +182,6 @@ static struct usb_serial_driver aircable_device = { .owner = THIS_MODULE, .name = "aircable", }, - .usb_driver = &aircable_driver, .id_table = id_table, .num_ports = 1, .bulk_out_size = HCI_COMPLETE_FRAME, @@ -194,36 +192,16 @@ static struct usb_serial_driver aircable_device = { .unthrottle = usb_serial_generic_unthrottle, }; -static int __init aircable_init(void) -{ - int retval; - retval = usb_serial_register(&aircable_device); - if (retval) - goto failed_serial_register; - retval = usb_register(&aircable_driver); - if (retval) - goto failed_usb_register; - return 0; - -failed_usb_register: - usb_serial_deregister(&aircable_device); -failed_serial_register: - return retval; -} +static struct usb_serial_driver * const serial_drivers[] = { + &aircable_device, NULL +}; -static void __exit aircable_exit(void) -{ - usb_deregister(&aircable_driver); - usb_serial_deregister(&aircable_device); -} +module_usb_serial_driver(aircable_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); -module_init(aircable_init); -module_exit(aircable_exit); - module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 69328dc..f99f4710 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -719,7 +719,6 @@ static struct usb_driver ark3116_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver ark3116_device = { @@ -728,7 +727,6 @@ static struct usb_serial_driver ark3116_device = { .name = "ark3116", }, .id_table = id_table, - .usb_driver = &ark3116_driver, .num_ports = 1, .attach = ark3116_attach, .release = ark3116_release, @@ -745,32 +743,12 @@ static struct usb_serial_driver ark3116_device = { .process_read_urb = ark3116_process_read_urb, }; -static int __init ark3116_init(void) -{ - int retval; - - retval = usb_serial_register(&ark3116_device); - if (retval) - return retval; - retval = usb_register(&ark3116_driver); - if (retval == 0) { - printk(KERN_INFO "%s:" - DRIVER_VERSION ":" - DRIVER_DESC "\n", - KBUILD_MODNAME); - } else - usb_serial_deregister(&ark3116_device); - return retval; -} +static struct usb_serial_driver * const serial_drivers[] = { + &ark3116_device, NULL +}; -static void __exit ark3116_exit(void) -{ - usb_deregister(&ark3116_driver); - usb_serial_deregister(&ark3116_device); -} +module_usb_serial_driver(ark3116_driver, serial_drivers); -module_init(ark3116_init); -module_exit(ark3116_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 29ffeb6..a52e0d2 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -78,7 +78,6 @@ static struct usb_driver belkin_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; /* All of the device info needed for the serial converters */ @@ -88,7 +87,6 @@ static struct usb_serial_driver belkin_device = { .name = "belkin", }, .description = "Belkin / Peracom / GoHubs USB Serial Adapter", - .usb_driver = &belkin_driver, .id_table = id_table_combined, .num_ports = 1, .open = belkin_sa_open, @@ -103,6 +101,10 @@ static struct usb_serial_driver belkin_device = { .release = belkin_sa_release, }; +static struct usb_serial_driver * const serial_drivers[] = { + &belkin_device, NULL +}; + struct belkin_sa_private { spinlock_t lock; unsigned long control_state; @@ -522,34 +524,7 @@ exit: return retval; } - -static int __init belkin_sa_init(void) -{ - int retval; - retval = usb_serial_register(&belkin_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&belkin_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&belkin_device); -failed_usb_serial_register: - return retval; -} - -static void __exit belkin_sa_exit (void) -{ - usb_deregister(&belkin_driver); - usb_serial_deregister(&belkin_device); -} - - -module_init(belkin_sa_init); -module_exit(belkin_sa_exit); +module_usb_serial_driver(belkin_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 5e53cc5..aaab32d 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -625,7 +625,6 @@ static struct usb_driver ch341_driver = { .resume = usb_serial_resume, .reset_resume = ch341_reset_resume, .id_table = id_table, - .no_dynamic_id = 1, .supports_autosuspend = 1, }; @@ -635,7 +634,6 @@ static struct usb_serial_driver ch341_device = { .name = "ch341-uart", }, .id_table = id_table, - .usb_driver = &ch341_driver, .num_ports = 1, .open = ch341_open, .dtr_rts = ch341_dtr_rts, @@ -650,30 +648,13 @@ static struct usb_serial_driver ch341_device = { .attach = ch341_attach, }; -static int __init ch341_init(void) -{ - int retval; - - retval = usb_serial_register(&ch341_device); - if (retval) - return retval; - retval = usb_register(&ch341_driver); - if (retval) - usb_serial_deregister(&ch341_device); - return retval; -} +static struct usb_serial_driver * const serial_drivers[] = { + &ch341_device, NULL +}; -static void __exit ch341_exit(void) -{ - usb_deregister(&ch341_driver); - usb_serial_deregister(&ch341_device); -} +module_usb_serial_driver(ch341_driver, serial_drivers); -module_init(ch341_init); -module_exit(ch341_exit); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); - -/* EOF ch341.c */ diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index fba1147..651b2aa 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -39,6 +39,8 @@ static void cp210x_get_termios(struct tty_struct *, struct usb_serial_port *port); static void cp210x_get_termios_port(struct usb_serial_port *port, unsigned int *cflagp, unsigned int *baudp); +static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *, + struct ktermios *); static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *, struct ktermios*); static int cp210x_tiocmget(struct tty_struct *); @@ -134,10 +136,13 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */ { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ + { USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */ + { USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */ { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ + { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */ { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ { } /* Terminating Entry */ }; @@ -149,7 +154,6 @@ static struct usb_driver cp210x_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver cp210x_device = { @@ -157,7 +161,6 @@ static struct usb_serial_driver cp210x_device = { .owner = THIS_MODULE, .name = "cp210x", }, - .usb_driver = &cp210x_driver, .id_table = id_table, .num_ports = 1, .bulk_in_size = 256, @@ -172,6 +175,10 @@ static struct usb_serial_driver cp210x_device = { .dtr_rts = cp210x_dtr_rts }; +static struct usb_serial_driver * const serial_drivers[] = { + &cp210x_device, NULL +}; + /* Config request types */ #define REQTYPE_HOST_TO_DEVICE 0x41 #define REQTYPE_DEVICE_TO_HOST 0xc1 @@ -201,6 +208,8 @@ static struct usb_serial_driver cp210x_device = { #define CP210X_EMBED_EVENTS 0x15 #define CP210X_GET_EVENTSTATE 0x16 #define CP210X_SET_CHARS 0x19 +#define CP210X_GET_BAUDRATE 0x1D +#define CP210X_SET_BAUDRATE 0x1E /* CP210X_IFC_ENABLE */ #define UART_ENABLE 0x0001 @@ -279,7 +288,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, if (result != size) { dbg("%s - Unable to send config request, " - "request=0x%x size=%d result=%d\n", + "request=0x%x size=%d result=%d", __func__, request, size, result); if (result > 0) result = -EPROTO; @@ -333,7 +342,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, if ((size > 2 && result != size) || result < 0) { dbg("%s - Unable to send request, " - "request=0x%x size=%d result=%d\n", + "request=0x%x size=%d result=%d", __func__, request, size, result); if (result > 0) result = -EPROTO; @@ -360,8 +369,8 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port, * Quantises the baud rate as per AN205 Table 1 */ static unsigned int cp210x_quantise_baudrate(unsigned int baud) { - if (baud <= 56) baud = 0; - else if (baud <= 300) baud = 300; + if (baud <= 300) + baud = 300; else if (baud <= 600) baud = 600; else if (baud <= 1200) baud = 1200; else if (baud <= 1800) baud = 1800; @@ -389,10 +398,10 @@ static unsigned int cp210x_quantise_baudrate(unsigned int baud) { else if (baud <= 491520) baud = 460800; else if (baud <= 567138) baud = 500000; else if (baud <= 670254) baud = 576000; - else if (baud <= 1053257) baud = 921600; - else if (baud <= 1474560) baud = 1228800; - else if (baud <= 2457600) baud = 1843200; - else baud = 3686400; + else if (baud < 1000000) + baud = 921600; + else if (baud > 2000000) + baud = 2000000; return baud; } @@ -409,13 +418,14 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port) return result; } - result = usb_serial_generic_open(tty, port); - if (result) - return result; - /* Configure the termios structure */ cp210x_get_termios(tty, port); - return 0; + + /* The baud rate must be initialised on cp2104 */ + if (tty) + cp210x_change_speed(tty, port, NULL); + + return usb_serial_generic_open(tty, port); } static void cp210x_close(struct usb_serial_port *port) @@ -467,10 +477,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, dbg("%s - port %d", __func__, port->number); - cp210x_get_config(port, CP210X_GET_BAUDDIV, &baud, 2); - /* Convert to baudrate */ - if (baud) - baud = cp210x_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); + cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4); dbg("%s - baud rate = %d", __func__, baud); *baudp = baud; @@ -579,11 +586,64 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, *cflagp = cflag; } +/* + * CP2101 supports the following baud rates: + * + * 300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 28800, + * 38400, 56000, 57600, 115200, 128000, 230400, 460800, 921600 + * + * CP2102 and CP2103 support the following additional rates: + * + * 4000, 16000, 51200, 64000, 76800, 153600, 250000, 256000, 500000, + * 576000 + * + * The device will map a requested rate to a supported one, but the result + * of requests for rates greater than 1053257 is undefined (see AN205). + * + * CP2104, CP2105 and CP2110 support most rates up to 2M, 921k and 1M baud, + * respectively, with an error less than 1%. The actual rates are determined + * by + * + * div = round(freq / (2 x prescale x request)) + * actual = freq / (2 x prescale x div) + * + * For CP2104 and CP2105 freq is 48Mhz and prescale is 4 for request <= 365bps + * or 1 otherwise. + * For CP2110 freq is 24Mhz and prescale is 4 for request <= 300bps or 1 + * otherwise. + */ +static void cp210x_change_speed(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) +{ + u32 baud; + + baud = tty->termios->c_ospeed; + + /* This maps the requested rate to a rate valid on cp2102 or cp2103, + * or to an arbitrary rate in [1M,2M]. + * + * NOTE: B0 is not implemented. + */ + baud = cp210x_quantise_baudrate(baud); + + dbg("%s - setting baud rate to %u", __func__, baud); + if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud, + sizeof(baud))) { + dev_warn(&port->dev, "failed to set baud rate to %u\n", baud); + if (old_termios) + baud = old_termios->c_ospeed; + else + baud = 9600; + } + + tty_encode_baud_rate(tty, baud, baud); +} + static void cp210x_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { unsigned int cflag, old_cflag; - unsigned int baud = 0, bits; + unsigned int bits; unsigned int modem_ctl[4]; dbg("%s - port %d", __func__, port->number); @@ -593,20 +653,9 @@ static void cp210x_set_termios(struct tty_struct *tty, cflag = tty->termios->c_cflag; old_cflag = old_termios->c_cflag; - baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty)); - - /* If the baud rate is to be updated*/ - if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { - dbg("%s - Setting baud rate to %d baud", __func__, - baud); - if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV, - ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { - dbg("Baud rate requested not supported by device"); - baud = tty_termios_baud_rate(old_termios); - } - } - /* Report back the resulting baud rate */ - tty_encode_baud_rate(tty, baud, baud); + + if (tty->termios->c_ospeed != old_termios->c_ospeed) + cp210x_change_speed(tty, port, old_termios); /* If the number of data bits is to be updated */ if ((cflag & CSIZE) != (old_cflag & CSIZE)) { @@ -636,13 +685,13 @@ static void cp210x_set_termios(struct tty_struct *tty, default: dbg("cp210x driver does not " "support the number of bits requested," - " using 8 bit mode\n"); + " using 8 bit mode"); bits |= BITS_DATA_8; break; } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) dbg("Number of data bits requested " - "not supported by device\n"); + "not supported by device"); } if ((cflag & (PARENB|PARODD|CMSPAR)) != @@ -669,8 +718,7 @@ static void cp210x_set_termios(struct tty_struct *tty, } } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) - dbg("Parity mode not supported " - "by device\n"); + dbg("Parity mode not supported by device"); } if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) { @@ -685,7 +733,7 @@ static void cp210x_set_termios(struct tty_struct *tty, } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) dbg("Number of stop bits requested " - "not supported by device\n"); + "not supported by device"); } if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { @@ -802,35 +850,7 @@ static int cp210x_startup(struct usb_serial *serial) return 0; } -static int __init cp210x_init(void) -{ - int retval; - - retval = usb_serial_register(&cp210x_device); - if (retval) - return retval; /* Failed to register */ - - retval = usb_register(&cp210x_driver); - if (retval) { - /* Failed to register */ - usb_serial_deregister(&cp210x_device); - return retval; - } - - /* Success */ - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -} - -static void __exit cp210x_exit(void) -{ - usb_deregister(&cp210x_driver); - usb_serial_deregister(&cp210x_device); -} - -module_init(cp210x_init); -module_exit(cp210x_exit); +module_usb_serial_driver(cp210x_driver, serial_drivers); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 6bc3802..d39b941 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -82,7 +82,6 @@ static struct usb_driver cyberjack_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver cyberjack_device = { @@ -91,7 +90,6 @@ static struct usb_serial_driver cyberjack_device = { .name = "cyberjack", }, .description = "Reiner SCT Cyberjack USB card reader", - .usb_driver = &cyberjack_driver, .id_table = id_table, .num_ports = 1, .attach = cyberjack_startup, @@ -106,6 +104,10 @@ static struct usb_serial_driver cyberjack_device = { .write_bulk_callback = cyberjack_write_bulk_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &cyberjack_device, NULL +}; + struct cyberjack_private { spinlock_t lock; /* Lock for SMP */ short rdtodo; /* Bytes still to read */ @@ -473,35 +475,7 @@ exit: usb_serial_port_softint(port); } -static int __init cyberjack_init(void) -{ - int retval; - retval = usb_serial_register(&cyberjack_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&cyberjack_driver); - if (retval) - goto failed_usb_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION " " - DRIVER_AUTHOR "\n"); - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); - - return 0; -failed_usb_register: - usb_serial_deregister(&cyberjack_device); -failed_usb_serial_register: - return retval; -} - -static void __exit cyberjack_exit(void) -{ - usb_deregister(&cyberjack_driver); - usb_serial_deregister(&cyberjack_device); -} - -module_init(cyberjack_init); -module_exit(cyberjack_exit); +module_usb_serial_driver(cyberjack_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 3bdeafa..afc886c 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -94,7 +94,6 @@ static struct usb_driver cypress_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; enum packet_format { @@ -163,7 +162,6 @@ static struct usb_serial_driver cypress_earthmate_device = { .name = "earthmate", }, .description = "DeLorme Earthmate USB", - .usb_driver = &cypress_driver, .id_table = id_table_earthmate, .num_ports = 1, .attach = cypress_earthmate_startup, @@ -190,7 +188,6 @@ static struct usb_serial_driver cypress_hidcom_device = { .name = "cyphidcom", }, .description = "HID->COM RS232 Adapter", - .usb_driver = &cypress_driver, .id_table = id_table_cyphidcomrs232, .num_ports = 1, .attach = cypress_hidcom_startup, @@ -217,7 +214,6 @@ static struct usb_serial_driver cypress_ca42v2_device = { .name = "nokiaca42v2", }, .description = "Nokia CA-42 V2 Adapter", - .usb_driver = &cypress_driver, .id_table = id_table_nokiaca42v2, .num_ports = 1, .attach = cypress_ca42v2_startup, @@ -238,6 +234,11 @@ static struct usb_serial_driver cypress_ca42v2_device = { .write_int_callback = cypress_write_int_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &cypress_earthmate_device, &cypress_hidcom_device, + &cypress_ca42v2_device, NULL +}; + /***************************************************************************** * Cypress serial helper functions *****************************************************************************/ @@ -800,7 +801,7 @@ send: cypress_write_int_callback, port, priv->write_urb_interval); result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, + dev_err_console(port, "%s - failed submitting write urb, error %d\n", __func__, result); priv->write_urb_in_use = 0; @@ -1345,58 +1346,7 @@ static void cypress_write_int_callback(struct urb *urb) cypress_send(port); } - -/***************************************************************************** - * Module functions - *****************************************************************************/ - -static int __init cypress_init(void) -{ - int retval; - - dbg("%s", __func__); - - retval = usb_serial_register(&cypress_earthmate_device); - if (retval) - goto failed_em_register; - retval = usb_serial_register(&cypress_hidcom_device); - if (retval) - goto failed_hidcom_register; - retval = usb_serial_register(&cypress_ca42v2_device); - if (retval) - goto failed_ca42v2_register; - retval = usb_register(&cypress_driver); - if (retval) - goto failed_usb_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; - -failed_usb_register: - usb_serial_deregister(&cypress_ca42v2_device); -failed_ca42v2_register: - usb_serial_deregister(&cypress_hidcom_device); -failed_hidcom_register: - usb_serial_deregister(&cypress_earthmate_device); -failed_em_register: - return retval; -} - - -static void __exit cypress_exit(void) -{ - dbg("%s", __func__); - - usb_deregister(&cypress_driver); - usb_serial_deregister(&cypress_earthmate_device); - usb_serial_deregister(&cypress_hidcom_device); - usb_serial_deregister(&cypress_ca42v2_device); -} - - -module_init(cypress_init); -module_exit(cypress_exit); +module_usb_serial_driver(cypress_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index b23bebd..999f91b 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -276,7 +276,6 @@ static struct usb_driver digi_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; @@ -288,7 +287,6 @@ static struct usb_serial_driver digi_acceleport_2_device = { .name = "digi_2", }, .description = "Digi 2 port USB adapter", - .usb_driver = &digi_driver, .id_table = id_table_2, .num_ports = 3, .open = digi_open, @@ -316,7 +314,6 @@ static struct usb_serial_driver digi_acceleport_4_device = { .name = "digi_4", }, .description = "Digi 4 port USB adapter", - .usb_driver = &digi_driver, .id_table = id_table_4, .num_ports = 4, .open = digi_open, @@ -337,6 +334,9 @@ static struct usb_serial_driver digi_acceleport_4_device = { .release = digi_release, }; +static struct usb_serial_driver * const serial_drivers[] = { + &digi_acceleport_2_device, &digi_acceleport_4_device, NULL +}; /* Functions */ @@ -995,7 +995,7 @@ static int digi_write(struct tty_struct *tty, struct usb_serial_port *port, /* return length of new data written, or error */ spin_unlock_irqrestore(&priv->dp_port_lock, flags); if (ret < 0) - dev_err(&port->dev, + dev_err_console(port, "%s: usb_submit_urb failed, ret=%d, port=%d\n", __func__, ret, priv->dp_port_num); dbg("digi_write: returning %d", ret); @@ -1065,7 +1065,7 @@ static void digi_write_bulk_callback(struct urb *urb) spin_unlock(&priv->dp_port_lock); if (ret && ret != -EPERM) - dev_err(&port->dev, + dev_err_console(port, "%s: usb_submit_urb failed, ret=%d, port=%d\n", __func__, ret, priv->dp_port_num); } @@ -1580,40 +1580,7 @@ static int digi_read_oob_callback(struct urb *urb) } -static int __init digi_init(void) -{ - int retval; - retval = usb_serial_register(&digi_acceleport_2_device); - if (retval) - goto failed_acceleport_2_device; - retval = usb_serial_register(&digi_acceleport_4_device); - if (retval) - goto failed_acceleport_4_device; - retval = usb_register(&digi_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&digi_acceleport_4_device); -failed_acceleport_4_device: - usb_serial_deregister(&digi_acceleport_2_device); -failed_acceleport_2_device: - return retval; -} - -static void __exit digi_exit (void) -{ - usb_deregister(&digi_driver); - usb_serial_deregister(&digi_acceleport_2_device); - usb_serial_deregister(&digi_acceleport_4_device); -} - - -module_init(digi_init); -module_exit(digi_exit); - +module_usb_serial_driver(digi_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index aced681..5b99fc0 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -56,7 +56,6 @@ static struct usb_driver empeg_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver empeg_device = { @@ -65,7 +64,6 @@ static struct usb_serial_driver empeg_device = { .name = "empeg", }, .id_table = id_table, - .usb_driver = &empeg_driver, .num_ports = 1, .bulk_out_size = 256, .throttle = usb_serial_generic_throttle, @@ -74,6 +72,10 @@ static struct usb_serial_driver empeg_device = { .init_termios = empeg_init_termios, }; +static struct usb_serial_driver * const serial_drivers[] = { + &empeg_device, NULL +}; + static int empeg_startup(struct usb_serial *serial) { int r; @@ -136,33 +138,7 @@ static void empeg_init_termios(struct tty_struct *tty) tty_encode_baud_rate(tty, 115200, 115200); } -static int __init empeg_init(void) -{ - int retval; - - retval = usb_serial_register(&empeg_device); - if (retval) - return retval; - retval = usb_register(&empeg_driver); - if (retval) { - usb_serial_deregister(&empeg_device); - return retval; - } - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; -} - -static void __exit empeg_exit(void) -{ - usb_deregister(&empeg_driver); - usb_serial_deregister(&empeg_device); -} - - -module_init(empeg_init); -module_exit(empeg_exit); +module_usb_serial_driver(empeg_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c new file mode 100644 index 0000000..88c0b19 --- /dev/null +++ b/drivers/usb/serial/f81232.c @@ -0,0 +1,405 @@ +/* + * Fintek F81232 USB to serial adaptor driver + * + * Copyright (C) 2012 Greg Kroah-Hartman (gregkh@linuxfoundation.org) + * Copyright (C) 2012 Linux Foundation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/tty.h> +#include <linux/tty_driver.h> +#include <linux/tty_flip.h> +#include <linux/serial.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/spinlock.h> +#include <linux/uaccess.h> +#include <linux/usb.h> +#include <linux/usb/serial.h> + +static bool debug; + +static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x1934, 0x0706) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, id_table); + +#define CONTROL_DTR 0x01 +#define CONTROL_RTS 0x02 + +#define UART_STATE 0x08 +#define UART_STATE_TRANSIENT_MASK 0x74 +#define UART_DCD 0x01 +#define UART_DSR 0x02 +#define UART_BREAK_ERROR 0x04 +#define UART_RING 0x08 +#define UART_FRAME_ERROR 0x10 +#define UART_PARITY_ERROR 0x20 +#define UART_OVERRUN_ERROR 0x40 +#define UART_CTS 0x80 + +struct f81232_private { + spinlock_t lock; + wait_queue_head_t delta_msr_wait; + u8 line_control; + u8 line_status; +}; + +static void f81232_update_line_status(struct usb_serial_port *port, + unsigned char *data, + unsigned int actual_length) +{ +} + +static void f81232_read_int_callback(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + unsigned char *data = urb->transfer_buffer; + unsigned int actual_length = urb->actual_length; + int status = urb->status; + int retval; + + dbg("%s (%d)", __func__, port->number); + + switch (status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __func__, + status); + return; + default: + dbg("%s - nonzero urb status received: %d", __func__, + status); + goto exit; + } + + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, urb->transfer_buffer); + + f81232_update_line_status(port, data, actual_length); + +exit: + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(&urb->dev->dev, + "%s - usb_submit_urb failed with result %d\n", + __func__, retval); +} + +static void f81232_process_read_urb(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + struct f81232_private *priv = usb_get_serial_port_data(port); + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + char tty_flag = TTY_NORMAL; + unsigned long flags; + u8 line_status; + int i; + + /* update line status */ + spin_lock_irqsave(&priv->lock, flags); + line_status = priv->line_status; + priv->line_status &= ~UART_STATE_TRANSIENT_MASK; + spin_unlock_irqrestore(&priv->lock, flags); + wake_up_interruptible(&priv->delta_msr_wait); + + if (!urb->actual_length) + return; + + tty = tty_port_tty_get(&port->port); + if (!tty) + return; + + /* break takes precedence over parity, */ + /* which takes precedence over framing errors */ + if (line_status & UART_BREAK_ERROR) + tty_flag = TTY_BREAK; + else if (line_status & UART_PARITY_ERROR) + tty_flag = TTY_PARITY; + else if (line_status & UART_FRAME_ERROR) + tty_flag = TTY_FRAME; + dbg("%s - tty_flag = %d", __func__, tty_flag); + + /* overrun is special, not associated with a char */ + if (line_status & UART_OVERRUN_ERROR) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + + if (port->port.console && port->sysrq) { + for (i = 0; i < urb->actual_length; ++i) + if (!usb_serial_handle_sysrq_char(port, data[i])) + tty_insert_flip_char(tty, data[i], tty_flag); + } else { + tty_insert_flip_string_fixed_flag(tty, data, tty_flag, + urb->actual_length); + } + + tty_flip_buffer_push(tty); + tty_kref_put(tty); +} + +static int set_control_lines(struct usb_device *dev, u8 value) +{ + /* FIXME - Stubbed out for now */ + return 0; +} + +static void f81232_break_ctl(struct tty_struct *tty, int break_state) +{ + /* FIXME - Stubbed out for now */ + + /* + * break_state = -1 to turn on break, and 0 to turn off break + * see drivers/char/tty_io.c to see it used. + * last_set_data_urb_value NEVER has the break bit set in it. + */ +} + +static void f81232_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) +{ + /* FIXME - Stubbed out for now */ + + /* Don't change anything if nothing has changed */ + if (!tty_termios_hw_change(tty->termios, old_termios)) + return; + + /* Do the real work here... */ +} + +static int f81232_tiocmget(struct tty_struct *tty) +{ + /* FIXME - Stubbed out for now */ + return 0; +} + +static int f81232_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + /* FIXME - Stubbed out for now */ + return 0; +} + +static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port) +{ + struct ktermios tmp_termios; + int result; + + /* Setup termios */ + if (tty) + f81232_set_termios(tty, port, &tmp_termios); + + dbg("%s - submitting interrupt urb", __func__); + result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (result) { + dev_err(&port->dev, "%s - failed submitting interrupt urb," + " error %d\n", __func__, result); + return result; + } + + result = usb_serial_generic_open(tty, port); + if (result) { + usb_kill_urb(port->interrupt_in_urb); + return result; + } + + port->port.drain_delay = 256; + return 0; +} + +static void f81232_close(struct usb_serial_port *port) +{ + usb_serial_generic_close(port); + usb_kill_urb(port->interrupt_in_urb); +} + +static void f81232_dtr_rts(struct usb_serial_port *port, int on) +{ + struct f81232_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + u8 control; + + spin_lock_irqsave(&priv->lock, flags); + /* Change DTR and RTS */ + if (on) + priv->line_control |= (CONTROL_DTR | CONTROL_RTS); + else + priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); + control = priv->line_control; + spin_unlock_irqrestore(&priv->lock, flags); + set_control_lines(port->serial->dev, control); +} + +static int f81232_carrier_raised(struct usb_serial_port *port) +{ + struct f81232_private *priv = usb_get_serial_port_data(port); + if (priv->line_status & UART_DCD) + return 1; + return 0; +} + +static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +{ + struct f81232_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + unsigned int prevstatus; + unsigned int status; + unsigned int changed; + + spin_lock_irqsave(&priv->lock, flags); + prevstatus = priv->line_status; + spin_unlock_irqrestore(&priv->lock, flags); + + while (1) { + interruptible_sleep_on(&priv->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + + spin_lock_irqsave(&priv->lock, flags); + status = priv->line_status; + spin_unlock_irqrestore(&priv->lock, flags); + + changed = prevstatus ^ status; + + if (((arg & TIOCM_RNG) && (changed & UART_RING)) || + ((arg & TIOCM_DSR) && (changed & UART_DSR)) || + ((arg & TIOCM_CD) && (changed & UART_DCD)) || + ((arg & TIOCM_CTS) && (changed & UART_CTS))) { + return 0; + } + prevstatus = status; + } + /* NOTREACHED */ + return 0; +} + +static int f81232_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct serial_struct ser; + struct usb_serial_port *port = tty->driver_data; + dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); + + switch (cmd) { + case TIOCGSERIAL: + memset(&ser, 0, sizeof ser); + ser.type = PORT_16654; + ser.line = port->serial->minor; + ser.port = port->number; + ser.baud_base = 460800; + + if (copy_to_user((void __user *)arg, &ser, sizeof ser)) + return -EFAULT; + + return 0; + + case TIOCMIWAIT: + dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + return wait_modem_info(port, arg); + default: + dbg("%s not supported = 0x%04x", __func__, cmd); + break; + } + return -ENOIOCTLCMD; +} + +static int f81232_startup(struct usb_serial *serial) +{ + struct f81232_private *priv; + int i; + + for (i = 0; i < serial->num_ports; ++i) { + priv = kzalloc(sizeof(struct f81232_private), GFP_KERNEL); + if (!priv) + goto cleanup; + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + usb_set_serial_port_data(serial->port[i], priv); + } + return 0; + +cleanup: + for (--i; i >= 0; --i) { + priv = usb_get_serial_port_data(serial->port[i]); + kfree(priv); + usb_set_serial_port_data(serial->port[i], NULL); + } + return -ENOMEM; +} + +static void f81232_release(struct usb_serial *serial) +{ + int i; + struct f81232_private *priv; + + for (i = 0; i < serial->num_ports; ++i) { + priv = usb_get_serial_port_data(serial->port[i]); + kfree(priv); + } +} + +static struct usb_driver f81232_driver = { + .name = "f81232", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, + .no_dynamic_id = 1, + .supports_autosuspend = 1, +}; + +static struct usb_serial_driver f81232_device = { + .driver = { + .owner = THIS_MODULE, + .name = "f81232", + }, + .id_table = id_table, + .usb_driver = &f81232_driver, + .num_ports = 1, + .bulk_in_size = 256, + .bulk_out_size = 256, + .open = f81232_open, + .close = f81232_close, + .dtr_rts = f81232_dtr_rts, + .carrier_raised = f81232_carrier_raised, + .ioctl = f81232_ioctl, + .break_ctl = f81232_break_ctl, + .set_termios = f81232_set_termios, + .tiocmget = f81232_tiocmget, + .tiocmset = f81232_tiocmset, + .process_read_urb = f81232_process_read_urb, + .read_int_callback = f81232_read_int_callback, + .attach = f81232_startup, + .release = f81232_release, +}; + +static struct usb_serial_driver * const serial_drivers[] = { + &f81232_device, + NULL, +}; + +module_usb_serial_driver(f81232_driver, serial_drivers); + +MODULE_DESCRIPTION("Fintek F81232 USB to serial adaptor driver"); +MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org"); +MODULE_LICENSE("GPL v2"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); + diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 01b6404..9892626 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -536,6 +536,10 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) }, { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) }, { USB_DEVICE(OCT_VID, OCT_US101_PID) }, { USB_DEVICE(OCT_VID, OCT_DK201_PID) }, @@ -797,6 +801,7 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(HORNBY_VID, HORNBY_ELITE_PID) }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, @@ -805,6 +810,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, TI_XDS100V2_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) }, { USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) }, { USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) }, @@ -836,11 +843,13 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CINTERION_MC55I_PID) }, { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) }, { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(ST_VID, ST_STMCLT1030_PID), .driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_RF_R106) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; @@ -852,7 +861,6 @@ static struct usb_driver ftdi_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; static const char *ftdi_chip_name[] = { @@ -910,7 +918,6 @@ static struct usb_serial_driver ftdi_sio_device = { .name = "ftdi_sio", }, .description = "FTDI USB Serial Device", - .usb_driver = &ftdi_driver, .id_table = id_table_combined, .num_ports = 1, .bulk_in_size = 512, @@ -933,6 +940,10 @@ static struct usb_serial_driver ftdi_sio_device = { .break_ctl = ftdi_break_ctl, }; +static struct usb_serial_driver * const serial_drivers[] = { + &ftdi_sio_device, NULL +}; + #define WDR_TIMEOUT 5000 /* default urb timeout */ #define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */ @@ -1333,8 +1344,7 @@ static int set_serial_info(struct tty_struct *tty, goto check_and_exit; } - if ((new_serial.baud_base != priv->baud_base) && - (new_serial.baud_base < 9600)) { + if (new_serial.baud_base != priv->baud_base) { mutex_unlock(&priv->cfg_lock); return -EINVAL; } @@ -1759,7 +1769,8 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial) dbg("%s", __func__); - if (strcmp(udev->manufacturer, "CALAO Systems") == 0) + if ((udev->manufacturer) && + (strcmp(udev->manufacturer, "CALAO Systems") == 0)) return ftdi_jtag_probe(serial); return 0; @@ -1824,6 +1835,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) { + struct ktermios dummy; struct usb_device *dev = port->serial->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); int result; @@ -1842,8 +1854,10 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) This is same behaviour as serial.c/rs_open() - Kuba */ /* ftdi_set_termios will send usb control messages */ - if (tty) - ftdi_set_termios(tty, port, tty->termios); + if (tty) { + memset(&dummy, 0, sizeof(dummy)); + ftdi_set_termios(tty, port, &dummy); + } /* Start reading from the device */ result = usb_serial_generic_open(tty, port); @@ -2413,19 +2427,10 @@ static int __init ftdi_init(void) id_table_combined[i].idVendor = vendor; id_table_combined[i].idProduct = product; } - retval = usb_serial_register(&ftdi_sio_device); - if (retval) - goto failed_sio_register; - retval = usb_register(&ftdi_driver); - if (retval) - goto failed_usb_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&ftdi_sio_device); -failed_sio_register: + retval = usb_serial_register_drivers(&ftdi_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } @@ -2433,8 +2438,7 @@ static void __exit ftdi_exit(void) { dbg("%s", __func__); - usb_deregister(&ftdi_driver); - usb_serial_deregister(&ftdi_sio_device); + usb_serial_deregister_drivers(&ftdi_driver, serial_drivers); } diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index df1d7da..ed74019 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -39,6 +39,13 @@ /* www.candapter.com Ewert Energy Systems CANdapter device */ #define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */ +/* + * Texas Instruments XDS100v2 JTAG / BeagleBone A3 + * http://processors.wiki.ti.com/index.php/XDS100 + * http://beagleboard.org/bone + */ +#define TI_XDS100V2_PID 0xa6d0 + #define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */ /* US Interface Navigator (http://www.usinterface.com/) */ @@ -525,6 +532,12 @@ #define ADI_GNICEPLUS_PID 0xF001 /* + * Hornby Elite + */ +#define HORNBY_VID 0x04D8 +#define HORNBY_ELITE_PID 0x000A + +/* * RATOC REX-USB60F */ #define RATOC_VENDOR_ID 0x0584 @@ -667,6 +680,10 @@ #define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */ #define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */ #define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */ +#define SEALEVEL_2803R_1_PID 0Xa02a /* SeaLINK+8 (2803-ROHS) Port 1+2 */ +#define SEALEVEL_2803R_2_PID 0Xa02b /* SeaLINK+8 (2803-ROHS) Port 3+4 */ +#define SEALEVEL_2803R_3_PID 0Xa02c /* SeaLINK+8 (2803-ROHS) Port 5+6 */ +#define SEALEVEL_2803R_4_PID 0Xa02d /* SeaLINK+8 (2803-ROHS) Port 7+8 */ /* * JETI SPECTROMETER SPECBOS 1201 @@ -1168,3 +1185,16 @@ */ /* TagTracer MIFARE*/ #define FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID 0xF7C0 + +/* + * Rainforest Automation + */ +/* ZigBee controller */ +#define FTDI_RF_R106 0x8A28 + +/* + * Product: HCP HIT GPRS modem + * Manufacturer: HCP d.o.o. + * ATI command output: Cinterion MC55i + */ +#define FTDI_CINTERION_MC55I_PID 0xA951 diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c index 5d4b099..4577b36 100644 --- a/drivers/usb/serial/funsoft.c +++ b/drivers/usb/serial/funsoft.c @@ -29,7 +29,6 @@ static struct usb_driver funsoft_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver funsoft_device = { @@ -38,31 +37,15 @@ static struct usb_serial_driver funsoft_device = { .name = "funsoft", }, .id_table = id_table, - .usb_driver = &funsoft_driver, .num_ports = 1, }; -static int __init funsoft_init(void) -{ - int retval; - - retval = usb_serial_register(&funsoft_device); - if (retval) - return retval; - retval = usb_register(&funsoft_driver); - if (retval) - usb_serial_deregister(&funsoft_device); - return retval; -} +static struct usb_serial_driver * const serial_drivers[] = { + &funsoft_device, NULL +}; -static void __exit funsoft_exit(void) -{ - usb_deregister(&funsoft_driver); - usb_serial_deregister(&funsoft_device); -} +module_usb_serial_driver(funsoft_driver, serial_drivers); -module_init(funsoft_init); -module_exit(funsoft_exit); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 2134337..e8eb634 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -224,7 +224,6 @@ static struct usb_driver garmin_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; @@ -1497,7 +1496,6 @@ static struct usb_serial_driver garmin_device = { .name = "garmin_gps", }, .description = "Garmin GPS usb/tty", - .usb_driver = &garmin_driver, .id_table = id_table, .num_ports = 1, .open = garmin_open, @@ -1514,40 +1512,11 @@ static struct usb_serial_driver garmin_device = { .read_int_callback = garmin_read_int_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &garmin_device, NULL +}; - -static int __init garmin_init(void) -{ - int retval; - - retval = usb_serial_register(&garmin_device); - if (retval) - goto failed_garmin_register; - retval = usb_register(&garmin_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; -failed_usb_register: - usb_serial_deregister(&garmin_device); -failed_garmin_register: - return retval; -} - - -static void __exit garmin_exit(void) -{ - usb_deregister(&garmin_driver); - usb_serial_deregister(&garmin_device); -} - - - - -module_init(garmin_init); -module_exit(garmin_exit); +module_usb_serial_driver(garmin_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); @@ -1557,4 +1526,3 @@ module_param(debug, bool, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(debug, "Debug enabled or not"); module_param(initial_mode, int, S_IRUGO); MODULE_PARM_DESC(initial_mode, "Initial mode"); - diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index f740357..664deb6 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -54,7 +54,6 @@ static struct usb_driver generic_driver = { .probe = generic_probe, .disconnect = usb_serial_disconnect, .id_table = generic_serial_ids, - .no_dynamic_id = 1, }; /* All of the device info needed for the Generic Serial Converter */ @@ -64,7 +63,6 @@ struct usb_serial_driver usb_serial_generic_device = { .name = "generic", }, .id_table = generic_device_ids, - .usb_driver = &generic_driver, .num_ports = 1, .disconnect = usb_serial_generic_disconnect, .release = usb_serial_generic_release, @@ -73,6 +71,10 @@ struct usb_serial_driver usb_serial_generic_device = { .resume = usb_serial_generic_resume, }; +static struct usb_serial_driver * const serial_drivers[] = { + &usb_serial_generic_device, NULL +}; + static int generic_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -97,13 +99,7 @@ int usb_serial_generic_register(int _debug) USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT; /* register our generic driver with ourselves */ - retval = usb_serial_register(&usb_serial_generic_device); - if (retval) - goto exit; - retval = usb_register(&generic_driver); - if (retval) - usb_serial_deregister(&usb_serial_generic_device); -exit: + retval = usb_serial_register_drivers(&generic_driver, serial_drivers); #endif return retval; } @@ -112,8 +108,7 @@ void usb_serial_generic_deregister(void) { #ifdef CONFIG_USB_SERIAL_GENERIC /* remove our generic driver */ - usb_deregister(&generic_driver); - usb_serial_deregister(&usb_serial_generic_device); + usb_serial_deregister_drivers(&generic_driver, serial_drivers); #endif } @@ -217,7 +212,7 @@ retry: clear_bit(i, &port->write_urbs_free); result = usb_submit_urb(urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, "%s - error submitting urb: %d\n", + dev_err_console(port, "%s - error submitting urb: %d\n", __func__, result); set_bit(i, &port->write_urbs_free); spin_lock_irqsave(&port->lock, flags); diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c index 8093791..2563e78 100644 --- a/drivers/usb/serial/hp4x.c +++ b/drivers/usb/serial/hp4x.c @@ -41,7 +41,6 @@ static struct usb_driver hp49gp_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver hp49gp_device = { @@ -50,36 +49,14 @@ static struct usb_serial_driver hp49gp_device = { .name = "hp4X", }, .id_table = id_table, - .usb_driver = &hp49gp_driver, .num_ports = 1, }; -static int __init hp49gp_init(void) -{ - int retval; - retval = usb_serial_register(&hp49gp_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&hp49gp_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&hp49gp_device); -failed_usb_serial_register: - return retval; -} - -static void __exit hp49gp_exit(void) -{ - usb_deregister(&hp49gp_driver); - usb_serial_deregister(&hp49gp_device); -} +static struct usb_serial_driver * const serial_drivers[] = { + &hp49gp_device, NULL +}; -module_init(hp49gp_init); -module_exit(hp49gp_exit); +module_usb_serial_driver(hp49gp_driver, serial_drivers); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 0497575..323e872 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -193,7 +193,8 @@ static const struct divisor_table_entry divisor_table[] = { /* local variables */ static bool debug; -static atomic_t CmdUrbs; /* Number of outstanding Command Write Urbs */ +/* Number of outstanding Command Write Urbs */ +static atomic_t CmdUrbs = ATOMIC_INIT(0); /* local function prototypes */ @@ -1286,7 +1287,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, count = fifo->count; buffer = kmalloc(count+2, GFP_ATOMIC); if (buffer == NULL) { - dev_err(&edge_port->port->dev, + dev_err_console(edge_port->port, "%s - no more kernel memory...\n", __func__); edge_port->write_in_progress = false; goto exit_send; @@ -1331,7 +1332,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { /* something went wrong */ - dev_err(&edge_port->port->dev, + dev_err_console(edge_port->port, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __func__, status); edge_port->write_in_progress = false; @@ -3180,65 +3181,8 @@ static void edge_release(struct usb_serial *serial) kfree(edge_serial); } +module_usb_serial_driver(io_driver, serial_drivers); -/**************************************************************************** - * edgeport_init - * This is called by the module subsystem, or on startup to initialize us - ****************************************************************************/ -static int __init edgeport_init(void) -{ - int retval; - - retval = usb_serial_register(&edgeport_2port_device); - if (retval) - goto failed_2port_device_register; - retval = usb_serial_register(&edgeport_4port_device); - if (retval) - goto failed_4port_device_register; - retval = usb_serial_register(&edgeport_8port_device); - if (retval) - goto failed_8port_device_register; - retval = usb_serial_register(&epic_device); - if (retval) - goto failed_epic_device_register; - retval = usb_register(&io_driver); - if (retval) - goto failed_usb_register; - atomic_set(&CmdUrbs, 0); - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; - -failed_usb_register: - usb_serial_deregister(&epic_device); -failed_epic_device_register: - usb_serial_deregister(&edgeport_8port_device); -failed_8port_device_register: - usb_serial_deregister(&edgeport_4port_device); -failed_4port_device_register: - usb_serial_deregister(&edgeport_2port_device); -failed_2port_device_register: - return retval; -} - - -/**************************************************************************** - * edgeport_exit - * Called when the driver is about to be unloaded. - ****************************************************************************/ -static void __exit edgeport_exit (void) -{ - usb_deregister(&io_driver); - usb_serial_deregister(&edgeport_2port_device); - usb_serial_deregister(&edgeport_4port_device); - usb_serial_deregister(&edgeport_8port_device); - usb_serial_deregister(&epic_device); -} - -module_init(edgeport_init); -module_exit(edgeport_exit); - -/* Module information */ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index 178b22e..d0e7c9a 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -100,7 +100,6 @@ static struct usb_driver io_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; static struct usb_serial_driver edgeport_2port_device = { @@ -109,7 +108,6 @@ static struct usb_serial_driver edgeport_2port_device = { .name = "edgeport_2", }, .description = "Edgeport 2 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_2port_id_table, .num_ports = 2, .open = edge_open, @@ -139,7 +137,6 @@ static struct usb_serial_driver edgeport_4port_device = { .name = "edgeport_4", }, .description = "Edgeport 4 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_4port_id_table, .num_ports = 4, .open = edge_open, @@ -169,7 +166,6 @@ static struct usb_serial_driver edgeport_8port_device = { .name = "edgeport_8", }, .description = "Edgeport 8 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_8port_id_table, .num_ports = 8, .open = edge_open, @@ -199,7 +195,6 @@ static struct usb_serial_driver epic_device = { .name = "epic", }, .description = "EPiC device", - .usb_driver = &io_driver, .id_table = Epic_port_id_table, .num_ports = 1, .open = edge_open, @@ -223,5 +218,10 @@ static struct usb_serial_driver epic_device = { .write_bulk_callback = edge_bulk_out_data_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &edgeport_2port_device, &edgeport_4port_device, + &edgeport_8port_device, &epic_device, NULL +}; + #endif diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 65bf06a..40a95a7 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -202,7 +202,6 @@ static struct usb_driver io_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; @@ -1817,7 +1816,7 @@ static void edge_bulk_out_callback(struct urb *urb) __func__, status); return; default: - dev_err(&urb->dev->dev, "%s - nonzero write bulk status " + dev_err_console(port, "%s - nonzero write bulk status " "received: %d\n", __func__, status); } @@ -2111,7 +2110,7 @@ static void edge_send(struct tty_struct *tty) /* send the data out the bulk port */ result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, + dev_err_console(port, "%s - failed submitting write urb, error %d\n", __func__, result); edge_port->ep_write_urb_in_use = 0; @@ -2657,15 +2656,7 @@ cleanup: static void edge_disconnect(struct usb_serial *serial) { - int i; - struct edgeport_port *edge_port; - dbg("%s", __func__); - - for (i = 0; i < serial->num_ports; ++i) { - edge_port = usb_get_serial_port_data(serial->port[i]); - edge_remove_sysfs_attrs(edge_port->port); - } } static void edge_release(struct usb_serial *serial) @@ -2733,7 +2724,6 @@ static struct usb_serial_driver edgeport_1port_device = { .name = "edgeport_ti_1", }, .description = "Edgeport TI 1 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_1port_id_table, .num_ports = 1, .open = edge_open, @@ -2744,6 +2734,7 @@ static struct usb_serial_driver edgeport_1port_device = { .disconnect = edge_disconnect, .release = edge_release, .port_probe = edge_create_sysfs_attrs, + .port_remove = edge_remove_sysfs_attrs, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -2764,7 +2755,6 @@ static struct usb_serial_driver edgeport_2port_device = { .name = "edgeport_ti_2", }, .description = "Edgeport TI 2 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_2port_id_table, .num_ports = 2, .open = edge_open, @@ -2775,6 +2765,7 @@ static struct usb_serial_driver edgeport_2port_device = { .disconnect = edge_disconnect, .release = edge_release, .port_probe = edge_create_sysfs_attrs, + .port_remove = edge_remove_sysfs_attrs, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -2788,41 +2779,12 @@ static struct usb_serial_driver edgeport_2port_device = { .write_bulk_callback = edge_bulk_out_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &edgeport_1port_device, &edgeport_2port_device, NULL +}; -static int __init edgeport_init(void) -{ - int retval; - retval = usb_serial_register(&edgeport_1port_device); - if (retval) - goto failed_1port_device_register; - retval = usb_serial_register(&edgeport_2port_device); - if (retval) - goto failed_2port_device_register; - retval = usb_register(&io_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&edgeport_2port_device); -failed_2port_device_register: - usb_serial_deregister(&edgeport_1port_device); -failed_1port_device_register: - return retval; -} - -static void __exit edgeport_exit(void) -{ - usb_deregister(&io_driver); - usb_serial_deregister(&edgeport_1port_device); - usb_serial_deregister(&edgeport_2port_device); -} - -module_init(edgeport_init); -module_exit(edgeport_exit); +module_usb_serial_driver(io_driver, serial_drivers); -/* Module information */ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 06053a9..10c02b8 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -510,7 +510,6 @@ static struct usb_driver ipaq_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = ipaq_id_table, - .no_dynamic_id = 1, }; @@ -521,7 +520,6 @@ static struct usb_serial_driver ipaq_device = { .name = "ipaq", }, .description = "PocketPC PDA", - .usb_driver = &ipaq_driver, .id_table = ipaq_id_table, .bulk_in_size = 256, .bulk_out_size = 256, @@ -530,6 +528,10 @@ static struct usb_serial_driver ipaq_device = { .calc_num_ports = ipaq_calc_num_ports, }; +static struct usb_serial_driver * const serial_drivers[] = { + &ipaq_device, NULL +}; + static int ipaq_open(struct tty_struct *tty, struct usb_serial_port *port) { @@ -624,30 +626,22 @@ static int ipaq_startup(struct usb_serial *serial) static int __init ipaq_init(void) { int retval; - retval = usb_serial_register(&ipaq_device); - if (retval) - goto failed_usb_serial_register; + if (vendor) { ipaq_id_table[0].idVendor = vendor; ipaq_id_table[0].idProduct = product; } - retval = usb_register(&ipaq_driver); - if (retval) - goto failed_usb_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&ipaq_device); -failed_usb_serial_register: + + retval = usb_serial_register_drivers(&ipaq_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit ipaq_exit(void) { - usb_deregister(&ipaq_driver); - usb_serial_deregister(&ipaq_device); + usb_serial_deregister_drivers(&ipaq_driver, serial_drivers); } diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 6f9356f..76a0640 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -144,7 +144,6 @@ static struct usb_driver usb_ipw_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = usb_ipw_ids, - .no_dynamic_id = 1, }; static bool debug; @@ -318,7 +317,6 @@ static struct usb_serial_driver ipw_device = { .name = "ipw", }, .description = "IPWireless converter", - .usb_driver = &usb_ipw_driver, .id_table = usb_ipw_ids, .num_ports = 1, .disconnect = usb_wwan_disconnect, @@ -331,33 +329,11 @@ static struct usb_serial_driver ipw_device = { .write = usb_wwan_write, }; +static struct usb_serial_driver * const serial_drivers[] = { + &ipw_device, NULL +}; - -static int __init usb_ipw_init(void) -{ - int retval; - - retval = usb_serial_register(&ipw_device); - if (retval) - return retval; - retval = usb_register(&usb_ipw_driver); - if (retval) { - usb_serial_deregister(&ipw_device); - return retval; - } - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -} - -static void __exit usb_ipw_exit(void) -{ - usb_deregister(&usb_ipw_driver); - usb_serial_deregister(&ipw_device); -} - -module_init(usb_ipw_init); -module_exit(usb_ipw_exit); +module_usb_serial_driver(usb_ipw_driver, serial_drivers); /* Module information */ MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 84a396e..84965cd 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -82,7 +82,6 @@ static struct usb_driver ir_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = ir_id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver ir_device = { @@ -91,7 +90,6 @@ static struct usb_serial_driver ir_device = { .name = "ir-usb", }, .description = "IR Dongle", - .usb_driver = &ir_driver, .id_table = ir_id_table, .num_ports = 1, .set_termios = ir_set_termios, @@ -101,6 +99,10 @@ static struct usb_serial_driver ir_device = { .process_read_urb = ir_process_read_urb, }; +static struct usb_serial_driver * const serial_drivers[] = { + &ir_device, NULL +}; + static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc) { dbg("bLength=%x", desc->bLength); @@ -445,30 +447,16 @@ static int __init ir_init(void) ir_device.bulk_out_size = buffer_size; } - retval = usb_serial_register(&ir_device); - if (retval) - goto failed_usb_serial_register; - - retval = usb_register(&ir_driver); - if (retval) - goto failed_usb_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; - -failed_usb_register: - usb_serial_deregister(&ir_device); - -failed_usb_serial_register: + retval = usb_serial_register_drivers(&ir_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit ir_exit(void) { - usb_deregister(&ir_driver); - usb_serial_deregister(&ir_device); + usb_serial_deregister_drivers(&ir_driver, serial_drivers); } diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 3077a44..f2192d5 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -56,7 +56,6 @@ static struct usb_driver iuu_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; /* turbo parameter */ @@ -1274,7 +1273,6 @@ static struct usb_serial_driver iuu_device = { .name = "iuu_phoenix", }, .id_table = id_table, - .usb_driver = &iuu_driver, .num_ports = 1, .bulk_in_size = 512, .bulk_out_size = 512, @@ -1292,32 +1290,11 @@ static struct usb_serial_driver iuu_device = { .release = iuu_release, }; -static int __init iuu_init(void) -{ - int retval; - retval = usb_serial_register(&iuu_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&iuu_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&iuu_device); -failed_usb_serial_register: - return retval; -} - -static void __exit iuu_exit(void) -{ - usb_deregister(&iuu_driver); - usb_serial_deregister(&iuu_device); -} +static struct usb_serial_driver * const serial_drivers[] = { + &iuu_device, NULL +}; -module_init(iuu_init); -module_exit(iuu_exit); +module_usb_serial_driver(iuu_driver, serial_drivers); MODULE_AUTHOR("Alain Degreffe eczema@ecze.com"); diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 4cc36c7..a39ddd1 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -130,53 +130,7 @@ struct keyspan_port_private { #include "keyspan_usa67msg.h" -/* Functions used by new usb-serial code. */ -static int __init keyspan_init(void) -{ - int retval; - retval = usb_serial_register(&keyspan_pre_device); - if (retval) - goto failed_pre_device_register; - retval = usb_serial_register(&keyspan_1port_device); - if (retval) - goto failed_1port_device_register; - retval = usb_serial_register(&keyspan_2port_device); - if (retval) - goto failed_2port_device_register; - retval = usb_serial_register(&keyspan_4port_device); - if (retval) - goto failed_4port_device_register; - retval = usb_register(&keyspan_driver); - if (retval) - goto failed_usb_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; -failed_usb_register: - usb_serial_deregister(&keyspan_4port_device); -failed_4port_device_register: - usb_serial_deregister(&keyspan_2port_device); -failed_2port_device_register: - usb_serial_deregister(&keyspan_1port_device); -failed_1port_device_register: - usb_serial_deregister(&keyspan_pre_device); -failed_pre_device_register: - return retval; -} - -static void __exit keyspan_exit(void) -{ - usb_deregister(&keyspan_driver); - usb_serial_deregister(&keyspan_pre_device); - usb_serial_deregister(&keyspan_1port_device); - usb_serial_deregister(&keyspan_2port_device); - usb_serial_deregister(&keyspan_4port_device); -} - -module_init(keyspan_init); -module_exit(keyspan_exit); +module_usb_serial_driver(keyspan_driver, serial_drivers); static void keyspan_break_ctl(struct tty_struct *tty, int break_state) { diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 13fa1d1..622853c 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -492,7 +492,6 @@ static struct usb_driver keyspan_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = keyspan_ids_combined, - .no_dynamic_id = 1, }; /* usb_device_id table for the pre-firmware download keyspan devices */ @@ -545,7 +544,6 @@ static struct usb_serial_driver keyspan_pre_device = { .name = "keyspan_no_firm", }, .description = "Keyspan - (without firmware)", - .usb_driver = &keyspan_driver, .id_table = keyspan_pre_ids, .num_ports = 1, .attach = keyspan_fake_startup, @@ -557,7 +555,6 @@ static struct usb_serial_driver keyspan_1port_device = { .name = "keyspan_1", }, .description = "Keyspan 1 port adapter", - .usb_driver = &keyspan_driver, .id_table = keyspan_1port_ids, .num_ports = 1, .open = keyspan_open, @@ -580,7 +577,6 @@ static struct usb_serial_driver keyspan_2port_device = { .name = "keyspan_2", }, .description = "Keyspan 2 port adapter", - .usb_driver = &keyspan_driver, .id_table = keyspan_2port_ids, .num_ports = 2, .open = keyspan_open, @@ -603,7 +599,6 @@ static struct usb_serial_driver keyspan_4port_device = { .name = "keyspan_4", }, .description = "Keyspan 4 port adapter", - .usb_driver = &keyspan_driver, .id_table = keyspan_4port_ids, .num_ports = 4, .open = keyspan_open, @@ -620,4 +615,9 @@ static struct usb_serial_driver keyspan_4port_device = { .release = keyspan_release, }; +static struct usb_serial_driver * const serial_drivers[] = { + &keyspan_pre_device, &keyspan_1port_device, + &keyspan_2port_device, &keyspan_4port_device, NULL +}; + #endif diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 7c62a70..693bcdf 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -91,7 +91,6 @@ static struct usb_driver keyspan_pda_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; static const struct usb_device_id id_table_std[] = { @@ -779,7 +778,6 @@ static struct usb_serial_driver keyspan_pda_fake_device = { .name = "keyspan_pda_pre", }, .description = "Keyspan PDA - (prerenumeration)", - .usb_driver = &keyspan_pda_driver, .id_table = id_table_fake, .num_ports = 1, .attach = keyspan_pda_fake_startup, @@ -793,7 +791,6 @@ static struct usb_serial_driver xircom_pgs_fake_device = { .name = "xircom_no_firm", }, .description = "Xircom / Entregra PGS - (prerenumeration)", - .usb_driver = &keyspan_pda_driver, .id_table = id_table_fake_xircom, .num_ports = 1, .attach = keyspan_pda_fake_startup, @@ -806,7 +803,6 @@ static struct usb_serial_driver keyspan_pda_device = { .name = "keyspan_pda", }, .description = "Keyspan PDA", - .usb_driver = &keyspan_pda_driver, .id_table = id_table_std, .num_ports = 1, .dtr_rts = keyspan_pda_dtr_rts, @@ -827,61 +823,18 @@ static struct usb_serial_driver keyspan_pda_device = { .release = keyspan_pda_release, }; - -static int __init keyspan_pda_init(void) -{ - int retval; - retval = usb_serial_register(&keyspan_pda_device); - if (retval) - goto failed_pda_register; +static struct usb_serial_driver * const serial_drivers[] = { + &keyspan_pda_device, #ifdef KEYSPAN - retval = usb_serial_register(&keyspan_pda_fake_device); - if (retval) - goto failed_pda_fake_register; + &keyspan_pda_fake_device, #endif #ifdef XIRCOM - retval = usb_serial_register(&xircom_pgs_fake_device); - if (retval) - goto failed_xircom_register; -#endif - retval = usb_register(&keyspan_pda_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: -#ifdef XIRCOM - usb_serial_deregister(&xircom_pgs_fake_device); -failed_xircom_register: -#endif /* XIRCOM */ -#ifdef KEYSPAN - usb_serial_deregister(&keyspan_pda_fake_device); -#endif -#ifdef KEYSPAN -failed_pda_fake_register: + &xircom_pgs_fake_device, #endif - usb_serial_deregister(&keyspan_pda_device); -failed_pda_register: - return retval; -} - - -static void __exit keyspan_pda_exit(void) -{ - usb_deregister(&keyspan_pda_driver); - usb_serial_deregister(&keyspan_pda_device); -#ifdef KEYSPAN - usb_serial_deregister(&keyspan_pda_fake_device); -#endif -#ifdef XIRCOM - usb_serial_deregister(&xircom_pgs_fake_device); -#endif -} - + NULL +}; -module_init(keyspan_pda_init); -module_exit(keyspan_pda_exit); +module_usb_serial_driver(keyspan_pda_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); @@ -889,4 +842,3 @@ MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); - diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index fc064e1..10f0540 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -91,7 +91,6 @@ static struct usb_driver kl5kusb105d_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver kl5kusb105d_device = { @@ -100,7 +99,6 @@ static struct usb_serial_driver kl5kusb105d_device = { .name = "kl5kusb105d", }, .description = "KL5KUSB105D / PalmConnect", - .usb_driver = &kl5kusb105d_driver, .id_table = id_table, .num_ports = 1, .bulk_out_size = 64, @@ -118,6 +116,10 @@ static struct usb_serial_driver kl5kusb105d_device = { .prepare_write_buffer = klsi_105_prepare_write_buffer, }; +static struct usb_serial_driver * const serial_drivers[] = { + &kl5kusb105d_device, NULL +}; + struct klsi_105_port_settings { __u8 pktlen; /* always 5, it seems */ __u8 baudrate; @@ -690,40 +692,11 @@ static int klsi_105_tiocmset(struct tty_struct *tty, return retval; } - -static int __init klsi_105_init(void) -{ - int retval; - retval = usb_serial_register(&kl5kusb105d_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&kl5kusb105d_driver); - if (retval) - goto failed_usb_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&kl5kusb105d_device); -failed_usb_serial_register: - return retval; -} - -static void __exit klsi_105_exit(void) -{ - usb_deregister(&kl5kusb105d_driver); - usb_serial_deregister(&kl5kusb105d_device); -} - - -module_init(klsi_105_init); -module_exit(klsi_105_exit); +module_usb_serial_driver(kl5kusb105d_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "enable extensive debugging messages"); diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 5d3beee..4a9a75e 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -38,7 +38,7 @@ #include <linux/ioctl.h> #include "kobil_sct.h" -static int debug; +static bool debug; /* Version Information */ #define DRIVER_VERSION "21/05/2004" @@ -90,7 +90,6 @@ static struct usb_driver kobil_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; @@ -100,7 +99,6 @@ static struct usb_serial_driver kobil_device = { .name = "kobil", }, .description = "KOBIL USB smart card terminal", - .usb_driver = &kobil_driver, .id_table = id_table, .num_ports = 1, .attach = kobil_startup, @@ -117,6 +115,9 @@ static struct usb_serial_driver kobil_device = { .read_int_callback = kobil_read_int_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &kobil_device, NULL +}; struct kobil_private { int write_int_endpoint_address; @@ -682,35 +683,7 @@ static int kobil_ioctl(struct tty_struct *tty, } } -static int __init kobil_init(void) -{ - int retval; - retval = usb_serial_register(&kobil_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&kobil_driver); - if (retval) - goto failed_usb_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; -failed_usb_register: - usb_serial_deregister(&kobil_device); -failed_usb_serial_register: - return retval; -} - - -static void __exit kobil_exit(void) -{ - usb_deregister(&kobil_driver); - usb_serial_deregister(&kobil_device); -} - -module_init(kobil_init); -module_exit(kobil_exit); +module_usb_serial_driver(kobil_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 27fa9c8..6edd261 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -88,7 +88,6 @@ static struct usb_driver mct_u232_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; static struct usb_serial_driver mct_u232_device = { @@ -97,7 +96,6 @@ static struct usb_serial_driver mct_u232_device = { .name = "mct_u232", }, .description = "MCT U232", - .usb_driver = &mct_u232_driver, .id_table = id_table_combined, .num_ports = 1, .open = mct_u232_open, @@ -116,6 +114,10 @@ static struct usb_serial_driver mct_u232_device = { .get_icount = mct_u232_get_icount, }; +static struct usb_serial_driver * const serial_drivers[] = { + &mct_u232_device, NULL +}; + struct mct_u232_private { spinlock_t lock; unsigned int control_state; /* Modem Line Setting (TIOCM) */ @@ -904,33 +906,7 @@ static int mct_u232_get_icount(struct tty_struct *tty, return 0; } -static int __init mct_u232_init(void) -{ - int retval; - retval = usb_serial_register(&mct_u232_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&mct_u232_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&mct_u232_device); -failed_usb_serial_register: - return retval; -} - - -static void __exit mct_u232_exit(void) -{ - usb_deregister(&mct_u232_driver); - usb_serial_deregister(&mct_u232_device); -} - -module_init(mct_u232_init); -module_exit(mct_u232_exit); +module_usb_serial_driver(mct_u232_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 4554ee4..bdce820 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1294,7 +1294,7 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port, urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); if (urb->transfer_buffer == NULL) { - dev_err(&port->dev, "%s no more kernel memory...\n", + dev_err_console(port, "%s no more kernel memory...\n", __func__); goto exit; } @@ -1315,7 +1315,7 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port, /* send it down the pipe */ status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { - dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " + dev_err_console(port, "%s - usb_submit_urb(write bulk) failed " "with status = %d\n", __func__, status); bytes_sent = status; goto exit; @@ -2169,7 +2169,6 @@ static struct usb_driver usb_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = moschip_port_id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver moschip7720_2port_driver = { @@ -2178,7 +2177,6 @@ static struct usb_serial_driver moschip7720_2port_driver = { .name = "moschip7720", }, .description = "Moschip 2 port adapter", - .usb_driver = &usb_driver, .id_table = moschip_port_id_table, .calc_num_ports = mos77xx_calc_num_ports, .open = mos7720_open, @@ -2201,44 +2199,12 @@ static struct usb_serial_driver moschip7720_2port_driver = { .read_int_callback = NULL /* dynamically assigned in probe() */ }; -static int __init moschip7720_init(void) -{ - int retval; - - dbg("%s: Entering ..........", __func__); - - /* Register with the usb serial */ - retval = usb_serial_register(&moschip7720_2port_driver); - if (retval) - goto failed_port_device_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - /* Register with the usb */ - retval = usb_register(&usb_driver); - if (retval) - goto failed_usb_register; - - return 0; - -failed_usb_register: - usb_serial_deregister(&moschip7720_2port_driver); - -failed_port_device_register: - return retval; -} - -static void __exit moschip7720_exit(void) -{ - usb_deregister(&usb_driver); - usb_serial_deregister(&moschip7720_2port_driver); -} +static struct usb_serial_driver * const serial_drivers[] = { + &moschip7720_2port_driver, NULL +}; -module_init(moschip7720_init); -module_exit(moschip7720_exit); +module_usb_serial_driver(usb_driver, serial_drivers); -/* Module information */ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 03b5e249..f7e6e30 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1509,7 +1509,7 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); if (urb->transfer_buffer == NULL) { - dev_err(&port->dev, "%s no more kernel memory...\n", + dev_err_console(port, "%s no more kernel memory...\n", __func__); goto exit; } @@ -1535,7 +1535,7 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, if (status) { mos7840_port->busy[i] = 0; - dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " + dev_err_console(port, "%s - usb_submit_urb(write bulk) failed " "with status = %d\n", __func__, status); bytes_sent = status; goto exit; @@ -2638,7 +2638,6 @@ static struct usb_driver io_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = moschip_id_table_combined, - .no_dynamic_id = 1, }; static struct usb_serial_driver moschip7840_4port_device = { @@ -2647,7 +2646,6 @@ static struct usb_serial_driver moschip7840_4port_device = { .name = "mos7840", }, .description = DRIVER_DESC, - .usb_driver = &io_driver, .id_table = moschip_port_id_table, .num_ports = 4, .open = mos7840_open, @@ -2674,57 +2672,12 @@ static struct usb_serial_driver moschip7840_4port_device = { .read_int_callback = mos7840_interrupt_callback, }; -/**************************************************************************** - * moschip7840_init - * This is called by the module subsystem, or on startup to initialize us - ****************************************************************************/ -static int __init moschip7840_init(void) -{ - int retval; - - dbg("%s", " mos7840_init :entering.........."); - - /* Register with the usb serial */ - retval = usb_serial_register(&moschip7840_4port_device); - - if (retval) - goto failed_port_device_register; - - dbg("%s", "Entering..."); - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - /* Register with the usb */ - retval = usb_register(&io_driver); - if (retval == 0) { - dbg("%s", "Leaving..."); - return 0; - } - usb_serial_deregister(&moschip7840_4port_device); -failed_port_device_register: - return retval; -} - -/**************************************************************************** - * moschip7840_exit - * Called when the driver is about to be unloaded. - ****************************************************************************/ -static void __exit moschip7840_exit(void) -{ - - dbg("%s", " mos7840_exit :entering.........."); - - usb_deregister(&io_driver); - - usb_serial_deregister(&moschip7840_4port_device); - - dbg("%s", "Entering..."); -} +static struct usb_serial_driver * const serial_drivers[] = { + &moschip7840_4port_device, NULL +}; -module_init(moschip7840_init); -module_exit(moschip7840_exit); +module_usb_serial_driver(io_driver, serial_drivers); -/* Module information */ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c index e2bfecc..3ab6214 100644 --- a/drivers/usb/serial/moto_modem.c +++ b/drivers/usb/serial/moto_modem.c @@ -36,7 +36,6 @@ static struct usb_driver moto_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver moto_device = { @@ -45,29 +44,12 @@ static struct usb_serial_driver moto_device = { .name = "moto-modem", }, .id_table = id_table, - .usb_driver = &moto_driver, .num_ports = 1, }; -static int __init moto_init(void) -{ - int retval; - - retval = usb_serial_register(&moto_device); - if (retval) - return retval; - retval = usb_register(&moto_driver); - if (retval) - usb_serial_deregister(&moto_device); - return retval; -} - -static void __exit moto_exit(void) -{ - usb_deregister(&moto_driver); - usb_serial_deregister(&moto_device); -} +static struct usb_serial_driver * const serial_drivers[] = { + &moto_device, NULL +}; -module_init(moto_init); -module_exit(moto_exit); +module_usb_serial_driver(moto_driver, serial_drivers); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index b28f1db..29ab6eb 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c @@ -35,7 +35,6 @@ static struct usb_driver navman_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static void navman_read_int_callback(struct urb *urb) @@ -122,7 +121,6 @@ static struct usb_serial_driver navman_device = { .name = "navman", }, .id_table = id_table, - .usb_driver = &navman_driver, .num_ports = 1, .open = navman_open, .close = navman_close, @@ -130,27 +128,12 @@ static struct usb_serial_driver navman_device = { .read_int_callback = navman_read_int_callback, }; -static int __init navman_init(void) -{ - int retval; - - retval = usb_serial_register(&navman_device); - if (retval) - return retval; - retval = usb_register(&navman_driver); - if (retval) - usb_serial_deregister(&navman_device); - return retval; -} +static struct usb_serial_driver * const serial_drivers[] = { + &navman_device, NULL +}; -static void __exit navman_exit(void) -{ - usb_deregister(&navman_driver); - usb_serial_deregister(&navman_device); -} +module_usb_serial_driver(navman_driver, serial_drivers); -module_init(navman_init); -module_exit(navman_exit); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 8b8d58a..88dc785 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -62,7 +62,6 @@ static struct usb_driver omninet_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; @@ -72,7 +71,6 @@ static struct usb_serial_driver zyxel_omninet_device = { .name = "omninet", }, .description = "ZyXEL - omni.net lcd plus usb", - .usb_driver = &omninet_driver, .id_table = id_table, .num_ports = 1, .attach = omninet_attach, @@ -86,6 +84,10 @@ static struct usb_serial_driver zyxel_omninet_device = { .release = omninet_release, }; +static struct usb_serial_driver * const serial_drivers[] = { + &zyxel_omninet_device, NULL +}; + /* The protocol. * @@ -254,7 +256,7 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, result = usb_submit_urb(wport->write_urb, GFP_ATOMIC); if (result) { set_bit(0, &wport->write_urbs_free); - dev_err(&port->dev, + dev_err_console(port, "%s - failed submitting write urb, error %d\n", __func__, result); } else @@ -319,35 +321,7 @@ static void omninet_release(struct usb_serial *serial) kfree(usb_get_serial_port_data(port)); } - -static int __init omninet_init(void) -{ - int retval; - retval = usb_serial_register(&zyxel_omninet_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&omninet_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&zyxel_omninet_device); -failed_usb_serial_register: - return retval; -} - - -static void __exit omninet_exit(void) -{ - usb_deregister(&omninet_driver); - usb_serial_deregister(&zyxel_omninet_device); -} - - -module_init(omninet_init); -module_exit(omninet_exit); +module_usb_serial_driver(omninet_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 262ded9..82cc9d2 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -604,7 +604,6 @@ static struct usb_driver opticon_driver = { .suspend = opticon_suspend, .resume = opticon_resume, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver opticon_device = { @@ -613,7 +612,6 @@ static struct usb_serial_driver opticon_device = { .name = "opticon", }, .id_table = id_table, - .usb_driver = &opticon_driver, .num_ports = 1, .attach = opticon_startup, .open = opticon_open, @@ -629,27 +627,12 @@ static struct usb_serial_driver opticon_device = { .tiocmset = opticon_tiocmset, }; -static int __init opticon_init(void) -{ - int retval; - - retval = usb_serial_register(&opticon_device); - if (retval) - return retval; - retval = usb_register(&opticon_driver); - if (retval) - usb_serial_deregister(&opticon_device); - return retval; -} +static struct usb_serial_driver * const serial_drivers[] = { + &opticon_device, NULL +}; -static void __exit opticon_exit(void) -{ - usb_deregister(&opticon_driver); - usb_serial_deregister(&opticon_device); -} +module_usb_serial_driver(opticon_driver, serial_drivers); -module_init(opticon_init); -module_exit(opticon_exit); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 420d985..005511b 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -480,6 +480,13 @@ static void option_instat_callback(struct urb *urb); #define ZD_VENDOR_ID 0x0685 #define ZD_PRODUCT_7000 0x7000 +/* LG products */ +#define LG_VENDOR_ID 0x1004 +#define LG_PRODUCT_L02C 0x618f + +/* MediaTek products */ +#define MEDIATEK_VENDOR_ID 0x0e8d + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -784,7 +791,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff), @@ -799,7 +805,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, - /* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) }, */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) }, @@ -824,7 +829,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - /* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0053, 0xff, 0xff, 0xff) }, */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, @@ -832,7 +836,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff), @@ -842,7 +845,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0067, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0077, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) }, @@ -851,6 +853,16 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0083, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0087, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0088, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0089, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0090, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0091, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0092, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0093, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0095, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0096, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0097, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0105, 0xff, 0xff, 0xff) }, @@ -871,23 +883,18 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0145, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0146, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0148, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0149, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0150, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0151, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0154, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0160, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0164, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, @@ -1062,17 +1069,27 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, + 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, - 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, @@ -1183,6 +1200,11 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) }, { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) }, + { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */ + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) }, /* MediaTek MT6276M modem & app port */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); @@ -1197,7 +1219,6 @@ static struct usb_driver option_driver = { .supports_autosuspend = 1, #endif .id_table = option_ids, - .no_dynamic_id = 1, }; /* The card has three separate interfaces, which the serial driver @@ -1210,7 +1231,6 @@ static struct usb_serial_driver option_1port_device = { .name = "option1", }, .description = "GSM modem (1-port)", - .usb_driver = &option_driver, .id_table = option_ids, .num_ports = 1, .probe = option_probe, @@ -1234,6 +1254,10 @@ static struct usb_serial_driver option_1port_device = { #endif }; +static struct usb_serial_driver * const serial_drivers[] = { + &option_1port_device, NULL +}; + static bool debug; /* per port private data */ @@ -1265,36 +1289,7 @@ struct option_port_private { unsigned long tx_start_time[N_OUT_URB]; }; -/* Functions used by new usb-serial code. */ -static int __init option_init(void) -{ - int retval; - retval = usb_serial_register(&option_1port_device); - if (retval) - goto failed_1port_device_register; - retval = usb_register(&option_driver); - if (retval) - goto failed_driver_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; - -failed_driver_register: - usb_serial_deregister(&option_1port_device); -failed_1port_device_register: - return retval; -} - -static void __exit option_exit(void) -{ - usb_deregister(&option_driver); - usb_serial_deregister(&option_1port_device); -} - -module_init(option_init); -module_exit(option_exit); +module_usb_serial_driver(option_driver, serial_drivers); static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason, const struct option_blacklist_info *blacklist) diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index e287fd3..5fdc33c 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -71,7 +71,6 @@ static struct usb_driver oti6858_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static bool debug; @@ -157,7 +156,6 @@ static struct usb_serial_driver oti6858_device = { .name = "oti6858", }, .id_table = id_table, - .usb_driver = &oti6858_driver, .num_ports = 1, .open = oti6858_open, .close = oti6858_close, @@ -176,6 +174,10 @@ static struct usb_serial_driver oti6858_device = { .release = oti6858_release, }; +static struct usb_serial_driver * const serial_drivers[] = { + &oti6858_device, NULL +}; + struct oti6858_private { spinlock_t lock; @@ -302,7 +304,7 @@ static void send_data(struct work_struct *work) if (count != 0) { allow = kmalloc(1, GFP_KERNEL); if (!allow) { - dev_err(&port->dev, "%s(): kmalloc failed\n", + dev_err_console(port, "%s(): kmalloc failed\n", __func__); return; } @@ -334,7 +336,7 @@ static void send_data(struct work_struct *work) port->write_urb->transfer_buffer_length = count; result = usb_submit_urb(port->write_urb, GFP_NOIO); if (result != 0) { - dev_err(&port->dev, "%s(): usb_submit_urb() failed" + dev_err_console(port, "%s(): usb_submit_urb() failed" " with error %d\n", __func__, result); priv->flags.write_urb_in_use = 0; } @@ -938,7 +940,7 @@ static void oti6858_write_bulk_callback(struct urb *urb) port->write_urb->transfer_buffer_length = 1; result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, "%s(): usb_submit_urb() failed," + dev_err_console(port, "%s(): usb_submit_urb() failed," " error %d\n", __func__, result); } else { return; @@ -956,29 +958,7 @@ static void oti6858_write_bulk_callback(struct urb *urb) } } -/* module description and (de)initialization */ - -static int __init oti6858_init(void) -{ - int retval; - - retval = usb_serial_register(&oti6858_device); - if (retval == 0) { - retval = usb_register(&oti6858_driver); - if (retval) - usb_serial_deregister(&oti6858_device); - } - return retval; -} - -static void __exit oti6858_exit(void) -{ - usb_deregister(&oti6858_driver); - usb_serial_deregister(&oti6858_device); -} - -module_init(oti6858_init); -module_exit(oti6858_exit); +module_usb_serial_driver(oti6858_driver, serial_drivers); MODULE_DESCRIPTION(OTI6858_DESCRIPTION); MODULE_AUTHOR(OTI6858_AUTHOR); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 3d8cda5..ff4a174 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -104,7 +104,6 @@ static struct usb_driver pl2303_driver = { .id_table = id_table, .suspend = usb_serial_suspend, .resume = usb_serial_resume, - .no_dynamic_id = 1, .supports_autosuspend = 1, }; @@ -834,7 +833,6 @@ static struct usb_serial_driver pl2303_device = { .name = "pl2303", }, .id_table = id_table, - .usb_driver = &pl2303_driver, .num_ports = 1, .bulk_in_size = 256, .bulk_out_size = 256, @@ -853,32 +851,11 @@ static struct usb_serial_driver pl2303_device = { .release = pl2303_release, }; -static int __init pl2303_init(void) -{ - int retval; - - retval = usb_serial_register(&pl2303_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&pl2303_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&pl2303_device); -failed_usb_serial_register: - return retval; -} - -static void __exit pl2303_exit(void) -{ - usb_deregister(&pl2303_driver); - usb_serial_deregister(&pl2303_device); -} +static struct usb_serial_driver * const serial_drivers[] = { + &pl2303_device, NULL +}; -module_init(pl2303_init); -module_exit(pl2303_exit); +module_usb_serial_driver(pl2303_driver, serial_drivers); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index 30b73e6..9662456 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -36,6 +36,7 @@ #define UTSTARCOM_PRODUCT_UM175_V1 0x3712 #define UTSTARCOM_PRODUCT_UM175_V2 0x3714 #define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715 +#define PANTECH_PRODUCT_UML190_VZW 0x3716 #define PANTECH_PRODUCT_UML290_VZW 0x3718 /* CMOTECH devices */ @@ -67,7 +68,11 @@ static struct usb_device_id id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xfe, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfd, 0xff) }, /* NMEA */ + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfe, 0xff) }, /* WMC */ + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, /* DIAG */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); @@ -77,7 +82,6 @@ static struct usb_driver qcaux_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver qcaux_device = { @@ -86,29 +90,12 @@ static struct usb_serial_driver qcaux_device = { .name = "qcaux", }, .id_table = id_table, - .usb_driver = &qcaux_driver, .num_ports = 1, }; -static int __init qcaux_init(void) -{ - int retval; - - retval = usb_serial_register(&qcaux_device); - if (retval) - return retval; - retval = usb_register(&qcaux_driver); - if (retval) - usb_serial_deregister(&qcaux_device); - return retval; -} - -static void __exit qcaux_exit(void) -{ - usb_deregister(&qcaux_driver); - usb_serial_deregister(&qcaux_device); -} +static struct usb_serial_driver * const serial_drivers[] = { + &qcaux_device, NULL +}; -module_init(qcaux_init); -module_exit(qcaux_exit); +module_usb_serial_driver(qcaux_driver, serial_drivers); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 1d5deee..0206b10 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -24,34 +24,44 @@ static bool debug; +#define DEVICE_G1K(v, p) \ + USB_DEVICE(v, p), .driver_info = 1 + static const struct usb_device_id id_table[] = { - {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ - {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ - {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */ - {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ - {USB_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ - {USB_DEVICE(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */ - {USB_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ - {USB_DEVICE(0x413c, 0x8171)}, /* Dell Gobi QDL device */ - {USB_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ - {USB_DEVICE(0x1410, 0xa008)}, /* Novatel Gobi QDL device */ - {USB_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ - {USB_DEVICE(0x0b05, 0x1774)}, /* Asus Gobi QDL device */ - {USB_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ - {USB_DEVICE(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */ - {USB_DEVICE(0x1557, 0x0a80)}, /* OQO Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9008)}, /* Generic Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9201)}, /* Generic Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ - {USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ + /* Gobi 1000 devices */ + {DEVICE_G1K(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ + {DEVICE_G1K(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ + {DEVICE_G1K(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */ + {DEVICE_G1K(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ + {DEVICE_G1K(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */ + {DEVICE_G1K(0x413c, 0x8172)}, /* Dell Gobi Modem device */ + {DEVICE_G1K(0x413c, 0x8171)}, /* Dell Gobi QDL device */ + {DEVICE_G1K(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ + {DEVICE_G1K(0x1410, 0xa008)}, /* Novatel Gobi QDL device */ + {DEVICE_G1K(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ + {DEVICE_G1K(0x0b05, 0x1774)}, /* Asus Gobi QDL device */ + {DEVICE_G1K(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ + {DEVICE_G1K(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */ + {DEVICE_G1K(0x1557, 0x0a80)}, /* OQO Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9008)}, /* Generic Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9201)}, /* Generic Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ + {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ + + /* Gobi 2000 devices */ + {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */ + {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi 2000 QDL device */ + {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi 2000 QDL device */ + {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi 2000 QDL device */ + {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi 2000 QDL device */ {USB_DEVICE(0x413c, 0x8185)}, /* Dell Gobi 2000 QDL device (N0218, VU936) */ {USB_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */ {USB_DEVICE(0x05c6, 0x9208)}, /* Generic Gobi 2000 QDL device */ @@ -86,7 +96,18 @@ static const struct usb_device_id id_table[] = { {USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ {USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */ {USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ + + /* Gobi 3000 devices */ + {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Gobi 3000 QDL */ + {USB_DEVICE(0x05c6, 0x920c)}, /* Gobi 3000 QDL */ + {USB_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */ + {USB_DEVICE(0x1410, 0xa020)}, /* Novatel Gobi 3000 QDL */ + {USB_DEVICE(0x1410, 0xa021)}, /* Novatel Gobi 3000 Composite */ + {USB_DEVICE(0x413c, 0x8193)}, /* Dell Gobi 3000 QDL */ + {USB_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */ {USB_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ + {USB_DEVICE(0x12D1, 0x14F0)}, /* Sony Gobi 3000 QDL */ + {USB_DEVICE(0x12D1, 0x14F1)}, /* Sony Gobi 3000 Composite */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, id_table); @@ -108,8 +129,10 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) int retval = -ENODEV; __u8 nintf; __u8 ifnum; + bool is_gobi1k = id->driver_info ? true : false; dbg("%s", __func__); + dbg("Is Gobi 1000 = %d", is_gobi1k); nintf = serial->dev->actconfig->desc.bNumInterfaces; dbg("Num Interfaces = %d", nintf); @@ -123,8 +146,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) spin_lock_init(&data->susp_lock); - usb_enable_autosuspend(serial->dev); - switch (nintf) { case 1: /* QDL mode */ @@ -157,15 +178,25 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) case 3: case 4: - /* Composite mode */ - /* ifnum == 0 is a broadband network adapter */ - if (ifnum == 1) { - /* - * Diagnostics Monitor (serial line 9600 8N1) - * Qualcomm DM protocol - * use "libqcdm" (ModemManager) for communication - */ - dbg("Diagnostics Monitor found"); + /* Composite mode; don't bind to the QMI/net interface as that + * gets handled by other drivers. + */ + + /* Gobi 1K USB layout: + * 0: serial port (doesn't respond) + * 1: serial port (doesn't respond) + * 2: AT-capable modem port + * 3: QMI/net + * + * Gobi 2K+ USB layout: + * 0: QMI/net + * 1: DM/DIAG (use libqcdm from ModemManager for communication) + * 2: AT-capable modem port + * 3: NMEA + */ + + if (ifnum == 1 && !is_gobi1k) { + dbg("Gobi 2K+ DM/DIAG interface found"); retval = usb_set_interface(serial->dev, ifnum, 0); if (retval < 0) { dev_err(&serial->dev->dev, @@ -184,13 +215,13 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) retval = -ENODEV; kfree(data); } - } else if (ifnum==3) { + } else if (ifnum==3 && !is_gobi1k) { /* * NMEA (serial line 9600 8N1) * # echo "\$GPS_START" > /dev/ttyUSBx * # echo "\$GPS_STOP" > /dev/ttyUSBx */ - dbg("NMEA GPS interface found"); + dbg("Gobi 2K+ NMEA GPS interface found"); retval = usb_set_interface(serial->dev, ifnum, 0); if (retval < 0) { dev_err(&serial->dev->dev, @@ -234,7 +265,6 @@ static struct usb_serial_driver qcdevice = { }, .description = "Qualcomm USB modem", .id_table = id_table, - .usb_driver = &qcdriver, .num_ports = 1, .probe = qcprobe, .open = usb_wwan_open, @@ -251,31 +281,11 @@ static struct usb_serial_driver qcdevice = { #endif }; -static int __init qcinit(void) -{ - int retval; - - retval = usb_serial_register(&qcdevice); - if (retval) - return retval; - - retval = usb_register(&qcdriver); - if (retval) { - usb_serial_deregister(&qcdevice); - return retval; - } - - return 0; -} - -static void __exit qcexit(void) -{ - usb_deregister(&qcdriver); - usb_serial_deregister(&qcdevice); -} +static struct usb_serial_driver * const serial_drivers[] = { + &qcdevice, NULL +}; -module_init(qcinit); -module_exit(qcexit); +module_usb_serial_driver(qcdriver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index d074b37..ae4ee30 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c @@ -156,7 +156,6 @@ static struct usb_driver safe_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static const __u16 crc10_table[256] = { @@ -309,16 +308,19 @@ static struct usb_serial_driver safe_device = { .name = "safe_serial", }, .id_table = id_table, - .usb_driver = &safe_driver, .num_ports = 1, .process_read_urb = safe_process_read_urb, .prepare_write_buffer = safe_prepare_write_buffer, .attach = safe_startup, }; +static struct usb_serial_driver * const serial_drivers[] = { + &safe_device, NULL +}; + static int __init safe_init(void) { - int i, retval; + int i; printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" DRIVER_DESC "\n"); @@ -337,24 +339,12 @@ static int __init safe_init(void) } } - retval = usb_serial_register(&safe_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&safe_driver); - if (retval) - goto failed_usb_register; - - return 0; -failed_usb_register: - usb_serial_deregister(&safe_device); -failed_usb_serial_register: - return retval; + return usb_serial_register_drivers(&safe_driver, serial_drivers); } static void __exit safe_exit(void) { - usb_deregister(&safe_driver); - usb_serial_deregister(&safe_device); + usb_serial_deregister_drivers(&safe_driver, serial_drivers); } module_init(safe_init); diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c index 74cd4cc..46c0430 100644 --- a/drivers/usb/serial/siemens_mpi.c +++ b/drivers/usb/serial/siemens_mpi.c @@ -42,37 +42,15 @@ static struct usb_serial_driver siemens_usb_mpi_device = { .name = "siemens_mpi", }, .id_table = id_table, - .usb_driver = &siemens_usb_mpi_driver, .num_ports = 1, }; -static int __init siemens_usb_mpi_init(void) -{ - int retval; - - retval = usb_serial_register(&siemens_usb_mpi_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&siemens_usb_mpi_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO DRIVER_DESC "\n"); - printk(KERN_INFO DRIVER_VERSION " " DRIVER_AUTHOR "\n"); - return retval; -failed_usb_register: - usb_serial_deregister(&siemens_usb_mpi_device); -failed_usb_serial_register: - return retval; -} +static struct usb_serial_driver * const serial_drivers[] = { + &siemens_usb_mpi_device, NULL +}; -static void __exit siemens_usb_mpi_exit(void) -{ - usb_deregister(&siemens_usb_mpi_driver); - usb_serial_deregister(&siemens_usb_mpi_device); -} +module_usb_serial_driver(siemens_usb_mpi_driver, serial_drivers); -module_init(siemens_usb_mpi_init); -module_exit(siemens_usb_mpi_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index fdae0a4..f14465a 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -1084,7 +1084,6 @@ static struct usb_driver sierra_driver = { .resume = usb_serial_resume, .reset_resume = sierra_reset_resume, .id_table = id_table, - .no_dynamic_id = 1, .supports_autosuspend = 1, }; @@ -1095,7 +1094,6 @@ static struct usb_serial_driver sierra_device = { }, .description = "Sierra USB modem", .id_table = id_table, - .usb_driver = &sierra_driver, .calc_num_ports = sierra_calc_num_ports, .probe = sierra_probe, .open = sierra_open, @@ -1113,38 +1111,11 @@ static struct usb_serial_driver sierra_device = { .read_int_callback = sierra_instat_callback, }; -/* Functions used by new usb-serial code. */ -static int __init sierra_init(void) -{ - int retval; - retval = usb_serial_register(&sierra_device); - if (retval) - goto failed_device_register; - - - retval = usb_register(&sierra_driver); - if (retval) - goto failed_driver_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; - -failed_driver_register: - usb_serial_deregister(&sierra_device); -failed_device_register: - return retval; -} - -static void __exit sierra_exit(void) -{ - usb_deregister(&sierra_driver); - usb_serial_deregister(&sierra_device); -} +static struct usb_serial_driver * const serial_drivers[] = { + &sierra_device, NULL +}; -module_init(sierra_init); -module_exit(sierra_exit); +module_usb_serial_driver(sierra_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index d7f5eee..f06c9a8 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -156,7 +156,6 @@ static struct usb_driver spcp8x5_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; @@ -649,7 +648,6 @@ static struct usb_serial_driver spcp8x5_device = { .name = "SPCP8x5", }, .id_table = id_table, - .usb_driver = &spcp8x5_driver, .num_ports = 1, .open = spcp8x5_open, .dtr_rts = spcp8x5_dtr_rts, @@ -664,32 +662,11 @@ static struct usb_serial_driver spcp8x5_device = { .process_read_urb = spcp8x5_process_read_urb, }; -static int __init spcp8x5_init(void) -{ - int retval; - retval = usb_serial_register(&spcp8x5_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&spcp8x5_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&spcp8x5_device); -failed_usb_serial_register: - return retval; -} - -static void __exit spcp8x5_exit(void) -{ - usb_deregister(&spcp8x5_driver); - usb_serial_deregister(&spcp8x5_device); -} +static struct usb_serial_driver * const serial_drivers[] = { + &spcp8x5_device, NULL +}; -module_init(spcp8x5_init); -module_exit(spcp8x5_exit); +module_usb_serial_driver(spcp8x5_driver, serial_drivers); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 7697858..3cdc8a5 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -70,7 +70,6 @@ static struct usb_driver ssu100_driver = { .id_table = id_table, .suspend = usb_serial_suspend, .resume = usb_serial_resume, - .no_dynamic_id = 1, .supports_autosuspend = 1, }; @@ -677,7 +676,6 @@ static struct usb_serial_driver ssu100_device = { }, .description = DRIVER_DESC, .id_table = id_table, - .usb_driver = &ssu100_driver, .num_ports = 1, .open = ssu100_open, .close = ssu100_close, @@ -693,41 +691,11 @@ static struct usb_serial_driver ssu100_device = { .disconnect = usb_serial_generic_disconnect, }; -static int __init ssu100_init(void) -{ - int retval; - - dbg("%s", __func__); - - /* register with usb-serial */ - retval = usb_serial_register(&ssu100_device); - - if (retval) - goto failed_usb_sio_register; - - retval = usb_register(&ssu100_driver); - if (retval) - goto failed_usb_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; - -failed_usb_register: - usb_serial_deregister(&ssu100_device); -failed_usb_sio_register: - return retval; -} - -static void __exit ssu100_exit(void) -{ - usb_deregister(&ssu100_driver); - usb_serial_deregister(&ssu100_device); -} +static struct usb_serial_driver * const serial_drivers[] = { + &ssu100_device, NULL +}; -module_init(ssu100_init); -module_exit(ssu100_exit); +module_usb_serial_driver(ssu100_driver, serial_drivers); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index 50651cf..1a5be13 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -287,7 +287,6 @@ static struct usb_driver symbol_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver symbol_device = { @@ -296,7 +295,6 @@ static struct usb_serial_driver symbol_device = { .name = "symbol", }, .id_table = id_table, - .usb_driver = &symbol_driver, .num_ports = 1, .attach = symbol_startup, .open = symbol_open, @@ -307,27 +305,12 @@ static struct usb_serial_driver symbol_device = { .unthrottle = symbol_unthrottle, }; -static int __init symbol_init(void) -{ - int retval; - - retval = usb_serial_register(&symbol_device); - if (retval) - return retval; - retval = usb_register(&symbol_driver); - if (retval) - usb_serial_deregister(&symbol_device); - return retval; -} +static struct usb_serial_driver * const serial_drivers[] = { + &symbol_device, NULL +}; -static void __exit symbol_exit(void) -{ - usb_deregister(&symbol_driver); - usb_serial_deregister(&symbol_device); -} +module_usb_serial_driver(symbol_driver, serial_drivers); -module_init(symbol_init); -module_exit(symbol_exit); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 8468eb7..ab74123 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -165,7 +165,7 @@ static unsigned int product_5052_count; /* the array dimension is the number of default entries plus */ /* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */ /* null entry */ -static struct usb_device_id ti_id_table_3410[13+TI_EXTRA_VID_PID_COUNT+1] = { +static struct usb_device_id ti_id_table_3410[14+TI_EXTRA_VID_PID_COUNT+1] = { { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) }, { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) }, @@ -179,6 +179,7 @@ static struct usb_device_id ti_id_table_3410[13+TI_EXTRA_VID_PID_COUNT+1] = { { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) }, + { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) }, }; static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = { @@ -188,7 +189,7 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = { { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, }; -static struct usb_device_id ti_id_table_combined[17+2*TI_EXTRA_VID_PID_COUNT+1] = { +static struct usb_device_id ti_id_table_combined[18+2*TI_EXTRA_VID_PID_COUNT+1] = { { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) }, { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) }, @@ -206,6 +207,7 @@ static struct usb_device_id ti_id_table_combined[17+2*TI_EXTRA_VID_PID_COUNT+1] { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) }, + { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) }, { } }; @@ -214,7 +216,6 @@ static struct usb_driver ti_usb_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = ti_id_table_combined, - .no_dynamic_id = 1, }; static struct usb_serial_driver ti_1port_device = { @@ -223,7 +224,6 @@ static struct usb_serial_driver ti_1port_device = { .name = "ti_usb_3410_5052_1", }, .description = "TI USB 3410 1 port adapter", - .usb_driver = &ti_usb_driver, .id_table = ti_id_table_3410, .num_ports = 1, .attach = ti_startup, @@ -252,7 +252,6 @@ static struct usb_serial_driver ti_2port_device = { .name = "ti_usb_3410_5052_2", }, .description = "TI USB 5052 2 port adapter", - .usb_driver = &ti_usb_driver, .id_table = ti_id_table_5052, .num_ports = 2, .attach = ti_startup, @@ -275,6 +274,9 @@ static struct usb_serial_driver ti_2port_device = { .write_bulk_callback = ti_bulk_out_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &ti_1port_device, &ti_2port_device, NULL +}; /* Module */ @@ -342,36 +344,17 @@ static int __init ti_init(void) ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE; } - ret = usb_serial_register(&ti_1port_device); - if (ret) - goto failed_1port; - ret = usb_serial_register(&ti_2port_device); - if (ret) - goto failed_2port; - - ret = usb_register(&ti_usb_driver); - if (ret) - goto failed_usb; - - printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":" - TI_DRIVER_DESC "\n"); - - return 0; - -failed_usb: - usb_serial_deregister(&ti_2port_device); -failed_2port: - usb_serial_deregister(&ti_1port_device); -failed_1port: + ret = usb_serial_register_drivers(&ti_usb_driver, serial_drivers); + if (ret == 0) + printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":" + TI_DRIVER_DESC "\n"); return ret; } static void __exit ti_exit(void) { - usb_deregister(&ti_usb_driver); - usb_serial_deregister(&ti_1port_device); - usb_serial_deregister(&ti_2port_device); + usb_serial_deregister_drivers(&ti_usb_driver, serial_drivers); } @@ -1248,7 +1231,6 @@ static void ti_bulk_out_callback(struct urb *urb) { struct ti_port *tport = urb->context; struct usb_serial_port *port = tport->tp_port; - struct device *dev = &urb->dev->dev; int status = urb->status; dbg("%s - port %d", __func__, port->number); @@ -1266,7 +1248,7 @@ static void ti_bulk_out_callback(struct urb *urb) wake_up_interruptible(&tport->tp_write_wait); return; default: - dev_err(dev, "%s - nonzero urb status, %d\n", + dev_err_console(port, "%s - nonzero urb status, %d\n", __func__, status); tport->tp_tdev->td_urb_error = 1; wake_up_interruptible(&tport->tp_write_wait); @@ -1335,7 +1317,7 @@ static void ti_send(struct ti_port *tport) result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, "%s - submit write urb failed, %d\n", + dev_err_console(port, "%s - submit write urb failed, %d\n", __func__, result); tport->tp_write_urb_in_use = 0; /* TODO: reschedule ti_send */ diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h index 2aac195..f140f1b 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.h +++ b/drivers/usb/serial/ti_usb_3410_5052.h @@ -49,6 +49,10 @@ #define MTS_MT9234ZBA_PRODUCT_ID 0xF115 #define MTS_MT9234ZBAOLD_PRODUCT_ID 0x0319 +/* Abbott Diabetics vendor and product ids */ +#define ABBOTT_VENDOR_ID 0x1a61 +#define ABBOTT_PRODUCT_ID 0x3410 + /* Commands */ #define TI_GET_VERSION 0x01 #define TI_GET_PORT_STATUS 0x02 diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 611b206..63ba47d 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1338,7 +1338,7 @@ static void fixup_generic(struct usb_serial_driver *device) set_to_generic_if_null(device, prepare_write_buffer); } -int usb_serial_register(struct usb_serial_driver *driver) +static int usb_serial_register(struct usb_serial_driver *driver) { int retval; @@ -1372,10 +1372,8 @@ int usb_serial_register(struct usb_serial_driver *driver) mutex_unlock(&table_lock); return retval; } -EXPORT_SYMBOL_GPL(usb_serial_register); - -void usb_serial_deregister(struct usb_serial_driver *device) +static void usb_serial_deregister(struct usb_serial_driver *device) { printk(KERN_INFO "USB Serial deregistering driver %s\n", device->description); @@ -1384,7 +1382,76 @@ void usb_serial_deregister(struct usb_serial_driver *device) usb_serial_bus_deregister(device); mutex_unlock(&table_lock); } -EXPORT_SYMBOL_GPL(usb_serial_deregister); + +/** + * usb_serial_register_drivers - register drivers for a usb-serial module + * @udriver: usb_driver used for matching devices/interfaces + * @serial_drivers: NULL-terminated array of pointers to drivers to be registered + * + * Registers @udriver and all the drivers in the @serial_drivers array. + * Automatically fills in the .no_dynamic_id field in @udriver and + * the .usb_driver field in each serial driver. + */ +int usb_serial_register_drivers(struct usb_driver *udriver, + struct usb_serial_driver * const serial_drivers[]) +{ + int rc; + const struct usb_device_id *saved_id_table; + struct usb_serial_driver * const *sd; + + /* + * udriver must be registered before any of the serial drivers, + * because the store_new_id() routine for the serial drivers (in + * bus.c) probes udriver. + * + * Performance hack: We don't want udriver to be probed until + * the serial drivers are registered, because the probe would + * simply fail for lack of a matching serial driver. + * Therefore save off udriver's id_table until we are all set. + */ + saved_id_table = udriver->id_table; + udriver->id_table = NULL; + + udriver->no_dynamic_id = 1; + rc = usb_register(udriver); + if (rc) + return rc; + + for (sd = serial_drivers; *sd; ++sd) { + (*sd)->usb_driver = udriver; + rc = usb_serial_register(*sd); + if (rc) + goto failed; + } + + /* Now restore udriver's id_table and look for matches */ + udriver->id_table = saved_id_table; + rc = driver_attach(&udriver->drvwrap.driver); + return 0; + + failed: + while (sd-- > serial_drivers) + usb_serial_deregister(*sd); + usb_deregister(udriver); + return rc; +} +EXPORT_SYMBOL_GPL(usb_serial_register_drivers); + +/** + * usb_serial_deregister_drivers - deregister drivers for a usb-serial module + * @udriver: usb_driver to unregister + * @serial_drivers: NULL-terminated array of pointers to drivers to be deregistered + * + * Deregisters @udriver and all the drivers in the @serial_drivers array. + */ +void usb_serial_deregister_drivers(struct usb_driver *udriver, + struct usb_serial_driver * const serial_drivers[]) +{ + for (; *serial_drivers; ++serial_drivers) + usb_serial_deregister(*serial_drivers); + usb_deregister(udriver); +} +EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers); /* Module information */ MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index 9b632e7..e3e8995 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -40,7 +40,6 @@ static struct usb_driver debug_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; /* This HW really does not support a serial break, so one will be @@ -74,32 +73,15 @@ static struct usb_serial_driver debug_device = { .name = "debug", }, .id_table = id_table, - .usb_driver = &debug_driver, .num_ports = 1, .bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE, .break_ctl = usb_debug_break_ctl, .process_read_urb = usb_debug_process_read_urb, }; -static int __init debug_init(void) -{ - int retval; - - retval = usb_serial_register(&debug_device); - if (retval) - return retval; - retval = usb_register(&debug_driver); - if (retval) - usb_serial_deregister(&debug_device); - return retval; -} - -static void __exit debug_exit(void) -{ - usb_deregister(&debug_driver); - usb_serial_deregister(&debug_device); -} +static struct usb_serial_driver * const serial_drivers[] = { + &debug_device, NULL +}; -module_init(debug_init); -module_exit(debug_exit); +module_usb_serial_driver(debug_driver, serial_drivers); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 210e4b1..71d6964 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -173,7 +173,6 @@ static struct usb_driver visor_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; /* All of the device info needed for the Handspring Visor, @@ -184,7 +183,6 @@ static struct usb_serial_driver handspring_device = { .name = "visor", }, .description = "Handspring Visor / Palm OS", - .usb_driver = &visor_driver, .id_table = id_table, .num_ports = 2, .bulk_out_size = 256, @@ -205,7 +203,6 @@ static struct usb_serial_driver clie_5_device = { .name = "clie_5", }, .description = "Sony Clie 5.0", - .usb_driver = &visor_driver, .id_table = clie_id_5_table, .num_ports = 2, .bulk_out_size = 256, @@ -226,7 +223,6 @@ static struct usb_serial_driver clie_3_5_device = { .name = "clie_3.5", }, .description = "Sony Clie 3.5", - .usb_driver = &visor_driver, .id_table = clie_id_3_5_table, .num_ports = 1, .bulk_out_size = 256, @@ -237,6 +233,10 @@ static struct usb_serial_driver clie_3_5_device = { .attach = clie_3_5_startup, }; +static struct usb_serial_driver * const serial_drivers[] = { + &handspring_device, &clie_5_device, &clie_3_5_device, NULL +}; + /****************************************************************************** * Handspring Visor specific driver functions ******************************************************************************/ @@ -685,38 +685,17 @@ static int __init visor_init(void) ": Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x\n", vendor, product); } - retval = usb_serial_register(&handspring_device); - if (retval) - goto failed_handspring_register; - retval = usb_serial_register(&clie_3_5_device); - if (retval) - goto failed_clie_3_5_register; - retval = usb_serial_register(&clie_5_device); - if (retval) - goto failed_clie_5_register; - retval = usb_register(&visor_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&clie_5_device); -failed_clie_5_register: - usb_serial_deregister(&clie_3_5_device); -failed_clie_3_5_register: - usb_serial_deregister(&handspring_device); -failed_handspring_register: + retval = usb_serial_register_drivers(&visor_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); return retval; } static void __exit visor_exit (void) { - usb_deregister(&visor_driver); - usb_serial_deregister(&handspring_device); - usb_serial_deregister(&clie_3_5_device); - usb_serial_deregister(&clie_5_device); + usb_serial_deregister_drivers(&visor_driver, serial_drivers); } diff --git a/drivers/usb/serial/vivopay-serial.c b/drivers/usb/serial/vivopay-serial.c index f719d00..078f338 100644 --- a/drivers/usb/serial/vivopay-serial.c +++ b/drivers/usb/serial/vivopay-serial.c @@ -30,7 +30,6 @@ static struct usb_driver vivopay_serial_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver vivopay_serial_device = { @@ -39,36 +38,14 @@ static struct usb_serial_driver vivopay_serial_device = { .name = "vivopay-serial", }, .id_table = id_table, - .usb_driver = &vivopay_serial_driver, .num_ports = 1, }; -static int __init vivopay_serial_init(void) -{ - int retval; - retval = usb_serial_register(&vivopay_serial_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&vivopay_serial_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&vivopay_serial_device); -failed_usb_serial_register: - return retval; -} - -static void __exit vivopay_serial_exit(void) -{ - usb_deregister(&vivopay_serial_driver); - usb_serial_deregister(&vivopay_serial_device); -} +static struct usb_serial_driver * const serial_drivers[] = { + &vivopay_serial_device, NULL +}; -module_init(vivopay_serial_init); -module_exit(vivopay_serial_exit); +module_usb_serial_driver(vivopay_serial_driver, serial_drivers); MODULE_AUTHOR("Forest Bond <forest.bond@outpostembedded.com>"); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 7e0acf5..407e23c 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -83,7 +83,6 @@ static struct usb_driver whiteheat_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; /* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */ @@ -121,7 +120,6 @@ static struct usb_serial_driver whiteheat_fake_device = { .name = "whiteheatnofirm", }, .description = "Connect Tech - WhiteHEAT - (prerenumeration)", - .usb_driver = &whiteheat_driver, .id_table = id_table_prerenumeration, .num_ports = 1, .probe = whiteheat_firmware_download, @@ -134,7 +132,6 @@ static struct usb_serial_driver whiteheat_device = { .name = "whiteheat", }, .description = "Connect Tech - WhiteHEAT", - .usb_driver = &whiteheat_driver, .id_table = id_table_std, .num_ports = 4, .attach = whiteheat_attach, @@ -155,6 +152,9 @@ static struct usb_serial_driver whiteheat_device = { .write_bulk_callback = whiteheat_write_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &whiteheat_fake_device, &whiteheat_device, NULL +}; struct whiteheat_command_private { struct mutex mutex; @@ -740,7 +740,7 @@ static int whiteheat_write(struct tty_struct *tty, urb->transfer_buffer_length = bytes; result = usb_submit_urb(urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, + dev_err_console(port, "%s - failed submitting write urb, error %d\n", __func__, result); sent = result; @@ -1454,44 +1454,7 @@ out: tty_kref_put(tty); } - -/***************************************************************************** - * Connect Tech's White Heat module functions - *****************************************************************************/ -static int __init whiteheat_init(void) -{ - int retval; - retval = usb_serial_register(&whiteheat_fake_device); - if (retval) - goto failed_fake_register; - retval = usb_serial_register(&whiteheat_device); - if (retval) - goto failed_device_register; - retval = usb_register(&whiteheat_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&whiteheat_device); -failed_device_register: - usb_serial_deregister(&whiteheat_fake_device); -failed_fake_register: - return retval; -} - - -static void __exit whiteheat_exit(void) -{ - usb_deregister(&whiteheat_driver); - usb_serial_deregister(&whiteheat_fake_device); - usb_serial_deregister(&whiteheat_device); -} - - -module_init(whiteheat_init); -module_exit(whiteheat_exit); +module_usb_serial_driver(whiteheat_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/serial/zio.c b/drivers/usb/serial/zio.c index f579672..9d0bb37 100644 --- a/drivers/usb/serial/zio.c +++ b/drivers/usb/serial/zio.c @@ -27,7 +27,6 @@ static struct usb_driver zio_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver zio_device = { @@ -36,29 +35,12 @@ static struct usb_serial_driver zio_device = { .name = "zio", }, .id_table = id_table, - .usb_driver = &zio_driver, .num_ports = 1, }; -static int __init zio_init(void) -{ - int retval; - - retval = usb_serial_register(&zio_device); - if (retval) - return retval; - retval = usb_register(&zio_driver); - if (retval) - usb_serial_deregister(&zio_device); - return retval; -} - -static void __exit zio_exit(void) -{ - usb_deregister(&zio_driver); - usb_serial_deregister(&zio_device); -} +static struct usb_serial_driver * const serial_drivers[] = { + &zio_device, NULL +}; -module_init(zio_init); -module_exit(zio_exit); +module_usb_serial_driver(zio_driver, serial_drivers); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index 51af2fe..bab8c8f 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -1276,6 +1276,7 @@ static struct usb_driver alauda_driver = { .post_reset = usb_stor_post_reset, .id_table = alauda_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(alauda_driver); diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 387cbd47..5fe451d 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -272,6 +272,7 @@ static struct usb_driver cypress_driver = { .post_reset = usb_stor_post_reset, .id_table = cypress_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(cypress_driver); diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 15d41f2..35e9c51 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -751,6 +751,7 @@ static struct usb_driver datafab_driver = { .post_reset = usb_stor_post_reset, .id_table = datafab_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(datafab_driver); diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index a6ade40..e7e6781 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -674,7 +674,7 @@ static int sd_scsi_read(struct us_data *us, struct scsi_cmnd *srb) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = blenByte; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[5] = (unsigned char)(bnByte); bcb->CDB[4] = (unsigned char)(bnByte>>8); @@ -858,7 +858,7 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x200; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x02; /* in init.c ENE_MSInit() is 0x01 */ @@ -877,7 +877,7 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x4; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x03; @@ -1170,7 +1170,7 @@ static int ms_read_eraseblock(struct us_data *us, u32 PhyBlockAddr) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x200; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF2; bcb->CDB[1] = 0x06; bcb->CDB[4] = (unsigned char)(bn); @@ -1249,7 +1249,7 @@ static int ms_lib_overwrite_extra(struct us_data *us, u32 PhyBlockAddr, memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x4; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF2; bcb->CDB[1] = 0x05; bcb->CDB[5] = (unsigned char)(PageNum); @@ -1331,7 +1331,7 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x4; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x03; bcb->CDB[5] = (unsigned char)(PageNum); @@ -1533,7 +1533,7 @@ static int ms_lib_read_extrablock(struct us_data *us, u32 PhyBlock, memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x4 * blen; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x03; bcb->CDB[5] = (unsigned char)(PageNum); @@ -1650,7 +1650,7 @@ static int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = blenByte; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x02; bcb->CDB[5] = (unsigned char)(bn); @@ -1694,7 +1694,7 @@ static int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x200 * len; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x02; bcb->CDB[5] = (unsigned char)(blkno); @@ -1827,7 +1827,7 @@ static int ene_get_card_type(struct us_data *us, u16 index, void *buf) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x01; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xED; bcb->CDB[2] = (unsigned char)(index>>8); bcb->CDB[3] = (unsigned char)index; @@ -2083,7 +2083,7 @@ static int ene_ms_init(struct us_data *us) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x200; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x01; @@ -2134,7 +2134,7 @@ static int ene_sd_init(struct us_data *us) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF2; result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0); @@ -2153,7 +2153,7 @@ static int ene_sd_init(struct us_data *us) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x200; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); @@ -2407,6 +2407,7 @@ static struct usb_driver ene_ub6250_driver = { .post_reset = usb_stor_post_reset, .id_table = ene_ub6250_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(ene_ub6250_driver); diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index fa16157..042cf9e 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -553,6 +553,7 @@ static struct usb_driver freecom_driver = { .post_reset = usb_stor_post_reset, .id_table = freecom_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(freecom_driver); diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index bd55027..31fa24e 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -1566,6 +1566,7 @@ static struct usb_driver isd200_driver = { .post_reset = usb_stor_post_reset, .id_table = isd200_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(isd200_driver); diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index a19211b..e3b9738 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -677,6 +677,7 @@ static struct usb_driver jumpshot_driver = { .post_reset = usb_stor_post_reset, .id_table = jumpshot_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(jumpshot_driver); diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c index e720f8e..a8708ea 100644 --- a/drivers/usb/storage/karma.c +++ b/drivers/usb/storage/karma.c @@ -230,6 +230,7 @@ static struct usb_driver karma_driver = { .post_reset = usb_stor_post_reset, .id_table = karma_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(karma_driver); diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index d75155c..886567a 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -312,6 +312,7 @@ static struct usb_driver onetouch_driver = { .post_reset = usb_stor_post_reset, .id_table = onetouch_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(onetouch_driver); diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index 1f62723..63cf282 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -219,7 +219,7 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun, /* set up the command wrapper */ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = cpu_to_le32(buf_len); - bcb->Flags = (dir == DMA_FROM_DEVICE) ? 1 << 7 : 0; + bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : 0; bcb->Tag = ++us->tag; bcb->Lun = lun; bcb->Length = cmd_len; @@ -305,7 +305,7 @@ static int rts51x_bulk_transport_special(struct us_data *us, u8 lun, /* set up the command wrapper */ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = cpu_to_le32(buf_len); - bcb->Flags = (dir == DMA_FROM_DEVICE) ? 1 << 7 : 0; + bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : 0; bcb->Tag = ++us->tag; bcb->Lun = lun; bcb->Length = cmd_len; @@ -507,9 +507,14 @@ static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len) { int retval; u8 cmnd[12] = {0}; + u8 *buf; US_DEBUGP("%s, addr = 0xfe47, len = %d\n", __FUNCTION__, len); + buf = kmemdup(data, len, GFP_NOIO); + if (!buf) + return USB_STOR_TRANSPORT_ERROR; + cmnd[0] = 0xF0; cmnd[1] = 0x0E; cmnd[2] = 0xfe; @@ -517,7 +522,8 @@ static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len) cmnd[4] = (u8)(len >> 8); cmnd[5] = (u8)len; - retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, data, len, DMA_TO_DEVICE, NULL); + retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, buf, len, DMA_TO_DEVICE, NULL); + kfree(buf); if (retval != USB_STOR_TRANSPORT_GOOD) { return -EIO; } @@ -789,7 +795,7 @@ static void rts51x_suspend_timer_fn(unsigned long data) rts51x_set_stat(chip, RTS51X_STAT_SS); /* ignore mass storage interface's children */ pm_suspend_ignore_children(&us->pusb_intf->dev, true); - usb_autopm_put_interface(us->pusb_intf); + usb_autopm_put_interface_async(us->pusb_intf); US_DEBUGP("%s: RTS51X_STAT_SS 01," "intf->pm_usage_cnt:%d, power.usage:%d\n", __func__, @@ -1100,6 +1106,7 @@ static struct usb_driver realtek_cr_driver = { .id_table = realtek_cr_ids, .soft_unbind = 1, .supports_autosuspend = 1, + .no_dynamic_id = 1, }; module_usb_driver(realtek_cr_driver); diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 13b8bcd..a324a5d 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -78,8 +78,6 @@ static const char* host_info(struct Scsi_Host *host) static int slave_alloc (struct scsi_device *sdev) { - struct us_data *us = host_to_us(sdev->host); - /* * Set the INQUIRY transfer length to 36. We don't use any of * the extra data and many devices choke if asked for more or @@ -104,18 +102,6 @@ static int slave_alloc (struct scsi_device *sdev) */ blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1)); - /* - * The UFI spec treates the Peripheral Qualifier bits in an - * INQUIRY result as reserved and requires devices to set them - * to 0. However the SCSI spec requires these bits to be set - * to 3 to indicate when a LUN is not present. - * - * Let the scanning code know if this target merely sets - * Peripheral Device Type to 0x1f to indicate no LUN. - */ - if (us->subclass == USB_SC_UFI) - sdev->sdev_target->pdt_1f_for_no_lun = 1; - return 0; } @@ -197,6 +183,9 @@ static int slave_configure(struct scsi_device *sdev) * page x08, so we will skip it. */ sdev->skip_ms_page_8 = 1; + /* Some devices don't handle VPD pages correctly */ + sdev->skip_vpd_pages = 1; + /* Some disks return the total number of blocks in response * to READ CAPACITY rather than the highest block number. * If this device makes that mistake, tell the sd driver. */ @@ -217,16 +206,6 @@ static int slave_configure(struct scsi_device *sdev) if (sdev->scsi_level > SCSI_SPC_2) us->fflags |= US_FL_SANE_SENSE; - /* Some devices report a SCSI revision level above 2 but are - * unable to handle the REPORT LUNS command (for which - * support is mandatory at level 3). Since we already have - * a Get-Max-LUN request, we won't lose much by setting the - * revision level down to 2. The only devices that would be - * affected are those with sparse LUNs. */ - if (sdev->scsi_level > SCSI_2) - sdev->sdev_target->scsi_level = - sdev->scsi_level = SCSI_2; - /* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable * Hardware Error) when any low-level error occurs, * recoverable or not. Setting this flag tells the SCSI @@ -283,6 +262,33 @@ static int slave_configure(struct scsi_device *sdev) return 0; } +static int target_alloc(struct scsi_target *starget) +{ + struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent)); + + /* + * Some USB drives don't support REPORT LUNS, even though they + * report a SCSI revision level above 2. Tell the SCSI layer + * not to issue that command; it will perform a normal sequential + * scan instead. + */ + starget->no_report_luns = 1; + + /* + * The UFI spec treats the Peripheral Qualifier bits in an + * INQUIRY result as reserved and requires devices to set them + * to 0. However the SCSI spec requires these bits to be set + * to 3 to indicate when a LUN is not present. + * + * Let the scanning code know if this target merely sets + * Peripheral Device Type to 0x1f to indicate no LUN. + */ + if (us->subclass == USB_SC_UFI) + starget->pdt_1f_for_no_lun = 1; + + return 0; +} + /* queue a command */ /* This is always called with scsi_lock(host) held */ static int queuecommand_lck(struct scsi_cmnd *srb, @@ -546,6 +552,7 @@ struct scsi_host_template usb_stor_host_template = { .slave_alloc = slave_alloc, .slave_configure = slave_configure, + .target_alloc = target_alloc, /* lots of sg segments can be handled */ .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 425df7d..3252a62 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -1787,6 +1787,7 @@ static struct usb_driver sddr09_driver = { .post_reset = usb_stor_post_reset, .id_table = sddr09_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(sddr09_driver); diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index e4ca5fc..c144078 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -1006,6 +1006,7 @@ static struct usb_driver sddr55_driver = { .post_reset = usb_stor_post_reset, .id_table = sddr55_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(sddr55_driver); diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index 1369d25..fa1ceeb 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -1863,6 +1863,7 @@ static struct usb_driver usbat_driver = { .post_reset = usb_stor_post_reset, .id_table = usbat_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(usbat_driver); diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 0e5c91c..c70109e 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -1071,7 +1071,8 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) /* set up the command wrapper */ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = cpu_to_le32(transfer_length); - bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0; + bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? + US_BULK_FLAG_IN : 0; bcb->Tag = ++us->tag; bcb->Lun = srb->device->lun; if (us->fflags & US_FL_SCM_MULT_TARG) diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h index 242ff5e..9369d75 100644 --- a/drivers/usb/storage/transport.h +++ b/drivers/usb/storage/transport.h @@ -42,45 +42,6 @@ #include <linux/blkdev.h> /* - * Bulk only data structures - */ - -/* command block wrapper */ -struct bulk_cb_wrap { - __le32 Signature; /* contains 'USBC' */ - __u32 Tag; /* unique per command id */ - __le32 DataTransferLength; /* size of data */ - __u8 Flags; /* direction in bit 0 */ - __u8 Lun; /* LUN normally 0 */ - __u8 Length; /* of of the CDB */ - __u8 CDB[16]; /* max command */ -}; - -#define US_BULK_CB_WRAP_LEN 31 -#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */ -#define US_BULK_FLAG_IN 1 -#define US_BULK_FLAG_OUT 0 - -/* command status wrapper */ -struct bulk_cs_wrap { - __le32 Signature; /* should = 'USBS' */ - __u32 Tag; /* same as original command */ - __le32 Residue; /* amount not transferred */ - __u8 Status; /* see below */ - __u8 Filler[18]; -}; - -#define US_BULK_CS_WRAP_LEN 13 -#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ -#define US_BULK_STAT_OK 0 -#define US_BULK_STAT_FAIL 1 -#define US_BULK_STAT_PHASE 2 - -/* bulk-only class specific requests */ -#define US_BULK_RESET_REQUEST 0xff -#define US_BULK_GET_MAX_LUN 0xfe - -/* * usb_stor_bulk_transfer_xxx() return codes, in order of severity */ diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index a33ead5..8ec8a6e 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -13,7 +13,9 @@ #include <linux/types.h> #include <linux/module.h> #include <linux/usb.h> +#include <linux/usb/hcd.h> #include <linux/usb/storage.h> +#include <linux/usb/uas.h> #include <scsi/scsi.h> #include <scsi/scsi_dbg.h> @@ -22,49 +24,6 @@ #include <scsi/scsi_host.h> #include <scsi/scsi_tcq.h> -/* Common header for all IUs */ -struct iu { - __u8 iu_id; - __u8 rsvd1; - __be16 tag; -}; - -enum { - IU_ID_COMMAND = 0x01, - IU_ID_STATUS = 0x03, - IU_ID_RESPONSE = 0x04, - IU_ID_TASK_MGMT = 0x05, - IU_ID_READ_READY = 0x06, - IU_ID_WRITE_READY = 0x07, -}; - -struct command_iu { - __u8 iu_id; - __u8 rsvd1; - __be16 tag; - __u8 prio_attr; - __u8 rsvd5; - __u8 len; - __u8 rsvd7; - struct scsi_lun lun; - __u8 cdb[16]; /* XXX: Overflow-checking tools may misunderstand */ -}; - -/* - * Also used for the Read Ready and Write Ready IUs since they have the - * same first four bytes - */ -struct sense_iu { - __u8 iu_id; - __u8 rsvd1; - __be16 tag; - __be16 status_qual; - __u8 status; - __u8 rsvd7[7]; - __be16 len; - __u8 sense[SCSI_SENSE_BUFFERSIZE]; -}; - /* * The r00-r01c specs define this version of the SENSE IU data structure. * It's still in use by several different firmware releases. @@ -79,18 +38,6 @@ struct sense_iu_old { __u8 sense[SCSI_SENSE_BUFFERSIZE]; }; -enum { - CMD_PIPE_ID = 1, - STATUS_PIPE_ID = 2, - DATA_IN_PIPE_ID = 3, - DATA_OUT_PIPE_ID = 4, - - UAS_SIMPLE_TAG = 0, - UAS_HEAD_TAG = 1, - UAS_ORDERED_TAG = 2, - UAS_ACA = 4, -}; - struct uas_dev_info { struct usb_interface *intf; struct usb_device *udev; @@ -98,6 +45,8 @@ struct uas_dev_info { unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe; unsigned use_streams:1; unsigned uas_sense_old:1; + struct scsi_cmnd *cmnd; + struct urb *status_urb; /* used only if stream support is available */ }; enum { @@ -109,6 +58,9 @@ enum { SUBMIT_DATA_OUT_URB = (1 << 5), ALLOC_CMD_URB = (1 << 6), SUBMIT_CMD_URB = (1 << 7), + COMPLETED_DATA_IN = (1 << 8), + COMPLETED_DATA_OUT = (1 << 9), + DATA_COMPLETES_CMD = (1 << 10), }; /* Overrides scsi_pointer */ @@ -116,6 +68,7 @@ struct uas_cmd_info { unsigned int state; unsigned int stream; struct urb *cmd_urb; + /* status_urb is used only if stream support isn't available */ struct urb *status_urb; struct urb *data_in_urb; struct urb *data_out_urb; @@ -125,33 +78,43 @@ struct uas_cmd_info { /* I hate forward declarations, but I actually have a loop */ static int uas_submit_urbs(struct scsi_cmnd *cmnd, struct uas_dev_info *devinfo, gfp_t gfp); +static void uas_do_work(struct work_struct *work); +static DECLARE_WORK(uas_work, uas_do_work); static DEFINE_SPINLOCK(uas_work_lock); static LIST_HEAD(uas_work_list); static void uas_do_work(struct work_struct *work) { struct uas_cmd_info *cmdinfo; + struct uas_cmd_info *temp; struct list_head list; + int err; spin_lock_irq(&uas_work_lock); list_replace_init(&uas_work_list, &list); spin_unlock_irq(&uas_work_lock); - list_for_each_entry(cmdinfo, &list, list) { + list_for_each_entry_safe(cmdinfo, temp, &list, list) { struct scsi_pointer *scp = (void *)cmdinfo; struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp); - uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); + err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); + if (err) { + list_del(&cmdinfo->list); + spin_lock_irq(&uas_work_lock); + list_add_tail(&cmdinfo->list, &uas_work_list); + spin_unlock_irq(&uas_work_lock); + schedule_work(&uas_work); + } } } -static DECLARE_WORK(uas_work, uas_do_work); - static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) { struct sense_iu *sense_iu = urb->transfer_buffer; struct scsi_device *sdev = cmnd->device; + struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; if (urb->actual_length > 16) { unsigned len = be16_to_cpup(&sense_iu->len); @@ -169,16 +132,15 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) } cmnd->result = sense_iu->status; - if (sdev->current_cmnd) - sdev->current_cmnd = NULL; - cmnd->scsi_done(cmnd); - usb_free_urb(urb); + if (!(cmdinfo->state & DATA_COMPLETES_CMD)) + cmnd->scsi_done(cmnd); } static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) { struct sense_iu_old *sense_iu = urb->transfer_buffer; struct scsi_device *sdev = cmnd->device; + struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; if (urb->actual_length > 8) { unsigned len = be16_to_cpup(&sense_iu->len) - 2; @@ -196,10 +158,8 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) } cmnd->result = sense_iu->status; - if (sdev->current_cmnd) - sdev->current_cmnd = NULL; - cmnd->scsi_done(cmnd); - usb_free_urb(urb); + if (!(cmdinfo->state & DATA_COMPLETES_CMD)) + cmnd->scsi_done(cmnd); } static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, @@ -208,7 +168,7 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; int err; - cmdinfo->state = direction | SUBMIT_STATUS_URB; + cmdinfo->state = direction; err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); if (err) { spin_lock(&uas_work_lock); @@ -221,27 +181,61 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, static void uas_stat_cmplt(struct urb *urb) { struct iu *iu = urb->transfer_buffer; - struct scsi_device *sdev = urb->context; - struct uas_dev_info *devinfo = sdev->hostdata; + struct Scsi_Host *shost = urb->context; + struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; struct scsi_cmnd *cmnd; + struct uas_cmd_info *cmdinfo; u16 tag; + int ret; if (urb->status) { dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status); - usb_free_urb(urb); + if (devinfo->use_streams) + usb_free_urb(urb); return; } tag = be16_to_cpup(&iu->tag) - 1; - if (sdev->current_cmnd) - cmnd = sdev->current_cmnd; + if (tag == 0) + cmnd = devinfo->cmnd; else - cmnd = scsi_find_tag(sdev, tag); - if (!cmnd) + cmnd = scsi_host_find_tag(shost, tag - 1); + if (!cmnd) { + if (devinfo->use_streams) { + usb_free_urb(urb); + return; + } + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) + dev_err(&urb->dev->dev, "failed submit status urb\n"); return; + } + cmdinfo = (void *)&cmnd->SCp; switch (iu->iu_id) { case IU_ID_STATUS: + if (devinfo->cmnd == cmnd) + devinfo->cmnd = NULL; + + if (!(cmdinfo->state & COMPLETED_DATA_IN) && + cmdinfo->data_in_urb) { + if (devinfo->use_streams) { + cmdinfo->state |= DATA_COMPLETES_CMD; + usb_unlink_urb(cmdinfo->data_in_urb); + } else { + usb_free_urb(cmdinfo->data_in_urb); + } + } + if (!(cmdinfo->state & COMPLETED_DATA_OUT) && + cmdinfo->data_out_urb) { + if (devinfo->use_streams) { + cmdinfo->state |= DATA_COMPLETES_CMD; + usb_unlink_urb(cmdinfo->data_in_urb); + } else { + usb_free_urb(cmdinfo->data_out_urb); + } + } + if (urb->actual_length < 16) devinfo->uas_sense_old = 1; if (devinfo->uas_sense_old) @@ -259,29 +253,70 @@ static void uas_stat_cmplt(struct urb *urb) scmd_printk(KERN_ERR, cmnd, "Bogus IU (%d) received on status pipe\n", iu->iu_id); } + + if (devinfo->use_streams) { + usb_free_urb(urb); + return; + } + + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) + dev_err(&urb->dev->dev, "failed submit status urb\n"); } -static void uas_data_cmplt(struct urb *urb) +static void uas_data_out_cmplt(struct urb *urb) { - struct scsi_data_buffer *sdb = urb->context; + struct scsi_cmnd *cmnd = urb->context; + struct scsi_data_buffer *sdb = scsi_out(cmnd); + struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + + cmdinfo->state |= COMPLETED_DATA_OUT; + sdb->resid = sdb->length - urb->actual_length; usb_free_urb(urb); + + if (cmdinfo->state & DATA_COMPLETES_CMD) + cmnd->scsi_done(cmnd); +} + +static void uas_data_in_cmplt(struct urb *urb) +{ + struct scsi_cmnd *cmnd = urb->context; + struct scsi_data_buffer *sdb = scsi_in(cmnd); + struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + + cmdinfo->state |= COMPLETED_DATA_IN; + + sdb->resid = sdb->length - urb->actual_length; + usb_free_urb(urb); + + if (cmdinfo->state & DATA_COMPLETES_CMD) + cmnd->scsi_done(cmnd); } static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp, - unsigned int pipe, u16 stream_id, - struct scsi_data_buffer *sdb, - enum dma_data_direction dir) + unsigned int pipe, struct scsi_cmnd *cmnd, + enum dma_data_direction dir) { + struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; struct usb_device *udev = devinfo->udev; struct urb *urb = usb_alloc_urb(0, gfp); + struct scsi_data_buffer *sdb; + usb_complete_t complete_fn; + u16 stream_id = cmdinfo->stream; if (!urb) goto out; - usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, uas_data_cmplt, - sdb); - if (devinfo->use_streams) - urb->stream_id = stream_id; + if (dir == DMA_FROM_DEVICE) { + sdb = scsi_in(cmnd); + complete_fn = uas_data_in_cmplt; + } else { + sdb = scsi_out(cmnd); + complete_fn = uas_data_out_cmplt; + } + usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, + complete_fn, cmnd); + urb->stream_id = stream_id; urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0; urb->sg = sdb->table.sgl; out: @@ -289,7 +324,7 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp, } static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, - struct scsi_cmnd *cmnd, u16 stream_id) + struct Scsi_Host *shost, u16 stream_id) { struct usb_device *udev = devinfo->udev; struct urb *urb = usb_alloc_urb(0, gfp); @@ -303,7 +338,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, goto free; usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu), - uas_stat_cmplt, cmnd->device); + uas_stat_cmplt, shost); urb->stream_id = stream_id; urb->transfer_flags |= URB_FREE_BUFFER; out: @@ -334,7 +369,10 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp, goto free; iu->iu_id = IU_ID_COMMAND; - iu->tag = cpu_to_be16(stream_id); + if (blk_rq_tagged(cmnd->request)) + iu->tag = cpu_to_be16(cmnd->request->tag + 2); + else + iu->tag = cpu_to_be16(1); iu->prio_attr = UAS_SIMPLE_TAG; iu->len = len; int_to_scsilun(sdev->lun, &iu->lun); @@ -362,8 +400,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; if (cmdinfo->state & ALLOC_STATUS_URB) { - cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd, - cmdinfo->stream); + cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, + cmnd->device->host, cmdinfo->stream); if (!cmdinfo->status_urb) return SCSI_MLQUEUE_DEVICE_BUSY; cmdinfo->state &= ~ALLOC_STATUS_URB; @@ -380,8 +418,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, if (cmdinfo->state & ALLOC_DATA_IN_URB) { cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp, - devinfo->data_in_pipe, cmdinfo->stream, - scsi_in(cmnd), DMA_FROM_DEVICE); + devinfo->data_in_pipe, cmnd, + DMA_FROM_DEVICE); if (!cmdinfo->data_in_urb) return SCSI_MLQUEUE_DEVICE_BUSY; cmdinfo->state &= ~ALLOC_DATA_IN_URB; @@ -398,8 +436,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, if (cmdinfo->state & ALLOC_DATA_OUT_URB) { cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp, - devinfo->data_out_pipe, cmdinfo->stream, - scsi_out(cmnd), DMA_TO_DEVICE); + devinfo->data_out_pipe, cmnd, + DMA_TO_DEVICE); if (!cmdinfo->data_out_urb) return SCSI_MLQUEUE_DEVICE_BUSY; cmdinfo->state &= ~ALLOC_DATA_OUT_URB; @@ -444,13 +482,13 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer)); - if (!cmdinfo->status_urb && sdev->current_cmnd) + if (devinfo->cmnd) return SCSI_MLQUEUE_DEVICE_BUSY; if (blk_rq_tagged(cmnd->request)) { - cmdinfo->stream = cmnd->request->tag + 1; + cmdinfo->stream = cmnd->request->tag + 2; } else { - sdev->current_cmnd = cmnd; + devinfo->cmnd = cmnd; cmdinfo->stream = 1; } @@ -472,7 +510,8 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, } if (!devinfo->use_streams) { - cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB); + cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB | + ALLOC_STATUS_URB | SUBMIT_STATUS_URB); cmdinfo->stream = 0; } @@ -551,7 +590,7 @@ static int uas_slave_configure(struct scsi_device *sdev) { struct uas_dev_info *devinfo = sdev->hostdata; scsi_set_tag_type(sdev, MSG_ORDERED_TAG); - scsi_activate_tcq(sdev, devinfo->qdepth - 1); + scsi_activate_tcq(sdev, devinfo->qdepth - 2); return 0; } @@ -589,22 +628,34 @@ static int uas_is_interface(struct usb_host_interface *intf) intf->desc.bInterfaceProtocol == USB_PR_UAS); } +static int uas_isnt_supported(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + dev_warn(&udev->dev, "The driver for the USB controller %s does not " + "support scatter-gather which is\n", + hcd->driver->description); + dev_warn(&udev->dev, "required by the UAS driver. Please try an" + "alternative USB controller if you wish to use UAS.\n"); + return -ENODEV; +} + static int uas_switch_interface(struct usb_device *udev, struct usb_interface *intf) { int i; - - if (uas_is_interface(intf->cur_altsetting)) - return 0; + int sg_supported = udev->bus->sg_tablesize != 0; for (i = 0; i < intf->num_altsetting; i++) { struct usb_host_interface *alt = &intf->altsetting[i]; - if (alt == intf->cur_altsetting) - continue; - if (uas_is_interface(alt)) + + if (uas_is_interface(alt)) { + if (!sg_supported) + return uas_isnt_supported(udev); return usb_set_interface(udev, alt->desc.bInterfaceNumber, alt->desc.bAlternateSetting); + } } return -ENODEV; @@ -619,6 +670,7 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo) unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints; devinfo->uas_sense_old = 0; + devinfo->cmnd = NULL; for (i = 0; i < n_endpoints; i++) { unsigned char *extra = endpoint[i].extra; @@ -670,6 +722,40 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo) } } +static int uas_alloc_status_urb(struct uas_dev_info *devinfo, + struct Scsi_Host *shost) +{ + if (devinfo->use_streams) { + devinfo->status_urb = NULL; + return 0; + } + + devinfo->status_urb = uas_alloc_sense_urb(devinfo, GFP_KERNEL, + shost, 0); + if (!devinfo->status_urb) + goto err_s_urb; + + if (usb_submit_urb(devinfo->status_urb, GFP_KERNEL)) + goto err_submit_urb; + + return 0; +err_submit_urb: + usb_free_urb(devinfo->status_urb); +err_s_urb: + return -ENOMEM; +} + +static void uas_free_streams(struct uas_dev_info *devinfo) +{ + struct usb_device *udev = devinfo->udev; + struct usb_host_endpoint *eps[3]; + + eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); + eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); + eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); + usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL); +} + /* * XXX: What I'd like to do here is register a SCSI host for each USB host in * the system. Follow usb-storage's design of registering a SCSI host for @@ -699,18 +785,33 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) shost->max_id = 1; shost->sg_tablesize = udev->bus->sg_tablesize; - result = scsi_add_host(shost, &intf->dev); + devinfo->intf = intf; + devinfo->udev = udev; + uas_configure_endpoints(devinfo); + + result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2); if (result) goto free; + + result = scsi_add_host(shost, &intf->dev); + if (result) + goto deconfig_eps; + shost->hostdata[0] = (unsigned long)devinfo; - devinfo->intf = intf; - devinfo->udev = udev; - uas_configure_endpoints(devinfo); + result = uas_alloc_status_urb(devinfo, shost); + if (result) + goto err_alloc_status; scsi_scan_host(shost); usb_set_intfdata(intf, shost); return result; + +err_alloc_status: + scsi_remove_host(shost); + shost = NULL; +deconfig_eps: + uas_free_streams(devinfo); free: kfree(devinfo); if (shost) @@ -732,18 +833,13 @@ static int uas_post_reset(struct usb_interface *intf) static void uas_disconnect(struct usb_interface *intf) { - struct usb_device *udev = interface_to_usbdev(intf); - struct usb_host_endpoint *eps[3]; struct Scsi_Host *shost = usb_get_intfdata(intf); struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; scsi_remove_host(shost); - - eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); - eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); - eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); - usb_free_streams(intf, eps, 3, GFP_KERNEL); - + usb_kill_urb(devinfo->status_urb); + usb_free_urb(devinfo->status_urb); + uas_free_streams(devinfo); kfree(devinfo); } diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 3dd7da9..c18538e 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -125,6 +125,9 @@ static struct us_unusual_dev us_unusual_dev_list[] = { { } /* Terminating entry */ }; +static struct us_unusual_dev for_dynamic_ids = + USUAL_DEV(USB_SC_SCSI, USB_PR_BULK, 0); + #undef UNUSUAL_DEV #undef COMPLIANT_DEV #undef USUAL_DEV @@ -788,15 +791,19 @@ static void quiesce_and_remove_host(struct us_data *us) struct Scsi_Host *host = us_to_host(us); /* If the device is really gone, cut short reset delays */ - if (us->pusb_dev->state == USB_STATE_NOTATTACHED) + if (us->pusb_dev->state == USB_STATE_NOTATTACHED) { set_bit(US_FLIDX_DISCONNECTING, &us->dflags); + wake_up(&us->delay_wait); + } - /* Prevent SCSI-scanning (if it hasn't started yet) - * and wait for the SCSI-scanning thread to stop. + /* Prevent SCSI scanning (if it hasn't started yet) + * or wait for the SCSI-scanning routine to stop. */ - set_bit(US_FLIDX_DONT_SCAN, &us->dflags); - wake_up(&us->delay_wait); - wait_for_completion(&us->scanning_done); + cancel_delayed_work_sync(&us->scan_dwork); + + /* Balance autopm calls if scanning was cancelled */ + if (test_bit(US_FLIDX_SCAN_PENDING, &us->dflags)) + usb_autopm_put_interface_no_suspend(us->pusb_intf); /* Removing the host will perform an orderly shutdown: caches * synchronized, disks spun down, etc. @@ -823,53 +830,28 @@ static void release_everything(struct us_data *us) scsi_host_put(us_to_host(us)); } -/* Thread to carry out delayed SCSI-device scanning */ -static int usb_stor_scan_thread(void * __us) +/* Delayed-work routine to carry out SCSI-device scanning */ +static void usb_stor_scan_dwork(struct work_struct *work) { - struct us_data *us = (struct us_data *)__us; + struct us_data *us = container_of(work, struct us_data, + scan_dwork.work); struct device *dev = &us->pusb_intf->dev; - dev_dbg(dev, "device found\n"); - - set_freezable(); + dev_dbg(dev, "starting scan\n"); - /* - * Wait for the timeout to expire or for a disconnect - * - * We can't freeze in this thread or we risk causing khubd to - * fail to freeze, but we can't be non-freezable either. Nor can - * khubd freeze while waiting for scanning to complete as it may - * hold the device lock, causing a hang when suspending devices. - * So instead of using wait_event_freezable(), explicitly test - * for (DONT_SCAN || freezing) in interruptible wait and proceed - * if any of DONT_SCAN, freezing or timeout has happened. - */ - if (delay_use > 0) { - dev_dbg(dev, "waiting for device to settle " - "before scanning\n"); - wait_event_interruptible_timeout(us->delay_wait, - test_bit(US_FLIDX_DONT_SCAN, &us->dflags) || - freezing(current), delay_use * HZ); + /* For bulk-only devices, determine the max LUN value */ + if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) { + mutex_lock(&us->dev_mutex); + us->max_lun = usb_stor_Bulk_max_lun(us); + mutex_unlock(&us->dev_mutex); } + scsi_scan_host(us_to_host(us)); + dev_dbg(dev, "scan complete\n"); - /* If the device is still connected, perform the scanning */ - if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) { - - /* For bulk-only devices, determine the max LUN value */ - if (us->protocol == USB_PR_BULK && - !(us->fflags & US_FL_SINGLE_LUN)) { - mutex_lock(&us->dev_mutex); - us->max_lun = usb_stor_Bulk_max_lun(us); - mutex_unlock(&us->dev_mutex); - } - scsi_scan_host(us_to_host(us)); - dev_dbg(dev, "scan complete\n"); - - /* Should we unbind if no devices were detected? */ - } + /* Should we unbind if no devices were detected? */ usb_autopm_put_interface(us->pusb_intf); - complete_and_exit(&us->scanning_done, 0); + clear_bit(US_FLIDX_SCAN_PENDING, &us->dflags); } static unsigned int usb_stor_sg_tablesize(struct usb_interface *intf) @@ -916,7 +898,7 @@ int usb_stor_probe1(struct us_data **pus, init_completion(&us->cmnd_ready); init_completion(&(us->notify)); init_waitqueue_head(&us->delay_wait); - init_completion(&us->scanning_done); + INIT_DELAYED_WORK(&us->scan_dwork, usb_stor_scan_dwork); /* Associate the us_data structure with the USB device */ result = associate_dev(us, intf); @@ -947,7 +929,6 @@ EXPORT_SYMBOL_GPL(usb_stor_probe1); /* Second part of general USB mass-storage probing */ int usb_stor_probe2(struct us_data *us) { - struct task_struct *th; int result; struct device *dev = &us->pusb_intf->dev; @@ -988,20 +969,14 @@ int usb_stor_probe2(struct us_data *us) goto BadDevice; } - /* Start up the thread for delayed SCSI-device scanning */ - th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan"); - if (IS_ERR(th)) { - dev_warn(dev, - "Unable to start the device-scanning thread\n"); - complete(&us->scanning_done); - quiesce_and_remove_host(us); - result = PTR_ERR(th); - goto BadDevice; - } - + /* Submit the delayed_work for SCSI-device scanning */ usb_autopm_get_interface_no_resume(us->pusb_intf); - wake_up_process(th); + set_bit(US_FLIDX_SCAN_PENDING, &us->dflags); + if (delay_use > 0) + dev_dbg(dev, "waiting for device to settle before scanning\n"); + queue_delayed_work(system_freezable_wq, &us->scan_dwork, + delay_use * HZ); return 0; /* We come here if there are any problems */ @@ -1027,8 +1002,10 @@ EXPORT_SYMBOL_GPL(usb_stor_disconnect); static int storage_probe(struct usb_interface *intf, const struct usb_device_id *id) { + struct us_unusual_dev *unusual_dev; struct us_data *us; int result; + int size; /* * If libusual is configured, let it decide whether a standard @@ -1047,8 +1024,19 @@ static int storage_probe(struct usb_interface *intf, * table, so we use the index of the id entry to find the * corresponding unusual_devs entry. */ - result = usb_stor_probe1(&us, intf, id, - (id - usb_storage_usb_ids) + us_unusual_dev_list); + + size = ARRAY_SIZE(us_unusual_dev_list); + if (id >= usb_storage_usb_ids && id < usb_storage_usb_ids + size) { + unusual_dev = (id - usb_storage_usb_ids) + us_unusual_dev_list; + } else { + unusual_dev = &for_dynamic_ids; + + US_DEBUGP("%s %s 0x%04x 0x%04x\n", "Use Bulk-Only transport", + "with the Transparent SCSI protocol for dynamic id:", + id->idVendor, id->idProduct); + } + + result = usb_stor_probe1(&us, intf, id, unusual_dev); if (result) return result; @@ -1074,7 +1062,6 @@ static struct usb_driver usb_storage_driver = { .id_table = usb_storage_usb_ids, .supports_autosuspend = 1, .soft_unbind = 1, - .no_dynamic_id = 1, }; static int __init usb_stor_init(void) diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 7b0f211..75f70f0 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -47,6 +47,7 @@ #include <linux/blkdev.h> #include <linux/completion.h> #include <linux/mutex.h> +#include <linux/workqueue.h> #include <scsi/scsi_host.h> struct us_data; @@ -72,7 +73,7 @@ struct us_unusual_dev { #define US_FLIDX_DISCONNECTING 3 /* disconnect in progress */ #define US_FLIDX_RESETTING 4 /* device reset in progress */ #define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */ -#define US_FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */ +#define US_FLIDX_SCAN_PENDING 6 /* scanning not yet done */ #define US_FLIDX_REDO_READ10 7 /* redo READ(10) command */ #define US_FLIDX_READ10_WORKED 8 /* previous READ(10) succeeded */ @@ -147,8 +148,8 @@ struct us_data { /* mutual exclusion and synchronization structures */ struct completion cmnd_ready; /* to sleep thread on */ struct completion notify; /* thread begin/end */ - wait_queue_head_t delay_wait; /* wait during scan, reset */ - struct completion scanning_done; /* wait for scan thread */ + wait_queue_head_t delay_wait; /* wait during reset */ + struct delayed_work scan_dwork; /* for async scanning */ /* subdriver information */ void *extra; /* Any extra data */ diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 8efeae2..b4a7167 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -27,8 +27,6 @@ #define USB_SKEL_VENDOR_ID 0xfff0 #define USB_SKEL_PRODUCT_ID 0xfff0 -static DEFINE_MUTEX(skel_mutex); - /* table of devices that work with this driver */ static const struct usb_device_id skel_table[] = { { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, @@ -101,25 +99,18 @@ static int skel_open(struct inode *inode, struct file *file) goto exit; } - mutex_lock(&skel_mutex); dev = usb_get_intfdata(interface); if (!dev) { - mutex_unlock(&skel_mutex); retval = -ENODEV; goto exit; } /* increment our usage count for the device */ kref_get(&dev->kref); - mutex_unlock(&skel_mutex); /* lock the device to allow correctly handling errors * in resumption */ mutex_lock(&dev->io_mutex); - if (!dev->interface) { - retval = -ENODEV; - goto out_err; - } retval = usb_autopm_get_interface(interface); if (retval) @@ -127,11 +118,7 @@ static int skel_open(struct inode *inode, struct file *file) /* save our object in the file's private structure */ file->private_data = dev; - -out_err: mutex_unlock(&dev->io_mutex); - if (retval) - kref_put(&dev->kref, skel_delete); exit: return retval; @@ -611,6 +598,7 @@ static void skel_disconnect(struct usb_interface *interface) int minor = interface->minor; dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); /* give back our minor */ usb_deregister_dev(interface, &skel_class); @@ -622,12 +610,8 @@ static void skel_disconnect(struct usb_interface *interface) usb_kill_anchored_urbs(&dev->submitted); - mutex_lock(&skel_mutex); - usb_set_intfdata(interface, NULL); - /* decrement our usage count */ kref_put(&dev->kref, skel_delete); - mutex_unlock(&skel_mutex); dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor); } diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/usb/wusbcore/Kconfig index 0ead882..f29fdd7 100644 --- a/drivers/usb/wusbcore/Kconfig +++ b/drivers/usb/wusbcore/Kconfig @@ -6,7 +6,7 @@ config USB_WUSB depends on EXPERIMENTAL depends on USB depends on PCI - select UWB + depends on UWB select CRYPTO select CRYPTO_BLKCIPHER select CRYPTO_CBC |