diff options
Diffstat (limited to 'drivers/usb/gadget/udc')
23 files changed, 270 insertions, 533 deletions
diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c index c862656d18b8..c0ec5f71f16f 100644 --- a/drivers/usb/gadget/udc/at91_udc.c +++ b/drivers/usb/gadget/udc/at91_udc.c @@ -176,7 +176,7 @@ static int proc_udc_show(struct seq_file *s, void *unused) udc->enabled ? (udc->vbus ? "active" : "enabled") : "disabled", - udc->selfpowered ? "self" : "VBUS", + udc->gadget.is_selfpowered ? "self" : "VBUS", udc->suspended ? ", suspended" : "", udc->driver ? udc->driver->driver.name : "(none)"); @@ -1000,7 +1000,7 @@ static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on) unsigned long flags; spin_lock_irqsave(&udc->lock, flags); - udc->selfpowered = (is_on != 0); + gadget->is_selfpowered = (is_on != 0); spin_unlock_irqrestore(&udc->lock, flags); return 0; } @@ -1149,7 +1149,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) */ case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) | USB_REQ_GET_STATUS: - tmp = (udc->selfpowered << USB_DEVICE_SELF_POWERED); + tmp = (udc->gadget.is_selfpowered << USB_DEVICE_SELF_POWERED); if (at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_ESR) tmp |= (1 << USB_DEVICE_REMOTE_WAKEUP); PACKET("get device status\n"); @@ -1653,7 +1653,7 @@ static int at91_start(struct usb_gadget *gadget, udc->driver = driver; udc->gadget.dev.of_node = udc->pdev->dev.of_node; udc->enabled = 1; - udc->selfpowered = 1; + udc->gadget.is_selfpowered = 1; return 0; } diff --git a/drivers/usb/gadget/udc/at91_udc.h b/drivers/usb/gadget/udc/at91_udc.h index 017524663381..467dcfb74a51 100644 --- a/drivers/usb/gadget/udc/at91_udc.h +++ b/drivers/usb/gadget/udc/at91_udc.h @@ -122,7 +122,6 @@ struct at91_udc { unsigned req_pending:1; unsigned wait_for_addr_ack:1; unsigned wait_for_config_ack:1; - unsigned selfpowered:1; unsigned active_suspend:1; u8 addr; struct at91_udc_data board; diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 9f93bed42052..c0410862c2a1 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -8,6 +8,7 @@ * published by the Free Software Foundation. */ #include <linux/clk.h> +#include <linux/clk/at91_pmc.h> #include <linux/module.h> #include <linux/init.h> #include <linux/interrupt.h> @@ -315,6 +316,17 @@ static inline void usba_cleanup_debugfs(struct usba_udc *udc) } #endif +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) +{ + usba_writel(udc, INT_ENB, val); + udc->int_enb_cache = val; +} + static int vbus_is_present(struct usba_udc *udc) { if (gpio_is_valid(udc->vbus_pin)) @@ -324,27 +336,22 @@ static int vbus_is_present(struct usba_udc *udc) return 1; } -#if defined(CONFIG_ARCH_AT91SAM9RL) - -#include <linux/clk/at91_pmc.h> - -static void toggle_bias(int is_on) +static void toggle_bias(struct usba_udc *udc, int is_on) { - unsigned int uckr = at91_pmc_read(AT91_CKGR_UCKR); - - if (is_on) - at91_pmc_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN); - else - at91_pmc_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN)); + if (udc->errata && udc->errata->toggle_bias) + udc->errata->toggle_bias(udc, is_on); } -#else - -static void toggle_bias(int is_on) +static void generate_bias_pulse(struct usba_udc *udc) { -} + if (!udc->bias_pulse_needed) + return; + + if (udc->errata && udc->errata->pulse_bias) + udc->errata->pulse_bias(udc); -#endif /* CONFIG_ARCH_AT91SAM9RL */ + udc->bias_pulse_needed = false; +} static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req) { @@ -601,16 +608,14 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) if (ep->can_dma) { u32 ctrl; - usba_writel(udc, INT_ENB, - (usba_readl(udc, INT_ENB) - | USBA_BF(EPT_INT, 1 << ep->index) - | USBA_BF(DMA_INT, 1 << ep->index))); + usba_int_enb_set(udc, usba_int_enb_get(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_writel(udc, INT_ENB, - (usba_readl(udc, INT_ENB) - | USBA_BF(EPT_INT, 1 << ep->index))); + usba_int_enb_set(udc, usba_int_enb_get(udc) | + USBA_BF(EPT_INT, 1 << ep->index)); } spin_unlock_irqrestore(&udc->lock, flags); @@ -618,7 +623,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) DBG(DBG_HW, "EPT_CFG%d after init: %#08lx\n", ep->index, (unsigned long)usba_ep_readl(ep, CFG)); DBG(DBG_HW, "INT_ENB after init: %#08lx\n", - (unsigned long)usba_readl(udc, INT_ENB)); + (unsigned long)usba_int_enb_get(udc)); return 0; } @@ -654,9 +659,8 @@ static int usba_ep_disable(struct usb_ep *_ep) usba_dma_readl(ep, STATUS); } usba_ep_writel(ep, CTL_DIS, USBA_EPT_ENABLE); - usba_writel(udc, INT_ENB, - usba_readl(udc, INT_ENB) - & ~USBA_BF(EPT_INT, 1 << ep->index)); + usba_int_enb_set(udc, usba_int_enb_get(udc) & + ~USBA_BF(EPT_INT, 1 << ep->index)); request_complete_list(ep, &req_list, -ESHUTDOWN); @@ -985,6 +989,7 @@ usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered) struct usba_udc *udc = to_usba_udc(gadget); unsigned long flags; + gadget->is_selfpowered = (is_selfpowered != 0); spin_lock_irqsave(&udc->lock, flags); if (is_selfpowered) udc->devstatus |= 1 << USB_DEVICE_SELF_POWERED; @@ -1619,18 +1624,21 @@ static void usba_dma_irq(struct usba_udc *udc, struct usba_ep *ep) static irqreturn_t usba_udc_irq(int irq, void *devid) { struct usba_udc *udc = devid; - u32 status; + u32 status, int_enb; u32 dma_status; u32 ep_status; spin_lock(&udc->lock); - status = usba_readl(udc, INT_STA); + int_enb = usba_int_enb_get(udc); + status = usba_readl(udc, INT_STA) & int_enb; DBG(DBG_INT, "irq, status=%#08x\n", status); if (status & USBA_DET_SUSPEND) { - toggle_bias(0); + 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; DBG(DBG_BUS, "Suspend detected\n"); if (udc->gadget.speed != USB_SPEED_UNKNOWN && udc->driver && udc->driver->suspend) { @@ -1641,13 +1649,15 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) } if (status & USBA_WAKE_UP) { - toggle_bias(1); + 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) { usba_writel(udc, INT_CLR, USBA_END_OF_RESUME); + generate_bias_pulse(udc); DBG(DBG_BUS, "Resume detected\n"); if (udc->gadget.speed != USB_SPEED_UNKNOWN && udc->driver && udc->driver->resume) { @@ -1683,6 +1693,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) struct usba_ep *ep0; usba_writel(udc, INT_CLR, USBA_END_OF_RESET); + generate_bias_pulse(udc); reset_all_endpoints(udc); if (udc->gadget.speed != USB_SPEED_UNKNOWN && udc->driver) { @@ -1708,11 +1719,8 @@ 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_writel(udc, INT_ENB, - (usba_readl(udc, INT_ENB) - | USBA_BF(EPT_INT, 1) - | USBA_DET_SUSPEND - | USBA_END_OF_RESUME)); + usba_int_enb_set(udc, int_enb | USBA_BF(EPT_INT, 1) | + USBA_DET_SUSPEND | USBA_END_OF_RESUME); /* * Unclear why we hit this irregularly, e.g. in usbtest, @@ -1745,13 +1753,13 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid) vbus = vbus_is_present(udc); if (vbus != udc->vbus_prev) { if (vbus) { - toggle_bias(1); + toggle_bias(udc, 1); usba_writel(udc, CTRL, USBA_ENABLE_MASK); - usba_writel(udc, INT_ENB, USBA_END_OF_RESET); + usba_int_enb_set(udc, USBA_END_OF_RESET); } else { udc->gadget.speed = USB_SPEED_UNKNOWN; reset_all_endpoints(udc); - toggle_bias(0); + toggle_bias(udc, 0); usba_writel(udc, CTRL, USBA_DISABLE_MASK); if (udc->driver->disconnect) { spin_unlock(&udc->lock); @@ -1797,9 +1805,9 @@ static int atmel_usba_start(struct usb_gadget *gadget, /* If Vbus is present, enable the controller and wait for reset */ spin_lock_irqsave(&udc->lock, flags); if (vbus_is_present(udc) && udc->vbus_prev == 0) { - toggle_bias(1); + toggle_bias(udc, 1); usba_writel(udc, CTRL, USBA_ENABLE_MASK); - usba_writel(udc, INT_ENB, USBA_END_OF_RESET); + usba_int_enb_set(udc, USBA_END_OF_RESET); } spin_unlock_irqrestore(&udc->lock, flags); @@ -1820,7 +1828,7 @@ static int atmel_usba_stop(struct usb_gadget *gadget) spin_unlock_irqrestore(&udc->lock, flags); /* This will also disable the DP pullup */ - toggle_bias(0); + toggle_bias(udc, 0); usba_writel(udc, CTRL, USBA_DISABLE_MASK); clk_disable_unprepare(udc->hclk); @@ -1832,6 +1840,41 @@ static int atmel_usba_stop(struct usb_gadget *gadget) } #ifdef CONFIG_OF +static void at91sam9rl_toggle_bias(struct usba_udc *udc, int is_on) +{ + unsigned int uckr = at91_pmc_read(AT91_CKGR_UCKR); + + if (is_on) + at91_pmc_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN); + else + at91_pmc_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN)); +} + +static void at91sam9g45_pulse_bias(struct usba_udc *udc) +{ + unsigned int uckr = at91_pmc_read(AT91_CKGR_UCKR); + + at91_pmc_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN)); + at91_pmc_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN); +} + +static const struct usba_udc_errata at91sam9rl_errata = { + .toggle_bias = at91sam9rl_toggle_bias, +}; + +static const struct usba_udc_errata at91sam9g45_errata = { + .pulse_bias = at91sam9g45_pulse_bias, +}; + +static const struct of_device_id atmel_udc_dt_ids[] = { + { .compatible = "atmel,at91sam9rl-udc", .data = &at91sam9rl_errata }, + { .compatible = "atmel,at91sam9g45-udc", .data = &at91sam9g45_errata }, + { .compatible = "atmel,sama5d3-udc" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, atmel_udc_dt_ids); + static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, struct usba_udc *udc) { @@ -1839,10 +1882,17 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, const char *name; enum of_gpio_flags flags; struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; struct device_node *pp; int i, ret; struct usba_ep *eps, *ep; + match = of_match_node(atmel_udc_dt_ids, np); + if (!match) + return ERR_PTR(-EINVAL); + + udc->errata = match->data; + udc->num_ep = 0; udc->vbus_pin = of_get_named_gpio_flags(np, "atmel,vbus-gpio", 0, @@ -2033,7 +2083,7 @@ static int usba_udc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Unable to enable pclk, aborting.\n"); return ret; } - toggle_bias(0); + usba_writel(udc, CTRL, USBA_DISABLE_MASK); clk_disable_unprepare(pclk); @@ -2042,6 +2092,8 @@ static int usba_udc_probe(struct platform_device *pdev) else udc->usba_ep = usba_udc_pdata(pdev, udc); + toggle_bias(udc, 0); + if (IS_ERR(udc->usba_ep)) return PTR_ERR(udc->usba_ep); @@ -2101,15 +2153,6 @@ static int __exit usba_udc_remove(struct platform_device *pdev) return 0; } -#if defined(CONFIG_OF) -static const struct of_device_id atmel_udc_dt_ids[] = { - { .compatible = "atmel,at91sam9rl-udc" }, - { /* sentinel */ } -}; - -MODULE_DEVICE_TABLE(of, atmel_udc_dt_ids); -#endif - static struct platform_driver udc_driver = { .remove = __exit_p(usba_udc_remove), .driver = { diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.h b/drivers/usb/gadget/udc/atmel_usba_udc.h index a70706e8cb02..497cd18836f3 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.h +++ b/drivers/usb/gadget/udc/atmel_usba_udc.h @@ -304,6 +304,11 @@ struct usba_request { unsigned int mapped:1; }; +struct usba_udc_errata { + void (*toggle_bias)(struct usba_udc *udc, int is_on); + void (*pulse_bias)(struct usba_udc *udc); +}; + struct usba_udc { /* Protect hw registers from concurrent modifications */ spinlock_t lock; @@ -314,6 +319,7 @@ struct usba_udc { struct usb_gadget gadget; struct usb_gadget_driver *driver; struct platform_device *pdev; + const struct usba_udc_errata *errata; int irq; int vbus_pin; int vbus_pin_inverted; @@ -321,12 +327,15 @@ struct usba_udc { struct clk *pclk; struct clk *hclk; struct usba_ep *usba_ep; + bool bias_pulse_needed; u16 devstatus; u16 test_mode; int vbus_prev; + u32 int_enb_cache; + #ifdef CONFIG_USB_GADGET_DEBUG_FS struct dentry *debugfs_root; struct dentry *debugfs_regs; diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c index c6dfef8c7bbc..5c8f4effb62a 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_core.c +++ b/drivers/usb/gadget/udc/bdc/bdc_core.c @@ -521,7 +521,6 @@ static int bdc_remove(struct platform_device *pdev) static struct platform_driver bdc_driver = { .driver = { .name = BRCM_BDC_NAME, - .owner = THIS_MODULE }, .probe = bdc_probe, .remove = bdc_remove, diff --git a/drivers/usb/gadget/udc/bdc/bdc_ep.c b/drivers/usb/gadget/udc/bdc/bdc_ep.c index d4fe8d769bd6..b04980cf6dc4 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_ep.c +++ b/drivers/usb/gadget/udc/bdc/bdc_ep.c @@ -718,7 +718,7 @@ static int ep_queue(struct bdc_ep *ep, struct bdc_req *req) struct bdc *bdc; int ret = 0; - if (!req || !ep || !ep->usb_ep.desc) + if (!req || !ep->usb_ep.desc) return -EINVAL; bdc = ep->bdc; @@ -882,8 +882,8 @@ static int ep_set_halt(struct bdc_ep *ep, u32 value) ret = bdc_ep_set_stall(bdc, ep->ep_num); if (ret) - dev_err(bdc->dev, "failed to %s STALL on %s\n", - value ? "set" : "clear", ep->name); + dev_err(bdc->dev, "failed to set STALL on %s\n", + ep->name); else ep->flags |= BDC_EP_STALL; } else { @@ -891,8 +891,8 @@ static int ep_set_halt(struct bdc_ep *ep, u32 value) dev_dbg(bdc->dev, "Before Clear\n"); ret = bdc_ep_clear_stall(bdc, ep->ep_num); if (ret) - dev_err(bdc->dev, "failed to %s STALL on %s\n", - value ? "set" : "clear", ep->name); + dev_err(bdc->dev, "failed to clear STALL on %s\n", + ep->name); else ep->flags &= ~BDC_EP_STALL; dev_dbg(bdc->dev, "After Clear\n"); diff --git a/drivers/usb/gadget/udc/bdc/bdc_udc.c b/drivers/usb/gadget/udc/bdc/bdc_udc.c index 3700ce70b0be..7f77db5d1278 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_udc.c +++ b/drivers/usb/gadget/udc/bdc/bdc_udc.c @@ -454,6 +454,7 @@ static int bdc_udc_set_selfpowered(struct usb_gadget *gadget, unsigned long flags; dev_dbg(bdc->dev, "%s()\n", __func__); + gadget->is_selfpowered = (is_self != 0); spin_lock_irqsave(&bdc->lock, flags); if (!is_self) bdc->devstatus |= 1 << USB_DEVICE_SELF_POWERED; diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index 9c598801404c..8dda48445f6f 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -802,6 +802,7 @@ static int dummy_set_selfpowered(struct usb_gadget *_gadget, int value) { struct dummy *dum; + _gadget->is_selfpowered = (value != 0); dum = gadget_to_dummy_hcd(_gadget)->dum; if (value) dum->devstatus |= (1 << USB_DEVICE_SELF_POWERED); @@ -1924,7 +1925,9 @@ ss_hub_descriptor(struct usb_hub_descriptor *desc) memset(desc, 0, sizeof *desc); desc->bDescriptorType = 0x2a; desc->bDescLength = 12; - desc->wHubCharacteristics = cpu_to_le16(0x0001); + desc->wHubCharacteristics = cpu_to_le16( + HUB_CHAR_INDV_PORT_LPSM | + HUB_CHAR_COMMON_OCPM); desc->bNbrPorts = 1; desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/ desc->u.ss.DeviceRemovable = 0xffff; @@ -1935,7 +1938,9 @@ static inline void hub_descriptor(struct usb_hub_descriptor *desc) memset(desc, 0, sizeof *desc); desc->bDescriptorType = 0x29; desc->bDescLength = 9; - desc->wHubCharacteristics = cpu_to_le16(0x0001); + desc->wHubCharacteristics = cpu_to_le16( + HUB_CHAR_INDV_PORT_LPSM | + HUB_CHAR_COMMON_OCPM); desc->bNbrPorts = 1; desc->u.hs.DeviceRemovable[0] = 0xff; desc->u.hs.DeviceRemovable[1] = 0xff; diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c index 795c99c77697..e0822f1b6639 100644 --- a/drivers/usb/gadget/udc/fsl_qe_udc.c +++ b/drivers/usb/gadget/udc/fsl_qe_udc.c @@ -2630,7 +2630,7 @@ static int qe_udc_remove(struct platform_device *ofdev) struct qe_udc *udc = platform_get_drvdata(ofdev); struct qe_ep *ep; unsigned int size; - DECLARE_COMPLETION(done); + DECLARE_COMPLETION_ONSTACK(done); usb_del_gadget_udc(&udc->gadget); diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index 2df807403f22..55fcb930f92e 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -1337,7 +1337,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) { /* Get device status */ - tmp = 1 << USB_DEVICE_SELF_POWERED; + tmp = udc->gadget.is_selfpowered; tmp |= udc->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP; } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) { /* Get interface status */ @@ -1948,6 +1948,7 @@ static int fsl_udc_start(struct usb_gadget *g, /* hook up the driver */ udc_controller->driver = driver; spin_unlock_irqrestore(&udc_controller->lock, flags); + g->is_selfpowered = 1; if (!IS_ERR_OR_NULL(udc_controller->transceiver)) { /* Suspend the controller until OTG enable it */ @@ -2529,7 +2530,7 @@ static int __exit fsl_udc_remove(struct platform_device *pdev) struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev); - DECLARE_COMPLETION(done); + DECLARE_COMPLETION_ONSTACK(done); if (!udc_controller) return -ENODEV; diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c index 34d9b7b831b3..27fd41333f71 100644 --- a/drivers/usb/gadget/udc/lpc32xx_udc.c +++ b/drivers/usb/gadget/udc/lpc32xx_udc.c @@ -191,7 +191,6 @@ struct lpc32xx_udc { bool enabled; bool clocked; bool suspended; - bool selfpowered; int ep0state; atomic_t enabled_ep_cnt; wait_queue_head_t ep_disable_wait_queue; @@ -547,7 +546,7 @@ static int proc_udc_show(struct seq_file *s, void *unused) udc->vbus ? "present" : "off", udc->enabled ? (udc->vbus ? "active" : "enabled") : "disabled", - udc->selfpowered ? "self" : "VBUS", + udc->gadget.is_selfpowered ? "self" : "VBUS", udc->suspended ? ", suspended" : "", udc->driver ? udc->driver->driver.name : "(none)"); @@ -2212,7 +2211,7 @@ static int udc_get_status(struct lpc32xx_udc *udc, u16 reqtype, u16 wIndex) break; /* Not supported */ case USB_RECIP_DEVICE: - ep0buff = (udc->selfpowered << USB_DEVICE_SELF_POWERED); + ep0buff = udc->gadget.is_selfpowered; if (udc->dev_status & (1 << USB_DEVICE_REMOTE_WAKEUP)) ep0buff |= (1 << USB_DEVICE_REMOTE_WAKEUP); break; @@ -2498,10 +2497,7 @@ static int lpc32xx_wakeup(struct usb_gadget *gadget) 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); + gadget->is_selfpowered = (is_on != 0); return 0; } @@ -2946,7 +2942,7 @@ static int lpc32xx_start(struct usb_gadget *gadget, udc->driver = driver; udc->gadget.dev.of_node = udc->dev->of_node; udc->enabled = 1; - udc->selfpowered = 1; + udc->gadget.is_selfpowered = 1; udc->vbus = 0; /* Force VBUS process once to check for cable insertion */ diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c index 253f3df8326a..d32160d6463f 100644 --- a/drivers/usb/gadget/udc/mv_udc_core.c +++ b/drivers/usb/gadget/udc/mv_udc_core.c @@ -1378,9 +1378,6 @@ static int mv_udc_start(struct usb_gadget *gadget, } } - /* pullup is always on */ - mv_udc_pullup(&udc->gadget, 1); - /* When boot with cable attached, there will be no vbus irq occurred */ if (udc->qwork) queue_work(udc->qwork, &udc->vbus_work); diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index d20de1fab08e..195baf3e1fcd 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c @@ -1132,13 +1132,10 @@ net2272_wakeup(struct usb_gadget *_gadget) static int net2272_set_selfpowered(struct usb_gadget *_gadget, int value) { - struct net2272 *dev; - if (!_gadget) return -ENODEV; - dev = container_of(_gadget, struct net2272, gadget); - dev->is_selfpowered = value; + _gadget->is_selfpowered = (value != 0); return 0; } @@ -1844,7 +1841,7 @@ net2272_handle_stat0_irqs(struct net2272 *dev, u8 stat) case USB_RECIP_DEVICE: if (u.r.wLength > 2) goto do_stall; - if (dev->is_selfpowered) + if (dev->gadget.is_selfpowered) status = (1 << USB_DEVICE_SELF_POWERED); /* don't bother with a request object! */ diff --git a/drivers/usb/gadget/udc/net2272.h b/drivers/usb/gadget/udc/net2272.h index e59505789359..127ab03fcde3 100644 --- a/drivers/usb/gadget/udc/net2272.h +++ b/drivers/usb/gadget/udc/net2272.h @@ -458,7 +458,6 @@ struct net2272 { struct usb_gadget_driver *driver; unsigned protocol_stall:1, softconnect:1, - is_selfpowered:1, wakeup:1, dma_eot_polarity:1, dma_dack_polarity:1, diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index d6411e0a8e03..d2c0bf65e345 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -12,11 +12,7 @@ * the Mass Storage, Serial, and Ethernet/RNDIS gadget drivers * as well as Gadget Zero and Gadgetfs. * - * DMA is enabled by default. Drivers using transfer queues might use - * DMA chaining to remove IRQ latencies between transfers. (Except when - * short OUT transfers happen.) Drivers can use the req->no_interrupt - * hint to completely eliminate some IRQs, if a later IRQ is guaranteed - * and DMA chaining is enabled. + * DMA is enabled by default. * * MSI is enabled by default. The legacy IRQ is used if MSI couldn't * be enabled. @@ -84,23 +80,6 @@ static const char *const ep_name[] = { "ep-e", "ep-f", "ep-g", "ep-h", }; -/* use_dma -- general goodness, fewer interrupts, less cpu load (vs PIO) - * use_dma_chaining -- dma descriptor queueing gives even more irq reduction - * - * The net2280 DMA engines are not tightly integrated with their FIFOs; - * not all cases are (yet) handled well in this driver or the silicon. - * Some gadget drivers work better with the dma support here than others. - * These two parameters let you use PIO or more aggressive DMA. - */ -static bool use_dma = true; -static bool use_dma_chaining; -static bool use_msi = true; - -/* "modprobe net2280 use_dma=n" etc */ -module_param(use_dma, bool, 0444); -module_param(use_dma_chaining, bool, 0444); -module_param(use_msi, bool, 0444); - /* mode 0 == ep-{a,b,c,d} 1K fifo each * mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable * mode 2 == ep-a 2K fifo, ep-{b,c} 1K each, ep-d unavailable @@ -120,11 +99,6 @@ static bool enable_suspend; /* "modprobe net2280 enable_suspend=1" etc */ module_param(enable_suspend, bool, 0444); -/* force full-speed operation */ -static bool full_speed; -module_param(full_speed, bool, 0444); -MODULE_PARM_DESC(full_speed, "force full-speed mode -- for testing only!"); - #define DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out") static char *type_string(u8 bmAttributes) @@ -202,15 +176,6 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) /* set speed-dependent max packet; may kick in high bandwidth */ set_max_speed(ep, max); - /* FIFO lines can't go to different packets. PIO is ok, so - * use it instead of troublesome (non-bulk) multi-packet DMA. - */ - if (ep->dma && (max % 4) != 0 && use_dma_chaining) { - ep_dbg(ep->dev, "%s, no dma for maxpacket %d\n", - ep->ep.name, ep->ep.maxpacket); - ep->dma = NULL; - } - /* set type, direction, address; reset fifo counters */ writel(BIT(FIFO_FLUSH), &ep->regs->ep_stat); tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); @@ -478,7 +443,7 @@ static int net2280_disable(struct usb_ep *_ep) /* synch memory views with the device */ (void)readl(&ep->cfg->ep_cfg); - if (use_dma && !ep->dma && ep->num >= 1 && ep->num <= 4) + if (!ep->dma && ep->num >= 1 && ep->num <= 4) ep->dma = &ep->dev->dma[ep->num - 1]; spin_unlock_irqrestore(&ep->dev->lock, flags); @@ -610,9 +575,15 @@ static void out_flush(struct net2280_ep *ep) u32 __iomem *statp; u32 tmp; - ASSERT_OUT_NAKING(ep); - statp = &ep->regs->ep_stat; + + tmp = readl(statp); + if (tmp & BIT(NAK_OUT_PACKETS)) { + ep_dbg(ep->dev, "%s %s %08x !NAK\n", + ep->ep.name, __func__, tmp); + writel(BIT(SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp); + } + writel(BIT(DATA_OUT_PING_TOKEN_INTERRUPT) | BIT(DATA_PACKET_RECEIVED_INTERRUPT), statp); @@ -747,8 +718,7 @@ static void fill_dma_desc(struct net2280_ep *ep, req->valid = valid; if (valid) dmacount |= BIT(VALID_BIT); - if (likely(!req->req.no_interrupt || !use_dma_chaining)) - dmacount |= BIT(DMA_DONE_INTERRUPT_ENABLE); + dmacount |= BIT(DMA_DONE_INTERRUPT_ENABLE); /* td->dmadesc = previously set by caller */ td->dmaaddr = cpu_to_le32 (req->req.dma); @@ -862,27 +832,11 @@ static void start_dma(struct net2280_ep *ep, struct net2280_request *req) req->td->dmadesc = cpu_to_le32 (ep->td_dma); fill_dma_desc(ep, req, 1); - if (!use_dma_chaining) - req->td->dmacount |= cpu_to_le32(BIT(END_OF_CHAIN)); + req->td->dmacount |= cpu_to_le32(BIT(END_OF_CHAIN)); start_queue(ep, tmp, req->td_dma); } -static inline void resume_dma(struct net2280_ep *ep) -{ - writel(readl(&ep->dma->dmactl) | BIT(DMA_ENABLE), &ep->dma->dmactl); - - ep->dma_started = true; -} - -static inline void ep_stop_dma(struct net2280_ep *ep) -{ - writel(readl(&ep->dma->dmactl) & ~BIT(DMA_ENABLE), &ep->dma->dmactl); - spin_stop_dma(ep->dma); - - ep->dma_started = false; -} - static inline void queue_dma(struct net2280_ep *ep, struct net2280_request *req, int valid) { @@ -973,10 +927,8 @@ net2280_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) return ret; } -#if 0 ep_vdbg(dev, "%s queue req %p, len %d buf %p\n", _ep->name, _req, _req->length, _req->buf); -#endif spin_lock_irqsave(&dev->lock, flags); @@ -984,24 +936,12 @@ net2280_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) _req->actual = 0; /* kickstart this i/o queue? */ - if (list_empty(&ep->queue) && !ep->stopped) { - /* DMA request while EP halted */ - if (ep->dma && - (readl(&ep->regs->ep_rsp) & BIT(CLEAR_ENDPOINT_HALT)) && - (dev->quirks & PLX_SUPERSPEED)) { - int valid = 1; - if (ep->is_in) { - int expect; - expect = likely(req->req.zero || - ((req->req.length % - ep->ep.maxpacket) != 0)); - if (expect != ep->in_fifo_validate) - valid = 0; - } - queue_dma(ep, req, valid); - } + if (list_empty(&ep->queue) && !ep->stopped && + !((dev->quirks & PLX_SUPERSPEED) && ep->dma && + (readl(&ep->regs->ep_rsp) & BIT(CLEAR_ENDPOINT_HALT)))) { + /* use DMA if the endpoint supports it, else pio */ - else if (ep->dma) + if (ep->dma) start_dma(ep, req); else { /* maybe there's no control data, just status ack */ @@ -1084,8 +1024,6 @@ dma_done(struct net2280_ep *ep, struct net2280_request *req, u32 dmacount, done(ep, req, status); } -static void restart_dma(struct net2280_ep *ep); - static void scan_dma_completions(struct net2280_ep *ep) { /* only look at descriptors that were "naturally" retired, @@ -1117,9 +1055,8 @@ static void scan_dma_completions(struct net2280_ep *ep) dma_done(ep, req, tmp, 0); break; } else if (!ep->is_in && - (req->req.length % ep->ep.maxpacket) != 0) { - if (ep->dev->quirks & PLX_SUPERSPEED) - return dma_done(ep, req, tmp, 0); + (req->req.length % ep->ep.maxpacket) && + !(ep->dev->quirks & PLX_SUPERSPEED)) { tmp = readl(&ep->regs->ep_stat); /* AVOID TROUBLE HERE by not issuing short reads from @@ -1150,67 +1087,15 @@ static void scan_dma_completions(struct net2280_ep *ep) static void restart_dma(struct net2280_ep *ep) { struct net2280_request *req; - u32 dmactl = dmactl_default; if (ep->stopped) return; req = list_entry(ep->queue.next, struct net2280_request, queue); - if (!use_dma_chaining) { - start_dma(ep, req); - return; - } - - /* the 2280 will be processing the queue unless queue hiccups after - * the previous transfer: - * IN: wanted automagic zlp, head doesn't (or vice versa) - * DMA_FIFO_VALIDATE doesn't init from dma descriptors. - * OUT: was "usb-short", we must restart. - */ - if (ep->is_in && !req->valid) { - struct net2280_request *entry, *prev = NULL; - int reqmode, done = 0; - - ep_dbg(ep->dev, "%s dma hiccup td %p\n", ep->ep.name, req->td); - ep->in_fifo_validate = likely(req->req.zero || - (req->req.length % ep->ep.maxpacket) != 0); - if (ep->in_fifo_validate) - dmactl |= BIT(DMA_FIFO_VALIDATE); - list_for_each_entry(entry, &ep->queue, queue) { - __le32 dmacount; - - if (entry == req) - continue; - dmacount = entry->td->dmacount; - if (!done) { - reqmode = likely(entry->req.zero || - (entry->req.length % ep->ep.maxpacket)); - if (reqmode == ep->in_fifo_validate) { - entry->valid = 1; - dmacount |= valid_bit; - entry->td->dmacount = dmacount; - prev = entry; - continue; - } else { - /* force a hiccup */ - prev->td->dmacount |= dma_done_ie; - done = 1; - } - } - - /* walk the rest of the queue so unlinks behave */ - entry->valid = 0; - dmacount &= ~valid_bit; - entry->td->dmacount = dmacount; - prev = entry; - } - } - - writel(0, &ep->dma->dmactl); - start_queue(ep, dmactl, req->td_dma); + start_dma(ep, req); } -static void abort_dma_228x(struct net2280_ep *ep) +static void abort_dma(struct net2280_ep *ep) { /* abort the current transfer */ if (likely(!list_empty(&ep->queue))) { @@ -1222,19 +1107,6 @@ static void abort_dma_228x(struct net2280_ep *ep) scan_dma_completions(ep); } -static void abort_dma_338x(struct net2280_ep *ep) -{ - writel(BIT(DMA_ABORT), &ep->dma->dmastat); - spin_stop_dma(ep->dma); -} - -static void abort_dma(struct net2280_ep *ep) -{ - if (ep->dev->quirks & PLX_LEGACY) - return abort_dma_228x(ep); - return abort_dma_338x(ep); -} - /* dequeue ALL requests */ static void nuke(struct net2280_ep *ep) { @@ -1306,25 +1178,6 @@ static int net2280_dequeue(struct usb_ep *_ep, struct usb_request *_req) done(ep, req, -ECONNRESET); } req = NULL; - - /* patch up hardware chaining data */ - } else if (ep->dma && use_dma_chaining) { - if (req->queue.prev == ep->queue.next) { - writel(le32_to_cpu(req->td->dmadesc), - &ep->dma->dmadesc); - if (req->td->dmacount & dma_done_ie) - writel(readl(&ep->dma->dmacount) | - le32_to_cpu(dma_done_ie), - &ep->dma->dmacount); - } else { - struct net2280_request *prev; - - prev = list_entry(req->queue.prev, - struct net2280_request, queue); - prev->td->dmadesc = req->td->dmadesc; - if (req->td->dmacount & dma_done_ie) - prev->td->dmacount |= dma_done_ie; - } } if (req) @@ -1512,10 +1365,10 @@ static int net2280_set_selfpowered(struct usb_gadget *_gadget, int value) tmp = readl(&dev->usb->usbctl); if (value) { tmp |= BIT(SELF_POWERED_STATUS); - dev->selfpowered = 1; + _gadget->is_selfpowered = 1; } else { tmp &= ~BIT(SELF_POWERED_STATUS); - dev->selfpowered = 0; + _gadget->is_selfpowered = 0; } writel(tmp, &dev->usb->usbctl); spin_unlock_irqrestore(&dev->lock, flags); @@ -1604,14 +1457,11 @@ static ssize_t registers_show(struct device *_dev, /* Main Control Registers */ t = scnprintf(next, size, "%s version " DRIVER_VERSION - ", chiprev %04x, dma %s\n\n" + ", chiprev %04x\n\n" "devinit %03x fifoctl %08x gadget '%s'\n" "pci irqenb0 %02x irqenb1 %08x " "irqstat0 %04x irqstat1 %08x\n", driver_name, dev->chiprev, - use_dma - ? (use_dma_chaining ? "chaining" : "enabled") - : "disabled", readl(&dev->regs->devinit), readl(&dev->regs->fifoctl), s, @@ -1913,76 +1763,73 @@ static void defect7374_disable_data_eps(struct net2280 *dev) static void defect7374_enable_data_eps_zero(struct net2280 *dev) { u32 tmp = 0, tmp_reg; - u32 fsmvalue, scratch; + u32 scratch; int i; unsigned char ep_sel; scratch = get_idx_reg(dev->regs, SCRATCH); - fsmvalue = scratch & (0xf << DEFECT7374_FSM_FIELD); + + WARN_ON((scratch & (0xf << DEFECT7374_FSM_FIELD)) + == DEFECT7374_FSM_SS_CONTROL_READ); + scratch &= ~(0xf << DEFECT7374_FSM_FIELD); - /*See if firmware needs to set up for workaround*/ - if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ) { - ep_warn(dev, "Operate Defect 7374 workaround soft this time"); - ep_warn(dev, "It will operate on cold-reboot and SS connect"); - - /*GPEPs:*/ - tmp = ((0 << ENDPOINT_NUMBER) | BIT(ENDPOINT_DIRECTION) | - (2 << OUT_ENDPOINT_TYPE) | (2 << IN_ENDPOINT_TYPE) | - ((dev->enhanced_mode) ? - BIT(OUT_ENDPOINT_ENABLE) : BIT(ENDPOINT_ENABLE)) | - BIT(IN_ENDPOINT_ENABLE)); - - for (i = 1; i < 5; i++) - writel(tmp, &dev->ep[i].cfg->ep_cfg); - - /* CSRIN, PCIIN, STATIN, RCIN*/ - tmp = ((0 << ENDPOINT_NUMBER) | BIT(ENDPOINT_ENABLE)); - writel(tmp, &dev->dep[1].dep_cfg); - writel(tmp, &dev->dep[3].dep_cfg); - writel(tmp, &dev->dep[4].dep_cfg); - writel(tmp, &dev->dep[5].dep_cfg); - - /*Implemented for development and debug. - * Can be refined/tuned later.*/ - for (ep_sel = 0; ep_sel <= 21; ep_sel++) { - /* Select an endpoint for subsequent operations: */ - tmp_reg = readl(&dev->plregs->pl_ep_ctrl); - writel(((tmp_reg & ~0x1f) | ep_sel), - &dev->plregs->pl_ep_ctrl); - - if (ep_sel == 1) { - tmp = - (readl(&dev->plregs->pl_ep_ctrl) | - BIT(CLEAR_ACK_ERROR_CODE) | 0); - writel(tmp, &dev->plregs->pl_ep_ctrl); - continue; - } + ep_warn(dev, "Operate Defect 7374 workaround soft this time"); + ep_warn(dev, "It will operate on cold-reboot and SS connect"); - if (ep_sel == 0 || (ep_sel > 9 && ep_sel < 14) || - ep_sel == 18 || ep_sel == 20) - continue; + /*GPEPs:*/ + tmp = ((0 << ENDPOINT_NUMBER) | BIT(ENDPOINT_DIRECTION) | + (2 << OUT_ENDPOINT_TYPE) | (2 << IN_ENDPOINT_TYPE) | + ((dev->enhanced_mode) ? + BIT(OUT_ENDPOINT_ENABLE) : BIT(ENDPOINT_ENABLE)) | + BIT(IN_ENDPOINT_ENABLE)); - tmp = (readl(&dev->plregs->pl_ep_cfg_4) | - BIT(NON_CTRL_IN_TOLERATE_BAD_DIR) | 0); - writel(tmp, &dev->plregs->pl_ep_cfg_4); + for (i = 1; i < 5; i++) + writel(tmp, &dev->ep[i].cfg->ep_cfg); - tmp = readl(&dev->plregs->pl_ep_ctrl) & - ~BIT(EP_INITIALIZED); - writel(tmp, &dev->plregs->pl_ep_ctrl); + /* CSRIN, PCIIN, STATIN, RCIN*/ + tmp = ((0 << ENDPOINT_NUMBER) | BIT(ENDPOINT_ENABLE)); + writel(tmp, &dev->dep[1].dep_cfg); + writel(tmp, &dev->dep[3].dep_cfg); + writel(tmp, &dev->dep[4].dep_cfg); + writel(tmp, &dev->dep[5].dep_cfg); + + /*Implemented for development and debug. + * Can be refined/tuned later.*/ + for (ep_sel = 0; ep_sel <= 21; ep_sel++) { + /* Select an endpoint for subsequent operations: */ + tmp_reg = readl(&dev->plregs->pl_ep_ctrl); + writel(((tmp_reg & ~0x1f) | ep_sel), + &dev->plregs->pl_ep_ctrl); + if (ep_sel == 1) { + tmp = + (readl(&dev->plregs->pl_ep_ctrl) | + BIT(CLEAR_ACK_ERROR_CODE) | 0); + writel(tmp, &dev->plregs->pl_ep_ctrl); + continue; } - /* Set FSM to focus on the first Control Read: - * - Tip: Connection speed is known upon the first - * setup request.*/ - scratch |= DEFECT7374_FSM_WAITING_FOR_CONTROL_READ; - set_idx_reg(dev->regs, SCRATCH, scratch); + if (ep_sel == 0 || (ep_sel > 9 && ep_sel < 14) || + ep_sel == 18 || ep_sel == 20) + continue; + + tmp = (readl(&dev->plregs->pl_ep_cfg_4) | + BIT(NON_CTRL_IN_TOLERATE_BAD_DIR) | 0); + writel(tmp, &dev->plregs->pl_ep_cfg_4); + + tmp = readl(&dev->plregs->pl_ep_ctrl) & + ~BIT(EP_INITIALIZED); + writel(tmp, &dev->plregs->pl_ep_ctrl); - } else{ - ep_warn(dev, "Defect 7374 workaround soft will NOT operate"); - ep_warn(dev, "It will operate on cold-reboot and SS connect"); } + + /* Set FSM to focus on the first Control Read: + * - Tip: Connection speed is known upon the first + * setup request.*/ + scratch |= DEFECT7374_FSM_WAITING_FOR_CONTROL_READ; + set_idx_reg(dev->regs, SCRATCH, scratch); + } /* keeping it simple: @@ -2033,21 +1880,13 @@ static void usb_reset_228x(struct net2280 *dev) static void usb_reset_338x(struct net2280 *dev) { u32 tmp; - u32 fsmvalue; dev->gadget.speed = USB_SPEED_UNKNOWN; (void)readl(&dev->usb->usbctl); net2280_led_init(dev); - fsmvalue = get_idx_reg(dev->regs, SCRATCH) & - (0xf << DEFECT7374_FSM_FIELD); - - /* See if firmware needs to set up for workaround: */ - if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ) { - ep_info(dev, "%s: Defect 7374 FsmValue 0x%08x\n", __func__, - fsmvalue); - } else { + if (dev->bug7734_patched) { /* disable automatic responses, and irqs */ writel(0, &dev->usb->stdrsp); writel(0, &dev->regs->pciirqenb0); @@ -2064,7 +1903,7 @@ static void usb_reset_338x(struct net2280 *dev) writel(~0, &dev->regs->irqstat0), writel(~0, &dev->regs->irqstat1); - if (fsmvalue == DEFECT7374_FSM_SS_CONTROL_READ) { + if (dev->bug7734_patched) { /* reset, and enable pci */ tmp = readl(&dev->regs->devinit) | BIT(PCI_ENABLE) | @@ -2093,10 +1932,6 @@ static void usb_reset(struct net2280 *dev) static void usb_reinit_228x(struct net2280 *dev) { u32 tmp; - int init_dma; - - /* use_dma changes are ignored till next device re-init */ - init_dma = use_dma; /* basic endpoint init */ for (tmp = 0; tmp < 7; tmp++) { @@ -2108,8 +1943,7 @@ static void usb_reinit_228x(struct net2280 *dev) if (tmp > 0 && tmp <= 4) { ep->fifo_size = 1024; - if (init_dma) - ep->dma = &dev->dma[tmp - 1]; + ep->dma = &dev->dma[tmp - 1]; } else ep->fifo_size = 64; ep->regs = &dev->epregs[tmp]; @@ -2133,17 +1967,12 @@ static void usb_reinit_228x(struct net2280 *dev) static void usb_reinit_338x(struct net2280 *dev) { - int init_dma; int i; u32 tmp, val; - u32 fsmvalue; static const u32 ne[9] = { 0, 1, 2, 3, 4, 1, 2, 3, 4 }; static const u32 ep_reg_addr[9] = { 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0xC0 }; - /* use_dma changes are ignored till next device re-init */ - init_dma = use_dma; - /* basic endpoint init */ for (i = 0; i < dev->n_ep; i++) { struct net2280_ep *ep = &dev->ep[i]; @@ -2152,7 +1981,7 @@ static void usb_reinit_338x(struct net2280 *dev) ep->dev = dev; ep->num = i; - if (i > 0 && i <= 4 && init_dma) + if (i > 0 && i <= 4) ep->dma = &dev->dma[i - 1]; if (dev->enhanced_mode) { @@ -2177,14 +2006,7 @@ static void usb_reinit_338x(struct net2280 *dev) dev->ep[0].stopped = 0; /* Link layer set up */ - fsmvalue = get_idx_reg(dev->regs, SCRATCH) & - (0xf << DEFECT7374_FSM_FIELD); - - /* See if driver needs to set up for workaround: */ - if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ) - ep_info(dev, "%s: Defect 7374 FsmValue %08x\n", - __func__, fsmvalue); - else { + if (dev->bug7734_patched) { tmp = readl(&dev->usb_ext->usbctl2) & ~(BIT(U1_ENABLE) | BIT(U2_ENABLE) | BIT(LTM_ENABLE)); writel(tmp, &dev->usb_ext->usbctl2); @@ -2291,15 +2113,8 @@ static void ep0_start_228x(struct net2280 *dev) static void ep0_start_338x(struct net2280 *dev) { - u32 fsmvalue; - - fsmvalue = get_idx_reg(dev->regs, SCRATCH) & - (0xf << DEFECT7374_FSM_FIELD); - if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ) - ep_info(dev, "%s: Defect 7374 FsmValue %08x\n", __func__, - fsmvalue); - else + if (dev->bug7734_patched) writel(BIT(CLEAR_NAK_OUT_PACKETS_MODE) | BIT(SET_EP_HIDE_STATUS_PHASE), &dev->epregs[0].ep_rsp); @@ -2382,16 +2197,12 @@ static int net2280_start(struct usb_gadget *_gadget, if (retval) goto err_func; - /* Enable force-full-speed testing mode, if desired */ - if (full_speed && (dev->quirks & PLX_LEGACY)) - writel(BIT(FORCE_FULL_SPEED_MODE), &dev->usb->xcvrdiag); - - /* ... then enable host detection and ep0; and we're ready + /* enable host detection and ep0; and we're ready * for set_configuration as well as eventual disconnect. */ net2280_led_active(dev, 1); - if (dev->quirks & PLX_SUPERSPEED) + if ((dev->quirks & PLX_SUPERSPEED) && !dev->bug7734_patched) defect7374_enable_data_eps_zero(dev); ep0_start(dev); @@ -2444,10 +2255,6 @@ static int net2280_stop(struct usb_gadget *_gadget) net2280_led_active(dev, 0); - /* Disable full-speed test mode */ - if (dev->quirks & PLX_LEGACY) - writel(0, &dev->usb->xcvrdiag); - device_remove_file(&dev->pdev->dev, &dev_attr_function); device_remove_file(&dev->pdev->dev, &dev_attr_queues); @@ -2478,10 +2285,10 @@ static void handle_ep_small(struct net2280_ep *ep) /* ack all, and handle what we care about */ t = readl(&ep->regs->ep_stat); ep->irqs++; -#if 0 + ep_vdbg(ep->dev, "%s ack ep_stat %08x, req %p\n", - ep->ep.name, t, req ? &req->req : 0); -#endif + ep->ep.name, t, req ? &req->req : NULL); + if (!ep->is_in || (ep->dev->quirks & PLX_2280)) writel(t & ~BIT(NAK_OUT_PACKETS), &ep->regs->ep_stat); else @@ -2717,6 +2524,7 @@ static void defect7374_workaround(struct net2280 *dev, struct usb_ctrlrequest r) * run after the next USB connection. */ scratch |= DEFECT7374_FSM_NON_SS_CONTROL_READ; + dev->bug7734_patched = 1; goto restore_data_eps; } @@ -2730,6 +2538,7 @@ static void defect7374_workaround(struct net2280 *dev, struct usb_ctrlrequest r) if ((state >= (ACK_GOOD_NORMAL << STATE)) && (state <= (ACK_GOOD_MORE_ACKS_TO_COME << STATE))) { scratch |= DEFECT7374_FSM_SS_CONTROL_READ; + dev->bug7734_patched = 1; break; } @@ -2766,80 +2575,19 @@ restore_data_eps: return; } -static void ep_stall(struct net2280_ep *ep, int stall) +static void ep_clear_seqnum(struct net2280_ep *ep) { struct net2280 *dev = ep->dev; u32 val; static const u32 ep_pl[9] = { 0, 3, 4, 7, 8, 2, 5, 6, 9 }; - if (stall) { - writel(BIT(SET_ENDPOINT_HALT) | - /* BIT(SET_NAK_PACKETS) | */ - BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE), - &ep->regs->ep_rsp); - ep->is_halt = 1; - } else { - if (dev->gadget.speed == USB_SPEED_SUPER) { - /* - * Workaround for SS SeqNum not cleared via - * Endpoint Halt (Clear) bit. select endpoint - */ - val = readl(&dev->plregs->pl_ep_ctrl); - val = (val & ~0x1f) | ep_pl[ep->num]; - writel(val, &dev->plregs->pl_ep_ctrl); - - val |= BIT(SEQUENCE_NUMBER_RESET); - writel(val, &dev->plregs->pl_ep_ctrl); - } - val = readl(&ep->regs->ep_rsp); - val |= BIT(CLEAR_ENDPOINT_HALT) | - BIT(CLEAR_ENDPOINT_TOGGLE); - writel(val, - /* | BIT(CLEAR_NAK_PACKETS),*/ - &ep->regs->ep_rsp); - ep->is_halt = 0; - val = readl(&ep->regs->ep_rsp); - } -} - -static void ep_stdrsp(struct net2280_ep *ep, int value, int wedged) -{ - /* set/clear, then synch memory views with the device */ - if (value) { - ep->stopped = 1; - if (ep->num == 0) - ep->dev->protocol_stall = 1; - else { - if (ep->dma) - ep_stop_dma(ep); - ep_stall(ep, true); - } - - if (wedged) - ep->wedged = 1; - } else { - ep->stopped = 0; - ep->wedged = 0; - - ep_stall(ep, false); + val = readl(&dev->plregs->pl_ep_ctrl) & ~0x1f; + val |= ep_pl[ep->num]; + writel(val, &dev->plregs->pl_ep_ctrl); + val |= BIT(SEQUENCE_NUMBER_RESET); + writel(val, &dev->plregs->pl_ep_ctrl); - /* Flush the queue */ - if (!list_empty(&ep->queue)) { - struct net2280_request *req = - list_entry(ep->queue.next, struct net2280_request, - queue); - if (ep->dma) - resume_dma(ep); - else { - if (ep->is_in) - write_fifo(ep, &req->req); - else { - if (read_fifo(ep, req)) - done(ep, req, 0); - } - } - } - } + return; } static void handle_stat0_irqs_superspeed(struct net2280 *dev, @@ -2863,7 +2611,7 @@ static void handle_stat0_irqs_superspeed(struct net2280 *dev, switch (r.bRequestType) { case (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE): status = dev->wakeup_enable ? 0x02 : 0x00; - if (dev->selfpowered) + if (dev->gadget.is_selfpowered) status |= BIT(0); status |= (dev->u1_enable << 2 | dev->u2_enable << 3 | dev->ltm_enable << 4); @@ -2940,7 +2688,12 @@ static void handle_stat0_irqs_superspeed(struct net2280 *dev, if (w_value != USB_ENDPOINT_HALT) goto do_stall3; ep_vdbg(dev, "%s clear halt\n", e->ep.name); - ep_stall(e, false); + /* + * Workaround for SS SeqNum not cleared via + * Endpoint Halt (Clear) bit. select endpoint + */ + ep_clear_seqnum(e); + clear_halt(e); if (!list_empty(&e->queue) && e->td_dma) restart_dma(e); allow_status(ep); @@ -2998,7 +2751,14 @@ static void handle_stat0_irqs_superspeed(struct net2280 *dev, e = get_ep_by_addr(dev, w_index); if (!e || (w_value != USB_ENDPOINT_HALT)) goto do_stall3; - ep_stdrsp(e, true, false); + ep->stopped = 1; + if (ep->num == 0) + ep->dev->protocol_stall = 1; + else { + if (ep->dma) + abort_dma(ep); + set_halt(ep); + } allow_status_338x(ep); break; @@ -3026,7 +2786,7 @@ do_stall3: r.bRequestType, r.bRequest, tmp); dev->protocol_stall = 1; /* TD 9.9 Halt Endpoint test. TD 9.22 Set feature test */ - ep_stall(ep, true); + set_halt(ep); } next_endpoints3: @@ -3091,9 +2851,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat) } ep->stopped = 0; dev->protocol_stall = 0; - if (dev->quirks & PLX_SUPERSPEED) - ep->is_halt = 0; - else{ + if (!(dev->quirks & PLX_SUPERSPEED)) { if (ep->dev->quirks & PLX_2280) tmp = BIT(FIFO_OVERFLOW) | BIT(FIFO_UNDERFLOW); @@ -3120,7 +2878,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat) cpu_to_le32s(&u.raw[0]); cpu_to_le32s(&u.raw[1]); - if (dev->quirks & PLX_SUPERSPEED) + if ((dev->quirks & PLX_SUPERSPEED) && !dev->bug7734_patched) defect7374_workaround(dev, u.r); tmp = 0; @@ -3423,17 +3181,12 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat) continue; } - /* chaining should stop on abort, short OUT from fifo, - * or (stat0 codepath) short OUT transfer. - */ - if (!use_dma_chaining) { - if (!(tmp & BIT(DMA_TRANSACTION_DONE_INTERRUPT))) { - ep_dbg(ep->dev, "%s no xact done? %08x\n", - ep->ep.name, tmp); - continue; - } - stop_dma(ep->dma); + if (!(tmp & BIT(DMA_TRANSACTION_DONE_INTERRUPT))) { + ep_dbg(ep->dev, "%s no xact done? %08x\n", + ep->ep.name, tmp); + continue; } + stop_dma(ep->dma); /* OUT transfers terminate when the data from the * host is in our memory. Process whatever's done. @@ -3448,30 +3201,9 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat) scan_dma_completions(ep); /* disable dma on inactive queues; else maybe restart */ - if (list_empty(&ep->queue)) { - if (use_dma_chaining) - stop_dma(ep->dma); - } else { + if (!list_empty(&ep->queue)) { tmp = readl(&dma->dmactl); - if (!use_dma_chaining || (tmp & BIT(DMA_ENABLE)) == 0) - restart_dma(ep); - else if (ep->is_in && use_dma_chaining) { - struct net2280_request *req; - __le32 dmacount; - - /* the descriptor at the head of the chain - * may still have VALID_BIT clear; that's - * used to trigger changing DMA_FIFO_VALIDATE - * (affects automagic zlp writes). - */ - req = list_entry(ep->queue.next, - struct net2280_request, queue); - dmacount = req->td->dmacount; - dmacount &= cpu_to_le32(BIT(VALID_BIT) | - DMA_BYTE_COUNT_MASK); - if (dmacount && (dmacount & valid_bit) == 0) - restart_dma(ep); - } + restart_dma(ep); } ep->irqs++; } @@ -3556,7 +3288,7 @@ static void net2280_remove(struct pci_dev *pdev) } if (dev->got_irq) free_irq(pdev->irq, dev); - if (use_msi && dev->quirks & PLX_SUPERSPEED) + if (dev->quirks & PLX_SUPERSPEED) pci_disable_msi(pdev); if (dev->regs) iounmap(dev->regs); @@ -3581,9 +3313,6 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id) void __iomem *base = NULL; int retval, i; - if (!use_dma) - use_dma_chaining = 0; - /* alloc, and start init */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { @@ -3663,9 +3392,12 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id) fsmvalue = get_idx_reg(dev->regs, SCRATCH) & (0xf << DEFECT7374_FSM_FIELD); /* See if firmware needs to set up for workaround: */ - if (fsmvalue == DEFECT7374_FSM_SS_CONTROL_READ) + if (fsmvalue == DEFECT7374_FSM_SS_CONTROL_READ) { + dev->bug7734_patched = 1; writel(0, &dev->usb->usbctl); - } else{ + } else + dev->bug7734_patched = 0; + } else { dev->enhanced_mode = 0; dev->n_ep = 7; /* put into initial config, link up all endpoints */ @@ -3682,7 +3414,7 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto done; } - if (use_msi && (dev->quirks & PLX_SUPERSPEED)) + if (dev->quirks & PLX_SUPERSPEED) if (pci_enable_msi(pdev)) ep_err(dev, "Failed to enable MSI mode\n"); @@ -3741,9 +3473,7 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id) ep_info(dev, "%s\n", driver_desc); ep_info(dev, "irq %d, pci mem %p, chip rev %04x\n", pdev->irq, base, dev->chiprev); - ep_info(dev, "version: " DRIVER_VERSION "; dma %s %s\n", - use_dma ? (use_dma_chaining ? "chaining" : "enabled") - : "disabled", + ep_info(dev, "version: " DRIVER_VERSION "; %s\n", dev->enhanced_mode ? "enhanced mode" : "legacy mode"); retval = device_create_file(&pdev->dev, &dev_attr_registers); if (retval) @@ -3776,9 +3506,6 @@ static void net2280_shutdown(struct pci_dev *pdev) /* disable the pullup so the host will think we're gone */ writel(0, &dev->usb->usbctl); - /* Disable full-speed test mode */ - if (dev->quirks & PLX_LEGACY) - writel(0, &dev->usb->xcvrdiag); } diff --git a/drivers/usb/gadget/udc/net2280.h b/drivers/usb/gadget/udc/net2280.h index 03f15242d794..ac8d5a20a378 100644 --- a/drivers/usb/gadget/udc/net2280.h +++ b/drivers/usb/gadget/udc/net2280.h @@ -100,7 +100,6 @@ struct net2280_ep { dma_addr_t td_dma; /* of dummy */ struct net2280 *dev; unsigned long irqs; - unsigned is_halt:1, dma_started:1; /* analogous to a host-side qh */ struct list_head queue; @@ -126,7 +125,7 @@ static inline void allow_status(struct net2280_ep *ep) ep->stopped = 1; } -static void allow_status_338x(struct net2280_ep *ep) +static inline void allow_status_338x(struct net2280_ep *ep) { /* * Control Status Phase Handshake was set by the chip when the setup @@ -165,8 +164,8 @@ struct net2280 { u2_enable:1, ltm_enable:1, wakeup_enable:1, - selfpowered:1, - addressed_state:1; + addressed_state:1, + bug7734_patched:1; u16 chiprev; int enhanced_mode; int n_ep; @@ -356,23 +355,6 @@ static inline void start_out_naking(struct net2280_ep *ep) readl(&ep->regs->ep_rsp); } -#ifdef DEBUG -static inline void assert_out_naking(struct net2280_ep *ep, const char *where) -{ - u32 tmp = readl(&ep->regs->ep_stat); - - if ((tmp & BIT(NAK_OUT_PACKETS)) == 0) { - ep_dbg(ep->dev, "%s %s %08x !NAK\n", - ep->ep.name, where, tmp); - writel(BIT(SET_NAK_OUT_PACKETS), - &ep->regs->ep_rsp); - } -} -#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep, __func__) -#else -#define ASSERT_OUT_NAKING(ep) do {} while (0) -#endif - static inline void stop_out_naking(struct net2280_ep *ep) { u32 tmp; diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index 288c087220a8..e2fcdb8e5596 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c @@ -1171,6 +1171,7 @@ omap_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered) unsigned long flags; u16 syscon1; + gadget->is_selfpowered = (is_selfpowered != 0); udc = container_of(gadget, struct omap_udc, gadget); spin_lock_irqsave(&udc->lock, flags); syscon1 = omap_readw(UDC_SYSCON1); diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index 1c7379ac2379..613547f07828 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -1161,6 +1161,7 @@ static int pch_udc_pcd_selfpowered(struct usb_gadget *gadget, int value) if (!gadget) return -EINVAL; + gadget->is_selfpowered = (value != 0); dev = container_of(gadget, struct pch_udc_dev, gadget); if (value) pch_udc_set_selfpowered(dev); diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c index 8550b2d5db32..f6cbe667ce39 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.c +++ b/drivers/usb/gadget/udc/pxa25x_udc.c @@ -1272,7 +1272,6 @@ static int pxa25x_udc_start(struct usb_gadget *g, goto bind_fail; } - pullup(dev); dump_state(dev); return 0; bind_fail: @@ -1339,7 +1338,6 @@ static int pxa25x_udc_stop(struct usb_gadget*g) local_irq_disable(); dev->pullup = 0; - pullup(dev); stop_activity(dev, NULL); local_irq_enable(); diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c index c61a896061fa..6a855fc9bd84 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.c +++ b/drivers/usb/gadget/udc/pxa27x_udc.c @@ -1809,7 +1809,6 @@ static int pxa27x_udc_start(struct usb_gadget *g, /* first hook up the driver ... */ udc->driver = driver; - dplus_pullup(udc, 1); if (!IS_ERR_OR_NULL(udc->transceiver)) { retval = otg_set_peripheral(udc->transceiver->otg, @@ -1862,7 +1861,6 @@ static int pxa27x_udc_stop(struct usb_gadget *g) stop_activity(udc, NULL); udc_disable(udc); - dplus_pullup(udc, 0); udc->driver = NULL; diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c index 06870da0b988..2495fe9c95c5 100644 --- a/drivers/usb/gadget/udc/r8a66597-udc.c +++ b/drivers/usb/gadget/udc/r8a66597-udc.c @@ -1803,6 +1803,7 @@ static int r8a66597_set_selfpowered(struct usb_gadget *gadget, int is_self) { struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget); + gadget->is_selfpowered = (is_self != 0); if (is_self) r8a66597->device_status |= 1 << USB_DEVICE_SELF_POWERED; else diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c index 824cf12e9add..b808951491cc 100644 --- a/drivers/usb/gadget/udc/s3c2410_udc.c +++ b/drivers/usb/gadget/udc/s3c2410_udc.c @@ -238,14 +238,6 @@ static inline void s3c2410_udc_set_ep0_de_out(void __iomem *base) S3C2410_UDC_EP0_CSR_REG); } -static inline void s3c2410_udc_set_ep0_sse_out(void __iomem *base) -{ - udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); - udc_writeb(base, (S3C2410_UDC_EP0_CSR_SOPKTRDY - | S3C2410_UDC_EP0_CSR_SSE), - S3C2410_UDC_EP0_CSR_REG); -} - static inline void s3c2410_udc_set_ep0_de_in(void __iomem *base) { udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); @@ -291,18 +283,6 @@ static void s3c2410_udc_nuke(struct s3c2410_udc *udc, } } -static inline void s3c2410_udc_clear_ep_state(struct s3c2410_udc *dev) -{ - unsigned i; - - /* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint - * fifos, and pending transactions mustn't be continued in any case. - */ - - for (i = 1; i < S3C2410_ENDPOINTS; i++) - s3c2410_udc_nuke(dev, &dev->ep[i], -ECONNABORTED); -} - static inline int s3c2410_udc_fifo_count_out(void) { int tmp; @@ -1454,6 +1434,7 @@ static int s3c2410_udc_set_selfpowered(struct usb_gadget *gadget, int value) dprintk(DEBUG_NORMAL, "%s()\n", __func__); + gadget->is_selfpowered = (value != 0); if (value) udc->devstatus |= (1 << USB_DEVICE_SELF_POWERED); else diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index e31d574d8860..5a81cb086b99 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -564,6 +564,7 @@ static USB_UDC_ATTR(is_a_peripheral); static USB_UDC_ATTR(b_hnp_enable); static USB_UDC_ATTR(a_hnp_support); static USB_UDC_ATTR(a_alt_hnp_support); +static USB_UDC_ATTR(is_selfpowered); static struct attribute *usb_udc_attrs[] = { &dev_attr_srp.attr, @@ -577,6 +578,7 @@ static struct attribute *usb_udc_attrs[] = { &dev_attr_b_hnp_enable.attr, &dev_attr_a_hnp_support.attr, &dev_attr_a_alt_hnp_support.attr, + &dev_attr_is_selfpowered.attr, NULL, }; |