Signed-off-by: Dmitry Baryshkov [EMAIL PROTECTED] --- drivers/usb/gadget/pxa2xx_udc.c | 72 ++++++++++++++++++++++----------------- drivers/usb/gadget/pxa2xx_udc.h | 6 +++- 2 files changed, 46 insertions(+), 32 deletions(-)
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 2900556..f4484e4 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -934,20 +934,36 @@ static void udc_disable(struct pxa2xx_udc *); /* We disable the UDC -- and its 48 MHz clock -- whenever it's not * in active use. */ -static int pullup(struct pxa2xx_udc *udc, int is_active) +static int pullup(struct pxa2xx_udc *udc) { - is_active = is_active && udc->vbus && udc->pullup; + int is_active = udc->vbus && udc->pullup && + ! udc->suspended; DMSG("%s\n", is_active ? "active" : "inactive"); - if (is_active) - udc_enable(udc); - else { - if (udc->gadget.speed != USB_SPEED_UNKNOWN) { - DMSG("disconnect %s\n", udc->driver - ? udc->driver->driver.name - : "(no driver)"); - stop_activity(udc, udc->driver); + if (is_active) { + if (!udc->active) { + udc->active = 1; +#ifdef CONFIG_ARCH_PXA + /* Enable clock for USB device */ + clk_enable(udc->clk); +#endif + udc_enable(udc); + } + } else { + if (udc->active) { + if (udc->gadget.speed != USB_SPEED_UNKNOWN) { + DMSG("disconnect %s\n", udc->driver + ? udc->driver->driver.name + : "(no driver)"); + stop_activity(udc, udc->driver); + } + udc_disable(udc); +#ifdef CONFIG_ARCH_PXA + /* Disable clock for USB device */ + clk_disable(udc->clk); +#endif + udc->active = 0; } - udc_disable(udc); + } return 0; } @@ -958,9 +974,9 @@ static int pxa2xx_udc_vbus_session(struct usb_gadget *_gadget, int is_active) struct pxa2xx_udc *udc; udc = container_of(_gadget, struct pxa2xx_udc, gadget); - udc->vbus = is_active = (is_active != 0); + udc->vbus = (is_active != 0); DMSG("vbus %s\n", is_active ? "supplied" : "inactive"); - pullup(udc, is_active); + pullup(udc); return 0; } @@ -975,9 +991,8 @@ static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active) if (!udc->mach->gpio_pullup && !udc->mach->udc_command) return -EOPNOTSUPP; - is_active = (is_active != 0); - udc->pullup = is_active; - pullup(udc, is_active); + udc->pullup = (is_active != 0); + pullup(udc); return 0; } @@ -1145,11 +1160,6 @@ static void udc_disable(struct pxa2xx_udc *dev) udc_clear_mask_UDCCR(UDCCR_UDE); -#ifdef CONFIG_ARCH_PXA - /* Disable clock for USB device */ - clk_disable(dev->clk); -#endif - ep0_idle (dev); dev->gadget.speed = USB_SPEED_UNKNOWN; } @@ -1190,11 +1200,6 @@ static void udc_enable (struct pxa2xx_udc *dev) { udc_clear_mask_UDCCR(UDCCR_UDE); -#ifdef CONFIG_ARCH_PXA - /* Enable clock for USB device */ - clk_enable(dev->clk); -#endif - /* try to clear these bits before we enable the udc */ udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR); @@ -1285,7 +1290,7 @@ fail: * for set_configuration as well as eventual disconnect. */ DMSG("registered gadget driver '%s'\n", driver->driver.name); - pullup(dev, 1); + pullup(dev); dump_state(dev); return 0; } @@ -1328,7 +1333,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) return -EINVAL; local_irq_disable(); - pullup(dev, 0); + dev->pullup = 0; + pullup(dev); stop_activity(dev, driver); local_irq_enable(); @@ -2267,7 +2273,9 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev) if (dev->driver) return -EBUSY; - udc_disable(dev); + dev->pullup = 0; + pullup(dev); + remove_debug_files(dev); if (dev->got_irq) { @@ -2318,7 +2326,8 @@ static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state) if (!udc->mach->gpio_pullup && !udc->mach->udc_command) WARN("USB host won't detect disconnect!\n"); - pullup(udc, 0); + udc->suspended = 1; + pullup(udc); return 0; } @@ -2327,7 +2336,8 @@ static int pxa2xx_udc_resume(struct platform_device *dev) { struct pxa2xx_udc *udc = platform_get_drvdata(dev); - pullup(udc, 1); + udc->suspended = 0; + pullup(udc); return 0; } diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h index c08b1a2..26c0347 100644 --- a/drivers/usb/gadget/pxa2xx_udc.h +++ b/drivers/usb/gadget/pxa2xx_udc.h @@ -119,13 +119,17 @@ struct pxa2xx_udc { has_cfr : 1, req_pending : 1, req_std : 1, - req_config : 1; + req_config : 1, + suspended : 1, + active : 1; #define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200)) struct timer_list timer; struct device *dev; +#ifdef CONFIG_ARCH_PXA struct clk *clk; +#endif struct pxa2xx_udc_mach_info *mach; u64 dma_mask; struct pxa2xx_ep ep [PXA_UDC_NUM_ENDPOINTS]; -- 1.5.3.8 -- With best wishes Dmitry - To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html