diff options
Diffstat (limited to 'drivers/usb')
191 files changed, 8265 insertions, 5210 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 76316a33061b..4473ae51ddb4 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -177,6 +177,8 @@ source "drivers/usb/serial/Kconfig" source "drivers/usb/misc/Kconfig" +source "drivers/usb/phy/Kconfig" + source "drivers/usb/atm/Kconfig" source "drivers/usb/gadget/Kconfig" diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 53a7bc07dd8d..77c835a15239 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/ obj-$(CONFIG_USB_SERIAL) += serial/ obj-$(CONFIG_USB) += misc/ +obj-$(CONFIG_USB) += phy/ obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/ obj-$(CONFIG_USB_ATM) += atm/ diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 98b89fe19867..b7eb86ad6bf2 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -674,7 +674,7 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, } ret = offd; - dbg("cm %#x", cm); + usb_dbg(instance->usbatm, "cm %#x\n", cm); fail: mutex_unlock(&instance->cm_serialize); err: @@ -733,7 +733,7 @@ static int cxacru_card_status(struct cxacru_data *instance) { int ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0); if (ret < 0) { /* firmware not loaded */ - dbg("cxacru_adsl_start: CARD_GET_STATUS returned %d", ret); + usb_dbg(instance->usbatm, "cxacru_adsl_start: CARD_GET_STATUS returned %d\n", ret); return ret; } return 0; @@ -758,7 +758,7 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, int ret; int start_polling = 1; - dbg("cxacru_atm_start"); + dev_dbg(&intf->dev, "%s\n", __func__); /* Read MAC address */ ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_MAC_ADDRESS, NULL, 0, @@ -962,13 +962,13 @@ static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw, ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD), buf, offb, NULL, CMD_TIMEOUT); if (ret < 0) { - dbg("sending fw %#x failed", fw); + dev_dbg(&usb_dev->dev, "sending fw %#x failed\n", fw); goto cleanup; } offb = 0; } } while (offd < size); - dbg("sent fw %#x", fw); + dev_dbg(&usb_dev->dev, "sent fw %#x\n", fw); ret = 0; @@ -988,7 +988,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, usb_dev->descriptor.idProduct }; __le32 val; - dbg("cxacru_upload_firmware"); + usb_dbg(usbatm, "%s\n", __func__); /* FirmwarePllFClkValue */ val = cpu_to_le32(instance->modem_type->pll_f_clk); @@ -1074,7 +1074,7 @@ static int cxacru_find_firmware(struct cxacru_data *instance, char buf[16]; sprintf(buf, "cxacru-%s.bin", phase); - dbg("cxacru_find_firmware: looking for %s", buf); + usb_dbg(usbatm, "cxacru_find_firmware: looking for %s\n", buf); if (request_firmware(fw_p, buf, dev)) { usb_dbg(usbatm, "no stage %s firmware found\n", phase); @@ -1115,9 +1115,9 @@ static int cxacru_heavy_init(struct usbatm_data *usbatm_instance, ret = cxacru_card_status(instance); if (ret) - dbg("modem initialisation failed"); + usb_dbg(usbatm_instance, "modem initialisation failed\n"); else - dbg("done setting up the modem"); + usb_dbg(usbatm_instance, "done setting up the modem\n"); return ret; } @@ -1133,7 +1133,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, /* instance init */ instance = kzalloc(sizeof(*instance), GFP_KERNEL); if (!instance) { - dbg("cxacru_bind: no memory for instance data"); + usb_dbg(usbatm_instance, "cxacru_bind: no memory for instance data\n"); return -ENOMEM; } @@ -1149,31 +1149,31 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, instance->rcv_buf = (u8 *) __get_free_page(GFP_KERNEL); if (!instance->rcv_buf) { - dbg("cxacru_bind: no memory for rcv_buf"); + usb_dbg(usbatm_instance, "cxacru_bind: no memory for rcv_buf\n"); ret = -ENOMEM; goto fail; } instance->snd_buf = (u8 *) __get_free_page(GFP_KERNEL); if (!instance->snd_buf) { - dbg("cxacru_bind: no memory for snd_buf"); + usb_dbg(usbatm_instance, "cxacru_bind: no memory for snd_buf\n"); ret = -ENOMEM; goto fail; } instance->rcv_urb = usb_alloc_urb(0, GFP_KERNEL); if (!instance->rcv_urb) { - dbg("cxacru_bind: no memory for rcv_urb"); + usb_dbg(usbatm_instance, "cxacru_bind: no memory for rcv_urb\n"); ret = -ENOMEM; goto fail; } instance->snd_urb = usb_alloc_urb(0, GFP_KERNEL); if (!instance->snd_urb) { - dbg("cxacru_bind: no memory for snd_urb"); + usb_dbg(usbatm_instance, "cxacru_bind: no memory for snd_urb\n"); ret = -ENOMEM; goto fail; } if (!cmd_ep) { - dbg("cxacru_bind: no command endpoint"); + usb_dbg(usbatm_instance, "cxacru_bind: no command endpoint\n"); ret = -ENODEV; goto fail; } @@ -1227,10 +1227,10 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance, struct cxacru_data *instance = usbatm_instance->driver_data; int is_polling = 1; - dbg("cxacru_unbind entered"); + usb_dbg(usbatm_instance, "cxacru_unbind entered\n"); if (!instance) { - dbg("cxacru_unbind: NULL instance!"); + usb_dbg(usbatm_instance, "cxacru_unbind: NULL instance!\n"); return; } diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 98dd9e49b684..975e9c6691d6 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -170,7 +170,7 @@ static void speedtch_set_swbuff(struct speedtch_instance_data *instance, int sta "%sabling SW buffering: usb_control_msg returned %d\n", state ? "En" : "Dis", ret); else - dbg("speedtch_set_swbuff: %sbled SW buffering", state ? "En" : "Dis"); + usb_dbg(usbatm, "speedtch_set_swbuff: %sbled SW buffering\n", state ? "En" : "Dis"); } static void speedtch_test_sequence(struct speedtch_instance_data *instance) diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 01ea5d7421d4..d7e422dc0ef7 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -1357,10 +1357,8 @@ static int uea_stat_e1(struct uea_softc *sc) /* release the dsp firmware as it is not needed until * the next failure */ - if (sc->dsp_firm) { - release_firmware(sc->dsp_firm); - sc->dsp_firm = NULL; - } + release_firmware(sc->dsp_firm); + sc->dsp_firm = NULL; } /* always update it as atm layer could not be init when we switch to @@ -1496,10 +1494,8 @@ static int uea_stat_e4(struct uea_softc *sc) /* release the dsp firmware as it is not needed until * the next failure */ - if (sc->dsp_firm) { - release_firmware(sc->dsp_firm); - sc->dsp_firm = NULL; - } + release_firmware(sc->dsp_firm); + sc->dsp_firm = NULL; } /* always update it as atm layer could not be init when we switch to @@ -2240,8 +2236,7 @@ static void uea_stop(struct uea_softc *sc) /* flush the work item, when no one can schedule it */ flush_work_sync(&sc->task); - if (sc->dsp_firm) - release_firmware(sc->dsp_firm); + release_firmware(sc->dsp_firm); uea_leaves(INS_TO_USBDEV(sc)); } diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index d3448ca110ce..ee62b3576f94 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -86,7 +86,7 @@ #ifdef VERBOSE_DEBUG static int usbatm_print_packet(const unsigned char *data, int len); #define PACKETDEBUG(arg...) usbatm_print_packet(arg) -#define vdbg(arg...) dbg(arg) +#define vdbg(arg...) dev_dbg(arg) #else #define PACKETDEBUG(arg...) #define vdbg(arg...) @@ -714,7 +714,7 @@ static void usbatm_destroy_instance(struct kref *kref) { struct usbatm_data *instance = container_of(kref, struct usbatm_data, refcount); - dbg("%s", __func__); + usb_dbg(instance, "%s\n", __func__); tasklet_kill(&instance->rx_channel.tasklet); tasklet_kill(&instance->tx_channel.tasklet); @@ -724,14 +724,14 @@ static void usbatm_destroy_instance(struct kref *kref) static void usbatm_get_instance(struct usbatm_data *instance) { - dbg("%s", __func__); + usb_dbg(instance, "%s\n", __func__); kref_get(&instance->refcount); } static void usbatm_put_instance(struct usbatm_data *instance) { - dbg("%s", __func__); + usb_dbg(instance, "%s\n", __func__); kref_put(&instance->refcount, usbatm_destroy_instance); } @@ -745,11 +745,10 @@ static void usbatm_atm_dev_close(struct atm_dev *atm_dev) { struct usbatm_data *instance = atm_dev->dev_data; - dbg("%s", __func__); - if (!instance) return; + usb_dbg(instance, "%s\n", __func__); atm_dev->dev_data = NULL; /* catch bugs */ usbatm_put_instance(instance); /* taken in usbatm_atm_init */ } @@ -759,10 +758,8 @@ static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *pag struct usbatm_data *instance = atm_dev->dev_data; int left = *pos; - if (!instance) { - dbg("%s: NULL instance!", __func__); + if (!instance) return -ENODEV; - } if (!left--) return sprintf(page, "%s\n", instance->description); @@ -804,10 +801,8 @@ static int usbatm_atm_open(struct atm_vcc *vcc) int vci = vcc->vci; short vpi = vcc->vpi; - if (!instance) { - dbg("%s: NULL data!", __func__); + if (!instance) return -ENODEV; - } atm_dbg(instance, "%s: vpi %hd, vci %d\n", __func__, vpi, vci); @@ -884,10 +879,8 @@ static void usbatm_atm_close(struct atm_vcc *vcc) struct usbatm_data *instance = vcc->dev->dev_data; struct usbatm_vcc_data *vcc_data = vcc->dev_data; - if (!instance || !vcc_data) { - dbg("%s: NULL data!", __func__); + if (!instance || !vcc_data) return; - } atm_dbg(instance, "%s entered\n", __func__); @@ -929,10 +922,8 @@ static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, { struct usbatm_data *instance = atm_dev->dev_data; - if (!instance || instance->disconnected) { - dbg("%s: %s!", __func__, instance ? "disconnected" : "NULL instance"); + if (!instance || instance->disconnected) return -ENODEV; - } switch (cmd) { case ATM_QUERYLOOP: @@ -1336,8 +1327,6 @@ EXPORT_SYMBOL_GPL(usbatm_usb_disconnect); static int __init usbatm_usb_init(void) { - dbg("%s: driver version %s", __func__, DRIVER_VERSION); - if (sizeof(struct usbatm_control) > FIELD_SIZEOF(struct sk_buff, cb)) { printk(KERN_ERR "%s unusable with this kernel!\n", usbatm_driver_name); return -EIO; @@ -1357,7 +1346,6 @@ module_init(usbatm_usb_init); static void __exit usbatm_usb_exit(void) { - dbg("%s", __func__); } module_exit(usbatm_usb_exit); diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c index 48ee0c5ff282..14ec9f0c5924 100644 --- a/drivers/usb/atm/xusbatm.c +++ b/drivers/usb/atm/xusbatm.c @@ -187,8 +187,6 @@ static int __init xusbatm_init(void) { int i; - dbg("xusbatm_init"); - if (!num_vendor || num_vendor != num_product || num_vendor != num_rx_endpoint || @@ -221,8 +219,6 @@ module_init(xusbatm_init); static void __exit xusbatm_exit(void) { - dbg("xusbatm_exit entered"); - usb_deregister(&xusbatm_usb_driver); } module_exit(xusbatm_exit); diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index c6f6560d436c..5d151653ae43 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -157,8 +157,9 @@ static void wdm_out_callback(struct urb *urb) spin_lock(&desc->iuspin); desc->werr = urb->status; spin_unlock(&desc->iuspin); - clear_bit(WDM_IN_USE, &desc->flags); kfree(desc->outbuf); + desc->outbuf = NULL; + clear_bit(WDM_IN_USE, &desc->flags); wake_up(&desc->wait); } @@ -338,7 +339,7 @@ static ssize_t wdm_write if (we < 0) return -EIO; - desc->outbuf = buf = kmalloc(count, GFP_KERNEL); + buf = kmalloc(count, GFP_KERNEL); if (!buf) { rv = -ENOMEM; goto outnl; @@ -368,6 +369,7 @@ static ssize_t wdm_write r = usb_autopm_get_interface(desc->intf); if (r < 0) { kfree(buf); + rv = usb_translate_errors(r); goto outnp; } @@ -383,6 +385,7 @@ static ssize_t wdm_write if (r < 0) { kfree(buf); + rv = r; goto out; } @@ -406,12 +409,15 @@ static ssize_t wdm_write req->wIndex = desc->inum; req->wLength = cpu_to_le16(count); set_bit(WDM_IN_USE, &desc->flags); + desc->outbuf = buf; rv = usb_submit_urb(desc->command, GFP_KERNEL); if (rv < 0) { kfree(buf); + desc->outbuf = NULL; clear_bit(WDM_IN_USE, &desc->flags); dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv); + rv = usb_translate_errors(rv); } else { dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d", req->wIndex); @@ -531,7 +537,7 @@ static int wdm_flush(struct file *file, fl_owner_t id) dev_err(&desc->intf->dev, "Error in flush path: %d\n", desc->werr); - return desc->werr; + return usb_translate_errors(desc->werr); } static unsigned int wdm_poll(struct file *file, struct poll_table_struct *wait) @@ -593,6 +599,7 @@ static int wdm_open(struct inode *inode, struct file *file) desc->count--; dev_err(&desc->intf->dev, "Error submitting int urb - %d\n", rv); + rv = usb_translate_errors(rv); } } else { rv = 0; @@ -620,8 +627,12 @@ static int wdm_release(struct inode *inode, struct file *file) if (!desc->count) { dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); kill_urbs(desc); - if (!test_bit(WDM_DISCONNECTING, &desc->flags)) + if (!test_bit(WDM_DISCONNECTING, &desc->flags)) { desc->manage_power(desc->intf, 0); + } else { + dev_dbg(&desc->intf->dev, "%s: device gone - cleaning up\n", __func__); + cleanup(desc); + } } mutex_unlock(&wdm_mutex); return 0; @@ -895,6 +906,8 @@ static void wdm_disconnect(struct usb_interface *intf) mutex_unlock(&desc->rlock); if (!desc->count) cleanup(desc); + else + dev_dbg(&intf->dev, "%s: %d open files - postponing cleanup\n", __func__, desc->count); mutex_unlock(&wdm_mutex); } diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index a68c1a63dc65..d4c47d5d7625 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -172,27 +172,31 @@ struct usblp { #ifdef DEBUG static void usblp_dump(struct usblp *usblp) { + struct device *dev = &usblp->intf->dev; int p; - dbg("usblp=0x%p", usblp); - dbg("dev=0x%p", usblp->dev); - dbg("present=%d", usblp->present); - dbg("readbuf=0x%p", usblp->readbuf); - dbg("readcount=%d", usblp->readcount); - dbg("ifnum=%d", usblp->ifnum); - for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) { - dbg("protocol[%d].alt_setting=%d", p, usblp->protocol[p].alt_setting); - dbg("protocol[%d].epwrite=%p", p, usblp->protocol[p].epwrite); - dbg("protocol[%d].epread=%p", p, usblp->protocol[p].epread); - } - dbg("current_protocol=%d", usblp->current_protocol); - dbg("minor=%d", usblp->minor); - dbg("wstatus=%d", usblp->wstatus); - dbg("rstatus=%d", usblp->rstatus); - dbg("quirks=%d", usblp->quirks); - dbg("used=%d", usblp->used); - dbg("bidir=%d", usblp->bidir); - dbg("device_id_string=\"%s\"", + dev_dbg(dev, "usblp=0x%p\n", usblp); + dev_dbg(dev, "dev=0x%p\n", usblp->dev); + dev_dbg(dev, "present=%d\n", usblp->present); + dev_dbg(dev, "readbuf=0x%p\n", usblp->readbuf); + dev_dbg(dev, "readcount=%d\n", usblp->readcount); + dev_dbg(dev, "ifnum=%d\n", usblp->ifnum); + for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) { + dev_dbg(dev, "protocol[%d].alt_setting=%d\n", p, + usblp->protocol[p].alt_setting); + dev_dbg(dev, "protocol[%d].epwrite=%p\n", p, + usblp->protocol[p].epwrite); + dev_dbg(dev, "protocol[%d].epread=%p\n", p, + usblp->protocol[p].epread); + } + dev_dbg(dev, "current_protocol=%d\n", usblp->current_protocol); + dev_dbg(dev, "minor=%d\n", usblp->minor); + dev_dbg(dev, "wstatus=%d\n", usblp->wstatus); + dev_dbg(dev, "rstatus=%d\n", usblp->rstatus); + dev_dbg(dev, "quirks=%d\n", usblp->quirks); + dev_dbg(dev, "used=%d\n", usblp->used); + dev_dbg(dev, "bidir=%d\n", usblp->bidir); + dev_dbg(dev, "device_id_string=\"%s\"\n", usblp->device_id_string ? usblp->device_id_string + 2 : (unsigned char *)"(null)"); @@ -262,7 +266,8 @@ static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, i retval = usb_control_msg(usblp->dev, dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0), request, type | dir | recip, value, index, buf, len, USBLP_CTL_TIMEOUT); - dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d idx: %d len: %#x result: %d", + dev_dbg(&usblp->intf->dev, + "usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d idx: %d len: %#x result: %d\n", request, !!dir, recip, value, index, len, retval); return retval < 0 ? retval : 0; } @@ -500,8 +505,9 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) goto done; } - dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd), - _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd)); + dev_dbg(&usblp->intf->dev, + "usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)\n", cmd, + _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd)); if (_IOC_TYPE(cmd) == 'P') /* new-style ioctl number */ @@ -594,7 +600,8 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) goto done; } - dbg("usblp%d requested/got HP channel %ld/%d", + dev_dbg(&usblp->intf->dev, + "usblp%d requested/got HP channel %ld/%d\n", usblp->minor, arg, newChannel); break; @@ -614,7 +621,8 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) goto done; } - dbg("usblp%d is bus=%d, device=%d", + dev_dbg(&usblp->intf->dev, + "usblp%d is bus=%d, device=%d\n", usblp->minor, twoints[0], twoints[1]); break; @@ -634,7 +642,8 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) goto done; } - dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X", + dev_dbg(&usblp->intf->dev, + "usblp%d is VID=0x%4.4X, PID=0x%4.4X\n", usblp->minor, twoints[0], twoints[1]); break; @@ -987,7 +996,7 @@ static int usblp_submit_read(struct usblp *usblp) usblp->rcomplete = 0; spin_unlock_irqrestore(&usblp->lock, flags); if ((rc = usb_submit_urb(urb, GFP_KERNEL)) < 0) { - dbg("error submitting urb (%d)", rc); + dev_dbg(&usblp->intf->dev, "error submitting urb (%d)\n", rc); spin_lock_irqsave(&usblp->lock, flags); usblp->rstatus = rc; usblp->rcomplete = 1; @@ -1129,7 +1138,8 @@ static int usblp_probe(struct usb_interface *intf, /* Analyze and pick initial alternate settings and endpoints. */ protocol = usblp_select_alts(usblp); if (protocol < 0) { - dbg("incompatible printer-class device 0x%4.4X/0x%4.4X", + dev_dbg(&intf->dev, + "incompatible printer-class device 0x%4.4X/0x%4.4X\n", le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct)); retval = -ENODEV; @@ -1158,14 +1168,14 @@ static int usblp_probe(struct usb_interface *intf, retval = usb_register_dev(intf, &usblp_class); if (retval) { - printk(KERN_ERR "usblp: Not able to get a minor" - " (base %u, slice default): %d\n", - USBLP_MINOR_BASE, retval); + dev_err(&intf->dev, + "usblp: Not able to get a minor (base %u, slice default): %d\n", + USBLP_MINOR_BASE, retval); goto abort_intfdata; } usblp->minor = intf->minor; - printk(KERN_INFO "usblp%d: USB %sdirectional printer dev %d " - "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X\n", + dev_info(&intf->dev, + "usblp%d: USB %sdirectional printer dev %d if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X\n", usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, usblp->ifnum, usblp->protocol[usblp->current_protocol].alt_setting, @@ -1302,7 +1312,8 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol) usblp->bidir = (usblp->protocol[protocol].epread != NULL); usblp->current_protocol = protocol; - dbg("usblp%d set protocol %d", usblp->minor, protocol); + dev_dbg(&usblp->intf->dev, "usblp%d set protocol %d\n", + usblp->minor, protocol); return 0; } @@ -1315,7 +1326,8 @@ static int usblp_cache_device_id_string(struct usblp *usblp) err = usblp_get_id(usblp, 0, usblp->device_id_string, USBLP_DEVICE_ID_SIZE - 1); if (err < 0) { - dbg("usblp%d: error = %d reading IEEE-1284 Device ID string", + dev_dbg(&usblp->intf->dev, + "usblp%d: error = %d reading IEEE-1284 Device ID string\n", usblp->minor, err); usblp->device_id_string[0] = usblp->device_id_string[1] = '\0'; return -EIO; @@ -1331,7 +1343,7 @@ static int usblp_cache_device_id_string(struct usblp *usblp) length = USBLP_DEVICE_ID_SIZE - 1; usblp->device_id_string[length] = '\0'; - dbg("usblp%d Device ID string [len=%d]=\"%s\"", + dev_dbg(&usblp->intf->dev, "usblp%d Device ID string [len=%d]=\"%s\"\n", usblp->minor, length, &usblp->device_id_string[2]); return length; diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 18d02e32a3d5..fe46fc09defc 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -27,58 +27,6 @@ config USB_ANNOUNCE_NEW_DEVICES comment "Miscellaneous USB options" depends on USB -config USB_DEVICEFS - bool "USB device filesystem (DEPRECATED)" - depends on USB - ---help--- - If you say Y here (and to "/proc file system support" in the "File - systems" section, above), you will get a file /proc/bus/usb/devices - which lists the devices currently connected to your USB bus or - busses, and for every connected device a file named - "/proc/bus/usb/xxx/yyy", where xxx is the bus number and yyy the - device number; the latter files can be used by user space programs - to talk directly to the device. These files are "virtual", meaning - they are generated on the fly and not stored on the hard drive. - - You may need to mount the usbfs file system to see the files, use - mount -t usbfs none /proc/bus/usb - - For the format of the various /proc/bus/usb/ files, please read - <file:Documentation/usb/proc_usb_info.txt>. - - Modern Linux systems do not use this. - - Usbfs entries are files and not character devices; usbfs can't - handle Access Control Lists (ACL) which are the default way to - grant access to USB devices for untrusted users of a desktop - system. - - The usbfs functionality is replaced by real device-nodes managed by - udev. These nodes lived in /dev/bus/usb and are used by libusb. - -config USB_DEVICE_CLASS - bool "USB device class-devices (DEPRECATED)" - depends on USB - default y - ---help--- - Userspace access to USB devices is granted by device-nodes exported - directly from the usbdev in sysfs. Old versions of the driver - core and udev needed additional class devices to export device nodes. - - These additional devices are difficult to handle in userspace, if - information about USB interfaces must be available. One device - contains the device node, the other device contains the interface - data. Both devices are at the same level in sysfs (siblings) and one - can't access the other. The device node created directly by the - usb device is the parent device of the interface and therefore - easily accessible from the interface event. - - This option provides backward compatibility for libusb device - nodes (lsusb) when usbfs is not used, and the following udev rule - doesn't exist: - SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", \ - NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0644" - config USB_DYNAMIC_MINORS bool "Dynamic USB minor allocation" depends on USB diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index 507a4e1b6360..c4ea846d3c02 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile @@ -9,6 +9,5 @@ usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o usbcore-y += devio.o notify.o generic.o quirks.o devices.o usbcore-$(CONFIG_PCI) += hcd-pci.o -usbcore-$(CONFIG_USB_DEVICEFS) += inode.o obj-$(CONFIG_USB) += usbcore.o diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 8df4b76465ac..c4a1af8a954b 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -727,17 +727,6 @@ static int usbdev_open(struct inode *inode, struct file *file) if (imajor(inode) == USB_DEVICE_MAJOR) dev = usbdev_lookup_by_devt(inode->i_rdev); -#ifdef CONFIG_USB_DEVICEFS - /* procfs file */ - if (!dev) { - dev = inode->i_private; - if (dev && dev->usbfs_dentry && - dev->usbfs_dentry->d_inode == inode) - usb_get_dev(dev); - else - dev = NULL; - } -#endif mutex_unlock(&usbfs_mutex); if (!dev) @@ -2062,44 +2051,13 @@ static void usbdev_remove(struct usb_device *udev) } } -#ifdef CONFIG_USB_DEVICE_CLASS -static struct class *usb_classdev_class; - -static int usb_classdev_add(struct usb_device *dev) -{ - struct device *cldev; - - cldev = device_create(usb_classdev_class, &dev->dev, dev->dev.devt, - NULL, "usbdev%d.%d", dev->bus->busnum, - dev->devnum); - if (IS_ERR(cldev)) - return PTR_ERR(cldev); - dev->usb_classdev = cldev; - return 0; -} - -static void usb_classdev_remove(struct usb_device *dev) -{ - if (dev->usb_classdev) - device_unregister(dev->usb_classdev); -} - -#else -#define usb_classdev_add(dev) 0 -#define usb_classdev_remove(dev) do {} while (0) - -#endif - static int usbdev_notify(struct notifier_block *self, unsigned long action, void *dev) { switch (action) { case USB_DEVICE_ADD: - if (usb_classdev_add(dev)) - return NOTIFY_BAD; break; case USB_DEVICE_REMOVE: - usb_classdev_remove(dev); usbdev_remove(dev); break; } @@ -2129,21 +2087,6 @@ int __init usb_devio_init(void) USB_DEVICE_MAJOR); goto error_cdev; } -#ifdef CONFIG_USB_DEVICE_CLASS - usb_classdev_class = class_create(THIS_MODULE, "usb_device"); - if (IS_ERR(usb_classdev_class)) { - printk(KERN_ERR "Unable to register usb_device class\n"); - retval = PTR_ERR(usb_classdev_class); - cdev_del(&usb_device_cdev); - usb_classdev_class = NULL; - goto out; - } - /* devices of this class shadow the major:minor of their parent - * device, so clear ->dev_kobj to prevent adding duplicate entries - * to /sys/dev - */ - usb_classdev_class->dev_kobj = NULL; -#endif usb_register_notify(&usbdev_nb); out: return retval; @@ -2156,9 +2099,6 @@ error_cdev: void usb_devio_cleanup(void) { usb_unregister_notify(&usbdev_nb); -#ifdef CONFIG_USB_DEVICE_CLASS - class_destroy(usb_classdev_class); -#endif cdev_del(&usb_device_cdev); unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); } diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 9a56635dc19c..112a7ae5095c 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -726,16 +726,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) return -ENODEV; } -#ifdef CONFIG_USB_DEVICEFS - /* If this is available, userspace programs can directly read - * all the device descriptors we don't tell them about. Or - * act as usermode drivers. - */ - if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d", - usb_dev->bus->busnum, usb_dev->devnum)) - return -ENOMEM; -#endif - /* per-device configurations are common */ if (add_uevent_var(env, "PRODUCT=%x/%x/%x", le16_to_cpu(usb_dev->descriptor.idVendor), @@ -788,15 +778,13 @@ int usb_register_device_driver(struct usb_device_driver *new_udriver, retval = driver_register(&new_udriver->drvwrap.driver); - if (!retval) { + if (!retval) pr_info("%s: registered new device driver %s\n", usbcore_name, new_udriver->name); - usbfs_update_special(); - } else { + else printk(KERN_ERR "%s: error %d registering device " " driver %s\n", usbcore_name, retval, new_udriver->name); - } return retval; } @@ -815,7 +803,6 @@ void usb_deregister_device_driver(struct usb_device_driver *udriver) usbcore_name, udriver->name); driver_unregister(&udriver->drvwrap.driver); - usbfs_update_special(); } EXPORT_SYMBOL_GPL(usb_deregister_device_driver); @@ -856,8 +843,6 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner, if (retval) goto out; - usbfs_update_special(); - retval = usb_create_newid_files(new_driver); if (retval) goto out_newid; @@ -897,8 +882,6 @@ void usb_deregister(struct usb_driver *driver) usb_remove_newid_files(driver); driver_unregister(&driver->drvwrap.driver); usb_free_dynids(driver); - - usbfs_update_special(); } EXPORT_SYMBOL_GPL(usb_deregister); diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index d95760de9e8b..e673b26e598f 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -183,7 +183,7 @@ int usb_register_dev(struct usb_interface *intf, if (retval) return retval; - dev_dbg(&intf->dev, "looking for a minor, starting at %d", minor_base); + dev_dbg(&intf->dev, "looking for a minor, starting at %d\n", minor_base); down_write(&minor_rwsem); for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) { @@ -239,7 +239,7 @@ void usb_deregister_dev(struct usb_interface *intf, if (intf->minor == -1) return; - dbg ("removing %d minor", intf->minor); + dev_dbg(&intf->dev, "removing %d minor\n", intf->minor); down_write(&minor_rwsem); usb_minors[intf->minor] = NULL; diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 622b4a48e732..57ed9e400c06 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -493,6 +493,15 @@ static int hcd_pci_suspend_noirq(struct device *dev) pci_save_state(pci_dev); + /* + * Some systems crash if an EHCI controller is in D3 during + * a sleep transition. We have to leave such controllers in D0. + */ + if (hcd->broken_pci_sleep) { + dev_dbg(dev, "Staying in PCI D0\n"); + return retval; + } + /* If the root hub is dead rather than suspended, disallow remote * wakeup. usb_hc_died() should ensure that both hosts are marked as * dying, so we only need to check the primary roothub. diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c deleted file mode 100644 index d2b9af59cba9..000000000000 --- a/drivers/usb/core/inode.c +++ /dev/null @@ -1,748 +0,0 @@ -/*****************************************************************************/ - -/* - * inode.c -- Inode/Dentry functions for the USB device file system. - * - * Copyright (C) 2000 Thomas Sailer (sailer@ife.ee.ethz.ch) - * Copyright (C) 2001,2002,2004 Greg Kroah-Hartman (greg@kroah.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * History: - * 0.1 04.01.2000 Created - * 0.2 10.12.2001 converted to use the vfs layer better - */ - -/*****************************************************************************/ - -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/mount.h> -#include <linux/pagemap.h> -#include <linux/init.h> -#include <linux/proc_fs.h> -#include <linux/usb.h> -#include <linux/namei.h> -#include <linux/usbdevice_fs.h> -#include <linux/parser.h> -#include <linux/notifier.h> -#include <linux/seq_file.h> -#include <linux/usb/hcd.h> -#include <asm/byteorder.h> -#include "usb.h" - -#define USBFS_DEFAULT_DEVMODE (S_IWUSR | S_IRUGO) -#define USBFS_DEFAULT_BUSMODE (S_IXUGO | S_IRUGO) -#define USBFS_DEFAULT_LISTMODE S_IRUGO - -static const struct file_operations default_file_operations; -static struct vfsmount *usbfs_mount; -static int usbfs_mount_count; /* = 0 */ - -static struct dentry *devices_usbfs_dentry; -static int num_buses; /* = 0 */ - -static uid_t devuid; /* = 0 */ -static uid_t busuid; /* = 0 */ -static uid_t listuid; /* = 0 */ -static gid_t devgid; /* = 0 */ -static gid_t busgid; /* = 0 */ -static gid_t listgid; /* = 0 */ -static umode_t devmode = USBFS_DEFAULT_DEVMODE; -static umode_t busmode = USBFS_DEFAULT_BUSMODE; -static umode_t listmode = USBFS_DEFAULT_LISTMODE; - -static int usbfs_show_options(struct seq_file *seq, struct dentry *root) -{ - if (devuid != 0) - seq_printf(seq, ",devuid=%u", devuid); - if (devgid != 0) - seq_printf(seq, ",devgid=%u", devgid); - if (devmode != USBFS_DEFAULT_DEVMODE) - seq_printf(seq, ",devmode=%o", devmode); - if (busuid != 0) - seq_printf(seq, ",busuid=%u", busuid); - if (busgid != 0) - seq_printf(seq, ",busgid=%u", busgid); - if (busmode != USBFS_DEFAULT_BUSMODE) - seq_printf(seq, ",busmode=%o", busmode); - if (listuid != 0) - seq_printf(seq, ",listuid=%u", listuid); - if (listgid != 0) - seq_printf(seq, ",listgid=%u", listgid); - if (listmode != USBFS_DEFAULT_LISTMODE) - seq_printf(seq, ",listmode=%o", listmode); - - return 0; -} - -enum { - Opt_devuid, Opt_devgid, Opt_devmode, - Opt_busuid, Opt_busgid, Opt_busmode, - Opt_listuid, Opt_listgid, Opt_listmode, - Opt_err, -}; - -static const match_table_t tokens = { - {Opt_devuid, "devuid=%u"}, - {Opt_devgid, "devgid=%u"}, - {Opt_devmode, "devmode=%o"}, - {Opt_busuid, "busuid=%u"}, - {Opt_busgid, "busgid=%u"}, - {Opt_busmode, "busmode=%o"}, - {Opt_listuid, "listuid=%u"}, - {Opt_listgid, "listgid=%u"}, - {Opt_listmode, "listmode=%o"}, - {Opt_err, NULL} -}; - -static int parse_options(struct super_block *s, char *data) -{ - char *p; - int option; - - /* (re)set to defaults. */ - devuid = 0; - busuid = 0; - listuid = 0; - devgid = 0; - busgid = 0; - listgid = 0; - devmode = USBFS_DEFAULT_DEVMODE; - busmode = USBFS_DEFAULT_BUSMODE; - listmode = USBFS_DEFAULT_LISTMODE; - - while ((p = strsep(&data, ",")) != NULL) { - substring_t args[MAX_OPT_ARGS]; - int token; - if (!*p) - continue; - - token = match_token(p, tokens, args); - switch (token) { - case Opt_devuid: - if (match_int(&args[0], &option)) - return -EINVAL; - devuid = option; - break; - case Opt_devgid: - if (match_int(&args[0], &option)) - return -EINVAL; - devgid = option; - break; - case Opt_devmode: - if (match_octal(&args[0], &option)) - return -EINVAL; - devmode = option & S_IRWXUGO; - break; - case Opt_busuid: - if (match_int(&args[0], &option)) - return -EINVAL; - busuid = option; - break; - case Opt_busgid: - if (match_int(&args[0], &option)) - return -EINVAL; - busgid = option; - break; - case Opt_busmode: - if (match_octal(&args[0], &option)) - return -EINVAL; - busmode = option & S_IRWXUGO; - break; - case Opt_listuid: - if (match_int(&args[0], &option)) - return -EINVAL; - listuid = option; - break; - case Opt_listgid: - if (match_int(&args[0], &option)) - return -EINVAL; - listgid = option; - break; - case Opt_listmode: - if (match_octal(&args[0], &option)) - return -EINVAL; - listmode = option & S_IRWXUGO; - break; - default: - printk(KERN_ERR "usbfs: unrecognised mount option " - "\"%s\" or missing value\n", p); - return -EINVAL; - } - } - - return 0; -} - -static void update_special(struct dentry *special) -{ - special->d_inode->i_uid = listuid; - special->d_inode->i_gid = listgid; - special->d_inode->i_mode = S_IFREG | listmode; -} - -static void update_dev(struct dentry *dev) -{ - dev->d_inode->i_uid = devuid; - dev->d_inode->i_gid = devgid; - dev->d_inode->i_mode = S_IFREG | devmode; -} - -static void update_bus(struct dentry *bus) -{ - struct dentry *dev = NULL; - - bus->d_inode->i_uid = busuid; - bus->d_inode->i_gid = busgid; - bus->d_inode->i_mode = S_IFDIR | busmode; - - mutex_lock(&bus->d_inode->i_mutex); - - list_for_each_entry(dev, &bus->d_subdirs, d_u.d_child) - if (dev->d_inode) - update_dev(dev); - - mutex_unlock(&bus->d_inode->i_mutex); -} - -static void update_sb(struct super_block *sb) -{ - struct dentry *root = sb->s_root; - struct dentry *bus = NULL; - - if (!root) - return; - - mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_PARENT); - - list_for_each_entry(bus, &root->d_subdirs, d_u.d_child) { - if (bus->d_inode) { - switch (S_IFMT & bus->d_inode->i_mode) { - case S_IFDIR: - update_bus(bus); - break; - case S_IFREG: - update_special(bus); - break; - default: - printk(KERN_WARNING "usbfs: Unknown node %s " - "mode %x found on remount!\n", - bus->d_name.name, bus->d_inode->i_mode); - break; - } - } - } - - mutex_unlock(&root->d_inode->i_mutex); -} - -static int remount(struct super_block *sb, int *flags, char *data) -{ - /* If this is not a real mount, - * i.e. it's a simple_pin_fs from create_special_files, - * then ignore it. - */ - if (*flags & MS_KERNMOUNT) - return 0; - - if (parse_options(sb, data)) { - printk(KERN_WARNING "usbfs: mount parameter error.\n"); - return -EINVAL; - } - - if (usbfs_mount) - update_sb(usbfs_mount->mnt_sb); - - return 0; -} - -static struct inode *usbfs_get_inode (struct super_block *sb, umode_t mode, dev_t dev) -{ - struct inode *inode = new_inode(sb); - - if (inode) { - inode->i_ino = get_next_ino(); - inode_init_owner(inode, NULL, mode); - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - switch (mode & S_IFMT) { - default: - init_special_inode(inode, mode, dev); - break; - case S_IFREG: - inode->i_fop = &default_file_operations; - break; - case S_IFDIR: - inode->i_op = &simple_dir_inode_operations; - inode->i_fop = &simple_dir_operations; - - /* directory inodes start off with i_nlink == 2 (for "." entry) */ - inc_nlink(inode); - break; - } - } - return inode; -} - -/* SMP-safe */ -static int usbfs_mknod (struct inode *dir, struct dentry *dentry, umode_t mode, - dev_t dev) -{ - struct inode *inode = usbfs_get_inode(dir->i_sb, mode, dev); - int error = -EPERM; - - if (dentry->d_inode) - return -EEXIST; - - if (inode) { - d_instantiate(dentry, inode); - dget(dentry); - error = 0; - } - return error; -} - -static int usbfs_mkdir (struct inode *dir, struct dentry *dentry, umode_t mode) -{ - int res; - - mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; - res = usbfs_mknod (dir, dentry, mode, 0); - if (!res) - inc_nlink(dir); - return res; -} - -static int usbfs_create (struct inode *dir, struct dentry *dentry, umode_t mode) -{ - mode = (mode & S_IALLUGO) | S_IFREG; - return usbfs_mknod (dir, dentry, mode, 0); -} - -static inline int usbfs_positive (struct dentry *dentry) -{ - return dentry->d_inode && !d_unhashed(dentry); -} - -static int usbfs_empty (struct dentry *dentry) -{ - struct list_head *list; - - spin_lock(&dentry->d_lock); - list_for_each(list, &dentry->d_subdirs) { - struct dentry *de = list_entry(list, struct dentry, d_u.d_child); - - spin_lock_nested(&de->d_lock, DENTRY_D_LOCK_NESTED); - if (usbfs_positive(de)) { - spin_unlock(&de->d_lock); - spin_unlock(&dentry->d_lock); - return 0; - } - spin_unlock(&de->d_lock); - } - spin_unlock(&dentry->d_lock); - return 1; -} - -static int usbfs_unlink (struct inode *dir, struct dentry *dentry) -{ - struct inode *inode = dentry->d_inode; - mutex_lock(&inode->i_mutex); - drop_nlink(dentry->d_inode); - dput(dentry); - mutex_unlock(&inode->i_mutex); - d_delete(dentry); - return 0; -} - -static int usbfs_rmdir(struct inode *dir, struct dentry *dentry) -{ - int error = -ENOTEMPTY; - struct inode * inode = dentry->d_inode; - - mutex_lock(&inode->i_mutex); - dentry_unhash(dentry); - if (usbfs_empty(dentry)) { - dont_mount(dentry); - drop_nlink(dentry->d_inode); - drop_nlink(dentry->d_inode); - dput(dentry); - inode->i_flags |= S_DEAD; - drop_nlink(dir); - error = 0; - } - mutex_unlock(&inode->i_mutex); - if (!error) - d_delete(dentry); - return error; -} - - -/* default file operations */ -static ssize_t default_read_file (struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - return 0; -} - -static ssize_t default_write_file (struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - return count; -} - -static loff_t default_file_lseek (struct file *file, loff_t offset, int orig) -{ - loff_t retval = -EINVAL; - - mutex_lock(&file->f_path.dentry->d_inode->i_mutex); - switch(orig) { - case 0: - if (offset > 0) { - file->f_pos = offset; - retval = file->f_pos; - } - break; - case 1: - if ((offset + file->f_pos) > 0) { - file->f_pos += offset; - retval = file->f_pos; - } - break; - default: - break; - } - mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); - return retval; -} - -static const struct file_operations default_file_operations = { - .read = default_read_file, - .write = default_write_file, - .open = simple_open, - .llseek = default_file_lseek, -}; - -static const struct super_operations usbfs_ops = { - .statfs = simple_statfs, - .drop_inode = generic_delete_inode, - .remount_fs = remount, - .show_options = usbfs_show_options, -}; - -static int usbfs_fill_super(struct super_block *sb, void *data, int silent) -{ - struct inode *inode; - - sb->s_blocksize = PAGE_CACHE_SIZE; - sb->s_blocksize_bits = PAGE_CACHE_SHIFT; - sb->s_magic = USBDEVICE_SUPER_MAGIC; - sb->s_op = &usbfs_ops; - sb->s_time_gran = 1; - inode = usbfs_get_inode(sb, S_IFDIR | 0755, 0); - sb->s_root = d_make_root(inode); - if (!sb->s_root) { - dbg("%s: could not get root dentry!",__func__); - return -ENOMEM; - } - return 0; -} - -/* - * fs_create_by_name - create a file, given a name - * @name: name of file - * @mode: type of file - * @parent: dentry of directory to create it in - * @dentry: resulting dentry of file - * - * This function handles both regular files and directories. - */ -static int fs_create_by_name (const char *name, umode_t mode, - struct dentry *parent, struct dentry **dentry) -{ - int error = 0; - - /* If the parent is not specified, we create it in the root. - * We need the root dentry to do this, which is in the super - * block. A pointer to that is in the struct vfsmount that we - * have around. - */ - if (!parent ) { - if (usbfs_mount) - parent = usbfs_mount->mnt_root; - } - - if (!parent) { - dbg("Ah! can not find a parent!"); - return -EFAULT; - } - - *dentry = NULL; - mutex_lock(&parent->d_inode->i_mutex); - *dentry = lookup_one_len(name, parent, strlen(name)); - if (!IS_ERR(*dentry)) { - if (S_ISDIR(mode)) - error = usbfs_mkdir (parent->d_inode, *dentry, mode); - else - error = usbfs_create (parent->d_inode, *dentry, mode); - } else - error = PTR_ERR(*dentry); - mutex_unlock(&parent->d_inode->i_mutex); - - return error; -} - -static struct dentry *fs_create_file (const char *name, umode_t mode, - struct dentry *parent, void *data, - const struct file_operations *fops, - uid_t uid, gid_t gid) -{ - struct dentry *dentry; - int error; - - dbg("creating file '%s'",name); - - error = fs_create_by_name (name, mode, parent, &dentry); - if (error) { - dentry = NULL; - } else { - if (dentry->d_inode) { - if (data) - dentry->d_inode->i_private = data; - if (fops) - dentry->d_inode->i_fop = fops; - dentry->d_inode->i_uid = uid; - dentry->d_inode->i_gid = gid; - } - } - - return dentry; -} - -static void fs_remove_file (struct dentry *dentry) -{ - struct dentry *parent = dentry->d_parent; - - if (!parent || !parent->d_inode) - return; - - mutex_lock_nested(&parent->d_inode->i_mutex, I_MUTEX_PARENT); - if (usbfs_positive(dentry)) { - if (dentry->d_inode) { - if (S_ISDIR(dentry->d_inode->i_mode)) - usbfs_rmdir(parent->d_inode, dentry); - else - usbfs_unlink(parent->d_inode, dentry); - dput(dentry); - } - } - mutex_unlock(&parent->d_inode->i_mutex); -} - -/* --------------------------------------------------------------------- */ - -static struct dentry *usb_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) -{ - return mount_single(fs_type, flags, data, usbfs_fill_super); -} - -static struct file_system_type usb_fs_type = { - .owner = THIS_MODULE, - .name = "usbfs", - .mount = usb_mount, - .kill_sb = kill_litter_super, -}; - -/* --------------------------------------------------------------------- */ - -static int create_special_files (void) -{ - struct dentry *parent; - int retval; - - /* create the devices special file */ - retval = simple_pin_fs(&usb_fs_type, &usbfs_mount, &usbfs_mount_count); - if (retval) { - printk(KERN_ERR "Unable to get usbfs mount\n"); - goto exit; - } - - parent = usbfs_mount->mnt_root; - devices_usbfs_dentry = fs_create_file ("devices", - listmode | S_IFREG, parent, - NULL, &usbfs_devices_fops, - listuid, listgid); - if (devices_usbfs_dentry == NULL) { - printk(KERN_ERR "Unable to create devices usbfs file\n"); - retval = -ENODEV; - goto error_clean_mounts; - } - - goto exit; - -error_clean_mounts: - simple_release_fs(&usbfs_mount, &usbfs_mount_count); -exit: - return retval; -} - -static void remove_special_files (void) -{ - if (devices_usbfs_dentry) - fs_remove_file (devices_usbfs_dentry); - devices_usbfs_dentry = NULL; - simple_release_fs(&usbfs_mount, &usbfs_mount_count); -} - -void usbfs_update_special (void) -{ - struct inode *inode; - - if (devices_usbfs_dentry) { - inode = devices_usbfs_dentry->d_inode; - if (inode) - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - } -} - -static void usbfs_add_bus(struct usb_bus *bus) -{ - struct dentry *parent; - char name[8]; - int retval; - - /* create the special files if this is the first bus added */ - if (num_buses == 0) { - retval = create_special_files(); - if (retval) - return; - } - ++num_buses; - - sprintf (name, "%03d", bus->busnum); - - parent = usbfs_mount->mnt_root; - bus->usbfs_dentry = fs_create_file (name, busmode | S_IFDIR, parent, - bus, NULL, busuid, busgid); - if (bus->usbfs_dentry == NULL) { - printk(KERN_ERR "Error creating usbfs bus entry\n"); - return; - } -} - -static void usbfs_remove_bus(struct usb_bus *bus) -{ - if (bus->usbfs_dentry) { - fs_remove_file (bus->usbfs_dentry); - bus->usbfs_dentry = NULL; - } - - --num_buses; - if (num_buses <= 0) { - remove_special_files(); - num_buses = 0; - } -} - -static void usbfs_add_device(struct usb_device *dev) -{ - char name[8]; - int i; - int i_size; - - sprintf (name, "%03d", dev->devnum); - dev->usbfs_dentry = fs_create_file (name, devmode | S_IFREG, - dev->bus->usbfs_dentry, dev, - &usbdev_file_operations, - devuid, devgid); - if (dev->usbfs_dentry == NULL) { - printk(KERN_ERR "Error creating usbfs device entry\n"); - return; - } - - /* Set the size of the device's file to be - * equal to the size of the device descriptors. */ - i_size = sizeof (struct usb_device_descriptor); - for (i = 0; i < dev->descriptor.bNumConfigurations; ++i) { - struct usb_config_descriptor *config = - (struct usb_config_descriptor *)dev->rawdescriptors[i]; - i_size += le16_to_cpu(config->wTotalLength); - } - if (dev->usbfs_dentry->d_inode) - dev->usbfs_dentry->d_inode->i_size = i_size; -} - -static void usbfs_remove_device(struct usb_device *dev) -{ - if (dev->usbfs_dentry) { - fs_remove_file (dev->usbfs_dentry); - dev->usbfs_dentry = NULL; - } -} - -static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev) -{ - switch (action) { - case USB_DEVICE_ADD: - usbfs_add_device(dev); - break; - case USB_DEVICE_REMOVE: - usbfs_remove_device(dev); - break; - case USB_BUS_ADD: - usbfs_add_bus(dev); - break; - case USB_BUS_REMOVE: - usbfs_remove_bus(dev); - } - - usbfs_update_special(); - usbfs_conn_disc_event(); - return NOTIFY_OK; -} - -static struct notifier_block usbfs_nb = { - .notifier_call = usbfs_notify, -}; - -/* --------------------------------------------------------------------- */ - -static struct proc_dir_entry *usbdir = NULL; - -int __init usbfs_init(void) -{ - int retval; - - retval = register_filesystem(&usb_fs_type); - if (retval) - return retval; - - usb_register_notify(&usbfs_nb); - - /* create mount point for usbfs */ - usbdir = proc_mkdir("bus/usb", NULL); - - return 0; -} - -void usbfs_cleanup(void) -{ - usb_unregister_notify(&usbfs_nb); - unregister_filesystem(&usb_fs_type); - if (usbdir) - remove_proc_entry("bus/usb", NULL); -} - diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 4c65eb6a867a..32d3adc315f5 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -123,6 +123,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Guillemot Webcam Hercules Dualpix Exchange*/ { USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Midiman M-Audio Keystation 88es */ + { USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME }, + /* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index cd9b3a2cd8a7..9d912bfdcffe 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -681,6 +681,27 @@ void usb_unpoison_urb(struct urb *urb) EXPORT_SYMBOL_GPL(usb_unpoison_urb); /** + * usb_block_urb - reliably prevent further use of an URB + * @urb: pointer to URB to be blocked, may be NULL + * + * After the routine has run, attempts to resubmit the URB will fail + * with error -EPERM. Thus even if the URB's completion handler always + * tries to resubmit, it will not succeed and the URB will become idle. + * + * The URB must not be deallocated while this routine is running. In + * particular, when a driver calls this routine, it must insure that the + * completion handler cannot deallocate the URB. + */ +void usb_block_urb(struct urb *urb) +{ + if (!urb) + return; + + atomic_inc(&urb->reject); +} +EXPORT_SYMBOL_GPL(usb_block_urb); + +/** * usb_kill_anchored_urbs - cancel transfer requests en masse * @anchor: anchor the requests are bound to * diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index c74ba7bbc748..0ce862bfdd77 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -1030,9 +1030,6 @@ static int __init usb_init(void) retval = usb_devio_init(); if (retval) goto usb_devio_init_failed; - retval = usbfs_init(); - if (retval) - goto fs_init_failed; retval = usb_hub_init(); if (retval) goto hub_init_failed; @@ -1042,8 +1039,6 @@ static int __init usb_init(void) usb_hub_cleanup(); hub_init_failed: - usbfs_cleanup(); -fs_init_failed: usb_devio_cleanup(); usb_devio_init_failed: usb_deregister(&usbfs_driver); @@ -1070,7 +1065,6 @@ static void __exit usb_exit(void) usb_deregister_device_driver(&usb_generic_driver); usb_major_cleanup(); - usbfs_cleanup(); usb_deregister(&usbfs_driver); usb_devio_cleanup(); usb_hub_cleanup(); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 6c7945b4cad3..9c5c73aae4f4 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -361,7 +361,6 @@ struct dwc3_ep { dma_addr_t trb_pool_dma; u32 free_slot; u32 busy_slot; - const struct usb_endpoint_descriptor *desc; const struct usb_ss_ep_comp_descriptor *comp_desc; struct dwc3 *dwc; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 3584a169886f..3453ca1f7479 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -179,7 +179,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, int ret; spin_lock_irqsave(&dwc->lock, flags); - if (!dep->desc) { + if (!dep->endpoint.desc) { dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", request, dep->name); ret = -ESHUTDOWN; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5255fe975ea1..561625a1284d 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -178,8 +178,8 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc) if (!(dep->flags & DWC3_EP_ENABLED)) continue; - if (usb_endpoint_xfer_bulk(dep->desc) - || usb_endpoint_xfer_isoc(dep->desc)) + if (usb_endpoint_xfer_bulk(dep->endpoint.desc) + || usb_endpoint_xfer_isoc(dep->endpoint.desc)) mult = 3; /* @@ -229,7 +229,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, * completed (not the LINK TRB). */ if (((dep->busy_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && - usb_endpoint_xfer_isoc(dep->desc)) + usb_endpoint_xfer_isoc(dep->endpoint.desc)) dep->busy_slot++; } list_del(&req->list); @@ -470,7 +470,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, if (ret) return ret; - dep->desc = desc; + dep->endpoint.desc = desc; dep->comp_desc = comp_desc; dep->type = usb_endpoint_type(desc); dep->flags |= DWC3_EP_ENABLED; @@ -533,7 +533,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); dep->stream_capable = false; - dep->desc = NULL; dep->endpoint.desc = NULL; dep->comp_desc = NULL; dep->type = 0; @@ -694,7 +693,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, /* Skip the LINK-TRB on ISOC */ if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && - usb_endpoint_xfer_isoc(dep->desc)) + usb_endpoint_xfer_isoc(dep->endpoint.desc)) return; if (!req->trb) { @@ -707,7 +706,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, trb->bpl = lower_32_bits(dma); trb->bph = upper_32_bits(dma); - switch (usb_endpoint_type(dep->desc)) { + switch (usb_endpoint_type(dep->endpoint.desc)) { case USB_ENDPOINT_XFER_CONTROL: trb->ctrl = DWC3_TRBCTL_CONTROL_SETUP; break; @@ -732,7 +731,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, BUG(); } - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; trb->ctrl |= DWC3_TRB_CTRL_CSP; } else { @@ -743,7 +742,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, trb->ctrl |= DWC3_TRB_CTRL_LST; } - if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) + if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable) trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id); trb->ctrl |= DWC3_TRB_CTRL_HWO; @@ -771,7 +770,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; /* Can't wrap around on a non-isoc EP since there's no link TRB */ - if (!usb_endpoint_xfer_isoc(dep->desc)) { + if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) { max = DWC3_TRB_NUM - (dep->free_slot & DWC3_TRB_MASK); if (trbs_left > max) trbs_left = max; @@ -797,7 +796,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) * processed from the first TRB until the last one. Since we * don't wrap around we have to start at the beginning. */ - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dep->busy_slot = 1; dep->free_slot = 1; } else { @@ -807,7 +806,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) } /* The last TRB is a link TRB, not used for xfer */ - if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->desc)) + if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->endpoint.desc)) return; list_for_each_entry_safe(req, n, &dep->request_list, list) { @@ -984,7 +983,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) int start_trans; start_trans = 1; - if (usb_endpoint_xfer_isoc(dep->desc) && + if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && (dep->flags & DWC3_EP_BUSY)) start_trans = 0; @@ -1011,7 +1010,7 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, int ret; - if (!dep->desc) { + if (!dep->endpoint.desc) { dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", request, ep->name); return -ESHUTDOWN; @@ -1125,7 +1124,7 @@ static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value) spin_lock_irqsave(&dwc->lock, flags); - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name); ret = -EINVAL; goto out; @@ -1681,7 +1680,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, case DWC3_DEPEVT_XFERCOMPLETE: dep->res_trans_idx = 0; - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dev_dbg(dwc->dev, "%s is an Isochronous endpoint\n", dep->name); return; @@ -1690,7 +1689,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dwc3_endpoint_transfer_complete(dwc, dep, event, 1); break; case DWC3_DEPEVT_XFERINPROGRESS: - if (!usb_endpoint_xfer_isoc(dep->desc)) { + if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dev_dbg(dwc->dev, "%s is not an Isochronous endpoint\n", dep->name); return; @@ -1699,7 +1698,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dwc3_endpoint_transfer_complete(dwc, dep, event, 0); break; case DWC3_DEPEVT_XFERNOTREADY: - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dwc3_gadget_start_isoc(dwc, dep, event); } else { int ret; @@ -1720,7 +1719,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, break; case DWC3_DEPEVT_STREAMEVT: - if (!usb_endpoint_xfer_bulk(dep->desc)) { + if (!usb_endpoint_xfer_bulk(dep->endpoint.desc)) { dev_err(dwc->dev, "Stream event for non-Bulk %s\n", dep->name); return; diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 2633f7595116..fb883e1405bc 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -147,6 +147,17 @@ config USB_AT91 dynamically linked module called "at91_udc" and force all gadget drivers to also be dynamically linked. +config USB_LPC32XX + tristate "LPC32XX USB Peripheral Controller" + depends on ARCH_LPC32XX + select USB_ISP1301 + help + This option selects the USB device controller in the LPC32xx SoC. + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "lpc32xx_udc" and force all + gadget drivers to also be dynamically linked. + config USB_ATMEL_USBA tristate "Atmel USBA" select USB_GADGET_DUALSPEED @@ -161,7 +172,7 @@ config USB_FSL_USB2 select USB_GADGET_DUALSPEED select USB_FSL_MPH_DR_OF if OF help - Some of Freescale PowerPC processors have a High Speed + Some of Freescale PowerPC and i.MX processors have a High Speed Dual-Role(DR) USB controller, which supports device mode. The number of programmable endpoints is different through diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index b7f6eefc3927..1565253bfdd2 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_USB_CI13XXX_PCI) += ci13xxx_pci.o obj-$(CONFIG_USB_S3C_HSOTG) += s3c-hsotg.o obj-$(CONFIG_USB_S3C_HSUDC) += s3c-hsudc.o obj-$(CONFIG_USB_LANGWELL) += langwell_udc.o +obj-$(CONFIG_USB_LPC32XX) += lpc32xx_udc.o obj-$(CONFIG_USB_EG20T) += pch_udc.o obj-$(CONFIG_USB_MV_UDC) += mv_udc.o mv_udc-y := mv_udc_core.o diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 77779271f487..187d21181cd5 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -333,7 +333,7 @@ udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc) return -ESHUTDOWN; spin_lock_irqsave(&dev->lock, iflags); - ep->desc = desc; + ep->ep.desc = desc; ep->halted = 0; @@ -442,7 +442,6 @@ static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep) u32 tmp; VDBG(ep->dev, "ep-%d reset\n", ep->num); - ep->desc = NULL; ep->ep.desc = NULL; ep->ep.ops = &udc_ep_ops; INIT_LIST_HEAD(&ep->queue); @@ -489,7 +488,7 @@ static int udc_ep_disable(struct usb_ep *usbep) return -EINVAL; ep = container_of(usbep, struct udc_ep, ep); - if (usbep->name == ep0_string || !ep->desc) + if (usbep->name == ep0_string || !ep->ep.desc) return -EINVAL; DBG(ep->dev, "Disable ep-%d\n", ep->num); @@ -1066,7 +1065,7 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp) return -EINVAL; ep = container_of(usbep, struct udc_ep, ep); - if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX)) + if (!ep->ep.desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX)) return -EINVAL; VDBG(ep->dev, "udc_queue(): ep%d-in=%d\n", ep->num, ep->in); @@ -1257,7 +1256,7 @@ static int udc_dequeue(struct usb_ep *usbep, struct usb_request *usbreq) unsigned long iflags; ep = container_of(usbep, struct udc_ep, ep); - if (!usbep || !usbreq || (!ep->desc && (ep->num != 0 + if (!usbep || !usbreq || (!ep->ep.desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))) return -EINVAL; @@ -1317,7 +1316,7 @@ udc_set_halt(struct usb_ep *usbep, int halt) pr_debug("set_halt %s: halt=%d\n", usbep->name, halt); ep = container_of(usbep, struct udc_ep, ep); - if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX)) + if (!ep->ep.desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX)) return -EINVAL; if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; @@ -1539,7 +1538,7 @@ static void udc_setup_endpoints(struct udc *dev) * disabling ep interrupts when ENUM interrupt occurs but ep is * not enabled by gadget driver */ - if (!ep->desc) + if (!ep->ep.desc) ep_init(dev->regs, ep); if (use_dma) { @@ -3402,19 +3401,7 @@ static struct pci_driver udc_pci_driver = { .remove = udc_pci_remove, }; -/* Inits driver */ -static int __init init(void) -{ - return pci_register_driver(&udc_pci_driver); -} -module_init(init); - -/* Cleans driver */ -static void __exit cleanup(void) -{ - pci_unregister_driver(&udc_pci_driver); -} -module_exit(cleanup); +module_pci_driver(udc_pci_driver); MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION); MODULE_AUTHOR("Thomas Dahlmann"); diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/amd5536udc.h index f87e29c65325..14af87d65caa 100644 --- a/drivers/usb/gadget/amd5536udc.h +++ b/drivers/usb/gadget/amd5536udc.h @@ -512,7 +512,6 @@ struct udc_ep { /* queue for requests */ struct list_head queue; - const struct usb_endpoint_descriptor *desc; unsigned halted; unsigned cancel_transfer; unsigned num : 5, diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 9d7bcd910074..43943aa965dc 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -212,7 +212,7 @@ static int proc_udc_show(struct seq_file *s, void *unused) if (udc->enabled && udc->vbus) { proc_ep_show(s, &udc->ep[0]); list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) { - if (ep->desc) + if (ep->ep.desc) proc_ep_show(s, ep); } } @@ -530,7 +530,7 @@ ok: tmp |= AT91_UDP_EPEDS; __raw_writel(tmp, ep->creg); - ep->desc = desc; + ep->ep.desc = desc; ep->ep.maxpacket = maxpacket; /* @@ -558,7 +558,6 @@ static int at91_ep_disable (struct usb_ep * _ep) nuke(ep, -ESHUTDOWN); /* restore the endpoint's pristine config */ - ep->desc = NULL; ep->ep.desc = NULL; ep->ep.maxpacket = ep->maxpacket; @@ -618,7 +617,7 @@ static int at91_ep_queue(struct usb_ep *_ep, return -EINVAL; } - if (!_ep || (!ep->desc && ep->ep.name != ep0name)) { + if (!_ep || (!ep->ep.desc && ep->ep.name != ep0name)) { DBG("invalid ep\n"); return -EINVAL; } @@ -833,7 +832,7 @@ static void udc_reinit(struct at91_udc *udc) if (i != 0) list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); - ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 0; ep->fifo_bank = 0; ep->ep.maxpacket = ep->maxpacket; @@ -978,18 +977,18 @@ static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on) return 0; } -static int at91_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); -static int at91_stop(struct usb_gadget_driver *driver); - +static int at91_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); +static int at91_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); static const struct usb_gadget_ops at91_udc_ops = { .get_frame = at91_get_frame, .wakeup = at91_wakeup, .set_selfpowered = at91_set_selfpowered, .vbus_session = at91_vbus_session, .pullup = at91_pullup, - .start = at91_start, - .stop = at91_stop, + .udc_start = at91_start, + .udc_stop = at91_stop, /* * VBUS-powered devices may also also want to support bigger @@ -1172,7 +1171,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) | USB_REQ_GET_STATUS: tmp = w_index & USB_ENDPOINT_NUMBER_MASK; ep = &udc->ep[tmp]; - if (tmp >= NUM_ENDPOINTS || (tmp && !ep->desc)) + if (tmp >= NUM_ENDPOINTS || (tmp && !ep->ep.desc)) goto stall; if (tmp) { @@ -1197,7 +1196,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) ep = &udc->ep[tmp]; if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS) goto stall; - if (!ep->desc || ep->is_iso) + if (!ep->ep.desc || ep->is_iso) goto stall; if ((w_index & USB_DIR_IN)) { if (!ep->is_in) @@ -1218,7 +1217,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) goto stall; if (tmp == 0) goto succeed; - if (!ep->desc || ep->is_iso) + if (!ep->ep.desc || ep->is_iso) goto stall; if ((w_index & USB_DIR_IN)) { if (!ep->is_in) @@ -1627,66 +1626,34 @@ static void at91_vbus_timer(unsigned long data) schedule_work(&udc->vbus_timer_work); } -static int at91_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) +static int at91_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct at91_udc *udc = &controller; - int retval; - unsigned long flags; - - if (!driver - || driver->max_speed < USB_SPEED_FULL - || !bind - || !driver->setup) { - DBG("bad parameter.\n"); - return -EINVAL; - } - - if (udc->driver) { - DBG("UDC already has a gadget driver\n"); - return -EBUSY; - } + struct at91_udc *udc; + udc = container_of(gadget, struct at91_udc, gadget); udc->driver = driver; udc->gadget.dev.driver = &driver->driver; dev_set_drvdata(&udc->gadget.dev, &driver->driver); udc->enabled = 1; udc->selfpowered = 1; - retval = bind(&udc->gadget); - if (retval) { - DBG("bind() returned %d\n", retval); - udc->driver = NULL; - udc->gadget.dev.driver = NULL; - dev_set_drvdata(&udc->gadget.dev, NULL); - udc->enabled = 0; - udc->selfpowered = 0; - return retval; - } - - spin_lock_irqsave(&udc->lock, flags); - pullup(udc, 1); - spin_unlock_irqrestore(&udc->lock, flags); - DBG("bound to %s\n", driver->driver.name); return 0; } -static int at91_stop(struct usb_gadget_driver *driver) +static int at91_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct at91_udc *udc = &controller; + struct at91_udc *udc; unsigned long flags; - if (!driver || driver != udc->driver || !driver->unbind) - return -EINVAL; - + udc = container_of(gadget, struct at91_udc, gadget); spin_lock_irqsave(&udc->lock, flags); udc->enabled = 0; at91_udp_write(udc, AT91_UDP_IDR, ~0); - pullup(udc, 0); spin_unlock_irqrestore(&udc->lock, flags); - driver->unbind(&udc->gadget); udc->gadget.dev.driver = NULL; dev_set_drvdata(&udc->gadget.dev, NULL); udc->driver = NULL; diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h index 3c0315b86ace..e647d1c2ada4 100644 --- a/drivers/usb/gadget/at91_udc.h +++ b/drivers/usb/gadget/at91_udc.h @@ -105,9 +105,6 @@ struct at91_ep { unsigned is_in:1; unsigned is_iso:1; unsigned fifo_bank:1; - - const struct usb_endpoint_descriptor - *desc; }; /* diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 9f98508966d1..e23bf7984aaf 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -599,13 +599,13 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) spin_lock_irqsave(&ep->udc->lock, flags); - if (ep->desc) { + if (ep->ep.desc) { spin_unlock_irqrestore(&ep->udc->lock, flags); DBG(DBG_ERR, "ep%d already enabled\n", ep->index); return -EBUSY; } - ep->desc = desc; + ep->ep.desc = desc; ep->ep.maxpacket = maxpacket; usba_ep_writel(ep, CFG, ept_cfg); @@ -647,7 +647,7 @@ static int usba_ep_disable(struct usb_ep *_ep) spin_lock_irqsave(&udc->lock, flags); - if (!ep->desc) { + if (!ep->ep.desc) { spin_unlock_irqrestore(&udc->lock, flags); /* REVISIT because this driver disables endpoints in * reset_all_endpoints() before calling disconnect(), @@ -658,7 +658,6 @@ static int usba_ep_disable(struct usb_ep *_ep) ep->ep.name); return -EINVAL; } - ep->desc = NULL; ep->ep.desc = NULL; list_splice_init(&ep->queue, &req_list); @@ -752,7 +751,7 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep, */ ret = -ESHUTDOWN; spin_lock_irqsave(&udc->lock, flags); - if (ep->desc) { + if (ep->ep.desc) { if (list_empty(&ep->queue)) submit_request(ep, req); @@ -776,7 +775,8 @@ usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) DBG(DBG_GADGET | DBG_QUEUE | DBG_REQ, "%s: queue req %p, len %u\n", ep->ep.name, req, _req->length); - if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN || !ep->desc) + if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN || + !ep->ep.desc) return -ESHUTDOWN; req->submitted = 0; @@ -792,7 +792,7 @@ usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) /* May have received a reset since last time we checked */ ret = -ESHUTDOWN; spin_lock_irqsave(&udc->lock, flags); - if (ep->desc) { + if (ep->ep.desc) { list_add_tail(&req->queue, &ep->queue); if ((!ep_is_control(ep) && ep->is_in) || @@ -905,7 +905,7 @@ static int usba_ep_set_halt(struct usb_ep *_ep, int value) DBG(DBG_GADGET, "endpoint %s: %s HALT\n", ep->ep.name, value ? "set" : "clear"); - if (!ep->desc) { + if (!ep->ep.desc) { DBG(DBG_ERR, "Attempted to halt uninitialized ep %s\n", ep->ep.name); return -ENODEV; @@ -1008,16 +1008,16 @@ usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered) return 0; } -static int atmel_usba_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); -static int atmel_usba_stop(struct usb_gadget_driver *driver); - +static int atmel_usba_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); +static int atmel_usba_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); static const struct usb_gadget_ops usba_udc_ops = { .get_frame = usba_udc_get_frame, .wakeup = usba_udc_wakeup, .set_selfpowered = usba_udc_set_selfpowered, - .start = atmel_usba_start, - .stop = atmel_usba_stop, + .udc_start = atmel_usba_start, + .udc_stop = atmel_usba_stop, }; static struct usb_endpoint_descriptor usba_ep0_desc = { @@ -1071,7 +1071,7 @@ static void reset_all_endpoints(struct usba_udc *udc) * FIXME remove this code ... and retest thoroughly. */ list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { - if (ep->desc) { + if (ep->ep.desc) { spin_unlock(&udc->lock); usba_ep_disable(&ep->ep); spin_lock(&udc->lock); @@ -1089,9 +1089,9 @@ static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex) list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) { u8 bEndpointAddress; - if (!ep->desc) + if (!ep->ep.desc) continue; - bEndpointAddress = ep->desc->bEndpointAddress; + bEndpointAddress = ep->ep.desc->bEndpointAddress; if ((wIndex ^ bEndpointAddress) & USB_DIR_IN) continue; if ((bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) @@ -1727,7 +1727,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) usb_speed_string(udc->gadget.speed)); ep0 = &usba_ep[0]; - ep0->desc = &usba_ep0_desc; + ep0->ep.desc = &usba_ep0_desc; ep0->state = WAIT_FOR_SETUP; usba_ep_writel(ep0, CFG, (USBA_BF(EPT_SIZE, EP0_EPT_SIZE) @@ -1795,21 +1795,13 @@ out: return IRQ_HANDLED; } -static int atmel_usba_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) +static int atmel_usba_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct usba_udc *udc = &the_udc; + struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget); unsigned long flags; - int ret; - - if (!udc->pdev) - return -ENODEV; spin_lock_irqsave(&udc->lock, flags); - if (udc->driver) { - spin_unlock_irqrestore(&udc->lock, flags); - return -EBUSY; - } udc->devstatus = 1 << USB_DEVICE_SELF_POWERED; udc->driver = driver; @@ -1819,13 +1811,6 @@ static int atmel_usba_start(struct usb_gadget_driver *driver, clk_enable(udc->pclk); clk_enable(udc->hclk); - ret = bind(&udc->gadget); - if (ret) { - DBG(DBG_ERR, "Could not bind to driver %s: error %d\n", - driver->driver.name, ret); - goto err_driver_bind; - } - DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name); udc->vbus_prev = 0; @@ -1842,23 +1827,14 @@ static int atmel_usba_start(struct usb_gadget_driver *driver, spin_unlock_irqrestore(&udc->lock, flags); return 0; - -err_driver_bind: - udc->driver = NULL; - udc->gadget.dev.driver = NULL; - return ret; } -static int atmel_usba_stop(struct usb_gadget_driver *driver) +static int atmel_usba_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct usba_udc *udc = &the_udc; + struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget); unsigned long flags; - if (!udc->pdev) - return -ENODEV; - if (driver != udc->driver || !driver->unbind) - return -EINVAL; - if (gpio_is_valid(udc->vbus_pin)) disable_irq(gpio_to_irq(udc->vbus_pin)); @@ -1871,10 +1847,6 @@ static int atmel_usba_stop(struct usb_gadget_driver *driver) toggle_bias(0); usba_writel(udc, CTRL, USBA_DISABLE_MASK); - if (udc->driver->disconnect) - udc->driver->disconnect(&udc->gadget); - - driver->unbind(&udc->gadget); udc->gadget.dev.driver = NULL; udc->driver = NULL; diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h index 88a2e07a11a8..9791259cbda7 100644 --- a/drivers/usb/gadget/atmel_usba_udc.h +++ b/drivers/usb/gadget/atmel_usba_udc.h @@ -280,7 +280,6 @@ struct usba_ep { struct usba_udc *udc; struct list_head queue; - const struct usb_endpoint_descriptor *desc; u16 fifo_size; u8 nr_banks; diff --git a/drivers/usb/gadget/ci13xxx_pci.c b/drivers/usb/gadget/ci13xxx_pci.c index 883ab5e832d1..63ef96c04bb7 100644 --- a/drivers/usb/gadget/ci13xxx_pci.c +++ b/drivers/usb/gadget/ci13xxx_pci.c @@ -148,27 +148,7 @@ static struct pci_driver ci13xxx_pci_driver = { .remove = __devexit_p(ci13xxx_pci_remove), }; -/** - * ci13xxx_pci_init: module init - * - * Driver load - */ -static int __init ci13xxx_pci_init(void) -{ - return pci_register_driver(&ci13xxx_pci_driver); -} -module_init(ci13xxx_pci_init); - -/** - * ci13xxx_pci_exit: module exit - * - * Driver unload - */ -static void __exit ci13xxx_pci_exit(void) -{ - pci_unregister_driver(&ci13xxx_pci_driver); -} -module_exit(ci13xxx_pci_exit); +module_pci_driver(ci13xxx_pci_driver); MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>"); MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller"); diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 243ef1adf969..1a44bf9c374f 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -1686,7 +1686,7 @@ __acquires(udc->lock) trace("%p", udc); if (udc == NULL) { - err("EINVAL"); + pr_err("EINVAL\n"); return; } @@ -1709,7 +1709,7 @@ __acquires(udc->lock) done: if (retval) - err("error: %i", retval); + pr_err("error: %i\n", retval); } /** @@ -1724,7 +1724,7 @@ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req) trace("%p, %p", ep, req); if (ep == NULL || req == NULL) { - err("EINVAL"); + pr_err("EINVAL\n"); return; } @@ -1907,7 +1907,7 @@ __acquires(udc->lock) trace("%p", udc); if (udc == NULL) { - err("EINVAL"); + pr_err("EINVAL\n"); return; } @@ -1916,7 +1916,7 @@ __acquires(udc->lock) int type, num, dir, err = -EINVAL; struct usb_ctrlrequest req; - if (mEp->desc == NULL) + if (mEp->ep.desc == NULL) continue; /* not configured */ if (hw_test_and_clear_complete(i)) { @@ -1929,7 +1929,8 @@ __acquires(udc->lock) "ERROR", err); spin_unlock(udc->lock); if (usb_ep_set_halt(&mEp->ep)) - err("error: ep_set_halt"); + dev_err(&udc->gadget.dev, + "error: ep_set_halt\n"); spin_lock(udc->lock); } } @@ -1940,7 +1941,8 @@ __acquires(udc->lock) continue; if (i != 0) { - warn("ctrl traffic received at endpoint"); + dev_warn(&udc->gadget.dev, + "ctrl traffic received at endpoint\n"); continue; } @@ -2079,7 +2081,8 @@ delegate: spin_unlock(udc->lock); if (usb_ep_set_halt(&mEp->ep)) - err("error: ep_set_halt"); + dev_err(&udc->gadget.dev, + "error: ep_set_halt\n"); spin_lock(udc->lock); } } @@ -2109,7 +2112,7 @@ static int ep_enable(struct usb_ep *ep, /* only internal SW should enable ctrl endpts */ - mEp->desc = desc; + mEp->ep.desc = desc; if (!list_empty(&mEp->qh.queue)) warn("enabling a non-empty endpoint!"); @@ -2161,7 +2164,7 @@ static int ep_disable(struct usb_ep *ep) if (ep == NULL) return -EINVAL; - else if (mEp->desc == NULL) + else if (mEp->ep.desc == NULL) return -EBUSY; spin_lock_irqsave(mEp->lock, flags); @@ -2180,7 +2183,6 @@ static int ep_disable(struct usb_ep *ep) } while (mEp->dir != direction); - mEp->desc = NULL; mEp->ep.desc = NULL; spin_unlock_irqrestore(mEp->lock, flags); @@ -2200,7 +2202,7 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) trace("%p, %i", ep, gfp_flags); if (ep == NULL) { - err("EINVAL"); + pr_err("EINVAL\n"); return NULL; } @@ -2236,10 +2238,10 @@ static void ep_free_request(struct usb_ep *ep, struct usb_request *req) trace("%p, %p", ep, req); if (ep == NULL || req == NULL) { - err("EINVAL"); + pr_err("EINVAL\n"); return; } else if (!list_empty(&mReq->queue)) { - err("EBUSY"); + pr_err("EBUSY\n"); return; } @@ -2269,7 +2271,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, trace("%p, %p, %X", ep, req, gfp_flags); - if (ep == NULL || req == NULL || mEp->desc == NULL) + if (ep == NULL || req == NULL || mEp->ep.desc == NULL) return -EINVAL; spin_lock_irqsave(mEp->lock, flags); @@ -2288,7 +2290,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, /* first nuke then test link, e.g. previous status has not sent */ if (!list_empty(&mReq->queue)) { retval = -EBUSY; - err("request already in queue"); + pr_err("request already in queue\n"); goto done; } @@ -2332,7 +2334,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) trace("%p, %p", ep, req); if (ep == NULL || req == NULL || mReq->req.status != -EALREADY || - mEp->desc == NULL || list_empty(&mReq->queue) || + mEp->ep.desc == NULL || list_empty(&mReq->queue) || list_empty(&mEp->qh.queue)) return -EINVAL; @@ -2375,7 +2377,7 @@ static int ep_set_halt(struct usb_ep *ep, int value) trace("%p, %i", ep, value); - if (ep == NULL || mEp->desc == NULL) + if (ep == NULL || mEp->ep.desc == NULL) return -EINVAL; spin_lock_irqsave(mEp->lock, flags); @@ -2418,7 +2420,7 @@ static int ep_set_wedge(struct usb_ep *ep) trace("%p", ep); - if (ep == NULL || mEp->desc == NULL) + if (ep == NULL || mEp->ep.desc == NULL) return -EINVAL; spin_lock_irqsave(mEp->lock, flags); @@ -2444,7 +2446,7 @@ static void ep_fifo_flush(struct usb_ep *ep) trace("%p", ep); if (ep == NULL) { - err("%02X: -EINVAL", _usb_addr(mEp)); + pr_err("%02X: -EINVAL\n", _usb_addr(mEp)); return; } @@ -2777,7 +2779,7 @@ static irqreturn_t udc_irq(void) trace(); if (udc == NULL) { - err("ENODEV"); + pr_err("ENODEV\n"); return IRQ_HANDLED; } @@ -2849,7 +2851,7 @@ static void udc_release(struct device *dev) trace("%p", dev); if (dev == NULL) - err("EINVAL"); + pr_err("EINVAL\n"); } /** @@ -2951,7 +2953,7 @@ remove_trans: usb_put_transceiver(udc->transceiver); } - err("error = %i", retval); + dev_err(dev, "error = %i\n", retval); remove_dbg: #ifdef CONFIG_USB_GADGET_DEBUG_FILES dbg_remove_files(&udc->gadget.dev); @@ -2977,7 +2979,7 @@ static void udc_remove(void) struct ci13xxx *udc = _udc; if (udc == NULL) { - err("EINVAL"); + pr_err("EINVAL\n"); return; } usb_del_gadget_udc(&udc->gadget); diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h index 0d31af56c989..6490cf872adb 100644 --- a/drivers/usb/gadget/ci13xxx_udc.h +++ b/drivers/usb/gadget/ci13xxx_udc.h @@ -82,7 +82,6 @@ struct ci13xxx_req { /* Extension of usb_ep */ struct ci13xxx_ep { struct usb_ep ep; - const struct usb_endpoint_descriptor *desc; u8 dir; u8 num; u8 type; @@ -212,7 +211,6 @@ do { \ "[%s] " format "\n", __func__, ## args); \ } while (0) -#define err(format, args...) ci13xxx_printk(KERN_ERR, format, ## args) #define warn(format, args...) ci13xxx_printk(KERN_WARNING, format, ## args) #define info(format, args...) ci13xxx_printk(KERN_INFO, format, ## args) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index baaebf2830fc..a3b19fe37f53 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -737,6 +737,19 @@ int usb_add_config(struct usb_composite_dev *cdev, status = bind(config); if (status < 0) { + while (!list_empty(&config->functions)) { + struct usb_function *f; + + f = list_first_entry(&config->functions, + struct usb_function, list); + list_del(&f->list); + if (f->unbind) { + DBG(cdev, "unbind function '%s'/%p\n", + f->name, f); + f->unbind(config, f); + /* may free memory for "f" */ + } + } list_del(&config->list); config->cdev = NULL; } else { @@ -785,7 +798,7 @@ done: static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf) { const struct usb_gadget_strings *s; - u16 language; + __le16 language; __le16 *tmp; while (*sp) { diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index a6dfd2164166..83bb2e3fa861 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -595,14 +595,12 @@ static struct usb_request *dummy_alloc_request(struct usb_ep *_ep, static void dummy_free_request(struct usb_ep *_ep, struct usb_request *_req) { - struct dummy_ep *ep; struct dummy_request *req; - if (!_ep || !_req) - return; - ep = usb_ep_to_dummy_ep(_ep); - if (!ep->desc && _ep->name != ep0name) + if (!_ep || !_req) { + __WARN(); return; + } req = usb_request_to_dummy_request(_req); WARN_ON(!list_empty(&req->queue)); @@ -927,7 +925,6 @@ static int dummy_udc_stop(struct usb_gadget *g, dum->driver = NULL; - dummy_pullup(&dum->gadget, 0); return 0; } diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index f52cb1ae45d9..1d4c535671a7 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -1473,8 +1473,22 @@ static int functionfs_bind_config(struct usb_composite_dev *cdev, static void ffs_func_free(struct ffs_function *func) { + struct ffs_ep *ep = func->eps; + unsigned count = func->ffs->eps_count; + unsigned long flags; + ENTER(); + /* cleanup after autoconfig */ + spin_lock_irqsave(&func->ffs->eps_lock, flags); + do { + if (ep->ep && ep->req) + usb_ep_free_request(ep->ep, ep->req); + ep->req = NULL; + ++ep; + } while (--count); + spin_unlock_irqrestore(&func->ffs->eps_lock, flags); + ffs_data_put(func->ffs); kfree(func->eps); diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c index b2113420b806..3b3932c55361 100644 --- a/drivers/usb/gadget/f_hid.c +++ b/drivers/usb/gadget/f_hid.c @@ -374,7 +374,7 @@ static int hidg_setup(struct usb_function *f, break; default: - VDBG(cdev, "Unknown decriptor request 0x%x\n", + VDBG(cdev, "Unknown descriptor request 0x%x\n", value >> 8); goto stall; break; diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 2c0cd824c667..7275706caeb0 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -286,7 +286,7 @@ static void disable_loopback(struct f_loopback *loop) struct usb_composite_dev *cdev; cdev = loop->function.config->cdev; - disable_endpoints(cdev, loop->in_ep, loop->out_ep); + disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL); VDBG(cdev, "%s disabled\n", loop->function.name); } @@ -329,7 +329,7 @@ fail0: * than 'buflen' bytes each. */ for (i = 0; i < qlen && result == 0; i++) { - req = alloc_ep_req(ep); + req = alloc_ep_req(ep, 0); if (req) { req->complete = loopback_complete; result = usb_ep_queue(ep, req, GFP_ATOMIC); diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index a371e966425f..f67b453740bd 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -2189,7 +2189,7 @@ unknown_cmnd: common->data_size_from_cmnd = 0; sprintf(unknown, "Unknown x%02x", common->cmnd[0]); reply = check_command(common, common->cmnd_size, - DATA_DIR_UNKNOWN, 0xff, 0, unknown); + DATA_DIR_UNKNOWN, ~0, 0, unknown); if (reply == 0) { common->curlun->sense_data = SS_INVALID_COMMAND; reply = -EINVAL; @@ -3110,13 +3110,6 @@ static int fsg_bind_config(struct usb_composite_dev *cdev, return rc; } -static inline int __deprecated __maybe_unused -fsg_add(struct usb_composite_dev *cdev, struct usb_configuration *c, - struct fsg_common *common) -{ - return fsg_bind_config(cdev, c, common); -} - /************************* Module parameters *************************/ diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index 7aa7ac82c02c..5c1b68b63c98 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -51,6 +51,9 @@ struct f_sourcesink { struct usb_ep *in_ep; struct usb_ep *out_ep; + struct usb_ep *iso_in_ep; + struct usb_ep *iso_out_ep; + int cur_alt; }; static inline struct f_sourcesink *func_to_ss(struct usb_function *f) @@ -59,18 +62,45 @@ static inline struct f_sourcesink *func_to_ss(struct usb_function *f) } static unsigned pattern; -module_param(pattern, uint, 0); -MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 "); +module_param(pattern, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63, 2 = none"); + +static unsigned isoc_interval = 4; +module_param(isoc_interval, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(isoc_interval, "1 - 16"); + +static unsigned isoc_maxpacket = 1024; +module_param(isoc_maxpacket, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(isoc_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)"); + +static unsigned isoc_mult; +module_param(isoc_mult, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(isoc_mult, "0 - 2 (hs/ss only)"); + +static unsigned isoc_maxburst; +module_param(isoc_maxburst, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)"); /*-------------------------------------------------------------------------*/ -static struct usb_interface_descriptor source_sink_intf = { - .bLength = sizeof source_sink_intf, +static struct usb_interface_descriptor source_sink_intf_alt0 = { + .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, + .bAlternateSetting = 0, .bNumEndpoints = 2, .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - /* .iInterface = DYNAMIC */ + /* .iInterface = DYNAMIC */ +}; + +static struct usb_interface_descriptor source_sink_intf_alt1 = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + + .bAlternateSetting = 1, + .bNumEndpoints = 4, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + /* .iInterface = DYNAMIC */ }; /* full speed support: */ @@ -91,10 +121,36 @@ static struct usb_endpoint_descriptor fs_sink_desc = { .bmAttributes = USB_ENDPOINT_XFER_BULK, }; +static struct usb_endpoint_descriptor fs_iso_source_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1023), + .bInterval = 4, +}; + +static struct usb_endpoint_descriptor fs_iso_sink_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1023), + .bInterval = 4, +}; + static struct usb_descriptor_header *fs_source_sink_descs[] = { - (struct usb_descriptor_header *) &source_sink_intf, + (struct usb_descriptor_header *) &source_sink_intf_alt0, (struct usb_descriptor_header *) &fs_sink_desc, (struct usb_descriptor_header *) &fs_source_desc, + (struct usb_descriptor_header *) &source_sink_intf_alt1, +#define FS_ALT_IFC_1_OFFSET 3 + (struct usb_descriptor_header *) &fs_sink_desc, + (struct usb_descriptor_header *) &fs_source_desc, + (struct usb_descriptor_header *) &fs_iso_sink_desc, + (struct usb_descriptor_header *) &fs_iso_source_desc, NULL, }; @@ -116,10 +172,34 @@ static struct usb_endpoint_descriptor hs_sink_desc = { .wMaxPacketSize = cpu_to_le16(512), }; +static struct usb_endpoint_descriptor hs_iso_source_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1024), + .bInterval = 4, +}; + +static struct usb_endpoint_descriptor hs_iso_sink_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1024), + .bInterval = 4, +}; + static struct usb_descriptor_header *hs_source_sink_descs[] = { - (struct usb_descriptor_header *) &source_sink_intf, + (struct usb_descriptor_header *) &source_sink_intf_alt0, (struct usb_descriptor_header *) &hs_source_desc, (struct usb_descriptor_header *) &hs_sink_desc, + (struct usb_descriptor_header *) &source_sink_intf_alt1, +#define HS_ALT_IFC_1_OFFSET 3 + (struct usb_descriptor_header *) &hs_source_desc, + (struct usb_descriptor_header *) &hs_sink_desc, + (struct usb_descriptor_header *) &hs_iso_source_desc, + (struct usb_descriptor_header *) &hs_iso_sink_desc, NULL, }; @@ -136,6 +216,7 @@ static struct usb_endpoint_descriptor ss_source_desc = { struct usb_ss_ep_comp_descriptor ss_source_comp_desc = { .bLength = USB_DT_SS_EP_COMP_SIZE, .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 0, .bmAttributes = 0, .wBytesPerInterval = 0, @@ -152,17 +233,64 @@ static struct usb_endpoint_descriptor ss_sink_desc = { struct usb_ss_ep_comp_descriptor ss_sink_comp_desc = { .bLength = USB_DT_SS_EP_COMP_SIZE, .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 0, .bmAttributes = 0, .wBytesPerInterval = 0, }; +static struct usb_endpoint_descriptor ss_iso_source_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1024), + .bInterval = 4, +}; + +struct usb_ss_ep_comp_descriptor ss_iso_source_comp_desc = { + .bLength = USB_DT_SS_EP_COMP_SIZE, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + .bMaxBurst = 0, + .bmAttributes = 0, + .wBytesPerInterval = cpu_to_le16(1024), +}; + +static struct usb_endpoint_descriptor ss_iso_sink_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1024), + .bInterval = 4, +}; + +struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = { + .bLength = USB_DT_SS_EP_COMP_SIZE, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + .bMaxBurst = 0, + .bmAttributes = 0, + .wBytesPerInterval = cpu_to_le16(1024), +}; + static struct usb_descriptor_header *ss_source_sink_descs[] = { - (struct usb_descriptor_header *) &source_sink_intf, + (struct usb_descriptor_header *) &source_sink_intf_alt0, (struct usb_descriptor_header *) &ss_source_desc, (struct usb_descriptor_header *) &ss_source_comp_desc, (struct usb_descriptor_header *) &ss_sink_desc, (struct usb_descriptor_header *) &ss_sink_comp_desc, + (struct usb_descriptor_header *) &source_sink_intf_alt1, +#define SS_ALT_IFC_1_OFFSET 5 + (struct usb_descriptor_header *) &ss_source_desc, + (struct usb_descriptor_header *) &ss_source_comp_desc, + (struct usb_descriptor_header *) &ss_sink_desc, + (struct usb_descriptor_header *) &ss_sink_comp_desc, + (struct usb_descriptor_header *) &ss_iso_source_desc, + (struct usb_descriptor_header *) &ss_iso_source_comp_desc, + (struct usb_descriptor_header *) &ss_iso_sink_desc, + (struct usb_descriptor_header *) &ss_iso_sink_comp_desc, NULL, }; @@ -196,9 +324,10 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f) id = usb_interface_id(c, f); if (id < 0) return id; - source_sink_intf.bInterfaceNumber = id; + source_sink_intf_alt0.bInterfaceNumber = id; + source_sink_intf_alt1.bInterfaceNumber = id; - /* allocate endpoints */ + /* allocate bulk endpoints */ ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc); if (!ss->in_ep) { autoconf_fail: @@ -213,12 +342,74 @@ autoconf_fail: goto autoconf_fail; ss->out_ep->driver_data = cdev; /* claim */ + /* sanity check the isoc module parameters */ + if (isoc_interval < 1) + isoc_interval = 1; + if (isoc_interval > 16) + isoc_interval = 16; + if (isoc_mult > 2) + isoc_mult = 2; + if (isoc_maxburst > 15) + isoc_maxburst = 15; + + /* fill in the FS isoc descriptors from the module parameters */ + fs_iso_source_desc.wMaxPacketSize = isoc_maxpacket > 1023 ? + 1023 : isoc_maxpacket; + fs_iso_source_desc.bInterval = isoc_interval; + fs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket > 1023 ? + 1023 : isoc_maxpacket; + fs_iso_sink_desc.bInterval = isoc_interval; + + /* allocate iso endpoints */ + ss->iso_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_source_desc); + if (!ss->iso_in_ep) + goto no_iso; + ss->iso_in_ep->driver_data = cdev; /* claim */ + + ss->iso_out_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_sink_desc); + if (ss->iso_out_ep) { + ss->iso_out_ep->driver_data = cdev; /* claim */ + } else { + ss->iso_in_ep->driver_data = NULL; + ss->iso_in_ep = NULL; +no_iso: + /* + * We still want to work even if the UDC doesn't have isoc + * endpoints, so null out the alt interface that contains + * them and continue. + */ + fs_source_sink_descs[FS_ALT_IFC_1_OFFSET] = NULL; + hs_source_sink_descs[HS_ALT_IFC_1_OFFSET] = NULL; + ss_source_sink_descs[SS_ALT_IFC_1_OFFSET] = NULL; + } + + if (isoc_maxpacket > 1024) + isoc_maxpacket = 1024; + /* support high speed hardware */ if (gadget_is_dualspeed(c->cdev->gadget)) { hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; + + /* + * Fill in the HS isoc descriptors from the module parameters. + * We assume that the user knows what they are doing and won't + * give parameters that their UDC doesn't support. + */ + hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket; + hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11; + hs_iso_source_desc.bInterval = isoc_interval; + hs_iso_source_desc.bEndpointAddress = + fs_iso_source_desc.bEndpointAddress; + + hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket; + hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11; + hs_iso_sink_desc.bInterval = isoc_interval; + hs_iso_sink_desc.bEndpointAddress = + fs_iso_sink_desc.bEndpointAddress; + f->hs_descriptors = hs_source_sink_descs; } @@ -228,13 +419,39 @@ autoconf_fail: fs_source_desc.bEndpointAddress; ss_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; + + /* + * Fill in the SS isoc descriptors from the module parameters. + * We assume that the user knows what they are doing and won't + * give parameters that their UDC doesn't support. + */ + ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket; + ss_iso_source_desc.bInterval = isoc_interval; + ss_iso_source_comp_desc.bmAttributes = isoc_mult; + ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst; + ss_iso_source_comp_desc.wBytesPerInterval = + isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); + ss_iso_source_desc.bEndpointAddress = + fs_iso_source_desc.bEndpointAddress; + + ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket; + ss_iso_sink_desc.bInterval = isoc_interval; + ss_iso_sink_comp_desc.bmAttributes = isoc_mult; + ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst; + ss_iso_sink_comp_desc.wBytesPerInterval = + isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); + ss_iso_sink_desc.bEndpointAddress = + fs_iso_sink_desc.bEndpointAddress; + f->ss_descriptors = ss_source_sink_descs; } - DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", + DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n", (gadget_is_superspeed(c->cdev->gadget) ? "super" : (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")), - f->name, ss->in_ep->name, ss->out_ep->name); + f->name, ss->in_ep->name, ss->out_ep->name, + ss->iso_in_ep ? ss->iso_in_ep->name : "<none>", + ss->iso_out_ep ? ss->iso_out_ep->name : "<none>"); return 0; } @@ -251,6 +468,9 @@ static int check_read_data(struct f_sourcesink *ss, struct usb_request *req) u8 *buf = req->buf; struct usb_composite_dev *cdev = ss->function.config->cdev; + if (pattern == 2) + return 0; + for (i = 0; i < req->actual; i++, buf++) { switch (pattern) { @@ -265,7 +485,7 @@ static int check_read_data(struct f_sourcesink *ss, struct usb_request *req) * each usb transfer request should be. Resync is done * with set_interface or set_config. (We *WANT* it to * get quickly out of sync if controllers or their drivers - * stutter for any reason, including buffer duplcation...) + * stutter for any reason, including buffer duplication...) */ case 1: if (*buf == (u8)(i % 63)) @@ -292,21 +512,30 @@ static void reinit_write_data(struct usb_ep *ep, struct usb_request *req) for (i = 0; i < req->length; i++) *buf++ = (u8) (i % 63); break; + case 2: + break; } } static void source_sink_complete(struct usb_ep *ep, struct usb_request *req) { - struct f_sourcesink *ss = ep->driver_data; - struct usb_composite_dev *cdev = ss->function.config->cdev; - int status = req->status; + struct usb_composite_dev *cdev; + struct f_sourcesink *ss = ep->driver_data; + int status = req->status; + + /* driver_data will be null if ep has been disabled */ + if (!ss) + return; + + cdev = ss->function.config->cdev; switch (status) { case 0: /* normal completion? */ if (ep == ss->out_ep) { check_read_data(ss, req); - memset(req->buf, 0x55, req->length); + if (pattern != 2) + memset(req->buf, 0x55, req->length); } else reinit_write_data(ep, req); break; @@ -344,32 +573,57 @@ static void source_sink_complete(struct usb_ep *ep, struct usb_request *req) } } -static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in) +static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in, + bool is_iso, int speed) { struct usb_ep *ep; struct usb_request *req; - int status; + int i, size, status; + + for (i = 0; i < 8; i++) { + if (is_iso) { + switch (speed) { + case USB_SPEED_SUPER: + size = isoc_maxpacket * (isoc_mult + 1) * + (isoc_maxburst + 1); + break; + case USB_SPEED_HIGH: + size = isoc_maxpacket * (isoc_mult + 1); + break; + default: + size = isoc_maxpacket > 1023 ? + 1023 : isoc_maxpacket; + break; + } + ep = is_in ? ss->iso_in_ep : ss->iso_out_ep; + req = alloc_ep_req(ep, size); + } else { + ep = is_in ? ss->in_ep : ss->out_ep; + req = alloc_ep_req(ep, 0); + } - ep = is_in ? ss->in_ep : ss->out_ep; - req = alloc_ep_req(ep); - if (!req) - return -ENOMEM; + if (!req) + return -ENOMEM; - req->complete = source_sink_complete; - if (is_in) - reinit_write_data(ep, req); - else - memset(req->buf, 0x55, req->length); + req->complete = source_sink_complete; + if (is_in) + reinit_write_data(ep, req); + else if (pattern != 2) + memset(req->buf, 0x55, req->length); - status = usb_ep_queue(ep, req, GFP_ATOMIC); - if (status) { - struct usb_composite_dev *cdev; + status = usb_ep_queue(ep, req, GFP_ATOMIC); + if (status) { + struct usb_composite_dev *cdev; - cdev = ss->function.config->cdev; - ERROR(cdev, "start %s %s --> %d\n", - is_in ? "IN" : "OUT", - ep->name, status); - free_ep_req(ep, req); + cdev = ss->function.config->cdev; + ERROR(cdev, "start %s%s %s --> %d\n", + is_iso ? "ISO-" : "", is_in ? "IN" : "OUT", + ep->name, status); + free_ep_req(ep, req); + } + + if (!is_iso) + break; } return status; @@ -380,17 +634,20 @@ static void disable_source_sink(struct f_sourcesink *ss) struct usb_composite_dev *cdev; cdev = ss->function.config->cdev; - disable_endpoints(cdev, ss->in_ep, ss->out_ep); + disable_endpoints(cdev, ss->in_ep, ss->out_ep, ss->iso_in_ep, + ss->iso_out_ep); VDBG(cdev, "%s disabled\n", ss->function.name); } static int -enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss) +enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss, + int alt) { int result = 0; + int speed = cdev->gadget->speed; struct usb_ep *ep; - /* one endpoint writes (sources) zeroes IN (to the host) */ + /* one bulk endpoint writes (sources) zeroes IN (to the host) */ ep = ss->in_ep; result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); if (result) @@ -400,7 +657,7 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss) return result; ep->driver_data = ss; - result = source_sink_start_ep(ss, true); + result = source_sink_start_ep(ss, true, false, speed); if (result < 0) { fail: ep = ss->in_ep; @@ -409,7 +666,7 @@ fail: return result; } - /* one endpoint reads (sinks) anything OUT (from the host) */ + /* one bulk endpoint reads (sinks) anything OUT (from the host) */ ep = ss->out_ep; result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); if (result) @@ -419,27 +676,82 @@ fail: goto fail; ep->driver_data = ss; - result = source_sink_start_ep(ss, false); + result = source_sink_start_ep(ss, false, false, speed); if (result < 0) { +fail2: + ep = ss->out_ep; usb_ep_disable(ep); ep->driver_data = NULL; goto fail; } - DBG(cdev, "%s enabled\n", ss->function.name); + if (alt == 0) + goto out; + + /* one iso endpoint writes (sources) zeroes IN (to the host) */ + ep = ss->iso_in_ep; + if (ep) { + result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); + if (result) + goto fail2; + result = usb_ep_enable(ep); + if (result < 0) + goto fail2; + ep->driver_data = ss; + + result = source_sink_start_ep(ss, true, true, speed); + if (result < 0) { +fail3: + ep = ss->iso_in_ep; + if (ep) { + usb_ep_disable(ep); + ep->driver_data = NULL; + } + goto fail2; + } + } + + /* one iso endpoint reads (sinks) anything OUT (from the host) */ + ep = ss->iso_out_ep; + if (ep) { + result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); + if (result) + goto fail3; + result = usb_ep_enable(ep); + if (result < 0) + goto fail3; + ep->driver_data = ss; + + result = source_sink_start_ep(ss, false, true, speed); + if (result < 0) { + usb_ep_disable(ep); + ep->driver_data = NULL; + goto fail3; + } + } +out: + ss->cur_alt = alt; + + DBG(cdev, "%s enabled, alt intf %d\n", ss->function.name, alt); return result; } static int sourcesink_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { - struct f_sourcesink *ss = func_to_ss(f); - struct usb_composite_dev *cdev = f->config->cdev; + struct f_sourcesink *ss = func_to_ss(f); + struct usb_composite_dev *cdev = f->config->cdev; - /* we know alt is zero */ if (ss->in_ep->driver_data) disable_source_sink(ss); - return enable_source_sink(cdev, ss); + return enable_source_sink(cdev, ss, alt); +} + +static int sourcesink_get_alt(struct usb_function *f, unsigned intf) +{ + struct f_sourcesink *ss = func_to_ss(f); + + return ss->cur_alt; } static void sourcesink_disable(struct usb_function *f) @@ -465,6 +777,7 @@ static int __init sourcesink_bind_config(struct usb_configuration *c) ss->function.bind = sourcesink_bind; ss->function.unbind = sourcesink_unbind; ss->function.set_alt = sourcesink_set_alt; + ss->function.get_alt = sourcesink_get_alt; ss->function.disable = sourcesink_disable; status = usb_add_function(c, &ss->function); @@ -536,7 +849,7 @@ unknown: req->length = value; value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC); if (value < 0) - ERROR(c->cdev, "source/sinkc response, err %d\n", + ERROR(c->cdev, "source/sink response, err %d\n", value); } @@ -545,12 +858,12 @@ unknown: } static struct usb_configuration sourcesink_driver = { - .label = "source/sink", - .strings = sourcesink_strings, - .setup = sourcesink_setup, - .bConfigurationValue = 3, - .bmAttributes = USB_CONFIG_ATT_SELFPOWER, - /* .iConfiguration = DYNAMIC */ + .label = "source/sink", + .strings = sourcesink_strings, + .setup = sourcesink_setup, + .bConfigurationValue = 3, + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, + /* .iConfiguration = DYNAMIC */ }; /** @@ -567,7 +880,8 @@ int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume) return id; strings_sourcesink[0].id = id; - source_sink_intf.iInterface = id; + source_sink_intf_alt0.iInterface = id; + source_sink_intf_alt1.iInterface = id; sourcesink_driver.iConfiguration = id; /* support autoresume for remote wakeup testing */ diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 4fac56927741..a896d73f7a93 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -2579,7 +2579,7 @@ static int do_scsi_command(struct fsg_dev *fsg) fsg->data_size_from_cmnd = 0; sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]); if ((reply = check_command(fsg, fsg->cmnd_size, - DATA_DIR_UNKNOWN, 0xff, 0, unknown)) == 0) { + DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) { fsg->curlun->sense_data = SS_INVALID_COMMAND; reply = -EINVAL; } diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 877a2c46672b..51881f3bd07a 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -71,9 +71,6 @@ static struct usb_endpoint_descriptor qe_ep0_desc = { .wMaxPacketSize = USB_MAX_CTRL_PAYLOAD, }; -/* it is initialized in probe() */ -static struct qe_udc *udc_controller; - /******************************************************************** * Internal Used Function Start ********************************************************************/ @@ -188,8 +185,8 @@ static int qe_ep0_stall(struct qe_udc *udc) { qe_eptx_stall_change(&udc->eps[0], 1); qe_eprx_stall_change(&udc->eps[0], 1); - udc_controller->ep0_state = WAIT_FOR_SETUP; - udc_controller->ep0_dir = 0; + udc->ep0_state = WAIT_FOR_SETUP; + udc->ep0_dir = 0; return 0; } @@ -450,13 +447,13 @@ static int qe_ep_rxbd_update(struct qe_ep *ep) ep->rxbuf_d = virt_to_phys((void *)ep->rxbuffer); if (ep->rxbuf_d == DMA_ADDR_INVALID) { - ep->rxbuf_d = dma_map_single(udc_controller->gadget.dev.parent, + ep->rxbuf_d = dma_map_single(ep->udc->gadget.dev.parent, ep->rxbuffer, size, DMA_FROM_DEVICE); ep->rxbufmap = 1; } else { - dma_sync_single_for_device(udc_controller->gadget.dev.parent, + dma_sync_single_for_device(ep->udc->gadget.dev.parent, ep->rxbuf_d, size, DMA_FROM_DEVICE); ep->rxbufmap = 0; @@ -489,10 +486,10 @@ static int qe_ep_register_init(struct qe_udc *udc, unsigned char pipe_num) epparam = udc->ep_param[pipe_num]; usep = 0; - logepnum = (ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + logepnum = (ep->ep.desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); usep |= (logepnum << USB_EPNUM_SHIFT); - switch (ep->desc->bmAttributes & 0x03) { + switch (ep->ep.desc->bmAttributes & 0x03) { case USB_ENDPOINT_XFER_BULK: usep |= USB_TRANS_BULK; break; @@ -644,7 +641,7 @@ static int qe_ep_init(struct qe_udc *udc, /* initialize ep structure */ ep->ep.maxpacket = max; ep->tm = (u8)(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); - ep->desc = desc; + ep->ep.desc = desc; ep->stopped = 0; ep->init = 1; @@ -698,14 +695,14 @@ en_done: return -ENODEV; } -static inline void qe_usb_enable(void) +static inline void qe_usb_enable(struct qe_udc *udc) { - setbits8(&udc_controller->usb_regs->usb_usmod, USB_MODE_EN); + setbits8(&udc->usb_regs->usb_usmod, USB_MODE_EN); } -static inline void qe_usb_disable(void) +static inline void qe_usb_disable(struct qe_udc *udc) { - clrbits8(&udc_controller->usb_regs->usb_usmod, USB_MODE_EN); + clrbits8(&udc->usb_regs->usb_usmod, USB_MODE_EN); } /*----------------------------------------------------------------------------* @@ -1599,7 +1596,7 @@ static int qe_ep_enable(struct usb_ep *_ep, ep = container_of(_ep, struct qe_ep, ep); /* catch various bogus parameters */ - if (!_ep || !desc || ep->desc || _ep->name == ep_name[0] || + if (!_ep || !desc || ep->ep.desc || _ep->name == ep_name[0] || (desc->bDescriptorType != USB_DT_ENDPOINT)) return -EINVAL; @@ -1629,7 +1626,7 @@ static int qe_ep_disable(struct usb_ep *_ep) ep = container_of(_ep, struct qe_ep, ep); udc = ep->udc; - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { dev_dbg(udc->dev, "%s not enabled\n", _ep ? ep->ep.name : NULL); return -EINVAL; } @@ -1637,7 +1634,6 @@ static int qe_ep_disable(struct usb_ep *_ep) spin_lock_irqsave(&udc->lock, flags); /* Nuke all pending requests (does flush) */ nuke(ep, -ESHUTDOWN); - ep->desc = NULL; ep->ep.desc = NULL; ep->stopped = 1; ep->tx_req = NULL; @@ -1656,13 +1652,13 @@ static int qe_ep_disable(struct usb_ep *_ep) if (ep->dir != USB_DIR_IN) { kfree(ep->rxframe); if (ep->rxbufmap) { - dma_unmap_single(udc_controller->gadget.dev.parent, + dma_unmap_single(udc->gadget.dev.parent, ep->rxbuf_d, size, DMA_FROM_DEVICE); ep->rxbuf_d = DMA_ADDR_INVALID; } else { dma_sync_single_for_cpu( - udc_controller->gadget.dev.parent, + udc->gadget.dev.parent, ep->rxbuf_d, size, DMA_FROM_DEVICE); } @@ -1715,7 +1711,7 @@ static int __qe_ep_queue(struct usb_ep *_ep, struct usb_request *_req) dev_dbg(udc->dev, "bad params\n"); return -EINVAL; } - if (!_ep || (!ep->desc && ep_index(ep))) { + if (!_ep || (!ep->ep.desc && ep_index(ep))) { dev_dbg(udc->dev, "bad ep\n"); return -EINVAL; } @@ -1826,7 +1822,7 @@ static int qe_ep_set_halt(struct usb_ep *_ep, int value) struct qe_udc *udc; ep = container_of(_ep, struct qe_ep, ep); - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { status = -EINVAL; goto out; } @@ -1880,9 +1876,10 @@ static struct usb_ep_ops qe_ep_ops = { /* Get the current frame number */ static int qe_get_frame(struct usb_gadget *gadget) { + struct qe_udc *udc = container_of(gadget, struct qe_udc, gadget); u16 tmp; - tmp = in_be16(&udc_controller->usb_param->frame_n); + tmp = in_be16(&udc->usb_param->frame_n); if (tmp & 0x8000) tmp = tmp & 0x07ff; else @@ -1891,57 +1888,16 @@ static int qe_get_frame(struct usb_gadget *gadget) return (int)tmp; } -/* Tries to wake up the host connected to this gadget - * - * Return : 0-success - * Negative-this feature not enabled by host or not supported by device hw - */ -static int qe_wakeup(struct usb_gadget *gadget) -{ - return -ENOTSUPP; -} - -/* Notify controller that VBUS is powered, Called by whatever - detects VBUS sessions */ -static int qe_vbus_session(struct usb_gadget *gadget, int is_active) -{ - return -ENOTSUPP; -} - -/* constrain controller's VBUS power usage - * This call is used by gadget drivers during SET_CONFIGURATION calls, - * reporting how much power the device may consume. For example, this - * could affect how quickly batteries are recharged. - * - * Returns zero on success, else negative errno. - */ -static int qe_vbus_draw(struct usb_gadget *gadget, unsigned mA) -{ - return -ENOTSUPP; -} - -/* Change Data+ pullup status - * this func is used by usb_gadget_connect/disconnect - */ -static int qe_pullup(struct usb_gadget *gadget, int is_on) -{ - return -ENOTSUPP; -} - -static int fsl_qe_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); -static int fsl_qe_stop(struct usb_gadget_driver *driver); +static int fsl_qe_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); +static int fsl_qe_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); /* defined in usb_gadget.h */ static struct usb_gadget_ops qe_gadget_ops = { .get_frame = qe_get_frame, - .wakeup = qe_wakeup, -/* .set_selfpowered = qe_set_selfpowered,*/ /* always selfpowered */ - .vbus_session = qe_vbus_session, - .vbus_draw = qe_vbus_draw, - .pullup = qe_pullup, - .start = fsl_qe_start, - .stop = fsl_qe_stop, + .udc_start = fsl_qe_start, + .udc_stop = fsl_qe_stop, }; /*------------------------------------------------------------------------- @@ -2015,7 +1971,7 @@ static void ch9getstatus(struct qe_udc *udc, u8 request_type, u16 value, u16 usep; /* stall if endpoint doesn't exist */ - if (!target_ep->desc) + if (!target_ep->ep.desc) goto stall; usep = in_be16(&udc->usb_regs->usb_usep[pipe]); @@ -2190,7 +2146,7 @@ static int reset_irq(struct qe_udc *udc) if (udc->usb_state == USB_STATE_DEFAULT) return 0; - qe_usb_disable(); + qe_usb_disable(udc); out_8(&udc->usb_regs->usb_usadr, 0); for (i = 0; i < USB_MAX_ENDPOINTS; i++) { @@ -2202,7 +2158,7 @@ static int reset_irq(struct qe_udc *udc) udc->usb_state = USB_STATE_DEFAULT; udc->ep0_state = WAIT_FOR_SETUP; udc->ep0_dir = USB_DIR_OUT; - qe_usb_enable(); + qe_usb_enable(udc); return 0; } @@ -2327,92 +2283,65 @@ static irqreturn_t qe_udc_irq(int irq, void *_udc) /*------------------------------------------------------------------------- Gadget driver probe and unregister. --------------------------------------------------------------------------*/ -static int fsl_qe_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) +static int fsl_qe_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - int retval; - unsigned long flags = 0; - - /* standard operations */ - if (!udc_controller) - return -ENODEV; - - if (!driver || driver->max_speed < USB_SPEED_FULL - || !bind || !driver->disconnect || !driver->setup) - return -EINVAL; - - if (udc_controller->driver) - return -EBUSY; + struct qe_udc *udc; + unsigned long flags; + udc = container_of(gadget, struct qe_udc, gadget); /* lock is needed but whether should use this lock or another */ - spin_lock_irqsave(&udc_controller->lock, flags); + spin_lock_irqsave(&udc->lock, flags); driver->driver.bus = NULL; /* hook up the driver */ - udc_controller->driver = driver; - udc_controller->gadget.dev.driver = &driver->driver; - udc_controller->gadget.speed = driver->max_speed; - spin_unlock_irqrestore(&udc_controller->lock, flags); - - retval = bind(&udc_controller->gadget); - if (retval) { - dev_err(udc_controller->dev, "bind to %s --> %d", - driver->driver.name, retval); - udc_controller->gadget.dev.driver = NULL; - udc_controller->driver = NULL; - return retval; - } + udc->driver = driver; + udc->gadget.dev.driver = &driver->driver; + udc->gadget.speed = driver->max_speed; /* Enable IRQ reg and Set usbcmd reg EN bit */ - qe_usb_enable(); - - out_be16(&udc_controller->usb_regs->usb_usber, 0xffff); - out_be16(&udc_controller->usb_regs->usb_usbmr, USB_E_DEFAULT_DEVICE); - udc_controller->usb_state = USB_STATE_ATTACHED; - udc_controller->ep0_state = WAIT_FOR_SETUP; - udc_controller->ep0_dir = USB_DIR_OUT; - dev_info(udc_controller->dev, "%s bind to driver %s \n", - udc_controller->gadget.name, driver->driver.name); + qe_usb_enable(udc); + + out_be16(&udc->usb_regs->usb_usber, 0xffff); + out_be16(&udc->usb_regs->usb_usbmr, USB_E_DEFAULT_DEVICE); + udc->usb_state = USB_STATE_ATTACHED; + udc->ep0_state = WAIT_FOR_SETUP; + udc->ep0_dir = USB_DIR_OUT; + spin_unlock_irqrestore(&udc->lock, flags); + + dev_info(udc->dev, "%s bind to driver %s\n", udc->gadget.name, + driver->driver.name); return 0; } -static int fsl_qe_stop(struct usb_gadget_driver *driver) +static int fsl_qe_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { + struct qe_udc *udc; struct qe_ep *loop_ep; unsigned long flags; - if (!udc_controller) - return -ENODEV; - - if (!driver || driver != udc_controller->driver) - return -EINVAL; - + udc = container_of(gadget, struct qe_udc, gadget); /* stop usb controller, disable intr */ - qe_usb_disable(); + qe_usb_disable(udc); /* in fact, no needed */ - udc_controller->usb_state = USB_STATE_ATTACHED; - udc_controller->ep0_state = WAIT_FOR_SETUP; - udc_controller->ep0_dir = 0; + udc->usb_state = USB_STATE_ATTACHED; + udc->ep0_state = WAIT_FOR_SETUP; + udc->ep0_dir = 0; /* stand operation */ - spin_lock_irqsave(&udc_controller->lock, flags); - udc_controller->gadget.speed = USB_SPEED_UNKNOWN; - nuke(&udc_controller->eps[0], -ESHUTDOWN); - list_for_each_entry(loop_ep, &udc_controller->gadget.ep_list, - ep.ep_list) + spin_lock_irqsave(&udc->lock, flags); + udc->gadget.speed = USB_SPEED_UNKNOWN; + nuke(&udc->eps[0], -ESHUTDOWN); + list_for_each_entry(loop_ep, &udc->gadget.ep_list, ep.ep_list) nuke(loop_ep, -ESHUTDOWN); - spin_unlock_irqrestore(&udc_controller->lock, flags); - - /* report disconnect; the controller is already quiesced */ - driver->disconnect(&udc_controller->gadget); + spin_unlock_irqrestore(&udc->lock, flags); - /* unbind gadget and unhook driver. */ - driver->unbind(&udc_controller->gadget); - udc_controller->gadget.dev.driver = NULL; - udc_controller->driver = NULL; + udc->gadget.dev.driver = NULL; + udc->driver = NULL; - dev_info(udc_controller->dev, "unregistered gadget driver '%s'\r\n", + dev_info(udc->dev, "unregistered gadget driver '%s'\r\n", driver->driver.name); return 0; } @@ -2502,7 +2431,7 @@ static int __devinit qe_ep_config(struct qe_udc *udc, unsigned char pipe_num) ep->ep.ops = &qe_ep_ops; ep->stopped = 1; ep->ep.maxpacket = (unsigned short) ~0; - ep->desc = NULL; + ep->ep.desc = NULL; ep->dir = 0xff; ep->epnum = (u8)pipe_num; ep->sent = 0; @@ -2531,21 +2460,22 @@ static int __devinit qe_ep_config(struct qe_udc *udc, unsigned char pipe_num) *----------------------------------------------------------------------*/ static void qe_udc_release(struct device *dev) { - int i = 0; + struct qe_udc *udc = container_of(dev, struct qe_udc, gadget.dev); + int i; - complete(udc_controller->done); - cpm_muram_free(cpm_muram_offset(udc_controller->ep_param[0])); + complete(udc->done); + cpm_muram_free(cpm_muram_offset(udc->ep_param[0])); for (i = 0; i < USB_MAX_ENDPOINTS; i++) - udc_controller->ep_param[i] = NULL; + udc->ep_param[i] = NULL; - kfree(udc_controller); - udc_controller = NULL; + kfree(udc); } /* Driver probe functions */ static const struct of_device_id qe_udc_match[]; static int __devinit qe_udc_probe(struct platform_device *ofdev) { + struct qe_udc *udc; const struct of_device_id *match; struct device_node *np = ofdev->dev.of_node; struct qe_ep *ep; @@ -2562,44 +2492,44 @@ static int __devinit qe_udc_probe(struct platform_device *ofdev) return -ENODEV; /* Initialize the udc structure including QH member and other member */ - udc_controller = qe_udc_config(ofdev); - if (!udc_controller) { + udc = qe_udc_config(ofdev); + if (!udc) { dev_err(&ofdev->dev, "failed to initialize\n"); return -ENOMEM; } - udc_controller->soc_type = (unsigned long)match->data; - udc_controller->usb_regs = of_iomap(np, 0); - if (!udc_controller->usb_regs) { + udc->soc_type = (unsigned long)match->data; + udc->usb_regs = of_iomap(np, 0); + if (!udc->usb_regs) { ret = -ENOMEM; goto err1; } /* initialize usb hw reg except for regs for EP, * leave usbintr reg untouched*/ - qe_udc_reg_init(udc_controller); + qe_udc_reg_init(udc); /* here comes the stand operations for probe * set the qe_udc->gadget.xxx */ - udc_controller->gadget.ops = &qe_gadget_ops; + udc->gadget.ops = &qe_gadget_ops; /* gadget.ep0 is a pointer */ - udc_controller->gadget.ep0 = &udc_controller->eps[0].ep; + udc->gadget.ep0 = &udc->eps[0].ep; - INIT_LIST_HEAD(&udc_controller->gadget.ep_list); + INIT_LIST_HEAD(&udc->gadget.ep_list); /* modify in register gadget process */ - udc_controller->gadget.speed = USB_SPEED_UNKNOWN; + udc->gadget.speed = USB_SPEED_UNKNOWN; /* name: Identifies the controller hardware type. */ - udc_controller->gadget.name = driver_name; + udc->gadget.name = driver_name; - device_initialize(&udc_controller->gadget.dev); + device_initialize(&udc->gadget.dev); - dev_set_name(&udc_controller->gadget.dev, "gadget"); + dev_set_name(&udc->gadget.dev, "gadget"); - udc_controller->gadget.dev.release = qe_udc_release; - udc_controller->gadget.dev.parent = &ofdev->dev; + udc->gadget.dev.release = qe_udc_release; + udc->gadget.dev.parent = &ofdev->dev; /* initialize qe_ep struct */ for (i = 0; i < USB_MAX_ENDPOINTS ; i++) { @@ -2608,104 +2538,104 @@ static int __devinit qe_udc_probe(struct platform_device *ofdev) /* setup the qe_ep struct and link ep.ep.list * into gadget.ep_list */ - qe_ep_config(udc_controller, (unsigned char)i); + qe_ep_config(udc, (unsigned char)i); } /* ep0 initialization in here */ - ret = qe_ep_init(udc_controller, 0, &qe_ep0_desc); + ret = qe_ep_init(udc, 0, &qe_ep0_desc); if (ret) goto err2; /* create a buf for ZLP send, need to remain zeroed */ - udc_controller->nullbuf = kzalloc(256, GFP_KERNEL); - if (udc_controller->nullbuf == NULL) { - dev_err(udc_controller->dev, "cannot alloc nullbuf\n"); + udc->nullbuf = kzalloc(256, GFP_KERNEL); + if (udc->nullbuf == NULL) { + dev_err(udc->dev, "cannot alloc nullbuf\n"); ret = -ENOMEM; goto err3; } /* buffer for data of get_status request */ - udc_controller->statusbuf = kzalloc(2, GFP_KERNEL); - if (udc_controller->statusbuf == NULL) { + udc->statusbuf = kzalloc(2, GFP_KERNEL); + if (udc->statusbuf == NULL) { ret = -ENOMEM; goto err4; } - udc_controller->nullp = virt_to_phys((void *)udc_controller->nullbuf); - if (udc_controller->nullp == DMA_ADDR_INVALID) { - udc_controller->nullp = dma_map_single( - udc_controller->gadget.dev.parent, - udc_controller->nullbuf, + udc->nullp = virt_to_phys((void *)udc->nullbuf); + if (udc->nullp == DMA_ADDR_INVALID) { + udc->nullp = dma_map_single( + udc->gadget.dev.parent, + udc->nullbuf, 256, DMA_TO_DEVICE); - udc_controller->nullmap = 1; + udc->nullmap = 1; } else { - dma_sync_single_for_device(udc_controller->gadget.dev.parent, - udc_controller->nullp, 256, + dma_sync_single_for_device(udc->gadget.dev.parent, + udc->nullp, 256, DMA_TO_DEVICE); } - tasklet_init(&udc_controller->rx_tasklet, ep_rx_tasklet, - (unsigned long)udc_controller); + tasklet_init(&udc->rx_tasklet, ep_rx_tasklet, + (unsigned long)udc); /* request irq and disable DR */ - udc_controller->usb_irq = irq_of_parse_and_map(np, 0); - if (!udc_controller->usb_irq) { + udc->usb_irq = irq_of_parse_and_map(np, 0); + if (!udc->usb_irq) { ret = -EINVAL; goto err_noirq; } - ret = request_irq(udc_controller->usb_irq, qe_udc_irq, 0, - driver_name, udc_controller); + ret = request_irq(udc->usb_irq, qe_udc_irq, 0, + driver_name, udc); if (ret) { - dev_err(udc_controller->dev, "cannot request irq %d err %d \n", - udc_controller->usb_irq, ret); + dev_err(udc->dev, "cannot request irq %d err %d\n", + udc->usb_irq, ret); goto err5; } - ret = device_add(&udc_controller->gadget.dev); + ret = device_add(&udc->gadget.dev); if (ret) goto err6; - ret = usb_add_gadget_udc(&ofdev->dev, &udc_controller->gadget); + ret = usb_add_gadget_udc(&ofdev->dev, &udc->gadget); if (ret) goto err7; - dev_info(udc_controller->dev, + dev_set_drvdata(&ofdev->dev, udc); + dev_info(udc->dev, "%s USB controller initialized as device\n", - (udc_controller->soc_type == PORT_QE) ? "QE" : "CPM"); + (udc->soc_type == PORT_QE) ? "QE" : "CPM"); return 0; err7: - device_unregister(&udc_controller->gadget.dev); + device_unregister(&udc->gadget.dev); err6: - free_irq(udc_controller->usb_irq, udc_controller); + free_irq(udc->usb_irq, udc); err5: - irq_dispose_mapping(udc_controller->usb_irq); + irq_dispose_mapping(udc->usb_irq); err_noirq: - if (udc_controller->nullmap) { - dma_unmap_single(udc_controller->gadget.dev.parent, - udc_controller->nullp, 256, + if (udc->nullmap) { + dma_unmap_single(udc->gadget.dev.parent, + udc->nullp, 256, DMA_TO_DEVICE); - udc_controller->nullp = DMA_ADDR_INVALID; + udc->nullp = DMA_ADDR_INVALID; } else { - dma_sync_single_for_cpu(udc_controller->gadget.dev.parent, - udc_controller->nullp, 256, + dma_sync_single_for_cpu(udc->gadget.dev.parent, + udc->nullp, 256, DMA_TO_DEVICE); } - kfree(udc_controller->statusbuf); + kfree(udc->statusbuf); err4: - kfree(udc_controller->nullbuf); + kfree(udc->nullbuf); err3: - ep = &udc_controller->eps[0]; + ep = &udc->eps[0]; cpm_muram_free(cpm_muram_offset(ep->rxbase)); kfree(ep->rxframe); kfree(ep->rxbuffer); kfree(ep->txframe); err2: - iounmap(udc_controller->usb_regs); + iounmap(udc->usb_regs); err1: - kfree(udc_controller); - udc_controller = NULL; + kfree(udc); return ret; } @@ -2723,44 +2653,41 @@ static int qe_udc_resume(struct platform_device *dev) static int __devexit qe_udc_remove(struct platform_device *ofdev) { + struct qe_udc *udc = dev_get_drvdata(&ofdev->dev); struct qe_ep *ep; unsigned int size; - DECLARE_COMPLETION(done); - if (!udc_controller) - return -ENODEV; - - usb_del_gadget_udc(&udc_controller->gadget); + usb_del_gadget_udc(&udc->gadget); - udc_controller->done = &done; - tasklet_disable(&udc_controller->rx_tasklet); + udc->done = &done; + tasklet_disable(&udc->rx_tasklet); - if (udc_controller->nullmap) { - dma_unmap_single(udc_controller->gadget.dev.parent, - udc_controller->nullp, 256, + if (udc->nullmap) { + dma_unmap_single(udc->gadget.dev.parent, + udc->nullp, 256, DMA_TO_DEVICE); - udc_controller->nullp = DMA_ADDR_INVALID; + udc->nullp = DMA_ADDR_INVALID; } else { - dma_sync_single_for_cpu(udc_controller->gadget.dev.parent, - udc_controller->nullp, 256, + dma_sync_single_for_cpu(udc->gadget.dev.parent, + udc->nullp, 256, DMA_TO_DEVICE); } - kfree(udc_controller->statusbuf); - kfree(udc_controller->nullbuf); + kfree(udc->statusbuf); + kfree(udc->nullbuf); - ep = &udc_controller->eps[0]; + ep = &udc->eps[0]; cpm_muram_free(cpm_muram_offset(ep->rxbase)); size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * (USB_BDRING_LEN + 1); kfree(ep->rxframe); if (ep->rxbufmap) { - dma_unmap_single(udc_controller->gadget.dev.parent, + dma_unmap_single(udc->gadget.dev.parent, ep->rxbuf_d, size, DMA_FROM_DEVICE); ep->rxbuf_d = DMA_ADDR_INVALID; } else { - dma_sync_single_for_cpu(udc_controller->gadget.dev.parent, + dma_sync_single_for_cpu(udc->gadget.dev.parent, ep->rxbuf_d, size, DMA_FROM_DEVICE); } @@ -2768,14 +2695,14 @@ static int __devexit qe_udc_remove(struct platform_device *ofdev) kfree(ep->rxbuffer); kfree(ep->txframe); - free_irq(udc_controller->usb_irq, udc_controller); - irq_dispose_mapping(udc_controller->usb_irq); + free_irq(udc->usb_irq, udc); + irq_dispose_mapping(udc->usb_irq); - tasklet_kill(&udc_controller->rx_tasklet); + tasklet_kill(&udc->rx_tasklet); - iounmap(udc_controller->usb_regs); + iounmap(udc->usb_regs); - device_unregister(&udc_controller->gadget.dev); + device_unregister(&udc->gadget.dev); /* wait for release() of gadget.dev to free udc */ wait_for_completion(&done); diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/fsl_qe_udc.h index 1da5fb03d218..4c07ca9cebf3 100644 --- a/drivers/usb/gadget/fsl_qe_udc.h +++ b/drivers/usb/gadget/fsl_qe_udc.h @@ -266,7 +266,6 @@ struct qe_ep { struct usb_ep ep; struct list_head queue; struct qe_udc *udc; - const struct usb_endpoint_descriptor *desc; struct usb_gadget *gadget; u8 state; diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 55abfb6bd612..28316858208b 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007,2011 Freescale Semiconductor, Inc. + * Copyright (C) 2004-2007,2011-2012 Freescale Semiconductor, Inc. * All rights reserved. * * Author: Li Yang <leoli@freescale.com> @@ -58,9 +58,8 @@ static const char driver_name[] = "fsl-usb2-udc"; static const char driver_desc[] = DRIVER_DESC; static struct usb_dr_device *dr_regs; -#ifndef CONFIG_ARCH_MXC + static struct usb_sys_interface *usb_sys_regs; -#endif /* it is initialized in probe() */ static struct fsl_udc *udc_controller = NULL; @@ -244,10 +243,9 @@ static int dr_controller_setup(struct fsl_udc *udc) { unsigned int tmp, portctrl, ep_num; unsigned int max_no_of_ep; -#ifndef CONFIG_ARCH_MXC unsigned int ctrl; -#endif unsigned long timeout; + #define FSL_UDC_RESET_TIMEOUT 1000 /* Config PHY interface */ @@ -255,12 +253,32 @@ static int dr_controller_setup(struct fsl_udc *udc) portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH); switch (udc->phy_mode) { case FSL_USB2_PHY_ULPI: + if (udc->pdata->have_sysif_regs) { + if (udc->pdata->controller_ver) { + /* controller version 1.6 or above */ + ctrl = __raw_readl(&usb_sys_regs->control); + ctrl &= ~USB_CTRL_UTMI_PHY_EN; + ctrl |= USB_CTRL_USB_EN; + __raw_writel(ctrl, &usb_sys_regs->control); + } + } portctrl |= PORTSCX_PTS_ULPI; break; case FSL_USB2_PHY_UTMI_WIDE: portctrl |= PORTSCX_PTW_16BIT; /* fall through */ case FSL_USB2_PHY_UTMI: + if (udc->pdata->have_sysif_regs) { + if (udc->pdata->controller_ver) { + /* controller version 1.6 or above */ + ctrl = __raw_readl(&usb_sys_regs->control); + ctrl |= (USB_CTRL_UTMI_PHY_EN | + USB_CTRL_USB_EN); + __raw_writel(ctrl, &usb_sys_regs->control); + mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI + PHY CLK to become stable - 10ms*/ + } + } portctrl |= PORTSCX_PTS_UTMI; break; case FSL_USB2_PHY_SERIAL: @@ -549,7 +567,7 @@ static int fsl_ep_enable(struct usb_ep *_ep, ep = container_of(_ep, struct fsl_ep, ep); /* catch various bogus parameters */ - if (!_ep || !desc || ep->desc + if (!_ep || !desc || ep->ep.desc || (desc->bDescriptorType != USB_DT_ENDPOINT)) return -EINVAL; @@ -590,7 +608,7 @@ static int fsl_ep_enable(struct usb_ep *_ep, spin_lock_irqsave(&udc->lock, flags); ep->ep.maxpacket = max; - ep->desc = desc; + ep->ep.desc = desc; ep->stopped = 0; /* Controller related setup */ @@ -614,7 +632,7 @@ static int fsl_ep_enable(struct usb_ep *_ep, retval = 0; VDBG("enabled %s (ep%d%s) maxpacket %d",ep->ep.name, - ep->desc->bEndpointAddress & 0x0f, + ep->ep.desc->bEndpointAddress & 0x0f, (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out", max); en_done: @@ -634,7 +652,7 @@ static int fsl_ep_disable(struct usb_ep *_ep) int ep_num; ep = container_of(_ep, struct fsl_ep, ep); - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { VDBG("%s not enabled", _ep ? ep->ep.name : NULL); return -EINVAL; } @@ -657,7 +675,6 @@ static int fsl_ep_disable(struct usb_ep *_ep) /* nuke all pending requests (does flush) */ nuke(ep, -ESHUTDOWN); - ep->desc = NULL; ep->ep.desc = NULL; ep->stopped = 1; spin_unlock_irqrestore(&udc->lock, flags); @@ -736,6 +753,8 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) lastreq = list_entry(ep->queue.prev, struct fsl_req, queue); lastreq->tail->next_td_ptr = cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK); + /* Ensure dTD's next dtd pointer to be updated */ + wmb(); /* Read prime bit, if 1 goto done */ if (fsl_readl(&dr_regs->endpointprime) & bitmask) return; @@ -874,11 +893,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) VDBG("%s, bad params", __func__); return -EINVAL; } - if (unlikely(!_ep || !ep->desc)) { + if (unlikely(!_ep || !ep->ep.desc)) { VDBG("%s, bad ep", __func__); return -EINVAL; } - if (usb_endpoint_xfer_isoc(ep->desc)) { + if (usb_endpoint_xfer_isoc(ep->ep.desc)) { if (req->req.length > ep->ep.maxpacket) return -EMSGSIZE; } @@ -1017,12 +1036,12 @@ static int fsl_ep_set_halt(struct usb_ep *_ep, int value) ep = container_of(_ep, struct fsl_ep, ep); udc = ep->udc; - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { status = -EINVAL; goto out; } - if (usb_endpoint_xfer_isoc(ep->desc)) { + if (usb_endpoint_xfer_isoc(ep->ep.desc)) { status = -EOPNOTSUPP; goto out; } @@ -1061,7 +1080,7 @@ static int fsl_ep_fifo_status(struct usb_ep *_ep) struct ep_queue_head *qh; ep = container_of(_ep, struct fsl_ep, ep); - if (!_ep || (!ep->desc && ep_index(ep) != 0)) + if (!_ep || (!ep->ep.desc && ep_index(ep) != 0)) return -ENODEV; udc = (struct fsl_udc *)ep->udc; @@ -1094,7 +1113,7 @@ static void fsl_ep_fifo_flush(struct usb_ep *_ep) return; } else { ep = container_of(_ep, struct fsl_ep, ep); - if (!ep->desc) + if (!ep->ep.desc) return; } ep_num = ep_index(ep); @@ -1349,7 +1368,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, target_ep = get_ep_by_pipe(udc, get_pipe_by_windex(index)); /* stall if endpoint doesn't exist */ - if (!target_ep->desc) + if (!target_ep->ep.desc) goto stall; tmp = dr_ep_get_stall(ep_index(target_ep), ep_is_in(target_ep)) << USB_ENDPOINT_HALT; @@ -2259,7 +2278,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, } /* other gadget->eplist ep */ list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { - if (ep->desc) { + if (ep->ep.desc) { t = scnprintf(next, size, "\nFor %s Maxpkt is 0x%x " "index is 0x%x\n", diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index e651469fd39b..5cd7b7e7ddb4 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -1,4 +1,12 @@ /* + * Copyright (C) 2004,2012 Freescale Semiconductor, Inc + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * * Freescale USB device/endpoint management registers */ #ifndef __FSL_USB2_UDC_H @@ -348,6 +356,9 @@ struct usb_sys_interface { /* control Register Bit Masks */ #define USB_CTRL_IOENB 0x00000004 #define USB_CTRL_ULPI_INT0EN 0x00000001 +#define USB_CTRL_UTMI_PHY_EN 0x00000200 +#define USB_CTRL_USB_EN 0x00000004 +#define USB_CTRL_ULPI_PHY_CLK_SEL 0x00000400 /* Endpoint Queue Head data struct * Rem: all the variables of qh are LittleEndian Mode @@ -450,7 +461,6 @@ struct fsl_ep { struct list_head queue; struct fsl_udc *udc; struct ep_queue_head *qh; - const struct usb_endpoint_descriptor *desc; struct usb_gadget *gadget; char name[14]; diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index 5831cb4a0b35..cdd94540e1cd 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -203,7 +203,7 @@ static int config_ep(struct fusb300_ep *ep, struct fusb300 *fusb300 = ep->fusb300; struct fusb300_ep_info info; - ep->desc = desc; + ep->ep.desc = desc; info.interval = 0; info.addrofs = 0; @@ -443,7 +443,7 @@ static int fusb300_queue(struct usb_ep *_ep, struct usb_request *_req, req->req.actual = 0; req->req.status = -EINPROGRESS; - if (ep->desc == NULL) /* ep0 */ + if (ep->ep.desc == NULL) /* ep0 */ ep0_queue(ep, req); else if (request && !ep->stall) enable_fifo_int(ep); diff --git a/drivers/usb/gadget/fusb300_udc.h b/drivers/usb/gadget/fusb300_udc.h index 92745bd03064..542cd83cc806 100644 --- a/drivers/usb/gadget/fusb300_udc.h +++ b/drivers/usb/gadget/fusb300_udc.h @@ -650,7 +650,6 @@ struct fusb300_ep { unsigned char epnum; unsigned char type; - const struct usb_endpoint_descriptor *desc; }; struct fusb300 { diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h index e84b3c47ed3c..71ca193358b8 100644 --- a/drivers/usb/gadget/g_zero.h +++ b/drivers/usb/gadget/g_zero.h @@ -13,10 +13,11 @@ extern unsigned buflen; extern const struct usb_descriptor_header *otg_desc[]; /* common utilities */ -struct usb_request *alloc_ep_req(struct usb_ep *ep); +struct usb_request *alloc_ep_req(struct usb_ep *ep, int len); void free_ep_req(struct usb_ep *ep, struct usb_request *req); void disable_endpoints(struct usb_composite_dev *cdev, - struct usb_ep *in, struct usb_ep *out); + struct usb_ep *in, struct usb_ep *out, + struct usb_ep *iso_in, struct usb_ep *iso_out); /* configuration-specific linkup */ int sourcesink_add(struct usb_composite_dev *cdev, bool autoresume); diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index a8855d0b7f3b..b8b3a3411218 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -37,6 +37,7 @@ #define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name)) #define gadget_is_imx(g) (!strcmp("imx_udc", (g)->name)) #define gadget_is_langwell(g) (!strcmp("langwell_udc", (g)->name)) +#define gadget_is_lpc32xx(g) (!strcmp("lpc32xx_udc", (g)->name)) #define gadget_is_m66592(g) (!strcmp("m66592_udc", (g)->name)) #define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name)) #define gadget_is_net2272(g) (!strcmp("net2272", (g)->name)) @@ -118,6 +119,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x31; else if (gadget_is_dwc3(gadget)) return 0x32; + else if (gadget_is_lpc32xx(gadget)) + return 0x33; return -ENOENT; } diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index e151d6b87dee..b241e6c6a7f2 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -102,7 +102,7 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) unsigned long flags; ep = container_of(_ep, struct goku_ep, ep); - if (!_ep || !desc || ep->desc + if (!_ep || !desc || ep->ep.desc || desc->bDescriptorType != USB_DT_ENDPOINT) return -EINVAL; dev = ep->dev; @@ -176,7 +176,7 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) command(ep->dev->regs, COMMAND_RESET, ep->num); ep->ep.maxpacket = max; ep->stopped = 0; - ep->desc = desc; + ep->ep.desc = desc; spin_unlock_irqrestore(&ep->dev->lock, flags); DBG(dev, "enable %s %s %s maxpacket %u\n", ep->ep.name, @@ -233,7 +233,6 @@ static void ep_reset(struct goku_udc_regs __iomem *regs, struct goku_ep *ep) } ep->ep.maxpacket = MAX_FIFO_SIZE; - ep->desc = NULL; ep->ep.desc = NULL; ep->stopped = 1; ep->irqs = 0; @@ -247,7 +246,7 @@ static int goku_ep_disable(struct usb_ep *_ep) unsigned long flags; ep = container_of(_ep, struct goku_ep, ep); - if (!_ep || !ep->desc) + if (!_ep || !ep->ep.desc) return -ENODEV; dev = ep->dev; if (dev->ep0state == EP0_SUSPEND) @@ -722,7 +721,7 @@ goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) || !_req->buf || !list_empty(&req->queue))) return -EINVAL; ep = container_of(_ep, struct goku_ep, ep); - if (unlikely(!_ep || (!ep->desc && ep->num != 0))) + if (unlikely(!_ep || (!ep->ep.desc && ep->num != 0))) return -EINVAL; dev = ep->dev; if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) @@ -815,7 +814,7 @@ static int goku_dequeue(struct usb_ep *_ep, struct usb_request *_req) unsigned long flags; ep = container_of(_ep, struct goku_ep, ep); - if (!_ep || !_req || (!ep->desc && ep->num != 0)) + if (!_ep || !_req || (!ep->ep.desc && ep->num != 0)) return -EINVAL; dev = ep->dev; if (!dev->driver) @@ -896,7 +895,7 @@ static int goku_set_halt(struct usb_ep *_ep, int value) return -EINVAL; /* don't change EPxSTATUS_EP_INVALID to READY */ - } else if (!ep->desc) { + } else if (!ep->ep.desc) { DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name); return -EINVAL; } @@ -955,7 +954,7 @@ static void goku_fifo_flush(struct usb_ep *_ep) VDBG(ep->dev, "%s %s\n", __func__, ep->ep.name); /* don't change EPxSTATUS_EP_INVALID to READY */ - if (!ep->desc && ep->num != 0) { + if (!ep->ep.desc && ep->num != 0) { DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name); return; } @@ -1152,7 +1151,7 @@ udc_proc_read(char *buffer, char **start, off_t off, int count, struct goku_ep *ep = &dev->ep [i]; struct goku_request *req; - if (i && !ep->desc) + if (i && !ep->ep.desc) continue; tmp = readl(ep->reg_status); @@ -1473,7 +1472,8 @@ static void ep0_setup(struct goku_udc *dev) case USB_RECIP_ENDPOINT: tmp = le16_to_cpu(ctrl.wIndex) & 0x0f; /* active endpoint */ - if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0)) + if (tmp > 3 || + (!dev->ep[tmp].ep.desc && tmp != 0)) goto stall; if (ctrl.wIndex & cpu_to_le16( USB_DIR_IN)) { @@ -1895,14 +1895,4 @@ static struct pci_driver goku_pci_driver = { /* FIXME add power management support */ }; -static int __init init (void) -{ - return pci_register_driver (&goku_pci_driver); -} -module_init (init); - -static void __exit cleanup (void) -{ - pci_unregister_driver (&goku_pci_driver); -} -module_exit (cleanup); +module_pci_driver(goku_pci_driver); diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h index e7e0c69d3b1f..85cdce0d1901 100644 --- a/drivers/usb/gadget/goku_udc.h +++ b/drivers/usb/gadget/goku_udc.h @@ -216,7 +216,6 @@ struct goku_ep { /* analogous to a host-side qh */ struct list_head queue; - const struct usb_endpoint_descriptor *desc; u32 __iomem *reg_fifo; u32 __iomem *reg_mode; diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 8d1c75abd73d..54034f84f992 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1237,14 +1237,15 @@ irq_handler_t intr_handler(int i) ******************************************************************************* */ -static int imx_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); -static int imx_udc_stop(struct usb_gadget_driver *driver); +static int imx_udc_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); +static int imx_udc_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); static const struct usb_gadget_ops imx_udc_ops = { - .get_frame = imx_udc_get_frame, - .wakeup = imx_udc_wakeup, - .start = imx_udc_start, - .stop = imx_udc_stop, + .get_frame = imx_udc_get_frame, + .wakeup = imx_udc_wakeup, + .udc_start = imx_udc_start, + .udc_stop = imx_udc_stop, }; static struct imx_udc_struct controller = { @@ -1329,23 +1330,13 @@ static struct imx_udc_struct controller = { * USB gadget driver functions ******************************************************************************* */ -static int imx_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) +static int imx_udc_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct imx_udc_struct *imx_usb = &controller; + struct imx_udc_struct *imx_usb; int retval; - if (!driver - || driver->max_speed < USB_SPEED_FULL - || !bind - || !driver->disconnect - || !driver->setup) - return -EINVAL; - if (!imx_usb) - return -ENODEV; - if (imx_usb->driver) - return -EBUSY; - + imx_usb = container_of(gadget, struct imx_udc_struct, gadget); /* first hook up the driver ... */ imx_usb->driver = driver; imx_usb->gadget.dev.driver = &driver->driver; @@ -1353,14 +1344,6 @@ static int imx_udc_start(struct usb_gadget_driver *driver, retval = device_add(&imx_usb->gadget.dev); if (retval) goto fail; - retval = bind(&imx_usb->gadget); - if (retval) { - D_ERR(imx_usb->dev, "<%s> bind to driver %s --> error %d\n", - __func__, driver->driver.name, retval); - device_del(&imx_usb->gadget.dev); - - goto fail; - } D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n", __func__, driver->driver.name); @@ -1374,20 +1357,16 @@ fail: return retval; } -static int imx_udc_stop(struct usb_gadget_driver *driver) +static int imx_udc_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct imx_udc_struct *imx_usb = &controller; - - if (!imx_usb) - return -ENODEV; - if (!driver || driver != imx_usb->driver || !driver->unbind) - return -EINVAL; + struct imx_udc_struct *imx_usb = container_of(gadget, + struct imx_udc_struct, gadget); udc_stop_activity(imx_usb, driver); imx_udc_disable(imx_usb); del_timer(&imx_usb->timer); - driver->unbind(&imx_usb->gadget); imx_usb->gadget.dev.driver = NULL; imx_usb->driver = NULL; diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index f9cedd52cf20..e119519cdaf4 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -154,7 +154,7 @@ static inline void print_all_registers(struct langwell_udc *dev) /*-------------------------------------------------------------------------*/ #define is_in(ep) (((ep)->ep_num == 0) ? ((ep)->dev->ep0_dir == \ - USB_DIR_IN) : (usb_endpoint_dir_in((ep)->desc))) + USB_DIR_IN) : (usb_endpoint_dir_in((ep)->ep.desc))) #define DIR_STRING(ep) (is_in(ep) ? "in" : "out") @@ -257,7 +257,7 @@ static int langwell_ep_enable(struct usb_ep *_ep, dev = ep->dev; dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (!_ep || !desc || ep->desc + if (!_ep || !desc || ep->ep.desc || desc->bDescriptorType != USB_DT_ENDPOINT) return -EINVAL; @@ -337,7 +337,7 @@ static int langwell_ep_enable(struct usb_ep *_ep, spin_lock_irqsave(&dev->lock, flags); ep->ep.maxpacket = max; - ep->desc = desc; + ep->ep.desc = desc; ep->stopped = 0; ep->ep_num = usb_endpoint_num(desc); @@ -432,7 +432,7 @@ static void nuke(struct langwell_ep *ep, int status) ep->stopped = 1; /* endpoint fifo flush */ - if (&ep->ep && ep->desc) + if (&ep->ep && ep->ep.desc) langwell_ep_fifo_flush(&ep->ep); while (!list_empty(&ep->queue)) { @@ -459,7 +459,7 @@ static int langwell_ep_disable(struct usb_ep *_ep) dev = ep->dev; dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (!_ep || !ep->desc) + if (!_ep || !ep->ep.desc) return -EINVAL; spin_lock_irqsave(&dev->lock, flags); @@ -476,7 +476,6 @@ static int langwell_ep_disable(struct usb_ep *_ep) /* nuke all pending requests (does flush) */ nuke(ep, -ESHUTDOWN); - ep->desc = NULL; ep->ep.desc = NULL; ep->stopped = 1; @@ -752,14 +751,14 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req, return -EINVAL; } - if (unlikely(!_ep || !ep->desc)) + if (unlikely(!_ep || !ep->ep.desc)) return -EINVAL; dev = ep->dev; req->ep = ep; dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (usb_endpoint_xfer_isoc(ep->desc)) { + if (usb_endpoint_xfer_isoc(ep->ep.desc)) { if (req->req.length > ep->ep.maxpacket) return -EMSGSIZE; is_iso = 1; @@ -822,7 +821,7 @@ static int langwell_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) dev = ep->dev; dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (!_ep || !ep->desc || !_req) + if (!_ep || !ep->ep.desc || !_req) return -EINVAL; if (!dev->driver) @@ -950,13 +949,13 @@ static int langwell_ep_set_halt(struct usb_ep *_ep, int value) dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (!_ep || !ep->desc) + if (!_ep || !ep->ep.desc) return -EINVAL; if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; - if (usb_endpoint_xfer_isoc(ep->desc)) + if (usb_endpoint_xfer_isoc(ep->ep.desc)) return -EOPNOTSUPP; spin_lock_irqsave(&dev->lock, flags); @@ -999,7 +998,7 @@ static int langwell_ep_set_wedge(struct usb_ep *_ep) dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (!_ep || !ep->desc) + if (!_ep || !ep->ep.desc) return -EINVAL; dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); @@ -1020,8 +1019,8 @@ static void langwell_ep_fifo_flush(struct usb_ep *_ep) dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (!_ep || !ep->desc) { - dev_vdbg(&dev->pdev->dev, "ep or ep->desc is NULL\n"); + if (!_ep || !ep->ep.desc) { + dev_vdbg(&dev->pdev->dev, "ep or ep->ep.desc is NULL\n"); dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return; } @@ -1402,7 +1401,7 @@ static int eps_reinit(struct langwell_udc *dev) ep->stopped = 0; ep->ep.maxpacket = EP0_MAX_PKT_SIZE; ep->ep_num = 0; - ep->desc = &langwell_ep0_desc; + ep->ep.desc = &langwell_ep0_desc; INIT_LIST_HEAD(&ep->queue); ep->ep_type = USB_ENDPOINT_XFER_CONTROL; @@ -1737,7 +1736,7 @@ static ssize_t show_langwell_udc(struct device *_dev, } /* other gadget->eplist ep */ list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) { - if (ep->desc) { + if (ep->ep.desc) { t = scnprintf(next, size, "\n%s MaxPacketSize: 0x%x, " "ep_num: %d\n", @@ -2046,10 +2045,10 @@ static struct langwell_ep *get_ep_by_windex(struct langwell_udc *dev, list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) { u8 bEndpointAddress; - if (!ep->desc) + if (!ep->ep.desc) continue; - bEndpointAddress = ep->desc->bEndpointAddress; + bEndpointAddress = ep->ep.desc->bEndpointAddress; if ((wIndex ^ bEndpointAddress) & USB_DIR_IN) continue; @@ -3412,23 +3411,9 @@ static struct pci_driver langwell_pci_driver = { .shutdown = langwell_udc_shutdown, }; - -static int __init init(void) -{ - return pci_register_driver(&langwell_pci_driver); -} -module_init(init); - - -static void __exit cleanup(void) -{ - pci_unregister_driver(&langwell_pci_driver); -} -module_exit(cleanup); - +module_pci_driver(langwell_pci_driver); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR("Xiaochen Shen <xiaochen.shen@intel.com>"); MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); - diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h index 8c8087abb481..38fa3c86d85c 100644 --- a/drivers/usb/gadget/langwell_udc.h +++ b/drivers/usb/gadget/langwell_udc.h @@ -116,7 +116,6 @@ struct langwell_ep { unsigned long irqs; struct list_head queue; struct langwell_dqh *dqh; - const struct usb_endpoint_descriptor *desc; char name[14]; unsigned stopped:1, ep_type:2, diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c new file mode 100644 index 000000000000..262acfd53e32 --- /dev/null +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -0,0 +1,3538 @@ +/* + * USB Gadget driver for LPC32xx + * + * Authors: + * Kevin Wells <kevin.wells@nxp.com> + * Mike James + * Roland Stigge <stigge@antcom.de> + * + * Copyright (C) 2006 Philips Semiconductors + * Copyright (C) 2009 NXP Semiconductors + * Copyright (C) 2012 Roland Stigge + * + * Note: This driver is based on original work done by Mike James for + * the LPC3180. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/ioport.h> +#include <linux/slab.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/list.h> +#include <linux/interrupt.h> +#include <linux/proc_fs.h> +#include <linux/clk.h> +#include <linux/usb/ch9.h> +#include <linux/usb/gadget.h> +#include <linux/i2c.h> +#include <linux/kthread.h> +#include <linux/freezer.h> +#include <linux/dma-mapping.h> +#include <linux/dmapool.h> +#include <linux/workqueue.h> +#include <linux/of.h> +#include <linux/usb/isp1301.h> + +#include <asm/byteorder.h> +#include <mach/hardware.h> +#include <linux/io.h> +#include <asm/irq.h> +#include <asm/system.h> + +#include <mach/platform.h> +#include <mach/irqs.h> +#include <mach/board.h> +#ifdef CONFIG_USB_GADGET_DEBUG_FILES +#include <linux/seq_file.h> +#endif + +/* + * USB device configuration structure + */ +typedef void (*usc_chg_event)(int); +struct lpc32xx_usbd_cfg { + int vbus_drv_pol; /* 0=active low drive for VBUS via ISP1301 */ + usc_chg_event conn_chgb; /* Connection change event (optional) */ + usc_chg_event susp_chgb; /* Suspend/resume event (optional) */ + usc_chg_event rmwk_chgb; /* Enable/disable remote wakeup */ +}; + +/* + * controller driver data structures + */ + +/* 16 endpoints (not to be confused with 32 hardware endpoints) */ +#define NUM_ENDPOINTS 16 + +/* + * IRQ indices make reading the code a little easier + */ +#define IRQ_USB_LP 0 +#define IRQ_USB_HP 1 +#define IRQ_USB_DEVDMA 2 +#define IRQ_USB_ATX 3 + +#define EP_OUT 0 /* RX (from host) */ +#define EP_IN 1 /* TX (to host) */ + +/* Returns the interrupt mask for the selected hardware endpoint */ +#define EP_MASK_SEL(ep, dir) (1 << (((ep) * 2) + dir)) + +#define EP_INT_TYPE 0 +#define EP_ISO_TYPE 1 +#define EP_BLK_TYPE 2 +#define EP_CTL_TYPE 3 + +/* EP0 states */ +#define WAIT_FOR_SETUP 0 /* Wait for setup packet */ +#define DATA_IN 1 /* Expect dev->host transfer */ +#define DATA_OUT 2 /* Expect host->dev transfer */ + +/* DD (DMA Descriptor) structure, requires word alignment, this is already + * defined in the LPC32XX USB device header file, but this version is slightly + * modified to tag some work data with each DMA descriptor. */ +struct lpc32xx_usbd_dd_gad { + u32 dd_next_phy; + u32 dd_setup; + u32 dd_buffer_addr; + u32 dd_status; + u32 dd_iso_ps_mem_addr; + u32 this_dma; + u32 iso_status[6]; /* 5 spare */ + u32 dd_next_v; +}; + +/* + * Logical endpoint structure + */ +struct lpc32xx_ep { + struct usb_ep ep; + struct list_head queue; + struct lpc32xx_udc *udc; + + u32 hwep_num_base; /* Physical hardware EP */ + u32 hwep_num; /* Maps to hardware endpoint */ + u32 maxpacket; + u32 lep; + + bool is_in; + bool req_pending; + u32 eptype; + + u32 totalints; + + bool wedge; + + const struct usb_endpoint_descriptor *desc; +}; + +/* + * Common UDC structure + */ +struct lpc32xx_udc { + struct usb_gadget gadget; + struct usb_gadget_driver *driver; + struct platform_device *pdev; + struct device *dev; + struct dentry *pde; + spinlock_t lock; + struct i2c_client *isp1301_i2c_client; + + /* Board and device specific */ + struct lpc32xx_usbd_cfg *board; + u32 io_p_start; + u32 io_p_size; + void __iomem *udp_baseaddr; + int udp_irq[4]; + struct clk *usb_pll_clk; + struct clk *usb_slv_clk; + + /* DMA support */ + u32 *udca_v_base; + u32 udca_p_base; + struct dma_pool *dd_cache; + + /* Common EP and control data */ + u32 enabled_devints; + u32 enabled_hwepints; + u32 dev_status; + u32 realized_eps; + + /* VBUS detection, pullup, and power flags */ + u8 vbus; + u8 last_vbus; + int pullup; + int poweron; + + /* Work queues related to I2C support */ + struct work_struct pullup_job; + struct work_struct vbus_job; + struct work_struct power_job; + + /* USB device peripheral - various */ + struct lpc32xx_ep ep[NUM_ENDPOINTS]; + bool enabled; + bool clocked; + bool suspended; + bool selfpowered; + int ep0state; + atomic_t enabled_ep_cnt; + wait_queue_head_t ep_disable_wait_queue; +}; + +/* + * Endpoint request + */ +struct lpc32xx_request { + struct usb_request req; + struct list_head queue; + struct lpc32xx_usbd_dd_gad *dd_desc_ptr; + bool mapped; + bool send_zlp; +}; + +static inline struct lpc32xx_udc *to_udc(struct usb_gadget *g) +{ + return container_of(g, struct lpc32xx_udc, gadget); +} + +#define ep_dbg(epp, fmt, arg...) \ + dev_dbg(epp->udc->dev, "%s: " fmt, __func__, ## arg) +#define ep_err(epp, fmt, arg...) \ + dev_err(epp->udc->dev, "%s: " fmt, __func__, ## arg) +#define ep_info(epp, fmt, arg...) \ + dev_info(epp->udc->dev, "%s: " fmt, __func__, ## arg) +#define ep_warn(epp, fmt, arg...) \ + dev_warn(epp->udc->dev, "%s:" fmt, __func__, ## arg) + +#define UDCA_BUFF_SIZE (128) + +/* TODO: When the clock framework is introduced in LPC32xx, IO_ADDRESS will + * be replaced with an inremap()ed pointer, see USB_OTG_CLK_CTRL() + * */ +#define USB_CTRL IO_ADDRESS(LPC32XX_CLK_PM_BASE + 0x64) +#define USB_CLOCK_MASK (AHB_M_CLOCK_ON | OTG_CLOCK_ON | \ + DEV_CLOCK_ON | I2C_CLOCK_ON) + +/* USB_CTRL bit defines */ +#define USB_SLAVE_HCLK_EN (1 << 24) +#define USB_HOST_NEED_CLK_EN (1 << 21) +#define USB_DEV_NEED_CLK_EN (1 << 22) + +#define USB_OTG_CLK_CTRL(udc) ((udc)->udp_baseaddr + 0xFF4) +#define USB_OTG_CLK_STAT(udc) ((udc)->udp_baseaddr + 0xFF8) + +/* USB_OTG_CLK_CTRL bit defines */ +#define AHB_M_CLOCK_ON (1 << 4) +#define OTG_CLOCK_ON (1 << 3) +#define I2C_CLOCK_ON (1 << 2) +#define DEV_CLOCK_ON (1 << 1) +#define HOST_CLOCK_ON (1 << 0) + +#define USB_OTG_STAT_CONTROL(udc) (udc->udp_baseaddr + 0x110) + +/* USB_OTG_STAT_CONTROL bit defines */ +#define TRANSPARENT_I2C_EN (1 << 7) +#define HOST_EN (1 << 0) + +/********************************************************************** + * USB device controller register offsets + **********************************************************************/ + +#define USBD_DEVINTST(x) ((x) + 0x200) +#define USBD_DEVINTEN(x) ((x) + 0x204) +#define USBD_DEVINTCLR(x) ((x) + 0x208) +#define USBD_DEVINTSET(x) ((x) + 0x20C) +#define USBD_CMDCODE(x) ((x) + 0x210) +#define USBD_CMDDATA(x) ((x) + 0x214) +#define USBD_RXDATA(x) ((x) + 0x218) +#define USBD_TXDATA(x) ((x) + 0x21C) +#define USBD_RXPLEN(x) ((x) + 0x220) +#define USBD_TXPLEN(x) ((x) + 0x224) +#define USBD_CTRL(x) ((x) + 0x228) +#define USBD_DEVINTPRI(x) ((x) + 0x22C) +#define USBD_EPINTST(x) ((x) + 0x230) +#define USBD_EPINTEN(x) ((x) + 0x234) +#define USBD_EPINTCLR(x) ((x) + 0x238) +#define USBD_EPINTSET(x) ((x) + 0x23C) +#define USBD_EPINTPRI(x) ((x) + 0x240) +#define USBD_REEP(x) ((x) + 0x244) +#define USBD_EPIND(x) ((x) + 0x248) +#define USBD_EPMAXPSIZE(x) ((x) + 0x24C) +/* DMA support registers only below */ +/* Set, clear, or get enabled state of the DMA request status. If + * enabled, an IN or OUT token will start a DMA transfer for the EP */ +#define USBD_DMARST(x) ((x) + 0x250) +#define USBD_DMARCLR(x) ((x) + 0x254) +#define USBD_DMARSET(x) ((x) + 0x258) +/* DMA UDCA head pointer */ +#define USBD_UDCAH(x) ((x) + 0x280) +/* EP DMA status, enable, and disable. This is used to specifically + * enabled or disable DMA for a specific EP */ +#define USBD_EPDMAST(x) ((x) + 0x284) +#define USBD_EPDMAEN(x) ((x) + 0x288) +#define USBD_EPDMADIS(x) ((x) + 0x28C) +/* DMA master interrupts enable and pending interrupts */ +#define USBD_DMAINTST(x) ((x) + 0x290) +#define USBD_DMAINTEN(x) ((x) + 0x294) +/* DMA end of transfer interrupt enable, disable, status */ +#define USBD_EOTINTST(x) ((x) + 0x2A0) +#define USBD_EOTINTCLR(x) ((x) + 0x2A4) +#define USBD_EOTINTSET(x) ((x) + 0x2A8) +/* New DD request interrupt enable, disable, status */ +#define USBD_NDDRTINTST(x) ((x) + 0x2AC) +#define USBD_NDDRTINTCLR(x) ((x) + 0x2B0) +#define USBD_NDDRTINTSET(x) ((x) + 0x2B4) +/* DMA error interrupt enable, disable, status */ +#define USBD_SYSERRTINTST(x) ((x) + 0x2B8) +#define USBD_SYSERRTINTCLR(x) ((x) + 0x2BC) +#define USBD_SYSERRTINTSET(x) ((x) + 0x2C0) + +/********************************************************************** + * USBD_DEVINTST/USBD_DEVINTEN/USBD_DEVINTCLR/USBD_DEVINTSET/ + * USBD_DEVINTPRI register definitions + **********************************************************************/ +#define USBD_ERR_INT (1 << 9) +#define USBD_EP_RLZED (1 << 8) +#define USBD_TXENDPKT (1 << 7) +#define USBD_RXENDPKT (1 << 6) +#define USBD_CDFULL (1 << 5) +#define USBD_CCEMPTY (1 << 4) +#define USBD_DEV_STAT (1 << 3) +#define USBD_EP_SLOW (1 << 2) +#define USBD_EP_FAST (1 << 1) +#define USBD_FRAME (1 << 0) + +/********************************************************************** + * USBD_EPINTST/USBD_EPINTEN/USBD_EPINTCLR/USBD_EPINTSET/ + * USBD_EPINTPRI register definitions + **********************************************************************/ +/* End point selection macro (RX) */ +#define USBD_RX_EP_SEL(e) (1 << ((e) << 1)) + +/* End point selection macro (TX) */ +#define USBD_TX_EP_SEL(e) (1 << (((e) << 1) + 1)) + +/********************************************************************** + * USBD_REEP/USBD_DMARST/USBD_DMARCLR/USBD_DMARSET/USBD_EPDMAST/ + * USBD_EPDMAEN/USBD_EPDMADIS/ + * USBD_NDDRTINTST/USBD_NDDRTINTCLR/USBD_NDDRTINTSET/ + * USBD_EOTINTST/USBD_EOTINTCLR/USBD_EOTINTSET/ + * USBD_SYSERRTINTST/USBD_SYSERRTINTCLR/USBD_SYSERRTINTSET + * register definitions + **********************************************************************/ +/* Endpoint selection macro */ +#define USBD_EP_SEL(e) (1 << (e)) + +/********************************************************************** + * SBD_DMAINTST/USBD_DMAINTEN + **********************************************************************/ +#define USBD_SYS_ERR_INT (1 << 2) +#define USBD_NEW_DD_INT (1 << 1) +#define USBD_EOT_INT (1 << 0) + +/********************************************************************** + * USBD_RXPLEN register definitions + **********************************************************************/ +#define USBD_PKT_RDY (1 << 11) +#define USBD_DV (1 << 10) +#define USBD_PK_LEN_MASK 0x3FF + +/********************************************************************** + * USBD_CTRL register definitions + **********************************************************************/ +#define USBD_LOG_ENDPOINT(e) ((e) << 2) +#define USBD_WR_EN (1 << 1) +#define USBD_RD_EN (1 << 0) + +/********************************************************************** + * USBD_CMDCODE register definitions + **********************************************************************/ +#define USBD_CMD_CODE(c) ((c) << 16) +#define USBD_CMD_PHASE(p) ((p) << 8) + +/********************************************************************** + * USBD_DMARST/USBD_DMARCLR/USBD_DMARSET register definitions + **********************************************************************/ +#define USBD_DMAEP(e) (1 << (e)) + +/* DD (DMA Descriptor) structure, requires word alignment */ +struct lpc32xx_usbd_dd { + u32 *dd_next; + u32 dd_setup; + u32 dd_buffer_addr; + u32 dd_status; + u32 dd_iso_ps_mem_addr; +}; + +/* dd_setup bit defines */ +#define DD_SETUP_ATLE_DMA_MODE 0x01 +#define DD_SETUP_NEXT_DD_VALID 0x04 +#define DD_SETUP_ISO_EP 0x10 +#define DD_SETUP_PACKETLEN(n) (((n) & 0x7FF) << 5) +#define DD_SETUP_DMALENBYTES(n) (((n) & 0xFFFF) << 16) + +/* dd_status bit defines */ +#define DD_STATUS_DD_RETIRED 0x01 +#define DD_STATUS_STS_MASK 0x1E +#define DD_STATUS_STS_NS 0x00 /* Not serviced */ +#define DD_STATUS_STS_BS 0x02 /* Being serviced */ +#define DD_STATUS_STS_NC 0x04 /* Normal completion */ +#define DD_STATUS_STS_DUR 0x06 /* Data underrun (short packet) */ +#define DD_STATUS_STS_DOR 0x08 /* Data overrun */ +#define DD_STATUS_STS_SE 0x12 /* System error */ +#define DD_STATUS_PKT_VAL 0x20 /* Packet valid */ +#define DD_STATUS_LSB_EX 0x40 /* LS byte extracted (ATLE) */ +#define DD_STATUS_MSB_EX 0x80 /* MS byte extracted (ATLE) */ +#define DD_STATUS_MLEN(n) (((n) >> 8) & 0x3F) +#define DD_STATUS_CURDMACNT(n) (((n) >> 16) & 0xFFFF) + +/* + * + * Protocol engine bits below + * + */ +/* Device Interrupt Bit Definitions */ +#define FRAME_INT 0x00000001 +#define EP_FAST_INT 0x00000002 +#define EP_SLOW_INT 0x00000004 +#define DEV_STAT_INT 0x00000008 +#define CCEMTY_INT 0x00000010 +#define CDFULL_INT 0x00000020 +#define RxENDPKT_INT 0x00000040 +#define TxENDPKT_INT 0x00000080 +#define EP_RLZED_INT 0x00000100 +#define ERR_INT 0x00000200 + +/* Rx & Tx Packet Length Definitions */ +#define PKT_LNGTH_MASK 0x000003FF +#define PKT_DV 0x00000400 +#define PKT_RDY 0x00000800 + +/* USB Control Definitions */ +#define CTRL_RD_EN 0x00000001 +#define CTRL_WR_EN 0x00000002 + +/* Command Codes */ +#define CMD_SET_ADDR 0x00D00500 +#define CMD_CFG_DEV 0x00D80500 +#define CMD_SET_MODE 0x00F30500 +#define CMD_RD_FRAME 0x00F50500 +#define DAT_RD_FRAME 0x00F50200 +#define CMD_RD_TEST 0x00FD0500 +#define DAT_RD_TEST 0x00FD0200 +#define CMD_SET_DEV_STAT 0x00FE0500 +#define CMD_GET_DEV_STAT 0x00FE0500 +#define DAT_GET_DEV_STAT 0x00FE0200 +#define CMD_GET_ERR_CODE 0x00FF0500 +#define DAT_GET_ERR_CODE 0x00FF0200 +#define CMD_RD_ERR_STAT 0x00FB0500 +#define DAT_RD_ERR_STAT 0x00FB0200 +#define DAT_WR_BYTE(x) (0x00000100 | ((x) << 16)) +#define CMD_SEL_EP(x) (0x00000500 | ((x) << 16)) +#define DAT_SEL_EP(x) (0x00000200 | ((x) << 16)) +#define CMD_SEL_EP_CLRI(x) (0x00400500 | ((x) << 16)) +#define DAT_SEL_EP_CLRI(x) (0x00400200 | ((x) << 16)) +#define CMD_SET_EP_STAT(x) (0x00400500 | ((x) << 16)) +#define CMD_CLR_BUF 0x00F20500 +#define DAT_CLR_BUF 0x00F20200 +#define CMD_VALID_BUF 0x00FA0500 + +/* Device Address Register Definitions */ +#define DEV_ADDR_MASK 0x7F +#define DEV_EN 0x80 + +/* Device Configure Register Definitions */ +#define CONF_DVICE 0x01 + +/* Device Mode Register Definitions */ +#define AP_CLK 0x01 +#define INAK_CI 0x02 +#define INAK_CO 0x04 +#define INAK_II 0x08 +#define INAK_IO 0x10 +#define INAK_BI 0x20 +#define INAK_BO 0x40 + +/* Device Status Register Definitions */ +#define DEV_CON 0x01 +#define DEV_CON_CH 0x02 +#define DEV_SUS 0x04 +#define DEV_SUS_CH 0x08 +#define DEV_RST 0x10 + +/* Error Code Register Definitions */ +#define ERR_EC_MASK 0x0F +#define ERR_EA 0x10 + +/* Error Status Register Definitions */ +#define ERR_PID 0x01 +#define ERR_UEPKT 0x02 +#define ERR_DCRC 0x04 +#define ERR_TIMOUT 0x08 +#define ERR_EOP 0x10 +#define ERR_B_OVRN 0x20 +#define ERR_BTSTF 0x40 +#define ERR_TGL 0x80 + +/* Endpoint Select Register Definitions */ +#define EP_SEL_F 0x01 +#define EP_SEL_ST 0x02 +#define EP_SEL_STP 0x04 +#define EP_SEL_PO 0x08 +#define EP_SEL_EPN 0x10 +#define EP_SEL_B_1_FULL 0x20 +#define EP_SEL_B_2_FULL 0x40 + +/* Endpoint Status Register Definitions */ +#define EP_STAT_ST 0x01 +#define EP_STAT_DA 0x20 +#define EP_STAT_RF_MO 0x40 +#define EP_STAT_CND_ST 0x80 + +/* Clear Buffer Register Definitions */ +#define CLR_BUF_PO 0x01 + +/* DMA Interrupt Bit Definitions */ +#define EOT_INT 0x01 +#define NDD_REQ_INT 0x02 +#define SYS_ERR_INT 0x04 + +#define DRIVER_VERSION "1.03" +static const char driver_name[] = "lpc32xx_udc"; + +/* + * + * proc interface support + * + */ +#ifdef CONFIG_USB_GADGET_DEBUG_FILES +static char *epnames[] = {"INT", "ISO", "BULK", "CTRL"}; +static const char debug_filename[] = "driver/udc"; + +static void proc_ep_show(struct seq_file *s, struct lpc32xx_ep *ep) +{ + struct lpc32xx_request *req; + + seq_printf(s, "\n"); + seq_printf(s, "%12s, maxpacket %4d %3s", + ep->ep.name, ep->ep.maxpacket, + ep->is_in ? "in" : "out"); + seq_printf(s, " type %4s", epnames[ep->eptype]); + seq_printf(s, " ints: %12d", ep->totalints); + + if (list_empty(&ep->queue)) + seq_printf(s, "\t(queue empty)\n"); + else { + list_for_each_entry(req, &ep->queue, queue) { + u32 length = req->req.actual; + + seq_printf(s, "\treq %p len %d/%d buf %p\n", + &req->req, length, + req->req.length, req->req.buf); + } + } +} + +static int proc_udc_show(struct seq_file *s, void *unused) +{ + struct lpc32xx_udc *udc = s->private; + struct lpc32xx_ep *ep; + unsigned long flags; + + seq_printf(s, "%s: version %s\n", driver_name, DRIVER_VERSION); + + spin_lock_irqsave(&udc->lock, flags); + + seq_printf(s, "vbus %s, pullup %s, %s powered%s, gadget %s\n\n", + udc->vbus ? "present" : "off", + udc->enabled ? (udc->vbus ? "active" : "enabled") : + "disabled", + udc->selfpowered ? "self" : "VBUS", + udc->suspended ? ", suspended" : "", + udc->driver ? udc->driver->driver.name : "(none)"); + + if (udc->enabled && udc->vbus) { + proc_ep_show(s, &udc->ep[0]); + list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { + if (ep->desc) + proc_ep_show(s, ep); + } + } + + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +} + +static int proc_udc_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_udc_show, PDE(inode)->data); +} + +static const struct file_operations proc_ops = { + .owner = THIS_MODULE, + .open = proc_udc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void create_debug_file(struct lpc32xx_udc *udc) +{ + udc->pde = debugfs_create_file(debug_filename, 0, NULL, udc, &proc_ops); +} + +static void remove_debug_file(struct lpc32xx_udc *udc) +{ + if (udc->pde) + debugfs_remove(udc->pde); +} + +#else +static inline void create_debug_file(struct lpc32xx_udc *udc) {} +static inline void remove_debug_file(struct lpc32xx_udc *udc) {} +#endif + +/* Primary initialization sequence for the ISP1301 transceiver */ +static void isp1301_udc_configure(struct lpc32xx_udc *udc) +{ + /* LPC32XX only supports DAT_SE0 USB mode */ + /* This sequence is important */ + + /* Disable transparent UART mode first */ + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + (ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), + MC1_UART_EN); + + /* Set full speed and SE0 mode */ + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + (ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), ~0); + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_MODE_CONTROL_1, (MC1_SPEED_REG | MC1_DAT_SE0)); + + /* + * The PSW_OE enable bit state is reversed in the ISP1301 User's Guide + */ + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + (ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR), ~0); + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_MODE_CONTROL_2, (MC2_BI_DI | MC2_SPD_SUSP_CTRL)); + + /* Driver VBUS_DRV high or low depending on board setup */ + if (udc->board->vbus_drv_pol != 0) + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV); + else + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR, + OTG1_VBUS_DRV); + + /* Bi-directional mode with suspend control + * Enable both pulldowns for now - the pullup will be enable when VBUS + * is detected */ + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + (ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), ~0); + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_OTG_CONTROL_1, + (0 | OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN)); + + /* Discharge VBUS (just in case) */ + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DISCHRG); + msleep(1); + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + (ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), + OTG1_VBUS_DISCHRG); + + /* Clear and enable VBUS high edge interrupt */ + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR, ~0); + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR, ~0); + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_INTERRUPT_FALLING, INT_VBUS_VLD); + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR, ~0); + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_INTERRUPT_RISING, INT_VBUS_VLD); + + /* Enable usb_need_clk clock after transceiver is initialized */ + writel((readl(USB_CTRL) | (1 << 22)), USB_CTRL); + + dev_info(udc->dev, "ISP1301 Vendor ID : 0x%04x\n", + i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00)); + dev_info(udc->dev, "ISP1301 Product ID : 0x%04x\n", + i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x02)); + dev_info(udc->dev, "ISP1301 Version ID : 0x%04x\n", + i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x14)); +} + +/* Enables or disables the USB device pullup via the ISP1301 transceiver */ +static void isp1301_pullup_set(struct lpc32xx_udc *udc) +{ + if (udc->pullup) + /* Enable pullup for bus signalling */ + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_OTG_CONTROL_1, OTG1_DP_PULLUP); + else + /* Enable pullup for bus signalling */ + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR, + OTG1_DP_PULLUP); +} + +static void pullup_work(struct work_struct *work) +{ + struct lpc32xx_udc *udc = + container_of(work, struct lpc32xx_udc, pullup_job); + + isp1301_pullup_set(udc); +} + +static void isp1301_pullup_enable(struct lpc32xx_udc *udc, int en_pullup, + int block) +{ + if (en_pullup == udc->pullup) + return; + + udc->pullup = en_pullup; + if (block) + isp1301_pullup_set(udc); + else + /* defer slow i2c pull up setting */ + schedule_work(&udc->pullup_job); +} + +#ifdef CONFIG_PM +/* Powers up or down the ISP1301 transceiver */ +static void isp1301_set_powerstate(struct lpc32xx_udc *udc, int enable) +{ + if (enable != 0) + /* Power up ISP1301 - this ISP1301 will automatically wakeup + when VBUS is detected */ + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR, + MC2_GLOBAL_PWR_DN); + else + /* Power down ISP1301 */ + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN); +} + +static void power_work(struct work_struct *work) +{ + struct lpc32xx_udc *udc = + container_of(work, struct lpc32xx_udc, power_job); + + isp1301_set_powerstate(udc, udc->poweron); +} +#endif + +/* + * + * USB protocol engine command/data read/write helper functions + * + */ +/* Issues a single command to the USB device state machine */ +static void udc_protocol_cmd_w(struct lpc32xx_udc *udc, u32 cmd) +{ + u32 pass = 0; + int to; + + /* EP may lock on CLRI if this read isn't done */ + u32 tmp = readl(USBD_DEVINTST(udc->udp_baseaddr)); + (void) tmp; + + while (pass == 0) { + writel(USBD_CCEMPTY, USBD_DEVINTCLR(udc->udp_baseaddr)); + + /* Write command code */ + writel(cmd, USBD_CMDCODE(udc->udp_baseaddr)); + to = 10000; + while (((readl(USBD_DEVINTST(udc->udp_baseaddr)) & + USBD_CCEMPTY) == 0) && (to > 0)) { + to--; + } + + if (to > 0) + pass = 1; + + cpu_relax(); + } +} + +/* Issues 2 commands (or command and data) to the USB device state machine */ +static inline void udc_protocol_cmd_data_w(struct lpc32xx_udc *udc, u32 cmd, + u32 data) +{ + udc_protocol_cmd_w(udc, cmd); + udc_protocol_cmd_w(udc, data); +} + +/* Issues a single command to the USB device state machine and reads + * response data */ +static u32 udc_protocol_cmd_r(struct lpc32xx_udc *udc, u32 cmd) +{ + u32 tmp; + int to = 1000; + + /* Write a command and read data from the protocol engine */ + writel((USBD_CDFULL | USBD_CCEMPTY), + USBD_DEVINTCLR(udc->udp_baseaddr)); + + /* Write command code */ + udc_protocol_cmd_w(udc, cmd); + + tmp = readl(USBD_DEVINTST(udc->udp_baseaddr)); + while ((!(readl(USBD_DEVINTST(udc->udp_baseaddr)) & USBD_CDFULL)) + && (to > 0)) + to--; + if (!to) + dev_dbg(udc->dev, + "Protocol engine didn't receive response (CDFULL)\n"); + + return readl(USBD_CMDDATA(udc->udp_baseaddr)); +} + +/* + * + * USB device interrupt mask support functions + * + */ +/* Enable one or more USB device interrupts */ +static inline void uda_enable_devint(struct lpc32xx_udc *udc, u32 devmask) +{ + udc->enabled_devints |= devmask; + writel(udc->enabled_devints, USBD_DEVINTEN(udc->udp_baseaddr)); +} + +/* Disable one or more USB device interrupts */ +static inline void uda_disable_devint(struct lpc32xx_udc *udc, u32 mask) +{ + udc->enabled_devints &= ~mask; + writel(udc->enabled_devints, USBD_DEVINTEN(udc->udp_baseaddr)); +} + +/* Clear one or more USB device interrupts */ +static inline void uda_clear_devint(struct lpc32xx_udc *udc, u32 mask) +{ + writel(mask, USBD_DEVINTCLR(udc->udp_baseaddr)); +} + +/* + * + * Endpoint interrupt disable/enable functions + * + */ +/* Enable one or more USB endpoint interrupts */ +static void uda_enable_hwepint(struct lpc32xx_udc *udc, u32 hwep) +{ + udc->enabled_hwepints |= (1 << hwep); + writel(udc->enabled_hwepints, USBD_EPINTEN(udc->udp_baseaddr)); +} + +/* Disable one or more USB endpoint interrupts */ +static void uda_disable_hwepint(struct lpc32xx_udc *udc, u32 hwep) +{ + udc->enabled_hwepints &= ~(1 << hwep); + writel(udc->enabled_hwepints, USBD_EPINTEN(udc->udp_baseaddr)); +} + +/* Clear one or more USB endpoint interrupts */ +static inline void uda_clear_hwepint(struct lpc32xx_udc *udc, u32 hwep) +{ + writel((1 << hwep), USBD_EPINTCLR(udc->udp_baseaddr)); +} + +/* Enable DMA for the HW channel */ +static inline void udc_ep_dma_enable(struct lpc32xx_udc *udc, u32 hwep) +{ + writel((1 << hwep), USBD_EPDMAEN(udc->udp_baseaddr)); +} + +/* Disable DMA for the HW channel */ +static inline void udc_ep_dma_disable(struct lpc32xx_udc *udc, u32 hwep) +{ + writel((1 << hwep), USBD_EPDMADIS(udc->udp_baseaddr)); +} + +/* + * + * Endpoint realize/unrealize functions + * + */ +/* Before an endpoint can be used, it needs to be realized + * in the USB protocol engine - this realizes the endpoint. + * The interrupt (FIFO or DMA) is not enabled with this function */ +static void udc_realize_hwep(struct lpc32xx_udc *udc, u32 hwep, + u32 maxpacket) +{ + int to = 1000; + + writel(USBD_EP_RLZED, USBD_DEVINTCLR(udc->udp_baseaddr)); + writel(hwep, USBD_EPIND(udc->udp_baseaddr)); + udc->realized_eps |= (1 << hwep); + writel(udc->realized_eps, USBD_REEP(udc->udp_baseaddr)); + writel(maxpacket, USBD_EPMAXPSIZE(udc->udp_baseaddr)); + + /* Wait until endpoint is realized in hardware */ + while ((!(readl(USBD_DEVINTST(udc->udp_baseaddr)) & + USBD_EP_RLZED)) && (to > 0)) + to--; + if (!to) + dev_dbg(udc->dev, "EP not correctly realized in hardware\n"); + + writel(USBD_EP_RLZED, USBD_DEVINTCLR(udc->udp_baseaddr)); +} + +/* Unrealize an EP */ +static void udc_unrealize_hwep(struct lpc32xx_udc *udc, u32 hwep) +{ + udc->realized_eps &= ~(1 << hwep); + writel(udc->realized_eps, USBD_REEP(udc->udp_baseaddr)); +} + +/* + * + * Endpoint support functions + * + */ +/* Select and clear endpoint interrupt */ +static u32 udc_selep_clrint(struct lpc32xx_udc *udc, u32 hwep) +{ + udc_protocol_cmd_w(udc, CMD_SEL_EP_CLRI(hwep)); + return udc_protocol_cmd_r(udc, DAT_SEL_EP_CLRI(hwep)); +} + +/* Disables the endpoint in the USB protocol engine */ +static void udc_disable_hwep(struct lpc32xx_udc *udc, u32 hwep) +{ + udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep), + DAT_WR_BYTE(EP_STAT_DA)); +} + +/* Stalls the endpoint - endpoint will return STALL */ +static void udc_stall_hwep(struct lpc32xx_udc *udc, u32 hwep) +{ + udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep), + DAT_WR_BYTE(EP_STAT_ST)); +} + +/* Clear stall or reset endpoint */ +static void udc_clrstall_hwep(struct lpc32xx_udc *udc, u32 hwep) +{ + udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep), + DAT_WR_BYTE(0)); +} + +/* Select an endpoint for endpoint status, clear, validate */ +static void udc_select_hwep(struct lpc32xx_udc *udc, u32 hwep) +{ + udc_protocol_cmd_w(udc, CMD_SEL_EP(hwep)); +} + +/* + * + * Endpoint buffer management functions + * + */ +/* Clear the current endpoint's buffer */ +static void udc_clr_buffer_hwep(struct lpc32xx_udc *udc, u32 hwep) +{ + udc_select_hwep(udc, hwep); + udc_protocol_cmd_w(udc, CMD_CLR_BUF); +} + +/* Validate the current endpoint's buffer */ +static void udc_val_buffer_hwep(struct lpc32xx_udc *udc, u32 hwep) +{ + udc_select_hwep(udc, hwep); + udc_protocol_cmd_w(udc, CMD_VALID_BUF); +} + +static inline u32 udc_clearep_getsts(struct lpc32xx_udc *udc, u32 hwep) +{ + /* Clear EP interrupt */ + uda_clear_hwepint(udc, hwep); + return udc_selep_clrint(udc, hwep); +} + +/* + * + * USB EP DMA support + * + */ +/* Allocate a DMA Descriptor */ +static struct lpc32xx_usbd_dd_gad *udc_dd_alloc(struct lpc32xx_udc *udc) +{ + dma_addr_t dma; + struct lpc32xx_usbd_dd_gad *dd; + + dd = (struct lpc32xx_usbd_dd_gad *) dma_pool_alloc( + udc->dd_cache, (GFP_KERNEL | GFP_DMA), &dma); + if (dd) + dd->this_dma = dma; + + return dd; +} + +/* Free a DMA Descriptor */ +static void udc_dd_free(struct lpc32xx_udc *udc, struct lpc32xx_usbd_dd_gad *dd) +{ + dma_pool_free(udc->dd_cache, dd, dd->this_dma); +} + +/* + * + * USB setup and shutdown functions + * + */ +/* Enables or disables most of the USB system clocks when low power mode is + * needed. Clocks are typically started on a connection event, and disabled + * when a cable is disconnected */ +#define OTGOFF_CLK_MASK (AHB_M_CLOCK_ON | I2C_CLOCK_ON) +static void udc_clk_set(struct lpc32xx_udc *udc, int enable) +{ + int to = 1000; + + if (enable != 0) { + if (udc->clocked) + return; + + udc->clocked = 1; + + /* 48MHz PLL up */ + clk_enable(udc->usb_pll_clk); + + /* Enable the USB device clock */ + writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN, + USB_CTRL); + + /* Set to enable all needed USB OTG clocks */ + writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL(udc)); + + while (((readl(USB_OTG_CLK_STAT(udc)) & USB_CLOCK_MASK) != + USB_CLOCK_MASK) && (to > 0)) + to--; + if (!to) + dev_dbg(udc->dev, "Cannot enable USB OTG clocking\n"); + } else { + if (!udc->clocked) + return; + + udc->clocked = 0; + + /* Never disable the USB_HCLK during normal operation */ + + /* 48MHz PLL dpwn */ + clk_disable(udc->usb_pll_clk); + + /* Enable the USB device clock */ + writel(readl(USB_CTRL) & ~USB_DEV_NEED_CLK_EN, + USB_CTRL); + + /* Set to enable all needed USB OTG clocks */ + writel(OTGOFF_CLK_MASK, USB_OTG_CLK_CTRL(udc)); + + while (((readl(USB_OTG_CLK_STAT(udc)) & + OTGOFF_CLK_MASK) != + OTGOFF_CLK_MASK) && (to > 0)) + to--; + if (!to) + dev_dbg(udc->dev, "Cannot disable USB OTG clocking\n"); + } +} + +/* Set/reset USB device address */ +static void udc_set_address(struct lpc32xx_udc *udc, u32 addr) +{ + /* Address will be latched at the end of the status phase, or + latched immediately if function is called twice */ + udc_protocol_cmd_data_w(udc, CMD_SET_ADDR, + DAT_WR_BYTE(DEV_EN | addr)); +} + +/* Setup up a IN request for DMA transfer - this consists of determining the + * list of DMA addresses for the transfer, allocating DMA Descriptors, + * installing the DD into the UDCA, and then enabling the DMA for that EP */ +static int udc_ep_in_req_dma(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep) +{ + struct lpc32xx_request *req; + u32 hwep = ep->hwep_num; + + ep->req_pending = 1; + + /* There will always be a request waiting here */ + req = list_entry(ep->queue.next, struct lpc32xx_request, queue); + + /* Place the DD Descriptor into the UDCA */ + udc->udca_v_base[hwep] = req->dd_desc_ptr->this_dma; + + /* Enable DMA and interrupt for the HW EP */ + udc_ep_dma_enable(udc, hwep); + + /* Clear ZLP if last packet is not of MAXP size */ + if (req->req.length % ep->ep.maxpacket) + req->send_zlp = 0; + + return 0; +} + +/* Setup up a OUT request for DMA transfer - this consists of determining the + * list of DMA addresses for the transfer, allocating DMA Descriptors, + * installing the DD into the UDCA, and then enabling the DMA for that EP */ +static int udc_ep_out_req_dma(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep) +{ + struct lpc32xx_request *req; + u32 hwep = ep->hwep_num; + + ep->req_pending = 1; + + /* There will always be a request waiting here */ + req = list_entry(ep->queue.next, struct lpc32xx_request, queue); + + /* Place the DD Descriptor into the UDCA */ + udc->udca_v_base[hwep] = req->dd_desc_ptr->this_dma; + + /* Enable DMA and interrupt for the HW EP */ + udc_ep_dma_enable(udc, hwep); + return 0; +} + +static void udc_disable(struct lpc32xx_udc *udc) +{ + u32 i; + + /* Disable device */ + udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(0)); + udc_protocol_cmd_data_w(udc, CMD_SET_DEV_STAT, DAT_WR_BYTE(0)); + + /* Disable all device interrupts (including EP0) */ + uda_disable_devint(udc, 0x3FF); + + /* Disable and reset all endpoint interrupts */ + for (i = 0; i < 32; i++) { + uda_disable_hwepint(udc, i); + uda_clear_hwepint(udc, i); + udc_disable_hwep(udc, i); + udc_unrealize_hwep(udc, i); + udc->udca_v_base[i] = 0; + + /* Disable and clear all interrupts and DMA */ + udc_ep_dma_disable(udc, i); + writel((1 << i), USBD_EOTINTCLR(udc->udp_baseaddr)); + writel((1 << i), USBD_NDDRTINTCLR(udc->udp_baseaddr)); + writel((1 << i), USBD_SYSERRTINTCLR(udc->udp_baseaddr)); + writel((1 << i), USBD_DMARCLR(udc->udp_baseaddr)); + } + + /* Disable DMA interrupts */ + writel(0, USBD_DMAINTEN(udc->udp_baseaddr)); + + writel(0, USBD_UDCAH(udc->udp_baseaddr)); +} + +static void udc_enable(struct lpc32xx_udc *udc) +{ + u32 i; + struct lpc32xx_ep *ep = &udc->ep[0]; + + /* Start with known state */ + udc_disable(udc); + + /* Enable device */ + udc_protocol_cmd_data_w(udc, CMD_SET_DEV_STAT, DAT_WR_BYTE(DEV_CON)); + + /* EP interrupts on high priority, FRAME interrupt on low priority */ + writel(USBD_EP_FAST, USBD_DEVINTPRI(udc->udp_baseaddr)); + writel(0xFFFF, USBD_EPINTPRI(udc->udp_baseaddr)); + + /* Clear any pending device interrupts */ + writel(0x3FF, USBD_DEVINTCLR(udc->udp_baseaddr)); + + /* Setup UDCA - not yet used (DMA) */ + writel(udc->udca_p_base, USBD_UDCAH(udc->udp_baseaddr)); + + /* Only enable EP0 in and out for now, EP0 only works in FIFO mode */ + for (i = 0; i <= 1; i++) { + udc_realize_hwep(udc, i, ep->ep.maxpacket); + uda_enable_hwepint(udc, i); + udc_select_hwep(udc, i); + udc_clrstall_hwep(udc, i); + udc_clr_buffer_hwep(udc, i); + } + + /* Device interrupt setup */ + uda_clear_devint(udc, (USBD_ERR_INT | USBD_DEV_STAT | USBD_EP_SLOW | + USBD_EP_FAST)); + uda_enable_devint(udc, (USBD_ERR_INT | USBD_DEV_STAT | USBD_EP_SLOW | + USBD_EP_FAST)); + + /* Set device address to 0 - called twice to force a latch in the USB + engine without the need of a setup packet status closure */ + udc_set_address(udc, 0); + udc_set_address(udc, 0); + + /* Enable master DMA interrupts */ + writel((USBD_SYS_ERR_INT | USBD_EOT_INT), + USBD_DMAINTEN(udc->udp_baseaddr)); + + udc->dev_status = 0; +} + +/* + * + * USB device board specific events handled via callbacks + * + */ +/* Connection change event - notify board function of change */ +static void uda_power_event(struct lpc32xx_udc *udc, u32 conn) +{ + /* Just notify of a connection change event (optional) */ + if (udc->board->conn_chgb != NULL) + udc->board->conn_chgb(conn); +} + +/* Suspend/resume event - notify board function of change */ +static void uda_resm_susp_event(struct lpc32xx_udc *udc, u32 conn) +{ + /* Just notify of a Suspend/resume change event (optional) */ + if (udc->board->susp_chgb != NULL) + udc->board->susp_chgb(conn); + + if (conn) + udc->suspended = 0; + else + udc->suspended = 1; +} + +/* Remote wakeup enable/disable - notify board function of change */ +static void uda_remwkp_cgh(struct lpc32xx_udc *udc) +{ + if (udc->board->rmwk_chgb != NULL) + udc->board->rmwk_chgb(udc->dev_status & + (1 << USB_DEVICE_REMOTE_WAKEUP)); +} + +/* Reads data from FIFO, adjusts for alignment and data size */ +static void udc_pop_fifo(struct lpc32xx_udc *udc, u8 *data, u32 bytes) +{ + int n, i, bl; + u16 *p16; + u32 *p32, tmp, cbytes; + + /* Use optimal data transfer method based on source address and size */ + switch (((u32) data) & 0x3) { + case 0: /* 32-bit aligned */ + p32 = (u32 *) data; + cbytes = (bytes & ~0x3); + + /* Copy 32-bit aligned data first */ + for (n = 0; n < cbytes; n += 4) + *p32++ = readl(USBD_RXDATA(udc->udp_baseaddr)); + + /* Handle any remaining bytes */ + bl = bytes - cbytes; + if (bl) { + tmp = readl(USBD_RXDATA(udc->udp_baseaddr)); + for (n = 0; n < bl; n++) + data[cbytes + n] = ((tmp >> (n * 8)) & 0xFF); + + } + break; + + case 1: /* 8-bit aligned */ + case 3: + /* Each byte has to be handled independently */ + for (n = 0; n < bytes; n += 4) { + tmp = readl(USBD_RXDATA(udc->udp_baseaddr)); + + bl = bytes - n; + if (bl > 3) + bl = 3; + + for (i = 0; i < bl; i++) + data[n + i] = (u8) ((tmp >> (n * 8)) & 0xFF); + } + break; + + case 2: /* 16-bit aligned */ + p16 = (u16 *) data; + cbytes = (bytes & ~0x3); + + /* Copy 32-bit sized objects first with 16-bit alignment */ + for (n = 0; n < cbytes; n += 4) { + tmp = readl(USBD_RXDATA(udc->udp_baseaddr)); + *p16++ = (u16)(tmp & 0xFFFF); + *p16++ = (u16)((tmp >> 16) & 0xFFFF); + } + + /* Handle any remaining bytes */ + bl = bytes - cbytes; + if (bl) { + tmp = readl(USBD_RXDATA(udc->udp_baseaddr)); + for (n = 0; n < bl; n++) + data[cbytes + n] = ((tmp >> (n * 8)) & 0xFF); + } + break; + } +} + +/* Read data from the FIFO for an endpoint. This function is for endpoints (such + * as EP0) that don't use DMA. This function should only be called if a packet + * is known to be ready to read for the endpoint. Note that the endpoint must + * be selected in the protocol engine prior to this call. */ +static u32 udc_read_hwep(struct lpc32xx_udc *udc, u32 hwep, u32 *data, + u32 bytes) +{ + u32 tmpv; + int to = 1000; + u32 tmp, hwrep = ((hwep & 0x1E) << 1) | CTRL_RD_EN; + + /* Setup read of endpoint */ + writel(hwrep, USBD_CTRL(udc->udp_baseaddr)); + + /* Wait until packet is ready */ + while ((((tmpv = readl(USBD_RXPLEN(udc->udp_baseaddr))) & + PKT_RDY) == 0) && (to > 0)) + to--; + if (!to) + dev_dbg(udc->dev, "No packet ready on FIFO EP read\n"); + + /* Mask out count */ + tmp = tmpv & PKT_LNGTH_MASK; + if (bytes < tmp) + tmp = bytes; + + if ((tmp > 0) && (data != NULL)) + udc_pop_fifo(udc, (u8 *) data, tmp); + + writel(((hwep & 0x1E) << 1), USBD_CTRL(udc->udp_baseaddr)); + + /* Clear the buffer */ + udc_clr_buffer_hwep(udc, hwep); + + return tmp; +} + +/* Stuffs data into the FIFO, adjusts for alignment and data size */ +static void udc_stuff_fifo(struct lpc32xx_udc *udc, u8 *data, u32 bytes) +{ + int n, i, bl; + u16 *p16; + u32 *p32, tmp, cbytes; + + /* Use optimal data transfer method based on source address and size */ + switch (((u32) data) & 0x3) { + case 0: /* 32-bit aligned */ + p32 = (u32 *) data; + cbytes = (bytes & ~0x3); + + /* Copy 32-bit aligned data first */ + for (n = 0; n < cbytes; n += 4) + writel(*p32++, USBD_TXDATA(udc->udp_baseaddr)); + + /* Handle any remaining bytes */ + bl = bytes - cbytes; + if (bl) { + tmp = 0; + for (n = 0; n < bl; n++) + tmp |= data[cbytes + n] << (n * 8); + + writel(tmp, USBD_TXDATA(udc->udp_baseaddr)); + } + break; + + case 1: /* 8-bit aligned */ + case 3: + /* Each byte has to be handled independently */ + for (n = 0; n < bytes; n += 4) { + bl = bytes - n; + if (bl > 4) + bl = 4; + + tmp = 0; + for (i = 0; i < bl; i++) + tmp |= data[n + i] << (i * 8); + + writel(tmp, USBD_TXDATA(udc->udp_baseaddr)); + } + break; + + case 2: /* 16-bit aligned */ + p16 = (u16 *) data; + cbytes = (bytes & ~0x3); + + /* Copy 32-bit aligned data first */ + for (n = 0; n < cbytes; n += 4) { + tmp = *p16++ & 0xFFFF; + tmp |= (*p16++ & 0xFFFF) << 16; + writel(tmp, USBD_TXDATA(udc->udp_baseaddr)); + } + + /* Handle any remaining bytes */ + bl = bytes - cbytes; + if (bl) { + tmp = 0; + for (n = 0; n < bl; n++) + tmp |= data[cbytes + n] << (n * 8); + + writel(tmp, USBD_TXDATA(udc->udp_baseaddr)); + } + break; + } +} + +/* Write data to the FIFO for an endpoint. This function is for endpoints (such + * as EP0) that don't use DMA. Note that the endpoint must be selected in the + * protocol engine prior to this call. */ +static void udc_write_hwep(struct lpc32xx_udc *udc, u32 hwep, u32 *data, + u32 bytes) +{ + u32 hwwep = ((hwep & 0x1E) << 1) | CTRL_WR_EN; + + if ((bytes > 0) && (data == NULL)) + return; + + /* Setup write of endpoint */ + writel(hwwep, USBD_CTRL(udc->udp_baseaddr)); + + writel(bytes, USBD_TXPLEN(udc->udp_baseaddr)); + + /* Need at least 1 byte to trigger TX */ + if (bytes == 0) + writel(0, USBD_TXDATA(udc->udp_baseaddr)); + else + udc_stuff_fifo(udc, (u8 *) data, bytes); + + writel(((hwep & 0x1E) << 1), USBD_CTRL(udc->udp_baseaddr)); + + udc_val_buffer_hwep(udc, hwep); +} + +/* USB device reset - resets USB to a default state with just EP0 + enabled */ +static void uda_usb_reset(struct lpc32xx_udc *udc) +{ + u32 i = 0; + /* Re-init device controller and EP0 */ + udc_enable(udc); + udc->gadget.speed = USB_SPEED_FULL; + + for (i = 1; i < NUM_ENDPOINTS; i++) { + struct lpc32xx_ep *ep = &udc->ep[i]; + ep->req_pending = 0; + } +} + +/* Send a ZLP on EP0 */ +static void udc_ep0_send_zlp(struct lpc32xx_udc *udc) +{ + udc_write_hwep(udc, EP_IN, NULL, 0); +} + +/* Get current frame number */ +static u16 udc_get_current_frame(struct lpc32xx_udc *udc) +{ + u16 flo, fhi; + + udc_protocol_cmd_w(udc, CMD_RD_FRAME); + flo = (u16) udc_protocol_cmd_r(udc, DAT_RD_FRAME); + fhi = (u16) udc_protocol_cmd_r(udc, DAT_RD_FRAME); + + return (fhi << 8) | flo; +} + +/* Set the device as configured - enables all endpoints */ +static inline void udc_set_device_configured(struct lpc32xx_udc *udc) +{ + udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(CONF_DVICE)); +} + +/* Set the device as unconfigured - disables all endpoints */ +static inline void udc_set_device_unconfigured(struct lpc32xx_udc *udc) +{ + udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(0)); +} + +/* reinit == restore initial software state */ +static void udc_reinit(struct lpc32xx_udc *udc) +{ + u32 i; + + INIT_LIST_HEAD(&udc->gadget.ep_list); + INIT_LIST_HEAD(&udc->gadget.ep0->ep_list); + + for (i = 0; i < NUM_ENDPOINTS; i++) { + struct lpc32xx_ep *ep = &udc->ep[i]; + + if (i != 0) + list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); + ep->desc = NULL; + ep->ep.maxpacket = ep->maxpacket; + INIT_LIST_HEAD(&ep->queue); + ep->req_pending = 0; + } + + udc->ep0state = WAIT_FOR_SETUP; +} + +/* Must be called with lock */ +static void done(struct lpc32xx_ep *ep, struct lpc32xx_request *req, int status) +{ + struct lpc32xx_udc *udc = ep->udc; + + list_del_init(&req->queue); + if (req->req.status == -EINPROGRESS) + req->req.status = status; + else + status = req->req.status; + + if (ep->lep) { + enum dma_data_direction direction; + + if (ep->is_in) + direction = DMA_TO_DEVICE; + else + direction = DMA_FROM_DEVICE; + + if (req->mapped) { + dma_unmap_single(ep->udc->gadget.dev.parent, + req->req.dma, req->req.length, + direction); + req->req.dma = 0; + req->mapped = 0; + } else + dma_sync_single_for_cpu(ep->udc->gadget.dev.parent, + req->req.dma, req->req.length, + direction); + + /* Free DDs */ + udc_dd_free(udc, req->dd_desc_ptr); + } + + if (status && status != -ESHUTDOWN) + ep_dbg(ep, "%s done %p, status %d\n", ep->ep.name, req, status); + + ep->req_pending = 0; + spin_unlock(&udc->lock); + req->req.complete(&ep->ep, &req->req); + spin_lock(&udc->lock); +} + +/* Must be called with lock */ +static void nuke(struct lpc32xx_ep *ep, int status) +{ + struct lpc32xx_request *req; + + while (!list_empty(&ep->queue)) { + req = list_entry(ep->queue.next, struct lpc32xx_request, queue); + done(ep, req, status); + } + + if (ep->desc && status == -ESHUTDOWN) { + uda_disable_hwepint(ep->udc, ep->hwep_num); + udc_disable_hwep(ep->udc, ep->hwep_num); + } +} + +/* IN endpoint 0 transfer */ +static int udc_ep0_in_req(struct lpc32xx_udc *udc) +{ + struct lpc32xx_request *req; + struct lpc32xx_ep *ep0 = &udc->ep[0]; + u32 tsend, ts = 0; + + if (list_empty(&ep0->queue)) + /* Nothing to send */ + return 0; + else + req = list_entry(ep0->queue.next, struct lpc32xx_request, + queue); + + tsend = ts = req->req.length - req->req.actual; + if (ts == 0) { + /* Send a ZLP */ + udc_ep0_send_zlp(udc); + done(ep0, req, 0); + return 1; + } else if (ts > ep0->ep.maxpacket) + ts = ep0->ep.maxpacket; /* Just send what we can */ + + /* Write data to the EP0 FIFO and start transfer */ + udc_write_hwep(udc, EP_IN, (req->req.buf + req->req.actual), ts); + + /* Increment data pointer */ + req->req.actual += ts; + + if (tsend >= ep0->ep.maxpacket) + return 0; /* Stay in data transfer state */ + + /* Transfer request is complete */ + udc->ep0state = WAIT_FOR_SETUP; + done(ep0, req, 0); + return 1; +} + +/* OUT endpoint 0 transfer */ +static int udc_ep0_out_req(struct lpc32xx_udc *udc) +{ + struct lpc32xx_request *req; + struct lpc32xx_ep *ep0 = &udc->ep[0]; + u32 tr, bufferspace; + + if (list_empty(&ep0->queue)) + return 0; + else + req = list_entry(ep0->queue.next, struct lpc32xx_request, + queue); + + if (req) { + if (req->req.length == 0) { + /* Just dequeue request */ + done(ep0, req, 0); + udc->ep0state = WAIT_FOR_SETUP; + return 1; + } + + /* Get data from FIFO */ + bufferspace = req->req.length - req->req.actual; + if (bufferspace > ep0->ep.maxpacket) + bufferspace = ep0->ep.maxpacket; + + /* Copy data to buffer */ + prefetchw(req->req.buf + req->req.actual); + tr = udc_read_hwep(udc, EP_OUT, req->req.buf + req->req.actual, + bufferspace); + req->req.actual += bufferspace; + + if (tr < ep0->ep.maxpacket) { + /* This is the last packet */ + done(ep0, req, 0); + udc->ep0state = WAIT_FOR_SETUP; + return 1; + } + } + + return 0; +} + +/* Must be called with lock */ +static void stop_activity(struct lpc32xx_udc *udc) +{ + struct usb_gadget_driver *driver = udc->driver; + int i; + + if (udc->gadget.speed == USB_SPEED_UNKNOWN) + driver = NULL; + + udc->gadget.speed = USB_SPEED_UNKNOWN; + udc->suspended = 0; + + for (i = 0; i < NUM_ENDPOINTS; i++) { + struct lpc32xx_ep *ep = &udc->ep[i]; + nuke(ep, -ESHUTDOWN); + } + if (driver) { + spin_unlock(&udc->lock); + driver->disconnect(&udc->gadget); + spin_lock(&udc->lock); + } + + isp1301_pullup_enable(udc, 0, 0); + udc_disable(udc); + udc_reinit(udc); +} + +/* + * Activate or kill host pullup + * Can be called with or without lock + */ +static void pullup(struct lpc32xx_udc *udc, int is_on) +{ + if (!udc->clocked) + return; + + if (!udc->enabled || !udc->vbus) + is_on = 0; + + if (is_on != udc->pullup) + isp1301_pullup_enable(udc, is_on, 0); +} + +/* Must be called without lock */ +static int lpc32xx_ep_disable(struct usb_ep *_ep) +{ + struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep); + struct lpc32xx_udc *udc = ep->udc; + unsigned long flags; + + if ((ep->hwep_num_base == 0) || (ep->hwep_num == 0)) + return -EINVAL; + spin_lock_irqsave(&udc->lock, flags); + + nuke(ep, -ESHUTDOWN); + + /* restore the endpoint's pristine config */ + ep->desc = NULL; + + /* Clear all DMA statuses for this EP */ + udc_ep_dma_disable(udc, ep->hwep_num); + writel(1 << ep->hwep_num, USBD_EOTINTCLR(udc->udp_baseaddr)); + writel(1 << ep->hwep_num, USBD_NDDRTINTCLR(udc->udp_baseaddr)); + writel(1 << ep->hwep_num, USBD_SYSERRTINTCLR(udc->udp_baseaddr)); + writel(1 << ep->hwep_num, USBD_DMARCLR(udc->udp_baseaddr)); + + /* Remove the DD pointer in the UDCA */ + udc->udca_v_base[ep->hwep_num] = 0; + + /* Disable and reset endpoint and interrupt */ + uda_clear_hwepint(udc, ep->hwep_num); + udc_unrealize_hwep(udc, ep->hwep_num); + + ep->hwep_num = 0; + + spin_unlock_irqrestore(&udc->lock, flags); + + atomic_dec(&udc->enabled_ep_cnt); + wake_up(&udc->ep_disable_wait_queue); + + return 0; +} + +/* Must be called without lock */ +static int lpc32xx_ep_enable(struct usb_ep *_ep, + const struct usb_endpoint_descriptor *desc) +{ + struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep); + struct lpc32xx_udc *udc = ep->udc; + u16 maxpacket; + u32 tmp; + unsigned long flags; + + /* Verify EP data */ + if ((!_ep) || (!ep) || (!desc) || (ep->desc) || + (desc->bDescriptorType != USB_DT_ENDPOINT)) { + dev_dbg(udc->dev, "bad ep or descriptor\n"); + return -EINVAL; + } + maxpacket = usb_endpoint_maxp(desc); + if ((maxpacket == 0) || (maxpacket > ep->maxpacket)) { + dev_dbg(udc->dev, "bad ep descriptor's packet size\n"); + return -EINVAL; + } + + /* Don't touch EP0 */ + if (ep->hwep_num_base == 0) { + dev_dbg(udc->dev, "Can't re-enable EP0!!!\n"); + return -EINVAL; + } + + /* Is driver ready? */ + if ((!udc->driver) || (udc->gadget.speed == USB_SPEED_UNKNOWN)) { + dev_dbg(udc->dev, "bogus device state\n"); + return -ESHUTDOWN; + } + + tmp = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + switch (tmp) { + case USB_ENDPOINT_XFER_CONTROL: + return -EINVAL; + + case USB_ENDPOINT_XFER_INT: + if (maxpacket > ep->maxpacket) { + dev_dbg(udc->dev, + "Bad INT endpoint maxpacket %d\n", maxpacket); + return -EINVAL; + } + break; + + case USB_ENDPOINT_XFER_BULK: + switch (maxpacket) { + case 8: + case 16: + case 32: + case 64: + break; + + default: + dev_dbg(udc->dev, + "Bad BULK endpoint maxpacket %d\n", maxpacket); + return -EINVAL; + } + break; + + case USB_ENDPOINT_XFER_ISOC: + break; + } + spin_lock_irqsave(&udc->lock, flags); + + /* Initialize endpoint to match the selected descriptor */ + ep->is_in = (desc->bEndpointAddress & USB_DIR_IN) != 0; + ep->desc = desc; + ep->ep.maxpacket = maxpacket; + + /* Map hardware endpoint from base and direction */ + if (ep->is_in) + /* IN endpoints are offset 1 from the OUT endpoint */ + ep->hwep_num = ep->hwep_num_base + EP_IN; + else + ep->hwep_num = ep->hwep_num_base; + + ep_dbg(ep, "EP enabled: %s, HW:%d, MP:%d IN:%d\n", ep->ep.name, + ep->hwep_num, maxpacket, (ep->is_in == 1)); + + /* Realize the endpoint, interrupt is enabled later when + * buffers are queued, IN EPs will NAK until buffers are ready */ + udc_realize_hwep(udc, ep->hwep_num, ep->ep.maxpacket); + udc_clr_buffer_hwep(udc, ep->hwep_num); + uda_disable_hwepint(udc, ep->hwep_num); + udc_clrstall_hwep(udc, ep->hwep_num); + + /* Clear all DMA statuses for this EP */ + udc_ep_dma_disable(udc, ep->hwep_num); + writel(1 << ep->hwep_num, USBD_EOTINTCLR(udc->udp_baseaddr)); + writel(1 << ep->hwep_num, USBD_NDDRTINTCLR(udc->udp_baseaddr)); + writel(1 << ep->hwep_num, USBD_SYSERRTINTCLR(udc->udp_baseaddr)); + writel(1 << ep->hwep_num, USBD_DMARCLR(udc->udp_baseaddr)); + + spin_unlock_irqrestore(&udc->lock, flags); + + atomic_inc(&udc->enabled_ep_cnt); + return 0; +} + +/* + * Allocate a USB request list + * Can be called with or without lock + */ +static struct usb_request *lpc32xx_ep_alloc_request(struct usb_ep *_ep, + gfp_t gfp_flags) +{ + struct lpc32xx_request *req; + + req = kzalloc(sizeof(struct lpc32xx_request), gfp_flags); + if (!req) + return NULL; + + INIT_LIST_HEAD(&req->queue); + return &req->req; +} + +/* + * De-allocate a USB request list + * Can be called with or without lock + */ +static void lpc32xx_ep_free_request(struct usb_ep *_ep, + struct usb_request *_req) +{ + struct lpc32xx_request *req; + + req = container_of(_req, struct lpc32xx_request, req); + BUG_ON(!list_empty(&req->queue)); + kfree(req); +} + +/* Must be called without lock */ +static int lpc32xx_ep_queue(struct usb_ep *_ep, + struct usb_request *_req, gfp_t gfp_flags) +{ + struct lpc32xx_request *req; + struct lpc32xx_ep *ep; + struct lpc32xx_udc *udc; + unsigned long flags; + int status = 0; + + req = container_of(_req, struct lpc32xx_request, req); + ep = container_of(_ep, struct lpc32xx_ep, ep); + + if (!_req || !_req->complete || !_req->buf || + !list_empty(&req->queue)) + return -EINVAL; + + udc = ep->udc; + + if (!_ep || (!ep->desc && ep->hwep_num_base != 0)) { + dev_dbg(udc->dev, "invalid ep\n"); + return -EINVAL; + } + + + if ((!udc) || (!udc->driver) || + (udc->gadget.speed == USB_SPEED_UNKNOWN)) { + dev_dbg(udc->dev, "invalid device\n"); + return -EINVAL; + } + + if (ep->lep) { + enum dma_data_direction direction; + struct lpc32xx_usbd_dd_gad *dd; + + /* Map DMA pointer */ + if (ep->is_in) + direction = DMA_TO_DEVICE; + else + direction = DMA_FROM_DEVICE; + + if (req->req.dma == 0) { + req->req.dma = dma_map_single( + ep->udc->gadget.dev.parent, + req->req.buf, req->req.length, direction); + req->mapped = 1; + } else { + dma_sync_single_for_device( + ep->udc->gadget.dev.parent, req->req.dma, + req->req.length, direction); + req->mapped = 0; + } + + /* For the request, build a list of DDs */ + dd = udc_dd_alloc(udc); + if (!dd) { + /* Error allocating DD */ + return -ENOMEM; + } + req->dd_desc_ptr = dd; + + /* Setup the DMA descriptor */ + dd->dd_next_phy = dd->dd_next_v = 0; + dd->dd_buffer_addr = req->req.dma; + dd->dd_status = 0; + + /* Special handling for ISO EPs */ + if (ep->eptype == EP_ISO_TYPE) { + dd->dd_setup = DD_SETUP_ISO_EP | + DD_SETUP_PACKETLEN(0) | + DD_SETUP_DMALENBYTES(1); + dd->dd_iso_ps_mem_addr = dd->this_dma + 24; + if (ep->is_in) + dd->iso_status[0] = req->req.length; + else + dd->iso_status[0] = 0; + } else + dd->dd_setup = DD_SETUP_PACKETLEN(ep->ep.maxpacket) | + DD_SETUP_DMALENBYTES(req->req.length); + } + + ep_dbg(ep, "%s queue req %p len %d buf %p (in=%d) z=%d\n", _ep->name, + _req, _req->length, _req->buf, ep->is_in, _req->zero); + + spin_lock_irqsave(&udc->lock, flags); + + _req->status = -EINPROGRESS; + _req->actual = 0; + req->send_zlp = _req->zero; + + /* Kickstart empty queues */ + if (list_empty(&ep->queue)) { + list_add_tail(&req->queue, &ep->queue); + + if (ep->hwep_num_base == 0) { + /* Handle expected data direction */ + if (ep->is_in) { + /* IN packet to host */ + udc->ep0state = DATA_IN; + status = udc_ep0_in_req(udc); + } else { + /* OUT packet from host */ + udc->ep0state = DATA_OUT; + status = udc_ep0_out_req(udc); + } + } else if (ep->is_in) { + /* IN packet to host and kick off transfer */ + if (!ep->req_pending) + udc_ep_in_req_dma(udc, ep); + } else + /* OUT packet from host and kick off list */ + if (!ep->req_pending) + udc_ep_out_req_dma(udc, ep); + } else + list_add_tail(&req->queue, &ep->queue); + + spin_unlock_irqrestore(&udc->lock, flags); + + return (status < 0) ? status : 0; +} + +/* Must be called without lock */ +static int lpc32xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) +{ + struct lpc32xx_ep *ep; + struct lpc32xx_request *req; + unsigned long flags; + + ep = container_of(_ep, struct lpc32xx_ep, ep); + if (!_ep || ep->hwep_num_base == 0) + return -EINVAL; + + spin_lock_irqsave(&ep->udc->lock, flags); + + /* make sure it's actually queued on this endpoint */ + list_for_each_entry(req, &ep->queue, queue) { + if (&req->req == _req) + break; + } + if (&req->req != _req) { + spin_unlock_irqrestore(&ep->udc->lock, flags); + return -EINVAL; + } + + done(ep, req, -ECONNRESET); + + spin_unlock_irqrestore(&ep->udc->lock, flags); + + return 0; +} + +/* Must be called without lock */ +static int lpc32xx_ep_set_halt(struct usb_ep *_ep, int value) +{ + struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep); + struct lpc32xx_udc *udc = ep->udc; + unsigned long flags; + + if ((!ep) || (ep->desc == NULL) || (ep->hwep_num <= 1)) + return -EINVAL; + + /* Don't halt an IN EP */ + if (ep->is_in) + return -EAGAIN; + + spin_lock_irqsave(&udc->lock, flags); + + if (value == 1) { + /* stall */ + udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(ep->hwep_num), + DAT_WR_BYTE(EP_STAT_ST)); + } else { + /* End stall */ + ep->wedge = 0; + udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(ep->hwep_num), + DAT_WR_BYTE(0)); + } + + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +} + +/* set the halt feature and ignores clear requests */ +static int lpc32xx_ep_set_wedge(struct usb_ep *_ep) +{ + struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep); + + if (!_ep || !ep->udc) + return -EINVAL; + + ep->wedge = 1; + + return usb_ep_set_halt(_ep); +} + +static const struct usb_ep_ops lpc32xx_ep_ops = { + .enable = lpc32xx_ep_enable, + .disable = lpc32xx_ep_disable, + .alloc_request = lpc32xx_ep_alloc_request, + .free_request = lpc32xx_ep_free_request, + .queue = lpc32xx_ep_queue, + .dequeue = lpc32xx_ep_dequeue, + .set_halt = lpc32xx_ep_set_halt, + .set_wedge = lpc32xx_ep_set_wedge, +}; + +/* Send a ZLP on a non-0 IN EP */ +void udc_send_in_zlp(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep) +{ + /* Clear EP status */ + udc_clearep_getsts(udc, ep->hwep_num); + + /* Send ZLP via FIFO mechanism */ + udc_write_hwep(udc, ep->hwep_num, NULL, 0); +} + +/* + * Handle EP completion for ZLP + * This function will only be called when a delayed ZLP needs to be sent out + * after a DMA transfer has filled both buffers. + */ +void udc_handle_eps(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep) +{ + u32 epstatus; + struct lpc32xx_request *req; + + if (ep->hwep_num <= 0) + return; + + uda_clear_hwepint(udc, ep->hwep_num); + + /* If this interrupt isn't enabled, return now */ + if (!(udc->enabled_hwepints & (1 << ep->hwep_num))) + return; + + /* Get endpoint status */ + epstatus = udc_clearep_getsts(udc, ep->hwep_num); + + /* + * This should never happen, but protect against writing to the + * buffer when full. + */ + if (epstatus & EP_SEL_F) + return; + + if (ep->is_in) { + udc_send_in_zlp(udc, ep); + uda_disable_hwepint(udc, ep->hwep_num); + } else + return; + + /* If there isn't a request waiting, something went wrong */ + req = list_entry(ep->queue.next, struct lpc32xx_request, queue); + if (req) { + done(ep, req, 0); + + /* Start another request if ready */ + if (!list_empty(&ep->queue)) { + if (ep->is_in) + udc_ep_in_req_dma(udc, ep); + else + udc_ep_out_req_dma(udc, ep); + } else + ep->req_pending = 0; + } +} + + +/* DMA end of transfer completion */ +static void udc_handle_dma_ep(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep) +{ + u32 status, epstatus; + struct lpc32xx_request *req; + struct lpc32xx_usbd_dd_gad *dd; + +#ifdef CONFIG_USB_GADGET_DEBUG_FILES + ep->totalints++; +#endif + + req = list_entry(ep->queue.next, struct lpc32xx_request, queue); + if (!req) { + ep_err(ep, "DMA interrupt on no req!\n"); + return; + } + dd = req->dd_desc_ptr; + + /* DMA descriptor should always be retired for this call */ + if (!(dd->dd_status & DD_STATUS_DD_RETIRED)) + ep_warn(ep, "DMA descriptor did not retire\n"); + + /* Disable DMA */ + udc_ep_dma_disable(udc, ep->hwep_num); + writel((1 << ep->hwep_num), USBD_EOTINTCLR(udc->udp_baseaddr)); + writel((1 << ep->hwep_num), USBD_NDDRTINTCLR(udc->udp_baseaddr)); + + /* System error? */ + if (readl(USBD_SYSERRTINTST(udc->udp_baseaddr)) & + (1 << ep->hwep_num)) { + writel((1 << ep->hwep_num), + USBD_SYSERRTINTCLR(udc->udp_baseaddr)); + ep_err(ep, "AHB critical error!\n"); + ep->req_pending = 0; + + /* The error could have occurred on a packet of a multipacket + * transfer, so recovering the transfer is not possible. Close + * the request with an error */ + done(ep, req, -ECONNABORTED); + return; + } + + /* Handle the current DD's status */ + status = dd->dd_status; + switch (status & DD_STATUS_STS_MASK) { + case DD_STATUS_STS_NS: + /* DD not serviced? This shouldn't happen! */ + ep->req_pending = 0; + ep_err(ep, "DMA critical EP error: DD not serviced (0x%x)!\n", + status); + + done(ep, req, -ECONNABORTED); + return; + + case DD_STATUS_STS_BS: + /* Interrupt only fires on EOT - This shouldn't happen! */ + ep->req_pending = 0; + ep_err(ep, "DMA critical EP error: EOT prior to service completion (0x%x)!\n", + status); + done(ep, req, -ECONNABORTED); + return; + + case DD_STATUS_STS_NC: + case DD_STATUS_STS_DUR: + /* Really just a short packet, not an underrun */ + /* This is a good status and what we expect */ + break; + + default: + /* Data overrun, system error, or unknown */ + ep->req_pending = 0; + ep_err(ep, "DMA critical EP error: System error (0x%x)!\n", + status); + done(ep, req, -ECONNABORTED); + return; + } + + /* ISO endpoints are handled differently */ + if (ep->eptype == EP_ISO_TYPE) { + if (ep->is_in) + req->req.actual = req->req.length; + else + req->req.actual = dd->iso_status[0] & 0xFFFF; + } else + req->req.actual += DD_STATUS_CURDMACNT(status); + + /* Send a ZLP if necessary. This will be done for non-int + * packets which have a size that is a divisor of MAXP */ + if (req->send_zlp) { + /* + * If at least 1 buffer is available, send the ZLP now. + * Otherwise, the ZLP send needs to be deferred until a + * buffer is available. + */ + if (udc_clearep_getsts(udc, ep->hwep_num) & EP_SEL_F) { + udc_clearep_getsts(udc, ep->hwep_num); + uda_enable_hwepint(udc, ep->hwep_num); + epstatus = udc_clearep_getsts(udc, ep->hwep_num); + + /* Let the EP interrupt handle the ZLP */ + return; + } else + udc_send_in_zlp(udc, ep); + } + + /* Transfer request is complete */ + done(ep, req, 0); + + /* Start another request if ready */ + udc_clearep_getsts(udc, ep->hwep_num); + if (!list_empty((&ep->queue))) { + if (ep->is_in) + udc_ep_in_req_dma(udc, ep); + else + udc_ep_out_req_dma(udc, ep); + } else + ep->req_pending = 0; + +} + +/* + * + * Endpoint 0 functions + * + */ +static void udc_handle_dev(struct lpc32xx_udc *udc) +{ + u32 tmp; + + udc_protocol_cmd_w(udc, CMD_GET_DEV_STAT); + tmp = udc_protocol_cmd_r(udc, DAT_GET_DEV_STAT); + + if (tmp & DEV_RST) + uda_usb_reset(udc); + else if (tmp & DEV_CON_CH) + uda_power_event(udc, (tmp & DEV_CON)); + else if (tmp & DEV_SUS_CH) { + if (tmp & DEV_SUS) { + if (udc->vbus == 0) + stop_activity(udc); + else if ((udc->gadget.speed != USB_SPEED_UNKNOWN) && + udc->driver) { + /* Power down transceiver */ + udc->poweron = 0; + schedule_work(&udc->pullup_job); + uda_resm_susp_event(udc, 1); + } + } else if ((udc->gadget.speed != USB_SPEED_UNKNOWN) && + udc->driver && udc->vbus) { + uda_resm_susp_event(udc, 0); + /* Power up transceiver */ + udc->poweron = 1; + schedule_work(&udc->pullup_job); + } + } +} + +static int udc_get_status(struct lpc32xx_udc *udc, u16 reqtype, u16 wIndex) +{ + struct lpc32xx_ep *ep; + u32 ep0buff = 0, tmp; + + switch (reqtype & USB_RECIP_MASK) { + case USB_RECIP_INTERFACE: + break; /* Not supported */ + + case USB_RECIP_DEVICE: + ep0buff = (udc->selfpowered << USB_DEVICE_SELF_POWERED); + if (udc->dev_status & (1 << USB_DEVICE_REMOTE_WAKEUP)) + ep0buff |= (1 << USB_DEVICE_REMOTE_WAKEUP); + break; + + case USB_RECIP_ENDPOINT: + tmp = wIndex & USB_ENDPOINT_NUMBER_MASK; + ep = &udc->ep[tmp]; + if ((tmp == 0) || (tmp >= NUM_ENDPOINTS) || (tmp && !ep->desc)) + return -EOPNOTSUPP; + + if (wIndex & USB_DIR_IN) { + if (!ep->is_in) + return -EOPNOTSUPP; /* Something's wrong */ + } else if (ep->is_in) + return -EOPNOTSUPP; /* Not an IN endpoint */ + + /* Get status of the endpoint */ + udc_protocol_cmd_w(udc, CMD_SEL_EP(ep->hwep_num)); + tmp = udc_protocol_cmd_r(udc, DAT_SEL_EP(ep->hwep_num)); + + if (tmp & EP_SEL_ST) + ep0buff = (1 << USB_ENDPOINT_HALT); + else + ep0buff = 0; + break; + + default: + break; + } + + /* Return data */ + udc_write_hwep(udc, EP_IN, &ep0buff, 2); + + return 0; +} + +static void udc_handle_ep0_setup(struct lpc32xx_udc *udc) +{ + struct lpc32xx_ep *ep, *ep0 = &udc->ep[0]; + struct usb_ctrlrequest ctrlpkt; + int i, bytes; + u16 wIndex, wValue, wLength, reqtype, req, tmp; + + /* Nuke previous transfers */ + nuke(ep0, -EPROTO); + + /* Get setup packet */ + bytes = udc_read_hwep(udc, EP_OUT, (u32 *) &ctrlpkt, 8); + if (bytes != 8) { + ep_warn(ep0, "Incorrectly sized setup packet (s/b 8, is %d)!\n", + bytes); + return; + } + + /* Native endianness */ + wIndex = le16_to_cpu(ctrlpkt.wIndex); + wValue = le16_to_cpu(ctrlpkt.wValue); + wLength = le16_to_cpu(ctrlpkt.wLength); + reqtype = le16_to_cpu(ctrlpkt.bRequestType); + + /* Set direction of EP0 */ + if (likely(reqtype & USB_DIR_IN)) + ep0->is_in = 1; + else + ep0->is_in = 0; + + /* Handle SETUP packet */ + req = le16_to_cpu(ctrlpkt.bRequest); + switch (req) { + case USB_REQ_CLEAR_FEATURE: + case USB_REQ_SET_FEATURE: + switch (reqtype) { + case (USB_TYPE_STANDARD | USB_RECIP_DEVICE): + if (wValue != USB_DEVICE_REMOTE_WAKEUP) + goto stall; /* Nothing else handled */ + + /* Tell board about event */ + if (req == USB_REQ_CLEAR_FEATURE) + udc->dev_status &= + ~(1 << USB_DEVICE_REMOTE_WAKEUP); + else + udc->dev_status |= + (1 << USB_DEVICE_REMOTE_WAKEUP); + uda_remwkp_cgh(udc); + goto zlp_send; + + case (USB_TYPE_STANDARD | USB_RECIP_ENDPOINT): + tmp = wIndex & USB_ENDPOINT_NUMBER_MASK; + if ((wValue != USB_ENDPOINT_HALT) || + (tmp >= NUM_ENDPOINTS)) + break; + + /* Find hardware endpoint from logical endpoint */ + ep = &udc->ep[tmp]; + tmp = ep->hwep_num; + if (tmp == 0) + break; + + if (req == USB_REQ_SET_FEATURE) + udc_stall_hwep(udc, tmp); + else if (!ep->wedge) + udc_clrstall_hwep(udc, tmp); + + goto zlp_send; + + default: + break; + } + + + case USB_REQ_SET_ADDRESS: + if (reqtype == (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) { + udc_set_address(udc, wValue); + goto zlp_send; + } + break; + + case USB_REQ_GET_STATUS: + udc_get_status(udc, reqtype, wIndex); + return; + + default: + break; /* Let GadgetFS handle the descriptor instead */ + } + + if (likely(udc->driver)) { + /* device-2-host (IN) or no data setup command, process + * immediately */ + spin_unlock(&udc->lock); + i = udc->driver->setup(&udc->gadget, &ctrlpkt); + + spin_lock(&udc->lock); + if (req == USB_REQ_SET_CONFIGURATION) { + /* Configuration is set after endpoints are realized */ + if (wValue) { + /* Set configuration */ + udc_set_device_configured(udc); + + udc_protocol_cmd_data_w(udc, CMD_SET_MODE, + DAT_WR_BYTE(AP_CLK | + INAK_BI | INAK_II)); + } else { + /* Clear configuration */ + udc_set_device_unconfigured(udc); + + /* Disable NAK interrupts */ + udc_protocol_cmd_data_w(udc, CMD_SET_MODE, + DAT_WR_BYTE(AP_CLK)); + } + } + + if (i < 0) { + /* setup processing failed, force stall */ + dev_err(udc->dev, + "req %02x.%02x protocol STALL; stat %d\n", + reqtype, req, i); + udc->ep0state = WAIT_FOR_SETUP; + goto stall; + } + } + + if (!ep0->is_in) + udc_ep0_send_zlp(udc); /* ZLP IN packet on data phase */ + + return; + +stall: + udc_stall_hwep(udc, EP_IN); + return; + +zlp_send: + udc_ep0_send_zlp(udc); + return; +} + +/* IN endpoint 0 transfer */ +static void udc_handle_ep0_in(struct lpc32xx_udc *udc) +{ + struct lpc32xx_ep *ep0 = &udc->ep[0]; + u32 epstatus; + + /* Clear EP interrupt */ + epstatus = udc_clearep_getsts(udc, EP_IN); + +#ifdef CONFIG_USB_GADGET_DEBUG_FILES + ep0->totalints++; +#endif + + /* Stalled? Clear stall and reset buffers */ + if (epstatus & EP_SEL_ST) { + udc_clrstall_hwep(udc, EP_IN); + nuke(ep0, -ECONNABORTED); + udc->ep0state = WAIT_FOR_SETUP; + return; + } + + /* Is a buffer available? */ + if (!(epstatus & EP_SEL_F)) { + /* Handle based on current state */ + if (udc->ep0state == DATA_IN) + udc_ep0_in_req(udc); + else { + /* Unknown state for EP0 oe end of DATA IN phase */ + nuke(ep0, -ECONNABORTED); + udc->ep0state = WAIT_FOR_SETUP; + } + } +} + +/* OUT endpoint 0 transfer */ +static void udc_handle_ep0_out(struct lpc32xx_udc *udc) +{ + struct lpc32xx_ep *ep0 = &udc->ep[0]; + u32 epstatus; + + /* Clear EP interrupt */ + epstatus = udc_clearep_getsts(udc, EP_OUT); + + +#ifdef CONFIG_USB_GADGET_DEBUG_FILES + ep0->totalints++; +#endif + + /* Stalled? */ + if (epstatus & EP_SEL_ST) { + udc_clrstall_hwep(udc, EP_OUT); + nuke(ep0, -ECONNABORTED); + udc->ep0state = WAIT_FOR_SETUP; + return; + } + + /* A NAK may occur if a packet couldn't be received yet */ + if (epstatus & EP_SEL_EPN) + return; + /* Setup packet incoming? */ + if (epstatus & EP_SEL_STP) { + nuke(ep0, 0); + udc->ep0state = WAIT_FOR_SETUP; + } + + /* Data available? */ + if (epstatus & EP_SEL_F) + /* Handle based on current state */ + switch (udc->ep0state) { + case WAIT_FOR_SETUP: + udc_handle_ep0_setup(udc); + break; + + case DATA_OUT: + udc_ep0_out_req(udc); + break; + + default: + /* Unknown state for EP0 */ + nuke(ep0, -ECONNABORTED); + udc->ep0state = WAIT_FOR_SETUP; + } +} + +/* Must be called without lock */ +static int lpc32xx_get_frame(struct usb_gadget *gadget) +{ + int frame; + unsigned long flags; + struct lpc32xx_udc *udc = to_udc(gadget); + + if (!udc->clocked) + return -EINVAL; + + spin_lock_irqsave(&udc->lock, flags); + + frame = (int) udc_get_current_frame(udc); + + spin_unlock_irqrestore(&udc->lock, flags); + + return frame; +} + +static int lpc32xx_wakeup(struct usb_gadget *gadget) +{ + return -ENOTSUPP; +} + +static int lpc32xx_set_selfpowered(struct usb_gadget *gadget, int is_on) +{ + struct lpc32xx_udc *udc = to_udc(gadget); + + /* Always self-powered */ + udc->selfpowered = (is_on != 0); + + return 0; +} + +/* + * vbus is here! turn everything on that's ready + * Must be called without lock + */ +static int lpc32xx_vbus_session(struct usb_gadget *gadget, int is_active) +{ + unsigned long flags; + struct lpc32xx_udc *udc = to_udc(gadget); + + spin_lock_irqsave(&udc->lock, flags); + + /* Doesn't need lock */ + if (udc->driver) { + udc_clk_set(udc, 1); + udc_enable(udc); + pullup(udc, is_active); + } else { + stop_activity(udc); + pullup(udc, 0); + + spin_unlock_irqrestore(&udc->lock, flags); + /* + * Wait for all the endpoints to disable, + * before disabling clocks. Don't wait if + * endpoints are not enabled. + */ + if (atomic_read(&udc->enabled_ep_cnt)) + wait_event_interruptible(udc->ep_disable_wait_queue, + (atomic_read(&udc->enabled_ep_cnt) == 0)); + + spin_lock_irqsave(&udc->lock, flags); + + udc_clk_set(udc, 0); + } + + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +} + +/* Can be called with or without lock */ +static int lpc32xx_pullup(struct usb_gadget *gadget, int is_on) +{ + struct lpc32xx_udc *udc = to_udc(gadget); + + /* Doesn't need lock */ + pullup(udc, is_on); + + return 0; +} + +static int lpc32xx_start(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)); +static int lpc32xx_stop(struct usb_gadget_driver *driver); + +static const struct usb_gadget_ops lpc32xx_udc_ops = { + .get_frame = lpc32xx_get_frame, + .wakeup = lpc32xx_wakeup, + .set_selfpowered = lpc32xx_set_selfpowered, + .vbus_session = lpc32xx_vbus_session, + .pullup = lpc32xx_pullup, + .start = lpc32xx_start, + .stop = lpc32xx_stop, +}; + +static void nop_release(struct device *dev) +{ + /* nothing to free */ +} + +static struct lpc32xx_udc controller = { + .gadget = { + .ops = &lpc32xx_udc_ops, + .ep0 = &controller.ep[0].ep, + .name = driver_name, + .dev = { + .init_name = "gadget", + .release = nop_release, + } + }, + .ep[0] = { + .ep = { + .name = "ep0", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 64, + .hwep_num_base = 0, + .hwep_num = 0, /* Can be 0 or 1, has special handling */ + .lep = 0, + .eptype = EP_CTL_TYPE, + }, + .ep[1] = { + .ep = { + .name = "ep1-int", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 64, + .hwep_num_base = 2, + .hwep_num = 0, /* 2 or 3, will be set later */ + .lep = 1, + .eptype = EP_INT_TYPE, + }, + .ep[2] = { + .ep = { + .name = "ep2-bulk", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 64, + .hwep_num_base = 4, + .hwep_num = 0, /* 4 or 5, will be set later */ + .lep = 2, + .eptype = EP_BLK_TYPE, + }, + .ep[3] = { + .ep = { + .name = "ep3-iso", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 1023, + .hwep_num_base = 6, + .hwep_num = 0, /* 6 or 7, will be set later */ + .lep = 3, + .eptype = EP_ISO_TYPE, + }, + .ep[4] = { + .ep = { + .name = "ep4-int", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 64, + .hwep_num_base = 8, + .hwep_num = 0, /* 8 or 9, will be set later */ + .lep = 4, + .eptype = EP_INT_TYPE, + }, + .ep[5] = { + .ep = { + .name = "ep5-bulk", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 64, + .hwep_num_base = 10, + .hwep_num = 0, /* 10 or 11, will be set later */ + .lep = 5, + .eptype = EP_BLK_TYPE, + }, + .ep[6] = { + .ep = { + .name = "ep6-iso", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 1023, + .hwep_num_base = 12, + .hwep_num = 0, /* 12 or 13, will be set later */ + .lep = 6, + .eptype = EP_ISO_TYPE, + }, + .ep[7] = { + .ep = { + .name = "ep7-int", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 64, + .hwep_num_base = 14, + .hwep_num = 0, + .lep = 7, + .eptype = EP_INT_TYPE, + }, + .ep[8] = { + .ep = { + .name = "ep8-bulk", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 64, + .hwep_num_base = 16, + .hwep_num = 0, + .lep = 8, + .eptype = EP_BLK_TYPE, + }, + .ep[9] = { + .ep = { + .name = "ep9-iso", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 1023, + .hwep_num_base = 18, + .hwep_num = 0, + .lep = 9, + .eptype = EP_ISO_TYPE, + }, + .ep[10] = { + .ep = { + .name = "ep10-int", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 64, + .hwep_num_base = 20, + .hwep_num = 0, + .lep = 10, + .eptype = EP_INT_TYPE, + }, + .ep[11] = { + .ep = { + .name = "ep11-bulk", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 64, + .hwep_num_base = 22, + .hwep_num = 0, + .lep = 11, + .eptype = EP_BLK_TYPE, + }, + .ep[12] = { + .ep = { + .name = "ep12-iso", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 1023, + .hwep_num_base = 24, + .hwep_num = 0, + .lep = 12, + .eptype = EP_ISO_TYPE, + }, + .ep[13] = { + .ep = { + .name = "ep13-int", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 64, + .hwep_num_base = 26, + .hwep_num = 0, + .lep = 13, + .eptype = EP_INT_TYPE, + }, + .ep[14] = { + .ep = { + .name = "ep14-bulk", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 64, + .hwep_num_base = 28, + .hwep_num = 0, + .lep = 14, + .eptype = EP_BLK_TYPE, + }, + .ep[15] = { + .ep = { + .name = "ep15-bulk", + .ops = &lpc32xx_ep_ops, + }, + .udc = &controller, + .maxpacket = 1023, + .hwep_num_base = 30, + .hwep_num = 0, + .lep = 15, + .eptype = EP_BLK_TYPE, + }, +}; + +/* ISO and status interrupts */ +static irqreturn_t lpc32xx_usb_lp_irq(int irq, void *_udc) +{ + u32 tmp, devstat; + struct lpc32xx_udc *udc = _udc; + + spin_lock(&udc->lock); + + /* Read the device status register */ + devstat = readl(USBD_DEVINTST(udc->udp_baseaddr)); + + devstat &= ~USBD_EP_FAST; + writel(devstat, USBD_DEVINTCLR(udc->udp_baseaddr)); + devstat = devstat & udc->enabled_devints; + + /* Device specific handling needed? */ + if (devstat & USBD_DEV_STAT) + udc_handle_dev(udc); + + /* Start of frame? (devstat & FRAME_INT): + * The frame interrupt isn't really needed for ISO support, + * as the driver will queue the necessary packets */ + + /* Error? */ + if (devstat & ERR_INT) { + /* All types of errors, from cable removal during transfer to + * misc protocol and bit errors. These are mostly for just info, + * as the USB hardware will work around these. If these errors + * happen alot, something is wrong. */ + udc_protocol_cmd_w(udc, CMD_RD_ERR_STAT); + tmp = udc_protocol_cmd_r(udc, DAT_RD_ERR_STAT); + dev_dbg(udc->dev, "Device error (0x%x)!\n", tmp); + } + + spin_unlock(&udc->lock); + + return IRQ_HANDLED; +} + +/* EP interrupts */ +static irqreturn_t lpc32xx_usb_hp_irq(int irq, void *_udc) +{ + u32 tmp; + struct lpc32xx_udc *udc = _udc; + + spin_lock(&udc->lock); + + /* Read the device status register */ + writel(USBD_EP_FAST, USBD_DEVINTCLR(udc->udp_baseaddr)); + + /* Endpoints */ + tmp = readl(USBD_EPINTST(udc->udp_baseaddr)); + + /* Special handling for EP0 */ + if (tmp & (EP_MASK_SEL(0, EP_OUT) | EP_MASK_SEL(0, EP_IN))) { + /* Handle EP0 IN */ + if (tmp & (EP_MASK_SEL(0, EP_IN))) + udc_handle_ep0_in(udc); + + /* Handle EP0 OUT */ + if (tmp & (EP_MASK_SEL(0, EP_OUT))) + udc_handle_ep0_out(udc); + } + + /* All other EPs */ + if (tmp & ~(EP_MASK_SEL(0, EP_OUT) | EP_MASK_SEL(0, EP_IN))) { + int i; + + /* Handle other EP interrupts */ + for (i = 1; i < NUM_ENDPOINTS; i++) { + if (tmp & (1 << udc->ep[i].hwep_num)) + udc_handle_eps(udc, &udc->ep[i]); + } + } + + spin_unlock(&udc->lock); + + return IRQ_HANDLED; +} + +static irqreturn_t lpc32xx_usb_devdma_irq(int irq, void *_udc) +{ + struct lpc32xx_udc *udc = _udc; + + int i; + u32 tmp; + + spin_lock(&udc->lock); + + /* Handle EP DMA EOT interrupts */ + tmp = readl(USBD_EOTINTST(udc->udp_baseaddr)) | + (readl(USBD_EPDMAST(udc->udp_baseaddr)) & + readl(USBD_NDDRTINTST(udc->udp_baseaddr))) | + readl(USBD_SYSERRTINTST(udc->udp_baseaddr)); + for (i = 1; i < NUM_ENDPOINTS; i++) { + if (tmp & (1 << udc->ep[i].hwep_num)) + udc_handle_dma_ep(udc, &udc->ep[i]); + } + + spin_unlock(&udc->lock); + + return IRQ_HANDLED; +} + +/* + * + * VBUS detection, pullup handler, and Gadget cable state notification + * + */ +static void vbus_work(struct work_struct *work) +{ + u8 value; + struct lpc32xx_udc *udc = container_of(work, struct lpc32xx_udc, + vbus_job); + + if (udc->enabled != 0) { + /* Discharge VBUS real quick */ + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DISCHRG); + + /* Give VBUS some time (100mS) to discharge */ + msleep(100); + + /* Disable VBUS discharge resistor */ + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR, + OTG1_VBUS_DISCHRG); + + /* Clear interrupt */ + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_INTERRUPT_LATCH | + ISP1301_I2C_REG_CLEAR_ADDR, ~0); + + /* Get the VBUS status from the transceiver */ + value = i2c_smbus_read_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_OTG_CONTROL_2); + + /* VBUS on or off? */ + if (value & OTG_B_SESS_VLD) + udc->vbus = 1; + else + udc->vbus = 0; + + /* VBUS changed? */ + if (udc->last_vbus != udc->vbus) { + udc->last_vbus = udc->vbus; + lpc32xx_vbus_session(&udc->gadget, udc->vbus); + } + } + + /* Re-enable after completion */ + enable_irq(udc->udp_irq[IRQ_USB_ATX]); +} + +static irqreturn_t lpc32xx_usb_vbus_irq(int irq, void *_udc) +{ + struct lpc32xx_udc *udc = _udc; + + /* Defer handling of VBUS IRQ to work queue */ + disable_irq_nosync(udc->udp_irq[IRQ_USB_ATX]); + schedule_work(&udc->vbus_job); + + return IRQ_HANDLED; +} + +static int lpc32xx_start(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) +{ + struct lpc32xx_udc *udc = &controller; + int retval, i; + + if (!driver || driver->max_speed < USB_SPEED_FULL || + !bind || !driver->setup) { + dev_err(udc->dev, "bad parameter.\n"); + return -EINVAL; + } + + if (udc->driver) { + dev_err(udc->dev, "UDC already has a gadget driver\n"); + return -EBUSY; + } + + udc->driver = driver; + udc->gadget.dev.driver = &driver->driver; + udc->enabled = 1; + udc->selfpowered = 1; + udc->vbus = 0; + + retval = bind(&udc->gadget); + if (retval) { + dev_err(udc->dev, "bind() returned %d\n", retval); + udc->enabled = 0; + udc->selfpowered = 0; + udc->driver = NULL; + udc->gadget.dev.driver = NULL; + return retval; + } + + dev_dbg(udc->dev, "bound to %s\n", driver->driver.name); + + /* Force VBUS process once to check for cable insertion */ + udc->last_vbus = udc->vbus = 0; + schedule_work(&udc->vbus_job); + + /* Do not re-enable ATX IRQ (3) */ + for (i = IRQ_USB_LP; i < IRQ_USB_ATX; i++) + enable_irq(udc->udp_irq[i]); + + return 0; +} + +static int lpc32xx_stop(struct usb_gadget_driver *driver) +{ + int i; + struct lpc32xx_udc *udc = &controller; + + if (!driver || driver != udc->driver || !driver->unbind) + return -EINVAL; + + /* Disable USB pullup */ + isp1301_pullup_enable(udc, 0, 1); + + for (i = IRQ_USB_LP; i <= IRQ_USB_ATX; i++) + disable_irq(udc->udp_irq[i]); + + if (udc->clocked) { + + spin_lock(&udc->lock); + stop_activity(udc); + spin_unlock(&udc->lock); + + /* + * Wait for all the endpoints to disable, + * before disabling clocks. Don't wait if + * endpoints are not enabled. + */ + if (atomic_read(&udc->enabled_ep_cnt)) + wait_event_interruptible(udc->ep_disable_wait_queue, + (atomic_read(&udc->enabled_ep_cnt) == 0)); + + spin_lock(&udc->lock); + udc_clk_set(udc, 0); + spin_unlock(&udc->lock); + } + + udc->enabled = 0; + pullup(udc, 0); + + driver->unbind(&udc->gadget); + udc->gadget.dev.driver = NULL; + udc->driver = NULL; + + dev_dbg(udc->dev, "unbound from %s\n", driver->driver.name); + return 0; +} + +static void lpc32xx_udc_shutdown(struct platform_device *dev) +{ + /* Force disconnect on reboot */ + struct lpc32xx_udc *udc = &controller; + + pullup(udc, 0); +} + +/* + * Callbacks to be overridden by options passed via OF (TODO) + */ + +static void lpc32xx_usbd_conn_chg(int conn) +{ + /* Do nothing, it might be nice to enable an LED + * based on conn state being !0 */ +} + +static void lpc32xx_usbd_susp_chg(int susp) +{ + /* Device suspend if susp != 0 */ +} + +static void lpc32xx_rmwkup_chg(int remote_wakup_enable) +{ + /* Enable or disable USB remote wakeup */ +} + +struct lpc32xx_usbd_cfg lpc32xx_usbddata = { + .vbus_drv_pol = 0, + .conn_chgb = &lpc32xx_usbd_conn_chg, + .susp_chgb = &lpc32xx_usbd_susp_chg, + .rmwk_chgb = &lpc32xx_rmwkup_chg, +}; + + +static u64 lpc32xx_usbd_dmamask = ~(u32) 0x7F; + +static int __init lpc32xx_udc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct lpc32xx_udc *udc = &controller; + int retval, i; + struct resource *res; + dma_addr_t dma_handle; + struct device_node *isp1301_node; + + /* init software state */ + udc->gadget.dev.parent = dev; + udc->pdev = pdev; + udc->dev = &pdev->dev; + udc->enabled = 0; + + if (pdev->dev.of_node) { + isp1301_node = of_parse_phandle(pdev->dev.of_node, + "transceiver", 0); + } else { + isp1301_node = NULL; + } + + udc->isp1301_i2c_client = isp1301_get_client(isp1301_node); + if (!udc->isp1301_i2c_client) + return -EPROBE_DEFER; + + dev_info(udc->dev, "ISP1301 I2C device at address 0x%x\n", + udc->isp1301_i2c_client->addr); + + pdev->dev.dma_mask = &lpc32xx_usbd_dmamask; + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + + udc->board = &lpc32xx_usbddata; + + /* + * Resources are mapped as follows: + * IORESOURCE_MEM, base address and size of USB space + * IORESOURCE_IRQ, USB device low priority interrupt number + * IORESOURCE_IRQ, USB device high priority interrupt number + * IORESOURCE_IRQ, USB device interrupt number + * IORESOURCE_IRQ, USB transceiver interrupt number + */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENXIO; + + spin_lock_init(&udc->lock); + + /* Get IRQs */ + for (i = 0; i < 4; i++) { + udc->udp_irq[i] = platform_get_irq(pdev, i); + if (udc->udp_irq[i] < 0) { + dev_err(udc->dev, + "irq resource %d not available!\n", i); + return udc->udp_irq[i]; + } + } + + udc->io_p_start = res->start; + udc->io_p_size = resource_size(res); + if (!request_mem_region(udc->io_p_start, udc->io_p_size, driver_name)) { + dev_err(udc->dev, "someone's using UDC memory\n"); + return -EBUSY; + } + + udc->udp_baseaddr = ioremap(udc->io_p_start, udc->io_p_size); + if (!udc->udp_baseaddr) { + retval = -ENOMEM; + dev_err(udc->dev, "IO map failure\n"); + goto io_map_fail; + } + + /* Enable AHB slave USB clock, needed for further USB clock control */ + writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL); + + /* Get required clocks */ + udc->usb_pll_clk = clk_get(&pdev->dev, "ck_pll5"); + if (IS_ERR(udc->usb_pll_clk)) { + dev_err(udc->dev, "failed to acquire USB PLL\n"); + retval = PTR_ERR(udc->usb_pll_clk); + goto pll_get_fail; + } + udc->usb_slv_clk = clk_get(&pdev->dev, "ck_usbd"); + if (IS_ERR(udc->usb_slv_clk)) { + dev_err(udc->dev, "failed to acquire USB device clock\n"); + retval = PTR_ERR(udc->usb_slv_clk); + goto usb_clk_get_fail; + } + + /* Setup PLL clock to 48MHz */ + retval = clk_enable(udc->usb_pll_clk); + if (retval < 0) { + dev_err(udc->dev, "failed to start USB PLL\n"); + goto pll_enable_fail; + } + + retval = clk_set_rate(udc->usb_pll_clk, 48000); + if (retval < 0) { + dev_err(udc->dev, "failed to set USB clock rate\n"); + goto pll_set_fail; + } + + writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN, USB_CTRL); + + /* Enable USB device clock */ + retval = clk_enable(udc->usb_slv_clk); + if (retval < 0) { + dev_err(udc->dev, "failed to start USB device clock\n"); + goto usb_clk_enable_fail; + } + + /* Set to enable all needed USB OTG clocks */ + writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL(udc)); + + i = 1000; + while (((readl(USB_OTG_CLK_STAT(udc)) & USB_CLOCK_MASK) != + USB_CLOCK_MASK) && (i > 0)) + i--; + if (!i) + dev_dbg(udc->dev, "USB OTG clocks not correctly enabled\n"); + + /* Setup deferred workqueue data */ + udc->poweron = udc->pullup = 0; + INIT_WORK(&udc->pullup_job, pullup_work); + INIT_WORK(&udc->vbus_job, vbus_work); +#ifdef CONFIG_PM + INIT_WORK(&udc->power_job, power_work); +#endif + + /* All clocks are now on */ + udc->clocked = 1; + + isp1301_udc_configure(udc); + /* Allocate memory for the UDCA */ + udc->udca_v_base = dma_alloc_coherent(&pdev->dev, UDCA_BUFF_SIZE, + &dma_handle, + (GFP_KERNEL | GFP_DMA)); + if (!udc->udca_v_base) { + dev_err(udc->dev, "error getting UDCA region\n"); + retval = -ENOMEM; + goto i2c_fail; + } + udc->udca_p_base = dma_handle; + dev_dbg(udc->dev, "DMA buffer(0x%x bytes), P:0x%08x, V:0x%p\n", + UDCA_BUFF_SIZE, udc->udca_p_base, udc->udca_v_base); + + /* Setup the DD DMA memory pool */ + udc->dd_cache = dma_pool_create("udc_dd", udc->dev, + sizeof(struct lpc32xx_usbd_dd_gad), + sizeof(u32), 0); + if (!udc->dd_cache) { + dev_err(udc->dev, "error getting DD DMA region\n"); + retval = -ENOMEM; + goto dma_alloc_fail; + } + + /* Clear USB peripheral and initialize gadget endpoints */ + udc_disable(udc); + udc_reinit(udc); + + retval = device_register(&udc->gadget.dev); + if (retval < 0) { + dev_err(udc->dev, "Device registration failure\n"); + goto dev_register_fail; + } + + /* Request IRQs - low and high priority USB device IRQs are routed to + * the same handler, while the DMA interrupt is routed elsewhere */ + retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq, + 0, "udc_lp", udc); + if (retval < 0) { + dev_err(udc->dev, "LP request irq %d failed\n", + udc->udp_irq[IRQ_USB_LP]); + goto irq_lp_fail; + } + retval = request_irq(udc->udp_irq[IRQ_USB_HP], lpc32xx_usb_hp_irq, + 0, "udc_hp", udc); + if (retval < 0) { + dev_err(udc->dev, "HP request irq %d failed\n", + udc->udp_irq[IRQ_USB_HP]); + goto irq_hp_fail; + } + + retval = request_irq(udc->udp_irq[IRQ_USB_DEVDMA], + lpc32xx_usb_devdma_irq, 0, "udc_dma", udc); + if (retval < 0) { + dev_err(udc->dev, "DEV request irq %d failed\n", + udc->udp_irq[IRQ_USB_DEVDMA]); + goto irq_dev_fail; + } + + /* The transceiver interrupt is used for VBUS detection and will + kick off the VBUS handler function */ + retval = request_irq(udc->udp_irq[IRQ_USB_ATX], lpc32xx_usb_vbus_irq, + 0, "udc_otg", udc); + if (retval < 0) { + dev_err(udc->dev, "VBUS request irq %d failed\n", + udc->udp_irq[IRQ_USB_ATX]); + goto irq_xcvr_fail; + } + + /* Initialize wait queue */ + init_waitqueue_head(&udc->ep_disable_wait_queue); + atomic_set(&udc->enabled_ep_cnt, 0); + + /* Keep all IRQs disabled until GadgetFS starts up */ + for (i = IRQ_USB_LP; i <= IRQ_USB_ATX; i++) + disable_irq(udc->udp_irq[i]); + + retval = usb_add_gadget_udc(dev, &udc->gadget); + if (retval < 0) + goto add_gadget_fail; + + dev_set_drvdata(dev, udc); + device_init_wakeup(dev, 1); + create_debug_file(udc); + + /* Disable clocks for now */ + udc_clk_set(udc, 0); + + dev_info(udc->dev, "%s version %s\n", driver_name, DRIVER_VERSION); + return 0; + +add_gadget_fail: + free_irq(udc->udp_irq[IRQ_USB_ATX], udc); +irq_xcvr_fail: + free_irq(udc->udp_irq[IRQ_USB_DEVDMA], udc); +irq_dev_fail: + free_irq(udc->udp_irq[IRQ_USB_HP], udc); +irq_hp_fail: + free_irq(udc->udp_irq[IRQ_USB_LP], udc); +irq_lp_fail: + device_unregister(&udc->gadget.dev); +dev_register_fail: + dma_pool_destroy(udc->dd_cache); +dma_alloc_fail: + dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE, + udc->udca_v_base, udc->udca_p_base); +i2c_fail: + clk_disable(udc->usb_slv_clk); +usb_clk_enable_fail: +pll_set_fail: + clk_disable(udc->usb_pll_clk); +pll_enable_fail: + clk_put(udc->usb_slv_clk); +usb_clk_get_fail: + clk_put(udc->usb_pll_clk); +pll_get_fail: + iounmap(udc->udp_baseaddr); +io_map_fail: + release_mem_region(udc->io_p_start, udc->io_p_size); + dev_err(udc->dev, "%s probe failed, %d\n", driver_name, retval); + + return retval; +} + +static int __devexit lpc32xx_udc_remove(struct platform_device *pdev) +{ + struct lpc32xx_udc *udc = platform_get_drvdata(pdev); + + usb_del_gadget_udc(&udc->gadget); + if (udc->driver) + return -EBUSY; + + udc_clk_set(udc, 1); + udc_disable(udc); + pullup(udc, 0); + + free_irq(udc->udp_irq[IRQ_USB_ATX], udc); + + device_init_wakeup(&pdev->dev, 0); + remove_debug_file(udc); + + dma_pool_destroy(udc->dd_cache); + dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE, + udc->udca_v_base, udc->udca_p_base); + free_irq(udc->udp_irq[IRQ_USB_DEVDMA], udc); + free_irq(udc->udp_irq[IRQ_USB_HP], udc); + free_irq(udc->udp_irq[IRQ_USB_LP], udc); + + device_unregister(&udc->gadget.dev); + + clk_disable(udc->usb_slv_clk); + clk_put(udc->usb_slv_clk); + clk_disable(udc->usb_pll_clk); + clk_put(udc->usb_pll_clk); + iounmap(udc->udp_baseaddr); + release_mem_region(udc->io_p_start, udc->io_p_size); + + return 0; +} + +#ifdef CONFIG_PM +static int lpc32xx_udc_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + int to = 1000; + struct lpc32xx_udc *udc = platform_get_drvdata(pdev); + + if (udc->clocked) { + /* Power down ISP */ + udc->poweron = 0; + isp1301_set_powerstate(udc, 0); + + /* Disable clocking */ + udc_clk_set(udc, 0); + + /* Keep clock flag on, so we know to re-enable clocks + on resume */ + udc->clocked = 1; + + /* Kill OTG and I2C clocks */ + writel(0, USB_OTG_CLK_CTRL(udc)); + while (((readl(USB_OTG_CLK_STAT(udc)) & OTGOFF_CLK_MASK) != + OTGOFF_CLK_MASK) && (to > 0)) + to--; + if (!to) + dev_dbg(udc->dev, + "USB OTG clocks not correctly enabled\n"); + + /* Kill global USB clock */ + clk_disable(udc->usb_slv_clk); + } + + return 0; +} + +static int lpc32xx_udc_resume(struct platform_device *pdev) +{ + struct lpc32xx_udc *udc = platform_get_drvdata(pdev); + + if (udc->clocked) { + /* Enable global USB clock */ + clk_enable(udc->usb_slv_clk); + + /* Enable clocking */ + udc_clk_set(udc, 1); + + /* ISP back to normal power mode */ + udc->poweron = 1; + isp1301_set_powerstate(udc, 1); + } + + return 0; +} +#else +#define lpc32xx_udc_suspend NULL +#define lpc32xx_udc_resume NULL +#endif + +#ifdef CONFIG_OF +static struct of_device_id lpc32xx_udc_of_match[] = { + { .compatible = "nxp,lpc3220-udc", }, + { }, +}; +MODULE_DEVICE_TABLE(of, lpc32xx_udc_of_match); +#endif + +static struct platform_driver lpc32xx_udc_driver = { + .remove = __devexit_p(lpc32xx_udc_remove), + .shutdown = lpc32xx_udc_shutdown, + .suspend = lpc32xx_udc_suspend, + .resume = lpc32xx_udc_resume, + .driver = { + .name = (char *) driver_name, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(lpc32xx_udc_of_match), + }, +}; + +static int __init udc_init_module(void) +{ + return platform_driver_probe(&lpc32xx_udc_driver, lpc32xx_udc_probe); +} +module_init(udc_init_module); + +static void __exit udc_exit_module(void) +{ + platform_driver_unregister(&lpc32xx_udc_driver); +} +module_exit(udc_exit_module); + +MODULE_DESCRIPTION("LPC32XX udc driver"); +MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>"); +MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:lpc32xx_udc"); diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 3608b3bd5732..8981fbb5748c 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -390,7 +390,7 @@ static int alloc_pipe_config(struct m66592_ep *ep, int *counter; int ret; - ep->desc = desc; + ep->ep.desc = desc; BUG_ON(ep->pipenum); @@ -558,7 +558,7 @@ static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req) static void start_packet(struct m66592_ep *ep, struct m66592_request *req) { - if (ep->desc->bEndpointAddress & USB_DIR_IN) + if (ep->ep.desc->bEndpointAddress & USB_DIR_IN) start_packet_write(ep, req); else start_packet_read(ep, req); @@ -734,7 +734,7 @@ __acquires(m66592->lock) if (restart) { req = list_entry(ep->queue.next, struct m66592_request, queue); - if (ep->desc) + if (ep->ep.desc) start_packet(ep, req); } } @@ -917,7 +917,7 @@ static void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb) ep = m66592->pipenum2ep[pipenum]; req = list_entry(ep->queue.next, struct m66592_request, queue); - if (ep->desc->bEndpointAddress & USB_DIR_IN) + if (ep->ep.desc->bEndpointAddress & USB_DIR_IN) irq_packet_write(ep, req); else irq_packet_read(ep, req); @@ -1377,7 +1377,7 @@ static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req, req->req.actual = 0; req->req.status = -EINPROGRESS; - if (ep->desc == NULL) /* control */ + if (ep->ep.desc == NULL) /* control */ start_ep0(ep, req); else { if (request && !ep->busy) diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h index 9d9f7e39f037..88c85b4116a2 100644 --- a/drivers/usb/gadget/m66592-udc.h +++ b/drivers/usb/gadget/m66592-udc.h @@ -456,7 +456,7 @@ struct m66592_ep { unsigned use_dma:1; u16 pipenum; u16 type; - const struct usb_endpoint_descriptor *desc; + /* register address */ unsigned long fifoaddr; unsigned long fifosel; diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h index e2be9519abbe..9073436d8b24 100644 --- a/drivers/usb/gadget/mv_udc.h +++ b/drivers/usb/gadget/mv_udc.h @@ -232,7 +232,6 @@ struct mv_ep { struct mv_udc *udc; struct list_head queue; struct mv_dqh *dqh; - const struct usb_endpoint_descriptor *desc; u32 direction; char name[14]; unsigned stopped:1, diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index a73cf406e2a4..dbcd1329495e 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -464,7 +464,7 @@ static int mv_ep_enable(struct usb_ep *_ep, ep = container_of(_ep, struct mv_ep, ep); udc = ep->udc; - if (!_ep || !desc || ep->desc + if (!_ep || !desc || ep->ep.desc || desc->bDescriptorType != USB_DT_ENDPOINT) return -EINVAL; @@ -528,7 +528,7 @@ static int mv_ep_enable(struct usb_ep *_ep, dqh->size_ioc_int_sts = 0; ep->ep.maxpacket = max; - ep->desc = desc; + ep->ep.desc = desc; ep->stopped = 0; /* Enable the endpoint for Rx or Tx and set the endpoint type */ @@ -580,7 +580,7 @@ static int mv_ep_disable(struct usb_ep *_ep) unsigned long flags; ep = container_of(_ep, struct mv_ep, ep); - if ((_ep == NULL) || !ep->desc) + if ((_ep == NULL) || !ep->ep.desc) return -EINVAL; udc = ep->udc; @@ -606,7 +606,6 @@ static int mv_ep_disable(struct usb_ep *_ep) /* nuke all pending requests (does flush) */ nuke(ep, -ESHUTDOWN); - ep->desc = NULL; ep->ep.desc = NULL; ep->stopped = 1; @@ -651,7 +650,7 @@ static void mv_ep_fifo_flush(struct usb_ep *_ep) return; ep = container_of(_ep, struct mv_ep, ep); - if (!ep->desc) + if (!ep->ep.desc) return; udc = ep->udc; @@ -715,11 +714,11 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) dev_err(&udc->dev->dev, "%s, bad params", __func__); return -EINVAL; } - if (unlikely(!_ep || !ep->desc)) { + if (unlikely(!_ep || !ep->ep.desc)) { dev_err(&udc->dev->dev, "%s, bad ep", __func__); return -EINVAL; } - if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { + if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { if (req->req.length > ep->ep.maxpacket) return -EMSGSIZE; } @@ -925,12 +924,12 @@ static int mv_ep_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge) ep = container_of(_ep, struct mv_ep, ep); udc = ep->udc; - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { status = -EINVAL; goto out; } - if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { + if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { status = -EOPNOTSUPP; goto out; } @@ -1279,7 +1278,7 @@ static int eps_init(struct mv_udc *udc) ep->stopped = 0; ep->ep.maxpacket = EP0_MAX_PKT_SIZE; ep->ep_num = 0; - ep->desc = &mv_ep0_desc; + ep->ep.desc = &mv_ep0_desc; INIT_LIST_HEAD(&ep->queue); ep->ep_type = USB_ENDPOINT_XFER_CONTROL; diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 3b4b6dd0f95a..7ba32469c5bd 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -153,7 +153,7 @@ static int omap_ep_enable(struct usb_ep *_ep, u16 maxp; /* catch various bogus parameters */ - if (!_ep || !desc || ep->desc + if (!_ep || !desc || ep->ep.desc || desc->bDescriptorType != USB_DT_ENDPOINT || ep->bEndpointAddress != desc->bEndpointAddress || ep->maxpacket < usb_endpoint_maxp(desc)) { @@ -200,7 +200,7 @@ static int omap_ep_enable(struct usb_ep *_ep, spin_lock_irqsave(&udc->lock, flags); - ep->desc = desc; + ep->ep.desc = desc; ep->irqs = 0; ep->stopped = 0; ep->ep.maxpacket = maxp; @@ -242,14 +242,13 @@ static int omap_ep_disable(struct usb_ep *_ep) struct omap_ep *ep = container_of(_ep, struct omap_ep, ep); unsigned long flags; - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { DBG("%s, %s not enabled\n", __func__, _ep ? ep->ep.name : NULL); return -EINVAL; } spin_lock_irqsave(&ep->udc->lock, flags); - ep->desc = NULL; ep->ep.desc = NULL; nuke (ep, -ESHUTDOWN); ep->ep.maxpacket = ep->maxpacket; @@ -917,7 +916,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) DBG("%s, bad params\n", __func__); return -EINVAL; } - if (!_ep || (!ep->desc && ep->bEndpointAddress)) { + if (!_ep || (!ep->ep.desc && ep->bEndpointAddress)) { DBG("%s, bad ep\n", __func__); return -EINVAL; } @@ -1121,7 +1120,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value) status = 0; /* otherwise, all active non-ISO endpoints can halt */ - } else if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC && ep->desc) { + } else if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC && ep->ep.desc) { /* IN endpoints must already be idle */ if ((ep->bEndpointAddress & USB_DIR_IN) @@ -1625,7 +1624,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) if (w_index & USB_DIR_IN) ep += 16; if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC - || !ep->desc) + || !ep->ep.desc) goto do_stall; use_ep(ep, 0); omap_writew(udc->clr_halt, UDC_CTRL); @@ -1653,7 +1652,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) if (w_index & USB_DIR_IN) ep += 16; if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC - || ep == ep0 || !ep->desc) + || ep == ep0 || !ep->ep.desc) goto do_stall; if (use_dma && ep->has_dma) { /* this has rude side-effects (aborts) and @@ -1688,7 +1687,7 @@ ep0out_status_stage: ep = &udc->ep[w_index & 0xf]; if (w_index & USB_DIR_IN) ep += 16; - if (!ep->desc) + if (!ep->ep.desc) goto do_stall; /* iso never stalls */ @@ -2509,7 +2508,7 @@ static int proc_udc_show(struct seq_file *s, void *_) if (tmp & UDC_ADD) { list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) { - if (ep->desc) + if (ep->ep.desc) proc_ep_show(s, ep); } } diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h index 59d3b2213cb1..cfadeb5fc5de 100644 --- a/drivers/usb/gadget/omap_udc.h +++ b/drivers/usb/gadget/omap_udc.h @@ -140,7 +140,6 @@ struct omap_ep { struct list_head queue; unsigned long irqs; struct list_head iso; - const struct usb_endpoint_descriptor *desc; char name[14]; u16 maxpacket; u8 bEndpointAddress; diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 65307064a6fd..1cfcc9ecbfbc 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -295,7 +295,6 @@ struct pch_udc_ep { struct pch_udc_data_dma_desc *td_data; struct pch_udc_dev *dev; unsigned long offset_addr; - const struct usb_endpoint_descriptor *desc; struct list_head queue; unsigned num:5, in:1, @@ -1705,7 +1704,7 @@ static int pch_udc_pcd_ep_enable(struct usb_ep *usbep, if (!dev->driver || (dev->gadget.speed == USB_SPEED_UNKNOWN)) return -ESHUTDOWN; spin_lock_irqsave(&dev->lock, iflags); - ep->desc = desc; + ep->ep.desc = desc; ep->halted = 0; pch_udc_ep_enable(ep, &ep->dev->cfg_data, desc); ep->ep.maxpacket = usb_endpoint_maxp(desc); @@ -1734,7 +1733,7 @@ static int pch_udc_pcd_ep_disable(struct usb_ep *usbep) ep = container_of(usbep, struct pch_udc_ep, ep); dev = ep->dev; - if ((usbep->name == ep0_string) || !ep->desc) + if ((usbep->name == ep0_string) || !ep->ep.desc) return -EINVAL; spin_lock_irqsave(&ep->dev->lock, iflags); @@ -1742,7 +1741,6 @@ static int pch_udc_pcd_ep_disable(struct usb_ep *usbep) ep->halted = 1; pch_udc_ep_disable(ep); pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num)); - ep->desc = NULL; ep->ep.desc = NULL; INIT_LIST_HEAD(&ep->queue); spin_unlock_irqrestore(&ep->dev->lock, iflags); @@ -1849,7 +1847,7 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq, return -EINVAL; ep = container_of(usbep, struct pch_udc_ep, ep); dev = ep->dev; - if (!ep->desc && ep->num) + if (!ep->ep.desc && ep->num) return -EINVAL; req = container_of(usbreq, struct pch_udc_request, req); if (!list_empty(&req->queue)) @@ -1949,7 +1947,7 @@ static int pch_udc_pcd_dequeue(struct usb_ep *usbep, ep = container_of(usbep, struct pch_udc_ep, ep); dev = ep->dev; - if (!usbep || !usbreq || (!ep->desc && ep->num)) + if (!usbep || !usbreq || (!ep->ep.desc && ep->num)) return ret; req = container_of(usbreq, struct pch_udc_request, req); spin_lock_irqsave(&ep->dev->lock, flags); @@ -1988,7 +1986,7 @@ static int pch_udc_pcd_set_halt(struct usb_ep *usbep, int halt) return -EINVAL; ep = container_of(usbep, struct pch_udc_ep, ep); dev = ep->dev; - if (!ep->desc && !ep->num) + if (!ep->ep.desc && !ep->num) return -EINVAL; if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN)) return -ESHUTDOWN; @@ -2033,7 +2031,7 @@ static int pch_udc_pcd_set_wedge(struct usb_ep *usbep) return -EINVAL; ep = container_of(usbep, struct pch_udc_ep, ep); dev = ep->dev; - if (!ep->desc && !ep->num) + if (!ep->ep.desc && !ep->num) return -EINVAL; if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN)) return -ESHUTDOWN; @@ -2065,7 +2063,7 @@ static void pch_udc_pcd_fifo_flush(struct usb_ep *usbep) return; ep = container_of(usbep, struct pch_udc_ep, ep); - if (ep->desc || !ep->num) + if (ep->ep.desc || !ep->num) pch_udc_ep_fifo_flush(ep, ep->in); } @@ -3282,7 +3280,6 @@ static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = { MODULE_DEVICE_TABLE(pci, pch_udc_pcidev_id); - static struct pci_driver pch_udc_driver = { .name = KBUILD_MODNAME, .id_table = pch_udc_pcidev_id, @@ -3293,17 +3290,7 @@ static struct pci_driver pch_udc_driver = { .shutdown = pch_udc_shutdown, }; -static int __init pch_udc_pci_init(void) -{ - return pci_register_driver(&pch_udc_driver); -} -module_init(pch_udc_pci_init); - -static void __exit pch_udc_pci_exit(void) -{ - pci_unregister_driver(&pch_udc_driver); -} -module_exit(pch_udc_pci_exit); +module_pci_driver(pch_udc_driver); MODULE_DESCRIPTION("Intel EG20T USB Device Controller"); MODULE_AUTHOR("LAPIS Semiconductor, <tomoya-linux@dsn.lapis-semi.com>"); diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 4e4dc1f5f388..f1f9290a2f47 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -51,6 +51,7 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ +#include "composite.c" #include "usbstring.c" #include "config.c" #include "epautoconf.c" @@ -75,8 +76,6 @@ struct printer_dev { /* lock buffer lists during read/write calls */ struct mutex lock_printer_io; struct usb_gadget *gadget; - struct usb_request *req; /* for control responses */ - u8 config; s8 interface; struct usb_ep *in_ep, *out_ep; @@ -100,6 +99,7 @@ struct printer_dev { struct device *pdev; u8 printer_cdev_open; wait_queue_head_t wait; + struct usb_function function; }; static struct printer_dev usb_printer_gadget; @@ -120,26 +120,6 @@ static struct printer_dev usb_printer_gadget; * parameters are in UTF-8 (superset of ASCII's 7 bit characters). */ -static ushort idVendor; -module_param(idVendor, ushort, S_IRUGO); -MODULE_PARM_DESC(idVendor, "USB Vendor ID"); - -static ushort idProduct; -module_param(idProduct, ushort, S_IRUGO); -MODULE_PARM_DESC(idProduct, "USB Product ID"); - -static ushort bcdDevice; -module_param(bcdDevice, ushort, S_IRUGO); -MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); - -static char *iManufacturer; -module_param(iManufacturer, charp, S_IRUGO); -MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); - -static char *iProduct; -module_param(iProduct, charp, S_IRUGO); -MODULE_PARM_DESC(iProduct, "USB Product string"); - static char *iSerialNum; module_param(iSerialNum, charp, S_IRUGO); MODULE_PARM_DESC(iSerialNum, "1"); @@ -154,47 +134,8 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR); #define QLEN qlen -#ifdef CONFIG_USB_GADGET_DUALSPEED -#define DEVSPEED USB_SPEED_HIGH -#else /* full speed (low speed doesn't do bulk) */ -#define DEVSPEED USB_SPEED_FULL -#endif - /*-------------------------------------------------------------------------*/ -#define xprintk(d, level, fmt, args...) \ - printk(level "%s: " fmt, DRIVER_DESC, ## args) - -#ifdef DEBUG -#define DBG(dev, fmt, args...) \ - xprintk(dev, KERN_DEBUG, fmt, ## args) -#else -#define DBG(dev, fmt, args...) \ - do { } while (0) -#endif /* DEBUG */ - -#ifdef VERBOSE -#define VDBG(dev, fmt, args...) \ - xprintk(dev, KERN_DEBUG, fmt, ## args) -#else -#define VDBG(dev, fmt, args...) \ - do { } while (0) -#endif /* VERBOSE */ - -#define ERROR(dev, fmt, args...) \ - xprintk(dev, KERN_ERR, fmt, ## args) -#define WARNING(dev, fmt, args...) \ - xprintk(dev, KERN_WARNING, fmt, ## args) -#define INFO(dev, fmt, args...) \ - xprintk(dev, KERN_INFO, fmt, ## args) - -/*-------------------------------------------------------------------------*/ - -/* USB DRIVER HOOKUP (to the hardware driver, below us), mostly - * ep0 implementation: descriptors, config management, setup(). - * also optional class-specific notification interrupt transfer. - */ - /* * DESCRIPTORS ... most are static, but strings and (full) configuration * descriptors are built on demand. @@ -227,24 +168,6 @@ static struct usb_device_descriptor device_desc = { .bNumConfigurations = 1 }; -static struct usb_otg_descriptor otg_desc = { - .bLength = sizeof otg_desc, - .bDescriptorType = USB_DT_OTG, - .bmAttributes = USB_OTG_SRP -}; - -static struct usb_config_descriptor config_desc = { - .bLength = sizeof config_desc, - .bDescriptorType = USB_DT_CONFIG, - - /* compute wTotalLength on the fly */ - .bNumInterfaces = 1, - .bConfigurationValue = DEV_CONFIG_VALUE, - .iConfiguration = 0, - .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, -}; - static struct usb_interface_descriptor intf_desc = { .bLength = sizeof intf_desc, .bDescriptorType = USB_DT_INTERFACE, @@ -270,16 +193,13 @@ static struct usb_endpoint_descriptor fs_ep_out_desc = { .bmAttributes = USB_ENDPOINT_XFER_BULK }; -static const struct usb_descriptor_header *fs_printer_function [11] = { - (struct usb_descriptor_header *) &otg_desc, +static struct usb_descriptor_header *fs_printer_function[] = { (struct usb_descriptor_header *) &intf_desc, (struct usb_descriptor_header *) &fs_ep_in_desc, (struct usb_descriptor_header *) &fs_ep_out_desc, NULL }; -#ifdef CONFIG_USB_GADGET_DUALSPEED - /* * usb 2.0 devices need to expose both high speed and full speed * descriptors, unless they only run at full speed. @@ -307,23 +227,26 @@ static struct usb_qualifier_descriptor dev_qualifier = { .bNumConfigurations = 1 }; -static const struct usb_descriptor_header *hs_printer_function [11] = { - (struct usb_descriptor_header *) &otg_desc, +static struct usb_descriptor_header *hs_printer_function[] = { (struct usb_descriptor_header *) &intf_desc, (struct usb_descriptor_header *) &hs_ep_in_desc, (struct usb_descriptor_header *) &hs_ep_out_desc, NULL }; -/* maxpacket and other transfer characteristics vary by speed. */ -#define ep_desc(g, hs, fs) (((g)->speed == USB_SPEED_HIGH)?(hs):(fs)) - -#else +static struct usb_otg_descriptor otg_descriptor = { + .bLength = sizeof otg_descriptor, + .bDescriptorType = USB_DT_OTG, + .bmAttributes = USB_OTG_SRP, +}; -/* if there's no high speed support, maxpacket doesn't change. */ -#define ep_desc(g, hs, fs) (((void)(g)), (fs)) +static const struct usb_descriptor_header *otg_desc[] = { + (struct usb_descriptor_header *) &otg_descriptor, + NULL, +}; -#endif /* !CONFIG_USB_GADGET_DUALSPEED */ +/* maxpacket and other transfer characteristics vary by speed. */ +#define ep_desc(g, hs, fs) (((g)->speed == USB_SPEED_HIGH)?(hs):(fs)) /*-------------------------------------------------------------------------*/ @@ -343,11 +266,16 @@ static struct usb_string strings [] = { { } /* end of list */ }; -static struct usb_gadget_strings stringtab = { +static struct usb_gadget_strings stringtab_dev = { .language = 0x0409, /* en-us */ .strings = strings, }; +static struct usb_gadget_strings *dev_strings[] = { + &stringtab_dev, + NULL, +}; + /*-------------------------------------------------------------------------*/ static struct usb_request * @@ -937,82 +865,8 @@ static void printer_reset_interface(struct printer_dev *dev) dev->interface = -1; } -/* change our operational config. must agree with the code - * that returns config descriptors, and altsetting code. - */ -static int -printer_set_config(struct printer_dev *dev, unsigned number) -{ - int result = 0; - struct usb_gadget *gadget = dev->gadget; - - switch (number) { - case DEV_CONFIG_VALUE: - result = 0; - break; - default: - result = -EINVAL; - /* FALL THROUGH */ - case 0: - break; - } - - if (result) { - usb_gadget_vbus_draw(dev->gadget, - dev->gadget->is_otg ? 8 : 100); - } else { - unsigned power; - - power = 2 * config_desc.bMaxPower; - usb_gadget_vbus_draw(dev->gadget, power); - - dev->config = number; - INFO(dev, "%s config #%d: %d mA, %s\n", - usb_speed_string(gadget->speed), - number, power, driver_desc); - } - return result; -} - -static int -config_buf(enum usb_device_speed speed, u8 *buf, u8 type, unsigned index, - int is_otg) -{ - int len; - const struct usb_descriptor_header **function; -#ifdef CONFIG_USB_GADGET_DUALSPEED - int hs = (speed == USB_SPEED_HIGH); - - if (type == USB_DT_OTHER_SPEED_CONFIG) - hs = !hs; - - if (hs) { - function = hs_printer_function; - } else { - function = fs_printer_function; - } -#else - function = fs_printer_function; -#endif - - if (index >= device_desc.bNumConfigurations) - return -EINVAL; - - /* for now, don't advertise srp-only devices */ - if (!is_otg) - function++; - - len = usb_gadget_config_buf(&config_desc, buf, USB_DESC_BUFSIZE, - function); - if (len < 0) - return len; - ((struct usb_config_descriptor *) buf)->bDescriptorType = type; - return len; -} - /* Change our operational Interface. */ -static int -set_interface(struct printer_dev *dev, unsigned number) +static int set_interface(struct printer_dev *dev, unsigned number) { int result = 0; @@ -1043,14 +897,6 @@ set_interface(struct printer_dev *dev, unsigned number) return result; } -static void printer_setup_complete(struct usb_ep *ep, struct usb_request *req) -{ - if (req->status || req->actual != req->length) - DBG((struct printer_dev *) ep->driver_data, - "setup complete --> %d, %d/%d\n", - req->status, req->actual, req->length); -} - static void printer_soft_reset(struct printer_dev *dev) { struct usb_request *req; @@ -1107,11 +953,12 @@ static void printer_soft_reset(struct printer_dev *dev) * The setup() callback implements all the ep0 functionality that's not * handled lower down. */ -static int -printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) +static int printer_func_setup(struct usb_function *f, + const struct usb_ctrlrequest *ctrl) { - struct printer_dev *dev = get_gadget_data(gadget); - struct usb_request *req = dev->req; + struct printer_dev *dev = container_of(f, struct printer_dev, function); + struct usb_composite_dev *cdev = f->config->cdev; + struct usb_request *req = cdev->req; int value = -EOPNOTSUPP; u16 wIndex = le16_to_cpu(ctrl->wIndex); u16 wValue = le16_to_cpu(ctrl->wValue); @@ -1120,102 +967,7 @@ printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) DBG(dev, "ctrl req%02x.%02x v%04x i%04x l%d\n", ctrl->bRequestType, ctrl->bRequest, wValue, wIndex, wLength); - req->complete = printer_setup_complete; - switch (ctrl->bRequestType&USB_TYPE_MASK) { - - case USB_TYPE_STANDARD: - switch (ctrl->bRequest) { - - case USB_REQ_GET_DESCRIPTOR: - if (ctrl->bRequestType != USB_DIR_IN) - break; - switch (wValue >> 8) { - - case USB_DT_DEVICE: - device_desc.bMaxPacketSize0 = - gadget->ep0->maxpacket; - value = min(wLength, (u16) sizeof device_desc); - memcpy(req->buf, &device_desc, value); - break; -#ifdef CONFIG_USB_GADGET_DUALSPEED - case USB_DT_DEVICE_QUALIFIER: - if (!gadget_is_dualspeed(gadget)) - break; - /* - * assumes ep0 uses the same value for both - * speeds - */ - dev_qualifier.bMaxPacketSize0 = - gadget->ep0->maxpacket; - value = min(wLength, - (u16) sizeof dev_qualifier); - memcpy(req->buf, &dev_qualifier, value); - break; - - case USB_DT_OTHER_SPEED_CONFIG: - if (!gadget_is_dualspeed(gadget)) - break; - /* FALLTHROUGH */ -#endif /* CONFIG_USB_GADGET_DUALSPEED */ - case USB_DT_CONFIG: - value = config_buf(gadget->speed, req->buf, - wValue >> 8, - wValue & 0xff, - gadget->is_otg); - if (value >= 0) - value = min(wLength, (u16) value); - break; - - case USB_DT_STRING: - value = usb_gadget_get_string(&stringtab, - wValue & 0xff, req->buf); - if (value >= 0) - value = min(wLength, (u16) value); - break; - } - break; - - case USB_REQ_SET_CONFIGURATION: - if (ctrl->bRequestType != 0) - break; - if (gadget->a_hnp_support) - DBG(dev, "HNP available\n"); - else if (gadget->a_alt_hnp_support) - DBG(dev, "HNP needs a different root port\n"); - value = printer_set_config(dev, wValue); - if (!value) - value = set_interface(dev, PRINTER_INTERFACE); - break; - case USB_REQ_GET_CONFIGURATION: - if (ctrl->bRequestType != USB_DIR_IN) - break; - *(u8 *)req->buf = dev->config; - value = min(wLength, (u16) 1); - break; - - case USB_REQ_SET_INTERFACE: - if (ctrl->bRequestType != USB_RECIP_INTERFACE || - !dev->config) - break; - - value = set_interface(dev, PRINTER_INTERFACE); - break; - case USB_REQ_GET_INTERFACE: - if (ctrl->bRequestType != - (USB_DIR_IN|USB_RECIP_INTERFACE) - || !dev->config) - break; - - *(u8 *)req->buf = dev->interface; - value = min(wLength, (u16) 1); - break; - - default: - goto unknown; - } - break; - case USB_TYPE_CLASS: switch (ctrl->bRequest) { case 0: /* Get the IEEE-1284 PNP String */ @@ -1261,44 +1013,50 @@ unknown: wValue, wIndex, wLength); break; } - - /* respond with data transfer before status phase? */ - if (value >= 0) { - req->length = value; - req->zero = value < wLength; - value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); - if (value < 0) { - DBG(dev, "ep_queue --> %d\n", value); - req->status = 0; - printer_setup_complete(gadget->ep0, req); - } - } - /* host either stalls (value < 0) or reports success */ return value; } -static void -printer_disconnect(struct usb_gadget *gadget) +static int __init printer_func_bind(struct usb_configuration *c, + struct usb_function *f) { - struct printer_dev *dev = get_gadget_data(gadget); + return 0; +} + +static void printer_func_unbind(struct usb_configuration *c, + struct usb_function *f) +{ +} + +static int printer_func_set_alt(struct usb_function *f, + unsigned intf, unsigned alt) +{ + struct printer_dev *dev = container_of(f, struct printer_dev, function); + int ret = -ENOTSUPP; + + if (!alt) + ret = set_interface(dev, PRINTER_INTERFACE); + return ret; +} + +static void printer_func_disable(struct usb_function *f) +{ + struct printer_dev *dev = container_of(f, struct printer_dev, function); unsigned long flags; DBG(dev, "%s\n", __func__); spin_lock_irqsave(&dev->lock, flags); - printer_reset_interface(dev); - spin_unlock_irqrestore(&dev->lock, flags); } -static void -printer_unbind(struct usb_gadget *gadget) +static void printer_cfg_unbind(struct usb_configuration *c) { - struct printer_dev *dev = get_gadget_data(gadget); + struct printer_dev *dev; struct usb_request *req; + dev = &usb_printer_gadget; DBG(dev, "%s\n", __func__); @@ -1336,18 +1094,18 @@ printer_unbind(struct usb_gadget *gadget) list_del(&req->list); printer_req_free(dev->out_ep, req); } - - if (dev->req) { - printer_req_free(gadget->ep0, dev->req); - dev->req = NULL; - } - - set_gadget_data(gadget, NULL); } -static int __init -printer_bind(struct usb_gadget *gadget) +static struct usb_configuration printer_cfg_driver = { + .label = "printer", + .unbind = printer_cfg_unbind, + .bConfigurationValue = 1, + .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, +}; + +static int __init printer_bind_config(struct usb_configuration *c) { + struct usb_gadget *gadget = c->cdev->gadget; struct printer_dev *dev; struct usb_ep *in_ep, *out_ep; int status = -ENOMEM; @@ -1358,6 +1116,14 @@ printer_bind(struct usb_gadget *gadget) dev = &usb_printer_gadget; + dev->function.name = shortname; + dev->function.descriptors = fs_printer_function; + dev->function.hs_descriptors = hs_printer_function; + dev->function.bind = printer_func_bind; + dev->function.setup = printer_func_setup; + dev->function.unbind = printer_func_unbind; + dev->function.set_alt = printer_func_set_alt; + dev->function.disable = printer_func_disable; /* Setup the sysfs files for the printer gadget. */ dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno, @@ -1393,29 +1159,6 @@ printer_bind(struct usb_gadget *gadget) init_utsname()->sysname, init_utsname()->release, gadget->name); - device_desc.idVendor = - cpu_to_le16(PRINTER_VENDOR_NUM); - device_desc.idProduct = - cpu_to_le16(PRINTER_PRODUCT_NUM); - - /* support optional vendor/distro customization */ - if (idVendor) { - if (!idProduct) { - dev_err(&gadget->dev, "idVendor needs idProduct!\n"); - return -ENODEV; - } - device_desc.idVendor = cpu_to_le16(idVendor); - device_desc.idProduct = cpu_to_le16(idProduct); - if (bcdDevice) - device_desc.bcdDevice = cpu_to_le16(bcdDevice); - } - - if (iManufacturer) - strlcpy(manufacturer, iManufacturer, sizeof manufacturer); - - if (iProduct) - strlcpy(product_desc, iProduct, sizeof product_desc); - if (iSerialNum) strlcpy(serial_num, iSerialNum, sizeof serial_num); @@ -1442,17 +1185,16 @@ autoconf_fail: goto autoconf_fail; out_ep->driver_data = out_ep; /* claim */ -#ifdef CONFIG_USB_GADGET_DUALSPEED /* assumes that all endpoints are dual-speed */ hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress; hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; -#endif /* DUALSPEED */ usb_gadget_set_selfpowered(gadget); if (gadget->is_otg) { - otg_desc.bmAttributes |= USB_OTG_HNP, - config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + otg_descriptor.bmAttributes |= USB_OTG_HNP; + printer_cfg_driver.descriptors = otg_desc; + printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } spin_lock_init(&dev->lock); @@ -1466,7 +1208,6 @@ autoconf_fail: init_waitqueue_head(&dev->tx_wait); init_waitqueue_head(&dev->tx_flush_wait); - dev->config = 0; dev->interface = -1; dev->printer_cdev_open = 0; dev->printer_status = PRINTER_NOT_ERROR; @@ -1477,14 +1218,6 @@ autoconf_fail: dev->in_ep = in_ep; dev->out_ep = out_ep; - /* preallocate control message data and buffer */ - dev->req = printer_req_alloc(gadget->ep0, USB_DESC_BUFSIZE, - GFP_KERNEL); - if (!dev->req) { - status = -ENOMEM; - goto fail; - } - for (i = 0; i < QLEN; i++) { req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL); if (!req) { @@ -1513,45 +1246,37 @@ autoconf_fail: list_add(&req->list, &dev->rx_reqs); } - dev->req->complete = printer_setup_complete; - /* finish hookup to lower layer ... */ dev->gadget = gadget; - set_gadget_data(gadget, dev); - gadget->ep0->driver_data = dev; INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc); INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, out_ep->name, in_ep->name); - return 0; fail: - printer_unbind(gadget); + printer_cfg_unbind(c); return status; } -/*-------------------------------------------------------------------------*/ +static int printer_unbind(struct usb_composite_dev *cdev) +{ + return 0; +} -static struct usb_gadget_driver printer_driver = { - .max_speed = DEVSPEED, +static int __init printer_bind(struct usb_composite_dev *cdev) +{ + return usb_add_config(cdev, &printer_cfg_driver, printer_bind_config); +} - .function = (char *) driver_desc, +static struct usb_composite_driver printer_driver = { + .name = shortname, + .dev = &device_desc, + .strings = dev_strings, + .max_speed = USB_SPEED_HIGH, .unbind = printer_unbind, - - .setup = printer_setup, - .disconnect = printer_disconnect, - - .driver = { - .name = (char *) shortname, - .owner = THIS_MODULE, - }, }; -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR("Craig Nadler"); -MODULE_LICENSE("GPL"); - static int __init init(void) { @@ -1560,23 +1285,23 @@ init(void) usb_gadget_class = class_create(THIS_MODULE, "usb_printer_gadget"); if (IS_ERR(usb_gadget_class)) { status = PTR_ERR(usb_gadget_class); - ERROR(dev, "unable to create usb_gadget class %d\n", status); + pr_err("unable to create usb_gadget class %d\n", status); return status; } status = alloc_chrdev_region(&g_printer_devno, 0, 1, "USB printer gadget"); if (status) { - ERROR(dev, "alloc_chrdev_region %d\n", status); + pr_err("alloc_chrdev_region %d\n", status); class_destroy(usb_gadget_class); return status; } - status = usb_gadget_probe_driver(&printer_driver, printer_bind); + status = usb_composite_probe(&printer_driver, printer_bind); if (status) { class_destroy(usb_gadget_class); unregister_chrdev_region(g_printer_devno, 1); - DBG(dev, "usb_gadget_probe_driver %x\n", status); + pr_err("usb_gadget_probe_driver %x\n", status); } return status; @@ -1586,15 +1311,14 @@ module_init(init); static void __exit cleanup(void) { - int status; - mutex_lock(&usb_printer_gadget.lock_printer_io); - status = usb_gadget_unregister_driver(&printer_driver); - if (status) - ERROR(dev, "usb_gadget_unregister_driver %x\n", status); - + usb_composite_unregister(&printer_driver); unregister_chrdev_region(g_printer_devno, 1); class_destroy(usb_gadget_class); mutex_unlock(&usb_printer_gadget.lock_printer_io); } module_exit(cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Craig Nadler"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 41ed69c96d8c..d7c8cb3bf759 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -218,7 +218,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep, struct pxa25x_udc *dev; ep = container_of (_ep, struct pxa25x_ep, ep); - if (!_ep || !desc || ep->desc || _ep->name == ep0name + if (!_ep || !desc || ep->ep.desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || ep->bEndpointAddress != desc->bEndpointAddress || ep->fifo_size < usb_endpoint_maxp (desc)) { @@ -249,7 +249,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep, return -ESHUTDOWN; } - ep->desc = desc; + ep->ep.desc = desc; ep->stopped = 0; ep->pio_irqs = 0; ep->ep.maxpacket = usb_endpoint_maxp (desc); @@ -269,7 +269,7 @@ static int pxa25x_ep_disable (struct usb_ep *_ep) unsigned long flags; ep = container_of (_ep, struct pxa25x_ep, ep); - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { DMSG("%s, %s not enabled\n", __func__, _ep ? ep->ep.name : NULL); return -EINVAL; @@ -281,7 +281,6 @@ static int pxa25x_ep_disable (struct usb_ep *_ep) /* flush fifo (mostly for IN buffers) */ pxa25x_ep_fifo_flush (_ep); - ep->desc = NULL; ep->ep.desc = NULL; ep->stopped = 1; @@ -390,7 +389,7 @@ write_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) { unsigned max; - max = usb_endpoint_maxp(ep->desc); + max = usb_endpoint_maxp(ep->ep.desc); do { unsigned count; int is_last, is_short; @@ -644,7 +643,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) } ep = container_of(_ep, struct pxa25x_ep, ep); - if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) { + if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) { DMSG("%s, bad ep\n", __func__); return -EINVAL; } @@ -660,7 +659,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) * we can report per-packet status. that also helps with dma. */ if (unlikely (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC - && req->req.length > usb_endpoint_maxp (ep->desc))) + && req->req.length > usb_endpoint_maxp(ep->ep.desc))) return -EMSGSIZE; DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n", @@ -673,7 +672,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) /* kickstart this i/o queue? */ if (list_empty(&ep->queue) && !ep->stopped) { - if (ep->desc == NULL/* ep0 */) { + if (ep->ep.desc == NULL/* ep0 */) { unsigned length = _req->length; switch (dev->ep0state) { @@ -722,7 +721,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) req = NULL; } - if (likely (req && ep->desc)) + if (likely(req && ep->ep.desc)) pio_irq_enable(ep->bEndpointAddress); } @@ -749,7 +748,7 @@ static void nuke(struct pxa25x_ep *ep, int status) queue); done(ep, req, status); } - if (ep->desc) + if (ep->ep.desc) pio_irq_disable (ep->bEndpointAddress); } @@ -792,7 +791,7 @@ static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value) ep = container_of(_ep, struct pxa25x_ep, ep); if (unlikely (!_ep - || (!ep->desc && ep->ep.name != ep0name)) + || (!ep->ep.desc && ep->ep.name != ep0name)) || ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) { DMSG("%s, bad ep\n", __func__); return -EINVAL; @@ -820,7 +819,7 @@ static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value) *ep->reg_udccs = UDCCS_BI_FST|UDCCS_BI_FTF; /* ep0 needs special care */ - if (!ep->desc) { + if (!ep->ep.desc) { start_watchdog(ep->dev); ep->dev->req_pending = 0; ep->dev->ep0state = EP0_STALL; @@ -1087,7 +1086,7 @@ udc_seq_show(struct seq_file *m, void *_d) if (i != 0) { const struct usb_endpoint_descriptor *desc; - desc = ep->desc; + desc = ep->ep.desc; if (!desc) continue; tmp = *dev->ep [i].reg_udccs; @@ -1191,7 +1190,6 @@ static void udc_reinit(struct pxa25x_udc *dev) if (i != 0) list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list); - ep->desc = NULL; ep->ep.desc = NULL; ep->stopped = 0; INIT_LIST_HEAD (&ep->queue); diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h index 893e917f048e..861f4df6ea22 100644 --- a/drivers/usb/gadget/pxa25x_udc.h +++ b/drivers/usb/gadget/pxa25x_udc.h @@ -41,7 +41,6 @@ struct pxa25x_ep { struct usb_ep ep; struct pxa25x_udc *dev; - const struct usb_endpoint_descriptor *desc; struct list_head queue; unsigned long pio_irqs; diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index c4401e7dd3a6..f3ac2a20c27c 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -459,7 +459,7 @@ static int alloc_pipe_config(struct r8a66597_ep *ep, unsigned char *counter; int ret; - ep->desc = desc; + ep->ep.desc = desc; if (ep->pipenum) /* already allocated pipe */ return 0; @@ -648,7 +648,7 @@ static int sudmac_alloc_channel(struct r8a66597 *r8a66597, /* set SUDMAC parameters */ dma = &r8a66597->dma; dma->used = 1; - if (ep->desc->bEndpointAddress & USB_DIR_IN) { + if (ep->ep.desc->bEndpointAddress & USB_DIR_IN) { dma->dir = 1; } else { dma->dir = 0; @@ -770,7 +770,7 @@ static void start_packet_read(struct r8a66597_ep *ep, static void start_packet(struct r8a66597_ep *ep, struct r8a66597_request *req) { - if (ep->desc->bEndpointAddress & USB_DIR_IN) + if (ep->ep.desc->bEndpointAddress & USB_DIR_IN) start_packet_write(ep, req); else start_packet_read(ep, req); @@ -930,7 +930,7 @@ __acquires(r8a66597->lock) if (restart) { req = get_request_from_ep(ep); - if (ep->desc) + if (ep->ep.desc) start_packet(ep, req); } } @@ -1116,7 +1116,7 @@ static void irq_pipe_ready(struct r8a66597 *r8a66597, u16 status, u16 enb) r8a66597_write(r8a66597, ~check, BRDYSTS); ep = r8a66597->pipenum2ep[pipenum]; req = get_request_from_ep(ep); - if (ep->desc->bEndpointAddress & USB_DIR_IN) + if (ep->ep.desc->bEndpointAddress & USB_DIR_IN) irq_packet_write(ep, req); else irq_packet_read(ep, req); @@ -1170,7 +1170,7 @@ __acquires(r8a66597->lock) switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_DEVICE: - status = 1 << USB_DEVICE_SELF_POWERED; + status = r8a66597->device_status; break; case USB_RECIP_INTERFACE: status = 0; @@ -1627,7 +1627,7 @@ static int r8a66597_queue(struct usb_ep *_ep, struct usb_request *_req, req->req.actual = 0; req->req.status = -EINPROGRESS; - if (ep->desc == NULL) /* control */ + if (ep->ep.desc == NULL) /* control */ start_ep0(ep, req); else { if (request && !ep->busy) @@ -1692,7 +1692,7 @@ static int r8a66597_set_wedge(struct usb_ep *_ep) ep = container_of(_ep, struct r8a66597_ep, ep); - if (!ep || !ep->desc) + if (!ep || !ep->ep.desc) return -EINVAL; spin_lock_irqsave(&ep->r8a66597->lock, flags); @@ -1800,11 +1800,24 @@ static int r8a66597_pullup(struct usb_gadget *gadget, int is_on) return 0; } +static int r8a66597_set_selfpowered(struct usb_gadget *gadget, int is_self) +{ + struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget); + + if (is_self) + r8a66597->device_status |= 1 << USB_DEVICE_SELF_POWERED; + else + r8a66597->device_status &= ~(1 << USB_DEVICE_SELF_POWERED); + + return 0; +} + static struct usb_gadget_ops r8a66597_gadget_ops = { .get_frame = r8a66597_get_frame, .udc_start = r8a66597_start, .udc_stop = r8a66597_stop, .pullup = r8a66597_pullup, + .set_selfpowered = r8a66597_set_selfpowered, }; static int __exit r8a66597_remove(struct platform_device *pdev) diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h index 8e3de61cd4b8..99908c76ccd1 100644 --- a/drivers/usb/gadget/r8a66597-udc.h +++ b/drivers/usb/gadget/r8a66597-udc.h @@ -72,7 +72,7 @@ struct r8a66597_ep { unsigned use_dma:1; u16 pipenum; u16 type; - const struct usb_endpoint_descriptor *desc; + /* register address */ unsigned char fifoaddr; unsigned char fifosel; @@ -111,6 +111,7 @@ struct r8a66597 { u16 old_vbus; u16 scount; u16 old_dvsq; + u16 device_status; /* for GET_STATUS */ /* pipe config */ unsigned char bulk; diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 105b206cd844..5061a2fe9620 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -1,4 +1,5 @@ -/* linux/drivers/usb/gadget/s3c-hsotg.c +/** + * linux/drivers/usb/gadget/s3c-hsotg.c * * Copyright (c) 2011 Samsung Electronics Co., Ltd. * http://www.samsung.com @@ -13,7 +14,7 @@ * 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/module.h> @@ -27,21 +28,25 @@ #include <linux/io.h> #include <linux/slab.h> #include <linux/clk.h> +#include <linux/regulator/consumer.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> #include <mach/map.h> -#include <plat/regs-usb-hsotg-phy.h> -#include <plat/regs-usb-hsotg.h> -#include <mach/regs-sys.h> -#include <plat/udc-hs.h> -#include <plat/cpu.h> +#include "s3c-hsotg.h" +#include <linux/platform_data/s3c-hsotg.h> #define DMA_ADDR_INVALID (~((dma_addr_t)0)) -/* EP0_MPS_LIMIT +static const char * const s3c_hsotg_supply_names[] = { + "vusb_d", /* digital USB supply, 1.2V */ + "vusb_a", /* analog USB supply, 1.1V */ +}; + +/* + * EP0_MPS_LIMIT * * Unfortunately there seems to be a limit of the amount of data that can * be transferred by IN transactions on EP0. This is either 127 bytes or 3 @@ -125,8 +130,6 @@ struct s3c_hsotg_ep { char name[10]; }; -#define S3C_HSOTG_EPS (8+1) /* limit to 9 for the moment */ - /** * struct s3c_hsotg - driver state. * @dev: The parent device supplied to the probe function @@ -135,7 +138,9 @@ struct s3c_hsotg_ep { * @regs: The memory area mapped for accessing registers. * @regs_res: The resource that was allocated when claiming register space. * @irq: The IRQ number we are using + * @supplies: Definition of USB power supplies * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos. + * @num_of_eps: Number of available EPs (excluding EP0) * @debug_root: root directrory for debugfs. * @debug_file: main status file for debugfs. * @debug_fifo: FIFO status file for debugfs. @@ -143,6 +148,8 @@ struct s3c_hsotg_ep { * @ep0_buff: Buffer for EP0 reply data, if needed. * @ctrl_buff: Buffer for EP0 control requests. * @ctrl_req: Request for EP0 control packets. + * @setup: NAK management for EP0 SETUP + * @last_rst: Time of last reset * @eps: The endpoints being supplied to the gadget framework */ struct s3c_hsotg { @@ -155,7 +162,10 @@ struct s3c_hsotg { int irq; struct clk *clk; + struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)]; + unsigned int dedicated_fifos:1; + unsigned char num_of_eps; struct dentry *debug_root; struct dentry *debug_file; @@ -167,7 +177,9 @@ struct s3c_hsotg { u8 ctrl_buff[8]; struct usb_gadget gadget; - struct s3c_hsotg_ep eps[]; + unsigned int setup; + unsigned long last_rst; + struct s3c_hsotg_ep *eps; }; /** @@ -244,14 +256,14 @@ static inline bool using_dma(struct s3c_hsotg *hsotg) */ static void s3c_hsotg_en_gsint(struct s3c_hsotg *hsotg, u32 ints) { - u32 gsintmsk = readl(hsotg->regs + S3C_GINTMSK); + u32 gsintmsk = readl(hsotg->regs + GINTMSK); u32 new_gsintmsk; new_gsintmsk = gsintmsk | ints; if (new_gsintmsk != gsintmsk) { dev_dbg(hsotg->dev, "gsintmsk now 0x%08x\n", new_gsintmsk); - writel(new_gsintmsk, hsotg->regs + S3C_GINTMSK); + writel(new_gsintmsk, hsotg->regs + GINTMSK); } } @@ -262,13 +274,13 @@ static void s3c_hsotg_en_gsint(struct s3c_hsotg *hsotg, u32 ints) */ static void s3c_hsotg_disable_gsint(struct s3c_hsotg *hsotg, u32 ints) { - u32 gsintmsk = readl(hsotg->regs + S3C_GINTMSK); + u32 gsintmsk = readl(hsotg->regs + GINTMSK); u32 new_gsintmsk; new_gsintmsk = gsintmsk & ~ints; if (new_gsintmsk != gsintmsk) - writel(new_gsintmsk, hsotg->regs + S3C_GINTMSK); + writel(new_gsintmsk, hsotg->regs + GINTMSK); } /** @@ -293,12 +305,12 @@ static void s3c_hsotg_ctrl_epint(struct s3c_hsotg *hsotg, bit <<= 16; local_irq_save(flags); - daint = readl(hsotg->regs + S3C_DAINTMSK); + daint = readl(hsotg->regs + DAINTMSK); if (en) daint |= bit; else daint &= ~bit; - writel(daint, hsotg->regs + S3C_DAINTMSK); + writel(daint, hsotg->regs + DAINTMSK); local_irq_restore(flags); } @@ -314,52 +326,51 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg) int timeout; u32 val; - /* the ryu 2.6.24 release ahs - writel(0x1C0, hsotg->regs + S3C_GRXFSIZ); - writel(S3C_GNPTXFSIZ_NPTxFStAddr(0x200) | - S3C_GNPTXFSIZ_NPTxFDep(0x1C0), - hsotg->regs + S3C_GNPTXFSIZ); - */ - /* set FIFO sizes to 2048/1024 */ - writel(2048, hsotg->regs + S3C_GRXFSIZ); - writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) | - S3C_GNPTXFSIZ_NPTxFDep(1024), - hsotg->regs + S3C_GNPTXFSIZ); + writel(2048, hsotg->regs + GRXFSIZ); + writel(GNPTXFSIZ_NPTxFStAddr(2048) | + GNPTXFSIZ_NPTxFDep(1024), + hsotg->regs + GNPTXFSIZ); - /* arange all the rest of the TX FIFOs, as some versions of this + /* + * arange all the rest of the TX FIFOs, as some versions of this * block have overlapping default addresses. This also ensures * that if the settings have been changed, then they are set to - * known values. */ + * known values. + */ /* start at the end of the GNPTXFSIZ, rounded up */ addr = 2048 + 1024; size = 768; - /* currently we allocate TX FIFOs for all possible endpoints, - * and assume that they are all the same size. */ + /* + * currently we allocate TX FIFOs for all possible endpoints, + * and assume that they are all the same size. + */ for (ep = 1; ep <= 15; ep++) { val = addr; - val |= size << S3C_DPTXFSIZn_DPTxFSize_SHIFT; + val |= size << DPTXFSIZn_DPTxFSize_SHIFT; addr += size; - writel(val, hsotg->regs + S3C_DPTXFSIZn(ep)); + writel(val, hsotg->regs + DPTXFSIZn(ep)); } - /* according to p428 of the design guide, we need to ensure that - * all fifos are flushed before continuing */ + /* + * according to p428 of the design guide, we need to ensure that + * all fifos are flushed before continuing + */ - writel(S3C_GRSTCTL_TxFNum(0x10) | S3C_GRSTCTL_TxFFlsh | - S3C_GRSTCTL_RxFFlsh, hsotg->regs + S3C_GRSTCTL); + writel(GRSTCTL_TxFNum(0x10) | GRSTCTL_TxFFlsh | + GRSTCTL_RxFFlsh, hsotg->regs + GRSTCTL); /* wait until the fifos are both flushed */ timeout = 100; while (1) { - val = readl(hsotg->regs + S3C_GRSTCTL); + val = readl(hsotg->regs + GRSTCTL); - if ((val & (S3C_GRSTCTL_TxFFlsh | S3C_GRSTCTL_RxFFlsh)) == 0) + if ((val & (GRSTCTL_TxFFlsh | GRSTCTL_RxFFlsh)) == 0) break; if (--timeout == 0) { @@ -415,7 +426,7 @@ static inline int is_ep_periodic(struct s3c_hsotg_ep *hs_ep) * * This is the reverse of s3c_hsotg_map_dma(), called for the completion * of a request to ensure the buffer is ready for access by the caller. -*/ + */ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg, struct s3c_hsotg_ep *hs_ep, struct s3c_hsotg_req *hs_req) @@ -456,13 +467,13 @@ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg, * otherwise -ENOSPC is returned if the FIFO space was used up. * * This routine is only needed for PIO -*/ + */ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, struct s3c_hsotg_ep *hs_ep, struct s3c_hsotg_req *hs_req) { bool periodic = is_ep_periodic(hs_ep); - u32 gnptxsts = readl(hsotg->regs + S3C_GNPTXSTS); + u32 gnptxsts = readl(hsotg->regs + GNPTXSTS); int buf_pos = hs_req->req.actual; int to_write = hs_ep->size_loaded; void *data; @@ -476,20 +487,23 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, return 0; if (periodic && !hsotg->dedicated_fifos) { - u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index)); + u32 epsize = readl(hsotg->regs + DIEPTSIZ(hs_ep->index)); int size_left; int size_done; - /* work out how much data was loaded so we can calculate - * how much data is left in the fifo. */ + /* + * work out how much data was loaded so we can calculate + * how much data is left in the fifo. + */ - size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); + size_left = DxEPTSIZ_XferSize_GET(epsize); - /* if shared fifo, we cannot write anything until the + /* + * if shared fifo, we cannot write anything until the * previous data has been completely sent. */ if (hs_ep->fifo_load != 0) { - s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp); + s3c_hsotg_en_gsint(hsotg, GINTSTS_PTxFEmp); return -ENOSPC; } @@ -510,47 +524,50 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, __func__, can_write); if (can_write <= 0) { - s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp); + s3c_hsotg_en_gsint(hsotg, GINTSTS_PTxFEmp); return -ENOSPC; } } else if (hsotg->dedicated_fifos && hs_ep->index != 0) { - can_write = readl(hsotg->regs + S3C_DTXFSTS(hs_ep->index)); + can_write = readl(hsotg->regs + DTXFSTS(hs_ep->index)); can_write &= 0xffff; can_write *= 4; } else { - if (S3C_GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) { + if (GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) { dev_dbg(hsotg->dev, "%s: no queue slots available (0x%08x)\n", __func__, gnptxsts); - s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_NPTxFEmp); + s3c_hsotg_en_gsint(hsotg, GINTSTS_NPTxFEmp); return -ENOSPC; } - can_write = S3C_GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts); + can_write = GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts); can_write *= 4; /* fifo size is in 32bit quantities. */ } dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n", __func__, gnptxsts, can_write, to_write, hs_ep->ep.maxpacket); - /* limit to 512 bytes of data, it seems at least on the non-periodic + /* + * limit to 512 bytes of data, it seems at least on the non-periodic * FIFO, requests of >512 cause the endpoint to get stuck with a * fragment of the end of the transfer in it. */ if (can_write > 512) can_write = 512; - /* limit the write to one max-packet size worth of data, but allow + /* + * limit the write to one max-packet size worth of data, but allow * the transfer to return that it did not run out of fifo space - * doing it. */ + * doing it. + */ if (to_write > hs_ep->ep.maxpacket) { to_write = hs_ep->ep.maxpacket; s3c_hsotg_en_gsint(hsotg, - periodic ? S3C_GINTSTS_PTxFEmp : - S3C_GINTSTS_NPTxFEmp); + periodic ? GINTSTS_PTxFEmp : + GINTSTS_NPTxFEmp); } /* see if we can write data */ @@ -559,8 +576,8 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, to_write = can_write; pkt_round = to_write % hs_ep->ep.maxpacket; - /* Not sure, but we probably shouldn't be writing partial - * packets into the FIFO, so round the write down to an + /* + * Round the write down to an * exact number of packets. * * Note, we do not currently check to see if we can ever @@ -570,12 +587,14 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, if (pkt_round) to_write -= pkt_round; - /* enable correct FIFO interrupt to alert us when there - * is more room left. */ + /* + * enable correct FIFO interrupt to alert us when there + * is more room left. + */ s3c_hsotg_en_gsint(hsotg, - periodic ? S3C_GINTSTS_PTxFEmp : - S3C_GINTSTS_NPTxFEmp); + periodic ? GINTSTS_PTxFEmp : + GINTSTS_NPTxFEmp); } dev_dbg(hsotg->dev, "write %d/%d, can_write %d, done %d\n", @@ -593,7 +612,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, to_write = DIV_ROUND_UP(to_write, 4); data = hs_req->req.buf + buf_pos; - writesl(hsotg->regs + S3C_EPFIFO(hs_ep->index), data, to_write); + writesl(hsotg->regs + EPFIFO(hs_ep->index), data, to_write); return (to_write >= can_write) ? -ENOSPC : 0; } @@ -612,12 +631,12 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep) unsigned maxpkt; if (index != 0) { - maxsize = S3C_DxEPTSIZ_XferSize_LIMIT + 1; - maxpkt = S3C_DxEPTSIZ_PktCnt_LIMIT + 1; + maxsize = DxEPTSIZ_XferSize_LIMIT + 1; + maxpkt = DxEPTSIZ_PktCnt_LIMIT + 1; } else { maxsize = 64+64; if (hs_ep->dir_in) - maxpkt = S3C_DIEPTSIZ0_PktCnt_LIMIT + 1; + maxpkt = DIEPTSIZ0_PktCnt_LIMIT + 1; else maxpkt = 2; } @@ -626,8 +645,10 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep) maxpkt--; maxsize--; - /* constrain by packet count if maxpkts*pktsize is greater - * than the length register size. */ + /* + * constrain by packet count if maxpkts*pktsize is greater + * than the length register size. + */ if ((maxpkt * hs_ep->ep.maxpacket) < maxsize) maxsize = maxpkt * hs_ep->ep.maxpacket; @@ -674,8 +695,8 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, } } - epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index); - epsize_reg = dir_in ? S3C_DIEPTSIZ(index) : S3C_DOEPTSIZ(index); + epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); + epsize_reg = dir_in ? DIEPTSIZ(index) : DOEPTSIZ(index); dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x, ep %d, dir %s\n", __func__, readl(hsotg->regs + epctrl_reg), index, @@ -684,13 +705,14 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, /* If endpoint is stalled, we will restart request later */ ctrl = readl(hsotg->regs + epctrl_reg); - if (ctrl & S3C_DxEPCTL_Stall) { + if (ctrl & DxEPCTL_Stall) { dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index); return; } length = ureq->length - ureq->actual; - + dev_dbg(hsotg->dev, "ureq->length:%d ureq->actual:%d\n", + ureq->length, ureq->actual); if (0) dev_dbg(hsotg->dev, "REQ buf %p len %d dma 0x%08x noi=%d zp=%d snok=%d\n", @@ -717,20 +739,22 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, packets = 1; /* send one packet if length is zero. */ if (dir_in && index != 0) - epsize = S3C_DxEPTSIZ_MC(1); + epsize = DxEPTSIZ_MC(1); else epsize = 0; if (index != 0 && ureq->zero) { - /* test for the packets being exactly right for the - * transfer */ + /* + * test for the packets being exactly right for the + * transfer + */ if (length == (packets * hs_ep->ep.maxpacket)) packets++; } - epsize |= S3C_DxEPTSIZ_PktCnt(packets); - epsize |= S3C_DxEPTSIZ_XferSize(length); + epsize |= DxEPTSIZ_PktCnt(packets); + epsize |= DxEPTSIZ_XferSize(length); dev_dbg(hsotg->dev, "%s: %d@%d/%d, 0x%08x => 0x%08x\n", __func__, packets, length, ureq->length, epsize, epsize_reg); @@ -744,26 +768,38 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, if (using_dma(hsotg) && !continuing) { unsigned int dma_reg; - /* write DMA address to control register, buffer already - * synced by s3c_hsotg_ep_queue(). */ + /* + * write DMA address to control register, buffer already + * synced by s3c_hsotg_ep_queue(). + */ - dma_reg = dir_in ? S3C_DIEPDMA(index) : S3C_DOEPDMA(index); + dma_reg = dir_in ? DIEPDMA(index) : DOEPDMA(index); writel(ureq->dma, hsotg->regs + dma_reg); dev_dbg(hsotg->dev, "%s: 0x%08x => 0x%08x\n", __func__, ureq->dma, dma_reg); } - ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */ - ctrl |= S3C_DxEPCTL_USBActEp; - ctrl |= S3C_DxEPCTL_CNAK; /* clear NAK set by core */ + ctrl |= DxEPCTL_EPEna; /* ensure ep enabled */ + ctrl |= DxEPCTL_USBActEp; + + dev_dbg(hsotg->dev, "setup req:%d\n", hsotg->setup); + + /* For Setup request do not clear NAK */ + if (hsotg->setup && index == 0) + hsotg->setup = 0; + else + ctrl |= DxEPCTL_CNAK; /* clear NAK set by core */ + dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl); writel(ctrl, hsotg->regs + epctrl_reg); - /* set these, it seems that DMA support increments past the end + /* + * set these, it seems that DMA support increments past the end * of the packet buffer so we need to calculate the length from - * this information. */ + * this information. + */ hs_ep->size_loaded = length; hs_ep->last_load = ureq->actual; @@ -774,17 +810,21 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, s3c_hsotg_write_fifo(hsotg, hs_ep, hs_req); } - /* clear the INTknTXFEmpMsk when we start request, more as a aide - * to debugging to see what is going on. */ + /* + * clear the INTknTXFEmpMsk when we start request, more as a aide + * to debugging to see what is going on. + */ if (dir_in) - writel(S3C_DIEPMSK_INTknTXFEmpMsk, - hsotg->regs + S3C_DIEPINT(index)); + writel(DIEPMSK_INTknTXFEmpMsk, + hsotg->regs + DIEPINT(index)); - /* Note, trying to clear the NAK here causes problems with transmit - * on the S3C6400 ending up with the TXFIFO becoming full. */ + /* + * Note, trying to clear the NAK here causes problems with transmit + * on the S3C6400 ending up with the TXFIFO becoming full. + */ /* check ep is enabled */ - if (!(readl(hsotg->regs + epctrl_reg) & S3C_DxEPCTL_EPEna)) + if (!(readl(hsotg->regs + epctrl_reg) & DxEPCTL_EPEna)) dev_warn(hsotg->dev, "ep%d: failed to become enabled (DxEPCTL=0x%08x)?\n", index, readl(hsotg->regs + epctrl_reg)); @@ -804,7 +844,7 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, * then ensure the buffer has been synced to memory. If our buffer has no * DMA memory, then we map the memory and mark our request to allow us to * cleanup on completion. -*/ + */ static int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg, struct s3c_hsotg_ep *hs_ep, struct usb_request *req) @@ -922,7 +962,7 @@ static void s3c_hsotg_complete_oursetup(struct usb_ep *ep, * * Convert the given wIndex into a pointer to an driver endpoint * structure, or return NULL if it is not a valid endpoint. -*/ + */ static struct s3c_hsotg_ep *ep_from_windex(struct s3c_hsotg *hsotg, u32 windex) { @@ -933,7 +973,7 @@ static struct s3c_hsotg_ep *ep_from_windex(struct s3c_hsotg *hsotg, if (windex >= 0x100) return NULL; - if (idx > S3C_HSOTG_EPS) + if (idx > hsotg->num_of_eps) return NULL; if (idx && ep->dir_in != dir) @@ -1151,24 +1191,28 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, ctrl->bRequest, ctrl->bRequestType, ctrl->wValue, ctrl->wLength); - /* record the direction of the request, for later use when enquing - * packets onto EP0. */ + /* + * record the direction of the request, for later use when enquing + * packets onto EP0. + */ ep0->dir_in = (ctrl->bRequestType & USB_DIR_IN) ? 1 : 0; dev_dbg(hsotg->dev, "ctrl: dir_in=%d\n", ep0->dir_in); - /* if we've no data with this request, then the last part of the - * transaction is going to implicitly be IN. */ + /* + * if we've no data with this request, then the last part of the + * transaction is going to implicitly be IN. + */ if (ctrl->wLength == 0) ep0->dir_in = 1; if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { switch (ctrl->bRequest) { case USB_REQ_SET_ADDRESS: - dcfg = readl(hsotg->regs + S3C_DCFG); - dcfg &= ~S3C_DCFG_DevAddr_MASK; - dcfg |= ctrl->wValue << S3C_DCFG_DevAddr_SHIFT; - writel(dcfg, hsotg->regs + S3C_DCFG); + dcfg = readl(hsotg->regs + DCFG); + dcfg &= ~DCFG_DevAddr_MASK; + dcfg |= ctrl->wValue << DCFG_DevAddr_SHIFT; + writel(dcfg, hsotg->regs + DCFG); dev_info(hsotg->dev, "new address %d\n", ctrl->wValue); @@ -1194,7 +1238,8 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret); } - /* the request is either unhandlable, or is not formatted correctly + /* + * the request is either unhandlable, or is not formatted correctly * so respond with a STALL for the status stage to indicate failure. */ @@ -1203,22 +1248,26 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, u32 ctrl; dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in); - reg = (ep0->dir_in) ? S3C_DIEPCTL0 : S3C_DOEPCTL0; + reg = (ep0->dir_in) ? DIEPCTL0 : DOEPCTL0; - /* S3C_DxEPCTL_Stall will be cleared by EP once it has - * taken effect, so no need to clear later. */ + /* + * DxEPCTL_Stall will be cleared by EP once it has + * taken effect, so no need to clear later. + */ ctrl = readl(hsotg->regs + reg); - ctrl |= S3C_DxEPCTL_Stall; - ctrl |= S3C_DxEPCTL_CNAK; + ctrl |= DxEPCTL_Stall; + ctrl |= DxEPCTL_CNAK; writel(ctrl, hsotg->regs + reg); dev_dbg(hsotg->dev, "written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n", ctrl, reg, readl(hsotg->regs + reg)); - /* don't believe we need to anything more to get the EP - * to reply with a STALL packet */ + /* + * don't believe we need to anything more to get the EP + * to reply with a STALL packet + */ } } @@ -1279,8 +1328,10 @@ static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg) ret = s3c_hsotg_ep_queue(&hsotg->eps[0].ep, req, GFP_ATOMIC); if (ret < 0) { dev_err(hsotg->dev, "%s: failed queue (%d)\n", __func__, ret); - /* Don't think there's much we can do other than watch the - * driver fail. */ + /* + * Don't think there's much we can do other than watch the + * driver fail. + */ } } @@ -1296,7 +1347,7 @@ static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg) * on the endpoint. * * Note, expects the ep to already be locked as appropriate. -*/ + */ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, struct s3c_hsotg_ep *hs_ep, struct s3c_hsotg_req *hs_req, @@ -1312,8 +1363,10 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, dev_dbg(hsotg->dev, "complete: ep %p %s, req %p, %d => %p\n", hs_ep, hs_ep->ep.name, hs_req, result, hs_req->req.complete); - /* only replace the status if we've not already set an error - * from a previous transaction */ + /* + * only replace the status if we've not already set an error + * from a previous transaction + */ if (hs_req->req.status == -EINPROGRESS) hs_req->req.status = result; @@ -1324,8 +1377,10 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, if (using_dma(hsotg)) s3c_hsotg_unmap_dma(hsotg, hs_ep, hs_req); - /* call the complete request with the locks off, just in case the - * request tries to queue more work for this endpoint. */ + /* + * call the complete request with the locks off, just in case the + * request tries to queue more work for this endpoint. + */ if (hs_req->req.complete) { spin_unlock(&hs_ep->lock); @@ -1333,9 +1388,11 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, spin_lock(&hs_ep->lock); } - /* Look to see if there is anything else to do. Note, the completion + /* + * Look to see if there is anything else to do. Note, the completion * of the previous request may have caused a new request to be started - * so be careful when doing this. */ + * so be careful when doing this. + */ if (!hs_ep->req && result >= 0) { restart = !list_empty(&hs_ep->queue); @@ -1355,7 +1412,7 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, * * See s3c_hsotg_complete_request(), but called with the endpoint's * lock held. -*/ + */ static void s3c_hsotg_complete_request_lock(struct s3c_hsotg *hsotg, struct s3c_hsotg_ep *hs_ep, struct s3c_hsotg_req *hs_req, @@ -1382,13 +1439,13 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) { struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep_idx]; struct s3c_hsotg_req *hs_req = hs_ep->req; - void __iomem *fifo = hsotg->regs + S3C_EPFIFO(ep_idx); + void __iomem *fifo = hsotg->regs + EPFIFO(ep_idx); int to_read; int max_req; int read_ptr; if (!hs_req) { - u32 epctl = readl(hsotg->regs + S3C_DOEPCTL(ep_idx)); + u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx)); int ptr; dev_warn(hsotg->dev, @@ -1412,7 +1469,8 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) __func__, to_read, max_req, read_ptr, hs_req->req.length); if (to_read > max_req) { - /* more data appeared than we where willing + /* + * more data appeared than we where willing * to deal with in this request. */ @@ -1424,8 +1482,10 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) hs_req->req.actual += to_read; to_read = DIV_ROUND_UP(to_read, 4); - /* note, we might over-write the buffer end by 3 bytes depending on - * alignment of the data. */ + /* + * note, we might over-write the buffer end by 3 bytes depending on + * alignment of the data. + */ readsl(fifo, hs_req->req.buf + read_ptr, to_read); spin_unlock(&hs_ep->lock); @@ -1465,14 +1525,14 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg, dev_dbg(hsotg->dev, "sending zero-length packet\n"); /* issue a zero-sized packet to terminate this */ - writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) | - S3C_DxEPTSIZ_XferSize(0), hsotg->regs + S3C_DIEPTSIZ(0)); + writel(DxEPTSIZ_MC(1) | DxEPTSIZ_PktCnt(1) | + DxEPTSIZ_XferSize(0), hsotg->regs + DIEPTSIZ(0)); - ctrl = readl(hsotg->regs + S3C_DIEPCTL0); - ctrl |= S3C_DxEPCTL_CNAK; /* clear NAK set by core */ - ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */ - ctrl |= S3C_DxEPCTL_USBActEp; - writel(ctrl, hsotg->regs + S3C_DIEPCTL0); + ctrl = readl(hsotg->regs + DIEPCTL0); + ctrl |= DxEPCTL_CNAK; /* clear NAK set by core */ + ctrl |= DxEPCTL_EPEna; /* ensure ep enabled */ + ctrl |= DxEPCTL_USBActEp; + writel(ctrl, hsotg->regs + DIEPCTL0); } /** @@ -1484,15 +1544,15 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg, * The RXFIFO has delivered an OutDone event, which means that the data * transfer for an OUT endpoint has been completed, either by a short * packet or by the finish of a transfer. -*/ + */ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, int epnum, bool was_setup) { - u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum)); + u32 epsize = readl(hsotg->regs + DOEPTSIZ(epnum)); struct s3c_hsotg_ep *hs_ep = &hsotg->eps[epnum]; struct s3c_hsotg_req *hs_req = hs_ep->req; struct usb_request *req = &hs_req->req; - unsigned size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); + unsigned size_left = DxEPTSIZ_XferSize_GET(epsize); int result = 0; if (!hs_req) { @@ -1503,7 +1563,8 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, if (using_dma(hsotg)) { unsigned size_done; - /* Calculate the size of the transfer by checking how much + /* + * Calculate the size of the transfer by checking how much * is left in the endpoint size register and then working it * out from the amount we loaded for the transfer. * @@ -1521,17 +1582,29 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, if (req->actual < req->length && size_left == 0) { s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true); return; + } else if (epnum == 0) { + /* + * After was_setup = 1 => + * set CNAK for non Setup requests + */ + hsotg->setup = was_setup ? 0 : 1; } if (req->actual < req->length && req->short_not_ok) { dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n", __func__, req->actual, req->length); - /* todo - what should we return here? there's no one else - * even bothering to check the status. */ + /* + * todo - what should we return here? there's no one else + * even bothering to check the status. + */ } if (epnum == 0) { + /* + * Condition req->complete != s3c_hsotg_complete_setup says: + * send ZLP when we have an asynchronous request from gadget + */ if (!was_setup && req->complete != s3c_hsotg_complete_setup) s3c_hsotg_send_zlp(hsotg, hs_req); } @@ -1544,14 +1617,14 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, * @hsotg: The device instance * * Return the current frame number -*/ + */ static u32 s3c_hsotg_read_frameno(struct s3c_hsotg *hsotg) { u32 dsts; - dsts = readl(hsotg->regs + S3C_DSTS); - dsts &= S3C_DSTS_SOFFN_MASK; - dsts >>= S3C_DSTS_SOFFN_SHIFT; + dsts = readl(hsotg->regs + DSTS); + dsts &= DSTS_SOFFN_MASK; + dsts >>= DSTS_SOFFN_SHIFT; return dsts; } @@ -1574,29 +1647,29 @@ static u32 s3c_hsotg_read_frameno(struct s3c_hsotg *hsotg) */ static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg) { - u32 grxstsr = readl(hsotg->regs + S3C_GRXSTSP); + u32 grxstsr = readl(hsotg->regs + GRXSTSP); u32 epnum, status, size; WARN_ON(using_dma(hsotg)); - epnum = grxstsr & S3C_GRXSTS_EPNum_MASK; - status = grxstsr & S3C_GRXSTS_PktSts_MASK; + epnum = grxstsr & GRXSTS_EPNum_MASK; + status = grxstsr & GRXSTS_PktSts_MASK; - size = grxstsr & S3C_GRXSTS_ByteCnt_MASK; - size >>= S3C_GRXSTS_ByteCnt_SHIFT; + size = grxstsr & GRXSTS_ByteCnt_MASK; + size >>= GRXSTS_ByteCnt_SHIFT; if (1) dev_dbg(hsotg->dev, "%s: GRXSTSP=0x%08x (%d@%d)\n", __func__, grxstsr, size, epnum); -#define __status(x) ((x) >> S3C_GRXSTS_PktSts_SHIFT) +#define __status(x) ((x) >> GRXSTS_PktSts_SHIFT) - switch (status >> S3C_GRXSTS_PktSts_SHIFT) { - case __status(S3C_GRXSTS_PktSts_GlobalOutNAK): + switch (status >> GRXSTS_PktSts_SHIFT) { + case __status(GRXSTS_PktSts_GlobalOutNAK): dev_dbg(hsotg->dev, "GlobalOutNAK\n"); break; - case __status(S3C_GRXSTS_PktSts_OutDone): + case __status(GRXSTS_PktSts_OutDone): dev_dbg(hsotg->dev, "OutDone (Frame=0x%08x)\n", s3c_hsotg_read_frameno(hsotg)); @@ -1604,24 +1677,24 @@ static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg) s3c_hsotg_handle_outdone(hsotg, epnum, false); break; - case __status(S3C_GRXSTS_PktSts_SetupDone): + case __status(GRXSTS_PktSts_SetupDone): dev_dbg(hsotg->dev, "SetupDone (Frame=0x%08x, DOPEPCTL=0x%08x)\n", s3c_hsotg_read_frameno(hsotg), - readl(hsotg->regs + S3C_DOEPCTL(0))); + readl(hsotg->regs + DOEPCTL(0))); s3c_hsotg_handle_outdone(hsotg, epnum, true); break; - case __status(S3C_GRXSTS_PktSts_OutRX): + case __status(GRXSTS_PktSts_OutRX): s3c_hsotg_rx_data(hsotg, epnum, size); break; - case __status(S3C_GRXSTS_PktSts_SetupRX): + case __status(GRXSTS_PktSts_SetupRX): dev_dbg(hsotg->dev, "SetupRX (Frame=0x%08x, DOPEPCTL=0x%08x)\n", s3c_hsotg_read_frameno(hsotg), - readl(hsotg->regs + S3C_DOEPCTL(0))); + readl(hsotg->regs + DOEPCTL(0))); s3c_hsotg_rx_data(hsotg, epnum, size); break; @@ -1638,18 +1711,18 @@ static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg) /** * s3c_hsotg_ep0_mps - turn max packet size into register setting * @mps: The maximum packet size in bytes. -*/ + */ static u32 s3c_hsotg_ep0_mps(unsigned int mps) { switch (mps) { case 64: - return S3C_D0EPCTL_MPS_64; + return D0EPCTL_MPS_64; case 32: - return S3C_D0EPCTL_MPS_32; + return D0EPCTL_MPS_32; case 16: - return S3C_D0EPCTL_MPS_16; + return D0EPCTL_MPS_16; case 8: - return S3C_D0EPCTL_MPS_8; + return D0EPCTL_MPS_8; } /* bad max packet size, warn and return invalid result */ @@ -1680,7 +1753,7 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg, if (mpsval > 3) goto bad_mps; } else { - if (mps >= S3C_DxEPCTL_MPS_LIMIT+1) + if (mps >= DxEPCTL_MPS_LIMIT+1) goto bad_mps; mpsval = mps; @@ -1688,19 +1761,21 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg, hs_ep->ep.maxpacket = mps; - /* update both the in and out endpoint controldir_ registers, even - * if one of the directions may not be in use. */ + /* + * update both the in and out endpoint controldir_ registers, even + * if one of the directions may not be in use. + */ - reg = readl(regs + S3C_DIEPCTL(ep)); - reg &= ~S3C_DxEPCTL_MPS_MASK; + reg = readl(regs + DIEPCTL(ep)); + reg &= ~DxEPCTL_MPS_MASK; reg |= mpsval; - writel(reg, regs + S3C_DIEPCTL(ep)); + writel(reg, regs + DIEPCTL(ep)); if (ep) { - reg = readl(regs + S3C_DOEPCTL(ep)); - reg &= ~S3C_DxEPCTL_MPS_MASK; + reg = readl(regs + DOEPCTL(ep)); + reg &= ~DxEPCTL_MPS_MASK; reg |= mpsval; - writel(reg, regs + S3C_DOEPCTL(ep)); + writel(reg, regs + DOEPCTL(ep)); } return; @@ -1719,16 +1794,16 @@ static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx) int timeout; int val; - writel(S3C_GRSTCTL_TxFNum(idx) | S3C_GRSTCTL_TxFFlsh, - hsotg->regs + S3C_GRSTCTL); + writel(GRSTCTL_TxFNum(idx) | GRSTCTL_TxFFlsh, + hsotg->regs + GRSTCTL); /* wait until the fifo is flushed */ timeout = 100; while (1) { - val = readl(hsotg->regs + S3C_GRSTCTL); + val = readl(hsotg->regs + GRSTCTL); - if ((val & (S3C_GRSTCTL_TxFFlsh)) == 0) + if ((val & (GRSTCTL_TxFFlsh)) == 0) break; if (--timeout == 0) { @@ -1778,7 +1853,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, struct s3c_hsotg_ep *hs_ep) { struct s3c_hsotg_req *hs_req = hs_ep->req; - u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index)); + u32 epsize = readl(hsotg->regs + DIEPTSIZ(hs_ep->index)); int size_left, size_done; if (!hs_req) { @@ -1786,7 +1861,15 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, return; } - /* Calculate the size of the transfer by checking how much is left + /* Finish ZLP handling for IN EP0 transactions */ + if (hsotg->eps[0].sent_zlp) { + dev_dbg(hsotg->dev, "zlp packet received\n"); + s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0); + return; + } + + /* + * Calculate the size of the transfer by checking how much is left * in the endpoint size register and then working it out from * the amount we loaded for the transfer. * @@ -1795,7 +1878,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, * aligned). */ - size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); + size_left = DxEPTSIZ_XferSize_GET(epsize); size_done = hs_ep->size_loaded - size_left; size_done += hs_ep->last_load; @@ -1805,9 +1888,28 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, __func__, hs_req->req.actual, size_done); hs_req->req.actual = size_done; + dev_dbg(hsotg->dev, "req->length:%d req->actual:%d req->zero:%d\n", + hs_req->req.length, hs_req->req.actual, hs_req->req.zero); + + /* + * Check if dealing with Maximum Packet Size(MPS) IN transfer at EP0 + * When sent data is a multiple MPS size (e.g. 64B ,128B ,192B + * ,256B ... ), after last MPS sized packet send IN ZLP packet to + * inform the host that no more data is available. + * The state of req.zero member is checked to be sure that the value to + * send is smaller than wValue expected from host. + * Check req.length to NOT send another ZLP when the current one is + * under completion (the one for which this completion has been called). + */ + if (hs_req->req.length && hs_ep->index == 0 && hs_req->req.zero && + hs_req->req.length == hs_req->req.actual && + !(hs_req->req.length % hs_ep->ep.maxpacket)) { - /* if we did all of the transfer, and there is more data left - * around, then try restarting the rest of the request */ + dev_dbg(hsotg->dev, "ep0 zlp IN packet sent\n"); + s3c_hsotg_send_zlp(hsotg, hs_req); + + return; + } if (!size_left && hs_req->req.actual < hs_req->req.length) { dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__); @@ -1823,14 +1925,14 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, * @dir_in: Set if this is an IN endpoint * * Process and clear any interrupt pending for an individual endpoint -*/ + */ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, int dir_in) { struct s3c_hsotg_ep *hs_ep = &hsotg->eps[idx]; - u32 epint_reg = dir_in ? S3C_DIEPINT(idx) : S3C_DOEPINT(idx); - u32 epctl_reg = dir_in ? S3C_DIEPCTL(idx) : S3C_DOEPCTL(idx); - u32 epsiz_reg = dir_in ? S3C_DIEPTSIZ(idx) : S3C_DOEPTSIZ(idx); + u32 epint_reg = dir_in ? DIEPINT(idx) : DOEPINT(idx); + u32 epctl_reg = dir_in ? DIEPCTL(idx) : DOEPCTL(idx); + u32 epsiz_reg = dir_in ? DIEPTSIZ(idx) : DOEPTSIZ(idx); u32 ints; ints = readl(hsotg->regs + epint_reg); @@ -1841,28 +1943,32 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, dev_dbg(hsotg->dev, "%s: ep%d(%s) DxEPINT=0x%08x\n", __func__, idx, dir_in ? "in" : "out", ints); - if (ints & S3C_DxEPINT_XferCompl) { + if (ints & DxEPINT_XferCompl) { dev_dbg(hsotg->dev, "%s: XferCompl: DxEPCTL=0x%08x, DxEPTSIZ=%08x\n", __func__, readl(hsotg->regs + epctl_reg), readl(hsotg->regs + epsiz_reg)); - /* we get OutDone from the FIFO, so we only need to look - * at completing IN requests here */ + /* + * we get OutDone from the FIFO, so we only need to look + * at completing IN requests here + */ if (dir_in) { s3c_hsotg_complete_in(hsotg, hs_ep); if (idx == 0 && !hs_ep->req) s3c_hsotg_enqueue_setup(hsotg); } else if (using_dma(hsotg)) { - /* We're using DMA, we need to fire an OutDone here - * as we ignore the RXFIFO. */ + /* + * We're using DMA, we need to fire an OutDone here + * as we ignore the RXFIFO. + */ s3c_hsotg_handle_outdone(hsotg, idx, false); } } - if (ints & S3C_DxEPINT_EPDisbld) { + if (ints & DxEPINT_EPDisbld) { dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__); if (dir_in) { @@ -1870,27 +1976,29 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, s3c_hsotg_txfifo_flush(hsotg, idx); - if ((epctl & S3C_DxEPCTL_Stall) && - (epctl & S3C_DxEPCTL_EPType_Bulk)) { - int dctl = readl(hsotg->regs + S3C_DCTL); + if ((epctl & DxEPCTL_Stall) && + (epctl & DxEPCTL_EPType_Bulk)) { + int dctl = readl(hsotg->regs + DCTL); - dctl |= S3C_DCTL_CGNPInNAK; - writel(dctl, hsotg->regs + S3C_DCTL); + dctl |= DCTL_CGNPInNAK; + writel(dctl, hsotg->regs + DCTL); } } } - if (ints & S3C_DxEPINT_AHBErr) + if (ints & DxEPINT_AHBErr) dev_dbg(hsotg->dev, "%s: AHBErr\n", __func__); - if (ints & S3C_DxEPINT_Setup) { /* Setup or Timeout */ + if (ints & DxEPINT_Setup) { /* Setup or Timeout */ dev_dbg(hsotg->dev, "%s: Setup/Timeout\n", __func__); if (using_dma(hsotg) && idx == 0) { - /* this is the notification we've received a + /* + * this is the notification we've received a * setup packet. In non-DMA mode we'd get this * from the RXFIFO, instead we need to process - * the setup here. */ + * the setup here. + */ if (dir_in) WARN_ON_ONCE(1); @@ -1899,26 +2007,25 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, } } - if (ints & S3C_DxEPINT_Back2BackSetup) + if (ints & DxEPINT_Back2BackSetup) dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__); if (dir_in) { - /* not sure if this is important, but we'll clear it anyway - */ - if (ints & S3C_DIEPMSK_INTknTXFEmpMsk) { + /* not sure if this is important, but we'll clear it anyway */ + if (ints & DIEPMSK_INTknTXFEmpMsk) { dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n", __func__, idx); } /* this probably means something bad is happening */ - if (ints & S3C_DIEPMSK_INTknEPMisMsk) { + if (ints & DIEPMSK_INTknEPMisMsk) { dev_warn(hsotg->dev, "%s: ep%d: INTknEP\n", __func__, idx); } /* FIFO has space or is empty (see GAHBCFG) */ if (hsotg->dedicated_fifos && - ints & S3C_DIEPMSK_TxFIFOEmpty) { + ints & DIEPMSK_TxFIFOEmpty) { dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n", __func__, idx); if (!using_dma(hsotg)) @@ -1933,40 +2040,45 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, * * Handle updating the device settings after the enumeration phase has * been completed. -*/ + */ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg) { - u32 dsts = readl(hsotg->regs + S3C_DSTS); + u32 dsts = readl(hsotg->regs + DSTS); int ep0_mps = 0, ep_mps; - /* This should signal the finish of the enumeration phase + /* + * This should signal the finish of the enumeration phase * of the USB handshaking, so we should now know what rate - * we connected at. */ + * we connected at. + */ dev_dbg(hsotg->dev, "EnumDone (DSTS=0x%08x)\n", dsts); - /* note, since we're limited by the size of transfer on EP0, and + /* + * note, since we're limited by the size of transfer on EP0, and * it seems IN transfers must be a even number of packets we do - * not advertise a 64byte MPS on EP0. */ + * not advertise a 64byte MPS on EP0. + */ /* catch both EnumSpd_FS and EnumSpd_FS48 */ - switch (dsts & S3C_DSTS_EnumSpd_MASK) { - case S3C_DSTS_EnumSpd_FS: - case S3C_DSTS_EnumSpd_FS48: + switch (dsts & DSTS_EnumSpd_MASK) { + case DSTS_EnumSpd_FS: + case DSTS_EnumSpd_FS48: hsotg->gadget.speed = USB_SPEED_FULL; ep0_mps = EP0_MPS_LIMIT; ep_mps = 64; break; - case S3C_DSTS_EnumSpd_HS: + case DSTS_EnumSpd_HS: hsotg->gadget.speed = USB_SPEED_HIGH; ep0_mps = EP0_MPS_LIMIT; ep_mps = 512; break; - case S3C_DSTS_EnumSpd_LS: + case DSTS_EnumSpd_LS: hsotg->gadget.speed = USB_SPEED_LOW; - /* note, we don't actually support LS in this driver at the + /* + * note, we don't actually support LS in this driver at the * moment, and the documentation seems to imply that it isn't * supported by the PHYs on some of the devices. */ @@ -1975,13 +2087,15 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg) dev_info(hsotg->dev, "new device is %s\n", usb_speed_string(hsotg->gadget.speed)); - /* we should now know the maximum packet size for an - * endpoint, so set the endpoints to a default value. */ + /* + * we should now know the maximum packet size for an + * endpoint, so set the endpoints to a default value. + */ if (ep0_mps) { int i; s3c_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps); - for (i = 1; i < S3C_HSOTG_EPS; i++) + for (i = 1; i < hsotg->num_of_eps; i++) s3c_hsotg_set_ep_maxpacket(hsotg, i, ep_mps); } @@ -1990,8 +2104,8 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg) s3c_hsotg_enqueue_setup(hsotg); dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", - readl(hsotg->regs + S3C_DIEPCTL0), - readl(hsotg->regs + S3C_DOEPCTL0)); + readl(hsotg->regs + DIEPCTL0), + readl(hsotg->regs + DOEPCTL0)); } /** @@ -2014,8 +2128,10 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, spin_lock_irqsave(&ep->lock, flags); list_for_each_entry_safe(req, treq, &ep->queue, queue) { - /* currently, we can't do much about an already - * running request on an in endpoint */ + /* + * currently, we can't do much about an already + * running request on an in endpoint + */ if (ep->req == req && ep->dir_in && !force) continue; @@ -2033,18 +2149,18 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, (_hs)->driver->_entry(&(_hs)->gadget); /** - * s3c_hsotg_disconnect_irq - disconnect irq service + * s3c_hsotg_disconnect - disconnect service * @hsotg: The device state. * - * A disconnect IRQ has been received, meaning that the host has - * lost contact with the bus. Remove all current transactions - * and signal the gadget driver that this has happened. -*/ -static void s3c_hsotg_disconnect_irq(struct s3c_hsotg *hsotg) + * The device has been disconnected. Remove all current + * transactions and signal the gadget driver that this + * has happened. + */ +static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg) { unsigned ep; - for (ep = 0; ep < S3C_HSOTG_EPS; ep++) + for (ep = 0; ep < hsotg->num_of_eps; ep++) kill_all_requests(hsotg, &hsotg->eps[ep], -ESHUTDOWN, true); call_gadget(hsotg, disconnect); @@ -2062,7 +2178,7 @@ static void s3c_hsotg_irq_fifoempty(struct s3c_hsotg *hsotg, bool periodic) /* look through for any more data to transmit */ - for (epno = 0; epno < S3C_HSOTG_EPS; epno++) { + for (epno = 0; epno < hsotg->num_of_eps; epno++) { ep = &hsotg->eps[epno]; if (!ep->dir_in) @@ -2078,12 +2194,187 @@ static void s3c_hsotg_irq_fifoempty(struct s3c_hsotg *hsotg, bool periodic) } } -static struct s3c_hsotg *our_hsotg; - /* IRQ flags which will trigger a retry around the IRQ loop */ -#define IRQ_RETRY_MASK (S3C_GINTSTS_NPTxFEmp | \ - S3C_GINTSTS_PTxFEmp | \ - S3C_GINTSTS_RxFLvl) +#define IRQ_RETRY_MASK (GINTSTS_NPTxFEmp | \ + GINTSTS_PTxFEmp | \ + GINTSTS_RxFLvl) + +/** + * s3c_hsotg_corereset - issue softreset to the core + * @hsotg: The device state + * + * Issue a soft reset to the core, and await the core finishing it. + */ +static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg) +{ + int timeout; + u32 grstctl; + + dev_dbg(hsotg->dev, "resetting core\n"); + + /* issue soft reset */ + writel(GRSTCTL_CSftRst, hsotg->regs + GRSTCTL); + + timeout = 1000; + do { + grstctl = readl(hsotg->regs + GRSTCTL); + } while ((grstctl & GRSTCTL_CSftRst) && timeout-- > 0); + + if (grstctl & GRSTCTL_CSftRst) { + dev_err(hsotg->dev, "Failed to get CSftRst asserted\n"); + return -EINVAL; + } + + timeout = 1000; + + while (1) { + u32 grstctl = readl(hsotg->regs + GRSTCTL); + + if (timeout-- < 0) { + dev_info(hsotg->dev, + "%s: reset failed, GRSTCTL=%08x\n", + __func__, grstctl); + return -ETIMEDOUT; + } + + if (!(grstctl & GRSTCTL_AHBIdle)) + continue; + + break; /* reset done */ + } + + dev_dbg(hsotg->dev, "reset successful\n"); + return 0; +} + +/** + * s3c_hsotg_core_init - issue softreset to the core + * @hsotg: The device state + * + * Issue a soft reset to the core, and await the core finishing it. + */ +static void s3c_hsotg_core_init(struct s3c_hsotg *hsotg) +{ + s3c_hsotg_corereset(hsotg); + + /* + * we must now enable ep0 ready for host detection and then + * set configuration. + */ + + /* set the PLL on, remove the HNP/SRP and set the PHY */ + writel(GUSBCFG_PHYIf16 | GUSBCFG_TOutCal(7) | + (0x5 << 10), hsotg->regs + GUSBCFG); + + s3c_hsotg_init_fifo(hsotg); + + __orr32(hsotg->regs + DCTL, DCTL_SftDiscon); + + writel(1 << 18 | DCFG_DevSpd_HS, hsotg->regs + DCFG); + + /* Clear any pending OTG interrupts */ + writel(0xffffffff, hsotg->regs + GOTGINT); + + /* Clear any pending interrupts */ + writel(0xffffffff, hsotg->regs + GINTSTS); + + writel(GINTSTS_ErlySusp | GINTSTS_SessReqInt | + GINTSTS_GOUTNakEff | GINTSTS_GINNakEff | + GINTSTS_ConIDStsChng | GINTSTS_USBRst | + GINTSTS_EnumDone | GINTSTS_OTGInt | + GINTSTS_USBSusp | GINTSTS_WkUpInt, + hsotg->regs + GINTMSK); + + if (using_dma(hsotg)) + writel(GAHBCFG_GlblIntrEn | GAHBCFG_DMAEn | + GAHBCFG_HBstLen_Incr4, + hsotg->regs + GAHBCFG); + else + writel(GAHBCFG_GlblIntrEn, hsotg->regs + GAHBCFG); + + /* + * Enabling INTknTXFEmpMsk here seems to be a big mistake, we end + * up being flooded with interrupts if the host is polling the + * endpoint to try and read data. + */ + + writel(((hsotg->dedicated_fifos) ? DIEPMSK_TxFIFOEmpty : 0) | + DIEPMSK_EPDisbldMsk | DIEPMSK_XferComplMsk | + DIEPMSK_TimeOUTMsk | DIEPMSK_AHBErrMsk | + DIEPMSK_INTknEPMisMsk, + hsotg->regs + DIEPMSK); + + /* + * don't need XferCompl, we get that from RXFIFO in slave mode. In + * DMA mode we may need this. + */ + writel((using_dma(hsotg) ? (DIEPMSK_XferComplMsk | + DIEPMSK_TimeOUTMsk) : 0) | + DOEPMSK_EPDisbldMsk | DOEPMSK_AHBErrMsk | + DOEPMSK_SetupMsk, + hsotg->regs + DOEPMSK); + + writel(0, hsotg->regs + DAINTMSK); + + dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", + readl(hsotg->regs + DIEPCTL0), + readl(hsotg->regs + DOEPCTL0)); + + /* enable in and out endpoint interrupts */ + s3c_hsotg_en_gsint(hsotg, GINTSTS_OEPInt | GINTSTS_IEPInt); + + /* + * Enable the RXFIFO when in slave mode, as this is how we collect + * the data. In DMA mode, we get events from the FIFO but also + * things we cannot process, so do not use it. + */ + if (!using_dma(hsotg)) + s3c_hsotg_en_gsint(hsotg, GINTSTS_RxFLvl); + + /* Enable interrupts for EP0 in and out */ + s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1); + s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1); + + __orr32(hsotg->regs + DCTL, DCTL_PWROnPrgDone); + udelay(10); /* see openiboot */ + __bic32(hsotg->regs + DCTL, DCTL_PWROnPrgDone); + + dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + DCTL)); + + /* + * DxEPCTL_USBActEp says RO in manual, but seems to be set by + * writing to the EPCTL register.. + */ + + /* set to read 1 8byte packet */ + writel(DxEPTSIZ_MC(1) | DxEPTSIZ_PktCnt(1) | + DxEPTSIZ_XferSize(8), hsotg->regs + DOEPTSIZ0); + + writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) | + DxEPCTL_CNAK | DxEPCTL_EPEna | + DxEPCTL_USBActEp, + hsotg->regs + DOEPCTL0); + + /* enable, but don't activate EP0in */ + writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) | + DxEPCTL_USBActEp, hsotg->regs + DIEPCTL0); + + s3c_hsotg_enqueue_setup(hsotg); + + dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", + readl(hsotg->regs + DIEPCTL0), + readl(hsotg->regs + DOEPCTL0)); + + /* clear global NAKs */ + writel(DCTL_CGOUTNak | DCTL_CGNPInNAK, + hsotg->regs + DCTL); + + /* must be at-least 3ms to allow bus to see disconnect */ + mdelay(3); + + /* remove the soft-disconnect and let's go */ + __bic32(hsotg->regs + DCTL, DCTL_SftDiscon); +} /** * s3c_hsotg_irq - handle device interrupt @@ -2098,52 +2389,45 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) u32 gintmsk; irq_retry: - gintsts = readl(hsotg->regs + S3C_GINTSTS); - gintmsk = readl(hsotg->regs + S3C_GINTMSK); + gintsts = readl(hsotg->regs + GINTSTS); + gintmsk = readl(hsotg->regs + GINTMSK); dev_dbg(hsotg->dev, "%s: %08x %08x (%08x) retry %d\n", __func__, gintsts, gintsts & gintmsk, gintmsk, retry_count); gintsts &= gintmsk; - if (gintsts & S3C_GINTSTS_OTGInt) { - u32 otgint = readl(hsotg->regs + S3C_GOTGINT); + if (gintsts & GINTSTS_OTGInt) { + u32 otgint = readl(hsotg->regs + GOTGINT); dev_info(hsotg->dev, "OTGInt: %08x\n", otgint); - writel(otgint, hsotg->regs + S3C_GOTGINT); - } - - if (gintsts & S3C_GINTSTS_DisconnInt) { - dev_dbg(hsotg->dev, "%s: DisconnInt\n", __func__); - writel(S3C_GINTSTS_DisconnInt, hsotg->regs + S3C_GINTSTS); - - s3c_hsotg_disconnect_irq(hsotg); + writel(otgint, hsotg->regs + GOTGINT); } - if (gintsts & S3C_GINTSTS_SessReqInt) { + if (gintsts & GINTSTS_SessReqInt) { dev_dbg(hsotg->dev, "%s: SessReqInt\n", __func__); - writel(S3C_GINTSTS_SessReqInt, hsotg->regs + S3C_GINTSTS); + writel(GINTSTS_SessReqInt, hsotg->regs + GINTSTS); } - if (gintsts & S3C_GINTSTS_EnumDone) { - writel(S3C_GINTSTS_EnumDone, hsotg->regs + S3C_GINTSTS); + if (gintsts & GINTSTS_EnumDone) { + writel(GINTSTS_EnumDone, hsotg->regs + GINTSTS); s3c_hsotg_irq_enumdone(hsotg); } - if (gintsts & S3C_GINTSTS_ConIDStsChng) { + if (gintsts & GINTSTS_ConIDStsChng) { dev_dbg(hsotg->dev, "ConIDStsChg (DSTS=0x%08x, GOTCTL=%08x)\n", - readl(hsotg->regs + S3C_DSTS), - readl(hsotg->regs + S3C_GOTGCTL)); + readl(hsotg->regs + DSTS), + readl(hsotg->regs + GOTGCTL)); - writel(S3C_GINTSTS_ConIDStsChng, hsotg->regs + S3C_GINTSTS); + writel(GINTSTS_ConIDStsChng, hsotg->regs + GINTSTS); } - if (gintsts & (S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt)) { - u32 daint = readl(hsotg->regs + S3C_DAINT); - u32 daint_out = daint >> S3C_DAINT_OutEP_SHIFT; - u32 daint_in = daint & ~(daint_out << S3C_DAINT_OutEP_SHIFT); + if (gintsts & (GINTSTS_OEPInt | GINTSTS_IEPInt)) { + u32 daint = readl(hsotg->regs + DAINT); + u32 daint_out = daint >> DAINT_OutEP_SHIFT; + u32 daint_in = daint & ~(daint_out << DAINT_OutEP_SHIFT); int ep; dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint); @@ -2159,102 +2443,116 @@ irq_retry: } } - if (gintsts & S3C_GINTSTS_USBRst) { + if (gintsts & GINTSTS_USBRst) { + + u32 usb_status = readl(hsotg->regs + GOTGCTL); + dev_info(hsotg->dev, "%s: USBRst\n", __func__); dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n", - readl(hsotg->regs + S3C_GNPTXSTS)); + readl(hsotg->regs + GNPTXSTS)); - writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS); + writel(GINTSTS_USBRst, hsotg->regs + GINTSTS); - kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true); + if (usb_status & GOTGCTL_BSESVLD) { + if (time_after(jiffies, hsotg->last_rst + + msecs_to_jiffies(200))) { - /* it seems after a reset we can end up with a situation - * where the TXFIFO still has data in it... the docs - * suggest resetting all the fifos, so use the init_fifo - * code to relayout and flush the fifos. - */ + kill_all_requests(hsotg, &hsotg->eps[0], + -ECONNRESET, true); - s3c_hsotg_init_fifo(hsotg); - - s3c_hsotg_enqueue_setup(hsotg); + s3c_hsotg_core_init(hsotg); + hsotg->last_rst = jiffies; + } + } } /* check both FIFOs */ - if (gintsts & S3C_GINTSTS_NPTxFEmp) { + if (gintsts & GINTSTS_NPTxFEmp) { dev_dbg(hsotg->dev, "NPTxFEmp\n"); - /* Disable the interrupt to stop it happening again + /* + * Disable the interrupt to stop it happening again * unless one of these endpoint routines decides that - * it needs re-enabling */ + * it needs re-enabling + */ - s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_NPTxFEmp); + s3c_hsotg_disable_gsint(hsotg, GINTSTS_NPTxFEmp); s3c_hsotg_irq_fifoempty(hsotg, false); } - if (gintsts & S3C_GINTSTS_PTxFEmp) { + if (gintsts & GINTSTS_PTxFEmp) { dev_dbg(hsotg->dev, "PTxFEmp\n"); - /* See note in S3C_GINTSTS_NPTxFEmp */ + /* See note in GINTSTS_NPTxFEmp */ - s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_PTxFEmp); + s3c_hsotg_disable_gsint(hsotg, GINTSTS_PTxFEmp); s3c_hsotg_irq_fifoempty(hsotg, true); } - if (gintsts & S3C_GINTSTS_RxFLvl) { - /* note, since GINTSTS_RxFLvl doubles as FIFO-not-empty, + if (gintsts & GINTSTS_RxFLvl) { + /* + * note, since GINTSTS_RxFLvl doubles as FIFO-not-empty, * we need to retry s3c_hsotg_handle_rx if this is still - * set. */ + * set. + */ s3c_hsotg_handle_rx(hsotg); } - if (gintsts & S3C_GINTSTS_ModeMis) { + if (gintsts & GINTSTS_ModeMis) { dev_warn(hsotg->dev, "warning, mode mismatch triggered\n"); - writel(S3C_GINTSTS_ModeMis, hsotg->regs + S3C_GINTSTS); + writel(GINTSTS_ModeMis, hsotg->regs + GINTSTS); } - if (gintsts & S3C_GINTSTS_USBSusp) { - dev_info(hsotg->dev, "S3C_GINTSTS_USBSusp\n"); - writel(S3C_GINTSTS_USBSusp, hsotg->regs + S3C_GINTSTS); + if (gintsts & GINTSTS_USBSusp) { + dev_info(hsotg->dev, "GINTSTS_USBSusp\n"); + writel(GINTSTS_USBSusp, hsotg->regs + GINTSTS); call_gadget(hsotg, suspend); + s3c_hsotg_disconnect(hsotg); } - if (gintsts & S3C_GINTSTS_WkUpInt) { - dev_info(hsotg->dev, "S3C_GINTSTS_WkUpIn\n"); - writel(S3C_GINTSTS_WkUpInt, hsotg->regs + S3C_GINTSTS); + if (gintsts & GINTSTS_WkUpInt) { + dev_info(hsotg->dev, "GINTSTS_WkUpIn\n"); + writel(GINTSTS_WkUpInt, hsotg->regs + GINTSTS); call_gadget(hsotg, resume); } - if (gintsts & S3C_GINTSTS_ErlySusp) { - dev_dbg(hsotg->dev, "S3C_GINTSTS_ErlySusp\n"); - writel(S3C_GINTSTS_ErlySusp, hsotg->regs + S3C_GINTSTS); + if (gintsts & GINTSTS_ErlySusp) { + dev_dbg(hsotg->dev, "GINTSTS_ErlySusp\n"); + writel(GINTSTS_ErlySusp, hsotg->regs + GINTSTS); + + s3c_hsotg_disconnect(hsotg); } - /* these next two seem to crop-up occasionally causing the core + /* + * these next two seem to crop-up occasionally causing the core * to shutdown the USB transfer, so try clearing them and logging - * the occurrence. */ + * the occurrence. + */ - if (gintsts & S3C_GINTSTS_GOUTNakEff) { + if (gintsts & GINTSTS_GOUTNakEff) { dev_info(hsotg->dev, "GOUTNakEff triggered\n"); - writel(S3C_DCTL_CGOUTNak, hsotg->regs + S3C_DCTL); + writel(DCTL_CGOUTNak, hsotg->regs + DCTL); s3c_hsotg_dump(hsotg); } - if (gintsts & S3C_GINTSTS_GINNakEff) { + if (gintsts & GINTSTS_GINNakEff) { dev_info(hsotg->dev, "GINNakEff triggered\n"); - writel(S3C_DCTL_CGNPInNAK, hsotg->regs + S3C_DCTL); + writel(DCTL_CGNPInNAK, hsotg->regs + DCTL); s3c_hsotg_dump(hsotg); } - /* if we've had fifo events, we should try and go around the - * loop again to see if there's any point in returning yet. */ + /* + * if we've had fifo events, we should try and go around the + * loop again to see if there's any point in returning yet. + */ if (gintsts & IRQ_RETRY_MASK && --retry_count > 0) goto irq_retry; @@ -2268,7 +2566,7 @@ irq_retry: * @desc: The USB endpoint descriptor to configure with. * * This is called from the USB gadget code's usb_ep_enable(). -*/ + */ static int s3c_hsotg_ep_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc) { @@ -2300,7 +2598,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, /* note, we handle this here instead of s3c_hsotg_set_ep_maxpacket */ - epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index); + epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); epctrl = readl(hsotg->regs + epctrl_reg); dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n", @@ -2308,20 +2606,23 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, spin_lock_irqsave(&hs_ep->lock, flags); - epctrl &= ~(S3C_DxEPCTL_EPType_MASK | S3C_DxEPCTL_MPS_MASK); - epctrl |= S3C_DxEPCTL_MPS(mps); + epctrl &= ~(DxEPCTL_EPType_MASK | DxEPCTL_MPS_MASK); + epctrl |= DxEPCTL_MPS(mps); - /* mark the endpoint as active, otherwise the core may ignore - * transactions entirely for this endpoint */ - epctrl |= S3C_DxEPCTL_USBActEp; + /* + * mark the endpoint as active, otherwise the core may ignore + * transactions entirely for this endpoint + */ + epctrl |= DxEPCTL_USBActEp; - /* set the NAK status on the endpoint, otherwise we might try and + /* + * set the NAK status on the endpoint, otherwise we might try and * do something with data that we've yet got a request to process * since the RXFIFO will take data for an endpoint even if the * size register hasn't been set. */ - epctrl |= S3C_DxEPCTL_SNAK; + epctrl |= DxEPCTL_SNAK; /* update the endpoint state */ hs_ep->ep.maxpacket = mps; @@ -2336,37 +2637,40 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, goto out; case USB_ENDPOINT_XFER_BULK: - epctrl |= S3C_DxEPCTL_EPType_Bulk; + epctrl |= DxEPCTL_EPType_Bulk; break; case USB_ENDPOINT_XFER_INT: if (dir_in) { - /* Allocate our TxFNum by simply using the index + /* + * Allocate our TxFNum by simply using the index * of the endpoint for the moment. We could do * something better if the host indicates how - * many FIFOs we are expecting to use. */ + * many FIFOs we are expecting to use. + */ hs_ep->periodic = 1; - epctrl |= S3C_DxEPCTL_TxFNum(index); + epctrl |= DxEPCTL_TxFNum(index); } - epctrl |= S3C_DxEPCTL_EPType_Intterupt; + epctrl |= DxEPCTL_EPType_Intterupt; break; case USB_ENDPOINT_XFER_CONTROL: - epctrl |= S3C_DxEPCTL_EPType_Control; + epctrl |= DxEPCTL_EPType_Control; break; } - /* if the hardware has dedicated fifos, we must give each IN EP + /* + * if the hardware has dedicated fifos, we must give each IN EP * a unique tx-fifo even if it is non-periodic. */ if (dir_in && hsotg->dedicated_fifos) - epctrl |= S3C_DxEPCTL_TxFNum(index); + epctrl |= DxEPCTL_TxFNum(index); /* for non control endpoints, set PID to D0 */ if (index) - epctrl |= S3C_DxEPCTL_SetD0PID; + epctrl |= DxEPCTL_SetD0PID; dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n", __func__, epctrl); @@ -2383,6 +2687,10 @@ out: return ret; } +/** + * s3c_hsotg_ep_disable - disable given endpoint + * @ep: The endpoint to disable. + */ static int s3c_hsotg_ep_disable(struct usb_ep *ep) { struct s3c_hsotg_ep *hs_ep = our_ep(ep); @@ -2400,7 +2708,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) return -EINVAL; } - epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index); + epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); /* terminate all requests with shutdown */ kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false); @@ -2408,9 +2716,9 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) spin_lock_irqsave(&hs_ep->lock, flags); ctrl = readl(hsotg->regs + epctrl_reg); - ctrl &= ~S3C_DxEPCTL_EPEna; - ctrl &= ~S3C_DxEPCTL_USBActEp; - ctrl |= S3C_DxEPCTL_SNAK; + ctrl &= ~DxEPCTL_EPEna; + ctrl &= ~DxEPCTL_USBActEp; + ctrl |= DxEPCTL_SNAK; dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl); writel(ctrl, hsotg->regs + epctrl_reg); @@ -2426,7 +2734,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) * on_list - check request is on the given endpoint * @ep: The endpoint to check. * @test: The request to test if it is on the endpoint. -*/ + */ static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test) { struct s3c_hsotg_req *req, *treq; @@ -2439,6 +2747,11 @@ static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test) return false; } +/** + * s3c_hsotg_ep_dequeue - dequeue given endpoint + * @ep: The endpoint to dequeue. + * @req: The request to be removed from a queue. + */ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) { struct s3c_hsotg_req *hs_req = our_req(req); @@ -2461,6 +2774,11 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) return 0; } +/** + * s3c_hsotg_ep_sethalt - set halt on a given endpoint + * @ep: The endpoint to set halt. + * @value: Set or unset the halt. + */ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) { struct s3c_hsotg_ep *hs_ep = our_ep(ep); @@ -2477,34 +2795,34 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) /* write both IN and OUT control registers */ - epreg = S3C_DIEPCTL(index); + epreg = DIEPCTL(index); epctl = readl(hs->regs + epreg); if (value) { - epctl |= S3C_DxEPCTL_Stall + S3C_DxEPCTL_SNAK; - if (epctl & S3C_DxEPCTL_EPEna) - epctl |= S3C_DxEPCTL_EPDis; + epctl |= DxEPCTL_Stall + DxEPCTL_SNAK; + if (epctl & DxEPCTL_EPEna) + epctl |= DxEPCTL_EPDis; } else { - epctl &= ~S3C_DxEPCTL_Stall; - xfertype = epctl & S3C_DxEPCTL_EPType_MASK; - if (xfertype == S3C_DxEPCTL_EPType_Bulk || - xfertype == S3C_DxEPCTL_EPType_Intterupt) - epctl |= S3C_DxEPCTL_SetD0PID; + epctl &= ~DxEPCTL_Stall; + xfertype = epctl & DxEPCTL_EPType_MASK; + if (xfertype == DxEPCTL_EPType_Bulk || + xfertype == DxEPCTL_EPType_Intterupt) + epctl |= DxEPCTL_SetD0PID; } writel(epctl, hs->regs + epreg); - epreg = S3C_DOEPCTL(index); + epreg = DOEPCTL(index); epctl = readl(hs->regs + epreg); if (value) - epctl |= S3C_DxEPCTL_Stall; + epctl |= DxEPCTL_Stall; else { - epctl &= ~S3C_DxEPCTL_Stall; - xfertype = epctl & S3C_DxEPCTL_EPType_MASK; - if (xfertype == S3C_DxEPCTL_EPType_Bulk || - xfertype == S3C_DxEPCTL_EPType_Intterupt) - epctl |= S3C_DxEPCTL_SetD0PID; + epctl &= ~DxEPCTL_Stall; + xfertype = epctl & DxEPCTL_EPType_MASK; + if (xfertype == DxEPCTL_EPType_Bulk || + xfertype == DxEPCTL_EPType_Intterupt) + epctl |= DxEPCTL_SetD0PID; } writel(epctl, hs->regs + epreg); @@ -2526,57 +2844,91 @@ static struct usb_ep_ops s3c_hsotg_ep_ops = { }; /** - * s3c_hsotg_corereset - issue softreset to the core - * @hsotg: The device state + * s3c_hsotg_phy_enable - enable platform phy dev + * @hsotg: The driver state * - * Issue a soft reset to the core, and await the core finishing it. -*/ -static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg) + * A wrapper for platform code responsible for controlling + * low-level USB code + */ +static void s3c_hsotg_phy_enable(struct s3c_hsotg *hsotg) { - int timeout; - u32 grstctl; + struct platform_device *pdev = to_platform_device(hsotg->dev); - dev_dbg(hsotg->dev, "resetting core\n"); + dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev); + if (hsotg->plat->phy_init) + hsotg->plat->phy_init(pdev, hsotg->plat->phy_type); +} - /* issue soft reset */ - writel(S3C_GRSTCTL_CSftRst, hsotg->regs + S3C_GRSTCTL); +/** + * s3c_hsotg_phy_disable - disable platform phy dev + * @hsotg: The driver state + * + * A wrapper for platform code responsible for controlling + * low-level USB code + */ +static void s3c_hsotg_phy_disable(struct s3c_hsotg *hsotg) +{ + struct platform_device *pdev = to_platform_device(hsotg->dev); - timeout = 1000; - do { - grstctl = readl(hsotg->regs + S3C_GRSTCTL); - } while ((grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0); + if (hsotg->plat->phy_exit) + hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type); +} - if (grstctl & S3C_GRSTCTL_CSftRst) { - dev_err(hsotg->dev, "Failed to get CSftRst asserted\n"); - return -EINVAL; - } +/** + * s3c_hsotg_init - initalize the usb core + * @hsotg: The driver state + */ +static void s3c_hsotg_init(struct s3c_hsotg *hsotg) +{ + /* unmask subset of endpoint interrupts */ - timeout = 1000; + writel(DIEPMSK_TimeOUTMsk | DIEPMSK_AHBErrMsk | + DIEPMSK_EPDisbldMsk | DIEPMSK_XferComplMsk, + hsotg->regs + DIEPMSK); - while (1) { - u32 grstctl = readl(hsotg->regs + S3C_GRSTCTL); + writel(DOEPMSK_SetupMsk | DOEPMSK_AHBErrMsk | + DOEPMSK_EPDisbldMsk | DOEPMSK_XferComplMsk, + hsotg->regs + DOEPMSK); - if (timeout-- < 0) { - dev_info(hsotg->dev, - "%s: reset failed, GRSTCTL=%08x\n", - __func__, grstctl); - return -ETIMEDOUT; - } + writel(0, hsotg->regs + DAINTMSK); - if (!(grstctl & S3C_GRSTCTL_AHBIdle)) - continue; + /* Be in disconnected state until gadget is registered */ + __orr32(hsotg->regs + DCTL, DCTL_SftDiscon); - break; /* reset done */ + if (0) { + /* post global nak until we're ready */ + writel(DCTL_SGNPInNAK | DCTL_SGOUTNak, + hsotg->regs + DCTL); } - dev_dbg(hsotg->dev, "reset successful\n"); - return 0; + /* setup fifos */ + + dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", + readl(hsotg->regs + GRXFSIZ), + readl(hsotg->regs + GNPTXFSIZ)); + + s3c_hsotg_init_fifo(hsotg); + + /* set the PLL on, remove the HNP/SRP and set the PHY */ + writel(GUSBCFG_PHYIf16 | GUSBCFG_TOutCal(7) | (0x5 << 10), + hsotg->regs + GUSBCFG); + + writel(using_dma(hsotg) ? GAHBCFG_DMAEn : 0x0, + hsotg->regs + GAHBCFG); } -static int s3c_hsotg_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) +/** + * s3c_hsotg_udc_start - prepare the udc for work + * @gadget: The usb gadget state + * @driver: The usb gadget driver + * + * Perform initialization to prepare udc device and driver + * to work. + */ +static int s3c_hsotg_udc_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct s3c_hsotg *hsotg = our_hsotg; + struct s3c_hsotg *hsotg = to_hsotg(gadget); int ret; if (!hsotg) { @@ -2592,7 +2944,7 @@ static int s3c_hsotg_start(struct usb_gadget_driver *driver, if (driver->max_speed < USB_SPEED_FULL) dev_err(hsotg->dev, "%s: bad speed\n", __func__); - if (!bind || !driver->setup) { + if (!driver->setup) { dev_err(hsotg->dev, "%s: missing entry points\n", __func__); return -EINVAL; } @@ -2605,135 +2957,17 @@ static int s3c_hsotg_start(struct usb_gadget_driver *driver, hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask; hsotg->gadget.speed = USB_SPEED_UNKNOWN; - ret = device_add(&hsotg->gadget.dev); + ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); if (ret) { - dev_err(hsotg->dev, "failed to register gadget device\n"); + dev_err(hsotg->dev, "failed to enable supplies: %d\n", ret); goto err; } - ret = bind(&hsotg->gadget); - if (ret) { - dev_err(hsotg->dev, "failed bind %s\n", driver->driver.name); - - hsotg->gadget.dev.driver = NULL; - hsotg->driver = NULL; - goto err; - } - - /* we must now enable ep0 ready for host detection and then - * set configuration. */ - - s3c_hsotg_corereset(hsotg); - - /* set the PLL on, remove the HNP/SRP and set the PHY */ - writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) | - (0x5 << 10), hsotg->regs + S3C_GUSBCFG); - - /* looks like soft-reset changes state of FIFOs */ - s3c_hsotg_init_fifo(hsotg); - - __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon); - - writel(1 << 18 | S3C_DCFG_DevSpd_HS, hsotg->regs + S3C_DCFG); - - /* Clear any pending OTG interrupts */ - writel(0xffffffff, hsotg->regs + S3C_GOTGINT); - - /* Clear any pending interrupts */ - writel(0xffffffff, hsotg->regs + S3C_GINTSTS); - - writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt | - S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst | - S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt | - S3C_GINTSTS_USBSusp | S3C_GINTSTS_WkUpInt | - S3C_GINTSTS_GOUTNakEff | S3C_GINTSTS_GINNakEff | - S3C_GINTSTS_ErlySusp, - hsotg->regs + S3C_GINTMSK); - - if (using_dma(hsotg)) - writel(S3C_GAHBCFG_GlblIntrEn | S3C_GAHBCFG_DMAEn | - S3C_GAHBCFG_HBstLen_Incr4, - hsotg->regs + S3C_GAHBCFG); - else - writel(S3C_GAHBCFG_GlblIntrEn, hsotg->regs + S3C_GAHBCFG); - - /* Enabling INTknTXFEmpMsk here seems to be a big mistake, we end - * up being flooded with interrupts if the host is polling the - * endpoint to try and read data. */ - - writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | - S3C_DIEPMSK_INTknEPMisMsk | - S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk | - ((hsotg->dedicated_fifos) ? S3C_DIEPMSK_TxFIFOEmpty : 0), - hsotg->regs + S3C_DIEPMSK); - - /* don't need XferCompl, we get that from RXFIFO in slave mode. In - * DMA mode we may need this. */ - writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk | - S3C_DOEPMSK_EPDisbldMsk | - (using_dma(hsotg) ? (S3C_DIEPMSK_XferComplMsk | - S3C_DIEPMSK_TimeOUTMsk) : 0), - hsotg->regs + S3C_DOEPMSK); - - writel(0, hsotg->regs + S3C_DAINTMSK); - - dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", - readl(hsotg->regs + S3C_DIEPCTL0), - readl(hsotg->regs + S3C_DOEPCTL0)); - - /* enable in and out endpoint interrupts */ - s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt); - - /* Enable the RXFIFO when in slave mode, as this is how we collect - * the data. In DMA mode, we get events from the FIFO but also - * things we cannot process, so do not use it. */ - if (!using_dma(hsotg)) - s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_RxFLvl); - - /* Enable interrupts for EP0 in and out */ - s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1); - s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1); - - __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone); - udelay(10); /* see openiboot */ - __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone); - - dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + S3C_DCTL)); - - /* S3C_DxEPCTL_USBActEp says RO in manual, but seems to be set by - writing to the EPCTL register.. */ - - /* set to read 1 8byte packet */ - writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) | - S3C_DxEPTSIZ_XferSize(8), hsotg->regs + DOEPTSIZ0); - - writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) | - S3C_DxEPCTL_CNAK | S3C_DxEPCTL_EPEna | - S3C_DxEPCTL_USBActEp, - hsotg->regs + S3C_DOEPCTL0); - - /* enable, but don't activate EP0in */ - writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) | - S3C_DxEPCTL_USBActEp, hsotg->regs + S3C_DIEPCTL0); - - s3c_hsotg_enqueue_setup(hsotg); - - dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", - readl(hsotg->regs + S3C_DIEPCTL0), - readl(hsotg->regs + S3C_DOEPCTL0)); - - /* clear global NAKs */ - writel(S3C_DCTL_CGOUTNak | S3C_DCTL_CGNPInNAK, - hsotg->regs + S3C_DCTL); - - /* must be at-least 3ms to allow bus to see disconnect */ - msleep(3); - - /* remove the soft-disconnect and let's go */ - __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon); - - /* report to the user, and return */ + s3c_hsotg_phy_enable(hsotg); + s3c_hsotg_core_init(hsotg); + hsotg->last_rst = jiffies; dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name); return 0; @@ -2743,9 +2977,17 @@ err: return ret; } -static int s3c_hsotg_stop(struct usb_gadget_driver *driver) +/** + * s3c_hsotg_udc_stop - stop the udc + * @gadget: The usb gadget state + * @driver: The usb gadget driver + * + * Stop udc hw block and stay tunned for future transmissions + */ +static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct s3c_hsotg *hsotg = our_hsotg; + struct s3c_hsotg *hsotg = to_hsotg(gadget); int ep; if (!hsotg) @@ -2755,16 +2997,15 @@ static int s3c_hsotg_stop(struct usb_gadget_driver *driver) return -EINVAL; /* all endpoints should be shutdown */ - for (ep = 0; ep < S3C_HSOTG_EPS; ep++) + for (ep = 0; ep < hsotg->num_of_eps; ep++) s3c_hsotg_ep_disable(&hsotg->eps[ep].ep); - call_gadget(hsotg, disconnect); + s3c_hsotg_phy_disable(hsotg); + regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); - driver->unbind(&hsotg->gadget); hsotg->driver = NULL; hsotg->gadget.speed = USB_SPEED_UNKNOWN; - - device_del(&hsotg->gadget.dev); + hsotg->gadget.dev.driver = NULL; dev_info(hsotg->dev, "unregistered gadget driver '%s'\n", driver->driver.name); @@ -2772,6 +3013,12 @@ static int s3c_hsotg_stop(struct usb_gadget_driver *driver) return 0; } +/** + * s3c_hsotg_gadget_getframe - read the frame number + * @gadget: The usb gadget state + * + * Read the {micro} frame number + */ static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget) { return s3c_hsotg_read_frameno(to_hsotg(gadget)); @@ -2779,8 +3026,8 @@ static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget) static struct usb_gadget_ops s3c_hsotg_gadget_ops = { .get_frame = s3c_hsotg_gadget_getframe, - .start = s3c_hsotg_start, - .stop = s3c_hsotg_stop, + .udc_start = s3c_hsotg_udc_start, + .udc_stop = s3c_hsotg_udc_stop, }; /** @@ -2827,111 +3074,42 @@ static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg, hs_ep->ep.maxpacket = epnum ? 512 : EP0_MPS_LIMIT; hs_ep->ep.ops = &s3c_hsotg_ep_ops; - /* Read the FIFO size for the Periodic TX FIFO, even if we're + /* + * Read the FIFO size for the Periodic TX FIFO, even if we're * an OUT endpoint, we may as well do this if in future the * code is changed to make each endpoint's direction changeable. */ - ptxfifo = readl(hsotg->regs + S3C_DPTXFSIZn(epnum)); - hs_ep->fifo_size = S3C_DPTXFSIZn_DPTxFSize_GET(ptxfifo) * 4; + ptxfifo = readl(hsotg->regs + DPTXFSIZn(epnum)); + hs_ep->fifo_size = DPTXFSIZn_DPTxFSize_GET(ptxfifo) * 4; - /* if we're using dma, we need to set the next-endpoint pointer + /* + * if we're using dma, we need to set the next-endpoint pointer * to be something valid. */ if (using_dma(hsotg)) { - u32 next = S3C_DxEPCTL_NextEp((epnum + 1) % 15); - writel(next, hsotg->regs + S3C_DIEPCTL(epnum)); - writel(next, hsotg->regs + S3C_DOEPCTL(epnum)); + u32 next = DxEPCTL_NextEp((epnum + 1) % 15); + writel(next, hsotg->regs + DIEPCTL(epnum)); + writel(next, hsotg->regs + DOEPCTL(epnum)); } } /** - * s3c_hsotg_otgreset - reset the OtG phy block - * @hsotg: The host state. + * s3c_hsotg_hw_cfg - read HW configuration registers + * @param: The device state * - * Power up the phy, set the basic configuration and start the PHY. + * Read the USB core HW configuration registers */ -static void s3c_hsotg_otgreset(struct s3c_hsotg *hsotg) -{ - struct clk *xusbxti; - u32 pwr, osc; - - pwr = readl(S3C_PHYPWR); - pwr &= ~0x19; - writel(pwr, S3C_PHYPWR); - mdelay(1); - - osc = hsotg->plat->is_osc ? S3C_PHYCLK_EXT_OSC : 0; - - xusbxti = clk_get(hsotg->dev, "xusbxti"); - if (xusbxti && !IS_ERR(xusbxti)) { - switch (clk_get_rate(xusbxti)) { - case 12*MHZ: - osc |= S3C_PHYCLK_CLKSEL_12M; - break; - case 24*MHZ: - osc |= S3C_PHYCLK_CLKSEL_24M; - break; - default: - case 48*MHZ: - /* default reference clock */ - break; - } - clk_put(xusbxti); - } - - writel(osc | 0x10, S3C_PHYCLK); - - /* issue a full set of resets to the otg and core */ - - writel(S3C_RSTCON_PHY, S3C_RSTCON); - udelay(20); /* at-least 10uS */ - writel(0, S3C_RSTCON); -} - - -static void s3c_hsotg_init(struct s3c_hsotg *hsotg) +static void s3c_hsotg_hw_cfg(struct s3c_hsotg *hsotg) { - u32 cfg4; - - /* unmask subset of endpoint interrupts */ - - writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | - S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk, - hsotg->regs + S3C_DIEPMSK); - - writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk | - S3C_DOEPMSK_EPDisbldMsk | S3C_DOEPMSK_XferComplMsk, - hsotg->regs + S3C_DOEPMSK); - - writel(0, hsotg->regs + S3C_DAINTMSK); - - /* Be in disconnected state until gadget is registered */ - __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon); - - if (0) { - /* post global nak until we're ready */ - writel(S3C_DCTL_SGNPInNAK | S3C_DCTL_SGOUTNak, - hsotg->regs + S3C_DCTL); - } - - /* setup fifos */ - - dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", - readl(hsotg->regs + S3C_GRXFSIZ), - readl(hsotg->regs + S3C_GNPTXFSIZ)); - - s3c_hsotg_init_fifo(hsotg); - - /* set the PLL on, remove the HNP/SRP and set the PHY */ - writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) | (0x5 << 10), - hsotg->regs + S3C_GUSBCFG); + u32 cfg2, cfg4; + /* check hardware configuration */ - writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0, - hsotg->regs + S3C_GAHBCFG); + cfg2 = readl(hsotg->regs + 0x48); + hsotg->num_of_eps = (cfg2 >> 10) & 0xF; - /* check hardware configuration */ + dev_info(hsotg->dev, "EPs:%d\n", hsotg->num_of_eps); cfg4 = readl(hsotg->regs + 0x50); hsotg->dedicated_fifos = (cfg4 >> 25) & 1; @@ -2940,6 +3118,10 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg) hsotg->dedicated_fifos ? "dedicated" : "shared"); } +/** + * s3c_hsotg_dump - dump state of the udc + * @param: The device state + */ static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) { #ifdef DEBUG @@ -2949,46 +3131,45 @@ static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) int idx; dev_info(dev, "DCFG=0x%08x, DCTL=0x%08x, DIEPMSK=%08x\n", - readl(regs + S3C_DCFG), readl(regs + S3C_DCTL), - readl(regs + S3C_DIEPMSK)); + readl(regs + DCFG), readl(regs + DCTL), + readl(regs + DIEPMSK)); dev_info(dev, "GAHBCFG=0x%08x, 0x44=0x%08x\n", - readl(regs + S3C_GAHBCFG), readl(regs + 0x44)); + readl(regs + GAHBCFG), readl(regs + 0x44)); dev_info(dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", - readl(regs + S3C_GRXFSIZ), readl(regs + S3C_GNPTXFSIZ)); + readl(regs + GRXFSIZ), readl(regs + GNPTXFSIZ)); /* show periodic fifo settings */ for (idx = 1; idx <= 15; idx++) { - val = readl(regs + S3C_DPTXFSIZn(idx)); + val = readl(regs + DPTXFSIZn(idx)); dev_info(dev, "DPTx[%d] FSize=%d, StAddr=0x%08x\n", idx, - val >> S3C_DPTXFSIZn_DPTxFSize_SHIFT, - val & S3C_DPTXFSIZn_DPTxFStAddr_MASK); + val >> DPTXFSIZn_DPTxFSize_SHIFT, + val & DPTXFSIZn_DPTxFStAddr_MASK); } for (idx = 0; idx < 15; idx++) { dev_info(dev, "ep%d-in: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n", idx, - readl(regs + S3C_DIEPCTL(idx)), - readl(regs + S3C_DIEPTSIZ(idx)), - readl(regs + S3C_DIEPDMA(idx))); + readl(regs + DIEPCTL(idx)), + readl(regs + DIEPTSIZ(idx)), + readl(regs + DIEPDMA(idx))); - val = readl(regs + S3C_DOEPCTL(idx)); + val = readl(regs + DOEPCTL(idx)); dev_info(dev, "ep%d-out: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n", - idx, readl(regs + S3C_DOEPCTL(idx)), - readl(regs + S3C_DOEPTSIZ(idx)), - readl(regs + S3C_DOEPDMA(idx))); + idx, readl(regs + DOEPCTL(idx)), + readl(regs + DOEPTSIZ(idx)), + readl(regs + DOEPDMA(idx))); } dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n", - readl(regs + S3C_DVBUSDIS), readl(regs + S3C_DVBUSPULSE)); + readl(regs + DVBUSDIS), readl(regs + DVBUSPULSE)); #endif } - /** * state_show - debugfs: show overall driver and device state. * @seq: The seq file to write to. @@ -3005,38 +3186,38 @@ static int state_show(struct seq_file *seq, void *v) int idx; seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n", - readl(regs + S3C_DCFG), - readl(regs + S3C_DCTL), - readl(regs + S3C_DSTS)); + readl(regs + DCFG), + readl(regs + DCTL), + readl(regs + DSTS)); seq_printf(seq, "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n", - readl(regs + S3C_DIEPMSK), readl(regs + S3C_DOEPMSK)); + readl(regs + DIEPMSK), readl(regs + DOEPMSK)); seq_printf(seq, "GINTMSK=0x%08x, GINTSTS=0x%08x\n", - readl(regs + S3C_GINTMSK), - readl(regs + S3C_GINTSTS)); + readl(regs + GINTMSK), + readl(regs + GINTSTS)); seq_printf(seq, "DAINTMSK=0x%08x, DAINT=0x%08x\n", - readl(regs + S3C_DAINTMSK), - readl(regs + S3C_DAINT)); + readl(regs + DAINTMSK), + readl(regs + DAINT)); seq_printf(seq, "GNPTXSTS=0x%08x, GRXSTSR=%08x\n", - readl(regs + S3C_GNPTXSTS), - readl(regs + S3C_GRXSTSR)); + readl(regs + GNPTXSTS), + readl(regs + GRXSTSR)); seq_printf(seq, "\nEndpoint status:\n"); for (idx = 0; idx < 15; idx++) { u32 in, out; - in = readl(regs + S3C_DIEPCTL(idx)); - out = readl(regs + S3C_DOEPCTL(idx)); + in = readl(regs + DIEPCTL(idx)); + out = readl(regs + DOEPCTL(idx)); seq_printf(seq, "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x", idx, in, out); - in = readl(regs + S3C_DIEPTSIZ(idx)); - out = readl(regs + S3C_DOEPTSIZ(idx)); + in = readl(regs + DIEPTSIZ(idx)); + out = readl(regs + DOEPTSIZ(idx)); seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x", in, out); @@ -3067,7 +3248,7 @@ static const struct file_operations state_fops = { * * Show the FIFO information for the overall fifo and all the * periodic transmission FIFOs. -*/ + */ static int fifo_show(struct seq_file *seq, void *v) { struct s3c_hsotg *hsotg = seq->private; @@ -3076,21 +3257,21 @@ static int fifo_show(struct seq_file *seq, void *v) int idx; seq_printf(seq, "Non-periodic FIFOs:\n"); - seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + S3C_GRXFSIZ)); + seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + GRXFSIZ)); - val = readl(regs + S3C_GNPTXFSIZ); + val = readl(regs + GNPTXFSIZ); seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n", - val >> S3C_GNPTXFSIZ_NPTxFDep_SHIFT, - val & S3C_GNPTXFSIZ_NPTxFStAddr_MASK); + val >> GNPTXFSIZ_NPTxFDep_SHIFT, + val & GNPTXFSIZ_NPTxFStAddr_MASK); seq_printf(seq, "\nPeriodic TXFIFOs:\n"); for (idx = 1; idx <= 15; idx++) { - val = readl(regs + S3C_DPTXFSIZn(idx)); + val = readl(regs + DPTXFSIZn(idx)); seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx, - val >> S3C_DPTXFSIZn_DPTxFSize_SHIFT, - val & S3C_DPTXFSIZn_DPTxFStAddr_MASK); + val >> DPTXFSIZn_DPTxFSize_SHIFT, + val & DPTXFSIZn_DPTxFStAddr_MASK); } return 0; @@ -3122,7 +3303,7 @@ static const char *decode_direction(int is_in) * * This debugfs entry shows the state of the given endpoint (one is * registered for each available). -*/ + */ static int ep_show(struct seq_file *seq, void *v) { struct s3c_hsotg_ep *ep = seq->private; @@ -3139,20 +3320,20 @@ static int ep_show(struct seq_file *seq, void *v) /* first show the register state */ seq_printf(seq, "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n", - readl(regs + S3C_DIEPCTL(index)), - readl(regs + S3C_DOEPCTL(index))); + readl(regs + DIEPCTL(index)), + readl(regs + DOEPCTL(index))); seq_printf(seq, "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n", - readl(regs + S3C_DIEPDMA(index)), - readl(regs + S3C_DOEPDMA(index))); + readl(regs + DIEPDMA(index)), + readl(regs + DOEPDMA(index))); seq_printf(seq, "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n", - readl(regs + S3C_DIEPINT(index)), - readl(regs + S3C_DOEPINT(index))); + readl(regs + DIEPINT(index)), + readl(regs + DOEPINT(index))); seq_printf(seq, "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n", - readl(regs + S3C_DIEPTSIZ(index)), - readl(regs + S3C_DOEPTSIZ(index))); + readl(regs + DIEPTSIZ(index)), + readl(regs + DOEPTSIZ(index))); seq_printf(seq, "\n"); seq_printf(seq, "mps %d\n", ep->ep.maxpacket); @@ -3202,7 +3383,7 @@ static const struct file_operations ep_fops = { * about the state of the system. The directory name is created * with the same name as the device itself, in case we end up * with multiple blocks in future systems. -*/ + */ static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg) { struct dentry *root; @@ -3231,7 +3412,7 @@ static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg) /* create one file for each endpoint */ - for (epidx = 0; epidx < S3C_HSOTG_EPS; epidx++) { + for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) { struct s3c_hsotg_ep *ep = &hsotg->eps[epidx]; ep->debugfs = debugfs_create_file(ep->name, 0444, @@ -3248,12 +3429,12 @@ static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg) * @hsotg: The driver state * * Cleanup (remove) the debugfs files for use on module exit. -*/ + */ static void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg) { unsigned epidx; - for (epidx = 0; epidx < S3C_HSOTG_EPS; epidx++) { + for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) { struct s3c_hsotg_ep *ep = &hsotg->eps[epidx]; debugfs_remove(ep->debugfs); } @@ -3264,48 +3445,39 @@ static void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg) } /** - * s3c_hsotg_gate - set the hardware gate for the block - * @pdev: The device we bound to - * @on: On or off. - * - * Set the hardware gate setting into the block. If we end up on - * something other than an S3C64XX, then we might need to change this - * to using a platform data callback, or some other mechanism. + * s3c_hsotg_release - release callback for hsotg device + * @dev: Device to for which release is called */ -static void s3c_hsotg_gate(struct platform_device *pdev, bool on) +static void s3c_hsotg_release(struct device *dev) { - unsigned long flags; - u32 others; - - local_irq_save(flags); - - others = __raw_readl(S3C64XX_OTHERS); - if (on) - others |= S3C64XX_OTHERS_USBMASK; - else - others &= ~S3C64XX_OTHERS_USBMASK; - __raw_writel(others, S3C64XX_OTHERS); + struct s3c_hsotg *hsotg = dev_get_drvdata(dev); - local_irq_restore(flags); + kfree(hsotg); } -static struct s3c_hsotg_plat s3c_hsotg_default_pdata; +/** + * s3c_hsotg_probe - probe function for hsotg driver + * @pdev: The platform information for the driver + */ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) { struct s3c_hsotg_plat *plat = pdev->dev.platform_data; struct device *dev = &pdev->dev; + struct s3c_hsotg_ep *eps; struct s3c_hsotg *hsotg; struct resource *res; int epnum; int ret; + int i; - if (!plat) - plat = &s3c_hsotg_default_pdata; + plat = pdev->dev.platform_data; + if (!plat) { + dev_err(&pdev->dev, "no platform data defined\n"); + return -EINVAL; + } - hsotg = kzalloc(sizeof(struct s3c_hsotg) + - sizeof(struct s3c_hsotg_ep) * S3C_HSOTG_EPS, - GFP_KERNEL); + hsotg = kzalloc(sizeof(struct s3c_hsotg), GFP_KERNEL); if (!hsotg) { dev_err(dev, "cannot get memory\n"); return -ENOMEM; @@ -3371,6 +3543,54 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) hsotg->gadget.dev.parent = dev; hsotg->gadget.dev.dma_mask = dev->dma_mask; + hsotg->gadget.dev.release = s3c_hsotg_release; + + /* reset the system */ + + clk_prepare_enable(hsotg->clk); + + /* regulators */ + + for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++) + hsotg->supplies[i].supply = s3c_hsotg_supply_names[i]; + + ret = regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); + if (ret) { + dev_err(dev, "failed to request supplies: %d\n", ret); + goto err_irq; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); + + if (ret) { + dev_err(hsotg->dev, "failed to enable supplies: %d\n", ret); + goto err_supplies; + } + + /* usb phy enable */ + s3c_hsotg_phy_enable(hsotg); + + s3c_hsotg_corereset(hsotg); + s3c_hsotg_init(hsotg); + s3c_hsotg_hw_cfg(hsotg); + + /* hsotg->num_of_eps holds number of EPs other than ep0 */ + + if (hsotg->num_of_eps == 0) { + dev_err(dev, "wrong number of EPs (zero)\n"); + goto err_supplies; + } + + eps = kcalloc(hsotg->num_of_eps + 1, sizeof(struct s3c_hsotg_ep), + GFP_KERNEL); + if (!eps) { + dev_err(dev, "cannot get memory\n"); + goto err_supplies; + } + + hsotg->eps = eps; /* setup endpoint information */ @@ -3383,39 +3603,47 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) GFP_KERNEL); if (!hsotg->ctrl_req) { dev_err(dev, "failed to allocate ctrl req\n"); - goto err_regs; + goto err_ep_mem; } - /* reset the system */ + /* initialise the endpoints now the core has been initialised */ + for (epnum = 0; epnum < hsotg->num_of_eps; epnum++) + s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum); - clk_enable(hsotg->clk); + /* disable power and clock */ - s3c_hsotg_gate(pdev, true); + ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); + if (ret) { + dev_err(hsotg->dev, "failed to disable supplies: %d\n", ret); + goto err_ep_mem; + } - s3c_hsotg_otgreset(hsotg); - s3c_hsotg_corereset(hsotg); - s3c_hsotg_init(hsotg); + s3c_hsotg_phy_disable(hsotg); - /* initialise the endpoints now the core has been initialised */ - for (epnum = 0; epnum < S3C_HSOTG_EPS; epnum++) - s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum); + ret = device_add(&hsotg->gadget.dev); + if (ret) { + put_device(&hsotg->gadget.dev); + goto err_ep_mem; + } ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget); if (ret) - goto err_add_udc; + goto err_ep_mem; s3c_hsotg_create_debug(hsotg); s3c_hsotg_dump(hsotg); - our_hsotg = hsotg; return 0; -err_add_udc: - s3c_hsotg_gate(pdev, false); - clk_disable(hsotg->clk); - clk_put(hsotg->clk); - +err_ep_mem: + kfree(eps); +err_supplies: + s3c_hsotg_phy_disable(hsotg); + regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); +err_irq: + free_irq(hsotg->irq, hsotg); err_regs: iounmap(hsotg->regs); @@ -3423,12 +3651,17 @@ err_regs_res: release_resource(hsotg->regs_res); kfree(hsotg->regs_res); err_clk: + clk_disable_unprepare(hsotg->clk); clk_put(hsotg->clk); err_mem: kfree(hsotg); return ret; } +/** + * s3c_hsotg_remove - remove function for hsotg driver + * @pdev: The platform information for the driver + */ static int __devexit s3c_hsotg_remove(struct platform_device *pdev) { struct s3c_hsotg *hsotg = platform_get_drvdata(pdev); @@ -3437,7 +3670,10 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev) s3c_hsotg_delete_debug(hsotg); - usb_gadget_unregister_driver(hsotg->driver); + if (hsotg->driver) { + /* should have been done already by driver model core */ + usb_gadget_unregister_driver(hsotg->driver); + } free_irq(hsotg->irq, hsotg); iounmap(hsotg->regs); @@ -3445,12 +3681,13 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev) release_resource(hsotg->regs_res); kfree(hsotg->regs_res); - s3c_hsotg_gate(pdev, false); + s3c_hsotg_phy_disable(hsotg); + regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); - clk_disable(hsotg->clk); + clk_disable_unprepare(hsotg->clk); clk_put(hsotg->clk); - kfree(hsotg); + device_unregister(&hsotg->gadget.dev); return 0; } diff --git a/drivers/usb/gadget/s3c-hsotg.h b/drivers/usb/gadget/s3c-hsotg.h new file mode 100644 index 000000000000..d650b1295831 --- /dev/null +++ b/drivers/usb/gadget/s3c-hsotg.h @@ -0,0 +1,377 @@ +/* drivers/usb/gadget/s3c-hsotg.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * USB2.0 Highspeed/OtG Synopsis DWC2 device block registers + * + * 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. +*/ + +#ifndef __REGS_USB_HSOTG_H +#define __REGS_USB_HSOTG_H __FILE__ + +#define HSOTG_REG(x) (x) + +#define GOTGCTL HSOTG_REG(0x000) +#define GOTGCTL_BSESVLD (1 << 19) +#define GOTGCTL_ASESVLD (1 << 18) +#define GOTGCTL_DBNC_SHORT (1 << 17) +#define GOTGCTL_CONID_B (1 << 16) +#define GOTGCTL_DEVHNPEN (1 << 11) +#define GOTGCTL_HSSETHNPEN (1 << 10) +#define GOTGCTL_HNPREQ (1 << 9) +#define GOTGCTL_HSTNEGSCS (1 << 8) +#define GOTGCTL_SESREQ (1 << 1) +#define GOTGCTL_SESREQSCS (1 << 0) + +#define GOTGINT HSOTG_REG(0x004) +#define GOTGINT_DbnceDone (1 << 19) +#define GOTGINT_ADevTOUTChg (1 << 18) +#define GOTGINT_HstNegDet (1 << 17) +#define GOTGINT_HstnegSucStsChng (1 << 9) +#define GOTGINT_SesReqSucStsChng (1 << 8) +#define GOTGINT_SesEndDet (1 << 2) + +#define GAHBCFG HSOTG_REG(0x008) +#define GAHBCFG_PTxFEmpLvl (1 << 8) +#define GAHBCFG_NPTxFEmpLvl (1 << 7) +#define GAHBCFG_DMAEn (1 << 5) +#define GAHBCFG_HBstLen_MASK (0xf << 1) +#define GAHBCFG_HBstLen_SHIFT (1) +#define GAHBCFG_HBstLen_Single (0x0 << 1) +#define GAHBCFG_HBstLen_Incr (0x1 << 1) +#define GAHBCFG_HBstLen_Incr4 (0x3 << 1) +#define GAHBCFG_HBstLen_Incr8 (0x5 << 1) +#define GAHBCFG_HBstLen_Incr16 (0x7 << 1) +#define GAHBCFG_GlblIntrEn (1 << 0) + +#define GUSBCFG HSOTG_REG(0x00C) +#define GUSBCFG_PHYLPClkSel (1 << 15) +#define GUSBCFG_HNPCap (1 << 9) +#define GUSBCFG_SRPCap (1 << 8) +#define GUSBCFG_PHYIf16 (1 << 3) +#define GUSBCFG_TOutCal_MASK (0x7 << 0) +#define GUSBCFG_TOutCal_SHIFT (0) +#define GUSBCFG_TOutCal_LIMIT (0x7) +#define GUSBCFG_TOutCal(_x) ((_x) << 0) + +#define GRSTCTL HSOTG_REG(0x010) + +#define GRSTCTL_AHBIdle (1 << 31) +#define GRSTCTL_DMAReq (1 << 30) +#define GRSTCTL_TxFNum_MASK (0x1f << 6) +#define GRSTCTL_TxFNum_SHIFT (6) +#define GRSTCTL_TxFNum_LIMIT (0x1f) +#define GRSTCTL_TxFNum(_x) ((_x) << 6) +#define GRSTCTL_TxFFlsh (1 << 5) +#define GRSTCTL_RxFFlsh (1 << 4) +#define GRSTCTL_INTknQFlsh (1 << 3) +#define GRSTCTL_FrmCntrRst (1 << 2) +#define GRSTCTL_HSftRst (1 << 1) +#define GRSTCTL_CSftRst (1 << 0) + +#define GINTSTS HSOTG_REG(0x014) +#define GINTMSK HSOTG_REG(0x018) + +#define GINTSTS_WkUpInt (1 << 31) +#define GINTSTS_SessReqInt (1 << 30) +#define GINTSTS_DisconnInt (1 << 29) +#define GINTSTS_ConIDStsChng (1 << 28) +#define GINTSTS_PTxFEmp (1 << 26) +#define GINTSTS_HChInt (1 << 25) +#define GINTSTS_PrtInt (1 << 24) +#define GINTSTS_FetSusp (1 << 22) +#define GINTSTS_incompIP (1 << 21) +#define GINTSTS_IncomplSOIN (1 << 20) +#define GINTSTS_OEPInt (1 << 19) +#define GINTSTS_IEPInt (1 << 18) +#define GINTSTS_EPMis (1 << 17) +#define GINTSTS_EOPF (1 << 15) +#define GINTSTS_ISOutDrop (1 << 14) +#define GINTSTS_EnumDone (1 << 13) +#define GINTSTS_USBRst (1 << 12) +#define GINTSTS_USBSusp (1 << 11) +#define GINTSTS_ErlySusp (1 << 10) +#define GINTSTS_GOUTNakEff (1 << 7) +#define GINTSTS_GINNakEff (1 << 6) +#define GINTSTS_NPTxFEmp (1 << 5) +#define GINTSTS_RxFLvl (1 << 4) +#define GINTSTS_SOF (1 << 3) +#define GINTSTS_OTGInt (1 << 2) +#define GINTSTS_ModeMis (1 << 1) +#define GINTSTS_CurMod_Host (1 << 0) + +#define GRXSTSR HSOTG_REG(0x01C) +#define GRXSTSP HSOTG_REG(0x020) + +#define GRXSTS_FN_MASK (0x7f << 25) +#define GRXSTS_FN_SHIFT (25) + +#define GRXSTS_PktSts_MASK (0xf << 17) +#define GRXSTS_PktSts_SHIFT (17) +#define GRXSTS_PktSts_GlobalOutNAK (0x1 << 17) +#define GRXSTS_PktSts_OutRX (0x2 << 17) +#define GRXSTS_PktSts_OutDone (0x3 << 17) +#define GRXSTS_PktSts_SetupDone (0x4 << 17) +#define GRXSTS_PktSts_SetupRX (0x6 << 17) + +#define GRXSTS_DPID_MASK (0x3 << 15) +#define GRXSTS_DPID_SHIFT (15) +#define GRXSTS_ByteCnt_MASK (0x7ff << 4) +#define GRXSTS_ByteCnt_SHIFT (4) +#define GRXSTS_EPNum_MASK (0xf << 0) +#define GRXSTS_EPNum_SHIFT (0) + +#define GRXFSIZ HSOTG_REG(0x024) + +#define GNPTXFSIZ HSOTG_REG(0x028) + +#define GNPTXFSIZ_NPTxFDep_MASK (0xffff << 16) +#define GNPTXFSIZ_NPTxFDep_SHIFT (16) +#define GNPTXFSIZ_NPTxFDep_LIMIT (0xffff) +#define GNPTXFSIZ_NPTxFDep(_x) ((_x) << 16) +#define GNPTXFSIZ_NPTxFStAddr_MASK (0xffff << 0) +#define GNPTXFSIZ_NPTxFStAddr_SHIFT (0) +#define GNPTXFSIZ_NPTxFStAddr_LIMIT (0xffff) +#define GNPTXFSIZ_NPTxFStAddr(_x) ((_x) << 0) + +#define GNPTXSTS HSOTG_REG(0x02C) + +#define GNPTXSTS_NPtxQTop_MASK (0x7f << 24) +#define GNPTXSTS_NPtxQTop_SHIFT (24) + +#define GNPTXSTS_NPTxQSpcAvail_MASK (0xff << 16) +#define GNPTXSTS_NPTxQSpcAvail_SHIFT (16) +#define GNPTXSTS_NPTxQSpcAvail_GET(_v) (((_v) >> 16) & 0xff) + +#define GNPTXSTS_NPTxFSpcAvail_MASK (0xffff << 0) +#define GNPTXSTS_NPTxFSpcAvail_SHIFT (0) +#define GNPTXSTS_NPTxFSpcAvail_GET(_v) (((_v) >> 0) & 0xffff) + + +#define HPTXFSIZ HSOTG_REG(0x100) + +#define DPTXFSIZn(_a) HSOTG_REG(0x104 + (((_a) - 1) * 4)) + +#define DPTXFSIZn_DPTxFSize_MASK (0xffff << 16) +#define DPTXFSIZn_DPTxFSize_SHIFT (16) +#define DPTXFSIZn_DPTxFSize_GET(_v) (((_v) >> 16) & 0xffff) +#define DPTXFSIZn_DPTxFSize_LIMIT (0xffff) +#define DPTXFSIZn_DPTxFSize(_x) ((_x) << 16) + +#define DPTXFSIZn_DPTxFStAddr_MASK (0xffff << 0) +#define DPTXFSIZn_DPTxFStAddr_SHIFT (0) + +/* Device mode registers */ +#define DCFG HSOTG_REG(0x800) + +#define DCFG_EPMisCnt_MASK (0x1f << 18) +#define DCFG_EPMisCnt_SHIFT (18) +#define DCFG_EPMisCnt_LIMIT (0x1f) +#define DCFG_EPMisCnt(_x) ((_x) << 18) + +#define DCFG_PerFrInt_MASK (0x3 << 11) +#define DCFG_PerFrInt_SHIFT (11) +#define DCFG_PerFrInt_LIMIT (0x3) +#define DCFG_PerFrInt(_x) ((_x) << 11) + +#define DCFG_DevAddr_MASK (0x7f << 4) +#define DCFG_DevAddr_SHIFT (4) +#define DCFG_DevAddr_LIMIT (0x7f) +#define DCFG_DevAddr(_x) ((_x) << 4) + +#define DCFG_NZStsOUTHShk (1 << 2) + +#define DCFG_DevSpd_MASK (0x3 << 0) +#define DCFG_DevSpd_SHIFT (0) +#define DCFG_DevSpd_HS (0x0 << 0) +#define DCFG_DevSpd_FS (0x1 << 0) +#define DCFG_DevSpd_LS (0x2 << 0) +#define DCFG_DevSpd_FS48 (0x3 << 0) + +#define DCTL HSOTG_REG(0x804) + +#define DCTL_PWROnPrgDone (1 << 11) +#define DCTL_CGOUTNak (1 << 10) +#define DCTL_SGOUTNak (1 << 9) +#define DCTL_CGNPInNAK (1 << 8) +#define DCTL_SGNPInNAK (1 << 7) +#define DCTL_TstCtl_MASK (0x7 << 4) +#define DCTL_TstCtl_SHIFT (4) +#define DCTL_GOUTNakSts (1 << 3) +#define DCTL_GNPINNakSts (1 << 2) +#define DCTL_SftDiscon (1 << 1) +#define DCTL_RmtWkUpSig (1 << 0) + +#define DSTS HSOTG_REG(0x808) + +#define DSTS_SOFFN_MASK (0x3fff << 8) +#define DSTS_SOFFN_SHIFT (8) +#define DSTS_SOFFN_LIMIT (0x3fff) +#define DSTS_SOFFN(_x) ((_x) << 8) +#define DSTS_ErraticErr (1 << 3) +#define DSTS_EnumSpd_MASK (0x3 << 1) +#define DSTS_EnumSpd_SHIFT (1) +#define DSTS_EnumSpd_HS (0x0 << 1) +#define DSTS_EnumSpd_FS (0x1 << 1) +#define DSTS_EnumSpd_LS (0x2 << 1) +#define DSTS_EnumSpd_FS48 (0x3 << 1) + +#define DSTS_SuspSts (1 << 0) + +#define DIEPMSK HSOTG_REG(0x810) + +#define DIEPMSK_TxFIFOEmpty (1 << 7) +#define DIEPMSK_INEPNakEffMsk (1 << 6) +#define DIEPMSK_INTknEPMisMsk (1 << 5) +#define DIEPMSK_INTknTXFEmpMsk (1 << 4) +#define DIEPMSK_TimeOUTMsk (1 << 3) +#define DIEPMSK_AHBErrMsk (1 << 2) +#define DIEPMSK_EPDisbldMsk (1 << 1) +#define DIEPMSK_XferComplMsk (1 << 0) + +#define DOEPMSK HSOTG_REG(0x814) + +#define DOEPMSK_Back2BackSetup (1 << 6) +#define DOEPMSK_OUTTknEPdisMsk (1 << 4) +#define DOEPMSK_SetupMsk (1 << 3) +#define DOEPMSK_AHBErrMsk (1 << 2) +#define DOEPMSK_EPDisbldMsk (1 << 1) +#define DOEPMSK_XferComplMsk (1 << 0) + +#define DAINT HSOTG_REG(0x818) +#define DAINTMSK HSOTG_REG(0x81C) + +#define DAINT_OutEP_SHIFT (16) +#define DAINT_OutEP(x) (1 << ((x) + 16)) +#define DAINT_InEP(x) (1 << (x)) + +#define DTKNQR1 HSOTG_REG(0x820) +#define DTKNQR2 HSOTG_REG(0x824) +#define DTKNQR3 HSOTG_REG(0x830) +#define DTKNQR4 HSOTG_REG(0x834) + +#define DVBUSDIS HSOTG_REG(0x828) +#define DVBUSPULSE HSOTG_REG(0x82C) + +#define DIEPCTL0 HSOTG_REG(0x900) +#define DOEPCTL0 HSOTG_REG(0xB00) +#define DIEPCTL(_a) HSOTG_REG(0x900 + ((_a) * 0x20)) +#define DOEPCTL(_a) HSOTG_REG(0xB00 + ((_a) * 0x20)) + +/* EP0 specialness: + * bits[29..28] - reserved (no SetD0PID, SetD1PID) + * bits[25..22] - should always be zero, this isn't a periodic endpoint + * bits[10..0] - MPS setting differenct for EP0 + */ +#define D0EPCTL_MPS_MASK (0x3 << 0) +#define D0EPCTL_MPS_SHIFT (0) +#define D0EPCTL_MPS_64 (0x0 << 0) +#define D0EPCTL_MPS_32 (0x1 << 0) +#define D0EPCTL_MPS_16 (0x2 << 0) +#define D0EPCTL_MPS_8 (0x3 << 0) + +#define DxEPCTL_EPEna (1 << 31) +#define DxEPCTL_EPDis (1 << 30) +#define DxEPCTL_SetD1PID (1 << 29) +#define DxEPCTL_SetOddFr (1 << 29) +#define DxEPCTL_SetD0PID (1 << 28) +#define DxEPCTL_SetEvenFr (1 << 28) +#define DxEPCTL_SNAK (1 << 27) +#define DxEPCTL_CNAK (1 << 26) +#define DxEPCTL_TxFNum_MASK (0xf << 22) +#define DxEPCTL_TxFNum_SHIFT (22) +#define DxEPCTL_TxFNum_LIMIT (0xf) +#define DxEPCTL_TxFNum(_x) ((_x) << 22) + +#define DxEPCTL_Stall (1 << 21) +#define DxEPCTL_Snp (1 << 20) +#define DxEPCTL_EPType_MASK (0x3 << 18) +#define DxEPCTL_EPType_SHIFT (18) +#define DxEPCTL_EPType_Control (0x0 << 18) +#define DxEPCTL_EPType_Iso (0x1 << 18) +#define DxEPCTL_EPType_Bulk (0x2 << 18) +#define DxEPCTL_EPType_Intterupt (0x3 << 18) + +#define DxEPCTL_NAKsts (1 << 17) +#define DxEPCTL_DPID (1 << 16) +#define DxEPCTL_EOFrNum (1 << 16) +#define DxEPCTL_USBActEp (1 << 15) +#define DxEPCTL_NextEp_MASK (0xf << 11) +#define DxEPCTL_NextEp_SHIFT (11) +#define DxEPCTL_NextEp_LIMIT (0xf) +#define DxEPCTL_NextEp(_x) ((_x) << 11) + +#define DxEPCTL_MPS_MASK (0x7ff << 0) +#define DxEPCTL_MPS_SHIFT (0) +#define DxEPCTL_MPS_LIMIT (0x7ff) +#define DxEPCTL_MPS(_x) ((_x) << 0) + +#define DIEPINT(_a) HSOTG_REG(0x908 + ((_a) * 0x20)) +#define DOEPINT(_a) HSOTG_REG(0xB08 + ((_a) * 0x20)) + +#define DxEPINT_INEPNakEff (1 << 6) +#define DxEPINT_Back2BackSetup (1 << 6) +#define DxEPINT_INTknEPMis (1 << 5) +#define DxEPINT_INTknTXFEmp (1 << 4) +#define DxEPINT_OUTTknEPdis (1 << 4) +#define DxEPINT_Timeout (1 << 3) +#define DxEPINT_Setup (1 << 3) +#define DxEPINT_AHBErr (1 << 2) +#define DxEPINT_EPDisbld (1 << 1) +#define DxEPINT_XferCompl (1 << 0) + +#define DIEPTSIZ0 HSOTG_REG(0x910) + +#define DIEPTSIZ0_PktCnt_MASK (0x3 << 19) +#define DIEPTSIZ0_PktCnt_SHIFT (19) +#define DIEPTSIZ0_PktCnt_LIMIT (0x3) +#define DIEPTSIZ0_PktCnt(_x) ((_x) << 19) + +#define DIEPTSIZ0_XferSize_MASK (0x7f << 0) +#define DIEPTSIZ0_XferSize_SHIFT (0) +#define DIEPTSIZ0_XferSize_LIMIT (0x7f) +#define DIEPTSIZ0_XferSize(_x) ((_x) << 0) + +#define DOEPTSIZ0 HSOTG_REG(0xB10) +#define DOEPTSIZ0_SUPCnt_MASK (0x3 << 29) +#define DOEPTSIZ0_SUPCnt_SHIFT (29) +#define DOEPTSIZ0_SUPCnt_LIMIT (0x3) +#define DOEPTSIZ0_SUPCnt(_x) ((_x) << 29) + +#define DOEPTSIZ0_PktCnt (1 << 19) +#define DOEPTSIZ0_XferSize_MASK (0x7f << 0) +#define DOEPTSIZ0_XferSize_SHIFT (0) + +#define DIEPTSIZ(_a) HSOTG_REG(0x910 + ((_a) * 0x20)) +#define DOEPTSIZ(_a) HSOTG_REG(0xB10 + ((_a) * 0x20)) + +#define DxEPTSIZ_MC_MASK (0x3 << 29) +#define DxEPTSIZ_MC_SHIFT (29) +#define DxEPTSIZ_MC_LIMIT (0x3) +#define DxEPTSIZ_MC(_x) ((_x) << 29) + +#define DxEPTSIZ_PktCnt_MASK (0x3ff << 19) +#define DxEPTSIZ_PktCnt_SHIFT (19) +#define DxEPTSIZ_PktCnt_GET(_v) (((_v) >> 19) & 0x3ff) +#define DxEPTSIZ_PktCnt_LIMIT (0x3ff) +#define DxEPTSIZ_PktCnt(_x) ((_x) << 19) + +#define DxEPTSIZ_XferSize_MASK (0x7ffff << 0) +#define DxEPTSIZ_XferSize_SHIFT (0) +#define DxEPTSIZ_XferSize_GET(_v) (((_v) >> 0) & 0x7ffff) +#define DxEPTSIZ_XferSize_LIMIT (0x7ffff) +#define DxEPTSIZ_XferSize(_x) ((_x) << 0) + +#define DIEPDMA(_a) HSOTG_REG(0x914 + ((_a) * 0x20)) +#define DOEPDMA(_a) HSOTG_REG(0xB14 + ((_a) * 0x20)) +#define DTXFSTS(_a) HSOTG_REG(0x918 + ((_a) * 0x20)) + +#define EPFIFO(_a) HSOTG_REG(0x1000 + ((_a) * 0x1000)) + +#endif /* __REGS_USB_HSOTG_H */ diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index cef9b82ff911..36c6836eeb0f 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -110,7 +110,6 @@ struct s3c_hsudc_ep { struct usb_ep ep; char name[20]; struct s3c_hsudc *dev; - const struct usb_endpoint_descriptor *desc; struct list_head queue; u8 stopped; u8 wedge; @@ -761,7 +760,7 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep, u32 ecr = 0; hsep = our_ep(_ep); - if (!_ep || !desc || hsep->desc || _ep->name == ep0name + if (!_ep || !desc || hsep->ep.desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || hsep->bEndpointAddress != desc->bEndpointAddress || ep_maxpacket(hsep) < usb_endpoint_maxp(desc)) @@ -783,7 +782,7 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep, writel(ecr, hsudc->regs + S3C_ECR); hsep->stopped = hsep->wedge = 0; - hsep->desc = desc; + hsep->ep.desc = desc; hsep->ep.maxpacket = usb_endpoint_maxp(desc); s3c_hsudc_set_halt(_ep, 0); @@ -806,7 +805,7 @@ static int s3c_hsudc_ep_disable(struct usb_ep *_ep) struct s3c_hsudc *hsudc = hsep->dev; unsigned long flags; - if (!_ep || !hsep->desc) + if (!_ep || !hsep->ep.desc) return -EINVAL; spin_lock_irqsave(&hsudc->lock, flags); @@ -816,7 +815,6 @@ static int s3c_hsudc_ep_disable(struct usb_ep *_ep) s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN); - hsep->desc = 0; hsep->ep.desc = NULL; hsep->stopped = 1; @@ -1006,7 +1004,6 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc, hsep->ep.maxpacket = epnum ? 512 : 64; hsep->ep.ops = &s3c_hsudc_ep_ops; hsep->fifo = hsudc->regs + S3C_BR(epnum); - hsep->desc = 0; hsep->ep.desc = NULL; hsep->stopped = 0; hsep->wedge = 0; diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 195524cde6c3..3de71d37d75e 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1062,7 +1062,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep, ep = to_s3c2410_ep(_ep); - if (!_ep || !desc || ep->desc + if (!_ep || !desc || ep->ep.desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT) return -EINVAL; @@ -1075,7 +1075,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep, local_irq_save (flags); _ep->maxpacket = max & 0x7ff; - ep->desc = desc; + ep->ep.desc = desc; ep->halted = 0; ep->bEndpointAddress = desc->bEndpointAddress; @@ -1136,7 +1136,7 @@ static int s3c2410_udc_ep_disable(struct usb_ep *_ep) unsigned long flags; u32 int_en_reg; - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { dprintk(DEBUG_NORMAL, "%s not enabled\n", _ep ? ep->ep.name : NULL); return -EINVAL; @@ -1146,7 +1146,6 @@ static int s3c2410_udc_ep_disable(struct usb_ep *_ep) dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name); - ep->desc = NULL; ep->ep.desc = NULL; ep->halted = 1; @@ -1195,7 +1194,7 @@ s3c2410_udc_free_request(struct usb_ep *_ep, struct usb_request *_req) dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req); - if (!ep || !_req || (!ep->desc && _ep->name != ep0name)) + if (!ep || !_req || (!ep->ep.desc && _ep->name != ep0name)) return; WARN_ON (!list_empty (&req->queue)); @@ -1215,7 +1214,7 @@ static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req, int fifo_count = 0; unsigned long flags; - if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) { + if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) { dprintk(DEBUG_NORMAL, "%s: invalid args\n", __func__); return -EINVAL; } @@ -1363,7 +1362,7 @@ static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value) unsigned long flags; u32 idx; - if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) { + if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) { dprintk(DEBUG_NORMAL, "%s: inval 2\n", __func__); return -EINVAL; } @@ -1629,7 +1628,6 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev) list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list); ep->dev = dev; - ep->desc = NULL; ep->ep.desc = NULL; ep->halted = 0; INIT_LIST_HEAD (&ep->queue); diff --git a/drivers/usb/gadget/s3c2410_udc.h b/drivers/usb/gadget/s3c2410_udc.h index 1653bae08b80..3e80fd5c820f 100644 --- a/drivers/usb/gadget/s3c2410_udc.h +++ b/drivers/usb/gadget/s3c2410_udc.h @@ -19,7 +19,6 @@ struct s3c2410_ep { unsigned long last_io; /* jiffies timestamp */ struct usb_gadget *gadget; struct s3c2410_udc *dev; - const struct usb_endpoint_descriptor *desc; struct usb_ep ep; u8 num; diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 2fa9865babed..e5e44f8cde9a 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -263,8 +263,8 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) if (udc_is_newstyle(udc)) { udc->driver->disconnect(udc->gadget); - udc->driver->unbind(udc->gadget); usb_gadget_disconnect(udc->gadget); + udc->driver->unbind(udc->gadget); usb_gadget_udc_stop(udc->gadget, udc->driver); } else { usb_gadget_stop(udc->gadget, udc->driver); @@ -415,9 +415,9 @@ static ssize_t usb_udc_softconn_store(struct device *dev, usb_gadget_udc_start(udc->gadget, udc->driver); usb_gadget_connect(udc->gadget); } else if (sysfs_streq(buf, "disconnect")) { + usb_gadget_disconnect(udc->gadget); if (udc_is_newstyle(udc)) usb_gadget_udc_stop(udc->gadget, udc->driver); - usb_gadget_disconnect(udc->gadget); } else { dev_err(dev, "unsupported command '%s'\n", buf); return -EINVAL; diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h index bc78c606c12b..ca4e03a1c73a 100644 --- a/drivers/usb/gadget/uvc.h +++ b/drivers/usb/gadget/uvc.h @@ -28,7 +28,7 @@ struct uvc_request_data { - unsigned int length; + __s32 length; __u8 data[60]; }; diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c index f6e083b50191..54d7ca559cb2 100644 --- a/drivers/usb/gadget/uvc_v4l2.c +++ b/drivers/usb/gadget/uvc_v4l2.c @@ -39,7 +39,7 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data) if (data->length < 0) return usb_ep_set_halt(cdev->gadget->ep0); - req->length = min(uvc->event_length, data->length); + req->length = min_t(unsigned int, uvc->event_length, data->length); req->zero = data->length < uvc->event_length; req->dma = DMA_ADDR_INVALID; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 31d34832907e..12ad516ada77 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -72,7 +72,7 @@ static const char longname[] = "Gadget Zero"; -unsigned buflen = 4096; +unsigned buflen = 4096; /* only used for bulk endpoints */ module_param(buflen, uint, 0); /* @@ -170,14 +170,17 @@ static struct usb_gadget_strings *dev_strings[] = { /*-------------------------------------------------------------------------*/ -struct usb_request *alloc_ep_req(struct usb_ep *ep) +struct usb_request *alloc_ep_req(struct usb_ep *ep, int len) { struct usb_request *req; req = usb_ep_alloc_request(ep, GFP_ATOMIC); if (req) { - req->length = buflen; - req->buf = kmalloc(buflen, GFP_ATOMIC); + if (len) + req->length = len; + else + req->length = buflen; + req->buf = kmalloc(req->length, GFP_ATOMIC); if (!req->buf) { usb_ep_free_request(ep, req); req = NULL; @@ -206,10 +209,15 @@ static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep) } void disable_endpoints(struct usb_composite_dev *cdev, - struct usb_ep *in, struct usb_ep *out) + struct usb_ep *in, struct usb_ep *out, + struct usb_ep *iso_in, struct usb_ep *iso_out) { disable_ep(cdev, in); disable_ep(cdev, out); + if (iso_in) + disable_ep(cdev, iso_in); + if (iso_out) + disable_ep(cdev, iso_out); } /*-------------------------------------------------------------------------*/ @@ -311,7 +319,6 @@ static int __init zero_bind(struct usb_composite_dev *cdev) device_desc.bcdDevice = cpu_to_le16(0x9999); } - INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname); snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index f788eb86707c..684a7bba9307 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -110,13 +110,14 @@ config USB_EHCI_BIG_ENDIAN_MMIO depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || \ ARCH_IXP4XX || XPS_USB_HCD_XILINX || \ PPC_MPC512x || CPU_CAVIUM_OCTEON || \ - PMC_MSP || SPARC_LEON) + PMC_MSP || SPARC_LEON || MIPS_SEAD3) default y config USB_EHCI_BIG_ENDIAN_DESC bool depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \ - PPC_MPC512x || PMC_MSP || SPARC_LEON) + PPC_MPC512x || PMC_MSP || SPARC_LEON || \ + MIPS_SEAD3) default y config XPS_USB_HCD_XILINX @@ -291,6 +292,7 @@ config USB_OHCI_HCD depends on USB && USB_ARCH_HAS_OHCI select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 select USB_OTG_UTILS if ARCH_OMAP + select USB_ISP1301 if ARCH_LPC32XX || ARCH_PNX4008 ---help--- The Open Host Controller Interface (OHCI) is a standard for accessing USB 1.1 host controller hardware. It does more in hardware than Intel's @@ -373,10 +375,15 @@ config USB_OHCI_HCD_PCI If unsure, say Y. config USB_OHCI_HCD_SSB - bool "OHCI support for Broadcom SSB OHCI core" + bool "OHCI support for Broadcom SSB OHCI core (DEPRECATED)" depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) && EXPERIMENTAL + select USB_HCD_SSB + select USB_OHCI_HCD_PLATFORM default n ---help--- + This option is deprecated now and the driver was removed, use + USB_HCD_SSB and USB_OHCI_HCD_PLATFORM instead. + Support for the Sonics Silicon Backplane (SSB) attached Broadcom USB OHCI core. @@ -638,3 +645,27 @@ config USB_OCTEON_OHCI config USB_OCTEON2_COMMON bool default y if USB_OCTEON_EHCI || USB_OCTEON_OHCI + +config USB_HCD_BCMA + tristate "BCMA usb host driver" + depends on BCMA && EXPERIMENTAL + select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD + select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD + help + Enbale support for the EHCI and OCHI host controller on an bcma bus. + It converts the bcma driver into two platform device drivers + for ehci and ohci. + + If unsure, say N. + +config USB_HCD_SSB + tristate "SSB usb host driver" + depends on SSB && EXPERIMENTAL + select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD + select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD + help + Enbale support for the EHCI and OCHI host controller on an bcma bus. + It converts the bcma driver into two platform device drivers + for ehci and ohci. + + If unsure, say N. diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 0982bcc140bd..9e0a89ced15c 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -41,3 +41,5 @@ obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o obj-$(CONFIG_MIPS_ALCHEMY) += alchemy-common.o +obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o +obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c new file mode 100644 index 000000000000..443da21d73ca --- /dev/null +++ b/drivers/usb/host/bcma-hcd.c @@ -0,0 +1,335 @@ +/* + * Broadcom specific Advanced Microcontroller Bus + * Broadcom USB-core driver (BCMA bus glue) + * + * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de> + * + * Based on ssb-ohci driver + * Copyright 2007 Michael Buesch <m@bues.ch> + * + * Derived from the OHCI-PCI driver + * Copyright 1999 Roman Weissgaerber + * Copyright 2000-2002 David Brownell + * Copyright 1999 Linus Torvalds + * Copyright 1999 Gregory P. Smith + * + * Derived from the USBcore related parts of Broadcom-SB + * Copyright 2005-2011 Broadcom Corporation + * + * Licensed under the GNU/GPL. See COPYING for details. + */ +#include <linux/bcma/bcma.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/usb/ehci_pdriver.h> +#include <linux/usb/ohci_pdriver.h> + +MODULE_AUTHOR("Hauke Mehrtens"); +MODULE_DESCRIPTION("Common USB driver for BCMA Bus"); +MODULE_LICENSE("GPL"); + +struct bcma_hcd_device { + struct platform_device *ehci_dev; + struct platform_device *ohci_dev; +}; + +/* Wait for bitmask in a register to get set or cleared. + * timeout is in units of ten-microseconds. + */ +static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask, + int timeout) +{ + int i; + u32 val; + + for (i = 0; i < timeout; i++) { + val = bcma_read32(dev, reg); + if ((val & bitmask) == bitmask) + return 0; + udelay(10); + } + + return -ETIMEDOUT; +} + +static void __devinit bcma_hcd_4716wa(struct bcma_device *dev) +{ +#ifdef CONFIG_BCMA_DRIVER_MIPS + /* Work around for 4716 failures. */ + if (dev->bus->chipinfo.id == 0x4716) { + u32 tmp; + + tmp = bcma_cpu_clock(&dev->bus->drv_mips); + if (tmp >= 480000000) + tmp = 0x1846b; /* set CDR to 0x11(fast) */ + else if (tmp == 453000000) + tmp = 0x1046b; /* set CDR to 0x10(slow) */ + else + tmp = 0; + + /* Change Shim mdio control reg to fix host not acking at + * high frequencies + */ + if (tmp) { + bcma_write32(dev, 0x524, 0x1); /* write sel to enable */ + udelay(500); + + bcma_write32(dev, 0x524, tmp); + udelay(500); + bcma_write32(dev, 0x524, 0x4ab); + udelay(500); + bcma_read32(dev, 0x528); + bcma_write32(dev, 0x528, 0x80000000); + } + } +#endif /* CONFIG_BCMA_DRIVER_MIPS */ +} + +/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ +static void __devinit bcma_hcd_init_chip(struct bcma_device *dev) +{ + u32 tmp; + + /* + * USB 2.0 special considerations: + * + * 1. Since the core supports both OHCI and EHCI functions, it must + * only be reset once. + * + * 2. In addition to the standard SI reset sequence, the Host Control + * Register must be programmed to bring the USB core and various + * phy components out of reset. + */ + if (!bcma_core_is_enabled(dev)) { + bcma_core_enable(dev, 0); + mdelay(10); + if (dev->id.rev >= 5) { + /* Enable Misc PLL */ + tmp = bcma_read32(dev, 0x1e0); + tmp |= 0x100; + bcma_write32(dev, 0x1e0, tmp); + if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100)) + printk(KERN_EMERG "Failed to enable misc PPL!\n"); + + /* Take out of resets */ + bcma_write32(dev, 0x200, 0x4ff); + udelay(25); + bcma_write32(dev, 0x200, 0x6ff); + udelay(25); + + /* Make sure digital and AFE are locked in USB PHY */ + bcma_write32(dev, 0x524, 0x6b); + udelay(50); + tmp = bcma_read32(dev, 0x524); + udelay(50); + bcma_write32(dev, 0x524, 0xab); + udelay(50); + tmp = bcma_read32(dev, 0x524); + udelay(50); + bcma_write32(dev, 0x524, 0x2b); + udelay(50); + tmp = bcma_read32(dev, 0x524); + udelay(50); + bcma_write32(dev, 0x524, 0x10ab); + udelay(50); + tmp = bcma_read32(dev, 0x524); + + if (bcma_wait_bits(dev, 0x528, 0xc000, 10000)) { + tmp = bcma_read32(dev, 0x528); + printk(KERN_EMERG + "USB20H mdio_rddata 0x%08x\n", tmp); + } + bcma_write32(dev, 0x528, 0x80000000); + tmp = bcma_read32(dev, 0x314); + udelay(265); + bcma_write32(dev, 0x200, 0x7ff); + udelay(10); + + /* Take USB and HSIC out of non-driving modes */ + bcma_write32(dev, 0x510, 0); + } else { + bcma_write32(dev, 0x200, 0x7ff); + + udelay(1); + } + + bcma_hcd_4716wa(dev); + } +} + +static const struct usb_ehci_pdata ehci_pdata = { +}; + +static const struct usb_ohci_pdata ohci_pdata = { +}; + +static struct platform_device * __devinit +bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr) +{ + struct platform_device *hci_dev; + struct resource hci_res[2]; + int ret = -ENOMEM; + + memset(hci_res, 0, sizeof(hci_res)); + + hci_res[0].start = addr; + hci_res[0].end = hci_res[0].start + 0x1000 - 1; + hci_res[0].flags = IORESOURCE_MEM; + + hci_res[1].start = dev->irq; + hci_res[1].flags = IORESOURCE_IRQ; + + hci_dev = platform_device_alloc(ohci ? "ohci-platform" : + "ehci-platform" , 0); + if (!hci_dev) + return NULL; + + hci_dev->dev.parent = &dev->dev; + hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask; + + ret = platform_device_add_resources(hci_dev, hci_res, + ARRAY_SIZE(hci_res)); + if (ret) + goto err_alloc; + if (ohci) + ret = platform_device_add_data(hci_dev, &ohci_pdata, + sizeof(ohci_pdata)); + else + ret = platform_device_add_data(hci_dev, &ehci_pdata, + sizeof(ehci_pdata)); + if (ret) + goto err_alloc; + ret = platform_device_add(hci_dev); + if (ret) + goto err_alloc; + + return hci_dev; + +err_alloc: + platform_device_put(hci_dev); + return ERR_PTR(ret); +} + +static int __devinit bcma_hcd_probe(struct bcma_device *dev) +{ + int err; + u16 chipid_top; + u32 ohci_addr; + struct bcma_hcd_device *usb_dev; + struct bcma_chipinfo *chipinfo; + + chipinfo = &dev->bus->chipinfo; + /* USBcores are only connected on embedded devices. */ + chipid_top = (chipinfo->id & 0xFF00); + if (chipid_top != 0x4700 && chipid_top != 0x5300) + return -ENODEV; + + /* TODO: Probably need checks here; is the core connected? */ + + if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) || + dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32))) + return -EOPNOTSUPP; + + usb_dev = kzalloc(sizeof(struct bcma_hcd_device), GFP_KERNEL); + if (!usb_dev) + return -ENOMEM; + + bcma_hcd_init_chip(dev); + + /* In AI chips EHCI is addrspace 0, OHCI is 1 */ + ohci_addr = dev->addr1; + if ((chipinfo->id == 0x5357 || chipinfo->id == 0x4749) + && chipinfo->rev == 0) + ohci_addr = 0x18009000; + + usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr); + if (IS_ERR(usb_dev->ohci_dev)) { + err = PTR_ERR(usb_dev->ohci_dev); + goto err_free_usb_dev; + } + + usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr); + if (IS_ERR(usb_dev->ehci_dev)) { + err = PTR_ERR(usb_dev->ehci_dev); + goto err_unregister_ohci_dev; + } + + bcma_set_drvdata(dev, usb_dev); + return 0; + +err_unregister_ohci_dev: + platform_device_unregister(usb_dev->ohci_dev); +err_free_usb_dev: + kfree(usb_dev); + return err; +} + +static void __devexit bcma_hcd_remove(struct bcma_device *dev) +{ + struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); + struct platform_device *ohci_dev = usb_dev->ohci_dev; + struct platform_device *ehci_dev = usb_dev->ehci_dev; + + if (ohci_dev) + platform_device_unregister(ohci_dev); + if (ehci_dev) + platform_device_unregister(ehci_dev); + + bcma_core_disable(dev, 0); +} + +static void bcma_hcd_shutdown(struct bcma_device *dev) +{ + bcma_core_disable(dev, 0); +} + +#ifdef CONFIG_PM + +static int bcma_hcd_suspend(struct bcma_device *dev) +{ + bcma_core_disable(dev, 0); + + return 0; +} + +static int bcma_hcd_resume(struct bcma_device *dev) +{ + bcma_core_enable(dev, 0); + + return 0; +} + +#else /* !CONFIG_PM */ +#define bcma_hcd_suspend NULL +#define bcma_hcd_resume NULL +#endif /* CONFIG_PM */ + +static const struct bcma_device_id bcma_hcd_table[] __devinitconst = { + BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS), + BCMA_CORETABLE_END +}; +MODULE_DEVICE_TABLE(bcma, bcma_hcd_table); + +static struct bcma_driver bcma_hcd_driver = { + .name = KBUILD_MODNAME, + .id_table = bcma_hcd_table, + .probe = bcma_hcd_probe, + .remove = __devexit_p(bcma_hcd_remove), + .shutdown = bcma_hcd_shutdown, + .suspend = bcma_hcd_suspend, + .resume = bcma_hcd_resume, +}; + +static int __init bcma_hcd_init(void) +{ + return bcma_driver_register(&bcma_hcd_driver); +} +module_init(bcma_hcd_init); + +static void __exit bcma_hcd_exit(void) +{ + bcma_driver_unregister(&bcma_hcd_driver); +} +module_exit(bcma_hcd_exit); diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 680e1a31fb87..7561966fbdc4 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -1025,10 +1025,8 @@ static ssize_t debug_lpm_write(struct file *file, const char __user *user_buf, if (strict_strtoul(buf + 5, 16, &hird)) return -EINVAL; printk(KERN_INFO "setting hird %s %lu\n", buf + 6, hird); - temp = ehci_readl(ehci, &ehci->regs->command); - temp &= ~CMD_HIRD; - temp |= hird << 24; - ehci_writel(ehci, temp, &ehci->regs->command); + ehci->command = (ehci->command & ~CMD_HIRD) | (hird << 24); + ehci_writel(ehci, ehci->command, &ehci->regs->command); } else if (strncmp(buf, "disable", 7) == 0) { if (strict_strtoul(buf + 8, 10, &port)) return -EINVAL; diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index d0a84bd3f3eb..34acfcee7405 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -1,6 +1,6 @@ /* * Copyright 2005-2009 MontaVista Software, Inc. - * Copyright 2008 Freescale Semiconductor, Inc. + * Copyright 2008,2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -211,22 +211,32 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd, usb_put_hcd(hcd); } -static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, +static void ehci_fsl_setup_phy(struct usb_hcd *hcd, enum fsl_usb2_phy_modes phy_mode, unsigned int port_offset) { - u32 portsc; - struct usb_hcd *hcd = ehci_to_hcd(ehci); + u32 portsc, temp; + struct ehci_hcd *ehci = hcd_to_ehci(hcd); void __iomem *non_ehci = hcd->regs; - struct fsl_usb2_platform_data *pdata; + struct device *dev = hcd->self.controller; + struct fsl_usb2_platform_data *pdata = dev->platform_data; - pdata = hcd->self.controller->platform_data; + if (pdata->controller_ver < 0) { + dev_warn(hcd->self.controller, "Could not get controller version\n"); + return; + } portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]); portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW); switch (phy_mode) { case FSL_USB2_PHY_ULPI: + if (pdata->controller_ver) { + /* controller version 1.6 or above */ + temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); + out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | + USB_CTRL_USB_EN | ULPI_PHY_CLK_SEL); + } portsc |= PORT_PTS_ULPI; break; case FSL_USB2_PHY_SERIAL: @@ -236,6 +246,14 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, portsc |= PORT_PTS_PTW; /* fall through */ case FSL_USB2_PHY_UTMI: + if (pdata->controller_ver) { + /* controller version 1.6 or above */ + temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); + out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | + UTMI_PHY_EN | USB_CTRL_USB_EN); + mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to + become stable - 10ms*/ + } /* enable UTMI PHY */ if (pdata->have_sysif_regs) setbits32(non_ehci + FSL_SOC_USB_CTRL, @@ -276,7 +294,7 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) if ((pdata->operating_mode == FSL_USB2_DR_HOST) || (pdata->operating_mode == FSL_USB2_DR_OTG)) - ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); + ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0); if (pdata->operating_mode == FSL_USB2_MPH_HOST) { unsigned int chip, rev, svr; @@ -290,9 +308,9 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) ehci->has_fsl_port_bug = 1; if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) - ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); + ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0); if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) - ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1); + ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1); } if (pdata->have_sysif_regs) { diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index 863fb0c080d7..88403684d10b 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc. +/* Copyright (C) 2005-2010,2012 Freescale Semiconductor, Inc. * Copyright (c) 2005 MontaVista Software * * This program is free software; you can redistribute it and/or modify it @@ -50,4 +50,15 @@ #define CTRL_UTMI_PHY_EN (1<<9) #define CTRL_PHY_CLK_VALID (1 << 17) #define SNOOP_SIZE_2GB 0x1e + +/* control Register Bit Masks */ +#define ULPI_INT_EN (1<<0) +#define WU_INT_EN (1<<1) +#define USB_CTRL_USB_EN (1<<2) +#define LINE_STATE_FILTER__EN (1<<3) +#define KEEP_OTG_ON (1<<4) +#define OTG_PORT (1<<5) +#define PLL_RESET (1<<8) +#define UTMI_PHY_EN (1<<9) +#define ULPI_PHY_CLK_SEL (1<<10) #endif /* _EHCI_FSL_H */ diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 4a3bc5b7a06f..de1e689d3df0 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -226,8 +226,13 @@ static int ehci_halt (struct ehci_hcd *ehci) if ((temp & STS_HALT) != 0) return 0; + /* + * This routine gets called during probe before ehci->command + * has been initialized, so we can't rely on its value. + */ + ehci->command &= ~CMD_RUN; temp = ehci_readl(ehci, &ehci->regs->command); - temp &= ~CMD_RUN; + temp &= ~(CMD_RUN | CMD_IAAD); ehci_writel(ehci, temp, &ehci->regs->command); return handshake (ehci, &ehci->regs->status, STS_HALT, STS_HALT, 16 * 125); @@ -347,6 +352,7 @@ static int ehci_reset (struct ehci_hcd *ehci) if (ehci->debug) dbgp_external_startup(); + ehci->command = ehci_readl(ehci, &ehci->regs->command); ehci->port_c_suspend = ehci->suspended_ports = ehci->resuming_ports = 0; return retval; @@ -363,16 +369,14 @@ static void ehci_quiesce (struct ehci_hcd *ehci) #endif /* wait for any schedule enables/disables to take effect */ - temp = ehci_readl(ehci, &ehci->regs->command) << 10; - temp &= STS_ASS | STS_PSS; + temp = (ehci->command << 10) & (STS_ASS | STS_PSS); if (handshake_on_error_set_halt(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125)) return; /* then disable anything that's still active */ - temp = ehci_readl(ehci, &ehci->regs->command); - temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE); - ehci_writel(ehci, temp, &ehci->regs->command); + ehci->command &= ~(CMD_ASE | CMD_PSE); + ehci_writel(ehci, ehci->command, &ehci->regs->command); /* hardware can take 16 microframes to turn off ... */ handshake_on_error_set_halt(ehci, &ehci->regs->status, @@ -417,9 +421,6 @@ static void ehci_iaa_watchdog(unsigned long param) * CMD_IAAD when it sets STS_IAA.) */ cmd = ehci_readl(ehci, &ehci->regs->command); - if (cmd & CMD_IAAD) - ehci_writel(ehci, cmd & ~CMD_IAAD, - &ehci->regs->command); /* If IAA is set here it either legitimately triggered * before we cleared IAAD above (but _way_ late, so we'll @@ -894,11 +895,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* complete the unlinking of some qh [4.15.2.3] */ if (status & STS_IAA) { /* guard against (alleged) silicon errata */ - if (cmd & CMD_IAAD) { - ehci_writel(ehci, cmd & ~CMD_IAAD, - &ehci->regs->command); + if (cmd & CMD_IAAD) ehci_dbg(ehci, "IAA with IAAD still set?\n"); - } if (ehci->reclaim) { COUNT(ehci->stats.reclaim); end_unlink_async(ehci); @@ -1378,6 +1376,11 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_ls1x_driver #endif +#ifdef CONFIG_MIPS_SEAD3 +#include "ehci-sead3.c" +#define PLATFORM_DRIVER ehci_hcd_sead3_driver +#endif + #ifdef CONFIG_USB_EHCI_HCD_PLATFORM #include "ehci-platform.c" #define PLATFORM_DRIVER ehci_platform_driver diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 38fe07623152..fc9e7cc6ac9b 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -233,7 +233,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) /* stop schedules, clean any completed work */ if (ehci->rh_state == EHCI_RH_RUNNING) ehci_quiesce (ehci); - ehci->command = ehci_readl(ehci, &ehci->regs->command); ehci_work(ehci); /* Unlike other USB host controller types, EHCI doesn't have @@ -374,6 +373,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next); /* restore CMD_RUN, framelist size, and irq threshold */ + ehci->command |= CMD_RUN; ehci_writel(ehci, ehci->command, &ehci->regs->command); ehci->rh_state = EHCI_RH_RUNNING; @@ -531,7 +531,8 @@ static int check_reset_complete ( if (ehci->has_amcc_usb23) set_ohci_hcfs(ehci, 1); } else { - ehci_dbg (ehci, "port %d high speed\n", index + 1); + ehci_dbg(ehci, "port %d reset complete, port enabled\n", + index + 1); /* ensure 440EPx ohci controller state is suspended */ if (ehci->has_amcc_usb23) set_ohci_hcfs(ehci, 0); @@ -699,6 +700,7 @@ static int ehci_hub_control ( goto error; wIndex--; temp = ehci_readl(ehci, status_reg); + temp &= ~PORT_RWC_BITS; /* * Even if OWNER is set, so the port is owned by the @@ -712,8 +714,7 @@ static int ehci_hub_control ( ehci_writel(ehci, temp & ~PORT_PE, status_reg); break; case USB_PORT_FEAT_C_ENABLE: - ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_PEC, - status_reg); + ehci_writel(ehci, temp | PORT_PEC, status_reg); break; case USB_PORT_FEAT_SUSPEND: if (temp & PORT_RESET) @@ -742,7 +743,7 @@ static int ehci_hub_control ( spin_lock_irqsave(&ehci->lock, flags); } /* resume signaling for 20 msec */ - temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); + temp &= ~PORT_WAKE_BITS; ehci_writel(ehci, temp | PORT_RESUME, status_reg); ehci->reset_done[wIndex] = jiffies + msecs_to_jiffies(20); @@ -752,9 +753,8 @@ static int ehci_hub_control ( break; case USB_PORT_FEAT_POWER: if (HCS_PPC (ehci->hcs_params)) - ehci_writel(ehci, - temp & ~(PORT_RWC_BITS | PORT_POWER), - status_reg); + ehci_writel(ehci, temp & ~PORT_POWER, + status_reg); break; case USB_PORT_FEAT_C_CONNECTION: if (ehci->has_lpm) { @@ -762,12 +762,10 @@ static int ehci_hub_control ( temp &= ~PORT_LPM; temp &= ~PORT_DEV_ADDR; } - ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC, - status_reg); + ehci_writel(ehci, temp | PORT_CSC, status_reg); break; case USB_PORT_FEAT_C_OVER_CURRENT: - ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_OCC, - status_reg); + ehci_writel(ehci, temp | PORT_OCC, status_reg); break; case USB_PORT_FEAT_C_RESET: /* GetPortStatus clears reset */ diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 5c78f9e71466..e669c6a7e91e 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -242,15 +242,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) ehci_reset(omap_ehci); - ret = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (ret) { - dev_err(dev, "failed to add hcd with err %d\n", ret); - goto err_add_hcd; - } - - /* root ports should always stay powered */ - ehci_port_power(omap_ehci, 1); - if (pdata->phy_reset) { /* Hold the PHY in RESET for enough time till * PHY is settled and ready @@ -264,6 +255,15 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) gpio_set_value(pdata->reset_gpio_port[1], 1); } + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (ret) { + dev_err(dev, "failed to add hcd with err %d\n", ret); + goto err_add_hcd; + } + + /* root ports should always stay powered */ + ehci_port_power(omap_ehci, 1); + return 0; err_add_hcd: diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 01bb7241d6ef..bc94d7bf072d 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -144,6 +144,14 @@ static int ehci_pci_setup(struct usb_hcd *hcd) hcd->has_tt = 1; tdi_reset(ehci); } + if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) { + /* EHCI #1 or #2 on 6 Series/C200 Series chipset */ + if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) { + ehci_info(ehci, "broken D3 during system sleep on ASUS\n"); + hcd->broken_pci_sleep = 1; + device_set_wakeup_capable(&pdev->dev, false); + } + } break; case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { @@ -360,7 +368,9 @@ static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev) { return pdev->class == PCI_CLASS_SERIAL_USB_EHCI && pdev->vendor == PCI_VENDOR_ID_INTEL && - pdev->device == 0x1E26; + (pdev->device == 0x1E26 || + pdev->device == 0x8C2D || + pdev->device == 0x8C26); } static void ehci_enable_xhci_companion(void) diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index d238b4e24bb6..23c530ae5aa3 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -94,12 +94,12 @@ static int __devinit ehci_platform_probe(struct platform_device *dev) irq = platform_get_irq(dev, 0); if (irq < 0) { - pr_err("no irq provieded"); + pr_err("no irq provided"); return irq; } res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res_mem) { - pr_err("no memory recourse provieded"); + pr_err("no memory recourse provided"); return -ENXIO; } diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 36ca5077cdf7..4378bf72bbac 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -943,7 +943,8 @@ qh_make ( } break; default: - dbg ("bogus dev %p speed %d", urb->dev, urb->dev->speed); + ehci_dbg(ehci, "bogus dev %p speed %d\n", urb->dev, + urb->dev->speed); done: qh_put (qh); return NULL; @@ -981,14 +982,12 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) head = ehci->async; timer_action_done (ehci, TIMER_ASYNC_OFF); if (!head->qh_next.qh) { - u32 cmd = ehci_readl(ehci, &ehci->regs->command); - - if (!(cmd & CMD_ASE)) { + if (!(ehci->command & CMD_ASE)) { /* in case a clear of CMD_ASE didn't take yet */ (void)handshake(ehci, &ehci->regs->status, STS_ASS, 0, 150); - cmd |= CMD_ASE; - ehci_writel(ehci, cmd, &ehci->regs->command); + ehci->command |= CMD_ASE; + ehci_writel(ehci, ehci->command, &ehci->regs->command); /* posted write need not be known to HC yet ... */ } } @@ -1204,7 +1203,6 @@ static void end_unlink_async (struct ehci_hcd *ehci) static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) { - int cmd = ehci_readl(ehci, &ehci->regs->command); struct ehci_qh *prev; #ifdef DEBUG @@ -1222,8 +1220,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) if (ehci->rh_state != EHCI_RH_HALTED && !ehci->reclaim) { /* ... and CMD_IAAD clear */ - ehci_writel(ehci, cmd & ~CMD_ASE, - &ehci->regs->command); + ehci->command &= ~CMD_ASE; + ehci_writel(ehci, ehci->command, &ehci->regs->command); wmb (); // handshake later, if we need to timer_action_done (ehci, TIMER_ASYNC_OFF); @@ -1253,8 +1251,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) return; } - cmd |= CMD_IAAD; - ehci_writel(ehci, cmd, &ehci->regs->command); + ehci_writel(ehci, ehci->command | CMD_IAAD, &ehci->regs->command); (void)ehci_readl(ehci, &ehci->regs->command); iaa_watchdog_start(ehci); } diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index f098e2a291a0..c474cec064e4 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -232,6 +232,8 @@ static int s5p_ehci_suspend(struct device *dev) if (pdata && pdata->phy_exit) pdata->phy_exit(pdev, S5P_USB_PHY_HOST); + clk_disable(s5p_ehci->clk); + return rc; } @@ -243,6 +245,8 @@ static int s5p_ehci_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; + clk_enable(s5p_ehci->clk); + if (pdata && pdata->phy_init) pdata->phy_init(pdev, S5P_USB_PHY_HOST); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index a60679cbbf85..cb7667967e5a 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -481,7 +481,6 @@ static int tt_no_collision ( static int enable_periodic (struct ehci_hcd *ehci) { - u32 cmd; int status; if (ehci->periodic_sched++) @@ -497,8 +496,8 @@ static int enable_periodic (struct ehci_hcd *ehci) return status; } - cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE; - ehci_writel(ehci, cmd, &ehci->regs->command); + ehci->command |= CMD_PSE; + ehci_writel(ehci, ehci->command, &ehci->regs->command); /* posted write ... PSS happens later */ /* make sure ehci_work scans these */ @@ -511,7 +510,6 @@ static int enable_periodic (struct ehci_hcd *ehci) static int disable_periodic (struct ehci_hcd *ehci) { - u32 cmd; int status; if (--ehci->periodic_sched) @@ -537,8 +535,8 @@ static int disable_periodic (struct ehci_hcd *ehci) return status; } - cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE; - ehci_writel(ehci, cmd, &ehci->regs->command); + ehci->command &= ~CMD_PSE; + ehci_writel(ehci, ehci->command, &ehci->regs->command); /* posted write ... */ free_cached_lists(ehci); @@ -2358,7 +2356,8 @@ restart: * in the previous frame for completions. */ if (q.fstn->hw_prev != EHCI_LIST_END(ehci)) { - dbg ("ignoring completions from FSTNs"); + ehci_dbg(ehci, + "ignoring completions from FSTNs\n"); } type = Q_NEXT_TYPE(ehci, q.fstn->hw_next); q = q.fstn->fstn_next; @@ -2441,7 +2440,7 @@ restart: q = *q_p; break; default: - dbg ("corrupt type %d frame %d shadow %p", + ehci_dbg(ehci, "corrupt type %d frame %d shadow %p\n", type, frame, q.ptr); // BUG (); q.ptr = NULL; diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c new file mode 100644 index 000000000000..4c164308ed20 --- /dev/null +++ b/drivers/usb/host/ehci-sead3.c @@ -0,0 +1,266 @@ +/* + * MIPS CI13320A EHCI Host Controller driver + * Based on "ehci-au1xxx.c" by K.Boge <karsten.boge@amd.com> + * + * Copyright (C) 2012 MIPS Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/platform_device.h> + +static int ehci_sead3_setup(struct usb_hcd *hcd) +{ + int ret; + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + + ehci->caps = hcd->regs + 0x100; + + ret = ehci_setup(hcd); + if (ret) + return ret; + + ehci->need_io_watchdog = 0; + +#ifdef __BIG_ENDIAN + ehci->big_endian_mmio = 1; + ehci->big_endian_desc = 1; +#endif + + /* Set burst length to 16 words. */ + ehci_writel(ehci, 0x1010, &ehci->regs->reserved[1]); + + return ret; +} + +const struct hc_driver ehci_sead3_hc_driver = { + .description = hcd_name, + .product_desc = "SEAD-3 EHCI", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + * + */ + .reset = ehci_sead3_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 ehci_hcd_sead3_drv_probe(struct platform_device *pdev) +{ + struct usb_hcd *hcd; + struct resource *res; + int ret; + + if (usb_disabled()) + return -ENODEV; + + if (pdev->resource[1].flags != IORESOURCE_IRQ) { + pr_debug("resource[1] is not IORESOURCE_IRQ"); + return -ENOMEM; + } + hcd = usb_create_hcd(&ehci_sead3_hc_driver, &pdev->dev, "SEAD-3"); + if (!hcd) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + pr_debug("request_mem_region failed"); + ret = -EBUSY; + goto err1; + } + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + pr_debug("ioremap failed"); + ret = -ENOMEM; + goto err2; + } + + /* Root hub has integrated TT. */ + hcd->has_tt = 1; + + ret = usb_add_hcd(hcd, pdev->resource[1].start, + IRQF_SHARED); + if (ret == 0) { + platform_set_drvdata(pdev, hcd); + return ret; + } + + iounmap(hcd->regs); +err2: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +err1: + usb_put_hcd(hcd); + return ret; +} + +static int ehci_hcd_sead3_drv_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); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +#ifdef CONFIG_PM +static int ehci_hcd_sead3_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(20); + + /* 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. + */ + ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); + spin_lock_irqsave(&ehci->lock, flags); + ehci_writel(ehci, 0, &ehci->regs->intr_enable); + (void)ehci_readl(ehci, &ehci->regs->intr_enable); + + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + spin_unlock_irqrestore(&ehci->lock, flags); + + /* could save FLADJ in case of Vaux power loss + * ... we'd only use it to handle clock skew + */ + + return rc; +} + +static int ehci_hcd_sead3_drv_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + + /* maybe restore FLADJ. */ + + if (time_before(jiffies, ehci->next_statechange)) + msleep(100); + + /* Mark hardware accessible again as we are out of D3 state by now */ + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + + /* If CF is still set, we maintained PCI Vaux power. + * Just undo the effect of ehci_pci_suspend(). + */ + 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; + } + + ehci_dbg(ehci, "lost power, restarting\n"); + 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. + */ + (void) ehci_halt(ehci); + (void) 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); + + ehci->rh_state = EHCI_RH_SUSPENDED; + + return 0; +} + +static const struct dev_pm_ops sead3_ehci_pmops = { + .suspend = ehci_hcd_sead3_drv_suspend, + .resume = ehci_hcd_sead3_drv_resume, +}; + +#define SEAD3_EHCI_PMOPS (&sead3_ehci_pmops) + +#else +#define SEAD3_EHCI_PMOPS NULL +#endif + +static struct platform_driver ehci_hcd_sead3_driver = { + .probe = ehci_hcd_sead3_drv_probe, + .remove = ehci_hcd_sead3_drv_remove, + .shutdown = usb_hcd_platform_shutdown, + .driver = { + .name = "sead3-ehci", + .owner = THIS_MODULE, + .pm = SEAD3_EHCI_PMOPS, + } +}; + +MODULE_ALIAS("platform:sead3-ehci"); diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index 9d9cf47d80da..ca819cdd0c5e 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -11,6 +11,7 @@ */ #include <linux/platform_device.h> #include <linux/clk.h> +#include <linux/platform_data/ehci-sh.h> struct ehci_sh_priv { struct clk *iclk, *fclk; @@ -100,6 +101,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) const struct hc_driver *driver = &ehci_sh_hc_driver; struct resource *res; struct ehci_sh_priv *priv; + struct ehci_sh_platdata *pdata; struct usb_hcd *hcd; int irq, ret; @@ -124,6 +126,9 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) goto fail_create_hcd; } + if (pdev->dev.platform_data != NULL) + pdata = pdev->dev.platform_data; + /* initialize hcd */ hcd = usb_create_hcd(&ehci_sh_hc_driver, &pdev->dev, dev_name(&pdev->dev)); @@ -168,6 +173,9 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) clk_enable(priv->fclk); clk_enable(priv->iclk); + if (pdata && pdata->phy_init) + pdata->phy_init(); + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret != 0) { dev_err(&pdev->dev, "Failed to add hcd"); diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c index 6e928559169c..37ba8c8d2fd0 100644 --- a/drivers/usb/host/ehci-spear.c +++ b/drivers/usb/host/ehci-spear.c @@ -13,6 +13,7 @@ #include <linux/clk.h> #include <linux/jiffies.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm.h> @@ -25,12 +26,12 @@ struct spear_ehci { static void spear_start_ehci(struct spear_ehci *ehci) { - clk_enable(ehci->clk); + clk_prepare_enable(ehci->clk); } static void spear_stop_ehci(struct spear_ehci *ehci) { - clk_disable(ehci->clk); + clk_disable_unprepare(ehci->clk); } static int ehci_spear_setup(struct usb_hcd *hcd) @@ -168,6 +169,8 @@ static int ehci_spear_drv_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend, ehci_spear_drv_resume); +static u64 spear_ehci_dma_mask = DMA_BIT_MASK(32); + static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd ; @@ -175,12 +178,9 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) struct resource *res; struct clk *usbh_clk; const struct hc_driver *driver = &ehci_spear_hc_driver; - int *pdata = pdev->dev.platform_data; int irq, retval; char clk_name[20] = "usbh_clk"; - - if (pdata == NULL) - return -EFAULT; + static int instance = -1; if (usb_disabled()) return -ENODEV; @@ -191,8 +191,22 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) goto fail_irq_get; } - if (*pdata >= 0) - sprintf(clk_name, "usbh.%01d_clk", *pdata); + /* + * Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &spear_ehci_dma_mask; + + /* + * Increment the device instance, when probing via device-tree + */ + if (pdev->id < 0) + instance++; + else + instance = pdev->id; + sprintf(clk_name, "usbh.%01d_clk", instance); usbh_clk = clk_get(NULL, clk_name); if (IS_ERR(usbh_clk)) { @@ -277,6 +291,11 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev) return 0; } +static struct of_device_id spear_ehci_id_table[] __devinitdata = { + { .compatible = "st,spear600-ehci", }, + { }, +}; + static struct platform_driver spear_ehci_hcd_driver = { .probe = spear_ehci_hcd_drv_probe, .remove = spear_ehci_hcd_drv_remove, @@ -285,6 +304,7 @@ static struct platform_driver spear_ehci_hcd_driver = { .name = "spear-ehci", .bus = &platform_bus_type, .pm = &ehci_spear_pm_ops, + .of_match_table = of_match_ptr(spear_ehci_id_table), } }; diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 86183366647f..e57aba52b31c 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -24,6 +24,7 @@ #include <linux/gpio.h> #include <linux/of.h> #include <linux/of_gpio.h> +#include <linux/pm_runtime.h> #include <mach/usb_phy.h> #include <mach/iomap.h> @@ -37,9 +38,7 @@ struct tegra_ehci_hcd { struct clk *emc_clk; struct usb_phy *transceiver; int host_resumed; - int bus_suspended; int port_resuming; - int power_down_on_bus_suspend; enum tegra_usb_phy_port_speed port_speed; }; @@ -148,18 +147,7 @@ static int tegra_ehci_hub_control( spin_lock_irqsave(&ehci->lock, flags); - /* - * In ehci_hub_control() for USB_PORT_FEAT_ENABLE clears the other bits - * that are write on clear, by writing back the register read value, so - * USB_PORT_FEAT_ENABLE is handled by masking the set on clear bits - */ - if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_ENABLE) { - temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS; - ehci_writel(ehci, temp & ~PORT_PE, status_reg); - goto done; - } - - else if (typeReq == GetPortStatus) { + if (typeReq == GetPortStatus) { temp = ehci_readl(ehci, status_reg); if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { /* Resume completed, re-enable disconnect detection */ @@ -175,7 +163,7 @@ static int tegra_ehci_hub_control( goto done; } - temp &= ~PORT_WKCONN_E; + temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E); temp |= PORT_WKDISC_E | PORT_WKOC_E; ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); @@ -273,120 +261,6 @@ static void tegra_ehci_restart(struct usb_hcd *hcd) up_write(&ehci_cf_port_reset_rwsem); } -static int tegra_usb_suspend(struct usb_hcd *hcd) -{ - struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); - struct ehci_regs __iomem *hw = tegra->ehci->regs; - unsigned long flags; - - spin_lock_irqsave(&tegra->ehci->lock, flags); - - tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3; - ehci_halt(tegra->ehci); - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - spin_unlock_irqrestore(&tegra->ehci->lock, flags); - - tegra_ehci_power_down(hcd); - return 0; -} - -static int tegra_usb_resume(struct usb_hcd *hcd) -{ - struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct ehci_regs __iomem *hw = ehci->regs; - unsigned long val; - - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - tegra_ehci_power_up(hcd); - - if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) { - /* Wait for the phy to detect new devices - * before we restart the controller */ - msleep(10); - goto restart; - } - - /* Force the phy to keep data lines in suspend state */ - tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed); - - /* Enable host mode */ - tdi_reset(ehci); - - /* Enable Port Power */ - val = readl(&hw->port_status[0]); - val |= PORT_POWER; - writel(val, &hw->port_status[0]); - udelay(10); - - /* Check if the phy resume from LP0. When the phy resume from LP0 - * USB register will be reset. */ - if (!readl(&hw->async_next)) { - /* Program the field PTC based on the saved speed mode */ - val = readl(&hw->port_status[0]); - val &= ~PORT_TEST(~0); - if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH) - val |= PORT_TEST_FORCE; - else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL) - val |= PORT_TEST(6); - else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) - val |= PORT_TEST(7); - writel(val, &hw->port_status[0]); - udelay(10); - - /* Disable test mode by setting PTC field to NORMAL_OP */ - val = readl(&hw->port_status[0]); - val &= ~PORT_TEST(~0); - writel(val, &hw->port_status[0]); - udelay(10); - } - - /* Poll until CCS is enabled */ - if (handshake(ehci, &hw->port_status[0], PORT_CONNECT, - PORT_CONNECT, 2000)) { - pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__); - goto restart; - } - - /* Poll until PE is enabled */ - if (handshake(ehci, &hw->port_status[0], PORT_PE, - PORT_PE, 2000)) { - pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__); - goto restart; - } - - /* Clear the PCI status, to avoid an interrupt taken upon resume */ - val = readl(&hw->status); - val |= STS_PCD; - writel(val, &hw->status); - - /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */ - val = readl(&hw->port_status[0]); - if ((val & PORT_POWER) && (val & PORT_PE)) { - val |= PORT_SUSPEND; - writel(val, &hw->port_status[0]); - - /* Wait until port suspend completes */ - if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND, - PORT_SUSPEND, 1000)) { - pr_err("%s: timeout waiting for PORT_SUSPEND\n", - __func__); - goto restart; - } - } - - tegra_ehci_phy_restore_end(tegra->phy); - return 0; - -restart: - if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH) - tegra_ehci_phy_restore_end(tegra->phy); - - tegra_ehci_restart(hcd); - return 0; -} - static void tegra_ehci_shutdown(struct usb_hcd *hcd) { struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); @@ -434,56 +308,23 @@ static int tegra_ehci_setup(struct usb_hcd *hcd) return retval; } -#ifdef CONFIG_PM -static int tegra_ehci_bus_suspend(struct usb_hcd *hcd) -{ - struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); - int error_status = 0; - - error_status = ehci_bus_suspend(hcd); - if (!error_status && tegra->power_down_on_bus_suspend) { - tegra_usb_suspend(hcd); - tegra->bus_suspended = 1; - } - - return error_status; -} - -static int tegra_ehci_bus_resume(struct usb_hcd *hcd) -{ - struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); - - if (tegra->bus_suspended && tegra->power_down_on_bus_suspend) { - tegra_usb_resume(hcd); - tegra->bus_suspended = 0; - } - - tegra_usb_phy_preresume(tegra->phy); - tegra->port_resuming = 1; - return ehci_bus_resume(hcd); -} -#endif - -struct temp_buffer { +struct dma_aligned_buffer { void *kmalloc_ptr; void *old_xfer_buffer; u8 data[0]; }; -static void free_temp_buffer(struct urb *urb) +static void free_dma_aligned_buffer(struct urb *urb) { - enum dma_data_direction dir; - struct temp_buffer *temp; + struct dma_aligned_buffer *temp; if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) return; - dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - - temp = container_of(urb->transfer_buffer, struct temp_buffer, - data); + temp = container_of(urb->transfer_buffer, + struct dma_aligned_buffer, data); - if (dir == DMA_FROM_DEVICE) + if (usb_urb_dir_in(urb)) memcpy(temp->old_xfer_buffer, temp->data, urb->transfer_buffer_length); urb->transfer_buffer = temp->old_xfer_buffer; @@ -492,10 +333,9 @@ static void free_temp_buffer(struct urb *urb) urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; } -static int alloc_temp_buffer(struct urb *urb, gfp_t mem_flags) +static int alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) { - enum dma_data_direction dir; - struct temp_buffer *temp, *kmalloc_ptr; + struct dma_aligned_buffer *temp, *kmalloc_ptr; size_t kmalloc_size; if (urb->num_sgs || urb->sg || @@ -503,22 +343,19 @@ static int alloc_temp_buffer(struct urb *urb, gfp_t mem_flags) !((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1))) return 0; - dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - /* Allocate a buffer with enough padding for alignment */ kmalloc_size = urb->transfer_buffer_length + - sizeof(struct temp_buffer) + TEGRA_USB_DMA_ALIGN - 1; + sizeof(struct dma_aligned_buffer) + TEGRA_USB_DMA_ALIGN - 1; kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); if (!kmalloc_ptr) return -ENOMEM; - /* Position our struct temp_buffer such that data is aligned */ + /* Position our struct dma_aligned_buffer such that data is aligned */ temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1; - temp->kmalloc_ptr = kmalloc_ptr; temp->old_xfer_buffer = urb->transfer_buffer; - if (dir == DMA_TO_DEVICE) + if (usb_urb_dir_out(urb)) memcpy(temp->data, urb->transfer_buffer, urb->transfer_buffer_length); urb->transfer_buffer = temp->data; @@ -533,13 +370,13 @@ static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, { int ret; - ret = alloc_temp_buffer(urb, mem_flags); + ret = alloc_dma_aligned_buffer(urb, mem_flags); if (ret) return ret; ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); if (ret) - free_temp_buffer(urb); + free_dma_aligned_buffer(urb); return ret; } @@ -547,38 +384,39 @@ static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) { usb_hcd_unmap_urb_for_dma(hcd, urb); - free_temp_buffer(urb); + free_dma_aligned_buffer(urb); } static const struct hc_driver tegra_ehci_hc_driver = { .description = hcd_name, .product_desc = "Tegra EHCI Host Controller", .hcd_priv_size = sizeof(struct ehci_hcd), - .flags = HCD_USB2 | HCD_MEMORY, - .reset = tegra_ehci_setup, + /* standard ehci functions */ .irq = ehci_irq, - .start = ehci_run, .stop = ehci_stop, - .shutdown = tegra_ehci_shutdown, .urb_enqueue = ehci_urb_enqueue, .urb_dequeue = ehci_urb_dequeue, - .map_urb_for_dma = tegra_ehci_map_urb_for_dma, - .unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma, .endpoint_disable = ehci_endpoint_disable, .endpoint_reset = ehci_endpoint_reset, .get_frame_number = ehci_get_frame, .hub_status_data = ehci_hub_status_data, - .hub_control = tegra_ehci_hub_control, .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -#ifdef CONFIG_PM - .bus_suspend = tegra_ehci_bus_suspend, - .bus_resume = tegra_ehci_bus_resume, -#endif .relinquish_port = ehci_relinquish_port, .port_handed_over = ehci_port_handed_over, + + /* modified ehci functions for tegra */ + .reset = tegra_ehci_setup, + .shutdown = tegra_ehci_shutdown, + .map_urb_for_dma = tegra_ehci_map_urb_for_dma, + .unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma, + .hub_control = tegra_ehci_hub_control, +#ifdef CONFIG_PM + .bus_suspend = ehci_bus_suspend, + .bus_resume = ehci_bus_resume, +#endif }; static int setup_vbus_gpio(struct platform_device *pdev) @@ -603,11 +441,187 @@ static int setup_vbus_gpio(struct platform_device *pdev) dev_err(&pdev->dev, "can't enable vbus\n"); return err; } - gpio_set_value(gpio, 1); return err; } +#ifdef CONFIG_PM + +static int controller_suspend(struct device *dev) +{ + struct tegra_ehci_hcd *tegra = + platform_get_drvdata(to_platform_device(dev)); + struct ehci_hcd *ehci = tegra->ehci; + struct usb_hcd *hcd = ehci_to_hcd(ehci); + struct ehci_regs __iomem *hw = ehci->regs; + unsigned long flags; + + if (time_before(jiffies, ehci->next_statechange)) + msleep(10); + + spin_lock_irqsave(&ehci->lock, flags); + + tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3; + ehci_halt(ehci); + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + + spin_unlock_irqrestore(&ehci->lock, flags); + + tegra_ehci_power_down(hcd); + return 0; +} + +static int controller_resume(struct device *dev) +{ + struct tegra_ehci_hcd *tegra = + platform_get_drvdata(to_platform_device(dev)); + struct ehci_hcd *ehci = tegra->ehci; + struct usb_hcd *hcd = ehci_to_hcd(ehci); + struct ehci_regs __iomem *hw = ehci->regs; + unsigned long val; + + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + tegra_ehci_power_up(hcd); + + if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) { + /* Wait for the phy to detect new devices + * before we restart the controller */ + msleep(10); + goto restart; + } + + /* Force the phy to keep data lines in suspend state */ + tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed); + + /* Enable host mode */ + tdi_reset(ehci); + + /* Enable Port Power */ + val = readl(&hw->port_status[0]); + val |= PORT_POWER; + writel(val, &hw->port_status[0]); + udelay(10); + + /* Check if the phy resume from LP0. When the phy resume from LP0 + * USB register will be reset. */ + if (!readl(&hw->async_next)) { + /* Program the field PTC based on the saved speed mode */ + val = readl(&hw->port_status[0]); + val &= ~PORT_TEST(~0); + if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH) + val |= PORT_TEST_FORCE; + else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL) + val |= PORT_TEST(6); + else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) + val |= PORT_TEST(7); + writel(val, &hw->port_status[0]); + udelay(10); + + /* Disable test mode by setting PTC field to NORMAL_OP */ + val = readl(&hw->port_status[0]); + val &= ~PORT_TEST(~0); + writel(val, &hw->port_status[0]); + udelay(10); + } + + /* Poll until CCS is enabled */ + if (handshake(ehci, &hw->port_status[0], PORT_CONNECT, + PORT_CONNECT, 2000)) { + pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__); + goto restart; + } + + /* Poll until PE is enabled */ + if (handshake(ehci, &hw->port_status[0], PORT_PE, + PORT_PE, 2000)) { + pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__); + goto restart; + } + + /* Clear the PCI status, to avoid an interrupt taken upon resume */ + val = readl(&hw->status); + val |= STS_PCD; + writel(val, &hw->status); + + /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */ + val = readl(&hw->port_status[0]); + if ((val & PORT_POWER) && (val & PORT_PE)) { + val |= PORT_SUSPEND; + writel(val, &hw->port_status[0]); + + /* Wait until port suspend completes */ + if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND, + PORT_SUSPEND, 1000)) { + pr_err("%s: timeout waiting for PORT_SUSPEND\n", + __func__); + goto restart; + } + } + + tegra_ehci_phy_restore_end(tegra->phy); + goto done; + + restart: + if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH) + tegra_ehci_phy_restore_end(tegra->phy); + + tegra_ehci_restart(hcd); + + done: + tegra_usb_phy_preresume(tegra->phy); + tegra->port_resuming = 1; + return 0; +} + +static int tegra_ehci_suspend(struct device *dev) +{ + struct tegra_ehci_hcd *tegra = + platform_get_drvdata(to_platform_device(dev)); + struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); + int rc = 0; + + /* + * When system sleep is supported and USB controller wakeup is + * implemented: If the controller is runtime-suspended and the + * wakeup setting needs to be changed, call pm_runtime_resume(). + */ + if (HCD_HW_ACCESSIBLE(hcd)) + rc = controller_suspend(dev); + return rc; +} + +static int tegra_ehci_resume(struct device *dev) +{ + int rc; + + rc = controller_resume(dev); + if (rc == 0) { + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + } + return rc; +} + +static int tegra_ehci_runtime_suspend(struct device *dev) +{ + return controller_suspend(dev); +} + +static int tegra_ehci_runtime_resume(struct device *dev) +{ + return controller_resume(dev); +} + +static const struct dev_pm_ops tegra_ehci_pm_ops = { + .suspend = tegra_ehci_suspend, + .resume = tegra_ehci_resume, + .runtime_suspend = tegra_ehci_runtime_suspend, + .runtime_resume = tegra_ehci_runtime_resume, +}; + +#endif + static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); static int tegra_ehci_probe(struct platform_device *pdev) @@ -722,7 +736,6 @@ static int tegra_ehci_probe(struct platform_device *pdev) } tegra->host_resumed = 1; - tegra->power_down_on_bus_suspend = pdata->power_down_on_bus_suspend; tegra->ehci = hcd_to_ehci(hcd); irq = platform_get_irq(pdev, 0); @@ -746,6 +759,14 @@ static int tegra_ehci_probe(struct platform_device *pdev) goto fail; } + pm_runtime_set_active(&pdev->dev); + pm_runtime_get_noresume(&pdev->dev); + + /* Don't skip the pm_runtime_forbid call if wakeup isn't working */ + /* if (!pdata->power_down_on_bus_suspend) */ + pm_runtime_forbid(&pdev->dev); + pm_runtime_enable(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); return err; fail: @@ -772,33 +793,6 @@ fail_hcd: return err; } -#ifdef CONFIG_PM -static int tegra_ehci_resume(struct platform_device *pdev) -{ - struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); - struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); - - if (tegra->bus_suspended) - return 0; - - return tegra_usb_resume(hcd); -} - -static int tegra_ehci_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); - struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); - - if (tegra->bus_suspended) - return 0; - - if (time_before(jiffies, tegra->ehci->next_statechange)) - msleep(10); - - return tegra_usb_suspend(hcd); -} -#endif - static int tegra_ehci_remove(struct platform_device *pdev) { struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); @@ -807,6 +801,10 @@ static int tegra_ehci_remove(struct platform_device *pdev) if (tegra == NULL || hcd == NULL) return -EINVAL; + pm_runtime_get_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + #ifdef CONFIG_USB_OTG_UTILS if (tegra->transceiver) { otg_set_host(tegra->transceiver->otg, NULL); @@ -847,13 +845,12 @@ static struct of_device_id tegra_ehci_of_match[] __devinitdata = { static struct platform_driver tegra_ehci_driver = { .probe = tegra_ehci_probe, .remove = tegra_ehci_remove, -#ifdef CONFIG_PM - .suspend = tegra_ehci_suspend, - .resume = tegra_ehci_resume, -#endif .shutdown = tegra_ehci_hcd_shutdown, .driver = { .name = "tegra-ehci", .of_match_table = tegra_ehci_of_match, +#ifdef CONFIG_PM + .pm = &tegra_ehci_pm_ops, +#endif } }; diff --git a/drivers/usb/host/fhci-tds.c b/drivers/usb/host/fhci-tds.c index 0ea577bfca2a..c5ed88199292 100644 --- a/drivers/usb/host/fhci-tds.c +++ b/drivers/usb/host/fhci-tds.c @@ -155,7 +155,7 @@ u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem, struct endpoint *ep; struct usb_td __iomem *td; unsigned long ep_offset; - char *err_for = "enpoint PRAM"; + char *err_for = "endpoint PRAM"; int ep_mem_size; u32 i; diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index ab333ac6071d..22ff6b3a676f 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -119,6 +119,39 @@ error: static const struct of_device_id fsl_usb2_mph_dr_of_match[]; +static int usb_get_ver_info(struct device_node *np) +{ + int ver = -1; + + /* + * returns 1 for usb controller version 1.6 + * returns 2 for usb controller version 2.2 + * returns 0 otherwise + */ + if (of_device_is_compatible(np, "fsl-usb2-dr")) { + if (of_device_is_compatible(np, "fsl-usb2-dr-v1.6")) + ver = FSL_USB_VER_1_6; + else if (of_device_is_compatible(np, "fsl-usb2-dr-v2.2")) + ver = FSL_USB_VER_2_2; + else /* for previous controller versions */ + ver = FSL_USB_VER_OLD; + + if (ver > -1) + return ver; + } + + if (of_device_is_compatible(np, "fsl-usb2-mph")) { + if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6")) + ver = FSL_USB_VER_1_6; + else if (of_device_is_compatible(np, "fsl-usb2-mph-v2.2")) + ver = FSL_USB_VER_2_2; + else /* for previous controller versions */ + ver = FSL_USB_VER_OLD; + } + + return ver; +} + static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev) { struct device_node *np = ofdev->dev.of_node; @@ -166,6 +199,14 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev) prop = of_get_property(np, "phy_type", NULL); pdata->phy_mode = determine_usb_phy(prop); + pdata->controller_ver = usb_get_ver_info(np); + + if (pdata->have_sysif_regs) { + if (pdata->controller_ver < 0) { + dev_warn(&ofdev->dev, "Could not get controller version\n"); + return -ENODEV; + } + } for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) { if (!dev_data->drivers[i]) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index fc72d44bf787..a35bbddf8968 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -1562,11 +1562,14 @@ static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { retval = -ESHUTDOWN; + qtd_list_free(&new_qtds); goto out; } retval = usb_hcd_link_urb_to_ep(hcd, urb); - if (retval) + if (retval) { + qtd_list_free(&new_qtds); goto out; + } qh = urb->ep->hcpriv; if (qh) { @@ -1584,6 +1587,7 @@ static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, if (!qh) { retval = -ENOMEM; usb_hcd_unlink_urb_from_ep(hcd, urb); + qtd_list_free(&new_qtds); goto out; } list_add_tail(&qh->qh_list, ep_queue); @@ -1683,6 +1687,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, list_for_each_entry(qtd, &qh->qtd_list, qtd_list) if (qtd->urb == urb) { dequeue_urb_from_qtd(hcd, qh, qtd); + list_move(&qtd->qtd_list, &qh->qtd_list); break; } @@ -2176,7 +2181,7 @@ static const struct hc_driver isp1760_hc_driver = { int __init init_kmem_once(void) { - urb_listitem_cachep = kmem_cache_create("isp1760 urb_listitem", + urb_listitem_cachep = kmem_cache_create("isp1760_urb_listitem", sizeof(struct urb_listitem), 0, SLAB_TEMPORARY | SLAB_MEM_SPREAD, NULL); diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 4592dc17a9f9..fff114fd5461 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -398,6 +398,9 @@ static int __devinit isp1760_plat_probe(struct platform_device *pdev) hcd = isp1760_register(mem_res->start, mem_size, irq_res->start, irqflags, -ENOENT, &pdev->dev, dev_name(&pdev->dev), devflags); + + dev_set_drvdata(&pdev->dev, hcd); + if (IS_ERR(hcd)) { pr_warning("isp1760: Failed to register the HCD device\n"); ret = -ENODEV; @@ -417,11 +420,16 @@ static int __devexit isp1760_plat_remove(struct platform_device *pdev) { struct resource *mem_res; resource_size_t mem_size; + struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); + + usb_remove_hcd(hcd); mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem_size = resource_size(mem_res); release_mem_region(mem_res->start, mem_size); + usb_put_hcd(hcd); + return 0; } diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 13ebeca8e73e..476fb4d3e45e 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -235,7 +235,8 @@ ohci_at91_start (struct usb_hcd *hcd) ohci->num_ports = board->ports; if ((ret = ohci_run(ohci)) < 0) { - err("can't start %s", hcd->self.bus_name); + dev_err(hcd->self.controller, "can't start %s\n", + hcd->self.bus_name); ohci_stop(hcd); return ret; } diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index 4ea63b2cac42..c611699b4aa6 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c @@ -37,7 +37,8 @@ static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd) return ret; if ((ret = ohci_run(ohci)) < 0) { - err ("can't start %s", hcd->self.bus_name); + dev_err(hcd->self.controller, "can't start %s", + hcd->self.bus_name); ohci_stop(hcd); return ret; } diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c index 5a00a1e1c6ca..2c9f233047be 100644 --- a/drivers/usb/host/ohci-cns3xxx.c +++ b/drivers/usb/host/ohci-cns3xxx.c @@ -41,7 +41,8 @@ cns3xxx_ohci_start(struct usb_hcd *hcd) ret = ohci_run(ohci); if (ret < 0) { - err("can't start %s", hcd->self.bus_name); + dev_err(hcd->self.controller, "can't start %s\n", + hcd->self.bus_name); ohci_stop(hcd); return ret; } diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index e4bcb62b930a..31b81f9eacdc 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -29,14 +29,14 @@ urb_print(struct urb * urb, char * str, int small, int status) unsigned int pipe= urb->pipe; if (!urb->dev || !urb->dev->bus) { - dbg("%s URB: no dev", str); + printk(KERN_DEBUG "%s URB: no dev\n", str); return; } #ifndef OHCI_VERBOSE_DEBUG if (status != 0) #endif - dbg("%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d", + printk(KERN_DEBUG "%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d\n", str, urb, usb_pipedevice (pipe), diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 3d63574d2c7e..dbfbd1dfd2e2 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -47,7 +47,7 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, struct usb_hcd *hcd; if (pdev->resource[1].flags != IORESOURCE_IRQ) { - dbg("resource[1] is not IORESOURCE_IRQ"); + dev_dbg(&pdev->dev, "resource[1] is not IORESOURCE_IRQ\n"); return -ENOMEM; } @@ -65,14 +65,14 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (hcd->regs == NULL) { - dbg("ioremap failed"); + dev_dbg(&pdev->dev, "ioremap failed\n"); retval = -ENOMEM; goto err2; } usb_host_clock = clk_get(&pdev->dev, NULL); if (IS_ERR(usb_host_clock)) { - dbg("clk_get failed"); + dev_dbg(&pdev->dev, "clk_get failed\n"); retval = PTR_ERR(usb_host_clock); goto err3; } @@ -116,7 +116,8 @@ static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd) return ret; if ((ret = ohci_run(ohci)) < 0) { - err("can't start %s", hcd->self.bus_name); + dev_err(hcd->self.controller, "can't start %s\n", + hcd->self.bus_name); ohci_stop(hcd); return ret; } diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index 37bb20ebb6fc..2909621ea196 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -35,7 +35,8 @@ static int ohci_exynos_start(struct usb_hcd *hcd) ret = ohci_run(ohci); if (ret < 0) { - err("can't start %s", hcd->self.bus_name); + dev_err(hcd->self.controller, "can't start %s\n", + hcd->self.bus_name); ohci_stop(hcd); return ret; } diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 235171f29460..e0adf5c0cf55 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1080,11 +1080,6 @@ MODULE_LICENSE ("GPL"); #define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver #endif -#ifdef CONFIG_USB_OHCI_HCD_SSB -#include "ohci-ssb.c" -#define SSB_OHCI_DRIVER ssb_ohci_driver -#endif - #ifdef CONFIG_MFD_SM501 #include "ohci-sm501.c" #define SM501_OHCI_DRIVER ohci_hcd_sm501_driver @@ -1128,8 +1123,7 @@ MODULE_LICENSE ("GPL"); !defined(SA1111_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && \ !defined(SM501_OHCI_DRIVER) && \ - !defined(TMIO_OHCI_DRIVER) && \ - !defined(SSB_OHCI_DRIVER) + !defined(TMIO_OHCI_DRIVER) #error "missing bus glue for ohci-hcd" #endif @@ -1195,12 +1189,6 @@ static int __init ohci_hcd_mod_init(void) goto error_pci; #endif -#ifdef SSB_OHCI_DRIVER - retval = ssb_driver_register(&SSB_OHCI_DRIVER); - if (retval) - goto error_ssb; -#endif - #ifdef SM501_OHCI_DRIVER retval = platform_driver_register(&SM501_OHCI_DRIVER); if (retval < 0) @@ -1224,10 +1212,6 @@ static int __init ohci_hcd_mod_init(void) platform_driver_unregister(&SM501_OHCI_DRIVER); error_sm501: #endif -#ifdef SSB_OHCI_DRIVER - ssb_driver_unregister(&SSB_OHCI_DRIVER); - error_ssb: -#endif #ifdef PCI_DRIVER pci_unregister_driver(&PCI_DRIVER); error_pci: @@ -1275,9 +1259,6 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef SM501_OHCI_DRIVER platform_driver_unregister(&SM501_OHCI_DRIVER); #endif -#ifdef SSB_OHCI_DRIVER - ssb_driver_unregister(&SSB_OHCI_DRIVER); -#endif #ifdef PCI_DRIVER pci_unregister_driver(&PCI_DRIVER); #endif diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c index 6618de1d881d..1e364ec962fb 100644 --- a/drivers/usb/host/ohci-nxp.c +++ b/drivers/usb/host/ohci-nxp.c @@ -22,6 +22,8 @@ #include <linux/clk.h> #include <linux/platform_device.h> #include <linux/i2c.h> +#include <linux/of.h> +#include <linux/usb/isp1301.h> #include <mach/hardware.h> #include <asm/mach-types.h> @@ -29,7 +31,6 @@ #include <mach/platform.h> #include <mach/irqs.h> -#include <asm/gpio.h> #define USB_CONFIG_BASE 0x31020000 #define PWRMAN_BASE 0x40004000 @@ -38,7 +39,9 @@ /* USB_CTRL bit defines */ #define USB_SLAVE_HCLK_EN (1 << 24) +#define USB_DEV_NEED_CLK_EN (1 << 22) #define USB_HOST_NEED_CLK_EN (1 << 21) +#define PAD_CONTROL_LAST_DRIVEN (1 << 19) #define USB_OTG_CLK_CTRL IO_ADDRESS(USB_CONFIG_BASE + 0xFF4) #define USB_OTG_CLK_STAT IO_ADDRESS(USB_CONFIG_BASE + 0xFF8) @@ -56,54 +59,6 @@ #define TRANSPARENT_I2C_EN (1 << 7) #define HOST_EN (1 << 0) -/* ISP1301 USB transceiver I2C registers */ -#define ISP1301_MODE_CONTROL_1 0x04 /* u8 read, set, +1 clear */ - -#define MC1_SPEED_REG (1 << 0) -#define MC1_SUSPEND_REG (1 << 1) -#define MC1_DAT_SE0 (1 << 2) -#define MC1_TRANSPARENT (1 << 3) -#define MC1_BDIS_ACON_EN (1 << 4) -#define MC1_OE_INT_EN (1 << 5) -#define MC1_UART_EN (1 << 6) -#define MC1_MASK 0x7f - -#define ISP1301_MODE_CONTROL_2 0x12 /* u8 read, set, +1 clear */ - -#define MC2_GLOBAL_PWR_DN (1 << 0) -#define MC2_SPD_SUSP_CTRL (1 << 1) -#define MC2_BI_DI (1 << 2) -#define MC2_TRANSP_BDIR0 (1 << 3) -#define MC2_TRANSP_BDIR1 (1 << 4) -#define MC2_AUDIO_EN (1 << 5) -#define MC2_PSW_EN (1 << 6) -#define MC2_EN2V7 (1 << 7) - -#define ISP1301_OTG_CONTROL_1 0x06 /* u8 read, set, +1 clear */ -# define OTG1_DP_PULLUP (1 << 0) -# define OTG1_DM_PULLUP (1 << 1) -# define OTG1_DP_PULLDOWN (1 << 2) -# define OTG1_DM_PULLDOWN (1 << 3) -# define OTG1_ID_PULLDOWN (1 << 4) -# define OTG1_VBUS_DRV (1 << 5) -# define OTG1_VBUS_DISCHRG (1 << 6) -# define OTG1_VBUS_CHRG (1 << 7) -#define ISP1301_OTG_STATUS 0x10 /* u8 readonly */ -# define OTG_B_SESS_END (1 << 6) -# define OTG_B_SESS_VLD (1 << 7) - -#define ISP1301_I2C_ADDR 0x2C - -#define ISP1301_I2C_MODE_CONTROL_1 0x4 -#define ISP1301_I2C_MODE_CONTROL_2 0x12 -#define ISP1301_I2C_OTG_CONTROL_1 0x6 -#define ISP1301_I2C_OTG_CONTROL_2 0x10 -#define ISP1301_I2C_INTERRUPT_SOURCE 0x8 -#define ISP1301_I2C_INTERRUPT_LATCH 0xA -#define ISP1301_I2C_INTERRUPT_FALLING 0xC -#define ISP1301_I2C_INTERRUPT_RISING 0xE -#define ISP1301_I2C_REG_CLEAR_ADDR 1 - /* On LPC32xx, those are undefined */ #ifndef start_int_set_falling_edge #define start_int_set_falling_edge(irq) @@ -113,42 +68,12 @@ #define start_int_umask(irq) #endif -static struct i2c_driver isp1301_driver; static struct i2c_client *isp1301_i2c_client; extern int usb_disabled(void); -extern int ocpi_enable(void); static struct clk *usb_clk; -static const unsigned short normal_i2c[] = - { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END }; - -static int isp1301_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - return 0; -} - -static int isp1301_remove(struct i2c_client *client) -{ - return 0; -} - -static const struct i2c_device_id isp1301_id[] = { - { "isp1301_nxp", 0 }, - { } -}; - -static struct i2c_driver isp1301_driver = { - .driver = { - .name = "isp1301_nxp", - }, - .probe = isp1301_probe, - .remove = isp1301_remove, - .id_table = isp1301_id, -}; - static void isp1301_configure_pnx4008(void) { /* PNX4008 only supports DAT_SE0 USB mode */ @@ -220,7 +145,7 @@ static void isp1301_configure_lpc32xx(void) ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR, ~0); /* Enable usb_need_clk clock after transceiver is initialized */ - __raw_writel((__raw_readl(USB_CTRL) | (1 << 22)), USB_CTRL); + __raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL); printk(KERN_INFO "ISP1301 Vendor ID : 0x%04x\n", i2c_smbus_read_word_data(isp1301_i2c_client, 0x00)); @@ -372,65 +297,55 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) struct usb_hcd *hcd = 0; struct ohci_hcd *ohci; const struct hc_driver *driver = &ohci_nxp_hc_driver; - struct i2c_adapter *i2c_adap; - struct i2c_board_info i2c_info; - + struct resource *res; int ret = 0, irq; + struct device_node *isp1301_node; - dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (nxp)\n", hcd_name); - if (usb_disabled()) { - err("USB is disabled"); - ret = -ENODEV; - goto out; + if (pdev->dev.of_node) { + isp1301_node = of_parse_phandle(pdev->dev.of_node, + "transceiver", 0); + } else { + isp1301_node = NULL; } - if (pdev->num_resources != 2 - || pdev->resource[0].flags != IORESOURCE_MEM - || pdev->resource[1].flags != IORESOURCE_IRQ) { - err("Invalid resource configuration"); - ret = -ENODEV; + isp1301_i2c_client = isp1301_get_client(isp1301_node); + if (!isp1301_i2c_client) { + ret = -EPROBE_DEFER; goto out; } - /* Enable AHB slave USB clock, needed for further USB clock control */ - __raw_writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL); + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; - ret = i2c_add_driver(&isp1301_driver); - if (ret < 0) { - err("failed to add ISP1301 driver"); - goto out; - } - i2c_adap = i2c_get_adapter(2); - memset(&i2c_info, 0, sizeof(struct i2c_board_info)); - strlcpy(i2c_info.type, "isp1301_nxp", I2C_NAME_SIZE); - isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info, - normal_i2c, NULL); - i2c_put_adapter(i2c_adap); - if (!isp1301_i2c_client) { - err("failed to connect I2C to ISP1301 USB Transceiver"); + dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (nxp)\n", hcd_name); + if (usb_disabled()) { + dev_err(&pdev->dev, "USB is disabled\n"); ret = -ENODEV; - goto out_i2c_driver; + goto out; } + /* Enable AHB slave USB clock, needed for further USB clock control */ + __raw_writel(USB_SLAVE_HCLK_EN | PAD_CONTROL_LAST_DRIVEN, USB_CTRL); + isp1301_configure(); /* Enable USB PLL */ usb_clk = clk_get(&pdev->dev, "ck_pll5"); if (IS_ERR(usb_clk)) { - err("failed to acquire USB PLL"); + dev_err(&pdev->dev, "failed to acquire USB PLL\n"); ret = PTR_ERR(usb_clk); goto out1; } ret = clk_enable(usb_clk); if (ret < 0) { - err("failed to start USB PLL"); + dev_err(&pdev->dev, "failed to start USB PLL\n"); goto out2; } ret = clk_set_rate(usb_clk, 48000); if (ret < 0) { - err("failed to set USB clock rate"); + dev_err(&pdev->dev, "failed to set USB clock rate\n"); goto out3; } @@ -442,9 +357,9 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) != USB_CLOCK_MASK) ; - hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev)); + hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { - err("Failed to allocate HC buffer"); + dev_err(&pdev->dev, "Failed to allocate HC buffer\n"); ret = -ENOMEM; goto out3; } @@ -452,14 +367,21 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) /* Set all USB bits in the Start Enable register */ nxp_set_usb_bits(); - hcd->rsrc_start = pdev->resource[0].start; - hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - dev_dbg(&pdev->dev, "request_mem_region failed\n"); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Failed to get MEM resource\n"); + ret = -ENOMEM; + goto out4; + } + + hcd->regs = devm_request_and_ioremap(&pdev->dev, res); + if (!hcd->regs) { + dev_err(&pdev->dev, "Failed to devm_request_and_ioremap\n"); ret = -ENOMEM; goto out4; } - hcd->regs = (void __iomem *)pdev->resource[0].start; + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -486,10 +408,7 @@ out3: out2: clk_put(usb_clk); out1: - i2c_unregister_device(isp1301_i2c_client); isp1301_i2c_client = NULL; -out_i2c_driver: - i2c_del_driver(&isp1301_driver); out: return ret; } @@ -507,7 +426,6 @@ static int usb_hcd_nxp_remove(struct platform_device *pdev) clk_put(usb_clk); i2c_unregister_device(isp1301_i2c_client); isp1301_i2c_client = NULL; - i2c_del_driver(&isp1301_driver); platform_set_drvdata(pdev, NULL); @@ -517,10 +435,19 @@ static int usb_hcd_nxp_remove(struct platform_device *pdev) /* work with hotplug and coldplug */ MODULE_ALIAS("platform:usb-ohci"); +#ifdef CONFIG_OF +static const struct of_device_id usb_hcd_nxp_match[] = { + { .compatible = "nxp,ohci-nxp" }, + {}, +}; +MODULE_DEVICE_TABLE(of, usb_hcd_nxp_match); +#endif + static struct platform_driver usb_hcd_nxp_driver = { .driver = { .name = "usb-ohci", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(usb_hcd_nxp_match), }, .probe = usb_hcd_nxp_probe, .remove = usb_hcd_nxp_remove, diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index ec5c6791c8b4..670c7059c9ae 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -93,13 +93,13 @@ static int __devinit ohci_platform_probe(struct platform_device *dev) irq = platform_get_irq(dev, 0); if (irq < 0) { - pr_err("no irq provieded"); + pr_err("no irq provided"); return irq; } res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res_mem) { - pr_err("no memory recourse provieded"); + pr_err("no memory recourse provided"); return -ENXIO; } diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c index f13d08f94d6b..148d27d6a67c 100644 --- a/drivers/usb/host/ohci-pnx8550.c +++ b/drivers/usb/host/ohci-pnx8550.c @@ -157,7 +157,8 @@ ohci_pnx8550_start (struct usb_hcd *hcd) return ret; if ((ret = ohci_run (ohci)) < 0) { - err ("can't start %s", hcd->self.bus_name); + dev_err(hcd->self.controller, "can't start %s", + hcd->self.bus_name); ohci_stop (hcd); return ret; } diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index d24cc89de16f..e27d5ae2b9eb 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -29,7 +29,8 @@ ohci_ppc_of_start(struct usb_hcd *hcd) return ret; if ((ret = ohci_run(ohci)) < 0) { - err("can't start %s", ohci_to_hcd(ohci)->self.bus_name); + dev_err(hcd->self.controller, "can't start %s\n", + hcd->self.bus_name); ohci_stop(hcd); return ret; } @@ -236,7 +237,7 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match); #if !defined(CONFIG_USB_OHCI_HCD_PPC_OF_BE) && \ !defined(CONFIG_USB_OHCI_HCD_PPC_OF_LE) -#error "No endianess selected for ppc-of-ohci" +#error "No endianness selected for ppc-of-ohci" #endif diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c index 1514b7067470..185c39ed81b7 100644 --- a/drivers/usb/host/ohci-ppc-soc.c +++ b/drivers/usb/host/ohci-ppc-soc.c @@ -130,7 +130,8 @@ ohci_ppc_soc_start(struct usb_hcd *hcd) return ret; if ((ret = ohci_run(ohci)) < 0) { - err("can't start %s", ohci_to_hcd(ohci)->self.bus_name); + dev_err(hcd->self.controller, "can't start %s\n", + hcd->self.bus_name); ohci_stop(hcd); return ret; } diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c index 6fd4fa1f19bb..2ee1d8d713d2 100644 --- a/drivers/usb/host/ohci-ps3.c +++ b/drivers/usb/host/ohci-ps3.c @@ -45,7 +45,8 @@ static int __devinit ps3_ohci_hc_start(struct usb_hcd *hcd) result = ohci_run(ohci); if (result < 0) { - err("can't start %s", hcd->self.bus_name); + dev_err(hcd->self.controller, "can't start %s\n", + hcd->self.bus_name); ohci_stop(hcd); } diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index c31b2815be1c..e1a3cc6d28dc 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -419,7 +419,8 @@ ohci_pxa27x_start (struct usb_hcd *hcd) return ret; if ((ret = ohci_run (ohci)) < 0) { - err ("can't start %s", hcd->self.bus_name); + dev_err(hcd->self.controller, "can't start %s", + hcd->self.bus_name); ohci_stop (hcd); return ret; } diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 56dcf069246d..664c869eb096 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -420,7 +420,8 @@ ohci_s3c2410_start(struct usb_hcd *hcd) ret = ohci_run(ohci); if (ret < 0) { - err("can't start %s", hcd->self.bus_name); + dev_err(hcd->self.controller, "can't start %s\n", + hcd->self.bus_name); ohci_stop(hcd); return ret; } diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index e1004fb37bd9..b6cc92520924 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c @@ -46,7 +46,7 @@ static void dump_hci_status(struct usb_hcd *hcd, const char *label) { unsigned long status = sa1111_readl(hcd->regs + USB_STATUS); - dbg("%s USB_STATUS = { %s%s%s%s%s}", label, + printk(KERN_DEBUG "%s USB_STATUS = { %s%s%s%s%s}\n", label, ((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""), ((status & USB_STATUS_IRQHCIBUFFACC) ? "IRQHCIBUFFACC " : ""), ((status & USB_STATUS_NIRQHCIM) ? "" : "IRQHCIM "), @@ -193,7 +193,7 @@ static int ohci_hcd_sa1111_probe(struct sa1111_dev *dev) hcd->rsrc_len = resource_size(&dev->res); if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - dbg("request_mem_region failed"); + dev_dbg(&dev->dev, "request_mem_region failed\n"); ret = -EBUSY; goto err1; } diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c index 84686d90805b..76a20c278362 100644 --- a/drivers/usb/host/ohci-sh.c +++ b/drivers/usb/host/ohci-sh.c @@ -88,20 +88,20 @@ static int ohci_hcd_sh_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { - err("platform_get_resource error."); + dev_err(&pdev->dev, "platform_get_resource error.\n"); return -ENODEV; } irq = platform_get_irq(pdev, 0); if (irq < 0) { - err("platform_get_irq error."); + dev_err(&pdev->dev, "platform_get_irq error.\n"); return -ENODEV; } /* initialize hcd */ hcd = usb_create_hcd(&ohci_sh_hc_driver, &pdev->dev, (char *)hcd_name); if (!hcd) { - err("Failed to create hcd"); + dev_err(&pdev->dev, "Failed to create hcd\n"); return -ENOMEM; } @@ -110,7 +110,7 @@ static int ohci_hcd_sh_probe(struct platform_device *pdev) hcd->rsrc_len = resource_size(res); ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret != 0) { - err("Failed to add hcd"); + dev_err(&pdev->dev, "Failed to add hcd\n"); usb_put_hcd(hcd); return ret; } diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c index 95c16489e883..fc7305ee3c9c 100644 --- a/drivers/usb/host/ohci-spear.c +++ b/drivers/usb/host/ohci-spear.c @@ -14,6 +14,7 @@ #include <linux/signal.h> #include <linux/platform_device.h> #include <linux/clk.h> +#include <linux/of.h> struct spear_ohci { struct ohci_hcd ohci; @@ -24,12 +25,12 @@ struct spear_ohci { static void spear_start_ohci(struct spear_ohci *ohci) { - clk_enable(ohci->clk); + clk_prepare_enable(ohci->clk); } static void spear_stop_ohci(struct spear_ohci *ohci) { - clk_disable(ohci->clk); + clk_disable_unprepare(ohci->clk); } static int __devinit ohci_spear_start(struct usb_hcd *hcd) @@ -90,6 +91,8 @@ static const struct hc_driver ohci_spear_hc_driver = { .start_port_reset = ohci_start_port_reset, }; +static u64 spear_ohci_dma_mask = DMA_BIT_MASK(32); + static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) { const struct hc_driver *driver = &ohci_spear_hc_driver; @@ -98,11 +101,8 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) struct spear_ohci *ohci_p; struct resource *res; int retval, irq; - int *pdata = pdev->dev.platform_data; char clk_name[20] = "usbh_clk"; - - if (pdata == NULL) - return -EFAULT; + static int instance = -1; irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -110,8 +110,22 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) goto fail_irq_get; } - if (*pdata >= 0) - sprintf(clk_name, "usbh.%01d_clk", *pdata); + /* + * Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &spear_ohci_dma_mask; + + /* + * Increment the device instance, when probing via device-tree + */ + if (pdev->id < 0) + instance++; + else + instance = pdev->id; + sprintf(clk_name, "usbh.%01d_clk", instance); usbh_clk = clk_get(NULL, clk_name); if (IS_ERR(usbh_clk)) { @@ -222,6 +236,11 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev) } #endif +static struct of_device_id spear_ohci_id_table[] __devinitdata = { + { .compatible = "st,spear600-ohci", }, + { }, +}; + /* Driver definition to register with the platform bus */ static struct platform_driver spear_ohci_hcd_driver = { .probe = spear_ohci_hcd_drv_probe, @@ -233,6 +252,7 @@ static struct platform_driver spear_ohci_hcd_driver = { .driver = { .owner = THIS_MODULE, .name = "spear-ohci", + .of_match_table = of_match_ptr(spear_ohci_id_table), }, }; diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c deleted file mode 100644 index 5ba18595d6f7..000000000000 --- a/drivers/usb/host/ohci-ssb.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Sonics Silicon Backplane - * Broadcom USB-core OHCI driver - * - * Copyright 2007 Michael Buesch <m@bues.ch> - * - * Derived from the OHCI-PCI driver - * Copyright 1999 Roman Weissgaerber - * Copyright 2000-2002 David Brownell - * Copyright 1999 Linus Torvalds - * Copyright 1999 Gregory P. Smith - * - * Derived from the USBcore related parts of Broadcom-SB - * Copyright 2005 Broadcom Corporation - * - * Licensed under the GNU/GPL. See COPYING for details. - */ -#include <linux/ssb/ssb.h> - - -#define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29) - -struct ssb_ohci_device { - struct ohci_hcd ohci; /* _must_ be at the beginning. */ - - u32 enable_flags; -}; - -static inline -struct ssb_ohci_device *hcd_to_ssb_ohci(struct usb_hcd *hcd) -{ - return (struct ssb_ohci_device *)(hcd->hcd_priv); -} - - -static int ssb_ohci_reset(struct usb_hcd *hcd) -{ - struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd); - struct ohci_hcd *ohci = &ohcidev->ohci; - int err; - - ohci_hcd_init(ohci); - err = ohci_init(ohci); - - return err; -} - -static int ssb_ohci_start(struct usb_hcd *hcd) -{ - struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd); - struct ohci_hcd *ohci = &ohcidev->ohci; - int err; - - err = ohci_run(ohci); - if (err < 0) { - ohci_err(ohci, "can't start\n"); - ohci_stop(hcd); - } - - return err; -} - -static const struct hc_driver ssb_ohci_hc_driver = { - .description = "ssb-usb-ohci", - .product_desc = "SSB OHCI Controller", - .hcd_priv_size = sizeof(struct ssb_ohci_device), - - .irq = ohci_irq, - .flags = HCD_MEMORY | HCD_USB11, - - .reset = ssb_ohci_reset, - .start = ssb_ohci_start, - .stop = ohci_stop, - .shutdown = ohci_shutdown, - - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - - .get_frame_number = ohci_get_frame, - - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - - .start_port_reset = ohci_start_port_reset, -}; - -static void ssb_ohci_detach(struct ssb_device *dev) -{ - struct usb_hcd *hcd = ssb_get_drvdata(dev); - - if (hcd->driver->shutdown) - hcd->driver->shutdown(hcd); - usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); - ssb_device_disable(dev, 0); -} - -static int ssb_ohci_attach(struct ssb_device *dev) -{ - struct ssb_ohci_device *ohcidev; - struct usb_hcd *hcd; - int err = -ENOMEM; - u32 tmp, flags = 0; - - if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) || - dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32))) - return -EOPNOTSUPP; - - if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) { - /* Put the device into host-mode. */ - flags |= SSB_OHCI_TMSLOW_HOSTMODE; - ssb_device_enable(dev, flags); - } else if (dev->id.coreid == SSB_DEV_USB20_HOST) { - /* - * USB 2.0 special considerations: - * - * In addition to the standard SSB reset sequence, the Host - * Control Register must be programmed to bring the USB core - * and various phy components out of reset. - */ - ssb_device_enable(dev, 0); - ssb_write32(dev, 0x200, 0x7ff); - - /* Change Flush control reg */ - tmp = ssb_read32(dev, 0x400); - tmp &= ~8; - ssb_write32(dev, 0x400, tmp); - tmp = ssb_read32(dev, 0x400); - - /* Change Shim control reg */ - tmp = ssb_read32(dev, 0x304); - tmp &= ~0x100; - ssb_write32(dev, 0x304, tmp); - tmp = ssb_read32(dev, 0x304); - - udelay(1); - - /* Work around for 5354 failures */ - if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) { - /* Change syn01 reg */ - tmp = 0x00fe00fe; - ssb_write32(dev, 0x894, tmp); - - /* Change syn03 reg */ - tmp = ssb_read32(dev, 0x89c); - tmp |= 0x1; - ssb_write32(dev, 0x89c, tmp); - } - } else - ssb_device_enable(dev, 0); - - hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev, - dev_name(dev->dev)); - if (!hcd) - goto err_dev_disable; - ohcidev = hcd_to_ssb_ohci(hcd); - ohcidev->enable_flags = flags; - - tmp = ssb_read32(dev, SSB_ADMATCH0); - hcd->rsrc_start = ssb_admatch_base(tmp); - hcd->rsrc_len = ssb_admatch_size(tmp); - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) - goto err_put_hcd; - err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED); - if (err) - goto err_iounmap; - - ssb_set_drvdata(dev, hcd); - - return err; - -err_iounmap: - iounmap(hcd->regs); -err_put_hcd: - usb_put_hcd(hcd); -err_dev_disable: - ssb_device_disable(dev, flags); - return err; -} - -static int ssb_ohci_probe(struct ssb_device *dev, - const struct ssb_device_id *id) -{ - int err; - u16 chipid_top; - - /* USBcores are only connected on embedded devices. */ - chipid_top = (dev->bus->chip_id & 0xFF00); - if (chipid_top != 0x4700 && chipid_top != 0x5300) - return -ENODEV; - - /* TODO: Probably need checks here; is the core connected? */ - - if (usb_disabled()) - return -ENODEV; - - /* We currently always attach SSB_DEV_USB11_HOSTDEV - * as HOST OHCI. If we want to attach it as Client device, - * we must branch here and call into the (yet to - * be written) Client mode driver. Same for remove(). */ - - err = ssb_ohci_attach(dev); - - return err; -} - -static void ssb_ohci_remove(struct ssb_device *dev) -{ - ssb_ohci_detach(dev); -} - -#ifdef CONFIG_PM - -static int ssb_ohci_suspend(struct ssb_device *dev, pm_message_t state) -{ - ssb_device_disable(dev, 0); - - return 0; -} - -static int ssb_ohci_resume(struct ssb_device *dev) -{ - struct usb_hcd *hcd = ssb_get_drvdata(dev); - struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd); - - ssb_device_enable(dev, ohcidev->enable_flags); - - ohci_finish_controller_resume(hcd); - return 0; -} - -#else /* !CONFIG_PM */ -#define ssb_ohci_suspend NULL -#define ssb_ohci_resume NULL -#endif /* CONFIG_PM */ - -static const struct ssb_device_id ssb_ohci_table[] = { - SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV), - SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV), - SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), - SSB_DEVTABLE_END -}; -MODULE_DEVICE_TABLE(ssb, ssb_ohci_table); - -static struct ssb_driver ssb_ohci_driver = { - .name = KBUILD_MODNAME, - .id_table = ssb_ohci_table, - .probe = ssb_ohci_probe, - .remove = ssb_ohci_remove, - .suspend = ssb_ohci_suspend, - .resume = ssb_ohci_resume, -}; diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index 120bfe6ede38..60c2b0722f2e 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c @@ -140,7 +140,8 @@ static int ohci_tmio_start(struct usb_hcd *hcd) return ret; if ((ret = ohci_run(ohci)) < 0) { - err("can't start %s", hcd->self.bus_name); + dev_err(hcd->self.controller, "can't start %s\n", + hcd->self.bus_name); ohci_stop(hcd); return ret; } diff --git a/drivers/usb/host/ohci-xls.c b/drivers/usb/host/ohci-xls.c index a2247867af86..41e378f17c66 100644 --- a/drivers/usb/host/ohci-xls.c +++ b/drivers/usb/host/ohci-xls.c @@ -88,7 +88,8 @@ static int __devinit ohci_xls_start(struct usb_hcd *hcd) ohci = hcd_to_ohci(hcd); ret = ohci_run(ohci); if (ret < 0) { - err("can't start %s", hcd->self.bus_name); + dev_err(hcd->self.controller, "can't start %s\n", + hcd->self.bus_name); ohci_stop(hcd); return ret; } diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 3b38030b02a8..4f0f0339532f 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -1399,8 +1399,8 @@ static struct ehci_qh *qh_make(struct oxu_hcd *oxu, * But interval 1 scheduling is simpler, and * includes high bandwidth. */ - dbg("intr period %d uframes, NYET!", - urb->interval); + oxu_dbg(oxu, "intr period %d uframes, NYET!\n", + urb->interval); goto done; } } else { @@ -1471,7 +1471,7 @@ static struct ehci_qh *qh_make(struct oxu_hcd *oxu, } break; default: - dbg("bogus dev %p speed %d", urb->dev, urb->dev->speed); + oxu_dbg(oxu, "bogus dev %p speed %d\n", urb->dev, urb->dev->speed); done: qh_put(qh); return NULL; @@ -2307,7 +2307,7 @@ restart: qh_put(temp.qh); break; default: - dbg("corrupt type %d frame %d shadow %p", + oxu_dbg(oxu, "corrupt type %d frame %d shadow %p\n", type, frame, q.ptr); q.ptr = NULL; } @@ -2991,8 +2991,9 @@ static int oxu_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) /* shouldn't happen often, but ... * FIXME kill those tds' urbs */ - err("can't reschedule qh %p, err %d", - qh, status); + dev_err(hcd->self.controller, + "can't reschedule qh %p, err %d\n", qh, + status); } return status; } diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 32dada8c8b4f..df0828cb2aa3 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -9,6 +9,7 @@ */ #include <linux/types.h> +#include <linux/kconfig.h> #include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> @@ -712,12 +713,28 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done, return -ETIMEDOUT; } -bool usb_is_intel_switchable_xhci(struct pci_dev *pdev) +#define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI 0x8C31 + +bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev) { return pdev->class == PCI_CLASS_SERIAL_USB_XHCI && pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI; } + +/* The Intel Lynx Point chipset also has switchable ports. */ +bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev) +{ + return pdev->class == PCI_CLASS_SERIAL_USB_XHCI && + pdev->vendor == PCI_VENDOR_ID_INTEL && + pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI; +} + +bool usb_is_intel_switchable_xhci(struct pci_dev *pdev) +{ + return usb_is_intel_ppt_switchable_xhci(pdev) || + usb_is_intel_lpt_switchable_xhci(pdev); +} EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci); /* @@ -742,6 +759,19 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) { u32 ports_available; + /* Don't switchover the ports if the user hasn't compiled the xHCI + * driver. Otherwise they will see "dead" USB ports that don't power + * the devices. + */ + if (!IS_ENABLED(CONFIG_USB_XHCI_HCD)) { + dev_warn(&xhci_pdev->dev, + "CONFIG_USB_XHCI_HCD is turned off, " + "defaulting to EHCI.\n"); + dev_warn(&xhci_pdev->dev, + "USB 3.0 devices will work at USB 2.0 speeds.\n"); + return; + } + ports_available = 0xffffffff; /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable * Register, to turn on SuperSpeed terminations for all diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 2bf1320dc9c3..c868be65e763 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -401,7 +401,7 @@ static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb) if (r8a66597->address_map & (1 << addr)) continue; - dbg("alloc_address: r8a66597_addr=%d", addr); + dev_dbg(&urb->dev->dev, "alloc_address: r8a66597_addr=%d\n", addr); r8a66597->address_map |= 1 << addr; if (make_r8a66597_device(r8a66597, urb, addr) < 0) @@ -426,7 +426,7 @@ static void free_usb_address(struct r8a66597 *r8a66597, if (!dev) return; - dbg("free_addr: addr=%d", dev->address); + dev_dbg(&dev->udev->dev, "free_addr: addr=%d\n", dev->address); dev->state = USB_STATE_DEFAULT; r8a66597->address_map &= ~(1 << dev->address); @@ -819,7 +819,7 @@ static void enable_r8a66597_pipe(struct r8a66597 *r8a66597, struct urb *urb, struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb); struct r8a66597_pipe *pipe = hep->hcpriv; - dbg("enable_pipe:"); + dev_dbg(&dev->udev->dev, "enable_pipe:\n"); pipe->info = *info; set_pipe_reg_addr(pipe, R8A66597_PIPE_NO_DMA); @@ -898,7 +898,7 @@ static void disable_r8a66597_pipe_all(struct r8a66597 *r8a66597, force_dequeue(r8a66597, pipenum, dev->address); } - dbg("disable_pipe"); + dev_dbg(&dev->udev->dev, "disable_pipe\n"); r8a66597->dma_map &= ~(dev->dma_map); dev->dma_map = 0; @@ -2264,7 +2264,7 @@ static int r8a66597_bus_suspend(struct usb_hcd *hcd) struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); int port; - dbg("%s", __func__); + dev_dbg(&r8a66597->device0.udev->dev, "%s\n", __func__); for (port = 0; port < r8a66597->max_root_hub; port++) { struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; @@ -2273,7 +2273,7 @@ static int r8a66597_bus_suspend(struct usb_hcd *hcd) if (!(rh->port & USB_PORT_STAT_ENABLE)) continue; - dbg("suspend port = %d", port); + dev_dbg(&rh->dev->udev->dev, "suspend port = %d\n", port); r8a66597_bclr(r8a66597, UACT, dvstctr_reg); /* suspend */ rh->port |= USB_PORT_STAT_SUSPEND; @@ -2295,7 +2295,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd) struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); int port; - dbg("%s", __func__); + dev_dbg(&r8a66597->device0.udev->dev, "%s\n", __func__); for (port = 0; port < r8a66597->max_root_hub; port++) { struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; @@ -2304,7 +2304,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd) if (!(rh->port & USB_PORT_STAT_SUSPEND)) continue; - dbg("resume port = %d", port); + dev_dbg(&rh->dev->udev->dev, "resume port = %d\n", port); rh->port &= ~USB_PORT_STAT_SUSPEND; rh->port |= USB_PORT_STAT_C_SUSPEND << 16; r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg); @@ -2360,7 +2360,7 @@ static int r8a66597_suspend(struct device *dev) struct r8a66597 *r8a66597 = dev_get_drvdata(dev); int port; - dbg("%s", __func__); + dev_dbg(dev, "%s\n", __func__); disable_controller(r8a66597); @@ -2378,7 +2378,7 @@ static int r8a66597_resume(struct device *dev) struct r8a66597 *r8a66597 = dev_get_drvdata(dev); struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); - dbg("%s", __func__); + dev_dbg(dev, "%s\n", __func__); enable_controller(r8a66597); usb_root_hub_lost_power(hcd->self.root_hub); diff --git a/drivers/usb/host/ssb-hcd.c b/drivers/usb/host/ssb-hcd.c new file mode 100644 index 000000000000..c2a29faba076 --- /dev/null +++ b/drivers/usb/host/ssb-hcd.c @@ -0,0 +1,280 @@ +/* + * Sonics Silicon Backplane + * Broadcom USB-core driver (SSB bus glue) + * + * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de> + * + * Based on ssb-ohci driver + * Copyright 2007 Michael Buesch <m@bues.ch> + * + * Derived from the OHCI-PCI driver + * Copyright 1999 Roman Weissgaerber + * Copyright 2000-2002 David Brownell + * Copyright 1999 Linus Torvalds + * Copyright 1999 Gregory P. Smith + * + * Derived from the USBcore related parts of Broadcom-SB + * Copyright 2005-2011 Broadcom Corporation + * + * Licensed under the GNU/GPL. See COPYING for details. + */ +#include <linux/ssb/ssb.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/usb/ehci_pdriver.h> +#include <linux/usb/ohci_pdriver.h> + +MODULE_AUTHOR("Hauke Mehrtens"); +MODULE_DESCRIPTION("Common USB driver for SSB Bus"); +MODULE_LICENSE("GPL"); + +#define SSB_HCD_TMSLOW_HOSTMODE (1 << 29) + +struct ssb_hcd_device { + struct platform_device *ehci_dev; + struct platform_device *ohci_dev; + + u32 enable_flags; +}; + +static void __devinit ssb_hcd_5354wa(struct ssb_device *dev) +{ +#ifdef CONFIG_SSB_DRIVER_MIPS + /* Work around for 5354 failures */ + if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) { + /* Change syn01 reg */ + ssb_write32(dev, 0x894, 0x00fe00fe); + + /* Change syn03 reg */ + ssb_write32(dev, 0x89c, ssb_read32(dev, 0x89c) | 0x1); + } +#endif +} + +static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev) +{ + if (dev->id.coreid == SSB_DEV_USB20_HOST) { + /* + * USB 2.0 special considerations: + * + * In addition to the standard SSB reset sequence, the Host + * Control Register must be programmed to bring the USB core + * and various phy components out of reset. + */ + ssb_write32(dev, 0x200, 0x7ff); + + /* Change Flush control reg */ + ssb_write32(dev, 0x400, ssb_read32(dev, 0x400) & ~8); + ssb_read32(dev, 0x400); + + /* Change Shim control reg */ + ssb_write32(dev, 0x304, ssb_read32(dev, 0x304) & ~0x100); + ssb_read32(dev, 0x304); + + udelay(1); + + ssb_hcd_5354wa(dev); + } +} + +/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ +static u32 __devinit ssb_hcd_init_chip(struct ssb_device *dev) +{ + u32 flags = 0; + + if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) + /* Put the device into host-mode. */ + flags |= SSB_HCD_TMSLOW_HOSTMODE; + + ssb_device_enable(dev, flags); + + ssb_hcd_usb20wa(dev); + + return flags; +} + +static const struct usb_ehci_pdata ehci_pdata = { +}; + +static const struct usb_ohci_pdata ohci_pdata = { +}; + +static struct platform_device * __devinit +ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len) +{ + struct platform_device *hci_dev; + struct resource hci_res[2]; + int ret = -ENOMEM; + + memset(hci_res, 0, sizeof(hci_res)); + + hci_res[0].start = addr; + hci_res[0].end = hci_res[0].start + len - 1; + hci_res[0].flags = IORESOURCE_MEM; + + hci_res[1].start = dev->irq; + hci_res[1].flags = IORESOURCE_IRQ; + + hci_dev = platform_device_alloc(ohci ? "ohci-platform" : + "ehci-platform" , 0); + if (!hci_dev) + return NULL; + + hci_dev->dev.parent = dev->dev; + hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask; + + ret = platform_device_add_resources(hci_dev, hci_res, + ARRAY_SIZE(hci_res)); + if (ret) + goto err_alloc; + if (ohci) + ret = platform_device_add_data(hci_dev, &ohci_pdata, + sizeof(ohci_pdata)); + else + ret = platform_device_add_data(hci_dev, &ehci_pdata, + sizeof(ehci_pdata)); + if (ret) + goto err_alloc; + ret = platform_device_add(hci_dev); + if (ret) + goto err_alloc; + + return hci_dev; + +err_alloc: + platform_device_put(hci_dev); + return ERR_PTR(ret); +} + +static int __devinit ssb_hcd_probe(struct ssb_device *dev, + const struct ssb_device_id *id) +{ + int err, tmp; + int start, len; + u16 chipid_top; + u16 coreid = dev->id.coreid; + struct ssb_hcd_device *usb_dev; + + /* USBcores are only connected on embedded devices. */ + chipid_top = (dev->bus->chip_id & 0xFF00); + if (chipid_top != 0x4700 && chipid_top != 0x5300) + return -ENODEV; + + /* TODO: Probably need checks here; is the core connected? */ + + if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) || + dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32))) + return -EOPNOTSUPP; + + usb_dev = kzalloc(sizeof(struct ssb_hcd_device), GFP_KERNEL); + if (!usb_dev) + return -ENOMEM; + + /* We currently always attach SSB_DEV_USB11_HOSTDEV + * as HOST OHCI. If we want to attach it as Client device, + * we must branch here and call into the (yet to + * be written) Client mode driver. Same for remove(). */ + usb_dev->enable_flags = ssb_hcd_init_chip(dev); + + tmp = ssb_read32(dev, SSB_ADMATCH0); + + start = ssb_admatch_base(tmp); + len = (coreid == SSB_DEV_USB20_HOST) ? 0x800 : ssb_admatch_size(tmp); + usb_dev->ohci_dev = ssb_hcd_create_pdev(dev, true, start, len); + if (IS_ERR(usb_dev->ohci_dev)) { + err = PTR_ERR(usb_dev->ohci_dev); + goto err_free_usb_dev; + } + + if (coreid == SSB_DEV_USB20_HOST) { + start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */ + usb_dev->ehci_dev = ssb_hcd_create_pdev(dev, false, start, len); + if (IS_ERR(usb_dev->ehci_dev)) { + err = PTR_ERR(usb_dev->ehci_dev); + goto err_unregister_ohci_dev; + } + } + + ssb_set_drvdata(dev, usb_dev); + return 0; + +err_unregister_ohci_dev: + platform_device_unregister(usb_dev->ohci_dev); +err_free_usb_dev: + kfree(usb_dev); + return err; +} + +static void __devexit ssb_hcd_remove(struct ssb_device *dev) +{ + struct ssb_hcd_device *usb_dev = ssb_get_drvdata(dev); + struct platform_device *ohci_dev = usb_dev->ohci_dev; + struct platform_device *ehci_dev = usb_dev->ehci_dev; + + if (ohci_dev) + platform_device_unregister(ohci_dev); + if (ehci_dev) + platform_device_unregister(ehci_dev); + + ssb_device_disable(dev, 0); +} + +static void __devexit ssb_hcd_shutdown(struct ssb_device *dev) +{ + ssb_device_disable(dev, 0); +} + +#ifdef CONFIG_PM + +static int ssb_hcd_suspend(struct ssb_device *dev, pm_message_t state) +{ + ssb_device_disable(dev, 0); + + return 0; +} + +static int ssb_hcd_resume(struct ssb_device *dev) +{ + struct ssb_hcd_device *usb_dev = ssb_get_drvdata(dev); + + ssb_device_enable(dev, usb_dev->enable_flags); + + return 0; +} + +#else /* !CONFIG_PM */ +#define ssb_hcd_suspend NULL +#define ssb_hcd_resume NULL +#endif /* CONFIG_PM */ + +static const struct ssb_device_id ssb_hcd_table[] __devinitconst = { + SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV), + SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV), + SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), + SSB_DEVTABLE_END +}; +MODULE_DEVICE_TABLE(ssb, ssb_hcd_table); + +static struct ssb_driver ssb_hcd_driver = { + .name = KBUILD_MODNAME, + .id_table = ssb_hcd_table, + .probe = ssb_hcd_probe, + .remove = __devexit_p(ssb_hcd_remove), + .shutdown = ssb_hcd_shutdown, + .suspend = ssb_hcd_suspend, + .resume = ssb_hcd_resume, +}; + +static int __init ssb_hcd_init(void) +{ + return ssb_driver_register(&ssb_hcd_driver); +} +module_init(ssb_hcd_init); + +static void __exit ssb_hcd_exit(void) +{ + ssb_driver_unregister(&ssb_hcd_driver); +} +module_exit(ssb_hcd_exit); diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 673ad120c43e..89850a82d51b 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -558,6 +558,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, xhci_dbg(xhci, "Resume USB2 port %d\n", wIndex + 1); bus_state->resume_done[wIndex] = 0; + clear_bit(wIndex, &bus_state->resuming_ports); xhci_set_link_state(xhci, port_array, wIndex, XDEV_U0); xhci_dbg(xhci, "set port %d resume\n", @@ -845,7 +846,12 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) /* Initial status is no changes */ retval = (max_ports + 8) / 8; memset(buf, 0, retval); - status = 0; + + /* + * Inform the usbcore about resume-in-progress by returning + * a non-zero value even if there are no status changes. + */ + status = bus_state->resuming_ports; mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC; @@ -885,15 +891,11 @@ int xhci_bus_suspend(struct usb_hcd *hcd) spin_lock_irqsave(&xhci->lock, flags); if (hcd->self.root_hub->do_remote_wakeup) { - port_index = max_ports; - while (port_index--) { - if (bus_state->resume_done[port_index] != 0) { - spin_unlock_irqrestore(&xhci->lock, flags); - xhci_dbg(xhci, "suspend failed because " - "port %d is resuming\n", - port_index + 1); - return -EBUSY; - } + if (bus_state->resuming_ports) { + spin_unlock_irqrestore(&xhci->lock, flags); + xhci_dbg(xhci, "suspend failed because " + "a port is resuming\n"); + return -EBUSY; } } diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 3d9422f16a20..d40194c8ca60 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1377,6 +1377,7 @@ static void handle_port_status(struct xhci_hcd *xhci, xhci_dbg(xhci, "resume HS port %d\n", port_id); bus_state->resume_done[faked_port_index] = jiffies + msecs_to_jiffies(20); + set_bit(faked_port_index, &bus_state->resuming_ports); mod_timer(&hcd->rh_timer, bus_state->resume_done[faked_port_index]); /* Do the rest in GetPortStatus */ @@ -1803,6 +1804,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, break; case COMP_DEV_ERR: case COMP_STALL: + case COMP_TX_ERR: frame->status = -EPROTO; skip_td = true; break; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 36641a7f2371..5910048b0a2e 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -152,7 +152,7 @@ int xhci_reset(struct xhci_hcd *xhci) { u32 command; u32 state; - int ret; + int ret, i; state = xhci_readl(xhci, &xhci->op_regs->status); if ((state & STS_HALT) == 0) { @@ -175,7 +175,15 @@ int xhci_reset(struct xhci_hcd *xhci) * xHCI cannot write to any doorbells or operational registers other * than status until the "Controller Not Ready" flag is cleared. */ - return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); + ret = handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); + + for (i = 0; i < 2; ++i) { + xhci->bus_state[i].port_c_suspend = 0; + xhci->bus_state[i].suspended_ports = 0; + xhci->bus_state[i].resuming_ports = 0; + } + + return ret; } #ifdef CONFIG_PCI diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 3d69c4b2b542..ce1edd7246aa 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1362,6 +1362,8 @@ struct xhci_bus_state { u32 suspended_ports; u32 port_remote_wakeup; unsigned long resume_done[USB_MAXCHILDREN]; + /* which ports have started to resume */ + unsigned long resuming_ports; }; static inline unsigned int hcd_index(struct usb_hcd *hcd) diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 575b56c79e97..7121b50098d3 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -284,18 +284,16 @@ static void mdc800_usb_irq (struct urb *urb) int data_received=0, wake_up; unsigned char* b=urb->transfer_buffer; struct mdc800_data* mdc800=urb->context; + struct device *dev = &mdc800->dev->dev; int status = urb->status; if (status >= 0) { - - //dbg ("%i %i %i %i %i %i %i %i \n",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]); - if (mdc800_isBusy (b)) { if (!mdc800->camera_busy) { mdc800->camera_busy=1; - dbg ("gets busy"); + dev_dbg(dev, "gets busy\n"); } } else @@ -303,13 +301,13 @@ static void mdc800_usb_irq (struct urb *urb) if (mdc800->camera_busy && mdc800_isReady (b)) { mdc800->camera_busy=0; - dbg ("gets ready"); + dev_dbg(dev, "gets ready\n"); } } if (!(mdc800_isBusy (b) || mdc800_isReady (b))) { /* Store Data in camera_answer field */ - dbg ("%i %i %i %i %i %i %i %i ",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]); + dev_dbg(dev, "%i %i %i %i %i %i %i %i \n",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]); memcpy (mdc800->camera_response,b,8); data_received=1; @@ -441,7 +439,7 @@ static int mdc800_usb_probe (struct usb_interface *intf, int irq_interval=0; int retval; - dbg ("(mdc800_usb_probe) called."); + dev_dbg(&intf->dev, "(%s) called.\n", __func__); if (mdc800->dev != NULL) @@ -554,7 +552,7 @@ static void mdc800_usb_disconnect (struct usb_interface *intf) { struct mdc800_data* mdc800 = usb_get_intfdata(intf); - dbg ("(mdc800_usb_disconnect) called"); + dev_dbg(&intf->dev, "(%s) called\n", __func__); if (mdc800) { if (mdc800->state == NOT_CONNECTED) @@ -656,7 +654,7 @@ static int mdc800_device_open (struct inode* inode, struct file *file) } mdc800->open=1; - dbg ("Mustek MDC800 device opened."); + dev_dbg(&mdc800->dev->dev, "Mustek MDC800 device opened.\n"); error_out: mutex_unlock(&mdc800->io_lock); @@ -670,7 +668,6 @@ error_out: static int mdc800_device_release (struct inode* inode, struct file *file) { int retval=0; - dbg ("Mustek MDC800 device closed."); mutex_lock(&mdc800->io_lock); if (mdc800->open && (mdc800->state != NOT_CONNECTED)) @@ -927,7 +924,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s { mdc800->pic_len=(int) 65536*(unsigned char) mdc800->camera_response[0]+256*(unsigned char) mdc800->camera_response[1]+(unsigned char) mdc800->camera_response[2]; - dbg ("cached imagesize = %i",mdc800->pic_len); + dev_dbg(&mdc800->dev->dev, "cached imagesize = %i\n", mdc800->pic_len); } } diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index ac0d75a9005a..0fc6e5fc745f 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -88,6 +88,7 @@ static struct workqueue_struct *wq; static void appledisplay_complete(struct urb *urb) { struct appledisplay *pdata = urb->context; + struct device *dev = &pdata->udev->dev; unsigned long flags; int status = urb->status; int retval; @@ -97,18 +98,18 @@ static void appledisplay_complete(struct urb *urb) /* success */ break; case -EOVERFLOW: - printk(KERN_ERR "appletouch: OVERFLOW with data " - "length %d, actual length is %d\n", + dev_err(dev, + "OVERFLOW with data length %d, actual length is %d\n", ACD_URB_BUFFER_LEN, pdata->urb->actual_length); case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* This urb is terminated, clean up */ - dbg("%s - urb shuttingdown with status: %d", + dev_dbg(dev, "%s - urb shuttingdown with status: %d\n", __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", + dev_dbg(dev, "%s - nonzero urb status received: %d/n", __func__, status); goto exit; } @@ -132,8 +133,7 @@ static void appledisplay_complete(struct urb *urb) exit: retval = usb_submit_urb(pdata->urb, GFP_ATOMIC); if (retval) { - dev_err(&pdata->udev->dev, - "%s - usb_submit_urb failed with result %d\n", + dev_err(dev, "%s - usb_submit_urb failed with result %d\n", __func__, retval); } } diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c index da97dcec1f32..d65984dee751 100644 --- a/drivers/usb/misc/emi26.c +++ b/drivers/usb/misc/emi26.c @@ -78,18 +78,14 @@ static int emi26_load_firmware (struct usb_device *dev) const struct firmware *bitstream_fw = NULL; const struct firmware *firmware_fw = NULL; const struct ihex_binrec *rec; - int err; + int err = -ENOMEM; int i; __u32 addr; /* Address to write */ __u8 *buf; buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL); - if (!buf) { - dev_err(&dev->dev, "%s - error loading firmware: error = %d\n", - __func__, -ENOMEM); - err = -ENOMEM; + if (!buf) goto wraperr; - } err = request_ihex_firmware(&loader_fw, "emi26/loader.fw", &dev->dev); if (err) @@ -111,11 +107,8 @@ static int emi26_load_firmware (struct usb_device *dev) /* Assert reset (stop the CPU in the EMI) */ err = emi26_set_reset(dev,1); - if (err < 0) { - dev_err(&dev->dev,"%s - error loading firmware: error = %d\n", - __func__, err); + if (err < 0) goto wraperr; - } rec = (const struct ihex_binrec *)loader_fw->data; /* 1. We need to put the loader for the FPGA into the EZ-USB */ @@ -123,19 +116,15 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } rec = ihex_next_binrec(rec); } /* De-assert reset (let the CPU run) */ err = emi26_set_reset(dev,0); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } msleep(250); /* let device settle */ /* 2. We upload the FPGA firmware into the EMI @@ -153,18 +142,14 @@ static int emi26_load_firmware (struct usb_device *dev) rec = ihex_next_binrec(rec); } err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } while (rec); /* Assert reset (stop the CPU in the EMI) */ err = emi26_set_reset(dev,1); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } /* 3. We need to put the loader for the firmware into the EZ-USB (again...) */ for (rec = (const struct ihex_binrec *)loader_fw->data; @@ -172,19 +157,15 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } msleep(250); /* let device settle */ /* De-assert reset (let the CPU run) */ err = emi26_set_reset(dev,0); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */ @@ -194,19 +175,15 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_EXTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } } - + /* Assert reset (stop the CPU in the EMI) */ err = emi26_set_reset(dev,1); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } for (rec = (const struct ihex_binrec *)firmware_fw->data; rec; rec = ihex_next_binrec(rec)) { @@ -214,19 +191,15 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } } /* De-assert reset (let the CPU run) */ err = emi26_set_reset(dev,0); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } msleep(250); /* let device settle */ /* return 1 to fail the driver inialization @@ -234,6 +207,10 @@ static int emi26_load_firmware (struct usb_device *dev) err = 1; wraperr: + if (err < 0) + dev_err(&dev->dev,"%s - error loading firmware: error = %d\n", + __func__, err); + release_firmware(loader_fw); release_firmware(bitstream_fw); release_firmware(firmware_fw); diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 4e0f167a6c4e..ff08015b230c 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -56,7 +56,7 @@ static int emi62_writememory(struct usb_device *dev, int address, unsigned char *buffer = kmemdup(data, length, GFP_KERNEL); if (!buffer) { - err("emi62: kmalloc(%d) failed.", length); + dev_err(&dev->dev, "kmalloc(%d) failed.\n", length); return -ENOMEM; } /* Note: usb_control_msg returns negative value on error or length of the @@ -73,9 +73,8 @@ static int emi62_set_reset (struct usb_device *dev, unsigned char reset_bit) dev_info(&dev->dev, "%s - %d\n", __func__, reset_bit); response = emi62_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0); - if (response < 0) { - err("emi62: set_reset (%d) failed", reset_bit); - } + if (response < 0) + dev_err(&dev->dev, "set_reset (%d) failed\n", reset_bit); return response; } @@ -87,18 +86,15 @@ static int emi62_load_firmware (struct usb_device *dev) const struct firmware *bitstream_fw = NULL; const struct firmware *firmware_fw = NULL; const struct ihex_binrec *rec; - int err; + int err = -ENOMEM; int i; __u32 addr; /* Address to write */ __u8 *buf; dev_dbg(&dev->dev, "load_firmware\n"); buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL); - if (!buf) { - err( "%s - error loading firmware: error = %d", __func__, -ENOMEM); - err = -ENOMEM; + if (!buf) goto wraperr; - } err = request_ihex_firmware(&loader_fw, "emi62/loader.fw", &dev->dev); if (err) @@ -112,16 +108,13 @@ static int emi62_load_firmware (struct usb_device *dev) err = request_ihex_firmware(&firmware_fw, FIRMWARE_FW, &dev->dev); if (err) { nofw: - err( "%s - request_firmware() failed", __func__); goto wraperr; } /* Assert reset (stop the CPU in the EMI) */ err = emi62_set_reset(dev,1); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } rec = (const struct ihex_binrec *)loader_fw->data; @@ -130,19 +123,15 @@ static int emi62_load_firmware (struct usb_device *dev) err = emi62_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } rec = ihex_next_binrec(rec); } /* De-assert reset (let the CPU run) */ err = emi62_set_reset(dev,0); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } msleep(250); /* let device settle */ /* 2. We upload the FPGA firmware into the EMI @@ -160,18 +149,14 @@ static int emi62_load_firmware (struct usb_device *dev) rec = ihex_next_binrec(rec); } err = emi62_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } while (rec); /* Assert reset (stop the CPU in the EMI) */ err = emi62_set_reset(dev,1); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } /* 3. We need to put the loader for the firmware into the EZ-USB (again...) */ for (rec = (const struct ihex_binrec *)loader_fw->data; @@ -179,18 +164,14 @@ static int emi62_load_firmware (struct usb_device *dev) err = emi62_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } /* De-assert reset (let the CPU run) */ err = emi62_set_reset(dev,0); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } msleep(250); /* let device settle */ /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */ @@ -201,19 +182,15 @@ static int emi62_load_firmware (struct usb_device *dev) err = emi62_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_EXTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } } /* Assert reset (stop the CPU in the EMI) */ err = emi62_set_reset(dev,1); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } for (rec = (const struct ihex_binrec *)firmware_fw->data; rec; rec = ihex_next_binrec(rec)) { @@ -221,19 +198,15 @@ static int emi62_load_firmware (struct usb_device *dev) err = emi62_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_EXTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } } /* De-assert reset (let the CPU run) */ err = emi62_set_reset(dev,0); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } msleep(250); /* let device settle */ release_firmware(loader_fw); @@ -247,6 +220,9 @@ static int emi62_load_firmware (struct usb_device *dev) return 1; wraperr: + if (err < 0) + dev_err(&dev->dev,"%s - error loading firmware: error = %d\n", + __func__, err); release_firmware(loader_fw); release_firmware(bitstream_fw); release_firmware(firmware_fw); diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index 0dee24698504..ce978384fda1 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c @@ -200,7 +200,8 @@ reset: return -EAGAIN; /* should be IMGSIZE == 65040 */ - dbg("read %d bytes fingerprint data", bytes_read); + dev_dbg(&dev->interface->dev, "read %d bytes fingerprint data\n", + bytes_read); return result; } @@ -366,14 +367,14 @@ static int idmouse_probe(struct usb_interface *interface, kmalloc(IMGSIZE + dev->bulk_in_size, GFP_KERNEL); if (!dev->bulk_in_buffer) { - err("Unable to allocate input buffer."); + dev_err(&interface->dev, "Unable to allocate input buffer.\n"); idmouse_delete(dev); return -ENOMEM; } } if (!(dev->bulk_in_endpointAddr)) { - err("Unable to find bulk-in endpoint."); + dev_err(&interface->dev, "Unable to find bulk-in endpoint.\n"); idmouse_delete(dev); return -ENODEV; } @@ -385,7 +386,7 @@ static int idmouse_probe(struct usb_interface *interface, result = usb_register_dev(interface, &idmouse_class); if (result) { /* something prevented us from registering this device */ - err("Unble to allocate minor number."); + dev_err(&interface->dev, "Unble to allocate minor number.\n"); usb_set_intfdata(interface, NULL); idmouse_delete(dev); return result; diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 4fd0dc835ae5..db46143c67a6 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -610,8 +610,8 @@ static int iowarrior_open(struct inode *inode, struct file *file) interface = usb_find_interface(&iowarrior_driver, subminor); if (!interface) { mutex_unlock(&iowarrior_mutex); - err("%s - error, can't find device for minor %d", __func__, - subminor); + printk(KERN_ERR "%s - error, can't find device for minor %d\n", + __func__, subminor); return -ENODEV; } diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 5db4ab52061e..ac762299eaa8 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -334,8 +334,8 @@ static int ld_usb_open(struct inode *inode, struct file *file) interface = usb_find_interface(&ld_usb_driver, subminor); if (!interface) { - err("%s - error, can't find device for minor %d\n", - __func__, subminor); + printk(KERN_ERR "%s - error, can't find device for minor %d\n", + __func__, subminor); return -ENODEV; } @@ -485,7 +485,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, /* verify that the device wasn't unplugged */ if (dev->intf == NULL) { retval = -ENODEV; - err("No device or device unplugged %d\n", retval); + printk(KERN_ERR "ldusb: No device or device unplugged %d\n", retval); goto unlock_exit; } @@ -565,7 +565,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, /* verify that the device wasn't unplugged */ if (dev->intf == NULL) { retval = -ENODEV; - err("No device or device unplugged %d\n", retval); + printk(KERN_ERR "ldusb: No device or device unplugged %d\n", retval); goto unlock_exit; } @@ -603,7 +603,9 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, bytes_to_write, USB_CTRL_SET_TIMEOUT * HZ); if (retval < 0) - err("Couldn't submit HID_REQ_SET_REPORT %d\n", retval); + dev_err(&dev->intf->dev, + "Couldn't submit HID_REQ_SET_REPORT %d\n", + retval); goto unlock_exit; } @@ -624,7 +626,8 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL); if (retval) { dev->interrupt_out_busy = 0; - err("Couldn't submit interrupt_out_urb %d\n", retval); + dev_err(&dev->intf->dev, + "Couldn't submit interrupt_out_urb %d\n", retval); goto unlock_exit; } retval = bytes_to_write; diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 575222042767..a2702cbfe804 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -354,8 +354,8 @@ static int tower_open (struct inode *inode, struct file *file) interface = usb_find_interface (&tower_driver, subminor); if (!interface) { - err ("%s - error, can't find device for minor %d", - __func__, subminor); + printk(KERN_ERR "%s - error, can't find device for minor %d\n", + __func__, subminor); retval = -ENODEV; goto exit; } @@ -397,7 +397,8 @@ static int tower_open (struct inode *inode, struct file *file) sizeof(reset_reply), 1000); if (result < 0) { - err("LEGO USB Tower reset control request failed"); + dev_err(&dev->udev->dev, + "LEGO USB Tower reset control request failed\n"); retval = result; goto unlock_exit; } @@ -420,7 +421,8 @@ static int tower_open (struct inode *inode, struct file *file) retval = usb_submit_urb (dev->interrupt_in_urb, GFP_KERNEL); if (retval) { - err("Couldn't submit interrupt_in_urb %d", retval); + dev_err(&dev->udev->dev, + "Couldn't submit interrupt_in_urb %d\n", retval); dev->interrupt_in_running = 0; dev->open_count = 0; goto unlock_exit; @@ -608,7 +610,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - err("No device or device unplugged %d", retval); + printk(KERN_ERR "legousbtower: No device or device unplugged %d\n", retval); goto unlock_exit; } @@ -697,7 +699,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - err("No device or device unplugged %d", retval); + printk(KERN_ERR "legousbtower: No device or device unplugged %d\n", retval); goto unlock_exit; } @@ -744,7 +746,8 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t retval = usb_submit_urb (dev->interrupt_out_urb, GFP_KERNEL); if (retval) { dev->interrupt_out_busy = 0; - err("Couldn't submit interrupt_out_urb %d", retval); + dev_err(&dev->udev->dev, + "Couldn't submit interrupt_out_urb %d\n", retval); goto unlock_exit; } retval = bytes_to_write; @@ -803,9 +806,10 @@ resubmit: /* resubmit if we're still running */ if (dev->interrupt_in_running && dev->udev) { retval = usb_submit_urb (dev->interrupt_in_urb, GFP_ATOMIC); - if (retval) { - err("%s: usb_submit_urb failed (%d)", __func__, retval); - } + if (retval) + dev_err(&dev->udev->dev, + "%s: usb_submit_urb failed (%d)\n", + __func__, retval); } exit: @@ -852,6 +856,7 @@ static void tower_interrupt_out_callback (struct urb *urb) */ static int tower_probe (struct usb_interface *interface, const struct usb_device_id *id) { + struct device *idev = &interface->dev; struct usb_device *udev = interface_to_usbdev(interface); struct lego_usb_tower *dev = NULL; struct usb_host_interface *iface_desc; @@ -871,7 +876,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device dev = kmalloc (sizeof(struct lego_usb_tower), GFP_KERNEL); if (dev == NULL) { - err ("Out of memory"); + dev_err(idev, "Out of memory\n"); goto exit; } @@ -915,37 +920,37 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device } } if(dev->interrupt_in_endpoint == NULL) { - err("interrupt in endpoint not found"); + dev_err(idev, "interrupt in endpoint not found\n"); goto error; } if (dev->interrupt_out_endpoint == NULL) { - err("interrupt out endpoint not found"); + dev_err(idev, "interrupt out endpoint not found\n"); goto error; } dev->read_buffer = kmalloc (read_buffer_size, GFP_KERNEL); if (!dev->read_buffer) { - err("Couldn't allocate read_buffer"); + dev_err(idev, "Couldn't allocate read_buffer\n"); goto error; } dev->interrupt_in_buffer = kmalloc (usb_endpoint_maxp(dev->interrupt_in_endpoint), GFP_KERNEL); if (!dev->interrupt_in_buffer) { - err("Couldn't allocate interrupt_in_buffer"); + dev_err(idev, "Couldn't allocate interrupt_in_buffer\n"); goto error; } dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->interrupt_in_urb) { - err("Couldn't allocate interrupt_in_urb"); + dev_err(idev, "Couldn't allocate interrupt_in_urb\n"); goto error; } dev->interrupt_out_buffer = kmalloc (write_buffer_size, GFP_KERNEL); if (!dev->interrupt_out_buffer) { - err("Couldn't allocate interrupt_out_buffer"); + dev_err(idev, "Couldn't allocate interrupt_out_buffer\n"); goto error; } dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->interrupt_out_urb) { - err("Couldn't allocate interrupt_out_urb"); + dev_err(idev, "Couldn't allocate interrupt_out_urb\n"); goto error; } dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval; @@ -958,7 +963,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device if (retval) { /* something prevented us from registering this driver */ - err ("Not able to get a minor for this device."); + dev_err(idev, "Not able to get a minor for this device.\n"); usb_set_intfdata (interface, NULL); goto error; } @@ -980,7 +985,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device sizeof(get_version_reply), 1000); if (result < 0) { - err("LEGO USB Tower get version control request failed"); + dev_err(idev, "LEGO USB Tower get version control request failed\n"); retval = result; goto error; } diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c index 487a8ce0775e..1084124c4a44 100644 --- a/drivers/usb/misc/rio500.c +++ b/drivers/usb/misc/rio500.c @@ -153,10 +153,10 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) requesttype = rio_cmd.requesttype | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - dbg - ("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x", - requesttype, rio_cmd.request, rio_cmd.value, - rio_cmd.index, rio_cmd.length); + dev_dbg(&rio->rio_dev->dev, + "sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", + requesttype, rio_cmd.request, rio_cmd.value, + rio_cmd.index, rio_cmd.length); /* Send rio control message */ retries = 3; while (retries) { @@ -171,11 +171,14 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) if (result == -ETIMEDOUT) retries--; else if (result < 0) { - err("Error executing ioctrl. code = %d", result); + dev_err(&rio->rio_dev->dev, + "Error executing ioctrl. code = %d\n", + result); retries = 0; } else { - dbg("Executed ioctl. Result = %d (data=%02x)", - result, buffer[0]); + dev_dbg(&rio->rio_dev->dev, + "Executed ioctl. Result = %d (data=%02x)\n", + result, buffer[0]); if (copy_to_user(rio_cmd.buffer, buffer, rio_cmd.length)) { free_page((unsigned long) buffer); @@ -221,9 +224,10 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) requesttype = rio_cmd.requesttype | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - dbg("sending command: reqtype=%0x req=%0x value=%0x index=%0x len=%0x", - requesttype, rio_cmd.request, rio_cmd.value, - rio_cmd.index, rio_cmd.length); + dev_dbg(&rio->rio_dev->dev, + "sending command: reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", + requesttype, rio_cmd.request, rio_cmd.value, + rio_cmd.index, rio_cmd.length); /* Send rio control message */ retries = 3; while (retries) { @@ -238,10 +242,13 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) if (result == -ETIMEDOUT) retries--; else if (result < 0) { - err("Error executing ioctrl. code = %d", result); + dev_err(&rio->rio_dev->dev, + "Error executing ioctrl. code = %d\n", + result); retries = 0; } else { - dbg("Executed ioctl. Result = %d", result); + dev_dbg(&rio->rio_dev->dev, + "Executed ioctl. Result = %d\n", result); retries = 0; } @@ -313,8 +320,9 @@ write_rio(struct file *file, const char __user *buffer, usb_sndbulkpipe(rio->rio_dev, 2), obuf, thistime, &partial, 5000); - dbg("write stats: result:%d thistime:%lu partial:%u", - result, thistime, partial); + dev_dbg(&rio->rio_dev->dev, + "write stats: result:%d thistime:%lu partial:%u\n", + result, thistime, partial); if (result == -ETIMEDOUT) { /* NAK - so hold for a while */ if (!maxretry--) { @@ -332,7 +340,8 @@ write_rio(struct file *file, const char __user *buffer, break; }; if (result) { - err("Write Whoops - %x", result); + dev_err(&rio->rio_dev->dev, "Write Whoops - %x\n", + result); errn = -EIO; goto error; } @@ -393,15 +402,17 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) ibuf, this_read, &partial, 8000); - dbg("read stats: result:%d this_read:%u partial:%u", - result, this_read, partial); + dev_dbg(&rio->rio_dev->dev, + "read stats: result:%d this_read:%u partial:%u\n", + result, this_read, partial); if (partial) { count = this_read = partial; } else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */ if (!maxretry--) { mutex_unlock(&(rio->lock)); - err("read_rio: maxretry timeout"); + dev_err(&rio->rio_dev->dev, + "read_rio: maxretry timeout\n"); return -ETIME; } prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE); @@ -410,8 +421,9 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) continue; } else if (result != -EREMOTEIO) { mutex_unlock(&(rio->lock)); - err("Read Whoops - result:%u partial:%u this_read:%u", - result, partial, this_read); + dev_err(&rio->rio_dev->dev, + "Read Whoops - result:%u partial:%u this_read:%u\n", + result, partial, this_read); return -EIO; } else { mutex_unlock(&(rio->lock)); @@ -459,26 +471,29 @@ static int probe_rio(struct usb_interface *intf, retval = usb_register_dev(intf, &usb_rio_class); if (retval) { - err("Not able to get a minor for this device."); + dev_err(&dev->dev, + "Not able to get a minor for this device.\n"); return -ENOMEM; } rio->rio_dev = dev; if (!(rio->obuf = kmalloc(OBUF_SIZE, GFP_KERNEL))) { - err("probe_rio: Not enough memory for the output buffer"); + dev_err(&dev->dev, + "probe_rio: Not enough memory for the output buffer\n"); usb_deregister_dev(intf, &usb_rio_class); return -ENOMEM; } - dbg("probe_rio: obuf address:%p", rio->obuf); + dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf); if (!(rio->ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL))) { - err("probe_rio: Not enough memory for the input buffer"); + dev_err(&dev->dev, + "probe_rio: Not enough memory for the input buffer\n"); usb_deregister_dev(intf, &usb_rio_class); kfree(rio->obuf); return -ENOMEM; } - dbg("probe_rio: ibuf address:%p", rio->ibuf); + dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf); mutex_init(&(rio->lock)); diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index e2b4bd31c2b6..89927bcff974 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -87,8 +87,8 @@ static int lcd_open(struct inode *inode, struct file *file) interface = usb_find_interface(&lcd_driver, subminor); if (!interface) { mutex_unlock(&lcd_mutex); - err("USBLCD: %s - error, can't find device for minor %d", - __func__, subminor); + printk(KERN_ERR "USBLCD: %s - error, can't find device for minor %d\n", + __func__, subminor); return -ENODEV; } @@ -209,8 +209,8 @@ static void lcd_write_bulk_callback(struct urb *urb) !(status == -ENOENT || status == -ECONNRESET || status == -ESHUTDOWN)) { - dbg("USBLCD: %s - nonzero write bulk status received: %d", - __func__, status); + dev_dbg(&dev->interface->dev, + "nonzero write bulk status received: %d\n", status); } /* free up our allocated buffer */ @@ -268,8 +268,9 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, /* send the data out the bulk port */ retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) { - err("USBLCD: %s - failed submitting write urb, error %d", - __func__, retval); + dev_err(&dev->udev->dev, + "%s - failed submitting write urb, error %d\n", + __func__, retval); goto error_unanchor; } @@ -322,7 +323,7 @@ static int lcd_probe(struct usb_interface *interface, /* allocate memory for our device state and initialize it */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { - err("Out of memory"); + dev_err(&interface->dev, "Out of memory\n"); goto error; } kref_init(&dev->kref); @@ -352,7 +353,8 @@ static int lcd_probe(struct usb_interface *interface, dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!dev->bulk_in_buffer) { - err("Could not allocate bulk_in_buffer"); + dev_err(&interface->dev, + "Could not allocate bulk_in_buffer\n"); goto error; } } @@ -364,7 +366,8 @@ static int lcd_probe(struct usb_interface *interface, } } if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) { - err("Could not find both bulk-in and bulk-out endpoints"); + dev_err(&interface->dev, + "Could not find both bulk-in and bulk-out endpoints\n"); goto error; } @@ -375,7 +378,8 @@ static int lcd_probe(struct usb_interface *interface, retval = usb_register_dev(interface, &lcd_class); if (retval) { /* something prevented us from registering this driver */ - err("Not able to get a minor for this device."); + dev_err(&interface->dev, + "Not able to get a minor for this device.\n"); usb_set_intfdata(interface, NULL); goto error; } diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 9dcb68f04f03..055b84adedac 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -1028,7 +1028,10 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param) case 13: /* short read, resembling case 10 */ req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0); /* last data packet "should" be DATA1, not DATA0 */ - len = 1024 - udev->descriptor.bMaxPacketSize0; + if (udev->speed == USB_SPEED_SUPER) + len = 1024 - 512; + else + len = 1024 - udev->descriptor.bMaxPacketSize0; expected = -EREMOTEIO; break; case 14: /* short read; try to fill the last packet */ @@ -1387,11 +1390,15 @@ static int test_halt(struct usbtest_dev *tdev, int ep, struct urb *urb) static int halt_simple(struct usbtest_dev *dev) { - int ep; - int retval = 0; - struct urb *urb; + int ep; + int retval = 0; + struct urb *urb; + struct usb_device *udev = testdev_to_usbdev(dev); - urb = simple_alloc_urb(testdev_to_usbdev(dev), 0, 512); + if (udev->speed == USB_SPEED_SUPER) + urb = simple_alloc_urb(udev, 0, 1024); + else + urb = simple_alloc_urb(udev, 0, 512); if (urb == NULL) return -ENOMEM; diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 8b1d94a76914..29cad9e0a7a9 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -85,9 +85,9 @@ static void destroy_priv(struct kref *kref) { struct parport_uss720_private *priv = container_of(kref, struct parport_uss720_private, ref_count); + dev_dbg(&priv->usbdev->dev, "destroying priv datastructure\n"); usb_put_dev(priv->usbdev); kfree(priv); - dbg("destroying priv datastructure"); } static void destroy_async(struct kref *kref) @@ -118,14 +118,17 @@ static void async_complete(struct urb *urb) priv = rq->priv; pp = priv->pp; if (status) { - err("async_complete: urb error %d", status); + dev_err(&urb->dev->dev, "async_complete: urb error %d\n", + status); } else if (rq->dr.bRequest == 3) { memcpy(priv->reg, rq->reg, sizeof(priv->reg)); #if 0 - dbg("async_complete regs %02x %02x %02x %02x %02x %02x %02x", - (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], (unsigned int)priv->reg[2], - (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], (unsigned int)priv->reg[5], - (unsigned int)priv->reg[6]); + dev_dbg(&priv->usbdev->dev, + "async_complete regs %02x %02x %02x %02x %02x %02x %02x\n", + (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], + (unsigned int)priv->reg[2], (unsigned int)priv->reg[3], + (unsigned int)priv->reg[4], (unsigned int)priv->reg[5], + (unsigned int)priv->reg[6]); #endif /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */ if (rq->reg[2] & rq->reg[1] & 0x10 && pp) @@ -151,7 +154,7 @@ static struct uss720_async_request *submit_async_request(struct parport_uss720_p return NULL; rq = kmalloc(sizeof(struct uss720_async_request), mem_flags); if (!rq) { - err("submit_async_request out of memory"); + dev_err(&usbdev->dev, "submit_async_request out of memory\n"); return NULL; } kref_init(&rq->ref_count); @@ -162,7 +165,7 @@ static struct uss720_async_request *submit_async_request(struct parport_uss720_p rq->urb = usb_alloc_urb(0, mem_flags); if (!rq->urb) { kref_put(&rq->ref_count, destroy_async); - err("submit_async_request out of memory"); + dev_err(&usbdev->dev, "submit_async_request out of memory\n"); return NULL; } rq->dr.bRequestType = requesttype; @@ -182,7 +185,7 @@ static struct uss720_async_request *submit_async_request(struct parport_uss720_p if (!ret) return rq; destroy_async(&rq->ref_count); - err("submit_async_request submit_urb failed with %d", ret); + dev_err(&usbdev->dev, "submit_async_request submit_urb failed with %d\n", ret); return NULL; } @@ -217,7 +220,8 @@ static int get_1284_register(struct parport *pp, unsigned char reg, unsigned cha priv = pp->private_data; rq = submit_async_request(priv, 3, 0xc0, ((unsigned int)reg) << 8, 0, mem_flags); if (!rq) { - err("get_1284_register(%u) failed", (unsigned int)reg); + dev_err(&priv->usbdev->dev, "get_1284_register(%u) failed", + (unsigned int)reg); return -EIO; } if (!val) { @@ -248,7 +252,8 @@ static int set_1284_register(struct parport *pp, unsigned char reg, unsigned cha priv = pp->private_data; rq = submit_async_request(priv, 4, 0x40, (((unsigned int)reg) << 8) | val, 0, mem_flags); if (!rq) { - err("set_1284_register(%u,%u) failed", (unsigned int)reg, (unsigned int)val); + dev_err(&priv->usbdev->dev, "set_1284_register(%u,%u) failed", + (unsigned int)reg, (unsigned int)val); return -EIO; } kref_put(&rq->ref_count, destroy_async); @@ -690,9 +695,9 @@ static int uss720_probe(struct usb_interface *intf, unsigned char reg; int i; - dbg("probe: vendor id 0x%x, device id 0x%x\n", - le16_to_cpu(usbdev->descriptor.idVendor), - le16_to_cpu(usbdev->descriptor.idProduct)); + dev_dbg(&intf->dev, "probe: vendor id 0x%x, device id 0x%x\n", + le16_to_cpu(usbdev->descriptor.idVendor), + le16_to_cpu(usbdev->descriptor.idProduct)); /* our known interfaces have 3 alternate settings */ if (intf->num_altsetting != 3) { @@ -700,7 +705,7 @@ static int uss720_probe(struct usb_interface *intf, return -ENODEV; } i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2); - dbg("set inteface result %d", i); + dev_dbg(&intf->dev, "set inteface result %d\n", i); interface = intf->cur_altsetting; @@ -731,11 +736,13 @@ static int uss720_probe(struct usb_interface *intf, set_1284_register(pp, 2, 0x0c, GFP_KERNEL); /* debugging */ get_1284_register(pp, 0, ®, GFP_KERNEL); - dbg("reg: %02x %02x %02x %02x %02x %02x %02x", - priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]); + dev_dbg(&intf->dev, "reg: %02x %02x %02x %02x %02x %02x %02x\n", + priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], + priv->reg[4], priv->reg[5], priv->reg[6]); endpoint = &interface->endpoint[2]; - dbg("epaddr %d interval %d", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval); + dev_dbg(&intf->dev, "epaddr %d interval %d\n", + endpoint->desc.bEndpointAddress, endpoint->desc.bInterval); parport_announce_port(pp); usb_set_intfdata(intf, pp); @@ -753,20 +760,20 @@ static void uss720_disconnect(struct usb_interface *intf) struct parport_uss720_private *priv; struct usb_device *usbdev; - dbg("disconnect"); + dev_dbg(&intf->dev, "disconnect\n"); usb_set_intfdata(intf, NULL); if (pp) { priv = pp->private_data; usbdev = priv->usbdev; priv->usbdev = NULL; priv->pp = NULL; - dbg("parport_remove_port"); + dev_dbg(&intf->dev, "parport_remove_port\n"); parport_remove_port(pp); parport_put_port(pp); kill_all_async_requests_priv(priv); kref_put(&priv->ref_count, destroy_priv); } - dbg("disconnect done"); + dev_dbg(&intf->dev, "disconnect done\n"); } /* table of cables that work through this driver */ diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index 70201462e19c..42ad2e6d86c4 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -83,7 +83,8 @@ static void yurex_control_callback(struct urb *urb) int status = urb->status; if (status) { - err("%s - control failed: %d\n", __func__, status); + dev_err(&urb->dev->dev, "%s - control failed: %d\n", + __func__, status); wake_up_interruptible(&dev->waitq); return; } @@ -94,7 +95,7 @@ static void yurex_delete(struct kref *kref) { struct usb_yurex *dev = to_yurex_dev(kref); - dbg("yurex_delete"); + dev_dbg(&dev->interface->dev, "%s\n", __func__); usb_put_dev(dev->udev); if (dev->cntl_urb) { @@ -137,8 +138,9 @@ static void yurex_interrupt(struct urb *urb) case 0: /*success*/ break; case -EOVERFLOW: - err("%s - overflow with length %d, actual length is %d", - __func__, YUREX_BUF_SIZE, dev->urb->actual_length); + dev_err(&dev->interface->dev, + "%s - overflow with length %d, actual length is %d\n", + __func__, YUREX_BUF_SIZE, dev->urb->actual_length); case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: @@ -146,7 +148,8 @@ static void yurex_interrupt(struct urb *urb) /* The device is terminated, clean up */ return; default: - err("%s - unknown status received: %d", __func__, status); + dev_err(&dev->interface->dev, + "%s - unknown status received: %d\n", __func__, status); goto exit; } @@ -162,16 +165,19 @@ static void yurex_interrupt(struct urb *urb) if (i != 5) dev->bbu <<= 8; } - dbg("%s count: %lld", __func__, dev->bbu); + dev_dbg(&dev->interface->dev, "%s count: %lld\n", + __func__, dev->bbu); spin_unlock_irqrestore(&dev->lock, flags); kill_fasync(&dev->async_queue, SIGIO, POLL_IN); } else - dbg("data format error - no EOF"); + dev_dbg(&dev->interface->dev, + "data format error - no EOF\n"); break; case CMD_ACK: - dbg("%s ack: %c", __func__, buf[1]); + dev_dbg(&dev->interface->dev, "%s ack: %c\n", + __func__, buf[1]); wake_up_interruptible(&dev->waitq); break; } @@ -179,7 +185,7 @@ static void yurex_interrupt(struct urb *urb) exit: retval = usb_submit_urb(dev->urb, GFP_ATOMIC); if (retval) { - err("%s - usb_submit_urb failed: %d", + dev_err(&dev->interface->dev, "%s - usb_submit_urb failed: %d\n", __func__, retval); } } @@ -196,7 +202,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ /* allocate memory for our device state and initialize it */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { - err("Out of memory"); + dev_err(&interface->dev, "Out of memory\n"); goto error; } kref_init(&dev->kref); @@ -219,7 +225,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ } if (!dev->int_in_endpointAddr) { retval = -ENODEV; - err("Could not find endpoints"); + dev_err(&interface->dev, "Could not find endpoints\n"); goto error; } @@ -227,14 +233,14 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ /* allocate control URB */ dev->cntl_urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->cntl_urb) { - err("Could not allocate control URB"); + dev_err(&interface->dev, "Could not allocate control URB\n"); goto error; } /* allocate buffer for control req */ dev->cntl_req = kmalloc(YUREX_BUF_SIZE, GFP_KERNEL); if (!dev->cntl_req) { - err("Could not allocate cntl_req"); + dev_err(&interface->dev, "Could not allocate cntl_req\n"); goto error; } @@ -243,7 +249,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ GFP_KERNEL, &dev->cntl_urb->transfer_dma); if (!dev->cntl_buffer) { - err("Could not allocate cntl_buffer"); + dev_err(&interface->dev, "Could not allocate cntl_buffer\n"); goto error; } @@ -265,7 +271,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ /* allocate interrupt URB */ dev->urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->urb) { - err("Could not allocate URB"); + dev_err(&interface->dev, "Could not allocate URB\n"); goto error; } @@ -273,7 +279,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ dev->int_buffer = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE, GFP_KERNEL, &dev->urb->transfer_dma); if (!dev->int_buffer) { - err("Could not allocate int_buffer"); + dev_err(&interface->dev, "Could not allocate int_buffer\n"); goto error; } @@ -285,7 +291,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ dev->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; if (usb_submit_urb(dev->urb, GFP_KERNEL)) { retval = -EIO; - err("Could not submitting URB"); + dev_err(&interface->dev, "Could not submitting URB\n"); goto error; } @@ -295,7 +301,8 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ /* we can register the device now, as it is ready */ retval = usb_register_dev(interface, &yurex_class); if (retval) { - err("Not able to get a minor for this device."); + dev_err(&interface->dev, + "Not able to get a minor for this device.\n"); usb_set_intfdata(interface, NULL); goto error; } @@ -368,8 +375,8 @@ static int yurex_open(struct inode *inode, struct file *file) interface = usb_find_interface(&yurex_driver, subminor); if (!interface) { - err("%s - error, can't find device for minor %d", - __func__, subminor); + printk(KERN_ERR "%s - error, can't find device for minor %d", + __func__, subminor); retval = -ENODEV; goto exit; } @@ -505,7 +512,8 @@ static ssize_t yurex_write(struct file *file, const char *user_buffer, size_t co /* send the data as the control msg */ prepare_to_wait(&dev->waitq, &wait, TASK_INTERRUPTIBLE); - dbg("%s - submit %c", __func__, dev->cntl_buffer[0]); + dev_dbg(&dev->interface->dev, "%s - submit %c\n", __func__, + dev->cntl_buffer[0]); retval = usb_submit_urb(dev->cntl_urb, GFP_KERNEL); if (retval >= 0) timeout = schedule_timeout(YUREX_WRITE_TIMEOUT); @@ -514,7 +522,9 @@ static ssize_t yurex_write(struct file *file, const char *user_buffer, size_t co mutex_unlock(&dev->io_mutex); if (retval < 0) { - err("%s - failed to send bulk msg, error %d", __func__, retval); + dev_err(&dev->interface->dev, + "%s - failed to send bulk msg, error %d\n", + __func__, retval); goto error; } if (set && timeout) diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 97ab975fa442..768b4b55c816 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -386,7 +386,7 @@ static int davinci_musb_init(struct musb *musb) usb_nop_xceiv_register(); musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) - return -ENODEV; + goto unregister; musb->mregs += DAVINCI_BASE_OFFSET; @@ -444,6 +444,7 @@ static int davinci_musb_init(struct musb *musb) fail: usb_put_transceiver(musb->xceiv); +unregister: usb_nop_xceiv_unregister(); return -ENODEV; } diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 93de517a32a0..f4a40f001c88 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -449,7 +449,7 @@ struct musb { * We added this flag to forcefully disable double * buffering until we get it working. */ - unsigned double_buffer_not_ok:1 __deprecated; + unsigned double_buffer_not_ok:1; struct musb_hdrc_config *config; diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c index 3ece43a2e4c1..a0a2178974fe 100644 --- a/drivers/usb/otg/gpio_vbus.c +++ b/drivers/usb/otg/gpio_vbus.c @@ -96,7 +96,7 @@ static void gpio_vbus_work(struct work_struct *work) struct gpio_vbus_data *gpio_vbus = container_of(work, struct gpio_vbus_data, work); struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data; - int gpio; + int gpio, status; if (!gpio_vbus->phy.otg->gadget) return; @@ -108,7 +108,9 @@ static void gpio_vbus_work(struct work_struct *work) */ gpio = pdata->gpio_pullup; if (is_vbus_powered(pdata)) { + status = USB_EVENT_VBUS; gpio_vbus->phy.state = OTG_STATE_B_PERIPHERAL; + gpio_vbus->phy.last_event = status; usb_gadget_vbus_connect(gpio_vbus->phy.otg->gadget); /* drawing a "unit load" is *always* OK, except for OTG */ @@ -117,6 +119,9 @@ static void gpio_vbus_work(struct work_struct *work) /* optionally enable D+ pullup */ if (gpio_is_valid(gpio)) gpio_set_value(gpio, !pdata->gpio_pullup_inverted); + + atomic_notifier_call_chain(&gpio_vbus->phy.notifier, + status, gpio_vbus->phy.otg->gadget); } else { /* optionally disable D+ pullup */ if (gpio_is_valid(gpio)) @@ -125,7 +130,12 @@ static void gpio_vbus_work(struct work_struct *work) set_vbus_draw(gpio_vbus, 0); usb_gadget_vbus_disconnect(gpio_vbus->phy.otg->gadget); + status = USB_EVENT_NONE; gpio_vbus->phy.state = OTG_STATE_B_IDLE; + gpio_vbus->phy.last_event = status; + + atomic_notifier_call_chain(&gpio_vbus->phy.notifier, + status, gpio_vbus->phy.otg->gadget); } } @@ -287,6 +297,9 @@ static int __init gpio_vbus_probe(struct platform_device *pdev) irq, err); goto err_irq; } + + ATOMIC_INIT_NOTIFIER_HEAD(&gpio_vbus->phy.notifier); + INIT_WORK(&gpio_vbus->work, gpio_vbus_work); gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw"); diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig new file mode 100644 index 000000000000..3cfabcba7447 --- /dev/null +++ b/drivers/usb/phy/Kconfig @@ -0,0 +1,17 @@ +# +# Physical Layer USB driver configuration +# +comment "USB Physical Layer drivers" + depends on USB + +config USB_ISP1301 + tristate "NXP ISP1301 USB transceiver support" + depends on USB + depends on I2C + help + Say Y here to add support for the NXP ISP1301 USB transceiver driver. + This chip is typically used as USB transceiver for USB host, gadget + and OTG drivers (to be selected separately). + + To compile this driver as a module, choose M here: the + module will be called isp1301. diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile new file mode 100644 index 000000000000..eca095b1a890 --- /dev/null +++ b/drivers/usb/phy/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for physical layer USB drivers +# + +ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG + +obj-$(CONFIG_USB_ISP1301) += isp1301.o diff --git a/drivers/usb/phy/isp1301.c b/drivers/usb/phy/isp1301.c new file mode 100644 index 000000000000..b19f4932a037 --- /dev/null +++ b/drivers/usb/phy/isp1301.c @@ -0,0 +1,77 @@ +/* + * NXP ISP1301 USB transceiver driver + * + * Copyright (C) 2012 Roland Stigge + * + * Author: Roland Stigge <stigge@antcom.de> + * + * 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/module.h> +#include <linux/i2c.h> + +#define DRV_NAME "isp1301" + +#define ISP1301_I2C_ADDR 0x2C + +static const unsigned short normal_i2c[] = { + ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END +}; + +static const struct i2c_device_id isp1301_id[] = { + { "isp1301", 0 }, + { } +}; + +static struct i2c_client *isp1301_i2c_client; + +static int isp1301_probe(struct i2c_client *client, + const struct i2c_device_id *i2c_id) +{ + isp1301_i2c_client = client; + return 0; +} + +static int isp1301_remove(struct i2c_client *client) +{ + return 0; +} + +static struct i2c_driver isp1301_driver = { + .driver = { + .name = DRV_NAME, + }, + .probe = isp1301_probe, + .remove = isp1301_remove, + .id_table = isp1301_id, +}; + +module_i2c_driver(isp1301_driver); + +static int match(struct device *dev, void *data) +{ + struct device_node *node = (struct device_node *)data; + return (dev->of_node == node) && + (dev->driver == &isp1301_driver.driver); +} + +struct i2c_client *isp1301_get_client(struct device_node *node) +{ + if (node) { /* reference of ISP1301 I2C node via DT */ + struct device *dev = bus_find_device(&i2c_bus_type, NULL, + node, match); + if (!dev) + return NULL; + return to_i2c_client(dev); + } else { /* non-DT: only one ISP1301 chip supported */ + return isp1301_i2c_client; + } +} +EXPORT_SYMBOL_GPL(isp1301_get_client); + +MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); +MODULE_DESCRIPTION("NXP ISP1301 USB transceiver driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 00bd2a5e0362..28478ce26c34 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -55,6 +55,7 @@ struct usbhsg_gpriv { #define USBHSG_STATUS_STARTED (1 << 0) #define USBHSG_STATUS_REGISTERD (1 << 1) #define USBHSG_STATUS_WEDGE (1 << 2) +#define USBHSG_STATUS_SELF_POWERED (1 << 3) }; struct usbhsg_recip_handle { @@ -333,7 +334,10 @@ static int usbhsg_recip_handler_std_get_device(struct usbhs_priv *priv, struct usb_ctrlrequest *ctrl) { struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); - unsigned short status = 1 << USB_DEVICE_SELF_POWERED; + unsigned short status = 0; + + if (usbhsg_status_has(gpriv, USBHSG_STATUS_SELF_POWERED)) + status = 1 << USB_DEVICE_SELF_POWERED; __usbhsg_recip_send_status(gpriv, status); @@ -879,8 +883,21 @@ static int usbhsg_get_frame(struct usb_gadget *gadget) return usbhs_frame_get_num(priv); } +static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self) +{ + struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); + + if (is_self) + usbhsg_status_set(gpriv, USBHSG_STATUS_SELF_POWERED); + else + usbhsg_status_clr(gpriv, USBHSG_STATUS_SELF_POWERED); + + return 0; +} + static struct usb_gadget_ops usbhsg_gadget_ops = { .get_frame = usbhsg_get_frame, + .set_selfpowered = usbhsg_set_selfpowered, .udc_start = usbhsg_gadget_start, .udc_stop = usbhsg_gadget_stop, }; diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index a52e0d2cec31..20073856cd18 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -2,17 +2,17 @@ * Belkin USB Serial Adapter Driver * * Copyright (C) 2000 William Greathouse (wgreathouse@smva.com) - * Copyright (C) 2000-2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2000-2001 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com) * * This program is largely derived from work by the linux-usb group * and associated source files. Please see the usb/serial files for * individual credits and copyrights. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * See Documentation/usb/usb-serial.txt for more information on using this * driver @@ -159,8 +159,6 @@ static void belkin_sa_release(struct usb_serial *serial) { int i; - dbg("%s", __func__); - for (i = 0; i < serial->num_ports; ++i) kfree(usb_get_serial_port_data(serial->port[i])); } @@ -170,8 +168,6 @@ static int belkin_sa_open(struct tty_struct *tty, { int retval; - dbg("%s port %d", __func__, port->number); - retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (retval) { dev_err(&port->dev, "usb_submit_urb(read int) failed\n"); @@ -187,8 +183,6 @@ static int belkin_sa_open(struct tty_struct *tty, static void belkin_sa_close(struct usb_serial_port *port) { - dbg("%s port %d", __func__, port->number); - usb_serial_generic_close(port); usb_kill_urb(port->interrupt_in_urb); } @@ -403,7 +397,8 @@ static void belkin_sa_set_termios(struct tty_struct *tty, case CS8: urb_value = BELKIN_SA_DATA_BITS(8); break; - default: dbg("CSIZE was not CS5-CS8, using default of 8"); + default: + dbg("CSIZE was not CS5-CS8, using default of 8"); urb_value = BELKIN_SA_DATA_BITS(8); break; } @@ -463,8 +458,6 @@ static int belkin_sa_tiocmget(struct tty_struct *tty) unsigned long control_state; unsigned long flags; - dbg("%s", __func__); - spin_lock_irqsave(&priv->lock, flags); control_state = priv->control_state; spin_unlock_irqrestore(&priv->lock, flags); @@ -484,8 +477,6 @@ static int belkin_sa_tiocmset(struct tty_struct *tty, int rts = 0; int dtr = 0; - dbg("%s", __func__); - spin_lock_irqsave(&priv->lock, flags); control_state = priv->control_state; diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index aaab32db31d0..70c46b0426ff 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -125,8 +125,6 @@ static int ch341_set_baudrate(struct usb_device *dev, unsigned long factor; short divisor; - dbg("ch341_set_baudrate(%d)", priv->baud_rate); - if (!priv->baud_rate) return -EINVAL; factor = (CH341_BAUDBASE_FACTOR / priv->baud_rate); @@ -153,7 +151,6 @@ static int ch341_set_baudrate(struct usb_device *dev, static int ch341_set_handshake(struct usb_device *dev, u8 control) { - dbg("ch341_set_handshake(0x%02x)", control); return ch341_control_out(dev, 0xa4, ~control, 0); } @@ -164,8 +161,6 @@ static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv) const unsigned size = 8; unsigned long flags; - dbg("ch341_get_status()"); - buffer = kmalloc(size, GFP_KERNEL); if (!buffer) return -ENOMEM; @@ -196,8 +191,6 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) int r; const unsigned size = 8; - dbg("ch341_configure()"); - buffer = kmalloc(size, GFP_KERNEL); if (!buffer) return -ENOMEM; @@ -254,8 +247,6 @@ static int ch341_attach(struct usb_serial *serial) struct ch341_private *priv; int r; - dbg("ch341_attach()"); - /* private data */ priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL); if (!priv) @@ -290,7 +281,6 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on) struct ch341_private *priv = usb_get_serial_port_data(port); unsigned long flags; - dbg("%s - port %d", __func__, port->number); /* drop DTR and RTS */ spin_lock_irqsave(&priv->lock, flags); if (on) @@ -304,8 +294,6 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on) static void ch341_close(struct usb_serial_port *port) { - dbg("%s - port %d", __func__, port->number); - usb_serial_generic_close(port); usb_kill_urb(port->interrupt_in_urb); } @@ -318,8 +306,6 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port) struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]); int r; - dbg("ch341_open()"); - priv->baud_rate = DEFAULT_BAUD_RATE; r = ch341_configure(serial->dev, priv); @@ -358,8 +344,6 @@ static void ch341_set_termios(struct tty_struct *tty, unsigned baud_rate; unsigned long flags; - dbg("ch341_set_termios()"); - baud_rate = tty_get_baud_rate(tty); priv->baud_rate = baud_rate; @@ -393,8 +377,6 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state) uint16_t reg_contents; uint8_t *break_reg; - dbg("%s()", __func__); - break_reg = kmalloc(2, GFP_KERNEL); if (!break_reg) { dev_err(&port->dev, "%s - kmalloc failed\n", __func__); @@ -461,8 +443,6 @@ static void ch341_read_int_callback(struct urb *urb) unsigned int actual_length = urb->actual_length; int status; - dbg("%s (%d)", __func__, port->number); - switch (urb->status) { case 0: /* success */ @@ -580,8 +560,6 @@ static int ch341_tiocmget(struct tty_struct *tty) u8 status; unsigned int result; - dbg("%s (%d)", __func__, port->number); - spin_lock_irqsave(&priv->lock, flags); mcr = priv->line_control; status = priv->line_status; diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 1ee6b2ab0f89..b9cca6dcde07 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -113,7 +113,8 @@ static int usb_console_setup(struct console *co, char *options) serial = usb_serial_get_by_index(co->index); if (serial == NULL) { /* no device is connected yet, sorry :( */ - err("No USB device connected to ttyUSB%i", co->index); + printk(KERN_ERR "No USB device connected to ttyUSB%i\n", + co->index); return -ENODEV; } @@ -137,7 +138,7 @@ static int usb_console_setup(struct console *co, char *options) tty = kzalloc(sizeof(*tty), GFP_KERNEL); if (!tty) { retval = -ENOMEM; - err("no more memory"); + dev_err(&port->dev, "no more memory\n"); goto reset_open_count; } kref_init(&tty->kref); @@ -146,7 +147,7 @@ static int usb_console_setup(struct console *co, char *options) tty->index = co->index; if (tty_init_termios(tty)) { retval = -ENOMEM; - err("no more memory"); + dev_err(&port->dev, "no more memory\n"); goto free_tty; } } @@ -159,7 +160,7 @@ static int usb_console_setup(struct console *co, char *options) retval = usb_serial_generic_open(NULL, port); if (retval) { - err("could not open USB console port"); + dev_err(&port->dev, "could not open USB console port\n"); goto fail; } diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index ec30f95ef399..81468c0f5e61 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -188,8 +188,10 @@ static struct usb_serial_driver * const serial_drivers[] = { }; /* Config request types */ -#define REQTYPE_HOST_TO_DEVICE 0x41 -#define REQTYPE_DEVICE_TO_HOST 0xc1 +#define REQTYPE_HOST_TO_INTERFACE 0x41 +#define REQTYPE_INTERFACE_TO_HOST 0xc1 +#define REQTYPE_HOST_TO_DEVICE 0x40 +#define REQTYPE_DEVICE_TO_HOST 0xc0 /* Config request codes */ #define CP210X_IFC_ENABLE 0x00 @@ -286,7 +288,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, /* Issue the request, attempting to read 'size' bytes */ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - request, REQTYPE_DEVICE_TO_HOST, 0x0000, + request, REQTYPE_INTERFACE_TO_HOST, 0x0000, port_priv->bInterfaceNumber, buf, size, USB_CTRL_GET_TIMEOUT); @@ -340,13 +342,13 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, if (size > 2) { result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - request, REQTYPE_HOST_TO_DEVICE, 0x0000, + request, REQTYPE_HOST_TO_INTERFACE, 0x0000, port_priv->bInterfaceNumber, buf, size, USB_CTRL_SET_TIMEOUT); } else { result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - request, REQTYPE_HOST_TO_DEVICE, data[0], + request, REQTYPE_HOST_TO_INTERFACE, data[0], port_priv->bInterfaceNumber, NULL, 0, USB_CTRL_SET_TIMEOUT); } @@ -422,8 +424,6 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port) { int result; - dbg("%s - port %d", __func__, port->number); - result = cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_ENABLE); if (result) { @@ -443,8 +443,6 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port) static void cp210x_close(struct usb_serial_port *port) { - dbg("%s - port %d", __func__, port->number); - usb_serial_generic_close(port); mutex_lock(&port->serial->disc_mutex); @@ -488,8 +486,6 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, unsigned int baud; unsigned int bits; - dbg("%s - port %d", __func__, port->number); - cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4); dbg("%s - baud rate = %d", __func__, baud); @@ -787,8 +783,6 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, { unsigned int control = 0; - dbg("%s - port %d", __func__, port->number); - if (set & TIOCM_RTS) { control |= CONTROL_RTS; control |= CONTROL_WRITE_RTS; @@ -825,8 +819,6 @@ static int cp210x_tiocmget (struct tty_struct *tty) unsigned int control; int result; - dbg("%s - port %d", __func__, port->number); - cp210x_get_config(port, CP210X_GET_MDMSTS, &control, 1); result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0) @@ -846,7 +838,6 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state) struct usb_serial_port *port = tty->driver_data; unsigned int state; - dbg("%s - port %d", __func__, port->number); if (break_state == 0) state = BREAK_OFF; else diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index d39b9418f2fb..7b804fd397c9 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -122,8 +122,6 @@ static int cyberjack_startup(struct usb_serial *serial) struct cyberjack_private *priv; int i; - dbg("%s", __func__); - /* allocate the private data structure */ priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL); if (!priv) @@ -155,8 +153,6 @@ static void cyberjack_disconnect(struct usb_serial *serial) { int i; - dbg("%s", __func__); - for (i = 0; i < serial->num_ports; ++i) usb_kill_urb(serial->port[i]->interrupt_in_urb); } @@ -165,8 +161,6 @@ static void cyberjack_release(struct usb_serial *serial) { int i; - dbg("%s", __func__); - for (i = 0; i < serial->num_ports; ++i) { /* My special items, the standard routines free my urbs */ kfree(usb_get_serial_port_data(serial->port[i])); @@ -180,8 +174,6 @@ static int cyberjack_open(struct tty_struct *tty, unsigned long flags; int result = 0; - dbg("%s - port %d", __func__, port->number); - dbg("%s - usb_clear_halt", __func__); usb_clear_halt(port->serial->dev, port->write_urb->pipe); @@ -197,8 +189,6 @@ static int cyberjack_open(struct tty_struct *tty, static void cyberjack_close(struct usb_serial_port *port) { - dbg("%s - port %d", __func__, port->number); - if (port->serial->dev) { /* shutdown any bulk reads that might be going on */ usb_kill_urb(port->write_urb); @@ -214,8 +204,6 @@ static int cyberjack_write(struct tty_struct *tty, int result; int wrexpected; - dbg("%s - port %d", __func__, port->number); - if (count == 0) { dbg("%s - write request of 0 bytes", __func__); return 0; @@ -307,8 +295,6 @@ static void cyberjack_read_int_callback(struct urb *urb) int status = urb->status; int result; - dbg("%s - port %d", __func__, port->number); - /* the urb might have been killed. */ if (status) return; @@ -367,8 +353,6 @@ static void cyberjack_read_bulk_callback(struct urb *urb) int result; int status = urb->status; - dbg("%s - port %d", __func__, port->number); - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); if (status) { @@ -417,8 +401,6 @@ static void cyberjack_write_bulk_callback(struct urb *urb) struct cyberjack_private *priv = usb_get_serial_port_data(port); int status = urb->status; - dbg("%s - port %d", __func__, port->number); - set_bit(0, &port->write_urbs_free); if (status) { dbg("%s - nonzero write bulk status received: %d", diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index afc886c75d2f..6fac26c5fd53 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -305,8 +305,6 @@ static int cypress_serial_control(struct tty_struct *tty, const unsigned int feature_len = 5; unsigned long flags; - dbg("%s", __func__); - priv = usb_get_serial_port_data(port); if (!priv->comm_is_ok) @@ -451,8 +449,6 @@ static int generic_startup(struct usb_serial *serial) struct cypress_private *priv; struct usb_serial_port *port = serial->port[0]; - dbg("%s - port %d", __func__, port->number); - priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -505,8 +501,6 @@ static int cypress_earthmate_startup(struct usb_serial *serial) struct cypress_private *priv; struct usb_serial_port *port = serial->port[0]; - dbg("%s", __func__); - if (generic_startup(serial)) { dbg("%s - Failed setting up port %d", __func__, port->number); @@ -537,8 +531,6 @@ static int cypress_hidcom_startup(struct usb_serial *serial) { struct cypress_private *priv; - dbg("%s", __func__); - if (generic_startup(serial)) { dbg("%s - Failed setting up port %d", __func__, serial->port[0]->number); @@ -556,8 +548,6 @@ static int cypress_ca42v2_startup(struct usb_serial *serial) { struct cypress_private *priv; - dbg("%s", __func__); - if (generic_startup(serial)) { dbg("%s - Failed setting up port %d", __func__, serial->port[0]->number); @@ -575,10 +565,7 @@ static void cypress_release(struct usb_serial *serial) { struct cypress_private *priv; - dbg("%s - port %d", __func__, serial->port[0]->number); - /* all open ports are closed at this point */ - priv = usb_get_serial_port_data(serial->port[0]); if (priv) { @@ -595,8 +582,6 @@ static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port) unsigned long flags; int result = 0; - dbg("%s - port %d", __func__, port->number); - if (!priv->comm_is_ok) return -EIO; @@ -661,8 +646,6 @@ static void cypress_close(struct usb_serial_port *port) struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; - dbg("%s - port %d", __func__, port->number); - /* writing is potentially harmful, lock must be taken */ mutex_lock(&port->serial->disc_mutex); if (port->serial->disconnected) { @@ -720,7 +703,6 @@ static void cypress_send(struct usb_serial_port *port) if (!priv->comm_is_ok) return; - dbg("%s - port %d", __func__, port->number); dbg("%s - interrupt out size is %d", __func__, port->interrupt_out_size); @@ -828,8 +810,6 @@ static int cypress_write_room(struct tty_struct *tty) int room = 0; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&priv->lock, flags); room = kfifo_avail(&priv->write_fifo); spin_unlock_irqrestore(&priv->lock, flags); @@ -847,8 +827,6 @@ static int cypress_tiocmget(struct tty_struct *tty) unsigned int result = 0; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&priv->lock, flags); control = priv->line_control; status = priv->current_status; @@ -874,8 +852,6 @@ static int cypress_tiocmset(struct tty_struct *tty, struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; - dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&priv->lock, flags); if (set & TIOCM_RTS) priv->line_control |= CONTROL_RTS; @@ -948,8 +924,6 @@ static void cypress_set_termios(struct tty_struct *tty, __u8 oldlines; int linechange = 0; - dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&priv->lock, flags); /* We can't clean this one up as we don't know the device type early enough */ @@ -1096,8 +1070,6 @@ static int cypress_chars_in_buffer(struct tty_struct *tty) int chars = 0; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&priv->lock, flags); chars = kfifo_len(&priv->write_fifo); spin_unlock_irqrestore(&priv->lock, flags); @@ -1112,8 +1084,6 @@ static void cypress_throttle(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); - dbg("%s - port %d", __func__, port->number); - spin_lock_irq(&priv->lock); priv->rx_flags = THROTTLED; spin_unlock_irq(&priv->lock); @@ -1126,8 +1096,6 @@ static void cypress_unthrottle(struct tty_struct *tty) struct cypress_private *priv = usb_get_serial_port_data(port); int actually_throttled, result; - dbg("%s - port %d", __func__, port->number); - spin_lock_irq(&priv->lock); actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED; priv->rx_flags = 0; @@ -1161,8 +1129,6 @@ static void cypress_read_int_callback(struct urb *urb) int i = 0; int status = urb->status; - dbg("%s - port %d", __func__, port->number); - switch (status) { case 0: /* success */ break; @@ -1303,8 +1269,6 @@ static void cypress_write_int_callback(struct urb *urb) int result; int status = urb->status; - dbg("%s - port %d", __func__, port->number); - switch (status) { case 0: /* success */ diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 999f91bf70de..f8dad3a3427b 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -657,9 +657,6 @@ static void digi_rx_throttle(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; struct digi_port *priv = usb_get_serial_port_data(port); - - dbg("digi_rx_throttle: TOP: port=%d", priv->dp_port_num); - /* stop receiving characters by not resubmitting the read urb */ spin_lock_irqsave(&priv->dp_port_lock, flags); priv->dp_throttled = 1; @@ -675,8 +672,6 @@ static void digi_rx_unthrottle(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; struct digi_port *priv = usb_get_serial_port_data(port); - dbg("digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num); - spin_lock_irqsave(&priv->dp_port_lock, flags); /* restart read chain */ @@ -904,8 +899,6 @@ static int digi_tiocmget(struct tty_struct *tty) unsigned int val; unsigned long flags; - dbg("%s: TOP: port=%d", __func__, priv->dp_port_num); - spin_lock_irqsave(&priv->dp_port_lock, flags); val = priv->dp_modem_signals; spin_unlock_irqrestore(&priv->dp_port_lock, flags); @@ -921,8 +914,6 @@ static int digi_tiocmset(struct tty_struct *tty, unsigned int val; unsigned long flags; - dbg("%s: TOP: port=%d", __func__, priv->dp_port_num); - spin_lock_irqsave(&priv->dp_port_lock, flags); val = (priv->dp_modem_signals & ~clear) | set; spin_unlock_irqrestore(&priv->dp_port_lock, flags); @@ -1013,8 +1004,6 @@ static void digi_write_bulk_callback(struct urb *urb) int ret = 0; int status = urb->status; - dbg("digi_write_bulk_callback: TOP, status=%d", status); - /* port and serial sanity check */ if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) { pr_err("%s: port or port->private is NULL, status=%d\n", @@ -1121,8 +1110,6 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port) struct digi_port *priv = usb_get_serial_port_data(port); struct ktermios not_termios; - dbg("digi_open: TOP: port=%d", priv->dp_port_num); - /* be sure the device is started up */ if (digi_startup_device(port->serial) != 0) return -ENXIO; @@ -1160,8 +1147,6 @@ static void digi_close(struct usb_serial_port *port) unsigned char buf[32]; struct digi_port *priv = usb_get_serial_port_data(port); - dbg("digi_close: TOP: port=%d", priv->dp_port_num); - mutex_lock(&port->serial->disc_mutex); /* if disconnected, just clear flags */ if (port->serial->disconnected) @@ -1220,7 +1205,6 @@ exit: wake_up_interruptible(&priv->dp_close_wait); spin_unlock_irq(&priv->dp_port_lock); mutex_unlock(&port->serial->disc_mutex); - dbg("digi_close: done"); } @@ -1269,8 +1253,6 @@ static int digi_startup(struct usb_serial *serial) struct digi_port *priv; struct digi_serial *serial_priv; - dbg("digi_startup: TOP"); - /* allocate the private data structures for all ports */ /* number of regular ports + 1 for the out-of-band port */ for (i = 0; i < serial->type->num_ports + 1; i++) { @@ -1325,7 +1307,6 @@ static int digi_startup(struct usb_serial *serial) static void digi_disconnect(struct usb_serial *serial) { int i; - dbg("digi_disconnect: TOP, in_interrupt()=%ld", in_interrupt()); /* stop reads and writes on all ports */ for (i = 0; i < serial->type->num_ports + 1; i++) { @@ -1338,7 +1319,6 @@ static void digi_disconnect(struct usb_serial *serial) static void digi_release(struct usb_serial *serial) { int i; - dbg("digi_release: TOP, in_interrupt()=%ld", in_interrupt()); /* free the private data structures for all ports */ /* number of regular ports + 1 for the out-of-band port */ @@ -1356,8 +1336,6 @@ static void digi_read_bulk_callback(struct urb *urb) int ret; int status = urb->status; - dbg("digi_read_bulk_callback: TOP"); - /* port sanity check, do not resubmit if port is not valid */ if (port == NULL) return; @@ -1507,9 +1485,6 @@ static int digi_read_oob_callback(struct urb *urb) int i; unsigned int rts; - dbg("digi_read_oob_callback: port=%d, len=%d", - priv->dp_port_num, urb->actual_length); - /* handle each oob command */ for (i = 0; i < urb->actual_length - 3;) { opcode = ((unsigned char *)urb->transfer_buffer)[i++]; diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 5b99fc09e327..615e3803cfb9 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -80,14 +80,12 @@ static int empeg_startup(struct usb_serial *serial) { int r; - dbg("%s", __func__); - if (serial->dev->actconfig->desc.bConfigurationValue != 1) { dev_err(&serial->dev->dev, "active config #%d != 1 ??\n", serial->dev->actconfig->desc.bConfigurationValue); return -ENODEV; } - dbg("%s - reset config", __func__); + r = usb_reset_configuration(serial->dev); /* continue on with initialization */ diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c index 3cfc762f5056..800e8eb60003 100644 --- a/drivers/usb/serial/ezusb.c +++ b/drivers/usb/serial/ezusb.c @@ -26,7 +26,6 @@ int ezusb_writememory(struct usb_serial *serial, int address, int result; unsigned char *transfer_buffer; - /* dbg("ezusb_writememory %x, %d", address, length); */ if (!serial->dev) { printk(KERN_ERR "ezusb: %s - no physical device present, " "failing.\n", __func__); @@ -50,7 +49,6 @@ int ezusb_set_reset(struct usb_serial *serial, unsigned char reset_bit) { int response; - /* dbg("%s - %d", __func__, reset_bit); */ response = ezusb_writememory(serial, CPUCS_REG, &reset_bit, 1, 0xa0); if (response < 0) dev_err(&serial->dev->dev, "%s- %d failed\n", diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 88c0b1963920..46aee85210e2 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -68,8 +68,6 @@ static void f81232_read_int_callback(struct urb *urb) int status = urb->status; int retval; - dbg("%s (%d)", __func__, port->number); - switch (status) { case 0: /* success */ @@ -203,7 +201,6 @@ static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port) 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," diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 02e7f2d32d52..5691b8be0c77 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1285,8 +1285,6 @@ static int read_latency_timer(struct usb_serial_port *port) unsigned char *buf; int rv; - dbg("%s", __func__); - buf = kmalloc(1, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -1593,8 +1591,6 @@ static int create_sysfs_attrs(struct usb_serial_port *port) struct ftdi_private *priv = usb_get_serial_port_data(port); int retval = 0; - dbg("%s", __func__); - /* XXX I've no idea if the original SIO supports the event_char * sysfs parameter, so I'm playing it safe. */ if (priv->chip_type != SIO) { @@ -1619,8 +1615,6 @@ static void remove_sysfs_attrs(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); - dbg("%s", __func__); - /* XXX see create_sysfs_attrs */ if (priv->chip_type != SIO) { device_remove_file(&port->dev, &dev_attr_event_char); @@ -1667,8 +1661,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial); - dbg("%s", __func__); - priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); if (!priv) { dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__, @@ -1704,8 +1696,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) /* Called from usbserial:serial_probe */ static void ftdi_USB_UIRT_setup(struct ftdi_private *priv) { - dbg("%s", __func__); - priv->flags |= ASYNC_SPD_CUST; priv->custom_divisor = 77; priv->force_baud = 38400; @@ -1716,8 +1706,6 @@ static void ftdi_USB_UIRT_setup(struct ftdi_private *priv) static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv) { - dbg("%s", __func__); - priv->flags |= ASYNC_SPD_CUST; priv->custom_divisor = 240; priv->force_baud = 38400; @@ -1767,8 +1755,6 @@ static int ftdi_jtag_probe(struct usb_serial *serial) struct usb_device *udev = serial->dev; struct usb_interface *interface = serial->interface; - dbg("%s", __func__); - if (interface == udev->actconfig->interface[0]) { dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n"); @@ -1782,8 +1768,6 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial) { struct usb_device *udev = serial->dev; - dbg("%s", __func__); - if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) || (udev->product && !strcmp(udev->product, "BeagleBone/XDS100"))) return ftdi_jtag_probe(serial); @@ -1800,8 +1784,6 @@ static int ftdi_stmclite_probe(struct usb_serial *serial) struct usb_device *udev = serial->dev; struct usb_interface *interface = serial->interface; - dbg("%s", __func__); - if (interface == udev->actconfig->interface[2]) return 0; @@ -1839,8 +1821,6 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); - dbg("%s", __func__); - priv->dev_gone = true; wake_up_interruptible_all(&priv->delta_msr_wait); @@ -1858,8 +1838,6 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) struct ftdi_private *priv = usb_get_serial_port_data(port); int result; - dbg("%s", __func__); - /* No error checking for this (will get errors later anyway) */ /* See ftdi_sio.h for description of what is reset */ usb_control_msg(dev, usb_sndctrlpipe(dev, 0), @@ -1918,8 +1896,6 @@ static void ftdi_close(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); - dbg("%s", __func__); - usb_serial_generic_close(port); kref_put(&priv->kref, ftdi_sio_priv_release); } @@ -1976,8 +1952,6 @@ static int ftdi_process_packet(struct tty_struct *tty, char flag; char *ch; - dbg("%s - port %d", __func__, port->number); - if (len < 2) { dbg("malformed packet"); return 0; @@ -2121,8 +2095,6 @@ static void ftdi_set_termios(struct tty_struct *tty, unsigned char vstop; unsigned char vstart; - dbg("%s", __func__); - /* Force baud rate if this device requires it, unless it is set to B0. */ if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) { @@ -2295,8 +2267,6 @@ static int ftdi_tiocmget(struct tty_struct *tty) int len; int ret; - dbg("%s TIOCMGET", __func__); - buf = kmalloc(2, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -2346,7 +2316,7 @@ static int ftdi_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; - dbg("%s TIOCMSET", __func__); + return update_mctrl(port, set, clear); } @@ -2435,7 +2405,6 @@ static int __init ftdi_init(void) { int retval; - dbg("%s", __func__); if (vendor > 0 && product > 0) { /* Add user specified VID/PID to reserved element of table. */ int i; @@ -2454,8 +2423,6 @@ static int __init ftdi_init(void) static void __exit ftdi_exit(void) { - dbg("%s", __func__); - usb_serial_deregister_drivers(&ftdi_driver, serial_drivers); } diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index e8eb6347bf3a..52c079d02ca3 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -345,8 +345,6 @@ static void pkt_clear(struct garmin_data *garmin_data_p) unsigned long flags; struct garmin_packet *result = NULL; - dbg("%s", __func__); - spin_lock_irqsave(&garmin_data_p->lock, flags); while (!list_empty(&garmin_data_p->pktlist)) { result = (struct garmin_packet *)garmin_data_p->pktlist.next; @@ -939,8 +937,6 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port) int status = 0; struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); - dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&garmin_data_p->lock, flags); garmin_data_p->mode = initial_mode; garmin_data_p->count = 0; @@ -996,8 +992,6 @@ static void garmin_write_bulk_callback(struct urb *urb) struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); - dbg("%s - port %d", __func__, port->number); - if (GARMIN_LAYERID_APPL == getLayerId(urb->transfer_buffer)) { if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { @@ -1027,9 +1021,6 @@ static int garmin_write_bulk(struct usb_serial_port *port, unsigned char *buffer; int status; - dbg("%s - port %d, state %d", __func__, port->number, - garmin_data_p->state); - spin_lock_irqsave(&garmin_data_p->lock, flags); garmin_data_p->flags &= ~FLAGS_DROP_DATA; spin_unlock_irqrestore(&garmin_data_p->lock, flags); @@ -1224,8 +1215,6 @@ static void garmin_read_bulk_callback(struct urb *urb) int status = urb->status; int retval; - dbg("%s - port %d", __func__, port->number); - if (!serial) { dbg("%s - bad serial pointer, exiting", __func__); return; @@ -1384,7 +1373,6 @@ static void garmin_throttle(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); - dbg("%s - port %d", __func__, port->number); /* set flag, data received will be put into a queue for later processing */ spin_lock_irq(&garmin_data_p->lock); @@ -1399,7 +1387,6 @@ static void garmin_unthrottle(struct tty_struct *tty) struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); int status; - dbg("%s - port %d", __func__, port->number); spin_lock_irq(&garmin_data_p->lock); garmin_data_p->flags &= ~FLAGS_THROTTLED; spin_unlock_irq(&garmin_data_p->lock); @@ -1441,8 +1428,6 @@ static int garmin_attach(struct usb_serial *serial) struct usb_serial_port *port = serial->port[0]; struct garmin_data *garmin_data_p = NULL; - dbg("%s", __func__); - garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL); if (garmin_data_p == NULL) { dev_err(&port->dev, "%s - Out of memory\n", __func__); @@ -1471,8 +1456,6 @@ static void garmin_disconnect(struct usb_serial *serial) struct usb_serial_port *port = serial->port[0]; struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); - dbg("%s", __func__); - usb_kill_urb(port->interrupt_in_urb); del_timer_sync(&garmin_data_p->timer); } @@ -1483,8 +1466,6 @@ static void garmin_release(struct usb_serial *serial) struct usb_serial_port *port = serial->port[0]; struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); - dbg("%s", __func__); - kfree(garmin_data_p); } diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 664deb63807c..2cc39badf90a 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -117,8 +117,6 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port int result = 0; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - /* clear the throttle flags */ spin_lock_irqsave(&port->lock, flags); port->throttled = 0; @@ -139,12 +137,9 @@ static void generic_cleanup(struct usb_serial_port *port) unsigned long flags; int i; - dbg("%s - port %d", __func__, port->number); - if (serial->dev) { /* shutdown any bulk transfers that might be going on */ if (port->bulk_out_size) { - usb_kill_urb(port->write_urb); for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) usb_kill_urb(port->write_urbs[i]); @@ -161,7 +156,6 @@ static void generic_cleanup(struct usb_serial_port *port) void usb_serial_generic_close(struct usb_serial_port *port) { - dbg("%s - port %d", __func__, port->number); generic_cleanup(port); } EXPORT_SYMBOL_GPL(usb_serial_generic_close); @@ -249,8 +243,6 @@ int usb_serial_generic_write(struct tty_struct *tty, { int result; - dbg("%s - port %d", __func__, port->number); - /* only do something if we have a bulk out endpoint */ if (!port->bulk_out_size) return -ENODEV; @@ -273,8 +265,6 @@ int usb_serial_generic_write_room(struct tty_struct *tty) unsigned long flags; int room; - dbg("%s - port %d", __func__, port->number); - if (!port->bulk_out_size) return 0; @@ -292,8 +282,6 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) unsigned long flags; int chars; - dbg("%s - port %d", __func__, port->number); - if (!port->bulk_out_size) return 0; @@ -313,7 +301,7 @@ static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port, if (!test_and_clear_bit(index, &port->read_urbs_free)) return 0; - dbg("%s - port %d, urb %d\n", __func__, port->number, index); + dbg("%s - port %d, urb %d", __func__, port->number, index); res = usb_submit_urb(port->read_urbs[index], mem_flags); if (res) { @@ -335,8 +323,6 @@ int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port, int res; int i; - dbg("%s - port %d", __func__, port->number); - for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) { res = usb_serial_generic_submit_read_urb(port, i, mem_flags); if (res) @@ -395,10 +381,10 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb) } set_bit(i, &port->read_urbs_free); - dbg("%s - port %d, urb %d, len %d\n", __func__, port->number, i, + dbg("%s - port %d, urb %d, len %d", __func__, port->number, i, urb->actual_length); if (urb->status) { - dbg("%s - non-zero urb status: %d\n", __func__, urb->status); + dbg("%s - non-zero urb status: %d", __func__, urb->status); return; } @@ -424,8 +410,6 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) int status = urb->status; int i; - dbg("%s - port %d", __func__, port->number); - for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) if (port->write_urbs[i] == urb) break; @@ -454,8 +438,6 @@ void usb_serial_generic_throttle(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - /* Set the throttle request flag. It will be picked up * by usb_serial_generic_read_bulk_callback(). */ spin_lock_irqsave(&port->lock, flags); @@ -469,8 +451,6 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; int was_throttled; - dbg("%s - port %d", __func__, port->number); - /* Clear the throttle flags */ spin_lock_irq(&port->lock); was_throttled = port->throttled; @@ -566,8 +546,6 @@ void usb_serial_generic_disconnect(struct usb_serial *serial) { int i; - dbg("%s", __func__); - /* stop reads and writes on all ports */ for (i = 0; i < serial->num_ports; ++i) generic_cleanup(serial->port[i]); @@ -576,5 +554,4 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect); void usb_serial_generic_release(struct usb_serial *serial) { - dbg("%s", __func__); } diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 40a95a7fe383..5e4b47194819 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -547,6 +547,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, { int baud_rate; struct tty_struct *tty = tty_port_tty_get(&port->port->port); + struct usb_serial *serial = port->port->serial; wait_queue_t wait; unsigned long flags; @@ -561,7 +562,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, set_current_state(TASK_INTERRUPTIBLE); if (kfifo_len(&port->write_fifo) == 0 || timeout == 0 || signal_pending(current) - || !usb_get_intfdata(port->port->serial->interface)) + || serial->disconnected) /* disconnect */ break; spin_unlock_irqrestore(&port->ep_lock, flags); @@ -578,7 +579,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, /* wait for data to drain from the device */ timeout += jiffies; while ((long)(jiffies - timeout) < 0 && !signal_pending(current) - && usb_get_intfdata(port->port->serial->interface)) { + && !serial->disconnected) { /* not disconnected */ if (!tx_active(port)) break; @@ -586,7 +587,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, } /* disconnected */ - if (!usb_get_intfdata(port->port->serial->interface)) + if (serial->disconnected) return; /* wait one more character time, based on baud rate */ @@ -2003,8 +2004,8 @@ static void edge_close(struct usb_serial_port *port) { struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; + struct usb_serial *serial = port->serial; int port_number; - int status; dbg("%s - port %d", __func__, port->number); @@ -2028,12 +2029,18 @@ static void edge_close(struct usb_serial_port *port) * send a close port command to it */ dbg("%s - send umpc_close_port", __func__); port_number = port->number - port->serial->minor; - status = send_cmd(port->serial->dev, + + mutex_lock(&serial->disc_mutex); + if (!serial->disconnected) { + send_cmd(serial->dev, UMPC_CLOSE_PORT, (__u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0); + } + mutex_unlock(&serial->disc_mutex); + mutex_lock(&edge_serial->es_lock); --edge_port->edge_serial->num_ports_open; if (edge_port->edge_serial->num_ports_open <= 0) { diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 10c02b8b5664..65b689a4e36f 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -33,7 +33,6 @@ #define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>" #define DRIVER_DESC "USB PocketPC PDA driver" -static __u16 product, vendor; static bool debug; static int connect_retries = KP_RETRIES; static int initial_wait; @@ -45,8 +44,6 @@ static int ipaq_calc_num_ports(struct usb_serial *serial); static int ipaq_startup(struct usb_serial *serial); static struct usb_device_id ipaq_id_table [] = { - /* The first entry is a placeholder for the insmod-specified device */ - { USB_DEVICE(0x049F, 0x0003) }, { USB_DEVICE(0x0104, 0x00BE) }, /* Socket USB Sync */ { USB_DEVICE(0x03F0, 0x1016) }, /* HP USB Sync */ { USB_DEVICE(0x03F0, 0x1116) }, /* HP USB Sync 1611 */ @@ -539,8 +536,6 @@ static int ipaq_open(struct tty_struct *tty, int result = 0; int retries = connect_retries; - dbg("%s - port %d", __func__, port->number); - msleep(1000*initial_wait); /* @@ -596,8 +591,6 @@ static int ipaq_calc_num_ports(struct usb_serial *serial) static int ipaq_startup(struct usb_serial *serial) { - dbg("%s", __func__); - /* Some of the devices in ipaq_id_table[] are composite, and we * shouldn't bind to all the interfaces. This test will rule out * some obviously invalid possibilities. @@ -623,30 +616,7 @@ static int ipaq_startup(struct usb_serial *serial) return usb_reset_configuration(serial->dev); } -static int __init ipaq_init(void) -{ - int retval; - - if (vendor) { - ipaq_id_table[0].idVendor = vendor; - ipaq_id_table[0].idProduct = product; - } - - 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_serial_deregister_drivers(&ipaq_driver, serial_drivers); -} - - -module_init(ipaq_init); -module_exit(ipaq_exit); +module_usb_serial_driver(ipaq_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); @@ -655,12 +625,6 @@ MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); -module_param(vendor, ushort, 0); -MODULE_PARM_DESC(vendor, "User specified USB idVendor"); - -module_param(product, ushort, 0); -MODULE_PARM_DESC(product, "User specified USB idProduct"); - module_param(connect_retries, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(connect_retries, "Maximum number of connect retries (one second each)"); diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 76a06406e26a..52c61d7cecd2 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -155,8 +155,6 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port) u8 *buf_flow_init; int result; - dbg("%s", __func__); - buf_flow_init = kmemdup(buf_flow_static, 16, GFP_KERNEL); if (!buf_flow_init) return -ENOMEM; diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 84965cd65c76..ea09cf7044d7 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -264,8 +264,6 @@ static int ir_open(struct tty_struct *tty, struct usb_serial_port *port) { int i; - dbg("%s - port %d", __func__, port->number); - for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) port->write_urbs[i]->transfer_flags = URB_ZERO_PACKET; @@ -322,15 +320,10 @@ static void ir_process_read_urb(struct urb *urb) static void ir_set_termios_callback(struct urb *urb) { - struct usb_serial_port *port = urb->context; - int status = urb->status; - - dbg("%s - port %d", __func__, port->number); - kfree(urb->transfer_buffer); - if (status) - dbg("%s - non-zero urb status: %d", __func__, status); + if (urb->status) + dbg("%s - non-zero urb status: %d", __func__, urb->status); } static void ir_set_termios(struct tty_struct *tty, @@ -342,8 +335,6 @@ static void ir_set_termios(struct tty_struct *tty, speed_t baud; int ir_baud; - dbg("%s - port %d", __func__, port->number); - baud = tty_get_baud_rate(tty); /* diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index f2192d527db0..c40e5c2d2bb4 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -135,8 +135,6 @@ static void iuu_release(struct usb_serial *serial) if (!port) return; - dbg("%s", __func__); - if (priv) { iuu_free_buf(priv); dbg("%s - I will free all", __func__); @@ -198,8 +196,6 @@ static void iuu_rxcmd(struct urb *urb) int result; int status = urb->status; - dbg("%s - enter", __func__); - if (status) { dbg("%s - status = %d", __func__, status); /* error stop all */ @@ -221,7 +217,6 @@ static int iuu_reset(struct usb_serial_port *port, u8 wt) struct iuu_private *priv = usb_get_serial_port_data(port); int result; char *buf_ptr = port->write_urb->transfer_buffer; - dbg("%s - enter", __func__); /* Prepare the reset sequence */ @@ -255,8 +250,6 @@ static void iuu_update_status_callback(struct urb *urb) u8 *st; int status = urb->status; - dbg("%s - enter", __func__); - if (status) { dbg("%s - status = %d", __func__, status); /* error stop all */ @@ -299,8 +292,6 @@ static int iuu_status(struct usb_serial_port *port) { int result; - dbg("%s - enter", __func__); - memset(port->write_urb->transfer_buffer, IUU_GET_STATE_REGISTER, 1); usb_fill_bulk_urb(port->write_urb, port->serial->dev, usb_sndbulkpipe(port->serial->dev, @@ -318,8 +309,6 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count) struct usb_serial *serial = port->serial; int actual = 0; - dbg("%s - enter", __func__); - /* send the data out the bulk port */ status = @@ -341,10 +330,7 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count) struct usb_serial *serial = port->serial; int actual = 0; - dbg("%s - enter", __func__); - /* send the data out the bulk port */ - status = usb_bulk_msg(serial->dev, usb_rcvbulkpipe(serial->dev, @@ -367,8 +353,6 @@ static int iuu_led(struct usb_serial_port *port, unsigned int R, if (!buf) return -ENOMEM; - dbg("%s - enter", __func__); - buf[0] = IUU_SET_LED; buf[1] = R & 0xFF; buf[2] = (R >> 8) & 0xFF; @@ -460,8 +444,6 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq) unsigned int P2 = 0; int frq = (int)dwFrq; - dbg("%s - enter", __func__); - if (frq == 0) { priv->buf[Count++] = IUU_UART_WRITE_I2C; priv->buf[Count++] = FrqGenAdr << 1; @@ -590,8 +572,6 @@ static int iuu_uart_flush(struct usb_serial_port *port) u8 rxcmd = IUU_UART_RX; struct iuu_private *priv = usb_get_serial_port_data(port); - dbg("%s - enter", __func__); - if (iuu_led(port, 0xF000, 0, 0, 0xFF) < 0) return -EIO; @@ -630,8 +610,6 @@ static void read_buf_callback(struct urb *urb) struct tty_struct *tty; int status = urb->status; - dbg("%s - status = %d", __func__, status); - if (status) { if (status == -EPROTO) { /* reschedule needed */ @@ -659,7 +637,6 @@ static int iuu_bulk_write(struct usb_serial_port *port) int i; int buf_len; char *buf_ptr = port->write_urb->transfer_buffer; - dbg("%s - enter", __func__); spin_lock_irqsave(&priv->lock, flags); *buf_ptr++ = IUU_UART_ESC; @@ -691,7 +668,6 @@ static int iuu_bulk_write(struct usb_serial_port *port) static int iuu_read_buf(struct usb_serial_port *port, int len) { int result; - dbg("%s - enter", __func__); usb_fill_bulk_urb(port->read_urb, port->serial->dev, usb_rcvbulkpipe(port->serial->dev, @@ -713,8 +689,6 @@ static void iuu_uart_read_callback(struct urb *urb) unsigned char *data = urb->transfer_buffer; priv->poll++; - dbg("%s - enter", __func__); - if (status) { dbg("%s - status = %d", __func__, status); /* error stop all */ @@ -771,7 +745,6 @@ static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port, { struct iuu_private *priv = usb_get_serial_port_data(port); unsigned long flags; - dbg("%s - enter", __func__); if (count > 256) return -ENOMEM; @@ -792,8 +765,6 @@ static void read_rxcmd_callback(struct urb *urb) int result; int status = urb->status; - dbg("%s - status = %d", __func__, status); - if (status) { /* error stop all */ return; @@ -1015,8 +986,6 @@ static void iuu_close(struct usb_serial_port *port) if (!serial) return; - dbg("%s - port %d", __func__, port->number); - iuu_uart_off(port); if (serial->dev) { /* free writebuf */ @@ -1031,7 +1000,6 @@ static void iuu_close(struct usb_serial_port *port) static void iuu_init_termios(struct tty_struct *tty) { - dbg("%s - enter", __func__); *(tty->termios) = tty_std_termios; tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600 | TIOCM_CTS | CSTOPB | PARENB; @@ -1188,8 +1156,6 @@ static int iuu_vcc_set(struct usb_serial_port *port, unsigned int vcc) if (!buf) return -ENOMEM; - dbg("%s - enter", __func__); - buf[0] = IUU_SET_VCC; buf[1] = vcc & 0xFF; buf[2] = (vcc >> 8) & 0xFF; @@ -1250,15 +1216,11 @@ static DEVICE_ATTR(vcc_mode, S_IRUSR | S_IWUSR, show_vcc_mode, static int iuu_create_sysfs_attrs(struct usb_serial_port *port) { - dbg("%s", __func__); - return device_create_file(&port->dev, &dev_attr_vcc_mode); } static int iuu_remove_sysfs_attrs(struct usb_serial_port *port) { - dbg("%s", __func__); - device_remove_file(&port->dev, &dev_attr_vcc_mode); return 0; } diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index a39ddd1b0dca..ec46053ad15f 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -137,8 +137,6 @@ static void keyspan_break_ctl(struct tty_struct *tty, int break_state) struct usb_serial_port *port = tty->driver_data; struct keyspan_port_private *p_priv; - dbg("%s", __func__); - p_priv = usb_get_serial_port_data(port); if (break_state == -1) @@ -158,8 +156,6 @@ static void keyspan_set_termios(struct tty_struct *tty, const struct keyspan_device_details *d_details; unsigned int cflag; - dbg("%s", __func__); - p_priv = usb_get_serial_port_data(port); d_details = p_priv->device_details; cflag = tty->termios->c_cflag; @@ -306,8 +302,6 @@ static void usa26_indat_callback(struct urb *urb) unsigned char *data = urb->transfer_buffer; int status = urb->status; - dbg("%s", __func__); - endpoint = usb_pipeendpoint(urb->pipe); if (status) { @@ -369,8 +363,6 @@ static void usa2x_outdat_callback(struct urb *urb) static void usa26_inack_callback(struct urb *urb) { - dbg("%s", __func__); - } static void usa26_outcont_callback(struct urb *urb) @@ -452,7 +444,6 @@ exit: ; static void usa26_glocont_callback(struct urb *urb) { - dbg("%s", __func__); } @@ -465,8 +456,6 @@ static void usa28_indat_callback(struct urb *urb) struct keyspan_port_private *p_priv; int status = urb->status; - dbg("%s", __func__); - port = urb->context; p_priv = usb_get_serial_port_data(port); data = urb->transfer_buffer; @@ -505,7 +494,6 @@ static void usa28_indat_callback(struct urb *urb) static void usa28_inack_callback(struct urb *urb) { - dbg("%s", __func__); } static void usa28_outcont_callback(struct urb *urb) @@ -585,7 +573,6 @@ exit: ; static void usa28_glocont_callback(struct urb *urb) { - dbg("%s", __func__); } @@ -596,8 +583,6 @@ static void usa49_glocont_callback(struct urb *urb) struct keyspan_port_private *p_priv; int i; - dbg("%s", __func__); - serial = urb->context; for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; @@ -625,8 +610,6 @@ static void usa49_instat_callback(struct urb *urb) int old_dcd_state; int status = urb->status; - dbg("%s", __func__); - serial = urb->context; if (status) { @@ -679,7 +662,6 @@ exit: ; static void usa49_inack_callback(struct urb *urb) { - dbg("%s", __func__); } static void usa49_indat_callback(struct urb *urb) @@ -691,8 +673,6 @@ static void usa49_indat_callback(struct urb *urb) unsigned char *data = urb->transfer_buffer; int status = urb->status; - dbg("%s", __func__); - endpoint = usb_pipeendpoint(urb->pipe); if (status) { @@ -742,8 +722,6 @@ static void usa49wg_indat_callback(struct urb *urb) unsigned char *data = urb->transfer_buffer; int status = urb->status; - dbg("%s", __func__); - serial = urb->context; if (status) { @@ -806,7 +784,6 @@ static void usa49wg_indat_callback(struct urb *urb) /* not used, usa-49 doesn't have per-port control endpoints */ static void usa49_outcont_callback(struct urb *urb) { - dbg("%s", __func__); } static void usa90_indat_callback(struct urb *urb) @@ -819,8 +796,6 @@ static void usa90_indat_callback(struct urb *urb) unsigned char *data = urb->transfer_buffer; int status = urb->status; - dbg("%s", __func__); - endpoint = usb_pipeendpoint(urb->pipe); if (status) { @@ -957,8 +932,6 @@ static void usa67_instat_callback(struct urb *urb) int old_dcd_state; int status = urb->status; - dbg("%s", __func__); - serial = urb->context; if (status) { @@ -1010,8 +983,6 @@ static void usa67_glocont_callback(struct urb *urb) struct keyspan_port_private *p_priv; int i; - dbg("%s", __func__); - serial = urb->context; for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; @@ -1035,7 +1006,6 @@ static int keyspan_write_room(struct tty_struct *tty) int data_len; struct urb *this_urb; - dbg("%s", __func__); p_priv = usb_get_serial_port_data(port); d_details = p_priv->device_details; @@ -1078,8 +1048,6 @@ static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port) p_priv = usb_get_serial_port_data(port); d_details = p_priv->device_details; - dbg("%s - port%d.", __func__, port->number); - /* Set some sane defaults */ p_priv->rts_state = 1; p_priv->dtr_state = 1; @@ -1165,7 +1133,6 @@ static void keyspan_close(struct usb_serial_port *port) struct keyspan_serial_private *s_priv; struct keyspan_port_private *p_priv; - dbg("%s", __func__); s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); @@ -1438,8 +1405,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial) struct callbacks *cback; int endp; - dbg("%s", __func__); - s_priv = usb_get_serial_data(serial); d_details = s_priv->device_details; @@ -1853,8 +1818,6 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, struct urb *this_urb; int device_port, err; - dbg("%s", __func__); - s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); d_details = s_priv->device_details; @@ -1980,8 +1943,6 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, struct urb *this_urb; int err, device_port; - dbg("%s", __func__); - s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); d_details = s_priv->device_details; @@ -2168,8 +2129,6 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, int err; u8 prescaler; - dbg("%s", __func__); - s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); d_details = s_priv->device_details; @@ -2300,8 +2259,6 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial, struct urb *this_urb; int err, device_port; - dbg("%s", __func__); - s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); d_details = s_priv->device_details; @@ -2442,8 +2399,6 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) struct keyspan_serial_private *s_priv; const struct keyspan_device_details *d_details; - dbg("%s", __func__); - s_priv = usb_get_serial_data(serial); d_details = s_priv->device_details; @@ -2477,8 +2432,6 @@ static int keyspan_startup(struct usb_serial *serial) struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; - dbg("%s", __func__); - for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i) if (d_details->product_id == le16_to_cpu(serial->dev->descriptor.idProduct)) @@ -2538,8 +2491,6 @@ static void keyspan_disconnect(struct usb_serial *serial) struct keyspan_serial_private *s_priv; struct keyspan_port_private *p_priv; - dbg("%s", __func__); - s_priv = usb_get_serial_data(serial); /* Stop reading/writing urbs */ @@ -2579,8 +2530,6 @@ static void keyspan_release(struct usb_serial *serial) struct usb_serial_port *port; struct keyspan_serial_private *s_priv; - dbg("%s", __func__); - s_priv = usb_get_serial_data(serial); /* dbg("Freeing serial->private."); */ diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 693bcdfcb3d5..341ae504915a 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -131,7 +131,6 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work) struct usb_serial *serial = priv->serial; int result; - dbg(" request_unthrottle"); /* ask the device to tell us when the tx buffer becomes sufficiently empty */ result = usb_control_msg(serial->dev, @@ -226,7 +225,7 @@ static void keyspan_pda_rx_throttle(struct tty_struct *tty) send an XOFF, although it might make sense to foist that off upon the device too. */ struct usb_serial_port *port = tty->driver_data; - dbg("keyspan_pda_rx_throttle port %d", port->number); + usb_kill_urb(port->interrupt_in_urb); } @@ -235,7 +234,7 @@ static void keyspan_pda_rx_unthrottle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; /* just restart the receive interrupt URB */ - dbg("keyspan_pda_rx_unthrottle port %d", port->number); + if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL)) dbg(" usb_submit_urb(read urb) failed"); } @@ -466,7 +465,6 @@ static int keyspan_pda_write(struct tty_struct *tty, select() or poll() too) until we receive that unthrottle interrupt. Block if we can't write anything at all, otherwise write as much as we can. */ - dbg("keyspan_pda_write(%d)", count); if (count == 0) { dbg(" write request of 0 bytes"); return 0; @@ -766,8 +764,6 @@ static int keyspan_pda_startup(struct usb_serial *serial) static void keyspan_pda_release(struct usb_serial *serial) { - dbg("%s", __func__); - kfree(usb_get_serial_port_data(serial->port[0])); } diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 10f05407e535..02e12702e629 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -282,8 +282,6 @@ static void klsi_105_release(struct usb_serial *serial) { int i; - dbg("%s", __func__); - for (i = 0; i < serial->num_ports; ++i) kfree(usb_get_serial_port_data(serial->port[i])); } @@ -298,8 +296,6 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) struct klsi_105_port_settings *cfg; unsigned long flags; - dbg("%s port %d", __func__, port->number); - /* Do a defined restart: * Set up sane default baud rate and send the 'READ_ON' * vendor command. @@ -376,8 +372,6 @@ static void klsi_105_close(struct usb_serial_port *port) { int rc; - dbg("%s port %d", __func__, port->number); - mutex_lock(&port->serial->disc_mutex); if (!port->serial->disconnected) { /* send READ_OFF */ @@ -646,7 +640,6 @@ static int klsi_105_tiocmget(struct tty_struct *tty) unsigned long flags; int rc; unsigned long line_state; - dbg("%s - request, just guessing", __func__); rc = klsi_105_get_line_state(port, &line_state); if (rc < 0) { @@ -668,8 +661,6 @@ static int klsi_105_tiocmset(struct tty_struct *tty, { int retval = -EINVAL; - dbg("%s", __func__); - /* if this ever gets implemented, it should be done something like this: struct usb_serial *serial = port->serial; struct klsi_105_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 4a9a75eb9b95..7336e0ecc20f 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -193,7 +193,6 @@ static int kobil_startup(struct usb_serial *serial) static void kobil_release(struct usb_serial *serial) { int i; - dbg("%s - port %d", __func__, serial->port[0]->number); for (i = 0; i < serial->num_ports; ++i) kfree(usb_get_serial_port_data(serial->port[i])); @@ -217,7 +216,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) int transfer_buffer_length = 8; int write_urb_transfer_buffer_length = 8; - dbg("%s - port %d", __func__, port->number); priv = usb_get_serial_port_data(port); /* allocate memory for transfer buffer */ @@ -327,8 +325,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) static void kobil_close(struct usb_serial_port *port) { - dbg("%s - port %d", __func__, port->number); - /* FIXME: Add rts/dtr methods */ if (port->write_urb) { usb_poison_urb(port->write_urb); @@ -349,8 +345,6 @@ static void kobil_read_int_callback(struct urb *urb) int status = urb->status; /* char *dbg_data; */ - dbg("%s - port %d", __func__, port->number); - if (status) { dbg("%s - port %d Read int status not zero: %d", __func__, port->number, status); @@ -474,7 +468,6 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, static int kobil_write_room(struct tty_struct *tty) { - /* dbg("%s - port %d", __func__, port->number); */ /* FIXME */ return 8; } diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 6edd26130e25..4361364a3050 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -427,8 +427,6 @@ static void mct_u232_release(struct usb_serial *serial) struct mct_u232_private *priv; int i; - dbg("%s", __func__); - for (i = 0; i < serial->num_ports; ++i) { /* My special items, the standard routines free my urbs */ priv = usb_get_serial_port_data(serial->port[i]); @@ -446,8 +444,6 @@ static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port) unsigned char last_lcr; unsigned char last_msr; - dbg("%s port %d", __func__, port->number); - /* Compensate for a hardware bug: although the Sitecom U232-P25 * device reports a maximum output packet size of 32 bytes, * it seems to be able to accept only 16 bytes (and that's what @@ -528,8 +524,6 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on) static void mct_u232_close(struct usb_serial_port *port) { - dbg("%s port %d", __func__, port->number); - if (port->serial->dev) { /* shutdown our urbs */ usb_kill_urb(port->write_urb); @@ -572,7 +566,6 @@ static void mct_u232_read_int_callback(struct urb *urb) return; } - dbg("%s - port %d", __func__, port->number); usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); @@ -733,8 +726,6 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) unsigned char lcr; unsigned long flags; - dbg("%sstate=%d", __func__, break_state); - spin_lock_irqsave(&priv->lock, flags); lcr = priv->last_lcr; @@ -753,8 +744,6 @@ static int mct_u232_tiocmget(struct tty_struct *tty) unsigned int control_state; unsigned long flags; - dbg("%s", __func__); - spin_lock_irqsave(&priv->lock, flags); control_state = priv->control_state; spin_unlock_irqrestore(&priv->lock, flags); @@ -771,8 +760,6 @@ static int mct_u232_tiocmset(struct tty_struct *tty, unsigned int control_state; unsigned long flags; - dbg("%s", __func__); - spin_lock_irqsave(&priv->lock, flags); control_state = priv->control_state; @@ -796,8 +783,6 @@ static void mct_u232_throttle(struct tty_struct *tty) struct mct_u232_private *priv = usb_get_serial_port_data(port); unsigned int control_state; - dbg("%s - port %d", __func__, port->number); - spin_lock_irq(&priv->lock); priv->rx_flags |= THROTTLED; if (C_CRTSCTS(tty)) { @@ -816,8 +801,6 @@ static void mct_u232_unthrottle(struct tty_struct *tty) struct mct_u232_private *priv = usb_get_serial_port_data(port); unsigned int control_state; - dbg("%s - port %d", __func__, port->number); - spin_lock_irq(&priv->lock); if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) { priv->rx_flags &= ~THROTTLED; diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 08d16e8c002d..d17c8677a293 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -17,7 +17,6 @@ #include <linux/tty_flip.h> #include <linux/moduleparam.h> #include <linux/spinlock.h> -#include <linux/errno.h> #include <linux/uaccess.h> #include <linux/usb/serial.h> @@ -56,6 +55,47 @@ MODULE_DEVICE_TABLE(usb, id_table); /* Input parameter constants. */ static bool debug; +/* UNI-Directional mode commands for device configure */ +#define UNI_CMD_OPEN 0x80 +#define UNI_CMD_CLOSE 0xFF + +inline int metrousb_is_unidirectional_mode(struct usb_serial_port *port) +{ + __u16 product_id = le16_to_cpu( + port->serial->dev->descriptor.idProduct); + + return product_id == FOCUS_PRODUCT_ID_UNI; +} + +static int metrousb_send_unidirectional_cmd(u8 cmd, struct usb_serial_port *port) +{ + int ret; + int actual_len; + u8 *buffer_cmd = NULL; + + if (!metrousb_is_unidirectional_mode(port)) + return 0; + + buffer_cmd = kzalloc(sizeof(cmd), GFP_KERNEL); + if (!buffer_cmd) + return -ENOMEM; + + *buffer_cmd = cmd; + + ret = usb_interrupt_msg(port->serial->dev, + usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress), + buffer_cmd, sizeof(cmd), + &actual_len, USB_CTRL_SET_TIMEOUT); + + kfree(buffer_cmd); + + if (ret < 0) + return ret; + else if (actual_len != sizeof(cmd)) + return -EIO; + return 0; +} + static void metrousb_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; @@ -78,12 +118,12 @@ static void metrousb_read_int_callback(struct urb *urb) /* urb has been terminated. */ dev_dbg(&port->dev, "%s - urb shutting down, error code=%d\n", - __func__, result); + __func__, urb->status); return; default: dev_dbg(&port->dev, "%s - non-zero urb received, error code=%d\n", - __func__, result); + __func__, urb->status); goto exit; } @@ -91,7 +131,7 @@ static void metrousb_read_int_callback(struct urb *urb) /* Set the data read from the usb port into the serial port buffer. */ tty = tty_port_tty_get(&port->port); if (!tty) { - dev_dbg(&port->dev, "%s - bad tty pointer - exiting\n", + dev_err(&port->dev, "%s - bad tty pointer - exiting\n", __func__); return; } @@ -121,7 +161,7 @@ static void metrousb_read_int_callback(struct urb *urb) result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); if (result) - dev_dbg(&port->dev, + dev_err(&port->dev, "%s - failed submitting interrupt in urb, error code=%d\n", __func__, result); } @@ -131,11 +171,19 @@ exit: /* Try to resubmit the urb. */ result = usb_submit_urb(urb, GFP_ATOMIC); if (result) - dev_dbg(&port->dev, + dev_err(&port->dev, "%s - failed submitting interrupt in urb, error code=%d\n", __func__, result); } +static void metrousb_write_int_callback(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + + dev_warn(&port->dev, "%s not implemented yet.\n", + __func__); +} + static void metrousb_cleanup(struct usb_serial_port *port) { dev_dbg(&port->dev, "%s\n", __func__); @@ -146,6 +194,9 @@ static void metrousb_cleanup(struct usb_serial_port *port) usb_unlink_urb(port->interrupt_in_urb); usb_kill_urb(port->interrupt_in_urb); } + + /* Send deactivate cmd to device */ + metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port); } } @@ -160,7 +211,7 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) /* Make sure the urb is initialized. */ if (!port->interrupt_in_urb) { - dev_dbg(&port->dev, "%s - interrupt urb not initialized\n", + dev_err(&port->dev, "%s - interrupt urb not initialized\n", __func__); return -ENODEV; } @@ -191,12 +242,21 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (result) { - dev_dbg(&port->dev, + dev_err(&port->dev, "%s - failed submitting interrupt in urb, error code=%d\n", __func__, result); goto exit; } + /* Send activate cmd to device */ + result = metrousb_send_unidirectional_cmd(UNI_CMD_OPEN, port); + if (result) { + dev_err(&port->dev, + "%s - failed to configure device for port number=%d, error code=%d\n", + __func__, port->number, result); + goto exit; + } + dev_dbg(&port->dev, "%s - port open\n", __func__); exit: return result; @@ -221,7 +281,7 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr METROUSB_SET_REQUEST_TYPE, METROUSB_SET_MODEM_CTRL_REQUEST, control_state, 0, NULL, 0, WDR_TIMEOUT); if (retval < 0) - dev_dbg(&serial->dev->dev, + dev_err(&serial->dev->dev, "%s - set modem ctrl=0x%x failed, error code=%d\n", __func__, mcr, retval); @@ -354,7 +414,7 @@ static void metrousb_unthrottle(struct tty_struct *tty) port->interrupt_in_urb->dev = port->serial->dev; result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); if (result) - dev_dbg(tty->dev, + dev_err(tty->dev, "failed submitting interrupt in urb error code=%d\n", result); } @@ -371,12 +431,13 @@ static struct usb_serial_driver metrousb_device = { .owner = THIS_MODULE, .name = "metro-usb", }, - .description = "Metrologic USB to serial converter.", + .description = "Metrologic USB to Serial", .id_table = id_table, .num_ports = 1, .open = metrousb_open, .close = metrousb_cleanup, .read_int_callback = metrousb_read_int_callback, + .write_int_callback = metrousb_write_int_callback, .attach = metrousb_startup, .release = metrousb_shutdown, .throttle = metrousb_throttle, diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index bdce82034122..178b76680079 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -257,7 +257,6 @@ static void destroy_mos_parport(struct kref *kref) struct mos7715_parport *mos_parport = container_of(kref, struct mos7715_parport, ref_count); - dbg("%s called", __func__); kfree(mos_parport); } @@ -266,7 +265,7 @@ static void destroy_urbtracker(struct kref *kref) struct urbtracker *urbtrack = container_of(kref, struct urbtracker, ref_count); struct mos7715_parport *mos_parport = urbtrack->mos_parport; - dbg("%s called", __func__); + usb_free_urb(urbtrack->urb); kfree(urbtrack); kref_put(&mos_parport->ref_count, destroy_mos_parport); @@ -285,8 +284,6 @@ static void send_deferred_urbs(unsigned long _mos_parport) struct urbtracker *urbtrack; struct list_head *cursor, *next; - dbg("%s called", __func__); - /* if release function ran, game over */ if (unlikely(mos_parport->serial == NULL)) return; @@ -335,7 +332,7 @@ static void async_complete(struct urb *urb) { struct urbtracker *urbtrack = urb->context; int status = urb->status; - dbg("%s called", __func__); + if (unlikely(status)) dbg("%s - nonzero urb status received: %d", __func__, status); @@ -355,7 +352,6 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport, struct usb_ctrlrequest setup; struct usb_serial *serial = mos_parport->serial; struct usb_device *usbdev = serial->dev; - dbg("%s called", __func__); /* create and initialize the control urb and containing urbtracker */ urbtrack = kmalloc(sizeof(struct urbtracker), GFP_ATOMIC); @@ -476,7 +472,7 @@ static inline void parport_epilogue(struct parport *pp) static void parport_mos7715_write_data(struct parport *pp, unsigned char d) { struct mos7715_parport *mos_parport = pp->private_data; - dbg("%s called: %2.2x", __func__, d); + if (parport_prologue(pp) < 0) return; mos7715_change_mode(mos_parport, SPP); @@ -488,7 +484,7 @@ static unsigned char parport_mos7715_read_data(struct parport *pp) { struct mos7715_parport *mos_parport = pp->private_data; unsigned char d; - dbg("%s called", __func__); + if (parport_prologue(pp) < 0) return 0; read_mos_reg(mos_parport->serial, dummy, DPR, &d); @@ -500,7 +496,7 @@ static void parport_mos7715_write_control(struct parport *pp, unsigned char d) { struct mos7715_parport *mos_parport = pp->private_data; __u8 data; - dbg("%s called: %2.2x", __func__, d); + if (parport_prologue(pp) < 0) return; data = ((__u8)d & 0x0f) | (mos_parport->shadowDCR & 0xf0); @@ -513,7 +509,7 @@ static unsigned char parport_mos7715_read_control(struct parport *pp) { struct mos7715_parport *mos_parport = pp->private_data; __u8 dcr; - dbg("%s called", __func__); + spin_lock(&release_lock); mos_parport = pp->private_data; if (unlikely(mos_parport == NULL)) { @@ -531,7 +527,7 @@ static unsigned char parport_mos7715_frob_control(struct parport *pp, { struct mos7715_parport *mos_parport = pp->private_data; __u8 dcr; - dbg("%s called", __func__); + mask &= 0x0f; val &= 0x0f; if (parport_prologue(pp) < 0) @@ -547,7 +543,7 @@ static unsigned char parport_mos7715_read_status(struct parport *pp) { unsigned char status; struct mos7715_parport *mos_parport = pp->private_data; - dbg("%s called", __func__); + spin_lock(&release_lock); mos_parport = pp->private_data; if (unlikely(mos_parport == NULL)) { /* release called */ @@ -561,17 +557,16 @@ static unsigned char parport_mos7715_read_status(struct parport *pp) static void parport_mos7715_enable_irq(struct parport *pp) { - dbg("%s called", __func__); } + static void parport_mos7715_disable_irq(struct parport *pp) { - dbg("%s called", __func__); } static void parport_mos7715_data_forward(struct parport *pp) { struct mos7715_parport *mos_parport = pp->private_data; - dbg("%s called", __func__); + if (parport_prologue(pp) < 0) return; mos7715_change_mode(mos_parport, PS2); @@ -583,7 +578,7 @@ static void parport_mos7715_data_forward(struct parport *pp) static void parport_mos7715_data_reverse(struct parport *pp) { struct mos7715_parport *mos_parport = pp->private_data; - dbg("%s called", __func__); + if (parport_prologue(pp) < 0) return; mos7715_change_mode(mos_parport, PS2); @@ -595,7 +590,6 @@ static void parport_mos7715_data_reverse(struct parport *pp) static void parport_mos7715_init_state(struct pardevice *dev, struct parport_state *s) { - dbg("%s called", __func__); s->u.pc.ctr = DCR_INIT_VAL; s->u.pc.ecr = ECR_INIT_VAL; } @@ -605,7 +599,7 @@ static void parport_mos7715_save_state(struct parport *pp, struct parport_state *s) { struct mos7715_parport *mos_parport; - dbg("%s called", __func__); + spin_lock(&release_lock); mos_parport = pp->private_data; if (unlikely(mos_parport == NULL)) { /* release called */ @@ -622,7 +616,7 @@ static void parport_mos7715_restore_state(struct parport *pp, struct parport_state *s) { struct mos7715_parport *mos_parport; - dbg("%s called", __func__); + spin_lock(&release_lock); mos_parport = pp->private_data; if (unlikely(mos_parport == NULL)) { /* release called */ @@ -641,7 +635,7 @@ static size_t parport_mos7715_write_compat(struct parport *pp, int retval; struct mos7715_parport *mos_parport = pp->private_data; int actual_len; - dbg("%s called: %u chars", __func__, (unsigned int)len); + if (parport_prologue(pp) < 0) return 0; mos7715_change_mode(mos_parport, PPF); diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index c526550694a0..d9086ee16663 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -114,6 +114,7 @@ #define USB_VENDOR_ID_MOSCHIP 0x9710 #define MOSCHIP_DEVICE_ID_7840 0x7840 #define MOSCHIP_DEVICE_ID_7820 0x7820 +#define MOSCHIP_DEVICE_ID_7810 0x7810 /* The native component can have its vendor/device id's overridden * in vendor-specific implementations. Such devices can be handled * by making a change here, in moschip_port_id_table, and in @@ -184,10 +185,16 @@ #define NUM_URBS 16 /* URB Count */ #define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */ +/* LED on/off milliseconds*/ +#define LED_ON_MS 500 +#define LED_OFF_MS 500 + +static int device_type; static const struct usb_device_id moschip_port_id_table[] = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, + {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7810)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, @@ -209,6 +216,7 @@ static const struct usb_device_id moschip_port_id_table[] = { static const struct usb_device_id moschip_id_table_combined[] __devinitconst = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, + {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7810)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, @@ -261,8 +269,13 @@ struct moschip_port { struct urb *write_urb_pool[NUM_URBS]; char busy[NUM_URBS]; bool read_urb_busy; -}; + /* For device(s) with LED indicator */ + bool has_led; + bool led_flag; + struct timer_list led_timer1; /* Timer for LED on */ + struct timer_list led_timer2; /* Timer for LED off */ +}; static bool debug; @@ -572,6 +585,69 @@ static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, return ret; } +static void mos7840_set_led_callback(struct urb *urb) +{ + switch (urb->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__, + urb->status); + break; + default: + dbg("%s - nonzero urb status received: %d", __func__, + urb->status); + } +} + +static void mos7840_set_led_async(struct moschip_port *mcs, __u16 wval, + __u16 reg) +{ + struct usb_device *dev = mcs->port->serial->dev; + struct usb_ctrlrequest *dr = mcs->dr; + + dr->bRequestType = MCS_WR_RTYPE; + dr->bRequest = MCS_WRREQ; + dr->wValue = cpu_to_le16(wval); + dr->wIndex = cpu_to_le16(reg); + dr->wLength = cpu_to_le16(0); + + usb_fill_control_urb(mcs->control_urb, dev, usb_sndctrlpipe(dev, 0), + (unsigned char *)dr, NULL, 0, mos7840_set_led_callback, NULL); + + usb_submit_urb(mcs->control_urb, GFP_ATOMIC); +} + +static void mos7840_set_led_sync(struct usb_serial_port *port, __u16 reg, + __u16 val) +{ + struct usb_device *dev = port->serial->dev; + + usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, MCS_WR_RTYPE, + val, reg, NULL, 0, MOS_WDR_TIMEOUT); +} + +static void mos7840_led_off(unsigned long arg) +{ + struct moschip_port *mcs = (struct moschip_port *) arg; + + /* Turn off LED */ + mos7840_set_led_async(mcs, 0x0300, MODEM_CONTROL_REGISTER); + mod_timer(&mcs->led_timer2, + jiffies + msecs_to_jiffies(LED_OFF_MS)); +} + +static void mos7840_led_flag_off(unsigned long arg) +{ + struct moschip_port *mcs = (struct moschip_port *) arg; + + mcs->led_flag = false; +} + /***************************************************************************** * mos7840_interrupt_callback * this is the callback function for when we have received data on the @@ -591,8 +667,6 @@ static void mos7840_interrupt_callback(struct urb *urb) __u16 wval, wreg = 0; int status = urb->status; - dbg("%s", " : Entering"); - switch (status) { case 0: /* success */ @@ -766,12 +840,8 @@ static void mos7840_bulk_in_callback(struct urb *urb) return; } - dbg("%s", "Entering... "); - data = urb->transfer_buffer; - dbg("%s", "Entering ..........."); - if (urb->actual_length) { tty = tty_port_tty_get(&mos7840_port->port->port); if (tty) { @@ -792,6 +862,14 @@ static void mos7840_bulk_in_callback(struct urb *urb) return; } + /* Turn on LED */ + if (mos7840_port->has_led && !mos7840_port->led_flag) { + mos7840_port->led_flag = true; + mos7840_set_led_async(mos7840_port, 0x0301, + MODEM_CONTROL_REGISTER); + mod_timer(&mos7840_port->led_timer1, + jiffies + msecs_to_jiffies(LED_ON_MS)); + } mos7840_port->read_urb_busy = true; retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); @@ -835,8 +913,6 @@ static void mos7840_bulk_out_data_callback(struct urb *urb) return; } - dbg("%s", "Entering ........."); - tty = tty_port_tty_get(&mos7840_port->port->port); if (tty && mos7840_port->open) tty_wakeup(tty); @@ -878,8 +954,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) struct moschip_port *mos7840_port; struct moschip_port *port0; - dbg ("%s enter", __func__); - if (mos7840_port_paranoia_check(port, __func__)) { dbg("%s", "Port Paranoia failed"); return -ENODEV; @@ -1151,10 +1225,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) dbg("usb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p", serial, mos7840_port, port); - dbg ("%s leave", __func__); - return 0; - } /***************************************************************************** @@ -1175,18 +1246,14 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty) unsigned long flags; struct moschip_port *mos7840_port; - dbg("%s", " mos7840_chars_in_buffer:entering ..........."); - if (mos7840_port_paranoia_check(port, __func__)) { dbg("%s", "Invalid port"); return 0; } mos7840_port = mos7840_get_port_private(port); - if (mos7840_port == NULL) { - dbg("%s", "mos7840_break:leaving ..........."); + if (mos7840_port == NULL) return 0; - } spin_lock_irqsave(&mos7840_port->pool_lock, flags); for (i = 0; i < NUM_URBS; ++i) @@ -1211,8 +1278,6 @@ static void mos7840_close(struct usb_serial_port *port) int j; __u16 Data; - dbg("%s", "mos7840_close:entering..."); - if (mos7840_port_paranoia_check(port, __func__)) { dbg("%s", "Port Paranoia failed"); return; @@ -1287,8 +1352,6 @@ static void mos7840_close(struct usb_serial_port *port) mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); mos7840_port->open = 0; - - dbg("%s", "Leaving ............"); } /************************************************************************ @@ -1343,9 +1406,6 @@ static void mos7840_break(struct tty_struct *tty, int break_state) struct usb_serial *serial; struct moschip_port *mos7840_port; - dbg("%s", "Entering ..........."); - dbg("mos7840_break: Start"); - if (mos7840_port_paranoia_check(port, __func__)) { dbg("%s", "Port Paranoia failed"); return; @@ -1395,8 +1455,6 @@ static int mos7840_write_room(struct tty_struct *tty) unsigned long flags; struct moschip_port *mos7840_port; - dbg("%s", " mos7840_write_room:entering ..........."); - if (mos7840_port_paranoia_check(port, __func__)) { dbg("%s", "Invalid port"); dbg("%s", " mos7840_write_room:leaving ..........."); @@ -1445,9 +1503,6 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, /* __u16 Data; */ const unsigned char *current_position = data; unsigned char *data1; - dbg("%s", "entering ..........."); - /* dbg("mos7840_write: mos7840_port->shadowLCR is %x", - mos7840_port->shadowLCR); */ #ifdef NOTMOS7840 Data = 0x00; @@ -1554,6 +1609,14 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, data1 = urb->transfer_buffer; dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress); + /* Turn on LED */ + if (mos7840_port->has_led && !mos7840_port->led_flag) { + mos7840_port->led_flag = true; + mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0301); + mod_timer(&mos7840_port->led_timer1, + jiffies + msecs_to_jiffies(LED_ON_MS)); + } + /* send it down the pipe */ status = usb_submit_urb(urb, GFP_ATOMIC); @@ -1602,8 +1665,6 @@ static void mos7840_throttle(struct tty_struct *tty) return; } - dbg("%s", "Entering .........."); - /* if we are implementing XON/XOFF, send the stop character */ if (I_IXOFF(tty)) { unsigned char stop_char = STOP_CHAR(tty); @@ -1646,8 +1707,6 @@ static void mos7840_unthrottle(struct tty_struct *tty) return; } - dbg("%s", "Entering .........."); - /* if we are implementing XON/XOFF, send the start character */ if (I_IXOFF(tty)) { unsigned char start_char = START_CHAR(tty); @@ -1676,8 +1735,6 @@ static int mos7840_tiocmget(struct tty_struct *tty) int status; mos7840_port = mos7840_get_port_private(port); - dbg("%s - port %d", __func__, port->number); - if (mos7840_port == NULL) return -ENODEV; @@ -1704,8 +1761,6 @@ static int mos7840_tiocmset(struct tty_struct *tty, unsigned int mcr; int status; - dbg("%s - port %d", __func__, port->number); - mos7840_port = mos7840_get_port_private(port); if (mos7840_port == NULL) @@ -1746,7 +1801,6 @@ static int mos7840_tiocmset(struct tty_struct *tty, static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor, __u16 *clk_sel_val) { - dbg("%s - %d", __func__, baudRate); if (baudRate <= 115200) { @@ -1839,8 +1893,6 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, return -1; } - dbg("%s", "Entering .........."); - number = mos7840_port->port->number - mos7840_port->port->serial->minor; dbg("%s - port = %d, baud = %d", __func__, @@ -1966,8 +2018,6 @@ static void mos7840_change_port_settings(struct tty_struct *tty, return; } - dbg("%s", "Entering .........."); - lData = LCR_BITS_8; lStop = LCR_STOP_1; lParity = LCR_PAR_NONE; @@ -2108,7 +2158,7 @@ static void mos7840_set_termios(struct tty_struct *tty, unsigned int cflag; struct usb_serial *serial; struct moschip_port *mos7840_port; - dbg("mos7840_set_termios: START"); + if (mos7840_port_paranoia_check(port, __func__)) { dbg("%s", "Invalid port"); return; @@ -2327,28 +2377,74 @@ static int mos7840_ioctl(struct tty_struct *tty, return -ENOIOCTLCMD; } +static int mos7810_check(struct usb_serial *serial) +{ + int i, pass_count = 0; + __u16 data = 0, mcr_data = 0; + __u16 test_pattern = 0x55AA; + + /* Store MCR setting */ + usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + MCS_RDREQ, MCS_RD_RTYPE, 0x0300, MODEM_CONTROL_REGISTER, + &mcr_data, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); + + for (i = 0; i < 16; i++) { + /* Send the 1-bit test pattern out to MCS7810 test pin */ + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + MCS_WRREQ, MCS_WR_RTYPE, + (0x0300 | (((test_pattern >> i) & 0x0001) << 1)), + MODEM_CONTROL_REGISTER, NULL, 0, MOS_WDR_TIMEOUT); + + /* Read the test pattern back */ + usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &data, + VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); + + /* If this is a MCS7810 device, both test patterns must match */ + if (((test_pattern >> i) ^ (~data >> 1)) & 0x0001) + break; + + pass_count++; + } + + /* Restore MCR setting */ + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCS_WRREQ, + MCS_WR_RTYPE, 0x0300 | mcr_data, MODEM_CONTROL_REGISTER, NULL, + 0, MOS_WDR_TIMEOUT); + + if (pass_count == 16) + return 1; + + return 0; +} + static int mos7840_calc_num_ports(struct usb_serial *serial) { - __u16 Data = 0x00; - int ret = 0; + __u16 data = 0x00; int mos7840_num_ports; - ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &Data, + usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &data, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); - if ((Data & 0x01) == 0) { - mos7840_num_ports = 2; - serial->num_bulk_in = 2; - serial->num_bulk_out = 2; - serial->num_ports = 2; + if (serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7810 || + serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7820) { + device_type = serial->dev->descriptor.idProduct; } else { - mos7840_num_ports = 4; - serial->num_bulk_in = 4; - serial->num_bulk_out = 4; - serial->num_ports = 4; + /* For a MCS7840 device GPIO0 must be set to 1 */ + if ((data & 0x01) == 1) + device_type = MOSCHIP_DEVICE_ID_7840; + else if (mos7810_check(serial)) + device_type = MOSCHIP_DEVICE_ID_7810; + else + device_type = MOSCHIP_DEVICE_ID_7820; } + mos7840_num_ports = (device_type >> 4) & 0x000F; + serial->num_bulk_in = mos7840_num_ports; + serial->num_bulk_out = mos7840_num_ports; + serial->num_ports = mos7840_num_ports; + return mos7840_num_ports; } @@ -2361,9 +2457,7 @@ static int mos7840_startup(struct usb_serial *serial) struct moschip_port *mos7840_port; struct usb_device *dev; int i, status; - __u16 Data; - dbg("%s", "mos7840_startup :Entering.........."); if (!serial) { dbg("%s", "Invalid Handler"); @@ -2372,9 +2466,6 @@ static int mos7840_startup(struct usb_serial *serial) dev = serial->dev; - dbg("%s", "Entering..."); - dbg ("mos7840_startup: serial = %p", serial); - /* we set up the pointers to the endpoints in the mos7840_open * * function, as the structures aren't created yet. */ @@ -2563,6 +2654,34 @@ static int mos7840_startup(struct usb_serial *serial) status = -ENOMEM; goto error; } + + mos7840_port->has_led = false; + + /* Initialize LED timers */ + if (device_type == MOSCHIP_DEVICE_ID_7810) { + mos7840_port->has_led = true; + + init_timer(&mos7840_port->led_timer1); + mos7840_port->led_timer1.function = mos7840_led_off; + mos7840_port->led_timer1.expires = + jiffies + msecs_to_jiffies(LED_ON_MS); + mos7840_port->led_timer1.data = + (unsigned long)mos7840_port; + + init_timer(&mos7840_port->led_timer2); + mos7840_port->led_timer2.function = + mos7840_led_flag_off; + mos7840_port->led_timer2.expires = + jiffies + msecs_to_jiffies(LED_OFF_MS); + mos7840_port->led_timer2.data = + (unsigned long)mos7840_port; + + mos7840_port->led_flag = false; + + /* Turn off LED */ + mos7840_set_led_sync(serial->port[i], + MODEM_CONTROL_REGISTER, 0x0300); + } } dbg ("mos7840_startup: all ports configured..........."); @@ -2602,7 +2721,6 @@ static void mos7840_disconnect(struct usb_serial *serial) int i; unsigned long flags; struct moschip_port *mos7840_port; - dbg("%s", " disconnect :entering.........."); if (!serial) { dbg("%s", "Invalid Handler"); @@ -2624,9 +2742,6 @@ static void mos7840_disconnect(struct usb_serial *serial) usb_kill_urb(mos7840_port->control_urb); } } - - dbg("%s", "Thank u :: "); - } /**************************************************************************** @@ -2638,7 +2753,6 @@ static void mos7840_release(struct usb_serial *serial) { int i; struct moschip_port *mos7840_port; - dbg("%s", " release :entering.........."); if (!serial) { dbg("%s", "Invalid Handler"); @@ -2654,14 +2768,19 @@ static void mos7840_release(struct usb_serial *serial) mos7840_port = mos7840_get_port_private(serial->port[i]); dbg("mos7840_port %d = %p", i, mos7840_port); if (mos7840_port) { + if (mos7840_port->has_led) { + /* Turn off LED */ + mos7840_set_led_sync(mos7840_port->port, + MODEM_CONTROL_REGISTER, 0x0300); + + del_timer_sync(&mos7840_port->led_timer1); + del_timer_sync(&mos7840_port->led_timer2); + } kfree(mos7840_port->ctrl_buf); kfree(mos7840_port->dr); kfree(mos7840_port); } } - - dbg("%s", "Thank u :: "); - } static struct usb_driver io_driver = { diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index 29ab6eb5b536..31de00aeb24e 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c @@ -84,8 +84,6 @@ static int navman_open(struct tty_struct *tty, struct usb_serial_port *port) { int result = 0; - dbg("%s - port %d", __func__, port->number); - if (port->interrupt_in_urb) { dbg("%s - adding interrupt input for treo", __func__); result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); @@ -99,16 +97,12 @@ static int navman_open(struct tty_struct *tty, struct usb_serial_port *port) static void navman_close(struct usb_serial_port *port) { - dbg("%s - port %d", __func__, port->number); - usb_kill_urb(port->interrupt_in_urb); } static int navman_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { - dbg("%s - port %d", __func__, port->number); - /* * This device can't write any data, only read from the device */ diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 88dc785bb298..1b6d53f4c610 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -144,8 +144,6 @@ static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port) struct usb_serial_port *wport; int result = 0; - dbg("%s - port %d", __func__, port->number); - wport = serial->port[1]; tty_port_tty_set(&wport->port, tty); @@ -160,7 +158,6 @@ static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port) static void omninet_close(struct usb_serial_port *port) { - dbg("%s - port %d", __func__, port->number); usb_kill_urb(port->read_urb); } @@ -178,8 +175,6 @@ static void omninet_read_bulk_callback(struct urb *urb) int result; int i; - dbg("%s - port %d", __func__, port->number); - if (status) { dbg("%s - nonzero read bulk status received: %d", __func__, status); @@ -225,8 +220,6 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, int result; - dbg("%s - port %d", __func__, port->number); - if (count == 0) { dbg("%s - write request of 0 bytes", __func__); return 0; @@ -289,8 +282,6 @@ static void omninet_write_bulk_callback(struct urb *urb) struct usb_serial_port *port = urb->context; int status = urb->status; - dbg("%s - port %0x", __func__, port->number); - set_bit(0, &port->write_urbs_free); if (status) { dbg("%s - nonzero write bulk status received: %d", @@ -306,8 +297,6 @@ static void omninet_disconnect(struct usb_serial *serial) { struct usb_serial_port *wport = serial->port[1]; - dbg("%s", __func__); - usb_kill_urb(wport->write_urb); } @@ -316,8 +305,6 @@ static void omninet_release(struct usb_serial *serial) { struct usb_serial_port *port = serial->port[0]; - dbg("%s", __func__); - kfree(usb_get_serial_port_data(port)); } diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 82cc9d202b83..858ee18f3618 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -70,8 +70,6 @@ static void opticon_read_bulk_callback(struct urb *urb) int data_length; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - switch (status) { case 0: /* success */ @@ -179,8 +177,6 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port) unsigned long flags; int result = 0; - dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&priv->lock, flags); priv->throttled = false; priv->actually_throttled = false; @@ -216,8 +212,6 @@ static void opticon_close(struct usb_serial_port *port) { struct opticon_private *priv = usb_get_serial_data(port->serial); - dbg("%s - port %d", __func__, port->number); - /* shutdown our urbs */ usb_kill_urb(priv->bulk_read_urb); } @@ -256,8 +250,6 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, int status; struct usb_ctrlrequest *dr; - dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&priv->lock, flags); if (priv->outstanding_urbs > URB_UPPER_LIMIT) { spin_unlock_irqrestore(&priv->lock, flags); @@ -338,8 +330,6 @@ static int opticon_write_room(struct tty_struct *tty) struct opticon_private *priv = usb_get_serial_data(port->serial); unsigned long flags; - dbg("%s - port %d", __func__, port->number); - /* * We really can take almost anything the user throws at us * but let's pick a nice big number to tell the tty @@ -362,7 +352,6 @@ static void opticon_throttle(struct tty_struct *tty) struct opticon_private *priv = usb_get_serial_data(port->serial); unsigned long flags; - dbg("%s - port %d", __func__, port->number); spin_lock_irqsave(&priv->lock, flags); priv->throttled = true; spin_unlock_irqrestore(&priv->lock, flags); @@ -376,8 +365,6 @@ static void opticon_unthrottle(struct tty_struct *tty) unsigned long flags; int result, was_throttled; - dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&priv->lock, flags); priv->throttled = false; was_throttled = priv->actually_throttled; @@ -400,10 +387,6 @@ static int opticon_tiocmget(struct tty_struct *tty) unsigned long flags; int result = 0; - dbg("%s - port %d", __func__, port->number); - if (!usb_get_intfdata(port->serial->interface)) - return -ENODEV; - spin_lock_irqsave(&priv->lock, flags); if (priv->rts) result |= TIOCM_RTS; @@ -419,13 +402,13 @@ static int opticon_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; + struct usb_serial *serial = port->serial; struct opticon_private *priv = usb_get_serial_data(port->serial); unsigned long flags; bool rts; bool changed = false; + int ret; - if (!usb_get_intfdata(port->serial->interface)) - return -ENODEV; /* We only support RTS so we only handle that */ spin_lock_irqsave(&priv->lock, flags); @@ -441,7 +424,14 @@ static int opticon_tiocmset(struct tty_struct *tty, return 0; /* Send the new RTS state to the connected device */ - return send_control_msg(port, CONTROL_RTS, !rts); + mutex_lock(&serial->disc_mutex); + if (!serial->disconnected) + ret = send_control_msg(port, CONTROL_RTS, !rts); + else + ret = -ENODEV; + mutex_unlock(&serial->disc_mutex); + + return ret; } static int get_serial_info(struct opticon_private *priv, @@ -555,8 +545,6 @@ static void opticon_disconnect(struct usb_serial *serial) { struct opticon_private *priv = usb_get_serial_data(serial); - dbg("%s", __func__); - usb_kill_urb(priv->bulk_read_urb); usb_free_urb(priv->bulk_read_urb); } @@ -565,8 +553,6 @@ static void opticon_release(struct usb_serial *serial) { struct opticon_private *priv = usb_get_serial_data(serial); - dbg("%s", __func__); - kfree(priv->bulk_in_buffer); kfree(priv); } diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index f4465ccddc35..ae0b4aa9aa59 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1375,7 +1375,6 @@ static void option_instat_callback(struct urb *urb) struct usb_serial_port *port = urb->context; struct option_port_private *portdata = usb_get_serial_port_data(port); - dbg("%s", __func__); dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata); if (status == 0) { @@ -1413,7 +1412,7 @@ static void option_instat_callback(struct urb *urb) req_pkt->bRequestType, req_pkt->bRequest); } } else - err("%s: error %d", __func__, status); + dev_err(&port->dev, "%s: error %d\n", __func__, status); /* Resubmit urb so we continue receiving IRQ data */ if (status != -ESHUTDOWN && status != -ENOENT) { @@ -1437,7 +1436,6 @@ static int option_send_setup(struct usb_serial_port *port) struct option_port_private *portdata; int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; int val = 0; - dbg("%s", __func__); if (is_blacklisted(ifNum, OPTION_BLACKLIST_SENDSETUP, (struct option_blacklist_info *) intfdata->private)) { diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 5fdc33c6a3c0..d4bce46df2d1 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -211,8 +211,6 @@ static void setup_line(struct work_struct *work) unsigned long flags; int result; - dbg("%s(port = %d)", __func__, port->number); - new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL); if (new_setup == NULL) { dev_err(&port->dev, "%s(): out of memory!\n", __func__); @@ -282,8 +280,6 @@ static void send_data(struct work_struct *work) unsigned long flags; u8 *allow; - dbg("%s(port = %d)", __func__, port->number); - spin_lock_irqsave(&priv->lock, flags); if (priv->flags.write_urb_in_use) { spin_unlock_irqrestore(&priv->lock, flags); @@ -379,8 +375,6 @@ static int oti6858_startup(struct usb_serial *serial) static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { - dbg("%s(port = %d, count = %d)", __func__, port->number, count); - if (!count) return count; @@ -395,8 +389,6 @@ static int oti6858_write_room(struct tty_struct *tty) int room = 0; unsigned long flags; - dbg("%s(port = %d)", __func__, port->number); - spin_lock_irqsave(&port->lock, flags); room = kfifo_avail(&port->write_fifo); spin_unlock_irqrestore(&port->lock, flags); @@ -410,8 +402,6 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty) int chars = 0; unsigned long flags; - dbg("%s(port = %d)", __func__, port->number); - spin_lock_irqsave(&port->lock, flags); chars = kfifo_len(&port->write_fifo); spin_unlock_irqrestore(&port->lock, flags); @@ -437,8 +427,6 @@ static void oti6858_set_termios(struct tty_struct *tty, __le16 divisor; int br; - dbg("%s(port = %d)", __func__, port->number); - if (!tty) { dbg("%s(): no tty structures", __func__); return; @@ -545,8 +533,6 @@ static int oti6858_open(struct tty_struct *tty, struct usb_serial_port *port) unsigned long flags; int result; - dbg("%s(port = %d)", __func__, port->number); - usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); @@ -602,8 +588,6 @@ static void oti6858_close(struct usb_serial_port *port) struct oti6858_private *priv = usb_get_serial_port_data(port); unsigned long flags; - dbg("%s(port = %d)", __func__, port->number); - spin_lock_irqsave(&port->lock, flags); /* clear out any remaining data in the buffer */ kfifo_reset_out(&port->write_fifo); @@ -633,9 +617,6 @@ static int oti6858_tiocmset(struct tty_struct *tty, dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)", __func__, port->number, set, clear); - if (!usb_get_intfdata(port->serial->interface)) - return -ENODEV; - /* FIXME: check if this is correct (active high/low) */ spin_lock_irqsave(&priv->lock, flags); control = priv->pending_setup.control; @@ -663,11 +644,6 @@ static int oti6858_tiocmget(struct tty_struct *tty) unsigned pin_state; unsigned result = 0; - dbg("%s(port = %d)", __func__, port->number); - - if (!usb_get_intfdata(port->serial->interface)) - return -ENODEV; - spin_lock_irqsave(&priv->lock, flags); pin_state = priv->status.pin_state & PIN_MASK; spin_unlock_irqrestore(&priv->lock, flags); @@ -750,8 +726,6 @@ static void oti6858_release(struct usb_serial *serial) { int i; - dbg("%s()", __func__); - for (i = 0; i < serial->num_ports; ++i) kfree(usb_get_serial_port_data(serial->port[i])); } @@ -763,9 +737,6 @@ static void oti6858_read_int_callback(struct urb *urb) int transient = 0, can_recv = 0, resubmit = 1; int status = urb->status; - dbg("%s(port = %d, status = %d)", - __func__, port->number, status); - switch (status) { case 0: /* success */ @@ -882,9 +853,6 @@ static void oti6858_read_bulk_callback(struct urb *urb) int status = urb->status; int result; - dbg("%s(port = %d, status = %d)", - __func__, port->number, status); - spin_lock_irqsave(&priv->lock, flags); priv->flags.read_urb_in_use = 0; spin_unlock_irqrestore(&priv->lock, flags); @@ -916,9 +884,6 @@ static void oti6858_write_bulk_callback(struct urb *urb) int status = urb->status; int result; - dbg("%s(port = %d, status = %d)", - __func__, port->number, status); - switch (status) { case 0: /* success */ diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index a1a9062954c4..9eec2c3574d8 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -38,8 +38,6 @@ static bool debug; -#define PL2303_CLOSING_WAIT (30*HZ) - static const struct usb_device_id id_table[] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, @@ -161,8 +159,9 @@ static int pl2303_vendor_read(__u16 value, __u16 index, int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE, value, index, buf, 1, 100); - dbg("0x%x:0x%x:0x%x:0x%x %d - %x", VENDOR_READ_REQUEST_TYPE, - VENDOR_READ_REQUEST, value, index, res, buf[0]); + dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x %d - %x\n", + VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, value, index, + res, buf[0]); return res; } @@ -172,8 +171,9 @@ static int pl2303_vendor_write(__u16 value, __u16 index, int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE, value, index, NULL, 0, 100); - dbg("0x%x:0x%x:0x%x:0x%x %d", VENDOR_WRITE_REQUEST_TYPE, - VENDOR_WRITE_REQUEST, value, index, res); + dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x %d\n", + VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, value, index, + res); return res; } @@ -196,7 +196,7 @@ static int pl2303_startup(struct usb_serial *serial) type = type_1; else if (serial->dev->descriptor.bDeviceClass == 0xFF) type = type_1; - dbg("device type: %d", type); + dev_dbg(&serial->interface->dev, "device type: %d\n", type); for (i = 0; i < serial->num_ports; ++i) { priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL); @@ -243,7 +243,8 @@ static int set_control_lines(struct usb_device *dev, u8 value) retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE, value, 0, NULL, 0, 100); - dbg("%s - value = %d, retval = %d", __func__, value, retval); + dev_dbg(&dev->dev, "%s - value = %d, retval = %d\n", __func__, + value, retval); return retval; } @@ -265,8 +266,6 @@ static void pl2303_set_termios(struct tty_struct *tty, int baud_floor, baud_ceil; int k; - dbg("%s - port %d", __func__, port->number); - /* The PL2303 is reported to lose bytes if you change serial settings even to the same values as before. Thus we actually need to filter in this specific case */ @@ -287,7 +286,7 @@ static void pl2303_set_termios(struct tty_struct *tty, i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 0, 0, buf, 7, 100); - dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, + dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x\n", i, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); if (cflag & CSIZE) { @@ -306,7 +305,7 @@ static void pl2303_set_termios(struct tty_struct *tty, buf[6] = 8; break; } - dbg("%s - data bits = %d", __func__, buf[6]); + dev_dbg(&port->dev, "data bits = %d\n", buf[6]); } /* For reference buf[0]:buf[3] baud rate value */ @@ -315,7 +314,7 @@ static void pl2303_set_termios(struct tty_struct *tty, * 9600 baud (at least my PL2303X always does) */ baud = tty_get_baud_rate(tty); - dbg("%s - baud requested = %d", __func__, baud); + dev_dbg(&port->dev, "baud requested = %d\n", baud); if (baud) { /* Set baudrate to nearest supported value */ for (k=0; k<ARRAY_SIZE(baud_sup); k++) { @@ -341,7 +340,7 @@ static void pl2303_set_termios(struct tty_struct *tty, else if (baud > 6000000) baud = 6000000; } - dbg("%s - baud set = %d", __func__, baud); + dev_dbg(&port->dev, "baud set = %d\n", baud); if (baud <= 115200) { buf[0] = baud & 0xff; buf[1] = (baud >> 8) & 0xff; @@ -372,14 +371,14 @@ static void pl2303_set_termios(struct tty_struct *tty, */ if ((cflag & CSIZE) == CS5) { buf[4] = 1; - dbg("%s - stop bits = 1.5", __func__); + dev_dbg(&port->dev, "stop bits = 1.5\n"); } else { buf[4] = 2; - dbg("%s - stop bits = 2", __func__); + dev_dbg(&port->dev, "stop bits = 2\n"); } } else { buf[4] = 0; - dbg("%s - stop bits = 1", __func__); + dev_dbg(&port->dev, "stop bits = 1\n"); } if (cflag & PARENB) { @@ -391,29 +390,29 @@ static void pl2303_set_termios(struct tty_struct *tty, if (cflag & PARODD) { if (cflag & CMSPAR) { buf[5] = 3; - dbg("%s - parity = mark", __func__); + dev_dbg(&port->dev, "parity = mark\n"); } else { buf[5] = 1; - dbg("%s - parity = odd", __func__); + dev_dbg(&port->dev, "parity = odd\n"); } } else { if (cflag & CMSPAR) { buf[5] = 4; - dbg("%s - parity = space", __func__); + dev_dbg(&port->dev, "parity = space\n"); } else { buf[5] = 2; - dbg("%s - parity = even", __func__); + dev_dbg(&port->dev, "parity = even\n"); } } } else { buf[5] = 0; - dbg("%s - parity = none", __func__); + dev_dbg(&port->dev, "parity = none\n"); } i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, 0, 0, buf, 7, 100); - dbg("0x21:0x20:0:0 %d", i); + dev_dbg(&port->dev, "0x21:0x20:0:0 %d\n", i); /* change control lines if we are switching to or from B0 */ spin_lock_irqsave(&priv->lock, flags); @@ -435,7 +434,7 @@ static void pl2303_set_termios(struct tty_struct *tty, i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 0, 0, buf, 7, 100); - dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, + dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x\n", i, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); if (cflag & CRTSCTS) { @@ -473,8 +472,6 @@ static void pl2303_dtr_rts(struct usb_serial_port *port, int on) static void pl2303_close(struct usb_serial_port *port) { - dbg("%s - port %d", __func__, port->number); - usb_serial_generic_close(port); usb_kill_urb(port->interrupt_in_urb); } @@ -486,8 +483,6 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) struct pl2303_private *priv = usb_get_serial_port_data(port); int result; - dbg("%s - port %d", __func__, port->number); - if (priv->type != HX) { usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); @@ -501,7 +496,6 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) if (tty) pl2303_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," @@ -523,12 +517,11 @@ static int pl2303_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; + struct usb_serial *serial = port->serial; struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; u8 control; - - if (!usb_get_intfdata(port->serial->interface)) - return -ENODEV; + int ret; spin_lock_irqsave(&priv->lock, flags); if (set & TIOCM_RTS) @@ -542,7 +535,14 @@ static int pl2303_tiocmset(struct tty_struct *tty, control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); - return set_control_lines(port->serial->dev, control); + mutex_lock(&serial->disc_mutex); + if (!serial->disconnected) + ret = set_control_lines(serial->dev, control); + else + ret = -ENODEV; + mutex_unlock(&serial->disc_mutex); + + return ret; } static int pl2303_tiocmget(struct tty_struct *tty) @@ -554,11 +554,6 @@ static int pl2303_tiocmget(struct tty_struct *tty) unsigned int status; unsigned int result; - dbg("%s (%d)", __func__, port->number); - - if (!usb_get_intfdata(port->serial->interface)) - return -ENODEV; - spin_lock_irqsave(&priv->lock, flags); mcr = priv->line_control; status = priv->line_status; @@ -571,7 +566,7 @@ static int pl2303_tiocmget(struct tty_struct *tty) | ((status & UART_RING) ? TIOCM_RI : 0) | ((status & UART_DCD) ? TIOCM_CD : 0); - dbg("%s - result = %x", __func__, result); + dev_dbg(&port->dev, "%s - result = %x\n", __func__, result); return result; } @@ -625,7 +620,8 @@ static int pl2303_ioctl(struct tty_struct *tty, { struct serial_struct ser; struct usb_serial_port *port = tty->driver_data; - dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); + + dev_dbg(&port->dev, "%s cmd = 0x%04x\n", __func__, cmd); switch (cmd) { case TIOCGSERIAL: @@ -641,10 +637,10 @@ static int pl2303_ioctl(struct tty_struct *tty, return 0; case TIOCMIWAIT: - dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__); return wait_modem_info(port, arg); default: - dbg("%s not supported = 0x%04x", __func__, cmd); + dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd); break; } return -ENOIOCTLCMD; @@ -657,20 +653,18 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state) u16 state; int result; - dbg("%s - port %d", __func__, port->number); - if (break_state == 0) state = BREAK_OFF; else state = BREAK_ON; - dbg("%s - turning break %s", __func__, + dev_dbg(&port->dev, "%s - turning break %s\n", __func__, state == BREAK_OFF ? "off" : "on"); result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 0, NULL, 0, 100); if (result) - dbg("%s - error sending break = %d", __func__, result); + dev_err(&port->dev, "error sending break = %d\n", result); } static void pl2303_release(struct usb_serial *serial) @@ -678,8 +672,6 @@ static void pl2303_release(struct usb_serial *serial) int i; struct pl2303_private *priv; - dbg("%s", __func__); - for (i = 0; i < serial->num_ports; ++i) { priv = usb_get_serial_port_data(serial->port[i]); kfree(priv); @@ -742,8 +734,6 @@ static void pl2303_read_int_callback(struct urb *urb) int status = urb->status; int retval; - dbg("%s (%d)", __func__, port->number); - switch (status) { case 0: /* success */ @@ -752,12 +742,12 @@ static void pl2303_read_int_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, - status); + dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n", + __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", __func__, - status); + dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n", + __func__, status); goto exit; } @@ -769,7 +759,7 @@ static void pl2303_read_int_callback(struct urb *urb) exit: retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - dev_err(&urb->dev->dev, + dev_err(&port->dev, "%s - usb_submit_urb failed with result %d\n", __func__, retval); } @@ -807,7 +797,7 @@ static void pl2303_process_read_urb(struct urb *urb) tty_flag = TTY_PARITY; else if (line_status & UART_FRAME_ERROR) tty_flag = TTY_FRAME; - dbg("%s - tty_flag = %d", __func__, tty_flag); + dev_dbg(&port->dev, "%s - tty_flag = %d\n", __func__, tty_flag); /* overrun is special, not associated with a char */ if (line_status & UART_OVERRUN_ERROR) diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 0206b10c9e6e..201f2810d503 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -131,7 +131,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) __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; @@ -250,8 +249,6 @@ static void qc_release(struct usb_serial *serial) { struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); - dbg("%s", __func__); - /* Call usb_wwan release & free the private data allocated in qcprobe */ usb_wwan_release(serial); usb_set_serial_data(serial, NULL); diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 8c8bf806f6fa..f298ddaac684 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -63,9 +63,7 @@ struct sierra_intf_private { static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) { - int result; - dev_dbg(&udev->dev, "%s\n", __func__); - result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), SWIMS_USB_REQUEST_SetPower, /* __u8 request */ USB_TYPE_VENDOR, /* __u8 request type */ swiState, /* __u16 value */ @@ -73,14 +71,11 @@ static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) NULL, /* void *data */ 0, /* __u16 size */ USB_CTRL_SET_TIMEOUT); /* int timeout */ - return result; } static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable) { - int result; - dev_dbg(&udev->dev, "%s\n", __func__); - result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), SWIMS_USB_REQUEST_SetNmea, /* __u8 request */ USB_TYPE_VENDOR, /* __u8 request type */ enable, /* __u16 value */ @@ -88,7 +83,6 @@ static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable) NULL, /* void *data */ 0, /* __u16 size */ USB_CTRL_SET_TIMEOUT); /* int timeout */ - return result; } static int sierra_calc_num_ports(struct usb_serial *serial) @@ -96,8 +90,6 @@ static int sierra_calc_num_ports(struct usb_serial *serial) int num_ports = 0; u8 ifnum, numendpoints; - dev_dbg(&serial->dev->dev, "%s\n", __func__); - ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber; numendpoints = serial->interface->cur_altsetting->desc.bNumEndpoints; @@ -150,7 +142,6 @@ static int sierra_calc_interface(struct usb_serial *serial) int interface; struct usb_interface *p_interface; struct usb_host_interface *p_host_interface; - dev_dbg(&serial->dev->dev, "%s\n", __func__); /* Get the interface structure pointer from the serial struct */ p_interface = serial->interface; @@ -175,9 +166,8 @@ static int sierra_probe(struct usb_serial *serial, u8 ifnum; udev = serial->dev; - dev_dbg(&udev->dev, "%s\n", __func__); - ifnum = sierra_calc_interface(serial); + /* * If this interface supports more than 1 alternate * select the 2nd one @@ -344,8 +334,6 @@ static int sierra_send_setup(struct usb_serial_port *port) int do_send = 0; int retval; - dev_dbg(&port->dev, "%s\n", __func__); - portdata = usb_get_serial_port_data(port); if (portdata->dtr_state) @@ -393,7 +381,6 @@ static int sierra_send_setup(struct usb_serial_port *port) static void sierra_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { - dev_dbg(&port->dev, "%s\n", __func__); tty_termios_copy_hw(tty->termios, old_termios); sierra_send_setup(port); } @@ -404,7 +391,6 @@ static int sierra_tiocmget(struct tty_struct *tty) unsigned int value; struct sierra_port_private *portdata; - dev_dbg(&port->dev, "%s\n", __func__); portdata = usb_get_serial_port_data(port); value = ((portdata->rts_state) ? TIOCM_RTS : 0) | @@ -441,8 +427,7 @@ static void sierra_release_urb(struct urb *urb) { struct usb_serial_port *port; if (urb) { - port = urb->context; - dev_dbg(&port->dev, "%s: %p\n", __func__, urb); + port = urb->context; kfree(urb->transfer_buffer); usb_free_urb(urb); } @@ -455,7 +440,6 @@ static void sierra_outdat_callback(struct urb *urb) struct sierra_intf_private *intfdata; int status = urb->status; - dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); intfdata = port->serial->private; /* free up the transfer buffer, as usb_free_urb() does not do this */ @@ -598,8 +582,6 @@ static void sierra_indat_callback(struct urb *urb) endpoint = usb_pipeendpoint(urb->pipe); port = urb->context; - dev_dbg(&port->dev, "%s: %p\n", __func__, urb); - if (status) { dev_dbg(&port->dev, "%s: nonzero status: %d on" " endpoint %02x\n", __func__, status, endpoint); @@ -697,8 +679,6 @@ static int sierra_write_room(struct tty_struct *tty) struct sierra_port_private *portdata = usb_get_serial_port_data(port); unsigned long flags; - dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); - /* try to give a good number back based on if we have any free urbs at * this point in time */ spin_lock_irqsave(&portdata->lock, flags); @@ -805,8 +785,6 @@ static void sierra_close(struct usb_serial_port *port) struct sierra_port_private *portdata; struct sierra_intf_private *intfdata = port->serial->private; - - dev_dbg(&port->dev, "%s\n", __func__); portdata = usb_get_serial_port_data(port); portdata->rts_state = 0; @@ -851,8 +829,6 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) portdata = usb_get_serial_port_data(port); - dev_dbg(&port->dev, "%s\n", __func__); - /* Set some sane defaults */ portdata->rts_state = 1; portdata->dtr_state = 1; @@ -915,8 +891,6 @@ static int sierra_startup(struct usb_serial *serial) int i; u8 ifnum; - dev_dbg(&serial->dev->dev, "%s\n", __func__); - /* Set Device mode to D0 */ sierra_set_power_state(serial->dev, 0x0000); @@ -977,8 +951,6 @@ static void sierra_release(struct usb_serial *serial) struct usb_serial_port *port; struct sierra_port_private *portdata; - dev_dbg(&serial->dev->dev, "%s\n", __func__); - for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; if (!port) diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index f06c9a8f3d37..91fea7bf15a6 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -454,8 +454,6 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port) u8 status = 0x30; /* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */ - dbg("%s - port %d", __func__, port->number); - usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 3cdc8a52de44..cda513bb01c7 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -85,7 +85,6 @@ static void ssu100_release(struct usb_serial *serial) { struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port); - dbg("%s", __func__); kfree(priv); } @@ -171,8 +170,6 @@ static int ssu100_initdevice(struct usb_device *dev) u8 *data; int result = 0; - dbg("%s", __func__); - data = kzalloc(3, GFP_KERNEL); if (!data) return -ENOMEM; @@ -237,8 +234,6 @@ static void ssu100_set_termios(struct tty_struct *tty, u16 urb_value = 0; /* will hold the new flags */ int result; - dbg("%s", __func__); - if (cflag & PARENB) { if (cflag & PARODD) urb_value |= UART_LCR_PARITY; @@ -312,8 +307,6 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) int result; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - data = kzalloc(2, GFP_KERNEL); if (!data) return -ENOMEM; @@ -348,7 +341,6 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) static void ssu100_close(struct usb_serial_port *port) { - dbg("%s", __func__); usb_serial_generic_close(port); } @@ -467,8 +459,6 @@ static int ssu100_attach(struct usb_serial *serial) struct ssu100_port_private *priv; struct usb_serial_port *port = *serial->port; - dbg("%s", __func__); - priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__, @@ -490,8 +480,6 @@ static int ssu100_tiocmget(struct tty_struct *tty) u8 *d; int r; - dbg("%s\n", __func__); - d = kzalloc(2, GFP_KERNEL); if (!d) return -ENOMEM; @@ -522,7 +510,6 @@ static int ssu100_tiocmset(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; struct usb_device *dev = port->serial->dev; - dbg("%s\n", __func__); return update_mctrl(dev, set, clear); } @@ -530,8 +517,6 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on) { struct usb_device *dev = port->serial->dev; - dbg("%s\n", __func__); - mutex_lock(&port->serial->disc_mutex); if (!port->serial->disconnected) { /* Disable flow control */ @@ -618,8 +603,6 @@ static int ssu100_process_packet(struct urb *urb, int i; char *ch; - dbg("%s - port %d", __func__, port->number); - if ((len >= 4) && (packet[0] == 0x1b) && (packet[1] == 0x1b) && ((packet[2] == 0x00) || (packet[2] == 0x01))) { @@ -656,8 +639,6 @@ static void ssu100_process_read_urb(struct urb *urb) struct tty_struct *tty; int count; - dbg("%s", __func__); - tty = tty_port_tty_get(&port->port); if (!tty) return; diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index 1a5be136e6cf..04e881217fe5 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -54,8 +54,6 @@ static void symbol_int_callback(struct urb *urb) int result; int data_length; - dbg("%s - port %d", __func__, port->number); - switch (status) { case 0: /* success */ @@ -125,8 +123,6 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port) unsigned long flags; int result = 0; - dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&priv->lock, flags); priv->throttled = false; priv->actually_throttled = false; @@ -150,8 +146,6 @@ static void symbol_close(struct usb_serial_port *port) { struct symbol_private *priv = usb_get_serial_data(port->serial); - dbg("%s - port %d", __func__, port->number); - /* shutdown our urbs */ usb_kill_urb(priv->int_urb); } @@ -161,7 +155,6 @@ static void symbol_throttle(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; struct symbol_private *priv = usb_get_serial_data(port->serial); - dbg("%s - port %d", __func__, port->number); spin_lock_irq(&priv->lock); priv->throttled = true; spin_unlock_irq(&priv->lock); @@ -174,8 +167,6 @@ static void symbol_unthrottle(struct tty_struct *tty) int result; bool was_throttled; - dbg("%s - port %d", __func__, port->number); - spin_lock_irq(&priv->lock); priv->throttled = false; was_throttled = priv->actually_throttled; @@ -266,8 +257,6 @@ static void symbol_disconnect(struct usb_serial *serial) { struct symbol_private *priv = usb_get_serial_data(serial); - dbg("%s", __func__); - usb_kill_urb(priv->int_urb); usb_free_urb(priv->int_urb); } @@ -276,8 +265,6 @@ static void symbol_release(struct usb_serial *serial) { struct symbol_private *priv = usb_get_serial_data(serial); - dbg("%s", __func__); - kfree(priv->int_buffer); kfree(priv); } diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index ab74123d658e..925f5f407cc5 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -394,7 +394,9 @@ static int ti_startup(struct usb_serial *serial) /* if we have only 1 configuration, download firmware */ if (dev->descriptor.bNumConfigurations == 1) { - if ((status = ti_download_firmware(tdev)) != 0) + status = ti_download_firmware(tdev); + + if (status != 0) goto free_tdev; /* 3410 must be reset, 5052 resets itself */ @@ -463,8 +465,6 @@ static void ti_release(struct usb_serial *serial) struct ti_device *tdev = usb_get_serial_data(serial); struct ti_port *tport; - dbg("%s", __func__); - for (i = 0; i < serial->num_ports; ++i) { tport = usb_get_serial_port_data(serial->port[i]); if (tport) { @@ -489,8 +489,6 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) TI_PIPE_TIMEOUT_ENABLE | (TI_TRANSFER_TIMEOUT << 2)); - dbg("%s - port %d", __func__, port->number); - if (tport == NULL) return -ENODEV; @@ -631,8 +629,6 @@ static void ti_close(struct usb_serial_port *port) int status; int do_unlock; - dbg("%s - port %d", __func__, port->number); - tdev = usb_get_serial_data(port->serial); tport = usb_get_serial_port_data(port); if (tdev == NULL || tport == NULL) @@ -666,8 +662,6 @@ static void ti_close(struct usb_serial_port *port) } if (do_unlock) mutex_unlock(&tdev->td_open_close_lock); - - dbg("%s - exit", __func__); } @@ -676,8 +670,6 @@ static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, { struct ti_port *tport = usb_get_serial_port_data(port); - dbg("%s - port %d", __func__, port->number); - if (count == 0) { dbg("%s - write request of 0 bytes", __func__); return 0; @@ -701,8 +693,6 @@ static int ti_write_room(struct tty_struct *tty) int room = 0; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - if (tport == NULL) return 0; @@ -722,8 +712,6 @@ static int ti_chars_in_buffer(struct tty_struct *tty) int chars = 0; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - if (tport == NULL) return 0; @@ -741,8 +729,6 @@ static void ti_throttle(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); - dbg("%s - port %d", __func__, port->number); - if (tport == NULL) return; @@ -758,8 +744,6 @@ static void ti_unthrottle(struct tty_struct *tty) struct ti_port *tport = usb_get_serial_port_data(port); int status; - dbg("%s - port %d", __func__, port->number); - if (tport == NULL) return; @@ -854,8 +838,6 @@ static void ti_set_termios(struct tty_struct *tty, int port_number = port->number - port->serial->minor; unsigned int mcr; - dbg("%s - port %d", __func__, port->number); - cflag = tty->termios->c_cflag; iflag = tty->termios->c_iflag; @@ -988,8 +970,6 @@ static int ti_tiocmget(struct tty_struct *tty) unsigned int mcr; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - if (tport == NULL) return -ENODEV; @@ -1020,8 +1000,6 @@ static int ti_tiocmset(struct tty_struct *tty, unsigned int mcr; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - if (tport == NULL) return -ENODEV; @@ -1084,8 +1062,6 @@ static void ti_interrupt_callback(struct urb *urb) int retval; __u8 msr; - dbg("%s", __func__); - switch (status) { case 0: break; @@ -1165,8 +1141,6 @@ static void ti_bulk_in_callback(struct urb *urb) int retval = 0; struct tty_struct *tty; - dbg("%s", __func__); - switch (status) { case 0: break; @@ -1233,8 +1207,6 @@ static void ti_bulk_out_callback(struct urb *urb) struct usb_serial_port *port = tport->tp_port; int status = urb->status; - dbg("%s - port %d", __func__, port->number); - tport->tp_write_urb_in_use = 0; switch (status) { @@ -1287,9 +1259,6 @@ static void ti_send(struct ti_port *tport) struct tty_struct *tty = tty_port_tty_get(&port->port); /* FIXME */ unsigned long flags; - - dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&tport->tp_lock, flags); if (tport->tp_write_urb_in_use) @@ -1366,8 +1335,6 @@ static int ti_get_lsr(struct ti_port *tport) int port_number = port->number - port->serial->minor; struct ti_port_status *data; - dbg("%s - port %d", __func__, port->number); - size = sizeof(struct ti_port_status); data = kmalloc(size, GFP_KERNEL); if (!data) { @@ -1480,8 +1447,6 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush) struct usb_serial_port *port = tport->tp_port; wait_queue_t wait; - dbg("%s - port %d", __func__, port->number); - spin_lock_irq(&tport->tp_lock); /* wait for data to drain from the buffer */ @@ -1679,11 +1644,12 @@ static int ti_download_firmware(struct ti_device *tdev) const struct firmware *fw_p; char buf[32]; - dbg("%s\n", __func__); /* try ID specific firmware first, then try generic firmware */ sprintf(buf, "ti_usb-v%04x-p%04x.fw", dev->descriptor.idVendor, dev->descriptor.idProduct); - if ((status = request_firmware(&fw_p, buf, &dev->dev)) != 0) { + status = request_firmware(&fw_p, buf, &dev->dev); + + if (status != 0) { buf[0] = '\0'; if (dev->descriptor.idVendor == MTS_VENDOR_ID) { switch (dev->descriptor.idProduct) { diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 97355a15bbea..906f06e97fde 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1043,6 +1043,8 @@ int usb_serial_probe(struct usb_interface *interface, dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined"); } + usb_set_intfdata(interface, serial); + /* if this device type has an attach function, call it */ if (type->attach) { retval = type->attach(serial); @@ -1087,10 +1089,7 @@ int usb_serial_probe(struct usb_interface *interface, serial->disconnected = 0; usb_serial_console_init(debug, minor); - exit: - /* success */ - usb_set_intfdata(interface, serial); module_put(type->driver.owner); return 0; @@ -1112,7 +1111,6 @@ void usb_serial_disconnect(struct usb_interface *interface) dbg("%s", __func__); mutex_lock(&serial->disc_mutex); - usb_set_intfdata(interface, NULL); /* must set a flag, to signal subdrivers */ serial->disconnected = 1; mutex_unlock(&serial->disc_mutex); diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index c88657dd31c8..f35971dff4a5 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -43,11 +43,8 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on) { struct usb_serial *serial = port->serial; struct usb_wwan_port_private *portdata; - struct usb_wwan_intf_private *intfdata; - dbg("%s", __func__); - intfdata = port->serial->private; if (!intfdata->send_setup) @@ -69,8 +66,6 @@ void usb_wwan_set_termios(struct tty_struct *tty, { struct usb_wwan_intf_private *intfdata = port->serial->private; - dbg("%s", __func__); - /* Doesn't support option setting */ tty_termios_copy_hw(tty->termios, old_termios); @@ -286,8 +281,6 @@ static void usb_wwan_indat_callback(struct urb *urb) unsigned char *data = urb->transfer_buffer; int status = urb->status; - dbg("%s: %p", __func__, urb); - endpoint = usb_pipeendpoint(urb->pipe); port = urb->context; @@ -307,20 +300,17 @@ static void usb_wwan_indat_callback(struct urb *urb) } /* Resubmit urb so we continue receiving */ - if (status != -ESHUTDOWN) { - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err) { - if (err != -EPERM) { - printk(KERN_ERR "%s: resubmit read urb failed. " - "(%d)", __func__, err); - /* busy also in error unless we are killed */ - usb_mark_last_busy(port->serial->dev); - } - } else { + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err) { + if (err != -EPERM) { + printk(KERN_ERR "%s: resubmit read urb failed. " + "(%d)", __func__, err); + /* busy also in error unless we are killed */ usb_mark_last_busy(port->serial->dev); } + } else { + usb_mark_last_busy(port->serial->dev); } - } } @@ -331,8 +321,6 @@ static void usb_wwan_outdat_callback(struct urb *urb) struct usb_wwan_intf_private *intfdata; int i; - dbg("%s", __func__); - port = urb->context; intfdata = port->serial->private; @@ -406,8 +394,6 @@ int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port) portdata = usb_get_serial_port_data(port); intfdata = serial->private; - dbg("%s", __func__); - /* Start reading from the IN endpoint */ for (i = 0; i < N_IN_URB; i++) { urb = portdata->in_urbs[i]; @@ -441,7 +427,6 @@ void usb_wwan_close(struct usb_serial_port *port) struct usb_wwan_port_private *portdata; struct usb_wwan_intf_private *intfdata = port->serial->private; - dbg("%s", __func__); portdata = usb_get_serial_port_data(port); if (serial->dev) { @@ -492,8 +477,6 @@ static void usb_wwan_setup_urbs(struct usb_serial *serial) struct usb_serial_port *port; struct usb_wwan_port_private *portdata; - dbg("%s", __func__); - for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; portdata = usb_get_serial_port_data(port); @@ -534,8 +517,6 @@ int usb_wwan_startup(struct usb_serial *serial) struct usb_wwan_port_private *portdata; u8 *buffer; - dbg("%s", __func__); - /* Now setup per port private data */ for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; @@ -603,8 +584,6 @@ static void stop_read_write_urbs(struct usb_serial *serial) void usb_wwan_disconnect(struct usb_serial *serial) { - dbg("%s", __func__); - stop_read_write_urbs(serial); } EXPORT_SYMBOL(usb_wwan_disconnect); @@ -615,8 +594,6 @@ void usb_wwan_release(struct usb_serial *serial) struct usb_serial_port *port; struct usb_wwan_port_private *portdata; - dbg("%s", __func__); - /* Now free them */ for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; @@ -649,8 +626,6 @@ int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message) struct usb_wwan_intf_private *intfdata = serial->private; int b; - dbg("%s entered", __func__); - if (PMSG_IS_AUTO(message)) { spin_lock_irq(&intfdata->susp_lock); b = intfdata->in_flight; @@ -714,7 +689,6 @@ int usb_wwan_resume(struct usb_serial *serial) struct urb *urb; int err = 0; - dbg("%s entered", __func__); /* get the interrupt URBs resubmitted unconditionally */ for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; @@ -725,8 +699,8 @@ int usb_wwan_resume(struct usb_serial *serial) err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); dbg("Submitted interrupt URB for port %d (result %d)", i, err); if (err < 0) { - err("%s: Error %d for interrupt URB of port%d", - __func__, err, i); + dev_err(&port->dev, "%s: Error %d for interrupt URB\n", + __func__, err); goto err_out; } } @@ -747,8 +721,8 @@ int usb_wwan_resume(struct usb_serial *serial) urb = portdata->in_urbs[j]; err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { - err("%s: Error %d for bulk URB %d", - __func__, err, i); + dev_err(&port->dev, "%s: Error %d for bulk URB %d\n", + __func__, err, i); spin_unlock_irq(&intfdata->susp_lock); goto err_out; } diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 71d696474f24..d9b41fa50203 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -53,8 +53,6 @@ static int palm_os_4_probe(struct usb_serial *serial, /* Parameters that may be passed into the module. */ static bool debug; -static __u16 vendor; -static __u16 product; static struct usb_device_id id_table [] = { { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID), @@ -115,14 +113,12 @@ static struct usb_device_id id_table [] = { .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, - { }, /* optional parameter entry */ { } /* Terminating entry */ }; static struct usb_device_id clie_id_5_table [] = { { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, - { }, /* optional parameter entry */ { } /* Terminating entry */ }; @@ -162,7 +158,6 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) }, { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID) }, { USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID) }, - { }, /* optional parameter entry */ { } /* Terminating entry */ }; @@ -244,8 +239,6 @@ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port) { int result = 0; - dbg("%s - port %d", __func__, port->number); - if (!port->read_urb) { /* this is needed for some brain dead Sony devices */ dev_err(&port->dev, "Device lied about number of ports, please use a lower one.\n"); @@ -258,7 +251,7 @@ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port) goto exit; if (port->interrupt_in_urb) { - dbg("%s - adding interrupt input for treo", __func__); + dev_dbg(&port->dev, "adding interrupt input for treo\n"); result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (result) dev_err(&port->dev, @@ -274,8 +267,6 @@ static void visor_close(struct usb_serial_port *port) { unsigned char *transfer_buffer; - dbg("%s - port %d", __func__, port->number); - /* shutdown our urbs */ usb_serial_generic_close(port); usb_kill_urb(port->interrupt_in_urb); @@ -310,12 +301,12 @@ static void visor_read_int_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __func__, status); + dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n", + __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", - __func__, status); + dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n", + __func__, status); goto exit; } @@ -348,8 +339,6 @@ static int palm_os_3_probe(struct usb_serial *serial, int i; int num_ports = 0; - dbg("%s", __func__); - transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL); if (!transfer_buffer) { dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__, @@ -445,8 +434,6 @@ static int palm_os_4_probe(struct usb_serial *serial, unsigned char *transfer_buffer; int retval; - dbg("%s", __func__); - transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL); if (!transfer_buffer) { dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__, @@ -478,8 +465,6 @@ static int visor_probe(struct usb_serial *serial, int (*startup)(struct usb_serial *serial, const struct usb_device_id *id); - dbg("%s", __func__); - /* * some Samsung Android phones in modem mode have the same ID * as SPH-I500, but they are ACM devices, so dont bind to them @@ -521,8 +506,6 @@ static int clie_3_5_startup(struct usb_serial *serial) int result; u8 *data; - dbg("%s", __func__); - data = kmalloc(1, GFP_KERNEL); if (!data) return -ENOMEM; @@ -585,8 +568,6 @@ static int treo_attach(struct usb_serial *serial) (serial->num_interrupt_in == 0)) return 0; - dbg("%s", __func__); - /* * It appears that Treos and Kyoceras want to use the * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint, @@ -622,8 +603,6 @@ static int clie_5_attach(struct usb_serial *serial) unsigned int pipe; int j; - dbg("%s", __func__); - /* TH55 registers 2 ports. Communication in from the UX50/TH55 uses bulk_in_endpointAddress from port 0. Communication out to the UX50/TH55 uses @@ -648,59 +627,7 @@ static int clie_5_attach(struct usb_serial *serial) return 0; } -static int __init visor_init(void) -{ - int i, retval; - /* Only if parameters were passed to us */ - if (vendor > 0 && product > 0) { - struct usb_device_id usb_dev_temp[] = { - { - USB_DEVICE(vendor, product), - .driver_info = - (kernel_ulong_t) &palm_os_4_probe - } - }; - - /* Find the last entry in id_table */ - for (i = 0;; i++) { - if (id_table[i].idVendor == 0) { - id_table[i] = usb_dev_temp[0]; - break; - } - } - /* Find the last entry in id_table_combined */ - for (i = 0;; i++) { - if (id_table_combined[i].idVendor == 0) { - id_table_combined[i] = usb_dev_temp[0]; - break; - } - } - printk(KERN_INFO KBUILD_MODNAME - ": Untested USB device specified at time of module insertion\n"); - printk(KERN_INFO KBUILD_MODNAME - ": Warning: This is not guaranteed to work\n"); - printk(KERN_INFO KBUILD_MODNAME - ": Using a newer kernel is preferred to this method\n"); - printk(KERN_INFO KBUILD_MODNAME - ": Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x\n", - vendor, product); - } - - 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_serial_deregister_drivers(&visor_driver, serial_drivers); -} - - -module_init(visor_init); -module_exit(visor_exit); +module_usb_serial_driver(visor_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); @@ -708,9 +635,3 @@ MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); - -module_param(vendor, ushort, 0); -MODULE_PARM_DESC(vendor, "User specified vendor ID"); -module_param(product, ushort, 0); -MODULE_PARM_DESC(product, "User specified product ID"); - diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 407e23c87946..d07794fda006 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -45,7 +45,6 @@ static bool debug; /* * Version Information */ -#define DRIVER_VERSION "v2.0" #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Stuart MacDonald <stuartm@connecttech.com>" #define DRIVER_DESC "USB ConnectTech WhiteHEAT driver" @@ -96,10 +95,6 @@ static void whiteheat_release(struct usb_serial *serial); static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port); static void whiteheat_close(struct usb_serial_port *port); -static int whiteheat_write(struct tty_struct *tty, - struct usb_serial_port *port, - const unsigned char *buf, int count); -static int whiteheat_write_room(struct tty_struct *tty); static int whiteheat_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); static void whiteheat_set_termios(struct tty_struct *tty, @@ -108,11 +103,6 @@ static int whiteheat_tiocmget(struct tty_struct *tty); static int whiteheat_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static void whiteheat_break_ctl(struct tty_struct *tty, int break_state); -static int whiteheat_chars_in_buffer(struct tty_struct *tty); -static void whiteheat_throttle(struct tty_struct *tty); -static void whiteheat_unthrottle(struct tty_struct *tty); -static void whiteheat_read_callback(struct urb *urb); -static void whiteheat_write_callback(struct urb *urb); static struct usb_serial_driver whiteheat_fake_device = { .driver = { @@ -138,18 +128,13 @@ static struct usb_serial_driver whiteheat_device = { .release = whiteheat_release, .open = whiteheat_open, .close = whiteheat_close, - .write = whiteheat_write, - .write_room = whiteheat_write_room, .ioctl = whiteheat_ioctl, .set_termios = whiteheat_set_termios, .break_ctl = whiteheat_break_ctl, .tiocmget = whiteheat_tiocmget, .tiocmset = whiteheat_tiocmset, - .chars_in_buffer = whiteheat_chars_in_buffer, - .throttle = whiteheat_throttle, - .unthrottle = whiteheat_unthrottle, - .read_bulk_callback = whiteheat_read_callback, - .write_bulk_callback = whiteheat_write_callback, + .throttle = usb_serial_generic_throttle, + .unthrottle = usb_serial_generic_unthrottle, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -166,29 +151,8 @@ struct whiteheat_command_private { __u8 result_buffer[64]; }; - -#define THROTTLED 0x01 -#define ACTUALLY_THROTTLED 0x02 - -static int urb_pool_size = 8; - -struct whiteheat_urb_wrap { - struct list_head list; - struct urb *urb; -}; - struct whiteheat_private { - spinlock_t lock; - __u8 flags; __u8 mcr; /* FIXME: no locking on mcr */ - struct list_head rx_urbs_free; - struct list_head rx_urbs_submitted; - struct list_head rx_urb_q; - struct work_struct rx_work; - struct usb_serial_port *port; - struct list_head tx_urbs_free; - struct list_head tx_urbs_submitted; - struct mutex deathwarrant; }; @@ -198,12 +162,6 @@ static void stop_command_port(struct usb_serial *serial); static void command_port_write_callback(struct urb *urb); static void command_port_read_callback(struct urb *urb); -static int start_port_read(struct usb_serial_port *port); -static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, - struct list_head *head); -static struct list_head *list_first(struct list_head *head); -static void rx_data_softint(struct work_struct *work); - static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize); static int firm_open(struct usb_serial_port *port); @@ -247,8 +205,6 @@ static int whiteheat_firmware_download(struct usb_serial *serial, const struct firmware *loader_fw = NULL, *firmware_fw = NULL; const struct ihex_binrec *record; - dbg("%s", __func__); - if (request_ihex_firmware(&firmware_fw, "whiteheat.fw", &serial->dev->dev)) { dev_err(&serial->dev->dev, @@ -349,11 +305,6 @@ static int whiteheat_attach(struct usb_serial *serial) __u8 *command; __u8 *result; int i; - int j; - struct urb *urb; - int buf_size; - struct whiteheat_urb_wrap *wrap; - struct list_head *tmp; command_port = serial->port[COMMAND_PORT]; @@ -408,8 +359,8 @@ static int whiteheat_attach(struct usb_serial *serial) hw_info = (struct whiteheat_hw_info *)&result[1]; - dev_info(&serial->dev->dev, "%s: Driver %s: Firmware v%d.%02d\n", - serial->type->description, DRIVER_VERSION, + dev_info(&serial->dev->dev, "%s: Firmware v%d.%02d\n", + serial->type->description, hw_info->sw_major_rev, hw_info->sw_minor_rev); for (i = 0; i < serial->num_ports; i++) { @@ -423,72 +374,7 @@ static int whiteheat_attach(struct usb_serial *serial) goto no_private; } - spin_lock_init(&info->lock); - mutex_init(&info->deathwarrant); - info->flags = 0; info->mcr = 0; - INIT_WORK(&info->rx_work, rx_data_softint); - info->port = port; - - INIT_LIST_HEAD(&info->rx_urbs_free); - INIT_LIST_HEAD(&info->rx_urbs_submitted); - INIT_LIST_HEAD(&info->rx_urb_q); - INIT_LIST_HEAD(&info->tx_urbs_free); - INIT_LIST_HEAD(&info->tx_urbs_submitted); - - for (j = 0; j < urb_pool_size; j++) { - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - dev_err(&port->dev, "No free urbs available\n"); - goto no_rx_urb; - } - buf_size = port->read_urb->transfer_buffer_length; - urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL); - if (!urb->transfer_buffer) { - dev_err(&port->dev, - "Couldn't allocate urb buffer\n"); - goto no_rx_buf; - } - wrap = kmalloc(sizeof(*wrap), GFP_KERNEL); - if (!wrap) { - dev_err(&port->dev, - "Couldn't allocate urb wrapper\n"); - goto no_rx_wrap; - } - usb_fill_bulk_urb(urb, serial->dev, - usb_rcvbulkpipe(serial->dev, - port->bulk_in_endpointAddress), - urb->transfer_buffer, buf_size, - whiteheat_read_callback, port); - wrap->urb = urb; - list_add(&wrap->list, &info->rx_urbs_free); - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - dev_err(&port->dev, "No free urbs available\n"); - goto no_tx_urb; - } - buf_size = port->write_urb->transfer_buffer_length; - urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL); - if (!urb->transfer_buffer) { - dev_err(&port->dev, - "Couldn't allocate urb buffer\n"); - goto no_tx_buf; - } - wrap = kmalloc(sizeof(*wrap), GFP_KERNEL); - if (!wrap) { - dev_err(&port->dev, - "Couldn't allocate urb wrapper\n"); - goto no_tx_wrap; - } - usb_fill_bulk_urb(urb, serial->dev, - usb_sndbulkpipe(serial->dev, - port->bulk_out_endpointAddress), - urb->transfer_buffer, buf_size, - whiteheat_write_callback, port); - wrap->urb = urb; - list_add(&wrap->list, &info->tx_urbs_free); - } usb_set_serial_port_data(port, info); } @@ -531,29 +417,6 @@ no_command_private: for (i = serial->num_ports - 1; i >= 0; i--) { port = serial->port[i]; info = usb_get_serial_port_data(port); - for (j = urb_pool_size - 1; j >= 0; j--) { - tmp = list_first(&info->tx_urbs_free); - list_del(tmp); - wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); - urb = wrap->urb; - kfree(wrap); -no_tx_wrap: - kfree(urb->transfer_buffer); -no_tx_buf: - usb_free_urb(urb); -no_tx_urb: - tmp = list_first(&info->rx_urbs_free); - list_del(tmp); - wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); - urb = wrap->urb; - kfree(wrap); -no_rx_wrap: - kfree(urb->transfer_buffer); -no_rx_buf: - usb_free_urb(urb); -no_rx_urb: - ; - } kfree(info); no_private: ; @@ -569,56 +432,27 @@ no_command_buffer: static void whiteheat_release(struct usb_serial *serial) { struct usb_serial_port *command_port; - struct usb_serial_port *port; struct whiteheat_private *info; - struct whiteheat_urb_wrap *wrap; - struct urb *urb; - struct list_head *tmp; - struct list_head *tmp2; int i; - dbg("%s", __func__); - /* free up our private data for our command port */ command_port = serial->port[COMMAND_PORT]; kfree(usb_get_serial_port_data(command_port)); for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - info = usb_get_serial_port_data(port); - list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) { - list_del(tmp); - wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); - urb = wrap->urb; - kfree(wrap); - kfree(urb->transfer_buffer); - usb_free_urb(urb); - } - list_for_each_safe(tmp, tmp2, &info->tx_urbs_free) { - list_del(tmp); - wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); - urb = wrap->urb; - kfree(wrap); - kfree(urb->transfer_buffer); - usb_free_urb(urb); - } + info = usb_get_serial_port_data(serial->port[i]); kfree(info); } } static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port) { - int retval = 0; - - dbg("%s - port %d", __func__, port->number); + int retval; retval = start_command_port(port->serial); if (retval) goto exit; - if (tty) - tty->low_latency = 1; - /* send an open port command */ retval = firm_open(port); if (retval) { @@ -640,144 +474,25 @@ static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port) usb_clear_halt(port->serial->dev, port->read_urb->pipe); usb_clear_halt(port->serial->dev, port->write_urb->pipe); - /* Start reading from the device */ - retval = start_port_read(port); + retval = usb_serial_generic_open(tty, port); if (retval) { - dev_err(&port->dev, - "%s - failed submitting read urb, error %d\n", - __func__, retval); firm_close(port); stop_command_port(port->serial); goto exit; } - exit: - dbg("%s - exit, retval = %d", __func__, retval); return retval; } static void whiteheat_close(struct usb_serial_port *port) { - struct whiteheat_private *info = usb_get_serial_port_data(port); - struct whiteheat_urb_wrap *wrap; - struct urb *urb; - struct list_head *tmp; - struct list_head *tmp2; - - dbg("%s - port %d", __func__, port->number); - firm_report_tx_done(port); firm_close(port); - /* shutdown our bulk reads and writes */ - mutex_lock(&info->deathwarrant); - spin_lock_irq(&info->lock); - list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) { - wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); - urb = wrap->urb; - list_del(tmp); - spin_unlock_irq(&info->lock); - usb_kill_urb(urb); - spin_lock_irq(&info->lock); - list_add(tmp, &info->rx_urbs_free); - } - list_for_each_safe(tmp, tmp2, &info->rx_urb_q) - list_move(tmp, &info->rx_urbs_free); - list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) { - wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); - urb = wrap->urb; - list_del(tmp); - spin_unlock_irq(&info->lock); - usb_kill_urb(urb); - spin_lock_irq(&info->lock); - list_add(tmp, &info->tx_urbs_free); - } - spin_unlock_irq(&info->lock); - mutex_unlock(&info->deathwarrant); - stop_command_port(port->serial); -} - - -static int whiteheat_write(struct tty_struct *tty, - struct usb_serial_port *port, const unsigned char *buf, int count) -{ - struct whiteheat_private *info = usb_get_serial_port_data(port); - struct whiteheat_urb_wrap *wrap; - struct urb *urb; - int result; - int bytes; - int sent = 0; - unsigned long flags; - struct list_head *tmp; - - dbg("%s - port %d", __func__, port->number); - - if (count == 0) { - dbg("%s - write request of 0 bytes", __func__); - return (0); - } - - while (count) { - spin_lock_irqsave(&info->lock, flags); - if (list_empty(&info->tx_urbs_free)) { - spin_unlock_irqrestore(&info->lock, flags); - break; - } - tmp = list_first(&info->tx_urbs_free); - list_del(tmp); - spin_unlock_irqrestore(&info->lock, flags); - - wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); - urb = wrap->urb; - bytes = (count > port->bulk_out_size) ? - port->bulk_out_size : count; - memcpy(urb->transfer_buffer, buf + sent, bytes); - - usb_serial_debug_data(debug, &port->dev, - __func__, bytes, urb->transfer_buffer); - - urb->transfer_buffer_length = bytes; - result = usb_submit_urb(urb, GFP_ATOMIC); - if (result) { - dev_err_console(port, - "%s - failed submitting write urb, error %d\n", - __func__, result); - sent = result; - spin_lock_irqsave(&info->lock, flags); - list_add(tmp, &info->tx_urbs_free); - spin_unlock_irqrestore(&info->lock, flags); - break; - } else { - sent += bytes; - count -= bytes; - spin_lock_irqsave(&info->lock, flags); - list_add(tmp, &info->tx_urbs_submitted); - spin_unlock_irqrestore(&info->lock, flags); - } - } + usb_serial_generic_close(port); - return sent; -} - -static int whiteheat_write_room(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - struct whiteheat_private *info = usb_get_serial_port_data(port); - struct list_head *tmp; - int room = 0; - unsigned long flags; - - dbg("%s - port %d", __func__, port->number); - - spin_lock_irqsave(&info->lock, flags); - list_for_each(tmp, &info->tx_urbs_free) - room++; - spin_unlock_irqrestore(&info->lock, flags); - room *= port->bulk_out_size; - - dbg("%s - returns %d", __func__, room); - return (room); + stop_command_port(port->serial); } static int whiteheat_tiocmget(struct tty_struct *tty) @@ -786,8 +501,6 @@ static int whiteheat_tiocmget(struct tty_struct *tty) struct whiteheat_private *info = usb_get_serial_port_data(port); unsigned int modem_signals = 0; - dbg("%s - port %d", __func__, port->number); - firm_get_dtr_rts(port); if (info->mcr & UART_MCR_DTR) modem_signals |= TIOCM_DTR; @@ -803,8 +516,6 @@ static int whiteheat_tiocmset(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; struct whiteheat_private *info = usb_get_serial_port_data(port); - dbg("%s - port %d", __func__, port->number); - if (set & TIOCM_RTS) info->mcr |= UART_MCR_RTS; if (set & TIOCM_DTR) @@ -837,7 +548,7 @@ static int whiteheat_ioctl(struct tty_struct *tty, serstruct.line = port->serial->minor; serstruct.port = port->number; serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; - serstruct.xmit_fifo_size = port->bulk_out_size; + serstruct.xmit_fifo_size = kfifo_size(&port->write_fifo); serstruct.custom_divisor = 0; serstruct.baud_base = 460800; serstruct.close_delay = CLOSING_DELAY; @@ -867,60 +578,6 @@ static void whiteheat_break_ctl(struct tty_struct *tty, int break_state) } -static int whiteheat_chars_in_buffer(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - struct whiteheat_private *info = usb_get_serial_port_data(port); - struct list_head *tmp; - struct whiteheat_urb_wrap *wrap; - int chars = 0; - unsigned long flags; - - dbg("%s - port %d", __func__, port->number); - - spin_lock_irqsave(&info->lock, flags); - list_for_each(tmp, &info->tx_urbs_submitted) { - wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); - chars += wrap->urb->transfer_buffer_length; - } - spin_unlock_irqrestore(&info->lock, flags); - - dbg("%s - returns %d", __func__, chars); - return chars; -} - - -static void whiteheat_throttle(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - struct whiteheat_private *info = usb_get_serial_port_data(port); - - dbg("%s - port %d", __func__, port->number); - - spin_lock_irq(&info->lock); - info->flags |= THROTTLED; - spin_unlock_irq(&info->lock); -} - - -static void whiteheat_unthrottle(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - struct whiteheat_private *info = usb_get_serial_port_data(port); - int actually_throttled; - - dbg("%s - port %d", __func__, port->number); - - spin_lock_irq(&info->lock); - actually_throttled = info->flags & ACTUALLY_THROTTLED; - info->flags &= ~(THROTTLED | ACTUALLY_THROTTLED); - spin_unlock_irq(&info->lock); - - if (actually_throttled) - rx_data_softint(&info->rx_work); -} - - /***************************************************************************** * Connect Tech's White Heat callback routines *****************************************************************************/ @@ -928,8 +585,6 @@ static void command_port_write_callback(struct urb *urb) { int status = urb->status; - dbg("%s", __func__); - if (status) { dbg("nonzero urb status: %d", status); return; @@ -945,8 +600,6 @@ static void command_port_read_callback(struct urb *urb) unsigned char *data = urb->transfer_buffer; int result; - dbg("%s", __func__); - command_info = usb_get_serial_port_data(command_port); if (!command_info) { dbg("%s - command_info is NULL, exiting.", __func__); @@ -989,80 +642,6 @@ static void command_port_read_callback(struct urb *urb) } -static void whiteheat_read_callback(struct urb *urb) -{ - struct usb_serial_port *port = urb->context; - struct whiteheat_urb_wrap *wrap; - unsigned char *data = urb->transfer_buffer; - struct whiteheat_private *info = usb_get_serial_port_data(port); - int status = urb->status; - - dbg("%s - port %d", __func__, port->number); - - spin_lock(&info->lock); - wrap = urb_to_wrap(urb, &info->rx_urbs_submitted); - if (!wrap) { - spin_unlock(&info->lock); - dev_err(&port->dev, "%s - Not my urb!\n", __func__); - return; - } - list_del(&wrap->list); - spin_unlock(&info->lock); - - if (status) { - dbg("%s - nonzero read bulk status received: %d", - __func__, status); - spin_lock(&info->lock); - list_add(&wrap->list, &info->rx_urbs_free); - spin_unlock(&info->lock); - return; - } - - usb_serial_debug_data(debug, &port->dev, - __func__, urb->actual_length, data); - - spin_lock(&info->lock); - list_add_tail(&wrap->list, &info->rx_urb_q); - if (info->flags & THROTTLED) { - info->flags |= ACTUALLY_THROTTLED; - spin_unlock(&info->lock); - return; - } - spin_unlock(&info->lock); - - schedule_work(&info->rx_work); -} - - -static void whiteheat_write_callback(struct urb *urb) -{ - struct usb_serial_port *port = urb->context; - struct whiteheat_private *info = usb_get_serial_port_data(port); - struct whiteheat_urb_wrap *wrap; - int status = urb->status; - - dbg("%s - port %d", __func__, port->number); - - spin_lock(&info->lock); - wrap = urb_to_wrap(urb, &info->tx_urbs_submitted); - if (!wrap) { - spin_unlock(&info->lock); - dev_err(&port->dev, "%s - Not my urb!\n", __func__); - return; - } - list_move(&wrap->list, &info->tx_urbs_free); - spin_unlock(&info->lock); - - if (status) { - dbg("%s - nonzero write bulk status received: %d", - __func__, status); - return; - } - - usb_serial_port_softint(port); -} - - /***************************************************************************** * Connect Tech's White Heat firmware interface *****************************************************************************/ @@ -1337,123 +916,6 @@ static void stop_command_port(struct usb_serial *serial) mutex_unlock(&command_info->mutex); } - -static int start_port_read(struct usb_serial_port *port) -{ - struct whiteheat_private *info = usb_get_serial_port_data(port); - struct whiteheat_urb_wrap *wrap; - struct urb *urb; - int retval = 0; - unsigned long flags; - struct list_head *tmp; - struct list_head *tmp2; - - spin_lock_irqsave(&info->lock, flags); - - list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) { - list_del(tmp); - wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); - urb = wrap->urb; - spin_unlock_irqrestore(&info->lock, flags); - retval = usb_submit_urb(urb, GFP_KERNEL); - if (retval) { - spin_lock_irqsave(&info->lock, flags); - list_add(tmp, &info->rx_urbs_free); - list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) { - wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); - urb = wrap->urb; - list_del(tmp); - spin_unlock_irqrestore(&info->lock, flags); - usb_kill_urb(urb); - spin_lock_irqsave(&info->lock, flags); - list_add(tmp, &info->rx_urbs_free); - } - break; - } - spin_lock_irqsave(&info->lock, flags); - list_add(tmp, &info->rx_urbs_submitted); - } - - spin_unlock_irqrestore(&info->lock, flags); - - return retval; -} - - -static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, - struct list_head *head) -{ - struct whiteheat_urb_wrap *wrap; - struct list_head *tmp; - - list_for_each(tmp, head) { - wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); - if (wrap->urb == urb) - return wrap; - } - - return NULL; -} - - -static struct list_head *list_first(struct list_head *head) -{ - return head->next; -} - - -static void rx_data_softint(struct work_struct *work) -{ - struct whiteheat_private *info = - container_of(work, struct whiteheat_private, rx_work); - struct usb_serial_port *port = info->port; - struct tty_struct *tty = tty_port_tty_get(&port->port); - struct whiteheat_urb_wrap *wrap; - struct urb *urb; - unsigned long flags; - struct list_head *tmp; - struct list_head *tmp2; - int result; - int sent = 0; - - spin_lock_irqsave(&info->lock, flags); - if (info->flags & THROTTLED) { - spin_unlock_irqrestore(&info->lock, flags); - goto out; - } - - list_for_each_safe(tmp, tmp2, &info->rx_urb_q) { - list_del(tmp); - spin_unlock_irqrestore(&info->lock, flags); - - wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); - urb = wrap->urb; - - if (tty && urb->actual_length) - sent += tty_insert_flip_string(tty, - urb->transfer_buffer, urb->actual_length); - - result = usb_submit_urb(urb, GFP_ATOMIC); - if (result) { - dev_err(&port->dev, - "%s - failed resubmitting read urb, error %d\n", - __func__, result); - spin_lock_irqsave(&info->lock, flags); - list_add(tmp, &info->rx_urbs_free); - continue; - } - - spin_lock_irqsave(&info->lock, flags); - list_add(tmp, &info->rx_urbs_submitted); - } - spin_unlock_irqrestore(&info->lock, flags); - - if (sent) - tty_flip_buffer_push(tty); -out: - tty_kref_put(tty); -} - module_usb_serial_driver(whiteheat_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); @@ -1463,8 +925,5 @@ MODULE_LICENSE("GPL"); MODULE_FIRMWARE("whiteheat.fw"); MODULE_FIRMWARE("whiteheat_loader.fw"); -module_param(urb_pool_size, int, 0); -MODULE_PARM_DESC(urb_pool_size, "Number of urbs to use for buffering"); - module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index e7e678109500..b28f2ad127d4 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -1933,11 +1933,7 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag) kfree(buf); nofw: - if (sd_fw != NULL) { - release_firmware(sd_fw); - sd_fw = NULL; - } - + release_firmware(sd_fw); return result; } diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index b4a71679c933..0616f235bd6b 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -93,8 +93,8 @@ static int skel_open(struct inode *inode, struct file *file) interface = usb_find_interface(&skel_driver, subminor); if (!interface) { - err("%s - error, can't find device for minor %d", - __func__, subminor); + pr_err("%s - error, can't find device for minor %d\n", + __func__, subminor); retval = -ENODEV; goto exit; } @@ -179,8 +179,9 @@ static void skel_read_bulk_callback(struct urb *urb) if (!(urb->status == -ENOENT || urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) - err("%s - nonzero write bulk status received: %d", - __func__, urb->status); + dev_err(&dev->interface->dev, + "%s - nonzero write bulk status received: %d\n", + __func__, urb->status); dev->errors = urb->status; } else { @@ -213,7 +214,8 @@ static int skel_do_read_io(struct usb_skel *dev, size_t count) /* do it */ rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL); if (rv < 0) { - err("%s - failed submitting read urb, error %d", + dev_err(&dev->interface->dev, + "%s - failed submitting read urb, error %d\n", __func__, rv); dev->bulk_in_filled = 0; rv = (rv == -ENOMEM) ? rv : -EIO; @@ -364,8 +366,9 @@ static void skel_write_bulk_callback(struct urb *urb) if (!(urb->status == -ENOENT || urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) - err("%s - nonzero write bulk status received: %d", - __func__, urb->status); + dev_err(&dev->interface->dev, + "%s - nonzero write bulk status received: %d\n", + __func__, urb->status); spin_lock(&dev->err_lock); dev->errors = urb->status; @@ -459,8 +462,9 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, retval = usb_submit_urb(urb, GFP_KERNEL); mutex_unlock(&dev->io_mutex); if (retval) { - err("%s - failed submitting write urb, error %d", __func__, - retval); + dev_err(&dev->interface->dev, + "%s - failed submitting write urb, error %d\n", + __func__, retval); goto error_unanchor; } @@ -519,7 +523,7 @@ static int skel_probe(struct usb_interface *interface, /* allocate memory for our device state and initialize it */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { - err("Out of memory"); + dev_err(&interface->dev, "Out of memory\n"); goto error; } kref_init(&dev->kref); @@ -546,12 +550,14 @@ static int skel_probe(struct usb_interface *interface, dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!dev->bulk_in_buffer) { - err("Could not allocate bulk_in_buffer"); + dev_err(&interface->dev, + "Could not allocate bulk_in_buffer\n"); goto error; } dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->bulk_in_urb) { - err("Could not allocate bulk_in_urb"); + dev_err(&interface->dev, + "Could not allocate bulk_in_urb\n"); goto error; } } @@ -563,7 +569,8 @@ static int skel_probe(struct usb_interface *interface, } } if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) { - err("Could not find both bulk-in and bulk-out endpoints"); + dev_err(&interface->dev, + "Could not find both bulk-in and bulk-out endpoints\n"); goto error; } @@ -574,7 +581,8 @@ static int skel_probe(struct usb_interface *interface, retval = usb_register_dev(interface, &skel_class); if (retval) { /* something prevented us from registering this driver */ - err("Not able to get a minor for this device."); + dev_err(&interface->dev, + "Not able to get a minor for this device.\n"); usb_set_intfdata(interface, NULL); goto error; } |