diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-05-03 18:05:27 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-05-03 18:05:27 +0200 |
commit | 3515468a87a47781f6af818773650513ff14656a (patch) | |
tree | 55241860ef8d7cf670c0d042aafd02976d0ef370 /drivers/usb/gadget | |
parent | 12456e509be25d24fe479394852428517922d02a (diff) | |
parent | 2e487d280525b91b03976203b15aba365ec5b4e6 (diff) | |
download | linux-stable-3515468a87a47781f6af818773650513ff14656a.tar.gz linux-stable-3515468a87a47781f6af818773650513ff14656a.tar.bz2 linux-stable-3515468a87a47781f6af818773650513ff14656a.zip |
Merge tag 'usb-for-v5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
Felipe writes:
USB: changes for v5.2 merge window
With a total of 50 non-merge commits, this is not a large pull
request. Most of the changes are, again, in dwc2 (37%) and dwc3 (32%)
with the rest of it scattered among other UDCs, function drivers and
device-tree bindings.
No really big feature this time around apart from support to Amlogic
being added to both dwc3 and dwc2 drivers.
* tag 'usb-for-v5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb: (50 commits)
usb: dwc3: Rename DWC3_DCTL_LPM_ERRATA
usb: dwc3: Fix default lpm_nyet_threshold value
usb: dwc3: debug: Print GET_STATUS(device) tracepoint
usb: dwc3: Do core validation early on probe
usb: dwc3: gadget: Set lpm_capable
usb: gadget: atmel: tie wake lock to running clock
usb: gadget: atmel: support USB suspend
usb: gadget: atmel_usba_udc: simplify setting of interrupt-enabled mask
dwc2: gadget: Fix completed transfer size calculation in DDMA
usb: dwc2: Set lpm mode parameters depend on HW configuration
usb: dwc2: Fix channel disable flow
usb: dwc2: Set actual frame number for completed ISOC transfer
usb: gadget: do not use __constant_cpu_to_le16
usb: dwc2: gadget: Increase descriptors count for ISOC's
usb: introduce usb_ep_type_string() function
usb: dwc3: move synchronize_irq() out of the spinlock protected block
usb: dwc3: Free resource immediately after use
usb: dwc3: of-simple: Convert to bulk clk API
usb: dwc2: Delayed status support
usb: gadget: udc: lpc32xx: rework interrupt handling
...
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_ncm.c | 57 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_uac1_legacy.c | 6 | ||||
-rw-r--r-- | drivers/usb/gadget/function/u_ncm.h | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/atmel_usba_udc.c | 84 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/atmel_usba_udc.h | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/dummy_hcd.c | 19 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/lpc32xx_udc.c | 167 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/net2272.c | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/net2280.c | 5 |
10 files changed, 210 insertions, 138 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 20413c276c61..47be961f1bf3 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1133,7 +1133,8 @@ error_lock: error_mutex: mutex_unlock(&epfile->mutex); error: - ffs_free_buffer(io_data); + if (ret != -EIOCBQUEUED) /* don't free if there is iocb queued */ + ffs_free_buffer(io_data); return ret; } diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index 5780fba620ab..2d6e76e4cffa 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -23,6 +23,7 @@ #include "u_ether.h" #include "u_ether_configfs.h" #include "u_ncm.h" +#include "configfs.h" /* * This function is a "CDC Network Control Model" (CDC NCM) Ethernet link. @@ -35,9 +36,7 @@ /* to trigger crc/non-crc ndp signature */ -#define NCM_NDP_HDR_CRC_MASK 0x01000000 #define NCM_NDP_HDR_CRC 0x01000000 -#define NCM_NDP_HDR_NOCRC 0x00000000 enum ncm_notify_state { NCM_NOTIFY_NONE, /* don't notify */ @@ -526,6 +525,7 @@ static inline void ncm_reset_values(struct f_ncm *ncm) { ncm->parser_opts = &ndp16_opts; ncm->is_crc = false; + ncm->ndp_sign = ncm->parser_opts->ndp_sign; ncm->port.cdc_filter = DEFAULT_FILTER; /* doesn't make sense for ncm, fixed size used */ @@ -805,25 +805,20 @@ static int ncm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) | USB_CDC_SET_CRC_MODE: { - int ndp_hdr_crc = 0; - if (w_length != 0 || w_index != ncm->ctrl_id) goto invalid; switch (w_value) { case 0x0000: ncm->is_crc = false; - ndp_hdr_crc = NCM_NDP_HDR_NOCRC; DBG(cdev, "non-CRC mode selected\n"); break; case 0x0001: ncm->is_crc = true; - ndp_hdr_crc = NCM_NDP_HDR_CRC; DBG(cdev, "CRC mode selected\n"); break; default: goto invalid; } - ncm->ndp_sign = ncm->parser_opts->ndp_sign | ndp_hdr_crc; value = 0; break; } @@ -840,6 +835,8 @@ invalid: ctrl->bRequestType, ctrl->bRequest, w_value, w_index, w_length); } + ncm->ndp_sign = ncm->parser_opts->ndp_sign | + (ncm->is_crc ? NCM_NDP_HDR_CRC : 0); /* respond with data transfer or status phase? */ if (value >= 0) { @@ -1395,6 +1392,16 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) return -EINVAL; ncm_opts = container_of(f->fi, struct f_ncm_opts, func_inst); + + if (cdev->use_os_string) { + f->os_desc_table = kzalloc(sizeof(*f->os_desc_table), + GFP_KERNEL); + if (!f->os_desc_table) + return -ENOMEM; + f->os_desc_n = 1; + f->os_desc_table[0].os_desc = &ncm_opts->ncm_os_desc; + } + /* * in drivers/usb/gadget/configfs.c:configfs_composite_bind() * configurations are bound in sequence with list_for_each_entry, @@ -1408,13 +1415,15 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) status = gether_register_netdev(ncm_opts->net); mutex_unlock(&ncm_opts->lock); if (status) - return status; + goto fail; ncm_opts->bound = true; } us = usb_gstrings_attach(cdev, ncm_strings, ARRAY_SIZE(ncm_string_defs)); - if (IS_ERR(us)) - return PTR_ERR(us); + if (IS_ERR(us)) { + status = PTR_ERR(us); + goto fail; + } ncm_control_intf.iInterface = us[STRING_CTRL_IDX].id; ncm_data_nop_intf.iInterface = us[STRING_DATA_IDX].id; ncm_data_intf.iInterface = us[STRING_DATA_IDX].id; @@ -1431,6 +1440,10 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) ncm_control_intf.bInterfaceNumber = status; ncm_union_desc.bMasterInterface0 = status; + if (cdev->use_os_string) + f->os_desc_table[0].if_id = + ncm_iad_desc.bFirstInterface; + status = usb_interface_id(c, f); if (status < 0) goto fail; @@ -1510,6 +1523,9 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) return 0; fail: + kfree(f->os_desc_table); + f->os_desc_n = 0; + if (ncm->notify_req) { kfree(ncm->notify_req->buf); usb_ep_free_request(ncm->notify, ncm->notify_req); @@ -1564,16 +1580,22 @@ static void ncm_free_inst(struct usb_function_instance *f) gether_cleanup(netdev_priv(opts->net)); else free_netdev(opts->net); + kfree(opts->ncm_interf_group); kfree(opts); } static struct usb_function_instance *ncm_alloc_inst(void) { struct f_ncm_opts *opts; + struct usb_os_desc *descs[1]; + char *names[1]; + struct config_group *ncm_interf_group; opts = kzalloc(sizeof(*opts), GFP_KERNEL); if (!opts) return ERR_PTR(-ENOMEM); + opts->ncm_os_desc.ext_compat_id = opts->ncm_ext_compat_id; + mutex_init(&opts->lock); opts->func_inst.free_func_inst = ncm_free_inst; opts->net = gether_setup_default(); @@ -1582,8 +1604,20 @@ static struct usb_function_instance *ncm_alloc_inst(void) kfree(opts); return ERR_CAST(net); } + INIT_LIST_HEAD(&opts->ncm_os_desc.ext_prop); + + descs[0] = &opts->ncm_os_desc; + names[0] = "ncm"; config_group_init_type_name(&opts->func_inst.group, "", &ncm_func_type); + ncm_interf_group = + usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs, + names, THIS_MODULE); + if (IS_ERR(ncm_interf_group)) { + ncm_free_inst(&opts->func_inst); + return ERR_CAST(ncm_interf_group); + } + opts->ncm_interf_group = ncm_interf_group; return &opts->func_inst; } @@ -1609,6 +1643,9 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f) hrtimer_cancel(&ncm->task_timer); + kfree(f->os_desc_table); + f->os_desc_n = 0; + ncm_string_defs[0].id = 0; usb_free_all_descriptors(f); diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c b/drivers/usb/gadget/function/f_uac1_legacy.c index 24c086bcdeaa..6677ae932de0 100644 --- a/drivers/usb/gadget/function/f_uac1_legacy.c +++ b/drivers/usb/gadget/function/f_uac1_legacy.c @@ -54,8 +54,8 @@ static struct uac1_ac_header_descriptor_1 ac_header_desc = { .bLength = UAC_DT_AC_HEADER_LENGTH, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = UAC_HEADER, - .bcdADC = __constant_cpu_to_le16(0x0100), - .wTotalLength = __constant_cpu_to_le16(UAC_DT_TOTAL_LENGTH), + .bcdADC = cpu_to_le16(0x0100), + .wTotalLength = cpu_to_le16(UAC_DT_TOTAL_LENGTH), .bInCollection = F_AUDIO_NUM_INTERFACES, .baInterfaceNr = { /* Interface number of the first AudioStream interface */ @@ -183,7 +183,7 @@ static struct uac_iso_endpoint_descriptor as_iso_out_desc = { .bDescriptorSubtype = UAC_EP_GENERAL, .bmAttributes = 1, .bLockDelayUnits = 1, - .wLockDelay = __constant_cpu_to_le16(1), + .wLockDelay = cpu_to_le16(1), }; static struct usb_descriptor_header *f_audio_desc[] = { diff --git a/drivers/usb/gadget/function/u_ncm.h b/drivers/usb/gadget/function/u_ncm.h index d483e45c0f77..70da3201a1d0 100644 --- a/drivers/usb/gadget/function/u_ncm.h +++ b/drivers/usb/gadget/function/u_ncm.h @@ -20,6 +20,9 @@ struct f_ncm_opts { struct net_device *net; bool bound; + struct config_group *ncm_interf_group; + struct usb_os_desc ncm_os_desc; + char ncm_ext_compat_id[16]; /* * Read/write access to configfs attributes is handled by configfs. * diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 660712e0bf98..503d275bc4c4 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -358,8 +358,20 @@ static inline u32 usba_int_enb_get(struct usba_udc *udc) return udc->int_enb_cache; } -static inline void usba_int_enb_set(struct usba_udc *udc, u32 val) +static inline void usba_int_enb_set(struct usba_udc *udc, u32 mask) { + u32 val; + + val = udc->int_enb_cache | mask; + usba_writel(udc, INT_ENB, val); + udc->int_enb_cache = val; +} + +static inline void usba_int_enb_clear(struct usba_udc *udc, u32 mask) +{ + u32 val; + + val = udc->int_enb_cache & ~mask; usba_writel(udc, INT_ENB, val); udc->int_enb_cache = val; } @@ -629,14 +641,12 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) if (ep->can_dma) { u32 ctrl; - usba_int_enb_set(udc, usba_int_enb_get(udc) | - USBA_BF(EPT_INT, 1 << ep->index) | + usba_int_enb_set(udc, USBA_BF(EPT_INT, 1 << ep->index) | USBA_BF(DMA_INT, 1 << ep->index)); ctrl = USBA_AUTO_VALID | USBA_INTDIS_DMA; usba_ep_writel(ep, CTL_ENB, ctrl); } else { - usba_int_enb_set(udc, usba_int_enb_get(udc) | - USBA_BF(EPT_INT, 1 << ep->index)); + usba_int_enb_set(udc, USBA_BF(EPT_INT, 1 << ep->index)); } spin_unlock_irqrestore(&udc->lock, flags); @@ -680,8 +690,7 @@ static int usba_ep_disable(struct usb_ep *_ep) usba_dma_readl(ep, STATUS); } usba_ep_writel(ep, CTL_DIS, USBA_EPT_ENABLE); - usba_int_enb_set(udc, usba_int_enb_get(udc) & - ~USBA_BF(EPT_INT, 1 << ep->index)); + usba_int_enb_clear(udc, USBA_BF(EPT_INT, 1 << ep->index)); request_complete_list(ep, &req_list, -ESHUTDOWN); @@ -1694,6 +1703,9 @@ static void usba_dma_irq(struct usba_udc *udc, struct usba_ep *ep) } } +static int start_clock(struct usba_udc *udc); +static void stop_clock(struct usba_udc *udc); + static irqreturn_t usba_udc_irq(int irq, void *devid) { struct usba_udc *udc = devid; @@ -1708,10 +1720,13 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) DBG(DBG_INT, "irq, status=%#08x\n", status); if (status & USBA_DET_SUSPEND) { + usba_writel(udc, INT_CLR, USBA_DET_SUSPEND|USBA_WAKE_UP); + usba_int_enb_set(udc, USBA_WAKE_UP); + usba_int_enb_clear(udc, USBA_DET_SUSPEND); + udc->suspended = true; toggle_bias(udc, 0); - usba_writel(udc, INT_CLR, USBA_DET_SUSPEND); - usba_int_enb_set(udc, int_enb | USBA_WAKE_UP); udc->bias_pulse_needed = true; + stop_clock(udc); DBG(DBG_BUS, "Suspend detected\n"); if (udc->gadget.speed != USB_SPEED_UNKNOWN && udc->driver && udc->driver->suspend) { @@ -1722,14 +1737,17 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) } if (status & USBA_WAKE_UP) { + start_clock(udc); toggle_bias(udc, 1); usba_writel(udc, INT_CLR, USBA_WAKE_UP); - usba_int_enb_set(udc, int_enb & ~USBA_WAKE_UP); DBG(DBG_BUS, "Wake Up CPU detected\n"); } if (status & USBA_END_OF_RESUME) { + udc->suspended = false; usba_writel(udc, INT_CLR, USBA_END_OF_RESUME); + usba_int_enb_clear(udc, USBA_WAKE_UP); + usba_int_enb_set(udc, USBA_DET_SUSPEND); generate_bias_pulse(udc); DBG(DBG_BUS, "Resume detected\n"); if (udc->gadget.speed != USB_SPEED_UNKNOWN @@ -1744,6 +1762,8 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) if (dma_status) { int i; + usba_int_enb_set(udc, USBA_DET_SUSPEND); + for (i = 1; i <= USBA_NR_DMAS; i++) if (dma_status & (1 << i)) usba_dma_irq(udc, &udc->usba_ep[i]); @@ -1753,6 +1773,8 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) if (ep_status) { int i; + usba_int_enb_set(udc, USBA_DET_SUSPEND); + for (i = 0; i < udc->num_ep; i++) if (ep_status & (1 << i)) { if (ep_is_control(&udc->usba_ep[i])) @@ -1766,7 +1788,9 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) struct usba_ep *ep0, *ep; int i, n; - usba_writel(udc, INT_CLR, USBA_END_OF_RESET); + usba_writel(udc, INT_CLR, + USBA_END_OF_RESET|USBA_END_OF_RESUME + |USBA_DET_SUSPEND|USBA_WAKE_UP); generate_bias_pulse(udc); reset_all_endpoints(udc); @@ -1793,7 +1817,12 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) | USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE))); usba_ep_writel(ep0, CTL_ENB, USBA_EPT_ENABLE | USBA_RX_SETUP); - usba_int_enb_set(udc, int_enb | USBA_BF(EPT_INT, 1) | + + /* If we get reset while suspended... */ + udc->suspended = false; + usba_int_enb_clear(udc, USBA_WAKE_UP); + + usba_int_enb_set(udc, USBA_BF(EPT_INT, 1) | USBA_DET_SUSPEND | USBA_END_OF_RESUME); /* @@ -1827,6 +1856,8 @@ static int start_clock(struct usba_udc *udc) if (udc->clocked) return 0; + pm_stay_awake(&udc->pdev->dev); + ret = clk_prepare_enable(udc->pclk); if (ret) return ret; @@ -1849,6 +1880,8 @@ static void stop_clock(struct usba_udc *udc) clk_disable_unprepare(udc->pclk); udc->clocked = false; + + pm_relax(&udc->pdev->dev); } static int usba_start(struct usba_udc *udc) @@ -1860,9 +1893,19 @@ static int usba_start(struct usba_udc *udc) if (ret) return ret; + if (udc->suspended) + return 0; + spin_lock_irqsave(&udc->lock, flags); toggle_bias(udc, 1); usba_writel(udc, CTRL, USBA_ENABLE_MASK); + /* Clear all requested and pending interrupts... */ + usba_writel(udc, INT_ENB, 0); + udc->int_enb_cache = 0; + usba_writel(udc, INT_CLR, + USBA_END_OF_RESET|USBA_END_OF_RESUME + |USBA_DET_SUSPEND|USBA_WAKE_UP); + /* ...and enable just 'reset' IRQ to get us started */ usba_int_enb_set(udc, USBA_END_OF_RESET); spin_unlock_irqrestore(&udc->lock, flags); @@ -1873,6 +1916,9 @@ static void usba_stop(struct usba_udc *udc) { unsigned long flags; + if (udc->suspended) + return; + spin_lock_irqsave(&udc->lock, flags); udc->gadget.speed = USB_SPEED_UNKNOWN; reset_all_endpoints(udc); @@ -1900,6 +1946,7 @@ static irqreturn_t usba_vbus_irq_thread(int irq, void *devid) if (vbus) { usba_start(udc); } else { + udc->suspended = false; usba_stop(udc); if (udc->driver->disconnect) @@ -1963,6 +2010,7 @@ static int atmel_usba_stop(struct usb_gadget *gadget) if (fifo_mode == 0) udc->configured_ep = 1; + udc->suspended = false; usba_stop(udc); udc->driver = NULL; @@ -2276,6 +2324,7 @@ static int usba_udc_suspend(struct device *dev) mutex_lock(&udc->vbus_mutex); if (!device_may_wakeup(dev)) { + udc->suspended = false; usba_stop(udc); goto out; } @@ -2285,10 +2334,13 @@ static int usba_udc_suspend(struct device *dev) * to request vbus irq, assuming always on. */ if (udc->vbus_pin) { + /* FIXME: right to stop here...??? */ usba_stop(udc); enable_irq_wake(gpiod_to_irq(udc->vbus_pin)); } + enable_irq_wake(udc->irq); + out: mutex_unlock(&udc->vbus_mutex); return 0; @@ -2302,8 +2354,12 @@ static int usba_udc_resume(struct device *dev) if (!udc->driver) return 0; - if (device_may_wakeup(dev) && udc->vbus_pin) - disable_irq_wake(gpiod_to_irq(udc->vbus_pin)); + if (device_may_wakeup(dev)) { + if (udc->vbus_pin) + disable_irq_wake(gpiod_to_irq(udc->vbus_pin)); + + disable_irq_wake(udc->irq); + } /* If Vbus is present, enable the controller and wait for reset */ mutex_lock(&udc->vbus_mutex); diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.h b/drivers/usb/gadget/udc/atmel_usba_udc.h index 030bf797cd25..a0225e4543d4 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.h +++ b/drivers/usb/gadget/udc/atmel_usba_udc.h @@ -331,6 +331,7 @@ struct usba_udc { struct usba_ep *usba_ep; bool bias_pulse_needed; bool clocked; + bool suspended; u16 devstatus; diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index 40c6a484e232..8414fac74493 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -965,8 +965,18 @@ static int dummy_udc_start(struct usb_gadget *g, struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(g); struct dummy *dum = dum_hcd->dum; - if (driver->max_speed == USB_SPEED_UNKNOWN) + switch (g->speed) { + /* All the speeds we support */ + case USB_SPEED_LOW: + case USB_SPEED_FULL: + case USB_SPEED_HIGH: + case USB_SPEED_SUPER: + break; + default: + dev_err(dummy_dev(dum_hcd), "Unsupported driver max speed %d\n", + driver->max_speed); return -EINVAL; + } /* * SLAVE side init ... the layer above hardware, which @@ -1770,9 +1780,10 @@ static void dummy_timer(struct timer_list *t) /* Bus speed is 500000 bytes/ms, so use a little less */ total = 490000; break; - default: + default: /* Can't happen */ dev_err(dummy_dev(dum_hcd), "bogus device speed\n"); - return; + total = 0; + break; } /* FIXME if HZ != 1000 this will probably misbehave ... */ @@ -1814,7 +1825,7 @@ restart: /* Used up this frame's bandwidth? */ if (total <= 0) - break; + continue; /* find the gadget's ep for this request (if configured) */ address = usb_pipeendpoint (urb->pipe); diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c index b0781771704e..d8f1c60793ed 100644 --- a/drivers/usb/gadget/udc/lpc32xx_udc.c +++ b/drivers/usb/gadget/udc/lpc32xx_udc.c @@ -115,6 +115,11 @@ struct lpc32xx_ep { bool wedge; }; +enum atx_type { + ISP1301, + STOTG04, +}; + /* * Common UDC structure */ @@ -129,8 +134,6 @@ struct lpc32xx_udc { /* 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_slv_clk; @@ -151,10 +154,10 @@ struct lpc32xx_udc { u8 last_vbus; int pullup; int poweron; + enum atx_type atx; /* 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 */ @@ -553,6 +556,15 @@ static inline void remove_debug_file(struct lpc32xx_udc *udc) {} /* Primary initialization sequence for the ISP1301 transceiver */ static void isp1301_udc_configure(struct lpc32xx_udc *udc) { + u8 value; + s32 vendor, product; + + vendor = i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00); + product = i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x02); + + if (vendor == 0x0483 && product == 0xa0c4) + udc->atx = STOTG04; + /* LPC32XX only supports DAT_SE0 USB mode */ /* This sequence is important */ @@ -572,8 +584,12 @@ static void isp1301_udc_configure(struct lpc32xx_udc *udc) */ i2c_smbus_write_byte_data(udc->isp1301_i2c_client, (ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR), ~0); + + value = MC2_BI_DI; + if (udc->atx != STOTG04) + value |= MC2_SPD_SUSP_CTRL; i2c_smbus_write_byte_data(udc->isp1301_i2c_client, - ISP1301_I2C_MODE_CONTROL_2, (MC2_BI_DI | MC2_SPD_SUSP_CTRL)); + ISP1301_I2C_MODE_CONTROL_2, value); /* Driver VBUS_DRV high or low depending on board setup */ if (udc->board->vbus_drv_pol != 0) @@ -601,24 +617,19 @@ static void isp1301_udc_configure(struct lpc32xx_udc *udc) (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); - 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 Vendor ID : 0x%04x\n", vendor); + dev_info(udc->dev, "ISP1301 Product ID : 0x%04x\n", product); 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 */ @@ -661,6 +672,10 @@ static void isp1301_pullup_enable(struct lpc32xx_udc *udc, int en_pullup, /* Powers up or down the ISP1301 transceiver */ static void isp1301_set_powerstate(struct lpc32xx_udc *udc, int enable) { + /* There is no "global power down" register for stotg04 */ + if (udc->atx == STOTG04) + return; + if (enable != 0) /* Power up ISP1301 - this ISP1301 will automatically wakeup when VBUS is detected */ @@ -2830,11 +2845,9 @@ static irqreturn_t lpc32xx_usb_devdma_irq(int irq, void *_udc) * VBUS detection, pullup handler, and Gadget cable state notification * */ -static void vbus_work(struct work_struct *work) +static void vbus_work(struct lpc32xx_udc *udc) { u8 value; - struct lpc32xx_udc *udc = container_of(work, struct lpc32xx_udc, - vbus_job); if (udc->enabled != 0) { /* Discharge VBUS real quick */ @@ -2870,18 +2883,13 @@ static void vbus_work(struct work_struct *work) 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); + vbus_work(udc); return IRQ_HANDLED; } @@ -2890,7 +2898,6 @@ static int lpc32xx_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { struct lpc32xx_udc *udc = to_udc(gadget); - int i; if (!driver || driver->max_speed < USB_SPEED_FULL || !driver->setup) { dev_err(udc->dev, "bad parameter.\n"); @@ -2910,22 +2917,25 @@ static int lpc32xx_start(struct usb_gadget *gadget, /* Force VBUS process once to check for cable insertion */ udc->last_vbus = udc->vbus = 0; - schedule_work(&udc->vbus_job); + vbus_work(udc); - /* Do not re-enable ATX IRQ (3) */ - for (i = IRQ_USB_LP; i < IRQ_USB_ATX; i++) - enable_irq(udc->udp_irq[i]); + /* enable interrupts */ + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_INTERRUPT_FALLING, INT_SESS_VLD | INT_VBUS_VLD); + i2c_smbus_write_byte_data(udc->isp1301_i2c_client, + ISP1301_I2C_INTERRUPT_RISING, INT_SESS_VLD | INT_VBUS_VLD); return 0; } static int lpc32xx_stop(struct usb_gadget *gadget) { - int i; struct lpc32xx_udc *udc = to_udc(gadget); - for (i = IRQ_USB_LP; i <= IRQ_USB_ATX; i++) - disable_irq(udc->udp_irq[i]); + 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_RISING | ISP1301_I2C_REG_CLEAR_ADDR, ~0); if (udc->clocked) { spin_lock(&udc->lock); @@ -2999,7 +3009,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) dma_addr_t dma_handle; struct device_node *isp1301_node; - udc = kmemdup(&controller_template, sizeof(*udc), GFP_KERNEL); + udc = devm_kmemdup(dev, &controller_template, sizeof(*udc), GFP_KERNEL); if (!udc) return -ENOMEM; @@ -3022,8 +3032,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) udc->isp1301_i2c_client = isp1301_get_client(isp1301_node); if (!udc->isp1301_i2c_client) { - retval = -EPROBE_DEFER; - goto phy_fail; + return -EPROBE_DEFER; } dev_info(udc->dev, "ISP1301 I2C device at address 0x%x\n", @@ -3032,7 +3041,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) pdev->dev.dma_mask = &lpc32xx_usbd_dmamask; retval = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (retval) - goto resource_fail; + return retval; udc->board = &lpc32xx_usbddata; @@ -3045,10 +3054,8 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) * IORESOURCE_IRQ, USB transceiver interrupt number */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - retval = -ENXIO; - goto resource_fail; - } + if (!res) + return -ENXIO; spin_lock_init(&udc->lock); @@ -3058,45 +3065,33 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) if (udc->udp_irq[i] < 0) { dev_err(udc->dev, "irq resource %d not available!\n", i); - retval = udc->udp_irq[i]; - goto irq_fail; + 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"); - retval = -EBUSY; - goto request_mem_region_fail; - } - - udc->udp_baseaddr = ioremap(udc->io_p_start, udc->io_p_size); + udc->udp_baseaddr = devm_ioremap_resource(dev, res); if (!udc->udp_baseaddr) { - retval = -ENOMEM; dev_err(udc->dev, "IO map failure\n"); - goto io_map_fail; + return -ENOMEM; } /* Get USB device clock */ - udc->usb_slv_clk = clk_get(&pdev->dev, NULL); + udc->usb_slv_clk = devm_clk_get(&pdev->dev, NULL); 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; + return PTR_ERR(udc->usb_slv_clk); } /* Enable USB device clock */ retval = clk_prepare_enable(udc->usb_slv_clk); if (retval < 0) { dev_err(udc->dev, "failed to start USB device clock\n"); - goto usb_clk_enable_fail; + return retval; } /* 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 @@ -3134,47 +3129,44 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) /* 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); + retval = devm_request_irq(dev, 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; + goto irq_req_fail; } - retval = request_irq(udc->udp_irq[IRQ_USB_HP], lpc32xx_usb_hp_irq, - 0, "udc_hp", udc); + retval = devm_request_irq(dev, 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; + goto irq_req_fail; } - retval = request_irq(udc->udp_irq[IRQ_USB_DEVDMA], - lpc32xx_usb_devdma_irq, 0, "udc_dma", udc); + retval = devm_request_irq(dev, 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; + goto irq_req_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); + retval = devm_request_threaded_irq(dev, udc->udp_irq[IRQ_USB_ATX], NULL, + lpc32xx_usb_vbus_irq, IRQF_ONESHOT, + "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; + goto irq_req_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; @@ -3190,32 +3182,15 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) 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: +irq_req_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_unprepare(udc->usb_slv_clk); -usb_clk_enable_fail: - clk_put(udc->usb_slv_clk); -usb_clk_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); -request_mem_region_fail: -irq_fail: -resource_fail: -phy_fail: - kfree(udc); + return retval; } @@ -3231,24 +3206,14 @@ static int lpc32xx_udc_remove(struct platform_device *pdev) 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); clk_disable_unprepare(udc->usb_slv_clk); - clk_put(udc->usb_slv_clk); - - iounmap(udc->udp_baseaddr); - release_mem_region(udc->io_p_start, udc->io_p_size); - kfree(udc); return 0; } diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index c2011cd7df8c..564aeee1a1fe 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c @@ -573,8 +573,7 @@ net2272_read_fifo(struct net2272_ep *ep, struct net2272_request *req) /* completion */ if (unlikely(cleanup || is_short || - ((req->req.actual == req->req.length) - && !req->req.zero))) { + req->req.actual == req->req.length)) { if (cleanup) { net2272_out_flush(ep); diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index 898339e5df10..b6bbe2e448ba 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -789,8 +789,7 @@ static int read_fifo(struct net2280_ep *ep, struct net2280_request *req) (void) readl(&ep->regs->ep_rsp); } - return is_short || ((req->req.actual == req->req.length) && - !req->req.zero); + return is_short || req->req.actual == req->req.length; } /* fill out dma descriptor to match a given request */ @@ -1058,7 +1057,7 @@ net2280_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) /* PIO ... stuff the fifo, or unblock it. */ if (ep->is_in) write_fifo(ep, _req); - else if (list_empty(&ep->queue)) { + else { u32 s; /* OUT FIFO might have packet(s) buffered */ |