Hi Felipe, Sorry for coming so late on this series :-(, was away actually. Just trying with patches in 'dwc3-dev-pm-ops' branch of your tree. On Mon, Feb 11, 2013 at 3:22 PM, Felipe Balbi <balbi@xxxxxx> wrote: > Add support for basic power management on > the dwc3 driver. While there is still lots > to improve for full PM support, this minimal > patch will already make sure that we survive > suspend-to-ram and suspend-to-disk without > major issues. > > Cc: Vikas C Sajjan <vikas.sajjan@xxxxxxxxxx> > Signed-off-by: Felipe Balbi <balbi@xxxxxx> > --- > drivers/usb/dwc3/core.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++ > drivers/usb/dwc3/core.h | 6 +++ > drivers/usb/dwc3/gadget.c | 57 ++++++++++++++++++++++++ > 3 files changed, 171 insertions(+) > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > index fb93918..466b894 100644 > --- a/drivers/usb/dwc3/core.c > +++ b/drivers/usb/dwc3/core.c > @@ -583,11 +583,119 @@ static int dwc3_remove(struct platform_device *pdev) > return 0; > } > > +#ifdef CONFIG_PM > +static int dwc3_prepare(struct device *dev) > +{ > + struct dwc3 *dwc = dev_get_drvdata(dev); > + unsigned long flags; > + > + spin_lock_irqsave(&dwc->lock, flags); > + > + switch (dwc->mode) { > + case DWC3_MODE_DEVICE: > + case DWC3_MODE_DRD: > + dwc3_gadget_prepare(dwc); Compiling Host only mode of DWC3 will give linker error :-( drivers/built-in.o: In function `dwc3_resume': drivers/usb/dwc3/core.c:675: undefined reference to `dwc3_gadget_resume' drivers/built-in.o: In function `dwc3_suspend': drivers/usb/dwc3/core.c:649: undefined reference to `dwc3_gadget_suspend' drivers/built-in.o: In function `dwc3_complete': drivers/usb/dwc3/core.c:628: undefined reference to `dwc3_gadget_complete' drivers/built-in.o: In function `dwc3_prepare': drivers/usb/dwc3/core.c:605: undefined reference to `dwc3_gadget_prepare' we will need to check the "mode" here, since dwc3/gadget.c won't be compiling for Host only mode. > + /* FALLTHROUGH */ > + case DWC3_MODE_HOST: > + default: > + dwc3_event_buffers_cleanup(dwc); > + break; > + } > + > + spin_unlock_irqrestore(&dwc->lock, flags); > + > + return 0; > +} > + > +static void dwc3_complete(struct device *dev) > +{ > + struct dwc3 *dwc = dev_get_drvdata(dev); > + unsigned long flags; > + > + spin_lock_irqsave(&dwc->lock, flags); > + > + switch (dwc->mode) { > + case DWC3_MODE_DEVICE: > + case DWC3_MODE_DRD: > + dwc3_gadget_complete(dwc); ditto > + /* FALLTHROUGH */ > + case DWC3_MODE_HOST: > + default: > + dwc3_event_buffers_setup(dwc); > + break; > + } > + > + spin_unlock_irqrestore(&dwc->lock, flags); > +} > + > +static int dwc3_suspend(struct device *dev) > +{ > + struct dwc3 *dwc = dev_get_drvdata(dev); > + unsigned long flags; > + > + spin_lock_irqsave(&dwc->lock, flags); > + > + switch (dwc->mode) { > + case DWC3_MODE_DEVICE: > + case DWC3_MODE_DRD: > + dwc3_gadget_suspend(dwc); ditto > + /* FALLTHROUGH */ > + case DWC3_MODE_HOST: > + default: > + /* do nothing */ > + break; > + } > + > + spin_unlock_irqrestore(&dwc->lock, flags); > + > + return 0; > +} > + > +static int dwc3_resume(struct device *dev) > +{ > + struct dwc3 *dwc = dev_get_drvdata(dev); > + unsigned long flags; > + > + spin_lock_irqsave(&dwc->lock, flags); > + > + switch (dwc->mode) { > + case DWC3_MODE_DEVICE: > + case DWC3_MODE_DRD: > + dwc3_gadget_resume(dwc); ditto > + /* FALLTHROUGH */ > + case DWC3_MODE_HOST: > + default: > + /* do nothing */ > + break; > + } > + > + spin_unlock_irqrestore(&dwc->lock, flags); > + > + pm_runtime_disable(dev); > + pm_runtime_set_active(dev); > + pm_runtime_enable(dev); > + > + return 0; > +} > + > +static const struct dev_pm_ops dwc3_dev_pm_ops = { > + .prepare = dwc3_prepare, > + .complete = dwc3_complete, > + > + SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) > +}; > + > +#define DWC3_PM_OPS &(dwc3_dev_pm_ops) > +#else > +#define DWC3_PM_OPS NULL > +#endif > + > static struct platform_driver dwc3_driver = { > .probe = dwc3_probe, > .remove = dwc3_remove, > .driver = { > .name = "dwc3", > + .pm = DWC3_PM_OPS, > }, > }; > > diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h > index e8d74a7..6f4e8ba 100644 > --- a/drivers/usb/dwc3/core.h > +++ b/drivers/usb/dwc3/core.h > @@ -862,4 +862,10 @@ void dwc3_host_exit(struct dwc3 *dwc); > int dwc3_gadget_init(struct dwc3 *dwc); > void dwc3_gadget_exit(struct dwc3 *dwc); > > +/* power management interface */ > +int dwc3_gadget_prepare(struct dwc3 *dwc); > +void dwc3_gadget_complete(struct dwc3 *dwc); > +int dwc3_gadget_suspend(struct dwc3 *dwc); > +int dwc3_gadget_resume(struct dwc3 *dwc); > + > #endif /* __DRIVERS_USB_DWC3_CORE_H */ > diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c > index 2656cca..b225723 100644 > --- a/drivers/usb/dwc3/gadget.c > +++ b/drivers/usb/dwc3/gadget.c > @@ -2530,6 +2530,8 @@ err0: > return ret; > } > > +/* -------------------------------------------------------------------------- */ > + > void dwc3_gadget_exit(struct dwc3 *dwc) > { > usb_del_gadget_udc(&dwc->gadget); > @@ -2547,3 +2549,58 @@ void dwc3_gadget_exit(struct dwc3 *dwc) > dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req), > dwc->ctrl_req, dwc->ctrl_req_addr); > } > + > +int dwc3_gadget_prepare(struct dwc3 *dwc) > +{ > + if (dwc->pullups_connected) > + dwc3_gadget_disable_irq(dwc); > + > + return 0; > +} > + > +void dwc3_gadget_complete(struct dwc3 *dwc) > +{ > + if (dwc->pullups_connected) { > + dwc3_gadget_enable_irq(dwc); > + dwc3_gadget_run_stop(dwc, true); > + } > +} > + > +int dwc3_gadget_suspend(struct dwc3 *dwc) > +{ > + __dwc3_gadget_ep_disable(dwc->eps[0]); > + __dwc3_gadget_ep_disable(dwc->eps[1]); > + > + return 0; > +} > + > +int dwc3_gadget_resume(struct dwc3 *dwc) > +{ > + struct dwc3_ep *dep; > + int ret; > + > + /* Start with SuperSpeed Default */ > + dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); > + > + dep = dwc->eps[0]; > + ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false); > + if (ret) > + goto err0; > + > + dep = dwc->eps[1]; > + ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false); > + if (ret) > + goto err1; > + > + /* begin to receive SETUP packets */ > + dwc->ep0state = EP0_SETUP_PHASE; > + dwc3_ep0_out_start(dwc); > + > + return 0; > + > +err1: > + __dwc3_gadget_ep_disable(dwc->eps[0]); > + > +err0: > + return ret; > +} > -- > 1.8.1.rc1.5.g7e0651a > -- Thanks & Regards Vivek -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html