From: Maxime Ripard Date: Tue, 13 May 2014 15:44:20 +0000 (+0200) Subject: usb: ohci-platform: Enable optional use of reset controller X-Git-Tag: v3.16-rc1~30^2~34^2~54 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4615f3bd089fc4c549ed90e14982b360779feb50;p=platform%2Fkernel%2Flinux-stable.git usb: ohci-platform: Enable optional use of reset controller The OHCI controllers used in the Allwinner A31 are asserted in reset using a global reset controller. Add optional support for such a controller in the OHCI platform driver. Signed-off-by: Maxime Ripard Reviewed-by: Hans de Goede Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt index 45f67d91e888..b968a1aea995 100644 --- a/Documentation/devicetree/bindings/usb/usb-ohci.txt +++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt @@ -12,6 +12,7 @@ Optional properties: - clocks : a list of phandle + clock specifier pairs - phys : phandle + phy specifier pair - phy-names : "usb" +- resets : phandle + reset specifier pair Example: diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index b6002c951c5c..4369299064c7 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,7 @@ struct ohci_platform_priv { struct clk *clks[OHCI_MAX_CLKS]; + struct reset_control *rst; struct phy *phy; }; @@ -191,6 +193,19 @@ static int ohci_platform_probe(struct platform_device *dev) break; } } + + } + + priv->rst = devm_reset_control_get_optional(&dev->dev, NULL); + if (IS_ERR(priv->rst)) { + err = PTR_ERR(priv->rst); + if (err == -EPROBE_DEFER) + goto err_put_clks; + priv->rst = NULL; + } else { + err = reset_control_deassert(priv->rst); + if (err) + goto err_put_clks; } if (pdata->big_endian_desc) @@ -203,7 +218,7 @@ static int ohci_platform_probe(struct platform_device *dev) dev_err(&dev->dev, "Error: CONFIG_USB_OHCI_BIG_ENDIAN_MMIO not set\n"); err = -EINVAL; - goto err_put_clks; + goto err_reset; } #endif #ifndef CONFIG_USB_OHCI_BIG_ENDIAN_DESC @@ -211,14 +226,14 @@ static int ohci_platform_probe(struct platform_device *dev) dev_err(&dev->dev, "Error: CONFIG_USB_OHCI_BIG_ENDIAN_DESC not set\n"); err = -EINVAL; - goto err_put_clks; + goto err_reset; } #endif if (pdata->power_on) { err = pdata->power_on(dev); if (err < 0) - goto err_put_clks; + goto err_reset; } hcd->rsrc_start = res_mem->start; @@ -242,6 +257,9 @@ static int ohci_platform_probe(struct platform_device *dev) err_power: if (pdata->power_off) pdata->power_off(dev); +err_reset: + if (priv->rst) + reset_control_assert(priv->rst); err_put_clks: while (--clk >= 0) clk_put(priv->clks[clk]); @@ -266,6 +284,9 @@ static int ohci_platform_remove(struct platform_device *dev) if (pdata->power_off) pdata->power_off(dev); + if (priv->rst) + reset_control_assert(priv->rst); + for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) clk_put(priv->clks[clk]);