[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 = &params_bcm2835 },
>  	{ .compatible = "rockchip,rk3066-usb", .data = &params_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