[PATCH] usb: dwc2: add shutdown callback to platform variant
John Youn
John.Youn at synopsys.com
Fri Dec 18 17:00:51 PST 2015
On 12/18/2015 10:31 AM, Heiko Stübner wrote:
> In specific conditions (involving usb hubs) dwc2 devices can create a
> lot of interrupts, even to the point of overwhelming devices running
> at low frequencies. Some devices need to do special clock handling
> at shutdown-time which may bring the system clock below the threshold
> of being able to handle the dwc2 interrupts. Disabling dwc2-irqs
> in a shutdown callbacks prevents reboots/poweroffs from getting stuck
> in such cases.
>
> The hsotg struct already contains an unused irq element, so we can
> just use it to store the irq number for the shutdown callback.
>
> Signed-off-by: Heiko Stuebner <heiko.stuebner at collabora.com>
> ---
> I'm also adapting the code on the clock-side to lessen the effects of
> the slow clock (see clk: rockchip: only enter pll slow-mode directly
> before reboots on rk3288), but this patch also fixes the issue of the
> overwhelming irq-number in itself and may be interesting for other/future
> platforms using the dwc2.
>
>
> drivers/usb/dwc2/platform.c | 35 +++++++++++++++++++++++++++--------
> 1 file changed, 27 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
> index 39c1cbf..5510d07 100644
> --- a/drivers/usb/dwc2/platform.c
> +++ b/drivers/usb/dwc2/platform.c
> @@ -306,6 +306,25 @@ static int dwc2_driver_remove(struct platform_device *dev)
> return 0;
> }
>
> +/**
> + * dwc2_driver_shutdown() - Called on device shutdown
> + *
> + * @dev: Platform device
> + *
> + * In specific conditions (involving usb hubs) dwc2 devices can create a
> + * lot of interrupts, even to the point of overwhelming devices running
> + * at low frequencies. Some devices need to do special clock handling
> + * at shutdown-time which may bring the system clock below the threshold
> + * of being able to handle the dwc2 interrupts. Disabling dwc2-irqs
> + * prevents reboots/poweroffs from getting stuck in such cases.
> + */
> +static void dwc2_driver_shutdown(struct platform_device *dev)
> +{
> + struct dwc2_hsotg *hsotg = platform_get_drvdata(dev);
> +
> + disable_irq(hsotg->irq);
> +}
> +
> static const struct of_device_id dwc2_of_match_table[] = {
> { .compatible = "brcm,bcm2835-usb", .data = ¶ms_bcm2835 },
> { .compatible = "rockchip,rk3066-usb", .data = ¶ms_rk3066 },
> @@ -335,7 +354,6 @@ static int dwc2_driver_probe(struct platform_device *dev)
> struct dwc2_hsotg *hsotg;
> struct resource *res;
> int retval;
> - int irq;
>
> match = of_match_device(dwc2_of_match_table, &dev->dev);
> if (match && match->data) {
> @@ -401,15 +419,15 @@ static int dwc2_driver_probe(struct platform_device *dev)
>
> dwc2_set_all_params(hsotg->core_params, -1);
>
> - irq = platform_get_irq(dev, 0);
> - if (irq < 0) {
> + hsotg->irq = platform_get_irq(dev, 0);
> + if (hsotg->irq < 0) {
> dev_err(&dev->dev, "missing IRQ resource\n");
> - return irq;
> + return hsotg->irq;
> }
>
> dev_dbg(hsotg->dev, "registering common handler for irq%d\n",
> - irq);
> - retval = devm_request_irq(hsotg->dev, irq,
> + hsotg->irq);
> + retval = devm_request_irq(hsotg->dev, hsotg->irq,
> dwc2_handle_common_intr, IRQF_SHARED,
> dev_name(hsotg->dev), hsotg);
> if (retval)
> @@ -428,14 +446,14 @@ static int dwc2_driver_probe(struct platform_device *dev)
> dwc2_set_parameters(hsotg, params);
>
> if (hsotg->dr_mode != USB_DR_MODE_HOST) {
> - retval = dwc2_gadget_init(hsotg, irq);
> + retval = dwc2_gadget_init(hsotg, hsotg->irq);
> if (retval)
> goto error;
> hsotg->gadget_enabled = 1;
> }
>
> if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) {
> - retval = dwc2_hcd_init(hsotg, irq);
> + retval = dwc2_hcd_init(hsotg, hsotg->irq);
> if (retval) {
> if (hsotg->gadget_enabled)
> dwc2_hsotg_remove(hsotg);
> @@ -502,6 +520,7 @@ static struct platform_driver dwc2_platform_driver = {
> },
> .probe = dwc2_driver_probe,
> .remove = dwc2_driver_remove,
> + .shutdown = dwc2_driver_shutdown,
> };
>
> module_platform_driver(dwc2_platform_driver);
>
Acked-by: John Youn <johnyoun at synopsys.com>
John
More information about the Linux-rockchip
mailing list