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 <ba...@ti.com> 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.saj...@linaro.org>
> Signed-off-by: Felipe Balbi <ba...@ti.com>
> ---
>  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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to